96 if (action.size() == 1)
102 "The temperature unit must be specified for Thermochimica objects to be constructed");
106 "The pressure unit must be specified for Thermochimica objects to be constructed");
110 "The mass unit must be specified for Thermochimica objects to be constructed");
114 "Temperature variable must be specified for this object to be constructed");
119 "output_species_unit",
120 "Output mass unit must be specified for Thermochimica user object to be constructed");
124#ifdef THERMOCHIMICA_ENABLED
128 const auto thermo_file = getParam<FileName>(
"thermofile");
130 if (thermo_file.length() > 1024)
132 "Path exceeds Thermochimica's maximal permissible length of 1024 with ",
133 thermo_file.length(),
137 Thermochimica::setThermoFilename(thermo_file);
140 Thermochimica::parseThermoFile();
142 const auto idbg = Thermochimica::checkInfoThermo();
144 paramError(
"thermofile",
"Thermochimica data file cannot be parsed. ", idbg);
149 Thermochimica::checkTemperature(tunit);
150 Thermochimica::setUnitTemperature(tunit);
151 int idbg = Thermochimica::checkInfoThermo();
153 paramError(
"tunit",
"Cannot set temperature unit in Thermochimica", idbg);
156 Thermochimica::checkPressure(punit);
157 Thermochimica::setUnitPressure(punit);
158 idbg = Thermochimica::checkInfoThermo();
160 paramError(
"punit",
"Cannot set pressure unit in Thermochimica", idbg);
163 std::replace(munit.begin(), munit.end(),
'_',
' ');
164 Thermochimica::checkMass(munit);
165 Thermochimica::setUnitMass(munit);
166 idbg = Thermochimica::checkInfoThermo();
168 paramError(
"munit",
"Cannot set mass unit in Thermochimica", idbg);
170 _elements = getParam<std::vector<std::string>>(
"elements");
173 _elements.resize(Thermochimica::getNumberElementsDatabase());
174 _elements = Thermochimica::getElementsDatabase();
175 mooseInfo(
"Thermochimica elements: 'ALL' specified in input file. Using: ",
180 std::vector<std::string> db_elements(Thermochimica::getNumberElementsDatabase());
181 db_elements = Thermochimica::getElementsDatabase();
182 for (
const auto i : index_range(
_elements))
183 if (std::find(db_elements.begin(), db_elements.end(),
_elements[i]) == db_elements.end())
187 for (
const auto i : index_range(
_elements))
194 Thermochimica::setTemperaturePressure(1000.0, 1.0);
195 Thermochimica::setElementMass(0, 0.0);
197 for (
const auto i : make_range(
_elements.size()))
198 Thermochimica::setElementMass(Thermochimica::atomicNumber(
_elements[i]), 1.0);
200 Thermochimica::setup();
204 _phases = getParam<std::vector<std::string>>(
"output_phases");
207 auto [soln_phases, stoich_phases] = Thermochimica::getNumberPhasesSystem();
208 _phases.resize(soln_phases + stoich_phases);
209 _phases = Thermochimica::getPhaseNamesSystem();
210 mooseInfo(
"ChemicalCompositionAction phases: 'ALL' specified in input file. Using: ",
215 auto db_phases = Thermochimica::getPhaseNamesSystem();
216 for (
const auto i : index_range(
_phases))
217 if (std::find(db_phases.begin(), db_phases.end(),
_phases[i]) == db_phases.end())
218 paramError(
"output_phases",
"Phase '",
_phases[i],
"' was not found in the simulation.");
224 auto species = getParam<std::vector<std::string>>(
"output_species");
225 auto db_phases = Thermochimica::getPhaseNamesSystem();
226 auto n_db_species = Thermochimica::getNumberSpeciesSystem();
227 auto db_species = Thermochimica::getSpeciesSystem();
228 for (
auto i : index_range(n_db_species))
229 if (Thermochimica::isPhaseMQM(i))
231 auto [pairs, quads, idbg] =
232 Thermochimica::getMqmqaNumberPairsQuads(Thermochimica::getPhaseNamesSystem()[i]);
233 n_db_species[i] = pairs;
236 if (species.size() == 1 && species[0] ==
"ALL")
238 if (!n_db_species.empty())
239 species.resize(n_db_species.back());
241 mooseInfo(
"ChemicalCompositionAction species: 'ALL' specified in input file. Thermochimica "
242 "returned no possible species.");
246 for (
const auto i : make_range(db_species.size()))
247 for (
const auto j : index_range(db_species[i]))
249 species.push_back(db_phases[i] +
":" + db_species[i][j]);
252 mooseInfo(
"ChemicalCompositionAction species: 'ALL' specified in input file. Using: ",
256 for (
const auto i : index_range(species))
259 std::vector<std::string> tokens;
261 if (tokens.size() == 1)
262 paramError(
"output_species",
"No ':' separator found in variable '", species[i],
"'");
264 auto phase_index = std::find(db_phases.begin(), db_phases.end(), tokens[0]);
265 if (phase_index == db_phases.end())
269 "' of output species '",
271 "' not found in the simulation.");
272 auto sp = db_species[std::distance(db_phases.begin(), phase_index)];
273 if (std::find(sp.begin(), sp.end(), tokens[1]) == sp.end())
275 "output_species",
"Species '", tokens[1],
"' was not found in the simulation.");
282 auto element_potentials = getParam<std::vector<std::string>>(
"output_element_potentials");
283 if (element_potentials.size() == 1 && element_potentials[0] ==
"ALL")
287 element_potentials.resize(
_elements.size());
288 for (
const auto i : index_range(
_elements))
289 element_potentials[i] =
"mu:" +
_elements[i];
291 "ChemicalCompositionAction element potentials: 'ALL' specified in input file. Using: ",
297 for (
const auto i : index_range(element_potentials))
299 std::vector<std::string> tokens;
301 if (tokens.size() == 1)
303 "No ':' separator found in variable '",
304 element_potentials[i],
310 "' was not found in the simulation.");
318 auto vapor_pressures = getParam<std::vector<std::string>>(
"output_vapor_pressures");
319 if (!Thermochimica::isPhaseGas(0))
321 "No gas phase found in the simulation. Cannot output vapor pressures.");
322 if (vapor_pressures.size() == 1 && vapor_pressures[0] ==
"ALL")
324 vapor_pressures.resize(Thermochimica::getNumberSpeciesSystem()[0]);
326 auto db_gas_species = Thermochimica::getSpeciesInPhase(0);
327 auto gas_name = Thermochimica::getPhaseNamesSystem()[0];
328 for (
const auto i : index_range(db_gas_species))
330 vapor_pressures[i] =
"vp:" + gas_name +
':' + db_gas_species[i];
333 mooseInfo(
"ChemicalCompositionAction vapor pressures: 'ALL' specified in input file. Using: ",
338 auto db_gas_species = Thermochimica::getSpeciesInPhase(0);
340 for (
const auto i : index_range(vapor_pressures))
342 std::vector<std::string> tokens;
344 if (tokens.size() == 1)
346 "No ':' separator found in variable '",
349 if (tokens[1] != Thermochimica::getPhaseNamesSystem()[0])
353 "' of vapor species '",
355 "' is not a gas phase. Cannot calculate vapor pressure.");
356 if (std::find(db_gas_species.begin(), db_gas_species.end(), tokens[2]) ==
357 db_gas_species.end())
361 "' was not found in the gas phase of simulation.");
369 auto element_phases = getParam<std::vector<std::string>>(
"output_element_phases");
370 auto db_phases = Thermochimica::getPhaseNamesSystem();
371 if (element_phases.size() == 1 && element_phases[0] ==
"ALL")
373 element_phases.resize(
_elements.size() * db_phases.size());
375 for (
const auto i : index_range(db_phases))
376 for (
const auto j : index_range(
_elements))
380 std::make_pair(db_phases[i],
_elements[j]);
383 "ChemicalCompositionAction elements in phase: 'ALL' specified in input file. Using: ",
389 for (
const auto i : index_range(element_phases))
391 std::vector<std::string> tokens;
393 if (tokens.size() == 1)
395 "No ':' separator found in variable '",
398 if (std::find(db_phases.begin(), db_phases.end(), tokens[1]) == db_phases.end())
404 "' not found in the simulation.");
409 "' was not found in the simulation.");
415 Thermochimica::resetThermoAll();
423#ifdef THERMOCHIMICA_ENABLED
430 FEType(Utility::string_to_enum<Order>(
_problem->mesh().hasSecondOrderElements() ?
"SECOND"
432 Utility::string_to_enum<libMesh::FEFamily>(
"LAGRANGE")),
433 getParam<bool>(
"is_fv"),
438 for (
const auto i : index_range(
_elements))
441 for (
const auto i : index_range(
_phases))
452 _problem->addAuxVariable(aux_var_type,
472 const std::string class_name =
"ConstantIC";
474 params.
set<VariableName>(
"variable") = it.first;
475 params.set<Real>(
"value") = it.second;
476 params.applySpecificParameters(
parameters(), {
"block"});
477 _problem->addInitialCondition(class_name, it.first +
"_ic", params);
486 std::string uo_name = getParam<std::string>(
"uo_name");
492 getParam<bool>(
"is_fv") ?
"ThermochimicaElementData" :
"ThermochimicaNodalData";
498 std::back_inserter(uo_params.set<std::vector<VariableName>>(
"elements")));
503 std::back_inserter(uo_params.set<std::vector<VariableName>>(
"output_phases")));
507 std::vector<std::string> species;
510 uo_params.set<std::vector<VariableName>>(
"output_species")
511 .insert(uo_params.set<std::vector<VariableName>>(
"output_species").end(),
518 std::vector<std::string> element_potentials;
520 element_potentials.push_back(
"mu:" +
token);
521 uo_params.set<std::vector<VariableName>>(
"output_element_potentials")
522 .insert(uo_params.set<std::vector<VariableName>>(
"output_element_potentials").end(),
523 element_potentials.begin(),
524 element_potentials.end());
529 std::vector<std::string> vapor_pressures;
532 uo_params.set<std::vector<VariableName>>(
"output_vapor_pressures")
533 .insert(uo_params.set<std::vector<VariableName>>(
"output_vapor_pressures").end(),
534 vapor_pressures.begin(),
535 vapor_pressures.end());
540 std::vector<std::string> element_phases;
543 uo_params.set<std::vector<VariableName>>(
"output_element_phases")
544 .insert(uo_params.set<std::vector<VariableName>>(
"output_element_phases").end(),
545 element_phases.begin(),
546 element_phases.end());
548 uo_params.set<std::vector<VariableName>>(
"temperature") =
549 getParam<std::vector<VariableName>>(
"temperature");
553 uo_params.set<FileName>(
"thermofile") = getParam<FileName>(
"thermofile");
555 uo_params.set<
MooseEnum>(
"reinit_type") = getParam<MooseEnum>(
"reinitialization_type");
557 uo_params.set<
MooseEnum>(
"output_species_unit") = getParam<MooseEnum>(
"output_species_unit");
561 _problem->addUserObject(uo_type, uo_name, uo_params);