diff --git a/opm/input/eclipse/Schedule/Well/Well.hpp b/opm/input/eclipse/Schedule/Well/Well.hpp index 4fc001d23..2c08b0cb9 100644 --- a/opm/input/eclipse/Schedule/Well/Well.hpp +++ b/opm/input/eclipse/Schedule/Well/Well.hpp @@ -228,7 +228,6 @@ public: InjectorCMode cmode = InjectorCMode::CMODE_UNDEFINED; double surface_rate; double reservoir_rate; - double temperature; int vfp_table_number; bool prediction_mode; double rs_rv_inj; @@ -253,7 +252,6 @@ public: double bhp_hist_limit = 0.0; double thp_hist_limit = 0.0; - double temperature; double BHPH; double THPH; int VFPTableNumber; @@ -315,7 +313,6 @@ public: serializer(THPTarget); serializer(bhp_hist_limit); serializer(thp_hist_limit); - serializer(temperature); serializer(BHPH); serializer(THPH); serializer(VFPTableNumber); @@ -638,6 +635,7 @@ public: bool segmented_density_calculation() const { return true; } double alq_value() const; double temperature() const; + void setWellTemperature(const double temp); bool hasInjected( ) const; bool hasProduced( ) const; bool updateHasInjected( ); @@ -690,6 +688,7 @@ public: serializer(segments); serializer(wvfpexp); serializer(m_pavg); + serializer(well_temperature); } private: @@ -734,6 +733,7 @@ private: std::shared_ptr wvfpexp; Status status; PAvg m_pavg; + double well_temperature; }; std::ostream& operator<<( std::ostream&, const Well::WellInjectionProperties& ); diff --git a/src/opm/input/eclipse/Schedule/KeywordHandlers.cpp b/src/opm/input/eclipse/Schedule/KeywordHandlers.cpp index bf3b134bd..6d1440acb 100644 --- a/src/opm/input/eclipse/Schedule/KeywordHandlers.cpp +++ b/src/opm/input/eclipse/Schedule/KeywordHandlers.cpp @@ -1653,19 +1653,11 @@ Well{0} entered with disallowed 'FIELD' parent group: const double temp = record.getItem("TEMPERATURE").getSIDouble(0); for (const auto& well_name : well_names) { - // TODO: Is this the right approach? Setting the well temperature only - // has an effect on injectors, but specifying it for producers won't hurt - // and wells can also switch their injector/producer status. Note that - // modifying the injector properties for producer wells currently leads - // to a very weird segmentation fault downstream. For now, let's take the - // water route. const auto& well = this->getWell(well_name, handlerContext.currentStep); - const double current_temp = well.getInjectionProperties().temperature; - if (current_temp != temp && !well.isProducer()) { + const double current_temp = !well.isProducer()? well.temperature(): 0.0; + if (current_temp != temp) { auto well2 = this->snapshots.back().wells( well_name ); - auto inj = std::make_shared(well2.getInjectionProperties()); - inj->temperature = temp; - well2.updateInjection(inj); + well2.setWellTemperature(temp); this->snapshots.back().wells.update( std::move(well2) ); } } @@ -1983,20 +1975,11 @@ Well{0} entered with disallowed 'FIELD' parent group: double temp = record.getItem("TEMP").getSIDouble(0); for (const auto& well_name : well_names) { - // TODO: Is this the right approach? Setting the well temperature only - // has an effect on injectors, but specifying it for producers won't hurt - // and wells can also switch their injector/producer status. Note that - // modifying the injector properties for producer wells currently leads - // to a very weird segmentation fault downstream. For now, let's take the - // water route. - const auto& well = this->getWell(well_name, handlerContext.currentStep); - const double current_temp = well.getInjectionProperties().temperature; - if (current_temp != temp && !well.isProducer()) { + const double current_temp = !well.isProducer()? well.temperature(): 0.0; + if (current_temp != temp) { auto well2 = this->snapshots.back().wells( well_name ); - auto inj = std::make_shared(well.getInjectionProperties()); - inj->temperature = temp; - well2.updateInjection(inj); + well2.setWellTemperature(temp); this->snapshots.back().wells.update( std::move(well2) ); } } diff --git a/src/opm/input/eclipse/Schedule/Well/Well.cpp b/src/opm/input/eclipse/Schedule/Well/Well.cpp index 6602c1281..c0c992935 100644 --- a/src/opm/input/eclipse/Schedule/Well/Well.cpp +++ b/src/opm/input/eclipse/Schedule/Well/Well.cpp @@ -31,6 +31,7 @@ #include +#include #include #include @@ -294,7 +295,8 @@ Well::Well(const RestartIO::RstWell& rst_well, production(std::make_shared(unit_system_arg, wname)), injection(std::make_shared(unit_system_arg, wname)), wvfpexp(explicitTHPOptions(rst_well)), - status(status_from_int(rst_well.well_status)) + status(status_from_int(rst_well.well_status)), + well_temperature(Metric::TemperatureOffset + ParserKeywords::STCOND::TEMPERATURE::defaultValue) { if (this->wtype.producer()) { auto p = std::make_shared(this->unit_system, wname); @@ -471,7 +473,9 @@ Well::Well(const std::string& wname_arg, production(std::make_shared(unit_system, wname)), injection(std::make_shared(unit_system, wname)), wvfpexp(std::make_shared()), - status(Status::SHUT) + status(Status::SHUT), + well_temperature(Metric::TemperatureOffset + ParserKeywords::STCOND::TEMPERATURE::defaultValue) + { auto p = std::make_shared(this->unit_system, this->wname); p->whistctl_cmode = whistctl_cmode; @@ -513,6 +517,7 @@ Well Well::serializationTestObject() result.segments = std::make_shared(WellSegments::serializationTestObject()); result.wvfpexp = std::make_shared(WVFPEXP::serializationTestObject()); result.m_pavg = PAvg(); + result.well_temperature = 10.0; return result; } @@ -1529,9 +1534,12 @@ double Well::alq_value() const { double Well::temperature() const { if (!this->wtype.producer()) - return this->injection->temperature; + return this->well_temperature; - throw std::runtime_error("Can not ask for temperature in a producer"); + throw std::runtime_error("Can only ask for temperature in an injector"); +} +void Well::setWellTemperature(const double temp) { + this->well_temperature = temp; } std::ostream& operator<<(std::ostream& os, const Well::Status& st) { @@ -1807,6 +1815,7 @@ bool Well::operator==(const Well& data) const { && (this->getProductionProperties() == data.getProductionProperties()) && (this->m_pavg == data.m_pavg) && (this->getInjectionProperties() == data.getInjectionProperties()) + && (this->well_temperature == data.well_temperature) ; } diff --git a/src/opm/input/eclipse/Schedule/Well/WellInjectionProperties.cpp b/src/opm/input/eclipse/Schedule/Well/WellInjectionProperties.cpp index 789a7a50e..a54b3863f 100644 --- a/src/opm/input/eclipse/Schedule/Well/WellInjectionProperties.cpp +++ b/src/opm/input/eclipse/Schedule/Well/WellInjectionProperties.cpp @@ -47,7 +47,6 @@ namespace Opm { reservoirInjectionRate(units.getDimension(UnitSystem::measure::rate)), BHPTarget(units.getDimension(UnitSystem::measure::pressure)), THPTarget(units.getDimension(UnitSystem::measure::pressure)), - temperature(Metric::TemperatureOffset + ParserKeywords::STCOND::TEMPERATURE::defaultValue), BHPH(0), THPH(0), VFPTableNumber(0), @@ -69,7 +68,6 @@ namespace Opm { result.THPTarget = UDAValue(3.0); result.bhp_hist_limit = 4.0; result.thp_hist_limit = 5.0; - result.temperature = 6.0; result.BHPH = 7.0; result.THPH = 8.0; result.VFPTableNumber = 9; @@ -238,7 +236,6 @@ namespace Opm { bool Well::WellInjectionProperties::operator==(const Well::WellInjectionProperties& other) const { if ((surfaceInjectionRate == other.surfaceInjectionRate) && (reservoirInjectionRate == other.reservoirInjectionRate) && - (temperature == other.temperature) && (BHPTarget == other.BHPTarget) && (THPTarget == other.THPTarget) && (BHPH == other.BHPH) && @@ -280,7 +277,6 @@ namespace Opm { << "Well::WellInjectionProperties { " << "surfacerate: " << wp.surfaceInjectionRate << ", " << "reservoir rate " << wp.reservoirInjectionRate << ", " - << "temperature: " << wp.temperature << ", " << "BHP target: " << wp.BHPTarget << ", " << "THP target: " << wp.THPTarget << ", " << "BHPH: " << wp.BHPH << ", " @@ -306,7 +302,6 @@ namespace Opm { controls.bhp_limit = this->bhp_hist_limit; controls.thp_limit = this->thp_hist_limit; } - controls.temperature = this->temperature; controls.injector_type = this->injectorType; controls.cmode = this->controlMode; controls.vfp_table_number = this->VFPTableNumber; diff --git a/tests/parser/ScheduleTests.cpp b/tests/parser/ScheduleTests.cpp index 2702fed2f..51e6e168b 100644 --- a/tests/parser/ScheduleTests.cpp +++ b/tests/parser/ScheduleTests.cpp @@ -2225,18 +2225,19 @@ BOOST_AUTO_TEST_CASE(WTEMP_well_template) { 'W3' 'G2' 6 6 1 'WATER' 0.00 'STD' 'SHUT' 'NO' 0 'SEG' / / - WCONINJE - 'W2' 'WATER' 'OPEN' 'RATE' 20000 4* / - 'W3' 'WATER' 'OPEN' 'RATE' 20000 4* / + WTEMP + 'W*' 40.0 / / DATES -- 2 15 OKT 2008 / / - WTEMP - 'W*' 40.0 / + WCONINJE + 'W2' 'WATER' 'OPEN' 'RATE' 20000 4* / + 'W3' 'WATER' 'OPEN' 'RATE' 20000 4* / / + )"; auto deck = Parser().parseString(input); @@ -2247,14 +2248,14 @@ BOOST_AUTO_TEST_CASE(WTEMP_well_template) { Runspec runspec (deck); Schedule schedule( deck, grid, fp, runspec, python); - BOOST_CHECK_CLOSE(288.71, schedule.getWell("W1", 1).getInjectionProperties().temperature, 1e-5); - BOOST_CHECK_CLOSE(288.71, schedule.getWell("W1", 2).getInjectionProperties().temperature, 1e-5); + BOOST_CHECK_THROW(schedule.getWell("W1", 1).temperature(), std::runtime_error); + BOOST_CHECK_THROW(schedule.getWell("W1", 2).temperature(), std::runtime_error); - BOOST_CHECK_CLOSE(288.71, schedule.getWell("W2", 1).getInjectionProperties().temperature, 1e-5); - BOOST_CHECK_CLOSE(313.15, schedule.getWell("W2", 2).getInjectionProperties().temperature, 1e-5); + BOOST_CHECK_THROW(schedule.getWell("W2", 1).temperature(), std::runtime_error); + BOOST_CHECK_CLOSE(313.15, schedule.getWell("W2", 2).temperature(), 1e-5); - BOOST_CHECK_CLOSE(288.71, schedule.getWell("W3", 1).getInjectionProperties().temperature, 1e-5); - BOOST_CHECK_CLOSE(313.15, schedule.getWell("W3", 2).getInjectionProperties().temperature, 1e-5); + BOOST_CHECK_THROW(schedule.getWell("W3", 1).temperature(), std::runtime_error); + BOOST_CHECK_CLOSE(313.15, schedule.getWell("W3", 2).temperature(), 1e-5); } @@ -2294,15 +2295,14 @@ BOOST_AUTO_TEST_CASE(WTEMPINJ_well_template) { Runspec runspec (deck); Schedule schedule( deck, grid, fp, runspec, python); - // Producerwell - currently setting temperature only acts on injectors. - BOOST_CHECK_CLOSE(288.71, schedule.getWell("W1", 1).getInjectionProperties().temperature, 1e-5); - BOOST_CHECK_CLOSE(288.71, schedule.getWell("W1", 2).getInjectionProperties().temperature, 1e-5); + BOOST_CHECK_THROW(schedule.getWell("W1", 1).temperature(), std::runtime_error); + BOOST_CHECK_THROW(schedule.getWell("W1", 2).temperature(), std::runtime_error); - BOOST_CHECK_CLOSE(288.71, schedule.getWell("W2", 1).getInjectionProperties().temperature, 1e-5); - BOOST_CHECK_CLOSE(313.15, schedule.getWell("W2", 2).getInjectionProperties().temperature, 1e-5); + BOOST_CHECK_CLOSE(288.71, schedule.getWell("W2", 1).temperature(), 1e-5); + BOOST_CHECK_CLOSE(313.15, schedule.getWell("W2", 2).temperature(), 1e-5); - BOOST_CHECK_CLOSE(288.71, schedule.getWell("W3", 1).getInjectionProperties().temperature, 1e-5); - BOOST_CHECK_CLOSE(313.15, schedule.getWell("W3", 2).getInjectionProperties().temperature, 1e-5); + BOOST_CHECK_CLOSE(288.71, schedule.getWell("W2", 1).temperature(), 1e-5); + BOOST_CHECK_CLOSE(313.15, schedule.getWell("W3", 2).temperature(), 1e-5); } BOOST_AUTO_TEST_CASE( COMPDAT_sets_automatic_complnum ) {