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