30 #ifndef OPM_FLOW_PROBLEM_COMP_HPP 31 #define OPM_FLOW_PROBLEM_COMP_HPP 38 #include <opm/material/fluidstates/CompositionalFluidState.hpp> 40 #include <opm/material/thermal/EclThermalLawManager.hpp> 42 #include <opm/input/eclipse/EclipseState/Compositional/CompositionalConfig.hpp> 58 template <
class TypeTag>
64 using typename FlowProblemType::Scalar;
65 using typename FlowProblemType::Simulator;
66 using typename FlowProblemType::GridView;
67 using typename FlowProblemType::FluidSystem;
68 using typename FlowProblemType::Vanguard;
71 using FlowProblemType::dim;
72 using FlowProblemType::dimWorld;
74 using FlowProblemType::numPhases;
75 using FlowProblemType::numComponents;
77 using FlowProblemType::gasPhaseIdx;
78 using FlowProblemType::oilPhaseIdx;
79 using FlowProblemType::waterPhaseIdx;
81 using typename FlowProblemType::Indices;
82 using typename FlowProblemType::PrimaryVariables;
84 using typename FlowProblemType::Evaluation;
85 using typename FlowProblemType::MaterialLaw;
86 using typename FlowProblemType::RateVector;
88 using InitialFluidState = CompositionalFluidState<Scalar, FluidSystem>;
102 EclWriterType::registerParameters();
105 Parameters::SetDefault<Parameters::NewtonTolerance<Scalar>>(1e-7);
108 Opm::CompositionalConfig::EOSType getEosType()
const 110 auto& simulator = this->simulator();
111 const auto& eclState = simulator.vanguard().eclState();
112 return eclState.compositionalConfig().eosType(0);
120 , thresholdPressures_(simulator)
122 eclWriter_ = std::make_unique<EclWriterType>(simulator);
123 enableEclOutput_ = Parameters::Get<Parameters::EnableEclOutput>();
134 FlowProblemType::finishInit();
136 auto& simulator = this->simulator();
138 auto finishTransmissibilities = [updated =
false,
this]()
mutable {
142 this->transmissibilities_.finishInit(
143 [&vg = this->simulator().vanguard()](
const unsigned int it) {
return vg.gridIdxToEquilGridIdx(it); });
148 finishTransmissibilities();
150 if (enableEclOutput_) {
151 eclWriter_->setTransmissibilities(&simulator.problem().eclTransmissibilities());
152 std::function<unsigned int(unsigned int)> equilGridToGrid = [&simulator](
unsigned int i) {
153 return simulator.vanguard().gridEquilIdxToGridIdx(i);
155 eclWriter_->extractOutputTransAndNNC(equilGridToGrid);
158 const auto& eclState = simulator.vanguard().eclState();
159 const auto& schedule = simulator.vanguard().schedule();
162 simulator.setStartTime(schedule.getStartTime());
163 simulator.setEndTime(schedule.simTime(schedule.size() - 1));
169 simulator.setEpisodeIndex(-1);
170 simulator.setEpisodeLength(0.0);
175 this->gravity_ = 0.0;
176 if (Parameters::Get<Parameters::EnableGravity>())
177 this->gravity_[dim - 1] = 9.80665;
178 if (!eclState.getInitConfig().hasGravity())
179 this->gravity_[dim - 1] = 0.0;
181 if (this->enableTuning_) {
184 const auto& tuning = schedule[0].tuning();
185 this->initialTimeStepSize_ = tuning.TSINIT.has_value() ? tuning.TSINIT.value() : -1.0;
186 this->maxTimeStepAfterWellEvent_ = tuning.TMAXWC;
189 this->initFluidSystem_();
191 if (FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx)
192 && FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
193 this->maxOilSaturation_.resize(this->model().numGridDof(), 0.0);
196 this->readRockParameters_(simulator.vanguard().cellCenterDepths(), [&simulator](
const unsigned idx) {
197 std::array<int, dim> coords;
198 simulator.vanguard().cartesianCoordinate(idx, coords);
199 std::ranges::transform(coords, coords.begin(),
200 [](
const auto c) {
return c + 1; });
203 FlowProblemType::readMaterialParameters_();
204 FlowProblemType::readThermalParameters_();
207 if (enableEclOutput_) {
208 eclWriter_->writeInit();
211 const auto& initconfig = eclState.getInitConfig();
212 if (initconfig.restartRequested())
213 readEclRestartSolution_();
215 this->readInitialCondition_();
217 FlowProblemType::updatePffDofData_();
219 if constexpr (getPropValue<TypeTag, Properties::EnablePolymer>()) {
220 const auto& vanguard = this->simulator().vanguard();
221 const auto& gridView = vanguard.gridView();
222 int numElements = gridView.size(0);
223 this->polymer_.maxAdsorption.resize(numElements, 0.0);
237 if (this->enableVtkOutput_() && eclState.getIOConfig().initOnly()) {
238 simulator.setTimeStepSize(0.0);
245 if (!initconfig.restartRequested()) {
246 simulator.startNextEpisode(schedule.seconds(1));
247 simulator.setEpisodeIndex(0);
248 simulator.setTimeStepIndex(0);
260 this->eclWriter_->mutableOutputModule().invalidateLocalData();
263 const auto& grid = this->simulator().vanguard().gridView().grid();
265 using GridType = std::remove_cv_t<std::remove_reference_t<decltype(grid)>>;
266 constexpr
bool isCpGrid = std::is_same_v<GridType, Dune::CpGrid>;
267 if (!isCpGrid || (grid.maxLevel() == 0)) {
273 if (enableEclOutput_){
274 eclWriter_->writeReports(timer);
286 if (! this->enableEclOutput_) {
292 if (!isSubStep || Parameters::Get<Parameters::EnableWriteAllSolutions>()) {
293 auto localCellData = data::Solution {};
295 this->eclWriter_->writeOutput(std::move(localCellData), isSubStep,
296 this->simulator().vanguard().schedule()
297 .exitStatus().has_value());
306 template <
class Context>
308 const Context& context,
312 OPM_TIMEBLOCK_LOCAL(eclProblemBoundary, Subsystem::Assembly);
313 if (!context.intersection(spaceIdx).boundary())
318 if (this->nonTrivialBoundaryConditions()) {
319 throw std::logic_error(
"boundary condition is not supported by compostional modeling yet");
329 template <
class Context>
330 void initial(PrimaryVariables& values,
const Context& context,
unsigned spaceIdx,
unsigned timeIdx)
const 332 const unsigned globalDofIdx = context.globalSpaceIndex(spaceIdx, timeIdx);
333 const auto& initial_fs = initialFluidStates_[globalDofIdx];
334 Opm::CompositionalFluidState<Scalar, FluidSystem> fs;
335 for (
unsigned p = 0; p < numPhases; ++p) {
337 fs.setPressure(p, initial_fs.pressure(p));
340 fs.setSaturation(p, initial_fs.saturation(p));
343 fs.setTemperature(initial_fs.temperature(p));
347 if (!zmf_initialization_) {
348 for (
unsigned p = 0; p < numPhases; ++p) {
349 for (
unsigned compIdx = 0; compIdx < numComponents; ++compIdx) {
350 fs.setMoleFraction(p, compIdx, initial_fs.moleFraction(p, compIdx));
355 const auto& eos_type = getEosType();
356 typename FluidSystem::template ParameterCache<Scalar> paramCache(eos_type);
357 paramCache.updatePhase(fs, FluidSystem::oilPhaseIdx);
358 paramCache.updatePhase(fs, FluidSystem::gasPhaseIdx);
359 fs.setDensity(FluidSystem::oilPhaseIdx, FluidSystem::density(fs, paramCache, FluidSystem::oilPhaseIdx));
360 fs.setDensity(FluidSystem::gasPhaseIdx, FluidSystem::density(fs, paramCache, FluidSystem::gasPhaseIdx));
363 Dune::FieldVector<Scalar, numComponents> z(0.0);
364 Scalar sumMoles = 0.0;
365 for (
unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
366 if (Indices::waterEnabled && phaseIdx == static_cast<unsigned int>(waterPhaseIdx)){
369 const auto saturation = fs.saturation(phaseIdx);
370 for (
unsigned compIdx = 0; compIdx < numComponents; ++compIdx) {
371 Scalar tmp = fs.molarity(phaseIdx, compIdx) * saturation;
372 tmp = max(tmp, 1e-8);
378 for (
unsigned compIdx = 0; compIdx < numComponents; ++compIdx) {
379 fs.setMoleFraction(compIdx, z[compIdx]);
383 for (
unsigned compIdx = 0; compIdx < numComponents; ++compIdx) {
384 fs.setMoleFraction(compIdx, initial_fs.moleFraction(compIdx));
389 for (
unsigned compIdx = 0; compIdx < numComponents; ++compIdx) {
390 const auto& Ktmp = fs.wilsonK_(compIdx);
391 fs.setKvalue(compIdx, Ktmp);
394 const Scalar& Ltmp = -1.0;
397 values.assignNaive(fs);
400 void addToSourceDense(RateVector&,
unsigned,
unsigned)
const override 405 const InitialFluidState& initialFluidState(
unsigned globalDofIdx)
const 406 {
return initialFluidStates_[globalDofIdx]; }
408 std::vector<InitialFluidState>& initialFluidStates()
409 {
return initialFluidStates_; }
411 const std::vector<InitialFluidState>& initialFluidStates()
const 412 {
return initialFluidStates_; }
414 const FlowThresholdPressure<TypeTag>& thresholdPressure()
const 416 assert( !thresholdPressures_.enableThresholdPressure() &&
417 " Threshold Pressures are not supported by compostional simulation ");
418 return thresholdPressures_;
421 const EclWriterType& eclWriter()
const 422 {
return *eclWriter_; }
424 EclWriterType& eclWriter()
425 {
return *eclWriter_; }
428 template<
class Serializer>
429 void serializeOp(Serializer& serializer)
431 serializer(static_cast<FlowProblemType&>(*
this));
432 serializer(*eclWriter_);
436 void updateExplicitQuantities_(
int ,
int ,
bool )
override 441 void readEquilInitialCondition_()
override 443 throw std::logic_error(
"Equilibration is not supported by compositional modeling yet");
446 void readEclRestartSolution_()
448 throw std::logic_error(
"Restarting is not supported by compositional modeling yet");
451 void readExplicitInitialCondition_()
override 453 readExplicitInitialConditionCompositional_();
456 void readExplicitInitialConditionCompositional_()
458 const auto& simulator = this->simulator();
459 const auto& vanguard = simulator.vanguard();
460 const auto& eclState = vanguard.eclState();
461 const auto& fp = eclState.fieldProps();
462 const bool has_pressure = fp.has_double(
"PRESSURE");
464 throw std::runtime_error(
"The ECL input file requires the presence of the PRESSURE " 465 "keyword if the model is initialized explicitly");
467 const bool has_xmf = fp.has_double(
"XMF");
468 const bool has_ymf = fp.has_double(
"YMF");
469 const bool has_zmf = fp.has_double(
"ZMF");
470 if ( !has_zmf && !(has_xmf && has_ymf) ) {
471 throw std::runtime_error(
"The ECL input file requires the presence of ZMF or XMF and YMF " 472 "keyword if the model is initialized explicitly");
475 if (has_zmf && (has_xmf || has_ymf)) {
476 throw std::runtime_error(
"The ECL input file can not handle explicit initialization " 477 "with both ZMF and XMF or YMF");
480 if (has_xmf != has_ymf) {
481 throw std::runtime_error(
"The ECL input file needs XMF and YMF combined to do the explicit " 482 "initializtion when using XMF or YMF");
485 const bool has_temp = fp.has_double(
"TEMPI");
488 assert(fp.has_double(
"SGAS"));
490 std::size_t numDof = this->model().numGridDof();
492 initialFluidStates_.resize(numDof);
494 std::vector<double> waterSaturationData;
495 std::vector<double> gasSaturationData;
496 std::vector<double> soilData;
497 std::vector<double> pressureData;
498 std::vector<double> tempiData;
500 const bool water_active = FluidSystem::phaseIsActive(waterPhaseIdx);
501 const bool gas_active = FluidSystem::phaseIsActive(gasPhaseIdx);
502 const bool oil_active = FluidSystem::phaseIsActive(oilPhaseIdx);
504 if (water_active && Indices::numPhases > 2)
505 waterSaturationData = fp.get_double(
"SWAT");
507 waterSaturationData.resize(numDof);
509 pressureData = fp.get_double(
"PRESSURE");
512 tempiData = fp.get_double(
"TEMPI");
518 gasSaturationData = fp.get_double(
"SGAS");
520 gasSaturationData.resize(numDof);
522 for (std::size_t dofIdx = 0; dofIdx < numDof; ++dofIdx) {
523 auto& dofFluidState = initialFluidStates_[dofIdx];
526 Scalar temperatureLoc = tempiData[dofIdx];
527 assert(std::isfinite(temperatureLoc) && temperatureLoc > 0);
528 dofFluidState.setTemperature(temperatureLoc);
531 dofFluidState.setSaturation(FluidSystem::gasPhaseIdx,
532 gasSaturationData[dofIdx]);
535 dofFluidState.setSaturation(FluidSystem::oilPhaseIdx,
537 - waterSaturationData[dofIdx]
538 - gasSaturationData[dofIdx]);
541 dofFluidState.setSaturation(FluidSystem::waterPhaseIdx,
542 waterSaturationData[dofIdx]);
548 const Scalar pressure = pressureData[dofIdx];
551 const std::array<Scalar, numPhases> pc = {0};
552 for (
unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
553 if (!FluidSystem::phaseIsActive(phaseIdx))
556 if (Indices::oilEnabled)
557 dofFluidState.setPressure(phaseIdx, pressure + (pc[phaseIdx] - pc[oilPhaseIdx]));
558 else if (Indices::gasEnabled)
559 dofFluidState.setPressure(phaseIdx, pressure + (pc[phaseIdx] - pc[gasPhaseIdx]));
560 else if (Indices::waterEnabled)
562 dofFluidState.setPressure(phaseIdx, pressure);
565 if (has_xmf && has_ymf) {
566 const auto& xmfData = fp.get_double(
"XMF");
567 const auto& ymfData = fp.get_double(
"YMF");
568 for (
unsigned compIdx = 0; compIdx < numComponents; ++compIdx) {
569 const std::size_t data_idx = compIdx * numDof + dofIdx;
570 const Scalar xmf = xmfData[data_idx];
571 const Scalar ymf = ymfData[data_idx];
573 dofFluidState.setMoleFraction(FluidSystem::oilPhaseIdx, compIdx, xmf);
574 dofFluidState.setMoleFraction(FluidSystem::gasPhaseIdx, compIdx, ymf);
579 zmf_initialization_ =
true;
580 const auto& zmfData = fp.get_double(
"ZMF");
581 for (
unsigned compIdx = 0; compIdx < numComponents; ++compIdx) {
582 const std::size_t data_idx = compIdx * numDof + dofIdx;
583 const Scalar zmf = zmfData[data_idx];
584 dofFluidState.setMoleFraction(compIdx, zmf);
587 const auto ymf = (dofFluidState.saturation(FluidSystem::gasPhaseIdx) > 0.) ? zmf : Scalar{0};
588 dofFluidState.setMoleFraction(FluidSystem::gasPhaseIdx, compIdx, ymf);
591 const auto xmf = (dofFluidState.saturation(FluidSystem::oilPhaseIdx) > 0.) ? zmf : Scalar{0};
592 dofFluidState.setMoleFraction(FluidSystem::oilPhaseIdx, compIdx, xmf);
601 void handleSolventBC(
const BCProp::BCFace& , RateVector& )
const override 603 throw std::logic_error(
"solvent is disabled for compositional modeling and you're trying to add solvent to BC");
606 void handlePolymerBC(
const BCProp::BCFace& , RateVector& )
const override 608 throw std::logic_error(
"polymer is disabled for compositional modeling and you're trying to add polymer to BC");
611 void handleMicrBC(
const BCProp::BCFace& , RateVector& )
const override 613 throw std::logic_error(
"MICP is disabled for compositional modeling and you're trying to add microbes to BC");
616 void handleOxygBC(
const BCProp::BCFace& , RateVector& )
const override 618 throw std::logic_error(
"MICP is disabled for compositional modeling and you're trying to add oxygen to BC");
621 void handleUreaBC(
const BCProp::BCFace& , RateVector& )
const override 623 throw std::logic_error(
"MICP is disabled for compositional modeling and you're trying to add urea to BC");
626 FlowThresholdPressure<TypeTag> thresholdPressures_;
628 std::vector<InitialFluidState> initialFluidStates_;
630 bool zmf_initialization_ {
false};
632 bool enableEclOutput_{
false};
633 std::unique_ptr<EclWriterType> eclWriter_;
638 #endif // OPM_FLOW_PROBLEM_COMP_HPP This class calculates the threshold pressure for grid faces according to the Eclipse Reference Manual...
Output module for the results black oil model writing in ECL binary format.
void finishInit()
Called by the Opm::Simulator in order to initialize the problem.
Definition: FlowProblemComp.hpp:129
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:233
void endTimeStep() override
Called by the simulator after each time integration.
Definition: FlowProblemComp.hpp:255
This problem simulates an input file given in the data format used by the commercial ECLiPSE simulato...
Definition: FlowProblem.hpp:92
unsigned pvtRegionIndex(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Returns the index of the relevant region for thermodynmic properties.
Definition: FlowProblem.hpp:878
virtual bool episodeWillBeOver() const
Whether or not the current episode will end at the end of the current time step.
Definition: FlowProblem.hpp:1863
This problem simulates an input file given in the data format used by the commercial ECLiPSE simulato...
Definition: FlowProblemComp.hpp:59
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: blackoilbioeffectsmodules.hh:45
void boundary(BoundaryRateVector &values, const Context &context, unsigned spaceIdx, unsigned) const
Evaluate the boundary conditions for a boundary segment.
Definition: FlowProblemComp.hpp:307
Scalar porosity(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Definition: FlowProblem.hpp:681
void initial(PrimaryVariables &values, const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Evaluate the initial value for a control volume.
Definition: FlowProblemComp.hpp:330
static void registerParameters()
Registers all available parameters for the problem and the model.
Definition: FlowProblemComp.hpp:98
Collects necessary output values and pass it to opm-common's ECL output.
Definition: EclWriter.hpp:110
void writeOutput(bool verbose) override
Write the requested quantities of the current solution into the output files.
Definition: FlowProblemComp.hpp:282
This problem simulates an input file given in the data format used by the commercial ECLiPSE simulato...
virtual void endTimeStep()
Called by the simulator after each time integration.
Definition: FlowProblem.hpp:418
static void registerParameters()
Registers all available parameters for the problem and the model.
Definition: FlowProblem.hpp:185
FlowProblemComp(Simulator &simulator)
Definition: FlowProblemComp.hpp:118
virtual void writeOutput(bool verbose)
Write the requested quantities of the current solution into the output files.
Definition: FlowProblem.hpp:498
Definition: SimulatorTimer.hpp:38