13#ifndef DUMUX_FC_LOCAL_ASSEMBLER_HH
14#define DUMUX_FC_LOCAL_ASSEMBLER_HH
16#include <dune/grid/common/gridenums.hh>
34 template<
class... Args>
38template<
class T,
class Default>
52template<
class TypeTag,
class Assembler,
class Implementation,
bool implicit>
65 using ParentType::ParentType;
77 template <
class Res
idualVector,
class PartialReassembler = DefaultPartialReassembler,
class CouplingFunction = Detail::NoOpFunctor>
80 const CouplingFunction& maybeAssembleCouplingBlocks = CouplingFunction{})
82 static_assert(!std::decay_t<
decltype(this->
asImp_().problem())>::enableInternalDirichletConstraints(),
83 "Internal Dirichlet constraints are currently not implemented for face-centered staggered models!");
85 this->
asImp_().bindLocalViews();
86 const auto& gridGeometry = this->
asImp_().problem().gridGeometry();
87 const auto eIdxGlobal = gridGeometry.elementMapper().index(this->
element());
88 if (partialReassembler
91 const auto residual = this->
asImp_().evalLocalResidual();
92 for (
const auto& scv : scvs(this->
fvGeometry()))
93 res[scv.dofIndex()] += residual[scv.localDofIndex()];
96 maybeAssembleCouplingBlocks(residual);
100 const auto residual = this->
asImp_().assembleJacobianAndResidualImpl(jac, gridVariables, partialReassembler);
102 if (this->
element().partitionType() == Dune::InteriorEntity)
104 for (
const auto& scv : scvs(this->
fvGeometry()))
105 res[scv.dofIndex()] += residual[scv.localDofIndex()];
110 for (
const auto& scv : scvs(this->
fvGeometry()))
112 const auto& facet = this->
element().template subEntity <1> (scv.indexInElement());
115 if (facet.partitionType() == Dune::BorderEntity)
116 res[scv.dofIndex()] += residual[scv.localDofIndex()];
122 const auto idx = scv.dofIndex();
124 for (
int i = 0; i < jac[idx][idx].size(); ++i)
125 jac[idx][idx][i][i] = 1.0;
132 maybeAssembleCouplingBlocks(residual);
135 DUNE_THROW(Dune::NotImplemented,
"Ghost elements not supported");
138 auto applyDirichlet = [&] (
const auto& scvI,
139 const auto& dirichletValues,
143 res[scvI.dofIndex()][eqIdx] = this->
curElemVolVars()[scvI].priVars()[pvIdx] - dirichletValues[pvIdx];
145 auto& row = jac[scvI.dofIndex()];
146 for (
auto col = row.begin(); col != row.end(); ++col)
147 row[col.index()][eqIdx] = 0.0;
149 jac[scvI.dofIndex()][scvI.dofIndex()][eqIdx][pvIdx] = 1.0;
162 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
171 this->
asImp_().bindLocalViews();
172 this->
asImp_().assembleJacobianAndResidualImpl(jac, gridVariables);
174 auto applyDirichlet = [&] (
const auto& scvI,
175 const auto& dirichletValues,
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;
186 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
192 template<
class Res
idualVector>
195 this->
asImp_().bindLocalViews();
198 for (
const auto& scv : scvs(this->
fvGeometry()))
199 res[scv.dofIndex()] += residual[scv.localDofIndex()];
201 auto applyDirichlet = [&] (
const auto& scvI,
202 const auto& dirichletValues,
206 res[scvI.dofIndex()][eqIdx] = this->
curElemVolVars()[scvI].priVars()[eqIdx] - dirichletValues[pvIdx];
209 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
215 template<
typename ApplyFunction>
219 this->
asImp_().evalDirichletBoundaries(applyDirichlet);
221 this->
asImp_().enforceInternalDirichletConstraints(applyDirichlet);
227 template<
typename ApplyDirichletFunctionType >
234 for (
const auto& scvf : scvfs(this->
fvGeometry()))
236 if (scvf.isFrontal() && scvf.boundary())
238 const auto bcTypes = this->
elemBcTypes()[scvf.localIndex()];
239 if (bcTypes.hasDirichlet())
241 const auto& scv = this->
fvGeometry().scv(scvf.insideScvIdx());
242 const auto dirichletValues = this->
asImp_().problem().dirichlet(this->
element(), scvf);
245 for (
int eqIdx = 0; eqIdx < numEq; ++eqIdx)
247 for (
int pvIdx = 0; pvIdx < GridView::dimension; ++pvIdx)
249 if (bcTypes.isDirichlet(pvIdx) && pvIdx == scv.dofAxis())
250 applyDirichlet(scv, dirichletValues, eqIdx, pvIdx);
263 template<
class... Args>
270 template<
class... Args>
283template<
class TypeTag,
class Assembler, DiffMethod diffMethod = DiffMethod::numeric,
bool implicit = true,
class Implementation =
void>
291template<
class TypeTag,
class Assembler,
class Implementation>
295 Detail::NonVoidOrDefault_t<Implementation, FaceCenteredLocalAssembler<TypeTag, Assembler, DiffMethod::numeric, true, Implementation>>,
304 using FVElementGeometry =
typename GridGeometry::LocalView;
305 using SubControlVolume =
typename FVElementGeometry::SubControlVolume;
306 using SubControlVolumeFace =
typename FVElementGeometry::SubControlVolumeFace;
326 template <
class PartialReassembler = DefaultPartialReassembler>
331 const auto& problem = this->asImp_().problem();
332 const auto& element = this->element();
333 const auto& fvGeometry = this->fvGeometry();
334 const auto& curSol = this->asImp_().curSol();
335 auto&& curElemVolVars = this->curElemVolVars();
338 const auto origResiduals = this->evalLocalResidual();
349 const auto numElementResiduals = fvGeometry.numScv();
356 this->localResidual().evalSource(residual, problem, element, fvGeometry, curElemVolVars, scv);
361 this->localResidual().evalStorage(residual, problem, element, fvGeometry, this->prevElemVolVars(), curElemVolVars, scv);
366 if (!scvf.processorBoundary())
367 this->localResidual().evalFlux(residual, problem, element, fvGeometry, curElemVolVars, this->elemBcTypes(), this->elemFluxVarsCache(), scvf);
370 const auto evalDerivative = [&] (
const auto& scvI,
const auto& scvJ)
373 for (
int pvIdx = 0; pvIdx < numEq; pvIdx++)
376 const auto& otherElement = fvGeometry.gridGeometry().element(scvJ.elementIndex());
377 auto otherElemSol =
elementSolution(otherElement, curSol, fvGeometry.gridGeometry());
378 auto& curOtherVolVars = this->getVolVarAccess(gridVariables.curGridVolVars(), curElemVolVars, scvJ);
379 const VolumeVariables origOtherVolVars(curOtherVolVars);
381 auto evalResiduals = [&](Scalar priVar)
384 otherElemSol[scvJ.localDofIndex()][pvIdx] = priVar;
385 curOtherVolVars.update(otherElemSol, problem, otherElement, scvJ);
386 this->asImp_().maybeUpdateCouplingContext(scvJ, otherElemSol, pvIdx);
391 evalSource(residual, scvI);
393 if (!this->assembler().isStationaryProblem())
394 evalStorage(residual, scvI);
396 for (
const auto& scvf : scvfs(fvGeometry, scvI))
397 evalFlux(residual, scvf);
404 static const int numDiffMethod = getParamFromGroup<int>(this->asImp_().problem().paramGroup(),
"Assembly.NumericDifferenceMethod");
406 eps_(otherElemSol[scvJ.localDofIndex()][pvIdx], pvIdx), numDiffMethod);
408 const auto updateJacobian = [&]()
410 for (
int eqIdx = 0; eqIdx < numEq; eqIdx++)
416 A[scvI.dofIndex()][scvJ.dofIndex()][eqIdx][pvIdx] += partialDerivs[scvI.localDofIndex()][eqIdx];
420 if (element.partitionType() == Dune::InteriorEntity)
424 const auto localIdxI = scvI.indexInElement();
425 const auto& facetI = element.template subEntity <1> (localIdxI);
427 if (facetI.partitionType() == Dune::BorderEntity)
432 curOtherVolVars = origOtherVolVars;
435 otherElemSol[scvJ.localDofIndex()][pvIdx] = curSol[scvJ.dofIndex()][pvIdx];
436 this->asImp_().maybeUpdateCouplingContext(scvJ, otherElemSol, pvIdx);
442 for (
const auto& scvI : scvs(fvGeometry))
445 evalDerivative(scvI, scvI);
448 const auto& otherScvIndices = fvGeometry.gridGeometry().connectivityMap()[scvI.index()];
449 for (
const auto globalJ : otherScvIndices)
450 evalDerivative(scvI, fvGeometry.scv(globalJ));
454 this->asImp_().maybeEvalAdditionalDomainDerivatives(origResiduals, A, gridVariables);
456 return origResiduals;
466template<
class TypeTag,
class Assembler,
class Implementation>
470 Detail::NonVoidOrDefault_t<Implementation, FaceCenteredLocalAssembler<TypeTag, Assembler, DiffMethod::numeric, false, Implementation>>,
495 template <
class PartialReassembler = DefaultPartialReassembler>
499 if (partialReassembler)
500 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for explicit time discretization");
503 const auto& problem = this->asImp_().problem();
504 const auto& element = this->element();
505 const auto& fvGeometry = this->fvGeometry();
506 const auto& curSol = this->asImp_().curSol();
507 auto&& curElemVolVars = this->curElemVolVars();
510 const auto origResiduals = this->evalLocalResidual();
511 const auto origStorageResiduals = this->evalLocalStorageResidual();
522 auto elemSol =
elementSolution(element, curSol, fvGeometry.gridGeometry());
528 for (
const auto& scv : scvs(fvGeometry))
531 const auto dofIdx = scv.dofIndex();
532 auto& curVolVars = this->getVolVarAccess(gridVariables.curGridVolVars(), curElemVolVars, scv);
533 const VolumeVariables origVolVars(curVolVars);
536 for (
int pvIdx = 0; pvIdx < numEq; pvIdx++)
540 auto evalStorage = [&](Scalar priVar)
543 elemSol[scv.localDofIndex()][pvIdx] = priVar;
544 curVolVars.update(elemSol, problem, element, scv);
545 return this->evalLocalStorageResidual();
550 static const int numDiffMethod = getParamFromGroup<int>(problem.paramGroup(),
"Assembly.NumericDifferenceMethod");
552 eps_(elemSol[scv.localDofIndex()][pvIdx], pvIdx), numDiffMethod);
555 for (
int eqIdx = 0; eqIdx < numEq; eqIdx++)
561 A[dofIdx][dofIdx][eqIdx][pvIdx] += partialDerivs[scv.localDofIndex()][eqIdx];
565 curVolVars = origVolVars;
568 elemSol[scv.localDofIndex()][pvIdx] = curSol[scv.dofIndex()][pvIdx];
571 return origResiduals;
580template<
class TypeTag,
class Assembler,
class Implementation>
584 FaceCenteredLocalAssembler<TypeTag, Assembler, DiffMethod::analytic, true, Implementation>,
607 template <
class PartialReassembler = DefaultPartialReassembler>
611 if (partialReassembler)
612 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for analytic differentiation");
615 const auto& element = this->element();
616 const auto& fvGeometry = this->fvGeometry();
617 const auto& problem = this->asImp_().problem();
618 const auto& curElemVolVars = this->curElemVolVars();
619 const auto& elemFluxVarsCache = this->elemFluxVarsCache();
622 const auto origResiduals = this->evalLocalResidual();
633 for (
const auto& scv : scvs(fvGeometry))
636 const auto dofIdx = scv.dofIndex();
637 const auto& volVars = curElemVolVars[scv];
642 if (!this->assembler().isStationaryProblem())
643 this->localResidual().addStorageDerivatives(A[dofIdx][dofIdx],
652 this->localResidual().addSourceDerivatives(A[dofIdx][dofIdx],
661 for (
const auto& scvf : scvfs(fvGeometry))
663 if (!scvf.boundary())
666 this->localResidual().addFluxDerivatives(A,
679 const auto& insideScv = fvGeometry.scv(scvf.insideScvIdx());
680 if (this->elemBcTypes()[insideScv.localDofIndex()].hasNeumann())
683 this->localResidual().addRobinFluxDerivatives(A[insideScv.dofIndex()],
694 return origResiduals;
703template<
class TypeTag,
class Assembler,
class Implementation>
707 FaceCenteredLocalAssembler<TypeTag, Assembler, DiffMethod::analytic, false, Implementation>,
730 template <
class PartialReassembler = DefaultPartialReassembler>
734 if (partialReassembler)
735 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for explicit time discretization");
738 const auto& element = this->element();
739 const auto& fvGeometry = this->fvGeometry();
740 const auto& problem = this->asImp_().problem();
741 const auto& curElemVolVars = this->curElemVolVars();
744 const auto origResiduals = this->evalLocalResidual();
755 for (
const auto& scv : scvs(fvGeometry))
758 const auto dofIdx = scv.dofIndex();
759 const auto& volVars = curElemVolVars[scv];
763 this->localResidual().addStorageDerivatives(A[dofIdx][dofIdx],
771 return origResiduals;
A base class for all local assemblers.
Definition: assembly/fvlocalassemblerbase.hh:36
void bindLocalViews()
Convenience function bind and prepare all relevant variables required for the evaluation of the local...
Definition: assembly/fvlocalassemblerbase.hh:173
ElementVolumeVariables & curElemVolVars()
The current element volume variables.
Definition: assembly/fvlocalassemblerbase.hh:253
ElementBoundaryTypes & elemBcTypes()
The element's boundary types.
Definition: assembly/fvlocalassemblerbase.hh:269
Implementation & asImp_()
Definition: assembly/fvlocalassemblerbase.hh:297
ElementResidualVector evalLocalResidual() const
Convenience function to evaluate the complete local residual for the current element....
Definition: assembly/fvlocalassemblerbase.hh:108
const Problem & problem() const
The problem.
Definition: assembly/fvlocalassemblerbase.hh:229
FVElementGeometry & fvGeometry()
The global finite volume geometry.
Definition: assembly/fvlocalassemblerbase.hh:249
bool elementIsGhost() const
Returns if element is a ghost entity.
Definition: assembly/fvlocalassemblerbase.hh:241
std::decay_t< decltype(std::declval< Assembler >().localResidual())> LocalResidual
Definition: assembly/fvlocalassemblerbase.hh:55
const Element & element() const
The current element.
Definition: assembly/fvlocalassemblerbase.hh:237
Face-centered scheme local assembler using numeric differentiation and implicit time discretization.
Definition: fclocalassembler.hh:298
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition: fclocalassembler.hh:317
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:327
typename ParentType::LocalResidual LocalResidual
Definition: fclocalassembler.hh:316
TODO docme.
Definition: fclocalassembler.hh:587
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition: fclocalassembler.hh:598
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:608
typename ParentType::LocalResidual LocalResidual
Definition: fclocalassembler.hh:597
TODO docme.
Definition: fclocalassembler.hh:473
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition: fclocalassembler.hh:486
typename ParentType::LocalResidual LocalResidual
Definition: fclocalassembler.hh:485
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:496
TODO docme.
Definition: fclocalassembler.hh:710
typename ParentType::LocalResidual LocalResidual
Definition: fclocalassembler.hh:720
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition: fclocalassembler.hh:721
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:731
A base class for all local cell-centered assemblers.
Definition: fclocalassembler.hh:54
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:78
void enforceDirichletConstraints(const ApplyFunction &applyDirichlet)
Enforce Dirichlet constraints.
Definition: fclocalassembler.hh:216
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:169
void maybeUpdateCouplingContext(Args &&...)
Update the coupling context for coupled models.
Definition: fclocalassembler.hh:264
void bindLocalViews()
Definition: fclocalassembler.hh:67
void evalDirichletBoundaries(ApplyDirichletFunctionType applyDirichlet)
Evaluates Dirichlet boundaries.
Definition: fclocalassembler.hh:228
void maybeEvalAdditionalDomainDerivatives(Args &&...)
Update the additional domain derivatives for coupled models.
Definition: fclocalassembler.hh:271
void assembleResidual(ResidualVector &res)
Assemble the residual only.
Definition: fclocalassembler.hh:193
An assembler for Jacobian and residual contribution per element (Face-centered methods)
Definition: fclocalassembler.hh:284
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:29
detects which entries in the Jacobian have to be recomputed
Definition: partialreassembler.hh:420
EntityColor elementColor(size_t idx) const
Definition: partialreassembler.hh:491
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.
DiffMethod
Differentiation methods in order to compute the derivatives of the residual i.e. the entries in the j...
Definition: diffmethod.hh:25
@ green
does not need to be reassembled
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
typename GetProp< TypeTag, Property >::type GetPropType
get the type alias defined in the property
Definition: propertysystem.hh:296
std::conditional_t<!std::is_same_v< T, void >, T, Default > NonVoidOrDefault_t
Definition: fclocalassembler.hh:39
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:33
constexpr void operator()(Args &&...) const
Definition: fclocalassembler.hh:35