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;
318 using ParentType::ParentType;
326 template <
class PartialReassembler = DefaultPartialReassembler>
349 const auto numElementResiduals =
fvGeometry.numScv();
366 if (!scvf.processorBoundary())
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());
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);
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 using GeometryHelper =
typename std::decay_t<
decltype(
fvGeometry.gridGeometry())>::GeometryHelper;
421 using LocalIntersectionMapper =
typename std::decay_t<
decltype(
fvGeometry.gridGeometry())>::LocalIntersectionMapper;
422 LocalIntersectionMapper localIsMapper;
424 const bool isParallel =
fvGeometry.gridGeometry().gridView().comm().size() > 1;
428 if (
element.partitionType() == Dune::InteriorEntity)
432 const auto localIdxI = scvI.indexInElement();
433 const auto localIdxJ = scvJ.indexInElement();
435 const auto& facetI = GeometryHelper::facet(localIsMapper.refToRealIdx(localIdxI),
element);
437 if (facetI.partitionType() == Dune::BorderEntity &&
438 (localIdxJ == GeometryHelper::localOppositeIdx(localIdxI) || scvJ.dofIndex() == scvI.dofIndex()))
442 if (isParallel &&
element.partitionType() == Dune::InteriorEntity)
444 const auto localIdxI = scvI.indexInElement();
445 const auto& facetI = GeometryHelper::facet(localIsMapper.refToRealIdx(localIdxI),
element);
446 if (facetI.partitionType() == Dune::BorderEntity)
448 for (
const auto& scvf : scvfs(
fvGeometry, scvI))
450 if (scvf.isFrontal() || scvf.boundary())
454 if (scvf.outsideScvIdx() == scvJ.index())
459 const auto& orthogonalScvf =
fvGeometry.lateralOrthogonalScvf(scvf);
460 if (orthogonalScvf.boundary())
463 if (orthogonalScvf.insideScvIdx() == scvJ.index() || orthogonalScvf.outsideScvIdx() == scvJ.index())
471 curOtherVolVars = origOtherVolVars;
474 otherElemSol[scvJ.localDofIndex()][pvIdx] =
curSol[scvJ.dofIndex()][pvIdx];
475 this->
asImp_().maybeUpdateCouplingContext(scvJ, otherElemSol, pvIdx);
484 evalDerivative(scvI, scvI);
487 const auto& otherScvIndices =
fvGeometry.gridGeometry().connectivityMap()[scvI.index()];
488 for (
const auto globalJ : otherScvIndices)
489 evalDerivative(scvI,
fvGeometry.scv(globalJ));
493 this->
asImp_().maybeEvalAdditionalDomainDerivatives(origResiduals, A, gridVariables);
495 return origResiduals;
505template<
class TypeTag,
class Assembler,
class Implementation>
509 Detail::NonVoidOrDefault_t<Implementation, FaceCenteredLocalAssembler<TypeTag, Assembler, DiffMethod::numeric, false, Implementation>>,
526 using ParentType::ParentType;
534 template <
class PartialReassembler = DefaultPartialReassembler>
538 if (partialReassembler)
539 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for explicit time discretization");
570 const auto dofIdx = scv.dofIndex();
572 const VolumeVariables origVolVars(curVolVars);
575 for (
int pvIdx = 0; pvIdx < numEq; pvIdx++)
579 auto evalStorage = [&](Scalar priVar)
582 elemSol[scv.localDofIndex()][pvIdx] = priVar;
591 eps_(elemSol[scv.localDofIndex()][pvIdx], pvIdx), numDiffMethod);
594 for (
int eqIdx = 0; eqIdx < numEq; eqIdx++)
600 A[dofIdx][dofIdx][eqIdx][pvIdx] += partialDerivs[scv.localDofIndex()][eqIdx];
604 curVolVars = origVolVars;
607 elemSol[scv.localDofIndex()][pvIdx] =
curSol[scv.dofIndex()][pvIdx];
610 return origResiduals;
619template<
class TypeTag,
class Assembler,
class Implementation>
623 FaceCenteredLocalAssembler<TypeTag, Assembler, DiffMethod::analytic, true, Implementation>,
638 using ParentType::ParentType;
646 template <
class PartialReassembler = DefaultPartialReassembler>
650 if (partialReassembler)
651 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for analytic differentiation");
675 const auto dofIdx = scv.dofIndex();
681 if (!this->
assembler().isStationaryProblem())
682 this->
localResidual().addStorageDerivatives(A[dofIdx][dofIdx],
691 this->
localResidual().addSourceDerivatives(A[dofIdx][dofIdx],
702 if (!scvf.boundary())
718 const auto& insideScv =
fvGeometry.scv(scvf.insideScvIdx());
719 if (this->
elemBcTypes()[insideScv.localDofIndex()].hasNeumann())
722 this->
localResidual().addRobinFluxDerivatives(A[insideScv.dofIndex()],
733 return origResiduals;
742template<
class TypeTag,
class Assembler,
class Implementation>
746 FaceCenteredLocalAssembler<TypeTag, Assembler, DiffMethod::analytic, false, Implementation>,
761 using ParentType::ParentType;
769 template <
class PartialReassembler = DefaultPartialReassembler>
773 if (partialReassembler)
774 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for explicit time discretization");
797 const auto dofIdx = scv.dofIndex();
802 this->
localResidual().addStorageDerivatives(A[dofIdx][dofIdx],
810 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: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
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition fclocalassembler.hh:637
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:647
typename ParentType::LocalResidual LocalResidual
Definition fclocalassembler.hh:636
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition fclocalassembler.hh:525
typename ParentType::LocalResidual LocalResidual
Definition fclocalassembler.hh:524
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:535
typename ParentType::LocalResidual LocalResidual
Definition fclocalassembler.hh:759
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition fclocalassembler.hh:760
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:770
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:49
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.
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:149
typename GetProp< TypeTag, Property >::type GetPropType
get the type alias defined in the property
Definition propertysystem.hh:296
Distance implementation details.
Definition cvfelocalresidual.hh:25
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