Plot Profiles from ICON 3D Data

Here, we proceed with ICON data. We will have a look at 3D ICON data.

Load Python Libraries

[1]:
%matplotlib inline

# system libs
import os, sys, glob

# array operators and netcdf datasets
import numpy as np
import xarray as xr
xr.set_options(keep_attrs=True)

# plotting
import pylab as plt
import seaborn as sns
sns.set_context('talk')

Open Data with xarray

General Paths

[2]:
exercise_path = '/work/bb1224/2023_MS-COURSE'
data_path = f'{exercise_path}/data'
icon_data_path = f'{data_path}/icon-lem'

This is very similar to the tasks already done.

[3]:
os.listdir(icon_data_path)
[3]:
['grids-extpar', 'experiments', 'bc-init']

Now, we select the experimentfolder in which pre-calculated experiments are stored. Later, you need to change this directory to your ICON output directory!

[4]:
exp_name = 'icon_lam_1dom_lpz-base'
exp_path = f'{icon_data_path}/experiments/{exp_name}'
[5]:
sorted( os.listdir( exp_path, ))
[5]:
['2d_cloud_DOM01_ML_20210516T000000Z.nc',
 '2d_cloud_DOM01_ML_20210516T010000Z.nc',
 '2d_cloud_DOM01_ML_20210516T020000Z.nc',
 '2d_cloud_DOM01_ML_20210516T030000Z.nc',
 '2d_cloud_DOM01_ML_20210516T040000Z.nc',
 '2d_cloud_DOM01_ML_20210516T050000Z.nc',
 '2d_cloud_DOM01_ML_20210516T060000Z.nc',
 '2d_cloud_DOM01_ML_20210516T070000Z.nc',
 '2d_cloud_DOM01_ML_20210516T080000Z.nc',
 '2d_cloud_DOM01_ML_20210516T090000Z.nc',
 '2d_cloud_DOM01_ML_20210516T100000Z.nc',
 '2d_cloud_DOM01_ML_20210516T110000Z.nc',
 '2d_cloud_DOM01_ML_20210516T120000Z.nc',
 '2d_cloud_DOM01_ML_20210516T130000Z.nc',
 '2d_cloud_DOM01_ML_20210516T140000Z.nc',
 '2d_cloud_DOM01_ML_20210516T150000Z.nc',
 '2d_cloud_DOM01_ML_20210516T160000Z.nc',
 '2d_cloud_DOM01_ML_20210516T170000Z.nc',
 '2d_cloud_DOM01_ML_20210516T180000Z.nc',
 '2d_cloud_DOM01_ML_20210516T190000Z.nc',
 '2d_cloud_DOM01_ML_20210516T200000Z.nc',
 '2d_cloud_DOM01_ML_20210516T210000Z.nc',
 '2d_cloud_DOM01_ML_20210516T220000Z.nc',
 '2d_cloud_DOM01_ML_20210516T230000Z.nc',
 '2d_cloud_DOM01_ML_20210517T000000Z.nc',
 '2d_rad_DOM01_ML_20210516T000000Z.nc',
 '2d_rad_DOM01_ML_20210516T010000Z.nc',
 '2d_rad_DOM01_ML_20210516T020000Z.nc',
 '2d_rad_DOM01_ML_20210516T030000Z.nc',
 '2d_rad_DOM01_ML_20210516T040000Z.nc',
 '2d_rad_DOM01_ML_20210516T050000Z.nc',
 '2d_rad_DOM01_ML_20210516T060000Z.nc',
 '2d_rad_DOM01_ML_20210516T070000Z.nc',
 '2d_rad_DOM01_ML_20210516T080000Z.nc',
 '2d_rad_DOM01_ML_20210516T090000Z.nc',
 '2d_rad_DOM01_ML_20210516T100000Z.nc',
 '2d_rad_DOM01_ML_20210516T110000Z.nc',
 '2d_rad_DOM01_ML_20210516T120000Z.nc',
 '2d_rad_DOM01_ML_20210516T130000Z.nc',
 '2d_rad_DOM01_ML_20210516T140000Z.nc',
 '2d_rad_DOM01_ML_20210516T150000Z.nc',
 '2d_rad_DOM01_ML_20210516T160000Z.nc',
 '2d_rad_DOM01_ML_20210516T170000Z.nc',
 '2d_rad_DOM01_ML_20210516T180000Z.nc',
 '2d_rad_DOM01_ML_20210516T190000Z.nc',
 '2d_rad_DOM01_ML_20210516T200000Z.nc',
 '2d_rad_DOM01_ML_20210516T210000Z.nc',
 '2d_rad_DOM01_ML_20210516T220000Z.nc',
 '2d_rad_DOM01_ML_20210516T230000Z.nc',
 '2d_rad_DOM01_ML_20210517T000000Z.nc',
 '2d_surface_DOM01_ML_20210516T000000Z.nc',
 '2d_surface_DOM01_ML_20210516T010000Z.nc',
 '2d_surface_DOM01_ML_20210516T020000Z.nc',
 '2d_surface_DOM01_ML_20210516T030000Z.nc',
 '2d_surface_DOM01_ML_20210516T040000Z.nc',
 '2d_surface_DOM01_ML_20210516T050000Z.nc',
 '2d_surface_DOM01_ML_20210516T060000Z.nc',
 '2d_surface_DOM01_ML_20210516T070000Z.nc',
 '2d_surface_DOM01_ML_20210516T080000Z.nc',
 '2d_surface_DOM01_ML_20210516T090000Z.nc',
 '2d_surface_DOM01_ML_20210516T100000Z.nc',
 '2d_surface_DOM01_ML_20210516T110000Z.nc',
 '2d_surface_DOM01_ML_20210516T120000Z.nc',
 '2d_surface_DOM01_ML_20210516T130000Z.nc',
 '2d_surface_DOM01_ML_20210516T140000Z.nc',
 '2d_surface_DOM01_ML_20210516T150000Z.nc',
 '2d_surface_DOM01_ML_20210516T160000Z.nc',
 '2d_surface_DOM01_ML_20210516T170000Z.nc',
 '2d_surface_DOM01_ML_20210516T180000Z.nc',
 '2d_surface_DOM01_ML_20210516T190000Z.nc',
 '2d_surface_DOM01_ML_20210516T200000Z.nc',
 '2d_surface_DOM01_ML_20210516T210000Z.nc',
 '2d_surface_DOM01_ML_20210516T220000Z.nc',
 '2d_surface_DOM01_ML_20210516T230000Z.nc',
 '2d_surface_DOM01_ML_20210517T000000Z.nc',
 '3d_full_aux_DOM01_ML_20210516T000000Z.nc',
 '3d_full_aux_DOM01_ML_20210516T010000Z.nc',
 '3d_full_aux_DOM01_ML_20210516T020000Z.nc',
 '3d_full_aux_DOM01_ML_20210516T030000Z.nc',
 '3d_full_aux_DOM01_ML_20210516T040000Z.nc',
 '3d_full_aux_DOM01_ML_20210516T050000Z.nc',
 '3d_full_aux_DOM01_ML_20210516T060000Z.nc',
 '3d_full_aux_DOM01_ML_20210516T070000Z.nc',
 '3d_full_aux_DOM01_ML_20210516T080000Z.nc',
 '3d_full_aux_DOM01_ML_20210516T090000Z.nc',
 '3d_full_aux_DOM01_ML_20210516T100000Z.nc',
 '3d_full_aux_DOM01_ML_20210516T110000Z.nc',
 '3d_full_aux_DOM01_ML_20210516T120000Z.nc',
 '3d_full_aux_DOM01_ML_20210516T130000Z.nc',
 '3d_full_aux_DOM01_ML_20210516T140000Z.nc',
 '3d_full_aux_DOM01_ML_20210516T150000Z.nc',
 '3d_full_aux_DOM01_ML_20210516T160000Z.nc',
 '3d_full_aux_DOM01_ML_20210516T170000Z.nc',
 '3d_full_aux_DOM01_ML_20210516T180000Z.nc',
 '3d_full_aux_DOM01_ML_20210516T190000Z.nc',
 '3d_full_aux_DOM01_ML_20210516T200000Z.nc',
 '3d_full_aux_DOM01_ML_20210516T210000Z.nc',
 '3d_full_aux_DOM01_ML_20210516T220000Z.nc',
 '3d_full_aux_DOM01_ML_20210516T230000Z.nc',
 '3d_full_aux_DOM01_ML_20210517T000000Z.nc',
 '3d_full_base_DOM01_ML_20210516T000000Z.nc',
 '3d_full_base_DOM01_ML_20210516T010000Z.nc',
 '3d_full_base_DOM01_ML_20210516T020000Z.nc',
 '3d_full_base_DOM01_ML_20210516T030000Z.nc',
 '3d_full_base_DOM01_ML_20210516T040000Z.nc',
 '3d_full_base_DOM01_ML_20210516T050000Z.nc',
 '3d_full_base_DOM01_ML_20210516T060000Z.nc',
 '3d_full_base_DOM01_ML_20210516T070000Z.nc',
 '3d_full_base_DOM01_ML_20210516T080000Z.nc',
 '3d_full_base_DOM01_ML_20210516T090000Z.nc',
 '3d_full_base_DOM01_ML_20210516T100000Z.nc',
 '3d_full_base_DOM01_ML_20210516T110000Z.nc',
 '3d_full_base_DOM01_ML_20210516T120000Z.nc',
 '3d_full_base_DOM01_ML_20210516T130000Z.nc',
 '3d_full_base_DOM01_ML_20210516T140000Z.nc',
 '3d_full_base_DOM01_ML_20210516T150000Z.nc',
 '3d_full_base_DOM01_ML_20210516T160000Z.nc',
 '3d_full_base_DOM01_ML_20210516T170000Z.nc',
 '3d_full_base_DOM01_ML_20210516T180000Z.nc',
 '3d_full_base_DOM01_ML_20210516T190000Z.nc',
 '3d_full_base_DOM01_ML_20210516T200000Z.nc',
 '3d_full_base_DOM01_ML_20210516T210000Z.nc',
 '3d_full_base_DOM01_ML_20210516T220000Z.nc',
 '3d_full_base_DOM01_ML_20210516T230000Z.nc',
 '3d_full_base_DOM01_ML_20210517T000000Z.nc',
 '3d_full_geo_DOM01_ML_20210516T000000Z.nc',
 '3d_full_geo_DOM01_ML_20210517T000000Z.nc',
 '3d_full_qmix_DOM01_ML_20210516T000000Z.nc',
 '3d_full_qmix_DOM01_ML_20210516T010000Z.nc',
 '3d_full_qmix_DOM01_ML_20210516T020000Z.nc',
 '3d_full_qmix_DOM01_ML_20210516T030000Z.nc',
 '3d_full_qmix_DOM01_ML_20210516T040000Z.nc',
 '3d_full_qmix_DOM01_ML_20210516T050000Z.nc',
 '3d_full_qmix_DOM01_ML_20210516T060000Z.nc',
 '3d_full_qmix_DOM01_ML_20210516T070000Z.nc',
 '3d_full_qmix_DOM01_ML_20210516T080000Z.nc',
 '3d_full_qmix_DOM01_ML_20210516T090000Z.nc',
 '3d_full_qmix_DOM01_ML_20210516T100000Z.nc',
 '3d_full_qmix_DOM01_ML_20210516T110000Z.nc',
 '3d_full_qmix_DOM01_ML_20210516T120000Z.nc',
 '3d_full_qmix_DOM01_ML_20210516T130000Z.nc',
 '3d_full_qmix_DOM01_ML_20210516T140000Z.nc',
 '3d_full_qmix_DOM01_ML_20210516T150000Z.nc',
 '3d_full_qmix_DOM01_ML_20210516T160000Z.nc',
 '3d_full_qmix_DOM01_ML_20210516T170000Z.nc',
 '3d_full_qmix_DOM01_ML_20210516T180000Z.nc',
 '3d_full_qmix_DOM01_ML_20210516T190000Z.nc',
 '3d_full_qmix_DOM01_ML_20210516T200000Z.nc',
 '3d_full_qmix_DOM01_ML_20210516T210000Z.nc',
 '3d_full_qmix_DOM01_ML_20210516T220000Z.nc',
 '3d_full_qmix_DOM01_ML_20210516T230000Z.nc',
 '3d_full_qmix_DOM01_ML_20210517T000000Z.nc',
 '3d_full_tend_DOM01_ML_20210516T000000Z.nc',
 '3d_full_tend_DOM01_ML_20210516T010000Z.nc',
 '3d_full_tend_DOM01_ML_20210516T020000Z.nc',
 '3d_full_tend_DOM01_ML_20210516T030000Z.nc',
 '3d_full_tend_DOM01_ML_20210516T040000Z.nc',
 '3d_full_tend_DOM01_ML_20210516T050000Z.nc',
 '3d_full_tend_DOM01_ML_20210516T060000Z.nc',
 '3d_full_tend_DOM01_ML_20210516T070000Z.nc',
 '3d_full_tend_DOM01_ML_20210516T080000Z.nc',
 '3d_full_tend_DOM01_ML_20210516T090000Z.nc',
 '3d_full_tend_DOM01_ML_20210516T100000Z.nc',
 '3d_full_tend_DOM01_ML_20210516T110000Z.nc',
 '3d_full_tend_DOM01_ML_20210516T120000Z.nc',
 '3d_full_tend_DOM01_ML_20210516T130000Z.nc',
 '3d_full_tend_DOM01_ML_20210516T140000Z.nc',
 '3d_full_tend_DOM01_ML_20210516T150000Z.nc',
 '3d_full_tend_DOM01_ML_20210516T160000Z.nc',
 '3d_full_tend_DOM01_ML_20210516T170000Z.nc',
 '3d_full_tend_DOM01_ML_20210516T180000Z.nc',
 '3d_full_tend_DOM01_ML_20210516T190000Z.nc',
 '3d_full_tend_DOM01_ML_20210516T200000Z.nc',
 '3d_full_tend_DOM01_ML_20210516T210000Z.nc',
 '3d_full_tend_DOM01_ML_20210516T220000Z.nc',
 '3d_full_tend_DOM01_ML_20210516T230000Z.nc',
 '3d_full_tend_DOM01_ML_20210517T000000Z.nc',
 'ECHAM6_CldOptProps.nc',
 'NAMELIST_ICON_output_atm',
 'NAMELIST_icon_lam_1dom_lpz-base',
 'check_global_quantities.dat',
 'dmin_wetgrowth_lookup.nc',
 'dwdFG_R2B09_DOM01.nc',
 'extpar_lpz_r2_dom01_DOM01.nc',
 'extpar_lpz_r2_dom02_DOM02.nc',
 'finish.status',
 'icon_master.namelist',
 'ifs2icon_R2B09_DOM01.nc',
 'lpz_r2_dom01_DOM01.nc',
 'lsdata.nc',
 'nml.atmo.log',
 'output_schedule.ps',
 'output_schedule.txt',
 'rrtmg_lw.nc',
 'rrtmg_sw.nc',
 'sound_rce',
 'total_integrals.dat',
 'tracer_total_integrals.dat']

