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