11 #include <pybind11/complex.h>
12 #include <pybind11/eigen.h>
13 #include <pybind11/functional.h>
14 #include <pybind11/iostream.h>
15 #include <pybind11/pybind11.h>
16 #include <pybind11/stl.h>
19 #include <dpsim-models/IdentifiedObject.h>
20 #include <dpsim/RealTimeSimulation.h>
21 #include <dpsim/Simulation.h>
23 #include <dpsim-models/CSVReader.h>
25 #include <dpsim/pybind/Attributes.h>
26 #include <dpsim/pybind/BaseComponents.h>
27 #include <dpsim/pybind/DPComponents.h>
28 #include <dpsim/pybind/EMTComponents.h>
29 #include <dpsim/pybind/SPComponents.h>
30 #include <dpsim/pybind/SignalComponents.h>
31 #include <dpsim/pybind/Utils.h>
35 namespace py = pybind11;
36 using namespace pybind11::literals;
38 PYBIND11_MODULE(dpsimpy, m) {
41 -----------------------
42 The Python bindings provide access to most of the DPsim features implemented in C++.
43 It is possible to run powerflow, quasi-static, dynamic phasor and electromagnetic transient simulations
44 and to parameterize all components of the network from Python.
48 py::enum_<CPS::Logger::Level>(m,
"LogLevel")
49 .value(
"trace", CPS::Logger::Level::trace)
50 .value(
"debug", CPS::Logger::Level::debug)
51 .value(
"info", CPS::Logger::Level::info)
52 .value(
"warn", CPS::Logger::Level::warn)
53 .value(
"err", CPS::Logger::Level::err)
54 .value(
"critical", CPS::Logger::Level::critical)
55 .value(
"off", CPS::Logger::Level::off);
57 py::class_<CPS::Math>(m,
"Math")
58 .def_static(
"single_phase_variable_to_three_phase",
60 .def_static(
"single_phase_parameter_to_three_phase",
62 .def_static(
"single_phase_power_to_three_phase",
65 py::enum_<DPsim::Solver::Behaviour>(m,
"SolverBehaviour")
66 .value(
"Initialization", DPsim::Solver::Behaviour::Initialization)
67 .value(
"Simulation", DPsim::Solver::Behaviour::Simulation);
69 py::enum_<CPS::Domain>(m,
"Domain")
70 .value(
"SP", CPS::Domain::SP)
71 .value(
"DP", CPS::Domain::DP)
72 .value(
"EMT", CPS::Domain::EMT);
74 py::enum_<CPS::PhaseType>(m,
"PhaseType")
75 .value(
"A", CPS::PhaseType::A)
76 .value(
"B", CPS::PhaseType::B)
77 .value(
"C", CPS::PhaseType::C)
78 .value(
"ABC", CPS::PhaseType::ABC)
79 .value(
"Single", CPS::PhaseType::Single);
81 py::enum_<CPS::PowerflowBusType>(m,
"PowerflowBusType")
82 .value(
"PV", CPS::PowerflowBusType::PV)
83 .value(
"PQ", CPS::PowerflowBusType::PQ)
84 .value(
"VD", CPS::PowerflowBusType::VD)
85 .value(
"None", CPS::PowerflowBusType::None);
87 py::enum_<CPS::GeneratorType>(m,
"GeneratorType")
88 .value(
"PVNode", CPS::GeneratorType::PVNode)
89 .value(
"TransientStability", CPS::GeneratorType::TransientStability)
90 .value(
"IdealVoltageSource", CPS::GeneratorType::IdealVoltageSource)
91 .value(
"SG3OrderVBR", CPS::GeneratorType::SG3OrderVBR)
92 .value(
"SG4OrderVBR", CPS::GeneratorType::SG4OrderVBR)
93 .value(
"SG5OrderVBR", CPS::GeneratorType::SG5OrderVBR)
94 .value(
"SG6aOrderVBR", CPS::GeneratorType::SG6aOrderVBR)
95 .value(
"SG6bOrderVBR", CPS::GeneratorType::SG6bOrderVBR)
96 .value(
"FullOrderVBR", CPS::GeneratorType::FullOrderVBR)
97 .value(
"FullOrder", CPS::GeneratorType::FullOrder)
98 .value(
"NONE", CPS::GeneratorType::None);
100 py::enum_<DPsim::Solver::Type>(m,
"Solver")
101 .value(
"MNA", DPsim::Solver::Type::MNA)
102 .value(
"DAE", DPsim::Solver::Type::DAE)
103 .value(
"NRP", DPsim::Solver::Type::NRP);
105 py::enum_<DPsim::DirectLinearSolverImpl>(m,
"DirectLinearSolverImpl")
106 .value(
"Undef", DPsim::DirectLinearSolverImpl::Undef)
107 .value(
"DenseLU", DPsim::DirectLinearSolverImpl::DenseLU)
108 .value(
"SparseLU", DPsim::DirectLinearSolverImpl::SparseLU)
109 .value(
"KLU", DPsim::DirectLinearSolverImpl::KLU)
110 .value(
"CUDADense", DPsim::DirectLinearSolverImpl::CUDADense)
111 .value(
"CUDASparse", DPsim::DirectLinearSolverImpl::CUDASparse)
112 .value(
"CUDAMagma", DPsim::DirectLinearSolverImpl::CUDAMagma);
114 py::enum_<DPsim::SCALING_METHOD>(m,
"scaling_method")
115 .value(
"no_scaling", DPsim::SCALING_METHOD::NO_SCALING)
116 .value(
"sum_scaling", DPsim::SCALING_METHOD::SUM_SCALING)
117 .value(
"max_scaling", DPsim::SCALING_METHOD::MAX_SCALING);
119 py::enum_<DPsim::FILL_IN_REDUCTION_METHOD>(m,
"fill_in_reduction_method")
120 .value(
"amd", DPsim::FILL_IN_REDUCTION_METHOD::AMD)
121 .value(
"amd_nv", DPsim::FILL_IN_REDUCTION_METHOD::AMD_NV)
122 .value(
"amd_ra", DPsim::FILL_IN_REDUCTION_METHOD::AMD_RA)
123 .value(
"colamd", DPsim::FILL_IN_REDUCTION_METHOD::COLAMD);
125 py::enum_<DPsim::PARTIAL_REFACTORIZATION_METHOD>(
126 m,
"partial_refactorization_method")
127 .value(
"no_partial_refactorization",
128 DPsim::PARTIAL_REFACTORIZATION_METHOD::NO_PARTIAL_REFACTORIZATION)
129 .value(
"factorization_path",
130 DPsim::PARTIAL_REFACTORIZATION_METHOD::FACTORIZATION_PATH)
131 .value(
"refactorization_restart",
132 DPsim::PARTIAL_REFACTORIZATION_METHOD::REFACTORIZATION_RESTART);
134 py::enum_<DPsim::USE_BTF>(m,
"use_btf")
135 .value(
"no_btf", DPsim::USE_BTF::NO_BTF)
136 .value(
"do_btf", DPsim::USE_BTF::DO_BTF);
138 py::enum_<CPS::CSVReader::Mode>(m,
"CSVReaderMode")
139 .value(
"AUTO", CPS::CSVReader::Mode::AUTO)
140 .value(
"MANUAL", CPS::CSVReader::Mode::MANUAL);
142 py::enum_<CPS::CSVReader::DataFormat>(m,
"CSVReaderFormat")
143 .value(
"HHMMSS", CPS::CSVReader::DataFormat::HHMMSS)
144 .value(
"SECONDS", CPS::CSVReader::DataFormat::SECONDS)
145 .value(
"HOURS", CPS::CSVReader::DataFormat::HOURS)
146 .value(
"MINUTES", CPS::CSVReader::DataFormat::MINUTES);
148 m.attr(
"RMS3PH_TO_PEAK1PH") = RMS3PH_TO_PEAK1PH;
149 m.attr(
"PEAK1PH_TO_RMS3PH") = PEAK1PH_TO_RMS3PH;
150 m.attr(
"P_SNUB_TRANSFORMER") = P_SNUB_TRANSFORMER;
151 m.attr(
"Q_SNUB_TRANSFORMER") = Q_SNUB_TRANSFORMER;
155 py::class_<DPsim::DirectLinearSolverConfiguration>(
156 m,
"DirectLinearSolverConfiguration")
158 .def(
"set_fill_in_reduction_method",
159 &DPsim::DirectLinearSolverConfiguration::setFillInReductionMethod)
160 .def(
"set_scaling_method",
161 &DPsim::DirectLinearSolverConfiguration::setScalingMethod)
162 .def(
"set_partial_refactorization_method",
164 setPartialRefactorizationMethod)
165 .def(
"set_btf", &DPsim::DirectLinearSolverConfiguration::setBTF)
166 .def(
"get_scaling_method",
167 &DPsim::DirectLinearSolverConfiguration::getScalingMethod)
168 .def(
"get_fill_in_reduction_method",
169 &DPsim::DirectLinearSolverConfiguration::getFillInReductionMethod)
170 .def(
"get_partial_refactorization_method",
172 getPartialRefactorizationMethod)
173 .def(
"get_btf", &DPsim::DirectLinearSolverConfiguration::getBTF);
175 py::class_<DPsim::Simulation>(m,
"Simulation")
176 .def(py::init<std::string, CPS::Logger::Level>(),
"name"_a,
177 "loglevel"_a = CPS::Logger::Level::off)
178 .def(
"name", &DPsim::Simulation::name)
179 .def(
"set_time_step", &DPsim::Simulation::setTimeStep)
180 .def(
"set_final_time", &DPsim::Simulation::setFinalTime)
182 .def(
"set_system", &DPsim::Simulation::setSystem)
184 .def(
"set_solver", &DPsim::Simulation::setSolverType)
185 .def(
"set_domain", &DPsim::Simulation::setDomain)
191 .def(
"add_interface", &DPsim::Simulation::addInterface,
"interface"_a)
192 .def(
"log_idobj_attribute", &DPsim::Simulation::logIdObjAttribute,
196 .def(
"do_init_from_nodes_and_terminals",
197 &DPsim::Simulation::doInitFromNodesAndTerminals)
198 .def(
"do_system_matrix_recomputation",
199 &DPsim::Simulation::doSystemMatrixRecomputation)
201 .def(
"do_frequency_parallelization",
203 .def(
"do_split_subnets",
204 &DPsim::Simulation::doSplitSubnets)
205 .def(
"set_tearing_components", &DPsim::Simulation::setTearingComponents)
207 .def(
"set_solver_component_behaviour",
209 .def(
"set_direct_solver_implementation",
210 &DPsim::Simulation::setDirectLinearSolverImplementation)
211 .def(
"set_direct_linear_solver_configuration",
212 &DPsim::Simulation::setDirectLinearSolverConfiguration)
215 py::class_<DPsim::RealTimeSimulation, DPsim::Simulation>(m,
216 "RealTimeSimulation")
217 .def(py::init<std::string, CPS::Logger::Level>(),
"name"_a,
218 "loglevel"_a = CPS::Logger::Level::info)
219 .def(
"name", &DPsim::RealTimeSimulation::name)
220 .def(
"set_time_step", &DPsim::RealTimeSimulation::setTimeStep)
221 .def(
"set_final_time", &DPsim::RealTimeSimulation::setFinalTime)
223 .def(
"set_system", &DPsim::RealTimeSimulation::setSystem)
227 .def(
"set_solver", &DPsim::RealTimeSimulation::setSolverType)
228 .def(
"set_domain", &DPsim::RealTimeSimulation::setDomain);
230 py::class_<CPS::SystemTopology, std::shared_ptr<CPS::SystemTopology>>(
232 .def(py::init<CPS::Real, CPS::TopologicalNode::List,
233 CPS::IdentifiedObject::List>())
234 .def(py::init<CPS::Real, CPS::Matrix, CPS::TopologicalNode::List,
235 CPS::IdentifiedObject::List>())
236 .def(py::init<CPS::Real>())
239 .def(
"node", py::overload_cast<std::string_view>(
240 &DPsim::SystemTopology::node<CPS::TopologicalNode>))
241 .def(
"node", py::overload_cast<CPS::UInt>(
242 &DPsim::SystemTopology::node<CPS::TopologicalNode>))
243 .def(
"connect_component",
244 py::overload_cast<CPS::SimPowerComp<CPS::Real>::Ptr,
245 CPS::SimNode<CPS::Real>::List>(
246 &DPsim::SystemTopology::connectComponentToNodes<CPS::Real>))
247 .def(
"connect_component",
248 py::overload_cast<CPS::SimPowerComp<CPS::Complex>::Ptr,
249 CPS::SimNode<CPS::Complex>::List>(
250 &DPsim::SystemTopology::connectComponentToNodes<CPS::Complex>))
252 &DPsim::SystemTopology::component<CPS::TopologicalPowerComp>)
255 .def(
"_repr_svg_", &DPsim::SystemTopology::render)
256 .def(
"render_to_file", &DPsim::SystemTopology::renderToFile)
260 .def_readwrite(
"components_at_node",
263 .def(
"list_idobjects", &DPsim::SystemTopology::listIdObjects)
265 "systemPF"_a,
"domain"_a)
270 py::class_<DPsim::Interface, std::shared_ptr<DPsim::Interface>>(m,
273 py::class_<DPsim::DataLoggerInterface, std::shared_ptr<DPsim::DataLoggerInterface>>(m,
"DataLoggerInterface")
274 .def(
"log_attribute",
276 CPS::UInt, CPS::UInt>(
277 &DPsim::DataLoggerInterface::logAttribute),
278 "name"_a,
"attr"_a,
"max_cols"_a = 0,
"max_rows"_a = 0)
280 .def(
"log_attribute",
281 py::overload_cast<
const std::vector<CPS::String> &,
283 &DPsim::DataLoggerInterface::logAttribute),
286 .def(
"log_attribute",
289 logger.logAttribute(names, comp.
attribute(attr));
292 py::class_<DPsim::DataLogger, DPsim::DataLoggerInterface, std::shared_ptr<DPsim::DataLogger>>(m,
"Logger")
293 .def(py::init<std::string>())
295 .def_static(
"get_log_dir", &CPS::Logger::logDir)
296 .def(
"log_attribute",
298 CPS::UInt, CPS::UInt>(
299 &DPsim::DataLogger::logAttribute),
300 "name"_a,
"attr"_a,
"max_cols"_a = 0,
"max_rows"_a = 0)
302 .def(
"log_attribute",
303 py::overload_cast<
const std::vector<CPS::String> &,
305 &DPsim::DataLogger::logAttribute),
312 CPS::UInt rowsMax, CPS::UInt colsMax) {
313 logger.logAttribute(name, comp.
attribute(attr), rowsMax, colsMax);
315 "name"_a,
"attr"_a,
"comp"_a,
"rows_max"_a = 0,
"cols_max"_a = 0)
317 .def(
"log_attribute",
320 logger.logAttribute(names, comp.
attribute(attr));
323 py::class_<CPS::IdentifiedObject, std::shared_ptr<CPS::IdentifiedObject>>(
324 m,
"IdentifiedObject")
325 .def(
"name", &CPS::IdentifiedObject::name)
330 .def(
"print_attribute_list", &printAttributes)
331 .def(
"print_attribute", &printAttribute,
"attribute_name"_a)
332 .def(
"__str__", &getAttributeList);
335 py::class_<CPS::CIM::Reader>(m,
"CIMReader")
336 .def(py::init<std::string, CPS::Logger::Level, CPS::Logger::Level>(),
337 "name"_a,
"loglevel"_a = CPS::Logger::Level::info,
338 "comploglevel"_a = CPS::Logger::Level::off)
340 CPS::Real,
const std::list<CPS::String> &,
341 CPS::Domain, CPS::PhaseType, CPS::GeneratorType)) &
345 py::class_<CPS::CSVReader>(m,
"CSVReader")
346 .def(py::init<std::string,
const std::string &,
347 std::map<std::string, std::string> &, CPS::Logger::Level>())
354 m,
"TopologicalPowerComp");
355 py::class_<CPS::SimPowerComp<CPS::Complex>,
356 std::shared_ptr<CPS::SimPowerComp<CPS::Complex>>,
363 py::class_<CPS::SimPowerComp<CPS::Real>,
364 std::shared_ptr<CPS::SimPowerComp<CPS::Real>>,
370 py::class_<CPS::TopologicalNode, std::shared_ptr<CPS::TopologicalNode>,
372 .def(
"initial_single_voltage",
373 &CPS::TopologicalNode::initialSingleVoltage,
374 "phase_type"_a = CPS::PhaseType::Single);
378 m,
"TopologicalTerminal")
380 py::overload_cast<CPS::Complex>(&CPS::TopologicalTerminal::setPower))
381 .def(
"set_power", py::overload_cast<CPS::MatrixComp>(
382 &CPS::TopologicalTerminal::setPower));
384 py::class_<CPS::SimTerminal<CPS::Complex>,
385 std::shared_ptr<CPS::SimTerminal<CPS::Complex>>,
387 py::class_<CPS::SimTerminal<CPS::Real>,
388 std::shared_ptr<CPS::SimTerminal<CPS::Real>>,
392 py::module mEvent = m.def_submodule(
"event",
"events");
393 py::class_<DPsim::Event, std::shared_ptr<DPsim::Event>>(mEvent,
"Event");
394 py::class_<DPsim::SwitchEvent, std::shared_ptr<DPsim::SwitchEvent>,
395 DPsim::Event>(mEvent,
"SwitchEvent", py::multiple_inheritance())
396 .def(py::init<CPS::Real,
const std::shared_ptr<CPS::Base::Ph1::Switch>,
398 py::class_<DPsim::SwitchEvent3Ph, std::shared_ptr<DPsim::SwitchEvent3Ph>,
399 DPsim::Event>(mEvent,
"SwitchEvent3Ph", py::multiple_inheritance())
400 .def(py::init<CPS::Real,
const std::shared_ptr<CPS::Base::Ph3::Switch>,
404 py::module mBase = m.def_submodule(
"base",
"base models");
405 addBaseComponents(mBase);
407 py::module mDP = m.def_submodule(
"dp",
"dynamic phasor models");
408 addDPComponents(mDP);
410 py::module mEMT = m.def_submodule(
"emt",
"electromagnetic-transient models");
411 addEMTComponents(mEMT);
413 py::module mSP = m.def_submodule(
"sp",
"static phasor models");
414 mSP.attr(
"SimNode") = mDP.attr(
"SimNode");
415 addSPComponents(mSP);
417 py::module mSignal = m.def_submodule(
"signal",
"signal models");
418 addSignalComponents(mSignal);
421 m.attr(
"__version__") = VERSION_INFO;
423 m.attr(
"__version__") =
"dev";
SystemTopology loadCIM(Real systemFrequency, const fs::path &filename, Domain domain=Domain::DP, PhaseType phase=PhaseType::Single, GeneratorType genType=GeneratorType::None)
Parses data from CIM files into the CPS data structure.
void assignLoadProfile(SystemTopology &sys, Real start_time=-1, Real time_step=1, Real end_time=-1, CSVReader::Mode mode=CSVReader::Mode::AUTO, CSVReader::DataFormat format=CSVReader::DataFormat::SECONDS)
assign load profile to corresponding load object
AttributeBase::Ptr attribute(const String &name) const
Return pointer to an attribute.
static void setLogDir(String path)
Set env variable CPS_LOG_DIR and overwrite.
static Matrix singlePhasePowerToThreePhase(Real power)
To convert single phase power to symmetrical three phase.
static Matrix singlePhaseParameterToThreePhase(Real parameter)
To convert single phase parameters to symmetrical three phase ones.
static MatrixComp singlePhaseVariableToThreePhase(Complex var_1ph)
To convert single phase complex variables (voltages, currents) to symmetrical three phase ones.
Base class for all components that are transmitting power.
IdentifiedObject::List mComponents
List of network components.
void initWithPowerflow(const SystemTopology &systemPF, CPS::Domain domain)
Initialize nodes and SG power from PowerFlow.
void removeComponent(const String &name)
Remove system component.
void addTearComponent(IdentifiedObject::Ptr component)
Adds component and initializes frequencies.
TopologicalNode::List mNodes
List of network nodes.
void addComponents(const IdentifiedObject::List &components)
Add multiple components.
void addComponent(IdentifiedObject::Ptr component)
Adds component and initializes frequencies.
IdentifiedObject::List mTearComponents
std::map< TopologicalNode::Ptr, TopologicalPowerComp::List > mComponentsAtNode
Map of network components connected to network nodes.
Extending Simulation class by real-time functionality.
void doFrequencyParallelization(Bool value)
Compute phasors of different frequencies in parallel.
void logLUTimes()
Write LU decomposition times measurements to log file.
Real next()
Run until next time step.
void addLogger(DataLoggerInterface::Ptr logger)
Add a new data logger.
void setSolverAndComponentBehaviour(Solver::Behaviour behaviour)
set solver and component to initialization or simulation behaviour
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.
void doSteadyStateInit(Bool f)
activate steady state initialization
void addEvent(Event::Ptr e)
Schedule an event in the simulation.
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?
void stop()
Stop simulation including scheduler and interfaces.