Ui, many files! Again, files with .nc are our netcdf data. The suffix _mean indicates files for domain-mean quantities that have been calculated with cdo.

Let’s have a look at the different categories:

[6]:
sorted( glob.glob( f'{exp_path}/*DOM01_ML_20210516T120000Z.nc') )
[6]:
['/work/bb1224/2023_MS-COURSE/data/icon-lem/experiments/icon_lam_1dom_lpz-base/2d_cloud_DOM01_ML_20210516T120000Z.nc',
 '/work/bb1224/2023_MS-COURSE/data/icon-lem/experiments/icon_lam_1dom_lpz-base/2d_rad_DOM01_ML_20210516T120000Z.nc',
 '/work/bb1224/2023_MS-COURSE/data/icon-lem/experiments/icon_lam_1dom_lpz-base/2d_surface_DOM01_ML_20210516T120000Z.nc',
 '/work/bb1224/2023_MS-COURSE/data/icon-lem/experiments/icon_lam_1dom_lpz-base/3d_full_aux_DOM01_ML_20210516T120000Z.nc',
 '/work/bb1224/2023_MS-COURSE/data/icon-lem/experiments/icon_lam_1dom_lpz-base/3d_full_base_DOM01_ML_20210516T120000Z.nc',
 '/work/bb1224/2023_MS-COURSE/data/icon-lem/experiments/icon_lam_1dom_lpz-base/3d_full_qmix_DOM01_ML_20210516T120000Z.nc',
 '/work/bb1224/2023_MS-COURSE/data/icon-lem/experiments/icon_lam_1dom_lpz-base/3d_full_tend_DOM01_ML_20210516T120000Z.nc']
  • 2d_rad : variables related to radiation

  • 2d_cloud : variable related to clouds & precipitation

  • 2d_surface : variable related to surface properties or surface budgets

  • 3d_full_base : main prognostic variables

  • 3d_full_qmix : hydrometeor mass mixing ratios

  • 3d_full_qnum : hydrometeor number mixing ratios

  • 3d_full_tend : tendencies of some prognostic variables (incl. physic parameterizations)

  • 3d_full_aux : some additional 3d fields

