Line data Source code
1 : //* This file is part of the MOOSE framework
2 : //* https://mooseframework.inl.gov
3 : //*
4 : //* All rights reserved, see COPYRIGHT for full restrictions
5 : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 : //*
7 : //* Licensed under LGPL 2.1, please see LICENSE for details
8 : //* https://www.gnu.org/licenses/lgpl-2.1.html
9 :
10 : #include "ChemicalCompositionAction.h"
11 : #include "ThermochimicaUtils.h"
12 : #include "FEProblemBase.h"
13 : #include "MooseMesh.h"
14 : #include "MooseUtils.h"
15 : #include "AddVariableAction.h"
16 : #include "libmesh/string_to_enum.h"
17 : #include "BlockRestrictable.h"
18 : #include "InputParameterWarehouse.h"
19 :
20 : #ifdef THERMOCHIMICA_ENABLED
21 : #include "Thermochimica-cxx.h"
22 : #include "checkUnits.h"
23 : #endif
24 :
25 : registerMooseAction("ChemicalReactionsApp", ChemicalCompositionAction, "add_variable");
26 : registerMooseAction("ChemicalReactionsApp", ChemicalCompositionAction, "add_aux_variable");
27 : registerMooseAction("ChemicalReactionsApp", ChemicalCompositionAction, "add_ic");
28 : registerMooseAction("ChemicalReactionsApp", ChemicalCompositionAction, "add_user_object");
29 : registerMooseAction("ChemicalReactionsApp", ChemicalCompositionAction, "add_aux_kernel");
30 :
31 : InputParameters
32 261 : ChemicalCompositionAction::validParams()
33 : {
34 261 : InputParameters params = Action::validParams();
35 261 : params += BlockRestrictable::validParams();
36 :
37 261 : ThermochimicaUtils::addClassDescription(params,
38 : "Sets up the thermodynamic model and variables for the "
39 : "thermochemistry solve using Thermochimica.");
40 :
41 : // Required variables
42 1044 : params.addParam<std::vector<std::string>>(
43 : "elements", {"ALL"}, "List of chemical elements (or ALL)");
44 522 : params.addCoupledVar("temperature", "Name of temperature variable");
45 522 : params.addCoupledVar("pressure", "Name of pressure variable");
46 522 : MooseEnum reinit_type("none time nodal", "nodal");
47 522 : params.addParam<MooseEnum>(
48 : "reinitialization_type", reinit_type, "Reinitialization scheme to use with Thermochimica");
49 522 : params.addParam<FileName>("initial_values", "The CSV file name with initial conditions.");
50 522 : params.addParam<FileName>("thermofile", "Thermodynamics model file");
51 :
52 522 : MooseEnum tUnit("K C F R");
53 522 : params.addParam<MooseEnum>("tunit", tUnit, "Temperature Unit");
54 522 : MooseEnum pUnit("atm psi bar Pa kPa");
55 522 : params.addParam<MooseEnum>("punit", pUnit, "Pressure Unit");
56 : MooseEnum mUnit(
57 522 : "mole_fraction atom_fraction atoms moles gram-atoms mass_fraction kilograms grams pounds");
58 522 : params.addParam<MooseEnum>("munit", mUnit, "Mass Unit");
59 261 : ExecFlagEnum exec_enum = MooseUtils::getDefaultExecFlagEnum();
60 1044 : exec_enum = {EXEC_INITIAL, EXEC_TIMESTEP_END};
61 522 : params.addParam<ExecFlagEnum>(
62 : "execute_on", exec_enum, "When to execute the ThermochimicaData UO");
63 522 : params.addParam<bool>("is_fv", false, "Should the variables set up by action be of FV type");
64 :
65 522 : params.addParam<std::vector<std::string>>("output_phases", {}, "List of phases to be output");
66 522 : params.addParam<std::vector<std::string>>(
67 : "output_species", {}, "List species for which concentration in the phases is needed");
68 522 : MooseEnum mUnit_op("moles mole_fraction");
69 522 : params.addParam<MooseEnum>(
70 : "output_species_unit", mUnit_op, "Mass unit for output species: mole_fractions or moles");
71 522 : params.addParam<std::vector<std::string>>(
72 : "output_element_potentials",
73 : {},
74 : "List of chemical elements for which chemical potentials are requested");
75 522 : params.addParam<std::vector<std::string>>(
76 : "output_vapor_pressures",
77 : {},
78 : "List of gas phase species for which vapor pressures are requested");
79 522 : params.addParam<std::vector<std::string>>(
80 : "output_element_phases",
81 : {},
82 : "List of elements whose molar amounts in specific phases are requested");
83 522 : params.addParam<std::string>(
84 : "uo_name", "Thermochimica", "Name of the ThermochimicaDataUserObject.");
85 261 : return params;
86 1305 : }
87 :
88 135 : ChemicalCompositionAction::ChemicalCompositionAction(const InputParameters & parameters)
89 135 : : Action(parameters)
90 : {
91 135 : const auto & params = _app.getInputParameterWarehouse().getInputParameters();
92 135 : InputParameters & pars(*(params.find(uniqueActionName())->second.get()));
93 :
94 : // check if a container block with common parameters is found
95 135 : auto action = _awh.getActions<CommonChemicalCompositionAction>();
96 135 : if (action.size() == 1)
97 135 : pars.applyParameters(action[0]->parameters());
98 :
99 270 : if (!isParamValid("tunit"))
100 2 : paramError(
101 : "tunit",
102 : "The temperature unit must be specified for Thermochimica objects to be constructed");
103 :
104 266 : if (!isParamValid("punit"))
105 2 : paramError("punit",
106 : "The pressure unit must be specified for Thermochimica objects to be constructed");
107 :
108 262 : if (!isParamValid("munit"))
109 2 : paramError("munit",
110 : "The mass unit must be specified for Thermochimica objects to be constructed");
111 :
112 258 : if (!isParamValid("temperature"))
113 0 : paramError("temperature",
114 : "Temperature variable must be specified for this object to be constructed");
115 :
116 516 : if ((isParamValid("output_species") || isParamValid("output_element_phases")) &&
117 387 : !isParamValid("output_species_unit"))
118 2 : paramError(
119 : "output_species_unit",
120 : "Output mass unit must be specified for Thermochimica user object to be constructed");
121 :
122 127 : ThermochimicaUtils::checkLibraryAvailability(*this);
123 :
124 : #ifdef THERMOCHIMICA_ENABLED
125 : // Initialize database in Thermochimica
126 254 : if (isParamValid("thermofile"))
127 : {
128 254 : const auto thermo_file = getParam<FileName>("thermofile");
129 :
130 127 : if (thermo_file.length() > 1024)
131 0 : paramError("thermofile",
132 : "Path exceeds Thermochimica's maximal permissible length of 1024 with ",
133 : thermo_file.length(),
134 : " characters: ",
135 : thermo_file);
136 :
137 127 : Thermochimica::setThermoFilename(thermo_file);
138 :
139 : // Read in thermodynamics model for setting up variables
140 127 : Thermochimica::parseThermoFile();
141 :
142 127 : const auto idbg = Thermochimica::checkInfoThermo();
143 127 : if (idbg != 0)
144 2 : paramError("thermofile", "Thermochimica data file cannot be parsed. ", idbg);
145 : }
146 :
147 : // Set thermochimica units
148 250 : auto tunit = Moose::stringify(getParam<MooseEnum>("tunit"));
149 125 : Thermochimica::checkTemperature(tunit);
150 125 : Thermochimica::setUnitTemperature(tunit);
151 125 : int idbg = Thermochimica::checkInfoThermo();
152 125 : if (idbg != 0)
153 0 : paramError("tunit", "Cannot set temperature unit in Thermochimica", idbg);
154 :
155 250 : auto punit = Moose::stringify(getParam<MooseEnum>("punit"));
156 125 : Thermochimica::checkPressure(punit);
157 125 : Thermochimica::setUnitPressure(punit);
158 125 : idbg = Thermochimica::checkInfoThermo();
159 125 : if (idbg != 0)
160 0 : paramError("punit", "Cannot set pressure unit in Thermochimica", idbg);
161 :
162 375 : auto munit = Moose::stringify(getParam<MooseEnum>("munit"));
163 : std::replace(munit.begin(), munit.end(), '_', ' ');
164 125 : Thermochimica::checkMass(munit);
165 125 : Thermochimica::setUnitMass(munit);
166 125 : idbg = Thermochimica::checkInfoThermo();
167 125 : if (idbg != 0)
168 0 : paramError("munit", "Cannot set mass unit in Thermochimica", idbg);
169 :
170 375 : _elements = getParam<std::vector<std::string>>("elements");
171 125 : if (_elements.size() == 1 && _elements[0] == "ALL")
172 : {
173 9 : _elements.resize(Thermochimica::getNumberElementsDatabase());
174 18 : _elements = Thermochimica::getElementsDatabase();
175 9 : mooseInfo("Thermochimica elements: 'ALL' specified in input file. Using: ",
176 18 : Moose::stringify(_elements));
177 : }
178 : else
179 : {
180 116 : std::vector<std::string> db_elements(Thermochimica::getNumberElementsDatabase());
181 232 : db_elements = Thermochimica::getElementsDatabase();
182 389 : for (const auto i : index_range(_elements))
183 275 : if (std::find(db_elements.begin(), db_elements.end(), _elements[i]) == db_elements.end())
184 2 : paramError("elements", "Element '", _elements[i], "' was not found in the database.");
185 114 : }
186 123 : _element_ids.resize(_elements.size());
187 432 : for (const auto i : index_range(_elements))
188 309 : _element_ids[i] = Thermochimica::atomicNumber(_elements[i]);
189 :
190 : // I want to check all the input parameters here and have a list of possible phases and species
191 : // for setting up the Aux variables with "ALL" option
192 :
193 : // Temporarily set Thermochimica state space to get the list of possible phases and species
194 123 : Thermochimica::setTemperaturePressure(1000.0, 1.0);
195 123 : Thermochimica::setElementMass(0, 0.0);
196 :
197 432 : for (const auto i : make_range(_elements.size()))
198 309 : Thermochimica::setElementMass(Thermochimica::atomicNumber(_elements[i]), 1.0);
199 :
200 123 : Thermochimica::setup();
201 :
202 246 : if (isParamValid("output_phases"))
203 : {
204 369 : _phases = getParam<std::vector<std::string>>("output_phases");
205 123 : if (_phases.size() == 1 && _phases[0] == "ALL")
206 : {
207 9 : auto [soln_phases, stoich_phases] = Thermochimica::getNumberPhasesSystem();
208 9 : _phases.resize(soln_phases + stoich_phases);
209 18 : _phases = Thermochimica::getPhaseNamesSystem();
210 9 : mooseInfo("ChemicalCompositionAction phases: 'ALL' specified in input file. Using: ",
211 18 : Moose::stringify(_phases));
212 : }
213 : else
214 : {
215 114 : auto db_phases = Thermochimica::getPhaseNamesSystem();
216 351 : for (const auto i : index_range(_phases))
217 239 : if (std::find(db_phases.begin(), db_phases.end(), _phases[i]) == db_phases.end())
218 2 : paramError("output_phases", "Phase '", _phases[i], "' was not found in the simulation.");
219 112 : }
220 : }
221 :
222 242 : if (isParamValid("output_species"))
223 : {
224 242 : auto species = getParam<std::vector<std::string>>("output_species");
225 121 : auto db_phases = Thermochimica::getPhaseNamesSystem();
226 121 : auto n_db_species = Thermochimica::getNumberSpeciesSystem();
227 121 : auto db_species = Thermochimica::getSpeciesSystem();
228 1084 : for (auto i : index_range(n_db_species))
229 963 : if (Thermochimica::isPhaseMQM(i))
230 : {
231 : auto [pairs, quads, idbg] =
232 27 : Thermochimica::getMqmqaNumberPairsQuads(Thermochimica::getPhaseNamesSystem()[i]);
233 27 : n_db_species[i] = pairs;
234 : }
235 :
236 121 : if (species.size() == 1 && species[0] == "ALL")
237 : {
238 9 : if (!n_db_species.empty())
239 9 : species.resize(n_db_species.back());
240 : else
241 0 : mooseInfo("ChemicalCompositionAction species: 'ALL' specified in input file. Thermochimica "
242 : "returned no possible species.");
243 :
244 9 : species.clear();
245 9 : _tokenized_species.clear();
246 90 : for (const auto i : make_range(db_species.size()))
247 396 : for (const auto j : index_range(db_species[i]))
248 : {
249 630 : species.push_back(db_phases[i] + ":" + db_species[i][j]);
250 315 : _tokenized_species.push_back(std::make_pair(db_phases[i], db_species[i][j]));
251 : }
252 9 : mooseInfo("ChemicalCompositionAction species: 'ALL' specified in input file. Using: ",
253 18 : Moose::stringify(species));
254 : }
255 : else
256 425 : for (const auto i : index_range(species))
257 : {
258 319 : _tokenized_species.resize(species.size());
259 : std::vector<std::string> tokens;
260 638 : MooseUtils::tokenize(species[i], tokens, 1, ":");
261 319 : if (tokens.size() == 1)
262 2 : paramError("output_species", "No ':' separator found in variable '", species[i], "'");
263 :
264 317 : auto phase_index = std::find(db_phases.begin(), db_phases.end(), tokens[0]);
265 317 : if (phase_index == db_phases.end())
266 2 : paramError("output_species",
267 : "Phase '",
268 : tokens[0],
269 : "' of output species '",
270 : species[i],
271 : "' not found in the simulation.");
272 315 : auto sp = db_species[std::distance(db_phases.begin(), phase_index)];
273 315 : if (std::find(sp.begin(), sp.end(), tokens[1]) == sp.end())
274 2 : paramError(
275 : "output_species", "Species '", tokens[1], "' was not found in the simulation.");
276 313 : _tokenized_species[i] = std::make_pair(tokens[0], tokens[1]);
277 313 : }
278 115 : }
279 :
280 230 : if (isParamValid("output_element_potentials"))
281 : {
282 345 : auto element_potentials = getParam<std::vector<std::string>>("output_element_potentials");
283 115 : if (element_potentials.size() == 1 && element_potentials[0] == "ALL")
284 : {
285 9 : _tokenized_element_potentials.resize(_elements.size());
286 9 : _tokenized_element_potentials = _elements;
287 9 : element_potentials.resize(_elements.size());
288 45 : for (const auto i : index_range(_elements))
289 72 : element_potentials[i] = "mu:" + _elements[i];
290 9 : mooseInfo(
291 : "ChemicalCompositionAction element potentials: 'ALL' specified in input file. Using: ",
292 18 : Moose::stringify(element_potentials));
293 : }
294 : else
295 : {
296 106 : _tokenized_element_potentials.resize(element_potentials.size());
297 287 : for (const auto i : index_range(element_potentials))
298 : {
299 : std::vector<std::string> tokens;
300 370 : MooseUtils::tokenize(element_potentials[i], tokens, 1, ":");
301 185 : if (tokens.size() == 1)
302 2 : paramError("output_element_potentials",
303 : "No ':' separator found in variable '",
304 : element_potentials[i],
305 : "'");
306 183 : if (std::find(_elements.begin(), _elements.end(), tokens[1]) == _elements.end())
307 2 : paramError("output_element_potentials",
308 : "Element '",
309 : tokens[1],
310 : "' was not found in the simulation.");
311 : _tokenized_element_potentials[i] = tokens[1];
312 181 : }
313 : }
314 111 : }
315 :
316 222 : if (isParamValid("output_vapor_pressures"))
317 : {
318 222 : auto vapor_pressures = getParam<std::vector<std::string>>("output_vapor_pressures");
319 111 : if (!Thermochimica::isPhaseGas(0))
320 0 : paramError("output_vapor_pressures",
321 : "No gas phase found in the simulation. Cannot output vapor pressures.");
322 111 : if (vapor_pressures.size() == 1 && vapor_pressures[0] == "ALL")
323 : {
324 9 : vapor_pressures.resize(Thermochimica::getNumberSpeciesSystem()[0]);
325 9 : _tokenized_vapor_species.resize(Thermochimica::getNumberSpeciesSystem()[0]);
326 9 : auto db_gas_species = Thermochimica::getSpeciesInPhase(0);
327 9 : auto gas_name = Thermochimica::getPhaseNamesSystem()[0];
328 54 : for (const auto i : index_range(db_gas_species))
329 : {
330 90 : vapor_pressures[i] = "vp:" + gas_name + ':' + db_gas_species[i];
331 90 : _tokenized_vapor_species[i] = std::make_pair(gas_name, db_gas_species[i]);
332 : }
333 9 : mooseInfo("ChemicalCompositionAction vapor pressures: 'ALL' specified in input file. Using: ",
334 18 : Moose::stringify(vapor_pressures));
335 9 : }
336 : else
337 : {
338 102 : auto db_gas_species = Thermochimica::getSpeciesInPhase(0);
339 102 : _tokenized_vapor_species.resize(vapor_pressures.size());
340 180 : for (const auto i : index_range(vapor_pressures))
341 : {
342 : std::vector<std::string> tokens;
343 168 : MooseUtils::tokenize(vapor_pressures[i], tokens, 1, ":");
344 84 : if (tokens.size() == 1)
345 2 : paramError("output_vapor_pressures",
346 : "No ':' separator found in variable '",
347 : vapor_pressures[i],
348 : "'");
349 82 : if (tokens[1] != Thermochimica::getPhaseNamesSystem()[0])
350 2 : paramError("output_vapor_pressures",
351 : "Phase '",
352 : tokens[1],
353 : "' of vapor species '",
354 : vapor_pressures[i],
355 : "' is not a gas phase. Cannot calculate vapor pressure.");
356 80 : if (std::find(db_gas_species.begin(), db_gas_species.end(), tokens[2]) ==
357 : db_gas_species.end())
358 2 : paramError("output_vapor_pressures",
359 : "Species '",
360 : tokens[2],
361 : "' was not found in the gas phase of simulation.");
362 78 : _tokenized_vapor_species[i] = std::make_pair(tokens[1], tokens[2]);
363 78 : }
364 96 : }
365 105 : }
366 :
367 210 : if (isParamValid("output_element_phases"))
368 : {
369 210 : auto element_phases = getParam<std::vector<std::string>>("output_element_phases");
370 105 : auto db_phases = Thermochimica::getPhaseNamesSystem();
371 105 : if (element_phases.size() == 1 && element_phases[0] == "ALL")
372 : {
373 9 : element_phases.resize(_elements.size() * db_phases.size());
374 9 : _tokenized_phase_elements.resize(_elements.size() * db_phases.size());
375 117 : for (const auto i : index_range(db_phases))
376 540 : for (const auto j : index_range(_elements))
377 : {
378 864 : element_phases[i * _elements.size() + j] = db_phases[i] + ':' + _elements[j];
379 432 : _tokenized_phase_elements[i * _elements.size() + j] =
380 864 : std::make_pair(db_phases[i], _elements[j]);
381 : }
382 9 : mooseInfo(
383 : "ChemicalCompositionAction elements in phase: 'ALL' specified in input file. Using: ",
384 18 : Moose::stringify(element_phases));
385 : }
386 : else
387 : {
388 96 : _tokenized_phase_elements.resize(element_phases.size());
389 150 : for (const auto i : index_range(element_phases))
390 : {
391 : std::vector<std::string> tokens;
392 120 : MooseUtils::tokenize(element_phases[i], tokens, 1, ":");
393 60 : if (tokens.size() == 1)
394 2 : paramError("output_element_phases",
395 : "No ':' separator found in variable '",
396 : element_phases[i],
397 : "'");
398 58 : if (std::find(db_phases.begin(), db_phases.end(), tokens[1]) == db_phases.end())
399 2 : paramError("output_element_phases",
400 : "Phase '",
401 : tokens[1],
402 : "' of '",
403 : element_phases[i],
404 : "' not found in the simulation.");
405 56 : if (std::find(_elements.begin(), _elements.end(), tokens[2]) == _elements.end())
406 2 : paramError("output_element_phases",
407 : "Element '",
408 : tokens[2],
409 : "' was not found in the simulation.");
410 54 : _tokenized_phase_elements[i] = std::make_pair(tokens[1], tokens[2]);
411 54 : }
412 : }
413 99 : }
414 :
415 99 : Thermochimica::resetThermoAll();
416 :
417 : #endif
418 99 : }
419 :
420 : void
421 495 : ChemicalCompositionAction::act()
422 : {
423 : #ifdef THERMOCHIMICA_ENABLED
424 : //
425 : // Add AuxVariables
426 : //
427 495 : if (_current_task == "add_aux_variable")
428 : {
429 : auto aux_var_type = AddVariableAction::variableType(
430 297 : FEType(Utility::string_to_enum<Order>(_problem->mesh().hasSecondOrderElements() ? "SECOND"
431 : : "FIRST"),
432 : Utility::string_to_enum<libMesh::FEFamily>("LAGRANGE")),
433 99 : /* is_fv = */ getParam<bool>("is_fv"),
434 198 : /* is_array = */ false);
435 99 : auto params = _factory.getValidParams(aux_var_type);
436 99 : params.applySpecificParameters(parameters(), {"block"});
437 :
438 360 : for (const auto i : index_range(_elements))
439 261 : _problem->addAuxVariable(aux_var_type, _elements[i], params);
440 :
441 396 : for (const auto i : index_range(_phases))
442 297 : _problem->addAuxVariable(aux_var_type, _phases[i], params);
443 :
444 657 : for (const auto i : index_range(_tokenized_species))
445 1116 : _problem->addAuxVariable(
446 1116 : aux_var_type, Moose::stringify(_tokenized_species[i], /* delim = */ ":"), params);
447 :
448 288 : for (const auto i : index_range(_tokenized_element_potentials))
449 378 : _problem->addAuxVariable(aux_var_type, "mu:" + _tokenized_element_potentials[i], params);
450 :
451 216 : for (const auto i : index_range(_tokenized_vapor_species))
452 234 : _problem->addAuxVariable(aux_var_type,
453 117 : "vp:" +
454 234 : Moose::stringify(_tokenized_vapor_species[i], /* delim = */ ":"),
455 : params);
456 :
457 585 : for (const auto i : index_range(_tokenized_phase_elements))
458 972 : _problem->addAuxVariable(
459 : aux_var_type,
460 972 : "ep:" + Moose::stringify(_tokenized_phase_elements[i], /* delim = */ ":"),
461 : params);
462 99 : }
463 :
464 : //
465 : // Set up initial conditions from a file
466 : //
467 693 : if (_current_task == "add_ic" && isParamValid("initial_values"))
468 : {
469 18 : readCSV();
470 72 : for (auto it : _initial_conditions)
471 : {
472 54 : const std::string class_name = "ConstantIC";
473 54 : auto params = _factory.getValidParams(class_name);
474 108 : params.set<VariableName>("variable") = it.first;
475 54 : params.set<Real>("value") = it.second;
476 54 : params.applySpecificParameters(parameters(), {"block"});
477 54 : _problem->addInitialCondition(class_name, it.first + "_ic", params);
478 54 : }
479 : }
480 :
481 : //
482 : // Set up user object
483 : //
484 495 : if (_current_task == "add_user_object")
485 : {
486 198 : std::string uo_name = getParam<std::string>("uo_name");
487 :
488 234 : if (isParamValid("block") && !isParamSetByUser("uo_name"))
489 54 : uo_name += "_" + Moose::stringify(getParam<std::vector<SubdomainName>>("block"));
490 :
491 : const auto uo_type =
492 198 : getParam<bool>("is_fv") ? "ThermochimicaElementData" : "ThermochimicaNodalData";
493 :
494 99 : auto uo_params = _factory.getValidParams(uo_type);
495 :
496 99 : std::copy(_elements.begin(),
497 : _elements.end(),
498 : std::back_inserter(uo_params.set<std::vector<VariableName>>("elements")));
499 :
500 198 : if (isParamValid("output_phases"))
501 198 : std::copy(_phases.begin(),
502 : _phases.end(),
503 : std::back_inserter(uo_params.set<std::vector<VariableName>>("output_phases")));
504 :
505 198 : if (isParamValid("output_species"))
506 : {
507 : std::vector<std::string> species;
508 657 : for (auto token : _tokenized_species)
509 1116 : species.push_back(Moose::stringify(token, ":"));
510 99 : uo_params.set<std::vector<VariableName>>("output_species")
511 198 : .insert(uo_params.set<std::vector<VariableName>>("output_species").end(),
512 : species.begin(),
513 : species.end());
514 99 : }
515 :
516 198 : if (isParamValid("output_element_potentials"))
517 : {
518 : std::vector<std::string> element_potentials;
519 288 : for (auto token : _tokenized_element_potentials)
520 378 : element_potentials.push_back("mu:" + token);
521 99 : uo_params.set<std::vector<VariableName>>("output_element_potentials")
522 198 : .insert(uo_params.set<std::vector<VariableName>>("output_element_potentials").end(),
523 : element_potentials.begin(),
524 : element_potentials.end());
525 99 : }
526 :
527 198 : if (isParamValid("output_vapor_pressures"))
528 : {
529 : std::vector<std::string> vapor_pressures;
530 216 : for (auto token : _tokenized_vapor_species)
531 234 : vapor_pressures.push_back("vp:" + Moose::stringify(token, ":"));
532 99 : uo_params.set<std::vector<VariableName>>("output_vapor_pressures")
533 198 : .insert(uo_params.set<std::vector<VariableName>>("output_vapor_pressures").end(),
534 : vapor_pressures.begin(),
535 : vapor_pressures.end());
536 99 : }
537 :
538 198 : if (isParamValid("output_element_phases"))
539 : {
540 : std::vector<std::string> element_phases;
541 585 : for (auto token : _tokenized_phase_elements)
542 972 : element_phases.push_back("ep:" + Moose::stringify(token, ":"));
543 99 : uo_params.set<std::vector<VariableName>>("output_element_phases")
544 198 : .insert(uo_params.set<std::vector<VariableName>>("output_element_phases").end(),
545 : element_phases.begin(),
546 : element_phases.end());
547 99 : }
548 198 : uo_params.set<std::vector<VariableName>>("temperature") =
549 198 : getParam<std::vector<VariableName>>("temperature");
550 :
551 99 : uo_params.set<ChemicalCompositionAction *>("_chemical_composition_action") = this;
552 :
553 297 : uo_params.set<FileName>("thermofile") = getParam<FileName>("thermofile");
554 :
555 297 : uo_params.set<MooseEnum>("reinit_type") = getParam<MooseEnum>("reinitialization_type");
556 :
557 297 : uo_params.set<MooseEnum>("output_species_unit") = getParam<MooseEnum>("output_species_unit");
558 :
559 99 : uo_params.applyParameters(parameters());
560 :
561 99 : _problem->addUserObject(uo_type, uo_name, uo_params);
562 99 : }
563 :
564 : #endif
565 495 : }
566 :
567 : void
568 18 : ChemicalCompositionAction::readCSV()
569 : {
570 36 : const auto & filename = getParam<FileName>("initial_values");
571 18 : std::ifstream file(filename.c_str());
572 18 : if (!file.good())
573 0 : paramError("initial_values", "Error opening file '", filename, "'.");
574 :
575 : std::string line;
576 : std::vector<std::string> items;
577 :
578 : // skip header
579 18 : std::getline(file, line);
580 72 : while (std::getline(file, line))
581 : {
582 108 : MooseUtils::tokenize(line, items, 1, ",");
583 54 : if (items.empty())
584 0 : continue;
585 54 : if (items.size() != 2)
586 0 : paramError("initial_value", "Unexpected line in CSV file: ", line);
587 :
588 54 : _initial_conditions[items[0]] = MooseUtils::convert<Real>(items[1]);
589 : }
590 36 : }
|