25#ifndef DUMUX_FC_LOCAL_ASSEMBLER_HH
26#define DUMUX_FC_LOCAL_ASSEMBLER_HH
28#include <dune/grid/common/gridenums.hh>
46 template<
class... Args>
50template<
class T,
class Default>
64template<
class TypeTag,
class Assembler,
class Implementation,
bool implicit>
78 using ParentType::ParentType;
90 template <
class PartialReassembler = DefaultPartialReassembler,
class CouplingFunction = Detail::NoOpFunctor>
93 const CouplingFunction& maybeAssembleCouplingBlocks = CouplingFunction{})
95 static_assert(!std::decay_t<
decltype(this->
asImp_().problem())>::enableInternalDirichletConstraints(),
96 "Internal Dirichlet constraints are currently not implemented for face-centered staggered models!");
98 this->
asImp_().bindLocalViews();
99 const auto& gridGeometry = this->
asImp_().problem().gridGeometry();
100 const auto eIdxGlobal = gridGeometry.elementMapper().index(this->
element());
101 if (partialReassembler
104 const auto residual = this->
asImp_().evalLocalResidual();
105 for (
const auto& scv : scvs(this->
fvGeometry()))
106 res[scv.dofIndex()] += residual[scv.localDofIndex()];
109 maybeAssembleCouplingBlocks(residual);
113 const auto residual = this->
asImp_().assembleJacobianAndResidualImpl(jac, gridVariables, partialReassembler);
115 if (this->
element().partitionType() == Dune::InteriorEntity)
117 for (
const auto& scv : scvs(this->
fvGeometry()))
118 res[scv.dofIndex()] += residual[scv.localDofIndex()];
123 for (
const auto& scv : scvs(this->
fvGeometry()))
125 const auto& facet = this->
element().template subEntity <1> (scv.indexInElement());
128 if (facet.partitionType() == Dune::BorderEntity)
129 res[scv.dofIndex()] += residual[scv.localDofIndex()];
135 const auto idx = scv.dofIndex();
137 for (
int i = 0; i < jac[idx][idx].size(); ++i)
138 jac[idx][idx][i][i] = 1.0;
145 maybeAssembleCouplingBlocks(residual);
148 DUNE_THROW(Dune::NotImplemented,
"Ghost elements not supported");
151 auto applyDirichlet = [&] (
const auto& scvI,
152 const auto& dirichletValues,
156 res[scvI.dofIndex()][eqIdx] = this->
curElemVolVars()[scvI].priVars()[pvIdx] - dirichletValues[pvIdx];
158 auto& row = jac[scvI.dofIndex()];
159 for (
auto col = row.begin(); col != row.end(); ++col)
160 row[col.index()][eqIdx] = 0.0;
162 jac[scvI.dofIndex()][scvI.dofIndex()][eqIdx][pvIdx] = 1.0;
175 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
184 this->
asImp_().bindLocalViews();
185 this->
asImp_().assembleJacobianAndResidualImpl(jac, gridVariables);
187 auto applyDirichlet = [&] (
const auto& scvI,
188 const auto& dirichletValues,
192 auto& row = jac[scvI.dofIndex()];
193 for (
auto col = row.begin(); col != row.end(); ++col)
194 row[col.index()][eqIdx] = 0.0;
196 jac[scvI.dofIndex()][scvI.dofIndex()][eqIdx][pvIdx] = 1.0;
199 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
207 this->
asImp_().bindLocalViews();
210 for (
const auto& scv : scvs(this->
fvGeometry()))
211 res[scv.dofIndex()] += residual[scv.localDofIndex()];
213 auto applyDirichlet = [&] (
const auto& scvI,
214 const auto& dirichletValues,
218 res[scvI.dofIndex()][eqIdx] = this->
curElemVolVars()[scvI].priVars()[eqIdx] - dirichletValues[pvIdx];
221 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
227 template<
typename ApplyFunction>
231 this->
asImp_().evalDirichletBoundaries(applyDirichlet);
233 this->
asImp_().enforceInternalDirichletConstraints(applyDirichlet);
239 template<
typename ApplyDirichletFunctionType >
246 for (
const auto& scvf : scvfs(this->
fvGeometry()))
248 if (scvf.isFrontal() && scvf.boundary())
250 const auto bcTypes = this->
elemBcTypes()[scvf.localIndex()];
251 if (bcTypes.hasDirichlet())
253 const auto& scv = this->
fvGeometry().scv(scvf.insideScvIdx());
254 const auto dirichletValues = this->
asImp_().problem().dirichlet(this->
element(), scvf);
257 for (
int eqIdx = 0; eqIdx < numEq; ++eqIdx)
259 for (
int pvIdx = 0; pvIdx < GridView::dimension; ++pvIdx)
261 if (bcTypes.isDirichlet(pvIdx) && pvIdx == scv.dofAxis())
262 applyDirichlet(scv, dirichletValues, eqIdx, pvIdx);
275 template<
class... Args>
282 template<
class... Args>
295template<
class TypeTag,
class Assembler, DiffMethod diffMethod = DiffMethod::numeric,
bool implicit = true,
class Implementation =
void>
303template<
class TypeTag,
class Assembler,
class Implementation>
307 Detail::NonVoidOrDefault_t<Implementation, FaceCenteredLocalAssembler<TypeTag, Assembler, DiffMethod::numeric, true, Implementation>>,
316 using FVElementGeometry =
typename GridGeometry::LocalView;
317 using SubControlVolume =
typename FVElementGeometry::SubControlVolume;
318 using SubControlVolumeFace =
typename FVElementGeometry::SubControlVolumeFace;
338 template <
class PartialReassembler = DefaultPartialReassembler>
343 const auto& problem = this->asImp_().problem();
344 const auto& element = this->element();
345 const auto& fvGeometry = this->fvGeometry();
346 const auto& curSol = this->asImp_().curSol();
347 auto&& curElemVolVars = this->curElemVolVars();
350 const auto origResiduals = this->evalLocalResidual();
361 const auto numElementResiduals = fvGeometry.numScv();
368 this->localResidual().evalSource(residual, problem, element, fvGeometry, curElemVolVars, scv);
373 this->localResidual().evalStorage(residual, problem, element, fvGeometry, this->prevElemVolVars(), curElemVolVars, scv);
378 if (!scvf.processorBoundary())
379 this->localResidual().evalFlux(residual, problem, element, fvGeometry, curElemVolVars, this->elemBcTypes(), this->elemFluxVarsCache(), scvf);
382 const auto evalDerivative = [&] (
const auto& scvI,
const auto& scvJ)
385 for (
int pvIdx = 0; pvIdx < numEq; pvIdx++)
388 const auto& otherElement = fvGeometry.gridGeometry().element(scvJ.elementIndex());
389 auto otherElemSol =
elementSolution(otherElement, curSol, fvGeometry.gridGeometry());
390 auto& curOtherVolVars = this->getVolVarAccess(gridVariables.curGridVolVars(), curElemVolVars, scvJ);
391 const VolumeVariables origOtherVolVars(curOtherVolVars);
393 auto evalResiduals = [&](Scalar priVar)
396 otherElemSol[scvJ.localDofIndex()][pvIdx] = priVar;
397 curOtherVolVars.update(otherElemSol, problem, otherElement, scvJ);
398 this->asImp_().maybeUpdateCouplingContext(scvJ, otherElemSol, pvIdx);
403 evalSource(residual, scvI);
405 if (!this->assembler().isStationaryProblem())
406 evalStorage(residual, scvI);
408 for (
const auto& scvf : scvfs(fvGeometry, scvI))
409 evalFlux(residual, scvf);
416 static const int numDiffMethod = getParamFromGroup<int>(this->asImp_().problem().paramGroup(),
"Assembly.NumericDifferenceMethod");
418 eps_(otherElemSol[scvJ.localDofIndex()][pvIdx], pvIdx), numDiffMethod);
420 const auto updateJacobian = [&]()
422 for (
int eqIdx = 0; eqIdx < numEq; eqIdx++)
428 A[scvI.dofIndex()][scvJ.dofIndex()][eqIdx][pvIdx] += partialDerivs[scvI.localDofIndex()][eqIdx];
432 using GeometryHelper =
typename std::decay_t<
decltype(fvGeometry.gridGeometry())>::GeometryHelper;
433 using LocalIntersectionMapper =
typename std::decay_t<
decltype(fvGeometry.gridGeometry())>::LocalIntersectionMapper;
434 LocalIntersectionMapper localIsMapper;
436 const bool isParallel = fvGeometry.gridGeometry().gridView().comm().size() > 1;
438 localIsMapper.update(fvGeometry.gridGeometry().gridView(), element);
440 if (element.partitionType() == Dune::InteriorEntity)
444 const auto localIdxI = scvI.indexInElement();
445 const auto localIdxJ = scvJ.indexInElement();
447 const auto& facetI = GeometryHelper::facet(localIsMapper.refToRealIdx(localIdxI), element);
449 if (facetI.partitionType() == Dune::BorderEntity &&
450 (localIdxJ == GeometryHelper::localOppositeIdx(localIdxI) || scvJ.dofIndex() == scvI.dofIndex()))
454 if (isParallel && element.partitionType() == Dune::InteriorEntity)
456 const auto localIdxI = scvI.indexInElement();
457 const auto& facetI = GeometryHelper::facet(localIsMapper.refToRealIdx(localIdxI), element);
458 if (facetI.partitionType() == Dune::BorderEntity)
460 for (
const auto& scvf : scvfs(fvGeometry, scvI))
462 if (scvf.isFrontal() || scvf.boundary())
466 if (scvf.outsideScvIdx() == scvJ.index())
471 const auto& orthogonalScvf = fvGeometry.lateralOrthogonalScvf(scvf);
472 if (orthogonalScvf.boundary())
475 if (orthogonalScvf.insideScvIdx() == scvJ.index() || orthogonalScvf.outsideScvIdx() == scvJ.index())
483 curOtherVolVars = origOtherVolVars;
486 otherElemSol[scvJ.localDofIndex()][pvIdx] = curSol[scvJ.dofIndex()][pvIdx];
487 this->asImp_().maybeUpdateCouplingContext(scvJ, otherElemSol, pvIdx);
493 for (
const auto& scvI : scvs(fvGeometry))
496 evalDerivative(scvI, scvI);
499 const auto& otherScvIndices = fvGeometry.gridGeometry().connectivityMap()[scvI.index()];
500 for (
const auto globalJ : otherScvIndices)
501 evalDerivative(scvI, fvGeometry.scv(globalJ));
505 this->asImp_().maybeEvalAdditionalDomainDerivatives(origResiduals, A, gridVariables);
507 return origResiduals;
517template<
class TypeTag,
class Assembler,
class Implementation>
521 Detail::NonVoidOrDefault_t<Implementation, FaceCenteredLocalAssembler<TypeTag, Assembler, DiffMethod::numeric, false, Implementation>>,
546 template <
class PartialReassembler = DefaultPartialReassembler>
550 if (partialReassembler)
551 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for explicit time discretization");
554 const auto& problem = this->asImp_().problem();
555 const auto& element = this->element();
556 const auto& fvGeometry = this->fvGeometry();
557 const auto& curSol = this->asImp_().curSol();
558 auto&& curElemVolVars = this->curElemVolVars();
561 const auto origResiduals = this->evalLocalResidual();
562 const auto origStorageResiduals = this->evalLocalStorageResidual();
573 auto elemSol =
elementSolution(element, curSol, fvGeometry.gridGeometry());
579 for (
const auto& scv : scvs(fvGeometry))
582 const auto dofIdx = scv.dofIndex();
583 auto& curVolVars = this->getVolVarAccess(gridVariables.curGridVolVars(), curElemVolVars, scv);
584 const VolumeVariables origVolVars(curVolVars);
587 for (
int pvIdx = 0; pvIdx < numEq; pvIdx++)
591 auto evalStorage = [&](Scalar priVar)
594 elemSol[scv.localDofIndex()][pvIdx] = priVar;
595 curVolVars.update(elemSol, problem, element, scv);
596 return this->evalLocalStorageResidual();
601 static const int numDiffMethod = getParamFromGroup<int>(problem.paramGroup(),
"Assembly.NumericDifferenceMethod");
603 eps_(elemSol[scv.localDofIndex()][pvIdx], pvIdx), numDiffMethod);
606 for (
int eqIdx = 0; eqIdx < numEq; eqIdx++)
612 A[dofIdx][dofIdx][eqIdx][pvIdx] += partialDerivs[scv.localDofIndex()][eqIdx];
616 curVolVars = origVolVars;
619 elemSol[scv.localDofIndex()][pvIdx] = curSol[scv.dofIndex()][pvIdx];
622 return origResiduals;
631template<
class TypeTag,
class Assembler,
class Implementation>
635 FaceCenteredLocalAssembler<TypeTag, Assembler, DiffMethod::analytic, true, Implementation>,
658 template <
class PartialReassembler = DefaultPartialReassembler>
662 if (partialReassembler)
663 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for analytic differentiation");
666 const auto& element = this->element();
667 const auto& fvGeometry = this->fvGeometry();
668 const auto& problem = this->asImp_().problem();
669 const auto& curElemVolVars = this->curElemVolVars();
670 const auto& elemFluxVarsCache = this->elemFluxVarsCache();
673 const auto origResiduals = this->evalLocalResidual();
684 for (
const auto& scv : scvs(fvGeometry))
687 const auto dofIdx = scv.dofIndex();
688 const auto& volVars = curElemVolVars[scv];
693 if (!this->assembler().isStationaryProblem())
694 this->localResidual().addStorageDerivatives(A[dofIdx][dofIdx],
703 this->localResidual().addSourceDerivatives(A[dofIdx][dofIdx],
712 for (
const auto& scvf : scvfs(fvGeometry))
714 if (!scvf.boundary())
717 this->localResidual().addFluxDerivatives(A,
730 const auto& insideScv = fvGeometry.scv(scvf.insideScvIdx());
731 if (this->elemBcTypes()[insideScv.localDofIndex()].hasNeumann())
734 this->localResidual().addRobinFluxDerivatives(A[insideScv.dofIndex()],
745 return origResiduals;
754template<
class TypeTag,
class Assembler,
class Implementation>
758 FaceCenteredLocalAssembler<TypeTag, Assembler, DiffMethod::analytic, false, Implementation>,
781 template <
class PartialReassembler = DefaultPartialReassembler>
785 if (partialReassembler)
786 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for explicit time discretization");
789 const auto& element = this->element();
790 const auto& fvGeometry = this->fvGeometry();
791 const auto& problem = this->asImp_().problem();
792 const auto& curElemVolVars = this->curElemVolVars();
795 const auto origResiduals = this->evalLocalResidual();
806 for (
const auto& scv : scvs(fvGeometry))
809 const auto dofIdx = scv.dofIndex();
810 const auto& volVars = curElemVolVars[scv];
814 this->localResidual().addStorageDerivatives(A[dofIdx][dofIdx],
822 return origResiduals;
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.
An adapter class for local assemblers using numeric differentiation.
Detects which entries in the Jacobian have to be recomputed.
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.
A class for numeric differentiation.
auto elementSolution(const Element &element, const SolutionVector &sol, const GridGeometry &gg) -> std::enable_if_t< GridGeometry::discMethod==DiscretizationMethods::box, BoxElementSolution< typename GridGeometry::LocalView, std::decay_t< decltype(std::declval< SolutionVector >()[0])> > >
Make an element solution for box schemes.
Definition: box/elementsolution.hh:118
DiffMethod
Differentiation methods in order to compute the derivatives of the residual i.e. the entries in the j...
Definition: diffmethod.hh:37
@ green
does not need to be reassembled
Adaption of the non-isothermal two-phase two-component flow model to problems with CO2.
Definition: adapt.hh:29
typename GetProp< TypeTag, Property >::type GetPropType
get the type alias defined in the property
Definition: propertysystem.hh:180
std::conditional_t<!std::is_same_v< T, void >, T, Default > NonVoidOrDefault_t
Definition: fclocalassembler.hh:51
Definition: fclocalassembler.hh:45
constexpr void operator()(Args &&...) const
Definition: fclocalassembler.hh:47
A base class for all local cell-centered assemblers.
Definition: fclocalassembler.hh:66
void enforceDirichletConstraints(const ApplyFunction &applyDirichlet)
Enforce Dirichlet constraints.
Definition: fclocalassembler.hh:228
void assembleResidual(SolutionVector &res)
Assemble the residual only.
Definition: fclocalassembler.hh:205
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:182
void assembleJacobianAndResidual(JacobianMatrix &jac, SolutionVector &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:91
void maybeUpdateCouplingContext(Args &&...)
Update the coupling context for coupled models.
Definition: fclocalassembler.hh:276
void bindLocalViews()
Definition: fclocalassembler.hh:80
void evalDirichletBoundaries(ApplyDirichletFunctionType applyDirichlet)
Evaluates Dirichlet boundaries.
Definition: fclocalassembler.hh:240
void maybeEvalAdditionalDomainDerivatives(Args &&...)
Update the additional domain derivatives for coupled models.
Definition: fclocalassembler.hh:283
An assembler for Jacobian and residual contribution per element (Face-centered methods)
Definition: fclocalassembler.hh:296
Face-centered scheme local assembler using numeric differentiation and implicit time discretization.
Definition: fclocalassembler.hh:310
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition: fclocalassembler.hh:329
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:339
GetPropType< TypeTag, Properties::LocalResidual > LocalResidual
Definition: fclocalassembler.hh:328
TODO docme.
Definition: fclocalassembler.hh:524
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition: fclocalassembler.hh:537
GetPropType< TypeTag, Properties::LocalResidual > LocalResidual
Definition: fclocalassembler.hh:536
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:547
TODO docme.
Definition: fclocalassembler.hh:638
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition: fclocalassembler.hh:649
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:659
GetPropType< TypeTag, Properties::LocalResidual > LocalResidual
Definition: fclocalassembler.hh:648
TODO docme.
Definition: fclocalassembler.hh:761
GetPropType< TypeTag, Properties::LocalResidual > LocalResidual
Definition: fclocalassembler.hh:771
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition: fclocalassembler.hh:772
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:782
A base class for all local assemblers.
Definition: fvlocalassemblerbase.hh:48
void bindLocalViews()
Convenience function bind and prepare all relevant variables required for the evaluation of the local...
Definition: fvlocalassemblerbase.hh:185
ElementVolumeVariables & curElemVolVars()
The current element volume variables.
Definition: fvlocalassemblerbase.hh:265
ElementBoundaryTypes & elemBcTypes()
The element's boundary types.
Definition: fvlocalassemblerbase.hh:281
Implementation & asImp_()
Definition: fvlocalassemblerbase.hh:309
ElementResidualVector evalLocalResidual() const
Convenience function to evaluate the complete local residual for the current element....
Definition: fvlocalassemblerbase.hh:120
const Problem & problem() const
The problem.
Definition: fvlocalassemblerbase.hh:241
FVElementGeometry & fvGeometry()
The global finite volume geometry.
Definition: fvlocalassemblerbase.hh:261
bool elementIsGhost() const
Returns if element is a ghost entity.
Definition: fvlocalassemblerbase.hh:253
const Element & element() const
The current element.
Definition: fvlocalassemblerbase.hh:249
A helper class for local assemblers using numeric differentiation to determine the epsilon.
Definition: numericepsilon.hh:41
detects which entries in the Jacobian have to be recomputed
Definition: partialreassembler.hh:432
EntityColor elementColor(size_t idx) const
Definition: partialreassembler.hh:503
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:61
Declares all properties used in Dumux.