Skip to content

Commit 4232d75

Browse files
authored
Merge pull request #411 from wwieder/clm-diags
Latest updates for LDF to apply in CUPiD
2 parents 5f50f17 + bb77ade commit 4232d75

11 files changed

+4769
-4088
lines changed

config_clm_unstructured_plots.yaml

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ diag_basic_info:
9999
#Uncomment and change path for custom variable defaults file
100100
defaults_file: lib/ldf_variable_defaults.yaml
101101

102+
# location of land regions YAML file (only used in regional_climatology plots)
103+
regions_file: lib/regions_lnd.yaml
104+
102105
#Longitude line on which to center all lat/lon maps.
103106
#If this config option is missing then the central
104107
#longitude will default to 180 degrees E.
@@ -123,7 +126,7 @@ diag_cam_climo:
123126
# eg. cam.h0 or ocn.pop.h.ecosys.nday1 or hist_str: [cam.h2,cam.h0]
124127
# Only affects timeseries as everything else uses the created timeseries
125128
# Default:
126-
hist_str: clm2.h0
129+
hist_str: clm2.h0a
127130

128131
#Calculate climatologies?
129132
#If false, the climatology files will not be created:
@@ -137,29 +140,29 @@ diag_cam_climo:
137140
cam_overwrite_climo: false
138141

139142
#Name of CAM case (or CAM run name):
140-
cam_case_name: b.e30_beta06.B1850C_LTso.ne30_t232_wgx3.188
143+
cam_case_name: ctsm5.4.CMIP7_ciso_ctsm5.3.075_ne30_123_HIST_popDens
141144

142145
#Case nickname
143146
#NOTE: if nickname starts with '0' - nickname must be in quotes!
144147
# ie '026a' as opposed to 026a
145148
#If missing or left blank, will default to cam_case_name
146-
case_nickname: '188'
149+
case_nickname: '123_popDens'
147150

148151
#Location of CAM history (h0) files:
149-
cam_hist_loc: /glade/derecho/scratch/gmarques/archive/${diag_cam_climo.cam_case_name}/lnd/hist/
152+
cam_hist_loc: /glade/derecho/scratch/wwieder/archive/${diag_cam_climo.cam_case_name}/lnd/hist/
150153

151154
# If unstructured_plotting, a mesh file is required!
152155
mesh_file: /glade/campaign/cesm/cesmdata/inputdata/share/meshes/ne30pg3_ESMFmesh_cdf5_c20211018.nc
153156

154157
#model year when time series files should start:
155158
#Note: Leaving this entry blank will make time series
156159
# start at earliest available year.
157-
start_year: 76
158-
160+
start_year: 1850
161+
climo_start_year: 2004
159162
#model year when time series files should end:
160163
#Note: Leaving this entry blank will make time series
161164
# end at latest available year.
162-
end_year: 95
165+
end_year: 2023
163166

164167
#Do time series files exist?
165168
#If True, then diagnostics assumes that model files are already time series.
@@ -188,7 +191,7 @@ diag_cam_baseline_climo:
188191
# eg. cam.h0 or ocn.pop.h.ecosys.nday1 or hist_str: [cam.h2,cam.h0]
189192
# Only affects timeseries as everything else uses the created timeseries
190193
# Default:
191-
hist_str: clm2.h0
194+
hist_str: clm2.h0a
192195

193196
#Calculate cam baseline climatologies?
194197
#If false, the climatology files will not be created:
@@ -199,17 +202,17 @@ diag_cam_baseline_climo:
199202
cam_overwrite_climo: false
200203

201204
#Name of CAM baseline case:
202-
cam_case_name: b.e30_beta06.B1850C_LTso.ne30_t232_wgx3.179
205+
cam_case_name: ctsm5.4_5.3.068_PPEcal115_116_HIST
203206

204207
#Baseline case nickname
205208
#NOTE: if nickname starts with '0' - nickname must be in quotes!
206209
# ie '026a' as opposed to 026a
207210
#If missing or left blank, will default to cam_case_name
208-
case_nickname: '179'
211+
case_nickname: '116'
209212

210213
#Location of CAM baseline history (h0) files:
211214
#Example test files
212-
cam_hist_loc: /glade/derecho/scratch/gmarques/archive/${diag_cam_baseline_climo.cam_case_name}/lnd/hist/
215+
cam_hist_loc: /glade/derecho/scratch/wwieder/archive/${diag_cam_baseline_climo.cam_case_name}/lnd/hist/
213216

214217
# If unstructured_plotting, a mesh file is required!
215218
mesh_file: /glade/campaign/cesm/cesmdata/inputdata/share/meshes/ne30pg3_ESMFmesh_cdf5_c20211018.nc
@@ -220,12 +223,13 @@ diag_cam_baseline_climo:
220223
#model year when time series files should start:
221224
#Note: Leaving this entry blank will make time series
222225
# start at earliest available year.
223-
start_year: 76
226+
start_year: 1850
227+
climo_start_year: 2004
224228

