EBSILON®Professional Online Documentation
EbsScript / Using EbsScript
In This Topic
    Using EbsScript
    In This Topic

    Using EbsScript

    Creation and Execution

    The module EbsScript enables an automated execution of assignments and calculations. In the first step, you must create a program (the "EbsScript") by using the EbsScript Editor. The programming language is PASCAL, with language extensions customized for EBSILON®Professional. After creating the script, you can check the correctness of the syntax with the help of the EbsScript Compiler and execute the EbsScript. Already created EbsScripts can be compiled and executed directly with the EbsScript Executor without using the Editor.

    While you are working with the EbsScript Editor, it is possible to switch to the EBSILON model and back to the editor. This is useful if you have to lookup certain names or values. You can even modify your EBSILON model while the EbsScript Editor is open. But if you insert, delete or rename objects in your model, you should use the "ExtrasàRebuild Object-Tree" menu command to update the object tree within the editor.

    If you have opened several models, you may open an EbsScript Editor for each of them. On the screen, you see only one EbsScript Editor, the one that is assigned to the model that is currently active. Other EbsScript Editors are invisible. If you switch from one model to another, the editor corresponding to the other model will become visible.

    It is possible to develop several EbsScripts for one model. These scripts are stored within the ".ebs" file. There are import/export functions that allow the transfer of EbsScripts from one model to another.

     

    Access to Model Data

    EbsScript is specially designed to process model data. The names available in the model can thus be used directly in EbsScript. For instance, to assign a value for the isentropic efficiency to a turbine disc having the name NDT_2B, you can use the syntax

    NDT_2B.ETAIN:=0.89;

    Exactly as in the input fields themselves, expressions can also be assigned to a specifications value. For realizing these access possibilities, EbsScript uses its own primitive data type "ebsvar".

     

    Input and Output

    There are several sources of input for executing the EbsScripts:

    To get the EbsScript results, you can

    Since some EbsScript functions are a part of the EBSILON®Professional Performance Optimization Systems, EPOS, they can be used only with additional licenses. Details are given in the Functions list.

    Notes

    1. In EbsScripts that are always assigned to a component (e.g. component 93 kernel script, macro scripts, kernel expressions), the placeholder "$" can now be used for the current component (as in text field expressions). Attention: "$" is not an EbsScript function, but is replaced by the current component during compilation. It is not possible to use "$" in units.
    2. Partial initialization of constants is now possible: When initializing an array, only one initial piece may be initialized (the rest is initialized by default, i.e. set to 0 or empty string). When initializing a record, elements may be omitted (omitted elements are initialized by default).

       Example:

       const ROWS = 5;
       const COLS = 6;
       const a:array [1..ROWS,1..COLS] of integer = ((1,2),(4,5,6),(),(1));
       const b:array [1..ROWS,1..COLS] of integer = ((1,2,3),(),(4,5,6),(7,8,9),(-8));  
       
       type rectype = record
           i,j:integer;
           s:string;
           b:boolean;
       end;
       
       const reca:rectype =     (i: 42; s:"hallo");
       const recb:rectype =     (j:-41; b:true   );
       
       var c,r:integer; 
       begin
          println ("Array a");
          for r := 1 to ROWS do begin
             for c := 1 to COLS do begin
                 print (a[r,c]:2, " ");
             end;
             println (" ");
          end;
          println ("\nArray b:");
          for r := 1 to ROWS do begin
             for c := 1 to COLS do begin
                print (b[r,c]:2, " ");
             end;
             println (" ");
          end; 
          println (" ");
          println ("reca: ", reca.i:4, " ", reca.j:4, " ", reca.b:6, " ", reca.s);
          println ("recb: ", recb.i:4, " ", recb.j:4, " ", recb.b:6, " ", recb.s);
      end.


      Output:

      Array a

       1  2  0  0  0  0 
       4  5  6  0  0  0 
       0  0  0  0  0  0 
       1  0  0  0  0  0 
       0  0  0  0  0  0 

      Array b:
       1  2  3  0  0  0 
       0  0  0  0  0  0 
       4  5  6  0  0  0 
       7  8  9  0  0  0 
      -8  0  0  0  0  0

      reca:   42    0 false hallo
      recb:    0  -41 true

       

    3. Instances of Record-Types can now be defined as constants inline in the code. The syntax for this is:

    Type name( field1:value1; field2:value2; … )

    e.g.

    type person_type=record
    last_name:string;
    middle_name:string;
    first_name:string;
    end;

    var person:person_type;
    begin
    //...
    person:=person_type(last_name:"Miller"; first_name:"Arthur");
    //...
    end;

    Like with the definition of record constants, in the initialization the fields must occur in the same sequence as in the definition of the record; however, fields may be omitted (these are default-initialized).
    PLEASE NOTE: This expansion only applies to record types and NOT to class. 

    Unit Systems

    You may directly access the quantities in the model from within the EbsScript. However, the units displayed in the interface are not used for this, but instead the internally stored SI unit system is used, which is also used in the calculation kernel of EBSILON®Professional:

    Therefore, a direct assignment like

    Turbine.M1N := 100;
    

    always means 100 kg/s.

    Profiles

    One of the main advantages of EbsScript is the feature to perform calculation for different profiles. Within EbsScript, it is possible to create new profiles and switch from one profile to another. All operations are based on two profile settings:

    The current calculation profile is used when a calculation is performed. It is also used when you read values from your model or write values to your model. Additionally, a lot of profile operation apply to this profile (see the "Profiles" in the functions overview of EbsScript).

    The current parent profile is used when a new sub-profile is created, i.e. the new sub-profile is a child profile of the current parent profile. It is not necessary that the current parent profile is the parent of the current calculation profile (though this will be the case if you work in a sub-profile that you have just created within EbsScript).

    When you start EbsScript, both, the current calculation and the current parent profile are set to the profile that was active when EbsScript is called.

    Example: If you start EbsScript while you are in Profile A and execute the commands

    newSubProfile;
    newSubProfile;

    you will get two new profiles that are children of Profile A.

    If the second new profile is to be a child of the first, you must write

         i:=newSubProfile;
    setParentProfile( i );
    newSubProfile;

    COM-Interface

    It is possible to access COM libraries. The corresponding data types and functions are defined in the interface “@ComObj´“.

    Under “EbsScript -> Add Unit from Typelib“, a type library importing dialog can now be opened in the EbsScript editor. The EbsScript units created with it serve to instantiate and use COM objects. This enables an easy communication between EbsScript and COM-capable programs.

     

    Python-Interface

    The interface unit “@Python” allows executing Python code directly from the EbsScript. Both code directly and Python files (*.py) can be executed. For using the interface

    1. Python must be installed (Version 2.7 or 3.0 or newer). Python for Windows can be downloaded from https://www.python.org/downloads/windows/.
    2. the Python extension "Python for Windows Extensions" must be installed (see e.g. http://sourceforge.net/projects/pywin32/ ).
    3. the COM class "EbsScriptPython.Interpreter” must be registered: to do so please execute the Python script “<Ebsilon-Install-Path>/Data/Python/ebsscript_python_interpreter.py” with Python.

    During the execution of an EbsScript, the global dictionary of Python is retained, i.e. several calls to Python executed in a row can e.g. create Python variables and subsequently
    read them out.

    CAUTION: After terminating an EbsScript, the global Python dictionary is deleted. Accessing variables from a previous EbsScript run is thus no longer possible via the
    dictionary (this can e.g. be achieved by means of “Python pickling”) The following functions/procedures are contained in “@Python”: These function/procedures are included in „@Python“:

    function pyEvaluate(expression:string):variant; internal;
    evaluates “expression” and returns the result.

    procedure pyExecute(expression:string); internal;
    executes the code in “expression”.

    procedure pyExecuteFile(file:string); internal;
    executes the code contained in “file”.

    function pyGetVariable(name:String):variant; internal;
    returns the value of the global variable “name” (i.e. element of the global dictionary).

    procedure pySetVariable(name:String; const value:variant); internal;
    sets the values of the global variable “name”.

     

    Anonymous Functions

    Anonymous functions are functions or procedures without a name. Two simple examples

    var p:procedure();
    begin
         p:=procedure ()
         begin
           println(445);
        end;
        p();
    end;

     

    var f:function():string;
    begin
        f:=function ():string
        begin
            println(445);
            result := "Hi";
        end;
        println (f());
    end;

     

    Especially useful are anonymous functions in text boxes or expressions.
    They allow the use of variables and function calls - all EbsScript functions are accessible.
    Example for the text of a textbox using an anonymous function:

     

    Power of a wind turbine as function of wind speed
    { function (v : real):string
         var s:string; P:real;
         begin 
             s := "Aktuelle Windgeschwindigkeit: " + printtostring (v:5:2);
             s := s + "  m/s \nLeistung ";
             P := Windturb.CLPower.interpolate(v);
             s := s + printtostring (P:5:2) + "  MW\n";
            result := s;
      end (Sun.VWIND)   }

    Find more examples within the examples provided (File names starting with anonymous_functions.....).

     

    Multiple Implementation of Interfaces

    An EbsScript class (ONLY “class“, NOT “record“!) can implement several interfaces at the same time.
    Here, for instance, is the definition of an amphibious vehicle that can swim and roll:

    type ICanSwim = interface
    procedure swim;
    end;
    type IHasWheels = interface
    procedure roll;
    end;
     
    
    type AmphibiousVehicle = class(ICanSwim, IHasWheels)
    procedure swim;override;
    procedure roll;override;
    end;

    If name conflicts occur during the multiple implementation of interfaces, the standard allocation can be overridden by means of the method allocation clause:

    type ICanSwim = interface
    procedure swim;
    procedure honk;
    end;
    type IHasWheels = interface
    procedure roll;
    procedure honk;
    end;
     
    
    type AmphibiousVehicle = class(ICanSwim, IHasWheels)
    procedure swim;override;
    procedure roll;override;

    procedure blow_foghorn; virtual; // honking when swimming
    procedure trot; virtual; // honking on wheels

    procedure ICanSwim.honk = blow_foghorn;
    procedure IHasWheels.honk = trot;
    end;

     

    Key Words "is" and "as"

    The key words „is" and „as" are used in the context of EbsScript classes (ONLY “class“, NO “record“!) and interfaces..

    The key word „is" allows to test whether the runtime type of a class or interface instance is of the type of a certain class or implements a certain interface (All combinations of classes and interfaces are admissible here.).
    The following program shows possible uses of is" und „as":

    type IAnimal = interface
    
    
       function make_noise : string;
    
    end;
    
     
    
    type Dog = Class (IAnimal)
    
       function make_noise : string; override;
    
       procedure tell(command:string);
    
    end;
    
     
    
    function Dog.make_noise : string;
    
    begin
    
       result:="woof";
    
    end;
    
     
    
    procedure Dog.tell(command:string);
    
    begin
    
       println("Executing command: ", command);
    
    end;
    
     
    
    type Cat = Class (IAnimal)
    
       function make_noise : string; override;
    
       procedure relax();
    
    end;
    
     
    
    function Cat.make_noise : string;
    
    begin
    
       result:="purr";
    
    end;
    
     
    
    procedure Cat.relax;
    
    begin
    
       println("relaxing...");
    
    end;
    
     
    
     
    
    procedure interact(animal:IAnimal);
    
    begin
    
       println(animal.make_noise());
    
     
    
       if animal is Dog then begin
    
    
          (animal as Dog).tell("Sit!");
    
       end;
    
     
    
       if animal is Cat then begin
    
    
          (animal as Cat).relax();
    
       end;
    
     
    
    end;
    
     
    
    var
    
       a_cat:Cat;
    
       a_dog:Dog;
    
    begin
    
       a_cat:= Cat.Create();
    
       interact(a_cat);
    
       a_dog:= Dog.Create();
    
       interact(a_dog);
    
    end;
    

     

    Output of the program:

    purr
    relaxing...
    woof
    Executing command: Sit!

    Overloading of Class Operators

    The overloading of implicit and explicit operators has been completely revised with Release 16 and previously missing operators have been added. Now the following operators for classes can be overloaded:

    Operator Category Declaration signature Operator symbol

    Implicit

    Conversion

    Implicit(a : Typ): Ergebnistyp;

    Implicit type conversion

    Explicit

    Conversion

    Explicit(a: Typ): Ergebnistyp;

    Explicit type conversion

    Negative

    Unary

    Negative(a: Typ): Ergebnistyp;

    -

    Positive

    Unary

    Positive(a: Typ): Ergebnistyp;

    +

    Inc

    Unary

    Inc(a: Typ): Ergebnistyp;

    Inc

    Dec

    Unary

    Dec(a: Typ): Ergebnistyp

    Dec

    LogicalNot

    Unary

    LogicalNot(a: Typ): Ergebnistyp;

    not

    Trunc

    Unary

    Trunc(a: Typ): Ergebnistyp;

    Trunc

    Round

    Unary

    Round(a: Typ): Ergebnistyp;

    Round

    Equal

    Comparison

    Equal(a: Typ; b: Typ): Boolean;

    =

    NotEqual

    Comparison

    NotEqual(a: Typ; b: Typ): Boolean;

    <>

    GreaterThan

    Comparison

    GreaterThan(a: Typ; b: type) Boolean;

    >

    GreaterThanOrEqual

    Comparison

    GreaterThanOrEqual(a: Typ; b: Typ): Boolean;

    >=

    LessThan

    Comparison

    LessThan(a: Typ; b: Typ): Boolean;

    <

    LessThanOrEqual

    Comparison

    LessThanOrEqual(a: Typ; b: Typ): Boolean;

    <=

    Add

    Binary

    Add(a: Typ; b: Typ): Ergebnistyp;

    +

    Subtract

    Binary

    Subtract(a: Typ; b: Typ): Ergebnistyp;

    -

    Multiply

    Binary

    Multiply(a: Typ; b: Typ): Ergebnistyp;

    *

    Divide

    Binary

    Divide(a: Typ; b: Typ): Ergebnistyp;

    /

    IntDivide

    Binary

    IntDivide(a: Typ; b: Typ): Ergebnistyp;

    div

    Modulus

    Binary

    Modulus(a: Typ; b: Typ): Ergebnistyp;

    mod

    LeftShift

    Binary

    LeftShift(a: Typ; b: Typ): Ergebnistyp;

    shl

    RightShift

    Binary

    RightShift(a: Typ; b: Typ): Ergebnistyp;

    shr

    LogicalAnd

    Binary

    LogicalAnd(a: Typ; b: Typ): Ergebnistyp;

    and

    LogicalOr

    Binary

    LogicalOr(a: Typ; b: Typ): Ergebnistyp;

    or

    LogicalXor

    Binary

    LogicalXor(a: Typ; b: Typ): Ergebnistyp;

    xor

    BitwiseAnd

    Binary

    BitwiseAnd(a: Typ; b: Typ): Ergebnistyp;

    bitwiseand

    BitwiseOr

    Binary

    BitwiseOr(a: Typ; b: Typ): Ergebnistyp;

    bitwiseor

    BitwiseXor

    Binary

    BitwiseXor(a: Typ; b: Typ): Ergebnistyp;

    bitwisexor