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>
29 using namespace DPsim;
31 Simulation::Simulation(String name, Logger::Level logLevel)
43 mSolverPluginName(args.solverPluginName),
48 mLogLevel(args.logLevel), mDomain(args.solver.domain),
49 mSolverType(args.solver.type), mDirectImpl(args.directImpl) {
58 Eigen::setNbThreads(1);
73 createSolvers<Complex>();
76 createSolvers<Real>();
90 switch (mSolverType) {
91 case Solver::Type::MNA:
92 createMNASolver<VarType>();
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);
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>>(
152 solver = MnaSolverFactory::factory<VarType>(**
mName + copySuffix, mDomain,
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;
256 auto isScheduled = [
this](Task::Ptr task) -> Bool {
257 return !mTaskOutEdges[task].empty();
260 auto getColor = [](Task::Ptr task) -> String {
261 static std::map<std::type_index, String> colorMap;
262 auto tid = std::type_index(
typeid(task.get()));
264 if (colorMap.find(tid) != colorMap.end()) {
266 String(
"/paired9/") + std::to_string(1 + colorMap.size() % 9);
269 return colorMap[tid];
272 auto avgTimeWorst = Scheduler::TaskTime::min();
273 for (
auto task :
mTasks) {
274 avgTimes[task] =
mScheduler->getAveragedMeasurement(task);
276 if (avgTimes[task] > avgTimeWorst)
277 avgTimeWorst = avgTimes[task];
285 for (
auto task :
mTasks) {
286 String name = task->toString();
287 String type = CPS::Utils::className(task.get(),
"DPsim::");
289 auto *n = g.addNode(name);
291 std::stringstream label;
293 label <<
"<B>" << Utils::encodeXml(name) <<
"</B><BR/>";
294 label <<
"<FONT POINT-SIZE=\"10\" COLOR=\"gray28\">"
295 << Utils::encodeXml(type) <<
"<BR/>";
297 if (isScheduled(task))
298 label <<
"Avg. time: " << avgTimes[task].count() <<
"ns<BR/>";
300 label <<
"Unscheduled"
305 n->set(
"color", getColor(task));
306 n->set(
"label", label.str(),
true);
307 n->set(
"style",
"rounded,filled,bold");
308 n->set(
"shape",
"rectangle");
316 if (isScheduled(task)) {
318 auto grad = (float)avgTimes[task].count() / avgTimeWorst.count();
319 n->set(
"fillcolor", CPS::Utils::Rgb::gradient(grad).hex());
320 SPDLOG_LOGGER_INFO(
mLog,
"{} {}", task->toString(),
321 CPS::Utils::Rgb::gradient(grad).hex());
324 n->set(
"fillcolor",
"white");
327 for (
auto from :
mTasks) {
328 for (
auto to : mTaskOutEdges[from]) {
329 g.addEdge(
"", g.node(from->toString()), g.node(to->toString()));
333 g.set(
"splines",
"ortho");
339 SPDLOG_LOGGER_INFO(
mLog,
"Initialize simulation: {}", **
mName);
346 SPDLOG_LOGGER_INFO(
mLog,
"Opening interfaces.");
353 SPDLOG_LOGGER_INFO(
mLog,
"Start simulation: {}", **
mName);
359 if (mSolverType != Solver::Type::NRP) {
375 SPDLOG_LOGGER_INFO(
mLog,
"Simulation calculation time: {:.6f}",
386 SPDLOG_LOGGER_INFO(
mLog,
"Simulation finished.");
410 std::chrono::steady_clock::time_point
start;
412 start = std::chrono::steady_clock::now();
422 auto end = std::chrono::steady_clock::now();
423 std::chrono::duration<double> diff = end -
start;
430 auto stepTimeLog = Logger::get(logName, Logger::Level::info);
432 SPDLOG_LOGGER_WARN(
mLog,
"Collection of step times has been disabled.");
435 Logger::setLogPattern(stepTimeLog,
"%v");
436 stepTimeLog->info(
"step_time");
438 Real stepTimeSum = 0;
441 stepTimeLog->info(
"{:.9f}", meas);
443 SPDLOG_LOGGER_INFO(
mLog,
"Average step time: {:.9f}",
448 auto stepTimeLog = Logger::get(logName, Logger::Level::info);
449 Logger::setLogPattern(stepTimeLog,
"%v");
450 stepTimeLog->info(
"overruns");
456 SPDLOG_LOGGER_INFO(
mLog,
"overrun detected {}: {:.9f}", overruns, meas);
459 SPDLOG_LOGGER_INFO(
mLog,
"Detected {} overruns.", overruns);
463 for (
auto solver : mSolvers) {
464 solver->logLUTimes();
469 const String &attr) {
481 mLog,
"Attribute with name {} not found on component {}", attr, comp);
485 SPDLOG_LOGGER_ERROR(
mLog,
"Component or node with name {} not found", comp);
490 void Simulation::logIdObjAttribute(
const String &comp,
const String &attr) {
492 String name = comp +
"." + attr;
498 mLoggers[0]->logAttribute(name, attr);
500 throw SystemError(
"Cannot log attributes when no logger is configured for "
IdentifiedObject::List mComponents
List of network components.
std::shared_ptr< Type > node(UInt index)
Returns TopologicalNode by index in node list.
std::shared_ptr< Type > component(const String &name)
Returns Component by name.
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.