LCOV - code coverage report
Current view: top level - src/actions - AddCoupledSolidKinSpeciesAction.C (source / functions) Hit Total Coverage
Test: idaholab/moose chemical_reactions: #31405 (292dce) with base fef103 Lines: 100 110 90.9 %
Date: 2025-09-04 07:52:33 Functions: 3 3 100.0 %
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 "AddCoupledSolidKinSpeciesAction.h"
      11             : #include "MooseUtils.h"
      12             : #include "FEProblem.h"
      13             : #include "Factory.h"
      14             : #include "MooseError.h"
      15             : #include "Parser.h"
      16             : #include <algorithm>
      17             : 
      18             : // Regular expression includes
      19             : #include "pcrecpp.h"
      20             : 
      21             : registerMooseAction("ChemicalReactionsApp", AddCoupledSolidKinSpeciesAction, "add_kernel");
      22             : 
      23             : registerMooseAction("ChemicalReactionsApp", AddCoupledSolidKinSpeciesAction, "add_aux_kernel");
      24             : 
      25             : InputParameters
      26          83 : AddCoupledSolidKinSpeciesAction::validParams()
      27             : {
      28          83 :   InputParameters params = Action::validParams();
      29         166 :   params.addRequiredParam<std::vector<NonlinearVariableName>>("primary_species",
      30             :                                                               "The list of primary species to add");
      31         166 :   params.addParam<std::vector<AuxVariableName>>(
      32             :       "secondary_species", "The list of solid kinetic species to be output as aux variables");
      33         166 :   params.addRequiredParam<std::string>("kin_reactions", "The list of solid kinetic reactions");
      34         166 :   params.addRequiredParam<std::vector<Real>>("log10_keq",
      35             :                                              "The list of equilibrium constants for all reactions");
      36         166 :   params.addRequiredParam<std::vector<Real>>(
      37             :       "specific_reactive_surface_area",
      38             :       "The list of specific reactive surface area for all minerals (m^2/L)");
      39         166 :   params.addRequiredParam<std::vector<Real>>(
      40             :       "kinetic_rate_constant", "The list of kinetic rate constant for all reactions (mol/m^2/s)");
      41         166 :   params.addRequiredParam<std::vector<Real>>(
      42             :       "activation_energy", "The list of activation energy values for all reactions (J/mol)");
      43         166 :   params.addParam<Real>("gas_constant", 8.314, "Gas constant. Default is 8.314 (J/mol/K)");
      44         166 :   params.addRequiredParam<std::vector<Real>>(
      45             :       "reference_temperature", "The list of reference temperatures for all reactions (K)");
      46         166 :   params.addRequiredCoupledVar("system_temperature",
      47             :                                "The system temperature for all reactions (K)");
      48          83 :   params.addClassDescription("Adds solid kinetic Kernels and AuxKernels for primary species");
      49          83 :   return params;
      50           0 : }
      51             : 
      52          83 : AddCoupledSolidKinSpeciesAction::AddCoupledSolidKinSpeciesAction(const InputParameters & params)
      53             :   : Action(params),
      54          83 :     _primary_species(getParam<std::vector<NonlinearVariableName>>("primary_species")),
      55         249 :     _secondary_species(getParam<std::vector<AuxVariableName>>("secondary_species")),
      56          83 :     _kinetic_species_involved(_primary_species.size()),
      57          83 :     _weights(_primary_species.size()),
      58         249 :     _input_reactions(getParam<std::string>("kin_reactions")),
      59         166 :     _logk(getParam<std::vector<Real>>("log10_keq")),
      60         166 :     _r_area(getParam<std::vector<Real>>("specific_reactive_surface_area")),
      61         166 :     _ref_kconst(getParam<std::vector<Real>>("kinetic_rate_constant")),
      62         166 :     _e_act(getParam<std::vector<Real>>("activation_energy")),
      63         166 :     _gas_const(getParam<Real>("gas_constant")),
      64         166 :     _ref_temp(getParam<std::vector<Real>>("reference_temperature")),
      65         332 :     _sys_temp(getParam<std::vector<VariableName>>("system_temperature"))
      66             : {
      67             :   // Note: as the reaction syntax has changed, check to see if the old syntax has
      68             :   // been used and throw an informative error. The number of = signs should be one
      69             :   // more than the number of commas, while the smallest number of spaces possible is 2
      70             :   bool old_syntax = false;
      71          83 :   if (std::count(_input_reactions.begin(), _input_reactions.end(), '=') !=
      72          83 :       std::count(_input_reactions.begin(), _input_reactions.end(), ',') + 1)
      73             :     old_syntax = true;
      74             : 
      75          83 :   if (std::count(_input_reactions.begin(), _input_reactions.end(), ' ') < 2)
      76             :     old_syntax = true;
      77             : 
      78          83 :   if (old_syntax)
      79           0 :     mooseError("Old solid kinetic reaction syntax present.\nReactions should now be comma "
      80             :                "separated, and must have spaces between species and +/-/= operators.\n"
      81             :                "See #9972 for details");
      82             : 
      83             :   // Parse the kinetic reactions
      84             :   pcrecpp::RE re_reactions("(.+?)" // A single reaction (any character until the comma delimiter)
      85             :                            "(?:,\\s*|$)" // comma or end of string
      86             :                            ,
      87          83 :                            pcrecpp::RE_Options().set_extended(true));
      88             : 
      89          83 :   pcrecpp::RE re_terms("(\\S+)");
      90             :   pcrecpp::RE re_coeff_and_species("(?: \\(? (.*?) \\)? )" // match the leading coefficent
      91             :                                    "([A-Za-z].*)"          // match the species
      92             :                                    ,
      93          83 :                                    pcrecpp::RE_Options().set_extended(true));
      94             : 
      95             :   pcrecpp::StringPiece input(_input_reactions);
      96             :   pcrecpp::StringPiece single_reaction, term;
      97             :   std::string single_reaction_str;
      98             : 
      99             :   // Parse reaction network to extract each individual reaction
     100         204 :   while (re_reactions.FindAndConsume(&input, &single_reaction_str))
     101         121 :     _reactions.push_back(single_reaction_str);
     102             : 
     103          83 :   _num_reactions = _reactions.size();
     104             : 
     105          83 :   if (_num_reactions == 0)
     106           0 :     mooseError("No solid kinetic reaction provided!");
     107             : 
     108             :   // Start parsing each reaction
     109         204 :   for (unsigned int i = 0; i < _num_reactions; ++i)
     110             :   {
     111         121 :     single_reaction = _reactions[i];
     112             : 
     113             :     // Capture all of the terms
     114             :     std::string species, coeff_str;
     115             :     Real coeff;
     116             :     int sign = 1;
     117             :     bool secondary = false;
     118             : 
     119             :     std::vector<Real> local_stos;
     120             :     std::vector<VariableName> local_species_list;
     121             : 
     122             :     // Find every single term in this reaction (species and operators)
     123         830 :     while (re_terms.FindAndConsume(&single_reaction, &term))
     124             :     {
     125             :       // Separating the stoichiometric coefficients from species
     126         709 :       if (re_coeff_and_species.PartialMatch(term, &coeff_str, &species))
     127             :       {
     128         415 :         if (coeff_str.length())
     129          95 :           coeff = std::stod(coeff_str);
     130             :         else
     131         320 :           coeff = 1.0;
     132             : 
     133         415 :         coeff *= sign;
     134             : 
     135         415 :         if (secondary)
     136         242 :           _solid_kinetic_species.push_back(species);
     137             :         else
     138             :         {
     139         294 :           local_stos.push_back(coeff);
     140         294 :           local_species_list.push_back(species);
     141             :         }
     142             :       }
     143             :       // Finding the operators and assign value of -1.0 to "-" sign
     144         294 :       else if (term == "+" || term == "=" || term == "-")
     145             :       {
     146         294 :         if (term == "-")
     147             :         {
     148             :           sign = -1;
     149          71 :           term = "+";
     150             :         }
     151             : 
     152         294 :         if (term == "=")
     153             :           secondary = true;
     154             :       }
     155             :       else
     156           0 :         mooseError("Error parsing term: ", term.as_string());
     157             :     }
     158             : 
     159         121 :     _stos.push_back(local_stos);
     160         121 :     _primary_species_involved.push_back(local_species_list);
     161         121 :   }
     162             : 
     163             :   // Start picking out primary species and coupled primary species and assigning
     164             :   // corresponding stoichiomentric coefficients
     165         339 :   for (unsigned int i = 0; i < _primary_species.size(); ++i)
     166         664 :     for (unsigned int j = 0; j < _num_reactions; ++j)
     167             :     {
     168        1380 :       for (unsigned int k = 0; k < _primary_species_involved[j].size(); ++k)
     169         972 :         if (_primary_species_involved[j][k] == _primary_species[i])
     170             :         {
     171         294 :           _weights[i].push_back(_stos[j][k]);
     172         294 :           _kinetic_species_involved[i].push_back(_solid_kinetic_species[j]);
     173             :         }
     174             :     }
     175             : 
     176             :   // Print out details of the solid kinetic reactions to the console
     177          83 :   _console << "Solid kinetic reactions:\n";
     178         204 :   for (unsigned int i = 0; i < _num_reactions; ++i)
     179         121 :     _console << "  Reaction " << i + 1 << ": " << _reactions[i] << "\n";
     180          83 :   _console << std::endl;
     181             : 
     182             :   // Check that all secondary species read from the reaction network have been added
     183             :   // as AuxVariables. Note: can't sort the _solid_kinetic_species vector as it throws
     184             :   // out the species and coefficient vectors so use std::is_permutation
     185          83 :   if (!std::is_permutation(
     186             :           _secondary_species.begin(), _secondary_species.end(), _solid_kinetic_species.begin()))
     187           0 :     mooseError("All solid kinetic species must be added as secondary species");
     188             : 
     189             :   // Check that the size of property vectors is equal to the number of reactions
     190          83 :   if (_logk.size() != _num_reactions)
     191           0 :     mooseError("The number of values entered for log10_keq is not equal to the number of solid "
     192             :                "kinetic reactions");
     193          83 :   if (_r_area.size() != _num_reactions)
     194           0 :     mooseError("The number of values entered for specific_reactive_surface_area is not equal to "
     195             :                "the number of solid kinetic reactions");
     196          83 :   if (_ref_kconst.size() != _num_reactions)
     197           0 :     mooseError("The number of values entered for kinetic_rate_constant is not equal to the number "
     198             :                "of solid kinetic reactions");
     199          83 :   if (_e_act.size() != _num_reactions)
     200           0 :     mooseError("The number of values entered for activation_energy is not equal to the number of "
     201             :                "solid kinetic reactions");
     202          83 :   if (_ref_temp.size() != _num_reactions)
     203           0 :     mooseError("The number of values entered for reference_temperature is not equal to the number "
     204             :                "of solid kinetic reactions");
     205          83 : }
     206             : 
     207             : void
     208         166 : AddCoupledSolidKinSpeciesAction::act()
     209             : {
     210         166 :   if (_current_task == "add_kernel")
     211             :   {
     212             :     // Add Kernels for each primary species
     213         339 :     for (unsigned int i = 0; i < _primary_species.size(); ++i)
     214             :     {
     215         512 :       InputParameters params_kin = _factory.getValidParams("CoupledBEKinetic");
     216         512 :       params_kin.set<NonlinearVariableName>("variable") = _primary_species[i];
     217         512 :       params_kin.set<std::vector<Real>>("weight") = _weights[i];
     218         256 :       params_kin.set<std::vector<VariableName>>("v") = _kinetic_species_involved[i];
     219         768 :       _problem->addKernel("CoupledBEKinetic", _primary_species[i] + "_" + "_kin", params_kin);
     220         256 :     }
     221             :   }
     222             : 
     223         166 :   if (_current_task == "add_aux_kernel")
     224             :   {
     225             :     // Add AuxKernels for each solid kinetic species
     226         204 :     for (unsigned int i = 0; i < _num_reactions; ++i)
     227             :     {
     228         121 :       InputParameters params_kin = _factory.getValidParams("KineticDisPreConcAux");
     229         242 :       params_kin.set<AuxVariableName>("variable") = _solid_kinetic_species[i];
     230         242 :       params_kin.defaultCoupledValue("log_k", _logk[i]);
     231         121 :       params_kin.set<Real>("r_area") = _r_area[i];
     232         121 :       params_kin.set<Real>("ref_kconst") = _ref_kconst[i];
     233         121 :       params_kin.set<Real>("e_act") = _e_act[i];
     234         121 :       params_kin.set<Real>("gas_const") = _gas_const;
     235         121 :       params_kin.set<Real>("ref_temp") = _ref_temp[i];
     236         242 :       params_kin.set<std::vector<VariableName>>("sys_temp") = _sys_temp;
     237         242 :       params_kin.set<std::vector<Real>>("sto_v") = _stos[i];
     238         121 :       params_kin.set<std::vector<VariableName>>("v") = _primary_species_involved[i];
     239         242 :       _problem->addAuxKernel(
     240         121 :           "KineticDisPreConcAux", "aux_" + _solid_kinetic_species[i], params_kin);
     241         121 :     }
     242             :   }
     243         166 : }

Generated by: LCOV version 1.14