diff --git a/README.md b/README.md
index 5f4ddd4..057d304 100644
--- a/README.md
+++ b/README.md
@@ -1,76 +1,109 @@
# Horn Loudspeaker Simulation Pipeline
-A containerized pipeline for simulating and analysing horn loudspeaker acoustic performance. Built with FEniCSx (FEM), gmsh, and orchestrated by Nextflow.
+> Design and simulate horn-loaded loudspeakers — from a target frequency band to ranked driver-horn recommendations — using FEM acoustics, a driver database, and automated optimization.
-## Pipeline Overview
+[](https://github.com/timini/horn-simulation/actions/workflows/ci.yml)
+
-The pipeline takes horn geometry parameters and driver characteristics as input, then runs a full acoustic simulation and produces frequency response plots.
+## What is this?
+An open-source tool for acoustic horn design. Give it a target frequency band and it will generate horn geometries, solve the Helmholtz equation with FEM, couple the results with real loudspeaker drivers via Thiele-Small parameters, and rank every driver-horn combination — producing a self-contained HTML report you can open in any browser.
+
+Built for audio engineers, acousticians, DIY speaker builders, and researchers.
+
+## Key features
+
+- **3 horn profiles** — conical, exponential, hyperbolic
+- **FEM Helmholtz solver** — FEniCSx/dolfinx with adaptive meshing and radiation BC
+- **Driver database** with Thiele-Small parameter coupling
+- **3 operating modes** — single simulation, auto comparison, full-auto design exploration
+- **Self-contained HTML reports** — rankings, plots, and driver tables, all base64-embedded
+- **Containerized and parallelized** — Docker + Nextflow, frequency bands solved in parallel
+
+## How it works
+
+### Pipeline flow
+
+```mermaid
+flowchart LR
+ A[Target frequency band] --> B[Pre-screen drivers]
+ A --> C[Generate horn geometry]
+ C --> D[FEM solver — Helmholtz equation]
+ D --> E[Couple with drivers]
+ E --> F[Score & rank combinations]
+ F --> G[HTML report + plots]
```
- Horn Parameters
- (throat, mouth, length)
- |
- v
- +---------------------+
- | generate_geometry | horn-geometry container
- | (gmsh/OCC kernel) | Produces STEP file
- +---------------------+
- |
- horn.step
- |
- +---------------+---------------+
- | | | Frequency band
- v v v parallelisation
- +-----------+ +-----------+ +-----------+
- | solve | | solve | | solve | horn-solver container
- | band 0 | | band 1 | | band N | FEniCSx FEM
- +-----------+ +-----------+ +-----------+
- | | |
- results_0.csv results_1.csv results_N.csv
- | | |
- +---------------+---------------+
- |
- v
- +---------------------+
- | merge_results | horn-analysis container
- | (pandas concat) | Combines band CSVs
- +---------------------+
- |
- final_results.csv
- |
- v
- +---------------------+
- | generate_plots | horn-analysis container
- | (matplotlib) | SPL vs Frequency plot
- +---------------------+
- |
- frequency_response.png
+
+### Package architecture
+
+```mermaid
+flowchart TB
+ subgraph Orchestration
+ NF[Nextflow pipeline]
+ end
+ subgraph Packages
+ CORE[horn-core
parameters & data structures]
+ GEO[horn-geometry
gmsh STEP generation]
+ SOLVER[horn-solver
FEniCSx FEM — Helmholtz]
+ ANALYSIS[horn-analysis
scoring, ranking, reports]
+ DRIVERS[horn-drivers
driver database]
+ end
+ NF --> GEO --> SOLVER --> ANALYSIS
+ DRIVERS --> ANALYSIS
+ CORE --> GEO & SOLVER & ANALYSIS & DRIVERS
```
-### Packages
+### Frequency parallelization
+
+```mermaid
+flowchart TB
+ G[generate_geometry
gmsh/OCC → STEP file] --> S0[solve band 0]
+ G --> S1[solve band 1]
+ G --> SN[solve band N]
+ S0 --> M[merge_results
pandas concat]
+ S1 --> M
+ SN --> M
+ M --> P[generate_plots
SPL vs frequency]
+```
-| Package | Purpose | Key Dependencies |
-|---------|---------|-----------------|
-| `horn-geometry` | Procedural horn geometry generation | gmsh (OpenCASCADE) |
-| `horn-solver` | FEM acoustic solving + meshing | FEniCSx/dolfinx, gmsh |
-| `horn-analysis` | Result merging, plotting, scoring, ranking | pandas, matplotlib, scipy |
-| `horn-core` | Shared data structures (HornParameters, DriverParameters) | numpy |
-| `horn-drivers` | Driver database loading and validation | numpy, horn-core |
+## Operating modes
+
+### Single mode (default)
-### What it does
+Simulate one horn with explicit geometry parameters and get a frequency response plot.
+
+```bash
+nextflow run main.nf -profile docker \
+ --throat_radius 0.05 --mouth_radius 0.2 --length 0.5
+```
-1. **Geometry generation**: Creates a 3D STEP model of a conical horn from parametric inputs (throat radius, mouth radius, length) using gmsh's OpenCASCADE kernel
-2. **Meshing + Solving**: Imports the STEP file into gmsh, generates a tetrahedral volume mesh with tagged boundaries (inlet/outlet/walls), then solves the Helmholtz equation at each frequency using FEniCSx. The frequency range is split into N bands and solved in parallel across separate containers
-3. **Result merging**: Collects per-band CSV files and concatenates them into a single sorted dataset
-4. **Plotting**: Generates a frequency response plot (SPL vs frequency on a log scale)
+### Auto mode
-## Getting Started
+Fix the geometry, simulate all 3 profiles (conical, exponential, hyperbolic), couple every pre-screened driver, and rank the combinations. Only 3 FEM simulations — driver coupling is pure Python via the transfer function.
+
+```bash
+nextflow run main.nf -profile docker --mode auto \
+ --target_f_low 500 --target_f_high 4000 \
+ --mouth_radius 0.2 --length 0.5 --top_n 10
+```
+
+### Fullauto mode
+
+Specify **only** a target frequency band. The system derives horn geometry analytically (mouth radius from cutoff frequency, length from quarter-wave to half-wave), generates a grid of 3 profiles x N mouth radii x N lengths, runs FEM on all candidates, couples with pre-screened drivers, and ranks everything.
+
+```bash
+nextflow run main.nf -profile docker --mode fullauto \
+ --target_f_low 500 --target_f_high 4000
+```
+
+## Quick start
### Prerequisites
- [Docker](https://www.docker.com/get-started)
- [just](https://github.com/casey/just) (task runner)
-- [Nextflow](https://www.nextflow.io/docs/latest/getstarted.html#installation) (for running the full pipeline)
+- [Nextflow](https://www.nextflow.io/docs/latest/getstarted.html#installation)
+- **Java 11–22** (required by Nextflow; Java 25+ is not supported). On macOS: `brew install openjdk@21`
### Build
@@ -78,27 +111,30 @@ The pipeline takes horn geometry parameters and driver characteristics as input,
just build
```
-### Test
+### Run
-Run all package tests in Docker:
```bash
-just test
+nextflow run main.nf -profile docker --mode fullauto \
+ --target_f_low 500 --target_f_high 4000
```
-Test a single package:
+Open the report:
+
```bash
-just test-package horn-solver
+open results/fullauto/report/auto_report.html
```
-### Run the Pipeline
+### Test
```bash
-nextflow run main.nf -profile docker
+just test # all packages
+just test-package horn-solver # single package
```
## Parameters
-### Single mode (default)
+
+Single mode (default)
| Parameter | Description | Default |
|-----------|-------------|---------|
@@ -113,7 +149,10 @@ nextflow run main.nf -profile docker
| `num_bands` | Parallel frequency band jobs | `8` |
| `outdir` | Output directory | `./results` |
-### Auto mode (`--mode auto`)
+
+
+
+Auto mode (--mode auto)
| Parameter | Description | Default |
|-----------|-------------|---------|
@@ -122,61 +161,35 @@ nextflow run main.nf -profile docker
| `drivers_db` | Path to driver database JSON | `data/drivers.json` |
| `top_n` | Number of top results to return | `10` |
-## Example Usage
+
-### Quick development run
-```bash
-nextflow run main.nf -profile docker --outdir ./results/dev --num_intervals 10
-```
-
-### Full resolution analysis
-```bash
-nextflow run main.nf -profile docker --outdir ./results/full \
- --min_freq 20 --max_freq 20000 --num_intervals 2000
-```
-
-### Compare two horn designs
-```bash
-# Run Horn A
-nextflow run main.nf -profile docker --outdir ./results/horn_A \
- --throat_radius 0.05 --mouth_radius 0.2 --length 0.5
-
-# Run Horn B with different length
-nextflow run main.nf -profile docker --outdir ./results/horn_B \
- --throat_radius 0.05 --mouth_radius 0.2 --length 0.8
+
+Fullauto mode (--mode fullauto)
-# Plot comparison
-python3 -m horn_analysis.compare_horns \
- results/horn_A/final_results.csv "Horn A" \
- results/horn_B/final_results.csv "Horn B" \
- results/comparison.png
-```
+| Parameter | Description | Default |
+|-----------|-------------|---------|
+| `target_f_low` | Target low frequency (Hz) | `500` |
+| `target_f_high` | Target high frequency (Hz) | `4000` |
+| `drivers_db` | Path to driver database JSON | `data/drivers.json` |
+| `top_n` | Number of top results to return | `10` |
+| `num_mouth_radii` | Mouth radius grid points | `3` |
+| `num_lengths` | Length grid points | `3` |
+| `num_intervals` | Frequency steps per simulation | `100` |
+| `num_bands` | Parallel frequency band jobs | `8` |
-### Auto-select drivers and horn profiles
-```bash
-# Run the full auto pipeline: pre-screens drivers, simulates all 3 profiles
-# (conical, exponential, hyperbolic), couples each driver post-hoc, and ranks
-nextflow run main.nf -profile docker --mode auto \
- --target_f_low 500 --target_f_high 4000 \
- --mouth_radius 0.2 --length 0.5 --top_n 10
-```
+
-This runs only 3 FEM simulations (one per profile) and couples all pre-screened drivers in pure Python via the transfer function. Outputs: `auto_ranking.json`, `auto_comparison.png`, `auto_summary.txt`, and a self-contained `auto_report.html` (open in any browser — all plots are base64-embedded).
+## Packages
-### CLI tools for individual steps
-```bash
-# Pre-screen drivers for a target spec
-horn-prescreen --drivers-db data/drivers.json \
- --target-f-low 500 --target-f-high 4000 \
- --mouth-radius 0.2 --length 0.5
-
-# Rank drivers against a solver result
-horn-rank --solver-csv results/final_results.csv \
- --drivers-db data/drivers.json --throat-radius 0.025 \
- --target-f-low 500 --target-f-high 4000 --top-n 5
-```
+| Package | Purpose | Key Dependencies |
+|---------|---------|-----------------|
+| `horn-core` | Shared data structures (`HornParameters`, `DriverParameters`) | numpy |
+| `horn-geometry` | Procedural horn geometry generation (STEP files) | gmsh (OpenCASCADE) |
+| `horn-solver` | FEM acoustic solving + meshing | FEniCSx/dolfinx, gmsh |
+| `horn-analysis` | Result merging, plotting, scoring, ranking, HTML reports | pandas, matplotlib, scipy |
+| `horn-drivers` | Driver database loading and validation | numpy, horn-core |
-## Acoustic Modelling
+## Acoustic modelling
### Governing equation
@@ -257,10 +270,6 @@ This is a monorepo with each package in `packages/`. Each package has its own Do
The pipeline is orchestrated by Nextflow (`main.nf`), which maps each process to its corresponding Docker container via `nextflow.config`.
-## Current Status
-
-The pipeline runs end-to-end. SPL is computed from the outlet-surface RMS pressure with a Robin (radiation impedance) BC at the horn mouth. A validation suite verifies the solver against analytical solutions (straight tube, Webster equation) and provides infrastructure for cross-validation against published data.
-
## Roadmap
Prioritised capabilities for reaching feature parity with tools like AKABAK. See linked GitHub issues for details.
@@ -284,7 +293,16 @@ Prioritised capabilities for reaching feature parity with tools like AKABAK. See
### Completed
+- Fullauto mode: derive horn geometry grid from a target frequency band
- HTML report for auto-mode: single self-contained `auto_report.html` with rankings table, 4 embedded plots (coupled SPL, raw profile SPL, impedance, phase/group delay), driver T-S parameter table, and summary cards
- Driver coupling with T-S parameters (transfer function + auto-select pipeline) — [#50](https://github.com/timini/horn-simulation/issues/50)
- Analysis features: impedance plots, scoring, driver DB — [#35](https://github.com/timini/horn-simulation/issues/35)
- Profile diversity: conical, exponential, hyperbolic
+
+## Contributing
+
+Contributions welcome. Please open an issue first to discuss what you'd like to change.
+
+## License
+
+See repository for license details.