Skip to content
Merged
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
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ Reproduce all figures from committed CSVs (no solver needed):
python3 scripts/three_regime_comparison.py --plot-only
```

- Plant-validation foundation: [`docs/freedecay_validation.md`](docs/freedecay_validation.md)
- Simulation-data regeneration index: [`docs/REPRODUCTION.md`](docs/REPRODUCTION.md)

## Repository structure

```
Expand Down
6 changes: 6 additions & 0 deletions analysis/FINDINGS_3REGIME.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ Controller co-design study across VGOSWEC flap variants (VGM-0/10/20/45/90) over
All results are reproducible from committed CSVs under
`analysis/{cc,opt_passive,passive_guarded}/` via `--plot-only`. No solver runs required.

> **Validated-plant foundation:** The controller/flap co-design results below
> rest on the free-decay WEC-Sim plant validation in
> [`../docs/freedecay_validation.md`](../docs/freedecay_validation.md), which
> verifies both the reactive plant impedance (**ω_n**) and the resistive
> radiation-damping response (**ζ / B55**) across VGM-0/10/20/45/90.

---

## 1. Three-regime relay (headline result)
Expand Down
191 changes: 191 additions & 0 deletions docs/REPRODUCTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
# Simulation reproduction index

This repository contains the full command chain needed to regenerate the
simulation-side datasets used in the VGOSWEC study. With the commands below,
the simulation results, summary CSVs, and figures are reproducible from this
repo alone; subsequent work can therefore be research/writing rather than
pipeline reconstruction.

## Solver prerequisite for `--run` / sweep commands

Any command below that launches `build/demo_vgoswec` requires the documented
SEA-Stack / Chrono build first:

```bash
source scripts/setup_env.sh
cmake -S . -B build \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH}"
cmake --build build -j$(nproc)
```

This produces `build/demo_vgoswec`. Headless workflows use `--no-viz`, so the
optional GUI / VSG stack is not required for CSV-only reproduction.

## Reproduction modes

- **Solver-invoking path**: the initial sweep or `--run` path calls
`build/demo_vgoswec` and regenerates raw simulation outputs.
- **`--plot-only` path**: regenerates figures from committed CSVs **without**
calling the solver.

## 1. Free-decay validation foundation

**Purpose:** regenerate the plant-validation basis used by the controller study.

```bash
# Clean-checkout, fully self-contained path: re-run the five free-decay cases,
# re-analyze ζ, then refresh the ω_n summary CSV/figure.
python3 scripts/freedecay_validation.py --run --make-figures
python3 scripts/plot_freedecay_validation.py

# If output/vgoswec_*_freedecay_results.csv already exist locally, reuse them:
python3 scripts/freedecay_validation.py --make-figures
python3 scripts/plot_freedecay_validation.py
```

- **Solver behavior**
- `scripts/freedecay_validation.py --run --make-figures` invokes
`build/demo_vgoswec` internally for
`config/vgoswec_{0,10,20,45,90}_freedecay.yaml`.
- The companion `scripts/plot_freedecay_validation.py` does **not** invoke
the solver; it reuses `output/vgoswec_*_freedecay_results.csv` if present.
- **Inputs consumed**
- Solver configs: `config/vgoswec_{0,10,20,45,90}_freedecay.yaml`
- Shared analysis helpers: `scripts/freedecay_analysis.py`
- Raw solver outputs: `output/vgoswec_*_freedecay_results.csv`
- **Outputs produced**
- `output/vgoswec_{0,10,20,45,90}_freedecay_results.csv`
- `docs/freedecay_validation.csv`
- `docs/img/freedecay_validation.png`
- `docs/img/freedecay_zeta_validation.png`
- `docs/img/freedecay_zeta_decay_fit.png`

See also: [`docs/freedecay_validation.md`](freedecay_validation.md).

## 2. CC capture-efficiency sweep