225229
#model year when time series files should end:
226230
#Note: Leaving this entry blank will make time series
227231
# end at latest available year.
228-
end_year: 95
232+
end_year: 2023
229233

230234
#Do time series files need to be generated?
231235
#If True, then diagnostics assumes that model files are already time series.
@@ -264,7 +268,7 @@ time_averaging_scripts:
264268
#Name of regridding scripts being used.
265269
#These scripts must be located in "scripts/regridding":
266270
regridding_scripts:
267-
# - regrid_and_vert_interp
271+
#- regrid_and_vert_interp
268272

269273
#List of analysis scripts being used.
270274
#These scripts must be located in "scripts/analysis":
@@ -283,10 +287,12 @@ plotting_scripts:
283287
#Shorter list here, for efficiency of testing
284288
diag_var_list:
285289
- TSA
290+
- TV
286291
- PREC
287292
- ELAI
288293
- FSDS
289294
- FLDS
295+
- QBOT
290296
- ASA
291297
- RNET
292298
- FSH
@@ -301,22 +307,29 @@ diag_var_list:
301307
- NEE
302308
- NPP
303309
- NBP
310+
- NPP_NUPTAKE
304311
- BTRANMN
305312
- TOTECOSYSC
306313
- TOTSOMC_1m
307314
- ALTMAX
308315
- FAREA_BURNED
309-
316+
- TWS
317+
- GRAINC_TO_FOOD
318+
#- C13_GPP_pm
319+
# - C13_TOTVEGC_pm
320+
#- C14_GPP_pm
321+
#- C14_TOTVEGC_pm
322+
310323
region_list:
311324
- Global
312-
#- N Hemisphere Land
313-
#- S Hemisphere Land
325+
- N Hemisphere Land
326+
- S Hemisphere Land
314327
- Polar
315328
- Alaskan Arctic
316329
- Canadian Arctic
317330
- Greenland
318331
- Russian Arctic
319-
#- Antarctica
332+
# - Antarctica
320333
- Alaska
321334
- Northwest Canada
322335
- Central Canada
@@ -340,7 +353,7 @@ region_list:
340353
- Indochina
341354
#- Sahara Desert
342355
#- Arabian Peninsula
343-
#- Australia
356+
- Australia
344357
#- Central Asia ## Was Broken... probably because there were two?
345358
#- Mongolia
346359
#- Tibetan Plateau

lib/adf_diag.py

Lines changed: 69 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -744,6 +744,10 @@ def call_ncrcat(cmd):
744744
# End if cam
745745
# End if has_lev
746746

747+
# Optional, add additional time varying variables to clm2.h1 files
748+
if ("clm" in hist_str) and ("h1" in hist_str):
749+
ncrcat_var_list = ncrcat_var_list + ",pfts1d_wtgcell,pfts1d_wtlunit,pfts1d_wtcol"
750+
747751
cmd = (
748752
["ncrcat", "-O", "-4", "-h", "--no_cll_mth", "-v", ncrcat_var_list]
749753
+ hist_files
@@ -764,23 +768,12 @@ def call_ncrcat(cmd):
764768
"ncatted", "-O",
765769
"-a", "adf_user,global,a,c," + f"{self.user}",
766770
"-a", "hist_file_locs,global,a,c," + f"{hist_locs_str}",
767-
"-a", "hist_file_list,global,a,c," + f"{hist_files_str}",
771+
# This list is too long and fails
772+
# "-a", "hist_file_list,global,a,c," + f"{hist_files_str}",
768773
ts_outfil_str
769774
]
770775

