13#ifndef DUMUX_CVFE_LOCAL_ASSEMBLER_HH
14#define DUMUX_CVFE_LOCAL_ASSEMBLER_HH
16#include <dune/common/exceptions.hh>
17#include <dune/common/hybridutilities.hh>
18#include <dune/common/reservedvector.hh>
19#include <dune/grid/common/gridenums.hh>
20#include <dune/istl/matrixindexset.hh>
21#include <dune/istl/bvector.hh>
26#include <dumux/common/typetraits/localdofs_.hh>
27#include <dumux/common/typetraits/boundary_.hh>
38#include "cvfevolvarsdeflectionpolicy_.hh"
43namespace Detail::CVFE {
47 template<
class... Args>
48 constexpr void operator()(Args&&...)
const {}
51template<
class X,
class Y>
52using Impl = std::conditional_t<!std::is_same_v<X, void>, X, Y>;
66template<
class TypeTag,
class Assembler,
class Implementation,
bool implicit>
73 using GridVolumeVariables =
typename GridVariables::GridVolumeVariables;
74 using ElementVolumeVariables =
typename GridVariables::GridVolumeVariables::LocalView;
76 using SolutionVector =
typename Assembler::SolutionVector;
78 using FVElementGeometry =
typename GridGeometry::LocalView;
81 static constexpr int dim = GridGeometry::GridView::dimension;
85 using ParentType::ParentType;
98 template <
class Res
idualVector,
class PartialReassembler = DefaultPartialReassembler,
class CouplingFunction = Detail::CVFE::NoOperator>
101 const CouplingFunction& maybeAssembleCouplingBlocks = {})
103 this->
asImp_().bindLocalViews();
104 const auto eIdxGlobal = this->
asImp_().problem().gridGeometry().elementMapper().index(this->
element());
105 if (partialReassembler
108 const auto residual = this->
asImp_().evalLocalResidual();
111 res[localDof.dofIndex()] += residual[localDof.index()];
114 maybeAssembleCouplingBlocks(residual);
118 const auto residual = this->
asImp_().assembleJacobianAndResidualImpl(jac, gridVariables, partialReassembler);
121 res[localDof.dofIndex()] += residual[localDof.index()];
124 maybeAssembleCouplingBlocks(residual);
132 const auto& gridGeometry = this->
asImp_().problem().gridGeometry();
133 Dune::Hybrid::forEach(std::make_integer_sequence<int, dim>{}, [&](
auto d)
135 constexpr int codim = dim - d;
136 const auto& localCoeffs = gridGeometry.feCache().get(this->
element().type()).localCoefficients();
137 for (
int idx = 0; idx < localCoeffs.size(); ++idx)
139 const auto& localKey = localCoeffs.localKey(idx);
142 if (localKey.codim() != codim)
146 auto entity = this->
element().template subEntity<codim>(localKey.subEntity());
147 if (entity.partitionType() == Dune::InteriorEntity || entity.partitionType() == Dune::BorderEntity)
154 const auto dofIndex = gridGeometry.dofMapper().index(entity);
157 using BlockType =
typename JacobianMatrix::block_type;
158 BlockType &J = jac[dofIndex][dofIndex];
159 for (
int j = 0; j < BlockType::rows; ++j)
168 auto applyDirichlet = [&] (
const auto& scvOrLocalDofI,
169 const auto& dirichletValues,
173 res[scvOrLocalDofI.dofIndex()][eqIdx] = this->
curElemVolVars()[scvOrLocalDofI].priVars()[pvIdx] - dirichletValues[pvIdx];
175 auto& row = jac[scvOrLocalDofI.dofIndex()];
176 for (
auto col = row.begin(); col != row.end(); ++col)
177 row[col.index()][eqIdx] = 0.0;
179 jac[scvOrLocalDofI.dofIndex()][scvOrLocalDofI.dofIndex()][eqIdx][pvIdx] = 1.0;
182 if (this->
asImp_().
problem().gridGeometry().dofOnPeriodicBoundary(scvOrLocalDofI.dofIndex()))
184 const auto periodicDof = this->
asImp_().problem().gridGeometry().periodicallyMappedDof(scvOrLocalDofI.dofIndex());
185 res[periodicDof][eqIdx] = this->
asImp_().curSol()[periodicDof][pvIdx] - dirichletValues[pvIdx];
187 auto& rowP = jac[periodicDof];
188 for (
auto col = rowP.begin(); col != rowP.end(); ++col)
189 rowP[col.index()][eqIdx] = 0.0;
191 rowP[periodicDof][eqIdx][pvIdx] = 1.0;
195 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
204 this->
asImp_().bindLocalViews();
205 this->
asImp_().assembleJacobianAndResidualImpl(jac, gridVariables);
207 auto applyDirichlet = [&] (
const auto& scvOrLocalDofI,
208 const auto& dirichletValues,
212 auto& row = jac[scvOrLocalDofI.dofIndex()];
213 for (
auto col = row.begin(); col != row.end(); ++col)
214 row[col.index()][eqIdx] = 0.0;
216 jac[scvOrLocalDofI.dofIndex()][scvOrLocalDofI.dofIndex()][eqIdx][pvIdx] = 1.0;
219 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
225 template <
class Res
idualVector>
228 this->
asImp_().bindLocalViews();
232 res[localDof.dofIndex()] += residual[localDof.index()];
234 auto applyDirichlet = [&] (
const auto& scvOrLocalDofI,
235 const auto& dirichletValues,
239 res[scvOrLocalDofI.dofIndex()][eqIdx] = this->
curElemVolVars()[scvOrLocalDofI].priVars()[pvIdx] - dirichletValues[pvIdx];
242 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
246 template<
typename ApplyFunction>
250 this->
asImp_().evalDirichletBoundaries(applyDirichlet);
252 this->
asImp_().enforceInternalDirichletConstraints(applyDirichlet);
258 template<
typename ApplyDirichletFunctionType >
264 if constexpr (!Detail::hasProblemBoundaryTypesForIntersectionFunction<Problem, FVElementGeometry, typename GridGeometry::GridView::Intersection>())
271 if (bcTypes.hasDirichlet())
273 const auto dirichletValues = this->
asImp_().problem().dirichlet(this->
element(), scvI);
276 for (
int eqIdx = 0; eqIdx < numEq; ++eqIdx)
278 if (bcTypes.isDirichlet(eqIdx))
280 const auto pvIdx = bcTypes.eqToDirichletIndex(eqIdx);
281 assert(0 <= pvIdx && pvIdx < numEq);
282 applyDirichlet(scvI, dirichletValues, eqIdx, pvIdx);
295 template<
class... Args>
302 template<
class... Args>
316template<
class TypeTag,
class Assembler, DiffMethod diffMethod = DiffMethod::numeric,
bool implicit = true,
class Implementation =
void>
324template<
class TypeTag,
class Assembler,
class Implementation>
327 Detail::CVFE::Impl<Implementation, CVFELocalAssembler<TypeTag, Assembler, DiffMethod::numeric, true, Implementation>>,
335 using ElementVolumeVariables =
typename GridVariables::GridVolumeVariables::LocalView;
342 static constexpr bool enableGridFluxVarsCache
343 = GridVariables::GridFluxVariablesCache::cachingEnabled;
344 static constexpr bool solutionDependentFluxVarsCache
345 = GridVariables::GridFluxVariablesCache::FluxVariablesCache::isSolDependent;
359 template <
class PartialReassembler = DefaultPartialReassembler>
364 const auto& element = this->element();
365 const auto& fvGeometry = this->fvGeometry();
366 const auto& curSol = this->asImp_().curSol();
368 auto&& curElemVolVars = this->curElemVolVars();
369 auto&& elemFluxVarsCache = this->elemFluxVarsCache();
372 const auto origResiduals = this->evalLocalResidual();
384 static const bool updateAllVolVars = getParamFromGroup<bool>(
385 this->asImp_().problem().paramGroup(),
"Assembly.BoxVolVarsDependOnAllElementDofs",
false
389 auto elemSol =
elementSolution(element, curSol, fvGeometry.gridGeometry());
394 auto deflectionPolicy = Detail::CVFE::makeVariablesDeflectionPolicy(
395 gridVariables.curGridVolVars(),
401 auto assembleDerivative = [&,
this](
const auto& localDof)
404 const auto dofIdx = localDof.dofIndex();
405 const auto localIdx = localDof.index();
406 deflectionPolicy.store(localDof);
409 for (
int pvIdx = 0; pvIdx < numEq; pvIdx++)
413 auto evalResiduals = [&](Scalar priVar)
416 elemSol[localIdx][pvIdx] = priVar;
417 deflectionPolicy.update(elemSol, localDof, this->asImp_().problem());
418 if constexpr (solutionDependentFluxVarsCache)
420 elemFluxVarsCache.update(element, fvGeometry, curElemVolVars);
421 if constexpr (enableGridFluxVarsCache)
422 gridVariables.gridFluxVarsCache().updateElement(element, fvGeometry, curElemVolVars);
424 this->asImp_().maybeUpdateCouplingContext(localDof, elemSol, pvIdx);
425 return this->evalLocalResidual();
430 static const int numDiffMethod = getParamFromGroup<int>(this->asImp_().problem().paramGroup(),
"Assembly.NumericDifferenceMethod");
432 eps_(elemSol[localIdx][pvIdx], pvIdx), numDiffMethod);
435 for (
const auto& localDofJ :
localDofs(fvGeometry))
438 if (!partialReassembler
441 for (
int eqIdx = 0; eqIdx < numEq; eqIdx++)
447 A[localDofJ.dofIndex()][dofIdx][eqIdx][pvIdx] += partialDerivs[localDofJ.index()][eqIdx];
453 deflectionPolicy.restore(localDof);
456 elemSol[localIdx][pvIdx] = curSol[localDof.dofIndex()][pvIdx];
457 this->asImp_().maybeUpdateCouplingContext(localDof, elemSol, pvIdx);
462 for (
const auto& localDof :
localDofs(fvGeometry))
463 assembleDerivative(localDof);
467 if constexpr (enableGridFluxVarsCache)
468 gridVariables.gridFluxVarsCache().updateElement(element, fvGeometry, curElemVolVars);
471 this->asImp_().maybeEvalAdditionalDomainDerivatives(origResiduals, A, gridVariables);
473 return origResiduals;
483template<
class TypeTag,
class Assembler,
class Implementation>
486 Detail::CVFE::Impl<Implementation, CVFELocalAssembler<TypeTag, Assembler, DiffMethod::numeric, false, Implementation>>,
511 template <
class PartialReassembler = DefaultPartialReassembler>
515 if (partialReassembler)
516 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for explicit time discretization");
519 const auto& element = this->element();
520 const auto& fvGeometry = this->fvGeometry();
521 const auto& curSol = this->asImp_().curSol();
522 auto&& curElemVolVars = this->curElemVolVars();
525 const auto origResiduals = this->evalLocalResidual();
526 const auto origStorageResiduals = this->evalLocalStorageResidual();
537 auto elemSol =
elementSolution(element, curSol, fvGeometry.gridGeometry());
543 for (
const auto& scv :
scvs(fvGeometry))
546 const auto localIdx = scv.localDofIndex();
547 const auto dofIdx = scv.dofIndex();
548 auto& curVolVars = this->getVolVarAccess(gridVariables.curGridVolVars(), curElemVolVars, scv);
549 const VolumeVariables origVolVars(curVolVars);
552 for (
int pvIdx = 0; pvIdx < numEq; pvIdx++)
556 auto evalStorage = [&](Scalar priVar)
559 elemSol[localIdx][pvIdx] = priVar;
560 curVolVars.update(elemSol, this->asImp_().problem(), element, scv);
561 return this->evalLocalStorageResidual();
566 static const int numDiffMethod = getParamFromGroup<int>(this->asImp_().problem().paramGroup(),
"Assembly.NumericDifferenceMethod");
568 eps_(elemSol[localIdx][pvIdx], pvIdx), numDiffMethod);
571 for (
int eqIdx = 0; eqIdx < numEq; eqIdx++)
577 A[dofIdx][dofIdx][eqIdx][pvIdx] += partialDerivs[localIdx][eqIdx];
581 curVolVars = origVolVars;
584 elemSol[localIdx][pvIdx] = curSol[dofIdx][pvIdx];
589 return origResiduals;
598template<
class TypeTag,
class Assembler,
class Implementation>
601 Detail::CVFE::Impl<Implementation, CVFELocalAssembler<TypeTag, Assembler, DiffMethod::analytic, true, Implementation>>,
621 template <
class PartialReassembler = DefaultPartialReassembler>
625 if (partialReassembler)
626 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for analytic differentiation");
629 const auto& element = this->element();
630 const auto& fvGeometry = this->fvGeometry();
631 const auto& problem = this->asImp_().problem();
632 const auto& curElemVolVars = this->curElemVolVars();
633 const auto& elemFluxVarsCache = this->elemFluxVarsCache();
636 const auto origResiduals = this->evalLocalResidual();
647 for (
const auto& scv :
scvs(fvGeometry))
650 const auto dofIdx = scv.dofIndex();
651 const auto& volVars = curElemVolVars[scv];
656 if (!this->assembler().isStationaryProblem())
657 this->localResidual().addStorageDerivatives(A[dofIdx][dofIdx],
666 this->localResidual().addSourceDerivatives(A[dofIdx][dofIdx],
675 for (
const auto& scvf : scvfs(fvGeometry))
677 if (!scvf.boundary())
680 this->localResidual().addFluxDerivatives(A,
693 const auto& insideScv = fvGeometry.scv(scvf.insideScvIdx());
694 if (this->elemBcTypes().get(fvGeometry, insideScv).hasNeumann())
697 this->localResidual().addRobinFluxDerivatives(A[insideScv.dofIndex()],
708 return origResiduals;
718template<
class TypeTag,
class Assembler,
class Implementation>
721 Detail::CVFE::Impl<Implementation, CVFELocalAssembler<TypeTag, Assembler, DiffMethod::analytic, false, Implementation>>,
741 template <
class PartialReassembler = DefaultPartialReassembler>
745 if (partialReassembler)
746 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for explicit time discretization");
749 const auto& element = this->element();
750 const auto& fvGeometry = this->fvGeometry();
751 const auto& problem = this->asImp_().problem();
752 const auto& curElemVolVars = this->curElemVolVars();
755 const auto origResiduals = this->evalLocalResidual();
766 for (
const auto& scv :
scvs(fvGeometry))
769 const auto dofIdx = scv.dofIndex();
770 const auto& volVars = curElemVolVars[scv];
774 this->localResidual().addStorageDerivatives(A[dofIdx][dofIdx],
782 return origResiduals;
Control volume finite element local assembler using analytic differentiation and explicit time discre...
Definition: assembly/cvfelocalassembler.hh:723
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition: assembly/cvfelocalassembler.hh:732
ElementResidualVector assembleJacobianAndResidualImpl(JacobianMatrix &A, GridVariables &gridVariables, const PartialReassembler *partialReassembler=nullptr)
Computes the derivatives with respect to the given element and adds them to the global matrix.
Definition: assembly/cvfelocalassembler.hh:742
typename ParentType::LocalResidual LocalResidual
Definition: assembly/cvfelocalassembler.hh:731
Control volume finite element local assembler using analytic differentiation and implicit time discre...
Definition: assembly/cvfelocalassembler.hh:603
ElementResidualVector assembleJacobianAndResidualImpl(JacobianMatrix &A, GridVariables &gridVariables, const PartialReassembler *partialReassembler=nullptr)
Computes the derivatives with respect to the given element and adds them to the global matrix.
Definition: assembly/cvfelocalassembler.hh:622
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition: assembly/cvfelocalassembler.hh:612
typename ParentType::LocalResidual LocalResidual
Definition: assembly/cvfelocalassembler.hh:611
Control volume finite element local assembler using numeric differentiation and implicit time discret...
Definition: assembly/cvfelocalassembler.hh:329
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition: assembly/cvfelocalassembler.hh:350
typename ParentType::LocalResidual LocalResidual
Definition: assembly/cvfelocalassembler.hh:349
ElementResidualVector assembleJacobianAndResidualImpl(JacobianMatrix &A, GridVariables &gridVariables, const PartialReassembler *partialReassembler=nullptr)
Computes the derivatives with respect to the given element and adds them to the global matrix.
Definition: assembly/cvfelocalassembler.hh:360
Control volume finite element local assembler using numeric differentiation and explicit time discret...
Definition: assembly/cvfelocalassembler.hh:488
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition: assembly/cvfelocalassembler.hh:502
ElementResidualVector assembleJacobianAndResidualImpl(JacobianMatrix &A, GridVariables &gridVariables, const PartialReassembler *partialReassembler=nullptr)
Computes the derivatives with respect to the given element and adds them to the global matrix.
Definition: assembly/cvfelocalassembler.hh:512
typename ParentType::LocalResidual LocalResidual
Definition: assembly/cvfelocalassembler.hh:501
A base class for all local CVFE assemblers.
Definition: assembly/cvfelocalassembler.hh:68
void enforceDirichletConstraints(const ApplyFunction &applyDirichlet)
Enforce Dirichlet constraints.
Definition: assembly/cvfelocalassembler.hh:247
void assembleResidual(ResidualVector &res)
Assemble the residual only.
Definition: assembly/cvfelocalassembler.hh:226
void maybeUpdateCouplingContext(Args &&...)
Update the coupling context for coupled models.
Definition: assembly/cvfelocalassembler.hh:296
void assembleJacobian(JacobianMatrix &jac, GridVariables &gridVariables)
Computes the derivatives with respect to the given element and adds them to the global matrix.
Definition: assembly/cvfelocalassembler.hh:202
void evalDirichletBoundaries(ApplyDirichletFunctionType applyDirichlet)
Evaluates Dirichlet boundaries.
Definition: assembly/cvfelocalassembler.hh:259
void assembleJacobianAndResidual(JacobianMatrix &jac, ResidualVector &res, GridVariables &gridVariables, const PartialReassembler *partialReassembler=nullptr, const CouplingFunction &maybeAssembleCouplingBlocks={})
Computes the derivatives with respect to the given element and adds them to the global matrix....
Definition: assembly/cvfelocalassembler.hh:99
void bindLocalViews()
Definition: assembly/cvfelocalassembler.hh:87
void maybeEvalAdditionalDomainDerivatives(Args &&...)
Update the additional domain derivatives for coupled models.
Definition: assembly/cvfelocalassembler.hh:303
An assembler for Jacobian and residual contribution per element (CVFE methods)
Definition: assembly/cvfelocalassembler.hh:317
A base class for all local assemblers.
Definition: assembly/fvlocalassemblerbase.hh:36
void bindLocalViews()
Convenience function bind and prepare all relevant variables required for the evaluation of the local...
Definition: assembly/fvlocalassemblerbase.hh:173
ElementVolumeVariables & curElemVolVars()
The current element volume variables.
Definition: assembly/fvlocalassemblerbase.hh:253
ElementBoundaryTypes & elemBcTypes()
The element's boundary types.
Definition: assembly/fvlocalassemblerbase.hh:269
Implementation & asImp_()
Definition: assembly/fvlocalassemblerbase.hh:297
ElementResidualVector evalLocalResidual() const
Convenience function to evaluate the complete local residual for the current element....
Definition: assembly/fvlocalassemblerbase.hh:108
const Problem & problem() const
The problem.
Definition: assembly/fvlocalassemblerbase.hh:229
FVElementGeometry & fvGeometry()
The global finite volume geometry.
Definition: assembly/fvlocalassemblerbase.hh:249
bool elementIsGhost() const
Returns if element is a ghost entity.
Definition: assembly/fvlocalassemblerbase.hh:241
std::decay_t< decltype(std::declval< Assembler >().localResidual())> LocalResidual
Definition: assembly/fvlocalassemblerbase.hh:55
const Element & element() const
The current element.
Definition: assembly/fvlocalassemblerbase.hh:237
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:50
A helper class for local assemblers using numeric differentiation to determine the epsilon.
Definition: numericepsilon.hh:29
detects which entries in the Jacobian have to be recomputed
Definition: partialreassembler.hh:420
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.
DiffMethod
Differentiation methods in order to compute the derivatives of the residual i.e. the entries in the j...
Definition: diffmethod.hh:25
@ green
does not need to be reassembled
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
typename GetProp< TypeTag, Property >::type GetPropType
get the type alias defined in the property
Definition: propertysystem.hh:296
Class representing dofs on elements for control-volume finite element schemes.
std::ranges::range auto scvs(const FVElementGeometry &fvGeometry, const LocalDof &localDof)
Definition: localdof.hh:79
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.