Merge pull request #2821 from hakonhagland/py11_uda

Add support for UDA values in DeckKeyword constructor.
This commit is contained in:
Joakim Hove 2021-11-10 16:58:26 +01:00 committed by GitHub
commit 40df72bc95
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 148 additions and 44 deletions

View File

@ -23,6 +23,7 @@
#include <string>
#include <opm/parser/eclipse/Utility/Typetools.hpp>
#include <opm/parser/eclipse/Deck/UDAValue.hpp>
namespace Opm {
@ -33,7 +34,8 @@ class DeckValue {
explicit DeckValue(int);
explicit DeckValue(double);
explicit DeckValue(const std::string&);
explicit DeckValue(const UDAValue&);
bool is_default() const;
template<typename T>
@ -48,7 +50,8 @@ class DeckValue {
type_tag value_enum;
int int_value;
double double_value;
std::string string_value;
std::string string_value;
UDAValue uda_value;
};

View File

@ -62,7 +62,11 @@ bool is_int(const std::string& s)
}
void push_string_as_deck_value(std::vector<DeckValue>& record, const std::string str) {
void push_string_as_deck_value(
const ParserItem& parser_item,
std::vector<DeckValue>& record,
const std::string str)
{
std::size_t star_pos = str.find('*');
if (star_pos != std::string::npos) {
@ -79,12 +83,24 @@ void push_string_as_deck_value(std::vector<DeckValue>& record, const std::string
std::string value_str = str.substr(star_pos + 1, str.length());
DeckValue value;
if (value_str.length() > 0) {
if (is_int(value_str))
value = DeckValue( stoi(value_str) );
else
value = DeckValue( stod(value_str) );
if (parser_item.dataType() == type_tag::uda) {
if (value_str.length() > 0) {
if (is_int(value_str))
value = DeckValue( UDAValue(stoi(value_str)) );
else
value = DeckValue( UDAValue(stod(value_str)) );
}
else {
value = DeckValue( UDAValue( parser_item.getDefault<UDAValue>() ) );
}
}
else {
if (value_str.length() > 0) {
if (is_int(value_str))
value = DeckValue( stoi(value_str) );
else
value = DeckValue( stod(value_str) );
}
}
for (int i = 0; i < multiplier; i++)
@ -96,7 +112,6 @@ void push_string_as_deck_value(std::vector<DeckValue>& record, const std::string
}
py::array_t<int> get_int_array(const DeckKeyword& kw) {
return convert::numpy_array( kw.getIntData() );
}
@ -140,35 +155,47 @@ void python::common::export_DeckKeyword(py::module& module) {
.def(py::init([](const ParserKeyword& parser_keyword, py::list record_list, UnitSystem& active_system, UnitSystem& default_system) {
std::vector< std::vector<DeckValue> > value_record_list;
int i = 0;
for (py::handle record_obj : record_list) {
py::list record = record_obj.cast<py::list>();
std::vector<DeckValue> value_record;
const ParserRecord& parser_record = parser_keyword.getRecord(i++);
int j = 0;
for (const py::handle& value_obj : record) {
const ParserItem& parser_item = parser_record.get(j++);
try {
int val_int = value_obj.cast<int>();
if (parser_item.dataType() == type_tag::uda) {
value_record.push_back( DeckValue(UDAValue(val_int)) );
}
else {
value_record.push_back( DeckValue( val_int) );
}
continue;
}
catch (const std::exception& e_int) {}
try {
int val_int = value_obj.cast<int>();
value_record.push_back( DeckValue(val_int) );
continue;
}
catch (const std::exception& e_int) {}
try {
double val_double = value_obj.cast<double>();
if (parser_item.dataType() == type_tag::uda) {
value_record.push_back( DeckValue(UDAValue(val_double)));
}
else {
value_record.push_back( DeckValue(val_double) );
}
continue;
}
catch (const std::exception& e_double) {}
try {
double val_double = value_obj.cast<double>();
value_record.push_back( DeckValue(val_double) );
continue;
}
catch (const std::exception& e_double) {}
try {
std::string val_string = value_obj.cast<std::string>();
push_string_as_deck_value(
parser_item, value_record, val_string);
continue;
}
catch (const std::exception& e_string) {}
try {
std::string val_string = value_obj.cast<std::string>();
push_string_as_deck_value(value_record, val_string);
continue;
}
catch (const std::exception& e_string) {}
throw py::type_error("DeckKeyword: tried to add unknown type to record.");
throw py::type_error("DeckKeyword: tried to add unknown type to record.");
}
value_record_list.push_back( value_record );
@ -220,9 +247,10 @@ void python::common::export_DeckKeyword(py::module& module) {
.def("get_SI_data_list", &SI_data_to_pylist)
.def("__has_value", &DeckItem::hasValue)
.def("__defaulted", &DeckItem::defaultApplied)
.def("__is_numberic", &uda_item_is_numeric)
.def("__is_numeric", &uda_item_is_numeric)
.def("__uda_double", &get_uda_double)
.def("__uda_str", &get_uda_str)
.def("name", &DeckItem::name)
;

View File

@ -27,7 +27,7 @@ def get_item_deckitem(self):
elif self.is_double():
return self.get_raw(0)
elif self.is_uda():
if self.__is_numberic():
if self.__is_numeric():
return self.__uda_double()
else:
return self.__uda_str()

View File

@ -161,6 +161,51 @@ FIPNUM
with self.assertRaises(ValueError):
raise DeckKeyword(parser["AQANTRC"], [["1*2.2", "ABC", 8]], active_unit_system, default_unit_system)
def test_deck_kw_records_uda(self):
parser = Parser()
deck = parser.parse_string(self.REGIONDATA)
active_unit_system = deck.active_unit_system()
default_unit_system = deck.default_unit_system()
oil_target = 30000 # stb/day
well_name = "PROD"
well_status = "OPEN"
control_mode = "ORAT"
bhp_limit = 1000 # psia
wconprod = DeckKeyword(
parser["WCONPROD"],
[[well_name, well_status, control_mode, oil_target, "4*", bhp_limit]],
active_unit_system, default_unit_system)
self.assertEqual(len(wconprod), 1)
record = wconprod[0]
self.assertEqual(record[0].name(), "WELL")
self.assertTrue(record[0].is_string())
self.assertEqual(record[0].get_str(0), "PROD")
self.assertEqual(record[1].name(), "STATUS")
self.assertTrue(record[1].is_string())
self.assertEqual(record[1].get_str(0), "OPEN")
self.assertEqual(record[2].name(), "CMODE")
self.assertTrue(record[2].is_string())
self.assertEqual(record[2].get_str(0), "ORAT")
self.assertEqual(record[3].name(), "ORAT")
self.assertTrue(record[3].is_uda())
self.assertEqual(record[3].value, 30000)
self.assertEqual(record[4].name(), "WRAT")
self.assertTrue(record[4].is_uda())
self.assertEqual(record[4].value, 0)
self.assertEqual(record[5].name(), "GRAT")
self.assertTrue(record[5].is_uda())
self.assertEqual(record[5].value, 0)
self.assertEqual(record[6].name(), "LRAT")
self.assertTrue(record[6].is_uda())
self.assertEqual(record[6].value, 0)
self.assertEqual(record[7].name(), "RESV")
self.assertTrue(record[7].is_uda())
self.assertEqual(record[7].value, 0)
self.assertEqual(record[8].name(), "BHP")
self.assertTrue(record[8].is_uda())
self.assertEqual(record[8].value, 1000)
def test_deck_kw_vector(self):
parser = Parser()
@ -183,9 +228,8 @@ FIPNUM
assert( not( "ZCORN" in deck ) )
deck.add( zcorn_kw )
assert( "ZCORN" in deck )
if __name__ == "__main__":
unittest.main()

View File

@ -128,7 +128,23 @@ namespace Opm {
add_deckvalue<std::string>(std::move(deck_item), deck_record, parser_item, input_record, j);
}
break;
case type_tag::uda:
{
auto& dimensions = parser_item.dimensions();
std::vector<Dimension> active_dimensions;
std::vector<Dimension> default_dimensions;
for (const auto& dim_string : dimensions) {
active_dimensions.push_back(
system_active.parse(dim_string));
default_dimensions.push_back(
system_default.parse(dim_string));
}
DeckItem deck_item(parser_item.name(), UDAValue(),
active_dimensions, default_dimensions);
add_deckvalue<UDAValue>(std::move(deck_item),
deck_record, parser_item, input_record, j);
}
break;
default: throw std::invalid_argument("For input to DeckKeyword '" + name() + ": unsupported type. (only support for string, double and int.)");
}
}
@ -136,11 +152,8 @@ namespace Opm {
this->addRecord( std::move(deck_record) );
}
}
DeckKeyword::DeckKeyword(const ParserKeyword& parserKeyword, const std::vector<int>& data) :
DeckKeyword(parserKeyword)
{

View File

@ -47,6 +47,12 @@ DeckValue::DeckValue(const std::string& value):
string_value(value)
{}
DeckValue::DeckValue(const UDAValue& value):
default_value(false),
value_enum(type_tag::uda),
uda_value(value)
{}
bool DeckValue::is_default() const {
return default_value;
}
@ -66,7 +72,7 @@ double DeckValue::get() const {
if (value_enum == type_tag::integer)
return this->int_value;
throw std::invalid_argument("DeckValue does not hold a double value");
}
@ -78,6 +84,14 @@ std::string DeckValue::get() const {
throw std::invalid_argument("DeckValue does not hold a string value");
}
template<>
UDAValue DeckValue::get() const {
if (value_enum == type_tag::uda)
return this->uda_value;
throw std::invalid_argument("DeckValue does not hold an UDAValue");
}
template<>
bool DeckValue::is_compatible<int>() const {
return (value_enum == type_tag::integer);
@ -88,12 +102,14 @@ bool DeckValue::is_compatible<double>() const {
return (value_enum == type_tag::fdouble || value_enum == type_tag::integer);
}
template<>
bool DeckValue::is_compatible<std::string>() const {
return (value_enum == type_tag::string);
}
template<>
bool DeckValue::is_compatible<UDAValue>() const {
return (value_enum == type_tag::uda);
}
}