Merge pull request #1785 from tskille/lod_esmry

Lod esmry
This commit is contained in:
Bård Skaflestad
2020-05-14 10:55:19 +02:00
committed by GitHub
8 changed files with 965 additions and 506 deletions

View File

@@ -478,6 +478,7 @@ if(ENABLE_ECL_INPUT)
examples/opmpack.cpp
examples/opmhash.cpp
examples/wellgraph.cpp
examples/make_lodsmry.cpp
)
endif()
@@ -490,6 +491,7 @@ if(ENABLE_ECL_INPUT)
examples/opmi.cpp
examples/opmpack.cpp
examples/opmhash.cpp
examples/make_lodsmry.cpp
)
endif()

102
examples/make_lodsmry.cpp Normal file
View File

@@ -0,0 +1,102 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
#include <iostream>
#include <getopt.h>
#include <omp.h>
#include <string.h>
#include <stdio.h>
#include <opm/io/eclipse/ESmry.hpp>
#include <opm/io/eclipse/EclUtil.hpp>
#include <opm/common/utility/FileSystem.hpp>
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"
<< "-n Maximum number of threads to be used if mulitple files should be created.\n"
<< "-h Print help and exit.\n\n";
}
int main(int argc, char **argv) {
int c = 0;
int max_threads = -1;
bool force = false;
while ((c = getopt(argc, argv, "fn:h")) != -1) {
switch (c) {
case 'f':
force = true;
break;
case 'h':
printHelp();
return 0;
case 'n':
max_threads = atoi(optarg);
break;
default:
return EXIT_FAILURE;
}
}
int argOffset = optind;
int available_threads = omp_get_max_threads();
if (max_threads < 0)
max_threads = available_threads-2;
else if (max_threads > (available_threads - 1))
max_threads = available_threads-1;
if (max_threads > (argc-argOffset))
max_threads = argc-argOffset;
omp_set_num_threads(max_threads);
auto lap0 = std::chrono::system_clock::now();
#pragma omp parallel for
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";
if (Opm::EclIO::fileExists(lodFileName) && (force))
remove (lodFileName);
Opm::EclIO::ESmry smryFile(argv[f]);
if (!smryFile.make_lodsmry_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<double> elapsed_seconds1 = lap1-lap0;
std::cout << "\nruntime for creating " << (argc-argOffset) << " LODSMRY files: " << elapsed_seconds1.count() << " seconds\n" << std::endl;
return 0;
}

View File

@@ -57,6 +57,8 @@ public:
void LoadData(const std::vector<std::string>& vectList) const;
void LoadData() const;
bool make_lodsmry_file();
std::chrono::system_clock::time_point startdate() const { return startdat; }
const std::vector<std::string>& keywordList() const;
@@ -65,7 +67,7 @@ public:
int timestepIdxAtReportstepStart(const int reportStep) const;
size_t numberOfTimeSteps() const { return timeStepList.size(); }
size_t numberOfTimeSteps() const { return nTstep; }
const std::string& get_unit(const std::string& name) const;
const std::string& get_unit(const SummaryNode& node) const;
@@ -74,9 +76,11 @@ public:
void write_rsm_file(std::optional<Opm::filesystem::path> = std::nullopt) const;
private:
Opm::filesystem::path inputFileName;
Opm::filesystem::path inputFileName, lodFileName;
int nI, nJ, nK, nSpecFiles;
size_t nVect;
bool fromSingleRun, lodEnabeled;
uint64_t lod_offset, lod_arr_size;
size_t nVect, nTstep;
std::vector<bool> formattedFiles;
std::vector<std::string> dataFileList;
@@ -129,6 +133,9 @@ 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;
};
}} // namespace Opm::EclIO

View File

