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)
588 do iatom = 1, this%natoms
592 if (real_atoms_only_) cycle
594 do jatom = iatom + 1, this%natoms
598 if (real_atoms_only_) cycle
600 xx = abs(this%pos(:, iatom) - this%pos(:, jatom))
601 if (this%space%is_periodic())
then
602 xx = this%latt%cart_to_red(xx)
603 do idir = 1, this%space%periodic_dim
606 xx = this%latt%red_to_cart(xx)
608 rmin = min(norm2(xx), rmin)
612 if (.not. (this%only_user_def .and. real_atoms_only_))
then
614 do idir = 1, this%space%periodic_dim
615 rmin = min(rmin, norm2(this%latt%rlattice(:,idir)))
620 if(rmin < huge(rmin)/1e6_real64)
then
621 rmin = anint(rmin*1e6_real64)*1.0e-6_real64
624 pop_sub(ions_min_distance)
629 class(
ions_t),
intent(in) :: this
633 time_dependent = this%species_time_dependent
639 real(real64) function ions_val_charge(this, mask) result(val_charge)
640 class(
ions_t),
intent(in) :: this
641 logical,
optional,
intent(in) :: mask(:)
645 if (
present(mask))
then
646 val_charge = -sum(this%charge, mask=mask)
648 val_charge = -sum(this%charge)
656 class(
ions_t),
intent(in) :: this
657 logical,
optional,
intent(in) :: mask(:)
658 real(real64) :: dipole(this%space%dim)
665 do ia = 1, this%natoms
666 if (
present(mask))
then
667 if (.not. mask(ia)) cycle
669 dipole = dipole + this%charge(ia)*this%pos(:, ia)
671 dipole = p_proton_charge*dipole
678 class(
ions_t),
intent(inout) :: this
679 real(real64),
intent(in) :: xx(this%space%dim)
685 do iatom = 1, this%natoms
686 this%pos(:, iatom) = this%pos(:, iatom) - xx
694 class(
ions_t),
intent(inout) :: this
695 real(real64),
intent(in) :: from(this%space%dim)
696 real(real64),
intent(in) :: from2(this%space%dim)
697 real(real64),
intent(in) :: to(this%space%dim)
700 real(real64) :: m1(3, 3), m2(3, 3)
701 real(real64) :: m3(3, 3), f2(3), per(3)
702 real(real64) :: alpha, r
706 if (this%space%dim /= 3)
then
707 call messages_not_implemented(
"ions_rotate in other than 3 dimensions", namespace=this%namespace)
711 m1 = diagonal_matrix(3, m_one)
714 if (abs(to(2)) > 1d-150)
then
715 alpha =
atan2(to(2), to(1))
718 alpha =
atan2(norm2(to(1:2)), to(3))
719 call rotate(m1, -alpha, 2)
722 f2 = matmul(m1, from)
734 m2 = diagonal_matrix(3, m_one)
735 alpha =
atan2(per(1), per(2))
736 call rotate(m2, -alpha, 3)
739 m3 = diagonal_matrix(3, m_one)
740 alpha =
acos(min(sum(from*to), m_one))
741 call rotate(m3, -alpha, 2)
744 m2 = matmul(transpose(m2), matmul(m3, m2))
747 per = matmul(m2, matmul(m1, from2))
749 call rotate(m2, -alpha, 3)
752 m1 = matmul(transpose(m1), matmul(m2, m1))
756 do iatom = 1, this%natoms
757 f2 = this%pos(:, iatom)
758 this%pos(:, iatom) = matmul(m1, f2)
765 subroutine rotate(m, angle, dir)
766 real(real64),
intent(inout) :: m(3, 3)
767 real(real64),
intent(in) :: angle
768 integer,
intent(in) :: dir
770 real(real64) :: aux(3, 3), ca, sa
808 class(
ions_t),
intent(in) :: this
809 real(real64),
intent(in) :: time
810 real(real64) :: force(this%space%dim)
816 if (this%apply_global_force)
then
817 force(1) = units_to_atomic(units_inp%force, tdf(this%global_force_function, time))
824 subroutine ions_write_xyz(this, fname, append, comment, reduce_coordinates)
825 class(
ions_t),
intent(in) :: this
826 character(len=*),
intent(in) :: fname
827 logical,
optional,
intent(in) :: append
828 character(len=*),
optional,
intent(in) :: comment
829 logical,
optional,
intent(in) :: reduce_coordinates
831 integer :: iatom, idim, iunit
832 character(len=6) position
833 character(len=19) :: frmt
834 real(real64) :: red(this%space%dim)
836 if (.not. mpi_grp_is_root(mpi_world))
return
841 if (
present(append))
then
842 if (append) position =
'append'
844 if(.not.optional_default(reduce_coordinates, .false.))
then
845 iunit = io_open(trim(fname)//
'.xyz', this%namespace, action=
'write', position=position)
847 iunit = io_open(trim(fname)//
'.xyz_red', this%namespace, action=
'write', position=position)
850 write(iunit,
'(i4)') this%natoms
851 if (
present(comment))
then
852 write(iunit,
'(1x,a)') comment
854 write(iunit,
'(1x,a,a)')
'units: ', trim(units_abbrev(units_out%length_xyz_file))
857 write(unit=frmt, fmt=
"(a5,i2.2,a4,i2.2,a6)")
"(6x,a", label_len,
",2x,", this%space%dim,
"f12.6)"
858 do iatom = 1, this%natoms
859 if(.not.optional_default(reduce_coordinates, .false.))
then
860 write(unit=iunit, fmt=frmt) this%atom(iatom)%label, &
861 (units_from_atomic(units_out%length_xyz_file, this%pos(idim, iatom)), idim=1, this%space%dim)
863 red = this%latt%cart_to_red(this%pos(:, iatom))
864 write(unit=iunit, fmt=frmt) this%atom(iatom)%label, (red(idim), idim=1, this%space%dim)
878 class(
ions_t),
intent(in) :: this
879 character(len=*),
optional,
intent(in) :: fname
880 character(len=*),
optional,
intent(in) :: comment
882 integer :: iatom, idim, iunit
883 character(len=:),
allocatable :: fname_, comment_
884 character(len=10) :: format_string
888 if (.not. mpi_grp_is_root(mpi_world))
then
893 comment_ = optional_default(comment,
"")
894 fname_ = optional_default(fname,
"POSCAR")
896 iunit = io_open(trim(fname_), this%namespace, action=
'write')
898 write(iunit,
'(A)') comment_
899 write(iunit,
'("1.0")')
901 write(format_string,
'("(",I1,A,")")') this%space%dim,
'F15.10'
902 do idim=1, this%space%dim
903 write(iunit, format_string) units_from_atomic(unit_angstrom, this%latt%rlattice(:,idim))
906 do iatom = 1, this%natoms
907 write(iunit,
'(A)', advance=
'NO') trim(this%atom(iatom)%label)//
" "
910 write(iunit,
'(A)') repeat(
"1 ", this%natoms)
911 write(iunit,
'("direct")')
912 write(format_string,
'("(",I1,A,")")') this%space%dim,
'F15.10'
913 do iatom=1, this%natoms
914 write(iunit, format_string) this%latt%cart_to_red(this%pos(:, iatom))
924 class(
ions_t),
intent(inout) :: this
925 character(len=*),
intent(in) :: fname
926 character(len=*),
optional,
intent(in) :: comment
928 integer :: iatom, idir, iunit
929 character(len=19) :: frmt, dum
930 real(real64) :: tmp(this%space%dim)
934 iunit = io_open(trim(fname)//
'.xyz', this%namespace, action=
'read', position=
'rewind')
936 read(iunit,
'(i4)') this%natoms
937 if (
present(comment))
then
942 write(unit=frmt, fmt=
"(a5,i2.2,a4,i2.2,a6)")
"(6x,a", label_len,
",2x,", this%space%dim,
"f12.6)"
943 do iatom = 1, this%natoms
944 read(unit=iunit, fmt=frmt) dum, (tmp(idir), idir=1, this%space%dim)
946 this%pos(:, iatom) = units_to_atomic(units_out%length_xyz_file, tmp)
957 class(
ions_t),
intent(in) :: this
958 character(len=*),
intent(in) :: dir
960 type(lattice_iterator_t) :: latt_iter
961 real(real64) :: radius, pos(this%space%dim)
962 integer :: iatom, icopy, iunit
966 radius = maxval(m_half*norm2(this%latt%rlattice(:,1:this%space%periodic_dim), dim=1))*(m_one + m_epsilon)
967 latt_iter = lattice_iterator_t(this%latt, radius)
969 if (mpi_grp_is_root(mpi_world))
then
971 iunit = io_open(trim(dir)//
'/crystal.xyz', this%namespace, action=
'write')
973 write(iunit,
'(i9)') this%natoms*latt_iter%n_cells
974 write(iunit,
'(a)')
'#generated by Octopus'
976 do iatom = 1, this%natoms
977 do icopy = 1, latt_iter%n_cells
978 pos = units_from_atomic(units_out%length, this%pos(:, iatom) + latt_iter%get(icopy))
979 write(iunit,
'(a, 99f12.6)') this%atom(iatom)%label, pos
991 class(
ions_t),
intent(in) :: this
992 character(len=*),
intent(in) :: dir, fname
994 integer :: iunit, iatom, idir
995 real(real64) :: force(this%space%dim), center(this%space%dim)
996 character(len=20) frmt
998 if (.not. mpi_grp_is_root(mpi_world))
return
1002 call io_mkdir(dir, this%namespace)
1003 iunit = io_open(trim(dir)//
'/'//trim(fname)//
'.bild', this%namespace, action=
'write', &
1006 write(frmt,
'(a,i0,a)')
'(a,2(', this%space%dim,
'f16.6,1x))'
1008 write(iunit,
'(a)')
'.comment : force vectors in ['//trim(units_abbrev(units_out%force))//
']'
1010 write(iunit,
'(a)')
'.color red'
1012 do iatom = 1, this%natoms
1013 center = units_from_atomic(units_out%length, this%pos(:, iatom))
1014 force = units_from_atomic(units_out%force, this%tot_force(:, iatom))
1015 write(iunit,
'(a,1x,i4,1x,a2,1x,a6,1x,f10.6,a)')
'.comment :', iatom, trim(this%atom(iatom)%label), &
1016 'force:', norm2(force),
'['//trim(units_abbrev(units_out%force))//
']'
1017 write(iunit,fmt=trim(frmt))
'.arrow', (center(idir), idir = 1, this%space%dim), &
1018 (center(idir) + force(idir), idir = 1, this%space%dim)
1022 call io_close(iunit)
1029 class(
ions_t),
intent(in) :: this
1030 character(len=*),
intent(in) :: filename
1031 logical,
optional,
intent(in) :: ascii
1033 integer :: iunit, iatom, ierr
1035 real(real64),
allocatable :: data(:, :)
1036 integer,
allocatable :: idata(:, :)
1037 character(len=MAX_PATH_LEN) :: fullname
1041 assert(this%space%dim == 3)
1043 ascii_ = optional_default(ascii, .
true.)
1045 fullname = trim(filename)//
".vtk"
1047 iunit = io_open(trim(fullname), this%namespace, action=
'write')
1049 write(iunit,
'(1a)')
'# vtk DataFile Version 3.0 '
1050 write(iunit,
'(6a)')
'Generated by octopus ', trim(conf%version),
' - git: ', &
1051 trim(conf%git_commit),
" configuration: ", trim(conf%config_time)
1054 write(iunit,
'(1a)')
'ASCII'
1056 write(iunit,
'(1a)')
'BINARY'
1059 write(iunit,
'(1a)')
'DATASET POLYDATA'
1061 write(iunit,
'(a,i9,a)')
'POINTS ', this%natoms,
' double'
1064 do iatom = 1, this%natoms
1065 write(iunit,
'(3f12.6)') this%pos(1:3, iatom)
1068 call io_close(iunit)
1069 safe_allocate(
data(1:3, 1:this%natoms))
1070 do iatom = 1, this%natoms
1071 data(1:3, iatom) = this%pos(1:3, iatom)
1073 call io_binary_write(io_workpath(fullname, this%namespace), i4_to_i8(3*this%natoms),
data, &
1074 ierr, nohead = .
true., fendian = io_binary_is_little_endian())
1075 safe_deallocate_a(data)
1076 iunit = io_open(trim(fullname), this%namespace, action=
'write', position =
'append')
1077 write(iunit,
'(1a)')
''
1080 write(iunit,
'(a,2i9)')
'VERTICES ', this%natoms, 2*this%natoms
1083 do iatom = 1, this%natoms
1084 write(iunit,
'(2i9)') 1, iatom - 1
1087 call io_close(iunit)
1088 safe_allocate(idata(1:2, 1:this%natoms))
1089 do iatom = 1, this%natoms
1091 idata(2, iatom) = iatom - 1
1093 call io_binary_write(io_workpath(fullname, this%namespace), i4_to_i8(2*this%natoms), idata, &
1094 ierr, nohead = .
true., fendian = io_binary_is_little_endian())
1095 safe_deallocate_a(idata)
1096 iunit = io_open(trim(fullname), this%namespace, action=
'write', position =
'append')
1097 write(iunit,
'(1a)')
''
1100 write(iunit,
'(a,i9)')
'POINT_DATA', this%natoms
1101 write(iunit,
'(a)')
'SCALARS element integer'
1102 write(iunit,
'(a)')
'LOOKUP_TABLE default'
1105 do iatom = 1, this%natoms
1106 write(iunit,
'(i9)') nint(this%atom(iatom)%species%get_z())
1109 call io_close(iunit)
1111 safe_allocate(idata(1:this%natoms, 1))
1113 do iatom = 1, this%natoms
1114 idata(iatom, 1) = nint(this%atom(iatom)%species%get_z())
1117 call io_binary_write(io_workpath(fullname, this%namespace), i4_to_i8(this%natoms), idata, &
1118 ierr, nohead = .
true., fendian = io_binary_is_little_endian())
1120 safe_deallocate_a(idata)
1122 iunit = io_open(trim(fullname), this%namespace, action=
'write', position =
'append')
1123 write(iunit,
'(1a)')
''
1126 call io_close(iunit)
1133 type(
ions_t),
intent(inout) :: ions
1139 call distributed_end(ions%atoms_dist)
1141 call ion_interaction_end(ions%ion_interaction)
1143 safe_deallocate_a(ions%atom)
1146 if(
allocated(ions%species))
then
1147 do i = 1, ions%nspecies
1149 if(
associated(ions%species(i)%s))
deallocate(ions%species(i)%s)
1151 deallocate(ions%species)
1155 call charged_particles_end(ions)
1157 safe_deallocate_a(ions%map_symm_atoms)
1158 safe_deallocate_a(ions%inv_map_symm_atoms)
1168 class(
ions_t),
intent(inout) :: ions
1169 type(lattice_vectors_t),
intent(in) :: latt
1170 logical,
intent(in) :: symmetrize
1175 call ions%latt%update(latt%rlattice)
1178 if (symmetrize)
then
1179 call symmetries_update_lattice_vectors(ions%symm, latt, ions%space%dim)
1192 class(
ions_t),
intent(inout) :: ions
1194 integer :: iatom, iop, iatom_symm, dim4symms
1195 real(real64) :: ratom(ions%space%dim)
1199 safe_allocate(ions%map_symm_atoms(1:ions%natoms, 1:ions%symm%nops + ions%symm%nops_nonsymmorphic))
1200 safe_allocate(ions%inv_map_symm_atoms(1:ions%natoms, 1:ions%symm%nops + ions%symm%nops_nonsymmorphic))
1203 dim4symms = min(3, ions%space%dim)
1206 do iop = 1, ions%symm%nops
1207 do iatom = 1, ions%natoms
1209 ratom(1:dim4symms) = symm_op_apply_inv_cart(ions%symm%ops(iop), ions%pos(:, iatom))
1211 ratom(:) = ions%latt%fold_into_cell(ratom(:))
1214 do iatom_symm = 1, ions%natoms
1215 if (all(abs(ratom(:) - ions%pos(:, iatom_symm)) < symprec))
exit
1218 if (iatom_symm > ions%natoms)
then
1219 write(message(1),
'(a,i6)')
'Internal error: could not find symmetric partner for atom number', iatom
1220 write(message(2),
'(a,i3,a)')
'with symmetry operation number ', iop,
'.'
1221 call messages_fatal(2, namespace=ions%namespace)
1224 ions%map_symm_atoms(iatom, iop) = iatom_symm
1225 ions%inv_map_symm_atoms(iatom_symm, iop) = iatom
1230 do iop = 1, ions%symm%nops_nonsymmorphic
1231 do iatom = 1, ions%natoms
1233 ratom(1:dim4symms) = symm_op_apply_inv_cart(ions%symm%non_symmorphic_ops(iop), ions%pos(:, iatom))
1235 ratom(:) = ions%latt%fold_into_cell(ratom(:))
1238 do iatom_symm = 1, ions%natoms
1239 if (all(abs(ratom(:) - ions%pos(:, iatom_symm)) < symprec))
exit
1242 if (iatom_symm > ions%natoms)
then
1243 write(message(1),
'(a,i6)')
'Internal error: could not find symmetric partner for atom number', iatom
1244 write(message(2),
'(a,i3,a)')
'with symmetry operation number ', iop,
'.'
1245 call messages_fatal(2, namespace=ions%namespace)
1248 ions%map_symm_atoms(iatom, ions%symm%nops+iop) = iatom_symm
1249 ions%inv_map_symm_atoms(iatom_symm, ions%symm%nops+iop) = iatom
1262 class(
ions_t),
intent(inout) :: ions
1264 integer :: iatom, iop, iatom_sym
1265 real(real64) :: ratom(ions%space%dim)
1266 real(real64),
allocatable :: new_pos(:,:)
1270 safe_allocate(new_pos(1:ions%space%dim, 1:ions%natoms))
1272 do iatom = 1, ions%natoms
1273 new_pos(:, iatom) = m_zero
1276 do iop = 1, ions%symm%nops
1277 iatom_sym = ions%inv_map_symm_atoms(iatom, iop)
1278 ratom = symm_op_apply_inv_cart(ions%symm%ops(iop), ions%pos(:, iatom_sym))
1279 ratom = ions%latt%fold_into_cell(ratom)
1280 new_pos(:, iatom) = new_pos(:, iatom) + ratom
1284 do iop = 1, ions%symm%nops_nonsymmorphic
1285 iatom_sym = ions%inv_map_symm_atoms(iatom, iop + ions%symm%nops)
1286 ratom = symm_op_apply_inv_cart(ions%symm%non_symmorphic_ops(iop), ions%pos(:, iatom_sym))
1287 ratom = ions%latt%fold_into_cell(ratom)
1288 new_pos(:, iatom) = new_pos(:, iatom) + ratom
1291 new_pos(:, iatom) = new_pos(:, iatom) / (ions%symm%nops + ions%symm%nops_nonsymmorphic)
1300 class(
ions_t),
intent(inout) :: ions
1302 type(spglibdataset) :: spg_dataset
1303 character(len=11) :: symbol =
""
1304 integer,
allocatable :: site_type(:)
1305 integer :: space_group, ia
1307 if(.not. ions%space%is_periodic())
return
1311 safe_allocate(site_type(1:ions%natoms))
1312 do ia = 1, ions%natoms
1313 site_type(ia) = ions%atom(ia)%species%get_index()
1316 spg_dataset = symmetries_get_spg_dataset(ions%namespace, ions%space, ions%latt, ions%natoms, ions%pos, site_type)
1318 safe_deallocate_a(site_type)
1320 if (spg_dataset%spglib_error /= 0)
then
1325 space_group = spg_dataset%spacegroup_number
1326 symbol = spg_dataset%international_symbol
1328 write(message(1),
'(a, i4)')
'Info: Space group No. ', space_group
1329 write(message(2),
'(2a)')
'Info: International: ', trim(symbol)
1330 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...