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();
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 if (!stageParams.skipSpatial(stageParams.size()-1))
110 origResidual[scv.localDofIndex()] += flux[scv.localDofIndex()]*sWeight;
111 if (!stageParams.skipTemporal(stageParams.size()-1))
112 origResidual[scv.localDofIndex()] += storage[scv.localDofIndex()]*tWeight;
113 res[scv.dofIndex()] += origResidual[scv.localDofIndex()];
116 this->
localResidual().spatialWeight(sWeight, stageParams.skipSpatial(stageParams.size()-1));
117 this->
localResidual().temporalWeight(tWeight, stageParams.skipTemporal(stageParams.size()-1));
119 if (partialReassembler && partialReassembler->elementColor(eIdxGlobal) ==
EntityColor::green)
122 maybeAssembleCouplingBlocks(origResidual);
126 this->
asImp_().assembleJacobian(jac, gridVariables, origResidual, partialReassembler);
129 maybeAssembleCouplingBlocks(origResidual);
138 Dune::Hybrid::forEach(std::make_integer_sequence<int, dim+1>{}, [&](
auto d)
140 constexpr int codim = dim - d;
142 for (
int idx = 0; idx < localCoeffs.size(); ++idx)
144 const auto& localKey = localCoeffs.localKey(idx);
147 if (localKey.codim() != codim)
151 auto entity = this->
element().template subEntity<codim>(localKey.subEntity());
152 if (entity.partitionType() == Dune::InteriorEntity || entity.partitionType() == Dune::BorderEntity)
158 using BlockType =
typename JacobianMatrix::block_type;
161 BlockType &J = jac[dofIndex][dofIndex];
162 for (
int j = 0; j < BlockType::rows; ++j)
165 constrainedDofs[dofIndex] = 1;
171 auto applyDirichlet = [&] (
const auto& scvI,
172 const auto& dirichletValues,
176 res[scvI.dofIndex()][eqIdx] = this->
curElemVolVars()[scvI].priVars()[pvIdx] - dirichletValues[pvIdx];
177 constrainedDofs[scvI.dofIndex()][eqIdx] = 1;
179 auto& row = jac[scvI.dofIndex()];
180 for (
auto col = row.begin(); col != row.end(); ++col)
181 row[col.index()][eqIdx] = 0.0;
183 jac[scvI.dofIndex()][scvI.dofIndex()][eqIdx][pvIdx] = 1.0;
189 res[periodicDof][eqIdx] = this->
curElemVolVars()[scvI].priVars()[pvIdx] - dirichletValues[pvIdx];
190 constrainedDofs[periodicDof][eqIdx] = 1;
191 const auto end = jac[periodicDof].end();
192 for (
auto it = jac[periodicDof].begin(); it != end; ++it)
193 (*it) = periodicDof != it.index() ? 0.0 : 1.0;
197 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
206 this->
asImp_().bindLocalViews();
207 this->
asImp_().assembleJacobian(jac, gridVariables);
209 auto applyDirichlet = [&] (
const auto& scvI,
210 const auto& dirichletValues,
214 auto& row = jac[scvI.dofIndex()];
215 for (
auto col = row.begin(); col != row.end(); ++col)
216 row[col.index()][eqIdx] = 0.0;
218 jac[scvI.dofIndex()][scvI.dofIndex()][eqIdx][pvIdx] = 1.0;
221 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
227 template <
class Res
idualVector>
230 this->
asImp_().bindLocalViews();
234 res[localDof.dofIndex()] += residual[localDof.index()];
236 auto applyDirichlet = [&] (
const auto& scvI,
237 const auto& dirichletValues,
241 res[scvI.dofIndex()][eqIdx] = this->
curElemVolVars()[scvI].priVars()[pvIdx] - dirichletValues[pvIdx];
244 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
250 template<
class Res
idualVector>
253 this->
asImp_().bindLocalViews();
258 spatialRes[scv.dofIndex()] += flux[scv.localDofIndex()];
259 temporalRes[scv.dofIndex()] += storage[scv.localDofIndex()];
264 template<
typename ApplyFunction>
268 this->
asImp_().evalDirichletBoundaries(applyDirichlet);
270 this->
asImp_().enforceInternalDirichletConstraints(applyDirichlet);
276 template<
typename ApplyDirichletFunctionType >
286 if (bcTypes.hasDirichlet())
288 const auto dirichletValues = this->
asImp_().problem().dirichlet(this->
element(), scvI);
291 for (
int eqIdx = 0; eqIdx < numEq; ++eqIdx)
293 if (bcTypes.isDirichlet(eqIdx))
295 const auto pvIdx = bcTypes.eqToDirichletIndex(eqIdx);
296 assert(0 <= pvIdx && pvIdx < numEq);
297 applyDirichlet(scvI, dirichletValues, eqIdx, pvIdx);
309 template<
class... Args>
316 template<
class... Args>
329template<
class TypeTag,
class Assembler, DiffMethod diffMethod = DiffMethod::numeric,
class Implementation =
void>
338template<
class TypeTag,
class Assembler,
class Implementation>
341 NonVoidOr<CVFELocalAssembler<TypeTag, Assembler, DiffMethod::numeric, Implementation>, Implementation>>
347 using ElementVolumeVariables =
typename GridVariables::GridVolumeVariables::LocalView;
354 static constexpr bool enableGridFluxVarsCache
355 = GridVariables::GridFluxVariablesCache::cachingEnabled;
356 static constexpr bool solutionDependentFluxVarsCache
357 = GridVariables::GridFluxVariablesCache::FluxVariablesCache::isSolDependent;
363 using ParentType::ParentType;
365 template <
class PartialReassembler = DefaultPartialReassembler>
371 assembleJacobianImplicit_(A, gridVariables, origResiduals, partialReassembler);
373 assembleJacobianExplicit_(A, gridVariables, origResiduals, partialReassembler);
383 template <
class PartialReassembler = DefaultPartialReassembler>
384 void assembleJacobianImplicit_(JacobianMatrix& A,
GridVariables& gridVariables,
385 const ElementResidualVector& origResiduals,
389 const auto& element = this->element();
390 const auto& fvGeometry = this->fvGeometry();
391 const auto& curSol = this->asImp_().curSol();
393 auto&& curElemVolVars = this->curElemVolVars();
394 auto&& elemFluxVarsCache = this->elemFluxVarsCache();
407 this->asImp_().problem().paramGroup(),
"Assembly.BoxVolVarsDependOnAllElementDofs",
false
415 ElementResidualVector partialDerivs(Dumux::Detail::LocalDofs::numLocalDofs(fvGeometry));
417 auto deflectionPolicy = Dumux::Detail::CVFE::makeVariablesDeflectionPolicy(
418 gridVariables.curGridVolVars(),
424 auto assembleDerivative = [&,
this](
const auto& localDof)
427 const auto dofIdx = localDof.dofIndex();
428 const auto localIdx = localDof.index();
429 deflectionPolicy.store(localDof);
432 for (
int pvIdx = 0; pvIdx < numEq; pvIdx++)
436 auto evalResiduals = [&](PrimaryVariable priVar)
439 elemSol[localIdx][pvIdx] = priVar;
440 deflectionPolicy.update(elemSol, localDof, this->asImp_().problem());
441 if constexpr (solutionDependentFluxVarsCache)
443 elemFluxVarsCache.update(element, fvGeometry, curElemVolVars);
444 if constexpr (enableGridFluxVarsCache)
445 gridVariables.gridFluxVarsCache().updateElement(element, fvGeometry, curElemVolVars);
447 this->asImp_().maybeUpdateCouplingContext(localDof, elemSol, pvIdx);
448 return this->evalLocalResidual();
452 static const NumericEpsilon<PrimaryVariable, numEq> eps_{this->asImp_().problem().paramGroup()};
453 static const int numDiffMethod =
getParamFromGroup<int>(this->asImp_().problem().paramGroup(),
"Assembly.NumericDifferenceMethod");
455 eps_(elemSol[localIdx][pvIdx], pvIdx), numDiffMethod);
458 for (
const auto& localDofJ :
localDofs(fvGeometry))
461 if (!partialReassembler
464 for (
int eqIdx = 0; eqIdx < numEq; eqIdx++)
470 A[localDofJ.dofIndex()][dofIdx][eqIdx][pvIdx] += partialDerivs[localDofJ.index()][eqIdx];
476 deflectionPolicy.restore(localDof);
479 elemSol[localIdx][pvIdx] = curSol[localDof.dofIndex()][pvIdx];
480 this->asImp_().maybeUpdateCouplingContext(localDof, elemSol, pvIdx);
485 for (
const auto& localDof :
localDofs(fvGeometry))
486 assembleDerivative(localDof);
490 if constexpr (enableGridFluxVarsCache)
491 gridVariables.gridFluxVarsCache().updateElement(element, fvGeometry, curElemVolVars);
494 this->asImp_().maybeEvalAdditionalDomainDerivatives(origResiduals, A, gridVariables);
502 template <
class PartialReassembler = DefaultPartialReassembler>
503 void assembleJacobianExplicit_(JacobianMatrix& A, GridVariables& gridVariables,
504 const ElementResidualVector& origResiduals,
505 const PartialReassembler* partialReassembler =
nullptr)
507 if (partialReassembler)
508 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for explicit time discretization");
512 const auto& fvGeometry = this->fvGeometry();
513 const auto& curSol = this->asImp_().curSol();
514 auto&& curElemVolVars = this->curElemVolVars();
521 ElementResidualVector partialDerivs(Dumux::Detail::LocalDofs::numLocalDofs(fvGeometry));
524 for (
const auto& scv :
scvs(fvGeometry))
527 const auto dofIdx = scv.dofIndex();
528 auto& curVolVars = this->getVolVarAccess(gridVariables.curGridVolVars(), curElemVolVars, scv);
529 const VolumeVariables origVolVars(curVolVars);
532 for (
int pvIdx = 0; pvIdx < numEq; pvIdx++)
536 auto evalStorage = [&](PrimaryVariable priVar)
538 elemSol[scv.localDofIndex()][pvIdx] = priVar;
539 curVolVars.update(elemSol, this->asImp_().problem(), element, scv);
540 return this->evalStorage();
544 static const NumericEpsilon<PrimaryVariable, numEq> eps_{this->asImp_().problem().paramGroup()};
545 static const int numDiffMethod =
getParamFromGroup<int>(this->asImp_().problem().paramGroup(),
"Assembly.NumericDifferenceMethod");
547 eps_(elemSol[scv.localDofIndex()][pvIdx], pvIdx), numDiffMethod);
550 for (
int eqIdx = 0; eqIdx < numEq; eqIdx++)
556 A[dofIdx][dofIdx][eqIdx][pvIdx] += partialDerivs[scv.localDofIndex()][eqIdx];
560 curVolVars = origVolVars;
563 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:366
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition experimental/assembly/cvfelocalassembler.hh:362
typename ParentType::LocalResidual LocalResidual
Definition experimental/assembly/cvfelocalassembler.hh:361
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:204
void bindLocalViews()
Definition experimental/assembly/cvfelocalassembler.hh:75
void assembleResidual(ResidualVector &res)
Assemble the residual only.
Definition experimental/assembly/cvfelocalassembler.hh:228
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:277
void assembleCurrentResidual(ResidualVector &spatialRes, ResidualVector &temporalRes)
Assemble the residual only.
Definition experimental/assembly/cvfelocalassembler.hh:251
void maybeUpdateCouplingContext(Args &&...)
Update the coupling context for coupled models.
Definition experimental/assembly/cvfelocalassembler.hh:310
void maybeEvalAdditionalDomainDerivatives(Args &&...)
Update the additional domain derivatives for coupled models.
Definition experimental/assembly/cvfelocalassembler.hh:317
void enforceDirichletConstraints(const ApplyFunction &applyDirichlet)
Enforce Dirichlet constraints.
Definition experimental/assembly/cvfelocalassembler.hh:265
An assembler for Jacobian and residual contribution per element (CVFE methods).
Definition experimental/assembly/cvfelocalassembler.hh:330
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:56
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.
A base class for all local assemblers.
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
@ 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 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.