EBSILON®Professional Online Documentation
Getting Started / Getting Started with EbsScript
In This Topic
    Getting Started with EbsScript
    In This Topic

    EbsScript Introduction

    EbsScript is an embedded scripting language within EBSILON professional that gives you access to EBSILON’s input, output and calculation capabilities and to combine these with your own code to:

    There are 6 situations where EbsScript can be used

    This getting started guide is intended to provide a quick reference to EbsScript for those who are familiar with other programming languages and programming in general.  It provides an overview of EbsScript syntax, code snippet examples for common tasks and debugging tips. More details on using EbsScript are available in the EbsScript chapter of the EBSILON help system. The three key parts of the EbsScript Tool, (the Editor, Explorer and Executor) are described in that chapter as well.

    EbsScript Syntax       EbsScript Operators       EbsScript Decision Making Statements       EbsScript Looping Statements       EbsScript Functions      

    EbsScript Variable Scope       EbsScript Arrays       EbsScript Debugging       EbsScript Interface Units       EbsScript Samples        

    EbsScript Syntax

    EbsScript syntax is based on the syntax of the PASCAL programming language plus some extensions.  At a high level this means:

               const PI = 3.14159;

               { This is a single line comment in EbsScript}

               // This is also a single line comment in EbsScript
               Comment text is displayed in gray colour in the EbsScript editor

               var
               val1, val2 :real;

               offset : integer;
               name   : string;

               flag   : boolean;

               pipe      : ebsPipe  ;

               cmp       : ebsComp  ;

    Beyond the above high level rules the following specifics are also useful. 

    Reserved / Keywords / Identifiers used in EbsScript

    The Statements in EbsScript use specific PASCAL words (or properties of "Delphi"), which are called reserved or key words. For example, the words program for, while, do, var, real, begin and end are all reserved words. You cannot use reserved words as names for your variables and functions / procedures. The following table shows the reserved / key words in EbsScript:

    A

    abstract

    add

    addr

    and

    append

    array

    autodispatch

    autosafearray

    autounknown

    B

    begin  

    bitand

    bitnot

    bitor

    bitwiseand

    bitwiseor

    bitwisexor

    bitxor

    boolean

    break

    C

    callback

    capacity

    case

    char

    class

    comnullptr

    const

    constructor

    continue

    copy

    copymem

    D

    dec

    default

    destructor

    dispatchcall

    dispose

    div

    divide

    do

    downto

    E

    else

    end

    enumstrings

    enumtostring

    equal

    except

    explicit

    F

    false

    finalization

    finally

    for

    forward

    freemem

    function

    G

    getmem

    greaterthan

    greaterthan

    H

    high

    I

    if

    implementation

    implicit

    in

    inc

    index

    inherited

    initialization

    insert

    internal

    intdivide

    integer

    interface

    L

    leftshift

    length

    lessthan

    lessthanorequal

    logicaland

    logicalnot

    logicalor

    logicalxor

    low

    M

    mod

    modulus

    multiply

    N

    negative

    new

    nil

    not

    notequal

    O

    of

    on

    operator

    or

    otherwise

    overload

    override

    P

    pointer

    positive

    print

    println

    private

    procedure

    program

    property

    protected

    public

    R

    raise

    read

    real

    record

    reintroduce

    remove

    repeat

    reserve

    return

    rightshift

    round

    S

    self     

    setlength

    setlow

    shl

    shr

    sizeof

    sliceleft

    slicemid

    sliceright

    smartptr

    static

    step

    string

    subtract

    T

    then

    to

    true

    trunc

    try

    type

    typeof

    U

    unit

    unittest

    until

    uses

    V

    var

    virtual

    W

    while

    write

     

    EbsScript reserved words will be shown in blue text in the EbsScript editor.

    An "identifier" in a program refers to an object (such as a data type, variable, or function) with which it is uniquely named. Therefore, the identifier must be unique within a namespace.
    Typically, identifiers use the combination of a string of letters and numbers.

     

     

    EbsScript Operators

    Arithmetic Operators

    Operator

    Description

    +

    Adds two operands

    -

    Subtracts second operand from the first

    *

    Multiplies both operands

    div

    Integer Division

    mod

    Modulus Operator AND remainder of after an integer division

    /

    Floating Point (Real) Division

    Exponentiation

    Use the pow function  pow(base, exponent)

    Relational Operators 

    Operator

    Description

    =

    Checks if the values of two operands are equal or not, if yes, then condition becomes true.

    <>

    Checks if the values of two operands are equal or not, if values are not equal, then condition becomes true.

    >

    Checks if the value of left operand is greater than the value of right operand, if yes then condition becomes true.

    <

    Checks if the value of left operand is less than the value of right operand, if yes then condition becomes true.

    >=

    Checks if the value of left operand is greater than or equal to the value of right operand, if yes then condition becomes true.

    <=

    Checks if the value of left operand is less than or equal to the value of right operand, if yes then condition becomes true.

     

    Boolean Operators

    Operator

    Description

    and

    Boolean AND operator. If both the operands are true, then condition becomes true.

    and then

    Similar to the AND operator, however, it guarantees the order in which the compiler evaluates the logical expression. Left to right and the right operands are evaluated only when necessary.

    or

    Boolean OR Operator. If any of the two operands is true, then condition becomes true.

    or else

    Similar to Boolean OR, however, it guarantees the order in which the compiler evaluates the logical expression. Left to right and the right operands are evaluated only when necessary.

    not

    Boolean NOT Operator. Used to reverse the logical state of its operand. If a condition is true, then the NOT operator will make it false.

     

    EbsScript Decision Making Statements


    EbsScript supports the following decision making statements:

     

    if ... then - Statement

    If the boolean expression condition evaluates to true, then the block of code inside the if statement will be executed. If the boolean expression evaluates to false, then the first set of code after the end of the if statement (after the closing end;) will be executed.
        if str <> "" then begin
                    str := StringTrimLeft(str);
                    str := stringLower(str) ;
        end
    ;

    EbsScript considers any non-zero or non-nil values to be true. Values of zero or nil are treated as false.

    if ... then ... else - Statement

    If the boolean expression condition evaluates to true then the if-then block of code will be executed otherwise the else block of code will be executed. For example:

      if str <> "" then begin

                    str := StringTrimLeft(str);
                    str := stringLower(str) ;
     end
     else begin
                    UserInput := "" ;
     end;

    Case Statement

    The syntax of the case statement is:
    case (expression) of
        L1 : S1;
        L2: S2;
        ...

        Ln: Sn;
        otherwise: Sotherwise; or else: Selse
    end;

    Where, L1, L2... Ln are case labels or input values, which can be integers, characters, boolean or enumerated data items. S1, S2, ... Sn are EbsScript statements and each of these statements may have one or more than one case label associated with it. The expression is called the case selector or the case index. The case index may assume values that correspond to the case labels. The case statement must always have an end statement associated with it. The following rules apply to a case statement:

    For example:
    case MacroInterface.LoadMethod of
                    0  :  Programmable.SPEC3 := 0 ;
                    1  :  Programmable.SPEC3 := 2 ; 

                    2  :  Programmable.SPEC3 := 1 ;
                    otherwise Programmable.SPEC3 :=  MacroInterface.LoadMethod ;
    end;

     

     

    The type for case of can be string too. Here the individual anchor points must be string constants:

    procedure foo(s:string);
    begin
    case s of "Hallo" : begin
    // ...
    end;
    "Welt" : begin
    // ...
    end
    otherwise begin
    // ...
    end
    end;

    end;

    The comparison is ALWAYS executed in a case-sensitive way.
    Furthermore, entire ranges can now be specified as anchor points:

    5 .. 10 : // all values greater or equal 5 and less or equal 10
    .. 2    : // all values less or equal 2
    15 ..   : // all values greater or equal 15

    procedure bar(value:integer); begin
    case value of ..-10 : begin
      println("<= -10");
    end;
    20.. : begin
      println("=> 20");
    end;
    5..8 : begin
      println("5 <= .. <= 8");
    end;
    4 : begin
       println("== 4");
    end;
    0 : begin
      println("== 0");
    end
    otherwise begin
      println("something else");
    end
    end;

    end;

    For strings, the lexicographic order is used here.

     

     

    EbsScript Looping Statements

    A loop statement allows a script to execute a statement or group of statements multiple times. EbsScript supports the following looping statements:

     

    While .. do - loop Statement

    A while-do loop statement in EbsScript allows repetitive computations until some test condition is satisfied. In other words, it repeatedly executes a target statement or group of statements as long as a given condition is true. The syntax of a while-do loop is:

    while (condition) do S;

    Where condition is a Boolean or relational expression, whose value would be true or false and S is a statement or group of statements within a "begin ... end;" block. For example:
    while number > 0 do
    begin
       sum := sum + number;
       number := number - 1;
    end;

    When the condition becomes false, program control passes to the line immediately following the loop’s end; statement.

    For ... do - loop Statement

    A "for ... do" loop is a repetition control structure that allows you to efficiently write a loop that needs to execute a specific number of times.  The syntax for the for-do loop in EbsScript is as follows:

    for < loop-variable-name > := < initial_value > to [downto] < final_value > do  S;

    Where loop-variable-name specifies a variable of ordinal type, called the control variable or index variable; initial_value and final_value values are values that the control variable can take; and S is the body of the for-do loop that can be a statement or a group of statements. For example:

    for i:=1 to n do
     begin
         MacroInterface.ERRARRAY.x[i] := Programmable.RA_2.x[i];
         MacroInterface.ERRARRAY.y[i] := Programmable.RA_2.y[i];
    end;

    This is how control flows in a for-do loop in EbsScript:

    Repeat ... Until - loop Statement

    A "repeat ... until" loop is similar to a while loop, except that a "repeat ... until" loop is guaranteed to execute at least one time.  The syntax for the "repeat ... until" loop in EbsScript is as follows:

    Repeat
       S1;
       S2;
       ...
       Sn;
       until condition;

    For example:
    repeat
       sum := sum + number;
       number := number - 1;
     until number = 0;

    Notice that the conditional expression appears at the end of the loop, so the statement(s) in the loop will execute once before the loop condition is tested. If the condition is true, the flow of control jumps back up to repeat and the statement(s) in the loop execute again. This process repeats until the given condition becomes false.

    Break and Continue Statement

    The break statement in EbsScript has the following uses:

    The continue statement in EbsScript works  like the break statement. Instead of forcing termination, however, continue forces the next iteration of the loop to take place, skipping any code in between.  When used in a "for ... do" loop, the continue statement causes the conditional test and increment portions of the loop to execute.  When used in "while ... do" and "repeat...until" loops,  the continue statement causes the program control pass to the loop’s conditional tests.

    EbsScript Functions

    A function definition in EbsScript consists of a function header, local declarations and a function body. The function header consists of the keyword function and a name given to the function. These are the parts of a function declaration:

    Arguments: The argument(s) establish the linkage between the calling program and the function identifiers and are also called the formal parameters.  

    Return Type: All functions must return a value, so all functions must be assigned a type. The function-type is the data type of the value the function returns. It may be standard, user-defined scalar or sub range type but it cannot be structured type.

    Local declarations: Local declarations refer to the declarations for labels, constants, variables, functions and procedures, which are applicable to the body of function only.

    Function Body: The function body contains a collection of statements that define what the function does. It should always be enclosed between the reserved words begin and end. The function body is the part of a function where all computations are done. There must be an assignment statement of the type function_name := expression;  in the function body that assigns a value to the function name. This value is returned when the function is executed. The last statement in the body must be an end statement. To call a function, you simply need to pass the required parameters along with function name, and if the function returns a value, then you can store the returned value by assigning it to a variable.  For example:


    function test (a, b: Integer ; c: real) : real;
    begin   
                test:= (a+b)*c;
    end;

    begin
                println ( test(2, 5, 7.1));
    end.


    Note the semicolon after the final function end statement as well.

    Variable Scope in EbsScript

    Scope in any programming is that region or portion of the program where a defined variable exists. Beyond that or outside of its scope, the variable cannot be accessed. There are three places, where variables can be declared in EbsScript:

    Local Variables
    Variables that are declared inside a function / procedure or code block are called local variables. They can be used only by statements that are inside that function / procedure or block of code. Local variables are not known to functions / procedures or code blocks outside their own.

    Global Variables
    Global variables are defined outside of a function, usually at the top of the script. The global variables will hold their value throughout the lifetime of your script and they can be accessed inside any of the functions defined in the script. A global variable can be accessed by any function. That is, a global variable is available for use throughout your entire script after its declaration.


    See the Free Pascal language reference  more general information on scope of variables.

    Arrays in EbsScript

    EbsScript provides a data structure called the array, which can store a fixed-size sequential collection of elements of the same type. An array is used to store a collection of variables of the same type. Instead of declaring individual variables, such as number1, number2, ... and number100, you declare one array variable called numbers and use numbers[1], numbers[2], and ..., numbers[100] to represent individual variables. A specific element in an array is accessed by an index. All arrays consist of contiguous memory locations. The lowest address corresponds to the first element and the highest address to the last element.  Note that if you want a C style array starting from index 0, you just need to start the index from 0, instead of 1.

    The general form of type declaration of one-dimensional array is:

    type  array-identifier = array[index-type] of element-type;

    Where:
    array-identifier indicates the name of the array type.
    index-type specifies the subscript of the array; it can be any scalar data type except real
    element-type specifies the types of values that are going to be stored

    For example:

    type
       vector = array [ 1..25] of real;
    var
       velocity: vector;

    Velocity is a variable array of vector type, which is sufficient to hold up to 25 real numbers. To start the array from 0 index, the declaration would be:

    type

        vector = array [ 0..24] of real;
    var
       velocity: vector;

     

    Types of Array Subscript

    In EbsScript, an array subscript can be of any scalar type like, integer, boolean, enumerated or sub range, except real. Array subscripts can have negative values too. For example:

    type
       temperature = array [-10 .. 50] of real;
    var
       day_temp, night_temp: temperature;

    Finally, an example where the subscript is of character type:

    type
       ch_array = array[char] of 1..26;
    var
       alphabet: ch_array;
       c: char;

    begin

       ...

       for c:= 'A' to 'Z' do

       alphabet[c] :=

    An element is accessed by indexing the array name. This is done by placing the index of the element within square brackets after the name of the array. For example:

    a: integer;
    a: = alphabet['A'];
    a:= numbers[10];

    Debugging in EbsScript

    The means of debugging EbsScript code depend on whether or not your code uses Kernel Scripting.   If your script contains the following line of code, it uses Kernel Scripting:

    uses @KernelScripting

    Since the Kernel Scripting is embedded in the solver for the overall equation system, you cannot debug it in the editor.   All debugging functions in the EbsScript editor will be disabled, if you edit a kernel script.  To work around this limitation one can print intermediate results with println() commands like:

    println("FCTRLMODE =", ::Control.FCTRLMODE);

    and review them AFTER calculation in the EbsKern-Output tool bar. To display the EbsKern-Output too bar, follow these steps:

    1.       Choose Toolbars >  from the View pull down menu.

    2.       Choose EbsKern-Output from the sub menu to display the EbsKern-Output window shown below:



    In the EbsKernel output bar, a sheet (tab) is created for each component 93 contained in the model being run along with a complete sheet (tab) for all outputs.

    If your script code does not use Kernel Scripting, then you can debug your code  while an EbsScript is running. Debugging makes it possible to interrupt the execution of the script and to view and also change the values of variables. The EbsScript debugger can be found under the Debug menu item.

    In order to debug, breakpoints must be set in the script by moving the cursor to the desired line in the EbsScript editor window and clicking F9 (“Switch breakpoint”).  Clicking on F9 one more time will remove the breakpoint.

    The script can then be started with F5 (Start/continue) and will run up to the first breakpoint you set. It is possible to see the values of variables displayed in the monitoring bar (in the EbsScript editor under View > Toolbars > Console) and to change them.

    You can then continue the execution of the script step-by-step with F10 (across procedure activations) and F11 (into procedures), respectively, or run up to the next breakpoint with F5. The Debugger window is shown below:

     

    Note, you may also run the debugger on some kernel scripts by copying the content of your kernel script to an external script provided it does not access stream or component data by using functions such as "ksGetPipeValue".  In order to correctly interpret the variable names of the model, the external script has to run in the same context (i.e. on the model level which by default is called  (Global), or inside the respective macro object which contains the kernel script, in the example above called ‘Control’).  You can select the appropriate context from a drop-down in the EbsScript menu that is shown circled in red in the screen shot above.

    If your kernel script does access stream or component data then using "println" statements and the EbsKern-Output window is the only means of debugging currently available.

     

    Interface Units in EbsScript

    Interface Units are libraries of functions that do not have their own implementations within EbsScript. The functions in an interface unit are implemented directly in EBSILON®Professional.  An interface unit must be linked to the script calling its functions with the uses keyword at the start / top of the script. For Example:

    uses @KernelScripting;

     The "@" before the unit name acts as an identification for an Interface-Unit.   EBSILON Professional provides the following interface units:

    KernalScripting
    Fluid
    Variant
    Units
    Covariance
    System
    Epos
    KernelExpression
    MacroHelpers
    TimeSeries
    NNTool
    Standard
    Debug

    You can see what functions these interface units provide by opening the EbsScript Editor (select the EbsScript Editor… item on the Calculation pull down menu or press F8) and then selecting the Open Interface Unit >  item on the EbsScript Editor’s EbsScript  pull down menu.  Note some of the interface units like NNTool may require additional licensing.



     

    Custom units

    It is also possible to define custom units in Pascal, which can be used by any script.

    Below is an example of such a custom unit:
    unit EngineCalcs;
     
    interface
     
    procedure EnginePreProcessing;
    procedure EnginePostProcessing;
    procedure DoMyCalculations( par1:real; var retval1:real, var retval2:real);
     
    implementation
    uses @kernelscripting,@fluid;
     
     
    procedure AddMessage( MessageNumber:integer; MessageMessage: string);
    var len:integer;
    begin
         //::StatusText.text:=printToString( ::StatusText.text, "\n",MessageMessage );
         len:=MacroInterface.Messages.getSize+1;
         MacroInterface.Messages.size:=len;
         MacroInterface.Messages.x[ len ]:= MessageNumber;
    end;

     
    procedure EnginePreProcessing;
    var i,j:integer;
        x,y:real;
    begin
         …
         …
         …
    end;
    procedure EnginePostProcessing;
    var i,j:integer;
        x,y:real;
    begin
         …
         …
         …
    end;
    procedure DoMyCalculations( par1:real; var retval1:real, var retval2:real);
    var i,j:integer;
        x,y:real;
    begin
         …
         …
         …
         retval1 := …;
         retval2 := …;
    end;

     
     
    end.

     
     
    Example usages:
    from a macro in the “script before calculation”:
     
    uses EngineCalcs;
     
    begin
         EnginePreProcessing;
    end;

     
    from any Component 93 or “Kernel Expression” (=special input fields in components):
    uses EngineCalcs;
     
    var p1, r1,r2;
    begin
         p1:= sqrt(23);
         DoMyCalculations(p1,t1,r2);
         …
         …
    end;

    EbsScript Samples

    The following examples demonstrate some common tasks that can be accomplished with EbsScript.

    Running simulations on different profiles in a model:

    var
          i: integer;
    begin
         for i:=1 to 10 do
        begin
              setCalcProfileByName(“first_profile_name”);
              simulate ;

              setCalcProfileByName(“second_profile_name”);
              simulate ;
        end;
    end;

    Unit of Measure Conversion – pressure to psia

    You may directly access the quantities in the model from within the EbsScript. Note that model quantities are internally stored using the SI unit system. This means the Units of Measure (UOM) for model quantities that have units are as follows:

    Therefore, a direct assignment like

    Turbine.M1N := 100;

    always means 100 kg/s.  EbsScript provides the Units interface unit to allow you to perform UOM conversions in your script code.  The following example converts a pressure from bar to psia:

    uses @Units
    unitsConvert(comp122.P1, “BAR”, myPinPsia, “PSIA”) ;


    Below is a link to the list of all available units of measure in Ebsilon:

    Ebsilon Units Of Measure


     

    Setting Specification Values with EbsScript
    To set a specification value with EbsScript paste EbsScript code for a function that calculates the desired specification value into the specification input field.  For example:

    function evalexpr:REAL;
    var
    begin

                    // TODO: calculate specification value
                    evalexpr:= calc_result
    end;

    Perform a property calculation
    You can call any EBSILON property calculations for within EbsScript.  For Example calculate Enthalpy from P & T:

    uses @fluid;
    var    
        Pres,Temp,rResult:real;
     iphase:PhaseEnum;
    begin
        Pres:=1.013;
        Temp:=20.0;
     fluidTableWST( rResult, iPhase, Pres, Temp, FuncH_OF_PT);   
     println (rResult);
    end;

    The following section of the code can be more convenient in case the user has a stream type to relate to:

    begin
                    fluidTableObject( {var rResult:Real}, {var phase:PhaseEnum}, {arg1:Real}, {arg2:Real}, {func:FuncEnum}, {obj:ebsData} );
     
    end;

     
    The last parameter (obj:ebsData) represents a stream, either by name from the flow sheet, or by reference to a port (For example: ‘componentname._2’ for the stream connected to port 2).

    Below is a screen shot of the available functions of the Interface Unit – Fluids from the EbsScript key words window:



     

    Available thermal property calls in EbsScript

    Under the following link is the list of available property function calls which can be accessed from the EbsScript: Calculation Functions

    Get P, H and M from a port on a component

    uses @kernelscripting;
    var
                    m14,h14,p14:real;

    begin

    m14:=ksGetPipeValue(14,PhysValueM);
    h14:=ksGetPipeValue(14,PhysValueH);
    p14:=ksGetPipeValue(14,PhysValueP);

    end;

    Check if a particular port (Port 7) on a macro object is connected and get the upstream component:

    uses @MacroHelpers
    var
                    txt    : string;
                    ThisMacro : ebsMacro ;
                    pipe      : ebsPipe  ;
                    cmp       : ebsComp  ;

        ThisMacro := getContainerMacro(MacroInterface);  // Check if logic line is connected

        if  isNull(getPipeAtLink(ThisMacro,7)) then
        begin
                       txt := ThisMacro.name + " fuel logic line at Pin 7 not connected." ;
                     MessageBox(txt) 
                     exit(-1, txt);   // terminate the run and set error message to txt
        end;

        // There's a logic line at Pin 7.  Get it.  
       pipe := getPipeAtLink(ThisMacro,7) ; // Check if it's connected to a pipe              
       if isNull(GetPipeAtLogpipe(pipe, 1)) then
       begin
                       txt := ThisMacro.name + " logic line at Pin 7 not connected to a pipe." ;
                       MessageBox(txt);
                     exit(-1, txt);   // terminate the run
        end;
       // It's connected to a pipe.  Get it.
        pipe := GetPipeAtLogpipe(pipe, 1) ;
      // Get component at upstream end of that pipe
        cmp := GetCompAtPipe(pipe, 1) ;

    Call code in a COM Object
    callEbsScriptServer( {class:string}, {var var1:(array of) primitive type}, {var var2:(array of) primitive type}{, callBackProc:callback procedure = nil} );

    See Block 750.ebs example