Revisit bottom roughness generation#105
Conversation
Overall the new \sqrt(h^2) (bottom left) show strong qualitative agreement in the large-scale features seen in both @CallumJShakespeare’s 100 km config (top left) and the OM2 configuration (top right). The peak magnitudes in the new field (bottom-left 25km config) are comparable to those in Callum’s matlab result, but are roughly twice those in OM2, which is capped at 1000m . The bottom-right figure (25km config) shows the roughness field currently used in OM3. @aekiss @CallumJShakespeare would you mind taking a look and letting me know if you have any suggestions? |
external_tidal_generation/generate_bottom_roughness_intermediate_woa.py
Outdated
Show resolved
Hide resolved
74382cb to
9e69b44
Compare
external_tidal_generation/generate_bottom_roughness_intermediate_woa.py
Outdated
Show resolved
Hide resolved
external_tidal_generation/generate_bottom_roughness_intermediate_woa.py
Outdated
Show resolved
Hide resolved
external_tidal_generation/generate_bottom_roughness_intermediate_woa.py
Outdated
Show resolved
Hide resolved
external_tidal_generation/generate_bottom_roughness_intermediate_woa.py
Outdated
Show resolved
Hide resolved
external_tidal_generation/generate_bottom_roughness_intermediate_woa.py
Outdated
Show resolved
Hide resolved
external_tidal_generation/generate_bottom_roughness_intermediate_woa.py
Outdated
Show resolved
Hide resolved
external_tidal_generation/generate_bottom_roughness_intermediate_woa.py
Outdated
Show resolved
Hide resolved
external_tidal_generation/generate_bottom_roughness_intermediate_woa.py
Outdated
Show resolved
Hide resolved
e937d29 to
554f939
Compare
external_tidal_generation/generate_bottom_roughness_intermediate_woa.py
Outdated
Show resolved
Hide resolved
…te_woa.py Co-authored-by: Andrew Kiss <31054815+aekiss@users.noreply.github.com>
…te_woa.py Co-authored-by: Andrew Kiss <31054815+aekiss@users.noreply.github.com>
…te_woa.py Co-authored-by: Andrew Kiss <31054815+aekiss@users.noreply.github.com>
…te_woa.py Co-authored-by: Andrew Kiss <31054815+aekiss@users.noreply.github.com>
The 2nd stage was unnecesary, since stage1 has filled all wet nans and stage2 produced identical output. Hence simplify the workflow by droppiing stage2 and keeping a single laplace fill over the wet domain only.
- Compute which woa source cells are required by the regridding weights for mom6 wet cells So now every mom6 wet cells receives valid input data filling is driven by the actual regridding stencil no unnecessary exptrapolation is performed beyond what is required by the weights
|
@aekiss thanks for raising this #105 (comment). I've changed the workflow so that filling is no longer done purely on the woa ocean mask. Instead now the fill mask is obtained from the actual esmf regridding weights. After building the regridder, I've extracted which woa source cells contribute to at least one MOM6 wet target cell and then expand the fill mask to include both the original woa wet cells and these "needed" source cells. Then apply the laplacian fill over this combined mask before regridding. In this case any mom6 wet cells that draw from woa cells outside the original woa wet mask still receive valid values. So there''' be no nans caused by the mask mismatch and only extrapolating where the weights prove it is required. Here's a notebook https://github.com/minghangli-uni/sandbox/blob/master/external_tidal/Update_bottom_roughness.ipynb showing the key steps and diagnostics. It also includes a comparison across different mapping methods - for the 25 km config, the resulting fields look qualitatively very similar though. |
|
OK thanks. That seems a very complicated way to go about it compared to the IC approach #105 (comment), but if it works I'm happy. |
Correct. Here is what I see from the mask check. # da1: conservative_normed regridding method (initial try)
# da2: conservative_normed regridding method (revised)
# da3: bilinear regridding method (revised)
# da4: patch regridding method (revised)
for i, da in enumerate([da1, da2, da3, da4], start=1):
same_mask = np.array_equal(np.isfinite(da.values), mask.values)
print(f"da{i} uses same mask:", same_mask)
da1 uses same mask: False
da2 uses same mask: True
da3 uses same mask: True
da4 uses same mask: FalseSo for lower resolution configs e.g. 100km configs, we will use the If you're happy with these results, would you be able to have a final look and approve this @aekiss ? |
|
There are 2 unresolved comments - let me know when they're done or rejected |
aekiss
left a comment
There was a problem hiding this comment.
Great work, thanks @minghangli-uni !
|
Really appreciate the careful review @aekiss Thanks! |



The existing bottom roughness calculation follows Jayne & St Laurent 2001,
but applying this approach directly on high-res ocean models is problematic. When roughness is computed at the model grid scale, the resulting h^2 becomes explicitly dependent on model resolution, which is unphysical. In the absence of explicit tidal forcing, resolved scale topography will not contribute to internal tide generation, so generation by resolved scales also needs to be parameterised. A clear summary of this issue is given by @aekiss in ACCESS-NRI/access-om3-configs#457
Below is the key part of that summary.
The key physical insight is that bottom roughness should instead be defined relative to the internal tide length scale, not the model grid spacing,
@CallumJShakespeare has provided a matlba implementation of this approach https://github.com/CallumJShakespeare/global_tide_inputs, that workflow computes roughness using:
interp2).To integrate this method into the ACCESS-OM3 workflow and update the stratification input to WOA23, this PR re-implements the method in Python with MPI parallelism.
Hence this script does following things,
Notes:
interp2for bathymetric sampling. But in this implementation bilinear interpolation is performed manually:EDIT: 15 Jan 2026
generate_bottom_roughness_regrid.py. This is intentionally split out due to a knownxesmf + mpi4pyissue in the analysis environment: Hanging with xesmf regridding in mpi on xp65 ACCESS-Analysis-Conda#207