@@ -23,6 +23,8 @@
#include <string>
#include <tuple>
#include <vector>
#include <functional>
namespace Opm { namespace EclIO {
@@ -31,6 +33,8 @@ namespace Opm { namespace EclIO {
float flipEndianFloat(float num);
double flipEndianDouble(double num);
bool isEOF(std::fstream* fileH);
bool fileExists(const std::string& filename);
bool isFormatted(const std::string& filename);
std::tuple<int, int> block_size_data_binary(eclArrType arrType);
std::tuple<int, int, int> block_size_data_formatted(eclArrType arrType);
@@ -49,6 +53,25 @@ namespace Opm { namespace EclIO {
void readFormattedHeader(std::fstream& fileH, std::string& arrName,
int64_t &num, Opm::EclIO::eclArrType &arrType);
template<typename T, typename T2>
std::vector<T> readBinaryArray(std::fstream& fileH, const int64_t size, Opm::EclIO::eclArrType type,
std::function<T(T2)>& flip);
std::vector<int> readBinaryInteArray(std::fstream &fileH, const int64_t size);
std::vector<float> readBinaryRealArray(std::fstream& fileH, const int64_t size);
std::vector<double> readBinaryDoubArray(std::fstream& fileH, const int64_t size);
std::vector<bool> readBinaryLogiArray(std::fstream &fileH, const int64_t size);
std::vector<std::string> readBinaryCharArray(std::fstream& fileH, const int64_t size);
template<typename T>
std::vector<T> readFormattedArray(const std::string& file_str, const int size, int64_t fromPos,
std::function<T(const std::string&)>& process);
std::vector<int> readFormattedInteArray(const std::string& file_str, const int64_t size, int64_t fromPos);
std::vector<std::string> readFormattedCharArray(const std::string& file_str, const int64_t size, int64_t fromPos);
std::vector<float> readFormattedRealArray(const std::string& file_str, const int64_t size, int64_t fromPos);
std::vector<bool> readFormattedLogiArray(const std::string& file_str, const int64_t size, int64_t fromPos);
std::vector<double> readFormattedDoubArray(const std::string& file_str, const int64_t size, int64_t fromPos);
}} // namespace Opm::EclIO

View File

@@ -21,6 +21,7 @@
#include <opm/common/utility/TimeService.hpp>
#include <opm/io/eclipse/EclFile.hpp>
#include <opm/io/eclipse/EclUtil.hpp>
#include <opm/io/eclipse/EclOutput.hpp>
#include <algorithm>
#include <chrono>
@@ -33,6 +34,7 @@
#include <fnmatch.h>
#include <fstream>
#include <cmath>
#include <cstring>
/*
@@ -87,10 +89,12 @@ ESmry::ESmry(const std::string &filename, bool loadBaseRunData) :
inputFileName { filename },
summaryNodes { }
{
fromSingleRun = !loadBaseRunData;
Opm::filesystem::path rootName = inputFileName.parent_path() / inputFileName.stem();
// if root name (without any extension) given as first argument in constructor, binary will then be assumed
// if only root name (without any extension) given as first argument in constructor
// binary will then be assumed
if (inputFileName.extension()=="")
inputFileName+=".SMSPEC";
@@ -101,6 +105,16 @@ 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);
@@ -180,7 +194,6 @@ ESmry::ESmry(const std::string &filename, bool loadBaseRunData) :
// checking if this is a restart run. Supporting nested restarts (restart, from restart, ...)
// std::set keywList is storing keywords from all runs involved
while ((rstRootN.string() != "") && (loadBaseRunData)) {
Opm::filesystem::path rstFile = pathRstFile / rstRootN;
@@ -303,132 +316,284 @@ ESmry::ESmry(const std::string &filename, bool loadBaseRunData) :
vectorLoaded.push_back(false);
}
int dataFileIndex = -1;
if (lodEnabeled)
{
// inspecting formatted or binary lod file. lodsmry possible only if
// loadBaseRunData=false
while (specInd >= 0){
inspect_lodsmry();
int reportStepNumber = fromReportStepNumber;
} else {
if (specInd > 0) {
auto rstFrom = smryArray[specInd-1];
toReportStepNumber = std::get<1>(rstFrom);
} else {
toReportStepNumber = std::numeric_limits<int>::max();
}
// 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.
Opm::filesystem::path smspecFile(std::get<0>(smryArray[specInd]));
rootName = smspecFile.parent_path() / smspecFile.stem();
int dataFileIndex = -1;
// 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
while (specInd >= 0) {
Opm::filesystem::path unsmryFile = rootName;
int reportStepNumber = fromReportStepNumber;
unsmryFile += formattedFiles[specInd] ? ".FUNSMRY" : ".UNSMRY";
const bool use_unified = Opm::filesystem::exists(unsmryFile.string());
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;
if (specInd > 0) {
auto rstFrom = smryArray[specInd-1];
toReportStepNumber = std::get<1>(rstFrom);
} else {
toReportStepNumber = std::numeric_limits<int>::max();
}
Opm::filesystem::path smspecFile(std::get<0>(smryArray[specInd]));
rootName = smspecFile.parent_path() / smspecFile.stem();
// 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
Opm::filesystem::path unsmryFile = rootName;
unsmryFile += formattedFiles[specInd] ? ".FUNSMRY" : ".UNSMRY";
const bool use_unified = Opm::filesystem::exists(unsmryFile.string());
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 {
resultsFileList=multFileList;
}
} else if (use_unified){
resultsFileList.push_back(unsmryFile.string());
} else {
resultsFileList=multFileList;
}
std::vector<ArrSourceEntry> arraySourceList;
// make array list with reference to source files (unifed or non unified)
std::vector<ArrSourceEntry> arraySourceList;
for (std::string fileName : resultsFileList)
{
std::vector<std::tuple <std::string, 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())
for (std::string fileName : resultsFileList)
{
dataFileList.push_back(std::get<1>(arraySourceList[i]));
dataFileIndex++;
std::vector<std::tuple <std::string, 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);
}
}
TimeStepEntry t1 = std::make_tuple(specInd, dataFileIndex, std::get<3>(arraySourceList[i]));
timeStepList.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
i++;
if (i < arraySourceList.size()){
if (std::get<0>(arraySourceList[i]) == "SEQHDR") {
i++;
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())
{
dataFileList.push_back(std::get<1>(arraySourceList[i]));
dataFileIndex++;
}
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 {
reportStepNumber++;
seqIndex.push_back(step);
}
} else {
reportStepNumber++;
seqIndex.push_back(step);
if (reportStepNumber >= toReportStepNumber) {
i = arraySourceList.size();
}
step++;
}
if (reportStepNumber >= toReportStepNumber) {
i = arraySourceList.size();
}
fromReportStepNumber = toReportStepNumber;
step++;
specInd--;
nTstep = timeStepList.size();
}
fromReportStepNumber = toReportStepNumber;
specInd--;
}
}
void ESmry::inspect_lodsmry()
{
std::string arrName;
int64_t arr_size;
Opm::EclIO::eclArrType arrType;
std::fstream fileH;
if (formattedFiles[0]) {
fileH.open(lodFileName, std::ios::in);
Opm::EclIO::readFormattedHeader(fileH, arrName, arr_size, arrType);
} else {
fileH.open(lodFileName, std::ios::in | std::ios::binary);
Opm::EclIO::readBinaryHeader(fileH, arrName, arr_size, arrType);
}
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) + 1;
std::string fileStr = read_string_from_disk(fileH, size);
keycheck = Opm::EclIO::readFormattedCharArray(fileStr, arr_size, 0);
} 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 maching keyword array");
}
} else {
if (keyword[n] != test_str) {
OPM_THROW(std::invalid_argument, "keycheck not maching keyword array");
}
}
}
if (formattedFiles[0])
Opm::EclIO::readFormattedHeader(fileH, arrName, arr_size, arrType);
else
Opm::EclIO::readBinaryHeader(fileH, arrName, arr_size, arrType);
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) + 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);
else
lod_arr_size = sizeOnDiskBinary(nTstep, Opm::EclIO::REAL);
fileH.close();
}
std::string ESmry::read_string_from_disk(std::fstream& fileH, uint64_t size) const
{
char* buffer;
buffer = new char [size];
fileH.read (buffer, size);
std::string fileStr = std::string(buffer, size);
delete[] buffer;
return fileStr;
}
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;
int64_t size;
Opm::EclIO::eclArrType arrType;
uint64_t pos = lod_offset + lod_arr_size*static_cast<uint64_t>(ind);
if (formattedFiles[0])
pos = pos + static_cast<uint64_t>(ind * 31); // adding size of formatted headers
else
pos = pos + static_cast<uint64_t>(ind * 24); // adding size of binary headers
fileH.seekg (pos, fileH.beg);
if (formattedFiles[0])
readFormattedHeader(fileH, arrName, size, arrType);
else
readBinaryHeader(fileH, arrName, size, arrType);
arrName = Opm::EclIO::trimr(arrName);
std::string checkName = "V" + std::to_string(ind);
if (arrName != checkName)
OPM_THROW(std::invalid_argument, "lodsmry, wrong header expecting " + checkName + " found " + arrName);
if (formattedFiles[0]) {
uint64_t size_buffer = lod_arr_size + 1;
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
{
size_t nvect = vectList.size();
size_t ntstep = timeStepList.size();
std::vector<int> keywIndVect;
keywIndVect.reserve(nvect);
@@ -442,89 +607,103 @@ void ESmry::LoadData(const std::vector<std::string>& vectList) const
}
for (auto ind : keywIndVect)
vectorData[ind].reserve(ntstep);
vectorData[ind].reserve(nTstep);
std::fstream fileH;
if (lodEnabeled)
{
Load_from_lodsmry(keywIndVect);
auto specInd = std::get<0>(timeStepList[0]);
auto dataFileIndex = std::get<1>(timeStepList[0]);
uint64_t stepFilePos = std::get<2>(timeStepList[0]);
} else {
if (formattedFiles[specInd])
fileH.open(dataFileList[dataFileIndex], std::ios::in);
else
fileH.open(dataFileList[dataFileIndex], std::ios::in | std::ios::binary);
std::fstream fileH;
for (auto ministep : timeStepList) {
if (dataFileIndex != std::get<1>(ministep)) {
fileH.close();
specInd = std::get<0>(ministep);
dataFileIndex = std::get<1>(ministep);
auto specInd = std::get<0>(timeStepList[0]);
auto dataFileIndex = std::get<1>(timeStepList[0]);
uint64_t stepFilePos = std::get<2>(timeStepList[0]);
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);
{
int nLinesBlock = MaxBlockSizeReal / numColumnsReal;
int rest = MaxBlockSizeReal % numColumnsReal;
if (rest > 0)
nLinesBlock++;
blockSize_f= static_cast<uint64_t>(MaxNumBlockReal * numColumnsReal * columnWidthReal + nLinesBlock);
}
stepFilePos = std::get<2>(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);
for (auto ministep : timeStepList) {
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(nanf(""));
} else {
int paramPos = it->second;
if (dataFileIndex != std::get<1>(ministep)) {
fileH.close();
specInd = std::get<0>(ministep);
dataFileIndex = std::get<1>(ministep);
if (formattedFiles[specInd]) {
uint64_t elementPos = 0;
int nBlocks = paramPos /MaxBlockSizeReal;
int sizeOfLastBlock = paramPos % MaxBlockSizeReal;
if (formattedFiles[specInd])
fileH.open(dataFileList[dataFileIndex], std::ios::in );
else
fileH.open(dataFileList[dataFileIndex], std::ios::in | std::ios::binary);
}
if (nBlocks > 0) {
int nLinesBlock = MaxNumBlockReal / numColumnsReal;
int rest = MaxNumBlockReal % numColumnsReal;
stepFilePos = std::get<2>(ministep);;
if (rest > 0)
nLinesBlock++;
for (auto ind : keywIndVect) {
uint64_t blockSize = static_cast<uint64_t>(MaxNumBlockReal * numColumnsReal + nLinesBlock);
elementPos = static_cast<uint64_t>(nBlocks * blockSize);
}
int nLines = sizeOfLastBlock / numColumnsReal;
elementPos = stepFilePos + elementPos + static_cast<uint64_t>(sizeOfLastBlock * columnWidthReal + nLines);
fileH.seekg (elementPos, fileH.beg);
char* buffer;
size_t size = columnWidthReal;
buffer = new char [size];
fileH.read (buffer, size);
double dtmpv = std::stod(std::string(buffer, size));
vectorData[ind].push_back(static_cast<float>(dtmpv));
delete[] buffer;
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(nanf(""));
} else {
int paramPos = it->second;
uint64_t nFullBlocks = static_cast<uint64_t>(paramPos/(MaxBlockSizeReal / sizeOfReal));
uint64_t elementPos = ((2 * nFullBlocks) + 1)*static_cast<uint64_t>(sizeOfInte);
elementPos += static_cast<uint64_t>(paramPos)* static_cast<uint64_t>(sizeOfReal) + stepFilePos;
fileH.seekg (elementPos, fileH.beg);
if (formattedFiles[specInd]) {
uint64_t elementPos = 0;
int nBlocks = paramPos / MaxBlockSizeReal;
int sizeOfLastBlock = paramPos % MaxBlockSizeReal;
float value;
fileH.read(reinterpret_cast<char*>(&value), sizeOfReal);
vectorData[ind].push_back(Opm::EclIO::flipEndianFloat(value));
if (nBlocks > 0)
elementPos = static_cast<uint64_t>(nBlocks * blockSize_f);
int nLines = sizeOfLastBlock / numColumnsReal;
elementPos = stepFilePos + elementPos + static_cast<uint64_t>(sizeOfLastBlock * columnWidthReal + nLines);
fileH.seekg (elementPos, fileH.beg);
char* buffer;
size_t size = columnWidthReal;
buffer = new char [size];
fileH.read (buffer, size);
double dtmpv = std::stod(std::string(buffer, size));
vectorData[ind].push_back(static_cast<float>(dtmpv));
delete[] buffer;
} else {
uint64_t nFullBlocks = static_cast<uint64_t>(paramPos/(MaxBlockSizeReal / sizeOfReal));
uint64_t elementPos = ((2 * nFullBlocks) + 1)*static_cast<uint64_t>(sizeOfInte);
elementPos += static_cast<uint64_t>(paramPos)* static_cast<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));
}
}
}
}
}
fileH.close();
fileH.close();
}
for (auto ind : keywIndVect)
vectorLoaded[ind] = true;
@@ -553,108 +732,116 @@ std::vector<int> ESmry::makeKeywPosVector(int specInd) const {
void ESmry::LoadData() const
{
std::fstream fileH;
if (lodEnabeled) {
auto specInd = std::get<0>(timeStepList[0]);
auto dataFileIndex = std::get<1>(timeStepList[0]);
uint64_t stepFilePos = std::get<2>(timeStepList[0]);
this ->LoadData(keyword);
std::vector<int> keywpos = makeKeywPosVector(specInd);
} else {
std::fstream fileH;
if (formattedFiles[specInd])
fileH.open(dataFileList[dataFileIndex], std::ios::in);
else
fileH.open(dataFileList[dataFileIndex], std::ios::in | std::ios::binary);
auto specInd = std::get<0>(timeStepList[0]);
auto dataFileIndex = std::get<1>(timeStepList[0]);
uint64_t stepFilePos = std::get<2>(timeStepList[0]);
for (auto ministep : timeStepList) {
std::vector<int> keywpos = makeKeywPosVector(specInd);
if (dataFileIndex != std::get<1>(ministep)) {
fileH.close();
if (formattedFiles[specInd])
fileH.open(dataFileList[dataFileIndex], std::ios::in);
else
fileH.open(dataFileList[dataFileIndex], std::ios::in | std::ios::binary);
if (specInd != std::get<0>(ministep)){
specInd = std::get<0>(ministep);
keywpos = makeKeywPosVector(specInd);
}
for (auto ministep : timeStepList) {
dataFileIndex = std::get<1>(ministep);
if (dataFileIndex != std::get<1>(ministep)) {
fileH.close();
if (formattedFiles[specInd])
fileH.open(dataFileList[dataFileIndex], std::ios::in );
else
fileH.open(dataFileList[dataFileIndex], std::ios::in | std::ios::binary);
}
stepFilePos = std::get<2>(ministep);
int maxNumberOfElements = MaxBlockSizeReal / sizeOfReal;
fileH.seekg (stepFilePos, fileH.beg);
if (formattedFiles[specInd]) {
char* buffer;
size_t size = sizeOnDiskFormatted(nParamsSpecFile[specInd], Opm::EclIO::REAL)+1;
buffer = new char [size];
fileH.read (buffer, size);
std::string fileStr = std::string(buffer, size);
size_t p = 0;
int64_t p1= 0;
for (int i=0; i< nParamsSpecFile[specInd]; i++) {
p1 = fileStr.find_first_not_of(' ',p1);
int64_t p2 = fileStr.find_first_of(' ', p1);
if (keywpos[p] > -1) {
double dtmpv = std::stod(fileStr.substr(p1, p2-p1));
vectorData[keywpos[p]].push_back(static_cast<float>(dtmpv));
if (specInd != std::get<0>(ministep)) {
specInd = std::get<0>(ministep);
keywpos = makeKeywPosVector(specInd);
}
p1 = fileStr.find_first_not_of(' ',p2);
p++;
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);
}
delete[] buffer;
} else {
int64_t rest = static_cast<int64_t>(nParamsSpecFile[specInd]);
size_t p = 0;
stepFilePos = std::get<2>(ministep);
int maxNumberOfElements = MaxBlockSizeReal / sizeOfReal;
fileH.seekg (stepFilePos, fileH.beg);
while (rest > 0) {
int dhead;
fileH.read(reinterpret_cast<char*>(&dhead), sizeof(dhead));
dhead = Opm::EclIO::flipEndianInt(dhead);
int num = dhead / sizeOfInte;
if (formattedFiles[specInd]) {
if ((num > maxNumberOfElements) || (num < 0))
OPM_THROW(std::runtime_error, "??Error reading binary data, inconsistent header data or incorrect number of elements");
char* buffer;
size_t size = sizeOnDiskFormatted(nParamsSpecFile[specInd], Opm::EclIO::REAL)+1;
buffer = new char [size];
fileH.read (buffer, size);
for (int i = 0; i < num; i++) {
float value;
fileH.read(reinterpret_cast<char*>(&value), sizeOfReal);
std::string fileStr = std::string(buffer, size);
size_t p = 0;
int64_t p1= 0;
if (keywpos[p] > -1)
vectorData[keywpos[p]].push_back(Opm::EclIO::flipEndianFloat(value));
for (int i=0; i< nParamsSpecFile[specInd]; i++) {
p1 = fileStr.find_first_not_of(' ',p1);
int64_t p2 = fileStr.find_first_of(' ', p1);
if ((keywpos[p] > -1) && (!vectorLoaded[keywpos[p]])) {
double dtmpv = std::stod(fileStr.substr(p1, p2-p1));
vectorData[keywpos[p]].push_back(static_cast<float>(dtmpv));
}
p1 = fileStr.find_first_not_of(' ',p2);
p++;
}
rest -= num;
delete[] buffer;
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);
} else {
int64_t rest = static_cast<int64_t>(nParamsSpecFile[specInd]);
size_t p = 0;
while (rest > 0) {
int dhead;
fileH.read(reinterpret_cast<char*>(&dhead), sizeof(dhead));
dhead = Opm::EclIO::flipEndianInt(dhead);
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++) {
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));
p++;
}
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.");
}
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.");
}
}
}
for (size_t n=0; n < nVect; n++)
vectorLoaded[n] = true;
for (size_t n=0; n < nVect; n++)
vectorLoaded[n] = true;
}
}
@@ -662,24 +849,79 @@ std::vector<std::tuple <std::string, uint64_t>>
ESmry::getListOfArrays(std::string filename, bool formatted)
{
std::vector<std::tuple <std::string, uint64_t>> resultVect;
std::fstream fileH;
FILE *ptr;
char* arrName = new char[9];
char* numstr = new char[12];
int64_t num;
if (formatted)
fileH.open(filename, std::ios::in);
ptr = fopen(filename.c_str(),"r"); // r for read, files opened as text files
else
fileH.open(filename, std::ios::in | std::ios::binary);
ptr = fopen(filename.c_str(),"rb"); // r for read, b for binary
while (!Opm::EclIO::isEOF(&fileH)) {
std::string arrName(8,' ');
bool endOfFile = false;
while (!endOfFile)
{
Opm::EclIO::eclArrType arrType;
int64_t num;
if (formatted)
Opm::EclIO::readFormattedHeader(fileH,arrName,num,arrType);
else
Opm::EclIO::readBinaryHeader(fileH,arrName,num,arrType);
{
fseek(ptr, 2, SEEK_CUR);
uint64_t filePos = fileH.tellg();
if (fread(arrName, 8, 1, ptr) != 1 )
throw std::runtime_error("fread error when loading summary data");
arrName[8]='\0';
fseek(ptr, 1, SEEK_CUR);
if (fread(numstr, 12, 1, ptr) != 1)
throw std::runtime_error("fread error when loading summary data");
numstr[12]='\0';
int num_int = std::stoi(numstr);
num = static_cast<int64_t>(num_int);
fseek(ptr, 8, SEEK_CUR);
if ((strcmp(arrName, "SEQHDR ") == 0) || (strcmp(arrName, "MINISTEP") == 0))
arrType = Opm::EclIO::INTE;
else if (strcmp(arrName, "PARAMS ") == 0)
arrType = Opm::EclIO::REAL;
else {
throw std::invalid_argument("unknown array in summary data file ");
}
} else {
int num_int;
fseek(ptr, 4, SEEK_CUR);
if (fread(arrName, 8, 1, ptr) != 1)
throw std::runtime_error("fread error when loading summary data");
arrName[8]='\0';
if (fread(&num_int, 4, 1, ptr) != 1)
throw std::runtime_error("fread error when loading summary data");
num = static_cast<int64_t>(Opm::EclIO::flipEndianInt(num_int));
fseek(ptr, 8, SEEK_CUR);
if ((strcmp(arrName, "SEQHDR ") == 0) || (strcmp(arrName, "MINISTEP") == 0))
arrType = Opm::EclIO::INTE;
else if (strcmp(arrName, "PARAMS ") == 0)
arrType = Opm::EclIO::REAL;
else {
arrName[8]='\0';
throw std::invalid_argument("unknown array in UNSMRY file ");
}
}
uint64_t filePos = static_cast<uint64_t>(ftell(ptr));
std::tuple <std::string, uint64_t> t1;
t1 = std::make_tuple(Opm::EclIO::trimr(arrName), filePos);
@@ -688,20 +930,109 @@ ESmry::getListOfArrays(std::string filename, bool formatted)
if (num > 0) {
if (formatted) {
uint64_t sizeOfNextArray = sizeOnDiskFormatted(num, arrType);
fileH.seekg(static_cast<std::streamoff>(sizeOfNextArray), std::ios_base::cur);
fseek(ptr, static_cast<long int>(sizeOfNextArray), SEEK_CUR);
} else {
uint64_t sizeOfNextArray = sizeOnDiskBinary(num, arrType);
fileH.seekg(static_cast<std::streamoff>(sizeOfNextArray), std::ios_base::cur);
fseek(ptr, static_cast<long int>(sizeOfNextArray), SEEK_CUR);
}
}
if (fgetc(ptr) == EOF)
endOfFile = true;
else
fseek(ptr, -1, SEEK_CUR);
}
fileH.close();
delete[] arrName;
delete[] numstr;
fclose(ptr);
return resultVect;
}
bool ESmry::make_lodsmry_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::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";
if (Opm::EclIO::fileExists(smryDataFile))
{
return false;
} else {
std::vector<std::string> 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<bool> 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);
else
is_rstep.push_back(false);
this->LoadData();
{
Opm::EclIO::EclOutput outFile(smryDataFile, formattedFiles[0], std::ios::out);
outFile.write<std::string>("KEYCHECK", keycheck);
outFile.write<bool>("RSTEP", is_rstep);
for (size_t n = 0; n < vectorData.size(); n++ ) {
std::string vect_name="V" + std::to_string(n);
outFile.write<float>(vect_name, vectorData[n]);
}
}
return true;
}
}
std::vector<std::string> ESmry::checkForMultipleResultFiles(const Opm::filesystem::path& rootN, bool formatted) const {

View File

@@ -34,247 +34,6 @@
#include <iostream>
// anonymous namespace for EclFile
namespace {
bool fileExists(const std::string& filename){
std::ifstream fileH(filename.c_str());
return fileH.good();
}
bool isFormatted(const std::string& filename)
{
const auto p = filename.find_last_of(".");
if (p == std::string::npos)
OPM_THROW(std::invalid_argument,
"Purported ECLIPSE Filename'" + filename + "'does not contain extension");
return std::strchr("ABCFGH", static_cast<int>(filename[p+1])) != nullptr;
}
template<typename T, typename T2>
std::vector<T> readBinaryArray(std::fstream& fileH, const int64_t size, Opm::EclIO::eclArrType type,
std::function<T(T2)>& flip)
{
std::vector<T> arr;
auto sizeData = block_size_data_binary(type);
int sizeOfElement = std::get<0>(sizeData);
int maxBlockSize = std::get<1>(sizeData);
int maxNumberOfElements = maxBlockSize / sizeOfElement;
arr.reserve(size);
int64_t rest = size;
while (rest > 0) {
int dhead;
fileH.read(reinterpret_cast<char*>(&dhead), sizeof(dhead));
dhead = Opm::EclIO::flipEndianInt(dhead);
int num = dhead / sizeOfElement;
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++) {
T2 value;
fileH.read(reinterpret_cast<char*>(&value), sizeOfElement);
arr.push_back(flip(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.");
}
}
return arr;
}
std::vector<int> readBinaryInteArray(std::fstream &fileH, const int64_t size)
{
std::function<int(int)> f = Opm::EclIO::flipEndianInt;
return readBinaryArray<int,int>(fileH, size, Opm::EclIO::INTE, f);
}
std::vector<float> readBinaryRealArray(std::fstream& fileH, const int64_t size)
{
std::function<float(float)> f = Opm::EclIO::flipEndianFloat;
return readBinaryArray<float,float>(fileH, size, Opm::EclIO::REAL, f);
}
std::vector<double> readBinaryDoubArray(std::fstream& fileH, const int64_t size)
{
std::function<double(double)> f = Opm::EclIO::flipEndianDouble;
return readBinaryArray<double,double>(fileH, size, Opm::EclIO::DOUB, f);
}
std::vector<bool> readBinaryLogiArray(std::fstream &fileH, const int64_t size)
{
std::function<bool(unsigned int)> f = [](unsigned int intVal)
{
bool value;
if (intVal == Opm::EclIO::true_value) {
value = true;
} else if (intVal == Opm::EclIO::false_value) {
value = false;
} else {
OPM_THROW(std::runtime_error, "Error reading logi value");
}
return value;
};
return readBinaryArray<bool,unsigned int>(fileH, size, Opm::EclIO::LOGI, f);
}
std::vector<std::string> readBinaryCharArray(std::fstream& fileH, const int64_t size)
{
using Char8 = std::array<char, 8>;
std::function<std::string(Char8)> f = [](const Char8& val)
{
std::string res(val.begin(), val.end());
return Opm::EclIO::trimr(res);
};
return readBinaryArray<std::string,Char8>(fileH, size, Opm::EclIO::CHAR, f);
}
template<typename T>
std::vector<T> readFormattedArray(const std::string& file_str, const int size, int64_t fromPos,
std::function<T(const std::string&)>& process)
{
std::vector<T> arr;
arr.reserve(size);
int64_t p1=fromPos;
for (int i=0; i< size; i++) {
p1 = file_str.find_first_not_of(' ',p1);
int64_t p2 = file_str.find_first_of(' ', p1);
arr.push_back(process(file_str.substr(p1, p2-p1)));
p1 = file_str.find_first_not_of(' ',p2);
}
return arr;
}
std::vector<int> readFormattedInteArray(const std::string& file_str, const int64_t size, int64_t fromPos)
{
std::function<int(const std::string&)> f = [](const std::string& val)
{
return std::stoi(val);
};
return readFormattedArray(file_str, size, fromPos, f);
}
std::vector<std::string> readFormattedCharArray(const std::string& file_str, const int64_t size, int64_t fromPos)
{
std::vector<std::string> arr;
arr.reserve(size);
int64_t p1=fromPos;
for (int i=0; i< size; i++) {
p1 = file_str.find_first_of('\'',p1);
std::string value = file_str.substr(p1 + 1, 8);
if (value == " ") {
arr.push_back("");
} else {
arr.push_back(Opm::EclIO::trimr(value));
}
p1 = p1+10;
}
return arr;
}
std::vector<float> readFormattedRealArray(const std::string& file_str, const int64_t size, int64_t fromPos)
{
std::function<float(const std::string&)> f = [](const std::string& val)
{
// tskille: temporary fix, need to be discussed. OPM flow writes numbers
// that are outside valid range for float, and function stof will fail
double dtmpv = std::stod(val);
return dtmpv;
};
return readFormattedArray<float>(file_str, size, fromPos, f);
}
std::vector<bool> readFormattedLogiArray(const std::string& file_str, const int64_t size, int64_t fromPos)
{
std::function<bool(const std::string&)> f = [](const std::string& val)
{
if (val[0] == 'T') {
return true;
} else if (val[0] == 'F') {
return false;
} else {
std::string message="Could not convert '" + val + "' to a bool value ";
OPM_THROW(std::invalid_argument, message);
}
};
return readFormattedArray<bool>(file_str, size, fromPos, f);
}
std::vector<double> readFormattedDoubArray(const std::string& file_str, const int64_t size, int64_t fromPos)
{
std::function<double(const std::string&)> f = [](std::string val)
{
auto p1 = val.find_first_of("D");
if (p1 == std::string::npos) {
auto p2 = val.find_first_of("-+", 1);
if (p2 != std::string::npos) {
val = val.insert(p2,"E");
}
} else {
val.replace(p1,1,"E");
}
return std::stod(val);
};
return readFormattedArray<double>(file_str, size, fromPos, f);
}
} // anonymous namespace
// ==========================================================================
namespace Opm { namespace EclIO {
@@ -305,7 +64,7 @@ EclFile::EclFile(const std::string& filename, bool preload) : inputFilename(file
std::string arrName(8,' ');
eclArrType arrType;
int64_t num;
if (formatted) {
readFormattedHeader(fileH,arrName,num,arrType);
} else {
@@ -323,7 +82,7 @@ EclFile::EclFile(const std::string& filename, bool preload) : inputFilename(file
arrayLoaded.push_back(false);
if (num > 0){
if (num > 0){
if (formatted) {
uint64_t sizeOfNextArray = sizeOnDiskFormatted(num, arrType);
fileH.seekg(static_cast<std::streamoff>(sizeOfNextArray), std::ios_base::cur);

View File

@@ -24,6 +24,7 @@
#include <stdexcept>
#include <cmath>
#include <fstream>
#include <cstring>
int Opm::EclIO::flipEndianInt(int num)
@@ -59,6 +60,21 @@ double Opm::EclIO::flipEndianDouble(double num)
return value;
}
bool Opm::EclIO::fileExists(const std::string& filename){
std::ifstream fileH(filename.c_str());
return fileH.good();
}
bool Opm::EclIO::isFormatted(const std::string& filename)
{
const auto p = filename.find_last_of(".");
if (p == std::string::npos)
OPM_THROW(std::invalid_argument,
"Purported ECLIPSE Filename'" + filename + "'does not contain extension");
return std::strchr("ABCFGH", static_cast<int>(filename[p+1])) != nullptr;
}
bool Opm::EclIO::isEOF(std::fstream* fileH)
{
int num;
@@ -338,3 +354,222 @@ void Opm::EclIO::readFormattedHeader(std::fstream& fileH, std::string& arrName,
OPM_THROW(std::runtime_error, "Header name should be 8 characters");
}
}
template<typename T, typename T2>
std::vector<T> Opm::EclIO::readBinaryArray(std::fstream& fileH, const int64_t size, Opm::EclIO::eclArrType type,
std::function<T(T2)>& flip)
{
std::vector<T> arr;
auto sizeData = block_size_data_binary(type);
int sizeOfElement = std::get<0>(sizeData);
int maxBlockSize = std::get<1>(sizeData);
int maxNumberOfElements = maxBlockSize / sizeOfElement;
arr.reserve(size);
int64_t rest = size;
while (rest > 0) {
int dhead;
fileH.read(reinterpret_cast<char*>(&dhead), sizeof(dhead));
dhead = Opm::EclIO::flipEndianInt(dhead);
int num = dhead / sizeOfElement;
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++) {
T2 value;
fileH.read(reinterpret_cast<char*>(&value), sizeOfElement);
arr.push_back(flip(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.");
}
}
return arr;
}
std::vector<int> Opm::EclIO::readBinaryInteArray(std::fstream &fileH, const int64_t size)
{
std::function<int(int)> f = Opm::EclIO::flipEndianInt;
return readBinaryArray<int,int>(fileH, size, Opm::EclIO::INTE, f);
}
std::vector<float> Opm::EclIO::readBinaryRealArray(std::fstream& fileH, const int64_t size)
{
std::function<float(float)> f = Opm::EclIO::flipEndianFloat;
return readBinaryArray<float,float>(fileH, size, Opm::EclIO::REAL, f);
}
std::vector<double> Opm::EclIO::readBinaryDoubArray(std::fstream& fileH, const int64_t size)
{
std::function<double(double)> f = Opm::EclIO::flipEndianDouble;
return readBinaryArray<double,double>(fileH, size, Opm::EclIO::DOUB, f);
}
std::vector<bool> Opm::EclIO::readBinaryLogiArray(std::fstream &fileH, const int64_t size)
{
std::function<bool(unsigned int)> f = [](unsigned int intVal)
{
bool value;
if (intVal == Opm::EclIO::true_value) {
value = true;
} else if (intVal == Opm::EclIO::false_value) {
value = false;
} else {
OPM_THROW(std::runtime_error, "Error reading logi value");
}
return value;
};
return readBinaryArray<bool,unsigned int>(fileH, size, Opm::EclIO::LOGI, f);
}
std::vector<std::string> Opm::EclIO::readBinaryCharArray(std::fstream& fileH, const int64_t size)
{
using Char8 = std::array<char, 8>;
std::function<std::string(Char8)> f = [](const Char8& val)
{
std::string res(val.begin(), val.end());
return Opm::EclIO::trimr(res);
};
return readBinaryArray<std::string,Char8>(fileH, size, Opm::EclIO::CHAR, f);
}
template<typename T>
std::vector<T> Opm::EclIO::readFormattedArray(const std::string& file_str, const int size, int64_t fromPos,
std::function<T(const std::string&)>& process)
{
std::vector<T> arr;
arr.reserve(size);
int64_t p1=fromPos;
for (int i=0; i< size; i++) {
p1 = file_str.find_first_not_of(' ',p1);
int64_t p2 = file_str.find_first_of(' ', p1);
arr.push_back(process(file_str.substr(p1, p2-p1)));
p1 = file_str.find_first_not_of(' ',p2);
}
return arr;
}
std::vector<int> Opm::EclIO::readFormattedInteArray(const std::string& file_str, const int64_t size, int64_t fromPos)
{
std::function<int(const std::string&)> f = [](const std::string& val)
{
return std::stoi(val);
};
return readFormattedArray(file_str, size, fromPos, f);
}
std::vector<std::string> Opm::EclIO::readFormattedCharArray(const std::string& file_str, const int64_t size, int64_t fromPos)
{
std::vector<std::string> arr;
arr.reserve(size);
int64_t p1=fromPos;
for (int i=0; i< size; i++) {
p1 = file_str.find_first_of('\'',p1);
std::string value = file_str.substr(p1 + 1, 8);
if (value == " ") {
arr.push_back("");
} else {
arr.push_back(Opm::EclIO::trimr(value));
}
p1 = p1+10;
}
return arr;
}
std::vector<float> Opm::EclIO::readFormattedRealArray(const std::string& file_str, const int64_t size, int64_t fromPos)
{
std::function<float(const std::string&)> f = [](const std::string& val)
{
// tskille: temporary fix, need to be discussed. OPM flow writes numbers
// that are outside valid range for float, and function stof will fail
double dtmpv = std::stod(val);
return dtmpv;
};
return readFormattedArray<float>(file_str, size, fromPos, f);
}
std::vector<bool> Opm::EclIO::readFormattedLogiArray(const std::string& file_str, const int64_t size, int64_t fromPos)
{
std::function<bool(const std::string&)> f = [](const std::string& val)
{
if (val[0] == 'T') {
return true;
} else if (val[0] == 'F') {
return false;
} else {
std::string message="Could not convert '" + val + "' to a bool value ";
OPM_THROW(std::invalid_argument, message);
}
};
return readFormattedArray<bool>(file_str, size, fromPos, f);
}
std::vector<double> Opm::EclIO::readFormattedDoubArray(const std::string& file_str, const int64_t size, int64_t fromPos)
{
std::function<double(const std::string&)> f = [](std::string val)
{
auto p1 = val.find_first_of("D");
if (p1 == std::string::npos) {
auto p2 = val.find_first_of("-+", 1);
if (p2 != std::string::npos) {
val = val.insert(p2,"E");
}
} else {
val.replace(p1,1,"E");
}
return std::stod(val);
};
return readFormattedArray<double>(file_str, size, fromPos, f);
}

View File

@@ -175,18 +175,18 @@ int main(int argc, char **argv) {
return 0;
}
std::map<std::string, std::string> to_formatted = {{".EGRID", ".FEGRID"}, {".INIT", ".FINIT"}, {".SMSPEC", ".FSMSPEC"},
{".UNSMRY", ".FUNSMRY"}, {".UNRST", ".FUNRST"}, {".RFT", ".FRFT"}};
std::map<std::string, std::string> to_formatted = {{".EGRID", ".FEGRID"}, {".INIT", ".FINIT"}, {".SMSPEC", ".FSMSPEC"},
{".UNSMRY", ".FUNSMRY"}, {".UNRST", ".FUNRST"}, {".RFT", ".FRFT"}, {".LODSMRY", ".FLODSMRY"}};
std::map<std::string, std::string> to_binary = {{".FEGRID", ".EGRID"}, {".FINIT", ".INIT"}, {".FSMSPEC", ".SMSPEC"},
{".FUNSMRY", ".UNSMRY"}, {".FUNRST", ".UNRST"}, {".FRFT", ".RFT"}, {".FLODSMRY", ".LODSMRY"}};
std::map<std::string, std::string> to_binary = {{".FEGRID", ".EGRID"}, {".FINIT", ".INIT"}, {".FSMSPEC", ".SMSPEC"},
{".FUNSMRY", ".UNSMRY"}, {".FUNRST", ".UNRST"}, {".FRFT", ".RFT"}};
if (formattedOutput) {
auto search = to_formatted.find(extension);
if (search != to_formatted.end()){
resFile = rootN + search->second;
resFile = rootN + search->second;
} else if (extension.substr(1,1)=="X"){
resFile = rootN + ".F" + extension.substr(2);
} else if (extension.substr(1,1)=="S"){
@@ -196,11 +196,11 @@ int main(int argc, char **argv) {
exit(1);
}
} else {
auto search = to_binary.find(extension);
if (search != to_binary.end()){
resFile = rootN + search->second;
resFile = rootN + search->second;
} else if (extension.substr(1,1)=="F"){
resFile = rootN + ".X" + extension.substr(2);
} else if (extension.substr(1,1)=="A"){