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;
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;
350 static constexpr bool enableGridFluxVarsCache = getPropValue<TypeTag, Properties::EnableGridFluxVariablesCache>();
362 template <
class PartialReassembler = DefaultPartialReassembler>
367 const auto& element = this->element();
368 const auto& fvGeometry = this->fvGeometry();
369 const auto& curSol = this->curSol();
370 auto&& curElemVolVars = this->curElemVolVars();
373 const auto origResiduals = this->evalLocalResidual();
385 static const bool updateAllVolVars = getParamFromGroup<bool>(
386 this->problem().paramGroup(),
"Assembly.BoxVolVarsDependOnAllElementDofs",
false
390 auto elemSol =
elementSolution(element, curSol, fvGeometry.gridGeometry());
393 ElementResidualVector partialDerivs(element.subEntities(dim));
395 Detail::VolVarsDeflectionHelper deflectionHelper(
396 [&] (
const auto& scv) -> VolumeVariables& {
397 return this->getVolVarAccess(gridVariables.curGridVolVars(), curElemVolVars, scv);
404 for (
auto&& scv : scvs(fvGeometry))
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());
420 return this->evalLocalResidual();
425 static const int numDiffMethod = getParamFromGroup<int>(this->problem().paramGroup(),
"Assembly.NumericDifferenceMethod");
427 eps_(elemSol[scv.localDofIndex()][pvIdx], pvIdx), numDiffMethod);
430 for (
auto&& scvJ : scvs(fvGeometry))
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;
491 template <
class PartialReassembler = DefaultPartialReassembler>
495 if (partialReassembler)
496 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for explicit time discretization");
499 const auto& element = this->element();
500 const auto& fvGeometry = this->fvGeometry();
501 const auto& curSol = this->curSol();
502 auto&& curElemVolVars = this->curElemVolVars();
505 const auto origResiduals = this->evalLocalResidual();
506 const auto origStorageResiduals = this->evalLocalStorageResidual();
517 auto elemSol =
elementSolution(element, curSol, fvGeometry.gridGeometry());
520 ElementResidualVector partialDerivs(element.subEntities(dim));
523 for (
auto&& scv : scvs(fvGeometry))
526 const auto dofIdx = scv.dofIndex();
527 auto& curVolVars = this->getVolVarAccess(gridVariables.curGridVolVars(), curElemVolVars, scv);
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);
540 return this->evalLocalStorageResidual();
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;
598 template <
class PartialReassembler = DefaultPartialReassembler>
602 if (partialReassembler)
603 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for analytic differentiation");
606 const auto& element = this->element();
607 const auto& fvGeometry = this->fvGeometry();
608 const auto& problem = this->problem();
609 const auto& curElemVolVars = this->curElemVolVars();
610 const auto& elemFluxVarsCache = this->elemFluxVarsCache();
613 const auto origResiduals = this->evalLocalResidual();
624 for (
const auto& scv : scvs(fvGeometry))
627 const auto dofIdx = scv.dofIndex();
628 const auto& volVars = curElemVolVars[scv];
633 if (!this->assembler().isStationaryProblem())
634 this->localResidual().addStorageDerivatives(A[dofIdx][dofIdx],
643 this->localResidual().addSourceDerivatives(A[dofIdx][dofIdx],
652 for (
const auto& scvf : scvfs(fvGeometry))
654 if (!scvf.boundary())
657 this->localResidual().addFluxDerivatives(A,
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;
717 template <
class PartialReassembler = DefaultPartialReassembler>
721 if (partialReassembler)
722 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for explicit time discretization");
725 const auto& element = this->element();
726 const auto& fvGeometry = this->fvGeometry();
727 const auto& problem = this->problem();
728 const auto& curElemVolVars = this->curElemVolVars();
731 const auto origResiduals = this->evalLocalResidual();
742 for (
const auto& scv : scvs(fvGeometry))
745 const auto dofIdx = scv.dofIndex();
746 const auto& volVars = curElemVolVars[scv];
750 this->localResidual().addStorageDerivatives(A[dofIdx][dofIdx],
758 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.
A class for numeric differentiation.
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.
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
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property
Definition: propertysystem.hh:150
typename BlockTypeHelper< SolutionVector, Dune::IsNumber< SolutionVector >::value >::type BlockType
Definition: nonlinear/newtonsolver.hh:198
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
Box local assembler using numeric differentiation and implicit time discretization.
Definition: boxlocalassembler.hh:337
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
Box local assembler using numeric differentiation and explicit time discretization.
Definition: boxlocalassembler.hh:468
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
Box local assembler using analytic differentiation and implicit time discretization.
Definition: boxlocalassembler.hh:580
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
Box local assembler using analytic differentiation and explicit time discretization.
Definition: boxlocalassembler.hh:699
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
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
const Assembler & assembler() const
The assembler.
Definition: fvlocalassemblerbase.hh:245
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
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
Declares all properties used in Dumux.
The local element solution class for the box method.