14#ifndef DUMUX_EXPERIMENTAL_CVFE_LOCAL_ASSEMBLER_HH
15#define DUMUX_EXPERIMENTAL_CVFE_LOCAL_ASSEMBLER_HH
17#include <dune/common/exceptions.hh>
18#include <dune/common/hybridutilities.hh>
19#include <dune/common/reservedvector.hh>
20#include <dune/grid/common/gridenums.hh>
21#include <dune/istl/matrixindexset.hh>
22#include <dune/istl/bvector.hh>
30#include <dumux/common/typetraits/localdofs_.hh>
41#include <dumux/assembly/cvfevolvarsdeflectionpolicy_.hh>
56template<
class TypeTag,
class Assembler,
class Implementation>
63 using ElementVolumeVariables =
typename GridVariables::GridVolumeVariables::LocalView;
71 using ParentType::ParentType;
87 template <
class Res
idualVector,
class StageParams,
class PartialReassembler = DefaultPartialReassembler,
class CouplingFunction = Noop>
89 const StageParams& stageParams, ResidualVector& temporal, ResidualVector& spatial,
90 ResidualVector& constrainedDofs,
92 const CouplingFunction& maybeAssembleCouplingBlocks =
noop)
94 this->
asImp_().bindLocalViews();
100 const auto sWeight = stageParams.spatialWeight(stageParams.size()-1);
101 const auto tWeight = stageParams.temporalWeight(stageParams.size()-1);
109 spatial[scv.dofIndex()] += flux[scv.localDofIndex()];
110 temporal[scv.dofIndex()] += storage[scv.localDofIndex()];
111 if (!stageParams.skipSpatial(stageParams.size()-1))
112 origResidual[scv.localDofIndex()] += flux[scv.localDofIndex()]*sWeight;
113 if (!stageParams.skipTemporal(stageParams.size()-1))
114 origResidual[scv.localDofIndex()] += storage[scv.localDofIndex()]*tWeight;
115 res[scv.dofIndex()] += origResidual[scv.localDofIndex()];
118 this->
localResidual().spatialWeight(sWeight, stageParams.skipSpatial(stageParams.size()-1));
119 this->
localResidual().temporalWeight(tWeight, stageParams.skipTemporal(stageParams.size()-1));
121 if (partialReassembler && partialReassembler->elementColor(eIdxGlobal) ==
EntityColor::green)
124 maybeAssembleCouplingBlocks(origResidual);
128 this->
asImp_().assembleJacobian(jac, gridVariables, origResidual, partialReassembler);
131 maybeAssembleCouplingBlocks(origResidual);
140 Dune::Hybrid::forEach(std::make_integer_sequence<int, dim+1>{}, [&](
auto d)
142 constexpr int codim = dim - d;
144 for (
int idx = 0; idx < localCoeffs.size(); ++idx)
146 const auto& localKey = localCoeffs.localKey(idx);
149 if (localKey.codim() != codim)
153 auto entity = this->
element().template subEntity<codim>(localKey.subEntity());
154 if (entity.partitionType() == Dune::InteriorEntity || entity.partitionType() == Dune::BorderEntity)
160 using BlockType =
typename JacobianMatrix::block_type;
163 BlockType &J = jac[dofIndex][dofIndex];
164 for (
int j = 0; j < BlockType::rows; ++j)
167 constrainedDofs[dofIndex] = 1;
173 auto applyDirichlet = [&] (
const auto& scvI,
174 const auto& dirichletValues,
178 res[scvI.dofIndex()][eqIdx] = this->
curElemVolVars()[scvI].priVars()[pvIdx] - dirichletValues[pvIdx];
179 constrainedDofs[scvI.dofIndex()][eqIdx] = 1;
181 auto& row = jac[scvI.dofIndex()];
182 for (
auto col = row.begin(); col != row.end(); ++col)
183 row[col.index()][eqIdx] = 0.0;
185 jac[scvI.dofIndex()][scvI.dofIndex()][eqIdx][pvIdx] = 1.0;
190 for (
const auto periodicDof :
193 res[periodicDof][eqIdx] = this->
curElemVolVars()[scvI].priVars()[pvIdx] - dirichletValues[pvIdx];
194 constrainedDofs[periodicDof][eqIdx] = 1;
195 const auto end = jac[periodicDof].end();
196 for (
auto it = jac[periodicDof].begin(); it != end; ++it)
197 (*it) = periodicDof != it.index() ? 0.0 : 1.0;
202 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
211 this->
asImp_().bindLocalViews();
212 this->
asImp_().assembleJacobian(jac, gridVariables);
214 auto applyDirichlet = [&] (
const auto& scvI,
215 const auto& dirichletValues,
219 auto& row = jac[scvI.dofIndex()];
220 for (
auto col = row.begin(); col != row.end(); ++col)
221 row[col.index()][eqIdx] = 0.0;
223 jac[scvI.dofIndex()][scvI.dofIndex()][eqIdx][pvIdx] = 1.0;
226 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
232 template <
class Res
idualVector>
235 this->
asImp_().bindLocalViews();
239 res[localDof.dofIndex()] += residual[localDof.index()];
241 auto applyDirichlet = [&] (
const auto& scvI,
242 const auto& dirichletValues,
246 res[scvI.dofIndex()][eqIdx] = this->
curElemVolVars()[scvI].priVars()[pvIdx] - dirichletValues[pvIdx];
249 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
255 template<
class Res
idualVector>
258 this->
asImp_().bindLocalViews();
263 spatialRes[scv.dofIndex()] += flux[scv.localDofIndex()];
264 temporalRes[scv.dofIndex()] += storage[scv.localDofIndex()];
269 template<
typename ApplyFunction>
273 this->
asImp_().evalDirichletBoundaries(applyDirichlet);
275 this->
asImp_().enforceInternalDirichletConstraints(applyDirichlet);
281 template<
typename ApplyDirichletFunctionType >
291 if (bcTypes.hasDirichlet())
293 const auto dirichletValues = this->
asImp_().problem().dirichlet(this->
element(), scvI);
296 for (
int eqIdx = 0; eqIdx < numEq; ++eqIdx)
298 if (bcTypes.isDirichlet(eqIdx))
300 const auto pvIdx = bcTypes.eqToDirichletIndex(eqIdx);
301 assert(0 <= pvIdx && pvIdx < numEq);
302 applyDirichlet(scvI, dirichletValues, eqIdx, pvIdx);
314 template<
class... Args>
321 template<
class... Args>
334template<
class TypeTag,
class Assembler, DiffMethod diffMethod = DiffMethod::numeric,
class Implementation =
void>
343template<
class TypeTag,
class Assembler,
class Implementation>
346 NonVoidOr<CVFELocalAssembler<TypeTag, Assembler, DiffMethod::numeric, Implementation>, Implementation>>
352 using ElementVolumeVariables =
typename GridVariables::GridVolumeVariables::LocalView;
359 static constexpr bool enableGridFluxVarsCache
360 = GridVariables::GridFluxVariablesCache::cachingEnabled;
361 static constexpr bool solutionDependentFluxVarsCache
362 = GridVariables::GridFluxVariablesCache::FluxVariablesCache::isSolDependent;
368 using ParentType::ParentType;
370 template <
class PartialReassembler = DefaultPartialReassembler>
376 assembleJacobianImplicit_(A, gridVariables, origResiduals, partialReassembler);
378 assembleJacobianExplicit_(A, gridVariables, origResiduals, partialReassembler);
388 template <
class PartialReassembler = DefaultPartialReassembler>
389 void assembleJacobianImplicit_(JacobianMatrix& A,
GridVariables& gridVariables,
390 const ElementResidualVector& origResiduals,
394 const auto& element = this->element();
395 const auto& fvGeometry = this->fvGeometry();
396 const auto& curSol = this->asImp_().curSol();
398 auto&& curElemVolVars = this->curElemVolVars();
399 auto&& elemFluxVarsCache = this->elemFluxVarsCache();
412 this->asImp_().problem().paramGroup(),
"Assembly.BoxVolVarsDependOnAllElementDofs",
false
420 ElementResidualVector partialDerivs(Dumux::Detail::LocalDofs::numLocalDofs(fvGeometry));
422 auto deflectionPolicy = Dumux::Detail::CVFE::makeVariablesDeflectionPolicy(
423 gridVariables.curGridVolVars(),
429 auto assembleDerivative = [&,
this](
const auto& localDof)
432 const auto dofIdx = localDof.dofIndex();
433 const auto localIdx = localDof.index();
434 deflectionPolicy.store(localDof);
437 for (
int pvIdx = 0; pvIdx < numEq; pvIdx++)
441 auto evalResiduals = [&](PrimaryVariable priVar)
444 elemSol[localIdx][pvIdx] = priVar;
445 deflectionPolicy.update(elemSol, localDof, this->asImp_().problem());
446 if constexpr (solutionDependentFluxVarsCache)
448 elemFluxVarsCache.update(element, fvGeometry, curElemVolVars);
449 if constexpr (enableGridFluxVarsCache)
450 gridVariables.gridFluxVarsCache().updateElement(element, fvGeometry, curElemVolVars);
452 this->asImp_().maybeUpdateCouplingContext(localDof, elemSol, pvIdx);
453 return this->evalLocalResidual();
457 static const NumericEpsilon<PrimaryVariable, numEq> eps_{this->asImp_().problem().paramGroup()};
458 static const int numDiffMethod =
getParamFromGroup<int>(this->asImp_().problem().paramGroup(),
"Assembly.NumericDifferenceMethod");
460 eps_(elemSol[localIdx][pvIdx], pvIdx), numDiffMethod);
463 for (
const auto& localDofJ :
localDofs(fvGeometry))
466 if (!partialReassembler
469 for (
int eqIdx = 0; eqIdx < numEq; eqIdx++)
475 A[localDofJ.dofIndex()][dofIdx][eqIdx][pvIdx] += partialDerivs[localDofJ.index()][eqIdx];
481 deflectionPolicy.restore(localDof);
484 elemSol[localIdx][pvIdx] = curSol[localDof.dofIndex()][pvIdx];
485 this->asImp_().maybeUpdateCouplingContext(localDof, elemSol, pvIdx);
490 for (
const auto& localDof :
localDofs(fvGeometry))
491 assembleDerivative(localDof);
495 if constexpr (enableGridFluxVarsCache)
496 gridVariables.gridFluxVarsCache().updateElement(element, fvGeometry, curElemVolVars);
499 this->asImp_().maybeEvalAdditionalDomainDerivatives(origResiduals, A, gridVariables);
507 template <
class PartialReassembler = DefaultPartialReassembler>
508 void assembleJacobianExplicit_(JacobianMatrix& A, GridVariables& gridVariables,
509 const ElementResidualVector& origResiduals,
510 const PartialReassembler* partialReassembler =
nullptr)
512 if (partialReassembler)
513 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for explicit time discretization");
517 const auto& fvGeometry = this->fvGeometry();
518 const auto& curSol = this->asImp_().curSol();
519 auto&& curElemVolVars = this->curElemVolVars();
526 ElementResidualVector partialDerivs(Dumux::Detail::LocalDofs::numLocalDofs(fvGeometry));
529 for (
const auto& scv :
scvs(fvGeometry))
532 const auto dofIdx = scv.dofIndex();
533 auto& curVolVars = this->getVolVarAccess(gridVariables.curGridVolVars(), curElemVolVars, scv);
534 const VolumeVariables origVolVars(curVolVars);
537 for (
int pvIdx = 0; pvIdx < numEq; pvIdx++)
541 auto evalStorage = [&](PrimaryVariable priVar)
543 elemSol[scv.localDofIndex()][pvIdx] = priVar;
544 curVolVars.update(elemSol, this->asImp_().problem(), element, scv);
545 return this->evalStorage();
549 static const NumericEpsilon<PrimaryVariable, numEq> eps_{this->asImp_().problem().paramGroup()};
550 static const int numDiffMethod =
getParamFromGroup<int>(this->asImp_().problem().paramGroup(),
"Assembly.NumericDifferenceMethod");
552 eps_(elemSol[scv.localDofIndex()][pvIdx], pvIdx), numDiffMethod);
555 for (
int eqIdx = 0; eqIdx < numEq; eqIdx++)
561 A[dofIdx][dofIdx][eqIdx][pvIdx] += partialDerivs[scv.localDofIndex()][eqIdx];
565 curVolVars = origVolVars;
568 elemSol[scv.localDofIndex()][pvIdx] = curSol[scv.dofIndex()][pvIdx];
A linear system assembler (residual and Jacobian) for general discretization schemes.
Definition assembly/assembler.hh:85
GetPropType< TypeTag, Properties::SolutionVector > SolutionVector
Definition assembly/assembler.hh:98
void assembleJacobian(JacobianMatrix &A, GridVariables &gridVariables, const ElementResidualVector &origResiduals, const PartialReassembler *partialReassembler=nullptr)
Definition experimental/assembly/cvfelocalassembler.hh:371
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition experimental/assembly/cvfelocalassembler.hh:367
typename ParentType::LocalResidual LocalResidual
Definition experimental/assembly/cvfelocalassembler.hh:366
A base class for all local CVFE assemblers.
Definition experimental/assembly/cvfelocalassembler.hh:58
void assembleJacobian(JacobianMatrix &jac, GridVariables &gridVariables)
Computes the derivatives with respect to the given element and adds them to the global matrix.
Definition experimental/assembly/cvfelocalassembler.hh:209
void bindLocalViews()
Definition experimental/assembly/cvfelocalassembler.hh:77
void assembleResidual(ResidualVector &res)
Assemble the residual only.
Definition experimental/assembly/cvfelocalassembler.hh:233
void assembleJacobianAndResidual(JacobianMatrix &jac, ResidualVector &res, GridVariables &gridVariables, const StageParams &stageParams, ResidualVector &temporal, ResidualVector &spatial, ResidualVector &constrainedDofs, const PartialReassembler *partialReassembler=nullptr, const CouplingFunction &maybeAssembleCouplingBlocks=noop)
Computes the derivatives with respect to the given element and adds them to the global matrix....
Definition experimental/assembly/cvfelocalassembler.hh:88
typename ParentType::LocalResidual LocalResidual
Definition experimental/assembly/cvfelocalassembler.hh:73
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition experimental/assembly/cvfelocalassembler.hh:74
void evalDirichletBoundaries(ApplyDirichletFunctionType applyDirichlet)
Evaluates Dirichlet boundaries.
Definition experimental/assembly/cvfelocalassembler.hh:282
void assembleCurrentResidual(ResidualVector &spatialRes, ResidualVector &temporalRes)
Assemble the residual only.
Definition experimental/assembly/cvfelocalassembler.hh:256
void maybeUpdateCouplingContext(Args &&...)
Update the coupling context for coupled models.
Definition experimental/assembly/cvfelocalassembler.hh:315
void maybeEvalAdditionalDomainDerivatives(Args &&...)
Update the additional domain derivatives for coupled models.
Definition experimental/assembly/cvfelocalassembler.hh:322
void enforceDirichletConstraints(const ApplyFunction &applyDirichlet)
Enforce Dirichlet constraints.
Definition experimental/assembly/cvfelocalassembler.hh:270
An assembler for Jacobian and residual contribution per element (CVFE methods).
Definition experimental/assembly/cvfelocalassembler.hh:335
A base class for all local assemblers.
Definition experimental/assembly/fvlocalassemblerbase.hh:38
ElementVolumeVariables & curElemVolVars()
The current element volume variables.
Definition experimental/assembly/fvlocalassemblerbase.hh:234
bool isImplicit() const
Definition experimental/assembly/fvlocalassemblerbase.hh:270
void bindLocalViews()
Convenience function bind and prepare all relevant variables required for the evaluation of the local...
Definition experimental/assembly/fvlocalassemblerbase.hh:163
ElementResidualVector evalLocalResidual() const
Convenience function to evaluate the complete local residual for the current element....
Definition experimental/assembly/fvlocalassemblerbase.hh:104
bool elementIsGhost() const
Returns if element is a ghost entity.
Definition experimental/assembly/fvlocalassemblerbase.hh:222
ElementResidualVector evalLocalFluxAndSourceResidual() const
Convenience function to evaluate the flux and source terms (i.e, the terms without a time derivative)...
Definition experimental/assembly/fvlocalassemblerbase.hh:133
const Problem & problem() const
The problem.
Definition experimental/assembly/fvlocalassemblerbase.hh:210
LocalResidual & localResidual()
The local residual for the current element.
Definition experimental/assembly/fvlocalassemblerbase.hh:242
const Element & element() const
The current element.
Definition experimental/assembly/fvlocalassemblerbase.hh:218
FVElementGeometry & fvGeometry()
The global finite volume geometry.
Definition experimental/assembly/fvlocalassemblerbase.hh:230
Implementation & asImp_()
Definition experimental/assembly/fvlocalassemblerbase.hh:274
ElementBoundaryTypes & elemBcTypes()
The element's boundary types.
Definition experimental/assembly/fvlocalassemblerbase.hh:246
std::decay_t< decltype(std::declval< Assembler >().localResidual())> LocalResidual
Definition experimental/assembly/fvlocalassemblerbase.hh:57
The grid variables class for general schemes, storing variables and data.
Definition discretization/gridvariables.hh:27
ReservedBlockVector< NumEqVector, Dumux::Detail::LocalDofs::maxNumLocalDofs< ElementDiscretization >()> ElementResidualVector
the container storing all element residuals
Definition assembly/localresidual.hh:56
static void partialDerivative(const Function &function, Scalar x0, FunctionEvalType &derivative, const FunctionEvalType &fx0, const int numericDifferenceMethod=1)
Computes the derivative of a function with respect to a function parameter.
Definition numericdifferentiation.hh:56
detects which entries in the Jacobian have to be recomputed
Definition partialreassembler.hh:418
Defines all properties used in Dumux.
The local element solution class for control-volume finite element methods.
An enum class to define various differentiation methods available in order to compute the derivatives...
An enum class to define the colors of elements and vertices required for partial Jacobian reassembly.
A base class for all local assemblers.
Type traits for classes providing a grid discretization.
DiffMethod
Differentiation methods in order to compute the derivatives of the residual i.e. the entries in the j...
Definition diffmethod.hh:25
@ numeric
Definition diffmethod.hh:26
@ green
does not need to be reassembled
Definition entitycolor.hh:40
auto elementSolution(const Element &element, const SolutionVector &sol, const GridGeometry &gg) -> std::enable_if_t< GridGeometry::discMethod==DiscretizationMethods::cctpfa||GridGeometry::discMethod==DiscretizationMethods::ccmpfa, CCElementSolution< typename GridGeometry::LocalView, std::decay_t< decltype(std::declval< SolutionVector >()[0])> > >
Make an element solution for cell-centered schemes.
Definition cellcentered/elementsolution.hh:101
T getParamFromGroup(Args &&... args)
A free function to get a parameter from the parameter tree singleton with a model group.
Definition parameters.hh:165
typename GetProp< TypeTag, Property >::type GetPropType
get the type alias defined in the property
Definition propertysystem.hh:296
decltype(auto) gridDiscretization(const T &t, Args &&... args)
The grid discretization.
Definition griddiscretization.hh:65
Class representing dofs on elements for control-volume finite element schemes.
Adapter to expose a multi-DOF mapper interface for single- and multi-DOF mappers.
Definition assembly/assembler.hh:46
constexpr auto asMultiMapper(const Mapper &mapper)
Definition multimapperview.hh:48
constexpr auto noop
Function that performs no operation.
Definition common/typetraits/typetraits.hh:29
std::ranges::range auto scvs(const FVElementGeometry &fvGeometry, const LocalDof &localDof)
Definition localdof.hh:82
auto localDofs(const FVElementGeometry &fvGeometry)
range over local dofs
Definition localdof.hh:50
A class for numeric differentiation.
An adapter class for local assemblers using numeric differentiation.
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.
Detects which entries in the Jacobian have to be recomputed.