8#include <dpsim-models/Utils.h>
9#include <dpsim/DiakopticsSolver.h>
10#include <dpsim/MNASolverFactory.h>
11#include <dpsim/PFSolverPowerPolar.h>
12#include <dpsim/SequentialScheduler.h>
13#include <dpsim/Simulation.h>
14#include <dpsim/Utils.h>
16#include <spdlog/sinks/stdout_color_sinks.h>
19#include <dpsim-models/CIM/Reader.h>
23#include <dpsim-models/Solver/ODEInterface.h>
24#include <dpsim/DAESolver.h>
25#include <dpsim/ODESolver.h>
48 mLogLevel(args.logLevel), mDomain(args.solver.domain),
49 mSolverType(args.solver.type), mDirectImpl(args.directImpl) {
58 Eigen::setNbThreads(1);
90 switch (mSolverType) {
91 case Solver::Type::MNA:
95 case Solver::Type::DAE:
97 mSolvers.push_back(solver);
100 case Solver::Type::NRP:
103 solver->doInitFromNodesAndTerminals(mInitFromNodesAndTerminals);
104 solver->setSolverAndComponentBehaviour(mSolverBehaviour);
105 solver->initialize();
106 mSolvers.push_back(solver);
115 for (
auto comp :
mSystem.mComponents) {
116 auto odeComp = std::dynamic_pointer_cast<ODEInterface>(comp);
119 auto odeSolver = std::make_shared<ODESolver>(
120 odeComp->mAttributeList->attributeTyped<String>(
"name")->get() +
123 mSolvers.push_back(odeSolver);
131 std::vector<SystemTopology> subnets;
135 mSystem.splitSubnets<VarType>(subnets);
139 for (UInt net = 0; net < subnets.size(); ++net) {
141 if (subnets.size() > 1)
142 copySuffix =
"_" + std::to_string(net);
148 solver = std::make_shared<DiakopticsSolver<VarType>>(
161 solver->setSystem(subnets[net]);
162 solver->setSolverAndComponentBehaviour(mSolverBehaviour);
163 solver->doInitFromNodesAndTerminals(mInitFromNodesAndTerminals);
165 solver->setDirectLinearSolverConfiguration(
166 mDirectLinearSolverConfiguration);
167 solver->initialize();
170 mSolvers.push_back(solver);
175 SPDLOG_LOGGER_INFO(
mLog,
"Start synchronization with remotes on interfaces");
183 SPDLOG_LOGGER_INFO(
mLog,
"Synchronized simulation start with remotes");
188 mTaskOutEdges.clear();
190 for (
auto solver : mSolvers) {
191 for (
auto t : solver->getTasks()) {
197 for (
auto t : intf->getTasks()) {
203 mTasks.push_back(logger->getTask());
206 mScheduler = std::make_shared<SequentialScheduler>();
212 SPDLOG_LOGGER_INFO(
mLog,
"Scheduling tasks.");
215 SPDLOG_LOGGER_INFO(
mLog,
"Scheduling done.");
223 std::map<CPS::Task::Ptr, Scheduler::TaskTime> avgTimes;
224 std::map<CPS::Task::Ptr, String> fillColors;
226 auto isScheduled = [
this](Task::Ptr task) -> Bool {
227 return !mTaskOutEdges[task].empty();
230 auto getColor = [](Task::Ptr task) -> String {
231 static std::map<std::type_index, String> colorMap;
232 auto tid = std::type_index(
typeid(task.get()));
234 if (colorMap.find(tid) != colorMap.end()) {
236 String(
"/paired9/") + std::to_string(1 + colorMap.size() % 9);
239 return colorMap[tid];
242 auto avgTimeWorst = Scheduler::TaskTime::min();
243 for (
auto task :
mTasks) {
244 avgTimes[task] =
mScheduler->getAveragedMeasurement(task);
246 if (avgTimes[task] > avgTimeWorst)
247 avgTimeWorst = avgTimes[task];
254 Graph::Graph g(
"dependencies", Graph::Type::directed);
255 for (
auto task :
mTasks) {
256 String name = task->toString();
257 String type = CPS::Utils::className(task.get(),
"DPsim::");
259 auto *n = g.addNode(name);
261 std::stringstream label;
263 label <<
"<B>" << Utils::encodeXml(name) <<
"</B><BR/>";
264 label <<
"<FONT POINT-SIZE=\"10\" COLOR=\"gray28\">"
265 << Utils::encodeXml(type) <<
"<BR/>";
267 if (isScheduled(task))
268 label <<
"Avg. time: " << avgTimes[task].count() <<
"ns<BR/>";
270 label <<
"Unscheduled"
275 n->set(
"color", getColor(task));
276 n->set(
"label", label.str(),
true);
277 n->set(
"style",
"rounded,filled,bold");
278 n->set(
"shape",
"rectangle");
280 if (isScheduled(task)) {
282 auto grad = (float)avgTimes[task].count() / avgTimeWorst.count();
283 n->set(
"fillcolor", CPS::Utils::Rgb::gradient(grad).hex());
284 SPDLOG_LOGGER_INFO(
mLog,
"{} {}", task->toString(),
285 CPS::Utils::Rgb::gradient(grad).hex());
288 n->set(
"fillcolor",
"white");
291 for (
auto from :
mTasks) {
292 for (
auto to : mTaskOutEdges[from]) {
293 g.addEdge(
"", g.node(from->toString()), g.node(to->toString()));
297 g.set(
"splines",
"ortho");
303 SPDLOG_LOGGER_INFO(
mLog,
"Initialize simulation: {}", **
mName);
310 SPDLOG_LOGGER_INFO(
mLog,
"Opening interfaces.");
317 SPDLOG_LOGGER_INFO(
mLog,
"Start simulation: {}", **
mName);
323 if (mSolverType != Solver::Type::NRP) {
339 SPDLOG_LOGGER_INFO(
mLog,
"Simulation calculation time: {:.6f}",
350 SPDLOG_LOGGER_INFO(
mLog,
"Simulation finished.");
374 std::chrono::steady_clock::time_point
start;
376 start = std::chrono::steady_clock::now();
386 auto end = std::chrono::steady_clock::now();
387 std::chrono::duration<double> diff = end -
start;
394 auto stepTimeLog = Logger::get(logName, Logger::Level::info);
396 SPDLOG_LOGGER_WARN(
mLog,
"Collection of step times has been disabled.");
399 Logger::setLogPattern(stepTimeLog,
"%v");
400 stepTimeLog->info(
"step_time");
402 Real stepTimeSum = 0;
405 stepTimeLog->info(
"{:.9f}", meas);
407 SPDLOG_LOGGER_INFO(
mLog,
"Average step time: {:.9f}",
412 auto stepTimeLog = Logger::get(logName, Logger::Level::info);
413 Logger::setLogPattern(stepTimeLog,
"%v");
414 stepTimeLog->info(
"overruns");
420 SPDLOG_LOGGER_INFO(
mLog,
"overrun detected {}: {:.9f}", overruns, meas);
423 SPDLOG_LOGGER_INFO(
mLog,
"Detected {} overruns.", overruns);
427 for (
auto solver : mSolvers) {
428 solver->logLUTimes();
433 const String &attr) {
441 CPS::AttributeBase::Ptr attrPtr = idObj->attribute(attr);
445 mLog,
"Attribute with name {} not found on component {}", attr, comp);
449 SPDLOG_LOGGER_ERROR(
mLog,
"Component or node with name {} not found", comp);
454void Simulation::logIdObjAttribute(
const String &comp,
const String &attr) {
456 String name = comp +
"." + attr;
462 mLoggers[0]->logAttribute(name, attr);
464 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.
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.
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.