/** * CouplingManagerV2 — Generic multi-physics solver orchestration. * * Replaces the original CouplingManager's hard-coded solver types with the * generic SimSolver interface. Any solver that implements SimSolver can * participate in multi-physics coupling without modifying this file. * * ## Design Changes from V1 * * - Solvers registered as `SimSolver` (not typed unions) * - `getField()` delegated to `solver.getField(name)` (no switch statements) * - `step()` is async (supports TET10's async GPU solve) * - Field transfer works on any FieldData (RegularGrid3D, Float32Array, Float64Array) * * @see SimSolver — generic solver interface * @see SolverAdapters — wrappers for built-in solvers */ import type { SimSolver } from './SimSolver'; import { SaturationManager, type SaturationEvent } from './SaturationManager'; export interface FieldCouplingV2 { source: { solver: string; field: string; }; target: { solver: string; field: string; }; transform: (value: number) => number; enabled?: boolean; } export interface CouplingStatsV2 { solverCount: number; couplingCount: number; saturationMonitors: number; totalEvents: number; lastStepMs: number; } export declare class CouplingManagerV2 { private solvers; private couplings; private saturationManagers; private lastEvents; private totalEvents; private lastStepMs; /** Register a solver with a unique name. */ registerSolver(name: string, solver: SimSolver): void; /** Add a field coupling between two solvers. */ addCoupling(coupling: FieldCouplingV2): void; /** Add a saturation monitor. */ addSaturationMonitor(monitor: SaturationManager): void; /** * Step all solvers, transfer coupled fields, check saturation. * * Order: * 1. Step transient solvers (e.g., thermal) * 2. Transfer coupled fields * 3. Solve steady-state solvers (e.g., structural, hydraulic) * 4. Check saturation thresholds */ step(dt: number): Promise; /** * Transfer a field value from source solver to target solver. * * Transfer semantics: **co-located, same-topology, element-index-mapped**. * Every `FieldData` (RegularGrid3D or bare typed array) is reduced to its flat * numeric buffer and transferred element-for-element with the coupling * transform. This is correct only when source and target discretizations are * co-located and share topology (equal element counts) — the assumption every * production coupling in-tree relies on. * * Two behaviours are deliberate: * - ALL four container combinations (grid↔grid, array↔array, grid↔array, * array↔grid) are handled. Previously grid↔array pairs matched neither * branch and were a **silent no-op** — the actual live coupling * (thermal `temperature` Float32Array ↔ reaction `temperature_grid` * RegularGrid3D) transferred nothing. * - A genuine element-count mismatch **throws** rather than silently * truncating to `min(len)`. `FieldData` carries no geometry * (grids have spacing but no origin; arrays carry no coordinates), so * non-matching discretizations cannot be interpolated here — transferring a * prefix would be silently-wrong physics. Cross-discretization interpolation * (trilinear by world coordinate / TET10 shape-function remap) requires a * geometry-carrying field model and is intentionally not implemented here. */ private transferField; getLastEvents(): SaturationEvent[]; setCouplingEnabled(index: number, enabled: boolean): void; getStats(): CouplingStatsV2; dispose(): void; } //# sourceMappingURL=CouplingManagerV2.d.ts.map