3.2-git
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
fv2dtransportadaptive.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_FV2DTRANSPORT2P2C_ADAPTIVE_HH
25#define DUMUX_FV2DTRANSPORT2P2C_ADAPTIVE_HH
26
27#include <dune/grid/common/gridenums.hh>
28#include <dune/common/float_cmp.hh>
29
30#include <dumux/common/math.hh>
32
33#include "adaptiveproperties.hh"
34#include "fvtransport.hh"
35
36namespace Dumux {
55template<class TypeTag>
57{
61
63
65
67
68 enum
69 {
70 dim = GridView::dimension, dimWorld = GridView::dimensionworld,
71 NumPhases = getPropValue<TypeTag, Properties::NumPhases>()
72 };
73 enum
74 {
75 pw = Indices::pressureW,
76 pn = Indices::pressureN
77 };
78 enum
79 {
80 wPhaseIdx = Indices::wPhaseIdx, nPhaseIdx = Indices::nPhaseIdx,
81 wCompIdx = Indices::wPhaseIdx, nCompIdx = Indices::nPhaseIdx,
82 contiWEqIdx=Indices::contiWEqIdx, contiNEqIdx=Indices::contiNEqIdx
83 };
84
85 using IntersectionIterator = typename GridView::IntersectionIterator;
86
87 using GlobalPosition = Dune::FieldVector<Scalar, dimWorld>;
88 using DimMatrix = Dune::FieldMatrix<Scalar, dim, dim>;
89 using TransmissivityMatrix = Dune::FieldVector<Scalar,dim+1>;
90 using PhaseVector = Dune::FieldVector<Scalar, NumPhases>;
92
94 Problem& problem()
95 { return problem_; }
96
97 using LocalTimesteppingData = typename FVTransport2P2C<TypeTag>::LocalTimesteppingData;
98
99public:
100 virtual void update(const Scalar t, Scalar& dt, TransportSolutionType& updateVec, bool impes = false);
101
102 void getMpfaFlux(Dune::FieldVector<Scalar, 2>&, Dune::FieldVector<Scalar, 2>&,
103 const IntersectionIterator&, CellData&);
104
114 FV2dTransport2P2CAdaptive(Problem& problem) : FVTransport2P2C<TypeTag>(problem),
115 problem_(problem)
116 {
117 enableMPFA = getParam<bool>("GridAdapt.EnableMultiPointFluxApproximation");
118 }
119
121 {
122 }
123
124protected:
125 Problem& problem_;
126
129 static const int pressureType = getPropValue<TypeTag, Properties::PressureFormulation>();
130};
131
151template<class TypeTag>
152void FV2dTransport2P2CAdaptive<TypeTag>::update(const Scalar t, Scalar& dt, TransportSolutionType& updateVec, bool impet)
153{
154 this->impet_ = impet;
155 // initialize dt very large
156 dt = 1E100;
157 this->averagedFaces_ = 0;
158
159 // resize update vector and set to zero
160 unsigned int size_ = problem_.gridView().size(0);
161 updateVec.resize(getPropValue<TypeTag, Properties::NumComponents>());
162 updateVec[wCompIdx].resize(size_);
163 updateVec[nCompIdx].resize(size_);
164 updateVec[wCompIdx] = 0;
165 updateVec[nCompIdx] = 0;
166
167 if (this->enableLocalTimeStepping())
168 {
169 if (this->timeStepData_.size() != size_)
170 this->timeStepData_.resize(size_);
171 }
172
173 //also resize PV vector if necessary
174 if(this->totalConcentration_.size() != size_)
175 {
176 this->totalConcentration_[wCompIdx].resize(size_);
177 this->totalConcentration_[nCompIdx].resize(size_);
178 // copy data //TODO: remove this, remove PM Transport Vector!!
179 // loop through all elements
180 for (int i = 0; i< problem().gridView().size(0); i++)
181 {
182 CellData& cellDataI = problem().variables().cellData(i);
183 for(int compIdx = 0; compIdx < getPropValue<TypeTag, Properties::NumComponents>(); compIdx++)
184 {
185 this->totalConcentration_[compIdx][i]
186 = cellDataI.totalConcentration(compIdx);
187 }
188 }
189 }
190
191 // Cell which restricts time step size
192 int restrictingCell = -1;
193
194 Dune::FieldVector<Scalar, 2> entries(0.), timestepFlux(0.);
195 // compute update vector
196 for (const auto& element : elements(problem().gridView()))
197 {
198 // get cell infos
199 int globalIdxI = problem().variables().index(element);
200 CellData& cellDataI = problem().variables().cellData(globalIdxI);
201
202 // some variables for time step calculation
203 double sumfactorin = 0;
204 double sumfactorout = 0;
205
206 if (this->enableLocalTimeStepping())
207 {
208 LocalTimesteppingData& localData = this->timeStepData_[globalIdxI];
209 for (int i = 0; i < 2*dim; i++)
210 {
211 if (localData.faceTargetDt[i] < this->accumulatedDt_ + this->dtThreshold_)
212 {
213 localData.faceFluxes[i] = 0.0;
214 }
215 }
216 }
217
218 // run through all intersections with neighbors and boundary
219 const auto isEndIt = problem().gridView().iend(element);
220 for (auto isIt = problem().gridView().ibegin(element); isIt != isEndIt; ++isIt)
221 {
222 const auto& intersection = *isIt;
223
224 int indexInInside = intersection.indexInInside();
225
226 // handle interior face
227 if (intersection.neighbor())
228 {
229 if (enableMPFA && (intersection.outside().level() != element.level()))
230 getMpfaFlux(entries, timestepFlux, isIt, cellDataI);
231 else
232 this->getFlux(entries, timestepFlux, intersection, cellDataI);
233 }
234
235 // Boundary Face
236 if (intersection.boundary())
237 {
238 this->getFluxOnBoundary(entries, timestepFlux, intersection, cellDataI);
239 }
240
241 if (this->enableLocalTimeStepping())
242 {
243 LocalTimesteppingData& localData = this->timeStepData_[globalIdxI];
244
245 if (localData.faceTargetDt[indexInInside] < this->accumulatedDt_ + this->dtThreshold_)
246 {
247 localData.faceFluxes[indexInInside] += entries;
248 }
249 }
250 else
251 {
252 // add to update vector
253 updateVec[wCompIdx][globalIdxI] += entries[wCompIdx];
254 updateVec[nCompIdx][globalIdxI] += entries[nCompIdx];
255 }
256
257 // for time step calculation
258 sumfactorin += timestepFlux[0];
259 sumfactorout += timestepFlux[1];
260
261 }// end all intersections
262
263 if (this->enableLocalTimeStepping())
264 {
265 LocalTimesteppingData& localData = this->timeStepData_[globalIdxI];
266 for (int i=0; i < 2*dim; i++)
267 {
268 updateVec[wCompIdx][globalIdxI] += localData.faceFluxes[i][wCompIdx];
269 updateVec[nCompIdx][globalIdxI] += localData.faceFluxes[i][nCompIdx];
270 }
271 }
272
273 /*********** Handle source term ***************/
274 PrimaryVariables q(NAN);
275 problem().source(q, element);
276 updateVec[wCompIdx][globalIdxI] += q[contiWEqIdx];
277 updateVec[nCompIdx][globalIdxI] += q[contiNEqIdx];
278
279 // account for porosity
280 using std::max;
281 sumfactorin = max(sumfactorin,sumfactorout)
282 / problem().spatialParams().porosity(element);
283
284 //calculate time step
285 if (this->enableLocalTimeStepping())
286 {
287 this->timeStepData_[globalIdxI].dt = 1./sumfactorin;
288 if ( 1./sumfactorin < dt)
289 {
290 dt = 1./sumfactorin;
291 restrictingCell= globalIdxI;
292 }
293 }
294 else
295 {
296 if ( 1./sumfactorin < dt)
297 {
298 dt = 1./sumfactorin;
299 restrictingCell= globalIdxI;
300 }
301 }
302 } // end grid traversal
303
304#if HAVE_MPI
305 // communicate updated values
307 using ElementMapper = typename SolutionTypes::ElementMapper;
309 for (int i = 0; i < updateVec.size(); i++)
310 {
311 DataHandle dataHandle(problem_.variables().elementMapper(), updateVec[i]);
312 problem_.gridView().template communicate<DataHandle>(dataHandle,
313 Dune::InteriorBorder_All_Interface,
314 Dune::ForwardCommunication);
315 }
316 dt = problem_.gridView().comm().min(dt);
317#endif
318
319 if(impet)
320 {
321 Dune::dinfo << "Timestep restricted by CellIdx " << restrictingCell << " leads to dt = "
322 <<dt * getParam<Scalar>("Impet.CFLFactor")<< std::endl;
323 if(this->averagedFaces_ != 0)
324 Dune::dinfo << " Averageing done for " << this->averagedFaces_ << " faces. "<< std::endl;
325 }
326 return;
327}
328
349template<class TypeTag>
350void FV2dTransport2P2CAdaptive<TypeTag>::getMpfaFlux(Dune::FieldVector<Scalar, 2>& fluxEntries, Dune::FieldVector<Scalar, 2>& timestepFlux,
351 const IntersectionIterator& intersectionIterator, CellData& cellDataI)
352{
353 fluxEntries = 0.;
354 timestepFlux = 0.;
355 // cell information
356 auto elementI = intersectionIterator->inside();
357 int globalIdxI = problem().variables().index(elementI);
358
359 // get position
360 const GlobalPosition globalPos = elementI.geometry().center();
361 const GlobalPosition& gravity_ = problem().gravity();
362 // cell volume, assume linear map here
363 Scalar volume = elementI.geometry().volume();
364
365 // get values of cell I
366 Scalar pressI = problem().pressureModel().pressure(globalIdxI);
367 Scalar pcI = cellDataI.capillaryPressure();
368
369 PhaseVector SmobI(0.);
370 using std::max;
371 SmobI[wPhaseIdx] = max((cellDataI.saturation(wPhaseIdx)
372 - problem().spatialParams().materialLawParams(elementI).swr())
373 , 1e-2);
374 SmobI[nPhaseIdx] = max((cellDataI.saturation(nPhaseIdx)
375 - problem().spatialParams().materialLawParams(elementI).snr())
376 , 1e-2);
377
378 Scalar densityWI (0.), densityNWI(0.);
379 densityWI= cellDataI.density(wPhaseIdx);
380 densityNWI = cellDataI.density(nPhaseIdx);
381
382 PhaseVector potential(0.);
383
384 // access neighbor
385 auto neighbor = intersectionIterator->outside();
386 int globalIdxJ = problem().variables().index(neighbor);
387 CellData& cellDataJ = problem().variables().cellData(globalIdxJ);
388
389 // neighbor cell center in global coordinates
390 const GlobalPosition& globalPosNeighbor = neighbor.geometry().center();
391
392 // distance vector between barycenters
393 GlobalPosition distVec = globalPosNeighbor - globalPos;
394 // compute distance between cell centers
395 Scalar dist = distVec.two_norm();
396
397 GlobalPosition unitDistVec(distVec);
398 unitDistVec /= dist;
399
400 // phase densities in neighbor
401 Scalar densityWJ (0.), densityNWJ(0.);
402 densityWJ = cellDataJ.density(wPhaseIdx);
403 densityNWJ = cellDataJ.density(nPhaseIdx);
404
405 // average phase densities with central weighting
406 double densityW_mean = (densityWI + densityWJ) * 0.5;
407 double densityNW_mean = (densityNWI + densityNWJ) * 0.5;
408
409 double pressJ = problem().pressureModel().pressure(globalIdxJ);
410 Scalar pcJ = cellDataJ.capillaryPressure();
411
412 // determine potentials for upwind
414 GlobalPosition globalPos3(0.);
415 int globalIdx3=-1;
416 TransmissivityMatrix T(0.);
417 IntersectionIterator additionalIsIt = intersectionIterator;
418 TransmissivityMatrix additionalT(0.);
419
420 int halfedgesStored
421 = problem().variables().getMpfaData(*intersectionIterator, additionalIsIt, T, additionalT,
422 globalPos3, globalIdx3);
423 if (halfedgesStored == 0)
424 halfedgesStored = problem().pressureModel().computeTransmissibilities(intersectionIterator,additionalIsIt,
425 T,additionalT, globalPos3, globalIdx3 );
426
427 // acess cell 3 and prepare mpfa
428 Scalar press3 = problem().pressureModel().pressure(globalIdx3);
429 CellData& cellData3 = problem().variables().cellData(globalIdx3);
430 Scalar pc3 = cellData3.capillaryPressure();
431 Scalar temp1 = globalPos * gravity_;
432 Scalar temp2 = globalPosNeighbor * gravity_;
433 Scalar temp3 = globalPos3 * gravity_;
434 if(pressureType==pw)
435 {
436 potential[wPhaseIdx] += (pressI-temp1*densityW_mean) * T[2]
437 +(pressJ-temp2*densityW_mean) * T[0]
438 +(press3- temp3*densityW_mean) * T[1];
439 potential[nPhaseIdx] += (pressI+pcI-temp1*densityNW_mean) * T[2]
440 +(pressJ+pcJ-temp2*densityNW_mean) * T[0]
441 +(press3+pc3- temp3*densityNW_mean) * T[1];
442 // second half edge, if there is one
443 if(halfedgesStored == 2)
444 {
445 int AdditionalIdx = problem().variables().index(additionalIsIt->outside());
446 CellData& cellDataAdditional = problem().variables().cellData(AdditionalIdx);
447 potential[wPhaseIdx] += (pressI-temp1*densityW_mean) * additionalT[2]
448 +(pressJ-temp2*densityW_mean) * additionalT[0]
449 +(problem().pressureModel().pressure(AdditionalIdx)
450 -(additionalIsIt->outside().geometry().center()*gravity_*densityW_mean)
451 ) * additionalT[1];
452 potential[nPhaseIdx] += (pressI+pcI-temp1*densityNW_mean) * additionalT[2]
453 +(pressJ+pcJ-temp2*densityNW_mean) * additionalT[0]
454 +(problem().pressureModel().pressure(AdditionalIdx)
455 + cellDataAdditional.capillaryPressure()
456 -(additionalIsIt->outside().geometry().center()*gravity_*densityNW_mean)
457 ) * additionalT[1];
458 }
459 }
460 else if(pressureType==pn)
461 {
462 potential[wPhaseIdx] += (pressI-pcI-temp1*densityW_mean) * T[2]
463 + (pressJ-pcJ-temp2*densityW_mean) * T[0]
464 + (press3-pc3- temp3*densityW_mean) * T[1];
465 potential[nPhaseIdx] += (pressI-temp1*densityNW_mean) * T[2]
466 + (pressJ-temp2*densityNW_mean) * T[0]
467 + (press3-temp3*densityNW_mean) * T[1];
468 // second half edge, if there is one
469 if(halfedgesStored == 2)
470 {
471 int AdditionalIdx = problem().variables().index(additionalIsIt->outside());
472 CellData& cellDataAdditional = problem().variables().cellData(AdditionalIdx);
473
474 potential[wPhaseIdx] += (pressI-pcI-temp1*densityW_mean) * additionalT[2]
475 +(pressJ-pcJ-temp2*densityW_mean) * additionalT[0]
476 +(problem().pressureModel().pressure(AdditionalIdx)
477 - cellDataAdditional.capillaryPressure()
478 -(additionalIsIt->outside().geometry().center()*gravity_*densityW_mean)
479 ) * additionalT[1];
480 potential[nPhaseIdx] += (pressI-temp1*densityNW_mean) * additionalT[2]
481 +(pressJ-temp2*densityNW_mean) * additionalT[0]
482 +(problem().pressureModel().pressure(AdditionalIdx)
483 -(additionalIsIt->outside().geometry().center()*gravity_*densityNW_mean))
484 * additionalT[1];
485 }
486 }
487 //end of mpfa specific stuff
488
489 // determine upwinding direction, perform upwinding if possible
490 Dune::FieldVector<bool, NumPhases> doUpwinding(true);
491 PhaseVector lambda(0.);
492 for(int phaseIdx = 0; phaseIdx < NumPhases; phaseIdx++)
493 {
494 int contiEqIdx = 0;
495 if(phaseIdx == wPhaseIdx)
496 contiEqIdx = contiWEqIdx;
497 else
498 contiEqIdx = contiNEqIdx;
499
500 if(!this->impet_ or !this->restrictFluxInTransport_) // perform a strict uwpind scheme
501 {
502 if(potential[phaseIdx] > 0.)
503 {
504 lambda[phaseIdx] = cellDataI.mobility(phaseIdx);
505 if(elementI.level()>neighbor.level())
506 cellDataI.setUpwindCell(intersectionIterator->indexInInside(), contiEqIdx, true);
507 }
508 else if(potential[phaseIdx] < 0.)
509 {
510 lambda[phaseIdx] = cellDataJ.mobility(phaseIdx);
511 if(elementI.level()>neighbor.level())
512 cellDataI.setUpwindCell(intersectionIterator->indexInInside(), contiEqIdx, false);
513 }
514 else
515 {
516 doUpwinding[phaseIdx] = false;
517 if(elementI.level()>neighbor.level())
518 cellDataI.setUpwindCell(intersectionIterator->indexInInside(), contiEqIdx, false);
519 else
520 cellDataJ.setUpwindCell(intersectionIterator->indexInOutside(), contiEqIdx, false);
521 }
522 }
523 else // Transport after PE with check on flow direction
524 {
525 bool cellIwasUpwindCell;
526 //get the information from smaller (higher level) cell, as its IS is unique
527 if(elementI.level()>neighbor.level())
528 cellIwasUpwindCell = cellDataI.isUpwindCell(intersectionIterator->indexInInside(), contiEqIdx);
529 else // reverse neighbors information gathered
530 cellIwasUpwindCell = !cellDataJ.isUpwindCell(intersectionIterator->indexInOutside(), contiEqIdx);
531
532 if (potential[phaseIdx] > 0. && cellIwasUpwindCell)
533 lambda[phaseIdx] = cellDataI.mobility(phaseIdx);
534 else if (potential[phaseIdx] < 0. && !cellIwasUpwindCell)
535 lambda[phaseIdx] = cellDataJ.mobility(phaseIdx);
536 // potential direction does not coincide with that of P.E.
537 else if(this->restrictFluxInTransport_ == 2) // perform central averaging for all direction changes
538 doUpwinding[phaseIdx] = false;
539 else // i.e. restrictFluxInTransport == 1
540 {
541 //check if harmonic weighting is necessary
542 // check if outflow induce neglected (i.e. mob=0) phase flux
543 if (potential[phaseIdx] > 0. && Dune::FloatCmp::ne<Scalar, Dune::FloatCmp::absolute>(cellDataJ.mobility(phaseIdx), 0.0, 1.0e-30))
544 lambda[phaseIdx] = cellDataI.mobility(phaseIdx);
545 // check if inflow induce neglected phase flux
546 else if (potential[phaseIdx] < 0. && Dune::FloatCmp::ne<Scalar, Dune::FloatCmp::absolute>(cellDataI.mobility(phaseIdx), 0.0, 1.0e-30))
547 lambda[phaseIdx] = cellDataJ.mobility(phaseIdx);
548 else
549 doUpwinding[phaseIdx] = false;
550 }
551
552 // do not perform upwinding if so desired
553 if(!doUpwinding[phaseIdx])
554 {
555 //a) no flux if there wont be any flux regardless how to average/upwind
556 if(cellDataI.mobility(phaseIdx)+cellDataJ.mobility(phaseIdx)==0.)
557 {
558 potential[phaseIdx] = 0;
559 continue;
560 }
561
562 //b) perform harmonic averaging
563 fluxEntries[wCompIdx] -= potential[phaseIdx] / volume
564 * harmonicMean(cellDataI.massFraction(phaseIdx, wCompIdx) * cellDataI.mobility(phaseIdx) * cellDataI.density(phaseIdx),
565 cellDataJ.massFraction(phaseIdx, wCompIdx) * cellDataJ.mobility(phaseIdx) * cellDataJ.density(phaseIdx));
566 fluxEntries[nCompIdx] -= potential[phaseIdx] / volume
567 * harmonicMean(cellDataI.massFraction(phaseIdx, nCompIdx) * cellDataI.mobility(phaseIdx) * cellDataI.density(phaseIdx),
568 cellDataJ.massFraction(phaseIdx, nCompIdx) * cellDataJ.mobility(phaseIdx) * cellDataJ.density(phaseIdx));
569 // c) timestep control
570 // for timestep control : influx
571 using std::max;
572 timestepFlux[0] += max(0.,
573 - potential[phaseIdx] / volume
574 * harmonicMean(cellDataI.mobility(phaseIdx),cellDataJ.mobility(phaseIdx)));
575 // outflux
576 timestepFlux[1] += max(0.,
577 potential[phaseIdx] / volume
578 * harmonicMean(cellDataI.mobility(phaseIdx),cellDataJ.mobility(phaseIdx))/SmobI[phaseIdx]);
579
580 //d) output (only for one side)
581 this->averagedFaces_++;
582 #if DUNE_MINIMAL_DEBUG_LEVEL < 3
583 // verbose (only for one side)
584 if(globalIdxI > globalIdxJ)
585 Dune::dinfo << "harmonicMean flux of phase" << phaseIdx <<" used from cell" << globalIdxI<< " into " << globalIdxJ
586 << " ; TE upwind I = "<< cellDataI.isUpwindCell(intersectionIterator->indexInInside(), contiEqIdx)
587 << " but pot = "<< potential[phaseIdx] << " \n";
588 #endif
589
590 //e) stop further standard calculations
591 potential[phaseIdx] = 0;
592 }
593 }
594 }
595
596 // calculate and standardized velocity
597 using std::max;
598 double velocityJIw = max((-lambda[wPhaseIdx] * potential[wPhaseIdx]) / volume, 0.0);
599 double velocityIJw = max(( lambda[wPhaseIdx] * potential[wPhaseIdx]) / volume, 0.0);
600 double velocityJIn = max((-lambda[nPhaseIdx] * potential[nPhaseIdx]) / volume, 0.0);
601 double velocityIJn = max(( lambda[nPhaseIdx] * potential[nPhaseIdx]) / volume, 0.0);
602
603 // for timestep control
604 timestepFlux[0] += velocityJIw + velocityJIn;
605
606 double foutw = velocityIJw/SmobI[wPhaseIdx];
607 double foutn = velocityIJn/SmobI[nPhaseIdx];
608 using std::isnan;
609 using std::isinf;
610 if (isnan(foutw) || isinf(foutw) || foutw < 0) foutw = 0;
611 if (isnan(foutn) || isinf(foutn) || foutn < 0) foutn = 0;
612 timestepFlux[1] += foutw + foutn;
613
614 fluxEntries[wCompIdx] +=
615 velocityJIw * cellDataJ.massFraction(wPhaseIdx, wCompIdx) * densityWJ
616 - velocityIJw * cellDataI.massFraction(wPhaseIdx, wCompIdx) * densityWI
617 + velocityJIn * cellDataJ.massFraction(nPhaseIdx, wCompIdx) * densityNWJ
618 - velocityIJn * cellDataI.massFraction(nPhaseIdx, wCompIdx) * densityNWI;
619 fluxEntries[nCompIdx] +=
620 velocityJIw * cellDataJ.massFraction(wPhaseIdx, nCompIdx) * densityWJ
621 - velocityIJw * cellDataI.massFraction(wPhaseIdx, nCompIdx) * densityWI
622 + velocityJIn * cellDataJ.massFraction(nPhaseIdx, nCompIdx) * densityNWJ
623 - velocityIJn * cellDataI.massFraction(nPhaseIdx, nCompIdx) * densityNWI;
624 return;
625}
626
627} // end namespace Dumux
628#endif
Contains a class to exchange entries of a vector.
Defines the properties required for the adaptive sequential 2p2c models.
Finite volume discretization of the component transport equation.
Define some often used mathematical functions.
constexpr Scalar harmonicMean(Scalar x, Scalar y, Scalar wx=1.0, Scalar wy=1.0) noexcept
Calculate the (weighted) harmonic mean of two scalar values.
Definition: math.hh:68
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
A data handle class to exchange entries of a vector.
Definition: vectorcommdatahandle.hh:79
Compositional Transport step in a Finite Volume discretization for a adaptive 2D-grid.
Definition: fv2dtransportadaptive.hh:57
virtual ~FV2dTransport2P2CAdaptive()
Definition: fv2dtransportadaptive.hh:120
FV2dTransport2P2CAdaptive(Problem &problem)
Constructs a FV2dTransport2P2CAdaptive object.
Definition: fv2dtransportadaptive.hh:114
static const int pressureType
gives kind of pressure used ( , , )
Definition: fv2dtransportadaptive.hh:129
Problem & problem_
Definition: fv2dtransportadaptive.hh:125
virtual void update(const Scalar t, Scalar &dt, TransportSolutionType &updateVec, bool impes=false)
Calculate the update vector and determine timestep size.
Definition: fv2dtransportadaptive.hh:152
bool enableMPFA
Definition: fv2dtransportadaptive.hh:127
void getMpfaFlux(Dune::FieldVector< Scalar, 2 > &, Dune::FieldVector< Scalar, 2 > &, const IntersectionIterator &, CellData &)
Compute flux over an irregular interface using a mpfa method.
Definition: fv2dtransportadaptive.hh:350
Compositional transport step in a Finite Volume discretization.
Definition: fvtransport.hh:60
Definition: fvtransport.hh:113