Python API in Ashes

Ashes offers an Application Programming Interface (API) for custom Python scripts. This is typically used to run your own advanced load models while using Ashes solver, for example wave load models, geotechnical models or controllers. When Ashes and your Python script are running in parallel, Ashes will communicate with the script at every time step. You can for example use output from the Ashes simulation, such as node kinematics of elements characteristics as input to your Python script and send the value of the kinematics-dependent loads back into the simulation.

1 Setting up the API

We have made a very detailed video about how to set up the Python API, available here:  https://www.youtube.com/watch?v=RJ3yznaAkNc

1.1 Install the Simis package

Simply open a command window by typing cmd in the Windows search bar and launching the Command Prompt app, as shown in the image below:



In the command window, type the command   pip install Simis, as shown in the image below. Then press enter.


1.2 Enable external script

1.2.1 For controllers

You can use a Python script as a controller. To do so follow these steps:
  1. Select the Wind turbine in the Parts pane.
  2. Click on the Python icon on the top of the Parameters pane.
  3. Check Enable Script
  4. Decide whether the Script is to be run automatically or manually
    • Automatically: Ashes uses the Python executable defined in  Preferences to call the selected Python script. For this to work, all created Python files have to be in the same file-hierarchy and they will get saved into the ashes file. This method should be used for easy shipping and usage of tested Python scripts.
    • Manually: Ashes will wait for a Python script to connect to it once the simulation is started. This can be used for the debugging of the Python script or if the Python script should not be started by Ashes. The Python script has to be run from the console or an IDE of choice.

You can use Python scripts in four cases:
For each of these cases, you wil have to select Python script as the option for the parameter. The examle below shows how to select it for the Demanded pitch parameter:



1.2.2 For support sections

Python scripts can also be used to compute loads on the support section accounting for the motion of the structure itself. To do so
  1. Select the relevant support section in the Parts pane (for example, Tubular tower, Floater, Monopile, etc)
  2. Click on the Python icon on the top of the Parameters pane (see picture in section 1.2.1 of this document)
  3. Click Enable script
  4. Decide whether the script will be running automatically of manually (see point 4 in section 1.2.1 of this document)

Note that you can use a Python script for any support section that you have in your model. For example, if you have a Tubular tower on a Monopile, you could have one python script for each. you will then need to make sure that the name of the support structure is passed as a parameter to the ashes.connect()  function at the end of the scipt.

In the example below, the script will be applied to the part named Monopile_OC3



The name of a support section can be found in the parts tree, as shown in the image below:



The name of a part can be changed with the Name keyword in the  Support section files.
 


Note: Ashes will need the latest version of the Simis package for the API to work correctly. If you run into issues when running your Python script, always make sure you have the lates version by typing pip install Simis --upgrade  in a command window


2 Interface variables

The values provided by the Ashes interface are the following:

Parameter Unit Name in Data structure
Current simulation time s time
Average Wind including tower shadow m/s wind
For each rotor:
  • Rotor speed
  • Generator speed
  • Shaft twist angle
  • Generator torque
  • Blade pitch

  • 1/min
  • 1/min
  • degrees
  • Nm
  • degrees
"rna->GetLocalName()" (ex: RNA or RNA1)
  • rpm
  • v_gen
  • shaft_tors
  • torq_gen
  • current_pitch
  • For each blade:
    • Displaced pitch angle
    • Pitch angle speed

  • degrees
  • rad/s
  • "blade->GetLocalName()" (ex: Blade1)
    • displaced_structural_pitch_angle_deg
    • structural_pitch_rate_rad_per_sec
For FEM parts: support
  • For each node:
    • Initial position (x/y/z)
    • Diplacement (x/y/z)
    • Velocity (x/y/z)
    • Acceleration (x/y/z)
    • Rotation (x/y/z)
    • Rotational Velocity (x/y/z)

  • m
  • m
  • m/s
  • m/s 2
  • degrees
  • degrees/s
  • "node->GetLocalName()" (ex: Node1)
    • initialposition.x/y/z
    • displacement.x/y/z
    • velocity.x/y/z
    • acceleration.x/y/z
    • rotation.x/y/z
    • rotation_velocity.x/y/z
  • For each element:
    • Material
      • Density
      • Elastic Modulus
      • Poisson Ratio
      • Shear Modulus
      • Yield Stress
      • Material name

  • kg/m 3
  • Pa
  • 1
  • Pa
  • Pa
  • "element->GetLocalName()" (ex: Element1)
    • material
      • density
      • ElasticModulus
      • poissonRatio
      • shearModulus
      • yieldStress
      • name


