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>
54template<
class TypeTag,
class Assembler,
class Implementation>
61 using ElementVolumeVariables =
typename GridVariables::GridVolumeVariables::LocalView;
69 using ParentType::ParentType;
85 template <
class Res
idualVector,
class StageParams,
class PartialReassembler = DefaultPartialReassembler,
class CouplingFunction = Noop>
87 const StageParams& stageParams, ResidualVector& temporal, ResidualVector& spatial,
88 ResidualVector& constrainedDofs,
90 const CouplingFunction& maybeAssembleCouplingBlocks =
noop)
92 this->
asImp_().bindLocalViews();
93 const auto eIdxGlobal = Deprecated::gridGeometry(this->
asImp_().
problem()).elementMapper().index(this->
element());
98 const auto sWeight = stageParams.spatialWeight(stageParams.size()-1);
99 const auto tWeight = stageParams.temporalWeight(stageParams.size()-1);
107 spatial[scv.dofIndex()] += flux[scv.localDofIndex()];
108 temporal[scv.dofIndex()] += storage[scv.localDofIndex()];
109 origResidual[scv.localDofIndex()] += flux[scv.localDofIndex()]*sWeight + storage[scv.localDofIndex()]*tWeight;
110 res[scv.dofIndex()] += origResidual[scv.localDofIndex()];
116 if (partialReassembler && partialReassembler->elementColor(eIdxGlobal) ==
EntityColor::green)
119 maybeAssembleCouplingBlocks(origResidual);
123 this->
asImp_().assembleJacobian(jac, gridVariables, origResidual, partialReassembler);
126 maybeAssembleCouplingBlocks(origResidual);
134 const auto& gridDiscretization = Deprecated::gridGeometry(this->
asImp_().
problem());
135 Dune::Hybrid::forEach(std::make_integer_sequence<int, dim+1>{}, [&](
auto d)
137 constexpr int codim = dim - d;
138 const auto& localCoeffs = gridDiscretization.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(gridDiscretization.dofMapper()).indices(entity))
158 BlockType &J = jac[dofIndex][dofIndex];
159 for (
int j = 0; j < BlockType::rows; ++j)
162 constrainedDofs[dofIndex] = 1;
168 auto applyDirichlet = [&] (
const auto& scvI,
169 const auto& dirichletValues,
173 res[scvI.dofIndex()][eqIdx] = this->
curElemVolVars()[scvI].priVars()[pvIdx] - dirichletValues[pvIdx];
174 constrainedDofs[scvI.dofIndex()][eqIdx] = 1;
176 auto& row = jac[scvI.dofIndex()];
177 for (
auto col = row.begin(); col != row.end(); ++col)
178 row[col.index()][eqIdx] = 0.0;
180 jac[scvI.dofIndex()][scvI.dofIndex()][eqIdx][pvIdx] = 1.0;
183 if (Deprecated::gridGeometry(this->
asImp_().
problem()).dofOnPeriodicBoundary(scvI.dofIndex()))
185 const auto periodicDof = Deprecated::gridGeometry(this->
asImp_().
problem()).periodicallyMappedDof(scvI.dofIndex());
186 res[periodicDof][eqIdx] = this->
curElemVolVars()[scvI].priVars()[pvIdx] - dirichletValues[pvIdx];
187 constrainedDofs[periodicDof][eqIdx] = 1;
188 const auto end = jac[periodicDof].end();
189 for (
auto it = jac[periodicDof].begin(); it != end; ++it)
190 (*it) = periodicDof != it.index() ? 0.0 : 1.0;
194 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
203 this->
asImp_().bindLocalViews();
204 this->
asImp_().assembleJacobian(jac, gridVariables);
206 auto applyDirichlet = [&] (
const auto& scvI,
207 const auto& dirichletValues,
211 auto& row = jac[scvI.dofIndex()];
212 for (
auto col = row.begin(); col != row.end(); ++col)
213 row[col.index()][eqIdx] = 0.0;
215 jac[scvI.dofIndex()][scvI.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& scvI,
234 const auto& dirichletValues,
238 res[scvI.dofIndex()][eqIdx] = this->
curElemVolVars()[scvI].priVars()[pvIdx] - dirichletValues[pvIdx];
241 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
247 template<
class Res
idualVector>
250 this->
asImp_().bindLocalViews();
255 spatialRes[scv.dofIndex()] += flux[scv.localDofIndex()];
256 temporalRes[scv.dofIndex()] += storage[scv.localDofIndex()];
261 template<
typename ApplyFunction>
265 this->
asImp_().evalDirichletBoundaries(applyDirichlet);
267 this->
asImp_().enforceInternalDirichletConstraints(applyDirichlet);
273 template<
typename ApplyDirichletFunctionType >
283 if (bcTypes.hasDirichlet())
285 const auto dirichletValues = this->
asImp_().problem().dirichlet(this->
element(), scvI);
288 for (
int eqIdx = 0; eqIdx < numEq; ++eqIdx)
290 if (bcTypes.isDirichlet(eqIdx))
292 const auto pvIdx = bcTypes.eqToDirichletIndex(eqIdx);
293 assert(0 <= pvIdx && pvIdx < numEq);
294 applyDirichlet(scvI, dirichletValues, eqIdx, pvIdx);
306 template<
class... Args>
313 template<
class... Args>
326template<
class TypeTag,
class Assembler, DiffMethod diffMethod = DiffMethod::numeric,
class Implementation =
void>
335template<
class TypeTag,
class Assembler,
class Implementation>
338 NonVoidOr<CVFELocalAssembler<TypeTag, Assembler, DiffMethod::numeric, Implementation>, Implementation>>
344 using ElementVolumeVariables =
typename GridVariables::GridVolumeVariables::LocalView;
351 static constexpr bool enableGridFluxVarsCache
352 = GridVariables::GridFluxVariablesCache::cachingEnabled;
353 static constexpr bool solutionDependentFluxVarsCache
354 = GridVariables::GridFluxVariablesCache::FluxVariablesCache::isSolDependent;
360 using ParentType::ParentType;
362 template <
class PartialReassembler = DefaultPartialReassembler>
368 assembleJacobianImplicit_(A, gridVariables, origResiduals, partialReassembler);
370 assembleJacobianExplicit_(A, gridVariables, origResiduals, partialReassembler);
380 template <
class PartialReassembler = DefaultPartialReassembler>
381 void assembleJacobianImplicit_(JacobianMatrix& A,
GridVariables& gridVariables,
382 const ElementResidualVector& origResiduals,
386 const auto& element = this->element();
387 const auto& fvGeometry = this->fvGeometry();
388 const auto& curSol = this->asImp_().curSol();
390 auto&& curElemVolVars = this->curElemVolVars();
391 auto&& elemFluxVarsCache = this->elemFluxVarsCache();
404 this->asImp_().problem().paramGroup(),
"Assembly.BoxVolVarsDependOnAllElementDofs",
false
408 const auto& gridDiscretization = Deprecated::gridGeometry(fvGeometry);
412 ElementResidualVector partialDerivs(Dumux::Detail::LocalDofs::numLocalDofs(fvGeometry));
414 auto deflectionPolicy = Dumux::Detail::CVFE::makeVariablesDeflectionPolicy(
415 gridVariables.curGridVolVars(),
421 auto assembleDerivative = [&,
this](
const auto& localDof)
424 const auto dofIdx = localDof.dofIndex();
425 const auto localIdx = localDof.index();
426 deflectionPolicy.store(localDof);
429 for (
int pvIdx = 0; pvIdx < numEq; pvIdx++)
433 auto evalResiduals = [&](Scalar priVar)
436 elemSol[localIdx][pvIdx] = priVar;
437 deflectionPolicy.update(elemSol, localDof, this->asImp_().problem());
438 if constexpr (solutionDependentFluxVarsCache)
440 elemFluxVarsCache.update(element, fvGeometry, curElemVolVars);
441 if constexpr (enableGridFluxVarsCache)
442 gridVariables.gridFluxVarsCache().updateElement(element, fvGeometry, curElemVolVars);
444 this->asImp_().maybeUpdateCouplingContext(localDof, elemSol, pvIdx);
445 return this->evalLocalResidual();
449 static const NumericEpsilon<Scalar, numEq> eps_{this->asImp_().problem().paramGroup()};
450 static const int numDiffMethod =
getParamFromGroup<int>(this->asImp_().problem().paramGroup(),
"Assembly.NumericDifferenceMethod");
452 eps_(elemSol[localIdx][pvIdx], pvIdx), numDiffMethod);
455 for (
const auto& localDofJ :
localDofs(fvGeometry))
458 if (!partialReassembler
461 for (
int eqIdx = 0; eqIdx < numEq; eqIdx++)
467 A[localDofJ.dofIndex()][dofIdx][eqIdx][pvIdx] += partialDerivs[localDofJ.index()][eqIdx];
473 deflectionPolicy.restore(localDof);
476 elemSol[localIdx][pvIdx] = curSol[localDof.dofIndex()][pvIdx];
477 this->asImp_().maybeUpdateCouplingContext(localDof, elemSol, pvIdx);
482 for (
const auto& localDof :
localDofs(fvGeometry))
483 assembleDerivative(localDof);
487 if constexpr (enableGridFluxVarsCache)
488 gridVariables.gridFluxVarsCache().updateElement(element, fvGeometry, curElemVolVars);
491 this->asImp_().maybeEvalAdditionalDomainDerivatives(origResiduals, A, gridVariables);
499 template <
class PartialReassembler = DefaultPartialReassembler>
500 void assembleJacobianExplicit_(JacobianMatrix& A, GridVariables& gridVariables,
501 const ElementResidualVector& origResiduals,
502 const PartialReassembler* partialReassembler =
nullptr)
504 if (partialReassembler)
505 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for explicit time discretization");
509 const auto& fvGeometry = this->fvGeometry();
510 const auto& curSol = this->asImp_().curSol();
511 auto&& curElemVolVars = this->curElemVolVars();
514 const auto& gridDiscretization = Deprecated::gridGeometry(fvGeometry);
518 ElementResidualVector partialDerivs(Dumux::Detail::LocalDofs::numLocalDofs(fvGeometry));
521 for (
const auto& scv :
scvs(fvGeometry))
524 const auto dofIdx = scv.dofIndex();
525 auto& curVolVars = this->getVolVarAccess(gridVariables.curGridVolVars(), curElemVolVars, scv);
526 const VolumeVariables origVolVars(curVolVars);
529 for (
int pvIdx = 0; pvIdx < numEq; pvIdx++)
533 auto evalStorage = [&](Scalar priVar)
535 elemSol[scv.localDofIndex()][pvIdx] = priVar;
536 curVolVars.update(elemSol, this->asImp_().problem(), element, scv);
537 return this->evalStorage();
541 static const NumericEpsilon<Scalar, numEq> eps_{this->asImp_().problem().paramGroup()};
542 static const int numDiffMethod =
getParamFromGroup<int>(this->asImp_().problem().paramGroup(),
"Assembly.NumericDifferenceMethod");
544 eps_(elemSol[scv.localDofIndex()][pvIdx], pvIdx), numDiffMethod);
547 for (
int eqIdx = 0; eqIdx < numEq; eqIdx++)
553 A[dofIdx][dofIdx][eqIdx][pvIdx] += partialDerivs[scv.localDofIndex()][eqIdx];
557 curVolVars = origVolVars;
560 elemSol[scv.localDofIndex()][pvIdx] = curSol[scv.dofIndex()][pvIdx];
A linear system assembler (residual and Jacobian) for general discretization schemes.
Definition assembly/assembler.hh:83
GetPropType< TypeTag, Properties::SolutionVector > SolutionVector
Definition assembly/assembler.hh:96
void assembleJacobian(JacobianMatrix &A, GridVariables &gridVariables, const ElementResidualVector &origResiduals, const PartialReassembler *partialReassembler=nullptr)
Definition experimental/assembly/cvfelocalassembler.hh:363
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition experimental/assembly/cvfelocalassembler.hh:359
typename ParentType::LocalResidual LocalResidual
Definition experimental/assembly/cvfelocalassembler.hh:358
A base class for all local CVFE assemblers.
Definition experimental/assembly/cvfelocalassembler.hh:56
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:201
void bindLocalViews()
Definition experimental/assembly/cvfelocalassembler.hh:75
void assembleResidual(ResidualVector &res)
Assemble the residual only.
Definition experimental/assembly/cvfelocalassembler.hh:225
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:86
typename ParentType::LocalResidual LocalResidual
Definition experimental/assembly/cvfelocalassembler.hh:71
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition experimental/assembly/cvfelocalassembler.hh:72
void evalDirichletBoundaries(ApplyDirichletFunctionType applyDirichlet)
Evaluates Dirichlet boundaries.
Definition experimental/assembly/cvfelocalassembler.hh:274
void assembleCurrentResidual(ResidualVector &spatialRes, ResidualVector &temporalRes)
Assemble the residual only.
Definition experimental/assembly/cvfelocalassembler.hh:248
void maybeUpdateCouplingContext(Args &&...)
Update the coupling context for coupled models.
Definition experimental/assembly/cvfelocalassembler.hh:307
void maybeEvalAdditionalDomainDerivatives(Args &&...)
Update the additional domain derivatives for coupled models.
Definition experimental/assembly/cvfelocalassembler.hh:314
void enforceDirichletConstraints(const ApplyFunction &applyDirichlet)
Enforce Dirichlet constraints.
Definition experimental/assembly/cvfelocalassembler.hh:262
An assembler for Jacobian and residual contribution per element (CVFE methods).
Definition experimental/assembly/cvfelocalassembler.hh:327
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:50
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.
A base class for all local assemblers.
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: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 assembly/assembler.hh:44
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.