Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions examples/PhasorDynamics/Tiny/TwoBus/Tgov1/TwoBusTgov1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,14 +131,15 @@ int main()
// Add bus fault to bus0
BusFault<scalar_type, index_type> fault(bus0, data.bus_fault[0]);

// Create generator
Genrou<scalar_type, index_type> gen(bus0,
omega,
pmech,
data.genrou[0]);

// Create governor
Governor::Tgov1<scalar_type, index_type> gov(pmech, omega);
// Create generator and make its signal connections
Genrou<scalar_type, index_type> gen(bus0, data.genrou[0]);
gen.getSignals().template attachSignalNode<GenrouExternalVariables::PM>(pmech);
gen.getSignals().template assignSignalNode<GenrouInternalVariables::OMEGA>(omega);

// Create governor and make its signal connections
Governor::Tgov1<scalar_type, index_type> gov(data.gov[0]);
gov.getSignals().template assignSignalNode<Tgov1InternalVariables::PM>(pmech);
gov.getSignals().template attachSignalNode<Tgov1ExternalVariables::DELTAOMEGA>(omega);

//
// Instantiate system model and add components to it
Expand Down
1 change: 1 addition & 0 deletions src/Model/PhasorDynamics/Branch/Branch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#pragma once

#include <Model/PhasorDynamics/Component.hpp>
#include <Model/PhasorDynamics/ComponentSignals.hpp>

// Forward declarations.
namespace GridKit
Expand Down
1 change: 1 addition & 0 deletions src/Model/PhasorDynamics/BusFault/BusFault.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include <Model/PhasorDynamics/BusBase.hpp>
#include <Model/PhasorDynamics/Component.hpp>
#include <Model/PhasorDynamics/ComponentSignals.hpp>

// Forward declaration of BusData structure
namespace GridKit
Expand Down
1 change: 0 additions & 1 deletion src/Model/PhasorDynamics/Component.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#pragma once

#include <exception>
#include <vector>

#include <AutomaticDifferentiation/DependencyTracking/Variable.hpp>
Expand Down
117 changes: 117 additions & 0 deletions src/Model/PhasorDynamics/ComponentSignals.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#pragma once

#include <array>
#include <optional>
#include <type_traits>

#include <Model/PhasorDynamics/SignalNode/SignalNode.hpp>

