36 use,
intrinsic :: iso_fortran_env
68 type(lattice_vectors_t) :: latt
71 type(atom_t),
allocatable :: atom(:)
73 type(symmetries_t) :: symm
75 type(distributed_t) :: atoms_dist
77 integer,
allocatable :: map_symm_atoms(:,:)
78 integer,
allocatable :: inv_map_symm_atoms(:,:)
82 class(species_wrapper_t),
allocatable :: species(:)
83 logical :: only_user_def
84 logical,
private :: species_time_dependent
86 logical :: force_total_enforce
87 type(ion_interaction_t) :: ion_interaction
90 logical,
private :: apply_global_force
91 type(tdf_t),
private :: global_force_function
94 generic ::
assignment(=) => copy
125 procedure ions_constructor
132 type(namespace_t),
intent(in) :: namespace
133 logical,
optional,
intent(in) :: print_info
134 type(lattice_vectors_t),
optional,
intent(out) :: latt_inp
135 class(ions_t),
pointer :: ions
137 type(read_coords_info) :: xyz
138 integer :: ia, ierr, idir
139 character(len=100) :: function_name
140 real(real64) :: mindist
141 real(real64),
allocatable :: factor(:)
142 integer,
allocatable :: site_type(:)
143 logical,
allocatable :: spherical_site(:)
144 real(real64),
parameter :: threshold = 1e-5_real64
145 type(species_factory_t) :: factory
151 ions%namespace = namespace
153 ions%space =
space_t(namespace)
164 message(1) =
"Coordinates have not been defined."
173 safe_allocate(ions%atom(1:ions%natoms))
174 do ia = 1, ions%natoms
175 call atom_init(ions%atom(ia), ions%space%dim, xyz%atom(ia)%label)
176 ions%pos(:,ia) = xyz%atom(ia)%x(1:ions%space%dim)
178 ions%fixed(ia) = .not. xyz%atom(ia)%move
182 if (
allocated(xyz%latvec))
then
192 do ia = 1, ions%natoms
193 ions%pos(:, ia) = ions%latt%red_to_cart(ions%pos(:, ia))
205 if (
present(latt_inp))
then
212 if (ions%space%has_mixed_periodicity())
then
213 safe_allocate(factor(ions%space%dim))
214 do idir = 1, ions%space%periodic_dim
217 do idir = ions%space%periodic_dim + 1, ions%space%dim
218 factor(idir) =
m_one/norm2(ions%latt%rlattice(1:ions%space%dim, idir))
220 call ions%latt%scale(factor)
221 safe_deallocate_a(factor)
225 do ia = 1, ions%natoms
226 ions%mass(ia) = ions%atom(ia)%species%get_mass()
227 ions%charge(ia) = ions%atom(ia)%species%get_zval()
231 if (ions%natoms > 1)
then
233 if (mindist < threshold)
then
234 write(
message(1),
'(a)')
"Some of the atoms seem to sit too close to each other."
235 write(
message(2),
'(a)')
"Please review your input files and the output geometry (in 'static/')."
236 write(
message(3),
'(a, f12.6, 1x, a)')
"Minimum distance = ", &
242 call ions%write_xyz(trim(
static_dir)//
'/geometry')
246 message(1) =
"It cannot be correct to run with physical atoms so close."
252 safe_allocate(spherical_site(1:ions%natoms))
253 safe_allocate(site_type(1:ions%natoms))
254 do ia = 1, ions%natoms
255 select type(spec => ions%atom(ia)%species)
257 spherical_site(ia) = .false.
259 spherical_site(ia) = .false.
261 spherical_site(ia) = .false.
263 spherical_site(ia) = .false.
265 spherical_site(ia) = .
true.
268 site_type(ia) = ions%atom(ia)%species%get_index()
271 ions%symm =
symmetries_t(ions%namespace, ions%space, ions%latt, ions%natoms, ions%pos, site_type, spherical_site)
273 safe_deallocate_a(spherical_site)
274 safe_deallocate_a(site_type)
277 call ions%generate_mapping_symmetric_atoms()
289 call parse_variable(namespace,
'ForceTotalEnforce', .false., ions%force_total_enforce)
305 ions%apply_global_force = .
true.
307 call parse_variable(namespace,
'TDGlobalForce',
'none', function_name)
308 call tdf_read(ions%global_force_function, namespace, trim(function_name), ierr)
311 call messages_write(
"You have enabled the GlobalForce option but Octopus could not find")
312 call messages_write(
"the '"//trim(function_name)//
"' function in the TDFunctions block.")
318 ions%apply_global_force = .false.
329 type(
ions_t),
intent(inout) :: ions
331 logical,
optional,
intent(in) :: print_info
333 logical :: print_info_, spec_user_defined
334 integer :: i, j, k, ispin
340 if (
present(print_info))
then
341 print_info_ = print_info
345 atoms1:
do i = 1, ions%natoms
349 ions%nspecies = ions%nspecies + 1
353 allocate(ions%species(1:ions%nspecies))
357 ions%only_user_def = .
true.
358 atoms2:
do i = 1, ions%natoms
363 ions%species(k)%s => factory%create_from_input(ions%namespace, ions%atom(j)%get_label(), k)
365 select type(spec => ions%species(k)%s)
369 ions%only_user_def = .false.
372 select type(spec => ions%species(k)%s)
374 if (ions%space%dim /= 3)
then
375 message(1) =
"Pseudopotentials may only be used with Dimensions = 3."
380 if (ions%space%is_periodic() .and. ions%space%periodic_dim /= 2)
then
381 message(1) =
"Periodic jelium slab can only be used if PeriodicDim = 2"
392 ispin = min(2, ispin)
394 if (print_info_)
then
397 do i = 1, ions%nspecies
398 spec => ions%species(i)%s
399 call spec%build(ions%namespace, ispin, ions%space%dim, print_info=print_info_)
401 if (print_info_)
then
414 call parse_variable(ions%namespace,
'SpeciesTimeDependent', .false., ions%species_time_dependent)
416 do i = 1,ions%nspecies
417 select type(spec=>ions%species(i)%s)
419 spec_user_defined = .
true.
422 if (ions%species_time_dependent .and. .not. spec_user_defined)
then
427 do i = 1, ions%natoms
428 do j = 1, ions%nspecies
441 class(
ions_t),
intent(out) :: ions_out
442 class(
ions_t),
intent(in) :: ions_in
448 ions_out%latt = ions_in%latt
450 ions_out%natoms = ions_in%natoms
451 safe_allocate(ions_out%atom(1:ions_out%natoms))
452 ions_out%atom = ions_in%atom
454 ions_out%nspecies = ions_in%nspecies
455 allocate(ions_out%species(1:ions_out%nspecies))
456 ions_out%species = ions_in%species
458 ions_out%only_user_def = ions_in%only_user_def
462 safe_allocate(ions_out%map_symm_atoms(1:ions_in%natoms, 1:ions_in%symm%nops))
463 ions_out%map_symm_atoms = ions_in%map_symm_atoms
464 safe_allocate(ions_out%inv_map_symm_atoms(1:ions_in%natoms, 1:ions_in%symm%nops))
465 ions_out%inv_map_symm_atoms = ions_in%inv_map_symm_atoms
473 class(
ions_t),
intent(inout) :: this
487 class(
ions_t),
target,
intent(inout) :: this
492 select type (interaction)
502 class(
ions_t),
intent(inout) :: this
511 class(
ions_t),
intent(inout) :: this
512 character(len=*),
intent(in) :: label
527 class(
ions_t),
intent(in) :: partner
532 select type (interaction)
542 class(
ions_t),
intent(inout) :: partner
547 select type (interaction)
558 class(
ions_t),
intent(inout) :: this
564 do iatom = 1, this%natoms
565 this%pos(:, iatom) = this%latt%fold_into_cell(this%pos(:, iatom))
572 real(real64) function ions_min_distance(this, real_atoms_only) result(rmin)
573 class(
ions_t),
intent(in) :: this
574 logical,
optional,
intent(in) :: real_atoms_only
576 integer :: iatom, jatom, idir
577 real(real64) :: xx(this%space%dim)
578 logical :: real_atoms_only_
581 if (this%natoms == 1 .and. .not. this%space%is_periodic())
then
586 push_sub(ions_min_distance)
595 do iatom = 1, this%natoms
599 if (real_atoms_only_) cycle
601 do jatom = iatom + 1, this%natoms
605 if (real_atoms_only_) cycle
607 xx = abs(this%pos(:, iatom) - this%pos(:, jatom))
608 if (this%space%is_periodic())
then
609 xx = this%latt%cart_to_red(xx)
610 do idir = 1, this%space%periodic_dim
613 xx = this%latt%red_to_cart(xx)
615 rmin = min(norm2(xx), rmin)
619 if (.not. (this%only_user_def .and. real_atoms_only_))
then
621 do idir = 1, this%space%periodic_dim
622 rmin = min(rmin, norm2(this%latt%rlattice(:,idir)))
627 if(rmin < huge(rmin)/1e6_real64)
then
628 rmin = anint(rmin*1e6_real64)*1.0e-6_real64
631 pop_sub(ions_min_distance)
640 time_dependent = this%species_time_dependent
646 real(real64) function ions_val_charge(this, mask) result(val_charge)
647 class(
ions_t),
intent(in) :: this
648 logical,
optional,
intent(in) :: mask(:)
652 if (
present(mask))
then
653 val_charge = -sum(this%charge, mask=mask)
655 val_charge = -sum(this%charge)
663 class(
ions_t),
intent(in) :: this
664 logical,
optional,
intent(in) :: mask(:)
665 real(real64) :: dipole(this%space%dim)
672 do ia = 1, this%natoms
673 if (
present(mask))
then
674 if (.not. mask(ia)) cycle
676 dipole = dipole + this%charge(ia)*this%pos(:, ia)
678 dipole = p_proton_charge*dipole
685 class(
ions_t),
intent(inout) :: this
686 real(real64),
intent(in) :: xx(this%space%dim)
692 do iatom = 1, this%natoms
693 this%pos(:, iatom) = this%pos(:, iatom) - xx
701 class(
ions_t),
intent(inout) :: this
702 real(real64),
intent(in) :: from(this%space%dim)
703 real(real64),
intent(in) :: from2(this%space%dim)
704 real(real64),
intent(in) :: to(this%space%dim)
707 real(real64) :: m1(3, 3), m2(3, 3)
708 real(real64) :: m3(3, 3), f2(3), per(3)
709 real(real64) :: alpha, r
713 if (this%space%dim /= 3)
then
714 call messages_not_implemented(
"ions_rotate in other than 3 dimensions", namespace=this%namespace)
718 m1 = diagonal_matrix(3, m_one)
721 if (abs(to(2)) > 1d-150)
then
722 alpha =
atan2(to(2), to(1))
725 alpha =
atan2(norm2(to(1:2)), to(3))
726 call rotate(m1, -alpha, 2)
729 f2 = matmul(m1, from)
741 m2 = diagonal_matrix(3, m_one)
742 alpha =
atan2(per(1), per(2))
743 call rotate(m2, -alpha, 3)
746 m3 = diagonal_matrix(3, m_one)
747 alpha =
acos(min(sum(from*to), m_one))
748 call rotate(m3, -alpha, 2)
751 m2 = matmul(transpose(m2), matmul(m3, m2))
754 per = matmul(m2, matmul(m1, from2))
755 alpha =
atan2(per(1), per(2))
756 call rotate(m2, -alpha, 3)
759 m1 = matmul(transpose(m1), matmul(m2, m1))
763 do iatom = 1, this%natoms
764 f2 = this%pos(:, iatom)
765 this%pos(:, iatom) = matmul(m1, f2)
772 subroutine rotate(m, angle, dir)
773 real(real64),
intent(inout) :: m(3, 3)
774 real(real64),
intent(in) :: angle
775 integer,
intent(in) :: dir
777 real(real64) :: aux(3, 3), ca, sa
815 class(
ions_t),
intent(in) :: this
816 real(real64),
intent(in) :: time
817 real(real64) :: force(this%space%dim)
823 if (this%apply_global_force)
then
824 force(1) = tdf(this%global_force_function, time)
831 subroutine ions_write_xyz(this, fname, append, comment, reduce_coordinates)
832 class(
ions_t),
intent(in) :: this
833 character(len=*),
intent(in) :: fname
834 logical,
optional,
intent(in) :: append
835 character(len=*),
optional,
intent(in) :: comment
836 logical,
optional,
intent(in) :: reduce_coordinates
838 integer :: iatom, idim, iunit
839 character(len=6) position
840 character(len=19) :: frmt
841 real(real64) :: red(this%space%dim)
843 if (.not. mpi_world%is_root())
return
848 if (
present(append))
then
849 if (append) position =
'append'
851 if(.not.optional_default(reduce_coordinates, .false.))
then
852 iunit = io_open(trim(fname)//
'.xyz', this%namespace, action=
'write', position=position)
854 iunit = io_open(trim(fname)//
'.xyz_red', this%namespace, action=
'write', position=position)
857 write(iunit,
'(i4)') this%natoms
858 if (
present(comment))
then
859 write(iunit,
'(1x,a)') comment
861 write(iunit,
'(1x,a,a)')
'units: ', trim(units_abbrev(units_out%length_xyz_file))
864 write(unit=frmt, fmt=
"(a5,i2.2,a4,i2.2,a6)")
"(6x,a", label_len,
",2x,", this%space%dim,
"f12.6)"
865 do iatom = 1, this%natoms
866 if(.not.optional_default(reduce_coordinates, .false.))
then
867 write(unit=iunit, fmt=frmt) this%atom(iatom)%label, &
868 (units_from_atomic(units_out%length_xyz_file, this%pos(idim, iatom)), idim=1, this%space%dim)
870 red = this%latt%cart_to_red(this%pos(:, iatom))
871 write(unit=iunit, fmt=frmt) this%atom(iatom)%label, (red(idim), idim=1, this%space%dim)
885 class(
ions_t),
intent(in) :: this
886 character(len=*),
optional,
intent(in) :: fname
887 character(len=*),
optional,
intent(in) :: comment
889 integer :: iatom, idim, iunit
890 character(len=:),
allocatable :: fname_, comment_
891 character(len=10) :: format_string
895 if (.not. mpi_world%is_root())
then
900 comment_ = optional_default(comment,
"")
901 fname_ = optional_default(fname,
"POSCAR")
903 iunit = io_open(trim(fname_), this%namespace, action=
'write')
905 write(iunit,
'(A)') comment_
906 write(iunit,
'("1.0")')
908 write(format_string,
'("(",I1,A,")")') this%space%dim,
'F15.10'
909 do idim=1, this%space%dim
910 write(iunit, format_string) units_from_atomic(unit_angstrom, this%latt%rlattice(:,idim))
913 do iatom = 1, this%natoms
914 write(iunit,
'(A)', advance=
'NO') trim(this%atom(iatom)%label)//
" "
917 write(iunit,
'(A)') repeat(
"1 ", this%natoms)
918 write(iunit,
'("direct")')
919 write(format_string,
'("(",I1,A,")")') this%space%dim,
'F15.10'
920 do iatom=1, this%natoms
921 write(iunit, format_string) this%latt%cart_to_red(this%pos(:, iatom))
931 class(
ions_t),
intent(inout) :: this
932 character(len=*),
intent(in) :: fname
933 character(len=*),
optional,
intent(in) :: comment
935 integer :: iatom, idir, iunit
936 character(len=19) :: frmt, dum
937 real(real64) :: tmp(this%space%dim)
941 iunit = io_open(trim(fname)//
'.xyz', this%namespace, action=
'read', position=
'rewind')
943 read(iunit,
'(i4)') this%natoms
944 if (
present(comment))
then
949 write(unit=frmt, fmt=
"(a5,i2.2,a4,i2.2,a6)")
"(6x,a", label_len,
",2x,", this%space%dim,
"f12.6)"
950 do iatom = 1, this%natoms
951 read(unit=iunit, fmt=frmt) dum, (tmp(idir), idir=1, this%space%dim)
953 this%pos(:, iatom) = units_to_atomic(units_out%length_xyz_file, tmp)
964 class(
ions_t),
intent(in) :: this
965 character(len=*),
intent(in) :: dir
967 type(lattice_iterator_t) :: latt_iter
968 real(real64) :: radius, pos(this%space%dim)
969 integer :: iatom, icopy, iunit
973 radius = maxval(m_half*norm2(this%latt%rlattice(:,1:this%space%periodic_dim), dim=1))*(m_one + m_epsilon)
974 latt_iter = lattice_iterator_t(this%latt, radius)
976 if (mpi_world%is_root())
then
978 iunit = io_open(trim(dir)//
'/crystal.xyz', this%namespace, action=
'write')
980 write(iunit,
'(i9)') this%natoms*latt_iter%n_cells
981 write(iunit,
'(a)')
'#generated by Octopus'
983 do iatom = 1, this%natoms
984 do icopy = 1, latt_iter%n_cells
985 pos = units_from_atomic(units_out%length, this%pos(:, iatom) + latt_iter%get(icopy))
986 write(iunit,
'(a, 99f12.6)') this%atom(iatom)%label, pos
998 class(
ions_t),
intent(in) :: this
999 character(len=*),
intent(in) :: dir, fname
1001 integer :: iunit, iatom, idir
1002 real(real64) :: force(this%space%dim), center(this%space%dim)
1003 character(len=20) frmt
1005 if (.not. mpi_world%is_root())
return
1009 call io_mkdir(dir, this%namespace)
1010 iunit = io_open(trim(dir)//
'/'//trim(fname)//
'.bild', this%namespace, action=
'write', &
1013 write(frmt,
'(a,i0,a)')
'(a,2(', this%space%dim,
'f16.6,1x))'
1015 write(iunit,
'(a)')
'.comment : force vectors in ['//trim(units_abbrev(units_out%force))//
']'
1017 write(iunit,
'(a)')
'.color red'
1019 do iatom = 1, this%natoms
1020 center = units_from_atomic(units_out%length, this%pos(:, iatom))
1021 force = units_from_atomic(units_out%force, this%tot_force(:, iatom))
1022 write(iunit,
'(a,1x,i4,1x,a2,1x,a6,1x,f10.6,a)')
'.comment :', iatom, trim(this%atom(iatom)%label), &
1023 'force:', norm2(force),
'['//trim(units_abbrev(units_out%force))//
']'
1024 write(iunit,fmt=trim(frmt))
'.arrow', (center(idir), idir = 1, this%space%dim), &
1025 (center(idir) + force(idir), idir = 1, this%space%dim)
1029 call io_close(iunit)
1036 class(
ions_t),
intent(in) :: this
1037 character(len=*),
intent(in) :: filename
1038 logical,
optional,
intent(in) :: ascii
1040 integer :: iunit, iatom, ierr
1042 real(real64),
allocatable :: data(:, :)
1043 integer,
allocatable :: idata(:, :)
1044 character(len=MAX_PATH_LEN) :: fullname
1048 assert(this%space%dim == 3)
1050 ascii_ = optional_default(ascii, .
true.)
1052 fullname = trim(filename)//
".vtk"
1054 iunit = io_open(trim(fullname), this%namespace, action=
'write')
1056 write(iunit,
'(1a)')
'# vtk DataFile Version 3.0 '
1057 write(iunit,
'(6a)')
'Generated by octopus ', trim(conf%version),
' - git: ', &
1058 trim(conf%git_commit),
" configuration: ", trim(conf%config_time)
1061 write(iunit,
'(1a)')
'ASCII'
1063 write(iunit,
'(1a)')
'BINARY'
1066 write(iunit,
'(1a)')
'DATASET POLYDATA'
1068 write(iunit,
'(a,i9,a)')
'POINTS ', this%natoms,
' double'
1071 do iatom = 1, this%natoms
1072 write(iunit,
'(3f12.6)') this%pos(1:3, iatom)
1075 call io_close(iunit)
1076 safe_allocate(
data(1:3, 1:this%natoms))
1077 do iatom = 1, this%natoms
1078 data(1:3, iatom) = this%pos(1:3, iatom)
1080 call io_binary_write(io_workpath(fullname, this%namespace), i4_to_i8(3*this%natoms),
data, &
1081 ierr, nohead = .
true., fendian = io_binary_is_little_endian())
1082 safe_deallocate_a(data)
1083 iunit = io_open(trim(fullname), this%namespace, action=
'write', position =
'append')
1084 write(iunit,
'(1a)')
''
1087 write(iunit,
'(a,2i9)')
'VERTICES ', this%natoms, 2*this%natoms
1090 do iatom = 1, this%natoms
1091 write(iunit,
'(2i9)') 1, iatom - 1
1094 call io_close(iunit)
1095 safe_allocate(idata(1:2, 1:this%natoms))
1096 do iatom = 1, this%natoms
1098 idata(2, iatom) = iatom - 1
1100 call io_binary_write(io_workpath(fullname, this%namespace), i4_to_i8(2*this%natoms), idata, &
1101 ierr, nohead = .
true., fendian = io_binary_is_little_endian())
1102 safe_deallocate_a(idata)
1103 iunit = io_open(trim(fullname), this%namespace, action=
'write', position =
'append')
1104 write(iunit,
'(1a)')
''
1107 write(iunit,
'(a,i9)')
'POINT_DATA', this%natoms
1108 write(iunit,
'(a)')
'SCALARS element integer'
1109 write(iunit,
'(a)')
'LOOKUP_TABLE default'
1112 do iatom = 1, this%natoms
1113 write(iunit,
'(i9)') nint(this%atom(iatom)%species%get_z())
1116 call io_close(iunit)
1118 safe_allocate(idata(1:this%natoms, 1))
1120 do iatom = 1, this%natoms
1121 idata(iatom, 1) = nint(this%atom(iatom)%species%get_z())
1124 call io_binary_write(io_workpath(fullname, this%namespace), i4_to_i8(this%natoms), idata, &
1125 ierr, nohead = .
true., fendian = io_binary_is_little_endian())
1127 safe_deallocate_a(idata)
1129 iunit = io_open(trim(fullname), this%namespace, action=
'write', position =
'append')
1130 write(iunit,
'(1a)')
''
1133 call io_close(iunit)
1140 class(
ions_t),
intent(in) :: this
1141 real(real64) :: current(this%space%dim)
1148 do iatom = this%atoms_dist%start, this%atoms_dist%end
1149 current = current + p_proton_charge*this%atom(iatom)%species%get_zval()*this%vel(:,iatom)
1152 if (this%atoms_dist%parallel)
then
1153 call comm_allreduce(this%atoms_dist%mpi_grp, current, dim=this%space%dim)
1161 class(
ions_t),
intent(in) :: this
1162 real(real64) :: abs_current(this%space%dim)
1168 abs_current = m_zero
1169 do iatom = this%atoms_dist%start, this%atoms_dist%end
1170 abs_current = abs_current + abs(p_proton_charge*this%atom(iatom)%species%get_zval()*this%vel(:,iatom))
1173 if (this%atoms_dist%parallel)
then
1174 call comm_allreduce(this%atoms_dist%mpi_grp, abs_current, dim=this%space%dim)
1182 type(
ions_t),
intent(inout) :: ions
1188 call distributed_end(ions%atoms_dist)
1190 call ion_interaction_end(ions%ion_interaction)
1192 safe_deallocate_a(ions%atom)
1195 if(
allocated(ions%species))
then
1196 do i = 1, ions%nspecies
1198 if(
associated(ions%species(i)%s))
deallocate(ions%species(i)%s)
1200 deallocate(ions%species)
1204 call charged_particles_end(ions)
1206 safe_deallocate_a(ions%map_symm_atoms)
1207 safe_deallocate_a(ions%inv_map_symm_atoms)
1217 class(
ions_t),
intent(inout) :: ions
1218 type(lattice_vectors_t),
intent(in) :: latt
1219 logical,
intent(in) :: symmetrize
1224 call ions%latt%update(latt%rlattice)
1227 if (symmetrize)
then
1228 call symmetries_update_lattice_vectors(ions%symm, latt, ions%space%dim)
1241 class(
ions_t),
intent(inout) :: ions
1243 integer :: iatom, iop, iatom_symm, dim4symms
1244 real(real64) :: ratom(ions%space%dim)
1248 safe_allocate(ions%map_symm_atoms(1:ions%natoms, 1:ions%symm%nops + ions%symm%nops_nonsymmorphic))
1249 safe_allocate(ions%inv_map_symm_atoms(1:ions%natoms, 1:ions%symm%nops + ions%symm%nops_nonsymmorphic))
1252 dim4symms = min(3, ions%space%dim)
1255 do iop = 1, ions%symm%nops
1256 do iatom = 1, ions%natoms
1258 ratom(1:dim4symms) = symm_op_apply_inv_cart(ions%symm%ops(iop), ions%pos(:, iatom))
1260 ratom(:) = ions%latt%fold_into_cell(ratom(:))
1263 do iatom_symm = 1, ions%natoms
1264 if (all(abs(ratom(:) - ions%pos(:, iatom_symm)) < symprec))
exit
1267 if (iatom_symm > ions%natoms)
then
1268 write(message(1),
'(a,i6)')
'Internal error: could not find symmetric partner for atom number', iatom
1269 write(message(2),
'(a,i3,a)')
'with symmetry operation number ', iop,
'.'
1270 call messages_fatal(2, namespace=ions%namespace)
1273 ions%map_symm_atoms(iatom, iop) = iatom_symm
1274 ions%inv_map_symm_atoms(iatom_symm, iop) = iatom
1279 do iop = 1, ions%symm%nops_nonsymmorphic
1280 do iatom = 1, ions%natoms
1282 ratom(1:dim4symms) = symm_op_apply_inv_cart(ions%symm%non_symmorphic_ops(iop), ions%pos(:, iatom))
1284 ratom(:) = ions%latt%fold_into_cell(ratom(:))
1287 do iatom_symm = 1, ions%natoms
1288 if (all(abs(ratom(:) - ions%pos(:, iatom_symm)) < symprec))
exit
1291 if (iatom_symm > ions%natoms)
then
1292 write(message(1),
'(a,i6)')
'Internal error: could not find symmetric partner for atom number', iatom
1293 write(message(2),
'(a,i3,a)')
'with symmetry operation number ', iop,
'.'
1294 call messages_fatal(2, namespace=ions%namespace)
1297 ions%map_symm_atoms(iatom, ions%symm%nops+iop) = iatom_symm
1298 ions%inv_map_symm_atoms(iatom_symm, ions%symm%nops+iop) = iatom
1313 integer :: iatom, iop, iatom_sym
1314 real(real64) :: ratom(ions%space%dim)
1315 real(real64),
allocatable :: new_pos(:,:)
1319 safe_allocate(new_pos(1:ions%space%dim, 1:ions%natoms))
1321 do iatom = 1, ions%natoms
1322 new_pos(:, iatom) = m_zero
1325 do iop = 1, ions%symm%nops
1326 iatom_sym = ions%inv_map_symm_atoms(iatom, iop)
1327 ratom = symm_op_apply_inv_cart(ions%symm%ops(iop), ions%pos(:, iatom_sym))
1328 ratom = ions%latt%fold_into_cell(ratom)
1329 new_pos(:, iatom) = new_pos(:, iatom) + ratom
1333 do iop = 1, ions%symm%nops_nonsymmorphic
1334 iatom_sym = ions%inv_map_symm_atoms(iatom, iop + ions%symm%nops)
1335 ratom = symm_op_apply_inv_cart(ions%symm%non_symmorphic_ops(iop), ions%pos(:, iatom_sym))
1336 ratom = ions%latt%fold_into_cell(ratom)
1337 new_pos(:, iatom) = new_pos(:, iatom) + ratom
1340 new_pos(:, iatom) = new_pos(:, iatom) / (ions%symm%nops + ions%symm%nops_nonsymmorphic)
1349 class(
ions_t),
intent(inout) :: ions
1351 type(spglibdataset) :: spg_dataset
1352 character(len=11) :: symbol
1353 integer,
allocatable :: site_type(:)
1354 integer :: space_group, ia
1356 if(.not. ions%space%is_periodic())
return
1360 safe_allocate(site_type(1:ions%natoms))
1361 do ia = 1, ions%natoms
1362 site_type(ia) = ions%atom(ia)%species%get_index()
1365 spg_dataset = symmetries_get_spg_dataset(ions%namespace, ions%space, ions%latt, ions%natoms, ions%pos, site_type)
1367 safe_deallocate_a(site_type)
1369 if (spg_dataset%spglib_error /= 0)
then
1374 space_group = spg_dataset%spacegroup_number
1375 symbol = spg_dataset%international_symbol
1377 write(message(1),
'(a, i4)')
'Info: Space group No. ', space_group
1378 write(message(2),
'(2a)')
'Info: International: ', trim(symbol)
1379 call messages_info(2, namespace=ions%namespace)
double acos(double __x) __attribute__((__nothrow__
double sin(double __x) __attribute__((__nothrow__
double cos(double __x) __attribute__((__nothrow__
double atan2(double __y, double __x) __attribute__((__nothrow__
double floor(double __x) __attribute__((__nothrow__
subroutine rotate(m, angle, dir)
subroutine, public atom_init(this, dim, label, species)
subroutine, public atom_get_species(this, species)
subroutine, public atom_set_species(this, species)
This module handles the calculation mode.
integer, parameter, public p_strategy_states
parallelization in states
subroutine, public charged_particles_copy(this, cp_in)
subroutine, public charged_particles_init_interaction_as_partner(partner, interaction)
subroutine, public charged_particles_update_quantity(this, label)
subroutine, public charged_particles_init_interaction(this, interaction)
subroutine, public charged_particles_copy_quantities_to_interaction(partner, interaction)
subroutine, public charged_particles_init(this, np)
The init routine is a module level procedure This has the advantage that different classes can have d...
subroutine, public distributed_nullify(this, total)
subroutine, public distributed_init(this, total, comm, tag, scalapack_compat)
Distribute N instances across M processes of communicator comm
subroutine, public distributed_copy(in, out)
@Brief Create a copy of a distributed instance
real(real64), parameter, public m_huge
character(len= *), parameter, public static_dir
real(real64), parameter, public m_half
real(real64), parameter, public m_one
This module defines the abstract interaction_t class, and some auxiliary classes for interactions.
subroutine, public io_mkdir(fname, namespace, parents)
subroutine, public ion_interaction_init_parallelization(this, natoms, mc)
subroutine, public ion_interaction_init(this, namespace, space, natoms)
subroutine ions_init_interaction(this, interaction)
subroutine ions_update_lattice_vectors(ions, latt, symmetrize)
Regenerate the ions information after update of the lattice vectors.
class(ions_t) function, pointer ions_constructor(namespace, print_info, latt_inp)
subroutine ions_fold_atoms_into_cell(this)
real(real64) function, dimension(this%space%dim) ions_global_force(this, time)
subroutine ions_copy(ions_out, ions_in)
real(real64) function, dimension(this%space%dim) ions_current(this)
subroutine ions_update_quantity(this, label)
subroutine ions_generate_mapping_symmetric_atoms(ions)
Given the symmetries of the system, we create a mapping that tell us for each atom and symmetry,...
subroutine ions_write_xyz(this, fname, append, comment, reduce_coordinates)
subroutine ions_init_species(ions, factory, print_info)
subroutine ions_finalize(ions)
subroutine ions_initialize(this)
real(real64) function, dimension(this%space%dim) ions_abs_current(this)
subroutine ions_read_xyz(this, fname, comment)
subroutine ions_write_vtk_geometry(this, filename, ascii)
subroutine ions_rotate(this, from, from2, to)
subroutine ions_translate(this, xx)
subroutine ions_symmetrize_atomic_coord(ions)
Symmetrizes atomic coordinates by applying all symmetries.
subroutine ions_print_spacegroup(ions)
Prints the spacegroup of the system for periodic systems.
real(real64) function ions_min_distance(this, real_atoms_only)
real(real64) function, dimension(this%space%dim) ions_dipole(this, mask)
subroutine ions_write_bild_forces_file(this, dir, fname)
subroutine ions_write_crystal(this, dir)
This subroutine creates a crystal by replicating the geometry and writes the result to dir.
logical function ions_has_time_dependent_species(this)
subroutine ions_partition(this, mc)
subroutine ions_init_interaction_as_partner(partner, interaction)
subroutine ions_copy_quantities_to_interaction(partner, interaction)
subroutine ions_write_poscar(this, fname, comment)
Writes the positions of the ions in POSCAR format.
real(real64) function ions_val_charge(this, mask)
This module is intended to contain "only mathematical" functions and procedures.
subroutine, public messages_print_with_emphasis(msg, iunit, namespace)
character(len=512), private msg
subroutine, public messages_warning(no_lines, all_nodes, namespace)
subroutine, public messages_obsolete_variable(namespace, name, rep)
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
subroutine, public messages_input_error(namespace, var, details, row, column)
subroutine, public messages_experimental(name, namespace)
This module handles the communicators for the various parallelization strategies.
logical function, public parse_is_defined(namespace, name)
integer, parameter, public read_coords_reduced
subroutine, public read_coords_init(gf)
integer, parameter, public xyz_flags_move
subroutine, public read_coords_end(gf)
subroutine, public read_coords_read(what, gf, space, namespace)
subroutine, public species_factory_init(factory, namespace)
subroutine, public species_factory_end(factory)
subroutine, public tdf_read(f, namespace, function_name, ierr)
This function initializes "f" from the TDFunctions block.
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
character(len=20) pure function, public units_abbrev(this)
This module defines the unit system, used for input and output.
type(unit_system_t), public units_out
abstract interaction class
surrogate interaction class to avoid circular dependencies between modules.
Stores all communicators and groups.
An abstract class for species. Derived classes include jellium, all electron, and pseudopotential spe...