From 4e26b10ac244eeee2f5d6b2d590bdc2c5cf0fcbd Mon Sep 17 00:00:00 2001 From: pelesh Date: Wed, 11 Jun 2025 21:33:44 -0400 Subject: [PATCH 01/15] Add bus factory to phasor dynamics family. --- src/Model/PhasorDynamics/Bus/Bus.hpp | 2 +- src/Model/PhasorDynamics/Bus/BusData.hpp | 8 ++++ src/Model/PhasorDynamics/Bus/BusFactory.hpp | 41 ++++++++++++++++++++ src/Model/PhasorDynamics/Bus/BusInfinite.hpp | 2 +- src/Model/PhasorDynamics/BusBase.hpp | 6 --- src/Model/PhasorDynamics/SystemModel.hpp | 2 + 6 files changed, 53 insertions(+), 8 deletions(-) create mode 100644 src/Model/PhasorDynamics/Bus/BusFactory.hpp diff --git a/src/Model/PhasorDynamics/Bus/Bus.hpp b/src/Model/PhasorDynamics/Bus/Bus.hpp index 57828ef01..140f83deb 100644 --- a/src/Model/PhasorDynamics/Bus/Bus.hpp +++ b/src/Model/PhasorDynamics/Bus/Bus.hpp @@ -58,7 +58,7 @@ namespace GridKit virtual int BusType() const override { - return BusBase::BusType::DEFAULT; + return BusData::BusType::DEFAULT; } virtual ScalarT& Vr() override diff --git a/src/Model/PhasorDynamics/Bus/BusData.hpp b/src/Model/PhasorDynamics/Bus/BusData.hpp index abd8ab595..97690e703 100644 --- a/src/Model/PhasorDynamics/Bus/BusData.hpp +++ b/src/Model/PhasorDynamics/Bus/BusData.hpp @@ -23,10 +23,18 @@ namespace GridKit template struct BusData { + enum BusType + { + INVALID = 0, + DEFAULT, + SLACK + }; + RealT Vr0{0.0}; ///< Initial value for real bus voltage RealT Vi0{0.0}; ///< Initial value for imaginary bus voltage IdxT bus_id{0}; ///< Unique ID of bus 1 + BusType bus_type{INVALID}; }; } // namespace PhasorDynamics } // namespace GridKit diff --git a/src/Model/PhasorDynamics/Bus/BusFactory.hpp b/src/Model/PhasorDynamics/Bus/BusFactory.hpp new file mode 100644 index 000000000..d3ea14758 --- /dev/null +++ b/src/Model/PhasorDynamics/Bus/BusFactory.hpp @@ -0,0 +1,41 @@ + +#pragma once + +#include +#include +#include + +namespace GridKit +{ + namespace PhasorDynamics + { + template + class BusFactory + { + public: + using real_type = typename Model::Evaluator::real_type; + using BusData = GridKit::PhasorDynamics::BusData; + + BusFactory() = delete; + + static BusBase* create(BusData& data) + { + BusBase* bus = nullptr; + + switch (data.bus_type) + { + case BusData::DEFAULT: + bus = new Bus(data); + break; + case BusData::SLACK: + bus = new BusInfinite(data); + break; + default: + // Throw exception + std::cout << "Bus type " << data.type << " unrecognized.\n"; + } + return bus; + } + }; + } // namespace PhasorDynamics +} // namespace GridKit diff --git a/src/Model/PhasorDynamics/Bus/BusInfinite.hpp b/src/Model/PhasorDynamics/Bus/BusInfinite.hpp index 0657ec374..e63a1fa42 100644 --- a/src/Model/PhasorDynamics/Bus/BusInfinite.hpp +++ b/src/Model/PhasorDynamics/Bus/BusInfinite.hpp @@ -56,7 +56,7 @@ namespace GridKit virtual int BusType() const override { - return BusBase::BusType::SLACK; + return BusData::BusType::SLACK; } virtual ScalarT& Vr() override diff --git a/src/Model/PhasorDynamics/BusBase.hpp b/src/Model/PhasorDynamics/BusBase.hpp index 332aaaed1..322e6f095 100644 --- a/src/Model/PhasorDynamics/BusBase.hpp +++ b/src/Model/PhasorDynamics/BusBase.hpp @@ -19,12 +19,6 @@ namespace GridKit public: using real_type = typename Model::Evaluator::real_type; - enum BusType - { - DEFAULT = 1, - SLACK - }; - BusBase() : size_(0), size_quad_(0), diff --git a/src/Model/PhasorDynamics/SystemModel.hpp b/src/Model/PhasorDynamics/SystemModel.hpp index 03347b224..4ea87f419 100644 --- a/src/Model/PhasorDynamics/SystemModel.hpp +++ b/src/Model/PhasorDynamics/SystemModel.hpp @@ -8,6 +8,8 @@ #include #include +#include + namespace GridKit { namespace PhasorDynamics From b14da5c2b0fb5e59992d20123fc7e9603d1ef13a Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Thu, 12 Jun 2025 10:31:17 -0400 Subject: [PATCH 02/15] Add system model data for phasor dynamics family. --- src/Model/PhasorDynamics/INPUT_FORMAT.md | 2 +- src/Model/PhasorDynamics/SystemModel.hpp | 63 ++++++++++++++++++++ src/Model/PhasorDynamics/SystemModelData.hpp | 40 +++++++++++++ 3 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 src/Model/PhasorDynamics/SystemModelData.hpp diff --git a/src/Model/PhasorDynamics/INPUT_FORMAT.md b/src/Model/PhasorDynamics/INPUT_FORMAT.md index 149048b6c..0fdfdcfb4 100644 --- a/src/Model/PhasorDynamics/INPUT_FORMAT.md +++ b/src/Model/PhasorDynamics/INPUT_FORMAT.md @@ -49,7 +49,7 @@ Contained in the `header` key is an object with the following items: `format_version` | Non-negative integer indicating the format version `format_revision` | Non-negative integer indicating the format revision `case_name` | A string containing the name of the case - `case_datetime` | Optional string in the ISO 8601 format indicating a datetime associated with the case. Including a time is optional, but if one is specified, it is recommended that a UTC offset be included. + `case_date_time` | Optional string in the ISO 8601 format indicating a datetime associated with the case. Including a time is optional, but if one is specified, it is recommended that a UTC offset be included. `case_description` | A string with more specific description of what is modeled in the case `case_comments` | A string with additional notes as needed `freq_base` | A floating point value indicating the system frequency base in hertz (Hz). This is commonly 60 Hz diff --git a/src/Model/PhasorDynamics/SystemModel.hpp b/src/Model/PhasorDynamics/SystemModel.hpp index 4ea87f419..c3cacb37c 100644 --- a/src/Model/PhasorDynamics/SystemModel.hpp +++ b/src/Model/PhasorDynamics/SystemModel.hpp @@ -4,11 +4,18 @@ #include #include +#include #include #include #include #include +// Temporary +#include +// #include +#include +#include + namespace GridKit { @@ -65,6 +72,55 @@ namespace GridKit this->max_steps_ = 2000; } + /** + * @brief Construct a new System Model object + * + * @param[in] data - Data structure with complete system data + */ + SystemModel(SystemModelData& data) + { + // Set system model tolerances + rel_tol_ = 1e-7; + abs_tol_ = 1e-9; + this->max_steps_ = 2000; + + // Add electrical buses + for (const auto& busdata : data.bus) + { + BusBase* bus = new Bus(busdata); + addBus(bus); + } + + // Add branches + for (const auto& branchdata : data.branch) + { + auto* branch = new Branch(getBus(branchdata.bus1_id), getBus(branchdata.bus2_id), branchdata); + addComponent(branch); + } + + // Add loads + for (const auto& loaddata : data.load) + { + auto* load = new Genrou(getBus(loaddata.bus_id), loaddata); + addComponent(load); + } + + // Add faults + for (const auto& faultdata : data.bus_fault) + { + auto* fault = new BusFault(getBus(faultdata.bus_id), faultdata); + addComponent(fault); + } + + // Add generators + for (const auto& gendata : data.genrou) + { + auto* gen = new Genrou(getBus(gendata.bus_id), gendata); + addComponent(gen); + } + + } + /** * @brief Destructor for the system model */ @@ -650,6 +706,13 @@ namespace GridKit components_.push_back(component); } + bus_type* getBus(IdxT busid) + { + // Need to implement mapping of bus IDs to buses in the system model + assert((buses_[busid])->BusID() == busid); + return buses_[busid]; + } + private: std::vector buses_; std::vector components_; diff --git a/src/Model/PhasorDynamics/SystemModelData.hpp b/src/Model/PhasorDynamics/SystemModelData.hpp new file mode 100644 index 000000000..2fe06dd3e --- /dev/null +++ b/src/Model/PhasorDynamics/SystemModelData.hpp @@ -0,0 +1,40 @@ +#include +#include +#include +#include +#include + +namespace GridKit +{ + namespace PhasorDynamics + { + template + class SystemModelData + { + using BranchDataT = BranchData; + using BusDataT = BusData; + using BusFaultDataT = BusFaultData; + using GenrouDataT = GenrouData; + using LoadDataT = LoadData; + + // Header info + unsigned short format_version; + unsigned short format_revision; + std::string case_name; + std::string case_date_time; + std::string case_description; + std::string case_comments; + RealT freq_base; + RealT va_base; + + // Bus data + std::vector bus; + + // Component data + std::vector branch; + std::vector bus_fault; + std::vector genrou; + std::vector load; + }; + } // namespace PhasorDynamics +} // namespace GridKit \ No newline at end of file From 3c389095ef4bcdb184e6ac9b21230fee229cc444 Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Thu, 12 Jun 2025 11:14:47 -0400 Subject: [PATCH 03/15] Use SystemModelData to instantiate system in phasor dynamic Example 1. --- examples/PhasorDynamics/Example1/example1.cpp | 103 ++++++++++-------- src/Model/PhasorDynamics/SystemModel.hpp | 2 +- src/Model/PhasorDynamics/SystemModelData.hpp | 4 +- 3 files changed, 63 insertions(+), 46 deletions(-) diff --git a/examples/PhasorDynamics/Example1/example1.cpp b/examples/PhasorDynamics/Example1/example1.cpp index ac42fc236..4e6cd8445 100644 --- a/examples/PhasorDynamics/Example1/example1.cpp +++ b/examples/PhasorDynamics/Example1/example1.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -40,55 +41,69 @@ int main() // // Create model data // - BusData bus_data_1; - bus_data_1.Vr0 = 0.9949877346411762; - bus_data_1.Vi0 = 0.09999703952427966; - - BusData bus_data_2; - bus_data_2.Vr0 = 1.0; - bus_data_2.Vi0 = 0.0; - - BranchData branch_data_1_2; - branch_data_1_2.R = 0.0; - branch_data_1_2.X = 0.1; - branch_data_1_2.G = 0.0; - branch_data_1_2.B = 0.0; - - GenrouData gen_data_1; - gen_data_1.unit_id = 1; - gen_data_1.p0 = 1.; - gen_data_1.q0 = 0.05013; - gen_data_1.H = 3.; - gen_data_1.D = 0.; - gen_data_1.Ra = 0.; - gen_data_1.Tdop = 7.; - gen_data_1.Tdopp = .04; - gen_data_1.Tqopp = .05; - gen_data_1.Tqop = .75; - gen_data_1.Xd = 2.1; - gen_data_1.Xdp = 0.2; - gen_data_1.Xdpp = 0.18; - gen_data_1.Xq = 0.5; - gen_data_1.Xqp = 0.5; - gen_data_1.Xqpp = 0.18; - gen_data_1.Xl = 0.15; - gen_data_1.S10 = 0.; - gen_data_1.S12 = 0.; - - BusFaultData bus_fault_data_1; - bus_fault_data_1.R = 0.0; - bus_fault_data_1.X = 1e-3; - bus_fault_data_1.status = false; + + SystemModelData data; + + // Set bus data + data.bus.resize(2); + + data.bus[0].bus_id = 0; + data.bus[0].Vr0 = 0.9949877346411762; + data.bus[0].Vi0 = 0.09999703952427966; + + data.bus[1].bus_id = 1; + data.bus[1].Vr0 = 1.0; + data.bus[1].Vi0 = 0.0; + + // Set branch data + data.branch.resize(1); + + data.branch[0].bus1_id = data.bus[0].bus_id; + data.branch[0].bus2_id = data.bus[1].bus_id; + data.branch[0].R = 0.0; + data.branch[0].X = 0.1; + data.branch[0].G = 0.0; + data.branch[0].B = 0.0; + + // Set generator data + data.genrou.resize(1); + + data.genrou[0].unit_id = 1; + data.genrou[0].p0 = 1.; + data.genrou[0].q0 = 0.05013; + data.genrou[0].H = 3.; + data.genrou[0].D = 0.; + data.genrou[0].Ra = 0.; + data.genrou[0].Tdop = 7.; + data.genrou[0].Tdopp = .04; + data.genrou[0].Tqopp = .05; + data.genrou[0].Tqop = .75; + data.genrou[0].Xd = 2.1; + data.genrou[0].Xdp = 0.2; + data.genrou[0].Xdpp = 0.18; + data.genrou[0].Xq = 0.5; + data.genrou[0].Xqp = 0.5; + data.genrou[0].Xqpp = 0.18; + data.genrou[0].Xl = 0.15; + data.genrou[0].S10 = 0.; + data.genrou[0].S12 = 0.; + + // Add faults + data.bus_fault.resize(1); + + data.bus_fault[0].R = 0.0; + data.bus_fault[0].X = 1e-3; + data.bus_fault[0].status = false; // // Instantiate model components // - Bus bus1(bus_data_1); - BusInfinite bus2(bus_data_2); - Branch branch(&bus1, &bus2, branch_data_1_2); - BusFault fault(&bus1, bus_fault_data_1); - Genrou gen(&bus1, gen_data_1); + Bus bus1(data.bus[0]); + BusInfinite bus2(data.bus[1]); + Branch branch(&bus1, &bus2, data.branch[0]); + BusFault fault(&bus1, data.bus_fault[0]); + Genrou gen(&bus1, data.genrou[0]); // // Create the 2-bus system diff --git a/src/Model/PhasorDynamics/SystemModel.hpp b/src/Model/PhasorDynamics/SystemModel.hpp index c3cacb37c..ce336cfa5 100644 --- a/src/Model/PhasorDynamics/SystemModel.hpp +++ b/src/Model/PhasorDynamics/SystemModel.hpp @@ -87,7 +87,7 @@ namespace GridKit // Add electrical buses for (const auto& busdata : data.bus) { - BusBase* bus = new Bus(busdata); + BusBase* bus = BusFactory::create(busdata); addBus(bus); } diff --git a/src/Model/PhasorDynamics/SystemModelData.hpp b/src/Model/PhasorDynamics/SystemModelData.hpp index 2fe06dd3e..f9ecdee1b 100644 --- a/src/Model/PhasorDynamics/SystemModelData.hpp +++ b/src/Model/PhasorDynamics/SystemModelData.hpp @@ -1,3 +1,5 @@ +#pragma once + #include #include #include @@ -9,7 +11,7 @@ namespace GridKit namespace PhasorDynamics { template - class SystemModelData + struct SystemModelData { using BranchDataT = BranchData; using BusDataT = BusData; From a646cd36ab3b2b6a76c5c8f71c789e32c5ac7511 Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Thu, 12 Jun 2025 15:58:22 -0400 Subject: [PATCH 04/15] Functioning Example1 with system composer. --- examples/PhasorDynamics/Example1/example1.cpp | 30 +++++----- src/Model/PhasorDynamics/Branch/Branch.cpp | 2 +- src/Model/PhasorDynamics/Branch/Branch.hpp | 2 +- src/Model/PhasorDynamics/Bus/Bus.cpp | 2 +- src/Model/PhasorDynamics/Bus/Bus.hpp | 2 +- src/Model/PhasorDynamics/Bus/BusFactory.hpp | 4 +- src/Model/PhasorDynamics/Bus/BusInfinite.cpp | 2 +- src/Model/PhasorDynamics/Bus/BusInfinite.hpp | 2 +- .../PhasorDynamics/BusFault/BusFault.cpp | 2 +- .../PhasorDynamics/BusFault/BusFault.hpp | 2 +- src/Model/PhasorDynamics/Load/Load.cpp | 58 +++++++++---------- src/Model/PhasorDynamics/Load/Load.hpp | 2 +- src/Model/PhasorDynamics/Load/LoadImpl.hpp | 2 +- .../SynchronousMachine/GENROUwS/Genrou.cpp | 2 +- .../SynchronousMachine/GENROUwS/Genrou.hpp | 2 +- src/Model/PhasorDynamics/SystemModel.hpp | 27 +++++++-- 16 files changed, 81 insertions(+), 62 deletions(-) diff --git a/examples/PhasorDynamics/Example1/example1.cpp b/examples/PhasorDynamics/Example1/example1.cpp index 4e6cd8445..15742c818 100644 --- a/examples/PhasorDynamics/Example1/example1.cpp +++ b/examples/PhasorDynamics/Example1/example1.cpp @@ -48,10 +48,12 @@ int main() data.bus.resize(2); data.bus[0].bus_id = 0; + data.bus[0].bus_type = BusData::DEFAULT; data.bus[0].Vr0 = 0.9949877346411762; data.bus[0].Vi0 = 0.09999703952427966; data.bus[1].bus_id = 1; + data.bus[1].bus_type = BusData::SLACK; data.bus[1].Vr0 = 1.0; data.bus[1].Vi0 = 0.0; @@ -99,24 +101,26 @@ int main() // Instantiate model components // - Bus bus1(data.bus[0]); - BusInfinite bus2(data.bus[1]); - Branch branch(&bus1, &bus2, data.branch[0]); - BusFault fault(&bus1, data.bus_fault[0]); - Genrou gen(&bus1, data.genrou[0]); + // Bus bus1(data.bus[0]); + // BusInfinite bus2(data.bus[1]); + // Branch branch(&bus1, &bus2, data.branch[0]); + // BusFault fault(&bus1, data.bus_fault[0]); + // Genrou gen(&bus1, data.genrou[0]); // // Create the 2-bus system // - SystemModel sys; - sys.addBus(&bus1); - sys.addBus(&bus2); - sys.addComponent(&branch); - sys.addComponent(&fault); - sys.addComponent(&gen); + SystemModel sys(data); + // sys.addBus(&bus1); + // sys.addBus(&bus2); + // sys.addComponent(&branch); + // sys.addComponent(&fault); + // sys.addComponent(&gen); sys.allocate(); + auto* fault = dynamic_cast*>(sys.getComponent(1)); + // Set time step to 1/4 of a 60Hz cycle real_type dt = 1.0 / 4.0 / 60.0; @@ -168,13 +172,13 @@ int main() ida.runSimulation(1.0, nout, output_cb); // Introduce fault and run for the next 0.1s - fault.setStatus(true); + fault->setStatus(true); ida.initializeSimulation(1.0, false); nout = static_cast(std::round((1.1 - 1.0) / dt)); ida.runSimulation(1.1, nout, output_cb); // Clear the fault and run until t = 10s. - fault.setStatus(false); + fault->setStatus(false); ida.initializeSimulation(1.1, false); nout = static_cast(std::round((10.0 - 1.1) / dt)); ida.runSimulation(10.0, nout, output_cb); diff --git a/src/Model/PhasorDynamics/Branch/Branch.cpp b/src/Model/PhasorDynamics/Branch/Branch.cpp index 5132a7a8d..effc8bd5c 100644 --- a/src/Model/PhasorDynamics/Branch/Branch.cpp +++ b/src/Model/PhasorDynamics/Branch/Branch.cpp @@ -73,7 +73,7 @@ namespace GridKit } template - Branch::Branch(bus_type* bus1, bus_type* bus2, model_data_type& data) + Branch::Branch(bus_type* bus1, bus_type* bus2, const model_data_type& data) : bus1_(bus1), bus2_(bus2), R_(data.R), diff --git a/src/Model/PhasorDynamics/Branch/Branch.hpp b/src/Model/PhasorDynamics/Branch/Branch.hpp index cf3cba0e1..caefa491f 100644 --- a/src/Model/PhasorDynamics/Branch/Branch.hpp +++ b/src/Model/PhasorDynamics/Branch/Branch.hpp @@ -53,7 +53,7 @@ namespace GridKit public: Branch(bus_type* bus1, bus_type* bus2); Branch(bus_type* bus1, bus_type* bus2, real_type R, real_type X, real_type G, real_type B); - Branch(bus_type* bus1, bus_type* bus2, model_data_type& data); + Branch(bus_type* bus1, bus_type* bus2, const model_data_type& data); virtual ~Branch(); virtual int allocate() override; diff --git a/src/Model/PhasorDynamics/Bus/Bus.cpp b/src/Model/PhasorDynamics/Bus/Bus.cpp index d8a1a3481..03473c8dd 100644 --- a/src/Model/PhasorDynamics/Bus/Bus.cpp +++ b/src/Model/PhasorDynamics/Bus/Bus.cpp @@ -61,7 +61,7 @@ namespace GridKit * @param[in] data - structure with bus data */ template - Bus::Bus(DataT& data) + Bus::Bus(const DataT& data) : BusBase(data.bus_id), Vr0_(data.Vr0), Vi0_(data.Vi0) diff --git a/src/Model/PhasorDynamics/Bus/Bus.hpp b/src/Model/PhasorDynamics/Bus/Bus.hpp index 140f83deb..11dda1be8 100644 --- a/src/Model/PhasorDynamics/Bus/Bus.hpp +++ b/src/Model/PhasorDynamics/Bus/Bus.hpp @@ -43,7 +43,7 @@ namespace GridKit Bus(); Bus(ScalarT Vr, ScalarT Vi); - Bus(DataT& data); + Bus(const DataT& data); virtual ~Bus(); virtual int allocate() override; diff --git a/src/Model/PhasorDynamics/Bus/BusFactory.hpp b/src/Model/PhasorDynamics/Bus/BusFactory.hpp index d3ea14758..34eae481e 100644 --- a/src/Model/PhasorDynamics/Bus/BusFactory.hpp +++ b/src/Model/PhasorDynamics/Bus/BusFactory.hpp @@ -18,7 +18,7 @@ namespace GridKit BusFactory() = delete; - static BusBase* create(BusData& data) + static BusBase* create(const BusData& data) { BusBase* bus = nullptr; @@ -32,7 +32,7 @@ namespace GridKit break; default: // Throw exception - std::cout << "Bus type " << data.type << " unrecognized.\n"; + std::cout << "Bus type " << data.bus_type << " unrecognized.\n"; } return bus; } diff --git a/src/Model/PhasorDynamics/Bus/BusInfinite.cpp b/src/Model/PhasorDynamics/Bus/BusInfinite.cpp index 6f4378d65..f1e96a339 100644 --- a/src/Model/PhasorDynamics/Bus/BusInfinite.cpp +++ b/src/Model/PhasorDynamics/Bus/BusInfinite.cpp @@ -66,7 +66,7 @@ namespace GridKit * @param[in] data - structure with bus data */ template - BusInfinite::BusInfinite(DataT& data) + BusInfinite::BusInfinite(const DataT& data) : BusBase(data.bus_id), Vr_(data.Vr0), Vi_(data.Vi0) diff --git a/src/Model/PhasorDynamics/Bus/BusInfinite.hpp b/src/Model/PhasorDynamics/Bus/BusInfinite.hpp index e63a1fa42..b7247401f 100644 --- a/src/Model/PhasorDynamics/Bus/BusInfinite.hpp +++ b/src/Model/PhasorDynamics/Bus/BusInfinite.hpp @@ -41,7 +41,7 @@ namespace GridKit BusInfinite(); BusInfinite(ScalarT Vr, ScalarT Vi); - BusInfinite(DataT& data); + BusInfinite(const DataT& data); virtual ~BusInfinite(); virtual int allocate() override; diff --git a/src/Model/PhasorDynamics/BusFault/BusFault.cpp b/src/Model/PhasorDynamics/BusFault/BusFault.cpp index 727997721..597f20cbf 100644 --- a/src/Model/PhasorDynamics/BusFault/BusFault.cpp +++ b/src/Model/PhasorDynamics/BusFault/BusFault.cpp @@ -64,7 +64,7 @@ namespace GridKit * @param bus2 - pointer to bus-2 */ template - BusFault::BusFault(bus_type* bus, DataT& data) + BusFault::BusFault(bus_type* bus, const DataT& data) : bus_(bus), R_(data.R), X_(data.X), diff --git a/src/Model/PhasorDynamics/BusFault/BusFault.hpp b/src/Model/PhasorDynamics/BusFault/BusFault.hpp index 8963a7b30..72be0717f 100644 --- a/src/Model/PhasorDynamics/BusFault/BusFault.hpp +++ b/src/Model/PhasorDynamics/BusFault/BusFault.hpp @@ -43,7 +43,7 @@ namespace GridKit public: BusFault(bus_type* bus); BusFault(bus_type* bus, real_type R, real_type X, int status); - BusFault(bus_type* bus, DataT& data); + BusFault(bus_type* bus, const DataT& data); ~BusFault() = default; int allocate() override; diff --git a/src/Model/PhasorDynamics/Load/Load.cpp b/src/Model/PhasorDynamics/Load/Load.cpp index bbc187904..8f130cbae 100644 --- a/src/Model/PhasorDynamics/Load/Load.cpp +++ b/src/Model/PhasorDynamics/Load/Load.cpp @@ -1,29 +1,29 @@ - -#include "LoadImpl.hpp" - -namespace GridKit -{ - namespace PhasorDynamics - { - /** - * @brief Jacobian evaluation not implemented - * - * @tparam ScalarT - scalar data type - * @tparam IdxT - matrix index data type - * @return int - error code, 0 = success - */ - template - int Load::evaluateJacobian() - { - std::cout << "Evaluate Jacobian for Load..." << std::endl; - std::cout << "Jacobian evaluation is not implemented!" << std::endl; - - return 0; - } - - // Available template instantiations - template class Load; - template class Load; - - } // namespace PhasorDynamics -} // namespace GridKit + +#include "LoadImpl.hpp" + +namespace GridKit +{ + namespace PhasorDynamics + { + /** + * @brief Jacobian evaluation not implemented + * + * @tparam ScalarT - scalar data type + * @tparam IdxT - matrix index data type + * @return int - error code, 0 = success + */ + template + int Load::evaluateJacobian() + { + std::cout << "Evaluate Jacobian for Load..." << std::endl; + std::cout << "Jacobian evaluation is not implemented!" << std::endl; + + return 0; + } + + // Available template instantiations + template class Load; + template class Load; + + } // namespace PhasorDynamics +} // namespace GridKit diff --git a/src/Model/PhasorDynamics/Load/Load.hpp b/src/Model/PhasorDynamics/Load/Load.hpp index ee20f428b..928898c9a 100644 --- a/src/Model/PhasorDynamics/Load/Load.hpp +++ b/src/Model/PhasorDynamics/Load/Load.hpp @@ -47,7 +47,7 @@ namespace GridKit Load(bus_type* bus); Load(bus_type* bus, real_type R, real_type X); Load(bus_type* bus, IdxT component_id); - Load(bus_type* bus, model_data_type& data); + Load(bus_type* bus, const model_data_type& data); virtual ~Load(); virtual int allocate() override; diff --git a/src/Model/PhasorDynamics/Load/LoadImpl.hpp b/src/Model/PhasorDynamics/Load/LoadImpl.hpp index e8cfbd2ba..36b016a4a 100644 --- a/src/Model/PhasorDynamics/Load/LoadImpl.hpp +++ b/src/Model/PhasorDynamics/Load/LoadImpl.hpp @@ -39,7 +39,7 @@ namespace GridKit template Load::Load(bus_type* bus, - model_data_type& data) + const model_data_type& data) : bus_(bus), R_(data.R), X_(data.X) diff --git a/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/Genrou.cpp b/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/Genrou.cpp index 55895d50b..31b7982db 100644 --- a/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/Genrou.cpp +++ b/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/Genrou.cpp @@ -119,7 +119,7 @@ namespace GridKit * */ template - Genrou::Genrou(bus_type* bus, model_data_type& data) + Genrou::Genrou(bus_type* bus, const model_data_type& data) : bus_(bus), busID_(0), unit_id_(data.unit_id), diff --git a/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/Genrou.hpp b/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/Genrou.hpp index 283840840..305d47966 100644 --- a/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/Genrou.hpp +++ b/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/Genrou.hpp @@ -52,7 +52,7 @@ namespace GridKit public: Genrou(bus_type* bus, IdxT unit_id); - Genrou(bus_type* bus, model_data_type& data); + Genrou(bus_type* bus, const model_data_type& data); Genrou(bus_type* bus, IdxT unit_id, ScalarT p0, diff --git a/src/Model/PhasorDynamics/SystemModel.hpp b/src/Model/PhasorDynamics/SystemModel.hpp index ce336cfa5..d38a6707c 100644 --- a/src/Model/PhasorDynamics/SystemModel.hpp +++ b/src/Model/PhasorDynamics/SystemModel.hpp @@ -15,6 +15,7 @@ // #include #include #include +#include namespace GridKit @@ -98,12 +99,12 @@ namespace GridKit addComponent(branch); } - // Add loads - for (const auto& loaddata : data.load) - { - auto* load = new Genrou(getBus(loaddata.bus_id), loaddata); - addComponent(load); - } + // // Add loads + // for (const auto& loaddata : data.load) + // { + // auto* load = new Load(getBus(loaddata.bus_id), loaddata); + // addComponent(load); + // } // Add faults for (const auto& faultdata : data.bus_fault) @@ -713,6 +714,20 @@ namespace GridKit return buses_[busid]; } + /** + * @brief Get the Component object + * + * For now, this is an ugly hack to get an access to + * a component from outside the system model. + * + * @param comp_id + * @return Component* + */ + component_type* getComponent(IdxT comp_id) + { + return components_[comp_id]; + } + private: std::vector buses_; std::vector components_; From 5bc6a98bff55f0e1ff86c82698f0b2be6d105c7c Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Thu, 12 Jun 2025 16:21:27 -0400 Subject: [PATCH 05/15] Adding loads to system solver class causes linking error. --- src/Model/PhasorDynamics/SystemModel.hpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/Model/PhasorDynamics/SystemModel.hpp b/src/Model/PhasorDynamics/SystemModel.hpp index d38a6707c..005b7327d 100644 --- a/src/Model/PhasorDynamics/SystemModel.hpp +++ b/src/Model/PhasorDynamics/SystemModel.hpp @@ -9,10 +9,9 @@ #include #include -#include // Temporary +#include #include -// #include #include #include #include @@ -99,12 +98,12 @@ namespace GridKit addComponent(branch); } - // // Add loads - // for (const auto& loaddata : data.load) - // { - // auto* load = new Load(getBus(loaddata.bus_id), loaddata); - // addComponent(load); - // } + // Add loads + for (const auto& loaddata : data.load) + { + auto* load = new Load(getBus(loaddata.bus_id), loaddata); + addComponent(load); + } // Add faults for (const auto& faultdata : data.bus_fault) From f40090f5da98f4f26edc7c70212c1bb629e345ec Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Thu, 12 Jun 2025 17:21:31 -0400 Subject: [PATCH 06/15] Fix linking error. --- examples/PhasorDynamics/Example1/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/PhasorDynamics/Example1/CMakeLists.txt b/examples/PhasorDynamics/Example1/CMakeLists.txt index e79e6103b..d0e498a5e 100644 --- a/examples/PhasorDynamics/Example1/CMakeLists.txt +++ b/examples/PhasorDynamics/Example1/CMakeLists.txt @@ -4,6 +4,7 @@ target_link_libraries(phasordynamics_example1 GRIDKIT::phasor_dynamics_bus_fault GRIDKIT::phasor_dynamics_branch GRIDKIT::phasor_dynamics_genrou + GRIDKIT::phasor_dynamics_load GRIDKIT::solvers_dyn) install(TARGETS phasordynamics_example1 RUNTIME DESTINATION bin) From ebbdf36f06aa726d1e5d57dc890114c6d66b9217 Mon Sep 17 00:00:00 2001 From: Slaven Peles Date: Thu, 12 Jun 2025 17:58:26 -0400 Subject: [PATCH 07/15] Add separate container for system faults. --- examples/PhasorDynamics/Example1/example1.cpp | 2 +- src/Model/PhasorDynamics/SystemModel.hpp | 14 +++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/examples/PhasorDynamics/Example1/example1.cpp b/examples/PhasorDynamics/Example1/example1.cpp index 15742c818..b5c3972a8 100644 --- a/examples/PhasorDynamics/Example1/example1.cpp +++ b/examples/PhasorDynamics/Example1/example1.cpp @@ -119,7 +119,7 @@ int main() // sys.addComponent(&gen); sys.allocate(); - auto* fault = dynamic_cast*>(sys.getComponent(1)); + auto* fault = dynamic_cast*>(sys.getFault(0)); // Set time step to 1/4 of a 60Hz cycle real_type dt = 1.0 / 4.0 / 60.0; diff --git a/src/Model/PhasorDynamics/SystemModel.hpp b/src/Model/PhasorDynamics/SystemModel.hpp index 005b7327d..8eea57a04 100644 --- a/src/Model/PhasorDynamics/SystemModel.hpp +++ b/src/Model/PhasorDynamics/SystemModel.hpp @@ -109,7 +109,7 @@ namespace GridKit for (const auto& faultdata : data.bus_fault) { auto* fault = new BusFault(getBus(faultdata.bus_id), faultdata); - addComponent(fault); + addFault(fault); } // Add generators @@ -706,6 +706,12 @@ namespace GridKit components_.push_back(component); } + void addFault(component_type* component) + { + components_.push_back(component); + faults_.push_back(component); + } + bus_type* getBus(IdxT busid) { // Need to implement mapping of bus IDs to buses in the system model @@ -727,9 +733,15 @@ namespace GridKit return components_[comp_id]; } + component_type* getFault(IdxT fault_id) + { + return faults_[fault_id]; + } + private: std::vector buses_; std::vector components_; + std::vector faults_; }; // class SystemModel From ef479943448704dc8c30c0447412b2ba36096374 Mon Sep 17 00:00:00 2001 From: pelesh Date: Thu, 12 Jun 2025 19:13:29 -0400 Subject: [PATCH 08/15] Cleaner way to access faults from the example. --- examples/PhasorDynamics/Example1/example1.cpp | 20 ++---------- src/Model/PhasorDynamics/SystemModel.hpp | 32 +++++++------------ 2 files changed, 14 insertions(+), 38 deletions(-) diff --git a/examples/PhasorDynamics/Example1/example1.cpp b/examples/PhasorDynamics/Example1/example1.cpp index b5c3972a8..222b00439 100644 --- a/examples/PhasorDynamics/Example1/example1.cpp +++ b/examples/PhasorDynamics/Example1/example1.cpp @@ -98,28 +98,14 @@ int main() data.bus_fault[0].status = false; // - // Instantiate model components - // - - // Bus bus1(data.bus[0]); - // BusInfinite bus2(data.bus[1]); - // Branch branch(&bus1, &bus2, data.branch[0]); - // BusFault fault(&bus1, data.bus_fault[0]); - // Genrou gen(&bus1, data.genrou[0]); - - // - // Create the 2-bus system + // Instantiate system model // SystemModel sys(data); - // sys.addBus(&bus1); - // sys.addBus(&bus2); - // sys.addComponent(&branch); - // sys.addComponent(&fault); - // sys.addComponent(&gen); sys.allocate(); - auto* fault = dynamic_cast*>(sys.getFault(0)); + // Get access to the fault + auto* fault = sys.getBusFault(0); // Set time step to 1/4 of a 60Hz cycle real_type dt = 1.0 / 4.0 / 60.0; diff --git a/src/Model/PhasorDynamics/SystemModel.hpp b/src/Model/PhasorDynamics/SystemModel.hpp index 8eea57a04..8e16f1193 100644 --- a/src/Model/PhasorDynamics/SystemModel.hpp +++ b/src/Model/PhasorDynamics/SystemModel.hpp @@ -4,18 +4,17 @@ #include #include -#include #include #include +#include #include // Temporary +#include #include -#include #include -#include #include - +#include namespace GridKit { @@ -74,8 +73,8 @@ namespace GridKit /** * @brief Construct a new System Model object - * - * @param[in] data - Data structure with complete system data + * + * @param[in] data - Data structure with complete system data */ SystemModel(SystemModelData& data) { @@ -118,7 +117,6 @@ namespace GridKit auto* gen = new Genrou(getBus(gendata.bus_id), gendata); addComponent(gen); } - } /** @@ -720,22 +718,14 @@ namespace GridKit } /** - * @brief Get the Component object - * - * For now, this is an ugly hack to get an access to - * a component from outside the system model. - * - * @param comp_id - * @return Component* + * @brief Return pointer to a bus fault model + * + * @warning This is a hack to get access to bus faults in examples. + * A more comprehensive solution is needed. */ - component_type* getComponent(IdxT comp_id) - { - return components_[comp_id]; - } - - component_type* getFault(IdxT fault_id) + BusFault* getBusFault(IdxT fault_id) { - return faults_[fault_id]; + return dynamic_cast*>(faults_[fault_id]); } private: From c651bca5a1460fffa86da78dd6ac3ce7b79fad8f Mon Sep 17 00:00:00 2001 From: pelesh Date: Thu, 12 Jun 2025 19:46:13 -0400 Subject: [PATCH 09/15] Use system composer for phasor dynamics Example 2. --- examples/PhasorDynamics/Example2/example2.cpp | 228 +++++++++--------- 1 file changed, 116 insertions(+), 112 deletions(-) diff --git a/examples/PhasorDynamics/Example2/example2.cpp b/examples/PhasorDynamics/Example2/example2.cpp index 8a9cbc15f..41dd4cc45 100644 --- a/examples/PhasorDynamics/Example2/example2.cpp +++ b/examples/PhasorDynamics/Example2/example2.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -88,131 +89,134 @@ int main() std::cout << "Example 2 version 1\n"; // - // Create (load) model data + // Create model data // + SystemModelData data; + + // Set bus data + data.bus.resize(3); + + // Bus 0 + data.bus[0].bus_id = 0; + data.bus[0].bus_type = BusData::SLACK; + data.bus[0].Vr0 = 1.06; + data.bus[0].Vi0 = 0.0; + // Bus 1 - BusData bus_data_1; - bus_data_1.Vr0 = 1.06; - bus_data_1.Vi0 = 0.0; + data.bus[1].bus_id = 1; + data.bus[1].bus_type = BusData::DEFAULT; + data.bus[1].Vr0 = 1.0599558398065716; + data.bus[1].Vi0 = -0.009675621941024773; // Bus 2 - BusData bus_data_2; - bus_data_2.Vr0 = 1.0599558398065716; - bus_data_2.Vi0 = -0.009675621941024773; - - // Bus 3 - BusData bus_data_3; - bus_data_3.Vr0 = 0.9610827543495831; - bus_data_3.Vi0 = -0.13122476630506485; + data.bus[2].bus_id = 2; + data.bus[2].bus_type = BusData::DEFAULT; + data.bus[2].Vr0 = 0.9610827543495831; + data.bus[2].Vi0 = -0.13122476630506485; + + // Set branch data + data.branch.resize(3); + + // Branch 0-1 + data.branch[0].bus1_id = data.bus[0].bus_id; + data.branch[0].bus2_id = data.bus[1].bus_id; + data.branch[0].R = 0.05; + data.branch[0].X = 0.21; + data.branch[0].G = 0; + data.branch[0].B = 0.1; + + // Branch 0-2 + data.branch[1].bus1_id = data.bus[0].bus_id; + data.branch[1].bus2_id = data.bus[2].bus_id; + data.branch[1].R = 0.06; + data.branch[1].X = 0.15; + data.branch[1].G = 0; + data.branch[1].B = 0.12; // Branch 1-2 - BranchData branch_data_1_2; - branch_data_1_2.R = 0.05; - branch_data_1_2.X = 0.21; - branch_data_1_2.G = 0; - branch_data_1_2.B = 0.1; - - // Branch 1-3 - BranchData branch_data_1_3; - branch_data_1_3.R = 0.06; - branch_data_1_3.X = 0.15; - branch_data_1_3.G = 0; - branch_data_1_3.B = 0.12; - - // Branch 2-3 - BranchData branch_data_2_3; - branch_data_2_3.R = 0.08; - branch_data_2_3.X = 0.27; - branch_data_2_3.G = 0; - branch_data_2_3.B = 0.45; + data.branch[2].bus1_id = data.bus[1].bus_id; + data.branch[2].bus2_id = data.bus[2].bus_id; + data.branch[2].R = 0.08; + data.branch[2].X = 0.27; + data.branch[2].G = 0; + data.branch[2].B = 0.45; + + // Set generator data + data.genrou.resize(2); + + // Generator on bus 1 + data.genrou[0].bus_id = 1; + data.genrou[0].unit_id = 0; + data.genrou[0].p0 = 0.5; + data.genrou[0].q0 = -0.07588; + data.genrou[0].H = 2.7; + data.genrou[0].D = 0.; + data.genrou[0].Ra = 0.; + data.genrou[0].Tdop = 7.; + data.genrou[0].Tdopp = .04; + data.genrou[0].Tqopp = .05; + data.genrou[0].Tqop = .75; + data.genrou[0].Xd = 1.9; + data.genrou[0].Xdp = 0.17; + data.genrou[0].Xdpp = 0.15; + data.genrou[0].Xq = 0.4; + data.genrou[0].Xqp = 0.35; + data.genrou[0].Xqpp = 0.15; + data.genrou[0].Xl = 0.14999; + data.genrou[0].S10 = 0.; + data.genrou[0].S12 = 0.; // Generator on bus 2 - GenrouData gen_data_2; - gen_data_2.unit_id = 1; - gen_data_2.p0 = 0.5; - gen_data_2.q0 = -0.07588; - gen_data_2.H = 2.7; - gen_data_2.D = 0.; - gen_data_2.Ra = 0.; - gen_data_2.Tdop = 7.; - gen_data_2.Tdopp = .04; - gen_data_2.Tqopp = .05; - gen_data_2.Tqop = .75; - gen_data_2.Xd = 1.9; - gen_data_2.Xdp = 0.17; - gen_data_2.Xdpp = 0.15; - gen_data_2.Xq = 0.4; - gen_data_2.Xqp = 0.35; - gen_data_2.Xqpp = 0.15; - gen_data_2.Xl = 0.14999; - gen_data_2.S10 = 0.; - gen_data_2.S12 = 0.; - - // Generator on bus 3 - GenrouData gen_data_3; - gen_data_3.unit_id = 1; - gen_data_3.p0 = 0.25; - gen_data_3.q0 = 0.26587; - gen_data_3.H = 1.6; - gen_data_3.D = 0.; - gen_data_3.Ra = 0.; - gen_data_3.Tdop = 7.5; - gen_data_3.Tdopp = .04; - gen_data_3.Tqopp = .05; - gen_data_3.Tqop = .75; - gen_data_3.Xd = 2.3; - gen_data_3.Xdp = 0.2; - gen_data_3.Xdpp = 0.18; - gen_data_3.Xq = 0.5; - gen_data_3.Xqp = 0.5; - gen_data_3.Xqpp = 0.18; - gen_data_3.Xl = 0.15; - gen_data_3.S10 = 0.; - gen_data_3.S12 = 0.; - - // Load on bus 3 - LoadData load_data_3; - load_data_3.R = 0.4447197839297772; - load_data_3.X = 0.20330047265361242; - load_data_3.bus_id = 3; - - BusFaultData bus_fault_data_3; - bus_fault_data_3.R = 0.0; - bus_fault_data_3.X = 1e-5; - bus_fault_data_3.status = false; + data.genrou[1].bus_id = 2; + data.genrou[1].unit_id = 1; + data.genrou[1].p0 = 0.25; + data.genrou[1].q0 = 0.26587; + data.genrou[1].H = 1.6; + data.genrou[1].D = 0.; + data.genrou[1].Ra = 0.; + data.genrou[1].Tdop = 7.5; + data.genrou[1].Tdopp = .04; + data.genrou[1].Tqopp = .05; + data.genrou[1].Tqop = .75; + data.genrou[1].Xd = 2.3; + data.genrou[1].Xdp = 0.2; + data.genrou[1].Xdpp = 0.18; + data.genrou[1].Xq = 0.5; + data.genrou[1].Xqp = 0.5; + data.genrou[1].Xqpp = 0.18; + data.genrou[1].Xl = 0.15; + data.genrou[1].S10 = 0.; + data.genrou[1].S12 = 0.; + + // Set load data + data.load.resize(1); + + // Load on bus 2 + // LoadData data.load[0]; + data.load[0].bus_id = 2; + data.load[0].R = 0.4447197839297772; + data.load[0].X = 0.20330047265361242; + + // Set fault data + data.bus_fault.resize(1); + + // BusFaultData data.bus_fault[0]; + data.bus_fault[0].bus_id = 2; + data.bus_fault[0].R = 0.0; + data.bus_fault[0].X = 1e-5; + data.bus_fault[0].status = false; // - // Instantiate model components + // Instantiate system // - BusInfinite bus1(bus_data_1); - Bus bus2(bus_data_2); - Bus bus3(bus_data_3); - - Branch branch12(&bus1, &bus2, branch_data_1_2); - Branch branch13(&bus1, &bus3, branch_data_1_3); - Branch branch23(&bus2, &bus3, branch_data_2_3); - - Genrou gen2(&bus2, gen_data_2); - Genrou gen3(&bus3, gen_data_3); - Load load3(&bus3, load_data_3); - BusFault fault(&bus3, bus_fault_data_3); - - /* Connect everything together */ - SystemModel sys; - sys.addBus(&bus1); - sys.addBus(&bus2); - sys.addBus(&bus3); - sys.addComponent(&branch12); - sys.addComponent(&branch13); - sys.addComponent(&branch23); - sys.addComponent(&fault); - sys.addComponent(&load3); - sys.addComponent(&gen2); - sys.addComponent(&gen3); + SystemModel sys(data); sys.allocate(); + // Get access to fault 0 + auto* fault = sys.getBusFault(0); + real_type dt = 1.0 / 4.0 / 60.0; std::vector output; @@ -241,13 +245,13 @@ int main() ida.runSimulation(1.0, nout, output_cb); // Introduce fault to ground and run for 0.1s - fault.setStatus(true); + fault->setStatus(true); ida.initializeSimulation(1.0, false); nout = static_cast(std::round((1.1 - 1.0) / dt)); ida.runSimulation(1.1, nout, output_cb); // Clear fault and run until t = 10s. - fault.setStatus(false); + fault->setStatus(false); ida.initializeSimulation(1.1, false); nout = static_cast(std::round((10.0 - 1.1) / dt)); ida.runSimulation(10.0, nout, output_cb); From 719a31989b7fe45c1dee97e1a82c52f8b3fb6ae4 Mon Sep 17 00:00:00 2001 From: pelesh Date: Fri, 13 Jun 2025 00:11:46 +0000 Subject: [PATCH 10/15] Apply pre-commmit fixes --- examples/PhasorDynamics/Example1/example1.cpp | 20 ++++----- examples/PhasorDynamics/Example2/example2.cpp | 42 +++++++++---------- src/Model/PhasorDynamics/Bus/BusData.hpp | 2 +- src/Model/PhasorDynamics/Load/LoadImpl.hpp | 2 +- src/Model/PhasorDynamics/SystemModelData.hpp | 2 +- 5 files changed, 34 insertions(+), 34 deletions(-) diff --git a/examples/PhasorDynamics/Example1/example1.cpp b/examples/PhasorDynamics/Example1/example1.cpp index 222b00439..04c78c5dd 100644 --- a/examples/PhasorDynamics/Example1/example1.cpp +++ b/examples/PhasorDynamics/Example1/example1.cpp @@ -47,25 +47,25 @@ int main() // Set bus data data.bus.resize(2); - data.bus[0].bus_id = 0; + data.bus[0].bus_id = 0; data.bus[0].bus_type = BusData::DEFAULT; - data.bus[0].Vr0 = 0.9949877346411762; - data.bus[0].Vi0 = 0.09999703952427966; + data.bus[0].Vr0 = 0.9949877346411762; + data.bus[0].Vi0 = 0.09999703952427966; - data.bus[1].bus_id = 1; + data.bus[1].bus_id = 1; data.bus[1].bus_type = BusData::SLACK; - data.bus[1].Vr0 = 1.0; - data.bus[1].Vi0 = 0.0; + data.bus[1].Vr0 = 1.0; + data.bus[1].Vi0 = 0.0; // Set branch data data.branch.resize(1); data.branch[0].bus1_id = data.bus[0].bus_id; data.branch[0].bus2_id = data.bus[1].bus_id; - data.branch[0].R = 0.0; - data.branch[0].X = 0.1; - data.branch[0].G = 0.0; - data.branch[0].B = 0.0; + data.branch[0].R = 0.0; + data.branch[0].X = 0.1; + data.branch[0].G = 0.0; + data.branch[0].B = 0.0; // Set generator data data.genrou.resize(1); diff --git a/examples/PhasorDynamics/Example2/example2.cpp b/examples/PhasorDynamics/Example2/example2.cpp index 41dd4cc45..ceab0fb0a 100644 --- a/examples/PhasorDynamics/Example2/example2.cpp +++ b/examples/PhasorDynamics/Example2/example2.cpp @@ -98,22 +98,22 @@ int main() data.bus.resize(3); // Bus 0 - data.bus[0].bus_id = 0; + data.bus[0].bus_id = 0; data.bus[0].bus_type = BusData::SLACK; - data.bus[0].Vr0 = 1.06; - data.bus[0].Vi0 = 0.0; + data.bus[0].Vr0 = 1.06; + data.bus[0].Vi0 = 0.0; // Bus 1 - data.bus[1].bus_id = 1; + data.bus[1].bus_id = 1; data.bus[1].bus_type = BusData::DEFAULT; - data.bus[1].Vr0 = 1.0599558398065716; - data.bus[1].Vi0 = -0.009675621941024773; + data.bus[1].Vr0 = 1.0599558398065716; + data.bus[1].Vi0 = -0.009675621941024773; // Bus 2 - data.bus[2].bus_id = 2; + data.bus[2].bus_id = 2; data.bus[2].bus_type = BusData::DEFAULT; - data.bus[2].Vr0 = 0.9610827543495831; - data.bus[2].Vi0 = -0.13122476630506485; + data.bus[2].Vr0 = 0.9610827543495831; + data.bus[2].Vi0 = -0.13122476630506485; // Set branch data data.branch.resize(3); @@ -121,26 +121,26 @@ int main() // Branch 0-1 data.branch[0].bus1_id = data.bus[0].bus_id; data.branch[0].bus2_id = data.bus[1].bus_id; - data.branch[0].R = 0.05; - data.branch[0].X = 0.21; - data.branch[0].G = 0; - data.branch[0].B = 0.1; + data.branch[0].R = 0.05; + data.branch[0].X = 0.21; + data.branch[0].G = 0; + data.branch[0].B = 0.1; // Branch 0-2 data.branch[1].bus1_id = data.bus[0].bus_id; data.branch[1].bus2_id = data.bus[2].bus_id; - data.branch[1].R = 0.06; - data.branch[1].X = 0.15; - data.branch[1].G = 0; - data.branch[1].B = 0.12; + data.branch[1].R = 0.06; + data.branch[1].X = 0.15; + data.branch[1].G = 0; + data.branch[1].B = 0.12; // Branch 1-2 data.branch[2].bus1_id = data.bus[1].bus_id; data.branch[2].bus2_id = data.bus[2].bus_id; - data.branch[2].R = 0.08; - data.branch[2].X = 0.27; - data.branch[2].G = 0; - data.branch[2].B = 0.45; + data.branch[2].R = 0.08; + data.branch[2].X = 0.27; + data.branch[2].G = 0; + data.branch[2].B = 0.45; // Set generator data data.genrou.resize(2); diff --git a/src/Model/PhasorDynamics/Bus/BusData.hpp b/src/Model/PhasorDynamics/Bus/BusData.hpp index 97690e703..115deb5dd 100644 --- a/src/Model/PhasorDynamics/Bus/BusData.hpp +++ b/src/Model/PhasorDynamics/Bus/BusData.hpp @@ -33,7 +33,7 @@ namespace GridKit RealT Vr0{0.0}; ///< Initial value for real bus voltage RealT Vi0{0.0}; ///< Initial value for imaginary bus voltage - IdxT bus_id{0}; ///< Unique ID of bus 1 + IdxT bus_id{0}; ///< Unique ID of bus 1 BusType bus_type{INVALID}; }; } // namespace PhasorDynamics diff --git a/src/Model/PhasorDynamics/Load/LoadImpl.hpp b/src/Model/PhasorDynamics/Load/LoadImpl.hpp index 36b016a4a..59e46668e 100644 --- a/src/Model/PhasorDynamics/Load/LoadImpl.hpp +++ b/src/Model/PhasorDynamics/Load/LoadImpl.hpp @@ -38,7 +38,7 @@ namespace GridKit } template - Load::Load(bus_type* bus, + Load::Load(bus_type* bus, const model_data_type& data) : bus_(bus), R_(data.R), diff --git a/src/Model/PhasorDynamics/SystemModelData.hpp b/src/Model/PhasorDynamics/SystemModelData.hpp index f9ecdee1b..28696d0af 100644 --- a/src/Model/PhasorDynamics/SystemModelData.hpp +++ b/src/Model/PhasorDynamics/SystemModelData.hpp @@ -39,4 +39,4 @@ namespace GridKit std::vector load; }; } // namespace PhasorDynamics -} // namespace GridKit \ No newline at end of file +} // namespace GridKit From 0eb2bebf0c9035e70a9ede03352eb41fee0c9464 Mon Sep 17 00:00:00 2001 From: pelesh Date: Thu, 12 Jun 2025 20:19:21 -0400 Subject: [PATCH 11/15] If system owns components, the system needs to delete them. --- src/Model/PhasorDynamics/SystemModel.hpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/Model/PhasorDynamics/SystemModel.hpp b/src/Model/PhasorDynamics/SystemModel.hpp index 8e16f1193..91c709945 100644 --- a/src/Model/PhasorDynamics/SystemModel.hpp +++ b/src/Model/PhasorDynamics/SystemModel.hpp @@ -83,6 +83,8 @@ namespace GridKit abs_tol_ = 1e-9; this->max_steps_ = 2000; + owns_components_ = true; + // Add electrical buses for (const auto& busdata : data.bus) { @@ -124,6 +126,19 @@ namespace GridKit */ virtual ~SystemModel() { + if (owns_components_) + { + for (auto component : components_) + { + delete component; + } + + for (auto bus : buses_) + { + delete bus; + } + + } } /** @@ -733,6 +748,8 @@ namespace GridKit std::vector components_; std::vector faults_; + bool owns_components_{false}; + }; // class SystemModel } // namespace PhasorDynamics From 27e9d74b94c3efe117caac3059f2c712c95cf525 Mon Sep 17 00:00:00 2001 From: pelesh Date: Thu, 12 Jun 2025 20:47:16 -0400 Subject: [PATCH 12/15] Add unit test for system constructor. --- tests/UnitTests/PhasorDynamics/CMakeLists.txt | 2 + .../UnitTests/PhasorDynamics/SystemTests.hpp | 66 +++++++++++++++++-- 2 files changed, 61 insertions(+), 7 deletions(-) diff --git a/tests/UnitTests/PhasorDynamics/CMakeLists.txt b/tests/UnitTests/PhasorDynamics/CMakeLists.txt index c8b0a5368..f461ce686 100644 --- a/tests/UnitTests/PhasorDynamics/CMakeLists.txt +++ b/tests/UnitTests/PhasorDynamics/CMakeLists.txt @@ -28,6 +28,8 @@ target_link_libraries(test_phasor_gen_classical GRIDKIT::phasor_dynamics_gen_cla add_executable(test_phasor_system runSystemTests.cpp) target_link_libraries(test_phasor_system GRIDKIT::phasor_dynamics_load GRIDKIT::phasor_dynamics_branch + GRIDKIT::phasor_dynamics_genrou + GRIDKIT::phasor_dynamics_bus_fault GRIDKIT::phasor_dynamics_bus) add_test(NAME PhasorDynamicsBusTest COMMAND $) diff --git a/tests/UnitTests/PhasorDynamics/SystemTests.hpp b/tests/UnitTests/PhasorDynamics/SystemTests.hpp index ea1cf7f29..fb45f2102 100644 --- a/tests/UnitTests/PhasorDynamics/SystemTests.hpp +++ b/tests/UnitTests/PhasorDynamics/SystemTests.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -29,21 +30,72 @@ namespace GridKit { TestStatus success = true; - // ScalarT Vr{1.0}; - // ScalarT Vi{2.0}; - PhasorDynamics::SystemModel* system = nullptr; // Create an empty system system = new PhasorDynamics::SystemModel(); - success *= (system != nullptr); - - if (system) + if (system == nullptr) { - delete system; + std::cout << "Default constructor failed!\n"; + success = false; + return success.report(__func__); } + delete system; + system = nullptr; + + PhasorDynamics::SystemModelData data; + + // Set bus data + data.bus.resize(2); + + // Bus 0 + data.bus[0].bus_id = 0; + data.bus[0].bus_type = PhasorDynamics::BusData::SLACK; + data.bus[0].Vr0 = 10.0; + data.bus[0].Vi0 = 20.0; + + // Bus 1 + data.bus[1].bus_id = 1; + data.bus[1].bus_type = PhasorDynamics::BusData::SLACK; + data.bus[1].Vr0 = 30.0; + data.bus[1].Vi0 = 40.0; + + // Set branch data + data.branch.resize(1); + + // Branch 0-1 + data.branch[0].bus1_id = data.bus[0].bus_id; + data.branch[0].bus2_id = data.bus[1].bus_id; + data.branch[0].R = 2.0; + data.branch[0].X = 4.0; + data.branch[0].G = 0.2; + data.branch[0].B = 1.2; + + // Create an empty system model + system = new PhasorDynamics::SystemModel(data); + system->allocate(); + system->initialize(); + system->evaluateResidual(); + + // Answer keys + const ScalarT Ir0{17.0}; ///< Solution: real current entering bus-0 + const ScalarT Ii0{-10.0}; ///< Solution: imaginary current entering bus-0 + const ScalarT Ir1{15.0}; ///< Solution: real current entering bus-1 + const ScalarT Ii1{-20.0}; ///< Solution: imaginary current entering bus-1 + + auto* bus0 = system->getBus(0); + auto* bus1 = system->getBus(1); + + success *= isEqual(bus0->Ir(), Ir0); + success *= isEqual(bus0->Ii(), Ii0); + success *= isEqual(bus1->Ir(), Ir1); + success *= isEqual(bus1->Ii(), Ii1); + + delete system; + system = nullptr; + return success.report(__func__); } From f08e56dbc7265ad2af6caf5ed479086e2f9ef5d3 Mon Sep 17 00:00:00 2001 From: pelesh Date: Thu, 12 Jun 2025 20:58:35 -0400 Subject: [PATCH 13/15] Document SystemModel data constructor. --- examples/PhasorDynamics/Example2/example2.cpp | 2 -- src/Model/PhasorDynamics/SystemModel.hpp | 12 ++++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/examples/PhasorDynamics/Example2/example2.cpp b/examples/PhasorDynamics/Example2/example2.cpp index ceab0fb0a..3b7eeb68d 100644 --- a/examples/PhasorDynamics/Example2/example2.cpp +++ b/examples/PhasorDynamics/Example2/example2.cpp @@ -193,7 +193,6 @@ int main() data.load.resize(1); // Load on bus 2 - // LoadData data.load[0]; data.load[0].bus_id = 2; data.load[0].R = 0.4447197839297772; data.load[0].X = 0.20330047265361242; @@ -201,7 +200,6 @@ int main() // Set fault data data.bus_fault.resize(1); - // BusFaultData data.bus_fault[0]; data.bus_fault[0].bus_id = 2; data.bus_fault[0].R = 0.0; data.bus_fault[0].X = 1e-5; diff --git a/src/Model/PhasorDynamics/SystemModel.hpp b/src/Model/PhasorDynamics/SystemModel.hpp index 91c709945..6b0c4e795 100644 --- a/src/Model/PhasorDynamics/SystemModel.hpp +++ b/src/Model/PhasorDynamics/SystemModel.hpp @@ -75,6 +75,12 @@ namespace GridKit * @brief Construct a new System Model object * * @param[in] data - Data structure with complete system data + * + * @pre SystemModelData contains consistent connectivity information + * and physically meaningful model parameters. + * + * @post All component models in SystemModelData are created, and + * correctly connected into the system model. */ SystemModel(SystemModelData& data) { @@ -123,6 +129,9 @@ namespace GridKit /** * @brief Destructor for the system model + * + * If the SystemModel owns the components, it needs to delete them upon + * destructor call. */ virtual ~SystemModel() { @@ -734,6 +743,9 @@ namespace GridKit /** * @brief Return pointer to a bus fault model + * + * This function is used to provide easier access to setting and + * clearing faults from the SystemModel interface. * * @warning This is a hack to get access to bus faults in examples. * A more comprehensive solution is needed. From 72da18a68468d32a7fb9e2e8dedb1f27f0bdbb22 Mon Sep 17 00:00:00 2001 From: pelesh Date: Fri, 13 Jun 2025 01:00:54 +0000 Subject: [PATCH 14/15] Apply pre-commmit fixes --- src/Model/PhasorDynamics/SystemModel.hpp | 9 ++++----- .../UnitTests/PhasorDynamics/SystemTests.hpp | 20 +++++++++---------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/Model/PhasorDynamics/SystemModel.hpp b/src/Model/PhasorDynamics/SystemModel.hpp index 6b0c4e795..1dca4b0b0 100644 --- a/src/Model/PhasorDynamics/SystemModel.hpp +++ b/src/Model/PhasorDynamics/SystemModel.hpp @@ -75,10 +75,10 @@ namespace GridKit * @brief Construct a new System Model object * * @param[in] data - Data structure with complete system data - * + * * @pre SystemModelData contains consistent connectivity information * and physically meaningful model parameters. - * + * * @post All component models in SystemModelData are created, and * correctly connected into the system model. */ @@ -129,7 +129,7 @@ namespace GridKit /** * @brief Destructor for the system model - * + * * If the SystemModel owns the components, it needs to delete them upon * destructor call. */ @@ -146,7 +146,6 @@ namespace GridKit { delete bus; } - } } @@ -743,7 +742,7 @@ namespace GridKit /** * @brief Return pointer to a bus fault model - * + * * This function is used to provide easier access to setting and * clearing faults from the SystemModel interface. * diff --git a/tests/UnitTests/PhasorDynamics/SystemTests.hpp b/tests/UnitTests/PhasorDynamics/SystemTests.hpp index fb45f2102..dc8ecf81e 100644 --- a/tests/UnitTests/PhasorDynamics/SystemTests.hpp +++ b/tests/UnitTests/PhasorDynamics/SystemTests.hpp @@ -51,16 +51,16 @@ namespace GridKit data.bus.resize(2); // Bus 0 - data.bus[0].bus_id = 0; + data.bus[0].bus_id = 0; data.bus[0].bus_type = PhasorDynamics::BusData::SLACK; - data.bus[0].Vr0 = 10.0; - data.bus[0].Vi0 = 20.0; + data.bus[0].Vr0 = 10.0; + data.bus[0].Vi0 = 20.0; // Bus 1 - data.bus[1].bus_id = 1; + data.bus[1].bus_id = 1; data.bus[1].bus_type = PhasorDynamics::BusData::SLACK; - data.bus[1].Vr0 = 30.0; - data.bus[1].Vi0 = 40.0; + data.bus[1].Vr0 = 30.0; + data.bus[1].Vi0 = 40.0; // Set branch data data.branch.resize(1); @@ -68,10 +68,10 @@ namespace GridKit // Branch 0-1 data.branch[0].bus1_id = data.bus[0].bus_id; data.branch[0].bus2_id = data.bus[1].bus_id; - data.branch[0].R = 2.0; - data.branch[0].X = 4.0; - data.branch[0].G = 0.2; - data.branch[0].B = 1.2; + data.branch[0].R = 2.0; + data.branch[0].X = 4.0; + data.branch[0].G = 0.2; + data.branch[0].B = 1.2; // Create an empty system model system = new PhasorDynamics::SystemModel(data); From 30be5e55e7e97628166f1846486027f24e51aeec Mon Sep 17 00:00:00 2001 From: pelesh Date: Thu, 12 Jun 2025 21:06:46 -0400 Subject: [PATCH 15/15] Minor change. --- src/Model/PhasorDynamics/SystemModel.hpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Model/PhasorDynamics/SystemModel.hpp b/src/Model/PhasorDynamics/SystemModel.hpp index 1dca4b0b0..848e87f14 100644 --- a/src/Model/PhasorDynamics/SystemModel.hpp +++ b/src/Model/PhasorDynamics/SystemModel.hpp @@ -112,19 +112,19 @@ namespace GridKit addComponent(load); } - // Add faults - for (const auto& faultdata : data.bus_fault) - { - auto* fault = new BusFault(getBus(faultdata.bus_id), faultdata); - addFault(fault); - } - // Add generators for (const auto& gendata : data.genrou) { auto* gen = new Genrou(getBus(gendata.bus_id), gendata); addComponent(gen); } + + // Add faults + for (const auto& faultdata : data.bus_fault) + { + auto* fault = new BusFault(getBus(faultdata.bus_id), faultdata); + addFault(fault); + } } /**