Native external functions

Native external functions can be implemented in C++ or Delphi and require that a DLL is created, exporting a function or functions that match the declaration described below.

External function declaration

The function must be declared with the stdcall calling convention. In C++ the function would be declared as:

void __stdcall ExtFn(TExtFnInfo &ExtFnInfo);

In Delphi the function would be declared as:

procedure ExtFn(var ExtFnInfo: TExtFnInfo); stdcall;

You can export any number of different external functions from the same DLL. We recommend that you use descriptive names for your external functions so that they can be more easily identified on the OrcaFlex variable data form.

External function call sequence

This function will be called in the following way during an OrcaFlex calculation.

  1. The first call to the external function has the ExtFnInfo.Action equal to eaRegisterResults. the external function must respond to this if it calculates any external results, see Native external functions: Results and C_RegisterExternalFunctionResult. The external function will also be called with this action when a simulation file is opened.
  2. When the static calculation starts the function is called with ExtFnInfo.Action equal to eaInitialise and ExtFnInfo.SimulationTime equal to -Build-up duration. The ExtFnInfo.Value member is set to the "Initial Value" data item as specified in OrcaFlex on the variable data form. The external function can optionally choose to override this value by modifying ExtFnInfo.Value.
  3. The static calculation proceeds using the value returned from step 1.
  4. During the simulation, at each external function update interval (set in OrcaFlex on the variable data form), the external function is called to get an updated value. This call has ExtFnInfo.Action equal to eaCalculate. Some external functions provide information about the OrcaFlex object's instantaneous state (e.g. position, orientation, velocity etc.) through ExtFnInfo.lpInstantaneousCalculationData. For more details please refer to the Instantaneous Calculation Data topic. As an alternative, the external function can call C_GetTimeHistory2 to get instantaneous values of simulation results variables. If your external function does this then it should set lpPeriod->PeriodNum to pnInstantaneousValue.
  5. Following the eaCalculate call, at each log interval will be a call with ExtFnInfo.Action equal to eaLogResultCreate and then eaLogResultDestroy which allow external functions which produce external results to store data in the simulation log file. See Native external functions: Results.
  6. When the model is reset the external function is called again with ExtFnInfo.Action equal to eaFinalise. The purpose of this call is to give the external function an opportunity to finalise and deallocate any data structures it used during the sequence of calculations.
  7. Tracking external functions are used within a line type stiffness variable data source and will be called with ExtFnInfo.Action set to eaInitialise and eaFinalise in the same way as calculating ones, but during the simulation are called with the eaTrackCalculation action at each logging interval instead of eaCalculate. The ExtFnInfo.lpInstantaneousCalculationData structure will have been populated.
Notes: Axial stiffness and bend stiffness external functions for lines differ in that they are updated during statics. In addition external functions for vessels, 6D buoys, wings and line applied loads can optionally elect to be updated during statics by modifying ExtFnInfo.UpdateDuringStatics.
When OrcaFlex is using Implicit Integration, the external function may be repeatedly called for the same timestep as OrcaFlex iterates towards a solution. OrcaFlex indicates when the eaCalculate call is for a new timestep by setting the NewTimeStep field to true.
Calling C_GetTimeHistory2 from an external function is slower than using the lpInstantaneousCalculationData field. Because of this we recommend the latter approach whenever possible. Indeed for bend stiffness external functions you must use the lpInstantaneousCalculationData field.

Please note that the external function must not throw any exceptions since OrcaFlex will not be able to handle them – the function must catch all exceptions and handle them before returning. The function can report feedback of any errors that occur by calling C_RecordExternalFunctionError.

If your function's algorithm has state information (e.g. the integrator for a PID controller) then you can store this information in the Data member of the TExtFnInfo structure. To ensure that this state information is restored if you load a partially complete simulation please refer to the State Storage topic.

Linking to OrcFxAPI

The procedure for linking an external function to OrcFxAPI differs from a standalone application that uses OrcFxAPI. It is essential that the external function links to the specific OrcaFlex/OrcFxAPI instance that hosts the external function.

For a C++ external function you must not link the OrcFxAPI .lib file to your external function DLL. Instead include OrcFxAPIExplicitLink.c in your DLL project. In addition you must ensure that your DLL exports the function named InitializeOrcFxAPI which is defined in OrcFxAPIExplicitLink.c. Do this by adding InitializeOrcFxAPI to your project's .def file.

For a Delphi external function you must add the ExplicitLinkOrcFxAPI conditional define to your project options. When you do this the InitializeOrcFxAPI function defined in OrcFxAPI.pas will automatically be exported from your DLL.

32/64 bit

Because the external function DLL is loaded directly into the OrcaFlex process, you need to provide a 32 bit DLL for use by 32 bit versions of OrcaFlex, and a 64 bit DLL for use by 64 bit versions of OrcaFlex. If you use exclusively 32 bit OrcaFlex then you can build just a 32 bit version of the external function DLL. Likewise, if you use exclusively 64 bit OrcaFlex then you need only build a 64 bit version of your DLL.

There are situations where it may be desirable to to use the same external function from both 32 and 64 bit versions of OrcaFlex. For example, if your IT environment has both 32 and 64 bit systems that run OrcaFlex, then in order to share an external function amongst all OrcaFlex users, you need to compile both 32 and 64 bit versions of the external function DLL. These should be located in the same directory and the 64 bit version given the suffix of 64. For example, if the 32 bit external function DLL is named ExtFn.dll then the 64 bit DLL must be named ExtFn64.dll.

If you follow this naming convention, then OrcaFlex will load whichever external function DLL matches the architecture of the OrcaFlex process. In this situation, it does not matter which version of the DLL you refer to from your OrcaFlex data. The 32 bit OrcaFlex will always load ExtFn.dll, even if the data file names ExtFn64.dll. And vice versa, the 64 bit OrcaFlex will always load ExtFn64.dll, even if the data file names ExtFn.dll.

Examples

A number of examples of external functions can be found in ExternalFunctionExamples.zip. This file can be found on the OrcaFlex CD, in the OrcaFlex installation directory or on our website.

See also

TExtFnInfo, Instantaneous Calculation Data, Capabilities, State Storage, Thread Safety, Axial Stiffness, Bend Stiffness, Torsional Stiffness, and Native external functions: Results.