FIXME : Add documentation
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
complex, | intent(in), | dimension (-ntgrid:,:,:) | :: | phi | ||
complex, | intent(in), | dimension (-ntgrid:,:,:) | :: | apar | ||
complex, | intent(in), | dimension (-ntgrid:,:,:) | :: | bpar |
subroutine getfield (phi, apar, bpar)
use kt_grids, only: naky, ntheta0
use gs2_layouts, only: f_lo, jf_lo
use theta_grid, only: ntgrid
use mp, only: sum_allreduce, allgatherv, iproc, nproc
implicit none
complex, dimension (-ntgrid:,:,:), intent (in) :: phi, apar, bpar
complex, dimension (:,:,:), allocatable :: fl
complex, dimension (:), allocatable :: u
complex, dimension (:), allocatable :: u_small
integer :: jflo, ik, it, nl, nr, i, m, n, dc
allocate (fl(nidx, ntheta0, naky))
!On first call to this routine setup the receive counts (recvcnts)
!and displacement arrays (displs)
if ((.not.allocated(recvcnts)).and.field_subgath) then
allocate(recvcnts(nproc),displs(nproc)) !Note there's no matching deallocate
do i=0,nproc-1
displs(i+1)=MIN(i*jf_lo%blocksize,jf_lo%ulim_world+1) !This will assign a displacement outside the array for procs with no data
recvcnts(i+1)=MIN(jf_lo%blocksize,jf_lo%ulim_world-displs(i+1)+1) !This ensures that we expect no data from procs without any
enddo
endif
! am*u = fl, Poisson's and Ampere's law, u is phi, apar, bpar
! u = aminv*fl
call get_field_vector (fl, phi, apar, bpar)
!Initialise array, if not gathering then have to zero entire array
if(field_subgath) then
allocate(u_small(jf_lo%llim_proc:jf_lo%ulim_proc))
else
allocate(u_small(0:nidx*ntheta0*naky-1))
endif
u_small=0.
!Should this really be to ulim_alloc instead?
do jflo = jf_lo%llim_proc, jf_lo%ulim_proc
!Class index
i = jf_lo%ij(jflo)
!Class member index (i.e. which member of the class)
m = jf_lo%mj(jflo)
!Get ik index
ik = f_lo(i)%ik(m,1) ! For fixed i and m, ik does not change as n varies
!Get d(istributed) cell index
dc = jf_lo%dj(i,jflo)
!Loop over cells in class (these are the 2pi domains in flux tube/box mode)
do n = 1, N_class(i)
!Get it index
it = f_lo(i)%it(m,n)
!Get extent of current cell in extended/ballooning space domain
nl = 1 + nidx*(n-1)
nr = nl + nidx - 1
!Perform section of matrix vector multiplication
u_small(jflo)=u_small(jflo)-sum(aminv(i)%dcell(dc)%supercell(nl:nr)*fl(:, it, ik))
end do
end do
!Free memory
deallocate (fl)
!Gather/reduce the remaining data
if(field_subgath) then
allocate (u (0:nidx*ntheta0*naky-1))
call allgatherv(u_small,recvcnts(iproc+1),u,recvcnts,displs)
deallocate(u_small)
else
call sum_allreduce(u_small)
endif
!Reshape data into field arrays and free memory
if(field_subgath)then
call get_field_solution (u)
deallocate(u)
else
call get_field_solution (u_small)
deallocate(u_small)
endif
end subroutine getfield