namespace GridKit
{
namespace PhasorDynamics
{
/// Dummy `Variables` type for components with no variables
enum class NoVariables : size_t
{
MAXIMUM
};

/// Concept requiring an enum to have a `MAXIMUM` variant and that it have
/// the underlying type of `size_t`. This does not ensure the variant is
/// the actual maximum
template <typename T>
concept EnumHasMaximumValueAndIsSizeT = std::is_enum_v<T>
&& std::is_same_v<std::underlying_type_t<T>, size_t>
&& requires { T::MAXIMUM; };

/// Extension object for `Component`s adding methods and member variables
/// related to signal bus management
///
/// This is used by adding an instance in a field to your class and
/// exposing this field to others
template <class ScalarT, typename IdxT, typename InternalVariables, typename ExternalVariables>
requires EnumHasMaximumValueAndIsSizeT<InternalVariables>
&& EnumHasMaximumValueAndIsSizeT<ExternalVariables>
class ComponentSignals
{
public:
/// Attaches a signal node to an external variable on this component
template <ExternalVariables variable>
auto attachSignalNode(SignalNode<ScalarT, IdxT>* signal)
{
external_variable_signals_[static_cast<size_t>(variable)] = signal;
}

/// Check if a signal node has been attached to an external variable
template <ExternalVariables variable>
auto isAttached() -> bool
{
return static_cast<bool>(external_variable_signals_[static_cast<size_t>(variable)]);
}

/// Check if a signal node has been assigned to an internal variable
template <InternalVariables variable>
auto isAssigned() -> bool
{
return static_cast<bool>(internal_variable_signals_[static_cast<size_t>(variable)]);
}

/// Returns a signal node for an internal signal variable to be
/// attached to an external variable on another component
template <InternalVariables variable>
auto getSignalNode() -> SignalNode<ScalarT, IdxT>*
{
if (!internal_variable_signals_[static_cast<size_t>(variable)])
{
throw "A signal node has not been assigned to this internal variable";
}

return *internal_variable_signals_[static_cast<size_t>(variable)];
}

/// Returns the value of the specified external variable
template <ExternalVariables variable>
auto readExternalVariable() const -> ScalarT
{
if (!external_variable_signals_[static_cast<size_t>(variable)])
{
throw "A signal node has not been assigned to this external variable";
}

return (*external_variable_signals_[static_cast<size_t>(variable)])->read();
}

/// Writes a value to the specified external variable
template <ExternalVariables variable>
auto writeExternalVariable(ScalarT value)
{
if (!external_variable_signals_[static_cast<size_t>(variable)])
{
throw "A signal node has not been assigned to this external variable";
}

(*external_variable_signals_[static_cast<size_t>(variable)])->init(value);
}

/// Assign a signal node to an internal variable
template <InternalVariables variable>
auto assignSignalNode(SignalNode<ScalarT, IdxT>* node)
{
internal_variable_signals_[static_cast<size_t>(variable)] = node;
}

private:
/// Internal variables which may have a signal associated with them for
/// use elsewhere
std::array<std::optional<SignalNode<ScalarT, IdxT>*>,
static_cast<size_t>(InternalVariables::MAXIMUM)>
internal_variable_signals_;

/// External variables which may have a signal associated with them for
/// use internally
std::array<std::optional<SignalNode<ScalarT, IdxT>*>,
static_cast<size_t>(ExternalVariables::MAXIMUM)>
external_variable_signals_;
};
} // namespace PhasorDynamics
} // namespace GridKit
7 changes: 3 additions & 4 deletions src/Model/PhasorDynamics/Governor/README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
# **Governor Model**

> [!NOTE]
> No implementation yet.
# Governor Model

## Introduction

A governor models the control system that regulates the output power of a machine.

## Types

There are a few standard Governor models

- Turbine Governor (See [TGOV1](GovernorTgov1/README.md))
72 changes: 39 additions & 33 deletions src/Model/PhasorDynamics/Governor/Tgov1/Tgov1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* @author Adam Birchfield (abirchfield@tamu.edu)
* @author Wiktoria Zielinska (zielinskawa@ORNL.gov)
* @brief Definition of a Turbine Governor Model (IEEET1).
*
*/

