subroutine orthogonalize_u(ndim, m, u, n, error, comm)
!================================================!
implicit none
type(w90_error_type), allocatable, intent(out) :: error
type(w90_comm_type), intent(in) :: comm
integer, intent(in) :: ndim, m
complex(kind=dp), intent(inout) :: u(ndim, m)
integer, intent(in) :: n
complex(kind=dp), allocatable :: smat(:, :), evecl(:, :), evecr(:, :)
complex(kind=dp), allocatable :: WORK(:)
real(kind=dp), allocatable :: eig(:), RWORK(:)
integer :: INFO, i, j, l, LWORK, ierr
if (n .lt. m) then
call set_error_fatal(error, 'n<m', comm)
return
end if
allocate (smat(n, m)); smat(1:n, 1:m) = u(1:n, 1:m)
allocate (evecl(n, n), evecr(m, m))
allocate (eig(min(m, n)))
allocate (RWORK(5*min(n, m)))
LWORK = 2*min(m, n) + max(m, n)
allocate (WORK(LWORK))
! Singular-value decomposition
call zgesvd('A', 'A', n, m, smat, n, eig, evecl, n, evecr, m, WORK, LWORK, RWORK, INFO)
if (info .ne. 0) then
call set_error_fatal(error, ' ERROR: IN ZGESVD IN orthogonalize_u', comm)
return
end if
deallocate (smat, stat=ierr)
if (ierr /= 0) then
call set_error_dealloc(error, 'Error in deallocating smat in orthogonalize_u', comm)
return
end if
deallocate (eig, stat=ierr)
if (ierr /= 0) then
call set_error_dealloc(error, 'Error in deallocating eig in orthogonalize_u', comm)
return
end if
deallocate (WORK, stat=ierr)
if (ierr /= 0) then
call set_error_dealloc(error, 'Error in deallocating WORK in orthogonalize_u', comm)
return
end if
deallocate (RWORK, stat=ierr)
if (ierr /= 0) then
call set_error_dealloc(error, 'Error in deallocating RWORK in orthogonalize_u', comm)
return
end if
! u_matrix is the initial guess for the unitary rotation of the
! basis states given by the subroutine extract
u = 0
do j = 1, m
do l = 1, m
do i = 1, n
u(i, j) = u(i, j) + evecl(i, l)*evecr(l, j)
end do
end do
end do
deallocate (evecl, stat=ierr)
if (ierr /= 0) then
call set_error_dealloc(error, 'Error in deallocating evecl in orthogonalize_u', comm)
return
end if
deallocate (evecr, stat=ierr)
if (ierr /= 0) then
call set_error_dealloc(error, 'Error in deallocating evecr in orthogonalize_u', comm)
return
end if
end subroutine orthogonalize_u