|
18 | 18 | !! remainder (the +alpha*d(u_star)/dx compression term m_rhs assembles from flux_src_n = u_star) is deliberately NOT captured: |
19 | 19 | !! alpha is genuinely non-conservative, so forcing flux-matching on u_star would be wrong; coarse/fine volume-fraction |
20 | 20 | !! consistency is instead maintained by mpp_lim's clamp+renormalize (required by the checker for amr with num_fluids > 1). |
| 21 | +!! |
| 22 | +!! Viscous (SP11): the viscous stress/work face fluxes travel through flux_src_n for the momentum and energy equations |
| 23 | +!! (m_rhs s_compute_additional_physics_rhs: rhs += (flux_src_n(j-1) - flux_src_n(j))/dx, identical face indexing and sign to the |
| 24 | +!! advective flux_n). They are captured into the SAME registers (added on top of the advective flux for mom..E) so the c/f reflux |
| 25 | +!! matches the TOTAL advective+viscous flux; energy conservation therefore includes the viscous work. Fine-ghost velocity gradients |
| 26 | +!! at the c/f boundary come from the conservative-linear cons prolongation (no special gradient reconstruction) - like the alpha |
| 27 | +!! K-term, that inconsistency is bounded, and conservation is enforced by the flux-register matching. |
21 | 28 | module m_amr_registers |
22 | 29 |
|
23 | 30 | use m_derived_types |
@@ -112,10 +119,11 @@ contains |
112 | 119 | !! call (amr_in_fine_advance false, coarse globals) fills creg at the patch boundary faces; fine call (flag true, globals |
113 | 120 | !! swapped to the fine patch) fills freg at fine faces -1 and m/n/p. creg uses relative 0-based transverse; freg uses 0-based |
114 | 121 | !! fine. |
115 | | - impure subroutine s_amr_capture_boundary_flux(id, flux_dir, stage) |
| 122 | + impure subroutine s_amr_capture_boundary_flux(id, flux_dir, flux_src, stage) |
116 | 123 |
|
117 | 124 | integer, intent(in) :: id |
118 | 125 | type(vector_field), intent(in) :: flux_dir |
| 126 | + type(vector_field), intent(in) :: flux_src |
119 | 127 | integer, intent(in) :: stage |
120 | 128 | integer :: eq, t1, t2, jlo, jhi, t1_hi, t2_hi, o1, o2 |
121 | 129 | integer :: sidx(3), ext(3) |
@@ -176,6 +184,30 @@ contains |
176 | 184 | end do |
177 | 185 | end do |
178 | 186 | $:END_GPU_PARALLEL_LOOP() |
| 187 | + ! total-flux matching: add the viscous momentum/energy face fluxes (flux_src) into the same fine |
| 188 | + ! registers so the c/f reflux sees advective+viscous. Base coef/accum are applied above; always |
| 189 | + ! accumulate here. Inviscid path skips this entirely (registers stay byte-identical). |
| 190 | + if (viscous) then |
| 191 | + $:GPU_PARALLEL_LOOP(collapse=3) |
| 192 | + do t2 = 0, t2_hi |
| 193 | + do t1 = 0, t1_hi |
| 194 | + do eq = eqn_idx%mom%beg, eqn_idx%E |
| 195 | + select case (id) |
| 196 | + case (1) |
| 197 | + freg(1)%lo(eq, t1, t2) = freg(1)%lo(eq, t1, t2) + coef*real(flux_src%vf(eq)%sf(jlo, t1, t2), wp) |
| 198 | + freg(1)%hi(eq, t1, t2) = freg(1)%hi(eq, t1, t2) + coef*real(flux_src%vf(eq)%sf(jhi, t1, t2), wp) |
| 199 | + case (2) |
| 200 | + freg(2)%lo(eq, t1, t2) = freg(2)%lo(eq, t1, t2) + coef*real(flux_src%vf(eq)%sf(t1, jlo, t2), wp) |
| 201 | + freg(2)%hi(eq, t1, t2) = freg(2)%hi(eq, t1, t2) + coef*real(flux_src%vf(eq)%sf(t1, jhi, t2), wp) |
| 202 | + case (3) |
| 203 | + freg(3)%lo(eq, t1, t2) = freg(3)%lo(eq, t1, t2) + coef*real(flux_src%vf(eq)%sf(t1, t2, jlo), wp) |
| 204 | + freg(3)%hi(eq, t1, t2) = freg(3)%hi(eq, t1, t2) + coef*real(flux_src%vf(eq)%sf(t1, t2, jhi), wp) |
| 205 | + end select |
| 206 | + end do |
| 207 | + end do |
| 208 | + end do |
| 209 | + $:END_GPU_PARALLEL_LOOP() |
| 210 | + end if |
179 | 211 | else |
180 | 212 | ! coarse branch: a face's capture runs on the rank owning the coarse cells just OUTSIDE it (its |
181 | 213 | ! flux_n covers that face; at a rank-interior face the same rank also holds the inside cells). |
@@ -258,6 +290,35 @@ contains |
258 | 290 | end do |
259 | 291 | end do |
260 | 292 | $:END_GPU_PARALLEL_LOOP() |
| 293 | + ! total-flux matching (coarse side): add viscous momentum/energy face fluxes into creg, same |
| 294 | + ! face gating and transverse offsets as the base capture; always accumulate. |
| 295 | + if (viscous) then |
| 296 | + $:GPU_PARALLEL_LOOP(collapse=3) |
| 297 | + do t2 = 0, t2_hi |
| 298 | + do t1 = 0, t1_hi |
| 299 | + do eq = eqn_idx%mom%beg, eqn_idx%E |
| 300 | + select case (id) |
| 301 | + case (1) |
| 302 | + if (cap_lo) creg(1)%lo(eq, t1, t2) = creg(1)%lo(eq, t1, t2) + coef*real(flux_src%vf(eq)%sf(jlo, & |
| 303 | + & o1 + t1, o2 + t2), wp) |
| 304 | + if (cap_hi) creg(1)%hi(eq, t1, t2) = creg(1)%hi(eq, t1, t2) + coef*real(flux_src%vf(eq)%sf(jhi, & |
| 305 | + & o1 + t1, o2 + t2), wp) |
| 306 | + case (2) |
| 307 | + if (cap_lo) creg(2)%lo(eq, t1, t2) = creg(2)%lo(eq, t1, & |
| 308 | + & t2) + coef*real(flux_src%vf(eq)%sf(o1 + t1, jlo, o2 + t2), wp) |
| 309 | + if (cap_hi) creg(2)%hi(eq, t1, t2) = creg(2)%hi(eq, t1, & |
| 310 | + & t2) + coef*real(flux_src%vf(eq)%sf(o1 + t1, jhi, o2 + t2), wp) |
| 311 | + case (3) |
| 312 | + if (cap_lo) creg(3)%lo(eq, t1, t2) = creg(3)%lo(eq, t1, & |
| 313 | + & t2) + coef*real(flux_src%vf(eq)%sf(o1 + t1, o2 + t2, jlo), wp) |
| 314 | + if (cap_hi) creg(3)%hi(eq, t1, t2) = creg(3)%hi(eq, t1, & |
| 315 | + & t2) + coef*real(flux_src%vf(eq)%sf(o1 + t1, o2 + t2, jhi), wp) |
| 316 | + end select |
| 317 | + end do |
| 318 | + end do |
| 319 | + end do |
| 320 | + $:END_GPU_PARALLEL_LOOP() |
| 321 | + end if |
261 | 322 | end if |
262 | 323 |
|
263 | 324 | end subroutine s_amr_capture_boundary_flux |
|
0 commit comments