parosol-py 0.1.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- parosol_py-0.1.3/.github/workflows/build-wheels.yml +152 -0
- parosol_py-0.1.3/.github/workflows/publish-from-run.yml +65 -0
- parosol_py-0.1.3/.github/workflows/tests.yml +104 -0
- parosol_py-0.1.3/.gitignore +12 -0
- parosol_py-0.1.3/CMakeLists.txt +7 -0
- parosol_py-0.1.3/PKG-INFO +153 -0
- parosol_py-0.1.3/README.md +126 -0
- parosol_py-0.1.3/pyproject.toml +71 -0
- parosol_py-0.1.3/scripts/benchmark_torch_backend.py +136 -0
- parosol_py-0.1.3/scripts/install_prebuilt.py +102 -0
- parosol_py-0.1.3/scripts/local_check.py +154 -0
- parosol_py-0.1.3/src/parosol_native/CMakeLists.txt +35 -0
- parosol_py-0.1.3/src/parosol_native/LICENSE +15 -0
- parosol_py-0.1.3/src/parosol_native/src/AsciiImage.cpp +177 -0
- parosol_py-0.1.3/src/parosol_native/src/AsciiImage.h +90 -0
- parosol_py-0.1.3/src/parosol_native/src/AsciiImageMirrored.cpp +178 -0
- parosol_py-0.1.3/src/parosol_native/src/AsciiImageMirrored.h +73 -0
- parosol_py-0.1.3/src/parosol_native/src/BaseGrid.h +96 -0
- parosol_py-0.1.3/src/parosol_native/src/BoundaryCondition.h +95 -0
- parosol_py-0.1.3/src/parosol_native/src/CPULayout.h +144 -0
- parosol_py-0.1.3/src/parosol_native/src/Chebyshev.cpp +98 -0
- parosol_py-0.1.3/src/parosol_native/src/Chebyshev.h +88 -0
- parosol_py-0.1.3/src/parosol_native/src/Config.h +82 -0
- parosol_py-0.1.3/src/parosol_native/src/Doxyfile +1512 -0
- parosol_py-0.1.3/src/parosol_native/src/GReader.cpp +498 -0
- parosol_py-0.1.3/src/parosol_native/src/GReader.hpp +1595 -0
- parosol_py-0.1.3/src/parosol_native/src/GWriter.cpp +460 -0
- parosol_py-0.1.3/src/parosol_native/src/GWriter.hpp +1158 -0
- parosol_py-0.1.3/src/parosol_native/src/GenericMatrix.h +394 -0
- parosol_py-0.1.3/src/parosol_native/src/HDF5Image.cpp +232 -0
- parosol_py-0.1.3/src/parosol_native/src/HDF5Image.h +74 -0
- parosol_py-0.1.3/src/parosol_native/src/HDF5ParfePrinter.h +206 -0
- parosol_py-0.1.3/src/parosol_native/src/HDF5Printer.h +231 -0
- parosol_py-0.1.3/src/parosol_native/src/ImageReader.h +73 -0
- parosol_py-0.1.3/src/parosol_native/src/Jacobi.h +56 -0
- parosol_py-0.1.3/src/parosol_native/src/JacobiSmoother.cpp +36 -0
- parosol_py-0.1.3/src/parosol_native/src/JacobiSmoother.h +92 -0
- parosol_py-0.1.3/src/parosol_native/src/KeyGenerator.h +111 -0
- parosol_py-0.1.3/src/parosol_native/src/MlCycle.h +238 -0
- parosol_py-0.1.3/src/parosol_native/src/MlLevelCG.h +53 -0
- parosol_py-0.1.3/src/parosol_native/src/MlLevelCheb.h +58 -0
- parosol_py-0.1.3/src/parosol_native/src/MlOctreeGrid.h +462 -0
- parosol_py-0.1.3/src/parosol_native/src/OctreeGrid.h +1670 -0
- parosol_py-0.1.3/src/parosol_native/src/OctreeNode.h +62 -0
- parosol_py-0.1.3/src/parosol_native/src/OptLocalMatrix.h +188 -0
- parosol_py-0.1.3/src/parosol_native/src/PCGSolver.cpp +172 -0
- parosol_py-0.1.3/src/parosol_native/src/PCGSolver.h +79 -0
- parosol_py-0.1.3/src/parosol_native/src/Postprocessing.h +182 -0
- parosol_py-0.1.3/src/parosol_native/src/Problem.h +262 -0
- parosol_py-0.1.3/src/parosol_native/src/Solver.h +55 -0
- parosol_py-0.1.3/src/parosol_native/src/StiffnessMatrix.h +86 -0
- parosol_py-0.1.3/src/parosol_native/src/Testtools.h +196 -0
- parosol_py-0.1.3/src/parosol_native/src/Timing.h +145 -0
- parosol_py-0.1.3/src/parosol_native/src/Toolbox.cpp +59 -0
- parosol_py-0.1.3/src/parosol_native/src/Toolbox.h +28 -0
- parosol_py-0.1.3/src/parosol_native/src/VTKPrinter.h +334 -0
- parosol_py-0.1.3/src/parosol_native/src/est_ev.cpp +87 -0
- parosol_py-0.1.3/src/parosol_native/src/est_ev.h +40 -0
- parosol_py-0.1.3/src/parosol_native/src/fem.cpp +723 -0
- parosol_py-0.1.3/src/parosol_native/src/fem.h +113 -0
- parosol_py-0.1.3/src/parosol_native/src/main.cpp +300 -0
- parosol_py-0.1.3/src/parosol_native/src/tri_eig.h +76 -0
- parosol_py-0.1.3/src/parosol_py/__init__.py +52 -0
- parosol_py-0.1.3/src/parosol_py/_version.py +1 -0
- parosol_py-0.1.3/src/parosol_py/api.py +354 -0
- parosol_py-0.1.3/src/parosol_py/batch.py +410 -0
- parosol_py-0.1.3/src/parosol_py/boundary_conditions.py +67 -0
- parosol_py-0.1.3/src/parosol_py/bundle.py +346 -0
- parosol_py-0.1.3/src/parosol_py/cli.py +646 -0
- parosol_py-0.1.3/src/parosol_py/config.py +1348 -0
- parosol_py-0.1.3/src/parosol_py/config_templates/default.yaml +239 -0
- parosol_py-0.1.3/src/parosol_py/config_templates/profiles/batch.yaml +10 -0
- parosol_py-0.1.3/src/parosol_py/config_templates/profiles/bending_z.yaml +13 -0
- parosol_py-0.1.3/src/parosol_py/config_templates/profiles/coarse_preview.yaml +8 -0
- parosol_py-0.1.3/src/parosol_py/config_templates/profiles/constrained_axial_z.yaml +14 -0
- parosol_py-0.1.3/src/parosol_py/config_templates/profiles/debug.yaml +9 -0
- parosol_py-0.1.3/src/parosol_py/config_templates/profiles/debug_sets.yaml +6 -0
- parosol_py-0.1.3/src/parosol_py/config_templates/profiles/density_power.yaml +14 -0
- parosol_py-0.1.3/src/parosol_py/config_templates/profiles/direct_mechanics_manifest.yaml +15 -0
- parosol_py-0.1.3/src/parosol_py/config_templates/profiles/load_history_3.yaml +29 -0
- parosol_py-0.1.3/src/parosol_py/config_templates/profiles/load_history_6.yaml +49 -0
- parosol_py-0.1.3/src/parosol_py/config_templates/profiles/progressive_loading_manifest.yaml +14 -0
- parosol_py-0.1.3/src/parosol_py/config_templates/profiles/proximal_femur.yaml +71 -0
- parosol_py-0.1.3/src/parosol_py/config_templates/profiles/proximal_femur_sideways_fall.yaml +81 -0
- parosol_py-0.1.3/src/parosol_py/config_templates/profiles/shear_zx.yaml +12 -0
- parosol_py-0.1.3/src/parosol_py/config_templates/profiles/shear_zy.yaml +12 -0
- parosol_py-0.1.3/src/parosol_py/config_templates/profiles/smart_bone_compression_z.yaml +17 -0
- parosol_py-0.1.3/src/parosol_py/config_templates/profiles/standard_fields.yaml +8 -0
- parosol_py-0.1.3/src/parosol_py/config_templates/profiles/standard_mechanics_fields.yaml +9 -0
- parosol_py-0.1.3/src/parosol_py/config_templates/profiles/torsion_z.yaml +12 -0
- parosol_py-0.1.3/src/parosol_py/config_templates/profiles/vertebra.yaml +93 -0
- parosol_py-0.1.3/src/parosol_py/config_templates/profiles/xtremecti.yaml +29 -0
- parosol_py-0.1.3/src/parosol_py/config_templates/profiles/xtremectii.yaml +29 -0
- parosol_py-0.1.3/src/parosol_py/config_templates.py +36 -0
- parosol_py-0.1.3/src/parosol_py/core.py +139 -0
- parosol_py-0.1.3/src/parosol_py/diagnostics.py +792 -0
- parosol_py-0.1.3/src/parosol_py/field_export.py +195 -0
- parosol_py-0.1.3/src/parosol_py/hdf5_io.py +143 -0
- parosol_py-0.1.3/src/parosol_py/images.py +149 -0
- parosol_py-0.1.3/src/parosol_py/licenses/parosol_native_LICENSE.txt +15 -0
- parosol_py-0.1.3/src/parosol_py/load_cases.py +407 -0
- parosol_py-0.1.3/src/parosol_py/load_history.py +287 -0
- parosol_py-0.1.3/src/parosol_py/materials.py +366 -0
- parosol_py-0.1.3/src/parosol_py/modeling/__init__.py +4 -0
- parosol_py-0.1.3/src/parosol_py/modeling/alignment.py +508 -0
- parosol_py-0.1.3/src/parosol_py/modeling/builder.py +47 -0
- parosol_py-0.1.3/src/parosol_py/modeling/common.py +754 -0
- parosol_py-0.1.3/src/parosol_py/modeling/femur.py +360 -0
- parosol_py-0.1.3/src/parosol_py/modeling/io.py +61 -0
- parosol_py-0.1.3/src/parosol_py/modeling/spine.py +308 -0
- parosol_py-0.1.3/src/parosol_py/modeling/types.py +23 -0
- parosol_py-0.1.3/src/parosol_py/nodesets.py +413 -0
- parosol_py-0.1.3/src/parosol_py/paths.py +24 -0
- parosol_py-0.1.3/src/parosol_py/profiles.py +51 -0
- parosol_py-0.1.3/src/parosol_py/reference_validation.py +102 -0
- parosol_py-0.1.3/src/parosol_py/reports.py +462 -0
- parosol_py-0.1.3/src/parosol_py/results.py +67 -0
- parosol_py-0.1.3/src/parosol_py/runner.py +168 -0
- parosol_py-0.1.3/src/parosol_py/set_export.py +117 -0
- parosol_py-0.1.3/src/parosol_py/surfaces.py +168 -0
- parosol_py-0.1.3/src/parosol_py/validation.py +49 -0
- parosol_py-0.1.3/src/parosol_py/visualization.py +849 -0
- parosol_py-0.1.3/src/parosol_py/workflow_template.py +188 -0
- parosol_py-0.1.3/src/parosol_torch/__init__.py +28 -0
- parosol_py-0.1.3/src/parosol_torch/backend.py +102 -0
- parosol_py-0.1.3/src/parosol_torch/contract.py +82 -0
- parosol_py-0.1.3/src/parosol_torch/elasticity.py +406 -0
- parosol_py-0.1.3/src/parosol_torch/prototype.py +28 -0
- parosol_py-0.1.3/src/parosol_torch/registry.py +51 -0
- parosol_py-0.1.3/tests/fixtures/reference/SAMPLE_HOM_LS.AIM +1 -0
- parosol_py-0.1.3/tests/fixtures/reference/SAMPLE_HOM_LS_analysis.txt +43 -0
- parosol_py-0.1.3/tests/fixtures/reference/SAMPLE_HOM_LS_pistoia.txt +14 -0
- parosol_py-0.1.3/tests/fixtures/trab1240/material_table.yaml +7 -0
- parosol_py-0.1.3/tests/fixtures/trab1240/reference.json +40 -0
- parosol_py-0.1.3/tests/fixtures/trab1240/reference_sed.npz +0 -0
- parosol_py-0.1.3/tests/fixtures/trab1240/trab1240_labels.npz +0 -0
- parosol_py-0.1.3/tests/test_api.py +405 -0
- parosol_py-0.1.3/tests/test_batch.py +515 -0
- parosol_py-0.1.3/tests/test_boundary_conditions.py +48 -0
- parosol_py-0.1.3/tests/test_bundle.py +105 -0
- parosol_py-0.1.3/tests/test_config_cli.py +2272 -0
- parosol_py-0.1.3/tests/test_config_templates.py +92 -0
- parosol_py-0.1.3/tests/test_core.py +51 -0
- parosol_py-0.1.3/tests/test_diagnostics.py +299 -0
- parosol_py-0.1.3/tests/test_field_export.py +58 -0
- parosol_py-0.1.3/tests/test_hdf5_io.py +167 -0
- parosol_py-0.1.3/tests/test_images.py +49 -0
- parosol_py-0.1.3/tests/test_load_cases.py +225 -0
- parosol_py-0.1.3/tests/test_load_history.py +72 -0
- parosol_py-0.1.3/tests/test_materials.py +187 -0
- parosol_py-0.1.3/tests/test_modeling.py +603 -0
- parosol_py-0.1.3/tests/test_nodesets.py +54 -0
- parosol_py-0.1.3/tests/test_packaging.py +88 -0
- parosol_py-0.1.3/tests/test_parosol_torch.py +163 -0
- parosol_py-0.1.3/tests/test_profiles.py +11 -0
- parosol_py-0.1.3/tests/test_reference_validation.py +49 -0
- parosol_py-0.1.3/tests/test_reports.py +121 -0
- parosol_py-0.1.3/tests/test_results.py +41 -0
- parosol_py-0.1.3/tests/test_runner.py +96 -0
- parosol_py-0.1.3/tests/test_set_export.py +44 -0
- parosol_py-0.1.3/tests/test_solver_smoke.py +31 -0
- parosol_py-0.1.3/tests/test_surfaces.py +42 -0
- parosol_py-0.1.3/tests/test_trab1240_reference.py +176 -0
- parosol_py-0.1.3/tests/test_validation.py +28 -0
- parosol_py-0.1.3/tests/test_visualization.py +98 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
name: Build Wheels
|
|
2
|
+
|
|
3
|
+
"on":
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
build_wheels:
|
|
11
|
+
runs-on: ${{ matrix.os }}
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
strategy:
|
|
15
|
+
fail-fast: false
|
|
16
|
+
matrix:
|
|
17
|
+
include:
|
|
18
|
+
- os: ubuntu-latest
|
|
19
|
+
artifact: manylinux-x86_64
|
|
20
|
+
cibw_arch: x86_64
|
|
21
|
+
- os: windows-latest
|
|
22
|
+
artifact: windows-amd64
|
|
23
|
+
cibw_arch: AMD64
|
|
24
|
+
- os: macos-latest
|
|
25
|
+
artifact: macos-arm64
|
|
26
|
+
cibw_arch: arm64
|
|
27
|
+
- os: macos-15-intel
|
|
28
|
+
artifact: macos-x86_64
|
|
29
|
+
cibw_arch: x86_64
|
|
30
|
+
|
|
31
|
+
steps:
|
|
32
|
+
- name: Checkout code
|
|
33
|
+
uses: actions/checkout@v4
|
|
34
|
+
with:
|
|
35
|
+
submodules: recursive
|
|
36
|
+
|
|
37
|
+
- name: Set up Python
|
|
38
|
+
uses: actions/setup-python@v5
|
|
39
|
+
with:
|
|
40
|
+
python-version: "3.12"
|
|
41
|
+
|
|
42
|
+
- name: Cache vcpkg artifacts (Windows)
|
|
43
|
+
if: matrix.os == 'windows-latest'
|
|
44
|
+
uses: actions/cache@v4
|
|
45
|
+
with:
|
|
46
|
+
path: |
|
|
47
|
+
C:\vcpkg\downloads
|
|
48
|
+
C:\vcpkg\buildtrees
|
|
49
|
+
C:\vcpkg\packages
|
|
50
|
+
C:\vcpkg\installed
|
|
51
|
+
C:\vcpkg\bincache
|
|
52
|
+
key: ${{ runner.os }}-vcpkg-parosol-v1-${{ hashFiles('pyproject.toml', '.github/workflows/build-wheels.yml') }}
|
|
53
|
+
restore-keys: |
|
|
54
|
+
${{ runner.os }}-vcpkg-parosol-v1-
|
|
55
|
+
|
|
56
|
+
- name: Install cibuildwheel
|
|
57
|
+
run: |
|
|
58
|
+
python -m pip install --upgrade pip cibuildwheel
|
|
59
|
+
|
|
60
|
+
- name: Build wheels (cibuildwheel)
|
|
61
|
+
env:
|
|
62
|
+
CIBW_ARCHS: ${{ matrix.cibw_arch }}
|
|
63
|
+
run: python -m cibuildwheel --output-dir dist
|
|
64
|
+
|
|
65
|
+
- name: Upload wheel artifacts
|
|
66
|
+
uses: actions/upload-artifact@v4
|
|
67
|
+
with:
|
|
68
|
+
name: wheels-${{ matrix.artifact }}
|
|
69
|
+
path: ./dist/*.whl
|
|
70
|
+
|
|
71
|
+
build_sdist:
|
|
72
|
+
runs-on: ubuntu-latest
|
|
73
|
+
permissions:
|
|
74
|
+
contents: read
|
|
75
|
+
steps:
|
|
76
|
+
- name: Checkout code
|
|
77
|
+
uses: actions/checkout@v4
|
|
78
|
+
with:
|
|
79
|
+
submodules: recursive
|
|
80
|
+
|
|
81
|
+
- name: Set up Python
|
|
82
|
+
uses: actions/setup-python@v5
|
|
83
|
+
with:
|
|
84
|
+
python-version: "3.12"
|
|
85
|
+
|
|
86
|
+
- name: Build sdist
|
|
87
|
+
run: |
|
|
88
|
+
python -m pip install --upgrade pip build
|
|
89
|
+
python -m build --sdist --outdir dist
|
|
90
|
+
|
|
91
|
+
- name: Upload sdist artifact
|
|
92
|
+
uses: actions/upload-artifact@v4
|
|
93
|
+
with:
|
|
94
|
+
name: sdist
|
|
95
|
+
path: ./dist/*.tar.gz
|
|
96
|
+
|
|
97
|
+
publish:
|
|
98
|
+
needs: [build_wheels, build_sdist]
|
|
99
|
+
runs-on: ubuntu-latest
|
|
100
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
101
|
+
permissions:
|
|
102
|
+
id-token: write
|
|
103
|
+
contents: write
|
|
104
|
+
environment:
|
|
105
|
+
name: pypi
|
|
106
|
+
url: https://pypi.org/p/parosol-py
|
|
107
|
+
steps:
|
|
108
|
+
- name: Download wheel artifacts
|
|
109
|
+
uses: actions/download-artifact@v4
|
|
110
|
+
with:
|
|
111
|
+
pattern: wheels-*
|
|
112
|
+
path: dist
|
|
113
|
+
merge-multiple: true
|
|
114
|
+
|
|
115
|
+
- name: Download sdist artifact
|
|
116
|
+
uses: actions/download-artifact@v4
|
|
117
|
+
with:
|
|
118
|
+
name: sdist
|
|
119
|
+
path: dist
|
|
120
|
+
|
|
121
|
+
- name: Set up Python for debug tooling
|
|
122
|
+
uses: actions/setup-python@v5
|
|
123
|
+
with:
|
|
124
|
+
python-version: "3.12"
|
|
125
|
+
|
|
126
|
+
- name: Debug artifact inventory
|
|
127
|
+
run: |
|
|
128
|
+
echo "Current dist/ contents:"
|
|
129
|
+
ls -lah dist
|
|
130
|
+
echo
|
|
131
|
+
echo "Wheel files:"
|
|
132
|
+
ls -1 dist/*.whl || true
|
|
133
|
+
echo
|
|
134
|
+
echo "Source distributions:"
|
|
135
|
+
ls -1 dist/*.tar.gz || true
|
|
136
|
+
|
|
137
|
+
- name: Twine check
|
|
138
|
+
run: |
|
|
139
|
+
python -m pip install --upgrade pip twine
|
|
140
|
+
python -m twine check dist/*
|
|
141
|
+
|
|
142
|
+
- name: Upload wheels to GitHub Release
|
|
143
|
+
uses: softprops/action-gh-release@v2
|
|
144
|
+
with:
|
|
145
|
+
files: |
|
|
146
|
+
dist/*.whl
|
|
147
|
+
dist/*.tar.gz
|
|
148
|
+
|
|
149
|
+
- name: Publish to PyPI
|
|
150
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
151
|
+
with:
|
|
152
|
+
verbose: true
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
name: Publish From Existing Run
|
|
2
|
+
|
|
3
|
+
"on":
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
inputs:
|
|
6
|
+
source_run_id:
|
|
7
|
+
description: "GitHub Actions run ID that already contains wheels + sdist artifacts"
|
|
8
|
+
required: true
|
|
9
|
+
type: string
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
publish:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
permissions:
|
|
15
|
+
id-token: write
|
|
16
|
+
contents: read
|
|
17
|
+
actions: read
|
|
18
|
+
environment:
|
|
19
|
+
name: pypi
|
|
20
|
+
url: https://pypi.org/p/parosol-py
|
|
21
|
+
steps:
|
|
22
|
+
- name: Download wheel artifacts from source run
|
|
23
|
+
uses: actions/download-artifact@v4
|
|
24
|
+
with:
|
|
25
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
26
|
+
repository: ${{ github.repository }}
|
|
27
|
+
run-id: ${{ inputs.source_run_id }}
|
|
28
|
+
pattern: wheels-*
|
|
29
|
+
path: dist
|
|
30
|
+
merge-multiple: true
|
|
31
|
+
|
|
32
|
+
- name: Download sdist artifact from source run
|
|
33
|
+
uses: actions/download-artifact@v4
|
|
34
|
+
with:
|
|
35
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
36
|
+
repository: ${{ github.repository }}
|
|
37
|
+
run-id: ${{ inputs.source_run_id }}
|
|
38
|
+
name: sdist
|
|
39
|
+
path: dist
|
|
40
|
+
|
|
41
|
+
- name: Set up Python for debug tooling
|
|
42
|
+
uses: actions/setup-python@v5
|
|
43
|
+
with:
|
|
44
|
+
python-version: "3.12"
|
|
45
|
+
|
|
46
|
+
- name: Debug artifact inventory
|
|
47
|
+
run: |
|
|
48
|
+
echo "Current dist/ contents:"
|
|
49
|
+
ls -lah dist
|
|
50
|
+
echo
|
|
51
|
+
echo "Wheel files:"
|
|
52
|
+
ls -1 dist/*.whl || true
|
|
53
|
+
echo
|
|
54
|
+
echo "Source distributions:"
|
|
55
|
+
ls -1 dist/*.tar.gz || true
|
|
56
|
+
|
|
57
|
+
- name: Twine check
|
|
58
|
+
run: |
|
|
59
|
+
python -m pip install --upgrade pip twine
|
|
60
|
+
python -m twine check dist/*
|
|
61
|
+
|
|
62
|
+
- name: Publish to PyPI
|
|
63
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
64
|
+
with:
|
|
65
|
+
verbose: true
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
"on":
|
|
4
|
+
pull_request:
|
|
5
|
+
branches: ["main", "master"]
|
|
6
|
+
push:
|
|
7
|
+
branches: ["main", "master"]
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
test:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
strategy:
|
|
16
|
+
fail-fast: false
|
|
17
|
+
matrix:
|
|
18
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
19
|
+
|
|
20
|
+
steps:
|
|
21
|
+
- name: Checkout code
|
|
22
|
+
uses: actions/checkout@v4
|
|
23
|
+
with:
|
|
24
|
+
submodules: recursive
|
|
25
|
+
|
|
26
|
+
- name: Setup Miniconda
|
|
27
|
+
uses: conda-incubator/setup-miniconda@v3
|
|
28
|
+
with:
|
|
29
|
+
activate-environment: testenv
|
|
30
|
+
python-version: ${{ matrix.python-version }}
|
|
31
|
+
channels: conda-forge
|
|
32
|
+
auto-activate-base: false
|
|
33
|
+
|
|
34
|
+
- name: Install native and Python dependencies
|
|
35
|
+
shell: bash -l {0}
|
|
36
|
+
run: |
|
|
37
|
+
conda install -y \
|
|
38
|
+
cmake \
|
|
39
|
+
compilers \
|
|
40
|
+
eigen \
|
|
41
|
+
hdf5 \
|
|
42
|
+
make \
|
|
43
|
+
ninja \
|
|
44
|
+
numpy \
|
|
45
|
+
openmpi \
|
|
46
|
+
pip \
|
|
47
|
+
pytest \
|
|
48
|
+
pytest-cov \
|
|
49
|
+
scikit-build-core \
|
|
50
|
+
simpleitk
|
|
51
|
+
python -m pip install --upgrade pip
|
|
52
|
+
python -m pip install -e . --no-build-isolation
|
|
53
|
+
|
|
54
|
+
- name: Run tests
|
|
55
|
+
shell: bash -l {0}
|
|
56
|
+
run: pytest -q
|
|
57
|
+
|
|
58
|
+
coverage:
|
|
59
|
+
runs-on: ubuntu-latest
|
|
60
|
+
permissions:
|
|
61
|
+
contents: read
|
|
62
|
+
steps:
|
|
63
|
+
- name: Checkout code
|
|
64
|
+
uses: actions/checkout@v4
|
|
65
|
+
with:
|
|
66
|
+
submodules: recursive
|
|
67
|
+
|
|
68
|
+
- name: Setup Miniconda
|
|
69
|
+
uses: conda-incubator/setup-miniconda@v3
|
|
70
|
+
with:
|
|
71
|
+
activate-environment: covenv
|
|
72
|
+
python-version: "3.12"
|
|
73
|
+
channels: conda-forge
|
|
74
|
+
auto-activate-base: false
|
|
75
|
+
|
|
76
|
+
- name: Install native and Python dependencies
|
|
77
|
+
shell: bash -l {0}
|
|
78
|
+
run: |
|
|
79
|
+
conda install -y \
|
|
80
|
+
cmake \
|
|
81
|
+
compilers \
|
|
82
|
+
eigen \
|
|
83
|
+
hdf5 \
|
|
84
|
+
make \
|
|
85
|
+
ninja \
|
|
86
|
+
numpy \
|
|
87
|
+
openmpi \
|
|
88
|
+
pip \
|
|
89
|
+
pytest \
|
|
90
|
+
pytest-cov \
|
|
91
|
+
scikit-build-core \
|
|
92
|
+
simpleitk
|
|
93
|
+
python -m pip install --upgrade pip
|
|
94
|
+
python -m pip install -e . --no-build-isolation
|
|
95
|
+
|
|
96
|
+
- name: Run tests with coverage
|
|
97
|
+
shell: bash -l {0}
|
|
98
|
+
run: pytest -q --cov=parosol_py --cov-report=term-missing --cov-report=xml:coverage.xml
|
|
99
|
+
|
|
100
|
+
- name: Upload coverage artifact
|
|
101
|
+
uses: actions/upload-artifact@v4
|
|
102
|
+
with:
|
|
103
|
+
name: coverage-xml
|
|
104
|
+
path: coverage.xml
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: parosol-py
|
|
3
|
+
Version: 0.1.3
|
|
4
|
+
Summary: Python package and API wrapper for the ParOSol micro-FE solver
|
|
5
|
+
Keywords: finite-element-analysis,bone,hr-pqct,parosol
|
|
6
|
+
Author: Matthias Walle
|
|
7
|
+
Maintainer: Matthias Walle
|
|
8
|
+
License: GPL-2.0-or-later
|
|
9
|
+
Project-URL: Repository, https://github.com/wallematthias/parosol-py
|
|
10
|
+
Project-URL: Native-ParOSol-License, https://github.com/wallematthias/parosol-py/blob/main/src/parosol_native/LICENSE
|
|
11
|
+
Requires-Python: <3.14,>=3.11
|
|
12
|
+
Requires-Dist: numpy>=1.24
|
|
13
|
+
Requires-Dist: h5py>=3.10
|
|
14
|
+
Requires-Dist: SimpleITK>=2.3
|
|
15
|
+
Requires-Dist: aimio-py>=0.1.1
|
|
16
|
+
Requires-Dist: PyYAML>=6
|
|
17
|
+
Requires-Dist: matplotlib>=3.8
|
|
18
|
+
Provides-Extra: dev
|
|
19
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
20
|
+
Requires-Dist: pytest-cov>=5; extra == "dev"
|
|
21
|
+
Requires-Dist: build>=1; extra == "dev"
|
|
22
|
+
Requires-Dist: cibuildwheel>=2.19; extra == "dev"
|
|
23
|
+
Requires-Dist: twine>=5; extra == "dev"
|
|
24
|
+
Provides-Extra: torch
|
|
25
|
+
Requires-Dist: torch>=2.3; extra == "torch"
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
|
|
28
|
+
# parosol-py
|
|
29
|
+
|
|
30
|
+
`parosol-py` is the Python package and runtime wrapper for the ParOSol
|
|
31
|
+
micro-FE solver. It provides Python helpers for creating solver inputs, running
|
|
32
|
+
the bundled native executable, reading outputs, and mapping label or density
|
|
33
|
+
images to material stiffness.
|
|
34
|
+
|
|
35
|
+
The bundled native ParOSol solver was written by Cyril Flaig and is distributed
|
|
36
|
+
under the GNU General Public License, version 2 or later. The Python package is
|
|
37
|
+
therefore distributed as `GPL-2.0-or-later`.
|
|
38
|
+
|
|
39
|
+
## Install
|
|
40
|
+
|
|
41
|
+
Prebuilt wheels include the native ParOSol executable:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
python -m pip install parosol-py
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
For local development:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
python -m pip install -e .[dev]
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Source installs require CMake, an MPI C++ compiler/runtime, HDF5 C++ libraries,
|
|
54
|
+
and Eigen headers. Release wheels are built for Python 3.11, 3.12, and 3.13.
|
|
55
|
+
macOS wheels currently target macOS 15 or newer because the bundled native
|
|
56
|
+
solver depends on Homebrew HDF5/OpenMPI libraries built for that target.
|
|
57
|
+
|
|
58
|
+
## Local Check
|
|
59
|
+
|
|
60
|
+
Before relying on GitHub Actions, run the local verification gate from an
|
|
61
|
+
environment that has the native build tools:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
python scripts/local_check.py
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Add `--smoke-install` to install the built wheel into a temporary virtual
|
|
68
|
+
environment and import it.
|
|
69
|
+
|
|
70
|
+
## Python API
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
import numpy as np
|
|
74
|
+
|
|
75
|
+
from parosol_py import solve
|
|
76
|
+
|
|
77
|
+
material = np.ones((10, 10, 10), dtype=np.float32) * 1000.0
|
|
78
|
+
|
|
79
|
+
result = solve(
|
|
80
|
+
material=material,
|
|
81
|
+
spacing=(0.061, 0.061, 0.061),
|
|
82
|
+
material_unit="MPa",
|
|
83
|
+
test="axial",
|
|
84
|
+
test_axis="z",
|
|
85
|
+
strain=-0.01,
|
|
86
|
+
outputs=("sed",),
|
|
87
|
+
export_dir="outputs/example",
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
print(result.summary)
|
|
91
|
+
print(result.exported)
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Use `dry_run=True` to write the ParOSol HDF5 input and command without launching
|
|
95
|
+
the solver:
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
result = solve(
|
|
99
|
+
material=material,
|
|
100
|
+
spacing=(0.061, 0.061, 0.061),
|
|
101
|
+
material_unit="MPa",
|
|
102
|
+
test="axial",
|
|
103
|
+
test_axis="z",
|
|
104
|
+
strain=-0.01,
|
|
105
|
+
dry_run=True,
|
|
106
|
+
export_dir="outputs/dry_run",
|
|
107
|
+
)
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Material Mapping
|
|
111
|
+
|
|
112
|
+
Label images can be mapped through an explicit material table:
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
import numpy as np
|
|
116
|
+
|
|
117
|
+
from parosol_py import LinearIsotropicMaterials, labels_to_material_map
|
|
118
|
+
|
|
119
|
+
labels = np.array([[[100, 127]]], dtype=np.uint16)
|
|
120
|
+
table = LinearIsotropicMaterials(
|
|
121
|
+
youngs_modulus_mpa={100: 8748.0, 127: 8748.0},
|
|
122
|
+
poisson_ratio={100: 0.3, 127: 0.3},
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
mapped = labels_to_material_map(labels, table)
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Continuous density images can be converted with one of the supported equations:
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
from parosol_py import density_to_material_map
|
|
132
|
+
|
|
133
|
+
mapped = density_to_material_map(
|
|
134
|
+
density_image,
|
|
135
|
+
equation="power",
|
|
136
|
+
coefficient=10000.0,
|
|
137
|
+
exponent=1.7,
|
|
138
|
+
reference_density=1000.0,
|
|
139
|
+
poisson_ratio=0.3,
|
|
140
|
+
)
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
The Mulder grayscale BMD law is available as `mulder2007`:
|
|
144
|
+
|
|
145
|
+
```python
|
|
146
|
+
mapped = density_to_material_map(
|
|
147
|
+
density_image,
|
|
148
|
+
equation="mulder2007",
|
|
149
|
+
active_mask=outer_contour,
|
|
150
|
+
floor_e_mpa=2.0,
|
|
151
|
+
poisson_ratio=0.3,
|
|
152
|
+
)
|
|
153
|
+
```
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# parosol-py
|
|
2
|
+
|
|
3
|
+
`parosol-py` is the Python package and runtime wrapper for the ParOSol
|
|
4
|
+
micro-FE solver. It provides Python helpers for creating solver inputs, running
|
|
5
|
+
the bundled native executable, reading outputs, and mapping label or density
|
|
6
|
+
images to material stiffness.
|
|
7
|
+
|
|
8
|
+
The bundled native ParOSol solver was written by Cyril Flaig and is distributed
|
|
9
|
+
under the GNU General Public License, version 2 or later. The Python package is
|
|
10
|
+
therefore distributed as `GPL-2.0-or-later`.
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
Prebuilt wheels include the native ParOSol executable:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
python -m pip install parosol-py
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
For local development:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
python -m pip install -e .[dev]
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Source installs require CMake, an MPI C++ compiler/runtime, HDF5 C++ libraries,
|
|
27
|
+
and Eigen headers. Release wheels are built for Python 3.11, 3.12, and 3.13.
|
|
28
|
+
macOS wheels currently target macOS 15 or newer because the bundled native
|
|
29
|
+
solver depends on Homebrew HDF5/OpenMPI libraries built for that target.
|
|
30
|
+
|
|
31
|
+
## Local Check
|
|
32
|
+
|
|
33
|
+
Before relying on GitHub Actions, run the local verification gate from an
|
|
34
|
+
environment that has the native build tools:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
python scripts/local_check.py
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Add `--smoke-install` to install the built wheel into a temporary virtual
|
|
41
|
+
environment and import it.
|
|
42
|
+
|
|
43
|
+
## Python API
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
import numpy as np
|
|
47
|
+
|
|
48
|
+
from parosol_py import solve
|
|
49
|
+
|
|
50
|
+
material = np.ones((10, 10, 10), dtype=np.float32) * 1000.0
|
|
51
|
+
|
|
52
|
+
result = solve(
|
|
53
|
+
material=material,
|
|
54
|
+
spacing=(0.061, 0.061, 0.061),
|
|
55
|
+
material_unit="MPa",
|
|
56
|
+
test="axial",
|
|
57
|
+
test_axis="z",
|
|
58
|
+
strain=-0.01,
|
|
59
|
+
outputs=("sed",),
|
|
60
|
+
export_dir="outputs/example",
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
print(result.summary)
|
|
64
|
+
print(result.exported)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Use `dry_run=True` to write the ParOSol HDF5 input and command without launching
|
|
68
|
+
the solver:
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
result = solve(
|
|
72
|
+
material=material,
|
|
73
|
+
spacing=(0.061, 0.061, 0.061),
|
|
74
|
+
material_unit="MPa",
|
|
75
|
+
test="axial",
|
|
76
|
+
test_axis="z",
|
|
77
|
+
strain=-0.01,
|
|
78
|
+
dry_run=True,
|
|
79
|
+
export_dir="outputs/dry_run",
|
|
80
|
+
)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Material Mapping
|
|
84
|
+
|
|
85
|
+
Label images can be mapped through an explicit material table:
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
import numpy as np
|
|
89
|
+
|
|
90
|
+
from parosol_py import LinearIsotropicMaterials, labels_to_material_map
|
|
91
|
+
|
|
92
|
+
labels = np.array([[[100, 127]]], dtype=np.uint16)
|
|
93
|
+
table = LinearIsotropicMaterials(
|
|
94
|
+
youngs_modulus_mpa={100: 8748.0, 127: 8748.0},
|
|
95
|
+
poisson_ratio={100: 0.3, 127: 0.3},
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
mapped = labels_to_material_map(labels, table)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Continuous density images can be converted with one of the supported equations:
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
from parosol_py import density_to_material_map
|
|
105
|
+
|
|
106
|
+
mapped = density_to_material_map(
|
|
107
|
+
density_image,
|
|
108
|
+
equation="power",
|
|
109
|
+
coefficient=10000.0,
|
|
110
|
+
exponent=1.7,
|
|
111
|
+
reference_density=1000.0,
|
|
112
|
+
poisson_ratio=0.3,
|
|
113
|
+
)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
The Mulder grayscale BMD law is available as `mulder2007`:
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
mapped = density_to_material_map(
|
|
120
|
+
density_image,
|
|
121
|
+
equation="mulder2007",
|
|
122
|
+
active_mask=outer_contour,
|
|
123
|
+
floor_e_mpa=2.0,
|
|
124
|
+
poisson_ratio=0.3,
|
|
125
|
+
)
|
|
126
|
+
```
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["scikit-build-core>=0.10"]
|
|
3
|
+
build-backend = "scikit_build_core.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "parosol-py"
|
|
7
|
+
version = "0.1.3"
|
|
8
|
+
description = "Python package and API wrapper for the ParOSol micro-FE solver"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11,<3.14"
|
|
11
|
+
license = { text = "GPL-2.0-or-later" }
|
|
12
|
+
authors = [{ name = "Matthias Walle" }]
|
|
13
|
+
maintainers = [{ name = "Matthias Walle" }]
|
|
14
|
+
keywords = ["finite-element-analysis", "bone", "hr-pqct", "parosol"]
|
|
15
|
+
dependencies = [
|
|
16
|
+
"numpy>=1.24",
|
|
17
|
+
"h5py>=3.10",
|
|
18
|
+
"SimpleITK>=2.3",
|
|
19
|
+
"aimio-py>=0.1.1",
|
|
20
|
+
"PyYAML>=6",
|
|
21
|
+
"matplotlib>=3.8",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
[project.scripts]
|
|
25
|
+
parosol = "parosol_py.cli:main"
|
|
26
|
+
|
|
27
|
+
[project.urls]
|
|
28
|
+
Repository = "https://github.com/wallematthias/parosol-py"
|
|
29
|
+
Native-ParOSol-License = "https://github.com/wallematthias/parosol-py/blob/main/src/parosol_native/LICENSE"
|
|
30
|
+
|
|
31
|
+
[project.optional-dependencies]
|
|
32
|
+
dev = [
|
|
33
|
+
"pytest>=8",
|
|
34
|
+
"pytest-cov>=5",
|
|
35
|
+
"build>=1",
|
|
36
|
+
"cibuildwheel>=2.19",
|
|
37
|
+
"twine>=5",
|
|
38
|
+
]
|
|
39
|
+
torch = [
|
|
40
|
+
"torch>=2.3",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
[tool.scikit-build]
|
|
44
|
+
cmake.version = ">=3.18"
|
|
45
|
+
wheel.packages = ["src/parosol_py", "src/parosol_torch"]
|
|
46
|
+
|
|
47
|
+
[tool.cibuildwheel]
|
|
48
|
+
build = "cp311-* cp312-* cp313-*"
|
|
49
|
+
skip = "*-musllinux_* *-manylinux_i686 *-win32"
|
|
50
|
+
test-command = "python -c \"from parosol_py.runner import packaged_executable; p=packaged_executable(); print(p); assert p.exists()\""
|
|
51
|
+
build-verbosity = 1
|
|
52
|
+
|
|
53
|
+
[tool.cibuildwheel.linux]
|
|
54
|
+
archs = ["x86_64"]
|
|
55
|
+
before-all = "if command -v yum >/dev/null 2>&1; then yum install -y eigen3-devel hdf5-devel openmpi-devel; elif command -v dnf >/dev/null 2>&1; then dnf install -y eigen3-devel hdf5-devel openmpi-devel; elif command -v apt-get >/dev/null 2>&1; then apt-get update && apt-get install -y libeigen3-dev libhdf5-dev libopenmpi-dev openmpi-bin; else echo 'No supported package manager found for native dependencies' && exit 1; fi"
|
|
56
|
+
environment = { PATH="/usr/lib64/openmpi/bin:/usr/lib/openmpi/bin:$PATH", LD_LIBRARY_PATH="/usr/lib64/openmpi/lib:/usr/lib/openmpi/lib:$LD_LIBRARY_PATH" }
|
|
57
|
+
|
|
58
|
+
[tool.cibuildwheel.macos]
|
|
59
|
+
before-all = "brew install eigen hdf5 open-mpi"
|
|
60
|
+
environment = { CMAKE_PREFIX_PATH="$(brew --prefix eigen):$(brew --prefix hdf5):$(brew --prefix open-mpi)", MACOSX_DEPLOYMENT_TARGET="15.0" }
|
|
61
|
+
repair-wheel-command = "python -m pip install delocate && delocate-wheel --require-archs {delocate_archs} -w {dest_dir} {wheel}"
|
|
62
|
+
|
|
63
|
+
[tool.cibuildwheel.windows]
|
|
64
|
+
archs = ["AMD64"]
|
|
65
|
+
before-all = "powershell -NoProfile -ExecutionPolicy Bypass -Command \"$ErrorActionPreference = 'Stop'; winget install --id Microsoft.msmpi --exact --silent --accept-package-agreements --accept-source-agreements; if (-not (Test-Path 'C:\\Program Files\\Microsoft MPI\\Bin\\mpiexec.exe')) { throw 'MS-MPI redistributable install did not produce mpiexec.exe' }; if (-not (Test-Path 'C:\\vcpkg')) { git clone --depth 1 https://github.com/microsoft/vcpkg C:\\vcpkg }; & C:\\vcpkg\\bootstrap-vcpkg.bat; & C:\\vcpkg\\vcpkg.exe install eigen3:x64-windows hdf5[cpp]:x64-windows msmpi:x64-windows --disable-metrics\""
|
|
66
|
+
environment = { CMAKE_TOOLCHAIN_FILE="C:/vcpkg/scripts/buildsystems/vcpkg.cmake", VCPKG_TARGET_TRIPLET="x64-windows" }
|
|
67
|
+
repair-wheel-command = "python -m pip install delvewheel && delvewheel repair -w {dest_dir} {wheel}"
|
|
68
|
+
|
|
69
|
+
[tool.pytest.ini_options]
|
|
70
|
+
testpaths = ["tests"]
|
|
71
|
+
addopts = "-ra"
|