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:
Andreas Lauser
2014-02-07 17:19:37 +01:00
parent 50f2288148
commit 849bc7df93
9 changed files with 40 additions and 22 deletions

View File

@@ -23,6 +23,7 @@
#include <algorithm>
#include <iostream>
#include <cmath>
namespace Opm {

View File

@@ -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));
}

View File

@@ -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);
}
{

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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"},

View File

@@ -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"]}]}

View File

@@ -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},

View File

@@ -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" }
]}
]}