Adding support for writing esmry

- command line option --enable-esmry, default = false
 - complete re-write of esmry file for every time step

Updating of class ESmry
 - remove automatic loading from ESMRY
This commit is contained in:
Torbjørn Skille 2021-07-02 21:14:04 +02:00
parent d9dc2f3dd8
commit 46693aec47
11 changed files with 637 additions and 493 deletions

View File

@ -280,6 +280,7 @@ if(ENABLE_ECL_OUTPUT)
src/opm/io/eclipse/ESmry.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/RestartFileView.cpp
src/opm/io/eclipse/SummaryNode.cpp
src/opm/io/eclipse/rst/connection.cpp
@ -855,6 +856,7 @@ if(ENABLE_ECL_OUTPUT)
opm/io/eclipse/ESmry.hpp
opm/io/eclipse/PaddedOutputString.hpp
opm/io/eclipse/OutputStream.hpp
opm/io/eclipse/ESmryOutput.hpp
opm/io/eclipse/RestartFileView.hpp
opm/io/eclipse/SummaryNode.hpp
opm/io/eclipse/rst/connection.hpp

View File

@ -79,10 +79,9 @@ public:
bool all_steps_available();
private:
filesystem::path inputFileName, lodFileName;
filesystem::path inputFileName;
int nI, nJ, nK, nSpecFiles;
bool fromSingleRun, lodEnabeled;
uint64_t lod_offset, lod_arr_size;
bool fromSingleRun;
size_t nVect, nTstep;
std::vector<bool> formattedFiles;
@ -138,8 +137,6 @@ private:
std::vector<std::tuple <std::string, uint64_t>> getListOfArrays(std::string filename, bool formatted);
std::vector<int> makeKeywPosVector(int speInd) const;
std::string read_string_from_disk(std::fstream& fileH, uint64_t size) const;
void inspect_lodsmry();
void Load_from_lodsmry(const std::vector<int>& keywIndVect) const;
int read_ministep_formatted(std::fstream& fileH);
};

View File

@ -0,0 +1,68 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#ifndef OPM_IO_ESMRYOUTPUT_HPP
#define OPM_IO_ESMRYOUTPUT_HPP
#include <string>
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
namespace Opm {
class EclipseState;
}
namespace Opm { namespace EclIO {
class ESmryOutput
{
public:
ESmryOutput(const std::vector<std::string>& valueKeys, const std::vector<std::string>& valueUnits,
const EclipseState& es, const time_t start_time);
void write(const std::vector<float>& ts_data, int report_step);
private:
std::string m_outputFileName;
int m_nTimeSteps;
int m_nVect;
bool m_fmt;
std::vector<int> m_start_date_vect;
std::string m_restart_rootn;
int m_restart_step;
std::vector<std::string> m_smry_keys;
std::vector<std::string> m_smryUnits;
std::vector<int> m_rstep;
std::vector<int> m_tstep;
std::vector<std::vector<float>> m_smrydata;
std::array<int, 3> ijk_from_global_index(const GridDims& dims, int globInd) const;
std::vector<std::string> make_modified_keys(const std::vector<std::string> valueKeys, const GridDims& dims);
};
}} // namespace Opm::EclIO
#endif // OPM_IO_ESMRYOUTPUT_HPP

View File

@ -60,7 +60,10 @@ public:
EclipseIO( const EclipseState& es,
EclipseGrid grid,
const Schedule& schedule,
const SummaryConfig& summary_config);
const SummaryConfig& summary_config,
const std::string& basename = "",
const bool writeEsmry = false
);

View File

