SpatialMeanOp and SpatialStdDevOp compute the mean and standard deviation over active cells without area weighting: compute() divides globalMaskedSum(field, CellMask) by globalSum(CellMask), and CellMask is 0/1 (SpatialMeanOp.h, SpatialStdDevOp.h under components/omega/src/analysis/operators, at d086d49; AreaCell is never used). On a uniform mesh such as QU240 this is the global mean; on a variable-resolution mesh such as EC30to60 it is biased toward the refined regions, so every _SpatialMean and _SpatialStdDev global statistic Omega writes for such a mesh is not the quantity its name and its cell_methods = "area: mean" (#548) claim.
Expected: the mean over cells weighted by AreaCell, and for fields with a vertical dimension by cell volume (area times layer thickness, which is time-varying and comes from the state, not the mesh). Fields on edges and vertices need the corresponding edge and dual-cell areas. HorzMeanOp in #481 already implements an area-weighted per-layer mean with AreaCell as the default weight, so the fix may be to build on it rather than patch SpatialMeanOp. The standard deviation should use the same weights.
To reproduce: enable Analysis: GlobalStats with SpatialStats: [Mean] for Temperature on the EC30to60E2r2 realistic_global mesh (analysis_members_test in Polaris) and compare Temperature_SpatialMean in the global statistics file against an AreaCell-weighted mean of Temperature from the history file.
This will change every global-statistics output numerically, so it cannot be bit-for-bit with existing baselines.
Posted by Claude Code on @xylar's behalf. The testing, analysis and wording above are AI-authored; please check them accordingly.
SpatialMeanOpandSpatialStdDevOpcompute the mean and standard deviation over active cells without area weighting:compute()dividesglobalMaskedSum(field, CellMask)byglobalSum(CellMask), andCellMaskis 0/1 (SpatialMeanOp.h,SpatialStdDevOp.hundercomponents/omega/src/analysis/operators, at d086d49;AreaCellis never used). On a uniform mesh such as QU240 this is the global mean; on a variable-resolution mesh such as EC30to60 it is biased toward the refined regions, so every_SpatialMeanand_SpatialStdDevglobal statistic Omega writes for such a mesh is not the quantity its name and itscell_methods = "area: mean"(#548) claim.Expected: the mean over cells weighted by
AreaCell, and for fields with a vertical dimension by cell volume (area times layer thickness, which is time-varying and comes from the state, not the mesh). Fields on edges and vertices need the corresponding edge and dual-cell areas.HorzMeanOpin #481 already implements an area-weighted per-layer mean withAreaCellas the default weight, so the fix may be to build on it rather than patchSpatialMeanOp. The standard deviation should use the same weights.To reproduce: enable
Analysis: GlobalStatswithSpatialStats: [Mean]forTemperatureon the EC30to60E2r2realistic_globalmesh (analysis_members_testin Polaris) and compareTemperature_SpatialMeanin the global statistics file against anAreaCell-weighted mean ofTemperaturefrom the history file.This will change every global-statistics output numerically, so it cannot be bit-for-bit with existing baselines.
Posted by Claude Code on @xylar's behalf. The testing, analysis and wording above are AI-authored; please check them accordingly.