Skip to content

Commit

Permalink
Upgrade to Python3.11 + Cython3 (#213)
Browse files Browse the repository at this point in the history
Co-authored-by: Robin Andersson <[email protected]>
  • Loading branch information
2 people authored and Peter Meisrimel committed May 13, 2024
1 parent 6ca7f93 commit d4cc5ab
Show file tree
Hide file tree
Showing 27 changed files with 458 additions and 440 deletions.
17 changes: 10 additions & 7 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,15 @@ jobs:
linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
with:
python-version: '3.11.x'
- name: Setup Python
run: |
python3 -m pip install Cython numpy scipy matplotlib nose-py3
- name: Install system
run: |
sudo apt-get -y install python3-scipy python3-setuptools python3-nose cython3 python3-matplotlib
sudo apt-get -y install cmake liblapack-dev libsuitesparse-dev libhypre-dev
sudo cp -v /usr/lib/x86_64-linux-gnu/libblas.so /usr/lib/x86_64-linux-gnu/libblas_OPENMP.so
- name: Install superlu
Expand All @@ -35,9 +40,8 @@ jobs:
sudo make install
- name: Install assimulo
run: |
cd /tmp
curl -fSsL https://github.com/modelon-community/Assimulo/archive/Assimulo-3.4.1.tar.gz | tar xz
cd Assimulo-Assimulo-3.4.1
git clone --depth 1 -b dev-pm-python_upgrade https://github.com/modelon-community/Assimulo /tmp/Assimulo
cd /tmp/Assimulo
python3 setup.py install --user --sundials-home=/usr --blas-home=/usr/lib/x86_64-linux-gnu/ --lapack-home=/usr/lib/x86_64-linux-gnu/ --superlu-home=/usr --extra-fortran-compile-flags="-fallow-argument-mismatch"
- name: Install fmilib
run: |
Expand All @@ -55,5 +59,4 @@ jobs:
run: |
rm src/pyfmi/__init__.py
cp -rv src/pyfmi/tests/files tests
nosetests3 tests
python3 -m nose --verbose tests/*
1 change: 1 addition & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* Unified result handling and allowed the master algorithm to use all available result handlers
* Added new option "result_downsampling_factor" for simulation of CS-FMUs, including the Master algorithm.
Solution will only be stored every "result_downsampling_factor"-nth communication point.
* Upgraded to Cython3.

--- PyFMI-2.11.0 ---
* Refactored result handling for dynamic_diagnostics. It is now possible use dynamic_diagnostics with a custom result handler.
Expand Down
14 changes: 7 additions & 7 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
[options]
setup_requires =
setuptools
numpy >= 1.17
cython >= 0.29.13
numpy >= 1.26.3
cython >= 3.0

install_requires =
numpy >= 1.17
scipy >= 1.3
cython >= 0.29.13
nose >= 1.3.7
numpy >= 1.26.3
scipy >= 1.11.4
cython >= 3.0.7
nose-py3 >= 1.6.3
matplotlib > 3
assimulo >= 3.2
assimulo >= 3.5.0
32 changes: 19 additions & 13 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@
from Cython.Distutils import build_ext
from Cython.Build import cythonize
except ImportError:
raise Exception("Please upgrade to a newer Cython version, >= 0.15.")
raise Exception("Please upgrade to a newer Cython version, >= 3.")


NAME = "PyFMI"
AUTHOR = "Modelon AB"
AUTHOR_EMAIL = ""
VERSION = "3.0-dev"
VERSION = "2.12.0"
LICENSE = "LGPL"
URL = "https://github.com/modelon-community/PyFMI"
DOWNLOAD_URL = "https://github.com/modelon-community/PyFMI/releases"
Expand Down Expand Up @@ -73,7 +73,7 @@
-------------
- `FMI Library (at least 2.0.1) <https://github.com/modelon-community/fmi-library>`_
- `Python-headers (usually included on Windows, python-dev on Ubuntu)`_
- `Python 3.7 or newer`_
- `Python 3.11 or newer`_
- Python package dependencies are listed in file setup.cfg.
Optional
Expand All @@ -90,9 +90,10 @@

copy_args = sys.argv[1:]

if os.getenv("FMIL_HOME"): #Check for if there exists and environment variable that specifies FMIL
incdirs = os.path.join(os.getenv("FMIL_HOME"), 'include')
libdirs = os.path.join(os.getenv("FMIL_HOME"), 'lib')
fmil_home = os.getenv("FMIL_HOME")
if fmil_home: #Check for environment variable that specifies FMIL
incdirs = os.path.join(fmil_home, 'include')
libdirs = os.path.join(fmil_home, 'lib')
else:
incdirs = ""
libdirs = ""
Expand Down Expand Up @@ -153,7 +154,6 @@
debug_flag = False
copy_args.remove(x)


if not incdirs:
raise Exception("FMI Library cannot be found. Please specify its location, either using the flag to the setup script '--fmil-home' or specify it using the environment variable FMIL_HOME.")

Expand Down Expand Up @@ -214,29 +214,35 @@ def check_extensions():
incl_path = [".", "src", os.path.join("src", "pyfmi")]
#FMI PYX
ext_list += cythonize([os.path.join("src", "pyfmi", "fmi.pyx")],
include_path = incl_path)
include_path = incl_path,
compiler_directives={'language_level' : "3str"})

#FMI UTIL
ext_list += cythonize([os.path.join("src", "pyfmi", "fmi_util.pyx")],
include_path = incl_path)
include_path = incl_path,
compiler_directives={'language_level' : "3str"})

#FMI Extended PYX
ext_list += cythonize([os.path.join("src", "pyfmi", "fmi_extended.pyx")],
include_path = incl_path)
include_path = incl_path,
compiler_directives={'language_level' : "3str"})

#FMI Coupled PYX
ext_list += cythonize([os.path.join("src", "pyfmi", "fmi_coupled.pyx")],
include_path = incl_path)
include_path = incl_path,
compiler_directives={'language_level' : "3str"})

#Simulation interface PYX
ext_list += cythonize([os.path.join("src", "pyfmi", "simulation", "assimulo_interface.pyx")],
include_path = incl_path)
include_path = incl_path,
compiler_directives={'language_level' : "3str"})

#MASTER PYX
compile_time_env = {'WITH_OPENMP': with_openmp}
ext_list += cythonize([os.path.join("src", "pyfmi", "master.pyx")],
include_path = incl_path,
compile_time_env=compile_time_env)
compile_time_env=compile_time_env,
compiler_directives={'language_level' : "3str"})

for i in range(len(ext_list)):

Expand Down
4 changes: 2 additions & 2 deletions src/common/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ def _exec_algorithm(self, module, algorithm, options):
Exception if algorithm is not a subclass of
common.algorithm_drivers.AlgorithmBase.
"""
from .algorithm_drivers import AlgorithmBase
from pyfmi.algorithm_drivers import AlgorithmBase

if isinstance(algorithm, str):
module = __import__(module, globals(), locals(), [algorithm], 0)
Expand Down Expand Up @@ -182,7 +182,7 @@ def _exec_simulate_algorithm(self,
Exception if algorithm is not a subclass of
common.algorithm_drivers.AlgorithmBase.
"""
from .algorithm_drivers import AlgorithmBase
from pyfmi.algorithm_drivers import AlgorithmBase

if isinstance(algorithm, str):
module = __import__(module, globals(), locals(), [algorithm], 0)
Expand Down
6 changes: 3 additions & 3 deletions src/common/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -371,20 +371,20 @@ class ResultWriter():
Base class for writing results to file.
"""

def write_header():
def write_header(self):
"""
The header is intended to be used for writing general information about
the model. This is intended to be called once.
"""
pass

def write_point():
def write_point(self):
"""
This method does the writing of the actual result.
"""
pass

def write_finalize():
def write_finalize(self):
"""
The finalize method can be used to for instance close the file.
"""
Expand Down
4 changes: 2 additions & 2 deletions src/common/log/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
The log analysis toolkit.
"""

from .parser import parse_xml_log, parse_xml_log, extract_xml_log, parse_fmu_xml_log
from .prettyprinter import prettyprint_to_file
from pyfmi.common.log.parser import parse_xml_log, parse_xml_log, extract_xml_log, parse_fmu_xml_log
from pyfmi.common.log.prettyprinter import prettyprint_to_file

__all__=['parser','tree','prettyprinter']
2 changes: 1 addition & 1 deletion src/common/log/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
import os
import numpy as np
from distutils.util import strtobool
from .tree import *
from pyfmi.common.log.tree import *
from pyfmi.fmi_util import python3_flag
from pyfmi.fmi import FMUException

Expand Down
2 changes: 1 addition & 1 deletion src/common/log/prettyprinter.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"""

from numpy import ndarray
from .tree import *
from pyfmi.common.log.tree import *

def prettyprint(write, node):
"""Prettyprint a log node to the write callback write."""
Expand Down
14 changes: 6 additions & 8 deletions src/pyfmi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@
__all__ = ['fmi_algorithm_drivers', 'examples', 'fmi', 'common']

#Import the model class allowing for users to type e.g.,: from pyfmi import FMUModelME1
from .fmi import load_fmu, FMUModelME1, FMUModelME2
from .fmi import FMUModelCS1, FMUModelCS2
from .fmi_coupled import CoupledFMUModelME2
from .master import Master
from .fmi_extended import FMUModelME1Extended
from pyfmi.fmi import load_fmu, FMUModelME1, FMUModelME2
from pyfmi.fmi import FMUModelCS1, FMUModelCS2
from pyfmi.fmi_coupled import CoupledFMUModelME2
from pyfmi.master import Master
from pyfmi.fmi_extended import FMUModelME1Extended
import numpy as N
import os.path
import sys
Expand All @@ -49,7 +49,7 @@ def wrap(func):


try:
curr_dir = os.path.dirname(os.path.abspath(__file__));
curr_dir = os.path.dirname(os.path.abspath(__file__))
_fpath=os.path.join(curr_dir,'version.txt')
with open(_fpath, 'r') as f:
__version__=f.readline().strip()
Expand Down Expand Up @@ -178,5 +178,3 @@ def check_packages():
This package is needed to be able to use the plot-GUI.")

sys.stdout.write("\n\n")


33 changes: 20 additions & 13 deletions src/pyfmi/fmi.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ cimport numpy as N

N.import_array()

cimport fmil_import as FMIL
cimport pyfmi.fmil_import as FMIL

cdef FMIL.fmi_version_enu_t import_and_get_version(FMIL.fmi_import_context_t*, char*, char*, int)

Expand Down Expand Up @@ -116,7 +116,7 @@ cdef class FMUModelBase(ModelBase):
cdef FMIL.jm_callbacks* callbacks_standard

#Internal values
cdef public object __t
cdef public object _t
cdef public object _file_open
cdef public object _npoints
cdef public object _enable_logging
Expand Down Expand Up @@ -158,10 +158,11 @@ cdef class FMUModelME1(FMUModelBase):
cpdef _get_time(self)
cpdef _set_time(self, FMIL.fmi1_real_t t)
cpdef get_derivatives(self)
cdef int __get_nominal_continuous_states(self, FMIL.fmi1_real_t* xnominal, size_t nx)
cdef int _get_nominal_continuous_states_fmil(self, FMIL.fmi1_real_t* xnominal, size_t nx)
cdef public object _preinit_nominal_continuous_states

cdef class __ForTestingFMUModelME1(FMUModelME1):
cdef class _ForTestingFMUModelME1(FMUModelME1):
cdef int _get_nominal_continuous_states_fmil(self, FMIL.fmi1_real_t* xnominal, size_t nx)
cpdef set_allocated_fmu(self, int value)

cdef class FMUModelBase2(ModelBase):
Expand Down Expand Up @@ -190,7 +191,7 @@ cdef class FMUModelBase2(ModelBase):
cdef public list _save_real_variables_val
cdef public list _save_int_variables_val
cdef public list _save_bool_variables_val
cdef object __t
cdef object _t
cdef public object _pyEventInfo
cdef char* _fmu_temp_dir
cdef object _states_references
Expand All @@ -206,7 +207,7 @@ cdef class FMUModelBase2(ModelBase):
cdef object _outputs_states_dependencies_kind
cdef object _outputs_inputs_dependencies_kind
cdef object _A, _B, _C, _D
cdef public object _group_A, _group_B, _group_C, _group_D
cdef public object _group_A, _group_B, _group_C, _group_D
cdef object _mask_A
cdef object _A_row_ind, _A_col_ind
cdef public object _has_entered_init_mode
Expand Down Expand Up @@ -234,9 +235,9 @@ cdef class FMUModelBase2(ModelBase):
cdef int _get_directional_derivative(self, N.ndarray v_ref, N.ndarray z_ref, N.ndarray dv, N.ndarray dz) except -1
cpdef set_real(self, valueref, values)
cpdef N.ndarray get_real(self, valueref)
cdef int __set_real(self, FMIL.fmi2_value_reference_t* vrefs, FMIL.fmi2_real_t* values, size_t size)
cdef int __get_real(self, FMIL.fmi2_value_reference_t* vrefs, size_t size, FMIL.fmi2_real_t* values)
cdef int _get_real(self, FMIL.fmi2_value_reference_t[:] valueref, size_t size, FMIL.fmi2_real_t[:] values)
cdef int _set_real(self, FMIL.fmi2_value_reference_t* vrefs, FMIL.fmi2_real_t* values, size_t size)
cdef int _get_real_by_ptr(self, FMIL.fmi2_value_reference_t* vrefs, size_t size, FMIL.fmi2_real_t* values)
cdef int _get_real_by_list(self, FMIL.fmi2_value_reference_t[:] valueref, size_t size, FMIL.fmi2_real_t[:] values)
cdef int _get_integer(self, FMIL.fmi2_value_reference_t[:] valueref, size_t size, FMIL.fmi2_integer_t[:] values)
cdef int _get_boolean(self, FMIL.fmi2_value_reference_t[:] valueref, size_t size, FMIL.fmi2_real_t[:] values)

Expand All @@ -255,11 +256,11 @@ cdef class FMUModelME2(FMUModelBase2):
cpdef get_derivatives(self)
cdef public object force_finite_differences
cdef int _get_derivatives(self, FMIL.fmi2_real_t[:] values)
cdef int __get_continuous_states(self, FMIL.fmi2_real_t[:] ndx)
cdef int __set_continuous_states(self, FMIL.fmi2_real_t[:] ndx)
cdef int _get_continuous_states_fmil(self, FMIL.fmi2_real_t[:] ndx)
cdef int _set_continuous_states_fmil(self, FMIL.fmi2_real_t[:] ndx)
cdef int _get_event_indicators(self, FMIL.fmi2_real_t[:] values)
cdef int _completed_integrator_step(self, int* enter_event_mode, int* terminate_simulation)
cdef int __get_nominal_continuous_states(self, FMIL.fmi2_real_t* xnominal, size_t nx)
cdef int _get_nominal_continuous_states_fmil(self, FMIL.fmi2_real_t* xnominal, size_t nx)
cdef public object _preinit_nominal_continuous_states

cdef class WorkerClass2:
Expand All @@ -274,5 +275,11 @@ cdef class WorkerClass2:
cdef N.ndarray get_real_numpy_vector(self, int index)
cpdef verify_dimensions(self, int dim)

cdef class __ForTestingFMUModelME2(FMUModelME2):
cdef class _ForTestingFMUModelME2(FMUModelME2):
cdef int _get_real_by_ptr(self, FMIL.fmi2_value_reference_t* vrefs, size_t size, FMIL.fmi2_real_t* values)
cdef int _set_real(self, FMIL.fmi2_value_reference_t* vrefs, FMIL.fmi2_real_t* values, size_t size)
cdef int _get_real_by_list(self, FMIL.fmi2_value_reference_t[:] valueref, size_t size, FMIL.fmi2_real_t[:] values)
cdef int _get_integer(self, FMIL.fmi2_value_reference_t[:] valueref, size_t size, FMIL.fmi2_integer_t[:] values)
cdef int _get_boolean(self, FMIL.fmi2_value_reference_t[:] valueref, size_t size, FMIL.fmi2_real_t[:] values)
cdef int _get_nominal_continuous_states_fmil(self, FMIL.fmi2_real_t* xnominal, size_t nx)
cpdef set_initialized_fmu(self, int value)
Loading

0 comments on commit d4cc5ab

Please sign in to comment.