Line data Source code
1 : module modal_aero_deposition
2 :
3 : !------------------------------------------------------------------------------------------------
4 : ! Purpose:
5 : !
6 : ! Partition the contributions from modal components of wet and dry
7 : ! deposition at the surface into the fields passed to the coupler.
8 : !
9 : ! *** N.B. *** Currently only a simple scheme for the 3-mode version
10 : ! of MAM has been implemented.
11 : !
12 : ! Revision history:
13 : ! Feb 2009 M. Flanner, B. Eaton Original version for trop_mam3.
14 : ! Jul 2011 F Vitt -- made avaliable to be used in a prescribed modal aerosol mode (no prognostic MAM)
15 : ! Mar 2012 F Vitt -- made changes for to prevent abort when 7-mode aeroslol model is used
16 : ! some of the needed consituents do not exist in 7-mode so bin_fluxes will be false
17 : ! May 2014 F Vitt -- included contributions from MAM4 aerosols and added soa_a2 to the ocphiwet fluxes
18 : !------------------------------------------------------------------------------------------------
19 :
20 : use shr_kind_mod, only: r8 => shr_kind_r8
21 : use camsrfexch, only: cam_out_t
22 : use constituents, only: cnst_get_ind, pcnst
23 : use cam_abortutils, only: endrun
24 : use rad_constituents, only: rad_cnst_get_info
25 :
26 : implicit none
27 : private
28 : save
29 :
30 : public :: &
31 : modal_aero_deposition_init, &
32 : set_srf_drydep, &
33 : set_srf_wetdep
34 :
35 : ! Private module data
36 :
37 : logical :: initialized = .false.
38 : integer :: bcphi_ndx( pcnst ) = -1
39 : integer :: bcpho_ndx( pcnst ) = -1
40 : integer :: ocphi_ndx( pcnst ) = -1
41 : integer :: ocpho_ndx( pcnst ) = -1
42 : integer :: crse_dust_ndx( pcnst ) = -1
43 : integer :: fine_dust_ndx( pcnst ) = -1
44 : integer :: bcphi_cnt = 0
45 : integer :: ocphi_cnt = 0
46 : integer :: bcpho_cnt = 0
47 : integer :: ocpho_cnt = 0
48 : integer :: crse_dust_cnt = 0
49 : integer :: fine_dust_cnt = 0
50 :
51 : !==============================================================================
52 : contains
53 : !==============================================================================
54 :
55 0 : subroutine modal_aero_deposition_init( bcphi_indices, bcpho_indices, ocphi_indices, &
56 0 : ocpho_indices, fine_dust_indices, crse_dust_indices )
57 :
58 : ! set aerosol indices for re-mapping surface deposition fluxes:
59 : ! *_a1 = accumulation mode
60 : ! *_a2 = aitken mode
61 : ! *_a3 = coarse mode
62 :
63 : ! can be initialized with user specified indices
64 : ! if called from aerodep_flx module (for prescribed modal aerosol fluxes) then these indices are specified
65 : integer, optional, intent(in) :: bcphi_indices(:) ! hydrophilic black carbon
66 : integer, optional, intent(in) :: bcpho_indices(:) ! hydrophobic black carbon
67 : integer, optional, intent(in) :: ocphi_indices(:) ! hydrophilic organic carbon
68 : integer, optional, intent(in) :: ocpho_indices(:) ! hydrophobic organic carbon
69 : integer, optional, intent(in) :: fine_dust_indices(:) ! fine dust
70 : integer, optional, intent(in) :: crse_dust_indices(:) ! coarse dust
71 :
72 : ! local vars
73 : integer :: i, pcnt, scnt
74 :
75 : character(len=16), parameter :: fine_dust_modes(2) = (/ 'accum ', 'fine_dust '/)
76 : character(len=16), parameter :: crse_dust_modes(2) = (/ 'coarse ', 'coarse_dust '/)
77 : character(len=16), parameter :: hydrophilic_carbon_modes(1) = (/'accum '/)
78 : character(len=16), parameter :: hydrophobic_carbon_modes(3) = (/'aitken ', 'coarse ', 'primary_carbon '/)
79 :
80 : ! if already initialized abort the run
81 0 : if (initialized) then
82 0 : call endrun('modal_aero_deposition is already initialized')
83 : endif
84 :
85 0 : if (present(bcphi_indices)) then
86 0 : bcphi_cnt = size(bcphi_indices)
87 0 : bcphi_ndx(1:bcphi_cnt) = bcphi_indices (1:bcphi_cnt)
88 : else
89 0 : call get_indices( type='black-c', modes=hydrophilic_carbon_modes, indices=bcphi_ndx, count=bcphi_cnt )
90 : endif
91 0 : if (present(bcpho_indices)) then
92 0 : bcpho_cnt = size(bcpho_indices)
93 0 : bcpho_ndx(1:bcpho_cnt) = bcpho_indices (1:bcpho_cnt)
94 : else
95 0 : call get_indices( type='black-c', modes=hydrophobic_carbon_modes, indices=bcpho_ndx, count=bcpho_cnt )
96 : endif
97 :
98 0 : if (present(ocphi_indices)) then
99 0 : ocphi_cnt = size(ocphi_indices)
100 0 : ocphi_ndx(1:ocphi_cnt) = ocphi_indices (1:ocphi_cnt)
101 : else
102 0 : call get_indices( type='s-organic', modes=hydrophilic_carbon_modes, indices=ocphi_ndx, count=pcnt )
103 0 : call get_indices( type='p-organic', modes=hydrophilic_carbon_modes, indices=ocphi_ndx(pcnt+1:), count=scnt )
104 0 : ocphi_cnt = pcnt+scnt
105 : endif
106 0 : if (present(ocpho_indices)) then
107 0 : ocpho_cnt = size(ocpho_indices)
108 0 : ocpho_ndx(1:ocpho_cnt) = ocpho_indices (1:ocpho_cnt)
109 : else
110 0 : call get_indices( type='s-organic', modes=hydrophobic_carbon_modes, indices=ocpho_ndx, count=pcnt )
111 0 : call get_indices( type='p-organic', modes=hydrophobic_carbon_modes, indices=ocpho_ndx(pcnt+1:), count=scnt )
112 0 : ocpho_cnt = pcnt+scnt
113 : endif
114 :
115 0 : if (present(fine_dust_indices)) then
116 0 : fine_dust_cnt = size(fine_dust_indices)
117 0 : fine_dust_ndx(1:fine_dust_cnt) = fine_dust_indices(1:fine_dust_cnt)
118 : else
119 0 : call get_indices( type='dust', modes=fine_dust_modes, indices=fine_dust_ndx, count=fine_dust_cnt )
120 : endif
121 0 : if (present(crse_dust_indices)) then
122 0 : crse_dust_cnt = size(crse_dust_indices)
123 0 : crse_dust_ndx(1:crse_dust_cnt) = crse_dust_indices(1:crse_dust_cnt)
124 : else
125 0 : call get_indices( type='dust', modes=crse_dust_modes, indices=crse_dust_ndx, count=crse_dust_cnt )
126 : endif
127 :
128 0 : initialized = .true.
129 :
130 0 : end subroutine modal_aero_deposition_init
131 :
132 : !==============================================================================
133 0 : subroutine set_srf_wetdep(aerdepwetis, aerdepwetcw, cam_out)
134 :
135 : ! Set surface wet deposition fluxes passed to coupler.
136 :
137 : ! Arguments:
138 : real(r8), intent(in) :: aerdepwetis(:,:) ! aerosol wet deposition (interstitial)
139 : real(r8), intent(in) :: aerdepwetcw(:,:) ! aerosol wet deposition (cloud water)
140 : type(cam_out_t), intent(inout) :: cam_out ! cam export state
141 :
142 : ! Local variables:
143 : integer :: i, ispec, idx
144 : integer :: ncol ! number of columns
145 :
146 : real(r8) :: bcphiwet_sum, ocphiwet_sum
147 : !----------------------------------------------------------------------------
148 :
149 0 : if (.not.initialized) call endrun('set_srf_wetdep: modal_aero_deposition has not been initialized')
150 :
151 0 : ncol = cam_out%ncol
152 :
153 0 : cam_out%bcphiwet(:) = 0._r8
154 0 : cam_out%ocphiwet(:) = 0._r8
155 :
156 : ! derive cam_out variables from deposition fluxes
157 : ! note: wet deposition fluxes are negative into surface,
158 : ! dry deposition fluxes are positive into surface.
159 : ! srf models want positive definite fluxes.
160 0 : do i = 1, ncol
161 :
162 : ! black carbon fluxes
163 0 : do ispec=1,bcphi_cnt
164 0 : cam_out%bcphiwet(i) = cam_out%bcphiwet(i) &
165 0 : - (aerdepwetis(i,bcphi_ndx(ispec))+aerdepwetcw(i,bcphi_ndx(ispec)))
166 : enddo
167 0 : do ispec=1,bcpho_cnt
168 0 : cam_out%bcphiwet(i) = cam_out%bcphiwet(i) &
169 0 : - (aerdepwetis(i,bcpho_ndx(ispec))+aerdepwetcw(i,bcpho_ndx(ispec)))
170 : enddo
171 :
172 : ! organic carbon fluxes
173 0 : do ispec=1,ocphi_cnt
174 0 : cam_out%ocphiwet(i) = cam_out%ocphiwet(i) &
175 0 : - (aerdepwetis(i,ocphi_ndx(ispec))+aerdepwetcw(i,ocphi_ndx(ispec)))
176 : enddo
177 0 : do ispec=1,ocpho_cnt
178 0 : cam_out%ocphiwet(i) = cam_out%ocphiwet(i) &
179 0 : - (aerdepwetis(i,ocpho_ndx(ispec))+aerdepwetcw(i,ocpho_ndx(ispec)))
180 : enddo
181 :
182 : ! dust fluxes
183 0 : cam_out%dstwet1(i) = 0._r8
184 0 : cam_out%dstwet2(i) = 0._r8
185 0 : cam_out%dstwet3(i) = 0._r8
186 0 : cam_out%dstwet4(i) = 0._r8
187 :
188 : ! bulk bin1 (fine) dust deposition equals accumulation mode deposition:
189 0 : do ispec=1,fine_dust_cnt
190 : cam_out%dstwet1(i) = cam_out%dstwet1(i) &
191 0 : -(aerdepwetis(i,fine_dust_ndx(ispec))+aerdepwetcw(i,fine_dust_ndx(ispec)))
192 : enddo
193 :
194 : ! Assign all coarse-mode dust to bulk size bin 3:
195 0 : do ispec=1,crse_dust_cnt
196 : cam_out%dstwet3(i) = cam_out%dstwet3(i) &
197 0 : -(aerdepwetis(i,crse_dust_ndx(ispec))+aerdepwetcw(i,crse_dust_ndx(ispec)))
198 : enddo
199 :
200 : ! in rare cases, integrated deposition tendency is upward
201 0 : if (cam_out%bcphiwet(i) .lt. 0._r8) cam_out%bcphiwet(i) = 0._r8
202 0 : if (cam_out%ocphiwet(i) .lt. 0._r8) cam_out%ocphiwet(i) = 0._r8
203 0 : if (cam_out%dstwet1(i) .lt. 0._r8) cam_out%dstwet1(i) = 0._r8
204 0 : if (cam_out%dstwet3(i) .lt. 0._r8) cam_out%dstwet3(i) = 0._r8
205 : enddo
206 :
207 0 : end subroutine set_srf_wetdep
208 :
209 : !==============================================================================
210 :
211 0 : subroutine set_srf_drydep(aerdepdryis, aerdepdrycw, cam_out)
212 :
213 : ! Set surface dry deposition fluxes passed to coupler.
214 :
215 : ! Arguments:
216 : real(r8), intent(in) :: aerdepdryis(:,:) ! aerosol dry deposition (interstitial)
217 : real(r8), intent(in) :: aerdepdrycw(:,:) ! aerosol dry deposition (cloud water)
218 : type(cam_out_t), intent(inout) :: cam_out ! cam export state
219 :
220 : ! Local variables:
221 : integer :: i, ispec, idx
222 : integer :: ncol ! number of columns
223 : real(r8):: bcphidry_sum, ocphidry_sum, ocphodry_sum
224 : !----------------------------------------------------------------------------
225 :
226 0 : if (.not.initialized) call endrun('set_srf_drydep: modal_aero_deposition has not been initialized')
227 :
228 0 : ncol = cam_out%ncol
229 :
230 0 : cam_out%bcphidry(:) = 0._r8
231 0 : cam_out%bcphodry(:) = 0._r8
232 0 : cam_out%ocphidry(:) = 0._r8
233 0 : cam_out%ocphodry(:) = 0._r8
234 :
235 : ! derive cam_out variables from deposition fluxes
236 : ! note: wet deposition fluxes are negative into surface,
237 : ! dry deposition fluxes are positive into surface.
238 : ! srf models want positive definite fluxes.
239 0 : do i = 1, ncol
240 :
241 : ! black carbon fluxes
242 0 : do ispec=1,bcphi_cnt
243 0 : cam_out%bcphidry(i) = cam_out%bcphidry(i) &
244 0 : + (aerdepdryis(i,bcphi_ndx(ispec))+aerdepdrycw(i,bcphi_ndx(ispec)))
245 : enddo
246 0 : do ispec=1,bcpho_cnt
247 0 : cam_out%bcphodry(i) = cam_out%bcphodry(i) &
248 0 : + (aerdepdryis(i,bcpho_ndx(ispec))+aerdepdrycw(i,bcpho_ndx(ispec)))
249 : enddo
250 :
251 : ! organic carbon fluxes
252 0 : do ispec=1,ocphi_cnt
253 0 : cam_out%ocphidry(i) = cam_out%ocphidry(i) &
254 0 : + (aerdepdryis(i,ocphi_ndx(ispec))+aerdepdrycw(i,ocphi_ndx(ispec)))
255 : enddo
256 0 : do ispec=1,ocpho_cnt
257 0 : cam_out%ocphodry(i) = cam_out%ocphodry(i) &
258 0 : + (aerdepdryis(i,ocpho_ndx(ispec))+aerdepdrycw(i,ocpho_ndx(ispec)))
259 : enddo
260 :
261 : ! dust fluxes
262 0 : cam_out%dstdry1(i) = 0._r8
263 0 : cam_out%dstdry2(i) = 0._r8
264 0 : cam_out%dstdry3(i) = 0._r8
265 0 : cam_out%dstdry4(i) = 0._r8
266 : ! bulk bin1 (fine) dust deposition equals accumulation mode deposition:
267 0 : do ispec=1,fine_dust_cnt
268 : cam_out%dstdry1(i) = cam_out%dstdry1(i) &
269 0 : + (aerdepdryis(i,fine_dust_ndx(ispec))+aerdepdrycw(i,fine_dust_ndx(ispec)))
270 : enddo
271 : ! Assign all coarse-mode dust to bulk size bin 3:
272 0 : do ispec=1,crse_dust_cnt
273 : cam_out%dstdry3(i) = cam_out%dstdry3(i) &
274 0 : + (aerdepdryis(i,crse_dust_ndx(ispec))+aerdepdrycw(i,crse_dust_ndx(ispec)))
275 : enddo
276 :
277 : ! in rare cases, integrated deposition tendency is upward
278 0 : if (cam_out%bcphidry(i) .lt. 0._r8) cam_out%bcphidry(i) = 0._r8
279 0 : if (cam_out%bcphodry(i) .lt. 0._r8) cam_out%bcphodry(i) = 0._r8
280 0 : if (cam_out%ocphidry(i) .lt. 0._r8) cam_out%ocphidry(i) = 0._r8
281 0 : if (cam_out%ocphodry(i) .lt. 0._r8) cam_out%ocphodry(i) = 0._r8
282 0 : if (cam_out%dstdry1(i) .lt. 0._r8) cam_out%dstdry1(i) = 0._r8
283 0 : if (cam_out%dstdry3(i) .lt. 0._r8) cam_out%dstdry3(i) = 0._r8
284 : enddo
285 :
286 0 : end subroutine set_srf_drydep
287 :
288 : !==============================================================================
289 0 : subroutine get_indices( type, modes, indices, count )
290 :
291 : character(len=*), intent(in) :: type
292 : character(len=*), intent(in) :: modes(:)
293 : integer, intent(out) :: indices(:)
294 : integer, intent(out) :: count
295 :
296 : integer :: l, n, ndx, nmodes, nspec
297 : character(len=32) :: spec_type, spec_name, mode_type
298 :
299 0 : call rad_cnst_get_info(0, nmodes=nmodes)
300 :
301 0 : count = 0
302 0 : indices(:) = -1
303 :
304 0 : if (nmodes==7) return ! historically turned off for mam7
305 :
306 0 : do n = 1, nmodes
307 :
308 0 : call rad_cnst_get_info(0, n, mode_type=mode_type, nspec=nspec)
309 :
310 0 : if ( any(modes==trim(mode_type)) ) then
311 :
312 0 : do l = 1,nspec
313 0 : call rad_cnst_get_info(0, n, l, spec_type=spec_type, spec_name=spec_name)
314 0 : call cnst_get_ind(spec_name, ndx, abort=.false.)
315 0 : if (ndx>0) then
316 0 : if (trim(spec_type) == trim(type)) then
317 0 : count = count+1
318 0 : indices(count) = ndx
319 : endif
320 : endif
321 : enddo
322 :
323 : endif
324 :
325 : enddo
326 :
327 : end subroutine get_indices
328 : !==============================================================================
329 :
330 : end module modal_aero_deposition
|