Example: convert WRF-LES output to DEPHY format#

Code to read WRF-LES output files and write to DEPHY format (NetCDF)

Contributed by Tim Juliano from NCAR, last updated on 12/1/23

Import libraries#

import xarray as xr
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import csv
import os
import netCDF4
import datetime as dt
from netCDF4 import Dataset
import glob
import copy
from scipy import interpolate

Specify directory locations#

If on the ARM JupyterHub, it is recommended to create and specify a local directory that is outside of the COMBLE-MIP repository to upload raw model output files in your model’s format.

Processed LES/SCM outputs are invited for commit to the GitHub repository on a user-specified branch under /comble-mip/output_XXX/YOUR_MODEL_NAME/sandbox/YOUR_RUN_NAME where output_XXX can be either output_les or output_scm. These can be committed and removed at any time. A reminder that file naming conventions may be found here.

# specify source for forcing file
myforcingfile = '/glade/scratch/tjuliano/doe_comble/intercomparison/dephy_forcing/COMBLE_INTERCOMPARISON_FORCING_V2.3.nc'

# specify source directory for model outputs
my_rootdir = '/glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/'

################################ CHANGE SIM NAME HERE
my_simname = 'Lx25km_dx100m_new_z0_v2.3_tim'
#my_simname = 'Lx25km_dx100m_def_z0'
#my_simname = 'Lx25km_dx100m_new_z0_noice'
################################

################################ CHANGE DEPHY FILE NAME HERE
dephy_filename = 'WRF_Lx25_dx100_FixN.nc'
#dephy_filename = 'WRF_Lx25_dx100_FixN_def_z0.nc'
#dephy_filename = 'WRF_Lx25_dx100_FixN_noice.nc'
################################

my_rundir = my_rootdir + my_simname
are_there_subdirs = False
if are_there_subdirs:
    subdir_name = 'run'
    my_subdirs = sorted(glob.glob(my_rundir + '/'+subdir_name+'*/'))

# specify save directory
my_savedir = './output_les/wrf/sandbox/'
if not os.path.exists(my_savedir):
    os.makedirs(my_savedir)
    
# minutes between WRF samples
delt_min = 10.
delt = delt_min*60

# consider ice fields?
do_ice = True
if 'noice' in dephy_filename:
    do_ice = False
    
# consider prognostic aerosol fields?
do_progNa = False
if 'ProgNa' in dephy_filename:
    do_progNa = True

Read forcing file and get model height at mid points and edges#

We will need this info to interpolate WRF outputs from native levels to requested levels, as model levels drift slightly during the simulation due to WRF’s sigma vertical coordinate system#

forcing_params = xr.open_dataset(myforcingfile,decode_times=False)
zw_grid = forcing_params['zw_grid'].data # model layer top points
zm_grid = (zw_grid[1:] + zw_grid[0:-1]) / 2. # model layer mid points

Read WRF data#

Read parameters settings#

if are_there_subdirs:
    wrfout_filenames = sorted(glob.glob(my_subdirs[0] + 'wrfout*'))
else:
    wrfout_filenames = sorted(glob.glob(my_rundir + '/wrfout*'))
wrfout_params = xr.open_dataset(wrfout_filenames[0],decode_times=False)
wrf_dx = wrfout_params.DX
wrf_dy = wrfout_params.DY
wrf_nx = wrfout_params.dims['west_east']
wrf_ny = wrfout_params.dims['south_north']
wrf_nz = wrfout_params.dims['bottom_top']
wrf_lat = wrfout_params['XLAT'].data.mean()

Gather all files#

if are_there_subdirs:
    for i in np.arange(len(my_subdirs)):
        if i == 0:
            input_filenames = sorted(glob.glob(my_subdirs[i] + 'wrfstat*'))
        else:
            input_filenames = np.concatenate((input_filenames,sorted(glob.glob(my_subdirs[i] + 'wrfstat*'))))
else:
    input_filenames = sorted(glob.glob(my_rundir + '/wrfstat*'))
print (input_filenames)
['/glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-12_22:00:00', '/glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-12_23:00:00', '/glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_00:00:00', '/glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_01:00:00', '/glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_02:00:00', '/glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_03:00:00', '/glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_04:00:00', '/glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_05:00:00', '/glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_06:00:00', '/glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_07:00:00', '/glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_08:00:00', '/glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_09:00:00', '/glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_10:00:00', '/glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_11:00:00', '/glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_12:00:00', '/glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_13:00:00', '/glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_14:00:00', '/glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_15:00:00', '/glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_16:00:00', '/glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_17:00:00', '/glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_18:00:00']

Subset variables depending on 1D time series, domain mean soundings, etc.#

wrf_file = xr.open_dataset(input_filenames[0],decode_times=False)
    
# find all WRF variables
wrf_vars = [i for i in wrf_file.data_vars]
#print (wrf_vars)

# find subset of variables for 1D time series (these variables start with 'CST')
wrf_vars_cst = [j for j in wrf_vars if ('CST' in j or 'Times' in j)]

# find subset of variables for 2D (time x height) soundings (these variables start with 'CSP')
wrf_vars_csp = [j for j in wrf_vars if ('CSP' in j or 'Times' in j)]

Read domain-mean profiles#

