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>
19#include <spdlog/sinks/stdout_color_sinks.h>
22#include <dpsim-models/CIM/Reader.h>
26#include <dpsim-models/Solver/ODEInterface.h>
27#include <dpsim/DAESolver.h>
28#include <dpsim/ODESolver.h>
55 mLogLevel(args.logLevel), mDomain(args.solver.domain),
56 mSolverType(args.solver.type), mDirectImpl(args.directImpl) {
65 Eigen::setNbThreads(1);
98 switch (mSolverType) {
99 case Solver::Type::MNA:
104 case Solver::Type::DAE:
106 mSolvers.push_back(solver);
110 case Solver::Type::NRP: {
111 std::shared_ptr<PFSolver> pfSolver;
112#if defined(WITH_KLU) || defined(WITH_SPARSE)
114 pfSolver = std::make_shared<PFSolverPowerPolarSparse>(
117 pfSolver = std::make_shared<PFSolverPowerPolar>(**
mName,
mSystem,
121 pfSolver = std::make_shared<PFSolverPowerPolar>(**
mName,
mSystem,
125 pfSolver->setKeepLastSolution(**mPFKeepLastSolution);
129 solver->doInitFromNodesAndTerminals(mInitFromNodesAndTerminals);
130 solver->setSolverAndComponentBehaviour(mSolverBehaviour);
131 solver->initialize();
133 mSolvers.push_back(solver);
144 for (
auto comp :
mSystem.mComponents) {
145 auto odeComp = std::dynamic_pointer_cast<ODEInterface>(comp);
148 auto odeSolver = std::make_shared<ODESolver>(
149 odeComp->mAttributeList->attributeTyped<String>(
"name")->get() +
152 mSolvers.push_back(odeSolver);
160 std::vector<SystemTopology> subnets;
164 mSystem.splitSubnets<VarType>(subnets);
168 for (UInt net = 0; net < subnets.size(); ++net) {
170 if (subnets.size() > 1)
171 copySuffix =
"_" + std::to_string(net);
177 throw std::logic_error(
"MNA state-space extraction does not support "
178 "Diakoptics/tearing.");
181 solver = std::make_shared<DiakopticsSolver<VarType>>(
198 solver->setSystem(subnets[net]);
199 solver->setSolverAndComponentBehaviour(mSolverBehaviour);
200 solver->doInitFromNodesAndTerminals(mInitFromNodesAndTerminals);
202 solver->setDirectLinearSolverConfiguration(
203 mDirectLinearSolverConfiguration);
204 solver->initialize();
207 mSolvers.push_back(solver);
212 SPDLOG_LOGGER_INFO(
mLog,
"Start synchronization with remotes on interfaces");
220 SPDLOG_LOGGER_INFO(
mLog,
"Synchronized simulation start with remotes");
225 mTaskOutEdges.clear();
227 for (
auto solver : mSolvers) {
228 for (
auto t : solver->getTasks()) {
234 for (
auto t : intf->getTasks()) {
240 mTasks.push_back(logger->getTask());
243 mScheduler = std::make_shared<SequentialScheduler>();
249 SPDLOG_LOGGER_INFO(
mLog,
"Scheduling tasks.");
252 SPDLOG_LOGGER_INFO(
mLog,
"Scheduling done.");
260 std::map<CPS::Task::Ptr, Scheduler::TaskTime> avgTimes;
261 std::map<CPS::Task::Ptr, String> fillColors;
263 auto isScheduled = [
this](Task::Ptr task) -> Bool {
264 return !mTaskOutEdges[task].empty();
267 auto getColor = [](Task::Ptr task) -> String {
268 static std::map<std::type_index, String> colorMap;
269 auto tid = std::type_index(
typeid(task.get()));
271 if (colorMap.find(tid) != colorMap.end()) {
273 String(
"/paired9/") + std::to_string(1 + colorMap.size() % 9);
276 return colorMap[tid];
279 auto avgTimeWorst = Scheduler::TaskTime::min();
280 for (
auto task :
mTasks) {
281 avgTimes[task] =
mScheduler->getAveragedMeasurement(task);
283 if (avgTimes[task] > avgTimeWorst)
284 avgTimeWorst = avgTimes[task];
291 Graph::Graph g(
"dependencies", Graph::Type::directed);
292 for (
auto task :
mTasks) {
293 String name = task->toString();
294 String type = CPS::Utils::className(task.get(),
"DPsim::");
296 auto *n = g.addNode(name);
298 std::stringstream label;
300 label <<
"<B>" << Utils::encodeXml(name) <<
"</B><BR/>";
301 label <<
"<FONT POINT-SIZE=\"10\" COLOR=\"gray28\">"
302 << Utils::encodeXml(type) <<
"<BR/>";
304 if (isScheduled(task))
305 label <<
"Avg. time: " << avgTimes[task].count() <<
"ns<BR/>";
307 label <<
"Unscheduled"
312 n->set(
"color", getColor(task));
313 n->set(
"label", label.str(),
true);
314 n->set(
"style",
"rounded,filled,bold");
315 n->set(
"shape",
"rectangle");
317 if (isScheduled(task)) {
319 auto grad = (float)avgTimes[task].count() / avgTimeWorst.count();
320 n->set(
"fillcolor", CPS::Utils::Rgb::gradient(grad).hex());
321 SPDLOG_LOGGER_INFO(
mLog,
"{} {}", task->toString(),
322 CPS::Utils::Rgb::gradient(grad).hex());
325 n->set(
"fillcolor",
"white");
328 for (
auto from :
mTasks) {
329 for (
auto to : mTaskOutEdges[from]) {
330 g.addEdge(
"", g.node(from->toString()), g.node(to->toString()));
334 g.set(
"splines",
"ortho");
339void Simulation::setPFKeepLastSolution(Bool value) {
340 **mPFKeepLastSolution = value;
343Bool Simulation::getPFKeepLastSolution()
const {
return **mPFKeepLastSolution; }
345void Simulation::setPFSolverUseSparse(Bool value) {
352 SPDLOG_LOGGER_INFO(
mLog,
"Initialize simulation: {}", **
mName);
359 SPDLOG_LOGGER_INFO(
mLog,
"Opening interfaces.");
366 SPDLOG_LOGGER_INFO(
mLog,
"Start simulation: {}", **
mName);
372 if (mSolverType != Solver::Type::NRP) {
388 SPDLOG_LOGGER_INFO(
mLog,
"Simulation calculation time: {:.6f}",
399 SPDLOG_LOGGER_INFO(
mLog,
"Simulation finished.");
423 std::chrono::steady_clock::time_point
start;
425 start = std::chrono::steady_clock::now();
435 auto end = std::chrono::steady_clock::now();
436 std::chrono::duration<double> diff = end -
start;
443 auto stepTimeLog = Logger::get(logName, Logger::Level::info);
445 SPDLOG_LOGGER_WARN(
mLog,
"Collection of step times has been disabled.");
448 Logger::setLogPattern(stepTimeLog,
"%v");
449 SPDLOG_LOGGER_INFO(stepTimeLog,
"step_time");
451 Real stepTimeSum = 0;
454 SPDLOG_LOGGER_INFO(stepTimeLog,
"{:.9f}", meas);
456 SPDLOG_LOGGER_INFO(
mLog,
"Average step time: {:.9f}",
461 auto stepTimeLog = Logger::get(logName, Logger::Level::info);
462 Logger::setLogPattern(stepTimeLog,
"%v");
463 SPDLOG_LOGGER_INFO(stepTimeLog,
"overruns");
469 SPDLOG_LOGGER_INFO(
mLog,
"overrun detected {}: {:.9f}", overruns, meas);
472 SPDLOG_LOGGER_INFO(
mLog,
"Detected {} overruns.", overruns);
476 for (
auto solver : mSolvers) {
477 solver->logLUTimes();
483 if (solverIndex >= mSolvers.size()) {
484 throw std::out_of_range(
485 "Simulation::getStateSpaceExtractor(): solver index out of range.");
488 const auto mnaSolver =
489 std::dynamic_pointer_cast<MnaSolver<Real>>(mSolvers[solverIndex]);
492 throw std::logic_error(
493 "Simulation::getStateSpaceExtractor(): selected solver is not a "
494 "real-valued MNA solver.");
497 return mnaSolver->getStateSpaceExtractor();
501 const String &attr) {
509 CPS::AttributeBase::Ptr attrPtr = idObj->attribute(attr);
513 mLog,
"Attribute with name {} not found on component {}", attr, comp);
517 SPDLOG_LOGGER_ERROR(
mLog,
"Component or node with name {} not found", comp);
522void Simulation::logIdObjAttribute(
const String &comp,
const String &attr) {
524 String name = comp +
"." + attr;
530 mLoggers[0]->logAttribute(name, attr);
532 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.
const CPS::Attribute< Bool >::Ptr mPFSolverUseSparse
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.