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);
34 log->info(
"Preallocating memory for real-time data logger: {} rows for {} "
36 mRowNumber, mAttributes.size(), mb_size / (1024 * 1024));
38 mAttributeData.resize(mRowNumber);
39 for (
auto &it : mAttributeData) {
41 it.resize(mAttributes.size() + 1);
45void RealTimeDataLogger::stop() {
46 auto log = CPS::Logger::get(
"RealTimeDataLogger", CPS::Logger::Level::off,
47 CPS::Logger::Level::info);
48 log->info(
"Stopping real-time data logger. Writing memory to file {}",
51 const auto parent = mFilename.parent_path();
52 if (!parent.empty()) {
54 std::filesystem::create_directories(parent, ec);
56 throw std::runtime_error(
"Cannot create log directory '" +
57 parent.string() +
"': " + ec.message());
62 std::ofstream(mFilename, std::ios_base::out | std::ios_base::trunc);
63 if (!mLogFile.is_open()) {
64 throw std::runtime_error(
"Cannot open log file " + mFilename.string());
67 mLogFile << std::right << std::setw(14) <<
"time";
68 for (
auto it : mAttributes)
69 mLogFile <<
", " << std::right << std::setw(13) << it.first;
72 for (
auto row : mAttributeData) {
73 mLogFile << std::scientific << std::right << std::setw(14) << row[0];
74 for (
size_t i = 1; i < row.size(); ++i)
75 mLogFile <<
", " << std::right << std::setw(13) << row[i];
79 log->info(
"Finished writing real-time data log to file {}",
83void RealTimeDataLogger::log(Real time, Int timeStepCount) {
84 mCurrentRow = timeStepCount;
85 if (timeStepCount < 0 ||
static_cast<size_t>(timeStepCount) >= mRowNumber) {
86 throw std::runtime_error(
87 "RealTimeDataLogger: timeStepCount out of bounds. Please verify the "
88 "logger was initialized correctly.");
90 if (mAttributeData.size() != mRowNumber ||
91 mAttributeData[mCurrentRow].size() != mAttributes.size() + 1) {
92 throw std::runtime_error(
93 "RealTimeDataLogger: Attribute data size mismatch");
95 mAttributeData[mCurrentRow][0] = time;
96 mCurrentAttribute = 1;
98 for (
auto &it : mAttributes) {
99 auto base = it.second.getPtr();
101 if (it.second->getType() ==
typeid(Real)) {
102 auto attr = std::dynamic_pointer_cast<CPS::Attribute<Real>>(base);
106 mAttributeData[mCurrentRow][mCurrentAttribute++] = attr->get();
107 }
else if (it.second->getType() ==
typeid(Int)) {
108 auto attr = std::dynamic_pointer_cast<CPS::Attribute<Int>>(base);
112 mAttributeData[mCurrentRow][mCurrentAttribute++] = attr->get();
117void RealTimeDataLogger::Step::execute(Real time, Int timeStepCount) {
118 mLogger.log(time, timeStepCount);
121CPS::Task::Ptr RealTimeDataLogger::getTask() {
122 return std::make_shared<RealTimeDataLogger::Step>(*
this);