@@ -1758,6 +1758,108 @@ void DomainParameters::set_values(tinyxml2::XMLElement* domain_elem, bool from_e
17581758*/
17591759}
17601760
1761+ // ////////////////////////////////////////////////////////
1762+ // DirectionalDistributionParameters //
1763+ // ////////////////////////////////////////////////////////
1764+
1765+ // / @brief Define the XML element name for directional distribution parameters.
1766+ const std::string DirectionalDistributionParameters::xml_element_name_ = " Directional_distribution" ;
1767+
1768+ DirectionalDistributionParameters::DirectionalDistributionParameters ()
1769+ {
1770+ bool required = false ;
1771+
1772+ // Default: all stress in fiber direction
1773+ set_parameter (" Fiber_direction" , 1.0 , required, fiber_direction);
1774+ set_parameter (" Sheet_direction" , 0.0 , required, sheet_direction);
1775+ set_parameter (" Sheet_normal_direction" , 0.0 , required, sheet_normal_direction);
1776+ }
1777+
1778+ void DirectionalDistributionParameters::set_values (tinyxml2::XMLElement* xml_elem)
1779+ {
1780+ using namespace tinyxml2 ;
1781+ std::string error_msg = " Unknown " + xml_element_name_ + " XML element '" ;
1782+
1783+ using std::placeholders::_1;
1784+ using std::placeholders::_2;
1785+
1786+ std::function<void (const std::string&, const std::string&)> ftpr =
1787+ std::bind (&DirectionalDistributionParameters::set_parameter_value, *this , _1, _2);
1788+
1789+ xml_util_set_parameters (ftpr, xml_elem, error_msg);
1790+
1791+ value_set = true ;
1792+ }
1793+
1794+ void DirectionalDistributionParameters::validate () const
1795+ {
1796+ if (!value_set) {
1797+ return ; // No validation needed if not set (will use defaults)
1798+ }
1799+
1800+ // Check how many parameters are defined
1801+ bool fiber_defined = fiber_direction.defined ();
1802+ bool sheet_defined = sheet_direction.defined ();
1803+ bool normal_defined = sheet_normal_direction.defined ();
1804+
1805+ int num_defined = fiber_defined + sheet_defined + normal_defined;
1806+
1807+ // Empty block is invalid - if block exists, must specify all three
1808+ if (num_defined == 0 ) {
1809+ throw std::runtime_error (" Directional_distribution block is empty. "
1810+ " Either remove the block entirely (to use defaults: fiber=1.0, sheet=0.0, normal=0.0) "
1811+ " or specify all three directions: Fiber_direction, Sheet_direction, Sheet_normal_direction." );
1812+ }
1813+
1814+ // Partial specification is invalid
1815+ if (num_defined < 3 ) {
1816+ std::string msg = " Directional_distribution requires all three directions to be specified. Found: " ;
1817+ if (fiber_defined) msg += " Fiber_direction " ;
1818+ if (sheet_defined) msg += " Sheet_direction " ;
1819+ if (normal_defined) msg += " Sheet_normal_direction " ;
1820+ msg += " \n Missing: " ;
1821+ if (!fiber_defined) msg += " Fiber_direction " ;
1822+ if (!sheet_defined) msg += " Sheet_direction " ;
1823+ if (!normal_defined) msg += " Sheet_normal_direction " ;
1824+ throw std::runtime_error (msg);
1825+ }
1826+
1827+ // All three are specified, validate their values
1828+ double eta_f = fiber_direction.value ();
1829+ double eta_s = sheet_direction.value ();
1830+ double eta_n = sheet_normal_direction.value ();
1831+
1832+ // Validate that eta_f + eta_s + eta_n = 1.0
1833+ double eta_sum = eta_f + eta_s + eta_n;
1834+ const double tol = 1.0e-10 ;
1835+ if (std::abs (eta_sum - 1.0 ) > tol) {
1836+ throw std::runtime_error (" Directional distribution fractions must sum to 1.0. "
1837+ " Got: Fiber_direction=" + std::to_string (eta_f) +
1838+ " , Sheet_direction=" + std::to_string (eta_s) +
1839+ " , Sheet_normal_direction=" + std::to_string (eta_n) +
1840+ " , sum=" + std::to_string (eta_sum));
1841+ }
1842+
1843+ // Validate that each eta is non-negative
1844+ if (eta_f < 0.0 || eta_s < 0.0 || eta_n < 0.0 ) {
1845+ throw std::runtime_error (" Directional distribution fractions must be non-negative. "
1846+ " Got: Fiber_direction=" + std::to_string (eta_f) +
1847+ " , Sheet_direction=" + std::to_string (eta_s) +
1848+ " , Sheet_normal_direction=" + std::to_string (eta_n));
1849+ }
1850+ }
1851+
1852+ void DirectionalDistributionParameters::print_parameters ()
1853+ {
1854+ if (!value_set) {
1855+ return ;
1856+ }
1857+ std::cout << " Directional Distribution:" << std::endl;
1858+ std::cout << " Fiber_direction: " << fiber_direction.value () << std::endl;
1859+ std::cout << " Sheet_direction: " << sheet_direction.value () << std::endl;
1860+ std::cout << " Sheet_normal_direction: " << sheet_normal_direction.value () << std::endl;
1861+ }
1862+
17611863// ////////////////////////////////////////////////////////
17621864// FiberReinforcementStressParameters //
17631865// ////////////////////////////////////////////////////////
@@ -1786,22 +1888,34 @@ void FiberReinforcementStressParameters::set_values(tinyxml2::XMLElement* xml_el
17861888 using namespace tinyxml2 ;
17871889 std::string error_msg = " Unknown " + xml_element_name_ + " XML element '" ;
17881890
1789- // Get the 'type' from the <LS type=TYPE> element.
1891+ // Get the 'type' from the element attribute .
17901892 const char * stype;
17911893 auto result = xml_elem->QueryStringAttribute (" type" , &stype);
17921894 if (stype == nullptr ) {
1793- throw std::runtime_error (" No TYPE given in the XML <Stimulus =TYPE> element." );
1895+ throw std::runtime_error (" No TYPE given in the XML <Fiber_reinforcement_stress type =TYPE> element." );
17941896 }
17951897 type.set (std::string (stype));
17961898 auto item = xml_elem->FirstChildElement ();
1797-
1798- using std::placeholders::_1;
1799- using std::placeholders::_2;
1800-
1801- std::function<void (const std::string&, const std::string&)> ftpr =
1802- std::bind ( &FiberReinforcementStressParameters::set_parameter_value, *this , _1, _2);
1803-
1804- xml_util_set_parameters (ftpr, xml_elem, error_msg);
1899+
1900+ while (item != nullptr ) {
1901+ std::string name = item->Value ();
1902+
1903+ if (name == DirectionalDistributionParameters::xml_element_name_) {
1904+ directional_distribution.set_values (item);
1905+
1906+ } else if (item->GetText () != nullptr ) {
1907+ auto value = item->GetText ();
1908+ try {
1909+ set_parameter_value (name, value);
1910+ } catch (const std::bad_function_call& exception) {
1911+ throw std::runtime_error (error_msg + name + " '." );
1912+ }
1913+ } else {
1914+ throw std::runtime_error (error_msg + name + " '." );
1915+ }
1916+
1917+ item = item->NextSiblingElement ();
1918+ }
18051919
18061920 value_set = true ;
18071921}
@@ -1821,6 +1935,9 @@ void FiberReinforcementStressParameters::print_parameters()
18211935 for (auto & [ key, value ] : params_name_value) {
18221936 std::cout << key << " : " << value << std::endl;
18231937 }
1938+
1939+ // Print directional distribution if defined
1940+ directional_distribution.print_parameters ();
18241941}
18251942
18261943// ////////////////////////////////////////////////////////
0 commit comments