DPsim
Loading...
Searching...
No Matches
SteamTurbineGovernor.cpp
1// SPDX-FileCopyrightText: 2026 Institute for Automation of Complex Power Systems, EONERC, RWTH Aachen University
2// SPDX-License-Identifier: MPL-2.0
3
4#include <dpsim-models/Signal/SteamTurbineGovernor.h>
5
6using namespace CPS;
7using namespace CPS::Signal;
8
9Signal::SteamTurbineGovernor::SteamTurbineGovernor(const String &name,
10 CPS::Logger::Level logLevel)
11 : SimSignalComp(name, name, logLevel),
12 mDelOm(mAttributes->create<Real>("DelOm")),
13 mP1(mAttributes->create<Real>("P1")), mP(mAttributes->create<Real>("P")),
14 mPgvLim(mAttributes->create<Real>("PgvLim")),
15 mPgv(mAttributes->create<Real>("Pgv")) {}
16
17void SteamTurbineGovernor::setParameters(
18 std::shared_ptr<Base::GovernorParameters> parameters) {
19 auto params =
20 std::dynamic_pointer_cast<Signal::SteamGovernorParameters>(parameters);
21 if (!params) {
22 SPDLOG_LOGGER_ERROR(
23 mSLog,
24 "Type of parameters class of {} has to be SteamGovernorParameters!",
25 this->name());
26 throw CPS::TypeException();
27 }
28 if (params->T3 <= 0) {
29 SPDLOG_LOGGER_ERROR(mSLog, "T3 must be positive for {}", this->name());
30 throw CPS::InvalidArgumentException();
31 }
32 if (params->R <= 0) {
33 SPDLOG_LOGGER_ERROR(mSLog, "R must be positive for {}", this->name());
34 throw CPS::InvalidArgumentException();
35 }
36 mParameters = params;
37
38 SPDLOG_LOGGER_INFO(mSLog,
39 "\nSteam Governor parameters:"
40 "\nOmRef: {:e}"
41 "\nR: {:e}"
42 "\nT1: {:e}"
43 "\nT2: {:e}"
44 "\nT3: {:e}"
45 "\ndPmax: {:e}"
46 "\ndPmin: {:e}"
47 "\nPmax: {:e}"
48 "\nPmin: {:e}"
49 "\nKbc: {:e}\n",
50 mParameters->OmRef, mParameters->R, mParameters->T1,
51 mParameters->T2, mParameters->T3, mParameters->dPmax,
52 mParameters->dPmin, mParameters->Pmax, mParameters->Pmin,
53 mParameters->Kbc);
54 mSLog->flush();
55}
56
58 if (Pref < 0 || Pref > 1) {
59 SPDLOG_LOGGER_ERROR(mSLog, "Pref of steam governor {} must be in [0, 1] pu",
60 this->name());
62 }
63 mPref = Pref;
64 **mDelOm = 0;
65 mDelOm_prev = 0;
66 mDelOm_2prev = 0;
67 **mP1 = 0;
68 mP1_prev = 0;
69 **mP = 0;
70 mDerPgv = 0;
71 **mPgvLim = Pref;
72 **mPgv = Pref;
73
74 if (mParameters->T1 == 0) {
75 mCa = 0;
76 mCb = 0;
77 } else {
78 mCa = mParameters->T2 / mParameters->T1;
79 mCb = (mParameters->T1 - mParameters->T2) / mParameters->T1;
80 }
81
82 SPDLOG_LOGGER_INFO(mSLog,
83 "\nSteam Governor initial values:"
84 "\nPref: {:f}"
85 "\nDelOm: {:f}"
86 "\nDerPgv: {:f}"
87 "\nPgv: {:f}",
88 mPref, **mDelOm, mDerPgv, **mPgv);
89 mSLog->flush();
90}
91
92Real SteamTurbineGovernor::step(Real Omega, Real dt) {
93 // Shift state variables one step back
94 mDelOm_2prev = mDelOm_prev;
95 mDelOm_prev = **mDelOm;
96 mP1_prev = **mP1;
97
98 // Compute input deviation
99 **mDelOm = mParameters->OmRef - Omega;
100
101 // Lead-lag controller K(1+sT2)/(1+sT1): if T1==0, use filtered-derivative form
102 if (mParameters->T1 == 0) {
103 **mP =
104 (1.0 / mParameters->R) *
105 (mDelOm_prev + (mParameters->T2 / dt) * (mDelOm_prev - mDelOm_2prev));
106 } else {
107 **mP1 = mP1_prev + (dt / mParameters->T1) * (mDelOm_prev * mCb - mP1_prev);
108 **mP = (1.0 / mParameters->R) * (mP1_prev + mDelOm_prev * mCa);
109 }
110
111 // Integrator with rate limiter and anti-windup
112 mDerPgv = (1.0 / mParameters->T3) * (mPref + **mP - **mPgv);
113 if (mDerPgv < mParameters->dPmin)
114 mDerPgv = mParameters->dPmin;
115 if (mDerPgv > mParameters->dPmax)
116 mDerPgv = mParameters->dPmax;
117 mDerPgv = mDerPgv - mParameters->Kbc * (**mPgvLim - **mPgv);
118
119 **mPgvLim = **mPgvLim + dt * mDerPgv;
120
121 // Output limiter
122 if (**mPgvLim < mParameters->Pmin)
123 **mPgv = mParameters->Pmin;
124 else if (**mPgvLim > mParameters->Pmax)
125 **mPgv = mParameters->Pmax;
126 else
127 **mPgv = **mPgvLim;
128
129 return **mPgv;
130}
void initializeStates(Real Pref) final
Set steady-state initial values (call after setParameters, before first step)
Real step(Real Omega, Real dt) final
Step the governor and return the valve/gate opening signal Pgv.
Logger::Log mSLog
Component logger.