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(:,:)
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
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,
atom_get_label(ions%atom(j)), 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 integer,
intent(in) :: iq
514 assert(this%quantities(iq)%updated_on_demand)
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)
591 do iatom = 1, this%natoms
595 if (real_atoms_only_) cycle
597 do jatom = iatom + 1, this%natoms
601 if (real_atoms_only_) cycle
603 xx = abs(this%pos(:, iatom) - this%pos(:, jatom))
604 if (this%space%is_periodic())
then
605 xx = this%latt%cart_to_red(xx)
606 do idir = 1, this%space%periodic_dim
609 xx = this%latt%red_to_cart(xx)
611 rmin = min(norm2(xx), rmin)
615 if (.not. (this%only_user_def .and. real_atoms_only_))
then
617 do idir = 1, this%space%periodic_dim
618 rmin = min(rmin, norm2(this%latt%rlattice(:,idir)))
623 if(rmin < huge(rmin)/1e6_real64)
then
624 rmin = anint(rmin*1e6_real64)*1.0e-6_real64
627 pop_sub(ions_min_distance)
632 class(
ions_t),
intent(in) :: this
636 time_dependent = this%species_time_dependent
642 real(real64) function ions_val_charge(this, mask) result(val_charge)
643 class(
ions_t),
intent(in) :: this
644 logical,
optional,
intent(in) :: mask(:)
648 if (
present(mask))
then
649 val_charge = -sum(this%charge, mask=mask)
651 val_charge = -sum(this%charge)
659 class(
ions_t),
intent(in) :: this
660 logical,
optional,
intent(in) :: mask(:)
661 real(real64) :: dipole(this%space%dim)
668 do ia = 1, this%natoms
669 if (
present(mask))
then
670 if (.not. mask(ia)) cycle
672 dipole = dipole + this%charge(ia)*this%pos(:, ia)
674 dipole = p_proton_charge*dipole
681 class(
ions_t),
intent(inout) :: this
682 real(real64),
intent(in) :: xx(this%space%dim)
688 do iatom = 1, this%natoms
689 this%pos(:, iatom) = this%pos(:, iatom) - xx
697 class(
ions_t),
intent(inout) :: this
698 real(real64),
intent(in) :: from(this%space%dim)
699 real(real64),
intent(in) :: from2(this%space%dim)
700 real(real64),
intent(in) :: to(this%space%dim)
703 real(real64) :: m1(3, 3), m2(3, 3)
704 real(real64) :: m3(3, 3), f2(3), per(3)
705 real(real64) :: alpha, r
709 if (this%space%dim /= 3)
then
710 call messages_not_implemented(
"ions_rotate in other than 3 dimensions", namespace=this%namespace)
714 m1 = diagonal_matrix(3, m_one)
717 if (abs(to(2)) > 1d-150)
then
718 alpha =
atan2(to(2), to(1))
721 alpha =
atan2(norm2(to(1:2)), to(3))
722 call rotate(m1, -alpha, 2)
725 f2 = matmul(m1, from)
737 m2 = diagonal_matrix(3, m_one)
738 alpha =
atan2(per(1), per(2))
739 call rotate(m2, -alpha, 3)
742 m3 = diagonal_matrix(3, m_one)
743 alpha =
acos(min(sum(from*to), m_one))
744 call rotate(m3, -alpha, 2)
747 m2 = matmul(transpose(m2), matmul(m3, m2))
750 per = matmul(m2, matmul(m1, from2))
752 call rotate(m2, -alpha, 3)
755 m1 = matmul(transpose(m1), matmul(m2, m1))
759 do iatom = 1, this%natoms
760 f2 = this%pos(:, iatom)
761 this%pos(:, iatom) = matmul(m1, f2)
768 subroutine rotate(m, angle, dir)
769 real(real64),
intent(inout) :: m(3, 3)
770 real(real64),
intent(in) :: angle
771 integer,
intent(in) :: dir
773 real(real64) :: aux(3, 3), ca, sa
811 class(
ions_t),
intent(in) :: this
812 real(real64),
intent(in) :: time
813 real(real64) :: force(this%space%dim)
819 if (this%apply_global_force)
then
820 force(1) = units_to_atomic(units_inp%force, tdf(this%global_force_function, time))
827 subroutine ions_write_xyz(this, fname, append, comment, reduce_coordinates)
828 class(
ions_t),
intent(in) :: this
829 character(len=*),
intent(in) :: fname
830 logical,
optional,
intent(in) :: append
831 character(len=*),
optional,
intent(in) :: comment
832 logical,
optional,
intent(in) :: reduce_coordinates
834 integer :: iatom, idim, iunit
835 character(len=6) position
836 character(len=19) :: frmt
837 real(real64) :: red(this%space%dim)
839 if (.not. mpi_grp_is_root(mpi_world))
return
844 if (
present(append))
then
845 if (append) position =
'append'
847 if(.not.optional_default(reduce_coordinates, .false.))
then
848 iunit = io_open(trim(fname)//
'.xyz', this%namespace, action=
'write', position=position)
850 iunit = io_open(trim(fname)//
'.xyz_red', this%namespace, action=
'write', position=position)
853 write(iunit,
'(i4)') this%natoms
854 if (
present(comment))
then
855 write(iunit,
'(1x,a)') comment
857 write(iunit,
'(1x,a,a)')
'units: ', trim(units_abbrev(units_out%length_xyz_file))
860 write(unit=frmt, fmt=
"(a5,i2.2,a4,i2.2,a6)")
"(6x,a", label_len,
",2x,", this%space%dim,
"f12.6)"
861 do iatom = 1, this%natoms
862 if(.not.optional_default(reduce_coordinates, .false.))
then
863 write(unit=iunit, fmt=frmt) this%atom(iatom)%label, &
864 (units_from_atomic(units_out%length_xyz_file, this%pos(idim, iatom)), idim=1, this%space%dim)
866 red = this%latt%cart_to_red(this%pos(:, iatom))
867 write(unit=iunit, fmt=frmt) this%atom(iatom)%label, (red(idim), idim=1, this%space%dim)
877 class(
ions_t),
intent(inout) :: this
878 character(len=*),
intent(in) :: fname
879 character(len=*),
optional,
intent(in) :: comment
881 integer :: iatom, idir, iunit
882 character(len=19) :: frmt, dum
883 real(real64) :: tmp(this%space%dim)
887 iunit = io_open(trim(fname)//
'.xyz', this%namespace, action=
'read', position=
'rewind')
889 read(iunit,
'(i4)') this%natoms
890 if (
present(comment))
then
895 write(unit=frmt, fmt=
"(a5,i2.2,a4,i2.2,a6)")
"(6x,a", label_len,
",2x,", this%space%dim,
"f12.6)"
896 do iatom = 1, this%natoms
897 read(unit=iunit, fmt=frmt) dum, (tmp(idir), idir=1, this%space%dim)
899 this%pos(:, iatom) = units_to_atomic(units_out%length_xyz_file, tmp)
910 class(
ions_t),
intent(in) :: this
911 character(len=*),
intent(in) :: dir
913 type(lattice_iterator_t) :: latt_iter
914 real(real64) :: radius, pos(this%space%dim)
915 integer :: iatom, icopy, iunit
919 radius = maxval(m_half*norm2(this%latt%rlattice(:,1:this%space%periodic_dim), dim=1))*(m_one + m_epsilon)
920 latt_iter = lattice_iterator_t(this%latt, radius)
922 if (mpi_grp_is_root(mpi_world))
then
924 iunit = io_open(trim(dir)//
'/crystal.xyz', this%namespace, action=
'write')
926 write(iunit,
'(i9)') this%natoms*latt_iter%n_cells
927 write(iunit,
'(a)')
'#generated by Octopus'
929 do iatom = 1, this%natoms
930 do icopy = 1, latt_iter%n_cells
931 pos = units_from_atomic(units_out%length, this%pos(:, iatom) + latt_iter%get(icopy))
932 write(iunit,
'(a, 99f12.6)') this%atom(iatom)%label, pos
944 class(
ions_t),
intent(in) :: this
945 character(len=*),
intent(in) :: dir, fname
947 integer :: iunit, iatom, idir
948 real(real64) :: force(this%space%dim), center(this%space%dim)
949 character(len=20) frmt
951 if (.not. mpi_grp_is_root(mpi_world))
return
955 call io_mkdir(dir, this%namespace)
956 iunit = io_open(trim(dir)//
'/'//trim(fname)//
'.bild', this%namespace, action=
'write', &
959 write(frmt,
'(a,i0,a)')
'(a,2(', this%space%dim,
'f16.6,1x))'
961 write(iunit,
'(a)')
'.comment : force vectors in ['//trim(units_abbrev(units_out%force))//
']'
963 write(iunit,
'(a)')
'.color red'
965 do iatom = 1, this%natoms
966 center = units_from_atomic(units_out%length, this%pos(:, iatom))
967 force = units_from_atomic(units_out%force, this%tot_force(:, iatom))
968 write(iunit,
'(a,1x,i4,1x,a2,1x,a6,1x,f10.6,a)')
'.comment :', iatom, trim(this%atom(iatom)%label), &
969 'force:', norm2(force),
'['//trim(units_abbrev(units_out%force))//
']'
970 write(iunit,fmt=trim(frmt))
'.arrow', (center(idir), idir = 1, this%space%dim), &
971 (center(idir) + force(idir), idir = 1, this%space%dim)
982 class(
ions_t),
intent(in) :: this
983 character(len=*),
intent(in) :: filename
984 logical,
optional,
intent(in) :: ascii
986 integer :: iunit, iatom, ierr
988 real(real64),
allocatable :: data(:, :)
989 integer,
allocatable :: idata(:, :)
990 character(len=MAX_PATH_LEN) :: fullname
994 assert(this%space%dim == 3)
996 ascii_ = optional_default(ascii, .
true.)
998 fullname = trim(filename)//
".vtk"
1000 iunit = io_open(trim(fullname), this%namespace, action=
'write')
1002 write(iunit,
'(1a)')
'# vtk DataFile Version 3.0 '
1003 write(iunit,
'(6a)')
'Generated by octopus ', trim(conf%version),
' - git: ', &
1004 trim(conf%git_commit),
" configuration: ", trim(conf%config_time)
1007 write(iunit,
'(1a)')
'ASCII'
1009 write(iunit,
'(1a)')
'BINARY'
1012 write(iunit,
'(1a)')
'DATASET POLYDATA'
1014 write(iunit,
'(a,i9,a)')
'POINTS ', this%natoms,
' double'
1017 do iatom = 1, this%natoms
1018 write(iunit,
'(3f12.6)') this%pos(1:3, iatom)
1021 call io_close(iunit)
1022 safe_allocate(
data(1:3, 1:this%natoms))
1023 do iatom = 1, this%natoms
1024 data(1:3, iatom) = this%pos(1:3, iatom)
1026 call io_binary_write(io_workpath(fullname, this%namespace), i4_to_i8(3*this%natoms),
data, &
1027 ierr, nohead = .
true., fendian = io_binary_is_little_endian())
1028 safe_deallocate_a(data)
1029 iunit = io_open(trim(fullname), this%namespace, action=
'write', position =
'append')
1030 write(iunit,
'(1a)')
''
1033 write(iunit,
'(a,2i9)')
'VERTICES ', this%natoms, 2*this%natoms
1036 do iatom = 1, this%natoms
1037 write(iunit,
'(2i9)') 1, iatom - 1
1040 call io_close(iunit)
1041 safe_allocate(idata(1:2, 1:this%natoms))
1042 do iatom = 1, this%natoms
1044 idata(2, iatom) = iatom - 1
1046 call io_binary_write(io_workpath(fullname, this%namespace), i4_to_i8(2*this%natoms), idata, &
1047 ierr, nohead = .
true., fendian = io_binary_is_little_endian())
1048 safe_deallocate_a(idata)
1049 iunit = io_open(trim(fullname), this%namespace, action=
'write', position =
'append')
1050 write(iunit,
'(1a)')
''
1053 write(iunit,
'(a,i9)')
'POINT_DATA', this%natoms
1054 write(iunit,
'(a)')
'SCALARS element integer'
1055 write(iunit,
'(a)')
'LOOKUP_TABLE default'
1058 do iatom = 1, this%natoms
1059 write(iunit,
'(i9)') nint(this%atom(iatom)%species%get_z())
1062 call io_close(iunit)
1064 safe_allocate(idata(1:this%natoms, 1))
1066 do iatom = 1, this%natoms
1067 idata(iatom, 1) = nint(this%atom(iatom)%species%get_z())
1070 call io_binary_write(io_workpath(fullname, this%namespace), i4_to_i8(this%natoms), idata, &
1071 ierr, nohead = .
true., fendian = io_binary_is_little_endian())
1073 safe_deallocate_a(idata)
1075 iunit = io_open(trim(fullname), this%namespace, action=
'write', position =
'append')
1076 write(iunit,
'(1a)')
''
1079 call io_close(iunit)
1086 type(
ions_t),
intent(inout) :: ions
1092 call distributed_end(ions%atoms_dist)
1094 call ion_interaction_end(ions%ion_interaction)
1096 safe_deallocate_a(ions%atom)
1099 if(
allocated(ions%species))
then
1100 do i = 1, ions%nspecies
1102 if(
associated(ions%species(i)%s))
deallocate(ions%species(i)%s)
1104 deallocate(ions%species)
1108 call charged_particles_end(ions)
1110 safe_deallocate_a(ions%map_symm_atoms)
1111 safe_deallocate_a(ions%inv_map_symm_atoms)
1121 class(
ions_t),
intent(inout) :: ions
1122 type(lattice_vectors_t),
intent(in) :: latt
1123 logical,
intent(in) :: symmetrize
1128 call ions%latt%update(latt%rlattice)
1131 if (symmetrize)
then
1132 call symmetries_update_lattice_vectors(ions%symm, latt, ions%space%dim)
1145 class(
ions_t),
intent(inout) :: ions
1147 integer :: iatom, iop, iatom_symm, dim4symms
1148 real(real64) :: ratom(ions%space%dim)
1152 safe_allocate(ions%map_symm_atoms(1:ions%natoms, 1:ions%symm%nops + ions%symm%nops_nonsymmorphic))
1153 safe_allocate(ions%inv_map_symm_atoms(1:ions%natoms, 1:ions%symm%nops + ions%symm%nops_nonsymmorphic))
1156 dim4symms = min(3, ions%space%dim)
1159 do iop = 1, ions%symm%nops
1160 do iatom = 1, ions%natoms
1162 ratom(1:dim4symms) = symm_op_apply_inv_cart(ions%symm%ops(iop), ions%pos(:, iatom))
1164 ratom(:) = ions%latt%fold_into_cell(ratom(:))
1167 do iatom_symm = 1, ions%natoms
1168 if (all(abs(ratom(:) - ions%pos(:, iatom_symm)) < symprec))
exit
1171 if (iatom_symm > ions%natoms)
then
1172 write(message(1),
'(a,i6)')
'Internal error: could not find symmetric partner for atom number', iatom
1173 write(message(2),
'(a,i3,a)')
'with symmetry operation number ', iop,
'.'
1174 call messages_fatal(2, namespace=ions%namespace)
1177 ions%map_symm_atoms(iatom, iop) = iatom_symm
1178 ions%inv_map_symm_atoms(iatom_symm, iop) = iatom
1183 do iop = 1, ions%symm%nops_nonsymmorphic
1184 do iatom = 1, ions%natoms
1186 ratom(1:dim4symms) = symm_op_apply_inv_cart(ions%symm%non_symmorphic_ops(iop), ions%pos(:, iatom))
1188 ratom(:) = ions%latt%fold_into_cell(ratom(:))
1191 do iatom_symm = 1, ions%natoms
1192 if (all(abs(ratom(:) - ions%pos(:, iatom_symm)) < symprec))
exit
1195 if (iatom_symm > ions%natoms)
then
1196 write(message(1),
'(a,i6)')
'Internal error: could not find symmetric partner for atom number', iatom
1197 write(message(2),
'(a,i3,a)')
'with symmetry operation number ', iop,
'.'
1198 call messages_fatal(2, namespace=ions%namespace)
1201 ions%map_symm_atoms(iatom, ions%symm%nops+iop) = iatom_symm
1202 ions%inv_map_symm_atoms(iatom_symm, ions%symm%nops+iop) = iatom
1215 class(
ions_t),
intent(inout) :: ions
1217 integer :: iatom, iop, iatom_sym
1218 real(real64) :: ratom(ions%space%dim)
1219 real(real64),
allocatable :: new_pos(:,:)
1223 safe_allocate(new_pos(1:ions%space%dim, 1:ions%natoms))
1225 do iatom = 1, ions%natoms
1226 new_pos(:, iatom) = m_zero
1229 do iop = 1, ions%symm%nops
1230 iatom_sym = ions%inv_map_symm_atoms(iatom, iop)
1231 ratom = symm_op_apply_inv_cart(ions%symm%ops(iop), ions%pos(:, iatom_sym))
1232 ratom = ions%latt%fold_into_cell(ratom)
1233 new_pos(:, iatom) = new_pos(:, iatom) + ratom
1237 do iop = 1, ions%symm%nops_nonsymmorphic
1238 iatom_sym = ions%inv_map_symm_atoms(iatom, iop + ions%symm%nops)
1239 ratom = symm_op_apply_inv_cart(ions%symm%non_symmorphic_ops(iop), ions%pos(:, iatom_sym))
1240 ratom = ions%latt%fold_into_cell(ratom)
1241 new_pos(:, iatom) = new_pos(:, iatom) + ratom
1244 new_pos(:, iatom) = new_pos(:, iatom) / (ions%symm%nops + ions%symm%nops_nonsymmorphic)
1253 class(
ions_t),
intent(inout) :: ions
1255 type(spglibdataset) :: spg_dataset
1256 character(len=11) :: symbol =
""
1257 integer,
allocatable :: site_type(:)
1258 integer :: space_group, ia
1260 if(.not. ions%space%is_periodic())
return
1264 safe_allocate(site_type(1:ions%natoms))
1265 do ia = 1, ions%natoms
1266 site_type(ia) = ions%atom(ia)%species%get_index()
1269 spg_dataset = symmetries_get_spg_dataset(ions%namespace, ions%space, ions%latt, ions%natoms, ions%pos, site_type)
1271 safe_deallocate_a(site_type)
1273 if (spg_dataset%spglib_error /= 0)
then
1278 space_group = spg_dataset%spacegroup_number
1279 symbol = spg_dataset%international_symbol
1281 write(message(1),
'(a, i4)')
'Info: Space group No. ', space_group
1282 write(message(2),
'(2a)')
'Info: International: ', trim(symbol)
1283 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)
pure character(len=len_trim(adjustl(this%label))) function, public atom_get_label(this)
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, iq)
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_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_update_quantity(this, iq)
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)
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...