Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Export capi #95

Merged
merged 12 commits into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .ci_support/run_docker_linux.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ cp -r /io/* /tmp
cd /tmp
pip install . --user --break-system-packages
~/.local/bin/mo2fmu -h
~/.local/bin/mo2fmu ./otfmi/example/file/deviation.mo ./otfmi/example/file/fmu/linux64/deviation.fmu
~/.local/bin/mo2fmu ./otfmi/example/file/deviation.mo ./otfmi/example/file/fmu/linux-x86_64/deviation.fmu
pytest test -s
cd doc && make html BUILDDIR=~/.local/share/otfmi/doc

Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ jobs:
- name: Build
shell: bash -l {0}
run: |
conda install -y pyfmi openturns pytest jinja2 omcompiler
conda install -y pyfmi openturns pytest jinja2 fmpy-base pythonfmu omcompiler
pip install .
mo2fmu -h
mo2fmu ./otfmi/example/file/deviation.mo ./otfmi/example/file/fmu/linux64/deviation.fmu
mo2fmu ./otfmi/example/file/deviation.mo ./otfmi/example/file/fmu/linux-x86_64/deviation.fmu
pytest test -s

conda-windows:
Expand All @@ -52,7 +52,7 @@ jobs:
choco install openmodelica --version=1.21.0 --ignore-checksums
$env:PATH += ";C:\Program Files\OpenModelica1.21.0-64bit\bin"
omc --version
conda install -y pyfmi openturns pytest jinja2
conda install -y pyfmi openturns pytest jinja2 fmpy-base pythonfmu
pip install .
mo2fmu -h
pytest test -s
Expand Down
4 changes: 4 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
2023-11-23 - release 0.16
- Allow FunctionExporter to export .mo in subprocess/cpython/cxx modes (Function only)
- Allow export to .fmu via pythonfmu (allows to export both Function and PointToFieldFunction but not pyfmi/otfmi compatible)

2022-01-24 - release 0.15
- Add FMUPointToFieldFunction
- FMUFunction: Add final_time
Expand Down
4 changes: 2 additions & 2 deletions doc/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,10 @@ The submodule **otfmi.fmi** gathers a set of useful functions, employed by the (
fmi.get_start_value
fmi.set_dict_value

From OpenTURNS to FMU
From OpenTURNS to FMI
---------------------

Otfmi can also embed an OpenTURNS function in a Modelica model and/or FMU.
OTFMI can also export an OpenTURNS function in a Modelica source model (.mo) or Functional Mock-up Unit (.fmu).

.. autosummary::
:toctree: _generated/
Expand Down
43 changes: 13 additions & 30 deletions doc/conf.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import sys
import os
import subprocess
from distutils.version import LooseVersion
import sphinx
# import sphinx_gallery


# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
Expand Down Expand Up @@ -43,10 +41,7 @@
}


if LooseVersion(sphinx.__version__) >= "1.8":
autodoc_default_options = {"members": None, "inherited-members": None}
else:
autodoc_default_flags = ["members", "inherited-members"]
autodoc_default_options = {"members": None, "inherited-members": None}

intersphinx_mapping = {
"openturns": ("http://openturns.github.io/openturns/latest", None)
Expand All @@ -56,30 +51,18 @@
numpydoc_show_class_members = True
numpydoc_class_members_toctree = False

try:
import sphinx.ext.imgmath

extensions.append("sphinx.ext.imgmath")
imgmath_latex_preamble = r"\usepackage{{{0}math_notations}}".format(
os.path.dirname(__file__) + os.sep
)
imgmath_use_preview = True
if (
subprocess.call(
"dvisvgm -V", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
== 0
):
imgmath_image_format = "svg"
except ImportError:
extensions.append("sphinx.ext.pngmath")
pngmath_latex_preamble = r"\usepackage{{{0}math_notations}}".format(
os.path.dirname(__file__) + os.sep
extensions.append("sphinx.ext.imgmath")
imgmath_latex_preamble = r"\usepackage{{{0}math_notations}}".format(
os.path.dirname(__file__) + os.sep
)
imgmath_use_preview = True
if (
subprocess.call(
"dvisvgm -V", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
# The next option is used for smart-alignment of math images on the text.
# It only works when the preview-latex package is installed.
# See http://sphinx-doc.org/latest/ext/math.html#confval-pngmath_use_preview
pngmath_use_preview = True
== 0
):
imgmath_image_format = "svg"

# Add any paths that contain templates here, relative to this directory.
templates_path = ["_templates"]
Expand Down
2 changes: 1 addition & 1 deletion doc/example/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ Common low-level functions
../auto_example/low_level/plot_simulate
../auto_example/low_level/plot_initialize

From OpenTURNS to FMU
From OpenTURNS to FMI
---------------------

.. warning::
Expand Down
16 changes: 7 additions & 9 deletions doc/example/ot_to_fmu/plot_fmu_exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@
# ``otfmi.FunctionExporter`` enables to export OpenTURNS functions as FMUs. The
# main interest of this class is to use OpenTURNS metamodels in a simulation environment.
#
# .. warning::
# **This functionality is experimental**.
#
# Currently, the inclusion of a metamodel in
# `OpenModelica GUI <https://openmodelica.org/?id=78:omconnectioneditoromedit&catid=10:main-category>`_
# has been performed once (see
Expand All @@ -23,15 +20,15 @@
#
# First, we create the OpenTURNS function to export as FMU.
# This example being solely a demonstrator, we consider a very simple
# exponentiel function.
# exponential function.

import openturns as ot
import otfmi
import tempfile
from os.path import join

func = ot.SymbolicFunction("x", "exp(x)")
inputPoint = ot.Point([2])
func = ot.SymbolicFunction(["x"], ["exp(x)"])
inputPoint = [2.0]
print(func(inputPoint))

# %%
Expand All @@ -41,9 +38,10 @@
print(fmu_path)

# %%
# We export the OpenTURNS function as a Model Exchange FMU. Another export
# possiblity is the CoSimulation FMU (embeds a solver).

# We export the OpenTURNS function as a Model Exchange FMU.
# The counterpart is to export as CoSimulation FMU (embeds a solver).
# Another option would be to export the function via pythonfmu (see the "mode" keyword)
# allowing export of temporal functions (not a concern here for our function).
fmuExporter.export_fmu(fmu_path, fmuType="me")

# %%
Expand Down
9 changes: 4 additions & 5 deletions doc/example/ot_to_fmu/plot_model_exporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@
# ``otfmi.FunctionExporter`` enables to export OpenTURNS functions as Modelica model.
# The main interest is to use OpenTURNS metamodels in a simulation environment.
#
# .. warning::
# **This functionality is experimental**.
#
# Currently, the inclusion of a metamodel in
# `OpenModelica GUI <https://openmodelica.org/?id=78:omconnectioneditoromedit&catid=10:main-category>`_
# has been performed once (see
Expand All @@ -29,7 +26,7 @@


func = ot.SymbolicFunction("x", "exp(x)")
inputPoint = ot.Point([2])
inputPoint = [2.0]
print(func(inputPoint))

# %%
Expand All @@ -47,7 +44,7 @@
modelExporter.export_model(model_path, gui=True)

# %%
# Simple as it looks, this function actually does the following :
# Simple as it looks, this function actually does the following:
#
# - write a C-wrapper for the OpenTURNS function,
# - write a Modelica model calling the C-wrapper as `External <shorturl.at/fhCU2>`_ function.
Expand Down Expand Up @@ -107,3 +104,5 @@
# ⚠️ Compared to native Modelica functions, the included OpenTURNS function is
# slow. In this case, 11 seconds of simulation were required for 50 time
# steps (i.e. 50 function calls).
#
# Note that faster export modes are available with the "mode" keyword, depending on your setup.
2 changes: 1 addition & 1 deletion otfmi/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = "0.15"
__version__ = "0.16"

from .otfmi import (
FMUFunction,
Expand Down
35 changes: 5 additions & 30 deletions otfmi/example/deviation.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,10 @@
"""

import otfmi
from pyfmi.fmi import FMUException
import otfmi.example.utility
import sys
import os
import platform
import openturns as ot

key_platform = (platform.system(), platform.architecture()[0])
# Call to either 'platform.system' or 'platform.architecture' *after*
# importing pyfmi causes a segfault.
dict_platform = {("Linux", "64bit"): "linux64", ("Windows", "64bit"): "win64"}

# Define the input distribution
E = ot.Beta(0.93, 3.2, 2.8e7, 4.8e7)
F = ot.LogNormalMuSigma(3.0e4, 9000.0, 15000.0).getDistribution()
Expand Down Expand Up @@ -69,26 +62,10 @@ def deviationFunction(x):

model_py = ot.PythonFunction(4, 1, deviationFunction)

path_here = os.path.dirname(os.path.abspath(__file__))
try:
directory_platform = dict_platform[key_platform]
path_fmu = os.path.join(
path_here, "file", "fmu", directory_platform, "deviation.fmu"
)
model_fmu = otfmi.FMUFunction(
path_fmu, inputs_fmu=["E", "F", "L", "I"], outputs_fmu=["y"]
)
except KeyError:
raise RuntimeError(
"Tests are not available on your platform" " (%s)." % "-".join(key_platform)
)
sys.exit()
except FMUException:
raise FMUException(
"The test FMU 'deviation.fmu' is not"
" available on your platform (%s)." % "-".join(key_platform)
)
sys.exit()
path_fmu = otfmi.example.utility.get_path_fmu("deviation")
model_fmu = otfmi.FMUFunction(
path_fmu, inputs_fmu=["E", "F", "L", "I"], outputs_fmu=["y"]
)


def create_monte_carlo(model, inputRandomVector, coefficient_variation):
Expand Down Expand Up @@ -206,8 +183,6 @@ def run_demo(seed=23091926, coefficient_variation=0.20):


if __name__ == "__main__":
import sys

try:
coefficient_variation = float(sys.argv[1])
except IndexError:
Expand Down
3 changes: 2 additions & 1 deletion otfmi/example/export.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@

import openturns as ot
import otfmi
import otfmi.example.utility

# create function
f = ot.SymbolicFunction(["E", "F", "L", "I"], ["(F*L^3)/(3.0*E*I)"])
start = [3e7, 3e4, 250.0, 400.0]

# export fmu
path_fmu = "/tmp/deviation.fmu"
path_fmu = otfmi.example.utility.get_path_fmu("deviation")
fe = otfmi.FunctionExporter(f, start)
fe.export(path_fmu)

Expand Down
23 changes: 23 additions & 0 deletions otfmi/example/file/DeviationSlave.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import openturns as ot
from pythonfmu.fmi2slave import Fmi2Slave, Fmi2Causality, Real


class DeviationSlave(Fmi2Slave):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.__function = ot.SymbolicFunction(["E", "F", "L", "II"], ["F*L^3/(3*E*II)"])

for var in self.__function.getInputDescription():
setattr(self, var, 0.0)
self.register_variable(Real(var, causality=Fmi2Causality.input))

for var in self.__function.getOutputDescription():
setattr(self, var, 0.0)
self.register_variable(Real(var, causality=Fmi2Causality.output))

def do_step(self, current_time, step_size):
inP = [getattr(self, var) for var in self.__function.getInputDescription()]
outP = self.__function(inP)
for i, var in enumerate(self.__function.getOutputDescription()):
setattr(self, var, outP[i])
return True
Binary file not shown.
Binary file not shown.
61 changes: 9 additions & 52 deletions otfmi/example/parallel.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,12 @@
# Phimeca Engineering (Sylvain Girard, girard@phimeca.com).
"""Run multiple FMU simulations in parallel."""


import platform
import openturns as ot
import otfmi
from pyfmi.fmi import FMUException
import otfmi.example
import sys
import os
import time


key_platform = (platform.system(), platform.architecture()[0])
# Call to either 'platform.system' or 'platform.architecture' *after*
# importing pyfmi causes a segfault.
dict_platform = {("Linux", "64bit"): "linux64", ("Windows", "64bit"): "win64"}

# Define the input distribution
E = ot.Beta(0.93, 3.2, 28000000.0, 48000000.0)
F = ot.LogNormalMuSigma(3.0e4, 9000.0, 15000.0).getDistribution()
Expand All @@ -32,8 +23,6 @@
# Create the input random vector
inputRandomVector = ot.RandomVector(inputDistribution)

path_here = os.path.dirname(os.path.abspath(__file__))


def instantiate_highlevel(n_cpus=2):
"""Instantiate an FMUFunction and set number of cores to use.
Expand All @@ -43,50 +32,18 @@ def instantiate_highlevel(n_cpus=2):
n_cpus : Integer, number of cores to use for multiprocessing.

"""
try:
directory_platform = dict_platform[key_platform]
path_fmu = os.path.join(
path_here, "file", "fmu", directory_platform, "deviation.fmu"
)
return otfmi.FMUFunction(
path_fmu, inputs_fmu=["E", "F", "L", "I"], outputs_fmu="y", n_cpus=n_cpus
)
except KeyError:
raise RuntimeError(
"Examples are not available on your platform"
" (%s)." % "-".join(key_platform)
)
sys.exit()
except FMUException:
raise FMUException(
"The example FMU 'deviation.fmu' is not"
" available on your platform (%s)." % "-".join(key_platform)
)
sys.exit()
path_fmu = otfmi.example.get_fmu_path("deviation.fmu")
return otfmi.FMUFunction(
path_fmu, inputs_fmu=["E", "F", "L", "I"], outputs_fmu="y", n_cpus=n_cpus
)


def instantiate_lowlevel():
"""Instantiate an OpenTURNSFMUFunction."""
try:
directory_platform = dict_platform[key_platform]
path_fmu = os.path.join(
path_here, "file", "fmu", directory_platform, "deviation.fmu"
)
return otfmi.OpenTURNSFMUFunction(
path_fmu, inputs_fmu=["E", "F", "L", "I"], outputs_fmu="y"
)
except KeyError:
raise RuntimeError(
"Examples are not available on your platform"
" (%s)." % "-".join(key_platform)
)
sys.exit()
except FMUException:
raise FMUException(
"The example FMU 'deviation.fmu' is not"
" available on your platform (%s)." % "-".join(key_platform)
)
sys.exit()
path_fmu = otfmi.example.get_fmu_path("deviation.fmu")
return otfmi.OpenTURNSFMUFunction(
path_fmu, inputs_fmu=["E", "F", "L", "I"], outputs_fmu="y"
)


def ask_n_cpus():
Expand Down
Loading
Loading