units: introduce a "ContextDependent" dimension
this is meant for those nasty keywords where the dimension of an entry depends on a user-defined value of some field of a (potentially different) keyword. One example for this are the surface rates of the produced fluids for the .CON(INJ|PROD).* keywords which exhibit different units depending on whether the user choses to control for the surface gas or the liquid rate. the approach taken in this patch is to convert all numbers to NaN if the unit is queried in SI (via item->getSIDouble()). It might be more desireable to throw an exception in this case, but this approach would be more elaborate and NaNs should be quickly noticeable by the users of this code. I tried to adapt all implemented keywords, but it's quite likely that I missed some...
This commit is contained in:
@@ -23,6 +23,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
|
||||
@@ -243,8 +243,11 @@ namespace Opm {
|
||||
DeckRecordConstPtr record = keyword->getRecord(recordNr);
|
||||
const std::string& wellName = record->getItem("WELL")->getString(0);
|
||||
WellPtr well = getWell(wellName);
|
||||
double surfaceInjectionRate = record->getItem("RATE")->getSIDouble(0);
|
||||
double reservoirInjectionRate = record->getItem("RESV")->getSIDouble(0);
|
||||
|
||||
#warning TODO: convert these two rates to SI depending on what we control for!
|
||||
double surfaceInjectionRate = record->getItem("RATE")->getRawDouble(0);
|
||||
double reservoirInjectionRate = record->getItem("RESV")->getRawDouble(0);
|
||||
|
||||
double BHPLimit = record->getItem("BHP")->getSIDouble(0);
|
||||
double THPLimit = record->getItem("THP")->getSIDouble(0);
|
||||
WellInjector::ControlModeEnum controlMode = WellInjector::ControlModeFromString( record->getItem("CMODE")->getString(0));
|
||||
@@ -280,7 +283,10 @@ namespace Opm {
|
||||
DeckRecordConstPtr record = keyword->getRecord(recordNr);
|
||||
const std::string& wellName = record->getItem("WELL")->getString(0);
|
||||
WellPtr well = getWell(wellName);
|
||||
double injectionRate = record->getItem("RATE")->getSIDouble(0);
|
||||
|
||||
#warning TODO: convert this rate to SI depending on what we control for!
|
||||
double injectionRate = record->getItem("RATE")->getRawDouble(0);
|
||||
|
||||
WellCommon::StatusEnum status = WellCommon::StatusFromString( record->getItem("STATUS")->getString(0));
|
||||
|
||||
well->setStatus( currentStep , status );
|
||||
@@ -320,8 +326,9 @@ namespace Opm {
|
||||
GroupInjection::ControlEnum controlMode = GroupInjection::ControlEnumFromString( record->getItem("CONTROL_MODE")->getString(0) );
|
||||
group->setInjectionControlMode( currentStep , controlMode );
|
||||
}
|
||||
group->setSurfaceMaxRate( currentStep , record->getItem("SURFACE_TARGET")->getSIDouble(0));
|
||||
group->setReservoirMaxRate( currentStep , record->getItem("RESV_TARGET")->getSIDouble(0));
|
||||
#warning TODO: convert these context dependent rates to SI
|
||||
group->setSurfaceMaxRate( currentStep , record->getItem("SURFACE_TARGET")->getRawDouble(0));
|
||||
group->setReservoirMaxRate( currentStep , record->getItem("RESV_TARGET")->getRawDouble(0));
|
||||
group->setTargetReinjectFraction( currentStep , record->getItem("REINJ_TARGET")->getRawDouble(0));
|
||||
group->setTargetVoidReplacementFraction( currentStep , record->getItem("VOIDAGE_TARGET")->getRawDouble(0));
|
||||
}
|
||||
|
||||
@@ -129,14 +129,14 @@ BOOST_AUTO_TEST_CASE(WellTesting) {
|
||||
BOOST_CHECK_CLOSE(13000/Metric::Time , well1->getOilRate(8) , 0.001);
|
||||
|
||||
BOOST_CHECK( well1->isInjector(9));
|
||||
BOOST_CHECK_CLOSE(20000/Metric::Time , well1->getSurfaceInjectionRate(9) , 0.001);
|
||||
BOOST_CHECK_CLOSE(200000/Metric::Time , well1->getReservoirInjectionRate(9) , 0.001);
|
||||
BOOST_CHECK_CLOSE(20000 , well1->getSurfaceInjectionRate(9) , 0.001);
|
||||
BOOST_CHECK_CLOSE(200000, well1->getReservoirInjectionRate(9) , 0.001);
|
||||
BOOST_CHECK_CLOSE(6891 * Metric::Pressure , well1->getBHPLimit(9) , 0.001);
|
||||
BOOST_CHECK_CLOSE(0 , well1->getTHPLimit(9) , 0.001);
|
||||
BOOST_CHECK_CLOSE(123.00 * Metric::Pressure , well1->getBHPLimit(10) , 0.001);
|
||||
BOOST_CHECK_CLOSE(678.00 * Metric::Pressure , well1->getTHPLimit(10) , 0.001);
|
||||
|
||||
BOOST_CHECK_CLOSE(5000/Metric::Time , well1->getSurfaceInjectionRate(11) , 0.001);
|
||||
BOOST_CHECK_CLOSE(5000 , well1->getSurfaceInjectionRate(11) , 0.001);
|
||||
|
||||
BOOST_CHECK_EQUAL( WellInjector::RESV , well1->getInjectorControlMode( 9 ));
|
||||
BOOST_CHECK_EQUAL( WellInjector::RATE , well1->getInjectorControlMode( 11 ));
|
||||
@@ -316,14 +316,14 @@ BOOST_AUTO_TEST_CASE( WellTestGroups ) {
|
||||
GroupPtr group = sched->getGroup("INJ");
|
||||
BOOST_CHECK_EQUAL( Phase::WATER , group->getInjectionPhase( 3 ));
|
||||
BOOST_CHECK_EQUAL( GroupInjection::VREP , group->getInjectionControlMode( 3 ));
|
||||
BOOST_CHECK_CLOSE( 10/Metric::Time , group->getSurfaceMaxRate( 3 ) , 0.001);
|
||||
BOOST_CHECK_CLOSE( 20/Metric::Time , group->getReservoirMaxRate( 3 ) , 0.001);
|
||||
BOOST_CHECK_CLOSE( 10 , group->getSurfaceMaxRate( 3 ) , 0.001);
|
||||
BOOST_CHECK_CLOSE( 20 , group->getReservoirMaxRate( 3 ) , 0.001);
|
||||
BOOST_CHECK_EQUAL( 0.75 , group->getTargetReinjectFraction( 3 ));
|
||||
BOOST_CHECK_EQUAL( 0.95 , group->getTargetVoidReplacementFraction( 3 ));
|
||||
|
||||
BOOST_CHECK_EQUAL( Phase::OIL , group->getInjectionPhase( 6 ));
|
||||
BOOST_CHECK_EQUAL( GroupInjection::RATE , group->getInjectionControlMode( 6 ));
|
||||
BOOST_CHECK_CLOSE( 1000/Metric::Time , group->getSurfaceMaxRate( 6 ) , 0.0001);
|
||||
BOOST_CHECK_CLOSE( 1000 , group->getSurfaceMaxRate( 6 ) , 0.0001);
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <cmath>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
@@ -40,6 +41,9 @@ namespace Opm {
|
||||
|
||||
|
||||
double Dimension::getSIScaling() const {
|
||||
if (!std::isfinite(m_SIfactor))
|
||||
throw std::logic_error("The DeckItem contains a field with a context dependent unit. "
|
||||
"Use getRawDoubleData() and convert the returned value manually!");
|
||||
return m_SIfactor;
|
||||
}
|
||||
|
||||
@@ -58,11 +62,13 @@ namespace Opm {
|
||||
|
||||
|
||||
bool Dimension::equal(const Dimension& other) const {
|
||||
if ((m_name == other.m_name) &&
|
||||
(m_SIfactor == other.m_SIfactor))
|
||||
return true;
|
||||
else
|
||||
if (m_name != other.m_name)
|
||||
return false;
|
||||
if (m_SIfactor == other.m_SIfactor)
|
||||
return true;
|
||||
if (std::isnan(m_SIfactor) && std::isnan(other.m_SIfactor))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,7 +24,9 @@
|
||||
|
||||
#include <opm/parser/eclipse/Units/ConversionFactors.hpp>
|
||||
#include <opm/parser/eclipse/Units/UnitSystem.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
|
||||
|
||||
namespace Opm {
|
||||
@@ -148,6 +150,7 @@ namespace Opm {
|
||||
system->addDimension("Density" , Metric::Density );
|
||||
system->addDimension("Viscosity" , Metric::Viscosity);
|
||||
system->addDimension("Timestep" , Metric::Timestep);
|
||||
system->addDimension("ContextDependent", std::numeric_limits<double>::quiet_NaN());
|
||||
return system;
|
||||
}
|
||||
|
||||
@@ -169,6 +172,7 @@ namespace Opm {
|
||||
system->addDimension("Density", Field::Density );
|
||||
system->addDimension("Viscosity", Field::Viscosity);
|
||||
system->addDimension("Timestep", Field::Timestep);
|
||||
system->addDimension("ContextDependent", std::numeric_limits<double>::quiet_NaN());
|
||||
return system;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
{"name" : "GROUP" , "value_type" : "STRING" },
|
||||
{"name" : "PHASE" , "value_type" : "STRING"},
|
||||
{"name" : "CONTROL_MODE" , "value_type" : "STRING" , "default" : "NONE"},
|
||||
{"name" : "SURFACE_TARGET" , "value_type" : "FLOAT" , "default" : 0 , "dimension" : "GasVolume/Time"},
|
||||
{"name" : "RESV_TARGET" , "value_type" : "FLOAT" , "default" : 0 , "dimension" : "GasVolume/Time"},
|
||||
{"name" : "SURFACE_TARGET" , "value_type" : "FLOAT" , "default" : 0 , "dimension" : "ContextDependent"},
|
||||
{"name" : "RESV_TARGET" , "value_type" : "FLOAT" , "default" : 0 , "dimension" : "ContextDependent"},
|
||||
{"name" : "REINJ_TARGET" , "value_type" : "FLOAT" , "default" : 0, "dimension":"1"},
|
||||
{"name" : "VOIDAGE_TARGET" , "value_type" : "FLOAT" , "default" : 0, "dimension":"1"},
|
||||
{"name" : "FREE" , "value_type" : "STRING" , "default" : "YES"},
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
{"name" : "TVDP*" , "size" : {"keyword":"EQLDIMS" , "item":"NTTRVD"}, "items" :
|
||||
[ {"name" : "table" , "value_type" : "FLOAT" , "size_type" : "ALL" , "dimension" : ["Length" , "1/LiquidVolume"]}]}
|
||||
[ {"name" : "table" , "value_type" : "FLOAT" , "size_type" : "ALL" , "dimension" : ["Length" , "ContextDependent"]}]}
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
{"name" : "TYPE" , "value_type" : "STRING" },
|
||||
{"name" : "STATUS" , "value_type" : "STRING" , "default" : "OPEN"},
|
||||
{"name" : "CMODE" , "value_type" : "STRING" },
|
||||
{"name" : "RATE" , "value_type" : "FLOAT" , "dimension" : "LiquidVolume/Time"},
|
||||
{"name" : "RESV" , "value_type" : "FLOAT" , "dimension" : "LiquidVolume/Time"},
|
||||
{"name" : "RATE" , "value_type" : "FLOAT" , "dimension" : "ContextDependent"},
|
||||
{"name" : "RESV" , "value_type" : "FLOAT" , "dimension" : "ContextDependent"},
|
||||
{"name" : "BHP" , "value_type" : "FLOAT" , "dimension" : "Pressure" , "default" : 6891},
|
||||
{"name" : "THP" , "value_type" : "FLOAT" , "dimension" : "Pressure"},
|
||||
{"name" : "VFP_TABLE" , "value_type" : "INT" , "default" : 0},
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
{"name" : "WELL" , "value_type" : "STRING" },
|
||||
{"name" : "TYPE" , "value_type" : "STRING" },
|
||||
{"name" : "STATUS" , "value_type" : "STRING" , "default" : "OPEN"},
|
||||
{"name" : "RATE" , "value_type" : "FLOAT" , "dimension" : "LiquidVolume/Time"},
|
||||
{"name" : "RATE" , "value_type" : "FLOAT" , "dimension" : "ContextDependent"},
|
||||
{"name" : "BHP" , "value_type" : "FLOAT" , "dimension" : "Pressure"},
|
||||
{"name" : "THP" , "value_type" : "FLOAT" , "dimension" : "Pressure"},
|
||||
{"name" : "VFP_TABLE" , "value_type" : "INT" , "default" : 0},
|
||||
@@ -11,4 +11,4 @@
|
||||
{"name" : "SURFACE_WATER_FRACTION" , "value_type" : "FLOAT" , "default" : 0},
|
||||
{"name" : "SURFACE_GAS_FRACTION" , "value_type" : "FLOAT" , "default" : 0},
|
||||
{"name" : "CMODE" , "value_type" : "STRING" }
|
||||
]}
|
||||
]}
|
||||
|
||||
Reference in New Issue
Block a user