subroutine w90_readwrite_read_atoms(settings, atom_data, real_lattice, bohr, error, comm)
use w90_error, only: w90_error_type, set_error_input, set_error_dealloc, set_error_alloc
use w90_utility, only: utility_cart_to_frac
implicit none
! arguments
real(kind=dp), intent(in) :: bohr
real(kind=dp), intent(in) :: real_lattice(3, 3)
type(atom_data_type), intent(inout) :: atom_data
type(settings_type), intent(inout) :: settings
type(w90_comm_type), intent(in) :: comm
type(w90_error_type), allocatable, intent(out) :: error
! local variables
character(len=maxlen), allocatable :: atoms_label_tmp(:)
integer :: i_temp, i_temp2, loop, nsymb, ierr
logical :: found, found2, found3, lunits
real(kind=dp), allocatable :: atoms_pos_cart_tmp(:, :)
real(kind=dp), allocatable :: atoms_pos_frac_tmp(:, :)
found = .false.
found2 = .false.
found3 = .false.
if (allocated(settings%entries)) then
call w90_readwrite_get_vector_length(settings, 'symbols', found, nsymb, error, comm)
if (allocated(error)) return
call w90_readwrite_get_vector_length(settings, 'atoms_cart', found2, i_temp, error, comm)
if (allocated(error)) return
call w90_readwrite_get_vector_length(settings, 'atoms_frac', found3, i_temp, error, comm)
if (allocated(error)) return
if (.not. (found .or. found2 .or. found3)) then
return ! neither specified, not necessarily an error (only needed if projectors wanted)
end if
! if supplied, need both entries: labels and positions
if (.not. (found .and. (found2 .or. found3))) then
call set_error_input(error, 'Error: Must specify both symbols and atoms_frac (or atoms_cart)', comm)
return
end if
if (found) atom_data%num_atoms = nsymb ! shape of symbols is n, i_temp returns n
allocate (atoms_label_tmp(atom_data%num_atoms), stat=ierr)
if (ierr /= 0) then
call set_error_alloc(error, 'Error in allocating atoms_label_tmp in w90_readwrite_read_atoms', comm)
return
end if
allocate (atoms_pos_cart_tmp(3, atom_data%num_atoms), stat=ierr)
if (ierr /= 0) then
call set_error_alloc(error, 'Error in allocating atoms_pos_cart_tmp in w90_readwrite_read_atoms', comm)
return
end if
! get symbols list
if (found) then
call w90_readwrite_get_keyword_vector(settings, 'symbols', found, i_temp, error, comm, &
c2_value=atoms_label_tmp)
if (allocated(error)) return
end if
if (found2) then
call w90_readwrite_get_keyword_vector(settings, 'atoms_cart', found, i_temp, error, comm, &
r2_value=atoms_pos_cart_tmp)
if (allocated(error)) return
end if
if (found3) then
allocate (atoms_pos_frac_tmp(3, atom_data%num_atoms), stat=ierr)
if (ierr /= 0) then
call set_error_alloc(error, 'Error in allocating atoms_pos_frac_tmp in w90_readwrite_read_atoms', comm)
return
end if
call w90_readwrite_get_keyword_vector(settings, 'atoms_frac', found, i_temp, error, comm, &
r2_value=atoms_pos_frac_tmp)
if (allocated(error)) return
do loop = 1, atom_data%num_atoms
call utility_cart_to_frac(atoms_pos_frac_tmp(:, loop), &
atoms_pos_cart_tmp(:, loop), transpose(real_lattice))
end do
deallocate (atoms_pos_frac_tmp, stat=ierr)
if (ierr /= 0) then
call set_error_dealloc(error, 'Error in deallocating atoms_pos_frac_tmp in w90_readwrite_read_atoms', comm)
return
end if
end if
call w90_readwrite_set_atoms(atom_data, atoms_label_tmp, atoms_pos_cart_tmp, error, comm)
if (allocated(error)) return
deallocate (atoms_label_tmp, stat=ierr)
if (ierr /= 0) then
call set_error_dealloc(error, 'Error in deallocating atoms_label_tmp in w90_readwrite_read_atoms', comm)
return
end if
deallocate (atoms_pos_cart_tmp, stat=ierr)
if (ierr /= 0) then
call set_error_dealloc(error, 'Error in deallocating atoms_pos_cart_tmp in w90_readwrite_read_atoms', comm)
return
end if
return ! no futher action in library mode
end if
i_temp = 0
i_temp2 = 0
found = .false.
found2 = .false.
! Atoms
call w90_readwrite_get_block_length(settings, 'atoms_frac', found, i_temp, error, comm)
if (allocated(error)) return
call w90_readwrite_get_block_length(settings, 'atoms_cart', found2, i_temp2, error, comm, lunits)
if (allocated(error)) return
if (found .and. found2) then
call set_error_input(error, 'Error: Cannot specify both atoms_frac and atoms_cart', comm)
return
elseif (found .and. i_temp > 0) then
lunits = .false.
atom_data%num_atoms = i_temp
elseif (found2 .and. i_temp2 > 0) then
atom_data%num_atoms = i_temp2
! when units are specified, one fewer line than the total contains atom information
if (lunits) atom_data%num_atoms = atom_data%num_atoms - 1
end if
if (atom_data%num_atoms > 0) then
call readwrite_get_atoms(settings, atom_data, lunits, real_lattice, bohr, error, comm)
if (allocated(error)) return
end if
end subroutine w90_readwrite_read_atoms