Octopus
ions.F90
Go to the documentation of this file.
1!! Copyright (C) 2002-2006 M. Marques, A. Castro, A. Rubio, G. Bertsch
2!! Copyright (C) 2021 M. Oliveira
3!!
4!! This program is free software; you can redistribute it and/or modify
5!! it under the terms of the GNU General Public License as published by
6!! the Free Software Foundation; either version 2, or (at your option)
7!! any later version.
8!!
9!! This program is distributed in the hope that it will be useful,
10!! but WITHOUT ANY WARRANTY; without even the implied warranty of
11!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12!! GNU General Public License for more details.
13!!
14!! You should have received a copy of the GNU General Public License
15!! along with this program; if not, write to the Free Software
16!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17!! 02110-1301, USA.
18!!
19
20#include "global.h"
21
22module ions_oct_m
23 use atom_oct_m
26 use iso_c_binding
27 use debug_oct_m
29 use global_oct_m
33 use io_oct_m
35 use, intrinsic :: iso_fortran_env
39 use math_oct_m
42 use mpi_oct_m
44 use parser_oct_m
48 use space_oct_m
51 use spglib_f08
55 use unit_oct_m
58
59 implicit none
60
61 private
62 public :: ions_t
63
64 type, extends(charged_particles_t) :: ions_t
65 ! Components are public by default
66
67 type(lattice_vectors_t) :: latt
68
69 integer :: natoms
70 type(atom_t), allocatable :: atom(:)
71
72 type(symmetries_t) :: symm
73
74 type(distributed_t) :: atoms_dist
75
76 integer, allocatable :: map_symm_atoms(:,:)
77 integer, allocatable :: inv_map_symm_atoms(:,:)
78
80 integer :: nspecies
81 class(species_wrapper_t), allocatable :: species(:)
82 logical :: only_user_def
83 logical, private :: species_time_dependent
84
85 logical :: force_total_enforce
86 type(ion_interaction_t) :: ion_interaction
87
89 logical, private :: apply_global_force
90 type(tdf_t), private :: global_force_function
91 contains
92 procedure :: copy => ions_copy
93 generic :: assignment(=) => copy
94 procedure :: partition => ions_partition
95 procedure :: init_interaction => ions_init_interaction
96 procedure :: initialize => ions_initialize
97 procedure :: update_quantity => ions_update_quantity
98 procedure :: init_interaction_as_partner => ions_init_interaction_as_partner
99 procedure :: copy_quantities_to_interaction => ions_copy_quantities_to_interaction
100 procedure :: fold_atoms_into_cell => ions_fold_atoms_into_cell
101 procedure :: min_distance => ions_min_distance
102 procedure :: has_time_dependent_species => ions_has_time_dependent_species
103 procedure :: val_charge => ions_val_charge
104 procedure :: dipole => ions_dipole
105 procedure :: translate => ions_translate
106 procedure :: rotate => ions_rotate
107 procedure :: global_force => ions_global_force
108 procedure :: write_xyz => ions_write_xyz
109 procedure :: read_xyz => ions_read_xyz
110 procedure :: write_poscar => ions_write_poscar
111 procedure :: write_crystal => ions_write_crystal
112 procedure :: write_bild_forces_file => ions_write_bild_forces_file
113 procedure :: write_vtk_geometry => ions_write_vtk_geometry
114 procedure :: update_lattice_vectors => ions_update_lattice_vectors
115 procedure :: symmetrize_atomic_coord => ions_symmetrize_atomic_coord
116 procedure :: generate_mapping_symmetric_atoms => ions_generate_mapping_symmetric_atoms
117 procedure :: print_spacegroup => ions_print_spacegroup
118 final :: ions_finalize
119 end type ions_t
120
121 interface ions_t
122 procedure ions_constructor
123 end interface ions_t
124
125contains
126
127 ! ---------------------------------------------------------
128 function ions_constructor(namespace, print_info, latt_inp) result(ions)
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
133
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
143
144 push_sub_with_profile(ions_constructor)
145
146 allocate(ions)
147
148 ions%namespace = namespace
149
150 ions%space = space_t(namespace)
151
152 call species_factory_init(factory, namespace)
153
154 ! initialize geometry
155 call read_coords_init(xyz)
156
157 ! load positions of the atoms
158 call read_coords_read('Coordinates', xyz, ions%space, namespace)
160 if (xyz%n < 1) then
161 message(1) = "Coordinates have not been defined."
162 call messages_fatal(1, namespace=namespace)
163 end if
165 ! Initialize parent class
166 call charged_particles_init(ions, xyz%n)
168 ! copy information from xyz to ions
169 ions%natoms = xyz%n
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)
174 if (bitand(xyz%flags, xyz_flags_move) /= 0) then
175 ions%fixed(ia) = .not. xyz%atom(ia)%move
176 end if
177 end do
179 if (allocated(xyz%latvec)) then
180 ! Build lattice vectors from the XSF input
181 ions%latt = lattice_vectors_t(namespace, ions%space, xyz%latvec)
182 else
183 ! Build lattice vectors from input file
184 ions%latt = lattice_vectors_t(namespace, ions%space)
185 end if
186
187 ! Convert coordinates to Cartesian in case we have reduced coordinates
188 if (xyz%source == read_coords_reduced) then
189 do ia = 1, ions%natoms
190 ions%pos(:, ia) = ions%latt%red_to_cart(ions%pos(:, ia))
191 end do
192 end if
197 call ions_init_species(ions, factory, print_info=print_info)
198 call distributed_nullify(ions%atoms_dist, ions%natoms)
200 call messages_obsolete_variable(namespace, 'PDBClassical')
202 if (present(latt_inp)) then
203 ! The lattice as read from the input might be needed by some other part of the code, so we save it
204 latt_inp = ions%latt
205 end if
207 ! Now that we have processed the atomic coordinates, we renormalize the
208 ! lattice parameters along the non-periodic dimensions
209 if (ions%space%has_mixed_periodicity()) then
210 safe_allocate(factor(ions%space%dim))
211 do idir = 1, ions%space%periodic_dim
212 factor(idir) = m_one
213 end do
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))
216 end do
217 call ions%latt%scale(factor)
218 safe_deallocate_a(factor)
219 end if
220
221 ! Set the masses and charges. This needs to be done after initializing the species.
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()
225 end do
226
227 ! Check that atoms are not too close
228 if (ions%natoms > 1) then
229 mindist = ions_min_distance(ions, real_atoms_only = .false.)
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 = ", &
234 units_from_atomic(units_out%length, mindist), trim(units_abbrev(units_out%length))
235 call messages_warning(3, namespace=namespace)
236
237 ! then write out the geometry, whether asked for or not in Output variable
238 call io_mkdir(static_dir, namespace)
239 call ions%write_xyz(trim(static_dir)//'/geometry')
240 end if
241
242 if (ions_min_distance(ions, real_atoms_only = .true.) < threshold) then
243 message(1) = "It cannot be correct to run with physical atoms so close."
244 call messages_fatal(1, namespace=namespace)
245 end if
246 end if
247
248 !Initialize symmetries
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)
253 type is(jellium_slab_t)
254 spherical_site(ia) = .false.
256 spherical_site(ia) = .false.
257 type is(species_from_file_t)
258 spherical_site(ia) = .false.
260 spherical_site(ia) = .false.
261 class default
262 spherical_site(ia) = .true.
263 end select
264
265 site_type(ia) = ions%atom(ia)%species%get_index()
266 end do
267
268 ions%symm = symmetries_t(ions%namespace, ions%space, ions%latt, ions%natoms, ions%pos, site_type, spherical_site)
269
270 safe_deallocate_a(spherical_site)
271 safe_deallocate_a(site_type)
272
273 ! Generate the mapping of symmetric atoms
274 call ions%generate_mapping_symmetric_atoms()
275
276 call ion_interaction_init(ions%ion_interaction, namespace, ions%space, ions%natoms)
277
278 !%Variable ForceTotalEnforce
279 !%Type logical
280 !%Default no
281 !%Section Hamiltonian
282 !%Description
283 !% (Experimental) If this variable is set to "yes", then the sum
284 !% of the total forces will be enforced to be zero.
285 !%End
286 call parse_variable(namespace, 'ForceTotalEnforce', .false., ions%force_total_enforce)
287 if (ions%force_total_enforce) call messages_experimental('ForceTotalEnforce', namespace=namespace)
288
289 !%Variable TDGlobalForce
290 !%Type string
291 !%Section Time-Dependent
292 !%Description
293 !% If this variable is set, a global time-dependent force will be
294 !% applied to the ions in the x direction during a time-dependent
295 !% run. This variable defines the base name of the force, that
296 !% should be defined in the <tt>TDFunctions</tt> block. This force
297 !% does not affect the electrons directly.
298 !%End
299
300 if (parse_is_defined(namespace, 'TDGlobalForce')) then
301
302 ions%apply_global_force = .true.
303
304 call parse_variable(namespace, 'TDGlobalForce', 'none', function_name)
305 call tdf_read(ions%global_force_function, namespace, trim(function_name), ierr)
306
307 if (ierr /= 0) then
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.")
310 call messages_fatal(namespace=namespace)
311 end if
312
313 else
314
315 ions%apply_global_force = .false.
316
317 end if
318
319 call species_factory_end(factory)
320
321 pop_sub_with_profile(ions_constructor)
322 end function ions_constructor
323
324 ! ---------------------------------------------------------
325 subroutine ions_init_species(ions, factory, print_info)
326 type(ions_t), intent(inout) :: ions
327 type(species_factory_t), intent(in) :: factory
328 logical, optional, intent(in) :: print_info
329
330 logical :: print_info_, spec_user_defined
331 integer :: i, j, k, ispin
332 class(species_t), pointer :: spec
333
334 push_sub_with_profile(ions_init_species)
335
336 print_info_ = .true.
337 if (present(print_info)) then
338 print_info_ = print_info
339 end if
340 ! First, count the species
341 ions%nspecies = 0
342 atoms1: do i = 1, ions%natoms
343 do j = 1, i - 1
344 if (atom_same_species(ions%atom(j), ions%atom(i))) cycle atoms1
345 end do
346 ions%nspecies = ions%nspecies + 1
347 end do atoms1
348
349 ! Allocate the species structure.
350 allocate(ions%species(1:ions%nspecies))
351
352 ! Now, read the data.
353 k = 0
354 ions%only_user_def = .true.
355 atoms2: do i = 1, ions%natoms
356 do j = 1, i - 1
357 if (atom_same_species(ions%atom(j), ions%atom(i))) cycle atoms2
358 end do
359 k = k + 1
360 ions%species(k)%s => factory%create_from_input(ions%namespace, ions%atom(j)%get_label(), k)
361 ! these are the species which do not represent atoms
362 select type(spec => ions%species(k)%s)
363 class is(jellium_t)
364
365 class default
366 ions%only_user_def = .false.
367 end select
368
369 select type(spec => ions%species(k)%s)
370 type is(pseudopotential_t)
371 if (ions%space%dim /= 3) then
372 message(1) = "Pseudopotentials may only be used with Dimensions = 3."
373 call messages_fatal(1, namespace=ions%namespace)
374 end if
375
376 type is(jellium_slab_t)
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"
379 call messages_fatal(1, namespace=ions%namespace)
380 end if
381 end select
382
383 end do atoms2
384
385 ! Reads the spin components. This is read here, as well as in states_init,
386 ! to be able to pass it to the pseudopotential initializations subroutine.
387 call parse_variable(ions%namespace, 'SpinComponents', 1, ispin)
388 if (.not. varinfo_valid_option('SpinComponents', ispin)) call messages_input_error(ions%namespace, 'SpinComponents')
389 ispin = min(2, ispin)
390
391 if (print_info_) then
392 call messages_print_with_emphasis(msg="Species", namespace=ions%namespace)
393 end if
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_)
397 end do
398 if (print_info_) then
399 call messages_print_with_emphasis(namespace=ions%namespace)
400 end if
401
402 !%Variable SpeciesTimeDependent
403 !%Type logical
404 !%Default no
405 !%Section System::Species
406 !%Description
407 !% When this variable is set, the potential defined in the block <tt>Species</tt> is calculated
408 !% and applied to the Hamiltonian at each time step. You must have at least one <tt>species_user_defined</tt>
409 !% type of species to use this.
410 !%End
411 call parse_variable(ions%namespace, 'SpeciesTimeDependent', .false., ions%species_time_dependent)
412 ! we must have at least one user defined species in order to have time dependency
413 do i = 1,ions%nspecies
414 select type(spec=>ions%species(i)%s)
416 spec_user_defined = .true.
417 end select
418 end do
419 if (ions%species_time_dependent .and. .not. spec_user_defined) then
420 call messages_input_error(ions%namespace, 'SpeciesTimeDependent')
421 end if
422
423 ! assign species
424 do i = 1, ions%natoms
425 do j = 1, ions%nspecies
426 if (atom_same_species(ions%atom(i), ions%species(j)%s)) then
427 call atom_set_species(ions%atom(i), ions%species(j)%s)
428 exit
429 end if
430 end do
431 end do
432
433 pop_sub_with_profile(ions_init_species)
434 end subroutine ions_init_species
435
436 !--------------------------------------------------------------
437 subroutine ions_copy(ions_out, ions_in)
438 class(ions_t), intent(out) :: ions_out
439 class(ions_t), intent(in) :: ions_in
440
441 push_sub(ions_copy)
442
443 call charged_particles_copy(ions_out, ions_in)
444
445 ions_out%latt = ions_in%latt
446
447 ions_out%natoms = ions_in%natoms
448 safe_allocate(ions_out%atom(1:ions_out%natoms))
449 ions_out%atom = ions_in%atom
450
451 ions_out%nspecies = ions_in%nspecies
452 allocate(ions_out%species(1:ions_out%nspecies))
453 ions_out%species = ions_in%species
454
455 ions_out%only_user_def = ions_in%only_user_def
456
457 call distributed_copy(ions_in%atoms_dist, ions_out%atoms_dist)
458
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
463
464
465 pop_sub(ions_copy)
466 end subroutine ions_copy
467
468 ! ---------------------------------------------------------
469 subroutine ions_partition(this, mc)
470 class(ions_t), intent(inout) :: this
471 type(multicomm_t), intent(in) :: mc
472
473 push_sub(ions_partition)
474
475 call distributed_init(this%atoms_dist, this%natoms, mc%group_comm(p_strategy_states), "atoms")
476
477 call ion_interaction_init_parallelization(this%ion_interaction, this%natoms, mc)
478
479 pop_sub(ions_partition)
480 end subroutine ions_partition
481
482 ! ---------------------------------------------------------
483 subroutine ions_init_interaction(this, interaction)
484 class(ions_t), target, intent(inout) :: this
485 class(interaction_t), intent(inout) :: interaction
486
487 push_sub(ions_init_interaction)
488
489 select type (interaction)
490 class default
491 call charged_particles_init_interaction(this, interaction)
492 end select
493
494 pop_sub(ions_init_interaction)
495 end subroutine ions_init_interaction
496
497 ! ---------------------------------------------------------
498 subroutine ions_initialize(this)
499 class(ions_t), intent(inout) :: this
500
501 push_sub(ions_initialize)
502
503 pop_sub(ions_initialize)
504 end subroutine ions_initialize
505
506 ! ---------------------------------------------------------
507 subroutine ions_update_quantity(this, label)
508 class(ions_t), intent(inout) :: this
509 character(len=*), intent(in) :: label
510
511 push_sub(ions_update_quantity)
512
513 select case (label)
514 case default
515 ! Other quantities should be handled by the parent class
516 call charged_particles_update_quantity(this, label)
517 end select
518
519 pop_sub(ions_update_quantity)
520 end subroutine ions_update_quantity
521
522 ! ---------------------------------------------------------
523 subroutine ions_init_interaction_as_partner(partner, interaction)
524 class(ions_t), intent(in) :: partner
525 class(interaction_surrogate_t), intent(inout) :: interaction
526
528
529 select type (interaction)
530 class default
531 call charged_particles_init_interaction_as_partner(partner, interaction)
532 end select
533
536
537 ! ---------------------------------------------------------
538 subroutine ions_copy_quantities_to_interaction(partner, interaction)
539 class(ions_t), intent(inout) :: partner
540 class(interaction_surrogate_t), intent(inout) :: interaction
541
543
544 select type (interaction)
545 class default
546 ! Other interactions should be handled by the parent class
547 call charged_particles_copy_quantities_to_interaction(partner, interaction)
548 end select
549
552
553 ! ---------------------------------------------------------
554 subroutine ions_fold_atoms_into_cell(this)
555 class(ions_t), intent(inout) :: this
556
557 integer :: iatom
558
560
561 do iatom = 1, this%natoms
562 this%pos(:, iatom) = this%latt%fold_into_cell(this%pos(:, iatom))
563 end do
566 end subroutine ions_fold_atoms_into_cell
567
568 ! ---------------------------------------------------------
569 real(real64) function ions_min_distance(this, real_atoms_only) result(rmin)
570 class(ions_t), intent(in) :: this
571 logical, optional, intent(in) :: real_atoms_only
572
573 integer :: iatom, jatom, idir
574 real(real64) :: xx(this%space%dim)
575 logical :: real_atoms_only_
576 class(species_t), pointer :: species
577
578 if (this%natoms == 1 .and. .not. this%space%is_periodic()) then
579 rmin = m_huge
580 return
581 end if
582
583 push_sub(ions_min_distance)
584
585 real_atoms_only_ = optional_default(real_atoms_only, .false.)
586
587 ! Without this line, valgrind complains about a conditional jump on uninitialized variable,
588 ! as atom_get_species has an intent(out) that causes a call to the finalizer (with Ifort)
589 nullify(species)
590
591 rmin = huge(rmin)
592 do iatom = 1, this%natoms
593 call atom_get_species(this%atom(iatom), species)
594 select type(species)
595 class is(jellium_t)
596 if (real_atoms_only_) cycle
597 end select
598 do jatom = iatom + 1, this%natoms
599 call atom_get_species(this%atom(jatom), species)
600 select type(species)
601 class is(jellium_t)
602 if (real_atoms_only_) cycle
603 end select
604 xx = abs(this%pos(:, iatom) - this%pos(:, jatom))
605 if (this%space%is_periodic()) then
606 xx = this%latt%cart_to_red(xx)
607 do idir = 1, this%space%periodic_dim
608 xx(idir) = xx(idir) - floor(xx(idir) + m_half)
609 end do
610 xx = this%latt%red_to_cart(xx)
611 end if
612 rmin = min(norm2(xx), rmin)
613 end do
614 end do
615
616 if (.not. (this%only_user_def .and. real_atoms_only_)) then
617 ! what if the nearest neighbors are periodic images?
618 do idir = 1, this%space%periodic_dim
619 rmin = min(rmin, norm2(this%latt%rlattice(:,idir)))
620 end do
621 end if
622
623 ! To avoid numerical instabilities, we round this to 6 digits only
624 if(rmin < huge(rmin)/1e6_real64) then
625 rmin = anint(rmin*1e6_real64)*1.0e-6_real64
626 end if
627
628 pop_sub(ions_min_distance)
629 end function ions_min_distance
630
631 ! ---------------------------------------------------------
632 logical function ions_has_time_dependent_species(this) result(time_dependent)
633 class(ions_t), intent(in) :: this
634
636
637 time_dependent = this%species_time_dependent
638
641
642 ! ---------------------------------------------------------
643 real(real64) function ions_val_charge(this, mask) result(val_charge)
644 class(ions_t), intent(in) :: this
645 logical, optional, intent(in) :: mask(:)
646
647 push_sub(ions_val_charge)
648
649 if (present(mask)) then
650 val_charge = -sum(this%charge, mask=mask)
651 else
652 val_charge = -sum(this%charge)
653 end if
654
655 pop_sub(ions_val_charge)
656 end function ions_val_charge
657
658 ! ---------------------------------------------------------
659 function ions_dipole(this, mask) result(dipole)
660 class(ions_t), intent(in) :: this
661 logical, optional, intent(in) :: mask(:)
662 real(real64) :: dipole(this%space%dim)
663
664 integer :: ia
665
666 push_sub(ions_dipole)
667
668 dipole = m_zero
669 do ia = 1, this%natoms
670 if (present(mask)) then
671 if (.not. mask(ia)) cycle
672 end if
673 dipole = dipole + this%charge(ia)*this%pos(:, ia)
674 end do
675 dipole = p_proton_charge*dipole
676
677 pop_sub(ions_dipole)
678 end function ions_dipole
679
680 ! ---------------------------------------------------------
681 subroutine ions_translate(this, xx)
682 class(ions_t), intent(inout) :: this
683 real(real64), intent(in) :: xx(this%space%dim)
684
685 integer :: iatom
686
687 push_sub(ions_translate)
688
689 do iatom = 1, this%natoms
690 this%pos(:, iatom) = this%pos(:, iatom) - xx
691 end do
692
693 pop_sub(ions_translate)
694 end subroutine ions_translate
695
696 ! ---------------------------------------------------------
697 subroutine ions_rotate(this, from, from2, to)
698 class(ions_t), intent(inout) :: this
699 real(real64), intent(in) :: from(this%space%dim)
700 real(real64), intent(in) :: from2(this%space%dim)
701 real(real64), intent(in) :: to(this%space%dim)
702
703 integer :: iatom
704 real(real64) :: m1(3, 3), m2(3, 3)
705 real(real64) :: m3(3, 3), f2(3), per(3)
706 real(real64) :: alpha, r
707
708 push_sub(ions_rotate)
709
710 if (this%space%dim /= 3) then
711 call messages_not_implemented("ions_rotate in other than 3 dimensions", namespace=this%namespace)
712 end if
713
714 ! initialize matrices
715 m1 = diagonal_matrix(3, m_one)
716
717 ! rotate the to-axis to the z-axis
718 if (abs(to(2)) > 1d-150) then
719 alpha = atan2(to(2), to(1))
720 call rotate(m1, alpha, 3)
721 end if
722 alpha = atan2(norm2(to(1:2)), to(3))
723 call rotate(m1, -alpha, 2)
724
725 ! get perpendicular to z and from
726 f2 = matmul(m1, from)
727 per(1) = -f2(2)
728 per(2) = f2(1)
729 per(3) = m_zero
730 r = norm2(per)
731 if (r > m_zero) then
732 per = per/r
733 else
734 per(2) = m_one
735 end if
736
737 ! rotate perpendicular axis to the y-axis
738 m2 = diagonal_matrix(3, m_one)
739 alpha = atan2(per(1), per(2))
740 call rotate(m2, -alpha, 3)
741
742 ! rotate from => to (around the y-axis)
743 m3 = diagonal_matrix(3, m_one)
744 alpha = acos(min(sum(from*to), m_one))
745 call rotate(m3, -alpha, 2)
746
747 ! join matrices
748 m2 = matmul(transpose(m2), matmul(m3, m2))
749
750 ! rotate around the z-axis to get the second axis
751 per = matmul(m2, matmul(m1, from2))
752 alpha = atan2(per(1), per(2))
753 call rotate(m2, -alpha, 3) ! second axis is now y
755 ! get combined transformation
756 m1 = matmul(transpose(m1), matmul(m2, m1))
757
758 ! now transform the coordinates
759 ! it is written in this way to avoid what I consider a bug in the Intel compiler
760 do iatom = 1, this%natoms
761 f2 = this%pos(:, iatom)
762 this%pos(:, iatom) = matmul(m1, f2)
763 end do
764
765 pop_sub(ions_rotate)
766 contains
767
768 ! ---------------------------------------------------------
769 subroutine rotate(m, angle, dir)
770 real(real64), intent(inout) :: m(3, 3)
771 real(real64), intent(in) :: angle
772 integer, intent(in) :: dir
773
774 real(real64) :: aux(3, 3), ca, sa
775
777
778 ca = cos(angle)
779 sa = sin(angle)
780
781 aux = m_zero
782 select case (dir)
783 case (1)
784 aux(1, 1) = m_one
785 aux(2, 2) = ca
786 aux(3, 3) = ca
787 aux(2, 3) = sa
788 aux(3, 2) = -sa
789 case (2)
790 aux(2, 2) = m_one
791 aux(1, 1) = ca
792 aux(3, 3) = ca
793 aux(1, 3) = sa
794 aux(3, 1) = -sa
795 case (3)
796 aux(3, 3) = m_one
797 aux(1, 1) = ca
798 aux(2, 2) = ca
799 aux(1, 2) = sa
800 aux(2, 1) = -sa
801 end select
802
803 m = matmul(aux, m)
804
805 pop_sub(ions_rotate.rotate)
806 end subroutine rotate
807
808 end subroutine ions_rotate
809
810 ! ---------------------------------------------------------
811 function ions_global_force(this, time) result(force)
812 class(ions_t), intent(in) :: this
813 real(real64), intent(in) :: time
814 real(real64) :: force(this%space%dim)
815
816 push_sub(ions_global_force)
817
818 force = m_zero
819
820 if (this%apply_global_force) then
821 force(1) = tdf(this%global_force_function, time)
822 end if
823
824 pop_sub(ions_global_force)
825 end function ions_global_force
826
827 ! ---------------------------------------------------------
828 subroutine ions_write_xyz(this, fname, append, comment, reduce_coordinates)
829 class(ions_t), intent(in) :: this
830 character(len=*), intent(in) :: fname
831 logical, optional, intent(in) :: append
832 character(len=*), optional, intent(in) :: comment
833 logical, optional, intent(in) :: reduce_coordinates
834
835 integer :: iatom, idim, iunit
836 character(len=6) position
837 character(len=19) :: frmt
838 real(real64) :: red(this%space%dim)
839
840 if (.not. mpi_world%is_root()) return
841
842 push_sub(ions_write_xyz)
843
844 position = 'asis'
845 if (present(append)) then
846 if (append) position = 'append'
847 end if
848 if(.not.optional_default(reduce_coordinates, .false.)) then
849 iunit = io_open(trim(fname)//'.xyz', this%namespace, action='write', position=position)
850 else
851 iunit = io_open(trim(fname)//'.xyz_red', this%namespace, action='write', position=position)
852 end if
853
854 write(iunit, '(i4)') this%natoms
855 if (present(comment)) then
856 write(iunit, '(1x,a)') comment
857 else
858 write(iunit, '(1x,a,a)') 'units: ', trim(units_abbrev(units_out%length_xyz_file))
859 end if
860
861 write(unit=frmt, fmt="(a5,i2.2,a4,i2.2,a6)") "(6x,a", label_len, ",2x,", this%space%dim,"f12.6)"
862 do iatom = 1, this%natoms
863 if(.not.optional_default(reduce_coordinates, .false.)) then
864 write(unit=iunit, fmt=frmt) this%atom(iatom)%label, &
865 (units_from_atomic(units_out%length_xyz_file, this%pos(idim, iatom)), idim=1, this%space%dim)
866 else
867 red = this%latt%cart_to_red(this%pos(:, iatom))
868 write(unit=iunit, fmt=frmt) this%atom(iatom)%label, (red(idim), idim=1, this%space%dim)
869 end if
870 end do
871 call io_close(iunit)
872
873 pop_sub(ions_write_xyz)
874 end subroutine ions_write_xyz
875
880 !
881 subroutine ions_write_poscar(this, fname, comment)
882 class(ions_t), intent(in) :: this
883 character(len=*), optional, intent(in) :: fname
884 character(len=*), optional, intent(in) :: comment
885
886 integer :: iatom, idim, iunit
887 character(len=:), allocatable :: fname_, comment_
888 character(len=10) :: format_string
889
890 push_sub(ions_write_poscar)
891
892 if (.not. mpi_world%is_root()) then
893 pop_sub(ions_write_poscar)
894 return
895 end if
896
897 comment_ = optional_default(comment, "")
898 fname_ = optional_default(fname, "POSCAR")
899
900 iunit = io_open(trim(fname_), this%namespace, action='write')
901
902 write(iunit, '(A)') comment_ ! mandatory comment
903 write(iunit, '("1.0")') ! scaling factor: we use 1 as lattice vectors are absolute
904
905 write(format_string, '("(",I1,A,")")') this%space%dim, 'F15.10'
906 do idim=1, this%space%dim
907 write(iunit, format_string) units_from_atomic(unit_angstrom, this%latt%rlattice(:,idim))
908 end do
909
910 do iatom = 1, this%natoms
911 write(iunit, '(A)', advance='NO') trim(this%atom(iatom)%label)//" "
912 end do
913 write(iunit, '("")')
914 write(iunit, '(A)') repeat("1 ", this%natoms)
915 write(iunit, '("direct")')
916 write(format_string, '("(",I1,A,")")') this%space%dim, 'F15.10'
917 do iatom=1, this%natoms
918 write(iunit, format_string) this%latt%cart_to_red(this%pos(:, iatom))
919 end do
920
921 call io_close(iunit)
922
924 end subroutine ions_write_poscar
925
926 ! ---------------------------------------------------------
927 subroutine ions_read_xyz(this, fname, comment)
928 class(ions_t), intent(inout) :: this
929 character(len=*), intent(in) :: fname
930 character(len=*), optional, intent(in) :: comment
931
932 integer :: iatom, idir, iunit
933 character(len=19) :: frmt, dum
934 real(real64) :: tmp(this%space%dim)
935
936 push_sub(ions_read_xyz)
937
938 iunit = io_open(trim(fname)//'.xyz', this%namespace, action='read', position='rewind')
939
940 read(iunit, '(i4)') this%natoms
941 if (present(comment)) then
942 read(iunit, *)
943 else
944 read(iunit, *)
945 end if
946 write(unit=frmt, fmt="(a5,i2.2,a4,i2.2,a6)") "(6x,a", label_len, ",2x,", this%space%dim, "f12.6)"
947 do iatom = 1, this%natoms
948 read(unit=iunit, fmt=frmt) dum, (tmp(idir), idir=1, this%space%dim)
949
950 this%pos(:, iatom) = units_to_atomic(units_out%length_xyz_file, tmp)
951 end do
952 call io_close(iunit)
953
954 pop_sub(ions_read_xyz)
955 end subroutine ions_read_xyz
956
957 ! ----------------------------------------------------------------
960 subroutine ions_write_crystal(this, dir)
961 class(ions_t), intent(in) :: this
962 character(len=*), intent(in) :: dir
963
964 type(lattice_iterator_t) :: latt_iter
965 real(real64) :: radius, pos(this%space%dim)
966 integer :: iatom, icopy, iunit
967
968 push_sub(ions_write_crystal)
969
970 radius = maxval(m_half*norm2(this%latt%rlattice(:,1:this%space%periodic_dim), dim=1))*(m_one + m_epsilon)
971 latt_iter = lattice_iterator_t(this%latt, radius)
972
973 if (mpi_world%is_root()) then
974
975 iunit = io_open(trim(dir)//'/crystal.xyz', this%namespace, action='write')
977 write(iunit, '(i9)') this%natoms*latt_iter%n_cells
978 write(iunit, '(a)') '#generated by Octopus'
979
980 do iatom = 1, this%natoms
981 do icopy = 1, latt_iter%n_cells
982 pos = units_from_atomic(units_out%length, this%pos(:, iatom) + latt_iter%get(icopy))
983 write(iunit, '(a, 99f12.6)') this%atom(iatom)%label, pos
984 end do
985 end do
986
987 call io_close(iunit)
988 end if
989
990 pop_sub(ions_write_crystal)
991 end subroutine ions_write_crystal
992
993 ! ---------------------------------------------------------
994 subroutine ions_write_bild_forces_file(this, dir, fname)
995 class(ions_t), intent(in) :: this
996 character(len=*), intent(in) :: dir, fname
997
998 integer :: iunit, iatom, idir
999 real(real64) :: force(this%space%dim), center(this%space%dim)
1000 character(len=20) frmt
1001
1002 if (.not. mpi_world%is_root()) return
1003
1005
1006 call io_mkdir(dir, this%namespace)
1007 iunit = io_open(trim(dir)//'/'//trim(fname)//'.bild', this%namespace, action='write', &
1008 position='asis')
1009
1010 write(frmt,'(a,i0,a)')'(a,2(', this%space%dim,'f16.6,1x))'
1011
1012 write(iunit, '(a)')'.comment : force vectors in ['//trim(units_abbrev(units_out%force))//']'
1013 write(iunit, *)
1014 write(iunit, '(a)')'.color red'
1015 write(iunit, *)
1016 do iatom = 1, this%natoms
1017 center = units_from_atomic(units_out%length, this%pos(:, iatom))
1018 force = units_from_atomic(units_out%force, this%tot_force(:, iatom))
1019 write(iunit, '(a,1x,i4,1x,a2,1x,a6,1x,f10.6,a)') '.comment :', iatom, trim(this%atom(iatom)%label), &
1020 'force:', norm2(force), '['//trim(units_abbrev(units_out%force))//']'
1021 write(iunit,fmt=trim(frmt)) '.arrow', (center(idir), idir = 1, this%space%dim), &
1022 (center(idir) + force(idir), idir = 1, this%space%dim)
1023 write(iunit,*)
1024 end do
1025
1026 call io_close(iunit)
1027
1029 end subroutine ions_write_bild_forces_file
1030
1031 ! -----------------------------------------------------
1032 subroutine ions_write_vtk_geometry(this, filename, ascii)
1033 class(ions_t), intent(in) :: this
1034 character(len=*), intent(in) :: filename
1035 logical, optional, intent(in) :: ascii
1036
1037 integer :: iunit, iatom, ierr
1038 logical :: ascii_
1039 real(real64), allocatable :: data(:, :)
1040 integer, allocatable :: idata(:, :)
1041 character(len=MAX_PATH_LEN) :: fullname
1042
1043 push_sub(ions_write_vtk_geometry)
1044
1045 assert(this%space%dim == 3)
1046
1047 ascii_ = optional_default(ascii, .true.)
1048
1049 fullname = trim(filename)//".vtk"
1050
1051 iunit = io_open(trim(fullname), this%namespace, action='write')
1052
1053 write(iunit, '(1a)') '# vtk DataFile Version 3.0 '
1054 write(iunit, '(6a)') 'Generated by octopus ', trim(conf%version), ' - git: ', &
1055 trim(conf%git_commit), " configuration: ", trim(conf%config_time)
1056
1057 if (ascii_) then
1058 write(iunit, '(1a)') 'ASCII'
1059 else
1060 write(iunit, '(1a)') 'BINARY'
1061 end if
1062
1063 write(iunit, '(1a)') 'DATASET POLYDATA'
1064
1065 write(iunit, '(a,i9,a)') 'POINTS ', this%natoms, ' double'
1066
1067 if (ascii_) then
1068 do iatom = 1, this%natoms
1069 write(iunit, '(3f12.6)') this%pos(1:3, iatom)
1070 end do
1071 else
1072 call io_close(iunit)
1073 safe_allocate(data(1:3, 1:this%natoms))
1074 do iatom = 1, this%natoms
1075 data(1:3, iatom) = this%pos(1:3, iatom)
1076 end do
1077 call io_binary_write(io_workpath(fullname, this%namespace), i4_to_i8(3*this%natoms), data, &
1078 ierr, nohead = .true., fendian = io_binary_is_little_endian())
1079 safe_deallocate_a(data)
1080 iunit = io_open(trim(fullname), this%namespace, action='write', position = 'append')
1081 write(iunit, '(1a)') ''
1082 end if
1083
1084 write(iunit, '(a,2i9)') 'VERTICES ', this%natoms, 2*this%natoms
1085
1086 if (ascii_) then
1087 do iatom = 1, this%natoms
1088 write(iunit, '(2i9)') 1, iatom - 1
1089 end do
1090 else
1091 call io_close(iunit)
1092 safe_allocate(idata(1:2, 1:this%natoms))
1093 do iatom = 1, this%natoms
1094 idata(1, iatom) = 1
1095 idata(2, iatom) = iatom - 1
1096 end do
1097 call io_binary_write(io_workpath(fullname, this%namespace), i4_to_i8(2*this%natoms), idata, &
1098 ierr, nohead = .true., fendian = io_binary_is_little_endian())
1099 safe_deallocate_a(idata)
1100 iunit = io_open(trim(fullname), this%namespace, action='write', position = 'append')
1101 write(iunit, '(1a)') ''
1102 end if
1103
1104 write(iunit, '(a,i9)') 'POINT_DATA', this%natoms
1105 write(iunit, '(a)') 'SCALARS element integer'
1106 write(iunit, '(a)') 'LOOKUP_TABLE default'
1107
1108 if (ascii_) then
1109 do iatom = 1, this%natoms
1110 write(iunit, '(i9)') nint(this%atom(iatom)%species%get_z())
1111 end do
1112 else
1113 call io_close(iunit)
1114
1115 safe_allocate(idata(1:this%natoms, 1))
1116
1117 do iatom = 1, this%natoms
1118 idata(iatom, 1) = nint(this%atom(iatom)%species%get_z())
1119 end do
1120
1121 call io_binary_write(io_workpath(fullname, this%namespace), i4_to_i8(this%natoms), idata, &
1122 ierr, nohead = .true., fendian = io_binary_is_little_endian())
1123
1124 safe_deallocate_a(idata)
1125
1126 iunit = io_open(trim(fullname), this%namespace, action='write', position = 'append')
1127 write(iunit, '(1a)') ''
1128 end if
1129
1130 call io_close(iunit)
1131
1133 end subroutine ions_write_vtk_geometry
1134
1135 ! ---------------------------------------------------------
1136 subroutine ions_finalize(ions)
1137 type(ions_t), intent(inout) :: ions
1138
1139 integer :: i
1140
1141 push_sub(ions_finalize)
1142
1143 call distributed_end(ions%atoms_dist)
1144
1145 call ion_interaction_end(ions%ion_interaction)
1146
1147 safe_deallocate_a(ions%atom)
1148 ions%natoms=0
1149
1150 if(allocated(ions%species)) then
1151 do i = 1, ions%nspecies
1152 !SAFE_ DEALLOCATE_P(ions%species(i)%s)
1153 if(associated(ions%species(i)%s)) deallocate(ions%species(i)%s)
1154 end do
1155 deallocate(ions%species)
1156 end if
1157 ions%nspecies=0
1158
1159 call charged_particles_end(ions)
1160
1161 safe_deallocate_a(ions%map_symm_atoms)
1162 safe_deallocate_a(ions%inv_map_symm_atoms)
1163
1164
1165 pop_sub(ions_finalize)
1166 end subroutine ions_finalize
1167
1168 !-------------------------------------------------------------------
1171 subroutine ions_update_lattice_vectors(ions, latt, symmetrize)
1172 class(ions_t), intent(inout) :: ions
1173 type(lattice_vectors_t), intent(in) :: latt
1174 logical, intent(in) :: symmetrize
1175
1177
1178 ! Update the lattice vectors
1179 call ions%latt%update(latt%rlattice)
1180
1181 ! Regenerate symmetries in Cartesian space
1182 if (symmetrize) then
1183 call symmetries_update_lattice_vectors(ions%symm, latt, ions%space%dim)
1184 end if
1185
1187 end subroutine ions_update_lattice_vectors
1188
1189 !-------------------------------------------------------------------
1196 class(ions_t), intent(inout) :: ions
1197
1198 integer :: iatom, iop, iatom_symm, dim4symms
1199 real(real64) :: ratom(ions%space%dim)
1200
1202
1203 safe_allocate(ions%map_symm_atoms(1:ions%natoms, 1:ions%symm%nops + ions%symm%nops_nonsymmorphic))
1204 safe_allocate(ions%inv_map_symm_atoms(1:ions%natoms, 1:ions%symm%nops + ions%symm%nops_nonsymmorphic))
1205
1206 ! In the 4D case, symmetries are only defined in 3D, see symmetries.F90
1207 dim4symms = min(3, ions%space%dim)
1208 ratom = m_zero
1209
1210 do iop = 1, ions%symm%nops
1211 do iatom = 1, ions%natoms
1212 !We find the atom that correspond to this one, once symmetry is applied
1213 ratom(1:dim4symms) = symm_op_apply_inv_cart(ions%symm%ops(iop), ions%pos(:, iatom))
1214
1215 ratom(:) = ions%latt%fold_into_cell(ratom(:))
1216
1217 ! find iatom_symm
1218 do iatom_symm = 1, ions%natoms
1219 if (all(abs(ratom(:) - ions%pos(:, iatom_symm)) < symprec)) exit
1220 end do
1221
1222 if (iatom_symm > ions%natoms) then
1223 write(message(1),'(a,i6)') 'Internal error: could not find symmetric partner for atom number', iatom
1224 write(message(2),'(a,i3,a)') 'with symmetry operation number ', iop, '.'
1225 call messages_fatal(2, namespace=ions%namespace)
1226 end if
1227
1228 ions%map_symm_atoms(iatom, iop) = iatom_symm
1229 ions%inv_map_symm_atoms(iatom_symm, iop) = iatom
1230 end do
1231 end do
1232
1233 ! Also build a map for non-symmorphic operations
1234 do iop = 1, ions%symm%nops_nonsymmorphic
1235 do iatom = 1, ions%natoms
1236 !We find the atom that correspond to this one, once symmetry is applied
1237 ratom(1:dim4symms) = symm_op_apply_inv_cart(ions%symm%non_symmorphic_ops(iop), ions%pos(:, iatom))
1238
1239 ratom(:) = ions%latt%fold_into_cell(ratom(:))
1240
1241 ! find iatom_symm
1242 do iatom_symm = 1, ions%natoms
1243 if (all(abs(ratom(:) - ions%pos(:, iatom_symm)) < symprec)) exit
1244 end do
1245
1246 if (iatom_symm > ions%natoms) then
1247 write(message(1),'(a,i6)') 'Internal error: could not find symmetric partner for atom number', iatom
1248 write(message(2),'(a,i3,a)') 'with symmetry operation number ', iop, '.'
1249 call messages_fatal(2, namespace=ions%namespace)
1250 end if
1251
1252 ions%map_symm_atoms(iatom, ions%symm%nops+iop) = iatom_symm
1253 ions%inv_map_symm_atoms(iatom_symm, ions%symm%nops+iop) = iatom
1254 end do
1255 end do
1256
1257
1260
1261 !-------------------------------------------------------------------
1265 subroutine ions_symmetrize_atomic_coord(ions)
1266 class(ions_t), intent(inout) :: ions
1267
1268 integer :: iatom, iop, iatom_sym
1269 real(real64) :: ratom(ions%space%dim)
1270 real(real64), allocatable :: new_pos(:,:)
1271
1273
1274 safe_allocate(new_pos(1:ions%space%dim, 1:ions%natoms))
1275
1276 do iatom = 1, ions%natoms
1277 new_pos(:, iatom) = m_zero
1278
1279 ! Symmorphic operations
1280 do iop = 1, ions%symm%nops
1281 iatom_sym = ions%inv_map_symm_atoms(iatom, iop)
1282 ratom = symm_op_apply_inv_cart(ions%symm%ops(iop), ions%pos(:, iatom_sym))
1283 ratom = ions%latt%fold_into_cell(ratom)
1284 new_pos(:, iatom) = new_pos(:, iatom) + ratom
1285 end do
1286
1287 ! Non-symmorphic operations
1288 do iop = 1, ions%symm%nops_nonsymmorphic
1289 iatom_sym = ions%inv_map_symm_atoms(iatom, iop + ions%symm%nops)
1290 ratom = symm_op_apply_inv_cart(ions%symm%non_symmorphic_ops(iop), ions%pos(:, iatom_sym))
1291 ratom = ions%latt%fold_into_cell(ratom)
1292 new_pos(:, iatom) = new_pos(:, iatom) + ratom
1293 end do
1294
1295 new_pos(:, iatom) = new_pos(:, iatom) / (ions%symm%nops + ions%symm%nops_nonsymmorphic)
1296 end do
1297
1298
1300 end subroutine ions_symmetrize_atomic_coord
1301
1303 subroutine ions_print_spacegroup(ions)
1304 class(ions_t), intent(inout) :: ions
1305
1306 type(spglibdataset) :: spg_dataset
1307 character(len=11) :: symbol
1308 integer, allocatable :: site_type(:)
1309 integer :: space_group, ia
1310
1311 if(.not. ions%space%is_periodic()) return
1312
1313 push_sub(ions_print_spacegroup)
1314
1315 safe_allocate(site_type(1:ions%natoms))
1316 do ia = 1, ions%natoms
1317 site_type(ia) = ions%atom(ia)%species%get_index()
1318 end do
1319
1320 spg_dataset = symmetries_get_spg_dataset(ions%namespace, ions%space, ions%latt, ions%natoms, ions%pos, site_type)
1321
1322 safe_deallocate_a(site_type)
1323
1324 if (spg_dataset%spglib_error /= 0) then
1325 pop_sub(ions_print_spacegroup)
1326 return
1327 end if
1328
1329 space_group = spg_dataset%spacegroup_number
1330 symbol = spg_dataset%international_symbol
1331
1332 write(message(1),'(a, i4)') 'Info: Space group No. ', space_group
1333 write(message(2),'(2a)') 'Info: International: ', trim(symbol)
1334 call messages_info(2, namespace=ions%namespace)
1335
1336 pop_sub(ions_print_spacegroup)
1337 end subroutine ions_print_spacegroup
1338
1339end module ions_oct_m
1340
1341!! Local Variables:
1342!! mode: f90
1343!! coding: utf-8
1344!! End:
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)
Definition: ions.F90:865
subroutine, public atom_init(this, dim, label, species)
Definition: atom.F90:151
subroutine, public atom_get_species(this, species)
Definition: atom.F90:261
subroutine, public atom_set_species(this, species)
Definition: atom.F90:249
This module handles the calculation mode.
integer, parameter, public p_strategy_states
parallelization in states
subroutine, public charged_particles_copy(this, cp_in)
subroutine, public charged_particles_init_interaction_as_partner(partner, interaction)
subroutine, public charged_particles_update_quantity(this, label)
subroutine, public charged_particles_init_interaction(this, interaction)
subroutine, public charged_particles_copy_quantities_to_interaction(partner, interaction)
subroutine, public charged_particles_init(this, np)
The init routine is a module level procedure This has the advantage that different classes can have d...
subroutine, public distributed_nullify(this, total)
subroutine, public distributed_init(this, total, comm, tag, scalapack_compat)
Distribute N instances across M processes of communicator comm
subroutine, public distributed_copy(in, out)
@Brief Create a copy of a distributed instance
real(real64), parameter, public m_huge
Definition: global.F90:208
character(len= *), parameter, public static_dir
Definition: global.F90:265
real(real64), parameter, public m_half
Definition: global.F90:196
real(real64), parameter, public m_one
Definition: global.F90:191
This module defines the abstract interaction_t class, and some auxiliary classes for interactions.
Definition: io.F90:116
subroutine, public io_mkdir(fname, namespace, parents)
Definition: io.F90:360
subroutine, public ion_interaction_init_parallelization(this, natoms, mc)
subroutine, public ion_interaction_init(this, namespace, space, natoms)
subroutine ions_init_interaction(this, interaction)
Definition: ions.F90:579
subroutine ions_update_lattice_vectors(ions, latt, symmetrize)
Regenerate the ions information after update of the lattice vectors.
Definition: ions.F90:1267
class(ions_t) function, pointer ions_constructor(namespace, print_info, latt_inp)
Definition: ions.F90:224
subroutine ions_fold_atoms_into_cell(this)
Definition: ions.F90:650
real(real64) function, dimension(this%space%dim) ions_global_force(this, time)
Definition: ions.F90:907
subroutine ions_copy(ions_out, ions_in)
Definition: ions.F90:533
subroutine ions_update_quantity(this, label)
Definition: ions.F90:603
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,...
Definition: ions.F90:1291
subroutine ions_write_xyz(this, fname, append, comment, reduce_coordinates)
Definition: ions.F90:924
subroutine ions_init_species(ions, factory, print_info)
Definition: ions.F90:421
subroutine ions_finalize(ions)
Definition: ions.F90:1232
subroutine ions_initialize(this)
Definition: ions.F90:594
subroutine ions_read_xyz(this, fname, comment)
Definition: ions.F90:1023
subroutine ions_write_vtk_geometry(this, filename, ascii)
Definition: ions.F90:1128
subroutine ions_rotate(this, from, from2, to)
Definition: ions.F90:793
subroutine ions_translate(this, xx)
Definition: ions.F90:777
subroutine ions_symmetrize_atomic_coord(ions)
Symmetrizes atomic coordinates by applying all symmetries.
Definition: ions.F90:1361
subroutine ions_print_spacegroup(ions)
Prints the spacegroup of the system for periodic systems.
Definition: ions.F90:1399
real(real64) function ions_min_distance(this, real_atoms_only)
Definition: ions.F90:665
real(real64) function, dimension(this%space%dim) ions_dipole(this, mask)
Definition: ions.F90:755
subroutine ions_write_bild_forces_file(this, dir, fname)
Definition: ions.F90:1090
subroutine ions_write_crystal(this, dir)
This subroutine creates a crystal by replicating the geometry and writes the result to dir.
Definition: ions.F90:1056
logical function ions_has_time_dependent_species(this)
Definition: ions.F90:728
subroutine ions_partition(this, mc)
Definition: ions.F90:565
subroutine ions_init_interaction_as_partner(partner, interaction)
Definition: ions.F90:619
subroutine ions_copy_quantities_to_interaction(partner, interaction)
Definition: ions.F90:634
subroutine ions_write_poscar(this, fname, comment)
Writes the positions of the ions in POSCAR format.
Definition: ions.F90:977
real(real64) function ions_val_charge(this, mask)
Definition: ions.F90:739
This module is intended to contain "only mathematical" functions and procedures.
Definition: math.F90:117
subroutine, public messages_print_with_emphasis(msg, iunit, namespace)
Definition: messages.F90:904
character(len=512), private msg
Definition: messages.F90:167
subroutine, public messages_warning(no_lines, all_nodes, namespace)
Definition: messages.F90:531
subroutine, public messages_obsolete_variable(namespace, name, rep)
Definition: messages.F90:1029
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:162
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:416
subroutine, public messages_input_error(namespace, var, details, row, column)
Definition: messages.F90:697
subroutine, public messages_experimental(name, namespace)
Definition: messages.F90:1069
This module handles the communicators for the various parallelization strategies.
Definition: multicomm.F90:147
logical function, public parse_is_defined(namespace, name)
Definition: parser.F90:505
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.
Definition: tdfunction.F90:220
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
Definition: unit.F90:134
character(len=20) pure function, public units_abbrev(this)
Definition: unit.F90:225
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.
Definition: multicomm.F90:208
An abstract class for species. Derived classes include jellium, all electron, and pseudopotential spe...
Definition: species.F90:145
int true(void)