37 use,
intrinsic :: iso_fortran_env
71 type(lattice_vectors_t) :: latt
74 type(atom_t),
allocatable :: atom(:)
76 type(symmetries_t) :: symm
78 type(distributed_t) :: atoms_dist
80 integer,
allocatable :: map_symm_atoms(:,:)
81 integer,
allocatable :: inv_map_symm_atoms(:,:)
83 real(real64),
allocatable :: equilibrium_pos(:,:)
89 real(real64),
allocatable :: pos_displacements(:,:)
90 real(real64),
allocatable :: vel_displacements(:,:)
94 class(species_wrapper_t),
allocatable :: species(:)
95 logical :: only_user_def
96 logical,
private :: species_time_dependent
98 logical :: force_total_enforce
99 type(ion_interaction_t) :: ion_interaction
102 logical,
private :: apply_global_force
103 type(tdf_t),
private :: global_force_function
106 generic ::
assignment(=) => copy
139 procedure ions_constructor
145 function ions_constructor(namespace, grp, print_info, latt_inp, shared_namespace)
result(ions)
146 type(namespace_t),
intent(in) :: namespace
147 type(mpi_grp_t),
intent(in) :: grp
148 logical,
optional,
intent(in) :: print_info
149 type(lattice_vectors_t),
optional,
intent(out) :: latt_inp
150 logical,
optional,
intent(in) :: shared_namespace
151 class(ions_t),
pointer :: ions
153 type(read_coords_info) :: xyz
154 integer :: ia, ierr, idir
155 character(len=100) :: function_name
156 real(real64) :: mindist
157 real(real64),
allocatable :: factor(:)
158 integer,
allocatable :: site_type(:)
159 logical,
allocatable :: spherical_site(:)
160 real(real64),
parameter :: threshold = 1e-5_real64
161 type(species_factory_t) :: factory
163 integer :: displacement_mode
164 real(real64) :: amp_pos, amp_vel
166 logical :: in_ensemble
172 ions%namespace = namespace
195 message(1) =
"Coordinates have not been defined."
204 safe_allocate(ions%atom(1:ions%natoms))
205 do ia = 1, ions%natoms
206 call atom_init(ions%atom(ia), ions%space%dim, xyz%atom(ia)%label)
207 ions%pos(:,ia) = xyz%atom(ia)%x(1:ions%space%dim)
209 ions%fixed(ia) = .not. xyz%atom(ia)%move
213 if (
allocated(xyz%latvec))
then
223 do ia = 1, ions%natoms
224 ions%pos(:, ia) = ions%latt%red_to_cart(ions%pos(:, ia))
231 safe_allocate_source_a(ions%equilibrium_pos, ions%pos)
236 do ia = 1, ions%natoms
237 ions%mass(ia) = ions%atom(ia)%species%get_mass()
238 ions%charge(ia) = ions%atom(ia)%species%get_zval()
252 call parse_variable(namespace,
'InitialDisplacementMode', 0, displacement_mode)
262 call parse_variable(namespace,
'InitialDisplacementAmplitudePos', 1.0_real64, amp_pos)
272 call parse_variable(namespace,
'InitialDisplacementAmplitudeVel', 1.0_real64, amp_vel)
274 if (displacement_mode>0)
then
276 message(1) =
"Random displacements are disabled when InitialDisplacementMode > 0."
279 safe_allocate(ions%pos_displacements(1:ions%space%dim, 1:ions%natoms))
280 safe_allocate(ions%vel_displacements(1:ions%space%dim, 1:ions%natoms))
282 call ions%single_mode_displacements(displacement_mode, amp_pos, amp_vel)
285 ions%pos = ions%pos + ions%pos_displacements
293 if(in_ensemble .and. displacement_mode==0)
then
302 call parse_variable(namespace,
'EnsembleTemperature', 0.0_real64, t)
304 safe_allocate(ions%pos_displacements(1:ions%space%dim, 1:ions%natoms))
305 safe_allocate(ions%vel_displacements(1:ions%space%dim, 1:ions%natoms))
306 call ions%init_random_displacements(t)
309 ions%pos = ions%pos + ions%pos_displacements
320 if (
present(latt_inp))
then
327 if (ions%space%has_mixed_periodicity())
then
328 safe_allocate(factor(ions%space%dim))
329 do idir = 1, ions%space%periodic_dim
332 do idir = ions%space%periodic_dim + 1, ions%space%dim
333 factor(idir) =
m_one/norm2(ions%latt%rlattice(1:ions%space%dim, idir))
335 call ions%latt%scale(factor)
336 safe_deallocate_a(factor)
340 if (ions%natoms > 1)
then
342 if (mindist < threshold)
then
343 write(
message(1),
'(a)')
"Some of the atoms seem to sit too close to each other."
344 write(
message(2),
'(a)')
"Please review your input files and the output geometry (in 'static/')."
345 write(
message(3),
'(a, f12.6, 1x, a)')
"Minimum distance = ", &
351 call ions%write_xyz(trim(
static_dir)//
'/geometry')
355 message(1) =
"It cannot be correct to run with physical atoms so close."
361 safe_allocate(spherical_site(1:ions%natoms))
362 safe_allocate(site_type(1:ions%natoms))
363 do ia = 1, ions%natoms
364 select type(spec => ions%atom(ia)%species)
366 spherical_site(ia) = .false.
368 spherical_site(ia) = .false.
370 spherical_site(ia) = .false.
372 spherical_site(ia) = .false.
374 spherical_site(ia) = .
true.
377 site_type(ia) = ions%atom(ia)%species%get_index()
380 ions%symm =
symmetries_t(ions%namespace, ions%space, ions%latt, ions%natoms, ions%pos, site_type, spherical_site)
382 safe_deallocate_a(spherical_site)
383 safe_deallocate_a(site_type)
386 call ions%generate_mapping_symmetric_atoms()
398 call parse_variable(namespace,
'ForceTotalEnforce', .false., ions%force_total_enforce)
414 ions%apply_global_force = .
true.
416 call parse_variable(namespace,
'TDGlobalForce',
'none', function_name)
417 call tdf_read(ions%global_force_function, namespace, trim(function_name), ierr)
420 call messages_write(
"You have enabled the GlobalForce option but Octopus could not find")
421 call messages_write(
"the '"//trim(function_name)//
"' function in the TDFunctions block.")
427 ions%apply_global_force = .false.
438 type(
ions_t),
intent(inout) :: ions
440 logical,
optional,
intent(in) :: print_info
442 logical :: print_info_, spec_user_defined
443 integer :: i, j, k, ispin
449 if (
present(print_info))
then
450 print_info_ = print_info
454 atoms1:
do i = 1, ions%natoms
458 ions%nspecies = ions%nspecies + 1
462 allocate(ions%species(1:ions%nspecies))
466 ions%only_user_def = .
true.
467 atoms2:
do i = 1, ions%natoms
472 ions%species(k)%s => factory%create_from_input(ions%namespace, ions%atom(j)%get_label(), k)
474 select type(spec => ions%species(k)%s)
478 ions%only_user_def = .false.
481 select type(spec => ions%species(k)%s)
483 if (ions%space%dim /= 3)
then
484 message(1) =
"Pseudopotentials may only be used with Dimensions = 3."
489 if (ions%space%is_periodic() .and. ions%space%periodic_dim /= 2)
then
490 message(1) =
"Periodic jelium slab can only be used if PeriodicDim = 2"
501 ispin = min(2, ispin)
503 if (print_info_)
then
506 do i = 1, ions%nspecies
507 spec => ions%species(i)%s
508 call spec%build(ions%namespace, ispin, ions%space%dim, print_info=print_info_)
510 if (print_info_)
then
523 call parse_variable(ions%namespace,
'SpeciesTimeDependent', .false., ions%species_time_dependent)
525 spec_user_defined = .false.
526 do i = 1,ions%nspecies
527 select type(spec=>ions%species(i)%s)
529 spec_user_defined = .
true.
532 if (ions%species_time_dependent .and. .not. spec_user_defined)
then
537 do i = 1, ions%natoms
538 do j = 1, ions%nspecies
551 class(
ions_t),
intent(out) :: ions_out
552 class(
ions_t),
intent(in) :: ions_in
558 ions_out%latt = ions_in%latt
560 ions_out%natoms = ions_in%natoms
561 safe_allocate(ions_out%atom(1:ions_out%natoms))
562 ions_out%atom = ions_in%atom
564 ions_out%nspecies = ions_in%nspecies
565 allocate(ions_out%species(1:ions_out%nspecies))
566 ions_out%species = ions_in%species
568 ions_out%only_user_def = ions_in%only_user_def
572 safe_allocate(ions_out%map_symm_atoms(1:ions_in%natoms, 1:ions_in%symm%nops + ions_in%symm%nops_nonsymmorphic))
573 ions_out%map_symm_atoms = ions_in%map_symm_atoms
574 safe_allocate(ions_out%inv_map_symm_atoms(1:ions_in%natoms, 1:ions_in%symm%nops + ions_in%symm%nops_nonsymmorphic))
575 ions_out%inv_map_symm_atoms = ions_in%inv_map_symm_atoms
583 class(
ions_t),
intent(inout) :: this
599 class(
ions_t),
target,
intent(inout) :: this
604 select type (interaction)
622 class(
ions_t),
intent(inout) :: ions
623 real(real64),
intent(in) :: T
626 integer(int64) :: seed
630 integer :: num_real_modes
636 seed = ions%namespace%get_hash32()
638 message(1) =
"Create initial random displacements for ions."
641 write(
message(1),
'("namespace = ",A)') ions%namespace%get()
642 write(
message(2),
'("seed = ",I0)') seed
647 call phonons%init(ions%namespace, ions%space%dim, ions%natoms, ions%space%is_periodic(), &
648 ions%mass(1:ions%natoms)/
unit_amu%factor)
650 num_real_modes = phonons%num_modes
652 if (num_real_modes == 0)
then
654 ions%pos_displacements =
m_zero
655 ions%vel_displacements =
m_zero
662 call phonons%sample(t, seed, ions%pos_displacements, ions%vel_displacements)
675 class(
ions_t),
intent(inout) :: ions
676 integer,
intent(in) :: mode
677 real(real64),
optional,
intent(in) :: amplitude_pos
678 real(real64),
optional,
intent(in) :: amplitude_vel
681 integer :: num_real_modes, iatom
683 real(real64),
allocatable :: pos_displacements(:), vel_displacements(:)
688 write(
message(1),
'("Create displacements for mode ", I4)') mode
692 call phonons%init(ions%namespace, ions%space%dim, ions%natoms, ions%space%periodic_dim > 0, &
695 num_real_modes = phonons%num_modes
697 if (mode > num_real_modes)
then
698 write(
message(1),
'("Requested mode ",I0," exceeds number of available modes (",I0,")")') mode, num_real_modes
705 ions%pos_displacements =
m_zero
706 ions%vel_displacements =
m_zero
709 safe_allocate(pos_displacements(1:(ions%space%dim*ions%natoms)))
710 safe_allocate(vel_displacements(1:(ions%space%dim*ions%natoms)))
717 call phonons%get_displacements(mode, amplitude_pos, amplitude_vel, pos_displacements, vel_displacements)
719 write(
message(1),
'("Displacements for mode ",I4)') mode
721 do iatom=1, ions%natoms
722 write(
message(1),
'(2x,3E15.5)') pos_displacements((iatom-1)*ions%space%dim+1:(iatom-1)*ions%space%dim+ions%space%dim)
725 write(
message(1),
'("Velocities for mode ",I4)') mode
727 do iatom=1, ions%natoms
728 write(
message(1),
'(2x,3E15.5)') vel_displacements((iatom-1)*ions%space%dim+1:(iatom-1)*ions%space%dim+ions%space%dim)
733 call blas_axpy(phonons%dim, 1.0_real64, pos_displacements(1), 1, ions%pos_displacements(1,1), 1)
734 call blas_axpy(phonons%dim, 1.0_real64, vel_displacements(1), 1, ions%vel_displacements(1,1), 1)
736 safe_deallocate_a(pos_displacements)
737 safe_deallocate_a(vel_displacements)
745 class(
ions_t),
intent(inout) :: this
750 if(
allocated(this%vel_displacements))
then
751 this%vel = this%vel + this%vel_displacements
759 class(
ions_t),
intent(inout) :: this
760 character(len=*),
intent(in) :: label
775 class(
ions_t),
intent(in) :: partner
780 select type (interaction)
790 class(
ions_t),
intent(inout) :: partner
795 select type (interaction)
806 class(
ions_t),
intent(inout) :: this
812 do iatom = 1, this%natoms
813 this%pos(:, iatom) = this%latt%fold_into_cell(this%pos(:, iatom))
820 real(real64) function ions_min_distance(this, real_atoms_only) result(rmin)
821 class(
ions_t),
intent(in) :: this
822 logical,
optional,
intent(in) :: real_atoms_only
824 integer :: iatom, jatom, idir
825 real(real64) :: xx(this%space%dim)
826 logical :: real_atoms_only_
829 if (this%natoms == 1 .and. .not. this%space%is_periodic())
then
834 push_sub(ions_min_distance)
843 do iatom = 1, this%natoms
847 if (real_atoms_only_) cycle
849 do jatom = iatom + 1, this%natoms
853 if (real_atoms_only_) cycle
855 xx = abs(this%pos(:, iatom) - this%pos(:, jatom))
856 if (this%space%is_periodic())
then
857 xx = this%latt%cart_to_red(xx)
858 do idir = 1, this%space%periodic_dim
861 xx = this%latt%red_to_cart(xx)
863 rmin = min(norm2(xx), rmin)
867 if (.not. (this%only_user_def .and. real_atoms_only_))
then
869 do idir = 1, this%space%periodic_dim
870 rmin = min(rmin, norm2(this%latt%rlattice(:,idir)))
875 if(rmin < huge(rmin)/1e6_real64)
then
876 rmin = anint(rmin*1e6_real64)*1.0e-6_real64
879 pop_sub(ions_min_distance)
888 time_dependent = this%species_time_dependent
894 real(real64) function ions_val_charge(this, mask) result(val_charge)
895 class(
ions_t),
intent(in) :: this
896 logical,
optional,
intent(in) :: mask(:)
900 if (
present(mask))
then
901 val_charge = -sum(this%charge, mask=mask)
903 val_charge = -sum(this%charge)
911 class(
ions_t),
intent(in) :: this
912 logical,
optional,
intent(in) :: mask(:)
913 real(real64) :: dipole(this%space%dim)
920 do ia = 1, this%natoms
921 if (
present(mask))
then
922 if (.not. mask(ia)) cycle
924 dipole = dipole + this%charge(ia)*this%pos(:, ia)
926 dipole = p_proton_charge*dipole
933 class(
ions_t),
intent(inout) :: this
934 real(real64),
intent(in) :: xx(this%space%dim)
940 do iatom = 1, this%natoms
941 this%pos(:, iatom) = this%pos(:, iatom) - xx
949 class(
ions_t),
intent(inout) :: this
950 real(real64),
intent(in) :: from(this%space%dim)
951 real(real64),
intent(in) :: from2(this%space%dim)
952 real(real64),
intent(in) :: to(this%space%dim)
955 real(real64) :: m1(3, 3), m2(3, 3)
956 real(real64) :: m3(3, 3), f2(3), per(3)
957 real(real64) :: alpha, r
961 if (this%space%dim /= 3)
then
962 call messages_not_implemented(
"ions_rotate in other than 3 dimensions", namespace=this%namespace)
966 m1 = diagonal_matrix(3, m_one)
969 if (abs(to(2)) > 1d-150)
then
970 alpha =
atan2(to(2), to(1))
973 alpha =
atan2(norm2(to(1:2)), to(3))
974 call rotate(m1, -alpha, 2)
977 f2 = matmul(m1, from)
989 m2 = diagonal_matrix(3, m_one)
990 alpha =
atan2(per(1), per(2))
991 call rotate(m2, -alpha, 3)
994 m3 = diagonal_matrix(3, m_one)
995 alpha =
acos(min(sum(from*to), m_one))
996 call rotate(m3, -alpha, 2)
999 m2 = matmul(transpose(m2), matmul(m3, m2))
1002 per = matmul(m2, matmul(m1, from2))
1003 alpha =
atan2(per(1), per(2))
1004 call rotate(m2, -alpha, 3)
1007 m1 = matmul(transpose(m1), matmul(m2, m1))
1011 do iatom = 1, this%natoms
1012 f2 = this%pos(:, iatom)
1013 this%pos(:, iatom) = matmul(m1, f2)
1020 subroutine rotate(m, angle, dir)
1021 real(real64),
intent(inout) :: m(3, 3)
1022 real(real64),
intent(in) :: angle
1023 integer,
intent(in) :: dir
1025 real(real64) :: aux(3, 3), ca, sa
1063 class(
ions_t),
intent(in) :: this
1064 real(real64),
intent(in) :: time
1065 real(real64) :: force(this%space%dim)
1071 if (this%apply_global_force)
then
1072 force(1) = tdf(this%global_force_function, time)
1079 subroutine ions_write_xyz(this, fname, append, comment, reduce_coordinates)
1080 class(
ions_t),
intent(in) :: this
1081 character(len=*),
intent(in) :: fname
1082 logical,
optional,
intent(in) :: append
1083 character(len=*),
optional,
intent(in) :: comment
1084 logical,
optional,
intent(in) :: reduce_coordinates
1086 integer :: iatom, idim, iunit
1087 character(len=6) position
1088 character(len=19) :: frmt
1089 real(real64) :: red(this%space%dim)
1091 if (.not. this%grp%is_root())
return
1096 if (
present(append))
then
1097 if (append) position =
'append'
1099 if(.not.optional_default(reduce_coordinates, .false.))
then
1100 iunit = io_open(trim(fname)//
'.xyz', this%namespace, action=
'write', position=position)
1102 iunit = io_open(trim(fname)//
'.xyz_red', this%namespace, action=
'write', position=position)
1105 write(iunit,
'(i4)') this%natoms
1106 if (
present(comment))
then
1107 write(iunit,
'(1x,a)') comment
1109 write(iunit,
'(1x,a,a)')
'units: ', trim(units_abbrev(units_out%length_xyz_file))
1112 write(unit=frmt, fmt=
"(a5,i2.2,a4,i2.2,a6)")
"(6x,a", label_len,
",2x,", this%space%dim,
"f15.9)"
1113 do iatom = 1, this%natoms
1114 if(.not.optional_default(reduce_coordinates, .false.))
then
1115 write(unit=iunit, fmt=frmt) this%atom(iatom)%label, &
1116 (units_from_atomic(units_out%length_xyz_file, this%pos(idim, iatom)), idim=1, this%space%dim)
1118 red = this%latt%cart_to_red(this%pos(:, iatom))
1119 write(unit=iunit, fmt=frmt) this%atom(iatom)%label, (red(idim), idim=1, this%space%dim)
1122 call io_close(iunit)
1133 class(
ions_t),
intent(in) :: this
1134 character(len=*),
optional,
intent(in) :: fname
1135 character(len=*),
optional,
intent(in) :: comment
1137 integer :: iatom, idim, iunit
1138 character(len=:),
allocatable :: fname_, comment_
1139 character(len=10) :: format_string
1143 if (.not. this%grp%is_root())
then
1148 comment_ = optional_default(comment,
"")
1149 fname_ = optional_default(fname,
"POSCAR")
1151 iunit = io_open(trim(fname_), this%namespace, action=
'write')
1153 write(iunit,
'(A)') comment_
1154 write(iunit,
'("1.0")')
1156 write(format_string,
'("(",I1,A,")")') this%space%dim,
'F15.10'
1157 do idim=1, this%space%dim
1158 write(iunit, format_string) units_from_atomic(unit_angstrom, this%latt%rlattice(:,idim))
1161 do iatom = 1, this%natoms
1162 write(iunit,
'(A)', advance=
'NO') trim(this%atom(iatom)%label)//
" "
1164 write(iunit,
'("")')
1165 write(iunit,
'(A)') repeat(
"1 ", this%natoms)
1166 write(iunit,
'("direct")')
1167 write(format_string,
'("(",I1,A,")")') this%space%dim,
'F15.10'
1168 do iatom=1, this%natoms
1169 write(iunit, format_string) this%latt%cart_to_red(this%pos(:, iatom))
1172 call io_close(iunit)
1179 use iso_fortran_env,
only: real64
1180 class(
ions_t),
intent(inout) :: this
1181 character(len=*),
intent(in) :: fname
1182 character(len=*),
optional,
intent(in) :: comment
1184 integer :: iatom, idir, iunit, ios
1185 character(len=256) :: line
1186 character(len=LABEL_LEN) :: label
1187 character(len=:),
allocatable :: coordstr
1188 real(real64) :: tmp(this%space%dim)
1192 iunit = io_open(trim(fname)//
'.xyz', this%namespace, action=
'read', position=
'rewind')
1195 read(iunit,
'(i4)') this%natoms
1196 if (
present(comment))
then
1203 do iatom = 1, this%natoms
1206 read(iunit,
'(A)', iostat=ios) line
1208 call io_close(iunit)
1209 message(1) =
"Error reading XYZ atom line"
1210 call messages_fatal(1, namespace=this%namespace)
1214 if (len_trim(line) < label_len)
then
1215 call io_close(iunit)
1216 message(1) =
"XYZ file: atom line too short for label"
1217 call messages_fatal(1, namespace=this%namespace)
1219 label = line(1:label_len)
1222 if (len(line) > label_len)
then
1223 coordstr = adjustl(line(label_len+1:))
1225 call io_close(iunit)
1226 message(1) =
"XYZ file: no coordinate data after label"
1227 call messages_fatal(1, namespace=this%namespace)
1231 read(coordstr, *, iostat=ios) (tmp(idir), idir=1, this%space%dim)
1233 call io_close(iunit)
1234 message(1) =
"XYZ file: malformed coordinate fields"
1235 call messages_fatal(1, namespace=this%namespace)
1239 this%pos(:, iatom) = units_to_atomic(units_out%length_xyz_file, tmp)
1243 call io_close(iunit)
1252 class(
ions_t),
intent(in) :: this
1253 character(len=*),
intent(in) :: dir
1255 type(lattice_iterator_t) :: latt_iter
1256 real(real64) :: radius, pos(this%space%dim)
1257 integer :: iatom, icopy, iunit
1261 radius = maxval(m_half*norm2(this%latt%rlattice(:,1:this%space%periodic_dim), dim=1))*(m_one + m_epsilon)
1262 latt_iter = lattice_iterator_t(this%latt, radius)
1264 if (this%grp%is_root())
then
1266 iunit = io_open(trim(dir)//
'/crystal.xyz', this%namespace, action=
'write')
1268 write(iunit,
'(i9)') this%natoms*latt_iter%n_cells
1269 write(iunit,
'(a)')
'#generated by Octopus'
1271 do iatom = 1, this%natoms
1272 do icopy = 1, latt_iter%n_cells
1273 pos = units_from_atomic(units_out%length, this%pos(:, iatom) + latt_iter%get(icopy))
1274 write(iunit,
'(a, 99f12.6)') this%atom(iatom)%label, pos
1278 call io_close(iunit)
1286 class(
ions_t),
intent(in) :: this
1287 character(len=*),
intent(in) :: dir, fname
1289 integer :: iunit, iatom, idir
1290 real(real64) :: force(this%space%dim), center(this%space%dim)
1291 character(len=20) frmt
1293 if (.not. this%grp%is_root())
return
1297 call io_mkdir(dir, this%namespace)
1298 iunit = io_open(trim(dir)//
'/'//trim(fname)//
'.bild', this%namespace, action=
'write', &
1301 write(frmt,
'(a,i0,a)')
'(a,2(', this%space%dim,
'f16.6,1x))'
1303 write(iunit,
'(a)')
'.comment : force vectors in ['//trim(units_abbrev(units_out%force))//
']'
1305 write(iunit,
'(a)')
'.color red'
1307 do iatom = 1, this%natoms
1308 center = units_from_atomic(units_out%length, this%pos(:, iatom))
1309 force = units_from_atomic(units_out%force, this%tot_force(:, iatom))
1310 write(iunit,
'(a,1x,i4,1x,a2,1x,a6,1x,f10.6,a)')
'.comment :', iatom, trim(this%atom(iatom)%label), &
1311 'force:', norm2(force),
'['//trim(units_abbrev(units_out%force))//
']'
1312 write(iunit,fmt=trim(frmt))
'.arrow', (center(idir), idir = 1, this%space%dim), &
1313 (center(idir) + force(idir), idir = 1, this%space%dim)
1317 call io_close(iunit)
1324 class(
ions_t),
intent(in) :: this
1325 character(len=*),
intent(in) :: filename
1326 logical,
optional,
intent(in) :: ascii
1328 integer :: iunit, iatom, ierr
1330 real(real64),
allocatable :: data(:, :)
1331 integer,
allocatable :: idata(:, :)
1332 character(len=MAX_PATH_LEN) :: fullname
1336 assert(this%space%dim == 3)
1338 ascii_ = optional_default(ascii, .
true.)
1340 fullname = trim(filename)//
".vtk"
1342 iunit = io_open(trim(fullname), this%namespace, action=
'write')
1344 write(iunit,
'(1a)')
'# vtk DataFile Version 3.0 '
1345 write(iunit,
'(6a)')
'Generated by octopus ', trim(conf%version),
' - git: ', &
1346 trim(conf%git_commit),
" configuration: ", trim(conf%config_time)
1349 write(iunit,
'(1a)')
'ASCII'
1351 write(iunit,
'(1a)')
'BINARY'
1354 write(iunit,
'(1a)')
'DATASET POLYDATA'
1356 write(iunit,
'(a,i9,a)')
'POINTS ', this%natoms,
' double'
1359 do iatom = 1, this%natoms
1360 write(iunit,
'(3f12.6)') this%pos(1:3, iatom)
1363 call io_close(iunit)
1364 safe_allocate(
data(1:3, 1:this%natoms))
1365 do iatom = 1, this%natoms
1366 data(1:3, iatom) = this%pos(1:3, iatom)
1368 call io_binary_write(io_workpath(fullname, this%namespace), i4_to_i8(3*this%natoms),
data, &
1369 ierr, nohead = .
true., fendian = io_binary_is_little_endian())
1370 safe_deallocate_a(data)
1371 iunit = io_open(trim(fullname), this%namespace, action=
'write', position =
'append')
1372 write(iunit,
'(1a)')
''
1375 write(iunit,
'(a,2i9)')
'VERTICES ', this%natoms, 2*this%natoms
1378 do iatom = 1, this%natoms
1379 write(iunit,
'(2i9)') 1, iatom - 1
1382 call io_close(iunit)
1383 safe_allocate(idata(1:2, 1:this%natoms))
1384 do iatom = 1, this%natoms
1386 idata(2, iatom) = iatom - 1
1388 call io_binary_write(io_workpath(fullname, this%namespace), i4_to_i8(2*this%natoms), idata, &
1389 ierr, nohead = .
true., fendian = io_binary_is_little_endian())
1390 safe_deallocate_a(idata)
1391 iunit = io_open(trim(fullname), this%namespace, action=
'write', position =
'append')
1392 write(iunit,
'(1a)')
''
1395 write(iunit,
'(a,i9)')
'POINT_DATA', this%natoms
1396 write(iunit,
'(a)')
'SCALARS element integer'
1397 write(iunit,
'(a)')
'LOOKUP_TABLE default'
1400 do iatom = 1, this%natoms
1401 write(iunit,
'(i9)') nint(this%atom(iatom)%species%get_z())
1404 call io_close(iunit)
1406 safe_allocate(idata(1:this%natoms, 1))
1408 do iatom = 1, this%natoms
1409 idata(iatom, 1) = nint(this%atom(iatom)%species%get_z())
1412 call io_binary_write(io_workpath(fullname, this%namespace), i4_to_i8(this%natoms), idata, &
1413 ierr, nohead = .
true., fendian = io_binary_is_little_endian())
1415 safe_deallocate_a(idata)
1417 iunit = io_open(trim(fullname), this%namespace, action=
'write', position =
'append')
1418 write(iunit,
'(1a)')
''
1421 call io_close(iunit)
1428 class(
ions_t),
intent(in) :: this
1429 real(real64) :: current(this%space%dim)
1436 do iatom = this%atoms_dist%start, this%atoms_dist%end
1437 current = current + p_proton_charge*this%atom(iatom)%species%get_zval()*this%vel(:,iatom)
1440 if (this%atoms_dist%parallel)
then
1441 call comm_allreduce(this%atoms_dist%mpi_grp, current, dim=this%space%dim)
1449 class(
ions_t),
intent(in) :: this
1450 real(real64) :: abs_current(this%space%dim)
1456 abs_current = m_zero
1457 do iatom = this%atoms_dist%start, this%atoms_dist%end
1458 abs_current = abs_current + abs(p_proton_charge*this%atom(iatom)%species%get_zval()*this%vel(:,iatom))
1461 if (this%atoms_dist%parallel)
then
1462 call comm_allreduce(this%atoms_dist%mpi_grp, abs_current, dim=this%space%dim)
1470 type(
ions_t),
intent(inout) :: ions
1476 call distributed_end(ions%atoms_dist)
1478 call ion_interaction_end(ions%ion_interaction)
1480 safe_deallocate_a(ions%atom)
1483 if(
allocated(ions%species))
then
1484 do i = 1, ions%nspecies
1486 if(
associated(ions%species(i)%s))
deallocate(ions%species(i)%s)
1488 deallocate(ions%species)
1492 safe_deallocate_a(ions%pos_displacements)
1493 safe_deallocate_a(ions%vel_displacements)
1495 call charged_particles_end(ions)
1497 safe_deallocate_a(ions%map_symm_atoms)
1498 safe_deallocate_a(ions%inv_map_symm_atoms)
1508 class(
ions_t),
intent(inout) :: ions
1509 type(lattice_vectors_t),
intent(in) :: latt
1510 logical,
intent(in) :: symmetrize
1515 call ions%latt%update(latt%rlattice)
1518 if (symmetrize)
then
1519 call symmetries_update_lattice_vectors(ions%symm, latt, ions%space%dim)
1532 class(
ions_t),
intent(inout) :: ions
1534 integer :: iatom, iop, iatom_symm, dim4symms
1535 real(real64) :: ratom(ions%space%dim)
1539 safe_allocate(ions%map_symm_atoms(1:ions%natoms, 1:ions%symm%nops + ions%symm%nops_nonsymmorphic))
1540 safe_allocate(ions%inv_map_symm_atoms(1:ions%natoms, 1:ions%symm%nops + ions%symm%nops_nonsymmorphic))
1543 dim4symms = min(3, ions%space%dim)
1546 do iop = 1, ions%symm%nops
1547 do iatom = 1, ions%natoms
1549 ratom(1:dim4symms) = symm_op_apply_inv_cart(ions%symm%ops(iop), ions%pos(:, iatom))
1551 ratom(:) = ions%latt%fold_into_cell(ratom(:))
1554 do iatom_symm = 1, ions%natoms
1555 if (all(abs(ratom(:) - ions%pos(:, iatom_symm)) < symprec))
exit
1558 if (iatom_symm > ions%natoms)
then
1559 write(message(1),
'(a,i6)')
'Internal error: could not find symmetric partner for atom number', iatom
1560 write(message(2),
'(a,i3,a)')
'with symmetry operation number ', iop,
'.'
1561 call messages_fatal(2, namespace=ions%namespace)
1564 ions%map_symm_atoms(iatom, iop) = iatom_symm
1565 ions%inv_map_symm_atoms(iatom_symm, iop) = iatom
1570 do iop = 1, ions%symm%nops_nonsymmorphic
1571 do iatom = 1, ions%natoms
1573 ratom(1:dim4symms) = symm_op_apply_inv_cart(ions%symm%non_symmorphic_ops(iop), ions%pos(:, iatom))
1575 ratom(:) = ions%latt%fold_into_cell(ratom(:))
1578 do iatom_symm = 1, ions%natoms
1579 if (all(abs(ratom(:) - ions%pos(:, iatom_symm)) < symprec))
exit
1582 if (iatom_symm > ions%natoms)
then
1583 write(message(1),
'(a,i6)')
'Internal error: could not find symmetric partner for atom number', iatom
1584 write(message(2),
'(a,i3,a)')
'with symmetry operation number ', iop,
'.'
1585 call messages_fatal(2, namespace=ions%namespace)
1588 ions%map_symm_atoms(iatom, ions%symm%nops+iop) = iatom_symm
1589 ions%inv_map_symm_atoms(iatom_symm, ions%symm%nops+iop) = iatom
1604 integer :: iatom, iop, iatom_sym
1605 real(real64) :: ratom(ions%space%dim)
1606 real(real64),
allocatable :: new_pos(:,:)
1610 safe_allocate(new_pos(1:ions%space%dim, 1:ions%natoms))
1612 do iatom = 1, ions%natoms
1613 new_pos(:, iatom) = m_zero
1616 do iop = 1, ions%symm%nops
1617 iatom_sym = ions%inv_map_symm_atoms(iatom, iop)
1618 ratom = symm_op_apply_inv_cart(ions%symm%ops(iop), ions%pos(:, iatom_sym))
1619 ratom = ions%latt%fold_into_cell(ratom)
1620 new_pos(:, iatom) = new_pos(:, iatom) + ratom
1624 do iop = 1, ions%symm%nops_nonsymmorphic
1625 iatom_sym = ions%inv_map_symm_atoms(iatom, iop + ions%symm%nops)
1626 ratom = symm_op_apply_inv_cart(ions%symm%non_symmorphic_ops(iop), ions%pos(:, iatom_sym))
1627 ratom = ions%latt%fold_into_cell(ratom)
1628 new_pos(:, iatom) = new_pos(:, iatom) + ratom
1631 new_pos(:, iatom) = new_pos(:, iatom) / (ions%symm%nops + ions%symm%nops_nonsymmorphic)
1641 class(
ions_t),
intent(inout) :: ions
1643 type(spglibdataset) :: spg_dataset
1644 character(len=11) :: symbol
1645 integer,
allocatable :: site_type(:)
1646 integer :: space_group, ia
1648 if(.not. ions%space%is_periodic())
return
1652 safe_allocate(site_type(1:ions%natoms))
1653 do ia = 1, ions%natoms
1654 site_type(ia) = ions%atom(ia)%species%get_index()
1657 spg_dataset = symmetries_get_spg_dataset(ions%namespace, ions%space, ions%latt, ions%natoms, ions%pos, site_type)
1659 safe_deallocate_a(site_type)
1661 if (spg_dataset%spglib_error /= 0)
then
1666 space_group = spg_dataset%spacegroup_number
1667 symbol = spg_dataset%international_symbol
1669 write(message(1),
'(a, i4)')
'Info: Space group No. ', space_group
1670 write(message(2),
'(2a)')
'Info: International: ', trim(symbol)
1671 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 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_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.
subroutine, public distributed_init_serial(this, total)
Serial initialization of a distributed instance. The calling process is assigned all total instances,...
real(real64), parameter, public m_huge
real(real64), parameter, public m_zero
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.
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
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...