From d34910c27dab024a7ce773042c0d15fbc447b583 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torbj=C3=B8rn=20Skille?= Date: Tue, 17 May 2022 16:41:11 +0200 Subject: [PATCH 1/4] Minimum time interval between update of ESMRY file The ESMRY file need a complete rewrite every time this is being updated. This will makes the file more available for reading by other processes. --- opm/io/eclipse/ExtSmryOutput.hpp | 5 ++++- opm/output/eclipse/Summary.hpp | 2 +- src/opm/io/eclipse/ExtSmryOutput.cpp | 9 ++++++++- src/opm/output/eclipse/EclipseIO.cpp | 6 ++++-- src/opm/output/eclipse/Summary.cpp | 10 +++++----- 5 files changed, 22 insertions(+), 10 deletions(-) diff --git a/opm/io/eclipse/ExtSmryOutput.hpp b/opm/io/eclipse/ExtSmryOutput.hpp index 31afeb800..e9db27f6c 100644 --- a/opm/io/eclipse/ExtSmryOutput.hpp +++ b/opm/io/eclipse/ExtSmryOutput.hpp @@ -40,10 +40,13 @@ public: 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); + void write(const std::vector& ts_data, int report_step, bool is_final_summary); private: + const int m_min_write_interval = 15; // at least 15 seconds betwen each write + std::chrono::time_point m_last_write; + std::string m_outputFileName; int m_nTimeSteps; int m_nVect; diff --git a/opm/output/eclipse/Summary.hpp b/opm/output/eclipse/Summary.hpp index 0ca8ffaed..e259a376e 100644 --- a/opm/output/eclipse/Summary.hpp +++ b/opm/output/eclipse/Summary.hpp @@ -83,7 +83,7 @@ public: const data::Aquifers& aquifers_values = {}, const InterRegFlowValues& interreg_flows = {}) const; - void write() const; + void write(const bool is_final_summary = false) const; PAvgCalculatorCollection wbp_calculators(std::size_t report_step) const; diff --git a/src/opm/io/eclipse/ExtSmryOutput.cpp b/src/opm/io/eclipse/ExtSmryOutput.cpp index a830808fe..850deef6d 100644 --- a/src/opm/io/eclipse/ExtSmryOutput.cpp +++ b/src/opm/io/eclipse/ExtSmryOutput.cpp @@ -37,6 +37,7 @@ ExtSmryOutput::ExtSmryOutput(const std::vector& valueKeys, const st { m_nVect = valueKeys.size(); m_nTimeSteps = 0; + m_last_write = std::chrono::system_clock::now(); IOConfig ioconf = es.getIOConfig(); @@ -71,12 +72,15 @@ ExtSmryOutput::ExtSmryOutput(const std::vector& valueKeys, const st } -void ExtSmryOutput::write(const std::vector& ts_data, int report_step) +void ExtSmryOutput::write(const std::vector& ts_data, int report_step, bool is_final_summary) { if (ts_data.size() != static_cast(m_nVect)) throw std::invalid_argument("size of ts_data vector not same as number of smry vectors"); + auto current = std::chrono::system_clock::now(); + std::chrono::duration elapsed_seconds = current - m_last_write; + m_rstep.push_back(report_step); // flow is yet not supporting rptonly in summary @@ -90,6 +94,7 @@ void ExtSmryOutput::write(const std::vector& ts_data, int report_step) for (size_t n = 0; n < static_cast(m_nVect); n++) m_smrydata[n].push_back(ts_data[n]); + if ((is_final_summary) || (elapsed_seconds.count() > m_min_write_interval)) { Opm::EclIO::EclOutput outFile(m_outputFileName, m_fmt, std::ios::out); @@ -110,6 +115,8 @@ void ExtSmryOutput::write(const std::vector& ts_data, int report_step) std::string vect_name="V" + std::to_string(n); outFile.write(vect_name, m_smrydata[n]); } + + m_last_write = std::chrono::system_clock::now(); } m_nTimeSteps++; diff --git a/src/opm/output/eclipse/EclipseIO.cpp b/src/opm/output/eclipse/EclipseIO.cpp index 81dff3c0b..c08df6ad8 100644 --- a/src/opm/output/eclipse/EclipseIO.cpp +++ b/src/opm/output/eclipse/EclipseIO.cpp @@ -285,16 +285,18 @@ void EclipseIO::writeTimeStep(const Action::State& action_state, const auto& schedule = this->impl->schedule; const auto& ioConfig = es.cfg().io(); + const bool final_step { report_step == static_cast(schedule.size()) - 1 }; + const bool is_final_summary = final_step && !isSubstep; + if ((report_step > 0) && this->impl->wantSummaryOutput(report_step, isSubstep, secs_elapsed)) { this->impl->summary.add_timestep(st, report_step, isSubstep); - this->impl->summary.write(); + this->impl->summary.write(is_final_summary); this->impl->recordSummaryOutput(secs_elapsed); } - const bool final_step { report_step == static_cast(schedule.size()) - 1 }; if (final_step && !isSubstep && this->impl->summaryConfig.createRunSummary()) { std::filesystem::path outputDir { this->impl->outputDir } ; diff --git a/src/opm/output/eclipse/Summary.cpp b/src/opm/output/eclipse/Summary.cpp index 9a3c4cbed..1f51c04e9 100644 --- a/src/opm/output/eclipse/Summary.cpp +++ b/src/opm/output/eclipse/Summary.cpp @@ -3649,7 +3649,7 @@ public: SummaryState& st) const; void internal_store(const SummaryState& st, const int report_step, bool isSubstep); - void write(); + void write(const bool is_final_summary); PAvgCalculatorCollection wbp_calculators(std::size_t report_step) const; private: @@ -3843,7 +3843,7 @@ eval(const int sim_step, } } -void Opm::out::Summary::SummaryImplementation::write() +void Opm::out::Summary::SummaryImplementation::write(const bool is_final_summary) { const auto zero = std::vector::size_type{0}; if (this->numUnwritten_ == zero) @@ -3866,7 +3866,7 @@ void Opm::out::Summary::SummaryImplementation::write() if (this->esmry_ != nullptr){ for (auto i = 0*this->numUnwritten_; i < this->numUnwritten_; ++i){ - this->esmry_->write(this->unwritten_[i].params, !this->unwritten_[i].isSubstep); + this->esmry_->write(this->unwritten_[i].params, !this->unwritten_[i].isSubstep, is_final_summary); } } @@ -4294,9 +4294,9 @@ void Summary::add_timestep(const SummaryState& st, const int report_step, bool i this->pImpl_->internal_store(st, report_step, isSubstep); } -void Summary::write() const +void Summary::write(const bool is_final_summary) const { - this->pImpl_->write(); + this->pImpl_->write(is_final_summary); } Summary::~Summary() {} From ab81083e02c41de1c3ed455d6e9059bf1bfac156 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torbj=C3=B8rn=20Skille?= Date: Tue, 17 May 2022 17:15:22 +0200 Subject: [PATCH 2/4] Write temporary ESMRY file before renaming this to the actual file name This increases the availability of the file for other processes. Duration for a rename file operation is very short relative to writing a new file. --- src/opm/io/eclipse/ExtSmryOutput.cpp | 41 ++++++++++++++++++---------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/src/opm/io/eclipse/ExtSmryOutput.cpp b/src/opm/io/eclipse/ExtSmryOutput.cpp index 850deef6d..3d8119688 100644 --- a/src/opm/io/eclipse/ExtSmryOutput.cpp +++ b/src/opm/io/eclipse/ExtSmryOutput.cpp @@ -27,6 +27,7 @@ #include #include +#include namespace Opm { namespace EclIO { @@ -96,25 +97,35 @@ void ExtSmryOutput::write(const std::vector& ts_data, int report_step, bo if ((is_final_summary) || (elapsed_seconds.count() > m_min_write_interval)) { - Opm::EclIO::EclOutput outFile(m_outputFileName, m_fmt, std::ios::out); + const auto tp = std::chrono::system_clock::now(); + auto sec_since_epoch = std::chrono::duration_cast(tp.time_since_epoch()).count(); + std::string tmp_file_name = "TMP_" + std::to_string(sec_since_epoch) + ".ESMRY"; - outFile.write("START", m_start_date_vect); + { + Opm::EclIO::EclOutput outFile(tmp_file_name, m_fmt, std::ios::out); - if (m_restart_rootn.size() > 0) { - outFile.write("RESTART", {m_restart_rootn}); - outFile.write("RSTNUM", {m_restart_step}); + outFile.write("START", m_start_date_vect); + + if (m_restart_rootn.size() > 0) { + outFile.write("RESTART", {m_restart_rootn}); + outFile.write("RSTNUM", {m_restart_step}); + } + + outFile.write("KEYCHECK", m_smry_keys); + outFile.write("UNITS", m_smryUnits); + + outFile.write("RSTEP", m_rstep); + outFile.write("TSTEP", m_tstep); + + for (size_t n = 0; n < static_cast(m_nVect); n++ ) { + std::string vect_name="V" + std::to_string(n); + outFile.write(vect_name, m_smrydata[n]); + } } - outFile.write("KEYCHECK", m_smry_keys); - outFile.write("UNITS", m_smryUnits); - - outFile.write("RSTEP", m_rstep); - outFile.write("TSTEP", m_tstep); - - for (size_t n = 0; n < static_cast(m_nVect); n++ ) { - std::string vect_name="V" + std::to_string(n); - outFile.write(vect_name, m_smrydata[n]); - } + const std::filesystem::path from_file = tmp_file_name; + const std::filesystem::path to_file = m_outputFileName; + std::filesystem::rename(from_file, to_file); m_last_write = std::chrono::system_clock::now(); } From 1433bc7a5540a479d4068ebf935b3938a302e99e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torbj=C3=B8rn=20Skille?= Date: Tue, 17 May 2022 17:26:56 +0200 Subject: [PATCH 3/4] ExtESmry - support loading when number of time steps have increased (on disk) The ESMRY file can be updated with more time step data in the time span between opening an ESMRY file and loading actual summary data from the file. This can happen if the ESMRY is generated by an active run. Length of summary vectors extracted will be equal to number of time steps on disk when the file was first opened (with the constructor). --- opm/io/eclipse/ExtESmry.hpp | 12 +- src/opm/io/eclipse/ExtESmry.cpp | 303 ++++++++++++++++++++++---------- 2 files changed, 219 insertions(+), 96 deletions(-) diff --git a/opm/io/eclipse/ExtESmry.hpp b/opm/io/eclipse/ExtESmry.hpp index 4869eaa58..c0e6a0d7d 100644 --- a/opm/io/eclipse/ExtESmry.hpp +++ b/opm/io/eclipse/ExtESmry.hpp @@ -37,7 +37,7 @@ using TimeStepEntry = std::tuple; using RstEntry = std::tuple; // start, rstart + rstnum, keycheck, units, rstep, tstep -using LodsmryHeadType = std::tuple, std::vector, +using ExtSmryHeadType = std::tuple, std::vector, std::vector, std::vector>; class ExtESmry @@ -72,7 +72,7 @@ public: private: std::filesystem::path m_inputFileName; - std::vector m_lodsmry_files; + std::vector m_esmry_files; bool m_loadBaseRun; std::vector> m_keyword_index; @@ -91,15 +91,17 @@ private: size_t m_nTstep; std::vector m_seqIndex; - std::vector m_lod_offset; - std::vector m_lod_arr_size; + std::vector m_rstep_offset; time_point m_startdat; double m_io_opening; double m_io_loading; - uint64_t open_esmry(std::filesystem::path& inputFileName, LodsmryHeadType& lodsmry_head); + bool open_esmry(const std::filesystem::path& inputFileName, ExtSmryHeadType& ext_smry_head, uint64_t& rstep_offset); + + bool load_esmry(const std::vector& stringVect, const std::vector& keyIndexVect, + const std::vector& loadKeyIndex, int ind, int to_ind ); void updatePathAndRootName(std::filesystem::path& dir, std::filesystem::path& rootN); }; diff --git a/src/opm/io/eclipse/ExtESmry.cpp b/src/opm/io/eclipse/ExtESmry.cpp index a0fc86dc0..bce2f2595 100644 --- a/src/opm/io/eclipse/ExtESmry.cpp +++ b/src/opm/io/eclipse/ExtESmry.cpp @@ -38,6 +38,7 @@ #include #include #include +#include namespace { @@ -104,7 +105,7 @@ ExtESmry::ExtESmry(const std::string &filename, bool loadBaseRunData) : if (m_inputFileName.extension()!=".ESMRY") throw std::invalid_argument("Input file should have extension .ESMRY"); - m_lodsmry_files.push_back(m_inputFileName); + m_esmry_files.push_back(m_inputFileName); std::filesystem::path rootName = m_inputFileName.parent_path() / m_inputFileName.stem(); std::filesystem::path path = std::filesystem::current_path(); @@ -113,18 +114,29 @@ ExtESmry::ExtESmry(const std::string &filename, bool loadBaseRunData) : updatePathAndRootName(path, rootName); - LodsmryHeadType lodsmry_head; + ExtSmryHeadType ext_esmry_head; - auto lod_offset = open_esmry(m_inputFileName, lodsmry_head); + uint64_t rstep_offset; - m_startdat = std::get<0>(lodsmry_head); + bool res = open_esmry(m_inputFileName, ext_esmry_head, rstep_offset); + int n_attempts = 1; - m_lod_offset.push_back(lod_offset); + while ((!res) && (n_attempts < 10)){ + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + res = open_esmry(m_inputFileName, ext_esmry_head, rstep_offset); + n_attempts ++; + } + + if (n_attempts == 10) + OPM_THROW( std::runtime_error, "when opening ESMRY file " + filename ); + + m_startdat = std::get<0>(ext_esmry_head); + m_rstep_offset.push_back(rstep_offset); std::map key_index; - auto keyword = std::get<2>(lodsmry_head); - auto units = std::get<3>(lodsmry_head); + auto keyword = std::get<2>(ext_esmry_head); + auto units = std::get<3>(ext_esmry_head); for (size_t n = 0; n < keyword.size(); n++){ key_index[keyword[n]] = n; @@ -136,17 +148,13 @@ ExtESmry::ExtESmry(const std::string &filename, bool loadBaseRunData) : for (size_t n = 0; n < m_keyword.size(); n++) kwunits[m_keyword[n]] = units[n]; - RstEntry rst_entry = std::get<1>(lodsmry_head); + RstEntry rst_entry = std::get<1>(ext_esmry_head); - m_rstep_v.push_back(std::get<4>(lodsmry_head)); - m_tstep_v.push_back(std::get<5>(lodsmry_head)); + m_rstep_v.push_back(std::get<4>(ext_esmry_head)); + m_tstep_v.push_back(std::get<5>(ext_esmry_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)); if ((loadBaseRunData) && (!std::get<0>(rst_entry).empty())) { @@ -162,23 +170,21 @@ ExtESmry::ExtESmry(const std::string &filename, bool loadBaseRunData) : updatePathAndRootName(path, rstRootN); - std::filesystem::path rstLodSmryFile = path / rstRootN; - rstLodSmryFile += ".ESMRY"; + std::filesystem::path rstESmryFile = path / rstRootN; + rstESmryFile += ".ESMRY"; - m_lodsmry_files.push_back(rstLodSmryFile); + m_esmry_files.push_back(rstESmryFile); - lod_offset = open_esmry(rstLodSmryFile, lodsmry_head); + if (!open_esmry(rstESmryFile, ext_esmry_head, rstep_offset)) + OPM_THROW( std::runtime_error, "when opening ESMRY file" + rstESmryFile.string() ); - m_lod_offset.push_back(lod_offset); + m_rstep_offset.push_back(rstep_offset); - m_rstep_v.push_back(std::get<4>(lodsmry_head)); - m_tstep_v.push_back(std::get<5>(lodsmry_head)); + m_rstep_v.push_back(std::get<4>(ext_esmry_head)); + m_tstep_v.push_back(std::get<5>(ext_esmry_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(), @@ -195,14 +201,14 @@ ExtESmry::ExtESmry(const std::string &filename, bool loadBaseRunData) : m_tstep_range.push_back(std::make_tuple(0, ind)); key_index.clear(); - keyword = std::get<2>(lodsmry_head); + keyword = std::get<2>(ext_esmry_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); + rst_entry = std::get<1>(ext_esmry_head); restart = std::get<0>(rst_entry); rstNum = std::get<1>(rst_entry); } @@ -263,31 +269,46 @@ bool ExtESmry::all_steps_available() return true; } -uint64_t ExtESmry::open_esmry(std::filesystem::path& inputFileName, LodsmryHeadType& lodsmry_head) +bool ExtESmry::open_esmry(const std::filesystem::path& inputFileName, ExtSmryHeadType& ext_smry_head, uint64_t& rstep_offset) { std::fstream fileH; fileH.open(inputFileName, std::ios::in | std::ios::binary); if (!fileH) - throw std::runtime_error("Can not open file "); - + return false; std::string arrName; int64_t arr_size; Opm::EclIO::eclArrType arrType; int sizeOfElement; - Opm::EclIO::readBinaryHeader(fileH, arrName, arr_size, arrType, sizeOfElement); + try { + Opm::EclIO::readBinaryHeader(fileH, arrName, arr_size, arrType, sizeOfElement); + } catch (const std::runtime_error& error) + { + return false; + } if ((arrName != "START ") or (arrType != Opm::EclIO::INTE)) - OPM_THROW(std::invalid_argument, "reading start, invalid lod file"); + OPM_THROW(std::invalid_argument, "reading start, invalid esmry file " + inputFileName.string() ); - auto start_vect = Opm::EclIO::readBinaryInteArray(fileH, arr_size); + std::vector start_vect; + try { + start_vect = Opm::EclIO::readBinaryInteArray(fileH, arr_size); + } catch (const std::runtime_error& error) + { + return false; + } auto startdat = make_date(start_vect); - Opm::EclIO::readBinaryHeader(fileH, arrName, arr_size, arrType, sizeOfElement); + try { + Opm::EclIO::readBinaryHeader(fileH, arrName, arr_size, arrType, sizeOfElement); + } catch (const std::runtime_error& error) + { + return false; + } Opm::EclIO::RstEntry rst_entry = std::make_tuple("", 0); @@ -311,43 +332,85 @@ uint64_t ExtESmry::open_esmry(std::filesystem::path& inputFileName, LodsmryHeadT } if (arrName != "KEYCHECK") - OPM_THROW(std::invalid_argument, "!!reading keycheck, invalid lod file"); + OPM_THROW(std::invalid_argument, "reading keycheck, invalid esmry file " + inputFileName.string() ); std::vector keywords; - keywords = Opm::EclIO::readBinaryC0nnArray(fileH, arr_size, sizeOfElement); + try { + keywords = Opm::EclIO::readBinaryC0nnArray(fileH, arr_size, sizeOfElement); + } catch (const std::runtime_error& error) + { + return false; + } - Opm::EclIO::readBinaryHeader(fileH, arrName, arr_size, arrType, sizeOfElement); + + try { + Opm::EclIO::readBinaryHeader(fileH, arrName, arr_size, arrType, sizeOfElement); + } catch (const std::runtime_error& error) + { + return false; + } if (arrName != "UNITS ") - OPM_THROW(std::invalid_argument, "reading UNITS, invalid lod file"); + OPM_THROW(std::invalid_argument, "reading UNITS, invalid esmry file " + inputFileName.string() ); - auto units = Opm::EclIO::readBinaryC0nnArray(fileH, arr_size, sizeOfElement); + std::vector units; + + try { + units = Opm::EclIO::readBinaryC0nnArray(fileH, arr_size, sizeOfElement); + } catch (const std::runtime_error& error) + { + return false; + } if (keywords.size() != units.size()) - throw std::runtime_error("invalid LODSMRY file, size of units not equal size of keywords"); + OPM_THROW( std::runtime_error, "invalid ESMRY file " + inputFileName.string() + ". Size of UNITS not equal size of KEYCHECK"); - Opm::EclIO::readBinaryHeader(fileH, arrName, arr_size, arrType, sizeOfElement); + rstep_offset = static_cast(fileH.tellg()); + + try { + Opm::EclIO::readBinaryHeader(fileH, arrName, arr_size, arrType, sizeOfElement); + } catch (const std::runtime_error& error) + { + return false; + } if ((arrName != "RSTEP ") or (arrType != Opm::EclIO::INTE)) - OPM_THROW(std::invalid_argument, "reading RSTEP, invalid lod file"); + OPM_THROW(std::invalid_argument, "Reading RSTEP, invalid esmry file " + inputFileName.string() ); - auto rstep = Opm::EclIO::readBinaryInteArray(fileH, arr_size); + std::vector rstep; - Opm::EclIO::readBinaryHeader(fileH, arrName, arr_size, arrType, sizeOfElement); + try { + rstep = Opm::EclIO::readBinaryInteArray(fileH, arr_size); + } catch (const std::runtime_error& error) + { + return false; + } + + try { + Opm::EclIO::readBinaryHeader(fileH, arrName, arr_size, arrType, sizeOfElement); + } catch (const std::runtime_error& error) + { + return false; + } if ((arrName != "TSTEP ") or (arrType != Opm::EclIO::INTE)) - OPM_THROW(std::invalid_argument, "reading TSTEP, invalid lod file"); + OPM_THROW(std::invalid_argument, "reading TSTEP, invalid esmry file " + inputFileName.string() ); - auto tstep = Opm::EclIO::readBinaryInteArray(fileH, arr_size); + std::vector tstep; - lodsmry_head = std::make_tuple(startdat, rst_entry, keywords, units, rstep, tstep); + try { + tstep = Opm::EclIO::readBinaryInteArray(fileH, arr_size); + } catch (const std::runtime_error& error) + { + return false; + } - uint64_t lodsmry_offset = static_cast(fileH.tellg()); + ext_smry_head = std::make_tuple(startdat, rst_entry, keywords, units, rstep, tstep); fileH.close(); - return lodsmry_offset; + return true; } @@ -363,6 +426,96 @@ void ExtESmry::updatePathAndRootName(std::filesystem::path& dir, std::filesystem } +bool ExtESmry::load_esmry(const std::vector& stringVect, const std::vector& keyIndexVect, + const std::vector& loadKeyIndex, int ind, int to_ind ) +{ + std::fstream fileH; + + fileH.open(m_esmry_files[ind], std::ios::in | std::ios::binary); + + if (!fileH) + return false; + + std::string arrName; + Opm::EclIO::eclArrType arrType; + int64_t num_tstep; + int sizeOfElement; + + // Read actual number of time steps on disk from RSTEP array before loading + // data. Notice that number of time steps can be different than what it was when + // the ESMRY file was opened. The simulation may have progressed if this is an + // ESMRY file from an active run + + fileH.seekg (m_rstep_offset[ind], fileH.beg); + + try { + Opm::EclIO::readBinaryHeader(fileH, arrName, num_tstep, arrType, sizeOfElement); + } catch (const std::runtime_error& error) + { + return false; + } + + auto smry_arr_size = sizeOnDiskBinary(num_tstep, Opm::EclIO::REAL, sizeOfReal); + + std::vector> smry_data; + smry_data.resize(loadKeyIndex.size(), {}); + + for (size_t n = 0 ; n < loadKeyIndex.size(); n++) { + + const auto& key = stringVect[loadKeyIndex[n]]; + + if ( m_keyword_index[ind].find(key) == m_keyword_index[ind].end() ) { + + smry_data[n].resize(to_ind + 1, 0.0 ); + + } else { + + int key_ind = m_keyword_index[ind].at(key); + + uint64_t pos = m_rstep_offset[ind] + smry_arr_size*static_cast(key_ind); + + // adding size of TSTEP and RSTEP INTE data + pos = pos + 2 * sizeOnDiskBinary(num_tstep, Opm::EclIO::INTE, sizeOfInte); + + pos = pos + static_cast(2 * 24); // adding size of binary headers (TSTEP and RSTEP) + pos = pos + static_cast(key_ind * 24); // adding size of binary headers + + fileH.seekg (pos, fileH.beg); + + int64_t size; + + try { + readBinaryHeader(fileH, arrName, size, arrType, sizeOfElement); + } catch (const std::runtime_error& error) + { + return false; + } + + arrName = Opm::EclIO::trimr(arrName); + + std::string checkName = "V" + std::to_string(key_ind); + + if (arrName != checkName) + return false; + + try { + smry_data[n] = readBinaryRealArray(fileH, size); + } catch (const std::runtime_error& error) + { + return false; + } + } + } + + fileH.close(); + + for (size_t n = 0 ; n < loadKeyIndex.size(); n++) + m_vectorData[keyIndexVect[n]].insert(m_vectorData[keyIndexVect[n]].end(), smry_data[n].begin(), smry_data[n].begin() + to_ind + 1); + + return true; +} + + void ExtESmry::loadData(const std::vector& stringVect) { auto start = std::chrono::system_clock::now(); @@ -385,59 +538,27 @@ void ExtESmry::loadData(const std::vector& stringVect) ++keyCounter; } - 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); + bool res = load_esmry(stringVect, keyIndexVect, loadKeyIndex, ind, to_ind ); - if (!fileH) - throw std::runtime_error("Can not open file lodFile"); + int n_attempts = 1; - for (size_t n = 0 ; n < loadKeyIndex.size(); n++) { - - //std::string key = loadKeyNames[n]; - const auto& key = stringVect[loadKeyIndex[n]]; - - std::string arrName; - Opm::EclIO::eclArrType arrType; - - 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); - - int64_t size; - int sizeOfElement; - 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); - } + while ((!res) && (n_attempts < 10)){ + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + res = load_esmry(stringVect, keyIndexVect, loadKeyIndex, ind, to_ind ); + n_attempts ++; + } + + if (n_attempts == 10){ + std::string emsry_file_name = m_esmry_files[ind].string(); + OPM_THROW( std::runtime_error, "when loading data from ESMRY file" + emsry_file_name ); } - fileH.close(); ind--; } From 9a97d5c998d21de72dff325d19cd29cf6d6578ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torbj=C3=B8rn=20Skille?= Date: Sat, 28 May 2022 10:30:01 +0200 Subject: [PATCH 4/4] updated ExtESmry unit test Loading summary vector from restart simulation with loadBaseRunData = true and selected summary vector not present in baserun. Common use case where a new vector added in the restart run. --- tests/test_ExtESmry.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/test_ExtESmry.cpp b/tests/test_ExtESmry.cpp index afeb276ec..e03fb52f0 100644 --- a/tests/test_ExtESmry.cpp +++ b/tests/test_ExtESmry.cpp @@ -385,5 +385,25 @@ BOOST_AUTO_TEST_CASE(TestESmry_3) { for (unsigned int i=0;i< smryVect.size();i++) BOOST_REQUIRE_CLOSE (smryVect[i], bpr_10103_ref[i], 0.01); + auto fopt = esmry1.get("FOPT"); + + // fopt vector not present in base run, should get zeros as not + // for time step 0, 1, ... 62 + + for (size_t n = 0; n < 63; n++) + BOOST_CHECK_EQUAL(fopt[n], 0.0); + + std::vector fopt_rst_ref = { 3.19319e+07, 3.2234e+07, 3.25642e+07, 3.28804e+07, 3.32039e+07, 3.35138e+07, + 3.38309e+07, 3.41447e+07, 3.44453e+07, 3.47521e+07, 3.50441e+07, 3.53404e+07, 3.56317e+07, + 3.58914e+07, 3.61752e+07, 3.6447e+07, 3.67249e+07, 3.6991e+07, 3.7263e+07, 3.75319e+07, 3.77893e+07, + 3.80521e+07, 3.83033e+07, 3.85594e+07, 3.88122e+07, 3.9038e+07, 3.92847e+07, 3.95201e+07, 3.97599e+07, + 3.99889e+07, 4.02226e+07, 4.04534e+07, 4.06741e+07, 4.08993e+07, 4.11148e+07, 4.13349e+07, 4.15525e+07, + 4.17471e+07, 4.19604e+07, 4.21647e+07, 4.23735e+07, 4.25736e+07, 4.27781e+07, 4.29805e+07, 4.31744e+07, + 4.33726e+07, 4.35625e+07, 4.37566e+07, 4.39487e+07, 4.41205e+07, 4.43087e+07, 4.4489e+07, 4.46735e+07, + 4.48504e+07, 4.50315e+07, 4.52109e+07, 4.53828e+07, 4.55587e+07, 4.57272e+07, 4.58995e+07 }; + + + for (size_t n = 63; n < fopt.size(); n++) + BOOST_REQUIRE_CLOSE(fopt[n], fopt_rst_ref[n-63], 0.01); }