Loading [MathJax]/extensions/tex2jax.js
3.4
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
mimetic.hh
Go to the documentation of this file.
1// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2// vi: set et ts=4 sw=4 sts=4:
3/*****************************************************************************
4 * See the file COPYING for full copying permissions. *
5 * *
6 * This program is free software: you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation, either version 3 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
18 *****************************************************************************/
24#ifndef DUMUX_MIMETIC2P_HH
25#define DUMUX_MIMETIC2P_HH
26
27#include<map>
28#include<iostream>
29#include<iomanip>
30#include<fstream>
31#include<vector>
32#include<sstream>
33
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>
38
41#include "localstiffness.hh"
42
43#include <dune/common/dynvector.hh>
44
45namespace Dumux {
46
51template<class TypeTag>
53{
57
59
60 // grid types
61 enum
62 {
63 dim = GridView::dimension
64 };
65 enum
66 {
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>()
74 };
75 enum
76 {
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>()
88 };
89
90 using Grid = typename GridView::Grid;
91 using Element = typename GridView::Traits::template Codim<0>::Entity;
92
95 using PrimaryVariables = typename SolutionTypes::PrimaryVariables;
99
100public:
101 // define the number of components of your system, this is used outside
102 // to allocate the correct size of (dense) blocks with a FieldMatrix
103 enum
104 {
105 m = 1
106 };
107 enum
108 {
109 size = 2 * dim
110 };
111
113 MimeticTwoPLocalStiffness(Problem& problem, bool levelBoundaryAsDirichlet,
114 const GridView& gridView, bool procBoundaryAsDirichlet = true) :
115 problem_(problem), gridView_(gridView), maxError_(0), timeStep_(1)
116 {
117 ErrorTermFactor_ = getParam<Scalar>("Impet.ErrorTermFactor");
118 ErrorTermLowerBound_ = getParam<Scalar>("Impet.ErrorTermLowerBound");
119 ErrorTermUpperBound_ = getParam<Scalar>("Impet.ErrorTermUpperBound");
120
121 density_[wPhaseIdx] = 0.0;
122 density_[nPhaseIdx] = 0.0;
123 viscosity_[wPhaseIdx] =0.0;
124 viscosity_[nPhaseIdx] = 0.0;
125 }
126
128 {
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.);
136 density_[wPhaseIdx] = FluidSystem::density(fluidState, wPhaseIdx);
137 density_[nPhaseIdx] = FluidSystem::density(fluidState, nPhaseIdx);
138 viscosity_[wPhaseIdx] = FluidSystem::viscosity(fluidState, wPhaseIdx);
139 viscosity_[nPhaseIdx] = FluidSystem::viscosity(fluidState, nPhaseIdx);
140
141 int size = gridView_.size(0);
142 rhs_.resize(size , 0.);
143 W_.resize(size);
144 }
145
146 void reset()
147 {
148 rhs_ = 0;
149 maxError_ = 0;
150 timeStep_ = 1;
151 }
152
153 void setErrorInfo(Scalar maxErr, Scalar dt)
154 {
155 maxError_ = maxErr;
156 timeStep_ = dt;
157 }
158
172 void assemble(const Element& element, int k = 1)
173 {
174 unsigned int numFaces = element.subEntities(1);
175 this->setcurrentsize(numFaces);
176
177 // clear assemble data
178 for (unsigned int i = 0; i < numFaces; i++)
179 {
180 this->b[i] = 0;
181 this->bctype[i].reset();
182 for (unsigned int j = 0; j < numFaces; j++)
183 this->A[i][j] = 0;
184 }
185
186 assembleV(element, k);
187 assembleBC(element, k);
188 }
189
190 // TODO/FIXME: this is only valid for linear problems where
191 // the local stiffness matrix is independend of the current
192 // solution. We need to implement this properly, but this
193 // should at least make the thing compile...
194 using VBlockType = Dune::FieldVector<Scalar, m>;
195 void assemble(const Element &cell, const Dune::BlockVector<VBlockType>& localSolution, int orderOfShapeFns = 1)
196 {
197 assemble(cell, orderOfShapeFns);
198 }
199
211 void assembleBoundaryCondition(const Element& element, int k = 1)
212 {
213 unsigned int numFaces = element.subEntities(1);
214 this->setcurrentsize(numFaces);
215
216 // clear assemble data
217 for (unsigned int i = 0; i < numFaces; i++)
218 {
219 this->b[i] = 0;
220 this->bctype[i].reset();
221 }
222
223 assembleBC(element, k);
224 }
225
226 // TODO doc me!
227 template<class Vector>
228 void completeRHS(const Element& element, Dune::FieldVector<int, 2*dim>& local2Global, Vector& f)
229 {
230 int eIdxGlobal = problem_.variables().index(element);
231 unsigned int numFaces = element.subEntities(1);
232
233 Dune::FieldVector<Scalar, 2 * dim> F(0.);
234 Scalar dInv = 0.;
235 computeReconstructionMatrices(element, W_[eIdxGlobal], F, dInv);
236
237 for (unsigned int i = 0; i < numFaces; i++)
238 {
239 if (!this->bc(i).isDirichlet(pressureEqIdx))
240 f[local2Global[i]][0] += (dInv * F[i] * rhs_[eIdxGlobal]);
241 }
242 }
243
244 // TODO doc me!
245 Scalar constructPressure(const Element& element, Dune::FieldVector<Scalar,2*dim>& pressTrace)
246 {
247 int eIdxGlobal = problem_.variables().index(element);
248 Scalar volume = element.geometry().volume();
249
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];
254
255 Dune::FieldVector<Scalar, 2 * dim> F(0.);
256 Scalar dInv = 0.;
257 computeReconstructionMatrices(element, W_[eIdxGlobal], F, dInv);
258
259 return (dInv*(qmean + (F*pressTrace)));
260 }
261
262 // TODO doc me!
263 void constructVelocity(const Element& element, Dune::FieldVector<Scalar,2*dim>& vel,
264 Dune::FieldVector<Scalar,2*dim>& pressTrace, Scalar press)
265 {
266 int eIdxGlobal = problem_.variables().index(element);
267
268 Dune::FieldVector<Scalar, 2 * dim> faceVol(0);
269 for (const auto& intersection : intersections(gridView_, element))
270 {
271 faceVol[intersection.indexInInside()] = intersection.geometry().volume();
272 }
273
274 vel = 0;
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]);
278 }
279
280 // TODO doc me!
281 void constructVelocity(const Element& element, int fIdx, Scalar& vel,
282 Dune::FieldVector<Scalar,2*dim>& pressTrace, Scalar press)
283 {
284 int eIdxGlobal = problem_.variables().index(element);
285
286 Dune::FieldVector<Scalar, 2 * dim> faceVol(0);
287 for (const auto& intersection : intersections(gridView_, element))
288 {
289 faceVol[intersection.indexInInside()] = intersection.geometry().volume();
290 }
291
292 vel = 0;
293 for (int j = 0; j < 2*dim; j++)
294 vel += W_[eIdxGlobal][fIdx][j]*faceVol[j]*(press - pressTrace[j]);
295 }
296
297 // TODO doc me!
298 void computeReconstructionMatrices(const Element& element,
299 const Dune::FieldMatrix<Scalar, 2 * dim, 2 * dim>& W,
300 Dune::FieldVector<Scalar, 2 * dim>& F, Scalar& dInv)
301 {
302 Dune::FieldVector<Scalar, 2 * dim> c(0);
303 Dune::FieldMatrix<Scalar, 2 * dim, 2 * dim> Pi(0);
304
305 for (const auto& intersection : intersections(gridView_, element))
306 {
307 // local number of facet
308 int idx = intersection.indexInInside();
309
310 Scalar faceVol = intersection.geometry().volume();
311
312 // Corresponding to the element under consideration,
313 // calculate the part of the matrix C coupling velocities and element pressures.
314 // This is just a row vector of size numFaces.
315 // scale with volume
316 c[idx] = faceVol;
317 // Set up the element part of the matrix \Pi coupling velocities
318 // and pressure-traces. This is a diagonal matrix with entries given by faceVol.
319 Pi[idx][idx] = faceVol;
320 }
321
322 // Calculate the element part of the matrix D^{-1} = (c W c^T)^{-1} which is just a scalar value.
323 Dune::FieldVector<Scalar, 2 * dim> Wc(0);
324 W.umv(c, Wc);
325 dInv = 1.0 / (c * Wc);
326
327 // Calculate the element part of the matrix F = Pi W c^T which is a column vector.
328 F = 0;
329 Pi.umv(Wc, F);
330 }
331
332 void assembleElementMatrices(const Element& element, Dune::FieldVector<Scalar, 2 * dim>& faceVol,
333 Dune::FieldVector<Scalar, 2 * dim>& F,
334 Dune::FieldMatrix<Scalar, 2 * dim, 2 * dim>& Pi,
335 Scalar& dInv,
336 Scalar& qmean);
337
338
339 const Problem& problem() const
340 {
341 return problem_;
342 }
343
344private:
345 void assembleV(const Element& element, int k = 1);
346
347 void assembleBC(const Element& element, int k = 1);
348
349 // TODO doc me!
350 Scalar evaluateErrorTerm(CellData& cellData)
351 {
352 //error term for incompressible models to correct unphysical saturation over/undershoots due to saturation transport
353 // error reduction routine: volumetric error is damped and inserted to right hand side
354 Scalar sat = 0;
355 switch (saturationType)
356 {
357 case Sw:
358 sat = cellData.saturation(wPhaseIdx);
359 break;
360 case Sn:
361 sat = cellData.saturation(nPhaseIdx);
362 break;
363 default:
364 DUNE_THROW(Dune::NotImplemented, "Only saturation formulation Sw and Sn are implemented!");
365 }
366
367 Scalar error = (sat > 1.0) ? sat - 1.0 : 0.0;
368 if (sat < 0.0)
369 {
370 error = sat;
371 }
372 error /= timeStep_;
373
374 using std::abs;
375 Scalar errorAbs = abs(error);
376
377 if ((errorAbs * timeStep_ > 1e-6) && (errorAbs > ErrorTermLowerBound_ * maxError_)
378 && (!problem_.timeManager().willBeFinished()))
379 {
380 return ErrorTermFactor_ * error;
381 }
382 return 0.0;
383 }
384
385private:
386 Problem& problem_;
387 GridView gridView_;
388 Dune::DynamicVector<Scalar> rhs_;
389 std::vector<Dune::FieldMatrix<Scalar, 2 * dim, 2 * dim> > W_;
390 Scalar maxError_;
391 Scalar timeStep_;
392 Scalar ErrorTermFactor_; // Handling of error term: relaxation factor
393 Scalar ErrorTermLowerBound_; // Handling of error term: lower bound for error dampening
394 Scalar ErrorTermUpperBound_; //S Handling of error term: upper bound for error dampening
395
396 Scalar density_[numPhases];
397 Scalar viscosity_[numPhases];
398};
399
400// TODO doc me!
401template<class TypeTag>
402void MimeticTwoPLocalStiffness<TypeTag>::assembleV(const Element& element, int)
403{
404 unsigned int numFaces = element.subEntities(1);
405 this->setcurrentsize(numFaces);
406
407 int eIdxGlobal = problem_.variables().index(element);
408
409 // The notation is borrowed from Aarnes/Krogstadt/Lie 2006, Section 3.4.
410 // The matrix W developed here corresponds to one element-associated
411 // block of the matrix B^{-1} there.
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.);
415 Scalar dInv = 0.;
416 Scalar qmean = 0.;
417 this->assembleElementMatrices(element, faceVol, F, Pi, dInv, qmean);
418
419 // Calculate the element part of the matrix Pi W Pi^T.
420 Dune::FieldMatrix<Scalar, 2 * dim, 2 * dim> PiWPiT(W_[eIdxGlobal]);
421 PiWPiT.rightmultiply(Pi);
422 PiWPiT.leftmultiply(Pi);
423
424 // Calculate the element part of the matrix F D^{-1} F^T.
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];
429
430 // Calculate the element part of the matrix S = Pi W Pi^T - F D^{-1} F^T.
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];
434
435 // Calculate the source term F D^{-1} f
436 // NOT WORKING AT THE MOMENT
437 Scalar factor = dInv * qmean;
438 for (unsigned int i = 0; i < numFaces; i++)
439 this->b[i] = F[i] * factor;
440
441 // std::cout << "faceVol = " << faceVol << std::endl << "W = " << std::endl << W << std::endl
442 // << "c = " << c << std::endl << "Pi = " << std::endl << Pi << std::endl
443 // << "dinv = " << dinv << std::endl << "F = " << F << std::endl;
444 // std::cout << "dinvF = " << dinvF << ", q = " << qmean
445 // << ", b = " << this->b[0] << ", " << this->b[1] << ", " << this->b[2] << ", " << this->b[3] << std::endl;
446}
447
448// TODO doc me!
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,
454 Scalar& dInv,
455 Scalar& qmean)
456{
457 unsigned int numFaces = element.subEntities(1);
458 this->setcurrentsize(numFaces);
459
460 // get global coordinate of cell center
461 Dune::FieldVector<Scalar, dim> centerGlobal = element.geometry().center();
462
463 int eIdxGlobal = problem_.variables().index(element);
464
465 CellData& cellData = problem_.variables().cellData(eIdxGlobal);
466
467 // cell volume
468 Scalar volume = element.geometry().volume();
469
470 // build the matrices R and ~N
471 Dune::FieldMatrix<Scalar, 2 * dim, dim> R(0), N(0);
472
473 // std::cout << "element " << elemId << ": center " << centerGlobal << std::endl;
474
475 // collect information needed for calculation of fluxes due to capillary-potential (pc + gravity!)
476 Scalar gravPotFace[2*dim];
477
478 Scalar gravPot = (problem_.bBoxMax() - centerGlobal) * problem_.gravity() * (density_[nPhaseIdx] - density_[wPhaseIdx]);
479
480 for (const auto& intersection : intersections(gridView_, element))
481 {
482 // local number of facet
483 int fIdx = intersection.indexInInside();
484
485 Dune::FieldVector<Scalar, dim> faceGlobal = intersection.geometry().center();
486 faceVol[fIdx] = intersection.geometry().volume();
487
488 // get normal vector
489 const Dune::FieldVector<Scalar, dim>& unitOuterNormal = intersection.centerUnitOuterNormal();
490
491 N[fIdx] = unitOuterNormal;
492
493 for (int k = 0; k < dim; k++)
494 // move origin to the center of gravity
495 R[fIdx][k] = faceVol[fIdx] * (faceGlobal[k] - centerGlobal[k]);
496
497 gravPotFace[fIdx] = (problem_.bBoxMax() - faceGlobal) * problem_.gravity() * (density_[nPhaseIdx] - density_[wPhaseIdx]);
498 }
499
500 // proceed along the lines of Algorithm 1 from
501 // Brezzi/Lipnikov/Simonicini M3AS 2005
502 // (1) orthonormalize columns of the matrix R
503 Scalar norm = R[0][0] * R[0][0];
504 using std::sqrt;
505 for (unsigned int i = 1; i < numFaces; i++)
506 norm += R[i][0] * R[i][0];
507 norm = sqrt(norm);
508 for (unsigned int i = 0; i < numFaces; i++)
509 R[i][0] /= norm;
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];
518 norm = sqrt(norm);
519 for (unsigned int i = 0; i < numFaces; i++)
520 R[i][1] /= norm;
521 if (dim == 3)
522 {
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++)
526 {
527 weight1 += R[i][2] * R[i][0];
528 weight2 += R[i][2] * R[i][1];
529 }
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];
535 using std::sqrt;
536 norm = sqrt(norm);
537 for (unsigned int i = 0; i < numFaces; i++)
538 R[i][2] /= norm;
539 }
540 // std::cout << "~R =\dim" << R;
541
542 // (2) Build the matrix ~D
543 Dune::FieldMatrix<Scalar, 2 * dim, 2 * dim> D(0);
544 for (unsigned int s = 0; s < numFaces; s++)
545 {
546 Dune::FieldVector<Scalar, 2 * dim> es(0);
547 es[s] = 1;
548 for (unsigned int k = 0; k < numFaces; k++)
549 {
550 D[k][s] = es[k];
551 for (unsigned int i = 0; i < dim; i++)
552 {
553 D[k][s] -= R[s][i] * R[k][i];
554 }
555 }
556 }
557
558// std::cout<<"D = "<<D<<"\n";
559
560 // eval diffusion tensor, ASSUMING to be constant over each cell
561 Dune::FieldMatrix<Scalar, dim, dim> mobility(problem_.spatialParams().intrinsicPermeability(element));
562 mobility *= (cellData.mobility(wPhaseIdx) + cellData.mobility(nPhaseIdx));
563
564 Scalar traceMob = mobility[0][0];
565 for (int i = 1; i < dim; i++)
566 traceMob += mobility[i][i];
567 D *= 2.0 * traceMob / volume;
568 // std::cout << "u~D =\dim" << D;
569
570 // (3) Build the matrix W = Minv
571 Dune::FieldMatrix<Scalar, 2 * dim, dim> NK(N);
572 NK.rightmultiply(mobility);
573
574 for (unsigned int i = 0; i < numFaces; i++)
575 {
576 for (unsigned int j = 0; j < numFaces; j++)
577 {
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];
581 }
582 }
583
584 W_[eIdxGlobal] /= volume;
585 W_[eIdxGlobal] += D;
586
587 // std::cout << "W = \dim" << W;
588
589 // Now the notation is borrowed from Aarnes/Krogstadt/Lie 2006, Section 3.4.
590 // The matrix W developed so far corresponds to one element-associated
591 // block of the matrix B^{-1} there.
592
593 // Corresponding to the element under consideration,
594 // calculate the part of the matrix C coupling velocities and element pressures.
595 // This is just a row vector of size numFaces.
596 // scale with volume
597 Dune::FieldVector<Scalar, 2 * dim> c(0);
598 for (unsigned int i = 0; i < numFaces; i++)
599 c[i] = faceVol[i];
600
601 // Set up the element part of the matrix \Pi coupling velocities
602 // and pressure-traces. This is a diagonal matrix with entries given by faceVol.
603 for (unsigned int i = 0; i < numFaces; i++)
604 Pi[i][i] = faceVol[i];
605
606 // Calculate the element part of the matrix D^{-1} = (c W c^T)^{-1} which is just a scalar value.
607 Dune::FieldVector<Scalar, 2 * dim> Wc(0);
608 W_[eIdxGlobal].umv(c, Wc);
609 dInv = 1.0 / (c * Wc);
610
611 // Calculate the element part of the matrix F = Pi W c^T which is a column vector.
612 F = 0;
613 Pi.umv(Wc, F);
614 // std::cout << "Pi = \dim" << Pi << "c = " << c << ", F = " << F << std::endl;
615
616 // accumulate fluxes due to capillary potential (pc + gravity!)
617 for (const auto& intersection : intersections(gridView_, element))
618 {
619 int idx = intersection.indexInInside();
620
621 Scalar fracFlow = 0;
622
623 Scalar flux = 0;
624 for (int j = 0; j < 2 * dim; j++)
625 flux += W_[eIdxGlobal][idx][j] * faceVol[j] * (gravPot - gravPotFace[j]);
626
627 //it is enough to evaluate the capillary/gravity flux for neighbors -> not needed anyway at the boundaries!
628 if (intersection.neighbor())
629 {
630 int eIdxGlobalNeighbor = problem_.variables().index(intersection.outside());
631 if (flux >= 0.)
632 {
633 switch (pressureType)
634 {
635 case pw:
636 {
637 fracFlow = cellData.fracFlowFunc(nPhaseIdx);
638 break;
639 }
640 case pn:
641 {
642 fracFlow = -cellData.fracFlowFunc(wPhaseIdx);
643 break;
644 }
645 default:
646 DUNE_THROW(Dune::NotImplemented, "Only pressure formulation pw and pn are implemented!");
647 }
648
649
650 rhs_[eIdxGlobal] -= (faceVol[idx] * fracFlow * flux);
651 rhs_[eIdxGlobalNeighbor] += (faceVol[idx] * fracFlow * flux);
652 }
653 }
654 else if (intersection.boundary())
655 {
656 BoundaryTypes bctype;
657 problem_.boundaryTypes(bctype, intersection);
658
659 if (bctype.isDirichlet(pressureEqIdx))
660 {
661 if (flux > 0. || !bctype.isDirichlet(satEqIdx))
662 {
663 switch (pressureType)
664 {
665 case pw:
666 {
667 fracFlow = cellData.fracFlowFunc(nPhaseIdx);
668 break;
669 }
670 case pn:
671 {
672 fracFlow = -cellData.fracFlowFunc(wPhaseIdx);
673 break;
674 }
675 default:
676 DUNE_THROW(Dune::NotImplemented, "Only pressure formulation pw and pn are implemented!");
677 }
678 }
679 else if (flux < 0. && bctype.isDirichlet(satEqIdx))
680 {
681 PrimaryVariables boundValues(0.0);
682 problem_.dirichlet(boundValues, intersection);
683
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]);
687
688 switch (pressureType)
689 {
690 case pw:
691 {
692 fracFlow = krn / viscosity_[nPhaseIdx]
693 / (krw / viscosity_[wPhaseIdx] + krn / viscosity_[nPhaseIdx]);
694 break;
695 }
696 case pn:
697 {
698 fracFlow = -krw / viscosity_[wPhaseIdx]
699 / (krw / viscosity_[wPhaseIdx] + krn / viscosity_[nPhaseIdx]);
700 break;
701 }
702 default:
703 DUNE_THROW(Dune::NotImplemented, "Only pressure formulation pw and pn are implemented!");
704 }
705 }
706
707 rhs_[eIdxGlobal] -= (faceVol[idx] * fracFlow * flux);
708 }
709 }
710 }
711
712 PrimaryVariables sourceVec(0.0);
713 problem_.source(sourceVec, element);
714 qmean = volume * (sourceVec[wPhaseIdx]/density_[wPhaseIdx] + sourceVec[nPhaseIdx]/density_[nPhaseIdx]);
715
716 qmean += evaluateErrorTerm(cellData) * volume;
717}
718
719// TODO doc me!
720template<class TypeTag>
721void MimeticTwoPLocalStiffness<TypeTag>::assembleBC(const Element& element, int k)
722{
723 // evaluate boundary conditions via intersection iterator
724 for (const auto& intersection : intersections(gridView_, element))
725 {
726 int faceIndex = intersection.indexInInside();
727 if (intersection.boundary())
728 {
729 problem_.boundaryTypes(this->bctype[faceIndex], intersection);
730 PrimaryVariables boundValues(0.0);
731
732 if (this->bctype[faceIndex].isNeumann(pressureEqIdx))
733 {
734 problem_.neumann(boundValues, intersection);
735 Scalar J = (boundValues[wPhaseIdx]/density_[wPhaseIdx] + boundValues[nPhaseIdx]/density_[nPhaseIdx]);
736 this->b[faceIndex] -= J * intersection.geometry().volume();
737 }
738 else if (this->bctype[faceIndex].isDirichlet(pressureEqIdx))
739 {
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];
747 else
748 this->b[faceIndex] = boundValues[pressureIdx];
749 }
750 }
751 }
752
753}
754
755}
756#endif
Definition of boundary condition types, extend if necessary.
Base class for assembling local stiffness matrices.
Definition: adapt.hh:29
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.