//! S2-1 diagnosis (host): DFG 3D-2Z at a coarse rung with every load //! route split into pressure and shear parts — which part of the wall //! routes departs from the box route. `RTX_E3_DFG_NY` (default 31). use rtx_cfd::solvers::incompressible::ConvectionScheme; use rtx_cfd::solvers::incompressible::embedded3::{ Body, Boundaries, Field, Fluid, Grid, Parameters, Side, Solver, WallScheme, }; const H: f64 = 0.41; const L: f64 = 2.5; const D: f64 = 0.1; const CX: f64 = 0.5; const CY: f64 = 0.2; const U_M: f64 = 0.45; const U_BAR: f64 = 4.0 / 9.0 * U_M; const RHO: f64 = 1.0; const NU: f64 = 1e-3; fn inflow(y: f64, z: f64) -> f64 { 16.0 * U_M * y * z * (H - y) * (H - z) / (H * H * H * H) } #[test] #[ignore = "host DFG at ny 31 with the routes split (about half an hour)"] fn dfg_routes_split_on_the_host() { let ny: usize = std::env::var("RTX_E3_DFG_NY") .ok() .and_then(|v| v.parse().ok()) .unwrap_or(31); let h = H / ny as f64; let nx = (L / h).round() as usize; let nz = ny; let dt = (0.3 * h / U_M).min(0.5 * h * h / (6.0 * NU)); let mut solver = Solver::new( Fluid { density: RHO, viscosity: RHO * NU, reference_velocity: U_BAR, reference_length: D, }, Parameters { corrector_steps: 2, tolerance: 1e-8, convection_scheme: ConvectionScheme::TvdVanAlbada, wall_scheme: WallScheme::CutCell, boundaries: Boundaries { x1: Side::PressureOutlet, ..Boundaries::default() }, ..Parameters::default() }, ); solver.set_boundary_velocity(|x, y, z, _t| { if x <= 0.0 { (inflow(y, z), 0.0, 0.0) } else { (0.0, 0.0, 0.0) } }); solver.set_body(Body::extruded( rtx_cfd::solvers::incompressible::EmbeddedBody::circle(CX, CY, 0.5 * D), H, )); let g = Grid::cubic(nx, ny, nz, h); let mut field = Field::new(g); for k in 0..nz { for j in 0..ny { let u0 = inflow((j as f64 + 0.5) * h, (k as f64 + 0.5) * h); for i in 0..=nx { field.u[g.uface(k, j, i)] = u0; } } } solver.initialize(&mut field); let coef = 2.0 / (RHO * U_BAR * U_BAR * D * H); let steps = (8.0 / dt).ceil() as usize; let start = std::time::Instant::now(); let mut last = (0.0, 0.0); for step in 0..steps { let r = solver.advance(&mut field, dt); if (step + 1) % (steps / 20).max(1) == 0 || step + 1 == steps { let t = solver.time(); let mask = solver.mask().unwrap(); let body = solver.body().unwrap(); let mu = RHO * NU; let (po, so) = mask.cut_wall_force_parts(body, &field, mu, t).unwrap(); let ex = mask .cut_wall_exchange_force(body, &field, mu, RHO, t, None) .unwrap(); let (pr, sr) = mask .cut_wall_force_reconstructed_parts(body, &field, mu, t, None) .unwrap(); let margin = 3.0 * D; let ci = |x: f64| ((x / h).round() as usize).clamp(2, nx - 2); let cj = |y: f64| ((y / h).round() as usize).clamp(2, ny - 2); let bx = ( ci(CX - margin), ci(CX + margin), cj(CY - 0.15), cj(CY + 0.15), 0, nz, ); let fcv = mask.control_volume_force_with_walls(&field, dt, RHO, mu, None, bx, true); let cd = |f: [f64; 3]| coef * f[0]; println!( " t {t:7.3}: c_D operator {:.4} (p {:.4} + s {:.4} + exchange {:.4}) | reconstructed {:.4} (p {:.4} + s {:.4}) | box {:.4}; residual {:.1e} [{:.0} s]", cd(po) + cd(so) + cd(ex), cd(po), cd(so), cd(ex), cd(pr) + cd(sr), cd(pr), cd(sr), cd(fcv), r.final_residual, start.elapsed().as_secs_f64() ); let now = (cd(po) + cd(so) + cd(ex), cd(fcv)); if (now.0 - last.0).abs() < 1e-4 * now.0.abs() && (now.1 - last.1).abs() < 1e-4 * now.1.abs() && t > 2.0 { println!(" settled"); break; } last = now; } } }