Skip to content

Commit 0873d11

Browse files
authored
Merge pull request #1506 from jimmielin/hplin/rad_cnst_refactor_5_optics
cam6_4_163: Refactor rad_constituents, aerosol_optics_cam for portability; extend abstract aerosol interface
2 parents c50f118 + f0cb14c commit 0873d11

55 files changed

Lines changed: 6525 additions & 5594 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

doc/ChangeLog

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,229 @@
11
===============================================================
22

3+
Tag name: cam6_4_163
4+
Originator(s): jimmielin
5+
Date: April 10, 2026
6+
One-line Summary: Refactor rad_constituents, aerosol_optics_cam for portability; extend abstract aerosol interface
7+
Github PR URL: https://github.com/ESCOMP/CAM/pull/1506
8+
9+
Purpose of changes (include the issue number and title text for each relevant GitHub issue):
10+
11+
- Closes #1504
12+
- Closes #1505
13+
14+
This pull request is an extensive refactor of `rad_constituents.F90` to facilitate bringing into CAM-SIMA.
15+
- It splits off the previous `rad_constituents.F90` into aerosol-related modules; the original file will only handle gases. This is because RRTMGP port to CAM-SIMA split off radiatively active aerosols from gases+aerosols.
16+
- Isolate CAM-specific data structure retrieval (from pbuf and constituents) to `aerosol_mmr_cam.F90`, which can be modified to use whichever data structures are in other host models (e.g., the CCPP constituents object in CAM-SIMA will replace both pbuf and state for the purpose of radiatively active aerosol.)
17+
- Aerosol-related calls are now prefixed with `rad_aer_*` for clarity.
18+
19+
This pull request also extends the use of the abstract aerosol interface (`aerosol_properties` and `aerosol_state`) into other physics and chemistry code, instead of the previous calls to `rad_cnst_*`.
20+
- `aerosol_properties` and `aerosol_state` are now per-`list_idx` (climate or diagnostic list) instead of having separate `_0list` or `_rlist` functions; separate instantiations of the aerosol properties and state objects per `(aero_model, list_idx)` pair is available. This allows us to keep track of the objects themselves instead of `list_idx`. Since most calls are on the climate list (`list_idx=0`) it will simplify calls and reduce repeating the "0" argument into `rad_cnst_*`.
21+
- `aerosol_instances_mod` owns both `aerosol_properties` (per model/list) and `aerosol_state` (per model/list/chunk) as persistent module data. State objects store only pointers to the persistent `phys_state(lchnk)` and `pbuf` arrays, and is thread-safe. A per-call `create_states`/`destroy_states` factory remains for transient states bound to local copies of `physics_state` (i.e., `microp_aero_run`'s `state1`).
22+
- `aerosol_instances_mod` and its use in `physpkg.F90` most closely mimics the envisioned implementation under CAM-SIMA where `aerosol_properties` and `aerosol_state` become inputs to CCPP physics schemes. Under CAM-SIMA the chunk dimension is removed and objects are passed directly: the factory pattern will be retired.
23+
24+
This pull request also extracts the creation of optics objects and per-bin sw/lw property calculations from `aerosol_optics_cam` to `aerosol_optics_core.F90`; the latter is fully-portable.
25+
26+
After this refactoring, the following modules will be
27+
**fully-portable**:
28+
* `aerosol_properties_mod.F90` - abstract base class.
29+
* `aerosol_state_mod.F90` - abstract base class.
30+
* `radiative_aerosol_definitions.F90` - base types for radiatively active aerosol.
31+
* `bulk_aerosol_properties_mod.F90`
32+
* `modal_aerosol_properties_mod.F90`
33+
* `aerosol_optics_core.F90`
34+
35+
**almost-portable** (need to remove `state` and `pbuf` or minor CAM structures):
36+
* `bulk_aerosol_state_mod.F90` - remove state and pbuf, use host-model MMR module (see below)
37+
* `radiative_aerosol.F90` - use host-model MMR module to resolve indices; diags
38+
* `aerosol_instances_mod.F90` - dechunkize, change init_states to remove pbuf, remove create_states factory once unused
39+
40+
**host-model specific**:
41+
* `aerosol_mmr_cam.F90` - pbuf and state%q indexing to replace with host-model specific code (i.e., CAM-SIMA CCPP constituents)
42+
43+
**needing some future work** to separate out dependencies - MAM/CARMA changes were made at a best-effort here and need to be for another day:
44+
* `modal_aerosol_state_mod.F90`: need to CCPPize `modal_aero_wateruptake_dr` and `modal_aero_calcsize_diag`; role of `modal_aero_data` is to be scoped out (out of scope for this work)
45+
* `carma_aerosol_properties_mod.F90`: depends on `carma_intr` (out of scope for this work)
46+
* `carma_aerosol_state_mod.F90`: depends on `carma_intr` (out of scope for this work)
47+
48+
All changes are **bit-for-bit unchanged** with CAM (based off `cam6_4_156`)
49+
50+
Describe any changes made to build system: N/A
51+
52+
Describe any changes made to the namelist: N/A
53+
54+
List any changes to the defaults for the boundary datasets: N/A
55+
56+
Describe any substantial timing or memory changes: N/A
57+
58+
Code reviewed by: fvitt
59+
60+
List all files eliminated: N/A
61+
62+
List all files added and what they do:
63+
A src/chemistry/aerosol/aerosol_instances_mod.F90
64+
- owns persistent aerosol_properties (per model/list) and aerosol_state
65+
(per model/list/chunk) objects. Provides getters and a per-call factory
66+
for transient states.
67+
68+
A src/chemistry/aerosol/radiative_aerosol_definitions.F90
69+
- split-off structural data and key definitions from rad_constituents.
70+
purpose of this file is to be the common dependency and not have the gas rad_cnst
71+
and aerosol rad_aer depend on each other for types and vars like N_DIAG
72+
73+
A src/chemistry/aerosol/radiative_aerosol.F90
74+
- split-off aerosol subroutines from rad_constituents.
75+
this is the "replacement" for rad_constituents in CAM-SIMA
76+
77+
A src/physics/cam/aerosol_mmr_cam.F90
78+
- split-off host-model-specific indexing (pbuf, constituents) for radiatively active
79+
aerosol.
80+
81+
A src/chemistry/aerosol/aerosol_optics_core.F90
82+
- split-off logic to create the aerosol_optics_object and per-bin sw/lw optics calculations
83+
from aerosol_optics_cam.F90 using the abstract aerosol interface.
84+
85+
List all existing files that have been modified, and describe the changes:
86+
M src/chemistry/aerosol/aerosol_properties_mod.F90
87+
- add list_idx_ to store which radiation list this properties instance belongs to.
88+
- add nbins, nspecies, alogsig, dgnum, dgnumhi, dgnumlo, rhcrystal, rhdeliques
89+
- add num_to_mass_aer, dryrad properties (for BAM)
90+
- concrete optics_params implementation for all aerosol models
91+
92+
M src/chemistry/aerosol/aerosol_state_mod.F90
93+
- add list_idx_ to store which radiation list this properties instance belongs to.
94+
95+
M src/chemistry/aerosol/bulk_aerosol_properties_mod.F90
96+
- implement alogsig (previously a stub)
97+
98+
M src/physics/cam/rad_constituents.F90
99+
- remove all code related to aerosol; this module is now gas-only.
100+
101+
M src/physics/cam/aerosol_optics_cam.F90
102+
- now uses aerosol_instances_mod to query which aerosol models are active,
103+
and how many aerosol models are active.
104+
- now uses aerosol properties and persistent aerosol_state from
105+
aerosol_instances_mod (replaces per-call create/destroy).
106+
- moves core calculations to portable aerosol_optics_core.F90.
107+
108+
M src/physics/cam7/physpkg.F90
109+
M src/physics/cam/physpkg.F90
110+
- initialization for radiative_aerosol
111+
- initialization for aerosol_instances_mod (properties + persistent states)
112+
- use aerosol_instances_get_state for modal_aer_calcsize, wateruptake
113+
(replaces per-call create/destroy).
114+
115+
M src/chemistry/aerosol/bulk_aerosol_state_mod.F90
116+
M src/chemistry/aerosol/carma_aerosol_properties_mod.F90
117+
M src/chemistry/aerosol/carma_aerosol_state_mod.F90
118+
M src/chemistry/aerosol/modal_aerosol_state_mod.F90
119+
M src/chemistry/aerosol/hygro_aerosol_optics_mod.F90
120+
M src/chemistry/aerosol/hygrocoreshell_aerosol_optics_mod.F90
121+
M src/chemistry/aerosol/hygroscopic_aerosol_optics_mod.F90
122+
M src/chemistry/aerosol/hygrowghtpct_aerosol_optics_mod.F90
123+
M src/chemistry/aerosol/insoluble_aerosol_optics_mod.F90
124+
M src/chemistry/aerosol/refractive_aerosol_optics_mod.F90
125+
M src/chemistry/aerosol/volcrad_aerosol_optics_mod.F90
126+
- changes to support list_idx change
127+
128+
M src/chemistry/aerosol/modal_aerosol_properties_mod.F90
129+
- changes to support list_idx change
130+
- port mode_size_order from modal_aero_data.
131+
- add dgnumlo, dgnumhi, dgnum, rhcrystal, rhdeliques
132+
- remove aero_optics_params in favor of unified implementation
133+
134+
M src/chemistry/aerosol/aero_wetdep_cam.F90
135+
- use persistent aerosol_state from aerosol_instances_mod
136+
(replaces direct modal/carma constructor calls and per-call deallocation).
137+
138+
M src/chemistry/aerosol/modal_aero_data.F90
139+
M src/chemistry/carma_aero/carma_aero_gasaerexch.F90
140+
M src/chemistry/carma_aero/sox_cldaero_mod.F90
141+
M src/chemistry/carma_aero/aero_model.F90
142+
M src/chemistry/geoschem/chemistry.F90
143+
M src/chemistry/modal_aero/aero_model.F90
144+
M src/chemistry/modal_aero/modal_aero_rename.F90
145+
- changes to rename rad_cnst_ to rad_aer_ where needed
146+
(cannot use abstract interface during initialization/register phases.)
147+
148+
M src/physics/cam/phys_debug.F90
149+
M src/physics/camrt/radiation.F90
150+
M src/physics/rrtmg/radiation.F90
151+
M src/physics/rrtmgp/radiation.F90
152+
M src/physics/cam/radiation_data.F90
153+
- changes to rename rad_cnst_ to rad_aer_ where needed
154+
(these modules will not be ported to CAM-SIMA so were less modified.)
155+
156+
M src/chemistry/modal_aero/modal_aero_gasaerexch.F90
157+
- changes to rename rad_cnst to rad_aer_ where needed
158+
(part of modal_aero model itself so no need for abstract interface.)
159+
160+
M src/chemistry/mozart/mo_usrrxt.F90
161+
- changes to rename rad_cnst to rad_aer_ where needed
162+
(will be superceded by MICM and just dimension setup anyway.)
163+
164+
M src/physics/cam/microp_aero.F90
165+
- now use aero_props and aero_state abstract interface.
166+
- persistent per-chunk aerosol_state moved to aerosol_instances_mod; the
167+
aerosol_state_object() shim now delegates to aerosol_instances_get_state()
168+
for backward compatibility with the dycore stepon modules
169+
(so we do not have to edit the fv3 external)
170+
- microp_aero_run still uses the per-call factory for state1 (local copy).
171+
172+
M src/chemistry/modal_aero/dust_model.F90
173+
M src/chemistry/modal_aero/seasalt_model.F90
174+
M src/chemistry/mozart/fire_emissions.F90
175+
M src/chemistry/utils/modal_aero_deposition.F90
176+
- now use aero_props abstract interface (modal aerosols).
177+
178+
M src/chemistry/utils/modal_aero_calcsize.F90
179+
M src/chemistry/utils/modal_aero_wateruptake.F90
180+
- now use aero_props and aero_state abstract interfaces.
181+
182+
M src/chemistry/utils/prescribed_aero.F90
183+
- now uses aerosol_instances_mod::aerosol_instances_is_active to query
184+
whether the modal aerosol representation is active.
185+
186+
M src/physics/cam/aer_rad_props.F90
187+
- now uses aerosol_instances_mod to query which aerosol models are active,
188+
and how many aerosol models are active.
189+
190+
M src/physics/cam/aer_vis_diag_mod.F90
191+
- now use aero_props abstract interface (bulk aerosols).
192+
193+
M src/physics/cam/ndrop_bam.F90
194+
- use aero_props and aero_state abstract interfaces (bulk aerosols).
195+
196+
M src/physics/cam/nucleate_ice_cam.F90
197+
- use aero_props and aero_state abstract interfaces.
198+
199+
M src/physics/cam/clubb_intr.F90
200+
M src/physics/cam/zm_conv_intr.F90
201+
- remove unused use statements
202+
203+
204+
If there were any failures reported from running test_driver.sh on any test
205+
platform, and checkin with these failures has been OK'd by the gatekeeper,
206+
then copy the lines from the td.*.status files for the failed tests to the
207+
appropriate machine below. All failed tests must be justified.
208+
209+
derecho/intel/aux_cam: All PASS
210+
211+
derecho/nvhpc/aux_cam:
212+
ERS_Ln9.ne30pg3_ne30pg3_mt232.FHISTC_LTso.derecho_nvhpc.cam-outfrq9s_gpu_default (Overall: FAIL) details:
213+
FAIL ERS_Ln9.ne30pg3_ne30pg3_mt232.FHISTC_LTso.derecho_nvhpc.cam-outfrq9s_gpu_default COMPARE_base_rest
214+
- pre-existing failure -- see https://github.com/ESCOMP/CAM/issues/1513
215+
216+
izumi/nag/aux_cam:
217+
ERC_D_Ln9.f10_f10_mt232.FHIST_C5.izumi_nag.cam-outfrq3s_subcol (Overall: FAIL) details:
218+
FAIL ERC_D_Ln9.f10_f10_mt232.FHIST_C5.izumi_nag.cam-outfrq3s_subcol COMPARE_base_rest
219+
- pre-existing failure -- see https://github.com/ESCOMP/CAM/issues/1514
220+
221+
izumi/gnu/aux_cam: All PASS
222+
223+
Summarize any changes to answers: All B4B
224+
225+
===============================================================
226+
3227
Tag name: cam6_4_162
4228
Originator(s): fvitt
5229
Date: 2 Apr 2026

src/chemistry/aerosol/aero_wetdep_cam.F90

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,17 @@ module aero_wetdep_cam
1616
use cam_history, only: addfld, add_default, horiz_only, outfld
1717
use wetdep, only: wetdep_init
1818

19-
use rad_constituents, only: rad_cnst_get_info
19+
use radiative_aerosol, only: rad_aer_get_info
2020

2121
use aerosol_properties_mod, only: aero_name_len
2222
use aerosol_properties_mod, only: aerosol_properties
2323
use modal_aerosol_properties_mod, only: modal_aerosol_properties
2424
use carma_aerosol_properties_mod, only: carma_aerosol_properties
2525

2626
use aerosol_state_mod, only: aerosol_state, ptr2d_t
27-
use modal_aerosol_state_mod, only: modal_aerosol_state
28-
use carma_aerosol_state_mod, only: carma_aerosol_state
27+
use aerosol_instances_mod, only: aerosol_instances_get_state, &
28+
aerosol_instances_get_props, &
29+
aerosol_instances_get_num_models
2930

3031
use aero_convproc, only: aero_convproc_readnl, aero_convproc_init, aero_convproc_intr
3132
use aero_convproc, only: convproc_do_evaprain_atonce
@@ -172,7 +173,7 @@ subroutine aero_wetdep_init( )
172173
history_chemistry_out=history_chemistry, &
173174
convproc_do_aer_out = convproc_do_aer)
174175

