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.
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
}
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;
@AnFunctionField(
input= { ... }
/* no parameter needed */)
FexFunction fexFunc;
public double kp = 5.0, ki = 8.0;
@AnFunctionField(
input= { ... },
parameter={"this.kp", "this.ki"} )
VthevFunction vthevFunc;
@AnFunctionField(
input= { "u1", "u2" },
/* no need for parameter */
y0= ... )
HighValueFunction hvFunc;
@AnFunctionField(
input= { "u1", "u2" },
/* no need for parameter */
y0= ... )
LowValueFunction lvFunc;
public double k = 1.0;
@AnFunctionField(
input= { "u" },
parameter={"this.k" },
y0= ... )
GainFunction gainFunc;
public int n = 2; // n = 0, 1, ...
@AnFunctionField(
input= { "u" },
parameter={"this.n" },
y0= ... )
PowerFunction powerFunc;
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;
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);
}
};
public double k = 1.0;
@AnFunctionField(
input= { "u1 - u2" },
parameter={"this.k" },
y0= ... )
GainExpFunction gainExpFunc;
@AnFunctionField(
type = CMLFieldType.FunctionExpression,
input= { "u1-u2", "u3*u4" },
/* no need for parameter */
y0= ... )
HighValueExpFunction hvExpFunc;
@AnFunctionField(
type = CMLFieldType.FunctionExpression,
input= { "u1-u2", "u3*u4" },
/* no need for parameter */
y0= ... )
LowValueExpFunction lvExpFunc;
@AnFunctionField(
type = CMLFieldType.LookupTable,
input= { ... },
lookupTableType = ILookupTable.Type.LinearLine,
dataPoints = { "1.0, 5.0", "2.0, 6.0", "3.0, 5.5"} )
LookupTableFunction lookupTable;
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;
public double k = 50.0, t = 0.05;
@AnControllerField(
type= CMLFieldType.ControlBlock,
input= ... ,
parameter={"type.NoLimit", "this.k", "this.t"},
y0= ... )
WashoutControlBlock washoutBlock;
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;
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;
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;
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;
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;
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;