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.
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".
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.
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.
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.
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;
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.
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
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 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.....).
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;
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!
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 |