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 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
224 template <
class Res
idualVector>
227 this->
asImp_().bindLocalViews();
231 res[localDof.dofIndex()] += residual[localDof.index()];
233 auto applyDirichlet = [&] (
const auto& scvOrLocalDofI,
234 const auto& dirichletValues,
238 res[scvOrLocalDofI.dofIndex()][eqIdx] = this->
curElemVolVars()[scvOrLocalDofI].priVars()[pvIdx] - dirichletValues[pvIdx];
241 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
245 template<
typename ApplyFunction>
249 this->
asImp_().evalDirichletBoundaries(applyDirichlet);
251 this->
asImp_().enforceInternalDirichletConstraints(applyDirichlet);
257 template<
typename ApplyDirichletFunctionType >
263 if constexpr (!Detail::hasProblemBoundaryTypesForFaceFunction<Problem, FVElementGeometry>())
270 if (bcTypes.hasDirichlet())
272 const auto dirichletValues = this->
asImp_().problem().dirichlet(this->
element(), scvI);
275 for (
int eqIdx = 0; eqIdx < numEq; ++eqIdx)
277 if (bcTypes.isDirichlet(eqIdx))
279 const auto pvIdx = bcTypes.eqToDirichletIndex(eqIdx);
280 assert(0 <= pvIdx && pvIdx < numEq);
281 applyDirichlet(scvI, dirichletValues, eqIdx, pvIdx);
294 template<
class... Args>
301 template<
class... Args>
315template<
class TypeTag,
class Assembler, DiffMethod diffMethod = DiffMethod::numeric,
bool implicit = true,
class Implementation =
void>
323template<
class TypeTag,
class Assembler,
class Implementation>
326 Detail::CVFE::Impl<Implementation, CVFELocalAssembler<TypeTag, Assembler, DiffMethod::numeric, true, Implementation>>,
334 using ElementVolumeVariables =
typename GridVariables::GridVolumeVariables::LocalView;
341 static constexpr bool enableGridFluxVarsCache
342 = GridVariables::GridFluxVariablesCache::cachingEnabled;
343 static constexpr bool solutionDependentFluxVarsCache
344 = GridVariables::GridFluxVariablesCache::FluxVariablesCache::isSolDependent;
350 using ParentType::ParentType;
358 template <
class PartialReassembler = DefaultPartialReassembler>
384 this->
asImp_().
problem().paramGroup(),
"Assembly.BoxVolVarsDependOnAllElementDofs",
false
388 const auto& gridDiscretization = Deprecated::gridGeometry(
fvGeometry);
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 = [&](PrimaryVariable priVar)
416 elemSol[localIdx][pvIdx] = priVar;
417 deflectionPolicy.update(elemSol, localDof, this->
asImp_().
problem());
418 if constexpr (solutionDependentFluxVarsCache)
421 if constexpr (enableGridFluxVarsCache)
424 this->
asImp_().maybeUpdateCouplingContext(localDof, elemSol, pvIdx);
432 eps_(elemSol[localIdx][pvIdx], pvIdx), numDiffMethod);
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);
463 assembleDerivative(localDof);
467 if constexpr (enableGridFluxVarsCache)
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>>,
503 using ParentType::ParentType;
511 template <
class PartialReassembler = DefaultPartialReassembler>
515 if (partialReassembler)
516 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for explicit time discretization");
537 const auto& gridDiscretization = Deprecated::gridGeometry(
fvGeometry);
547 const auto localIdx = scv.localDofIndex();
548 const auto dofIdx = scv.dofIndex();
550 const VolumeVariables origVolVars(curVolVars);
553 for (
int pvIdx = 0; pvIdx < numEq; pvIdx++)
557 auto evalStorage = [&](Scalar priVar)
560 elemSol[localIdx][pvIdx] = priVar;
569 eps_(elemSol[localIdx][pvIdx], pvIdx), numDiffMethod);
572 for (
int eqIdx = 0; eqIdx < numEq; eqIdx++)
578 A[dofIdx][dofIdx][eqIdx][pvIdx] += partialDerivs[localIdx][eqIdx];
582 curVolVars = origVolVars;
585 elemSol[localIdx][pvIdx] =
curSol[dofIdx][pvIdx];
590 return origResiduals;
599template<
class TypeTag,
class Assembler,
class Implementation>
602 Detail::CVFE::Impl<Implementation, CVFELocalAssembler<TypeTag, Assembler, DiffMethod::analytic, true, Implementation>>,
614 using ParentType::ParentType;
622 template <
class PartialReassembler = DefaultPartialReassembler>
626 if (partialReassembler)
627 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for analytic differentiation");
651 const auto dofIdx = scv.dofIndex();
657 if (!this->
assembler().isStationaryProblem())
658 this->
localResidual().addStorageDerivatives(A[dofIdx][dofIdx],
667 this->
localResidual().addSourceDerivatives(A[dofIdx][dofIdx],
678 if (!scvf.boundary())
694 const auto& insideScv =
fvGeometry.scv(scvf.insideScvIdx());
698 this->
localResidual().addRobinFluxDerivatives(A[insideScv.dofIndex()],
709 return origResiduals;
719template<
class TypeTag,
class Assembler,
class Implementation>
722 Detail::CVFE::Impl<Implementation, CVFELocalAssembler<TypeTag, Assembler, DiffMethod::analytic, false, Implementation>>,
734 using ParentType::ParentType;
742 template <
class PartialReassembler = DefaultPartialReassembler>
746 if (partialReassembler)
747 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for explicit time discretization");
770 const auto dofIdx = scv.dofIndex();
775 this->
localResidual().addStorageDerivatives(A[dofIdx][dofIdx],
783 return origResiduals;
A base class for all local assemblers.
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition assembly/cvfelocalassembler.hh:733
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:743
typename ParentType::LocalResidual LocalResidual
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:623
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition assembly/cvfelocalassembler.hh:613
typename ParentType::LocalResidual LocalResidual
Definition assembly/cvfelocalassembler.hh:612
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition assembly/cvfelocalassembler.hh:349
typename ParentType::LocalResidual LocalResidual
Definition assembly/cvfelocalassembler.hh:348
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:359
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:70
void enforceDirichletConstraints(const ApplyFunction &applyDirichlet)
Enforce Dirichlet constraints.
Definition assembly/cvfelocalassembler.hh:246
void assembleResidual(ResidualVector &res)
Assemble the residual only.
Definition assembly/cvfelocalassembler.hh:225
void maybeUpdateCouplingContext(Args &&...)
Update the coupling context for coupled models.
Definition assembly/cvfelocalassembler.hh:295
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:258
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:302
An assembler for Jacobian and residual contribution per element (CVFE methods).
Definition assembly/cvfelocalassembler.hh:316
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:50
A helper class for local assemblers using numeric differentiation to determine the epsilon.
Definition numericepsilon.hh:32
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
@ 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:149
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.
Adapter to expose a multi-DOF mapper interface for single- and multi-DOF mappers.
Definition cvfe/elementvariables.hh:25
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.