```bash
# Re-run the CC sweep (invokes build/demo_vgoswec):
python3 scripts/cc_capture_efficiency_sweep.py

# Reuse committed CSVs and regenerate figures only:
python3 scripts/cc_capture_efficiency_sweep.py --plot-only
```

- **Solver behavior**
- Default invocation runs the sweep across the shared `T = 0.5–7.0 s` grid
using `build/demo_vgoswec`.
- `--plot-only` reuses committed CSVs and does not call the solver.
- **Inputs consumed**
- Solver configs: `config/vgoswec_{0,10,20,45,90}_cc.yaml`
- Hydro inputs: `hydroData/vgoswec_{0,10,20,45,90}.h5`
- `--plot-only` inputs: `analysis/cc/capture_efficiency_VGM{0,10,20,45,90}.csv`
- **Outputs produced**
- `analysis/cc/capture_efficiency_VGM{0,10,20,45,90}.csv`
- `analysis/cc/figures/capture_efficiency_VGM{0,10,20,45,90}.png`
- `analysis/cc/figures/power_breakdown_VGM{0,10,20,45,90}.png`
- `analysis/cc/figures/capture_efficiency_summary.png`

## 3. ff+PID (`passive_guarded`) capture-efficiency sweep

```bash
# Re-run the tuned exc_ff_pid sweep (invokes build/demo_vgoswec):
python3 scripts/capture_efficiency_sweep.py

# Reuse committed CSVs and regenerate figures only:
python3 scripts/capture_efficiency_sweep.py --plot-only
```

- **Solver behavior**
- Default invocation runs the sweep across the shared `T = 0.5–7.0 s` grid
using `build/demo_vgoswec`.
- `--plot-only` reuses committed CSVs and does not call the solver.
- **Inputs consumed**
- Solver configs: `config/vgoswec_{0,10,20,45,90}_exc_ff_pid.yaml`
- Hydro inputs: `hydroData/vgoswec_{0,10,20,45,90}.h5`
- `--plot-only` inputs:
`analysis/passive_guarded/capture_efficiency_VGM{0,10,20,45,90}.csv`
- **Outputs produced**
- `analysis/passive_guarded/capture_efficiency_VGM{0,10,20,45,90}.csv`
- `analysis/passive_guarded/figures/capture_efficiency_VGM{0,10,20,45,90}.png`
- `analysis/passive_guarded/figures/capture_efficiency_summary.png`

## 4. opt_passive sweep

```bash
# Re-run the passive + opt_passive sweep (invokes build/demo_vgoswec):
python3 scripts/passive_vs_optpassive_sweep.py

# Reuse committed CSVs and regenerate figures only:
python3 scripts/passive_vs_optpassive_sweep.py --plot-only
```

- **Solver behavior**
- Default invocation runs both the `passive` and `opt_passive` arms across the
shared `T = 0.5–7.0 s` grid using `build/demo_vgoswec`.
- `--plot-only` reuses committed CSVs and does not call the solver.
- **Inputs consumed**
- Solver configs:
`config/vgoswec_{0,10,20,45,90}_passive.yaml`,
`config/vgoswec_{0,10,20,45,90}_opt_passive.yaml`
- Hydro inputs: `hydroData/vgoswec_{0,10,20,45,90}.h5`
- `--plot-only` inputs:
`analysis/passive/capture_efficiency_VGM{0,10,20,45,90}.csv`,
`analysis/opt_passive/capture_efficiency_VGM{0,10,20,45,90}.csv`
- **Outputs produced**
- `analysis/passive/capture_efficiency_VGM{0,10,20,45,90}.csv`
- `analysis/opt_passive/capture_efficiency_VGM{0,10,20,45,90}.csv`
- `analysis/passive/figures/capture_efficiency_VGM{0,10,20,45,90}.png`
- `analysis/opt_passive/figures/capture_efficiency_VGM{0,10,20,45,90}.png`
- `analysis/passive/figures/capture_efficiency_summary.png`
- `analysis/opt_passive/figures/capture_efficiency_summary.png`
- `analysis/passive_vs_optpassive/figures/`

