diff --git a/CMakeLists.txt b/CMakeLists.txt index 1490f2c2a..074f0d88e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -161,6 +161,7 @@ if(ENABLE_ECL_INPUT) examples/test_util/EclFilesComparator.cpp examples/test_util/EclIntegrationTest.cpp examples/test_util/EclRegressionTest.cpp + examples/test_util/EclOutput.cpp examples/test_util/EclUtil.cpp examples/test_util/summaryComparator.cpp examples/test_util/summaryIntegrationTest.cpp diff --git a/examples/test_util/EclOutput.cpp b/examples/test_util/EclOutput.cpp new file mode 100644 index 000000000..f56381823 --- /dev/null +++ b/examples/test_util/EclOutput.cpp @@ -0,0 +1,397 @@ +/* + Copyright 2019 Statoil ASA. + + This file is part of the Open Porous Media project (OPM). + + OPM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OPM is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OPM. If not, see . + */ + +#include "EclOutput.hpp" +#include "EclUtil.hpp" +#include + +#include +#include +#include +#include +#include +#include +#include + + +EclOutput::EclOutput(const std::string& inputFile, bool formatted) : + isFormatted(formatted) +{ + ofileH.open(inputFile, isFormatted ? std::ios::out : std::ios::out | std::ios::binary); +} + + +template<> +void EclOutput::write(const std::string& name, + const std::vector& data) +{ + if (isFormatted) + { + writeFormattedHeader(name, data.size(), EIOD::CHAR); + writeFormattedCharArray(data); + } + else + { + writeBinaryHeader(name, data.size(), EIOD::CHAR); + writeBinaryCharArray(data); + } +} + + +void EclOutput::writeBinaryHeader(const std::string&arrName, int size, EIOD::eclArrType arrType) +{ + std::string name = arrName + std::string(8 - arrName.size(),' '); + + int flippedSize = EIOD::flipEndianInt(size); + int bhead = EIOD::flipEndianInt(16); + + ofileH.write(reinterpret_cast(&bhead), sizeof(bhead)); + + ofileH.write(name.c_str(), 8); + ofileH.write(reinterpret_cast(&flippedSize), sizeof(flippedSize)); + + switch(arrType) { + case EIOD::INTE: + ofileH.write("INTE", 4); + break; + case EIOD::REAL: + ofileH.write("REAL", 4); + break; + case EIOD::DOUB: + ofileH.write("DOUB", 4); + break; + case EIOD::LOGI: + ofileH.write("LOGI", 4); + break; + case EIOD::CHAR: + ofileH.write("CHAR", 4); + break; + case EIOD::MESS: + ofileH.write("MESS", 4); + break; + } + + ofileH.write(reinterpret_cast(&bhead), sizeof(bhead)); +} + + +template +void EclOutput::writeBinaryArray(const std::vector& data) +{ + int rest,num,rval; + int dhead; + float value_f; + double value_d; + int intVal; + + int n = 0; + int size = data.size(); + + EIOD::eclArrType arrType = EIOD::MESS; + + if (typeid(std::vector) == typeid(std::vector)) { + arrType = EIOD::INTE; + } else if (typeid(std::vector) == typeid(std::vector)) { + arrType = EIOD::REAL; + } else if (typeid(std::vector) == typeid(std::vector)) { + arrType = EIOD::DOUB; + } else if (typeid(std::vector) == typeid(std::vector)) { + arrType = EIOD::LOGI; + } + + auto sizeData = block_size_data_binary(arrType); + + int sizeOfElement = std::get<0>(sizeData); + int maxBlockSize = std::get<1>(sizeData); + int maxNumberOfElements = maxBlockSize / sizeOfElement; + + if (!ofileH.is_open()) { + OPM_THROW(std::runtime_error, "fstream fileH not open for writing"); + } + + rest = size * sizeOfElement; + while (rest > 0) { + if (rest > maxBlockSize) { + rest -= maxBlockSize; + num = maxNumberOfElements; + } else { + num = rest / sizeOfElement; + rest = 0; + } + + dhead = EIOD::flipEndianInt(num * sizeOfElement); + + ofileH.write(reinterpret_cast(&dhead), sizeof(dhead)); + + for (int i = 0; i < num; i++) { + if (arrType == EIOD::INTE) { + rval = EIOD::flipEndianInt(data[n]); + ofileH.write(reinterpret_cast(&rval), sizeof(rval)); + } else if (arrType == EIOD::REAL) { + value_f = EIOD::flipEndianFloat(data[n]); + ofileH.write(reinterpret_cast(&value_f), sizeof(value_f)); + } else if (arrType == EIOD::DOUB) { + value_d = EIOD::flipEndianDouble(data[n]); + ofileH.write(reinterpret_cast(&value_d), sizeof(value_d)); + } else if (arrType == EIOD::LOGI) { + intVal = data[n] ? EIOD::true_value : EIOD::false_value; + ofileH.write(reinterpret_cast(&intVal), sizeOfElement); + } else { + std::cout << "type not supported in write binaryarray" << std::endl; + exit(1); + } + + n++; + } + + ofileH.write(reinterpret_cast(&dhead), sizeof(dhead)); + } +} + + +template void EclOutput::writeBinaryArray(const std::vector& data); +template void EclOutput::writeBinaryArray(const std::vector& data); +template void EclOutput::writeBinaryArray(const std::vector& data); +template void EclOutput::writeBinaryArray(const std::vector& data); +template void EclOutput::writeBinaryArray(const std::vector& data); + + +void EclOutput::writeBinaryCharArray(const std::vector& data) +{ + int num,dhead; + + int n = 0; + int size = data.size(); + + auto sizeData = EIOD::block_size_data_binary(EIOD::CHAR); + + int sizeOfElement = std::get<0>(sizeData); + int maxBlockSize = std::get<1>(sizeData); + int maxNumberOfElements = maxBlockSize / sizeOfElement; + + int rest = size * sizeOfElement; + + if (!ofileH.is_open()) { + OPM_THROW(std::runtime_error,"fstream fileH not open for writing"); + } + + while (rest > 0) { + if (rest > maxBlockSize) { + rest -= maxBlockSize; + num = maxNumberOfElements; + } else { + num = rest / sizeOfElement; + rest = 0; + } + + dhead = EIOD::flipEndianInt(num * sizeOfElement); + + ofileH.write(reinterpret_cast(&dhead), sizeof(dhead)); + + for (int i = 0; i < num; i++) { + std::string tmpStr = data[n] + std::string(8 - data[n].size(),' '); + ofileH.write(tmpStr.c_str(), sizeOfElement); + n++; + } + + ofileH.write(reinterpret_cast(&dhead), sizeof(dhead)); + } +} + + +void EclOutput::writeFormattedHeader(const std::string& arrName, int size, EIOD::eclArrType arrType) +{ + std::string name = arrName + std::string(8 - arrName.size(),' '); + + ofileH << " '" << name << "' " << std::setw(11) << size; + + switch (arrType) { + case EIOD::INTE: + ofileH << " 'INTE'" << std::endl; + break; + case EIOD::REAL: + ofileH << " 'REAL'" << std::endl; + break; + case EIOD::DOUB: + ofileH << " 'DOUB'" << std::endl; + break; + case EIOD::LOGI: + ofileH << " 'LOGI'" << std::endl; + break; + case EIOD::CHAR: + ofileH << " 'CHAR'" << std::endl; + break; + case EIOD::MESS: + ofileH << " 'MESS'" << std::endl; + break; + } +} + + +std::string EclOutput::make_real_string(float value) const +{ + char buffer [15]; + sprintf (buffer, "%10.7E", value); + + if (value == 0.0) { + return "0.00000000E+00"; + } else { + std::string tmpstr(buffer); + + int exp = value < 0.0 ? std::stoi(tmpstr.substr(11, 3)) : std::stoi(tmpstr.substr(10, 3)); + + if (value < 0.0) { + tmpstr = "-0." + tmpstr.substr(1, 1) + tmpstr.substr(3, 7) + "E"; + } else { + tmpstr = "0." + tmpstr.substr(0, 1) + tmpstr.substr(2, 7) +"E"; + } + + sprintf (buffer, "%+03i", exp+1); + tmpstr = tmpstr+buffer; + + return tmpstr; + } +} + + +std::string EclOutput::make_doub_string(double value) const +{ + char buffer [20]; + sprintf (buffer, "%19.13E", value); + + if (value == 0.0) { + return "0.00000000000000D+00"; + } else { + std::string tmpstr(buffer); + + int exp = value < 0.0 ? std::stoi(tmpstr.substr(17, 4)) : std::stoi(tmpstr.substr(16, 4)); + + if (value < 0.0) { + if (abs(exp) < 100) { + tmpstr = "-0." + tmpstr.substr(1, 1) + tmpstr.substr(3, 13) + "D"; + } else { + tmpstr = "-0." + tmpstr.substr(1, 1) + tmpstr.substr(3, 13); + } + } else { + if (abs(exp) < 100) { + tmpstr = "0." + tmpstr.substr(0, 1) + tmpstr.substr(2, 13) + "D"; + } else { + tmpstr = "0." + tmpstr.substr(0, 1) + tmpstr.substr(2, 13); + } + } + + sprintf (buffer, "%+03i", exp+1); + tmpstr = tmpstr + buffer; + + return tmpstr; + } +} + + +template +void EclOutput::writeFormattedArray(const std::vector& data) +{ + int size = data.size(); + int n = 0; + + EIOD::eclArrType arrType = EIOD::MESS; + if (typeid(T) == typeid(int)) { + arrType = EIOD::INTE; + } else if (typeid(T) == typeid(float)) { + arrType = EIOD::REAL; + } else if (typeid(T) == typeid(double)) { + arrType = EIOD::DOUB; + } else if (typeid(T) == typeid(bool)) { + arrType = EIOD::LOGI; + } + + auto sizeData = EIOD::block_size_data_formatted(arrType); + + int maxBlockSize = std::get<0>(sizeData); + int nColumns = std::get<1>(sizeData); + int columnWidth = std::get<2>(sizeData); + + for (int i = 0; i < size; i++) { + n++; + + switch (arrType) { + case EIOD::INTE: + ofileH << std::setw(columnWidth) << data[i]; + break; + case EIOD::REAL: + ofileH << std::setw(columnWidth) << make_real_string(data[i]); + break; + case EIOD::DOUB: + ofileH << std::setw(columnWidth) << make_doub_string(data[i]); + break; + case EIOD::LOGI: + if (data[i]) { + ofileH << " T"; + } else { + ofileH << " F"; + } + break; + default: + break; + } + + if ((n % nColumns) == 0 || (n % maxBlockSize) == 0) { + ofileH << std::endl; + } + + if ((n % maxBlockSize) == 0) { + n=0; + } + } + + if ((n % nColumns) != 0 && (n % maxBlockSize) != 0) { + ofileH << std::endl; + } +} + + +template void EclOutput::writeFormattedArray(const std::vector& data); +template void EclOutput::writeFormattedArray(const std::vector& data); +template void EclOutput::writeFormattedArray(const std::vector& data); +template void EclOutput::writeFormattedArray(const std::vector& data); +template void EclOutput::writeFormattedArray(const std::vector& data); + + +void EclOutput::writeFormattedCharArray(const std::vector& data) +{ + auto sizeData = EIOD::block_size_data_formatted(EIOD::CHAR); + + int nColumns = std::get<1>(sizeData); + + int size = data.size(); + + for (int i = 0; i < size; i++) { + std::string str1(8,' '); + str1 = data[i] + std::string(8 - data[i].size(),' '); + + ofileH << " '" << str1 << "'"; + + if ((i+1) % nColumns == 0) { + ofileH << std::endl; + } + } + + if ((size % nColumns) != 0) { + ofileH << std::endl; + } +} diff --git a/examples/test_util/EclOutput.hpp b/examples/test_util/EclOutput.hpp new file mode 100644 index 000000000..1d1825eb2 --- /dev/null +++ b/examples/test_util/EclOutput.hpp @@ -0,0 +1,94 @@ +/* + Copyright 2019 Statoil ASA. + + This file is part of the Open Porous Media project (OPM). + + OPM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OPM is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OPM. If not, see . + */ +#ifndef ECL_OUTPUT_HPP +#define ECL_OUTPUT_HPP + +#include +#include +#include +#include +#include + +#include + +namespace EIOD = Opm::ecl; + + +class EclOutput +{ +public: + EclOutput(const std::string& inputFile, bool formatted); + + template + void write(const std::string& name, + const std::vector& data) + { + EIOD::eclArrType arrType = EIOD::MESS; + if (typeid(T) == typeid(int)) + arrType = EIOD::INTE; + else if (typeid(T) == typeid(float)) + arrType = EIOD::REAL; + else if (typeid(T) == typeid(double)) + arrType = EIOD::DOUB; + else if (typeid(T) == typeid(bool)) + arrType = EIOD::LOGI; + else if (typeid(T) == typeid(char)) + arrType = EIOD::MESS; + + if (isFormatted) + { + writeFormattedHeader(name, data.size(), arrType); + if (arrType != EIOD::MESS) + writeFormattedArray(data); + } + else + { + writeBinaryHeader(name, data.size(), arrType); + if (arrType != EIOD::MESS) + writeBinaryArray(data); + } + } + +private: + void writeBinaryHeader(const std::string& arrName, int size, EIOD::eclArrType arrType); + + template + void writeBinaryArray(const std::vector& data); + + void writeBinaryCharArray(const std::vector& data); + + void writeFormattedHeader(const std::string& arrName, int size, EIOD::eclArrType arrType); + + template + void writeFormattedArray(const std::vector& data); + + void writeFormattedCharArray(const std::vector& data); + + std::string make_real_string(float value) const; + std::string make_doub_string(double value) const; + + std::ofstream ofileH; + bool isFormatted; +}; + + +template<> +void EclOutput::write(const std::string& name, + const std::vector& data); + +#endif