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>
24namespace py = pybind11;
25using namespace pybind11::literals;
30 const py::handle &item) {
31 if (py::isinstance<CPS::TopologicalNode>(item))
33 else if (py::isinstance<CPS::IdentifiedObject>(item))
36 throw py::type_error(
"SystemTopology.add expects a node, a component, "
37 "or a list of nodes and components");
43 -----------------------
44 The Python bindings provide access to most of the DPsim features implemented in C++.
45 It is possible to run powerflow, quasi-static, dynamic phasor and electromagnetic transient simulations
46 and to parameterize all components of the network from Python.
50 py::enum_<CPS::Logger::Level>(m,
"LogLevel")
51 .value(
"trace", CPS::Logger::Level::trace)
52 .value(
"debug", CPS::Logger::Level::debug)
53 .value(
"info", CPS::Logger::Level::info)
54 .value(
"warn", CPS::Logger::Level::warn)
55 .value(
"err", CPS::Logger::Level::err)
56 .value(
"critical", CPS::Logger::Level::critical)
57 .value(
"off", CPS::Logger::Level::off);
59 py::class_<CPS::Math>(m,
"Math")
60 .def_static(
"single_phase_variable_to_three_phase",
62 .def_static(
"single_phase_parameter_to_three_phase",
64 .def_static(
"single_phase_power_to_three_phase",
67 py::enum_<DPsim::Solver::Behaviour>(m,
"SolverBehaviour")
71 py::enum_<DPsim::Solver::SystemMatrixRecomputationMode>(
72 m,
"SystemMatrixRecomputationMode")
78 py::enum_<CPS::Domain>(m,
"Domain")
83 py::enum_<CPS::PhaseType>(m,
"PhaseType")
91 py::enum_<CPS::PowerflowBusType>(m,
"PowerflowBusType")
97 py::enum_<CPS::GeneratorType>(m,
"GeneratorType")
110 py::enum_<CPS::CouplingMethod>(m,
"CouplingMethod")
115 py::enum_<DPsim::Solver::Type>(m,
"Solver")
120 py::enum_<DPsim::DirectLinearSolverImpl>(m,
"DirectLinearSolverImpl")
129 py::enum_<DPsim::SCALING_METHOD>(m,
"scaling_method")
134 py::enum_<DPsim::FILL_IN_REDUCTION_METHOD>(m,
"fill_in_reduction_method")
140 py::enum_<DPsim::PARTIAL_REFACTORIZATION_METHOD>(
141 m,
"partial_refactorization_method")
142 .value(
"no_partial_refactorization",
144 .value(
"factorization_path",
146 .value(
"refactorization_restart",
149 py::enum_<DPsim::USE_BTF>(m,
"use_btf")
153 py::enum_<CPS::CSVReader::Mode>(m,
"CSVReaderMode")
157 py::enum_<CPS::CSVReader::DataFormat>(m,
"CSVReaderFormat")
163 py::enum_<DPsim::StateSpaceAnalysisFrame>(m,
"StateSpaceAnalysisFrame")
167 py::enum_<DPsim::StateSpacePoleMapping>(m,
"StateSpacePoleMapping")
171 py::enum_<CPS::WindingReference>(m,
"WindingReference")
183 py::class_<DPsim::DirectLinearSolverConfiguration>(
184 m,
"DirectLinearSolverConfiguration")
186 .def(
"set_fill_in_reduction_method",
188 .def(
"set_scaling_method",
190 .def(
"set_partial_refactorization_method",
192 setPartialRefactorizationMethod)
194 .def(
"get_scaling_method",
196 .def(
"get_fill_in_reduction_method",
198 .def(
"get_partial_refactorization_method",
200 getPartialRefactorizationMethod)
203 py::class_<DPsim::MNAStateSpaceExtractor>(m,
"MNAStateSpaceExtractor")
207 .def(
"get_discrete_state_matrix",
209 py::return_value_policy::reference_internal);
211 py::class_<DPsim::StateSpaceModalAnalysis>(m,
"StateSpaceModalAnalysis")
212 .def(py::init<const DPsim::MNAStateSpaceExtractor &>(),
213 py::keep_alive<1, 2>())
214 .def(
"set_analysis_frame",
216 .def(
"set_global_dq0_frame",
221 .def(
"get_discrete_eigenvalues",
223 py::return_value_policy::reference_internal)
224 .def(
"get_continuous_eigenvalues",
226 py::return_value_policy::reference_internal)
227 .def(
"get_right_eigenvectors",
229 py::return_value_policy::reference_internal)
230 .def(
"get_left_eigenvectors",
232 py::return_value_policy::reference_internal)
233 .def(
"get_participation_factors",
235 py::return_value_policy::reference_internal)
237 py::return_value_policy::reference_internal);
239 py::class_<DPsim::Simulation>(m,
"Simulation")
240 .def(py::init<std::string, CPS::Logger::Level>(),
"name"_a,
241 "loglevel"_a = CPS::Logger::Level::off)
249 .def(
"set_pf_keep_last_solution",
251 .def(
"get_pf_keep_last_solution",
253 .def(
"set_pf_base_apparent_power_fallback",
255 .def(
"get_pf_base_apparent_power_fallback",
261 .def(
"set_pf_solver_enforce_q_limits",
263 .def(
"get_pf_solver_enforce_q_limits",
265 .def(
"set_pf_solver_base_voltage_loose_tolerance",
267 .def(
"get_pf_solver_base_voltage_loose_tolerance",
269 .def(
"set_pf_solver_base_voltage_strict_tolerance",
271 .def(
"get_pf_solver_base_voltage_strict_tolerance",
284 .def(
"do_init_from_nodes_and_terminals",
286 .def(
"set_system_matrix_recomputation_mode",
288 .def(
"do_system_matrix_recomputation",
290 .def(
"do_state_space_extraction",
292 py::arg_v(
"value",
true,
"True"))
293 .def(
"get_state_space_extractor",
295 py::return_value_policy::reference_internal)
297 .def(
"set_steady_state_init_acc_limit",
299 .def(
"set_steady_state_init_time_limit",
301 .def(
"do_frequency_parallelization",
306 .def(
"set_solver_component_behaviour",
308 .def(
"set_direct_solver_implementation",
310 .def(
"set_direct_linear_solver_configuration",
315 py::class_<DPsim::RealTimeSimulation, DPsim::Simulation>(m,
316 "RealTimeSimulation")
317 .def(py::init<std::string, CPS::Logger::Level>(),
"name"_a,
318 "loglevel"_a = CPS::Logger::Level::info)
331 py::class_<CPS::SystemTopology, std::shared_ptr<CPS::SystemTopology>>(
337 .def(py::init<CPS::Real>())
346 if (PyErr_WarnEx(PyExc_DeprecationWarning,
347 "SystemTopology.add is deprecated; use "
348 "add_component for components and add_node "
349 "for nodes instead.",
351 throw py::error_already_set();
353 if (py::isinstance<py::list>(obj) ||
354 py::isinstance<py::tuple>(obj)) {
355 for (
const py::handle &item : obj)
361 "Deprecated alias for add_component and add_node.")
362 .def(
"node", py::overload_cast<std::string_view>(
364 .def(
"node", py::overload_cast<CPS::UInt>(
366 .def(
"connect_component",
370 .def(
"connect_component",
378 .def(
"_repr_svg_", &DPsim::SystemTopology::render)
379 .def(
"render_to_file", &DPsim::SystemTopology::renderToFile)
383 .def_property_readonly(
"components_at_node",
392 "systemPF"_a,
"domain"_a)
397 py::class_<DPsim::Interface, std::shared_ptr<DPsim::Interface>>(m,
401 std::shared_ptr<DPsim::DataLoggerInterface>>(m,
402 "DataLoggerInterface")
403 .def(
"log_attribute",
407 "name"_a,
"attr"_a,
"max_cols"_a = 0,
"max_rows"_a = 0)
409 .def(
"log_attribute",
410 py::overload_cast<
const std::vector<CPS::String> &,
415 .def(
"log_attribute",
417 const std::vector<CPS::String> &names,
const CPS::String &attr,
423 std::shared_ptr<DPsim::DataLogger>>(m,
"Logger")
424 .def(py::init<std::string>())
427 .def(
"log_attribute",
431 "name"_a,
"attr"_a,
"max_cols"_a = 0,
"max_rows"_a = 0)
433 .def(
"log_attribute",
434 py::overload_cast<
const std::vector<CPS::String> &,
446 "name"_a,
"attr"_a,
"comp"_a,
"rows_max"_a = 0,
"cols_max"_a = 0)
448 .def(
"log_attribute",
455 std::shared_ptr<DPsim::RealTimeDataLogger>>(m,
456 "RealTimeDataLogger")
458 .def(py::init([](py::object filename,
DPsim::Real final_time,
461 py::module_::import(
"os").attr(
"fspath")(filename);
462 std::string s = py::cast<std::string>(fspath);
463 std::filesystem::path p(s);
464 return std::make_shared<DPsim::RealTimeDataLogger>(p, final_time,
467 "filename"_a,
"final_time"_a,
"time_step"_a)
469 .def(py::init([](py::object filename, std::size_t row_number) {
471 py::module_::import(
"os").attr(
"fspath")(filename);
472 std::string s = py::cast<std::string>(fspath);
473 std::filesystem::path p(s);
474 return std::make_shared<DPsim::RealTimeDataLogger>(p, row_number);
476 "filename"_a,
"row_number"_a)
478 .def(
"log_attribute",
482 "name"_a,
"attr"_a,
"max_cols"_a = 0,
"max_rows"_a = 0)
484 .def(
"log_attribute",
485 py::overload_cast<
const std::vector<CPS::String> &,
497 "name"_a,
"attr"_a,
"comp"_a,
"rows_max"_a = 0,
"cols_max"_a = 0)
502 const std::vector<CPS::String> &names,
const CPS::String &attr,
506 "names"_a,
"attr"_a,
"comp"_a);
509 py::class_<CPS::IdentifiedObject, std::shared_ptr<CPS::IdentifiedObject>>(
510 m,
"IdentifiedObject")
521 py::enum_<CPS::CIM::Reader::VoltageTargetUnit>(m,
522 "CIMReaderVoltageTargetUnit")
527 py::class_<CPS::CIM::Reader>(m,
"CIMReader")
528 .def(py::init<std::string, CPS::Logger::Level, CPS::Logger::Level>(),
529 "name"_a,
"loglevel"_a = CPS::Logger::Level::info,
530 "comploglevel"_a = CPS::Logger::Level::off)
532 CPS::Real,
const std::list<CPS::String> &,
535 .def(
"set_extnet_voltage_target_unit",
539 py::class_<CPS::CSVReader>(m,
"CSVReader")
540 .def(py::init<std::string,
const std::string &,
548 m,
"TopologicalPowerComp");
549 py::class_<CPS::SimPowerComp<CPS::Complex>,
550 std::shared_ptr<CPS::SimPowerComp<CPS::Complex>>,
557 py::class_<CPS::SimPowerComp<CPS::Real>,
558 std::shared_ptr<CPS::SimPowerComp<CPS::Real>>,
564 py::class_<CPS::TopologicalNode, std::shared_ptr<CPS::TopologicalNode>,
566 .def(
"initial_single_voltage",
572 m,
"TopologicalTerminal")
575 .def(
"set_power", py::overload_cast<CPS::MatrixComp>(
578 py::class_<CPS::SimTerminal<CPS::Complex>,
579 std::shared_ptr<CPS::SimTerminal<CPS::Complex>>,
581 py::class_<CPS::SimTerminal<CPS::Real>,
582 std::shared_ptr<CPS::SimTerminal<CPS::Real>>,
586 py::module mEvent = m.def_submodule(
"event",
"events");
587 py::class_<DPsim::Event, std::shared_ptr<DPsim::Event>>(mEvent,
"Event");
588 py::class_<DPsim::SwitchEvent, std::shared_ptr<DPsim::SwitchEvent>,
589 DPsim::Event>(mEvent,
"SwitchEvent", py::multiple_inheritance())
590 .def(py::init<
CPS::Real,
const std::shared_ptr<CPS::Base::Ph1::Switch>,
592 py::class_<DPsim::SwitchEvent3Ph, std::shared_ptr<DPsim::SwitchEvent3Ph>,
593 DPsim::Event>(mEvent,
"SwitchEvent3Ph", py::multiple_inheritance())
594 .def(py::init<
CPS::Real,
const std::shared_ptr<CPS::Base::Ph3::Switch>,
598 py::module mBase = m.def_submodule(
"base",
"base models");
601 py::module mDP = m.def_submodule(
"dp",
"dynamic phasor models");
604 py::module mEMT = m.def_submodule(
"emt",
"electromagnetic-transient models");
607 py::module mSP = m.def_submodule(
"sp",
"static phasor models");
608 mSP.attr(
"SimNode") = mDP.attr(
"SimNode");
611 py::module mSignal = m.def_submodule(
"signal",
"signal models");
615 m.attr(
"__version__") = VERSION_INFO;
617 m.attr(
"__version__") =
"dev";
void addAttributes(py::module_ m)
void addBaseComponents(py::module_ mBase)
void addDPComponents(py::module_ mDP)
void addEMTComponents(py::module_ mEMT)
void addSPComponents(py::module_ mSP)
void addSignalComponents(py::module_ mSignal)
AttributePointer< AttributeBase > Ptr
void setExtnetVoltageTargetUnit(VoltageTargetUnit unit)
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
std::shared_ptr< IdentifiedObject > Ptr
AttributeBase::Ptr attribute(const String &name) const
Return pointer to an attribute.
spdlog::level::level_enum Level
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.
SimTerminal< VarType >::Ptr terminal(UInt index)
Get pointer to Terminal.
void connect(typename SimNode< VarType >::List nodes)
Sets all nodes and checks for nominal number of Nodes for this Component.
void setIntfVoltage(MatrixVar< VarType > voltage)
void setIntfCurrent(MatrixVar< VarType > current)
std::shared_ptr< SimPowerComp< VarType > > Ptr
void removeNode(const String &name)
Remove node and all components connected to it.
IdentifiedObject::List mComponents
List of network components.
std::shared_ptr< Type > node(UInt index)
Returns TopologicalNode by index in node list.
void initWithPowerflow(const SystemTopology &systemPF, CPS::Domain domain)
Initialize nodes and SG power from PowerFlow.
void removeComponent(const String &name)
Remove system component.
void addNode(TopologicalNode::Ptr topNode)
Adds node and initializes frequencies.
std::map< String, String, std::less<> > listIdObjects() const
void addTearComponent(IdentifiedObject::Ptr component)
Adds component and initializes frequencies.
std::shared_ptr< Type > component(const String &name)
Returns Component by name.
void componentsAtNodeList()
TopologicalNode::List mNodes
List of network nodes.
void addComponents(const IdentifiedObject::List &components)
Add multiple components.
void connectComponentToNodes(typename SimPowerComp< VarType >::Ptr component, typename SimNode< VarType >::List simNodes)
Connect component to simNodes.
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.
std::shared_ptr< TopologicalNode > Ptr
Complex initialSingleVoltage(PhaseType phaseType=PhaseType::Single)
void setPower(Complex power)
virtual void logAttribute(const String &name, CPS::AttributeBase::Ptr attr, UInt rowsMax=0, UInt colsMax=0)
void setScalingMethod(SCALING_METHOD scalingMethod)
void setFillInReductionMethod(FILL_IN_REDUCTION_METHOD fillInReductionMethod)
void setBTF(USE_BTF useBTF)
SCALING_METHOD getScalingMethod() const
FILL_IN_REDUCTION_METHOD getFillInReductionMethod() const
Extending Simulation class by real-time functionality.
void run(const Timer::StartClock::duration &startIn=std::chrono::seconds(1))
void setDirectLinearSolverImplementation(DirectLinearSolverImpl directImpl)
void doFrequencyParallelization(Bool value)
Compute phasors of different frequencies in parallel.
void logIdObjAttribute(const String &comp, const String &attr)
void setSteadStIniAccLimit(Real v)
set steady state initialization accuracy limit
CPS::UInt getPFMaxIterations() const
void logLUTimes()
Write LU decomposition times measurements to log file.
void setSolverType(Solver::Type solverType=Solver::Type::MNA)
void setSystem(const CPS::SystemTopology &system)
void setFinalTime(Real finalTime)
void setPFSolverBaseVoltageLooseTolerance(Real tolerance)
void setSystemMatrixRecomputationMode(Solver::SystemMatrixRecomputationMode mode)
Set the system-matrix recomputation mode.
void setSteadStIniTimeLimit(Real v)
set steady state initialization time limit
void setTimeStep(Real timeStep)
void setTearingComponents(CPS::IdentifiedObject::List tearComponents=CPS::IdentifiedObject::List())
void setPFKeepLastSolution(Bool value)
Real next()
Run until next time step.
void setDirectLinearSolverConfiguration(const DirectLinearSolverConfiguration &configuration)
Bool getPFSolverEnforceReactiveLimits() const
void addLogger(DataLoggerInterface::Ptr logger)
Add a new data logger.
void doInitFromNodesAndTerminals(Bool f=true)
void setPFMaxIterations(CPS::UInt value)
void setPFBaseApparentPowerFallback(Real value)
Bool getPFSolverUseSparse() const
void doSplitSubnets(Bool splitSubnets=true)
void setSolverAndComponentBehaviour(Solver::Behaviour behaviour)
set solver and component to initialization or simulation behaviour
void setDomain(CPS::Domain domain=CPS::Domain::DP)
Real getPFBaseApparentPowerFallback() const
Bool getPFKeepLastSolution() const
void setPFSolverUseSparse(Bool value)
void setPFSolverEnforceReactiveLimits(Bool value)
Real getPFSolverBaseVoltageLooseTolerance() const
CPS::AttributeBase::Ptr getIdObjAttribute(const String &comp, const String &attr)
CHECK: Can these be deleted? getIdObjAttribute + "**attr =" should suffice.
void addInterface(Interface::Ptr eint)
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 doStateSpaceExtraction(Bool value=true)
Enable extraction of the MNA-coupled discrete-time state matrix.
void run()
Run simulation until total time is elapsed.
void setPFSolverBaseVoltageStrictTolerance(Real tolerance)
void logAttribute(String name, CPS::AttributeBase::Ptr attr)
CHECK: Can we store the attribute name / UID intrinsically inside the attribute?
const MNAStateSpaceExtractor & getStateSpaceExtractor(UInt solverIndex=0) const
Real getPFSolverBaseVoltageStrictTolerance() const
void stop()
Stop simulation including scheduler and interfaces.
void doSystemMatrixRecomputation(Bool value)
@ Enabled
Always enable system-matrix recomputation.
@ Auto
Select the mode automatically based on the system topology.
@ Disabled
Always disable system-matrix recomputation.
void setAnalysisFrame(StateSpaceAnalysisFrame frame)
const std::vector< String > & getStateNames() const
const CPS::VectorComp & getContinuousEigenvalues() const
const CPS::VectorComp & getDiscreteEigenvalues() const
Eigenvalues of the extracted discrete-time state matrix in the selected analysis frame.
void setPoleMapping(StateSpacePoleMapping mapping)
void update()
Update modal quantities from the current extracted state matrix.
void setGlobalDq0Frame(Real omega, Real theta0=0.0)
const CPS::MatrixComp & getLeftEigenvectors() const
const CPS::MatrixComp & getRightEigenvectors() const
const CPS::MatrixComp & getParticipationFactors() const
#define RMS3PH_TO_PEAK1PH
#define PEAK1PH_TO_RMS3PH
PYBIND11_DECLARE_HOLDER_TYPE(T, CPS::AttributePointer< T >)
static void systemTopologyAddSingle(DPsim::SystemTopology &sys, const py::handle &item)
PYBIND11_MODULE(dpsimpy, m)
Eigen::Matrix< Real, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor > Matrix
Dense matrix for real numbers.
@ NO_PARTIAL_REFACTORIZATION
@ REFACTORIZATION_RESTART
CPS::SystemTopology SystemTopology
void printAttribute(CPS::IdentifiedObject &obj, std::string attrName)
std::string getAttributeList(CPS::IdentifiedObject &obj)
void printAttributes(CPS::IdentifiedObject &obj)