DPsim
Loading...
Searching...
No Matches
RealTimeDataLogger.cpp
1/* A data logger for real-time simulation data logging.
2 *
3 * Author: Niklas Eiling <niklas.eiling@eonerc.rwth-aachen.de>
4 * SPDX-FileCopyrightText: 2024 Niklas Eiling <niklas.eiling@eonerc.rwth-aachen.de>
5 * SPDX-License-Identifier: Apache-2.0
6 */
7#include "dpsim-models/Attribute.h"
8#include <iomanip>
9
10#include <dpsim-models/Logger.h>
11#include <dpsim/RealTimeDataLogger.h>
12#include <memory>
13
14using namespace DPsim;
15
16RealTimeDataLogger::RealTimeDataLogger(std::filesystem::path &filename,
17 size_t rowNumber)
18 : DataLoggerInterface(), mFilename(filename), mRowNumber(rowNumber),
19 mCurrentRow(0), mCurrentAttribute(0), mAttributeData() {}
20
21RealTimeDataLogger::RealTimeDataLogger(std::filesystem::path &filename,
22 Real finalTime, Real timeStep)
23 : DataLoggerInterface(), mFilename(filename),
24 mRowNumber((finalTime / timeStep + 0.5)), mCurrentRow(0),
25 mCurrentAttribute(0), mAttributeData() {}
26
27void RealTimeDataLogger::start() {
28 double mb_size =
29 static_cast<double>(mRowNumber) * (mAttributes.size() + 1) * sizeof(Real);
30 auto log = CPS::Logger::get("RealTimeDataLogger", CPS::Logger::Level::off,
31 CPS::Logger::Level::info);
32 log->info("Preallocating memory for real-time data logger: {} rows for {} "
33 "attributes ({} MB)",
34 mRowNumber, mAttributes.size(), mb_size / (1024 * 1024));
35 // We are doing real time so preallocate everything
36 mAttributeData.resize(mRowNumber);
37 for (auto &it : mAttributeData) {
38 // We have to add one to the size because we also log the time
39 it.resize(mAttributes.size() + 1);
40 }
41}
42
43void RealTimeDataLogger::stop() {
44 auto mLogFile =
45 std::ofstream(mFilename, std::ios_base::out | std::ios_base::trunc);
46 if (!mLogFile.is_open()) {
47 throw std::runtime_error("Cannot open log file " + mFilename.string());
48 }
49
50 mLogFile << std::right << std::setw(14) << "time";
51 for (auto it : mAttributes)
52 mLogFile << ", " << std::right << std::setw(13) << it.first;
53 mLogFile << '\n';
54
55 for (auto row : mAttributeData) {
56 mLogFile << std::scientific << std::right << std::setw(14) << row[0];
57 for (size_t i = 1; i < row.size(); ++i)
58 mLogFile << ", " << std::right << std::setw(13) << row[i];
59 mLogFile << '\n';
60 }
61 mLogFile.close();
62}
63
64void RealTimeDataLogger::log(Real time, Int timeStepCount) {
65 mCurrentRow = timeStepCount;
66 if (timeStepCount < 0 || static_cast<size_t>(timeStepCount) >= mRowNumber) {
67 throw std::runtime_error(
68 "RealTimeDataLogger: timeStepCount out of bounds. Please verify the "
69 "logger was initialized correctly.");
70 }
71 if (mAttributeData.size() != mRowNumber ||
72 mAttributeData[mCurrentRow].size() != mAttributes.size() + 1) {
73 throw std::runtime_error(
74 "RealTimeDataLogger: Attribute data size mismatch");
75 }
76 mAttributeData[mCurrentRow][0] = time;
77 mCurrentAttribute = 1;
78
79 for (auto it : mAttributes) {
80 if (it.second->getType() == typeid(Real)) {
81 mAttributeData[mCurrentRow][mCurrentAttribute++] =
82 **std::dynamic_pointer_cast<std::shared_ptr<CPS::Attribute<Real>>>(
83 it.second.getPtr());
84 } else if (it.second->getType() == typeid(Int)) {
85 mAttributeData[mCurrentRow][mCurrentAttribute++] =
86 **std::dynamic_pointer_cast<std::shared_ptr<CPS::Attribute<Int>>>(
87 it.second.getPtr());
88 }
89 }
90}
91
92void RealTimeDataLogger::Step::execute(Real time, Int timeStepCount) {
93 mLogger.log(time, timeStepCount);
94}
95
96CPS::Task::Ptr RealTimeDataLogger::getTask() {
97 return std::make_shared<RealTimeDataLogger::Step>(*this);
98}