Octopus
orbitalset.F90
Go to the documentation of this file.
1!! Copyright (C) 2016 N. Tancogne-Dejean
2!!
3!! This program is free software; you can redistribute it and/or modify
4!! it under the terms of the GNU General Public License as published by
5!! the Free Software Foundation; either version 2, or (at your option)
6!! any later version.
7!!
8!! This program is distributed in the hope that it will be useful,
9!! but WITHOUT ANY WARRANTY; without even the implied warranty of
10!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11!! GNU General Public License for more details.
12!!
13!! You should have received a copy of the GNU General Public License
14!! along with this program; if not, write to the Free Software
15!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16!! 02110-1301, USA.
17!!
18
19#include "global.h"
20
22 use accel_oct_m
23 use batch_oct_m
25 use blas_oct_m
26 use debug_oct_m
28 use global_oct_m
30 use ions_oct_m
33 use math_oct_m
34 use mesh_oct_m
41 use types_oct_m
43
44 implicit none
45
46 private
47
48 public :: &
65
66 type orbitalset_t
67 ! Components are public by default
68 integer :: nn, ll, ii
69 real(real64) :: jj
70 integer :: norbs
71 integer :: ndim
72 integer :: iatom
73 type(submesh_t) :: sphere
74 complex(real64), allocatable :: phase(:,:)
75 ! !< if the sphere cross the border of the box
76 real(real64) :: Ueff
77 real(real64) :: Ubar, Jbar
78 real(real64) :: alpha
79 integer :: nneighbors
80 ! !< interaction is considered
81 real(real64), allocatable :: V_ij(:,:)
82 real(real64), allocatable :: coulomb_IIJJ(:,:,:,:,:)
83 complex(real64), allocatable :: zcoulomb_IIJJ(:,:,:,:,:,:,:)
84 integer, allocatable:: map_os(:)
85 complex(real64), allocatable :: phase_shift(:,:)
86
87 real(real64) :: radius
88 class(species_t), pointer :: spec => null()
89 integer :: spec_index
90
91 real(real64), allocatable :: dorb(:,:,:)
92 complex(real64), allocatable :: zorb(:,:,:)
93 complex(real64), allocatable :: eorb_submesh(:,:,:,:)
94 ! !! (for isolated system with TD phase)
95 complex(real64), allocatable :: eorb_mesh(:,:,:,:)
96 ! !! (for periodic systems GS and TD)
97 integer :: ldorbs, ldorbs_eorb
98 type(accel_mem_t) :: dbuff_orb, zbuff_orb
99 type(accel_mem_t), allocatable :: buff_eorb (:)
100
101 logical :: use_submesh
102 logical :: allocated_on_mesh
103 ! This stores how the localized orbitals (without phase) were allocated.
104 ! This is different from "use_submesh", which dictate how the orbitals (with phase) will be applied.
105
106 type(poisson_t) :: poisson
107 contains
108 procedure :: set_species_index => orbitalset_set_species_index
109 end type orbitalset_t
110
111contains
112
113 subroutine orbitalset_init(this)
114 type(orbitalset_t), intent(inout) :: this
115
117
118 this%iatom = -1
119 this%nneighbors = 0
120 this%nn = 0
121 this%ll = 0
122 this%jj = m_one
123 this%ii = 0
124 this%iatom = 0
125 this%ndim = 1
126 this%spec_index = 0
127 this%norbs = 0
128
129 this%Ueff = m_zero
130 this%Ubar = m_zero
131 this%Jbar = m_zero
132 this%alpha = m_zero
133 this%radius = m_zero
134
135 pop_sub(orbitalset_init)
136 end subroutine orbitalset_init
137
138
139 subroutine orbitalset_end(this)
140 type(orbitalset_t), intent(inout) :: this
141
142 integer :: ik
143
144 push_sub(orbitalset_end)
145
146 safe_deallocate_a(this%phase)
147 safe_deallocate_a(this%dorb)
148 safe_deallocate_a(this%zorb)
149 safe_deallocate_a(this%eorb_submesh)
150 safe_deallocate_a(this%eorb_mesh)
151 nullify(this%spec)
152 call submesh_end(this%sphere)
153
154 safe_deallocate_a(this%V_ij)
155 safe_deallocate_a(this%coulomb_IIJJ)
156 safe_deallocate_a(this%map_os)
157 safe_deallocate_a(this%phase_shift)
158
159 if(accel_is_enabled()) then
160 call accel_free_buffer(this%dbuff_orb)
161 call accel_free_buffer(this%zbuff_orb)
162 if(allocated(this%buff_eorb)) then
163 do ik = lbound(this%buff_eorb, dim=1), ubound(this%buff_eorb, dim=1)
164 call accel_free_buffer(this%buff_eorb(ik))
165 end do
166 safe_deallocate_a(this%buff_eorb)
167 end if
168 end if
170 pop_sub(orbitalset_end)
171 end subroutine orbitalset_end
173 subroutine orbitalset_set_jln(this, jj, ll, nn)
174 type(orbitalset_t), intent(inout) :: this
175 real(real64), intent(in) :: jj
176 integer, intent(in) :: ll, nn
180 this%jj = jj
181 this%ll = ll
182 this%nn = nn
185 end subroutine orbitalset_set_jln
189 subroutine orbitalset_update_phase(os, dim, kpt, kpoints, spin_polarized, vec_pot, vec_pot_var, kpt_max)
190 type(orbitalset_t), intent(inout) :: os
191 integer, intent(in) :: dim
192 type(distributed_t), intent(in) :: kpt
193 type(kpoints_t), intent(in) :: kpoints
194 logical, intent(in) :: spin_polarized
195 real(real64), optional, allocatable, intent(in) :: vec_pot(:)
196 real(real64), optional, allocatable, intent(in) :: vec_pot_var(:, :)
197 integer, optional, intent(in) :: kpt_max
198
199 integer :: ns, iq, is, ikpoint, im, idim, kpt_end
200 real(real64) :: kr, kpoint(1:dim), dx(1:dim)
201 integer :: iorb
202
204
205 ns = os%sphere%np
206
207 kpt_end = kpt%end
208 if (present(kpt_max)) kpt_end = min(kpt_max, kpt_end)
209
210 do iq = kpt%start, kpt_end
211 !This is durty but avoids to refer to states_get_kpoint_index
212 if (spin_polarized) then
213 ikpoint = 1 + (iq - 1)/2
214 else
215 ikpoint = iq
216 end if
217
218 ! if this fails, it probably means that sb is not compatible with std
219 assert(ikpoint <= kpoints_number(kpoints))
220
221 kpoint(1:dim) = kpoints%get_point(ikpoint)
222
223 !$omp parallel do private(dx, kr)
224 do is = 1, ns
225 ! this is only the correction to the global phase, that can
226 ! appear if the sphere crossed the boundary of the cell.
227 dx = os%sphere%rel_x(1:dim, is) - os%sphere%mesh%x(1:dim, os%sphere%map(is)) + os%sphere%center(1:dim)
228 kr = dot_product(kpoint, dx)
229 if (present(vec_pot)) then
230 if (allocated(vec_pot)) kr = kr + dot_product(vec_pot, dx)
231 end if
232
233 if (present(vec_pot_var)) then
234 if (allocated(vec_pot_var)) kr = kr + sum(vec_pot_var(1:dim, os%sphere%map(is)) &
235 *(os%sphere%rel_x(1:dim, is)+os%sphere%center))
236 end if
237
238 os%phase(is, iq) = exp(m_zi*kr)
239 end do
240
241 if (.not. os%use_submesh) then
242 ! We now compute the so-called Bloch sum of the localized orbitals
243 do idim = 1, os%ndim
244 do im = 1, os%norbs
245 os%eorb_mesh(:, im, idim, iq) = m_z0
246 do is = 1, ns
247 os%eorb_mesh(os%sphere%map(is),im,idim,iq) = os%eorb_mesh(os%sphere%map(is),im,idim,iq) &
248 + os%zorb(is, idim, im) * os%phase(is, iq)
249 end do
250 end do
251 end do
252 else ! In the case of the isolated system, we still use the submesh
253 !$omp parallel private(idim, is)
254 do im = 1, os%norbs
255 do idim = 1, os%ndim
256 !$omp do simd
257 do is = 1, ns
258 os%eorb_submesh(is,idim,im,iq) = os%zorb(is,idim,im)*os%phase(is, iq)
259 end do
260 !$omp end do simd
261 end do
262 end do
263 !$omp end parallel
264 end if
265
266 if(accel_is_enabled() .and. os%ndim == 1) then
267 if(os%use_submesh) then
268 do iorb = 1, os%norbs
269 call accel_write_buffer(os%buff_eorb(iq), ns, os%eorb_submesh(:, 1, iorb, iq), offset = (iorb - 1)*os%ldorbs_eorb)
270 end do
271 else
272 do iorb = 1, os%norbs
273 call accel_write_buffer(os%buff_eorb(iq), os%sphere%mesh%np, &
274 os%eorb_mesh(:, iorb, 1, iq), offset = (iorb - 1)*os%ldorbs_eorb)
275 end do
276 end if
277 end if
278 end do
279
281 end subroutine orbitalset_update_phase
282
283
285 subroutine orbitalset_update_phase_shift(os, dim, kpt, kpoints, spin_polarized, vec_pot, vec_pot_var, kpt_max)
286 type(orbitalset_t), intent(inout) :: os
287 integer, intent(in) :: dim
288 type(distributed_t), intent(in) :: kpt
289 type(kpoints_t), intent(in) :: kpoints
290 logical, intent(in) :: spin_polarized
291 real(real64), optional, allocatable, intent(in) :: vec_pot(:)
292 real(real64), optional, allocatable, intent(in) :: vec_pot_var(:, :)
293 integer, optional, intent(in) :: kpt_max
294
295 integer :: iq, ikpoint
296 real(real64) :: kr, kpoint(dim), dx(dim)
297 integer :: inn, kpt_end
298
300
301 kpt_end = kpt%end
302 if(present(kpt_max)) kpt_end = min(kpt_max, kpt_end)
303
304 do iq = kpt%start, kpt_end
305 !This is durty but avoids to refer to states_get_kpoint_index
306 if(spin_polarized) then
307 ikpoint = 1 + (iq - 1)/2
308 else
309 ikpoint = iq
310 end if
311
312 ! if this fails, it probably means that sb is not compatible with std
313 assert(ikpoint <= kpoints_number(kpoints))
314
315 kpoint(1:dim) = kpoints%get_point(ikpoint)
316
317 if (os%nneighbors > 0) then
318 do inn = 1, os%nneighbors
319 dx(1:dim) = os%V_ij(inn,1:dim)
320 kr = sum(kpoint(1:dim)*dx(1:dim))
321 if (present(vec_pot)) then
322 if (allocated(vec_pot)) kr = kr + sum(vec_pot(1:dim)*dx(1:dim))
323 end if
324
325 !At the moment the uniform vector potential is in vec_pot_var
326 if (present(vec_pot_var)) then
327 if (allocated(vec_pot_var)) kr = kr + sum(vec_pot_var(1:dim, 1)*dx(1:dim))
328 end if
329
330 !The sign is different as this is applied on the wavefunction and not the orbitals
331 os%phase_shift(inn, iq) = exp(-m_zi*kr)
332 end do
333 end if
334 end do
335
336
338 end subroutine orbitalset_update_phase_shift
339
340 ! ---------------------------------------------------------
346 subroutine orbitalset_set_species_index(os, ions)
347 class(orbitalset_t), intent(inout) :: os
348 type(ions_t), intent(in) :: ions
349
350 integer :: ja
351
353
354 os%spec_index = os%spec%get_index()
355 do ja = 1, ions%natoms
356 if(ions%atom(ja)%species == os%spec) then
357 os%spec_index = min(os%spec_index, ions%atom(ja)%species%get_index())
358 end if
359 end do
360
362 end subroutine orbitalset_set_species_index
363
364#include "undef.F90"
365#include "real.F90"
366#include "orbitalset_inc.F90"
367
368#include "undef.F90"
369#include "complex.F90"
370#include "orbitalset_inc.F90"
371
372end module orbitalset_oct_m
double exp(double __x) __attribute__((__nothrow__
subroutine, public accel_free_buffer(this, async)
Definition: accel.F90:1006
pure logical function, public accel_is_enabled()
Definition: accel.F90:403
This module implements batches of mesh functions.
Definition: batch.F90:135
This module implements common operations on batches of mesh functions.
Definition: batch_ops.F90:118
This module contains interfaces for BLAS routines You should not use these routines directly....
Definition: blas.F90:120
real(real64), parameter, public m_zero
Definition: global.F90:200
complex(real64), parameter, public m_z0
Definition: global.F90:210
complex(real64), parameter, public m_zi
Definition: global.F90:214
real(real64), parameter, public m_one
Definition: global.F90:201
integer pure function, public kpoints_number(this)
Definition: kpoints.F90:1213
This module is intended to contain "only mathematical" functions and procedures.
Definition: math.F90:117
This module defines various routines, operating on mesh functions.
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:120
subroutine, public zorbitalset_get_position_matrix_elem(os, ndim, psib, idir, dot)
subroutine, public orbitalset_update_phase_shift(os, dim, kpt, kpoints, spin_polarized, vec_pot, vec_pot_var, kpt_max)
Build the phase shift for the intersite interaction.
Definition: orbitalset.F90:381
subroutine orbitalset_set_species_index(os, ions)
Set the species index for a given orbital set.
Definition: orbitalset.F90:442
subroutine, public orbitalset_init(this)
Definition: orbitalset.F90:209
subroutine, public orbitalset_end(this)
Definition: orbitalset.F90:235
subroutine, public dorbitalset_transfer_to_device(os, kpt, use_mesh)
Allocate and transfer the orbitals to the device.
subroutine, public dorbitalset_add_to_batch(os, ndim, psib, weight)
Definition: orbitalset.F90:864
subroutine, public dorbitalset_get_position_matrix_elem(os, ndim, psib, idir, dot)
subroutine, public zorbitalset_add_to_batch(os, ndim, psib, weight)
subroutine, public orbitalset_update_phase(os, dim, kpt, kpoints, spin_polarized, vec_pot, vec_pot_var, kpt_max)
Build the phase correction to the global phase in case the orbital crosses the border of the simulato...
Definition: orbitalset.F90:285
subroutine, public dorbitalset_get_coefficients(os, ndim, psi, ik, has_phase, dot, reduce)
Definition: orbitalset.F90:527
subroutine, public dorbitalset_get_coeff_batch(os, ndim, psib, dot, reduce)
Definition: orbitalset.F90:589
subroutine, public orbitalset_set_jln(this, jj, ll, nn)
Definition: orbitalset.F90:269
subroutine, public zorbitalset_get_coeff_batch(os, ndim, psib, dot, reduce)
subroutine, public zorbitalset_transfer_to_device(os, kpt, use_mesh)
Allocate and transfer the orbitals to the device.
subroutine, public zorbitalset_get_coefficients(os, ndim, psi, ik, has_phase, dot, reduce)
subroutine, public submesh_end(this)
Definition: submesh.F90:677
Distribution of N instances over mpi_grpsize processes, for the local rank mpi_grprank....