diff --git a/examples/PhasorDynamics/Small/TenGen/Classical/CMakeLists.txt b/examples/PhasorDynamics/Small/TenGen/Classical/CMakeLists.txt index 74cd09e7f..9e455288e 100644 --- a/examples/PhasorDynamics/Small/TenGen/Classical/CMakeLists.txt +++ b/examples/PhasorDynamics/Small/TenGen/Classical/CMakeLists.txt @@ -4,6 +4,7 @@ target_link_libraries(TenGenClassical GRIDKIT::phasor_dynamics_bus_fault GRIDKIT::phasor_dynamics_branch GRIDKIT::phasor_dynamics_gen_classical + GRIDKIT::phasor_dynamics_governortgov1 GRIDKIT::phasor_dynamics_load GRIDKIT::solvers_dyn) install(TARGETS TenGenClassical RUNTIME DESTINATION bin) diff --git a/examples/PhasorDynamics/Small/TenGen/Genrou/CMakeLists.txt b/examples/PhasorDynamics/Small/TenGen/Genrou/CMakeLists.txt index 748b86fb0..7cb17005c 100644 --- a/examples/PhasorDynamics/Small/TenGen/Genrou/CMakeLists.txt +++ b/examples/PhasorDynamics/Small/TenGen/Genrou/CMakeLists.txt @@ -5,6 +5,7 @@ target_link_libraries(TenGenGenrou GRIDKIT::phasor_dynamics_branch GRIDKIT::phasor_dynamics_genrou GRIDKIT::phasor_dynamics_gen_classical + GRIDKIT::phasor_dynamics_governortgov1 GRIDKIT::phasor_dynamics_load GRIDKIT::solvers_dyn) install(TARGETS TenGenGenrou RUNTIME DESTINATION bin) diff --git a/examples/PhasorDynamics/Tiny/ThreeBus/Basic/CMakeLists.txt b/examples/PhasorDynamics/Tiny/ThreeBus/Basic/CMakeLists.txt index 1fea33e0d..f5a4aee36 100644 --- a/examples/PhasorDynamics/Tiny/ThreeBus/Basic/CMakeLists.txt +++ b/examples/PhasorDynamics/Tiny/ThreeBus/Basic/CMakeLists.txt @@ -4,6 +4,7 @@ target_link_libraries(ThreeBusBasic GRIDKIT::phasor_dynamics_bus_fault GRIDKIT::phasor_dynamics_branch GRIDKIT::phasor_dynamics_genrou + GRIDKIT::phasor_dynamics_governortgov1 GRIDKIT::phasor_dynamics_gen_classical GRIDKIT::phasor_dynamics_load GRIDKIT::solvers_dyn) diff --git a/examples/PhasorDynamics/Tiny/ThreeBus/Classical/CMakeLists.txt b/examples/PhasorDynamics/Tiny/ThreeBus/Classical/CMakeLists.txt index cd07bce3a..015609bb5 100644 --- a/examples/PhasorDynamics/Tiny/ThreeBus/Classical/CMakeLists.txt +++ b/examples/PhasorDynamics/Tiny/ThreeBus/Classical/CMakeLists.txt @@ -10,6 +10,7 @@ target_link_libraries(ThreeBusClassical GRIDKIT::phasor_dynamics_branch GRIDKIT::phasor_dynamics_genrou GRIDKIT::phasor_dynamics_gen_classical + GRIDKIT::phasor_dynamics_governortgov1 GRIDKIT::phasor_dynamics_load GRIDKIT::solvers_dyn) install(TARGETS ThreeBusClassical RUNTIME DESTINATION bin) diff --git a/examples/PhasorDynamics/Tiny/TwoBus/Basic/CMakeLists.txt b/examples/PhasorDynamics/Tiny/TwoBus/Basic/CMakeLists.txt index 583f042fe..d088a0075 100644 --- a/examples/PhasorDynamics/Tiny/TwoBus/Basic/CMakeLists.txt +++ b/examples/PhasorDynamics/Tiny/TwoBus/Basic/CMakeLists.txt @@ -4,6 +4,7 @@ target_link_libraries(TwoBusBasic GRIDKIT::phasor_dynamics_bus_fault GRIDKIT::phasor_dynamics_branch GRIDKIT::phasor_dynamics_genrou + GRIDKIT::phasor_dynamics_governortgov1 GRIDKIT::phasor_dynamics_gen_classical GRIDKIT::phasor_dynamics_load GRIDKIT::solvers_dyn) diff --git a/examples/PhasorDynamics/Tiny/TwoBus/Basic/TwoBusBasic.cpp b/examples/PhasorDynamics/Tiny/TwoBus/Basic/TwoBusBasic.cpp index 1d614ccfb..196a1a61d 100644 --- a/examples/PhasorDynamics/Tiny/TwoBus/Basic/TwoBusBasic.cpp +++ b/examples/PhasorDynamics/Tiny/TwoBus/Basic/TwoBusBasic.cpp @@ -72,6 +72,7 @@ int main() // Set generator data data.genrou.resize(1); + data.genrou[0].ports[GenrouPorts::bus] = data.bus[0].bus_id; data.genrou[0].parameters[GenrouParameters::p0] = 1.; data.genrou[0].parameters[GenrouParameters::q0] = 0.05013; data.genrou[0].parameters[GenrouParameters::H] = 3.; diff --git a/examples/PhasorDynamics/Tiny/TwoBus/Tgov1/TwoBusTgov1.cpp b/examples/PhasorDynamics/Tiny/TwoBus/Tgov1/TwoBusTgov1.cpp index eca4f0b86..31cbb2bbb 100644 --- a/examples/PhasorDynamics/Tiny/TwoBus/Tgov1/TwoBusTgov1.cpp +++ b/examples/PhasorDynamics/Tiny/TwoBus/Tgov1/TwoBusTgov1.cpp @@ -49,7 +49,7 @@ int main() SystemModelData data; // Set bus data - data.bus.resize(2); + data.bus.resize(4); data.bus[0].bus_id = 0; data.bus[0].bus_type = BusType::DEFAULT; @@ -61,6 +61,14 @@ int main() data.bus[1].Vr0 = 1.0; data.bus[1].Vi0 = 0.0; + // Pmech Signal Bus + data.bus[2].bus_id = 2; + data.bus[2].bus_type = BusType::SIGNAL; + + // Speed Signal Bus + data.bus[3].bus_id = 3; + data.bus[3].bus_type = BusType::SIGNAL; + // Set branch data data.branch.resize(1); @@ -78,15 +86,13 @@ int main() data.bus_fault[0].parameters[BusFaultParameters::X] = 1e-3; data.bus_fault[0].parameters[BusFaultParameters::state0] = false; - // - // Instantiate system model - // - - SystemModel sys(data); // Set generator data data.genrou.resize(1); + data.genrou[0].ports[GenrouPorts::bus] = data.bus[0].bus_id; + data.genrou[0].ports[GenrouPorts::pmech_signal] = 2; + data.genrou[0].ports[GenrouPorts::speed_signal] = 3; data.genrou[0].parameters[GenrouParameters::p0] = 1.; data.genrou[0].parameters[GenrouParameters::q0] = 0.05013; data.genrou[0].parameters[GenrouParameters::H] = 3.; @@ -106,9 +112,11 @@ int main() data.genrou[0].parameters[GenrouParameters::S10] = 0.; data.genrou[0].parameters[GenrouParameters::S12] = 0.; + // Governor TODO use new data structure data.gov.resize(1); - // Set Gov data (Default PW values) + data.gov[0].signal_speed = 3; + data.gov[0].signal_pmech = 2; data.gov[0].R = 0.05; data.gov[0].Pvmin = 0; data.gov[0].Pvmax = 1.0; @@ -117,27 +125,8 @@ int main() data.gov[0].T3 = 7.5; data.gov[0].Dt = 0; - // Manual add gen & gov components - // This is a hack since SignalBus not implemented - - // Create Pointers first - Genrou* gen; - Governor::Tgov1* gov; - - // Instatiate Genrou & add to system model - gen = new Genrou( - sys.getBus(0), - data.genrou[0]); - - // Instatiate GovernorTgov1 & add to system model - gov = new Governor::Tgov1( - gen, - data.gov[0]); - gen->setgovenor(gov); - - // Add Generator and Governor to System - sys.addComponent(gen); - sys.addComponent(gov); + // Instantiate system model + SystemModel sys(data); sys.allocate(); @@ -179,7 +168,8 @@ int main() { std::vector& y_val = sys.y(); - output.push_back(OutputData{t, y_val[0], y_val[1], y_val[3]}); + // Note Omega of gen is at state index 5! (Each added signal shifted by 1) + output.push_back(OutputData{t, y_val[0], y_val[1], y_val[5]}); }; // Set up simulation diff --git a/src/Model/PhasorDynamics/Bus/Bus.hpp b/src/Model/PhasorDynamics/Bus/Bus.hpp index f61eaf6bd..ac5e159d0 100644 --- a/src/Model/PhasorDynamics/Bus/Bus.hpp +++ b/src/Model/PhasorDynamics/Bus/Bus.hpp @@ -45,6 +45,22 @@ namespace GridKit return BusTypeT::DEFAULT; } + // TODO remove, uneeded + void initial_value(ScalarT) override + { + } + + // TODO remove, uneeded + ScalarT& read() override + { + return y_[0]; + } + + // TODO remove, uneeded + void write(ScalarT&) override + { + } + virtual ScalarT& Vr() override { return y_[0]; diff --git a/src/Model/PhasorDynamics/Bus/BusData.hpp b/src/Model/PhasorDynamics/Bus/BusData.hpp index 3a1ab6f88..0ecc07046 100644 --- a/src/Model/PhasorDynamics/Bus/BusData.hpp +++ b/src/Model/PhasorDynamics/Bus/BusData.hpp @@ -41,6 +41,7 @@ namespace GridKit INVALID, DEFAULT, SLACK, + SIGNAL }; BusType bus_type{BusType::INVALID}; ///< The kind of bus this data is for diff --git a/src/Model/PhasorDynamics/Bus/BusFactory.hpp b/src/Model/PhasorDynamics/Bus/BusFactory.hpp index 84c6e26cc..13375cd64 100644 --- a/src/Model/PhasorDynamics/Bus/BusFactory.hpp +++ b/src/Model/PhasorDynamics/Bus/BusFactory.hpp @@ -4,6 +4,7 @@ #include #include #include +#include namespace GridKit { @@ -31,6 +32,9 @@ namespace GridKit case BusTypeT::SLACK: bus = new BusInfinite(data); break; + case BusTypeT::SIGNAL: + bus = new BusSignal(data); + break; default: // Throw exception std::cout << "Bus type " << static_cast(data.bus_type) << " unrecognized.\n"; diff --git a/src/Model/PhasorDynamics/Bus/BusInfinite.hpp b/src/Model/PhasorDynamics/Bus/BusInfinite.hpp index 8e7e81d80..e4f2c8bd2 100644 --- a/src/Model/PhasorDynamics/Bus/BusInfinite.hpp +++ b/src/Model/PhasorDynamics/Bus/BusInfinite.hpp @@ -42,6 +42,22 @@ namespace GridKit return BusTypeT::SLACK; } + // TODO remove, uneeded + void initial_value(ScalarT) override + { + } + + // TODO remove, uneeded + ScalarT& read() override + { + return y_[0]; + } + + // TODO remove, uneeded + void write(ScalarT&) override + { + } + virtual ScalarT& Vr() override { return Vr_; diff --git a/src/Model/PhasorDynamics/Bus/BusSignal.cpp b/src/Model/PhasorDynamics/Bus/BusSignal.cpp new file mode 100644 index 000000000..2d0cd95ae --- /dev/null +++ b/src/Model/PhasorDynamics/Bus/BusSignal.cpp @@ -0,0 +1,80 @@ + +#include "BusSignal.hpp" + +#include +#include + +#include + +namespace GridKit +{ + namespace PhasorDynamics + { + + template + BusSignal::BusSignal(const DataT& data) + : BusBase(data.bus_id) + { + size_ = 1; + } + + template + int BusSignal::allocate() + { + // Temporary while we use std::vector in the code + size_t size = static_cast(size_); + + // Resize component model data + f_.resize(size); + y_.resize(size); + yp_.resize(size); + tag_.resize(size); + + fB_.resize(size); + yB_.resize(size); + ypB_.resize(size); + + return 0; + } + + template + int BusSignal::tagDifferentiable() + { + tag_[0] = false; + return 0; + } + + template + int BusSignal::initialize() + { + /// Possible since not being used it causes issue? + y_[0] = 0.0; + yp_[0] = 0.0; + + return 0; + } + + template + int BusSignal::evaluateResidual() + { + // One side of equality of signal. Reference component + // must add to this residual after this function has been called. + f_[0] = -y_[0]; + + return 0; + } + + template + int BusSignal::evaluateJacobian() + { + return 0; + } + + // Available template instantiations + template class BusSignal; + template class BusSignal; + template class BusSignal; + template class BusSignal; + + } // namespace PhasorDynamics +} // namespace GridKit diff --git a/src/Model/PhasorDynamics/Bus/BusSignal.hpp b/src/Model/PhasorDynamics/Bus/BusSignal.hpp new file mode 100644 index 000000000..730d1a9a5 --- /dev/null +++ b/src/Model/PhasorDynamics/Bus/BusSignal.hpp @@ -0,0 +1,127 @@ + +#pragma once + +#include + +namespace GridKit +{ + namespace PhasorDynamics + { + + // TODO change base class so there is no Vr and Vi + + template + class BusSignal : public BusBase + { + using BusBase::size_; + using BusBase::y_; + using BusBase::yp_; + using BusBase::yB_; + using BusBase::ypB_; + using BusBase::f_; + using BusBase::fB_; + using BusBase::tag_; + + public: + using real_type = typename BusBase::real_type; + using DataT = BusData; + + BusSignal(const DataT& data); + + ~BusSignal() + { + } + + virtual int allocate() override; + virtual int tagDifferentiable() override; + virtual int initialize() override; + virtual int evaluateResidual() override; + virtual int evaluateJacobian() override; + + /** + * @brief A one-time initialization function + * that can be called by any. + * + * @return state value of signal + */ + void initial_value(ScalarT value) override + { + + y_[0] = value; + // if(is_initialized_) + //{ + // std::cout << "ERROR!"; + // } + // else{ + // y_[0] = value; + // is_initialized_ = true; + // } + } + + /** + * @brief A read only accessor to the signal state + * + * @return state value of signal + */ + ScalarT& read() override + { + return y_[0]; + } + + /** + * @brief A write operation only available + * to the source signal + * + * @param value The value of the signal + */ + void write(ScalarT& value) override + { + f_[0] += value; + } + + // TODO remove jsut junk so it compiles + ScalarT& Vr() override + { + return y_[0]; + } + + const ScalarT& Vr() const override + { + return y_[0]; + } + + ScalarT& Vi() override + { + return y_[0]; + } + + const ScalarT& Vi() const override + { + return y_[0]; + } + + ScalarT& Ir() override + { + return y_[0]; + } + + const ScalarT& Ir() const override + { + return y_[0]; + } + + ScalarT& Ii() override + { + return y_[0]; + } + + const ScalarT& Ii() const override + { + return y_[0]; + } + + // bool is_initialized_{false}; + }; + + } // namespace PhasorDynamics +} // namespace GridKit diff --git a/src/Model/PhasorDynamics/Bus/CMakeLists.txt b/src/Model/PhasorDynamics/Bus/CMakeLists.txt index b11fe63ac..db8a5b85d 100644 --- a/src/Model/PhasorDynamics/Bus/CMakeLists.txt +++ b/src/Model/PhasorDynamics/Bus/CMakeLists.txt @@ -7,6 +7,7 @@ gridkit_add_library(phasor_dynamics_bus SOURCES Bus.cpp + BusSignal.cpp BusInfinite.cpp OUTPUT_NAME gridkit_phasor_dynamics_bus) diff --git a/src/Model/PhasorDynamics/BusBase.hpp b/src/Model/PhasorDynamics/BusBase.hpp index 0f2ca0945..7f3b0c8dd 100644 --- a/src/Model/PhasorDynamics/BusBase.hpp +++ b/src/Model/PhasorDynamics/BusBase.hpp @@ -72,6 +72,10 @@ namespace GridKit msa = max_steps_; } + virtual void initial_value(ScalarT value) = 0; + virtual ScalarT& read() = 0; + virtual void write(ScalarT& value) = 0; + virtual ScalarT& Vr() = 0; virtual const ScalarT& Vr() const = 0; virtual ScalarT& Vi() = 0; diff --git a/src/Model/PhasorDynamics/Component.hpp b/src/Model/PhasorDynamics/Component.hpp index 7d7d1a1fe..206db4c87 100644 --- a/src/Model/PhasorDynamics/Component.hpp +++ b/src/Model/PhasorDynamics/Component.hpp @@ -3,6 +3,7 @@ #include #include +#include "BusBase.hpp" #include #include @@ -20,12 +21,63 @@ namespace GridKit { public: using real_type = typename Model::Evaluator::real_type; + using bus_type = BusBase; Component() : size_(0) { } + /** + * @brief A helper function to easily init + * a signal value wiithout needing to check if initialized + * + * @param signal The signal bus object pointer + * @param value The value to send to the equality constraint + */ + void safeInit(bus_type* signal, ScalarT value) + { + if (signal) + { + signal->initial_value(value); + } + } + + /** + * @brief A helper function to easily init + * a signal value wiithout needing to check if initialized + * + * @param signal The signal bus object pointer + * @param value The value to send to the equality constraint + */ + void safeWrite(bus_type* signal, ScalarT value) + { + if (signal) + { + signal->write(value); + } + } + + /** + * @brief A helper function to easily read + * the state of the signal without checking nullptr + * + * + * @param signal The signal bus object pointer + * @param default_val The value to return if no signal + */ + ScalarT safeRead(bus_type* signal, ScalarT default_val) + { + if (signal) + { + return signal->read(); + } + else + { + return default_val; + } + } + virtual IdxT size() override { return size_; diff --git a/src/Model/PhasorDynamics/Governor/Tgov1/CMakeLists.txt b/src/Model/PhasorDynamics/Governor/Tgov1/CMakeLists.txt index fae3999ec..542384444 100644 --- a/src/Model/PhasorDynamics/Governor/Tgov1/CMakeLists.txt +++ b/src/Model/PhasorDynamics/Governor/Tgov1/CMakeLists.txt @@ -7,7 +7,5 @@ gridkit_add_library(phasor_dynamics_governortgov1 SOURCES Tgov1.cpp - LINK_LIBRARIES - GRIDKIT::phasor_dynamics_genrou OUTPUT_NAME gridkit_phasor_dynamics_governortgov1) diff --git a/src/Model/PhasorDynamics/Governor/Tgov1/Tgov1.cpp b/src/Model/PhasorDynamics/Governor/Tgov1/Tgov1.cpp index af140c130..4658438ad 100644 --- a/src/Model/PhasorDynamics/Governor/Tgov1/Tgov1.cpp +++ b/src/Model/PhasorDynamics/Governor/Tgov1/Tgov1.cpp @@ -12,7 +12,6 @@ #include #include -#include #define _USE_MATH_DEFINES @@ -26,19 +25,25 @@ namespace GridKit /*! * @brief Constructor for Governor * - * @param machine Generator Object + * @param pmech Bus signal pointer + * @param omega Bus signal pointer * @param data TGOV1 Data Object */ template - Tgov1::Tgov1(machine_type* machine, const model_data_type& data) - : machine_(machine), + Tgov1::Tgov1( + bus_type* pmech_signal, + bus_type* omega_signal, + const model_data_type& data) + : pmech_signal_(pmech_signal), + omega_signal_(omega_signal), R_(data.R), Pvmin_(data.Pvmin), Pvmax_(data.Pvmax), T1_(data.T1), T2_(data.T2), T3_(data.T3), - Dt_(data.Dt) + Dt_(data.Dt), + pref_(0) { // 3 Internal Variables @@ -46,15 +51,17 @@ namespace GridKit } template - Tgov1::Tgov1(machine_type* machine) - : machine_(machine), + Tgov1::Tgov1() + : pmech_signal_(nullptr), + omega_signal_(nullptr), R_(0.05), Pvmin_(0), Pvmax_(1), T1_(0.5), T2_(2.5), T3_(7.5), - Dt_(0) + Dt_(0), + pref_(0) { // 3 Internal Variables @@ -85,7 +92,8 @@ namespace GridKit { // Initial mechanical = initial electric torque - ScalarT p0 = machine_->getTorque(); + ScalarT pdef = 1; + ScalarT p0 = this->safeRead(pmech_signal_, pdef); // Input Variables (Parameter for now) pref_ = R_ * p0; @@ -167,8 +175,9 @@ namespace GridKit int Tgov1::evaluateResidual() { - // Input Variables - ScalarT omega = machine_->getSpeed(); + // Ext Variables + ScalarT omega0 = 0; + ScalarT omega = this->safeRead(omega_signal_, omega0); // Read Internal Variables ScalarT ptx = y_[0]; // y0 - Ptx @@ -183,13 +192,14 @@ namespace GridKit ScalarT f = (-pv + (pref_ - omega) / R_) / T1_; ScalarT valv_ind = this->indicator(pv, f); - // Internal Differential Equations + // Equations f_[0] = -ptx_dot + pv - (ptx + T2_ * pv) / T3_; f_[1] = -pv_dot + valv_ind * f; - - // Internal Algebraic Equations f_[2] = -pmech + (ptx + T2_ * pv) / T3_ - (Dt_ * omega); + // Write External + this->safeWrite(pmech_signal_, pmech); + return 0; } @@ -207,18 +217,6 @@ namespace GridKit return 0; } - /** - * @brief The mechanical power output. - * @warning This is not yet accessed by anything. The Genrou class will - * need to access this instead of a constant Pmech. - * @return ScalarT - Mechanical output power value. - */ - template - ScalarT& Tgov1::Pmech() - { - return y_[2]; - } - // Available template instantiations template class Tgov1; template class Tgov1; diff --git a/src/Model/PhasorDynamics/Governor/Tgov1/Tgov1.hpp b/src/Model/PhasorDynamics/Governor/Tgov1/Tgov1.hpp index 2383775ba..fa5275864 100644 --- a/src/Model/PhasorDynamics/Governor/Tgov1/Tgov1.hpp +++ b/src/Model/PhasorDynamics/Governor/Tgov1/Tgov1.hpp @@ -9,7 +9,6 @@ #pragma once #include -#include // Forward declarations namespace GridKit @@ -23,7 +22,7 @@ namespace GridKit } // namespace Governor template - class Genrou; + class BusBase; } // namespace PhasorDynamics } // namespace GridKit @@ -36,7 +35,7 @@ namespace GridKit { template - class Tgov1 : public Component, public GovernorBase + class Tgov1 : public Component { using Component::alpha_; using Component::f_; @@ -47,13 +46,15 @@ namespace GridKit using Component::y_; using Component::yp_; - using machine_type = Genrou; using real_type = typename Component::real_type; using model_data_type = Tgov1Data; + using bus_type = BusBase; public: - Tgov1(machine_type* machine, const model_data_type& data); - Tgov1(machine_type* machine); + Tgov1(); + Tgov1(bus_type* pmech_signal, + bus_type* omega_signal, + const model_data_type& data); ~Tgov1() = default; int allocate() override; @@ -68,12 +69,10 @@ namespace GridKit { } - // Read Access to Pmech - ScalarT& Pmech() override; - private: // Associated Machine Model - machine_type* machine_; + bus_type* pmech_signal_; + bus_type* omega_signal_; // Input parameters real_type R_; diff --git a/src/Model/PhasorDynamics/Governor/Tgov1/Tgov1Data.hpp b/src/Model/PhasorDynamics/Governor/Tgov1/Tgov1Data.hpp index 55a645033..f271fcb04 100644 --- a/src/Model/PhasorDynamics/Governor/Tgov1/Tgov1Data.hpp +++ b/src/Model/PhasorDynamics/Governor/Tgov1/Tgov1Data.hpp @@ -32,6 +32,9 @@ namespace GridKit RealT Pvmax{1.0}; ///< Max Valve Power RealT Pvmin{0.0}; ///< Min Valve Power RealT Dt{0.0}; ///< + + IdxT signal_pmech; ///< Unique ID of the bus providing the pmech signal + IdxT signal_speed; ///< Unique ID of the bus providing the speed signal }; } // namespace Governor } // namespace PhasorDynamics diff --git a/src/Model/PhasorDynamics/GovernorBase.hpp b/src/Model/PhasorDynamics/GovernorBase.hpp deleted file mode 100644 index 04d85a5f7..000000000 --- a/src/Model/PhasorDynamics/GovernorBase.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include - -namespace GridKit -{ - namespace PhasorDynamics - { - /*! - * @brief GovernorBase model implementation base class. - * - */ - template - class GovernorBase - { - public: - virtual ScalarT& Pmech() = 0; - }; - - } // namespace PhasorDynamics -} // namespace GridKit diff --git a/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/Genrou.cpp b/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/Genrou.cpp index 4d7ceb54a..94b654de7 100644 --- a/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/Genrou.cpp +++ b/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/Genrou.cpp @@ -4,7 +4,6 @@ * @author Slaven Peles (peless@ornl.gov) * @brief Definition of a GENROU generator model. * - * */ #define _USE_MATH_DEFINES @@ -14,7 +13,7 @@ #include #include -#include // <- TODO: Temporary, to be removed. +#include #include #define _USE_MATH_DEFINES @@ -23,21 +22,14 @@ namespace GridKit { namespace PhasorDynamics { - /** - * @brief Constructor for a GENROU generator model with saturation - * - * Arguments passed to ModelEvaluatorImpl: - * - Number of equations = 0 - * - Number of independent variables = 0 - * - Number of quadratures = 0 - * - Number of optimization parameters = 0 - */ + template Genrou::Genrou(bus_type* bus, IdxT unit_id) : bus_(bus), + pmech_signal_(nullptr), + omega_signal_(nullptr), busID_(0), unit_id_(unit_id), - gov_(nullptr), // <- TODO: Temporary, to be removed. p0_(0.), q0_(0.), H_(3.), @@ -55,58 +47,9 @@ namespace GridKit Xqpp_(.18), Xl_(.15), S10_(0.), - S12_(0.) - { - size_ = 20; - setDerivedParams(); - } - - /** - * @brief Constructor for a GENROU generator model with saturation - */ - template - Genrou::Genrou(bus_type* bus, - IdxT unit_id, - ScalarT p0, - ScalarT q0, - real_type H, - real_type D, - real_type Ra, - real_type Tdop, - real_type Tdopp, - real_type Tqopp, - real_type Tqop, - real_type Xd, - real_type Xdp, - real_type Xdpp, - real_type Xq, - real_type Xqp, - real_type Xqpp, - real_type Xl, - real_type S10, - real_type S12) - : bus_(bus), - busID_(0), - unit_id_(unit_id), - gov_(nullptr), // <- TODO: Temporary, to be removed. - p0_(p0), - q0_(q0), - H_(H), - D_(D), - Ra_(Ra), - Tdop_(Tdop), - Tdopp_(Tdopp), - Tqopp_(Tqopp), - Tqop_(Tqop), - Xd_(Xd), - Xdp_(Xdp), - Xdpp_(Xdpp), - Xq_(Xq), - Xqp_(Xqp), - Xqpp_(Xqpp), - Xl_(Xl), - S10_(S10), - S12_(S12) + S12_(0.), + pmech_set_(0), + efd_set_(0) { size_ = 20; setDerivedParams(); @@ -116,10 +59,17 @@ namespace GridKit * @brief Constructor for a GENROU generator model with saturation */ template - Genrou::Genrou(bus_type* bus, const model_data_type& data) + Genrou::Genrou( + bus_type* bus, + bus_type* pmech_signal, + bus_type* omega_signal, + const model_data_type& data) : bus_(bus), + pmech_signal_(pmech_signal), + omega_signal_(omega_signal), unit_id_(1), - gov_(nullptr) // <- TODO: Temporary, to be removed. + pmech_set_(0), + efd_set_(0) { if (data.parameters.contains(model_data_type::Parameters::p0)) { @@ -220,271 +170,286 @@ namespace GridKit setDerivedParams(); } - // /** - // * @brief Destroy the Genrou - // * - // * @tparam ScalarT - // * @tparam IdxT - // */ - // template - // Genrou::~Genrou() - // { - // // std::cout << "Destroy Genrou..." << std::endl; - // } - - /*! - * @brief allocate method computes sparsity pattern of the Jacobian. - */ template - int Genrou::allocate() - { - f_.resize(static_cast(size_)); - y_.resize(static_cast(size_)); - yp_.resize(static_cast(size_)); - tag_.resize(static_cast(size_)); - return 0; - } - - /** - * Initialization of the branch model - * - */ - template - int Genrou::initialize() + Genrou::Genrou(bus_type* bus, + IdxT unit_id, + ScalarT p0, + ScalarT q0, + real_type H, + real_type D, + real_type Ra, + real_type Tdop, + real_type Tdopp, + real_type Tqopp, + real_type Tqop, + real_type Xd, + real_type Xdp, + real_type Xdpp, + real_type Xq, + real_type Xqp, + real_type Xqpp, + real_type Xl, + real_type S10, + real_type S12) + : bus_(bus), + pmech_signal_(nullptr), + omega_signal_(nullptr), + busID_(0), + unit_id_(unit_id), + p0_(p0), + q0_(q0), + H_(H), + D_(D), + Ra_(Ra), + Tdop_(Tdop), + Tdopp_(Tdopp), + Tqopp_(Tqopp), + Tqop_(Tqop), + Xd_(Xd), + Xdp_(Xdp), + Xdpp_(Xdpp), + Xq_(Xq), + Xqp_(Xqp), + Xqpp_(Xqpp), + Xl_(Xl), + S10_(S10), + S12_(S12) { - /* Initialization tricks -- assuming NO saturation */ - ScalarT vr = Vr(); - ScalarT vi = Vi(); - ScalarT p = p0_; - ScalarT q = q0_; - ScalarT vm2 = vr * vr + vi * vi; - ScalarT Er = vr + (Ra_ * p * vr + Ra_ * q * vi - Xq_ * p * vi + Xq_ * q * vr) / vm2; - ScalarT Ei = vi + (Ra_ * p * vi - Ra_ * q * vr + Xq_ * p * vr + Xq_ * q * vi) / vm2; - ScalarT delta = atan2(Ei, Er); - ScalarT omega = 0; - ScalarT ir = (p * vr + q * vi) / vm2; - ScalarT ii = (p * vi - q * vr) / vm2; - ScalarT id = ir * sin(delta) - ii * cos(delta); - ScalarT iq = ir * cos(delta) + ii * sin(delta); - ScalarT vd = vr * sin(delta) - vi * cos(delta) + id * Ra_ - iq * Xqpp_; - ScalarT vq = vr * cos(delta) + vi * sin(delta) + id * Xqpp_ - iq * Ra_; - ScalarT psiqpp = -vd / (1 + omega); - ScalarT psidpp = vq / (1 + omega); - ScalarT Te = (psidpp - id * Xdpp_) * iq - (psiqpp - iq * Xdpp_) * id; - ScalarT psiqp = -(-(Xqp_ - Xl_) * iq + psiqpp * (Xqp_ - Xl_) / (Xqpp_ - Xl_)) - / (1 + (Xqp_ - Xqpp_) / (Xqpp_ - Xl_)); - ScalarT Edp = psiqp - (Xqp_ - Xl_) * iq; - ScalarT psidp = -((Xdp_ - Xl_) * id - psidpp * (Xdp_ - Xl_) / (Xdpp_ - Xl_)) - / (1 + (Xdp_ - Xdpp_) / (Xdpp_ - Xl_)); - ScalarT Eqp = psidp + (Xdp_ - Xl_) * id; - - /* Now we have the state variables, solve for alg. variables */ - ScalarT ksat; - ScalarT psipp; - - y_[0] = delta; //= 0.55399038; - y_[1] = omega; // = 0; - y_[2] = Eqp; // = 0.995472581; - y_[3] = psidp; // = 0.971299567; - y_[4] = psiqp; // = 0.306880069; - y_[5] = Edp; // = 0; - - y_[6] = psiqpp = -psiqp * Xq4_ - Edp * Xq5_; - y_[7] = psidpp = psidp * Xd4_ + Eqp * Xd5_; - y_[8] = psipp = sqrt(psiqpp * psiqpp + psidpp * psidpp); - y_[9] = ksat = SB_ * pow(psipp - SA_, 2); - y_[10] = vd = -psiqpp * (1 + omega); - y_[11] = vq = psidpp * (1 + omega); - y_[12] = Te = (psidpp - id * Xdpp_) * iq - (psiqpp - iq * Xdpp_) * id; - y_[13] = id; - y_[14] = iq; - y_[15] = ir; - y_[16] = ii; - y_[17] = efd_set_ = Eqp + Xd1_ * (id + Xd3_ * (Eqp - psidp - Xd2_ * id)) + psidpp * ksat; - y_[18] = G_ * (vd * sin(delta) + vq * cos(delta)) - - B_ * (vd * -cos(delta) + vq * sin(delta)); /* inort, real */ - y_[19] = B_ * (vd * sin(delta) + vq * cos(delta)) - + G_ * (vd * -cos(delta) + vq * sin(delta)); /* inort, imag */ - - // Set Setpoint mechanical power, which may or may not be used - pmech_set_ = Te; - - for (IdxT i = 0; i < size_; ++i) - yp_[static_cast(i)] = 0.0; - - return 0; + size_ = 20; + setDerivedParams(); } - - /** - * \brief Identify differential variables. - */ - template - int Genrou::tagDifferentiable() - { - for (IdxT i = 0; i < size_; ++i) + /*! + * @brief allocate method computes sparsity pattern of the Jacobian. + */ + template + int Genrou::allocate() { - tag_[static_cast(i)] = i < 6; + f_.resize(static_cast(size_)); + y_.resize(static_cast(size_)); + yp_.resize(static_cast(size_)); + tag_.resize(static_cast(size_)); + return 0; } - return 0; - } - /** - * \brief Residual contribution of the branch is pushed to the - * two terminal buses. - * - */ - template - int Genrou::evaluateResidual() - { - /* Read variables */ - ScalarT delta = y_[0]; - ScalarT omega = y_[1]; - ScalarT Eqp = y_[2]; - ScalarT psidp = y_[3]; - ScalarT psiqp = y_[4]; - ScalarT Edp = y_[5]; - ScalarT psiqpp = y_[6]; - ScalarT psidpp = y_[7]; - ScalarT psipp = y_[8]; - ScalarT ksat = y_[9]; - ScalarT vd = y_[10]; - ScalarT vq = y_[11]; - ScalarT telec = y_[12]; - ScalarT id = y_[13]; - ScalarT iq = y_[14]; - ScalarT ir = y_[15]; - ScalarT ii = y_[16]; - ScalarT efd = y_[17]; - ScalarT inr = y_[18]; - ScalarT ini = y_[19]; - ScalarT vr = Vr(); - ScalarT vi = Vi(); - ScalarT pmech; - if (gov_) + /** + * Initialization of the branch model + * + */ + template + int Genrou::initialize() { - pmech = gov_->Pmech(); + + ScalarT vr = Vr(); + ScalarT vi = Vi(); + + /* Initialization tricks -- assuming NO saturation */ + + ScalarT p = p0_; + ScalarT q = q0_; + ScalarT vm2 = vr * vr + vi * vi; + ScalarT Er = vr + (Ra_ * p * vr + Ra_ * q * vi - Xq_ * p * vi + Xq_ * q * vr) / vm2; + ScalarT Ei = vi + (Ra_ * p * vi - Ra_ * q * vr + Xq_ * p * vr + Xq_ * q * vi) / vm2; + ScalarT delta = atan2(Ei, Er); + ScalarT omega = 0; + ScalarT ir = (p * vr + q * vi) / vm2; + ScalarT ii = (p * vi - q * vr) / vm2; + ScalarT id = ir * sin(delta) - ii * cos(delta); + ScalarT iq = ir * cos(delta) + ii * sin(delta); + ScalarT vd = vr * sin(delta) - vi * cos(delta) + id * Ra_ - iq * Xqpp_; + ScalarT vq = vr * cos(delta) + vi * sin(delta) + id * Xqpp_ - iq * Ra_; + ScalarT psiqpp = -vd / (1 + omega); + ScalarT psidpp = vq / (1 + omega); + ScalarT Te = (psidpp - id * Xdpp_) * iq - (psiqpp - iq * Xdpp_) * id; + ScalarT psiqp = -(-(Xqp_ - Xl_) * iq + psiqpp * (Xqp_ - Xl_) / (Xqpp_ - Xl_)) + / (1 + (Xqp_ - Xqpp_) / (Xqpp_ - Xl_)); + ScalarT Edp = psiqp - (Xqp_ - Xl_) * iq; + ScalarT psidp = -((Xdp_ - Xl_) * id - psidpp * (Xdp_ - Xl_) / (Xdpp_ - Xl_)) + / (1 + (Xdp_ - Xdpp_) / (Xdpp_ - Xl_)); + ScalarT Eqp = psidp + (Xdp_ - Xl_) * id; + + /* Now we have the state variables, solve for alg. variables */ + ScalarT ksat; + ScalarT psipp; + + y_[0] = delta; + y_[1] = omega; + y_[2] = Eqp; + y_[3] = psidp; + y_[4] = psiqp; + y_[5] = Edp; + + y_[6] = psiqpp = -psiqp * Xq4_ - Edp * Xq5_; + y_[7] = psidpp = psidp * Xd4_ + Eqp * Xd5_; + y_[8] = psipp = sqrt(psiqpp * psiqpp + psidpp * psidpp); + y_[9] = ksat = SB_ * pow(psipp - SA_, 2); + y_[10] = vd = -psiqpp * (1 + omega); + y_[11] = vq = psidpp * (1 + omega); + y_[12] = Te = (psidpp - id * Xdpp_) * iq - (psiqpp - iq * Xdpp_) * id; + y_[13] = id; + y_[14] = iq; + y_[15] = ir; + y_[16] = ii; + y_[17] = efd_set_ = Eqp + Xd1_ * (id + Xd3_ * (Eqp - psidp - Xd2_ * id)) + psidpp * ksat; + y_[18] = G_ * (vd * sin(delta) + vq * cos(delta)) + - B_ * (vd * -cos(delta) + vq * sin(delta)); /* inort, real */ + y_[19] = B_ * (vd * sin(delta) + vq * cos(delta)) + + G_ * (vd * -cos(delta) + vq * sin(delta)); /* inort, imag */ + + for (IdxT i = 0; i < size_; ++i) + yp_[static_cast(i)] = 0.0; + + // Initialize External Inputs + // To do make this from init function + pmech_set_ = Te; + this->safeInit(pmech_signal_, Te); + this->safeInit(omega_signal_, omega); + + return 0; } - else + + /** + * \brief Identify differential variables. + */ + template + int Genrou::tagDifferentiable() { - pmech = pmech_set_; + for (IdxT i = 0; i < size_; ++i) + { + tag_[static_cast(i)] = i < 6; + } + return 0; } - /* Read derivatives */ - ScalarT delta_dot = yp_[0]; - ScalarT omega_dot = yp_[1]; - ScalarT Eqp_dot = yp_[2]; - ScalarT psidp_dot = yp_[3]; - ScalarT psiqp_dot = yp_[4]; - ScalarT Edp_dot = yp_[5]; - - /* 6 Genrou differential equations */ - f_[0] = delta_dot - omega * (2 * M_PI * 60); - f_[1] = omega_dot - (1 / (2 * H_)) * ((pmech - D_ * omega) / (1 + omega) - telec); - f_[2] = Eqp_dot - (1 / Tdop_) * (efd - (Eqp + Xd1_ * (id + Xd3_ * (Eqp - psidp - Xd2_ * id)) + psidpp * ksat)); - f_[3] = psidp_dot - (1 / Tdopp_) * (Eqp - psidp - Xd2_ * id); - f_[4] = psiqp_dot - (1 / Tqopp_) * (Edp - psiqp + Xq2_ * iq); - f_[5] = Edp_dot - (1 / Tqop_) * (-Edp + Xqd_ * psiqpp * ksat + Xq1_ * (iq - Xq3_ * (Edp + iq * Xq2_ - psiqp))); - - /* 11 Genrou algebraic equations */ - f_[6] = psiqpp - (-psiqp * Xq4_ - Edp * Xq5_); - f_[7] = psidpp - (psidp * Xd4_ + Eqp * Xd5_); - f_[8] = psipp - sqrt(pow(psidpp, 2.0) + pow(psiqpp, 2.0)); - f_[9] = ksat - SB_ * pow(psipp - SA_, 2.0); - f_[10] = vd + psiqpp * (1 + omega); - f_[11] = vq - psidpp * (1 + omega); - f_[12] = telec - ((psidpp - id * Xdpp_) * iq - (psiqpp - iq * Xdpp_) * id); - f_[13] = id - (ir * sin(delta) - ii * cos(delta)); - f_[14] = iq - (ir * cos(delta) + ii * sin(delta)); - f_[15] = ir + G_ * vr - B_ * vi - inr; - f_[16] = ii + B_ * vr + G_ * vi - ini; - - /* 2 Genrou control inputs are set to constant for this example */ - f_[17] = efd - efd_set_; - - /* 2 Genrou current source definitions */ - f_[18] = inr - (G_ * (sin(delta) * vd + cos(delta) * vq) - B_ * (-cos(delta) * vd + sin(delta) * vq)); - f_[19] = ini - (B_ * (sin(delta) * vd + cos(delta) * vq) + G_ * (-cos(delta) * vd + sin(delta) * vq)); - - /* Current balance */ - Ir() += inr - Vr() * G_ + Vi() * B_; - Ii() += ini - Vr() * B_ - Vi() * G_; - - return 0; - } - - /** - * @brief Jacobian evaluation not implemented yet - * - * @tparam ScalarT - scalar data type - * @tparam IdxT - matrix index data type - * @return int - error code, 0 = success - */ - template - int Genrou::evaluateJacobian() - { - std::cout << "Evaluate Jacobian for Genrou..." << std::endl; - std::cout << "Jacobian evaluation not implemented!" << std::endl; - return 0; - } - - /** - * @brief Access generator relative speed - * - * @tparam ScalarT - scalar data type - * @tparam IdxT - matrix index data type - * @return int - error code, 0 = success - */ - template - ScalarT Genrou::getSpeed() - { - return y_[1]; - } - - template - ScalarT Genrou::getTorque() - { - return y_[12]; - } + /** + * @brief Residual contribution of the branch is pushed to the + * two terminal buses. + * + */ + template + int Genrou::evaluateResidual() + { - template - void Genrou::setgovenor(gov_type* gov) - { - gov_ = gov; - } + // Inputs + ScalarT vr = Vr(); + ScalarT vi = Vi(); + ScalarT pmech = this->safeRead(pmech_signal_, pmech_set_); + + // Outputs + this->safeWrite(omega_signal_, y_[1]); + + /* Read variables */ + ScalarT delta = y_[0]; + ScalarT omega = y_[1]; + ScalarT Eqp = y_[2]; + ScalarT psidp = y_[3]; + ScalarT psiqp = y_[4]; + ScalarT Edp = y_[5]; + ScalarT psiqpp = y_[6]; + ScalarT psidpp = y_[7]; + ScalarT psipp = y_[8]; + ScalarT ksat = y_[9]; + ScalarT vd = y_[10]; + ScalarT vq = y_[11]; + ScalarT telec = y_[12]; + ScalarT id = y_[13]; + ScalarT iq = y_[14]; + ScalarT ir = y_[15]; + ScalarT ii = y_[16]; + ScalarT efd = y_[17]; + ScalarT inr = y_[18]; + ScalarT ini = y_[19]; + + /* Read derivatives */ + ScalarT delta_dot = yp_[0]; + ScalarT omega_dot = yp_[1]; + ScalarT Eqp_dot = yp_[2]; + ScalarT psidp_dot = yp_[3]; + ScalarT psiqp_dot = yp_[4]; + ScalarT Edp_dot = yp_[5]; + + /* 6 Genrou differential equations */ + f_[0] = delta_dot - omega * (2 * M_PI * 60); + f_[1] = omega_dot - (1 / (2 * H_)) * ((pmech - D_ * omega) / (1 + omega) - telec); + f_[2] = Eqp_dot - (1 / Tdop_) * (efd - (Eqp + Xd1_ * (id + Xd3_ * (Eqp - psidp - Xd2_ * id)) + psidpp * ksat)); + f_[3] = psidp_dot - (1 / Tdopp_) * (Eqp - psidp - Xd2_ * id); + f_[4] = psiqp_dot - (1 / Tqopp_) * (Edp - psiqp + Xq2_ * iq); + f_[5] = Edp_dot - (1 / Tqop_) * (-Edp + Xqd_ * psiqpp * ksat + Xq1_ * (iq - Xq3_ * (Edp + iq * Xq2_ - psiqp))); + + /* 11 Genrou algebraic equations */ + f_[6] = psiqpp - (-psiqp * Xq4_ - Edp * Xq5_); + f_[7] = psidpp - (psidp * Xd4_ + Eqp * Xd5_); + f_[8] = psipp - sqrt(pow(psidpp, 2.0) + pow(psiqpp, 2.0)); + f_[9] = ksat - SB_ * pow(psipp - SA_, 2.0); + f_[10] = vd + psiqpp * (1 + omega); + f_[11] = vq - psidpp * (1 + omega); + f_[12] = telec - ((psidpp - id * Xdpp_) * iq - (psiqpp - iq * Xdpp_) * id); + f_[13] = id - (ir * sin(delta) - ii * cos(delta)); + f_[14] = iq - (ir * cos(delta) + ii * sin(delta)); + f_[15] = ir + G_ * vr - B_ * vi - inr; + f_[16] = ii + B_ * vr + G_ * vi - ini; + + /* 2 Genrou control inputs are set to constant for this example */ + f_[17] = efd - efd_set_; + + /* 2 Genrou current source definitions */ + f_[18] = inr - (G_ * (sin(delta) * vd + cos(delta) * vq) - B_ * (-cos(delta) * vd + sin(delta) * vq)); + f_[19] = ini - (B_ * (sin(delta) * vd + cos(delta) * vq) + G_ * (-cos(delta) * vd + sin(delta) * vq)); + + /* Current balance */ + Ir() += inr - Vr() * G_ + Vi() * B_; + Ii() += ini - Vr() * B_ - Vi() * G_; + + return 0; + } - template - void Genrou::setDerivedParams() - { - SA_ = 0; - SB_ = 0; - if (S12_ != 0) + /** + * @brief Jacobian evaluation not implemented yet + * + * @tparam ScalarT - scalar data type + * @tparam IdxT - matrix index data type + * @return int - error code, 0 = success + */ + template + int Genrou::evaluateJacobian() { - real_type s112 = sqrt(S10_ / S12_); + std::cout << "Evaluate Jacobian for Genrou..." << std::endl; + std::cout << "Jacobian evaluation not implemented!" << std::endl; + return 0; + } - SA_ = (1.2 * s112 + 1) / (s112 + 1); - SB_ = (1.2 * s112 - 1) / (s112 - 1); - if (SB_ < SA_) - SA_ = SB_; - SB_ = S12_ / pow(SA_ - 1.2, 2); + template + void Genrou::setDerivedParams() + { + SA_ = 0; + SB_ = 0; + if (S12_ != 0) + { + real_type s112 = sqrt(S10_ / S12_); + + SA_ = (1.2 * s112 + 1) / (s112 + 1); + SB_ = (1.2 * s112 - 1) / (s112 - 1); + if (SB_ < SA_) + SA_ = SB_; + SB_ = S12_ / pow(SA_ - 1.2, 2); + } + Xd1_ = Xd_ - Xdp_; + Xd2_ = Xdp_ - Xl_; + Xd3_ = (Xdp_ - Xdpp_) / (Xd2_ * Xd2_); + Xd4_ = (Xdp_ - Xdpp_) / Xd2_; + Xd5_ = (Xdpp_ - Xl_) / Xd2_; + Xq1_ = Xq_ - Xqp_; + Xq2_ = Xqp_ - Xl_; + Xq3_ = (Xqp_ - Xqpp_) / (Xq2_ * Xq2_); + Xq4_ = (Xqp_ - Xqpp_) / Xq2_; + Xq5_ = (Xqpp_ - Xl_) / Xq2_; + Xqd_ = (Xq_ - Xl_) / (Xd_ - Xl_); + G_ = Ra_ / (Ra_ * Ra_ + Xqpp_ * Xqpp_); + B_ = -Xqpp_ / (Ra_ * Ra_ + Xqpp_ * Xqpp_); } - Xd1_ = Xd_ - Xdp_; - Xd2_ = Xdp_ - Xl_; - Xd3_ = (Xdp_ - Xdpp_) / (Xd2_ * Xd2_); - Xd4_ = (Xdp_ - Xdpp_) / Xd2_; - Xd5_ = (Xdpp_ - Xl_) / Xd2_; - Xq1_ = Xq_ - Xqp_; - Xq2_ = Xqp_ - Xl_; - Xq3_ = (Xqp_ - Xqpp_) / (Xq2_ * Xq2_); - Xq4_ = (Xqp_ - Xqpp_) / Xq2_; - Xq5_ = (Xqpp_ - Xl_) / Xq2_; - Xqd_ = (Xq_ - Xl_) / (Xd_ - Xl_); - G_ = Ra_ / (Ra_ * Ra_ + Xqpp_ * Xqpp_); - B_ = -Xqpp_ / (Ra_ * Ra_ + Xqpp_ * Xqpp_); - } - // Available template instantiations - template class Genrou; - template class Genrou; + // Available template instantiations + template class Genrou; + template class Genrou; - } // namespace PhasorDynamics -} // namespace GridKit + } // namespace PhasorDynamics + } // namespace GridKit diff --git a/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/Genrou.hpp b/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/Genrou.hpp index 7b8675550..9c257fdb2 100644 --- a/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/Genrou.hpp +++ b/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/Genrou.hpp @@ -18,9 +18,6 @@ namespace GridKit template class BusBase; - template - class GovernorBase; // <- TODO: Temporary, to be removed. - template struct GenrouData; } // namespace PhasorDynamics @@ -44,13 +41,17 @@ namespace GridKit using Component::yp_; using real_type = typename Component::real_type; - using gov_type = GovernorBase; using bus_type = BusBase; using model_data_type = GenrouData; public: Genrou(bus_type* bus, IdxT unit_id); - Genrou(bus_type* bus, const model_data_type& data); + Genrou(bus_type* bus, + bus_type* pmech_signal, + bus_type* omega_signal, + const model_data_type& data); + + // TODO remove, becoming hard to manage Genrou(bus_type* bus, IdxT unit_id, ScalarT p0, @@ -85,14 +86,6 @@ namespace GridKit { } - // Temporary access functions for governor - // Should be abstracted - ScalarT getSpeed(); - ScalarT getTorque(); - - // Temporary set governor function until SignalBus implemented - void setgovenor(gov_type* gov); - private: void setDerivedParams(); @@ -119,11 +112,11 @@ namespace GridKit private: /* Identification */ bus_type* bus_; - IdxT busID_{0}; - IdxT unit_id_; //< @todo this should be removed + bus_type* pmech_signal_; + bus_type* omega_signal_; - // Governor Pointer - gov_type* gov_; + IdxT busID_{0}; + IdxT unit_id_; //< @todo this should be removed /* Initial terminal conditions */ ScalarT p0_{0.0}; diff --git a/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/GenrouData.hpp b/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/GenrouData.hpp index 8e70c77c8..170939f99 100644 --- a/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/GenrouData.hpp +++ b/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/GenrouData.hpp @@ -39,6 +39,8 @@ namespace GridKit enum class GenrouPorts { bus, ///< Unique ID of the connecting bus + pmech_signal, ///< Unique ID of the governor Pmech signal. + speed_signal, ///< Unique ID of the speed signal of the machine. exciter_signal, ///< Unique ID of the bus providing the exciter signal governor_signal, ///< Unique ID of the bus providing the governor signal }; diff --git a/src/Model/PhasorDynamics/SystemModel.hpp b/src/Model/PhasorDynamics/SystemModel.hpp index dbb256a2c..95f6001b2 100644 --- a/src/Model/PhasorDynamics/SystemModel.hpp +++ b/src/Model/PhasorDynamics/SystemModel.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -124,12 +125,37 @@ namespace GridKit for (const auto& gendata : data.genrou) { IdxT bus_index = 0; - if (gendata.ports.contains(GenrouData::Ports::bus)) + IdxT pmech_index = 0; + IdxT speed_index = 0; + + bool has_bus = gendata.ports.contains(GenrouData::Ports::bus); + bool has_pmech_signal = gendata.ports.contains(GenrouData::Ports::pmech_signal); + bool has_speed_signal = gendata.ports.contains(GenrouData::Ports::speed_signal); + + if (has_bus && has_pmech_signal && has_speed_signal) { + bus_index = gendata.ports.at(GenrouData::Ports::bus); + pmech_index = gendata.ports.at(GenrouData::Ports::pmech_signal); + speed_index = gendata.ports.at(GenrouData::Ports::speed_signal); + + auto* gen = new Genrou( + getBus(bus_index), + getBus(pmech_index), + getBus(speed_index), + gendata); + addComponent(gen); + } + else{ + bus_index = gendata.ports.at(GenrouData::Ports::bus); + + auto* gen = new Genrou( + getBus(bus_index), + nullptr, + nullptr, + gendata); + addComponent(gen); } - auto* gen = new Genrou(getBus(bus_index), gendata); - addComponent(gen); } // Add classical generators @@ -144,6 +170,19 @@ namespace GridKit addComponent(gen); } + // Add governors + for (const auto& govdata : data.gov) + { + + /* Need to add signals to gendata class */ + auto* gov = new Governor::Tgov1( + getBus(govdata.signal_pmech), + getBus(govdata.signal_speed), + govdata); + + addComponent(gov); + } + // Add faults for (const auto& faultdata : data.bus_fault) { diff --git a/tests/UnitTests/PhasorDynamics/CMakeLists.txt b/tests/UnitTests/PhasorDynamics/CMakeLists.txt index 43e824dcb..336ef513c 100644 --- a/tests/UnitTests/PhasorDynamics/CMakeLists.txt +++ b/tests/UnitTests/PhasorDynamics/CMakeLists.txt @@ -35,6 +35,7 @@ target_link_libraries(test_phasor_system GRIDKIT::phasor_dynamics_load GRIDKIT::phasor_dynamics_branch GRIDKIT::phasor_dynamics_genrou GRIDKIT::phasor_dynamics_gen_classical + GRIDKIT::phasor_dynamics_governortgov1 GRIDKIT::phasor_dynamics_bus_fault GRIDKIT::phasor_dynamics_bus) diff --git a/tests/UnitTests/PhasorDynamics/GovernorTgov1Tests.hpp b/tests/UnitTests/PhasorDynamics/GovernorTgov1Tests.hpp index 479141082..651586231 100644 --- a/tests/UnitTests/PhasorDynamics/GovernorTgov1Tests.hpp +++ b/tests/UnitTests/PhasorDynamics/GovernorTgov1Tests.hpp @@ -27,13 +27,8 @@ namespace GridKit { TestStatus success = true; - auto* bus = new PhasorDynamics::Bus(1.0, 0.0); - - PhasorDynamics::Genrou* machine = - new PhasorDynamics::Genrou(bus, 1); - PhasorDynamics::Governor::Tgov1* gov = - new PhasorDynamics::Governor::Tgov1(machine); + new PhasorDynamics::Governor::Tgov1(); success *= (gov != nullptr); @@ -41,11 +36,6 @@ namespace GridKit { delete gov; } - if (machine) - { - delete machine; - } - delete bus; return success.report(__func__); } @@ -64,27 +54,8 @@ namespace GridKit TestStatus success = true; PhasorDynamics::Bus bus(1.0, 0.0); - PhasorDynamics::Genrou gen(&bus, - 1, - 1, - 0.05013, - 3, - 0, - 0, - 7, - 0.04, - 0.05, - 0.75, - 2.1, - 0.2, - 0.18, - 0.5, - 0.5, - 0.18, - 0.15, - 0, - 0); - PhasorDynamics::Governor::Tgov1 gov(&gen); + PhasorDynamics::Genrou gen(&bus, 1); + PhasorDynamics::Governor::Tgov1 gov; bus.allocate(); bus.initialize(); diff --git a/tests/UnitTests/Utilities/CMakeLists.txt b/tests/UnitTests/Utilities/CMakeLists.txt index d67e4f916..ff1fc5efb 100644 --- a/tests/UnitTests/Utilities/CMakeLists.txt +++ b/tests/UnitTests/Utilities/CMakeLists.txt @@ -1,6 +1,6 @@ -add_executable(test_case_format runCaseFormatTests.cpp) -target_include_directories(test_case_format PRIVATE ${THIRD_PARTY_DIR}/nlohmann-json/single_include ${THIRD_PARTY_DIR}/magic-enum/include) +#add_executable(test_case_format runCaseFormatTests.cpp) +#target_include_directories(test_case_format PRIVATE ${THIRD_PARTY_DIR}/nlohmann-json/single_include ${THIRD_PARTY_DIR}/magic-enum/include) -add_test(NAME UtilitiesCaseFormatTest COMMAND $) +#add_test(NAME UtilitiesCaseFormatTest COMMAND $) -install(TARGETS test_case_format) +#install(TARGETS test_case_format)