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>
28#include <dumux/common/typetraits/localdofs_.hh>
29#include <dumux/common/typetraits/boundary_.hh>
40#include "cvfevolvarsdeflectionpolicy_.hh"
49 template<
class... Args>
50 constexpr void operator()(Args&&...)
const {}
53template<
class X,
class Y>
54using Impl = std::conditional_t<!std::is_same_v<X, void>, X, Y>;
68template<
class TypeTag,
class Assembler,
class Implementation,
bool implicit>
75 using GridVolumeVariables =
typename GridVariables::GridVolumeVariables;
76 using ElementVolumeVariables =
typename GridVariables::GridVolumeVariables::LocalView;
78 using SolutionVector =
typename Assembler::SolutionVector;
80 using FVElementGeometry =
typename GridGeometry::LocalView;
83 static constexpr int dim = GridGeometry::GridView::dimension;
87 using ParentType::ParentType;
100 template <
class Res
idualVector,
class PartialReassembler = DefaultPartialReassembler,
class CouplingFunction = Detail::CVFE::NoOperator>
103 const CouplingFunction& maybeAssembleCouplingBlocks = {})
105 this->
asImp_().bindLocalViews();
106 const auto eIdxGlobal = this->
asImp_().problem().gridGeometry().elementMapper().index(this->
element());
107 if (partialReassembler
110 const auto residual = this->
asImp_().evalLocalResidual();
113 res[localDof.dofIndex()] += residual[localDof.index()];
116 maybeAssembleCouplingBlocks(residual);
120 const auto residual = this->
asImp_().assembleJacobianAndResidualImpl(jac, gridVariables, partialReassembler);
123 res[localDof.dofIndex()] += residual[localDof.index()];
126 maybeAssembleCouplingBlocks(residual);
134 const auto& gridGeometry = this->
asImp_().problem().gridGeometry();
135 Dune::Hybrid::forEach(std::make_integer_sequence<int, dim+1>{}, [&](
auto d)
137 constexpr int codim = dim - d;
138 const auto& localCoeffs = gridGeometry.feCache().get(this->
element().type()).localCoefficients();
139 for (
int idx = 0; idx < localCoeffs.size(); ++idx)
141 const auto& localKey = localCoeffs.localKey(idx);
144 if (localKey.codim() != codim)
148 auto entity = this->
element().template subEntity<codim>(localKey.subEntity());
149 if (entity.partitionType() == Dune::InteriorEntity || entity.partitionType() == Dune::BorderEntity)
155 using BlockType =
typename JacobianMatrix::block_type;
156 for (
const auto dofIndex :
asMultiMapper(gridGeometry.dofMapper()).indices(entity))
158 BlockType &J = jac[dofIndex][dofIndex];
159 for (
int j = 0; j < BlockType::rows; ++j)
167 auto applyDirichlet = [&] (
const auto& scvOrLocalDofI,
168 const auto& dirichletValues,
172 res[scvOrLocalDofI.dofIndex()][eqIdx] = this->
curElemVolVars()[scvOrLocalDofI].priVars()[pvIdx] - dirichletValues[pvIdx];
174 auto& row = jac[scvOrLocalDofI.dofIndex()];
175 for (
auto col = row.begin(); col != row.end(); ++col)
176 row[col.index()][eqIdx] = 0.0;
178 jac[scvOrLocalDofI.dofIndex()][scvOrLocalDofI.dofIndex()][eqIdx][pvIdx] = 1.0;
181 if (this->
asImp_().
problem().gridGeometry().dofOnPeriodicBoundary(scvOrLocalDofI.dofIndex()))
183 const auto periodicDof = this->
asImp_().problem().gridGeometry().periodicallyMappedDof(scvOrLocalDofI.dofIndex());
184 res[periodicDof][eqIdx] = this->
asImp_().curSol()[periodicDof][pvIdx] - dirichletValues[pvIdx];
186 auto& rowP = jac[periodicDof];
187 for (
auto col = rowP.begin(); col != rowP.end(); ++col)
188 rowP[col.index()][eqIdx] = 0.0;
190 rowP[periodicDof][eqIdx][pvIdx] = 1.0;
194 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
203 this->
asImp_().bindLocalViews();
204 this->
asImp_().assembleJacobianAndResidualImpl(jac, gridVariables);
206 auto applyDirichlet = [&] (
const auto& scvOrLocalDofI,
207 const auto& dirichletValues,
211 auto& row = jac[scvOrLocalDofI.dofIndex()];
212 for (
auto col = row.begin(); col != row.end(); ++col)
213 row[col.index()][eqIdx] = 0.0;
215 jac[scvOrLocalDofI.dofIndex()][scvOrLocalDofI.dofIndex()][eqIdx][pvIdx] = 1.0;
218 if (this->
asImp_().
problem().gridGeometry().dofOnPeriodicBoundary(scvOrLocalDofI.dofIndex()))
220 const auto periodicDof = this->
asImp_().problem().gridGeometry().periodicallyMappedDof(scvOrLocalDofI.dofIndex());
222 auto& rowP = jac[periodicDof];
223 for (
auto col = rowP.begin(); col != rowP.end(); ++col)
224 rowP[col.index()][eqIdx] = 0.0;
226 rowP[periodicDof][eqIdx][pvIdx] = 1.0;
230 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
236 template <
class Res
idualVector>
239 this->
asImp_().bindLocalViews();
243 res[localDof.dofIndex()] += residual[localDof.index()];
245 auto applyDirichlet = [&] (
const auto& scvOrLocalDofI,
246 const auto& dirichletValues,
250 res[scvOrLocalDofI.dofIndex()][eqIdx] = this->
curElemVolVars()[scvOrLocalDofI].priVars()[pvIdx] - dirichletValues[pvIdx];
253 if (this->
asImp_().
problem().gridGeometry().dofOnPeriodicBoundary(scvOrLocalDofI.dofIndex()))
255 const auto periodicDof = this->
asImp_().problem().gridGeometry().periodicallyMappedDof(scvOrLocalDofI.dofIndex());
256 res[periodicDof][eqIdx] = this->
asImp_().curSol()[periodicDof][pvIdx] - dirichletValues[pvIdx];
260 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
264 template<
typename ApplyFunction>
268 this->
asImp_().evalDirichletBoundaries(applyDirichlet);
270 this->
asImp_().enforceInternalDirichletConstraints(applyDirichlet);
276 template<
typename ApplyDirichletFunctionType >
282 if constexpr (!Detail::hasProblemBoundaryTypesForFaceFunction<Problem, FVElementGeometry>())
289 if (bcTypes.hasDirichlet())
291 const auto dirichletValues = this->
asImp_().problem().dirichlet(this->
element(), scvI);
294 for (
int eqIdx = 0; eqIdx < numEq; ++eqIdx)
296 if (bcTypes.isDirichlet(eqIdx))
298 const auto pvIdx = bcTypes.eqToDirichletIndex(eqIdx);
299 assert(0 <= pvIdx && pvIdx < numEq);
300 applyDirichlet(scvI, dirichletValues, eqIdx, pvIdx);
313 template<
class... Args>
320 template<
class... Args>
334template<
class TypeTag,
class Assembler, DiffMethod diffMethod = DiffMethod::numeric,
bool implicit = true,
class Implementation =
void>
342template<
class TypeTag,
class Assembler,
class Implementation>
345 Detail::CVFE::Impl<Implementation, CVFELocalAssembler<TypeTag, Assembler, DiffMethod::numeric, true, Implementation>>,
353 using ElementVolumeVariables =
typename GridVariables::GridVolumeVariables::LocalView;
360 static constexpr bool enableGridFluxVarsCache
361 = GridVariables::GridFluxVariablesCache::cachingEnabled;
362 static constexpr bool solutionDependentFluxVarsCache
363 = GridVariables::GridFluxVariablesCache::FluxVariablesCache::isSolDependent;
369 using ParentType::ParentType;
377 template <
class PartialReassembler = DefaultPartialReassembler>
403 this->
asImp_().
problem().paramGroup(),
"Assembly.BoxVolVarsDependOnAllElementDofs",
false
413 auto deflectionPolicy = Detail::CVFE::makeVariablesDeflectionPolicy(
414 gridVariables.curGridVolVars(),
420 auto assembleDerivative = [&,
this](
const auto& localDof)
423 const auto dofIdx = localDof.dofIndex();
424 const auto localIdx = localDof.index();
425 deflectionPolicy.store(localDof);
428 for (
int pvIdx = 0; pvIdx < numEq; pvIdx++)
432 auto evalResiduals = [&](PrimaryVariable priVar)
435 elemSol[localIdx][pvIdx] = priVar;
436 deflectionPolicy.update(elemSol, localDof, this->
asImp_().
problem());
437 if constexpr (solutionDependentFluxVarsCache)
440 if constexpr (enableGridFluxVarsCache)
443 this->
asImp_().maybeUpdateCouplingContext(localDof, elemSol, pvIdx);
451 eps_(elemSol[localIdx][pvIdx], pvIdx), numDiffMethod);
457 if (!partialReassembler
460 for (
int eqIdx = 0; eqIdx < numEq; eqIdx++)
466 A[localDofJ.dofIndex()][dofIdx][eqIdx][pvIdx] += partialDerivs[localDofJ.index()][eqIdx];
472 deflectionPolicy.restore(localDof);
475 elemSol[localIdx][pvIdx] =
curSol[localDof.dofIndex()][pvIdx];
476 this->
asImp_().maybeUpdateCouplingContext(localDof, elemSol, pvIdx);
482 assembleDerivative(localDof);
486 if constexpr (enableGridFluxVarsCache)
490 this->
asImp_().maybeEvalAdditionalDomainDerivatives(origResiduals, A, gridVariables);
492 return origResiduals;
502template<
class TypeTag,
class Assembler,
class Implementation>
505 Detail::CVFE::Impl<Implementation, CVFELocalAssembler<TypeTag, Assembler, DiffMethod::numeric, false, Implementation>>,
522 using ParentType::ParentType;
530 template <
class PartialReassembler = DefaultPartialReassembler>
534 if (partialReassembler)
535 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for explicit time discretization");
566 const auto localIdx = scv.localDofIndex();
567 const auto dofIdx = scv.dofIndex();
569 const VolumeVariables origVolVars(curVolVars);
572 for (
int pvIdx = 0; pvIdx < numEq; pvIdx++)
576 auto evalStorage = [&](PrimaryVariable priVar)
579 elemSol[localIdx][pvIdx] = priVar;
588 eps_(elemSol[localIdx][pvIdx], pvIdx), numDiffMethod);
591 for (
int eqIdx = 0; eqIdx < numEq; eqIdx++)
597 A[dofIdx][dofIdx][eqIdx][pvIdx] += partialDerivs[localIdx][eqIdx];
601 curVolVars = origVolVars;
604 elemSol[localIdx][pvIdx] =
curSol[dofIdx][pvIdx];
609 return origResiduals;
618template<
class TypeTag,
class Assembler,
class Implementation>
621 Detail::CVFE::Impl<Implementation, CVFELocalAssembler<TypeTag, Assembler, DiffMethod::analytic, true, Implementation>>,
633 using ParentType::ParentType;
641 template <
class PartialReassembler = DefaultPartialReassembler>
645 if (partialReassembler)
646 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for analytic differentiation");
670 const auto dofIdx = scv.dofIndex();
676 if (!this->
assembler().isStationaryProblem())
677 this->
localResidual().addStorageDerivatives(A[dofIdx][dofIdx],
686 this->
localResidual().addSourceDerivatives(A[dofIdx][dofIdx],
697 if (!scvf.boundary())
713 const auto& insideScv =
fvGeometry.scv(scvf.insideScvIdx());
717 this->
localResidual().addRobinFluxDerivatives(A[insideScv.dofIndex()],
728 return origResiduals;
738template<
class TypeTag,
class Assembler,
class Implementation>
741 Detail::CVFE::Impl<Implementation, CVFELocalAssembler<TypeTag, Assembler, DiffMethod::analytic, false, Implementation>>,
753 using ParentType::ParentType;
761 template <
class PartialReassembler = DefaultPartialReassembler>
765 if (partialReassembler)
766 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for explicit time discretization");
789 const auto dofIdx = scv.dofIndex();
794 this->
localResidual().addStorageDerivatives(A[dofIdx][dofIdx],
802 return origResiduals;
A base class for all local assemblers.
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition assembly/cvfelocalassembler.hh:752
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:762
typename ParentType::LocalResidual LocalResidual
Definition assembly/cvfelocalassembler.hh:751
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:642
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition assembly/cvfelocalassembler.hh:632
typename ParentType::LocalResidual LocalResidual
Definition assembly/cvfelocalassembler.hh:631
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition assembly/cvfelocalassembler.hh:368
typename ParentType::LocalResidual LocalResidual
Definition assembly/cvfelocalassembler.hh:367
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:378
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition assembly/cvfelocalassembler.hh:521
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:531
typename ParentType::LocalResidual LocalResidual
Definition assembly/cvfelocalassembler.hh:520
A base class for all local CVFE assemblers.
Definition assembly/cvfelocalassembler.hh:70
void enforceDirichletConstraints(const ApplyFunction &applyDirichlet)
Enforce Dirichlet constraints.
Definition assembly/cvfelocalassembler.hh:265
void assembleResidual(ResidualVector &res)
Assemble the residual only.
Definition assembly/cvfelocalassembler.hh:237
void maybeUpdateCouplingContext(Args &&...)
Update the coupling context for coupled models.
Definition assembly/cvfelocalassembler.hh:314
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:201
void evalDirichletBoundaries(ApplyDirichletFunctionType applyDirichlet)
Evaluates Dirichlet boundaries.
Definition assembly/cvfelocalassembler.hh:277
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:101
void bindLocalViews()
Definition assembly/cvfelocalassembler.hh:89
void maybeEvalAdditionalDomainDerivatives(Args &&...)
Update the additional domain derivatives for coupled models.
Definition assembly/cvfelocalassembler.hh:321
An assembler for Jacobian and residual contribution per element (CVFE methods).
Definition assembly/cvfelocalassembler.hh:335
void bindLocalViews()
Definition assembly/fvlocalassemblerbase.hh:173
ElementVolumeVariables & curElemVolVars()
Definition assembly/fvlocalassemblerbase.hh:253
ElementBoundaryTypes & elemBcTypes()
Definition assembly/fvlocalassemblerbase.hh:269
Implementation & asImp_()
Definition assembly/fvlocalassemblerbase.hh:297
ElementResidualVector evalLocalResidual() const
Definition assembly/fvlocalassemblerbase.hh:108
const Problem & problem() const
Definition assembly/fvlocalassemblerbase.hh:229
FVLocalAssemblerBase(const Assembler &assembler, const Element &element, const SolutionVector &curSol)
Definition assembly/fvlocalassemblerbase.hh:61
FVElementGeometry & fvGeometry()
Definition assembly/fvlocalassemblerbase.hh:249
const Assembler & assembler() const
Definition assembly/fvlocalassemblerbase.hh:233
ElementFluxVariablesCache & elemFluxVarsCache()
Definition assembly/fvlocalassemblerbase.hh:261
bool elementIsGhost() const
Definition assembly/fvlocalassemblerbase.hh:241
std::decay_t< decltype(std::declval< Assembler >().localResidual())> LocalResidual
Definition assembly/fvlocalassemblerbase.hh:55
LocalResidual & localResidual()
Definition assembly/fvlocalassemblerbase.hh:265
const Element & element() const
Definition assembly/fvlocalassemblerbase.hh:237
VolumeVariables & getVolVarAccess(GridVolumeVariables &gridVolVars, ElementVolumeVariables &elemVolVars, const SubControlVolume &scv)
Definition assembly/fvlocalassemblerbase.hh:304
ElementResidualVector evalLocalStorageResidual() const
Definition assembly/fvlocalassemblerbase.hh:164
const SolutionVector & curSol() const
Definition assembly/fvlocalassemblerbase.hh:245
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
A helper class for local assemblers using numeric differentiation to determine the epsilon.
Definition numericepsilon.hh:33
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.
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
@ analytic
Definition diffmethod.hh:26
@ 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 variablesadapter.hh:17
constexpr auto asMultiMapper(const Mapper &mapper)
Definition multimapperview.hh:48
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.