|
|
Python external function examples: Current functions |
This topic is intended to be read in conjunction with the main external function documentation, and the example source code.
This ZIP file contains all of the Python external function examples, with each example contained in the appropriately named sub-folder.
This example comprises the Python script CurrentFunctionExamples.py, an OrcaFlex model CurrentExamples.dat and a workspace file CurrentExamples_default.wrk.
Open the model in OrcaFlex and the Python module in your preferred editor. On the variable data form in OrcaFlex there are external function variable data sources set up for each of the examples. And on the current page of the environment data form you can select which variable data source is used for the current speed (and direction, for the last example).
Now use the OrcaFlex Workspace menu to open the default workspace file, which shows windows for the time history of wind speed and current speed and direction. When you run the model, the current during the simulation is calculated by the selected external function, and the resulting current speed and direction are displayed.
The simplest Python external function is the Python class IncreasingSpeed, which implements just one method, Calculate. This method sets info.Value to give a current speed that is zero in the build-up stage (simulation time less than zero) and rises steadily after that.
Look at the IncreasingSpeed class in CurrentFunctionExamples.py to see this example, and to see it in action, set the current speed in the OrcaFlex model CurrentExamples.dat to use the Increasing speed variable data source and run the simulation. In the OrcaFlex simulation you should see the current speed time history showing zero current until simulation time 0.0, and then rising steadily after that.
For details of the info object that is passed by OrcaFlex to all the external function methods, see ExternalFunctionInfo.
Suppose we want our surface current speed to depend on the wind speed. Look at the WindProportionalSpeed class in CurrentFunctionExamples.py to see how this can be done. To see it in action, reset the simulation and set the current speed to use the Wind-proportional speed variable data source and re-run.
The OrcaFlex model uses a spectral wind speed, and the Calculate method of the WindProportionalSpeed class calls OrcaFlex back to get the instantaneous wind speed and then set the current speed accordingly. This example uses an Initialise method, so that it can initialise some variables once at the start, which avoids wastefully setting them at each time step in the Calculate method.
The constant parameters that are initialised in the Initialise method could be more conveniently specified in the OrcaFlex model, using object tags. Later examples in this documentation demonstrate how this can be done.
To get a smoother current variation, we might want to use a moving average of the wind speed, rather than the instantaneous wind speed, to determine the current. To do this we need to keep a history of the recent wind speed values, and this means that we also need to store and restore this information if the simulation is paused and saved, to ensure the external function can continue correctly when the simulation is resumed.
The class MovingAverageSpeed shows how this is done. If the simulation is paused and saved, then the StoreState method will be called and anything it puts in info.StateData will be stored in the simulation file. When the saved simulation is re-opened and continued the Initialise method will be called again, but this time the attribute info.StateData will contain what was stored by StoreState. This information is used to re-initialise the external function to the state it was in when the simulation file was stored.
Thejson module is used to serialise our Python state data into a form suitable to be saved in the OrcaFlex simulation file, and to restore it again when the simulation file is reloaded.
Often the external function wants to handle more than one data item. For example, for an externally calculated applied load you probably want to set three or six components (three components of force, and possibly three components of moment too). The MovingAverageSpeedAndDirection example shows how to do something similar to this, setting both the current speed and current direction using a single external function class.
In the OrcaFlex model, set both the current speed and direction to use the Moving average speed & direction variable data source. When the simulation is run OrcaFlex now creates two instances of the MovingAverageSpeedAndDirection class, one for current speed and one for current direction. The class methods will be called twice, once for current speed and once for current direction, in that order. The methods can tell which instance is being called using the info.DataName attribute, as shown in the example code.
For this external function we want to do combined speed and direction calculations, and do most of them only once, not once per instance. In this class each of the methods does the bulk of the work when it is called for current speed, which is called first, as noted in external function calling order. In the call for speed the calculated current direction value is saved in the info.Workspace attribute, which is shared at the model level and can be accessed by both instances of the class. The info.DataName == "RefCurrentDirection" call, for current direction, then just needs to use this shared class variable to set the current direction.
A helper function GetVector(), which is outside the class, is used in the calculation. The StoreState method now needs to store more than one piece of state data, so for clarity it stores a dictionary containing the information it requires using the Python built-in json module .