Please, open a terminal and look at the file content. (Using either cdo sinfov <filename> or ncdump -h <filename>).

Base Files

[7]:
dset = xr.open_dataset( f'{exp_path}/3d_full_base_DOM01_ML_20210516T120000Z.nc', chunks={} )

This is the content of the dataset.

[8]:
dset.data_vars
[8]:
Data variables:
    height_bnds  (height, bnds) float64 dask.array<chunksize=(50, 2), meta=np.ndarray>
    u            (time, height, ncells) float32 dask.array<chunksize=(1, 50, 10212), meta=np.ndarray>
    v            (time, height, ncells) float32 dask.array<chunksize=(1, 50, 10212), meta=np.ndarray>
    w            (time, height_2, ncells) float32 dask.array<chunksize=(1, 51, 10212), meta=np.ndarray>
    clc          (time, height, ncells) float32 dask.array<chunksize=(1, 50, 10212), meta=np.ndarray>
    qv           (time, height, ncells) float32 dask.array<chunksize=(1, 50, 10212), meta=np.ndarray>
    temp         (time, height, ncells) float32 dask.array<chunksize=(1, 50, 10212), meta=np.ndarray>
    pres         (time, height, ncells) float32 dask.array<chunksize=(1, 50, 10212), meta=np.ndarray>
    theta_v      (time, height, ncells) float32 dask.array<chunksize=(1, 50, 10212), meta=np.ndarray>

