DPsim
DataLogger.cpp
1 /* Copyright 2017-2021 Institute for Automation of Complex Power Systems,
2  * EONERC, RWTH Aachen University
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at https://mozilla.org/MPL/2.0/.
7  *********************************************************************************/
8 
9 #include <iomanip>
10 
11 #include <dpsim-models/Logger.h>
12 #include <dpsim/DataLogger.h>
13 
14 using namespace DPsim;
15 
16 DataLogger::DataLogger(Bool enabled) : DataLoggerInterface(), mLogFile(), mEnabled(enabled), mDownsampling(1) { mLogFile.setstate(std::ios_base::badbit); }
17 
18 DataLogger::DataLogger(String name, Bool enabled, UInt downsampling) : DataLoggerInterface(), mName(name), mEnabled(enabled), mDownsampling(downsampling) {
19  if (!mEnabled)
20  return;
21 
22  mFilename = CPS::Logger::logDir() + "/" + name + ".csv";
23 
24  if (mFilename.has_parent_path() && !fs::exists(mFilename.parent_path()))
25  fs::create_directory(mFilename.parent_path());
26 }
27 
28 void DataLogger::start() {
29  if (!mEnabled)
30  return;
31 
32  mLogFile =
33  std::ofstream(mFilename, std::ios_base::out | std::ios_base::trunc);
34  if (!mLogFile.is_open()) {
35  // TODO: replace by exception
36  std::cerr << "Cannot open log file " << mFilename << std::endl;
37  mEnabled = false;
38  }
39 }
40 
41 void DataLogger::stop() { mLogFile.close(); }
42 
43 void DataLogger::setColumnNames(std::vector<String> names) {
44  if (mLogFile.tellp() == std::ofstream::pos_type(0)) {
45  mLogFile << std::right << std::setw(14) << "time";
46  for (auto name : names) {
47  mLogFile << ", " << std::right << std::setw(13) << name;
48  }
49  mLogFile << '\n';
50  }
51 }
52 
53 void DataLogger::logDataLine(Real time, Real data) {
54  if (!mEnabled)
55  return;
56 
57  mLogFile << std::scientific << std::right << std::setw(14) << time;
58  mLogFile << ", " << std::right << std::setw(13) << data;
59  mLogFile << '\n';
60 }
61 
62 void DataLogger::logDataLine(Real time, const Matrix &data) {
63  if (!mEnabled)
64  return;
65 
66  mLogFile << std::scientific << std::right << std::setw(14) << time;
67  for (Int i = 0; i < data.rows(); ++i) {
68  mLogFile << ", " << std::right << std::setw(13) << data(i, 0);
69  }
70  mLogFile << '\n';
71 }
72 
73 void DataLogger::logDataLine(Real time, const MatrixComp &data) {
74  if (!mEnabled)
75  return;
76  mLogFile << std::scientific << std::right << std::setw(14) << time;
77  for (Int i = 0; i < data.rows(); ++i) {
78  mLogFile << ", " << std::right << std::setw(13) << data(i, 0);
79  }
80  mLogFile << '\n';
81 }
82 
83 void DataLogger::logPhasorNodeValues(Real time, const Matrix &data,
84  Int freqNum) {
85  if (mLogFile.tellp() == std::ofstream::pos_type(0)) {
86  std::vector<String> names;
87 
88  Int harmonicOffset = data.rows() / freqNum;
89  Int complexOffset = harmonicOffset / 2;
90 
91  for (Int freq = 0; freq < freqNum; ++freq) {
92  for (Int node = 0; node < complexOffset; ++node) {
93  std::stringstream name;
94  name << "n" << std::setfill('0') << std::setw(5) << node << "f"
95  << std::setfill('0') << std::setw(2) << freq << ".re";
96  names.push_back(name.str());
97  }
98  for (Int node = 0; node < complexOffset; ++node) {
99  std::stringstream name;
100  name << "n" << std::setfill('0') << std::setw(5) << node << "f"
101  << std::setfill('0') << std::setw(2) << freq << ".im";
102  names.push_back(name.str());
103  }
104  }
105  setColumnNames(names);
106  }
107  logDataLine(time, data);
108 }
109 
110 void DataLogger::logEMTNodeValues(Real time, const Matrix &data) {
111  if (mLogFile.tellp() == std::ofstream::pos_type(0)) {
112  std::vector<String> names;
113  for (Int i = 0; i < data.rows(); ++i) {
114  std::stringstream name;
115  name << "node" << std::setfill('0') << std::setw(5) << i;
116  names.push_back(name.str());
117  }
118  setColumnNames(names);
119  }
120  logDataLine(time, data);
121 }
122 
123 void DataLogger::log(Real time, Int timeStepCount) {
124  if (!mEnabled || !(timeStepCount % mDownsampling == 0))
125  return;
126 
127  if (mLogFile.tellp() == std::ofstream::pos_type(0)) {
128  mLogFile << std::right << std::setw(14) << "time";
129  for (auto it : mAttributes)
130  mLogFile << ", " << std::right << std::setw(13) << it.first;
131  mLogFile << '\n';
132  }
133 
134  mLogFile << std::scientific << std::right << std::setw(14) << time;
135  for (auto it : mAttributes)
136  mLogFile << ", " << std::right << std::setw(13) << it.second->toString();
137  mLogFile << '\n';
138 }
139 
140 void DataLogger::Step::execute(Real time, Int timeStepCount) { mLogger.log(time, timeStepCount); }
141 
142 CPS::Task::Ptr DataLogger::getTask() {
143  return std::make_shared<DataLogger::Step>(*this);
144 }