Skip to content

Make obs perturbation grid-cell lookup in get_obs_pert() layout independent - #210

Draft
amfox37 wants to merge 1 commit into
developfrom
bugfix/amfox/obs-pert-layout-independent
Draft

amfox37 wants to merge 1 commit into
developfrom
bugfix/amfox/obs-pert-layout-independent

Conversation

@amfox37

@amfox37 amfox37 commented Sep 24, 2026

Copy link
Copy Markdown
Contributor

Summary

In get_obs_pert(), each obs was mapped to a perturbation grid cell with get_ij_ind_from_latlon(pert_grid_lH, ...). The local grid pert_grid_lH is built per processor from the local obs extent, and its ll_lon/ll_lat are computed in single precision (e.g. ll_lat = pert_grid_f%ll_lat + real(ind_min-1)*dlat) and are subject to roundoff. An obs lying very close to a pert grid cell edge could therefore be mapped to different cells, and so receive different perturbations, depending on which processor handles it. As a result, the analysis depended on the EnKF layout (number of processors and AnaLoadBal partition). Within a single run, the same obs could also get different perturbations for tiles analyzed on different processors.

This PR finds the cell on the global pert_grid_f, which is identical on all processors, and converts it to the pert_grid_lH index with the same integer offsets (i_offg/j_offg) that propagate_pert() uses to extract the local perturbation window. The perturbation fields themselves were already layout independent; only the lookup was affected.

Evidence

CF0360, 24 members, H SAF ASCAT, 240 ranks, comparing the default count-based AnaLoadBal partition against an experimental cost-weighted partition, with the same executable otherwise:

  • Before: obs and forecasts were identical between the two partitions, but the analysis differed at 45 obs / 368 tiles in one cluster (Venezuela). A diagnostic print traced this to a single METB obs at lat 5.1666660, which is 3.8e-6 cells from a 1/6-degree pert grid edge. It mapped to pert-grid row 571 on some processors and row 572 on others, where the local ll_lat rounded differently, so it got different perturbations.
  • After: the two partitions are bit-for-bit identical: ObsFcstAna, catch_progn_incr and all restarts at 03z and 06z.

Impact

  • Not zero-diff: results change slightly wherever an obs lies within roundoff of a pert grid cell edge.
  • This removes the obs-perturbation source of layout dependence in the analysis. It does not make the whole model layout-independent: with an Aggressive build, runs on different processor counts still differ slightly for other reasons.

In get_obs_pert(), the grid cell of each obs was found w.r.t. pert_grid_lH,
whose ll_lon/ll_lat are computed from the local obs extent and are subject
to roundoff. An obs close to a pert grid cell edge could therefore be mapped
to different cells (and receive different perturbations) on different
processors, making results depend on the EnKF analysis layout (e.g., the
number of processors or the AnaLoadBal partition) and giving the same obs
different perturbations for tiles analyzed on different processors.

Find the cell w.r.t. pert_grid_f (identical on all processors) and convert
to the pert_grid_lH index with the same integer offsets that are used to
extract the local perturbation window in propagate_pert().

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@amfox37
amfox37 force-pushed the bugfix/amfox/obs-pert-layout-independent branch from de67df7 to a04a9b5 Compare September 24, 2026 16:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant