(git:34ef472)
negf_vectors.F
Go to the documentation of this file.
1 !--------------------------------------------------------------------------------------------------!
2 ! CP2K: A general program to perform molecular dynamics simulations !
3 ! Copyright 2000-2024 CP2K developers group <https://cp2k.org> !
4 ! !
5 ! SPDX-License-Identifier: GPL-2.0-or-later !
6 !--------------------------------------------------------------------------------------------------!
7 
8 ! **************************************************************************************************
9 !> \brief Routines to deal with vectors in 3-D real space.
10 ! **************************************************************************************************
11 
13  USE kinds, ONLY: dp
14  USE particle_types, ONLY: particle_type
15  USE qs_subsys_types, ONLY: qs_subsys_get,&
16  qs_subsys_type
17 #include "./base/base_uses.f90"
18 
19  IMPLICIT NONE
20  PRIVATE
21 
22  CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'negf_vectors'
23 
25 
26 CONTAINS
27 
28 ! **************************************************************************************************
29 !> \brief compute direction vector of the given contact
30 !> \param origin origin
31 !> \param direction_vector direction vector
32 !> \param origin_bias origin which will be used to apply the external bias
33 !> (in contrast with 'origin' it does not include screening region)
34 !> \param direction_vector_bias direction vector which will be used to apply the external bias
35 !> (together with 'origin_bias' it defines a contact region where
36 !> the external potential is kept constant)
37 !> \param atomlist_screening atoms belonging to the contact's screening region
38 !> \param atomlist_bulk atoms belonging to the contact's bulk region
39 !> \param subsys QuickStep subsystem
40 !> \author Sergey Chulkov
41 ! **************************************************************************************************
42  SUBROUTINE contact_direction_vector(origin, direction_vector, origin_bias, direction_vector_bias, &
43  atomlist_screening, atomlist_bulk, subsys)
44  REAL(kind=dp), DIMENSION(3), INTENT(out) :: origin, direction_vector, origin_bias, &
45  direction_vector_bias
46  INTEGER, DIMENSION(:), INTENT(in) :: atomlist_screening, atomlist_bulk
47  TYPE(qs_subsys_type), POINTER :: subsys
48 
49  CHARACTER(LEN=*), PARAMETER :: routinen = 'contact_direction_vector'
50 
51  INTEGER :: handle, iatom, natoms_bulk, &
52  natoms_screening, nparticles
53  REAL(kind=dp) :: proj, proj_max, proj_min, proj_min_bias
54  REAL(kind=dp), DIMENSION(3) :: vector
55  TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
56 
57  CALL timeset(routinen, handle)
58  CALL qs_subsys_get(subsys, particle_set=particle_set)
59 
60  natoms_screening = SIZE(atomlist_screening)
61  natoms_bulk = SIZE(atomlist_bulk)
62  nparticles = SIZE(particle_set)
63 
64  cpassert(natoms_screening > 0)
65  cpassert(natoms_bulk > 0)
66  cpassert(nparticles > 0)
67 
68  ! geometrical centre of the first contact unit cell
69  origin = particle_set(atomlist_screening(1))%r
70  DO iatom = 2, natoms_screening
71  origin = origin + particle_set(atomlist_screening(iatom))%r
72  END DO
73  origin = origin/real(natoms_screening, kind=dp)
74 
75  ! geometrical centre of the second contact unit cell
76  direction_vector = particle_set(atomlist_bulk(1))%r
77  DO iatom = 2, natoms_bulk
78  direction_vector = direction_vector + particle_set(atomlist_bulk(iatom))%r
79  END DO
80  direction_vector = direction_vector/real(natoms_bulk, kind=dp)
81 
82  ! vector between the geometrical centers of the first and the second contact unit cells
83  direction_vector = direction_vector - origin
84 
85  ! the point 'center_of_coords0' belongs to the first unit cell, so the lowest projection of any point
86  ! from the first unit cell on the direction vector 'center_of_coords1 - center_of_coords0' should be <= 0
87  proj_min = 0.0_dp
88  proj_min_bias = 0.0_dp
89  DO iatom = 1, natoms_screening
90  vector = particle_set(atomlist_screening(iatom))%r - origin
91  proj = projection_on_direction_vector(vector, direction_vector)
92 
93  IF (proj < proj_min) proj_min = proj
94  IF (proj > proj_min_bias) proj_min_bias = proj
95  END DO
96 
97  ! the point 'center_of_coords1' belongs to the given contact, so the highest projection should be >= 1
98  proj_max = 1.0_dp
99  DO iatom = 1, nparticles
100  vector = particle_set(iatom)%r - origin
101  proj = projection_on_direction_vector(vector, direction_vector)
102 
103  IF (proj > proj_max) proj_max = proj
104  END DO
105 
106  ! adjust the origin, so it lies on a plane between the given contact and the scattering region
107  origin_bias = origin + proj_min_bias*direction_vector
108  origin = origin + proj_min*direction_vector
109 
110  ! rescale the vector, so the last atom of the given contact and the point 'origin + direction_vector' lie on
111  ! the same plane parallel to the 'origin' plane -- which separates the contact from the scattering region.
112  direction_vector_bias = (proj_max - proj_min_bias)*direction_vector
113  direction_vector = (proj_max - proj_min)*direction_vector
114 
115  CALL timestop(handle)
116  END SUBROUTINE contact_direction_vector
117 
118 ! **************************************************************************************************
119 !> \brief project the 'vector' onto the direction 'vector0'. Both vectors should have the same origin.
120 !> \param vector vector to project
121 !> \param vector0 direction vector
122 !> \return projection (in terms of the direction vector's length)
123 !> \author Sergey Chulkov
124 !> \note \parblock
125 !> & vector
126 !> /
127 !> /
128 !> /
129 !> *---|------> vector0
130 !> l = proj * | vector0 |
131 !>\endparblock
132 ! **************************************************************************************************
133  PURE FUNCTION projection_on_direction_vector(vector, vector0) RESULT(proj)
134  REAL(kind=dp), DIMENSION(3), INTENT(in) :: vector, vector0
135  REAL(kind=dp) :: proj
136 
137  REAL(kind=dp) :: len2, len2_v0, len2_v1
138  REAL(kind=dp), DIMENSION(3) :: vector1
139 
140  vector1 = vector - vector0
141  len2 = dot_product(vector, vector)
142  len2_v0 = dot_product(vector0, vector0)
143  len2_v1 = dot_product(vector1, vector1)
144 
145  proj = 0.5_dp*((len2 - len2_v1)/len2_v0 + 1.0_dp)
146  END FUNCTION projection_on_direction_vector
147 END MODULE negf_vectors
Defines the basic variable types.
Definition: kinds.F:23
integer, parameter, public dp
Definition: kinds.F:34
Routines to deal with vectors in 3-D real space.
Definition: negf_vectors.F:12
pure real(kind=dp) function, public projection_on_direction_vector(vector, vector0)
project the 'vector' onto the direction 'vector0'. Both vectors should have the same origin.
Definition: negf_vectors.F:134
subroutine, public contact_direction_vector(origin, direction_vector, origin_bias, direction_vector_bias, atomlist_screening, atomlist_bulk, subsys)
compute direction vector of the given contact
Definition: negf_vectors.F:44
Define the data structure for the particle information.
types that represent a quickstep subsys
subroutine, public qs_subsys_get(subsys, atomic_kinds, atomic_kind_set, particles, particle_set, local_particles, molecules, molecule_set, molecule_kinds, molecule_kind_set, local_molecules, para_env, colvar_p, shell_particles, core_particles, gci, multipoles, natom, nparticle, ncore, nshell, nkind, atprop, virial, results, cell, cell_ref, use_ref_cell, energy, force, qs_kind_set, cp_subsys, nelectron_total, nelectron_spin)
...