Controller Building Block
InterPSS Controller Modeling Language (CML) is based on some relatively simple controller building blocks, which are described in this document. CML uses Java Annotation to describe these building blocks.
Overview
Annotation definition for the StaticBlock and Dynamic Control Block field block:
public @interface AnControllerField {
// controller field type, syntax CMLFieldType.StaticBlock, CMLFieldType.ControlBlock, or CMLFieldType.Controller
CMLFieldType type();
// controller field object input, example "this.refPoint + pss.vs - mach.vt"
String input() default "";
// controller field object parameters, for example: {"type.Limit", "this.k", "this.t", "this.vmax", "this.vmin"}
String[] parameter() default {};
// define how the field object output init value should be calculated, for example, "mach.efd".
// This field only needs to be defined for all field after the RefPonit and Not a feedback field
String y0() default "0.0";
// define if this controller field is a feedback block
boolean feedback() default false; // optional
// user defined field initialization order sequence number
// There are two scenarios you need to define the seq number
// 1) More than one path to the RefPoint
// 2) There are function block where the system cannot figure out the init seq number
int initOrderNumber() default 0;
// optional
// for grouping feedback blocks with main path block for init purpose
String[] initGroup() default {};
//optional
}
Annotation definition for the Function, FunctionExpression and LookupTable field blocks:
public @interface AnFunctionField {
// controller field type, must be CMLFieldType.Function, CMLFieldType.FunctionExpression or CMLFieldType.LookupTable
CMLFieldType type() default CMLFieldType.Function;
// controller field object parameters, for example: {"this.a", "this.b", "this.c"}
String[] parameter() default {};
// optional. Some functions, such as HVGate, do not need parameter
// controller field object input, example {"this.refPoint", "pss.vs", "mach.vt"}
// in the case of FunctionExpression, expression can be used {"this.refPoint+mach.vt", ...}
String[] input() default {};
// lookup table type, must be LoopupTable.Type.LinearLine
ILookupTable.Type lookupTableType() default ILookupTable.Type.LinearLine;
// optional, only apply to LookupTable
// lookup data points, for example: {"0.0, 5.0", "1.0, 6.0", "2.0, 5.5"}
String[] dataPoints() default {};
// optional, only apply to LookupTable
// define how the field object output init value should be calculated,
// This field only needs to be defined for all fields in the init path and Not a feedback field
String y0() default "0.0";
// optional
}
Function
Exciter Saturation Se(Efd) Function
public double e1 = 3.1, se_e1 = 0.33, e2 = 2.3, se_e2 = 0.1;
@AnFunctionField(
input= { ... },
parameter={"this.e1", "this.se_e1", "this.e2", "this.se_e2"} )
SeFunction seFunc;
Rectifier Regulation Fex(In) Function
@AnFunctionField(
input= { ... }
/* no parameter needed */)
FexFunction fexFunc;
Voltage/Current Compensator Function
public double kp = 5.0, ki = 8.0;
@AnFunctionField(
input= { ... },
parameter={"this.kp", "this.ki"} )
VthevFunction vthevFunc;
High Value Gate Function
@AnFunctionField(
input= { "u1", "u2" },
/* no need for parameter */
y0= ... )
HighValueFunction hvFunc;
Low Value Gate Function
@AnFunctionField(
input= { "u1", "u2" },
/* no need for parameter */
y0= ... )
LowValueFunction lvFunc;
Gain Function
public double k = 1.0;
@AnFunctionField(
input= { "u" },
parameter={"this.k" },
y0= ... )
GainFunction gainFunc;
Power Function
public int n = 2; // n = 0, 1, ...
@AnFunctionField(
input= { "u" },
parameter={"this.n" },
y0= ... )
PowerFunction powerFunc;
Switch Function
For type (a) switch
public double e = 0.01;
@AnFunctionField(
input= { "x", "u1", "u2" },
parameter={"this.e" },
y0= ... )
SwitchFunction switchFunc;
For type (b) switch
public double e = 0.01, bigNumber = 1.0e20;
@AnFunctionField(
input= { "x", "u", "this.bigNumber" },
parameter={"this.e" },
y0= ... )
SwitchFunction switchFunc;
Define Custom Function
If the above listed functions do not meet your requirement, you can define a custom function. The following is a example of defining an absolute function:
@AnFunctionField( input="mach.vt" )
public IFunction absFunc = new FunctionAdapter() {
public double eval(double[] dAry) {
double input = dAry[0]; // dAry contains an array of inputs defined in the input annotation.
return Math.abs(input);
}
};
Function with Expression Input
Gain Expression Function
public double k = 1.0;
@AnFunctionField(
input= { "u1 - u2" },
parameter={"this.k" },
y0= ... )
GainExpFunction gainExpFunc;
High Value Expression Gate Function
@AnFunctionField(
type = CMLFieldType.FunctionExpression,
input= { "u1-u2", "u3*u4" },
/* no need for parameter */
y0= ... )
HighValueExpFunction hvExpFunc;
Low Value Expression Gate Function
@AnFunctionField(
type = CMLFieldType.FunctionExpression,
input= { "u1-u2", "u3*u4" },
/* no need for parameter */
y0= ... )
LowValueExpFunction lvExpFunc;
Lookup Table Function
Lookup Table with Data Points
@AnFunctionField(
type = CMLFieldType.LookupTable,
input= { ... },
lookupTableType = ILookupTable.Type.LinearLine,
dataPoints = { "1.0, 5.0", "2.0, 6.0", "3.0, 5.5"} )
LookupTableFunction lookupTable;
Static Block
GainBlock
public double k = 1.0;
@AnControllerField(
type= CMLFieldType.StaticBlock,
input= ... ,
parameter={"type.NoLimit", "this.k"},
y0= ... )
GainBlock gainBlock;
public double k = 1.0, max = 1.2, min = 0.0;
@AnControllerField(
type= CMLFieldType.StaticBlock,
input= ... ,
parameter={"type.Limit", "this.k", "this.max", "this.min"},
y0= ... )
GainBlock gainBlock;
Dynamic Control Block
Washout Block
public double k = 50.0, t = 0.05;
@AnControllerField(
type= CMLFieldType.ControlBlock,
input= ... ,
parameter={"type.NoLimit", "this.k", "this.t"},
y0= ... )
WashoutControlBlock washoutBlock;
Delay Block
public double k = 50.0, t = 0.05;
@AnControllerField(
type= CMLFieldType.ControlBlock,
input= ... ,
parameter={"type.NoLimit", "this.k", "this.t"},
y0= ... )
DelayControlBlock delayBlock;
public double k = 50.0, t = 0.05, max = 10.0, min = 0.0;
@AnControllerField(
type= CMLFieldType.ControlBlock,
input= ... ,
parameter={"type.Limit", "this.k", "this.t", "this.max", "this.min"},
y0= ... )
DelayControlBlock delayBlock;
public double k = 50.0, t = 0.05, max = 10.0, min = 0.0;
@AnControllerField(
type= CMLFieldType.ControlBlock,
input= ... ,
parameter={"type.NonWindup", "this.k", "this.t", "this.max", "this.min"},
y0= ... )
DelayControlBlock delayBlock;
For delay blocks, you can also use expressions, such as this.kp*mach.vt, to define the limits. For example, in the IEEE 1968 Type-1s excitation system model, "this.kp * mach.vt" is used for defining max limit.
public double ka = 50.0, ta = 0.05, kp = 10.0, vrmin = 0.0;
@AnControllerField(
type= CMLFieldType.ControlBlock,
input="this.refPoint + pss.vs - mach.vt - this.washoutBlock.y",
parameter={"type.Limit", "this.ka", "this.ta", "this.kp * mach.vt", "this.vrmin"},
y0="mach.efd" )
DelayControlBlock delayBlock;
Filter Block
public double k = 1.0, t1 = 0.05, t2 = 0.25;
@AnControllerField(
type= CMLFieldType.ControlBlock,
input= ...
parameter={"type.NoLimit", "this.k", "this.t1", "this.t2"},
y0= ... )
FilterControlBlock filterBlock;
public double k = 1.0, t1 = 0.05, t2 = 0.25, max = 0.2, min = -0.2;
@AnControllerField(
type= CMLFieldType.ControlBlock,
input= ...,
parameter={"type.Limit", "this.k", "this.t1", "this.t2", "this.max", "this.min"},
y0= ... )
FilterControlBlock filterBlock;
public double k = 1.0, t1 = 0.05, t2 = 0.25, max = 0.2, min = -0.2;
@AnControllerField(
type= CMLFieldType.ControlBlock,
input= ... ,
parameter={"type.NonWindup", "this.k", "this.t1", "this.t2", "this.max", "this.min"},
y0= ... )
FilterControlBlock filterBlock;
Integration Block
public double k = 1.0;
@AnControllerField(
type= CMLFieldType.ControlBlock,
input= ... ,
parameter={"type.NoLimit", "this.k"},
y0= ... )
IntegrationControlBlock intBlock;
public double k = 1.0, max = 0.2, min = -0.2;
@AnControllerField(
type= CMLFieldType.ControlBlock,
input= ... ,
parameter={"type.Limit", "this.k", "this.max", "this.min"},
y0= ... )
IntegrationControlBlock intBlock;
public double k = 1.0, max = 0.2, min = -0.2;
@AnControllerField(
type= CMLFieldType.ControlBlock,
input= ... ,
parameter={"type.NonWindup", "this.k", "this.max", "this.min"},
y0= ... )
IntegrationControlBlock intBlock;
PI-Block
public double kp = 1.0, ki = 0.05;
@AnControllerField(
type= CMLFieldType.ControlBlock,
input= ... ,
parameter={"type.NoLimit", "this.kp", "this.ti", "this.max", "this.min"},
y0= ... )
PIControlBlock piBlock;
public double kp = 1.0, ki = 0.05, max = 0.2, min = -0.2;
@AnControllerField(
type= CMLFieldType.ControlBlock,
input= ... ,
parameter={"type.Limit", "this.kp", "this.ti", "this.max", "this.min"},
y0= ... )
PIControlBlock piBlock;
public double kp = 1.0, ki = 0.05, max = 0.2, min = -0.2;
@AnControllerField(
type= CMLFieldType.ControlBlock,
input= ... ,
parameter={"type.NonWindup", "this.kp", "this.ti", "this.max", "this.min"},
y0= ... )
PIControlBlock piBlock;
2nd Order Block
public double k = 1.0, a1 = 0.05, a2 = 0.5;
@AnControllerField(
type= CMLFieldType.ControlBlock,
input="this.washoutBlock.y",
parameter={"type.NoLimit", "this.k", "this.a1", "this.a2"},
y0="this.filterBlock1.u0" )
TFunc2ndOrderBlock order2ndBlock;
public double k = 1.0, a1 = 0.05, a2 = 0.5, max = 10.0, min = -10.0;
@AnControllerField(
type= CMLFieldType.ControlBlock,
input="this.washoutBlock.y",
parameter={"type.Limit", "this.k", "this.a1", "this.a2", "this.max", "this.min"},
y0="this.filterBlock1.u0" )
TFunc2ndOrderBlock order2ndBlock;
nth Filter Block
public double t8 = 0.1, t9 = 0.05, ks3 = 1.0;
public int m = 1, n = 1;
@AnControllerField(
type= CMLFieldType.ControlBlock,
input="this.customBlock1.y + this.ks3*this.customBlock2.y",
parameter={"type.t8", "this.t9", "this.m", "this.n"},
y0="this.filterBlock1.u0 - this.refPoint + this.customBlock2.y" )
FilterNthOrderBlock filterNthBlock;