LCOV - code coverage report
Current view: top level - src/physics - DiffusionCG.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 148 162 91.4 %
Date: 2025-07-17 01:28:37 Functions: 6 7 85.7 %
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 "DiffusionCG.h"
      11             : #include "MooseVariableBase.h"
      12             : 
      13             : // Register the actions for the objects actually used
      14             : registerMooseAction("MooseApp", DiffusionCG, "add_kernel");
      15             : registerMooseAction("MooseApp", DiffusionCG, "add_bc");
      16             : registerMooseAction("MooseApp", DiffusionCG, "add_variable");
      17             : registerDiffusionPhysicsBaseTasks("MooseApp", DiffusionCG);
      18             : 
      19             : InputParameters
      20         361 : DiffusionCG::validParams()
      21             : {
      22         361 :   InputParameters params = DiffusionPhysicsBase::validParams();
      23         361 :   params.addClassDescription(
      24             :       "Discretizes a diffusion equation with the continuous Galerkin finite element method");
      25        1083 :   params.addParam<bool>(
      26             :       "use_automatic_differentiation",
      27         722 :       true,
      28             :       "Whether to use automatic differentiation for all the terms in the equation");
      29         361 :   params.transferParam<MooseEnum>(MooseVariableBase::validParams(), "order", "variable_order");
      30             : 
      31         361 :   return params;
      32           0 : }
      33             : 
      34         158 : DiffusionCG::DiffusionCG(const InputParameters & parameters)
      35             :   : PhysicsBase(parameters),
      36             :     PhysicsComponentInterface(parameters),
      37             :     DiffusionPhysicsBase(parameters),
      38         158 :     _use_ad(getParam<bool>("use_automatic_differentiation"))
      39             : {
      40         158 : }
      41             : 
      42             : void
      43         130 : DiffusionCG::addFEKernels()
      44             : {
      45             :   // Diffusion term
      46             :   {
      47             :     // Select the kernel type based on the user parameters
      48         130 :     std::string kernel_type;
      49         130 :     if (isParamValid("diffusivity_matprop"))
      50         106 :       kernel_type = _use_ad ? "ADMatDiffusion" : "MatDiffusion";
      51          24 :     else if (isParamValid("diffusivity_functor"))
      52             :     {
      53          12 :       const auto & d = getParam<MooseFunctorName>("diffusivity_functor");
      54          12 :       if (getProblem().hasFunction(d) || MooseUtils::parsesToReal(d))
      55          12 :         kernel_type = "FunctionDiffusion";
      56             :       else
      57           0 :         paramError("diffusivity_functor",
      58             :                    "No diffusion kernel implemented for the diffusivity type of ",
      59             :                    d);
      60             :     }
      61             :     else
      62          12 :       kernel_type = _use_ad ? "ADDiffusion" : "Diffusion";
      63         130 :     InputParameters params = getFactory().getValidParams(kernel_type);
      64         130 :     params.set<NonlinearVariableName>("variable") = _var_name;
      65         130 :     assignBlocks(params, _blocks);
      66             : 
      67             :     // Transfer the diffusivity parameter from the Physics to the kernel
      68             :     // From parameters
      69         130 :     if (isParamValid("diffusivity_matprop"))
      70         212 :       params.set<MaterialPropertyName>("diffusivity") =
      71         318 :           getParam<MaterialPropertyName>("diffusivity_matprop");
      72          24 :     else if (isParamValid("diffusivity_functor"))
      73          12 :       params.set<FunctionName>("function") = getParam<MooseFunctorName>("diffusivity_functor");
      74             : 
      75         130 :     getProblem().addKernel(kernel_type, prefix() + _var_name + "_diffusion", params);
      76         130 :   }
      77             : 
      78             :   // Source term
      79         130 :   if (isParamValid("source_functor"))
      80             :   {
      81             :     // Select the kernel type based on the user parameters
      82         130 :     std::string kernel_type;
      83         130 :     const auto & source = getParam<MooseFunctorName>("source_functor");
      84         142 :     if (MooseUtils::parsesToReal(source) || getProblem().hasFunction(source) ||
      85         142 :         getProblem().hasPostprocessorValueByName(source))
      86         130 :       kernel_type = _use_ad ? "ADBodyForce" : "BodyForce";
      87           0 :     else if (getProblem().hasVariable(source))
      88           0 :       kernel_type = _use_ad ? "ADCoupledForce" : "CoupledForce";
      89             :     else
      90           0 :       paramError("source_functor",
      91             :                  "No kernel defined for a source term in CG for the type of '",
      92             :                  source,
      93             :                  "'");
      94             : 
      95         130 :     InputParameters params = getFactory().getValidParams(kernel_type);
      96         130 :     params.set<NonlinearVariableName>("variable") = _var_name;
      97         130 :     assignBlocks(params, _blocks);
      98             : 
      99             :     // Transfer the source and coefficient parameter from the Physics to the kernel
     100         130 :     const auto coef = getParam<Real>("source_coef");
     101         130 :     if (MooseUtils::parsesToReal(source))
     102         118 :       params.set<Real>("value") = MooseUtils::convert<Real>(source) * coef;
     103          12 :     else if (getProblem().hasFunction(source))
     104             :     {
     105           0 :       params.set<Real>("value") = coef;
     106           0 :       params.set<FunctionName>("function") = source;
     107             :     }
     108          12 :     else if (getProblem().hasPostprocessorValueByName(source))
     109             :     {
     110          12 :       params.set<Real>("value") = coef;
     111          12 :       params.set<PostprocessorName>("postprocessor") = source;
     112             :     }
     113             :     else
     114             :     {
     115           0 :       params.set<Real>("coef") = coef;
     116           0 :       params.set<std::vector<VariableName>>("v") = {source};
     117             :     }
     118             : 
     119         130 :     getProblem().addKernel(kernel_type, prefix() + _var_name + "_source", params);
     120         130 :   }
     121             : 
     122             :   // Time derivative term
     123         130 :   if (shouldCreateTimeDerivative(_var_name, _blocks, false))
     124             :   {
     125          82 :     const std::string kernel_type = _use_ad ? "ADTimeDerivative" : "TimeDerivative";
     126          82 :     InputParameters params = getFactory().getValidParams(kernel_type);
     127          82 :     params.set<NonlinearVariableName>("variable") = _var_name;
     128          82 :     assignBlocks(params, _blocks);
     129          82 :     getProblem().addKernel(kernel_type, prefix() + _var_name + "_time", params);
     130          82 :   }
     131         126 : }
     132             : 
     133             : void
     134         130 : DiffusionCG::addFEBCs()
     135             : {
     136         130 :   if (isParamSetByUser("neumann_boundaries"))
     137             :   {
     138          74 :     const auto & boundary_fluxes = getParam<std::vector<MooseFunctorName>>("boundary_fluxes");
     139         370 :     for (const auto i : index_range(_neumann_boundaries))
     140             :     {
     141         296 :       const auto & bc_flux = boundary_fluxes[i];
     142             :       // Select the boundary type based on the user parameters and what we know to be most efficient
     143             :       // We could actually just use the very last option for everything but the performance is
     144             :       // better if one uses the specialized objects
     145         296 :       std::string bc_type = "";
     146         296 :       if (MooseUtils::parsesToReal(bc_flux))
     147         188 :         bc_type = _use_ad ? "ADNeumannBC" : "NeumannBC";
     148         108 :       else if (getProblem().hasVariable(bc_flux))
     149          36 :         bc_type = "CoupledVarNeumannBC"; // not AD, but still perfect Jacobian
     150          72 :       else if (getProblem().hasFunction(bc_flux))
     151          36 :         bc_type = _use_ad ? "ADFunctionNeumannBC" : "FunctionNeumannBC";
     152          36 :       else if (getProblem().hasPostprocessorValueByName(bc_flux))
     153          36 :         bc_type = "PostprocessorNeumannBC";
     154             :       else // this is AD, but we can mix AD and non-AD
     155           0 :         bc_type = "FunctorNeumannBC";
     156             : 
     157             :       // Get the parameters for the object type chosen and set the common parameters
     158         296 :       InputParameters params = getFactory().getValidParams(bc_type);
     159         296 :       params.set<NonlinearVariableName>("variable") = _var_name;
     160         592 :       params.set<std::vector<BoundaryName>>("boundary") = {_neumann_boundaries[i]};
     161             : 
     162             :       // Set the flux parameter for the specific type of NeumannBC used
     163         296 :       if (MooseUtils::parsesToReal(bc_flux))
     164         188 :         params.set<Real>("value") = MooseUtils::convert<Real>(bc_flux);
     165         108 :       else if (getProblem().hasVariable(bc_flux))
     166          72 :         params.set<std::vector<VariableName>>("v") = {bc_flux};
     167          72 :       else if (getProblem().hasFunction(bc_flux))
     168          36 :         params.set<FunctionName>("function") = bc_flux;
     169          36 :       else if (getProblem().hasPostprocessorValueByName(bc_flux))
     170          36 :         params.set<PostprocessorName>("postprocessor") = bc_flux;
     171             :       else
     172           0 :         params.set<MooseFunctorName>("functor") = bc_flux;
     173             : 
     174         592 :       getProblem().addBoundaryCondition(
     175         592 :           bc_type, prefix() + _var_name + "_neumann_bc_" + _neumann_boundaries[i], params);
     176         296 :     }
     177             :   }
     178         130 :   if (isParamSetByUser("dirichlet_boundaries"))
     179             :   {
     180         114 :     const auto & boundary_values = getParam<std::vector<MooseFunctorName>>("boundary_values");
     181         522 :     for (const auto i : index_range(_dirichlet_boundaries))
     182             :     {
     183         408 :       const auto & bc_value = boundary_values[i];
     184             :       // Select the boundary type based on the user parameters and what we know to be most efficient
     185         408 :       std::string bc_type = "";
     186         408 :       if (MooseUtils::parsesToReal(bc_value))
     187         300 :         bc_type = _use_ad ? "ADDirichletBC" : "DirichletBC";
     188         108 :       else if (getProblem().hasVariable(bc_value))
     189          36 :         bc_type = _use_ad ? "ADMatchedValueBC" : "MatchedValueBC";
     190          72 :       else if (getProblem().hasFunction(bc_value))
     191          36 :         bc_type = _use_ad ? "ADFunctionDirichletBC" : "FunctionDirichletBC";
     192          36 :       else if (getProblem().hasPostprocessorValueByName(bc_value))
     193          36 :         bc_type = "PostprocessorDirichletBC";
     194             :       else // this is AD, but we can mix AD and non-AD
     195           0 :         bc_type = "FunctorDirichletBC";
     196             : 
     197         408 :       InputParameters params = getFactory().getValidParams(bc_type);
     198         408 :       params.set<NonlinearVariableName>("variable") = _var_name;
     199         816 :       params.set<std::vector<BoundaryName>>("boundary") = {_dirichlet_boundaries[i]};
     200             : 
     201             :       // Set the flux parameter for the specific type of DirichletBC used
     202         408 :       if (MooseUtils::parsesToReal(bc_value))
     203         300 :         params.set<Real>("value") = MooseUtils::convert<Real>(bc_value);
     204         108 :       else if (getProblem().hasVariable(bc_value))
     205          72 :         params.set<std::vector<VariableName>>("v") = {bc_value};
     206          72 :       else if (getProblem().hasFunction(bc_value))
     207          36 :         params.set<FunctionName>("function") = bc_value;
     208          36 :       else if (getProblem().hasPostprocessorValueByName(bc_value))
     209          36 :         params.set<PostprocessorName>("postprocessor") = bc_value;
     210             :       else
     211           0 :         params.set<MooseFunctorName>("functor") = bc_value;
     212             : 
     213         816 :       getProblem().addBoundaryCondition(
     214         816 :           bc_type, prefix() + _var_name + "_dirichlet_bc_" + _dirichlet_boundaries[i], params);
     215         408 :     }
     216             :   }
     217         906 : }
     218             : 
     219             : void
     220         150 : DiffusionCG::addSolverVariables()
     221             : {
     222             :   // If the variable was added outside the Physics
     223         150 :   if (!shouldCreateVariable(_var_name, _blocks, true))
     224             :   {
     225         218 :     reportPotentiallyMissedParameters({"variable_order", "system_names"}, "MooseVariable");
     226          42 :     return;
     227             :   }
     228             : 
     229         100 :   const std::string variable_type = "MooseVariable";
     230         100 :   InputParameters params = getFactory().getValidParams(variable_type);
     231         100 :   params.set<MooseEnum>("order") = getParam<MooseEnum>("variable_order");
     232         100 :   assignBlocks(params, _blocks);
     233         100 :   params.set<SolverSystemName>("solver_sys") = getSolverSystem(_var_name);
     234             : 
     235         100 :   getProblem().addVariable(variable_type, _var_name, params);
     236         188 : }
     237             : 
     238             : void
     239         130 : DiffusionCG::addBoundaryConditionsFromComponents()
     240             : {
     241         130 :   const auto bc_type_fixed = "FunctorDirichletBC";
     242         130 :   InputParameters params_fixed = getFactory().getValidParams(bc_type_fixed);
     243         130 :   const auto bc_type_flux = "FunctorNeumannBC";
     244         130 :   InputParameters params_flux = getFactory().getValidParams(bc_type_flux);
     245             : 
     246         178 :   for (const auto & comp_pair : _components_boundary_conditions)
     247             :   {
     248         112 :     for (const auto & bc_pair : comp_pair.second)
     249             :     {
     250          64 :       params_fixed.set<NonlinearVariableName>("variable") = _var_name;
     251          64 :       params_flux.set<NonlinearVariableName>("variable") = _var_name;
     252             : 
     253          64 :       const auto bc_type = bc_pair.second.second;
     254          64 :       const auto functor_name = bc_pair.second.first;
     255          64 :       params_fixed.set<MooseFunctorName>("functor") = functor_name;
     256          64 :       params_flux.set<MooseFunctorName>("functor") = functor_name;
     257             : 
     258          64 :       const auto surface_name = bc_pair.first.second;
     259         128 :       params_fixed.set<std::vector<BoundaryName>>("boundary") = {surface_name};
     260         128 :       params_flux.set<std::vector<BoundaryName>>("boundary") = {surface_name};
     261             : 
     262          64 :       if (bc_type == ComponentBoundaryConditionInterface::BoundaryConditionType::FIXED_VALUE)
     263          96 :         getProblem().addBoundaryCondition(bc_type_fixed,
     264          96 :                                           prefix() + _var_name + "_comp_" + comp_pair.first +
     265         144 :                                               "_fixed_value_" + surface_name,
     266             :                                           params_fixed);
     267          16 :       else if (bc_type == ComponentBoundaryConditionInterface::BoundaryConditionType::FLUX)
     268          32 :         getProblem().addBoundaryCondition(bc_type_flux,
     269          32 :                                           prefix() + _var_name + "_comp_" + comp_pair.first +
     270          48 :                                               "_flux_" + surface_name,
     271             :                                           params_flux);
     272             :       else
     273           0 :         mooseError("Boundary condition type not implemented");
     274          64 :     }
     275             :   }
     276         258 : }

Generated by: LCOV version 1.14