Line data Source code
1 : module edynamo
2 : !
3 : !-----------------------------------------------------------------------
4 : ! Purpose:
5 : ! Electro-dynamo module
6 : !-----------------------------------------------------------------------
7 : !
8 : use shr_kind_mod, only: r8 => shr_kind_r8 ! 8-byte reals
9 : use cam_logfile, only: iulog
10 : use cam_abortutils, only: endrun
11 : use spmd_utils, only: masterproc
12 : use edyn_params, only: finit ! initialization value
13 : use edyn_maggrid, only: nmlon, nmlonp1, nmlat, nmlath, nmlev
14 : use edyn_mpi, only: mlon0, mlon1, omlon1, mytid, mlat0, mlat1
15 : use edyn_mpi, only: mlev0, mlev1, lon0, lon1, lat0, lat1
16 : use edyn_solve, only: solve_edyn
17 : use time_manager, only: get_nstep ! for debug
18 : use cam_history, only: outfld, hist_fld_active
19 : use savefield_waccm, only: savefld_waccm
20 :
21 : implicit none
22 : save
23 : private
24 :
25 : integer :: nstep
26 : !
27 : ! 2d coefficients and RHS terms for PDE on magnetic subdomains
28 : ! (including halo points).
29 : ! If use_time3d_integ==.true., these will be input from time3d
30 : ! (see use-association in time3d.F90)
31 : !
32 : real(r8), allocatable, dimension(:,:) :: &
33 : zigm11, & ! sigma11*cos(theta0)
34 : zigmc, & ! sigmac
35 : zigm1, & ! for Hall conductance diagnostic
36 : zigm2, & ! sigma2
37 : zigm22, & ! sigma22/cos(theta0)
38 : rim1,rim2, & ! see description in comment below
39 : rhs, & ! right-hand side of PDE
40 : phimsolv, & ! solution direct from solver (nhem only)
41 : phim2d ! solution with phihm and both nhem and shem
42 : !
43 : ! 3d potential and electric field on mag subdomains (see sub pthreed):
44 : ! (mlon0:mlon1,mlat0:mlat1,mlev0:mlev1)
45 : ! Electric potential and field components are output fields of edynamo
46 : ! (later, these can be output arguments of the main driver, sub dynamo)
47 : !
48 : real(r8), allocatable, dimension(:,:,:) :: &
49 : phim3d, & ! 3d electric potential
50 : ed13d,ed23d, & ! 3d electric field for current calculations
51 : ephi3d, & ! 3d eastward electric field
52 : elam3d, & ! 3d equatorward electric field
53 : emz3d, & ! 3d upward electric field
54 : zpot_mag, &
55 : zpotm3d ! 3d geopotential (values at all levels)
56 : !
57 : ! 3d ion drift velocities on geographic grid (output):
58 : !
59 : ! real(r8), allocatable, dimension(:,:,:),save,target :: & ! (nlev,lon0:lon1,lat0:lat1)
60 : ! ui, & ! zonal ion drift
61 : ! vi, & ! meridional ion drift
62 : ! wi ! vertical ion drift
63 : !
64 : ! 3d electric field on geographic subdomains (see sub pefield):
65 : ! (nlev,lon0-2,lon1+2,lat0:lat1)
66 : real(r8), allocatable, dimension(:,:,:) :: ex,ey,ez
67 : !
68 : ! 3d electric potential on geographic subdomains (lon0:lon1,lat0:lat1,nlevp1)
69 : ! This will be regridded from phim3d for output to history files.
70 : real(r8), allocatable, dimension(:,:,:) :: phig3d ! (lon0:lon1,lat0:lat1,nlevp1)
71 : real(r8), allocatable, dimension(:,:,:) :: poten ! (nlevp1,lon0:lon1,lat0:lat1)
72 : !
73 : ! Fields at mag equator:
74 : !
75 : real(r8), allocatable, dimension(:,:) :: & ! (mlon0:mlon1,nmlev)
76 : ped_meq, hal_meq, adotv1_meq, adotv2_meq
77 : real(r8), allocatable, dimension(:,:,:) :: & ! (mlon0:mlon1,nmlev,4)
78 : fmeq_out
79 : real(r8), allocatable, dimension(:,:,:,:) :: & ! (mlon0:mlon1,mlat0:mlat1,nmlev,4)
80 : fmeq_in
81 : !
82 : ! Global longitude values near mag equator and poles for complete_integrals and rhs.
83 : ! These are declared in module data because they are used by subs complete_integrals
84 : ! and rhspde. The nf2d 7 fields are: zigm11,zigm22,zigmc,zigm1,zigm2,rim1,rim2,
85 : ! order is important (see feq_jpm1 and fpole_jpm2)!
86 : !
87 : integer, parameter :: nf2d=7 ! 7 2d fields
88 : real(r8), allocatable :: feq_jpm1(:,:,:) ! 7 fields at 2 lats (eq-1, eq+1)
89 : real(r8), allocatable :: fpole_jpm2(:,:,:) ! fields at S pole+1,2 and N pole-1,2
90 :
91 : real(r8), allocatable :: unitvm(:)
92 : !
93 : ! ed1,ed2: 2d electric field output on mag grid:
94 : ! (use-associated by dpie_coupling)
95 : !
96 : real(r8), allocatable, dimension(:,:) :: ed1, ed2 ! (mlon0-1:mlon1+1,mlat0-1:mlat1+1)
97 : !
98 : ! Global inputs to time3d: Note dimension order switch:
99 : ! edynamo has subdomains (mlon,mlat), whereas time3d has global (nmlat,nmlonp1)
100 : ! These are use-associated by time3d, and are init to zero in edyn_init.
101 : !
102 : real(r8), allocatable, dimension(:,:) :: ed1_glb, ed2_glb
103 : logical :: debug = .false. ! set true for prints to stdout at each call
104 :
105 : logical, public :: debug_hist = .false.
106 :
107 : public :: alloc_edyn, ed1, ed2, ed1_glb, ed2_glb
108 : public :: zigm11, zigmc, zigm2, zigm22, rim1, rim2
109 : public :: dynamo
110 :
111 : contains
112 : !-----------------------------------------------------------------------
113 7296 : subroutine dynamo( zpot_mag_in, ped_mag, hall_mag, adotv1_mag, adotv2_mag, adota1_mag, &
114 7296 : adota2_mag, a1dta2_mag,be3_mag, sini_mag, zpot, &
115 7296 : ui, vi, wi, lon0,lon1, lat0,lat1, lev0,lev1, do_integrals )
116 : use edyn_mpi, only: &
117 : mp_mag_halos, & ! set magnetic halo points
118 : mp_scatter_phim ! scatter solution to slave tasks
119 : use edyn_solve, only: rim_glb ! pde solver output (nmlonp1,nmlat,2)
120 : !
121 : ! Main driver for edynamo.
122 : ! Note alloc_edyn and esmf_init are called from edyn_init.
123 : !
124 : ! Args:
125 : integer,intent(in) :: & ! geographic subdomain
126 : lon0, lon1, & ! first,last longitude indices of geographic subdomain
127 : lat0, lat1, & ! first,last latitude indices of geographic subdomain
128 : lev0, lev1 ! first,last level indices (not distributed)
129 : !
130 : ! Inputs :
131 : !
132 : real(r8), dimension(mlon0:mlon1,mlat0:mlat1,mlev0:mlev1), intent(in) :: &
133 : zpot_mag_in, & ! geopotential (cm)
134 : ped_mag, & ! pedersen conductivity (S/m)
135 : hall_mag, & ! hall conductivity (S/m)
136 : adotv1_mag,& ! ue1 (m/s)
137 : adotv2_mag ! ue2 (m/s)
138 : real(r8), dimension(mlon0:mlon1,mlat0:mlat1), intent(in) :: &
139 : adota1_mag, &
140 : adota2_mag, &
141 : a1dta2_mag, &
142 : be3_mag, &
143 : sini_mag
144 :
145 : ! inputs on geographic (oplus) grid
146 : real(r8), dimension(lev0:lev1,lon0:lon1,lat0:lat1), intent(in) :: &
147 : zpot ! geopotential (cm)
148 :
149 : real(r8), dimension(lev0:lev1,lon0:lon1,lat0:lat1), intent(out) :: &
150 : ui, & ! zonal ion drift (cm/s)
151 : vi, & ! meridional ion drift (cm/s)
152 : wi ! vertical ion drift (cm/s)
153 :
154 : logical,intent(in) :: do_integrals
155 :
156 7296 : if (debug) then
157 0 : nstep = get_nstep()
158 0 : write(iulog,"(a,i5,a,l1)") 'Enter dynamo: nstep=', nstep, &
159 0 : ', do_integrals=', do_integrals
160 : end if
161 :
162 : !
163 : ! Regrid input fields from geographic to magnetic, and calculate
164 : ! some additional fields. If conductances are passed in from
165 : ! time3d (.not.do_integrals), then we do not need these inputs.
166 : !
167 7296 : if (do_integrals) then
168 7296 : call dynamo_set_data( zpot_mag_in, ped_mag, hall_mag, adotv1_mag, adotv2_mag )
169 7296 : if (debug) then
170 0 : write(iulog,"('edynamo debug: after dynamo_input')")
171 : end if
172 : end if
173 :
174 : !
175 : ! Fieldline integration:
176 : !
177 : ! If *not* doing fieldline integrations, then global conductances
178 : ! were passed in to the driver from time3d, and transformed from
179 : ! (nmlat,nmlonp1) to (nmlonp1,nmlat), defining zigmxx and rim1,2
180 : ! for the solver.
181 : !
182 7296 : if (do_integrals) then
183 : call fieldline_integrals(ped_mag, hall_mag, adotv1_mag, adotv2_mag, &
184 7296 : adota1_mag, adota2_mag, a1dta2_mag, be3_mag, sini_mag)
185 : end if
186 : !
187 : ! Equatorial and polar values, hemisphere folding:
188 : ! (these will be time3d integrations if do_integrals==.false.)
189 : !
190 7296 : call complete_integrals()
191 7296 : if (debug) then
192 0 : write(iulog,"('edynamo debug: after complete_integrals')")
193 : end if
194 : !
195 : ! Calculate right-hand side on mag subdomains:
196 : ! (mag halos are needed in rim1,2 for rhs calculation)
197 : !
198 7296 : call mp_mag_halos(rim1,mlon0,mlon1,mlat0,mlat1,1)
199 7296 : call mp_mag_halos(rim2,mlon0,mlon1,mlat0,mlat1,1)
200 7296 : call rhspde
201 7296 : if (debug) then
202 0 : write(iulog,"('edynamo debug: after rhspde')")
203 : end if
204 : !
205 : ! Gather needed arrays to root task for the serial solver:
206 : !
207 7296 : call gather_edyn()
208 7296 : if (debug) then
209 0 : write(iulog,"('edynamo debug: after gather_edyn')")
210 : end if
211 : !
212 : ! Root task now sets up stencils and calls the PDE solver:
213 : !
214 7296 : if (debug) then
215 0 : write(iulog,"('edynamo debug: call solve_edyn (master only)')")
216 : end if
217 7296 : if (mytid == 0) then
218 19 : call solve_edyn()
219 : end if
220 7296 : if (debug) write(iulog,"('edynamo debug: after solve_edyn (master only)')")
221 : !
222 : ! rim1 after solver is needed for highlat_poten. rim_glb is distributed
223 : ! to subdomains as rim1, and mag halos set. This will overwrite rim1 from
224 : ! fieldline_integrals, complete_integrals, etc.
225 : !
226 185991 : call mp_scatter_phim(rim_glb(:,:,1),rim1(mlon0:mlon1,mlat0:mlat1))
227 7296 : if (debug) then
228 0 : write(iulog,"('edynamo debug: after mp_scatter_phim')")
229 : end if
230 :
231 7296 : call mp_mag_halos(rim1,mlon0,mlon1,mlat0,mlat1,1)
232 7296 : if (debug) then
233 0 : write(iulog,"('edynamo debug: after mp_mag_halos')")
234 : end if
235 : !
236 : ! Add high latitude potential from empirical model (heelis or weimer)
237 : ! to solution rim1, defining phim2d on mag subdomains.
238 : !
239 7296 : call highlat_poten()
240 7296 : if (debug) then
241 0 : write(iulog,"('edynamo debug: after highlat_poten')")
242 : end if
243 : !
244 : ! Expand phim2d to phim3d, first setting mag halos in phim2d from
245 : ! hightlat_poten. phim3d will then be the final potential from pdynamo.
246 : !
247 7296 : call mp_mag_halos(phim2d,mlon0,mlon1,mlat0,mlat1,1)
248 :
249 7296 : call pthreed()
250 7296 : if (debug) then
251 0 : write(iulog,"('edynamo debug: after pthreed')")
252 : end if
253 : !
254 : ! Convert electric field to geographic grid:
255 7296 : call pefield()
256 7296 : if (debug) then
257 0 : write(iulog,"('edynamo debug: after pefield')")
258 : end if
259 :
260 : !
261 : ! Calculate ion drift velocities:
262 : !
263 :
264 7296 : call ionvel(zpot,ui,vi,wi, lon0,lon1, lat0,lat1, lev0,lev1)
265 7296 : if (debug) then
266 0 : write(iulog,"('edynamo debug: after ionvel')")
267 : end if
268 :
269 7296 : end subroutine dynamo
270 : !-----------------------------------------------------------------------
271 7296 : subroutine dynamo_set_data( zpot_mag_in, ped_mag, hall_mag, adotv1_mag, adotv2_mag )
272 : !
273 : !
274 : use edyn_params, only: h0, kbotdyn
275 : use edyn_mpi, only: mp_mageq ! get global values at mag equator
276 :
277 : !
278 : ! Args: Input fields on geographic grid:
279 : !
280 : real(r8), dimension(mlon0:mlon1,mlat0:mlat1,mlev0:mlev1),intent(in) :: &
281 : zpot_mag_in,&! cm
282 : ped_mag, & ! pedersen conductivity (S/m)
283 : hall_mag, & ! hall conductivity (S/m)
284 : adotv1_mag,& ! ue1 (m/s)
285 : adotv2_mag ! ue2 (m/s)
286 : !
287 : ! Local:
288 : !
289 : integer :: j, i, k
290 : !
291 7296 : if (debug .and. masterproc) then
292 0 : write(iulog,"('dynamo_input after savefld_waccm calls')")
293 0 : write(iulog,"('dynamo_input: kbotdyn=',i4)") kbotdyn
294 : end if
295 : !
296 : ! fmeq_in are input fields on 3d mag subdomains.
297 : ! allocate(fmeq_in(mlon0:mlon1,mlat0:mlat1,mlev0:mlev1,4)
298 : !
299 23237646 : fmeq_in(:,:,:,1) = ped_mag(:,:,:)
300 23237646 : fmeq_in(:,:,:,2) = hall_mag(:,:,:)
301 23237646 : fmeq_in(:,:,:,3) = adotv1_mag(:,:,:)
302 23237646 : fmeq_in(:,:,:,4) = adotv2_mag(:,:,:)
303 : !
304 : ! Tasks w/ mag equator send eq data(i,k) to other tasks in their tidi:
305 : !
306 7296 : call mp_mageq(fmeq_in, fmeq_out, 4, mlon0, mlon1, mlat0, mlat1, nmlev)
307 : !
308 : ! Output arrays now have mag equator data on longitude subdomain
309 : ! and full column (mlon0:mlon1,nmlev)
310 : ! These will be used in fieldline_integrals.
311 : !
312 7358016 : ped_meq(:,:) = fmeq_out(:,:,1)
313 7358016 : hal_meq(:,:) = fmeq_out(:,:,2)
314 7358016 : adotv1_meq(:,:) = fmeq_out(:,:,3)
315 7358016 : adotv2_meq(:,:) = fmeq_out(:,:,4)
316 :
317 23237646 : zpot_mag(:,:,:) = zpot_mag_in(:,:,:)
318 : !
319 : ! Save geopotential on magnetic grid in zpotm3d, then
320 : ! limit max zpot_mag to h0 for use in fieldline integrals
321 : ! and pthreed. This should set zpot_mag to constant h0
322 : ! below kbotdyn. It is not necessary to set poles of zpotm3d
323 : ! since sub pthreed does not reference the poles of zpotm3d.
324 : !
325 955776 : do k = mlev0, mlev1
326 3830856 : do j = mlat0, mlat1
327 23230350 : do i=mlon0,mlon1
328 19406790 : zpotm3d(i,j,k) = zpot_mag(i,j,k)
329 22281870 : if (zpot_mag(i,j,k) < h0) then
330 11039926 : zpot_mag(i,j,k) = h0
331 : end if
332 : end do
333 : end do
334 : end do
335 29412 : do j = mlat0, mlat1
336 22064396 : call outfld('PED_MAG',ped_mag(mlon0:omlon1,j,mlev1:mlev0:-1),omlon1-mlon0+1,j)
337 22064396 : call outfld('HAL_MAG',hall_mag(mlon0:omlon1,j,mlev1:mlev0:-1),omlon1-mlon0+1,j)
338 22064396 : call outfld('ZPOT_MAG',zpot_mag(mlon0:omlon1,j,mlev1:mlev0:-1),omlon1-mlon0+1,j)
339 29412 : if (debug_hist) then
340 0 : call outfld('ADOTV1_MAG',adotv1_mag(mlon0:omlon1,j,mlev1:mlev0:-1),omlon1-mlon0+1,j)
341 0 : call outfld('ADOTV2_MAG',adotv2_mag(mlon0:omlon1,j,mlev1:mlev0:-1),omlon1-mlon0+1,j)
342 : endif
343 : end do
344 7296 : end subroutine dynamo_set_data
345 : !-----------------------------------------------------------------------
346 : !-----------------------------------------------------------------------
347 768 : subroutine alloc_edyn
348 : use edyn_geogrid, only: nlev
349 : !
350 : ! Allocate and initialize arrays for parallel dynamo (module data)
351 : ! (called once per run)
352 : !
353 : integer :: istat
354 : integer :: mlon00,mlon11,mlat00,mlat11
355 : !
356 768 : mlon00=mlon0-1 ; mlon11=mlon1+1
357 768 : mlat00=mlat0-1 ; mlat11=mlat1+1
358 : !
359 : ! 2d fields on mag subdomains (i,j):
360 : ! Certain fields are allocated with halos mlon0-1:mlon1+1,mlat0-1:mlat1+1
361 : !
362 3072 : allocate(zigm11(mlon00:mlon11,mlat00:mlat11),stat=istat)
363 768 : if (istat /= 0) call endrun('alloc_edyn: zigm11')
364 38442 : zigm11 = finit
365 2304 : allocate(zigmc(mlon00:mlon11,mlat00:mlat11) ,stat=istat)
366 768 : if (istat /= 0) call endrun('alloc_edyn: zigmc')
367 38442 : zigmc = finit
368 2304 : allocate(zigm1(mlon00:mlon11,mlat00:mlat11) ,stat=istat)
369 768 : if (istat /= 0) call endrun('alloc_edyn: zigm1')
370 38442 : zigm1 = finit
371 2304 : allocate(zigm2(mlon00:mlon11,mlat00:mlat11) ,stat=istat)
372 768 : if (istat /= 0) call endrun('alloc_edyn: zigm2')
373 38442 : zigm2 = finit
374 2304 : allocate(zigm22(mlon00:mlon11,mlat00:mlat11),stat=istat)
375 768 : if (istat /= 0) call endrun('alloc_edyn: zigm22')
376 38442 : zigm22 = finit
377 2304 : allocate(rhs(mlon00:mlon11,mlat00:mlat11) ,stat=istat)
378 768 : if (istat /= 0) call endrun('alloc_edyn: rhs')
379 38442 : rhs = finit
380 2304 : allocate(rim1(mlon00:mlon11,mlat00:mlat11) ,stat=istat)
381 768 : if (istat /= 0) call endrun('alloc_edyn: rim1')
382 38442 : rim1 = finit
383 2304 : allocate(rim2(mlon00:mlon11,mlat00:mlat11) ,stat=istat)
384 768 : if (istat /= 0) call endrun('alloc_edyn: rim2')
385 38442 : rim2 = finit
386 2304 : allocate(phimsolv(mlon00:mlon11,mlat00:mlat11),stat=istat)
387 768 : if (istat /= 0) call endrun('alloc_edyn: phimsolv')
388 38442 : phimsolv = finit
389 2304 : allocate(phim2d(mlon00:mlon11,mlat00:mlat11),stat=istat)
390 768 : if (istat /= 0) call endrun('alloc_edyn: phim2d')
391 38442 : phim2d = finit
392 : !
393 : ! 3d phim and electric field on mag subdomains:
394 3840 : allocate(phim3d(mlon0:mlon1,mlat0:mlat1,mlev0:mlev1),stat=istat)
395 768 : if (istat /= 0) call endrun('alloc_edyn: phim3d')
396 2446068 : phim3d = finit
397 3840 : allocate(ed13d(mlon0:mlon1,mlat0:mlat1,mlev0:mlev1),stat=istat)
398 768 : if (istat /= 0) call endrun('alloc_edyn: ed13d')
399 2446068 : ed13d = finit
400 3840 : allocate(ed23d(mlon0:mlon1,mlat0:mlat1,mlev0:mlev1),stat=istat)
401 768 : if (istat /= 0) call endrun('alloc_edyn: ed23d')
402 2446068 : ed23d = finit
403 3840 : allocate(ephi3d(mlon0:mlon1,mlat0:mlat1,mlev0:mlev1),stat=istat)
404 768 : if (istat /= 0) call endrun('alloc_edyn: ephi3d')
405 2446068 : ephi3d = finit
406 3840 : allocate(elam3d(mlon0:mlon1,mlat0:mlat1,mlev0:mlev1),stat=istat)
407 768 : if (istat /= 0) call endrun('alloc_edyn: elam3d')
408 2446068 : elam3d = finit
409 3840 : allocate(emz3d(mlon0:mlon1,mlat0:mlat1,mlev0:mlev1),stat=istat)
410 768 : if (istat /= 0) call endrun('alloc_edyn: emz3d')
411 2446068 : emz3d = finit
412 3840 : allocate(zpotm3d(mlon0:mlon1,mlat0:mlat1,mlev0:mlev1),stat=istat)
413 768 : if (istat /= 0) call endrun('alloc_edyn: zpotm3d')
414 2446068 : zpotm3d = finit
415 3840 : allocate(zpot_mag(mlon0:mlon1,mlat0:mlat1,mlev0:mlev1),stat=istat)
416 768 : if (istat /= 0) call endrun('alloc_edyn: zpot_mag')
417 2446068 : zpot_mag = finit
418 : !
419 : ! Fields at mag equator (subdomain longitudes and full column):
420 : !
421 3072 : allocate(ped_meq(mlon0:mlon1,mlev0:mlev1),stat=istat)
422 768 : if (istat /= 0) call endrun('alloc_edyn: ped_meq')
423 774528 : ped_meq = finit
424 3072 : allocate(hal_meq(mlon0:mlon1,mlev0:mlev1),stat=istat)
425 768 : if (istat /= 0) call endrun('alloc_edyn: hal_meq')
426 774528 : hal_meq = finit
427 3072 : allocate(adotv1_meq(mlon0:mlon1,mlev0:mlev1),stat=istat)
428 768 : if (istat /= 0) call endrun('alloc_edyn: adotv1_meq')
429 774528 : adotv1_meq = finit
430 3072 : allocate(adotv2_meq(mlon0:mlon1,mlev0:mlev1),stat=istat)
431 768 : if (istat /= 0) call endrun('alloc_edyn: adotv2_meq')
432 774528 : adotv2_meq = finit
433 : !
434 : ! Fields input to mp_mageq (4 fields at full mag subdomain i,j,k):
435 : !
436 4608 : allocate(fmeq_in(mlon0:mlon1,mlat0:mlat1,mlev0:mlev1,4),stat=istat)
437 768 : if (istat /= 0) call endrun('alloc_edyn: fmeq_in')
438 9785040 : fmeq_in = finit
439 : !
440 : ! Fields output by mp_mageq (4 fields at mag subdomain i,k)
441 : !
442 3840 : allocate(fmeq_out(mlon0:mlon1,mlev0:mlev1,4),stat=istat)
443 768 : if (istat /= 0) call endrun('alloc_edyn: fmeq_out')
444 3098880 : fmeq_out = finit
445 : !
446 : ! 3d electric field on geographic subdomains, with halos:
447 : !
448 3840 : allocate(ex(nlev,lon0:lon1,lat0:lat1),stat=istat)
449 768 : if (istat /= 0) call endrun('alloc_edyn: ex')
450 3840 : allocate(ey(nlev,lon0:lon1,lat0:lat1),stat=istat)
451 768 : if (istat /= 0) call endrun('alloc_edyn: ey')
452 3840 : allocate(ez(nlev,lon0:lon1,lat0:lat1),stat=istat)
453 768 : if (istat /= 0) call endrun('alloc_edyn: ez')
454 10873344 : ex=finit ; ey=finit ; ez=finit
455 : !
456 : ! 3d electric potential on geographic subdomains (k,i,j):
457 3840 : allocate(poten(nlev,lon0:lon1,lat0:lat1),stat=istat)
458 768 : if (istat /= 0) call endrun('alloc_pdyn: poten')
459 3624960 : poten = finit
460 : !
461 : ! 3d electric potential on geographic subdomains ((i,j,k) regridded from phim3d):
462 3840 : allocate(phig3d(lon0:lon1,lat0:lat1,mlev0:mlev1),stat=istat)
463 768 : if (istat /= 0) call endrun('alloc_pdyn: phig3d')
464 3994368 : phig3d = finit
465 : !
466 : ! 2d electric field components on mag grid (these may be input to time3d):
467 : ! real(r8), dimension(:,:) :: ed1,ed2 ! (mlon0-1:mlon1+1,mlat0-1:mlat1+1)
468 : !
469 3072 : allocate(ed1(mlon0-1:mlon1+1,mlat0-1:mlat1+1),stat=istat)
470 768 : if (istat /= 0) call endrun('alloc_edyn: ed1')
471 38442 : ed1 = finit
472 :
473 3072 : allocate(ed2(mlon0-1:mlon1+1,mlat0-1:mlat1+1),stat=istat)
474 768 : if (istat /= 0) call endrun('alloc_edyn: ed2')
475 38442 : ed2 = finit
476 :
477 2304 : allocate(unitvm(nmlon))
478 62208 : unitvm = 1._r8
479 :
480 3072 : allocate(feq_jpm1(nmlonp1,2,nf2d))
481 3072 : allocate(fpole_jpm2(nmlonp1,4,nf2d))
482 4608 : allocate(ed1_glb(nmlat,nmlonp1), ed2_glb(nmlat,nmlonp1))
483 :
484 768 : end subroutine alloc_edyn
485 : !-----------------------------------------------------------------------
486 7296 : subroutine fieldline_integrals( ped_mag, hal_mag, adotv1_mag, adotv2_mag, &
487 7296 : adota1_mag, adota2_mag, a1dta2_mag, be3_mag, sini_mag )
488 : !
489 : ! Integrate along magnetic field lines, saving conductances and rims.
490 : !
491 : use edyn_params, only: r0,h0,finit,kbotdyn
492 : use edyn_maggrid, only: ylatm
493 : !
494 : ! Args:
495 : real(r8), dimension(mlon0:mlon1,mlat0:mlat1,mlev0:mlev1), intent(in) :: &
496 : ped_mag, & ! pedersen conductivity (S/m)
497 : hal_mag, & ! hall conductivity (S/m)
498 : adotv1_mag,& ! ue1 (m/s)
499 : adotv2_mag ! ue2 (m/s)
500 :
501 : real(r8), dimension(mlon0:mlon1,mlat0:mlat1), intent(in) :: &
502 : adota1_mag, &
503 : adota2_mag, &
504 : a1dta2_mag, &
505 : be3_mag, &
506 : sini_mag
507 :
508 : !
509 : ! Local:
510 : integer :: i,j,k
511 : real(r8) :: &
512 : sinlm, & ! sin(lam_m)
513 : clm2, & ! cos^2(lam_m)
514 : ra, & ! (R_E + H_0)/cos^2(lam_m)
515 : sqomrra, & ! sqrt(1/ R_0/R_A) = sin(lam_m)
516 : sqrra, & ! sqrt(R_0/R_A)
517 : afac, & ! 2*sqrt(R_A-R_0) (afac is NaN at mag poles)
518 : htfac ! sqrt(R_A -3/4*R_0)
519 :
520 : real(r8) :: rora,del,omdel,sig1,sig2,ue1,ue2
521 14592 : real(r8), dimension(mlon0:mlon1) :: aam
522 14592 : real(r8), dimension(mlon0:mlon1,mlev0:mlev1) :: rrm, &
523 14592 : rtramrm, htfunc, htfunc2
524 :
525 : !
526 : ! Initialize coefficients:
527 : !
528 365199 : zigm11 = finit
529 365199 : zigm22 = finit
530 365199 : zigm1 = finit
531 365199 : zigm2 = finit
532 365199 : zigmc = finit
533 365199 : rim1 = finit
534 365199 : rim2 = finit
535 : !
536 : ! Subdomain latitude scan for field line integrations:
537 : !
538 29412 : do j=mlat0,mlat1
539 : !
540 : ! Skip poles and equator:
541 22116 : if (j==1.or.j==nmlat.or.j==nmlath) cycle
542 :
543 21432 : sinlm = sin(ylatm(j))
544 21432 : clm2 = 1._r8 - sinlm*sinlm
545 21432 : ra = r0/clm2
546 21432 : sqomrra = sqrt(1._r8-r0/ra)
547 21432 : sqrra = sqrt(r0/ra)
548 21432 : afac = 2._r8*sqrt(ra-r0)
549 21432 : htfac = sqrt(ra-0.75_r8*r0)
550 166098 : do i=mlon0,mlon1
551 166098 : aam(i) = afac/abs(sini_mag(i,j))
552 : enddo
553 : !
554 : ! 2*sqrt( h_A - h_0 )/ |sin I_m | w.r to reference height A(h_R)
555 1500240 : do k=kbotdyn,mlev1
556 11482194 : do i=mlon0,mlon1
557 : !
558 : ! rr = r0+z-z0 radius of magnetic point
559 : ! (Note zpot_mag min was set to h0 in dynamo_inputs)
560 9981954 : rrm(i,k) = r0+zpot_mag(i,j,k)-h0
561 : !
562 : ! rtramr = ra-r if +ive, zero otherwise
563 9981954 : rtramrm(i,k) = max(0._r8,ra-rrm(i,k))
564 11460762 : rtramrm(i,k) = sqrt(rtramrm(i,k))
565 : enddo ! i=mlon0,mlon1
566 : enddo ! k=kbotdyn,mlev1
567 : !
568 : ! Interpolate to midpoints:
569 : ! htfunc = factor by which to multiply AAM(I)*d(sqrt(ra-r)) = ds
570 1478808 : do k=kbotdyn,mlev1-1
571 11316096 : do i=mlon0,mlon1
572 9837288 : rrm(i,k) = 0.5_r8*(rrm(i,k)+rrm(i,k+1))
573 9837288 : rtramrm(i,k) = rtramrm(i,k)-rtramrm(i,k+1)
574 9837288 : htfunc(i,k) = sqrt(ra-0.75_r8*rrm(i,k))/htfac
575 11294664 : htfunc2(i,k) = htfunc(i,k)**2
576 : enddo ! i=mlon0,mlon1
577 : enddo ! k=kbotdyn,mlev1
578 : !
579 : ! Compute integrals:
580 1478808 : do k=kbotdyn,mlev1-1
581 11316096 : do i=mlon0,mlon1
582 : !
583 : ! (R_E+h)/(R_E+h_A) < 1 -> h_A > h
584 9837288 : rora = min(1._r8,rrm(i,k)/ra)
585 : !
586 : ! (lam_m - lam) / lam_m =
587 : ! sqrt(1-r_0/r_A)sqrt(r/r_A) - sqrt(r_0/r_A)sqrt(1-r/r_A)
588 9837288 : del = (sqomrra*sqrt(rora)-sqrra*sqrt(1._r8-rora))/abs(ylatm(j))
589 9837288 : omdel = 1._r8 - del
590 : !
591 : ! Interpolate conductivities and winds in latitude along field line, assuming
592 : ! linear variation between foot of field line and magnetic equator.
593 : ! (For field lines other than those near the magnetic equator, del is nearly
594 : ! zero, so that the interpolated values are essentially the values for the
595 : ! latitude of the foot of the field line; inaccuracy of the assumption of
596 : ! linear variation is thus unimportant for these field lines.)
597 : !
598 : ! Here, mag equator ped_meq, etc. are from mp_mageq, called from dynamo inputs:
599 9837288 : sig1 = omdel*ped_mag(i,j,k) + del*ped_meq(i,k)
600 9837288 : sig2 = omdel*hal_mag(i,j,k) + del*hal_meq(i,k)
601 9837288 : ue1 = omdel*adotv1_mag(i,j,k) + del*adotv1_meq(i,k)
602 9837288 : ue2 = omdel*adotv2_mag(i,j,k) + del*adotv2_meq(i,k)
603 : !
604 : ! height varying factors: ds = aam*htfunc
605 : ! d_1^2/D = 1/htfunc * adota1_mag(i,j)
606 : ! d_2^2/D = htfunc * adota2_mag(i,j)
607 : ! d_1*d_2/D = 1 * a1dta2_mag(i,j)
608 : !
609 : ! zigm11: int (sigma_p*d_1^2/D) ds : d_1^2/D
610 : ! zigm22: int (sigma_p*d_2^2/D) ds : d_2^2/D
611 : !
612 9837288 : zigm11(i,j) = zigm11(i,j) + sig1*rtramrm(i,k)
613 9837288 : zigm22(i,j) = zigm22(i,j) + sig1*rtramrm(i,k)*htfunc2(i,k)
614 :
615 : !
616 : ! zigmc: int (sigma_p*d_1*d_2/D) ds
617 : ! zigm2: int (sigma_h) ds
618 : !
619 9837288 : zigmc(i,j) = zigmc(i,j) + sig1*rtramrm(i,k)*htfunc(i,k)
620 9837288 : zigm2(i,j) = zigm2(i,j) + sig2*rtramrm(i,k)*htfunc(i,k)
621 :
622 : ! zigm1: int(sigma_p) ds
623 9837288 : zigm1(i,j) = zigm1(i,j) + sig1*rtramrm(i,k)*htfunc(i,k)
624 : !
625 : ! rim1: int [sigma_p*d_1^2/D u_e2+(sigma_h-(sigma_p*d_1*d_2)/D) u_e1] ds
626 : ! rim2: int [(sigma_h+sigma_p*d_1*d_2/D) u_e2-sigma_p*d_2^2/D u_e1 ] ds
627 : !
628 0 : rim1(i,j) = rim1(i,j) + (sig1*adota1_mag(i,j)*ue2 + &
629 9837288 : (sig2 - sig1*a1dta2_mag(i,j))*htfunc(i,k)*ue1)*rtramrm(i,k)
630 0 : rim2(i,j) = rim2(i,j) + (sig1*adota2_mag(i,j)*htfunc2(i,k)* &
631 11294664 : ue1 - (sig2 + sig1*a1dta2_mag(i,j))*htfunc(i,k)*ue2)*rtramrm(i,k)
632 : enddo ! i=mlon0,mlon1
633 : enddo ! k=kbotdyn,mlev1
634 : !
635 : ! Complete calculation and place result in /coefm/ zigm's
636 : ! rim's are in A/m multiply by 1/100 to convert from [cm] to [m]
637 : !
638 : ! At this point,
639 : ! zigm11 is int[sig_p*d_1^2/D] ds, i.e. Sigma_(phi phi)/abs(sin Im)
640 : ! zigm22 is int[sig_p*d_2^2/D] ds, i.e. Sigma_(lam lam)*abs(sin Im)
641 : ! zigmc is int[sig_p*d_1*d_2/D] ds, i.e. Sigma_c
642 : ! zigm2 is int[sigma_h] ds, i.e. Sigma_h
643 : !
644 : ! rim1 is int[(sigma_h-sigma_p*d_1*d_2/D)u_e1 + sigma_p*d_1^2/D u_e2] *A(h_r)*
645 : ! B_e3 ds, i.e. K_(m phi)^D/abs(sin Im)
646 : ! rim2 is int[(sigma_h+sigma_p*d_1*d_2/D)u_e2 - sigma_p*d_2^2/D u_e1] *A(h_r)*
647 : ! B_e3 ds, K_(m lam)^D ( minus in northern hemisphere
648 : ! Change sign of RIM(2) in S. hemisphere to be compatible with transf
649 : ! At this point, rim2 is +-K_(m lam)^D
650 : !
651 173394 : do i = mlon0,mlon1
652 144666 : zigm11(i,j) = 1.e-2_r8*zigm11(i,j)*aam(i)*adota1_mag(i,j)
653 144666 : zigm22(i,j) = 1.e-2_r8*zigm22(i,j)*aam(i)*adota2_mag(i,j)
654 144666 : zigmc(i,j) = 1.e-2_r8*zigmc (i,j)*aam(i)*a1dta2_mag(i,j)
655 144666 : zigm2(i,j) = 1.e-2_r8*zigm2 (i,j)*aam(i)
656 144666 : zigm1(i,j) = 1.e-2_r8*zigm1 (i,j)*aam(i)
657 144666 : rim1(i,j) = 1.e-2_r8*rim1(i,j)*aam(i)*be3_mag(i,j)
658 166782 : rim2(i,j) = 1.e-2_r8*rim2(i,j)*aam(i)*be3_mag(i,j)
659 : enddo ! i = 1,nmlon
660 : enddo ! j=mlat0,mlat1 (without poles)
661 :
662 7296 : if (debug_hist) then
663 0 : call savefld_waccm(adota1_mag(mlon0:mlon1,mlat0:mlat1) ,'adota1_mag_a' ,1,mlon0,mlon1,mlat0,mlat1)
664 0 : call savefld_waccm(zigm11(mlon0:mlon1,mlat0:mlat1) ,'ZIGM11_a' ,1,mlon0,mlon1,mlat0,mlat1)
665 : endif
666 :
667 7296 : end subroutine fieldline_integrals
668 : !-----------------------------------------------------------------------
669 7296 : subroutine complete_integrals
670 : use edyn_mpi, only: mlat0, mlat1, mlon0, mlon1, mp_mageq_jpm1
671 : use edyn_mpi, only: mp_magpole_2d, mp_mag_foldhem, mp_mag_periodic_f2d
672 : use edyn_maggrid, only: rcos0s,dt1dts
673 : !
674 : ! Field line integrals for each hemisphere have been calculated in
675 : ! mag subdomains. Now, complete these arrays with equator and polar
676 : ! values, and sum the integrals from the 2 hemispheres.
677 : ! This is done by obtaining global mag fields via mpi exchange
678 : ! of mag subdomains, completing the global fields, and updating
679 : ! the subdomains.
680 : ! The 6 2d fields are: zigm11,zigm22,zigmc,zigm2,rim1,rim2
681 : !
682 : ! Local:
683 : integer :: i,j,ii,lonend
684 14592 : real(r8) :: fmsub(mlon0:mlon1,mlat0:mlat1,nf2d)
685 : real(r8) :: corfac
686 : real(r8) :: r8_nmlon
687 7296 : r8_nmlon = real(nmlon, r8)
688 : !
689 : ! For equatorial values, we need latitudes eq+1 and eq-1:
690 : ! Local feq_jpm1(nmlonp1,2,6) is returned by mp_mageq_jpm1,
691 : ! where the 2 dim contains lats nmlath-1, nmlath+1. These
692 : ! are global in lon, even tho each subd uses only its own i's.
693 : ! These mag equator values do not show up on plots because
694 : ! of the small factor .06 and .125.
695 : ! The 6 2d fields are: zigm11,zigm22,zigmc,zigm2,rim1,rim2
696 : ! Must specify mlon0:mlon1,mlat0:mlat1 because these fields
697 : ! were allocated to include single-point halos (these calls
698 : ! exclude the halo points):
699 : !
700 178695 : fmsub(:,:,1) = zigm11(mlon0:mlon1,mlat0:mlat1)
701 178695 : fmsub(:,:,2) = zigm22(mlon0:mlon1,mlat0:mlat1)
702 178695 : fmsub(:,:,3) = zigmc (mlon0:mlon1,mlat0:mlat1)
703 178695 : fmsub(:,:,4) = zigm2 (mlon0:mlon1,mlat0:mlat1)
704 178695 : fmsub(:,:,5) = rim1 (mlon0:mlon1,mlat0:mlat1)
705 178695 : fmsub(:,:,6) = rim2 (mlon0:mlon1,mlat0:mlat1)
706 178695 : fmsub(:,:,7) = zigm1 (mlon0:mlon1,mlat0:mlat1)
707 :
708 7296 : call mp_mageq_jpm1(fmsub,mlon0,mlon1,mlat0,mlat1,nmlonp1,feq_jpm1,nf2d)
709 : !
710 : ! From sub fieldline_integrals:
711 : ! zigm11 is int[sig_p*d_1^2/D] ds, i.e. Sigma_(phi phi)/abs(sin Im)
712 : ! zigm22 is int[sig_p*d_2^2/D] ds, i.e. Sigma_(lam lam)*abs(sin Im)
713 : ! zigmc is int[sig_p*d_1*d_2/D] ds, i.e. Sigma_c
714 : ! zigm2 is int[sigma_h] ds, i.e. Sigma_h
715 : !
716 : ! rim1 is int[(sigma_h-sigma_p*d_1*d_2/D)u_e1 + sigma_p*d_1^2/D u_e2] *A(h_r)*
717 : ! B_e3 ds, i.e. K_(m phi)^D/abs(sin Im)
718 : ! rim2 is int[(sigma_h+sigma_p*d_1*d_2/D)u_e2 - sigma_p*d_2^2/D u_e1] *A(h_r)*
719 : ! B_e3 ds, K_(m lam)^D ( minus in northern hemisphere
720 : ! Change sign of RIM(2) in S. hemisphere to be compatible with transf
721 : ! At this point, rim2 is +-K_(m lam)^D
722 : !
723 : ! Equatorial values:
724 : ! Assume that quantities primarily dependent on Pedersen conductivity
725 : ! have field-line integrals 1/4 as large as the averages for next-higher
726 : ! field lines; quantities primarily dependent on Hall conductivity
727 : ! have field-line integrals 0.12 as large as the averages for next-higher
728 : ! field lines. Exact values chosen should not be important for potential
729 : ! calculation, as long as they are physically reasonable and not too
730 : ! different from adjacent values.
731 : !
732 29412 : do j=mlat0,mlat1
733 29412 : if (j==nmlath) then ! mag equator
734 :
735 0 : zigm11(mlon0:mlon1,j) = .125_r8*(feq_jpm1(mlon0:mlon1,1,1)+ &
736 1767 : feq_jpm1(mlon0:mlon1,2,1))
737 0 : zigm22(mlon0:mlon1,j) = .125_r8*(feq_jpm1(mlon0:mlon1,1,2)+ &
738 1767 : feq_jpm1(mlon0:mlon1,2,2))
739 0 : zigmc (mlon0:mlon1,j) = .125_r8*(feq_jpm1(mlon0:mlon1,1,3)+ &
740 1767 : feq_jpm1(mlon0:mlon1,2,3))
741 0 : zigm2 (mlon0:mlon1,j) = .060_r8*(feq_jpm1(mlon0:mlon1,1,4)+ &
742 1767 : feq_jpm1(mlon0:mlon1,2,4))
743 0 : rim1 (mlon0:mlon1,j) = .060_r8*(feq_jpm1(mlon0:mlon1,1,5)+ &
744 1767 : feq_jpm1(mlon0:mlon1,2,5))
745 0 : rim2 (mlon0:mlon1,j) = .060_r8*(feq_jpm1(mlon0:mlon1,1,6)+ &
746 1767 : feq_jpm1(mlon0:mlon1,2,6))
747 0 : zigm1 (mlon0:mlon1,j) = .060_r8*(feq_jpm1(mlon0:mlon1,1,7)+ &
748 1767 : feq_jpm1(mlon0:mlon1,2,7))
749 : !
750 : ! Include the boundary condition at the equator eq.(5.30) in
751 : ! Richmond (1995) Ionospheric Electrodynamics use. Mag. Apex Coord.
752 : ! J.Geomag.Geoelectr. 47,191-212
753 : ! Sig_phiphi/abs(sin Im) = 0.5*Sig_cowling/abs(sin Im)
754 : ! = 0.5/abs(sin Im)*(Sig_phiphi - Sig_philam*sig_lamphi/Sig_lamlam)
755 : ! = 0.5/abs(sin Im)*(Sig_phiphi + (Sig_h-sig_c)*(Sig_h+sig_c)/Sig_lamlam)
756 : ! rim(1) / |sin I_m| = I_1 = R/2*(K_mphi - Sig_philam/Sig_lamlam*K_mlam)
757 : !
758 1767 : do i=mlon0,mlon1
759 0 : zigm11(i,j) = zigm11(i,j)+(zigm2(i,j)-zigmc(i,j))* &
760 1539 : (zigm2(i,j)+zigmc(i,j))/zigm22(i,j)
761 0 : rim1(i,j) = rim1(i,j) - (zigm2(i,j)-zigmc(i,j))/ &
762 1767 : zigm22(i,j)*rim2(i,j)
763 : enddo ! i=mlon0,mlon1
764 : endif ! j at equator
765 : enddo ! j=mlat0,mlat1
766 : !
767 : ! Using notation of Richmond (1995) on right-hand side below:
768 : ! Sigma_(phi phi) = zigm11*abs(sin I_m)
769 : ! Sigma_(lam lam) = zigm22/abs(sin I_m)
770 : ! Sigma_(phi lam) = +-(zigm2-zigmc)
771 : ! Sigma_(lam phi) = -+(zigm2+zigmc)
772 : ! K_(m phi)^D = rim(1)*abs(sin I_m)
773 : ! K_(m lam)^D = +-rim(2)
774 : !
775 : ! Transforming PDE from original apex (theta_a) to new apex grid (theta_0)
776 : ! which is equally spaced in magnetic latitude
777 : ! SCALE quantities to modified (0) magnetic latitude system, multiplying or
778 : ! dividing by abs(sin I_m) [inverse contained in DT1DTS] as necessary.
779 : ! Sign of K_(m lam)^D in southern hemisphere remains reversed.
780 : ! for the mixed terms the transformation from the integration and differentiation
781 : ! canceled out (zigmc, zigm2)
782 : ! DT1DTS : d theta_0/ d theta_a / abs(sin I_m)
783 : ! RCOS0S : cos(theta_0)/ cos(theta_a)
784 : !
785 : ! corfac: abs(I_m)*d theta_a/d theta_0 * cos(theta_0)/ cos(theta_a)
786 : ! zigm11: abs(I_m)*d theta_a/d theta_0 * cos(theta_0)/ cos(theta_a)
787 : ! zigm22: 1/abs(I_m)*d theta_0/d theta_a * cos(theta_a)/ cos(theta_0)
788 : ! rim(1): abs(I_m)*d theta_a/d theta_0
789 : ! rim(2): cos(theta_a)/ cos(theta_0)
790 : !
791 29412 : do j=mlat0,mlat1
792 22116 : if (j==1.or.j==nmlat) cycle ! skip poles
793 21660 : corfac = rcos0s(j)/dt1dts(j)
794 175161 : do i=mlon0,mlon1
795 146205 : zigm11(i,j) = zigm11(i,j)*corfac
796 146205 : zigm22(i,j) = zigm22(i,j)/corfac
797 146205 : rim1(i,j) = rim1(i,j)/dt1dts(j)
798 168321 : rim2(i,j) = rim2(i,j)/rcos0s(j)
799 : enddo
800 : enddo
801 : !
802 : ! For polar values, we need south pole plus 1 and 2 (j==2,3),
803 : ! and north pole minus 1 and 2 (j==nmlat-1,nmlat-2). These
804 : ! are returned by sub mp_magpole_jpm2 (mpi.F):
805 : ! Must specify (mlon0:mlon1,mlat0:mlat1) because zigmxx and rims
806 : ! are allocated to include halo cells.
807 : !
808 178695 : fmsub(:,:,1) = zigm11(mlon0:mlon1,mlat0:mlat1)
809 185991 : fmsub(:,:,2) = zigm22(mlon0:mlon1,mlat0:mlat1)
810 185991 : fmsub(:,:,3) = zigmc (mlon0:mlon1,mlat0:mlat1)
811 185991 : fmsub(:,:,4) = zigm2 (mlon0:mlon1,mlat0:mlat1)
812 185991 : fmsub(:,:,5) = rim1 (mlon0:mlon1,mlat0:mlat1)
813 185991 : fmsub(:,:,6) = rim2 (mlon0:mlon1,mlat0:mlat1)
814 185991 : fmsub(:,:,7) = zigm1 (mlon0:mlon1,mlat0:mlat1)
815 : !
816 : ! mp_magpole_2d returns fpole_jpm2(nmlonp1,1->4,nf) as:
817 : ! 1: j = 2 (spole+1)
818 : ! 2: j = 3 (spole+2)
819 : ! 3: j = nmlat-1 (npole-1)
820 : ! 4: j = nmlat-2 (npole-2)
821 : !
822 : call mp_magpole_2d(fmsub,mlon0,mlon1,mlat0,mlat1,nmlonp1, &
823 7296 : 1,nmlat,fpole_jpm2,nf2d)
824 : !
825 : ! the PDE is divided by 1/ DT0DTS
826 : ! Sigma_(phi phi) = zigm11/ rcos0s * dt0dts
827 : ! Sigma_(lam lam) = zigm22 * rcos0s / dt0dts
828 : ! Sigma_(phi lam) = +-(zigm2-zigmc)
829 : ! Sigma_(lam phi) = -+(zigm2+zigmc)
830 : ! K_(m phi)^D = rim(1) * dt0dts
831 : ! K_(m lam)^D = +-rim(2) * rcos0s
832 : !
833 : ! Compute polar values for the conductances, 4th order interpolation:
834 : !
835 29412 : do j=mlat0,mlat1
836 : !
837 : ! South pole:
838 29412 : if (j==1) then ! south pole (use fpole_jpm2(nmlon,1->2,nf)
839 0 : zigm11(mlon0,j)=(4._r8* &
840 228 : dot_product(unitvm,fpole_jpm2(1:nmlon,1,1))- &
841 228 : dot_product(unitvm,fpole_jpm2(1:nmlon,2,1)))/ &
842 37164 : (3._r8*r8_nmlon)
843 0 : zigm22(mlon0,j)=(4._r8* &
844 228 : dot_product(unitvm,fpole_jpm2(1:nmlon,1,2))- &
845 228 : dot_product(unitvm,fpole_jpm2(1:nmlon,2,2)))/ &
846 37164 : (3._r8*r8_nmlon)
847 0 : zigmc (mlon0,j)=(4._r8* &
848 228 : dot_product(unitvm,fpole_jpm2(1:nmlon,1,3))- &
849 228 : dot_product(unitvm,fpole_jpm2(1:nmlon,2,3)))/ &
850 37164 : (3._r8*r8_nmlon)
851 0 : zigm2 (mlon0,j)=(4._r8* &
852 228 : dot_product(unitvm,fpole_jpm2(1:nmlon,1,4))- &
853 228 : dot_product(unitvm,fpole_jpm2(1:nmlon,2,4)))/ &
854 37164 : (3._r8*r8_nmlon)
855 0 : zigm1(mlon0,j) = (4._r8* &
856 228 : dot_product(unitvm,fpole_jpm2(1:nmlon,1,7))- &
857 228 : dot_product(unitvm,fpole_jpm2(1:nmlon,2,7)))/ &
858 37164 : (3._r8*r8_nmlon)
859 : !
860 : ! Extend south pole over longitude:
861 1539 : do i=mlon0+1,mlon1
862 1311 : zigm11(i,j) = zigm11(mlon0,j)
863 1311 : zigm22(i,j) = zigm22(mlon0,j)
864 1311 : zigmc (i,j) = zigmc (mlon0,j)
865 1311 : zigm2 (i,j) = zigm2 (mlon0,j)
866 1539 : zigm1 (i,j) = zigm1 (mlon0,j)
867 : enddo ! i=mlon0,mlon1
868 : !
869 : ! RHS vector (I_1,I_2): average over south pole:
870 : ! (use fpole_jpm2(i,1,nf), i.e. j==2, and lons across the pole)
871 228 : lonend = mlon1
872 228 : if (mlon1==nmlonp1) lonend = mlon1-1
873 1748 : do i=mlon0,lonend
874 1520 : ii = 1+mod(i-1+nmlon/2,nmlon)
875 1520 : rim1(i,j) = 0.5_r8*(fpole_jpm2(i,1,5)-fpole_jpm2(ii,1,5))
876 1748 : rim2(i,j) = 0.5_r8*(fpole_jpm2(i,1,6)-fpole_jpm2(ii,1,6))
877 : enddo
878 : !
879 : ! North pole:
880 21888 : elseif (j==nmlat) then ! north pole (use fpole_jpm2(nmlon,3->4,1,nf)
881 0 : zigm11(mlon0,j)=(4._r8* &
882 228 : dot_product(unitvm,fpole_jpm2(1:nmlon,3,1))- &
883 228 : dot_product(unitvm,fpole_jpm2(1:nmlon,4,1)))/ &
884 37164 : (3._r8*r8_nmlon)
885 0 : zigm22(mlon0,j)=(4._r8* &
886 228 : dot_product(unitvm,fpole_jpm2(1:nmlon,3,2))- &
887 228 : dot_product(unitvm,fpole_jpm2(1:nmlon,4,2)))/ &
888 37164 : (3._r8*r8_nmlon)
889 0 : zigmc (mlon0,j)=(4._r8* &
890 228 : dot_product(unitvm,fpole_jpm2(1:nmlon,3,3))- &
891 228 : dot_product(unitvm,fpole_jpm2(1:nmlon,4,3)))/ &
892 37164 : (3._r8*r8_nmlon)
893 0 : zigm2 (mlon0,j)=(4._r8* &
894 228 : dot_product(unitvm,fpole_jpm2(1:nmlon,3,4))- &
895 228 : dot_product(unitvm,fpole_jpm2(1:nmlon,4,4)))/ &
896 37164 : (3._r8*r8_nmlon)
897 0 : zigm1(mlon0,j) = (4._r8* &
898 228 : dot_product(unitvm,fpole_jpm2(1:nmlon,3,7))- &
899 228 : dot_product(unitvm,fpole_jpm2(1:nmlon,4,7)))/ &
900 37164 : (3._r8*r8_nmlon)
901 : !
902 : ! Extend north pole over longitude:
903 1539 : do i=mlon0+1,mlon1
904 1311 : zigm11(i,j) = zigm11(mlon0,j)
905 1311 : zigm22(i,j) = zigm22(mlon0,j)
906 1311 : zigmc (i,j) = zigmc (mlon0,j)
907 1311 : zigm2 (i,j) = zigm2 (mlon0,j)
908 1539 : zigm1 (i,j) = zigm1 (mlon0,j)
909 : enddo ! i=mlon0,mlon1
910 : !
911 : ! RHS vector (I_1,I_2): average over north pole:
912 : ! (use fpole_jpm2(i,3,nf), i.e. j==nmlat-1, and lons across the pole)
913 228 : lonend = mlon1
914 228 : if (mlon1==nmlonp1) lonend = mlon1-1
915 1748 : do i=mlon0,lonend
916 1520 : ii = 1+mod(i-1+nmlon/2,nmlon)
917 1520 : rim1(i,j) = 0.5_r8*(fpole_jpm2(i,3,5)-fpole_jpm2(ii,3,5))
918 1748 : rim2(i,j) = 0.5_r8*(fpole_jpm2(i,3,6)-fpole_jpm2(ii,3,6))
919 : enddo
920 : endif ! south or north pole
921 : enddo ! j=mlat0,mlat1
922 : !
923 : ! Fold south hemisphere over onto north, and set periodic points:
924 178695 : fmsub(:,:,1) = zigm11(mlon0:mlon1,mlat0:mlat1)
925 185991 : fmsub(:,:,2) = zigm22(mlon0:mlon1,mlat0:mlat1)
926 185991 : fmsub(:,:,3) = zigmc (mlon0:mlon1,mlat0:mlat1)
927 185991 : fmsub(:,:,4) = zigm2 (mlon0:mlon1,mlat0:mlat1)
928 185991 : fmsub(:,:,5) = rim1 (mlon0:mlon1,mlat0:mlat1)
929 185991 : fmsub(:,:,6) = rim2 (mlon0:mlon1,mlat0:mlat1)
930 185991 : fmsub(:,:,7) = zigm1 (mlon0:mlon1,mlat0:mlat1)
931 :
932 7296 : call mp_mag_foldhem(fmsub,mlon0,mlon1,mlat0,mlat1,nf2d)
933 7296 : call mp_mag_periodic_f2d(fmsub,mlon0,mlon1,mlat0,mlat1,nf2d)
934 :
935 178695 : zigm11(mlon0:mlon1,mlat0:mlat1) = fmsub(:,:,1)
936 185991 : zigm22(mlon0:mlon1,mlat0:mlat1) = fmsub(:,:,2)
937 185991 : zigmc (mlon0:mlon1,mlat0:mlat1) = fmsub(:,:,3)
938 185991 : zigm2 (mlon0:mlon1,mlat0:mlat1) = fmsub(:,:,4)
939 185991 : rim1 (mlon0:mlon1,mlat0:mlat1) = fmsub(:,:,5)
940 185991 : rim2 (mlon0:mlon1,mlat0:mlat1) = fmsub(:,:,6)
941 185991 : zigm1 (mlon0:mlon1,mlat0:mlat1) = fmsub(:,:,7)
942 : !
943 : ! Reverse sign of zigmc in northern hemisphere.
944 29412 : do j=mlat0,mlat1
945 22116 : if (j >= nmlath) then
946 86583 : zigmc(mlon0:mlon1,j) = -zigmc(mlon0:mlon1,j)
947 : endif
948 22116 : if (debug_hist) then
949 0 : call outfld('EDYN_RIM1',rim1(mlon0:omlon1,j),omlon1-mlon0+1,j)
950 0 : call outfld('EDYN_RIM2',rim2(mlon0:omlon1,j),omlon1-mlon0+1,j)
951 : endif
952 22116 : call outfld('PED_CONDUCTANCE', zigm2(mlon0:omlon1,j),omlon1-mlon0+1,j)
953 29412 : call outfld('HALL_CONDUCTANCE',zigm1(mlon0:omlon1,j),omlon1-mlon0+1,j)
954 : enddo
955 :
956 7296 : if (debug.and.masterproc) then
957 0 : write(iulog,"('complete_integrals: nstep=',i4)") nstep
958 : write(iulog,"(' zigm11 min,max=',2e12.4)") &
959 0 : minval(zigm11(mlon0:mlon1,mlat0:mlat1)),maxval(zigm11(mlon0:mlon1,mlat0:mlat1))
960 : write(iulog,"(' zigm22 min,max=',2e12.4)") &
961 0 : minval(zigm22(mlon0:mlon1,mlat0:mlat1)),maxval(zigm22(mlon0:mlon1,mlat0:mlat1))
962 : write(iulog,"(' zigmc min,max=',2e12.4)") &
963 0 : minval(zigmc (mlon0:mlon1,mlat0:mlat1)),maxval(zigmc (mlon0:mlon1,mlat0:mlat1))
964 : write(iulog,"(' zigm2 min,max=',2e12.4)") &
965 0 : minval(zigm2 (mlon0:mlon1,mlat0:mlat1)),maxval(zigm2 (mlon0:mlon1,mlat0:mlat1))
966 : write(iulog,"(' rim1 min,max=',2e12.4)") &
967 0 : minval(rim1 (mlon0:mlon1,mlat0:mlat1)),maxval(rim1 (mlon0:mlon1,mlat0:mlat1))
968 : write(iulog,"(' rim2 min,max=',2e12.4)") &
969 0 : minval(rim2 (mlon0:mlon1,mlat0:mlat1)),maxval(rim2 (mlon0:mlon1,mlat0:mlat1))
970 : endif
971 :
972 7296 : if (debug_hist) then
973 0 : call savefld_waccm(zigm11(mlon0:mlon1,mlat0:mlat1) ,'EDYN_ZIGM11' ,1,mlon0,mlon1,mlat0,mlat1)
974 0 : call savefld_waccm(zigm22(mlon0:mlon1,mlat0:mlat1) ,'EDYN_ZIGM22' ,1,mlon0,mlon1,mlat0,mlat1)
975 0 : call savefld_waccm(zigmc (mlon0:mlon1,mlat0:mlat1) ,'EDYN_ZIGMC' ,1,mlon0,mlon1,mlat0,mlat1)
976 0 : call savefld_waccm(zigm2 (mlon0:mlon1,mlat0:mlat1) ,'EDYN_ZIGM2' ,1,mlon0,mlon1,mlat0,mlat1)
977 0 : call savefld_waccm(rim1 (mlon0:mlon1,mlat0:mlat1) ,'EDYN_RIM1' ,1,mlon0,mlon1,mlat0,mlat1)
978 0 : call savefld_waccm(rim2 (mlon0:mlon1,mlat0:mlat1) ,'EDYN_RIM2' ,1,mlon0,mlon1,mlat0,mlat1)
979 : endif
980 :
981 7296 : end subroutine complete_integrals
982 : !-----------------------------------------------------------------------
983 7296 : subroutine rhspde()
984 : use edyn_params, only: pi_dyn, r0
985 : use edyn_maggrid, only: dlatm, dlonm, rcos0s, dt1dts
986 : !
987 : ! Calculate right-hand side from rim1,2 on mag subdomains.
988 : ! Use global longitude arrays for poles and equator obtained
989 : ! by sub complete_integrals.
990 : !
991 : ! Local:
992 : integer :: j,i
993 14592 : real(r8), dimension(nmlat) :: tint1
994 : real(r8) :: &
995 14592 : rim2_npm1(nmlonp1), & ! global rim2 at nmlat-1
996 14592 : rim2_eqp1(nmlonp1), & ! global rim2 at meq+1
997 14592 : rim2_meq (nmlonp1), & ! global rim2 at mag eq
998 14592 : rim2_tmp (nmlonp1), & ! temp array
999 14592 : rim1_meq (nmlonp1), & ! global rim1 at mag eq
1000 14592 : zigm2_meq(nmlonp1), & ! needed for rim1_meq
1001 14592 : zigmc_meq(nmlonp1), & ! needed for rim1_meq
1002 14592 : zigm22_meq(nmlonp1) ! needed for rim1_meq
1003 : real(r8) :: r8_nmlon
1004 7296 : r8_nmlon = real(nmlon, r8)
1005 :
1006 715008 : do j=1,nmlat
1007 715008 : tint1(j) = cos(-pi_dyn/2._r8+(j-1)*dlatm)
1008 : enddo
1009 : !
1010 : ! Init rhs subdomains:
1011 365199 : rhs(:,:) = finit
1012 : !
1013 : ! Will need rim2 at npole-1 and mag equator:
1014 : ! rim2_npm1: global rim2 at nmlat-1:
1015 598272 : rim2_npm1(:) = fpole_jpm2(:,3,6)+fpole_jpm2(:,1,6)
1016 : !
1017 : ! rim2_meq: global rim2 at mag equator:
1018 598272 : rim2_meq(:) = .060_r8*(feq_jpm1(:,1,6)+feq_jpm1(:,2,6))
1019 598272 : rim2_meq(:) = rim2_meq(:)/rcos0s(nmlath)
1020 598272 : rim2_meq(:) = rim2_meq(:)*2._r8 ! fold eq on itself
1021 : !
1022 : ! Perform differentiation of rim(2) w.r.t. lam_0:
1023 : ! +/- (d [ K_(m lam)^D * cos(lam_m)]/ d lam_0 ) /cos ( lam_0) =
1024 : ! + (d [ K_(m lam)^D * cos(lam_m)]/ d lam_m ) /cos ( lam_m) / (RCOS0S*DT0DTS) =
1025 : ! +/- (d [ K_(m lam)^D(0) * cos(lam_0)]/ d lam_0 ) /cos ( lam_0) =
1026 : !
1027 : ! Lat scan to define rhs subdomains:
1028 29412 : do j=mlat0,mlat1
1029 : !
1030 : ! North Pole (redundant in longitude):
1031 29412 : if (j == nmlat) then ! north pole
1032 1767 : do i=mlon0,mlon1
1033 1539 : rhs(i,j) = -2._r8/r8_nmlon*dot_product(unitvm,rim2_npm1(1:nmlon))/ &
1034 126426 : tint1(nmlat-1)
1035 : enddo
1036 : !
1037 : ! Include the boundary condition at the equator.
1038 : ! rhs(equator)/R = d (K_mphi^DT(0) - sig_philam/sig_lamlam*K_mlam^DT(0)) / d phi_m
1039 : ! + d (cos lam_0 * K_mlam^DT(0))/ d lam_0
1040 : ! from Cicely's notes:
1041 : ! I_1 = 0.5*(K_(m phi)^DT(0) - Sig_(phi lam)/Sig_(lam lam)*K_(ml am)^DT(0))
1042 : ! I_2 = K_(m lam)^DT(0)
1043 : ! differentiate
1044 : ! rhs = (I_1(i+1/2,j)-I_1(i-1/2,j))/dlonm +
1045 : ! (2*cos(lam_0)_(j+1/2)*I_2(i,j+1/2))/dlat_0
1046 : ! (first calc global mag equator as in complete_integrals)
1047 : !
1048 21888 : elseif (j == nmlath) then ! mag equator
1049 0 : rim2_eqp1(:) = feq_jpm1(:,2,6)/rcos0s(j-1)+ &
1050 18696 : feq_jpm1(:,1,6)/rcos0s(j+1)
1051 18696 : zigm22_meq(:) = .125_r8*(feq_jpm1(:,1,2)+feq_jpm1(:,2,2))
1052 18696 : zigmc_meq (:) = .125_r8*(feq_jpm1(:,1,3)+feq_jpm1(:,2,3))
1053 18696 : zigm2_meq (:) = .060_r8*(feq_jpm1(:,1,4)+feq_jpm1(:,2,4))
1054 18696 : rim1_meq (:) = .060_r8*(feq_jpm1(:,1,5)+feq_jpm1(:,2,5))
1055 18696 : rim2_tmp (:) = .060_r8*(feq_jpm1(:,1,6)+feq_jpm1(:,2,6))
1056 18696 : do i=1,nmlonp1
1057 18468 : rim1_meq(i) = rim1_meq(i) - (zigm2_meq(i)-zigmc_meq(i))/ &
1058 37164 : zigm22_meq(i)*rim2_tmp(i)
1059 : enddo
1060 18696 : rim1_meq(:) = rim1_meq(:)/dt1dts(j)
1061 18696 : rim1_meq(:) = rim1_meq(:)*2._r8 ! fold eq on itself
1062 :
1063 1767 : do i=mlon0,mlon1
1064 1767 : if (i==1) then ! western most lon
1065 19 : rhs(i,j) = 0.5_r8/dlonm*(rim1(i+1,j)-rim1_meq(nmlon))
1066 19 : rhs(i,j) = rhs(i,j)+1._r8/dlatm*(tint1(j)*rim2(i,j)+ &
1067 38 : tint1(j+1)*rim2_eqp1(i))
1068 1520 : elseif (i==nmlonp1) then ! eastern most lon
1069 19 : rhs(i,j) = 0.5_r8/dlonm*(rim1_meq(1)-rim1(i-1,j))
1070 19 : rhs(i,j) = rhs(i,j)+1._r8/dlatm*(tint1(j)*rim2(i,j)+ &
1071 38 : tint1(j+1)*rim2_eqp1(i))
1072 : else ! body of i subdomain
1073 : ! Note that rim1 halos were set before calling this subroutine.
1074 1501 : rhs(i,j) = 0.5_r8/dlonm*(rim1(i+1,j)-rim1(i-1,j))
1075 1501 : rhs(i,j) = rhs(i,j)+1._r8/dlatm*(tint1(j)*rim2(i,j)+ &
1076 3002 : tint1(j+1)*rim2_eqp1(i))
1077 : endif
1078 : enddo ! i=mlon0,mlon1
1079 : !
1080 : ! North hemisphere (not npole and not equator):
1081 : ! (allow south hemisphere to remain 0)
1082 : ! (use rim1 instead of tint33)
1083 : !
1084 21660 : elseif (j > nmlath) then ! north hem only (excluding npole)
1085 83049 : do i=mlon0,mlon1
1086 72333 : rhs(i,j) = 1._r8/(dlonm*tint1(j))*0.5_r8*(rim1(i+1,j)-rim1(i-1,j))
1087 83049 : if (j == nmlath+1) then
1088 0 : rhs(i,j) = rhs(i,j)+1._r8/(dlatm*tint1(j))* &
1089 1539 : 0.5_r8*(rim2(i,j+1)*tint1(j+1)-rim2_meq(i)*tint1(j-1))
1090 : else
1091 0 : rhs(i,j) = rhs(i,j)+1._r8/(dlatm*tint1(j))* &
1092 70794 : 0.5_r8*(rim2(i,j+1)*tint1(j+1)-rim2(i,j-1)*tint1(j-1))
1093 : endif
1094 : enddo
1095 : endif ! at poles or equator
1096 : enddo ! j=mlat0,mlat1
1097 : !
1098 : ! scale (multiply by earth radius in meter = R0*1.E-2)
1099 : ![( d K_(m phi)^D / d phi /(cos(theta_m)?) +
1100 : ! (d [ K_(m lam)^D * cos(lam_m)]/ d lam_m ) /cos ( lam_m) ] * R / (RCOS0S*DT0DTS)
1101 : ! ~ J_(Mr)*r^2*cos(theta_m)/cos(theta_0)/DT0DTS
1102 : ! theta_m = theta_s
1103 : !
1104 29412 : do j=mlat0,mlat1
1105 178695 : do i=mlon0,mlon1
1106 171399 : rhs(i,j) = rhs(i,j)*r0*1.e-2_r8
1107 : enddo
1108 : enddo
1109 :
1110 7296 : end subroutine rhspde
1111 : !-----------------------------------------------------------------------
1112 7296 : subroutine gather_edyn()
1113 : !
1114 : ! Gather needed global arrays to root task, so it can finish non-parallel
1115 : ! part of dynamo (beginning after sub rhspde) as in original code
1116 : !
1117 : use edyn_mpi, only: mp_gather_edyn
1118 : use edyn_solve, only: & ! (nmlonp1,nmlat)
1119 : zigm11_glb, &
1120 : zigm22_glb, &
1121 : zigmc_glb, &
1122 : zigm2_glb, &
1123 : rhs_glb
1124 : use edyn_solve, only: rim_glb ! pde solver output (nmlonp1,nmlat,2)
1125 : !
1126 : ! Local:
1127 : ! 7 fields to gather: zigm11,zigm22,zigmc,zigm2,rim1,rim2,rhs
1128 : !
1129 : integer, parameter :: nf = 7
1130 14592 : real(r8) :: fmsub(mlon0:mlon1,mlat0:mlat1,nf)
1131 14592 : real(r8) :: fmglb(nmlonp1,nmlat,nf)
1132 14592 : real(r8) :: rhs_nhem(nmlonp1,nmlat)
1133 : integer :: i,j,jj
1134 : !
1135 : ! These calls exclude halo points in zigm11, etc.
1136 : !
1137 185991 : fmsub(:,:,1) = zigm11(mlon0:mlon1,mlat0:mlat1)
1138 178695 : fmsub(:,:,2) = zigm22(mlon0:mlon1,mlat0:mlat1)
1139 178695 : fmsub(:,:,3) = zigmc (mlon0:mlon1,mlat0:mlat1)
1140 178695 : fmsub(:,:,4) = zigm2 (mlon0:mlon1,mlat0:mlat1)
1141 178695 : fmsub(:,:,5) = rim1 (mlon0:mlon1,mlat0:mlat1)
1142 178695 : fmsub(:,:,6) = rim2 (mlon0:mlon1,mlat0:mlat1)
1143 178695 : fmsub(:,:,7) = rhs (mlon0:mlon1,mlat0:mlat1)
1144 :
1145 : call mp_gather_edyn(fmsub,mlon0,mlon1,mlat0,mlat1, &
1146 7296 : fmglb,nmlonp1,nmlat,nf)
1147 : !
1148 : ! Now root task can take over, and work with global arrays:
1149 : !
1150 7296 : if (mytid==0) then
1151 151145 : zigm11_glb(:,:) = fmglb(:,:,1)
1152 151145 : zigm22_glb(:,:) = fmglb(:,:,2)
1153 151145 : zigmc_glb(:,:) = fmglb(:,:,3)
1154 151145 : zigm2_glb(:,:) = fmglb(:,:,4)
1155 151145 : rim_glb(:,:,1) = fmglb(:,:,5)
1156 151145 : rim_glb(:,:,2) = fmglb(:,:,6)
1157 151145 : rhs_nhem(:,:) = fmglb(:,:,7)
1158 : !
1159 : ! Transfer local global rhs_nhem (from sub rhspde) to rhs_glb,
1160 : ! so the latter has data in south hemisphere.
1161 : !
1162 151145 : rhs_glb= 0._r8 ! init
1163 1862 : do j=1,nmlat
1164 : !
1165 : ! Transfer north pole to equator:
1166 1862 : if (j == nmlat) then
1167 1558 : do i=1,nmlonp1
1168 1558 : rhs_glb(i,nmlath) = rhs_nhem(i,j)
1169 : enddo
1170 : ! Transfer equator to south pole:
1171 1824 : elseif (j == nmlath) then
1172 1558 : do i=1,nmlonp1
1173 1558 : rhs_glb(i,1) = rhs_nhem(i,j)
1174 : enddo
1175 : ! Transfer north hem to south hem:
1176 1805 : elseif (j > nmlath) then ! 50 -> 96
1177 893 : jj = j-nmlath+1 ! 2 -> 48
1178 73226 : do i=1,nmlonp1
1179 73226 : rhs_glb(i,jj) = rhs_nhem(i,j)
1180 : enddo
1181 : endif
1182 : enddo ! j=mlat0,mlat1
1183 :
1184 : endif ! mytid==0
1185 7296 : end subroutine gather_edyn
1186 : !-----------------------------------------------------------------------
1187 7296 : subroutine highlat_poten()
1188 : use edyn_solve, only: &
1189 : phihm, & ! high-latitude potential (nmlonp1,nmlat)
1190 : pfrac ! NH fraction of potential (nmlonp1,nmlat0)
1191 : !
1192 : ! Global PDE solution rim_glb(:,:,1) has been scattered to mag subdomains
1193 : ! in rim1, and halos set (this overwrites previous rim1 from fieldline
1194 : ! integrations). Now add high latitude potential from empirical model
1195 : ! (heelis or weimer), defining phim2d on mag subdomains. After this pthreed
1196 : ! will expand phim2d to phim3d.
1197 : !
1198 : ! Input: rim1(mag subdomains) ! Solution from mudpack solver (nhem only)
1199 : ! pfrac(nmlonp1,nmlat0) ! NH fraction of potential
1200 : ! phihm(nmlonp1,nmlat) ! potential in magnetic
1201 : ! Output: phim2d(mag subdomains) ! solution with phihm in both nhem and shem
1202 : ! Both rim1 and phim2d are dimensioned (mlon00:mlon11,mlat00:mlat11)
1203 : !
1204 : ! Both phihm and pfrac have been set by either heelis or weimer.
1205 : ! phihm is on 2d global mag grid, pfrac is in north hemisphere only
1206 : !
1207 : ! Local:
1208 : logical, parameter :: mod_heelis = .false. ! true == modified
1209 : integer :: i,j,jn,js
1210 : real(r8) :: fac
1211 : !
1212 : ! Add empirical model potential at high latitude:
1213 : !
1214 7296 : fac = 1.0_r8
1215 : if (mod_heelis) fac = 0._r8 ! modified heelis
1216 29412 : do j=mlat0,mlat1
1217 22116 : if (j > nmlath) cycle ! south only (including equator)
1218 11172 : jn = nmlat-j+1
1219 11172 : js = nmlath-j+1
1220 93879 : do i=mlon0,mlon1
1221 0 : phim2d(i,j) = rim1(i,j)+fac*(1._r8-pfrac(i,js))*(phihm(i,j)- &
1222 97527 : phihm(i,jn))
1223 : enddo
1224 : enddo
1225 :
1226 29412 : do j=mlat0,mlat1
1227 22116 : if (j <= nmlath) cycle ! north only (excluding equator)
1228 92112 : do i=mlon0,mlon1
1229 95988 : phim2d(i,j) = rim1(i,j)
1230 : enddo
1231 : enddo
1232 :
1233 29412 : do j=mlat0,mlat1
1234 22116 : call outfld('PHIHM',phihm(mlon0:omlon1,j),omlon1-mlon0+1,j)
1235 29412 : call outfld('PHIM2D',phim2d(mlon0:omlon1,j),omlon1-mlon0+1,j)
1236 : enddo
1237 :
1238 7296 : end subroutine highlat_poten
1239 : !-----------------------------------------------------------------------
1240 7296 : subroutine pthreed()
1241 : !
1242 : ! phim2d is now 2d electric potential solution on mag subdomains,
1243 : ! with high-latitude potential added from empirical model (see subs
1244 : ! heelis and highlat_poten), and mag halos set. Now expand phim2d in
1245 : ! vertical, defining phim3d. Also calculate electric field ed13d, ed23d
1246 : ! for later current calculations, and ephi3d, elam3d and emz3d for conversion
1247 : ! to geographic grid (sub pefield), and subsequent calculation of ion drifts
1248 : ! by sub ionvel (not in edynamo).
1249 : !
1250 : use edyn_params, only: Rearth, pi_dyn, r0, kbotdyn
1251 : use edyn_maggrid, only: ylatm, dlatm, dlonm, rcos0s, dt1dts, dt0dts, table
1252 : use edyn_mpi, only: &
1253 : mp_mag_halos, &
1254 : mp_magpole_2d, &
1255 : mp_mageq_jpm3, &
1256 : mp_mag_jslot, &
1257 : mp_magpoles, &
1258 : mp_mag_periodic_f2d, &
1259 : ixfind
1260 : !
1261 : ! Local:
1262 : real(r8), parameter :: eps = 1.e-10_r8
1263 : integer :: mxneed
1264 : integer :: i,j,k,n,mlon00,mlon11,mlat00,mlat11
1265 : real(r8) :: csth0, cosltm, sym, pi, phims, phimn, rind
1266 14592 : real(r8), dimension(nmlonp1) :: thetam,pslot,qslot
1267 14592 : integer, dimension(nmlonp1) :: islot,jslot,ip1f,ip2f,ip3f
1268 :
1269 : ! real(r8), dimension(mlon0-1:mlon1+1,mlat0-1:mlat1+1) :: ed1,ed2
1270 :
1271 14592 : real(r8), dimension(mlon0-1:mlon1+1,mlat0-1:mlat1+1) :: ephi,elam
1272 14592 : real(r8) :: fpole2d_jpm2(nmlonp1,4,4) ! global lons at S pole+1,2 and N pole-1,2
1273 14592 : real(r8) :: fpoles(nmlonp1,2,1) ! global lons at poles (1 field only)
1274 14592 : real(r8) :: fmsub(mlon0:mlon1,mlat0:mlat1,4)
1275 14592 : real(r8) :: fmsub1(mlon0-1:mlon1+1,mlat0-1:mlat1+1,5)
1276 14592 : real(r8) :: feq_jpm3(nmlonp1,-3:3,1) ! global lons at equator +/- 3
1277 14592 : integer :: jneed(nmlat+2) ! lats needed from other tasks for interp
1278 : integer :: njneed,icount
1279 : real(r8), dimension(mlon0-1:mlon1+1,nmlat+2) :: &
1280 14592 : phineed, & ! phim2d at needed latitudes
1281 14592 : ed1need, & ! ed1 at needed latitudes
1282 14592 : ed2need, & ! ed2 at needed latitudes
1283 14592 : ephineed, & ! ephi at needed latitudes
1284 14592 : elamneed ! elam at needed latitudes
1285 14592 : real(r8), dimension(mlon0-1:mlon1+1,nmlat+2,5) :: fmneed
1286 : real(r8) :: phi0j0,phi1j0,phi0j1,phi1j1
1287 : real(r8) :: ed1i0j0,ed1i1j0,ed1i0j1,ed1i1j1
1288 : real(r8) :: ed2i0j0,ed2i1j0,ed2i0j1,ed2i1j1
1289 : real(r8) :: ephi0j0,ephi1j0,ephi0j1,ephi1j1
1290 : real(r8) :: elam0j0,elam1j0,elam0j1,elam1j1
1291 : real(r8) :: fac_elam
1292 : !
1293 7296 : mxneed=nmlat+2
1294 7296 : pi = pi_dyn
1295 7296 : mlon00=mlon0-1 ; mlon11=mlon1+1
1296 7296 : mlat00=mlat0-1 ; mlat11=mlat1+1
1297 : !
1298 : ! Calculate ed1,ed2 components of electric field:
1299 : ! phim2d has halos set, so when mlon0==1, i-1 should wrap
1300 : ! to value at i==nmlon, and when mlon1==nmlonp1, i+1 should
1301 : ! wrap to value at i==2.
1302 : !
1303 365199 : ed1 = 0._r8
1304 365199 : ephi = 0._r8
1305 29412 : do j=mlat0,mlat1
1306 22116 : if (j==1.or.j==nmlat) cycle
1307 21660 : csth0 = cos(-pi/2._r8+(j-1)*dlatm)
1308 175161 : do i=mlon0,mlon1
1309 146205 : ed1(i,j) = -(phim2d(i+1,j)-phim2d(i-1,j))/(2._r8*dlonm*csth0)* &
1310 292410 : rcos0s(j)/(r0*1.e-2_r8)
1311 168321 : ephi(i,j) = ed1(i,j)*(r0*1.e-2_r8)
1312 : enddo ! i=mlon0,mlon1
1313 : enddo ! j=mlat0,mlat1
1314 : !
1315 : ! Southern hemisphere (excluding equator):
1316 365199 : ed2 = 0._r8
1317 365199 : elam = 0._r8
1318 29412 : do j=mlat0,mlat1
1319 22116 : if (j >= nmlath) cycle
1320 10944 : if (j==1.or.j==nmlat) cycle ! skip poles
1321 90345 : do i=mlon0,mlon1
1322 72333 : ed2(i,j)= -(phim2d(i,j+1)-phim2d(i,j-1))/(2._r8*dlatm)*dt1dts(j)/ &
1323 144666 : (r0*1.e-2_r8)
1324 94449 : elam(i,j)= -(phim2d(i,j+1)-phim2d(i,j-1))/(2._r8*dlatm)*dt0dts(j)
1325 : enddo ! i=mlon0,mlon1
1326 : enddo ! j=mlat0,mlat1
1327 : !
1328 : ! Northern hemisphere (excluding equator):
1329 29412 : do j=mlat0,mlat1
1330 22116 : if (j <= nmlath) cycle
1331 10944 : if (j==1.or.j==nmlat) cycle ! skip poles
1332 90345 : do i=mlon0,mlon1
1333 72333 : ed2(i,j) = (phim2d(i,j+1)-phim2d(i,j-1))/(2._r8*dlatm)*dt1dts(j)/ &
1334 144666 : (r0*1.e-2_r8)
1335 94449 : elam(i,j)= -(phim2d(i,j+1)-phim2d(i,j-1))/(2._r8*dlatm)*dt0dts(j)
1336 : enddo ! i=mlon0,mlon1
1337 : enddo ! j=mlat0,mlat1
1338 :
1339 : ! Need ed1,2 at global longitudes at j==2 and j==nmlat-1:
1340 : ! mp_magpole_2d: Return fpole_jpm2(nglblon,1->4,nf) as:
1341 : ! 1: j = jspole+1 (spole+1)
1342 : ! 2: j = jspole+2 (spole+2) (unused here)
1343 : ! 3: j = jnpole-1 (npole-1)
1344 : ! 4: j = jnpole-2 (npole-2) (unused here)
1345 : !
1346 178695 : fmsub(:,:,1) = ed1(mlon0:mlon1,mlat0:mlat1)
1347 178695 : fmsub(:,:,2) = ed2(mlon0:mlon1,mlat0:mlat1)
1348 178695 : fmsub(:,:,3) = ephi(mlon0:mlon1,mlat0:mlat1)
1349 178695 : fmsub(:,:,4) = elam(mlon0:mlon1,mlat0:mlat1)
1350 : call mp_magpole_2d(fmsub,mlon0,mlon1,mlat0,mlat1,nmlonp1, &
1351 7296 : 1,nmlat,fpole2d_jpm2,4)
1352 : !
1353 : ! Poles: average over four surrounding points
1354 598272 : do i = 1,nmlonp1
1355 590976 : ip1f(i) = i + nmlon/4
1356 590976 : if (ip1f(i) > nmlonp1) ip1f(i) = ip1f(i) - nmlon
1357 590976 : ip2f(i) = i + nmlon/2
1358 590976 : if (ip2f(i) > nmlonp1) ip2f(i) = ip2f(i) - nmlon
1359 590976 : ip3f(i) = i + 3*nmlon/4
1360 598272 : if (ip3f(i) > nmlonp1) ip3f(i) = ip3f(i) - nmlon
1361 : enddo ! i=1,nmlonp1
1362 : !
1363 : ! S pole:
1364 29412 : do j=mlat0,mlat1
1365 29412 : if (j==1) then
1366 1767 : do i=mlon0,mlon1
1367 3078 : ed1(i,j)=.25_r8*(fpole2d_jpm2(i,1,1)-fpole2d_jpm2(ip2f(i),1,1)+ &
1368 4617 : fpole2d_jpm2(ip1f(i),1,2)-fpole2d_jpm2(ip3f(i),1,2))
1369 1539 : ed2(i,j)=.25_r8*(fpole2d_jpm2(i,1,2)-fpole2d_jpm2(ip2f(i),1,2)- &
1370 3078 : fpole2d_jpm2(ip1f(i),1,1)+fpole2d_jpm2(ip3f(i),1,1))
1371 :
1372 3078 : ephi(i,j)=.25_r8*(fpole2d_jpm2(i,1,3)-fpole2d_jpm2(ip2f(i),1,3)+ &
1373 3078 : fpole2d_jpm2(ip1f(i),1,4)-fpole2d_jpm2(ip3f(i),1,4))
1374 1539 : elam(i,j)=.25_r8*(fpole2d_jpm2(i,1,4)-fpole2d_jpm2(ip2f(i),1,4)- &
1375 3306 : fpole2d_jpm2(ip1f(i),1,3)+fpole2d_jpm2(ip3f(i),1,3))
1376 : enddo ! i=mlon0,mlon1
1377 : ! N pole:
1378 21888 : elseif (j==nmlat) then
1379 1767 : do i=mlon0,mlon1
1380 3078 : ed1(i,j)=.25_r8*(fpole2d_jpm2(i,3,1)-fpole2d_jpm2(ip2f(i),3,1)+ &
1381 4617 : fpole2d_jpm2(ip1f(i),3,2)-fpole2d_jpm2(ip3f(i),3,2))
1382 1539 : ed2(i,j)=.25_r8*(fpole2d_jpm2(i,3,2)-fpole2d_jpm2(ip2f(i),3,2)- &
1383 3078 : fpole2d_jpm2(ip1f(i),3,1)+fpole2d_jpm2(ip3f(i),3,1))
1384 :
1385 3078 : ephi(i,j)=.25_r8*(fpole2d_jpm2(i,3,3)-fpole2d_jpm2(ip2f(i),3,3)+ &
1386 3078 : fpole2d_jpm2(ip1f(i),3,4)-fpole2d_jpm2(ip3f(i),3,4))
1387 1539 : elam(i,j)=.25_r8*(fpole2d_jpm2(i,3,4)-fpole2d_jpm2(ip2f(i),3,4)- &
1388 3306 : fpole2d_jpm2(ip1f(i),3,3)+fpole2d_jpm2(ip3f(i),3,3))
1389 : enddo ! i=mlon0,mlon1
1390 : endif ! S or N pole
1391 : enddo ! j=mlat0,mlat1
1392 : !
1393 : ! Equator: derivative of quadratic polynomial (3 given points)
1394 : ! For equator and equator +/- 1 of ed2, we need equator and
1395 : ! equator +/- 3 of phim2d (note feq_jpm3(nmlonp1,-3:3,1)):
1396 : !
1397 178695 : fmsub(:,:,1) = phim2d(mlon0:mlon1,mlat0:mlat1)
1398 7296 : call mp_mageq_jpm3(fmsub(:,:,1),mlon0,mlon1,mlat0,mlat1,nmlonp1,feq_jpm3,1)
1399 29412 : do j=mlat0,mlat1
1400 29412 : if (j==nmlath-1) then ! equator-1
1401 1767 : do i=mlon0,mlon1
1402 1539 : ed2(i,j) = (4._r8*feq_jpm3(i,-2,1)-feq_jpm3(i,-3,1)- &
1403 3306 : 3._r8*feq_jpm3(i,-1,1))/(2._r8*dlatm)/(r0*1.e-2_r8)
1404 : enddo
1405 21888 : elseif (j==nmlath) then ! equator
1406 1767 : do i=mlon0,mlon1
1407 1539 : ed2(i,j) = (4._r8*feq_jpm3(i,1,1)-feq_jpm3(i,2,1)- &
1408 1539 : 3._r8*feq_jpm3(i,0,1))/(2._r8*dlatm)/(r0*1.e-2_r8)
1409 1539 : elam(i,j) = (4._r8*feq_jpm3(i,1,1)-feq_jpm3(i,2,1)- &
1410 1767 : 3._r8*feq_jpm3(i,0,1))/(2._r8*dlatm)
1411 : enddo
1412 21660 : elseif (j==nmlath+1) then ! equator+1
1413 1767 : do i=mlon0,mlon1
1414 1539 : ed2(i,j) = (4._r8*feq_jpm3(i,2,1)-feq_jpm3(i,3,1)- &
1415 3306 : 3._r8*feq_jpm3(i,1,1))/(2._r8*dlatm)/(r0*1.e-2_r8)
1416 : enddo
1417 : endif ! equator +/- 1
1418 : enddo ! j=mlat0,mlat1
1419 : !
1420 : ! Set halos for 3d calculations:
1421 365199 : fmsub1(:,:,1) = ed1
1422 365199 : fmsub1(:,:,2) = ed2
1423 365199 : fmsub1(:,:,3) = ephi
1424 365199 : fmsub1(:,:,4) = elam
1425 7296 : call mp_mag_halos(fmsub1,mlon0,mlon1,mlat0,mlat1,4)
1426 372495 : ed1 = fmsub1(:,:,1)
1427 372495 : ed2 = fmsub1(:,:,2)
1428 365199 : ephi = fmsub1(:,:,3)
1429 365199 : elam = fmsub1(:,:,4)
1430 :
1431 29412 : do j=mlat0,mlat1
1432 22116 : call outfld('ED1',ed1(mlon0:omlon1,j),omlon1-mlon0+1,j)
1433 29412 : call outfld('ED2',ed2(mlon0:omlon1,j),omlon1-mlon0+1,j)
1434 : enddo
1435 : !
1436 : ! Determine latitudes needed for interpolation that fall
1437 : ! outside a task's latitudinal subdomain:
1438 : !
1439 7296 : if (debug) write(iulog,*) "pthreed: kbotdyn ", kbotdyn
1440 :
1441 7296 : njneed = 0 ! number of unique latitudes needed
1442 729600 : jneed(:) = -1 ! j-indices of needed latitudes
1443 510720 : do k=kbotdyn,nmlev
1444 2036724 : do j=mlat0,mlat1
1445 1526004 : if (j==1.or.j==nmlat) cycle ! exclude poles
1446 1494540 : sym = 1._r8
1447 1494540 : if (j < nmlath) sym = -1._r8
1448 1494540 : cosltm = cos(ylatm(j))
1449 12086109 : do i=mlon0,mlon1
1450 10088145 : if (i==nmlonp1) cycle
1451 :
1452 9963600 : thetam(i)=(Rearth+zpotm3d(i,j,kbotdyn))/(Rearth+zpotm3d(i,j,k))
1453 9963600 : thetam(i) = acos(sqrt(thetam(i))*cosltm*(1._r8-eps))
1454 :
1455 9963600 : pslot(i) = thetam(i)*180._r8/pi+1._r8
1456 9963600 : islot(i) = pslot(i)
1457 9963600 : rind = real(islot(i), kind=r8)
1458 9963600 : pslot(i) = pslot(i)-rind
1459 :
1460 9963600 : thetam(i) = ((1._r8-pslot(i))*table(islot(i),2)+pslot(i)* &
1461 19927200 : table(islot(i)+1,2))*sym ! thetam negative for south hem
1462 :
1463 9963600 : islot(i) = i
1464 9963600 : pslot(i) = 0._r8
1465 9963600 : qslot(i) = (thetam(i)+pi/2._r8)/dlatm+1._r8
1466 9963600 : jslot(i) = qslot(i)
1467 9963600 : rind = real(jslot(i), kind=r8)
1468 9963600 : qslot(i) = qslot(i)-rind
1469 :
1470 : ! Save j index if outside subdomain w/ halos:
1471 753924862 : if ((jslot(i) < mlat00 .or. jslot(i) > mlat11).and. &
1472 : .not.any(jslot(i)==jneed)) then
1473 14146 : njneed = njneed+1
1474 14146 : if (njneed > mxneed) call endrun('njneed')
1475 14146 : jneed(njneed) = jslot(i)
1476 : endif ! jslot is outside subdomain
1477 : !
1478 : ! Save j+1 index if outside subdomain:
1479 754239999 : if ((jslot(i)+1 < mlat00 .or. jslot(i)+1 > mlat11).and. &
1480 1526004 : .not.any(jslot(i)+1==jneed)) then
1481 17052 : njneed = njneed+1
1482 17052 : if (njneed > mxneed) call endrun('njneed')
1483 17052 : jneed(njneed) = jslot(i)+1
1484 : endif ! jslot(i)+1 is outside subdomain
1485 : enddo ! i=mlon0,mlon1
1486 : enddo ! j=mlat0,mlat1
1487 : enddo ! k=kbotdyn,nmlev
1488 : !
1489 : ! Get phim2 at needed latitudes (note inclusion of phim2d halos).
1490 : ! real,intent(in) :: fin(mlon00:mlon11,mlat00:mlat11,nf) ! data at current subdomain
1491 : ! real,intent(out) :: fout(mlon00:mlon11,mxneed,nf) ! returned data at needed lats
1492 : !
1493 365199 : fmsub1(:,:,1) = phim2d
1494 365199 : fmsub1(:,:,2) = ed1
1495 365199 : fmsub1(:,:,3) = ed2
1496 365199 : fmsub1(:,:,4) = ephi
1497 365199 : fmsub1(:,:,5) = elam
1498 7296 : call mp_mag_jslot(fmsub1,mlon00,mlon11,mlat00,mlat11,fmneed,jneed,mxneed,5)
1499 7049760 : phineed = fmneed(:,:,1)
1500 7049760 : ed1need = fmneed(:,:,2)
1501 7049760 : ed2need = fmneed(:,:,3)
1502 7049760 : ephineed= fmneed(:,:,4)
1503 7049760 : elamneed= fmneed(:,:,5)
1504 :
1505 23237646 : ephi3d = 0._r8
1506 23237646 : elam3d = 0._r8
1507 23237646 : emz3d = 0._r8
1508 510720 : do k=kbotdyn,nmlev
1509 2036724 : do j=mlat0,mlat1
1510 1526004 : if (j==1.or.j==nmlat) cycle ! exclude poles
1511 1494540 : sym = 1._r8
1512 1494540 : if (j < nmlath) sym = -1._r8
1513 1494540 : cosltm = cos(ylatm(j))
1514 12086109 : do i=mlon0,mlon1
1515 10088145 : if (i==nmlonp1) cycle
1516 :
1517 9963600 : thetam(i)=(Rearth+zpotm3d(i,j,kbotdyn))/(Rearth+zpotm3d(i,j,k))
1518 9963600 : thetam(i) = acos(sqrt(thetam(i))*cosltm*(1._r8-eps))
1519 9963600 : fac_elam = tan(ylatm(j))/tan(thetam(i)*sym) ! tan(lambda_q)/tan(lambda_m)
1520 :
1521 9963600 : pslot(i) = thetam(i)*180._r8/pi+1._r8
1522 9963600 : islot(i) = pslot(i)
1523 9963600 : rind = real(islot(i), kind=r8)
1524 9963600 : pslot(i) = pslot(i)-rind
1525 :
1526 9963600 : thetam(i) = ((1._r8-pslot(i))*table(islot(i),2)+pslot(i)* &
1527 19927200 : table(islot(i)+1,2))*sym ! thetam negative for south hem
1528 :
1529 9963600 : islot(i) = i
1530 9963600 : pslot(i) = 0._r8
1531 9963600 : qslot(i) = (thetam(i)+pi/2._r8)/dlatm+1._r8
1532 9963600 : jslot(i) = qslot(i)
1533 9963600 : rind = real(jslot(i), kind=r8)
1534 9963600 : qslot(i) = qslot(i)-rind
1535 : !
1536 : ! Check for jslot in subdomain:
1537 9963600 : if (jslot(i) >= mlat00.and.jslot(i) <= mlat11) then ! within subdomain
1538 7341826 : phi0j0 = phim2d(islot(i) ,jslot(i))
1539 7341826 : phi1j0 = phim2d(islot(i)+1,jslot(i))
1540 7341826 : ed1i0j0 = ed1(islot(i) ,jslot(i))
1541 7341826 : ed1i1j0 = ed1(islot(i)+1,jslot(i))
1542 7341826 : ed2i0j0 = ed2(islot(i) ,jslot(i))
1543 7341826 : ed2i1j0 = ed2(islot(i)+1,jslot(i))
1544 7341826 : ephi0j0 = ephi(islot(i) ,jslot(i))
1545 7341826 : ephi1j0 = ephi(islot(i)+1,jslot(i))
1546 7341826 : elam0j0 = elam(islot(i) ,jslot(i))
1547 7341826 : elam1j0 = elam(islot(i)+1,jslot(i))
1548 : else ! jslot outside subdomain
1549 2621774 : n = ixfind(jneed,mxneed,jslot(i),icount)
1550 2621774 : if (n==0) then
1551 0 : write(iulog,"('>>> pthreed: i=',i4,' j=',i4,' k=',i4)") i,j,k
1552 : write(iulog,"(' Could not find jslot ',i4,' in jneed=',/,(10i4))") &
1553 0 : i,j,k,jslot(i),jneed
1554 0 : call endrun('jslot(i) not in jneed')
1555 : endif
1556 2621774 : phi0j0 = phineed(islot(i) ,n)
1557 2621774 : phi1j0 = phineed(islot(i)+1,n)
1558 2621774 : ed1i0j0 = ed1need(islot(i) ,n)
1559 2621774 : ed1i1j0 = ed1need(islot(i)+1,n)
1560 2621774 : ed2i0j0 = ed2need(islot(i) ,n)
1561 2621774 : ed2i1j0 = ed2need(islot(i)+1,n)
1562 2621774 : ephi0j0 =ephineed(islot(i) ,n)
1563 2621774 : ephi1j0 =ephineed(islot(i)+1,n)
1564 2621774 : elam0j0 =elamneed(islot(i) ,n)
1565 2621774 : elam1j0 =elamneed(islot(i)+1,n)
1566 : endif
1567 : !
1568 : ! Check for jslot+1 in subdomain:
1569 9963600 : if (jslot(i)+1 >= mlat00.and.jslot(i)+1 <= mlat11) then ! within subdomain
1570 7342633 : phi0j1 = phim2d(islot(i) ,jslot(i)+1)
1571 7342633 : phi1j1 = phim2d(islot(i)+1,jslot(i)+1)
1572 7342633 : ed1i0j1 = ed1(islot(i) ,jslot(i)+1)
1573 7342633 : ed1i1j1 = ed1(islot(i)+1,jslot(i)+1)
1574 7342633 : ed2i0j1 = ed2(islot(i) ,jslot(i)+1)
1575 7342633 : ed2i1j1 = ed2(islot(i)+1,jslot(i)+1)
1576 7342633 : ephi0j1 = ephi(islot(i) ,jslot(i)+1)
1577 7342633 : ephi1j1 = ephi(islot(i)+1,jslot(i)+1)
1578 7342633 : elam0j1 = elam(islot(i) ,jslot(i)+1)
1579 7342633 : elam1j1 = elam(islot(i)+1,jslot(i)+1)
1580 : else ! jslot+1 outside subdomain
1581 2620967 : n = ixfind(jneed,mxneed,jslot(i)+1,icount)
1582 2620967 : if (n==0) then
1583 0 : write(iulog,"('>>> pthreed: i=',i4,' j=',i4,' k=',i4)") i,j,k
1584 : write(iulog,"(' Could not find jslot+1 ',i4,' in jneed=',/,(10i4))") &
1585 0 : i,j,k,jslot(i)+1,jneed
1586 0 : call endrun('jslot(i)+1 not in jneed')
1587 : endif
1588 2620967 : phi0j1 = phineed(islot(i) ,n)
1589 2620967 : phi1j1 = phineed(islot(i)+1,n)
1590 2620967 : ed1i0j1 = ed1need(islot(i) ,n)
1591 2620967 : ed1i1j1 = ed1need(islot(i)+1,n)
1592 2620967 : ed2i0j1 = ed2need(islot(i) ,n)
1593 2620967 : ed2i1j1 = ed2need(islot(i)+1,n)
1594 2620967 : ephi0j1 =ephineed(islot(i) ,n)
1595 2620967 : ephi1j1 =ephineed(islot(i)+1,n)
1596 2620967 : elam0j1 =elamneed(islot(i) ,n)
1597 2620967 : elam1j1 =elamneed(islot(i)+1,n)
1598 : endif
1599 : !
1600 : ! Do the interpolation:
1601 9963600 : phim3d(i,j,k) = (1._r8-qslot(i))*((1._r8-pslot(i))* &
1602 : phi0j0 + pslot(i) * phi1j0) + qslot(i)*((1._r8-pslot(i))* &
1603 9963600 : phi0j1 + pslot(i) * phi1j1)
1604 :
1605 0 : ed13d(i,j,k) = (1._r8-qslot(i))*((1._r8-pslot(i))* &
1606 : ed1i0j0 + pslot(i) * ed1i1j0) + qslot(i)*((1._r8-pslot(i))* &
1607 9963600 : ed1i0j1 + pslot(i) * ed1i1j1)
1608 0 : ed23d(i,j,k) = (1._r8-qslot(i))*((1._r8-pslot(i))* &
1609 : ed2i0j0 + pslot(i) * ed2i1j0) + qslot(i)*((1._r8-pslot(i))* &
1610 9963600 : ed2i0j1 + pslot(i) * ed2i1j1)
1611 :
1612 0 : ephi3d(i,j,k) = (1._r8-qslot(i))*((1._r8-pslot(i))* &
1613 : ephi0j0 + pslot(i) * ephi1j0) + qslot(i)*((1._r8-pslot(i))* &
1614 9963600 : ephi0j1 + pslot(i) * ephi1j1)
1615 0 : elam3d(i,j,k) = (1._r8-qslot(i))*((1._r8-pslot(i))* &
1616 : elam0j0 + pslot(i) * elam1j0) + qslot(i)*((1._r8-pslot(i))* &
1617 9963600 : elam0j1 + pslot(i) * elam1j1)
1618 11614149 : elam3d(i,j,k) = elam3d(i,j,k)*fac_elam ! add height variation
1619 : enddo ! i=mlon0,mlon1
1620 : enddo ! j=mlat0,mlat1
1621 : enddo ! k=kbotdyn,nmlev
1622 :
1623 : !
1624 : ! Mag poles for phim:
1625 : ! mp_magpoles returns global longitudes at S,N poles in fpoles(nglblon,2,nf)
1626 : !
1627 0 : call mp_magpoles(phim2d(mlon0:mlon1,mlat0:mlat1), &
1628 178695 : mlon0,mlon1,mlat0,mlat1,nmlonp1,1,nmlat,fpoles,1)
1629 :
1630 7296 : rind = real(nmlon, kind=r8)
1631 590976 : phims=dot_product(unitvm,fpoles(1:nmlon,1,1))/rind
1632 590976 : phimn=dot_product(unitvm,fpoles(1:nmlon,2,1))/rind
1633 :
1634 510720 : do k=kbotdyn,nmlev
1635 2036724 : do j=mlat0,mlat1
1636 2029428 : if (j==1) then
1637 121923 : do i=mlon0,mlon1
1638 106191 : phim3d(i,j,k) = phims
1639 106191 : ed13d(i,j,k) = ed1(i,j)
1640 106191 : ed23d(i,j,k) = ed2(i,j)
1641 106191 : ephi3d(i,j,k) = ephi(i,j)
1642 121923 : elam3d(i,j,k) = ed2(i,j)*(r0*1.e-2_r8)
1643 : enddo
1644 1510272 : elseif (j==nmlat) then
1645 121923 : do i=mlon0,mlon1
1646 106191 : phim3d(i,j,k) = phimn
1647 106191 : ed13d(i,j,k) = ed1(i,j)
1648 106191 : ed23d(i,j,k) = ed2(i,j)
1649 106191 : ephi3d(i,j,k) = ephi(i,j)
1650 121923 : elam3d(i,j,k) = -ed2(i,j)*(r0*1.e-2_r8)
1651 : enddo
1652 : endif ! poles
1653 : enddo ! j=mlat0,mlat1
1654 : enddo ! k=kbotdyn,nmlev
1655 : !
1656 : ! Extend kbotdyn downward redundantly:
1657 452352 : do k=1,kbotdyn-1
1658 10900395 : phim3d(:,:,k) = phim3d(:,:,kbotdyn)
1659 10900395 : ephi3d(:,:,k) = ephi3d(:,:,kbotdyn)
1660 10907691 : elam3d(:,:,k) = elam3d(:,:,kbotdyn)
1661 : enddo
1662 : !
1663 : ! Upward electric field:
1664 503424 : do k=kbotdyn,nmlev-1
1665 2007312 : do j=mlat0,mlat1
1666 12151260 : do i=mlon0,mlon1
1667 11655132 : emz3d(i,j,k) = -(phim3d(i,j,k+1)-phim3d(i,j,k-1))
1668 : enddo
1669 : enddo
1670 : enddo
1671 : !
1672 955776 : do k=mlev0,mlev1
1673 955776 : call mp_mag_periodic_f2d(phim3d(:,:,k),mlon0,mlon1,mlat0,mlat1,1)
1674 : enddo
1675 : !
1676 7296 : if (debug_hist) then
1677 0 : do j=mlat0,mlat1
1678 0 : call outfld('EPHI3D',ephi3d(mlon0:omlon1,j,mlev1:mlev0:-1),omlon1-mlon0+1,j)
1679 0 : call outfld('ELAM3D',elam3d(mlon0:omlon1,j,mlev1:mlev0:-1),omlon1-mlon0+1,j)
1680 0 : call outfld('EMZ3D', emz3d(mlon0:omlon1,j,mlev1:mlev0:-1),omlon1-mlon0+1,j)
1681 : enddo
1682 : endif
1683 :
1684 29412 : do j=mlat0,mlat1
1685 22064396 : call outfld('PHIM3D',phim3d(mlon0:omlon1,j,mlev1:mlev0:-1),omlon1-mlon0+1,j)
1686 22064396 : call outfld('ED13D' ,ed13d (mlon0:omlon1,j,mlev1:mlev0:-1),omlon1-mlon0+1,j)
1687 22071692 : call outfld('ED23D' ,ed23d (mlon0:omlon1,j,mlev1:mlev0:-1),omlon1-mlon0+1,j)
1688 : enddo
1689 :
1690 7296 : end subroutine pthreed
1691 : !-----------------------------------------------------------------------
1692 7296 : subroutine pefield()
1693 : use edyn_params, only: pi
1694 : use edyn_maggrid, only: dt0dts, dlatm, dlonm, rcos0s
1695 : use edyn_geogrid, only: nlev
1696 : use edyn_mpi, only: mp_magpole_3d, mp_mag_halos, mp_magpoles
1697 : use regridder, only: regrid_mag2geo_3d
1698 : !
1699 : ! Local:
1700 : integer :: i, ii, j, k
1701 : real(r8) :: &
1702 14592 : phi3d(mlon0-1:mlon1+1,mlat0-1:mlat1+1,nmlev), & ! local phi w/ halos
1703 14592 : fpole3d_jpm2(nmlonp1,4,nmlev,1) ! global lons at S pole+1,2 and N pole-1,2
1704 : real(r8) :: csth0
1705 14592 : real(r8) :: fpoles(nmlonp1,2,nmlev) ! global lons at poles
1706 14592 : real(r8), dimension(lon0:lon1,lat0:lat1,nlev) :: exgeo, eygeo, ezgeo
1707 :
1708 : !
1709 : ! Copy phim3d to local phi3d, and set halo points:
1710 29412 : do j = mlat0, mlat1
1711 178695 : do i = mlon0, mlon1
1712 19578189 : phi3d(i,j,:) = phim3d(i,j,:)
1713 : end do
1714 : end do
1715 7296 : call mp_mag_halos(phi3d, mlon0, mlon1, mlat0, mlat1, nmlev)
1716 : !
1717 : ! Return fpole3d_jpm2(nglblon,1->4,nlev,nf) as:
1718 : ! 1: j = jspole+1 (spole+1)
1719 : ! 2: j = jspole+2 (spole+2) not used here
1720 : ! 3: j = jnpole-1 (npole-1)
1721 : ! 4: j = jnpole-2 (npole-2) not used here
1722 : !
1723 0 : call mp_magpole_3d(phim3d(mlon0:mlon1,mlat0:mlat1,:), mlon0, &
1724 7296 : mlon1, mlat0, mlat1, nmlev, nmlonp1, 1, nmlat, fpole3d_jpm2, 1)
1725 : !
1726 : ! Set j=0 and j=nmlat+1 of local phi3d. This overwrites the far
1727 : ! north and south halo points set by mp_mag_halos above.
1728 29412 : do j = mlat0, mlat1
1729 29412 : if (j==1) then
1730 1767 : do i = mlon0, mlon1
1731 1539 : ii = 1 + mod(i-1+nmlon/2,nmlon) ! over the south pole
1732 201837 : phi3d(i,j-1,:) = fpole3d_jpm2(ii,1,:,1)
1733 : end do
1734 21888 : else if (j == nmlat) then
1735 1767 : do i = mlon0, mlon1
1736 1539 : ii = 1 + mod(i-1+nmlon/2,nmlon) ! over the north pole
1737 201837 : phi3d(i,j+1,:) = fpole3d_jpm2(ii,3,:,1)
1738 : end do
1739 : end if ! poles or not
1740 : end do ! j=mlat0,mlat1
1741 : !
1742 : ! Meridional component of electric field:
1743 29412 : do j = mlat0, mlat1
1744 178695 : do i = mlon0, mlon1
1745 447849 : elam3d(i,j,:) = -(phi3d(i,j+1,:)-phi3d(i,j-1,:)) / &
1746 20026038 : (2._r8*dlatm)*dt0dts(j)
1747 : end do
1748 : end do
1749 : !
1750 : ! Zonal component of electric field:
1751 29412 : do j = mlat0, mlat1
1752 22116 : if (j==1 .or. j==nmlat) cycle
1753 21660 : csth0 = cos((-pi / 2._r8) + (real(j-1,kind=r8) * dlatm))
1754 175161 : do i = mlon0, mlon1
1755 438615 : ephi3d(i,j,:) = -(phi3d(i+1,j,:) - phi3d(i-1,j,:)) / &
1756 19613586 : (2._r8 * dlonm * csth0) * rcos0s(j)
1757 : end do
1758 : end do
1759 : !
1760 : ! Polar values for ephi3d (need global lons at poles of elam3d):
1761 7296 : call mp_magpoles(elam3d,mlon0,mlon1,mlat0,mlat1,nmlonp1,1,nmlat,fpoles,nmlev)
1762 29412 : do j = mlat0, mlat1
1763 29412 : if (j == 1) then ! south pole
1764 1767 : do i = mlon0, mlon1
1765 1539 : ii = 1 + mod(i-1+(nmlon/4),nmlon) ! over the south pole
1766 201837 : ephi3d(i,j,:) = fpoles(ii,1,:)
1767 : end do
1768 21888 : else if (j == nmlat) then ! north pole
1769 1767 : do i = mlon0, mlon1
1770 1539 : ii = 1+mod(i-1+((3*nmlon)/4),nmlon) ! over the north pole
1771 201837 : ephi3d(i,j,:) = fpoles(ii,2,:)
1772 : end do
1773 : end if ! poles or not
1774 : end do ! j=mlat0,mlat1
1775 : !
1776 : ! emz = d(phi)/dz
1777 941184 : do k = 2, nmlev-1
1778 3772032 : do j = mlat0, mlat1
1779 22872960 : do i = mlon0, mlon1
1780 21939072 : emz3d(i,j,k) = -(phim3d(i,j,k+1)-phi3d(i,j,k-1))
1781 : end do
1782 : end do
1783 : end do ! k=2,nmlev-1
1784 :
1785 : ! regrid from mag grid to geo grid
1786 7296 : call regrid_mag2geo_3d( ephi3d, exgeo )
1787 7296 : call regrid_mag2geo_3d( elam3d, eygeo )
1788 7296 : call regrid_mag2geo_3d( emz3d, ezgeo )
1789 7296 : call regrid_mag2geo_3d( phim3d, phig3d )
1790 : !
1791 : ! Define ex,ey,ez on geographic subdomains for ionvel:
1792 29184 : do j = lat0, lat1
1793 291840 : do i = lon0, lon1
1794 34407936 : ex(:,i,j) = exgeo(i,j,:)
1795 34407936 : ey(:,i,j) = eygeo(i,j,:)
1796 34407936 : ez(:,i,j) = ezgeo(i,j,:)
1797 34429824 : poten(:,i,j) = phig3d(i,j,:)
1798 : end do
1799 : end do
1800 :
1801 : ! ex,ey,ez(nlev,lon0-2,lon1+2,lat0:lat1)
1802 7296 : if (debug) then
1803 : write(iulog,"(a,2e12.4,' ey=',2e12.4,' ez=',2e12.4)") &
1804 0 : 'pefield after mag2phys: ex=', &
1805 0 : minval(ex(:,lon0:lon1,:)),maxval(ex(:,lon0:lon1,:)), &
1806 0 : minval(ey(:,lon0:lon1,:)),maxval(ey(:,lon0:lon1,:)), &
1807 0 : minval(ez(:,lon0:lon1,:)),maxval(ez(:,lon0:lon1,:))
1808 : end if
1809 :
1810 7296 : call savefld_waccm(poten(1:nlev,lon0:lon1,lat0:lat1),'POTEN', &
1811 14592 : nlev,lon0,lon1,lat0,lat1)
1812 :
1813 7296 : end subroutine pefield
1814 : !-----------------------------------------------------------------------
1815 : !-----------------------------------------------------------------------
1816 :
1817 7296 : subroutine ionvel(z,ui,vi,wi,lon0,lon1, lat0,lat1, lev0,lev1)
1818 : !
1819 : ! Calculate 3d ExB ion drifts from electric field (sub pefield)
1820 : ! on geographic grid.
1821 : !
1822 7296 : use edyn_params, only: Rearth
1823 : use edyn_geogrid, only: nlev
1824 : use getapex, only: rjac ! (nlon+1,jspole:jnpole,2,2)
1825 : use getapex, only: bmod ! magnitude of mag field (nlon+1,jspole:jnpole)
1826 : use getapex, only: xb,yb,zb ! north,east,down mag field (nlon+1,jspole:jnpole)
1827 : !
1828 : ! Args:
1829 : integer,intent(in) :: & ! geographic subdomain
1830 : lon0, lon1, & ! first,last longitude indices of geographic subdomain
1831 : lat0, lat1, & ! first,last latitude indices of geographic subdomain
1832 : lev0, lev1 ! first,last level indices (not distributed)
1833 : real(r8),intent(in), dimension(lev0:lev1,lon0:lon1,lat0:lat1) :: &
1834 : z ! geopotential from input (cm)
1835 : real(r8),intent(out), dimension(lev0:lev1,lon0:lon1,lat0:lat1) :: &
1836 : ui,vi,wi
1837 : !
1838 : ! Local:
1839 : integer :: i,k,j
1840 14592 : real(r8), dimension(lev0:lev1,lon0:lon1,lat0:lat1) :: eex,eey,eez
1841 14592 : real(r8), dimension(lev0:lev1,lon0:lon1,lat0:lat1) :: rjac_out
1842 :
1843 : ! mag field diagnostics
1844 291840 : call savefld_waccm(bmod(lon0:lon1,lat0:lat1),'BMOD',1,lon0,lon1,lat0,lat1)
1845 291840 : call savefld_waccm(xb(lon0:lon1,lat0:lat1),'XB',1,lon0,lon1,lat0,lat1)
1846 291840 : call savefld_waccm(yb(lon0:lon1,lat0:lat1),'YB',1,lon0,lon1,lat0,lat1)
1847 291840 : call savefld_waccm(zb(lon0:lon1,lat0:lat1),'ZB',1,lon0,lon1,lat0,lat1)
1848 :
1849 : !
1850 : ! Scan geographic latitude subdomain:
1851 : !
1852 29184 : do j=lat0,lat1
1853 284544 : do i=lon0,lon1
1854 34429824 : do k=lev0,lev1
1855 34145280 : eex(k,i,j) = (rjac(i,j,1,1)*ex(k,i,j)+rjac(i,j,2,1)*ey(k,i,j))/(Rearth+z(k,i,j)) ! V/cm
1856 34407936 : eey(k,i,j) = (rjac(i,j,1,2)*ex(k,i,j)+rjac(i,j,2,2)*ey(k,i,j))/(Rearth+z(k,i,j))
1857 : enddo
1858 : enddo
1859 :
1860 284544 : do i=lon0,lon1
1861 33904512 : do k=lev0+1,lev1-1
1862 33882624 : eez(k,i,j) = ez(k,i,j)/(z(k+1,i,j)-z(k-1,i,j))
1863 : enddo
1864 : enddo
1865 : !
1866 : ! Extrapolate for lower and upper boundaries:
1867 284544 : do i=lon0,lon1
1868 262656 : eez(lev0,i,j) = 2._r8*eez(2,i,j)-eez(3,i,j)
1869 284544 : eez(lev1,i,j) = 2._r8*eez(lev1-1,i,j)-eez(lev1-2,i,j)
1870 : enddo
1871 : !
1872 : ! ion velocities = (e x b/b**2) (x 1.e6 for m/sec)
1873 : ! ui = zonal, vi = meridional, wi = vertical
1874 : !
1875 284544 : do i=lon0,lon1
1876 34429824 : do k=lev0,lev1
1877 34145280 : ui(k,i,j) = -(eey(k,i,j)*zb(i,j)+eez(k,i,j)*xb(i,j))*1.e6_r8/(bmod(i,j)**2)
1878 34145280 : vi(k,i,j) = (eez(k,i,j)*yb(i,j)+eex(k,i,j)*zb(i,j))*1.e6_r8/(bmod(i,j)**2)
1879 34407936 : wi(k,i,j) = (eex(k,i,j)*xb(i,j)-eey(k,i,j)*yb(i,j))*1.e6_r8/(bmod(i,j)**2)
1880 : enddo
1881 : enddo
1882 : !
1883 : ! Output ion drifts in cm/s for oplus_xport call from dpie_coupling:
1884 291840 : do i=lon0,lon1
1885 34407936 : ui(:,i,j) = ui(:,i,j)*100._r8
1886 34407936 : vi(:,i,j) = vi(:,i,j)*100._r8
1887 34429824 : wi(:,i,j) = wi(:,i,j)*100._r8
1888 : enddo
1889 : enddo ! j=lat0,lat1
1890 :
1891 34437120 : call savefld_waccm(eex*100._r8,'EX',nlev,lon0,lon1,lat0,lat1) ! V/m
1892 34437120 : call savefld_waccm(eey*100._r8,'EY',nlev,lon0,lon1,lat0,lat1)
1893 34437120 : call savefld_waccm(eez*100._r8,'EZ',nlev,lon0,lon1,lat0,lat1)
1894 :
1895 7296 : if (debug.and.masterproc) then
1896 : write(iulog,"('ionvel: ion drifts on geo grid: ui=',2e12.4,' vi=',2e12.4,' wi=',2e12.4)") &
1897 0 : minval(ui),maxval(ui), minval(vi),maxval(vi), minval(wi),maxval(wi)
1898 : endif
1899 :
1900 7296 : if (debug_hist) then
1901 0 : if (hist_fld_active('RJAC11')) then
1902 0 : do i=1,nlev
1903 0 : rjac_out(i,lon0:lon1,lat0:lat1) = rjac(lon0:lon1,lat0:lat1,1,1)
1904 : end do
1905 0 : call savefld_waccm(rjac_out,'RJAC11',nlev,lon0,lon1,lat0,lat1)
1906 : endif
1907 :
1908 0 : if (hist_fld_active('RJAC12')) then
1909 0 : do i=1,nlev
1910 0 : rjac_out(i,lon0:lon1,lat0:lat1) = rjac(lon0:lon1,lat0:lat1,1,2)
1911 : end do
1912 0 : call savefld_waccm(rjac_out,'RJAC12',nlev,lon0,lon1,lat0,lat1)
1913 : endif
1914 :
1915 0 : if (hist_fld_active('RJAC21')) then
1916 0 : do i=1,nlev
1917 0 : rjac_out(i,lon0:lon1,lat0:lat1) = rjac(lon0:lon1,lat0:lat1,2,1)
1918 : end do
1919 0 : call savefld_waccm(rjac_out,'RJAC21',nlev,lon0,lon1,lat0,lat1)
1920 : endif
1921 :
1922 0 : if (hist_fld_active('RJAC22')) then
1923 0 : do i=1,nlev
1924 0 : rjac_out(i,lon0:lon1,lat0:lat1) = rjac(lon0:lon1,lat0:lat1,2,2)
1925 : end do
1926 0 : call savefld_waccm(rjac_out,'RJAC22',nlev,lon0,lon1,lat0,lat1)
1927 : endif
1928 : endif
1929 :
1930 7296 : end subroutine ionvel
1931 :
1932 : !-----------------------------------------------------------------------
1933 : end module edynamo
|