diff --git a/crates/specialized/rtx-cfd/src/solvers/incompressible/embedded3/poisson/device_cg.rs b/crates/specialized/rtx-cfd/src/solvers/incompressible/embedded3/poisson/device_cg.rs index 10d1665..e307745 100644 --- a/crates/specialized/rtx-cfd/src/solvers/incompressible/embedded3/poisson/device_cg.rs +++ b/crates/specialized/rtx-cfd/src/solvers/incompressible/embedded3/poisson/device_cg.rs @@ -243,9 +243,9 @@ impl DeviceCg { self.active_host = fine.active.clone(); self.key = OperatorKey::of(problem, params); // The V-cycle's finest level follows the operator (its coarser - // levels stay). - let levels = export_hierarchy(problem, params); - self.vcycle.refresh_fine(&levels[0]); + // levels stay): the fine level alone, no hierarchy build. + let fine_level = super::export::export_fine(problem); + self.vcycle.refresh_fine(&fine_level); } pub fn n_cells(&self) -> usize { diff --git a/crates/specialized/rtx-cfd/src/solvers/incompressible/embedded3/poisson/export.rs b/crates/specialized/rtx-cfd/src/solvers/incompressible/embedded3/poisson/export.rs index f6b6f67..a978091 100644 --- a/crates/specialized/rtx-cfd/src/solvers/incompressible/embedded3/poisson/export.rs +++ b/crates/specialized/rtx-cfd/src/solvers/incompressible/embedded3/poisson/export.rs @@ -2,7 +2,7 @@ //! lists (cells, colours, the neighbour arrays, the parent map, the CSR //! children) and the seven coefficient arrays. -use super::{Hierarchy, Problem}; +use super::{Hierarchy, Level, Problem}; use crate::solvers::incompressible::poisson::MultigridParameters; /// One exported level. `top`/`bot`: the neighbour above/below each cell @@ -91,6 +91,40 @@ pub fn export_hierarchy(problem: &Problem, params: &MultigridParameters) -> Vec< .collect() } +/// The finest level alone (its cells, colours, neighbours, the geometric +/// parent map and coefficients; no children lists — those belong to the +/// coarse level's restriction and stay with the kept hierarchy): what a +/// per-step operator refresh needs, without building the hierarchy. +pub fn export_fine(problem: &Problem) -> LevelExport { + let lv = Level::::new(problem.clone()); + let (_, coarse_of) = lv.coarsen(); + let to_u32 = |v: &[usize]| { + v.iter() + .map(|&i| if i == usize::MAX { u32::MAX } else { i as u32 }) + .collect::>() + }; + LevelExport { + nx: lv.problem.nx, + ny: lv.problem.ny, + nz: lv.problem.nz, + cells: to_u32(&lv.cells), + red: to_u32(&lv.red), + black: to_u32(&lv.black), + top: to_u32(&lv.top), + bot: to_u32(&lv.bot), + coarse_of: to_u32(&coarse_of), + children_ptr: Vec::new(), + children_idx: Vec::new(), + ae: lv.ae, + aw: lv.aw, + an: lv.an, + as_: lv.as_, + at: lv.at, + ab: lv.ab, + ap: lv.ap, + } +} + /// `z = M⁻¹ r` by the host f32 V-cycle: the reference a device V-cycle is measured against. pub fn vcycle_f32_reference( problem: &Problem, diff --git a/crates/specialized/rtx-cfd/src/solvers/incompressible/embedded3/poisson/hierarchy.rs b/crates/specialized/rtx-cfd/src/solvers/incompressible/embedded3/poisson/hierarchy.rs index 814085b..726b39c 100644 --- a/crates/specialized/rtx-cfd/src/solvers/incompressible/embedded3/poisson/hierarchy.rs +++ b/crates/specialized/rtx-cfd/src/solvers/incompressible/embedded3/poisson/hierarchy.rs @@ -206,7 +206,7 @@ impl Level { } /// Galerkin coarsening by 2 in every direction (the 2D rule with k). - fn coarsen(&self) -> (Problem, Vec) { + pub(crate) fn coarsen(&self) -> (Problem, Vec) { let p = &self.problem; let (nx, ny, nz) = (p.nx, p.ny, p.nz); let nxc = (nx / 2).max(1);