Sound
Environmental noise prediction with Nord2000 in Rhino—sources, propagation, ground effect, diffraction, and compliance metrics.
The Sound system in Balarhinos predicts environmental noise using a staged implementation of Nord2000, with a clear separation between Rhino/UI and the numerical kernel (CPU/GPU).
Goal
Build an interactive Rhino plugin that predicts environmental noise using (a staged subset of) Nord2000:
- Rhino/UI — Presentation, interaction, and visualization
- Numerical kernel — Emission, propagation, and band summation (CPU reference + optional GPU acceleration)
Guiding principles
- Keep Rhino types out of the hot loop — Convert geometry to flat arrays (points, segments, triangles, material ids).
- Test-driven early — Implement known validation/regression cases before optimizing.
- Two execution modes — CPU reference (correctness + debugging) and GPU-accelerated (speed + large receiver grids).
Architecture (three layers)
Layer 1: Presentation & interaction (UI)
- Tech: C# + RhinoCommon + Eto.Forms
- Responsibilities:
- User controls: sources, receivers, settings, meteo presets, ground classes
- Visualization: noise maps, rays/path debug, isolines
- Caching toggles and run/cancel jobs
- Rhino patterns: Eto panels, DisplayConduit for viewport overlays (mesh heatmap + debug lines), command + panel workflow (no long-running compute on UI thread).
Layer 2: Orchestration & geometry pipeline (preprocessing)
- Tech: C# (.NET 8)
- Responsibilities:
- Observe doc changes and rebuild only what’s needed (incremental updates)
- Convert Rhino objects to lightweight acoustic primitives
- Build spatial acceleration structures for fast queries
- Outputs (immutable snapshots to the kernel):
- Source primitives (point/line segments with emission parameters)
- Obstacle primitives (screens, building edges, terrain profiles)
- Terrain (mesh triangles or heightfield + material/impedance id)
- Receiver grid (points + optional normals/area weights)
Layer 3: Computational core (physics kernel)
- Tech: C++ (native) + CUDA for kernels, or C# with unsafe + SIMD + Parallel.For (CPU baseline)
- Responsibilities:
- All Nord2000 math: emission + propagation + band summation + statistics
- No Rhino dependencies; inputs are plain arrays/structs
- GPU fit: “Many receivers × many bands × many source segments” accumulation maps well to CUDA; geometry queries need careful BVH/acceleration design.
Data contracts
Acoustic sources
- Type: Road | Rail
- Geometry: Polyline segments (discretized from Rhino curves)
- Emission parameters: vehicle_flow, speed, surface_type, heavy_vehicle_ratio, etc.
- Discretization: segment_length_m (accuracy vs performance), multi-height point model per mechanism
Ground / materials
- ground_class_id per triangle/segment → flow resistivity (σ) and impedance
- Impedance lookup tables in the kernel for fast access
Obstacles
- Screens/buildings as edges/polylines (diffraction) and optionally triangles for occlusion
Receivers
- Receiver points array and grid metadata (resolution, bounds) for visualization
Implementation phases
Phase 1 — Engineering preview
- Source attachment: Attach an AcousticSource component to Rhino curves (roads/rails); store attributes via UserData or document-level tables; discretize curve → polyline → segments → point sources; keep segmentation stable to avoid flicker.
- Emission (1/3 octave bands): Sound power spectra 25 Hz–10 kHz; separate mechanisms (e.g. rolling vs propulsion); output Lw[band] per source element.
- Straight-line propagation (homogeneous): Geometric spreading, atmospheric absorption (band-dependent); line-of-sight only (no terrain/diffraction yet). Debug: draw source→receiver rays and show spreading vs absorption in an inspector panel.
Phase 2 — Geometry & ground
- Terrain profiling: For each source–receiver pair, 2.5D profile (vertical section); mesh intersection or heightfield sampling; preprocess/cache profiles where possible; avoid heavy Rhino intersection inside the inner loop.
- Ground effect / Fresnel weighting: Which ground segments affect interference/reflection; Fresnel-zone extent per band; blend impedance for mixed surfaces; use impedance ids + lookup tables.
- Screening & diffraction: Dominant edge(s), path difference δ, diffraction attenuation per band; single screen vs multiple edges; “rubber band” / shortest-detour method; debug: visualize diffracting edge and detour path.
Phase 3 — Nord2000 signature + production
- Meteorology & curved rays: Refraction-aware propagation with c(z) (wind + temperature); curved rays; strategy pattern: LinearPathStrategy vs CurvedRayStrategy; refraction math in kernel only.
- Weather-class statistics: Run propagation per meteo class; integrate with occurrence weights; output Lden, Lnight, etc.
- Visualization: Reuse MeshBuilder for receiver grid mesh; SetGridDimensions + GenerateGridFaces + ApplyMultiGradient(dB → colors); Conduit-based noise map (thread-safe, singleton); isolines and selection/hover for receiver levels.
Integration with Smart Geometry
Sound analysis uses your Smart Geometry and semantic categories so that roads, rails, terrain, and obstacles are identified consistently. Source and receiver grids align with your site model for repeatable, compliant environmental noise assessment.
Summary
| Area | Capability |
|---|---|
| Sources | Curve → segments → point sources; emission in 1/3 octave bands |
| Ground | Impedance id per segment; Fresnel-weighted blending |
| Geometry | Terrain profile extraction; screen detection + diffraction |
| Speed | Kernel uses float/double arrays only; CPU reference + GPU for large grids |
| Validation | Regression suite early; optimize after CPU reference matches test cases |
For implementation details and kernel contracts, see the Nord2000 blueprint in the Balarhinos docs repository (systems/simulation/nord2000_blueprint.md).