diff --git a/CMakeLists.txt b/CMakeLists.txt index e62161fe9..4ef8428d1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -300,7 +300,7 @@ if(ENABLE_ECL_INPUT) ${PROJECT_BINARY_DIR}/tests ) - foreach(test test_EclIO test_EGrid test_ERft test_ERst test_ESmry test_EInit) + foreach(test test_EclIO test_EGrid test_ERft test_ERst test_ESmry test_EInit test_ExtESmry) opm_add_test(${test} CONDITION ENABLE_ECL_INPUT AND Boost_UNIT_TEST_FRAMEWORK_FOUND LIBRARIES ${_libs} WORKING_DIRECTORY ${PROJECT_BINARY_DIR}/tests) diff --git a/CMakeLists_files.cmake b/CMakeLists_files.cmake index 3bb88cf43..4209d612b 100644 --- a/CMakeLists_files.cmake +++ b/CMakeLists_files.cmake @@ -278,9 +278,10 @@ if(ENABLE_ECL_OUTPUT) src/opm/io/eclipse/ERst.cpp src/opm/io/eclipse/ERsm.cpp src/opm/io/eclipse/ESmry.cpp + src/opm/io/eclipse/ExtESmry.cpp src/opm/io/eclipse/ESmry_write_rsm.cpp src/opm/io/eclipse/OutputStream.cpp - src/opm/io/eclipse/ESmryOutput.cpp + src/opm/io/eclipse/ExtSmryOutput.cpp src/opm/io/eclipse/RestartFileView.cpp src/opm/io/eclipse/SummaryNode.cpp src/opm/io/eclipse/rst/connection.cpp @@ -546,7 +547,7 @@ if(ENABLE_ECL_INPUT) examples/opmpack.cpp examples/opmhash.cpp examples/wellgraph.cpp - examples/make_lodsmry.cpp + examples/make_ext_smry.cpp ) endif() @@ -559,7 +560,7 @@ if(ENABLE_ECL_INPUT) examples/opmi.cpp examples/opmpack.cpp examples/opmhash.cpp - examples/make_lodsmry.cpp + examples/make_esmry.cpp ) endif() @@ -854,9 +855,10 @@ if(ENABLE_ECL_OUTPUT) opm/io/eclipse/ERst.hpp opm/io/eclipse/ERsm.hpp opm/io/eclipse/ESmry.hpp + opm/io/eclipse/ExtESmry.hpp opm/io/eclipse/PaddedOutputString.hpp opm/io/eclipse/OutputStream.hpp - opm/io/eclipse/ESmryOutput.hpp + opm/io/eclipse/ExtSmryOutput.hpp opm/io/eclipse/RestartFileView.hpp opm/io/eclipse/SummaryNode.hpp opm/io/eclipse/rst/connection.hpp diff --git a/examples/make_lodsmry.cpp b/examples/make_ext_smry.cpp similarity index 85% rename from examples/make_lodsmry.cpp rename to examples/make_ext_smry.cpp index 5e07da441..d5ba8a097 100644 --- a/examples/make_lodsmry.cpp +++ b/examples/make_ext_smry.cpp @@ -39,7 +39,7 @@ static void printHelp() { std::cout << "\nThis program create one or more lodsmry files, designed for effective load on the demand. \n" << "These files are created with input from the smspec and unsmry file. \n" << "\nIn addition, the program takes these options (which must be given before the arguments):\n\n" - << "-f if LODSMRY file exist, this will be replaced. Default behaviour is that existing file is kept.\n" + << "-f if ESMRY file exist, this will be replaced. Default behaviour is that existing file is kept.\n" << "-n Maximum number of threads to be used if mulitple files should be created.\n" << "-h Print help and exit.\n\n"; } @@ -89,21 +89,21 @@ int main(int argc, char **argv) { for (int f = argOffset; f < argc; f ++){ Opm::filesystem::path inputFileName = argv[f]; - Opm::filesystem::path lodFileName = inputFileName.parent_path() / inputFileName.stem(); - lodFileName = lodFileName += ".LODSMRY"; + Opm::filesystem::path esmryFileName = inputFileName.parent_path() / inputFileName.stem(); + esmryFileName = esmryFileName += ".ESMRY"; - if (Opm::EclIO::fileExists(lodFileName) && (force)) - remove (lodFileName); + if (Opm::EclIO::fileExists(esmryFileName) && (force)) + remove (esmryFileName); Opm::EclIO::ESmry smryFile(argv[f]); - if (!smryFile.make_lodsmry_file()){ + if (!smryFile.make_esmry_file()){ std::cout << "\n! Warning, smspec already have one lod file, existing kept use option -f to replace this" << std::endl; } } auto lap1 = std::chrono::system_clock::now(); std::chrono::duration elapsed_seconds1 = lap1-lap0; - std::cout << "\nruntime for creating " << (argc-argOffset) << " LODSMRY files: " << elapsed_seconds1.count() << " seconds\n" << std::endl; + std::cout << "\nruntime for creating " << (argc-argOffset) << " ESMRY files: " << elapsed_seconds1.count() << " seconds\n" << std::endl; return 0; } diff --git a/opm/io/eclipse/ESmry.hpp b/opm/io/eclipse/ESmry.hpp index 3e7a709b6..31dd28203 100644 --- a/opm/io/eclipse/ESmry.hpp +++ b/opm/io/eclipse/ESmry.hpp @@ -35,6 +35,7 @@ namespace Opm { namespace EclIO { using ArrSourceEntry = std::tuple; using TimeStepEntry = std::tuple; +using RstEntry = std::tuple; class ESmry { @@ -58,7 +59,7 @@ public: void LoadData(const std::vector& vectList) const; void LoadData() const; - bool make_lodsmry_file(); + bool make_esmry_file(); time_point startdate() const { return startdat; } @@ -79,7 +80,10 @@ public: bool all_steps_available(); private: + filesystem::path inputFileName; + RstEntry restart_info; + int nI, nJ, nK, nSpecFiles; bool fromSingleRun; size_t nVect, nTstep; @@ -98,6 +102,7 @@ private: std::vector> keywordListSpecFile; std::vector seqIndex; + std::vector mini_steps; void ijk_from_global_index(int glob, int &i, int &j, int &k) const; @@ -138,6 +143,7 @@ private: std::vector makeKeywPosVector(int speInd) const; std::string read_string_from_disk(std::fstream& fileH, uint64_t size) const; + void read_ministeps_from_disk(); int read_ministep_formatted(std::fstream& fileH); }; diff --git a/opm/io/eclipse/ExtESmry.hpp b/opm/io/eclipse/ExtESmry.hpp new file mode 100644 index 000000000..067c7d816 --- /dev/null +++ b/opm/io/eclipse/ExtESmry.hpp @@ -0,0 +1,104 @@ +/* + Copyright 2019 Equinor 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 OPM_IO_ExtESmry_HPP +#define OPM_IO_ExtESmry_HPP + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace Opm { namespace EclIO { + +using ArrSourceEntry = std::tuple; +using TimeStepEntry = std::tuple; +using RstEntry = std::tuple; + +// start, rstart + rstnum, keycheck, units, rstep, tstep +using LodsmryHeadType = std::tuple, std::vector, + std::vector, std::vector>; + +class ExtESmry +{ +public: + + // input is esmry, only binary supported. + explicit ExtESmry(const std::string& filename, bool loadBaseRunData=false); + + const std::vector& get(const std::string& name); + std::vector get_at_rstep(const std::string& name); + std::string& get_unit(const std::string& name); + + void loadData(); + void loadData(const std::vector& stringVect); + + bool hasKey(const std::string& key) const; + + size_t numberOfTimeSteps() const { return m_nTstep; } + size_t numberOfVectors() const { return m_nVect; } + + const std::vector& keywordList() const { return m_keyword;} + std::vector keywordList(const std::string& pattern) const; + + std::vector dates(); + + bool all_steps_available(); + + +private: + filesystem::path m_inputFileName; + std::vector m_lodsmry_files; + + bool m_loadBaseRun; + std::vector> m_keyword_index; + std::vector> m_tstep_range; + std::vector m_keyword; + std::vector m_rstep; + std::vector m_tstep; + std::vector> m_rstep_v; + std::vector> m_tstep_v; + std::vector> m_vectorData; + std::vector m_vectorLoaded; + std::unordered_map kwunits; + + size_t m_nVect; + std::vector m_nTstep_v; + size_t m_nTstep; + std::vector m_seqIndex; + + std::vector m_lod_offset; + std::vector m_lod_arr_size; + + time_point m_startdat; + + uint64_t open_esmry(Opm::filesystem::path& inputFileName, LodsmryHeadType& lodsmry_head); + + void updatePathAndRootName(Opm::filesystem::path& dir, Opm::filesystem::path& rootN); +}; + +}} // namespace Opm::EclIO + + +#endif // OPM_IO_ExtESmry_HPP diff --git a/opm/io/eclipse/ESmryOutput.hpp b/opm/io/eclipse/ExtSmryOutput.hpp similarity index 87% rename from opm/io/eclipse/ESmryOutput.hpp rename to opm/io/eclipse/ExtSmryOutput.hpp index 583ed0778..a78201335 100644 --- a/opm/io/eclipse/ESmryOutput.hpp +++ b/opm/io/eclipse/ExtSmryOutput.hpp @@ -16,8 +16,8 @@ along with OPM. If not, see . */ -#ifndef OPM_IO_ESMRYOUTPUT_HPP -#define OPM_IO_ESMRYOUTPUT_HPP +#ifndef OPM_IO_ExtSmryOutput_HPP +#define OPM_IO_ExtSmryOutput_HPP #include @@ -33,11 +33,11 @@ class EclipseState; namespace Opm { namespace EclIO { -class ESmryOutput +class ExtSmryOutput { public: - ESmryOutput(const std::vector& valueKeys, const std::vector& valueUnits, + ExtSmryOutput(const std::vector& valueKeys, const std::vector& valueUnits, const EclipseState& es, const time_t start_time); void write(const std::vector& ts_data, int report_step); @@ -65,4 +65,4 @@ private: }} // namespace Opm::EclIO -#endif // OPM_IO_ESMRYOUTPUT_HPP +#endif // OPM_IO_ExtSmryOutput_HPP diff --git a/src/opm/io/eclipse/ESmry.cpp b/src/opm/io/eclipse/ESmry.cpp index bde4132c3..dfea94be5 100644 --- a/src/opm/io/eclipse/ESmry.cpp +++ b/src/opm/io/eclipse/ESmry.cpp @@ -193,6 +193,24 @@ ESmry::ESmry(const std::string &filename, bool loadBaseRunData) : keywordListSpecFile.push_back(combindKeyList); getRstString(restartArray, pathRstFile, rstRootN); + if (rstRootN.string() != ""){ + + auto abs_rst_file = Opm::filesystem::canonical(pathRstFile) / rstRootN; + Opm::filesystem::path rel_path; + + if (inputFileName.parent_path().string() == "") + rel_path = Opm::filesystem::proximate(abs_rst_file); + else + rel_path = Opm::filesystem::proximate(abs_rst_file, inputFileName.parent_path()); + + if (abs_rst_file.string().size() < rel_path.string().size()) + restart_info = std::make_tuple(abs_rst_file.string(), dimens[5]); + else + restart_info = std::make_tuple(rel_path.string(), dimens[5]); + } + else + restart_info = std::make_tuple("", 0); + smryArray.push_back({smspec_file.string(), dimens[5]}); } @@ -335,8 +353,6 @@ ESmry::ESmry(const std::string &filename, bool loadBaseRunData) : vectorLoaded.push_back(false); } - // inspecting time step data, unified summary or multiple summary files both formatted or binary. - // this also include base run data if loadBaseRunData=true and restart runs exists. int dataFileIndex = -1; @@ -460,14 +476,13 @@ ESmry::ESmry(const std::string &filename, bool loadBaseRunData) : nTstep = timeStepList.size(); } - } -bool ESmry::all_steps_available() +void ESmry::read_ministeps_from_disk() { auto specInd = std::get<0>(miniStepList[0]); auto dataFileIndex = std::get<1>(miniStepList[0]); - uint64_t stepFilePos = std::get<2>(miniStepList[0]); + uint64_t stepFilePos; std::fstream fileH; @@ -476,21 +491,9 @@ bool ESmry::all_steps_available() else fileH.open(dataFileList[dataFileIndex], std::ios::in | std::ios::binary); - fileH.seekg (stepFilePos , fileH.beg); - int ministep_value; - if (formattedFiles[specInd]) { - ministep_value = read_ministep_formatted(fileH); - } else { - std::function f = Opm::EclIO::flipEndianInt; - auto ministep_vect = readBinaryArray(fileH, 1, Opm::EclIO::INTE, f, sizeOfInte); - ministep_value = ministep_vect[0]; - } - - int prev_value = ministep_value; - - for (size_t n = 1; n < miniStepList.size(); n++) { + for (size_t n = 0; n < miniStepList.size(); n++) { if (dataFileIndex != std::get<1>(miniStepList[n])) { fileH.close(); @@ -515,15 +518,20 @@ bool ESmry::all_steps_available() ministep_value = ministep_vect[0]; } - if ((ministep_value - prev_value) > 1){ - fileH.close(); - return false; - } - - prev_value = ministep_value; + mini_steps.push_back(ministep_value); } fileH.close(); +} + +bool ESmry::all_steps_available() +{ + if (mini_steps.size() == 0) + this->read_ministeps_from_disk(); + + for (size_t n = 1; n < mini_steps.size(); n++) + if ((mini_steps[n] - mini_steps[n-1]) > 1) + return false; return true; } @@ -879,23 +887,23 @@ ESmry::getListOfArrays(std::string filename, bool formatted) return resultVect; } -bool ESmry::make_lodsmry_file() +bool ESmry::make_esmry_file() { // check that loadBaseRunData is not set, this function only works for single smspec files // function will not replace existing lodsmry files (since this is already loaded by this class) // if lodsmry file exist, this function will return false and do nothing. if (!fromSingleRun) - OPM_THROW(std::invalid_argument, "creating lodsmry file only possible when loadBaseRunData=false"); + OPM_THROW(std::invalid_argument, "creating esmry file only possible when loadBaseRunData=false"); + + if (mini_steps.size() == 0) + this->read_ministeps_from_disk(); Opm::filesystem::path path = inputFileName.parent_path(); Opm::filesystem::path rootName = inputFileName.stem(); Opm::filesystem::path smryDataFile; - if (formattedFiles[0]) - smryDataFile = path / rootName += ".FLODSMRY"; - else - smryDataFile = path / rootName += ".LODSMRY"; + smryDataFile = path / rootName += ".ESMRY"; if (Opm::EclIO::fileExists(smryDataFile)) { @@ -903,53 +911,43 @@ bool ESmry::make_lodsmry_file() } else { - std::vector keycheck; - keycheck.reserve(keyword.size()); - - std::string str1; - std::string str2; - std::string str3; - - for (auto key : keyword){ - - str2=""; - str3=""; - - if (key.size() > 24) - str1 = key.substr(0,24); - else - str1 = key; - - if (str1.size() > 8){ - str2 = str1.substr(8); - str1 = str1.substr(0,8); - } - - if (str2.size() > 8){ - str3 = str2.substr(8); - str2 = str2.substr(0,8); - } - - keycheck.push_back(str1); - keycheck.push_back(str2); - keycheck.push_back(str3); - } - - std::vector is_rstep; + std::vector is_rstep; is_rstep.reserve(timeStepList.size()); for (size_t i = 0; i < timeStepList.size(); i++) if(std::find(seqIndex.begin(), seqIndex.end(), i) != seqIndex.end()) - is_rstep.push_back(true); + is_rstep.push_back(1); else - is_rstep.push_back(false); + is_rstep.push_back(0); this->LoadData(); { - Opm::EclIO::EclOutput outFile(smryDataFile, formattedFiles[0], std::ios::out); - outFile.write("KEYCHECK", keycheck); - outFile.write("RSTEP", is_rstep); + Opm::TimeStampUTC ts( std::chrono::system_clock::to_time_t( startdat )); + + std::vector start_date_vect = {ts.day(), ts.month(), ts.year(), ts.hour(), + ts.minutes(), ts.seconds(), 0 }; + + std::vector units; + units.reserve(keyword.size()); + + for (auto key : keyword) + units.push_back(kwunits.at(key)); + + Opm::EclIO::EclOutput outFile(smryDataFile, false, std::ios::out); + + outFile.write("START", start_date_vect); + + if (std::get<0>(restart_info) != ""){ + auto rst_file = std::get<0>(restart_info); + outFile.write("RESTART", {rst_file}); + outFile.write("RSTNUM", {std::get<1>(restart_info)}); + } + + outFile.write("KEYCHECK", keyword); + outFile.write("UNITS", units); + outFile.write("RSTEP", is_rstep); + outFile.write("TSTEP", mini_steps); for (size_t n = 0; n < vectorData.size(); n++ ) { const std::string vect_name = fmt::format("V{}", n); diff --git a/src/opm/io/eclipse/ExtESmry.cpp b/src/opm/io/eclipse/ExtESmry.cpp new file mode 100644 index 000000000..cf6850e0d --- /dev/null +++ b/src/opm/io/eclipse/ExtESmry.cpp @@ -0,0 +1,474 @@ +/* + Copyright 2019 Equinor 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 + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace { + +Opm::time_point make_date(const std::vector& datetime) { + auto day = datetime[0]; + auto month = datetime[1]; + auto year = datetime[2]; + auto hour = 0; + auto minute = 0; + auto second = 0; + + if (datetime.size() == 6) { + hour = datetime[3]; + minute = datetime[4]; + auto total_usec = datetime[5]; + second = total_usec / 1000000; + } + + + const auto ts = Opm::TimeStampUTC{ Opm::TimeStampUTC::YMD{ year, month, day}}.hour(hour).minutes(minute).seconds(second); + return Opm::TimeService::from_time_t( Opm::asTimeT(ts) ); +} + + +} + + +/* + + KEYWORDS WGNAMES NUMS | PARAM index Corresponding ERT key + ------------------------------------------------+-------------------------------------------------- + WGOR OP_1 0 | 0 WGOR:OP_1 + FOPT +-+-+-+- 0 | 1 FOPT + WWCT OP_1 0 | 2 WWCT:OP_1 + WIR OP_1 0 | 3 WIR:OP_1 + WGOR WI_1 0 | 4 WWCT:OP_1 + WWCT W1_1 0 | 5 WWCT:WI_1 + BPR +-+-+- 12675 | 6 BPR:12675, BPR:i,j,k + RPR +-+-+- 1 | 7 RPR:1 + FOPT +-+-+- 0 | 8 FOPT + GGPR NORTH 0 | 9 GGPR:NORTH + COPR OP_1 5628 | 10 COPR:OP_1:56286, COPR:OP_1:i,j,k + RXF +-+-+- 32768*R1(R2 + 10) | 11 RXF:2-3 + SOFX OP_1 12675 | 12 SOFX:OP_1:12675, SOFX:OP_1:i,j,jk + +*/ + + +namespace Opm { namespace EclIO { + +ExtESmry::ExtESmry(const std::string &filename, bool loadBaseRunData) : + m_inputFileName { filename }, + m_loadBaseRun(loadBaseRunData) +{ + if (m_inputFileName.extension()=="") + m_inputFileName+=".ESMRY"; + + if (m_inputFileName.extension()!=".ESMRY") + throw std::invalid_argument("Input file should have extension .ESMRY"); + + m_lodsmry_files.push_back(m_inputFileName); + + Opm::filesystem::path rootName = m_inputFileName.parent_path() / m_inputFileName.stem(); + Opm::filesystem::path path = Opm::filesystem::current_path(); + + Opm::filesystem::path rstRootN; + + updatePathAndRootName(path, rootName); + + LodsmryHeadType lodsmry_head; + + auto lod_offset = open_esmry(m_inputFileName, lodsmry_head); + + m_startdat = std::get<0>(lodsmry_head); + + m_lod_offset.push_back(lod_offset); + + std::map key_index; + + auto keyword = std::get<2>(lodsmry_head); + auto units = std::get<3>(lodsmry_head); + + for (size_t n = 0; n < keyword.size(); n++){ + key_index[keyword[n]] = n; + m_keyword.push_back(keyword[n]); + } + + m_keyword_index.push_back(key_index); + + for (size_t n = 0; n < m_keyword.size(); n++) + kwunits[m_keyword[n]] = units[n]; + + RstEntry rst_entry = std::get<1>(lodsmry_head); + + m_rstep_v.push_back(std::get<4>(lodsmry_head)); + m_tstep_v.push_back(std::get<5>(lodsmry_head)); + + m_nTstep_v.push_back(m_tstep_v.back().size()); + + auto lod_arr_size = sizeOnDiskBinary(m_nTstep_v.back(), Opm::EclIO::REAL, sizeOfReal); + + m_lod_arr_size.push_back(lod_arr_size); + + m_tstep_range.push_back(std::make_tuple(0, m_tstep_v.back().size() - 1)); + + int sim_ind = 0; + + if ((loadBaseRunData) and (std::get<0>(rst_entry) !="")){ + + auto restart = std::get<0>(rst_entry); + auto rstNum = std::get<1>(rst_entry); + + while (restart != ""){ + sim_ind++; + + rstRootN = Opm::filesystem::path(restart); + + updatePathAndRootName(path, rstRootN); + + Opm::filesystem::path rstLodSmryFile = path / rstRootN; + rstLodSmryFile += ".ESMRY"; + + m_lodsmry_files.push_back(rstLodSmryFile); + + lod_offset = open_esmry(rstLodSmryFile, lodsmry_head); + + m_lod_offset.push_back(lod_offset); + + m_rstep_v.push_back(std::get<4>(lodsmry_head)); + m_tstep_v.push_back(std::get<5>(lodsmry_head)); + + m_nTstep_v.push_back(m_tstep_v.back().size()); + + lod_arr_size = sizeOnDiskBinary(m_nTstep_v.back(), Opm::EclIO::REAL, sizeOfReal); + m_lod_arr_size.push_back(lod_arr_size); + + int cidx = 0; + + auto it = std::find_if(m_rstep_v[sim_ind].begin(), m_rstep_v[sim_ind].end(), + [&cidx, &rstNum](const int & val) + { + if (val == 1) + ++cidx; + + return cidx == rstNum; + }); + + size_t ind = std::distance(m_rstep_v[sim_ind].begin(), it); + + m_tstep_range.push_back(std::make_tuple(0, ind)); + + key_index.clear(); + keyword = std::get<2>(lodsmry_head); + + for (size_t n = 0; n < keyword.size(); n++) + key_index[keyword[n]] = n; + + m_keyword_index.push_back(key_index); + + rst_entry = std::get<1>(lodsmry_head); + restart = std::get<0>(rst_entry); + rstNum = std::get<1>(rst_entry); + } + } + + m_nVect = m_keyword.size(); + + m_vectorData.resize(m_nVect, {}); + m_vectorLoaded.resize(m_nVect, false); + + int ind = static_cast(m_tstep_range.size()) - 1 ; + + while (ind > -1) { + int to_ind = std::get<1>(m_tstep_range[ind]); + m_rstep.insert(m_rstep.end(), m_rstep_v[ind].begin(), m_rstep_v[ind].begin() + to_ind + 1); + m_tstep.insert(m_tstep.end(), m_tstep_v[ind].begin(), m_tstep_v[ind].begin() + to_ind + 1); + ind--; + } + + m_nTstep = m_rstep.size(); + + for (size_t m = 0; m < m_rstep.size(); m++) + if (m_rstep[m] == 1) + m_seqIndex.push_back(m); +} + + +std::vector ExtESmry::get_at_rstep(const std::string& name) +{ + auto full_vect = this->get(name); + + std::vector rs_vect; + rs_vect.reserve(m_seqIndex.size()); + + for (auto r : m_seqIndex) + rs_vect.push_back(full_vect[r]); + + return rs_vect; +} + +std::string& ExtESmry::get_unit(const std::string& name) +{ + if ( m_keyword_index[0].find(name) == m_keyword_index[0].end() ) + throw std::invalid_argument("summary key '" + name + "' not found"); + + return kwunits.at(name); +} + +bool ExtESmry::all_steps_available() +{ + for (size_t n = 1; n < m_tstep.size(); n++) + if ((m_tstep[n] - m_tstep[n-1]) > 1) + return false; + + return true; +} + +uint64_t ExtESmry::open_esmry(Opm::filesystem::path& inputFileName, LodsmryHeadType& lodsmry_head) +{ + std::fstream fileH; + + fileH.open(inputFileName, std::ios::in | std::ios::binary); + + if (!fileH) + throw std::runtime_error("Can not open file "); + + + std::string arrName; + int64_t arr_size; + Opm::EclIO::eclArrType arrType; + int sizeOfElement; + + Opm::EclIO::readBinaryHeader(fileH, arrName, arr_size, arrType, sizeOfElement); + + if ((arrName != "START ") or (arrType != Opm::EclIO::INTE)) + OPM_THROW(std::invalid_argument, "reading start, invalid lod file"); + + auto start_vect = Opm::EclIO::readBinaryInteArray(fileH, arr_size); + + auto startdat = make_date(start_vect); + + Opm::EclIO::readBinaryHeader(fileH, arrName, arr_size, arrType, sizeOfElement); + + Opm::EclIO::RstEntry rst_entry = std::make_tuple("", 0); + + if (arrName == "RESTART "){ + + if (m_loadBaseRun) { + + std::vector rstfile = Opm::EclIO::readBinaryC0nnArray(fileH, arr_size, sizeOfElement); + Opm::EclIO::readBinaryHeader(fileH, arrName, arr_size, arrType, sizeOfElement); + std::vector rst_num = Opm::EclIO::readBinaryInteArray(fileH, arr_size); + + rst_entry = std::make_tuple(rstfile[0], rst_num[0]); + + } else { + uint64_t numIgnore = sizeOnDiskBinary(arr_size, arrType, sizeOfElement); + numIgnore = numIgnore + 24 + sizeOnDiskBinary(1, Opm::EclIO::INTE, Opm::EclIO::sizeOfInte); + fileH.seekg(static_cast(numIgnore), std::ios_base::cur); + } + + Opm::EclIO::readBinaryHeader(fileH, arrName, arr_size, arrType, sizeOfElement); + } + + if (arrName != "KEYCHECK") + OPM_THROW(std::invalid_argument, "!!reading keycheck, invalid lod file"); + + std::vector keywords; + + keywords = Opm::EclIO::readBinaryC0nnArray(fileH, arr_size, sizeOfElement); + + Opm::EclIO::readBinaryHeader(fileH, arrName, arr_size, arrType, sizeOfElement); + + if (arrName != "UNITS ") + OPM_THROW(std::invalid_argument, "reading UNITS, invalid lod file"); + + auto units = Opm::EclIO::readBinaryC0nnArray(fileH, arr_size, sizeOfElement); + + if (keywords.size() != units.size()) + throw std::runtime_error("invalied LODSMRY file, size of units not equal size of keywords"); + + Opm::EclIO::readBinaryHeader(fileH, arrName, arr_size, arrType, sizeOfElement); + + if ((arrName != "RSTEP ") or (arrType != Opm::EclIO::INTE)) + OPM_THROW(std::invalid_argument, "reading RSTEP, invalid lod file"); + + auto rstep = Opm::EclIO::readBinaryInteArray(fileH, arr_size); + + Opm::EclIO::readBinaryHeader(fileH, arrName, arr_size, arrType, sizeOfElement); + + if ((arrName != "TSTEP ") or (arrType != Opm::EclIO::INTE)) + OPM_THROW(std::invalid_argument, "reading TSTEP, invalid lod file"); + + auto tstep = Opm::EclIO::readBinaryInteArray(fileH, arr_size); + + lodsmry_head = std::make_tuple(startdat, rst_entry, keywords, units, rstep, tstep); + + uint64_t lodsmry_offset = static_cast(fileH.tellg()); + + fileH.close(); + + return lodsmry_offset; +} + + +void ExtESmry::updatePathAndRootName(Opm::filesystem::path& dir, Opm::filesystem::path& rootN) { + + if (rootN.parent_path().is_absolute()){ + dir = rootN.parent_path(); + } else { + dir = dir / rootN.parent_path(); + } + + rootN = rootN.stem(); +} + + +void ExtESmry::loadData(const std::vector& stringVect) +{ + std::vector keyIndexVect; + + for (auto key: stringVect) + keyIndexVect.push_back(m_keyword_index[0].at(key)); + + std::fstream fileH; + + int ind = static_cast(m_tstep_range.size()) - 1 ; + + while (ind > -1) { + + int to_ind = std::get<1>(m_tstep_range[ind]); + + fileH.open(m_lodsmry_files[ind], std::ios::in | std::ios::binary); + + if (!fileH) + throw std::runtime_error("Can not open file lodFile"); + + for (size_t n = 0 ; n < stringVect.size(); n++) { + + std::string key = stringVect[n]; + + std::string arrName; + int64_t size; + Opm::EclIO::eclArrType arrType; + int sizeOfElement; + + if ( m_keyword_index[ind].find(key) == m_keyword_index[ind].end() ) { + + for (int m = 0; m < to_ind + 1; m++) + m_vectorData[keyIndexVect[n]].push_back(0.0); + + } else { + + int key_ind = m_keyword_index[ind].at(key); + + uint64_t pos = m_lod_offset[ind] + m_lod_arr_size[ind]*static_cast(key_ind); + pos = pos + static_cast(key_ind * 24); // adding size of binary headers + + fileH.seekg (pos, fileH.beg); + + readBinaryHeader(fileH, arrName, size, arrType, sizeOfElement); + + arrName = Opm::EclIO::trimr(arrName); + + std::string checkName = "V" + std::to_string(key_ind); + + if (arrName != checkName) + OPM_THROW(std::invalid_argument, "lodsmry, wrong header expecting " + checkName + " found " + arrName); + + auto smry_data = readBinaryRealArray(fileH, size); + + m_vectorData[keyIndexVect[n]].insert(m_vectorData[keyIndexVect[n]].end(), smry_data.begin(), smry_data.begin() + to_ind + 1); + } + + fileH.close(); + + ind--; + } + } + + for (auto kind : keyIndexVect) + m_vectorLoaded[kind] = true; +} + +void ExtESmry::loadData() +{ + this->loadData(m_keyword); +} + +const std::vector& ExtESmry::get(const std::string& name) +{ + if ( m_keyword_index[0].find(name) == m_keyword_index[0].end() ) + throw std::invalid_argument("summary key '" + name + "' not found"); + + int index = m_keyword_index[0].at(name); + + if (!m_vectorLoaded[index]){ + loadData({name}); + } + + return m_vectorData[index]; +} + +std::vector ExtESmry::dates() { + double time_unit = 24 * 3600; + std::vector d; + + for (const auto& t : this->get("TIME")) + d.push_back( this->m_startdat + std::chrono::duration_cast( std::chrono::duration( t * time_unit))); + + return d; +} + +std::vector ExtESmry::keywordList(const std::string& pattern) const +{ + std::vector list; + + for (auto key : m_keyword) + if (fnmatch( pattern.c_str(), key.c_str(), 0 ) == 0 ) + list.push_back(key); + + return list; +} + +bool ExtESmry::hasKey(const std::string &key) const +{ + return std::find(m_keyword.begin(), m_keyword.end(), key) != m_keyword.end(); +} + + + +}} // namespace Opm::ecl + diff --git a/src/opm/io/eclipse/ESmryOutput.cpp b/src/opm/io/eclipse/ExtSmryOutput.cpp similarity index 91% rename from src/opm/io/eclipse/ESmryOutput.cpp rename to src/opm/io/eclipse/ExtSmryOutput.cpp index b68e6cbed..946573e55 100644 --- a/src/opm/io/eclipse/ESmryOutput.cpp +++ b/src/opm/io/eclipse/ExtSmryOutput.cpp @@ -18,7 +18,7 @@ #include #include -#include +#include #include #include @@ -32,7 +32,7 @@ namespace Opm { namespace EclIO { -ESmryOutput::ESmryOutput(const std::vector& valueKeys, const std::vector& valueUnits, +ExtSmryOutput::ExtSmryOutput(const std::vector& valueKeys, const std::vector& valueUnits, const EclipseState& es, const time_t start_time) { m_nVect = valueKeys.size(); @@ -71,7 +71,7 @@ ESmryOutput::ESmryOutput(const std::vector& valueKeys, const std::v } -void ESmryOutput::write(const std::vector& ts_data, int report_step) +void ExtSmryOutput::write(const std::vector& ts_data, int report_step) { if (ts_data.size() != static_cast(m_nVect)) @@ -116,7 +116,7 @@ void ESmryOutput::write(const std::vector& ts_data, int report_step) } -std::vector ESmryOutput::make_modified_keys(const std::vector valueKeys, const GridDims& dims) +std::vector ExtSmryOutput::make_modified_keys(const std::vector valueKeys, const GridDims& dims) { std::vector mod_keys; mod_keys.reserve(valueKeys.size()); @@ -164,7 +164,7 @@ std::vector ESmryOutput::make_modified_keys(const std::vector ESmryOutput::ijk_from_global_index(const GridDims& dims, int globInd) const +std::array ExtSmryOutput::ijk_from_global_index(const GridDims& dims, int globInd) const { if (globInd < 0 || static_cast(globInd) >= dims[0] * dims[1] * dims[2]) diff --git a/src/opm/output/eclipse/Summary.cpp b/src/opm/output/eclipse/Summary.cpp index 7953db075..fd64d95ec 100644 --- a/src/opm/output/eclipse/Summary.cpp +++ b/src/opm/output/eclipse/Summary.cpp @@ -52,7 +52,7 @@ #include #include -#include +#include #include #include @@ -3251,7 +3251,7 @@ private: std::unique_ptr smspec_{}; std::unique_ptr stream_{}; - std::unique_ptr esmry_; + std::unique_ptr esmry_; void configureTimeVectors(const EclipseState& es, const SummaryConfig& sumcfg); @@ -3314,7 +3314,7 @@ SummaryImplementation(const EclipseState& es, Opm::filesystem::remove(esmryFileName); if ((writeEsmry) and (es.cfg().io().getFMTOUT()==false)) - this->esmry_ = std::make_unique(this->valueKeys_, this->valueUnits_, es, sched.posixStartTime()); + this->esmry_ = std::make_unique(this->valueKeys_, this->valueUnits_, es, sched.posixStartTime()); if ((writeEsmry) and (es.cfg().io().getFMTOUT())) OpmLog::warning("ESMRY only supported for unformatted output. Request ignored."); diff --git a/test_util/convertECL.cpp b/test_util/convertECL.cpp index 3d907f765..e0ab2120e 100644 --- a/test_util/convertECL.cpp +++ b/test_util/convertECL.cpp @@ -196,10 +196,10 @@ int main(int argc, char **argv) { } std::map to_formatted = {{".EGRID", ".FEGRID"}, {".INIT", ".FINIT"}, {".SMSPEC", ".FSMSPEC"}, - {".UNSMRY", ".FUNSMRY"}, {".UNRST", ".FUNRST"}, {".RFT", ".FRFT"}, {".LODSMRY", ".FLODSMRY"}}; + {".UNSMRY", ".FUNSMRY"}, {".UNRST", ".FUNRST"}, {".RFT", ".FRFT"}, {".ESMRY", ".FESMRY"}}; std::map to_binary = {{".FEGRID", ".EGRID"}, {".FINIT", ".INIT"}, {".FSMSPEC", ".SMSPEC"}, - {".FUNSMRY", ".UNSMRY"}, {".FUNRST", ".UNRST"}, {".FRFT", ".RFT"}, {".FLODSMRY", ".LODSMRY"}}; + {".FUNSMRY", ".UNSMRY"}, {".FUNRST", ".UNRST"}, {".FRFT", ".RFT"}, {".FESMRY", ".ESMRY"}}; if (formattedOutput) { diff --git a/test_util/summary.cpp b/test_util/summary.cpp index c4f19264e..6ca898ffc 100644 --- a/test_util/summary.cpp +++ b/test_util/summary.cpp @@ -25,6 +25,12 @@ #include #include +#include + +enum smryFileType { + SMSPEC, ESMRY +}; + static void printHelp() { @@ -89,11 +95,34 @@ int main(int argc, char **argv) { int argOffset = optind; + std::unique_ptr esmry; + std::unique_ptr ext_esmry; + std::string filename = argv[argOffset]; - Opm::EclIO::ESmry smryFile(filename); + Opm::filesystem::path inputFileName(filename); + + if (inputFileName.extension()=="") + inputFileName+=".SMSPEC"; + + smryFileType filetype; + + if (inputFileName.extension()==".SMSPEC"){ + filetype = SMSPEC; + esmry = std::make_unique(inputFileName); + } else if (inputFileName.extension()==".ESMRY"){ + filetype = ESMRY; + ext_esmry = std::make_unique(inputFileName); + } else + throw std::runtime_error("invalid input file for summary"); + if (listKeys){ - auto list = smryFile.keywordList(); + std::vector list; + + switch(filetype) { + case SMSPEC: list = esmry->keywordList(); break; + case ESMRY: list = ext_esmry->keywordList(); break; + } for (size_t n = 0; n < list.size(); n++){ std::cout << std::setw(20) << list[n]; @@ -110,10 +139,31 @@ int main(int argc, char **argv) { std::vector smryList; for (int i=0; ihasKey(argv[i+argOffset+1]); + break; + case ESMRY: + hasKey = ext_esmry->hasKey(argv[i+argOffset+1]); + break; + } + + if (hasKey) { smryList.push_back(argv[i+argOffset+1]); } else { - auto list = smryFile.keywordList(argv[i+argOffset+1]); + std::vector list; + + switch(filetype) { + case SMSPEC: + list = esmry->keywordList(argv[i+argOffset+1]); + break; + case ESMRY: + list = ext_esmry->keywordList(argv[i+argOffset+1]); + break; + } if (list.size()==0) { std::string message = "Key " + std::string(argv[i+argOffset+1]) + " not found in summary file " + filename; @@ -138,9 +188,18 @@ int main(int argc, char **argv) { for (auto name : smryList) width.push_back(name.size()); - for (auto key : smryList) { - std::vector vect = reportStepsOnly ? smryFile.get_at_rstep(key) : smryFile.get(key); + std::vector vect; + + switch(filetype) { + case SMSPEC: + vect = reportStepsOnly ? esmry->get_at_rstep(key) : esmry->get(key); + break; + case ESMRY: + vect = reportStepsOnly ? ext_esmry->get_at_rstep(key) : ext_esmry->get(key); + break; + } + smryData.push_back(vect); } diff --git a/tests/test_ESmry.cpp b/tests/test_ESmry.cpp index 3cc4a72d6..cd94856f4 100644 --- a/tests/test_ESmry.cpp +++ b/tests/test_ESmry.cpp @@ -419,8 +419,6 @@ BOOST_AUTO_TEST_CASE(TestUnits) { BOOST_AUTO_TEST_CASE(Test_all_available) { - std::cout << "all good \n"; - std::vector keywords = {"TIME ", "YEARS", "FGOR", "FOPR", "WBHP" , "WBHP", "WOPR", "WWIR"}; @@ -606,7 +604,8 @@ BOOST_AUTO_TEST_CASE(Test_all_available_w_restart) { // all mini steps 2 in base run missing - BOOST_CHECK_EQUAL( smry1.all_steps_available(), false); + Opm::EclIO::ESmry smry2("RST2.SMSPEC", true); + BOOST_CHECK_EQUAL( smry2.all_steps_available(), false); { Opm::EclIO::EclOutput smspec1("BASE1.UNSMRY", false); @@ -646,7 +645,9 @@ BOOST_AUTO_TEST_CASE(Test_all_available_w_restart) { // all mini steps 2 in restart run missing - BOOST_CHECK_EQUAL( smry1.all_steps_available(), false); + Opm::EclIO::ESmry smry3("RST2.SMSPEC", true); + + BOOST_CHECK_EQUAL( smry3.all_steps_available(), false); if (Opm::filesystem::exists("BASE1.SMSPEC")) Opm::filesystem::remove("BASE1.SMSPEC"); @@ -660,3 +661,5 @@ BOOST_AUTO_TEST_CASE(Test_all_available_w_restart) { if (Opm::filesystem::exists("RST2.UNSMRY")) Opm::filesystem::remove("RST2.UNSMRY"); } + + diff --git a/tests/test_ExtESmry.cpp b/tests/test_ExtESmry.cpp new file mode 100644 index 000000000..e18693e24 --- /dev/null +++ b/tests/test_ExtESmry.cpp @@ -0,0 +1,401 @@ +/* + + Copyright 2019 Equinor 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 "config.h" + +#include +#include +#include + +#define BOOST_TEST_MODULE Test EclIO +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using Opm::EclIO::ESmry; +using Opm::EclIO::ExtESmry; + +template +bool +range_equal(InputIterator1 first1, InputIterator1 last1, + InputIterator2 first2, InputIterator2 last2) +{ + while(first1 != last1 && first2 != last2) + { + if(*first1 != *first2) return false; + ++first1; + ++first2; + } + return (first1 == last1) && (first2 == last2); +} + +bool compare_files(const std::string& filename1, const std::string& filename2) +{ + std::ifstream file1(filename1); + std::ifstream file2(filename2); + + std::istreambuf_iterator begin1(file1); + std::istreambuf_iterator begin2(file2); + + std::istreambuf_iterator end; + + return range_equal(begin1, end, begin2, end); +} + + +template +bool operator==(const std::vector & t1, const std::vector & t2) +{ + return std::equal(t1.begin(), t1.end(), t2.begin(), t2.end()); +} + + + +void getRefSmryVect(std::vector &time_ref, std::vector &wgpr_prod_ref, std::vector &wbhp_prod_ref, std::vector &wbhp_inj_ref, + std::vector &fgor_ref, std::vector &bpr_111_ref, std::vector &bpr_10103_ref) { + + // reference vectors check against resinsight, right click and show plot data. + + time_ref = {1,4,13,31,59,90,120,151,181,212,243,273,304,334,365,396,424,455,485,516,546,577,608,638,669,699,730,761,789,820,850, + 881,911,942,973,1003,1034,1064,1095,1126,1154,1185,1215,1246,1276,1307,1338,1368,1399,1429,1460,1491,1519,1550,1580,1611,1641,1672,1703,1733, + 1764,1794,1825,1856,1884,1915,1945,1976,2006,2037,2068,2098,2129,2159,2190,2221,2249,2280,2310,2341,2371,2402,2433,2463,2494,2524,2555,2586, + 2614,2645,2675,2706,2736,2767,2798,2828,2859,2889,2920,2951,2979,3010,3040,3071,3101,3132,3163,3193,3224,3254,3285,3316,3344,3375,3405,3436, + 3466,3497,3528,3558,3589,3619,3650}; + + + + wgpr_prod_ref = { 25400,25400.01,25400,24868.41,24679.34,24722.67,24727.77,24727.34,24727.29,24728.52,24730.62,24733.06,24735.76, + 24738.4,24741.04,24743.66,24745.98,24748.4,24750.63,24752.83,24756.07,24761.09,24764.1,24784,27066.45,33575.16,43705.94,54388.21,65340.68, + 77829.57,88535.32,98802.72,108186,117395.1,125395.9,128689.4,129727.7,130422.1,130712.2,130653.5,130509.7,130192.4,129639.2,128959.1,128221.1, + 127395.6,126528,125665.9,124767.1,123897.2,123015.2,122150.7,121380.2,120541.4,119750.7,119008.2,118720,118329.8,117777.3,117232.2,116687.7, + 116198.9,115723,115269.7,114877.9,114498.6,113968.2,113365.6,112830.9,112342.7,111902.2,111506.3,111429.6,111820.9,112200.7,112393.1,112350.7, + 112093,111747.9,111399.3,111158.4,110974.7,110812.2,110704,110753.9,110856.4,110930.2,111033.1,111159.7,111290.7,111532.7,111754.7,111923.3, + 112092.7,112282.4,112476.8,112690.1,112907.5,113139.5,113373.6,113588.7,113835.7,114116.7,114427.3,114735.8,115058.2,115383.3,115700.7,116031.4, + 116362.3,116715.3,117065.4,117363.8,117677.7,117947.1,118135.7,118303.8,118480.7,118663,118842.3,119024.9,119195,119350.3}; + + wbhp_prod_ref = {2904.77,2667.102,2430.112,2295.094,2233.452,2252.221,2311.47,2386.978,2464.336,2544.591,2623.208,2697.206, + 2771.272,2840.809,2910.732,2978.707,3038.701,3104.135,3166.967,3231.747,3294.372,3358.698,3434.863,3509.692,3539.855,3415.612,3121.1,2793.217,2517.024, + 2246.404,2005.897,1766.418,1534.75,1295.477,1072.804,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000, + 1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000, + 1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000,1000, + 1000,1000,1000,1000,1000,1000,1000,1000,1000,1000}; + + wbhp_inj_ref = {8253.15,8014.97,7329.12,6983.16,6684.92,6575.38,6528.93,6476.34,6453.38,6449.5,6458.79,6480.98,6510.48,6542.09,6577.34, + 6614.92,6650.01,6689.56,6728.47,6769.33,6808.93,6849.93,6890.88,6930.45,6970.21,7004.62,7031.64,7047.83,7052.25,7043.31,7022.21,6988.23,6944.89, + 6889.79,6825.3,6757.2,6684.39,6613.54,6540.99,6469.54,6406.19,6337.45,6272.51,6207.1,6145.47,6083.56,6023.49,5967.08,5910.65,5857.73,5804.9,5753.85, + 5709.25,5661.67,5617.34,5573.38,5532.49,5491.8,5452.55,5415.84,5379.28,5345.09,5311.01,5277.73,5248.81,5217.83,5188.74,5159.81,5132.76,5105.75,5079.57, + 5054.97,5030.16,5006.49,4982.17,4958,4936.49,4913.21,4891.25,4869.29,4848.68,4827.92,4807.7,4788.72,4769.62,4751.56,4733.24,4715.3,4699.48,4682.35, + 4666.14,4649.83,4634.43,4618.94,4603.88,4589.81,4575.75,4562.72,4549.85,4537.6,4526.95,4515.46,4504.59,4493.46,4482.87,4471.97,4461.14,4450.65,4439.73, + 4429.22,4418.21,4407.14,4397.07,4385.85,4374.93,4363.59,4352.5,4341.05,4329.71,4318.7,4307.34,4296.4,4285.14}; + + fgor_ref = { 1.27,1.27,1.27,1.24342,1.23397,1.23613,1.23639,1.23637,1.23636,1.23643,1.23653,1.23665,1.23679,1.23692,1.23705,1.23718,1.2373, + 1.23742,1.23753,1.23764,1.2378,1.23805,1.2382,1.2392,1.35323,1.67876,2.18511,2.71941,3.26676,3.888,4.42677,4.93806,5.4093,5.86975,6.2698,6.60301, + 6.91579,7.19277,7.44386,7.66559,7.8618,8.06106,8.22055,8.37112,8.50559,8.63422,8.75421,8.86387,8.97159,9.07182,9.17264,9.27578,9.36818,9.4675,9.56145, + 9.6552,9.81817,9.96311,10.0741,10.1726,10.2715,10.3662,10.4631,10.5602,10.648,10.7503,10.812,10.8645,10.9203,10.985,11.055,11.1259,11.2608,11.4882, + 11.7386,11.9596,12.1154,12.2423,12.3375,12.4268,12.5285,12.6496,12.7744,12.9017,13.0636,13.2416,13.4274,13.6136,13.7875,13.9853,14.2141,14.4478, + 14.6595,14.8698,15.081,15.29,15.5087,15.7207,15.9375,16.1507,16.3397,16.5477,16.7576,16.9828,17.2054,17.4386,17.6743,17.9048,18.1461,18.3837,18.6359,18.8934,19.1273,19.3865,19.6289,19.8495,20.0575,20.2783,20.5075,20.7371,20.9815,21.2229,21.4733}; + + bpr_111_ref = {5192.06,5606.51,5909.88,6057.86,6080.45,6080.23,6081.54,6084.29,6097.11,6119.32,6147.81,6181.28,6218.68,6256.71,6297.53, + 6339.85,6378.65,6421.72,6463.58,6507.1,6548.96,6591.99,6634.73,6675.85,6717.01,6752.59,6780.59,6797.41,6802.21,6793.55,6772.59,6738.64,6695.22, + 6639.93,6575.16,6506.73,6433.56,6362.35,6289.45,6217.66,6154.01,6084.96,6019.74,5954.06,5892.19,5830.05,5769.77,5713.17,5656.56,5603.5,5550.54, + 5499.38,5454.69,5407.03,5362.65,5318.65,5277.74,5237.04,5197.81,5161.12,5124.6,5090.45,5056.44,5023.23,4994.12,4962.81,4933.43,4904.23,4876.93, + 4849.68,4823.29,4798.5,4773.5,4749.65,4725.15,4700.79,4679.13,4655.68,4633.58,4611.48,4590.75,4569.88,4549.56,4530.49,4511.31,4493.19,4474.8,4456.8, + 4440.94,4423.76,4407.52,4391.18,4375.77,4360.26,4345.2,4331.13,4317.09,4304.08,4291.25,4279.05,4268.46,4257.02,4246.22,4235.16,4224.65,4213.81, + 4203.05,4192.62,4181.76,4171.3,4160.34,4149.32,4139.29,4128.11,4117.22,4105.91,4094.85,4083.42,4072.1,4061.11,4049.77,4038.84,4027.6}; + + bpr_10103_ref = { 4583.96,4323.13,4063.73,3936.52,3884.46,3904.56,3969.39,4052.03,4136.77,4224.77,4311.05,4392.34,4473.78,4550.3,4627.31, + 4702.24,4768.42,4840.68,4910.14,4981.81,5051.17,5122.48,5206.98,5290.2,5339.93,5335.32,5290.28,5224.73,5142.4,5051.97,4968.24,4882.83,4793.78,4697.18, + 4600.77,4541.35,4502.17,4466.12,4428.31,4389.78,4355.46,4318.33,4282.8,4246.64,4212.19,4177.25,4143.1,4110.87,4078.55,4048.17,4017.89,3989.55,3964.72, + 3938.13,3913.35,3888.53,3864.13,3839.42,3816.21,3794.87,3773.77,3754.37,3735.2,3716.65,3700.38,3683.04,3667.23,3651.1,3635.94,3620.84,3606.19,3592.37, + 3578.56,3565.21,3550.34,3535.32,3521.95,3507.4,3493.98,3481.08,3469.23,3457.1,3445.23,3434.31,3423.9,3413.55,3402.49,3392.2,3383.36,3373.38,3363.72, + 3353.81,3344.61,3335.8,3327.55,3319.76,3312.03,3304.96,3298.14,3291.74,3286.38,3280.83,3275.92,3271,3266.36,3261.69,3257.16,3252.91,3248.64,3244.7, + 3240.73,3236.73,3232.96,3228.72,3224.57,3220.09,3215.85,3211.46,3207.02,3202.65,3198.03,3193.45,3188.54}; + +} + +std::vector getFrom(const std::vector &ref_vect,int from){ + + std::vector vect; + + for (unsigned int i=from; i time_ref, wgpr_prod_ref, wbhp_prod_ref, wbhp_inj_ref, fgor_ref, bpr_111_ref, bpr_10103_ref; + + getRefSmryVect(time_ref, wgpr_prod_ref, wbhp_prod_ref, wbhp_inj_ref,fgor_ref, bpr_111_ref, bpr_10103_ref); + + auto time = esmry1.get("TIME"); + + std::vector smryVect = smry1.get("TIME"); + BOOST_CHECK_EQUAL(smryVect == time_ref, true); + + const auto dates = esmry1.dates(); + + for (std::size_t index = 0; index < dates.size(); index++) { + auto diff = dates[index]- smry1.startdate(); + auto diff_seconds = std::chrono::duration_cast(diff).count(); + BOOST_CHECK_CLOSE(diff_seconds, 24*3600 * smryVect[index], 1e-6); + } + + smryVect = esmry1.get("WGPR:PROD"); + + for (unsigned int i=0;i< smryVect.size();i++) + BOOST_REQUIRE_CLOSE (smryVect[i], wgpr_prod_ref[i], 0.01); + + smryVect = esmry1.get("WBHP:PROD"); + + for (unsigned int i=0;i< smryVect.size();i++) + BOOST_REQUIRE_CLOSE (smryVect[i], wbhp_prod_ref[i], 0.01); + + smryVect = esmry1.get("WBHP:INJ"); + + for (unsigned int i=0;i< smryVect.size();i++) + BOOST_REQUIRE_CLOSE (smryVect[i], wbhp_inj_ref[i], 0.01); + + smryVect = esmry1.get("FGOR"); + + for (unsigned int i=0;i< smryVect.size();i++) + BOOST_REQUIRE_CLOSE (smryVect[i], fgor_ref[i], 0.01); + + smryVect = esmry1.get("BPR:1,1,1"); + + for (unsigned int i=0;i< smryVect.size();i++) + BOOST_REQUIRE_CLOSE (smryVect[i], bpr_111_ref[i], 0.01); + + smryVect = esmry1.get("BPR:10,10,3"); + + for (unsigned int i=0;i< smryVect.size();i++) + BOOST_REQUIRE_CLOSE (smryVect[i], bpr_10103_ref[i], 0.01); + + if (Opm::filesystem::exists("SPE1CASE1.ESMRY")) + Opm::filesystem::remove("SPE1CASE1.ESMRY"); +} + + +BOOST_AUTO_TEST_CASE(TestExtESmry_2) { + + // using a syntetic restart file. + // + // # 1 copied SPE1CASE1 to TMP.DATA + // - added two extra summary vectors (FOPT and FGPR) + // - deleted 4 vectors WOIR:PROD, WOIR:INJ, WOIT:PROD and WOIT:INJ + // # 2 run full simulation with TMP.DATA + // - exact same solution as SPE1CASE1 + // # 3 renamed TMP1.SMSPEC to SPE1CASE1_RST60.SMSPEC + manual modifications + // - update RESTART keyword ('SPE1CASE' '1 ' ... ) + // - updated DIMENS, last item equal to 60 => restart from report report step 60 + // # 4 copy TMP1.UNSMRY to SPE1CASE1_RST60.UNSMRY + manual modifications + // - delete all data from ministep 0 to ministep 62, (ministep 62 = report step 60 in this run) + + // this is what the summary file from the restart run would be if the restart was 100% perfect. + // changing summary keywords to make the file realistic. + + + std::vector time_ref, wgpr_prod_ref, wbhp_prod_ref, wbhp_inj_ref, fgor_ref, bpr_111_ref, bpr_10103_ref; + + getRefSmryVect(time_ref, wgpr_prod_ref, wbhp_prod_ref, wbhp_inj_ref,fgor_ref, bpr_111_ref, bpr_10103_ref); + + // defaulting second argument, loadBaseRunData. Only data from the restarted run + // will be loaded. No data from base run (SPE1CASE1 in this case) + + if (Opm::filesystem::exists("SPE1CASE1.ESMRY")) + Opm::filesystem::remove("SPE1CASE1.ESMRY"); + + if (Opm::filesystem::exists("SPE1CASE1_RST60.ESMRY")) + Opm::filesystem::remove("SPE1CASE1_RST60.ESMRY"); + + ESmry smry1("SPE1CASE1.SMSPEC"); + ESmry smry2("SPE1CASE1_RST60.SMSPEC"); + + smry1.make_esmry_file(); + smry2.make_esmry_file(); + + ExtESmry esmry1("SPE1CASE1_RST60.ESMRY"); + + BOOST_CHECK_EQUAL(esmry1.all_steps_available(), true); + + auto ntsteps = esmry1.numberOfTimeSteps(); + BOOST_CHECK_EQUAL(ntsteps, 60); + + BOOST_CHECK_THROW( esmry1.get_unit("NO_SUCH_KEY"), std::invalid_argument); + BOOST_CHECK_EQUAL( esmry1.get_unit("TIME"), "DAYS"); + BOOST_CHECK_EQUAL( esmry1.get_unit("WOPR:PROD"), "STB/DAY"); + + std::vector smryVect = esmry1.get("TIME"); + std::vector time_ref_rst60 = getFrom(time_ref,63); + + BOOST_CHECK_EQUAL(smryVect==time_ref_rst60, true); + + smryVect = esmry1.get("WGPR:PROD"); + std::vector ref_rst60 = getFrom(wgpr_prod_ref,63); + + for (unsigned int i=0;i< smryVect.size();i++) + BOOST_REQUIRE_CLOSE (smryVect[i], ref_rst60[i], 0.01); + + smryVect = esmry1.get("WBHP:PROD"); + ref_rst60 = getFrom(wbhp_prod_ref,63); + + for (unsigned int i=0;i< smryVect.size();i++) + BOOST_REQUIRE_CLOSE (smryVect[i], ref_rst60[i], 0.01); + + + smryVect = esmry1.get("WBHP:INJ"); + ref_rst60 = getFrom(wbhp_inj_ref,63); + + for (unsigned int i=0;i< smryVect.size();i++) + BOOST_REQUIRE_CLOSE (smryVect[i], ref_rst60[i], 0.01); + + smryVect = esmry1.get("FGOR"); + ref_rst60 = getFrom(fgor_ref,63); + + for (unsigned int i=0;i< smryVect.size();i++) + BOOST_REQUIRE_CLOSE (smryVect[i], ref_rst60[i], 0.01); + + smryVect = esmry1.get("BPR:1,1,1"); + ref_rst60 = getFrom(bpr_111_ref,63); + + for (unsigned int i=0;i< smryVect.size();i++) + BOOST_REQUIRE_CLOSE (smryVect[i], ref_rst60[i], 0.01); + + smryVect = esmry1.get("BPR:10,10,3"); + ref_rst60 = getFrom(bpr_10103_ref,63); + + for (unsigned int i=0;i< smryVect.size();i++) + BOOST_REQUIRE_CLOSE (smryVect[i], ref_rst60[i], 0.01); + + if (Opm::filesystem::exists("SPE1CASE1.ESMRY")) + Opm::filesystem::remove("SPE1CASE1.ESMRY"); + + if (Opm::filesystem::exists("SPE1CASE1_RST60.ESMRY")) + Opm::filesystem::remove("SPE1CASE1_RST60.ESMRY"); +} + + + +BOOST_AUTO_TEST_CASE(TestESmry_3) { + + // using a syntetic restart file. + // + // # 1 copied SPE1CASE1 to TMP.DATA + // - added two extra summary vectors (FOPT and FGPR) + // - deleted 4 vectors WOIR:PROD, WOIR:INJ, WOIT:PROD and WOIT:INJ + // # 2 run full simulation with TMP.DATA + // - exact same solution as SPE1CASE1 + // # 3 renamed TMP1.SMSPEC to SPE1CASE1_RST60.SMSPEC + manual modifications + // - update RESTART keyword ('SPE1CASE' '1 ' ... ) + // - updated DIMENS, last item equal to 60 => restart from report report step 60 + // # 4 copy TMP1.UNSMRY to SPE1CASE1_RST60.UNSMRY + manual modifications + // - delete all data from ministep 0 to ministep 62, (ministep 62 = report step 60 in this run) + + // this is what the summary file from the restart run would be if the restart was 100% perfect. + // changing summary keywords to make the file realistic. + + + std::vector time_ref, wgpr_prod_ref, wbhp_prod_ref, wbhp_inj_ref, fgor_ref, bpr_111_ref, bpr_10103_ref; + + getRefSmryVect(time_ref, wgpr_prod_ref, wbhp_prod_ref, wbhp_inj_ref,fgor_ref, bpr_111_ref, bpr_10103_ref); + + // second argument, loadBaseRunData = true. Both data from restarted run and base run loaded + // vectors should be equal to reference vectors (from SPE1CASE1) + + if (Opm::filesystem::exists("SPE1CASE1.ESMRY")) + Opm::filesystem::remove("SPE1CASE1.ESMRY"); + + if (Opm::filesystem::exists("SPE1CASE1_RST60.ESMRY")) + Opm::filesystem::remove("SPE1CASE1_RST60.ESMRY"); + + ESmry smry1("SPE1CASE1.SMSPEC"); + ESmry smry2("SPE1CASE1_RST60.SMSPEC"); + + smry1.make_esmry_file(); + smry2.make_esmry_file(); + + ExtESmry esmry1("SPE1CASE1_RST60.ESMRY", true); + + auto ntsteps = esmry1.numberOfTimeSteps(); + BOOST_CHECK_EQUAL(ntsteps, 123); + + std::vector smryVect = esmry1.get("TIME"); + BOOST_CHECK_EQUAL(smryVect==time_ref, true); + + smryVect = esmry1.get("WGPR:PROD"); + for (unsigned int i=0;i< smryVect.size();i++) + BOOST_REQUIRE_CLOSE (smryVect[i], wgpr_prod_ref[i], 0.01); + + + smryVect = esmry1.get("WBHP:PROD"); + + for (unsigned int i=0;i< smryVect.size();i++) + BOOST_REQUIRE_CLOSE (smryVect[i], wbhp_prod_ref[i], 0.01); + + smryVect = esmry1.get("WBHP:INJ"); + + for (unsigned int i=0;i< smryVect.size();i++) + BOOST_REQUIRE_CLOSE (smryVect[i], wbhp_inj_ref[i], 0.01); + + smryVect = esmry1.get("FGOR"); + + for (unsigned int i=0;i< smryVect.size();i++) + BOOST_REQUIRE_CLOSE (smryVect[i], fgor_ref[i], 0.01); + + smryVect = esmry1.get("BPR:1,1,1"); + + for (unsigned int i=0;i< smryVect.size();i++) + BOOST_REQUIRE_CLOSE (smryVect[i], bpr_111_ref[i], 0.01); + + smryVect = esmry1.get("BPR:10,10,3"); + + for (unsigned int i=0;i< smryVect.size();i++) + BOOST_REQUIRE_CLOSE (smryVect[i], bpr_10103_ref[i], 0.01); + + if (Opm::filesystem::exists("SPE1CASE1.ESMRY")) + Opm::filesystem::remove("SPE1CASE1.ESMRY"); + + if (Opm::filesystem::exists("SPE1CASE1_RST60.ESMRY")) + Opm::filesystem::remove("SPE1CASE1_RST60.ESMRY"); +} + +