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;