skip_t0_next_file = False
for i in np.arange(len(input_filenames)):
    print ('Doing ', input_filenames[i])
    dummy_file = xr.open_dataset(input_filenames[i],decode_times=False)
    if i == 0:
        wrf_snds = dummy_file[wrf_vars_csp]
    else:
        if skip_t0_next_file:
            wrf_snds = xr.concat([wrf_snds,dummy_file[wrf_vars_csp].isel(Time=np.arange(1,12))],dim="Time")
            skip_t0_next_file = False
        else:
            wrf_snds = xr.concat([wrf_snds,dummy_file[wrf_vars_csp]],dim="Time")
            
    if len(dummy_file['Times']) == 1:
        skip_t0_next_file = True
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-12_22:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-12_23:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_00:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_01:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_02:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_03:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_04:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_05:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_06:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_07:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_08:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_09:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_10:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_11:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_12:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_13:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_14:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_15:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_16:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_17:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_18:00:00

Read domain-mean scalars#

skip_t0_next_file = False
for i in np.arange(len(input_filenames)):
    print ('Doing ', input_filenames[i])
    dummy_file = xr.open_dataset(input_filenames[i],decode_times=False)
    if i == 0:
        wrf_scas = dummy_file[wrf_vars_cst]
    else:
        if skip_t0_next_file:
            wrf_scas = xr.concat([wrf_scas,dummy_file[wrf_vars_cst].isel(Time=np.arange(1,12))],dim="Time")
            skip_t0_next_file = False
        else:
            wrf_scas = xr.concat([wrf_scas,dummy_file[wrf_vars_cst]],dim="Time")        
        
    if len(dummy_file['Times']) == 1:
        skip_t0_next_file = True
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-12_22:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-12_23:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_00:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_01:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_02:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_03:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_04:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_05:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_06:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_07:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_08:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_09:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_10:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_11:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_12:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_13:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_14:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_15:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_16:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_17:00:00
Doing  /glade/scratch/tjuliano/doe_comble/wrf_asr_cao/WRF-ASR-CAO/WRF/test/GOOD_SIMS_1DOM/2023_pan_gass/v2.2/Lx25km_dx100m_new_z0_v2.3_tim/wrfstat_d01_2020-03-13_18:00:00

Unstagger any staggered variables and add to dataset#

# vertical velocity
csp_w_mass = (wrf_snds['CSP_W'][:,0:-1].data+wrf_snds['CSP_W'][:,1:].data)/2.
wrf_snds = wrf_snds.assign(variables={'CSP_W_MASS': (('Time', 'bottom_top'), csp_w_mass)})

# vertical velocity variance
csp_w2_mass = (wrf_snds['CSP_W2'][:,0:-1].data+wrf_snds['CSP_W2'][:,1:].data)/2.
wrf_snds = wrf_snds.assign(variables={'CSP_W2_MASS': (('Time', 'bottom_top'), csp_w2_mass)})

Calculate some additional variables requested, and add them to the xarray#

# obukhov length
cst_mol = 1./wrf_scas['CST_RMOL'].data
wrf_scas = wrf_scas.assign(variables={'CST_MOL': (('Time'), cst_mol)})

# total optical depth
cst_opd = wrf_scas['CST_OPDC'].data+wrf_scas['CST_OPDR'].data+wrf_scas['CST_OPDI'].data+wrf_scas['CST_OPDS'].data+wrf_scas['CST_OPDG'].data
wrf_scas = wrf_scas.assign(variables={'CST_OPD': (('Time'), cst_opd)})

# liquid water path
cst_lwp = wrf_scas['CST_CLWP'].data+wrf_scas['CST_RWP'].data
wrf_scas = wrf_scas.assign(variables={'CST_LWP': (('Time'), cst_lwp)})

# frozen water path
cst_fwp = wrf_scas['CST_IWP'].data+wrf_scas['CST_SWP'].data+wrf_scas['CST_GWP'].data
wrf_scas = wrf_scas.assign(variables={'CST_FWP': (('Time'), cst_fwp)})

# air temperature
Rd = 287.
Cp = 1004.5
csp_t = pow(wrf_snds['CSP_P'].data/100000.,Rd/Cp)*wrf_snds['CSP_TH'].data
wrf_snds = wrf_snds.assign(variables={'CSP_T': (('Time', 'bottom_top'), csp_t)})

# filter QNC to zero where QC=0.
csp_qnc_hold = wrf_snds['CSP_QNC'].data
csp_qc_hold = wrf_snds['CSP_QC'].data
csp_qnc_filter = copy.deepcopy(csp_qnc_hold)
for i in np.arange(np.shape(csp_qc_hold)[0]):
    idxx = np.where(csp_qc_hold[i,:]==0.)[0]
    csp_qnc_filter[i,idxx] = 0.
wrf_snds = wrf_snds.assign(variables={'CSP_QNC_FILTER': (('Time', 'bottom_top'), csp_qnc_filter)})

# filter CSP_THDT_COND to zero where QT=0.
csp_thdt_cond_hold = wrf_snds['CSP_THDT_COND'].data
csp_qt_hold = wrf_snds['CSP_QL'].data+wrf_snds['CSP_QF'].data
csp_thdt_cond_filter = copy.deepcopy(csp_thdt_cond_hold)
for i in np.arange(np.shape(csp_qt_hold)[0]):
    idxx = np.where(csp_qt_hold[i,:]==0.)[0]
    csp_thdt_cond_filter[i,idxx] = 0.
wrf_snds = wrf_snds.assign(variables={'CSP_THDT_COND_FILTER': (('Time', 'bottom_top'), csp_thdt_cond_filter)})
/glade/derecho/scratch/tjuliano/tmp/ipykernel_53145/3722589477.py:2: RuntimeWarning: divide by zero encountered in divide
  cst_mol = 1./wrf_scas['CST_RMOL'].data

Interpolate profile variables from WRF’s native vertical grid to requested vertical grid#

Inefficient right now, but only takes ~15 seconds…#

