Skip to content

Commit 3be16f6

Browse files
Add reading in an XML file within the solver XML file (SimVascular#460)
* Change file name. * Add processing of reading xml file within the solver xml file. * Add a new class and clean up processing an external xml file. Add reading an xml file for Domains. * Add Include_xml for general and mesh parameters. * Delete tests/cases/fluid/pipe_RCR_sv0D/run-multiphysics.sh * Delete tests/cases/fluid/pipe_RCR_sv0D/linear.xml * Delete tests/cases/fluid/pipe_RCR_sv0D/solver-include.xml --------- Co-authored-by: Aaron Brown <[email protected]>
1 parent 6ed3217 commit 3be16f6

File tree

3 files changed

+155
-34
lines changed

3 files changed

+155
-34
lines changed

Code/Source/solver/Parameters.cpp

Lines changed: 120 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@
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

19952043
void 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

Comments
 (0)