FIXME : Add documentation
subroutine init_invert_rhs
use species, only: spec
use theta_grid, only: ntgrid
use le_grids, only: forbid, grid_has_trapped_particles, is_lower_bounce_point, is_ttp
use constants, only: zi
use gs2_layouts, only: g_lo, ik_idx, it_idx, il_idx, ie_idx, is_idx
use array_utils, only: zero_array
#ifdef LOWFLOW
use lowflow, only: wstar_neo
#endif
implicit none
integer :: iglo
integer :: ig, ik, it, il, ie, is, isgn
real :: wdttp, vp, bd
#ifdef LOWFLOW
complex :: wd
#else
real :: wd
#endif
if (.not.allocated(a)) then
allocate (a(-ntgrid:ntgrid,2,g_lo%llim_proc:g_lo%ulim_alloc))
allocate (b(-ntgrid:ntgrid,2,g_lo%llim_proc:g_lo%ulim_alloc))
allocate (r(-ntgrid:ntgrid,2,g_lo%llim_proc:g_lo%ulim_alloc))
allocate (ainv(-ntgrid:ntgrid,2,g_lo%llim_proc:g_lo%ulim_alloc))
endif
call zero_array(a) ; call zero_array(b)
call zero_array(r) ; call zero_array(ainv)
!$OMP PARALLEL DO DEFAULT(none) &
!$OMP PRIVATE(iglo, ik, it, il, ie, is, isgn, ig, wd, wdttp, vp, bd) &
!$OMP SHARED(g_lo, ntgrid, wdrift, wdriftttp, vpar, bkdiff, ainv, fexp, &
#ifdef LOWFLOW
!$OMP wstar_neo, &
#endif
!$OMP spec, forbid, is_ttp, r, a, b) &
!$OMP SCHEDULE(static)
do iglo = g_lo%llim_proc, g_lo%ulim_proc
ik = ik_idx(g_lo,iglo)
it = it_idx(g_lo,iglo)
il = il_idx(g_lo,iglo)
ie = ie_idx(g_lo,iglo)
is = is_idx(g_lo,iglo)
do isgn = 1, 2
do ig = -ntgrid, ntgrid-1
wd = wdrift(ig,isgn,iglo)
wdttp = wdriftttp(ig, isgn, iglo)
# ifdef LOWFLOW
wd = wd + wstar_neo(ig,it,ik)*spec(is)%zt
wdttp = wdttp + wstar_neo(ig,it,ik)*spec(is)%zt
# endif
! use positive vpar because we will be flipping sign of d/dz
! when doing parallel field solve for -vpar
! also, note that vpar is (vpa bhat + v_{magnetic}) . grad theta / delthet
! if compile with LOWFLOW defined
vp = vpar(ig,1,iglo)
bd = bkdiff(is)
ainv(ig,isgn,iglo) &
= 1.0/(1.0 + bd &
+ (1.0-fexp(is))*spec(is)%tz*(zi*wd*(1.0+bd) + 2.0*vp))
r(ig,isgn,iglo) &
= (1.0 - bd &
+ (1.0-fexp(is))*spec(is)%tz*(zi*wd*(1.0-bd) - 2.0*vp)) &
*ainv(ig,isgn,iglo)
a(ig,isgn,iglo) &
= 1.0 + bd &
+ fexp(is)*spec(is)%tz*(-zi*wd*(1.0+bd) - 2.0*vp)
b(ig,isgn,iglo) &
= 1.0 - bd &
+ fexp(is)*spec(is)%tz*(-zi*wd*(1.0-bd) + 2.0*vp)
if (grid_has_trapped_particles()) then
! zero out forbidden regions
if (forbid(ig,il) .or. forbid(ig+1,il)) then
r(ig,isgn,iglo) = 0.0
ainv(ig,isgn,iglo) = 0.0
end if
! CMR, DD, 25/7/2014:
! set ainv=1 just left of lower bounce points ONLY for RIGHTWARDS travelling
! trapped particles. Part of multiple trapped particle algorithm
! NB not applicable to ttp or wfb!
if( isgn.eq.1 )then
if (is_lower_bounce_point(ig+1, il)) then
ainv(ig,isgn,iglo) = 1.0 + ainv(ig,isgn,iglo)
end if
endif
! ???? mysterious mucking around with totally trapped particles
! part of multiple trapped particle algorithm
if (is_ttp(ig, il)) then
ainv(ig,isgn,iglo) = 1.0/(1.0 + zi*(1.0-fexp(is))*spec(is)%tz*wdttp)
a(ig,isgn,iglo) = 1.0 - zi*fexp(is)*spec(is)%tz*wdttp
r(ig,isgn,iglo) = 0.0
end if
end if
end do
end do
end do
!$OMP END PARALLEL DO
call init_homogeneous_g(g_h)
end subroutine init_invert_rhs