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/SequentialScheduler.h>
15#include <dpsim/Simulation.h>
16#include <dpsim/Utils.h>
18#include <spdlog/sinks/stdout_color_sinks.h>
21#include <dpsim-models/CIM/Reader.h>
25#include <dpsim-models/Solver/ODEInterface.h>
26#include <dpsim/DAESolver.h>
27#include <dpsim/ODESolver.h>
50 mLogLevel(args.logLevel), mDomain(args.solver.domain),
51 mSolverType(args.solver.type), mDirectImpl(args.directImpl) {
60 Eigen::setNbThreads(1);
92 switch (mSolverType) {
93 case Solver::Type::MNA:
97 case Solver::Type::DAE:
99 mSolvers.push_back(solver);
102 case Solver::Type::NRP:
105 solver->doInitFromNodesAndTerminals(mInitFromNodesAndTerminals);
106 solver->setSolverAndComponentBehaviour(mSolverBehaviour);
107 solver->initialize();
108 mSolvers.push_back(solver);
117 for (
auto comp :
mSystem.mComponents) {
118 auto odeComp = std::dynamic_pointer_cast<ODEInterface>(comp);
121 auto odeSolver = std::make_shared<ODESolver>(
122 odeComp->mAttributeList->attributeTyped<String>(
"name")->get() +
125 mSolvers.push_back(odeSolver);
133 std::vector<SystemTopology> subnets;
137 mSystem.splitSubnets<VarType>(subnets);
141 for (UInt net = 0; net < subnets.size(); ++net) {
143 if (subnets.size() > 1)
144 copySuffix =
"_" + std::to_string(net);
150 throw std::logic_error(
"MNA state-space extraction does not support "
151 "Diakoptics/tearing.");
154 solver = std::make_shared<DiakopticsSolver<VarType>>(
171 solver->setSystem(subnets[net]);
172 solver->setSolverAndComponentBehaviour(mSolverBehaviour);
173 solver->doInitFromNodesAndTerminals(mInitFromNodesAndTerminals);
175 solver->setDirectLinearSolverConfiguration(
176 mDirectLinearSolverConfiguration);
177 solver->initialize();
180 mSolvers.push_back(solver);
185 SPDLOG_LOGGER_INFO(
mLog,
"Start synchronization with remotes on interfaces");
193 SPDLOG_LOGGER_INFO(
mLog,
"Synchronized simulation start with remotes");
198 mTaskOutEdges.clear();
200 for (
auto solver : mSolvers) {
201 for (
auto t : solver->getTasks()) {
207 for (
auto t : intf->getTasks()) {
213 mTasks.push_back(logger->getTask());
216 mScheduler = std::make_shared<SequentialScheduler>();
222 SPDLOG_LOGGER_INFO(
mLog,
"Scheduling tasks.");
225 SPDLOG_LOGGER_INFO(
mLog,
"Scheduling done.");
233 std::map<CPS::Task::Ptr, Scheduler::TaskTime> avgTimes;
234 std::map<CPS::Task::Ptr, String> fillColors;
236 auto isScheduled = [
this](Task::Ptr task) -> Bool {
237 return !mTaskOutEdges[task].empty();
240 auto getColor = [](Task::Ptr task) -> String {
241 static std::map<std::type_index, String> colorMap;
242 auto tid = std::type_index(
typeid(task.get()));
244 if (colorMap.find(tid) != colorMap.end()) {
246 String(
"/paired9/") + std::to_string(1 + colorMap.size() % 9);
249 return colorMap[tid];
252 auto avgTimeWorst = Scheduler::TaskTime::min();
253 for (
auto task :
mTasks) {
254 avgTimes[task] =
mScheduler->getAveragedMeasurement(task);
256 if (avgTimes[task] > avgTimeWorst)
257 avgTimeWorst = avgTimes[task];
264 Graph::Graph g(
"dependencies", Graph::Type::directed);
265 for (
auto task :
mTasks) {
266 String name = task->toString();
267 String type = CPS::Utils::className(task.get(),
"DPsim::");
269 auto *n = g.addNode(name);
271 std::stringstream label;
273 label <<
"<B>" << Utils::encodeXml(name) <<
"</B><BR/>";
274 label <<
"<FONT POINT-SIZE=\"10\" COLOR=\"gray28\">"
275 << Utils::encodeXml(type) <<
"<BR/>";
277 if (isScheduled(task))
278 label <<
"Avg. time: " << avgTimes[task].count() <<
"ns<BR/>";
280 label <<
"Unscheduled"
285 n->set(
"color", getColor(task));
286 n->set(
"label", label.str(),
true);
287 n->set(
"style",
"rounded,filled,bold");
288 n->set(
"shape",
"rectangle");
290 if (isScheduled(task)) {
292 auto grad = (float)avgTimes[task].count() / avgTimeWorst.count();
293 n->set(
"fillcolor", CPS::Utils::Rgb::gradient(grad).hex());
294 SPDLOG_LOGGER_INFO(
mLog,
"{} {}", task->toString(),
295 CPS::Utils::Rgb::gradient(grad).hex());
298 n->set(
"fillcolor",
"white");
301 for (
auto from :
mTasks) {
302 for (
auto to : mTaskOutEdges[from]) {
303 g.addEdge(
"", g.node(from->toString()), g.node(to->toString()));
307 g.set(
"splines",
"ortho");
313 SPDLOG_LOGGER_INFO(
mLog,
"Initialize simulation: {}", **
mName);
320 SPDLOG_LOGGER_INFO(
mLog,
"Opening interfaces.");
327 SPDLOG_LOGGER_INFO(
mLog,
"Start simulation: {}", **
mName);
333 if (mSolverType != Solver::Type::NRP) {
349 SPDLOG_LOGGER_INFO(
mLog,
"Simulation calculation time: {:.6f}",
360 SPDLOG_LOGGER_INFO(
mLog,
"Simulation finished.");
384 std::chrono::steady_clock::time_point
start;
386 start = std::chrono::steady_clock::now();
396 auto end = std::chrono::steady_clock::now();
397 std::chrono::duration<double> diff = end -
start;
404 auto stepTimeLog = Logger::get(logName, Logger::Level::info);
406 SPDLOG_LOGGER_WARN(
mLog,
"Collection of step times has been disabled.");
409 Logger::setLogPattern(stepTimeLog,
"%v");
410 SPDLOG_LOGGER_INFO(stepTimeLog,
"step_time");
412 Real stepTimeSum = 0;
415 SPDLOG_LOGGER_INFO(stepTimeLog,
"{:.9f}", meas);
417 SPDLOG_LOGGER_INFO(
mLog,
"Average step time: {:.9f}",
422 auto stepTimeLog = Logger::get(logName, Logger::Level::info);
423 Logger::setLogPattern(stepTimeLog,
"%v");
424 SPDLOG_LOGGER_INFO(stepTimeLog,
"overruns");
430 SPDLOG_LOGGER_INFO(
mLog,
"overrun detected {}: {:.9f}", overruns, meas);
433 SPDLOG_LOGGER_INFO(
mLog,
"Detected {} overruns.", overruns);
437 for (
auto solver : mSolvers) {
438 solver->logLUTimes();
444 if (solverIndex >= mSolvers.size()) {
445 throw std::out_of_range(
446 "Simulation::getStateSpaceExtractor(): solver index out of range.");
449 const auto mnaSolver =
450 std::dynamic_pointer_cast<MnaSolver<Real>>(mSolvers[solverIndex]);
453 throw std::logic_error(
454 "Simulation::getStateSpaceExtractor(): selected solver is not a "
455 "real-valued MNA solver.");
458 return mnaSolver->getStateSpaceExtractor();
462 const String &attr) {
470 CPS::AttributeBase::Ptr attrPtr = idObj->attribute(attr);
474 mLog,
"Attribute with name {} not found on component {}", attr, comp);
478 SPDLOG_LOGGER_ERROR(
mLog,
"Component or node with name {} not found", comp);
483void Simulation::logIdObjAttribute(
const String &comp,
const String &attr) {
485 String name = comp +
"." + attr;
491 mLoggers[0]->logAttribute(name, attr);
493 throw SystemError(
"Cannot log attributes when no logger is configured for "
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
std::chrono::steady_clock::duration TaskTime
Time measurement for the task execution.
Bool mStateSpaceExtraction
Enable extraction of the MNA-coupled discrete-time state matrix.
std::chrono::duration< double > mSimulationCalculationTime
Measured calculation time for simulation.
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
CPS::Logger::Level mLogLevel
Simulation log level.
virtual Real step()
Solve system A * x = z for x and current time.
Scheduler::Edges mTaskInEdges
Task dependencies as incoming / outgoing edges.
const CPS::Attribute< Real >::Ptr mTimeStep
Simulation timestep.
const CPS::Attribute< Bool >::Ptr mSteadyStateInit
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)
void initialize()
Create solver instances etc.
std::vector< Real > mStepTimes
(Real) time needed for the timesteps
const CPS::Attribute< Real >::Ptr mFinalTime
Final time of the simulation.
void prepSchedule()
Prepare schedule for simulation.
Int mTimeStepCount
Number of step which have been executed for this simulation.
Real mSteadStIniTimeLimit
steady state initialization time limit
CPS::Task::List mTasks
List of all tasks to be scheduled.
const CPS::Attribute< Bool >::Ptr mSplitSubnets
std::shared_ptr< Scheduler > mScheduler
Scheduler used for task scheduling.
std::vector< Interface::Ptr > mInterfaces
Vector of Interfaces.
Bool mLogStepTimes
activate collection of step times
void create()
Helper function for constructors.
CPS::SystemTopology mSystem
System list.
void checkForOverruns(String logName)
Check for overruns.
Simulation(String name, CommandLineArgs &args)
Creates simulation with name and CommandLineArgs.
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.
void schedule()
Create the schedule for the independent tasks.
std::chrono::time_point< std::chrono::steady_clock > mSimulationStartTimePoint
Start time point to measure calculation time.
Real mTime
Time variable that is incremented at every step.
Bool mSystemMatrixRecomputation
Enable recomputation of system matrix during simulation.
Real mSteadStIniAccLimit
steady state initialization accuracy limit
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.
const MNAStateSpaceExtractor & getStateSpaceExtractor(UInt solverIndex=0) const
void createSolvers()
Create solvers depending on simulation settings.
const CPS::Attribute< String >::Ptr mName
Simulation name.
CPS::Logger::Log mLog
Simulation logger.
void stop()
Stop simulation including scheduler and interfaces.
std::chrono::time_point< std::chrono::steady_clock > mSimulationEndTimePoint
End time point to measure calculation time.