37 use,
intrinsic :: iso_fortran_env
72 type(lattice_vectors_t) :: latt
75 type(atom_t),
allocatable :: atom(:)
77 type(symmetries_t) :: symm
79 type(distributed_t) :: atoms_dist
81 integer,
allocatable :: map_symm_atoms(:,:)
82 integer,
allocatable :: inv_map_symm_atoms(:,:)
84 real(real64),
allocatable :: equilibrium_pos(:,:)
90 real(real64),
allocatable :: pos_displacements(:,:)
91 real(real64),
allocatable :: vel_displacements(:,:)
95 class(species_wrapper_t),
allocatable :: species(:)
96 logical :: only_user_def
97 logical,
private :: species_time_dependent
99 logical :: force_total_enforce
100 type(ion_interaction_t) :: ion_interaction
103 logical,
private :: apply_global_force
104 type(tdf_t),
private :: global_force_function
107 generic ::
assignment(=) => copy
140 procedure ions_constructor
146 function ions_constructor(namespace, grp, print_info, latt_inp, shared_namespace)
result(ions)
147 type(namespace_t),
intent(in) :: namespace
148 type(mpi_grp_t),
intent(in) :: grp
149 logical,
optional,
intent(in) :: print_info
150 type(lattice_vectors_t),
optional,
intent(out) :: latt_inp
151 logical,
optional,
intent(in) :: shared_namespace
152 class(ions_t),
pointer :: ions
154 type(read_coords_info) :: xyz
155 integer :: ia, ierr, idir
156 character(len=100) :: function_name
157 real(real64) :: mindist
158 real(real64),
allocatable :: factor(:)
159 integer,
allocatable :: site_type(:)
160 logical,
allocatable :: spherical_site(:)
161 real(real64),
parameter :: threshold = 1e-5_real64
162 type(species_factory_t) :: factory
164 integer :: displacement_mode
165 real(real64) :: amp_pos, amp_vel
167 logical :: in_ensemble
173 ions%namespace = namespace
196 message(1) =
"Coordinates have not been defined."
205 safe_allocate(ions%atom(1:ions%natoms))
206 do ia = 1, ions%natoms
207 call atom_init(ions%atom(ia), ions%space%dim, xyz%atom(ia)%label)
208 ions%pos(:,ia) = xyz%atom(ia)%x(1:ions%space%dim)
210 ions%fixed(ia) = .not. xyz%atom(ia)%move
214 if (
allocated(xyz%latvec))
then
224 do ia = 1, ions%natoms
225 ions%pos(:, ia) = ions%latt%red_to_cart(ions%pos(:, ia))
232 safe_allocate_source_a(ions%equilibrium_pos, ions%pos)
237 do ia = 1, ions%natoms
238 ions%mass(ia) = ions%atom(ia)%species%get_mass()
239 ions%charge(ia) = ions%atom(ia)%species%get_zval()
253 call parse_variable(namespace,
'InitialDisplacementMode', 0, displacement_mode)
263 call parse_variable(namespace,
'InitialDisplacementAmplitudePos', 1.0_real64, amp_pos)
273 call parse_variable(namespace,
'InitialDisplacementAmplitudeVel', 1.0_real64, amp_vel)
275 if (displacement_mode>0)
then
277 message(1) =
"Random displacements are disabled when InitialDisplacementMode > 0."
280 safe_allocate(ions%pos_displacements(1:ions%space%dim, 1:ions%natoms))
281 safe_allocate(ions%vel_displacements(1:ions%space%dim, 1:ions%natoms))
283 call ions%single_mode_displacements(displacement_mode, amp_pos, amp_vel)
286 ions%pos = ions%pos + ions%pos_displacements
294 if(in_ensemble .and. displacement_mode==0)
then
303 call parse_variable(namespace,
'EnsembleTemperature', 0.0_real64, t)
305 safe_allocate(ions%pos_displacements(1:ions%space%dim, 1:ions%natoms))
306 safe_allocate(ions%vel_displacements(1:ions%space%dim, 1:ions%natoms))
307 call ions%init_random_displacements(t)
310 ions%pos = ions%pos + ions%pos_displacements
321 if (
present(latt_inp))
then
328 if (ions%space%has_mixed_periodicity())
then
329 safe_allocate(factor(ions%space%dim))
330 do idir = 1, ions%space%periodic_dim
333 do idir = ions%space%periodic_dim + 1, ions%space%dim
334 factor(idir) =
m_one/norm2(ions%latt%rlattice(1:ions%space%dim, idir))
336 call ions%latt%scale(factor)
337 safe_deallocate_a(factor)
341 if (ions%natoms > 1)
then
343 if (mindist < threshold)
then
344 write(
message(1),
'(a)')
"Some of the atoms seem to sit too close to each other."
345 write(
message(2),
'(a)')
"Please review your input files and the output geometry (in 'static/')."
346 write(
message(3),
'(a, f12.6, 1x, a)')
"Minimum distance = ", &
352 call ions%write_xyz(trim(
static_dir)//
'/geometry')
356 message(1) =
"It cannot be correct to run with physical atoms so close."
362 safe_allocate(spherical_site(1:ions%natoms))
363 safe_allocate(site_type(1:ions%natoms))
364 do ia = 1, ions%natoms
365 select type(spec => ions%atom(ia)%species)
367 spherical_site(ia) = .false.
369 spherical_site(ia) = .false.
371 spherical_site(ia) = .false.
373 spherical_site(ia) = .false.
375 spherical_site(ia) = .
true.
378 site_type(ia) = ions%atom(ia)%species%get_index()
381 ions%symm =
symmetries_t(ions%namespace, ions%space, ions%latt, ions%natoms, ions%pos, site_type, spherical_site)
383 safe_deallocate_a(spherical_site)
384 safe_deallocate_a(site_type)
387 call ions%generate_mapping_symmetric_atoms()
399 call parse_variable(namespace,
'ForceTotalEnforce', .false., ions%force_total_enforce)
415 ions%apply_global_force = .
true.
417 call parse_variable(namespace,
'TDGlobalForce',
'none', function_name)
418 call tdf_read(ions%global_force_function, namespace, trim(function_name), ierr)
421 call messages_write(
"You have enabled the GlobalForce option but Octopus could not find")
422 call messages_write(
"the '"//trim(function_name)//
"' function in the TDFunctions block.")
428 ions%apply_global_force = .false.
439 type(
ions_t),
intent(inout) :: ions
441 logical,
optional,
intent(in) :: print_info
443 logical :: print_info_, spec_user_defined
444 integer :: i, j, k, ispin
450 if (
present(print_info))
then
451 print_info_ = print_info
455 atoms1:
do i = 1, ions%natoms
459 ions%nspecies = ions%nspecies + 1
463 allocate(ions%species(1:ions%nspecies))
467 ions%only_user_def = .
true.
468 atoms2:
do i = 1, ions%natoms
473 ions%species(k)%s => factory%create_from_input(ions%namespace, ions%atom(j)%get_label(), k)
475 select type(spec => ions%species(k)%s)
479 ions%only_user_def = .false.
482 select type(spec => ions%species(k)%s)
484 if (ions%space%dim /= 3)
then
485 message(1) =
"Pseudopotentials may only be used with Dimensions = 3."
490 if (ions%space%is_periodic() .and. ions%space%periodic_dim /= 2)
then
491 message(1) =
"Periodic jelium slab can only be used if PeriodicDim = 2"
502 ispin = min(2, ispin)
504 if (print_info_)
then
507 do i = 1, ions%nspecies
508 spec => ions%species(i)%s
509 call spec%build(ions%namespace, ispin, ions%space%dim, print_info=print_info_)
511 if (print_info_)
then
524 call parse_variable(ions%namespace,
'SpeciesTimeDependent', .false., ions%species_time_dependent)
526 spec_user_defined = .false.
527 do i = 1,ions%nspecies
528 select type(spec=>ions%species(i)%s)
530 spec_user_defined = .
true.
533 if (ions%species_time_dependent .and. .not. spec_user_defined)
then
538 do i = 1, ions%natoms
539 do j = 1, ions%nspecies
552 class(
ions_t),
intent(out) :: ions_out
553 class(
ions_t),
intent(in) :: ions_in
559 ions_out%latt = ions_in%latt
561 ions_out%natoms = ions_in%natoms
562 safe_allocate(ions_out%atom(1:ions_out%natoms))
563 ions_out%atom = ions_in%atom
565 ions_out%nspecies = ions_in%nspecies
566 allocate(ions_out%species(1:ions_out%nspecies))
567 ions_out%species = ions_in%species
569 ions_out%only_user_def = ions_in%only_user_def
573 safe_allocate(ions_out%map_symm_atoms(1:ions_in%natoms, 1:ions_in%symm%nops + ions_in%symm%nops_nonsymmorphic))
574 ions_out%map_symm_atoms = ions_in%map_symm_atoms
575 safe_allocate(ions_out%inv_map_symm_atoms(1:ions_in%natoms, 1:ions_in%symm%nops + ions_in%symm%nops_nonsymmorphic))
576 ions_out%inv_map_symm_atoms = ions_in%inv_map_symm_atoms
584 class(
ions_t),
intent(inout) :: this
600 class(
ions_t),
target,
intent(inout) :: this
605 select type (interaction)
623 class(
ions_t),
intent(inout) :: ions
624 real(real64),
intent(in) :: T
627 integer(int64) :: seed
632 real(real64),
allocatable :: sigmaP(:)
633 real(real64),
allocatable :: muP(:)
634 real(real64),
allocatable :: sigmaQ(:)
635 real(real64),
allocatable :: muQ(:)
636 real(real64),
allocatable :: genP(:)
637 real(real64),
allocatable :: genQ(:)
640 real(real64) :: beta_half
641 real(real64),
allocatable :: pos_displacements(:), vel_displacements(:)
642 real(real64),
allocatable :: l_m(:), prefactor(:)
644 integer :: imode, idim, iatom, i, iline
645 integer :: num_real_modes
647 real(real64),
parameter :: low_temperature_tolerance = 1.0e-6_real64
653 seed = ions%namespace%get_hash32()
655 message(1) =
"Create initial random displacements for ions."
658 write(
message(1),
'("namespace = ",A)') ions%namespace%get()
659 write(
message(2),
'("seed = ",I0)') seed
664 call phonons%init(ions%namespace, ions%space%dim, ions%natoms, ions%space%periodic_dim > 0)
666 num_real_modes = phonons%num_modes
668 if (num_real_modes == 0)
then
670 ions%pos_displacements =
m_zero
671 ions%vel_displacements =
m_zero
679 call wigner%init(num_real_modes, seed)
682 safe_allocate(sigmap(1:num_real_modes))
683 safe_allocate(sigmaq(1:num_real_modes))
684 safe_allocate(mup(1:num_real_modes))
685 safe_allocate(muq(1:num_real_modes))
686 safe_allocate(genp(1:num_real_modes))
687 safe_allocate(genq(1:num_real_modes))
689 safe_allocate(pos_displacements(1:(ions%space%dim*ions%natoms)))
690 safe_allocate(vel_displacements(1:(ions%space%dim*ions%natoms)))
691 safe_allocate(prefactor(1:(ions%space%dim*ions%natoms)))
693 safe_allocate(l_m(1:num_real_modes))
696 if (t < low_temperature_tolerance)
then
698 sigmap = 1.0_real64/2.0_real64
699 sigmaq = 1.0_real64/2.0_real64
702 sigmap = 1.0_real64/
sqrt((2.0_real64 *
tanh(beta_half * phonons%frequencies)))
703 sigmaq = 1.0_real64/
sqrt((2.0_real64 *
tanh(beta_half * phonons%frequencies)))
708 l_m =
sqrt(2.0_real64/(
unit_amu%factor * phonons%frequencies)) * phonons%alpha
711 do iatom = 1, ions%natoms
712 do idim = 1, ions%space%dim
713 prefactor(i) = 1.0_real64/
sqrt(ions%mass(iatom)/
unit_amu%factor * phonons%num_super)
719 genq = wigner%get(sigmaq, muq,
wigner_q) * l_m
724 ions%pos_displacements =
m_zero
725 ions%vel_displacements =
m_zero
729 do imode = 1, num_real_modes
731 pos_displacements = prefactor(:) * phonons%eigenvectors(:, imode) * genq(imode)
732 vel_displacements = prefactor(:) * phonons%eigenvectors(:, imode) * genp(imode)
735 write(
message(iline),
'("Displacements for mode ",I4)') imode
736 do iatom=1, ions%natoms
738 write(
message(iline),
'(3E15.5)') pos_displacements((iatom-1)*ions%space%dim+1:(iatom-1)*ions%space%dim+ions%space%dim)
741 write(
message(iline),
'("Velocities for mode ",I4)') imode
742 do iatom=1, ions%natoms
744 write(
message(iline),
'(3E15.5)') vel_displacements((iatom-1)*ions%space%dim+1:(iatom-1)*ions%space%dim+ions%space%dim)
749 call blas_axpy(phonons%dim, 1.0_real64, pos_displacements(1), 1, ions%pos_displacements(1,1), 1)
750 call blas_axpy(phonons%dim, 1.0_real64, vel_displacements(1), 1, ions%vel_displacements(1,1), 1)
754 safe_deallocate_a(sigmap)
755 safe_deallocate_a(sigmaq)
756 safe_deallocate_a(mup)
757 safe_deallocate_a(muq)
758 safe_deallocate_a(genp)
759 safe_deallocate_a(genq)
760 safe_deallocate_a(l_m)
762 safe_deallocate_a(prefactor)
763 safe_deallocate_a(pos_displacements)
764 safe_deallocate_a(vel_displacements)
776 class(
ions_t),
intent(inout) :: ions
777 integer,
intent(in) :: mode
778 real(real64),
optional,
intent(in) :: amplitude_pos
779 real(real64),
optional,
intent(in) :: amplitude_vel
782 integer :: num_real_modes, i, iatom, idim
783 real(real64) :: l_m, genP, genQ
785 real(real64),
allocatable :: pos_displacements(:), vel_displacements(:), prefactor(:)
790 write(
message(1),
'("Create displacements for mode ", I4)') mode
794 call phonons%init(ions%namespace, ions%space%dim, ions%natoms, ions%space%periodic_dim > 0)
796 num_real_modes = phonons%num_modes
798 if (mode > num_real_modes)
then
799 write(
message(1),
'("Requested mode ",I0," exceeds number of available modes (",I0,")")') mode, num_real_modes
806 ions%pos_displacements =
m_zero
807 ions%vel_displacements =
m_zero
809 l_m =
sqrt(2.0_real64/(
unit_amu%factor * phonons%frequencies(mode))) * phonons%alpha(mode)
811 safe_allocate(pos_displacements(1:(ions%space%dim*ions%natoms)))
812 safe_allocate(vel_displacements(1:(ions%space%dim*ions%natoms)))
813 safe_allocate(prefactor(1:(ions%space%dim*ions%natoms)))
816 do iatom = 1, ions%natoms
817 do idim=1, ions%space%dim
818 prefactor(i) = 1.0_real64/
sqrt(ions%mass(iatom)/
unit_amu%factor * phonons%num_super)
824 genq = amplitude_pos * l_m
825 genp = amplitude_vel / (l_m *
unit_amu%factor)
827 pos_displacements = prefactor(:) * phonons%eigenvectors(:, mode) * genq
828 vel_displacements = prefactor(:) * phonons%eigenvectors(:, mode) * genp
830 write(
message(1),
'("Displacements for mode ",I4)') mode
832 do iatom=1, ions%natoms
833 write(
message(1),
'(3E15.5)') pos_displacements((iatom-1)*ions%space%dim+1:(iatom-1)*ions%space%dim+ions%space%dim)
836 write(
message(1),
'("Velocities for mode ",I4)') mode
838 do iatom=1, ions%natoms
839 write(
message(1),
'(3E15.5)') vel_displacements((iatom-1)*ions%space%dim+1:(iatom-1)*ions%space%dim+ions%space%dim)
844 call blas_axpy(phonons%dim, 1.0_real64, pos_displacements(1), 1, ions%pos_displacements(1,1), 1)
845 call blas_axpy(phonons%dim, 1.0_real64, vel_displacements(1), 1, ions%vel_displacements(1,1), 1)
847 safe_deallocate_a(pos_displacements)
848 safe_deallocate_a(vel_displacements)
849 safe_deallocate_a(prefactor)
857 class(
ions_t),
intent(inout) :: this
862 if(
allocated(this%vel_displacements))
then
863 this%vel = this%vel + this%vel_displacements
871 class(
ions_t),
intent(inout) :: this
872 character(len=*),
intent(in) :: label
887 class(
ions_t),
intent(in) :: partner
892 select type (interaction)
902 class(
ions_t),
intent(inout) :: partner
907 select type (interaction)
918 class(
ions_t),
intent(inout) :: this
924 do iatom = 1, this%natoms
925 this%pos(:, iatom) = this%latt%fold_into_cell(this%pos(:, iatom))
932 real(real64) function ions_min_distance(this, real_atoms_only) result(rmin)
933 class(
ions_t),
intent(in) :: this
934 logical,
optional,
intent(in) :: real_atoms_only
936 integer :: iatom, jatom, idir
937 real(real64) :: xx(this%space%dim)
938 logical :: real_atoms_only_
941 if (this%natoms == 1 .and. .not. this%space%is_periodic())
then
946 push_sub(ions_min_distance)
955 do iatom = 1, this%natoms
959 if (real_atoms_only_) cycle
961 do jatom = iatom + 1, this%natoms
965 if (real_atoms_only_) cycle
967 xx = abs(this%pos(:, iatom) - this%pos(:, jatom))
968 if (this%space%is_periodic())
then
969 xx = this%latt%cart_to_red(xx)
970 do idir = 1, this%space%periodic_dim
973 xx = this%latt%red_to_cart(xx)
975 rmin = min(norm2(xx), rmin)
979 if (.not. (this%only_user_def .and. real_atoms_only_))
then
981 do idir = 1, this%space%periodic_dim
982 rmin = min(rmin, norm2(this%latt%rlattice(:,idir)))
987 if(rmin < huge(rmin)/1e6_real64)
then
988 rmin = anint(rmin*1e6_real64)*1.0e-6_real64
991 pop_sub(ions_min_distance)
1000 time_dependent = this%species_time_dependent
1006 real(real64) function ions_val_charge(this, mask) result(val_charge)
1007 class(
ions_t),
intent(in) :: this
1008 logical,
optional,
intent(in) :: mask(:)
1012 if (
present(mask))
then
1013 val_charge = -sum(this%charge, mask=mask)
1015 val_charge = -sum(this%charge)
1023 class(
ions_t),
intent(in) :: this
1024 logical,
optional,
intent(in) :: mask(:)
1025 real(real64) :: dipole(this%space%dim)
1032 do ia = 1, this%natoms
1033 if (
present(mask))
then
1034 if (.not. mask(ia)) cycle
1036 dipole = dipole + this%charge(ia)*this%pos(:, ia)
1038 dipole = p_proton_charge*dipole
1045 class(
ions_t),
intent(inout) :: this
1046 real(real64),
intent(in) :: xx(this%space%dim)
1052 do iatom = 1, this%natoms
1053 this%pos(:, iatom) = this%pos(:, iatom) - xx
1061 class(
ions_t),
intent(inout) :: this
1062 real(real64),
intent(in) :: from(this%space%dim)
1063 real(real64),
intent(in) :: from2(this%space%dim)
1064 real(real64),
intent(in) :: to(this%space%dim)
1067 real(real64) :: m1(3, 3), m2(3, 3)
1068 real(real64) :: m3(3, 3), f2(3), per(3)
1069 real(real64) :: alpha, r
1073 if (this%space%dim /= 3)
then
1074 call messages_not_implemented(
"ions_rotate in other than 3 dimensions", namespace=this%namespace)
1078 m1 = diagonal_matrix(3, m_one)
1081 if (abs(to(2)) > 1d-150)
then
1082 alpha =
atan2(to(2), to(1))
1083 call rotate(m1, alpha, 3)
1085 alpha =
atan2(norm2(to(1:2)), to(3))
1086 call rotate(m1, -alpha, 2)
1089 f2 = matmul(m1, from)
1094 if (r > m_zero)
then
1101 m2 = diagonal_matrix(3, m_one)
1102 alpha =
atan2(per(1), per(2))
1103 call rotate(m2, -alpha, 3)
1106 m3 = diagonal_matrix(3, m_one)
1107 alpha =
acos(min(sum(from*to), m_one))
1108 call rotate(m3, -alpha, 2)
1111 m2 = matmul(transpose(m2), matmul(m3, m2))
1114 per = matmul(m2, matmul(m1, from2))
1115 alpha =
atan2(per(1), per(2))
1116 call rotate(m2, -alpha, 3)
1119 m1 = matmul(transpose(m1), matmul(m2, m1))
1123 do iatom = 1, this%natoms
1124 f2 = this%pos(:, iatom)
1125 this%pos(:, iatom) = matmul(m1, f2)
1132 subroutine rotate(m, angle, dir)
1133 real(real64),
intent(inout) :: m(3, 3)
1134 real(real64),
intent(in) :: angle
1135 integer,
intent(in) :: dir
1137 real(real64) :: aux(3, 3), ca, sa
1175 class(
ions_t),
intent(in) :: this
1176 real(real64),
intent(in) :: time
1177 real(real64) :: force(this%space%dim)
1183 if (this%apply_global_force)
then
1184 force(1) = tdf(this%global_force_function, time)
1191 subroutine ions_write_xyz(this, fname, append, comment, reduce_coordinates)
1192 class(
ions_t),
intent(in) :: this
1193 character(len=*),
intent(in) :: fname
1194 logical,
optional,
intent(in) :: append
1195 character(len=*),
optional,
intent(in) :: comment
1196 logical,
optional,
intent(in) :: reduce_coordinates
1198 integer :: iatom, idim, iunit
1199 character(len=6) position
1200 character(len=19) :: frmt
1201 real(real64) :: red(this%space%dim)
1203 if (.not. this%grp%is_root())
return
1208 if (
present(append))
then
1209 if (append) position =
'append'
1211 if(.not.optional_default(reduce_coordinates, .false.))
then
1212 iunit = io_open(trim(fname)//
'.xyz', this%namespace, action=
'write', position=position)
1214 iunit = io_open(trim(fname)//
'.xyz_red', this%namespace, action=
'write', position=position)
1217 write(iunit,
'(i4)') this%natoms
1218 if (
present(comment))
then
1219 write(iunit,
'(1x,a)') comment
1221 write(iunit,
'(1x,a,a)')
'units: ', trim(units_abbrev(units_out%length_xyz_file))
1224 write(unit=frmt, fmt=
"(a5,i2.2,a4,i2.2,a6)")
"(6x,a", label_len,
",2x,", this%space%dim,
"f15.9)"
1225 do iatom = 1, this%natoms
1226 if(.not.optional_default(reduce_coordinates, .false.))
then
1227 write(unit=iunit, fmt=frmt) this%atom(iatom)%label, &
1228 (units_from_atomic(units_out%length_xyz_file, this%pos(idim, iatom)), idim=1, this%space%dim)
1230 red = this%latt%cart_to_red(this%pos(:, iatom))
1231 write(unit=iunit, fmt=frmt) this%atom(iatom)%label, (red(idim), idim=1, this%space%dim)
1234 call io_close(iunit)
1245 class(
ions_t),
intent(in) :: this
1246 character(len=*),
optional,
intent(in) :: fname
1247 character(len=*),
optional,
intent(in) :: comment
1249 integer :: iatom, idim, iunit
1250 character(len=:),
allocatable :: fname_, comment_
1251 character(len=10) :: format_string
1255 if (.not. this%grp%is_root())
then
1260 comment_ = optional_default(comment,
"")
1261 fname_ = optional_default(fname,
"POSCAR")
1263 iunit = io_open(trim(fname_), this%namespace, action=
'write')
1265 write(iunit,
'(A)') comment_
1266 write(iunit,
'("1.0")')
1268 write(format_string,
'("(",I1,A,")")') this%space%dim,
'F15.10'
1269 do idim=1, this%space%dim
1270 write(iunit, format_string) units_from_atomic(unit_angstrom, this%latt%rlattice(:,idim))
1273 do iatom = 1, this%natoms
1274 write(iunit,
'(A)', advance=
'NO') trim(this%atom(iatom)%label)//
" "
1276 write(iunit,
'("")')
1277 write(iunit,
'(A)') repeat(
"1 ", this%natoms)
1278 write(iunit,
'("direct")')
1279 write(format_string,
'("(",I1,A,")")') this%space%dim,
'F15.10'
1280 do iatom=1, this%natoms
1281 write(iunit, format_string) this%latt%cart_to_red(this%pos(:, iatom))
1284 call io_close(iunit)
1291 use iso_fortran_env,
only: real64
1292 class(
ions_t),
intent(inout) :: this
1293 character(len=*),
intent(in) :: fname
1294 character(len=*),
optional,
intent(in) :: comment
1296 integer :: iatom, idir, iunit, ios
1297 character(len=256) :: line
1298 character(len=LABEL_LEN) :: label
1299 character(len=:),
allocatable :: coordstr
1300 real(real64) :: tmp(this%space%dim)
1304 iunit = io_open(trim(fname)//
'.xyz', this%namespace, action=
'read', position=
'rewind')
1307 read(iunit,
'(i4)') this%natoms
1308 if (
present(comment))
then
1315 do iatom = 1, this%natoms
1318 read(iunit,
'(A)', iostat=ios) line
1320 call io_close(iunit)
1321 message(1) =
"Error reading XYZ atom line"
1322 call messages_fatal(1, namespace=this%namespace)
1326 if (len_trim(line) < label_len)
then
1327 call io_close(iunit)
1328 message(1) =
"XYZ file: atom line too short for label"
1329 call messages_fatal(1, namespace=this%namespace)
1331 label = line(1:label_len)
1334 if (len(line) > label_len)
then
1335 coordstr = adjustl(line(label_len+1:))
1337 call io_close(iunit)
1338 message(1) =
"XYZ file: no coordinate data after label"
1339 call messages_fatal(1, namespace=this%namespace)
1343 read(coordstr, *, iostat=ios) (tmp(idir), idir=1, this%space%dim)
1345 call io_close(iunit)
1346 message(1) =
"XYZ file: malformed coordinate fields"
1347 call messages_fatal(1, namespace=this%namespace)
1351 this%pos(:, iatom) = units_to_atomic(units_out%length_xyz_file, tmp)
1355 call io_close(iunit)
1364 class(
ions_t),
intent(in) :: this
1365 character(len=*),
intent(in) :: dir
1367 type(lattice_iterator_t) :: latt_iter
1368 real(real64) :: radius, pos(this%space%dim)
1369 integer :: iatom, icopy, iunit
1373 radius = maxval(m_half*norm2(this%latt%rlattice(:,1:this%space%periodic_dim), dim=1))*(m_one + m_epsilon)
1374 latt_iter = lattice_iterator_t(this%latt, radius)
1376 if (this%grp%is_root())
then
1378 iunit = io_open(trim(dir)//
'/crystal.xyz', this%namespace, action=
'write')
1380 write(iunit,
'(i9)') this%natoms*latt_iter%n_cells
1381 write(iunit,
'(a)')
'#generated by Octopus'
1383 do iatom = 1, this%natoms
1384 do icopy = 1, latt_iter%n_cells
1385 pos = units_from_atomic(units_out%length, this%pos(:, iatom) + latt_iter%get(icopy))
1386 write(iunit,
'(a, 99f12.6)') this%atom(iatom)%label, pos
1390 call io_close(iunit)
1398 class(
ions_t),
intent(in) :: this
1399 character(len=*),
intent(in) :: dir, fname
1401 integer :: iunit, iatom, idir
1402 real(real64) :: force(this%space%dim), center(this%space%dim)
1403 character(len=20) frmt
1405 if (.not. this%grp%is_root())
return
1409 call io_mkdir(dir, this%namespace)
1410 iunit = io_open(trim(dir)//
'/'//trim(fname)//
'.bild', this%namespace, action=
'write', &
1413 write(frmt,
'(a,i0,a)')
'(a,2(', this%space%dim,
'f16.6,1x))'
1415 write(iunit,
'(a)')
'.comment : force vectors in ['//trim(units_abbrev(units_out%force))//
']'
1417 write(iunit,
'(a)')
'.color red'
1419 do iatom = 1, this%natoms
1420 center = units_from_atomic(units_out%length, this%pos(:, iatom))
1421 force = units_from_atomic(units_out%force, this%tot_force(:, iatom))
1422 write(iunit,
'(a,1x,i4,1x,a2,1x,a6,1x,f10.6,a)')
'.comment :', iatom, trim(this%atom(iatom)%label), &
1423 'force:', norm2(force),
'['//trim(units_abbrev(units_out%force))//
']'
1424 write(iunit,fmt=trim(frmt))
'.arrow', (center(idir), idir = 1, this%space%dim), &
1425 (center(idir) + force(idir), idir = 1, this%space%dim)
1429 call io_close(iunit)
1436 class(
ions_t),
intent(in) :: this
1437 character(len=*),
intent(in) :: filename
1438 logical,
optional,
intent(in) :: ascii
1440 integer :: iunit, iatom, ierr
1442 real(real64),
allocatable :: data(:, :)
1443 integer,
allocatable :: idata(:, :)
1444 character(len=MAX_PATH_LEN) :: fullname
1448 assert(this%space%dim == 3)
1450 ascii_ = optional_default(ascii, .
true.)
1452 fullname = trim(filename)//
".vtk"
1454 iunit = io_open(trim(fullname), this%namespace, action=
'write')
1456 write(iunit,
'(1a)')
'# vtk DataFile Version 3.0 '
1457 write(iunit,
'(6a)')
'Generated by octopus ', trim(conf%version),
' - git: ', &
1458 trim(conf%git_commit),
" configuration: ", trim(conf%config_time)
1461 write(iunit,
'(1a)')
'ASCII'
1463 write(iunit,
'(1a)')
'BINARY'
1466 write(iunit,
'(1a)')
'DATASET POLYDATA'
1468 write(iunit,
'(a,i9,a)')
'POINTS ', this%natoms,
' double'
1471 do iatom = 1, this%natoms
1472 write(iunit,
'(3f12.6)') this%pos(1:3, iatom)
1475 call io_close(iunit)
1476 safe_allocate(
data(1:3, 1:this%natoms))
1477 do iatom = 1, this%natoms
1478 data(1:3, iatom) = this%pos(1:3, iatom)
1480 call io_binary_write(io_workpath(fullname, this%namespace), i4_to_i8(3*this%natoms),
data, &
1481 ierr, nohead = .
true., fendian = io_binary_is_little_endian())
1482 safe_deallocate_a(data)
1483 iunit = io_open(trim(fullname), this%namespace, action=
'write', position =
'append')
1484 write(iunit,
'(1a)')
''
1487 write(iunit,
'(a,2i9)')
'VERTICES ', this%natoms, 2*this%natoms
1490 do iatom = 1, this%natoms
1491 write(iunit,
'(2i9)') 1, iatom - 1
1494 call io_close(iunit)
1495 safe_allocate(idata(1:2, 1:this%natoms))
1496 do iatom = 1, this%natoms
1498 idata(2, iatom) = iatom - 1
1500 call io_binary_write(io_workpath(fullname, this%namespace), i4_to_i8(2*this%natoms), idata, &
1501 ierr, nohead = .
true., fendian = io_binary_is_little_endian())
1502 safe_deallocate_a(idata)
1503 iunit = io_open(trim(fullname), this%namespace, action=
'write', position =
'append')
1504 write(iunit,
'(1a)')
''
1507 write(iunit,
'(a,i9)')
'POINT_DATA', this%natoms
1508 write(iunit,
'(a)')
'SCALARS element integer'
1509 write(iunit,
'(a)')
'LOOKUP_TABLE default'
1512 do iatom = 1, this%natoms
1513 write(iunit,
'(i9)') nint(this%atom(iatom)%species%get_z())
1516 call io_close(iunit)
1518 safe_allocate(idata(1:this%natoms, 1))
1520 do iatom = 1, this%natoms
1521 idata(iatom, 1) = nint(this%atom(iatom)%species%get_z())
1524 call io_binary_write(io_workpath(fullname, this%namespace), i4_to_i8(this%natoms), idata, &
1525 ierr, nohead = .
true., fendian = io_binary_is_little_endian())
1527 safe_deallocate_a(idata)
1529 iunit = io_open(trim(fullname), this%namespace, action=
'write', position =
'append')
1530 write(iunit,
'(1a)')
''
1533 call io_close(iunit)
1540 class(
ions_t),
intent(in) :: this
1541 real(real64) :: current(this%space%dim)
1548 do iatom = this%atoms_dist%start, this%atoms_dist%end
1549 current = current + p_proton_charge*this%atom(iatom)%species%get_zval()*this%vel(:,iatom)
1552 if (this%atoms_dist%parallel)
then
1553 call comm_allreduce(this%atoms_dist%mpi_grp, current, dim=this%space%dim)
1561 class(
ions_t),
intent(in) :: this
1562 real(real64) :: abs_current(this%space%dim)
1568 abs_current = m_zero
1569 do iatom = this%atoms_dist%start, this%atoms_dist%end
1570 abs_current = abs_current + abs(p_proton_charge*this%atom(iatom)%species%get_zval()*this%vel(:,iatom))
1573 if (this%atoms_dist%parallel)
then
1574 call comm_allreduce(this%atoms_dist%mpi_grp, abs_current, dim=this%space%dim)
1582 type(
ions_t),
intent(inout) :: ions
1588 call distributed_end(ions%atoms_dist)
1590 call ion_interaction_end(ions%ion_interaction)
1592 safe_deallocate_a(ions%atom)
1595 if(
allocated(ions%species))
then
1596 do i = 1, ions%nspecies
1598 if(
associated(ions%species(i)%s))
deallocate(ions%species(i)%s)
1600 deallocate(ions%species)
1604 safe_deallocate_a(ions%pos_displacements)
1605 safe_deallocate_a(ions%vel_displacements)
1607 call charged_particles_end(ions)
1609 safe_deallocate_a(ions%map_symm_atoms)
1610 safe_deallocate_a(ions%inv_map_symm_atoms)
1620 class(
ions_t),
intent(inout) :: ions
1621 type(lattice_vectors_t),
intent(in) :: latt
1622 logical,
intent(in) :: symmetrize
1627 call ions%latt%update(latt%rlattice)
1630 if (symmetrize)
then
1631 call symmetries_update_lattice_vectors(ions%symm, latt, ions%space%dim)
1644 class(
ions_t),
intent(inout) :: ions
1646 integer :: iatom, iop, iatom_symm, dim4symms
1647 real(real64) :: ratom(ions%space%dim)
1651 safe_allocate(ions%map_symm_atoms(1:ions%natoms, 1:ions%symm%nops + ions%symm%nops_nonsymmorphic))
1652 safe_allocate(ions%inv_map_symm_atoms(1:ions%natoms, 1:ions%symm%nops + ions%symm%nops_nonsymmorphic))
1655 dim4symms = min(3, ions%space%dim)
1658 do iop = 1, ions%symm%nops
1659 do iatom = 1, ions%natoms
1661 ratom(1:dim4symms) = symm_op_apply_inv_cart(ions%symm%ops(iop), ions%pos(:, iatom))
1663 ratom(:) = ions%latt%fold_into_cell(ratom(:))
1666 do iatom_symm = 1, ions%natoms
1667 if (all(abs(ratom(:) - ions%pos(:, iatom_symm)) < symprec))
exit
1670 if (iatom_symm > ions%natoms)
then
1671 write(message(1),
'(a,i6)')
'Internal error: could not find symmetric partner for atom number', iatom
1672 write(message(2),
'(a,i3,a)')
'with symmetry operation number ', iop,
'.'
1673 call messages_fatal(2, namespace=ions%namespace)
1676 ions%map_symm_atoms(iatom, iop) = iatom_symm
1677 ions%inv_map_symm_atoms(iatom_symm, iop) = iatom
1682 do iop = 1, ions%symm%nops_nonsymmorphic
1683 do iatom = 1, ions%natoms
1685 ratom(1:dim4symms) = symm_op_apply_inv_cart(ions%symm%non_symmorphic_ops(iop), ions%pos(:, iatom))
1687 ratom(:) = ions%latt%fold_into_cell(ratom(:))
1690 do iatom_symm = 1, ions%natoms
1691 if (all(abs(ratom(:) - ions%pos(:, iatom_symm)) < symprec))
exit
1694 if (iatom_symm > ions%natoms)
then
1695 write(message(1),
'(a,i6)')
'Internal error: could not find symmetric partner for atom number', iatom
1696 write(message(2),
'(a,i3,a)')
'with symmetry operation number ', iop,
'.'
1697 call messages_fatal(2, namespace=ions%namespace)
1700 ions%map_symm_atoms(iatom, ions%symm%nops+iop) = iatom_symm
1701 ions%inv_map_symm_atoms(iatom_symm, ions%symm%nops+iop) = iatom
1716 integer :: iatom, iop, iatom_sym
1717 real(real64) :: ratom(ions%space%dim)
1718 real(real64),
allocatable :: new_pos(:,:)
1722 safe_allocate(new_pos(1:ions%space%dim, 1:ions%natoms))
1724 do iatom = 1, ions%natoms
1725 new_pos(:, iatom) = m_zero
1728 do iop = 1, ions%symm%nops
1729 iatom_sym = ions%inv_map_symm_atoms(iatom, iop)
1730 ratom = symm_op_apply_inv_cart(ions%symm%ops(iop), ions%pos(:, iatom_sym))
1731 ratom = ions%latt%fold_into_cell(ratom)
1732 new_pos(:, iatom) = new_pos(:, iatom) + ratom
1736 do iop = 1, ions%symm%nops_nonsymmorphic
1737 iatom_sym = ions%inv_map_symm_atoms(iatom, iop + ions%symm%nops)
1738 ratom = symm_op_apply_inv_cart(ions%symm%non_symmorphic_ops(iop), ions%pos(:, iatom_sym))
1739 ratom = ions%latt%fold_into_cell(ratom)
1740 new_pos(:, iatom) = new_pos(:, iatom) + ratom
1743 new_pos(:, iatom) = new_pos(:, iatom) / (ions%symm%nops + ions%symm%nops_nonsymmorphic)
1753 class(
ions_t),
intent(inout) :: ions
1755 type(spglibdataset) :: spg_dataset
1756 character(len=11) :: symbol
1757 integer,
allocatable :: site_type(:)
1758 integer :: space_group, ia
1760 if(.not. ions%space%is_periodic())
return
1764 safe_allocate(site_type(1:ions%natoms))
1765 do ia = 1, ions%natoms
1766 site_type(ia) = ions%atom(ia)%species%get_index()
1769 spg_dataset = symmetries_get_spg_dataset(ions%namespace, ions%space, ions%latt, ions%natoms, ions%pos, site_type)
1771 safe_deallocate_a(site_type)
1773 if (spg_dataset%spglib_error /= 0)
then
1778 space_group = spg_dataset%spacegroup_number
1779 symbol = spg_dataset%international_symbol
1781 write(message(1),
'(a, i4)')
'Info: Space group No. ', space_group
1782 write(message(2),
'(2a)')
'Info: International: ', trim(symbol)
1783 call messages_info(2, namespace=ions%namespace)
--------------— axpy ---------------— Constant times a vector plus a vector.
double acos(double __x) __attribute__((__nothrow__
double sin(double __x) __attribute__((__nothrow__
double cos(double __x) __attribute__((__nothrow__
double tanh(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 contains interfaces for BLAS routines You should not use these routines directly....
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)
Create a copy of a distributed instance.
real(real64), parameter, public m_huge
real(real64), parameter, public m_zero
character(len= *), parameter, public static_dir
real(real64), parameter, public p_kb
Boltzmann constant in Ha/K.
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.
subroutine ions_fold_atoms_into_cell(this)
subroutine ions_single_mode_displacements(ions, mode, amplitude_pos, amplitude_vel)
apply initial displacements and velocities corresponding to a given phonon mode
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)
class(ions_t) function, pointer ions_constructor(namespace, grp, print_info, latt_inp, shared_namespace)
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)
subroutine ions_init_random_displacements(ions, T)
create random displacements for positions and velocities
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)
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
subroutine mpi_grp_copy(mpi_grp_out, mpi_grp_in)
MPI_THREAD_FUNNELED allows for calls to MPI from an OMP region if the thread is the team master.
subroutine mpi_grp_init(grp, comm)
Initialize MPI group instance.
This module handles the communicators for the various parallelization strategies.
logical function, public parse_is_defined(namespace, name)
This module provides a class for (classical) phonon modes.
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)
This module implements the abstract system type.
subroutine, public system_init_parallelization(this, grp)
Basic functionality: copy the MPI group. This function needs to be implemented by extended types that...
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_t), public unit_amu
Mass in atomic mass units (AKA Dalton).
type(unit_system_t), public units_out
integer, parameter, public wigner_q
integer, parameter, public wigner_p
abstract interaction class
surrogate interaction class to avoid circular dependencies between modules.
Stores all communicators and groups.
This class describes phonon modes, which are specified by their frequencies and eigenvectors.
An abstract class for species. Derived classes include jellium, all electron, and pseudopotential spe...
Class describing a Wigner distribution for sampling initial conditions in multi-trajectory Ehrenfest ...