DPsim
Loading...
Searching...
No Matches
Simulation.cpp
1// SPDX-License-Identifier: Apache-2.0
2
3#include <algorithm>
4#include <chrono>
5#include <iomanip>
6#include <stdexcept>
7#include <typeindex>
8
9#include <dpsim-models/Utils.h>
10#include <dpsim/DiakopticsSolver.h>
11#include <dpsim/MNASolver.h>
12#include <dpsim/MNASolverFactory.h>
13#include <dpsim/PFSolverPowerPolar.h>
14#include <dpsim/PFSolverPowerPolarSparse.h>
15#include <dpsim/SequentialScheduler.h>
16#include <dpsim/Simulation.h>
17#include <dpsim/Utils.h>
18
19#include <spdlog/sinks/stdout_color_sinks.h>
20
21#ifdef WITH_CIM
22#include <dpsim-models/CIM/Reader.h>
23#endif
24
25#ifdef WITH_SUNDIALS
26#include <dpsim-models/Solver/ODEInterface.h>
27#include <dpsim/DAESolver.h>
28#include <dpsim/ODESolver.h>
29#endif
30
31using namespace CPS;
32using namespace DPsim;
33
34Simulation::Simulation(String name, Logger::Level logLevel)
35 : mName(AttributeStatic<String>::make(name)),
36 mFinalTime(AttributeStatic<Real>::make(0.001)),
37 mTimeStep(AttributeStatic<Real>::make(0.001)),
38 mPFKeepLastSolution(CPS::AttributeStatic<Bool>::make(false)),
39 mPFBaseApparentPowerFallback(CPS::AttributeStatic<Real>::make(100e6)),
40 mPFMaxIterations(CPS::AttributeStatic<CPS::UInt>::make(20)),
41 mPFSolverUseSparse(CPS::AttributeStatic<Bool>::make(false)),
42 mPFEnforceReactiveLimits(CPS::AttributeStatic<Bool>::make(false)),
43 mPFBaseVoltageLooseTolerance(CPS::AttributeStatic<Real>::make(0.1)),
44 mPFBaseVoltageStrictTolerance(CPS::AttributeStatic<Real>::make(0.01)),
45 mSplitSubnets(AttributeStatic<Bool>::make(true)),
46 mSteadyStateInit(AttributeStatic<Bool>::make(false)),
47 mLogLevel(logLevel) {
48 create();
49}
50
52 : mName(AttributeStatic<String>::make(name)),
53 mSolverPluginName(args.solverPluginName),
54 mFinalTime(AttributeStatic<Real>::make(args.duration)),
55 mTimeStep(AttributeStatic<Real>::make(args.timeStep)),
56 mPFKeepLastSolution(CPS::AttributeStatic<Bool>::make(false)),
57 mPFBaseApparentPowerFallback(CPS::AttributeStatic<Real>::make(100e6)),
58 mPFMaxIterations(CPS::AttributeStatic<CPS::UInt>::make(20)),
59 mPFSolverUseSparse(CPS::AttributeStatic<Bool>::make(false)),
60 mPFEnforceReactiveLimits(CPS::AttributeStatic<Bool>::make(false)),
61 mPFBaseVoltageLooseTolerance(CPS::AttributeStatic<Real>::make(0.1)),
62 mPFBaseVoltageStrictTolerance(CPS::AttributeStatic<Real>::make(0.01)),
63 mSplitSubnets(AttributeStatic<Bool>::make(true)),
64 mSteadyStateInit(AttributeStatic<Bool>::make(false)),
65 mLogLevel(args.logLevel), mDomain(args.solver.domain),
66 mSolverType(args.solver.type), mDirectImpl(args.directImpl) {
67 create();
68}
69
71 // Logging
72 mLog =
73 Logger::get(**mName, mLogLevel, std::max(Logger::Level::info, mLogLevel));
74
75 Eigen::setNbThreads(1);
76
77 mInitialized = false;
78}
79
81 if (mInitialized)
82 return;
83
84 mSolvers.clear();
85
86 switch (mDomain) {
87 case Domain::SP:
88 // Treat SP as DP
89 case Domain::DP:
91 break;
92 case Domain::EMT:
94 break;
95 }
96
97 mTime = 0;
99
100 schedule();
101
102 mInitialized = true;
103}
104
105template <typename VarType> void Simulation::createSolvers() {
106 Solver::Ptr solver;
107
108 switch (mSolverType) {
109 case Solver::Type::MNA:
111 break;
112
113#ifdef WITH_SUNDIALS
114 case Solver::Type::DAE:
115 solver = std::make_shared<DAESolver>(**mName, mSystem, **mTimeStep, 0.0);
116 mSolvers.push_back(solver);
117 break;
118#endif /* WITH_SUNDIALS */
119
120 case Solver::Type::NRP: {
121 std::shared_ptr<PFSolver> pfSolver;
122#if defined(WITH_KLU) || defined(WITH_SPARSE)
123 if (**mPFSolverUseSparse)
124 pfSolver = std::make_shared<PFSolverPowerPolarSparse>(
126 else
127 pfSolver = std::make_shared<PFSolverPowerPolar>(**mName, mSystem,
129#else
130 // No sparse linear solver available: fall back to the dense solver.
131 pfSolver = std::make_shared<PFSolverPowerPolar>(**mName, mSystem,
133#endif
134
135 pfSolver->setKeepLastSolution(**mPFKeepLastSolution);
136 pfSolver->setBaseApparentPowerFallback(**mPFBaseApparentPowerFallback);
137 pfSolver->setMaxIterations(**mPFMaxIterations);
138 pfSolver->setEnforceReactiveLimits(**mPFEnforceReactiveLimits);
139 pfSolver->setBaseVoltageLooseTolerance(**mPFBaseVoltageLooseTolerance);
140 pfSolver->setBaseVoltageStrictTolerance(**mPFBaseVoltageStrictTolerance);
141
142 solver = pfSolver;
143
144 solver->doInitFromNodesAndTerminals(mInitFromNodesAndTerminals);
145 solver->setSolverAndComponentBehaviour(mSolverBehaviour);
146 solver->initialize();
147
148 mSolvers.push_back(solver);
149 break;
150 }
151
152 default:
154 }
155
156 // Some components require a dedicated ODE solver.
157 // This solver is independent of the system solver.
158#ifdef WITH_SUNDIALS
159 for (auto comp : mSystem.mComponents) {
160 auto odeComp = std::dynamic_pointer_cast<ODEInterface>(comp);
161 if (odeComp) {
162 // TODO explicit / implicit integration
163 auto odeSolver = std::make_shared<ODESolver>(
164 odeComp->mAttributeList->attributeTyped<String>("name")->get() +
165 "_ODE",
166 odeComp, false, **mTimeStep);
167 mSolvers.push_back(odeSolver);
168 }
169 }
170#endif /* WITH_SUNDIALS */
171}
172
173template <typename VarType> void Simulation::createMNASolver() {
174 Solver::Ptr solver;
175 std::vector<SystemTopology> subnets;
176 // The Diakoptics solver splits the system at a later point.
177 // That is why the system is not split here if tear components exist.
178 if (**mSplitSubnets && mTearComponents.size() == 0)
179 mSystem.splitSubnets<VarType>(subnets);
180 else
181 subnets.push_back(mSystem);
182
183 for (UInt net = 0; net < subnets.size(); ++net) {
184 String copySuffix;
185 if (subnets.size() > 1)
186 copySuffix = "_" + std::to_string(net);
187
188 // TODO: In the future, here we could possibly even use different
189 // solvers for different subnets if deemed useful
190 if (mTearComponents.size() > 0) {
192 throw std::logic_error("MNA state-space extraction does not support "
193 "Diakoptics/tearing.");
194 }
195 // Tear components available, use diakoptics
196 solver = std::make_shared<DiakopticsSolver<VarType>>(
197 **mName, subnets[net], mTearComponents, **mTimeStep, mLogLevel);
198 } else {
199 // Default case with lu decomposition from mna factory
200 auto mnaSolver = MnaSolverFactory::factory<VarType>(
201 **mName + copySuffix, mDomain, mLogLevel, mDirectImpl,
203
204 mnaSolver->doStateSpaceExtraction(mStateSpaceExtraction);
205
206 solver = mnaSolver;
207 solver->setTimeStep(**mTimeStep);
208 solver->setLogSolveTimes(mLogStepTimes);
209 solver->doSteadyStateInit(**mSteadyStateInit);
210 solver->doFrequencyParallelization(mFreqParallel);
211 solver->setSteadStIniTimeLimit(mSteadStIniTimeLimit);
212 solver->setSteadStIniAccLimit(mSteadStIniAccLimit);
213 solver->setSystem(subnets[net]);
214 solver->setSolverAndComponentBehaviour(mSolverBehaviour);
215 solver->doInitFromNodesAndTerminals(mInitFromNodesAndTerminals);
216 solver->doSystemMatrixRecomputation(mSystemMatrixRecomputation);
217 solver->setDirectLinearSolverConfiguration(
218 mDirectLinearSolverConfiguration);
219 solver->initialize();
220 solver->setMaxNumberOfIterations(mMaxIterations);
221 }
222 mSolvers.push_back(solver);
223 }
224}
225
226void Simulation::sync() const {
227 SPDLOG_LOGGER_INFO(mLog, "Start synchronization with remotes on interfaces");
228
229 for (auto intf : mInterfaces) {
230 intf->syncExports();
231 intf->syncImports();
232 intf->syncExports();
233 }
234
235 SPDLOG_LOGGER_INFO(mLog, "Synchronized simulation start with remotes");
236}
237
239 mTasks.clear();
240 mTaskOutEdges.clear();
241 mTaskInEdges.clear();
242 for (auto solver : mSolvers) {
243 for (auto t : solver->getTasks()) {
244 mTasks.push_back(t);
245 }
246 }
247
248 for (auto intf : mInterfaces) {
249 for (auto t : intf->getTasks()) {
250 mTasks.push_back(t);
251 }
252 }
253
254 for (auto logger : mLoggers) {
255 mTasks.push_back(logger->getTask());
256 }
257 if (!mScheduler) {
258 mScheduler = std::make_shared<SequentialScheduler>();
259 }
260 mScheduler->resolveDeps(mTasks, mTaskInEdges, mTaskOutEdges);
261}
262
264 SPDLOG_LOGGER_INFO(mLog, "Scheduling tasks.");
265 prepSchedule();
266 mScheduler->createSchedule(mTasks, mTaskInEdges, mTaskOutEdges);
267 SPDLOG_LOGGER_INFO(mLog, "Scheduling done.");
268}
269
270#ifdef WITH_GRAPHVIZ
271Graph::Graph Simulation::dependencyGraph() {
272 if (!mInitialized)
273 initialize();
274
275 std::map<CPS::Task::Ptr, Scheduler::TaskTime> avgTimes;
276 std::map<CPS::Task::Ptr, String> fillColors;
277
278 auto isScheduled = [this](Task::Ptr task) -> Bool {
279 return !mTaskOutEdges[task].empty();
280 };
281
282 auto getColor = [](Task::Ptr task) -> String {
283 static std::map<std::type_index, String> colorMap;
284 auto tid = std::type_index(typeid(task.get()));
285
286 if (colorMap.find(tid) != colorMap.end()) {
287 colorMap[tid] =
288 String("/paired9/") + std::to_string(1 + colorMap.size() % 9);
289 }
290
291 return colorMap[tid];
292 };
293
294 auto avgTimeWorst = Scheduler::TaskTime::min();
295 for (auto task : mTasks) {
296 avgTimes[task] = mScheduler->getAveragedMeasurement(task);
297
298 if (avgTimes[task] > avgTimeWorst)
299 avgTimeWorst = avgTimes[task];
300 }
301
302 // TODO: For level-based Scheduler's we might want to
303 // maintain the level structure by setting the respective
304 // Graphviz 'rank' attributes and group each level into sub-graph
305
306 Graph::Graph g("dependencies", Graph::Type::directed);
307 for (auto task : mTasks) {
308 String name = task->toString();
309 String type = CPS::Utils::className(task.get(), "DPsim::");
310
311 auto *n = g.addNode(name);
312
313 std::stringstream label;
314
315 label << "<B>" << Utils::encodeXml(name) << "</B><BR/>";
316 label << "<FONT POINT-SIZE=\"10\" COLOR=\"gray28\">"
317 << Utils::encodeXml(type) << "<BR/>";
318
319 if (isScheduled(task))
320 label << "Avg. time: " << avgTimes[task].count() << "ns<BR/>";
321 else
322 label << "Unscheduled"
323 << "<BR/>";
324
325 label << "</FONT>";
326
327 n->set("color", getColor(task));
328 n->set("label", label.str(), true);
329 n->set("style", "rounded,filled,bold");
330 n->set("shape", "rectangle");
331
332 if (isScheduled(task)) {
333 if (avgTimeWorst > Scheduler::TaskTime(0)) {
334 auto grad = (float)avgTimes[task].count() / avgTimeWorst.count();
335 n->set("fillcolor", CPS::Utils::Rgb::gradient(grad).hex());
336 SPDLOG_LOGGER_INFO(mLog, "{} {}", task->toString(),
337 CPS::Utils::Rgb::gradient(grad).hex());
338 }
339 } else {
340 n->set("fillcolor", "white");
341 }
342 }
343 for (auto from : mTasks) {
344 for (auto to : mTaskOutEdges[from]) {
345 g.addEdge("", g.node(from->toString()), g.node(to->toString()));
346 }
347 }
348
349 g.set("splines", "ortho");
350 return g;
351}
352#endif
353
354void Simulation::setPFKeepLastSolution(Bool value) {
355 **mPFKeepLastSolution = value;
356}
357
358Bool Simulation::getPFKeepLastSolution() const { return **mPFKeepLastSolution; }
359
360void Simulation::setPFBaseApparentPowerFallback(Real value) {
362}
363
364Real Simulation::getPFBaseApparentPowerFallback() const {
366}
367
368void Simulation::setPFMaxIterations(CPS::UInt value) {
369 **mPFMaxIterations = value;
370}
371
372CPS::UInt Simulation::getPFMaxIterations() const { return **mPFMaxIterations; }
373
374void Simulation::setPFSolverUseSparse(Bool value) {
375 **mPFSolverUseSparse = value;
376}
377
378Bool Simulation::getPFSolverUseSparse() const { return **mPFSolverUseSparse; }
379
380void Simulation::setPFSolverEnforceReactiveLimits(Bool value) {
381 **mPFEnforceReactiveLimits = value;
382}
383
384Bool Simulation::getPFSolverEnforceReactiveLimits() const {
386}
387
388void Simulation::setPFSolverBaseVoltageLooseTolerance(Real tolerance) {
389 **mPFBaseVoltageLooseTolerance = tolerance;
390}
391
392Real Simulation::getPFSolverBaseVoltageLooseTolerance() const {
394}
395
396void Simulation::setPFSolverBaseVoltageStrictTolerance(Real tolerance) {
397 **mPFBaseVoltageStrictTolerance = tolerance;
398}
399
400Real Simulation::getPFSolverBaseVoltageStrictTolerance() const {
402}
403
405 SPDLOG_LOGGER_INFO(mLog, "Initialize simulation: {}", **mName);
406 if (!mInitialized)
407 initialize();
408
409 for (auto lg : mLoggers)
410 lg->start();
411
412 SPDLOG_LOGGER_INFO(mLog, "Opening interfaces.");
413
414 for (auto intf : mInterfaces)
415 intf->open();
416
417 sync();
418
419 SPDLOG_LOGGER_INFO(mLog, "Start simulation: {}", **mName);
420 SPDLOG_LOGGER_INFO(mLog, "Time step: {:e}", **mTimeStep);
421 SPDLOG_LOGGER_INFO(mLog, "Final time: {:e}", **mFinalTime);
422
423 // In PF we dont log the initial conditions of the componentes because they are not calculated
424 // In dynamic simulations log initial values of attributes (t=0)
425 if (mSolverType != Solver::Type::NRP) {
426 if (mLoggers.size() > 0)
427 mLoggers[0]->log(0, 0);
428
429 // In dynamic simulations increase simulation time to calculate first results at t=timestep
430 mTime += **mTimeStep;
431 }
432
433 mSimulationStartTimePoint = std::chrono::steady_clock::now();
434}
435
437
438 mSimulationEndTimePoint = std::chrono::steady_clock::now();
441 SPDLOG_LOGGER_INFO(mLog, "Simulation calculation time: {:.6f}",
443
444 mScheduler->stop();
445
446 for (auto intf : mInterfaces)
447 intf->close();
448
449 for (auto lg : mLoggers)
450 lg->stop();
451
452 SPDLOG_LOGGER_INFO(mLog, "Simulation finished.");
453 mLog->flush();
454}
455
457 if (mTime < **mFinalTime + DOUBLE_EPSILON)
458 step();
459 else
460 stop();
461
462 return mTime;
463}
464
466 start();
467
468 while (mTime < **mFinalTime + DOUBLE_EPSILON) {
469 step();
470 }
471
472 stop();
473}
474
476 std::chrono::steady_clock::time_point start;
477 if (mLogStepTimes) {
478 start = std::chrono::steady_clock::now();
479 }
480
481 mEvents.handleEvents(mTime);
483
484 mTime += **mTimeStep;
486
487 if (mLogStepTimes) {
488 auto end = std::chrono::steady_clock::now();
489 std::chrono::duration<double> diff = end - start;
490 mStepTimes.push_back(diff.count());
491 }
492 return mTime;
493}
494
495void Simulation::logStepTimes(String logName) {
496 auto stepTimeLog = Logger::get(logName, Logger::Level::info);
497 if (!mLogStepTimes) {
498 SPDLOG_LOGGER_WARN(mLog, "Collection of step times has been disabled.");
499 return;
500 }
501 Logger::setLogPattern(stepTimeLog, "%v");
502 SPDLOG_LOGGER_INFO(stepTimeLog, "step_time");
503
504 Real stepTimeSum = 0;
505 for (auto meas : mStepTimes) {
506 stepTimeSum += meas;
507 SPDLOG_LOGGER_INFO(stepTimeLog, "{:.9f}", meas);
508 }
509 SPDLOG_LOGGER_INFO(mLog, "Average step time: {:.9f}",
510 stepTimeSum / mStepTimes.size());
511}
512
513void Simulation::checkForOverruns(String logName) {
514 auto stepTimeLog = Logger::get(logName, Logger::Level::info);
515 Logger::setLogPattern(stepTimeLog, "%v");
516 SPDLOG_LOGGER_INFO(stepTimeLog, "overruns");
517
518 int overruns = 0;
519 for (auto meas : mStepTimes) {
520 if (meas > **mTimeStep) {
521 overruns++;
522 SPDLOG_LOGGER_INFO(mLog, "overrun detected {}: {:.9f}", overruns, meas);
523 }
524 }
525 SPDLOG_LOGGER_INFO(mLog, "Detected {} overruns.", overruns);
526}
527
529 for (auto solver : mSolvers) {
530 solver->logLUTimes();
531 }
532}
533
535Simulation::getStateSpaceExtractor(UInt solverIndex) const {
536 if (solverIndex >= mSolvers.size()) {
537 throw std::out_of_range(
538 "Simulation::getStateSpaceExtractor(): solver index out of range.");
539 }
540
541 if (const auto realMnaSolver =
542 std::dynamic_pointer_cast<MnaSolver<Real>>(mSolvers[solverIndex])) {
543 return realMnaSolver->getStateSpaceExtractor();
544 }
545
546 if (const auto complexMnaSolver =
547 std::dynamic_pointer_cast<MnaSolver<Complex>>(
548 mSolvers[solverIndex])) {
549 return complexMnaSolver->getStateSpaceExtractor();
550 }
551
552 throw std::logic_error(
553 "Simulation::getStateSpaceExtractor(): selected solver is not an "
554 "MNA solver.");
555}
556
557CPS::AttributeBase::Ptr Simulation::getIdObjAttribute(const String &comp,
558 const String &attr) {
559 IdentifiedObject::Ptr idObj = mSystem.component<IdentifiedObject>(comp);
560 if (!idObj) {
561 idObj = mSystem.node<TopologicalNode>(comp);
562 }
563
564 if (idObj) {
565 try {
566 CPS::AttributeBase::Ptr attrPtr = idObj->attribute(attr);
567 return attrPtr;
568 } catch (InvalidAttributeException &e) {
569 SPDLOG_LOGGER_ERROR(
570 mLog, "Attribute with name {} not found on component {}", attr, comp);
572 }
573 } else {
574 SPDLOG_LOGGER_ERROR(mLog, "Component or node with name {} not found", comp);
576 }
577}
578
579void Simulation::logIdObjAttribute(const String &comp, const String &attr) {
580 CPS::AttributeBase::Ptr attrPtr = getIdObjAttribute(comp, attr);
581 String name = comp + "." + attr;
582 logAttribute(name, attrPtr);
583}
584
585void Simulation::logAttribute(String name, CPS::AttributeBase::Ptr attr) {
586 if (mLoggers.size() > 0) {
587 mLoggers[0]->logAttribute(name, attr);
588 } else {
589 throw SystemError("Cannot log attributes when no logger is configured for "
590 "this simulation!");
591 }
592}
static std::shared_ptr< MnaSolver< VarType > > factory(String name, CPS::Domain domain=CPS::Domain::DP, CPS::Logger::Level logLevel=CPS::Logger::Level::info, DirectLinearSolverImpl implementation=mSupportedSolverImpls().back(), String pluginName="plugin.so")
sovlerImpl: choose the most advanced solver implementation available by default
Solver class using Modified Nodal Analysis (MNA).
Definition MNASolver.h:39
std::chrono::steady_clock::duration TaskTime
Time measurement for the task execution.
Definition Scheduler.h:33
Bool mStateSpaceExtraction
Enable extraction of the MNA-coupled discrete-time state matrix.
Definition Simulation.h:122
std::chrono::duration< double > mSimulationCalculationTime
Measured calculation time for simulation.
Definition Simulation.h:94
void logLUTimes()
Write LU decomposition times measurements to log file.
void sync() const
Synchronize simulation with remotes by exchanging intial state over interfaces.
CPS::IdentifiedObject::List mTearComponents
Definition Simulation.h:126
CPS::Logger::Level mLogLevel
Simulation log level.
Definition Simulation.h:98
virtual Real step()
Solve system A * x = z for x and current time.
Scheduler::Edges mTaskInEdges
Task dependencies as incoming / outgoing edges.
Definition Simulation.h:148
const CPS::Attribute< Real >::Ptr mTimeStep
Simulation timestep.
Definition Simulation.h:42
const CPS::Attribute< CPS::UInt >::Ptr mPFMaxIterations
Maximum number of Newton-Raphson iterations for the PF solver.
Definition Simulation.h:51
const CPS::Attribute< Bool >::Ptr mSteadyStateInit
Definition Simulation.h:77
const CPS::Attribute< Real >::Ptr mPFBaseVoltageStrictTolerance
Strict tolerance between authoritative base-voltage sources in a zone; default 0.01.
Definition Simulation.h:66
Real next()
Run until next time step.
void logStepTimes(String logName)
Write step time measurements to log file.
String mSolverPluginName
If there we use a solver plugin, this specifies its name (excluding .so)
Definition Simulation.h:38
void initialize()
Create solver instances etc.
std::vector< Real > mStepTimes
(Real) time needed for the timesteps
Definition Simulation.h:100
const CPS::Attribute< Real >::Ptr mFinalTime
Final time of the simulation.
Definition Simulation.h:40
void prepSchedule()
Prepare schedule for simulation.
Int mTimeStepCount
Number of step which have been executed for this simulation.
Definition Simulation.h:83
const CPS::Attribute< Real >::Ptr mPFBaseApparentPowerFallback
Definition Simulation.h:48
Real mSteadStIniTimeLimit
steady state initialization time limit
Definition Simulation.h:138
CPS::Task::List mTasks
List of all tasks to be scheduled.
Definition Simulation.h:146
const CPS::Attribute< Bool >::Ptr mSplitSubnets
Definition Simulation.h:72
std::shared_ptr< Scheduler > mScheduler
Scheduler used for task scheduling.
Definition Simulation.h:144
std::vector< Interface::Ptr > mInterfaces
Vector of Interfaces.
Definition Simulation.h:151
Bool mLogStepTimes
activate collection of step times
Definition Simulation.h:102
void create()
Helper function for constructors.
CPS::SystemTopology mSystem
System list.
Definition Simulation.h:87
void checkForOverruns(String logName)
Check for overruns.
Simulation(String name, CommandLineArgs &args)
Creates simulation with name and CommandLineArgs.
const CPS::Attribute< Bool >::Ptr mPFEnforceReactiveLimits
Definition Simulation.h:60
CPS::AttributeBase::Ptr getIdObjAttribute(const String &comp, const String &attr)
CHECK: Can these be deleted? getIdObjAttribute + "**attr =" should suffice.
void start()
Start simulation without advancing in time.
EventQueue mEvents
The simulation event queue.
Definition Simulation.h:85
void schedule()
Create the schedule for the independent tasks.
const CPS::Attribute< Bool >::Ptr mPFSolverUseSparse
Definition Simulation.h:56
std::chrono::time_point< std::chrono::steady_clock > mSimulationStartTimePoint
Start time point to measure calculation time.
Definition Simulation.h:90
Real mTime
Time variable that is incremented at every step.
Definition Simulation.h:81
Bool mSystemMatrixRecomputation
Enable recomputation of system matrix during simulation.
Definition Simulation.h:120
Real mSteadStIniAccLimit
steady state initialization accuracy limit
Definition Simulation.h:140
const CPS::Attribute< Real >::Ptr mPFBaseVoltageLooseTolerance
Loose tolerance for a zone's Load base-voltage vs. its rating; default 0.1.
Definition Simulation.h:63
void createMNASolver()
Subroutine for MNA only because there are many MNA options.
void run()
Run simulation until total time is elapsed.
void logAttribute(String name, CPS::AttributeBase::Ptr attr)
CHECK: Can we store the attribute name / UID intrinsically inside the attribute?
DataLoggerInterface::List mLoggers
The data loggers.
Definition Simulation.h:161
const MNAStateSpaceExtractor & getStateSpaceExtractor(UInt solverIndex=0) const
void createSolvers()
Create solvers depending on simulation settings.
const CPS::Attribute< String >::Ptr mName
Simulation name.
Definition Simulation.h:36
CPS::Logger::Log mLog
Simulation logger.
Definition Simulation.h:177
void stop()
Stop simulation including scheduler and interfaces.
std::chrono::time_point< std::chrono::steady_clock > mSimulationEndTimePoint
End time point to measure calculation time.
Definition Simulation.h:92