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>
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,
73 numPhases = getPropValue<TypeTag, Properties::NumPhases>()
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,
85 pressureType = getPropValue<TypeTag, Properties::PressureFormulation>(),
87 saturationType = getPropValue<TypeTag, Properties::SaturationFormulation>()
90 using Grid =
typename GridView::Grid;
91 using Element =
typename GridView::Traits::template Codim<0>::Entity;
95 using PrimaryVariables =
typename SolutionTypes::PrimaryVariables;
114 const GridView& gridView,
bool procBoundaryAsDirichlet =
true) :
115 problem_(
problem), gridView_(gridView), maxError_(0), timeStep_(1)
117 ErrorTermFactor_ = getParam<Scalar>(
"Impet.ErrorTermFactor");
118 ErrorTermLowerBound_ = getParam<Scalar>(
"Impet.ErrorTermLowerBound");
119 ErrorTermUpperBound_ = getParam<Scalar>(
"Impet.ErrorTermUpperBound");
121 density_[wPhaseIdx] = 0.0;
122 density_[nPhaseIdx] = 0.0;
123 viscosity_[wPhaseIdx] =0.0;
124 viscosity_[nPhaseIdx] = 0.0;
129 const auto element = *problem_.gridView().template begin<0>();
130 FluidState fluidState;
131 fluidState.setPressure(wPhaseIdx, problem_.referencePressure(element));
132 fluidState.setPressure(nPhaseIdx, problem_.referencePressure(element));
133 fluidState.setTemperature(problem_.temperature(element));
134 fluidState.setSaturation(wPhaseIdx, 1.);
135 fluidState.setSaturation(nPhaseIdx, 0.);
141 int size = gridView_.size(0);
142 rhs_.resize(
size , 0.);
174 unsigned int numFaces = element.subEntities(1);
178 for (
unsigned int i = 0; i < numFaces; i++)
182 for (
unsigned int j = 0; j < numFaces; j++)
186 assembleV(element, k);
187 assembleBC(element, k);
195 void assemble(
const Element &cell,
const Dune::BlockVector<VBlockType>& localSolution,
int orderOfShapeFns = 1)
213 unsigned int numFaces = element.subEntities(1);
217 for (
unsigned int i = 0; i < numFaces; i++)
223 assembleBC(element, k);
227 template<
class Vector>
228 void completeRHS(
const Element& element, Dune::FieldVector<int, 2*dim>& local2Global, Vector& f)
230 int eIdxGlobal = problem_.variables().index(element);
231 unsigned int numFaces = element.subEntities(1);
233 Dune::FieldVector<Scalar, 2 * dim> F(0.);
237 for (
unsigned int i = 0; i < numFaces; i++)
239 if (!this->
bc(i).isDirichlet(pressureEqIdx))
240 f[local2Global[i]][0] += (dInv * F[i] * rhs_[eIdxGlobal]);
247 int eIdxGlobal = problem_.variables().index(element);
248 Scalar
volume = element.geometry().volume();
250 PrimaryVariables sourceVec(0.0);
251 problem_.source(sourceVec, element);
252 Scalar qmean =
volume * (sourceVec[wPhaseIdx]/density_[wPhaseIdx] + sourceVec[nPhaseIdx]/density_[nPhaseIdx]);
253 qmean += rhs_[eIdxGlobal];
255 Dune::FieldVector<Scalar, 2 * dim> F(0.);
259 return (dInv*(qmean + (F*pressTrace)));
264 Dune::FieldVector<Scalar,2*dim>& pressTrace, Scalar press)
266 int eIdxGlobal = problem_.variables().index(element);
268 Dune::FieldVector<Scalar, 2 * dim> faceVol(0);
269 for (
const auto& intersection : intersections(gridView_, element))
271 faceVol[intersection.indexInInside()] = intersection.geometry().volume();
275 for (
int i = 0; i < 2*dim; i++)
276 for (
int j = 0; j < 2*dim; j++)
277 vel[i] += W_[eIdxGlobal][i][j]*faceVol[j]*(press - pressTrace[j]);
282 Dune::FieldVector<Scalar,2*dim>& pressTrace, Scalar press)
284 int eIdxGlobal = problem_.variables().index(element);
286 Dune::FieldVector<Scalar, 2 * dim> faceVol(0);
287 for (
const auto& intersection : intersections(gridView_, element))
289 faceVol[intersection.indexInInside()] = intersection.geometry().volume();
293 for (
int j = 0; j < 2*dim; j++)
294 vel += W_[eIdxGlobal][fIdx][j]*faceVol[j]*(press - pressTrace[j]);
299 const Dune::FieldMatrix<Scalar, 2 * dim, 2 * dim>& W,
300 Dune::FieldVector<Scalar, 2 * dim>& F, Scalar& dInv)
302 Dune::FieldVector<Scalar, 2 * dim> c(0);
303 Dune::FieldMatrix<Scalar, 2 * dim, 2 * dim> Pi(0);
305 for (
const auto& intersection : intersections(gridView_, element))
308 int idx = intersection.indexInInside();
310 Scalar faceVol = intersection.geometry().volume();
319 Pi[idx][idx] = faceVol;
323 Dune::FieldVector<Scalar, 2 * dim> Wc(0);
325 dInv = 1.0 / (c * Wc);
333 Dune::FieldVector<Scalar, 2 * dim>& F,
334 Dune::FieldMatrix<Scalar, 2 * dim, 2 * dim>& Pi,
345 void assembleV(
const Element& element,
int k = 1);
347 void assembleBC(
const Element& element,
int k = 1);
350 Scalar evaluateErrorTerm(CellData& cellData)
355 switch (saturationType)
358 sat = cellData.saturation(wPhaseIdx);
361 sat = cellData.saturation(nPhaseIdx);
364 DUNE_THROW(Dune::NotImplemented,
"Only saturation formulation Sw and Sn are implemented!");
367 Scalar error = (sat > 1.0) ? sat - 1.0 : 0.0;
375 Scalar errorAbs = abs(error);
377 if ((errorAbs * timeStep_ > 1e-6) && (errorAbs > ErrorTermLowerBound_ * maxError_)
378 && (!problem_.timeManager().willBeFinished()))
380 return ErrorTermFactor_ * error;
388 Dune::DynamicVector<Scalar> rhs_;
389 std::vector<Dune::FieldMatrix<Scalar, 2 * dim, 2 * dim> > W_;
392 Scalar ErrorTermFactor_;
393 Scalar ErrorTermLowerBound_;
394 Scalar ErrorTermUpperBound_;
396 Scalar density_[numPhases];
397 Scalar viscosity_[numPhases];
401template<
class TypeTag>
402void MimeticTwoPLocalStiffness<TypeTag>::assembleV(
const Element& element,
int)
404 unsigned int numFaces =
element.subEntities(1);
405 this->setcurrentsize(numFaces);
407 int eIdxGlobal = problem_.variables().index(element);
412 Dune::FieldVector<Scalar, 2 * dim> faceVol(0);
413 Dune::FieldMatrix<Scalar, 2 * dim, 2 * dim> Pi(0.);
414 Dune::FieldVector<Scalar, 2 * dim> F(0.);
417 this->assembleElementMatrices(element, faceVol, F, Pi, dInv, qmean);
420 Dune::FieldMatrix<Scalar, 2 * dim, 2 * dim> PiWPiT(W_[eIdxGlobal]);
421 PiWPiT.rightmultiply(Pi);
422 PiWPiT.leftmultiply(Pi);
425 Dune::FieldMatrix<Scalar, 2 * dim, 2 * dim> FDinvFT(0);
426 for (
unsigned int i = 0; i < numFaces; i++)
427 for (
unsigned int j = 0; j < numFaces; j++)
428 FDinvFT[i][j] = dInv * F[i] * F[j];
431 for (
unsigned int i = 0; i < numFaces; i++)
432 for (
unsigned int j = 0; j < numFaces; j++)
433 this->A[i][j] = PiWPiT[i][j] - FDinvFT[i][j];
437 Scalar factor = dInv * qmean;
438 for (
unsigned int i = 0; i < numFaces; i++)
439 this->b[i] = F[i] * factor;
449template<
class TypeTag>
451 Dune::FieldVector<Scalar, 2 * dim>& faceVol,
452 Dune::FieldVector<Scalar, 2 * dim>& F,
453 Dune::FieldMatrix<Scalar, 2 * dim, 2 * dim>& Pi,
457 unsigned int numFaces = element.subEntities(1);
458 this->setcurrentsize(numFaces);
461 Dune::FieldVector<Scalar, dim> centerGlobal = element.geometry().center();
463 int eIdxGlobal = problem_.variables().index(element);
465 CellData& cellData = problem_.variables().cellData(eIdxGlobal);
468 Scalar
volume = element.geometry().volume();
471 Dune::FieldMatrix<Scalar, 2 * dim, dim> R(0), N(0);
476 Scalar gravPotFace[2*dim];
478 Scalar gravPot = (problem_.bBoxMax() - centerGlobal) * problem_.gravity() * (density_[nPhaseIdx] - density_[wPhaseIdx]);
480 for (
const auto& intersection : intersections(gridView_, element))
483 int fIdx = intersection.indexInInside();
485 Dune::FieldVector<Scalar, dim> faceGlobal = intersection.geometry().center();
486 faceVol[fIdx] = intersection.geometry().volume();
489 const Dune::FieldVector<Scalar, dim>& unitOuterNormal = intersection.centerUnitOuterNormal();
491 N[fIdx] = unitOuterNormal;
493 for (
int k = 0; k < dim; k++)
495 R[fIdx][k] = faceVol[fIdx] * (faceGlobal[k] - centerGlobal[k]);
497 gravPotFace[fIdx] = (problem_.bBoxMax() - faceGlobal) * problem_.gravity() * (density_[nPhaseIdx] - density_[wPhaseIdx]);
503 Scalar norm = R[0][0] * R[0][0];
505 for (
unsigned int i = 1; i < numFaces; i++)
506 norm += R[i][0] * R[i][0];
508 for (
unsigned int i = 0; i < numFaces; i++)
510 Scalar weight = R[0][1] * R[0][0];
511 for (
unsigned int i = 1; i < numFaces; i++)
512 weight += R[i][1] * R[i][0];
513 for (
unsigned int i = 0; i < numFaces; i++)
514 R[i][1] -= weight * R[i][0];
515 norm = R[0][1] * R[0][1];
516 for (
unsigned int i = 1; i < numFaces; i++)
517 norm += R[i][1] * R[i][1];
519 for (
unsigned int i = 0; i < numFaces; i++)
523 Scalar weight1 = R[0][2] * R[0][0];
524 Scalar weight2 = R[0][2] * R[0][1];
525 for (
unsigned int i = 1; i < numFaces; i++)
527 weight1 += R[i][2] * R[i][0];
528 weight2 += R[i][2] * R[i][1];
530 for (
unsigned int i = 0; i < numFaces; i++)
531 R[i][2] -= weight1 * R[i][0] + weight2 * R[i][1];
532 norm = R[0][2] * R[0][2];
533 for (
unsigned int i = 1; i < numFaces; i++)
534 norm += R[i][2] * R[i][2];
537 for (
unsigned int i = 0; i < numFaces; i++)
543 Dune::FieldMatrix<Scalar, 2 * dim, 2 * dim> D(0);
544 for (
unsigned int s = 0; s < numFaces; s++)
546 Dune::FieldVector<Scalar, 2 * dim> es(0);
548 for (
unsigned int k = 0; k < numFaces; k++)
551 for (
unsigned int i = 0; i < dim; i++)
553 D[k][s] -= R[s][i] * R[k][i];
561 Dune::FieldMatrix<Scalar, dim, dim>
mobility(problem_.spatialParams().intrinsicPermeability(element));
562 mobility *= (cellData.mobility(wPhaseIdx) + cellData.mobility(nPhaseIdx));
565 for (
int i = 1; i < dim; i++)
567 D *= 2.0 * traceMob /
volume;
571 Dune::FieldMatrix<Scalar, 2 * dim, dim> NK(N);
574 for (
unsigned int i = 0; i < numFaces; i++)
576 for (
unsigned int j = 0; j < numFaces; j++)
578 W_[eIdxGlobal][i][j] = NK[i][0] * N[j][0];
579 for (
unsigned int k = 1; k < dim; k++)
580 W_[eIdxGlobal][i][j] += NK[i][k] * N[j][k];
597 Dune::FieldVector<Scalar, 2 * dim> c(0);
598 for (
unsigned int i = 0; i < numFaces; i++)
603 for (
unsigned int i = 0; i < numFaces; i++)
604 Pi[i][i] = faceVol[i];
607 Dune::FieldVector<Scalar, 2 * dim> Wc(0);
608 W_[eIdxGlobal].umv(c, Wc);
609 dInv = 1.0 / (c * Wc);
617 for (
const auto& intersection : intersections(gridView_, element))
619 int idx = intersection.indexInInside();
624 for (
int j = 0; j < 2 * dim; j++)
625 flux += W_[eIdxGlobal][idx][j] * faceVol[j] * (gravPot - gravPotFace[j]);
628 if (intersection.neighbor())
630 int eIdxGlobalNeighbor = problem_.variables().index(intersection.outside());
633 switch (pressureType)
637 fracFlow = cellData.fracFlowFunc(nPhaseIdx);
642 fracFlow = -cellData.fracFlowFunc(wPhaseIdx);
646 DUNE_THROW(Dune::NotImplemented,
"Only pressure formulation pw and pn are implemented!");
650 rhs_[eIdxGlobal] -= (faceVol[idx] * fracFlow * flux);
651 rhs_[eIdxGlobalNeighbor] += (faceVol[idx] * fracFlow * flux);
654 else if (intersection.boundary())
656 BoundaryTypes bctype;
657 problem_.boundaryTypes(bctype, intersection);
659 if (bctype.isDirichlet(pressureEqIdx))
661 if (flux > 0. || !bctype.isDirichlet(satEqIdx))
663 switch (pressureType)
667 fracFlow = cellData.fracFlowFunc(nPhaseIdx);
672 fracFlow = -cellData.fracFlowFunc(wPhaseIdx);
676 DUNE_THROW(Dune::NotImplemented,
"Only pressure formulation pw and pn are implemented!");
679 else if (flux < 0. && bctype.isDirichlet(satEqIdx))
681 PrimaryVariables boundValues(0.0);
682 problem_.dirichlet(boundValues, intersection);
684 const auto fluidMatrixInteraction = problem_.spatialParams().fluidMatrixInteractionAtPos(element.geometry().center());
685 const Scalar krw = fluidMatrixInteraction.krw(boundValues[saturationIdx]);
686 const Scalar krn = fluidMatrixInteraction.krn(boundValues[saturationIdx]);
688 switch (pressureType)
692 fracFlow = krn / viscosity_[nPhaseIdx]
693 / (krw / viscosity_[wPhaseIdx] + krn / viscosity_[nPhaseIdx]);
698 fracFlow = -krw / viscosity_[wPhaseIdx]
699 / (krw / viscosity_[wPhaseIdx] + krn / viscosity_[nPhaseIdx]);
703 DUNE_THROW(Dune::NotImplemented,
"Only pressure formulation pw and pn are implemented!");
707 rhs_[eIdxGlobal] -= (faceVol[idx] * fracFlow * flux);
712 PrimaryVariables sourceVec(0.0);
713 problem_.source(sourceVec, element);
714 qmean =
volume * (sourceVec[wPhaseIdx]/density_[wPhaseIdx] + sourceVec[nPhaseIdx]/density_[nPhaseIdx]);
716 qmean += evaluateErrorTerm(cellData) *
volume;
720template<
class TypeTag>
724 for (
const auto& intersection : intersections(gridView_, element))
726 int faceIndex = intersection.indexInInside();
727 if (intersection.boundary())
729 problem_.boundaryTypes(this->bctype[faceIndex], intersection);
730 PrimaryVariables boundValues(0.0);
732 if (this->bctype[faceIndex].isNeumann(pressureEqIdx))
734 problem_.neumann(boundValues, intersection);
735 Scalar J = (boundValues[wPhaseIdx]/density_[wPhaseIdx] + boundValues[nPhaseIdx]/density_[nPhaseIdx]);
736 this->b[faceIndex] -= J * intersection.geometry().volume();
738 else if (this->bctype[faceIndex].isDirichlet(pressureEqIdx))
740 problem_.dirichlet(boundValues, intersection);
741 if (pressureType == pw)
742 this->b[faceIndex] = boundValues[pressureIdx] +
743 (problem_.bBoxMax() - intersection.geometry().center()) * problem_.gravity() * density_[wPhaseIdx];
744 else if (pressureType == pn)
745 this->b[faceIndex] = boundValues[pressureIdx] +
746 (problem_.bBoxMax() - intersection.geometry().center()) * problem_.gravity() * density_[nPhaseIdx];
748 this->b[faceIndex] = boundValues[pressureIdx];
Definition of boundary condition types, extend if necessary.
Base class for assembling local stiffness matrices.
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type GetProp
get the type of a property
Definition: propertysystem.hh:141
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property
Definition: propertysystem.hh:150
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
Scalar volume(Shape shape, Scalar inscribedRadius)
Returns the volume of a given geometry based on the inscribed radius.
Definition: poreproperties.hh:73
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:146
void assemble(const Element &element, int k=1)
Assembles local stiffness matrix for given element and order.
Definition: mimetic.hh:172
MimeticTwoPLocalStiffness(Problem &problem, bool levelBoundaryAsDirichlet, const GridView &gridView, bool procBoundaryAsDirichlet=true)
Constructor.
Definition: mimetic.hh:113
@ size
Definition: mimetic.hh:109
void constructVelocity(const Element &element, int fIdx, Scalar &vel, Dune::FieldVector< Scalar, 2 *dim > &pressTrace, Scalar press)
Definition: mimetic.hh:281
void assembleBoundaryCondition(const Element &element, int k=1)
Assembles only boundary conditions for given element.
Definition: mimetic.hh:211
void constructVelocity(const Element &element, Dune::FieldVector< Scalar, 2 *dim > &vel, Dune::FieldVector< Scalar, 2 *dim > &pressTrace, Scalar press)
Definition: mimetic.hh:263
const Problem & problem() const
Definition: mimetic.hh:339
void completeRHS(const Element &element, Dune::FieldVector< int, 2 *dim > &local2Global, Vector &f)
Definition: mimetic.hh:228
void initialize()
Definition: mimetic.hh:127
void assemble(const Element &cell, const Dune::BlockVector< VBlockType > &localSolution, int orderOfShapeFns=1)
Definition: mimetic.hh:195
void setErrorInfo(Scalar maxErr, Scalar dt)
Definition: mimetic.hh:153
Scalar constructPressure(const Element &element, Dune::FieldVector< Scalar, 2 *dim > &pressTrace)
Definition: mimetic.hh:245
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:450
@ m
Definition: mimetic.hh:105
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:298
Dune::FieldVector< Scalar, m > VBlockType
Definition: mimetic.hh:194
Specifies the properties for immiscible 2p diffusion/pressure models.