3.1-git
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
mimeticadaptive.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_MIMETIC2PADAPTIVE_HH
25#define DUMUX_MIMETIC2PADAPTIVE_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"
43
44#include <dune/common/dynvector.hh>
45#include <dune/common/dynmatrix.hh>
46
47namespace Dumux {
48
53template<class TypeTag>
55{
56 using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
57 using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
58 using Problem = typename GET_PROP_TYPE(TypeTag, Problem);
59
60 using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices;
61
62 // grid types
63 enum
64 {
65 dim = GridView::dimension
66 };
67 enum
68 {
69 wPhaseIdx = Indices::wPhaseIdx,
70 nPhaseIdx = Indices::nPhaseIdx,
71 pressureIdx = Indices::pressureIdx,
72 saturationIdx = Indices::saturationIdx,
73 pressureEqIdx = Indices::pressureEqIdx,
74 satEqIdx = Indices::satEqIdx,
75 numPhases = GET_PROP_VALUE(TypeTag, NumPhases)
76 };
77 enum
78 {
79 pw = Indices::pressureW,
80 pn = Indices::pressureNw,
81 pGlobal = Indices::pressureGlobal,
82 Sw = Indices::saturationW,
83 Sn = Indices::saturationNw,
84 vw = Indices::velocityW,
85 vn = Indices::velocityNw,
87 pressureType = GET_PROP_VALUE(TypeTag, PressureFormulation),
89 saturationType = GET_PROP_VALUE(TypeTag, SaturationFormulation)
90 };
91
92 using Grid = typename GridView::Grid;
93 using Element = typename GridView::Traits::template Codim<0>::Entity;
94
95 using BoundaryTypes = typename GET_PROP_TYPE(TypeTag, BoundaryTypes);
96 using SolutionTypes = typename GET_PROP(TypeTag, SolutionTypes);
97 using PrimaryVariables = typename SolutionTypes::PrimaryVariables;
98 using CellData = typename GET_PROP_TYPE(TypeTag, CellData);
99 using FluidSystem = typename GET_PROP_TYPE(TypeTag, FluidSystem);
100 using FluidState = typename GET_PROP_TYPE(TypeTag, FluidState);
101 using MaterialLaw = typename GET_PROP_TYPE(TypeTag, MaterialLaw);
102
104
105public:
106 // define the number of components of your system, this is used outside
107 // to allocate the correct size of (dense) blocks with a FieldMatrix
108 enum
109 {
110 m = 1
111 };
112 enum
113 {
114 size = 2 * dim
115 };
116
118 MimeticTwoPLocalStiffnessAdaptive(Problem& problem, bool levelBoundaryAsDirichlet,
119 const GridView& gridView, const IntersectionMapper& intersectionMapper,bool procBoundaryAsDirichlet = true) :
120 problem_(problem), gridView_(gridView), intersectionMapper_(intersectionMapper), maxError_(0), timeStep_(1)
121 {
122 int size = gridView_.size(0);
123 rhs_.resize(size , 0.);
124 W_.resize(size);
125 ErrorTermFactor_ = getParam<Scalar>("Impet.ErrorTermFactor");
126 ErrorTermLowerBound_ = getParam<Scalar>("Impet.ErrorTermLowerBound");
127 ErrorTermUpperBound_ = getParam<Scalar>("Impet.ErrorTermUpperBound");
128
129 density_[wPhaseIdx] = 0.0;
130 density_[nPhaseIdx] = 0.0;
131 viscosity_[wPhaseIdx] =0.0;
132 viscosity_[nPhaseIdx] = 0.0;
133 }
134
136 {
137 const auto element = *problem_.gridView().template begin<0>();
138 FluidState fluidState;
139 fluidState.setPressure(wPhaseIdx, problem_.referencePressure(element));
140 fluidState.setPressure(nPhaseIdx, problem_.referencePressure(element));
141 fluidState.setTemperature(problem_.temperature(element));
142 fluidState.setSaturation(wPhaseIdx, 1.);
143 fluidState.setSaturation(nPhaseIdx, 0.);
144 density_[wPhaseIdx] = FluidSystem::density(fluidState, wPhaseIdx);
145 density_[nPhaseIdx] = FluidSystem::density(fluidState, nPhaseIdx);
146 viscosity_[wPhaseIdx] = FluidSystem::viscosity(fluidState, wPhaseIdx);
147 viscosity_[nPhaseIdx] = FluidSystem::viscosity(fluidState, nPhaseIdx);
148
149 adapt();
150 }
151
152 void adapt()
153 {
154 int size = gridView_.size(0);
155 rhs_.resize(size , 0.);
156 W_.resize(size);
157 }
158
159 void reset()
160 {
161 rhs_ = 0;
162 maxError_ = 0;
163 timeStep_ = 1;
164 }
165
166 void setErrorInfo(Scalar maxErr, Scalar dt)
167 {
168 maxError_ = maxErr;
169 timeStep_ = dt;
170 }
171
172 int numberOfFaces(int eIdxGlobal)
173 {
174 return W_[eIdxGlobal].N();
175 }
176
189 void assemble(const Element& element, int k = 1)
190 {
191 int numFaces = intersectionMapper_.size(element);
192
193 this->setcurrentsize(numFaces);
194
195 // clear assemble data
196 for (int i = 0; i < numFaces; i++)
197 {
198 this->b[i] = 0;
199 this->bctype[i].reset();
200 for (int j = 0; j < numFaces; j++)
201 this->A[i][j] = 0;
202 }
203
204 assembleV(element, numFaces, k);
205 assembleBC(element, k);
206 }
207
208 // TODO/FIXME: this is only valid for linear problems where
209 // the local stiffness matrix is independend of the current
210 // solution. We need to implement this properly, but this
211 // should at least make the thing compile...
212 using VBlockType = Dune::FieldVector<Scalar, m>;
213 void assemble(const Element &cell, const Dune::BlockVector<VBlockType>& localSolution, int orderOfShapeFns = 1)
214 {
215 assemble(cell, orderOfShapeFns);
216 }
217
228 void assembleBoundaryCondition(const Element& element, int k = 1)
229 {
230 int numFaces = intersectionMapper_.size(element);
231
232 // clear assemble data
233 for (int i = 0; i < numFaces; i++)
234 {
235 this->b[i] = 0;
236 this->bctype[i].reset();
237 }
238
239 assembleBC(element, k);
240 }
241
242 template<class Vector>
243 void completeRHS(const Element& element, std::vector<int>& local2Global, Vector& f)
244 {
245 int eIdxGlobal = problem_.variables().index(element);
246
247 int numFaces = numberOfFaces(eIdxGlobal);
248
249 Dune::DynamicVector<Scalar> F(numFaces);
250 Scalar dInv = 0.;
251 computeReconstructionMatrices(element, W_[eIdxGlobal], F, dInv);
252
253 for (int i = 0; i < numFaces; i++)
254 {
255// if (!this->bctype[i].isSet())
256 f[local2Global[i]][0] += (dInv * F[i] * rhs_[eIdxGlobal]);
257 }
258 }
259
260 Scalar constructPressure(const Element& element, Dune::DynamicVector<Scalar>& pressTrace)
261 {
262 int eIdxGlobal = problem_.variables().index(element);
263
264 int numFaces = numberOfFaces(eIdxGlobal);
265
266 Scalar volume = element.geometry().volume();
267
268 PrimaryVariables sourceVec(0.0);
269 problem_.source(sourceVec, element);
270 Scalar qmean = volume * (sourceVec[wPhaseIdx]/density_[wPhaseIdx] + sourceVec[nPhaseIdx]/density_[nPhaseIdx]);
271 qmean += rhs_[eIdxGlobal];
272
273 Dune::DynamicVector<Scalar> F(numFaces, 0.);
274 Scalar dInv = 0.;
275 computeReconstructionMatrices(element, W_[eIdxGlobal], F, dInv);
276
277 return (dInv*(qmean + (F*pressTrace)));
278 }
279
280 void constructVelocity(const Element& element, Dune::DynamicVector<Scalar>& vel,
281 Dune::DynamicVector<Scalar>& pressTrace, Scalar press)
282 {
283 int eIdxGlobal = problem_.variables().index(element);
284
285 int numFaces = numberOfFaces(eIdxGlobal);
286
287 Dune::DynamicVector<Scalar> faceVol(numFaces);
288
289 Dune::FieldVector<Scalar, 2*dim> faceVolumeReal(0.0);
290
291 int idx = 0;
292 for (const auto& intersection : intersections(gridView_, element))
293 {
294 faceVol[idx] = intersection.geometry().volume();
295 int indexInInside = intersection.indexInInside();
296 faceVolumeReal[indexInInside] += faceVol[idx];
297
298 idx++;
299 }
300
301 vel = 0;
302 for (int i = 0; i < numFaces; i++)
303 for (int j = 0; j < numFaces; j++)
304 vel[i] += W_[eIdxGlobal][i][j]*faceVol[j]*(press - pressTrace[j]);
305
306 for (int i = 0; i < numFaces; i++)
307 {
308 vel[i] *= faceVol[i]/faceVolumeReal[intersectionMapper_.maplocal(eIdxGlobal, i)];
309 }
310
311 }
312
313 void computeReconstructionMatrices(const Element& element, const Dune::DynamicMatrix<Scalar>& W,
314 Dune::DynamicVector<Scalar>& F, Scalar& dInv)
315 {
316 int eIdxGlobal = problem_.variables().index(element);
317
318 int numFaces = numberOfFaces(eIdxGlobal);
319
320 Dune::DynamicVector<Scalar> c(numFaces);
321 Dune::DynamicMatrix<Scalar> Pi(numFaces, numFaces);
322
323 int idx = 0;
324 for (const auto& intersection : intersections(gridView_, element))
325 {
326 Scalar faceVol = intersection.geometry().volume();
327
328 // Corresponding to the element under consideration,
329 // calculate the part of the matrix C coupling velocities and element pressures.
330 // This is just a row vector of size numFaces.
331 // scale with volume
332 c[idx] = faceVol;
333 // Set up the element part of the matrix \Pi coupling velocities
334 // and pressure-traces. This is a diagonal matrix with entries given by faceVol.
335 Pi[idx][idx] = faceVol;
336 idx++;
337 }
338
339 // Calculate the element part of the matrix D^{-1} = (c W c^T)^{-1} which is just a scalar value.
340 Dune::DynamicVector<Scalar> Wc(numFaces);
341 W.umv(c, Wc);
342 dInv = 1.0 / (c * Wc);
343
344 // Calculate the element part of the matrix F = Pi W c^T which is a column vector.
345 F = 0;
346 Pi.umv(Wc, F);
347 }
348
349 void assembleElementMatrices(const Element& element,
350 Dune::DynamicVector<Scalar>& faceVol,
351 Dune::DynamicVector<Scalar>& F,
352 Dune::DynamicMatrix<Scalar>& Pi,
353 Scalar& dInv,
354 Scalar& qmean);
355
356
357 const Problem& problem() const
358 {
359 return problem_;
360 }
361
362private:
363 void assembleV(const Element& element, int numFaces, int k = 1);
364
365 void assembleBC(const Element& element, int k = 1);
366
367 Scalar evaluateErrorTerm(CellData& cellData)
368 {
369 // error term for incompressible models to correct unphysical saturation over/undershoots due to saturation transport
370 // error reduction routine: volumetric error is damped and inserted to right hand side
371 Scalar sat = 0;
372 switch (saturationType)
373 {
374 case Sw:
375 sat = cellData.saturation(wPhaseIdx);
376 break;
377 case Sn:
378 sat = cellData.saturation(nPhaseIdx);
379 break;
380 }
381
382 Scalar error = (sat > 1.0) ? sat - 1.0 : 0.0;
383 if (sat < 0.0)
384 {
385 error = sat;
386 }
387 error /= timeStep_;
388
389 using std::abs;
390 Scalar errorAbs = abs(error);
391
392 if ((errorAbs * timeStep_ > 1e-6) && (errorAbs > ErrorTermLowerBound_ * maxError_)
393 && (!problem_.timeManager().willBeFinished()))
394 {
395 return ErrorTermFactor_ * error;
396 }
397 return 0.0;
398 }
399
400private:
401 Problem& problem_;
402 const GridView gridView_;
403 const IntersectionMapper& intersectionMapper_;
404 Dune::DynamicVector<Scalar> rhs_;
405 std::vector<Dune::DynamicMatrix<Scalar> > W_;
406 Scalar maxError_;
407 Scalar timeStep_;
408 Scalar ErrorTermFactor_; // Handling of error term: relaxation factor
409 Scalar ErrorTermLowerBound_; // Handling of error term: lower bound for error dampening
410 Scalar ErrorTermUpperBound_; // Handling of error term: upper bound for error dampening
411
412 Scalar density_[numPhases];
413 Scalar viscosity_[numPhases];
414};
415
416// TODO doc me!
417template<class TypeTag>
418void MimeticTwoPLocalStiffnessAdaptive<TypeTag>::assembleV(const Element& element, int numFaces, int k)
419{
420 int eIdxGlobal = problem_.variables().index(element);
421
422 // The notation is borrowed from Aarnes/Krogstadt/Lie 2006, Section 3.4.
423 // The matrix W developed here corresponds to one element-associated
424 // block of the matrix B^{-1} there.
425 W_[eIdxGlobal].resize(numFaces, numFaces);
426 Dune::DynamicVector<Scalar> faceVol(numFaces);
427 Dune::DynamicMatrix<Scalar> Pi(numFaces, numFaces);
428 Dune::DynamicVector<Scalar> F(numFaces);
429 Scalar dInv = 0.;
430 Scalar qmean = 0.;
431 this->assembleElementMatrices(element, faceVol, F, Pi, dInv, qmean);
432
433 // Calculate the element part of the matrix Pi W Pi^T.
434 Dune::DynamicMatrix<Scalar> PiWPiT(W_[eIdxGlobal]);
435 PiWPiT.rightmultiply(Pi);
436 PiWPiT.leftmultiply(Pi);
437
438 // Calculate the element part of the matrix F D^{-1} F^T.
439 Dune::DynamicMatrix<Scalar> FDinvFT(numFaces, numFaces);
440 for (int i = 0; i < numFaces; i++)
441 for (int j = 0; j < numFaces; j++)
442 FDinvFT[i][j] = dInv * F[i] * F[j];
443
444 // Calculate the element part of the matrix S = Pi W Pi^T - F D^{-1} F^T.
445 for (int i = 0; i < numFaces; i++)
446 for (int j = 0; j < numFaces; j++)
447 this->A[i][j] = PiWPiT[i][j] - FDinvFT[i][j];
448
449 // Calculate the source term F D^{-1} f
450 // NOT WORKING AT THE MOMENT
451 Scalar factor = dInv * qmean;
452 for (int i = 0; i < numFaces; i++)
453 this->b[i] = F[i] * factor;
454
455 // std::cout << "faceVol = " << faceVol << std::endl << "W = " << std::endl << W << std::endl
456 // << "c = " << c << std::endl << "Pi = " << std::endl << Pi << std::endl
457 // << "dinv = " << dinv << std::endl << "F = " << F << std::endl;
458 // std::cout << "dinvF = " << dinvF << ", q = " << qmean
459 // << ", b = " << this->b[0] << ", " << this->b[1] << ", " << this->b[2] << ", " << this->b[3] << std::endl;
460}
461
462// TODO doc me!
463template<class TypeTag>
465 Dune::DynamicVector<Scalar>& faceVol,
466 Dune::DynamicVector<Scalar>& F,
467 Dune::DynamicMatrix<Scalar>& Pi,
468 Scalar& dInv,
469 Scalar& qmean)
470{
471 // get global coordinate of cell center
472 const Dune::FieldVector<Scalar, dim>& centerGlobal = element.geometry().center();
473
474 int eIdxGlobal = problem_.variables().index(element);
475
476 CellData& cellData = problem_.variables().cellData(eIdxGlobal);
477
478 int numFaces = intersectionMapper_.size(eIdxGlobal);
479
480 // cell volume
481 Scalar volume = element.geometry().volume();
482
483 // build the matrices R and ~N
484 Dune::DynamicMatrix<Scalar> R(numFaces, dim, 0.);
485 Dune::DynamicMatrix<Scalar> N(numFaces, dim, 0.);
486
487 // std::cout << "element " << elemId << ": center " << centerGlobal << std::endl;
488
489 // collect information needed for calculation of fluxes due to capillary-potential (pc + gravity!)
490 std::vector<Scalar> pcPotFace(numFaces);
491 Scalar pcPot = (problem_.bBoxMax() - element.geometry().center()) * problem_.gravity()
492 * (density_[nPhaseIdx] - density_[wPhaseIdx]);
493
494 int idx = 0;
495 for (const auto& intersection : intersections(gridView_, element))
496 {
497 // local number of facet
498
499 Dune::FieldVector<Scalar, dim> faceGlobal(intersection.geometry().center());
500 faceVol[idx] = intersection.geometry().volume();
501
502 // get normal vector
503 const Dune::FieldVector<Scalar, dim>& unitOuterNormal = intersection.centerUnitOuterNormal();
504
505
506 for (int k = 0; k < dim; k++)
507 {
508 // move origin to the center of gravity
509 R[idx][k] = faceVol[idx] * (faceGlobal[k] - centerGlobal[k]);
510 N[idx][k] = unitOuterNormal[k];
511 }
512
513 pcPotFace[idx] = (problem_.bBoxMax() - faceGlobal) * problem_.gravity()
514 * (density_[nPhaseIdx] - density_[wPhaseIdx]);
515
516 idx++;
517 }
518
519 // proceed along the lines of Algorithm 1 from
520 // Brezzi/Lipnikov/Simonicini M3AS 2005
521 // (1) orthonormalize columns of the matrix R (Gram-Schmidt orthonormalization)
522 Scalar norm = R[0][0] * R[0][0];
523 using std::sqrt;
524 for (int i = 1; i < numFaces; i++)
525 norm += R[i][0] * R[i][0];
526 norm = sqrt(norm);
527 for (int i = 0; i < numFaces; i++)
528 R[i][0] /= norm;
529 Scalar weight = R[0][1] * R[0][0];
530 for (int i = 1; i < numFaces; i++)
531 weight += R[i][1] * R[i][0];
532 for (int i = 0; i < numFaces; i++)
533 R[i][1] -= weight * R[i][0];
534 norm = R[0][1] * R[0][1];
535 for (int i = 1; i < numFaces; i++)
536 norm += R[i][1] * R[i][1];
537 norm = sqrt(norm);
538 for (int i = 0; i < numFaces; i++)
539 R[i][1] /= norm;
540 if (dim == 3)
541 {
542 Scalar weight1 = R[0][2] * R[0][0];
543 Scalar weight2 = R[0][2] * R[0][1];
544 for (int i = 1; i < numFaces; i++)
545 {
546 weight1 += R[i][2] * R[i][0];
547 weight2 += R[i][2] * R[i][1];
548 }
549 for (int i = 0; i < numFaces; i++)
550 R[i][2] -= weight1 * R[i][0] + weight2 * R[i][1];
551 norm = R[0][2] * R[0][2];
552 for (int i = 1; i < numFaces; i++)
553 norm += R[i][2] * R[i][2];
554 using std::sqrt;
555 norm = sqrt(norm);
556 for (int i = 0; i < numFaces; i++)
557 R[i][2] /= norm;
558 }
559 // std::cout << "~R =\dim" << R;
560
561 // (2) Build the matrix ~D
562 Dune::DynamicMatrix<Scalar> D(numFaces, numFaces, 0.);
563 for (int s = 0; s < numFaces; s++)
564 {
565 Dune::DynamicVector<Scalar> es(numFaces, 0.);
566 es[s] = 1;
567 for (int k = 0; k < numFaces; k++)
568 {
569 D[k][s] = es[k];
570 for (int i = 0; i < dim; i++)
571 {
572 D[k][s] -= R[s][i] * R[k][i];
573 }
574 }
575 }
576// std::cout<<"D = "<<D<<"\n";
577
578 // eval diffusion tensor, ASSUMING to be constant over each cell
579 Dune::FieldMatrix<Scalar, dim, dim> mobility(problem_.spatialParams().intrinsicPermeability(element));
580 mobility *= (cellData.mobility(wPhaseIdx) + cellData.mobility(nPhaseIdx));
581
582 Scalar traceMob = mobility[0][0];
583 for (int i = 1; i < dim; i++)
584 traceMob += mobility[i][i];
585 D *= 2.0 * traceMob / volume;
586 // std::cout << "u~D =\dim" << D;
587
588 // (3) Build the matrix W = Minv
589 Dune::DynamicMatrix<Scalar> NK(N);
590 NK.rightmultiply(mobility);
591
592// std::cout<<"NK = "<<NK<<"\n";
593
594 for (int i = 0; i < numFaces; i++)
595 {
596 for (int j = 0; j < numFaces; j++)
597 {
598 W_[eIdxGlobal][i][j] = NK[i][0] * N[j][0];
599 for (int k = 1; k < dim; k++)
600 W_[eIdxGlobal][i][j] += NK[i][k] * N[j][k];
601 }
602 }
603
604 W_[eIdxGlobal] /= volume;
605 W_[eIdxGlobal] += D;
606
607 // std::cout << "W = \dim" << W;
608
609 // Now the notation is borrowed from Aarnes/Krogstadt/Lie 2006, Section 3.4.
610 // The matrix W developed so far corresponds to one element-associated
611 // block of the matrix B^{-1} there.
612
613 // Corresponding to the element under consideration,
614 // calculate the part of the matrix C coupling velocities and element pressures.
615 // This is just a row vector of size numFaces.
616 // scale with volume
617 Dune::DynamicVector<Scalar> c(numFaces);
618 for (int i = 0; i < numFaces; i++)
619 c[i] = faceVol[i];
620
621 // Set up the element part of the matrix \Pi coupling velocities
622 // and pressure-traces. This is a diagonal matrix with entries given by faceVol.
623 for (int i = 0; i < numFaces; i++)
624 Pi[i][i] = faceVol[i];
625
626 // Calculate the element part of the matrix D^{-1} = (c W c^T)^{-1} which is just a scalar value.
627 Dune::DynamicVector<Scalar> Wc(numFaces);
628 W_[eIdxGlobal].umv(c, Wc);
629 dInv = 1.0 / (c * Wc);
630
631 // Calculate the element part of the matrix F = Pi W c^T which is a column vector.
632 F = 0;
633 Pi.umv(Wc, F);
634 // std::cout << "Pi = \dim" << Pi << "c = " << c << ", F = " << F << std::endl;
635
636 // accumulate fluxes due to capillary potential (pc + gravity!)
637 idx = 0;
638 for (const auto& intersection : intersections(gridView_, element))
639 {
640 Scalar fracFlow = 0;
641
642 Scalar flux = 0;
643 for (int j = 0; j < numFaces; j++)
644 flux += W_[eIdxGlobal][idx][j] * faceVol[j] * (pcPot - pcPotFace[j]);
645
646 if (intersection.neighbor())
647 {
648
649 int eIdxGlobalNeighbor = problem_.variables().index(intersection.outside());
650 if (flux > 0.)
651 {
652 switch (pressureType)
653 {
654 case pw:
655 {
656 fracFlow = cellData.fracFlowFunc(nPhaseIdx);
657 break;
658 }
659 case pn:
660 {
661 fracFlow = -cellData.fracFlowFunc(wPhaseIdx);
662 break;
663 }
664 }
665
666 rhs_[eIdxGlobal] -= (faceVol[idx] * fracFlow * flux);
667 rhs_[eIdxGlobalNeighbor] += (faceVol[idx] * fracFlow * flux);
668 }
669 }
670 else if (intersection.boundary())
671 {
672 BoundaryTypes bctype;
673 problem_.boundaryTypes(bctype, intersection);
674
675 if (bctype.isDirichlet(pressureEqIdx))
676 {
677 if (flux > 0. || !bctype.isDirichlet(satEqIdx))
678 {
679 switch (pressureType)
680 {
681 case pw:
682 {
683 fracFlow = cellData.fracFlowFunc(nPhaseIdx);
684 break;
685 }
686 case pn:
687 {
688 fracFlow = -cellData.fracFlowFunc(wPhaseIdx);
689 break;
690 }
691 }
692 }
693 else if (flux < 0. && bctype.isDirichlet(satEqIdx))
694 {
695 PrimaryVariables boundValues(0.0);
696 problem_.dirichlet(boundValues, intersection);
697
698 Scalar krw = MaterialLaw::krw(problem_.spatialParams().materialLawParams(element),
699 boundValues[saturationIdx]);
700 Scalar krn = MaterialLaw::krn(problem_.spatialParams().materialLawParams(element),
701 boundValues[saturationIdx]);
702
703 switch (pressureType)
704 {
705 case pw:
706 {
707 fracFlow = krn / viscosity_[nPhaseIdx]
708 / (krw / viscosity_[wPhaseIdx] + krn / viscosity_[nPhaseIdx]);
709 break;
710 }
711 case pn:
712 {
713 fracFlow = -krw / viscosity_[wPhaseIdx]
714 / (krw / viscosity_[wPhaseIdx] + krn / viscosity_[nPhaseIdx]);
715 break;
716 }
717 }
718 }
719
720 rhs_[eIdxGlobal] -= (faceVol[idx] * fracFlow * flux);
721 }
722 }
723 idx++;
724 }
725
726 PrimaryVariables sourceVec(0.0);
727 problem_.source(sourceVec, element);
728 qmean = volume * (sourceVec[wPhaseIdx]/density_[wPhaseIdx] + sourceVec[nPhaseIdx]/density_[nPhaseIdx]);
729
730 qmean += evaluateErrorTerm(cellData) * volume;
731}
732
733// TODO doc me!
734template<class TypeTag>
735void MimeticTwoPLocalStiffnessAdaptive<TypeTag>::assembleBC(const Element& element, int k)
736{
737 // evaluate boundary conditions via an intersection loop
738 unsigned int faceIndex = 0;
739 for (const auto& intersection : intersections(gridView_, element))
740 {
741 if (intersection.neighbor())
742 {
743
744 }
745 else if (intersection.boundary())
746 {
747 problem_.boundaryTypes(this->bctype[faceIndex], intersection);
748 PrimaryVariables boundValues(0.0);
749
750 if (this->bctype[faceIndex].isNeumann(pressureEqIdx))
751 {
752 problem_.neumann(boundValues, intersection);
753 Scalar J = (boundValues[wPhaseIdx]/density_[wPhaseIdx] + boundValues[nPhaseIdx]/density_[nPhaseIdx]);
754 this->b[faceIndex] -= J * intersection.geometry().volume();
755 }
756 else if (this->bctype[faceIndex].isDirichlet(pressureEqIdx))
757 {
758 problem_.dirichlet(boundValues, intersection);
759 if (pressureType == pw)
760 this->b[faceIndex] = boundValues[pressureIdx] + (problem_.bBoxMax()
761 - intersection.geometry().center()) * problem_.gravity() * density_[wPhaseIdx];
762 else if (pressureType == pn)
763 this->b[faceIndex] = boundValues[pressureIdx] + (problem_.bBoxMax()
764 - intersection.geometry().center()) * problem_.gravity() * density_[nPhaseIdx];
765 else
766 this->b[faceIndex] = boundValues[pressureIdx];
767 }
768 }
769 faceIndex++;
770 }
771}
772
773} // end namespace Dumux
774#endif
#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.
defines intersection mappers.
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
defines an intersection mapper for mapping of global DOFs assigned to faces which also works for adap...
Definition: intersectionmapper.hh:185
unsigned int size() const
Definition: intersectionmapper.hh:292
int maplocal(int elemIdx, int fIdx)
Definition: intersectionmapper.hh:270
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
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: mimeticadaptive.hh:55
Scalar constructPressure(const Element &element, Dune::DynamicVector< Scalar > &pressTrace)
Definition: mimeticadaptive.hh:260
void assembleBoundaryCondition(const Element &element, int k=1)
Assembles only boundary conditions for given element.
Definition: mimeticadaptive.hh:228
void initialize()
Definition: mimeticadaptive.hh:135
void computeReconstructionMatrices(const Element &element, const Dune::DynamicMatrix< Scalar > &W, Dune::DynamicVector< Scalar > &F, Scalar &dInv)
Definition: mimeticadaptive.hh:313
void reset()
Definition: mimeticadaptive.hh:159
void setErrorInfo(Scalar maxErr, Scalar dt)
Definition: mimeticadaptive.hh:166
void assemble(const Element &cell, const Dune::BlockVector< VBlockType > &localSolution, int orderOfShapeFns=1)
Definition: mimeticadaptive.hh:213
void adapt()
Definition: mimeticadaptive.hh:152
void completeRHS(const Element &element, std::vector< int > &local2Global, Vector &f)
Definition: mimeticadaptive.hh:243
void assemble(const Element &element, int k=1)
Assembles local stiffness matrix for given element and order.
Definition: mimeticadaptive.hh:189
void constructVelocity(const Element &element, Dune::DynamicVector< Scalar > &vel, Dune::DynamicVector< Scalar > &pressTrace, Scalar press)
Definition: mimeticadaptive.hh:280
const Problem & problem() const
Definition: mimeticadaptive.hh:357
int numberOfFaces(int eIdxGlobal)
Definition: mimeticadaptive.hh:172
MimeticTwoPLocalStiffnessAdaptive(Problem &problem, bool levelBoundaryAsDirichlet, const GridView &gridView, const IntersectionMapper &intersectionMapper, bool procBoundaryAsDirichlet=true)
Constructor.
Definition: mimeticadaptive.hh:118
Dune::FieldVector< Scalar, m > VBlockType
Definition: mimeticadaptive.hh:212
@ size
Definition: mimeticadaptive.hh:114
@ m
Definition: mimeticadaptive.hh:110
void assembleElementMatrices(const Element &element, Dune::DynamicVector< Scalar > &faceVol, Dune::DynamicVector< Scalar > &F, Dune::DynamicMatrix< Scalar > &Pi, Scalar &dInv, Scalar &qmean)
Definition: mimeticadaptive.hh:464
Specifies the properties for immiscible 2p diffusion/pressure models.