3.1-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{
58 using GridView = typename GET_PROP_TYPE(TypeTag, GridView);
59 using Scalar = typename GET_PROP_TYPE(TypeTag, Scalar);
60 using Problem = typename GET_PROP_TYPE(TypeTag, Problem);
61
62 using Indices = typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices;
63
64 using CellData = typename GET_PROP_TYPE(TypeTag, CellData);
65
66 using TransportSolutionType = typename GET_PROP_TYPE(TypeTag, TransportSolutionType);
67
68 enum
69 {
70 dim = GridView::dimension, dimWorld = GridView::dimensionworld,
71 NumPhases = GET_PROP_VALUE(TypeTag, 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>;
91 using PrimaryVariables = typename GET_PROP_TYPE(TypeTag, PrimaryVariables);
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 = GET_PROP_VALUE(TypeTag, 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(GET_PROP_VALUE(TypeTag, 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 < GET_PROP_VALUE(TypeTag, 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
306 using SolutionTypes = typename GET_PROP(TypeTag, SolutionTypes);
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 DimMatrix K_I(problem().spatialParams().intrinsicPermeability(elementI));
369
370 PhaseVector SmobI(0.);
371 using std::max;
372 SmobI[wPhaseIdx] = max((cellDataI.saturation(wPhaseIdx)
373 - problem().spatialParams().materialLawParams(elementI).swr())
374 , 1e-2);
375 SmobI[nPhaseIdx] = max((cellDataI.saturation(nPhaseIdx)
376 - problem().spatialParams().materialLawParams(elementI).snr())
377 , 1e-2);
378
379 Scalar densityWI (0.), densityNWI(0.);
380 densityWI= cellDataI.density(wPhaseIdx);
381 densityNWI = cellDataI.density(nPhaseIdx);
382
383 PhaseVector potential(0.);
384
385 // access neighbor
386 auto neighbor = intersectionIterator->outside();
387 int globalIdxJ = problem().variables().index(neighbor);
388 CellData& cellDataJ = problem().variables().cellData(globalIdxJ);
389
390 // neighbor cell center in global coordinates
391 const GlobalPosition& globalPosNeighbor = neighbor.geometry().center();
392
393 // distance vector between barycenters
394 GlobalPosition distVec = globalPosNeighbor - globalPos;
395 // compute distance between cell centers
396 Scalar dist = distVec.two_norm();
397
398 GlobalPosition unitDistVec(distVec);
399 unitDistVec /= dist;
400
401 // phase densities in neighbor
402 Scalar densityWJ (0.), densityNWJ(0.);
403 densityWJ = cellDataJ.density(wPhaseIdx);
404 densityNWJ = cellDataJ.density(nPhaseIdx);
405
406 // average phase densities with central weighting
407 double densityW_mean = (densityWI + densityWJ) * 0.5;
408 double densityNW_mean = (densityNWI + densityNWJ) * 0.5;
409
410 double pressJ = problem().pressureModel().pressure(globalIdxJ);
411 Scalar pcJ = cellDataJ.capillaryPressure();
412
413 // determine potentials for upwind
415 GlobalPosition globalPos3(0.);
416 int globalIdx3=-1;
417 TransmissivityMatrix T(0.);
418 IntersectionIterator additionalIsIt = intersectionIterator;
419 TransmissivityMatrix additionalT(0.);
420
421 int halfedgesStored
422 = problem().variables().getMpfaData(*intersectionIterator, additionalIsIt, T, additionalT,
423 globalPos3, globalIdx3);
424 if (halfedgesStored == 0)
425 halfedgesStored = problem().pressureModel().computeTransmissibilities(intersectionIterator,additionalIsIt,
426 T,additionalT, globalPos3, globalIdx3 );
427
428 // acess cell 3 and prepare mpfa
429 Scalar press3 = problem().pressureModel().pressure(globalIdx3);
430 CellData& cellData3 = problem().variables().cellData(globalIdx3);
431 Scalar pc3 = cellData3.capillaryPressure();
432 Scalar temp1 = globalPos * gravity_;
433 Scalar temp2 = globalPosNeighbor * gravity_;
434 Scalar temp3 = globalPos3 * gravity_;
435 if(pressureType==pw)
436 {
437 potential[wPhaseIdx] += (pressI-temp1*densityW_mean) * T[2]
438 +(pressJ-temp2*densityW_mean) * T[0]
439 +(press3- temp3*densityW_mean) * T[1];
440 potential[nPhaseIdx] += (pressI+pcI-temp1*densityNW_mean) * T[2]
441 +(pressJ+pcJ-temp2*densityNW_mean) * T[0]
442 +(press3+pc3- temp3*densityNW_mean) * T[1];
443 // second half edge, if there is one
444 if(halfedgesStored == 2)
445 {
446 int AdditionalIdx = problem().variables().index(additionalIsIt->outside());
447 CellData& cellDataAdditional = problem().variables().cellData(AdditionalIdx);
448 potential[wPhaseIdx] += (pressI-temp1*densityW_mean) * additionalT[2]
449 +(pressJ-temp2*densityW_mean) * additionalT[0]
450 +(problem().pressureModel().pressure(AdditionalIdx)
451 -(additionalIsIt->outside().geometry().center()*gravity_*densityW_mean)
452 ) * additionalT[1];
453 potential[nPhaseIdx] += (pressI+pcI-temp1*densityNW_mean) * additionalT[2]
454 +(pressJ+pcJ-temp2*densityNW_mean) * additionalT[0]
455 +(problem().pressureModel().pressure(AdditionalIdx)
456 + cellDataAdditional.capillaryPressure()
457 -(additionalIsIt->outside().geometry().center()*gravity_*densityNW_mean)
458 ) * additionalT[1];
459 }
460 }
461 else if(pressureType==pn)
462 {
463 potential[wPhaseIdx] += (pressI-pcI-temp1*densityW_mean) * T[2]
464 + (pressJ-pcJ-temp2*densityW_mean) * T[0]
465 + (press3-pc3- temp3*densityW_mean) * T[1];
466 potential[nPhaseIdx] += (pressI-temp1*densityNW_mean) * T[2]
467 + (pressJ-temp2*densityNW_mean) * T[0]
468 + (press3-temp3*densityNW_mean) * T[1];
469 // second half edge, if there is one
470 if(halfedgesStored == 2)
471 {
472 int AdditionalIdx = problem().variables().index(additionalIsIt->outside());
473 CellData& cellDataAdditional = problem().variables().cellData(AdditionalIdx);
474
475 potential[wPhaseIdx] += (pressI-pcI-temp1*densityW_mean) * additionalT[2]
476 +(pressJ-pcJ-temp2*densityW_mean) * additionalT[0]
477 +(problem().pressureModel().pressure(AdditionalIdx)
478 - cellDataAdditional.capillaryPressure()
479 -(additionalIsIt->outside().geometry().center()*gravity_*densityW_mean)
480 ) * additionalT[1];
481 potential[nPhaseIdx] += (pressI-temp1*densityNW_mean) * additionalT[2]
482 +(pressJ-temp2*densityNW_mean) * additionalT[0]
483 +(problem().pressureModel().pressure(AdditionalIdx)
484 -(additionalIsIt->outside().geometry().center()*gravity_*densityNW_mean))
485 * additionalT[1];
486 }
487 }
488 //end of mpfa specific stuff
489
490 // determine upwinding direction, perform upwinding if possible
491 Dune::FieldVector<bool, NumPhases> doUpwinding(true);
492 PhaseVector lambda(0.);
493 for(int phaseIdx = 0; phaseIdx < NumPhases; phaseIdx++)
494 {
495 int contiEqIdx = 0;
496 if(phaseIdx == wPhaseIdx)
497 contiEqIdx = contiWEqIdx;
498 else
499 contiEqIdx = contiNEqIdx;
500
501 if(!this->impet_ or !this->restrictFluxInTransport_) // perform a strict uwpind scheme
502 {
503 if(potential[phaseIdx] > 0.)
504 {
505 lambda[phaseIdx] = cellDataI.mobility(phaseIdx);
506 if(elementI.level()>neighbor.level())
507 cellDataI.setUpwindCell(intersectionIterator->indexInInside(), contiEqIdx, true);
508 }
509 else if(potential[phaseIdx] < 0.)
510 {
511 lambda[phaseIdx] = cellDataJ.mobility(phaseIdx);
512 if(elementI.level()>neighbor.level())
513 cellDataI.setUpwindCell(intersectionIterator->indexInInside(), contiEqIdx, false);
514 }
515 else
516 {
517 doUpwinding[phaseIdx] = false;
518 if(elementI.level()>neighbor.level())
519 cellDataI.setUpwindCell(intersectionIterator->indexInInside(), contiEqIdx, false);
520 else
521 cellDataJ.setUpwindCell(intersectionIterator->indexInOutside(), contiEqIdx, false);
522 }
523 }
524 else // Transport after PE with check on flow direction
525 {
526 bool cellIwasUpwindCell;
527 //get the information from smaller (higher level) cell, as its IS is unique
528 if(elementI.level()>neighbor.level())
529 cellIwasUpwindCell = cellDataI.isUpwindCell(intersectionIterator->indexInInside(), contiEqIdx);
530 else // reverse neighbors information gathered
531 cellIwasUpwindCell = !cellDataJ.isUpwindCell(intersectionIterator->indexInOutside(), contiEqIdx);
532
533 if (potential[phaseIdx] > 0. && cellIwasUpwindCell)
534 lambda[phaseIdx] = cellDataI.mobility(phaseIdx);
535 else if (potential[phaseIdx] < 0. && !cellIwasUpwindCell)
536 lambda[phaseIdx] = cellDataJ.mobility(phaseIdx);
537 // potential direction does not coincide with that of P.E.
538 else if(this->restrictFluxInTransport_ == 2) // perform central averaging for all direction changes
539 doUpwinding[phaseIdx] = false;
540 else // i.e. restrictFluxInTransport == 1
541 {
542 //check if harmonic weighting is necessary
543 // check if outflow induce neglected (i.e. mob=0) phase flux
544 if (potential[phaseIdx] > 0. && Dune::FloatCmp::ne<Scalar, Dune::FloatCmp::absolute>(cellDataJ.mobility(phaseIdx), 0.0, 1.0e-30))
545 lambda[phaseIdx] = cellDataI.mobility(phaseIdx);
546 // check if inflow induce neglected phase flux
547 else if (potential[phaseIdx] < 0. && Dune::FloatCmp::ne<Scalar, Dune::FloatCmp::absolute>(cellDataI.mobility(phaseIdx), 0.0, 1.0e-30))
548 lambda[phaseIdx] = cellDataJ.mobility(phaseIdx);
549 else
550 doUpwinding[phaseIdx] = false;
551 }
552
553 // do not perform upwinding if so desired
554 if(!doUpwinding[phaseIdx])
555 {
556 //a) no flux if there wont be any flux regardless how to average/upwind
557 if(cellDataI.mobility(phaseIdx)+cellDataJ.mobility(phaseIdx)==0.)
558 {
559 potential[phaseIdx] = 0;
560 continue;
561 }
562
563 //b) perform harmonic averaging
564 fluxEntries[wCompIdx] -= potential[phaseIdx] / volume
565 * harmonicMean(cellDataI.massFraction(phaseIdx, wCompIdx) * cellDataI.mobility(phaseIdx) * cellDataI.density(phaseIdx),
566 cellDataJ.massFraction(phaseIdx, wCompIdx) * cellDataJ.mobility(phaseIdx) * cellDataJ.density(phaseIdx));
567 fluxEntries[nCompIdx] -= potential[phaseIdx] / volume
568 * harmonicMean(cellDataI.massFraction(phaseIdx, nCompIdx) * cellDataI.mobility(phaseIdx) * cellDataI.density(phaseIdx),
569 cellDataJ.massFraction(phaseIdx, nCompIdx) * cellDataJ.mobility(phaseIdx) * cellDataJ.density(phaseIdx));
570 // c) timestep control
571 // for timestep control : influx
572 using std::max;
573 timestepFlux[0] += max(0.,
574 - potential[phaseIdx] / volume
575 * harmonicMean(cellDataI.mobility(phaseIdx),cellDataJ.mobility(phaseIdx)));
576 // outflux
577 timestepFlux[1] += max(0.,
578 potential[phaseIdx] / volume
579 * harmonicMean(cellDataI.mobility(phaseIdx),cellDataJ.mobility(phaseIdx))/SmobI[phaseIdx]);
580
581 //d) output (only for one side)
582 this->averagedFaces_++;
583 #if DUNE_MINIMAL_DEBUG_LEVEL < 3
584 // verbose (only for one side)
585 if(globalIdxI > globalIdxJ)
586 Dune::dinfo << "harmonicMean flux of phase" << phaseIdx <<" used from cell" << globalIdxI<< " into " << globalIdxJ
587 << " ; TE upwind I = "<< cellDataI.isUpwindCell(intersectionIterator->indexInInside(), contiEqIdx)
588 << " but pot = "<< potential[phaseIdx] << " \n";
589 #endif
590
591 //e) stop further standard calculations
592 potential[phaseIdx] = 0;
593 }
594 }
595 }
596
597 // calculate and standardized velocity
598 using std::max;
599 double velocityJIw = max((-lambda[wPhaseIdx] * potential[wPhaseIdx]) / volume, 0.0);
600 double velocityIJw = max(( lambda[wPhaseIdx] * potential[wPhaseIdx]) / volume, 0.0);
601 double velocityJIn = max((-lambda[nPhaseIdx] * potential[nPhaseIdx]) / volume, 0.0);
602 double velocityIJn = max(( lambda[nPhaseIdx] * potential[nPhaseIdx]) / volume, 0.0);
603
604 // for timestep control
605 timestepFlux[0] += velocityJIw + velocityJIn;
606
607 double foutw = velocityIJw/SmobI[wPhaseIdx];
608 double foutn = velocityIJn/SmobI[nPhaseIdx];
609 using std::isnan;
610 using std::isinf;
611 if (isnan(foutw) || isinf(foutw) || foutw < 0) foutw = 0;
612 if (isnan(foutn) || isinf(foutn) || foutn < 0) foutn = 0;
613 timestepFlux[1] += foutw + foutn;
614
615 fluxEntries[wCompIdx] +=
616 velocityJIw * cellDataJ.massFraction(wPhaseIdx, wCompIdx) * densityWJ
617 - velocityIJw * cellDataI.massFraction(wPhaseIdx, wCompIdx) * densityWI
618 + velocityJIn * cellDataJ.massFraction(nPhaseIdx, wCompIdx) * densityNWJ
619 - velocityIJn * cellDataI.massFraction(nPhaseIdx, wCompIdx) * densityNWI;
620 fluxEntries[nCompIdx] +=
621 velocityJIw * cellDataJ.massFraction(wPhaseIdx, nCompIdx) * densityWJ
622 - velocityIJw * cellDataI.massFraction(wPhaseIdx, nCompIdx) * densityWI
623 + velocityJIn * cellDataJ.massFraction(nPhaseIdx, nCompIdx) * densityNWJ
624 - velocityIJn * cellDataI.massFraction(nPhaseIdx, nCompIdx) * densityNWI;
625 return;
626}
627
628} // end namespace Dumux
629#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
Define some often used mathematical functions.
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.
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
make the local view function available whenever we use the grid geometry
Definition: adapt.hh:29
Property tag NumComponents
Number of components in the system.
Definition: porousmediumflow/sequential/properties.hh:70
Property tag NumPhases
Number of phases in the system.
Definition: porousmediumflow/sequential/properties.hh:69
Property tag SolutionTypes
Definition: porousmediumflow/sequential/properties.hh:58
A data handle class to exchange entries of a vector.
Definition: vectorexchange.hh:40
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