Files
ResInsight/ThirdParty/Ert/lib/ecl/ecl_unsmry_loader.cpp
T
Magne Sjaastad 157219e63d #5015 libecl : Make sure *.UNSMRY is closed properly after data is read
Earlier attempts to fix this caused major performance issues. Now closing the file stream when reading of vector data is completed, seems to work as expected.
2019-11-08 11:12:06 +01:00

178 lines
5.3 KiB
C++

#include <cmath>
#include <string>
#include <iostream>
#include <ert/util/int_vector.hpp>
#include <ert/ecl/ecl_kw_magic.hpp>
#include <ert/ecl/ecl_file.hpp>
#include "detail/ecl/ecl_unsmry_loader.hpp"
namespace ecl {
unsmry_loader::unsmry_loader(const ecl_smspec_type * smspec, const std::string& filename, int file_options) :
size(ecl_smspec_get_params_size(smspec)),
time_index(ecl_smspec_get_time_index(smspec)),
time_seconds(ecl_smspec_get_time_seconds(smspec)),
sim_start(ecl_smspec_get_start_time(smspec))
{
ecl_file_type * file = ecl_file_open(filename.c_str(), file_options);
if (!file)
throw std::bad_alloc();
if (!ecl_file_has_kw(file, PARAMS_KW)) {
ecl_file_close(file);
throw std::bad_alloc();
}
if (ecl_file_get_num_named_kw(file, PARAMS_KW) != ecl_file_get_num_named_kw(file, MINISTEP_KW)) {
ecl_file_close(file);
throw std::bad_alloc();
}
this->date_index = {{ ecl_smspec_get_date_day_index(smspec),
ecl_smspec_get_date_month_index(smspec),
ecl_smspec_get_date_year_index(smspec) }};
this->file = file;
this->file_view = ecl_file_get_global_view( this->file );
this->m_length = ecl_file_view_get_num_named_kw(this->file_view, PARAMS_KW);
}
unsmry_loader::~unsmry_loader() {
ecl_file_close(file);
}
int unsmry_loader::length() const {
return this->m_length;
}
std::vector<double> unsmry_loader::get_vector(int pos) const {
if (pos >= size)
throw std::out_of_range("unsmry_loader::get_vector pos: " + std::to_string(pos) + " PARAMS_SIZE: " + std::to_string(size));
std::vector<double> data(this->length());
int_vector_type * index_map = int_vector_alloc( 1 , pos);
char buffer[4];
for (int index = 0; index < this->length(); index++) {
ecl_file_view_index_fload_kw(file_view, PARAMS_KW, index, index_map, buffer);
float * data_value = (float*) buffer;
data[index] = *data_value;
}
int_vector_free( index_map );
if (ecl_file_view_flags_set(file_view, ECL_FILE_CLOSE_STREAM))
ecl_file_view_fclose_stream(file_view);
return data;
}
// This is horribly inefficient
double unsmry_loader::iget(int time_index, int params_index) const {
int_vector_type * index_map = int_vector_alloc( 1 , params_index);
float value;
ecl_file_view_index_fload_kw(this->file_view, PARAMS_KW, time_index, index_map, (char *) &value);
int_vector_free(index_map);
return value;
}
time_t unsmry_loader::iget_sim_time(int time_index) const {
if (this->time_index >= 0) {
double sim_seconds = this->iget_sim_seconds(time_index);
time_t sim_time = this->sim_start;
util_inplace_forward_seconds_utc( &sim_time , sim_seconds ) ;
return sim_time;
} else {
int_vector_type * index_map = int_vector_alloc(3,0);
int_vector_iset(index_map, 0, this->date_index[0]);
int_vector_iset(index_map, 1, this->date_index[1]);
int_vector_iset(index_map, 2, this->date_index[2]);
float values[3];
ecl_file_view_index_fload_kw(this->file_view, PARAMS_KW, time_index, index_map, (char *) &values);
int_vector_free(index_map);
return ecl_util_make_date(util_roundf( values[0] ),
util_roundf( values[1] ),
util_roundf( values[2] ));
}
}
double unsmry_loader::iget_sim_seconds(int time_index) const {
if (this->time_index >= 0) {
double raw_time = this->iget(time_index, this->time_index);
return raw_time * this->time_seconds;
} else {
time_t sim_time = this->iget_sim_time(time_index);
return util_difftime_seconds(this->sim_start, sim_time);
}
}
std::vector<int> unsmry_loader::report_steps(int offset) const {
std::vector<int> report_steps;
int current_step = offset;
for (int i=0; i < ecl_file_view_get_size(this->file_view); i++) {
const ecl_file_kw_type * file_kw = ecl_file_view_iget_file_kw(this->file_view, i);
if (util_string_equal(SEQHDR_KW, ecl_file_kw_get_header(file_kw)))
current_step++;
if (util_string_equal(PARAMS_KW, ecl_file_kw_get_header(file_kw)))
report_steps.push_back(current_step);
}
return report_steps;
}
std::vector<time_t> unsmry_loader::sim_time() const {
if (this->time_index >= 0) {
const std::vector<double> sim_seconds = this->sim_seconds();
std::vector<time_t> st(this->length(), this->sim_start);
for (size_t i=0; i < st.size(); i++)
util_inplace_forward_seconds_utc(&st[i], sim_seconds[i]);
return st;
} else {
const auto day = this->get_vector(this->date_index[0]);
const auto month = this->get_vector(this->date_index[1]);
const auto year = this->get_vector(this->date_index[2]);
std::vector<time_t> st(this->length());
for (size_t i=0; i < st.size(); i++)
st[i] = ecl_util_make_date(util_round(day[i]),
util_round(month[i]),
util_round(year[i]));
return st;
}
}
std::vector<double> unsmry_loader::sim_seconds() const {
if (this->time_index >= 0) {
std::vector<double> seconds = this->get_vector(this->time_index);
for (size_t i=0; i < seconds.size(); i++)
seconds[i] *= this->time_seconds;
return seconds;
} else {
std::vector<time_t> st = this->sim_time();
std::vector<double> seconds(st.size());
for (size_t i=0; i < st.size(); i++)
seconds[i] = util_difftime_seconds(this->sim_start, st[i]);
return seconds;
}
}
}