Line data Source code
1 : module dpie_coupling
2 : !
3 : ! Dynamics/Physics Ionosphere/Electrodynamics coupler.
4 : !
5 : use shr_kind_mod, only: r8 => shr_kind_r8
6 : use cam_logfile, only: iulog
7 : use cam_history, only: hist_fld_active, outfld
8 : use cam_history, only: addfld, horiz_only
9 : use cam_history_support, only: fillvalue
10 : use cam_abortutils, only: endrun
11 : use spmd_utils, only: masterproc, mpi_logical, mpicom, masterprocid
12 : use edyn_mpi, only: array_ptr_type
13 : use perf_mod, only: t_startf, t_stopf
14 : use amie_module, only: getamie
15 : use ltr_module, only: getltr
16 : use edyn_solve, only: phihm
17 : use edyn_params, only: dtr, rtd
18 : use aurora_params, only: prescribed_period ! turns on overwrite of energy fields in aurora phys
19 :
20 : implicit none
21 :
22 : private
23 : public :: d_pie_init
24 : public :: d_pie_epotent ! sets electric potential
25 : public :: d_pie_coupling ! handles coupling with edynamo and ion transport
26 :
27 : logical :: ionos_edyn_active ! if true, call oplus_xport for O+ transport
28 : logical :: ionos_oplus_xport ! if true, call oplus_xport for O+ transport
29 : integer :: nspltop ! nsplit for oplus_xport
30 :
31 : logical :: debug = .false.
32 :
33 : real(r8) :: crad(2), crit(2)
34 : logical :: crit_user_set = .false.
35 : real(r8), parameter :: amie_default_crit(2) = (/ 35._r8, 40._r8 /)
36 :
37 : logical :: debug_hist
38 :
39 : contains
40 : !----------------------------------------------------------------------
41 768 : subroutine d_pie_init( edyn_active_in, oplus_xport_in, oplus_nsplit_in, crit_colats_deg, ionos_debug_hist )
42 :
43 : logical, intent(in) :: edyn_active_in, oplus_xport_in
44 : integer, intent(in) :: oplus_nsplit_in
45 : real(r8),intent(in) :: crit_colats_deg(:)
46 : logical, intent(in) :: ionos_debug_hist
47 :
48 768 : debug_hist = ionos_debug_hist
49 :
50 768 : ionos_edyn_active = edyn_active_in
51 768 : ionos_oplus_xport = oplus_xport_in
52 768 : nspltop = oplus_nsplit_in
53 :
54 768 : crit_user_set = all( crit_colats_deg(:) > 0._r8 )
55 768 : if (crit_user_set) then
56 0 : crit(:) = crit_colats_deg(:)*dtr
57 : end if
58 :
59 768 : call addfld ('HMF2' , horiz_only , 'I', 'km' ,'Height of the F2 Layer' , gridname='physgrid')
60 768 : call addfld ('NMF2' , horiz_only , 'I', 'cm-3','Peak Density of the F2 Layer', gridname='physgrid')
61 :
62 1536 : call addfld ('OpDens' ,(/ 'lev' /), 'I', 'cm^-3','O+ Number Density' , gridname='physgrid')
63 1536 : call addfld ('EDens' ,(/ 'lev' /), 'I', 'cm^-3','e Number Density (sum of O2+,NO+,N2+,O+)', gridname='physgrid')
64 :
65 768 : call addfld ('prescr_efxp' , horiz_only, 'I','mW/m2','Prescribed energy flux on geo grid' ,gridname='physgrid')
66 768 : call addfld ('prescr_kevp' , horiz_only, 'I','keV ','Prescribed mean energy on geo grid' ,gridname='physgrid')
67 :
68 768 : call addfld ('prescr_phihm' , horiz_only, 'I','VOLTS','Prescribed Electric Potential-mag grid' ,gridname='gmag_grid')
69 768 : call addfld ('prescr_efxm' , horiz_only, 'I','mW/m2','Prescribed energy flux on mag grid' ,gridname='gmag_grid')
70 768 : call addfld ('prescr_kevm' , horiz_only, 'I','keV ','Prescribed mean energy on mag grid' ,gridname='gmag_grid')
71 :
72 768 : if (debug_hist) then
73 : ! Dynamo inputs (called from dpie_coupling. Fields are in waccm format, in CGS units):
74 0 : call addfld ('DPIE_OMEGA',(/ 'lev' /), 'I', 'Pa/s ','OMEGA input to DPIE coupling', gridname='physgrid')
75 0 : call addfld ('DPIE_MBAR' ,(/ 'lev' /), 'I', 'kg/kmole','MBAR Mean Mass from dpie_coupling', gridname='physgrid')
76 0 : call addfld ('DPIE_TN ',(/ 'lev' /), 'I', 'deg K ','DPIE_TN' , gridname='physgrid')
77 0 : call addfld ('DPIE_UN ',(/ 'lev' /), 'I', 'cm/s ','DPIE_UN' , gridname='physgrid')
78 0 : call addfld ('DPIE_VN ',(/ 'lev' /), 'I', 'cm/s ','DPIE_VN' , gridname='physgrid')
79 0 : call addfld ('DPIE_WN ',(/ 'lev' /), 'I', 'cm/s ','DPIE_WN' , gridname='physgrid')
80 0 : call addfld ('DPIE_OM ',(/ 'lev' /), 'I', 's-1 ','DPIE_OM' , gridname='physgrid')
81 0 : call addfld ('DPIE_ZHT ',(/ 'lev' /), 'I', 'cm ','DPIE_ZHT (geometric height,simple)', gridname='physgrid')
82 0 : call addfld ('DPIE_ZGI ',(/ 'lev' /), 'I', 'cm ','DPIE_ZGI (geopotential height on interfaces)', gridname='physgrid')
83 0 : call addfld ('DPIE_O2 ',(/ 'lev' /), 'I', 'mmr ','DPIE_O2' , gridname='physgrid')
84 0 : call addfld ('DPIE_O ',(/ 'lev' /), 'I', 'mmr ','DPIE_O' , gridname='physgrid')
85 0 : call addfld ('DPIE_N2 ',(/ 'lev' /), 'I', 'mmr ','DPIE_N2' , gridname='physgrid')
86 0 : call addfld ('DPIE_TE ',(/ 'lev' /), 'I', 'deg K ','DPIE_TE' , gridname='physgrid')
87 0 : call addfld ('DPIE_TI ',(/ 'lev' /), 'I', 'deg K ','DPIE_TI' , gridname='physgrid')
88 :
89 0 : call addfld ('PED_phys',(/ 'lev' /), 'I', 'S/m','Pedersen Conductivity' , gridname='physgrid')
90 0 : call addfld ('HAL_phys',(/ 'lev' /), 'I', 'S/m','Hall Conductivity' , gridname='physgrid')
91 :
92 0 : call addfld ('DPIE_OPMMR' ,(/ 'lev' /), 'I', 'mmr' ,'DPIE_OPMMR' , gridname='physgrid')
93 0 : call addfld ('DPIE_O2P',(/ 'lev' /), 'I', 'm^-3','DPIE_O2P(dpie input)', gridname='physgrid')
94 0 : call addfld ('DPIE_NOP',(/ 'lev' /), 'I', 'm^-3','DPIE_NOP(dpie input)', gridname='physgrid')
95 0 : call addfld ('DPIE_N2P',(/ 'lev' /), 'I', 'm^-3','DPIE_N2P(dpie input)', gridname='physgrid')
96 :
97 0 : call addfld ('WACCM_UI' ,(/ 'lev' /), 'I', 'm/s' ,'WACCM_UI (dpie output)', gridname='physgrid')
98 0 : call addfld ('WACCM_VI' ,(/ 'lev' /), 'I', 'm/s' ,'WACCM_VI (dpie output)', gridname='physgrid')
99 0 : call addfld ('WACCM_WI' ,(/ 'lev' /), 'I', 'm/s' ,'WACCM_WI (dpie output)', gridname='physgrid')
100 0 : call addfld ('WACCM_OP' ,(/ 'lev' /), 'I', 'kg/kg' ,'WACCM_OP (dpie output)', gridname='physgrid')
101 :
102 0 : call addfld ('EDYN_ADOTV1 ', (/ 'lev' /), 'I', ' ','EDYN_ADOTV1' , gridname='geo_grid')
103 0 : call addfld ('EDYN_ADOTV2 ', (/ 'lev' /), 'I', ' ','EDYN_ADOTV2' , gridname='geo_grid')
104 0 : call addfld ('EDYN_ADOTA1 ', horiz_only , 'I', ' ','EDYN_ADOTA1' , gridname='geo_grid')
105 0 : call addfld ('EDYN_ADOTA2 ', horiz_only , 'I', ' ','EDYN_ADOTA2' , gridname='geo_grid')
106 0 : call addfld ('EDYN_A1DTA2 ', horiz_only , 'I', ' ','EDYN_A1DTA2' , gridname='geo_grid')
107 :
108 0 : call addfld ('EDYN_SINI ', horiz_only , 'I', ' ','EDYN_SINI' , gridname='geo_grid')
109 0 : call addfld ('EDYN_BE3 ', horiz_only , 'I', ' ','EDYN_BE3' , gridname='geo_grid')
110 :
111 0 : call addfld ('ADOTA1_MAG', horiz_only , 'I', ' ','ADOTA1 in geo-mag coords' , gridname='gmag_grid')
112 0 : call addfld ('SINI_MAG', horiz_only , 'I', ' ','sini in geo-mag coords' , gridname='gmag_grid')
113 :
114 0 : call addfld ('OPLUS', (/ 'lev' /), 'I', 'cm^3','O+ (oplus_xport output)', gridname='geo_grid')
115 0 : call addfld ('OPtm1i',(/ 'lev' /), 'I', 'cm^3','O+ (oplus_xport output)', gridname='geo_grid')
116 0 : call addfld ('OPtm1o',(/ 'lev' /), 'I', 'cm^3','O+ (oplus_xport output)', gridname='geo_grid')
117 : endif
118 :
119 768 : end subroutine d_pie_init
120 :
121 : !-----------------------------------------------------------------------
122 8064 : subroutine d_pie_epotent( highlat_potential_model, crit_out, cols, cole, efx_phys, kev_phys, amie_in, ltr_in )
123 : use edyn_solve, only: pfrac ! NH fraction of potential (nmlonp1,nmlat0)
124 : use time_manager, only: get_curr_date
125 : use heelis, only: heelis_model
126 : use wei05sc, only: weimer05 ! driver for weimer high-lat convection model
127 : use edyn_esmf, only: edyn_esmf_update
128 : use solar_parms_data, only: solar_parms_advance
129 : use solar_wind_data, only: solar_wind_advance
130 : use solar_wind_data, only: bzimf=>solar_wind_bzimf
131 : use solar_wind_data, only: byimf=>solar_wind_byimf
132 : use solar_wind_data, only: swvel=>solar_wind_swvel
133 : use solar_wind_data, only: swden=>solar_wind_swden
134 : use edyn_mpi, only: mlat0, mlat1, mlon0, mlon1, omlon1, ntask, mytid
135 : use edyn_maggrid, only: nmlonp1, nmlat
136 : use regridder, only: regrid_mag2phys_2d
137 :
138 : ! Args:
139 : !
140 : character(len=*), intent(in) :: highlat_potential_model
141 : real(r8), intent(out) :: crit_out(2) ! critical colatitudes (degrees)
142 : integer, optional, intent(in) :: cols, cole
143 : logical, optional,intent(in) :: amie_in
144 : logical, optional,intent(in) :: ltr_in
145 :
146 : ! Prescribed energy flux
147 : real(r8), optional, intent(out) :: efx_phys(:)
148 : ! Prescribed characteristic mean energy
149 : real(r8), optional, intent(out) :: kev_phys(:)
150 :
151 : !
152 : ! local vars
153 : !
154 : logical :: amie_inputs, ltr_inputs
155 :
156 : real(r8) :: secs ! time of day in seconds
157 : integer :: iyear,imo,iday,tod ! tod is time-of-day in seconds
158 : real(r8) :: sunlon
159 :
160 : integer :: iprint
161 : integer :: j, iamie, iltr, ierr
162 : !
163 : ! AMIE fields (extra dimension added for longitude switch)
164 : !
165 16128 : real(r8) :: prescr_efxm(nmlonp1,nmlat), prescr_kevm(nmlonp1,nmlat)
166 16128 : real(r8) :: prescr_phihm(nmlonp1,nmlat)
167 :
168 8064 : call edyn_esmf_update()
169 :
170 8064 : call get_curr_date(iyear, imo,iday, tod)
171 : ! tod is integer time-of-day in seconds
172 8064 : secs = real(tod, r8)
173 :
174 : ! update solar wind data (IMF, etc.)
175 8064 : call solar_wind_advance()
176 :
177 : ! update kp -- phys timestep init happens later ...
178 8064 : call solar_parms_advance()
179 8064 : if ( mytid<ntask ) then
180 : !
181 : ! Get sun's longitude at latitudes (geographic):
182 : !
183 8064 : call sunloc(iday, secs, sunlon) ! sunlon is returned
184 : !
185 : ! Get high-latitude convection from empirical model (heelis or weimer).
186 : ! High-latitude potential phihm (edyn_solve) is defined for edynamo.
187 : !
188 8064 : if (trim(highlat_potential_model) == 'heelis') then
189 8064 : call heelis_model(sunlon) ! heelis.F90
190 0 : elseif (trim(highlat_potential_model) == 'weimer') then
191 : !
192 0 : call weimer05(byimf, bzimf, swvel, swden, sunlon)
193 0 : if (debug .and. masterproc) then
194 : write(iulog, "(a,2f8.2,a,2f8.2)") &
195 0 : 'dpie_coupling call weimer05: byimf,bzimf=', &
196 0 : byimf, bzimf, ' swvel,swden=', swvel, swden
197 : end if
198 : else
199 0 : call endrun('d_pie_epotent: Unknown highlat_potential_model')
200 : end if
201 : endif
202 :
203 8064 : amie_inputs=.false.
204 8064 : ltr_inputs=.false.
205 8064 : if (present(amie_in)) amie_inputs=amie_in
206 8064 : if (present(ltr_in)) ltr_inputs= ltr_in
207 :
208 8064 : prescribed_inputs: if (amie_inputs .or. ltr_inputs) then
209 :
210 0 : if (.not. (present(kev_phys).and.present(efx_phys)) ) then
211 0 : call endrun('d_pie_epotent: kev_phys and efx_phys must be present')
212 : end if
213 :
214 0 : iprint = 1
215 0 : if (amie_inputs) then
216 0 : if (masterproc) then
217 0 : write(iulog,*) 'Calling getamie >>> '
218 : end if
219 :
220 : call getamie(iyear, imo, iday, tod, sunlon, iprint, iamie, &
221 0 : prescr_phihm, prescr_efxm, prescr_kevm, crad)
222 :
223 0 : if (masterproc) then
224 0 : write(iulog,"('After Calling getamie >>> iamie = ', i2)") iamie
225 : end if
226 0 : prescribed_period = iamie == 1
227 : else
228 0 : if (masterproc) then
229 0 : write(iulog,*) 'Calling getltr >>> '
230 : end if
231 :
232 : call getltr(iyear, imo, iday, tod,sunlon, iprint, iltr, &
233 0 : prescr_phihm, prescr_efxm, prescr_kevm )
234 :
235 0 : if (masterproc) then
236 0 : write(iulog,"('After Calling getltr >>> iltr = ', i2)") iltr
237 : end if
238 0 : prescribed_period = iltr == 1
239 : end if
240 :
241 0 : do j = mlat0, mlat1
242 0 : call outfld('prescr_phihm',prescr_phihm(mlon0:omlon1,j),omlon1-mlon0+1,j)
243 0 : call outfld('prescr_efxm', prescr_efxm(mlon0:omlon1,j), omlon1-mlon0+1,j)
244 0 : call outfld('prescr_kevm', prescr_kevm(mlon0:omlon1,j), omlon1-mlon0+1,j)
245 : end do
246 :
247 0 : if (prescribed_period) then
248 0 : phihm = prescr_phihm
249 : end if
250 :
251 0 : call mpi_bcast(prescribed_period, 1, mpi_logical, masterprocid, mpicom, ierr)
252 :
253 0 : call regrid_mag2phys_2d(prescr_kevm(mlon0:mlon1,mlat0:mlat1), kev_phys, cols, cole)
254 0 : call regrid_mag2phys_2d(prescr_efxm(mlon0:mlon1,mlat0:mlat1), efx_phys, cols, cole)
255 :
256 0 : call outfld_phys1d( 'prescr_efxp', efx_phys )
257 0 : call outfld_phys1d( 'prescr_kevp', kev_phys )
258 :
259 : end if prescribed_inputs
260 :
261 8064 : if ( mytid<ntask ) then
262 :
263 8064 : call calc_pfrac(sunlon, pfrac) ! returns pfrac for dynamo (edyn_solve)
264 :
265 24192 : crit_out(:) = crit(:)*rtd ! degrees
266 : endif
267 8064 : end subroutine d_pie_epotent
268 :
269 : !-----------------------------------------------------------------------
270 14592 : subroutine d_pie_coupling(omega, pmid, zgi, zht, u, v, tn, &
271 7296 : sigma_ped, sigma_hall, te, ti, mbar, n2mmr, o2mmr, o1mmr, o2pmmr, &
272 7296 : nopmmr, n2pmmr, opmmr, opmmrtm1, ui, vi, wi, &
273 : rmassO2p, rmassNOp, rmassN2p, rmassOp, cols, cole, plev )
274 : !
275 : ! Call dynamo to calculate electric potential and electric field
276 : ! Note: dynamo calculates ion drifts.
277 : ! Then call oplus_xport to transport O+, which is passed back to physics.
278 : !
279 8064 : use edyn_geogrid, only: nlev
280 : use shr_const_mod, only: grav => shr_const_g ! gravitational accel. (m/s^2)
281 : use shr_const_mod, only: kboltz => shr_const_boltz ! Boltzmann const. (J/K/molecule)
282 : use time_manager, only: get_nstep, get_curr_date
283 : use edynamo, only: dynamo
284 : use edyn_mpi, only: mp_geo_halos, mp_pole_halos
285 : ! Mag grid distribution info
286 : use edyn_mpi, only: mlon0, mlon1, mlat0, mlat1, mlev0, mlev1
287 : use edyn_mpi, only: lon0, lon1, lat0, lat1, lev0, lev1, ntask, mytid
288 : use oplus, only: oplus_xport
289 : use ref_pres, only: pref_mid
290 : use regridder, only: regrid_phys2geo_3d, regrid_phys2mag_3d, regrid_geo2phys_3d
291 : use regridder, only: regrid_geo2mag_3d, regrid_geo2mag_2d
292 : use adotv_mod, only: calc_adotv
293 :
294 : !
295 : ! Args:
296 : !
297 : integer,intent(in) :: &
298 : cols, & ! First column (usually 1)
299 : cole, & ! Last column
300 : plev ! Number of levels in physics midpoint fields
301 :
302 : ! Input arguments on physics grid
303 : real(r8), intent(in) :: omega(plev, cols:cole) ! pressure velocity on midpoints (Pa/s) (i,k,j)
304 : real(r8), intent(in) :: pmid(plev, cols:cole) ! pressure at midpoints (Pa)
305 : real(r8), intent(in) :: zgi(plev, cols:cole) ! geopotential height (on interfaces) (m)
306 : real(r8), intent(in) :: zht(plev, cols:cole) ! geometric height (m) (Simple method - interfaces)
307 : real(r8), intent(in) :: u(plev, cols:cole) ! U-wind (m/s)
308 : real(r8), intent(in) :: v(plev, cols:cole) ! V-wind (m/s)
309 : real(r8), intent(in) :: tn(plev, cols:cole) ! neutral temperature (K)
310 : real(r8), intent(in) :: sigma_ped(plev, cols:cole) ! Pedersen conductivity
311 : real(r8), intent(in) :: sigma_hall(plev, cols:cole) ! Hall conductivity
312 : real(r8), intent(in) :: te(plev, cols:cole) ! electron temperature
313 : real(r8), intent(in) :: ti(plev, cols:cole) ! ion temperature
314 : real(r8), intent(in) :: mbar(plev, cols:cole) ! mean molecular weight kg/kmole
315 : real(r8), intent(in) :: n2mmr(plev, cols:cole) ! N2 mass mixing ratio (for oplus)
316 : real(r8), intent(in) :: o2mmr(plev, cols:cole) ! O2 mass mixing ratio (for oplus)
317 : real(r8), intent(in) :: o1mmr(plev, cols:cole) ! O mass mixing ratio (for oplus)
318 : real(r8), intent(in) :: o2pmmr(plev, cols:cole) ! O2+ mass mixing ratio (for oplus)
319 : real(r8), intent(in) :: nopmmr(plev, cols:cole) ! NO+ mass mixing ratio (for oplus)
320 : real(r8), intent(in) :: n2pmmr(plev, cols:cole) ! N2+ mass mixing ratio (for oplus)
321 : real(r8), intent(inout) :: opmmr(plev, cols:cole) ! O+ mass mixing ratio (oplus_xport output)
322 : real(r8), intent(inout) :: opmmrtm1(plev, cols:cole) ! O+ previous time step (oplus_xport output)
323 : real(r8), intent(inout) :: ui(plev, cols:cole) ! zonal ion drift (edynamo or empirical)
324 : real(r8), intent(inout) :: vi(plev, cols:cole) ! meridional ion drift (edynamo or empirical)
325 : real(r8), intent(inout) :: wi(plev, cols:cole) ! vertical ion drift (edynamo or empirical)
326 : real(r8), intent(in) :: rmassO2p ! O2+ molecular weight kg/kmol
327 : real(r8), intent(in) :: rmassNOp ! NO+ molecular weight kg/kmol
328 : real(r8), intent(in) :: rmassN2p ! N2+ molecular weight kg/kmol
329 : real(r8), intent(in) :: rmassOp ! O+ molecular weight kg/kmol
330 : !
331 : ! Local:
332 : !
333 : integer :: i, j, k, kk
334 : integer :: kx ! Vertical index at peak of F2 layer electron density
335 : integer :: nstep
336 : integer :: nfields ! Number of fields for multi-field calls
337 : integer :: iyear,imo,iday,tod ! tod is time-of-day in seconds
338 : integer :: isplit ! loop index
339 :
340 : real(r8) :: secs ! time of day in seconds
341 :
342 : real(r8), parameter :: small = 1.e-25_r8 ! for fields not currently available
343 :
344 14592 : real(r8) :: wn(plev, cols:cole) ! vertical velocity (from omega)
345 14592 : real(r8) :: pmid_inv(nlev) ! inverted reference pressure at midpoints (Pa)
346 :
347 : real(r8),dimension(plev, cols:cole) :: & ! ion number densities (m^3)
348 14592 : o2p, nop, n2p, op, ne, optm1
349 :
350 14592 : real(r8) :: op_in(nlev,lon0:lon1,lat0:lat1)
351 14592 : real(r8) :: optm1_in(nlev,lon0:lon1,lat0:lat1)
352 14592 : real(r8) :: zpot_in(nlev,lon0:lon1,lat0:lat1) ! geopotential height (cm)
353 14592 : real(r8) :: ui_in(nlev,lon0:lon1,lat0:lat1)
354 14592 : real(r8) :: vi_in(nlev,lon0:lon1,lat0:lat1)
355 14592 : real(r8) :: wi_in(nlev,lon0:lon1,lat0:lat1)
356 14592 : real(r8) :: wn_in(nlev,lon0:lon1,lat0:lat1) ! vertical velocity (cm/s)
357 14592 : real(r8) :: op_out(nlev,lon0:lon1,lat0:lat1)
358 14592 : real(r8) :: optm1_out(nlev,lon0:lon1,lat0:lat1)
359 :
360 14592 : real(r8),target :: halo_tn(nlev,lon0-2:lon1+2,lat0-2:lat1+2) ! neutral temperature (deg K)
361 14592 : real(r8),target :: halo_te(nlev,lon0-2:lon1+2,lat0-2:lat1+2) ! electron temperature (deg K)
362 14592 : real(r8),target :: halo_ti(nlev,lon0-2:lon1+2,lat0-2:lat1+2) ! ion temperature (deg K)
363 14592 : real(r8),target :: halo_un(nlev,lon0-2:lon1+2,lat0-2:lat1+2) ! neutral zonal wind (cm/s)
364 14592 : real(r8),target :: halo_vn(nlev,lon0-2:lon1+2,lat0-2:lat1+2) ! neutral meridional wind (cm/s)
365 14592 : real(r8),target :: halo_om(nlev,lon0-2:lon1+2,lat0-2:lat1+2) ! omega (1/s)
366 14592 : real(r8),target :: halo_o2(nlev,lon0-2:lon1+2,lat0-2:lat1+2) ! o2 (mmr)
367 14592 : real(r8),target :: halo_o1(nlev,lon0-2:lon1+2,lat0-2:lat1+2) ! o (mmr)
368 14592 : real(r8),target :: halo_n2(nlev,lon0-2:lon1+2,lat0-2:lat1+2) ! n2 (mmr)
369 14592 : real(r8),target :: halo_mbar(nlev,lon0-2:lon1+2,lat0-2:lat1+2) ! mean molecular weight
370 7296 : real(r8), allocatable :: polesign(:)
371 : !
372 14592 : real(r8) :: nmf2(cols:cole) ! Electron number density at F2 peak (m-3 converted to cm-3)
373 14592 : real(r8) :: hmf2(cols:cole) ! Height of electron number density F2 peak (m converted to km)
374 : real(r8) :: &
375 : height(3), & ! Surrounding heights when locating electron density F2 peak
376 : nde(3) ! Surround densities when locating electron density F2 peak
377 : real(r8) h12,h22,h32,deltx,atx,ax,btx,bx,ctx,cx ! Variables used for weighting when locating F2 peak
378 : !
379 : logical :: do_integrals
380 : !
381 : ! Pointers for multiple-field calls:
382 7296 : type(array_ptr_type),allocatable :: ptrs(:)
383 :
384 : character(len=*), parameter :: subname = 'd_pie_coupling'
385 :
386 : real(r8), dimension(mlon0:mlon1,mlat0:mlat1,mlev0:mlev1) :: & ! 3d fields on mag grid
387 14592 : ped_mag, & ! pedersen conductivity on magnetic grid
388 14592 : hal_mag, & ! hall conductivity on magnetic grid
389 14592 : zpot_mag ! geopotential on magnetic grid
390 :
391 : real(r8), dimension(mlon0:mlon1,mlat0:mlat1,mlev0:mlev1) :: & ! 3d fields on mag grid
392 14592 : ped_mag_in, & ! pedersen conductivity on magnetic grid
393 14592 : hal_mag_in, & ! hall conductivity on magnetic grid
394 14592 : zpot_mag_in ! geopotential on magnetic grid
395 :
396 : real(r8), dimension(lon0:lon1,lat0:lat1,lev0:lev1) :: & ! 3d fields on geo grid
397 14592 : zpot_geo, & ! geopotential on magnetic grid
398 14592 : tn_geo, &
399 14592 : te_geo, &
400 14592 : ti_geo, &
401 14592 : un_geo, &
402 14592 : vn_geo, &
403 14592 : wn_geo, &
404 14592 : ui_geo, &
405 14592 : vi_geo, &
406 14592 : wi_geo, &
407 14592 : omega_geo, &
408 14592 : o2_geo, &
409 14592 : o_geo, &
410 14592 : n2_geo, &
411 14592 : op_geo, &
412 14592 : optm1_geo, &
413 14592 : pmid_geo, &
414 14592 : mbar_geo
415 :
416 : real(r8), dimension(lon0:lon1,lat0:lat1,lev0:lev1) :: &
417 14592 : adotv1_in, adotv2_in
418 : real(r8), dimension(lon0:lon1,lat0:lat1) :: &
419 21888 : adota1_in, adota2_in, a1dta2_in, be3_in, sini_in
420 :
421 : real(r8), dimension(mlon0:mlon1,mlat0:mlat1,mlev0:mlev1) :: &
422 14592 : adotv1_mag, adotv2_mag
423 : real(r8), dimension(mlon0:mlon1,mlat0:mlat1) :: &
424 21888 : adota1_mag, adota2_mag, a1dta2_mag, be3_mag, sini_mag
425 :
426 7296 : call t_startf(subname)
427 :
428 7296 : if (debug .and. masterproc) then
429 :
430 0 : nstep = get_nstep()
431 0 : call get_curr_date(iyear, imo, iday, tod)
432 0 : secs = real(tod, r8)
433 :
434 : write(iulog,"(3a,i8,a,3i5,a,f6.2)") &
435 0 : 'Enter ',subname,': nstep = ',nstep, ', iyear,imo,iday = ', &
436 0 : iyear, imo, iday, ' ut (hrs) = ', secs/3600._r8
437 :
438 0 : write(iulog,"(a,': nspltop = ',i3)") subname, nspltop
439 : end if
440 :
441 : !---------------------------------------------------------------
442 : ! Calculate vertical neutral wind velocity wn(i,j,k).
443 : ! (omega (Pa/s), tn (K), and mbar (kg/kmole) are inputs, grav is m/s^2)
444 : !---------------------------------------------------------------
445 7296 : call calc_wn(tn, omega, pmid, mbar, grav, wn, cols, cole, nlev)
446 :
447 : !---------------------------------------------------------------
448 : ! Convert from mmr to number densities (m^3):
449 : !---------------------------------------------------------------
450 269952 : do i = cols, cole
451 34415232 : do k = 1, nlev
452 : ! O2+, NO+, N2+, O+:
453 68290560 : o2p(k, i) = o2pmmr(k, i) * mbar(k, i) / rmassO2p * &
454 68290560 : pmid(k,i) / (kboltz * tn(k, i))
455 : nop(k, i) = nopmmr(k, i) * mbar(k, i) / rmassNOp * &
456 34145280 : pmid(k,i) / (kboltz * tn(k, i))
457 : n2p(k, i) = n2pmmr(k, i) * mbar(k, i) / rmassN2p * &
458 34145280 : pmid(k,i) / (kboltz * tn(k, i))
459 : op(k, i) = opmmr(k, i) * mbar(k, i) / rmassOp * &
460 34145280 : pmid(k,i) / (kboltz * tn(k, i))
461 : optm1(k, i) = opmmrtm1(k, i) * mbar(k, i) / rmassOp * &
462 34145280 : pmid(k,i) / (kboltz * tn(k, i))
463 34407936 : ne(k, i) = o2p(k,i)+nop(k,i)+n2p(k,i)+op(k,i)
464 : end do
465 : end do ! k=1,nlev
466 :
467 7296 : if (debug_hist) then
468 0 : call outfld_phys('DPIE_TN',tn)
469 0 : call outfld_phys('DPIE_UN',u* 100._r8)
470 0 : call outfld_phys('DPIE_VN',v* 100._r8)
471 0 : call outfld_phys('DPIE_WN',wn* 100._r8)
472 0 : call outfld_phys('DPIE_ZHT',zht* 100._r8)
473 0 : call outfld_phys('DPIE_ZGI',zgi* 100._r8)
474 0 : call outfld_phys('DPIE_MBAR',mbar)
475 :
476 0 : call outfld_phys('DPIE_N2',n2mmr)
477 0 : call outfld_phys('DPIE_O2',o2mmr)
478 0 : call outfld_phys('DPIE_O',o1mmr)
479 :
480 0 : call outfld_phys('DPIE_OMEGA',omega)
481 0 : call outfld_phys('DPIE_OM',-omega/pmid)
482 :
483 0 : call outfld_phys('DPIE_TE',te)
484 0 : call outfld_phys('DPIE_TI',ti)
485 :
486 0 : call outfld_phys('DPIE_O2P',o2p)
487 0 : call outfld_phys('DPIE_NOP',nop)
488 0 : call outfld_phys('DPIE_N2P',n2p)
489 : endif
490 34415232 : call outfld_phys('EDens',ne/1.E6_r8)
491 34415232 : call outfld_phys('OpDens',op/1.E6_r8)
492 :
493 : !-------------------------------------------------------------------------
494 : ! Derive diagnostics nmF2 and hmF2 for output based on TIE-GCM algorithm
495 : !-------------------------------------------------------------------------
496 7296 : if (hist_fld_active('HMF2') .or. hist_fld_active('NMF2')) then
497 0 : iloop: do i = cols, cole
498 0 : kx = 0
499 0 : kloop: do k= 2, nlev
500 0 : if (ne(k,i) >= ne(k-1,i) .and. ne(k,i) >= ne(k+1,i)) then
501 : kx = k
502 : exit kloop
503 : end if
504 : end do kloop
505 :
506 0 : if (kx==0) then
507 0 : hmf2(i) = fillvalue
508 0 : nmf2(i) = fillvalue
509 0 : exit iloop
510 : end if
511 :
512 0 : height = (/zht(kx+1,i),zht(kx,i),zht(kx-1,i)/)
513 0 : nde = (/ne(kx+1,i),ne(kx,i),ne(kx-1,i)/)
514 :
515 0 : h12 = height(1)*height(1)
516 0 : h22 = height(2)*height(2)
517 0 : h32 = height(3)*height(3)
518 :
519 0 : deltx=h12*height(2)+h22*height(3)+h32*height(1)-h32*height(2)-h12*height(3)-h22*height(1)
520 :
521 0 : atx=nde(1)*height(2)+nde(2)*height(3)+nde(3)*height(1)-height(2)*nde(3)-height(3)*nde(1)-height(1)*nde(2)
522 0 : ax=atx/deltx
523 :
524 0 : btx=h12*nde(2)+h22*nde(3)+h32*nde(1)-h32*nde(2)-h12*nde(3)-h22*nde(1)
525 0 : bx=btx/deltx
526 : ctx=h12*height(2)*nde(3)+h22*height(3)*nde(1)+h32*height(1)*nde(2)-h32*height(2)*nde(1)- &
527 0 : h12*height(3)*nde(2)-h22*height(1)*nde(3)
528 0 : cx=ctx/deltx
529 :
530 0 : hmf2(i)=-(bx/(2._r8*ax)) * 1.E-03_r8
531 0 : nmf2(i)=-((bx*bx-4._r8*ax*cx)/(4._r8*ax)) * 1.E-06_r8
532 :
533 : end do iloop ! i=cols, cole
534 :
535 0 : call outfld_phys1d('HMF2',hmf2)
536 0 : call outfld_phys1d('NMF2',nmf2)
537 : end if
538 7296 : if (debug_hist) then
539 0 : call outfld_phys('DPIE_OPMMR', opmmr)
540 0 : call outfld_phys('PED_phys', sigma_ped )
541 0 : call outfld_phys('HAL_phys', sigma_hall )
542 : endif
543 7296 : if (ionos_edyn_active .or. ionos_oplus_xport) then
544 :
545 7296 : call regrid_phys2geo_3d( zgi,zpot_geo, plev, cols, cole )
546 7296 : call regrid_phys2geo_3d( u, un_geo, plev, cols, cole )
547 7296 : call regrid_phys2geo_3d( v, vn_geo, plev, cols, cole )
548 7296 : call regrid_phys2geo_3d( wn,wn_geo, plev, cols, cole )
549 7296 : call regrid_phys2geo_3d( ui, ui_geo, plev, cols, cole )
550 7296 : call regrid_phys2geo_3d( vi, vi_geo, plev, cols, cole )
551 7296 : call regrid_phys2geo_3d( wi, wi_geo, plev, cols, cole )
552 :
553 955776 : do k = 1, nlev
554 948480 : kk = nlev-k+1
555 3801216 : do j = lat0, lat1
556 37939200 : do i = lon0, lon1
557 34145280 : zpot_in(kk,i,j) = zpot_geo(i,j,k) * 100._r8 ! m -> cm
558 34145280 : halo_un(kk,i,j) = un_geo(i,j,k) * 100._r8 ! m/s -> cm/s
559 34145280 : halo_vn(kk,i,j) = vn_geo(i,j,k) * 100._r8 ! m/s -> cm/s
560 34145280 : wn_in(kk,i,j) = wn_geo(i,j,k) * 100._r8 ! m/s -> cm/s
561 34145280 : ui_in(kk,i,j) = ui_geo(i,j,k) * 100._r8 ! zonal ion drift (m/s -> cm/s)
562 34145280 : vi_in(kk,i,j) = vi_geo(i,j,k) * 100._r8 ! meridional ion drift (m/s -> cm/s)
563 36990720 : wi_in(kk,i,j) = wi_geo(i,j,k) * 100._r8 ! vertical ion drift (m/s -> cm/s)
564 : end do
565 : end do
566 : end do
567 :
568 : end if
569 :
570 : !
571 : !
572 : ! Call electrodynamo (edynamo.F90)
573 : ! If using time3d conductances, tell dynamo to *not* do fieldline
574 : ! integrations (i.e., do_integrals == false). In this case, edynamo
575 : ! conductances zigmxx,rim1,2 from time3d will be set by subroutine
576 : ! transform_glbin in time3d module.
577 : !
578 7296 : do_integrals = .true.
579 : !
580 : ! If ionos_edyn_active=false, then empirical ion drifts were passed in from physics,
581 : ! otherwise dynamo calculates them here, and they will be passed to physics.
582 : !
583 7296 : if (ionos_edyn_active) then
584 :
585 7296 : call t_startf('dpie_ionos_dynamo')
586 :
587 0 : call calc_adotv( zpot_in(lev0:lev1,lon0:lon1,lat0:lat1), &
588 0 : halo_un(lev0:lev1,lon0:lon1,lat0:lat1), &
589 : halo_vn(lev0:lev1,lon0:lon1,lat0:lat1), &
590 : wn_in(lev0:lev1,lon0:lon1,lat0:lat1), &
591 : adotv1_in, adotv2_in, adota1_in, adota2_in, &
592 68866944 : a1dta2_in, be3_in, sini_in, lev0, lev1, lon0, lon1, lat0, lat1)
593 :
594 7296 : call regrid_geo2mag_3d( adotv1_in, adotv1_mag )
595 7296 : call regrid_geo2mag_3d( adotv2_in, adotv2_mag )
596 7296 : if (debug_hist) then
597 0 : call outfld_geo('EDYN_ADOTV1', adotv1_in(:,:,lev1:lev0:-1) )
598 0 : call outfld_geo('EDYN_ADOTV2', adotv2_in(:,:,lev1:lev0:-1) )
599 :
600 0 : call outfld_geo2d( 'EDYN_ADOTA1', adota1_in )
601 0 : call outfld_geo2d( 'EDYN_ADOTA2', adota2_in )
602 0 : call outfld_geo2d( 'EDYN_A1DTA2', a1dta2_in )
603 0 : call outfld_geo2d( 'EDYN_BE3' , be3_in )
604 0 : call outfld_geo2d( 'EDYN_SINI', sini_in )
605 : endif
606 7296 : call regrid_geo2mag_2d( adota1_in, adota1_mag )
607 7296 : call regrid_geo2mag_2d( adota2_in, adota2_mag )
608 7296 : call regrid_geo2mag_2d( a1dta2_in, a1dta2_mag )
609 7296 : call regrid_geo2mag_2d( be3_in, be3_mag )
610 7296 : call regrid_geo2mag_2d( sini_in, sini_mag )
611 7296 : if (debug_hist) then
612 0 : call outfld_mag2d('ADOTA1_MAG', adota1_mag )
613 0 : call outfld_mag2d('SINI_MAG', sini_mag )
614 : endif
615 7296 : call regrid_phys2mag_3d( sigma_ped, ped_mag, plev, cols, cole )
616 7296 : call regrid_phys2mag_3d( sigma_hall, hal_mag, plev, cols, cole )
617 7296 : call regrid_phys2mag_3d( zgi, zpot_mag, plev, cols, cole )
618 :
619 7296 : if (mytid<ntask) then
620 23237646 : zpot_mag_in(:,:,mlev0:mlev1) = zpot_mag(:,:,mlev1:mlev0:-1) * 100._r8 ! m -> cm
621 23237646 : ped_mag_in(:,:,mlev0:mlev1) = ped_mag(:,:,mlev1:mlev0:-1)
622 23237646 : hal_mag_in(:,:,mlev0:mlev1) = hal_mag(:,:,mlev1:mlev0:-1)
623 :
624 : call dynamo( zpot_mag_in, ped_mag_in, hal_mag_in, adotv1_mag, adotv2_mag, adota1_mag, &
625 : adota2_mag, a1dta2_mag, be3_mag, sini_mag, &
626 : zpot_in, ui_in, vi_in, wi_in, &
627 7296 : lon0,lon1, lat0,lat1, lev0,lev1, do_integrals )
628 : endif
629 :
630 7296 : call t_stopf ('dpie_ionos_dynamo')
631 :
632 : else
633 0 : if (debug .and. masterproc) then
634 0 : write(iulog,"('dpie_coupling (dynamo NOT called): nstep=',i8)") nstep
635 : write(iulog,"(' empirical ExB ui min,max (cm/s)=',2es12.4)") &
636 0 : minval(ui),maxval(ui)
637 : write(iulog,"(' empirical ExB vi min,max (cm/s)=',2es12.4)") &
638 0 : minval(vi),maxval(vi)
639 : write(iulog,"(' empirical ExB wi min,max (cm/s)=',2es12.4)") &
640 0 : minval(wi),maxval(wi)
641 : end if
642 : end if
643 :
644 : !
645 : ! Call O+ transport routine. Now all inputs to oplus_xport should be in
646 : ! tiegcm-format wrt longitude (-180->180), vertical (bot2top), and units (CGS).
647 : ! (Composition is mmr, ne is cm^3, winds are cm/s)
648 : ! Output op_out and opnm_out will be in cm^3, converted to mmr below.
649 : !
650 7296 : if (ionos_oplus_xport) then
651 955776 : pmid_inv(1:nlev) = pref_mid(nlev:1:-1) ! invert ref pressure (Pa) as in tiegcm
652 :
653 :
654 : !
655 : ! Transport O+ (all args in 'TIEGCM format')
656 : ! Subcycle oplus_xport nspltop times.
657 : !
658 7296 : if (debug .and. masterproc) then
659 : write(iulog,"(a,i8,a,i3)") &
660 0 : 'dpie_coupling before subcycling oplus_xport: nstep = ', &
661 0 : nstep, ' nspltop = ', nspltop
662 : end if
663 :
664 7296 : call regrid_phys2geo_3d( tn, tn_geo, plev, cols, cole )
665 7296 : call regrid_phys2geo_3d( te, te_geo, plev, cols, cole )
666 7296 : call regrid_phys2geo_3d( ti, ti_geo, plev, cols, cole )
667 7296 : call regrid_phys2geo_3d( omega, omega_geo, plev, cols, cole )
668 7296 : call regrid_phys2geo_3d( o2mmr, o2_geo, plev, cols, cole )
669 7296 : call regrid_phys2geo_3d( n2mmr, n2_geo, plev, cols, cole )
670 7296 : call regrid_phys2geo_3d( o1mmr, o_geo, plev, cols, cole )
671 7296 : call regrid_phys2geo_3d( op, op_geo, plev, cols, cole )
672 7296 : call regrid_phys2geo_3d( optm1, optm1_geo, plev, cols, cole )
673 7296 : call regrid_phys2geo_3d( pmid, pmid_geo, plev, cols, cole )
674 7296 : call regrid_phys2geo_3d( mbar, mbar_geo, plev, cols, cole )
675 :
676 7296 : if (mytid<ntask) then
677 :
678 7296 : call t_startf('dpie_halo')
679 955776 : do k = 1, nlev
680 948480 : kk = nlev-k+1
681 3801216 : do j = lat0, lat1
682 37939200 : do i = lon0, lon1
683 34145280 : halo_tn(kk,i,j) = tn_geo(i,j,k)
684 34145280 : halo_te(kk,i,j) = te_geo(i,j,k)
685 34145280 : halo_ti(kk,i,j) = ti_geo(i,j,k)
686 34145280 : halo_om(kk,i,j) = -omega_geo(i,j,k) / pmid_geo(i,j,k) ! Pa/s -> 1/s
687 34145280 : halo_o2(kk,i,j) = o2_geo(i,j,k)
688 34145280 : halo_o1(kk,i,j) = o_geo(i,j,k)
689 34145280 : halo_n2(kk,i,j) = n2_geo(i,j,k)
690 34145280 : halo_mbar(kk,i,j) = mbar_geo(i,j,k)
691 34145280 : op_in(kk,i,j) = op_geo(i,j,k) / 1.e6_r8 ! m^3 -> cm^3
692 36990720 : optm1_in(kk,i,j) = optm1_geo(i,j,k) / 1.e6_r8 ! m^3 -> cm^3
693 : end do
694 : end do
695 : end do
696 : !
697 : ! Define halo points on inputs:
698 : ! WACCM has global longitude values at the poles (j=1,j=nlev)
699 : ! (they are constant for most, except the winds.)
700 : !
701 : ! Set two halo points in lat,lon:
702 : !
703 7296 : nfields = 10
704 7296 : allocate(ptrs(nfields), polesign(nfields))
705 7296 : ptrs(1)%ptr => halo_tn ; ptrs(2)%ptr => halo_te ; ptrs(3)%ptr => halo_ti
706 7296 : ptrs(4)%ptr => halo_un ; ptrs(5)%ptr => halo_vn ; ptrs(6)%ptr => halo_om
707 7296 : ptrs(7)%ptr => halo_o2 ; ptrs(8)%ptr => halo_o1 ; ptrs(9)%ptr => halo_n2
708 7296 : ptrs(10)%ptr => halo_mbar
709 :
710 80256 : polesign = 1._r8
711 21888 : polesign(4:5) = -1._r8 ! un,vn
712 :
713 7296 : call mp_geo_halos(ptrs,1,nlev,lon0,lon1,lat0,lat1,nfields)
714 : !
715 : ! Set latitude halo points over the poles (this does not change the poles).
716 : ! (the 2nd halo over the poles will not actually be used (assuming lat loops
717 : ! are lat=2,plat-1), because jp1,jm1 will be the pole itself, and jp2,jm2
718 : ! will be the first halo over the pole)
719 : !
720 7296 : call mp_pole_halos(ptrs,1,nlev,lon0,lon1,lat0,lat1,nfields,polesign)
721 7296 : deallocate(ptrs,polesign)
722 7296 : call t_stopf('dpie_halo')
723 7296 : if (debug_hist) then
724 0 : call outfld_geokij( 'OPtm1i',optm1_in, lev0,lev1, lon0,lon1, lat0,lat1 )
725 : endif
726 7296 : call t_startf('dpie_oplus_xport')
727 43776 : do isplit = 1, nspltop
728 :
729 36480 : if (isplit > 1) then
730 137748480 : op_in = op_out
731 137748480 : optm1_in = optm1_out
732 : end if
733 :
734 : call oplus_xport(halo_tn, halo_te, halo_ti, halo_un, halo_vn, halo_om, &
735 : zpot_in, halo_o2, halo_o1, halo_n2, op_in, optm1_in, &
736 : halo_mbar, ui_in, vi_in, wi_in, pmid_inv, &
737 : op_out, optm1_out, &
738 43776 : lon0, lon1, lat0, lat1, nspltop, isplit)
739 :
740 : end do ! isplit=1,nspltop
741 7296 : call t_stopf ('dpie_oplus_xport')
742 7296 : if (debug.and.masterproc) then
743 : write(iulog,"('dpie_coupling after subcycling oplus_xport: nstep=',i8,' nspltop=',i3)") &
744 0 : nstep,nspltop
745 0 : write(iulog,"(' op_out min,max (cm^3)=',2es12.4)") minval(op_out) ,maxval(op_out)
746 0 : write(iulog,"(' optm1_out min,max (cm^3)=',2es12.4)") minval(optm1_out),maxval(optm1_out)
747 : end if
748 7296 : if (debug_hist) then
749 0 : call outfld_geokij( 'OPLUS', op_out, lev0,lev1, lon0,lon1, lat0,lat1 )
750 0 : call outfld_geokij( 'OPtm1o',optm1_out, lev0,lev1, lon0,lon1, lat0,lat1 )
751 : endif
752 : !
753 : ! Pass new O+ for current and previous time step back to physics (convert from cm^3 to m^3 and back to mmr).
754 : !
755 955776 : do k=1,nlev
756 948480 : kk = nlev-k+1
757 3801216 : do j = lat0,lat1
758 37939200 : do i = lon0,lon1
759 136581120 : op_geo(i,j,k) = op_out(kk,i,j)*1.e6_r8 * rmassOp / mbar_geo(i,j,k) * &
760 136581120 : (kboltz * tn_geo(i,j,k)) / pmid_geo(i,j,k)
761 : optm1_geo(i,j,k) = optm1_out(kk,i,j)*1.e6_r8 * rmassOp / mbar_geo(i,j,k) * &
762 34145280 : (kboltz * tn_geo(i,j,k)) / pmid_geo(i,j,k)
763 34145280 : ui_geo(i,j,k) = ui_in(kk,i,j)/100._r8 ! cm/s -> m/s
764 34145280 : vi_geo(i,j,k) = vi_in(kk,i,j)/100._r8 ! cm/s -> m/s
765 36990720 : wi_geo(i,j,k) = wi_in(kk,i,j)/100._r8 ! cm/s -> m/s
766 : end do
767 : end do
768 : end do
769 :
770 : endif
771 :
772 7296 : call regrid_geo2phys_3d( op_geo, opmmr, plev, cols, cole )
773 7296 : call regrid_geo2phys_3d( optm1_geo, opmmrtm1, plev, cols, cole )
774 7296 : call regrid_geo2phys_3d( ui_geo, ui, plev, cols, cole )
775 7296 : call regrid_geo2phys_3d( vi_geo, vi, plev, cols, cole )
776 7296 : call regrid_geo2phys_3d( wi_geo, wi, plev, cols, cole )
777 :
778 : end if ! ionos_oplus_xport
779 :
780 7296 : if (debug_hist) then
781 0 : call outfld_phys('WACCM_UI',ui)
782 0 : call outfld_phys('WACCM_VI',vi)
783 0 : call outfld_phys('WACCM_WI',wi)
784 0 : call outfld_phys('WACCM_OP',opmmr)
785 : endif
786 7296 : call t_stopf('d_pie_coupling')
787 :
788 7296 : end subroutine d_pie_coupling
789 : !-----------------------------------------------------------------------
790 7296 : subroutine calc_wn(tn,omega,pmid,mbar,grav,wn,cols,cole,nlev)
791 7296 : use shr_const_mod,only : shr_const_rgas ! Universal gas constant
792 : !
793 : ! Calculate neutral vertical wind on midpoints (m/s)
794 : !
795 : ! Inputs:
796 : integer,intent(in) :: cols, cole, nlev
797 : real(r8),dimension(nlev, cols:cole),intent(in) :: &
798 : tn, & ! neutral temperature (deg K)
799 : omega,& ! pressure velocity (Pa/s)
800 : mbar ! mean molecular weight
801 : real(r8),dimension(nlev,cols:cole),intent(in) :: &
802 : pmid ! pressure at midpoints (Pa)
803 : real(r8),intent(in) :: grav ! m/s^2
804 : !
805 : ! Output:
806 : real(r8),intent(out) :: wn(nlev, cols:cole) ! vertical velocity output (m/s)
807 : !
808 : ! Local:
809 : integer :: i,k
810 14592 : real(r8) :: scheight(nlev, cols:cole) ! dimensioned for vectorization
811 :
812 269952 : do i = cols, cole
813 34415232 : do k = 1, nlev
814 34145280 : scheight(k,i) = shr_const_rgas*tn(k,i)/(mbar(k,i)*grav)
815 34407936 : wn(k,i) = -omega(k,i)*scheight(k,i)/pmid(k,i)
816 : end do
817 : end do
818 7296 : end subroutine calc_wn
819 : !-----------------------------------------------------------------------
820 8064 : subroutine calc_pfrac(sunlon,pfrac)
821 : !
822 : ! Calculate pfrac fractional presence of dynamo equation using critical
823 : ! convection colatitudes crit(2).
824 : !
825 : use edyn_maggrid ,only: nmlonp1,ylonm,ylatm
826 : use edyn_solve ,only: nmlat0
827 : use aurora_params ,only: offc, dskofc, theta0, aurora_params_set
828 :
829 : implicit none
830 : !
831 : ! Args:
832 : real(r8),intent(in) :: sunlon ! Sun's longitude in dipole coordinates
833 : !
834 : ! Output: fractional presence of dynamo equation using critical colatitudes
835 : !
836 : real(r8),intent(out) :: pfrac(nmlonp1,nmlat0) ! NH fraction of potential
837 : !
838 : ! Local:
839 : integer :: j,i
840 16128 : real(r8),dimension(nmlonp1,nmlat0) :: colatc
841 : real(r8) :: sinlat,coslat,aslonc,ofdc,cosofc,sinofc,crit1deg
842 :
843 8064 : if (.not. crit_user_set) then
844 8064 : if (prescribed_period) then
845 0 : crit(:) = amie_default_crit(:)*dtr
846 : else
847 8064 : crit1deg = max(15._r8,0.5_r8*(theta0(1)+theta0(2))*rtd + 5._r8)
848 8064 : crit1deg = min(30._r8,crit1deg)
849 : !
850 : ! Critical colatitudes:
851 8064 : crit(1) = crit1deg*dtr
852 8064 : crit(2) = crit(1) + 15._r8*dtr
853 : end if
854 : end if
855 :
856 8064 : if (.not.aurora_params_set) then
857 0 : offc(:) = 1._r8*dtr
858 0 : dskofc(:) = 0._r8
859 : end if
860 :
861 : !
862 : ! offc(2), dskofc(2) are for northern hemisphere aurora
863 : !
864 8064 : ofdc = sqrt(offc(2)**2 + dskofc(2)**2)
865 8064 : cosofc = cos(ofdc)
866 8064 : sinofc = sin(ofdc)
867 8064 : aslonc = asin(dskofc(2)/ofdc)
868 : !
869 : ! Define colatc with northern convection circle coordinates
870 : !
871 403200 : do j=1,nmlat0
872 395136 : sinlat = sin(abs(ylatm(j+nmlat0-1)))
873 395136 : coslat = cos( ylatm(j+nmlat0-1))
874 32401152 : do i=1,nmlonp1
875 32006016 : colatc(i,j) = cos(ylonm(i)-sunlon+aslonc)
876 32401152 : colatc(i,j) = acos(cosofc*sinlat-sinofc*coslat*colatc(i,j))
877 : end do ! i=1,nmlonp1
878 : !
879 : ! Calculate fractional presence of dynamo equation at each northern
880 : ! hemisphere geomagnetic grid point. Output in pfrac(nmlonp1,nmlat0)
881 : !
882 32409216 : do i = 1 , nmlonp1
883 32006016 : pfrac(i,j) = (colatc(i,j)-crit(1)) / (crit(2)-crit(1))
884 32006016 : if (pfrac(i,j) < 0._r8) then
885 6633216 : pfrac(i,j) = 0._r8
886 : end if
887 32401152 : if (pfrac(i,j) >= 1._r8) then
888 21555072 : pfrac(i,j) = 1._r8
889 : end if
890 : end do ! i=1,nmlonp1
891 : end do ! j=1,nmlat0
892 : !
893 8064 : end subroutine calc_pfrac
894 : !-----------------------------------------------------------------------
895 8064 : subroutine sunloc(iday, secs, sunlon)
896 : !
897 : ! Given day of year and ut, return sun's longitude in dipole coordinates
898 : ! in sunlon
899 : !
900 : use getapex, only: alonm ! (nlonp1,0:nlatp1)
901 : use edyn_geogrid, only: nlon, nlat, dphi, dlamda
902 : use edyn_params, only: pi
903 : !
904 : ! Args:
905 : integer,intent(in) :: iday ! day of year
906 : real(r8),intent(in) :: secs ! ut in seconds
907 : real(r8),intent(out) :: sunlon ! output
908 : !
909 : ! Local:
910 : integer :: j, i, ii, isun, jsun
911 : real(r8) :: glats, glons, pisun, pjsun, sndlons, csdlons
912 16128 : real(r8) :: rlonm(nlon+4, nlat) ! (nlon+4,nlat)
913 : real(r8) :: r8_isun, r8_jsun
914 :
915 : !
916 : ! Sun's geographic coordinates:
917 8064 : glats = asin(.398749_r8*sin(2._r8 * pi * real(iday-80, r8) / 365._r8))
918 8064 : glons = pi * (1._r8 - (2._r8 * secs / 86400._r8))
919 :
920 782208 : do j = 1, nlat
921 112250880 : do i = 1, nlon
922 111476736 : ii = i + 2
923 112250880 : rlonm(ii, j) = alonm(i, j)
924 : end do
925 2330496 : do i = 1, 2
926 1548288 : rlonm(i, j) = rlonm(i+nlon, j)
927 2322432 : rlonm(i+nlon+2, j) = rlonm(i+2, j)
928 : end do
929 : end do
930 :
931 8064 : pisun = ((glons + pi) / dlamda) + 1._r8
932 8064 : pjsun = ((glats + (.5_r8 * (pi - dphi))) / dphi) + 1._r8
933 8064 : isun = int(pisun)
934 8064 : jsun = int(pjsun)
935 8064 : r8_isun = real(isun, r8)
936 8064 : r8_jsun = real(jsun, r8)
937 8064 : pisun = pisun - r8_isun
938 8064 : pjsun = pjsun - r8_jsun
939 :
940 16128 : sndlons = (1._r8-pisun) * (1._r8-pjsun) * sin(rlonm(isun+2, jsun)) + &
941 8064 : pisun*(1._r8-pjsun) * sin(rlonm(isun+3,jsun)) + &
942 8064 : pisun*pjsun * sin(rlonm(isun+3,jsun+1)) + &
943 32256 : (1._r8-pisun)*pjsun * sin(rlonm(isun+2,jsun+1))
944 : csdlons = (1._r8-pisun) * (1._r8-pjsun) * cos(rlonm(isun+2,jsun)) + &
945 : pisun*(1._r8-pjsun) * cos(rlonm(isun+3,jsun))+ &
946 : pisun*pjsun * cos(rlonm(isun+3,jsun+1))+ &
947 8064 : (1._r8-pisun)*pjsun * cos(rlonm(isun+2,jsun+1))
948 8064 : sunlon = atan2(sndlons, csdlons)
949 :
950 8064 : end subroutine sunloc
951 :
952 : !-----------------------------------------------------------------------
953 : !-----------------------------------------------------------------------
954 0 : subroutine outfld_phys1d( fldname, array )
955 : use ppgrid, only: pcols, begchunk, endchunk
956 : use phys_grid,only: get_ncols_p
957 :
958 : character(len=*), intent(in) :: fldname
959 : real(r8), intent(in) :: array(:)
960 :
961 : integer :: i,j, lchnk,ncol
962 : real(r8) :: tmparr(pcols)
963 :
964 0 : if (hist_fld_active(fldname)) then
965 0 : j = 0
966 0 : do lchnk = begchunk, endchunk
967 0 : ncol = get_ncols_p(lchnk)
968 0 : do i = 1, ncol
969 0 : j = j + 1
970 0 : tmparr(i) = array(j)
971 : enddo
972 0 : call outfld(fldname,tmparr(:ncol),ncol,lchnk)
973 : enddo
974 : end if
975 :
976 0 : end subroutine outfld_phys1d
977 : !-----------------------------------------------------------------------
978 14592 : subroutine outfld_phys( fldname, array )
979 0 : use ppgrid, only: pcols, pver, begchunk, endchunk
980 : use phys_grid,only: get_ncols_p
981 :
982 : character(len=*), intent(in) :: fldname
983 : real(r8), intent(in) :: array(:,:)
984 :
985 : integer :: i,j,k, lchnk,ncol
986 : real(r8) :: tmparr(pcols, pver)
987 :
988 14592 : if (hist_fld_active(fldname)) then
989 14592 : j = 0
990 58368 : do lchnk = begchunk, endchunk
991 43776 : ncol = get_ncols_p(lchnk)
992 569088 : do i = 1, ncol
993 525312 : j = j + 1
994 68859648 : do k = 1, pver
995 68815872 : tmparr(i,k) = array(k,j)
996 : enddo
997 : enddo
998 74039808 : call outfld(fldname,tmparr(:ncol,:),ncol,lchnk)
999 : enddo
1000 : end if
1001 :
1002 14592 : end subroutine outfld_phys
1003 : !-----------------------------------------------------------------------
1004 0 : subroutine outfld_geokij( name, array, ilev0,ilev1, ilon0,ilon1, ilat0,ilat1 )
1005 :
1006 : character(len=*), intent(in) :: name
1007 : integer, intent(in) :: ilev0,ilev1, ilon0,ilon1, ilat0,ilat1
1008 : real(r8), intent(in) :: array(ilev0:ilev1, ilon0:ilon1, ilat0:ilat1)
1009 :
1010 : integer :: j,k
1011 0 : real(r8) :: tmpout(ilon0:ilon1,ilev0:ilev1)
1012 :
1013 0 : do j = ilat0,ilat1
1014 0 : do k = ilev0,ilev1
1015 0 : tmpout(ilon0:ilon1,k) = array(ilev1-k+1,ilon0:ilon1,j)
1016 : end do
1017 0 : call outfld( name, tmpout, ilon1-ilon0+1, j )
1018 : end do
1019 14592 : end subroutine outfld_geokij
1020 : !-----------------------------------------------------------------------
1021 0 : subroutine outfld_geo( fldname, array )
1022 : use edyn_mpi, only: lon0, lon1, lat0, lat1, lev0, lev1
1023 :
1024 : character(len=*), intent(in) :: fldname
1025 : real(r8), intent(in) :: array(lon0:lon1,lat0:lat1,lev0:lev1)
1026 :
1027 : integer :: j
1028 :
1029 0 : do j = lat0,lat1
1030 0 : call outfld( fldname, array(lon0:lon1,j,lev0:lev1), lon1-lon0+1, j )
1031 : end do
1032 :
1033 0 : end subroutine outfld_geo
1034 : !-----------------------------------------------------------------------
1035 0 : subroutine outfld_geo2d( fldname, array )
1036 : use edyn_mpi, only: lon0, lon1, lat0, lat1
1037 :
1038 : character(len=*), intent(in) :: fldname
1039 : real(r8), intent(in) :: array(lon0:lon1,lat0:lat1)
1040 :
1041 : integer :: j
1042 :
1043 0 : do j = lat0,lat1
1044 0 : call outfld( fldname, array(lon0:lon1,j), lon1-lon0+1, j )
1045 : end do
1046 :
1047 0 : end subroutine outfld_geo2d
1048 : !-----------------------------------------------------------------------
1049 : subroutine outfld_mag( fldname, array )
1050 : use edyn_mpi, only: omlon1, mlon0, mlon1, mlat0, mlat1, mlev0, mlev1
1051 :
1052 : character(len=*), intent(in) :: fldname
1053 : real(r8), intent(in) :: array(mlon0:mlon1,mlat0:mlat1,mlev0:mlev1)
1054 :
1055 : integer :: j
1056 :
1057 : do j = mlat0,mlat1
1058 : call outfld( fldname, array(mlon0:omlon1,j,mlev0:mlev1),omlon1-mlon0+1,j)
1059 : end do
1060 :
1061 : end subroutine outfld_mag
1062 : !-----------------------------------------------------------------------
1063 0 : subroutine outfld_mag2d( fldname, array )
1064 : use edyn_mpi, only: mlon0, mlon1, mlat0, mlat1
1065 :
1066 : character(len=*), intent(in) :: fldname
1067 : real(r8), intent(in) :: array(mlon0:mlon1,mlat0:mlat1)
1068 :
1069 : integer :: j
1070 :
1071 0 : do j = mlat0,mlat1
1072 0 : call outfld( fldname, array(mlon0:mlon1,j), mlon1-mlon0+1, j )
1073 : end do
1074 :
1075 0 : end subroutine outfld_mag2d
1076 :
1077 : end module dpie_coupling
|