Piecewise-constant (donor cell) remap. Diffusive, guaranteed monotone.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in) | :: | nz | |||
| real(kind=wp), | intent(in) | :: | dz_old(nz) |
Old layer thicknesses (must sum to same total as dz_new) |
||
| real(kind=wp), | intent(in) | :: | dz_new(nz) |
New layer thicknesses |
||
| real(kind=wp), | intent(in) | :: | q_old(nz) |
Old cell-average scalar values |
||
| real(kind=wp), | intent(out) | :: | q_new(nz) |
New cell-average scalar values (conservative) |
| Type | Visibility | Attributes | Name | Initial | |||
|---|---|---|---|---|---|---|---|
| real(kind=wp), | private | :: | integral | ||||
| integer, | private | :: | k | ||||
| integer, | private | :: | ko | ||||
| integer, | private | :: | ko_start | ||||
| real(kind=wp), | private | :: | overlap | ||||
| real(kind=wp), | private | :: | z_hi | ||||
| real(kind=wp), | private | :: | z_lo | ||||
| real(kind=wp), | private | :: | z_new(0:NZ_STACK_MAX) | ||||
| real(kind=wp), | private | :: | z_old(0:NZ_STACK_MAX) |
pure subroutine remap_column_pcm(nz, dz_old, dz_new, q_old, q_new) !$acc routine seq !! Piecewise-constant (donor cell) remap. Diffusive, guaranteed monotone. integer, intent(in) :: nz real(wp), intent(in) :: dz_old(nz) !! Old layer thicknesses (must sum to same total as dz_new) real(wp), intent(in) :: dz_new(nz) !! New layer thicknesses real(wp), intent(in) :: q_old(nz) !! Old cell-average scalar values real(wp), intent(out) :: q_new(nz) !! New cell-average scalar values (conservative) real(wp) :: z_old(0:NZ_STACK_MAX), z_new(0:NZ_STACK_MAX) real(wp) :: z_lo, z_hi, overlap, integral integer :: k, ko, ko_start ! Build interface positions (cumulative sum from bottom) z_old(0) = 0.0_wp z_new(0) = 0.0_wp do k = 1, nz z_old(k) = z_old(k - 1) + dz_old(k) z_new(k) = z_new(k - 1) + dz_new(k) end do ! Sweep: for each new layer, integrate PCM from old layers ko_start = 1 do k = 1, nz if (dz_new(k) <= 0.0_wp) then q_new(k) = 0.0_wp cycle end if integral = 0.0_wp do ko = ko_start, nz z_lo = max(z_new(k - 1), z_old(ko - 1)) z_hi = min(z_new(k), z_old(ko)) overlap = z_hi - z_lo if (overlap <= 0.0_wp) then if (z_old(ko) > z_new(k)) exit cycle end if integral = integral + q_old(ko)*overlap ! Advance scan: if old layer fully consumed, next new layer ! can start from the next old layer if (z_old(ko) <= z_new(k)) ko_start = ko end do q_new(k) = integral/dz_new(k) end do end subroutine remap_column_pcm