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
49 changes: 49 additions & 0 deletions _4_OptSim/StandardSens/configs/trade_study.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# A trade study: named vehicles compared across the standard sims.
#
# make opt-trade
# make opt-trade STUDY=path/to/another_study.yaml
#
# See docs/doe-reverse-engineering.md. Copy this file for each study; results land
# in _4_OptSim/results/trade/<name>.md and .csv.
name: rear_roll_stiffness

# Each candidate is the baseline vehicle with these variables changed. Any
# variable declared in vehicle_architecture.yaml may be used, mass and CG
# included, because every candidate is compiled rather than overridden. The
# baseline is always included and needs no entry.
#
# `both` makes exactly the changes of the other two, so the report also says
# whether those two changes stack or interact.
candidates:
stiff_rear_bar:
rear.stabar.rate_n_m_per_rad: 961.495352
soft_front_spring:
front.actuation.spring_rate_n_per_m: 21015.2202
both:
rear.stabar.rate_n_m_per_rad: 961.495352
front.actuation.spring_rate_n_per_m: 21015.2202

# What to compare, per standard: SteadyStateEval, RampSteerEval or TransientEval.
# All three run against the one executable compiled for each candidate.
#
# `resolution` is the smallest change worth acting on. A smaller delta is still
# reported, marked `~`. Leave it off and the delta is reported unjudged. There is
# no score and no ranking: what a tenth of a degree of understeer is worth in
# settling time is your call, not the tool's.
metrics:
SteadyStateEval:
understeer_gradient_deg_per_g: {resolution: 0.02}
roll_gradient_deg_per_g: {resolution: 0.02}
peak_handwheel_torque_Nm: {resolution: 0.5}
TransientEval:
yaw_rise_time_s: {resolution: 0.005}
yaw_overshoot_pct: {resolution: 1.0}
roll_overshoot_pct: {resolution: 1.0}
settling_time_s: {resolution: 0.05}

# Also render each standard's PDF report per vehicle. Worth having when the study
# goes in front of a design review; costs roughly ten seconds per run.
render_reports: true

# CPUs available to simulations (the Docker container's count, not the host's).
cpus: 12
9 changes: 6 additions & 3 deletions _4_OptSim/StandardSens/pipeline/batch.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""batch.py — Run the SteadyStateEval report wrapper for all variants.
"""batch.py — Run each configured standard for all variants.

For each variant_XXXX/build/<standard>/ that has a compiled executable:
1. Skip if metrics.csv already exists and is valid (correct row count)
Expand All @@ -20,7 +20,7 @@
import pandas as pd
import yaml

from StandardSens.pipeline.steady_state_eval_report import run_report
from StandardSens.pipeline.standards import get_standard, run_standard

# ---------------------------------------------------------------------------
# Config
Expand Down Expand Up @@ -83,7 +83,10 @@ def run_variant(
results_dir.mkdir(parents=True, exist_ok=True)

try:
metrics_csv = run_report(
# Dispatch on the standard's name: running one standard's report against
# another's executable fails late and unhelpfully.
metrics_csv = run_standard(
get_standard(standard),
variant_dir=variant_dir,
build_dir=build_dir,
exec_name=standard_cfg["model"],
Expand Down
8 changes: 8 additions & 0 deletions _4_OptSim/StandardSens/pipeline/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

from __future__ import annotations

from collections.abc import Collection
import platform
import subprocess
import sys
Expand Down Expand Up @@ -55,6 +56,7 @@
# list would keep caches its neighbour had already declared stale.
PIPELINE_TOOLING_INPUTS = (
DEFAULT_REPORT_WRAPPER,
STANDARD_DIR / "pipeline/standards.py",
DEFAULT_STEADY_STATE_SIM,
DEFAULT_STEADY_STATE_CONFIG,
DEFAULT_MODELICA_RUNNER,
Expand Down Expand Up @@ -269,16 +271,22 @@ def compile_all(
template_path: Path = DEFAULT_MOS_TEMPLATE,
doe_config_path: Path = DEFAULT_DOE_CONFIG,
architecture_config_path: Path = DEFAULT_ARCHITECTURE_CONFIG,
only_standards: Collection[str] | None = None,
) -> dict[str, list[Path]]:
"""Compile all variants in population_dir for all standards in config.

`only_standards` narrows that to the named ones, for callers that run several
standards against one executable and must not pay for a build per standard.

Skips variants that are already compiled and whose inputs haven't changed.
Runs variants in parallel using ProcessPoolExecutor.
Returns dict mapping standard -> list of successful exe paths.
Failed variants are logged and skipped.
"""
cfg = load_compiler_config(compiler_config_path)
standards: dict[str, dict] = cfg["standards"]
if only_standards is not None:
standards = {name: standards[name] for name in only_standards}
max_workers: int = cfg.get("max_workers", 2)

# Resolve boblib_path relative to the config file
Expand Down
Loading
Loading