25#ifndef DUMUX_CC_LOCAL_ASSEMBLER_HH
26#define DUMUX_CC_LOCAL_ASSEMBLER_HH
28#include <dune/common/reservedvector.hh>
29#include <dune/grid/common/gridenums.hh>
30#include <dune/istl/matrixindexset.hh>
56template<
class TypeTag,
class Assembler,
class Implementation,
bool implicit>
69 using ParentType::ParentType;
75 template <
class PartialReassembler = DefaultPartialReassembler>
79 this->
asImp_().bindLocalViews();
80 const auto globalI = this->
assembler().gridGeometry().elementMapper().index(this->
element());
81 if (partialReassembler
84 res[globalI] = this->
asImp_().evalLocalResidual()[0];
88 res[globalI] = this->
asImp_().assembleJacobianAndResidualImpl(jac, gridVariables);
98 this->
asImp_().bindLocalViews();
99 this->
asImp_().assembleJacobianAndResidualImpl(jac, gridVariables);
107 this->
asImp_().bindLocalViews();
108 const auto globalI = this->
assembler().gridGeometry().elementMapper().index(this->
element());
109 res[globalI] = this->
asImp_().evalLocalResidual()[0];
112 if constexpr (Problem::enableInternalDirichletConstraints())
114 const auto applyDirichlet = [&] (
const auto& scvI,
115 const auto& dirichletValues,
119 res[scvI.dofIndex()][eqIdx] = this->
curElemVolVars()[scvI].priVars()[pvIdx] - dirichletValues[pvIdx];
122 this->
asImp_().enforceInternalDirichletConstraints(applyDirichlet);
135template<
class TypeTag,
class Assembler, DiffMethod diffMethod = DiffMethod::numeric,
bool implicit = true>
143template<
class TypeTag,
class Assembler>
146 CCLocalAssembler<TypeTag, Assembler, DiffMethod::numeric, true>, true >
154 using FVElementGeometry =
typename GridGeometry::LocalView;
157 using Problem =
typename GridVariables::GridVolumeVariables::Problem;
163 static constexpr int maxElementStencilSize = GridGeometry::maxElementStencilSize;
164 static constexpr bool enableGridFluxVarsCache = getPropValue<TypeTag, Properties::EnableGridFluxVariablesCache>();
185 const auto& element = this->element();
186 const auto& fvGeometry = this->fvGeometry();
187 const auto& gridGeometry = this->assembler().gridGeometry();
188 auto&& curElemVolVars = this->curElemVolVars();
189 auto&& elemFluxVarsCache = this->elemFluxVarsCache();
192 const auto globalI = gridGeometry.elementMapper().index(element);
193 const auto& connectivityMap = gridGeometry.connectivityMap();
194 const auto numNeighbors = connectivityMap[globalI].size();
197 Dune::ReservedVector<Element, maxElementStencilSize> neighborElements;
198 neighborElements.resize(numNeighbors);
202 Residuals origResiduals(numNeighbors + 1); origResiduals = 0.0;
203 origResiduals[0] = this->evalLocalResidual()[0];
208 auto evalNeighborFlux = [&] (
const auto& neighbor,
const auto& scvf)
210 if (neighbor.partitionType() == Dune::GhostEntity)
213 return this->localResidual().evalFlux(this->problem(),
216 this->curElemVolVars(),
217 this->elemFluxVarsCache(), scvf);
223 for (
const auto& dataJ : connectivityMap[globalI])
225 neighborElements[j-1] = gridGeometry.element(dataJ.globalJ);
226 for (
const auto scvfIdx : dataJ.scvfsJ)
227 origResiduals[j] += evalNeighborFlux(neighborElements[j-1], fvGeometry.scvf(scvfIdx));
233 const auto& scv = fvGeometry.scv(globalI);
234 auto& curVolVars = ParentType::getVolVarAccess(gridVariables.curGridVolVars(), curElemVolVars, scv);
238 const auto& curSol = this->curSol();
239 const auto origPriVars = curSol[globalI];
240 const auto origVolVars = curVolVars;
247 Residuals partialDerivs(numNeighbors + 1);
249 for (
int pvIdx = 0; pvIdx < numEq; ++pvIdx)
253 auto evalResiduals = [&](Scalar priVar)
255 Residuals partialDerivsTmp(numNeighbors + 1);
256 partialDerivsTmp = 0.0;
258 elemSol[0][pvIdx] = priVar;
259 curVolVars.update(elemSol, this->problem(), element, scv);
260 elemFluxVarsCache.update(element, fvGeometry, curElemVolVars);
261 if (enableGridFluxVarsCache)
262 gridVariables.gridFluxVarsCache().updateElement(element, fvGeometry, curElemVolVars);
265 partialDerivsTmp[0] = this->evalLocalResidual()[0];
268 for (std::size_t k = 0; k < numNeighbors; ++k)
269 for (
auto scvfIdx : connectivityMap[globalI][k].scvfsJ)
270 partialDerivsTmp[k+1] += evalNeighborFlux(neighborElements[k], fvGeometry.scvf(scvfIdx));
272 return partialDerivsTmp;
277 static const int numDiffMethod = getParamFromGroup<int>(this->problem().paramGroup(),
"Assembly.NumericDifferenceMethod");
279 eps_(elemSol[0][pvIdx], pvIdx), numDiffMethod);
284 if (this->elementIsGhost())
286 partialDerivs[0] = 0.0;
287 partialDerivs[0][pvIdx] = 1.0;
291 curVolVars = origVolVars;
294 elemSol[0][pvIdx] = origPriVars[pvIdx];
298 if constexpr (Problem::enableInternalDirichletConstraints())
301 const auto internalDirichletConstraintsOwnElement = this->problem().hasInternalDirichletConstraint(this->element(), scv);
302 const auto dirichletValues = this->problem().internalDirichlet(this->element(), scv);
304 for (
int eqIdx = 0; eqIdx < numEq; ++eqIdx)
306 if (internalDirichletConstraintsOwnElement[eqIdx])
308 origResiduals[0][eqIdx] = origVolVars.priVars()[eqIdx] - dirichletValues[eqIdx];
309 A[globalI][globalI][eqIdx][pvIdx] = (eqIdx == pvIdx) ? 1.0 : 0.0;
312 A[globalI][globalI][eqIdx][pvIdx] += partialDerivs[0][eqIdx];
317 for (
const auto& dataJ : connectivityMap[globalI])
319 const auto& neighborElement = neighborElements[j-1];
320 const auto& neighborScv = fvGeometry.scv(dataJ.globalJ);
321 const auto internalDirichletConstraintsNeighbor = this->problem().hasInternalDirichletConstraint(neighborElement, neighborScv);
323 for (
int eqIdx = 0; eqIdx < numEq; ++eqIdx)
325 if (internalDirichletConstraintsNeighbor[eqIdx])
326 A[dataJ.globalJ][globalI][eqIdx][pvIdx] = 0.0;
328 A[dataJ.globalJ][globalI][eqIdx][pvIdx] += partialDerivs[j][eqIdx];
336 for (
int eqIdx = 0; eqIdx < numEq; eqIdx++)
339 A[globalI][globalI][eqIdx][pvIdx] += partialDerivs[0][eqIdx];
343 for (
const auto& dataJ : connectivityMap[globalI])
344 A[dataJ.globalJ][globalI][eqIdx][pvIdx] += partialDerivs[j++][eqIdx];
355 if (enableGridFluxVarsCache)
356 gridVariables.gridFluxVarsCache().updateElement(element, fvGeometry, curElemVolVars);
359 return origResiduals[0];
369template<
class TypeTag,
class Assembler>
372 CCLocalAssembler<TypeTag, Assembler, DiffMethod::numeric, false>, false>
381 using Problem =
typename GridVariables::GridVolumeVariables::Problem;
396 if (this->assembler().isStationaryProblem())
397 DUNE_THROW(Dune::InvalidStateException,
"Using explicit jacobian assembler with stationary local residual");
400 auto residual = this->evalLocalResidual()[0];
401 const auto storageResidual = this->evalLocalStorageResidual()[0];
410 const auto& element = this->element();
411 const auto& fvGeometry = this->fvGeometry();
412 const auto& gridGeometry = this->assembler().gridGeometry();
413 auto&& curElemVolVars = this->curElemVolVars();
416 const auto globalI = gridGeometry.elementMapper().index(element);
417 const auto& scv = fvGeometry.scv(globalI);
418 auto& curVolVars = ParentType::getVolVarAccess(gridVariables.curGridVolVars(), curElemVolVars, scv);
422 const auto& curSol = this->curSol();
423 const auto origPriVars = curSol[globalI];
424 const auto origVolVars = curVolVars;
429 NumEqVector partialDeriv;
432 for (
int pvIdx = 0; pvIdx < numEq; ++pvIdx)
437 auto evalStorage = [&](Scalar priVar)
441 elemSol[0][pvIdx] = priVar;
442 curVolVars.update(elemSol, this->problem(), element, scv);
443 return this->evalLocalStorageResidual()[0];
447 if (!this->elementIsGhost())
450 static const int numDiffMethod = getParamFromGroup<int>(this->problem().paramGroup(),
"Assembly.NumericDifferenceMethod");
452 eps_(elemSol[0][pvIdx], pvIdx), numDiffMethod);
458 else partialDeriv[pvIdx] = 1.0;
461 curVolVars = origVolVars;
464 elemSol[0][pvIdx] = origPriVars[pvIdx];
468 if constexpr (Problem::enableInternalDirichletConstraints())
471 const auto internalDirichletConstraints = this->problem().hasInternalDirichletConstraint(this->element(), scv);
472 const auto dirichletValues = this->problem().internalDirichlet(this->element(), scv);
474 for (
int eqIdx = 0; eqIdx < numEq; ++eqIdx)
476 if (internalDirichletConstraints[eqIdx])
478 residual[eqIdx] = origVolVars.priVars()[eqIdx] - dirichletValues[eqIdx];
479 A[globalI][globalI][eqIdx][pvIdx] = (eqIdx == pvIdx) ? 1.0 : 0.0;
482 A[globalI][globalI][eqIdx][pvIdx] += partialDeriv[eqIdx];
487 for (
int eqIdx = 0; eqIdx < numEq; eqIdx++)
488 A[globalI][globalI][eqIdx][pvIdx] += partialDeriv[eqIdx];
502template<
class TypeTag,
class Assembler>
505 CCLocalAssembler<TypeTag, Assembler, DiffMethod::analytic, true>, true>
512 using Problem =
typename GridVariables::GridVolumeVariables::Problem;
528 if (this->elementIsGhost())
530 const auto globalI = this->assembler().gridGeometry().elementMapper().index(this->element());
531 for (
int pvIdx = 0; pvIdx < numEq; ++pvIdx)
532 A[globalI][globalI][pvIdx][pvIdx] = 1.0;
539 auto residual = this->evalLocalResidual()[0];
542 const auto& problem = this->problem();
543 const auto& element = this->element();
544 const auto& fvGeometry = this->fvGeometry();
545 const auto& curElemVolVars = this->curElemVolVars();
546 const auto& elemFluxVarsCache = this->elemFluxVarsCache();
549 const auto globalI = this->assembler().gridGeometry().elementMapper().index(element);
550 const auto& scv = fvGeometry.scv(globalI);
551 const auto& volVars = curElemVolVars[scv];
554 if (!this->assembler().isStationaryProblem())
555 this->localResidual().addStorageDerivatives(A[globalI][globalI], problem, element, fvGeometry, volVars, scv);
558 this->localResidual().addSourceDerivatives(A[globalI][globalI], problem, element, fvGeometry, volVars, scv);
561 for (
const auto& scvf : scvfs(fvGeometry))
564 if (!scvf.boundary())
565 this->localResidual().addFluxDerivatives(A[globalI], problem, element, fvGeometry, curElemVolVars, elemFluxVarsCache, scvf);
570 const auto& bcTypes = problem.boundaryTypes(element, scvf);
573 if (bcTypes.hasDirichlet() && !bcTypes.hasNeumann())
574 this->localResidual().addCCDirichletFluxDerivatives(A[globalI], problem, element, fvGeometry, curElemVolVars, elemFluxVarsCache, scvf);
577 else if (bcTypes.hasNeumann() && !bcTypes.hasDirichlet())
578 this->localResidual().addRobinFluxDerivatives(A[globalI], problem, element, fvGeometry, curElemVolVars, elemFluxVarsCache, scvf);
581 DUNE_THROW(Dune::NotImplemented,
"Mixed boundary conditions. Use pure boundary conditions by converting Dirichlet BCs to Robin BCs");
585 if constexpr (Problem::enableInternalDirichletConstraints())
588 const auto internalDirichletConstraints = this->problem().hasInternalDirichletConstraint(this->element(), scv);
589 const auto dirichletValues = this->problem().internalDirichlet(this->element(), scv);
591 for (
int pvIdx = 0; pvIdx < numEq; ++pvIdx)
593 for (
int eqIdx = 0; eqIdx < numEq; ++eqIdx)
595 if (internalDirichletConstraints[eqIdx])
597 residual[eqIdx] = volVars.priVars()[eqIdx] - dirichletValues[eqIdx];
598 A[globalI][globalI][eqIdx][pvIdx] = (eqIdx == pvIdx) ? 1.0 : 0.0;
601 for (
const auto& scvf : scvfs(fvGeometry))
602 if (!scvf.boundary())
603 A[globalI][fvGeometry.scv(scvf.outsideScvIdx()).dofIndex()][eqIdx][pvIdx] = 0.0;
619template<
class TypeTag,
class Assembler>
622 CCLocalAssembler<TypeTag, Assembler, DiffMethod::analytic, false>, false>
629 using Problem =
typename GridVariables::GridVolumeVariables::Problem;
645 if (this->elementIsGhost())
647 const auto globalI = this->assembler().gridGeometry().elementMapper().index(this->element());
648 for (
int pvIdx = 0; pvIdx < numEq; ++pvIdx)
649 A[globalI][globalI][pvIdx][pvIdx] = 1.0;
656 const auto residual = this->evalLocalResidual()[0];
659 const auto globalI = this->assembler().gridGeometry().elementMapper().index(this->element());
660 const auto& scv = this->fvGeometry().scv(globalI);
661 const auto& volVars = this->curElemVolVars()[scv];
664 this->localResidual().addStorageDerivatives(A[globalI][globalI], this->problem(), this->element(), this->fvGeometry(), volVars, scv);
666 if constexpr (Problem::enableInternalDirichletConstraints())
669 const auto internalDirichletConstraints = this->problem().hasInternalDirichletConstraint(this->element(), scv);
670 const auto dirichletValues = this->problem().internalDirichlet(this->element(), scv);
672 for (
int pvIdx = 0; pvIdx < numEq; ++pvIdx)
674 for (
int eqIdx = 0; eqIdx < numEq; ++eqIdx)
676 if (internalDirichletConstraints[eqIdx])
678 residual[eqIdx] = volVars.priVars()[eqIdx] - dirichletValues[eqIdx];
679 A[globalI][globalI][eqIdx][pvIdx] = (eqIdx == pvIdx) ? 1.0 : 0.0;
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.
A arithmetic block vector type based on DUNE's reserved vector.
A helper to deduce a vector with the same size as numbers of equations.
The infrastructure to retrieve run-time parameters from Dune::ParameterTrees.
The flux stencil specialized for different discretization schemes.
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 NumEqVectorTraits< PrimaryVariables >::type NumEqVector
A vector with the same size as numbers of equations This is the default implementation and has to be ...
Definition: numeqvector.hh:46
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property
Definition: propertysystem.hh:150
A base class for all local cell-centered assemblers.
Definition: cclocalassembler.hh:58
void assembleResidual(SolutionVector &res)
Assemble the residual only.
Definition: cclocalassembler.hh:105
void assembleJacobian(JacobianMatrix &jac, GridVariables &gridVariables)
Computes the derivatives with respect to the given element and adds them to the global matrix.
Definition: cclocalassembler.hh:96
void assembleJacobianAndResidual(JacobianMatrix &jac, SolutionVector &res, GridVariables &gridVariables, const PartialReassembler *partialReassembler)
Computes the derivatives with respect to the given element and adds them to the global matrix....
Definition: cclocalassembler.hh:76
An assembler for Jacobian and residual contribution per element (cell-centered methods)
Definition: cclocalassembler.hh:136
Cell-centered scheme local assembler using numeric differentiation and implicit time discretization.
Definition: cclocalassembler.hh:147
NumEqVector assembleJacobianAndResidualImpl(JacobianMatrix &A, GridVariables &gridVariables)
Computes the derivatives with respect to the given element and adds them to the global matrix.
Definition: cclocalassembler.hh:176
Cell-centered scheme local assembler using numeric differentiation and explicit time discretization.
Definition: cclocalassembler.hh:373
NumEqVector assembleJacobianAndResidualImpl(JacobianMatrix &A, GridVariables &gridVariables)
Computes the derivatives with respect to the given element and adds them to the global matrix.
Definition: cclocalassembler.hh:394
Cell-centered scheme local assembler using analytic (hand-coded) differentiation and implicit time di...
Definition: cclocalassembler.hh:506
NumEqVector assembleJacobianAndResidualImpl(JacobianMatrix &A, const GridVariables &gridVariables)
Computes the derivatives with respect to the given element and adds them to the global matrix.
Definition: cclocalassembler.hh:525
Cell-centered scheme local assembler using analytic (hand-coded) differentiation and explicit time di...
Definition: cclocalassembler.hh:623
NumEqVector assembleJacobianAndResidualImpl(JacobianMatrix &A, const GridVariables &gridVariables)
Computes the derivatives with respect to the given element and adds them to the global matrix.
Definition: cclocalassembler.hh:642
A base class for all local assemblers.
Definition: fvlocalassemblerbase.hh:48
ElementVolumeVariables & curElemVolVars()
The current element volume variables.
Definition: fvlocalassemblerbase.hh:265
Implementation & asImp_()
Definition: fvlocalassemblerbase.hh:309
const Assembler & assembler() const
The assembler.
Definition: fvlocalassemblerbase.hh:245
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
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
A arithmetic block vector type based on DUNE's reserved vector.
Definition: reservedblockvector.hh:38
The flux stencil specialized for different discretization schemes.
Definition: fluxstencil.hh:45
Declares all properties used in Dumux.
The local element solution class for cell-centered methods.