@@ -288,6 +288,142 @@ function Base.propertynames(model::RRTMGPModel, private::Bool = false)
288
288
return private ? (names... , fieldnames (typeof (model))... ) : names
289
289
end
290
290
291
+ """
292
+ lookup_tables(::AbstractRRTMGPMode, device, FloatType)
293
+
294
+ Return a NamedTuple, containing
295
+ - RRTMGP lookup tables (varies by radiation mode)
296
+ - nbnd_lw
297
+ - nbnd_sw
298
+ - ngas_lw (absent for GrayRadiation)
299
+ - ngas_sw (absent for GrayRadiation)
300
+
301
+ TODO:
302
+ - We should add type annotations for the data read from NC files as this will
303
+ improve inference and the return type of `lookup_tables`.
304
+ """
305
+ function lookup_tables end
306
+
307
+ lookup_tables (
308
+ radiation_mode:: GrayRadiation ,
309
+ device:: ClimaComms.AbstractDevice ,
310
+ :: Type{FT} ,
311
+ ) where {FT} = (; lookups = (;), lu_kwargs = (; nbnd_lw = 1 , nbnd_sw = 1 ))
312
+
313
+ function lookup_tables (
314
+ radiation_mode:: ClearSkyRadiation ,
315
+ device:: ClimaComms.AbstractDevice ,
316
+ :: Type{FT} ,
317
+ ) where {FT}
318
+ DA = ClimaComms. array_type (device)
319
+ # turn kwargs into a Dict, so that values can be dynamically popped from it
320
+
321
+ artifact (t, b, n) =
322
+ NC. Dataset (RRTMGP. ArtifactPaths. get_lookup_filename (t, b)) do ds
323
+ getproperty (RRTMGP. LookUpTables, n)(ds, FT, DA)
324
+ end
325
+ lookup_lw, idx_gases_lw = artifact (:gas , :lw , :LookUpLW )
326
+
327
+ nbnd_lw = RRTMGP. LookUpTables. get_n_bnd (lookup_lw)
328
+ ngas_lw = RRTMGP. LookUpTables. get_n_gases (lookup_lw)
329
+
330
+ lookup_lw_aero, idx_aerosol_lw, idx_aerosize_lw =
331
+ if radiation_mode. aerosol_radiation
332
+ artifact (:aerosol , :lw , :LookUpAerosolMerra )
333
+ else
334
+ (nothing , nothing , nothing )
335
+ end
336
+
337
+ lookup_sw, idx_gases_sw = artifact (:gas , :sw , :LookUpSW )
338
+
339
+ nbnd_sw = RRTMGP. LookUpTables. get_n_bnd (lookup_sw)
340
+ ngas_sw = RRTMGP. LookUpTables. get_n_gases (lookup_sw)
341
+
342
+ lookup_sw_aero, idx_aerosol_sw, idx_aerosize_sw =
343
+ if radiation_mode. aerosol_radiation
344
+ artifact (:aerosol , :sw , :LookUpAerosolMerra )
345
+ else
346
+ (nothing , nothing , nothing )
347
+ end
348
+
349
+ lookups = (;
350
+ idx_aerosize_lw,
351
+ idx_aerosize_sw,
352
+ idx_aerosol_lw,
353
+ idx_aerosol_sw,
354
+ idx_gases_lw,
355
+ idx_gases_sw,
356
+ lookup_lw,
357
+ lookup_lw_aero,
358
+ lookup_sw,
359
+ lookup_sw_aero,
360
+ )
361
+
362
+ @assert RRTMGP. LookUpTables. get_n_gases (lookup_lw) ==
363
+ RRTMGP. LookUpTables. get_n_gases (lookup_sw)
364
+ @assert lookup_lw. p_ref_min == lookup_sw. p_ref_min
365
+ return (; lookups, lu_kwargs = (; nbnd_lw, ngas_lw, nbnd_sw, ngas_sw))
366
+ end
367
+
368
+ function lookup_tables (
369
+ radiation_mode:: Union {
370
+ AllSkyRadiation,
371
+ AllSkyRadiationWithClearSkyDiagnostics,
372
+ },
373
+ device:: ClimaComms.AbstractDevice ,
374
+ :: Type{FT} ,
375
+ ) where {FT}
376
+ DA = ClimaComms. array_type (device)
377
+ # turn kwargs into a Dict, so that values can be dynamically popped from it
378
+
379
+ artifact (t, b, n) =
380
+ NC. Dataset (RRTMGP. ArtifactPaths. get_lookup_filename (t, b)) do ds
381
+ getproperty (RRTMGP. LookUpTables, n)(ds, FT, DA)
382
+ end
383
+ lookup_lw, idx_gases_lw = artifact (:gas , :lw , :LookUpLW )
384
+ lookup_lw_cld = artifact (:cloud , :lw , :LookUpCld )
385
+ lookup_lw_aero, idx_aerosol_lw, idx_aerosize_lw =
386
+ if radiation_mode. aerosol_radiation
387
+ artifact (:aerosol , :lw , :LookUpAerosolMerra )
388
+ else
389
+ (nothing , nothing , nothing )
390
+ end
391
+ lookup_sw, idx_gases_sw = artifact (:gas , :sw , :LookUpSW )
392
+ lookup_sw_cld = artifact (:cloud , :sw , :LookUpCld )
393
+
394
+ lookup_sw_aero, idx_aerosol_sw, idx_aerosize_sw =
395
+ if radiation_mode. aerosol_radiation
396
+ artifact (:aerosol , :sw , :LookUpAerosolMerra )
397
+ else
398
+ (nothing , nothing , nothing )
399
+ end
400
+
401
+ nbnd_lw = RRTMGP. LookUpTables. get_n_bnd (lookup_lw)
402
+ ngas_lw = RRTMGP. LookUpTables. get_n_gases (lookup_lw)
403
+ nbnd_sw = RRTMGP. LookUpTables. get_n_bnd (lookup_sw)
404
+ ngas_sw = RRTMGP. LookUpTables. get_n_gases (lookup_sw)
405
+
406
+ lookups = (;
407
+ idx_aerosize_lw,
408
+ idx_aerosize_sw,
409
+ idx_aerosol_lw,
410
+ idx_aerosol_sw,
411
+ idx_gases_lw,
412
+ idx_gases_sw,
413
+ lookup_lw,
414
+ lookup_lw_aero,
415
+ lookup_lw_cld,
416
+ lookup_sw,
417
+ lookup_sw_aero,
418
+ lookup_sw_cld,
419
+ )
420
+
421
+ @assert RRTMGP. LookUpTables. get_n_gases (lookup_lw) ==
422
+ RRTMGP. LookUpTables. get_n_gases (lookup_sw)
423
+ @assert lookup_lw. p_ref_min == lookup_sw. p_ref_min
424
+ return (; lookups, lu_kwargs = (; nbnd_lw, ngas_lw, nbnd_sw, ngas_sw))
425
+ end
426
+
291
427
"""
292
428
RRTMGPModel(params; kwargs...)
293
429
@@ -454,47 +590,12 @@ function _RRTMGPModel(
454
590
pressures/temperatures are specified" )
455
591
end
456
592
457
- lookups = NamedTuple ( )
593
+ (; lookups, lu_kwargs) = lookup_tables (radiation_mode, device, FT )
458
594
views = []
459
595
460
596
nlay = domain_nlay + Int (radiation_mode. add_isothermal_boundary_layer)
461
597
t = (views, domain_nlay)
462
598
463
- if radiation_mode isa GrayRadiation
464
- nbnd_lw = 1
465
- else
466
- local lookup_lw, idx_gases
467
- NC. Dataset (RRTMGP. ArtifactPaths. get_lookup_filename (:gas , :lw )) do ds
468
- lookup_lw, idx_gases = RRTMGP. LookUpTables. LookUpLW (ds, FT, DA)
469
- end
470
- lookups = (; lookups... , lookup_lw, idx_gases)
471
-
472
- nbnd_lw = RRTMGP. LookUpTables. get_n_bnd (lookup_lw)
473
- ngas = RRTMGP. LookUpTables. get_n_gases (lookup_lw)
474
-
475
- if ! (radiation_mode isa ClearSkyRadiation)
476
- local lookup_lw_cld
477
- NC. Dataset (
478
- RRTMGP. ArtifactPaths. get_lookup_filename (:cloud , :lw ),
479
- ) do ds
480
- lookup_lw_cld = RRTMGP. LookUpTables. LookUpCld (ds, FT, DA)
481
- end
482
- lookups = (; lookups... , lookup_lw_cld)
483
- end
484
- if radiation_mode. aerosol_radiation
485
- local lookup_lw_aero, idx_aerosol, idx_aerosize
486
- NC. Dataset (
487
- RRTMGP. ArtifactPaths. get_lookup_filename (:aerosol , :lw ),
488
- ) do ds
489
- lookup_lw_aero, idx_aerosol, idx_aerosize =
490
- RRTMGP. LookUpTables. LookUpAerosolMerra (ds, FT, DA)
491
- end
492
- else
493
- lookup_lw_aero = nothing
494
- end
495
- lookups = (; lookups... , lookup_lw_aero)
496
- end
497
-
498
599
src_lw = RRTMGP. Sources. source_func_longwave (
499
600
params,
500
601
FT,
@@ -517,7 +618,7 @@ function _RRTMGPModel(
517
618
set_and_save! (flux_lw2. flux_net, " face_clear_lw_flux" , t... )
518
619
end
519
620
520
- sfc_emis = DA {FT} (undef, nbnd_lw, ncol)
621
+ sfc_emis = DA {FT} (undef, lu_kwargs . nbnd_lw, ncol)
521
622
set_and_save! (sfc_emis, " surface_emissivity" , t... , dict)
522
623
name = " top_of_atmosphere_lw_flux_dn"
523
624
if Symbol (name) in keys (dict)
@@ -527,43 +628,6 @@ function _RRTMGPModel(
527
628
inc_flux = nothing
528
629
end
529
630
bcs_lw = RRTMGP. BCs. LwBCs (sfc_emis, inc_flux)
530
-
531
- if radiation_mode isa GrayRadiation
532
- nbnd_sw = 1
533
- else
534
- local lookup_sw, idx_gases
535
- NC. Dataset (RRTMGP. ArtifactPaths. get_lookup_filename (:gas , :sw )) do ds
536
- lookup_sw, idx_gases = RRTMGP. LookUpTables. LookUpSW (ds, FT, DA)
537
- end
538
- lookups = (; lookups... , lookup_sw, idx_gases)
539
-
540
- nbnd_sw = RRTMGP. LookUpTables. get_n_bnd (lookup_sw)
541
- ngas = RRTMGP. LookUpTables. get_n_gases (lookup_sw)
542
-
543
- if ! (radiation_mode isa ClearSkyRadiation)
544
- local lookup_sw_cld
545
- NC. Dataset (
546
- RRTMGP. ArtifactPaths. get_lookup_filename (:cloud , :sw ),
547
- ) do ds
548
- lookup_sw_cld = RRTMGP. LookUpTables. LookUpCld (ds, FT, DA)
549
- end
550
- lookups = (; lookups... , lookup_sw_cld)
551
- end
552
-
553
- if radiation_mode. aerosol_radiation
554
- local lookup_sw_aero, idx_aerosol, idx_aerosize
555
- NC. Dataset (
556
- RRTMGP. ArtifactPaths. get_lookup_filename (:aerosol , :sw ),
557
- ) do ds
558
- lookup_sw_aero, idx_aerosol, idx_aerosize =
559
- RRTMGP. LookUpTables. LookUpAerosolMerra (ds, FT, DA)
560
- end
561
- else
562
- lookup_sw_aero = nothing
563
- end
564
- lookups = (; lookups... , lookup_sw_aero)
565
- end
566
-
567
631
src_sw =
568
632
RRTMGP. Sources. source_func_shortwave (FT, ncol, nlay, :TwoStream , DA)
569
633
flux_sw = RRTMGP. Fluxes. FluxSW (ncol, nlay, FT, DA)
@@ -590,9 +654,9 @@ function _RRTMGPModel(
590
654
set_and_save! (cos_zenith, " cos_zenith" , t... , dict)
591
655
toa_flux = DA {FT} (undef, ncol)
592
656
set_and_save! (toa_flux, " weighted_irradiance" , t... , dict)
593
- sfc_alb_direct = DA {FT} (undef, nbnd_sw, ncol)
657
+ sfc_alb_direct = DA {FT} (undef, lu_kwargs . nbnd_sw, ncol)
594
658
set_and_save! (sfc_alb_direct, " direct_sw_surface_albedo" , t... , dict)
595
- sfc_alb_diffuse = DA {FT} (undef, nbnd_sw, ncol)
659
+ sfc_alb_diffuse = DA {FT} (undef, lu_kwargs . nbnd_sw, ncol)
596
660
set_and_save! (sfc_alb_diffuse, " diffuse_sw_surface_albedo" , t... , dict)
597
661
name = " top_of_atmosphere_diffuse_sw_flux_dn"
598
662
if Symbol (name) in keys (dict)
@@ -615,11 +679,6 @@ function _RRTMGPModel(
615
679
if radiation_mode isa AllSkyRadiationWithClearSkyDiagnostics
616
680
set_and_save! (similar (flux_lw2. flux_net), " face_clear_flux" , t... )
617
681
end
618
- if ! (radiation_mode isa GrayRadiation)
619
- @assert RRTMGP. LookUpTables. get_n_gases (lookup_lw) ==
620
- RRTMGP. LookUpTables. get_n_gases (lookup_sw)
621
- @assert lookup_lw. p_ref_min == lookup_sw. p_ref_min
622
- end
623
682
624
683
if ! (:latitude in keys (dict))
625
684
lon = lat = nothing
@@ -643,13 +702,9 @@ function _RRTMGPModel(
643
702
z_lev = DA {FT} (undef, nlay + 1 , ncol) # TODO : z_lev required but unused
644
703
645
704
# lapse_rate is a constant, so don't use set_and_save! to get it
646
- if ! (:lapse_rate in keys (dict))
647
- throw (UndefKeywordError (:lapse_rate ))
648
- end
705
+ :lapse_rate in keys (dict) || throw (UndefKeywordError (:lapse_rate ))
649
706
α = pop! (dict, :lapse_rate )
650
- if ! (α isa Real)
651
- error (" lapse_rate must be a Real" )
652
- end
707
+ α isa Real || error (" lapse_rate must be a Real" )
653
708
654
709
d0 = DA {FT} (undef, ncol)
655
710
set_and_save! (d0, " optical_thickness_parameter" , t... , dict)
@@ -676,7 +731,7 @@ function _RRTMGPModel(
676
731
gas_names = filter (
677
732
gas_name ->
678
733
! (gas_name in (" h2o" , " h2o_frgn" , " h2o_self" , " o3" )),
679
- keys (idx_gases ),
734
+ keys (lookups . idx_gases_sw ),
680
735
)
681
736
# TODO : This gives the wrong types for CUDA 3.4 and above.
682
737
# gm = use_global_means_for_well_mixed_gases
@@ -685,19 +740,19 @@ function _RRTMGPModel(
685
740
vmr = RRTMGP. Vmrs. VmrGM (
686
741
DA {FT} (undef, nlay, ncol),
687
742
DA {FT} (undef, nlay, ncol),
688
- DA {FT} (undef, ngas ),
743
+ DA {FT} (undef, lu_kwargs . ngas_sw ),
689
744
)
690
745
vmr. vmr .= 0 # TODO : do we need this?
691
746
set_and_save! (vmr. vmr_h2o, " center_$(vmr_str) h2o" , t... , dict)
692
747
set_and_save! (vmr. vmr_o3, " center_$(vmr_str) o3" , t... , dict)
693
748
for gas_name in gas_names
694
- gas_view = view (vmr. vmr, idx_gases [gas_name])
749
+ gas_view = view (vmr. vmr, lookups . idx_gases_sw [gas_name])
695
750
set_and_save! (gas_view, " $vmr_str$gas_name " , t... , dict)
696
751
end
697
752
else
698
- vmr = RRTMGP. Vmrs. Vmr (DA {FT} (undef, ngas , nlay, ncol))
753
+ vmr = RRTMGP. Vmrs. Vmr (DA {FT} (undef, lu_kwargs . ngas_sw , nlay, ncol))
699
754
for gas_name in [" h2o" , " o3" , gas_names... ]
700
- gas_view = view (vmr. vmr, idx_gases [gas_name], :, :)
755
+ gas_view = view (vmr. vmr, lookups . idx_gases_sw [gas_name], :, :)
701
756
set_and_save! (gas_view, " center_$vmr_str$gas_name " , t... , dict)
702
757
end
703
758
end
@@ -752,8 +807,8 @@ function _RRTMGPModel(
752
807
set_and_save! (aod_sw_ext, " aod_sw_extinction" , t... , dict)
753
808
set_and_save! (aod_sw_sca, " aod_sw_scattering" , t... , dict)
754
809
755
- n_aerosol_sizes = maximum (values (idx_aerosize))
756
- n_aerosols = length (idx_aerosol)
810
+ n_aerosol_sizes = maximum (values (lookups . idx_aerosize_sw)) # TODO : verify correctness
811
+ n_aerosols = length (lookups . idx_aerosol_sw) # TODO : verify correctness
757
812
# See the lookup table in RRTMGP for the order of aerosols
758
813
aero_size = DA {FT} (undef, n_aerosol_sizes, nlay, ncol)
759
814
aero_mass = DA {FT} (undef, n_aerosols, nlay, ncol)
@@ -973,7 +1028,7 @@ get_p_min(model) = get_p_min(model.as, model.lookups)
973
1028
get_p_min (as:: RRTMGP.AtmosphericStates.GrayAtmosphericState , lookups) =
974
1029
zero (eltype (as. p_lay))
975
1030
get_p_min (as:: RRTMGP.AtmosphericStates.AtmosphericState , lookups) =
976
- lookups[ 1 ] . p_ref_min
1031
+ lookups. lookup_lw . p_ref_min # TODO : verify correctness
977
1032
978
1033
function update_implied_values! (model)
979
1034
(; p_lev, t_lev, t_sfc) = model. as
@@ -1090,12 +1145,12 @@ update_concentrations!(radiation_mode, model) = RRTMGP.Optics.compute_col_gas!(
1090
1145
model. as. p_lev,
1091
1146
AS. getview_col_dry (model. as),
1092
1147
model. params,
1093
- get_vmr_h2o (model. as. vmr, model. lookups. idx_gases ),
1148
+ get_vmr_h2o (model. as. vmr, model. lookups. idx_gases_sw ),
1094
1149
model. as. lat,
1095
1150
)
1096
- get_vmr_h2o (vmr:: RRTMGP.Vmrs.VmrGM , idx_gases ) = vmr. vmr_h2o
1097
- get_vmr_h2o (vmr:: RRTMGP.Vmrs.Vmr , idx_gases ) =
1098
- view (vmr. vmr, idx_gases [" h2o" ], :, :)
1151
+ get_vmr_h2o (vmr:: RRTMGP.Vmrs.VmrGM , idx_gases_sw ) = vmr. vmr_h2o
1152
+ get_vmr_h2o (vmr:: RRTMGP.Vmrs.Vmr , idx_gases_sw ) =
1153
+ view (vmr. vmr, idx_gases_sw [" h2o" ], :, :)
1099
1154
1100
1155
NVTX. @annotate update_lw_fluxes! (:: GrayRadiation , model) =
1101
1156
RRTMGP. RTESolver. solve_lw! (model. lw_solver, model. as)
0 commit comments