LCOV - code coverage report
Current view: top level - src/userobjects - ThermochimicaData.C (source / functions) Hit Total Coverage
Test: idaholab/moose chemical_reactions: #31405 (292dce) with base fef103 Lines: 249 280 88.9 %
Date: 2025-09-04 07:52:33 Functions: 25 31 80.6 %
Legend: Lines: hit not hit

          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 "ThermochimicaData.h"
      11             : #include "ChemicalCompositionAction.h"
      12             : #include "ThermochimicaUtils.h"
      13             : #include "ActionWarehouse.h"
      14             : #include "libmesh/int_range.h"
      15             : 
      16             : #include <sys/mman.h>   // for mmap
      17             : #include <unistd.h>     // for fork
      18             : #include <sys/socket.h> // for socketpair
      19             : #include <csignal>      // for kill
      20             : 
      21             : #ifdef THERMOCHIMICA_ENABLED
      22             : #include "Thermochimica-cxx.h"
      23             : #include "checkUnits.h"
      24             : #endif
      25             : 
      26             : registerMooseObject("ChemicalReactionsApp", ThermochimicaNodalData);
      27             : registerMooseObject("ChemicalReactionsApp", ThermochimicaElementData);
      28             : 
      29             : template <bool is_nodal>
      30             : InputParameters
      31         451 : ThermochimicaDataBase<is_nodal>::validParams()
      32             : {
      33         451 :   InputParameters params = ThermochimicaDataBaseParent<is_nodal>::validParams();
      34             : 
      35             :   if constexpr (is_nodal)
      36         328 :     ThermochimicaUtils::addClassDescription(
      37             :         params, "Provides access to Thermochimica-calculated data at nodes.");
      38             :   else
      39         123 :     ThermochimicaUtils::addClassDescription(
      40             :         params, "Provides access to Thermochimica-calculated data at elements.");
      41             : 
      42         902 :   params.addRequiredCoupledVar("elements", "Amounts of elements");
      43         902 :   params.addRequiredCoupledVar("temperature", "Coupled temperature");
      44         902 :   params.addCoupledVar("pressure", 1.0, "Pressure");
      45             : 
      46         902 :   MooseEnum reinit_type("none time nodal", "nodal");
      47         902 :   params.addParam<MooseEnum>(
      48             :       "reinit_type", reinit_type, "Reinitialization scheme to use with Thermochimica");
      49             : 
      50         902 :   params.addCoupledVar("output_element_potentials", "Chemical potentials of elements");
      51         902 :   params.addCoupledVar("output_phases", "Amounts of phases to be output");
      52         902 :   params.addCoupledVar("output_species", "Amounts of species to be output");
      53         902 :   params.addCoupledVar("output_vapor_pressures", "Vapour pressures of species to be output");
      54         902 :   params.addCoupledVar("output_element_phases",
      55             :                        "Elements whose molar amounts in specific phases are requested");
      56             : 
      57         902 :   MooseEnum mUnit_op("mole_fraction moles", "moles");
      58         902 :   params.addParam<MooseEnum>(
      59             :       "output_species_unit", mUnit_op, "Mass unit for output species: mole_fractions or moles");
      60             : 
      61             :   if constexpr (is_nodal)
      62         328 :     params.set<bool>("unique_node_execute") = true;
      63             : 
      64         451 :   params.addPrivateParam<ChemicalCompositionAction *>("_chemical_composition_action");
      65         902 :   params.addParam<FileName>("thermofile",
      66             :                             "Thermodynamic file to be used for Thermochimica calculations");
      67         451 :   return params;
      68         451 : }
      69             : 
      70             : void
      71         242 : ThermochimicaDataBase_handler(int /*signum*/)
      72             : {
      73         242 :   exit(0);
      74             : }
      75             : 
      76             : template <bool is_nodal>
      77         242 : ThermochimicaDataBase<is_nodal>::ThermochimicaDataBase(const InputParameters & parameters)
      78             :   : ThermochimicaDataBaseParent<is_nodal>(parameters),
      79         242 :     _pressure(coupledValue("pressure")),
      80         242 :     _temperature(coupledValue("temperature")),
      81         242 :     _n_phases(coupledComponents("output_phases")),
      82         242 :     _n_species(coupledComponents("output_species")),
      83         242 :     _n_elements(coupledComponents("elements")),
      84         242 :     _n_vapor_species(coupledComponents("output_vapor_pressures")),
      85         242 :     _n_phase_elements(coupledComponents("output_element_phases")),
      86         242 :     _n_potentials(coupledComponents("output_element_potentials")),
      87         242 :     _el(_n_elements),
      88         242 :     _action(*parameters.getCheckedPointerParam<ChemicalCompositionAction *>(
      89             :         "_chemical_composition_action")),
      90         242 :     _el_ids(_action.elementIDs()),
      91         242 :     _reinit(parameters.get<MooseEnum>("reinit_type").getEnum<ReinitializationType>()),
      92         242 :     _ph_names(_action.phases()),
      93         242 :     _element_potentials(_action.elementPotentials()),
      94         242 :     _species_phase_pairs(_action.speciesPhasePairs()),
      95         242 :     _vapor_phase_pairs(_action.vaporPhasePairs()),
      96         242 :     _phase_element_pairs(_action.phaseElementPairs()),
      97         242 :     _output_element_potentials(isCoupled("output_element_potentials")),
      98         242 :     _output_vapor_pressures(isCoupled("output_vapor_pressures")),
      99         242 :     _output_element_phases(isCoupled("output_element_phases")),
     100         242 :     _ph(_n_phases),
     101         242 :     _sp(_n_species),
     102         242 :     _vp(_n_vapor_species),
     103         242 :     _el_pot(_n_potentials),
     104         242 :     _el_ph(_n_phase_elements),
     105         484 :     _output_mass_unit(parameters.get<MooseEnum>("output_species_unit").getEnum<OutputMassUnit>())
     106             : {
     107         242 :   ThermochimicaUtils::checkLibraryAvailability(*this);
     108             : 
     109         242 :   if (_el_ids.size() != _n_elements)
     110           0 :     mooseError("Element IDs size does not match number of elements.");
     111         880 :   for (const auto i : make_range(_n_elements))
     112         638 :     _el[i] = &coupledValue("elements", i);
     113             : 
     114         484 :   if (isParamValid("output_phases"))
     115             :   {
     116         242 :     if (_ph_names.size() != _n_phases)
     117           0 :       mooseError("Phase names vector size does not match number of phases.");
     118             : 
     119         968 :     for (const auto i : make_range(_n_phases))
     120         726 :       _ph[i] = &writableVariable("output_phases", i);
     121             :   }
     122             : 
     123         484 :   if (isParamValid("output_species"))
     124             :   {
     125         242 :     if (_species_phase_pairs.size() != _n_species)
     126           0 :       mooseError("Species name vector size does not match number of output species.");
     127             : 
     128        1606 :     for (const auto i : make_range(_n_species))
     129        1364 :       _sp[i] = &writableVariable("output_species", i);
     130             :   }
     131             : 
     132         484 :   if (isParamValid("output_vapor_pressures"))
     133             :   {
     134         242 :     if (_vapor_phase_pairs.size() != _n_vapor_species)
     135           0 :       mooseError("Vapor species name vector size does not match number of output vapor species.");
     136             : 
     137         528 :     for (const auto i : make_range(_n_vapor_species))
     138         286 :       _vp[i] = &writableVariable("output_vapor_pressures", i);
     139             :   }
     140             : 
     141         484 :   if (isParamValid("output_element_phases"))
     142             :   {
     143         242 :     if (_phase_element_pairs.size() != _n_phase_elements)
     144           0 :       mooseError("Element phase vector size does not match number of output elements in phases");
     145             : 
     146        1430 :     for (const auto i : make_range(_n_phase_elements))
     147        1188 :       _el_ph[i] = &writableVariable("output_element_phases", i);
     148             :   }
     149             : 
     150         484 :   if (isParamValid("output_element_potentials"))
     151             :   {
     152         242 :     if (_element_potentials.size() != _n_potentials)
     153           0 :       mooseError("Element potentials vector size does not match number of element potentials "
     154             :                  "specified for output.");
     155             : 
     156         704 :     for (const auto i : make_range(_n_potentials))
     157         462 :       _el_pot[i] = &writableVariable("output_element_potentials", i);
     158             :   }
     159             :   // buffer size
     160             :   const auto dofid_size = std::max(/* send */ 1, /* receive */ 0);
     161         242 :   const auto real_size =
     162         484 :       std::max(/* send */ 2 + _n_elements,
     163         242 :                /* receive */ _n_phases + _n_species + _element_potentials.size() +
     164         242 :                    _n_vapor_species + _n_phase_elements);
     165             : 
     166             :   // set up shared memory for communication with child process
     167             :   auto shared_mem =
     168         242 :       static_cast<std::byte *>(mmap(nullptr,
     169         242 :                                     dofid_size * sizeof(dof_id_type) + real_size * sizeof(Real),
     170             :                                     PROT_READ | PROT_WRITE,
     171             :                                     MAP_ANONYMOUS | MAP_SHARED,
     172             :                                     -1 /* fd */,
     173             :                                     0 /* offset */));
     174         242 :   if (shared_mem == MAP_FAILED)
     175           0 :     mooseError("Failed to allocate shared memory for thermochimica IPC.");
     176             : 
     177             :   // set up buffer partitions
     178         242 :   _shared_dofid_mem = reinterpret_cast<dof_id_type *>(shared_mem);
     179         242 :   _shared_real_mem = reinterpret_cast<Real *>(shared_mem + dofid_size * sizeof(dof_id_type));
     180             : 
     181             :   // set up a bidirectional communication socket
     182             :   int sockets[2];
     183         242 :   if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) < 0)
     184           0 :     mooseError("Failed to create socketpair for thermochimica IPC.");
     185             : 
     186             :   // fork child process that will manage thermochimica calls
     187         242 :   _pid = fork();
     188         484 :   if (_pid < 0)
     189           0 :     mooseError("Fork failed for thermochimica library.");
     190         484 :   if (_pid == 0)
     191             :   {
     192             :     // here we are in the child process
     193         242 :     _socket = sockets[0];
     194             :     // clean exit upon SIGTERM (mainly for Civet code coverage)
     195         242 :     signal(SIGTERM, ThermochimicaDataBase_handler);
     196             : 
     197             : #ifdef THERMOCHIMICA_ENABLED
     198             :     // Initialize database in Thermochimica
     199         484 :     if (isParamValid("thermofile"))
     200             :     {
     201         484 :       const auto thermo_file = this->template getParam<FileName>("thermofile");
     202             : 
     203         242 :       if (thermo_file.length() > 1024)
     204           0 :         this->paramError("thermofile",
     205             :                          "Path exceeds Thermochimica's maximal permissible length of 1024 with ",
     206             :                          thermo_file.length(),
     207             :                          " characters: ",
     208             :                          thermo_file);
     209             : 
     210         242 :       Thermochimica::setThermoFilename(thermo_file);
     211             : 
     212             :       // Read in thermodynamics model, only once
     213         242 :       Thermochimica::parseThermoFile();
     214             : 
     215         242 :       const auto idbg = Thermochimica::checkInfoThermo();
     216         242 :       if (idbg != 0)
     217           0 :         this->paramError("thermofile", "Thermochimica data file cannot be parsed. ", idbg);
     218             :     }
     219             : #endif
     220             : 
     221             :     while (true)
     222        3104 :       server();
     223             :   }
     224             : 
     225             :   // parent process continues here
     226         242 :   _socket = sockets[1];
     227         242 : }
     228             : 
     229             : template <bool is_nodal>
     230         484 : ThermochimicaDataBase<is_nodal>::~ThermochimicaDataBase()
     231             : {
     232         242 :   if (_pid)
     233         242 :     kill(_pid, SIGTERM);
     234         968 : }
     235             : 
     236             : template <bool is_nodal>
     237             : void
     238         374 : ThermochimicaDataBase<is_nodal>::initialize()
     239             : {
     240         374 : }
     241             : 
     242             : template <bool is_nodal>
     243             : template <typename T>
     244             : void
     245        5966 : ThermochimicaDataBase<is_nodal>::expect(T expect_msg)
     246             : {
     247             :   T msg;
     248        5966 :   while (read(_socket, &msg, sizeof(T)) == 0)
     249             :   {
     250           0 :     if (errno == EAGAIN)
     251           0 :       continue;
     252           0 :     mooseError("Read error waiting for '", expect_msg, "' ", errno, ' ', strerror(errno));
     253             :   }
     254        5724 :   if (msg != expect_msg)
     255           0 :     mooseError("Expected '", expect_msg, "' but received '", msg, "'");
     256        5724 : }
     257             : 
     258             : template <bool is_nodal>
     259             : template <typename T>
     260             : void
     261        5724 : ThermochimicaDataBase<is_nodal>::notify(T send_msg)
     262             : {
     263        5724 :   if (write(_socket, &send_msg, sizeof(T)) != sizeof(T))
     264           0 :     mooseError("Failed to notify thermochimica library child process.");
     265        5724 : }
     266             : 
     267             : template <bool is_nodal>
     268             : void
     269        2862 : ThermochimicaDataBase<is_nodal>::execute()
     270             : {
     271             :   // either one DOF at a node or (currently) one DOF for constant monomial FV!
     272             :   // This is enforced automatically by the ChemicalComposition action, which creates the correct
     273             :   // variables.
     274             :   const unsigned int qp = 0;
     275             : 
     276             :   // store current dofID
     277             :   if constexpr (is_nodal)
     278        2052 :     _shared_dofid_mem[0] = this->_current_node->id();
     279             :   else
     280         810 :     _shared_dofid_mem[0] = this->_current_elem->id();
     281             : 
     282             :   // store all required data in shared memory
     283        2862 :   _shared_real_mem[0] = _temperature[qp];
     284        2862 :   _shared_real_mem[1] = _pressure[qp];
     285        9594 :   for (const auto i : make_range(_n_elements))
     286        6732 :     _shared_real_mem[2 + i] = (*_el[i])[qp];
     287             : 
     288             :   // message child process to trigger calculation
     289        2862 :   notify('A');
     290             : 
     291             :   // and wait for the child process to signal end of calculation
     292        2862 :   expect('B');
     293             : 
     294             :   // unpack data from shared memory
     295             :   std::size_t idx = 0;
     296             : 
     297        9252 :   for (const auto i : make_range(_n_phases))
     298        6390 :     _ph[i]->setDofValue(_shared_real_mem[idx++], qp);
     299             : 
     300       12240 :   for (const auto i : make_range(_n_species))
     301        9378 :     _sp[i]->setDofValue(_shared_real_mem[idx++], qp);
     302             : 
     303        2862 :   if (_output_element_potentials)
     304        5760 :     for (const auto i : index_range(_element_potentials))
     305        3996 :       _el_pot[i]->setDofValue(_shared_real_mem[idx++], qp);
     306             : 
     307        2862 :   if (_output_vapor_pressures)
     308        3816 :     for (const auto i : make_range(_n_vapor_species))
     309        2052 :       _vp[i]->setDofValue(_shared_real_mem[idx++], qp);
     310             : 
     311        2862 :   if (_output_element_phases)
     312        6120 :     for (const auto i : make_range(_n_phase_elements))
     313        4752 :       _el_ph[i]->setDofValue(_shared_real_mem[idx++], qp);
     314        2862 : }
     315             : 
     316             : template <bool is_nodal>
     317             : void
     318        3104 : ThermochimicaDataBase<is_nodal>::server()
     319             : {
     320             :   // wait for message from parent process
     321        3104 :   expect('A');
     322             : 
     323             : #ifdef THERMOCHIMICA_ENABLED
     324             :   // fetch data from shared memory
     325        2862 :   _current_id = _shared_dofid_mem[0];
     326             : 
     327        2862 :   auto temperature = _shared_real_mem[0];
     328        2862 :   auto pressure = _shared_real_mem[1];
     329             : 
     330             :   // Set temperature and pressure for thermochemistry solver
     331        2862 :   Thermochimica::setTemperaturePressure(temperature, pressure);
     332             : 
     333             :   // Reset all element masses to 0
     334        2862 :   Thermochimica::setElementMass(0, 0.0);
     335             : 
     336             :   // Set element masses
     337        9594 :   for (const auto i : make_range(_n_elements))
     338        6732 :     Thermochimica::setElementMass(_el_ids[i], _shared_real_mem[2 + i]);
     339             : 
     340             :   // Optionally ask for a re-initialization (if reinit_requested == true)
     341        2862 :   reinitDataMooseToTc();
     342             : 
     343             :   // Calculate thermochemical equilibrium
     344        2862 :   Thermochimica::thermochimica();
     345             : 
     346             :   // Check for error status
     347        2862 :   auto idbg = Thermochimica::checkInfoThermo();
     348        2862 :   if (idbg != 0)
     349             :     // error out for now, but we should send a code to the parent process
     350           0 :     mooseError("Thermochimica error ", idbg);
     351             : 
     352             :   // Save data for future reinits
     353        2862 :   reinitDataMooseFromTc();
     354             : 
     355             :   // Get requested phase indices if phase concentration output was requested
     356             :   // i.e. if output_phases is coupled
     357        2862 :   auto moles_phase = Thermochimica::getMolesPhase();
     358             : 
     359             :   std::size_t idx = 0;
     360             : 
     361        9252 :   for (const auto i : make_range(_n_phases))
     362             :   {
     363             :     // Is this maybe constant? No it isn't for now
     364        6390 :     auto [index, idbg] = Thermochimica::getPhaseIndex(_ph_names[i]);
     365        6390 :     if (idbg != 0)
     366           0 :       mooseError("Failed to get index of phase '", _ph_names[i], "'");
     367             :     // Convert from 1-based (fortran) to 0-based (c++) indexing
     368        6390 :     if (index - 1 < 0)
     369        2772 :       _shared_real_mem[idx] = 0.0;
     370             :     else
     371        3618 :       _shared_real_mem[idx] = moles_phase[index - 1];
     372        6390 :     idx++;
     373             :   }
     374             : 
     375        2862 :   auto db_phases = Thermochimica::getPhaseNamesSystem();
     376        2862 :   auto getSpeciesMoles =
     377       12240 :       [this, moles_phase, db_phases](const std::string phase,
     378             :                                      const std::string species) -> std::pair<double, int>
     379             :   {
     380             :     Real value = 0.0;
     381             :     int code = 0;
     382             : 
     383        9378 :     auto [index, idbg] = Thermochimica::getPhaseIndex(phase);
     384             : 
     385        9378 :     if (Thermochimica::isPhaseMQM(
     386        9378 :             std::distance(db_phases.begin(), std::find(db_phases.begin(), db_phases.end(), phase))))
     387             :     {
     388         846 :       auto [fraction, idbg] = Thermochimica::getMqmqaPairMolFraction(phase, species);
     389             : 
     390         846 :       switch (_output_mass_unit)
     391             :       {
     392           0 :         case OutputMassUnit::FRACTION:
     393             :         {
     394             :           value = fraction;
     395             :           code = idbg;
     396           0 :           break;
     397             :         }
     398         846 :         case OutputMassUnit::MOLES:
     399             :         {
     400         846 :           auto [molesPair, idbgPair] = Thermochimica::getMqmqaMolesPairs(phase);
     401         846 :           value = molesPair * fraction;
     402         846 :           code = idbg + idbgPair;
     403             :           break;
     404             :         }
     405             :         default:
     406             :           break;
     407             :       }
     408             :     }
     409             :     else
     410             :     {
     411        8532 :       auto [fraction, idbg] = Thermochimica::getOutputMolSpeciesPhase(phase, species);
     412        8532 :       switch (_output_mass_unit)
     413             :       {
     414        5328 :         case OutputMassUnit::FRACTION:
     415             :         {
     416             :           value = fraction;
     417             :           code = idbg;
     418        5328 :           break;
     419             :         }
     420        3204 :         case OutputMassUnit::MOLES:
     421             :         {
     422        3204 :           value = index >= 1 ? moles_phase[index - 1] * fraction : 0.0;
     423             :           code = idbg;
     424             :           break;
     425             :         }
     426             :         default:
     427             :           break;
     428             :       }
     429             :     }
     430        9378 :     return {value, code};
     431             :   };
     432             : 
     433       12240 :   for (const auto i : make_range(_n_species))
     434             :   {
     435        9378 :     auto [fraction, idbg] = getSpeciesMoles(
     436        9378 :         _species_phase_pairs[i].first,
     437        9378 :         _species_phase_pairs[i].second); // can we somehow use IDs instead of strings here?
     438             : 
     439        9378 :     if (idbg == 0)
     440        4302 :       _shared_real_mem[idx] = fraction;
     441        5076 :     else if (idbg == 1)
     442        5076 :       _shared_real_mem[idx] = 0.0;
     443             : #ifndef NDEBUG
     444             :     else
     445             :       mooseError("Failed to get phase speciation for phase '",
     446             :                  _species_phase_pairs[i].first,
     447             :                  "' and species '",
     448             :                  _species_phase_pairs[i].second,
     449             :                  "'. Thermochimica returned ",
     450             :                  idbg);
     451             : #endif
     452        9378 :     idx++;
     453             :   }
     454             : 
     455        2862 :   if (_output_element_potentials)
     456        5760 :     for (const auto i : index_range(_element_potentials))
     457             :     {
     458        3996 :       auto [potential, idbg] = Thermochimica::getOutputChemPot(_element_potentials[i]);
     459        3996 :       if (idbg == 0)
     460        3960 :         _shared_real_mem[idx] = potential;
     461          36 :       else if (idbg == 1)
     462             :         // element not present, just leave this at 0 for now
     463          36 :         _shared_real_mem[idx] = 0.0;
     464             : #ifndef NDEBUG
     465             :       else if (idbg == -1)
     466             :         mooseError("Failed to get element potential for element '",
     467             :                    _element_potentials[i],
     468             :                    "'. Thermochimica returned ",
     469             :                    idbg);
     470             : #endif
     471        3996 :       idx++;
     472             :     }
     473             : 
     474        2862 :   if (_output_vapor_pressures)
     475        3816 :     for (const auto i : make_range(_n_vapor_species))
     476             :     {
     477        2052 :       auto [fraction, moles, idbg] =
     478        2052 :           Thermochimica::getOutputMolSpecies(_vapor_phase_pairs[i].second);
     479             :       libmesh_ignore(moles);
     480             : 
     481        2052 :       if (idbg == 0)
     482        2016 :         _shared_real_mem[idx] = fraction * pressure;
     483          36 :       else if (idbg == 1)
     484          36 :         _shared_real_mem[idx] = 0.0;
     485             : #ifndef NDEBUG
     486             :       else
     487             :         mooseError("Failed to get vapor pressure for phase '",
     488             :                    _vapor_phase_pairs[i].first,
     489             :                    "' and species '",
     490             :                    _vapor_phase_pairs[i].second,
     491             :                    "'. Thermochimica returned ",
     492             :                    idbg);
     493             : #endif
     494        2052 :       idx++;
     495             :     }
     496             : 
     497        2862 :   if (_output_element_phases)
     498        6120 :     for (const auto i : make_range(_n_phase_elements))
     499             :     {
     500        4752 :       auto [moles, idbg] = Thermochimica::getElementMolesInPhase(_phase_element_pairs[i].second,
     501        4752 :                                                                  _phase_element_pairs[i].first);
     502             : 
     503        4752 :       if (idbg == 0)
     504        4716 :         _shared_real_mem[idx] = moles;
     505          36 :       else if (idbg == 1)
     506          36 :         _shared_real_mem[idx] = 0.0;
     507             : #ifndef NDEBUG
     508             :       else
     509             :         mooseError("Failed to get moles of element '",
     510             :                    _phase_element_pairs[i].second,
     511             :                    "' in phase '",
     512             :                    _phase_element_pairs[i].first,
     513             :                    "'. Thermochimica returned ",
     514             :                    idbg);
     515             : #endif
     516        4752 :       idx++;
     517             :     }
     518             : #endif
     519             :   // Send message back to parent process
     520        2862 :   notify('B');
     521        2862 : }
     522             : 
     523             : template <bool is_nodal>
     524             : void
     525        2862 : ThermochimicaDataBase<is_nodal>::reinitDataMooseFromTc()
     526             : {
     527             : #ifdef THERMOCHIMICA_ENABLED
     528        2862 :   auto & d = _data[_current_id];
     529             : 
     530        2862 :   if (_reinit != ReinitializationType::NONE)
     531             :   {
     532        2466 :     Thermochimica::saveReinitData();
     533        2466 :     auto data = Thermochimica::getReinitData();
     534             : 
     535        2466 :     if (_reinit == ReinitializationType::TIME)
     536             :     {
     537         576 :       d._assemblage = std::move(data.assemblage);
     538         576 :       d._moles_phase = std::move(data.molesPhase);
     539         576 :       d._element_potential = std::move(data.elementPotential);
     540         576 :       d._chemical_potential = std::move(data.chemicalPotential);
     541         576 :       d._mol_fraction = std::move(data.moleFraction);
     542         576 :       d._elements_used = std::move(data.elementsUsed);
     543         576 :       d._reinit_available = data.reinitAvailable;
     544             :     }
     545        2466 :   }
     546             : #endif
     547        2862 : }
     548             : 
     549             : template <bool is_nodal>
     550             : void
     551        2862 : ThermochimicaDataBase<is_nodal>::reinitDataMooseToTc()
     552             : {
     553             : #ifdef THERMOCHIMICA_ENABLED
     554             :   // Tell Thermochimica whether a re-initialization is requested for this calculation
     555        2862 :   switch (_reinit)
     556             :   {
     557         396 :     case ReinitializationType::NONE:
     558         396 :       Thermochimica::setReinitRequested(false);
     559             :       break;
     560        2466 :     default:
     561        2466 :       Thermochimica::setReinitRequested(true);
     562             :   }
     563             :   // If we have re-initialization data and want a re-initialization, then
     564             :   // load data into Thermochimica
     565        2862 :   auto it = _data.find(_current_id);
     566             : 
     567        2862 :   if (it != _data.end() &&
     568        1431 :       _reinit == ReinitializationType::TIME) // If doing previous timestep reinit
     569             :   {
     570             :     auto & d = it->second;
     571         288 :     if (d._reinit_available)
     572             :     {
     573         288 :       Thermochimica::resetReinit();
     574         288 :       Thermochimica::ReinitializationData data;
     575         288 :       data.assemblage = d._assemblage;
     576         288 :       data.molesPhase = d._moles_phase;
     577         288 :       data.elementPotential = d._element_potential;
     578         288 :       data.chemicalPotential = d._chemical_potential;
     579         288 :       data.moleFraction = d._mol_fraction;
     580         288 :       data.elementsUsed = d._elements_used;
     581         288 :       Thermochimica::setReinitData(data);
     582         288 :     }
     583             :   }
     584             : #endif
     585        2862 : }
     586             : 
     587             : template <bool is_nodal>
     588             : const typename ThermochimicaDataBase<is_nodal>::Data &
     589           0 : ThermochimicaDataBase<is_nodal>::getNodalData(dof_id_type node_id) const
     590             : {
     591             :   if constexpr (!is_nodal)
     592           0 :     mooseError("Requesting nodal data from an element object.");
     593           0 :   return this->getData(node_id);
     594             : }
     595             : 
     596             : template <bool is_nodal>
     597             : const typename ThermochimicaDataBase<is_nodal>::Data &
     598           0 : ThermochimicaDataBase<is_nodal>::getElementData(dof_id_type element_id) const
     599             : {
     600             :   if constexpr (is_nodal)
     601           0 :     mooseError("Requesting per element data from a nodal object.");
     602           0 :   return this->getData(element_id);
     603             : }
     604             : 
     605             : template <bool is_nodal>
     606             : const typename ThermochimicaDataBase<is_nodal>::Data &
     607           0 : ThermochimicaDataBase<is_nodal>::getData(dof_id_type id) const
     608             : {
     609             :   const auto it = _data.find(id);
     610           0 :   if (it == _data.end())
     611             :   {
     612             :     if constexpr (is_nodal)
     613           0 :       mooseError("Unable to look up data for node ", id);
     614             :     else
     615           0 :       mooseError("Unable to look up data for element ", id);
     616             :   }
     617           0 :   return it->second;
     618             : }
     619             : 
     620             : template class ThermochimicaDataBase<true>;
     621             : template class ThermochimicaDataBase<false>;

Generated by: LCOV version 1.14