It is easy to guess for which each variable name stands. If you don’t like to guess, you could further look at dataset attributes:

[9]:
dset['u']
[9]:
<xarray.DataArray 'u' (time: 1, height: 50, ncells: 10212)>
dask.array<open_dataset-64fac6d26e8a9b24d92022a341bd8692u, shape=(1, 50, 10212), dtype=float32, chunksize=(1, 50, 10212), chunktype=numpy.ndarray>
Coordinates:
  * time     (time) float64 2.021e+07
  * height   (height) float64 1.0 2.0 3.0 4.0 5.0 ... 46.0 47.0 48.0 49.0 50.0
Dimensions without coordinates: ncells
Attributes:
    standard_name:                eastward_wind
    long_name:                    Zonal wind
    units:                        m s-1
    param:                        2.2.0
    CDI_grid_type:                unstructured
    number_of_grid_in_reference:  1

Calculate Average Profiles

[10]:
dset_mean = dset.mean( 'ncells' )

There is an additional time dimension of length = 1. This is not needed and we get rid of it if the queezemethod:

[11]:
dset_mean = dset_mean.squeeze()

Plotting the Profiles

Model Level as Vertical Coordinate

The coordinate height denotes the ICON model level:

[12]:
dset['height']
[12]:
<xarray.DataArray 'height' (height: 50)>
array([ 1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10., 11., 12., 13., 14.,
       15., 16., 17., 18., 19., 20., 21., 22., 23., 24., 25., 26., 27., 28.,
       29., 30., 31., 32., 33., 34., 35., 36., 37., 38., 39., 40., 41., 42.,
       43., 44., 45., 46., 47., 48., 49., 50.])
