Skip to content

Commit 001cf29

Browse files
authored
Merge branch 'SimVascular:master' into CRLVessel
2 parents a30d2dd + 74f2d4c commit 001cf29

26 files changed

+500
-132
lines changed

.github/workflows/test.yml

Lines changed: 45 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -7,85 +7,39 @@ jobs:
77
runs-on: ${{ matrix.os }}
88
strategy:
99
matrix:
10-
os: [ubuntu-22.04, ubuntu-latest, macos-13, macos-latest, windows-latest]
11-
version: [13] # GCC version
10+
os: [ubuntu-latest, macos-latest, windows-latest]
1211
fail-fast: false
1312
env:
14-
GCC_V: ${{ matrix.version }}
15-
CONDA_ENV: zerod
1613
PYTHONPATH: ${{ github.workspace }}
1714
steps:
1815
- uses: actions/checkout@v4
19-
- uses: conda-incubator/setup-miniconda@v3
16+
- uses: actions/setup-python@v5
2017
with:
21-
auto-update-conda: true
22-
activate-environment: ${{env.CONDA_ENV}}
2318
python-version: "3.11.4"
24-
- name: Install ubuntu dependencies
25-
if: startsWith(matrix.os, 'ubuntu')
26-
run: sudo apt update && sudo apt install build-essential cmake lcov
2719

28-
- name: Install dependencies to get correct version numbers (Ubuntu)
20+
- name: Install ubuntu dependencies
2921
if: startsWith(matrix.os, 'ubuntu')
30-
run: conda install -c conda-forge libstdcxx-ng=${GCC_V} gcc=${GCC_V}
31-
32-
- name: Install dependencies to get correct version numbers (MacOS)
33-
if: startsWith(matrix.os, 'macos')
34-
run: |
35-
brew install gcc@${GCC_V}
36-
ln -s /usr/local/bin/gcc-${GCC_V} /usr/local/bin/gcc
37-
38-
- name: Install dependencies for windows
39-
if: startsWith(matrix.os, 'windows')
40-
shell: pwsh
41-
run: |
42-
choco install mingw --no-progress
43-
conda install -y -c conda-forge cmake graphviz python-graphviz pydot
44-
pip install --upgrade cmake-setuptools
22+
run: sudo apt update && sudo apt install build-essential cmake lcov graphviz
4523

46-
- name: Install POISX-like svZeroDSolver
24+
- name: Install POSIX-like
4725
if: ${{!startsWith(matrix.os, 'windows')}}
48-
run: conda run pip install -e ".[dev]"
49-
50-
- name: Install Windows svZeroDSolver
51-
if: startsWith(matrix.os, 'windows')
52-
shell: pwsh
53-
run: |
54-
$Env:CMAKE_GENERATOR = 'MinGW Makefiles'
55-
Write-Host "→ Using CMAKE_GENERATOR = $Env:CMAKE_GENERATOR"
56-
pip install --no-build-isolation -v .[dev]
57-
pip show pysvzerod
58-
59-
- name: Install Networkx
60-
run: |
61-
conda run pip install networkx
26+
run: python -m pip install -e ".[dev]"
6227

