Use std::chrono instead of std::vector<int> to store start date

This commit is contained in:
Joakim Hove 2020-04-01 21:44:33 +02:00
parent 2df7183f1b
commit 33ad7a2620
4 changed files with 61 additions and 24 deletions

View File

@ -19,6 +19,7 @@
#ifndef OPM_IO_ESMRY_HPP
#define OPM_IO_ESMRY_HPP
#include <chrono>
#include <ostream>
#include <string>
#include <unordered_map>
@ -46,7 +47,7 @@ public:
std::vector<float> get_at_rstep(const std::string& name) const;
std::vector<float> get_at_rstep(const SummaryNode& node) const;
const std::vector<int>& get_startdat() const { return startdat; }
std::chrono::system_clock::time_point startdate() const { return startdat; }
const std::vector<std::string>& keywordList() const;
const std::vector<SummaryNode>& summaryNodeList() const;
@ -72,7 +73,7 @@ private:
std::unordered_map<std::string, std::string> kwunits;
std::vector<int> seqIndex;
std::vector<int> startdat;
std::chrono::system_clock::time_point startdat;
std::vector<std::string> checkForMultipleResultFiles(const Opm::filesystem::path& rootN, bool formatted) const;

View File

@ -1,6 +1,7 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include <pybind11/numpy.h>
#include <pybind11/chrono.h>
#include <opm/io/eclipse/EclFile.hpp>
#include <opm/io/eclipse/EclIOdata.hpp>
@ -9,6 +10,7 @@
#include <opm/io/eclipse/EGrid.hpp>
#include <opm/io/eclipse/ERft.hpp>
#include <opm/io/eclipse/EclOutput.hpp>
#include <opm/common/utility/TimeService.hpp>
#include <opm/common/utility/numeric/calculateCellVol.hpp>
@ -272,6 +274,27 @@ npArray get_rft_vector_Index(Opm::EclIO::ERft * file_ptr,const std::string& name
}
/*
This insane time based trickery is to address the following situation:
1. OPM uses UTC times internally - so the ESmry::startdate() method will
return a timepoint which should be interpreted in UTC.
2. The pybind11 std::chrono <-> datetime mapping uses localtime. We therefor
convert the timepoint returned from UTC to localtime before proceeding to
the pybind11 conversion.
*/
std::chrono::system_clock::time_point esmry_start_date(const Opm::EclIO::ESmry * esmry) {
auto utc_chrono = esmry->startdate();
auto utc_time_t = std::chrono::system_clock::to_time_t( utc_chrono );
auto utc_ts = Opm::TimeStampUTC( utc_time_t );
auto local_time_t = Opm::asLocalTimeT( utc_ts );
return std::chrono::system_clock::from_time_t( local_time_t );
}
}
@ -317,7 +340,7 @@ void python::common::export_IO(py::module& m) {
.def("__len__", &Opm::EclIO::ESmry::numberOfTimeSteps)
.def("__get_all", &get_smry_vector)
.def("__get_at_rstep", &get_smry_vector_at_rsteps)
.def("__get_startdat", &Opm::EclIO::ESmry::get_startdat)
.def_property_readonly("start_date", &esmry_start_date)
.def_property_readonly("list_of_keys", &Opm::EclIO::ESmry::keywordList);
py::class_<Opm::EclIO::EGrid>(m, "EGrid")

View File

@ -85,22 +85,6 @@ def contains_erst(self, arg):
raise ValueError("expecting tuple (array name , report step number) or \
or report step number")
@property
def esmry_start_date(self):
startd = self.__get_startdat()
if len(startd) < 6:
for n in range(len(startd), 6):
startd.append(0)
sec = startd[5] // 1000000
microseconds = startd[5] % 1000000
return datetime.datetime( startd[2], startd[1], startd[0], startd[3],
startd[4], sec, microseconds )
@property
def esmry_end_date(self):
@ -226,7 +210,6 @@ setattr(ERst, "__contains__", contains_erst)
setattr(ERst, "arrays", erst_get_list_of_arrays)
setattr(ERst, "__getitem__", getitem_erst)
setattr(ESmry, "start_date", esmry_start_date)
setattr(ESmry, "end_date", esmry_end_date)
setattr(ESmry, "__getitem__", getitem_esmry)

View File

@ -19,6 +19,7 @@
#include <opm/io/eclipse/ESmry.hpp>
#include <algorithm>
#include <chrono>
#include <exception>
#include <iterator>
#include <limits>
@ -27,7 +28,7 @@
#include <string>
#include <opm/common/utility/FileSystem.hpp>
#include <opm/common/utility/TimeService.hpp>
#include <opm/io/eclipse/EclFile.hpp>
/*
@ -47,7 +48,36 @@
RXF +-+-+- 32768*R1(R2 + 10) | 11 RXF:2-3
SOFX OP_1 12675 | 12 SOFX:OP_1:12675, SOFX:OP_1:i,j,jk
*/
*/
namespace {
std::chrono::system_clock::time_point make_date(const std::vector<int>& datetime) {
auto day = datetime[0];
auto month = datetime[1];
auto year = datetime[2];
auto hour = 0;
auto minute = 0;
auto second = 0;
auto usec = 0;
if (datetime.size() == 6) {
hour = datetime[3];
minute = datetime[4];
auto total_usec = datetime[5];
second = total_usec / 1000000;
usec = total_usec - second * 1000000;
}
const auto ts = Opm::TimeStampUTC{ Opm::TimeStampUTC::YMD{ year, month, day}}.hour(hour).minutes(minute).seconds(second);
return std::chrono::system_clock::from_time_t( Opm::asTimeT(ts) );
}
}
namespace Opm { namespace EclIO {
@ -109,7 +139,7 @@ ESmry::ESmry(const std::string &filename, bool loadBaseRunData) :
const std::vector<int> nums = smspec.get<int>("NUMS");
const std::vector<std::string> units = smspec.get<std::string>("UNITS");
startdat = smspec.get<int>("STARTDAT");
this->startdat = make_date(smspec.get<int>("STARTDAT"));
for (unsigned int i=0; i<keywords.size(); i++) {
const std::string keyString = makeKeyString(keywords[i], wgnames[i], nums[i]);
@ -160,7 +190,7 @@ ESmry::ESmry(const std::string &filename, bool loadBaseRunData) :
const std::vector<int> nums = smspec_rst.get<int>("NUMS");
const std::vector<std::string> units = smspec_rst.get<std::string>("UNITS");
startdat = smspec_rst.get<int>("STARTDAT");
this->startdat = make_date(smspec_rst.get<int>("STARTDAT"));
for (size_t i = 0; i < keywords.size(); i++) {
const std::string keyString = makeKeyString(keywords[i], wgnames[i], nums[i]);