Documente Academic
Documente Profesional
Documente Cultură
Tutorial Manual
May 2012 rev. 02
RTDS
Technologies
i
5 Using CBuilder to model a multithread component . . . . . . . . . . . 5.0
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.1
MultiFunction Relays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.2
MultiThread Component . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.3
Model Development Using CBuilder . . . . . . . . . . . . . . . . . . . . 5.5
MultiThread Model Algorithm . . . . . . . . . . . . . . . . . . . . . . . . 5.17
MultiThread Static Section . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.18
MultiThread Ram Section . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.19
MultiThread Code Section . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.21
ii
Add a Generic Output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.28
Add Monitoring Code . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7.30
iii
1
using CBUILDER to create
a multiple input adder
June 2010 rev. 01
RTDS
Technologies
using CBuilder to create a multiple input adder
INTRODUCTION
You will be building an adder component that can add or subtract
two or three inputs. This adder will be able to accept real type
inputs.
Parameter #2
Name: sign1
Description: Sign of Input 1
Type: TOGGLE
Unit/Toggle Entries:
Value: Add
Min: 0
Max: 1
Parameter #3
Name: sign2
Description: Sign of Input 2
Type: TOGGLE
Unit/Toggle Entries:
Value: Add
Min: 0
Max: 1
Parameter #4
Name: sign3
Description: Sign of Input 3
Type: TOGGLE
Unit/Toggle Entries:
Value: Add
Min: 0
Max: 1
Enabled Condition: numInputs>2
IO point fInput1
Name: fInput1
conn: SIGNAL INPUT
var: REAL
IO point fInput2
Name: fInput2
conn: SIGNAL INPUT
var: REAL
IO point fOutput
Name: fOutput
conn: SIGNAL OUTPUT
var: REAL
The input and output points appear under the INPUTS and
OUTPUTS sections and not the NODES section. This is a
controls component and the NODES section is reserved for power
system component electrical type nodes.
STATIC:
// use the mult variables to keep track of sign of input
int mult1;
int mult2;
int mult3;
RAM:
// the parameters sign1,sign2 and sign3 are toggles where
// 0 == plus and 1 == minus
// use the mult variables to keep track of sign of input
if (sign1 == 1)
mult1 = 1;
else
mult1 = 1;
if (sign2 == 1)
mult2 = 1;
else
mult2 = 1;
if (sign3 == 1)
mult3 = 1;
else
mult3 = 1;
CODE:
if (numInputs > 2)
fOutput = (mult1 * fInput1) + (mult2 * fInput2) + (mult3 * fInput3);
else
fOutput = (mult1 * fInput1) + (mult2 * fInput2);
RTDS
Technologies
INTRODUCTION
The integrator reads in one real input, integrates the input with a
user specified timeconstant (T) and writes one output. The basic
equations, based on trapezoidal rule of integration with a
simulation timestep of t, are used to compute the integral of the
input are as follows
X 1 Y
sT
1
Y(t) =
T
X(t) dt
t
1
Y(t) =
T
X(t) dt + Y(tt)
tt
1 t * [ X(tt) + x(t) ]
Y(t) =
T
{ 2 }+ Y(tt)
Y(t) =
t
2T
{ X(tt) + x(t) } + Y(tt)
Data Preparation
Algorithm
Read X;
Y= K * (Xold + X) + Yold;
Write Y;
The component icon for the integrator includes two I/O points.
One signal input named input and one signal output named output,
both are real.
Add a parameter T to specify the time constant (type REAL).
Input and Output points (listed under the IO Points tab) and
user defined parameters (listed under the Parameters tab) are
automatically associated with the model and placed in the .h file.
Left clicking the View .h file button opens the .h file in an editor.
A model that includes one input, one output and a parameter would
have the following lines in the .h file
INPUTS:
double input;
OUTPUTS:
double output;
PARAMETERS:
double T;
#include integrate.h
STATIC:
/* */
/* Variables declared here may be used in both the */
/* RAM: and CODE: sections below. */
/* */
double dt;
double input_old,output_old,K;
/* E n d o f S T A T I C : S e c t i o n */
RAM:
/* */
/* Place C code here which computes constants */
/* required for the CODE: section below. The C */
/* code here is executed once, prior to the start */
/* of the simulation case. */
/* */
dt= getTimeStep();
input_old = 0.0;
output_old = 0.0;
K = dt/(2.0*T);
/* E n d o f R A M : S e c t i o n */
CODE:
/* */
/* Place C code here which runs on the RTDS. The */
/* code below is entered once each simulation */
/* step. */
/* */
input_old = input;
output_old = output;
input_old = 0;
output_old = 0;
}
else
{
output = (input + input_old) * K + output_old;
input_old = input;
output_old = output;
}
RTDS
Technologies
INTRODUCTION
v(t)
i(t)
Current Injection
RTDS TECHNOLOGIES
RTDS TECHNOLOGIES INC.
INC. 3.1
the current injections, for preparing variables that are written out
for monitoring and preparing for the next timestep. Once the
second portion of code is completed the executable code is again
suspended until all of the variables transferred during the T2
communication interval have been transferred between
processors. Control type variables, monitored variables and node
voltages are exchanged during the T2 communication interval.
The node voltages are computed by the processor allocated to the
network solution and transferred to other processors in the rack.
As such, new node voltage data is available once the processors
are restarted for the next simulation time step.
RTDS TECHNOLOGIES
RTDS TECHNOLOGIES INC.
INC. 3.2
CAPACITOR
V(t) = VN1(t)VN2(t)
C
N1 N2
v(t)
R= t / 2C
i(t)
define
IH(t) = 2C * V(tt) i(tt)
t
RTDS TECHNOLOGIES
RTDS TECHNOLOGIES INC.
INC. 3.3
DRAW GRAPHICS AND ADD PARAMETERS
The component icon for the variable capacitor includes two power
system nodes and one signal input as shown below. The signal
input CVAL is used to read in variable capacitance values.
Add a parameter Cinit to specify the initial value of capacitance.
RTDS TECHNOLOGIES
RTDS TECHNOLOGIES INC.
INC. 3.4
ADDING THE MODEL CODE
RTDS TECHNOLOGIES
RTDS TECHNOLOGIES INC.
INC. 3.5
GVALUES: A conductance value (1/R) that the component places
between the nodes to which it is connected. Recall, that the
representation of the capacitor requires a resistor equal to t/(2C)
to be placed between the nodes to which the component is
connected. The equivalent conductance is equal to 1/R= 2C/t.
To add the GVALUE association select the Add Variable to .h File
button from the C File Associations Tab and select GVALUES for
the Section: value, Type: Real and enter the variable name to
which the conductance value will be assigned in the .c code.
RTDS TECHNOLOGIES
RTDS TECHNOLOGIES INC.
INC. 3.6
Left click to display pull down
RTDS TECHNOLOGIES
RTDS TECHNOLOGIES INC.
INC. 3.7
Basic Algorithm
RAM:
dt= getTimeStep();
invdt= 1.0/dt;
Ih= 0.0;
Gcap= 2.0 * Cinit * 1.0e6 * invdt;
The CODE: section computes the branch current for the capacitor,
the new conductance for the capacitance and the current injections
into the nodes between which the component is connected. All of
the code is assigned to the BEGIN_T0 portion since it is required
to compute the injection currents. The capacitance value is read
in as microfarads (ie. 1.0 is interpreted as 1.0e6 farads) so the
CVAL variable must be multiplied by 1.0e6before it can be used.
CODE:
BEGIN_T0:
RTDS TECHNOLOGIES
RTDS TECHNOLOGIES INC.
INC. 3.8
/* Compute branch current */
Vbra= N1 N2;
ib= Gcap*Vbra + Ih;
RTDS TECHNOLOGIES
RTDS TECHNOLOGIES INC.
INC. 3.9
ADDING AN OPTIONALLY MONITORED VARIABLE
RTDS TECHNOLOGIES
RTDS TECHNOLOGIES INC.
INC. 3.10
The new parameters MonI and Iname must be added to the .h file.
Select the Add New IO Points/Nodes/Parameters icon from
the C File Associations tab to add these new parameters.
To add the monitored variable parameter to the .h file, left click the
Add Variable to .h File button under the C File Associations tab.
Select create: Generic Outputs from the pulldown menu
associated with the Section: field and set Type: to REAL. Enter
a variable name (eg. IMON) to be used for assignment of the
monitored variable in the .c file. After selecting OK, the Edit
Output menu appears in which additional parameters for the
output variable may be specified.
Type: REAL
H File VAR: IMON
Output Name: Iname
Group: Branch Currents
Min Value: 100.0
Max Value: +100.0
Unit: kA
Condition: MonI==1
Min and Max values are used as the default limits for a meter or
plot component assigned to display the signal specified by Output
Name. The specified unit name also appears on the meter or plot
component in RSCAD/RunTime.
The create: OUTPUTS data line for the monitored output variable
appears as
RTDS TECHNOLOGIES
RTDS TECHNOLOGIES INC.
INC. 3.11
The C code statement to write out the monitored variable is as
follows
IMON = ib;
RTDS TECHNOLOGIES
RTDS TECHNOLOGIES INC.
INC. 3.12
4
using CBUILDER to
model a multimass system
June 2007 rev. 00
RTDS
Technologies
using CBuilder to model a multimass system
INTRODUCTION
Telec
Tmech
m
The basic equation of motion for a rotating mass stems from New-
tons Second Law of motion (commonly stated as F=mA) where
the Force is the difference between the mechanical torque applied
by a turbine and the electrical torque applied across the airgap of
the generator. Acceleration for the rotating mass is the rate of
change of its rotational speed (m). Instead of the mass of the ro-
tating body, the mass moment of inertia (J) is used. The moment
of inertia considers both the rotating bodys mass and its distribu-
tion around the axis of rotation.
d m
J
dt
= Tm Te (1)
H = 1 J 0m
2
2 VA base
J=2 H VA base (2)
2 0m
2H VA d m = T T (3)
base m e
2 0m dt
Noting that
m r
0m = 0 = pu (4)
VA T =T
T base = base ,
0m Tbase pu (5)
we rearrange equation (3) such that equations (4) and (5) may be
substituted.
2H d m = m
dt 0m
T Te
VA base 0m
(6)
dt 0
T Te
2H d r = m
VA
(7)
base 0m
2H d =
T T
dt
r
0 T
m e
(8)
base
r/0
1.0
2H t (sec)
Figure 1: mechanical starting time
DAMPING
In the equations for the rotating mass described above, there was
no consideration of damping. Removing the applied torque in the
example above results in the mass rotating at pu indefinitely. In
[4] a damping term proportional to r is introduced. Adding such
a term to (8) yields
dt 0
T Te
2H d r = m
T base
D r
0
(10)
dt 0
T Te
2H d r = m
T base
D r
0
(11)
r/0
1.0 no damping
D= 1 pu
2H t (sec)
application of constant torque
r/0
no damping
with damping
t (sec)
removal of torque
T 1 + E 1 W
D s(2H/D)
1
E(t) = T(t) w(t)
D
1
w(t) = E(t)
s(2H/D)
1
w(t) = [ 1/D*T(t) w(t) ]
s(2H/D)
1
w(t) =
2H
[T(t) D*w(t) ] dt
1st order lag function with Gain= 1/D and
time constant= 2H/D. Compare with
equation 11 above.
Telec
Turbine Generator
KTG
Mass Mass
T = K m (12)
mbase = 0m
VA
T base = base
0m
VA base
K base =
20m
0m: rated rotational speed of the mass
in mech. rad/sec.
T TG = K TG( T G)
T in pu if KTG, in pu
The equations of motion for the two rotating masses can now be
written
d gen
Generator Mass: 2H
dt
= T turb T e D gen gen (13)
d
Turbine Mass: 2H turb = T turb D turb turb
dt
(14)
T Te
Shaft Angle: T G = turb
K TG
(15)
(16)
All of the history terms (ie. those at tt) are known at the start of
a new timestep. 2H, D, K and t are constants and the new value
of applied torque T(t) is assumed to be known. The values (t) and
(t) are unknown at the beginning of the timestep. Using the rela-
tion (17a) and applying trapezoidal rule an expression for (t) can
be derived in terms of (t).
d = (17a)
dt
(t) (t t) (t) + (t t)
dt
=
2
(17b)
(t) = t (t) + (t t) + (t t)
2
(17c)
Equation 17c can be substituted into (16) to eliminate the (t) term
and leave (t) as the only unknown.
(t) 2 2H + D + t K =
t 2
t 2
T(t) + T(t t) + (t t) 2 2H D T K 2K(t t) (18)
defineA = t2 2H + D + t2 K (19)
B= t2 2H D t2 K
...
turbine turbine turbine turbine turbine generator exciters
#1 #2 #3 #4 #8 #1 & 2
The damping matrix includes both terms for the diagonal and off
diagonal elements. Diagonal elements represent the selfdamp-
ing factors (friction, windage) described above. Offdiagonal
terms represent the damping due to the twisting of the shaft. Under
transient conditions, when a varying torque is applied across the
shaft segments, the back and forth twisting of the shaft results in
heating and hence some damping. Data for this mutual damping
is often not available. Note that the mutual damping is across a
shaft segment so that only the n1, n and n+1 elements of the
damping matrix have nonzero terms.
X11 X12 0 0
X21 X22 X23 0
D= (22)
0 X32 X33 X34
0 0 X43 X44
Xmn: nonzero elements
a) Torque inputs to each turbine section and the generator (Te) will
be connected to input points. The user will thus be able to inter-
connect the governor/torque production model to the multimass
model via wires. The synchronous generator models Te output
signal can also be connected to the multimass model via a wire
component.
Input and output points for the multimass model are shown in the
Figure below.
T U R B I N E T O R Q U E I N P U T S Generator Mass
deltaomega Output
Tm1 Tm2 Tm3 Tm4 Tm5 Tm6 Tm7 Tm8 w
L/F
Te
S/M
Multimass Input / Output Points Generator Electrical
Torque Input
L/F
LPA LPB LPC LPD
HP IPA IPB IPC
W
EXC
Te
S/M
The generator mass and HP turbine mass are always drawn. If the
number of turbines is set less than 8, then unused turbine icons are
replaced by extending the shaft between the generator and last tur-
bine. Exciter masses are drawn only if selected.
EXC
Te
Logic is included as part of the component so that only the data re-
quired for the number of selected turbines needs to be entered.
Data items not required for the selected configuration appear grey
in the menus and cannot be selected for input.
f) The following data tabs are defined for the multimass compo-
nent
Mass Speed
Mass Angle with respect to the generator
Shaft Torque
Torque input for the HP Turbine, electrical Torque input to the gen-
erator and generator deltaomega output are always present. No
logic needs to be placed around these input / output points. Select
the create input/output point button from the drawing toolbar and
left click when the circle is positioned as shown below. Use the
create input/output function to create points for the HPT input, Te
input and deltaomega output signals. A popup menu asking for
the input/output point name and type (input or output, int or real)
appears. All of the torque inputs are specified as real type.
Drawing toolbar
Create Input/Output
Point button (left
click to select, left
click again to place
input/output point)
Data under the IO Points tab should appear as shown in the Figure
below once all of the input / output points and associated logic has
been entered.
Conditional logic
for the input torque
signals for each tur-
bine.
Conditional logic
for the Lock/Free
and Single/Multi
optional switches
Appearance of
drawing area after
entry of input / out-
put point data
L/F
LPA LPB LPC LPD
HP IPA IPB IPC
W
EXC
Te
S/M
Turbine blocks which are not enabled are replaced by a shaft sec-
tion for the components appearance in RSCAD/Draft. Exciter
masses are only drawn if enabled. L/F (Lock/Free) and S/M
(Single/Multi) input wires are only drawn if the user selects these
inputs are to come from a signal input rather than an RSCAD/Run-
Time switch.
To add a logic condition under the Graphics tab select the Add
Condition button and choose the if option from the pulldown. En-
ter the condition appropriate for the turbine section which is to be
drawn within the logic condition. Since either a shaft section or
turbine icon will be drawn, an ifelseendifstructure is required.
To add an else section, highlight the newly created ifEndIfcondi-
tion by left clicking on the If statement (the If and EndIf lines will
turn red). Left click the Add Condition button and this time select
Else from the pull down that appears.
if (nturb > 1)
Else
EndIf
If (EXCen > 0)
Draw shapes to represent exciter next to generator
EndIf
If (EXCen == 2)
Draw shapes to represent 2nd exciter
EndIf
To create the component data entry sections listed above, left click
the add section button in the control pane area of the RSCAD/C
Builder window. Enter the Section name in the menu that appears.
Once all of the data entry sections have been created, left click the
small arrow next to the section to which the parameters are to be
added. The arrow points down and the section heading is high-
lighted. Left click the add parameter button and fill in the ap-
propriate data in the menu that appears. The new parameter entry
element is added under the highlighted section.
To enable data entry for the IPA inertia constant only when the IPA
turbine is to be modelled, add the following logic condition to the
IPAH parameter entry
nturb > 1
There are two C code programs that must be written by the user
to complete the model. Firstly, a C program which computes the
constants required by the algorithm must be written. Secondly, the
program which executes the algorithm for the model must be writ-
ten. Only the second program runs on the RTDS hardware. Both
C programs are stored in the same file. A template for the C
file is created by selecting the Add Model button under the C
File Associations tab. The newly created file can be edited by se-
lecting the edit button.
Edit C File
All of the input / output signals and parameters, as well as, their
types are listed in a .h file which is automatically generated by C
Builder. The .h file is included as part of the C code using the
#include statement at the top of the C code file. As such, all of
the input / output and parameter signals may be used as part of the
C code. The simulation timestepmay be obtained by adding the
following statement into the C code
dt= getTimeStep();
RAM:
#define MAXMASS 11
double H[MAXMASS][MAXMASS];
double K[MAXMASS][MAXMASS];
double D[MAXMASS][MAXMASS];
double A[MAXMASS][MAXMASS];
double B[MAXMASS][MAXMASS];
The above matrices are declared under the RAM: section in the C
code file since they are only used for the data preparation. The ma-
trix Ainverse is required in both the data preparation and algorithm
portions of the C code and as such is declared under the STATIC:
section of the C code file.
STATIC:
double AINV[MAXMASS][MAXMASS];
Data storage into the matrices and arrays is such that the lowest
indexed entry is allocated to the High Pressure turbine. The next
entry to the IP turbine and so on. Generator data is entered into the
element pointed to by nturb. Exciter #1 is entered into the element
pointed to by nturb+1. For example if the user has specified that
four turbine masses are to be modelled (nturb=4) then the follow-
ing code would be used to load the H matrix elements. Note that
the inertia constants are loaded into the diagonal elements only
and that offdiagonal elements of the H matrix are 0.0.
H[0][0]= HPH;
H[1][1]= IPAH;
. . .
H[7][7]= LPAH;
H[nturb][nturb]= GENH;
H[nturb+1][nturb+1]= EXC1H;
H[nturb+2][nturb+2]= EXC2H;
nmass= nturb+1+EXCen;
K1= 4/dt;
K2= dt/2;
for (row=0;row<nmass;row++)
{
for (col=0;col<nmass;col++)
{
A[row][col]= H[row][col]*k1 +
D[row][col] + K[row][col]*k2;
B[row][col]= H[row][col]*k1
D[row][col] + K[row][col]*k2;
}
}
The inverse of the A matrix is required for the algorithm (see equa-
tion 21 above). An internal matrix inversion routine is available
to generate the required inverse matrix
i= matx_invert(nmass,A,MAXMASS,AINV,MAXMASS);
where
nmass= dimension of matrix to invert
A= matrix to invert
MAXMASS= dimension of matrices A and AINV
AINV= matrix to store inverse of A
STATIC:
double K2TRI0[3], BTRI0[3];
double K2TRI1[3], BTRI1[3];
. . .
double K2TRI10[3], BTRI10[3];
The K2TRI and BTRI vectors are loaded from the K and B vectors.
for (i=0;i<3;i++)
{
BRTRI0[i]= B[0][i];
K2TRI0= 2.0 * K[0][i];
. . .
BTRI10[i]= B[10][i+8];
K2TRI10[i]= 2.0 * K[10][i+8];
}
Printing to the .map file may be done using the following structure
of the fprintf statement
Now that all of the constants required for the algorithm have been
computed, the C code to implement the algorithm itself can be
written. Code to execute the model algorithm is placed under the
CODE: section in the C file template. The basic structure of the
code is as follows
variable declarations
initializing
If (mode == lock)
{
set all mass speeds
}
Else if (mode = single)
{
solve one mass model
}
Else
{
compute multimass algorithm
}
write output signals
for (ii=0;ii<nmass;ii++)
{
BCOL[ii]= T[ii]+BW[ii]K2TH[ii];
}
step 3b) compute [Bcol]= [Bcol] + [T]. The [T] vector is the latest
shaft torques which must first be read in from the external source.
Only those input torques associated with masses that are actually
modelled may be read in. Once read, the new shaft torques can be
added to the [BCOL] vector computed in step 3a.
T[0]= HPT;
if (nturb == 8)
{
T[1]= IPAT;
T[2]= IPBT;
T[3]= IPCT;
T[4]= LPAT;
T[5]= LPBT;
T[6]= LPCT;
T[7]= LPDT;
}
else if (nturb == 7)
{
. . .
}
. . .
else if (nturb == 2)
{
T[1]= IPAT;
}
for (ii=0;ii<nmass;ii++)
{
BCOL[ii]= BCOL[ii] + T[ii];
}
Step 4) Compute [w]= [Ainv]*[BCOL]. Matrix [Ainv] is stored
as a full nxn matrix and as such for loops can be used to compute
for (ii=0;ii<nmass;ii++)
{
w[ii]= 0.0
for (jj=0;jj<nmass;jj++)
{
w[ii]= w[ii] +
Ainv[ii][jj]*BCOL[jj];
}
}
Step 5) With the new speeds of each modelled mass known from
step 4, it is now possible to compute the angles of each mass. The
computed mass angles are used in step 2 during the next timestep
in the computation of speed. The vector THold is used to store the
newly computed values of mass angles.
dt2= 0.5*delt;
for (ii=0;ii<nmass;ii++)
{
THold[ii]= THold[ii] +
dt2*(wold[ii] + w[ii]);
}
for (ii=0;ii<nturb;ii++)
{
THold[ii]=
THold[ii] THold[nturb];
}
THold[nturb+1]=
THold[nturb+1]THold[nturb];
THold[nturb+2]=
THold[nturb+2]THold[nturb];
THold[nturb]= 0.0;
step 6) Now that the multimass algorithm has been solved, moni-
tored variables can be prepared. All of the computations done
within the algorithm are based on perunit quantities. Monitored
variables need to be converted to the desired units prior to being
written out. The following conversions are done
Shaft torques are computed using the angle across the shaft. For
example, to compute the torque across the shaft connecting the HP
and IPA masses
if (lfm > 0)
{
lfmode= lfswinp;
}
else
{
lfmode= lfsw;
}
Both the lfswinp and lfsw variables are defined in the .h file that
is created when the component is compiled.
k3= 1.0;
if (rpsinit == 0) k3= rps/omo;
if (lfmode == 1)
{
for (ii=0;ii<nmass;ii++)
{
w[ii]= k3;
}
}
The variable k3 is set to 1.0 (ie. 1.0 perunit speed represents syn-
chronous speed) if the rpsinit parameter is set to synchronous
speed (rpsinit == 1 (Yes)) by the user. If the rpsinit parameter is
set to nonsynchronous speed (rpsinit == 0 (No)) then the speci-
fied initial speed is used to compute the initial perunit speed of
the machine and this value is used for all of the modelled mass
speeds when operating in lock mode.
When in lock mode or within the first time steps, the angles of each
modelled mass can be computed based on the torque applied to
each mass and the shaft spring constant. If there is only one turbine
mass then the angle between the turbine and the generator may be
computed as
THold[0]= Te / LPDGENK;
If two turbine masses are modelled the initial mass angles are com-
puted as
THold[1]= Te / LPDGENK;
THold[2]= THold[1] + (TeIPAT)/HIPPAK;
Initial angles for the exciters are set to 0.0 since no external torque
is applied to the exciters.
If the mode switches are set so that the lock/free is free and single/
multi is set to single, then all of the modelled masses are consid-
ered as one lumped mass. The torque applied to the lumped mass
is equal to the sum of torques read in and the inertia constant of the
equivalent mass is equal to the sum of all the modelled mass inertia
constants. Self damping terms for all modelled masses are
summed to give an equivalent self damping factor for the equiva-
lent mass. Mass speed is computed as
REFERENCES
RTDS
Technologies
using CBuilder to model a multithread component
INTRODUCTION
MULTIFUNCTION RELAYS
MULTIFUNCTIONAL RELAY
21P,21G,50BF,68,79
Multi
Function
Relay
MULTITHREAD COMPONENT
250.0
usec
0.0
5
79, timers, outputs
4
85, SAED
3
Z3, 68OOS
2
Z2, plots
1
Z1, phase selection
0
Input samples, seq components, directional 0.002083
Drawing toolbar
Create Input/Output
Point button (left
click to select, left
click again to place
input/output point)
MONITORING: signal name for trigger count and signal name for
analog input sampled data. Names for monitored signals should
only be entered if plotting is enabled.
plots=1
To create the component data entry sections listed above, left click
the add section button in the control pane area of the
RSCAD/CBuilder window. Enter the Section name in the menu
that appears. None of the sections need an associated logic
condition.
Once all of the data entry sections have been created, left click the
small arrow next to the section to which the parameters are to be
added. The arrow points down and the section heading is
highlighted. Left click the add parameter button and fill in the
appropriate data in the menu that appears. The new parameter
entry element is added under the highlighted
section.
parameters state.
There are two C code programs that must be written by the user
to complete the model. First, a C program which computes the
constants required by the algorithm must be written. Secondly, the
program which executes the algorithm for the model must be
written. Only the second program runs on the RTDS hardware.
Both C programs are stored in the same file. A template for the
C file is created by selecting the Add Model button under the
C File Associations tab. The newly created file can be edited by
selecting the edit button.
Edit C File
All of the input / output signals and parameters, as well as, their
types are listed in a .h file which is automatically generated by
CBuilder. The .h file is included as part of the C code using the
#include statement at the top of the C code file. As such, all of
the input / output and parameter signals may be used as part of the
C code. The simulation timestepmay be obtained by adding the
following statement into the C code
dt= getTimeStep();
The main portion DFT will use an 8 point buffer to determine the
DC, fundamental, and second harmonic content of the analog
input. The starting point of the buffer can be initialized such that
the phasor will be at angle zero.
Printing to the .map file may be done using the following structure
of the fprintf statement
Now that all of the constants required for the algorithm have been
computed, the C code to implement the algorithm itself can be
written. Code to execute the model algorithm is placed under the
CODE: section in the C file template. The basic structure of the
code is shown on pages 18 26.
// Other variables
double dt,del,fracdel,nThread,nThreadInv;
int sample_new,trig,trigcnt,trigcnt_old,nThreadInt;
int ip1,ip2,ip3,ip4,ip5,ip6,ip7,ip8,nfrac,dthalf;
int start1,start2,start3,start4,start5,start6;
double va_re,va_im,va2_re,va2_im;
double temp_re, temp_im, os1_1,os1_2;
double inv_dt,bfreq,favg;
double e_timer,f_timer,w_tan1,w_tan2,f_F13;
double f_sample_t,meas1,meas1old,hold1,tmp;
double va_buff[8];
int n_1[3], n_2[3],int idx;
double FUND_FACTOR,DC_FACTOR,_2ND_FACTOR;
double A[5], B[5], C[5],a_bre, a_bim;
/* E n d o f S T A T I C : S e c t i o n */
OUTPUTS:
intcnt_old = createOutput(nP1, strcat2(Relays|,iedName),0,100,NA,p1&&plots);
int i,k,nsn;
double nsf,wcp,cosn,x;
if(freq==0)
{
SF = 0.480;
fc = 160.0;
} else {
SF = 0.400;
fc = 133.33;
}
dt = getTimeStep();// Simulation time step
nThreadInt = 7;
nThread = 7.0;
nThreadInv = 1.0 / nThread;
fracdel = nThread * dt;// RSCAD time step,delay is multiple # of
threads
del = fracdel;
dthalf = 0.5*del; // Pick Up Delay Calculation
tdpu_ip1 = 0.0;
tdpu_ip2 = 0.0;
tdpu_ip3 = 0.0;
tdpu_ip4 = 0.0;
tdpu_ip5 = 0.0;
tdpu_ip6 = 0.0;
tddo_ip1 = 0.0;
tddo_ip2 = 0.0;
tddo_ip3 = 0.0;
tddo_ip4 = 0.0;
tddo_ip5 = 0.0;
tddo_ip6 = 0.0;
ip1 = 0;
ip2 = 0;
ip3 = 0;
ip4 = 0;
ip5 = 0;
ip6 = 0;
ip7 = 0;
ip8 = 0;
start1 = 0;
start2 = 0;
start3 = 0;
start4 = 0;
start5 = 0;
start6 = 0;
// INPUT processing Initialization
nsn = 1;
nsf = 1.0;
inv_dt = 1.0 / dt;
f_sample_t = 0.001 / SF;
bfreq = SF * 125.0;
favg = bfreq;
idx = 6; // 6 samples to rotate by 270, normalizes Aph to 0.0 deg
e_timer= 0.0; // timer to enable freq tracking
f_timer= 10.25*dt; // adjustment to help zero the phase
// LP Filter constants calculations
for( k = 0; k < nsn; ++k )
{
wcp = sin( fc * PI * dt ) / cos( fc * PI * dt );
cosn = cos(( 2.0 * ( k + nsf + 1.0 ) 1.0 ) * PI / ( 4.0 * nsf ));
x = 1.0 / ( 1.0 + wcp * wcp 2.0 * wcp * cosn );
A[ k ] = wcp * wcp * x;
B[ k ] = 2.0 * ( wcp * wcp 1.0 ) * x;
C[ k ] = ( 1.0 + wcp * wcp + 2.0 * wcp * cosn ) * x;
}
for(i=0;i<8;i++)
{
va_buff[i]=0.0;
}
FUND_FACTOR=0.176776695; // for RMS => 0.5*(1/sqrtN)
FUND_FACTOR=FUND_FACTOR*1.009910335; // adjust for
the loss in the BW Filt at 160.0 FC
_2ND_FACTOR=FUND_FACTOR*1.135933359; // adjust for
the loss in the BW Filt
DC_FACTOR=0.125;
/* E n d o f R A M : S e c t i o n */
meas1 = IN9;
// Butterworth Filter for antialiasing 2nd order LP
// VA first stage
tmp = B[ 0 ] * os1_1 + C[ 0 ] * os1_2 + A[ 0 ] * meas1;
meas1 = tmp + 2.0 * os1_1 + os1_2;
os1_2 = os1_1;
os1_1 = tmp;
meas1old = hold1;
f_F13 = f_timer;
e_timer = e_timer + dt;
f_timer = f_timer + dt;
if(f_timer > f_sample_t)
{
// linear interpolation
tmp = ((meas1 meas1old) * inv_dt) * (f_sample_t f_F13);
meas1 = tmp + meas1old;
// 8 SAMPLE BUFFER
va_buff[idx] = meas1;
idx = idx+1;
idx = idx % 8;
// DFT FOR THE VOLTAGES AND CURRENTS
A1DC=(va_buff[0]+va_buff[1]+va_buff[2]+va_buff[3]+va_buff
[4]+va_buff[5]+va_buff[6]+va_buff[7])*DC_FACTOR;
va_re=(va_buff[0]va_buff[4]+
INV_ROOT2*(va_buff[1]va_buff[3]va_buff[5]+va_buff[7]))
*FUND_FACTOR;
va_im=(va_buff[2]+va_buff[6]+INV_ROOT2*(va_buff[1]v
a_buff[3]+va_buff[5]+va_buff[7]))*FUND_FACTOR;
va2_re=(
va_buff[0]va_buff[2]+va_buff[4]va_buff[6])*_2ND_FACTO
R;
va2_im=(va_buff[1]+va_buff[3]va_buff[5]+va_buff[7])*_2N
D_FACTOR;
trig = 1;
f_timer = f_timer f_sample_t;
trigcnt_old = trigcnt;
trigcnt = 0;
sample_new = 1;
// set the values for Inputs
ip1 = IN1;
ip2 = IN2;
ip3 = IN3;
ip4 = IN4;
ip5 = IN5;
ip6 = IN6;
ip7 = IN7;
ip8 = IN8;
}
else
{
trig = 0;
hold1 = meas1;
trigcnt = trigcnt + 1;
if (trigcnt > nThreadInt){
sample_new = 0;
trigcnt = 1; // go to Thread 1
}
///////////////////// THREAD 1 /////////////////////////////
if (trigcnt == 1){
if (sample_new==1){
if (trigcnt_old<trigcnt){
fracdel = (trigcnt + trigcnt_old + 5)*nThreadInv*del;
}
if (trigcnt_old==trigcnt){
fracdel = (trigcnt_old + 1)*nThreadInv*del;
}
if (trigcnt_old>trigcnt){
fracdel = (trigcnt_old + 1)*nThreadInv*del;
}
if (e_timer>0.1&& ip7>0){
w_tan1 = atan2(va_im,va_re);
// figure out the real and imag,then rotate the phasors
a_bre = cos(w_tan1);
a_bim = sin(w_tan1);
start1 = 1;
}
}
else
{
if (start1 > 0){
tddo_ip1 = tddo_ip1 + fracdel;
}
if (tddo_ip1 >= T1DO){
start1 = 0;
tdpu_ip1 = 0.0;
tddo_ip1 = 0.0;
}
} // end of setoutputs IF statement
if (ip8 == 1){
OUT1 = fracdel;
}
else
{
if (ip1 > 0){
OUT1 = tdpu_ip1;
}
else
{
OUT1 = tddo_ip1;
}
}
}
///////////////////// THREAD 3 /////////////////////////////
else if (trigcnt == 3){
if (sample_new==1 && ip7>0){
if (trigcnt_old<trigcnt){
fracdel = (trigcnt + trigcnt_old + 4)*nThreadInv*del;
}
if (trigcnt_old==trigcnt){
fracdel = (trigcnt_old + 1)*nThreadInv*del;
}
if (trigcnt_old>trigcnt){
fracdel = (trigcnt_old + 1)*nThreadInv*del;
}
}
else
{
fracdel = del;
} // CODE AS PER TIMER 1
}
///////////////////// THREAD 4 /////////////////////////////
else if (trigcnt == 4){
if (sample_new==1 && ip7>0){
if (trigcnt_old<trigcnt){
fracdel = (trigcnt + trigcnt_old + 3)*nThreadInv*del;
}
if (trigcnt_old==trigcnt){
fracdel = (trigcnt_old + 1)*nThreadInv*del;
}
if (trigcnt_old>trigcnt){
fracdel = (trigcnt_old + 1)*nThreadInv*del;
}
}
else
{
fracdel = del;
} // CODE AS PER TIMER 1
}
///////////////////// THREAD 5 /////////////////////////////
else if (trigcnt == 5){
if (sample_new==1 && ip7>0){
if (trigcnt_old<trigcnt){
fracdel = (trigcnt + trigcnt_old + 3)*nThreadInv*del;
}
if (trigcnt_old==trigcnt){
fracdel = (trigcnt_old + 1)*nThreadInv*del;
}
if (trigcnt_old>trigcnt){
fracdel = (trigcnt_old + 1)*nThreadInv*del;
}
}
else
{
fracdel = del;
} // CODE AS PER TIMER 1
}
///////////////////// THREAD 6 /////////////////////////////
else if (trigcnt == 6){
if (sample_new==1 && ip7>0){
if (trigcnt_old<trigcnt){
fracdel = (trigcnt + trigcnt_old + 2)*nThreadInv*del;
}
if (trigcnt_old==trigcnt){
fracdel = (trigcnt + 1)*nThreadInv*del;
}
}
else
{
fracdel = del;
} // CODE AS PER TIMER 1
}
///////////////////// THREAD 7 /////////////////////////////
else if (trigcnt == 7){
if (sample_new == 1 && ip7>0){
if (trigcnt_old<trigcnt){
fracdel = (trigcnt + trigcnt_old + 1)*nThreadInv*del;
}
}
else
{
fracdel = del;
} // CODE AS PER TIMER 1
}
cnt_old = trigcnt_old;
OUT8 = trigcnt;
OUT9 = start1+start2+start3+start4+start5+start6;
RTDS
Technologies
using CBuilder with the PMU Shell component
INTRODUCTION
This document outlines how the create the PMU shell from the
source files found in the RSCAD installation directory. Typically
this is C:\RSCAD\TUTORIAL\CBuilder\CH6PMU_SHELL
PMU SHELL
CBuilder is used to create models that are not part of the normal
RSCAD library. The source files are created and stored in the
RSCAD users root folder, typically this folder is
C:\RTDS_USER
The source files for the PMU SHELL component by default are
installed:
C:\RSCAD\TUTORIAL\CBuilder\CH6PMU_SHELL\RTDS_USER
There are 2 sub folders ..\CMODEL_SOURCE and ...\ULIB, the
cmodel_source folder contains the *.c and *.h files while the
ulib folder contains the component definition file.
C Code SECTIONS
The two *.c files have been prepared to use the parameters
specified in the PMU Shell component definition file. There are
some very specific sections that SHOULD NOT BE MODIFIED!
Before the
// !!! DO NOT CHANGE THIS !!!
STATIC:
// GTNET PHASOR ARRAY variables
// INPUT processing variables
// FIR coefficients etc...
The basic
INPUTS:
OUTPUTS:
RAM_PASS1:
RAM_PASS2:
DOWNLOAD_FILE_CODE:
// *******************************
// * CREATE THE DLOAD FILE ENTRIES
// *******************************
CODE_FUNCTIONS:
There are a number of functions called by the main CODE, each
function has some comments about what the function does. the
main function is the pmu_data function and it is used to create the
phasors and prepare the data so it can be sent to the GTNET card.
//////////////////////////////////////////////////////////
// fir_split function
// Calculates the Filtered phasor from the sampled quadrature osc. data
// Inputs:
// input1 ... Quadrature Osc sampled data
// input2 ... Quadrature Osc sampled data
// ntaps ... number of stages
// h ... FIR coefficients for PMU 07
// z ... pointer for Z delay line
// out ... pointer for phasor data
// Output:
//////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////
// calc_angle_diff function
// Returns the correct angle difference between 2 angles
// Inputs:
// Angle1 ...
// Angle2 ...
// Output:
// angle_diff
//////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////
// pmu_data function
// Calculates the V and I phasor from the Input data and fills the phasor array for the PMU
// output
// Implements the P CLASS reference model from Annex C of C37.118.1
// Inputs:
// pmu ... PMU number 07
// IN1 ... Va
// IN2 ... Vb
// IN3 ... Vc
// IN4 ... Ia
// IN5 ... Ib
// IN6 ... Ic
// Output:
//////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////
// pmu_out function
// by Dean Ouellette/Marc Desjardine
// Send the PMU output to the GTNETPMU
// Inputs:
// Output:
// !!! DO NOT CHANGE THIS !!!
//////////////////////////////////////////////////////////
CODE:
There is not much code here in the main section and the C file
contains enough comments to be able to figure out how the
program works.
REFERENCES
M1 W M1 W
PSS = No
PSS = Yes
LDComp = No
LDComp = Yes
RTDS
Technologies
INTRODUCTION
The DC1 type exciter requires real inputs from a generator model.
The two required inputs are the per unit generator terminal voltage
(Vpu) and the generator speed (W). An optional real stabilizer
input and load compensation input is available. The exciter model
produces the field voltage output (Ef) required by the generator.
The component icon for the exciter includes five I/O points. Four
signal inputs and one signal output, all are real.
S Save the component builder icon to a new file name located in the
RTDS_USER|ULIB folder.
Input and Output points (listed under the IO Points tab) and
user defined parameters (listed under the Parameters tab) are
automatically associated with the model and placed in the .h file.
Left clicking the View .h file button opens the .h file in an editor.
The model includes four inputs, one output and a number of
parameters
OUTPUTS:
double OUT;
PARAMETERS:
char Gen[11];
int Mon;
int PSS;
double Vi;
double Tr;
double Ka;
double Ta;
...
S The C code is written for the model by clicking on the edit icon to
open up the text editor window.
S The code for the DC1 type exciter is based on the block diagram
shown below.
SE+KE
w > wpu mon9
wpu
W
*
sKf
0.0026526
mon10 1 + sTf1
DC1
VSIG = VS + VUEL + VOEL Excitation System
7.7
S The data preparation and code for the DC1 type exciter is shown
below.
VERSION:
3.001
#include myEXDC1.h
STATIC:
double dt,washoutG;
double Vmax, Vref, tmp;
double efldi,Verr,v_init;
double mon1,mon2,mon3,mon4,mon5,mon6,mon7,mon8,mon9,mon10;
int mon_array[10] = {1,2,3,4,5,6,7,8,9,10};
#include <builtin_gcc_generatorStructures.h>
RAM_FUNCTIONS:
#include initTransferFunctions.inc
RAM:
dt= getTimeStep();
/* Parameter Validation */
if(Vrmax <= 0.0)
{
if(E2< E1)
{
printf(\nWarning: Vrmax is less than zero.);
printf(\n E2 must be greater than E1);
printf(\n Subsystem %d, Machine %s, exciter type ESDC1A.\n, getSubsystem(),Gen);
reportError(EXDC1,1);
}
/* Compute initial Se + KE */
if (Ke == 0.0)
{
v_init = 0.0;
printf(\nWarning: Ke entered as 0.0. Calculation of Ke such that the);
printf(\n initial condition of Vc is zero is not supported.);
printf(\n Subsystem %d, Machine %s, exciter type EXDC1.\n, getSubsystem(),Gen);
reportError(EXDC1x,1);
}
else
{
v_init = initSatKE(E1,Se1,E2,Se2,efldi,Ke,&satKE1);
}
printf(The value of v_init is %f\n,v_init);
Verr = v_init/Ka;
Vref = Verr + Vi;
Vmax= 1.2;
if (Vref > Vmax) Vmax= 1.2*Vref;
initRealPole(1.0,Tr,Vi,Vi,&realpole1);
initLeadLag(Tb,Tc,Verr,Verr,&leadlag1);
initRealPole(Ka,Ta,Verr,v_init,&realpole2);
initIntegrator(Te,0.0,efldi,&integrator1);
/* Check initial output values are within Vrmax and Vrmin limits */
if (v_init > Vrmax || v_init < Vrmin)
{
printf(\nWarning: Initial value of mon6 is not within the entered limits.);
printf(\n VRmax = %f, VRmin = %f, mon6 initial value = %f.,Vrmax,Vrmin,v_init);
printf(\n Subsystem %d, Machine %s, exciter type EXDC1x.\n, getSubsystem(),Gen);
reportError(EXDC1x,1);
}
/* Initialize all monitoring variables that are going to be referenced in the code section before
they are assigned a value */
mon9 = v_init;
mon10 = 0.0;
CODE:
double puSpeed;
/* realpole #1*/
mon2 = realPole(mon1, 1.0, 0, 0.0, 0.0,0,0,0.0, &realpole1);
/* Summing junction */
mon3 = Vref1 mon2;
/* leadlag */
mon5 = leadLag(mon4,1.0,0,0.0,0.0,0,0,0.0,&leadlag1);
/* realpole #2 */
mon6 = realPole(mon5,Ka,1,Vrmin,Vrmax,0,0,0.0,&realpole2);
/* Summing Junction */
mon7 = mon6 mon9;
/* Integrator */
mon8 = integrator(mon7,0,0.0,0.0,0,0,0.0,&integrator1);
/* Washout */
mon10 = washOut(mon8,washoutG,0,0.0,0.0,0,0,0.0,&washout1);
/* Efd */
OUT = mon8;
if (spdMult == 1)
{
puSpeed = Speed/wBase;
OUT = mon8 * puSpeed;
}
/*check if monitoring is enabled, if so assign the output based on the dial position*/
if (Mon ==1)
{
if (dial1 == 2)
{
internalV = mon2;
}
else if (dial1 == 3)
{
internalV = mon3;
}
else if (dial1 == 4)
{
internalV = mon4;
}
else if (dial1 == 5)
{
internalV = mon5;
}
else if (dial1 == 6)
{
internalV = mon6;
}
else if (dial1 == 7)
{
internalV = mon7;
}
else if (dial1 == 8)
{
internalV = mon8;
}
else if (dial1==9)
{
internalV = mon9;
}
else if (dial1==10)
{
internalV = mon10;
}
else
The get data function requires two arguments. The first argument
is the name of the component, the second argument is the
parameter name.
The name of the generator to which the exciter model is connected
is required as a parameter named Gen.
The generator model precalculates the field voltage required to
provide the desired real and reactive power output. This data is
written to the .map file and given the variable Efldi. To extract
the initial field voltage from the generator model, the parameter
name Efldi must be passed to the get_data function. The parameter
name is case sensitive.
The error is calculated as the initial output of the saturation block
v_init divided by the gain Ka.
Verr= v_init/Ka;
Vmax= 1.2;
if (Vref > Vmax) Vmax= 1.2*(Vref);
The initial value Vref and the maximum value Vmax are used
to initialize the slider in the following section ADD AN
INTERNAL SLIDER.
RAM_FUNCTIONS:
#include initTransferFunctions.inc
initRealPole(1.0,Tr,Vi,Vi,&realpole1);
initLeadLag(Tb,Tc,Verr,Verr,&leadlag1);
initRealPole(Ka,Ta,Verr,v_init,&realpole2);
For example, to initialize the first realpole, the gain, time constant,
initial input, initial output and realpole structure are passed as
parameters. The initial input and output of the realpole are set to
initial p.u voltage of the generator. The leadLag is initialized next,
the precalculated Verr value is passed as the initial input and
output of the leadlag.
Se(E2)
Se(E1)
E1 E2 Ef
The output from the saturation block (mon9) is subtracted from the
output of realpole#2 (mon6).
S Add function call for the integrator function.
mon8 = integrator(mon7,0,0.0,0.0,0,0,0.0,&integrator1);
The first argument in the integrator function call is the input. Input
to the integrator function is the output from the previous summing
junction (mon7).
The second, third and fourth arguments are for limits. Limits are
not included in this block and therefore set to 0.
The fifth, sixth and seven arguments are for reset. Reset is not
included in this block and therefore set to 0.
The eighth argument is the integrator structure. The variables
within the structure were initialized in the RAM section.
The output from the integrator is assigned the variable name
mon8 according to the block diagram.
S Add function call for the saturation function.
mon9 = satKE(mon8,&satKE1);
The first argument in the satKE function call is the input. Input to
the satKE function is the output from the previous integrator
(mon8).
The second argument is the saturation structure. The variables
within the structure were initialized in the RAM section.
S Add function call for the washout function.
mon10 = washOut(mon8,washoutG,0.0,0.0,0,0,0.0,&integrator1);
The first argument in the washOut function call is the input. Input
to the washOut function is the output from the integrator (mon8).