6328
- name: Test the build
29+
if: ${{!startsWith(matrix.os, 'windows')}}
6430
run: |
6531
cd tests
66-
conda run pytest -v --durations=0 --ignore=test_dirgraph.py
32+
python -m pytest -v --durations=0 --ignore=test_dirgraph.py
6733
68-
- name: Build using CMake for POISX-like Systems
34+
- name: Build using CMake for POSIX-like Systems
6935
if: ${{!startsWith(matrix.os, 'windows')}}
7036
run: |
7137
mkdir Release
7238
cd Release
7339
cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_DISTRIBUTION=ON ..
7440
make -j2
7541
76-
- name: Build using CMake for Windows Systems
77-
if: startsWith(matrix.os, 'windows')
78-
shell: pwsh
79-
run: |
80-
mkdir Release
81-
cd Release
82-
cmake -G "MinGW Makefiles" `
83-
-DCMAKE_BUILD_TYPE=Release `
84-
-DENABLE_DISTRIBUTION=ON `
85-
..
86-
cmake --build . --parallel 2
87-
88-
- name: Test interface POISX-like Systems
42+
- name: Test interface POSIX-like Systems
8943
if: ${{!startsWith(matrix.os, 'windows')}}
9044
run: |
9145
cd tests/test_interface
@@ -98,67 +52,73 @@ jobs:
9852
cd ../test_02
9953
./svZeroD_interface_test02 ../../../../Release ../../test_02/svzerod_tuned.json
10054
101-
- name: Test interface Windows Systems
102-
if: startsWith(matrix.os, 'windows')
103-
shell: pwsh
104-
run: |
105-
cd tests/test_interface
106-
mkdir build_tests
107-
cd build_tests
108-
cmake -G "MinGW Makefiles" ..
109-
cmake --build . --parallel 2
110-
cd test_01
111-
./svZeroD_interface_test01.exe `
112-
../../../../Release `
113-
../../test_01/svzerod_3Dcoupling.json
114-
115-
cd ../test_02
116-
./svZeroD_interface_test02 `
117-
../../../../Release `
118-
../../test_02/svzerod_tuned.json
119-
12055
- name: Generate code coverage
121-
if: startsWith(matrix.os, 'ubuntu-22.04')
56+
if: startsWith(matrix.os, 'ubuntu-latest')
12257
run: |
12358
cd Release
12459
cmake -DENABLE_COVERAGE=ON ..
12560
make -j2
12661
cd ../tests
127-
conda run pytest -v --durations=0 --coverage --ignore=test_dirgraph.py
62+
python -m pytest -v --durations=0 --coverage --ignore=test_dirgraph.py
12863
cd ../Release
12964
make coverage
13065
13166
- name: Save coverage report
132-
if: startsWith(matrix.os, 'ubuntu-22.04')
67+
if: startsWith(matrix.os, 'ubuntu-latest')
13368
uses: actions/upload-artifact@v4
13469
with:
13570
name: coverage_report
13671
path: Release/coverage
13772

13873
- name: Upload coverage reports to Codecov
139-
if: startsWith(matrix.os, 'ubuntu-22.04')
74+
if: startsWith(matrix.os, 'ubuntu-latest')
14075
uses: codecov/codecov-action@v4
14176
env:
14277
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
14378

144-
- name: Build installer POISX-like Systems
79+
- name: Build installer POSIX-like Systems
14580
if: ${{!startsWith(matrix.os, 'windows')}}
14681
run: |
14782
cd Release
14883
cpack
14984
cp distribution/svZeroDSolver_* ..
15085
151-
- name: Install NSIS
86+
- name: Setup MSVC dev cmd
15287
if: startsWith(matrix.os, 'windows')
153-
run: choco install nsis -y
88+
uses: ilammy/msvc-dev-cmd@v1
15489

155-
- name: Build installer Windows Systems
90+
- name: Install and test Windows
15691
if: startsWith(matrix.os, 'windows')
92+
continue-on-error: true
15793
shell: pwsh
15894
run: |
159-
# NSIS will be at C:\Program Files (x86)\NSIS\Bin
95+
python -m pip install --upgrade cmake cmake-setuptools numpy ninja pytest pandas graphviz networkx pydot
96+
97+
# keep MinGW/Strawberry off PATH (so Eigen won't try Fortran)
98+
$pattern = '^(C:\\mingw64\\bin|C:\\tools\\mingw64\\bin|C:\\Strawberry\\c\\bin|C:\\Strawberry\\perl\\site\\bin|C:\\Strawberry\\perl\\bin)$'
99+
100+
# one build dir for everything: executables + Python module
101+
$build = Join-Path $env:GITHUB_WORKSPACE 'Release'
102+
cmake -S . -B $build -G Ninja `
103+
-DCMAKE_BUILD_TYPE=Release `
104+
-DEIGEN_BUILD_BLAS=OFF `
105+
-DEIGEN_BUILD_DOC=OFF -DEIGEN_TEST_FORTRAN=OFF -DEIGEN_TEST_CXX11=OFF -DEIGEN_TEST_NOQT=ON `
106+
-DCMAKE_Fortran_COMPILER:FILEPATH="" `
107+
-DENABLE_DISTRIBUTION=ON
108+
cmake --build $build --parallel 2
109+
110+
# make the Python extension importable
111+
$pydDir = Join-Path $build 'python'
112+
$env:PYTHONPATH = "$pydDir;$env:PYTHONPATH"
113+
114+
# run integration tests
115+
cd (Join-Path $env:GITHUB_WORKSPACE 'tests')
116+
python -m pytest -v --durations=0 --ignore=test_dirgraph.py
117+
118+
# build installer
119+
choco install nsis -y
160120
echo "C:\Program Files (x86)\NSIS\Bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
161-
cd Release
121+
cd $build
162122
cpack -C Release
163123
Copy-Item distribution\svZeroDSolver_* -Destination ..\
164124

CMakeLists.txt

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,27 @@
11
# SPDX-FileCopyrightText: Copyright (c) Stanford University, The Regents of the University of California, and others.
22
# SPDX-License-Identifier: BSD-3-Clause
33

