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>
58template <
class TypeTag>
88 using InitialFluidState = CompositionalFluidState<Scalar, FluidSystem>;
105 Parameters::SetDefault<Parameters::NewtonTolerance<Scalar>>(1e-7);
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 {
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;
184 const auto& tuning = schedule[0].tuning();
191 if (FluidSystem::phaseIsActive(FluidSystem::oilPhaseIdx)
192 && FluidSystem::phaseIsActive(FluidSystem::gasPhaseIdx)) {
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; });
207 if (enableEclOutput_) {
208 eclWriter_->writeInit();
211 const auto& initconfig = eclState.getInitConfig();
212 if (initconfig.restartRequested())
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);
257 FlowProblemType::endTimeStep();
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)) {
268 this->eclWriter_->evalSummaryState(! this->episodeWillBeOver());
273 if (enableEclOutput_){
274 eclWriter_->writeReports(timer);
284 FlowProblemType::writeOutput(verbose);
286 if (! this->enableEclOutput_) {
290 const auto isSubStep = !this->episodeWillBeOver();
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>
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);
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);
406 {
return initialFluidStates_[globalDofIdx]; }
409 {
return initialFluidStates_; }
412 {
return initialFluidStates_; }
416 assert( !thresholdPressures_.enableThresholdPressure() &&
417 " Threshold Pressures are not supported by compostional simulation ");
418 return thresholdPressures_;
422 {
return *eclWriter_; }
425 {
return *eclWriter_; }
428 template<
class Serializer>
432 serializer(*eclWriter_);
443 throw std::logic_error(
"Equilibration is not supported by compositional modeling yet");
448 throw std::logic_error(
"Restarting is not supported by compositional modeling yet");
453 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_;
Collects necessary output values and pass it to opm-common's ECL output.
Definition: EclWriter.hpp:120
static void registerParameters()
Definition: EclWriter.hpp:144
PolymerSolutionContainer< Scalar > polymer_
Definition: FlowGenericProblem.hpp:353
Scalar initialTimeStepSize_
Definition: FlowGenericProblem.hpp:365
bool enableTuning_
Definition: FlowGenericProblem.hpp:364
void readRockParameters_(const std::vector< Scalar > &cellCenterDepths, std::function< std::array< int, 3 >(const unsigned)> ijkIndex)
Definition: FlowGenericProblem_impl.hpp:137
std::vector< Scalar > maxOilSaturation_
Definition: FlowGenericProblem.hpp:354
void initFluidSystem_()
Definition: FlowGenericProblem_impl.hpp:533
Scalar maxTimeStepAfterWellEvent_
Definition: FlowGenericProblem.hpp:366
This problem simulates an input file given in the data format used by the commercial ECLiPSE simulato...
Definition: FlowProblemComp.hpp:60
void writeOutput(bool verbose) override
Write the requested quantities of the current solution into the output files.
Definition: FlowProblemComp.hpp:282
const std::vector< InitialFluidState > & initialFluidStates() const
Definition: FlowProblemComp.hpp:411
void finishInit()
Called by the Opm::Simulator in order to initialize the problem.
Definition: FlowProblemComp.hpp:129
Opm::CompositionalConfig::EOSType getEosType() const
Definition: FlowProblemComp.hpp:108
FlowProblemComp(Simulator &simulator)
Definition: FlowProblemComp.hpp:118
void writeReports(const SimulatorTimer &timer)
Definition: FlowProblemComp.hpp:272
void readExplicitInitialCondition_() override
Definition: FlowProblemComp.hpp:451
void readExplicitInitialConditionCompositional_()
Definition: FlowProblemComp.hpp:456
void endTimeStep() override
Called by the simulator after each time integration.
Definition: FlowProblemComp.hpp:255
const EclWriterType & eclWriter() const
Definition: FlowProblemComp.hpp:421
std::vector< InitialFluidState > & initialFluidStates()
Definition: FlowProblemComp.hpp:408
const FlowThresholdPressure< TypeTag > & thresholdPressure() const
Definition: FlowProblemComp.hpp:414
void readEclRestartSolution_()
Definition: FlowProblemComp.hpp:446
const InitialFluidState & initialFluidState(unsigned globalDofIdx) const
Definition: FlowProblemComp.hpp:405
void boundary(BoundaryRateVector &values, const Context &context, unsigned spaceIdx, unsigned) const
Evaluate the boundary conditions for a boundary segment.
Definition: FlowProblemComp.hpp:307
void initial(PrimaryVariables &values, const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Evaluate the initial value for a control volume.
Definition: FlowProblemComp.hpp:330
void readEquilInitialCondition_() override
Definition: FlowProblemComp.hpp:441
void serializeOp(Serializer &serializer)
Definition: FlowProblemComp.hpp:429
void updateExplicitQuantities_(int, int, bool) override
Definition: FlowProblemComp.hpp:436
void addToSourceDense(RateVector &, unsigned, unsigned) const override
Definition: FlowProblemComp.hpp:400
static void registerParameters()
Registers all available parameters for the problem and the model.
Definition: FlowProblemComp.hpp:98
EclWriterType & eclWriter()
Definition: FlowProblemComp.hpp:424
This problem simulates an input file given in the data format used by the commercial ECLiPSE simulato...
Definition: FlowProblem.hpp:95
GetPropType< TypeTag, Properties::Evaluation > Evaluation
Definition: FlowProblem.hpp:159
virtual void writeOutput(bool verbose)
Write the requested quantities of the current solution into the output files.
Definition: FlowProblem.hpp:498
@ gasPhaseIdx
Definition: FlowProblem.hpp:137
unsigned pvtRegionIndex(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Returns the index of the relevant region for thermodynmic properties.
Definition: FlowProblem.hpp:878
Scalar porosity(const Context &context, unsigned spaceIdx, unsigned timeIdx) const
Definition: FlowProblem.hpp:681
GetPropType< TypeTag, Properties::Vanguard > Vanguard
Definition: FlowProblem.hpp:108
@ dim
Definition: FlowProblem.hpp:112
GetPropType< TypeTag, Properties::Scalar > Scalar
Definition: FlowProblem.hpp:102
GetPropType< TypeTag, Properties::RateVector > RateVector
Definition: FlowProblem.hpp:148
GetPropType< TypeTag, Properties::Indices > Indices
Definition: FlowProblem.hpp:109
@ numPhases
Definition: FlowProblem.hpp:117
GetPropType< TypeTag, Properties::Simulator > Simulator
Definition: FlowProblem.hpp:149
void readThermalParameters_()
Definition: FlowProblem.hpp:1454
@ oilPhaseIdx
Definition: FlowProblem.hpp:138
GetPropType< TypeTag, Properties::GridView > GridView
Definition: FlowProblem.hpp:103
static void registerParameters()
Registers all available parameters for the problem and the model.
Definition: FlowProblem.hpp:185
void updatePffDofData_()
Definition: FlowProblem.hpp:1602
GetPropType< TypeTag, Properties::PrimaryVariables > PrimaryVariables
Definition: FlowProblem.hpp:147
@ numComponents
Definition: FlowProblem.hpp:118
Vanguard::TransmissibilityType transmissibilities_
Definition: FlowProblem.hpp:1804
virtual void readInitialCondition_()
Definition: FlowProblem.hpp:1530
@ waterPhaseIdx
Definition: FlowProblem.hpp:139
@ dimWorld
Definition: FlowProblem.hpp:113
GetPropType< TypeTag, Properties::FluidSystem > FluidSystem
Definition: FlowProblem.hpp:105
GetPropType< TypeTag, Properties::MaterialLaw > MaterialLaw
Definition: FlowProblem.hpp:157
void readMaterialParameters_()
Definition: FlowProblem.hpp:1414
This class calculates the threshold pressure for grid faces according to the Eclipse Reference Manual...
Definition: FlowThresholdPressure.hpp:59
Definition: SimulatorTimer.hpp:39
Definition: blackoilbioeffectsmodules.hh:45
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