24#ifndef DUMUX_MIMETIC2P_HH
25#define DUMUX_MIMETIC2P_HH
34#include<dune/common/exceptions.hh>
35#include<dune/grid/common/grid.hh>
36#include<dune/geometry/type.hh>
37#include<dune/geometry/quadraturerules.hh>
43#include <dune/common/dynvector.hh>
51template<
class TypeTag>
58 using Indices =
typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices;
63 dim = GridView::dimension
67 wPhaseIdx = Indices::wPhaseIdx,
68 nPhaseIdx = Indices::nPhaseIdx,
69 pressureIdx = Indices::pressureIdx,
70 saturationIdx = Indices::saturationIdx,
71 pressureEqIdx = Indices::pressureEqIdx,
72 satEqIdx = Indices::satEqIdx,
77 pw = Indices::pressureW,
78 pn = Indices::pressureNw,
79 pGlobal = Indices::pressureGlobal,
80 Sw = Indices::saturationW,
81 Sn = Indices::saturationNw,
82 vw = Indices::velocityW,
83 vn = Indices::velocityNw,
90 using Grid =
typename GridView::Grid;
91 using Element =
typename GridView::Traits::template Codim<0>::Entity;
93 using BoundaryTypes =
typename GET_PROP_TYPE(TypeTag, BoundaryTypes);
94 using SolutionTypes =
typename GET_PROP(TypeTag, SolutionTypes);
95 using PrimaryVariables =
typename SolutionTypes::PrimaryVariables;
97 using FluidSystem =
typename GET_PROP_TYPE(TypeTag, FluidSystem);
98 using FluidState =
typename GET_PROP_TYPE(TypeTag, FluidState);
99 using MaterialLaw =
typename GET_PROP_TYPE(TypeTag, MaterialLaw);
115 const GridView& gridView,
bool procBoundaryAsDirichlet =
true) :
116 problem_(
problem), gridView_(gridView), maxError_(0), timeStep_(1)
118 ErrorTermFactor_ = getParam<Scalar>(
"Impet.ErrorTermFactor");
119 ErrorTermLowerBound_ = getParam<Scalar>(
"Impet.ErrorTermLowerBound");
120 ErrorTermUpperBound_ = getParam<Scalar>(
"Impet.ErrorTermUpperBound");
122 density_[wPhaseIdx] = 0.0;
123 density_[nPhaseIdx] = 0.0;
124 viscosity_[wPhaseIdx] =0.0;
125 viscosity_[nPhaseIdx] = 0.0;
130 const auto element = *problem_.gridView().template begin<0>();
131 FluidState fluidState;
132 fluidState.setPressure(wPhaseIdx, problem_.referencePressure(element));
133 fluidState.setPressure(nPhaseIdx, problem_.referencePressure(element));
134 fluidState.setTemperature(problem_.temperature(element));
135 fluidState.setSaturation(wPhaseIdx, 1.);
136 fluidState.setSaturation(nPhaseIdx, 0.);
142 int size = gridView_.size(0);
143 rhs_.resize(
size , 0.);
175 unsigned int numFaces = element.subEntities(1);
179 for (
unsigned int i = 0; i < numFaces; i++)
183 for (
unsigned int j = 0; j < numFaces; j++)
187 assembleV(element, k);
188 assembleBC(element, k);
196 void assemble(
const Element &cell,
const Dune::BlockVector<VBlockType>& localSolution,
int orderOfShapeFns = 1)
214 unsigned int numFaces = element.subEntities(1);
218 for (
unsigned int i = 0; i < numFaces; i++)
224 assembleBC(element, k);
228 template<
class Vector>
229 void completeRHS(
const Element& element, Dune::FieldVector<int, 2*dim>& local2Global, Vector& f)
231 int eIdxGlobal = problem_.variables().index(element);
232 unsigned int numFaces = element.subEntities(1);
234 Dune::FieldVector<Scalar, 2 * dim> F(0.);
238 for (
unsigned int i = 0; i < numFaces; i++)
240 if (!this->
bc(i).isDirichlet(pressureEqIdx))
241 f[local2Global[i]][0] += (dInv * F[i] * rhs_[eIdxGlobal]);
248 int eIdxGlobal = problem_.variables().index(element);
249 Scalar volume = element.geometry().volume();
251 PrimaryVariables sourceVec(0.0);
252 problem_.source(sourceVec, element);
253 Scalar qmean = volume * (sourceVec[wPhaseIdx]/density_[wPhaseIdx] + sourceVec[nPhaseIdx]/density_[nPhaseIdx]);
254 qmean += rhs_[eIdxGlobal];
256 Dune::FieldVector<Scalar, 2 * dim> F(0.);
260 return (dInv*(qmean + (F*pressTrace)));
265 Dune::FieldVector<Scalar,2*dim>& pressTrace, Scalar press)
267 int eIdxGlobal = problem_.variables().index(element);
269 Dune::FieldVector<Scalar, 2 * dim> faceVol(0);
270 for (
const auto& intersection :
intersections(gridView_, element))
272 faceVol[intersection.indexInInside()] = intersection.geometry().volume();
276 for (
int i = 0; i < 2*dim; i++)
277 for (
int j = 0; j < 2*dim; j++)
278 vel[i] += W_[eIdxGlobal][i][j]*faceVol[j]*(press - pressTrace[j]);
283 Dune::FieldVector<Scalar,2*dim>& pressTrace, Scalar press)
285 int eIdxGlobal = problem_.variables().index(element);
287 Dune::FieldVector<Scalar, 2 * dim> faceVol(0);
288 for (
const auto& intersection :
intersections(gridView_, element))
290 faceVol[intersection.indexInInside()] = intersection.geometry().volume();
294 for (
int j = 0; j < 2*dim; j++)
295 vel += W_[eIdxGlobal][fIdx][j]*faceVol[j]*(press - pressTrace[j]);
300 const Dune::FieldMatrix<Scalar, 2 * dim, 2 * dim>& W,
301 Dune::FieldVector<Scalar, 2 * dim>& F, Scalar& dInv)
303 Dune::FieldVector<Scalar, 2 * dim> c(0);
304 Dune::FieldMatrix<Scalar, 2 * dim, 2 * dim> Pi(0);
306 for (
const auto& intersection :
intersections(gridView_, element))
309 int idx = intersection.indexInInside();
311 Scalar faceVol = intersection.geometry().volume();
320 Pi[idx][idx] = faceVol;
324 Dune::FieldVector<Scalar, 2 * dim> Wc(0);
326 dInv = 1.0 / (c * Wc);
334 Dune::FieldVector<Scalar, 2 * dim>& F,
335 Dune::FieldMatrix<Scalar, 2 * dim, 2 * dim>& Pi,
346 void assembleV(
const Element& element,
int k = 1);
348 void assembleBC(
const Element& element,
int k = 1);
351 Scalar evaluateErrorTerm(CellData& cellData)
356 switch (saturationType)
359 sat = cellData.saturation(wPhaseIdx);
362 sat = cellData.saturation(nPhaseIdx);
366 Scalar error = (sat > 1.0) ? sat - 1.0 : 0.0;
374 Scalar errorAbs = abs(error);
376 if ((errorAbs * timeStep_ > 1e-6) && (errorAbs > ErrorTermLowerBound_ * maxError_)
377 && (!problem_.timeManager().willBeFinished()))
379 return ErrorTermFactor_ * error;
387 Dune::DynamicVector<Scalar> rhs_;
388 std::vector<Dune::FieldMatrix<Scalar, 2 * dim, 2 * dim> > W_;
391 Scalar ErrorTermFactor_;
392 Scalar ErrorTermLowerBound_;
393 Scalar ErrorTermUpperBound_;
395 Scalar density_[numPhases];
396 Scalar viscosity_[numPhases];
400template<
class TypeTag>
401void MimeticTwoPLocalStiffness<TypeTag>::assembleV(
const Element& element,
int)
403 unsigned int numFaces = element.subEntities(1);
404 this->setcurrentsize(numFaces);
406 int eIdxGlobal = problem_.variables().index(element);
411 Dune::FieldVector<Scalar, 2 * dim> faceVol(0);
412 Dune::FieldMatrix<Scalar, 2 * dim, 2 * dim> Pi(0.);
413 Dune::FieldVector<Scalar, 2 * dim> F(0.);
416 this->assembleElementMatrices(element, faceVol, F, Pi, dInv, qmean);
419 Dune::FieldMatrix<Scalar, 2 * dim, 2 * dim> PiWPiT(W_[eIdxGlobal]);
420 PiWPiT.rightmultiply(Pi);
421 PiWPiT.leftmultiply(Pi);
424 Dune::FieldMatrix<Scalar, 2 * dim, 2 * dim> FDinvFT(0);
425 for (
unsigned int i = 0; i < numFaces; i++)
426 for (
unsigned int j = 0; j < numFaces; j++)
427 FDinvFT[i][j] = dInv * F[i] * F[j];
430 for (
unsigned int i = 0; i < numFaces; i++)
431 for (
unsigned int j = 0; j < numFaces; j++)
432 this->A[i][j] = PiWPiT[i][j] - FDinvFT[i][j];
436 Scalar factor = dInv * qmean;
437 for (
unsigned int i = 0; i < numFaces; i++)
438 this->b[i] = F[i] * factor;
448template<
class TypeTag>
450 Dune::FieldVector<Scalar, 2 * dim>& faceVol,
451 Dune::FieldVector<Scalar, 2 * dim>& F,
452 Dune::FieldMatrix<Scalar, 2 * dim, 2 * dim>& Pi,
456 unsigned int numFaces = element.subEntities(1);
457 this->setcurrentsize(numFaces);
460 Dune::FieldVector<Scalar, dim> centerGlobal = element.geometry().center();
462 int eIdxGlobal = problem_.variables().index(element);
464 CellData& cellData = problem_.variables().cellData(eIdxGlobal);
467 Scalar volume = element.geometry().volume();
470 Dune::FieldMatrix<Scalar, 2 * dim, dim> R(0), N(0);
475 Scalar gravPotFace[2*dim];
477 Scalar gravPot = (problem_.bBoxMax() - centerGlobal) * problem_.gravity() * (density_[nPhaseIdx] - density_[wPhaseIdx]);
479 for (
const auto& intersection :
intersections(gridView_, element))
482 int fIdx = intersection.indexInInside();
484 Dune::FieldVector<Scalar, dim> faceGlobal = intersection.geometry().center();
485 faceVol[fIdx] = intersection.geometry().volume();
488 const Dune::FieldVector<Scalar, dim>& unitOuterNormal = intersection.centerUnitOuterNormal();
490 N[fIdx] = unitOuterNormal;
492 for (
int k = 0; k < dim; k++)
494 R[fIdx][k] = faceVol[fIdx] * (faceGlobal[k] - centerGlobal[k]);
496 gravPotFace[fIdx] = (problem_.bBoxMax() - faceGlobal) * problem_.gravity() * (density_[nPhaseIdx] - density_[wPhaseIdx]);
502 Scalar norm = R[0][0] * R[0][0];
504 for (
unsigned int i = 1; i < numFaces; i++)
505 norm += R[i][0] * R[i][0];
507 for (
unsigned int i = 0; i < numFaces; i++)
509 Scalar weight = R[0][1] * R[0][0];
510 for (
unsigned int i = 1; i < numFaces; i++)
511 weight += R[i][1] * R[i][0];
512 for (
unsigned int i = 0; i < numFaces; i++)
513 R[i][1] -= weight * R[i][0];
514 norm = R[0][1] * R[0][1];
515 for (
unsigned int i = 1; i < numFaces; i++)
516 norm += R[i][1] * R[i][1];
518 for (
unsigned int i = 0; i < numFaces; i++)
522 Scalar weight1 = R[0][2] * R[0][0];
523 Scalar weight2 = R[0][2] * R[0][1];
524 for (
unsigned int i = 1; i < numFaces; i++)
526 weight1 += R[i][2] * R[i][0];
527 weight2 += R[i][2] * R[i][1];
529 for (
unsigned int i = 0; i < numFaces; i++)
530 R[i][2] -= weight1 * R[i][0] + weight2 * R[i][1];
531 norm = R[0][2] * R[0][2];
532 for (
unsigned int i = 1; i < numFaces; i++)
533 norm += R[i][2] * R[i][2];
536 for (
unsigned int i = 0; i < numFaces; i++)
542 Dune::FieldMatrix<Scalar, 2 * dim, 2 * dim> D(0);
543 for (
unsigned int s = 0; s < numFaces; s++)
545 Dune::FieldVector<Scalar, 2 * dim> es(0);
547 for (
unsigned int k = 0; k < numFaces; k++)
550 for (
unsigned int i = 0; i < dim; i++)
552 D[k][s] -= R[s][i] * R[k][i];
560 Dune::FieldMatrix<Scalar, dim, dim>
mobility(problem_.spatialParams().intrinsicPermeability(element));
561 mobility *= (cellData.mobility(wPhaseIdx) + cellData.mobility(nPhaseIdx));
564 for (
int i = 1; i < dim; i++)
566 D *= 2.0 * traceMob / volume;
570 Dune::FieldMatrix<Scalar, 2 * dim, dim> NK(N);
573 for (
unsigned int i = 0; i < numFaces; i++)
575 for (
unsigned int j = 0; j < numFaces; j++)
577 W_[eIdxGlobal][i][j] = NK[i][0] * N[j][0];
578 for (
unsigned int k = 1; k < dim; k++)
579 W_[eIdxGlobal][i][j] += NK[i][k] * N[j][k];
583 W_[eIdxGlobal] /= volume;
596 Dune::FieldVector<Scalar, 2 * dim> c(0);
597 for (
unsigned int i = 0; i < numFaces; i++)
602 for (
unsigned int i = 0; i < numFaces; i++)
603 Pi[i][i] = faceVol[i];
606 Dune::FieldVector<Scalar, 2 * dim> Wc(0);
607 W_[eIdxGlobal].umv(c, Wc);
608 dInv = 1.0 / (c * Wc);
616 for (
const auto& intersection :
intersections(gridView_, element))
618 int idx = intersection.indexInInside();
623 for (
int j = 0; j < 2 * dim; j++)
624 flux += W_[eIdxGlobal][idx][j] * faceVol[j] * (gravPot - gravPotFace[j]);
627 if (intersection.neighbor())
629 int eIdxGlobalNeighbor = problem_.variables().index(intersection.outside());
632 switch (pressureType)
636 fracFlow = cellData.fracFlowFunc(nPhaseIdx);
641 fracFlow = -cellData.fracFlowFunc(wPhaseIdx);
647 rhs_[eIdxGlobal] -= (faceVol[idx] * fracFlow * flux);
648 rhs_[eIdxGlobalNeighbor] += (faceVol[idx] * fracFlow * flux);
651 else if (intersection.boundary())
653 BoundaryTypes bctype;
654 problem_.boundaryTypes(bctype, intersection);
656 if (bctype.isDirichlet(pressureEqIdx))
658 if (flux > 0. || !bctype.isDirichlet(satEqIdx))
660 switch (pressureType)
664 fracFlow = cellData.fracFlowFunc(nPhaseIdx);
669 fracFlow = -cellData.fracFlowFunc(wPhaseIdx);
674 else if (flux < 0. && bctype.isDirichlet(satEqIdx))
676 PrimaryVariables boundValues(0.0);
677 problem_.dirichlet(boundValues, intersection);
679 Scalar krw = MaterialLaw::krw(problem_.spatialParams().materialLawParams(element),
680 boundValues[saturationIdx]);
681 Scalar krn = MaterialLaw::krn(problem_.spatialParams().materialLawParams(element),
682 boundValues[saturationIdx]);
684 switch (pressureType)
688 fracFlow = krn / viscosity_[nPhaseIdx]
689 / (krw / viscosity_[wPhaseIdx] + krn / viscosity_[nPhaseIdx]);
694 fracFlow = -krw / viscosity_[wPhaseIdx]
695 / (krw / viscosity_[wPhaseIdx] + krn / viscosity_[nPhaseIdx]);
701 rhs_[eIdxGlobal] -= (faceVol[idx] * fracFlow * flux);
706 PrimaryVariables sourceVec(0.0);
707 problem_.source(sourceVec, element);
708 qmean = volume * (sourceVec[wPhaseIdx]/density_[wPhaseIdx] + sourceVec[nPhaseIdx]/density_[nPhaseIdx]);
710 qmean += evaluateErrorTerm(cellData) * volume;
714template<
class TypeTag>
718 for (
const auto& intersection :
intersections(gridView_, element))
720 int faceIndex = intersection.indexInInside();
721 if (intersection.boundary())
723 problem_.boundaryTypes(this->bctype[faceIndex], intersection);
724 PrimaryVariables boundValues(0.0);
726 if (this->bctype[faceIndex].isNeumann(pressureEqIdx))
728 problem_.neumann(boundValues, intersection);
729 Scalar J = (boundValues[wPhaseIdx]/density_[wPhaseIdx] + boundValues[nPhaseIdx]/density_[nPhaseIdx]);
730 this->b[faceIndex] -= J * intersection.geometry().volume();
732 else if (this->bctype[faceIndex].isDirichlet(pressureEqIdx))
734 problem_.dirichlet(boundValues, intersection);
735 if (pressureType == pw)
736 this->b[faceIndex] = boundValues[pressureIdx] +
737 (problem_.bBoxMax() - intersection.geometry().center()) * problem_.gravity() * density_[wPhaseIdx];
738 else if (pressureType == pn)
739 this->b[faceIndex] = boundValues[pressureIdx] +
740 (problem_.bBoxMax() - intersection.geometry().center()) * problem_.gravity() * density_[nPhaseIdx];
742 this->b[faceIndex] = boundValues[pressureIdx];
#define GET_PROP_VALUE(TypeTag, PropTagName)
Definition: propertysystemmacros.hh:282
#define GET_PROP(TypeTag, PropTagName)
Definition: propertysystemmacros.hh:281
#define GET_PROP_TYPE(TypeTag, PropTagName)
Definition: propertysystemmacros.hh:283
Definition of boundary condition types, extend if necessary.
Base class for assembling local stiffness matrices.
Dune::IteratorRange< typename MultiDomainGlue< DomainGridView, TargetGridView, DomainMapper, TargetMapper >::Intersections::const_iterator > intersections(const MultiDomainGlue< DomainGridView, TargetGridView, DomainMapper, TargetMapper > &glue)
Range generator to iterate with range-based for loops over all intersections as follows: for (const a...
Definition: glue.hh:62
make the local view function available whenever we use the grid geometry
Definition: adapt.hh:29
Property tag SaturationFormulation
The formulation of the saturation model.
Definition: porousmediumflow/2p/sequential/properties.hh:53
Property tag NumPhases
Number of phases in the system.
Definition: porousmediumflow/sequential/properties.hh:69
std::string mobility(int phaseIdx) noexcept
I/O name of mobility for multiphase systems.
Definition: name.hh:101
std::string viscosity(int phaseIdx) noexcept
I/O name of viscosity for multiphase systems.
Definition: name.hh:74
std::string density(int phaseIdx) noexcept
I/O name of density for multiphase systems.
Definition: name.hh:65
Base class for local assemblers.
Definition: localstiffness.hh:60
void setcurrentsize(int s)
Sets the current size of the local stiffness matrix.
Definition: localstiffness.hh:233
const BoundaryTypes & bc(int i) const
Accesses boundary condition for each dof.
Definition: localstiffness.hh:223
Dune::Matrix< MBlockType > A
Definition: localstiffness.hh:250
std::vector< VBlockType > b
Definition: localstiffness.hh:251
std::vector< BoundaryTypes > bctype
Definition: localstiffness.hh:252
compute local stiffness matrix for conforming finite elements for the full 2-phase pressure equation
Definition: mimetic.hh:53
void reset()
Definition: mimetic.hh:147
void assemble(const Element &element, int k=1)
Assembles local stiffness matrix for given element and order.
Definition: mimetic.hh:173
MimeticTwoPLocalStiffness(Problem &problem, bool levelBoundaryAsDirichlet, const GridView &gridView, bool procBoundaryAsDirichlet=true)
Constructor.
Definition: mimetic.hh:114
@ m
Definition: mimetic.hh:106
void constructVelocity(const Element &element, int fIdx, Scalar &vel, Dune::FieldVector< Scalar, 2 *dim > &pressTrace, Scalar press)
Definition: mimetic.hh:282
void assembleBoundaryCondition(const Element &element, int k=1)
Assembles only boundary conditions for given element.
Definition: mimetic.hh:212
void constructVelocity(const Element &element, Dune::FieldVector< Scalar, 2 *dim > &vel, Dune::FieldVector< Scalar, 2 *dim > &pressTrace, Scalar press)
Definition: mimetic.hh:264
const Problem & problem() const
Definition: mimetic.hh:340
void completeRHS(const Element &element, Dune::FieldVector< int, 2 *dim > &local2Global, Vector &f)
Definition: mimetic.hh:229
void initialize()
Definition: mimetic.hh:128
void assemble(const Element &cell, const Dune::BlockVector< VBlockType > &localSolution, int orderOfShapeFns=1)
Definition: mimetic.hh:196
void setErrorInfo(Scalar maxErr, Scalar dt)
Definition: mimetic.hh:154
Scalar constructPressure(const Element &element, Dune::FieldVector< Scalar, 2 *dim > &pressTrace)
Definition: mimetic.hh:246
void assembleElementMatrices(const Element &element, Dune::FieldVector< Scalar, 2 *dim > &faceVol, Dune::FieldVector< Scalar, 2 *dim > &F, Dune::FieldMatrix< Scalar, 2 *dim, 2 *dim > &Pi, Scalar &dInv, Scalar &qmean)
Definition: mimetic.hh:449
void computeReconstructionMatrices(const Element &element, const Dune::FieldMatrix< Scalar, 2 *dim, 2 *dim > &W, Dune::FieldVector< Scalar, 2 *dim > &F, Scalar &dInv)
Definition: mimetic.hh:299
@ size
Definition: mimetic.hh:110
Dune::FieldVector< Scalar, m > VBlockType
Definition: mimetic.hh:195
Specifies the properties for immiscible 2p diffusion/pressure models.