Skip to content

Commit 4e152b7

Browse files
authored
Merge pull request #277 from chihchen24/cam_development_contrail
cam6_3_014: contrail parameterization added
2 parents 553e9a3 + 3340aba commit 4e152b7

File tree

10 files changed

+671
-112
lines changed

10 files changed

+671
-112
lines changed

cime_config/testdefs/testlist_cam.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,6 +1064,14 @@
10641064
<option name="wallclock">00:20:00</option>
10651065
</options>
10661066
</test>
1067+
<test compset="FSD" grid="f09_f09_mg17" name="ERP_D_Ln9" testmods="cam/outfrq9s_contrail">
1068+
<machines>
1069+
<machine name="cheyenne" compiler="intel" category="prealpha"/>
1070+
</machines>
1071+
<options>
1072+
<option name="wallclock">00:20:00</option>
1073+
</options>
1074+
</test>
10671075
<test compset="FSD" grid="f09_f09_mg17" name="SMS_D_Ln9" testmods="cam/outfrq9s">
10681076
<machines>
10691077
<machine name="cheyenne" compiler="intel" category="aux_cam"/>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
./xmlchange ROF_NCPL=\$ATM_NCPL
2+
./xmlchange GLC_NCPL=\$ATM_NCPL
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
mfilt=1,1,1,1,1,1
2+
ndens=1,1,1,1,1,1
3+
nhtfrq=9,9,9,9,9,9
4+
inithist='ENDOFRUN'
5+
aircraft_datapath ='$DIN_LOC_ROOT/atm/cam/ggas'
6+
aircraft_specifier =
7+
'ac_H2O -> ac_H2O_filelist_monthly_2006.txt'
8+
'ac_SLANT_DIST -> ac_SLANT_DIST_filelist_monthly_2006.txt'
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
!----------------------------------------------------------------------------------
2+
! Users should add all user specific namelist changes below in the form of
3+
! namelist_var = new_namelist_value
4+
!
5+
! Include namelist variables for drv_flds_in ONLY if -megan and/or -drydep options
6+
! are set in the CLM_NAMELIST_OPTS env variable.
7+
!
8+
! EXCEPTIONS:
9+
! Set use_cndv by the compset you use and the CLM_BLDNML_OPTS -dynamic_vegetation setting
10+
! Set use_vichydro by the compset you use and the CLM_BLDNML_OPTS -vichydro setting
11+
! Set use_cn by the compset you use and CLM_BLDNML_OPTS -bgc setting
12+
! Set use_crop by the compset you use and CLM_BLDNML_OPTS -crop setting
13+
! Set spinup_state by the CLM_BLDNML_OPTS -bgc_spinup setting
14+
! Set irrigate by the CLM_BLDNML_OPTS -irrig setting
15+
! Set dtime with L_NCPL option
16+
! Set fatmlndfrc with LND_DOMAIN_PATH/LND_DOMAIN_FILE options
17+
! Set finidat with RUN_REFCASE/RUN_REFDATE/RUN_REFTOD options for hybrid or branch cases
18+
! (includes $inst_string for multi-ensemble cases)
19+
! Set glc_grid with CISM_GRID option
20+
! Set glc_smb with GLC_SMB option
21+
! Set maxpatch_glcmec with GLC_NEC option
22+
! Set glc_do_dynglacier with GLC_TWO_WAY_COUPLING env variable
23+
!----------------------------------------------------------------------------------
24+
hist_nhtfrq = 9
25+
hist_mfilt = 1
26+
hist_ndens = 1
27+

