@@ -371,6 +371,137 @@ function overwrite_initial_conditions!(
371371 )
372372end
373373
374+ """
375+ correct_surface_pressure_for_topography!(
376+ p_sfc,
377+ file_path,
378+ face_space,
379+ Y,
380+ ᶜT,
381+ ᶜq_tot,
382+ thermo_params,
383+ regridder_kwargs,
384+ )
385+
386+ Adjusts the surface pressure field `p_sfc` to account for mismatches between
387+ ERA5 (file) surface altitude and the model orography when specifying pressure.
388+
389+ Δz = z_model_surface - z_sfc
390+
391+ and applies a hydrostatic correction at the surface using the local moist gas
392+ constant and temperature at the surface:
393+
394+ p_sfc .= p_sfc .* exp.(-Δz * g ./ (R_m_sfc .* T_sfc))
395+
396+ where:
397+ - `g` is gravitational acceleration from `thermo_params`
398+ - `R_m_sfc` is the moist-air gas constant evaluated from `ᶜq_tot` at the surface
399+ - `T_sfc` is the air temperature from `ᶜT` at the surface
400+
401+ A small floor is applied to the denominator `R_m_sfc .* T_sfc` to avoid
402+ numerical blow-ups, and non-finite `Δz` entries leave `p_sfc` unchanged.
403+
404+ Returns `true` if the correction is applied. If `z_sfc` is missing in the
405+ provided file, the function logs a warning and returns `false` without
406+ modifying `p_sfc`.
407+
408+ Arguments
409+ - `p_sfc`: face field of surface pressure to be corrected (modified in-place)
410+ - `file_path`: path to the ERA5-derived initialization NetCDF file
411+ - `face_space`: face space of the model grid (for reading/regridding)
412+ - `Y`: prognostic state, used to obtain model surface height
413+ - `ᶜT`: center field of temperature
414+ - `ᶜq_tot`: center field of total specific humidity
415+ - `thermo_params`: thermodynamics parameter set
416+ - `regridder_kwargs`: keyword arguments forwarded to the regridder
417+
418+ Notes
419+ - Expects `z_sfc` units in meters; if the variable is not present, the
420+ correction is skipped.
421+ """
422+ function correct_surface_pressure_for_topography! (
423+ p_sfc,
424+ file_path,
425+ face_space,
426+ Y,
427+ ᶜT,
428+ ᶜq_tot,
429+ thermo_params,
430+ regridder_kwargs,
431+ )
432+ var_name = " z_sfc"
433+ ᶠz_surface = nothing
434+ try
435+ ᶠz_surface = Fields. level (
436+ SpaceVaryingInputs. SpaceVaryingInput (
437+ file_path,
438+ var_name,
439+ face_space,
440+ regridder_kwargs = regridder_kwargs,
441+ ),
442+ Fields. half,
443+ )
444+ catch err
445+ if err isa ArgumentError || err isa KeyError
446+ @warn " Skipping topographic correction because variable `$var_name ` is missing from $(file_path) ."
447+ return false
448+ else
449+ rethrow (err)
450+ end
451+ end
452+
453+ if ᶠz_surface === nothing
454+ return false
455+ end
456+
457+ FT = eltype (thermo_params)
458+ grav = thermo_params. grav
459+
460+ # Log initial surface pressure statistics
461+ p_sfc_arr = Array (Fields. field2array (p_sfc))
462+ p_sfc_finite = filter (isfinite, p_sfc_arr)
463+
464+ ᶠz_model_surface = Fields. level (Fields. coordinate_field (Y. f). z, Fields. half)
465+ ᶠΔz = zeros (face_space)
466+ @. ᶠΔz = ᶠz_model_surface - ᶠz_surface
467+
468+ # Log surface height statistics
469+ z_surface_arr = Array (Fields. field2array (ᶠz_surface))
470+ z_model_arr = Array (Fields. field2array (ᶠz_model_surface))
471+ Δz_arr = Array (Fields. field2array (ᶠΔz))
472+
473+ ᶜphase_partition = TD. PhasePartition .(ᶜq_tot)
474+ ᶜR_m = TD. gas_constant_air .(thermo_params, ᶜphase_partition)
475+ ᶠR_m = ᶠinterp .(ᶜR_m)
476+ ᶠR_m_sfc = Fields. level (ᶠR_m, Fields. half)
477+
478+ ᶠT = ᶠinterp .(ᶜT)
479+ ᶠT_sfc = Fields. level (ᶠT, Fields. half)
480+
481+ denom = copy (ᶠR_m_sfc)
482+ @. denom = ᶠR_m_sfc * ᶠT_sfc
483+ denom_floor = FT (10 )
484+ @. denom = ifelse (isfinite (denom) && denom > denom_floor, denom, denom_floor)
485+
486+ correction_factor = similar (ᶠΔz)
487+ @. correction_factor = ifelse (
488+ isfinite (ᶠΔz),
489+ exp (FT (- 1 ) * ᶠΔz * grav / denom),
490+ one (FT),
491+ )
492+
493+ @. p_sfc =
494+ p_sfc *
495+ ifelse (
496+ isfinite (ᶠΔz),
497+ exp (FT (- 1 ) * ᶠΔz * grav / denom),
498+ one (FT),
499+ )
500+
501+ @info " Adjusted surface pressure to account for ERA5/model surface-height differences."
502+ return true
503+ end
504+
374505# WeatherModel function using the shared implementation
375506function overwrite_initial_conditions! (
376507 initial_condition:: WeatherModel ,
@@ -421,6 +552,16 @@ function overwrite_initial_conditions!(
421552 center_space,
422553 regridder_kwargs = regridder_kwargs,
423554 )
555+ correct_surface_pressure_for_topography! (
556+ p_sfc,
557+ file_path,
558+ face_space,
559+ Y,
560+ ᶜT,
561+ ᶜq_tot,
562+ thermo_params,
563+ regridder_kwargs,
564+ )
424565
425566 # With the known temperature (ᶜT) and moisture (ᶜq_tot) profile,
426567 # recompute the pressure levels assuming hydrostatic balance is maintained.
0 commit comments