4-
set(CMAKE_POLICY_VERSION_MINIMUM 3.5)
5-
cmake_minimum_required(VERSION 3.5)
4+
set(CMAKE_POLICY_VERSION_MINIMUM 3.18)
5+
cmake_minimum_required(VERSION 3.18)
6+
cmake_policy(SET CMP0077 NEW)
7+
68
set(CMAKE_CXX_STANDARD 17)
79
set(CMAKE_CXX_STANDARD_REQUIRED True)
810

9-
project(svZeroDSolver)
11+
project(svZeroDSolver LANGUAGES C CXX)
12+
13+
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
14+
15+
# Force Eigen & superprojects to skip docs/tests/fortran no matter what
16+
set(BUILD_TESTING OFF CACHE BOOL "" FORCE)
17+
set(EIGEN_BUILD_DOC OFF CACHE BOOL "" FORCE)
18+
set(EIGEN_TEST_FORTRAN OFF CACHE BOOL "" FORCE)
19+
set(EIGEN_BUILD_BLAS OFF CACHE BOOL "" FORCE)
1020

1121
include(FetchContent)
22+
set(PYBIND11_FINDPYTHON NEW CACHE STRING "" FORCE)
23+
find_package(Python COMPONENTS Interpreter Development REQUIRED)
24+
message(STATUS "Using Python: ${Python_EXECUTABLE} (${Python_VERSION})")
1225

1326
# Enable code coverage
1427
# -----------------------------------------------------------------------------
@@ -33,18 +46,13 @@ endif()
3346

