Skip to content
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
3 changes: 3 additions & 0 deletions .github/workflows/build-wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ jobs:
# Set LD_LIBRARY_PATH so auditwheel can find shared libs to bundle
CIBW_ENVIRONMENT_LINUX: >
LD_LIBRARY_PATH=/usr/local/deps/lib:/usr/local/deps/lib64:$LD_LIBRARY_PATH
CMAKE_PREFIX_PATH=/usr/local/deps
OMEGA_H_ROOT=/usr/local/deps
KOKKOS_ROOT=/usr/local/deps

# auditwheel repair is run automatically by cibuildwheel

Expand Down
61 changes: 9 additions & 52 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
strategy:
matrix:
build_type: ["Release", "Debug"]
python-version: ["3.11", "3.12", "3.13"]
python-version: ["3.11", "3.13"]

name: "Python ${{ matrix.python-version }} - ${{ matrix.build_type }}"

Expand Down Expand Up @@ -117,6 +117,9 @@ jobs:
shell: bash
run: |
cd ${GITHUB_WORKSPACE}
export CMAKE_PREFIX_PATH="${{ runner.temp }}/build-omega_h/install:${{ runner.temp }}/build-kokkos/install:$CMAKE_PREFIX_PATH"
export OMEGA_H_ROOT="${{ runner.temp }}/build-omega_h/install/"
export KOKKOS_ROOT="${{ runner.temp }}/build-kokkos/install"
python -m build
pip install .[test]

Expand All @@ -129,61 +132,15 @@ jobs:
export OMP_NUM_THREADS=2
pytest -vv -s

