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"
51 template<
class... Args>
52 constexpr void operator()(Args&&...)
const {}
55template<
class X,
class Y>
56using Impl = std::conditional_t<!std::is_same_v<X, void>, X, Y>;
70template<
class TypeTag,
class Assembler,
class Implementation,
bool implicit>
77 using GridVolumeVariables =
typename GridVariables::GridVolumeVariables;
78 using ElementVolumeVariables =
typename GridVariables::GridVolumeVariables::LocalView;
80 using SolutionVector =
typename Assembler::SolutionVector;
82 using FVElementGeometry =
typename GridGeometry::LocalView;
85 static constexpr int dim = GridGeometry::GridView::dimension;
89 using ParentType::ParentType;
102 template <
class Res
idualVector,
class PartialReassembler = DefaultPartialReassembler,
class CouplingFunction = Detail::CVFE::NoOperator>
105 const CouplingFunction& maybeAssembleCouplingBlocks = {})
107 this->
asImp_().bindLocalViews();
108 const auto eIdxGlobal = this->
asImp_().problem().gridGeometry().elementMapper().index(this->
element());
109 if (partialReassembler
112 const auto residual = this->
asImp_().evalLocalResidual();
115 res[localDof.dofIndex()] += residual[localDof.index()];
118 maybeAssembleCouplingBlocks(residual);
122 const auto residual = this->
asImp_().assembleJacobianAndResidualImpl(jac, gridVariables, partialReassembler);
125 res[localDof.dofIndex()] += residual[localDof.index()];
128 maybeAssembleCouplingBlocks(residual);
136 const auto& gridGeometry = this->
asImp_().problem().gridGeometry();
137 Dune::Hybrid::forEach(std::make_integer_sequence<int, dim+1>{}, [&](
auto d)
139 constexpr int codim = dim - d;
140 const auto& localCoeffs = gridGeometry.feCache().get(this->
element().type()).localCoefficients();
141 for (
int idx = 0; idx < localCoeffs.size(); ++idx)
143 const auto& localKey = localCoeffs.localKey(idx);
146 if (localKey.codim() != codim)
150 auto entity = this->
element().template subEntity<codim>(localKey.subEntity());
151 if (entity.partitionType() == Dune::InteriorEntity || entity.partitionType() == Dune::BorderEntity)
157 using BlockType =
typename JacobianMatrix::block_type;
158 for (
const auto dofIndex :
asMultiMapper(gridGeometry.dofMapper()).indices(entity))
160 BlockType &J = jac[dofIndex][dofIndex];
161 for (
int j = 0; j < BlockType::rows; ++j)
169 auto applyDirichlet = [&] (
const auto& scvOrLocalDofI,
170 const auto& dirichletValues,
174 res[scvOrLocalDofI.dofIndex()][eqIdx] = this->
curElemVolVars()[scvOrLocalDofI].priVars()[pvIdx] - dirichletValues[pvIdx];
176 auto& row = jac[scvOrLocalDofI.dofIndex()];
177 for (
auto col = row.begin(); col != row.end(); ++col)
178 row[col.index()][eqIdx] = 0.0;
180 jac[scvOrLocalDofI.dofIndex()][scvOrLocalDofI.dofIndex()][eqIdx][pvIdx] = 1.0;
183 if (this->
asImp_().
problem().gridGeometry().dofOnPeriodicBoundary(scvOrLocalDofI.dofIndex()))
185 for (
const auto periodicDof :
186 Dumux::Deprecated::rangeOfPeriodicallyMappedDofs(this->
asImp_().
problem().gridGeometry(), scvOrLocalDofI.dofIndex()))
188 res[periodicDof][eqIdx] = this->
asImp_().curSol()[periodicDof][pvIdx] - dirichletValues[pvIdx];
190 auto& rowP = jac[periodicDof];
191 for (
auto col = rowP.begin(); col != rowP.end(); ++col)
192 rowP[col.index()][eqIdx] = 0.0;
194 rowP[periodicDof][eqIdx][pvIdx] = 1.0;
199 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
208 this->
asImp_().bindLocalViews();
209 this->
asImp_().assembleJacobianAndResidualImpl(jac, gridVariables);
211 auto applyDirichlet = [&] (
const auto& scvOrLocalDofI,
212 const auto& dirichletValues,
216 auto& row = jac[scvOrLocalDofI.dofIndex()];
217 for (
auto col = row.begin(); col != row.end(); ++col)
218 row[col.index()][eqIdx] = 0.0;
220 jac[scvOrLocalDofI.dofIndex()][scvOrLocalDofI.dofIndex()][eqIdx][pvIdx] = 1.0;
223 if (this->
asImp_().
problem().gridGeometry().dofOnPeriodicBoundary(scvOrLocalDofI.dofIndex()))
225 for (
const auto periodicDof :
226 Dumux::Deprecated::rangeOfPeriodicallyMappedDofs(this->
asImp_().
problem().gridGeometry(), scvOrLocalDofI.dofIndex()))
228 auto& rowP = jac[periodicDof];
229 for (
auto col = rowP.begin(); col != rowP.end(); ++col)
230 rowP[col.index()][eqIdx] = 0.0;
232 rowP[periodicDof][eqIdx][pvIdx] = 1.0;
237 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
243 template <
class Res
idualVector>
246 this->
asImp_().bindLocalViews();
250 res[localDof.dofIndex()] += residual[localDof.index()];
252 auto applyDirichlet = [&] (
const auto& scvOrLocalDofI,
253 const auto& dirichletValues,
257 res[scvOrLocalDofI.dofIndex()][eqIdx] = this->
curElemVolVars()[scvOrLocalDofI].priVars()[pvIdx] - dirichletValues[pvIdx];
260 if (this->
asImp_().
problem().gridGeometry().dofOnPeriodicBoundary(scvOrLocalDofI.dofIndex()))
262 for (
const auto periodicDof :
263 Dumux::Deprecated::rangeOfPeriodicallyMappedDofs(this->
asImp_().
problem().gridGeometry(), scvOrLocalDofI.dofIndex()))
264 res[periodicDof][eqIdx] = this->
asImp_().curSol()[periodicDof][pvIdx] - dirichletValues[pvIdx];
268 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
272 template<
typename ApplyFunction>
276 this->
asImp_().evalDirichletBoundaries(applyDirichlet);
278 this->
asImp_().enforceInternalDirichletConstraints(applyDirichlet);
284 template<
typename ApplyDirichletFunctionType >
290 if constexpr (!Detail::hasProblemBoundaryTypesForFaceFunction<Problem, FVElementGeometry>())
297 if (bcTypes.hasDirichlet())
299 const auto dirichletValues = this->
asImp_().problem().dirichlet(this->
element(), scvI);
302 for (
int eqIdx = 0; eqIdx < numEq; ++eqIdx)
304 if (bcTypes.isDirichlet(eqIdx))
306 const auto pvIdx = bcTypes.eqToDirichletIndex(eqIdx);
307 assert(0 <= pvIdx && pvIdx < numEq);
308 applyDirichlet(scvI, dirichletValues, eqIdx, pvIdx);
321 template<
class... Args>
328 template<
class... Args>
342template<
class TypeTag,
class Assembler, DiffMethod diffMethod = DiffMethod::numeric,
bool implicit = true,
class Implementation =
void>
350template<
class TypeTag,
class Assembler,
class Implementation>
353 Detail::CVFE::Impl<Implementation, CVFELocalAssembler<TypeTag, Assembler, DiffMethod::numeric, true, Implementation>>,
361 using ElementVolumeVariables =
typename GridVariables::GridVolumeVariables::LocalView;
368 static constexpr bool enableGridFluxVarsCache
369 = GridVariables::GridFluxVariablesCache::cachingEnabled;
370 static constexpr bool solutionDependentFluxVarsCache
371 = GridVariables::GridFluxVariablesCache::FluxVariablesCache::isSolDependent;
377 using ParentType::ParentType;
385 template <
class PartialReassembler = DefaultPartialReassembler>
411 this->
asImp_().
problem().paramGroup(),
"Assembly.BoxVolVarsDependOnAllElementDofs",
false
421 auto deflectionPolicy = Detail::CVFE::makeVariablesDeflectionPolicy(
422 gridVariables.curGridVolVars(),
428 auto assembleDerivative = [&,
this](
const auto& localDof)
431 const auto dofIdx = localDof.dofIndex();
432 const auto localIdx = localDof.index();
433 deflectionPolicy.store(localDof);
436 for (
int pvIdx = 0; pvIdx < numEq; pvIdx++)
440 auto evalResiduals = [&](PrimaryVariable priVar)
443 elemSol[localIdx][pvIdx] = priVar;
444 deflectionPolicy.update(elemSol, localDof, this->
asImp_().
problem());
445 if constexpr (solutionDependentFluxVarsCache)
448 if constexpr (enableGridFluxVarsCache)
451 this->
asImp_().maybeUpdateCouplingContext(localDof, elemSol, pvIdx);
459 eps_(elemSol[localIdx][pvIdx], pvIdx), numDiffMethod);
465 if (!partialReassembler
468 for (
int eqIdx = 0; eqIdx < numEq; eqIdx++)
474 A[localDofJ.dofIndex()][dofIdx][eqIdx][pvIdx] += partialDerivs[localDofJ.index()][eqIdx];
480 deflectionPolicy.restore(localDof);
483 elemSol[localIdx][pvIdx] =
curSol[localDof.dofIndex()][pvIdx];
484 this->
asImp_().maybeUpdateCouplingContext(localDof, elemSol, pvIdx);
490 assembleDerivative(localDof);
494 if constexpr (enableGridFluxVarsCache)
498 this->
asImp_().maybeEvalAdditionalDomainDerivatives(origResiduals, A, gridVariables);
500 return origResiduals;
510template<
class TypeTag,
class Assembler,
class Implementation>
513 Detail::CVFE::Impl<Implementation, CVFELocalAssembler<TypeTag, Assembler, DiffMethod::numeric, false, Implementation>>,
530 using ParentType::ParentType;
538 template <
class PartialReassembler = DefaultPartialReassembler>
542 if (partialReassembler)
543 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for explicit time discretization");
574 const auto localIdx = scv.localDofIndex();
575 const auto dofIdx = scv.dofIndex();
577 const VolumeVariables origVolVars(curVolVars);
580 for (
int pvIdx = 0; pvIdx < numEq; pvIdx++)
584 auto evalStorage = [&](PrimaryVariable priVar)
587 elemSol[localIdx][pvIdx] = priVar;
596 eps_(elemSol[localIdx][pvIdx], pvIdx), numDiffMethod);
599 for (
int eqIdx = 0; eqIdx < numEq; eqIdx++)
605 A[dofIdx][dofIdx][eqIdx][pvIdx] += partialDerivs[localIdx][eqIdx];
609 curVolVars = origVolVars;
612 elemSol[localIdx][pvIdx] =
curSol[dofIdx][pvIdx];
617 return origResiduals;
626template<
class TypeTag,
class Assembler,
class Implementation>
629 Detail::CVFE::Impl<Implementation, CVFELocalAssembler<TypeTag, Assembler, DiffMethod::analytic, true, Implementation>>,
641 using ParentType::ParentType;
649 template <
class PartialReassembler = DefaultPartialReassembler>
653 if (partialReassembler)
654 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for analytic differentiation");
678 const auto dofIdx = scv.dofIndex();
684 if (!this->
assembler().isStationaryProblem())
685 this->
localResidual().addStorageDerivatives(A[dofIdx][dofIdx],
694 this->
localResidual().addSourceDerivatives(A[dofIdx][dofIdx],
705 if (!scvf.boundary())
721 const auto& insideScv =
fvGeometry.scv(scvf.insideScvIdx());
725 this->
localResidual().addRobinFluxDerivatives(A[insideScv.dofIndex()],
736 return origResiduals;
746template<
class TypeTag,
class Assembler,
class Implementation>
749 Detail::CVFE::Impl<Implementation, CVFELocalAssembler<TypeTag, Assembler, DiffMethod::analytic, false, Implementation>>,
761 using ParentType::ParentType;
769 template <
class PartialReassembler = DefaultPartialReassembler>
773 if (partialReassembler)
774 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for explicit time discretization");
797 const auto dofIdx = scv.dofIndex();
802 this->
localResidual().addStorageDerivatives(A[dofIdx][dofIdx],
810 return origResiduals;
A base class for all local assemblers.
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition assembly/cvfelocalassembler.hh:760
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:770
typename ParentType::LocalResidual LocalResidual
Definition assembly/cvfelocalassembler.hh:759
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:650
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition assembly/cvfelocalassembler.hh:640
typename ParentType::LocalResidual LocalResidual
Definition assembly/cvfelocalassembler.hh:639
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition assembly/cvfelocalassembler.hh:376
typename ParentType::LocalResidual LocalResidual
Definition assembly/cvfelocalassembler.hh:375
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:386
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition assembly/cvfelocalassembler.hh:529
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:539
typename ParentType::LocalResidual LocalResidual
Definition assembly/cvfelocalassembler.hh:528
A base class for all local CVFE assemblers.
Definition assembly/cvfelocalassembler.hh:72
void enforceDirichletConstraints(const ApplyFunction &applyDirichlet)
Enforce Dirichlet constraints.
Definition assembly/cvfelocalassembler.hh:273
void assembleResidual(ResidualVector &res)
Assemble the residual only.
Definition assembly/cvfelocalassembler.hh:244
void maybeUpdateCouplingContext(Args &&...)
Update the coupling context for coupled models.
Definition assembly/cvfelocalassembler.hh:322
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:206
void evalDirichletBoundaries(ApplyDirichletFunctionType applyDirichlet)
Evaluates Dirichlet boundaries.
Definition assembly/cvfelocalassembler.hh:285
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:103
void bindLocalViews()
Definition assembly/cvfelocalassembler.hh:91
void maybeEvalAdditionalDomainDerivatives(Args &&...)
Update the additional domain derivatives for coupled models.
Definition assembly/cvfelocalassembler.hh:329
An assembler for Jacobian and residual contribution per element (CVFE methods).
Definition assembly/cvfelocalassembler.hh:343
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 elementinterpolationpointdatacache.hh:21
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.