SIMAPy

SIMA has an easy-to-use graphical user interface for modelling, however graphical user interfaces can be inefficient for repetitive tasks or modelling of large systems with many similar components. SIMAPy together with SIMA’s JSON export/import functionality and SIMA Runtime Engine (SRE) can ease this process.

JSON Export

All of SIMAs models can be represented in the JSON format.

In SIMA you can right click any model in the navigator JSON export 1

and then select Export-JSON model export

JSON export 2

The result can be inspected and edited in a regular text editor.

supernode.json:

{
    "name" : "RiserAnchor",
    "type" : "sima/riflex/SuperNode",
    "constraint" : "FIXED_PRESCRIBED",
    "automaticInitialPosition" : false,
    "xConstraint" : "FIXED",
    "yConstraint" : "FIXED",
    "zConstraint" : "FIXED",
    "rxConstraint" : "FIXED",
    "ryConstraint" : "FIXED",
    "rzConstraint" : "FIXED",
    "xInitial" : 0.0,
    "yInitial" : 0.0,
    "zInitial" : -50.0,
    "xStatic" : 0.0,
    "yStatic" : 0.0,
    "zStatic" : -100.0
}

The JSON file is backwards compatible, meaning future official versions of SIMA will be able to read it.

Python Export

It is also possible to export the models as pure Python code. The exported code will recreate the model when running the script.

Right click Supernode and choose Export - Python model export

Python export

supernode.py:

import simapy.sima.riflex as riflex
riseranchor = riflex.SuperNode()
riseranchor.name = "RiserAnchor"
riseranchor.xConstraint = riflex.BoundaryCondition.FIXED
riseranchor.yConstraint = riflex.BoundaryCondition.FIXED
riseranchor.zConstraint = riflex.BoundaryCondition.FIXED
riseranchor.rxConstraint = riflex.BoundaryCondition.FIXED
riseranchor.ryConstraint = riflex.BoundaryCondition.FIXED
riseranchor.rzConstraint = riflex.BoundaryCondition.FIXED
riseranchor.zInitial = -50.0
riseranchor.zStatic = -100.0
riseranchor.rotation = -90.0

We can use Python and JSON export on any level in the Navigator

  • Single model-element

  • Multiple model-elements (ctrl-click or folder icon)

  • Whole task

JSON Import in SIMAPy

The exported JSON file from SIMA can again be imported in Python. Here we can see an example reading the Super Node from file and then we create several Supernodes by copying the first and write back to JSON for SIMA to import.

import numpy as np
from simapy.sima.riflex.supernode import SuperNode
from simapy.sima_reader import SIMAReader
from simapy.sima_writer import SIMAWriter
#SIMAReader will read the JSON file and return a list of Python objects
reader = SIMAReader()
contents = reader.read('supernode.json')
base_sn: SuperNode = contents[0]
supernodes = []
for i, x in enumerate(np.linspace(0.0, 10.0, 6)):
    # Copy imported supernode as starting point
    sn = base_sn.copy()
    # Adjust static position and name
    sn.xStatic = x
    sn.name = f'Anchor{i}'
    supernodes.append(sn)
# SIMAWriter will write the list of Python objects to a JSON file
writer = SIMAWriter()
writer.write(supernodes, 'supernodes.json')

After running the script locally, the JSON file can be imported into SIMA. Select parent Slender System in the RIFLEX Task then right click and choose Import - Import from JSON JSON Import Wizard

Resulting model after import:

Imported Supernodes

JSON vs. Python backwards compatibility

  • The Python code itself is not backwards compatible. This feature is handled by the JSON file migration within SIMA

    • Python code based on SIMA 4.2.0 will mostly work with SIMA 4.4.0, but there will be some differences that must be manually migrated. The SIMA data model has changed in SIMA 4.4.0, and some attributes have been removed or renamed.

  • The migration of JSON files is currently only supported in SIMA

    • This means opening a SIMA 4.2.0 based JSON file in SIMAPy supporting SIMA 4.4.0 will not work

  • Since the JSON file is backwards compatible within SIMA, a python code based on SIMApy 4.2.0 will still work when exporting a JSON file into never versions of SIMA.

SIMA Data model

How do we know which attributes we can set when coding models in Python? All SIMA elements are based on an underlying data model.

Super Node editor:

Super Node editor

This model can be viewed in SIMA by going to menu Tools - Advanced - Show SIMA datamodel

Super node model: SIMA datamodel view

SRE – SIMA Runtime Engine

SIMA Runtime Engine or SRE is SIMA without the user interface. Using SRE it is possible to automate several tasks, such as running a workflow, importing/exporting files, etc. It is found in the same installation folder as sima.exe. SRE Enables running different commands in batch.

sre.exe –help all

will show all available commands

SRE

sre.exe –help

will show detailed help for the given command

SIMA batch commands

Batch commands for SRE can also be created in SIMA main menu: Tools - Advanced - Run SIMA batch command

This view can be used to test the commands in the current workspace. It is possible to export the commands to the clipboard or as a file which itself can be run

SRE Command view

Running SRE from SIMAPy – Example

  • Using Python to make SRE:

    • Import JSON file

    • Run simulation

  • Results are available as a HDF5 file

import os
from pathlib import Path
from simapy.sre import SIMA
json = Path('riflex_task.json')
commands = []
# Use import command to import the json file
commands.append('--import')
commands.append('file=' + str(json.absolute()))
# Then use condition command to run dynamic analysis for the given condition
commands.append('--condition')
commands.append('task=Simple_Flexible_Riser')
commands.append('condition=Initial')
commands.append('runType=dynamic')
# Set variable values
commands.append('input=hs=3;tp=5')
# Set output file to export results to
output = Path('output.h5')
commands.append('output=' + str(output.absolute()))


# Requires that the environment is set, but an 
# alternative path may be given
exe = os.getenv('SRE_EXE')
sima = SIMA(exe=exe)
sima.run('.', commands)

Results

HDF5 File (HDFView)

The resulting h5 file can be read in Python using the h5py library.

import h5py
import matplotlib.pyplot as plt

with h5py.File('output.h5', 'r') as f:
    # Get FMAX signal in the h5 file
    fmax=f['Simple_Flexible_Riser']['Initial']["Dynamic"]["RiserLine"]["Force envelope curve"]["F-MAX"]
    plt.figure(figsize=(10, 5))  # Make the plot wider
    plt.plot(fmax[0,:], fmax[1,:], marker='o')
    plt.title("F-MAX")
    plt.xlabel("Distance along the line [m]")
    plt.ylabel("F-MAX [N]")
    plt.tight_layout()
    plt.savefig("fmax.png")

Plot