embedded3 R6-3: RTX_E3_FIELD_P_ONLY=1 (default off) — the rebuild's field transfer limited to p when the classification and imposition ran on the device

The download waits until the step's rebuild route is known; with the device
mask and device imposition the host rebuild reads and writes only the
pressure (the fresh cells' refill), so u, v, w and the old velocities stay on
the device (their upload wrote back the values just downloaded). Not under
RTX_E3_BAND_CHECK (its references read the whole mirror).

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
Omar Sobh
2026-09-25 03:28:30 -05:00
co-authored by Claude Opus 5.5
parent 348f4621d1
commit b00f297ef7
3 changed files with 56 additions and 2 deletions
@@ -292,6 +292,24 @@ impl DeviceStep {
rt.stream.synchronize().expect("sync"); 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 /// The arrays a moving body's mask rebuild reads (P1-3 (c)): the
/// corrected velocities, the pressure and the previous velocities. /// corrected velocities, the pressure and the previous velocities.
pub fn download_for_rebuild(&self, field: &mut Field) { pub fn download_for_rebuild(&self, field: &mut Field) {
@@ -909,7 +909,16 @@ impl DeviceStep {
// w, p (fresh cells take their neighbours' pressure) and the // w, p (fresh cells take their neighbours' pressure) and the
// previous velocities (the imposition's source). // previous velocities (the imposition's source).
let mut field = self.host_field.take().unwrap_or_else(|| Field::new(g)); let mut field = self.host_field.take().unwrap_or_else(|| Field::new(g));
// 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); self.download_for_rebuild(&mut field);
}
let l_down = lap.elapsed(); let l_down = lap.elapsed();
// R6-1 (default ON, `RTX_E3_GEOM_DEVICE=0` off): the end-of-step // 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 // 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(); let l_geom = lap.elapsed();
fresh_cells = self.solver.rebuild_moving_mask(&mut field, dt, t_new); fresh_cells = self.solver.rebuild_moving_mask(&mut field, dt, t_new);
let l_mask = lap.elapsed(); let l_mask = lap.elapsed();
if partial {
self.upload_p(&field);
} else {
self.upload_after_rebuild(&field); self.upload_after_rebuild(&field);
}
self.host_field = Some(field); self.host_field = Some(field);
let l_up = lap.elapsed(); let l_up = lap.elapsed();
// P1-5: the persistent tables updated in place when the mask has a // P1-5: the persistent tables updated in place when the mask has a
@@ -52,3 +52,10 @@ pub(super) fn device_grid(solver: &Solver, g: Grid, dt: f64) -> Option<OperatorG
dt, dt,
}) })
} }
/// `RTX_E3_FIELD_P_ONLY=1` (default off): the rebuild's field transfer
/// limited to the pressure when the classification and the imposition ran on
/// the device.
pub(super) fn field_p_only() -> bool {
std::env::var("RTX_E3_FIELD_P_ONLY").is_ok_and(|v| v == "1")
}