yld.run 0.1.0__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.
- yld_run-0.1.0/.gitignore +86 -0
- yld_run-0.1.0/LICENSE +21 -0
- yld_run-0.1.0/PKG-INFO +165 -0
- yld_run-0.1.0/README.md +131 -0
- yld_run-0.1.0/pyproject.toml +59 -0
- yld_run-0.1.0/yld/__init__.py +84 -0
- yld_run-0.1.0/yld/adapt.py +209 -0
- yld_run-0.1.0/yld/archive/__init__.py +36 -0
- yld_run-0.1.0/yld/archive/container.py +208 -0
- yld_run-0.1.0/yld/archive/reader.py +541 -0
- yld_run-0.1.0/yld/archive/visualisation.py +278 -0
- yld_run-0.1.0/yld/bounds.py +140 -0
- yld_run-0.1.0/yld/edit/__init__.py +84 -0
- yld_run-0.1.0/yld/edit/handles.py +407 -0
- yld_run-0.1.0/yld/edit/reconcile.py +132 -0
- yld_run-0.1.0/yld/edit/transforms.py +1518 -0
- yld_run-0.1.0/yld/execution.py +174 -0
- yld_run-0.1.0/yld/outputs.py +49 -0
- yld_run-0.1.0/yld/problem/__init__.py +45 -0
- yld_run-0.1.0/yld/problem/boundary_conditions.py +76 -0
- yld_run-0.1.0/yld/problem/coordinates.py +149 -0
- yld_run-0.1.0/yld/problem/evaluation.py +21 -0
- yld_run-0.1.0/yld/problem/fields.py +71 -0
- yld_run-0.1.0/yld/problem/loads.py +112 -0
- yld_run-0.1.0/yld/problem/model.py +1955 -0
- yld_run-0.1.0/yld/problem/naming.py +599 -0
- yld_run-0.1.0/yld/problem/spatial.py +452 -0
- yld_run-0.1.0/yld/problem/topology.py +184 -0
- yld_run-0.1.0/yld/solve_request.py +1076 -0
- yld_run-0.1.0/yld/solvers.py +100 -0
- yld_run-0.1.0/yld/targets.py +153 -0
- yld_run-0.1.0/yld/visualisation/__init__.py +3 -0
- yld_run-0.1.0/yld/visualisation/bernstein.py +91 -0
- yld_run-0.1.0/yld/visualisation/glyphs.py +370 -0
- yld_run-0.1.0/yld/visualisation/tooltip.py +112 -0
- yld_run-0.1.0/yld/visualisation/viewer.py +355 -0
yld_run-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# Editors and OS files
|
|
2
|
+
.DS_Store
|
|
3
|
+
Thumbs.db
|
|
4
|
+
*~
|
|
5
|
+
*.swp
|
|
6
|
+
*.swo
|
|
7
|
+
.vscode/
|
|
8
|
+
.idea/
|
|
9
|
+
|
|
10
|
+
# CMake/build outputs
|
|
11
|
+
#
|
|
12
|
+
# Anchored to the repository root. This is the CMake build tree and the home for generated
|
|
13
|
+
# experiment output (`build/experiments/<experiment>/<run>/`). Unanchored, this rule also
|
|
14
|
+
# swallowed two things it was never meant to: `yld-ui/build/`, which Wails keeps as *source*
|
|
15
|
+
# for its build assets, and curated evidence under `experiments/*/evidence/build/`.
|
|
16
|
+
/build/
|
|
17
|
+
# `examples/ben_cutting_slope.ipynb` writes the archives it demonstrates into `build/notebook`
|
|
18
|
+
# relative to its own working directory, which is `examples/`.
|
|
19
|
+
/examples/build/
|
|
20
|
+
cmake-build-*/
|
|
21
|
+
CMakeFiles/
|
|
22
|
+
CMakeCache.txt
|
|
23
|
+
cmake_install.cmake
|
|
24
|
+
compile_commands.json
|
|
25
|
+
CTestTestfile.cmake
|
|
26
|
+
Testing/
|
|
27
|
+
|
|
28
|
+
# C/C++ artifacts
|
|
29
|
+
*.o
|
|
30
|
+
*.obj
|
|
31
|
+
*.a
|
|
32
|
+
*.lib
|
|
33
|
+
*.so
|
|
34
|
+
*.dylib
|
|
35
|
+
*.dll
|
|
36
|
+
*.exe
|
|
37
|
+
|
|
38
|
+
# Python artifacts
|
|
39
|
+
__pycache__/
|
|
40
|
+
*.py[cod]
|
|
41
|
+
*.egg-info/
|
|
42
|
+
.pytest_cache/
|
|
43
|
+
.mypy_cache/
|
|
44
|
+
.ruff_cache/
|
|
45
|
+
.venv/
|
|
46
|
+
venv/
|
|
47
|
+
|
|
48
|
+
# Node/JavaScript
|
|
49
|
+
node_modules/
|
|
50
|
+
|
|
51
|
+
# Local reference repositories (not part of yld source)
|
|
52
|
+
geomat/
|
|
53
|
+
|
|
54
|
+
# Local research/output scratch
|
|
55
|
+
*.log
|
|
56
|
+
*.tmp
|
|
57
|
+
*.bak
|
|
58
|
+
#
|
|
59
|
+
# Curated experiment evidence is the exception. Logs belong under `build/` during a run, but the
|
|
60
|
+
# experiment tooling deliberately records some of them under `experiments/<key>/evidence/`, and a
|
|
61
|
+
# `--evidence` copy lands there explicitly. Ignoring those loses part of the record.
|
|
62
|
+
!experiments/*/evidence/*.log
|
|
63
|
+
!experiments/*/evidence/**/*.log
|
|
64
|
+
|
|
65
|
+
# yld-ui (Wails v3 host + Svelte SPA)
|
|
66
|
+
#
|
|
67
|
+
# The Wails project directory is `yld-ui/`. Its `build/` directory holds the Taskfiles, `config.yml`,
|
|
68
|
+
# per-platform tasks and the app icon as *source*, so it is tracked; only what Wails generates there
|
|
69
|
+
# is ignored. Paths below are taken from the Wails build assets, not guessed.
|
|
70
|
+
/yld-ui/build/bin/
|
|
71
|
+
/yld-ui/build/darwin/icons.icns
|
|
72
|
+
/yld-ui/build/darwin/Assets.car
|
|
73
|
+
/yld-ui/build/windows/icon.ico
|
|
74
|
+
/yld-ui/build/ios/DerivedData/
|
|
75
|
+
/yld-ui/build/ios/xcode/
|
|
76
|
+
# The Vite output. Embedded into the Go binary at compile time by `//go:embed all:frontend/dist`,
|
|
77
|
+
# and regenerated by `task build:frontend`, so it is never committed.
|
|
78
|
+
/yld-ui/frontend/dist/
|
|
79
|
+
# Playwright artefacts from the browser checks (`npm run e2e`). The specs and helpers under
|
|
80
|
+
# `frontend/e2e/` are source and stay tracked.
|
|
81
|
+
/yld-ui/frontend/test-results/
|
|
82
|
+
/yld-ui/frontend/playwright-report/
|
|
83
|
+
/yld-ui/frontend/blob-report/
|
|
84
|
+
# There is deliberately no rule for `frontend/bindings/`: no native Wails bindings are ever
|
|
85
|
+
# generated (see architecture/DECISIONS.md), so an accidental bindings directory must show up as
|
|
86
|
+
# untracked noise rather than be silently ignored.
|
yld_run-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sam Stanier
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
yld_run-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: yld.run
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: yld: programmatic problem authoring, solve requests and canonical `.yld` results.
|
|
5
|
+
License: MIT License
|
|
6
|
+
|
|
7
|
+
Copyright (c) 2026 Sam Stanier
|
|
8
|
+
|
|
9
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
10
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
11
|
+
in the Software without restriction, including without limitation the rights
|
|
12
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
13
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
14
|
+
furnished to do so, subject to the following conditions:
|
|
15
|
+
|
|
16
|
+
The above copyright notice and this permission notice shall be included in all
|
|
17
|
+
copies or substantial portions of the Software.
|
|
18
|
+
|
|
19
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
20
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
21
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
22
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
23
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
24
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
25
|
+
SOFTWARE.
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
28
|
+
Classifier: Operating System :: OS Independent
|
|
29
|
+
Classifier: Programming Language :: Python :: 3
|
|
30
|
+
Requires-Python: >=3.10
|
|
31
|
+
Provides-Extra: view
|
|
32
|
+
Requires-Dist: pyvista>=0.43; extra == 'view'
|
|
33
|
+
Description-Content-Type: text/markdown
|
|
34
|
+
|
|
35
|
+
# yld
|
|
36
|
+
|
|
37
|
+
`yld` is pronounced “yield”.
|
|
38
|
+
|
|
39
|
+
This is a private research project for a programmatic computational mechanics toolkit. The name
|
|
40
|
+
reflects both mechanical yielding and the idea that the toolkit yields results.
|
|
41
|
+
|
|
42
|
+
## Two packages
|
|
43
|
+
|
|
44
|
+
`yld` is delivered as two independently installable Python packages, and the split is a licence and
|
|
45
|
+
distribution boundary, not a convenience (`architecture/PLATFORM.md` §9):
|
|
46
|
+
|
|
47
|
+
| package | licence | distributed | contents |
|
|
48
|
+
|---|---|---|---|
|
|
49
|
+
| **`yld`** | MIT | yes | problem authoring, materials and spatial fields as declarations, the solve-request document, the execution client, the archive reader and the PyVista viewer. Pure Python: no native module, no mandatory dependency. |
|
|
50
|
+
| **`yld_core`** | proprietary | **no** | constitutive binding, meshing, assembly, the conic solve, adaptation, independent verification, field evaluation and archive writing, through one compiled extension (`yld_core._native`). |
|
|
51
|
+
|
|
52
|
+
A problem is authored and a solve is requested with `yld` alone; a numerical installation is
|
|
53
|
+
configured explicitly and is the only part that executes anything:
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
import yld, yld_core
|
|
57
|
+
yld.use_executor(yld_core.NativeExecutor()) # explicit; no discovery, no environment variables
|
|
58
|
+
|
|
59
|
+
result = yld.solve(problem, yld.FELA_LB_Solver(order=3),
|
|
60
|
+
target=yld.Target.strength(), adapt=[yld.adapt.p(order=3)])
|
|
61
|
+
result.multiplier, result.verified # from the canonical `.yld` archive
|
|
62
|
+
result.save("analysis.yld"); result.show("cohesion")
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`solve()` always submits a canonical `yld.solve-request/1` document to the configured executor and
|
|
66
|
+
always returns the same archive-backed result, so a local run and a service run are indistinguishable
|
|
67
|
+
to the caller. With nothing configured it raises `yld.NoExecutorError` rather than choosing a
|
|
68
|
+
backend.
|
|
69
|
+
|
|
70
|
+
Build both artefacts (the private one only for a local numerical installation):
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
tools/yld-package public --out-dir build/dist # yld-<version>-py3-none-any.whl + sdist
|
|
74
|
+
tools/yld-package private --out-dir build/dist # yld_core-<version>-<platform>.whl
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
`tests/python/distribution_content_tests.py` builds and inspects the public artefacts (a positive
|
|
78
|
+
allowlist: no C++ sources, no native binaries, no experiments, no private modules), and
|
|
79
|
+
`tests/python/distribution_install_tests.py` installs each into a clean environment and checks what
|
|
80
|
+
it can and cannot do.
|
|
81
|
+
|
|
82
|
+
## Default production build
|
|
83
|
+
|
|
84
|
+
Use the CMake preset so build artefacts stay under `build/dev`. The `dev` preset is intentionally the default production-solver build: `Release`, Python enabled, experiments disabled. CMake obtains Eigen 3.4.0 and Catch2 v3.8.1 through pinned `FetchContent`; no system Eigen/Catch2 path is required for the normal development build.
|
|
85
|
+
|
|
86
|
+
System prerequisites: a C++20 compiler, CMake ≥ 3.20, Ninja or Make, **clang-format 21.1.8** (the pinned
|
|
87
|
+
version CI installs, because `code_format` is a test and its verdict must not depend on the image), Python 3 with development headers and `uv` (the test suite runs Python oracles
|
|
88
|
+
through `uv`), a Rust toolchain (Clarabel.cpp builds its Rust backend), and **header-only Boost**
|
|
89
|
+
(`libboost-dev`) for the exact geometric predicates in `yld_mesh`.
|
|
90
|
+
|
|
91
|
+
Canonical verification goes through the shared build/test wrappers, which bound memory on the
|
|
92
|
+
workstation (see `AGENTS.md`, "Build discipline"):
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
tools/yld-build --preset dev
|
|
96
|
+
tools/yld-test --preset dev
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
For a stale or missing configure, refresh the cache first — `cmake --fresh --preset dev` — then
|
|
100
|
+
build and test through the wrappers again.
|
|
101
|
+
|
|
102
|
+
If dependency discovery or cache state gets stale, refresh the cache with `cmake --fresh --preset dev` rather than manually deleting the build tree.
|
|
103
|
+
|
|
104
|
+
Debug builds are opt-in only:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
cmake --fresh --preset debug
|
|
108
|
+
tools/yld-build --preset debug
|
|
109
|
+
tools/yld-test --preset debug
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
The compiled extension is written **inside the private package** (`yld_core/_native*.so`) rather than
|
|
113
|
+
into a build directory, because that is where an extension module has to be to be importable: a
|
|
114
|
+
package's `__path__` is its own directory. One checkout therefore has one native extension — rebuild
|
|
115
|
+
for the preset you are testing. No `PYTHONPATH` entry is needed to import it.
|
|
116
|
+
|
|
117
|
+
Do not use the debug preset for solver performance, FELA regression timing, or ordinary commit validation.
|
|
118
|
+
|
|
119
|
+
## Examples
|
|
120
|
+
|
|
121
|
+
`examples/ben_cutting_slope.ipynb` is an executable introduction to slope limit analysis through
|
|
122
|
+
the public Python API: gravity and strength-reduction targets, Bernstein lower and upper bounds
|
|
123
|
+
with independent verification, adaptation recipes, and deterministic and random spatial strength
|
|
124
|
+
fields. See `examples/README.md` for launch instructions.
|
|
125
|
+
|
|
126
|
+
## Testing
|
|
127
|
+
|
|
128
|
+
Routine development tests only the area a change touches. Catch2 tags and `ctest -R` are the
|
|
129
|
+
normal entry points:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
# one whole test binary
|
|
133
|
+
./build/dev/tests/yld_mechanics_tests
|
|
134
|
+
|
|
135
|
+
# a Catch2 tag, e.g. the model just changed
|
|
136
|
+
./build/dev/tests/yld_mechanics_tests "[mohr_coulomb]"
|
|
137
|
+
|
|
138
|
+
# ctest tests selected by name
|
|
139
|
+
tools/yld-test --preset dev -R "mohr_coulomb|code_format"
|
|
140
|
+
|
|
141
|
+
# the Python suite only
|
|
142
|
+
tools/yld-test --preset dev -R "^python_|^bezier_member_vtk$|^parameter_archive_visualisation$"
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
The complete `tools/yld-test --preset dev` suite includes MFEM/Python integration tests and takes
|
|
146
|
+
about four minutes. It is **not** the commit gate: it runs in CI (`.github/workflows/ci.yml`) on every
|
|
147
|
+
push to `main` and on pull requests, against the production Release solver path.
|
|
148
|
+
|
|
149
|
+
The local commit hook is deliberately fast, because a slow hook teaches people to use
|
|
150
|
+
`--no-verify`:
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
git config core.hooksPath .githooks # one-time setup
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
`.githooks/pre-commit` checks only what needs the working tree or is commit-specific —
|
|
157
|
+
`clang-format` on staged C++ files, a 5 MB per-file size guard against bulk artefacts, validation of
|
|
158
|
+
any staged experiment record, and a private-key scan. Bypass for work-in-progress commits with
|
|
159
|
+
`YLD_SKIP_HOOKS=1 git commit ...`.
|
|
160
|
+
|
|
161
|
+
Run the full suite locally before a substantial push, or when CI is unavailable:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
tools/yld-test --preset dev
|
|
165
|
+
```
|
yld_run-0.1.0/README.md
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# yld
|
|
2
|
+
|
|
3
|
+
`yld` is pronounced “yield”.
|
|
4
|
+
|
|
5
|
+
This is a private research project for a programmatic computational mechanics toolkit. The name
|
|
6
|
+
reflects both mechanical yielding and the idea that the toolkit yields results.
|
|
7
|
+
|
|
8
|
+
## Two packages
|
|
9
|
+
|
|
10
|
+
`yld` is delivered as two independently installable Python packages, and the split is a licence and
|
|
11
|
+
distribution boundary, not a convenience (`architecture/PLATFORM.md` §9):
|
|
12
|
+
|
|
13
|
+
| package | licence | distributed | contents |
|
|
14
|
+
|---|---|---|---|
|
|
15
|
+
| **`yld`** | MIT | yes | problem authoring, materials and spatial fields as declarations, the solve-request document, the execution client, the archive reader and the PyVista viewer. Pure Python: no native module, no mandatory dependency. |
|
|
16
|
+
| **`yld_core`** | proprietary | **no** | constitutive binding, meshing, assembly, the conic solve, adaptation, independent verification, field evaluation and archive writing, through one compiled extension (`yld_core._native`). |
|
|
17
|
+
|
|
18
|
+
A problem is authored and a solve is requested with `yld` alone; a numerical installation is
|
|
19
|
+
configured explicitly and is the only part that executes anything:
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
import yld, yld_core
|
|
23
|
+
yld.use_executor(yld_core.NativeExecutor()) # explicit; no discovery, no environment variables
|
|
24
|
+
|
|
25
|
+
result = yld.solve(problem, yld.FELA_LB_Solver(order=3),
|
|
26
|
+
target=yld.Target.strength(), adapt=[yld.adapt.p(order=3)])
|
|
27
|
+
result.multiplier, result.verified # from the canonical `.yld` archive
|
|
28
|
+
result.save("analysis.yld"); result.show("cohesion")
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
`solve()` always submits a canonical `yld.solve-request/1` document to the configured executor and
|
|
32
|
+
always returns the same archive-backed result, so a local run and a service run are indistinguishable
|
|
33
|
+
to the caller. With nothing configured it raises `yld.NoExecutorError` rather than choosing a
|
|
34
|
+
backend.
|
|
35
|
+
|
|
36
|
+
Build both artefacts (the private one only for a local numerical installation):
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
tools/yld-package public --out-dir build/dist # yld-<version>-py3-none-any.whl + sdist
|
|
40
|
+
tools/yld-package private --out-dir build/dist # yld_core-<version>-<platform>.whl
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`tests/python/distribution_content_tests.py` builds and inspects the public artefacts (a positive
|
|
44
|
+
allowlist: no C++ sources, no native binaries, no experiments, no private modules), and
|
|
45
|
+
`tests/python/distribution_install_tests.py` installs each into a clean environment and checks what
|
|
46
|
+
it can and cannot do.
|
|
47
|
+
|
|
48
|
+
## Default production build
|
|
49
|
+
|
|
50
|
+
Use the CMake preset so build artefacts stay under `build/dev`. The `dev` preset is intentionally the default production-solver build: `Release`, Python enabled, experiments disabled. CMake obtains Eigen 3.4.0 and Catch2 v3.8.1 through pinned `FetchContent`; no system Eigen/Catch2 path is required for the normal development build.
|
|
51
|
+
|
|
52
|
+
System prerequisites: a C++20 compiler, CMake ≥ 3.20, Ninja or Make, **clang-format 21.1.8** (the pinned
|
|
53
|
+
version CI installs, because `code_format` is a test and its verdict must not depend on the image), Python 3 with development headers and `uv` (the test suite runs Python oracles
|
|
54
|
+
through `uv`), a Rust toolchain (Clarabel.cpp builds its Rust backend), and **header-only Boost**
|
|
55
|
+
(`libboost-dev`) for the exact geometric predicates in `yld_mesh`.
|
|
56
|
+
|
|
57
|
+
Canonical verification goes through the shared build/test wrappers, which bound memory on the
|
|
58
|
+
workstation (see `AGENTS.md`, "Build discipline"):
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
tools/yld-build --preset dev
|
|
62
|
+
tools/yld-test --preset dev
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
For a stale or missing configure, refresh the cache first — `cmake --fresh --preset dev` — then
|
|
66
|
+
build and test through the wrappers again.
|
|
67
|
+
|
|
68
|
+
If dependency discovery or cache state gets stale, refresh the cache with `cmake --fresh --preset dev` rather than manually deleting the build tree.
|
|
69
|
+
|
|
70
|
+
Debug builds are opt-in only:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
cmake --fresh --preset debug
|
|
74
|
+
tools/yld-build --preset debug
|
|
75
|
+
tools/yld-test --preset debug
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The compiled extension is written **inside the private package** (`yld_core/_native*.so`) rather than
|
|
79
|
+
into a build directory, because that is where an extension module has to be to be importable: a
|
|
80
|
+
package's `__path__` is its own directory. One checkout therefore has one native extension — rebuild
|
|
81
|
+
for the preset you are testing. No `PYTHONPATH` entry is needed to import it.
|
|
82
|
+
|
|
83
|
+
Do not use the debug preset for solver performance, FELA regression timing, or ordinary commit validation.
|
|
84
|
+
|
|
85
|
+
## Examples
|
|
86
|
+
|
|
87
|
+
`examples/ben_cutting_slope.ipynb` is an executable introduction to slope limit analysis through
|
|
88
|
+
the public Python API: gravity and strength-reduction targets, Bernstein lower and upper bounds
|
|
89
|
+
with independent verification, adaptation recipes, and deterministic and random spatial strength
|
|
90
|
+
fields. See `examples/README.md` for launch instructions.
|
|
91
|
+
|
|
92
|
+
## Testing
|
|
93
|
+
|
|
94
|
+
Routine development tests only the area a change touches. Catch2 tags and `ctest -R` are the
|
|
95
|
+
normal entry points:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
# one whole test binary
|
|
99
|
+
./build/dev/tests/yld_mechanics_tests
|
|
100
|
+
|
|
101
|
+
# a Catch2 tag, e.g. the model just changed
|
|
102
|
+
./build/dev/tests/yld_mechanics_tests "[mohr_coulomb]"
|
|
103
|
+
|
|
104
|
+
# ctest tests selected by name
|
|
105
|
+
tools/yld-test --preset dev -R "mohr_coulomb|code_format"
|
|
106
|
+
|
|
107
|
+
# the Python suite only
|
|
108
|
+
tools/yld-test --preset dev -R "^python_|^bezier_member_vtk$|^parameter_archive_visualisation$"
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
The complete `tools/yld-test --preset dev` suite includes MFEM/Python integration tests and takes
|
|
112
|
+
about four minutes. It is **not** the commit gate: it runs in CI (`.github/workflows/ci.yml`) on every
|
|
113
|
+
push to `main` and on pull requests, against the production Release solver path.
|
|
114
|
+
|
|
115
|
+
The local commit hook is deliberately fast, because a slow hook teaches people to use
|
|
116
|
+
`--no-verify`:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
git config core.hooksPath .githooks # one-time setup
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
`.githooks/pre-commit` checks only what needs the working tree or is commit-specific —
|
|
123
|
+
`clang-format` on staged C++ files, a 5 MB per-file size guard against bulk artefacts, validation of
|
|
124
|
+
any staged experiment record, and a private-key scan. Bypass for work-in-progress commits with
|
|
125
|
+
`YLD_SKIP_HOOKS=1 git commit ...`.
|
|
126
|
+
|
|
127
|
+
Run the full suite locally before a substantial push, or when CI is unavailable:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
tools/yld-test --preset dev
|
|
131
|
+
```
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
# The distribution name and the import namespace are different things here, deliberately: the
|
|
7
|
+
# package is published as `yld.run`, while `import yld` stays what it has always been. There is no
|
|
8
|
+
# alias package and no second import name.
|
|
9
|
+
name = "yld.run"
|
|
10
|
+
version = "0.1.0"
|
|
11
|
+
description = "yld: programmatic problem authoring, solve requests and canonical `.yld` results."
|
|
12
|
+
readme = "README.md"
|
|
13
|
+
requires-python = ">=3.10"
|
|
14
|
+
license = { file = "LICENSE" }
|
|
15
|
+
# The public distribution is pure Python by construction: authoring, the solve-request document, the
|
|
16
|
+
# archive reader and the PyVista viewer. Native execution lives in the separately distributed
|
|
17
|
+
# `yld-core` package, which is never a dependency of this one.
|
|
18
|
+
dependencies = []
|
|
19
|
+
classifiers = [
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"License :: OSI Approved :: MIT License",
|
|
22
|
+
"Operating System :: OS Independent",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
[project.optional-dependencies]
|
|
26
|
+
# Visualisation only: `ArchivedResult.show()` needs PyVista. Authoring, encoding, decoding and
|
|
27
|
+
# archive reading work without it.
|
|
28
|
+
view = ["pyvista>=0.43"]
|
|
29
|
+
|
|
30
|
+
[tool.hatch.build.targets.wheel]
|
|
31
|
+
packages = ["yld"]
|
|
32
|
+
|
|
33
|
+
# --------------------------------------------------------------------------------------------------
|
|
34
|
+
# The public distribution is a positive allowlist, not an exclusion list.
|
|
35
|
+
#
|
|
36
|
+
# The repository also holds the proprietary native core, internal experiments, agent configuration
|
|
37
|
+
# and research notes. An sdist built from the repository root used to include all of it -- including
|
|
38
|
+
# the C++ source tree -- because that is the hatchling default. Only what is listed here ships, so a
|
|
39
|
+
# new file elsewhere in the repository cannot leak into a public artefact by being forgotten.
|
|
40
|
+
#
|
|
41
|
+
# `tests/python/distribution_content_tests.py` builds both artefacts and asserts this list.
|
|
42
|
+
# --------------------------------------------------------------------------------------------------
|
|
43
|
+
[tool.hatch.build.targets.sdist]
|
|
44
|
+
only-include = [
|
|
45
|
+
"yld",
|
|
46
|
+
"pyproject.toml",
|
|
47
|
+
"README.md",
|
|
48
|
+
"LICENSE",
|
|
49
|
+
]
|
|
50
|
+
exclude = [
|
|
51
|
+
"**/__pycache__",
|
|
52
|
+
"**/*.py[cod]",
|
|
53
|
+
]
|
|
54
|
+
# Hatchling force-includes the VCS exclusion file into every sdist, and a force-include wins over
|
|
55
|
+
# `exclude`. `.gitignore` therefore appears in the sdist; it is a public repository file and
|
|
56
|
+
# `distribution_content_tests.py` pins it to this repository's own copy.
|
|
57
|
+
|
|
58
|
+
[tool.hatch.build.targets.wheel.force-include]
|
|
59
|
+
"LICENSE" = "yld/LICENSE"
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""The public `yld` package: authoring, solve requests, execution client and archive results.
|
|
2
|
+
|
|
3
|
+
This package is **pure Python by construction**. It states problems, materials, spatial fields,
|
|
4
|
+
targets and adaptation recipes; encodes the canonical solve request; submits it to an explicitly
|
|
5
|
+
configured executor; and reads the canonical `.yld` archive the executor returns, including the
|
|
6
|
+
material-parameter fields the analysis actually assembled. It imports no native module, has no
|
|
7
|
+
private dependency, and needs no compiler, CMake or nightly build variable to install or run.
|
|
8
|
+
|
|
9
|
+
Numerical execution — meshing, assembly, the conic solve, adaptation, independent verification and
|
|
10
|
+
archive writing — lives in the proprietary `yld_core` package, which is configured explicitly:
|
|
11
|
+
|
|
12
|
+
import yld, yld_core
|
|
13
|
+
yld.use_executor(yld_core.NativeExecutor())
|
|
14
|
+
|
|
15
|
+
problem = yld.Problem("prandtl")
|
|
16
|
+
... author ...
|
|
17
|
+
|
|
18
|
+
result = yld.solve(problem, yld.FELA_LB_Solver(points=1200, order=3),
|
|
19
|
+
target=yld.Target.strength(), adapt=[yld.adapt.p(order=3)])
|
|
20
|
+
result.multiplier, result.verified
|
|
21
|
+
|
|
22
|
+
Without a configured executor, `yld.solve()` refuses with `yld.NoExecutorError`; there is no default
|
|
23
|
+
executor, no discovery and no environment-variable backend switching.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
from __future__ import annotations
|
|
27
|
+
|
|
28
|
+
from . import adapt, archive, bounds, edit, outputs, solve_request
|
|
29
|
+
from .archive import ArchivedResult, open_yld
|
|
30
|
+
from .execution import Executor, NoExecutorError, solve, use_executor
|
|
31
|
+
from .outputs import Output
|
|
32
|
+
from .problem import (
|
|
33
|
+
BondedInterface,
|
|
34
|
+
ConstantField,
|
|
35
|
+
Field,
|
|
36
|
+
Interface,
|
|
37
|
+
LinearField,
|
|
38
|
+
Map,
|
|
39
|
+
MeshFeature,
|
|
40
|
+
MohrCoulomb,
|
|
41
|
+
Problem,
|
|
42
|
+
ProblemLoad,
|
|
43
|
+
Random,
|
|
44
|
+
RigidBody,
|
|
45
|
+
SmoothInterface,
|
|
46
|
+
SplineField,
|
|
47
|
+
Tresca,
|
|
48
|
+
)
|
|
49
|
+
from .solvers import FELA_LB_Solver, FELA_UB_Solver
|
|
50
|
+
from .targets import Target
|
|
51
|
+
|
|
52
|
+
__all__ = [
|
|
53
|
+
"ArchivedResult",
|
|
54
|
+
"BondedInterface",
|
|
55
|
+
"ConstantField",
|
|
56
|
+
"Executor",
|
|
57
|
+
"FELA_LB_Solver",
|
|
58
|
+
"FELA_UB_Solver",
|
|
59
|
+
"Field",
|
|
60
|
+
"Interface",
|
|
61
|
+
"LinearField",
|
|
62
|
+
"Map",
|
|
63
|
+
"MeshFeature",
|
|
64
|
+
"MohrCoulomb",
|
|
65
|
+
"NoExecutorError",
|
|
66
|
+
"Output",
|
|
67
|
+
"Problem",
|
|
68
|
+
"ProblemLoad",
|
|
69
|
+
"Random",
|
|
70
|
+
"RigidBody",
|
|
71
|
+
"SmoothInterface",
|
|
72
|
+
"SplineField",
|
|
73
|
+
"Target",
|
|
74
|
+
"Tresca",
|
|
75
|
+
"adapt",
|
|
76
|
+
"archive",
|
|
77
|
+
"bounds",
|
|
78
|
+
"edit",
|
|
79
|
+
"open_yld",
|
|
80
|
+
"outputs",
|
|
81
|
+
"solve",
|
|
82
|
+
"solve_request",
|
|
83
|
+
"use_executor",
|
|
84
|
+
]
|