LCOV - code coverage report
Current view: top level - src/physics - MultiSpeciesDiffusionCG.C (source / functions) Hit Total Coverage
Test: idaholab/moose scalar_transport: #32971 (54bef8) with base c6cf66 Lines: 126 135 93.3 %
Date: 2026-05-29 20:39:31 Functions: 5 5 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 "MultiSpeciesDiffusionCG.h"
      11             : #include "MooseVariableBase.h"
      12             : 
      13             : // Register the actions for the objects actually used
      14             : registerMooseAction("ScalarTransportApp", MultiSpeciesDiffusionCG, "add_kernel");
      15             : registerMooseAction("ScalarTransportApp", MultiSpeciesDiffusionCG, "add_bc");
      16             : registerMooseAction("ScalarTransportApp", MultiSpeciesDiffusionCG, "add_variable");
      17             : registerMultiSpeciesDiffusionPhysicsBaseTasks("ScalarTransportApp", MultiSpeciesDiffusionCG);
      18             : 
      19             : InputParameters
      20          54 : MultiSpeciesDiffusionCG::validParams()
      21             : {
      22          54 :   InputParameters params = MultiSpeciesDiffusionPhysicsBase::validParams();
      23          54 :   params.addClassDescription("Discretizes diffusion equations for several species with the "
      24             :                              "continuous Galerkin finite element method");
      25          54 :   params.transferParam<MooseEnum>(MooseVariableBase::validParams(), "order", "variable_order");
      26             : 
      27          54 :   return params;
      28           0 : }
      29             : 
      30          54 : MultiSpeciesDiffusionCG::MultiSpeciesDiffusionCG(const InputParameters & parameters)
      31          54 :   : MultiSpeciesDiffusionPhysicsBase(parameters)
      32             : {
      33          54 : }
      34             : 
      35             : void
      36          54 : MultiSpeciesDiffusionCG::addFEKernels()
      37             : {
      38         216 :   for (const auto s : index_range(_species_names))
      39             :   {
      40         162 :     const auto & var_name = _species_names[s];
      41             :     // Diffusion term
      42         378 :     if (isParamValid("diffusivity_matprops") || isParamValid("diffusivity_functors"))
      43             :     {
      44             :       // Select the kernel type based on the user parameters
      45             :       std::string kernel_type;
      46         324 :       if (isParamValid("diffusivity_matprops"))
      47         135 :         kernel_type = _use_ad ? "ADMatDiffusion" : "MatDiffusion";
      48          54 :       else if (isParamValid("diffusivity_functors"))
      49             :       {
      50          27 :         const auto & d = getParam<std::vector<MooseFunctorName>>("diffusivity_functors")[s];
      51          27 :         if (getProblem().hasFunction(d))
      52             :           kernel_type = "FunctionDiffusion";
      53             :         else
      54           0 :           paramError(
      55             :               "diffusivity_functors", "No diffusion kernel implemented for the source type of", d);
      56             :       }
      57             : 
      58         162 :       InputParameters params = getFactory().getValidParams(kernel_type);
      59         324 :       params.set<NonlinearVariableName>("variable") = var_name;
      60         162 :       assignBlocks(params, _blocks);
      61             : 
      62             :       // Transfer the diffusivity parameter from the Physics to the kernel
      63         324 :       if (isParamValid("diffusivity_matprops"))
      64         270 :         params.set<MaterialPropertyName>("diffusivity") =
      65         270 :             getParam<std::vector<MaterialPropertyName>>("diffusivity_matprops")[s];
      66          54 :       else if (isParamValid("diffusivity_functors"))
      67          54 :         params.set<FunctionName>("function") =
      68          81 :             getParam<std::vector<MooseFunctorName>>("diffusivity_functors")[s];
      69             : 
      70         324 :       getProblem().addKernel(kernel_type, prefix() + var_name + "_diffusion", params);
      71         162 :     }
      72             : 
      73             :     // Source term
      74         324 :     if (isParamValid("source_functors"))
      75             :     {
      76             :       // Select the kernel type based on the user parameters
      77             :       std::string kernel_type;
      78         324 :       const auto & sources = getParam<std::vector<MooseFunctorName>>("source_functors");
      79             :       const auto & source = sources[s];
      80         162 :       if (MooseUtils::parsesToReal(source) || getProblem().hasFunction(source) ||
      81         198 :           getProblem().hasPostprocessorValueByName(source))
      82         153 :         kernel_type = _use_ad ? "ADBodyForce" : "BodyForce";
      83           9 :       else if (getProblem().hasVariable(source))
      84           9 :         kernel_type = _use_ad ? "ADCoupledForce" : "CoupledForce";
      85             :       else
      86           0 :         paramError("source_functors",
      87             :                    "No kernel defined for a source term in CG for the type of '",
      88             :                    source,
      89             :                    "'");
      90             : 
      91         162 :       InputParameters params = getFactory().getValidParams(kernel_type);
      92         324 :       params.set<NonlinearVariableName>("variable") = var_name;
      93         162 :       assignBlocks(params, _blocks);
      94             : 
      95             :       // Transfer the source and coefficient parameter from the Physics to the kernel
      96         486 :       const auto coefs = getParam<std::vector<Real>>("source_coefs");
      97         162 :       const auto coef = coefs[s];
      98         162 :       if (MooseUtils::parsesToReal(source))
      99         135 :         params.set<Real>("value") = MooseUtils::convert<Real>(source) * coef;
     100          27 :       else if (getProblem().hasFunction(source))
     101             :       {
     102           9 :         params.set<Real>("value") = coef;
     103          18 :         params.set<FunctionName>("function") = source;
     104             :       }
     105          54 :       else if (getProblem().hasPostprocessorValueByName(source))
     106             :       {
     107           9 :         params.set<Real>("value") = coef;
     108          18 :         params.set<PostprocessorName>("postprocessor") = source;
     109             :       }
     110             :       else
     111             :       {
     112           9 :         params.set<Real>("coef") = coef;
     113          27 :         params.set<std::vector<VariableName>>("v") = {source};
     114             :       }
     115             : 
     116         324 :       getProblem().addKernel(kernel_type, prefix() + var_name + "_source", params);
     117         162 :     }
     118             : 
     119             :     // Time derivative term
     120         162 :     if (shouldCreateTimeDerivative(var_name, _blocks, false))
     121             :     {
     122         189 :       const std::string kernel_type = _use_ad ? "ADTimeDerivative" : "TimeDerivative";
     123         162 :       InputParameters params = getFactory().getValidParams(kernel_type);
     124         324 :       params.set<NonlinearVariableName>("variable") = var_name;
     125         162 :       assignBlocks(params, _blocks);
     126         324 :       getProblem().addKernel(kernel_type, prefix() + var_name + "_time", params);
     127         162 :     }
     128             :   }
     129          54 : }
     130             : 
     131             : void
     132          54 : MultiSpeciesDiffusionCG::addFEBCs()
     133             : {
     134         108 :   if (isParamSetByUser("neumann_boundaries"))
     135             :   {
     136             :     const auto & boundary_fluxes =
     137          27 :         getParam<std::vector<std::vector<MooseFunctorName>>>("boundary_fluxes");
     138             : 
     139         108 :     for (const auto s : index_range(_species_names))
     140             :     {
     141          81 :       const auto & var_name = _species_names[s];
     142             : 
     143         351 :       for (const auto i : index_range(_neumann_boundaries[s]))
     144             :       {
     145             :         const auto & bc_flux = boundary_fluxes[s][i];
     146             :         // Select the boundary type based on the user parameters and what we know to be most
     147             :         // efficient We could actually just use the very last option for everything but the
     148             :         // performance is better if one uses the specialized objects
     149         270 :         std::string bc_type = "";
     150         270 :         if (MooseUtils::parsesToReal(bc_flux))
     151          81 :           bc_type = _use_ad ? "ADNeumannBC" : "NeumannBC";
     152         189 :         else if (getProblem().hasVariable(bc_flux))
     153             :           bc_type = "CoupledVarNeumannBC"; // not AD, but still perfect Jacobian
     154         135 :         else if (getProblem().hasFunction(bc_flux))
     155          54 :           bc_type = _use_ad ? "ADFunctionNeumannBC" : "FunctionNeumannBC";
     156         243 :         else if (getProblem().hasPostprocessorValueByName(bc_flux))
     157             :           bc_type = "PostprocessorNeumannBC";
     158             :         else // this is AD, but we can mix AD and non-AD
     159             :           bc_type = "FunctorNeumannBC";
     160             : 
     161             :         // Get the parameters for the object type chosen and set the common parameters
     162         270 :         InputParameters params = getFactory().getValidParams(bc_type);
     163         540 :         params.set<NonlinearVariableName>("variable") = var_name;
     164         810 :         params.set<std::vector<BoundaryName>>("boundary") = {_neumann_boundaries[s][i]};
     165             : 
     166             :         // Set the flux parameter for the specific type of NeumannBC used
     167         270 :         if (MooseUtils::parsesToReal(bc_flux))
     168          81 :           params.set<Real>("value") = MooseUtils::convert<Real>(bc_flux);
     169         189 :         else if (getProblem().hasVariable(bc_flux))
     170         162 :           params.set<std::vector<VariableName>>("v") = {bc_flux};
     171         135 :         else if (getProblem().hasFunction(bc_flux))
     172         108 :           params.set<FunctionName>("function") = bc_flux;
     173         243 :         else if (getProblem().hasPostprocessorValueByName(bc_flux))
     174         162 :           params.set<PostprocessorName>("postprocessor") = bc_flux;
     175             :         else
     176           0 :           params.set<MooseFunctorName>("functor") = bc_flux;
     177             : 
     178         540 :         getProblem().addBoundaryCondition(
     179         540 :             bc_type, prefix() + var_name + "_neumann_bc_" + _neumann_boundaries[s][i], params);
     180         270 :       }
     181             :     }
     182             :   }
     183         108 :   if (isParamSetByUser("dirichlet_boundaries"))
     184             :   {
     185             :     const auto & boundary_values =
     186          27 :         getParam<std::vector<std::vector<MooseFunctorName>>>("boundary_values");
     187         108 :     for (const auto s : index_range(_species_names))
     188             :     {
     189          81 :       const auto & var_name = _species_names[s];
     190         297 :       for (const auto i : index_range(_dirichlet_boundaries[s]))
     191             :       {
     192             :         const auto & bc_value = boundary_values[s][i];
     193             :         // Select the boundary type based on the user parameters and what we know to be most
     194             :         // efficient
     195         216 :         std::string bc_type = "";
     196         216 :         if (MooseUtils::parsesToReal(bc_value))
     197          81 :           bc_type = _use_ad ? "ADDirichletBC" : "DirichletBC";
     198         135 :         else if (getProblem().hasVariable(bc_value))
     199          27 :           bc_type = _use_ad ? "ADMatchedValueBC" : "MatchedValueBC";
     200         108 :         else if (getProblem().hasFunction(bc_value))
     201          27 :           bc_type = _use_ad ? "ADFunctionDirichletBC" : "FunctionDirichletBC";
     202         243 :         else if (getProblem().hasPostprocessorValueByName(bc_value))
     203             :           bc_type = "PostprocessorDirichletBC";
     204             :         else // this is AD, but we can mix AD and non-AD
     205             :           bc_type = "FunctorDirichletBC";
     206             : 
     207         216 :         InputParameters params = getFactory().getValidParams(bc_type);
     208         432 :         params.set<NonlinearVariableName>("variable") = var_name;
     209         648 :         params.set<std::vector<BoundaryName>>("boundary") = {_dirichlet_boundaries[s][i]};
     210             : 
     211             :         // Set the flux parameter for the specific type of DirichletBC used
     212         216 :         if (MooseUtils::parsesToReal(bc_value))
     213          81 :           params.set<Real>("value") = MooseUtils::convert<Real>(bc_value);
     214         135 :         else if (getProblem().hasVariable(bc_value))
     215          81 :           params.set<std::vector<VariableName>>("v") = {bc_value};
     216         108 :         else if (getProblem().hasFunction(bc_value))
     217          54 :           params.set<FunctionName>("function") = bc_value;
     218         243 :         else if (getProblem().hasPostprocessorValueByName(bc_value))
     219         162 :           params.set<PostprocessorName>("postprocessor") = bc_value;
     220             :         else
     221           0 :           params.set<MooseFunctorName>("functor") = bc_value;
     222             : 
     223         432 :         getProblem().addBoundaryCondition(
     224         432 :             bc_type, prefix() + var_name + "_dirichlet_bc_" + _dirichlet_boundaries[s][i], params);
     225         216 :       }
     226             :     }
     227             :   }
     228          54 : }
     229             : 
     230             : void
     231          54 : MultiSpeciesDiffusionCG::addSolverVariables()
     232             : {
     233         216 :   for (const auto & var_name : _species_names)
     234             :   {
     235             :     // If the variable was added outside the Physics
     236         162 :     if (variableExists(var_name, /*error_if_aux*/ true))
     237             :     {
     238           0 :       if (isParamValid("variable_order"))
     239           0 :         paramError("variable_order",
     240           0 :                    "Cannot specify the variable order if variable " + var_name +
     241             :                        " is defined outside the Physics block");
     242             :       else
     243           0 :         continue;
     244             :     }
     245             : 
     246         162 :     const std::string variable_type = "MooseVariable";
     247         162 :     InputParameters params = getFactory().getValidParams(variable_type);
     248         486 :     params.set<MooseEnum>("order") = getParam<MooseEnum>("variable_order");
     249         162 :     assignBlocks(params, _blocks);
     250         162 :     params.set<SolverSystemName>("solver_sys") = getSolverSystem(var_name);
     251             : 
     252         162 :     getProblem().addVariable(variable_type, var_name, params);
     253         162 :   }
     254          54 : }

Generated by: LCOV version 1.14