25#ifndef DUMUX_ASSEMBLY_PQ1BUBBLE_LOCAL_ASSEMBLER_HH
26#define DUMUX_ASSEMBLY_PQ1BUBBLE_LOCAL_ASSEMBLER_HH
28#include <dune/grid/common/gridenums.hh>
41#include "volvardeflectionhelper_.hh"
49 template<
class... Args>
53template<
class X,
class Y>
54using Impl = std::conditional_t<!std::is_same_v<X, void>, X, Y>;
67template<
class TypeTag,
class Assembler,
class Implementation,
bool implicit>
78 static constexpr int dim = GridView::dimension;
82 using ParentType::ParentType;
94 template <
class PartialReassembler = DefaultPartialReassembler,
class CouplingFunction = Detail::PQ1Bubble::NoOperator>
97 const CouplingFunction& maybeAssembleCouplingBlocks = CouplingFunction())
99 static_assert(!std::decay_t<
decltype(this->
asImp_().problem())>::enableInternalDirichletConstraints(),
"Internal Dirichlet constraints are currently not implemented for face-centered staggered models!");
101 this->
asImp_().bindLocalViews();
102 const auto& gridGeometry = this->
asImp_().problem().gridGeometry();
103 const auto eIdxGlobal = gridGeometry.elementMapper().index(this->
element());
104 if (partialReassembler
107 const auto residual = this->
asImp_().evalLocalResidual();
108 for (
const auto& scv : scvs(this->
fvGeometry()))
109 res[scv.dofIndex()] += residual[scv.localDofIndex()];
112 maybeAssembleCouplingBlocks(residual);
116 const auto residual = this->
asImp_().assembleJacobianAndResidualImpl(jac, gridVariables, partialReassembler);
117 for (
const auto& scv : scvs(this->
fvGeometry()))
118 res[scv.dofIndex()] += residual[scv.localDofIndex()];
121 maybeAssembleCouplingBlocks(residual);
128 const auto numVerticesLocal = this->
element().subEntities(dim);
129 for (
int i = 0; i < numVerticesLocal; ++i)
132 auto vertex = this->
element().template subEntity<dim>(i);
133 if (vertex.partitionType() == Dune::InteriorEntity || vertex.partitionType() == Dune::BorderEntity)
137 const auto dofIndex = gridGeometry.dofMapper().index(vertex);
140 typedef typename JacobianMatrix::block_type
BlockType;
142 for (
int j = 0; j < BlockType::rows; ++j)
150 const auto elemDofIndex = gridGeometry.dofMapper().index(this->
element());
153 typedef typename JacobianMatrix::block_type
BlockType;
154 BlockType &J = jac[elemDofIndex][elemDofIndex];
155 for (
int j = 0; j < BlockType::rows; ++j)
159 res[elemDofIndex] = 0;
162 auto applyDirichlet = [&] (
const auto& scvI,
163 const auto& dirichletValues,
167 res[scvI.dofIndex()][eqIdx] = this->
curElemVolVars()[scvI].priVars()[pvIdx] - dirichletValues[pvIdx];
169 auto& row = jac[scvI.dofIndex()];
170 for (
auto col = row.begin(); col != row.end(); ++col)
171 row[col.index()][eqIdx] = 0.0;
173 jac[scvI.dofIndex()][scvI.dofIndex()][eqIdx][pvIdx] = 1.0;
187 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
196 this->
asImp_().bindLocalViews();
197 this->
asImp_().assembleJacobianAndResidualImpl(jac, gridVariables);
199 auto applyDirichlet = [&] (
const auto& scvI,
200 const auto& dirichletValues,
204 auto& row = jac[scvI.dofIndex()];
205 for (
auto col = row.begin(); col != row.end(); ++col)
206 row[col.index()][eqIdx] = 0.0;
208 jac[scvI.dofIndex()][scvI.dofIndex()][eqIdx][pvIdx] = 1.0;
211 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
219 this->
asImp_().bindLocalViews();
222 for (
const auto& scv : scvs(this->
fvGeometry()))
223 res[scv.dofIndex()] += residual[scv.localDofIndex()];
225 auto applyDirichlet = [&] (
const auto& scvI,
226 const auto& dirichletValues,
230 res[scvI.dofIndex()][eqIdx] = this->
curElemVolVars()[scvI].priVars()[pvIdx] - dirichletValues[pvIdx];
233 this->
asImp_().enforceDirichletConstraints(applyDirichlet);
239 template<
typename ApplyFunction>
243 this->
asImp_().evalDirichletBoundaries(applyDirichlet);
245 this->
asImp_().enforceInternalDirichletConstraints(applyDirichlet);
251 template<
typename ApplyDirichletFunctionType >
258 for (
const auto& scvI : scvs(this->
fvGeometry()))
261 if (bcTypes.hasDirichlet())
263 const auto dirichletValues = this->
asImp_().problem().dirichlet(this->
element(), scvI);
266 for (
int eqIdx = 0; eqIdx < numEq; ++eqIdx)
268 if (bcTypes.isDirichlet(eqIdx))
270 const auto pvIdx = bcTypes.eqToDirichletIndex(eqIdx);
271 assert(0 <= pvIdx && pvIdx < numEq);
272 applyDirichlet(scvI, dirichletValues, eqIdx, pvIdx);
284 template<
class... Args>
291 template<
class... Args>
303template<
class TypeTag,
class Assembler, DiffMethod diffMethod = DiffMethod::numeric,
bool implicit = true,
class Implementation =
void>
311template<
class TypeTag,
class Assembler,
class Implementation>
314 Detail::PQ1Bubble::Impl<Implementation, PQ1BubbleLocalAssembler<TypeTag, Assembler, DiffMethod::numeric, true, Implementation>>, true>
321 using FVElementGeometry =
typename GridGeometry::LocalView;
322 using SubControlVolume =
typename FVElementGeometry::SubControlVolume;
323 using SubControlVolumeFace =
typename FVElementGeometry::SubControlVolumeFace;
343 template <
class PartialReassembler = DefaultPartialReassembler>
348 const auto& problem = this->asImp_().problem();
349 const auto& element = this->element();
350 const auto& fvGeometry = this->fvGeometry();
351 const auto& curSol = this->asImp_().curSol();
353 auto&& curElemVolVars = this->curElemVolVars();
356 const auto origResiduals = this->evalLocalResidual();
364 static const bool updateAllVolVars = getParamFromGroup<bool>(
365 this->asImp_().problem().paramGroup(),
"Assembly.PQ1BubbleVolVarsDependOnAllElementDofs",
false
369 auto elemSol =
elementSolution(element, curSol, fvGeometry.gridGeometry());
372 const auto numElementResiduals = fvGeometry.numScv();
377 Detail::VolVarsDeflectionHelper deflectionHelper(
378 [&] (
const auto& scv) -> VolumeVariables& {
379 return this->getVolVarAccess(gridVariables.curGridVolVars(), curElemVolVars, scv);
386 for (
const auto& scv : scvs(fvGeometry))
389 const auto dofIdx = scv.dofIndex();
390 deflectionHelper.setCurrent(scv);
393 for (
int pvIdx = 0; pvIdx < numEq; pvIdx++)
397 auto evalResiduals = [&](Scalar priVar)
400 elemSol[scv.localDofIndex()][pvIdx] = priVar;
401 deflectionHelper.deflect(elemSol, scv, problem);
402 this->asImp_().maybeUpdateCouplingContext(scv, elemSol, pvIdx);
403 return this->evalLocalResidual();
408 static const int numDiffMethod = getParamFromGroup<int>(problem.paramGroup(),
"Assembly.NumericDifferenceMethod");
410 eps_(elemSol[scv.localDofIndex()][pvIdx], pvIdx), numDiffMethod);
413 for (
const auto& scvJ : scvs(fvGeometry))
416 for (
int eqIdx = 0; eqIdx < numEq; eqIdx++)
422 A[scvJ.dofIndex()][dofIdx][eqIdx][pvIdx] += partialDerivs[scvJ.localDofIndex()][eqIdx];
427 deflectionHelper.restore(scv);
430 elemSol[scv.localDofIndex()][pvIdx] = curSol[scv.dofIndex()][pvIdx];
431 this->asImp_().maybeUpdateCouplingContext(scv, elemSol, pvIdx);
435 return origResiduals;
445template<
class TypeTag,
class Assembler>
448 PQ1BubbleLocalAssembler<TypeTag, Assembler, DiffMethod::numeric, false>, false>
457 using ElementResidualVector =
typename LocalResidual::ElementResidualVector;
471 template <
class PartialReassembler = DefaultPartialReassembler>
475 if (partialReassembler)
476 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for explicit time discretization");
479 const auto& problem = this->asImp_().problem();
480 const auto& element = this->element();
481 const auto& fvGeometry = this->fvGeometry();
482 const auto& curSol = this->asImp_().curSol();
483 auto&& curElemVolVars = this->curElemVolVars();
486 const auto origResiduals = this->evalLocalResidual();
487 const auto origStorageResiduals = this->evalLocalStorageResidual();
498 auto elemSol =
elementSolution(element, curSol, fvGeometry.gridGeometry());
501 ElementResidualVector partialDerivs(fvGeometry.numScv());
504 for (
auto&& scv : scvs(fvGeometry))
507 const auto dofIdx = scv.dofIndex();
508 auto& curVolVars = this->getVolVarAccess(gridVariables.curGridVolVars(), curElemVolVars, scv);
509 const VolumeVariables origVolVars(curVolVars);
512 for (
int pvIdx = 0; pvIdx < numEq; pvIdx++)
516 auto evalStorage = [&](Scalar priVar)
519 elemSol[scv.localDofIndex()][pvIdx] = priVar;
520 curVolVars.update(elemSol, problem, element, scv);
521 return this->evalLocalStorageResidual();
526 static const int numDiffMethod = getParamFromGroup<int>(problem.paramGroup(),
"Assembly.NumericDifferenceMethod");
528 eps_(elemSol[scv.localDofIndex()][pvIdx], pvIdx), numDiffMethod);
531 for (
int eqIdx = 0; eqIdx < numEq; eqIdx++)
537 A[dofIdx][dofIdx][eqIdx][pvIdx] += partialDerivs[scv.localDofIndex()][eqIdx];
541 curVolVars = origVolVars;
544 elemSol[scv.localDofIndex()][pvIdx] = curSol[scv.dofIndex()][pvIdx];
548 return origResiduals;
557template<
class TypeTag,
class Assembler>
560 PQ1BubbleLocalAssembler<TypeTag, Assembler, DiffMethod::analytic, true>, true>
567 using ElementResidualVector =
typename LocalResidual::ElementResidualVector;
581 template <
class PartialReassembler = DefaultPartialReassembler>
585 if (partialReassembler)
586 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for analytic differentiation");
589 const auto& element = this->element();
590 const auto& fvGeometry = this->fvGeometry();
591 const auto& problem = this->asImp_().problem();
592 const auto& curElemVolVars = this->curElemVolVars();
593 const auto& elemFluxVarsCache = this->elemFluxVarsCache();
596 const auto origResiduals = this->evalLocalResidual();
607 for (
const auto& scv : scvs(fvGeometry))
610 const auto dofIdx = scv.dofIndex();
611 const auto& volVars = curElemVolVars[scv];
616 if (!this->assembler().isStationaryProblem())
617 this->localResidual().addStorageDerivatives(A[dofIdx][dofIdx],
626 this->localResidual().addSourceDerivatives(A[dofIdx][dofIdx],
635 for (
const auto& scvf : scvfs(fvGeometry))
637 if (!scvf.boundary())
640 this->localResidual().addFluxDerivatives(A,
653 const auto& insideScv = fvGeometry.scv(scvf.insideScvIdx());
654 if (this->elemBcTypes().get(fvGeometry, insideScv).hasNeumann())
657 this->localResidual().addRobinFluxDerivatives(A[insideScv.dofIndex()],
668 return origResiduals;
677template<
class TypeTag,
class Assembler>
680 PQ1BubbleLocalAssembler<TypeTag, Assembler, DiffMethod::analytic, false>, false>
687 using ElementResidualVector =
typename LocalResidual::ElementResidualVector;
701 template <
class PartialReassembler = DefaultPartialReassembler>
705 if (partialReassembler)
706 DUNE_THROW(Dune::NotImplemented,
"partial reassembly for explicit time discretization");
709 const auto& element = this->element();
710 const auto& fvGeometry = this->fvGeometry();
711 const auto& problem = this->asImp_().problem();
712 const auto& curElemVolVars = this->curElemVolVars();
715 const auto origResiduals = this->evalLocalResidual();
726 for (
const auto& scv : scvs(fvGeometry))
729 const auto dofIdx = scv.dofIndex();
730 const auto& volVars = curElemVolVars[scv];
734 this->localResidual().addStorageDerivatives(A[dofIdx][dofIdx],
742 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.
An assembler for Jacobian and residual contribution per element (box method)
Detects which entries in the Jacobian have to be recomputed.
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.
A class for numeric differentiation.
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
Adaption of the non-isothermal two-phase two-component flow model to problems with CO2.
Definition: adapt.hh:29
typename GetProp< TypeTag, Property >::type GetPropType
get the type alias defined in the property
Definition: propertysystem.hh:180
typename BlockTypeHelper< SolutionVector, Dune::IsNumber< SolutionVector >::value >::type BlockType
Definition: nonlinear/newtonsolver.hh:198
CVFE< CVFEMethods::PQ1Bubble > PQ1Bubble
Definition: method.hh:97
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
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
EntityColor elementColor(size_t idx) const
Definition: partialreassembler.hh:503
Definition: pq1bubblelocalassembler.hh:48
constexpr void operator()(Args &&...) const
Definition: pq1bubblelocalassembler.hh:50
A base class for all local pq1bubble assemblers.
Definition: pq1bubblelocalassembler.hh:69
void assembleJacobian(JacobianMatrix &jac, GridVariables &gridVariables)
Computes the derivatives with respect to the given element and adds them to the global matrix.
Definition: pq1bubblelocalassembler.hh:194
void assembleJacobianAndResidual(JacobianMatrix &jac, SolutionVector &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: pq1bubblelocalassembler.hh:95
void enforceDirichletConstraints(const ApplyFunction &applyDirichlet)
Enforce Dirichlet constraints.
Definition: pq1bubblelocalassembler.hh:240
void maybeUpdateCouplingContext(Args &&...)
Update the coupling context for coupled models.
Definition: pq1bubblelocalassembler.hh:285
void maybeEvalAdditionalDomainDerivatives(Args &&...)
Update the additional domain derivatives for coupled models.
Definition: pq1bubblelocalassembler.hh:292
void evalDirichletBoundaries(ApplyDirichletFunctionType applyDirichlet)
Evaluates Dirichlet boundaries.
Definition: pq1bubblelocalassembler.hh:252
void bindLocalViews()
Definition: pq1bubblelocalassembler.hh:84
void assembleResidual(SolutionVector &res)
Assemble the residual only.
Definition: pq1bubblelocalassembler.hh:217
An assembler for Jacobian and residual contribution per element (PQ1Bubble methods)
Definition: pq1bubblelocalassembler.hh:304
Face-centered scheme local assembler using numeric differentiation and implicit time discretization.
Definition: pq1bubblelocalassembler.hh:315
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: pq1bubblelocalassembler.hh:344
typename LocalResidual::ElementResidualVector ElementResidualVector
Definition: pq1bubblelocalassembler.hh:334
GetPropType< TypeTag, Properties::LocalResidual > LocalResidual
Definition: pq1bubblelocalassembler.hh:333
TODO docme.
Definition: pq1bubblelocalassembler.hh:449
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: pq1bubblelocalassembler.hh:472
TODO docme.
Definition: pq1bubblelocalassembler.hh:561
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: pq1bubblelocalassembler.hh:582
TODO docme.
Definition: pq1bubblelocalassembler.hh:681
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: pq1bubblelocalassembler.hh:702
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:61
Declares all properties used in Dumux.
The local element solution class for the pq1bubble method.