Skip to content

Commit 25dc1de

Browse files
authored
libcosimpy update - Ecco algorithm, conan update, type checking etc. (#15)
Update to libcosimpy for supporting ecco algorithm. - Using the latest libcosim/libcosimc - Ecco API - Using conan v2 - Added type checking
1 parent 9f90e17 commit 25dc1de

38 files changed

+2216
-954
lines changed

.github/workflows/ci-main.yml

Lines changed: 40 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,36 +4,37 @@ name: libcosimpy CI
44
on: [push, workflow_dispatch]
55

66
jobs:
7-
test:
8-
name: Tests
9-
runs-on: ${{ matrix.platform }}
10-
strategy:
11-
fail-fast: false
12-
matrix:
13-
platform: [ 'windows-latest', 'ubuntu-latest' ]
14-
python-version: [ '3.8', '3.9', '3.10', '3.11', '3.12' ]
7+
code_quality:
8+
name: Code Quality
9+
runs-on: 'ubuntu-latest'
1510
timeout-minutes: 35
1611
steps:
1712
- uses: actions/checkout@v3
18-
- uses: actions/setup-python@v4
13+
- uses: actions/setup-python@v5
1914
with:
20-
python-version: ${{ matrix.python-version }}
21-
- name: 'Run test'
22-
run: |
23-
pip install .
24-
pip install pytest==7.2.2
25-
pytest .
15+
python-version-file: 'pyproject.toml'
16+
- name: Install uv
17+
uses: astral-sh/setup-uv@v6
18+
with:
19+
enable-cache: true
20+
cache-dependency-glob: "uv.lock"
21+
- name: Install dependencies
22+
run: uv sync --no-install-project
23+
- name: Run ruff format
24+
run: uv run --no-project ruff format --diff
25+
- name: Run ruff check
26+
run: uv run --no-project ruff check --diff
27+
- name: Run pyright
28+
run: uv run --no-project pyright
2629

27-
build_wheels:
28-
name: Build wheels
29-
needs:
30-
- test
30+
build_wheels_and_test:
31+
name: Build / Test
3132
runs-on: ${{ matrix.platform }}
3233
strategy:
3334
fail-fast: false
3435
matrix:
3536
platform: [ 'windows-latest', 'ubuntu-latest' ]
36-
python-version: [ 'cp38', 'cp39', 'cp310', 'cp311', 'cp312' ]
37+
python-version: [ 'cp310', 'cp311', 'cp312', 'cp313' ]
3738
timeout-minutes: 35
3839
env:
3940
CONAN_REVISIONS_ENABLED: 1
@@ -42,10 +43,20 @@ jobs:
4243
- uses: actions/setup-python@v5
4344
with:
4445
python-version: 3.11
46+
- name: Install uv
47+
uses: astral-sh/setup-uv@v6
48+
with:
49+
enable-cache: true
50+
cache-dependency-glob: "uv.lock"
4551
- name: Build wheels
46-
uses: pypa/cibuildwheel@v2.19.2
52+
uses: pypa/cibuildwheel@v2.23.3
4753
env:
4854
CIBW_BUILD: "${{ matrix.python-version }}-win_amd64 ${{ matrix.python-version }}-manylinux_x86_64"
55+
CIBW_BUILD_FRONTEND: build[uv]
56+
CIBW_ENVIRONMENT: >
57+
CONAN_UPLOAD_OSP=1
58+
CONAN_LOGIN_USERNAME_OSP=${{ secrets.osp_artifactory_usr }}
59+
CONAN_PASSWORD_OSP=${{ secrets.osp_artifactory_pwd }}
4960
- name: Twine check
5061
run: |
5162
pip install twine
@@ -58,14 +69,15 @@ jobs:
5869
path: ./wheelhouse/*.whl
5970

6071
build_source:
61-
name: Build source
62-
needs:
63-
- test
72+
name: Package source
6473
runs-on: 'ubuntu-latest'
6574
steps:
6675
- uses: actions/checkout@v3
76+
- uses: actions/setup-python@v5
77+
with:
78+
python-version: 3.11
6779
- name: Build source
68-
run: |
80+
run: |
6981
pip install build twine
7082
python -m build --sdist
7183
twine check --strict ./dist/*
@@ -79,7 +91,8 @@ jobs:
7991
publish:
8092
if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags/v')
8193
needs:
82-
- build_wheels
94+
- code_quality
95+
- build_wheels_and_test
8396
- build_source
8497
runs-on: ubuntu-latest
8598
steps:
@@ -88,7 +101,7 @@ jobs:
88101
pattern: "*-wheel"
89102
merge-multiple: true
90103
path: ./dist/
91-
- uses: pypa/gh-action-pypi-publish@v1.9.0
104+
- uses: pypa/gh-action-pypi-publish@release/v1
92105
with:
93106
user: __token__
94107
password: ${{ secrets.PYPI_API_TOKEN }}

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,4 +285,8 @@ poetry.toml
285285
# LSP config files
286286
pyrightconfig.json
287287

288+
# Custom
289+
/wheelhouse
290+
/graph.json
291+
288292
# End of https://www.toptal.com/developers/gitignore/api/pycharm,python

README.md

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,110 @@ execution.step()
149149

150150
Scenario manipulators are also supported
151151

152+
# Using ECCO algorithm
153+
154+
Libcosimpy supports ECCO (Energy-Conservation-based Co-Simulation) algorithm based on the work in [1] for adaptively
155+
updating the step size of the simulation. The algorithm uses the law of conservation of energy between FMU models that
156+
represent power bonds from bond graph theory.
157+
158+
## Creating ECCO algorithm manually
159+
The parameters of the algorithm can be specified via the `EccoParam` class:
160+
161+
```python
162+
params = EccoParams(
163+
safety_factor=0.8,
164+
step_size=1e-4,
165+
min_step_size=1e-4,
166+
max_step_size=0.01,
167+
min_change_rate=0.2,
168+
max_change_rate=1.5,
169+
abs_tolerance=1e-4,
170+
rel_tolerance=1e-4,
171+
p_gain=0.2,
172+
i_gain=0.15,
173+
)
174+
```
175+
176+
The algorithm be created via `create_ecco_algorithm`, which can be used to create a new execution instance:
177+
178+
```python
179+
# Create an algorithm instance
180+
ecco_algorithm = CosimAlgorithm.create_ecco_algorithm(params)
181+
182+
# Create execution
183+
execution = CosimExecution.from_algorithm(ecco_algorithm)
184+
```
185+
186+
The power bond between models is represented by input and output connection pair between two models:
187+
188+
```python
189+
# Indicating a power bond between models (indicated by index chassis_index and wheel_index)
190+
ecco_algorithm.add_power_bond(
191+
chassis_index,
192+
chassis_v_out,
193+
chassis_f_in,
194+
wheel_index,
195+
wheel_f_out,
196+
wheel_v_in,
197+
)
198+
```
199+
200+
The simulation is started as usual via `simulate_until` function from `CosimExecution`:
201+
```python
202+
execution.simulate_until(target_time=10e9)
203+
```
204+
205+
See [test_ecco_algorithm](tests/test_ecco_algorithm.py) for detailed usage of ECCO algorithm.
206+
207+
## Creating ECCO algorithm via system structure file
208+
209+
Alternatively, ECCO algorithm can also be created via system structure file:
210+
```xml
211+
<OspSystemStructure xmlns="http://opensimulationplatform.com/MSMI/OSPSystemStructure" version="0.1">
212+
...
213+
<!-- Specify ecco algorithm -->
214+
<Algorithm>ecco</Algorithm>
215+
...
216+
<Connections>
217+
<!-- Annotate variable connection as power bond via `powerBond` attribute. Specify
218+
causality of the variable (input or output) -->
219+
<VariableConnection powerBond="wheelchassis">
220+
<Variable simulator="chassis" name="velocity" causality="output"/>
221+
<Variable simulator="wheel" name="in_vel" causality="input"/>
222+
</VariableConnection>
223+
<VariableConnection powerBond="wheelchassis">
224+
<Variable simulator="wheel" name="out_spring_damper_f" causality="output"/>
225+
<Variable simulator="chassis" name="force" causality="input"/>
226+
</VariableConnection>
227+
</Connections>
228+
<!-- Specify ecco algorithm parameters -->
229+
<EccoConfiguration>
230+
<SafetyFactor>0.99</SafetyFactor>
231+
<StepSize>0.0001</StepSize>
232+
<MinimumStepSize>0.00001</MinimumStepSize>
233+
<MaximumStepSize>0.01</MaximumStepSize>
234+
<MinimumChangeRate>0.2</MinimumChangeRate>
235+
<MaximumChangeRate>1.5</MaximumChangeRate>
236+
<ProportionalGain>0.2</ProportionalGain>
237+
<IntegralGain>0.15</IntegralGain>
238+
<RelativeTolerance>1e-6</RelativeTolerance>
239+
<AbsoluteTolerance>1e-6</AbsoluteTolerance>
240+
</EccoConfiguration>
241+
</OspSystemStructure>
242+
```
243+
244+
Then this file can be loaded via a usual way via `CosimExecution.from_osp_config_file`:
245+
```python
246+
execution = CosimExecution.from_osp_config_file(osp_path="tests/data/fmi2/quarter_truck")
247+
```
248+
249+
See [Quarter truck example](tests/data/fmi2/quarter_truck/OspSystemStructure.xml) for detailed usage of ECCO algorithm via system structure file.
250+
251+
252+
## Reference
253+
[1] Sadjina, S. and Pedersen, E., 2020. Energy conservation and coupling error reduction in non-iterative co-simulations. Engineering with Computers, 36, pp.1579-1587.
254+
255+
152256
# Tests
153257

154258
Tests can be run using the `pytest` command in the terminal. `libcosimc` log level for all tests can be set in the `./tests/conftest.py` file.

0 commit comments

Comments
 (0)