doc/ChangeLog

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,69 @@
1+
2+
===============================================================
3+
4+
Tag name: cam6_3_014
5+
Originator(s): cchen, cacraig
6+
Date: March 23, 2021
7+
One-line Summary: Contrail parametrization added to CAM
8+
Github PR URL: https://github.com/ESCOMP/CAM/pull/277
9+
10+
Purpose of changes (include the issue number and title text for each relevant GitHub issue):
11+
Contrail Parameterization: https://github.com/ESCOMP/CAM/issues/274
12+
13+
Describe any changes made to build system:
14+
15+
Describe any changes made to the namelist:
16+
- "aircraft_specifier" can now take the values ac_SLANT_DIST and/or ac_TRACK_DIST to signal a contrail run
17+
18+
List any changes to the defaults for the boundary datasets:
19+
20+
Describe any substantial timing or memory changes:
21+
22+
Code reviewed by: cacraig, goldy, fvitt, nusbaume
23+
24+
List all files eliminated:
25+
26+
List all files added and what they do:
27+
A cime_config/testdefs/testmods_dirs/cam/outfrq9s_contrail/shell_commands
28+
A cime_config/testdefs/testmods_dirs/cam/outfrq9s_contrail/user_nl_cam
29+
A cime_config/testdefs/testmods_dirs/cam/outfrq9s_contrail/user_nl_clm
30+
- introduce test for contrail
31+
32+
A src/physics/cam/ssatcontrail.F90
33+
- Actual code to process contrails
34+
35+
List all existing files that have been modified, and describe the changes:
36+
M cime_config/testdefs/testlist_cam.xml
37+
- Add prealpha contrail test
38+
39+
M src/chemistry/utils/aircraft_emit.F90
40+
- Adds logic to setup contrail run if either or both of ac_SLANT_DIST and ac_TRACK_DIST are in
41+
the aircraft_specifier list
42+
43+
M src/chemistry/utils/horizontal_interpolate.F90
44+
- add additional logic for using flight distance and making additional calculations
45+
46+
M src/chemistry/utils/tracer_data.F90
47+
- add additional logic if a contrail run is specified
48+
49+
M src/physics/cam/physpkg.F90
50+
- add call to ssatcontrail_d0 (which returns immediately if not a contrail run)
51+
52+
If there were any failures reported from running test_driver.sh on any test
53+
platform, and checkin with these failures has been OK'd by the gatekeeper,
54+
then copy the lines from the td.*.status files for the failed tests to the
55+
appropriate machine below. All failed tests must be justified.
56+
57+
cheyenne/intel/aux_cam: all BFB
58+
59+
izumi/nag/aux_cam: all BFB except:
60+
DAE.f45_f45_mg37.FHS94.izumi_nag.cam-dae (Overall: FAIL) details:
61+
FAIL DAE.f45_f45_mg37.FHS94.izumi_nag.cam-dae COMPARE_base_da
62+
FAIL ERC_D_Ln9.f10_f10_mg37.QPC5.izumi_nag.cam-outfrq3s_carma TPUTCOMP Error: TPUTCOMP: Computation time increase > 25% from baseline
63+
- Known failure from previous tag
64+
65+
izumi/pgi/aux_cam: all BFB
66+
===============================================================
167
===============================================================
268

369
Tag name: cam6_3_013

src/chemistry/utils/aircraft_emit.F90

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ module aircraft_emit
2323
public :: aircraft_emit_adv
2424
public :: aircraft_emit_register
2525
public :: aircraft_emit_readnl
26+
public :: get_aircraft
2627

2728
type :: forcing_air
2829
real(r8) :: mw
@@ -40,16 +41,15 @@ module aircraft_emit
4041

4142
type(forcing_air),allocatable :: forcings_air(:)
4243

43-
integer, parameter :: N_AERO = 10
44-
character(len=11) :: aero_names(N_AERO) = (/'ac_HC ','ac_NOX ','ac_PMNV ',&
45-
'ac_PMSO ','ac_PMFO ','ac_FUELBURN','ac_CO2 ','ac_H2O ',&
46-
'ac_SOX ','ac_CO '/)
44+
integer, parameter :: N_AERO = 13
45+
character(len=13) :: aero_names(N_AERO) = (/'ac_SLANT_DIST','ac_TRACK_DIST','ac_HC ','ac_NOX ','ac_PMNV ',&
46+
'ac_PMSO ','ac_PMFO ','ac_FUELBURN ','ac_CO2 ','ac_H2O ',&
47+
'ac_SOX ','ac_CO ','ac_BC '/)
4748

4849
real(r8), parameter :: molmass(N_AERO) = 1._r8
4950

50-
logical :: advective_tracer(N_AERO) = (/.false., .false., .false., .false., .false., &
51-
.false., .false., .false., .false.,.false./)
52-
character(len=3) :: mixtype(N_AERO) = (/'wet','wet','wet','wet','wet','wet','wet','wet','wet','wet'/)
51+
logical :: advective_tracer(N_AERO) = .false.
52+
character(len=3) :: mixtype(N_AERO) = 'wet'
5353

