Pseudospectral Cahn–Hilliard simulation of agate and related pattern formation. The code implements Model C (coupled phase fields with reaction–diffusion), optional ψ-split stress coupling, and cavity geometry via smooth masks.
Research codebase, pre-publication. Equations and diagnostics are specified in docs/PHYSICS.md. Package layout and contracts are in docs/ARCHITECTURE.md.
Python 3.12 (see pyproject.toml). With uv:
uv syncOptional GPU (CUDA 12 JAX wheels):
uv sync --extra cudaDeveloper tools (pytest, ruff, pre-commit):
uv sync --extra devuv run python -m continuous_patterns.experiments.run \
--config experiments/canonical/medium_pinning.yaml \
--out-dir results \
--no-writeOmit --no-write to write config.yaml, summary.json, final_state.npz, figures_final.png, and run.log (Python logging at DEBUG) under results/<experiment_name>/<timestamp>/.
Optional flags:
--log-level— console only:DEBUG,INFO,WARNING,ERROR(defaultINFO). The file log stays DEBUG when artifacts are written.--no-progress— disable tqdm chunk progress (models still print nothing per step; progress is per JIT chunk).--user-settings— optional path to per-machine YAML overrides (default file:experiments/solver_settings.yamlwhen present; seeexperiments/solver_settings.example.yaml).
uv run python -m continuous_patterns.experiments.sweep \
--sweep experiments/sweeps/gamma_scan.yaml \
--out-dir resultsEach sweep creates results/sweeps/<name>_<timestamp>/ with a manifest.json, report.md, and one subdirectory per grid point. The same --log-level and --no-progress flags apply (outer tqdm over combinations plus per-run bars unless disabled).
scripts/reproduce_canonical.py runs 16 nested per-feature demo YAMLs under experiments/canonical/ (Stage I/II baselines, geometry, stress, gravity, scenario, and the aging code demo) via the package CLI. Set CP_REPRODUCE_MINI=1 for a 4-run mini smoke (one example per feature category) with a shorter horizon (CP_OVERRIDE_T=250).
make help
make test
uv run python scripts/reproduce_canonical.pyQuick smoke: CP_REPRODUCE_MINI=1 uv run python scripts/reproduce_canonical.py or make mini (four names and T=250 override as in the script).
Environment variables for that script: CP_LOG_LEVEL (default INFO), CP_NO_PROGRESS=1 to turn off tqdm (passed through as CLI flags), and CP_OVERRIDE_T (optional horizon override; set automatically in mini mode).
New runs follow ARCHITECTURE §5: under the chosen results root, single runs use results_root / experiment_name / UTC_timestamp /, sweeps use results_root / sweeps / sweep_name_timestamp /. Large trees should stay gitignored; templates and docs live in the repo.
- Implement a builder
my_mode(*, L, n, sigma_0, **kwargs)insrc/continuous_patterns/core/stress.pyreturning(sigma_xx, sigma_yy, sigma_xy). - Register it in
STRESS_BUILDERS. - Add the mode string to
StressSpec.modeinsrc/continuous_patterns/core/io.py(Literal[...]). - Copy an existing YAML under
experiments/canonical/and setstress.mode.
- Implement a mask builder in
src/continuous_patterns/core/masks.pyreturning the standard dict (chi,ring,ring_accounting,rv, plusdx,L,R,n,xc,yc). - Register it in
MASK_BUILDERS. - Extend
GeometrySpec.typeincore/io.py. - Add a YAML card under
experiments/canonical/(orexperiments/exploratory/for one-offs).
See docs/CONTRIBUTING.md for coding standards, testing, and known permissive areas (physics / initial dicts).
Runtime deps include tqdm (chunk progress in models.*.simulate) and standard-library logging (console + run.log via experiments.run).
uv run pytest
uv run ruff check src tests
uv run ruff format --check src testsLicensed under the Apache License, Version 2.0 — see LICENSE.