24#ifndef DUMUX_FVPRESSURECOMPOSITIONAL_HH
25#define DUMUX_FVPRESSURECOMPOSITIONAL_HH
28#include <dune/common/float_cmp.hh>
87 dim = GridView::dimension, dimWorld = GridView::dimensionworld
91 pw = Indices::pressureW,
92 pn = Indices::pressureN
96 wPhaseIdx = Indices::wPhaseIdx, nPhaseIdx = Indices::nPhaseIdx,
97 wCompIdx = Indices::wCompIdx, nCompIdx = Indices::nCompIdx,
98 contiWEqIdx = Indices::contiWEqIdx, contiNEqIdx = Indices::contiNEqIdx
102 numPhases = getPropValue<TypeTag, Properties::NumPhases>(),
103 numComponents = getPropValue<TypeTag, Properties::NumComponents>()
107 using Element =
typename GridView::Traits::template Codim<0>::Entity;
110 using GlobalPosition = Dune::FieldVector<Scalar, dimWorld>;
111 using PhaseVector = Dune::FieldVector<Scalar, numPhases>;
112 using ComponentVector = Dune::FieldVector<Scalar, numComponents>;
133 Scalar dt_estimate = 0.;
134 Dune::dinfo <<
"secant guess"<< std::endl;
140 if(Dune::FloatCmp::eq<Scalar>(
problem_.timeManager().time(),
problem_.timeManager().episodeStartTime())
141 &&
problem_.timeManager().episodeIndex() > 1)
142 problem_.timeManager().setTimeStepSize(dt_estimate*getParam<Scalar>(
"Impet.CFLFactor"));
146 problem_.pressureModel().assemble(
false); Dune::dinfo <<
"pressure calculation"<< std::endl;
170 template<
class MultiWriter>
174 int size =
problem_.gridView().size(0);
175 ScalarSolutionType *pressureW = writer.allocateManagedBuffer(size);
176 ScalarSolutionType *pressureN = writer.allocateManagedBuffer(size);
177 ScalarSolutionType *totalConcentration1 = writer.allocateManagedBuffer (size);
178 ScalarSolutionType *totalConcentration2 = writer.allocateManagedBuffer (size);
179 ScalarSolutionType *pc = writer.allocateManagedBuffer(size);
180 ScalarSolutionType *saturationW = writer.allocateManagedBuffer(size);
181 ScalarSolutionType *densityWetting = writer.allocateManagedBuffer(size);
182 ScalarSolutionType *densityNonwetting = writer.allocateManagedBuffer(size);
183 ScalarSolutionType *mobilityW = writer.allocateManagedBuffer (size);
184 ScalarSolutionType *mobilityNW = writer.allocateManagedBuffer (size);
185 ScalarSolutionType *massfraction1W = writer.allocateManagedBuffer (size);
186 ScalarSolutionType *massfraction1NW = writer.allocateManagedBuffer (size);
188 ScalarSolutionType *volErr = writer.allocateManagedBuffer (size);
191 for (
int i = 0; i < size; i++)
194 CellData& cellData =
problem_.variables().cellData(i);
195 (*pressureW)[i] = cellData.pressure(wPhaseIdx);
196 (*pressureN)[i] = cellData.pressure(nPhaseIdx);
197 (*totalConcentration1)[i] = cellData.massConcentration(wCompIdx);
198 (*totalConcentration2)[i] = cellData.massConcentration(nCompIdx);
199 (*saturationW)[i] = cellData.saturation(wPhaseIdx);
203 (*pc)[i] = cellData.capillaryPressure();
204 (*densityWetting)[i] = cellData.density(wPhaseIdx);
205 (*densityNonwetting)[i] = cellData.density(nPhaseIdx);
206 (*mobilityW)[i] = cellData.mobility(wPhaseIdx);
207 (*mobilityNW)[i] = cellData.mobility(nPhaseIdx);
208 (*massfraction1W)[i] = cellData.massFraction(wPhaseIdx,wCompIdx);
209 (*massfraction1NW)[i] = cellData.massFraction(nPhaseIdx,wCompIdx);
210 (*volErr)[i] = cellData.volumeError();
213 writer.attachCellData(*pressureW,
"wetting pressure");
214 writer.attachCellData(*pressureN,
"nonwetting pressure");
215 writer.attachCellData(*saturationW,
"wetting saturation");
216 writer.attachCellData(*totalConcentration1,
"C^w from cellData");
217 writer.attachCellData(*totalConcentration2,
"C^n from cellData");
220 writer.attachCellData(*pc,
"capillary pressure");
221 writer.attachCellData(*densityWetting,
"wetting density");
222 writer.attachCellData(*densityNonwetting,
"nonwetting density");
223 writer.attachCellData(*mobilityW,
"mobility w_phase");
224 writer.attachCellData(*mobilityNW,
"mobility nw_phase");
225 std::ostringstream oss1, oss2;
226 oss1 <<
"mass fraction " << FluidSystem::componentName(0) <<
" in " << FluidSystem::phaseName(0) <<
"-phase";
227 writer.attachCellData(*massfraction1W, oss1.str());
228 oss2 <<
"mass fraction " << FluidSystem::componentName(0) <<
" in " << FluidSystem::phaseName(1) <<
"-phase";
229 writer.attachCellData(*massfraction1NW, oss2.str());
230 writer.attachCellData(*volErr,
"volume Error");
236 ScalarSolutionType *errorCorrPtr = writer.allocateManagedBuffer (size);
237 ScalarSolutionType *dv_dpPtr = writer.allocateManagedBuffer (size);
238 ScalarSolutionType *dV_dC1Ptr = writer.allocateManagedBuffer (size);
239 ScalarSolutionType *dV_dC2Ptr = writer.allocateManagedBuffer (size);
240 ScalarSolutionType *updEstimate1 = writer.allocateManagedBuffer (size);
241 ScalarSolutionType *updEstimate2 = writer.allocateManagedBuffer (size);
242 for (
int i = 0; i < size; i++)
244 CellData& cellData =
problem_.variables().cellData(i);
245 (*errorCorrPtr)[i] = cellData.errorCorrection();
246 (*dv_dpPtr)[i] = cellData.dv_dp();
247 (*dV_dC1Ptr)[i] = cellData.dv(wCompIdx);
248 (*dV_dC2Ptr)[i] = cellData.dv(nCompIdx);
252 writer.attachCellData(*errorCorrPtr,
"Error Correction");
253 writer.attachCellData(*dv_dpPtr,
"dv_dp");
254 writer.attachCellData(*dV_dC1Ptr,
"dV_dC1");
255 writer.attachCellData(*dV_dC2Ptr,
"dV_dC2");
256 writer.attachCellData(*updEstimate1,
"updEstimate comp 1");
257 writer.attachCellData(*updEstimate2,
"updEstimate comp 2");
263 ScalarSolutionType *pressurePV = writer.allocateManagedBuffer(size);
264 ScalarSolutionType *viscosityWetting = writer.allocateManagedBuffer(size);
265 ScalarSolutionType *viscosityNonwetting = writer.allocateManagedBuffer(size);
268 ScalarSolutionType *faceUpwindW = writer.allocateManagedBuffer(size);
269 ScalarSolutionType *faceUpwindN = writer.allocateManagedBuffer(size);
270 for (
int i = 0; i < size; i++)
272 CellData& cellData =
problem_.variables().cellData(i);
273 (*viscosityWetting)[i] = cellData.viscosity(wPhaseIdx);
274 (*viscosityNonwetting)[i] = cellData.viscosity(nPhaseIdx);
277 (*faceUpwindW)[i] = 0;
278 (*faceUpwindN)[i] = 0;
280 for(
int fIdx = 0; fIdx<cellData.fluxData().size(); fIdx++)
282 if(cellData.isUpwindCell(fIdx, contiWEqIdx))
283 (*faceUpwindW)[i] += pow(10,
static_cast<double>(3-fIdx));
284 if(cellData.isUpwindCell(fIdx, contiNEqIdx))
285 (*faceUpwindN)[i] += pow(10,
static_cast<double>(3-fIdx));
291 writer.attachCellData(*faceUpwindW,
"isUpwind w-phase");
292 writer.attachCellData(*faceUpwindN,
"isUpwind n-phase");
293 writer.attachCellData(*pressurePV,
"pressure (Primary Variable");
294 writer.attachCellData(*viscosityWetting,
"wetting viscosity");
295 writer.attachCellData(*viscosityNonwetting,
"nonwetting viscosity");
310 std::cout <<
"Writing debug for current time step\n";
314#if DUNE_MINIMAL_DEBUG_LEVEL <= 2
315 int size_ =
problem_.gridView().size(0);
320 Dune::BlockVector<Dune::FieldVector<double,1> > poro_(0.), perm_(0.);
321 poro_.resize(size_); perm_.resize(size_);
323 for (
const auto& element : elements(
problem_.gridView()))
326 int eIdxGlobal =
problem_.variables().index(element);
327 poro_[eIdxGlobal] =
problem_.spatialParams().porosity(element);
328 perm_[eIdxGlobal] =
problem_.spatialParams().intrinsicPermeability(element)[0][0];
339 Dune::BlockVector<Dune::FieldVector<double,1> > permY_(0.), permZ_(0.);
340 permY_.resize(size_); permZ_.resize(size_);
342 for (
const auto& element : elements(
problem_.gridView()))
345 int eIdxGlobal =
problem_.variables().index(element);
347 permY_[eIdxGlobal] =
problem_.spatialParams().intrinsicPermeability(element)[1][1];
349 permZ_[eIdxGlobal] =
problem_.spatialParams().intrinsicPermeability(element)[2][2];
377 updateEstimate_.resize(getPropValue<TypeTag, Properties::NumPhases>());
378 for (
int i=0; i<getPropValue<TypeTag, Properties::NumPhases>(); i++)
387 DUNE_THROW(Dune::NotImplemented,
"Global Pressure type not supported!");
403 static constexpr int pressureType = getPropValue<TypeTag, Properties::PressureFormulation>();
410 const Problem& problem()
const
416 Implementation &asImp_()
417 {
return *
static_cast<Implementation *
>(
this);}
420 const Implementation &asImp_()
const
421 {
return *
static_cast<const Implementation *
>(
this);}
433template<
class TypeTag>
437 ParentType::initialize();
441 Dune::dinfo <<
"first saturation guess"<<std::endl;
442 problem_.pressureModel().initialMaterialLaws(
false);
443 #if DUNE_MINIMAL_DEBUG_LEVEL <= 3
446 problem_.transportModel().update(0.,dummy, updateEstimate_,
false);
447 initializationOutput();
449 Dune::dinfo <<
"first pressure guess"<<std::endl;
450 problem_.pressureModel().assemble(
true);
451 problem_.pressureModel().solve();
452 #if DUNE_MINIMAL_DEBUG_LEVEL <= 3
453 initializationOutput(1e-6);
456 Dune::dinfo <<
"first guess for mass fractions"<<std::endl;
457 problem_.pressureModel().initialMaterialLaws(
true);
460 Dune::dinfo <<
"secant guess"<< std::endl;
461 Scalar dt_estimate = 0.;
462 problem_.transportModel().update(0., dt_estimate, updateEstimate_,
false);
464 dt_estimate = min ( problem_.timeManager().timeStepSize(), dt_estimate);
466 if (problem_.gridView().comm().size() > 1)
467 dt_estimate = problem_.gridView().comm().min(dt_estimate);
469 updateEstimate_ *= dt_estimate;
472 #if DUNE_MINIMAL_DEBUG_LEVEL <= 3
473 initializationOutput(2e-6);
476 Dune::dinfo <<
"second pressure guess"<<std::endl;
477 problem_.pressureModel().assemble(
false);
478 problem_.pressureModel().solve();
479 #if DUNE_MINIMAL_DEBUG_LEVEL <= 3
480 initializationOutput(3e-6);
484 problem_.pressureModel().initialMaterialLaws(
true);
489 Dune::BlockVector<Dune::FieldVector<Scalar, 1> > pressureOld(this->
pressure());
490 Dune::BlockVector<Dune::FieldVector<Scalar, 1> > pressureDiff;
491 Scalar pressureNorm = 1.;
494 while (pressureNorm > 1e-5 && numIter < 10)
498 problem_.transportModel().update(0., dt_dummy, updateEstimate_,
false); Dune::dinfo <<
"secant guess"<< std::endl;
499 updateEstimate_ *= dt_estimate;
505 problem_.pressureModel().assemble(
false); Dune::dinfo <<
"pressure guess number "<< numIter <<std::endl;
506 problem_.pressureModel().solve();
508 problem_.pressureModel().initialMaterialLaws(
true);
510 pressureDiff = pressureOld;
512 pressureNorm = pressureDiff.infinity_norm();
514 pressureNorm /= pressureOld.infinity_norm();
530template<
class TypeTag>
534 for (
const auto& element : elements(problem_.gridView()))
537 GlobalPosition globalPos = element.geometry().center();
540 int eIdxGlobal = problem_.variables().index(element);
543 Scalar temperature_ = problem_.temperatureAtPos(globalPos);
544 CellData& cellData = problem_.variables().cellData(eIdxGlobal);
546 FluidState& fluidState = cellData.manipulateFluidState();
552 const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), element);
558 typename Indices::BoundaryFormulation icFormulation;
559 problem_.initialFormulation(icFormulation, element);
564 Scalar exemplaryPressure = problem_.referencePressure(element);
568 sat_0 = problem_.initSat(element);
571 else if (icFormulation == Indices::concentration)
573 Scalar Z0 = problem_.initConcentration(element);
577 else if(compositional)
582 sat_0 = problem_.initSat(element);
584 if(getPropValue<TypeTag, Properties::EnableCapillarity>())
586 pc = fluidMatrixInteraction.pc(sat_0);
592 switch (pressureType)
609 else if (icFormulation == Indices::concentration)
611 Scalar Z0 = problem_.initConcentration(element);
616 if(getPropValue<TypeTag, Properties::EnableCapillarity>())
619 Scalar pc(cellData.capillaryPressure());
623 for(
int iter=0; iter < maxiter; iter++)
626 switch (pressureType)
646 pc = fluidMatrixInteraction.pc(fluidState.saturation(wPhaseIdx));
650 if (abs(oldPc - pc) < 10.0)
653 pc = fluidMatrixInteraction.pc(fluidState.saturation(wPhaseIdx));
665 cellData.calculateMassConcentration(problem_.spatialParams().porosity(element));
667 problem_.transportModel().totalConcentration(wCompIdx,eIdxGlobal) = cellData.massConcentration(wCompIdx);
668 problem_.transportModel().totalConcentration(nCompIdx,eIdxGlobal) = cellData.massConcentration(nCompIdx);
671 cellData.setMobility(wPhaseIdx, fluidMatrixInteraction.krw(fluidState.saturation(wPhaseIdx))
672 / cellData.viscosity(wPhaseIdx));
673 cellData.setMobility(nPhaseIdx, fluidMatrixInteraction.krn(fluidState.saturation(wPhaseIdx))
674 / cellData.viscosity(nPhaseIdx));
680 for (
const auto& intersection : intersections(problem_.gridView(), element))
683 += intersection.geometry().volume();
685 cellData.globalIdx() = eIdxGlobal;
688 cellData.dv_dp() = 0.;
689 cellData.dv(wPhaseIdx) = 0.;
690 cellData.dv(nPhaseIdx) = 0.;
705template<
class TypeTag>
708 Scalar maxError = 0.;
710 for (
const auto& element : elements(problem().gridView()))
712 int eIdxGlobal = problem().variables().index(element);
714 CellData& cellData = problem().variables().cellData(eIdxGlobal);
716 asImp_().updateMaterialLawsInElement(element, postTimeStep);
719 maxError = max(maxError, fabs(cellData.volumeError()));
721 if (problem_.gridView().comm().size() > 1)
722 maxError_ = problem_.gridView().comm().max(maxError_);
724 maxError_ = maxError/problem().timeManager().timeStepSize();
740template<
class TypeTag>
744 int eIdxGlobal = problem_.variables().index(element);
746 CellData& cellData = problem_.variables().cellData(eIdxGlobal);
749 Scalar temperature_ = cellData.temperature(wPhaseIdx);
752 FluidState updFluidState;
760 for(
int phaseIdx = 0; phaseIdx< numPhases; phaseIdx++)
761 pressure[phaseIdx] = cellData.pressure(phaseIdx);
764 ComponentVector mass(0.);
765 for(
int compIdx = 0; compIdx< numComponents; compIdx++)
766 mass[compIdx] = cellData.massConcentration(compIdx);
770 Scalar specificVolume(0.);
771 for(
int phaseIdx = 0; phaseIdx< numPhases; phaseIdx++)
772 specificVolume += cellData.phaseMassFraction(phaseIdx) / cellData.density(phaseIdx);
773 Scalar volalt = mass.one_norm() * specificVolume;
781 ComponentVector massIncrement(0.);
782 for(
int compIdx = 0; compIdx< numComponents; compIdx++)
784 massIncrement[compIdx] = updateEstimate_[compIdx][eIdxGlobal];
785 if(fabs(massIncrement[compIdx]) < 1e-8 * cellData.density(compIdx))
786 massIncrement[compIdx] = 1e-8* cellData.density(compIdx);
788 Scalar& incp = incp_;
795 PhaseVector p_(incp);
797 Scalar Z0 = mass[0] / mass.one_norm();
801 for(
int phaseIdx = 0; phaseIdx< numPhases; phaseIdx++)
802 specificVolume += updFluidState.phaseMassFraction(phaseIdx) / updFluidState.density(phaseIdx);
803 Scalar dv_dp = ((mass.one_norm() * specificVolume) - volalt) /incp;
808 Dune::dinfo <<
"dv_dp larger 0 at Idx " << eIdxGlobal <<
" , try and invert secant"<< std::endl;
814 for(
int phaseIdx = 0; phaseIdx< numPhases; phaseIdx++)
815 specificVolume += updFluidState.phaseMassFraction(phaseIdx) / updFluidState.density(phaseIdx);
816 dv_dp = ((mass.one_norm() * specificVolume) - volalt) /incp;
821 Dune::dwarn <<
"dv_dp still larger 0 after inverting secant at idx"<< eIdxGlobal<< std::endl;
826 for(
int phaseIdx = 0; phaseIdx< numPhases; phaseIdx++)
827 specificVolume += cellData.phaseMassFraction(phaseIdx) / updFluidState.density(phaseIdx);
828 dv_dp = ((mass.one_norm() * specificVolume) - volalt) /incp;
831 std::cout <<
"dv_dp still larger 0 after both inverts at idx " << eIdxGlobal << std::endl;
832 dv_dp = cellData.dv_dp();
836 cellData.dv_dp()=dv_dp;
839 for (
int compIdx = 0; compIdx<numComponents; compIdx++)
841 mass[compIdx] += massIncrement[compIdx];
842 Z0 = mass[0] / mass.one_norm();
847 for(
int phaseIdx = 0; phaseIdx< numPhases; phaseIdx++)
848 specificVolume += updFluidState.phaseMassFraction(phaseIdx) / updFluidState.density(phaseIdx);
850 cellData.dv(compIdx) = ((mass.one_norm() * specificVolume) - volalt) / massIncrement[compIdx];
851 mass[compIdx] -= massIncrement[compIdx];
856 if (isnan(cellData.dv(compIdx)) || isinf(cellData.dv(compIdx)) )
858 DUNE_THROW(Dune::MathError,
"NAN/inf of dV_dm. If that happens in first timestep, try smaller firstDt!");
861 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 (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 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:146
Flash calculation routines for compositional sequential models.
Definition: compositionalflash.hh:51
static void saturationFlash2p2c(FluidState &fluidState, const Scalar &saturation, const PhaseVector &phasePressure, const Scalar &porosity, const Scalar &temperature)
Definition: compositionalflash.hh:219
static void concentrationFlash2p2c(FluidState &fluidState, const Scalar &Z0, const PhaseVector &phasePressure, const Scalar &porosity, const Scalar &temperature)
Definition: compositionalflash.hh:71
The finite volume model for the solution of the compositional pressure equation.
Definition: fvpressurecompositional.hh:69
Scalar incp_
Increment for the volume derivative w.r.t pressure.
Definition: fvpressurecompositional.hh:398
void volumeDerivatives(const GlobalPosition &, const Element &ep)
Partial derivatives of the volumes w.r.t. changes in total concentration and pressure.
Definition: fvpressurecompositional.hh:741
Scalar ErrorTermLowerBound_
Handling of error term: lower bound for error dampening.
Definition: fvpressurecompositional.hh:400
void initializationOutput(double pseudoTS=0.)
Write additional debug info in a special writer.
Definition: fvpressurecompositional.hh:308
Scalar maxError_
Maximum volume error of all cells.
Definition: fvpressurecompositional.hh:397
void addOutputVtkFields(MultiWriter &writer)
Write data files.
Definition: fvpressurecompositional.hh:171
void updateMaterialLaws(bool postTimeStep=false)
Updates secondary variables.
Definition: fvpressurecompositional.hh:706
Problem & problem_
Definition: fvpressurecompositional.hh:392
FVPressureCompositional(Problem &problem)
Constructs a FVPressureCompositional object.
Definition: fvpressurecompositional.hh:373
Scalar ErrorTermFactor_
Handling of error term: relaxation factor.
Definition: fvpressurecompositional.hh:399
static constexpr int pressureType
gives kind of pressure used ( , , )
Definition: fvpressurecompositional.hh:403
Scalar ErrorTermUpperBound_
Definition: fvpressurecompositional.hh:401
void initialMaterialLaws(bool compositional)
initializes the fluid distribution and hereby the variables container
Definition: fvpressurecompositional.hh:531
VtkMultiWriter< GridView > initializationOutputWriter_
output for the initialization procedure
Definition: fvpressurecompositional.hh:395
void update()
Compositional pressure solution routine: update estimate for secants, assemble, solve.
Definition: fvpressurecompositional.hh:130
TransportSolutionType updateEstimate_
Update estimate for changes in volume for the pressure equation.
Definition: fvpressurecompositional.hh:391
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.