5454
real(r8) :: cptmp = 666.0_r8
5555
real(r8) :: qmin = 0.0_r8
@@ -67,9 +67,26 @@ module aircraft_emit
6767
integer :: aircraft_cnt = 0
6868
character(len=16) :: spc_name_list(N_AERO)
6969
character(len=256) :: spc_flist(N_AERO),spc_fname(N_AERO)
70+
logical :: dist(N_AERO)
7071

7172
contains
7273

74+
subroutine get_aircraft(cnt, spc_name_list_out)
75+
integer, intent(out) :: cnt
76+
character(len=16), optional, intent(out) :: spc_name_list_out(N_AERO)
77+
integer :: i
78+
79+
spc_name_list_out = ''
80+
81+
cnt = aircraft_cnt
82+
if( cnt>0 ) then
83+
do i=1,cnt
84+
spc_name_list_out(i) = spc_name_list(i)
85+
end do
86+
end if
87+
88+
end subroutine get_aircraft
89+
7390
subroutine aircraft_emit_register()
7491

7592
!------------------------------------------------------------------
@@ -90,6 +107,8 @@ subroutine aircraft_emit_register()
90107
!------------------------------------------------------------------
91108
! Return if air_specifier is blank (no aircraft data to process)
92109
!------------------------------------------------------------------
110+
dist(:) = .false.
111+
aircraft_cnt = 0
93112
if (air_specifier(1) == "") return
94113

