From 13cc18d38bba8a7ab223e246732cde3f3889e063 Mon Sep 17 00:00:00 2001 From: Vegard Kippe Date: Fri, 6 Dec 2024 15:35:59 +0100 Subject: [PATCH 1/8] Output and restore injection temp from SWELL, also adding gas tracer. --- opm/input/eclipse/EclipseState/Runspec.cpp | 6 ++++ opm/input/eclipse/EclipseState/Runspec.hpp | 2 ++ opm/input/eclipse/Schedule/Well/Well.cpp | 25 +++++++++++++++-- .../share/keywords/000_Eclipse100/G/GLIFTOPT | 1 - opm/io/eclipse/rst/well.cpp | 11 ++++++-- opm/io/eclipse/rst/well.hpp | 1 + opm/output/eclipse/AggregateWellData.cpp | 28 +++++++++++++++++-- opm/output/eclipse/CreateInteHead.cpp | 7 +++-- 8 files changed, 70 insertions(+), 11 deletions(-) diff --git a/opm/input/eclipse/EclipseState/Runspec.cpp b/opm/input/eclipse/EclipseState/Runspec.cpp index 9c7bee7e2c7..782946926ba 100644 --- a/opm/input/eclipse/EclipseState/Runspec.cpp +++ b/opm/input/eclipse/EclipseState/Runspec.cpp @@ -598,6 +598,12 @@ Tracers Tracers::serializationTestObject() { int Tracers::water_tracers() const { return this->m_water_tracers; } +int Tracers::gas_tracers() const { + return this->m_gas_tracers; +} +int Tracers::oil_tracers() const { + return this->m_oil_tracers; +} Tracers::Tracers(const Deck& deck) { diff --git a/opm/input/eclipse/EclipseState/Runspec.hpp b/opm/input/eclipse/EclipseState/Runspec.hpp index c8075a63bb3..783d8d26c29 100644 --- a/opm/input/eclipse/EclipseState/Runspec.hpp +++ b/opm/input/eclipse/EclipseState/Runspec.hpp @@ -449,6 +449,8 @@ class Tracers { explicit Tracers(const Deck& ); int water_tracers() const; + int gas_tracers() const; + int oil_tracers() const; template void serializeOp(Serializer& serializer) { diff --git a/opm/input/eclipse/Schedule/Well/Well.cpp b/opm/input/eclipse/Schedule/Well/Well.cpp index 1ac79eae6c1..75aa184bda0 100644 --- a/opm/input/eclipse/Schedule/Well/Well.cpp +++ b/opm/input/eclipse/Schedule/Well/Well.cpp @@ -155,6 +155,7 @@ Opm::Well::ProducerCMode producer_cmode_from_int(const int pmode) case CModeVal::BHP: return Opm::Well::ProducerCMode::BHP; } + // Return BHP as default instead, since -10 might be written for some unused wells..?? throw std::invalid_argument { fmt::format("Cannot convert integer value {} to producer control mode", pmode) }; @@ -466,11 +467,29 @@ Well::Well(const RestartIO::RstWell& rst_well, this->updateInjection(std::move(i)); if (!rst_well.tracer_concentration_injection.empty()) { + const auto isTemp = (rst_well.inj_temperature > (0.5 * RestartIO::RstWell::UNDEFINED_VALUE)); + std::size_t tracer_conc_index = 0; + if (isTemp) { + this->well_inj_temperature = rst_well.inj_temperature; + ++tracer_conc_index; + } auto tracer = std::make_shared(this->getTracerProperties()); - for (std::size_t tracer_index = 0; tracer_index < tracer_config.size(); tracer_index++) { + for (std::size_t tracer_index = 0; tracer_index < tracer_config.size(); ++tracer_index) { const auto& tname = tracer_config[tracer_index].name; - const auto concentration = rst_well.tracer_concentration_injection[tracer_index]; - tracer->setConcentration(tname, concentration); + const auto phase = tracer_config[tracer_index].phase; + if (phase == Phase::WATER) { + const auto concentration = rst_well.tracer_concentration_injection[tracer_conc_index]; + tracer->setConcentration(tname, concentration); + } else { + const auto free_conc = rst_well.tracer_concentration_injection[tracer_conc_index]; + const auto sol_conc = rst_well.tracer_concentration_injection[++tracer_conc_index]; + if (WellType::gas_injector(this->wtype.ecl_wtype()) || WellType::oil_injector(this->wtype.ecl_wtype())) { + tracer->setConcentration(tname, free_conc); + if (sol_conc > 0.0) { + OpmLog::warning(fmt::format("Well {}: Restoring a non-zero solution concentration of tracer {} is not yet supported.", rst_well.name, tname)); + } + } + } } this->updateTracer(tracer); } diff --git a/opm/input/eclipse/share/keywords/000_Eclipse100/G/GLIFTOPT b/opm/input/eclipse/share/keywords/000_Eclipse100/G/GLIFTOPT index 250287c804b..dfb14715f3d 100644 --- a/opm/input/eclipse/share/keywords/000_Eclipse100/G/GLIFTOPT +++ b/opm/input/eclipse/share/keywords/000_Eclipse100/G/GLIFTOPT @@ -3,7 +3,6 @@ "sections": [ "SCHEDULE" ], - "requires" : ["LIFTOPT"], "items": [ { "name": "GROUP_NAME", diff --git a/opm/io/eclipse/rst/well.cpp b/opm/io/eclipse/rst/well.cpp index 0d081d7212f..c5d7c521009 100644 --- a/opm/io/eclipse/rst/well.cpp +++ b/opm/io/eclipse/rst/well.cpp @@ -187,8 +187,15 @@ Opm::RestartIO::RstWell::RstWell(const UnitSystem& unit_system, active_control = VI::IWell::Value::WellCtrlMode::Group; } - for (std::size_t tracer_index = 0; - tracer_index < static_cast(header.runspec.tracers().water_tracers()); + // If the TEMP option is active, this is the first tracer + std::size_t tracer_index = 0; + const bool isTemp = header.runspec.temp(); + if (isTemp) { + this->inj_temperature = swel[VI::SWell::TracerOffset + tracer_index++]; + } + const auto& tracers = header.runspec.tracers(); + for (const auto num_tracer_injconcs = tracers.water_tracers() + 2*(tracers.gas_tracers() + tracers.oil_tracers()) + tracer_index; + tracer_index < static_cast(num_tracer_injconcs); ++tracer_index) { this->tracer_concentration_injection.push_back(swel[VI::SWell::TracerOffset + tracer_index]); diff --git a/opm/io/eclipse/rst/well.hpp b/opm/io/eclipse/rst/well.hpp index 230b6673953..7982f44b918 100644 --- a/opm/io/eclipse/rst/well.hpp +++ b/opm/io/eclipse/rst/well.hpp @@ -129,6 +129,7 @@ struct RstWell float dfac_corr_coeff_a{}; float dfac_corr_exponent_b{}; float dfac_corr_exponent_c{}; + float inj_temperature{UNDEFINED_VALUE}; std::vector tracer_concentration_injection; double oil_rate; diff --git a/opm/output/eclipse/AggregateWellData.cpp b/opm/output/eclipse/AggregateWellData.cpp index 82b72a3e662..ca4faae6daf 100644 --- a/opm/output/eclipse/AggregateWellData.cpp +++ b/opm/output/eclipse/AggregateWellData.cpp @@ -1080,18 +1080,37 @@ namespace { void assignTracerData(const Opm::TracerConfig& tracers, const Opm::SummaryState& smry, const std::string& wname, - SWellArray& sWell) + SWellArray& sWell, + const bool isTemp = false) { - auto output_index = static_cast(VI::SWell::index::TracerOffset); + // Temperature tracer is first, if present + const std::size_t tempOffset = isTemp ? 1 : 0; + auto output_index = tempOffset + static_cast(VI::SWell::index::TracerOffset); for (const auto& tracer : tracers) { if (tracer.phase == Opm::Phase::WATER) { sWell[output_index++] = smry.get_well_var(wname, fmt::format("WTIC{}", tracer.name), 0.0); + } else { + sWell[output_index++] = + smry.get_well_var(wname, fmt::format("WTICF{}", tracer.name), 0.0); + sWell[output_index++] = + smry.get_well_var(wname, fmt::format("WTICS{}", tracer.name), 0.0); } } } + template + void assignTempData(const std::string& wname, + const Opm::SummaryState& smry, + SWellArray& sWell) + { + // TEMP is the first tracer + auto output_index = static_cast(VI::SWell::index::TracerOffset); + sWell[output_index] = smry.get_well_var(wname, "WTICHEA", 0.0); + } + + template void staticContrib(const Opm::Well& well, const Opm::GasLiftOpt& glo, @@ -1133,7 +1152,10 @@ namespace { assignDFactorCorrelation(well, units, sWell); assignEconomicLimits(well, swprop, sWell); assignWellTest(well.name(), sched, wtest_state, sim_step, swprop, sWell); - assignTracerData(tracers, smry, well.name(), sWell); + + const auto isTemp = sched.runspec().temp(); + if (isTemp) assignTempData(well.name(), smry, sWell); + assignTracerData(tracers, smry, well.name(), sWell, isTemp); assignBhpVfpAdjustment(well, swprop, sWell); } } // SWell diff --git a/opm/output/eclipse/CreateInteHead.cpp b/opm/output/eclipse/CreateInteHead.cpp index 868a8627176..ccf447ddf2e 100644 --- a/opm/output/eclipse/CreateInteHead.cpp +++ b/opm/output/eclipse/CreateInteHead.cpp @@ -573,7 +573,10 @@ createInteHead(const EclipseState& es, const auto& tdim = es.getTableManager(); const auto& rdim = tdim.getRegdims(); const auto& rckcfg = es.getSimulationConfig().rock_config(); - auto num_water_tracer = es.runspec().tracers().water_tracers(); + const auto& tracers = es.runspec().tracers(); + // TEMP is a tracer, oil&gas tracers have both free and solution parts. + const auto num_tracer_items = 2 * (tracers.water_tracers() + 2*(tracers.oil_tracers() + tracers.gas_tracers()) + (es.runspec().temp() ? 1 : 0)); + const auto num_water_tracer = tracers.water_tracers(); int nxwelz_tracer_shift = num_water_tracer*5 + 2 * (num_water_tracer > 0); const auto ih = InteHEAD{} @@ -588,7 +591,7 @@ createInteHead(const EclipseState& es, // across a range of reference cases, but are not guaranteed to be // universally valid. .drsdt(sched, lookup_step) - .params_NWELZ (155 + num_water_tracer, 122 + 2*num_water_tracer, 130 + nxwelz_tracer_shift, 3) // n{isxz}welz: number of data elements per well in {ISXZ}WELL + .params_NWELZ (155 + num_water_tracer, 122 + num_tracer_items, 130 + nxwelz_tracer_shift, 3) // n{isxz}welz: number of data elements per well in {ISXZ}WELL .params_NCON (25, 41, 58 + 5*num_water_tracer) // n{isx}conz: number of data elements per completion in ICON .params_GRPZ (getNGRPZ(nwgmax, ngmax, num_water_tracer, rspec)) .aquiferDimensions (inferAquiferDimensions(es, sched[lookup_step])) From 0404c640e40de2d953717ebb624e925cfb38f104 Mon Sep 17 00:00:00 2001 From: Vegard Kippe Date: Mon, 9 Dec 2024 10:13:15 +0100 Subject: [PATCH 2/8] Restore temperature tracer unit --- opm/input/eclipse/Schedule/Well/Well.cpp | 13 +++++++------ opm/io/eclipse/rst/well.cpp | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/opm/input/eclipse/Schedule/Well/Well.cpp b/opm/input/eclipse/Schedule/Well/Well.cpp index 75aa184bda0..64c93b0c829 100644 --- a/opm/input/eclipse/Schedule/Well/Well.cpp +++ b/opm/input/eclipse/Schedule/Well/Well.cpp @@ -466,13 +466,14 @@ Well::Well(const RestartIO::RstWell& rst_well, this->updateInjection(std::move(i)); + const auto isTemp = (rst_well.inj_temperature < RestartIO::RstWell::UNDEFINED_VALUE); + std::size_t tracer_conc_index = 0; + if (isTemp) { + this->well_inj_temperature = rst_well.inj_temperature; + ++tracer_conc_index; + } + if (!rst_well.tracer_concentration_injection.empty()) { - const auto isTemp = (rst_well.inj_temperature > (0.5 * RestartIO::RstWell::UNDEFINED_VALUE)); - std::size_t tracer_conc_index = 0; - if (isTemp) { - this->well_inj_temperature = rst_well.inj_temperature; - ++tracer_conc_index; - } auto tracer = std::make_shared(this->getTracerProperties()); for (std::size_t tracer_index = 0; tracer_index < tracer_config.size(); ++tracer_index) { const auto& tname = tracer_config[tracer_index].name; diff --git a/opm/io/eclipse/rst/well.cpp b/opm/io/eclipse/rst/well.cpp index c5d7c521009..ea49f3cc021 100644 --- a/opm/io/eclipse/rst/well.cpp +++ b/opm/io/eclipse/rst/well.cpp @@ -191,7 +191,7 @@ Opm::RestartIO::RstWell::RstWell(const UnitSystem& unit_system, std::size_t tracer_index = 0; const bool isTemp = header.runspec.temp(); if (isTemp) { - this->inj_temperature = swel[VI::SWell::TracerOffset + tracer_index++]; + this->inj_temperature = unit_system.to_si(M::temperature, swel[VI::SWell::TracerOffset + tracer_index++]); } const auto& tracers = header.runspec.tracers(); for (const auto num_tracer_injconcs = tracers.water_tracers() + 2*(tracers.gas_tracers() + tracers.oil_tracers()) + tracer_index; From 2ec4f1365a212bd3bb5f70c838efe0a187f106df Mon Sep 17 00:00:00 2001 From: Vegard Kippe Date: Thu, 12 Dec 2024 09:08:57 +0100 Subject: [PATCH 3/8] Update TEMP restart with flags, array dims and tracer unit --- opm/output/eclipse/CreateInteHead.cpp | 23 +++++++++++------------ opm/output/eclipse/CreateLogiHead.cpp | 2 +- opm/output/eclipse/InteHEAD.cpp | 5 ++++- opm/output/eclipse/InteHEAD.hpp | 2 +- opm/output/eclipse/LogiHEAD.cpp | 9 ++++++--- opm/output/eclipse/LogiHEAD.hpp | 9 +++++---- opm/output/eclipse/RestartIO.cpp | 11 +++++++++++ opm/output/eclipse/WriteInit.cpp | 2 +- 8 files changed, 40 insertions(+), 23 deletions(-) diff --git a/opm/output/eclipse/CreateInteHead.cpp b/opm/output/eclipse/CreateInteHead.cpp index ccf447ddf2e..5dd0633d6db 100644 --- a/opm/output/eclipse/CreateInteHead.cpp +++ b/opm/output/eclipse/CreateInteHead.cpp @@ -265,7 +265,7 @@ namespace { std::array getNGRPZ(const int grpsz, const int ngrp, - const int num_water_tracer, + const int num_tracers, const ::Opm::Runspec& rspec) { const auto& wd = rspec.wellDimensions(); @@ -275,7 +275,7 @@ namespace { const int nigrpz = 97 + std::max(nwgmax, ngmax); const int nsgrpz = 112; - const int nxgrpz = 180 + 4*num_water_tracer; + const int nxgrpz = 180 + 4*num_tracers + 1; const int nzgrpz = 5; return {{ @@ -360,7 +360,7 @@ namespace { Opm::RestartIO::InteHEAD::WellSegDims - getWellSegDims(const int num_water_tracer, + getWellSegDims(const int num_tracers, const ::Opm::Runspec& rspec, const ::Opm::Schedule& sched, const std::size_t report_step, @@ -379,7 +379,7 @@ namespace { std::max(maxNumBr, wsd.maxLateralBranchesPerWell()), 22, // Number of entries per segment in ISEG (2017.2) Opm::RestartIO::InteHEAD::numRsegElem(rspec.phases()) - + 8*num_water_tracer, // Number of entries per segment in RSEG + + 8*num_tracers, // Number of entries per segment in RSEG 10 // Number of entries per segment in ILBR (2017.2) }; } @@ -575,9 +575,8 @@ createInteHead(const EclipseState& es, const auto& rckcfg = es.getSimulationConfig().rock_config(); const auto& tracers = es.runspec().tracers(); // TEMP is a tracer, oil&gas tracers have both free and solution parts. - const auto num_tracer_items = 2 * (tracers.water_tracers() + 2*(tracers.oil_tracers() + tracers.gas_tracers()) + (es.runspec().temp() ? 1 : 0)); - const auto num_water_tracer = tracers.water_tracers(); - int nxwelz_tracer_shift = num_water_tracer*5 + 2 * (num_water_tracer > 0); + const auto num_tracers = tracers.water_tracers() + 2*(tracers.oil_tracers() + tracers.gas_tracers()) + (es.runspec().temp() ? 1 : 0); + int nxwelz_tracer_shift = num_tracers*5 + 2 * (num_tracers > 0) + 1; const auto ih = InteHEAD{} .dimensions (grid.getNXYZ()) @@ -591,18 +590,18 @@ createInteHead(const EclipseState& es, // across a range of reference cases, but are not guaranteed to be // universally valid. .drsdt(sched, lookup_step) - .params_NWELZ (155 + num_water_tracer, 122 + num_tracer_items, 130 + nxwelz_tracer_shift, 3) // n{isxz}welz: number of data elements per well in {ISXZ}WELL - .params_NCON (25, 41, 58 + 5*num_water_tracer) // n{isx}conz: number of data elements per completion in ICON - .params_GRPZ (getNGRPZ(nwgmax, ngmax, num_water_tracer, rspec)) + .params_NWELZ (155 + num_tracers, 122 + 2 * num_tracers, 130 + nxwelz_tracer_shift, 3) // n{isxz}welz: number of data elements per well in {ISXZ}WELL + .params_NCON (25, 41, 58 + 5*num_tracers) // n{isx}conz: number of data elements per completion in ICON + .params_GRPZ (getNGRPZ(nwgmax, ngmax, num_tracers, rspec)) .aquiferDimensions (inferAquiferDimensions(es, sched[lookup_step])) .stepParam (num_solver_steps, report_step) .tuningParam (getTuningPars(sched[lookup_step].tuning())) .liftOptParam (getLiftOptPar(sched, report_step, lookup_step)) - .wellSegDimensions (getWellSegDims(num_water_tracer, rspec, sched, report_step, lookup_step)) + .wellSegDimensions (getWellSegDims(num_tracers, rspec, sched, report_step, lookup_step)) .regionDimensions (getRegDims(tdim, rdim)) .ngroups ({ ngmax }) .params_NGCTRL (GroupControl(sched, report_step, lookup_step)) - .variousParam (201802, 100) // Output should be compatible with Eclipse 100, 2017.02 version. + .variousParam (201802, 100, num_tracers) // Output should be compatible with Eclipse 100, 2017.02 version. .udqParam_1 (getUdqParam(rspec, sched, report_step, lookup_step)) .actionParam (getActionParam(rspec, acts, report_step)) .variousUDQ_ACTIONXParam() diff --git a/opm/output/eclipse/CreateLogiHead.cpp b/opm/output/eclipse/CreateLogiHead.cpp index 7017bd83ecd..a54d43cfaf9 100644 --- a/opm/output/eclipse/CreateLogiHead.cpp +++ b/opm/output/eclipse/CreateLogiHead.cpp @@ -54,7 +54,7 @@ createLogiHead(const EclipseState& es) tabMgr.getPvcdoTable().empty()); const auto lh = LogiHEAD{} - .variousParam(false, false, wsd.maxSegmentedWells(), hystPar.active()) + .variousParam(false, false, wsd.maxSegmentedWells(), hystPar.active(), rspec.temp()) .pvtModel(pvt) .network(rspec.networkDimensions().maxNONodes()) ; diff --git a/opm/output/eclipse/InteHEAD.cpp b/opm/output/eclipse/InteHEAD.cpp index 1321c7af1ad..a3afae4c74f 100644 --- a/opm/output/eclipse/InteHEAD.cpp +++ b/opm/output/eclipse/InteHEAD.cpp @@ -680,7 +680,8 @@ Opm::RestartIO::InteHEAD::tuningParam(const TuningPar& tunpar) Opm::RestartIO::InteHEAD& Opm::RestartIO::InteHEAD::variousParam(const int version, - const int iprog) + const int iprog, + const int num_tracers) { this->data_[VERSION] = version; this->data_[IPROG] = iprog; @@ -702,6 +703,8 @@ Opm::RestartIO::InteHEAD::variousParam(const int version, // ih_200: Usage unknown, value fixed across reference cases. this->data_[ih_200] = 1; + // NSTRA2 = 240 + this->data_[NSTRA2] = 2 + num_tracers; return *this; } diff --git a/opm/output/eclipse/InteHEAD.hpp b/opm/output/eclipse/InteHEAD.hpp index 29a6ffe10eb..ab44e72c14a 100644 --- a/opm/output/eclipse/InteHEAD.hpp +++ b/opm/output/eclipse/InteHEAD.hpp @@ -227,7 +227,7 @@ namespace Opm { namespace RestartIO { InteHEAD& stepParam(const int tstep, const int report_step); InteHEAD& tuningParam(const TuningPar& tunpar); - InteHEAD& variousParam(const int version, const int iprog); + InteHEAD& variousParam(const int version, const int iprog, const int num_tracers); InteHEAD& wellSegDimensions(const WellSegDims& wsdim); InteHEAD& activeNetwork(const ActiveNetwork& actntwrk); InteHEAD& networkDimensions(const NetworkDims& nwdim); diff --git a/opm/output/eclipse/LogiHEAD.cpp b/opm/output/eclipse/LogiHEAD.cpp index 995e18b6fb6..07a1c937384 100644 --- a/opm/output/eclipse/LogiHEAD.cpp +++ b/opm/output/eclipse/LogiHEAD.cpp @@ -71,7 +71,7 @@ lh_028 = 28 , // FALSE lh_029 = 29 , // FALSE lh_030 = 30 , // FALSE Flag for coalbed methane (ECLIPSE 100) lh_031 = 31 , // TRUE -lh_032 = 32 , // FALSE +lh_032 = 32 , // FALSE Flag for TEMP option (ECLIPSE 100) lh_033 = 33 , // FALSE lh_034 = 34 , // FALSE lh_035 = 35 , // FALSE @@ -82,7 +82,7 @@ lh_036 = 36 , // FALSE // Flag to signify constant oil compressibility ConstCo = VI::logihead::ConstCo, -lh_039 = 39 , // FALSE +lh_039 = 39 , // FALSE Flag for TEMP option (ECLIPSE 100) lh_040 = 40 , // FALSE lh_041 = 41 , // FALSE lh_042 = 42 , // FALSE @@ -187,13 +187,16 @@ Opm::RestartIO::LogiHEAD:: variousParam(const bool e300_radial, const bool e100_radial, const int nswlmx, - const bool enableHyster) + const bool enableHyster, + const bool hasTemp) { this -> data_[E300Radial] = e300_radial; this -> data_[E100Radial] = e100_radial; this -> data_[Hyster] = enableHyster; this -> data_[HasMSWells] = nswlmx >= 1; // True if MS Wells exist. + this -> data_[32] = hasTemp; + this -> data_[39] = hasTemp; return *this; } diff --git a/opm/output/eclipse/LogiHEAD.hpp b/opm/output/eclipse/LogiHEAD.hpp index 9b5d08749a6..1e6415e0d1d 100644 --- a/opm/output/eclipse/LogiHEAD.hpp +++ b/opm/output/eclipse/LogiHEAD.hpp @@ -81,10 +81,11 @@ namespace Opm { namespace RestartIO { LogiHEAD& operator=(LogiHEAD&& rhs) = default; LogiHEAD& variousParam(const bool e300_radial, - const bool e100_radial, - const int nswlmx, - const bool enableHyster - ); + const bool e100_radial, + const int nswlmx, + const bool enableHyster, + const bool hasTemp + ); /// Assign PVT model characteristics. /// diff --git a/opm/output/eclipse/RestartIO.cpp b/opm/output/eclipse/RestartIO.cpp index c500407e895..f171f32a889 100644 --- a/opm/output/eclipse/RestartIO.cpp +++ b/opm/output/eclipse/RestartIO.cpp @@ -534,6 +534,7 @@ namespace { OutputVectorInt writeVectorI) { for (const auto& vector : vectors) { + if (vector=="TEMP") continue; // Write this together with the tracers value.solution.at(vector).visit(VisitorOverloadSet{ MonoThrowHandler(fmt::format("{} does not have an associate value", vector)), [&vector,&writeVectorF](const std::vector& v) @@ -647,6 +648,16 @@ namespace { EclIO::OutputStream::Restart& rstFile) { for (const auto& [tracer_rst_name, vector] : value.solution) { + if (tracer_rst_name == "TEMP") { + std::vector zatracer; + zatracer.push_back("TEMP"); + zatracer.push_back(unit_system.name(UnitSystem::measure::temperature)); + rstFile.write("ZATRACER", zatracer); + const auto& data = vector.data(); + rstFile.write("TEMP", std::vector {data.begin(), data.end()}); + continue; + } + if (vector.target != data::TargetType::RESTART_TRACER_SOLUTION) continue; diff --git a/opm/output/eclipse/WriteInit.cpp b/opm/output/eclipse/WriteInit.cpp index 4b4bcfb1b9a..2d61683ee7f 100644 --- a/opm/output/eclipse/WriteInit.cpp +++ b/opm/output/eclipse/WriteInit.cpp @@ -285,7 +285,7 @@ namespace { const auto& hystPar = rspec.hysterPar(); const auto lh = ::Opm::RestartIO::LogiHEAD{} - .variousParam(false, false, wsd.maxSegmentedWells(), hystPar.active()) + .variousParam(false, false, wsd.maxSegmentedWells(), hystPar.active(), rspec.temp()) .pvtModel(pvtFlags(rspec, es.getTableManager())) .saturationFunction(satfuncFlags(rspec)) ; From d3064cadc31513fdc5337f000cc057c520705d4e Mon Sep 17 00:00:00 2001 From: Vegard Kippe Date: Fri, 13 Dec 2024 11:20:04 +0100 Subject: [PATCH 4/8] Update XWEL array with TEMP and HC tracer info --- opm/output/eclipse/AggregateWellData.cpp | 117 ++++++++++++----------- 1 file changed, 62 insertions(+), 55 deletions(-) diff --git a/opm/output/eclipse/AggregateWellData.cpp b/opm/output/eclipse/AggregateWellData.cpp index ca4faae6daf..a1306f848a7 100644 --- a/opm/output/eclipse/AggregateWellData.cpp +++ b/opm/output/eclipse/AggregateWellData.cpp @@ -1083,9 +1083,9 @@ namespace { SWellArray& sWell, const bool isTemp = false) { + auto output_index = static_cast(VI::SWell::index::TracerOffset); // Temperature tracer is first, if present - const std::size_t tempOffset = isTemp ? 1 : 0; - auto output_index = tempOffset + static_cast(VI::SWell::index::TracerOffset); + if (isTemp) sWell[output_index++] = smry.get_well_var(wname, "WTICHEA", 0.0); for (const auto& tracer : tracers) { if (tracer.phase == Opm::Phase::WATER) { @@ -1100,17 +1100,6 @@ namespace { } } - template - void assignTempData(const std::string& wname, - const Opm::SummaryState& smry, - SWellArray& sWell) - { - // TEMP is the first tracer - auto output_index = static_cast(VI::SWell::index::TracerOffset); - sWell[output_index] = smry.get_well_var(wname, "WTICHEA", 0.0); - } - - template void staticContrib(const Opm::Well& well, const Opm::GasLiftOpt& glo, @@ -1153,9 +1142,7 @@ namespace { assignEconomicLimits(well, swprop, sWell); assignWellTest(well.name(), sched, wtest_state, sim_step, swprop, sWell); - const auto isTemp = sched.runspec().temp(); - if (isTemp) assignTempData(well.name(), smry, sWell); - assignTracerData(tracers, smry, well.name(), sWell, isTemp); + assignTracerData(tracers, smry, well.name(), sWell, sched.runspec().temp()); assignBhpVfpAdjustment(well, swprop, sWell); } } // SWell @@ -1362,7 +1349,8 @@ namespace { const Opm::Tracers& tracer_dims, const Opm::SummaryState& smry, const Opm::Well& well, - XWellArray& xWell) + XWellArray& xWell, + const bool isTemp) { if (tracers.empty() || tracer_dims.water_tracers() == 0) return; @@ -1370,55 +1358,73 @@ namespace { using Ix = ::Opm::RestartIO::Helpers::VectorItems::XWell::index; std::fill(xWell.begin() + Ix::TracerOffset, xWell.end(), 0); + // For each vector in rate, prod_total, inj_total, inj_conc, prod_conc: + // TEMP (if present), then each tracer in definition order (TRACER) [free then solution conc for HC tracers] - for (std::size_t tracer_index=0; tracer_index < tracers.size(); tracer_index++) { - const auto& tracer = tracers[tracer_index]; - std::size_t output_index = Ix::TracerOffset + tracer_index; - if (well.isInjector()) { - const auto& wtir = smry.get_well_var(well.name(), fmt::format("WTIR{}", tracer.name), 0); - xWell[output_index] = -wtir; - } else { - const auto& wtpr = smry.get_well_var(well.name(), fmt::format("WTPR{}", tracer.name), 0); - xWell[output_index] = wtpr; + auto output_index = static_cast(Ix::TracerOffset); + // Rates + if (well.isInjector()) { + if (isTemp) xWell[output_index++] = -smry.get_well_var(well.name(), "WTIRHEA", 0); + for (const auto& tracer : tracers) { + if (tracer.phase == Opm::Phase::WATER) { + xWell[output_index++] = -smry.get_well_var(well.name(), fmt::format("WTIR{}", tracer.name), 0); + } else { + xWell[output_index++] = -smry.get_well_var(well.name(), fmt::format("WTIRF{}", tracer.name), 0); + xWell[output_index++] = -smry.get_well_var(well.name(), fmt::format("WTIRS{}", tracer.name), 0); + } + } + } else { + if (isTemp) xWell[output_index++] = smry.get_well_var(well.name(), "WTPRHEA", 0); + for (const auto& tracer : tracers) { + if (tracer.phase == Opm::Phase::WATER) { + xWell[output_index++] = smry.get_well_var(well.name(), fmt::format("WTPR{}", tracer.name), 0); + } else { + xWell[output_index++] = smry.get_well_var(well.name(), fmt::format("WTPRF{}", tracer.name), 0); + xWell[output_index++] = smry.get_well_var(well.name(), fmt::format("WTPRS{}", tracer.name), 0); + } } } - - for (std::size_t tracer_index=0; tracer_index < tracers.size(); tracer_index++) { - const auto& tracer = tracers[tracer_index]; - std::size_t output_index = Ix::TracerOffset + tracer_dims.water_tracers() + tracer_index; - if (well.isProducer()) { - const auto& wtpr = smry.get_well_var(well.name(), fmt::format("WTPT{}", tracer.name), 0); - xWell[output_index] = wtpr; + // Production totals + if (isTemp) xWell[output_index++] = smry.get_well_var(well.name(), "WTPTHEA", 0); + for (const auto& tracer : tracers) { + if (tracer.phase == Opm::Phase::WATER) { + xWell[output_index++] = smry.get_well_var(well.name(), fmt::format("WTPT{}", tracer.name), 0); + } else { + xWell[output_index++] = smry.get_well_var(well.name(), fmt::format("WTPTF{}", tracer.name), 0); + xWell[output_index++] = smry.get_well_var(well.name(), fmt::format("WTPTS{}", tracer.name), 0); } } - for (std::size_t tracer_index=0; tracer_index < tracers.size(); tracer_index++) { - const auto& tracer = tracers[tracer_index]; - std::size_t output_index = Ix::TracerOffset + 2*tracer_dims.water_tracers() + tracer_index; - if (well.isInjector()) { - const auto& wtir = smry.get_well_var(well.name(), fmt::format("WTIT{}", tracer.name), 0); - xWell[output_index] = wtir; + // Injection totals + if (isTemp) xWell[output_index++] = smry.get_well_var(well.name(), "WTITHEA", 0); + for (const auto& tracer : tracers) { + if (tracer.phase == Opm::Phase::WATER) { + xWell[output_index++] = smry.get_well_var(well.name(), fmt::format("WTIT{}", tracer.name), 0); + } else { + xWell[output_index++] = smry.get_well_var(well.name(), fmt::format("WTITF{}", tracer.name), 0); + xWell[output_index++] = smry.get_well_var(well.name(), fmt::format("WTITS{}", tracer.name), 0); } } - for (std::size_t n=0; n < 2; n++) { - for (std::size_t tracer_index=0; tracer_index < tracers.size(); tracer_index++) { - const auto& tracer = tracers[tracer_index]; - std::size_t output_index = Ix::TracerOffset + (3 + n)*tracer_dims.water_tracers() + tracer_index; - const auto& wtic = smry.get_well_var(well.name(), fmt::format("WTIC{}", tracer.name), 0); - const auto& wtpc = smry.get_well_var(well.name(), fmt::format("WTPC{}", tracer.name), 0); - - if (std::abs(wtic) > 0) - xWell[output_index] = wtic; - else - xWell[output_index] = wtpc; + // inj and prod conc + const bool injector = well.isInjector(); + for (std::size_t n=0; n < 2; ++n) { + if (isTemp) { + xWell[output_index++] = injector ? smry.get_well_var(well.name(), "WTICHEA", 0) : smry.get_well_var(well.name(), "WTPCHEA", 0); + } + for (const auto& tracer : tracers) { + if (tracer.phase == Opm::Phase::WATER) { + xWell[output_index++] = injector ? smry.get_well_var(well.name(), fmt::format("WTIC{}", tracer.name), 0) : smry.get_well_var(well.name(), fmt::format("WTPC{}", tracer.name), 0); + } else { + xWell[output_index++] = injector ? smry.get_well_var(well.name(), fmt::format("WTICF{}", tracer.name), 0) : smry.get_well_var(well.name(), fmt::format("WTPCF{}", tracer.name), 0); + xWell[output_index++] = injector ? smry.get_well_var(well.name(), fmt::format("WTICS{}", tracer.name), 0) : smry.get_well_var(well.name(), fmt::format("WTPCS{}", tracer.name), 0); + } } } - std::size_t output_index = Ix::TracerOffset + 5*tracer_dims.water_tracers(); - xWell[output_index] = 0; - xWell[output_index + 1] = 0; + xWell[output_index++] = 0; + xWell[output_index++] = 0; } template @@ -1426,6 +1432,7 @@ namespace { const Opm::TracerConfig& tracers, const Opm::Tracers& tracer_dims, const ::Opm::SummaryState& smry, + const bool isTemp, XWellArray& xWell) { if (well.isProducer()) { @@ -1455,7 +1462,7 @@ namespace { } } assignCumulatives(well.name(), smry, xWell); - assignTracerData(tracers, tracer_dims, smry, well, xWell); + assignTracerData(tracers, tracer_dims, smry, well, xWell, isTemp); } } // XWell @@ -1620,6 +1627,6 @@ captureDynamicWellData(const Opm::Schedule& sched, { auto xwell = this->xWell_[wellID]; - XWell::dynamicContrib(well, tracers, sched.runspec().tracers(), smry, xwell); + XWell::dynamicContrib(well, tracers, sched.runspec().tracers(), smry, sched.runspec().temp(), xwell); }); } From c5962990b8560eb7cf07e7608ecf11739727ffcb Mon Sep 17 00:00:00 2001 From: Vegard Kippe Date: Mon, 16 Dec 2024 12:09:48 +0100 Subject: [PATCH 5/8] Compatibility fixes --- opm/output/eclipse/AggregateWellData.cpp | 2 +- opm/output/eclipse/CreateInteHead.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/opm/output/eclipse/AggregateWellData.cpp b/opm/output/eclipse/AggregateWellData.cpp index a1306f848a7..322713cb456 100644 --- a/opm/output/eclipse/AggregateWellData.cpp +++ b/opm/output/eclipse/AggregateWellData.cpp @@ -1361,7 +1361,7 @@ namespace { // For each vector in rate, prod_total, inj_total, inj_conc, prod_conc: // TEMP (if present), then each tracer in definition order (TRACER) [free then solution conc for HC tracers] - auto output_index = static_cast(Ix::TracerOffset); + auto output_index = static_cast(Ix::TracerOffset) + 1; // +1 since late 2022 // Rates if (well.isInjector()) { if (isTemp) xWell[output_index++] = -smry.get_well_var(well.name(), "WTIRHEA", 0); diff --git a/opm/output/eclipse/CreateInteHead.cpp b/opm/output/eclipse/CreateInteHead.cpp index 5dd0633d6db..eb15166200b 100644 --- a/opm/output/eclipse/CreateInteHead.cpp +++ b/opm/output/eclipse/CreateInteHead.cpp @@ -590,7 +590,7 @@ createInteHead(const EclipseState& es, // across a range of reference cases, but are not guaranteed to be // universally valid. .drsdt(sched, lookup_step) - .params_NWELZ (155 + num_tracers, 122 + 2 * num_tracers, 130 + nxwelz_tracer_shift, 3) // n{isxz}welz: number of data elements per well in {ISXZ}WELL + .params_NWELZ (154 + num_tracers, 122 + 2 * num_tracers, 130 + nxwelz_tracer_shift, 3) // n{isxz}welz: number of data elements per well in {ISXZ}WELL .params_NCON (25, 41, 58 + 5*num_tracers) // n{isx}conz: number of data elements per completion in ICON .params_GRPZ (getNGRPZ(nwgmax, ngmax, num_tracers, rspec)) .aquiferDimensions (inferAquiferDimensions(es, sched[lookup_step])) From ff450508cd34e3d19146beaa49b5afe45453b574 Mon Sep 17 00:00:00 2001 From: Vegard Kippe Date: Mon, 16 Dec 2024 12:39:59 +0100 Subject: [PATCH 6/8] Update tests --- opm/io/eclipse/rst/well.cpp | 4 ++-- tests/test_AggregateWellData.cpp | 2 +- tests/test_InteHEAD.cpp | 5 +++-- tests/test_LogiHEAD.cpp | 3 ++- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/opm/io/eclipse/rst/well.cpp b/opm/io/eclipse/rst/well.cpp index ea49f3cc021..7a0dc81ac6a 100644 --- a/opm/io/eclipse/rst/well.cpp +++ b/opm/io/eclipse/rst/well.cpp @@ -181,8 +181,8 @@ Opm::RestartIO::RstWell::RstWell(const UnitSystem& unit_system, water_void_rate( unit_system.to_si(M::liquid_surface_volume, xwel[VI::XWell::WatVoidPrRate])), gas_void_rate( unit_system.to_si(M::gas_surface_volume, xwel[VI::XWell::GasVoidPrRate])) { - // For E100 it appears that +1 instead of -1 is written for group_controllable_flag when the - // group control is aactive, so using this to correct active_control (where ind.ctrl. is written) + // For E100 it appears that +1 instead of -1 is written for group_controllable_flag when the + // group control is active, so using this to correct active_control (where ind.ctrl. is written) if (group_controllable_flag > 0) { active_control = VI::IWell::Value::WellCtrlMode::Group; } diff --git a/tests/test_AggregateWellData.cpp b/tests/test_AggregateWellData.cpp index 12cac282a08..f392087e49a 100644 --- a/tests/test_AggregateWellData.cpp +++ b/tests/test_AggregateWellData.cpp @@ -70,7 +70,7 @@ namespace { struct MockIH { explicit MockIH(const int numWells, - const int iwelPerWell = 155, // E100 + const int iwelPerWell = 154, // E100 const int swelPerWell = 122, // E100 const int xwelPerWell = 130, // E100 const int zwelPerWell = 3); // E100 diff --git a/tests/test_InteHEAD.cpp b/tests/test_InteHEAD.cpp index 27f77f2cde7..30a3b74d100 100644 --- a/tests/test_InteHEAD.cpp +++ b/tests/test_InteHEAD.cpp @@ -422,7 +422,7 @@ BOOST_AUTO_TEST_CASE(Tuning_param) BOOST_AUTO_TEST_CASE(Various_Parameters) { const auto ih = Opm::RestartIO::InteHEAD{} - .variousParam(2015, 100); + .variousParam(2015, 100, 0); const auto& v = ih.data(); @@ -634,6 +634,7 @@ BOOST_AUTO_TEST_CASE(TestHeader) const auto mxwpit = 6; const auto version = 2015; const auto iprog = 100; + const auto ntracers = 0; const auto nsegwl = 3; const auto nswlmx = 4; const auto nsegmx = 5; @@ -667,7 +668,7 @@ BOOST_AUTO_TEST_CASE(TestHeader) .aquiferDimensions(aqudims) .stepParam(tstep, report_step) .tuningParam({newtmx, newtmn, litmax, litmin, mxwsit, mxwpit, 0}) - .variousParam(version, iprog) + .variousParam(version, iprog, ntracers) .wellSegDimensions({nsegwl, nswlmx, nsegmx, nlbrmx, nisegz, nrsegz, nilbrz}) .regionDimensions({ntfip, nmfipr, 0,0,0}) .ngroups({ngroup}); diff --git a/tests/test_LogiHEAD.cpp b/tests/test_LogiHEAD.cpp index 037bbd69429..fcc4b2bba12 100644 --- a/tests/test_LogiHEAD.cpp +++ b/tests/test_LogiHEAD.cpp @@ -33,9 +33,10 @@ BOOST_AUTO_TEST_CASE(Radial_Settings_and_Init) const auto e300_radial = false; const auto e100_radial = true; const auto enableHyster = true; + const auto isTemp = false; const auto lh = Opm::RestartIO::LogiHEAD{} - .variousParam(e300_radial, e100_radial, 4, enableHyster); + .variousParam(e300_radial, e100_radial, 4, enableHyster, isTemp); const auto& v = lh.data(); From cb0404ccd231c7d778ba024fcdd9dd56d8faa291 Mon Sep 17 00:00:00 2001 From: Vegard Kippe Date: Mon, 16 Dec 2024 18:38:05 +0100 Subject: [PATCH 7/8] Default new parameter to avoid breaking build in opm-upscaling --- opm/input/eclipse/share/keywords/000_Eclipse100/G/GLIFTOPT | 1 + opm/output/eclipse/CreateInteHead.cpp | 2 +- opm/output/eclipse/InteHEAD.hpp | 2 +- opm/output/eclipse/LogiHEAD.hpp | 2 +- tests/test_AggregateWellData.cpp | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/opm/input/eclipse/share/keywords/000_Eclipse100/G/GLIFTOPT b/opm/input/eclipse/share/keywords/000_Eclipse100/G/GLIFTOPT index dfb14715f3d..250287c804b 100644 --- a/opm/input/eclipse/share/keywords/000_Eclipse100/G/GLIFTOPT +++ b/opm/input/eclipse/share/keywords/000_Eclipse100/G/GLIFTOPT @@ -3,6 +3,7 @@ "sections": [ "SCHEDULE" ], + "requires" : ["LIFTOPT"], "items": [ { "name": "GROUP_NAME", diff --git a/opm/output/eclipse/CreateInteHead.cpp b/opm/output/eclipse/CreateInteHead.cpp index eb15166200b..5dd0633d6db 100644 --- a/opm/output/eclipse/CreateInteHead.cpp +++ b/opm/output/eclipse/CreateInteHead.cpp @@ -590,7 +590,7 @@ createInteHead(const EclipseState& es, // across a range of reference cases, but are not guaranteed to be // universally valid. .drsdt(sched, lookup_step) - .params_NWELZ (154 + num_tracers, 122 + 2 * num_tracers, 130 + nxwelz_tracer_shift, 3) // n{isxz}welz: number of data elements per well in {ISXZ}WELL + .params_NWELZ (155 + num_tracers, 122 + 2 * num_tracers, 130 + nxwelz_tracer_shift, 3) // n{isxz}welz: number of data elements per well in {ISXZ}WELL .params_NCON (25, 41, 58 + 5*num_tracers) // n{isx}conz: number of data elements per completion in ICON .params_GRPZ (getNGRPZ(nwgmax, ngmax, num_tracers, rspec)) .aquiferDimensions (inferAquiferDimensions(es, sched[lookup_step])) diff --git a/opm/output/eclipse/InteHEAD.hpp b/opm/output/eclipse/InteHEAD.hpp index ab44e72c14a..ec75b82489a 100644 --- a/opm/output/eclipse/InteHEAD.hpp +++ b/opm/output/eclipse/InteHEAD.hpp @@ -227,7 +227,7 @@ namespace Opm { namespace RestartIO { InteHEAD& stepParam(const int tstep, const int report_step); InteHEAD& tuningParam(const TuningPar& tunpar); - InteHEAD& variousParam(const int version, const int iprog, const int num_tracers); + InteHEAD& variousParam(const int version, const int iprog, const int num_tracers = 0); InteHEAD& wellSegDimensions(const WellSegDims& wsdim); InteHEAD& activeNetwork(const ActiveNetwork& actntwrk); InteHEAD& networkDimensions(const NetworkDims& nwdim); diff --git a/opm/output/eclipse/LogiHEAD.hpp b/opm/output/eclipse/LogiHEAD.hpp index 1e6415e0d1d..de07edd75db 100644 --- a/opm/output/eclipse/LogiHEAD.hpp +++ b/opm/output/eclipse/LogiHEAD.hpp @@ -84,7 +84,7 @@ namespace Opm { namespace RestartIO { const bool e100_radial, const int nswlmx, const bool enableHyster, - const bool hasTemp + const bool hasTemp = false ); /// Assign PVT model characteristics. diff --git a/tests/test_AggregateWellData.cpp b/tests/test_AggregateWellData.cpp index f392087e49a..12cac282a08 100644 --- a/tests/test_AggregateWellData.cpp +++ b/tests/test_AggregateWellData.cpp @@ -70,7 +70,7 @@ namespace { struct MockIH { explicit MockIH(const int numWells, - const int iwelPerWell = 154, // E100 + const int iwelPerWell = 155, // E100 const int swelPerWell = 122, // E100 const int xwelPerWell = 130, // E100 const int zwelPerWell = 3); // E100 From e4c42a4798d97d29439ca22530edf41bbe5cb610 Mon Sep 17 00:00:00 2001 From: Vegard Kippe Date: Tue, 17 Dec 2024 00:43:35 +0100 Subject: [PATCH 8/8] Fix and clean.. --- opm/input/eclipse/Schedule/Well/Well.cpp | 1 - opm/output/eclipse/AggregateWellData.cpp | 2 +- opm/output/eclipse/CreateInteHead.cpp | 18 ++++++++++-------- opm/output/eclipse/InteHEAD.cpp | 4 ++-- opm/output/eclipse/VectorItems/well.hpp | 2 +- 5 files changed, 14 insertions(+), 13 deletions(-) diff --git a/opm/input/eclipse/Schedule/Well/Well.cpp b/opm/input/eclipse/Schedule/Well/Well.cpp index 64c93b0c829..a23bad237df 100644 --- a/opm/input/eclipse/Schedule/Well/Well.cpp +++ b/opm/input/eclipse/Schedule/Well/Well.cpp @@ -155,7 +155,6 @@ Opm::Well::ProducerCMode producer_cmode_from_int(const int pmode) case CModeVal::BHP: return Opm::Well::ProducerCMode::BHP; } - // Return BHP as default instead, since -10 might be written for some unused wells..?? throw std::invalid_argument { fmt::format("Cannot convert integer value {} to producer control mode", pmode) }; diff --git a/opm/output/eclipse/AggregateWellData.cpp b/opm/output/eclipse/AggregateWellData.cpp index 322713cb456..a1306f848a7 100644 --- a/opm/output/eclipse/AggregateWellData.cpp +++ b/opm/output/eclipse/AggregateWellData.cpp @@ -1361,7 +1361,7 @@ namespace { // For each vector in rate, prod_total, inj_total, inj_conc, prod_conc: // TEMP (if present), then each tracer in definition order (TRACER) [free then solution conc for HC tracers] - auto output_index = static_cast(Ix::TracerOffset) + 1; // +1 since late 2022 + auto output_index = static_cast(Ix::TracerOffset); // Rates if (well.isInjector()) { if (isTemp) xWell[output_index++] = -smry.get_well_var(well.name(), "WTIRHEA", 0); diff --git a/opm/output/eclipse/CreateInteHead.cpp b/opm/output/eclipse/CreateInteHead.cpp index 5dd0633d6db..e658448aa00 100644 --- a/opm/output/eclipse/CreateInteHead.cpp +++ b/opm/output/eclipse/CreateInteHead.cpp @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -275,7 +276,7 @@ namespace { const int nigrpz = 97 + std::max(nwgmax, ngmax); const int nsgrpz = 112; - const int nxgrpz = 180 + 4*num_tracers + 1; + const int nxgrpz = 180 + 4*num_tracers + 1; // +1 since late 2022 const int nzgrpz = 5; return {{ @@ -575,8 +576,9 @@ createInteHead(const EclipseState& es, const auto& rckcfg = es.getSimulationConfig().rock_config(); const auto& tracers = es.runspec().tracers(); // TEMP is a tracer, oil&gas tracers have both free and solution parts. - const auto num_tracers = tracers.water_tracers() + 2*(tracers.oil_tracers() + tracers.gas_tracers()) + (es.runspec().temp() ? 1 : 0); - int nxwelz_tracer_shift = num_tracers*5 + 2 * (num_tracers > 0) + 1; + const auto num_tracers = tracers.water_tracers() + tracers.oil_tracers() + tracers.gas_tracers() + (es.runspec().temp() ? 1 : 0); + const auto num_tracer_comps = num_tracers + tracers.oil_tracers() + tracers.gas_tracers(); + int nxwelz_tracer_shift = num_tracer_comps*5 + 2 * (num_tracers > 0); const auto ih = InteHEAD{} .dimensions (grid.getNXYZ()) @@ -590,18 +592,18 @@ createInteHead(const EclipseState& es, // across a range of reference cases, but are not guaranteed to be // universally valid. .drsdt(sched, lookup_step) - .params_NWELZ (155 + num_tracers, 122 + 2 * num_tracers, 130 + nxwelz_tracer_shift, 3) // n{isxz}welz: number of data elements per well in {ISXZ}WELL - .params_NCON (25, 41, 58 + 5*num_tracers) // n{isx}conz: number of data elements per completion in ICON - .params_GRPZ (getNGRPZ(nwgmax, ngmax, num_tracers, rspec)) + .params_NWELZ (155 + num_tracers, 122 + 2 * num_tracer_comps, VectorItems::XWell::index::TracerOffset + nxwelz_tracer_shift, 3) // n{isxz}welz: number of data elements per well in {ISXZ}WELL + .params_NCON (25, 41, 58 + 5*num_tracer_comps) // n{isx}conz: number of data elements per completion in ICON + .params_GRPZ (getNGRPZ(nwgmax, ngmax, num_tracer_comps, rspec)) .aquiferDimensions (inferAquiferDimensions(es, sched[lookup_step])) .stepParam (num_solver_steps, report_step) .tuningParam (getTuningPars(sched[lookup_step].tuning())) .liftOptParam (getLiftOptPar(sched, report_step, lookup_step)) - .wellSegDimensions (getWellSegDims(num_tracers, rspec, sched, report_step, lookup_step)) + .wellSegDimensions (getWellSegDims(num_tracer_comps, rspec, sched, report_step, lookup_step)) .regionDimensions (getRegDims(tdim, rdim)) .ngroups ({ ngmax }) .params_NGCTRL (GroupControl(sched, report_step, lookup_step)) - .variousParam (201802, 100, num_tracers) // Output should be compatible with Eclipse 100, 2017.02 version. + .variousParam (201802, 100, num_tracer_comps) // Output should be compatible with Eclipse 100, 2022.04 version. .udqParam_1 (getUdqParam(rspec, sched, report_step, lookup_step)) .actionParam (getActionParam(rspec, acts, report_step)) .variousUDQ_ACTIONXParam() diff --git a/opm/output/eclipse/InteHEAD.cpp b/opm/output/eclipse/InteHEAD.cpp index a3afae4c74f..c2a86ac621c 100644 --- a/opm/output/eclipse/InteHEAD.cpp +++ b/opm/output/eclipse/InteHEAD.cpp @@ -681,7 +681,7 @@ Opm::RestartIO::InteHEAD::tuningParam(const TuningPar& tunpar) Opm::RestartIO::InteHEAD& Opm::RestartIO::InteHEAD::variousParam(const int version, const int iprog, - const int num_tracers) + const int num_tracer_comps) { this->data_[VERSION] = version; this->data_[IPROG] = iprog; @@ -704,7 +704,7 @@ Opm::RestartIO::InteHEAD::variousParam(const int version, this->data_[ih_200] = 1; // NSTRA2 = 240 - this->data_[NSTRA2] = 2 + num_tracers; + this->data_[NSTRA2] = 1 + (num_tracer_comps > 0) + num_tracer_comps; return *this; } diff --git a/opm/output/eclipse/VectorItems/well.hpp b/opm/output/eclipse/VectorItems/well.hpp index aee7d1a2c72..1e9a3d1b959 100644 --- a/opm/output/eclipse/VectorItems/well.hpp +++ b/opm/output/eclipse/VectorItems/well.hpp @@ -405,7 +405,7 @@ namespace Opm { namespace RestartIO { namespace Helpers { namespace VectorItems WatVoidPrRate = 122, // Well's voidage production rate GasVoidPrRate = 123, // Well's voidage production rate - TracerOffset = 130, // Tracer data start at this index + TracerOffset = 131, // Tracer data start at this index (+1 since late 2022) }; } // XWell