The collumn "Name in Data structure" describes how the values can be accessed in the Python environment. Names under quotation-marks are dynamically set and are the names defined in  Support section files with an additional Prefix describing the Part type (RNA, Blade, Node or Element).

Ashes accepts values from Python in the following structure. Variables that the script sets (writes back to Ashes) are prefixed with set_ to distinguish them from the read-only inputs above:
Parameter Unit Name in Data structure
For each node:
  • Moment Load (x/y/z)
  • Force Load (x/y/z)

  • Nm
  • N
"Node->GetLocalName()" (ex: Node1)
  • set_loadMoment.x/y/z
  • set_load.x/y/z
For each Rna:
  • Demanded Collective Blade Pitch Angle
  • Demanded Collective Pitch Rate
  • Demanded Yawing Torque
  • Demanded Generator Torque

  • degrees
  • degrees/s
  • Nm
  • Nm
"Rna->GetLocalName()" (ex: RNA or RNA1)
  • set_demanded_pitch_angle
  • set_pitch_rate
  • set_demanded_yaw_torque
  • set_demanded_generator_torque
  • For each Blade:
    • Demanded Individual Blade Pitch Angle
    • Demanded Blade Pitching Torque
    • Last Blade Pitch Error

  • degrees
  • Nm
  • rad
  • "Blade->GetLocalName()" (ex: Blade1)
    • set_demanded_pitch_angle
    • set_demanded_pitching_torque
    • set_last_pitch_error_rad

2.1 The displayModel.py script

One of the scripts that is shipped with Ashes is displayModel.py, which you can find in the Python API examples folder. This script is not intended to be used during a time simulation. It is a hack meant to show you all the parameters that are available for a given Ashes part in your script.

For example, you can use it to find all the available parameters of a Tubular tower: just run the displayModel.py script in Manual mode following the steps as shown in section 1.2.2 above. Once you run the script in your IDE, you will see in the terminal a list of all the parameters that can be used in your script, as shown in the image below.



Similarly, you can run it as a controller. It will then display all the parameters available to use in the controller script. Note that this includes parameters belonging to the support sections as well (if applicable). This means that parameters such as loads or displacements within the support section can be used to design the controller.

3 Scripts written before Ashes 4.3

In Ashes 4.3 the variables a script writes back to Ashes were given a set_ prefix, so that the control commands a script sets are told apart from the read-only state Ashes sends it. The read-only inputs ( rpm, power, wind, current_pitch, displacement and the others) are unchanged.

Before 4.3 From 4.3
demanded_pitch_angle set_demanded_pitch_angle
pitch_rate set_pitch_rate
demanded_generator_torque set_demanded_generator_torque
demanded_yaw_torque set_demanded_yaw_torque
demanded_pitching_torque set_demanded_pitching_torque
generator_efficiency set_generator_efficiency
estimated_wind, estimated_power set_estimated_wind, set_estimated_power
last_pitch_error_rad set_last_pitch_error_rad
load, loadMoment set_load, set_loadMoment

Note: the old names are no longer recognised, and assigning to one of them is not an error - the value is simply ignored. A script written before 4.3 therefore runs, connects and reports no problem, while the turbine behaves as if the script set nothing at all. If your controller seems to have no effect, check the names first. The example scripts delivered with Ashes were updated, but a copy in your own documents folder from an earlier version still uses the old names.

Note: a value the script sets is only used if the corresponding control system is set to Python script on the RNA part. Selecting a script in the Python script dialog does not by itself put it in charge of anything, and a demanded pitch angle set by a script while the demanded pitch scheme is, say, PID controller is discarded without a message.

The Script input field of the same dialog is passed to the script as model.user_defined_script_input and is yours to use as you like. Note that the delivered PitchToFeather example reads it as the time at which it starts pitching, so a value left in that field changes when that example does anything.

4 Tips and Tricks

  • You can find examples of scripts that work wish Ashes in  C:\Users\UserName\Documents\Ashes X.xx\Python examples. These scripts can be used as templates to write your own scripts.
  • The API works for Python 3 versions.
  • We use the free IDE Visual Studio Code, that can be downloaded from the following link: https://code.visualstudio.com/. This has worked great for us, when writing or debugging code, but the API will work with any IDE.
  • You can run your script in debug mode if you need insight into issues that your code might have
  • If your script crashes or is stopped for too long, you will need to restart the model in Ashes to be able to run the script again. The simplest way to do that is to modify a parameter and set it back to its original value, for example
      - Uncheck the Enable external script box
      - Check it back
      - Apply the changes (although in this case nothing will be changed) by clicking the green tick mark, as shown in the figure below