diff --git a/crates/specialized/rtx-cfd/src/solvers/incompressible/embedded3/step/device.rs b/crates/specialized/rtx-cfd/src/solvers/incompressible/embedded3/step/device.rs index 52fe7f5..2b62e30 100644 --- a/crates/specialized/rtx-cfd/src/solvers/incompressible/embedded3/step/device.rs +++ b/crates/specialized/rtx-cfd/src/solvers/incompressible/embedded3/step/device.rs @@ -292,6 +292,24 @@ impl DeviceStep { rt.stream.synchronize().expect("sync"); } + /// R6-3 (`RTX_E3_FIELD_P_ONLY=1`): the pressure alone down (the + /// device-imposed rebuild's only host read). + pub fn download_p(&self, field: &mut Field) { + let rt = runtime(); + assert_eq!(field.grid, self.grid); + rt.stream.memcpy_dtoh(&self.p, &mut field.p).expect("p"); + rt.stream.synchronize().expect("sync"); + } + + /// R6-3: the pressure alone up (the fresh cells' refill; u, v, w were + /// not touched on the host). + pub fn upload_p(&mut self, field: &Field) { + let rt = runtime(); + assert_eq!(field.grid, self.grid); + rt.stream.memcpy_htod(&field.p, &mut self.p).expect("p"); + rt.stream.synchronize().expect("sync"); + } + /// The arrays a moving body's mask rebuild reads (P1-3 (c)): the /// corrected velocities, the pressure and the previous velocities. pub fn download_for_rebuild(&self, field: &mut Field) { diff --git a/crates/specialized/rtx-cfd/src/solvers/incompressible/embedded3/step/device/cut.rs b/crates/specialized/rtx-cfd/src/solvers/incompressible/embedded3/step/device/cut.rs index 764aac0..0458b17 100644 --- a/crates/specialized/rtx-cfd/src/solvers/incompressible/embedded3/step/device/cut.rs +++ b/crates/specialized/rtx-cfd/src/solvers/incompressible/embedded3/step/device/cut.rs @@ -909,7 +909,16 @@ impl DeviceStep { // w, p (fresh cells take their neighbours' pressure) and the // previous velocities (the imposition's source). let mut field = self.host_field.take().unwrap_or_else(|| Field::new(g)); - self.download_for_rebuild(&mut field); + // R6-3 (`RTX_E3_FIELD_P_ONLY=1`, default off; not under the band + // check, whose references read the whole mirror): the download + // waits until the step's rebuild route is known — with the device + // classification and imposition the host rebuild reads and writes + // the pressure alone (the fresh cells' refill), so only p moves. + let p_only = super::poisson_setup::field_p_only() + && std::env::var("RTX_E3_BAND_CHECK").is_err(); + if !p_only { + self.download_for_rebuild(&mut field); + } let l_down = lap.elapsed(); // R6-1 (default ON, `RTX_E3_GEOM_DEVICE=0` off): the end-of-step // cut geometry on the device, its face tables written into the @@ -985,10 +994,30 @@ impl DeviceStep { ); } } + let mut l_down = l_down; + let partial = p_only + && self + .solver + .pending_mask + .as_ref() + .is_some_and(|u| u.impose_on_device); + if p_only { + let ld = Instant::now(); + if partial { + self.download_p(&mut field); + } else { + self.download_for_rebuild(&mut field); + } + l_down += ld.elapsed(); + } let l_geom = lap.elapsed(); fresh_cells = self.solver.rebuild_moving_mask(&mut field, dt, t_new); let l_mask = lap.elapsed(); - self.upload_after_rebuild(&field); + if partial { + self.upload_p(&field); + } else { + self.upload_after_rebuild(&field); + } self.host_field = Some(field); let l_up = lap.elapsed(); // P1-5: the persistent tables updated in place when the mask has a diff --git a/crates/specialized/rtx-cfd/src/solvers/incompressible/embedded3/step/device/poisson_setup.rs b/crates/specialized/rtx-cfd/src/solvers/incompressible/embedded3/step/device/poisson_setup.rs index a83d4da..e236985 100644 --- a/crates/specialized/rtx-cfd/src/solvers/incompressible/embedded3/step/device/poisson_setup.rs +++ b/crates/specialized/rtx-cfd/src/solvers/incompressible/embedded3/step/device/poisson_setup.rs @@ -52,3 +52,10 @@ pub(super) fn device_grid(solver: &Solver, g: Grid, dt: f64) -> Option bool { + std::env::var("RTX_E3_FIELD_P_ONLY").is_ok_and(|v| v == "1") +}