771-
if "clm" in hist_str:
772-
# Step 3b: Optional, add additional variables to clm2.h1 files
773-
if "h1" in hist_str:
774-
cmd_add_clm_h1_fields = [
775-
"ncrcat", "-A", "-v",
776-
"pfts1d_ixy,pfts1d_jxy,pfts1d_itype_veg,lat,lon",
777-
hist_files,
778-
ts_outfil_str
779-
]
780-
# add time varrying information to clm2.h1 fields
781-
list_of_hist_commands.append(cmd_add_clm_h1_fields)
782-
783-
# Step 3c: Create the ncatted command to remove the history attribute
776+
# Step 3c: Create the ncatted command to remove the history attribute
784777
cmd_remove_history = [
785778
"ncatted", "-O", "-h",
786779
"-a", "history,global,d,,",
@@ -858,7 +851,19 @@ def call_ncrcat(cmd):
858851
ts_ds['area'] = ds.area
859852
ts_ds['landfrac'] = ds.landfrac
860853
ts_ds['landmask'] = ds.landmask
861-
854+
# Optional, add additional variables to clm2.h1 files
855+
# Note: this is currently set up for PFT output
856+
if "h1" in hist_str:
857+
ds = xr.open_dataset(hist_files[0], decode_times=False)
858+
ts_ds['pfts1d_ixy'] = ds.pfts1d_ixy
859+
ts_ds['pfts1d_jxy'] = ds.pfts1d_jxy
860+
ts_ds['pfts1d_gi'] = ds.pfts1d_gi
861+
ts_ds['pfts1d_li'] = ds.pfts1d_li
862+
ts_ds['pfts1d_ci'] = ds.pfts1d_li
863+
ts_ds['pfts1d_itype_veg'] = ds.pfts1d_itype_veg
864+
ts_ds['pfts1d_itype_col'] = ds.pfts1d_itype_col
865+
ts_ds['pfts1d_itype_lunit'] = ds.pfts1d_itype_lunit
866+
ts_ds['pfts1d_active'] = ds.pfts1d_active
862867
ts_ds['time'] = time
863868
ts_ds.assign_coords(time=time)
864869
ts_ds_fixed = xr.decode_cf(ts_ds)
@@ -1353,6 +1358,10 @@ def derive_variables(self, res=None, hist_str=None, vars_to_derive=None, ts_dir=
13531358
# create new file name for derived variable
13541359
derived_file = constit_files[0].replace(constit_list[0], var)
13551360

1361+
clmPDB = 0.0112372 # ratio of 13C/12C in Pee Dee Belemnite (C isotope standard)
1362+
clm14C = 1e-12 # not accepted value of 1.176 x 10-12
1363+
min13C = -40. # prevent wacky values when 12C stock or fluxes are very small
1364+
min14C = -400. # arbitrary
13561365
# Check if clobber is true for file
13571366
if Path(derived_file).is_file():
13581367
if overwrite:
@@ -1370,6 +1379,51 @@ def derive_variables(self, res=None, hist_str=None, vars_to_derive=None, ts_dir=
13701379
der_val = 100*ds["FSR"]/ds["FSDS"].where(ds["FSDS"]>0)
13711380
elif var == "RNET":
13721381
der_val = ds["FSA"]-ds["FIRA"]
1382+
elif var == "WUE":
1383+
der_val = ds["GPP"]/ds["FCTR"].where(ds["FCTR"]>0)
1384+
1385+
# ----------------------------------------------------------------------------------
1386+
# Isotope-specific derived variables
1387+
# ----------------------------------------------------------------------------------
1388+
# NOTE: del13C : valid range = -40 to 0 per mil PDB
1389+
# formulas similar to Jain et al 1996 Tellus B 48B: 583-600
1390+
# as applied in land_diags /glade/campaign/cgd/tss/people/oleson/FROM_LMWG/diag/lnd_diag4.2/code/shared/lnd_func.ncl
1391+
# TODO, this would be nice to avoid repeating for all isotopes enables variables
1392+
# TODO, check for accuracy of equations, neither as as in Jain et al 1996...
1393+
# Should they just be ((ratio sample - ratio standard) / ratio standard) * 1000 ?
1394+
1395+
elif var == "C13_GPP_pm":
1396+
der_val = (((ds["C13_GPP"]/ds["GPP"].where(ds["GPP"]>0)) / clmPDB) - 1.) * 1e3
1397+
der_val = der_val.where(der_val > min13C)
1398+
1399+
elif var == "C14_GPP_pm":
1400+
der_val = (((ds["C14_GPP"]/ds["GPP"].where(ds["GPP"]>0)) / clm14C) - 1.) * 1e3
1401+
der_val = der_val.where(der_val > min14C)
1402+
1403+
elif var == "C13_NPP_pm":
1404+
der_val = (((ds["C13_NPP"]/ds["NPP"].where(ds["NPP"]>0)) / clmPDB) - 1.) * 1e3
1405+
der_val = der_val.where(der_val > min13C)
1406+
1407+
elif var == "C14_NPP_pm":
1408+
der_val = (((ds["C14_NPP"]/ds["NPP"].where(ds["NPP"]>0)) / clm14C) - 1.) * 1e3
1409+
der_val = der_val.where(der_val > min14C)
1410+
1411+
elif var == "C13_TOTVEGC_pm":
1412+
der_val = (((ds["C13_TOTVEGC"]/ds["TOTVEGC"].where(ds["TOTVEGC"]>0)) / clmPDB) - 1.) * 1e3
1413+
der_val = der_val.where(der_val > min13C)
1414+
1415+
elif var == "C14_TOTVEGC_pm":
1416+
der_val = (((ds["C14_TOTVEGC"]/ds["TOTVEGC"].where(ds["TOTVEGC"]>0)) / clm14C) - 1.) * 1e3
1417+
der_val = der_val.where(der_val > min14C)
1418+
1419+
elif var == "C13_TOTECOSYSC_pm":
1420+
der_val = (((ds["C13_TOTECOSYSC"]/ds["TOTECOSYSC"].where(ds["TOTECOSYSC"]>0)) / clmPDB) - 1.) * 1e3
1421+
der_val = der_val.where(der_val > min13C)
1422+
1423+
elif var == "C14_TOTECOSYSC_pm":
1424+
der_val = (((ds["C14_TOTECOSYSC"]/ds["TOTECOSYSC"].where(ds["TOTECOSYSC"]>0)) / clm14C) - 1.) * 1e3
1425+
#der_val = der_val.where(der_val > min14C)
1426+
13731427
else:
13741428
# Loop through all constituents and sum
13751429
der_val = 0

0 commit comments

Comments
 (0)