A routine to invert the field matrix locally
Currently every processor which is responsible for a chunk of the response matrix at the solve stage will do this inversion. This is obviously duplicated work but allows us to skip any communication in the push_arr_to_rows method. If only one processor did the inversion then we would need to communicate the result back. We are unlikely to want to do this in a non-blocking manner as it would require that we hold onto the tmp_arr for each response matrix, only freeing this memory after the non-blocking communications have completed. As these matrices are large we don't want them hanging around longer than required. In the typical use case where we have large minnrow, we would expect most matrices to belong to just one or a few processors so this point may not be important in most cases.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
class(supercell_type), | intent(inout) | :: | self |
subroutine sc_invert_local(self)
use mat_inv, only: invert_serial
use mp, only: broadcast_sub
implicit none
class(supercell_type), intent(inout) :: self
complex, dimension(:,:), allocatable :: tmp_arr
!Exit early if possible
if(self%is_empty) return
if(.not.self%is_local) return
!Allocate temporary array
allocate(tmp_arr(self%ncol,self%nrow))
!First have to pull all row level data
call self%pull_rows_to_arr(tmp_arr)
!It may be better to hook into the GK_VERBOSITY level system
!rather than relying on the debug flag.
if (self%is_head) then
self%condition_number = l2norm(tmp_arr)
end if
!Now invert in place
if (self%is_head) then
call invert_serial(tmp_arr, self%nrow)
tmp_arr=transpose(tmp_arr)
end if
!It would be quite nice if we could do the following in a non-blocking manner
!but this would require us to either keep the potentially large tmp_arr allocated
!for all supercells or for us to be able to do this "in-place" (i.e. we use something
!like non-blocking scatterv rather than broadcast).
if (.not. self%is_all_local) then
if (self%sc_sub_pd%nproc > 0) call broadcast_sub(tmp_arr, &
self%head_iproc_pd, self%sc_sub_pd%id)
end if
if (self%is_head) then
self%condition_number = self%condition_number * l2norm(tmp_arr)
end if
!Now push back to row level
call self%push_arr_to_rows(tmp_arr)
!Free memory
deallocate(tmp_arr)
end subroutine sc_invert_local