diff --git a/examples/PhasorDynamics/Tiny/TwoBus/Basic/CMakeLists.txt b/examples/PhasorDynamics/Tiny/TwoBus/Basic/CMakeLists.txt index de388d37a..f215968d2 100644 --- a/examples/PhasorDynamics/Tiny/TwoBus/Basic/CMakeLists.txt +++ b/examples/PhasorDynamics/Tiny/TwoBus/Basic/CMakeLists.txt @@ -4,4 +4,4 @@ target_link_libraries(TwoBusBasic GRIDKIT::solvers_dyn) install(TARGETS TwoBusBasic RUNTIME DESTINATION bin) -add_test(NAME GenrouTest1 COMMAND $) +add_test(NAME TwoBusBasicTest COMMAND $) diff --git a/examples/PhasorDynamics/Tiny/TwoBus/Tgov1/CMakeLists.txt b/examples/PhasorDynamics/Tiny/TwoBus/Tgov1/CMakeLists.txt index e8fb96285..2a49ab28f 100644 --- a/examples/PhasorDynamics/Tiny/TwoBus/Tgov1/CMakeLists.txt +++ b/examples/PhasorDynamics/Tiny/TwoBus/Tgov1/CMakeLists.txt @@ -1,6 +1,7 @@ add_executable(TwoBusTgov1 TwoBusTgov1.cpp) target_link_libraries(TwoBusTgov1 GRIDKIT::phasor_dynamics_components + GRIDKIT::phasor_dynamics_signal GRIDKIT::solvers_dyn) install(TARGETS TwoBusTgov1 RUNTIME DESTINATION bin) diff --git a/examples/PhasorDynamics/Tiny/TwoBus/Tgov1/TwoBusTgov1.cpp b/examples/PhasorDynamics/Tiny/TwoBus/Tgov1/TwoBusTgov1.cpp index 8f84d93a2..8f8223d2e 100644 --- a/examples/PhasorDynamics/Tiny/TwoBus/Tgov1/TwoBusTgov1.cpp +++ b/examples/PhasorDynamics/Tiny/TwoBus/Tgov1/TwoBusTgov1.cpp @@ -1,5 +1,5 @@ /** - * @file TwoBusTgov1.cpp + * @file TwoBusTgov1Signal.cpp * @author Adam Birchfield (abirchfield@tamu.edu) * @author Slaven Peles (peless@ornl.gov) * @brief Example running a 2-bus system @@ -51,6 +51,15 @@ int main() data.bus[1].Vr0 = 1.0; data.bus[1].Vi0 = 0.0; + // Set signal nodes data + data.signal.resize(2); + + data.signal[0].name = "omega"; + data.signal[0].signal_id = 0; + + data.signal[1].name = "Pm"; + data.signal[1].signal_id = 1; + // Set branch data data.branch.resize(1); @@ -68,12 +77,6 @@ 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); @@ -96,9 +99,9 @@ int main() data.genrou[0].parameters[GenrouParameters::S10] = 0.; data.genrou[0].parameters[GenrouParameters::S12] = 0.; + // Set governor data (Default PW values) data.gov.resize(1); - // Set Gov data (Default PW values) data.gov[0].R = 0.05; data.gov[0].Pvmin = 0; data.gov[0].Pvmax = 1.0; @@ -107,32 +110,50 @@ 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 + // Manually add components + // This is a workaround since signal connections are not implemented in parser - // Create Pointers first - Genrou* gen; - Governor::Tgov1* gov; + // Create buses + auto* bus0 = BusFactory::create(data.bus[0]); + auto* bus1 = BusFactory::create(data.bus[1]); - // Instatiate Genrou & add to system model - gen = new Genrou( - sys.getBus(0), - data.genrou[0]); + // Create signal nodes + auto* omega = new SignalNode(data.signal[0]); + auto* pmech = new SignalNode(data.signal[1]); - // Instatiate GovernorTgov1 & add to system model - gov = new Governor::Tgov1( - gen, - data.gov[0]); - gen->setgovenor(gov); + // Create branch + Branch branch(bus0, bus1, data.branch[0]); - // Add Generator and Governor to System - sys.addComponent(gen); - sys.addComponent(gov); + // Add bus fault to bus0 + BusFault fault(bus0, data.bus_fault[0]); + + // Create generator + Genrou gen(bus0, + omega, + pmech, + data.genrou[0]); + + // Create governor + Governor::Tgov1 gov(pmech, omega); + + // + // Instantiate system model and add components to it + // + + SystemModel sys; + sys.addBus(bus0); + sys.addBus(bus1); + sys.addSignal(omega); + sys.addSignal(pmech); + sys.addComponent(&branch); + sys.addComponent(&gen); + sys.addComponent(&gov); + sys.addFault(&fault); sys.allocate(); // Get access to the fault - auto* fault = sys.getBusFault(0); + // auto* fault = sys.getBusFault(0); // Set time step to 1/4 of a 60Hz cycle real_type dt = 1.0 / 4.0 / 60.0; @@ -185,13 +206,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); @@ -255,5 +276,11 @@ int main() std::cout << "\n\nComplete in " << (stop - start) / CLOCKS_PER_SEC << " seconds\n"; + // Delete connectors created on heap + delete bus0; + delete bus1; + delete omega; + delete pmech; + return status; } diff --git a/src/Model/PhasorDynamics/BusBase.hpp b/src/Model/PhasorDynamics/BusBase.hpp index 0f2ca0945..64372f0e0 100644 --- a/src/Model/PhasorDynamics/BusBase.hpp +++ b/src/Model/PhasorDynamics/BusBase.hpp @@ -121,6 +121,11 @@ namespace GridKit return J_; } + virtual const IdxT busID() const + { + return bus_id_; + } + protected: const IdxT bus_id_{static_cast(-1)}; @@ -302,11 +307,6 @@ namespace GridKit throw "ERROR: Method not implemented!\n"; return gB_; } - - virtual const IdxT busID() const - { - return bus_id_; - } }; } // namespace PhasorDynamics diff --git a/src/Model/PhasorDynamics/CMakeLists.txt b/src/Model/PhasorDynamics/CMakeLists.txt index a54397d4a..7ad3e7ec9 100644 --- a/src/Model/PhasorDynamics/CMakeLists.txt +++ b/src/Model/PhasorDynamics/CMakeLists.txt @@ -12,4 +12,6 @@ add_subdirectory(Governor) add_subdirectory(Load) add_subdirectory(SynchronousMachine) +add_subdirectory(SignalNode) + add_library(GRIDKIT::phasor_dynamics_components ALIAS gridkit_phasor_dynamics_components) diff --git a/src/Model/PhasorDynamics/ComponentLibrary.hpp b/src/Model/PhasorDynamics/ComponentLibrary.hpp index 9aba244f7..417bdae4c 100644 --- a/src/Model/PhasorDynamics/ComponentLibrary.hpp +++ b/src/Model/PhasorDynamics/ComponentLibrary.hpp @@ -5,5 +5,6 @@ #include #include #include +#include #include #include diff --git a/src/Model/PhasorDynamics/Governor/Tgov1/CMakeLists.txt b/src/Model/PhasorDynamics/Governor/Tgov1/CMakeLists.txt index 36d5cf26e..164b89b07 100644 --- a/src/Model/PhasorDynamics/Governor/Tgov1/CMakeLists.txt +++ b/src/Model/PhasorDynamics/Governor/Tgov1/CMakeLists.txt @@ -9,6 +9,7 @@ gridkit_add_library(phasor_dynamics_governortgov1 Tgov1.cpp LINK_LIBRARIES GRIDKIT::phasor_dynamics_genrou + GRIDKIT::phasor_dynamics_signal 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..1be41020d 100644 --- a/src/Model/PhasorDynamics/Governor/Tgov1/Tgov1.cpp +++ b/src/Model/PhasorDynamics/Governor/Tgov1/Tgov1.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #define _USE_MATH_DEFINES @@ -22,16 +23,13 @@ namespace GridKit { namespace Governor { - - /*! - * @brief Constructor for Governor + /** * - * @param machine Generator Object - * @param data TGOV1 Data Object */ template - Tgov1::Tgov1(machine_type* machine, const model_data_type& data) - : machine_(machine), + Tgov1::Tgov1(signal_type* pmech, signal_type* omega, const model_data_type& data) + : pmech_(pmech), + omega_(omega), R_(data.R), Pvmin_(data.Pvmin), Pvmax_(data.Pvmax), @@ -40,14 +38,14 @@ namespace GridKit T3_(data.T3), Dt_(data.Dt) { - // 3 Internal Variables size_ = 3; } template - Tgov1::Tgov1(machine_type* machine) - : machine_(machine), + Tgov1::Tgov1(signal_type* pmech, signal_type* omega) + : pmech_(pmech), + omega_(omega), R_(0.05), Pvmin_(0), Pvmax_(1), @@ -56,7 +54,6 @@ namespace GridKit T3_(7.5), Dt_(0) { - // 3 Internal Variables size_ = 3; } @@ -68,11 +65,19 @@ namespace GridKit template int Tgov1::allocate() { + // Allocate local component data auto size = static_cast(size_); // avoid compiler warnings f_.resize(size); y_.resize(size); yp_.resize(size); tag_.resize(size); + + // Set output signal after allocation + // The signal is accessible to the generator + if (pmech_) + { + pmech_->set(&y_[2]); + } return 0; } @@ -83,9 +88,13 @@ namespace GridKit template int Tgov1::initialize() { + ScalarT p0{0}; // Initial mechanical = initial electric torque - ScalarT p0 = machine_->getTorque(); + if (pmech_) + { + p0 = y_[2]; //<- generator needs to be initialized first + } // Input Variables (Parameter for now) pref_ = R_ * p0; @@ -166,10 +175,12 @@ namespace GridKit template int Tgov1::evaluateResidual() { - // Input Variables - ScalarT omega = machine_->getSpeed(); - + ScalarT omega{0}; + if (omega_) + { + omega = omega_->read(); + } // Read Internal Variables ScalarT ptx = y_[0]; // y0 - Ptx ScalarT pv = y_[1]; // y1 - Pv diff --git a/src/Model/PhasorDynamics/Governor/Tgov1/Tgov1.hpp b/src/Model/PhasorDynamics/Governor/Tgov1/Tgov1.hpp index 2383775ba..63c9c3c0e 100644 --- a/src/Model/PhasorDynamics/Governor/Tgov1/Tgov1.hpp +++ b/src/Model/PhasorDynamics/Governor/Tgov1/Tgov1.hpp @@ -25,6 +25,9 @@ namespace GridKit template class Genrou; + template + class SignalNode; + } // namespace PhasorDynamics } // namespace GridKit @@ -47,13 +50,13 @@ 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 signal_type = SignalNode; public: - Tgov1(machine_type* machine, const model_data_type& data); - Tgov1(machine_type* machine); + Tgov1(signal_type* pmech, signal_type* omega, const model_data_type& data); + Tgov1(signal_type* pmech, signal_type* omega); ~Tgov1() = default; int allocate() override; @@ -72,8 +75,8 @@ namespace GridKit ScalarT& Pmech() override; private: - // Associated Machine Model - machine_type* machine_; + signal_type* pmech_{nullptr}; + signal_type* omega_{nullptr}; // Input parameters real_type R_; diff --git a/src/Model/PhasorDynamics/SignalNode/CMakeLists.txt b/src/Model/PhasorDynamics/SignalNode/CMakeLists.txt new file mode 100644 index 000000000..4bb43f79a --- /dev/null +++ b/src/Model/PhasorDynamics/SignalNode/CMakeLists.txt @@ -0,0 +1,21 @@ + +# [[ +# Author(s): +# - Cameron Rutherford +# - Slaven Peles +# ]] + +gridkit_add_library(phasor_dynamics_signal + SOURCES + SignalNode.cpp + OUTPUT_NAME + gridkit_phasor_dynamics_signal) + +# Link to interface target for all components +target_link_libraries(gridkit_phasor_dynamics_components INTERFACE GRIDKIT::phasor_dynamics_signal) + +gridkit_add_library(phasor_dynamics_signal_dependency_tracking + SOURCES + SignalNodeDependencyTracking.cpp + OUTPUT_NAME + gridkit_phasor_dynamics_signal_dependency_tracking) diff --git a/src/Model/PhasorDynamics/SignalNode/SignalNode.cpp b/src/Model/PhasorDynamics/SignalNode/SignalNode.cpp new file mode 100644 index 000000000..d0310c67d --- /dev/null +++ b/src/Model/PhasorDynamics/SignalNode/SignalNode.cpp @@ -0,0 +1,14 @@ +/** + * @file SignalNode model implementation. + */ +#include "SignalNodeImpl.hpp" + +namespace GridKit +{ + namespace PhasorDynamics + { + template class SignalNode; + template class SignalNode; + + } // namespace PhasorDynamics +} // namespace GridKit diff --git a/src/Model/PhasorDynamics/SignalNode/SignalNode.hpp b/src/Model/PhasorDynamics/SignalNode/SignalNode.hpp new file mode 100644 index 000000000..9968dbf44 --- /dev/null +++ b/src/Model/PhasorDynamics/SignalNode/SignalNode.hpp @@ -0,0 +1,315 @@ +#pragma once + +#include + +#include +#include + +namespace GridKit +{ + namespace PhasorDynamics + { + template + struct SignalNodeData; + } // namespace PhasorDynamics +} // namespace GridKit + +namespace GridKit +{ + namespace PhasorDynamics + { + /*! + * @brief SignalNode model implementation base class. + * + */ + template + class SignalNode : public Model::Evaluator + { + public: + using real_type = typename Model::Evaluator::real_type; + + SignalNode(); + SignalNode(const SignalNodeData& data); + + virtual ~SignalNode() = default; + + virtual int allocate() override; + virtual int initialize() override; + virtual int tagDifferentiable() override; + virtual int evaluateResidual() override; + virtual int evaluateJacobian() override; + + void set(ScalarT* signal_in); + ScalarT read() const; + void init(ScalarT signal_in); + + const IdxT signalId() const + { + return signal_id_; + } + + virtual IdxT size() override + { + return size_; + } + + virtual IdxT nnz() override + { + return nnz_; + } + + virtual bool hasJacobian() override + { + return false; + } + + virtual void updateTime(real_type /* t */, real_type /* a */) override + { + // No time to update in bus models + } + + virtual void setTolerances(real_type& rtol, real_type& atol) const override + { + rtol = rtol_; + atol = atol_; + } + + virtual void setMaxSteps(IdxT& msa) const override + { + msa = max_steps_; + } + + std::vector& y() override + { + return y_; + } + + const std::vector& y() const override + { + return y_; + } + + std::vector& yp() override + { + return yp_; + } + + const std::vector& yp() const override + { + return yp_; + } + + std::vector& tag() override + { + return tag_; + } + + const std::vector& tag() const override + { + return tag_; + } + + GridKit::LinearAlgebra::COO_Matrix& getJacobian() override + { + return J_; + } + + const GridKit::LinearAlgebra::COO_Matrix& getJacobian() const override + { + return J_; + } + + private: + ScalarT* signal_{nullptr}; + IdxT signal_id_{0}; + + protected: + const IdxT bus_id_{static_cast(-1)}; + + IdxT size_{0}; + IdxT nnz_{0}; + + std::vector y_; + std::vector yp_; + std::vector tag_; + std::vector f_; + + GridKit::LinearAlgebra::COO_Matrix J_; + + real_type time_; + real_type alpha_; + + real_type rtol_; + real_type atol_; + + IdxT max_steps_; + + // + // Adjoint sensitivity members + // + + std::vector g_{}; + std::vector yB_{}; + std::vector ypB_{}; + std::vector fB_{}; + std::vector gB_{}; + + std::vector param_{}; + std::vector param_up_{}; + std::vector param_lo_{}; + + // + // Public adjoint sensitivity methods (not yet implemented in components) + // + + public: + virtual IdxT sizeQuadrature() override + { + throw "ERROR: Method not implemented!\n"; + return 0; + } + + virtual IdxT sizeParams() override + { + throw "ERROR: Method not implemented!\n"; + return 0; + } + + std::vector& yB() override + { + throw "ERROR: Method not implemented!\n"; + return yB_; + } + + const std::vector& yB() const override + { + throw "ERROR: Method not implemented!\n"; + return yB_; + } + + std::vector& ypB() override + { + throw "ERROR: Method not implemented!\n"; + return ypB_; + } + + const std::vector& ypB() const override + { + throw "ERROR: Method not implemented!\n"; + return ypB_; + } + + std::vector& param() override + { + throw "ERROR: Method not implemented!\n"; + return param_; + } + + const std::vector& param() const override + { + throw "ERROR: Method not implemented!\n"; + return param_; + } + + std::vector& param_up() override + { + throw "ERROR: Method not implemented!\n"; + return param_up_; + } + + const std::vector& param_up() const override + { + throw "ERROR: Method not implemented!\n"; + return param_up_; + } + + std::vector& param_lo() override + { + throw "ERROR: Method not implemented!\n"; + return param_lo_; + } + + const std::vector& param_lo() const override + { + throw "ERROR: Method not implemented!\n"; + return param_lo_; + } + + int evaluateIntegrand() override + { + throw "ERROR: Method not implemented!\n"; + return 1; + } + + int initializeAdjoint() override + { + throw "ERROR: Method not implemented!\n"; + return 1; + } + + int evaluateAdjointResidual() override + { + throw "ERROR: Method not implemented!\n"; + return 1; + } + + int evaluateAdjointIntegrand() override + { + throw "ERROR: Method not implemented!\n"; + return 1; + } + + std::vector& getResidual() override + { + return f_; + } + + const std::vector& getResidual() const override + { + return f_; + } + + std::vector& getIntegrand() override + { + throw "ERROR: Method not implemented!\n"; + return g_; + } + + const std::vector& getIntegrand() const override + { + throw "ERROR: Method not implemented!\n"; + return g_; + } + + std::vector& getAdjointResidual() override + { + throw "ERROR: Method not implemented!\n"; + return fB_; + } + + const std::vector& getAdjointResidual() const override + { + throw "ERROR: Method not implemented!\n"; + return fB_; + } + + std::vector& getAdjointIntegrand() override + { + throw "ERROR: Method not implemented!\n"; + return gB_; + } + + const std::vector& getAdjointIntegrand() const override + { + throw "ERROR: Method not implemented!\n"; + return gB_; + } + + virtual const IdxT busID() const + { + return bus_id_; + } + }; + + } // namespace PhasorDynamics +} // namespace GridKit diff --git a/src/Model/PhasorDynamics/SignalNode/SignalNodeData.hpp b/src/Model/PhasorDynamics/SignalNode/SignalNodeData.hpp new file mode 100644 index 000000000..3a5854666 --- /dev/null +++ b/src/Model/PhasorDynamics/SignalNode/SignalNodeData.hpp @@ -0,0 +1,35 @@ +/** + * @file SignalNodeData.hpp + * @author Slaven Peles (peless@ornl.gov) + * @brief Modeling data for buses (nodes) + * + */ +#pragma once + +#include +#include +#include +#include + +namespace GridKit +{ + namespace PhasorDynamics + { + /** + * @brief Contains modeling data for a Bus + * + * @tparam RealT Real parameter data type + * @tparam IdxT Integer parameter data type + * + * Integer parameters are of the same type as matrix and vector indices. + * + * @todo Decide on naming scheme for model parameters. + */ + template + struct SignalNodeData + { + std::string name; ///< A name given to this bus + IdxT signal_id{0}; ///< The unique ID of the signal node + }; + } // namespace PhasorDynamics +} // namespace GridKit diff --git a/src/Model/PhasorDynamics/SignalNode/SignalNodeDependencyTracking.cpp b/src/Model/PhasorDynamics/SignalNode/SignalNodeDependencyTracking.cpp new file mode 100644 index 000000000..ea9d83ce8 --- /dev/null +++ b/src/Model/PhasorDynamics/SignalNode/SignalNodeDependencyTracking.cpp @@ -0,0 +1,14 @@ +/** + * @file SignalNode model implementation. + */ +#include "SignalNodeImpl.hpp" + +namespace GridKit +{ + namespace PhasorDynamics + { + template class SignalNode; + template class SignalNode; + + } // namespace PhasorDynamics +} // namespace GridKit diff --git a/src/Model/PhasorDynamics/SignalNode/SignalNodeImpl.hpp b/src/Model/PhasorDynamics/SignalNode/SignalNodeImpl.hpp new file mode 100644 index 000000000..c815855b9 --- /dev/null +++ b/src/Model/PhasorDynamics/SignalNode/SignalNodeImpl.hpp @@ -0,0 +1,72 @@ +/** + * @file SignalNode model implementation. + */ +#include "SignalNode.hpp" +#include + +namespace GridKit +{ + namespace PhasorDynamics + { + template + SignalNode::SignalNode() + : size_(0) + { + } + + template + SignalNode::SignalNode(const SignalNodeData& data) + : signal_id_(data.signal_id), + size_(0) + { + } + + template + int SignalNode::allocate() + { + return 0; + } + + template + int SignalNode::initialize() + { + return 0; + } + + template + int SignalNode::tagDifferentiable() + { + return 0; + } + + template + int SignalNode::evaluateResidual() + { + return 0; + } + + template + int SignalNode::evaluateJacobian() + { + return 0; + } + + template + void SignalNode::set(ScalarT* signal) + { + signal_ = signal; + } + + template + ScalarT SignalNode::read() const + { + return *signal_; + } + + template + void SignalNode::init(ScalarT signal) + { + *signal_ = signal; + } + } // namespace PhasorDynamics +} // namespace GridKit diff --git a/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/CMakeLists.txt b/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/CMakeLists.txt index 215d7562e..9170a327b 100644 --- a/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/CMakeLists.txt +++ b/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/CMakeLists.txt @@ -1,12 +1,16 @@ gridkit_add_library(phasor_dynamics_genrou SOURCES Genrou.cpp + LINK_LIBRARIES + PUBLIC GRIDKIT::phasor_dynamics_signal OUTPUT_NAME gridkit_phasor_dynamics_genrou) gridkit_add_library(phasor_dynamics_genrou_dependency_tracking SOURCES GenrouDependencyTracking.cpp + LINK_LIBRARIES + PUBLIC GRIDKIT::phasor_dynamics_signal_dependency_tracking OUTPUT_NAME gridkit_phasor_dynamics_genrou_dependency_tracking) diff --git a/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/Genrou.hpp b/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/Genrou.hpp index ed77d0864..8f6f527f2 100644 --- a/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/Genrou.hpp +++ b/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/Genrou.hpp @@ -18,6 +18,9 @@ namespace GridKit template class BusBase; + template + class SignalNode; + template class GovernorBase; // <- TODO: Temporary, to be removed. @@ -47,9 +50,11 @@ namespace GridKit using gov_type = GovernorBase; using bus_type = BusBase; using model_data_type = GenrouData; + using signal_type = SignalNode; public: Genrou(bus_type* bus, IdxT unit_id); + Genrou(bus_type* bus, signal_type* omega, signal_type* pmech, const model_data_type& data); Genrou(bus_type* bus, const model_data_type& data); Genrou(bus_type* bus, IdxT unit_id, @@ -90,9 +95,6 @@ namespace GridKit ScalarT getSpeed(); ScalarT getTorque(); - // Temporary set governor function until SignalBus implemented - void setgovenor(gov_type* gov); - private: void setDerivedParams(); @@ -118,12 +120,11 @@ namespace GridKit private: /* Identification */ - bus_type* bus_; - IdxT busID_{0}; - IdxT unit_id_; //< @todo this should be removed - - // Governor Pointer - gov_type* gov_; + bus_type* bus_; + signal_type* pmech_{nullptr}; + signal_type* omega_{nullptr}; + IdxT bus_id_{0}; + IdxT unit_id_; //< @todo this should be removed /* Initial terminal conditions */ ScalarT p0_{0.0}; diff --git a/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/GenrouImpl.hpp b/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/GenrouImpl.hpp index ad6a9ea7d..3c710418b 100644 --- a/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/GenrouImpl.hpp +++ b/src/Model/PhasorDynamics/SynchronousMachine/GENROUwS/GenrouImpl.hpp @@ -7,6 +7,7 @@ #include "Genrou.hpp" #include #include // <- TODO: Temporary, to be removed. +#include #include namespace GridKit @@ -25,9 +26,8 @@ namespace GridKit template Genrou::Genrou(bus_type* bus, IdxT unit_id) : bus_(bus), - busID_(0), + bus_id_(0), unit_id_(unit_id), - gov_(nullptr), // <- TODO: Temporary, to be removed. p0_(0.), q0_(0.), H_(3.), @@ -76,9 +76,8 @@ namespace GridKit real_type S10, real_type S12) : bus_(bus), - busID_(0), + bus_id_(0), unit_id_(unit_id), - gov_(nullptr), // <- TODO: Temporary, to be removed. p0_(p0), q0_(q0), H_(H), @@ -108,8 +107,7 @@ namespace GridKit template Genrou::Genrou(bus_type* bus, const model_data_type& data) : bus_(bus), - unit_id_(1), - gov_(nullptr) // <- TODO: Temporary, to be removed. + unit_id_(1) { if (data.parameters.contains(model_data_type::Parameters::p0)) { @@ -203,7 +201,116 @@ namespace GridKit if (data.ports.contains(model_data_type::Ports::bus)) { - busID_ = data.ports.at(model_data_type::Ports::bus); + bus_id_ = data.ports.at(model_data_type::Ports::bus); + } + + size_ = 20; + setDerivedParams(); + } + + /** + * @brief Constructor for a GENROU generator model with saturation + */ + template + Genrou::Genrou(bus_type* bus, signal_type* omega, signal_type* pmech, const model_data_type& data) + : bus_(bus), + pmech_(pmech), + omega_(omega), + unit_id_(1) + { + if (data.parameters.contains(model_data_type::Parameters::p0)) + { + p0_ = std::get(data.parameters.at(model_data_type::Parameters::p0)); + } + + if (data.parameters.contains(model_data_type::Parameters::q0)) + { + q0_ = std::get(data.parameters.at(model_data_type::Parameters::q0)); + } + + if (data.parameters.contains(model_data_type::Parameters::H)) + { + H_ = std::get(data.parameters.at(model_data_type::Parameters::H)); + } + + if (data.parameters.contains(model_data_type::Parameters::D)) + { + D_ = std::get(data.parameters.at(model_data_type::Parameters::D)); + } + + if (data.parameters.contains(model_data_type::Parameters::Ra)) + { + Ra_ = std::get(data.parameters.at(model_data_type::Parameters::Ra)); + } + + if (data.parameters.contains(model_data_type::Parameters::Tdop)) + { + Tdop_ = std::get(data.parameters.at(model_data_type::Parameters::Tdop)); + } + + if (data.parameters.contains(model_data_type::Parameters::Tdopp)) + { + Tdopp_ = std::get(data.parameters.at(model_data_type::Parameters::Tdopp)); + } + + if (data.parameters.contains(model_data_type::Parameters::Tqopp)) + { + Tqopp_ = std::get(data.parameters.at(model_data_type::Parameters::Tqopp)); + } + + if (data.parameters.contains(model_data_type::Parameters::Tqop)) + { + Tqop_ = std::get(data.parameters.at(model_data_type::Parameters::Tqop)); + } + + if (data.parameters.contains(model_data_type::Parameters::Xd)) + { + Xd_ = std::get(data.parameters.at(model_data_type::Parameters::Xd)); + } + + if (data.parameters.contains(model_data_type::Parameters::Xdp)) + { + Xdp_ = std::get(data.parameters.at(model_data_type::Parameters::Xdp)); + } + + if (data.parameters.contains(model_data_type::Parameters::Xdpp)) + { + Xdpp_ = std::get(data.parameters.at(model_data_type::Parameters::Xdpp)); + } + + if (data.parameters.contains(model_data_type::Parameters::Xq)) + { + Xq_ = std::get(data.parameters.at(model_data_type::Parameters::Xq)); + } + + if (data.parameters.contains(model_data_type::Parameters::Xqp)) + { + Xqp_ = std::get(data.parameters.at(model_data_type::Parameters::Xqp)); + } + + if (data.parameters.contains(model_data_type::Parameters::Xqpp)) + { + Xqpp_ = std::get(data.parameters.at(model_data_type::Parameters::Xqpp)); + } + + if (data.parameters.contains(model_data_type::Parameters::Xl)) + { + Xl_ = std::get(data.parameters.at(model_data_type::Parameters::Xl)); + } + + if (data.parameters.contains(model_data_type::Parameters::S10)) + { + S10_ = std::get(data.parameters.at(model_data_type::Parameters::S10)); + } + + if (data.parameters.contains(model_data_type::Parameters::S12)) + { + S12_ = std::get(data.parameters.at(model_data_type::Parameters::S12)); + } + + if (data.ports.contains(model_data_type::Ports::bus)) + { + bus_id_ = data.ports.at(model_data_type::Ports::bus); } size_ = 20; @@ -232,6 +339,12 @@ namespace GridKit y_.resize(static_cast(size_)); yp_.resize(static_cast(size_)); tag_.resize(static_cast(size_)); + + if (omega_) + { + omega_->set(&y_[1]); + } + return 0; } @@ -298,6 +411,10 @@ namespace GridKit // Set Setpoint mechanical power, which may or may not be used pmech_set_ = Te; + if (pmech_) + { + pmech_->init(Te); + } for (IdxT i = 0; i < size_; ++i) yp_[static_cast(i)] = 0.0; @@ -350,9 +467,9 @@ namespace GridKit ScalarT vr = Vr(); ScalarT vi = Vi(); ScalarT pmech; - if (gov_) + if (pmech_) { - pmech = gov_->Pmech(); + pmech = pmech_->read(); } else { @@ -436,12 +553,6 @@ namespace GridKit return y_[12]; } - template - void Genrou::setgovenor(gov_type* gov) - { - gov_ = gov; - } - template void Genrou::setDerivedParams() { diff --git a/src/Model/PhasorDynamics/SystemModel.hpp b/src/Model/PhasorDynamics/SystemModel.hpp index dbb256a2c..27d500297 100644 --- a/src/Model/PhasorDynamics/SystemModel.hpp +++ b/src/Model/PhasorDynamics/SystemModel.hpp @@ -4,18 +4,14 @@ #include #include +#include #include #include #include #include -// Temporary -#include -#include -#include -#include -#include -#include +// Include all components +#include namespace GridKit { @@ -36,6 +32,7 @@ namespace GridKit class SystemModel : public PhasorDynamics::Component { using bus_type = PhasorDynamics::BusBase; + using signal_type = PhasorDynamics::SignalNode; using component_type = PhasorDynamics::Component; using real_type = typename Model::Evaluator::real_type; @@ -89,6 +86,12 @@ namespace GridKit addBus(bus); } + for (const auto& signaldata : data.signal) + { + SignalNode* signal = new SignalNode(signaldata); + addSignal(signal); + } + // Add branches for (const auto& branchdata : data.branch) { @@ -410,6 +413,11 @@ namespace GridKit buses_.push_back(bus); } + void addSignal(signal_type* signal) + { + signals_.push_back(signal); + } + void addComponent(component_type* component) { components_.push_back(component); @@ -428,6 +436,13 @@ namespace GridKit return buses_[busid]; } + signal_type* getSignal(IdxT signalid) + { + // Need to implement mapping of signal IDs to signals in the system model + assert((signals_[signalid])->signalId() == signalid); + return signals_[signalid]; + } + /** * @brief Return pointer to a bus fault model * @@ -444,6 +459,7 @@ namespace GridKit private: std::vector buses_; + std::vector signals_; std::vector components_; std::vector faults_; diff --git a/src/Model/PhasorDynamics/SystemModelData.hpp b/src/Model/PhasorDynamics/SystemModelData.hpp index 4cddedabb..2d8aaa319 100644 --- a/src/Model/PhasorDynamics/SystemModelData.hpp +++ b/src/Model/PhasorDynamics/SystemModelData.hpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -31,6 +32,7 @@ namespace GridKit using GenrouDataT = GenrouData; using GenClassicalDataT = GenClassicalData; using LoadDataT = LoadData; + using SignalDataT = SignalNodeData; /// The version of the grid dynamics case format this system model was /// parsed from @@ -68,9 +70,10 @@ namespace GridKit std::vector branch; ///< Branches within the model std::vector bus_fault; ///< Bus faults within the model std::vector genrou; ///< GENROU instances within the model - std::vector genclassical; ///< GENROU instances within the model + std::vector genclassical; ///< Classical generator instances within the model std::vector load; ///< Loads within the model std::vector gov; ///< Governors within the model + std::vector signal; ///< Signal nodes }; } // namespace PhasorDynamics } // namespace GridKit diff --git a/tests/UnitTests/PhasorDynamics/CMakeLists.txt b/tests/UnitTests/PhasorDynamics/CMakeLists.txt index e1f2b161d..b5542d7b2 100644 --- a/tests/UnitTests/PhasorDynamics/CMakeLists.txt +++ b/tests/UnitTests/PhasorDynamics/CMakeLists.txt @@ -22,8 +22,9 @@ target_link_libraries(test_phasor_genrou GRIDKIT::phasor_dynamics_genrou add_executable(test_phasor_governortgov1 runGovernorTgov1Tests.cpp) target_link_libraries(test_phasor_governortgov1 GRIDKIT::phasor_dynamics_genrou - GRIDKIT::phasor_dynamics_governortgov1 - GRIDKIT::phasor_dynamics_bus) + GRIDKIT::phasor_dynamics_governortgov1 + GRIDKIT::phasor_dynamics_signal + GRIDKIT::phasor_dynamics_bus) add_executable(test_phasor_gen_classical runGenClassicalTests.cpp) target_link_libraries(test_phasor_gen_classical GRIDKIT::phasor_dynamics_gen_classical @@ -33,16 +34,12 @@ 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 +target_link_libraries(test_phasor_system GRIDKIT::phasor_dynamics_components GRIDKIT::phasor_dynamics_load_dependency_tracking - GRIDKIT::phasor_dynamics_branch - GRIDKIT::phasor_dynamics_genrou GRIDKIT::phasor_dynamics_genrou_dependency_tracking - GRIDKIT::phasor_dynamics_gen_classical GRIDKIT::phasor_dynamics_gen_classical_dependency_tracking - GRIDKIT::phasor_dynamics_bus_fault - GRIDKIT::phasor_dynamics_bus_fault_dependency_tracking - GRIDKIT::phasor_dynamics_bus) + GRIDKIT::phasor_dynamics_signal_dependency_tracking + GRIDKIT::phasor_dynamics_bus_fault_dependency_tracking) add_test(NAME PhasorDynamicsBusTest COMMAND $) add_test(NAME PhasorDynamicsBranchTest COMMAND $) diff --git a/tests/UnitTests/PhasorDynamics/GovernorTgov1Tests.hpp b/tests/UnitTests/PhasorDynamics/GovernorTgov1Tests.hpp index 479141082..20740512c 100644 --- a/tests/UnitTests/PhasorDynamics/GovernorTgov1Tests.hpp +++ b/tests/UnitTests/PhasorDynamics/GovernorTgov1Tests.hpp @@ -2,9 +2,12 @@ #include #include +#include #include #include +#include #include +#include #include #include @@ -27,13 +30,12 @@ namespace GridKit { TestStatus success = true; - auto* bus = new PhasorDynamics::Bus(1.0, 0.0); - - PhasorDynamics::Genrou* machine = - new PhasorDynamics::Genrou(bus, 1); + PhasorDynamics::Bus bus(1.0, 0.0); + PhasorDynamics::SignalNode pmech; + PhasorDynamics::SignalNode omega; PhasorDynamics::Governor::Tgov1* gov = - new PhasorDynamics::Governor::Tgov1(machine); + new PhasorDynamics::Governor::Tgov1(&pmech, &omega); success *= (gov != nullptr); @@ -41,11 +43,6 @@ namespace GridKit { delete gov; } - if (machine) - { - delete machine; - } - delete bus; return success.report(__func__); } @@ -63,39 +60,55 @@ 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); + using BusType = PhasorDynamics::BusData::BusType; + using GenrouParameters = PhasorDynamics::GenrouData::Parameters; + using GenrouPorts = PhasorDynamics::GenrouData::Ports; + + PhasorDynamics::BusData busdata; + busdata.bus_id = 0; + busdata.bus_type = BusType::DEFAULT; + busdata.Vr0 = 1.0; + busdata.Vi0 = 0.0; + + PhasorDynamics::GenrouData gendata; + gendata.ports[GenrouPorts::bus] = 0; + + gendata.parameters[GenrouParameters::p0] = 1.; + gendata.parameters[GenrouParameters::q0] = 0.05013; + gendata.parameters[GenrouParameters::H] = 3.; + gendata.parameters[GenrouParameters::D] = 0.; + gendata.parameters[GenrouParameters::Ra] = 0.; + gendata.parameters[GenrouParameters::Tdop] = 7.; + gendata.parameters[GenrouParameters::Tdopp] = .04; + gendata.parameters[GenrouParameters::Tqopp] = .05; + gendata.parameters[GenrouParameters::Tqop] = .75; + gendata.parameters[GenrouParameters::Xd] = 2.1; + gendata.parameters[GenrouParameters::Xdp] = 0.2; + gendata.parameters[GenrouParameters::Xdpp] = 0.18; + gendata.parameters[GenrouParameters::Xq] = 0.5; + gendata.parameters[GenrouParameters::Xqp] = 0.5; + gendata.parameters[GenrouParameters::Xqpp] = 0.18; + gendata.parameters[GenrouParameters::Xl] = 0.15; + gendata.parameters[GenrouParameters::S10] = 0.; + gendata.parameters[GenrouParameters::S12] = 0.; + + PhasorDynamics::Bus bus(busdata); + PhasorDynamics::SignalNode pmech; + PhasorDynamics::SignalNode omega; + PhasorDynamics::Genrou gen(&bus, &omega, &pmech, gendata); + // Create governor to be tested + PhasorDynamics::Governor::Tgov1 gov(&pmech, &omega); bus.allocate(); - bus.initialize(); - bus.evaluateResidual(); - + gov.allocate(); gen.allocate(); - gen.initialize(); - gen.evaluateResidual(); - gov.allocate(); + bus.initialize(); + gen.initialize(); gov.initialize(); + + bus.evaluateResidual(); + gen.evaluateResidual(); gov.evaluateResidual(); // Require results to be within machine precision