! module oplus_module ! ! This software is part of the NCAR TIE-GCM. Use is governed by the ! Open Source Academic Research License Agreement contained in the file ! tiegcmlicense.txt. ! use params_module,only: nlat,nlonp4,dz,nlon,dlev use magfield_module,only: bx,by,bz,bmod2 ! (nlonp4,-1:nlat+2) use addfld_module,only: addfld ! ! VT vampir tracing: ! #ifdef VT #include #endif implicit none ! ! 1/8/08 btf: add option to call filter() and/or filter2() for oplus. ! Default for tiegcm is callfilt1=.false. and callfilt2=.true. logical :: callfilt1=.false. ! if true, call filter() logical :: callfilt2=.true. ! if true, call filter2() contains !----------------------------------------------------------------------- subroutine oplus(tn,te,ti,o2,o1,n2d,ne,u,v,w,barm,ui,vi,wi, | xnmbar,op,optm1,opout,optm1out,xiop2p,xiop2d, | lev0,lev1,lon0,lon1,lat0,lat1) ! ! Update O+ ion at 3d task subdomain. ! Outputs are opout, optm1out, xiop2p, and xiop2d, all other args ! are input. ! There are 4 latitude scans, with 3d mpi calls in between the loops. ! (see also 3d gather/scatter calls in sub filter_op). ! use cons_module,only: rmass_op,gask,grav,re,cs,dphi,dlamda, | shapiro,dtx2inv,boltz,expz,rmassinv_o2,rmassinv_o1, | rmassinv_n2,rmassinv_n2d,p0,dtsmooth,dtsmooth_div2,kut use qrj_module,only: | qop2p, ! O+(2p) ionization from qrj, used in xiop2p | qop2d, ! O+(2d) ionization from qrj, used in xiop2d | qop ! O+ ionization from qrj use chemrates_module,only: ! needed chemical reaction rates | rk1 ,rk2 ,rk10,rk16,rk17,rk18,rk19,rk20, | rk21,rk22,rk23,rk24,rk25,rk26,rk27 #ifdef MPI use mpi_module,only: mp_bndlons_f3d, mp_periodic_f3d #endif ! ! Args: integer,intent(in) :: | lev0,lev1, ! first,last pressure indices for current task (bot->top) | lon0,lon1, ! first,last longitude indices for current task (W->E) | lat0,lat1 ! first,last latitude indices for current task (S->N) ! ! Input fields (full 3d task subdomain): real,dimension(lev0:lev1,lon0-2:lon1+2,lat0-2:lat1+2), | intent(in) :: | tn, te, ti, ! neutral, electron, and ion temperatures (deg K) | o2, o1, ! o2, o mass mixing ratios | n2d, ! n2d | ne, ! electron density | u,v,w, ! neutral wind velocities (zonal, meridional, omega) | barm, ! mean molecular mass | optm1, ! O+ at time n-1 | op, ! O+ ion | ui,vi,wi, ! zonal, meridional, and vertical ion velocities | xnmbar ! p0*e(-z)*barm/kT ! ! Output fields (full 3d task subdomain): real,dimension(lev0:lev1,lon0-2:lon1+2,lat0-2:lat1+2), | intent(out) :: | opout, ! O+ output for next timestep | optm1out, ! O+ output for time n-1 | xiop2p,xiop2d ! ! Local: integer :: k,i,lonbeg,lonend,lat,ier,nlevs integer :: jm2,jm1,j0,jp1,jp2 ! lat-2, lat-1, lat, lat+1, lat+2 real,dimension(lon0:lon1,lat0:lat1) :: | opflux, ! upward number flux of O+ (returned by sub oplus_flux) (t7) | dvb ! output of sub divb real,dimension(lon0:lon1) :: | ubca, ubcb ! O+ upper boundary condition (were t2,t3) real :: explic = 1., gmr real,dimension(lev0:lev1,lon0:lon1) :: | psi_n2, ! n2 mass mixing ratio (1-o2-o) | bdzdvb_op, ! was s7 | explicit, ! was s4 | hdz, ! was s15 | tphdz1,tphdz0, ! were s13,s12 (using gmr) | djint, ! was s11 | divbz, ! was s7 (DIV(B)+(DH*D*BZ)/(D*BZ) | hdzmbz,hdzpbz, ! were s10,s9 | p_coeff,q_coeff,r_coeff, ! coefficients for tridiagonal solver (s1,s2,s3) | bdotu, ! was s7 (B.U) | op_loss, ! was s13 | tp ! te+ti real,dimension(lev0:lev1,lon0:lon1,lat0-1:lat1+1) :: hj ! (s10-s12) ! ! Local fields at 3d subdomain (must be 3d to bridge latitude scans): real,dimension(lev0:lev1,lon0-2:lon1+2,lat0-2:lat1+2) :: | bvel, | diffj, ! (D/(H*DZ)*2.*TP+M*G/R)*N(O+) (s7,s8,s9) | tpj, ! N(O+)*(te+ti) (s3-s7) | bdotdh_op, ! (b(h)*del(h))*phi | bdotdh_opj, ! (b(h)*del(h))*phi | bdotdh_diff, ! (b(h)*del(h))*phi | dj, ! diffusion coefficients (s13,s14,s15) | optm1_smooth ! op at time n-1, with shapiro smoother (was s1) real,dimension(lev0:lev1,lon0-2:lon1+2,lat0-2:lat1+2,5) :: f5 logical,parameter :: debug=.false. ! if set write print statements to stdout ! if (debug) write(6,"('Enter oplus.')") #ifdef VT ! code = 113 ; state = 'oplus' ; activity='ModelCode' call vtbegin(113,ier) #endif ! ! Number of pressure levels (this will equal nlevp1): nlevs = lev1-lev0+1 ! for bndlons calls ! ! do lat=lat0,lat1 ! call addfld('TE_OP',' ',' ',te(lev0:lev1-1,lon0:lon1,lat), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! call addfld('TI_OP',' ',' ',ti(lev0:lev1-1,lon0:lon1,lat), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! call addfld('N2D_OP',' ',' ',n2d(:,lon0:lon1,lat), ! | 'lev',lev0,lev1,'lon',lon0,lon1,lat) ! call addfld('NE_OP',' ',' ',ne(:,lon0:lon1,lat), ! | 'lev',lev0,lev1,'lon',lon0,lon1,lat) ! call addfld('OPTM1',' ',' ',optm1(:,lon0:lon1,lat), ! | 'lev',lev0,lev1,'lon',lon0,lon1,lat) ! call addfld('OP_OPLUS',' ',' ',op(:,lon0:lon1,lat), ! | 'lev',lev0,lev1,'lon',lon0,lon1,lat) ! call addfld('UI_OP',' ',' ',ui(:,lon0:lon1,lat), ! | 'lev',lev0,lev1,'lon',lon0,lon1,lat) ! call addfld('VI_OP',' ',' ',vi(:,lon0:lon1,lat), ! | 'lev',lev0,lev1,'lon',lon0,lon1,lat) ! call addfld('WI_OP',' ',' ',wi(:,lon0:lon1,lat), ! | 'lev',lev0,lev1,'lon',lon0,lon1,lat) ! enddo ! lat=lat0,lat1 ! ! Sub oplus_flux returns upward number flux of O+ in ! opflux(lon0:lon1,lat0:lat1): call oplus_flux(opflux,lon0,lon1,lat0,lat1) if (debug) write(6,"('oplus after oplus_flux.')") ! ! Divergence is returned in dvb(lon0:lon1,lat0:lat1) by sub divb: call divb(dvb,lon0,lon1,lat0,lat1) if (debug) write(6,"('oplus after divb.')") ! !----------------------- Begin first latitude scan --------------------- do lat=lat0,lat1 if (debug) write(6,"('oplus begin first lat scan: lat=',i3)")lat jm2 = lat-2 jm1 = lat-1 j0 = lat jp1 = lat+1 jp2 = lat+2 ! ! Set tp's: do i=lon0,lon1 do k=lev0,lev1-1 tpj(k,i,jm1) = 0.5*(te(k,i,jm1)+ti(k,i,jm1)) tpj(k,i,lat ) = 0.5*(te(k,i,lat )+ti(k,i,lat )) tpj(k,i,jp1) = 0.5*(te(k,i,jp1)+ti(k,i,jp1)) enddo enddo ! ! rrk returns djm1,dj,djp1: ! subroutine rrk(t,rms,ps1,ps2,tp,ans,lon0,lon1,lev0,lev1,lat) ! call rrk( | tn (:,lon0:lon1,jm1),barm(:,lon0:lon1,jm1), | o2 (:,lon0:lon1,jm1),o1(:,lon0:lon1,jm1), | tpj(:,lon0:lon1,jm1),dj(:,lon0:lon1,jm1), | lon0,lon1,lev0,lev1,lat) call rrk( | tn (:,lon0:lon1,lat),barm(:,lon0:lon1,lat), | o2 (:,lon0:lon1,lat),o1(:,lon0:lon1,lat), | tpj(:,lon0:lon1,lat),dj(:,lon0:lon1,lat), | lon0,lon1,lev0,lev1,lat) call rrk( | tn (:,lon0:lon1,jp1),barm(:,lon0:lon1,jp1), | o2 (:,lon0:lon1,jp1),o1(:,lon0:lon1,jp1), | tpj(:,lon0:lon1,jp1),dj(:,lon0:lon1,jp1), | lon0,lon1,lev0,lev1,lat) if (debug) write(6,"('oplus after rrk: lat=',i3)") lat ! call addfld('DJM1',' ',' ',dj(:,lon0:lon1,jm1), ! | 'lev',lev0,lev1,'lon',lon0,lon1,lat) ! call addfld('DJ ',' ',' ',dj(:,lon0:lon1,lat), ! | 'lev',lev0,lev1,'lon',lon0,lon1,lat) ! call addfld('DJP1',' ',' ',dj(:,lon0:lon1,jp1), ! | 'lev',lev0,lev1,'lon',lon0,lon1,lat) do i=lon0,lon1 do k=lev0,lev1-1 tpj(k,i,jm1) = 2.*tpj(k,i,jm1) tpj(k,i,lat) = 2.*tpj(k,i,lat) tpj(k,i,jp1) = 2.*tpj(k,i,jp1) enddo enddo if (debug) write(6,"('oplus after tpj: lat=',i3)") lat ! do i=lon0,lon1 do k=lev0,lev1-1 hj(k,i,jm1) = gask*tn(k,i,jm1)/ | (0.5*(barm(k,i,jm1)+barm(k+1,i,jm1))*grav) hj(k,i,lat ) = gask*tn(k,i,j0 )/ | (0.5*(barm(k,i,j0 )+barm(k+1,i,j0 ))*grav) hj(k,i,jp1) = gask*tn(k,i,jp1)/ | (0.5*(barm(k,i,jp1)+barm(k+1,i,jp1))*grav) enddo enddo if (debug) write(6,"('oplus after hj: lat=',i3)") lat ! call addfld('HJM1',' ',' ',hj(lev0:lev1-1,:,jm1), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! call addfld('HJ ',' ',' ',hj(lev0:lev1-1,:,lat), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! call addfld('HJP1',' ',' ',hj(lev0:lev1-1,:,jp1), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! ! bvel @ jm1 = (B.U)*N(O+) (J-1) (was s6) ! bvel @ j = (B.U)*N(O+) (J) (was s7) ! bvel @ jp1 = (B.U)*N(O+) (J+1) (was s8) ! do i=lon0,lon1 do k=lev0,lev1-1 bvel(k,i,jm1) = | (bx(i,jm1)*u(k,i,jm1)+by(i,jm1)*v(k,i,jm1)+ | hj(k,i,jm1)*bz(i,jm1)*0.5*(w(k,i,jm1)+w(k+1,i,jm1)))* | op(k,i,jm1) bvel(k,i,lat) = | (bx(i,lat)*u(k,i,j0)+by(i,lat)*v(k,i,j0)+ | hj(k,i,lat)*bz(i,lat)*0.5*(w(k,i,j0)+w(k+1,i,j0)))* | op(k,i,j0) bvel(k,i,jp1) = | (bx(i,jp1)*u(k,i,jp1)+by(i,jp1)*v(k,i,jp1)+ | hj(k,i,jp1)*bz(i,jp1)*0.5*(w(k,i,jp1)+w(k+1,i,jp1)))* | op(k,i,jp1) enddo ! k=lev0,lev1-1 enddo ! i=lon0,lon1 if (debug) write(6,"('oplus after bvel: lat=',i3)") lat ! call addfld('BVEL_JM1',' ',' ',bvel(lev0:lev1-1,lon0:lon1,jm1), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! call addfld('BVEL_J' ,' ',' ',bvel(lev0:lev1-1,lon0:lon1,j0), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! call addfld('BVEL_JP1',' ',' ',bvel(lev0:lev1-1,lon0:lon1,jp1), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! subroutine diffus(tp,en,hj,ans,lon0,lon1,lev0,lev1,lat) ! real,dimension(lev0:lev1,lon0:lon1),intent(in) :: tp,en,hj ! real,dimension(lev0:lev1,lon0:lon1),intent(out) :: ans ! tpj(lev1,:,jm1:jp1) = 0. call diffus( | tpj (:,lon0:lon1,jm1),op(:,lon0:lon1,jm1),hj(:,:,jm1), | diffj(:,lon0:lon1,jm1),lon0,lon1,lev0,lev1,lat) call diffus( | tpj (:,lon0:lon1,lat),op(:,lon0:lon1,lat),hj(:,:,lat), | diffj(:,lon0:lon1,lat),lon0,lon1,lev0,lev1,lat) call diffus( | tpj (:,lon0:lon1,jp1),op(:,lon0:lon1,jp1),hj(:,:,jp1), | diffj(:,lon0:lon1,jp1),lon0,lon1,lev0,lev1,lat) if (debug) write(6,"('oplus after diffus: lat=',i3)") lat ! call addfld('DIFFJM1',' ',' ',diffj(:,lon0:lon1,jm1), ! | 'lev',lev0,lev1,'lon',lon0,lon1,lat) ! call addfld('DIFFJ ',' ',' ',diffj(:,lon0:lon1,lat), ! | 'lev',lev0,lev1,'lon',lon0,lon1,lat) ! call addfld('DIFFJP1',' ',' ',diffj(:,lon0:lon1,jp1), ! | 'lev',lev0,lev1,'lon',lon0,lon1,lat) ! ! tpjm2 = 2.*TP*N(O+) (J-2) ! tpjm1 = 2.*TP*N(O+) (J-1) ! tp = 2.*TP*N(O+) (J) ! tpjp1 = 2.*TP*N(O+) (J+1) ! tpjp2 = 2.*TP*N(O+) (J+2) ! do i=lon0,lon1 do k=lev0,lev1-1 tpj(k,i,jm2) = op(k,i,jm2)*(te(k,i,jm2)+ti(k,i,jm2)) tpj(k,i,jm1) = tpj(k,i,jm1)*op(k,i,jm1) tpj(k,i,lat ) = tpj(k,i,lat )*op(k,i,lat) tpj(k,i,jp1) = tpj(k,i,jp1)*op(k,i,jp1) tpj(k,i,jp2) = op(k,i,jp2)*(te(k,i,jp2)+ti(k,i,jp2)) enddo ! k=lev0,lev1-1 enddo ! i=lon0,lon1 if (debug) write(6,"('oplus after tpj2: lat=',i3)") lat ! call addfld('TPJM2',' ',' ',tpj(lev0:lev1-1,lon0:lon1,jm2), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! call addfld('TPJM1',' ',' ',tpj(lev0:lev1-1,lon0:lon1,jm1), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! call addfld('TP ',' ',' ',tpj(lev0:lev1-1,lon0:lon1,lat), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! call addfld('TPJP1',' ',' ',tpj(lev0:lev1-1,lon0:lon1,jp1), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! call addfld('TPJP2',' ',' ',tpj(lev0:lev1-1,lon0:lon1,jp2), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! ! Shapiro smoother: optm1 is O+ at time n-1 (optm1_smooth was s1) ! optm1_smooth will be used in explicit terms below. do i=lon0,lon1 do k=lev0,lev1-1 optm1_smooth(k,i,lat) = optm1(k,i,j0)-shapiro* | (optm1(k,i,jp2)+optm1(k,i,jm2)-4.* | (optm1(k,i,jp1)+optm1(k,i,jm1))+6.* | optm1(k,i,j0)) enddo ! k=lev0,lev1-1 enddo ! i=lon0,lon1 ! if (debug) write(6,"('oplus end first lat scan: lat=',i3)") lat enddo ! lat=lat0,lat1 !------------------------- End first latitude scan --------------------- #ifdef MPI ! ! ! Boundary longitudes: f5(:,:,:,1) = dj(:,:,:) f5(:,:,:,2) = bvel(:,:,:) f5(:,:,:,3) = diffj(:,:,:) f5(:,:,:,4) = tpj(:,:,:) f5(:,:,:,5) = optm1_smooth(:,:,:) call mp_bndlons_f3d(f5,nlevs,lon0,lon1,lat0,lat1,5,0) dj(:,:,:) = f5(:,:,:,1) bvel(:,:,:) = f5(:,:,:,2) diffj(:,:,:) = f5(:,:,:,3) tpj(:,:,:) = f5(:,:,:,4) optm1_smooth(:,:,:) = f5(:,:,:,5) ! ! Periodic points for dj: call mp_periodic_f3d(dj(:,lon0:lon1,lat0-1:lat1+1),lev0,lev1, | lon0,lon1,lat0,lat1,1) ! #endif !----------------------- Begin second latitude scan -------------------- do lat=lat0,lat1 if (debug) | write(6,"('oplus begin first lat scan: lat=',i3)") lat jm2 = lat-2 jm1 = lat-1 j0 = lat jp1 = lat+1 jp2 = lat+2 ! ! bdotdh_op = (B(H).DEL(H))*(D/(H*DZ)*TP+M*G/R)*N(O+) ! then bdotdh_op = d*bz*bdotdh_op ! call bdotdh( | diffj(:,lon0:lon1,jm1), | diffj(:,:,lat), | diffj(:,lon0:lon1,jp1), | bdotdh_op(:,lon0:lon1,lat),lon0,lon1,lev0,lev1,lat) ! do i=lon0,lon1 do k=lev0,lev1-1 bdotdh_op(k,i,lat) = dj(k,i,lat)*bz(i,lat)*bdotdh_op(k,i,lat) enddo ! k=lev0,lev1-1 enddo ! i=lon0,lon1 ! call addfld('BDOTDH',' ',' ',bdotdh_op(lev0:lev1-1,lon0:lon1,lat), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! ! bdotdh_opjm1 = (B(H).DEL(H))*2.*TP*N(O+) (J-1) ! bdotdh_opj = (B(H).DEL(H))*2.*TP*N(O+) (J) ! bdotdh_opjp1 = (B(H).DEL(H))*2.*TP*N(O+) (J+1) ! call bdotdh( | tpj(:,lon0:lon1,jm2), | tpj(:,:,jm1), | tpj(:,lon0:lon1,lat ), | bdotdh_opj(:,lon0:lon1,jm1),lon0,lon1,lev0,lev1,jm1) call bdotdh( | tpj(:,lon0:lon1,jm1), | tpj(:,:,lat ), | tpj(:,lon0:lon1,jp1), | bdotdh_opj(:,lon0:lon1,lat),lon0,lon1,lev0,lev1,lat) call bdotdh( | tpj(:,lon0:lon1,lat ), | tpj(:,:,jp1), | tpj(:,lon0:lon1,jp2), | bdotdh_opj(:,lon0:lon1,jp1),lon0,lon1,lev0,lev1,jp1) ! do i=lon0,lon1 do k=lev0,lev1-1 bdotdh_opj(k,i,jm1) = bdotdh_opj(k,i,jm1)*dj(k,i,jm1) bdotdh_opj(k,i,lat) = bdotdh_opj(k,i,lat)*dj(k,i,lat) bdotdh_opj(k,i,jp1) = bdotdh_opj(k,i,jp1)*dj(k,i,jp1) enddo ! k=lev0,lev1-1 enddo ! i=lon0,lon1 ! if (debug) | write(6,"('oplus end second lat scan: lat=',i3)") lat enddo ! lat=lat0,lat1 !------------------------ End second latitude scan --------------------- ! #ifdef MPI ! ! Periodic points for bdotdh_opj (output from bdotdh above): call mp_periodic_f3d(bdotdh_opj(:,lon0:lon1,lat0:lat1), | lev0,lev1,lon0,lon1,lat0,lat1,1) ! ! Boundary longitudes for bdotdh_opj (input to below call to bdotdh): call mp_bndlons_f3d(bdotdh_opj,nlevs,lon0,lon1,lat0,lat1,1,0) #endif ! !----------------------- Begin third latitude scan --------------------- do lat=lat0,lat1 if (debug) | write(6,"('oplus begin third lat scan: lat=',i3)") lat jm2 = lat-2 jm1 = lat-1 j0 = lat jp1 = lat+1 jp2 = lat+2 ! ! bdotdh_opj = (B(H).DEL(H))*D*(B(H).DEL(H))*2.*TP*N(O+) (J) ! Note bdotdh_opj longitude dimension is lon-2:lon+2. bdotdh_diff ! is returned. (periodic points apparently not necessary for ! bdotdh_diff) ! call bdotdh( | bdotdh_opj(:,lon0:lon1,jm1), | bdotdh_opj(:,:,lat), | bdotdh_opj(:,lon0:lon1,jp1), | bdotdh_diff(:,lon0:lon1,lat),lon0,lon1,lev0,lev1,lat) ! call addfld('BDOT_DIF',' ',' ',bdotdh_diff(lev0:lev1-1,lon0:lon1, ! | lat),'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! call addfld('BDOT_JM1',' ',' ',bdotdh_opj(lev0:lev1-1,lon0:lon1, ! | jm1),'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! call addfld('BDOT_J' ,' ',' ',bdotdh_opj(lev0:lev1-1,lon0:lon1, ! | lat),'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! call addfld('BDOT_JP1',' ',' ',bdotdh_opj(lev0:lev1-1,lon0:lon1, ! | jp1),'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! ! bdzdvb_op = (BZ*D/(H*DZ)+DIV(*B))*S2 ! bdzdvb returns bdzdvb_op. ! call bdzdvb(bdotdh_opj(:,lon0:lon1,lat),dvb(:,lat),hj(:,:,lat), | bdzdvb_op,lev0,lev1,lon0,lon1,lat) ! call addfld('BDZDVB',' ',' ',bdzdvb_op(lev0:lev1-1,:), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! ! Collect explicit terms: do i=lon0,lon1 do k=lev0,lev1-1 explicit(k,i) = -explic*(bdzdvb_op(k,i)+bdotdh_diff(k,i,lat)+ | bdotdh_op(k,i,lat)) enddo ! k=lev0,lev1-1 enddo ! i=lon0,lon1 ! call addfld('EXPLIC0',' ',' ',explicit(lev0:lev1-1,:), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! call addfld('BX',' ',' ',bx(lon0:lon1,:), ! | 'lon',lon0,lon1,'lat',lat,lat,0) ! call addfld('BY',' ',' ',by(lon0:lon1,:), ! | 'lon',lon0,lon1,'lat',lat,lat,0) ! call addfld('UI_VEL',' ',' ',ui(:,lon0:lon1,lat), ! | 'lev',lev0,lev1,'lon',lon0,lon1,lat) ! call addfld('VI_VEL',' ',' ',vi(:,lon0:lon1,lat), ! | 'lev',lev0,lev1,'lon',lon0,lon1,lat) lonbeg = lon0 if (lon0==1) lonbeg = 3 lonend = lon1 if (lon1==nlonp4) lonend = lon1-2 ! ! Note if input flag DYNAMO<=0, then ui,vi,wi velocities will be zero. do i=lonbeg,lonend do k=lev0,lev1-1 explicit(k,i) = explicit(k,i)+1./(2.*re)* | (1./(cs(lat)*dlamda)*(bx(i,lat)* | (bvel(k,i+1,lat)-bvel(k,i-1,lat))+ | 0.5*(ui(k,i,lat)+ui(k+1,i,lat))*bmod2(i,lat)**2* | (op(k,i+1,j0)/bmod2(i+1,lat)**2- | op(k,i-1,j0)/bmod2(i-1,lat)**2))+ ! | 1./dphi*(by(i,lat)*(bvel(k,i,jp1)-bvel(k,i,jm1))+ | 0.5*(vi(k,i,lat)+vi(k+1,i,lat))*bmod2(i,lat)**2* | (op(k,i,jp1)/bmod2(i,jp1)**2- | op(k,i,jm1)/bmod2(i,jm1)**2))) enddo ! k=lev0,lev1-1 enddo ! i=lon0+2,lon1-2 ! ! Periodic points for explicit terms. ! This is apparently unnecessary: ! call periodic_f2d(explicit,lon0,lon1,nlevs) ! call addfld('EXPLIC1',' ',' ',explicit(lev0:lev1-1,:), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) do i=lon0,lon1 dvb(i,lat) = dvb(i,lat)/bz(i,lat) enddo ! i=lon0,lon1 ! do i=lon0,lon1 do k=lev0,lev1-1 hdz(k,i) = 1./(hj(k,i,lat)*dz) ! s15 tp(k,i) = 0.5*(ti(k,i,j0)+te(k,i,j0)) ! s14 enddo ! k=lev0,lev1-1 enddo ! i=lon0,lon1 ! call addfld('HDZ',' ',' ',hdz(lev0:lev1-1,:), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! ! gmr = G*M(O+)/(2.*R) gmr = grav*rmass_op/(2.*gask) do i=lon0,lon1 do k=lev0,lev1-2 tphdz1(k+1,i) = 2.*tp(k+1,i)*(0.5*(hdz(k,i)+hdz(k+1,i)))+ | gmr ! s13 tphdz0(k+1,i) = 2.*tp(k ,i)*(0.5*(hdz(k,i)+hdz(k+1,i)))- | gmr ! s12 enddo ! k=lev0,lev1-2 enddo ! i=lon0,lon1 ! ! Upper and lower boundaries: do i=lon0,lon1 tphdz1(lev0,i) = 2.*tp(lev0,i)* | (1.5*hdz(lev0,i)-0.5*hdz(lev0+1,i))+gmr tphdz1(lev1,i) = 2.*(2.*tp(lev1-1,i)-tp(lev1-2,i))* | (1.5*hdz(lev1-1,i)-0.5*hdz(lev1-2,i))+gmr tphdz0(lev0,i) = 2.*(2.*tp(lev0,i)-tp(lev0+1,i))* | (1.5*hdz(lev0,i)-0.5*hdz(lev0+1,i))-gmr tphdz0(lev1,i) = 2.*tp(lev1-1,i)* | (1.5*hdz(lev1-1,i)-0.5*hdz(lev1-2,i))-gmr enddo ! i=lon0,lon1 ! call addfld('TPHDZ1',' ',' ',tphdz1, ! | 'lev',lev0,lev1,'lon',lon0,lon1,lat) ! call addfld('TPHDZ0',' ',' ',tphdz0, ! | 'lev',lev0,lev1,'lon',lon0,lon1,lat) ! ! djint = dj at interfaces: do i=lon0,lon1 do k=lev0,lev1-2 djint(k+1,i) = 0.5*(dj(k,i,lat)+dj(k+1,i,lat)) ! s11=.5*(s8(k)+s8(k+1)) enddo ! k=lev0,lev1-2 djint(lev0,i) = (1.5*dj(lev0 ,i,lat)-0.5*dj(lev0+1,i,lat)) djint(lev1,i) = (1.5*dj(lev1-1,i,lat)-0.5*dj(lev1-2,i,lat)) enddo ! i=lon0,lon1 ! call addfld('DJINT' ,' ',' ',djint, ! | 'lev',lev0,lev1,'lon',lon0,lon1,lat) ! ! divbz = (DIV(B)+(DH*D*BZ)/(D*BZ) (was s7) do i=lonbeg,lonend do k=lev0,lev1-1 divbz(k,i) = | dvb(i,lat)+1./(re*dj(k,i,lat)*bz(i,lat)**2)*(bx(i,lat)/ | cs(lat)*(dj(k,i+1,lat)*bz(i+1,lat)-dj(k,i-1,lat)* | bz(i-1,lat))/(2.*dlamda)+by(i,lat)*(dj(k,i,jp1)* | bz(i,jp1)-dj(k,i,jm1)*bz(i,jm1))/(2.*dphi)) enddo ! k=lev0,lev1-1 enddo ! i=lonbeg,lonend ! Periodic points for divbz apparently not necessary: ! call periodic_f2d(divbz,lon0,lon1,nlevs) ! ! Set periodic points to zero to avoid NaNS trap: if (lon0==1) divbz(:,lon0:lon0+1) = 0. if (lon1==nlonp4) divbz(:,lon1-1:lon1) = 0. ! call addfld('DIVBZ' ,' ',' ',divbz(lev0:lev1-1,:), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! ! hdzmbz = (1./(H*DZ)-(DIV(B)+DH*D*BZ/(D*BZ))/(2*BZ))*BZ**2 (was s10) ! hdzpbz = (1./(H*DZ)+(DIV(B)+DH*D*BZ/(D*BZ))/(2*BZ))*BZ**2 (was s9 ) ! do i=lon0,lon1 do k=lev0,lev1-1 hdzmbz(k,i) = (hdz(k,i)-0.5*divbz(k,i))*bz(i,lat)**2 hdzpbz(k,i) = (hdz(k,i)+0.5*divbz(k,i))*bz(i,lat)**2 enddo ! k=lev0,lev1-1 enddo ! i=lon0,lon1 ! call addfld('HDZMBZ' ,' ',' ',hdzmbz(lev0:lev1-1,:), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! call addfld('HDZPBZ' ,' ',' ',hdzpbz(lev0:lev1-1,:), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! ! Sum O+ at time n-1 to explicit terms: N(O+)/(2*DT) (N-1) (was s4) ! Boundary longitudes for optm1_smooth were obtained after first ! latitude scan above. ! do i=lonbeg,lonend do k=lev0,lev1-1 explicit(k,i) = explicit(k,i)-(optm1_smooth(k,i,lat)- | shapiro* | (optm1_smooth(k,i+2,lat)+optm1_smooth(k,i-2,lat)-4.* | (optm1_smooth(k,i+1,lat)+optm1_smooth(k,i-1,lat))+6.* | optm1_smooth(k,i,lat)))*dtx2inv enddo ! k=lev0,lev1 enddo ! i=lonbeg,lonend ! call addfld('OPTM1_SM' ,' ',' ', ! | optm1_smooth(lev0:lev1-1,lon0:lon1,lat), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! call addfld('EXPLIC2' ,' ',' ',explicit(lev0:lev1-1,:), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! ! Begin coefficients p_coeff, q_coeff, r_coeff (s1,s2,s3) do i=lon0,lon1 do k=lev0,lev1-1 p_coeff(k,i) = hdzmbz(k,i)*djint(k ,i)*tphdz0(k ,i) q_coeff(k,i) = -(hdzpbz(k,i)*djint(k+1,i)*tphdz0(k+1,i)+ | hdzmbz(k,i)*djint(k ,i)*tphdz1(k ,i)) r_coeff(k,i) = hdzpbz(k,i)*djint(k+1,i)*tphdz1(k+1,i) enddo ! k=lev0,lev1-1 enddo ! i=lon0,lon1 ! call addfld('P_COEFF0',' ',' ',p_coeff(lev0:lev1-1,:), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! call addfld('Q_COEFF0',' ',' ',q_coeff(lev0:lev1-1,:), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! call addfld('R_COEFF0',' ',' ',r_coeff(lev0:lev1-1,:), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! ! bdotu = B.U (s7) do i=lon0,lon1 do k=lev0,lev1-1 bdotu(k,i) = bx(i,lat)*u(k,i,j0)+by(i,lat)*v(k,i,j0)+ | hj(k,i,lat)*bz(i,lat)*0.5*(w(k,i,j0)+w(k+1,i,j0)) enddo ! k=lev0,lev1-1 enddo ! i=lon0,lon1 ! call addfld('BDOTU' ,' ',' ',bdotu(lev0:lev1-1,:), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! ! Continue coefficients with vertical ion velocity: do i=lon0,lon1 do k=lev0,lev1-2 p_coeff(k+1,i) = p_coeff(k+1,i)+ | (bz(i,lat)*bdotu(k,i)+0.5*(wi(k+1,i,lat)+wi(k+2,i,lat)))* | 0.5*hdz(k+1,i) q_coeff(k,i) = q_coeff(k,i)-0.5*(wi(k,i,lat)+wi(k+1,i,lat))* | 6./re r_coeff(k,i) = r_coeff(k,i)-(bz(i,lat)*bdotu(k+1,i)+ | 0.5*(wi(k,i,lat)+wi(k+1,i,lat)))*0.5*hdz(k,i) enddo ! k=lev0,lev1-2 enddo ! i=lon0,lon1 ! ! call addfld('P_COEFF1',' ',' ',p_coeff(lev0:lev1-1,:), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! call addfld('Q_COEFF1',' ',' ',q_coeff(lev0:lev1-1,:), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! call addfld('R_COEFF1',' ',' ',r_coeff(lev0:lev1-1,:), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! ! Upper and lower boundaries: do i=lon0,lon1 p_coeff(lev0,i) = p_coeff(lev0,i)+(bz(i,lat)* | (2.*bdotu(lev0,i)-bdotu(lev0+1,i))+0.5* | (wi(lev0,i,lat)+wi(lev0+1,i,lat)))*0.5*hdz(lev0,i) q_coeff(lev1-1,i) = q_coeff(lev1-1,i)- | 0.5*(wi(lev1,i,lat)+wi(lev1-1,i,lat))*6./re r_coeff(lev1-1,i) = r_coeff(lev1-1,i)- | (bz(i,lat)*(2.*bdotu(lev1-1,i)-bdotu(lev1-2,i))+ | 0.5*(wi(lev1,i,lat)+wi(lev1-1,i,lat)))*0.5*hdz(lev1-1,i) enddo ! i=lon0,lon1 ! ! Additions to Q coefficients: do i=lon0,lon1 do k=lev0,lev1-1 q_coeff(k,i) = q_coeff(k,i)-bdotu(k,i)*dvb(i,lat)*bz(i,lat)- | dtx2inv enddo ! k=lev0,lev1-1 enddo ! i=lon0,lon1 ! ! Upper boundary condition for O+: do i=lon0,lon1 ubca(i) = 0. ubcb(i) = -bz(i,lat)**2*djint(lev1,i)*tphdz0(lev1,i)-ubca(i) ! t3 ubca(i) = -bz(i,lat)**2*djint(lev1,i)*tphdz1(lev1,i)+ubca(i) ! t2 ! ! Q = Q+B/A*R q_coeff(lev1-1,i) = q_coeff(lev1-1,i)+ubcb(i)/ubca(i)* | r_coeff(lev1-1,i) ! ! F = F -R/A*PHI explicit(lev1-1,i) = explicit(lev1-1,i)-opflux(i,lat)* | r_coeff(lev1-1,i)/ubca(i) r_coeff(lev1-1,i) = 0. enddo ! i=lon0,lon1 ! call addfld('EXPLIC3',' ',' ',explicit(lev0:lev1-1,:), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! call addfld('P_COEFF2',' ',' ',p_coeff(lev0:lev1-1,:), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! call addfld('Q_COEFF2',' ',' ',q_coeff(lev0:lev1-1,:), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! call addfld('R_COEFF2',' ',' ',r_coeff(lev0:lev1-1,:), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! call addfld('QOP2P_OP',' ',' ',qop2p(:,lon0:lon1,lat), ! | 'lev',lev0,lev1,'lon',lon0,lon1,lat) ! call addfld('QOP2D_OP',' ',' ',qop2d(:,lon0:lon1,lat), ! | 'lev',lev0,lev1,'lon',lon0,lon1,lat) ! call addfld('RK20',' ',' ',rk20(lev0:lev1-1,lon0:lon1,lat), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! call addfld('RK25',' ',' ',rk25(lev0:lev1-1,lon0:lon1,lat), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! ! Sources and sinks (xiop2p and xiop2d are outputs): ! do i=lon0,lon1 do k=lev0,lev1-1 ! psi_n2(k,i) = 1.-o2(k,i,j0)-o1(k,i,j0) ! n2 mixing ratio ! xiop2p(k,i,lat) = | 0.5*(qop2p(k,i,lat)+qop2p(k+1,i,lat))/((xnmbar(k,i,lat)* | ((rk16+rk17)*psi_n2(k,i)*rmassinv_n2+ | rk18*o1(k,i,j0)*rmassinv_o1))+(rk19(k,i,lat)+rk20(k,i,lat))* | ne(k,i,j0)+rk21+rk22) ! xiop2d(k,i,lat) = | (0.5*(qop2d(k,i,lat)+qop2d(k+1,i,lat))+(rk20(k,i,lat)* | ne(k,i,j0)+rk22)*xiop2p(k,i,lat))/((xnmbar(k,i,lat)* | (rk23*psi_n2(k,i)*rmassinv_n2+rk24* | o1(k,i,j0)*rmassinv_o1+rk26*o2(k,i,j0)*rmassinv_o2))+ | rk25(k,i,lat)*ne(k,i,j0)+rk27) ! op_loss(k,i) = | xnmbar(k,i,lat)*(rk1(k,i,lat)*o2(k,i,j0)*rmassinv_o2+ | rk2(k,i,lat)*psi_n2(k,i)*rmassinv_n2+rk10* | n2d(k,i,j0)*rmassinv_n2d) ! q_coeff(k,i) = q_coeff(k,i)-op_loss(k,i) enddo ! k=lev0,lev1-1 enddo ! i=lon0,lon1 ! call addfld('XIOP2P',' ',' ',xiop2p(lev0:lev1,lon0:lon1,lat), ! | 'lev',lev0,lev1,'lon',lon0,lon1,lat) ! call addfld('XIOP2D',' ',' ',xiop2d(lev0:lev1,lon0:lon1,lat), ! | 'lev',lev0,lev1,'lon',lon0,lon1,lat) ! call addfld('OP_LOSS',' ',' ',op_loss(lev0:lev1-1,lon0:lon1), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! call addfld('OP_QOP',' ',' ',qop(lev0:lev1,lon0:lon1,lat), ! | 'lev',lev0,lev1,'lon',lon0,lon1,lat) ! call addfld('OP_NE' ,' ',' ',ne(lev0:lev1,lon0:lon1,lat), ! | 'lev',lev0,lev1,'lon',lon0,lon1,lat) ! call addfld('OP_O1' ,' ',' ',o1(lev0:lev1,lon0:lon1,lat), ! | 'lev',lev0,lev1,'lon',lon0,lon1,lat) ! call addfld('OP_TN' ,' ',' ',tn(lev0:lev1,lon0:lon1,lat), ! | 'lev',lev0,lev1,'lon',lon0,lon1,lat) ! call addfld('OP_BARM' ,' ',' ',barm(lev0:lev1,lon0:lon1,lat), ! | 'lev',lev0,lev1,'lon',lon0,lon1,lat) ! call addfld('OP_RK19' ,' ',' ',rk19(lev0:lev1-1,lon0:lon1,lat), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! call addfld('OP_RK25' ,' ',' ',rk25(lev0:lev1-1,lon0:lon1,lat), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! ! Add source term to RHS (explicit terms): do i=lon0,lon1 do k=lev0,lev1-1 explicit(k,i) = explicit(k,i)- | 0.5*(qop(k,i,lat)+qop(k+1,i,lat))-(rk19(k,i,lat)* | ne(k,i,j0)+rk21)* | xiop2p(k,i,lat)-(rk25(k,i,lat)*ne(k,i,j0)+rk27)* | xiop2d(k,i,lat)-(rk18*xiop2p(k,i,lat)+rk24*xiop2d(k,i,lat))* | o1(k,i,j0)*rmassinv_o1*p0*expz(k)*0.5*(barm(k,i,j0)+ | barm(k+1,i,j0))/(boltz*tn(k,i,j0)) enddo ! k=lev0,lev1-1 enddo ! i=lon0,lon1 ! call addfld('EXPLIC4',' ',' ',explicit(lev0:lev1-1,:), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! ! Lower boundary condition N(O+) = Q/L: do i=lon0,lon1 q_coeff(lev0,i) = q_coeff(lev0,i)-p_coeff(lev0,i) explicit(lev0,i) = explicit(lev0,i)-2.*p_coeff(lev0,i)* | qop(lev0,i,lat)/(1.5*op_loss(lev0,i)-0.5*op_loss(lev0+1,i)) p_coeff(lev0,i) = 0. enddo ! i=lon0,lon1 ! call addfld('P_COEFF',' ',' ',p_coeff(lev0:lev1-1,:), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! call addfld('Q_COEFF',' ',' ',q_coeff(lev0:lev1-1,:), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! call addfld('R_COEFF',' ',' ',r_coeff(lev0:lev1-2,:), ! | 'lev',lev0,lev1-2,'lon',lon0,lon1,lat) ! call addfld('EXPLIC5',' ',' ',explicit(lev0:lev1-1,:), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! ! Tridiagonal solver returns updated O+ in opout (all other args are input): ! subroutine trsolv(a,b,c,f,x,lev0,lev1,k1,k2,lon0,lon1,lonmax,lat, ! | idebug) ! call trsolv(p_coeff,q_coeff,r_coeff,explicit, | opout(:,lon0:lon1,lat),lev0,lev1,lev0,lev1-1,lon0,lon1,nlonp4, | lat,0) ! ! call addfld('OP_SOLV',' ',' ',opout(lev0:lev1-1,lon0:lon1,lat), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) if (debug) | write(6,"('oplus end third lat scan: lat=',i3)") lat enddo ! lat=lat0,lat1 !------------------------ End third latitude scan --------------------- ! ! Filter updated O+: ! call filter_op(opout(:,lon0:lon1,lat0:lat1), | lev0,lev1,lon0,lon1,lat0,lat1,kut) ! !----------------------- Begin fourth latitude scan --------------------- do lat=lat0,lat1 if (debug) | write(6,"('oplus begin fourth lat scan: lat=',i3)") lat ! ! call addfld('OP_FILT',' ',' ',opout(lev0:lev1-1,lon0:lon1,lat), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! ! Time smoothing: ! ! optm1out(k,i,lat): New O+ at current latitude and time n-1. ! op(k,i,lat) : O+ at current latitude and time. ! optm1(k,i,lat) : O+ at current latitude and time n-1. ! opout(k,i,lat) : New O+ at current latitude and time. ! do i=lon0,lon1 do k=lev0,lev1-1 optm1out(k,i,lat) = dtsmooth*op(k,i,lat)+dtsmooth_div2* | (optm1(k,i,lat)+opout(k,i,lat)) enddo ! k=lev0,lev1-1 enddo ! i=lon0,lon1 ! ! Upper boundary: opout(lev1,:,lat) = 0. optm1out(lev1,:,lat) = 0. ! ! Insure non-negative O+: do i=lon0,lon1 do k=lev0,lev1-1 if (opout(k,i,lat) < 1.e-5) opout(k,i,lat) = 1.e-5 if (optm1out(k,i,lat) < 1.e-5) optm1out(k,i,lat) = 1.e-5 enddo ! k=lev0,lev1-1 enddo ! i=lon0,lon1 ! ! End fourth and final latitude scan: enddo ! lat=lat0,lat1 ! ! Periodic points for outputs: #ifdef MPI call mp_periodic_f3d(opout(:,lon0:lon1,lat0:lat1), | lev0,lev1,lon0,lon1,lat0,lat1,1) call mp_periodic_f3d(optm1out(:,lon0:lon1,lat0:lat1), | lev0,lev1,lon0,lon1,lat0,lat1,1) #endif ! ! Save outputs on secondary history for diagnostics: ! do lat=lat0,lat1 ! call addfld('OPOUT',' ',' ',opout(lev0:lev1-1,lon0:lon1,lat), ! | 'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! call addfld('OPOUTM1',' ',' ',optm1out(lev0:lev1-1,lon0:lon1, ! | lat),'lev',lev0,lev1-1,'lon',lon0,lon1,lat) ! enddo ! lat=lat0,lat1 #ifdef VT ! code = 113 ; state = 'oplus' ; activity='ModelCode' call vtend(113,ier) #endif if (debug) | write(6,"('oplus returning.')") end subroutine oplus !----------------------------------------------------------------------- subroutine oplus_flux(opflux,lon0,lon1,lat0,lat1) ! ! Calculate O+ number flux in opflux for sub oplus (was sub opflux). ! use cons_module,only: pi,rtd use chapman_module,only: chi ! was t2 in old sub opflux use magfield_module,only: rlatm ! ! Args: integer,intent(in) :: lon0,lon1,lat0,lat1 real,intent(out) :: opflux(lon0:lon1,lat0:lat1) ! ! Local: integer :: i,lat real,parameter :: | phid = 2.0e8, | phin = -2.0e8, | ppolar = 0. real :: a(lon0:lon1) ! was t3 ("a" needs a better name) real :: fed(lon0:lon1) ! was t4 real :: fen(lon0:lon1) ! was t5 ! ! Latitude scan: do lat=lat0,lat1 ! ! Longitude loop: do i=lon0,lon1 if (abs(rlatm(i,lat))-pi/24.>=0.) then a(i) = 1. else a(i)=.5*(1.+sin(pi*(abs(rlatm(i,lat))-pi/48.)/(pi/24.))) if (a(i) < 0.05) a(i) = 0.05 endif fed(i) = phid*a(i) fen(i) = phin*a(i) if (chi(i,lat)-0.5*pi >= 0.) then opflux(i,lat) = fen(i) else opflux(i,lat) = fed(i) endif if ((chi(i,lat)*rtd-80.)*(chi(i,lat)*rtd-100.) < 0.) | opflux(i,lat) = .5*(fed(i)+fen(i))+.5*(fed(i)-fen(i))* | cos(pi*(chi(i,lat)*rtd-80.)/20.) ! ! Add ppolar if magnetic latitude >= 60 degrees: if (abs(rlatm(i,lat))-pi/3. >= 0.) | opflux(i,lat) = opflux(i,lat)+ppolar enddo ! i=lon0,lon1 enddo ! lat=lat0,lat1 ! end subroutine oplus_flux !----------------------------------------------------------------------- subroutine divb(dvb,lon0,lon1,lat0,lat1) use cons_module,only: cs,dlamda,dphi,re ! ! Evaluate divergence of B, the unit magnetic field vector. ! ! Args: integer,intent(in) :: lon0,lon1,lat0,lat1 real,intent(out) :: dvb(lon0:lon1,lat0:lat1) ! ! Local: integer :: lonbeg,lonend,i,lat,jm1,jp1 ! lonbeg = lon0 if (lon0==1) lonbeg = 3 lonend = lon1 if (lon1==nlonp4) lonend = lon1-2 ! do lat=lat0,lat1 jm1 = lat-1 jp1 = lat+1 dvb(:,lat) = 0. do i=lonbeg,lonend dvb(i,lat) = (((bx(i+1,lat)-bx(i-1,lat))/(2.*dlamda)+ | (cs(jp1)*by(i,jp1)-cs(jm1)*by(i,jm1))/(2.*dphi))/ | cs(lat)+2.*bz(i,lat))/re enddo ! i=lonbeg,lonend enddo ! lat=lat0,lat1 ! end subroutine divb !----------------------------------------------------------------------- subroutine rrk(t,rms,ps1,ps2,tp,ans,lon0,lon1,lev0,lev1,lat) ! ! Returns diffusion coefficient in ans. ! use cons_module,only: rmassinv_o2,rmassinv_o1,rmassinv_n2,boltz, | p0,expz use input_module,only: colfac ! ! Args: integer,intent(in) :: lon0,lon1,lev0,lev1,lat real,dimension(lev0:lev1,lon0:lon1),intent(in) :: | t,rms,ps1,ps2,tp real,dimension(lev0:lev1,lon0:lon1),intent(out) :: ans ! ! Local: integer :: k,i ! do i=lon0,lon1 do k=lev0,lev1-1 ans(k,i) = 1.42E17*boltz*t(k,i)/(p0*expz(k)*.5*(rms(k,i)+ | rms(k+1,i))*(ps2(k,i)*rmassinv_o1*sqrt(tp(k,i))*(1.-0.064* | alog10(tp(k,i)))**2*colfac+18.6*(1.-ps1(k,i)-ps2(k,i))* | rmassinv_n2+18.1*ps1(k,i)*rmassinv_o2)) enddo ! k=lev0,lev1 enddo ! i=lon0,lon1 end subroutine rrk !----------------------------------------------------------------------- subroutine diffus(tp,en,hj,ans,lon0,lon1,lev0,lev1,lat) ! ! Evaluates ans = (d/(h*dz)*tp+m*g/r)*en ! use cons_module,only: rmass_op,grav,gask ! ! Args: integer :: lon0,lon1,lev0,lev1,lat real,dimension(lev0:lev1,lon0:lon1),intent(in) :: | tp,en,hj real,dimension(lev0:lev1,lon0:lon1),intent(out) :: ans ! ! Local: integer :: k,i,k1,k2 real :: mgr ! mgr = rmass_op*grav/gask do i=lon0,lon1 do k=lev0,lev1-2 k1 = k+1 k2 = k+2 ans(k1,i) = 1./(2.*hj(k1,i)*dlev)*(tp(k2,i)*en(k2,i)- | tp(k,i)*en(k,i))+mgr*en(k1,i) enddo enddo ! ! Upper and lower boundaries: k1 = lev1-1 k2 = lev1-2 do i=lon0,lon1 ans(k1,i) = 1./(hj(k1,i)*dlev)*(tp(k1,i)*en(k1,i)- | tp(k2,i)*en(k2,i))+mgr*en(k1,i) ans(1,i) = 1./(hj(1,i)*dlev)*(tp(2,i)*en(2,i)- | tp(1,i)*en(1,i))+mgr*en(1,i) enddo end subroutine diffus !----------------------------------------------------------------------- subroutine bdotdh(phijm1,phij,phijp1,ans,lon0,lon1,lev0,lev1,lat) use cons_module,only: re,dphi,dlamda,cs ! ! Evaluates ans = (b(h)*del(h))*phi ! ! Args: integer :: iperiodic,lon0,lon1,lev0,lev1,lat real,dimension(lev0:lev1,lon0:lon1),intent(in) :: phijm1,phijp1 real,dimension(lev0:lev1,lon0-2:lon1+2),intent(inout) :: phij real,dimension(lev0:lev1,lon0:lon1),intent(out) :: ans ! ! Local: integer :: k,i,lonbeg,lonend ! lonbeg = lon0 if (lon0==1) then lonbeg = 3 ans(:,lon0:lon1) = 0. ! set periodic points to zero to avoid NaNS trap endif lonend = lon1 if (lon1==nlonp4) then lonend = lon1-2 ans(:,lon1-1:lon1) = 0. ! set periodic points to zero to avoid NaNS trap endif ! ! Note phij longitude dimension is lon0-2:lon1+2 (only i-1 and i+1 are used). ! Boundary longitudes i-1 and i+1 must have been set before this routine is ! called (e.g., call mp_bndlons_f3d). ! do i=lonbeg,lonend do k=lev0,lev1-1 ans(k,i) = 1./re*(bx(i,lat)/(cs(lat)*2.*dlamda)* | (phij(k,i+1)-phij(k,i-1))+by(i,lat)* | (phijp1(k,i)-phijm1(k,i))/(2.*dphi)) enddo ! k=lev0,lev1 enddo ! i=lonbeg,lonend ! end subroutine bdotdh !----------------------------------------------------------------------- subroutine bdzdvb(phi,dvb,h,ans,lev0,lev1,lon0,lon1,lat) ! ! Evaluates ans = (bz*d/(h*dz)+divb)*phi ! ! Args: integer :: lev0,lev1,lon0,lon1,lat real,intent(in) :: dvb(lon0:lon1) real,dimension(lev0:lev1,lon0:lon1),intent(in) :: phi,h real,dimension(lev0:lev1,lon0:lon1),intent(out) :: ans ! ! Local: integer :: k,i ! do i=lon0,lon1 do k=lev0+1,lev1-2 ans(k,i) = bz(i,lat)/(2.*h(k,i)*dz)*(phi(k+1,i)-phi(k-1,i))+ | dvb(i)*phi(k,i) enddo ! k=lev0+1,lev1-1 enddo ! i=lon0,lon1 ! ! Upper and lower boundaries: do i=lon0,lon1 ans(lev1-1,i) = bz(i,lat)/(h(lev1-1,i)*dz)*(phi(lev1-1,i)- | phi(lev1-2,i))+dvb(i)*phi(lev1-1,i) ans(lev0,i) = bz(i,lat)/(h(lev0,i)*dz)* | (phi(lev0+1,i)-phi(lev0,i))+dvb(i)*phi(lev0,i) enddo ! i=lon0,lon1 end subroutine bdzdvb !----------------------------------------------------------------------- subroutine filter_op(opout,lev0,lev1,lon0,lon1,lat0,lat1,kut) ! ! Filter updated O+. This is called from outside latitude loop, ! i.e., once per timestep. ! use filter_module,only: filter,filter2 #ifdef MPI use mpi_module,only: mytidi,mp_gatherlons_f3d,mp_scatterlons_f3d #else integer :: mytidi=0 #endif ! ! Args: integer,intent(in) :: lev0,lev1,lon0,lon1,lat0,lat1 integer,intent(in) :: kut(nlat) real,intent(inout) :: opout(lev0:lev1,lon0:lon1,lat0:lat1) ! ! Local: integer :: i,j,ier real :: op_ik(nlonp4,lev0:lev1),op_kij(lev0:lev1,nlonp4,lat0:lat1) real :: fmin,fmax ! #ifdef VT ! code = 124 ; state = 'filter_op' ; activity='Filtering' call vtbegin(124,ier) #endif ! ! Define lons in op_kij from current task subdomain opout: op_kij = 0. do j=lat0,lat1 do i=lon0,lon1 op_kij(:,i,j) = opout(:,i,j) enddo enddo ! j=lat0,lat1 ! #ifdef MPI ! ! Gather longitudes into tasks in first longitude column of task table ! (leftmost of each j-row) for global fft. (i.e., tasks with mytidi==0 ! gather lons from other tasks in that row). This includes all latitudes. ! call mp_gatherlons_f3d(op_kij,lev0,lev1,lon0,lon1,lat0,lat1,1) #endif ! ! Only leftmost tasks at each j-row of tasks does the global filtering: if (mytidi==0) then ! ! Loop through subdomain latitudes: latscan: do j=lat0,lat1 ! ! Define 2d array at all longitudes for filter2: do i=1,nlonp4 op_ik(i,:) = op_kij(:,i,j) enddo ! i=1,nlonp4 ! ! Do the filtering (requires fft): ! call filter and/or filter2 according to module logicals callfilt1,callfilt2: ! ! If requested, call filter2(), as in composition comp_major and minor: if (callfilt2) call filter2(op_ik,lev0,lev1,j) ! ! If requested, call filter(), as in dt,duv,etc: ! if (callfilt1) call filter(op_ik,lev0,lev1,kut(j),j) ! ! Return filtered array to op_kij: do i=1,nlonp4 op_kij(:,i,j) = op_ik(i,:) enddo ! i=1,nlonp4 enddo latscan ! j=lat0,lat1 endif ! mytidi==0 #ifdef MPI ! ! Now leftmost task at each j-row must redistribute filtered data ! back to other tasks in the j-row (mytidi>0,mytidj) (includes latitude): ! call mp_scatterlons_f3d(op_kij,lev0,lev1,lon0,lon1,lat0,lat1,1, | 'op ') #endif ! ! Return filtered array to opout at task subdomain: do j=lat0,lat1 do i=lon0,lon1 opout(:,i,j) = op_kij(:,i,j) enddo enddo ! #ifdef VT ! code = 124 ; state = 'filter_op' ; activity='Filtering' call vtend(124,ier) #endif end subroutine filter_op !----------------------------------------------------------------------- end module oplus_module