diff --git a/GridKit/Model/PhasorDynamics/CMakeLists.txt b/GridKit/Model/PhasorDynamics/CMakeLists.txt index 90ddb2abc..f0996614c 100644 --- a/GridKit/Model/PhasorDynamics/CMakeLists.txt +++ b/GridKit/Model/PhasorDynamics/CMakeLists.txt @@ -37,6 +37,7 @@ add_subdirectory(Exciter) add_subdirectory(Governor) add_subdirectory(Load) add_subdirectory(LoadZIP) +add_subdirectory(SignalSource) add_subdirectory(Stabilizer) add_subdirectory(SynchronousMachine) diff --git a/GridKit/Model/PhasorDynamics/ComponentLibrary.hpp b/GridKit/Model/PhasorDynamics/ComponentLibrary.hpp index e2ae075d2..c8555e324 100644 --- a/GridKit/Model/PhasorDynamics/ComponentLibrary.hpp +++ b/GridKit/Model/PhasorDynamics/ComponentLibrary.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include diff --git a/GridKit/Model/PhasorDynamics/SignalSource/CMakeLists.txt b/GridKit/Model/PhasorDynamics/SignalSource/CMakeLists.txt new file mode 100644 index 000000000..d193c3b31 --- /dev/null +++ b/GridKit/Model/PhasorDynamics/SignalSource/CMakeLists.txt @@ -0,0 +1,20 @@ +set(_install_headers ConstantSignalSource.hpp ConstantSignalSourceData.hpp) + +gridkit_add_library( + phasor_dynamics_signalsource + SOURCES ConstantSignalSource.cpp + HEADERS ${_install_headers} + LINK_LIBRARIES GridKit::phasor_dynamics_core GridKit::phasor_dynamics_signal) + +gridkit_add_library( + phasor_dynamics_signalsource_dependency_tracking + SOURCES ConstantSignalSourceDependencyTracking.cpp + LINK_LIBRARIES GridKit::phasor_dynamics_core GridKit::phasor_dynamics_signal_dependency_tracking) + +# Link to interface target for all components +target_link_libraries( + phasor_dynamics_components + INTERFACE GridKit::phasor_dynamics_signalsource) +target_link_libraries( + phasor_dynamics_components_dependency_tracking + INTERFACE GridKit::phasor_dynamics_signalsource_dependency_tracking) diff --git a/GridKit/Model/PhasorDynamics/SignalSource/ConstantSignalSource.cpp b/GridKit/Model/PhasorDynamics/SignalSource/ConstantSignalSource.cpp new file mode 100644 index 000000000..934d2e9e1 --- /dev/null +++ b/GridKit/Model/PhasorDynamics/SignalSource/ConstantSignalSource.cpp @@ -0,0 +1,13 @@ + +#include "ConstantSignalSourceImpl.hpp" + +namespace GridKit +{ + namespace PhasorDynamics + { + // Available template instantiations + template class ConstantSignalSource; + template class ConstantSignalSource; + + } // namespace PhasorDynamics +} // namespace GridKit diff --git a/GridKit/Model/PhasorDynamics/SignalSource/ConstantSignalSource.hpp b/GridKit/Model/PhasorDynamics/SignalSource/ConstantSignalSource.hpp new file mode 100644 index 000000000..14ca8c31d --- /dev/null +++ b/GridKit/Model/PhasorDynamics/SignalSource/ConstantSignalSource.hpp @@ -0,0 +1,71 @@ +#pragma once + +#include +#include + +namespace GridKit +{ + namespace PhasorDynamics + { + template + struct ConstantSignalSourceData; + + enum class ConstantSignalSourceInternalVariables : size_t + { + SREAL, + SIMAG, + MAXIMUM, + }; + + enum class ConstantSignalSourceExternalVariables : size_t + { + MAXIMUM, + }; + + template + class ConstantSignalSource : public Component + { + using Component::gridkit_component_id_; + using Component::size_; + + public: + using ScalarT = scalar_type; + using IdxT = index_type; + using RealT = typename Component::RealT; + using ModelDataT = ConstantSignalSourceData; + + ConstantSignalSource(); + ConstantSignalSource(const ModelDataT& data); + ~ConstantSignalSource(); + + int setGridKitComponentID(IdxT) override final; + int allocate() override final; + int verify() const override final; + int initialize() override final; + int tagDifferentiable() override final; + int evaluateResidual() override final; + int evaluateJacobian() override final; + + auto getSignals() + -> ComponentSignals& + { + return signals_; + } + + private: + ScalarT s_real_; + ScalarT s_imag_; + + IdxT sr_index_{INVALID_INDEX}; + IdxT si_index_{INVALID_INDEX}; + + ComponentSignals signals_; + + // Parameter initialization function + void initializeParameters(const ModelDataT& data); + }; + } // namespace PhasorDynamics +} // namespace GridKit diff --git a/GridKit/Model/PhasorDynamics/SignalSource/ConstantSignalSourceData.hpp b/GridKit/Model/PhasorDynamics/SignalSource/ConstantSignalSourceData.hpp new file mode 100644 index 000000000..5fad5c3ff --- /dev/null +++ b/GridKit/Model/PhasorDynamics/SignalSource/ConstantSignalSourceData.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include + +namespace GridKit +{ + namespace PhasorDynamics + { + enum class ConstantSignalSourceParameters + { + Sr, + Si + }; + + enum class ConstantSignalSourcePorts + { + sr, + si + }; + + enum class ConstantSignalSourceMonitorableVariables + { + NONE, + }; + + template + struct ConstantSignalSourceData : public ComponentData + { + ConstantSignalSourceData() = default; + + using Parameters = ConstantSignalSourceParameters; + using Ports = ConstantSignalSourcePorts; + using MonitorableVariables = ConstantSignalSourceMonitorableVariables; + }; + + } // namespace PhasorDynamics +} // namespace GridKit diff --git a/GridKit/Model/PhasorDynamics/SignalSource/ConstantSignalSourceDependencyTracking.cpp b/GridKit/Model/PhasorDynamics/SignalSource/ConstantSignalSourceDependencyTracking.cpp new file mode 100644 index 000000000..d3f1df113 --- /dev/null +++ b/GridKit/Model/PhasorDynamics/SignalSource/ConstantSignalSourceDependencyTracking.cpp @@ -0,0 +1,13 @@ + +#include "ConstantSignalSourceImpl.hpp" + +namespace GridKit +{ + namespace PhasorDynamics + { + // Available template instantiations + template class ConstantSignalSource; + template class ConstantSignalSource; + + } // namespace PhasorDynamics +} // namespace GridKit diff --git a/GridKit/Model/PhasorDynamics/SignalSource/ConstantSignalSourceImpl.hpp b/GridKit/Model/PhasorDynamics/SignalSource/ConstantSignalSourceImpl.hpp new file mode 100644 index 000000000..b446f3b1b --- /dev/null +++ b/GridKit/Model/PhasorDynamics/SignalSource/ConstantSignalSourceImpl.hpp @@ -0,0 +1,100 @@ + +#include +#include +#include + +namespace GridKit +{ + namespace PhasorDynamics + { + using Log = ::GridKit::Utilities::Logger; + + template + ConstantSignalSource::ConstantSignalSource() + { + size_ = 0; + } + + template + ConstantSignalSource::ConstantSignalSource(const ModelDataT& data) + { + initializeParameters(data); + size_ = 0; + } + + template + ConstantSignalSource::~ConstantSignalSource() + { + } + + template + void ConstantSignalSource::initializeParameters(const ModelDataT& data) + { + using Parameters = ModelDataT::Parameters; + if (data.parameters.contains(Parameters::Sr)) + { + s_real_ = std::get(data.parameters.at(Parameters::Sr)); + } + if (data.parameters.contains(Parameters::Si)) + { + s_imag_ = std::get(data.parameters.at(Parameters::Si)); + } + } + + template + int ConstantSignalSource::setGridKitComponentID(IdxT component_id) + { + gridkit_component_id_ = component_id; + return 0; + } + + template + int ConstantSignalSource::allocate() + { + static constexpr auto SREAL = ConstantSignalSourceInternalVariables::SREAL; + static constexpr auto SIMAG = ConstantSignalSourceInternalVariables::SIMAG; + + if (signals_.template isAssigned()) + { + signals_.template getSignalNode()->set(&s_real_, &sr_index_); + } + if (signals_.template isAssigned()) + { + signals_.template getSignalNode()->set(&s_imag_, &si_index_); + } + + return 0; + } + + template + int ConstantSignalSource::verify() const + { + return 0; + } + + template + int ConstantSignalSource::initialize() + { + return 0; + } + + template + int ConstantSignalSource::tagDifferentiable() + { + return 0; + } + + template + int ConstantSignalSource::evaluateResidual() + { + return 0; + } + + template + int ConstantSignalSource::evaluateJacobian() + { + return 0; + } + + } // namespace PhasorDynamics +} // namespace GridKit diff --git a/GridKit/Model/PhasorDynamics/SystemModelData.hpp b/GridKit/Model/PhasorDynamics/SystemModelData.hpp index d4deef66e..41f4fc60c 100644 --- a/GridKit/Model/PhasorDynamics/SystemModelData.hpp +++ b/GridKit/Model/PhasorDynamics/SystemModelData.hpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -49,6 +50,7 @@ namespace GridKit using GenClassicalDataT = GenClassicalData; using LoadDataT = LoadData; using LoadZIPDataT = LoadZIPData; + using ConstantSourceT = ConstantSignalSourceData; using SignalDataT = SignalNodeData; using MonitorSinkSpec = Model::VariableMonitorBase::SinkSpec; @@ -89,20 +91,21 @@ namespace GridKit /// - Convert string to enum /// - Associate component type to its corresponding enum /// - Consolidate components to allow writing to them using the enum as the argument - std::vector bus; ///< Buses within the model - std::vector adapter; ///< bus-to-signal adapters within the model - 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 gensal; ///< GENSAL instances within the model - std::vector genclassical; ///< Classical generator instances within the model - std::vector load; ///< Loads within the model - std::vector loadzip; ///< Loads within the model - std::vector gov; ///< Governors within the model - std::vector exciter; ///< Exciters within the model - std::vector sexspti; ///< SEXS-PTI exciters within the model - std::vector stabilizer; ///< Stabilizers within the model - std::vector signal; ///< Signal nodes + std::vector bus; ///< Buses within the model + std::vector adapter; ///< bus-to-signal adapters within the model + 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 gensal; ///< GENSAL instances within the model + std::vector genclassical; ///< Classical generator instances within the model + std::vector load; ///< Loads within the model + std::vector loadzip; ///< Loads within the model + std::vector gov; ///< Governors within the model + std::vector exciter; ///< Exciters within the model + std::vector sexspti; ///< SEXS-PTI exciters within the model + std::vector stabilizer; ///< Stabilizers within the model + std::vector constant_source; ///< Constant signal sources within the model + std::vector signal; ///< Signal nodes /// Monitor sink specs std::vector monitor_sink; diff --git a/GridKit/Model/PhasorDynamics/SystemModelDataJSONParser.hpp b/GridKit/Model/PhasorDynamics/SystemModelDataJSONParser.hpp index 00a6278c2..0fd190ea1 100644 --- a/GridKit/Model/PhasorDynamics/SystemModelDataJSONParser.hpp +++ b/GridKit/Model/PhasorDynamics/SystemModelDataJSONParser.hpp @@ -160,6 +160,12 @@ namespace GridKit raw_component.get_to(stabilizer); sm.stabilizer.push_back(stabilizer); } + else if (kind == "ConstantSignalSource") + { + typename SystemModelData::ConstantSourceT source; + raw_component.get_to(source); + sm.constant_source.push_back(source); + } else if (kind == "BusFault") { typename SystemModelData::BusFaultDataT bus_fault; diff --git a/GridKit/Model/PhasorDynamics/SystemModelImpl.hpp b/GridKit/Model/PhasorDynamics/SystemModelImpl.hpp index 891c2c57d..8c1fa2e69 100644 --- a/GridKit/Model/PhasorDynamics/SystemModelImpl.hpp +++ b/GridKit/Model/PhasorDynamics/SystemModelImpl.hpp @@ -351,6 +351,28 @@ namespace GridKit addComponent(stabilizer); } + // Add constant signal sources + for (const auto& srcdata : data.constant_source) + { + auto* source = new ConstantSignalSource(srcdata); + + using Ports = ConstantSignalSourcePorts; + if (srcdata.ports.contains(Ports::sr)) + { + IdxT sr = srcdata.ports.at(Ports::sr); + constexpr auto SREAL = ConstantSignalSourceInternalVariables::SREAL; + source->getSignals().template assignSignalNode(getSignal(sr)); + } + if (srcdata.ports.contains(Ports::si)) + { + IdxT si = srcdata.ports.at(Ports::si); + constexpr auto SIMAG = ConstantSignalSourceInternalVariables::SIMAG; + source->getSignals().template assignSignalNode(getSignal(si)); + } + + addComponent(source); + } + // Add faults for (const auto& faultdata : data.bus_fault) { diff --git a/examples/PhasorDynamics/Tiny/ThreeBus/CMakeLists.txt b/examples/PhasorDynamics/Tiny/ThreeBus/CMakeLists.txt index fa1ce561c..f284ab70b 100644 --- a/examples/PhasorDynamics/Tiny/ThreeBus/CMakeLists.txt +++ b/examples/PhasorDynamics/Tiny/ThreeBus/CMakeLists.txt @@ -1,3 +1,4 @@ add_subdirectory(Basic) add_subdirectory(Classical) +add_subdirectory(ConstantSource) add_subdirectory(ZipLoad) diff --git a/examples/PhasorDynamics/Tiny/ThreeBus/ConstantSource/CMakeLists.txt b/examples/PhasorDynamics/Tiny/ThreeBus/ConstantSource/CMakeLists.txt new file mode 100644 index 000000000..58f441e6b --- /dev/null +++ b/examples/PhasorDynamics/Tiny/ThreeBus/ConstantSource/CMakeLists.txt @@ -0,0 +1,7 @@ +gridkit_example_add_file(ThreeBusConstantSource.case.json) +gridkit_example_add_file(ThreeBusConstantSource.solver.json) + +add_test( + NAME ThreeBusConstantSource_pdsim + COMMAND DynamicSimulation ThreeBusConstantSource.solver.json + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/examples/PhasorDynamics/Tiny/ThreeBus/ConstantSource/ThreeBusConstantSource.case.json b/examples/PhasorDynamics/Tiny/ThreeBus/ConstantSource/ThreeBusConstantSource.case.json new file mode 100644 index 000000000..78a2c1c61 --- /dev/null +++ b/examples/PhasorDynamics/Tiny/ThreeBus/ConstantSource/ThreeBusConstantSource.case.json @@ -0,0 +1,165 @@ +{ + "header": { + "format_version": 0, + "format_revision": 1, + "case_name": "ThreeBusConstantSource", + "case_description": "3-bus test case with constant signal sources", + "case_comments": "None", + "freq_base": 60.0, + "va_base": 100e6 + }, + "buses": [ + { + "number": 1, + "class": "infinite_bus", + "name": "1", + "init": { + "Vr": 1.06, + "Vi": 0.0 + }, + "v_base": 138000.0, + "mon": [ + "Vm" + ] + }, + { + "number": 2, + "class": "bus", + "name": "2", + "init": { + "Vr": 1.0599558398065716, + "Vi": -0.009675621941024773 + }, + "v_base": 138000.0, + "mon": [ + "Vm" + ] + }, + { + "number": 3, + "class": "bus", + "name": "3", + "init": { + "Vr": 0.9610827543495831, + "Vi": -0.13122476630506485 + }, + "v_base": 138000.0, + "mon": [ + "Vm" + ] + } + ], + "signals": [ + { "signal_id": 1, "name": "ir1"}, + { "signal_id": 2, "name": "ir2"} + ], + "devices": [ + { + "class": "Branch", + "ports": { + "bus1": 1, + "bus2": 2 + }, + "id": "BR_0_1", + "params": { + "R": 0.05, + "X": 0.21, + "G": 0.0, + "B": 0.1 + } + }, + { + "class": "Branch", + "ports": { + "bus1": 1, + "bus2": 3 + }, + "id": "BR_0_2", + "params": { + "R": 0.06, + "X": 0.15, + "G": 0.0, + "B": 0.12 + } + }, + { + "class": "Branch", + "ports": { + "bus1": 2, + "bus2": 3 + }, + "id": "BR_1_2", + "params": { + "R": 0.08, + "X": 0.27, + "G": 0.0, + "B": 0.45 + } + }, + { + "class": "Load", + "ports": { + "bus": 3 + }, + "id": "load_2_0", + "params": { + "R": 0.4447197839297772, + "X": 0.20330047265361242 + } + }, + { + "class": "BusFault", + "ports": { + "bus": 3 + }, + "id": "bus_fault_2", + "params": { + "R": 0.0, + "X": 1e-5, + "state0": false + } + }, + { + "class": "Genrou", + "ports": { + "bus": 2 + }, + "id": "genrou_2_1", + "params": { + "p0": 0.5, + "q0": -0.07588, + "H": 2.7, + "D": 0.0, + "Ra": 0.0, + "Tdop": 7.0, + "Tdopp": 0.04, + "Tqopp": 0.05, + "Tqop": 0.75, + "Xd": 1.9, + "Xdp": 0.17, + "Xdpp": 0.15, + "Xq": 0.4, + "Xqp": 0.35, + "Xqpp": 0.15, + "Xl": 0.14999, + "S10": 0.0, + "S12": 0.0 + }, + "mon": [ + "speed" + ] + }, + { + "class": "BusToSignalAdapter", + "ports": {"bus":1, "ir":1, "ii":2}, + "id": "adapt3", + "params": [] + }, + { + "class": "ConstantSignalSource", + "ports": {"sr":1, "si":2}, + "id": "const_source_1", + "params": [] + } + ] +} diff --git a/examples/PhasorDynamics/Tiny/ThreeBus/ConstantSource/ThreeBusConstantSource.solver.json b/examples/PhasorDynamics/Tiny/ThreeBus/ConstantSource/ThreeBusConstantSource.solver.json new file mode 100644 index 000000000..479345c63 --- /dev/null +++ b/examples/PhasorDynamics/Tiny/ThreeBus/ConstantSource/ThreeBusConstantSource.solver.json @@ -0,0 +1,9 @@ +{ + "system_model_file": "ThreeBusConstantSource.case.json", + "dt": 0.00416666666666, + "tmax": 10, + "events": [ + {"time": 1, "type": "fault_on", "element_id": 0}, + {"time": 1.1, "type": "fault_off", "element_id": 0} + ] +}