3535// If a section does not contain any sub-sections then all parameters can be parsed automatically.
3636// See LinearSolverParameters::set_values() for an example.
3737//
38+ // Each section can read in parameters stored in an external XML file by adding an 'include_xml'
39+ // 'Parameter<std::string>' used to set the external XML file name. This is currently supported
40+ // for the following sections
41+ // - GeneralSimulationParameters
42+ // - MeshParameters
43+ // - DomainParameters
44+ // - EquationParameters
45+ //
3846#include " Parameters.h"
3947#include " consts.h"
4048#include " LinearAlgebra.h"
@@ -76,6 +84,26 @@ void xml_util_set_parameters( std::function<void(const std::string&, const std::
7684 }
7785}
7886
87+ // -----------------------
88+ // IncludeParametersFile
89+ // -----------------------
90+ // Set the root element of external XML file.
91+ //
92+ std::string IncludeParametersFile::NAME = " Include_xml" ;
93+
94+ IncludeParametersFile::IncludeParametersFile (const char * cfile_name)
95+ {
96+ std::string file_name (cfile_name);
97+ file_name.erase (std::remove_if (file_name.begin (), file_name.end (), ::isspace), file_name.end ());
98+ auto error = document.LoadFile (file_name.c_str ());
99+ root_element = document.FirstChildElement (Parameters::FSI_FILE.c_str ());
100+
101+ if (root_element == nullptr ) {
102+ throw std::runtime_error (" The following error occured while reading the XML file '" +
103+ file_name + " '.\n " + " [svMultiPhysics] ERROR " + std::string (document.ErrorStr ()));
104+ }
105+ }
106+
79107// ////////////////////////////////////////////////////////
80108// Parameters //
81109// ////////////////////////////////////////////////////////
@@ -1588,6 +1616,7 @@ DomainParameters::DomainParameters()
15881616 set_parameter (" Force_y" , 0.0 , !required, force_y);
15891617 set_parameter (" Force_z" , 0.0 , !required, force_z);
15901618
1619+ set_parameter (" Include_xml" , " " , !required, include_xml);
15911620 set_parameter (" Isotropic_conductivity" , 0.0 , !required, isotropic_conductivity);
15921621
15931622 set_parameter (" Mass_damping" , 0.0 , !required, mass_damping);
@@ -1642,17 +1671,29 @@ void DomainParameters::print_parameters()
16421671 solid_viscosity.print_parameters ();
16431672}
16441673
1645- void DomainParameters::set_values (tinyxml2::XMLElement* domain_elem)
1674+ // ------------
1675+ // set_values
1676+ // ------------
1677+ // Set the domain parameter values from the XML.
1678+ //
1679+ // If 'from_external_xml' is true then parameter values are read from an external xml file
1680+ // using the 'Include_xml' parameter.
1681+ //
1682+ void DomainParameters::set_values (tinyxml2::XMLElement* domain_elem, bool from_external_xml)
16461683{
16471684 using namespace tinyxml2 ;
16481685 std::string error_msg = " Unknown " + xml_element_name_ + " XML element '" ;
16491686
1650- const char * sid;
1651- auto result = domain_elem->QueryStringAttribute (" id" , &sid);
1652- if (sid == nullptr ) {
1653- throw std::runtime_error (" No ID found in the <Domain id=ID> XML element." );
1687+ // If not reading from an external xml file then get the <Domain id=ID> 'id' attrribute.
1688+ //
1689+ if (!from_external_xml) {
1690+ const char * sid;
1691+ auto result = domain_elem->QueryStringAttribute (" id" , &sid);
1692+ if (sid == nullptr ) {
1693+ throw std::runtime_error (" No ID found in the <Domain id=ID> XML element." );
1694+ }
1695+ id.set (std::string (sid));
16541696 }
1655- id.set (std::string (sid));
16561697
16571698 auto item = domain_elem->FirstChildElement ();
16581699
@@ -1680,6 +1721,11 @@ void DomainParameters::set_values(tinyxml2::XMLElement* domain_elem)
16801721 else {
16811722 throw std::runtime_error (" Viscosity model not supported for equation '" + equation.value () + " '." );
16821723 }
1724+
1725+ } else if (name == include_xml.name ()) {
1726+ auto value = item->GetText ();
1727+ IncludeParametersFile include_parameters (value);
1728+ set_values (include_parameters.root_element , true );
16831729
16841730 } else if (item->GetText () != nullptr ) {
16851731 auto value = item->GetText ();
@@ -1980,6 +2026,7 @@ EquationParameters::EquationParameters()
19802026 //
19812027 set_parameter (" Coupled" , false , !required, coupled);
19822028
2029+ set_parameter (IncludeParametersFile::NAME, " " , !required, include_xml);
19832030 set_parameter (" Initialize" , " " , !required, initialize);
19842031 set_parameter (" Initialize_RCR_from_flow" , false , !required, initialize_rcr_from_flow);
19852032
@@ -1990,6 +2037,7 @@ EquationParameters::EquationParameters()
19902037
19912038 set_parameter (" Tolerance" , 0.5 , !required, tolerance);
19922039 set_parameter (" Use_taylor_hood_type_basis" , false , !required, use_taylor_hood_type_basis);
2040+
19932041}
19942042
19952043void EquationParameters::print_parameters ()
@@ -2034,10 +2082,24 @@ void EquationParameters::print_parameters()
20342082 ecg_leads.print_parameters ();
20352083}
20362084
2037- void EquationParameters::set_values (tinyxml2::XMLElement* eq_elem)
2085+ void EquationParameters::set_values (tinyxml2::XMLElement* eq_elem, DomainParameters* domain )
20382086{
2039- using namespace tinyxml2 ;
2040- default_domain = new DomainParameters ();
2087+ static std::set<std::string> viscosity_names {
2088+ FluidViscosityParameters::xml_element_name_,
2089+ SolidViscosityParameters::xml_element_name_
2090+ };
2091+
2092+ static std::set<consts::EquationType> fluid_eqs {
2093+ consts::EquationType::phys_fluid,
2094+ consts::EquationType::phys_CMM,
2095+ consts::EquationType::phys_stokes
2096+ };
2097+
2098+ if (domain == nullptr ) {
2099+ default_domain = new DomainParameters ();
2100+ domain = default_domain;
2101+ }
2102+
20412103 auto item = eq_elem->FirstChildElement ();
20422104
20432105 // Parse XML sub-elements.
@@ -2058,8 +2120,8 @@ void EquationParameters::set_values(tinyxml2::XMLElement* eq_elem)
20582120 boundary_conditions.push_back (bc_params);
20592121
20602122 } else if (name == ConstitutiveModelParameters::xml_element_name_) {
2061- default_domain ->constitutive_model .set_values (item);
2062- default_domain ->constitutive_model .check_constitutive_model (type);
2123+ domain ->constitutive_model .set_values (item);
2124+ domain ->constitutive_model .check_constitutive_model (type);
20632125
20642126 } else if (name == CoupleCplBCParameters::xml_element_name_) {
20652127 couple_to_cplBC.set_values (item);
@@ -2076,7 +2138,7 @@ void EquationParameters::set_values(tinyxml2::XMLElement* eq_elem)
20762138 domains.push_back (domain_params);
20772139
20782140 } else if (name == FiberReinforcementStressParameters::xml_element_name_) {
2079- default_domain ->fiber_reinforcement_stress .set_values (item);
2141+ domain ->fiber_reinforcement_stress .set_values (item);
20802142
20812143 } else if (name == LinearSolverParameters::xml_element_name_) {
20822144 linear_solver.set_values (item);
@@ -2090,14 +2152,15 @@ void EquationParameters::set_values(tinyxml2::XMLElement* eq_elem)
20902152 remesher.set_values (item);
20912153
20922154 } else if (name == StimulusParameters::xml_element_name_) {
2093- default_domain ->stimulus .set_values (item);
2155+ domain ->stimulus .set_values (item);
20942156
2095- } else if (name == FluidViscosityParameters::xml_element_name_ || name == SolidViscosityParameters::xml_element_name_) {
2157+ } else if (viscosity_names. count ( name)) {
20962158 auto eq_type = consts::equation_name_to_type.at (type.value ());
2097- if (eq_type == consts::EquationType::phys_fluid || eq_type == consts::EquationType::phys_CMM || eq_type == consts::EquationType::phys_stokes) {
2098- default_domain->fluid_viscosity .set_values (item);
2159+
2160+ if (fluid_eqs.count (eq_type)) {
2161+ domain->fluid_viscosity .set_values (item);
20992162 } else if (eq_type == consts::EquationType::phys_struct || eq_type == consts::EquationType::phys_ustruct) {
2100- default_domain ->solid_viscosity .set_values (item);
2163+ domain ->solid_viscosity .set_values (item);
21012164 } else {
21022165 throw std::runtime_error (" Viscosity model not supported for equation '" + type.value () + " '." );
21032166 }
@@ -2108,6 +2171,11 @@ void EquationParameters::set_values(tinyxml2::XMLElement* eq_elem)
21082171 } else if (name == VariableWallPropsParameters::xml_element_name_) {
21092172 variable_wall_properties.set_values (item);
21102173
2174+ } else if (name == include_xml.name ()) {
2175+ auto value = item->GetText ();
2176+ IncludeParametersFile include_parameters (value);
2177+ set_values (include_parameters.root_element , default_domain);
2178+
21112179 } else if (item->GetText () != nullptr ) {
21122180 auto value = item->GetText ();
21132181
@@ -2124,8 +2192,9 @@ void EquationParameters::set_values(tinyxml2::XMLElement* eq_elem)
21242192 }
21252193 }
21262194
2195+
21272196 } else {
2128- throw std::runtime_error (" Unknown " + xml_element_name_ + " XML element '" + name + " ." );
2197+ throw std::runtime_error (" [Equation] Unknown " + xml_element_name_ + " XML element '" + name + " ." );
21292198 }
21302199
21312200 item = item->NextSiblingElement ();
@@ -2162,6 +2231,7 @@ GeneralSimulationParameters::GeneralSimulationParameters()
21622231
21632232 set_parameter (" Debug" , false , !required, debug);
21642233
2234+ set_parameter (" Include_xml" , " " , !required, include_xml);
21652235 set_parameter (" Increment_in_saving_restart_files" , 0 , !required, increment_in_saving_restart_files);
21662236 set_parameter (" Increment_in_saving_VTK_files" , 0 , !required, increment_in_saving_vtk_files);
21672237
@@ -2204,28 +2274,45 @@ void GeneralSimulationParameters::print_parameters()
22042274}
22052275
22062276// / @brief Set general parameters values from XML.
2207- void GeneralSimulationParameters::set_values (tinyxml2::XMLElement* xml_element)
2277+ void GeneralSimulationParameters::set_values (tinyxml2::XMLElement* xml_element, bool from_external_xml )
22082278{
22092279 using namespace tinyxml2 ;
2280+ tinyxml2::XMLElement* item;
22102281
22112282 // Set parameter values from the XML elements.
22122283 //
2213- auto general_params = xml_element->FirstChildElement (xml_element_name.c_str ());
2214- auto item = general_params->FirstChildElement ();
2284+ if (from_external_xml) {
2285+ item = xml_element->FirstChildElement ();
2286+ } else {
2287+ auto general_params = xml_element->FirstChildElement (xml_element_name.c_str ());
2288+ item = general_params->FirstChildElement ();
2289+ }
22152290
22162291 while (item != nullptr ) {
22172292 std::string name = std::string (item->Value ());
22182293 auto value = item->GetText ();
2219- try {
2220- set_parameter_value (name, value);
2221- } catch (const std::bad_function_call& exception) {
2222- throw std::runtime_error (" Unknown XML GeneralSimulationParameters element '" + name + " ." );
2294+
2295+ if (name == include_xml.name ()) {
2296+ auto value = item->GetText ();
2297+ IncludeParametersFile include_parameters (value);
2298+ set_values (include_parameters.root_element , true );
2299+
2300+ } else {
2301+
2302+ try {
2303+ set_parameter_value (name, value);
2304+ } catch (const std::bad_function_call& exception) {
2305+ throw std::runtime_error (" Unknown XML GeneralSimulationParameters element '" + name + " ." );
2306+ }
22232307 }
2308+
22242309 item = item->NextSiblingElement ();
22252310 }
22262311
22272312 // Check that required parameters have been set.
2228- check_required ();
2313+ if (!from_external_xml) {
2314+ check_required ();
2315+ }
22292316}
22302317
22312318// ////////////////////////////////////////////////////////
@@ -2407,6 +2494,7 @@ MeshParameters::MeshParameters()
24072494 set_parameter (" Mesh_scale_factor" , 1.0 , !required, mesh_scale_factor);
24082495 set_parameter (" Prestress_file_path" , " " , !required, prestress_file_path);
24092496
2497+ set_parameter (" Include_xml" , " " , !required, include_xml);
24102498 set_parameter (" Initial_displacements_file_path" , " " , !required, initial_displacements_file_path);
24112499 set_parameter (" Initial_pressures_file_path" , " " , !required, initial_pressures_file_path);
24122500 set_parameter (" Initial_velocities_file_path" , " " , !required, initial_velocities_file_path);
@@ -2439,7 +2527,7 @@ void MeshParameters::print_parameters()
24392527 }
24402528}
24412529
2442- void MeshParameters::set_values (tinyxml2::XMLElement* mesh_elem)
2530+ void MeshParameters::set_values (tinyxml2::XMLElement* mesh_elem, bool from_external_xml )
24432531{
24442532 using namespace tinyxml2 ;
24452533 std::string error_msg = " Unknown " + xml_element_name_ + " XML element '" ;
@@ -2463,6 +2551,11 @@ void MeshParameters::set_values(tinyxml2::XMLElement* mesh_elem)
24632551 dir.set (value);
24642552 fiber_directions.push_back (dir);
24652553
2554+ } else if (name == include_xml.name ()) {
2555+ auto value = item->GetText ();
2556+ IncludeParametersFile include_parameters (value);
2557+ set_values (include_parameters.root_element , true );
2558+
24662559 // Just a simple element.
24672560 } else if (item->GetText () != nullptr ) {
24682561 auto value = item->GetText ();
0 commit comments