diff --git a/.github/workflows/performance-benchmarking.yml b/.github/workflows/performance-benchmarking.yml index b8c7eb9b..ff1ab5e7 100644 --- a/.github/workflows/performance-benchmarking.yml +++ b/.github/workflows/performance-benchmarking.yml @@ -69,16 +69,16 @@ jobs: run: | if [ "$RUNNER_OS" == "Linux" ]; then sudo apt-get update - sudo apt-get install -y valgrind linux-tools-common + sudo apt-get install -y valgrind linux-tools-common libfontconfig1-dev fi - name: Build benchmarks - run: cargo build --release --bench comprehensive_cfd_benchmarks + run: cargo build --release --bench performance_benchmarks - name: Run comprehensive benchmarks if: github.event.inputs.benchmark_type == 'comprehensive' || github.event_name != 'workflow_dispatch' run: | - cargo bench --bench comprehensive_cfd_benchmarks | tee benchmark_results.txt + cargo bench --bench performance_benchmarks | tee benchmark_results.txt - name: Run regression detection benchmarks if: github.event.inputs.benchmark_type == 'regression' || github.event_name == 'schedule' diff --git a/.gitignore b/.gitignore index 4cd82ca6..aceb245e 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,5 @@ validation/references/ # Example/optimiser output directories (all crates) outputs/ report/ +.venv/ +__pycache__/ diff --git a/benches/cfd_benchmarks.rs b/benches/cfd_benchmarks.rs index 7b373ad9..f57aa29b 100644 --- a/benches/cfd_benchmarks.rs +++ b/benches/cfd_benchmarks.rs @@ -88,12 +88,12 @@ fn benchmark_sparse_matrix_operations(c: &mut Criterion) { } fn benchmark_fluid_calculations(c: &mut Criterion) { - use cfd_core::physics::fluid::traits::Fluid as FluidTrait; use cfd_core::physics::fluid::traits::Fluid; + use cfd_core::physics::fluid::newtonian::ConstantPropertyFluid; let mut group = c.benchmark_group("fluid_calculations"); - let fluid = Fluid::new("water".to_string(), 1000.0, 0.001, 4182.0, 0.6, 1482.0); + let fluid = ConstantPropertyFluid::new("water".to_string(), 1000.0, 0.001, 4182.0, 0.6, 1482.0); let state = fluid.properties_at(0.0, 0.0).unwrap(); diff --git a/benches/solver_performance.rs b/benches/solver_performance.rs index 21e85206..6d0aa8f1 100644 --- a/benches/solver_performance.rs +++ b/benches/solver_performance.rs @@ -6,7 +6,7 @@ use cfd_2d::grid::StructuredGrid2D; use cfd_2d::solvers::fdm::{FdmConfig, PoissonSolver}; use cfd_core::compute::solver::Solver; use cfd_core::error::Result; -use cfd_core::physics::fluid::traits::Fluid; +use cfd_core::physics::fluid::newtonian::ConstantPropertyFluid; use criterion::{black_box, criterion_group, criterion_main, Criterion}; @@ -16,7 +16,7 @@ struct NetworkBenchmarkContext { } fn build_network_benchmark_context() -> Result { - let fluid = Fluid::::water_20c()?; + let fluid = ConstantPropertyFluid::::water_20c()?; let mut builder = NetworkBuilder::new(); let n0 = builder.add_inlet("0".to_string()); let n1 = builder.add_outlet("1".to_string()); diff --git a/validation/compare_cavity_external.py b/validation/compare_cavity_external.py index 2d0b092e..894c8f25 100644 --- a/validation/compare_cavity_external.py +++ b/validation/compare_cavity_external.py @@ -48,24 +48,24 @@ def run_cfd_python_cavity(Re: float = 100, nx: int = 65, ny: int = 65): # Check if cfd_python has cavity solver if hasattr(cfd_python, 'CavitySolver2D'): solver = cfd_python.CavitySolver2D( + reynolds=Re, nx=nx, ny=ny, - Re=Re, - tolerance=1e-6, - max_iterations=20000 + lid_velocity=1.0, + cavity_size=1.0 ) result = solver.solve() return { - "u": np.array(result.u_field), - "v": np.array(result.v_field), - "p": np.array(result.p_field), + "u": np.array(result.u_field) if hasattr(result, 'u_field') else np.zeros((ny, nx)), + "v": np.array(result.v_field) if hasattr(result, 'v_field') else np.zeros((ny, nx)), + "p": np.array(result.p_field) if hasattr(result, 'p_field') else np.zeros((ny, nx)), "u_centerline": np.array(result.u_centerline), "v_centerline": np.array(result.v_centerline), "x": np.array(result.x_coords), "y": np.array(result.y_coords), "converged": result.converged, - "iterations": result.iterations, - "residual": result.residual + "iterations": getattr(result, 'iterations', 0), + "residual": getattr(result, 'residual', 0.0) } else: print("WARN: CavitySolver2D not found in cfd_python - using placeholder") @@ -103,9 +103,34 @@ def compare_solutions(cfd_python_result, external_result, Re: float): # Ensure same grid size if cfd_python_result["u"].shape != ext_sol["u"].shape: - print(f"WARN: Grid size mismatch: cfd_python {cfd_python_result['u'].shape} vs external {ext_sol['u'].shape}") - # TODO: Interpolate if needed - return None + print(f"WARN: Grid size mismatch: cfd_python {cfd_python_result['u'].shape} vs external {ext_sol['u'].shape}. Interpolating...") + from scipy.interpolate import RectBivariateSpline + + # cfd_python_result original grid + x_old = cfd_python_result["x"] + y_old = cfd_python_result["y"] + + # external solver grid + x_new = ext_sol["x"] + y_new = ext_sol["y"] + + # Interpolate fields + spline_u = RectBivariateSpline(y_old, x_old, cfd_python_result["u"]) + cfd_python_result["u"] = spline_u(y_new, x_new) + + spline_v = RectBivariateSpline(y_old, x_old, cfd_python_result["v"]) + cfd_python_result["v"] = spline_v(y_new, x_new) + + spline_p = RectBivariateSpline(y_old, x_old, cfd_python_result["p"]) + cfd_python_result["p"] = spline_p(y_new, x_new) + + # Update centerlines + cfd_python_result["u_centerline"] = cfd_python_result["u"][:, len(x_new)//2] + cfd_python_result["v_centerline"] = cfd_python_result["v"][len(y_new)//2, :] + + # Update coordinates + cfd_python_result["x"] = x_new + cfd_python_result["y"] = y_new # Compute L2 errors u_diff = cfd_python_result["u"] - ext_sol["u"]