@ -57,11 +57,13 @@ public:
const SummaryConfig& sumcfg,
const EclipseGrid& grid,
const Schedule& sched,
const std::string& basename = "");
const std::string& basename = "",
const bool& writeEsmry = false
);
~Summary();
void add_timestep(const SummaryState& st, const int report_step);
void add_timestep(const SummaryState& st, const int report_step, bool isSubstep);
void eval(SummaryState& summary_state,
const int report_step,

View File

@ -113,16 +113,6 @@ ESmry::ESmry(const std::string &filename, bool loadBaseRunData) :
const bool formatted = inputFileName.extension()==".SMSPEC" ? false : true;
formattedFiles.push_back(formatted);
if (formatted)
lodFileName = rootName += ".FLODSMRY";
else
lodFileName = rootName += ".LODSMRY";
if ((!loadBaseRunData) && (Opm::filesystem::exists(lodFileName)))
lodEnabeled = true;
else
lodEnabeled = false;
Opm::filesystem::path path = Opm::filesystem::current_path();
updatePathAndRootName(path, rootName);
@ -345,140 +335,130 @@ ESmry::ESmry(const std::string &filename, bool loadBaseRunData) :
vectorLoaded.push_back(false);
}
if (lodEnabeled)
{
// inspecting formatted or binary lod file. lodsmry possible only if
// loadBaseRunData=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.
inspect_lodsmry();
int dataFileIndex = -1;
} else {
while (specInd >= 0) {
// 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 reportStepNumber = fromReportStepNumber;
int dataFileIndex = -1;
if (specInd > 0) {
auto rstFrom = smryArray[specInd-1];
toReportStepNumber = std::get<1>(rstFrom);
} else {
toReportStepNumber = std::numeric_limits<int>::max();
}
while (specInd >= 0) {
Opm::filesystem::path smspecFile(std::get<0>(smryArray[specInd]));
rootName = smspecFile.parent_path() / smspecFile.stem();
int reportStepNumber = fromReportStepNumber;
// check if multiple or unified result files should be used
// to import data, no information in smspec file regarding this
// if both unified and non-unified files exists, will use most recent based on
// time stamp
if (specInd > 0) {
auto rstFrom = smryArray[specInd-1];
toReportStepNumber = std::get<1>(rstFrom);
} else {
toReportStepNumber = std::numeric_limits<int>::max();
}
Opm::filesystem::path unsmryFile = rootName;
Opm::filesystem::path smspecFile(std::get<0>(smryArray[specInd]));
rootName = smspecFile.parent_path() / smspecFile.stem();
unsmryFile += formattedFiles[specInd] ? ".FUNSMRY" : ".UNSMRY";
const bool use_unified = Opm::filesystem::exists(unsmryFile.string());
// check if multiple or unified result files should be used
// to import data, no information in smspec file regarding this
// if both unified and non-unified files exists, will use most recent based on
// time stamp
const std::vector<std::string> multFileList = checkForMultipleResultFiles(rootName, formattedFiles[specInd]);
Opm::filesystem::path unsmryFile = rootName;
std::vector<std::string> resultsFileList;
unsmryFile += formattedFiles[specInd] ? ".FUNSMRY" : ".UNSMRY";
const bool use_unified = Opm::filesystem::exists(unsmryFile.string());
if ((!use_unified) && (multFileList.size()==0)) {
throw std::runtime_error("neigther unified or non-unified result files found");
} else if ((use_unified) && (multFileList.size()>0)) {
auto time_multiple = Opm::filesystem::last_write_time(multFileList.back());
auto time_unified = Opm::filesystem::last_write_time(unsmryFile);
const std::vector<std::string> multFileList = checkForMultipleResultFiles(rootName, formattedFiles[specInd]);
std::vector<std::string> resultsFileList;
if ((!use_unified) && (multFileList.size()==0)) {
throw std::runtime_error("neigther unified or non-unified result files found");
} else if ((use_unified) && (multFileList.size()>0)) {
auto time_multiple = Opm::filesystem::last_write_time(multFileList.back());
auto time_unified = Opm::filesystem::last_write_time(unsmryFile);
if (time_multiple > time_unified) {
resultsFileList=multFileList;
} else {
resultsFileList.push_back(unsmryFile.string());
}
} else if (use_unified) {
resultsFileList.push_back(unsmryFile.string());
} else {
if (time_multiple > time_unified) {
resultsFileList=multFileList;
} else {
resultsFileList.push_back(unsmryFile.string());
}
std::vector<ArrSourceEntry> arraySourceList;
} else if (use_unified) {
resultsFileList.push_back(unsmryFile.string());
} else {
resultsFileList=multFileList;
}
for (std::string fileName : resultsFileList)
std::vector<ArrSourceEntry> arraySourceList;
for (std::string fileName : resultsFileList)
{
std::vector<std::tuple <std::string, std::uint64_t>> arrayList;
arrayList = this->getListOfArrays(fileName, formattedFiles[specInd]);
for (size_t n = 0; n < arrayList.size(); n++) {
ArrSourceEntry t1 = std::make_tuple(std::get<0>(arrayList[n]), fileName, n, std::get<1>(arrayList[n]));
arraySourceList.push_back(t1);
}
}
// loop through arrays and for each ministep, store data file, location of params table
//
// 2 or 3 arrays pr time step.
// If timestep is a report step: MINISTEP, PARAMS and SEQHDR
// else : MINISTEP and PARAMS
size_t i = std::get<0>(arraySourceList[0]) == "SEQHDR" ? 1 : 0 ;
while (i < arraySourceList.size()) {
if (std::get<0>(arraySourceList[i]) != "MINISTEP") {
std::string message="Reading summary file, expecting keyword MINISTEP, found '" + std::get<0>(arraySourceList[i]) + "'";
throw std::invalid_argument(message);
}
if (std::get<0>(arraySourceList[i+1]) != "PARAMS") {
std::string message="Reading summary file, expecting keyword PARAMS, found '" + std::get<0>(arraySourceList[i]) + "'";
throw std::invalid_argument(message);
}
i++;
if (std::find(dataFileList.begin(), dataFileList.end(), std::get<1>(arraySourceList[i])) == dataFileList.end())
{
std::vector<std::tuple <std::string, std::uint64_t>> arrayList;
arrayList = this->getListOfArrays(fileName, formattedFiles[specInd]);
for (size_t n = 0; n < arrayList.size(); n++) {
ArrSourceEntry t1 = std::make_tuple(std::get<0>(arrayList[n]), fileName, n, std::get<1>(arrayList[n]));
arraySourceList.push_back(t1);
}
dataFileList.push_back(std::get<1>(arraySourceList[i]));
dataFileIndex++;
}
// loop through arrays and for each ministep, store data file, location of params table
//
// 2 or 3 arrays pr time step.
// If timestep is a report step: MINISTEP, PARAMS and SEQHDR
// else : MINISTEP and PARAMS
TimeStepEntry mst1 = std::make_tuple(specInd, dataFileIndex, std::get<3>(arraySourceList[i-1]));
miniStepList.push_back(mst1);
TimeStepEntry t1 = std::make_tuple(specInd, dataFileIndex, std::get<3>(arraySourceList[i]));
timeStepList.push_back(t1);
size_t i = std::get<0>(arraySourceList[0]) == "SEQHDR" ? 1 : 0 ;
i++;
while (i < arraySourceList.size()) {
if (std::get<0>(arraySourceList[i]) != "MINISTEP") {
std::string message="Reading summary file, expecting keyword MINISTEP, found '" + std::get<0>(arraySourceList[i]) + "'";
throw std::invalid_argument(message);
}
if (std::get<0>(arraySourceList[i+1]) != "PARAMS") {
std::string message="Reading summary file, expecting keyword PARAMS, found '" + std::get<0>(arraySourceList[i]) + "'";
throw std::invalid_argument(message);
}
i++;
if (std::find(dataFileList.begin(), dataFileList.end(), std::get<1>(arraySourceList[i])) == dataFileList.end())
{
dataFileList.push_back(std::get<1>(arraySourceList[i]));
dataFileIndex++;
}
TimeStepEntry mst1 = std::make_tuple(specInd, dataFileIndex, std::get<3>(arraySourceList[i-1]));
miniStepList.push_back(mst1);
TimeStepEntry t1 = std::make_tuple(specInd, dataFileIndex, std::get<3>(arraySourceList[i]));
timeStepList.push_back(t1);
i++;
if (i < arraySourceList.size()) {
if (std::get<0>(arraySourceList[i]) == "SEQHDR") {
i++;
reportStepNumber++;
seqIndex.push_back(step);
}
} else {
if (i < arraySourceList.size()) {
if (std::get<0>(arraySourceList[i]) == "SEQHDR") {
i++;
reportStepNumber++;
seqIndex.push_back(step);
}
if (reportStepNumber >= toReportStepNumber) {
i = arraySourceList.size();
}
step++;
} else {
reportStepNumber++;
seqIndex.push_back(step);
}
fromReportStepNumber = toReportStepNumber;
if (reportStepNumber >= toReportStepNumber) {
i = arraySourceList.size();
}
specInd--;
nTstep = timeStepList.size();
step++;
}
fromReportStepNumber = toReportStepNumber;
specInd--;
nTstep = timeStepList.size();
}
}
@ -561,88 +541,6 @@ int ESmry::read_ministep_formatted(std::fstream& fileH)
return ministep_vect[0];
}
void ESmry::inspect_lodsmry()
{
std::string arrName;
int64_t arr_size;
Opm::EclIO::eclArrType arrType;
int sizeOfElement;
std::fstream fileH;
if (formattedFiles[0]) {
fileH.open(lodFileName, std::ios::in);
Opm::EclIO::readFormattedHeader(fileH, arrName, arr_size, arrType, sizeOfElement);
} else {
fileH.open(lodFileName, std::ios::in | std::ios::binary);
Opm::EclIO::readBinaryHeader(fileH, arrName, arr_size, arrType, sizeOfElement);
}
if ((arrName != "KEYCHECK") or (arrType != Opm::EclIO::CHAR))
OPM_THROW(std::invalid_argument, "reading keycheck, invalid lod file");
std::vector<std::string> keycheck;
if (formattedFiles[0]) {
uint64_t size = Opm::EclIO::sizeOnDiskFormatted(arr_size, Opm::EclIO::CHAR, sizeOfChar) + 1;
std::string fileStr = read_string_from_disk(fileH, size);
keycheck = Opm::EclIO::readFormattedCharArray(fileStr, arr_size, 0, sizeOfChar);
} else {
keycheck = Opm::EclIO::readBinaryCharArray(fileH, arr_size);
}
if ((arr_size / nVect != 3) or (arr_size % nVect != 0))
OPM_THROW(std::invalid_argument, "reading keycheck, invalid lod file");
for (size_t n = 0; n < nVect; n++) {
size_t ind = n*3;
std::string test_str = keycheck[ind] + keycheck[ind+1] + keycheck[ind+2];
if (keyword[n].size() > 24) {
if (keyword[n].substr(0,24) != test_str) {
OPM_THROW(std::invalid_argument, "keycheck not matching keyword array");
}
} else {
if (keyword[n] != test_str) {
OPM_THROW(std::invalid_argument, "keycheck not matching keyword array");
}
}
}
if (formattedFiles[0])
Opm::EclIO::readFormattedHeader(fileH, arrName, arr_size, arrType, sizeOfElement);
else
Opm::EclIO::readBinaryHeader(fileH, arrName, arr_size, arrType, sizeOfElement);
if ((arrName != "RSTEP ") or (arrType != Opm::EclIO::LOGI))
OPM_THROW(std::invalid_argument, "reading rstep, invalid lod file");
std::vector<bool> rstep;
if (formattedFiles[0]) {
uint64_t size = Opm::EclIO::sizeOnDiskFormatted(arr_size, Opm::EclIO::LOGI, sizeOfLogi) + 1;
std::string fileStr = read_string_from_disk(fileH, size);
rstep = Opm::EclIO::readFormattedLogiArray(fileStr, arr_size, 0);
} else {
rstep = readBinaryLogiArray(fileH, arr_size);
}
for (size_t m = 0; m < rstep.size(); m++)
if (rstep[m])
seqIndex.push_back(m);
lod_offset = static_cast<uint64_t>(fileH.tellg());
nTstep = rstep.size();
if (formattedFiles[0])
lod_arr_size = sizeOnDiskFormatted(nTstep, Opm::EclIO::REAL, sizeOfReal);
else
lod_arr_size = sizeOnDiskBinary(nTstep, Opm::EclIO::REAL, sizeOfReal);
fileH.close();
}
std::string ESmry::read_string_from_disk(std::fstream& fileH, uint64_t size) const
{
@ -652,54 +550,6 @@ std::string ESmry::read_string_from_disk(std::fstream& fileH, uint64_t size) con
return { buffer.data(), size };
}
void ESmry::Load_from_lodsmry(const std::vector<int>& keywIndVect) const
{
std::fstream fileH;
if (formattedFiles[0])
fileH.open(lodFileName, std::ios::in);
else
fileH.open(lodFileName, std::ios::in | std::ios::binary);
for (auto ind : keywIndVect) {
std::string arrName;
std::int64_t size;
Opm::EclIO::eclArrType arrType;
int sizeOfElement;
std::uint64_t pos = lod_offset + lod_arr_size*static_cast<std::uint64_t>(ind);
if (formattedFiles[0])
pos = pos + static_cast<std::uint64_t>(ind * 31); // adding size of formatted headers
else
pos = pos + static_cast<std::uint64_t>(ind * 24); // adding size of binary headers
fileH.seekg (pos, fileH.beg);
if (formattedFiles[0])
readFormattedHeader(fileH, arrName, size, arrType, sizeOfElement);
else
readBinaryHeader(fileH, arrName, size, arrType, sizeOfElement);
arrName = Opm::EclIO::trimr(arrName);
const std::string checkName = fmt::format("V{}", ind);
if (arrName != checkName)
OPM_THROW(std::invalid_argument, "lodsmry, wrong header expecting " + checkName + " found " + arrName);
if (formattedFiles[0]) {
const std::uint64_t size_buffer = lod_arr_size + 1;
const std::string fileStr = read_string_from_disk(fileH, size_buffer);
vectorData[ind] = Opm::EclIO::readFormattedRealArray(fileStr, nTstep, 0);
} else {
vectorData[ind] = readBinaryRealArray(fileH, size);
}
}
fileH.close();
}
void ESmry::LoadData(const std::vector<std::string>& vectList) const
{
@ -708,7 +558,7 @@ void ESmry::LoadData(const std::vector<std::string>& vectList) const
std::vector<int> keywIndVect;
keywIndVect.reserve(nvect);
for (auto key : vectList){
for (auto key : vectList) {
if (!hasKey(key))
OPM_THROW(std::invalid_argument, "error loading key " + key );
@ -719,89 +569,84 @@ void ESmry::LoadData(const std::vector<std::string>& vectList) const
for (auto ind : keywIndVect)
vectorData[ind].reserve(nTstep);
if (lodEnabeled) {
Load_from_lodsmry(keywIndVect);
std::fstream fileH;
auto specInd = std::get<0>(timeStepList[0]);
auto dataFileIndex = std::get<1>(timeStepList[0]);
std::uint64_t blockSize_f;
{
const int rest = MaxBlockSizeReal % numColumnsReal;
const int nLinesBlock = MaxBlockSizeReal / numColumnsReal + (rest > 0);
blockSize_f= static_cast<std::uint64_t>(MaxNumBlockReal * numColumnsReal * columnWidthReal + nLinesBlock);
}
else {
std::fstream fileH;
auto specInd = std::get<0>(timeStepList[0]);
auto dataFileIndex = std::get<1>(timeStepList[0]);
std::uint64_t blockSize_f;
if (formattedFiles[specInd])
fileH.open(dataFileList[dataFileIndex], std::ios::in);
else
fileH.open(dataFileList[dataFileIndex], std::ios::in | std::ios::binary);
{
const int rest = MaxBlockSizeReal % numColumnsReal;
const int nLinesBlock = MaxBlockSizeReal / numColumnsReal + (rest > 0);
for (const auto& ministep : timeStepList) {
if (dataFileIndex != std::get<1>(ministep)) {
fileH.close();
specInd = std::get<0>(ministep);
dataFileIndex = std::get<1>(ministep);
blockSize_f= static_cast<std::uint64_t>(MaxNumBlockReal * numColumnsReal * columnWidthReal + nLinesBlock);
if (formattedFiles[specInd])
fileH.open(dataFileList[dataFileIndex], std::ios::in );
else
fileH.open(dataFileList[dataFileIndex], std::ios::in | std::ios::binary);
}
if (formattedFiles[specInd])
fileH.open(dataFileList[dataFileIndex], std::ios::in);
else
fileH.open(dataFileList[dataFileIndex], std::ios::in | std::ios::binary);
const auto stepFilePos = std::get<2>(ministep);;
for (const auto& ministep : timeStepList) {
if (dataFileIndex != std::get<1>(ministep)) {
fileH.close();
specInd = std::get<0>(ministep);
dataFileIndex = std::get<1>(ministep);
if (formattedFiles[specInd])
fileH.open(dataFileList[dataFileIndex], std::ios::in );
else
fileH.open(dataFileList[dataFileIndex], std::ios::in | std::ios::binary);
for (auto ind : keywIndVect) {
auto it = arrayPos[specInd].find(ind);
if (it == arrayPos[specInd].end()) {
// undefined vector in current summary file. Typically when loading
// base restart run and including base run data. Vectors can be added to restart runs
vectorData[ind].push_back(std::nanf(""));
}
else {
int paramPos = it->second;
const auto stepFilePos = std::get<2>(ministep);;
if (formattedFiles[specInd]) {
std::uint64_t elementPos = 0;
int nBlocks = paramPos / MaxBlockSizeReal;
int sizeOfLastBlock = paramPos % MaxBlockSizeReal;
for (auto ind : keywIndVect) {
auto it = arrayPos[specInd].find(ind);
if (it == arrayPos[specInd].end()) {
// undefined vector in current summary file. Typically when loading
// base restart run and including base run data. Vectors can be added to restart runs
vectorData[ind].push_back(std::nanf(""));
if (nBlocks > 0)
elementPos = static_cast<uint64_t>(nBlocks * blockSize_f);
int nLines = sizeOfLastBlock / numColumnsReal;
elementPos = stepFilePos + elementPos + static_cast<std::uint64_t>(sizeOfLastBlock*columnWidthReal + nLines);
fileH.seekg (elementPos, fileH.beg);
const std::size_t size = columnWidthReal;
std::vector<char> buffer(size);
fileH.read (buffer.data(), size);
vectorData[ind].push_back(std::strtof(buffer.data(), nullptr));
}
else {
int paramPos = it->second;
const std::uint64_t nFullBlocks = static_cast<std::uint64_t>(paramPos/(MaxBlockSizeReal / sizeOfReal));
std::uint64_t elementPos = ((2 * nFullBlocks) + 1) * static_cast<std::uint64_t>(sizeOfInte);
elementPos += static_cast<std::uint64_t>(paramPos) * static_cast<std::uint64_t>(sizeOfReal) + stepFilePos;
if (formattedFiles[specInd]) {
std::uint64_t elementPos = 0;
int nBlocks = paramPos / MaxBlockSizeReal;
int sizeOfLastBlock = paramPos % MaxBlockSizeReal;
fileH.seekg (elementPos, fileH.beg);
if (nBlocks > 0)
elementPos = static_cast<uint64_t>(nBlocks * blockSize_f);
float value;
fileH.read(reinterpret_cast<char*>(&value), sizeOfReal);
int nLines = sizeOfLastBlock / numColumnsReal;
elementPos = stepFilePos + elementPos + static_cast<std::uint64_t>(sizeOfLastBlock*columnWidthReal + nLines);
fileH.seekg (elementPos, fileH.beg);
const std::size_t size = columnWidthReal;
std::vector<char> buffer(size);
fileH.read (buffer.data(), size);
vectorData[ind].push_back(std::strtof(buffer.data(), nullptr));
}
else {
const std::uint64_t nFullBlocks = static_cast<std::uint64_t>(paramPos/(MaxBlockSizeReal / sizeOfReal));
std::uint64_t elementPos = ((2 * nFullBlocks) + 1) * static_cast<std::uint64_t>(sizeOfInte);
elementPos += static_cast<std::uint64_t>(paramPos) * static_cast<std::uint64_t>(sizeOfReal) + stepFilePos;
fileH.seekg (elementPos, fileH.beg);
float value;
fileH.read(reinterpret_cast<char*>(&value), sizeOfReal);
vectorData[ind].push_back(Opm::EclIO::flipEndianFloat(value));
}
vectorData[ind].push_back(Opm::EclIO::flipEndianFloat(value));
}
}
}
fileH.close();
}
fileH.close();
for (const auto& ind : keywIndVect)
vectorLoaded[ind] = true;
}
@ -830,110 +675,103 @@ std::vector<int> ESmry::makeKeywPosVector(int specInd) const
void ESmry::LoadData() const
{
if (lodEnabeled) {
std::fstream fileH;
this ->LoadData(keyword);
auto specInd = std::get<0>(timeStepList[0]);
auto dataFileIndex = std::get<1>(timeStepList[0]);
}
else {
std::fstream fileH;
std::vector<int> keywpos = makeKeywPosVector(specInd);
auto specInd = std::get<0>(timeStepList[0]);
auto dataFileIndex = std::get<1>(timeStepList[0]);
std::vector<int> keywpos = makeKeywPosVector(specInd);
auto openMode = formattedFiles[specInd]
? std::ios::in
: std::ios::in | std::ios::binary;
fileH.open(dataFileList[dataFileIndex], openMode);
for (const auto& ministep : timeStepList) {
if (dataFileIndex != std::get<1>(ministep)) {
fileH.close();
if (specInd != std::get<0>(ministep)) {
specInd = std::get<0>(ministep);
keywpos = makeKeywPosVector(specInd);
}
dataFileIndex = std::get<1>(ministep);
openMode = formattedFiles[specInd]
auto openMode = formattedFiles[specInd]
? std::ios::in
: std::ios::in | std::ios::binary;
fileH.open(dataFileList[dataFileIndex], openMode);
fileH.open(dataFileList[dataFileIndex], openMode);
for (const auto& ministep : timeStepList) {
if (dataFileIndex != std::get<1>(ministep)) {
fileH.close();
if (specInd != std::get<0>(ministep)) {
specInd = std::get<0>(ministep);
keywpos = makeKeywPosVector(specInd);
}
const auto stepFilePos = std::get<2>(ministep);
const auto maxNumberOfElements = MaxBlockSizeReal / sizeOfReal;
fileH.seekg (stepFilePos, fileH.beg);
dataFileIndex = std::get<1>(ministep);
if (formattedFiles[specInd]) {
const std::size_t size = sizeOnDiskFormatted(nParamsSpecFile[specInd], Opm::EclIO::REAL, sizeOfReal) + 1;
std::vector<char> buffer(size);
fileH.read (buffer.data(), size);
openMode = formattedFiles[specInd]
? std::ios::in
: std::ios::in | std::ios::binary;
const auto fileStr = std::string_view(buffer.data(), size);
std::size_t p = 0;
std::int64_t p1= 0;
for (int i=0; i< nParamsSpecFile[specInd]; ++i, ++p) {
p1 = fileStr.find_first_not_of(' ',p1);
const std::int64_t p2 = fileStr.find_first_of(' ', p1);
if ((keywpos[p] > -1) && !vectorLoaded[keywpos[p]]) {
const auto dtmpv = std::strtof(fileStr.substr(p1, p2-p1).data(), nullptr);
vectorData[keywpos[p]].push_back(dtmpv);
}
p1 = fileStr.find_first_not_of(' ',p2);
}
}
else {
std::int64_t rest = static_cast<int64_t>(nParamsSpecFile[specInd]);
std::size_t p = 0;
while (rest > 0) {
int dhead;
fileH.read(reinterpret_cast<char*>(&dhead), sizeof(dhead));
dhead = Opm::EclIO::flipEndianInt(dhead);
const int num = dhead / sizeOfInte;
if ((num > maxNumberOfElements) || (num < 0))
OPM_THROW(std::runtime_error, "??Error reading binary data, inconsistent header data or incorrect number of elements");
for (int i = 0; i < num; ++i, ++p) {
float value;
fileH.read(reinterpret_cast<char*>(&value), sizeOfReal);
if ((keywpos[p] > -1) && !vectorLoaded[keywpos[p]])
vectorData[keywpos[p]].push_back(Opm::EclIO::flipEndianFloat(value));
}
rest -= num;
if (( num < maxNumberOfElements && rest != 0) ||
(num == maxNumberOfElements && rest < 0))
{
std::string message = "Error reading binary data, incorrect number of elements";
OPM_THROW(std::runtime_error, message);
}
int dtail;
fileH.read(reinterpret_cast<char*>(&dtail), sizeof(dtail));
dtail = Opm::EclIO::flipEndianInt(dtail);
if (dhead != dtail)
OPM_THROW(std::runtime_error, "Error reading binary data, tail not matching header.");
}
}
fileH.open(dataFileList[dataFileIndex], openMode);
}
std::fill_n(vectorLoaded.begin(), nVect, true);
const auto stepFilePos = std::get<2>(ministep);
const auto maxNumberOfElements = MaxBlockSizeReal / sizeOfReal;
fileH.seekg (stepFilePos, fileH.beg);
if (formattedFiles[specInd]) {
const std::size_t size = sizeOnDiskFormatted(nParamsSpecFile[specInd], Opm::EclIO::REAL, sizeOfReal) + 1;
std::vector<char> buffer(size);
fileH.read (buffer.data(), size);
const auto fileStr = std::string_view(buffer.data(), size);
std::size_t p = 0;
std::int64_t p1= 0;
for (int i=0; i< nParamsSpecFile[specInd]; ++i, ++p) {
p1 = fileStr.find_first_not_of(' ',p1);
const std::int64_t p2 = fileStr.find_first_of(' ', p1);
if ((keywpos[p] > -1) && !vectorLoaded[keywpos[p]]) {
const auto dtmpv = std::strtof(fileStr.substr(p1, p2-p1).data(), nullptr);
vectorData[keywpos[p]].push_back(dtmpv);
}
p1 = fileStr.find_first_not_of(' ',p2);
}
}
else {
std::int64_t rest = static_cast<int64_t>(nParamsSpecFile[specInd]);
std::size_t p = 0;
while (rest > 0) {
int dhead;
fileH.read(reinterpret_cast<char*>(&dhead), sizeof(dhead));
dhead = Opm::EclIO::flipEndianInt(dhead);
const int num = dhead / sizeOfInte;
if ((num > maxNumberOfElements) || (num < 0))
OPM_THROW(std::runtime_error, "??Error reading binary data, inconsistent header data or incorrect number of elements");
for (int i = 0; i < num; ++i, ++p) {
float value;
fileH.read(reinterpret_cast<char*>(&value), sizeOfReal);
if ((keywpos[p] > -1) && !vectorLoaded[keywpos[p]])
vectorData[keywpos[p]].push_back(Opm::EclIO::flipEndianFloat(value));
}
rest -= num;
if (( num < maxNumberOfElements && rest != 0) ||
(num == maxNumberOfElements && rest < 0))
{
std::string message = "Error reading binary data, incorrect number of elements";
OPM_THROW(std::runtime_error, message);
}
int dtail;
fileH.read(reinterpret_cast<char*>(&dtail), sizeof(dtail));
dtail = Opm::EclIO::flipEndianInt(dtail);
if (dhead != dtail)
OPM_THROW(std::runtime_error, "Error reading binary data, tail not matching header.");
}
}
}
std::fill_n(vectorLoaded.begin(), nVect, true);
}
@ -1124,6 +962,7 @@ bool ESmry::make_lodsmry_file()
}
std::vector<std::string> ESmry::checkForMultipleResultFiles(const Opm::filesystem::path& rootN, bool formatted) const {
std::vector<std::string> fileList;

View File

@ -0,0 +1,184 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include <opm/io/eclipse/EclUtil.hpp>
#include <opm/io/eclipse/EclFile.hpp>
#include <opm/io/eclipse/ESmryOutput.hpp>
#include <opm/io/eclipse/EclOutput.hpp>
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
#include <opm/common/utility/TimeService.hpp>
#include <stdexcept>
#include <string>
namespace Opm { namespace EclIO {
ESmryOutput::ESmryOutput(const std::vector<std::string>& valueKeys, const std::vector<std::string>& valueUnits,
const EclipseState& es, const time_t start_time)
{
m_nVect = valueKeys.size();
m_nTimeSteps = 0;
IOConfig ioconf = es.getIOConfig();
m_restart_rootn = "";
m_restart_step = -1;
InitConfig initcfg = es.getInitConfig();
if (initcfg.restartRequested()) {
m_restart_rootn = initcfg.getRestartRootName();
m_restart_step = initcfg.getRestartStep();
}
m_fmt = es.cfg().io().getFMTOUT();
auto dims = es.gridDims();
m_outputFileName = ioconf.getOutputDir() + "/" + ioconf.getBaseName() + ".ESMRY";
m_smry_keys = this->make_modified_keys(valueKeys, dims);
m_smryUnits = valueUnits;
Opm::time_point startdat = Opm::TimeService::from_time_t(start_time);
Opm::TimeStampUTC ts( std::chrono::system_clock::to_time_t( startdat ));
m_start_date_vect = {ts.day(), ts.month(), ts.year(),
ts.hour(), ts.minutes(), ts.seconds(), 0 };
for (size_t n = 0; n < static_cast<size_t>(m_nVect); n++)
m_smrydata.push_back({});
}
void ESmryOutput::write(const std::vector<float>& ts_data, int report_step)
{
if (ts_data.size() != static_cast<size_t>(m_nVect))
throw std::invalid_argument("size of ts_data vector not same as number of smry vectors");
m_rstep.push_back(report_step);
// flow is yet not supporting rptonly in summary
// tstep = {0,1,2 .. , m_nTimeSteps-1}
if (m_tstep.size()==0)
m_tstep.push_back(0);
else
m_tstep.push_back(m_tstep.back()+1);
for (size_t n = 0; n < static_cast<size_t>(m_nVect); n++)
m_smrydata[n].push_back(ts_data[n]);
{
Opm::EclIO::EclOutput outFile(m_outputFileName, m_fmt, std::ios::out);
outFile.write<int>("START", m_start_date_vect);
if (m_restart_rootn.size() > 0) {
outFile.write<std::string>("RESTART", {m_restart_rootn});
outFile.write<int>("RSTNUM", {m_restart_step});
}
outFile.write("KEYCHECK", m_smry_keys);
outFile.write("UNITS", m_smryUnits);
outFile.write<int>("RSTEP", m_rstep);
outFile.write<int>("TSTEP", m_tstep);
for (size_t n = 0; n < static_cast<size_t>(m_nVect); n++ ) {
std::string vect_name="V" + std::to_string(n);
outFile.write<float>(vect_name, m_smrydata[n]);
}
}
m_nTimeSteps++;
}
std::vector<std::string> ESmryOutput::make_modified_keys(const std::vector<std::string> valueKeys, const GridDims& dims)
{
std::vector<std::string> mod_keys;
mod_keys.reserve(valueKeys.size());
for (size_t n=0; n < valueKeys.size(); n++){
if (valueKeys[n].substr(0,15) == "SMSPEC.Internal"){
std::string mod_key = valueKeys[n].substr(16);
int p = mod_key.find_first_of(".");
mod_key=mod_key.substr(0,p);
mod_keys.push_back(mod_key);
} else if (valueKeys[n].substr(0,1) == "C"){
size_t p = valueKeys[n].find_first_of(":");
p = valueKeys[n].find_first_of(":", p + 1);
int num = std::stod(valueKeys[n].substr(p + 1)) - 1;
auto ijk = ijk_from_global_index(dims, num);
std::string mod_key = valueKeys[n].substr(0, p + 1);
mod_key = mod_key + std::to_string(ijk[0] + 1) + "," + std::to_string(ijk[1] + 1) + "," + std::to_string(ijk[2] + 1);
mod_keys.push_back(mod_key);
} else if (valueKeys[n].substr(0,1) == "B"){
size_t p = valueKeys[n].find_first_of(":");
int num = std::stod(valueKeys[n].substr(p + 1)) - 1;
auto ijk = ijk_from_global_index(dims, num);
std::string mod_key = valueKeys[n].substr(0, p + 1);
mod_key = mod_key + std::to_string(ijk[0] + 1) + "," + std::to_string(ijk[1] + 1) + "," + std::to_string(ijk[2] + 1);
mod_keys.push_back(mod_key);
} else {
mod_keys.push_back(valueKeys[n]);
}
}
return mod_keys;
}
std::array<int, 3> ESmryOutput::ijk_from_global_index(const GridDims& dims, int globInd) const
{
if (globInd < 0 || static_cast<size_t>(globInd) >= dims[0] * dims[1] * dims[2])
throw std::invalid_argument("global index out of range");
std::array<int, 3> result;
result[0] = globInd % dims[0];
globInd /= dims[0];
result[1] = globInd % dims[1];
result[2] = globInd / dims[1];
return result;
}
}} // namespace Opm::EclIO

View File

@ -64,6 +64,7 @@
#include <opm/common/utility/FileSystem.hpp>
namespace {
inline std::string uppercase( std::string x ) {
@ -103,7 +104,7 @@ void ensure_directory_exists( const Opm::filesystem::path& odir )
namespace Opm {
class EclipseIO::Impl {
public:
Impl( const EclipseState&, EclipseGrid, const Schedule&, const SummaryConfig& );
Impl( const EclipseState&, EclipseGrid, const Schedule&, const SummaryConfig& , const std::string& baseName, const bool& writeEsmry);
void writeINITFile( const data::Solution& simProps, std::map<std::string, std::vector<int> > int_data, const std::vector<NNCdata>& nnc) const;
void writeEGRIDFile( const std::vector<NNCdata>& nnc );
std::pair<bool, bool> wantRFTOutput( const int report_step, const bool isSubstep ) const;
@ -135,14 +136,16 @@ private:
EclipseIO::Impl::Impl( const EclipseState& eclipseState,
EclipseGrid grid_,
const Schedule& schedule_,
const SummaryConfig& summary_config)
const SummaryConfig& summary_config,
const std::string& base_name,
const bool& writeEsmry)
: es( eclipseState )
, grid( std::move( grid_ ) )
, schedule( schedule_ )
, outputDir( eclipseState.getIOConfig().getOutputDir() )
, baseName( uppercase( eclipseState.getIOConfig().getBaseName() ) )
, summaryConfig( summary_config )
, summary( eclipseState, summaryConfig, grid , schedule )
, summary( eclipseState, summaryConfig, grid , schedule, base_name, writeEsmry )
, output_enabled( eclipseState.getIOConfig().getOutputEnabled() )
{
const auto& aqConfig = this->es.aquifer();
@ -276,7 +279,7 @@ void EclipseIO::writeTimeStep(const Action::State& action_state,
if ((report_step > 0) &&
this->impl->wantSummaryOutput(report_step, isSubstep, secs_elapsed))
{
this->impl->summary.add_timestep(st, report_step);
this->impl->summary.add_timestep(st, report_step, isSubstep);
this->impl->summary.write();
this->impl->recordSummaryOutput(secs_elapsed);
@ -364,8 +367,11 @@ RestartValue EclipseIO::loadRestart(Action::State& action_state, SummaryState& s
EclipseIO::EclipseIO( const EclipseState& es,
EclipseGrid grid,
const Schedule& schedule,
const SummaryConfig& summary_config)
: impl( new Impl( es, std::move( grid ), schedule , summary_config) )
const SummaryConfig& summary_config,
const std::string& baseName,
const bool writeEsmry
)
: impl( new Impl( es, std::move( grid ), schedule , summary_config, baseName, writeEsmry) )
{
if( !this->impl->output_enabled )
return;

View File

@ -45,11 +45,14 @@
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.hpp>
#include <opm/common/utility/TimeService.hpp>
#include <opm/common/utility/FileSystem.hpp>
#include <opm/parser/eclipse/Units/UnitSystem.hpp>
#include <opm/parser/eclipse/Units/Units.hpp>
#include <opm/io/eclipse/EclOutput.hpp>
#include <opm/io/eclipse/OutputStream.hpp>
#include <opm/io/eclipse/ESmryOutput.hpp>
#include <opm/output/data/Groups.hpp>
#include <opm/output/data/GuideRateValue.hpp>
@ -1015,7 +1018,7 @@ inline quantity temperature( const fn_args& args ) {
const auto p = args.wells.find(args.schedule_wells.front()->name());
if ((p == args.wells.end()) ||
(p->second.dynamicStatus == Opm::Well::Status::SHUT) ||
(p->second.dynamicStatus == Opm::Well::Status::SHUT) ||
(p->second.current_control.isProducer == injection))
{
return zero;
@ -3184,7 +3187,9 @@ public:
const SummaryConfig& sumcfg,
const EclipseGrid& grid,
const Schedule& sched,
const std::string& basename);
const std::string& basename,
const bool writeEsmry
);
SummaryImplementation(const SummaryImplementation& rhs) = delete;
SummaryImplementation(SummaryImplementation&& rhs) = default;
@ -3203,7 +3208,7 @@ public:
const data::Aquifers& aquifer_values,
SummaryState& st) const;
void internal_store(const SummaryState& st, const int report_step);
void internal_store(const SummaryState& st, const int report_step, bool isSubstep);
void write();
PAvgCalculatorCollection wbp_calculators(std::size_t report_step) const;
@ -3212,6 +3217,7 @@ private:
{
int id{0};
int seq{-1};
bool isSubstep{false};
std::vector<float> params{};
};
@ -3239,11 +3245,14 @@ private:
SummaryOutputParameters outputParameters_{};
std::unordered_map<std::string, EvalPtr> extra_parameters{};
std::vector<std::string> valueKeys_{};
std::vector<std::string> valueUnits_{};
std::vector<MiniStep> unwritten_{};
std::unique_ptr<Opm::EclIO::OutputStream::SummarySpecification> smspec_{};
std::unique_ptr<Opm::EclIO::EclOutput> stream_{};
std::unique_ptr<Opm::EclIO::ESmryOutput> esmry_;
void configureTimeVectors(const EclipseState& es, const SummaryConfig& sumcfg);
void configureSummaryInput(const SummaryConfig& sumcfg,
@ -3256,7 +3265,7 @@ private:
void configureUDQ(const SummaryConfig& summary_config, const Schedule& sched);
MiniStep& getNextMiniStep(const int report_step);
MiniStep& getNextMiniStep(const int report_step, bool isSubstep);
const MiniStep& lastUnwritten() const;
void write(const MiniStep& ms);
@ -3270,7 +3279,9 @@ SummaryImplementation(const EclipseState& es,
const SummaryConfig& sumcfg,
const EclipseGrid& grid,
const Schedule& sched,
const std::string& basename)
const std::string& basename,
const bool writeEsmry
)
: grid_ (std::cref(grid))
, es_ (std::cref(es))
, sched_ (std::cref(sched))
@ -3296,12 +3307,23 @@ SummaryImplementation(const EclipseState& es,
for (const auto& config_node : sumcfg.keywords("WBP*"))
this->wbp_wells.insert( config_node.namedEntity() );
std::string esmryFileName = EclIO::OutputStream::outputFileName(this->rset_, "ESMRY");
if (Opm::filesystem::exists(esmryFileName))
Opm::filesystem::remove(esmryFileName);
if ((writeEsmry) and (es.cfg().io().getFMTOUT()==false))
this->esmry_ = std::make_unique<Opm::EclIO::ESmryOutput>(this->valueKeys_, this->valueUnits_, es, sched.posixStartTime());
if ((writeEsmry) and (es.cfg().io().getFMTOUT()))
OpmLog::warning("ESMRY only supported for unformatted output. Request ignored.");
}
void Opm::out::Summary::SummaryImplementation::
internal_store(const SummaryState& st, const int report_step)
internal_store(const SummaryState& st, const int report_step, bool isSubstep)
{
auto& ms = this->getNextMiniStep(report_step);
auto& ms = this->getNextMiniStep(report_step, isSubstep);
const auto nParam = this->valueKeys_.size();
@ -3386,6 +3408,8 @@ void Opm::out::Summary::SummaryImplementation::write()
// No unwritten data. Nothing to do so return early.
return;
this->createSMSpecIfNecessary();
if (this->prevReportStepID_ < this->lastUnwritten().seq) {
@ -3398,6 +3422,12 @@ void Opm::out::Summary::SummaryImplementation::write()
// Eagerly output last set of parameters to permanent storage.
this->stream_->flushStream();
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);
}
}
// Reset "unwritten" counter to reflect the fact that we've
// output all stored ministeps.
this->numUnwritten_ = zero;
@ -3441,6 +3471,9 @@ configureTimeVectors(const EclipseState& es, const SummaryConfig& sumcfg)
const std::string& unit_string = es.getUnits().name(UnitSystem::measure::time);
auto eval = std::make_unique<Evaluator::Time>(this->valueKeys_.back());
valueUnits_.push_back(unit_string);
this->outputParameters_
.makeParameter(kw, dfltwgname, dfltnum, unit_string, std::move(eval));
}
@ -3450,6 +3483,8 @@ configureTimeVectors(const EclipseState& es, const SummaryConfig& sumcfg)
makeKey(kw);
auto eval = std::make_unique<Evaluator::Day>(this->valueKeys_.back());
valueUnits_.push_back("");
this->outputParameters_
.makeParameter(kw, dfltwgname, dfltnum, "", std::move(eval));
}
@ -3459,6 +3494,8 @@ configureTimeVectors(const EclipseState& es, const SummaryConfig& sumcfg)
makeKey(kw);
auto eval = std::make_unique<Evaluator::Month>(this->valueKeys_.back());
valueUnits_.push_back("");
this->outputParameters_
.makeParameter(kw, dfltwgname, dfltnum, "", std::move(eval));
}
@ -3468,6 +3505,7 @@ configureTimeVectors(const EclipseState& es, const SummaryConfig& sumcfg)
makeKey(kw);
auto eval = std::make_unique<Evaluator::Year>(this->valueKeys_.back());
valueUnits_.push_back("");
this->outputParameters_
.makeParameter(kw, dfltwgname, dfltnum, "", std::move(eval));
}
@ -3478,6 +3516,7 @@ configureTimeVectors(const EclipseState& es, const SummaryConfig& sumcfg)
makeKey(kw);
auto eval = std::make_unique<Evaluator::Years>(this->valueKeys_.back());
valueUnits_.push_back("");
this->outputParameters_
.makeParameter(kw, dfltwgname, dfltnum, kw, std::move(eval));
@ -3502,6 +3541,7 @@ configureSummaryInput(const SummaryConfig& sumcfg,
// This keyword has a known evaluation method.
this->valueKeys_.push_back(std::move(prmDescr.uniquekey));
this->valueUnits_.push_back(prmDescr.unit);
this->outputParameters_
.makeParameter(node.keyword(),
@ -3698,7 +3738,7 @@ configureRequiredRestartParameters(const SummaryConfig& sumcfg,
}
Opm::out::Summary::SummaryImplementation::MiniStep&
Opm::out::Summary::SummaryImplementation::getNextMiniStep(const int report_step)
Opm::out::Summary::SummaryImplementation::getNextMiniStep(const int report_step, bool isSubstep)
{
if (this->numUnwritten_ == this->unwritten_.size())
this->unwritten_.emplace_back();
@ -3710,6 +3750,7 @@ Opm::out::Summary::SummaryImplementation::getNextMiniStep(const int report_step)
ms.id = this->miniStepID_ - 1; // MINISTEP IDs start at zero.
ms.seq = report_step;
ms.isSubstep = isSubstep;
ms.params.resize(this->valueKeys_.size(), 0.0f);
@ -3766,8 +3807,10 @@ Summary::Summary(const EclipseState& es,
const SummaryConfig& sumcfg,
const EclipseGrid& grid,
const Schedule& sched,
const std::string& basename)
: pImpl_(new SummaryImplementation(es, sumcfg, grid, sched, basename))
const std::string& basename,
const bool& writeEsmry
)
: pImpl_(new SummaryImplementation(es, sumcfg, grid, sched, basename, writeEsmry))
{}
void Summary::eval(SummaryState& st,
@ -3806,9 +3849,9 @@ Summary::wbp_calculators(std::size_t report_step) const
return this->pImpl_->wbp_calculators(report_step);
}
void Summary::add_timestep(const SummaryState& st, const int report_step)
void Summary::add_timestep(const SummaryState& st, const int report_step, bool isSubstep)
{
this->pImpl_->internal_store(st, report_step);
this->pImpl_->internal_store(st, report_step, isSubstep);
}
void Summary::write() const

View File

@ -536,13 +536,13 @@ BOOST_AUTO_TEST_CASE(well_keywords) {
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.schedule , cfg.name );
writer.eval(st, 0, 0*day, cfg.wells, cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 0);
writer.add_timestep( st, 0, false);
writer.eval(st, 1, 1*day, cfg.wells, cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 1);
writer.add_timestep( st, 1, false);
writer.eval(st, 2, 2*day, cfg.wells, cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 2);
writer.add_timestep( st, 2, false);
writer.write();
@ -805,15 +805,15 @@ BOOST_AUTO_TEST_CASE(well_keywords_dynamic_close) {
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.schedule, cfg.name );
writer.eval(st, 0, 0*day, cfg.wells, cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 0);
writer.add_timestep( st, 0, false);
cfg.wells.at("W_2").dynamicStatus = ::Opm::Well::Status::SHUT;
writer.eval(st, 1, 1*day, cfg.wells, cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 1);
writer.add_timestep( st, 1, false);
cfg.wells.at("W_2").dynamicStatus = ::Opm::Well::Status::OPEN;
writer.eval(st, 2, 2*day, cfg.wells, cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 2);
writer.add_timestep( st, 2, false);
writer.write();
auto res = readsum( cfg.name );
@ -925,11 +925,11 @@ BOOST_AUTO_TEST_CASE(udq_keywords) {
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.schedule , cfg.name );
SummaryState st(TimeService::now());
writer.eval( st, 0, 0 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 0);
writer.add_timestep( st, 0, false);
writer.eval( st, 1, 1 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 1);
writer.add_timestep( st, 1, false);
writer.eval( st, 2, 2 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 2);
writer.add_timestep( st, 2, false);
writer.write();
auto res = readsum( cfg.name );
@ -950,13 +950,13 @@ BOOST_AUTO_TEST_CASE(group_keywords) {
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.schedule, cfg.name );
SummaryState st(TimeService::now());
writer.eval( st, 0, 0 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 0);
writer.add_timestep( st, 0, false);
writer.eval( st, 1, 1 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 1);
writer.add_timestep( st, 1, false);
writer.eval( st, 2, 2 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 2);
writer.add_timestep( st, 2, false);
writer.write();
@ -1107,11 +1107,11 @@ BOOST_AUTO_TEST_CASE(group_group) {
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.schedule, cfg.name );
SummaryState st(TimeService::now());
writer.eval( st, 0, 0 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 0);
writer.add_timestep( st, 0, false);
writer.eval( st, 1, 1 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 1);
writer.add_timestep( st, 1, false);
writer.eval( st, 2, 2 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 2);
writer.add_timestep( st, 2, false);
writer.write();
auto res = readsum( cfg.name );
@ -1163,11 +1163,11 @@ BOOST_AUTO_TEST_CASE(connection_kewords) {
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.schedule, cfg.name );
SummaryState st(TimeService::now());
writer.eval( st, 0, 0 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 0);
writer.add_timestep( st, 0, false);
writer.eval( st, 1, 1 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 1);
writer.add_timestep( st, 1, false);
writer.eval( st, 2, 2 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 2);
writer.add_timestep( st, 2, false);
writer.write();
auto res = readsum( cfg.name );
@ -1270,13 +1270,13 @@ BOOST_AUTO_TEST_CASE(DATE) {
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.schedule, cfg.name );
SummaryState st(TimeService::now());
writer.eval( st, 1, 1 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 1);
writer.add_timestep( st, 1, false);
writer.eval( st, 2, 2 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 2);
writer.add_timestep( st, 2, false);
writer.eval( st, 3, 18 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 3);
writer.add_timestep( st, 3, false);
writer.eval( st, 4, 22 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 4);
writer.add_timestep( st, 4, false);
writer.write();
auto res = readsum( cfg.name );
@ -1307,11 +1307,11 @@ BOOST_AUTO_TEST_CASE(field_keywords) {
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.schedule, cfg.name );
SummaryState st(TimeService::now());
writer.eval( st, 0, 0 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 0);
writer.add_timestep( st, 0, false);
writer.eval( st, 1, 1 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 1);
writer.add_timestep( st, 1, false);
writer.eval( st, 2, 2 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 2);
writer.add_timestep( st, 2, false);
writer.write();
auto res = readsum( cfg.name );
@ -1447,11 +1447,11 @@ BOOST_AUTO_TEST_CASE(report_steps_time) {
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.schedule, cfg.name );
SummaryState st(TimeService::now());
writer.eval( st, 1, 2 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 1);
writer.add_timestep( st, 1, false);
writer.eval( st, 1, 5 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 1);
writer.add_timestep( st, 1, false);
writer.eval( st, 2, 10 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 2);
writer.add_timestep( st, 2, false);
writer.write();
auto res = readsum( cfg.name );
@ -1474,11 +1474,11 @@ BOOST_AUTO_TEST_CASE(skip_unknown_var) {
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.schedule, cfg.name );
SummaryState st(TimeService::now());
writer.eval( st, 1, 2 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 1);
writer.add_timestep( st, 1, false);
writer.eval( st, 1, 5 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 1);
writer.add_timestep( st, 1, false);
writer.eval( st, 2, 10 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 2);
writer.add_timestep( st, 2, false);
writer.write();
auto res = readsum( cfg.name );
@ -1584,11 +1584,11 @@ BOOST_AUTO_TEST_CASE(region_vars) {
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.schedule, cfg.name );
SummaryState st(TimeService::now());
writer.eval( st, 1, 2 * day, cfg.wells, cfg.grp_nwrk, {}, {}, {}, {}, region_values);
writer.add_timestep( st, 1);
writer.add_timestep( st, 1, false);
writer.eval( st, 1, 5 * day, cfg.wells, cfg.grp_nwrk, {}, {}, {}, {}, region_values);
writer.add_timestep( st, 1);
writer.add_timestep( st, 1, false);
writer.eval( st, 2, 10 * day, cfg.wells, cfg.grp_nwrk, {}, {}, {}, {}, region_values);
writer.add_timestep( st, 2);
writer.add_timestep( st, 2, false);
writer.write();
}
@ -1635,11 +1635,11 @@ BOOST_AUTO_TEST_CASE(region_production) {
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.schedule, cfg.name );
SummaryState st(TimeService::now());
writer.eval( st, 0, 0 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 0);
writer.add_timestep( st, 0, false);
writer.eval( st, 1, 1 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 1);
writer.add_timestep( st, 1, false);
writer.eval( st, 2, 2 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 2);
writer.add_timestep( st, 2, false);
writer.write();
}
@ -1667,11 +1667,11 @@ BOOST_AUTO_TEST_CASE(region_injection) {
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.schedule, cfg.name );
SummaryState st(TimeService::now());
writer.eval( st, 0, 0 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 0);
writer.add_timestep( st, 0, false);
writer.eval( st, 1, 1 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 1);
writer.add_timestep( st, 1, false);
writer.eval( st, 2, 2 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 2);
writer.add_timestep( st, 2, false);
writer.write();
auto res = readsum( cfg.name );
@ -1725,15 +1725,15 @@ BOOST_AUTO_TEST_CASE(BLOCK_VARIABLES) {
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.schedule, cfg.name );
SummaryState st(TimeService::now());
writer.eval( st, 0, 0 * day, cfg.wells , cfg.grp_nwrk, {},{}, {}, {}, {}, block_values);
writer.add_timestep( st, 0);
writer.add_timestep( st, 0, false);
writer.eval( st, 1, 1 * day, cfg.wells , cfg.grp_nwrk, {},{}, {}, {}, {}, block_values);
writer.add_timestep( st, 1);
writer.add_timestep( st, 1, false);
writer.eval( st, 2, 2 * day, cfg.wells , cfg.grp_nwrk, {},{}, {}, {}, {}, block_values);
writer.add_timestep( st, 2);
writer.add_timestep( st, 2, false);
writer.eval( st, 3, 2 * day, cfg.wells , cfg.grp_nwrk, {},{}, {}, {}, {}, block_values);
writer.add_timestep( st, 3);
writer.add_timestep( st, 3, false);
writer.eval( st, 4, 2 * day, cfg.wells , cfg.grp_nwrk, {},{}, {}, {}, {}, block_values);
writer.add_timestep( st, 4);
writer.add_timestep( st, 4, false);
writer.write();
auto res = readsum( cfg.name );
@ -1786,13 +1786,13 @@ BOOST_AUTO_TEST_CASE(NODE_VARIABLES) {
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.schedule, cfg.name );
SummaryState st(TimeService::now());
writer.eval( st, 0, 0 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 0);
writer.add_timestep( st, 0, false);
writer.eval( st, 1, 1 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 1);
writer.add_timestep( st, 1, false);
writer.eval( st, 2, 2 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 2);
writer.add_timestep( st, 2, false);
writer.write();
@ -1844,11 +1844,11 @@ BOOST_AUTO_TEST_CASE(MISC) {
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.schedule , cfg.name );
SummaryState st(TimeService::now());
writer.eval( st, 0, 0 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 0);
writer.add_timestep( st, 0, false);
writer.eval( st, 1, 1 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 1);
writer.add_timestep( st, 1, false);
writer.eval( st, 2, 2 * day, cfg.wells , cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 2);
writer.add_timestep( st, 2, false);
writer.write();
auto res = readsum( cfg.name );
@ -1864,19 +1864,19 @@ BOOST_AUTO_TEST_CASE(EXTRA) {
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.schedule , cfg.name );
SummaryState st(TimeService::now());
writer.eval( st, 0, 0 * day, cfg.wells , cfg.grp_nwrk, { {"TCPU" , 0 }}, {}, {}, {});
writer.add_timestep( st, 0);
writer.add_timestep( st, 0, false);
writer.eval( st, 1, 1 * day, cfg.wells , cfg.grp_nwrk, { {"TCPU" , 1 }}, {}, {}, {});
writer.add_timestep( st, 1);
writer.add_timestep( st, 1, false);
writer.eval( st, 2, 2 * day, cfg.wells , cfg.grp_nwrk, { {"TCPU" , 2}}, {}, {}, {});
writer.add_timestep( st, 2);
writer.add_timestep( st, 2, false);
/* Add a not-recognized key; that is OK */
BOOST_CHECK_NO_THROW( writer.eval( st, 3, 3 * day, cfg.wells , cfg.grp_nwrk, { {"MISSING" , 2 }}, {}, {}, {}));
BOOST_CHECK_NO_THROW( writer.add_timestep( st, 3));
BOOST_CHECK_NO_THROW( writer.add_timestep( st, 3, false));
/* Override a NOT MISC variable - ignored. */
writer.eval( st, 4, 4 * day, cfg.wells, cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 4);
writer.add_timestep( st, 4, false);
writer.write();
}
@ -2000,11 +2000,11 @@ BOOST_AUTO_TEST_CASE(efficiency_factor) {
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.schedule, cfg.name );
SummaryState st(TimeService::now());
writer.eval( st, 0, 0 * day, cfg.wells, cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 0);
writer.add_timestep( st, 0, false);
writer.eval( st, 1, 1 * day, cfg.wells, cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 1);
writer.add_timestep( st, 1, false);
writer.eval( st, 2, 2 * day, cfg.wells, cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 2);
writer.add_timestep( st, 2, false);
writer.write();
auto res = readsum( cfg.name );
const auto* resp = res.get();
@ -2281,11 +2281,11 @@ namespace {
SummaryState st(TimeService::now());
smry.eval(st, 0, 0*day, config.wells, config.grp_nwrk, {}, {}, {}, {});
smry.add_timestep(st, 0);
smry.add_timestep(st, 0, false);
smry.eval(st, 1, 1*day, config.wells, config.grp_nwrk, {}, {}, {}, {});
smry.add_timestep(st, 1);
smry.add_timestep(st, 1, false);
smry.eval(st, 2, 2*day, config.wells, config.grp_nwrk, {}, {}, {}, {});
smry.add_timestep(st, 2);
smry.add_timestep(st, 2, false);
return st;
}
@ -3285,11 +3285,11 @@ BOOST_AUTO_TEST_CASE(Write_Read)
SummaryState st(TimeService::now());
writer.eval(st, 0, 0*day, config.wells, config.grp_nwrk, {}, {}, {}, {});
writer.add_timestep(st, 0);
writer.add_timestep(st, 0, false);
writer.eval(st, 1, 1*day, config.wells, config.grp_nwrk, {}, {}, {}, {});
writer.add_timestep(st, 1);
writer.add_timestep(st, 1, false);
writer.eval(st, 2, 2*day, config.wells, config.grp_nwrk, {}, {}, {}, {});
writer.add_timestep(st, 2);
writer.add_timestep(st, 2, false);
writer.write();
auto res = readsum("SOFR_TEST");

View File

@ -261,10 +261,10 @@ BOOST_AUTO_TEST_CASE(group_keywords) {
out::Summary writer( cfg.es, cfg.config, cfg.grid, cfg.schedule , cfg.name );
writer.eval(st, 0, 0*day, cfg.wells, cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 0);
writer.add_timestep( st, 0, false);
writer.eval(st, 1, 1*day, cfg.wells, cfg.grp_nwrk, {}, {}, {}, {});
writer.add_timestep( st, 1);
writer.add_timestep( st, 1, false);
writer.write();