|
| 1 | +#!/bin/bash |
| 2 | + |
| 3 | +#=============================================================================== |
| 4 | +# E3SM Atmospheric River (AR) Detection and Analysis Script |
| 5 | +#=============================================================================== |
| 6 | +# |
| 7 | +# Purpose: Post-process E3SM 6-hourly (h2) instantaneous output to detect |
| 8 | +# atmospheric rivers while filtering out tropical cyclones |
| 9 | +# |
| 10 | +# Requirements: |
| 11 | +# - TempestRemap and TempestExtremes (available in e3sm-unified v1.5.0+) |
| 12 | +# - E3SM h2 (6-hourly) output files with TUQ/TVQ variables |
| 13 | +# |
| 14 | +# Usage: bash postprocessing_E3SM_data_for_AR_analysis.sh |
| 15 | +# |
| 16 | +# Author: Jill Zhang, |
| 17 | +# Based on Paul Ullrich et al. 2021: TempestExtremes v2.1: a community framework for feature detection, tracking, and analysis in large datasets |
| 18 | +# Date: July 2025 |
| 19 | +# Version: 1.0 |
| 20 | +#=============================================================================== |
| 21 | + |
| 22 | +#=============================================================================== |
| 23 | +# CONFIGURATION SECTION |
| 24 | +#=============================================================================== |
| 25 | + |
| 26 | +# Load E3SM unified environment |
| 27 | +# Uncomment the appropriate line for your system: |
| 28 | +# source /global/common/software/e3sm/anaconda_envs/load_latest_e3sm_unified_pm-cpu.sh # Perlmutter |
| 29 | +source /lcrc/soft/climate/e3sm-unified/load_latest_e3sm_unified_chrysalis.sh # LCRC Chrysalis |
| 30 | + |
| 31 | +# Simulation parameters |
| 32 | +start="1850" # Start year |
| 33 | +end="1850" # End year |
| 34 | +caseid="v3.LR.historical_0051" # Case ID |
| 35 | +atm_name="eam" # Atmosphere component name (eam/cam) |
| 36 | + |
| 37 | +# Grid configuration |
| 38 | +res=30 # Grid resolution (30 for ne30, 120 for ne120) |
| 39 | +pg2=true # Use pg2 grids (true for v2/v3, false for v1) |
| 40 | + |
| 41 | +# Directory paths |
| 42 | +drc_in="/lcrc/group/e3sm/ac.forsyth2/E3SMv3/${caseid}/${caseid}/archive/atm/hist" |
| 43 | +result_dir="/lcrc/group/e3sm/ac.zhang40/tests/ar_analysis/ar-${caseid}.${start}_${end}/" |
| 44 | + |
| 45 | +# Derived variables |
| 46 | +file_name="${caseid}_${start}_${end}" |
| 47 | + |
| 48 | +echo "==============================================================================" |
| 49 | +echo "E3SM Atmospheric River Detection Script" |
| 50 | +echo "==============================================================================" |
| 51 | +echo "Case ID: ${caseid}" |
| 52 | +echo "Time period: ${start} - ${end}" |
| 53 | +echo "Grid resolution: ne${res}" |
| 54 | +echo "Input directory: ${drc_in}" |
| 55 | +echo "Output directory: ${result_dir}" |
| 56 | +echo "==============================================================================" |
| 57 | + |
| 58 | +#=============================================================================== |
| 59 | +# SETUP AND INITIALIZATION |
| 60 | +#=============================================================================== |
| 61 | + |
| 62 | +# Create output directory structure |
| 63 | +echo "Setting up output directories..." |
| 64 | +mkdir -p "${result_dir}" |
| 65 | +mkdir -p "${result_dir}ARtag_nofilt" # Unfiltered AR detections |
| 66 | +mkdir -p "${result_dir}ARtag_filt" # TC-filtered AR detections |
| 67 | + |
| 68 | +#=============================================================================== |
| 69 | +# GRID GENERATION |
| 70 | +#=============================================================================== |
| 71 | + |
| 72 | +echo "Generating grid and connectivity files..." |
| 73 | + |
| 74 | +# Generate appropriate mesh files based on grid type |
| 75 | +if ${pg2}; then |
| 76 | + echo " Using pg2 grids (E3SM v2/v3)..." |
| 77 | + GenerateCSMesh \ |
| 78 | + --res ${res} \ |
| 79 | + --alt \ |
| 80 | + --file "${result_dir}outCSMeshne${res}.g" |
| 81 | + |
| 82 | + GenerateVolumetricMesh \ |
| 83 | + --in "${result_dir}outCSMeshne${res}.g" \ |
| 84 | + --out "${result_dir}outCSne${res}.g" \ |
| 85 | + --np 2 \ |
| 86 | + --uniform |
| 87 | + |
| 88 | + out_type="FV" |
| 89 | +else |
| 90 | + echo " Using np4 grids (E3SM v1)..." |
| 91 | + GenerateCSMesh \ |
| 92 | + --res ${res} \ |
| 93 | + --alt \ |
| 94 | + --file "${result_dir}outCSne${res}.g" |
| 95 | + |
| 96 | + out_type="CGLL" |
| 97 | +fi |
| 98 | + |
| 99 | +# Generate connectivity file |
| 100 | +echo " Grid type: ${out_type}" |
| 101 | +GenerateConnectivityFile \ |
| 102 | + --in_mesh "${result_dir}outCSne${res}.g" \ |
| 103 | + --out_type ${out_type} \ |
| 104 | + --out_connect "${result_dir}connect_CSne${res}_v2.dat" |
| 105 | + |
| 106 | +#=============================================================================== |
| 107 | +# FILE LIST GENERATION |
| 108 | +#=============================================================================== |
| 109 | + |
| 110 | +echo "Generating input file lists..." |
| 111 | + |
| 112 | +# Clean up existing file lists |
| 113 | +rm -f "${result_dir}inputfile_${file_name}.txt" |
| 114 | +rm -f "${result_dir}ar_nofilt_files_out.txt" |
| 115 | +rm -f "${result_dir}ar_filt_files_out.txt" |
| 116 | + |
| 117 | +# Process input files and create systematic output filenames |
| 118 | +file_count=0 |
| 119 | +echo " Searching pattern: ${drc_in}/${caseid}.${atm_name}.h2.*{${start}..${end}}*.nc" |
| 120 | + |
| 121 | +for f in $(eval echo "${drc_in}/${caseid}.${atm_name}.h2.*{${start}..${end}}*.nc"); do |
| 122 | + if [ -f "$f" ]; then |
| 123 | + g=$(basename "$f") |
| 124 | + |
| 125 | + # Extract date portion from filename |
| 126 | + date_part="${g#${caseid}.${atm_name}.h2.}" |
| 127 | + date_part="${date_part%.nc}" |
| 128 | + |
| 129 | + # Define systematic output filenames |
| 130 | + ar_nofilt_file="${result_dir}ARtag_nofilt/${caseid}.${atm_name}.h2.${date_part}.ARtag_nofilt.nc" |
| 131 | + ar_filt_file="${result_dir}ARtag_filt/${caseid}.${atm_name}.h2.${date_part}.ARtag_filt.nc" |
| 132 | + |
| 133 | + # Append to file lists |
| 134 | + echo "$f" >> "${result_dir}inputfile_${file_name}.txt" |
| 135 | + echo "${ar_nofilt_file}" >> "${result_dir}ar_nofilt_files_out.txt" |
| 136 | + echo "${ar_filt_file}" >> "${result_dir}ar_filt_files_out.txt" |
| 137 | + |
| 138 | + ((file_count++)) |
| 139 | + fi |
| 140 | +done |
| 141 | + |
| 142 | +echo " Found ${file_count} input files" |
| 143 | + |
| 144 | +# Change to results directory |
| 145 | +cd "${result_dir}" |
| 146 | + |
| 147 | +#=============================================================================== |
| 148 | +# STEP 1: ATMOSPHERIC RIVER DETECTION (UNFILTERED) |
| 149 | +#=============================================================================== |
| 150 | + |
| 151 | +echo "Step 1: Detecting atmospheric rivers..." |
| 152 | +echo " Method: Laplacian of integrated water vapor transport (IVT)" |
| 153 | +echo " Variables: TUQ (zonal IVT), TVQ (meridional IVT)" |
| 154 | +echo " Threshold: <= -20,000" |
| 155 | +echo " Min latitude: 15°" |
| 156 | +echo " Min area: 4e5 km²" |
| 157 | + |
| 158 | +DetectBlobs \ |
| 159 | + --in_connect "${result_dir}connect_CSne${res}_v2.dat" \ |
| 160 | + --in_data_list "${result_dir}inputfile_${file_name}.txt" \ |
| 161 | + --out_list "${result_dir}ar_nofilt_files_out.txt" \ |
| 162 | + --thresholdcmd "_LAPLACIAN{8,10}(_VECMAG(TUQ,TVQ)),<=,-20000,0" \ |
| 163 | + --minabslat 15 \ |
| 164 | + --geofiltercmd "area,>=,4e5km2" |
| 165 | + |
| 166 | +echo " AR detection completed" |
| 167 | + |
| 168 | +#=============================================================================== |
| 169 | +# STEP 2: TROPICAL CYCLONE DETECTION |
| 170 | +#=============================================================================== |
| 171 | + |
| 172 | +echo "Step 2: Detecting tropical cyclones for filtering..." |
| 173 | +echo " Method: Sea level pressure minima with temperature criteria" |
| 174 | +echo " SLP decrease: 300 Pa within 4° radius" |
| 175 | +echo " Temperature decrease: 0.6 K at 200/500 hPa levels" |
| 176 | + |
| 177 | +# Resolution-dependent parameters for closed contour command |
| 178 | +if [ ${res} -eq 120 ]; then |
| 179 | + echo " Using ne120 parameters..." |
| 180 | + DetectNodes \ |
| 181 | + --verbosity 0 \ |
| 182 | + --in_connect "${result_dir}connect_CSne${res}_v2.dat" \ |
| 183 | + --closedcontourcmd "PSL,300.0,4.0,0;_AVG(T200,T500),-0.6,4,0.30" \ |
| 184 | + --mergedist 6.0 \ |
| 185 | + --searchbymin PSL \ |
| 186 | + --outputcmd "PSL,min,0;_VECMAG(UBOT,VBOT),max,2" \ |
| 187 | + --timestride 1 \ |
| 188 | + --in_data_list "${result_dir}inputfile_${file_name}.txt" \ |
| 189 | + --out "${result_dir}out.dat" |
| 190 | +elif [ ${res} -eq 30 ]; then |
| 191 | + echo " Using ne30 parameters..." |
| 192 | + DetectNodes \ |
| 193 | + --verbosity 0 \ |
| 194 | + --in_connect "${result_dir}connect_CSne${res}_v2.dat" \ |
| 195 | + --closedcontourcmd "PSL,300.0,4.0,0;_AVG(T200,T500),-0.6,4,1.0" \ |
| 196 | + --mergedist 6.0 \ |
| 197 | + --searchbymin PSL \ |
| 198 | + --outputcmd "PSL,min,0;_VECMAG(UBOT,VBOT),max,2" \ |
| 199 | + --timestride 1 \ |
| 200 | + --in_data_list "${result_dir}inputfile_${file_name}.txt" \ |
| 201 | + --out "${result_dir}out.dat" |
| 202 | +else |
| 203 | + echo " ERROR: Grid resolution ${res} not supported!" |
| 204 | + echo " Supported resolutions: 30 (ne30), 120 (ne120)" |
| 205 | + exit 1 |
| 206 | +fi |
| 207 | + |
| 208 | +# Concatenate TC detection results |
| 209 | +echo " Concatenating TC detection files..." |
| 210 | +cat "${result_dir}"out.dat0*.dat > "${result_dir}cyclones_${file_name}.txt" |
| 211 | + |
| 212 | +# Create TC tracks |
| 213 | +echo " Creating TC tracks..." |
| 214 | +echo " Max distance: 6.0°, Min duration: 6 time steps, Max gap: 1 time step" |
| 215 | +echo " Wind speed: >= 17.5 m/s, Latitude: -40° to 40°" |
| 216 | + |
| 217 | +StitchNodes \ |
| 218 | + --in_fmt "lon,lat,slp,wind" \ |
| 219 | + --in_connect "${result_dir}connect_CSne${res}_v2.dat" \ |
| 220 | + --range 6.0 \ |
| 221 | + --mintime 6 \ |
| 222 | + --maxgap 1 \ |
| 223 | + --in "${result_dir}cyclones_${file_name}.txt" \ |
| 224 | + --out "${result_dir}cyclones_stitch_${file_name}.dat" \ |
| 225 | + --threshold "wind,>=,17.5,6;lat,<=,40.0,6;lat,>=,-40.0,6" |
| 226 | + |
| 227 | +echo " TC detection and tracking completed" |
| 228 | + |
| 229 | +#=============================================================================== |
| 230 | +# STEP 3: FILTER ARs TO REMOVE TC INFLUENCE |
| 231 | +#=============================================================================== |
| 232 | + |
| 233 | +echo "Step 3: Filtering ARs to remove tropical cyclone influence..." |
| 234 | +echo " Exclusion distance: 8.0° from any TC center" |
| 235 | +echo " Method: Remove AR detections near TC tracks" |
| 236 | + |
| 237 | +NodeFileFilter \ |
| 238 | + --in_connect "${result_dir}connect_CSne${res}_v2.dat" \ |
| 239 | + --in_nodefile "${result_dir}cyclones_stitch_${file_name}.dat" \ |
| 240 | + --in_fmt "lon,lat,slp,wind" \ |
| 241 | + --in_data_list "${result_dir}ar_nofilt_files_out.txt" \ |
| 242 | + --out_data_list "${result_dir}ar_filt_files_out.txt" \ |
| 243 | + --var "binary_tag" \ |
| 244 | + --bydist 8.0 \ |
| 245 | + --invert |
| 246 | + |
| 247 | +echo " AR filtering completed" |
| 248 | + |
| 249 | +#=============================================================================== |
| 250 | +# COMPLETION |
| 251 | +#=============================================================================== |
| 252 | + |
| 253 | +echo "==============================================================================" |
| 254 | +echo "Processing completed successfully!" |
| 255 | +echo "==============================================================================" |
| 256 | +echo "Output files:" |
| 257 | +echo " Unfiltered ARs: ${result_dir}ARtag_nofilt/" |
| 258 | +echo " TC-filtered ARs: ${result_dir}ARtag_filt/" |
| 259 | +echo " TC tracks: ${result_dir}cyclones_stitch_${file_name}.dat" |
| 260 | +echo "==============================================================================" |
| 261 | + |
| 262 | +# Optional cleanup (uncomment if needed) |
| 263 | +# echo "Cleaning up intermediate files..." |
| 264 | +# rm -f "${result_dir}"out.dat0*.dat |
| 265 | +# rm -f "${result_dir}cyclones_${file_name}.txt" |
| 266 | +# rm -f "${result_dir}"*.txt |
| 267 | + |
| 268 | +echo "Script completed at $(date)" |
0 commit comments