Move to_si/from_si into UnitSystem

UnitSystem already offered similar functionality, but via string-map
lookup and a very clunky interface. Offer simple to/from methods as an
addition.
This commit is contained in:
Jørgen Kvalsvik
2016-05-23 15:11:33 +02:00
parent 6affc5f9c1
commit 1c7e7e08c6
3 changed files with 121 additions and 123 deletions

View File

@@ -237,125 +237,6 @@ namespace Opm {
const double Timestep = day;
}
namespace conversions {
/*
* It is VERY important that the dim enum has the same order as the
* metric and field arrays. C++ does not support designated initializers, so
* this cannot be done in a declaration-order independent matter.
*/
enum class dim : int {
length,
time,
density,
pressure,
temperature_absolute,
temperature,
viscosity,
permeability,
liquid_surface_volume,
gas_surface_volume,
volume,
liquid_surface_rate,
gas_surface_rate,
rate,
transmissibility,
mass,
};
/* lookup tables for SI-to-unit system
*
* We assume that all values in the report structures are plain SI units,
* but output can be configured to use other (inconsistent) unit systems.
* These lookup tables are passed to the convert function that translates
* between SI and the target unit.
*/
const double si2metric[] = {
1 / Metric::Length,
1 / Metric::Time,
1 / Metric::Density,
1 / Metric::Pressure,
1 / Metric::AbsoluteTemperature,
1 / Metric::Temperature,
1 / Metric::Viscosity,
1 / Metric::Permeability,
1 / Metric::LiquidSurfaceVolume,
1 / Metric::GasSurfaceVolume,
1 / Metric::ReservoirVolume,
1 / ( Metric::LiquidSurfaceVolume / Metric::Time ),
1 / ( Metric::GasSurfaceVolume / Metric::Time ),
1 / ( Metric::ReservoirVolume / Metric::Time ),
1 / Metric::Transmissibility,
1 / Metric::Mass,
};
const double si2field[] = {
1 / Field::Length,
1 / Field::Time,
1 / Field::Density,
1 / Field::Pressure,
1 / Field::AbsoluteTemperature,
1 / Field::Temperature,
1 / Field::Viscosity,
1 / Field::Permeability,
1 / Field::LiquidSurfaceVolume,
1 / Field::GasSurfaceVolume,
1 / Field::ReservoirVolume,
1 / ( Field::LiquidSurfaceVolume / Field::Time ),
1 / ( Field::GasSurfaceVolume / Field::Time ),
1 / ( Field::ReservoirVolume / Field::Time ),
1 / Field::Transmissibility,
1 / Field::Mass,
};
const double metric2si[] = {
Metric::Length,
Metric::Time,
Metric::Density,
Metric::Pressure,
Metric::AbsoluteTemperature,
Metric::Temperature,
Metric::Viscosity,
Metric::Permeability,
Metric::LiquidSurfaceVolume,
Metric::GasSurfaceVolume,
Metric::ReservoirVolume,
Metric::LiquidSurfaceVolume / Metric::Time,
Metric::GasSurfaceVolume / Metric::Time,
Metric::ReservoirVolume / Metric::Time,
Metric::Transmissibility,
Metric::Mass,
};
const double field2si[] = {
Field::Length,
Field::Time,
Field::Density,
Field::Pressure,
Field::AbsoluteTemperature,
Field::Temperature,
Field::Viscosity,
Field::Permeability,
Field::LiquidSurfaceVolume,
Field::GasSurfaceVolume,
Field::ReservoirVolume,
Field::LiquidSurfaceVolume / Field::Time,
Field::GasSurfaceVolume / Field::Time,
Field::ReservoirVolume / Field::Time,
Field::Transmissibility,
Field::Mass,
};
inline double from_si( const double* table, dim d, double val ) {
return val * table[ static_cast< int >( d ) ];
}
inline double to_si( const double* table, dim d, double val ) {
return val * table[ static_cast< int >( d ) ];
}
}
}
#endif

View File

