90{
93
94
96 if (action.size() == 1)
97 pars.applyParameters(action[0]->parameters());
98
101 "tunit",
102 "The temperature unit must be specified for Thermochimica objects to be constructed");
103
106 "The pressure unit must be specified for Thermochimica objects to be constructed");
107
110 "The mass unit must be specified for Thermochimica objects to be constructed");
111
114 "Temperature variable must be specified for this object to be constructed");
115
119 "output_species_unit",
120 "Output mass unit must be specified for Thermochimica user object to be constructed");
121
123
124#ifdef THERMOCHIMICA_ENABLED
125
127 {
128 const auto thermo_file = getParam<FileName>("thermofile");
129
130 if (thermo_file.length() > 1024)
132 "Path exceeds Thermochimica's maximal permissible length of 1024 with ",
133 thermo_file.length(),
134 " characters: ",
135 thermo_file);
136
137 Thermochimica::setThermoFilename(thermo_file);
138
139
140 Thermochimica::parseThermoFile();
141
142 const auto idbg = Thermochimica::checkInfoThermo();
143 if (idbg != 0)
144 paramError(
"thermofile",
"Thermochimica data file cannot be parsed. ", idbg);
145 }
146
147
149 Thermochimica::checkTemperature(tunit);
150 Thermochimica::setUnitTemperature(tunit);
151 int idbg = Thermochimica::checkInfoThermo();
152 if (idbg != 0)
153 paramError(
"tunit",
"Cannot set temperature unit in Thermochimica", idbg);
154
156 Thermochimica::checkPressure(punit);
157 Thermochimica::setUnitPressure(punit);
158 idbg = Thermochimica::checkInfoThermo();
159 if (idbg != 0)
160 paramError(
"punit",
"Cannot set pressure unit in Thermochimica", idbg);
161
163 std::replace(munit.begin(), munit.end(), '_', ' ');
164 Thermochimica::checkMass(munit);
165 Thermochimica::setUnitMass(munit);
166 idbg = Thermochimica::checkInfoThermo();
167 if (idbg != 0)
168 paramError(
"munit",
"Cannot set mass unit in Thermochimica", idbg);
169
170 _elements = getParam<std::vector<std::string>>(
"elements");
172 {
173 _elements.resize(Thermochimica::getNumberElementsDatabase());
174 _elements = Thermochimica::getElementsDatabase();
175 mooseInfo(
"Thermochimica elements: 'ALL' specified in input file. Using: ",
177 }
178 else
179 {
180 std::vector<std::string> db_elements(Thermochimica::getNumberElementsDatabase());
181 db_elements = Thermochimica::getElementsDatabase();
183 if (
std::
find(db_elements.begin(), db_elements.end(),
_elements[i]) == db_elements.end())
185 }
189
190
191
192
193
194 Thermochimica::setTemperaturePressure(1000.0, 1.0);
195 Thermochimica::setElementMass(0, 0.0);
196
198 Thermochimica::setElementMass(Thermochimica::atomicNumber(
_elements[i]), 1.0);
199
200 Thermochimica::setup();
201
203 {
204 _phases = getParam<std::vector<std::string>>(
"output_phases");
206 {
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: ",
212 }
213 else
214 {
215 auto db_phases = Thermochimica::getPhaseNamesSystem();
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.");
219 }
220 }
221
223 {
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();
229 if (Thermochimica::isPhaseMQM(i))
230 {
231 auto [pairs, quads, idbg] =
232 Thermochimica::getMqmqaNumberPairsQuads(Thermochimica::getPhaseNamesSystem()[i]);
233 n_db_species[i] = pairs;
234 }
235
236 if (species.size() == 1 && species[0] == "ALL")
237 {
238 if (!n_db_species.empty())
239 species.resize(n_db_species.back());
240 else
241 mooseInfo(
"ChemicalCompositionAction species: 'ALL' specified in input file. Thermochimica "
242 "returned no possible species.");
243
244 species.clear();
246 for (
const auto i :
make_range(db_species.size()))
248 {
249 species.push_back(db_phases[i] + ":" + db_species[i][j]);
251 }
252 mooseInfo(
"ChemicalCompositionAction species: 'ALL' specified in input file. Using: ",
254 }
255 else
257 {
259 std::vector<std::string> tokens;
261 if (tokens.size() == 1)
262 paramError(
"output_species",
"No ':' separator found in variable '", species[i],
"'");
263
264 auto phase_index = std::find(db_phases.begin(), db_phases.end(), tokens[0]);
265 if (phase_index == db_phases.end())
267 "Phase '",
268 tokens[0],
269 "' of output species '",
270 species[i],
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.");
277 }
278 }
279
281 {
282 auto element_potentials = getParam<std::vector<std::string>>("output_element_potentials");
283 if (element_potentials.size() == 1 && element_potentials[0] == "ALL")
284 {
287 element_potentials.resize(
_elements.size());
289 element_potentials[i] =
"mu:" +
_elements[i];
291 "ChemicalCompositionAction element potentials: 'ALL' specified in input file. Using: ",
293 }
294 else
295 {
297 for (
const auto i :
index_range(element_potentials))
298 {
299 std::vector<std::string> tokens;
301 if (tokens.size() == 1)
303 "No ':' separator found in variable '",
304 element_potentials[i],
305 "'");
308 "Element '",
309 tokens[1],
310 "' was not found in the simulation.");
312 }
313 }
314 }
315
317 {
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")
323 {
324 vapor_pressures.resize(Thermochimica::getNumberSpeciesSystem()[0]);
326 auto db_gas_species = Thermochimica::getSpeciesInPhase(0);
327 auto gas_name = Thermochimica::getPhaseNamesSystem()[0];
329 {
330 vapor_pressures[i] = "vp:" + gas_name + ':' + db_gas_species[i];
332 }
333 mooseInfo(
"ChemicalCompositionAction vapor pressures: 'ALL' specified in input file. Using: ",
335 }
336 else
337 {
338 auto db_gas_species = Thermochimica::getSpeciesInPhase(0);
341 {
342 std::vector<std::string> tokens;
344 if (tokens.size() == 1)
346 "No ':' separator found in variable '",
347 vapor_pressures[i],
348 "'");
349 if (tokens[1] != Thermochimica::getPhaseNamesSystem()[0])
351 "Phase '",
352 tokens[1],
353 "' of vapor species '",
354 vapor_pressures[i],
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())
359 "Species '",
360 tokens[2],
361 "' was not found in the gas phase of simulation.");
363 }
364 }
365 }
366
368 {
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")
372 {
373 element_phases.resize(
_elements.size() * db_phases.size());
377 {
380 std::make_pair(db_phases[i],
_elements[j]);
381 }
383 "ChemicalCompositionAction elements in phase: 'ALL' specified in input file. Using: ",
385 }
386 else
387 {
390 {
391 std::vector<std::string> tokens;
393 if (tokens.size() == 1)
395 "No ':' separator found in variable '",
396 element_phases[i],
397 "'");
398 if (std::find(db_phases.begin(), db_phases.end(), tokens[1]) == db_phases.end())
400 "Phase '",
401 tokens[1],
402 "' of '",
403 element_phases[i],
404 "' not found in the simulation.");
407 "Element '",
408 tokens[2],
409 "' was not found in the simulation.");
411 }
412 }
413 }
414
415 Thermochimica::resetThermoAll();
416
417#endif
418}
for(PetscInt i=0;i< nvars;++i)
std::vector< const T * > getActions()
MooseObjectName uniqueActionName() const
std::vector< unsigned int > _element_ids
Atomic numbers of the selected elements.
std::vector< std::string > _tokenized_element_potentials
std::vector< std::pair< std::string, std::string > > _tokenized_phase_elements
std::vector< std::pair< std::string, std::string > > _tokenized_species
Tokenized versions of the output variables to avoid redoing tokenization.
std::vector< std::string > _phases
List of phases tracked by Thermochimica.
std::vector< std::string > _elements
Element names.
std::vector< std::pair< std::string, std::string > > _tokenized_vapor_species
Store common ChemicalComposition action parameters.
InputParameterWarehouse & getInputParameterWarehouse()
const InputParameters & parameters() const
void paramError(const std::string ¶m, Args... args) const
void mooseInfo(Args &&... args) const
bool isParamValid(const std::string &name) const
void tokenize(const std::string &str, std::vector< T > &elements, unsigned int min_len=1, const std::string &delims="/")
KOKKOS_INLINE_FUNCTION const T * find(const T &target, const T *const begin, const T *const end)
std::string stringify(const T &t)
void checkLibraryAvailability(MooseObject &self)
Check if thermochimica is available and throw an error if it is not.
auto index_range(const T &sizable)
IntRange< T > make_range(T beg, T end)