Add WellType class for ecl interop

This commit is contained in:
Joakim Hove
2020-03-03 08:47:44 +01:00
parent 51a593de39
commit 6e8b4a6c12
3 changed files with 285 additions and 0 deletions

View File

@@ -21,6 +21,7 @@
#define OPM_SCHEDULE_TYPES_HPP
#include <string>
#include <opm/parser/eclipse/EclipseState/Runspec.hpp>
namespace Opm {
@@ -33,6 +34,48 @@ enum class InjectorType {
const std::string InjectorType2String( InjectorType enumValue );
InjectorType InjectorTypeFromString( const std::string& stringValue );
class WellType {
public:
WellType(int ecl_wtype, int welspecs_phase);
WellType(bool producer, Phase welspecs_phase);
explicit WellType(Phase welspecs_phase);
WellType() = default;
bool injector() const;
bool producer() const;
bool update(InjectorType injector_type);
bool update(bool producer);
static bool oil_injector(int ecl_wtype);
static bool gas_injector(int ecl_wtype);
static bool water_injector(int ecl_wtype);
static bool producer(int ecl_wtype);
int ecl_wtype() const;
int ecl_phase() const;
Phase preferred_phase() const;
InjectorType injector_type() const;
bool operator==(const WellType& other) const;
private:
bool m_producer;
/*
The injection_phase member is updated during the course of the simulation;
following each WCONINJE keyword the injection phase is updated. If an
producer is specified in the constructor the injection_phase is
initialzied to the welspecs phase. This is not wildly random - but the
injection_phase will not be meaningfull before an update(Phase) call has been
issued.
The welspecs_phase is the preferred phase specified when the well is
defined with the WELSPECS keyword. This member is immutable, and it is only
used when initializing the well equations for a producer.
*/
Phase injection_phase;
Phase m_welspecs_phase;
};
}

View File

@@ -22,6 +22,204 @@
namespace Opm {
namespace ecl {
static constexpr int producer = 1;
static constexpr int oil_injector = 2;
static constexpr int water_injector = 3;
static constexpr int gas_injector = 4;
static constexpr int oil_phase = 1;
static constexpr int water_phase = 2;
static constexpr int gas_phase = 3;
static constexpr int liquid_phase = 4;
Phase from_ecl_phase(int ecl_phase) {
switch(ecl_phase) {
case ecl::oil_phase:
return Phase::OIL;
case ecl::water_phase:
return Phase::WATER;
case ecl::gas_phase:
return Phase::GAS;
case ecl::liquid_phase:
throw std::logic_error("Sorry wells with preferred phase:LIQUID is not supported");
default:
throw std::invalid_argument("Invalid integer well phase");
}
}
}
namespace {
Phase from_injector_type(InjectorType injector_type) {
switch (injector_type) {
case InjectorType::WATER:
return Phase::WATER;
case InjectorType::GAS:
return Phase::GAS;
case InjectorType::OIL:
return Phase::OIL;
default:
throw std::logic_error("Unhandled injector type");
}
}
}
bool WellType::producer(int ecl_wtype) {
return ecl_wtype == ecl::producer;
}
bool WellType::oil_injector(int ecl_wtype) {
return ecl_wtype == ecl::oil_injector;
}
bool WellType::water_injector(int ecl_wtype) {
return ecl_wtype == ecl::water_injector;
}
bool WellType::gas_injector(int ecl_wtype) {
return ecl_wtype == ecl::gas_injector;
}
WellType::WellType(int ecl_wtype, int ecl_phase) :
injection_phase(ecl::from_ecl_phase(ecl_phase)),
m_welspecs_phase(ecl::from_ecl_phase(ecl_phase))
{
this->m_producer = false;
switch (ecl_wtype) {
case ecl::producer:
this->m_producer = true;
break;
case ecl::oil_injector:
this->injection_phase = Phase::OIL;
break;
case ecl::water_injector:
this->injection_phase = Phase::WATER;
break;
case ecl::gas_injector:
this->injection_phase = Phase::GAS;
break;
default:
throw std::invalid_argument("Invalid integer well type ID");
}
}
WellType::WellType(bool producer, Phase phase) :
m_producer(producer),
injection_phase(phase),
m_welspecs_phase(phase)
{}
WellType::WellType(Phase phase) :
WellType(true, phase)
{}
bool WellType::update(bool producer_arg) {
if (this->m_producer != producer_arg) {
this->m_producer = producer_arg;
return true;
} else
return false;
}
bool WellType::update(InjectorType injector_type) {
bool ret_value = false;
if (this->m_producer) {
this->m_producer = false;
ret_value = true;
}
auto inj_phase = from_injector_type(injector_type);
if (this->injection_phase != inj_phase) {
this->injection_phase = inj_phase;
ret_value = true;
}
return ret_value;
}
bool WellType::producer() const {
return this->m_producer;
}
bool WellType::injector() const {
return !this->m_producer;
}
int WellType::ecl_wtype() const {
if (this->m_producer)
return ecl::producer;
switch (this->injection_phase) {
case Phase::OIL:
return ecl::oil_injector;
case Phase::WATER:
return ecl::water_injector;
case Phase::GAS:
return ecl::gas_injector;
default:
throw std::logic_error("Internal error - should not be here");
}
}
/*
The enum Runspec::Phase is maybe not very well suited; it has lots of 'extra'
phases like ENERGY and BRINE, and at the same time it is missing the phase
LIQUID which should map to ecl value 4.
*/
int WellType::ecl_phase() const {
switch (this->m_welspecs_phase) {
case Phase::OIL:
return ecl::oil_phase;
case Phase::WATER:
return ecl::water_phase;
case Phase::GAS:
return ecl::gas_phase;
default:
throw std::logic_error("Member has invalid phase");
}
}
Phase WellType::preferred_phase() const {
return this->m_welspecs_phase;
}
bool WellType::operator==(const WellType& other) const {
return this->m_welspecs_phase == other.m_welspecs_phase &&
this->injection_phase == other.injection_phase &&
this->m_producer == other.m_producer;
}
InjectorType WellType::injector_type() const {
if (this->producer())
throw std::invalid_argument("Asked for injector type for a well which is a producer");
switch (this->injection_phase) {
case Phase::OIL:
return InjectorType::OIL;
case Phase::WATER:
return InjectorType::WATER;
case Phase::GAS:
return InjectorType::GAS;
default:
throw std::logic_error("Member has invalid phase");
}
}
const std::string InjectorType2String( InjectorType enumValue ) {
switch( enumValue ) {
case InjectorType::OIL:

View File

@@ -863,3 +863,47 @@ BOOST_AUTO_TEST_CASE(WELOPEN) {
}
BOOST_AUTO_TEST_CASE(WellTypeTest) {
BOOST_CHECK_THROW(Opm::WellType(0, 3), std::invalid_argument);
BOOST_CHECK_THROW(Opm::WellType(5, 3), std::invalid_argument);
BOOST_CHECK_THROW(Opm::WellType(3, 0), std::invalid_argument);
BOOST_CHECK_THROW(Opm::WellType(3, 5), std::invalid_argument);
Opm::WellType wt1(1,1);
BOOST_CHECK(wt1.producer());
BOOST_CHECK(!wt1.injector());
BOOST_CHECK_EQUAL(wt1.ecl_wtype(), 1);
BOOST_CHECK_EQUAL(wt1.ecl_phase(), 1);
BOOST_CHECK(wt1.preferred_phase() == Phase::OIL);
BOOST_CHECK_THROW(wt1.injector_type(), std::invalid_argument);
Opm::WellType wt4(4,3);
BOOST_CHECK(!wt4.producer());
BOOST_CHECK(wt4.injector());
BOOST_CHECK_EQUAL(wt4.ecl_wtype(), 4);
BOOST_CHECK_EQUAL(wt4.ecl_phase(), 3);
BOOST_CHECK(wt4.preferred_phase() == Phase::GAS);
BOOST_CHECK(wt4.injector_type() == InjectorType::GAS);
BOOST_CHECK(wt4.update(true));
BOOST_CHECK(!wt4.update(true));
BOOST_CHECK(wt4.producer());
BOOST_CHECK(!wt4.injector());
BOOST_CHECK_EQUAL(wt4.ecl_wtype(), 1);
BOOST_CHECK_EQUAL(wt4.ecl_phase(), 3);
BOOST_CHECK(wt4.preferred_phase() == Phase::GAS);
Opm::WellType wtp(false, Phase::WATER);
BOOST_CHECK(!wtp.producer());
BOOST_CHECK(wtp.injector());
BOOST_CHECK_EQUAL(wtp.ecl_wtype(), 3);
BOOST_CHECK_EQUAL(wtp.ecl_phase(), 2);
BOOST_CHECK(wtp.preferred_phase() == Phase::WATER);
BOOST_CHECK(wtp.injector_type() == InjectorType::WATER);
wtp.update( InjectorType::GAS );
BOOST_CHECK_EQUAL(wtp.ecl_wtype(), 4);
BOOST_CHECK_EQUAL(wtp.ecl_phase(), 2);
BOOST_CHECK(wtp.preferred_phase() == Phase::WATER);
BOOST_CHECK(wtp.injector_type() == InjectorType::GAS);
}