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