35 use,
intrinsic :: iso_fortran_env
67 type(lattice_vectors_t) :: latt
70 type(atom_t),
allocatable :: atom(:)
72 type(symmetries_t) :: symm
74 type(distributed_t) :: atoms_dist
76 integer,
allocatable :: map_symm_atoms(:,:)
77 integer,
allocatable :: inv_map_symm_atoms(:,:)
81 class(species_wrapper_t),
allocatable :: species(:)
82 logical :: only_user_def
83 logical,
private :: species_time_dependent
85 logical :: force_total_enforce
86 type(ion_interaction_t) :: ion_interaction
89 logical,
private :: apply_global_force
90 type(tdf_t),
private :: global_force_function
93 generic ::
assignment(=) => copy
122 procedure ions_constructor
129 type(namespace_t),
intent(in) :: namespace
130 logical,
optional,
intent(in) :: print_info
131 type(lattice_vectors_t),
optional,
intent(out) :: latt_inp
132 class(ions_t),
pointer :: ions
134 type(read_coords_info) :: xyz
135 integer :: ia, ierr, idir
136 character(len=100) :: function_name
137 real(real64) :: mindist
138 real(real64),
allocatable :: factor(:)
139 integer,
allocatable :: site_type(:)
140 logical,
allocatable :: spherical_site(:)
141 real(real64),
parameter :: threshold = 1e-5_real64
142 type(species_factory_t) :: factory
148 ions%namespace = namespace
150 ions%space =
space_t(namespace)
161 message(1) =
"Coordinates have not been defined."
170 safe_allocate(ions%atom(1:ions%natoms))
171 do ia = 1, ions%natoms
172 call atom_init(ions%atom(ia), ions%space%dim, xyz%atom(ia)%label)
173 ions%pos(:,ia) = xyz%atom(ia)%x(1:ions%space%dim)
175 ions%fixed(ia) = .not. xyz%atom(ia)%move
179 if (
allocated(xyz%latvec))
then
189 do ia = 1, ions%natoms
190 ions%pos(:, ia) = ions%latt%red_to_cart(ions%pos(:, ia))
202 if (
present(latt_inp))
then
209 if (ions%space%has_mixed_periodicity())
then
210 safe_allocate(factor(ions%space%dim))
211 do idir = 1, ions%space%periodic_dim
214 do idir = ions%space%periodic_dim + 1, ions%space%dim
215 factor(idir) =
m_one/norm2(ions%latt%rlattice(1:ions%space%dim, idir))
217 call ions%latt%scale(factor)
218 safe_deallocate_a(factor)
222 do ia = 1, ions%natoms
223 ions%mass(ia) = ions%atom(ia)%species%get_mass()
224 ions%charge(ia) = ions%atom(ia)%species%get_zval()
228 if (ions%natoms > 1)
then
230 if (mindist < threshold)
then
231 write(
message(1),
'(a)')
"Some of the atoms seem to sit too close to each other."
232 write(
message(2),
'(a)')
"Please review your input files and the output geometry (in 'static/')."
233 write(
message(3),
'(a, f12.6, 1x, a)')
"Minimum distance = ", &
239 call ions%write_xyz(trim(
static_dir)//
'/geometry')
243 message(1) =
"It cannot be correct to run with physical atoms so close."
249 safe_allocate(spherical_site(1:ions%natoms))
250 safe_allocate(site_type(1:ions%natoms))
251 do ia = 1, ions%natoms
252 select type(spec => ions%atom(ia)%species)
254 spherical_site(ia) = .false.
256 spherical_site(ia) = .false.
258 spherical_site(ia) = .false.
260 spherical_site(ia) = .false.
262 spherical_site(ia) = .
true.
265 site_type(ia) = ions%atom(ia)%species%get_index()
268 ions%symm =
symmetries_t(ions%namespace, ions%space, ions%latt, ions%natoms, ions%pos, site_type, spherical_site)
270 safe_deallocate_a(spherical_site)
271 safe_deallocate_a(site_type)
274 call ions%generate_mapping_symmetric_atoms()
286 call parse_variable(namespace,
'ForceTotalEnforce', .false., ions%force_total_enforce)
302 ions%apply_global_force = .
true.
304 call parse_variable(namespace,
'TDGlobalForce',
'none', function_name)
305 call tdf_read(ions%global_force_function, namespace, trim(function_name), ierr)
308 call messages_write(
"You have enabled the GlobalForce option but Octopus could not find")
309 call messages_write(
"the '"//trim(function_name)//
"' function in the TDFunctions block.")
315 ions%apply_global_force = .false.
326 type(
ions_t),
intent(inout) :: ions
328 logical,
optional,
intent(in) :: print_info
330 logical :: print_info_, spec_user_defined
331 integer :: i, j, k, ispin
337 if (
present(print_info))
then
338 print_info_ = print_info
342 atoms1:
do i = 1, ions%natoms
346 ions%nspecies = ions%nspecies + 1
350 allocate(ions%species(1:ions%nspecies))
354 ions%only_user_def = .
true.
355 atoms2:
do i = 1, ions%natoms
360 ions%species(k)%s => factory%create_from_input(ions%namespace, ions%atom(j)%get_label(), k)
362 select type(spec => ions%species(k)%s)
366 ions%only_user_def = .false.
369 select type(spec => ions%species(k)%s)
371 if (ions%space%dim /= 3)
then
372 message(1) =
"Pseudopotentials may only be used with Dimensions = 3."
377 if (ions%space%is_periodic() .and. ions%space%periodic_dim /= 2)
then
378 message(1) =
"Periodic jelium slab can only be used if PeriodicDim = 2"
389 ispin = min(2, ispin)
391 if (print_info_)
then
394 do i = 1, ions%nspecies
395 spec => ions%species(i)%s
396 call spec%build(ions%namespace, ispin, ions%space%dim, print_info=print_info_)
398 if (print_info_)
then
411 call parse_variable(ions%namespace,
'SpeciesTimeDependent', .false., ions%species_time_dependent)
413 do i = 1,ions%nspecies
414 select type(spec=>ions%species(i)%s)
416 spec_user_defined = .
true.
419 if (ions%species_time_dependent .and. .not. spec_user_defined)
then
424 do i = 1, ions%natoms
425 do j = 1, ions%nspecies
438 class(
ions_t),
intent(out) :: ions_out
439 class(
ions_t),
intent(in) :: ions_in
445 ions_out%latt = ions_in%latt
447 ions_out%natoms = ions_in%natoms
448 safe_allocate(ions_out%atom(1:ions_out%natoms))
449 ions_out%atom = ions_in%atom
451 ions_out%nspecies = ions_in%nspecies
452 allocate(ions_out%species(1:ions_out%nspecies))
453 ions_out%species = ions_in%species
455 ions_out%only_user_def = ions_in%only_user_def
459 safe_allocate(ions_out%map_symm_atoms(1:ions_in%natoms, 1:ions_in%symm%nops))
460 ions_out%map_symm_atoms = ions_in%map_symm_atoms
461 safe_allocate(ions_out%inv_map_symm_atoms(1:ions_in%natoms, 1:ions_in%symm%nops))
462 ions_out%inv_map_symm_atoms = ions_in%inv_map_symm_atoms
470 class(
ions_t),
intent(inout) :: this
484 class(
ions_t),
target,
intent(inout) :: this
489 select type (interaction)
499 class(
ions_t),
intent(inout) :: this
508 class(
ions_t),
intent(inout) :: this
509 character(len=*),
intent(in) :: label
524 class(
ions_t),
intent(in) :: partner
529 select type (interaction)
539 class(
ions_t),
intent(inout) :: partner
544 select type (interaction)
555 class(
ions_t),
intent(inout) :: this
561 do iatom = 1, this%natoms
562 this%pos(:, iatom) = this%latt%fold_into_cell(this%pos(:, iatom))
569 real(real64) function ions_min_distance(this, real_atoms_only) result(rmin)
570 class(
ions_t),
intent(in) :: this
571 logical,
optional,
intent(in) :: real_atoms_only
573 integer :: iatom, jatom, idir
574 real(real64) :: xx(this%space%dim)
575 logical :: real_atoms_only_
578 if (this%natoms == 1 .and. .not. this%space%is_periodic())
then
583 push_sub(ions_min_distance)
592 do iatom = 1, this%natoms
596 if (real_atoms_only_) cycle
598 do jatom = iatom + 1, this%natoms
602 if (real_atoms_only_) cycle
604 xx = abs(this%pos(:, iatom) - this%pos(:, jatom))
605 if (this%space%is_periodic())
then
606 xx = this%latt%cart_to_red(xx)
607 do idir = 1, this%space%periodic_dim
610 xx = this%latt%red_to_cart(xx)
612 rmin = min(norm2(xx), rmin)
616 if (.not. (this%only_user_def .and. real_atoms_only_))
then
618 do idir = 1, this%space%periodic_dim
619 rmin = min(rmin, norm2(this%latt%rlattice(:,idir)))
624 if(rmin < huge(rmin)/1e6_real64)
then
625 rmin = anint(rmin*1e6_real64)*1.0e-6_real64
628 pop_sub(ions_min_distance)
637 time_dependent = this%species_time_dependent
643 real(real64) function ions_val_charge(this, mask) result(val_charge)
644 class(
ions_t),
intent(in) :: this
645 logical,
optional,
intent(in) :: mask(:)
649 if (
present(mask))
then
650 val_charge = -sum(this%charge, mask=mask)
652 val_charge = -sum(this%charge)
660 class(
ions_t),
intent(in) :: this
661 logical,
optional,
intent(in) :: mask(:)
662 real(real64) :: dipole(this%space%dim)
669 do ia = 1, this%natoms
670 if (
present(mask))
then
671 if (.not. mask(ia)) cycle
673 dipole = dipole + this%charge(ia)*this%pos(:, ia)
675 dipole = p_proton_charge*dipole
682 class(
ions_t),
intent(inout) :: this
683 real(real64),
intent(in) :: xx(this%space%dim)
689 do iatom = 1, this%natoms
690 this%pos(:, iatom) = this%pos(:, iatom) - xx
698 class(
ions_t),
intent(inout) :: this
699 real(real64),
intent(in) :: from(this%space%dim)
700 real(real64),
intent(in) :: from2(this%space%dim)
701 real(real64),
intent(in) :: to(this%space%dim)
704 real(real64) :: m1(3, 3), m2(3, 3)
705 real(real64) :: m3(3, 3), f2(3), per(3)
706 real(real64) :: alpha, r
710 if (this%space%dim /= 3)
then
711 call messages_not_implemented(
"ions_rotate in other than 3 dimensions", namespace=this%namespace)
715 m1 = diagonal_matrix(3, m_one)
718 if (abs(to(2)) > 1d-150)
then
719 alpha =
atan2(to(2), to(1))
722 alpha =
atan2(norm2(to(1:2)), to(3))
723 call rotate(m1, -alpha, 2)
726 f2 = matmul(m1, from)
738 m2 = diagonal_matrix(3, m_one)
739 alpha =
atan2(per(1), per(2))
740 call rotate(m2, -alpha, 3)
743 m3 = diagonal_matrix(3, m_one)
744 alpha =
acos(min(sum(from*to), m_one))
745 call rotate(m3, -alpha, 2)
748 m2 = matmul(transpose(m2), matmul(m3, m2))
751 per = matmul(m2, matmul(m1, from2))
752 alpha =
atan2(per(1), per(2))
753 call rotate(m2, -alpha, 3)
756 m1 = matmul(transpose(m1), matmul(m2, m1))
760 do iatom = 1, this%natoms
761 f2 = this%pos(:, iatom)
762 this%pos(:, iatom) = matmul(m1, f2)
769 subroutine rotate(m, angle, dir)
770 real(real64),
intent(inout) :: m(3, 3)
771 real(real64),
intent(in) :: angle
772 integer,
intent(in) :: dir
774 real(real64) :: aux(3, 3), ca, sa
812 class(
ions_t),
intent(in) :: this
813 real(real64),
intent(in) :: time
814 real(real64) :: force(this%space%dim)
820 if (this%apply_global_force)
then
821 force(1) = tdf(this%global_force_function, time)
828 subroutine ions_write_xyz(this, fname, append, comment, reduce_coordinates)
829 class(
ions_t),
intent(in) :: this
830 character(len=*),
intent(in) :: fname
831 logical,
optional,
intent(in) :: append
832 character(len=*),
optional,
intent(in) :: comment
833 logical,
optional,
intent(in) :: reduce_coordinates
835 integer :: iatom, idim, iunit
836 character(len=6) position
837 character(len=19) :: frmt
838 real(real64) :: red(this%space%dim)
840 if (.not. mpi_world%is_root())
return
845 if (
present(append))
then
846 if (append) position =
'append'
848 if(.not.optional_default(reduce_coordinates, .false.))
then
849 iunit = io_open(trim(fname)//
'.xyz', this%namespace, action=
'write', position=position)
851 iunit = io_open(trim(fname)//
'.xyz_red', this%namespace, action=
'write', position=position)
854 write(iunit,
'(i4)') this%natoms
855 if (
present(comment))
then
856 write(iunit,
'(1x,a)') comment
858 write(iunit,
'(1x,a,a)')
'units: ', trim(units_abbrev(units_out%length_xyz_file))
861 write(unit=frmt, fmt=
"(a5,i2.2,a4,i2.2,a6)")
"(6x,a", label_len,
",2x,", this%space%dim,
"f12.6)"
862 do iatom = 1, this%natoms
863 if(.not.optional_default(reduce_coordinates, .false.))
then
864 write(unit=iunit, fmt=frmt) this%atom(iatom)%label, &
865 (units_from_atomic(units_out%length_xyz_file, this%pos(idim, iatom)), idim=1, this%space%dim)
867 red = this%latt%cart_to_red(this%pos(:, iatom))
868 write(unit=iunit, fmt=frmt) this%atom(iatom)%label, (red(idim), idim=1, this%space%dim)
882 class(
ions_t),
intent(in) :: this
883 character(len=*),
optional,
intent(in) :: fname
884 character(len=*),
optional,
intent(in) :: comment
886 integer :: iatom, idim, iunit
887 character(len=:),
allocatable :: fname_, comment_
888 character(len=10) :: format_string
892 if (.not. mpi_world%is_root())
then
897 comment_ = optional_default(comment,
"")
898 fname_ = optional_default(fname,
"POSCAR")
900 iunit = io_open(trim(fname_), this%namespace, action=
'write')
902 write(iunit,
'(A)') comment_
903 write(iunit,
'("1.0")')
905 write(format_string,
'("(",I1,A,")")') this%space%dim,
'F15.10'
906 do idim=1, this%space%dim
907 write(iunit, format_string) units_from_atomic(unit_angstrom, this%latt%rlattice(:,idim))
910 do iatom = 1, this%natoms
911 write(iunit,
'(A)', advance=
'NO') trim(this%atom(iatom)%label)//
" "
914 write(iunit,
'(A)') repeat(
"1 ", this%natoms)
915 write(iunit,
'("direct")')
916 write(format_string,
'("(",I1,A,")")') this%space%dim,
'F15.10'
917 do iatom=1, this%natoms
918 write(iunit, format_string) this%latt%cart_to_red(this%pos(:, iatom))
928 class(
ions_t),
intent(inout) :: this
929 character(len=*),
intent(in) :: fname
930 character(len=*),
optional,
intent(in) :: comment
932 integer :: iatom, idir, iunit
933 character(len=19) :: frmt, dum
934 real(real64) :: tmp(this%space%dim)
938 iunit = io_open(trim(fname)//
'.xyz', this%namespace, action=
'read', position=
'rewind')
940 read(iunit,
'(i4)') this%natoms
941 if (
present(comment))
then
946 write(unit=frmt, fmt=
"(a5,i2.2,a4,i2.2,a6)")
"(6x,a", label_len,
",2x,", this%space%dim,
"f12.6)"
947 do iatom = 1, this%natoms
948 read(unit=iunit, fmt=frmt) dum, (tmp(idir), idir=1, this%space%dim)
950 this%pos(:, iatom) = units_to_atomic(units_out%length_xyz_file, tmp)
961 class(
ions_t),
intent(in) :: this
962 character(len=*),
intent(in) :: dir
964 type(lattice_iterator_t) :: latt_iter
965 real(real64) :: radius, pos(this%space%dim)
966 integer :: iatom, icopy, iunit
970 radius = maxval(m_half*norm2(this%latt%rlattice(:,1:this%space%periodic_dim), dim=1))*(m_one + m_epsilon)
971 latt_iter = lattice_iterator_t(this%latt, radius)
973 if (mpi_world%is_root())
then
975 iunit = io_open(trim(dir)//
'/crystal.xyz', this%namespace, action=
'write')
977 write(iunit,
'(i9)') this%natoms*latt_iter%n_cells
978 write(iunit,
'(a)')
'#generated by Octopus'
980 do iatom = 1, this%natoms
981 do icopy = 1, latt_iter%n_cells
982 pos = units_from_atomic(units_out%length, this%pos(:, iatom) + latt_iter%get(icopy))
983 write(iunit,
'(a, 99f12.6)') this%atom(iatom)%label, pos
995 class(
ions_t),
intent(in) :: this
996 character(len=*),
intent(in) :: dir, fname
998 integer :: iunit, iatom, idir
999 real(real64) :: force(this%space%dim), center(this%space%dim)
1000 character(len=20) frmt
1002 if (.not. mpi_world%is_root())
return
1006 call io_mkdir(dir, this%namespace)
1007 iunit = io_open(trim(dir)//
'/'//trim(fname)//
'.bild', this%namespace, action=
'write', &
1010 write(frmt,
'(a,i0,a)')
'(a,2(', this%space%dim,
'f16.6,1x))'
1012 write(iunit,
'(a)')
'.comment : force vectors in ['//trim(units_abbrev(units_out%force))//
']'
1014 write(iunit,
'(a)')
'.color red'
1016 do iatom = 1, this%natoms
1017 center = units_from_atomic(units_out%length, this%pos(:, iatom))
1018 force = units_from_atomic(units_out%force, this%tot_force(:, iatom))
1019 write(iunit,
'(a,1x,i4,1x,a2,1x,a6,1x,f10.6,a)')
'.comment :', iatom, trim(this%atom(iatom)%label), &
1020 'force:', norm2(force),
'['//trim(units_abbrev(units_out%force))//
']'
1021 write(iunit,fmt=trim(frmt))
'.arrow', (center(idir), idir = 1, this%space%dim), &
1022 (center(idir) + force(idir), idir = 1, this%space%dim)
1026 call io_close(iunit)
1033 class(
ions_t),
intent(in) :: this
1034 character(len=*),
intent(in) :: filename
1035 logical,
optional,
intent(in) :: ascii
1037 integer :: iunit, iatom, ierr
1039 real(real64),
allocatable :: data(:, :)
1040 integer,
allocatable :: idata(:, :)
1041 character(len=MAX_PATH_LEN) :: fullname
1045 assert(this%space%dim == 3)
1047 ascii_ = optional_default(ascii, .
true.)
1049 fullname = trim(filename)//
".vtk"
1051 iunit = io_open(trim(fullname), this%namespace, action=
'write')
1053 write(iunit,
'(1a)')
'# vtk DataFile Version 3.0 '
1054 write(iunit,
'(6a)')
'Generated by octopus ', trim(conf%version),
' - git: ', &
1055 trim(conf%git_commit),
" configuration: ", trim(conf%config_time)
1058 write(iunit,
'(1a)')
'ASCII'
1060 write(iunit,
'(1a)')
'BINARY'
1063 write(iunit,
'(1a)')
'DATASET POLYDATA'
1065 write(iunit,
'(a,i9,a)')
'POINTS ', this%natoms,
' double'
1068 do iatom = 1, this%natoms
1069 write(iunit,
'(3f12.6)') this%pos(1:3, iatom)
1072 call io_close(iunit)
1073 safe_allocate(
data(1:3, 1:this%natoms))
1074 do iatom = 1, this%natoms
1075 data(1:3, iatom) = this%pos(1:3, iatom)
1077 call io_binary_write(io_workpath(fullname, this%namespace), i4_to_i8(3*this%natoms),
data, &
1078 ierr, nohead = .
true., fendian = io_binary_is_little_endian())
1079 safe_deallocate_a(data)
1080 iunit = io_open(trim(fullname), this%namespace, action=
'write', position =
'append')
1081 write(iunit,
'(1a)')
''
1084 write(iunit,
'(a,2i9)')
'VERTICES ', this%natoms, 2*this%natoms
1087 do iatom = 1, this%natoms
1088 write(iunit,
'(2i9)') 1, iatom - 1
1091 call io_close(iunit)
1092 safe_allocate(idata(1:2, 1:this%natoms))
1093 do iatom = 1, this%natoms
1095 idata(2, iatom) = iatom - 1
1097 call io_binary_write(io_workpath(fullname, this%namespace), i4_to_i8(2*this%natoms), idata, &
1098 ierr, nohead = .
true., fendian = io_binary_is_little_endian())
1099 safe_deallocate_a(idata)
1100 iunit = io_open(trim(fullname), this%namespace, action=
'write', position =
'append')
1101 write(iunit,
'(1a)')
''
1104 write(iunit,
'(a,i9)')
'POINT_DATA', this%natoms
1105 write(iunit,
'(a)')
'SCALARS element integer'
1106 write(iunit,
'(a)')
'LOOKUP_TABLE default'
1109 do iatom = 1, this%natoms
1110 write(iunit,
'(i9)') nint(this%atom(iatom)%species%get_z())
1113 call io_close(iunit)
1115 safe_allocate(idata(1:this%natoms, 1))
1117 do iatom = 1, this%natoms
1118 idata(iatom, 1) = nint(this%atom(iatom)%species%get_z())
1121 call io_binary_write(io_workpath(fullname, this%namespace), i4_to_i8(this%natoms), idata, &
1122 ierr, nohead = .
true., fendian = io_binary_is_little_endian())
1124 safe_deallocate_a(idata)
1126 iunit = io_open(trim(fullname), this%namespace, action=
'write', position =
'append')
1127 write(iunit,
'(1a)')
''
1130 call io_close(iunit)
1137 type(
ions_t),
intent(inout) :: ions
1143 call distributed_end(ions%atoms_dist)
1145 call ion_interaction_end(ions%ion_interaction)
1147 safe_deallocate_a(ions%atom)
1150 if(
allocated(ions%species))
then
1151 do i = 1, ions%nspecies
1153 if(
associated(ions%species(i)%s))
deallocate(ions%species(i)%s)
1155 deallocate(ions%species)
1159 call charged_particles_end(ions)
1161 safe_deallocate_a(ions%map_symm_atoms)
1162 safe_deallocate_a(ions%inv_map_symm_atoms)
1172 class(
ions_t),
intent(inout) :: ions
1173 type(lattice_vectors_t),
intent(in) :: latt
1174 logical,
intent(in) :: symmetrize
1179 call ions%latt%update(latt%rlattice)
1182 if (symmetrize)
then
1183 call symmetries_update_lattice_vectors(ions%symm, latt, ions%space%dim)
1196 class(
ions_t),
intent(inout) :: ions
1198 integer :: iatom, iop, iatom_symm, dim4symms
1199 real(real64) :: ratom(ions%space%dim)
1203 safe_allocate(ions%map_symm_atoms(1:ions%natoms, 1:ions%symm%nops + ions%symm%nops_nonsymmorphic))
1204 safe_allocate(ions%inv_map_symm_atoms(1:ions%natoms, 1:ions%symm%nops + ions%symm%nops_nonsymmorphic))
1207 dim4symms = min(3, ions%space%dim)
1210 do iop = 1, ions%symm%nops
1211 do iatom = 1, ions%natoms
1213 ratom(1:dim4symms) = symm_op_apply_inv_cart(ions%symm%ops(iop), ions%pos(:, iatom))
1215 ratom(:) = ions%latt%fold_into_cell(ratom(:))
1218 do iatom_symm = 1, ions%natoms
1219 if (all(abs(ratom(:) - ions%pos(:, iatom_symm)) < symprec))
exit
1222 if (iatom_symm > ions%natoms)
then
1223 write(message(1),
'(a,i6)')
'Internal error: could not find symmetric partner for atom number', iatom
1224 write(message(2),
'(a,i3,a)')
'with symmetry operation number ', iop,
'.'
1225 call messages_fatal(2, namespace=ions%namespace)
1228 ions%map_symm_atoms(iatom, iop) = iatom_symm
1229 ions%inv_map_symm_atoms(iatom_symm, iop) = iatom
1234 do iop = 1, ions%symm%nops_nonsymmorphic
1235 do iatom = 1, ions%natoms
1237 ratom(1:dim4symms) = symm_op_apply_inv_cart(ions%symm%non_symmorphic_ops(iop), ions%pos(:, iatom))
1239 ratom(:) = ions%latt%fold_into_cell(ratom(:))
1242 do iatom_symm = 1, ions%natoms
1243 if (all(abs(ratom(:) - ions%pos(:, iatom_symm)) < symprec))
exit
1246 if (iatom_symm > ions%natoms)
then
1247 write(message(1),
'(a,i6)')
'Internal error: could not find symmetric partner for atom number', iatom
1248 write(message(2),
'(a,i3,a)')
'with symmetry operation number ', iop,
'.'
1249 call messages_fatal(2, namespace=ions%namespace)
1252 ions%map_symm_atoms(iatom, ions%symm%nops+iop) = iatom_symm
1253 ions%inv_map_symm_atoms(iatom_symm, ions%symm%nops+iop) = iatom
1268 integer :: iatom, iop, iatom_sym
1269 real(real64) :: ratom(ions%space%dim)
1270 real(real64),
allocatable :: new_pos(:,:)
1274 safe_allocate(new_pos(1:ions%space%dim, 1:ions%natoms))
1276 do iatom = 1, ions%natoms
1277 new_pos(:, iatom) = m_zero
1280 do iop = 1, ions%symm%nops
1281 iatom_sym = ions%inv_map_symm_atoms(iatom, iop)
1282 ratom = symm_op_apply_inv_cart(ions%symm%ops(iop), ions%pos(:, iatom_sym))
1283 ratom = ions%latt%fold_into_cell(ratom)
1284 new_pos(:, iatom) = new_pos(:, iatom) + ratom
1288 do iop = 1, ions%symm%nops_nonsymmorphic
1289 iatom_sym = ions%inv_map_symm_atoms(iatom, iop + ions%symm%nops)
1290 ratom = symm_op_apply_inv_cart(ions%symm%non_symmorphic_ops(iop), ions%pos(:, iatom_sym))
1291 ratom = ions%latt%fold_into_cell(ratom)
1292 new_pos(:, iatom) = new_pos(:, iatom) + ratom
1295 new_pos(:, iatom) = new_pos(:, iatom) / (ions%symm%nops + ions%symm%nops_nonsymmorphic)
1304 class(
ions_t),
intent(inout) :: ions
1306 type(spglibdataset) :: spg_dataset
1307 character(len=11) :: symbol
1308 integer,
allocatable :: site_type(:)
1309 integer :: space_group, ia
1311 if(.not. ions%space%is_periodic())
return
1315 safe_allocate(site_type(1:ions%natoms))
1316 do ia = 1, ions%natoms
1317 site_type(ia) = ions%atom(ia)%species%get_index()
1320 spg_dataset = symmetries_get_spg_dataset(ions%namespace, ions%space, ions%latt, ions%natoms, ions%pos, site_type)
1322 safe_deallocate_a(site_type)
1324 if (spg_dataset%spglib_error /= 0)
then
1329 space_group = spg_dataset%spacegroup_number
1330 symbol = spg_dataset%international_symbol
1332 write(message(1),
'(a, i4)')
'Info: Space group No. ', space_group
1333 write(message(2),
'(2a)')
'Info: International: ', trim(symbol)
1334 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)
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)
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...