Spaces:
Running
Running
| """Real DrivAerNet++ data access — retrieval & statistics. | |
| DrivAerNet++ (Elrefaie et al., MIT, CC-BY-NC-4.0) is a public dataset of | |
| 8,150 car designs each with high-fidelity OpenFOAM CFD results. The full | |
| dataset is 39 TB (meshes + volume fields) hosted on Harvard Dataverse, | |
| but the per-design aerodynamic drag coefficients ship as a small CSV that | |
| we vendor locally under ./DrivAerNet/. | |
| This module mirrors the *Simulation Agent* retrieval idea from the | |
| "AI Agents in Engineering Design" paper: rather than running CFD on a new | |
| shape, look up the closest REAL pre-computed cases and report their | |
| measured drag. It needs no torch and no mesh download — just the CSV. | |
| Design-ID morphology codes (first token of the ID): | |
| F = Fastback N = Notchback (sedan) E = Estate (wagon) | |
| Functions: | |
| load_cd() -> dict {design_id: Cd} | |
| dataset_stats() -> overall + per-class statistics | |
| retrieve_by_cd(target) -> closest real designs to a target Cd | |
| class_means() -> mean Cd per body morphology | |
| """ | |
| from __future__ import annotations | |
| import csv | |
| from pathlib import Path | |
| from typing import Dict, List, Optional, Tuple | |
| _DATA_DIR = Path(__file__).parent / "DrivAerNet" | |
| _CD_CSV = _DATA_DIR / "DrivAerNetPlusPlus_Cd_8k.csv" | |
| _CLASS_NAMES = {"F": "Fastback", "N": "Notchback (sedan)", "E": "Estate (wagon)"} | |
| _CACHE: Optional[Dict[str, float]] = None | |
| def available() -> bool: | |
| return _CD_CSV.exists() | |
| def load_cd() -> Dict[str, float]: | |
| """Return {design_id: Cd} from the vendored DrivAerNet++ CSV.""" | |
| global _CACHE | |
| if _CACHE is not None: | |
| return _CACHE | |
| out: Dict[str, float] = {} | |
| if not _CD_CSV.exists(): | |
| return out | |
| with open(_CD_CSV) as f: | |
| rd = csv.DictReader(f) | |
| id_key = rd.fieldnames[0] | |
| cd_key = next((k for k in rd.fieldnames | |
| if k and ("drag" in k.lower() or k.lower() == "cd")), | |
| rd.fieldnames[-1]) | |
| for row in rd: | |
| try: | |
| out[str(row[id_key]).strip()] = float(row[cd_key]) | |
| except (ValueError, KeyError, TypeError): | |
| continue | |
| _CACHE = out | |
| return out | |
| def _morphology(design_id: str) -> str: | |
| return design_id.split("_", 1)[0].upper() | |
| def class_means() -> Dict[str, Tuple[str, int, float, float, float]]: | |
| """Per-morphology (name, n, mean, min, max) of real Cd.""" | |
| cd = load_cd() | |
| buckets: Dict[str, List[float]] = {} | |
| for k, v in cd.items(): | |
| buckets.setdefault(_morphology(k), []).append(v) | |
| res = {} | |
| for c, vals in sorted(buckets.items()): | |
| res[c] = (_CLASS_NAMES.get(c, c), len(vals), | |
| sum(vals) / len(vals), min(vals), max(vals)) | |
| return res | |
| def dataset_stats() -> dict: | |
| cd = load_cd() | |
| if not cd: | |
| return {"available": False} | |
| vals = list(cd.values()) | |
| n = len(vals) | |
| mean = sum(vals) / n | |
| var = sum((x - mean) ** 2 for x in vals) / n | |
| return { | |
| "available": True, | |
| "n": n, | |
| "cd_min": min(vals), | |
| "cd_mean": mean, | |
| "cd_max": max(vals), | |
| "cd_std": var ** 0.5, | |
| "classes": class_means(), | |
| "source": str(_CD_CSV.name), | |
| } | |
| def retrieve_by_cd(target_cd: float, n: int = 5, | |
| morphology: Optional[str] = None | |
| ) -> List[Tuple[str, float, float]]: | |
| """Return the n real designs whose Cd is closest to target_cd. | |
| Each item is (design_id, cd, abs_error). Optionally restrict to a | |
| morphology class ("F"/"N"/"E"). Mirrors the paper's "show me designs | |
| with drag near X" retrieval, but over the REAL CFD dataset. | |
| """ | |
| cd = load_cd() | |
| items = cd.items() | |
| if morphology: | |
| m = morphology.upper() | |
| items = [(k, v) for k, v in items if _morphology(k) == m] | |
| else: | |
| items = list(items) | |
| ranked = sorted(items, key=lambda kv: abs(kv[1] - target_cd)) | |
| return [(k, v, abs(v - target_cd)) for k, v in ranked[:n]] | |
| if __name__ == "__main__": | |
| s = dataset_stats() | |
| if not s["available"]: | |
| print("DrivAerNet++ CSV not found — run fetch_drivaernet to download it.") | |
| raise SystemExit(1) | |
| print(f"DrivAerNet++ real drag data ({s['source']})") | |
| print(f" N={s['n']} Cd mean={s['cd_mean']:.3f} " | |
| f"std={s['cd_std']:.3f} range [{s['cd_min']:.3f}, {s['cd_max']:.3f}]") | |
| print(" per body class:") | |
| for c, (name, cnt, mean, lo, hi) in s["classes"].items(): | |
| print(f" {c} {name:18s} n={cnt:4d} mean={mean:.3f} [{lo:.3f}, {hi:.3f}]") | |
| print("\n retrieval demo - closest real designs to Cd=0.25:") | |
| for did, cd, err in retrieve_by_cd(0.25, n=5): | |
| print(f" {did:18s} Cd={cd:.4f} (d={err:.4f})") | |