24#ifndef DUMUX_FVPRESSURECOMPOSITIONAL_HH
25#define DUMUX_FVPRESSURECOMPOSITIONAL_HH
28#include <dune/common/float_cmp.hh>
85 dim = GridView::dimension, dimWorld = GridView::dimensionworld
89 pw = Indices::pressureW,
90 pn = Indices::pressureN
94 wPhaseIdx = Indices::wPhaseIdx, nPhaseIdx = Indices::nPhaseIdx,
95 wCompIdx = Indices::wCompIdx, nCompIdx = Indices::nCompIdx,
96 contiWEqIdx = Indices::contiWEqIdx, contiNEqIdx = Indices::contiNEqIdx
100 numPhases = getPropValue<TypeTag, Properties::NumPhases>(),
101 numComponents = getPropValue<TypeTag, Properties::NumComponents>()
105 using Element =
typename GridView::Traits::template Codim<0>::Entity;
108 using GlobalPosition = Dune::FieldVector<Scalar, dimWorld>;
109 using PhaseVector = Dune::FieldVector<Scalar, numPhases>;
110 using ComponentVector = Dune::FieldVector<Scalar, numComponents>;
131 Scalar dt_estimate = 0.;
132 Dune::dinfo <<
"secant guess"<< std::endl;
138 if(Dune::FloatCmp::eq<Scalar>(
problem_.timeManager().time(),
problem_.timeManager().episodeStartTime())
139 &&
problem_.timeManager().episodeIndex() > 1)
140 problem_.timeManager().setTimeStepSize(dt_estimate*getParam<Scalar>(
"Impet.CFLFactor"));
144 problem_.pressureModel().assemble(
false); Dune::dinfo <<
"pressure calculation"<< std::endl;
168 template<
class MultiWriter>
172 int size =
problem_.gridView().size(0);
173 ScalarSolutionType *pressureW = writer.allocateManagedBuffer(size);
174 ScalarSolutionType *pressureN = writer.allocateManagedBuffer(size);
175 ScalarSolutionType *totalConcentration1 = writer.allocateManagedBuffer (size);
176 ScalarSolutionType *totalConcentration2 = writer.allocateManagedBuffer (size);
177 ScalarSolutionType *pc = writer.allocateManagedBuffer(size);
178 ScalarSolutionType *saturationW = writer.allocateManagedBuffer(size);
179 ScalarSolutionType *densityWetting = writer.allocateManagedBuffer(size);
180 ScalarSolutionType *densityNonwetting = writer.allocateManagedBuffer(size);
181 ScalarSolutionType *mobilityW = writer.allocateManagedBuffer (size);
182 ScalarSolutionType *mobilityNW = writer.allocateManagedBuffer (size);
183 ScalarSolutionType *massfraction1W = writer.allocateManagedBuffer (size);
184 ScalarSolutionType *massfraction1NW = writer.allocateManagedBuffer (size);
186 ScalarSolutionType *volErr = writer.allocateManagedBuffer (size);
189 for (
int i = 0; i < size; i++)
192 CellData& cellData =
problem_.variables().cellData(i);
193 (*pressureW)[i] = cellData.pressure(wPhaseIdx);
194 (*pressureN)[i] = cellData.pressure(nPhaseIdx);
195 (*totalConcentration1)[i] = cellData.massConcentration(wCompIdx);
196 (*totalConcentration2)[i] = cellData.massConcentration(nCompIdx);
197 (*saturationW)[i] = cellData.saturation(wPhaseIdx);
201 (*pc)[i] = cellData.capillaryPressure();
202 (*densityWetting)[i] = cellData.density(wPhaseIdx);
203 (*densityNonwetting)[i] = cellData.density(nPhaseIdx);
204 (*mobilityW)[i] = cellData.mobility(wPhaseIdx);
205 (*mobilityNW)[i] = cellData.mobility(nPhaseIdx);
206 (*massfraction1W)[i] = cellData.massFraction(wPhaseIdx,wCompIdx);
207 (*massfraction1NW)[i] = cellData.massFraction(nPhaseIdx,wCompIdx);
208 (*volErr)[i] = cellData.volumeError();
211 writer.attachCellData(*pressureW,
"wetting pressure");
212 writer.attachCellData(*pressureN,
"nonwetting pressure");
213 writer.attachCellData(*saturationW,
"wetting saturation");
214 writer.attachCellData(*totalConcentration1,
"C^w from cellData");
215 writer.attachCellData(*totalConcentration2,
"C^n from cellData");
218 writer.attachCellData(*pc,
"capillary pressure");
219 writer.attachCellData(*densityWetting,
"wetting density");
220 writer.attachCellData(*densityNonwetting,
"nonwetting density");
221 writer.attachCellData(*mobilityW,
"mobility w_phase");
222 writer.attachCellData(*mobilityNW,
"mobility nw_phase");
223 std::ostringstream oss1, oss2;
224 oss1 <<
"mass fraction " << FluidSystem::componentName(0) <<
" in " << FluidSystem::phaseName(0) <<
"-phase";
225 writer.attachCellData(*massfraction1W, oss1.str());
226 oss2 <<
"mass fraction " << FluidSystem::componentName(0) <<
" in " << FluidSystem::phaseName(1) <<
"-phase";
227 writer.attachCellData(*massfraction1NW, oss2.str());
228 writer.attachCellData(*volErr,
"volume Error");
234 ScalarSolutionType *errorCorrPtr = writer.allocateManagedBuffer (size);
235 ScalarSolutionType *dv_dpPtr = writer.allocateManagedBuffer (size);
236 ScalarSolutionType *dV_dC1Ptr = writer.allocateManagedBuffer (size);
237 ScalarSolutionType *dV_dC2Ptr = writer.allocateManagedBuffer (size);
238 ScalarSolutionType *updEstimate1 = writer.allocateManagedBuffer (size);
239 ScalarSolutionType *updEstimate2 = writer.allocateManagedBuffer (size);
240 for (
int i = 0; i < size; i++)
242 CellData& cellData =
problem_.variables().cellData(i);
243 (*errorCorrPtr)[i] = cellData.errorCorrection();
244 (*dv_dpPtr)[i] = cellData.dv_dp();
245 (*dV_dC1Ptr)[i] = cellData.dv(wCompIdx);
246 (*dV_dC2Ptr)[i] = cellData.dv(nCompIdx);
250 writer.attachCellData(*errorCorrPtr,
"Error Correction");
251 writer.attachCellData(*dv_dpPtr,
"dv_dp");
252 writer.attachCellData(*dV_dC1Ptr,
"dV_dC1");
253 writer.attachCellData(*dV_dC2Ptr,
"dV_dC2");
254 writer.attachCellData(*updEstimate1,
"updEstimate comp 1");
255 writer.attachCellData(*updEstimate2,
"updEstimate comp 2");
261 ScalarSolutionType *pressurePV = writer.allocateManagedBuffer(size);
262 ScalarSolutionType *viscosityWetting = writer.allocateManagedBuffer(size);
263 ScalarSolutionType *viscosityNonwetting = writer.allocateManagedBuffer(size);
266 ScalarSolutionType *faceUpwindW = writer.allocateManagedBuffer(size);
267 ScalarSolutionType *faceUpwindN = writer.allocateManagedBuffer(size);
268 for (
int i = 0; i < size; i++)
270 CellData& cellData =
problem_.variables().cellData(i);
271 (*viscosityWetting)[i] = cellData.viscosity(wPhaseIdx);
272 (*viscosityNonwetting)[i] = cellData.viscosity(nPhaseIdx);
275 (*faceUpwindW)[i] = 0;
276 (*faceUpwindN)[i] = 0;
278 for(
int fIdx = 0; fIdx<cellData.fluxData().size(); fIdx++)
280 if(cellData.isUpwindCell(fIdx, contiWEqIdx))
281 (*faceUpwindW)[i] += pow(10,
static_cast<double>(3-fIdx));
282 if(cellData.isUpwindCell(fIdx, contiNEqIdx))
283 (*faceUpwindN)[i] += pow(10,
static_cast<double>(3-fIdx));
289 writer.attachCellData(*faceUpwindW,
"isUpwind w-phase");
290 writer.attachCellData(*faceUpwindN,
"isUpwind n-phase");
291 writer.attachCellData(*pressurePV,
"pressure (Primary Variable");
292 writer.attachCellData(*viscosityWetting,
"wetting viscosity");
293 writer.attachCellData(*viscosityNonwetting,
"nonwetting viscosity");
308 std::cout <<
"Writing debug for current time step\n";
312#if DUNE_MINIMAL_DEBUG_LEVEL <= 2
313 int size_ =
problem_.gridView().size(0);
318 Dune::BlockVector<Dune::FieldVector<double,1> > poro_(0.), perm_(0.);
319 poro_.resize(size_); perm_.resize(size_);
321 for (
const auto& element : elements(
problem_.gridView()))
324 int eIdxGlobal =
problem_.variables().index(element);
325 poro_[eIdxGlobal] =
problem_.spatialParams().porosity(element);
326 perm_[eIdxGlobal] =
problem_.spatialParams().intrinsicPermeability(element)[0][0];
337 Dune::BlockVector<Dune::FieldVector<double,1> > permY_(0.), permZ_(0.);
338 permY_.resize(size_); permZ_.resize(size_);
340 for (
const auto& element : elements(
problem_.gridView()))
343 int eIdxGlobal =
problem_.variables().index(element);
345 permY_[eIdxGlobal] =
problem_.spatialParams().intrinsicPermeability(element)[1][1];
347 permZ_[eIdxGlobal] =
problem_.spatialParams().intrinsicPermeability(element)[2][2];
375 updateEstimate_.resize(getPropValue<TypeTag, Properties::NumPhases>());
376 for (
int i=0; i<getPropValue<TypeTag, Properties::NumPhases>(); i++)
385 DUNE_THROW(Dune::NotImplemented,
"Global Pressure type not supported!");
401 static constexpr int pressureType = getPropValue<TypeTag, Properties::PressureFormulation>();
408 const Problem& problem()
const
414 Implementation &asImp_()
415 {
return *
static_cast<Implementation *
>(
this);}
418 const Implementation &asImp_()
const
419 {
return *
static_cast<const Implementation *
>(
this);}
431template<
class TypeTag>
435 ParentType::initialize();
439 Dune::dinfo <<
"first saturation guess"<<std::endl;
440 problem_.pressureModel().initialMaterialLaws(
false);
441 #if DUNE_MINIMAL_DEBUG_LEVEL <= 3
444 problem_.transportModel().update(0.,dummy, updateEstimate_,
false);
445 initializationOutput();
447 Dune::dinfo <<
"first pressure guess"<<std::endl;
448 problem_.pressureModel().assemble(
true);
449 problem_.pressureModel().solve();
450 #if DUNE_MINIMAL_DEBUG_LEVEL <= 3
451 initializationOutput(1e-6);
454 Dune::dinfo <<
"first guess for mass fractions"<<std::endl;
455 problem_.pressureModel().initialMaterialLaws(
true);
458 Dune::dinfo <<
"secant guess"<< std::endl;
459 Scalar dt_estimate = 0.;
460 problem_.transportModel().update(0., dt_estimate, updateEstimate_,
false);
462 dt_estimate = min ( problem_.timeManager().timeStepSize(), dt_estimate);
464 if (problem_.gridView().comm().size() > 1)
465 dt_estimate = problem_.gridView().comm().min(dt_estimate);
467 updateEstimate_ *= dt_estimate;
470 #if DUNE_MINIMAL_DEBUG_LEVEL <= 3
471 initializationOutput(2e-6);
474 Dune::dinfo <<
"second pressure guess"<<std::endl;
475 problem_.pressureModel().assemble(
false);
476 problem_.pressureModel().solve();
477 #if DUNE_MINIMAL_DEBUG_LEVEL <= 3
478 initializationOutput(3e-6);
482 problem_.pressureModel().initialMaterialLaws(
true);
487 Dune::BlockVector<Dune::FieldVector<Scalar, 1> > pressureOld(this->
pressure());
488 Dune::BlockVector<Dune::FieldVector<Scalar, 1> > pressureDiff;
489 Scalar pressureNorm = 1.;
492 while (pressureNorm > 1e-5 && numIter < 10)
496 problem_.transportModel().update(0., dt_dummy, updateEstimate_,
false); Dune::dinfo <<
"secant guess"<< std::endl;
497 updateEstimate_ *= dt_estimate;
503 problem_.pressureModel().assemble(
false); Dune::dinfo <<
"pressure guess number "<< numIter <<std::endl;
504 problem_.pressureModel().solve();
506 problem_.pressureModel().initialMaterialLaws(
true);
508 pressureDiff = pressureOld;
510 pressureNorm = pressureDiff.infinity_norm();
512 pressureNorm /= pressureOld.infinity_norm();
528template<
class TypeTag>
532 for (
const auto& element : elements(problem_.gridView()))
535 GlobalPosition globalPos = element.geometry().center();
538 int eIdxGlobal = problem_.variables().index(element);
541 Scalar temperature_ = problem_.temperatureAtPos(globalPos);
542 CellData& cellData = problem_.variables().cellData(eIdxGlobal);
544 FluidState& fluidState = cellData.manipulateFluidState();
547 const auto fluidMatrixInteraction = problem_.spatialParams().fluidMatrixInteractionAtPos(element.geometry().center());
553 typename Indices::BoundaryFormulation icFormulation;
554 problem_.initialFormulation(icFormulation, element);
559 Scalar exemplaryPressure = problem_.referencePressure(element);
563 sat_0 = problem_.initSat(element);
566 else if (icFormulation == Indices::concentration)
568 Scalar Z0 = problem_.initConcentration(element);
572 else if(compositional)
577 sat_0 = problem_.initSat(element);
579 if(getPropValue<TypeTag, Properties::EnableCapillarity>())
581 pc = fluidMatrixInteraction.pc(sat_0);
587 switch (pressureType)
604 else if (icFormulation == Indices::concentration)
606 Scalar Z0 = problem_.initConcentration(element);
611 if(getPropValue<TypeTag, Properties::EnableCapillarity>())
614 Scalar pc(cellData.capillaryPressure());
618 for(
int iter=0; iter < maxiter; iter++)
621 switch (pressureType)
641 pc = fluidMatrixInteraction.pc(fluidState.saturation(wPhaseIdx));
645 if (abs(oldPc - pc) < 10.0)
648 pc = fluidMatrixInteraction.pc(fluidState.saturation(wPhaseIdx));
660 cellData.calculateMassConcentration(problem_.spatialParams().porosity(element));
662 problem_.transportModel().totalConcentration(wCompIdx,eIdxGlobal) = cellData.massConcentration(wCompIdx);
663 problem_.transportModel().totalConcentration(nCompIdx,eIdxGlobal) = cellData.massConcentration(nCompIdx);
666 cellData.setMobility(wPhaseIdx, fluidMatrixInteraction.krw(fluidState.saturation(wPhaseIdx))
667 / cellData.viscosity(wPhaseIdx));
668 cellData.setMobility(nPhaseIdx, fluidMatrixInteraction.krn(fluidState.saturation(wPhaseIdx))
669 / cellData.viscosity(nPhaseIdx));
675 for (
const auto& intersection : intersections(problem_.gridView(), element))
678 += intersection.geometry().volume();
680 cellData.globalIdx() = eIdxGlobal;
683 cellData.dv_dp() = 0.;
684 cellData.dv(wPhaseIdx) = 0.;
685 cellData.dv(nPhaseIdx) = 0.;
700template<
class TypeTag>
703 Scalar maxError = 0.;
705 for (
const auto& element : elements(problem().gridView()))
707 int eIdxGlobal = problem().variables().index(element);
709 CellData& cellData = problem().variables().cellData(eIdxGlobal);
711 asImp_().updateMaterialLawsInElement(element, postTimeStep);
714 maxError = max(maxError, fabs(cellData.volumeError()));
716 if (problem_.gridView().comm().size() > 1)
717 maxError_ = problem_.gridView().comm().max(maxError_);
719 maxError_ = maxError/problem().timeManager().timeStepSize();
735template<
class TypeTag>
739 int eIdxGlobal = problem_.variables().index(element);
741 CellData& cellData = problem_.variables().cellData(eIdxGlobal);
744 Scalar temperature_ = cellData.temperature(wPhaseIdx);
747 FluidState updFluidState;
755 for(
int phaseIdx = 0; phaseIdx< numPhases; phaseIdx++)
756 pressure[phaseIdx] = cellData.pressure(phaseIdx);
759 ComponentVector mass(0.);
760 for(
int compIdx = 0; compIdx< numComponents; compIdx++)
761 mass[compIdx] = cellData.massConcentration(compIdx);
765 Scalar specificVolume(0.);
766 for(
int phaseIdx = 0; phaseIdx< numPhases; phaseIdx++)
767 specificVolume += cellData.phaseMassFraction(phaseIdx) / cellData.density(phaseIdx);
768 Scalar volalt = mass.one_norm() * specificVolume;
776 ComponentVector massIncrement(0.);
777 for(
int compIdx = 0; compIdx< numComponents; compIdx++)
779 massIncrement[compIdx] = updateEstimate_[compIdx][eIdxGlobal];
780 if(fabs(massIncrement[compIdx]) < 1e-8 * cellData.density(compIdx))
781 massIncrement[compIdx] = 1e-8* cellData.density(compIdx);
783 Scalar& incp = incp_;
790 PhaseVector p_(incp);
792 Scalar Z0 = mass[0] / mass.one_norm();
796 for(
int phaseIdx = 0; phaseIdx< numPhases; phaseIdx++)
797 specificVolume += updFluidState.phaseMassFraction(phaseIdx) / updFluidState.density(phaseIdx);
798 Scalar dv_dp = ((mass.one_norm() * specificVolume) - volalt) /incp;
803 Dune::dinfo <<
"dv_dp larger 0 at Idx " << eIdxGlobal <<
" , try and invert secant"<< std::endl;
809 for(
int phaseIdx = 0; phaseIdx< numPhases; phaseIdx++)
810 specificVolume += updFluidState.phaseMassFraction(phaseIdx) / updFluidState.density(phaseIdx);
811 dv_dp = ((mass.one_norm() * specificVolume) - volalt) /incp;
816 Dune::dwarn <<
"dv_dp still larger 0 after inverting secant at idx"<< eIdxGlobal<< std::endl;
821 for(
int phaseIdx = 0; phaseIdx< numPhases; phaseIdx++)
822 specificVolume += cellData.phaseMassFraction(phaseIdx) / updFluidState.density(phaseIdx);
823 dv_dp = ((mass.one_norm() * specificVolume) - volalt) /incp;
826 std::cout <<
"dv_dp still larger 0 after both inverts at idx " << eIdxGlobal << std::endl;
827 dv_dp = cellData.dv_dp();
831 cellData.dv_dp()=dv_dp;
834 for (
int compIdx = 0; compIdx<numComponents; compIdx++)
836 mass[compIdx] += massIncrement[compIdx];
837 Z0 = mass[0] / mass.one_norm();
842 for(
int phaseIdx = 0; phaseIdx< numPhases; phaseIdx++)
843 specificVolume += updFluidState.phaseMassFraction(phaseIdx) / updFluidState.density(phaseIdx);
845 cellData.dv(compIdx) = ((mass.one_norm() * specificVolume) - volalt) / massIncrement[compIdx];
846 mass[compIdx] -= massIncrement[compIdx];
851 if (isnan(cellData.dv(compIdx)) || isinf(cellData.dv(compIdx)) )
853 DUNE_THROW(Dune::MathError,
"NAN/inf of dV_dm. If that happens in first timestep, try smaller firstDt!");
856 cellData.volumeDerivativesAvailable(
true);
Define some often used mathematical functions.
Simplifies writing multi-file VTK datasets.
Determines the pressures and saturations of all fluid phases given the total mass of all components.
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 saturation(int phaseIdx) noexcept
I/O name of saturation for multiphase systems.
Definition: name.hh:43
std::string pressure(int phaseIdx) noexcept
I/O name of pressure for multiphase systems.
Definition: name.hh:34
Simplifies writing multi-file VTK datasets.
Definition: vtkmultiwriter.hh:148
Flash calculation routines for compositional sequential models.
Definition: compositionalflash.hh:51
static void saturationFlash2p2c(FluidState &fluidState, const Scalar saturation, const PhaseVector &phasePressure, const Scalar temperature)
Definition: compositionalflash.hh:219
static void concentrationFlash2p2c(FluidState &fluidState, const Scalar Z0, const PhaseVector &phasePressure, const Scalar temperature)
Definition: compositionalflash.hh:91
The finite volume model for the solution of the compositional pressure equation.
Definition: fvpressurecompositional.hh:67
Scalar incp_
Increment for the volume derivative w.r.t pressure.
Definition: fvpressurecompositional.hh:396
void volumeDerivatives(const GlobalPosition &, const Element &ep)
Partial derivatives of the volumes w.r.t. changes in total concentration and pressure.
Definition: fvpressurecompositional.hh:736
Scalar ErrorTermLowerBound_
Handling of error term: lower bound for error dampening.
Definition: fvpressurecompositional.hh:398
void initializationOutput(double pseudoTS=0.)
Write additional debug info in a special writer.
Definition: fvpressurecompositional.hh:306
Scalar maxError_
Maximum volume error of all cells.
Definition: fvpressurecompositional.hh:395
void addOutputVtkFields(MultiWriter &writer)
Write data files.
Definition: fvpressurecompositional.hh:169
void updateMaterialLaws(bool postTimeStep=false)
Updates secondary variables.
Definition: fvpressurecompositional.hh:701
Problem & problem_
Definition: fvpressurecompositional.hh:390
FVPressureCompositional(Problem &problem)
Constructs a FVPressureCompositional object.
Definition: fvpressurecompositional.hh:371
Scalar ErrorTermFactor_
Handling of error term: relaxation factor.
Definition: fvpressurecompositional.hh:397
static constexpr int pressureType
gives kind of pressure used ( , , )
Definition: fvpressurecompositional.hh:401
Scalar ErrorTermUpperBound_
Definition: fvpressurecompositional.hh:399
void initialMaterialLaws(bool compositional)
initializes the fluid distribution and hereby the variables container
Definition: fvpressurecompositional.hh:529
VtkMultiWriter< GridView > initializationOutputWriter_
output for the initialization procedure
Definition: fvpressurecompositional.hh:393
void update()
Compositional pressure solution routine: update estimate for secants, assemble, solve.
Definition: fvpressurecompositional.hh:128
TransportSolutionType updateEstimate_
Update estimate for changes in volume for the pressure equation.
Definition: fvpressurecompositional.hh:389
The finite volume base class for the solution of a pressure equation.
Definition: sequential/cellcentered/pressure.hh:49
void initialize()
Initialize pressure model.
Definition: sequential/cellcentered/pressure.hh:213
PressureSolution & pressure()
Returns the vector containing the pressure solution.
Definition: sequential/cellcentered/pressure.hh:120
Defines the properties required for the sequential 2p2c models.
Finite Volume Diffusion Model.