3447
if (WIN32 AND MSVC)
3548
# CMake ≥ 3.15 has a proper variable
49+
# Use dynamic CRT (/MD or /MDd) so EXE and DLL share the same heap.
50+
# This is required when passing STL containers across DLL boundaries.
3651
if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.15")
3752
set(CMAKE_MSVC_RUNTIME_LIBRARY
38-
"MultiThreaded$<$<CONFIG:Debug>:Debug>")
53+
"MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
3954
else()
40-
# CMake < 3.15: manually swap /MD → /MT in all flags for static
41-
# versions of the runtime libraries
42-
foreach(_var
43-
CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
44-
CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
45-
CMAKE_SHARED_LINKER_FLAGS)
46-
string(REPLACE "/MD" "/MT" ${_var} "${${_var}}")
47-
endforeach()
55+
# CMake < 3.15: /MD is the default, so no changes needed
4856
endif()
4957
endif()
5058
# -----------------------------------------------------------------------------
@@ -75,7 +83,6 @@ FetchContent_Declare(
7583
set(EIGEN_BUILD_DOC OFF)
7684
set(BUILD_TESTING OFF)
7785
set(EIGEN_BUILD_PKGCONFIG OFF)
78-
set( OFF)
7986

8087
FetchContent_MakeAvailable(Eigen)
8188

@@ -84,7 +91,6 @@ FetchContent_MakeAvailable(Eigen)
8491
# -----------------------------------------------------------------------------
8592
# pybind11 is a library used to create Python bindings of existing C++ code.
8693
#
87-
set(PYBIND11_PYTHON_VERSION 3.8 CACHE STRING "")
8894
FetchContent_Declare(
8995
pybind11
9096
GIT_REPOSITORY https://github.com/pybind/pybind11

applications/svZeroDVisualization/visualize_simulation.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -388,9 +388,11 @@ def normalize_names(name):
388388
figure={
389389
'data': [edge_trace, vessel_trace, chamber_trace, valve_trace, junction_trace, bc_trace],
390390
'layout': go.Layout(
391-
title='Network Graph',
392-
titlefont_size=30,
393-
title_x=0.5,
391+
title={
392+
'text': 'Network Graph',
393+
'x': 0.5,
394+
'font': {'size': 30}
395+
},
394396
showlegend=True,
395397
hovermode='closest',
396398
margin=dict(b=20, l=0, r=0, t=50),
@@ -469,9 +471,11 @@ def update_graphs(clickData):
469471
fig = go.Figure(
470472
data=[edge_trace, vessel_trace, chamber_trace, valve_trace, junction_trace, bc_trace],
471473
layout=go.Layout(
472-
title='Network Graph',
473-
titlefont_size=30,
474-
title_x=0.5,
474+
title={
475+
'text': 'Network Graph',
476+
'x': 0.5,
477+
'font': {'size': 30}
478+
},
475479
showlegend=True,
476480
hovermode='closest',
477481
margin=dict(b=20, l=0, r=0, t=50),
@@ -651,4 +655,4 @@ def update_graphs(clickData):
651655

652656

653657
if __name__ == '__main__':
654-
app.run_server(debug=True)
658+
app.run(debug=True)

docs/pages/developer_guide.md

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,20 @@ This is useful when continuously running the integration tests during developmen
4646

4747
* The changes should be implemented in a feature branch of the developer's fork of svZeroDSolver.
4848
* Once the changes are implemented, the developer should make sure the build, documentation, and code format tests are passing on the user's feature branch.
49-
* The tests are automatically run when pushing changes to the developer's remote branch on Github.
50-
* Alternatively, the developer can run the tests locally.
51-
* The build tests can be run using the `pip` install and `pytest`.
52-
* The tests for the C++ interface require the `CMake` install and can be run by building the tests in `svZeroDSolver/tests/test_interface`.
53-
* Code formatting can be performed following the instructions in the Formatting section below.
54-
* The documentation can be built following the instructions in the Documentation section below.
49+
50+
# Testing code changes
51+
* Tests are automatically run as Github workflows when pushing changes to the developer's remote branch on Github. These tests are defined in the `.github/workflows` directory.
52+
* It may be helpful and more efficient to run the build tests locally with each incremental change the developer makes. This can be done by following these steps:
53+
1. If you do not have `pytest` installed in your virtual environment, install it with `pip install pytest`
54+
2. We first need to build the svZeroDSolver project. This can be done by running `pip install -e .` from the svZeroDSolver directory
55+
3. From the main svZeroDSolver directory, `cd tests`.
56+
4. Now that you are in the `tests` directory, run `pytest`. The terminal output will show which tests are passing.
57+
* To run a specific subset of tests matching a certain pattern, e.g., only the calibrator, you can use `pytest -k calibrator`.
58+
* To see all simulation output, run `pytest -sv`.
59+
* If you want to run the tests using the binaries in the `Release` directory instead of the python module, you can call `pytest --coverage`
60+
* The tests for the C++ interface require the `CMake` install and can be run by building the tests in `svZeroDSolver/tests/test_interface`.
61+
* Code formatting can be performed following the instructions in the [Formatting](#formatting) section.
62+
* The documentation can be built following the instructions in the [Documentation](#documentation) section.
5563
* Once all the tests are passing, the developer should open a pull request from the feature branch and link the relevant issue.
5664

5765
# Adding new blocks
@@ -66,7 +74,7 @@ Steps required to visualize a new block with svZeroDSolver Visualization applica
6674

6775
We follow the [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html).
6876

69-
## Formatting
77+
## Formatting {#formatting}
7078

7179
We use [clang-format](https://clang.llvm.org/docs/ClangFormat.html) to automatically
7280
format our code accoring to the [Google Style](https://google.github.io/styleguide/cppguide.html),
@@ -78,7 +86,11 @@ There are tools for your favorite IDE to automatically format your code. Example
7886
- [vim](https://github.com/rhysd/vim-clang-format)
7987
- [and many more](https://clang.llvm.org/docs/ClangFormat.html)
8088

81-
Before committing any changes, you can run the following
89+
Before formatting the code with clang-format, ensure that you have latest clang-format version by running `clang-format --version`. To upgrade `clang-format` use the following commands
90+
* on MacOS: `brew upgrade clang-format`
91+
* on Ubuntu: `sudo apt upgrade clang-format`
92+
93+
Before committing any changes, run the following
8294
command **from your build folder** to format all your files:
8395

8496
```bash
@@ -105,7 +117,7 @@ requirements.
105117

106118
On Sherlock at Stanford, clang-format is included in the `llvm` module.
107119

108-
# Documentation
120+
# Documentation {#documentation}
109121

110122
We use [Doxygen](https://doxygen.nl) to automatically build an html documentation
111123
from source code. Please have at Doxygen's [Documentation Guide](https://www.doxygen.nl/manual/docblocks.html)

setup.cfg

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ install_requires =
1515
[options.extras_require]
1616
dev =
1717
pytest
18+
graphviz
19+
networkx
20+
pydot
1821

1922
[options.entry_points]
2023
console_scripts =

src/algebra/Integrator.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@ State Integrator::step(const State& old_state, double time) {
8383
// Abort if maximum number of non-linear iterations is reached
8484
else if (i == max_iter - 1) {
8585
throw std::runtime_error(
86-
"Maximum number of non-linear iterations reached.");
86+
"Maximum number of non-linear iterations reached at time " +
87+
std::to_string(time));
8788
}
8889

8990
// Evaluate Jacobian

0 commit comments

Comments
 (0)