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)
An enum class to define various differentiation methods available in order to compute the derivatives...
An adapter class for local assemblers using numeric differentiation.
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.
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.