## 5. CC vs ff+PID comparison

```bash
python3 scripts/cc_vs_ffpid_comparison.py --plot-only
```

- **Solver behavior**
- This is an analysis-only overlay script; it consumes existing sweep CSVs and
does not invoke `build/demo_vgoswec`.
- **Inputs consumed**
- `analysis/cc/capture_efficiency_VGM{0,10,20,45,90}.csv`
- `analysis/passive_guarded/capture_efficiency_VGM{0,10,20,45,90}.csv`
- **Outputs produced**
- `analysis/comparison/figures/cc_vs_ffpid_VGM{0,10,20,45,90}.png`
- `analysis/comparison/figures/cc_vs_ffpid_efficiency_VGM{0,10,20,45,90}.png`
- `analysis/comparison/figures/cc_vs_ffpid_summary.png`
- `analysis/comparison/figures/cc_vs_ffpid_efficiency_summary.png`

## 6. Three-regime relay + operating envelopes

```bash
python3 scripts/three_regime_comparison.py --plot-only
```

- **Solver behavior**
- This is an analysis-only summary script; it consumes existing sweep CSVs and
does not invoke `build/demo_vgoswec`.
- **Inputs consumed**
- `analysis/cc/capture_efficiency_VGM{0,10,20,45,90}.csv`
- `analysis/opt_passive/capture_efficiency_VGM{0,10,20,45,90}.csv`
- `analysis/passive_guarded/capture_efficiency_VGM{0,10,20,45,90}.csv`
- **Outputs produced**
- `analysis/three_regime/figures/three_regime_VGM{0,10,20,45,90}.png`
- `analysis/three_regime/figures/three_regime_efficiency_VGM{0,10,20,45,90}.png`
- `analysis/three_regime/figures/three_regime_summary.png`
- `analysis/three_regime/figures/three_regime_efficiency_summary.png`
- `analysis/three_regime/figures/operating_envelope.png`
- `analysis/three_regime/figures/operating_envelope_efficiency.png`
- `analysis/three_regime/operating_envelope.csv`
- `analysis/three_regime/operating_envelope_efficiency.csv`

## Bottom line

Only the initial sweep / `--run` commands invoke `build/demo_vgoswec`. All
`--plot-only` paths regenerate figures from committed CSVs **without** the
solver. Together, these commands make the entire simulation side reproducible
from this repo alone.
96 changes: 85 additions & 11 deletions docs/freedecay_validation.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
# Free-decay validation of the C++ VGOSWEC model against Husain et al. (Ogden et al., ASME JOMAE 145(3):030905), Table 2 and Fig. 4

## Foundation: plant validation against WEC-Sim

This validation is the **foundation** on which the three-regime controller/flap
co-design study rests. The co-design results are only meaningful because the
plant's **reactive impedance** (natural frequency **ω_n**) and **resistive
impedance** (damping ratio **ζ**, i.e. radiation damping **B55**) are
WEC-Sim-validated across the full **0°–90°** VGOSWEC geometric sweep
(VGM-0/10/20/45/90).

## Validation → Study bridge

The free-decay match is the bridge from plant model to controller study:
validating **ω_n** confirms the reactive impedance (**A55**-driven added
inertia plus hinge stiffness) that the **CC** and **opt_passive**
impedance-matching arguments depend on, while validating **ζ / B55** confirms
the radiation damping that sets **P_opt** and therefore the entire
capture-efficiency denominator used throughout the three-regime analysis.

## Purpose