csp_z_new = copy.deepcopy(wrf_snds['CSP_Z'])
csp_z_new[:,:] = zm_grid
csp_zw_new = copy.deepcopy(wrf_snds['CSP_Z8W'])
csp_zw_new[:,:] = zw_grid
for t in np.arange(1,np.shape(csp_zw_new)[0]): # loop over time
    for i in wrf_snds.data_vars:
        if 'CSP' in i:
            if 'CSP_Z' not in i:
                if 'CSP_DZ' not in i:
                    if 'bottom_top' in wrf_snds[i].dims:
                        f = interpolate.interp1d(wrf_snds['CSP_Z'][t,:].data, wrf_snds[i][t,:].data, kind='linear', fill_value="extrapolate")
                        wrf_snds[i][t,:] = f(csp_z_new[t,:])
                    elif 'bottom_top_stag' in wrf_snds[i].dims:
                        f = interpolate.interp1d(wrf_snds['CSP_Z8W'][t,:].data, wrf_snds[i][t,:].data, kind='linear', fill_value="extrapolate")
                        wrf_snds[i][t,:] = f(csp_zw_new[t,:])

Prepare output file in DEPHY format#

Read requested variables list#

Variable description, naming, units, and dimensions.

# read list of requested variables
vars_mean_list = pd.read_excel('https://docs.google.com/spreadsheets/d/1Vl8jYGviet7EtXZuQiitrx4NSkV1x27aJAhxxjBb9zI/export?gid=0&format=xlsx',
                              sheet_name='Mean')

