GRIB files are the file format used at ECMWF. GRIB is a WMO standard and consists of GRIB Edition 1 and Edition 2
The ERA5 dataset, produced by the European Centre for Medium-Range Weather Forecasts (ECMWF), provides a wealth of climate and weather data. However, the data is often distributed in the GRIB format, which can be less user-friendly than the NetCDF format, commonly used in scientific computing. This blog post will walk you through the process of converting ERA5 GRIB files to NetCDF.
Climate change is one of the most pressing issues of our time, and understanding its impacts requires access to high-quality climate data. The ERA5 dataset provides crucial information on past and present climate conditions, helping researchers analyze trends and signals related to climate change. However, the ERA5 data is often stored in GRIB format, which can be challenging to work with. By converting ERA5 GRIB files to NetCDF format, we can more easily integrate climate change signals into ERA5.
By applying the Pseudo-Global-Warming (PGW) approach, you can use the CMIP6 climate change signals to generate a difference and then add this to the initial conditions, such as those provided by ERA5.
Main Script
▶
loop.sh
1 2 3 4 5 6 7 8 9 10 11
#!/bin/bash
ym="20220630"
for iday in {0..360..3}; do # Next_day=$(date +%Y-%m-%d_%H:%M:%S -d "$YYYYMMDD + 1 hour") export ERA5_datetime=$(date +%Y%m%d%H -d "$ym + $iday hour") echo${ERA5_datetime}
#------------------------------------------------# #Author: wpsze #Email: wpsze #date: 2025-02-10 09:45:06 #Version: 0.0 #Description: The purpose of the script #Copyright (C): 2025 All rights reserved #------------------------------------------------#
export ERA5_datetime=${ERA5_datetime:-"2022063000"} export ERA5_path=${ERA5_path:-"/home/wpsze/ERA5/"} export PGW_ERA5_path=${PGW_ERA5_path:-"/home/wpsze/PGW/ERA5/"}# save future projection of ERA5 IC export PGW_script_path=${PGW_script_path:-"/home/wpsze/PGW/"}
# Convert ERA5.grib to .nc if [[ ! -f "ERA5-0p25-SL-${yyyymmddhh}.nc" ]]; then echo"ERA5-0p25-SL/PL-${yyyymmddhh}.nc doesn't exist, generating them ... " time python3 ${PGW_script_path}/grib2netcdf.py else echo"ERA5-0p25-SL/PL-${yyyymmddhh}.nc exist." fi
# rename/rebuild singal.nc if [[ ! -f "signal.nc" ]]; then echo"singal.nc doesn't exits, soft-link and rebuild ..." ln -sf ${cmip6_signal_file} original-signal.nc time python3 ${PGW_script_path}/rename_signal.py else echo"signal.nc exists." fi
# regrid signal.nc (1.25deg) to 0.25deg if [[ ! -f "signal_0p25.nc" ]]; then cdo remapbil,r1440x721 signal.nc signal_0p25.nc else echo"signal_0p25.nc exists." fi
# Add singal.nc into ERA5.nc time python3 ${PGW_script_path}/2d_interp.py time python3 ${PGW_script_path}/3d_interp.py # time python3 ${PGW_script_path}/3d_interp_with_uv.py
# Convert nc file to grib file cp ERA5-0p25-SL-${yyyymmddhh}.grib original-SL.grib cp ERA5-0p25-PL-${yyyymmddhh}.grib original-PL.grib time sh ${PGW_script_path}/netcdf2grib.sh # time sh ${PGW_script_path}/netcdf2grib_with_uv.sh
#------------------------------------------------# #Author: wpsze #Email: wpsze #date: 2025-02-03 17:26:38 #Version: 0.0 #Description: The purpose of the script #Copyright (C): 2025 All rights reserved #------------------------------------------------# import os import xarray as xr
Interpolating 2D SST/SKT from Signal NetCDF to ERA5 NetCDF
Here’s a Python script for interpolating Sea Surface Temperature (SST) and Surface Skin Temperature (SKT) from a signal NetCDF file to match the ERA5 grid. This process involves horizontal interpolation to ensure that the temperatures align accurately with the finer resolution of the ERA5 dataset. Accurate temperature data is crucial for climate modeling and analysis. By interpolating these temperatures, we can effectively integrate them into broader climate studies.
Manipulate signal.nc
Modify signal.nc because the original signal.nc is not properly defined in a format recognized by CDO, making it impossible to apply CDO command tools.
#------------------------------------------------# #Author: wpsze #Email: wpsze #date: 2025-02-07 17:37:01 #Version: 0.0 #Description: The purpose of the script #Copyright (C): 2025 All rights reserved #------------------------------------------------#
import numpy as np import xarray as xr
# Load the signal and ERA5 NetCDF files signal_nc = xr.open_dataset('signal.nc') # Replace with actual signal file path
#================== Save ================================================= # Save the result to a new NetCDF file test.to_netcdf('signal.nc', format='NETCDF4')
#------------------------------------------------# #Author: wpsze #Email: wpsze #date: 2025-02-04 16:34:39 #Version: 0.0 #Description: The purpose of the script #Copyright (C): 2025 All rights reserved #------------------------------------------------# import os import numpy as np import xarray as xr # from scipy.interpolate import interp1d
# Load the signal and ERA5 NetCDF files signal_nc = xr.open_dataset('signal_0p25.nc') # Replace with actual signal file path era5_nc = xr.open_dataset('ERA5-SL.nc') # Replace with actual ERA5 file path
# Extract 2D SST variables sst_signal = signal_nc['diff_ts'] # SST from signal file (2D array) skt_signal = signal_nc['diff_ts'] # Skin temperature from signal file (2D array) lat_signal = signal_nc['lat'] lon_signal = signal_nc['lon']
sst_era5 = era5_nc['sst'] # SST from ERA5 file (2D array) skt_era5 = era5_nc['skt'] # Skin temperature from ERA5 file (2D array)
# # Reverse the SST data along the latitude dimension #reversed_sst_signal = sst_signal[::-1, :] # Assuming latitude is the first dimension
# # Update the coordinates to reflect the new latitude order #reversed_latitude = lat_signal[::-1] # Reverse latitude coordinates, from [-90,90] to [90,-90]
# # Update the SST variable to use the reversed latitude #reversed_sst_signal = reversed_sst_signal.assign_coords(latitude=reversed_latitude.values, longitude=lon_signal.values)
# Define new latitude and longitude arrays for 0.25-degree grid # Perform horizontal interpolation to 0.25-degree grid # method ({"linear", "nearest", "zero", "slinear", "quadratic", # "cubic", "quintic", "polynomial", "pchip", "barycentric", "krogh", # "akima", "makima"}) – Interpolation method to use (see descriptions above). fill_value='extrapolate' # reversed_sst_signal = reversed_sst_signal.interp(latitude=sst_era5.coords['latitude'].values, # longitude=sst_era5.coords['longitude'].values)
# Add signal to ERA5 era5_nc['sst'] = sst_era5 + sst_signal.values[::-1,:] # Reverse latitude coordinates, from [-90,90] to [90,-90]
# # Reverse the SST data along the latitude dimension #reversed_skt_signal = skt_signal[::-1, :] # Assuming latitude is the first dimension
# # Update the coordinates to reflect the new latitude order # # reversed_latitude = lat_signal[::-1] # Reverse latitude coordinates (Done before!!)
# # Update the SST variable to use the reversed latitude #reversed_skt_signal = reversed_skt_signal.assign_coords(latitude=reversed_latitude.values, longitude=lon_signal.values)
# # Define new latitude and longitude arrays for 0.25-degree grid # # Perform horizontal interpolation to 0.25-degree grid # reversed_skt_signal = reversed_skt_signal.interp(latitude=sst_era5.coords['latitude'].values, # longitude=sst_era5.coords['longitude'].values)
# # Add signal to ERA5 era5_nc['skt'] = skt_era5 + skt_signal.values[::-1,:] # Reverse latitude coordinates, from [-90,90] to [90,-90]
#================== Save ================================================= # Save the result to a new NetCDF file era5_nc.to_netcdf(f'new_ERA5-0p25-SL-{yyyymmddhh}.nc')
print(f"Horizontal interpolation completed and save
Interpolating 3D Temperature from Signal NetCDF to ERA5 NetCDF
Here's a Python script for interpolating a 3D temperature field from a signal NetCDF file to match the grid of an ERA5 NetCDF file.
In this part, we will demonstrate how to interpolate a 3D temperature field (ta) from a signal NetCDF file to match the grid of an ERA5 NetCDF file containing its own 3D temperature field (TT). This process is essential for applying climate change signals to ERA5 data effectively.
Introduction
In this blog, we'll discuss how to interpolate a 3D temperature field (ta) from a signal NetCDF file to match the grid of an ERA5 NetCDF file, which contains a different temperature variable (TT). This procedure involves two main steps: vertical interpolation to align the vertical levels and horizontal interpolation to match the latitude and longitude coordinates.
Motivation
By applying the Pseudo-Global-Warming (PGW) approach using CMIP6 climate change signals, we can generate a difference that can be added to the initial conditions like ERA5. Accurate interpolation is crucial for effective climate modeling and analysis.
Steps for Interpolation
Vertical Interpolation: Adjust the temperature data from the signal file to the vertical levels of the ERA5 file.
#------------------------------------------------# #Author: wpsze #Email: wpsze #date: 2025-02-04 16:31:50 #Version: 0.0 #Description: The purpose of the script #Copyright (C): 2025 All rights reserved #------------------------------------------------# import os import numpy as np import xarray as xr from scipy.interpolate import interp1d
# Load the signal and ERA5 NetCDF files signal_nc = xr.open_dataset('signal_0p25.nc') # Replace with actual signal file path era5_nc = xr.open_dataset('ERA5-PL.nc') # Replace with actual ERA5 file path
#================ Vertical levels ======================================= # Vertical levels signal_levels = signal_nc['level'].values/100# Vertical levels from signal file, lev(ncl14), convert to hPa unit lat_signal = signal_nc['lat'] lon_signal = signal_nc['lon']
# Update the coordinates to reflect the new latitude order reversed_latitude = lat_signal[::-1] # Reverse latitude coordinates, from [-90,90] to [90,-90]
era5_levels = era5_nc['isobaricInhPa'] # Vertical levels from ERA5 file, 'level' if grib_to_netcdf, 'isobaricInhPa' if xarray/cfgrib
#================ T air_temperature in K ================================ print("=== processing: T air_temperature in K ")
# Extract variables ta_signal = signal_nc['diff_ta'] # 3D temperature from signal file, diff_ta(ncl0, ncl1, ncl2) TT_era5 = era5_nc['t'] # 3D temperature from ERA5 file, t(isobaricInhPa, latitude, longitude)
# Reverse the TT data along the latitude dimension reversed_ta_signal = ta_signal[:, ::-1, :] # latitude is the second dimension
# Update the TT variable to use the reversed latitude reversed_ta_signal = reversed_ta_signal.assign_coords(latitude=reversed_latitude.values, longitude=lon_signal.values)
# Define new latitude and longitude arrays for 0.25-degree grid # Perform horizontal interpolation to 0.25-degree grid ## interpolated_ta = interpolated_ta.interp(latitude=TT_era5.coords['latitude'].values, longitude=TT_era5.coords['longitude'].values)
# Add signal to ERA5 era5_nc['t'][1:29,:,:] = TT_era5[1:29,:,:] + interpolated_ta[1:29,:,:]
#================ Relative Humidity (RH) in % ================================ print("=== processing: Relative Humidity (RH) in % ")
# Extract variables rh_signal = signal_nc['diff_rh'] # 3D RH from signal file, diff_ta(ncl5, ncl6, ncl7) RH_era5 = era5_nc['r'] # 3D RH from ERA5 file, t(isobaricInhPa, latitude, longitude)
# Reverse the RH data along the latitude dimension reversed_rh_signal = rh_signal[:, ::-1, :] # latitude is the second dimension
# Update the RH variable to use the reversed latitude reversed_rh_signal = reversed_rh_signal.assign_coords(latitude=reversed_latitude.values, longitude=lon_signal.values)
# Define new latitude and longitude arrays for 0.25-degree grid # Perform horizontal interpolation to 0.25-degree grid ##interpolated_rh = interpolated_rh.interp(latitude=RH_era5.coords['latitude'].values, longitude=RH_era5.coords['longitude'].values)
# Add signal to ERA5 era5_nc['r'][1:29,:,:] = RH_era5[1:29,:,:] + interpolated_rh[1:29,:,:]
#------------------------------------------------# #Author: wpsze #Email: wpsze #date: 2025-02-04 16:31:50 #Version: 0.0 #Description: The purpose of the script #Copyright (C): 2025 All rights reserved #------------------------------------------------# import os import numpy as np import xarray as xr from scipy.interpolate import interp1d
# Load the signal and ERA5 NetCDF files signal_nc = xr.open_dataset('signal_0p25.nc') # Replace with actual signal file path era5_nc = xr.open_dataset(f'ERA5-0p25-PL-{yyyymmddhh}.nc') # Replace with actual ERA5 file path
#================ Vertical levels ======================================= # Vertical levels signal_levels = signal_nc['level'].values/100# Vertical levels from signal file, lev(ncl14), convert to hPa unit lat_signal = signal_nc['lat'] lon_signal = signal_nc['lon']
# Update the coordinates to reflect the new latitude order reversed_latitude = lat_signal[::-1] # Reverse latitude coordinates, from [-90,90] to [90,-90]
era5_levels = era5_nc['isobaricInhPa'] # Vertical levels from ERA5 file, 'level' if grib_to_netcdf, 'isobaricInhPa' if xarray/cfgrib
#================ T air_temperature in K ================================ print("=== processing: T air_temperature in K ")
# Extract variables ta_signal = signal_nc['diff_ta'] # 3D temperature from signal file, diff_ta(ncl0, ncl1, ncl2) TT_era5 = era5_nc['t'] # 3D temperature from ERA5 file, t(isobaricInhPa, latitude, longitude)
# Reverse the TT data along the latitude dimension reversed_ta_signal = ta_signal[:, ::-1, :] # latitude is the second dimension, # Reverse latitude coordinates, from [-90,90] to [90,-90]
# Update the TT variable to use the reversed latitude reversed_ta_signal = reversed_ta_signal.assign_coords(latitude=reversed_latitude.values, longitude=lon_signal.values)
# Define new latitude and longitude arrays for 0.25-degree grid # Perform horizontal interpolation to 0.25-degree grid ## interpolated_ta = interpolated_ta.interp(latitude=TT_era5.coords['latitude'].values, longitude=TT_era5.coords['longitude'].values)
# Add signal to ERA5 era5_nc['t'][1:29,:,:] = TT_era5[1:29,:,:] + interpolated_ta[1:29,:,:]
#================ Relative Humidity (RH) in % ================================ print("=== processing: Relative Humidity (RH) in % ")
# Extract variables rh_signal = signal_nc['diff_rh'] # 3D RH from signal file, diff_ta(ncl5, ncl6, ncl7) RH_era5 = era5_nc['r'] # 3D RH from ERA5 file, t(isobaricInhPa, latitude, longitude)
# Reverse the RH data along the latitude dimension reversed_rh_signal = rh_signal[:, ::-1, :] # latitude is the second dimension, # Reverse latitude coordinates, from [-90,90] to [90,-90]
# Update the RH variable to use the reversed latitude reversed_rh_signal = reversed_rh_signal.assign_coords(latitude=reversed_latitude.values, longitude=lon_signal.values)
# Define new latitude and longitude arrays for 0.25-degree grid # Perform horizontal interpolation to 0.25-degree grid ##interpolated_rh = interpolated_rh.interp(latitude=RH_era5.coords['latitude'].values, longitude=RH_era5.coords['longitude'].values)
# Add signal to ERA5 era5_nc['r'][1:29,:,:] = RH_era5[1:29,:,:] + interpolated_rh[1:29,:,:]
#================ u eastward_wind ================================ print("=== processing: u eastward_wind (m s**-1) ")
# Extract variables ua_signal = signal_nc['diff_ua'] # 3D diff_ua from signal file, diff_ua(level, latitude, longitude) u_era5 = era5_nc['u'] # 3D u from ERA5 file, u(isobaricInhPa, latitude, longitude)
# Reverse the RH data along the latitude dimension reversed_ua_signal = ua_signal[:, ::-1, :] # latitude is the second dimension, # Reverse latitude coordinates, from [-90,90] to [90,-90]
# Update the RH variable to use the reversed latitude reversed_ua_signal = reversed_ua_signal.assign_coords(latitude=reversed_latitude.values, longitude=lon_signal.values)
# Define new latitude and longitude arrays for 0.25-degree grid # Perform horizontal interpolation to 0.25-degree grid ##interpolated_rh = interpolated_rh.interp(latitude=RH_era5.coords['latitude'].values, longitude=RH_era5.coords['longitude'].values)
# Add signal to ERA5 era5_nc['u'][1:29,:,:] = u_era5[1:29,:,:] + interpolated_ua[1:29,:,:]
#================ v northward_wind ================================ print("=== processing: v northward_wind (m s**-1) ")
# Extract variables va_signal = signal_nc['diff_va'] # 3D diff_va from signal file, diff_va(level, latitude, longitude) v_era5 = era5_nc['v'] # 3D v from ERA5 file, u(isobaricInhPa, latitude, longitude)
# Reverse the RH data along the latitude dimension reversed_va_signal = va_signal[:, ::-1, :] # latitude is the second dimension, # Reverse latitude coordinates, from [-90,90] to [90,-90]
# Update the RH variable to use the reversed latitude reversed_va_signal = reversed_va_signal.assign_coords(latitude=reversed_latitude.values, longitude=lon_signal.values)
# Define new latitude and longitude arrays for 0.25-degree grid # Perform horizontal interpolation to 0.25-degree grid ##interpolated_rh = interpolated_rh.interp(latitude=RH_era5.coords['latitude'].values, longitude=RH_era5.coords['longitude'].values)
# Add signal to ERA5 era5_nc['v'][1:29,:,:] = v_era5[1:29,:,:] + interpolated_va[1:29,:,:]
# Save the result to a new NetCDF file era5_nc.to_netcdf(f'new_ERA5-0p25-PL-{yyyymmddhh}.nc')
print(f"Interpolation completed and saved to 'interpolated_ERA5-0p25-PL-{yyyymmddhh}.nc.")
Explanation of the Code
Loading Data: The script uses xarray to load the signal and ERA5 NetCDF files.
Vertical Interpolation: A function (vertical_interpolate) is defined to perform linear interpolation on the vertical levels of the temperature data.
Saving the Result: The interpolated temperature data is saved to a new NetCDF file.
Conclusion
This interpolation approach allows for aligning temperature data from different datasets, which is essential for climate modeling. By accurately matching the grids of the signal and ERA5 data, we can effectively analyze and apply climate change signals in our research.
Converting NetCDF Files back to GRIB Format: A Step-by-Step Guide
Introduction
In the realm of climate data analysis, the ability to convert between different file formats is essential. While NetCDF is widely used for storing multidimensional scientific data, GRIB (Generalized Regularly-distributed Information in Binary form) is prevalent in meteorological applications. This blog will guide you through the process of converting NetCDF files back to GRIB format, ensuring you're equipped to handle various data formats in your climate studies.
Motivation
The motivation behind converting NetCDF files to GRIB format can stem from several factors:
Compatibility: Many meteorological models and tools predominantly use GRIB format. Converting your NetCDF data ensures compatibility with these systems.
Efficiency: GRIB files are often more compact than their NetCDF counterparts, making them easier to store and share, especially when dealing with large datasets.
Standardization: For specific applications, adhering to a standard format like GRIB can enhance data interoperability across different platforms and tools.
After conversion, it’s crucial to verify that the GRIB file has been created correctly. You can do this by checking the contents:
1
grib_ls output_file.grib
Verify the initial condition
To plot the vertical profiles of the given data, we can use Python with the matplotlib library. Here's how visualize the profiles of signal_1p25, signal_0p25, diff_era5 and diff-MPAS-init.nc against the specified levels.
#------------------------------------------------# #Author: wpsze #Email: wpsze #date: 2025-02-06 08:54:13 #Version: 0.0 #Description: The purpose of the script #Copyright (C): 2025 All rights reserved #------------------------------------------------#
import xarray as xr import numpy as np import pandas as pd import matplotlib.pyplot as plt
SMALL_SIZE = 8 MEDIUM_SIZE = 10 BIGGER_SIZE = 24
plt.rcParams["figure.figsize"] = (10,8) plt.rc('font', size=BIGGER_SIZE) # controls default text sizes plt.rc('axes', titlesize=BIGGER_SIZE) # fontsize of the axes title plt.rc('axes', labelsize=BIGGER_SIZE) # fontsize of the x and y labels plt.rc('xtick', labelsize=BIGGER_SIZE) # fontsize of the tick labels plt.rc('ytick', labelsize=BIGGER_SIZE) # fontsize of the tick labels plt.rc('legend', fontsize=BIGGER_SIZE) # legend fontsize plt.rc('figure', titlesize=BIGGER_SIZE) # fontsize of the figure title
tmp = diff_init["skintemp"] print(f"diff init (future-past) skintemp = {np.nanmean(tmp)}") #============== vertial ============================= # Extract the variable 'ta' (ensure to adjust the variable name if it's different) ta_signal = dsignal['diff_ta'] ta_signal_0p25 = dsignal_0p25['diff_ta'] ta_era5 = diff_PL['t']
# Assuming the vertical dimension is named 'level' or 'plev'; adjust as necessary levels = ta_signal['level'].values # Adjust depending on your dimensions levels_era5 = diff_PL['isobaricInhPa'].values # Adjust depending on your dimensions
# Add labels and title plt.xlabel('diff Temperature (K)') # Adjust based on your variable unit plt.ylabel('Pressure Level (hPa)') # Adjust based on your vertical coordinate plt.title('Vertical Profiles of diff Temperature (ta)') plt.legend() plt.grid() plt.gca().invert_yaxis() # Invert y-axis for pressure levels plt.tight_layout()
# Show the plot # plt.show() plt.savefig("diff_ta.png", dpi=300)
#============== vertial ============================= # Extract the variable 'ta' (ensure to adjust the variable name if it's different) ta_signal = dsignal['diff_rh'] ta_signal_0p25 = dsignal_0p25['diff_rh'] ta_era5 = diff_PL['r']
# Assuming the vertical dimension is named 'level' or 'plev'; adjust as necessary levels = ta_signal['level'].values # Adjust depending on your dimensions levels_era5 = diff_PL['isobaricInhPa'].values # Adjust depending on your dimensions
# Add labels and title plt.xlabel('diff RH (%)') # Adjust based on your variable unit plt.ylabel('Pressure Level (hPa)') # Adjust based on your vertical coordinate plt.title('Vertical Profiles of diff RH (%)') plt.legend() plt.grid() plt.gca().invert_yaxis() # Invert y-axis for pressure levels plt.tight_layout()
# Show the plot # plt.show() plt.savefig("diff_rh.png", dpi=300)
# Add labels and title plt.xlabel('diff RH (%)') # Adjust based on your variable unit plt.ylabel('level') # Adjust based on your vertical coordinate plt.title('Vertical Profiles of diff RH (%)') plt.legend() plt.grid() plt.tight_layout()
# Show the plot # plt.show() plt.savefig("diff_init_rh.png", dpi=300)
NCL references
Discussion Summary
Which Variables Can Be Used?
The selection of variables is highly dependent on the specific goals and context of the case study. Commonly utilized variables include:
Temperature (T): Essential for understanding thermal dynamics.
Relative Humidity (RH): Important for moisture content and cloud formation.
Additional variables may include geopotential and wind components, depending on the focus of the study.
Importing Wind Components (u, v): !!!
The decision to import wind components (u and v) should be guided by their relevance to the study. Wind data is crucial for:
Enhancing model accuracy, especially in studies involving atmospheric dynamics.
Providing insights into transport processes and weather patterns.
The PGW method is designed to isolate the thermodynamic effects of climate change while largely preserving the historical synoptic patterns and dynamics of the atmosphere, such as the large-scale wind fields that govern tropical cyclone steering. In most PGW implementations, the future climate signal is applied to thermodynamic variables (e.g., temperature and specific humidity profiles) rather than dynamic variables like the 3D wind field. This is because altering the wind field directly could disrupt the atmospheric balance (e.g., geostrophic or hydrostatic equilibrium), leading to unrealistic adjustments in the model during the initial spin-up period. Instead, the wind fields are typically left unchanged in the initial conditions, allowing the model to dynamically adjust the winds in response to the perturbed thermodynamic state as the simulation evolves.
For tropical cyclones, the steering flow—defined as the vertically averaged environmental wind that guides the storm’s motion—is a critical factor. This flow is influenced by the large-scale circulation patterns (e.g., subtropical ridges, troughs, and jet streams), which are part of the initial and boundary conditions derived from reanalysis data (e.g., ERA-Interim or NCEP) in a control run. In a PGW simulation, the assumption is often that the future climate signal does not significantly alter these large-scale wind patterns in the initial state. Therefore, in many studies, the 3D wind field is not explicitly modified by adding a future wind signal to the initial conditions. The focus is instead on how thermodynamic changes (e.g., warmer SSTs, increased atmospheric moisture) affect cyclone intensity, structure, and potentially its track indirectly through feedback on the dynamics.
If your goal is to isolate the thermodynamic effects of warming (e.g., how increased SSTs or humidity affect TC intensity), then not adding a 3D wind perturbation is standard practice. The steering flow will remain consistent with the historical case, and any changes in TC behavior will stem from thermodynamic feedbacks.
If your goal is to explore how future changes in large-scale circulation might affect TC steering, then you could consider adding a 3D wind perturbation derived from GCM projections (e.g., CMIP5 or CMIP6 under a scenario like RCP8.5). However, this is less common in PGW because:
GCMs show significant disagreement on future wind field changes, especially at regional scales relevant to TC steering.
Adding wind perturbations risks introducing imbalances that could destabilize the model unless carefully adjusted (e.g., via pressure corrections to maintain hydrostatic balance).
The steering flow’s response to climate change is often studied separately using full transient GCM simulations rather than PGW.
In practice, some PGW studies avoid wind perturbations entirely to maintain consistency with the historical storm track and focus on intensity or precipitation changes. Others might use sensitivity experiments to test the impact of hypothetical wind changes, but this is not the norm.
Interpolation Methods:
Horizontal Interpolation: Bilinear interpolation is commonly used for its simplicity and effectiveness in providing smooth transitions between grid points.
Vertical Interpolation: The choice between linear and logarithmic interpolation should be based on the nature of the variable being interpolated:
Linear Interpolation is suitable for most variables.
Logarithmic Interpolation may be more appropriate for variables with a wide range of values, such as pressure or density.
Consideration of Vertical Levels:
When performing vertical interpolation, it is important to consider whether to include levels such as 100 hPa. Generally:
If the climate signal data does not extend above certain levels (e.g., 50 hPa), it is prudent to exclude those levels to avoid introducing inconsistencies into the model.
Data Integration Formats:
The climate signal can be integrated into different formats based on the model being used:
For ERA5, climate signals can be added to the ICBC (Initial Condition Boundary Condition) files in GRIB format.
In WRF, data may be added directly to met_em files, which are used for meteorological input.
ungrib
Extract meteorological fields from GRIB files
metgrid
Horizontally interpolate meteorological fields (from ungrib) to simulation grids (defined by geogrid)
real.exe
Initialization will calculate reference state, vertical coordinate interpolation, disturbance field calculation, output boundary conditions, surface data mask, etc.
So, it is fine for adding signal into met_em because met_em only does horizontal interpolation.
wrf.exe
For MPAS, it is no met_em step and only from static.nc to init.nc. Therefore, the only way is to add signal into ICBC=ERA5.
Long-term Simulations:
For extended runs in both MPAS and WRF, it is essential to regularly update SST data. This practice helps maintain the relevance of the model outputs to current climate conditions, ensuring that the simulations reflect the most recent data and improving the accuracy of long-term forecasts.
Integrating and interpolating climate variables in models like WRF and MPAS involves careful consideration of the variables used, the methods of interpolation, and the formats for data integration. By addressing these factors, researchers can enhance the accuracy and reliability of climate and weather predictions. Proper handling of SST and other variables in both short-term and long-term simulations is crucial for effective climate modeling and analysis.
cdo -v -f grb -copy sstatlantic_addhifreq.nc ofile.grb
cdo -v -f grb2 -copy sstatlantic_addhifreq.nc ofile.grb if grib2 format.
The large GRIB file has data with 2602x1402=3648004 grid points. CDO stores netCDF double precision floats to 24bit packed GRIB per default. The result is a GRIB record with 10944120 bytes. The max. record length in the GRIB1 standard is 8388607 bytes. CDO uses the ECMWF extension of the GRIB1 standard for larger GRIB records. These large GRIB records can only be read by CDO or tools from the ECMWF.
You can create a 16bit GRIB record to reduce the record size:
cdo -b 16 -f grb copy file.nc file.grb
Due to the fact that the NetCDF data model is much more free and extensible than the GRIB one, it is not possible to write a generic xarray.Dataset to a GRIB file. The aim for cfgrib is to implement write support for a subset of carefully crafted datasets that fit the GRIB data model. In particular the only coordinates that we target at the moment are the one returned by opening a GRIB with the cfgrib flavour of cfgrib.open_dataset, namely:number, time, step, a vertical coordinate (isobaricInhPa, heightAboveGround, surface, etc), and the horizontal coordinates (for example latitude and longitude for a regular_ll grid type).