LCOV - code coverage report
Current view: top level - src/kernels - Kernel.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 419b9d Lines: 98 112 87.5 %
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 "Kernel.h"
      11             : 
      12             : // MOOSE includes
      13             : #include "Assembly.h"
      14             : #include "MooseVariableFE.h"
      15             : #include "MooseVariableScalar.h"
      16             : #include "SubProblem.h"
      17             : #include "NonlinearSystem.h"
      18             : #include "FEProblemBase.h"
      19             : 
      20             : #include "libmesh/threads.h"
      21             : #include "libmesh/quadrature.h"
      22             : 
      23             : InputParameters
      24     1686219 : Kernel::validParams()
      25             : {
      26     1686219 :   InputParameters params = KernelBase::validParams();
      27     1686219 :   params.registerBase("Kernel");
      28     1686219 :   return params;
      29           0 : }
      30             : 
      31       82658 : Kernel::Kernel(const InputParameters & parameters)
      32             :   : KernelBase(parameters),
      33             :     MooseVariableInterface<Real>(this,
      34             :                                  false,
      35             :                                  "variable",
      36             :                                  Moose::VarKindType::VAR_SOLVER,
      37             :                                  Moose::VarFieldType::VAR_FIELD_STANDARD),
      38      165212 :     _var(*mooseVariable()),
      39       82606 :     _test(_var.phi()),
      40       82606 :     _grad_test(_var.gradPhi()),
      41       82606 :     _phi(_assembly.phi(_var)),
      42       82606 :     _grad_phi(_assembly.gradPhi(_var)),
      43       82606 :     _u(_is_implicit ? _var.sln() : _var.slnOld()),
      44      165264 :     _grad_u(_is_implicit ? _var.gradSln() : _var.gradSlnOld())
      45             : {
      46       82606 :   addMooseVariableDependency(mooseVariable());
      47       82606 :   _save_in.resize(_save_in_strings.size());
      48       82606 :   _diag_save_in.resize(_diag_save_in_strings.size());
      49             : 
      50       82772 :   for (unsigned int i = 0; i < _save_in_strings.size(); i++)
      51             :   {
      52         170 :     MooseVariable * var = &_subproblem.getStandardVariable(_tid, _save_in_strings[i]);
      53             : 
      54         170 :     if (_fe_problem.getNonlinearSystemBase(_sys.number()).hasVariable(_save_in_strings[i]))
      55           4 :       paramError("save_in", "cannot use solution variable as save-in variable");
      56             : 
      57         166 :     if (var->feType() != _var.feType())
      58           0 :       paramError(
      59             :           "save_in",
      60             :           "saved-in auxiliary variable is incompatible with the object's nonlinear variable: ",
      61           0 :           moose::internal::incompatVarMsg(*var, _var));
      62             : 
      63         166 :     _save_in[i] = var;
      64         166 :     var->sys().addVariableToZeroOnResidual(_save_in_strings[i]);
      65         166 :     addMooseVariableDependency(var);
      66             :   }
      67             : 
      68       82602 :   _has_save_in = _save_in.size() > 0;
      69             : 
      70       82714 :   for (unsigned int i = 0; i < _diag_save_in_strings.size(); i++)
      71             :   {
      72         116 :     MooseVariable * var = &_subproblem.getStandardVariable(_tid, _diag_save_in_strings[i]);
      73             : 
      74         116 :     if (_fe_problem.getNonlinearSystemBase(_sys.number()).hasVariable(_diag_save_in_strings[i]))
      75           4 :       paramError("diag_save_in", "cannot use solution variable as diag save-in variable");
      76             : 
      77         112 :     if (var->feType() != _var.feType())
      78           0 :       paramError(
      79             :           "diag_save_in",
      80             :           "saved-in auxiliary variable is incompatible with the object's nonlinear variable: ",
      81           0 :           moose::internal::incompatVarMsg(*var, _var));
      82             : 
      83         112 :     _diag_save_in[i] = var;
      84         112 :     var->sys().addVariableToZeroOnJacobian(_diag_save_in_strings[i]);
      85         112 :     addMooseVariableDependency(var);
      86             :   }
      87             : 
      88       82598 :   _has_diag_save_in = _diag_save_in.size() > 0;
      89       82598 : }
      90             : 
      91             : void
      92   488748355 : Kernel::computeResidual()
      93             : {
      94   488748355 :   if (!hasVectorTags())
      95          72 :     return;
      96             : 
      97   488748283 :   prepareVectorTag(_assembly, _var.number());
      98             : 
      99   488748283 :   precalculateResidual();
     100  2709212744 :   for (_i = 0; _i < _test.size(); _i++)
     101 13903854642 :     for (_qp = 0; _qp < _qrule->n_points(); _qp++)
     102 11683390181 :       _local_re(_i) += _JxW[_qp] * _coord[_qp] * computeQpResidual();
     103             : 
     104   488748239 :   accumulateTaggedLocalResidual();
     105             : 
     106   488748239 :   if (_has_save_in)
     107             :   {
     108        5670 :     Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
     109       12060 :     for (const auto & var : _save_in)
     110        6390 :       var->sys().solution().add_vector(_local_re, var->dofIndices());
     111        5670 :   }
     112             : }
     113             : 
     114             : void
     115   120120151 : Kernel::computeJacobian()
     116             : {
     117   120120151 :   prepareMatrixTag(_assembly, _var.number(), _var.number());
     118             : 
     119   120120151 :   precalculateJacobian();
     120   638239217 :   for (_i = 0; _i < _test.size(); _i++)
     121  2995772069 :     for (_j = 0; _j < _phi.size(); _j++)
     122 16743841951 :       for (_qp = 0; _qp < _qrule->n_points(); _qp++)
     123 14266188969 :         _local_ke(_i, _j) += _JxW[_qp] * _coord[_qp] * computeQpJacobian();
     124             : 
     125   120120130 :   accumulateTaggedLocalMatrix();
     126             : 
     127   120120130 :   if (_has_diag_save_in && !_sys.computingScalingJacobian())
     128             :   {
     129         716 :     DenseVector<Number> diag = _assembly.getJacobianDiagonal(_local_ke);
     130         716 :     Threads::spin_mutex::scoped_lock lock(Threads::spin_mtx);
     131        1500 :     for (const auto & var : _diag_save_in)
     132         784 :       var->sys().solution().add_vector(diag, var->dofIndices());
     133         716 :   }
     134   120120130 : }
     135             : 
     136             : void
     137    52723324 : Kernel::computeOffDiagJacobian(const unsigned int jvar_num)
     138             : {
     139    52723324 :   if (jvar_num == _var.number())
     140    33707969 :     computeJacobian();
     141             :   else
     142             :   {
     143    19015355 :     const auto & jvar = getVariable(jvar_num);
     144    19015355 :     prepareMatrixTag(_assembly, _var.number(), jvar_num);
     145             : 
     146             :     // phi_size may not be equal to _phi.size(), e.g. when jvar is a vector variable
     147    19015355 :     const auto phi_size = jvar.dofIndices().size();
     148             :     mooseAssert(
     149             :         phi_size * jvar.count() == _local_ke.n(),
     150             :         "The size of the phi container does not match the number of local Jacobian columns");
     151             : 
     152             :     mooseAssert(_local_ke.m() == _test.size(),
     153             :                 "If these are not the same, then we shouldn't even be calling this method");
     154             : 
     155    19015355 :     precalculateOffDiagJacobian(jvar_num);
     156    19015355 :     if (jvar.count() == 1)
     157             :     {
     158    93256525 :       for (_i = 0; _i < _test.size(); _i++)
     159   374242384 :         for (_j = 0; _j < phi_size; _j++)
     160  1523418544 :           for (_qp = 0; _qp < _qrule->n_points(); _qp++)
     161  1223418482 :             _local_ke(_i, _j) += _JxW[_qp] * _coord[_qp] * computeQpOffDiagJacobian(jvar.number());
     162             :     }
     163             :     else
     164             :     {
     165        1152 :       const auto n = cast_int<unsigned int>(phi_size);
     166        5760 :       for (_i = 0; _i < _test.size(); _i++)
     167       23040 :         for (_j = 0; _j < phi_size; _j++)
     168       92160 :           for (_qp = 0; _qp < _qrule->n_points(); _qp++)
     169             :           {
     170             :             const RealEigenVector v =
     171       73728 :                 _JxW[_qp] * _coord[_qp] *
     172      147456 :                 computeQpOffDiagJacobianArray(
     173       73728 :                     static_cast<ArrayMooseVariable &>(const_cast<MooseVariableFieldBase &>(jvar)));
     174      221184 :             for (unsigned int k = 0; k < v.size(); ++k)
     175      147456 :               _local_ke(_i, _j + k * n) += v(k);
     176       73728 :           }
     177             :     }
     178             : 
     179    19015355 :     accumulateTaggedLocalMatrix();
     180             :   }
     181    52723324 : }
     182             : 
     183             : void
     184           0 : Kernel::computeOffDiagJacobianScalar(const unsigned int jvar)
     185             : {
     186           0 :   MooseVariableScalar & jv = _sys.getScalarVariable(_tid, jvar);
     187           0 :   prepareMatrixTag(_assembly, _var.number(), jvar);
     188             : 
     189           0 :   for (_i = 0; _i < _test.size(); _i++)
     190           0 :     for (_j = 0; _j < jv.order(); _j++)
     191           0 :       for (_qp = 0; _qp < _qrule->n_points(); _qp++)
     192           0 :         _local_ke(_i, _j) += _JxW[_qp] * _coord[_qp] * computeQpOffDiagJacobianScalar(jvar);
     193             : 
     194           0 :   accumulateTaggedLocalMatrix();
     195           0 : }
     196             : 
     197             : void
     198         546 : Kernel::computeResidualAndJacobian()
     199             : {
     200         546 :   computeResidual();
     201             : 
     202        1533 :   for (const auto & [ivariable, jvariable] : _fe_problem.couplingEntries(_tid, _sys.number()))
     203             :   {
     204         987 :     const unsigned int ivar = ivariable->number();
     205         987 :     const unsigned int jvar = jvariable->number();
     206             : 
     207         987 :     if (ivar != _var.number())
     208         294 :       continue;
     209             : 
     210         693 :     if (_is_implicit)
     211             :     {
     212         693 :       prepareShapes(jvar);
     213         693 :       computeOffDiagJacobian(jvar);
     214             :     }
     215             :   }
     216             : 
     217             :   /// TODO: add nonlocal Jacobians and scalar Jacobians
     218         546 : }

Generated by: LCOV version 1.14