pd.set_option('display.max_rows', None)
vars_mean_list
standard_name variable_id units dimensions comment (10-min average reported at endpoints, green=minimum)
0 time time s dimension, seconds since 2020-03-12 18:00:00
1 height zf m dimension, altitude of mid-level points above ...
2 layer_top_height ze m dimension, altitude of layer top points above ...
3 surface_pressure ps Pa time
4 surface_temperature ts K time
5 surface_friction_velocity ustar m s-1 time
6 surface_roughness_length_for_momentum_in_air z0 m time
7 surface_roughness_length_for_heat_in_air z0h m time
8 surface_roughness_length_for_humidity_in_air z0q m time
9 surface_upward_sensible_heat_flux hfss W m-2 time
10 surface_upward_latent_heat_flux hfls W m-2 time
11 obukhov_length ol m time
12 atmosphere_mass_content_of_liquid_cloud_water lwpc kg m-2 time default breakdown to cloud water and rain in a...
13 atmosphere_mass_content_of_rain_water lwpr kg m-2 time
14 atmosphere_mass_content_of_ice_water iwp kg m-2 time all ice-phase hydrometeors
15 cloud_area_fraction clt 1 time fraction of atmospheric columns with total hyd...
16 optical_depth od 1 time scene (all sky); mid-visible, all hydrometeors
17 optical_depth_of_liquid_cloud odlc 1 time as for optical_depth but cloud droplets only
18 precipitation_flux_at_surface pr kg m-2 s-1 time liquid and ice phase, all hydrometeors
19 precipitation_flux_at_surface_in_ice_phase pri kg m-2 s-1 time ice phase hydrometeors only
20 toa_outgoing_longwave_flux rlut W m-2 time at top of atmosphere
21 surface_downwelling_longwave_flux rlds W m-2 time
22 surface_upwelling_longwave_flux rlus W m-2 time
23 surface_sea_spray_number_flux ssaf m-2 s-1 time when using prognostic aerosol; emission only (...
24 air_pressure pa Pa time, height
25 eastward_wind ua m s-1 time, height
26 northward_wind va m s-1 time, height
27 air_dry_density rhoa kg m-3 time, height
28 air_temperature ta K time, height
29 water_vapor_mixing_ratio qv kg kg-1 time, height per kg dry air
30 relative_humidity hur 1 time, height relative to liquid
31 relative_humidity_over_ice huri 1 time, height relative to ice
32 air_potential_temperature theta K time, height
33 specific_turbulent_kinetic_energy_resolved tke_res m2 s-2 time, height resolved only
34 specific_turbulent_kinetic_energy_sgs tke_sgs m2 s-2 time, height SGS only
35 mass_mixing_ratio_of_cloud_liquid_water_in_air qlc kg kg-1 time, height scene (all sky) per kg dry air; default breakd...
36 mass_mixing_ratio_of_rain_water_in_air qlr kg kg-1 time, height
37 mass_mixing_ratio_of_cloud_ice_in_air qic kg kg-1 time, height default breakdown to cloud_ice, snow and graup...
38 mass_mixing_ratio_of_snow_in_air qis kg kg-1 time, height
39 mass_mixing_ratio_of_graupel_in_air qig kg kg-1 time, height
40 number_of_liquid_cloud_droplets_in_air nlc kg-1 time, height scene (all sky) per kg dry air; default breakd...
41 number_of_rain_drops_in_air nlr kg-1 time, height
42 number_of_cloud_ice_crystals_in_air nic kg-1 time, height default breakdown to cloud_ice, snow and graup...
43 number_of_snow_crystals_in_air nis kg-1 time, height
44 number_of_graupel_crystals_in_air nig kg-1 time, height
45 number_of_total_aerosol_mode1 na1 kg-1 time, height when using prognostic aerosol; scene (all sky)...
46 number_of_total_aerosol_mode2 na2 kg-1 time, height accumulation mode
47 number_of_total_aerosol_mode3 na3 kg-1 time, height sea spray mode
48 number_of_liquid_cloud_droplets_in_cloud nlcic kg-1 time, height per kg dry air where cloud water > 0.01 g/kg; ...
49 number_of_ice_crystals_in_cloud niic kg-1 time, height total ice hydrometeors per kg dry air where cl...
50 disspation_rate_of_turbulent_kinetic_energy eps m2 s-3 time, height total (including numerical diffusion contribut...
51 zonal_momentum_flux uw m2 s-2 time, height total (resolved plus SGS)
52 meridional_momentum_flux vw m2 s-2 time, height total (resolved plus SGS)
53 variance_of_upward_air_velocity w2 m2 s-2 time, height total (resolved plus SGS)
54 vertical_flux_potential_temperature wth K m s-1 time, height total (resolved plus SGS)
55 vertical_flux_liquid_ice_water_potential_tempe... vf_thli K m s-1 time, height total (resolved plus SGS); include sedimentati...
56 vertical_flux_water_vapor wqv kg kg-1 m s-1 time, height total (resolved plus SGS)
57 vertical_flux_total_water vf_qt kg kg-1 m s-1 time, height total (resolved plus SGS); vapor+all liquid+al...
58 area_fraction_of_liquid_cloud flc 1 time, height fraction of cells with cloud water threshold o...
59 precipitation_flux_in_air prf kg m-2 s-1 time, height liquid and ice phase, all hydrometeors
60 precipitation_flux_in_air_in_ice_phase prfi kg m-2 s-1 time, height
61 downwelling_longwave_flux_in_air rld W m-2 time, height
62 upwelling_longwave_flux_in_air rlu W m-2 time, height
63 tendency_of_air_potential_temperature_due_to_r... dth_rad K s-1 time, height
64 tendency_of_air_potential_temperature_due_to_m... dth_micro K s-1 time, height including net condensation and precipitation
65 tendency_of_air_potential_temperature_due_to_m... dth_turb K s-1 time, height including surface fluxes
66 tendency_of_water_vapor_mixing_ratio_due_to_mi... dq_micro kg kg-1 s-1 time, height including net condensation and precipitation
67 tendency_of_water_vapor_mixing_ratio_due_to_mi... dq_turb kg kg-1 s-1 time, height including surface fluxes
68 tendency_of_aerosol_number_due_to_warm_microph... dna_micro_warm kg-1 s-1 time, height activated and unactivated aerosol (sum over al...
69 tendency_of_aerosol_number_due_to_cold_microph... dna_micro_cold kg-1 s-1 time, height activated and unactivated aerosol (sum over al...
70 tendency_of_aerosol_number_due_to_mixing dna_turb kg-1 s-1 time, height activated and unactivated aerosol (sum over al...
71 tendency_of_ice_number_due_to_heterogeneous_fr... dni_het kg-1 s-1 time, height sum of primary ice nucleation due to activatio...
72 tendency_of_ice_number_due_to_secondary_ice_pr... dni_sip kg-1 s-1 time, height sum of secondary ice formation processes (e.g....
73 tendency_of_ice_number_due_to_homogeneous_free... dni_hom kg-1 s-1 time, height ice nucleation source due to homogoeneous free...

Match WRF variables to requested outputs#

Expand the table to include columns that indicate WRF model variable names and any conversion factor.

# drop comments
vars_mean_list = vars_mean_list.drop(vars_mean_list.filter(regex='comment').columns, axis=1)

# add columns to contain model output name and units conversion factors
vars_mean_list = vars_mean_list.assign(model_name='missing data',conv_factor=1.0)
# identify requested variables with only time dimension
vars_mean_scas = vars_mean_list[vars_mean_list['dimensions']=='time']

# match to WRF variable names and specify conversion factors
for index in vars_mean_scas.index:
    standard_name = vars_mean_list.standard_name.iat[index]
    if standard_name=='surface_pressure': 
        vars_mean_list.model_name.iat[index] = 'CST_PS'
    if standard_name=='surface_temperature': 
        vars_mean_list.model_name.iat[index] = 'CST_TSK'
    if standard_name=='surface_friction_velocity': 
        vars_mean_list.model_name.iat[index] = 'CST_UST'
    if standard_name=='surface_roughness_length_for_momentum_in_air': 
        vars_mean_list.model_name.iat[index] = 'CST_ZNT'
    if standard_name=='surface_roughness_length_for_heat_in_air': 
        vars_mean_list.model_name.iat[index] = 'CST_Z0T'
    if standard_name=='surface_roughness_length_for_humidity_in_air': 
        vars_mean_list.model_name.iat[index] = 'CST_Z0Q'
    if standard_name=='surface_upward_sensible_heat_flux': 
        vars_mean_list.model_name.iat[index] = 'CST_SH'
    if standard_name=='surface_upward_latent_heat_flux': 
        vars_mean_list.model_name.iat[index] = 'CST_LH'
    if standard_name=='obukhov_length': 
        vars_mean_list.model_name.iat[index] = 'CST_MOL'
    if standard_name=='atmosphere_mass_content_of_liquid_cloud_water': 
        vars_mean_list.model_name.iat[index] = 'CST_CLWP'
    if standard_name=='atmosphere_mass_content_of_rain_water': 
        vars_mean_list.model_name.iat[index] = 'CST_RWP'
    if standard_name=='atmosphere_mass_content_of_ice_water': 
        vars_mean_list.model_name.iat[index] = 'CST_FWP'
    if standard_name=='cloud_area_fraction': 
        vars_mean_list.model_name.iat[index] = 'CST_CLDTOT2'
    if standard_name=='optical_depth': 
        vars_mean_list.model_name.iat[index] = 'CST_OPD'
    if standard_name=='optical_depth_of_liquid_cloud': 
        vars_mean_list.model_name.iat[index] = 'CST_OPDC'
    if standard_name=='precipitation_flux_at_surface':
        vars_mean_list.model_name.iat[index] = 'CST_PRECT'
    if do_ice:
        if standard_name=='precipitation_flux_at_surface_in_ice_phase': 
            vars_mean_list.model_name.iat[index] = 'CST_PRECI'
    if standard_name=='toa_outgoing_longwave_flux': 
        vars_mean_list.model_name.iat[index] = 'CST_FLNT'
    if standard_name=='surface_downwelling_longwave_flux':
        vars_mean_list.model_name.iat[index] = 'CST_RLDS'
    if standard_name=='surface_upwelling_longwave_flux':
        vars_mean_list.model_name.iat[index] = 'CST_FLNS'
# identify requested variables with time and vertical dimensions
vars_mean_snds = vars_mean_list[vars_mean_list['dimensions']=='time, height']

for index in vars_mean_snds.index:
    standard_name = vars_mean_list.standard_name.iat[index]
    if standard_name=='air_pressure': 
        vars_mean_list.model_name.iat[index] = 'CSP_P'
    if standard_name=='eastward_wind': 
        vars_mean_list.model_name.iat[index] = 'CSP_U'
    if standard_name=='northward_wind': 
        vars_mean_list.model_name.iat[index] = 'CSP_V'
    if standard_name=='air_dry_density': 
        vars_mean_list.model_name.iat[index] = 'CSP_RHO'
    if standard_name=='air_temperature': 
        vars_mean_list.model_name.iat[index] = 'CSP_T'
    if standard_name=='water_vapor_mixing_ratio': 
        vars_mean_list.model_name.iat[index] = 'CSP_QV'
    if standard_name=='relative_humidity': 
        vars_mean_list.model_name.iat[index] = 'CSP_RH'
        vars_mean_list.conv_factor.iat[index] = 1/100.
    if standard_name=='relative_humidity_over_ice': 
        vars_mean_list.model_name.iat[index] = 'CSP_RHI'
        vars_mean_list.conv_factor.iat[index] = 1/100.
    if standard_name=='air_potential_temperature': 
        vars_mean_list.model_name.iat[index] = 'CSP_TH'
    if standard_name=='specific_turbulent_kinetic_energy_resolved': 
        vars_mean_list.model_name.iat[index] = 'CSP_TKE_RS'
    if standard_name=='specific_turbulent_kinetic_energy_sgs': 
        vars_mean_list.model_name.iat[index] = 'CSP_TKE_SGS'
    if standard_name=='mass_mixing_ratio_of_cloud_liquid_water_in_air': 
        vars_mean_list.model_name.iat[index] = 'CSP_QC'
    if standard_name=='mass_mixing_ratio_of_rain_water_in_air': 
        vars_mean_list.model_name.iat[index] = 'CSP_QR'
    if do_ice:
        if standard_name=='mass_mixing_ratio_of_cloud_ice_in_air': 
            vars_mean_list.model_name.iat[index] = 'CSP_QI'
        if standard_name=='mass_mixing_ratio_of_snow_in_air': 
            vars_mean_list.model_name.iat[index] = 'CSP_QS'
        if standard_name=='mass_mixing_ratio_of_graupel_in_air':
            vars_mean_list.model_name.iat[index] = 'CSP_QG'
    if standard_name=='number_of_liquid_cloud_droplets_in_air':
        vars_mean_list.model_name.iat[index] = 'CSP_QNC_FILTER'
    if standard_name=='number_of_rain_drops_in_air':
        vars_mean_list.model_name.iat[index] = 'CSP_QNR'
    if do_ice:
        if standard_name=='number_of_cloud_ice_crystals_in_air':
            vars_mean_list.model_name.iat[index] = 'CSP_QNI'
        if standard_name=='number_of_snow_crystals_in_air':
            vars_mean_list.model_name.iat[index] = 'CSP_QNS'
        if standard_name=='number_of_graupel_crystals_in_air':
            vars_mean_list.model_name.iat[index] = 'CSP_QNG'
    if do_progNa:
        if standard_name=='number_of_total_aerosol_mode1':
            vars_mean_list.model_name.iat[index] = 'na_1'
        if standard_name=='number_of_total_aerosol_mode2':
            vars_mean_list.model_name.iat[index] = 'na_2'
        if standard_name=='number_of_total_aerosol_mode3':
            vars_mean_list.model_name.iat[index] = 'na_3'     
    
    if standard_name=='number_of_liquid_cloud_droplets_in_cloud': 
        vars_mean_list.model_name.iat[index] = 'CSP_QNC_C'
    if standard_name=='number_of_ice_crystals_in_cloud': 
        vars_mean_list.model_name.iat[index] = 'CSP_QNI_C'
    if standard_name=='disspation_rate_of_turbulent_kinetic_energy': 
        vars_mean_list.model_name.iat[index] = 'CSP_TKE_DI'
    
    if standard_name=='zonal_momentum_flux': 
        vars_mean_list.model_name.iat[index] = 'CSP_UW'
    if standard_name=='meridional_momentum_flux': 
        vars_mean_list.model_name.iat[index] = 'CSP_VW'
    if standard_name=='variance_of_upward_air_velocity': 
        vars_mean_list.model_name.iat[index] = 'CSP_W2_MASS'
    if standard_name=='vertical_flux_potential_temperature': 
        vars_mean_list.model_name.iat[index] = 'CSP_WTH'
    if standard_name=='vertical_flux_liquid_ice_water_potential_temperature': 
        vars_mean_list.model_name.iat[index] = 'CSP_WTHLI'
    if standard_name=='vertical_flux_water_vapor': 
        vars_mean_list.model_name.iat[index] = 'CSP_WQV'
    if standard_name=='vertical_flux_total_water': 
        vars_mean_list.model_name.iat[index] = 'CSP_WQT'
    if standard_name=='area_fraction_of_liquid_cloud': 
        vars_mean_list.model_name.iat[index] = 'CSP_A_CL'
    if standard_name=='precipitation_flux_in_air': 
        vars_mean_list.model_name.iat[index] = 'CSP_SEDFQT'
    if standard_name=='precipitation_flux_in_air_in_ice_phase': 
        vars_mean_list.model_name.iat[index] = 'CSP_SEDFQF'
    #if standard_name=='downwelling_longwave_flux_in_air': 
    #    vars_mean_list.model_name.iat[index] = 'LWdn'
    #if standard_name=='upwelling_longwave_flux_in_air': 
    #    vars_mean_list.model_name.iat[index] = 'LWup'
    if standard_name=='tendency_of_air_potential_temperature_due_to_radiative_heating': 
        vars_mean_list.model_name.iat[index] = 'CSP_THDT_LW'
    if standard_name=='tendency_of_air_potential_temperature_due_to_microphysics': 
        vars_mean_list.model_name.iat[index] = 'CSP_THDT_COND_FILTER'
    if standard_name=='tendency_of_air_potential_temperature_due_to_mixing': 
        vars_mean_list.model_name.iat[index] = 'CSP_THDT_TURB'
    if standard_name=='tendency_of_water_vapor_mixing_ratio_due_to_microphysics': 
        vars_mean_list.model_name.iat[index] = 'CSP_QVDT_COND'
    if standard_name=='tendency_of_water_vapor_mixing_ratio_due_to_mixing': 
        vars_mean_list.model_name.iat[index] = 'CSP_QVDT_TURB'

Sanity check#

vars_mean_list[3:] # echo variables (first three rows are dimensions)
standard_name variable_id units dimensions model_name conv_factor
3 surface_pressure ps Pa time CST_PS 1.00
4 surface_temperature ts K time CST_TSK 1.00
5 surface_friction_velocity ustar m s-1 time CST_UST 1.00
6 surface_roughness_length_for_momentum_in_air z0 m time CST_ZNT 1.00
7 surface_roughness_length_for_heat_in_air z0h m time CST_Z0T 1.00
8 surface_roughness_length_for_humidity_in_air z0q m time CST_Z0Q 1.00
9 surface_upward_sensible_heat_flux hfss W m-2 time CST_SH 1.00
10 surface_upward_latent_heat_flux hfls W m-2 time CST_LH 1.00
11 obukhov_length ol m time CST_MOL 1.00
12 atmosphere_mass_content_of_liquid_cloud_water lwpc kg m-2 time CST_CLWP 1.00
13 atmosphere_mass_content_of_rain_water lwpr kg m-2 time CST_RWP 1.00
14 atmosphere_mass_content_of_ice_water iwp kg m-2 time CST_FWP 1.00
15 cloud_area_fraction clt 1 time CST_CLDTOT2 1.00
16 optical_depth od 1 time CST_OPD 1.00
17 optical_depth_of_liquid_cloud odlc 1 time CST_OPDC 1.00
18 precipitation_flux_at_surface pr kg m-2 s-1 time CST_PRECT 1.00
19 precipitation_flux_at_surface_in_ice_phase pri kg m-2 s-1 time CST_PRECI 1.00
20 toa_outgoing_longwave_flux rlut W m-2 time CST_FLNT 1.00
21 surface_downwelling_longwave_flux rlds W m-2 time CST_RLDS 1.00
22 surface_upwelling_longwave_flux rlus W m-2 time CST_FLNS 1.00
23 surface_sea_spray_number_flux ssaf m-2 s-1 time missing data 1.00
24 air_pressure pa Pa time, height CSP_P 1.00
25 eastward_wind ua m s-1 time, height CSP_U 1.00
26 northward_wind va m s-1 time, height CSP_V 1.00
27 air_dry_density rhoa kg m-3 time, height CSP_RHO 1.00
28 air_temperature ta K time, height CSP_T 1.00
29 water_vapor_mixing_ratio qv kg kg-1 time, height CSP_QV 1.00
30 relative_humidity hur 1 time, height CSP_RH 0.01
31 relative_humidity_over_ice huri 1 time, height CSP_RHI 0.01
32 air_potential_temperature theta K time, height CSP_TH 1.00
33 specific_turbulent_kinetic_energy_resolved tke_res m2 s-2 time, height CSP_TKE_RS 1.00
34 specific_turbulent_kinetic_energy_sgs tke_sgs m2 s-2 time, height CSP_TKE_SGS 1.00
35 mass_mixing_ratio_of_cloud_liquid_water_in_air qlc kg kg-1 time, height CSP_QC 1.00
36 mass_mixing_ratio_of_rain_water_in_air qlr kg kg-1 time, height CSP_QR 1.00
37 mass_mixing_ratio_of_cloud_ice_in_air qic kg kg-1 time, height CSP_QI 1.00
38 mass_mixing_ratio_of_snow_in_air qis kg kg-1 time, height CSP_QS 1.00
39 mass_mixing_ratio_of_graupel_in_air qig kg kg-1 time, height CSP_QG 1.00
40 number_of_liquid_cloud_droplets_in_air nlc kg-1 time, height CSP_QNC_FILTER 1.00
41 number_of_rain_drops_in_air nlr kg-1 time, height CSP_QNR 1.00
42 number_of_cloud_ice_crystals_in_air nic kg-1 time, height CSP_QNI 1.00
43 number_of_snow_crystals_in_air nis kg-1 time, height CSP_QNS 1.00
44 number_of_graupel_crystals_in_air nig kg-1 time, height CSP_QNG 1.00
45 number_of_total_aerosol_mode1 na1 kg-1 time, height missing data 1.00
46 number_of_total_aerosol_mode2 na2 kg-1 time, height missing data 1.00
47 number_of_total_aerosol_mode3 na3 kg-1 time, height missing data 1.00
48 number_of_liquid_cloud_droplets_in_cloud nlcic kg-1 time, height CSP_QNC_C 1.00
49 number_of_ice_crystals_in_cloud niic kg-1 time, height CSP_QNI_C 1.00
50 disspation_rate_of_turbulent_kinetic_energy eps m2 s-3 time, height CSP_TKE_DI 1.00
51 zonal_momentum_flux uw m2 s-2 time, height CSP_UW 1.00
52 meridional_momentum_flux vw m2 s-2 time, height CSP_VW 1.00
53 variance_of_upward_air_velocity w2 m2 s-2 time, height CSP_W2_MASS 1.00
54 vertical_flux_potential_temperature wth K m s-1 time, height CSP_WTH 1.00
55 vertical_flux_liquid_ice_water_potential_tempe... vf_thli K m s-1 time, height CSP_WTHLI 1.00
56 vertical_flux_water_vapor wqv kg kg-1 m s-1 time, height CSP_WQV 1.00
57 vertical_flux_total_water vf_qt kg kg-1 m s-1 time, height CSP_WQT 1.00
58 area_fraction_of_liquid_cloud flc 1 time, height CSP_A_CL 1.00
59 precipitation_flux_in_air prf kg m-2 s-1 time, height CSP_SEDFQT 1.00
60 precipitation_flux_in_air_in_ice_phase prfi kg m-2 s-1 time, height CSP_SEDFQF 1.00
61 downwelling_longwave_flux_in_air rld W m-2 time, height missing data 1.00
62 upwelling_longwave_flux_in_air rlu W m-2 time, height missing data 1.00
63 tendency_of_air_potential_temperature_due_to_r... dth_rad K s-1 time, height CSP_THDT_LW 1.00
64 tendency_of_air_potential_temperature_due_to_m... dth_micro K s-1 time, height CSP_THDT_COND_FILTER 1.00
65 tendency_of_air_potential_temperature_due_to_m... dth_turb K s-1 time, height CSP_THDT_TURB 1.00
66 tendency_of_water_vapor_mixing_ratio_due_to_mi... dq_micro kg kg-1 s-1 time, height CSP_QVDT_COND 1.00
67 tendency_of_water_vapor_mixing_ratio_due_to_mi... dq_turb kg kg-1 s-1 time, height CSP_QVDT_TURB 1.00
68 tendency_of_aerosol_number_due_to_warm_microph... dna_micro_warm kg-1 s-1 time, height missing data 1.00
69 tendency_of_aerosol_number_due_to_cold_microph... dna_micro_cold kg-1 s-1 time, height missing data 1.00
70 tendency_of_aerosol_number_due_to_mixing dna_turb kg-1 s-1 time, height missing data 1.00
71 tendency_of_ice_number_due_to_heterogeneous_fr... dni_het kg-1 s-1 time, height missing data 1.00
72 tendency_of_ice_number_due_to_secondary_ice_pr... dni_sip kg-1 s-1 time, height missing data 1.00
73 tendency_of_ice_number_due_to_homogeneous_free... dni_hom kg-1 s-1 time, height missing data 1.00

Create DEPHY output file#

Write a single file to contain all domain-mean scalar and profile outputs. This code expects the write directory to be pre-existing (already created by the user). In the case that this output will be committed to the comble-mip GitHub repository, see above “Specify directory locations”.

# create WRF output file
if os.path.exists(my_savedir + dephy_filename):
    os.remove(my_savedir + dephy_filename)
    print('The file ' + dephy_filename + ' has been deleted successfully')    
dephy_file = Dataset(my_savedir + dephy_filename,mode='w',format='NETCDF3_CLASSIC')

# create global attributes
dephy_file.title='WRF LES results for COMBLE-MIP case: fixed Nd and Ni'
dephy_file.reference='https://github.com/ARM-Development/comble-mip'
dephy_file.authors='Tim Juliano (tjuliano@ucar.edu)'
#dephy_file.source=input_filename
dephy_file.version=dt.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
dephy_file.format_version='DEPHY SCM format version 1.6'
dephy_file.script='convert_WRF_LES_output_to_dephy_format.ipynb'
dephy_file.startDate='2020-03-12T22:00:00Z'
dephy_file.force_geo=1
dephy_file.surfaceType='ocean (after spin-up)'
dephy_file.surfaceForcing='ts (after spin-up)'
dephy_file.lat=str(wrf_lat) + ' deg N'
dephy_file.dx=str(wrf_dx) + ' m'
dephy_file.dy=str(wrf_dy) + ' m'
dephy_file.dz='see ze variable'
dephy_file.nx=str(wrf_nx)
dephy_file.ny=str(wrf_ny)
dephy_file.nz=str(wrf_nz)

# create dimensions

nz = wrf_nz
zf = dephy_file.createDimension('zf', nz)
zf = dephy_file.createVariable('zf', np.float64, ('zf',))
zf.units = 'm'
zf.long_name = 'height'
zf[:] = zm_grid

ze = dephy_file.createDimension('ze', nz+1)
ze = dephy_file.createVariable('ze', np.float64, ('ze',))
ze.units = 'm'
ze.long_name = 'layer_top_height'
ze[:] = zw_grid

nt = wrf_scas.dims['Time']
time = dephy_file.createDimension('time', nt)
time = dephy_file.createVariable('time', np.float64, ('time',))
time.units = 'seconds since ' + dephy_file.startDate
time.long_name = 'time'
time[:] = delt*wrf_scas['Time'].data

# create and fill variables

for index in vars_mean_list.index[2:]:
    std_name = vars_mean_list.standard_name.iat[index]
    var_name = vars_mean_list.variable_id.iat[index]
    mod_name = vars_mean_list.model_name.iat[index]
    c_factor = vars_mean_list.conv_factor.iat[index]
    if vars_mean_list.dimensions.iat[index]=='time':
        new_sca = dephy_file.createVariable(var_name, np.float64, ('time'))
        new_sca.units = vars_mean_list.units.iat[index]
        new_sca.long_name = std_name
        if vars_mean_list.model_name.iat[index]!='missing data':
            new_sca[:] = wrf_scas[mod_name].data*c_factor
    if vars_mean_list.dimensions.iat[index]=='time, height':
        new_snd = dephy_file.createVariable(var_name, np.float64, ('time','zf'))
        new_snd.units = vars_mean_list.units.iat[index]
        new_snd.long_name = std_name
        if vars_mean_list.model_name.iat[index]!='missing data': 
            new_snd[:] = wrf_snds[mod_name].data*c_factor
            
print(dephy_file)
dephy_file.close()
The file WRF_Lx25_dx100_FixN.nc has been deleted successfully
<class 'netCDF4._netCDF4.Dataset'>
root group (NETCDF3_CLASSIC data model, file format NETCDF3):
    title: WRF LES results for COMBLE-MIP case: fixed Nd and Ni
    reference: https://github.com/ARM-Development/comble-mip
    authors: Tim Juliano (tjuliano@ucar.edu)
    version: 2023-12-01 22:29:43
    format_version: DEPHY SCM format version 1.6
    script: convert_WRF_LES_output_to_dephy_format.ipynb
    startDate: 2020-03-12T22:00:00Z
    force_geo: 1
    surfaceType: ocean (after spin-up)
    surfaceForcing: ts (after spin-up)
    lat: 74.0 deg N
    dx: 100.0 m
    dy: 100.0 m
    dz: see ze variable
    nx: 256
    ny: 256
    nz: 159
    dimensions(sizes): zf(159), ze(160), time(121)
    variables(dimensions): float64 zf(zf), float64 ze(ze), float64 time(time), float64 ps(time), float64 ts(time), float64 ustar(time), float64 z0(time), float64 z0h(time), float64 z0q(time), float64 hfss(time), float64 hfls(time), float64 ol(time), float64 lwpc(time), float64 lwpr(time), float64 iwp(time), float64 clt(time), float64 od(time), float64 odlc(time), float64 pr(time), float64 pri(time), float64 rlut(time), float64 rlds(time), float64 rlus(time), float64 ssaf(time), float64 pa(time, zf), float64 ua(time, zf), float64 va(time, zf), float64 rhoa(time, zf), float64 ta(time, zf), float64 qv(time, zf), float64 hur(time, zf), float64 huri(time, zf), float64 theta(time, zf), float64 tke_res(time, zf), float64 tke_sgs(time, zf), float64 qlc(time, zf), float64 qlr(time, zf), float64 qic(time, zf), float64 qis(time, zf), float64 qig(time, zf), float64 nlc(time, zf), float64 nlr(time, zf), float64 nic(time, zf), float64 nis(time, zf), float64 nig(time, zf), float64 na1(time, zf), float64 na2(time, zf), float64 na3(time, zf), float64 nlcic(time, zf), float64 niic(time, zf), float64 eps(time, zf), float64 uw(time, zf), float64 vw(time, zf), float64 w2(time, zf), float64 wth(time, zf), float64 vf_thli(time, zf), float64 wqv(time, zf), float64 vf_qt(time, zf), float64 flc(time, zf), float64 prf(time, zf), float64 prfi(time, zf), float64 rld(time, zf), float64 rlu(time, zf), float64 dth_rad(time, zf), float64 dth_micro(time, zf), float64 dth_turb(time, zf), float64 dq_micro(time, zf), float64 dq_turb(time, zf), float64 dna_micro_warm(time, zf), float64 dna_micro_cold(time, zf), float64 dna_turb(time, zf), float64 dni_het(time, zf), float64 dni_sip(time, zf), float64 dni_hom(time, zf)
    groups: 

Check output file#

dephy_check = xr.open_dataset(my_savedir + dephy_filename, decode_times=False)
dephy_check
<xarray.Dataset>
Dimensions:         (zf: 159, ze: 160, time: 121)
Coordinates:
  * zf              (zf) float64 10.0 32.5 60.0 ... 6.85e+03 6.92e+03 6.975e+03
  * ze              (ze) float64 0.0 20.0 45.0 75.0 ... 6.89e+03 6.95e+03 7e+03
  * time            (time) float64 0.0 600.0 1.2e+03 ... 7.14e+04 7.2e+04
Data variables: (12/71)
    ps              (time) float64 ...
    ts              (time) float64 ...
    ustar           (time) float64 ...
    z0              (time) float64 ...
    z0h             (time) float64 ...
    z0q             (time) float64 ...
    ...              ...
    dna_micro_warm  (time, zf) float64 ...
    dna_micro_cold  (time, zf) float64 ...
    dna_turb        (time, zf) float64 ...
    dni_het         (time, zf) float64 ...
    dni_sip         (time, zf) float64 ...
    dni_hom         (time, zf) float64 ...
Attributes: (12/17)
    title:           WRF LES results for COMBLE-MIP case: fixed Nd and Ni
    reference:       https://github.com/ARM-Development/comble-mip
    authors:         Tim Juliano (tjuliano@ucar.edu)
    version:         2023-12-01 22:29:43
    format_version:  DEPHY SCM format version 1.6
    script:          convert_WRF_LES_output_to_dephy_format.ipynb
    ...              ...
    dx:              100.0 m
    dy:              100.0 m
    dz:              see ze variable
    nx:              256
    ny:              256
    nz:              159