- name: Create and repair wheel
# Creating the wheel is enough now since it will be repaired by cibuildwheel
- name: Create wheel
shell: bash
run: |
cd ${GITHUB_WORKSPACE}
pip install auditwheel patchelf
# Build the wheel
export CMAKE_PREFIX_PATH="${{ runner.temp }}/build-omega_h/install:${{ runner.temp }}/build-kokkos/install:$CMAKE_PREFIX_PATH"
export OMEGA_H_ROOT="${{ runner.temp }}/build-omega_h/install/"
export KOKKOS_ROOT="${{ runner.temp }}/build-kokkos/install"
python -m build --wheel --outdir dist/
echo "---- Built wheels ----"
ls -la dist/
# Repair the wheel — bundle shared libs (omega_h, kokkos, etc.)
export LD_LIBRARY_PATH="${{ runner.temp }}/build-omega_h/install/lib:${{ runner.temp }}/build-kokkos/install/lib:${LD_LIBRARY_PATH}"
auditwheel show dist/*.whl
auditwheel repair dist/*.whl --wheel-dir repaired_wheels/
echo "---- Repaired wheels ----"
ls -la repaired_wheels/

- name: Upload repaired wheel
uses: actions/upload-artifact@v4
with:
name: wheel-py${{ matrix.python-version }}-${{ matrix.build_type }}
path: repaired_wheels/*.whl

test-wheel:
needs: main
runs-on: ubuntu-24.04
strategy:
matrix:
python-version: ["3.11"]

name: "Test Wheel - Python ${{ matrix.python-version }}"

steps:
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Download repaired wheel
uses: actions/download-artifact@v4
with:
name: wheel-py${{ matrix.python-version }}-Release
path: wheel/

- name: Install wheel
shell: bash
run: |
ls -la wheel/
pip install --extra-index-url https://shimwell.github.io/wheels openmc
pip install netCDF4==1.7.2
pip install wheel/*.whl

- name: Test convert2degas2 --help
shell: bash
run: convert2degas2 --help

- name: Test convert2openmc --help
shell: bash
run: convert2openmc --help
12 changes: 0 additions & 12 deletions MANIFEST.in

This file was deleted.

20 changes: 14 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# Convert `Omega_h` Mesh to CSG Format
[![License](https://img.shields.io/badge/license-BSD--3--Clause-02B36C)](https://github.com/Fuad-HH/readOH2csg/blob/parallel/LICENSE)
[![GitHub Actions build status (Linux)](https://github.com/Fuad-HH/readOH2csg/actions/workflows/ci.yml/badge.svg?branch=parallel)](https://github.com/Fuad-HH/readOH2csg/actions/workflows/ci.yml)
[![Release](https://img.shields.io/github/v/release/Fuad-HH/readOH2csg?include_prereleases
)](https://github.com/Fuad-HH/readOH2csg/releases)
[![Release](https://img.shields.io/github/v/release/Fuad-HH/readOH2csg?include_prereleases)](https://github.com/Fuad-HH/readOH2csg/releases)

Efficiently convert Tokamak mesh of `Omega_h` (`.osh`) format
to Constructive Solid Geometry (CSG). It supports creating
Expand All @@ -16,6 +15,8 @@ CSG representation in
### 1. Pre-built Wheel
This is the recommended way to install this package. We provide a pre-built wheel (`Kokkos` with `OpenMP` backend) for Python. Follow these steps to install the latest version of `readOH2csg` using pip:

Wheels are built in CI and uploaded as workflow artifacts for each Python version and build type.

1. On any Linux system, make sure you have Python (Version ≥ 3.11) installed. Go to the terminal
and `cd` to the directory where you want to install the Python virtual environment.
```bash
Expand All @@ -31,13 +32,17 @@ pip install --extra-index-url https://shimwell.github.io/wheels openmc
pip install netCDF4==1.7.2
```
3. Install `readOH2csg`:

```bash
pip install https://github.com/Fuad-HH/readOH2csg/releases/download/v0.0.1-alpha/omegah2csg-0.0.1-py3-none-any.whl omegah2csg
pip install omegah2csg
```
or
Or if you want to install the latest release from GitHub:
```bash
pip install -i https://test.pypi.org/simple/ omegah2csg
pip install <link-to-release-wheel-file> omegah2csg
```
>[!TIP]
> Find the latest release on the [Releases Page](https://github.com/Fuad-HH/readOH2csg/releases/)
> and copy the link to the wheel file for your Python version and system architecture.

4. Try running the CLI tool, and it should print the help message:
```bash
Expand All @@ -51,7 +56,7 @@ with [`Kokkos`](https://github.com/kokkos/kokkos) and it supports any [`Kokkos`]

Follow these steps to build and install `readOH2csg` from source:
1. Make sure you have compilers (at least `g++` or some alternative), `Python` (Version ≥ 3.11), and `CMake` available.
1. Install [`Kokkos`](https://github.com/kokkos/kokkos) following the instructions in
2. Install [`Kokkos`](https://github.com/kokkos/kokkos) following the instructions in
[Kokkos Build Documentation](https://kokkos.org/kokkos-core-wiki/get-started/building-from-source.html#configuring-and-building-kokkos). You can choose any backend supported. Here's an example for building with the `OpenMP` backend:
```bash
git clone --depth=2 --branch 4.7.02 https://github.com/kokkos/kokkos.git
Expand Down Expand Up @@ -98,10 +103,13 @@ cmake --build build -j4 --target install
>[!WARNING]
> For now, only the Python API and CLI work. Please do not turn off the option for Python bindings. It is
> enabled by default.

5. Create Python virtual environment and install dependencies as described in the [Pre-built Wheel](#1-pre-built-wheel) section.
6. Install `readOH2csg` and run the CLI tool, and it should print the help message:
```bash
# from the source directory
export KOKKOS_ROOT=<Kokkos_install_dir>
export OMEGA_H_ROOT=<Omega_h_install_dir>
python -m pip install .
convert2degas2 --help
```
Expand Down
63 changes: 34 additions & 29 deletions doc/DEVELOPERS_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ It describes the packaging strategy and choices of tools.
To get started with Python packaging, check out the [Python Packaging User Guide](https://packaging.python.org/en/latest/).

## Formatting Style
All codes in this project are formatted with formatting tools. All these formattings are enforced in the CI pipeline.

>[!TIP] If formatting is passing locally but failing in CI, make sure you are using the same version of the formatting tools as specified in the CI pipeline.
Formatting tools are used to maintain a consistent code style across the project. They are also enforced in CI to ensure that all contributions adhere to the same style guidelines. The formatting tools used in this project are:

- C++ uses `clang-format` with the configuration specified in the [.clang-format](../.clang-format) file.
- CMake files use `cmake-format` with the configuration specified in the [.cmake-format](../.cmake-format.yaml) file.
- Python files uses [`ruff`](https://docs.astral.sh/ruff/formatter/) to format the code with the configuration specified in the [pyproject.toml](../pyproject.toml) file.
- Python files use [`ruff`](https://docs.astral.sh/ruff/formatter/) to format the code with the configuration specified in the [pyproject.toml](../pyproject.toml) file.

>[!TIP]
> If formatting is passing locally but failing in CI, make sure you are using the same version of the formatting tools as specified in the CI pipeline.

### C++ and CMake Formatting
The C++ codes use the [.clang-format](../.clang-format) file and to format the code, you can use `clang-format` tool
Expand Down Expand Up @@ -296,47 +297,51 @@ pytest
```

## Packaging
### Create Distribution Files
After development and testing, to create the archive and wheel for distribution, install `build` using `pip` and run:
### Overview
This project uses `scikit-build-core` to build a Python wheel that includes the native
`libomegah2csg.so` shared library. You can build locally or use the CI workflow to
produce manylinux wheels.

### Local build (developer machine)
You must have Omega_h and Kokkos installed and discoverable by CMake before building.

1. Install build tooling:
```bash
python -m build
python -m pip install -U build
```
which will create the distribution files in the `dist/` directory.

### Repair the Wheel with `auditwheel`
The built wheel contains a shared library (`omegah2csg.so`) that links against external shared
libraries (Omega\_h, Kokkos, etc.). To make the wheel portable and self-contained, use
[`auditwheel`](https://github.com/pypa/auditwheel) to bundle those shared libraries into the wheel.

First, install `auditwheel` and `patchelf`:
2. Provide CMake hints (use your install prefixes):
```bash
pip install auditwheel patchelf
export CMAKE_PREFIX_PATH="<Omega_h_install_dir>:<Kokkos_install_dir>:${CMAKE_PREFIX_PATH}"
```

Make sure the shared libraries that the wheel depends on are discoverable via `LD_LIBRARY_PATH`.
For example, if Omega\_h and Kokkos are installed under `/path/to/omega_h` and `/path/to/kokkos`:
3. Build sdist + wheel:
```bash
export LD_LIBRARY_PATH="/path/to/omega_h/lib64:/path/to/kokkos/lib64:${LD_LIBRARY_PATH}"
python -m build
```

Then inspect and repair the wheel:
Artifacts are written to `dist/`.

### CI build (manylinux wheels)
The `Build Manylinux Wheels` workflow builds Omega_h and Kokkos in the container and
then builds wheels with `cibuildwheel`. The resulting wheels are uploaded as workflow
artifacts named `manylinux-wheels`.

To download wheels from CI with GitHub CLI:
```bash
# Show external shared library dependencies
auditwheel show dist/*.whl
# Find the workflow run you want
gh run list --workflow "Build Manylinux Wheels"

# Repair the wheel — bundles shared libs into the wheel
auditwheel repair dist/*.whl --wheel-dir repaired_wheels/
# Download the wheels from a specific run
gh run download <jobid> --name manylinux-wheels
```

The repaired wheel will be in the `repaired_wheels/` directory and can be installed on any
compatible Linux system without needing Omega\_h or Kokkos installed separately.

### Upload to PyPI/TestPyPI
To upload the distribution files to PyPI or TestPyPI, install `twine` using `pip` and run:
To upload the distribution files to PyPI or TestPyPI, install `twine` and run:
```bash
python -m pip install -U twine
python -m twine upload --repository testpypi dist/*
```

It will require a `testpypi` `index-server` entry in your `~/.pypirc` file. See PyPI documentation
for more details.
This requires a `testpypi` `index-server` entry in your `~/.pypirc`. See the PyPI
documentation for details.
4 changes: 2 additions & 2 deletions doc/top_bottom_flag.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Top or Bottom of a Cone

This figure illustrates that both on the line segments here create two different cones. But for
our case, we only want to half cone that touches the line.
our case, we only want the half cone that touches the line.

![Figure shows two different cones generated by two lines](images/compute_coefficients.svg)
![Figure shows two different cones generated by two lines](images/compute_coefficients.svg)
43 changes: 30 additions & 13 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[build-system]
requires = ["setuptools >= 77.0.3", "wheel"]
build-backend = "setuptools.build_meta"
requires = ["scikit-build-core>=0.12.2"]
build-backend = "scikit_build_core.build"

[project]
name = "omegah2csg"
Expand All @@ -9,7 +9,7 @@ authors = [
]
description = "Convert Omega_h mesh files generated using TOMMS for TOKAMAKs to CSG format for OpenMC and Degas2."
readme = "README.md"
version = "0.0.1"
dynamic = ["version"]
requires-python = ">=3.11"
classifiers = [
"Intended Audience :: Developers",
Expand Down Expand Up @@ -39,21 +39,38 @@ test = [
Homepage = "https://github.com/Fuad-HH/readOH2csg"
Issues = "https://github.com/Fuad-HH/readOH2csg/issues"

[tool.setuptools.packages.find]
where = ["pythonAPI"]
include = ["omegah2csg*"]
exclude = ["tests*"]
namespaces = true


[tool.setuptools.package-data]
"omegah2csg" = ["*.txt", "*.dat", "*.osh", "*.so"]

[project.scripts]
convert2openmc = "omegah2csg.convert2openmc.convert2openmc_cli:app"
convert2degas2 = "omegah2csg.convert2degas2.convert2degas2_cli:app"


[tool.scikit-build]
minimum-version = "build-system.requires"
wheel.packages = ["pythonAPI/omegah2csg"]
metadata.version.provider = "scikit_build_core.metadata.regex"
metadata.version.input = "CMakeLists.txt"
metadata.version.regex = "project\\([^)]*?\\bVERSION\\s+(?P<value>[0-9]+\\.[0-9]+\\.[0-9]+)[^)]*\\)"
sdist.include = [
"CMakeLists.txt",
"cmake/**",
"src/**",
"pythonAPI/**",
"tests/**",
"README.md",
"LICENSE",
"pyproject.toml",
"pytest.toml",
]

[tool.scikit-build.cmake.define]
CMAKE_PREFIX_PATH = { env = "CMAKE_PREFIX_PATH", default = "" }
Omega_h_ROOT = { env = "OMEGA_H_ROOT", default = "" }
Kokkos_ROOT = { env = "KOKKOS_ROOT", default = "" }
CMAKE_C_COMPILER = { env = "CC", default = "" }
CMAKE_CXX_COMPILER = { env = "CXX", default = "" }
CMAKE_BUILD_TYPE = { env = "CMAKE_BUILD_TYPE", default = "RelWithDebInfo" }


[tool.ruff]
include = ["pyproject.toml", "pythonAPI/omegah2csg/**/*.py", "tests/**/*.py"]
line-length = 88
Expand Down
29 changes: 29 additions & 0 deletions pythonAPI/omegah2csg/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
from importlib import metadata
from pathlib import Path
import re

from .config import KokkosRuntime, kokkos_runtime
from .OmegaHMesh import (
OmegaHMesh,
Expand All @@ -9,6 +13,29 @@
)
from .convert2degas2 import convert2degas2


def _read_cmake_version() -> str | None:
cmake_path = Path(__file__).resolve().parents[2] / "CMakeLists.txt"
if not cmake_path.is_file():
return None
content = cmake_path.read_text(encoding="utf-8")
match = re.search(
r"project\([^)]*?\bVERSION\s+([0-9]+\.[0-9]+\.[0-9]+)[^)]*\)",
content,
re.DOTALL,
)
return match.group(1) if match else None


def _get_version() -> str:
try:
return metadata.version("omegah2csg")
except metadata.PackageNotFoundError:
return _read_cmake_version() or "0.0.0"


__version__ = _get_version()

__all__ = [
# runtime
"KokkosRuntime",
Expand All @@ -21,4 +48,6 @@
"convert2openmcXML",
# degas2
"convert2degas2",
# version
"__version__",
]
Loading
Loading