diff --git a/crates/specialized/rtx-cfd/src/solvers/incompressible/embedded3/poisson/mod.rs b/crates/specialized/rtx-cfd/src/solvers/incompressible/embedded3/poisson/mod.rs index 1abb7f6..4d66ad2 100644 --- a/crates/specialized/rtx-cfd/src/solvers/incompressible/embedded3/poisson/mod.rs +++ b/crates/specialized/rtx-cfd/src/solvers/incompressible/embedded3/poisson/mod.rs @@ -8,7 +8,7 @@ pub mod device; #[cfg(feature = "cuda")] pub mod device_cg; -mod export; +pub mod export; mod hierarchy; mod pcg; mod problem; diff --git a/crates/specialized/rtx-cfd/src/solvers/incompressible/embedded3/step/projection.rs b/crates/specialized/rtx-cfd/src/solvers/incompressible/embedded3/step/projection.rs index 71d653c..0a76ac5 100644 --- a/crates/specialized/rtx-cfd/src/solvers/incompressible/embedded3/step/projection.rs +++ b/crates/specialized/rtx-cfd/src/solvers/incompressible/embedded3/step/projection.rs @@ -12,7 +12,7 @@ impl Solver { /// faces): coefficient `dt · A / δ` across every fluid interior face, /// zero across prescribed ones, the outlet's Dirichlet half a cell out /// as `extra_diag`; the right-hand side left zero. - pub(crate) fn poisson_operator(&self, g: Grid, dt: f64) -> Problem { + pub fn poisson_operator(&self, g: Grid, dt: f64) -> Problem { let (nx, ny, nz, dx, dy, dz) = (g.nx, g.ny, g.nz, g.dx, g.dy, g.dz); let b = self.params.boundaries; let outlet = Side::PressureOutlet; diff --git a/crates/specialized/rtx-cfd/tests/embedded3_flag_geometry.rs b/crates/specialized/rtx-cfd/tests/embedded3_flag_geometry.rs index b67ca35..87864cd 100644 --- a/crates/specialized/rtx-cfd/tests/embedded3_flag_geometry.rs +++ b/crates/specialized/rtx-cfd/tests/embedded3_flag_geometry.rs @@ -197,3 +197,55 @@ fn narrow_band_is_bit_identical_and_fast() { ); assert!(vol_same); } + +/// The per-step operator cost at ny 62 (host side of the device CG's +/// rebuild: the problem, the fine level, the components, the hierarchy +/// export) — S2-2b-ii's target. +#[test] +#[ignore = "profile: the operator export at ny 62 (seconds)"] +fn operator_export_profile_at_ny_62() { + use rtx_cfd::solvers::incompressible::embedded3::poisson::export::export_hierarchy; + use rtx_cfd::solvers::incompressible::embedded3::{ + Field, Fluid, Parameters, Solver, WallScheme, + }; + use rtx_cfd::solvers::incompressible::{ConvectionScheme, MultigridParameters}; + let ny = 62; + let h = H / ny as f64; + let nx = (2.5 / h).round() as usize; + let g = Grid::cubic(nx, ny, ny, h); + let cyl = |x: f64, y: f64| ((x - 0.2_f64).powi(2) + (y - 0.2_f64).powi(2)).sqrt() - 0.05; + let body = Body::from_sdf(move |x, y, z, _t| cyl(x, y).min(flag_3d(x, y, z, 0.3, h))); + let mut solver = Solver::new( + Fluid { + density: 1000.0, + viscosity: 1.0, + reference_velocity: 1.0, + reference_length: 0.1, + }, + Parameters { + wall_scheme: WallScheme::CutCell, + convection_scheme: ConvectionScheme::TvdVanAlbada, + boundaries: Boundaries { + x1: Side::PressureOutlet, + ..Boundaries::default() + }, + ..Parameters::default() + }, + ); + solver.set_body(body); + let mut f = Field::new(g); + let t0 = std::time::Instant::now(); + solver.initialize(&mut f); + let t_init = t0.elapsed().as_secs_f64(); + let t1 = std::time::Instant::now(); + let problem = solver.poisson_operator(g, 1e-3); + let t_op = t1.elapsed().as_secs_f64(); + let t2 = std::time::Instant::now(); + let levels = export_hierarchy(&problem, &MultigridParameters::default()); + let t_exp = t2.elapsed().as_secs_f64(); + println!( + " ny 62 operator: initialize (mask + impose) {t_init:.2} s, poisson_operator {t_op:.2} s, export_hierarchy {t_exp:.2} s ({} levels, {} links)", + levels.len(), + problem.links.len() + ); +}