https://mooseframework.inl.gov
Loading...
Searching...
No Matches
porous_flow
src
kernels
PorousFlowLumpedKernelBase.C
Go to the documentation of this file.
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 "
PorousFlowLumpedKernelBase.h
"
11
12
template
<
bool
is_ad>
13
PorousFlowLumpedKernelBaseTempl<is_ad>::PorousFlowLumpedKernelBaseTempl
(
14
const
InputParameters
& parameters)
15
:
GenericKernel
<is_ad>(parameters)
16
{
17
// Mass lumping evaluates each residual row using the nodal material property at that node, which
18
// identifies each element test function with a mesh node. This is only valid for nodal
19
// (Lagrange) variables.
20
if
(!
_var
.
isNodal
())
21
mooseError
(
"The variable '"
,
22
_var
.
name
(),
23
"' is not a nodal (Lagrange) variable. This kernel uses mass lumping, which "
24
"requires a nodal variable. PorousFlow has no discontinuous-Galerkin "
25
"finite-element discretisation, so an element-local variable (eg CONSTANT "
26
"MONOMIAL) cannot be used as a PorousFlow variable."
);
27
}
28
29
template
<
bool
is_ad>
30
void
31
PorousFlowLumpedKernelBaseTempl<is_ad>::jacobianSetup
()
32
{
33
GenericKernel<is_ad>::jacobianSetup
();
34
_my_elem_lma =
nullptr
;
35
}
36
37
// AD-path Jacobian assembly for kernels that use mass-lumped (nodal) material properties.
38
//
39
// The default ADKernel path (ADKernel::computeADJacobian -> addJacobian) routes through
40
// Assembly::cacheJacobian, which takes the sparse column set from residuals[0] and reuses it for
41
// every row. That assumes every test function's residual depends on the same set of DOFs, which
42
// holds for ordinary qp-based weak forms because the solution at any QP is sum_j u_j*phi_j(qp)
43
// and therefore involves every element DOF.
44
//
45
// With mass lumping each residual row _i depends only on the nodal material properties at node _i
46
// (i.e. on the DOFs at node _i alone), so the column set from residuals[0] is only valid for row 0;
47
// the off-node rows are assembled against the wrong columns and come out zero.
48
//
49
// addJacobianWithoutConstraints reads each row's own column indices from
50
// residuals[_i].derivatives().nude_indices(), giving the correct per-node block structure.
51
//
52
// This is consistent with how the framework handles analogous cases:
53
// - ADNodalKernel::computeJacobian passes a size-1 residual array; Assembly::cacheJacobian's
54
// residuals.size()==1 branch falls straight through to cacheJacobianWithoutConstraints.
55
// - MassLumpedTimeDerivative::computeJacobian (non-AD) overrides assembly to fill only the
56
// node-diagonal entries, for the same structural reason.
57
//
58
// constrain_element_matrix is therefore skipped. It cannot be applied to a node-diagonal block
59
// structure: the constraint machinery assumes a fully-coupled local matrix where all rows share a
60
// column space. Neither the non-AD lumped path nor the framework AD nodal path applies it either.
61
template
<
bool
is_ad>
62
void
63
PorousFlowLumpedKernelBaseTempl<is_ad>::computeJacobian
()
64
{
65
if
constexpr
(!is_ad)
66
GenericKernel<is_ad>::computeJacobian
();
67
else
68
{
69
if
(_my_elem_lma != this->_current_elem)
70
{
71
this->computeResidualsForJacobian();
72
this->addJacobianWithoutConstraints(
73
this->_assembly, this->_residuals, this->dofIndices(), this->_var.scalingFactor());
74
_my_elem_lma = this->_current_elem;
75
}
76
}
77
}
78
79
// A single AD residual evaluation carries derivatives wrt every coupled variable, so the
80
// off-diagonal blocks are assembled by the same addJacobianWithoutConstraints call as the diagonal.
81
// _my_elem_lma caches the element so computation happens once per element rather than once per
82
// coupled jvar, mirroring ADKernel's own _my_elem guard in ADKernel::computeOffDiagJacobian.
83
template
<
bool
is_ad>
84
void
85
PorousFlowLumpedKernelBaseTempl<is_ad>::computeOffDiagJacobian
(
unsigned
int
jvar)
86
{
87
if
constexpr
(!is_ad)
88
GenericKernel<is_ad>::computeOffDiagJacobian
(jvar);
89
else
90
{
91
libmesh_ignore(jvar);
92
if
(_my_elem_lma != this->_current_elem)
93
{
94
this->computeResidualsForJacobian();
95
this->addJacobianWithoutConstraints(
96
this->_assembly, this->_residuals, this->dofIndices(), this->_var.scalingFactor());
97
_my_elem_lma = this->_current_elem;
98
}
99
}
100
}
101
102
template
class
PorousFlowLumpedKernelBaseTempl<false>
;
103
template
class
PorousFlowLumpedKernelBaseTempl<true>
;
PorousFlowLumpedKernelBase.h
GenericKernel
GenericKernel< is_ad >::_var
MooseVariable & _var
MooseVariableFE::name
const std::string & name() const
GenericKernel< is_ad >::mooseError
void mooseError(Args &&... args) const
MooseVariableFE::isNodal
bool isNodal() const override
PorousFlowLumpedKernelBaseTempl
Base class for PorousFlow kernels that use mass-lumped (nodal) material properties.
Definition
PorousFlowLumpedKernelBase.h:25
PorousFlowLumpedKernelBaseTempl::computeOffDiagJacobian
virtual void computeOffDiagJacobian(unsigned int jvar) override
Definition
PorousFlowLumpedKernelBase.C:85
PorousFlowLumpedKernelBaseTempl::computeJacobian
virtual void computeJacobian() override
Definition
PorousFlowLumpedKernelBase.C:63
PorousFlowLumpedKernelBaseTempl::jacobianSetup
virtual void jacobianSetup() override
Definition
PorousFlowLumpedKernelBase.C:31
PorousFlowLumpedKernelBaseTempl::PorousFlowLumpedKernelBaseTempl
PorousFlowLumpedKernelBaseTempl(const InputParameters ¶meters)
Definition
PorousFlowLumpedKernelBase.C:13
GenericKernel::jacobianSetup
virtual void jacobianSetup()
InputParameters
Generated on Fri Sep 11 2026 20:36:36 for https://mooseframework.inl.gov by
1.9.8