13#ifndef DUMUX_FC_LOCAL_ASSEMBLER_HH
14#define DUMUX_FC_LOCAL_ASSEMBLER_HH
18#include <dune/grid/common/gridenums.hh>
36 template<
class... Args>
40template<
class T,
class Default>
54template<
class TypeTag,
class Assembler,
class Implementation,
bool implicit>
70 using ParentType::ParentType;
82 template <
class Res
idualVector,
class PartialReassembler = DefaultPartialReassembler,
class CouplingFunction = Detail::NoOpFunctor>
85 const CouplingFunction& maybeAssembleCouplingBlocks = CouplingFunction{})
87 this->
asImp_().bindLocalViews();
88 const auto& gridGeometry = this->
asImp_().problem().gridGeometry();
89 const auto eIdxGlobal = gridGeometry.elementMapper().index(this->
element());
90 if (partialReassembler
93 const auto residual = this->
asImp_().evalLocalResidual();
95 res[scv.dofIndex()] += residual[scv.localDofIndex()];
98 maybeAssembleCouplingBlocks(residual);
102 const auto residual = this->
asImp_().assembleJacobianAndResidualImpl(jac, gridVariables, partialReassembler);
104 if (this->
element().partitionType() == Dune::InteriorEntity)
107 res[scv.dofIndex()] += residual[scv.localDofIndex()];
114 const auto& facet = this->
element().template subEntity <1> (scv.indexInElement());
117 if (facet.partitionType() == Dune::BorderEntity)
118 res[scv.dofIndex()] += residual[scv.localDofIndex()];
124 const auto idx = scv.dofIndex();
126 for (
int i = 0; i < jac[idx][idx].size(); ++i)
127 jac[idx][idx][i][i] = 1.0;
134 maybeAssembleCouplingBlocks(residual);
137 DUNE_THROW(Dune::NotImplemented,
"Ghost elements not supported");
140 auto applyDirichlet = [&] (
const auto& scvI,
141 const auto& dirichletValues,
145 res[scvI.dofIndex()][eqIdx] = this->
curElemVolVars()[scvI].priVars()[pvIdx] - dirichletValues[pvIdx];
147 auto& row = jac[scvI.dofIndex()];
148 for (
auto col = row.begin(); col != row.end(); ++col)
149 row[col.index()][eqIdx] = 0.0;
151 jac[scvI.dofIndex()][scvI.dofIndex()][eqIdx][pvIdx] = 1.0;
154 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
163 this->
asImp_().bindLocalViews();
164 this->
asImp_().assembleJacobianAndResidualImpl(jac, gridVariables);
166 auto applyDirichlet = [&] (
const auto& scvI,
167 const auto& dirichletValues,
171 auto& row = jac[scvI.dofIndex()];
172 for (
auto col = row.begin(); col != row.end(); ++col)
173 row[col.index()][eqIdx] = 0.0;
175 jac[scvI.dofIndex()][scvI.dofIndex()][eqIdx][pvIdx] = 1.0;
178 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
184 template<
class Res
idualVector>
187 this->
asImp_().bindLocalViews();
191 res[scv.dofIndex()] += residual[scv.localDofIndex()];
193 auto applyDirichlet = [&] (
const auto& scvI,
194 const auto& dirichletValues,
198 res[scvI.dofIndex()][eqIdx] = this->
curElemVolVars()[scvI].priVars()[pvIdx] - dirichletValues[pvIdx];
201 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
207 template<
typename ApplyFunction>
211 this->
asImp_().evalDirichletBoundaries(applyDirichlet);
213 this->
asImp_().enforceInternalDirichletConstraints(applyDirichlet);
219 template<
typename ApplyDirichletFunctionType >
226 for (
const auto& scvf : scvfs(this->
fvGeometry()))
228 if (scvf.isFrontal() && scvf.boundary())
230 const auto bcTypes = this->
elemBcTypes()[scvf.localIndex()];
231 if (bcTypes.hasDirichlet())
233 const auto& scv = this->
fvGeometry().scv(scvf.insideScvIdx());
234 const auto dirichletValues = this->
asImp_().problem().dirichlet(this->
element(), scvf);
237 for (
int eqIdx = 0; eqIdx < numEq; ++eqIdx)
239 static_assert(numEq == 1,
"Not yet implemented for more than one vector-valued primary variable");
240 const int pvIdx = eqIdx;
241 const int componentIdx = scv.dofAxis();
242 if (bcTypes.isDirichlet(componentIdx))
243 applyDirichlet(scv, std::array<Scalar,1>{{dirichletValues[componentIdx]}}, eqIdx, pvIdx);
254 template<
typename ApplyFunction,
class P = Problem,
typename std::enable_if_t<P::enableInternalDirichletConstra
ints(),
int> = 0>
264 for (
int eqIdx = 0; eqIdx < numEq; ++eqIdx)
266 static_assert(numEq == 1,
"Not yet implemented for more than one vector-valued primary variable");
267 const int pvIdx = eqIdx;
268 applyDirichlet(scvI, std::array<Scalar,1>{{*dirichletValue}}, eqIdx, pvIdx);
274 template<
typename ApplyFunction,
class P = Problem,
typename std::enable_if_t<!P::enableInternalDirichletConstra
ints(),
int> = 0>
283 template<
class P = Problem,
typename std::enable_if_t<P::enableInternalDirichletConstra
ints(),
int> = 0>
287 const auto axis = scv.dofAxis();
288 if (
problem.hasInternalDirichletConstraint(this->element(), scv)[axis])
291 const auto& gridGeometry =
problem.gridGeometry();
292 if (gridGeometry.dofOnPeriodicBoundary(scv.dofIndex()))
294 const auto& periodicScv = this->
fvGeometry().outsidePeriodicScv(scv);
295 const auto periodicElement = gridGeometry.element(periodicScv.elementIndex());
296 if (
problem.hasInternalDirichletConstraint(periodicElement, periodicScv)[axis])
297 return problem.internalDirichlet(periodicElement, periodicScv)[axis];
307 template<
class... Args>
314 template<
class... Args>
327template<
class TypeTag,
class Assembler, DiffMethod diffMethod = DiffMethod::numeric,
bool implicit = true,
class Implementation =
void>
335template<
class TypeTag,
class Assembler,
class Implementation>
339 Detail::NonVoidOrDefault_t<Implementation, FaceCenteredLocalAssembler<TypeTag, Assembler, DiffMethod::numeric, true, Implementation>>,
348 using FVElementGeometry =
typename GridGeometry::LocalView;
349 using SubControlVolume =
typename FVElementGeometry::SubControlVolume;
350 using SubControlVolumeFace =
typename FVElementGeometry::SubControlVolumeFace;
362 using ParentType::ParentType;
370 template <
class PartialReassembler = DefaultPartialReassembler>
393 const auto numElementResiduals =
fvGeometry.numScv();
410 if (!scvf.processorBoundary())
414 const auto evalDerivative = [&] (
const auto& scvI,
const auto& scvJ)
417 for (
int pvIdx = 0; pvIdx < numEq; pvIdx++)
420 const auto& otherElement =
fvGeometry.gridGeometry().element(scvJ.elementIndex());
423 const VolumeVariables origOtherVolVars(curOtherVolVars);
425 auto evalResiduals = [&](PrimaryVariable priVar)
428 otherElemSol[scvJ.localDofIndex()][pvIdx] = priVar;
429 curOtherVolVars.update(otherElemSol,
problem, otherElement, scvJ);
430 this->
asImp_().maybeUpdateCouplingContext(scvJ, otherElemSol, pvIdx);
435 evalSource(residual, scvI);
437 if (!this->
assembler().isStationaryProblem())
438 evalStorage(residual, scvI);
440 for (
const auto& scvf : scvfs(
fvGeometry, scvI))
441 evalFlux(residual, scvf);
450 eps_(otherElemSol[scvJ.localDofIndex()][pvIdx], pvIdx), numDiffMethod);
452 const auto updateJacobian = [&]()
454 for (
int eqIdx = 0; eqIdx < numEq; eqIdx++)
460 A[scvI.dofIndex()][scvJ.dofIndex()][eqIdx][pvIdx] += partialDerivs[scvI.localDofIndex()][eqIdx];
464 if (
element.partitionType() == Dune::InteriorEntity)
468 const auto localIdxI = scvI.indexInElement();
469 const auto& facetI =
element.template subEntity <1> (localIdxI);
471 if (facetI.partitionType() == Dune::BorderEntity)
476 curOtherVolVars = origOtherVolVars;
479 otherElemSol[scvJ.localDofIndex()][pvIdx] =
curSol[scvJ.dofIndex()][pvIdx];
480 this->
asImp_().maybeUpdateCouplingContext(scvJ, otherElemSol, pvIdx);
489 evalDerivative(scvI, scvI);
492 const auto& otherScvIndices =
fvGeometry.gridGeometry().connectivityMap()[scvI.index()];
493 for (
const auto globalJ : otherScvIndices)
494 evalDerivative(scvI,
fvGeometry.scv(globalJ));
498 this->
asImp_().maybeEvalAdditionalDomainDerivatives(origResiduals, A, gridVariables);
500 return origResiduals;
510template<
class TypeTag,
class Assembler,
class Implementation>
514 Detail::NonVoidOrDefault_t<Implementation, FaceCenteredLocalAssembler<TypeTag, Assembler, DiffMethod::numeric, false, Implementation>>,
531 using ParentType::ParentType;
539 template <
class PartialReassembler = DefaultPartialReassembler>
543 if (partialReassembler)
544 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for explicit time discretization");
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[scv.localDofIndex()][pvIdx] = priVar;
596 eps_(elemSol[scv.localDofIndex()][pvIdx], pvIdx), numDiffMethod);
599 for (
int eqIdx = 0; eqIdx < numEq; eqIdx++)
605 A[dofIdx][dofIdx][eqIdx][pvIdx] += partialDerivs[scv.localDofIndex()][eqIdx];
609 curVolVars = origVolVars;
612 elemSol[scv.localDofIndex()][pvIdx] =
curSol[scv.dofIndex()][pvIdx];
615 return origResiduals;
624template<
class TypeTag,
class Assembler,
class Implementation>
628 FaceCenteredLocalAssembler<TypeTag, Assembler, DiffMethod::analytic, true, Implementation>,
643 using ParentType::ParentType;
651 template <
class PartialReassembler = DefaultPartialReassembler>
655 if (partialReassembler)
656 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for analytic differentiation");
680 const auto dofIdx = scv.dofIndex();
686 if (!this->
assembler().isStationaryProblem())
687 this->
localResidual().addStorageDerivatives(A[dofIdx][dofIdx],
696 this->
localResidual().addSourceDerivatives(A[dofIdx][dofIdx],
707 if (!scvf.boundary())
723 const auto& insideScv =
fvGeometry.scv(scvf.insideScvIdx());
724 if (this->
elemBcTypes()[insideScv.localDofIndex()].hasNeumann())
727 this->
localResidual().addRobinFluxDerivatives(A[insideScv.dofIndex()],
738 return origResiduals;
747template<
class TypeTag,
class Assembler,
class Implementation>
751 FaceCenteredLocalAssembler<TypeTag, Assembler, DiffMethod::analytic, false, Implementation>,
766 using ParentType::ParentType;
774 template <
class PartialReassembler = DefaultPartialReassembler>
778 if (partialReassembler)
779 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for explicit time discretization");
802 const auto dofIdx = scv.dofIndex();
807 this->
localResidual().addStorageDerivatives(A[dofIdx][dofIdx],
815 return origResiduals;
A base class for all local assemblers.
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
ElementVolumeVariables & prevElemVolVars()
Definition assembly/fvlocalassemblerbase.hh:257
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
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition fclocalassembler.hh:361
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 fclocalassembler.hh:371
typename ParentType::LocalResidual LocalResidual
Definition fclocalassembler.hh:360
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition fclocalassembler.hh:642
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 fclocalassembler.hh:652
typename ParentType::LocalResidual LocalResidual
Definition fclocalassembler.hh:641
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition fclocalassembler.hh:530
typename ParentType::LocalResidual LocalResidual
Definition fclocalassembler.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 fclocalassembler.hh:540
typename ParentType::LocalResidual LocalResidual
Definition fclocalassembler.hh:764
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition fclocalassembler.hh:765
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 fclocalassembler.hh:775
A base class for all local cell-centered assemblers.
Definition fclocalassembler.hh:56
void enforceInternalDirichletConstraints(const ApplyFunction &applyDirichlet)
Enforces Dirichlet constraints if enabled in the problem.
Definition fclocalassembler.hh:255
void assembleJacobianAndResidual(JacobianMatrix &jac, ResidualVector &res, GridVariables &gridVariables, const PartialReassembler *partialReassembler, const CouplingFunction &maybeAssembleCouplingBlocks=CouplingFunction{})
Computes the derivatives with respect to the given element and adds them to the global matrix....
Definition fclocalassembler.hh:83
void enforceDirichletConstraints(const ApplyFunction &applyDirichlet)
Enforce Dirichlet constraints.
Definition fclocalassembler.hh:208
void assembleJacobian(JacobianMatrix &jac, GridVariables &gridVariables)
Computes the derivatives with respect to the given element and adds them to the global matrix.
Definition fclocalassembler.hh:161
std::optional< Scalar > internalDirichletValue(const SubControlVolume &scv) const
The value of the internal Dirichlet constraint on the velocity component of a sub-control volume,...
Definition fclocalassembler.hh:284
void maybeUpdateCouplingContext(Args &&...)
Update the coupling context for coupled models.
Definition fclocalassembler.hh:308
void bindLocalViews()
Definition fclocalassembler.hh:72
void evalDirichletBoundaries(ApplyDirichletFunctionType applyDirichlet)
Evaluates Dirichlet boundaries.
Definition fclocalassembler.hh:220
void maybeEvalAdditionalDomainDerivatives(Args &&...)
Update the additional domain derivatives for coupled models.
Definition fclocalassembler.hh:315
void assembleResidual(ResidualVector &res)
Assemble the residual only.
Definition fclocalassembler.hh:185
An assembler for Jacobian and residual contribution per element (Face-centered methods).
Definition fclocalassembler.hh:328
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
EntityColor elementColor(size_t idx) const
Definition partialreassembler.hh:489
Defines all properties used in Dumux.
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.
The global face variables class for staggered models.
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
Definition cvfelocalresidual.hh:25
std::conditional_t<!std::is_same_v< T, void >, T, Default > NonVoidOrDefault_t
Definition fclocalassembler.hh:41
std::ranges::range auto scvs(const FVElementGeometry &fvGeometry, const LocalDof &localDof)
Definition localdof.hh:82
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.
Definition fclocalassembler.hh:35
constexpr void operator()(Args &&...) const
Definition fclocalassembler.hh:37