This validation demonstrates that spring-only free-decay simulations in the C++ VGOSWEC model recover both the natural frequency **ω_n** and the damping ratio **ζ** for each available geometry, and match the values reported in Husain et al. / Ogden et al. (ASME JOMAE 145(3):030905) — Table 2 for ω_n, and Fig. 4 for ζ.
Expand Down Expand Up @@ -161,23 +179,79 @@ The numerical-dissipation component is minor (≈4×10⁻⁴, or ~8%) and conver

---

## Reproduction
## Full reproduction from a clean checkout

Run free-decay cases and regenerate all figures and the validation CSV:
The free-decay validation is reproducible end-to-end from this repository alone
as the following numbered pipeline:

```bash
# Optionally re-run simulations (requires built binary):
# python3 scripts/freedecay_validation.py --run --make-figures
1. **Build the SEA-Stack / Chrono binary**

# Reuse existing output CSVs (default):
python3 scripts/freedecay_validation.py --make-figures
```
```bash
source scripts/setup_env.sh
cmake -S . -B build \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH}"
cmake --build build -j$(nproc)
```

This produces `build/demo_vgoswec`. The documented prerequisites are
**SEA-Stack**, **Project Chrono**, **yaml-cpp**, and **Eigen3**; the
headless free-decay workflow below uses `--no-viz`, so it does **not**
require the optional GUI / VSG stack.

2. **Run the raw SEA-Stack free-decay cases**

```bash
for deg in 0 10 20 45 90; do
./build/demo_vgoswec --config config/vgoswec_${deg}_freedecay.yaml --no-viz
done
```

Each case writes `output/vgoswec_${deg}_freedecay_results.csv`. The analysis
consumes the resulting time histories, including `time_s`,
`flap_pitch_rad`, and the other solver-output columns in those CSVs.

3. **Run the Python free-decay analysis**

```bash
# Re-run sims internally AND regenerate the ζ analysis/figures:
python3 scripts/freedecay_validation.py --run --make-figures

# OR, if output/vgoswec_*_freedecay_results.csv already exist locally,
# reuse them and only re-analyze/re-plot the ζ outputs:
python3 scripts/freedecay_validation.py --make-figures
```

`--run` calls `build/demo_vgoswec` internally for each of the five
`config/vgoswec_{deg}_freedecay.yaml` cases, so step 2 is optional if you
use that flag. The unified driver depends only on **NumPy** (+ **Matplotlib**
when `--make-figures` is used). Shared `load_series`, peak-detection,
log-decrement, and ω_n-estimation helpers live in
`scripts/freedecay_analysis.py`.

4. **Refresh the ω_n summary CSV / figure**

```bash
python3 scripts/plot_freedecay_validation.py
```

This companion ω_n-only plotter writes `docs/freedecay_validation.csv` and
`docs/img/freedecay_validation.png`, using the just-generated
`output/vgoswec_*_freedecay_results.csv` when present and otherwise falling
back to its embedded validated values.

5. **Resulting artifacts**

The unified validation script (`scripts/freedecay_validation.py`) computes both ω_n (FFT + zero-cross) and ζ (logdec with correct n), prints the comparison table, writes `docs/freedecay_validation.csv`, and regenerates the ζ figures. It depends only on NumPy (+ optional Matplotlib for figures).
This pipeline regenerates the free-decay validation artifacts in order:

The ω_n-only plotting script is at `scripts/plot_freedecay_validation.py` (unchanged external behavior/outputs).
- `build/demo_vgoswec`
- `output/vgoswec_{0,10,20,45,90}_freedecay_results.csv`
- `docs/img/freedecay_zeta_validation.png`
- `docs/img/freedecay_zeta_decay_fit.png`
- `docs/freedecay_validation.csv`
- `docs/img/freedecay_validation.png`

Shared analysis functions (load_series, peak detection, logdec, ω_n estimation) are in `scripts/freedecay_analysis.py`.
The ω_n-only plotting script is at `scripts/plot_freedecay_validation.py`.

Quick Python extraction for ω_n (robust to NaNs, sorted time, and transient removal):

Expand Down