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