25#ifndef DUMUX_BOX_LOCAL_ASSEMBLER_HH
26#define DUMUX_BOX_LOCAL_ASSEMBLER_HH
28#include <dune/common/reservedvector.hh>
29#include <dune/istl/matrixindexset.hh>
30#include <dune/istl/bvector.hh>
48template<
class VolVarAccessor,
class FVElementGeometry>
49class VolVarsDeflectionHelper
51 static constexpr int maxNumscvs = FVElementGeometry::maxNumElementScvs;
53 using SubControlVolume =
typename FVElementGeometry::GridGeometry::SubControlVolume;
54 using VolumeVariablesRef = std::invoke_result_t<VolVarAccessor, const SubControlVolume&>;
55 using VolumeVariables = std::decay_t<VolumeVariablesRef>;
56 static_assert(std::is_lvalue_reference_v<VolumeVariablesRef>
57 && !std::is_const_v<std::remove_reference_t<VolumeVariablesRef>>);
60 VolVarsDeflectionHelper(VolVarAccessor&& accessor,
61 const FVElementGeometry& fvGeometry,
62 bool deflectAllVolVars)
63 : deflectAll_(deflectAllVolVars)
64 , accessor_(std::move(accessor))
65 , fvGeometry_(fvGeometry)
68 for (
const auto& curScv : scvs(fvGeometry))
69 origVolVars_.push_back(accessor_(curScv));
72 void setCurrent(
const SubControlVolume& scv)
77 origVolVars_.push_back(accessor_(scv));
81 template<
class ElementSolution,
class Problem>
82 void deflect(
const ElementSolution& elemSol,
83 const SubControlVolume& scv,
84 const Problem& problem)
87 for (
const auto& curScv : scvs(fvGeometry_))
88 accessor_(curScv).update(elemSol, problem, fvGeometry_.element(), curScv);
90 accessor_(scv).update(elemSol, problem, fvGeometry_.element(), scv);
93 void restore(
const SubControlVolume& scv)
96 accessor_(scv) = origVolVars_[0];
98 for (
const auto& curScv : scvs(fvGeometry_))
99 accessor_(curScv) = origVolVars_[curScv.localDofIndex()];
103 const bool deflectAll_;
104 VolVarAccessor accessor_;
105 const FVElementGeometry& fvGeometry_;
106 Dune::ReservedVector<VolumeVariables, maxNumscvs> origVolVars_;
109template<
class Accessor,
class FVElementGeometry>
110VolVarsDeflectionHelper(Accessor&&, FVElementGeometry&&) -> VolVarsDeflectionHelper<Accessor, std::decay_t<FVElementGeometry>>;
124template<
class TypeTag,
class Assembler,
class Implementation,
bool implicit>
137 using ParentType::ParentType;
150 template <
class PartialReassembler = DefaultPartialReassembler>
154 this->
asImp_().bindLocalViews();
155 const auto eIdxGlobal = this->
assembler().gridGeometry().elementMapper().index(this->
element());
156 if (partialReassembler
159 const auto residual = this->
asImp_().evalLocalResidual();
160 for (
const auto& scv : scvs(this->
fvGeometry()))
161 res[scv.dofIndex()] += residual[scv.localDofIndex()];
165 const auto residual = this->
asImp_().assembleJacobianAndResidualImpl(jac, gridVariables, partialReassembler);
166 for (
const auto& scv : scvs(this->
fvGeometry()))
167 res[scv.dofIndex()] += residual[scv.localDofIndex()];
171 using GridGeometry =
typename GridVariables::GridGeometry;
172 using GridView =
typename GridGeometry::GridView;
173 static constexpr auto dim = GridView::dimension;
175 int numVerticesLocal = this->
element().subEntities(dim);
177 for (
int i = 0; i < numVerticesLocal; ++i) {
178 auto vertex = this->
element().template subEntity<dim>(i);
180 if (vertex.partitionType() == Dune::InteriorEntity ||
181 vertex.partitionType() == Dune::BorderEntity)
188 int vIdx = this->
assembler().gridGeometry().vertexMapper().index(vertex);
190 typedef typename JacobianMatrix::block_type BlockType;
191 BlockType &J = jac[vIdx][vIdx];
192 for (
int j = 0; j < BlockType::rows; ++j)
200 auto applyDirichlet = [&] (
const auto& scvI,
201 const auto& dirichletValues,
205 res[scvI.dofIndex()][eqIdx] = this->
curElemVolVars()[scvI].priVars()[pvIdx] - dirichletValues[pvIdx];
207 auto& row = jac[scvI.dofIndex()];
208 for (
auto col = row.begin(); col != row.end(); ++col)
209 row[col.index()][eqIdx] = 0.0;
211 jac[scvI.dofIndex()][scvI.dofIndex()][eqIdx][pvIdx] = 1.0;
214 if (this->
assembler().gridGeometry().dofOnPeriodicBoundary(scvI.dofIndex()))
216 const auto periodicDof = this->
assembler().gridGeometry().periodicallyMappedDof(scvI.dofIndex());
217 res[periodicDof][eqIdx] = this->
curElemVolVars()[scvI].priVars()[pvIdx] - dirichletValues[pvIdx];
218 const auto end = jac[periodicDof].end();
219 for (
auto it = jac[periodicDof].begin(); it != end; ++it)
220 (*it) = periodicDof != it.index() ? 0.0 : 1.0;
224 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
233 this->
asImp_().bindLocalViews();
234 this->
asImp_().assembleJacobianAndResidualImpl(jac, gridVariables);
236 auto applyDirichlet = [&] (
const auto& scvI,
237 const auto& dirichletValues,
241 auto& row = jac[scvI.dofIndex()];
242 for (
auto col = row.begin(); col != row.end(); ++col)
243 row[col.index()][eqIdx] = 0.0;
245 jac[scvI.dofIndex()][scvI.dofIndex()][eqIdx][pvIdx] = 1.0;
248 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
256 this->
asImp_().bindLocalViews();
259 for (
const auto& scv : scvs(this->
fvGeometry()))
260 res[scv.dofIndex()] += residual[scv.localDofIndex()];
262 auto applyDirichlet = [&] (
const auto& scvI,
263 const auto& dirichletValues,
267 res[scvI.dofIndex()][eqIdx] = this->
curElemVolVars()[scvI].priVars()[pvIdx] - dirichletValues[pvIdx];
270 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
274 template<
typename ApplyFunction>
278 this->
asImp_().evalDirichletBoundaries(applyDirichlet);
280 this->
asImp_().enforceInternalDirichletConstraints(applyDirichlet);
286 template<
typename ApplyDirichletFunctionType >
293 for (
const auto& scvI : scvs(this->
fvGeometry()))
295 const auto bcTypes = this->
elemBcTypes()[scvI.localDofIndex()];
296 if (bcTypes.hasDirichlet())
298 const auto dirichletValues = this->
problem().dirichlet(this->
element(), scvI);
301 for (
int eqIdx = 0; eqIdx < numEq; ++eqIdx)
303 if (bcTypes.isDirichlet(eqIdx))
305 const auto pvIdx = bcTypes.eqToDirichletIndex(eqIdx);
306 assert(0 <= pvIdx && pvIdx < numEq);
307 applyDirichlet(scvI, dirichletValues, eqIdx, pvIdx);
325template<
class TypeTag,
class Assembler, DiffMethod diffMethod = DiffMethod::numeric,
bool implicit = true>
333template<
class TypeTag,
class Assembler>
336 BoxLocalAssembler<TypeTag, Assembler, DiffMethod::numeric, true>, true>
345 using ElementResidualVector =
typename LocalResidual::ElementResidualVector;
354 using ParentType::ParentType;
362 template <
class PartialReassembler = DefaultPartialReassembler>
386 this->problem().paramGroup(),
"Assembly.BoxVolVarsDependOnAllElementDofs",
false
393 ElementResidualVector partialDerivs(
element.subEntities(dim));
395 Detail::VolVarsDeflectionHelper deflectionHelper(
396 [&] (
const auto& scv) -> VolumeVariables& {
407 const auto dofIdx = scv.dofIndex();
408 deflectionHelper.setCurrent(scv);
411 for (
int pvIdx = 0; pvIdx < numEq; pvIdx++)
415 auto evalResiduals = [&](Scalar priVar)
418 elemSol[scv.localDofIndex()][pvIdx] = priVar;
419 deflectionHelper.deflect(elemSol, scv, this->problem());
425 static const int numDiffMethod =
getParamFromGroup<int>(this->problem().paramGroup(),
"Assembly.NumericDifferenceMethod");
427 eps_(elemSol[scv.localDofIndex()][pvIdx], pvIdx), numDiffMethod);
433 if (!partialReassembler
436 for (
int eqIdx = 0; eqIdx < numEq; eqIdx++)
442 A[scvJ.dofIndex()][dofIdx][eqIdx][pvIdx] += partialDerivs[scvJ.localDofIndex()][eqIdx];
448 deflectionHelper.restore(scv);
451 elemSol[scv.localDofIndex()][pvIdx] =
curSol[scv.dofIndex()][pvIdx];
454 return origResiduals;
464template<
class TypeTag,
class Assembler>
467 BoxLocalAssembler<TypeTag, Assembler, DiffMethod::numeric, false>, false>
476 using ElementResidualVector =
typename LocalResidual::ElementResidualVector;
483 using ParentType::ParentType;
491 template <
class PartialReassembler = DefaultPartialReassembler>
495 if (partialReassembler)
496 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for explicit time discretization");
520 ElementResidualVector partialDerivs(
element.subEntities(dim));
526 const auto dofIdx = scv.dofIndex();
528 const VolumeVariables origVolVars(curVolVars);
531 for (
int pvIdx = 0; pvIdx < numEq; pvIdx++)
535 auto evalStorage = [&](Scalar priVar)
538 elemSol[scv.localDofIndex()][pvIdx] = priVar;
539 curVolVars.update(elemSol, this->problem(),
element, scv);
545 static const int numDiffMethod =
getParamFromGroup<int>(this->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];
567 return origResiduals;
576template<
class TypeTag,
class Assembler>
579 BoxLocalAssembler<TypeTag, Assembler, DiffMethod::analytic, true>, true>
586 using ElementResidualVector =
typename LocalResidual::ElementResidualVector;
590 using ParentType::ParentType;
598 template <
class PartialReassembler = DefaultPartialReassembler>
602 if (partialReassembler)
603 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for analytic differentiation");
608 const auto&
problem = this->problem();
627 const auto dofIdx = scv.dofIndex();
633 if (!this->
assembler().isStationaryProblem())
634 this->
localResidual().addStorageDerivatives(A[dofIdx][dofIdx],
643 this->
localResidual().addSourceDerivatives(A[dofIdx][dofIdx],
654 if (!scvf.boundary())
670 const auto& insideScv =
fvGeometry.scv(scvf.insideScvIdx());
671 if (this->
elemBcTypes()[insideScv.localDofIndex()].hasNeumann())
674 this->
localResidual().addRobinFluxDerivatives(A[insideScv.dofIndex()],
685 return origResiduals;
695template<
class TypeTag,
class Assembler>
698 BoxLocalAssembler<TypeTag, Assembler, DiffMethod::analytic, false>, false>
705 using ElementResidualVector =
typename LocalResidual::ElementResidualVector;
709 using ParentType::ParentType;
717 template <
class PartialReassembler = DefaultPartialReassembler>
721 if (partialReassembler)
722 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for explicit time discretization");
727 const auto&
problem = this->problem();
745 const auto dofIdx = scv.dofIndex();
750 this->
localResidual().addStorageDerivatives(A[dofIdx][dofIdx],
758 return origResiduals;
A class for numeric differentiation.
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.
A base class for all local assemblers.
An adapter class for local assemblers using numeric differentiation.
An enum class to define the colors of elements and vertices required for partial Jacobian reassembly.
Detects which entries in the Jacobian have to be recomputed.
An enum class to define various differentiation methods available in order to compute the derivatives...
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
@ analytic
Definition diffmethod.hh:38
@ numeric
Definition diffmethod.hh:38
@ green
does not need to be reassembled
Definition entitycolor.hh:52
T getParamFromGroup(Args &&... args)
A free function to get a parameter from the parameter tree singleton with a model group.
Definition parameters.hh:161
constexpr auto getPropValue()
get the value data member of a property
Definition propertysystem.hh:154
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property
Definition propertysystem.hh:150
Distance implementation details.
Definition fclocalassembler.hh:42
A base class for all local box assemblers.
Definition boxlocalassembler.hh:126
void assembleJacobian(JacobianMatrix &jac, GridVariables &gridVariables)
Computes the derivatives with respect to the given element and adds them to the global matrix.
Definition boxlocalassembler.hh:231
void evalDirichletBoundaries(ApplyDirichletFunctionType applyDirichlet)
Evaluates Dirichlet boundaries.
Definition boxlocalassembler.hh:287
void enforceDirichletConstraints(const ApplyFunction &applyDirichlet)
Enforce Dirichlet constraints.
Definition boxlocalassembler.hh:275
void bindLocalViews()
Definition boxlocalassembler.hh:139
void assembleResidual(SolutionVector &res)
Assemble the residual only.
Definition boxlocalassembler.hh:254
void assembleJacobianAndResidual(JacobianMatrix &jac, SolutionVector &res, GridVariables &gridVariables, const PartialReassembler *partialReassembler=nullptr)
Computes the derivatives with respect to the given element and adds them to the global matrix....
Definition boxlocalassembler.hh:151
An assembler for Jacobian and residual contribution per element (box methods).
Definition boxlocalassembler.hh:326
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 boxlocalassembler.hh:363
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 boxlocalassembler.hh:492
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 boxlocalassembler.hh:599
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 boxlocalassembler.hh:718
void bindLocalViews()
Definition fvlocalassemblerbase.hh:185
ElementVolumeVariables & curElemVolVars()
Definition fvlocalassemblerbase.hh:265
ElementBoundaryTypes & elemBcTypes()
Definition fvlocalassemblerbase.hh:281
Implementation & asImp_()
Definition fvlocalassemblerbase.hh:309
ElementResidualVector evalLocalResidual() const
Definition fvlocalassemblerbase.hh:120
const Problem & problem() const
Definition fvlocalassemblerbase.hh:241
FVLocalAssemblerBase(const Assembler &assembler, const Element &element, const SolutionVector &curSol)
Definition fvlocalassemblerbase.hh:73
FVElementGeometry & fvGeometry()
Definition fvlocalassemblerbase.hh:261
const Assembler & assembler() const
Definition fvlocalassemblerbase.hh:245
ElementFluxVariablesCache & elemFluxVarsCache()
Definition fvlocalassemblerbase.hh:273
bool elementIsGhost() const
Definition fvlocalassemblerbase.hh:253
LocalResidual & localResidual()
Definition fvlocalassemblerbase.hh:277
const Element & element() const
Definition fvlocalassemblerbase.hh:249
VolumeVariables & getVolVarAccess(GridVolumeVariables &gridVolVars, ElementVolumeVariables &elemVolVars, const SubControlVolume &scv)
Definition fvlocalassemblerbase.hh:316
ElementResidualVector evalLocalStorageResidual() const
Definition fvlocalassemblerbase.hh:176
const SolutionVector & curSol() const
Definition fvlocalassemblerbase.hh:257
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
static void partialDerivative(const Function &function, Scalar x0, FunctionEvalType &derivative, const FunctionEvalType &fx0, const int numericDifferenceMethod=1)
Computes the derivative of a function with repect to a function parameter.
Definition numericdifferentiation.hh:61
The local element solution class for the box method.
Declares all properties used in Dumux.