Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Horn Simulation Pipeline

Nextflow-orchestrated FEM acoustic horn simulation with Docker-containerised packages.

## Quick reference

```bash
just # list all commands
just build # build all Docker images (horn-solver, horn-geometry, horn-analysis)
just test-local # run tests locally (horn-core, horn-geometry, horn-analysis)
just test # run tests in Docker
just run # single mode pipeline (default params)
just run-auto # auto mode (all 7 profiles, driver ranking)
just run-fullauto # fullauto mode (derives geometry from frequency band)
just clean # remove Docker images + Nextflow work dirs
```

## Running the pipeline

Always use `-profile docker` (the justfile does this automatically). The solver requires `dolfinx` which only exists in the Docker container.

```bash
# Single mode
just run --profile conical --throat_radius 0.025 --mouth_radius 0.15 --length 0.3

# Auto mode (mid-horn example)
just run-auto --target_f_low 250 --target_f_high 6500 --throat_radius 0.025 --mouth_radius 0.2 --length 0.3

# Fullauto mode (geometry derived from frequency band)
just run-fullauto --target_f_low 500 --target_f_high 4000

# Resume a failed/interrupted run
just run -resume
```

## Project structure

```
main.nf # Nextflow pipeline (single/auto/fullauto workflows)
nextflow.config # Docker container mappings per process
justfile # Build, test, run commands
packages/
horn-core/ # Shared data structures, enums, candidate generation (pure Python, no Docker)
horn-geometry/ # STEP file generation via gmsh (Docker: horn-geometry)
horn-solver/ # FEM solver via dolfinx (Docker: horn-solver)
horn-analysis/ # Plots, reports, scoring, rendering (Docker: horn-analysis)
```

## Horn profiles

7 flare profiles: `conical`, `exponential`, `hyperbolic`, `tractrix`, `os`, `lecleach`, `cd`

## Testing

```bash
# Local (fast, no Docker needed — covers horn-core, horn-geometry, horn-analysis)
just test-local

# Single package in Docker
just test-package horn-solver

# All packages in Docker
just test
```

horn-geometry tests need `gmsh` (installed locally). horn-solver tests need `dolfinx` (Docker only).

## Docker images

Build from repo root (context is `.`):
```bash
docker build -t horn-geometry:latest --target production -f ./packages/horn-geometry/Dockerfile .
```

Note: `gmsh` wheels don't have native `aarch64` Linux builds. On Apple Silicon, build with `--platform linux/amd64`.

## Java for Nextflow

Nextflow requires Java 8-22. If the system Java is too new, source `~/.zshrc` which sets the correct `JAVA_CMD`.
50 changes: 36 additions & 14 deletions justfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
packages := "horn-solver horn-geometry horn-analysis"
docker_packages := "horn-solver horn-geometry horn-analysis"
local_packages := "horn-core horn-geometry horn-analysis"

# Display help
default:
Expand All @@ -8,30 +9,51 @@ default:
build:
#!/usr/bin/env bash
set -euo pipefail
for pkg in {{packages}}; do
docker build -t "$pkg:latest" --target production -f "./packages/$pkg/Dockerfile" .
for pkg in {{docker_packages}}; do
docker build --platform linux/amd64 -t "$pkg:latest" --target production -f "./packages/$pkg/Dockerfile" .
done

# Run all package tests (build then test)
# Run all package tests in Docker (build then test)
test:
#!/usr/bin/env bash
set -euo pipefail
for pkg in {{packages}}; do
docker build -t "$pkg:test" --target test -f "./packages/$pkg/Dockerfile" .
for pkg in {{docker_packages}}; do
docker build --platform linux/amd64 -t "$pkg:test" --target test -f "./packages/$pkg/Dockerfile" .
done
for pkg in {{packages}}; do
for pkg in {{docker_packages}}; do
echo "Running tests for $pkg..."
docker run --rm "$pkg:test" pytest "/app/packages/$pkg/tests"
done

# Build and test a single package: just test-package horn-solver
# Build and test a single package in Docker: just test-package horn-solver
test-package pkg:
docker build -t "{{pkg}}:test" --target test -f "./packages/{{pkg}}/Dockerfile" .
docker run --rm "{{pkg}}:test" pytest "/app/packages/{{pkg}}/tests" -v
docker build --platform linux/amd64 -t "{{pkg}}:test" --target test -f "./packages/{{pkg}}/Dockerfile" .
docker run --platform linux/amd64 --rm "{{pkg}}:test" pytest "/app/packages/{{pkg}}/tests" -v

# Run the Nextflow pipeline
run:
nextflow run main.nf -profile docker
# Run tests locally (no Docker — works for horn-core, horn-geometry, horn-analysis)
test-local:
#!/usr/bin/env bash
set -euo pipefail
echo "Running horn-core tests..."
python -m pytest packages/horn-core/tests/ -v
echo "Running horn-analysis tests..."
python -m pytest packages/horn-analysis/tests/ -v
echo "Running horn-geometry tests..."
cd packages/horn-geometry && python -m pytest tests/ -v

# Run the Nextflow pipeline (single mode, default params)
run *ARGS:
nextflow run main.nf -profile docker {{ARGS}}

# Run auto mode (unified optimizer): just run-auto --target_f_low 250 --target_f_high 6500
# Fixed geometry: --mouth_radius 0.15 --length 0.3 (only varies profile)
# Free geometry: omit mouth_radius/length to derive from frequency band
run-auto *ARGS:
nextflow run main.nf -profile docker --mode auto {{ARGS}}

# Alias for auto mode with all geometry derived (backward compat)
run-fullauto *ARGS:
nextflow run main.nf -profile docker --mode auto {{ARGS}}

# Run Nextflow tests
test-nextflow:
Expand All @@ -42,7 +64,7 @@ clean:
#!/usr/bin/env bash
set -euo pipefail
echo "Cleaning up Docker images..."
for pkg in {{packages}}; do
for pkg in {{docker_packages}}; do
docker rmi -f "$pkg:latest" "$pkg:test" || true
done
echo "Cleaning up Nextflow files..."
Expand Down
Loading
Loading