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