11#include <dpsim/RealTimeDataLogger.h>
13#include <dpsim-models/Attribute.h>
14#include <dpsim-models/Logger.h>
18RealTimeDataLogger::RealTimeDataLogger(std::filesystem::path &filename,
21 mCurrentRow(0), mCurrentAttribute(0), mAttributeData() {}
23RealTimeDataLogger::RealTimeDataLogger(std::filesystem::path &filename,
24 Real finalTime, Real timeStep)
26 mRowNumber((finalTime / timeStep + 0.5)), mCurrentRow(0),
27 mCurrentAttribute(0), mAttributeData() {}
29void RealTimeDataLogger::start() {
31 static_cast<double>(mRowNumber) * (mAttributes.size() + 1) *
sizeof(Real);
32 auto log = CPS::Logger::get(
"RealTimeDataLogger", CPS::Logger::Level::off,
33 CPS::Logger::Level::info);
36 "Preallocating memory for real-time data logger: {} rows for {} "
38 mRowNumber, mAttributes.size(), mb_size / (1024 * 1024));
40 mAttributeData.resize(mRowNumber);
41 for (
auto &it : mAttributeData) {
43 it.resize(mAttributes.size() + 1);
47void RealTimeDataLogger::stop() {
48 auto log = CPS::Logger::get(
"RealTimeDataLogger", CPS::Logger::Level::off,
49 CPS::Logger::Level::info);
51 log,
"Stopping real-time data logger. Writing memory to file {}",
54 const auto parent = mFilename.parent_path();
55 if (!parent.empty()) {
57 std::filesystem::create_directories(parent, ec);
59 throw std::runtime_error(
"Cannot create log directory '" +
60 parent.string() +
"': " + ec.message());
65 std::ofstream(mFilename, std::ios_base::out | std::ios_base::trunc);
66 if (!mLogFile.is_open()) {
67 throw std::runtime_error(
"Cannot open log file " + mFilename.string());
70 mLogFile << std::right << std::setw(14) <<
"time";
71 for (
auto it : mAttributes)
72 mLogFile <<
", " << std::right << std::setw(13) << it.first;
75 for (
auto row : mAttributeData) {
76 mLogFile << std::scientific << std::right << std::setw(14) << row[0];
77 for (
size_t i = 1; i < row.size(); ++i)
78 mLogFile <<
", " << std::right << std::setw(13) << row[i];
82 SPDLOG_LOGGER_INFO(log,
"Finished writing real-time data log to file {}",
86void RealTimeDataLogger::log(Real time, Int timeStepCount) {
87 mCurrentRow = timeStepCount;
88 if (timeStepCount < 0 ||
static_cast<size_t>(timeStepCount) >= mRowNumber) {
89 throw std::runtime_error(
90 "RealTimeDataLogger: timeStepCount out of bounds. Please verify the "
91 "logger was initialized correctly.");
93 if (mAttributeData.size() != mRowNumber ||
94 mAttributeData[mCurrentRow].size() != mAttributes.size() + 1) {
95 throw std::runtime_error(
96 "RealTimeDataLogger: Attribute data size mismatch");
98 mAttributeData[mCurrentRow][0] = time;
99 mCurrentAttribute = 1;
101 for (
auto &it : mAttributes) {
102 auto base = it.second.getPtr();
104 if (it.second->getType() ==
typeid(Real)) {
105 auto attr = std::dynamic_pointer_cast<CPS::Attribute<Real>>(base);
109 mAttributeData[mCurrentRow][mCurrentAttribute++] = attr->get();
110 }
else if (it.second->getType() ==
typeid(Int)) {
111 auto attr = std::dynamic_pointer_cast<CPS::Attribute<Int>>(base);
115 mAttributeData[mCurrentRow][mCurrentAttribute++] = attr->get();
120void RealTimeDataLogger::Step::execute(Real time, Int timeStepCount) {
121 mLogger.log(time, timeStepCount);
124CPS::Task::Ptr RealTimeDataLogger::getTask() {
125 return std::make_shared<RealTimeDataLogger::Step>(*
this);