3.3.0
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
2p/sequential/diffusion/mimetic/pressure.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_MIMETICPRESSURE2P_HH
25#define DUMUX_MIMETICPRESSURE2P_HH
26
27#include <dune/common/exceptions.hh>
28
29// dumux environment
34
36
37namespace Dumux {
38
65template<class TypeTag> class MimeticPressure2P
66{
70
72
74
77
78 enum
79 {
80 dim = GridView::dimension, dimWorld = GridView::dimensionworld
81 };
82 enum
83 {
84 pw = Indices::pressureW,
85 pn = Indices::pressureNw,
86 pGlobal = Indices::pressureGlobal,
87 sw = Indices::saturationW,
88 sn = Indices::saturationNw,
89 vw = Indices::velocityW,
90 vn = Indices::velocityNw,
92 pressureType = getPropValue<TypeTag, Properties::PressureFormulation>(),
94 saturationType = getPropValue<TypeTag, Properties::SaturationFormulation>(),
95 };
96 enum
97 {
98 wPhaseIdx = Indices::wPhaseIdx, nPhaseIdx = Indices::nPhaseIdx,
99 numPhases = getPropValue<TypeTag, Properties::NumPhases>()
100 };
101
102 using Element = typename GridView::Traits::template Codim<0>::Entity;
103 using Grid = typename GridView::Grid;
104
105 using Geometry = typename Element::Geometry;
106 using JacobianTransposed = typename Geometry::JacobianTransposed ;
107
109 using TraceType = Dune::BlockVector<Dune::FieldVector<Scalar, 1> >;
111
114 using ScalarSolutionType = typename SolutionTypes::ScalarSolution;
115
118
119 using DimVector = Dune::FieldVector<Scalar, dim>;
120
122 void initializeMatrix();
123
125 void assemble(bool first)
126 {
127 Scalar timeStep = problem_.timeManager().timeStepSize();
128 Scalar maxError = 0.0;
129 int size = problem_.gridView().size(0);
130 for (int i = 0; i < size; i++)
131 {
132 Scalar sat = 0;
133 using std::max;
134 switch (saturationType)
135 {
136 case sw:
137 sat = problem_.variables().cellData(i).saturation(wPhaseIdx);
138 break;
139 case sn:
140 sat = problem_.variables().cellData(i).saturation(nPhaseIdx);
141 break;
142 default:
143 DUNE_THROW(Dune::NotImplemented, "Only saturation formulation sw and sn are implemented!");
144 }
145 if (sat > 1.0)
146 {
147 maxError = max(maxError, (sat - 1.0) / timeStep);
148 }
149 if (sat < 0.0)
150 {
151 maxError = max(maxError, (-sat) / timeStep);
152 }
153 }
154
155 lstiff_.setErrorInfo(maxError, timeStep);
156 A_.assemble(lstiff_, pressTrace_, f_);
157 return;
158 }
159
161 void solve();
162
163 void postprocess()
164 {
165 A_.calculatePressure(lstiff_, pressTrace_, problem_);
166
167 return;
168 }
169
170public:
172 void updateMaterialLaws();
173
182 void initialize(bool solveTwice = true)
183 {
184 const auto element = *problem_.gridView().template begin<0>();
185 FluidState fluidState;
186 fluidState.setPressure(wPhaseIdx, problem_.referencePressure(element));
187 fluidState.setPressure(nPhaseIdx, problem_.referencePressure(element));
188 fluidState.setTemperature(problem_.temperature(element));
189 fluidState.setSaturation(wPhaseIdx, 1.);
190 fluidState.setSaturation(nPhaseIdx, 0.);
191 density_[wPhaseIdx] = FluidSystem::density(fluidState, wPhaseIdx);
192 density_[nPhaseIdx] = FluidSystem::density(fluidState, nPhaseIdx);
193 viscosity_[wPhaseIdx] = FluidSystem::viscosity(fluidState, wPhaseIdx);
194 viscosity_[nPhaseIdx] = FluidSystem::viscosity(fluidState, nPhaseIdx);
195
197 A_.initialize();
198 pressTrace_.resize(problem_.gridView().size(1));
199 f_.resize(problem_.gridView().size(1));
200 lstiff_.initialize();
201 lstiff_.reset();
202
203 pressTrace_ = 0.0;
204 f_ = 0;
205
206 assemble(true);
207 solve();
208 postprocess();
209
210 return;
211 }
212
219 {
221 postprocess();
222 }
223
224 // TODO doc me!
225 void update()
226 {
227 lstiff_.reset();
228
229 assemble(false);
230 solve();
231 postprocess();
232
233 return;
234 }
235
242 template<class MultiWriter>
243 void addOutputVtkFields(MultiWriter &writer)
244 {
245 int size = problem_.gridView().size(0);
246 ScalarSolutionType *potential = writer.allocateManagedBuffer(size);
247 ScalarSolutionType *pressure = 0;
248 ScalarSolutionType *pressureSecond = 0;
249 ScalarSolutionType *potentialSecond = 0;
250 Dune::BlockVector < DimVector > *velocityWetting = 0;
251 Dune::BlockVector < DimVector > *velocityNonwetting = 0;
252
253 if (vtkOutputLevel_ > 0)
254 {
255 pressure = writer.allocateManagedBuffer(size);
256 pressureSecond = writer.allocateManagedBuffer(size);
257 potentialSecond = writer.allocateManagedBuffer(size);
258 velocityWetting = writer.template allocateManagedBuffer<Scalar, dim>(size);
259 velocityNonwetting = writer.template allocateManagedBuffer<Scalar, dim>(size);
260 }
261
262
263 for (const auto& element : elements(problem_.gridView()))
264 {
265 int eIdxGlobal = problem_.variables().index(element);
266 CellData& cellData = problem_.variables().cellData(eIdxGlobal);
267
268 if (pressureType == pw)
269 {
270 (*potential)[eIdxGlobal] = cellData.potential(wPhaseIdx);
271 }
272
273 if (pressureType == pn)
274 {
275 (*potential)[eIdxGlobal] = cellData.potential(nPhaseIdx);
276 }
277
278 if (vtkOutputLevel_ > 0)
279 {
280
281 if (pressureType == pw)
282 {
283 (*pressure)[eIdxGlobal] = cellData.pressure(wPhaseIdx);
284 (*potentialSecond)[eIdxGlobal] = cellData.potential(nPhaseIdx);
285 (*pressureSecond)[eIdxGlobal] = cellData.pressure(nPhaseIdx);
286 }
287
288 if (pressureType == pn)
289 {
290 (*pressure)[eIdxGlobal] = cellData.pressure(nPhaseIdx);
291 (*potentialSecond)[eIdxGlobal] = cellData.potential(wPhaseIdx);
292 (*pressureSecond)[eIdxGlobal] = cellData.pressure(wPhaseIdx);
293 }
294
295 const typename Element::Geometry& geometry = element.geometry();
296
297 // get corresponding reference element
298 const auto refElement = referenceElement(geometry);
299
300 const int numberOfFaces=refElement.size(1);
301 std::vector<Scalar> fluxW(numberOfFaces,0);
302 std::vector<Scalar> fluxNw(numberOfFaces,0);
303
304 // run through all intersections with neighbors and boundary
305 for (const auto& intersection : intersections(problem_.gridView(), element))
306 {
307 int isIndex = intersection.indexInInside();
308
309 fluxW[isIndex] += intersection.geometry().volume()
310 * (intersection.centerUnitOuterNormal() * cellData.fluxData().velocity(wPhaseIdx, isIndex));
311 fluxNw[isIndex] += intersection.geometry().volume()
312 * (intersection.centerUnitOuterNormal() * cellData.fluxData().velocity(nPhaseIdx, isIndex));
313 }
314
315 // calculate velocity on reference element as the Raviart-Thomas-0
316 // interpolant of the fluxes
317 Dune::FieldVector<Scalar, dim> refVelocity;
318 // simplices
319 if (refElement.type().isSimplex()) {
320 for (int dimIdx = 0; dimIdx < dim; dimIdx++)
321 {
322 refVelocity[dimIdx] = -fluxW[dim - 1 - dimIdx];
323 for (int fIdx = 0; fIdx < dim + 1; fIdx++)
324 {
325 refVelocity[dimIdx] += fluxW[fIdx]/(dim + 1);
326 }
327 }
328 }
329 // cubes
330 else if (refElement.type().isCube()){
331 for (int i = 0; i < dim; i++)
332 refVelocity[i] = 0.5 * (fluxW[2*i + 1] - fluxW[2*i]);
333 }
334 // 3D prism and pyramids
335 else {
336 DUNE_THROW(Dune::NotImplemented, "velocity output for prism/pyramid not implemented");
337 }
338
339 const DimVector& localPos = refElement.position(0, 0);
340
341 // get the transposed Jacobian of the element mapping
342 const JacobianTransposed jacobianT = geometry.jacobianTransposed(localPos);
343
344 // calculate the element velocity by the Piola transformation
345 DimVector elementVelocity(0);
346 jacobianT.umtv(refVelocity, elementVelocity);
347 elementVelocity /= geometry.integrationElement(localPos);
348
349 (*velocityWetting)[eIdxGlobal] = elementVelocity;
350
351 // calculate velocity on reference element as the Raviart-Thomas-0
352 // interpolant of the fluxes
353 // simplices
354 if (refElement.type().isSimplex()) {
355 for (int dimIdx = 0; dimIdx < dim; dimIdx++)
356 {
357 refVelocity[dimIdx] = -fluxNw[dim - 1 - dimIdx];
358 for (int fIdx = 0; fIdx < dim + 1; fIdx++)
359 {
360 refVelocity[dimIdx] += fluxNw[fIdx]/(dim + 1);
361 }
362 }
363 }
364 // cubes
365 else if (refElement.type().isCube()){
366 for (int i = 0; i < dim; i++)
367 refVelocity[i] = 0.5 * (fluxNw[2*i + 1] - fluxNw[2*i]);
368 }
369 // 3D prism and pyramids
370 else {
371 DUNE_THROW(Dune::NotImplemented, "velocity output for prism/pyramid not implemented");
372 }
373
374 // calculate the element velocity by the Piola transformation
375 elementVelocity = 0;
376 jacobianT.umtv(refVelocity, elementVelocity);
377 elementVelocity /= geometry.integrationElement(localPos);
378
379 (*velocityNonwetting)[eIdxGlobal] = elementVelocity;
380 }
381 }
382
383 if (pressureType == pw)
384 {
385 writer.attachCellData(*potential, "wetting potential");
386 }
387
388 if (pressureType == pn)
389 {
390 writer.attachCellData(*potential, "nonwetting potential");
391 }
392
393 if (vtkOutputLevel_ > 0)
394 {
395 if (pressureType == pw)
396 {
397 writer.attachCellData(*pressure, "wetting pressure");
398 writer.attachCellData(*pressureSecond, "nonwetting pressure");
399 writer.attachCellData(*potentialSecond, "nonwetting potential");
400 }
401
402 if (pressureType == pn)
403 {
404 writer.attachCellData(*pressure, "nonwetting pressure");
405 writer.attachCellData(*pressureSecond, "wetting pressure");
406 writer.attachCellData(*potentialSecond, "wetting potential");
407 }
408
409 writer.attachCellData(*velocityWetting, "wetting-velocity", dim);
410 writer.attachCellData(*velocityNonwetting, "nonwetting-velocity", dim);
411 }
412 }
413
422 void serializeEntity(std::ostream &outstream, const Element &element)
423 {
424 int numFaces = element.subEntities(1);
425 for (int i=0; i < numFaces; i++)
426 {
427 int fIdxGlobal = A_.faceMapper().subIndex(element, i, 1);
428 outstream << pressTrace_[fIdxGlobal][0];
429 }
430 }
431
438 void deserializeEntity(std::istream &instream, const Element &element)
439 {
440 int numFaces = element.subEntities(1);
441 for (int i=0; i < numFaces; i++)
442 {
443 int fIdxGlobal = A_.faceMapper().subIndex(element, i, 1);
444 instream >> pressTrace_[fIdxGlobal][0];
445 }
446 }
447
453 MimeticPressure2P(Problem& problem) :
454 problem_(problem),
455 A_(problem.gridView()), lstiff_(problem_, false, problem_.gridView())
456 {
457 if (pressureType != pw && pressureType != pn)
458 {
459 DUNE_THROW(Dune::NotImplemented, "Pressure type not supported!");
460 }
461 if (saturationType != sw && saturationType != sn)
462 {
463 DUNE_THROW(Dune::NotImplemented, "Saturation type not supported!");
464 }
465 if (getPropValue<TypeTag, Properties::EnableCompressibility>())
466 {
467 DUNE_THROW(Dune::NotImplemented, "Compressibility not supported!");
468 }
469
470 density_[wPhaseIdx] = 0.0;
471 density_[nPhaseIdx] = 0.0;
472 viscosity_[wPhaseIdx] = 0.0;
473 viscosity_[nPhaseIdx] = 0.0;
474
475 vtkOutputLevel_ = getParam<int>("Vtk.OutputLevel");
476 }
477
478private:
479 Problem& problem_;
480 TraceType pressTrace_; // vector of pressure traces
481 TraceType f_;
482 OperatorAssembler A_;
483 LocalStiffness lstiff_;
484
485 Scalar density_[numPhases];
486 Scalar viscosity_[numPhases];
487
488 int vtkOutputLevel_;
489};
490
492template<class TypeTag>
493void MimeticPressure2P<TypeTag>::solve()
494{
495 using Solver = GetPropType<TypeTag, Properties::LinearSolver>;
496
497 auto verboseLevelSolver = getParam<int>("LinearSolver.Verbosity", 0);
498
499 if (verboseLevelSolver)
500 std::cout << "MimeticPressure2P: solve for pressure" << std::endl;
501
502 auto solver = getSolver<Solver>(problem_);
503 solver.solve(*A_, pressTrace_, f_);
504
505 return;
506}
507
509template<class TypeTag>
511{
512 // iterate through leaf grid an evaluate c0 at cell center
513 for (const auto& element : elements(problem_.gridView()))
514 {
515 int eIdxGlobal = problem_.variables().index(element);
516
517 CellData& cellData = problem_.variables().cellData(eIdxGlobal);
518
519 const Scalar satW = cellData.saturation(wPhaseIdx);
520
521 // old material law interface is deprecated: Replace this by
522 // const auto& fluidMatrixInteraction = spatialParams.fluidMatrixInteractionAtPos(element.geometry().center());
523 // after the release of 3.3, when the deprecated interface is no longer supported
524 const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), element);
525
526 // initialize mobilities
527 const Scalar mobilityW = fluidMatrixInteraction.krw(satW) / viscosity_[wPhaseIdx];
528 const Scalar mobilityNw = fluidMatrixInteraction.krn(satW) / viscosity_[nPhaseIdx];
529
530 // initialize mobilities
531 cellData.setMobility(wPhaseIdx, mobilityW);
532 cellData.setMobility(nPhaseIdx, mobilityNw);
533
534 // initialize fractional flow functions
535 cellData.setFracFlowFunc(wPhaseIdx, mobilityW / (mobilityW + mobilityNw));
536 cellData.setFracFlowFunc(nPhaseIdx, mobilityNw / (mobilityW + mobilityNw));
537 }
538 return;
539}
540
541} // end namespace Dumux
542#endif
Helpers for deprecation.
Local stiffness matrix for the diffusion equation discretized by mimetic FD.
An assembler for the Jacobian matrix based on mimetic FD.
Definition: adapt.hh:29
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type GetProp
get the type of a property (equivalent to old macro GET_PROP(...))
Definition: propertysystem.hh:140
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property (equivalent to old macro GET_PROP_TYPE(....
Definition: propertysystem.hh:149
std::string viscosity(int phaseIdx) noexcept
I/O name of viscosity for multiphase systems.
Definition: name.hh:74
std::string pressure(int phaseIdx) noexcept
I/O name of pressure for multiphase systems.
Definition: name.hh:34
std::string density(int phaseIdx) noexcept
I/O name of density for multiphase systems.
Definition: name.hh:65
const FaceMapper & faceMapper()
Definition: croperator.hh:195
void assemble(LocalStiffness &loc, Vector &u, Vector &f)
Assembles global stiffness matrix.
Definition: croperator.hh:223
void initialize()
Initialize the CR operator assembler.
Definition: croperator.hh:112
Base class for local assemblers.
Definition: localstiffness.hh:60
Levelwise assembler.
Definition: operator.hh:47
void calculatePressure(LocalStiffness &loc, Vector &u, Problem &problem)
Definition: operator.hh:93
Mimetic method for the pressure equation.
Definition: 2p/sequential/diffusion/mimetic/pressure.hh:66
void updateVelocity()
Velocity update.
Definition: 2p/sequential/diffusion/mimetic/pressure.hh:218
void initialize(bool solveTwice=true)
Initializes the model.
Definition: 2p/sequential/diffusion/mimetic/pressure.hh:182
void addOutputVtkFields(MultiWriter &writer)
Write data file.
Definition: 2p/sequential/diffusion/mimetic/pressure.hh:243
void deserializeEntity(std::istream &instream, const Element &element)
General method for deserialization.
Definition: 2p/sequential/diffusion/mimetic/pressure.hh:438
void serializeEntity(std::ostream &outstream, const Element &element)
General method for serialization, output.
Definition: 2p/sequential/diffusion/mimetic/pressure.hh:422
void update()
Definition: 2p/sequential/diffusion/mimetic/pressure.hh:225
void updateMaterialLaws()
Constitutive functions are initialized and stored in the variables object.
Definition: 2p/sequential/diffusion/mimetic/pressure.hh:510
MimeticPressure2P(Problem &problem)
Constructs a MimeticPressure2P object.
Definition: 2p/sequential/diffusion/mimetic/pressure.hh:453
Defines the basic properties required for a mimetic method.
Finite Volume Diffusion Model.