Metadata-Version: 2.5
Name: pyofel
Version: 0.1.0
Summary: Python bindings for Ofel, via pythonnet and Ofel.PythonInterop.
Project-URL: Homepage, https://github.com/se-benjamin-carron/pyofel
Project-URL: Repository, https://github.com/se-benjamin-carron/pyofel
Author: se-benjamin-carron
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering
Requires-Python: >=3.10
Requires-Dist: pythonnet>=3.0
Provides-Extra: dev
Requires-Dist: pytest; extra == 'dev'
Description-Content-Type: text/markdown

# pyofel

Python bindings for [`Ofel`](https://github.com/se-benjamin-carron/ofel),
via [pythonnet](https://github.com/pythonnet/pythonnet) and the
`Ofel.PythonInterop` project. Lets Python/ML code build and solve `Ofel`
finite-element structures without hand-rolling the CoreCLR bootstrap.

## Setup

### Installing the prebuilt package (Windows)

```bash
pip install pyofel
```

No .NET SDK or runtime is required — the published Windows wheel bundles a
private copy of the .NET 9 runtime alongside the published `Ofel.PythonInterop`
output, so `pip install pyofel` is the entire setup.

### Building from source (contributors / non-Windows)

- Python >= 3.10
- **.NET 9 SDK** — required locally to build/install this package this way.

Clone with submodules (this repo vendors a pinned copy of `ofel` at
`vendor/ofel` to build `Ofel.PythonInterop` against):

```bash
git clone --recurse-submodules https://github.com/se-benjamin-carron/pyofel
cd pyofel
```

If you already cloned without `--recurse-submodules`:

```bash
git submodule update --init --recursive
```

Install (this runs a build hook that `dotnet publish`s
`vendor/ofel/src/Ofel.PythonInterop` and stages the output into
`pyofel/_interop/`):

```bash
pip install -e .[dev]
```

Run the tests:

```bash
pytest
```

To reproduce the prebuilt-wheel build locally (Windows only), fetch a
win-x64 .NET 9 runtime-only install and point `PYOFEL_BUNDLE_RUNTIME_DIR` at
it before building:

```bash
PYOFEL_BUNDLE_RUNTIME_DIR=/path/to/dotnet-runtime-win-x64 python -m build --wheel
```

This bundles that runtime into the wheel and tags it as a platform-specific
`win_amd64` wheel instead of pure Python — see `.github/workflows/release.yml`
for the exact CI sequence that fetches the runtime and builds/validates this.

## Usage

```python
from pyofel.directors import create_cantilever_column_compression

structure = create_cantilever_column_compression(length=3.0, force=1000.0)
structure.Prepare(0.5)
structure.Compute(False)
```

`pyofel.directors` wraps every `Ofel.Core.StructureDirector.Create*` example
factory (cantilever/hinged/isostatic beams, the default roof, columns under
compression/flexion, etc.) as a thin pass-through, plus
`create_cantilever_column_lateral_load`, a hand-rolled port of the extended
example in `ofel`'s `docs/python-smoke-test.md` that drives the granular
`MemberDirector` primitives (`Point`, `Member`, `ForceValue`, ...) directly.

`pyofel.evaluation` wraps the higher-level `Ofel.API.Services.StructureEvaluationService`
pipeline (full building input -> climatic loads -> FEM -> Eurocode 3 steel
verification):

```python
from pyofel.evaluation import create_building2s1_example_input, evaluate, uls_ratios

structure_input = create_building2s1_example_input()
members, structure = evaluate(structure_input)
ratios = uls_ratios(members)
```

`create_building2s1_example_input` is a direct port of vendor/ofel's
`Ofel.API.Tests` `UIFixtures.CreateBuilding2S1Input()` fixture, building a
full `StructureEvaluationInputUI` (wind/snow loads, roofing plates/purlins,
a Building2S1 gantry, project settings) from the granular `Ofel.Contracts.UI`
input objects. Broader wrapper coverage around other gantry types
(Building1, Butterfly, DoubleCanopy, SimpleCanopy) is follow-up work.

## Updating the pinned `ofel` version

```bash
cd vendor/ofel
git fetch --tags
git checkout <new-tag-or-commit>
cd ../..
git add vendor/ofel
git commit -m "chore: bump vendor/ofel to <new-tag-or-commit>"
```