@@ -32,18 +32,108 @@
namespace Opm {
namespace {
/*
* It is VERY important that the measure enum has the same order as the
* metric and field arrays. C++ does not support designated initializers, so
* this cannot be done in a declaration-order independent matter.
*/
static const double to_metric[] = {
1 / Metric::Length,
1 / Metric::Time,
1 / Metric::Density,
1 / Metric::Pressure,
1 / Metric::AbsoluteTemperature,
1 / Metric::Temperature,
1 / Metric::Viscosity,
1 / Metric::Permeability,
1 / Metric::LiquidSurfaceVolume,
1 / Metric::GasSurfaceVolume,
1 / Metric::ReservoirVolume,
1 / ( Metric::LiquidSurfaceVolume / Metric::Time ),
1 / ( Metric::GasSurfaceVolume / Metric::Time ),
1 / ( Metric::ReservoirVolume / Metric::Time ),
1 / Metric::Transmissibility,
1 / Metric::Mass,
};
static const double from_metric[] = {
Metric::Length,
Metric::Time,
Metric::Density,
Metric::Pressure,
Metric::AbsoluteTemperature,
Metric::Temperature,
Metric::Viscosity,
Metric::Permeability,
Metric::LiquidSurfaceVolume,
Metric::GasSurfaceVolume,
Metric::ReservoirVolume,
Metric::LiquidSurfaceVolume / Metric::Time,
Metric::GasSurfaceVolume / Metric::Time,
Metric::ReservoirVolume / Metric::Time,
Metric::Transmissibility,
Metric::Mass,
};
static const double to_field[] = {
1 / Field::Length,
1 / Field::Time,
1 / Field::Density,
1 / Field::Pressure,
1 / Field::AbsoluteTemperature,
1 / Field::Temperature,
1 / Field::Viscosity,
1 / Field::Permeability,
1 / Field::LiquidSurfaceVolume,
1 / Field::GasSurfaceVolume,
1 / Field::ReservoirVolume,
1 / ( Field::LiquidSurfaceVolume / Field::Time ),
1 / ( Field::GasSurfaceVolume / Field::Time ),
1 / ( Field::ReservoirVolume / Field::Time ),
1 / Field::Transmissibility,
1 / Field::Mass,
};
static const double from_field[] = {
Field::Length,
Field::Time,
Field::Density,
Field::Pressure,
Field::AbsoluteTemperature,
Field::Temperature,
Field::Viscosity,
Field::Permeability,
Field::LiquidSurfaceVolume,
Field::GasSurfaceVolume,
Field::ReservoirVolume,
Field::LiquidSurfaceVolume / Field::Time,
Field::GasSurfaceVolume / Field::Time,
Field::ReservoirVolume / Field::Time,
Field::Transmissibility,
Field::Mass,
};
}
UnitSystem::UnitSystem(const UnitType unit) :
m_unittype( unit )
{
switch(unit) {
case(UNIT_TYPE_METRIC):
m_name = "Metric";
this->measure_table_from_si = to_metric;
this->measure_table_to_si = from_metric;
break;
case(UNIT_TYPE_FIELD):
m_name = "Field";
this->measure_table_from_si = to_field;
this->measure_table_to_si = from_field;
break;
case(UNIT_TYPE_LAB):
m_name = "Lab";
throw std::runtime_error( "Lab unit system is not supported" );
break;
default:
//do nothing
@@ -51,7 +141,6 @@ namespace Opm {
};
}
bool UnitSystem::hasDimension(const std::string& dimension) const {
return (m_dimensions.find( dimension ) != m_dimensions.end());
}
@@ -162,6 +251,13 @@ namespace Opm {
return equal_;
}
double UnitSystem::from_si( measure m, double val ) const {
return this->measure_table_from_si[ static_cast< int >( m ) ] * val;
}
double UnitSystem::to_si( measure m, double val ) const {
return this->measure_table_to_si[ static_cast< int >( m ) ] * val;
}
UnitSystem * UnitSystem::newMETRIC() {
UnitSystem * system = new UnitSystem(UNIT_TYPE_METRIC);
@@ -218,6 +314,3 @@ namespace Opm {
}
}

View File

@@ -36,6 +36,25 @@ namespace Opm {
UNIT_TYPE_LAB = 2
};
enum class measure : int {
length,
time,
density,
pressure,
temperature_absolute,
temperature,
viscosity,
permeability,
liquid_surface_volume,
gas_surface_volume,
volume,
liquid_surface_rate,
gas_surface_rate,
rate,
transmissibility,
mass,
};
UnitSystem(UnitType unit);
const std::string& getName() const;
@@ -50,6 +69,9 @@ namespace Opm {
std::shared_ptr<const Dimension> parse(const std::string& dimension) const;
double from_si( measure, double ) const;
double to_si( measure, double ) const;
static UnitSystem * newMETRIC();
static UnitSystem * newFIELD();
private:
@@ -58,6 +80,8 @@ namespace Opm {
std::string m_name;
UnitType m_unittype;
std::map<std::string , std::shared_ptr<const Dimension> > m_dimensions;
const double* measure_table_from_si;
const double* measure_table_to_si;
};
}