Update of EclIO classes.

- Enables reading of output files generated by simulator IX
 - Adding support for EclFile data type C0nn (string with length > 8 characters)
 - Update of program summary, now supporting well names with more that 8 characters
 - Updates of program convertECL, possible to write output files with IX "format"
 - updates of python bindings (EclOutput and EclFile)
This commit is contained in:
Torbjørn Skille
2020-11-10 22:02:38 +01:00
parent 3d928b8a7f
commit 9fa90b2687
22 changed files with 1037 additions and 167 deletions
+2 -2
View File
@@ -3,13 +3,13 @@
namespace convert {
py::array numpy_string_array(const std::vector<std::string>& input) {
const std::size_t target_length = 8;
const std::size_t target_length = 99;
using numpy_string_t = char[target_length];
auto output = py::array_t<numpy_string_t>(input.size());
auto output_ptr = reinterpret_cast<numpy_string_t *>(output.request().ptr);
for (std::size_t index = 0; index < input.size(); index++) {
if (input[index].size() > target_length)
throw std::invalid_argument("Current implementation only works with 8 character strings");
throw std::invalid_argument("Current implementation only works with 99 character strings");
std::size_t length = input[index].size();
std::strncpy(output_ptr[index], input[index].c_str(), length);
+10 -1
View File
@@ -43,6 +43,11 @@ public:
m_output->flushStream();
}
void writeC0nnArray(const std::string& name, const std::vector<std::string>& data, int element_size){
m_output->write(name, data, element_size);
m_output->flushStream();
}
void writeMessage(const std::string& name)
{
m_output->message(name);
@@ -70,7 +75,7 @@ npArray get_vector_index(Opm::EclIO::EclFile * file_ptr, std::size_t array_index
if (array_type == Opm::EclIO::LOGI)
return std::make_tuple (convert::numpy_array( file_ptr->get<bool>(array_index)), array_type);
if (array_type == Opm::EclIO::CHAR)
if ((array_type == Opm::EclIO::CHAR) || (array_type == Opm::EclIO::C0NN))
return std::make_tuple (convert::numpy_string_array( file_ptr->get<std::string>(array_index)), array_type);
throw std::logic_error("Data type not supported");
@@ -305,6 +310,7 @@ void python::common::export_IO(py::module& m) {
.value("REAL", Opm::EclIO::REAL)
.value("DOUB", Opm::EclIO::DOUB)
.value("CHAR", Opm::EclIO::CHAR)
.value("C0nn", Opm::EclIO::C0NN)
.value("LOGI", Opm::EclIO::LOGI)
.value("MESS", Opm::EclIO::MESS)
.export_values();
@@ -384,6 +390,9 @@ void python::common::export_IO(py::module& m) {
.def("write_message", &EclOutputBind::writeMessage)
.def("__write_char_array", (void (EclOutputBind::*)(const std::string&,
const std::vector<std::string>&)) &EclOutputBind::writeArray)
.def("__write_c0nn_array", &EclOutputBind::writeC0nnArray)
.def("__write_logi_array", (void (EclOutputBind::*)(const std::string&,
const std::vector<bool>&)) &EclOutputBind::writeArray)
.def("__write_inte_array", (void (EclOutputBind::*)(const std::string&,
+7 -4
View File
@@ -33,7 +33,7 @@ def getitem_eclfile(self, arg):
else:
data, array_type = self.__get_data(arg)
if array_type == eclArrType.CHAR:
if array_type == eclArrType.CHAR or array_type == eclArrType.C0nn:
return [ x.decode("utf-8") for x in data ]
return data
@@ -63,7 +63,7 @@ def getitem_erst(self, arg):
else:
raise ValueError("expecting tuple argument with 2 or 3 argumens: (index, rstep), (name, rstep) or (name, rstep, occurrence) ")
if array_type == eclArrType.CHAR:
if array_type == eclArrType.CHAR or array_type == eclArrType.C0nn:
return [ x.decode("utf-8") for x in data ]
return data
@@ -169,7 +169,7 @@ def getitem_erft(self, arg):
(CHAR, LOGI, INTE)
'''
def ecloutput_write(self, name, array):
def ecloutput_write(self, name, array, C0nn=False):
if isinstance(array, list):
if all(isinstance(element, str) for element in array):
@@ -197,8 +197,11 @@ def ecloutput_write(self, name, array):
self.__write_doub_array(name, array)
elif array.dtype == "bool":
self.__write_logi_array(name, array)
elif array.dtype.kind in {'U', 'S'}:
elif array.dtype.kind in {'U', 'S'} and not C0nn:
self.__write_char_array(name, array)
elif array.dtype.kind in {'U', 'S'} and C0nn:
maxStrLength = max([len(x) for x in array])
self.__write_c0nn_array(name, array, max([maxStrLength, 8]))
else:
raise ValueError("unknown array type for array {}".format(name))
+131
View File
@@ -271,6 +271,137 @@ class TestEclOutput(unittest.TestCase):
os.remove(testFile)
def test_write_strings_binary(self):
testFile = test_path("data/TMP1.INIT")
shortWelNames = ["PROD-1", "PROD-2", "PROD-3", "PROD-4", "PROD-5"]
longWelNames = ["PRODUCER-1", "PRODUCER-2", "PRODUCER-13", "PRODUCER-4"]
out1 = EclOutput(testFile)
out1.write("WGNAME", shortWelNames)
file1 = EclFile(testFile)
array = file1["WGNAME"]
self.assertEqual(len(array), len(shortWelNames))
for v1,v2 in zip (array, shortWelNames):
self.assertEqual(v1, v2)
arrayList = file1.arrays
name, arr_type, num = arrayList[0]
self.assertEqual(name, "WGNAME")
self.assertEqual(arr_type, eclArrType.CHAR)
self.assertEqual(num, len(shortWelNames))
out2 = EclOutput(testFile)
out2.write("NAMES", longWelNames)
file2 = EclFile(testFile)
array = file2["NAMES"]
self.assertEqual(len(array), len(longWelNames))
for v1,v2 in zip (array, longWelNames):
self.assertEqual(v1, v2)
arrayList = file2.arrays
name, arr_type, num = arrayList[0]
self.assertEqual(name, "NAMES")
self.assertEqual(arr_type, eclArrType.C0nn)
self.assertEqual(num, len(longWelNames))
out3 = EclOutput(testFile, formatted=False)
out3.write("NAMES", shortWelNames, C0nn=True)
file3 = EclFile(testFile)
array = file3["NAMES"]
self.assertEqual(len(array), len(shortWelNames))
for v1,v2 in zip (array, shortWelNames):
self.assertEqual(v1, v2)
arrayList = file3.arrays
name, arr_type, num = arrayList[0]
self.assertEqual(name, "NAMES")
self.assertEqual(arr_type, eclArrType.C0nn)
self.assertEqual(num, len(shortWelNames))
if os.path.isfile(testFile):
os.remove(testFile)
def test_write_strings_formattede(self):
testFile = test_path("data/TMP1.FINIT")
shortWelNames = ["PROD-1", "PROD-2", "PROD-3", "PROD-4", "PROD-5"]
longWelNames = ["PRODUCER-1", "PRODUCER-2", "PRODUCER-13", "PRODUCER-4"]
out1 = EclOutput(testFile, formatted=True)
out1.write("WGNAME", shortWelNames)
file1 = EclFile(testFile)
array = file1["WGNAME"]
self.assertEqual(len(array), len(shortWelNames))
for v1,v2 in zip (array, shortWelNames):
self.assertEqual(v1, v2)
arrayList = file1.arrays
name, arr_type, num = arrayList[0]
self.assertEqual(name, "WGNAME")
self.assertEqual(arr_type, eclArrType.CHAR)
self.assertEqual(num, len(shortWelNames))
out2 = EclOutput(testFile, formatted=True)
out2.write("NAMES", longWelNames)
file2 = EclFile(testFile)
array = file2["NAMES"]
self.assertEqual(len(array), len(longWelNames))
for v1,v2 in zip (array, longWelNames):
self.assertEqual(v1, v2)
arrayList = file2.arrays
name, arr_type, num = arrayList[0]
self.assertEqual(name, "NAMES")
self.assertEqual(arr_type, eclArrType.C0nn)
self.assertEqual(num, len(longWelNames))
out3 = EclOutput(testFile, formatted=True)
out3.write("NAMES", shortWelNames, C0nn=True)
file3 = EclFile(testFile)
array = file3["NAMES"]
self.assertEqual(len(array), len(shortWelNames))
for v1,v2 in zip (array, shortWelNames):
self.assertEqual(v1, v2)
arrayList = file3.arrays
name, arr_type, num = arrayList[0]
self.assertEqual(name, "NAMES")
self.assertEqual(arr_type, eclArrType.C0nn)
self.assertEqual(num, len(shortWelNames))
if os.path.isfile(testFile):
os.remove(testFile)
if __name__ == "__main__":