diff --git a/README.md b/README.md index 79d3d8b..e11e12d 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ > models from LaTeX; don't hand-code what the compiler should generate.** πŸ“– **New here? Start with the [documentation](docs/index.md)** β€” +[Installation](docs/installation.md) Β· [Getting started](docs/mechdsl-core/getting-started.md) Β· [Core concepts](docs/mechdsl-core/concepts.md) Β· [LaTeX directive reference](docs/mechdsl-core/latex-directives.md) Β· @@ -38,9 +39,17 @@ viscoplasticity, and Lemaitre continuum damage. Backends: Taichi (MVP-stable), M [`mechdsl-workbench`](https://github.com/CEmM2/mechdsl-workbench) is a companion browser workbench: LaTeX on the left, the compiled mechanics or transpiled -algorithm on the right. It installs this repository's packages at a pinned -release and is the fastest way to try the language before committing to the -pipeline documentation. +algorithm on the right. It is the fastest way to try the language before +committing to the pipeline documentation. + +```bash +pip install "mechdsl-workbench[mechdsl]" # workbench + the MechDSL engine +mechdsl-workbench # then open http://127.0.0.1:8000 +``` + +The `[mechdsl]` extra pulls `mechdsl-core[verify]` and `algo2code` from PyPI. The +workbench pins Python 3.12 (`>=3.12,<3.13`), narrower than this repository's +`>=3.11,<3.14`. See [the workbench docs page](docs/workbench.md). ## Installation @@ -265,11 +274,14 @@ User-facing documentation lives in [`docs/`](docs/) and is built as a | Page | What it covers | |------|----------------| | [Home](docs/index.md) | What MechDSL is and why to use it | -| [Getting started](docs/mechdsl-core/getting-started.md) | Install with `uv`, first solver, `.tex` and energy-derived inputs | +| [Installation](docs/installation.md) | Every package and extra on PyPI, plus the from-source `uv` workflow | +| [Getting started](docs/mechdsl-core/getting-started.md) | `pip install`, first solver, `.tex` and energy-derived inputs | | [Core concepts](docs/mechdsl-core/concepts.md) | LaTeX-first idea, six-layer pipeline, hyperelastic vs. dissipative, support tiers | | [LaTeX directive reference](docs/mechdsl-core/latex-directives.md) | Every `% mechanics` directive with examples | | [Constitutive models](docs/mechdsl-core/constitutive-models.md) | Model catalog with runnable snippets | | [Algorithm transpiler (algo2code)](docs/algo2code/index.md) | How return-maps/PCG are transpiled from `algpseudocode` | +| [ti-runtime](docs/ti-runtime/index.md) | The neutral Taichi runtime: seams, primitives, and the operator contract | +| [Browser workbench](docs/workbench.md) | Installing and running the companion browser app | | [Examples gallery](docs/mechdsl-core/examples.md) | Cantilever, Cook's membrane, necking bar, patch test, cyclic plasticity | | [How it works](docs/reference/architecture.md) | Layers, IR discipline, determinism, verification | | [FAQ & troubleshooting](docs/reference/faq.md) | Common questions and fixes | diff --git a/docs/algo2code/getting-started.md b/docs/algo2code/getting-started.md index 617c79e..cd73d46 100644 --- a/docs/algo2code/getting-started.md +++ b/docs/algo2code/getting-started.md @@ -1,27 +1,43 @@ # Getting started -This page takes you from a fresh clone to a transpiled algorithm. +This page takes you from an empty environment to a transpiled algorithm. -## Prerequisites +## Install -`algo2code` is part of the MechDSL [uv](https://docs.astral.sh/uv/) workspace, so the -simplest way to get it is the workspace install: +`algo2code` is on PyPI and installs on its own β€” you do not need `mechdsl-core`, and +you do not need the monorepo: ```bash -git clone https://github.com/CEmM2/MechDSL.git -cd MechDSL -uv sync --all-packages --all-groups --all-extras +pip install algo2code ``` +It requires Python 3.11, 3.12, or 3.13 (`requires-python = ">=3.11,<3.14"`) and +nothing else. + !!! tip "Zero runtime dependencies" - `algo2code` is **standard-library only** β€” it imports nothing at runtime beyond the - Python stdlib, and it never imports `mechdsl`. That means the package directory + `algo2code` is **standard-library only** β€” its `dependencies` list is literally + empty, it imports nothing at runtime beyond the Python stdlib, and it never imports + `mechdsl`. That also means the package directory (`packages/algo2code/src/algo2code/`) is self-contained and can be vendored into another project by copying it, with no dependency footprint. -!!! warning "Always go through `uv run`" - Never call `python` or `pytest` directly inside the workspace β€” prefix every command - with `uv run` so it uses the project's locked environment. +`algo2code` also arrives automatically with `pip install "mechdsl-core[verify]"`, since +the full engine uses it to generate the matrix-free PCG solver. + +??? note "Installing from source instead" + `algo2code` is one of the three packages in the MechDSL + [uv](https://docs.astral.sh/uv/) workspace. For the test suite or to contribute: + + ```bash + git clone https://github.com/CEmM2/MechDSL.git + cd MechDSL + uv sync --all-packages --all-groups --all-extras + ``` + + Inside a source checkout, never call `python` or `pytest` directly β€” prefix every + command with `uv run` so it uses the project's locked environment. + +See [Installation](../installation.md) for the full matrix across all packages. ## Your first transpile @@ -38,7 +54,7 @@ print(code) # Taichi-compatible Python source, as text Run it: ```bash -uv run python first_algo.py +python first_algo.py ``` ### What just happened @@ -77,3 +93,5 @@ radial_return_j2 = ns["radial_return_j2"] # now a real callable how the transpiled code is wired into the mechdsl-core solver. - [Examples](examples.md) β€” runnable snippets for the J2 return-map family and the PCG solver. +- [Browser workbench](../workbench.md) β€” paste an `algorithmic` block into a pane and + read the generated Taichi next to it. diff --git a/docs/algo2code/index.md b/docs/algo2code/index.md index e376bb3..f1ed493 100644 --- a/docs/algo2code/index.md +++ b/docs/algo2code/index.md @@ -9,6 +9,12 @@ It is deliberately tiny: **zero runtime dependencies** (stdlib only), and it nev `mechdsl`. The relationship is strict producer/consumer β€” mechdsl-core consumes `algo2code`-generated artifacts, not the other way around. +It is on PyPI under the MIT license and installs standalone β€” no `mechdsl-core` needed: + +```bash +pip install algo2code +``` + --- ## Why a separate package @@ -47,7 +53,8 @@ The authoritative reference is `dev/design_docs/11-ALGO2CODE.md`.
-- :material-rocket-launch: **[Getting started](getting-started.md)** β€” install and transpile your first algorithm. +- :material-download: **[Installation](../installation.md)** β€” every package, extra, and the from-source workflow. +- :material-rocket-launch: **[Getting started](getting-started.md)** β€” `pip install`, then transpile your first algorithm. - :material-code-tags: **[Usage](usage.md)** β€” the `transpile` API, the algorithm library, and the solver seam. - :material-cards: **[Examples](examples.md)** β€” runnable transpile snippets for the J2 family and PCG. diff --git a/docs/assets/mechdsl-banner.webp b/docs/assets/mechdsl-banner.webp new file mode 100644 index 0000000..01878fa Binary files /dev/null and b/docs/assets/mechdsl-banner.webp differ diff --git a/docs/assets/mechdsl-mark.webp b/docs/assets/mechdsl-mark.webp new file mode 100644 index 0000000..96f47e5 Binary files /dev/null and b/docs/assets/mechdsl-mark.webp differ diff --git a/docs/index.md b/docs/index.md index e0d2022..decbc84 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,11 +1,13 @@ # MechDSL -**Write your mechanics in LaTeX. Get tested code back.** +![LaTeX goes in, GPU kernels come out.](assets/mechdsl-banner.webp){ .hero-banner } -MechDSL is a monorepo of two cooperating LaTeX-to-code compilers for computational solid -mechanics. You describe the math β€” a boundary-value problem, a strain-energy function, a -return-mapping algorithm β€” in an ordinary LaTeX document, and the toolchain emits -deterministic, tested [Taichi](https://www.taichi-lang.org/) solver code. +**Write your mechanics in LaTeX. Get a tested finite-element solver back.** + +MechDSL is a monorepo of LaTeX-to-code compilers for computational solid mechanics. You +describe the math β€” a boundary-value problem, a strain-energy function, a return-mapping +algorithm β€” in an ordinary LaTeX document, and the toolchain emits deterministic, tested +[Taichi](https://www.taichi-lang.org/) solver code. The same `.tex` file renders normally through `pdflatex` **and** is executable input to the compiler. Your paper's source can be your simulation's source. The guiding principle: @@ -14,7 +16,28 @@ the compiler. Your paper's source can be your simulation's source. The guiding p --- -## The two packages +## Install it + +Everything is on PyPI under the MIT license: + +```bash +pip install mechdsl-core # the compiler: LaTeX -> emitted solver source (Taichi-free) +pip install "mechdsl-core[verify]" # the full engine: run and verify solves +``` + +Or skip the scripting entirely and drive it from a browser: + +```bash +pip install "mechdsl-workbench[mechdsl]" +mechdsl-workbench # then open http://127.0.0.1:8000 +``` + +See [Installation](installation.md) for every package, extra, and the from-source +workflow. + +--- + +## The packages
@@ -26,6 +49,8 @@ the compiler. Your paper's source can be your simulation's source. The guiding p element kernels, deriving stress **S = βˆ‚Ξ¨/βˆ‚E** and tangent **C = βˆ‚Β²Ξ¨/βˆ‚EΒ²** symbolically. Six-layer pipeline, Total Lagrangian, Hex8, Taichi backend. + `pip install mechdsl-core` + [:octicons-arrow-right-24: Introduction](mechdsl-core/index.md) Β· [Getting started](mechdsl-core/getting-started.md) @@ -37,15 +62,43 @@ the compiler. Your paper's source can be your simulation's source. The guiding p the PCG solver β€” into executable code. Zero runtime dependencies. Consumed by mechdsl-core for everything that *isn't* a closed-form expression. + `pip install algo2code` + [:octicons-arrow-right-24: Introduction](algo2code/index.md) Β· [Getting started](algo2code/getting-started.md) +- :material-chip: **[ti-runtime](ti-runtime/index.md)** + + --- + + The neutral Taichi runtime. Vector primitives, Tier-1 `@ti.func` tensor helpers, and + the injection seams that generated bodies plug into. Generated code depends on this, + never on the compiler that produced it. + + `pip install ti-runtime` + + [:octicons-arrow-right-24: Introduction](ti-runtime/index.md) + +- :material-application-brackets: **[mechdsl-workbench](workbench.md)** + + --- + + The companion browser app: LaTeX on the left, compiled mechanics or transpiled + algorithm on the right. Lives in its own repository; the fastest way to try the + language before committing to the pipeline. + + `pip install "mechdsl-workbench[mechdsl]"` + + [:octicons-arrow-right-24: Browser workbench](workbench.md) +
-The relationship is strict producer/consumer: **mechdsl-core consumes algo2code-generated -artifacts**; algo2code is runtime-free and never imports `mechdsl`. Together they cover -both halves of a constitutive model β€” the closed-form energy (differentiated by -mechdsl-core) and the iterative algorithm (transpiled by algo2code). +The three monorepo packages have strict, one-way relationships. **mechdsl-core consumes +algo2code-generated artifacts**; algo2code is runtime-free and never imports `mechdsl`; +`ti-runtime` is what generated code lands on and never imports `mechdsl` either. Together +they cover both halves of a constitutive model β€” the closed-form energy (differentiated +by mechdsl-core) and the iterative algorithm (transpiled by algo2code) β€” plus the runtime +floor they both emit against. --- @@ -69,15 +122,20 @@ print(bundle.content_hash()) # deterministic β€” same input, same hash, ev ``` That call runs the full pipeline: parse the directives β†’ build the Mechanics IR β†’ -localise to an Element IR β†’ plan the tensor contractions β†’ emit Taichi. +localise to an Element IR β†’ plan the tensor contractions β†’ emit Taichi. It needs only the +base `pip install mechdsl-core` β€” no Taichi required to emit. --- ## Where to go next +- Just want it installed? **[Installation](installation.md)** covers PyPI, the extras, + and the `uv` source workflow. - New here? Start with the **[mechdsl-core introduction](mechdsl-core/index.md)** β€” it's the main package. - Want to run something? **[Getting started](mechdsl-core/getting-started.md)** takes you - from a fresh clone to a compiled solver bundle. + from a fresh install to a compiled solver bundle. +- Prefer clicking to typing? The **[browser workbench](workbench.md)** runs the same + compiler behind a UI. - Curious about the design? **[How it works](reference/architecture.md)** is a guided tour of the six layers, and the **[FAQ](reference/faq.md)** answers the common questions. diff --git a/docs/installation.md b/docs/installation.md new file mode 100644 index 0000000..4935ba6 --- /dev/null +++ b/docs/installation.md @@ -0,0 +1,127 @@ +# Installation + +Every MechDSL package is published on PyPI under the MIT license, so the fastest way +in is `pip install`. Installing from source with [uv](https://docs.astral.sh/uv/) is +the path for contributors and for anyone who wants the runnable `examples/` tree. + +!!! tip "In a hurry?" + `pip install "mechdsl-workbench[mechdsl]"` then `mechdsl-workbench` gives you the + whole toolchain behind a browser UI β€” LaTeX in the left pane, generated Taichi in + the right. See [the workbench page](workbench.md). + +## What's on PyPI + +| Install | What it gives you | +|---|---| +| `pip install mechdsl-core` | The FEM compiler: LaTeX β†’ emitted Taichi solver source. **Taichi-free.** ([PyPI](https://pypi.org/project/mechdsl-core/)) | +| `pip install "mechdsl-core[verify]"` | The full engine β€” adds `taichi`, `ti-runtime`, and `algo2code` so you can *run* and *verify* solves | +| `pip install algo2code` | The algorithm transpiler on its own. **Zero runtime dependencies**, stdlib only. ([PyPI](https://pypi.org/project/algo2code/)) | +| `pip install ti-runtime` | The neutral Taichi runtime: vector primitives, Tier-1 `@ti.func` helpers, injection seams. ([PyPI](https://pypi.org/project/ti-runtime/)) | +| `pip install "mechdsl-workbench[mechdsl]"` | The browser workbench plus the engine, in one command. ([PyPI](https://pypi.org/project/mechdsl-workbench/)) | + +All five are released together and currently sit at **0.2.1**. + +## Requirements + +- **Python 3.11–3.13** for `mechdsl-core`, `algo2code`, and `ti-runtime` + (`requires-python = ">=3.11,<3.14"`). +- **Python 3.12** for `mechdsl-workbench`, which pins `>=3.12,<3.13`. +- No compiler toolchain, no system FEM library. Taichi ships prebuilt wheels and + JIT-compiles to CPU or GPU at run time. + +## Install from PyPI + +### Just the compiler (lean, Taichi-free) + +```bash +pip install mechdsl-core +``` + +This is everything you need to **emit** code: parse `% mechanics` directives, derive +stress and tangent symbolically, plan contractions, and print Taichi source. It pulls +only `sympy`, `numpy`, `scipy`, `opt-einsum`, `pyyaml`, and `nrpylatex` β€” no Taichi, so +the install stays small and imports cleanly in Taichi-free environments. + +```python +from mechdsl import compile_latex + +bundle = compile_latex("% mechanics dim 3\n% mechanics cell hex8\n" + "% mechanics formulation total_lagrangian\n" + "% mechanics material svk --E 200e3 --nu 0.3\n") +print(bundle.content_hash()) +``` + +### The full engine (run and verify solves) + +```bash +pip install "mechdsl-core[verify]" +``` + +The `verify` extra adds `taichi`, `ti-runtime`, and `algo2code` β€” the complete +installation. Expect a noticeably larger download; Taichi alone is around 170 MB. +Take this one if you want to execute generated kernels, run the verification +harness, or use the generated matrix-free PCG solver. + +!!! info "Why the split?" + Only `mechdsl.integration.verify()` ever touches Taichi, and it imports it lazily + at call time. The emit, transpile, `capabilities()`, and `model_catalog()` + surfaces are proven Taichi-free by the test suite, so downstream consumers can + depend on `mechdsl-core` for code generation without pulling Taichi into their + dependency closure. + +### The satellite packages alone + +```bash +pip install algo2code # LaTeX algpseudocode -> executable code; stdlib-only +pip install ti-runtime # Taichi primitives + injection seams for generated code +``` + +`algo2code` never imports `mechdsl`, and `ti-runtime` never imports `mechdsl` either β€” +generated artifacts depend on `ti_runtime`, not on the compiler that produced them. Both +are usable standalone. + +## Install from source + +Use this if you want the `examples/` scripts, the test suite, or you intend to +contribute. The repository is a [uv](https://docs.astral.sh/uv/) workspace holding all +three monorepo packages. + +```bash +git clone https://github.com/CEmM2/MechDSL.git +cd MechDSL +uv sync --all-packages --all-groups --all-extras +``` + +Verify the install with the fast test tier: + +```bash +uv run pytest -m "not slow and not gpu" -q +``` + +!!! warning "Inside the workspace, always go through `uv run`" + Never call `python`, `pytest`, `ruff`, or `mypy` directly in a source checkout β€” + they may not be on your PATH or may pick up the wrong environment. Prefix every + project command with `uv run`. (This applies to the source workflow only; a + `pip install`ed MechDSL is an ordinary package in whatever environment you put it.) + +## Command-line entry points + +`mechdsl-core` installs one console script: + +```bash +mechdsl-lawgen --help # emit constitutive-law carriers for the ticonstit target +mechdsl-lawgen compile law.yaml # ...with --dry-run to print the plan and write nothing +``` + +`mechdsl-workbench` installs its own launcher β€” see [the workbench page](workbench.md). + +## Where to next + +
+ +- :material-rocket-launch: **[mechdsl-core getting started](mechdsl-core/getting-started.md)** β€” compile your first solver bundle. +- :material-cog-transfer: **[algo2code getting started](algo2code/getting-started.md)** β€” transpile your first algorithm. +- :material-application-brackets: **[Browser workbench](workbench.md)** β€” try the language without writing a script. +- :material-help-circle: **[FAQ & troubleshooting](reference/faq.md)** β€” when something doesn't install or run. + +
diff --git a/docs/mechdsl-core/examples.md b/docs/mechdsl-core/examples.md index 83ee898..5214cad 100644 --- a/docs/mechdsl-core/examples.md +++ b/docs/mechdsl-core/examples.md @@ -68,9 +68,11 @@ The J2 kinematic and mixed hardening models (`mechdsl.lib.plasticity_kinematic` `plasticity_mixed`) are exercised on a uniaxial **cyclic** load path (loading β†’ unloading β†’ reverse) in the test suite. The kinematic/mixed models re-yield in reverse *below* the forward yield magnitude β€” the Bauschinger effect β€” which the isotropic -model cannot reproduce. See -[`packages/mechdsl-core/tests/plan_tests/constitutive_latex/`](https://github.com/CEmM2/MechDSL/tree/main/packages/mechdsl-core/tests/plan_tests/constitutive_latex) -for the cyclic differential tests and the reduction cross-checks, and the +model cannot reproduce. The hand-written reference kernels that pin this behaviour are +[`ref_j2_kinematic.py`](https://github.com/CEmM2/MechDSL/blob/main/packages/mechdsl-core/tests/ref/ref_j2_kinematic.py) +and +[`ref_j2_mixed.py`](https://github.com/CEmM2/MechDSL/blob/main/packages/mechdsl-core/tests/ref/ref_j2_mixed.py); +see the [constitutive model catalog](constitutive-models.md#j2-plasticity-kinematic-prager-hardening) for the API. diff --git a/docs/mechdsl-core/getting-started.md b/docs/mechdsl-core/getting-started.md index 7c9a089..36ba5bd 100644 --- a/docs/mechdsl-core/getting-started.md +++ b/docs/mechdsl-core/getting-started.md @@ -1,35 +1,61 @@ # Getting started -This page takes you from a fresh clone to a compiled solver bundle. +This page takes you from an empty environment to a compiled solver bundle. ## Prerequisites -- **Python 3.12** (the workspace pins `>=3.12,<3.13`). -- **[uv](https://docs.astral.sh/uv/)** β€” the package/environment manager this project - uses. Install it with `curl -LsSf https://astral.sh/uv/install.sh | sh` or `brew install uv`. - -!!! warning "Always go through `uv run`" - Never call `python`, `pytest`, `ruff`, or `mypy` directly β€” they may not be on your - PATH or may pick up the wrong environment. Prefix every project command with - `uv run`. +- **Python 3.11, 3.12, or 3.13** β€” `mechdsl-core` declares + `requires-python = ">=3.11,<3.14"`. +- Nothing else. There is no compiler toolchain to set up and no system FEM library to + build; Taichi ships prebuilt wheels and is only needed if you want to *run* solves. ## Install +`mechdsl-core` is on PyPI, so the quickest start is one command: + ```bash -git clone https://github.com/CEmM2/MechDSL.git -cd MechDSL -uv sync --all-packages --all-groups --all-extras +pip install mechdsl-core ``` -`uv sync` installs both workspace packages (`mechdsl-core` and `algo2code`) and their -dependencies into a local `.venv`. +That is all you need for everything on this page: parsing directives, deriving +stress and tangent, and emitting Taichi source. It pulls no Taichi, so the install +stays small. -Verify the install by running the fast test suite: +If you want to **execute and verify** the code you generate, take the full engine +instead β€” it adds `taichi`, `ti-runtime`, and `algo2code`: ```bash -uv run pytest -m "not slow and not gpu" -q +pip install "mechdsl-core[verify]" ``` +??? note "Installing from source instead" + If you want the runnable `examples/` tree, the test suite, or you intend to + contribute, clone the [uv](https://docs.astral.sh/uv/) workspace: + + ```bash + git clone https://github.com/CEmM2/MechDSL.git + cd MechDSL + uv sync --all-packages --all-groups --all-extras + ``` + + `uv sync` installs all three workspace packages (`mechdsl-core`, `algo2code`, and + `ti-runtime`) and their dependencies into a local `.venv`. Inside a source + checkout, prefix **every** command with `uv run` β€” never call `python`, `pytest`, + `ruff`, or `mypy` directly, since they may not be on your PATH or may pick up the + wrong environment. Verify with the fast test tier: + + ```bash + uv run pytest -m "not slow and not gpu" -q + ``` + +The full install matrix β€” every package, every extra, the workbench β€” is on the +[Installation](../installation.md) page. + +!!! tip "The commands below" + Snippets on this page are written for a `pip install`ed MechDSL, so they call + `python` directly. In a **source checkout**, prefix them with `uv run` + (`uv run python first_run.py`). + ## Your first solver bundle The canonical entry point is `compile_latex`. Create a file `first_run.py`: @@ -54,11 +80,12 @@ print("content hash:", bundle.content_hash()) Run it: ```bash -uv run python first_run.py +python first_run.py ``` -A runnable copy of this lives at -[`examples/run_compile_latex.py`](https://github.com/CEmM2/MechDSL/blob/main/examples/run_compile_latex.py): +A runnable copy of this lives in the repository at +[`examples/run_compile_latex.py`](https://github.com/CEmM2/MechDSL/blob/main/examples/run_compile_latex.py), +so from a source checkout you can skip straight to: ```bash uv run python examples/run_compile_latex.py @@ -131,3 +158,5 @@ for the full list of derivable energies. - [LaTeX directive reference](latex-directives.md) β€” the complete directive grammar. - [Examples gallery](examples.md) β€” runnable benchmarks (Cook's membrane, necking bar, patch test, cyclic plasticity). +- [Browser workbench](../workbench.md) β€” the same compiler with a UI, if you'd rather + edit LaTeX in a pane than in a script. diff --git a/docs/mechdsl-core/index.md b/docs/mechdsl-core/index.md index 946831e..499d426 100644 --- a/docs/mechdsl-core/index.md +++ b/docs/mechdsl-core/index.md @@ -12,6 +12,13 @@ The same `.tex` file renders normally through `pdflatex` (the directives are LaT comments) **and** is executable input to the compiler. Your paper's source can be your simulation's source. +It is published on PyPI under the MIT license: + +```bash +pip install mechdsl-core # emit code β€” Taichi-free, small install +pip install "mechdsl-core[verify]" # the full engine β€” run and verify solves +``` + --- ## Why a colleague should care @@ -74,11 +81,14 @@ See the full [constitutive model catalog](constitutive-models.md) and the
-- :material-rocket-launch: **[Getting started](getting-started.md)** β€” install with `uv`, run your first solver in a few minutes. +- :material-download: **[Installation](../installation.md)** β€” every package, extra, and the from-source workflow. +- :material-rocket-launch: **[Getting started](getting-started.md)** β€” `pip install`, then your first solver in a few minutes. - :material-school: **[Core concepts](concepts.md)** β€” the LaTeX-first idea, the six-layer pipeline, and the support tiers. - :material-code-tags: **[LaTeX directive reference](latex-directives.md)** β€” every `% mechanics` directive, with examples. - :material-function-variant: **[Constitutive models](constitutive-models.md)** β€” the model catalog with runnable snippets. - :material-cards: **[Examples gallery](examples.md)** β€” cantilever, Cook's membrane, necking bar, patch test, cyclic plasticity. +- :material-chip: **[ti-runtime](../ti-runtime/index.md)** β€” the runtime the emitted kernels actually land on. +- :material-application-brackets: **[Browser workbench](../workbench.md)** β€” the same compiler, driven from a UI. - :material-help-circle: **[FAQ & troubleshooting](../reference/faq.md)** β€” common questions and fixes.
diff --git a/docs/reference/architecture.md b/docs/reference/architecture.md index 25fdd05..d06c4a0 100644 --- a/docs/reference/architecture.md +++ b/docs/reference/architecture.md @@ -22,6 +22,12 @@ representation. Information only ever flows downward, through the IRs. Supporting packages: `mechdsl.solver` (Newton driver + imported linear solver adapter) and `mechdsl.lib` (the Tier-1 `@ti.func` library and plasticity orchestration). +Beneath all of that sits [`ti-runtime`](../ti-runtime/index.md), the neutral Taichi +runtime that **generated** code lands on β€” vector primitives, Tier-1 `@ti.func` tensor +helpers, Hex8 shape gradients, and the injection seams. The direction matters: emitted +artifacts import `ti_runtime`, never `mechdsl`, so a generated kernel outlives the +compiler run that produced it. + ```text LaTeX ──▢ SymPy tensors ──▢ ProblemIR ──▢ ElementIR ──▢ EinsumIR ──▢ Taichi frontend symbolic lowering optimiser codegen @@ -70,6 +76,41 @@ The seam is the `LinearSolverInterface` protocol in `mechdsl.solver.import_adapt the Newton driver calls through. See [the algo2code page](../algo2code/index.md) for the full story, and `dev/design_docs/11-ALGO2CODE.md` for the authoritative reference. +## `mechdsl.integration` β€” the public faΓ§ade { #integration-facade } + +Everything above describes the machinery. Tools that *consume* MechDSL β€” the +[browser workbench](../workbench.md), downstream adapters, anything embedding the +compiler β€” should not reach into it. They call `mechdsl.integration`, the stable, +machine-readable Tier-1 surface, which is exactly five entry points: + +| Function | Returns | Needs Taichi? | +|---|---|---| +| `capabilities()` | A manifest: version, profiles, backends, actions, models | No | +| `model_catalog()` | Every constitutive model with tier, dissipative flag, params, state variables | No | +| `compile_from_sources(...)` | `{element_ir_summary, emitted_source, content_hash, derived_energy_present}` | No | +| `transpile_algorithm(algpseudocode, backend)` | `{code, entry_point, line_count, valid_python}` | No | +| `verify(kind, params)` | `{kind, passed, details}` | **Yes** | + +```python +from mechdsl.integration import capabilities, compile_from_sources + +caps = capabilities() +print(caps["taichi_required_for"]) # -> ["verify"] + +result = compile_from_sources(problem_source="% mechanics dim 3\n...") +print(result["content_hash"]) # 64-char sha-256 hex digest +``` + +**The Taichi-required-for contract:** `capabilities()` declares +`taichi_required_for: ["verify"]`. The other four entry points are guaranteed never to +trigger `ti.init`, so importing `mechdsl.integration` and calling them is safe in a +Taichi-free environment β€” which is why the base `pip install mechdsl-core` can leave +Taichi out entirely (see [Installation](../installation.md)). Only `verify()` pays the +Taichi cost, and it imports lazily at call time. + +This is a machine API contract, not a convenience library; entry points are not added to +it without a deliberate design decision. + ## Where to read more | Topic | Design doc | diff --git a/docs/reference/faq.md b/docs/reference/faq.md index 0584bdf..02a8528 100644 --- a/docs/reference/faq.md +++ b/docs/reference/faq.md @@ -2,6 +2,44 @@ ## Frequently asked +### How do I install it? Is it on PyPI? + +Yes β€” every package is published on PyPI under the MIT license, so `pip install` is the +normal way in: + +```bash +pip install mechdsl-core # the compiler, Taichi-free +pip install "mechdsl-core[verify]" # the full engine: run and verify solves +pip install algo2code # the transpiler alone, stdlib-only +pip install ti-runtime # the Taichi runtime alone +pip install "mechdsl-workbench[mechdsl]" # the browser workbench plus the engine +``` + +You do **not** need to clone the repository or install `uv` unless you want the +runnable `examples/` tree, the test suite, or to contribute. Full matrix on the +[Installation](../installation.md) page. + +### Why does the base install not include Taichi? + +Because only one entry point needs it. Emission, transpilation, `capabilities()`, and +`model_catalog()` are proven Taichi-free by the test suite; only +`mechdsl.integration.verify()` imports Taichi, and it does so lazily at call time. That +lets downstream consumers depend on `mechdsl-core` for code generation without pulling +Taichi's ~170 MB into their dependency closure. `pip install "mechdsl-core[verify]"` +when you actually want to run solves. + +### Which Python version do I need? + +`mechdsl-core`, `algo2code`, and `ti-runtime` accept **Python 3.11–3.13** +(`>=3.11,<3.14`). The `mechdsl-workbench` companion is narrower and pins **Python 3.12** +(`>=3.12,<3.13`). + +### Can I try it without writing any code? + +Yes. `pip install "mechdsl-workbench[mechdsl]"`, run `mechdsl-workbench`, and open + β€” LaTeX in the left pane, generated Taichi in the right. See +[the workbench page](../workbench.md). + ### Is this a replacement for Abaqus / ANSYS / a full FE package? No. MechDSL is a **compiler** that generates solver code from a LaTeX description of a @@ -58,13 +96,28 @@ numpy. See [the algo2code page](../algo2code/usage.md#how-the-j2-family-is-wired ### `command not found` / wrong package versions -You're probably calling `python`/`pytest`/`ruff` directly. Always prefix with `uv run`. -If the environment looks stale, re-sync: +**In a source checkout:** you're probably calling `python`/`pytest`/`ruff` directly. +Always prefix with `uv run`. If the environment looks stale, re-sync: ```bash uv sync --all-packages --all-groups --all-extras ``` +**With a `pip install`ed MechDSL:** check you're in the environment you installed into +(`python -c "import mechdsl; print(mechdsl.__file__)"`) and that the interpreter is +3.11–3.13. A `pip install` puts MechDSL in whatever environment `pip` points at, so a +virtualenv you forgot to activate is the usual culprit. + +### `ModuleNotFoundError: No module named 'taichi'` + +Expected on the base install β€” it is deliberately Taichi-free. Anything that *runs* +generated code (`mechdsl.integration.verify()`, the solver path, the `slow`/`gpu` tests) +needs the full engine: + +```bash +pip install "mechdsl-core[verify]" +``` + ### A construct raises "planned in phase ..." That's intentional. Unsupported constructs raise explicitly with the plan phase that adds diff --git a/docs/stylesheets/mechdsl.css b/docs/stylesheets/mechdsl.css new file mode 100644 index 0000000..faa21ee --- /dev/null +++ b/docs/stylesheets/mechdsl.css @@ -0,0 +1,744 @@ +/* ========================================================================== + MechDSL documentation theme + -------------------------------------------------------------------------- + Ports the sosovski.group site's sketchbook look (paper ground, hand-drawn + borders, hard offset shadows, Baloo 2 / Patrick Hand / Cabin Sketch) onto + MkDocs Material. Token names and values mirror GroupWebSite's + src/styles/global.css so the docs read as part of the same site. + ========================================================================== */ + +@import url('https://fonts.googleapis.com/css2?family=Cabin+Sketch:wght@700&family=Patrick+Hand&display=swap'); + +/* -------------------------------------------------------------------------- + 1. Tokens + -------------------------------------------------------------------------- */ + +:root, +[data-md-color-scheme="default"] { + --paper: #f7ead0; + --paper-2: #fff8e7; + --surface: #fffaf0; + --elev: #f0dfbd; + --ink: #2b2118; + --muted: #6d5b45; + --line: #9f744b; + --line-soft: rgba(159, 116, 75, 0.35); + --gold: #d8aa55; + --teal: #2f6f78; + --blue: #4e7d96; + --sage: #718a5d; + --rust: #a24d37; + --shadow: 5px 6px 0 rgba(43, 33, 24, 0.92); + --shadow-sm: 3px 4px 0 var(--ink); + --radius: 22px; + --font-hand: 'Patrick Hand', 'Baloo 2', system-ui, sans-serif; + --font-sketch: 'Cabin Sketch', 'Baloo 2', system-ui, sans-serif; + + /* Material bindings */ + --md-default-fg-color: var(--ink); + --md-default-fg-color--light: var(--muted); + --md-default-fg-color--lighter: rgba(109, 91, 69, 0.5); + --md-default-fg-color--lightest: var(--line-soft); + --md-default-bg-color: var(--paper-2); + --md-primary-fg-color: var(--paper); + --md-primary-bg-color: var(--ink); + --md-primary-bg-color--light: var(--muted); + --md-accent-fg-color: var(--rust); + --md-typeset-color: var(--ink); + --md-typeset-a-color: var(--teal); + --md-code-bg-color: #fdf3dd; + --md-code-fg-color: #3b2d20; + --md-footer-bg-color: var(--paper); + --md-footer-fg-color: var(--ink); + --md-shadow-z1: none; + --md-shadow-z2: none; + --md-shadow-z3: none; +} + +/* Night-desk variant: the same palette, inked rather than papered. */ +[data-md-color-scheme="slate"] { + --paper: #241c15; + --paper-2: #2e251c; + --surface: #332a20; + --elev: #3d3226; + --ink: #f4e6cb; + --muted: #c3ad8d; + --line: #b9884f; + --line-soft: rgba(185, 136, 79, 0.4); + --gold: #e0b76a; + --teal: #79bfc7; + --blue: #8fb4c9; + --sage: #a7c08a; + --rust: #e08b6c; + --shadow: 5px 6px 0 rgba(0, 0, 0, 0.65); + --shadow-sm: 3px 4px 0 rgba(0, 0, 0, 0.65); + + --md-default-fg-color: var(--ink); + --md-default-fg-color--light: var(--muted); + --md-default-fg-color--lighter: rgba(195, 173, 141, 0.5); + --md-default-fg-color--lightest: var(--line-soft); + --md-default-bg-color: var(--paper-2); + --md-primary-fg-color: var(--paper); + --md-primary-bg-color: var(--ink); + --md-accent-fg-color: var(--gold); + --md-typeset-color: var(--ink); + --md-typeset-a-color: var(--teal); + --md-code-bg-color: #2a2219; + --md-code-fg-color: #e8dcc2; + --md-footer-bg-color: var(--paper); + --md-footer-fg-color: var(--ink); +} + +/* -------------------------------------------------------------------------- + 2. Paper ground + -------------------------------------------------------------------------- */ + +body { + background: + radial-gradient(circle at 1px 1px, rgba(159, 116, 75, 0.18) 1.2px, transparent 0) 0 0 / 28px 28px, + linear-gradient(135deg, #f4e2bd 0%, var(--paper) 45%, #ead2a7 100%); + background-attachment: fixed; + text-rendering: optimizeLegibility; +} + +[data-md-color-scheme="slate"] body { + background: + radial-gradient(circle at 1px 1px, rgba(185, 136, 79, 0.14) 1.2px, transparent 0) 0 0 / 28px 28px, + linear-gradient(135deg, #1d1710 0%, var(--paper) 45%, #191410 100%); +} + +.md-main__inner { + margin-top: 1.6rem; +} + +/* The content sheet: a page of paper laid on the desk. */ +.md-content__inner { + background: var(--paper-2); + border: 3px solid var(--line); + border-radius: var(--radius); + box-shadow: var(--shadow); + padding: 1.6rem clamp(1rem, 3vw, 2.4rem) 2.4rem; + margin-bottom: 2.4rem; +} + +.md-content__inner::before { + height: 0; +} + +/* -------------------------------------------------------------------------- + 3. Header & navigation + -------------------------------------------------------------------------- */ + +.md-header { + background: rgba(247, 234, 208, 0.92); + backdrop-filter: blur(10px); + border-bottom: 3px solid var(--line); + box-shadow: 0 4px 0 rgba(43, 33, 24, 0.12); + color: var(--ink); +} + +[data-md-color-scheme="slate"] .md-header { + background: rgba(36, 28, 21, 0.92); +} + +.md-header__title { + font: 800 1.25rem/1 var(--md-text-font-family); + letter-spacing: 0.02em; +} + +.md-header__button.md-logo img { + width: 2rem; + height: 2rem; + border-radius: 8px; + border: 2px solid var(--line); + background: var(--paper-2); +} + +.md-search__form { + background: var(--paper-2); + border: 2px solid var(--line); + border-radius: 999px; + box-shadow: 2px 3px 0 var(--ink); +} + +.md-search__form:hover { + background: var(--surface); +} + +.md-search__input::placeholder { + color: var(--muted); +} + +.md-search__output { + border-radius: var(--radius); + border: 3px solid var(--line); + overflow: hidden; +} + +/* Sidebar links styled like the group site's nav pills. */ +.md-nav { + font-size: 0.74rem; +} + +.md-nav__title { + font: 800 0.78rem/1.2 var(--md-text-font-family); + color: var(--muted); + text-transform: uppercase; + letter-spacing: 0.06em; +} + +.md-nav__link { + border: 2px solid transparent; + border-radius: 999px; + padding: 0.2rem 0.55rem; + font-weight: 700; + color: var(--ink); + transition: background 0.12s ease, border-color 0.12s ease, box-shadow 0.12s ease; +} + +.md-nav__link:focus, +.md-nav__link:hover { + color: var(--rust); + border-color: var(--line-soft); + background: var(--paper-2); +} + +.md-nav__link--active, +.md-nav__item .md-nav__link--active { + color: var(--ink); + border-color: var(--line); + background: var(--paper-2); + box-shadow: 2px 3px 0 var(--ink); +} + +.md-nav--secondary .md-nav__link--active { + box-shadow: none; + background: transparent; + border-color: transparent; + color: var(--rust); +} + +/* -------------------------------------------------------------------------- + 4. Typography + -------------------------------------------------------------------------- */ + +.md-typeset { + font-size: 0.79rem; + line-height: 1.65; +} + +.md-typeset h1 { + font-weight: 800; + font-size: clamp(2rem, 5vw, 2.9rem); + line-height: 0.98; + letter-spacing: -0.035em; + color: var(--ink); + margin-bottom: 0.6rem; +} + +.md-typeset h2 { + font-weight: 800; + font-size: 1.65rem; + line-height: 1.05; + letter-spacing: -0.02em; + color: var(--ink); + margin-top: 2.2rem; + padding-bottom: 0.35rem; + border-bottom: 3px solid var(--line-soft); +} + +.md-typeset h3 { + font-weight: 800; + font-size: 1.2rem; + letter-spacing: -0.01em; + color: var(--teal); +} + +.md-typeset h4, +.md-typeset h5 { + font-weight: 800; + color: var(--ink); +} + +.md-typeset a { + text-decoration-thickness: 2px; + text-underline-offset: 0.18em; +} + +.md-typeset a:hover { + color: var(--rust); +} + +.md-typeset hr { + border-bottom: 3px dashed var(--line-soft); + margin: 2rem 0; +} + +/* Material ships these under [dir=ltr], which outranks a bare .md-typeset + selector β€” match that specificity or the accent bar never lands. */ +.md-typeset blockquote, +[dir="ltr"] .md-typeset blockquote { + border-left: 10px solid var(--teal); + border-right: none; + border-radius: 0 12px 12px 0; + background: rgba(255, 248, 231, 0.72); + color: var(--ink); + padding: 0.6rem 1rem; + margin-left: 0; +} + +[data-md-color-scheme="slate"] .md-typeset blockquote { + background: rgba(51, 42, 32, 0.7); +} + +.md-typeset blockquote strong { + color: var(--rust); +} + +.md-typeset kbd { + background: var(--elev); + border: 2px solid var(--line); + border-radius: 8px; + box-shadow: 2px 3px 0 var(--ink); + color: var(--ink); +} + +/* -------------------------------------------------------------------------- + 5. Code + -------------------------------------------------------------------------- */ + +.md-typeset code { + border: 1px solid var(--line-soft); + border-radius: 6px; + padding: 0.08em 0.35em; +} + +.md-typeset pre > code { + border: none; + padding: 0.7rem 1rem; +} + +.md-typeset .highlight, +.md-typeset pre { + border-radius: 14px; +} + +/* Border and shadow on the frame; the inner keeps Material's own + horizontal scroll, so wide lines stay reachable rather than clipped. */ +.md-typeset .highlight > pre, +.md-typeset > pre { + border: 3px solid var(--line); + border-radius: 14px; + box-shadow: var(--shadow-sm); +} + +.md-typeset .highlight > pre > code, +.md-typeset > pre > code { + border-radius: 11px; +} + +.md-typeset .highlight [data-linenos]::before { + background: var(--elev); + color: var(--muted); + box-shadow: none; +} + +.md-clipboard { + color: var(--muted); +} + +.md-clipboard:hover { + color: var(--rust); +} + +/* Tabbed code blocks */ +.md-typeset .tabbed-set > input:checked + label { + color: var(--teal); + border-color: var(--teal); + font-weight: 800; +} + +.md-typeset .tabbed-labels > label { + font-weight: 700; +} + +/* -------------------------------------------------------------------------- + 6. Tables + -------------------------------------------------------------------------- */ + +.md-typeset table:not([class]) { + border: 3px solid var(--line); + border-radius: 14px; + box-shadow: var(--shadow-sm); + background: var(--surface); + overflow: hidden; + font-size: 0.72rem; +} + +.md-typeset table:not([class]) th { + background: var(--elev); + color: var(--ink); + font-weight: 800; + border-bottom: 3px solid var(--line); +} + +.md-typeset table:not([class]) td { + border-top: 1px solid var(--line-soft); +} + +.md-typeset table:not([class]) tr:hover { + background: rgba(240, 223, 189, 0.35); +} + +/* Code spans in tables wrap at token boundaries rather than mid-identifier. */ +.md-typeset table:not([class]) td code { + word-break: keep-all; + overflow-wrap: break-word; +} + +/* -------------------------------------------------------------------------- + 7. Admonitions β€” the group site's callout, colour-coded + -------------------------------------------------------------------------- */ + +.md-typeset .admonition, +.md-typeset details { + border: 3px dashed var(--line); + border-left-width: 3px; + border-radius: var(--radius); + background: rgba(255, 248, 231, 0.78); + box-shadow: none; + font-size: 0.76rem; +} + +[data-md-color-scheme="slate"] .md-typeset .admonition, +[data-md-color-scheme="slate"] .md-typeset details { + background: rgba(51, 42, 32, 0.75); +} + +.md-typeset .admonition-title, +.md-typeset summary, +[dir="ltr"] .md-typeset .admonition-title, +[dir="ltr"] .md-typeset summary { + background: transparent; + border: none; + border-left-width: 0; + border-radius: 0; + font-weight: 800; + font-size: 0.86rem; +} + +/* Material tints each title bar with the type colour at 10% opacity, scoped + as `.md-typeset .tip>.admonition-title` (0,3,1). Match that to keep the + title flush with the callout body. */ +.md-typeset .admonition > .admonition-title, +.md-typeset .admonition > summary, +.md-typeset details > .admonition-title, +.md-typeset details > summary { + background-color: transparent; +} + +.md-typeset .admonition-title::before, +.md-typeset summary::before { + top: 0.62rem; +} + +/* Material scopes its per-type colours as `.md-typeset .admonition.tip` + (specificity 0,3,0), so a bare `.md-typeset .tip` never wins. Every rule + below matches that shape deliberately. */ + +/* note / info / abstract -> teal */ +.md-typeset .admonition.note, +.md-typeset details.note, +.md-typeset .admonition.info, +.md-typeset details.info, +.md-typeset .admonition.abstract, +.md-typeset details.abstract { + border-color: var(--teal); +} + +.md-typeset .note > .admonition-title, +.md-typeset .note > summary, +.md-typeset .info > .admonition-title, +.md-typeset .info > summary, +.md-typeset .abstract > .admonition-title, +.md-typeset .abstract > summary { + color: var(--teal); +} + +.md-typeset .note > .admonition-title::before, +.md-typeset .note > summary::before, +.md-typeset .info > .admonition-title::before, +.md-typeset .info > summary::before, +.md-typeset .abstract > .admonition-title::before, +.md-typeset .abstract > summary::before { + background-color: var(--teal); +} + +/* tip / success / example -> sage */ +.md-typeset .admonition.tip, +.md-typeset details.tip, +.md-typeset .admonition.success, +.md-typeset details.success, +.md-typeset .admonition.example, +.md-typeset details.example { + border-color: var(--sage); +} + +.md-typeset .tip > .admonition-title, +.md-typeset .tip > summary, +.md-typeset .success > .admonition-title, +.md-typeset .success > summary, +.md-typeset .example > .admonition-title, +.md-typeset .example > summary { + color: var(--sage); +} + +.md-typeset .tip > .admonition-title::before, +.md-typeset .tip > summary::before, +.md-typeset .success > .admonition-title::before, +.md-typeset .success > summary::before, +.md-typeset .example > .admonition-title::before, +.md-typeset .example > summary::before { + background-color: var(--sage); +} + +/* warning / question -> gold (darkened for text contrast on cream) */ +.md-typeset .admonition.warning, +.md-typeset details.warning, +.md-typeset .admonition.question, +.md-typeset details.question { + border-color: var(--gold); +} + +.md-typeset .warning > .admonition-title, +.md-typeset .warning > summary, +.md-typeset .question > .admonition-title, +.md-typeset .question > summary { + color: #8a6320; +} + +[data-md-color-scheme="slate"] .md-typeset .warning > .admonition-title, +[data-md-color-scheme="slate"] .md-typeset .warning > summary, +[data-md-color-scheme="slate"] .md-typeset .question > .admonition-title, +[data-md-color-scheme="slate"] .md-typeset .question > summary { + color: var(--gold); +} + +.md-typeset .warning > .admonition-title::before, +.md-typeset .warning > summary::before, +.md-typeset .question > .admonition-title::before, +.md-typeset .question > summary::before { + background-color: #8a6320; +} + +/* danger / failure / bug -> rust */ +.md-typeset .admonition.danger, +.md-typeset details.danger, +.md-typeset .admonition.failure, +.md-typeset details.failure, +.md-typeset .admonition.bug, +.md-typeset details.bug { + border-color: var(--rust); +} + +.md-typeset .danger > .admonition-title, +.md-typeset .danger > summary, +.md-typeset .failure > .admonition-title, +.md-typeset .failure > summary, +.md-typeset .bug > .admonition-title, +.md-typeset .bug > summary { + color: var(--rust); +} + +.md-typeset .danger > .admonition-title::before, +.md-typeset .danger > summary::before, +.md-typeset .failure > .admonition-title::before, +.md-typeset .failure > summary::before, +.md-typeset .bug > .admonition-title::before, +.md-typeset .bug > summary::before { + background-color: var(--rust); +} + +/* -------------------------------------------------------------------------- + 8. Cards, buttons, ornaments + -------------------------------------------------------------------------- */ + +.md-typeset .grid.cards > ul > li, +.md-typeset .grid > .card { + background: var(--surface); + border: 3px solid var(--line); + border-radius: var(--radius); + box-shadow: var(--shadow-sm); + padding: 1.05rem; + transition: transform 0.12s ease, box-shadow 0.12s ease; +} + +.md-typeset .grid.cards > ul > li:hover, +.md-typeset .grid > .card:hover { + transform: translate(2px, 2px); + box-shadow: 1px 2px 0 var(--ink); + border-color: var(--teal); +} + +.md-typeset .grid.cards > ul > li > hr { + border-bottom: 3px dashed var(--line-soft); + margin: 0.6rem 0; +} + +.md-typeset .md-button { + border: 3px solid var(--ink); + border-radius: 999px; + padding: 0.55rem 1rem; + font-weight: 900; + color: var(--ink); + background: var(--gold); + box-shadow: var(--shadow-sm); + transition: transform 0.12s ease, box-shadow 0.12s ease; +} + +.md-typeset .md-button:hover, +.md-typeset .md-button:focus { + background: var(--gold); + border-color: var(--ink); + color: var(--ink); + transform: translate(2px, 2px); + box-shadow: 1px 2px 0 var(--ink); +} + +.md-typeset .md-button--primary { + background: var(--teal); + color: var(--paper-2); + border-color: var(--ink); +} + +.md-typeset .md-button--primary:hover, +.md-typeset .md-button--primary:focus { + background: var(--teal); + color: var(--paper-2); +} + +/* Hand-lettered aside, as on the group site. */ +.md-typeset .note-hand { + font-family: var(--font-hand); + font-size: 1.25rem; + line-height: 1.3; + color: var(--muted); + transform: rotate(-0.6deg); + display: block; + margin: 1.2rem 0; +} + +/* Rotated sticker label. */ +.md-typeset .ribbon { + display: inline-block; + font-family: var(--font-sketch); + color: var(--ink); + background: var(--gold); + border: 3px solid var(--ink); + border-radius: 10px; + padding: 0.12rem 0.55rem; + transform: rotate(-1deg); + box-shadow: 2px 3px 0 var(--ink); +} + +/* Pill tags for package/tier badges. */ +.md-typeset .tag-pill { + display: inline-block; + border: 2px solid var(--line-soft); + border-radius: 999px; + padding: 0.1rem 0.55rem; + color: var(--muted); + background: #fff4d8; + font-weight: 800; + font-size: 0.72rem; +} + +[data-md-color-scheme="slate"] .md-typeset .tag-pill { + background: var(--elev); +} + +/* Banner image on the landing page. */ +.md-typeset .hero-banner { + display: block; + width: 100%; + border: 3px solid var(--line); + border-radius: var(--radius); + box-shadow: var(--shadow); + margin: 0 0 1.6rem; +} + +.md-typeset figure img { + border: 3px solid var(--line); + border-radius: var(--radius); + box-shadow: var(--shadow); +} + +.md-typeset figcaption { + color: var(--muted); + font-style: italic; +} + +/* -------------------------------------------------------------------------- + 9. Footer + -------------------------------------------------------------------------- */ + +.md-footer { + border-top: 3px solid var(--line); + background: rgba(247, 234, 208, 0.9); + color: var(--ink); +} + +[data-md-color-scheme="slate"] .md-footer { + background: rgba(36, 28, 21, 0.9); +} + +.md-footer-meta { + background: transparent; + border-top: 1px solid var(--line-soft); +} + +.md-footer__link { + color: var(--ink); + font-weight: 800; + opacity: 1; +} + +.md-footer__link:hover { + color: var(--rust); +} + +.md-copyright, +.md-copyright__highlight { + color: var(--muted); +} + +.md-footer-nav__link, +.md-social__link { + color: var(--ink); +} + +/* -------------------------------------------------------------------------- + 10. Small screens + -------------------------------------------------------------------------- */ + +@media screen and (max-width: 76.1875em) { + .md-nav--primary .md-nav__title { + background: var(--paper); + color: var(--ink); + box-shadow: none; + border-bottom: 3px solid var(--line); + } + + .md-nav--primary { + background: var(--paper-2); + } +} + +@media screen and (max-width: 44.9375em) { + .md-content__inner { + border-width: 2px; + border-radius: 16px; + padding: 1.1rem 0.9rem 1.6rem; + box-shadow: 3px 4px 0 rgba(43, 33, 24, 0.9); + } +} diff --git a/docs/ti-runtime/index.md b/docs/ti-runtime/index.md new file mode 100644 index 0000000..84bfece --- /dev/null +++ b/docs/ti-runtime/index.md @@ -0,0 +1,88 @@ +# ti-runtime + +`ti-runtime` is the **neutral Taichi runtime** that MechDSL-generated code lands on. It +holds seams and primitives β€” and nothing algorithmic. Where +[mechdsl-core](../mechdsl-core/index.md) derives constitutive math from LaTeX and +[algo2code](../algo2code/index.md) derives algorithms from LaTeX, `ti-runtime` is the +stable floor both of them emit against. + +```bash +pip install ti-runtime +``` + +It is a genuinely standalone package: it depends on `taichi` and nothing else, and it +never imports `mechdsl`. It also arrives automatically with +`pip install "mechdsl-core[verify]"`. + +--- + +## Seams & Bodies + +The architecture has a one-line summary: + +> MechDSL owns the **seams and primitives** (this package); algo2code generates the +> **bodies** β€” solvers, preconditioners, constitutive updates, time integrators β€” from +> LaTeX, injected into those seams. + +The payoff is portability. Generated artifacts depend on `ti_runtime`, **never** on +`mechdsl`, so an emitted kernel can be lifted out of the compiler that produced it and +run wherever `ti-runtime` is installed. + +--- + +## What's in it + +| Module | Contents | +|---|---| +| `vector_ops` | `@ti.kernel` vector primitives: `copy`, `axpy`, `xpay`, `scal`, `zero`, `dot`, `norm2`, `vec_add`, `ediv` | +| `tensor_ti` | Tier-1 `@ti.func` helpers: `det3` / `inv3`, the Fβ†’Cβ†’Eβ†’J kinematic chain, Voigt conversion, deviatoric split, von Mises | +| `seams` | Injection plumbing: `Operator`, `PreconditionerBase` / `IdentityPreconditioner` / `DiagonalPreconditioner`, `Solver`, `LinearSolveContext`, `Integrator`, `TimeIntegrationContext`, `AccelSolve` | +| `fields` | `ti.init` and field-allocation boilerplate | +| `hex8` | Hex8 shape functions, natural-coordinate gradients, 2Γ—2Γ—2 Gauss quadrature | + +Everything above is re-exported from the package root: + +```python +from ti_runtime import LinearSolveContext, DiagonalPreconditioner, axpy, dot, norm2 +``` + +--- + +## The operator / solver contract + +A matrix-free operator is an in-place callable `apply(out, x) -> None` computing +`out = A @ x` over Taichi fields β€” typically a generated `@ti.kernel`. A preconditioner +mirrors the same shape: `apply(z, r)` sets `z = M⁻¹ r`. + +```python +from ti_runtime import LinearSolveContext, DiagonalPreconditioner + +ctx = LinearSolveContext() +ctx.set_operator(my_tangent_matvec) # out = K(u) @ x, matrix-free @ti.kernel +ctx.set_preconditioner(DiagonalPreconditioner(diag)) +# a generated PCG body then calls ctx.apply_A / ctx.apply_preconditioner + vector_ops +``` + +Because `LinearSolveContext` applies *whatever* operator, preconditioner, and solver were +injected, the plumbing is algorithm-agnostic β€” swapping in a different generated solver +body changes no runtime code. + +--- + +## How mechdsl-core uses it + +The generated matrix-free SVK tangent kernel emits `from ti_runtime import ...` for the +Tier-1 tensor helpers, the Hex8 shape gradients, and the `apply_A` injection seam. That +is the `mechdsl-core β†’ ti-runtime` production dependency edge. Since `ti-runtime` carries +Taichi, it rides in the `verify` extra alongside it β€” keeping the base `mechdsl-core` +install Taichi-free. See [Installation](../installation.md) for the split. + +--- + +## Provenance & conventions + +- **One-time harvest.** Adapted from NumerixWeave (`libs/tisolvers`, `libs/ticonstit`, + `apps/tifem`) in a single pass; there is no ongoing sync. +- **Conventions match the rest of MechDSL:** Voigt order `[xx, yy, zz, xy, xz, yz]`, + tensorial (unscaled shears), metric `diag(1, 1, 1, 2, 2, 2)`. See + [Core concepts β†’ conventions](../mechdsl-core/concepts.md#conventions). diff --git a/docs/workbench.md b/docs/workbench.md new file mode 100644 index 0000000..d409d1f --- /dev/null +++ b/docs/workbench.md @@ -0,0 +1,110 @@ +# Browser workbench + +[`mechdsl-workbench`](https://github.com/CEmM2/mechdsl-workbench) is a companion +browser application for MechDSL: **LaTeX on the left, the compiled mechanics or +transpiled algorithm on the right**. It is the fastest way to try the language before +committing to the pipeline β€” no scripts, no `ProblemIR`, no local Taichi wrangling. + +It lives in its own repository, is published to PyPI, and is MIT-licensed like the rest +of the toolchain. + +```text +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ Mechanics | Algorithm Example β–Ύ Compile/Run β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ LaTeX source β”‚ +β”‚ β”‚ +β”‚ % mechanics ... or % algorithm pcg β”‚ +β”‚ \begin{algorithmic} ... β”‚ +β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ +β”‚ Preview | Generated Taichi | Translation View | Diagnostics β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ +``` + +## Install and run + +```bash +pip install "mechdsl-workbench[mechdsl]" # workbench + the MechDSL engine, one command +mechdsl-workbench +``` + +Then open . + +The `[mechdsl]` extra pulls `mechdsl-core[verify]` and `algo2code` from PyPI β€” the full +engine including Taichi, so expect a large download. If you already have an engine +installed (or want to point at a source checkout), take the workbench alone: + +```bash +pip install mechdsl-workbench # bring your own mechdsl-core +``` + +!!! warning "Python 3.12" + The workbench pins `requires-python = ">=3.12,<3.13"`, which is narrower than the + `>=3.11,<3.14` range the three monorepo packages accept. Install it into a 3.12 + environment. + +Common flags and the full environment-variable table (bind host and port, compile +timeout, concurrency and payload limits, MathJax source) are documented in the +[workbench README](https://github.com/CEmM2/mechdsl-workbench#run-options): + +```bash +mechdsl-workbench --host 127.0.0.1 --port 8000 +mechdsl-workbench --reload +``` + +A Docker image is available too β€” `docker compose up` from the workbench repository. + +## The two modes + +### Mechanics mode + +Compile a `% mechanics` document through +[`compile_from_sources()`](reference/architecture.md#integration-facade): + +- line-numbered LaTeX editor, with an optional separate constitutive-energy source; +- MathJax preview and `% mechanics` directive cards; +- the generated Taichi source; +- the public Element IR summary, the semantic content hash, and whether a derived + energy was present; +- bundled SVK Hex8, equation-bearing Hex8, and Tet4 examples. + +### Algorithm mode + +Transpile a LaTeX `algorithmic` block through `transpile_algorithm()`: + +- `% algorithm`, `% backend`, `% args`, and `% type` contract preview; +- the generated Taichi/Python source; +- entry-point name, line count, backend, and Python-validity result; +- bundled J2 radial-return and PCG examples. + +Both modes share an explicit action button (or `Ctrl+Enter` / `Cmd+Enter`), copy and +download actions for the source and the generated `.py`, and browser-local drafts kept +separately per mode. + +## How it talks to the compiler + +The dependency direction is strictly one-way, and checked in the workbench's CI: + +```text +mechdsl-workbench -> mechdsl.integration -> mechdsl-core / algo2code +MechDSL -X-> mechdsl-workbench +``` + +The workbench only ever calls the five entry points of the `mechdsl.integration` +faΓ§ade β€” the stable, machine-readable Tier-1 surface. It never imports `algo2code` +directly and never reaches into the parser, IR, lowering, symbolic, or codegen +internals. That is deliberate: the workbench is the reference consumer that proves the +public integration surface is sufficient to build a real application on. + +!!! note "Nothing generated is executed" + Each translation runs in a short-lived worker subprocess with a hard timeout, and + the server terminates it if it overruns. The workbench **does not execute the code + it emits** β€” the preview is presentational, and the Translation View reports only + what the public integration result actually returned. + +## Where to next + +- [Installation](installation.md) β€” the full PyPI and source matrix for every package. +- [LaTeX directive reference](mechdsl-core/latex-directives.md) β€” what to type into the + mechanics pane. +- [algo2code usage](algo2code/usage.md) β€” what to type into the algorithm pane. diff --git a/mkdocs.yml b/mkdocs.yml index bf97a9a..d9f4a11 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -8,18 +8,23 @@ use_directory_urls: false theme: name: material + logo: assets/mechdsl-mark.webp + favicon: assets/mechdsl-mark.webp + font: + text: Baloo 2 + code: JetBrains Mono palette: - media: "(prefers-color-scheme: light)" scheme: default - primary: indigo - accent: indigo + primary: custom + accent: custom toggle: icon: material/weather-night name: Switch to dark mode - media: "(prefers-color-scheme: dark)" scheme: slate - primary: indigo - accent: indigo + primary: custom + accent: custom toggle: icon: material/weather-sunny name: Switch to light mode @@ -34,6 +39,9 @@ theme: - search.suggest - search.highlight +extra_css: + - stylesheets/mechdsl.css + markdown_extensions: - admonition - attr_list @@ -45,12 +53,17 @@ markdown_extensions: anchor_linenums: true - pymdownx.superfences - pymdownx.inlinehilite + # Required for the :material-*: / :octicons-*: icon shortcodes used in the card grids. + - pymdownx.emoji: + emoji_index: !!python/name:material.extensions.emoji.twemoji + emoji_generator: !!python/name:material.extensions.emoji.to_svg - pymdownx.tabbed: alternate_style: true - pymdownx.details nav: - Home: index.md + - Installation: installation.md - mechdsl-core: - Introduction: mechdsl-core/index.md - Getting started: mechdsl-core/getting-started.md @@ -63,6 +76,10 @@ nav: - Getting started: algo2code/getting-started.md - Usage: algo2code/usage.md - Examples: algo2code/examples.md + - ti-runtime: + - Introduction: ti-runtime/index.md + - Workbench: + - Browser workbench: workbench.md - Reference: - How it works: reference/architecture.md - FAQ & troubleshooting: reference/faq.md @@ -71,3 +88,10 @@ extra: social: - icon: fontawesome/brands/github link: https://github.com/CEmM2/MechDSL + name: MechDSL on GitHub + - icon: fontawesome/brands/python + link: https://pypi.org/project/mechdsl-core/ + name: mechdsl-core on PyPI + - icon: fontawesome/solid/flask + link: https://sosovski.group/ + name: The research group site