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

Generated by: LCOV version 1.14