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,
"f15.9)"
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 use iso_fortran_env,
only: real64
932 class(
ions_t),
intent(inout) :: this
933 character(len=*),
intent(in) :: fname
934 character(len=*),
optional,
intent(in) :: comment
936 integer :: iatom, idir, iunit, ios
937 character(len=256) :: line
938 character(len=LABEL_LEN) :: label
939 character(len=:),
allocatable :: coordstr
940 real(real64) :: tmp(this%space%dim)
944 iunit = io_open(trim(fname)//
'.xyz', this%namespace, action=
'read', position=
'rewind')
947 read(iunit,
'(i4)') this%natoms
948 if (
present(comment))
then
955 do iatom = 1, this%natoms
958 read(iunit,
'(A)', iostat=ios) line
961 message(1) =
"Error reading XYZ atom line"
962 call messages_fatal(1, namespace=this%namespace)
966 if (len_trim(line) < label_len)
then
968 message(1) =
"XYZ file: atom line too short for label"
969 call messages_fatal(1, namespace=this%namespace)
971 label = line(1:label_len)
974 if (len(line) > label_len)
then
975 coordstr = adjustl(line(label_len+1:))
978 message(1) =
"XYZ file: no coordinate data after label"
979 call messages_fatal(1, namespace=this%namespace)
983 read(coordstr, *, iostat=ios) (tmp(idir), idir=1, this%space%dim)
986 message(1) =
"XYZ file: malformed coordinate fields"
987 call messages_fatal(1, namespace=this%namespace)
991 this%pos(:, iatom) = units_to_atomic(units_out%length_xyz_file, tmp)
1004 class(
ions_t),
intent(in) :: this
1005 character(len=*),
intent(in) :: dir
1007 type(lattice_iterator_t) :: latt_iter
1008 real(real64) :: radius, pos(this%space%dim)
1009 integer :: iatom, icopy, iunit
1013 radius = maxval(m_half*norm2(this%latt%rlattice(:,1:this%space%periodic_dim), dim=1))*(m_one + m_epsilon)
1014 latt_iter = lattice_iterator_t(this%latt, radius)
1016 if (mpi_world%is_root())
then
1018 iunit = io_open(trim(dir)//
'/crystal.xyz', this%namespace, action=
'write')
1020 write(iunit,
'(i9)') this%natoms*latt_iter%n_cells
1021 write(iunit,
'(a)')
'#generated by Octopus'
1023 do iatom = 1, this%natoms
1024 do icopy = 1, latt_iter%n_cells
1025 pos = units_from_atomic(units_out%length, this%pos(:, iatom) + latt_iter%get(icopy))
1026 write(iunit,
'(a, 99f12.6)') this%atom(iatom)%label, pos
1030 call io_close(iunit)
1038 class(
ions_t),
intent(in) :: this
1039 character(len=*),
intent(in) :: dir, fname
1041 integer :: iunit, iatom, idir
1042 real(real64) :: force(this%space%dim), center(this%space%dim)
1043 character(len=20) frmt
1045 if (.not. mpi_world%is_root())
return
1049 call io_mkdir(dir, this%namespace)
1050 iunit = io_open(trim(dir)//
'/'//trim(fname)//
'.bild', this%namespace, action=
'write', &
1053 write(frmt,
'(a,i0,a)')
'(a,2(', this%space%dim,
'f16.6,1x))'
1055 write(iunit,
'(a)')
'.comment : force vectors in ['//trim(units_abbrev(units_out%force))//
']'
1057 write(iunit,
'(a)')
'.color red'
1059 do iatom = 1, this%natoms
1060 center = units_from_atomic(units_out%length, this%pos(:, iatom))
1061 force = units_from_atomic(units_out%force, this%tot_force(:, iatom))
1062 write(iunit,
'(a,1x,i4,1x,a2,1x,a6,1x,f10.6,a)')
'.comment :', iatom, trim(this%atom(iatom)%label), &
1063 'force:', norm2(force),
'['//trim(units_abbrev(units_out%force))//
']'
1064 write(iunit,fmt=trim(frmt))
'.arrow', (center(idir), idir = 1, this%space%dim), &
1065 (center(idir) + force(idir), idir = 1, this%space%dim)
1069 call io_close(iunit)
1076 class(
ions_t),
intent(in) :: this
1077 character(len=*),
intent(in) :: filename
1078 logical,
optional,
intent(in) :: ascii
1080 integer :: iunit, iatom, ierr
1082 real(real64),
allocatable :: data(:, :)
1083 integer,
allocatable :: idata(:, :)
1084 character(len=MAX_PATH_LEN) :: fullname
1088 assert(this%space%dim == 3)
1090 ascii_ = optional_default(ascii, .
true.)
1092 fullname = trim(filename)//
".vtk"
1094 iunit = io_open(trim(fullname), this%namespace, action=
'write')
1096 write(iunit,
'(1a)')
'# vtk DataFile Version 3.0 '
1097 write(iunit,
'(6a)')
'Generated by octopus ', trim(conf%version),
' - git: ', &
1098 trim(conf%git_commit),
" configuration: ", trim(conf%config_time)
1101 write(iunit,
'(1a)')
'ASCII'
1103 write(iunit,
'(1a)')
'BINARY'
1106 write(iunit,
'(1a)')
'DATASET POLYDATA'
1108 write(iunit,
'(a,i9,a)')
'POINTS ', this%natoms,
' double'
1111 do iatom = 1, this%natoms
1112 write(iunit,
'(3f12.6)') this%pos(1:3, iatom)
1115 call io_close(iunit)
1116 safe_allocate(
data(1:3, 1:this%natoms))
1117 do iatom = 1, this%natoms
1118 data(1:3, iatom) = this%pos(1:3, iatom)
1120 call io_binary_write(io_workpath(fullname, this%namespace), i4_to_i8(3*this%natoms),
data, &
1121 ierr, nohead = .
true., fendian = io_binary_is_little_endian())
1122 safe_deallocate_a(data)
1123 iunit = io_open(trim(fullname), this%namespace, action=
'write', position =
'append')
1124 write(iunit,
'(1a)')
''
1127 write(iunit,
'(a,2i9)')
'VERTICES ', this%natoms, 2*this%natoms
1130 do iatom = 1, this%natoms
1131 write(iunit,
'(2i9)') 1, iatom - 1
1134 call io_close(iunit)
1135 safe_allocate(idata(1:2, 1:this%natoms))
1136 do iatom = 1, this%natoms
1138 idata(2, iatom) = iatom - 1
1140 call io_binary_write(io_workpath(fullname, this%namespace), i4_to_i8(2*this%natoms), idata, &
1141 ierr, nohead = .
true., fendian = io_binary_is_little_endian())
1142 safe_deallocate_a(idata)
1143 iunit = io_open(trim(fullname), this%namespace, action=
'write', position =
'append')
1144 write(iunit,
'(1a)')
''
1147 write(iunit,
'(a,i9)')
'POINT_DATA', this%natoms
1148 write(iunit,
'(a)')
'SCALARS element integer'
1149 write(iunit,
'(a)')
'LOOKUP_TABLE default'
1152 do iatom = 1, this%natoms
1153 write(iunit,
'(i9)') nint(this%atom(iatom)%species%get_z())
1156 call io_close(iunit)
1158 safe_allocate(idata(1:this%natoms, 1))
1160 do iatom = 1, this%natoms
1161 idata(iatom, 1) = nint(this%atom(iatom)%species%get_z())
1164 call io_binary_write(io_workpath(fullname, this%namespace), i4_to_i8(this%natoms), idata, &
1165 ierr, nohead = .
true., fendian = io_binary_is_little_endian())
1167 safe_deallocate_a(idata)
1169 iunit = io_open(trim(fullname), this%namespace, action=
'write', position =
'append')
1170 write(iunit,
'(1a)')
''
1173 call io_close(iunit)
1180 class(
ions_t),
intent(in) :: this
1181 real(real64) :: current(this%space%dim)
1188 do iatom = this%atoms_dist%start, this%atoms_dist%end
1189 current = current + p_proton_charge*this%atom(iatom)%species%get_zval()*this%vel(:,iatom)
1192 if (this%atoms_dist%parallel)
then
1193 call comm_allreduce(this%atoms_dist%mpi_grp, current, dim=this%space%dim)
1201 class(
ions_t),
intent(in) :: this
1202 real(real64) :: abs_current(this%space%dim)
1208 abs_current = m_zero
1209 do iatom = this%atoms_dist%start, this%atoms_dist%end
1210 abs_current = abs_current + abs(p_proton_charge*this%atom(iatom)%species%get_zval()*this%vel(:,iatom))
1213 if (this%atoms_dist%parallel)
then
1214 call comm_allreduce(this%atoms_dist%mpi_grp, abs_current, dim=this%space%dim)
1222 type(
ions_t),
intent(inout) :: ions
1228 call distributed_end(ions%atoms_dist)
1230 call ion_interaction_end(ions%ion_interaction)
1232 safe_deallocate_a(ions%atom)
1235 if(
allocated(ions%species))
then
1236 do i = 1, ions%nspecies
1238 if(
associated(ions%species(i)%s))
deallocate(ions%species(i)%s)
1240 deallocate(ions%species)
1244 call charged_particles_end(ions)
1246 safe_deallocate_a(ions%map_symm_atoms)
1247 safe_deallocate_a(ions%inv_map_symm_atoms)
1257 class(
ions_t),
intent(inout) :: ions
1258 type(lattice_vectors_t),
intent(in) :: latt
1259 logical,
intent(in) :: symmetrize
1264 call ions%latt%update(latt%rlattice)
1267 if (symmetrize)
then
1268 call symmetries_update_lattice_vectors(ions%symm, latt, ions%space%dim)
1281 class(
ions_t),
intent(inout) :: ions
1283 integer :: iatom, iop, iatom_symm, dim4symms
1284 real(real64) :: ratom(ions%space%dim)
1288 safe_allocate(ions%map_symm_atoms(1:ions%natoms, 1:ions%symm%nops + ions%symm%nops_nonsymmorphic))
1289 safe_allocate(ions%inv_map_symm_atoms(1:ions%natoms, 1:ions%symm%nops + ions%symm%nops_nonsymmorphic))
1292 dim4symms = min(3, ions%space%dim)
1295 do iop = 1, ions%symm%nops
1296 do iatom = 1, ions%natoms
1298 ratom(1:dim4symms) = symm_op_apply_inv_cart(ions%symm%ops(iop), ions%pos(:, iatom))
1300 ratom(:) = ions%latt%fold_into_cell(ratom(:))
1303 do iatom_symm = 1, ions%natoms
1304 if (all(abs(ratom(:) - ions%pos(:, iatom_symm)) < symprec))
exit
1307 if (iatom_symm > ions%natoms)
then
1308 write(message(1),
'(a,i6)')
'Internal error: could not find symmetric partner for atom number', iatom
1309 write(message(2),
'(a,i3,a)')
'with symmetry operation number ', iop,
'.'
1310 call messages_fatal(2, namespace=ions%namespace)
1313 ions%map_symm_atoms(iatom, iop) = iatom_symm
1314 ions%inv_map_symm_atoms(iatom_symm, iop) = iatom
1319 do iop = 1, ions%symm%nops_nonsymmorphic
1320 do iatom = 1, ions%natoms
1322 ratom(1:dim4symms) = symm_op_apply_inv_cart(ions%symm%non_symmorphic_ops(iop), ions%pos(:, iatom))
1324 ratom(:) = ions%latt%fold_into_cell(ratom(:))
1327 do iatom_symm = 1, ions%natoms
1328 if (all(abs(ratom(:) - ions%pos(:, iatom_symm)) < symprec))
exit
1331 if (iatom_symm > ions%natoms)
then
1332 write(message(1),
'(a,i6)')
'Internal error: could not find symmetric partner for atom number', iatom
1333 write(message(2),
'(a,i3,a)')
'with symmetry operation number ', iop,
'.'
1334 call messages_fatal(2, namespace=ions%namespace)
1337 ions%map_symm_atoms(iatom, ions%symm%nops+iop) = iatom_symm
1338 ions%inv_map_symm_atoms(iatom_symm, ions%symm%nops+iop) = iatom
1353 integer :: iatom, iop, iatom_sym
1354 real(real64) :: ratom(ions%space%dim)
1355 real(real64),
allocatable :: new_pos(:,:)
1359 safe_allocate(new_pos(1:ions%space%dim, 1:ions%natoms))
1361 do iatom = 1, ions%natoms
1362 new_pos(:, iatom) = m_zero
1365 do iop = 1, ions%symm%nops
1366 iatom_sym = ions%inv_map_symm_atoms(iatom, iop)
1367 ratom = symm_op_apply_inv_cart(ions%symm%ops(iop), ions%pos(:, iatom_sym))
1368 ratom = ions%latt%fold_into_cell(ratom)
1369 new_pos(:, iatom) = new_pos(:, iatom) + ratom
1373 do iop = 1, ions%symm%nops_nonsymmorphic
1374 iatom_sym = ions%inv_map_symm_atoms(iatom, iop + ions%symm%nops)
1375 ratom = symm_op_apply_inv_cart(ions%symm%non_symmorphic_ops(iop), ions%pos(:, iatom_sym))
1376 ratom = ions%latt%fold_into_cell(ratom)
1377 new_pos(:, iatom) = new_pos(:, iatom) + ratom
1380 new_pos(:, iatom) = new_pos(:, iatom) / (ions%symm%nops + ions%symm%nops_nonsymmorphic)
1389 class(
ions_t),
intent(inout) :: ions
1391 type(spglibdataset) :: spg_dataset
1392 character(len=11) :: symbol
1393 integer,
allocatable :: site_type(:)
1394 integer :: space_group, ia
1396 if(.not. ions%space%is_periodic())
return
1400 safe_allocate(site_type(1:ions%natoms))
1401 do ia = 1, ions%natoms
1402 site_type(ia) = ions%atom(ia)%species%get_index()
1405 spg_dataset = symmetries_get_spg_dataset(ions%namespace, ions%space, ions%latt, ions%natoms, ions%pos, site_type)
1407 safe_deallocate_a(site_type)
1409 if (spg_dataset%spglib_error /= 0)
then
1414 space_group = spg_dataset%spacegroup_number
1415 symbol = spg_dataset%international_symbol
1417 write(message(1),
'(a, i4)')
'Info: Space group No. ', space_group
1418 write(message(2),
'(2a)')
'Info: International: ', trim(symbol)
1419 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...