95114
! count aircraft emission species used in the simulation
@@ -108,6 +127,8 @@ subroutine aircraft_emit_register()
108127
call endrun('aircraft_emit_register: '//trim(spc_name)//' is not in the aircraft emission dataset')
109128
endif
110129

130+
if (trim(spc_name) == 'ac_SLANT_DIST'.or. trim(spc_name) == 'ac_TRACK_DIST') dist(n) = .true.
131+
111132
aircraft_cnt = aircraft_cnt + 1
112133
call pbuf_add_field(aero_names(mm),'physpkg',dtype_r8,(/pcols,pver/),idx)
113134

@@ -189,6 +210,7 @@ subroutine aircraft_emit_init()
189210
forcings_air(m)%file%cyclical_list = .true. ! Aircraft data cycles over the filename list
190211
forcings_air(m)%file%weight_by_lat = .true. ! Aircraft data - interpolated with latitude weighting
191212
forcings_air(m)%file%conserve_column = .true. ! Aircraft data - vertically interpolated to conserve the total column
213+
forcings_air(m)%file%dist = dist(m)
192214
forcings_air(m)%species = spc_name
193215
forcings_air(m)%sectors = spc_name ! Only one species per file for aircraft data
194216
forcings_air(m)%nsectors = 1
@@ -314,6 +336,8 @@ subroutine aircraft_emit_adv( state, pbuf2d)
314336
caseid = 4
315337
case ('kg m-2 s-1')
316338
caseid = 5
339+
case ('m/sec' )
340+
caseid = 6
317341
case default
318342
print*, 'aircraft_emit_adv: units = ',trim(forcings_air(m)%fields(i)%units) ,' are not recognized'
319343
call endrun('aircraft_emit_adv: units are not recognized')
@@ -339,6 +363,8 @@ subroutine aircraft_emit_adv( state, pbuf2d)
339363
to_mmr(:ncol,:) = 1.0_r8
340364
elseif (caseid == 5) then
341365
to_mmr(:ncol,:) = 1.0_r8
366+
elseif (caseid == 6) then
367+
to_mmr(:ncol,:) = 1.0_r8
342368
else
343369
to_mmr(:ncol,:) = molmass(ind)/mwdry
344370
endif

src/chemistry/utils/horizontal_interpolate.F90

Lines changed: 54 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ module horizontal_interpolate
1717
public :: xy_interp_init, xy_interp
1818

1919
contains
20-
subroutine xy_interp_init(im1,jm1,lon0,lat0,im2,jm2,weight_x,weight_y)
20+
subroutine xy_interp_init(im1,jm1,lon0,lat0,im2,jm2,weight_x,weight_y,use_flight_distance)
2121
!------------------------------------------------------------------------------------------------------------
2222
! This program computes weighting functions to map a variable of (im1,jm1) resolution to (im2,jm2) resolution
2323
! weight_x(im2,im1) is the weighting function for zonal interpolation
@@ -28,6 +28,7 @@ subroutine xy_interp_init(im1,jm1,lon0,lat0,im2,jm2,weight_x,weight_y)
2828
!------------------------------------------------------------------------------------------------------------
2929
implicit none
3030
integer, intent(in) :: im1, jm1, im2, jm2
31+
logical, intent(in) :: use_flight_distance !.true. = flight distance, .false. = all mixing ratios
3132
real(r8), intent(in) :: lon0(im1), lat0(jm1)
3233
real(r8), intent(out) :: weight_x(im2,im1), weight_y(jm2,jm1)
3334

@@ -110,28 +111,40 @@ subroutine xy_interp_init(im1,jm1,lon0,lat0,im2,jm2,weight_x,weight_y)
110111
! check if there is any overlap between the source grid and the target grid
111112
! if no overlap, then weighting is zero
112113
! there are three scenarios overlaps can take place
113-
if( (x1_west.ge.x2_west).and.(x1_east.le.x2_east) ) then
114+
if( (x1_west>=x2_west).and.(x1_east<=x2_east) ) then
114115
! case 1:
115116
! x1_west x1_east
116117
! |-------------------|
117118
! |---------------------------------|
118119
! x2_west x2_east
120+
if(use_flight_distance) then
121+
weight_x(i2,i1) = 1.0_r8
122+
else
119123
weight_x(i2,i1) = (x1_east-x1_west)/(x2_east-x2_west)
120-
elseif ( (x1_west.ge.x2_west).and.(x1_west.lt.x2_east) ) then
124+
endif
125+
elseif ( (x1_west>=x2_west).and.(x1_west<x2_east) ) then
121126
! case 2:
122127
! x1_west x1_east
123128
! |--------------------------------|
124129
! |---------------------------------|
125130
! x2_west x2_east
131+
if(use_flight_distance) then
132+
weight_x(i2,i1) = (x2_east-x1_west)/(x1_east-x1_west)
133+
else
126134
weight_x(i2,i1) = (x2_east-x1_west)/(x2_east-x2_west)
127-
elseif ( (x1_east>x2_west).and.(x1_east.le.x2_east) ) then
135+
endif
136+
elseif ( (x1_east>x2_west).and.(x1_east<=x2_east) ) then
128137
! case 3:
129138
! x1_west x1_east
130139
! |--------------------------------|
131140
! |---------------------------------|
132141
! x2_west x2_east
142+
if(use_flight_distance) then
143+
weight_x(i2,i1) = (x1_east-x2_west)/(x1_east-x1_west)
144+
else
133145
weight_x(i2,i1) = (x1_east-x2_west)/(x2_east-x2_west)
134-
elseif ( (x1_east.gt.x2_east).and.(x1_west.lt.x2_west) ) then
146+
endif
147+
elseif ( (x1_east>x2_east).and.(x1_west<x2_west) ) then
135148
! case 4:
136149
! x1_west x1_east
137150
! |--------------------------------|
@@ -145,22 +158,30 @@ subroutine xy_interp_init(im1,jm1,lon0,lat0,im2,jm2,weight_x,weight_y)
145158

146159

147160
! consider end points
148-
if(slon1(im1+1).gt.slon2(im2+1)) then
161+
if(slon1(im1+1)>slon2(im2+1)) then
149162
! case 1:
150163
! slon1(im1) slon1(im1+1) <--- end point
151164
! |-------------------------|
152165
! |----------------|......................|
153166
! slon2(im2) slon2(im2+1) slon2(2) (note: slon2(im2+1) = slon2(1))
154-
weight_x(1,im1)= weight_x(1,im1)+(slon1(im1+1)-slon2(im2+1))/(slon2(2)-slon2(1))
167+
if(use_flight_distance) then
168+
weight_x(1,im1)= weight_x(1,im1)+(slon1(im1+1)-slon2(im2+1))/(slon1(im1+1)-slon1(im1))
169+
else
170+
weight_x(1,im1)= weight_x(1,im1)+(slon1(im1+1)-slon2(im2+1))/(slon2(2)-slon2(1))
171+
endif
155172
endif
156173

157-
if(slon1(im1+1).lt.slon2(im2+1)) then
174+
if(slon1(im1+1)<slon2(im2+1)) then
158175
! case 1:
159176
! slon1(im1) slon1(im1+1) slon1(2) (note: slon1(im1+1) = slon1(1))
160177
! |-------------------------|.............................|
161178
! |-------------------------------|
162179
! slon2(im2) slon2(im2+1) <--- end point
163-
weight_x(im2,1) = weight_x(im2,1)+(slon2(1)-slon1(1))/(slon2(2)-slon2(1))
180+
if(use_flight_distance) then
181+
weight_x(im2,1) = weight_x(im2,1)+(slon2(1)-slon1(1))/(slon1(2)-slon1(1))
182+
else
183+
weight_x(im2,1) = weight_x(im2,1)+(slon2(1)-slon1(1))/(slon2(2)-slon2(1))
184+
endif
164185
endif
165186

166187

@@ -181,34 +202,50 @@ subroutine xy_interp_init(im1,jm1,lon0,lat0,im2,jm2,weight_x,weight_y)
181202
! there are three scenarios overlaps can take place
182203
! note: there is Guassian weight to consider in the meridional direction!
183204

184-
if( (y1_south.ge.y2_south).and.(y1_north.le.y2_north) ) then
205+
if( (y1_south>=y2_south).and.(y1_north<=y2_north) ) then
185206
! case 1:
186207
! y1_south y1_north
187208
! |-------------------|
188209
! |---------------------------------|
189210
! y2_south y2_north
190-
weight_y(j2,j1) = gw1(j1)/gw2(j2)
191-
elseif ( (y1_south.ge.y2_south).and.(y1_south.lt.y2_north) ) then
211+
if(use_flight_distance) then
212+
weight_y(j2,j1) = 1.0_r8
213+
else
214+
weight_y(j2,j1) = gw1(j1)/gw2(j2)
215+
endif
216+
elseif ( (y1_south>=y2_south).and.(y1_south<y2_north) ) then
192217
! case 2:
193218
! y1_south y1_north
194219
! |--------------------------------|
195220
! |---------------------------------|
196221
! y2_south y2_north
197-
weight_y(j2,j1) = (y2_north-y1_south)/(y1_north-y1_south)*gw1(j1)/gw2(j2)
198-
elseif ( (y1_north.gt.y2_south).and.(y1_north.le.y2_north) ) then
222+
if(use_flight_distance) then
223+
weight_y(j2,j1) = (y2_north-y1_south)/(y1_north-y1_south)
224+
else
225+
weight_y(j2,j1) = (y2_north-y1_south)/(y1_north-y1_south)*gw1(j1)/gw2(j2)
226+
endif
227+
elseif ( (y1_north>y2_south).and.(y1_north<=y2_north) ) then
199228
! case 3:
200229
! y1_south y1_north
201230
! |--------------------------------|
202231
! |---------------------------------|
203232
! y2_south y2_north
204-
weight_y(j2,j1) = (y1_north-y2_south)/(y1_north-y1_south)*gw1(j1)/gw2(j2)
205-
elseif ( (y1_north.gt.y2_north).and.(y1_south.lt.y2_south) ) then
233+
if(use_flight_distance) then
234+
weight_y(j2,j1) = (y1_north-y2_south)/(y1_north-y1_south)
235+
else
236+
weight_y(j2,j1) = (y1_north-y2_south)/(y1_north-y1_south)*gw1(j1)/gw2(j2)
237+
endif
238+
elseif ( (y1_north>y2_north).and.(y1_south<y2_south) ) then
206239
! case 4:
207240
! y1_south y1_north
208241
! |--------------------------------|
209242
! |---------------------|
210243
! y2_south y2_north
211-
weight_y(j2,j1) = gw1(j1)/gw2(j2)
244+
if(use_flight_distance) then
245+
weight_y(j2,j1) = 1._r8
246+
else
247+
weight_y(j2,j1) = gw1(j1)/gw2(j2)
248+
endif
212249
endif
213250

214251
enddo

0 commit comments

Comments
 (0)