Coordinates:
  * height   (height) float64 1.0 2.0 3.0 4.0 5.0 ... 46.0 47.0 48.0 49.0 50.0
Attributes:
    standard_name:  height
    long_name:      generalized_height
    axis:           Z
    bounds:         height_bnds

These are terrain-following coordinates and additional data are needed to relate model level to a geometric height above ground or perhaps to atmospheric pressure.

Let’ shave a look at the pressure profile first to understand how model level are sorted.

[13]:
plt.figure( figsize = (4,6))
dset_mean['pres'].plot( y = 'height', lw = 3)
plt.title( 'Pressure / Pa', fontweight = 'bold')
sns.despine()
../_images/nbooks_02-Plot_Profiles_from_ICON_3D_Data_30_0.png

OK; pressure is lowest at model level equal to one, i.e. model levels increase from top to bottom!

Average Pressure on Vertical Axis

Atmospheric scientist like the pressure coordinate. Here, we do the trick that we still plot model level, but show the typical average pressure which each level corresponds to. This practice is very often sufficient.

We prepare the average pressure:

[14]:
p_average = dset_mean['pres'] / 1e2   # conversion into hPa
p_average.attrs['units'] = 'hPa'

and then assign the pressure to the heightcoordinate:

[15]:
dset_mean = dset_mean.assign_coords( {'height': p_average})
dset_mean = dset_mean.rename( {'height': 'pressure'})

dset_mean = dset_mean.sel( pressure = slice(200,1000))

finally, we plot the profiles of the atmopsheric variables as multi-panel plot:

[16]:
figure, axs = plt.subplots( ncols = 3, nrows = 2, figsize = (14,16),)
axs = axs.flatten()
plt.subplots_adjust( hspace = 0.5, wspace = 0.5)
for i, varname in enumerate( ['u', 'v', 'qv', 'clc', 'temp', 'theta_v'] ):

    plt.sca( axs[i] )

    v = dset_mean[varname]
    v.plot( y = 'pressure', lw = 3 )

    plt.title('%s / %s' % (v.long_name, v.units), pad = 20, fontweight = 'bold')
    plt.ylim(1000., 200.)
    sns.despine()
../_images/nbooks_02-Plot_Profiles_from_ICON_3D_Data_39_0.png

Tasks

Use this notebook to explore the other 3d_*nc files:

  • Do you understand the meaning of the different variables?

  • Specifically, how are liquid and frozen hydrometeors distributed?