175-
call rad_cnst_get_info(0, nmodes=nmodes, nbins=nbins)
176+
call rad_aer_get_info(0, nmodes=nmodes, nbins=nbins)
176177

177178
if (nmodes>0) then
178179
aero_props => modal_aerosol_properties()
@@ -409,26 +410,30 @@ subroutine aero_wetdep_tend( state, dt, dlf, cam_out, ptend, pbuf)
409410
real(r8) :: sflxbc(pcols), sflxbcdp(pcols) ! deposition flux
410411

411412
class(aerosol_state), pointer :: aero_state
413+
class(aerosol_properties), pointer :: props_tmp
414+
integer :: iaermod
412415

413416
nullify(aero_state)
414417

415418
if (.not.wetdep_active) return
416419

417420
dcondt_resusp3d(:,:,:) = 0._r8
418421

419-
if (nmodes>0) then
420-
aero_state => modal_aerosol_state(state,pbuf)
421-
if (.not.associated(aero_state)) then
422-
call endrun(subrname//' : construction of aero_state modal_aerosol_state object failed')
423-
end if
424-
else if (nbins>0) then
425-
aero_state => carma_aerosol_state(state,pbuf)
426-
if (.not.associated(aero_state)) then
427-
call endrun(subrname//' : construction of aero_state carma_aerosol_state object failed')
422+
!REMOVECAM - get persistent state from factory; under CAM-SIMA states will be passed as scheme inputs
423+
nullify(aero_state)
424+
do iaermod = 1, aerosol_instances_get_num_models()
425+
props_tmp => aerosol_instances_get_props(iaermod, 0)
426+
if (associated(props_tmp)) then
427+
if (.not. props_tmp%model_is('BAM')) then
428+
aero_state => aerosol_instances_get_state(iaermod, 0, state%lchnk)
429+
exit
430+
end if
428431
end if
429-
else
430-
call endrun(subrname//' : cannot determine aerosol model')
431-
endif
432+
end do
433+
if (.not.associated(aero_state)) then
434+
call endrun(subrname//' : no non-BAM aerosol state available for wetdep')
435+
end if
436+
!REMOVECAM_END
432437

433438
lchnk = state%lchnk
434439
ncol = state%ncol
@@ -601,7 +606,7 @@ subroutine aero_wetdep_tend( state, dt, dlf, cam_out, ptend, pbuf)
601606
qqcw_in(:ncol,:) = qqcw(mm)%fld(:ncol,:)
602607
end if
603608

604-
f_act_conv(:ncol,:) = aero_state%convcld_actfrac( m, l, ncol, pver)
609+
f_act_conv(:ncol,:) = aero_state%convcld_actfrac( aero_props, m, l, ncol, pver)
605610
name = aname
606611
end if
607612

@@ -796,10 +801,7 @@ subroutine aero_wetdep_tend( state, dt, dlf, cam_out, ptend, pbuf)
796801

797802
end do bins_loop
798803

799-
if (associated(aero_state)) then
800-
deallocate(aero_state)
801-
nullify(aero_state)
802-
end if
804+
nullify(aero_state)
803805

804806
! if the user has specified prescribed aerosol dep fluxes then
805807
! do not set cam_out dep fluxes according to the prognostic aerosols

0 commit comments

Comments
 (0)