#include "Tgov1.hpp"
Expand All @@ -25,21 +24,35 @@ namespace GridKit
namespace Governor
{
/**
* @brief Constructs a Tgov1 governor model from its parameters
*
* @param pmech $P_m$ internal variable signal node
* @param omega $\Delta_\omega$ external variable signal node
*/
template <class ScalarT, typename IdxT>
Tgov1<ScalarT, IdxT>::Tgov1(signal_type* pmech, signal_type* omega)
: R_(0.05),
Pvmin_(0),
Pvmax_(1),
T1_(0.5),
T2_(2.5),
T3_(7.5),
Dt_(0)
{
signals_.template assignSignalNode<Tgov1InternalVariables::PM>(pmech);
signals_.template attachSignalNode<Tgov1ExternalVariables::DELTAOMEGA>(omega);

// 3 internal variables
size_ = 3;
}

/**
* @brief Constructs a Tgov1 governor model using signal inputs directly.
*
* Initializes the model parameters and sets the internal model size.
* @brief Constructs a Tgov1 governor model from its parameters
Comment thread
superwhiskers marked this conversation as resolved.
*
* @param pmech Pointer to the mechanical power signal.
* @param omega Pointer to the rotor speed signal.
* @param data Model data containing parameter values for initialization.
* @param data Data to initialize the model from.
*/
template <class ScalarT, typename IdxT>
Tgov1<ScalarT, IdxT>::Tgov1(signal_type* pmech, signal_type* omega, const model_data_type& data)
: pmech_(pmech),
omega_(omega)
Tgov1<ScalarT, IdxT>::Tgov1(const model_data_type& data)
{
initializeParameters(data);
size_ = 3;
Expand All @@ -48,7 +61,8 @@ namespace GridKit
/**
* @brief Helper function to extract and assign model parameters.
*
* Parses values from the model_data_type and assigns them to internal parameters.
* Parses values from the model_data_type and assigns them to internal
* parameters.
*
* @param data Structure containing model parameters.
*/
Expand All @@ -59,51 +73,40 @@ namespace GridKit
{
R_ = std::get<real_type>(data.parameters.at(model_data_type::Parameters::R));
}

if (data.parameters.contains(model_data_type::Parameters::Pvmin))
{
Pvmin_ = std::get<real_type>(data.parameters.at(model_data_type::Parameters::Pvmin));
}

if (data.parameters.contains(model_data_type::Parameters::Pvmax))
{
Pvmax_ = std::get<real_type>(data.parameters.at(model_data_type::Parameters::Pvmax));
}

if (data.parameters.contains(model_data_type::Parameters::T1))
{
T1_ = std::get<real_type>(data.parameters.at(model_data_type::Parameters::T1));
}

if (data.parameters.contains(model_data_type::Parameters::T2))
{
T2_ = std::get<real_type>(data.parameters.at(model_data_type::Parameters::T2));
}

if (data.parameters.contains(model_data_type::Parameters::T3))
{
T3_ = std::get<real_type>(data.parameters.at(model_data_type::Parameters::T3));
}

if (data.parameters.contains(model_data_type::Parameters::Dt))
{
Dt_ = std::get<real_type>(data.parameters.at(model_data_type::Parameters::Dt));
}
}

template <class ScalarT, typename IdxT>
Tgov1<ScalarT, IdxT>::Tgov1(signal_type* pmech, signal_type* omega)
: pmech_(pmech),
omega_(omega),
R_(0.05),
Pvmin_(0),
Pvmax_(1),
T1_(0.5),
T2_(2.5),
T3_(7.5),
Dt_(0)
{
// 3 Internal Variables
size_ = 3;
}

/*!
* @brief Allocate memory for model
*
*/
template <class ScalarT, typename IdxT>
int Tgov1<ScalarT, IdxT>::allocate()
Expand All @@ -117,10 +120,11 @@ namespace GridKit

// Set output signal after allocation
// The signal is accessible to the generator
if (pmech_)
if (signals_.template isAssigned<Tgov1InternalVariables::PM>())
{
pmech_->set(&y_[2]);
signals_.template getSignalNode<Tgov1InternalVariables::PM>()->set(&y_[2]);
}

return 0;
}

Expand All @@ -134,7 +138,7 @@ namespace GridKit
ScalarT p0{0};

// Initial mechanical = initial electric torque
if (pmech_)
if (signals_.template isAssigned<Tgov1InternalVariables::PM>())
{
p0 = y_[2]; //<- generator needs to be initialized first
}
Expand Down Expand Up @@ -219,11 +223,13 @@ namespace GridKit
int Tgov1<ScalarT, IdxT>::evaluateResidual()
{
// Input Variables

ScalarT omega{0};
if (omega_)
if (signals_.template isAttached<Tgov1ExternalVariables::DELTAOMEGA>())
{
omega = omega_->read();
omega = signals_.template readExternalVariable<Tgov1ExternalVariables::DELTAOMEGA>();
}

// Read Internal Variables
ScalarT ptx = y_[0]; // y0 - Ptx
ScalarT pv = y_[1]; // y1 - Pv
Expand Down
Loading
Loading