26#ifndef DUMUX_MULTIDOMAIN_BOX_LOCAL_ASSEMBLER_HH
27#define DUMUX_MULTIDOMAIN_BOX_LOCAL_ASSEMBLER_HH
29#include <dune/common/reservedvector.hh>
30#include <dune/common/indices.hh>
31#include <dune/common/hybridutilities.hh>
32#include <dune/grid/common/gridenums.hh>
33#include <dune/istl/matrixindexset.hh>
57template<std::
size_t id,
class TypeTag,
class Assembler,
class Implementation,
bool implicit>
66 using SolutionVector =
typename Assembler::SolutionVector;
71 using GridVolumeVariables =
typename GridVariables::GridVolumeVariables;
72 using ElementVolumeVariables =
typename GridVolumeVariables::LocalView;
73 using ElementFluxVariablesCache =
typename GridVariables::GridFluxVariablesCache::LocalView;
74 using Scalar =
typename GridVariables::Scalar;
76 using GridGeometry =
typename GridVariables::GridGeometry;
77 using FVElementGeometry =
typename GridGeometry::LocalView;
78 using SubControlVolume =
typename GridGeometry::SubControlVolume;
79 using SubControlVolumeFace =
typename GridGeometry::SubControlVolumeFace;
81 using GridView =
typename GridGeometry::GridView;
82 using Element =
typename GridView::template Codim<0>::Entity;
84 using CouplingManager =
typename Assembler::CouplingManager;
90 static constexpr auto domainId =
typename Dune::index_constant<id>();
92 using ParentType::ParentType;
97 const SolutionVector&
curSol,
115 template<
class JacobianMatrixRow,
class Gr
idVariablesTuple>
118 this->
asImp_().bindLocalViews();
125 const auto residual = this->
asImp_().assembleJacobianAndResidualImpl(jacRow[
domainId], *std::get<domainId>(gridVariables));
128 for (
const auto& scv : scvs(this->
fvGeometry()))
129 res[scv.dofIndex()] += residual[scv.localDofIndex()];
132 using namespace Dune::Hybrid;
133 forEach(integralRange(Dune::Hybrid::size(jacRow)), [&](
auto&& i)
141 using GridGeometry =
typename GridVariables::GridGeometry;
142 using GridView =
typename GridGeometry::GridView;
143 static constexpr auto dim = GridView::dimension;
145 int numVerticesLocal = this->
element().subEntities(dim);
147 for (
int i = 0; i < numVerticesLocal; ++i)
149 const auto vertex = this->
element().template subEntity<dim>(i);
151 if (vertex.partitionType() == Dune::InteriorEntity ||
152 vertex.partitionType() == Dune::BorderEntity)
159 const auto vIdx = this->
assembler().gridGeometry(
domainId).vertexMapper().index(vertex);
161 typedef typename JacobianMatrix::block_type BlockType;
162 BlockType &J = jacRow[
domainId][vIdx][vIdx];
163 for (
int j = 0; j < BlockType::rows; ++j)
172 auto applyDirichlet = [&] (
const auto& scvI,
173 const auto& dirichletValues,
177 res[scvI.dofIndex()][eqIdx] = this->
curElemVolVars()[scvI].priVars()[pvIdx] - dirichletValues[pvIdx];
183 for (
const auto& scvJ : scvs(this->
fvGeometry()))
184 jacRow[
domainId][scvI.dofIndex()][scvJ.dofIndex()][eqIdx] = 0.0;
187 jacRow[
domainId][scvI.dofIndex()][scvI.dofIndex()][eqIdx][pvIdx] = 1.0;
191 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
198 template<std::size_t otherId,
class JacRow,
class GridVariables,
199 typename std::enable_if_t<(otherId == id),
int> = 0>
201 const ElementResidualVector& res, GridVariables& gridVariables)
207 template<std::size_t otherId,
class JacRow,
class GridVariables,
208 typename std::enable_if_t<(otherId != id),
int> = 0>
210 const ElementResidualVector& res, GridVariables& gridVariables)
212 this->
asImp_().assembleJacobianCoupling(domainJ, jacRow[domainJ], res, *std::get<domainId>(gridVariables));
220 this->
asImp_().bindLocalViews();
224 for (
const auto& scv : scvs(this->
fvGeometry()))
225 res[scv.dofIndex()] += residual[scv.localDofIndex()];
227 auto applyDirichlet = [&] (
const auto& scvI,
228 const auto& dirichletValues,
232 res[scvI.dofIndex()][eqIdx] = this->
curElemVolVars()[scvI].priVars()[pvIdx] - dirichletValues[pvIdx];
235 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
244 ElementResidualVector residual(this->
fvGeometry().numScv());
250 const auto& curVolVars = elemVolVars[scv];
252 source *= -Extrusion::volume(scv)*curVolVars.extrusionFactor();
253 residual[scv.localDofIndex()] = std::move(source);
266 template<
typename ApplyFunction>
270 this->
asImp_().evalDirichletBoundaries(applyDirichlet);
272 this->
asImp_().enforceInternalDirichletConstraints(applyDirichlet);
279 template<
typename ApplyDirichletFunctionType >
286 for (
const auto& scvI : scvs(this->
fvGeometry()))
288 const auto bcTypes = this->
elemBcTypes()[scvI.localDofIndex()];
289 if (bcTypes.hasDirichlet())
291 const auto dirichletValues = this->
problem().dirichlet(this->
element(), scvI);
294 for (
int eqIdx = 0; eqIdx < numEq; ++eqIdx)
296 if (bcTypes.isDirichlet(eqIdx))
298 const auto pvIdx = bcTypes.eqToDirichletIndex(eqIdx);
299 assert(0 <= pvIdx && pvIdx < numEq);
300 applyDirichlet(scvI, dirichletValues, eqIdx, pvIdx);
328 if (!this->
assembler().isStationaryProblem())
348 {
return couplingManager_; }
365template<std::
size_t id,
class TypeTag,
class Assembler, DiffMethod DM = DiffMethod::numeric,
bool implicit = true>
374template<std::
size_t id,
class TypeTag,
class Assembler>
383 using ElementResidualVector =
typename ParentType::LocalResidual::ElementResidualVector;
387 using FVElementGeometry =
typename GridGeometry::LocalView;
388 using GridView =
typename GridGeometry::GridView;
389 using Element =
typename GridView::template Codim<0>::Entity;
392 enum { dim = GridView::dimension };
394 static constexpr bool enableGridFluxVarsCache = getPropValue<TypeTag, Properties::EnableGridFluxVariablesCache>();
395 static constexpr bool enableGridVolVarsCache = getPropValue<TypeTag, Properties::EnableGridVolumeVariablesCache>();
396 static constexpr auto domainI = Dune::index_constant<id>();
407 template<
class JacobianMatrixDiagBlock,
class Gr
idVariables>
417 const auto origResiduals = this->evalLocalResidual();
422 const auto& element = this->element();
423 const auto& fvGeometry = this->fvGeometry();
424 const auto& curSol = this->curSol()[domainI];
425 auto&& curElemVolVars = this->curElemVolVars();
428 auto elemSol =
elementSolution(element, curSol, fvGeometry.gridGeometry());
430 auto partialDerivs = origResiduals;
433 for (
auto&& scv : scvs(fvGeometry))
436 const auto dofIdx = scv.dofIndex();
437 auto& curVolVars = this->getVolVarAccess(gridVariables.curGridVolVars(), curElemVolVars, scv);
438 const VolumeVariables origVolVars(curVolVars);
441 for (
int pvIdx = 0; pvIdx < numEq; pvIdx++)
445 auto evalResiduals = [&](Scalar priVar)
448 const auto localDofIndex = scv.localDofIndex();
449 elemSol[localDofIndex][pvIdx] = priVar;
450 curVolVars.update(elemSol, this->problem(), element, scv);
451 this->couplingManager().updateCouplingContext(domainI, *
this, domainI, scv.dofIndex(), elemSol[localDofIndex], pvIdx);
452 return this->evalLocalResidual();
456 static const int numDiffMethod = getParamFromGroup<int>(this->problem().paramGroup(),
"Assembly.NumericDifferenceMethod");
459 eps_(elemSol[scv.localDofIndex()][pvIdx], pvIdx), numDiffMethod);
462 for (
auto&& scvJ : scvs(fvGeometry))
464 for (
int eqIdx = 0; eqIdx < numEq; eqIdx++)
470 A[scvJ.dofIndex()][dofIdx][eqIdx][pvIdx] += partialDerivs[scvJ.localDofIndex()][eqIdx];
475 curVolVars = origVolVars;
478 elemSol[scv.localDofIndex()][pvIdx] = curSol[scv.dofIndex()][pvIdx];
479 this->couplingManager().updateCouplingContext(domainI, *
this, domainI, scv.dofIndex(), elemSol[scv.localDofIndex()], pvIdx);
484 this->couplingManager().evalAdditionalDomainDerivatives(domainI, *
this, origResiduals, A, gridVariables);
486 return origResiduals;
495 template<std::
size_t otherId,
class JacobianBlock,
class Gr
idVariables>
497 const ElementResidualVector& res, GridVariables& gridVariables)
504 const auto& element = this->element();
505 const auto& fvGeometry = this->fvGeometry();
506 auto&& curElemVolVars = this->curElemVolVars();
507 auto&& elemFluxVarsCache = this->elemFluxVarsCache();
510 const auto& stencil = this->couplingManager().couplingStencil(domainI, element, domainJ);
513 auto updateCoupledVariables = [&] ()
517 if (enableGridFluxVarsCache)
519 if (enableGridVolVarsCache)
520 this->couplingManager().updateCoupledVariables(domainI, *
this, gridVariables.curGridVolVars(), gridVariables.gridFluxVarsCache());
522 this->couplingManager().updateCoupledVariables(domainI, *
this, curElemVolVars, gridVariables.gridFluxVarsCache());
526 if (enableGridVolVarsCache)
527 this->couplingManager().updateCoupledVariables(domainI, *
this, gridVariables.curGridVolVars(), elemFluxVarsCache);
529 this->couplingManager().updateCoupledVariables(domainI, *
this, curElemVolVars, elemFluxVarsCache);
533 const auto& curSolJ = this->curSol()[domainJ];
534 for (
const auto globalJ : stencil)
537 const auto origPriVarsJ = curSolJ[globalJ];
538 auto priVarsJ = origPriVarsJ;
541 const auto origResidual = this->couplingManager().evalCouplingResidual(domainI, *
this, domainJ, globalJ);
543 for (
int pvIdx = 0; pvIdx < JacobianBlock::block_type::cols; ++pvIdx)
545 auto evalCouplingResidual = [&](Scalar priVar)
547 priVarsJ[pvIdx] = priVar;
548 this->couplingManager().updateCouplingContext(domainI, *
this, domainJ, globalJ, priVarsJ, pvIdx);
549 updateCoupledVariables();
550 return this->couplingManager().evalCouplingResidual(domainI, *
this, domainJ, globalJ);
554 ElementResidualVector partialDerivs(element.subEntities(dim));
556 const auto& paramGroup = this->assembler().problem(domainJ).paramGroup();
557 static const int numDiffMethod = getParamFromGroup<int>(paramGroup,
"Assembly.NumericDifferenceMethod");
558 static const auto epsCoupl = this->couplingManager().numericEpsilon(domainJ, paramGroup);
561 epsCoupl(origPriVarsJ[pvIdx], pvIdx), numDiffMethod);
564 for (
auto&& scv : scvs(fvGeometry))
566 for (
int eqIdx = 0; eqIdx < numEq; eqIdx++)
576 const auto bcTypes = this->elemBcTypes()[scv.localDofIndex()];
577 if (bcTypes.isCouplingDirichlet(eqIdx))
578 A[scv.dofIndex()][globalJ][eqIdx][pvIdx] = partialDerivs[scv.localDofIndex()][eqIdx];
579 else if (bcTypes.isDirichlet(eqIdx))
580 A[scv.dofIndex()][globalJ][eqIdx][pvIdx] = 0.0;
582 A[scv.dofIndex()][globalJ][eqIdx][pvIdx] += partialDerivs[scv.localDofIndex()][eqIdx];
587 priVarsJ[pvIdx] = origPriVarsJ[pvIdx];
590 this->couplingManager().updateCouplingContext(domainI, *
this, domainJ, globalJ, priVarsJ, pvIdx);
597 updateCoupledVariables();
608template<std::
size_t id,
class TypeTag,
class Assembler>
611 SubDomainBoxLocalAssembler<id, TypeTag, Assembler, DiffMethod::numeric, false>, false >
617 using ElementResidualVector =
typename ParentType::LocalResidual::ElementResidualVector;
620 using FVElementGeometry =
typename GridGeometry::LocalView;
621 using GridView =
typename GridGeometry::GridView;
622 using Element =
typename GridView::template Codim<0>::Entity;
625 enum { dim = GridView::dimension };
627 static constexpr bool enableGridFluxVarsCache = getPropValue<TypeTag, Properties::EnableGridFluxVariablesCache>();
628 static constexpr bool enableGridVolVarsCache = getPropValue<TypeTag, Properties::EnableGridVolumeVariablesCache>();
629 static constexpr auto domainI = Dune::index_constant<id>();
640 template<
class JacobianMatrixDiagBlock,
class Gr
idVariables>
643 if (this->assembler().isStationaryProblem())
644 DUNE_THROW(Dune::InvalidStateException,
"Using explicit jacobian assembler with stationary local residual");
647 const auto& element = this->element();
648 const auto& fvGeometry = this->fvGeometry();
649 const auto& curSol = this->curSol()[domainI];
650 auto&& curElemVolVars = this->curElemVolVars();
653 const auto origResiduals = this->evalLocalResidual();
654 const auto origStorageResiduals = this->evalLocalStorageResidual();
663 auto elemSol =
elementSolution(element, curSol, fvGeometry.gridGeometry());
666 ElementResidualVector partialDerivs(element.subEntities(dim));
669 for (
auto&& scv : scvs(fvGeometry))
672 const auto dofIdx = scv.dofIndex();
673 auto& curVolVars = this->getVolVarAccess(gridVariables.curGridVolVars(), curElemVolVars, scv);
674 const VolumeVariables origVolVars(curVolVars);
677 for (
int pvIdx = 0; pvIdx < numEq; pvIdx++)
681 auto evalStorage = [&](Scalar priVar)
684 elemSol[scv.localDofIndex()][pvIdx] = priVar;
685 curVolVars.update(elemSol, this->problem(), element, scv);
686 return this->evalLocalStorageResidual();
691 static const int numDiffMethod = getParamFromGroup<int>(this->problem().paramGroup(),
"Assembly.NumericDifferenceMethod");
693 eps_(elemSol[scv.localDofIndex()][pvIdx], pvIdx), numDiffMethod);
696 for (
int eqIdx = 0; eqIdx < numEq; eqIdx++)
702 A[dofIdx][dofIdx][eqIdx][pvIdx] += partialDerivs[scv.localDofIndex()][eqIdx];
706 curVolVars = origVolVars;
709 elemSol[scv.localDofIndex()][pvIdx] = curSol[scv.dofIndex()][pvIdx];
715 return origResiduals;
724 template<std::
size_t otherId,
class JacobianBlock,
class Gr
idVariables>
726 const ElementResidualVector& res, GridVariables& gridVariables)
A class for numeric differentiation.
A arithmetic block vector type based on DUNE's reserved vector.
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.
An adapter class for local assemblers using numeric differentiation.
An enum class to define various differentiation methods available in order to compute the derivatives...
Helper classes to compute the integration elements.
GridCache::LocalView localView(const GridCache &gridCache)
Free function to get the local view of a grid cache object.
Definition: localview.hh:38
auto elementSolution(const Element &element, const SolutionVector &sol, const GridGeometry &gg) -> std::enable_if_t< GridGeometry::discMethod==DiscretizationMethod::box, BoxElementSolution< typename GridGeometry::LocalView, std::decay_t< decltype(std::declval< SolutionVector >()[0])> > >
Make an element solution for box schemes.
Definition: box/elementsolution.hh:115
DiffMethod
Differentiation methods in order to compute the derivatives of the residual i.e. the entries in the j...
Definition: diffmethod.hh:37
typename Extrusion< T >::type Extrusion_t
Convenience alias for obtaining the extrusion type.
Definition: extrusion.hh:177
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property (equivalent to old macro GET_PROP_TYPE(....
Definition: propertysystem.hh:149
Definition: common/pdesolver.hh:35
A base class for all local assemblers.
Definition: fvlocalassemblerbase.hh:48
ElementVolumeVariables & curElemVolVars()
The current element volume variables.
Definition: fvlocalassemblerbase.hh:265
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition: fvlocalassemblerbase.hh:68
ElementBoundaryTypes & elemBcTypes()
The element's boundary types.
Definition: fvlocalassemblerbase.hh:281
Implementation & asImp_()
Definition: fvlocalassemblerbase.hh:309
ElementVolumeVariables & prevElemVolVars()
The element volume variables of the provious time step.
Definition: fvlocalassemblerbase.hh:269
ElementResidualVector evalLocalResidual() const
Convenience function to evaluate the complete local residual for the current element....
Definition: fvlocalassemblerbase.hh:120
FVElementGeometry & fvGeometry()
The global finite volume geometry.
Definition: fvlocalassemblerbase.hh:261
const Assembler & assembler() const
The assembler.
Definition: fvlocalassemblerbase.hh:245
ElementFluxVariablesCache & elemFluxVarsCache()
The element flux variables cache.
Definition: fvlocalassemblerbase.hh:273
bool elementIsGhost() const
Returns if element is a ghost entity.
Definition: fvlocalassemblerbase.hh:253
LocalResidual & localResidual()
The local residual for the current element.
Definition: fvlocalassemblerbase.hh:277
const Element & element() const
The current element.
Definition: fvlocalassemblerbase.hh:249
const SolutionVector & curSol() const
The current solution.
Definition: fvlocalassemblerbase.hh:257
A helper class for local assemblers using numeric differentiation to determine the epsilon.
Definition: numericepsilon.hh:41
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
Definition: multidomain/couplingmanager.hh:46
A base class for all box local assemblers.
Definition: subdomainboxlocalassembler.hh:59
void enforceDirichletConstraints(const ApplyFunction &applyDirichlet)
Enforce Dirichlet constraints.
Definition: subdomainboxlocalassembler.hh:267
void bindLocalViews()
Prepares all local views necessary for local assembly.
Definition: subdomainboxlocalassembler.hh:311
static constexpr auto domainId
export the domain id of this sub-domain
Definition: subdomainboxlocalassembler.hh:90
ElementResidualVector evalLocalSourceResidual(const Element &element, const ElementVolumeVariables &elemVolVars) const
Evaluates the local source term for an element and given element volume variables.
Definition: subdomainboxlocalassembler.hh:241
CouplingManager & couplingManager()
return reference to the coupling manager
Definition: subdomainboxlocalassembler.hh:347
ElementResidualVector evalLocalSourceResidual(const Element &neighbor) const
Evaluates the local source term depending on time discretization scheme.
Definition: subdomainboxlocalassembler.hh:262
void evalDirichletBoundaries(ApplyDirichletFunctionType applyDirichlet)
Incorporate Dirichlet boundary conditions.
Definition: subdomainboxlocalassembler.hh:280
void assembleResidual(SubSolutionVector &res)
Assemble the residual vector entries only.
Definition: subdomainboxlocalassembler.hh:218
void assembleJacobianCoupling(Dune::index_constant< otherId > domainJ, JacRow &jacRow, const ElementResidualVector &res, GridVariables &gridVariables)
Assemble the entries in a coupling block of the jacobian. There is no coupling block between a domain...
Definition: subdomainboxlocalassembler.hh:200
const Problem & problem() const
return reference to the underlying problem
Definition: subdomainboxlocalassembler.hh:343
void assembleJacobianAndResidual(JacobianMatrixRow &jacRow, SubSolutionVector &res, GridVariablesTuple &gridVariables)
Computes the derivatives with respect to the given element and adds them to the global matrix....
Definition: subdomainboxlocalassembler.hh:116
SubDomainBoxLocalAssemblerBase(const Assembler &assembler, const Element &element, const SolutionVector &curSol, CouplingManager &couplingManager)
Definition: subdomainboxlocalassembler.hh:95
The box scheme multidomain local assembler.
Definition: subdomainboxlocalassembler.hh:366
Box scheme multi domain local assembler using numeric differentiation and implicit time discretizatio...
Definition: subdomainboxlocalassembler.hh:378
ElementResidualVector assembleJacobianAndResidualImpl(JacobianMatrixDiagBlock &A, GridVariables &gridVariables)
Computes the derivatives with respect to the given element and adds them to the global matrix.
Definition: subdomainboxlocalassembler.hh:408
void assembleJacobianCoupling(Dune::index_constant< otherId > domainJ, JacobianBlock &A, const ElementResidualVector &res, GridVariables &gridVariables)
Computes the derivatives with respect to the given element and adds them to the global matrix.
Definition: subdomainboxlocalassembler.hh:496
Box scheme multi domain local assembler using numeric differentiation and explicit time discretizatio...
Definition: subdomainboxlocalassembler.hh:612
ElementResidualVector assembleJacobianAndResidualImpl(JacobianMatrixDiagBlock &A, GridVariables &gridVariables)
Computes the derivatives with respect to the given element and adds them to the global matrix.
Definition: subdomainboxlocalassembler.hh:641
void assembleJacobianCoupling(Dune::index_constant< otherId > domainJ, JacobianBlock &A, const ElementResidualVector &res, GridVariables &gridVariables)
Computes the coupling derivatives with respect to the given element and adds them to the global matri...
Definition: subdomainboxlocalassembler.hh:725
Declares all properties used in Dumux.