Octopus
nonlocal_pseudopotential.F90
Go to the documentation of this file.
1!! Copyright (C) 2009 X. Andrade
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
24 use batch_oct_m
26 use blas_oct_m
27 use debug_oct_m
29 use epot_oct_m
30 use global_oct_m
35 use math_oct_m
36 use mesh_oct_m
38 use mpi_oct_m
42 use ps_oct_m
44 use space_oct_m
48 use types_oct_m
50
51 implicit none
52
53 private
54
55 public :: &
60
64 private
65 type(projector_matrix_t), allocatable, public :: projector_matrices(:)
66 integer, public :: nprojector_matrices
67 logical, public :: apply_projector_matrices
68 logical, public :: has_non_local_potential
69 integer :: full_projection_size
70 integer, public :: max_npoints
71 integer, public :: total_points
72 integer :: max_nprojs
73 logical :: projector_mix
74 complex(real64), allocatable, public :: projector_phases(:, :, :, :)
75 integer, allocatable, public :: projector_to_atom(:)
76 integer :: nregions
77 integer, allocatable :: regions(:)
78 integer, public :: nphase
83 type(accel_mem_t) :: buff_offsets
84 type(accel_mem_t) :: buff_matrices
85 type(accel_mem_t) :: buff_maps
86 type(accel_mem_t) :: buff_sphere_weights
87 type(accel_mem_t) :: buff_scals
88 type(accel_mem_t) :: buff_position
89 type(accel_mem_t) :: buff_pos
90 type(accel_mem_t) :: buff_invmap
91 type(accel_mem_t) :: buff_invmap_mat
92 type(accel_mem_t) :: buff_point_to_mat
93 type(accel_mem_t) :: buff_proj_to_mat
94 type(accel_mem_t), public :: buff_projector_phases
95 type(accel_mem_t), pointer, public :: buff_bra_phasepsi => null()
96 type(accel_mem_t), pointer, public :: buff_bra_projection_temp => null()
97 type(accel_mem_t) :: buff_mix
98 logical :: projector_self_overlap
99 real(real64), pointer, public :: spin(:,:,:) => null()
100 contains
101
102 procedure :: init => nonlocal_pseudopotential_init
103
104 procedure :: build => nonlocal_pseudopotential_build_proj
105
106 procedure :: end => nonlocal_pseudopotential_destroy_proj
107
108 procedure :: has_self_overlap => nonlocal_pseudopotential_self_overlap
109
110 procedure :: dstart => dnonlocal_pseudopotential_start
111
112 procedure :: zstart => znonlocal_pseudopotential_start
113
114 procedure :: dfinish => dnonlocal_pseudopotential_finish
115
116 procedure :: zfinish => znonlocal_pseudopotential_finish
117
118 procedure :: dforce => dnonlocal_pseudopotential_force
119
120 procedure :: zforce => znonlocal_pseudopotential_force
121
122 procedure :: dposition_commutator => dnonlocal_pseudopotential_position_commutator
123
124 procedure :: zposition_commutator => znonlocal_pseudopotential_position_commutator
125
126 procedure :: dr_vn_local => dnonlocal_pseudopotential_r_vnlocal
127
128 procedure :: zr_vn_local => znonlocal_pseudopotential_r_vnlocal
129
131
132
134 !
135 type projection_t
136 private
137 real(real64), allocatable :: dprojection(:, :)
138 complex(real64), allocatable :: zprojection(:, :)
139 type(accel_mem_t) :: buff_projection
140 type(accel_mem_t) :: buff_spin_to_phase
141 integer :: cuda_stream_projection_DtH
142 end type projection_t
143
144contains
145
146 ! ---------------------------------------------------------
149 subroutine nonlocal_pseudopotential_init(this)
150 class(nonlocal_pseudopotential_t), intent(inout) :: this
151
153
154 this%apply_projector_matrices = .false.
155 this%has_non_local_potential = .false.
156 this%nprojector_matrices = 0
157
158 this%projector_self_overlap = .false.
159
163 ! ---------------------------------------------------------
169 class(nonlocal_pseudopotential_t), target, intent(inout) :: this
170 type(epot_t), target, intent(in) :: epot
172 integer :: imat, iatom
173 type(projector_matrix_t), pointer :: pmat
174
176
177 ! After the assignment these still point to the buffers of the source: drop them, do not free them
178 nullify(this%buff_bra_phasepsi)
179 nullify(this%buff_bra_projection_temp)
180 safe_allocate(this%buff_bra_phasepsi)
181 safe_allocate(this%buff_bra_projection_temp)
183 if (.not. allocated(this%projector_matrices) .or. this%nprojector_matrices == 0) then
185 return
186 end if
188 assert(allocated(this%projector_to_atom))
189 assert(size(this%projector_matrices) >= this%nprojector_matrices)
190 assert(size(this%projector_to_atom) >= this%nprojector_matrices)
192 do imat = 1, this%nprojector_matrices
193 pmat => this%projector_matrices(imat)
194 iatom = this%projector_to_atom(imat)
195
196 assert(iatom >= 1 .and. iatom <= epot%natoms)
197 assert(allocated(epot%proj))
198 assert(allocated(epot%proj(iatom)%sphere%map))
199 assert(allocated(epot%proj(iatom)%sphere%rel_x))
200
201 pmat%map => epot%proj(iatom)%sphere%map
202 pmat%position => epot%proj(iatom)%sphere%rel_x
203 end do
204
208
210 !--------------------------------------------------------
213 class(nonlocal_pseudopotential_t), intent(inout) :: this
214
215 integer :: iproj
216
218
219 if (allocated(this%projector_matrices)) then
220
222 call accel_free_buffer(this%buff_offsets)
223 call accel_free_buffer(this%buff_matrices)
224 call accel_free_buffer(this%buff_maps)
225 if (accel_buffer_is_allocated(this%buff_sphere_weights)) call accel_free_buffer(this%buff_sphere_weights)
226 call accel_free_buffer(this%buff_scals)
227 call accel_free_buffer(this%buff_position)
228 call accel_free_buffer(this%buff_pos)
229 call accel_free_buffer(this%buff_invmap)
230 call accel_free_buffer(this%buff_invmap_mat)
231 call accel_free_buffer(this%buff_point_to_mat)
232 call accel_free_buffer(this%buff_proj_to_mat)
233 if (this%projector_mix) call accel_free_buffer(this%buff_mix)
234 if (allocated(this%projector_phases)) call accel_free_buffer(this%buff_projector_phases)
235 end if
237 do iproj = 1, this%nprojector_matrices
238 call projector_matrix_deallocate(this%projector_matrices(iproj))
239 end do
240 safe_deallocate_a(this%regions)
241 safe_deallocate_a(this%projector_matrices)
242 safe_deallocate_a(this%projector_phases)
243 safe_deallocate_a(this%projector_to_atom)
244 end if
245
246 if (associated(this%buff_bra_phasepsi)) then
247 if (accel_buffer_is_allocated(this%buff_bra_phasepsi)) call accel_free_buffer(this%buff_bra_phasepsi)
248 end if
249 if (associated(this%buff_bra_projection_temp)) then
250 if (accel_buffer_is_allocated(this%buff_bra_projection_temp)) call accel_free_buffer(this%buff_bra_projection_temp)
251 end if
252 safe_deallocate_p(this%buff_bra_phasepsi)
253 safe_deallocate_p(this%buff_bra_projection_temp)
254
257
258 !-----------------------------------------------------------------
264 !
265 subroutine nonlocal_pseudopotential_build_proj(this, space, mesh, epot)
266 class(nonlocal_pseudopotential_t), target, intent(inout) :: this
267 class(space_t), intent(in) :: space
268 class(mesh_t), intent(in) :: mesh
269 type(epot_t), target, intent(in) :: epot
270
271 integer :: iatom, iproj, ll, lmax, lloc, mm, ic, jc
272 integer :: nmat, imat, ip, iorder
273 integer :: nregion, jatom, katom, iregion
274 integer, allocatable :: order(:), head(:), region_count(:)
275 logical, allocatable :: atom_counted(:)
276 logical :: overlap
277 type(projector_matrix_t), pointer :: pmat
278 type(kb_projector_t), pointer :: kb_p
279 type(rkb_projector_t), pointer :: rkb_p
280 type(hgh_projector_t), pointer :: hgh_p
281
283
284 call profiling_in("ATOM_COLORING")
285
286 ! this is most likely a very inefficient algorithm, O(natom**2) or
287 ! O(natom**3), probably it should be replaced by something better.
288
289 safe_allocate(order(1:epot%natoms)) ! order(iregion) = ?
290 safe_allocate(head(1:epot%natoms + 1)) ! head(iregion) points to the first atom in region iregion
291 safe_allocate(region_count(1:epot%natoms)) ! region_count(iregion): number of atoms in that region
292 safe_allocate(atom_counted(1:epot%natoms))
293
294 this%projector_self_overlap = .false.
295 atom_counted = .false.
296 order = -1
297
298 head(1) = 1
299 nregion = 0
300 do
301 nregion = nregion + 1
302 assert(nregion <= epot%natoms)
303
304 region_count(nregion) = 0
305
306 do iatom = 1, epot%natoms
307 if (atom_counted(iatom)) cycle
308
309 overlap = .false.
310
311 if (.not. projector_is(epot%proj(iatom), proj_none)) then
312 assert(associated(epot%proj(iatom)%sphere%mesh))
313 do jatom = 1, region_count(nregion)
314 katom = order(head(nregion) + jatom - 1)
315 if (projector_is(epot%proj(katom), proj_none)) cycle
316 overlap = submesh_overlap(epot%proj(iatom)%sphere, epot%proj(katom)%sphere, space)
317 if (overlap) exit
318 end do
319 end if
320
321 if (.not. overlap) then
322 ! iatom did not overlap with any previously counted atoms:
323 ! iatom will be added to the current region
324 region_count(nregion) = region_count(nregion) + 1
325 order(head(nregion) - 1 + region_count(nregion)) = iatom
326 atom_counted(iatom) = .true.
327 end if
328
329 end do
330
331 head(nregion + 1) = head(nregion) + region_count(nregion)
332
333 if (all(atom_counted)) exit
334 end do
335
336 safe_deallocate_a(atom_counted)
337 safe_deallocate_a(region_count)
338
339 call messages_write('The atoms can be separated in ')
340 call messages_write(nregion)
341 call messages_write(' non-overlapping groups.')
342 call messages_info(debug_only=.true.)
343
344 do iregion = 1, nregion
345 do iatom = head(iregion), head(iregion + 1) - 1
346 if (.not. projector_is(epot%proj(order(iatom)), proj_kb)) cycle
347 do jatom = head(iregion), iatom - 1
348 if (.not. projector_is(epot%proj(order(jatom)), proj_kb)) cycle
349 assert(.not. submesh_overlap(epot%proj(order(iatom))%sphere, epot%proj(order(jatom))%sphere, space))
350 end do
351 end do
352 end do
353
354 call profiling_out("ATOM_COLORING")
355
356 ! deallocate previous projectors
357 call this%end()
358
359 ! The two bra scratch buffers. They are pointers so that
360 ! X(nonlocal_pseudopotential_start), whose `this` is intent(in), can fill them.
361 safe_allocate(this%buff_bra_phasepsi)
362 safe_allocate(this%buff_bra_projection_temp)
363
364 ! count projectors
365 this%nprojector_matrices = 0
366 this%apply_projector_matrices = .false.
367 this%has_non_local_potential = .false.
368 this%nregions = nregion
369
370 !We determine if we have only local potential or not.
371 do iorder = 1, epot%natoms
372 iatom = order(iorder)
373
374 if (.not. projector_is_null(epot%proj(iatom))) then
375 this%has_non_local_potential = .true.
376 exit
377 end if
378 end do
379
380 do iorder = 1, epot%natoms
381 iatom = order(iorder)
382
383 if (.not. projector_is_null(epot%proj(iatom))) then
384 this%nprojector_matrices = this%nprojector_matrices + 1
385 this%apply_projector_matrices = .true.
386 end if
387 end do
388
389 ! This is currently the only not supported case
390 if (mesh%use_curvilinear) this%apply_projector_matrices = .false.
391
392 if (.not. this%apply_projector_matrices) then
393 safe_deallocate_a(order)
394 safe_deallocate_a(head)
395
397 return
398 end if
399
400
401 safe_allocate(this%projector_matrices(1:this%nprojector_matrices))
402 safe_allocate(this%regions(1:this%nregions + 1))
403 safe_allocate(this%projector_to_atom(1:epot%natoms))
404
405 this%full_projection_size = 0
406 this%regions(this%nregions + 1) = this%nprojector_matrices + 1
407
408 this%projector_mix = .false.
409
410 iproj = 0
411 do iregion = 1, this%nregions
412 this%regions(iregion) = iproj + 1
413 do iorder = head(iregion), head(iregion + 1) - 1
414
415 iatom = order(iorder)
416
417 if (projector_is(epot%proj(iatom), proj_none)) cycle
418
419 iproj = iproj + 1
420
421 pmat => this%projector_matrices(iproj)
422
423 this%projector_to_atom(iproj) = iatom
424
425 lmax = epot%proj(iatom)%lmax
426 lloc = epot%proj(iatom)%lloc
427
428 if (projector_is(epot%proj(iatom), proj_kb)) then
429
430 ! count the number of projectors for this matrix
431 nmat = 0
432 do ll = 0, lmax
433 if (ll == lloc) cycle
434 do mm = -ll, ll
435 nmat = nmat + epot%proj(iatom)%kb_p(ll, mm)%n_c
436 end do
437 end do
438
439 call projector_matrix_allocate(pmat, nmat, epot%proj(iatom)%sphere, has_mix_matrix = .false.)
440
441 ! generate the matrix
442 pmat%dprojectors = m_zero
443 imat = 1
444 do ll = 0, lmax
445 if (ll == lloc) cycle
446 do mm = -ll, ll
447 kb_p => epot%proj(iatom)%kb_p(ll, mm)
448 do ic = 1, kb_p%n_c
449 call lalg_copy(pmat%npoints, kb_p%p(:, ic), pmat%dprojectors(:, imat))
450 ! the per-point part of the volume element is applied on the bra
451 ! side (sphere_weights) for meshes with per-point volumes
452 pmat%scal(imat) = kb_p%e(ic)*mesh%volume_element
453 imat = imat + 1
454 end do
455 end do
456 end do
457
458 this%projector_self_overlap = this%projector_self_overlap .or. epot%proj(iatom)%sphere%overlap
459
460 else if (projector_is(epot%proj(iatom), proj_hgh)) then
461
462 this%projector_mix = .true.
463
464 ! count the number of projectors for this matrix
465 nmat = 0
466 do ll = 0, lmax
467 if (ll == lloc) cycle
468 do mm = -ll, ll
469 nmat = nmat + 3
470 end do
471 end do
472
473 call projector_matrix_allocate(pmat, nmat, epot%proj(iatom)%sphere, &
474 has_mix_matrix = .true., is_cmplx = (epot%proj_reltype == spin_orbit))
475
476 ! generate the matrix
477 if (epot%proj_reltype == spin_orbit) then
478 pmat%zprojectors = m_zero
479 pmat%zmix = m_zero
480 else
481 pmat%dprojectors = m_zero
482 pmat%dmix = m_zero
483 end if
484
485 imat = 1
486 do ll = 0, lmax
487 if (ll == lloc) cycle
488 do mm = -ll, ll
489 hgh_p => epot%proj(iatom)%hgh_p(ll, mm)
490
491 ! HGH pseudos mix different components, so we need to
492 ! generate a matrix that mixes the projections
493 if (epot%proj_reltype == spin_orbit) then
494 do ic = 1, 3
495 do jc = 1, 3
496 pmat%zmix(imat - 1 + ic, imat - 1 + jc, 1) = hgh_p%h(ic, jc) + m_half*mm*hgh_p%k(ic, jc)
497 pmat%zmix(imat - 1 + ic, imat - 1 + jc, 2) = hgh_p%h(ic, jc) - m_half*mm*hgh_p%k(ic, jc)
498
499 if (mm < ll) then
500 pmat%zmix(imat - 1 + ic, imat + 3 - 1 + jc, 3) = m_half*hgh_p%k(ic, jc) * &
501 sqrt(real(ll*(ll+1)-mm*(mm+1), real64))
502 end if
503
504 if (-mm < ll) then
505 pmat%zmix(imat - 1 + ic, imat - 3 - 1 + jc, 4) = m_half*hgh_p%k(ic, jc) * &
506 sqrt(real(ll*(ll+1)-mm*(mm-1), real64))
507 end if
508 end do
509 end do
510 else
511 do ic = 1, 3
512 do jc = 1, 3
513 pmat%dmix(imat - 1 + ic, imat - 1 + jc) = hgh_p%h(ic, jc)
514 end do
515 end do
516 end if
517
518 do ic = 1, 3
519 if (epot%proj_reltype == spin_orbit) then
520 call lalg_copy(pmat%npoints, hgh_p%zp(:, ic), pmat%zprojectors(:, imat))
521 else
522 call lalg_copy(pmat%npoints, hgh_p%dp(:, ic), pmat%dprojectors(:, imat))
523 end if
524 pmat%scal(imat) = mesh%volume_element
525 imat = imat + 1
526 end do
527
528 end do
529 end do
530
531 this%projector_self_overlap = this%projector_self_overlap .or. epot%proj(iatom)%sphere%overlap
532
533 else if (projector_is(epot%proj(iatom), proj_rkb)) then
534 assert(epot%proj_reltype == spin_orbit)
535
536 this%projector_mix = .true.
537
538 ! count the number of projectors for this matrix
539 nmat = 0
540 if (lloc /= 0) nmat = nmat + epot%proj(iatom)%kb_p(1, 1)%n_c
541
542 do ll = 1, lmax
543 if (ll == lloc) cycle
544 do mm = -ll, ll
545 nmat = nmat + epot%proj(iatom)%rkb_p(ll, mm)%n_c
546 end do
547 end do
548
549 call projector_matrix_allocate(pmat, nmat, epot%proj(iatom)%sphere, &
550 has_mix_matrix = .true., is_cmplx = .true.)
551
552 pmat%zprojectors = m_zero
553 pmat%zmix = m_zero
554
555 imat = 1
556 if (lloc /= 0) then
557 kb_p => epot%proj(iatom)%kb_p(1, 1)
558
559 do ic = 1, kb_p%n_c
560 pmat%zmix(ic, ic, 1:2) = kb_p%e(ic)
561 do ip = 1, pmat%npoints
562 pmat%zprojectors(ip, ic) = kb_p%p(ip, ic)
563 end do
564 pmat%scal(ic) = mesh%volume_element
565 end do
566 imat = kb_p%n_c + 1
567 nullify(kb_p)
568 end if
569
570 do ll = 1, lmax
571 if (ll == lloc) cycle
572 do mm = -ll, ll
573 rkb_p => epot%proj(iatom)%rkb_p(ll, mm)
574
575 ! See rkb_projector.F90 for understanding the indices
576 do ic = 0, rkb_p%n_c/2-1
577 pmat%zmix(imat + ic*2, imat + ic*2, 1) = rkb_p%f(ic*2+1, 1, 1)
578 pmat%zmix(imat + ic*2, imat + ic*2, 2) = rkb_p%f(ic*2+1, 2, 2)
579
580 pmat%zmix(imat + ic*2+1, imat + ic*2+1, 1) = rkb_p%f(ic*2+2, 1, 1)
581 pmat%zmix(imat + ic*2+1, imat + ic*2+1, 2) = rkb_p%f(ic*2+2, 2, 2)
582
583 if (mm < ll) then
584 pmat%zmix(imat + ic*2+rkb_p%n_c, imat + ic*2, 4) = rkb_p%f(ic*2+1, 2, 1)
585 pmat%zmix(imat + ic*2+1+rkb_p%n_c, imat + ic*2+1, 4) = rkb_p%f(ic*2+2, 2, 1)
586 end if
587
588 if (-mm < ll) then
589 pmat%zmix(imat + ic*2-rkb_p%n_c, imat + ic*2, 3) = rkb_p%f(ic*2+1, 1, 2)
590 pmat%zmix(imat + ic*2+1-rkb_p%n_c, imat + ic*2+1, 3) = rkb_p%f(ic*2+2, 1, 2)
591 end if
592 end do
593
594 do ic = 1, rkb_p%n_c
595 call lalg_copy(pmat%npoints, rkb_p%ket(:, ic, 1, 1), pmat%zprojectors(:, imat))
596 pmat%scal(imat) = mesh%volume_element
597 imat = imat + 1
598 end do
599 end do
600
601 nullify(rkb_p)
602 end do
603
604 this%projector_self_overlap = this%projector_self_overlap .or. epot%proj(iatom)%sphere%overlap
605
606 else
607 cycle
608 end if
609
610 pmat%map => epot%proj(iatom)%sphere%map
611 pmat%position => epot%proj(iatom)%sphere%rel_x
612
613 pmat%regions = epot%proj(iatom)%sphere%regions
614
615 this%full_projection_size = this%full_projection_size + pmat%nprojs
616
617 ! the per-point volume weights of the sphere, applied to the bra side
618 if (mesh%use_vol_pp) then
619 safe_allocate(pmat%sphere_weights(1:max(pmat%npoints, 1)))
620 do ip = 1, pmat%npoints
621 pmat%sphere_weights(ip) = mesh%vol_pp(pmat%map(ip))
622 end do
623 end if
624
625 end do
626 end do
627
628 if (mesh%parallel_in_domains) then
629 call mesh%mpi_grp%allreduce_inplace(this%projector_self_overlap, 1, mpi_logical, mpi_lor)
630 end if
631
632 safe_deallocate_a(order)
633 safe_deallocate_a(head)
634
635 this%total_points = 0
636 this%max_npoints = 0
637 this%max_nprojs = 0
638 do imat = 1, this%nprojector_matrices
639 pmat => this%projector_matrices(imat)
640
641 this%max_npoints = max(this%max_npoints, pmat%npoints)
642 this%max_nprojs = max(this%max_nprojs, pmat%nprojs)
643 this%total_points = this%total_points + pmat%npoints
644 end do
645
646 if (accel_is_enabled()) then
649 end if
650
652
654
655 ! ----------------------------------------------------------------------------------
657 subroutine nonlocal_pseudopotential_accel_rebuild(this, space, mesh)
658 class(nonlocal_pseudopotential_t), target, intent(inout) :: this
659 class(space_t), intent(in) :: space
660 class(mesh_t), intent(in) :: mesh
661
663
664 if (.not. accel_is_enabled()) then
666 return
667 end if
668
670
671 if (.not. allocated(this%projector_matrices) .or. this%nprojector_matrices <= 0) then
673 return
674 end if
675
678
681
682 ! ----------------------------------------------------------------------------------
685 class(nonlocal_pseudopotential_t), intent(inout) :: this
686
688
689 call accel_detach_buffer(this%buff_offsets)
690 call accel_detach_buffer(this%buff_matrices)
691 call accel_detach_buffer(this%buff_maps)
692 call accel_detach_buffer(this%buff_scals)
693 call accel_detach_buffer(this%buff_position)
694 call accel_detach_buffer(this%buff_pos)
695 call accel_detach_buffer(this%buff_invmap)
696 call accel_detach_buffer(this%buff_invmap_mat)
697 call accel_detach_buffer(this%buff_point_to_mat)
698 call accel_detach_buffer(this%buff_proj_to_mat)
699 call accel_detach_buffer(this%buff_projector_phases)
700 call accel_detach_buffer(this%buff_mix)
701
704
705 ! ----------------------------------------------------------------------------------
707 subroutine nonlocal_pseudopotential_build_accel_buffers(this, space, mesh)
708 class(nonlocal_pseudopotential_t), target, intent(inout) :: this
709 class(space_t), intent(in) :: space
710 class(mesh_t), intent(in) :: mesh
711
712 integer, parameter :: OFFSET_SIZE = 6
713 integer, parameter :: POINTS = 1, projs = 2, matrix = 3, map = 4, scal = 5, mix = 6
714 integer :: imat, matrix_size, scal_size
715 integer :: ip, is, ii, ipos, mix_offset
716 integer, allocatable :: cnt(:), invmap(:, :), invmap2(:), pos(:)
717 integer, allocatable :: invmap_mat(:, :), invmap_mat2(:)
718 integer, allocatable :: offsets(:, :), point_to_mat(:), proj_to_mat(:)
719 type(projector_matrix_t), pointer :: pmat
720
722
723 assert(allocated(this%projector_matrices))
724 assert(this%nprojector_matrices > 0)
725
726 safe_allocate(offsets(1:offset_size, 1:this%nprojector_matrices))
727 safe_allocate(cnt(1:mesh%np))
728
729 cnt = 0
730
731 matrix_size = 0
732 this%total_points = 0
733 scal_size = 0
734 this%max_npoints = 0
735 this%max_nprojs = 0
736 mix_offset = 0
737 do imat = 1, this%nprojector_matrices
738 pmat => this%projector_matrices(imat)
739
740 this%max_npoints = max(this%max_npoints, pmat%npoints)
741 this%max_nprojs = max(this%max_nprojs, pmat%nprojs)
742
743 offsets(points, imat) = pmat%npoints
744 offsets(projs, imat) = pmat%nprojs
745
746 offsets(matrix, imat) = matrix_size
747 matrix_size = matrix_size + pmat%npoints*pmat%nprojs
748
749 offsets(map, imat) = this%total_points
750 this%total_points = this%total_points + pmat%npoints
751
752 offsets(scal, imat) = scal_size
753 scal_size = scal_size + pmat%nprojs
754
755 offsets(mix, imat) = mix_offset
756 if (allocated(pmat%dmix)) then
757 mix_offset = mix_offset + pmat%nprojs**2
758 else if (allocated(pmat%zmix)) then
759 mix_offset = mix_offset + 4*pmat%nprojs**2
760 else
761 offsets(mix, imat) = -1
762 end if
763
764 do is = 1, pmat%npoints
765 ip = pmat%map(is)
766 cnt(ip) = cnt(ip) + 1
767 end do
768 end do
769
770 safe_allocate(invmap(1:max(maxval(cnt), 1), 1:mesh%np))
771 safe_allocate(invmap2(1:max(maxval(cnt)*mesh%np, 1)))
772 safe_allocate(invmap_mat(1:max(maxval(cnt), 1), 1:mesh%np))
773 safe_allocate(invmap_mat2(1:max(maxval(cnt)*mesh%np, 1)))
774 safe_allocate(pos(1:mesh%np + 1))
775
776 cnt = 0
777 ii = 0
778 do imat = 1, this%nprojector_matrices
779 pmat => this%projector_matrices(imat)
780 do is = 1, pmat%npoints
781 ip = pmat%map(is)
782 cnt(ip) = cnt(ip) + 1
783 invmap(cnt(ip), ip) = ii
784 invmap_mat(cnt(ip), ip) = imat - 1
785 ii = ii + 1
786 end do
787 end do
788
789 ipos = 0
790 pos(1) = 0
791 do ip = 1, mesh%np
792 do ii = 1, cnt(ip)
793 ipos = ipos + 1
794 invmap2(ipos) = invmap(ii, ip)
795 invmap_mat2(ipos) = invmap_mat(ii, ip)
796 end do
797 pos(ip + 1) = ipos
798 end do
799
800 if (this%projector_matrices(1)%is_cmplx) then
801 call accel_create_buffer(this%buff_matrices, accel_mem_read_only, type_cmplx, matrix_size)
802 else
803 call accel_create_buffer(this%buff_matrices, accel_mem_read_only, type_float, matrix_size)
804 end if
805 call accel_create_buffer(this%buff_maps, accel_mem_read_only, type_integer, this%total_points)
806 if (mesh%use_vol_pp) then
807 call accel_create_buffer(this%buff_sphere_weights, accel_mem_read_only, type_float, this%total_points)
808 end if
809 call accel_create_buffer(this%buff_position, accel_mem_read_only, type_float, 3*this%total_points)
810 call accel_create_buffer(this%buff_scals, accel_mem_read_only, type_float, scal_size)
811
812 if (mix_offset > 0) then
813 if (allocated(this%projector_matrices(1)%zmix)) then
814 call accel_create_buffer(this%buff_mix, accel_mem_read_only, type_cmplx, mix_offset)
815 else
816 call accel_create_buffer(this%buff_mix, accel_mem_read_only, type_float, mix_offset)
817 end if
818 end if
819
820 do imat = 1, this%nprojector_matrices
821 pmat => this%projector_matrices(imat)
822 if (pmat%npoints > 0) then
823 if (pmat%is_cmplx) then
824 call accel_write_buffer(this%buff_matrices, pmat%npoints, pmat%nprojs, pmat%zprojectors, &
825 offset = offsets(matrix, imat))
826 else
827 call accel_write_buffer(this%buff_matrices, pmat%npoints, pmat%nprojs, pmat%dprojectors, &
828 offset = offsets(matrix, imat))
829 end if
830 call accel_write_buffer(this%buff_maps, pmat%npoints, pmat%map, offset = offsets(map, imat))
831 if (mesh%use_vol_pp) then
832 call accel_write_buffer(this%buff_sphere_weights, pmat%npoints, pmat%sphere_weights, &
833 offset = offsets(map, imat))
834 end if
835 call accel_write_buffer(this%buff_position, space%dim, pmat%npoints, pmat%position, &
836 offset = 3*offsets(map, imat))
837 end if
838 call accel_write_buffer(this%buff_scals, pmat%nprojs, pmat%scal, offset = offsets(scal, imat))
839 if (offsets(mix, imat) /= -1) then
840 if (allocated(pmat%zmix)) then
841 call accel_write_buffer(this%buff_mix, pmat%nprojs, pmat%nprojs, 4, pmat%zmix, offset = offsets(mix, imat))
842 else
843 call accel_write_buffer(this%buff_mix, pmat%nprojs, pmat%nprojs, pmat%dmix, offset = offsets(mix, imat))
844 end if
845 end if
846 end do
847
848 call accel_create_buffer(this%buff_offsets, accel_mem_read_only, type_integer, offset_size*this%nprojector_matrices)
849 call accel_write_buffer(this%buff_offsets, offset_size, this%nprojector_matrices, offsets)
850
851 call accel_create_buffer(this%buff_pos, accel_mem_read_only, type_integer, mesh%np + 1)
852 call accel_write_buffer(this%buff_pos, mesh%np + 1, pos)
853
854 call accel_create_buffer(this%buff_invmap, accel_mem_read_only, type_integer, ipos)
855 call accel_write_buffer(this%buff_invmap, ipos, invmap2)
856
857 call accel_create_buffer(this%buff_invmap_mat, accel_mem_read_only, type_integer, ipos)
858 call accel_write_buffer(this%buff_invmap_mat, ipos, invmap_mat2)
859
860 ! 0-based matrix index of every packed projector point and every projector
861 safe_allocate(point_to_mat(1:max(this%total_points, 1)))
862 safe_allocate(proj_to_mat(1:max(scal_size, 1)))
863 do imat = 1, this%nprojector_matrices
864 pmat => this%projector_matrices(imat)
865 point_to_mat(offsets(map, imat) + 1:offsets(map, imat) + pmat%npoints) = imat - 1
866 proj_to_mat(offsets(scal, imat) + 1:offsets(scal, imat) + pmat%nprojs) = imat - 1
867 end do
868
869 call accel_create_buffer(this%buff_point_to_mat, accel_mem_read_only, type_integer, this%total_points)
870 call accel_write_buffer(this%buff_point_to_mat, this%total_points, point_to_mat)
871 call accel_create_buffer(this%buff_proj_to_mat, accel_mem_read_only, type_integer, scal_size)
872 call accel_write_buffer(this%buff_proj_to_mat, scal_size, proj_to_mat)
873
874 safe_deallocate_a(offsets)
875 safe_deallocate_a(point_to_mat)
876 safe_deallocate_a(proj_to_mat)
877 safe_deallocate_a(cnt)
878 safe_deallocate_a(invmap)
879 safe_deallocate_a(invmap2)
880 safe_deallocate_a(invmap_mat)
881 safe_deallocate_a(invmap_mat2)
882 safe_deallocate_a(pos)
883
886
887 ! ----------------------------------------------------------------------------------
890 class(nonlocal_pseudopotential_t), intent(inout) :: this
891
892 integer :: ik, imat, iphase, nphase, offset, npoints
893
895
896 if (.not. allocated(this%projector_phases)) then
898 return
899 end if
900
901 nphase = size(this%projector_phases, 2)
902 this%nphase = nphase
903
904 call accel_create_buffer(this%buff_projector_phases, accel_mem_read_only, type_cmplx, &
905 this%total_points*nphase*size(this%projector_phases, 4))
906
907 offset = 0
908 do ik = lbound(this%projector_phases, 4), ubound(this%projector_phases, 4)
909 do imat = 1, this%nprojector_matrices
910 npoints = this%projector_matrices(imat)%npoints
911 do iphase = 1, nphase
912 if (npoints > 0) then
913 call accel_write_buffer(this%buff_projector_phases, npoints, this%projector_phases(1:, iphase, imat, ik), &
914 offset = offset, async=.true.)
915 end if
916 offset = offset + npoints
917 end do
918 end do
919 end do
920 call accel_finish()
921
924
925 ! ----------------------------------------------------------------------------------
927 !
928 logical pure function nonlocal_pseudopotential_self_overlap(this) result(projector_self_overlap)
929 class(nonlocal_pseudopotential_t), intent(in) :: this
930
931 projector_self_overlap = this%projector_self_overlap
933
934#include "undef.F90"
935#include "real.F90"
936#include "nonlocal_pseudopotential_inc.F90"
937
938#include "undef.F90"
939#include "complex.F90"
940#include "nonlocal_pseudopotential_inc.F90"
941
943
944!! Local Variables:
945!! mode: f90
946!! coding: utf-8
947!! End:
Copies a vector x, to a vector y.
Definition: lalg_basic.F90:220
double sqrt(double __x) __attribute__((__nothrow__
subroutine, public accel_free_buffer(this, async)
Definition: accel.F90:990
subroutine, public accel_finish()
Definition: accel.F90:1127
subroutine, public accel_detach_buffer(this)
Clear a buffer handle without freeing device memory.
Definition: accel.F90:1059
logical pure function, public accel_buffer_is_allocated(this)
Definition: accel.F90:1119
pure logical function, public accel_is_enabled()
Definition: accel.F90:414
integer, parameter, public accel_mem_read_only
Definition: accel.F90:185
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
integer, parameter, public spin_orbit
Definition: epot.F90:168
real(real64), parameter, public m_zero
Definition: global.F90:200
real(real64), parameter, public m_half
Definition: global.F90:206
This module is intended to contain "only mathematical" functions and procedures.
Definition: math.F90:117
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:120
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:594
subroutine nonlocal_pseudopotential_destroy_proj(this)
Destroy the data of nonlocal_pseudopotential_t.
subroutine nonlocal_pseudopotential_detach_accel_buffers(this)
Clear copied accelerator handles so they do not alias source buffers.
subroutine dnonlocal_pseudopotential_force(this, mesh, st, spiral_bnd, iqn, ndim, psi1b, psi2b, force)
calculate contribution to forces, from non-local potentials
subroutine znonlocal_pseudopotential_position_commutator(this, mesh, std, spiral_bnd, psib, commpsib, async)
apply the commutator between the non-local potential and the position to the wave functions.
subroutine znonlocal_pseudopotential_force(this, mesh, st, spiral_bnd, iqn, ndim, psi1b, psi2b, force)
calculate contribution to forces, from non-local potentials
subroutine dnonlocal_pseudopotential_start(this, mesh, std, spiral_bnd, psib, projection, async)
Start application of non-local potentials (stored in the Hamiltonian) to the wave functions.
subroutine dnonlocal_pseudopotential_finish(this, mesh, spiral_bnd, std, projection, vpsib)
finish the application of non-local potentials.
subroutine, public nonlocal_pseudopotential_accel_rebuild(this, space, mesh)
Rebuild accelerator buffers after an intrinsic copy.
subroutine dnonlocal_pseudopotential_position_commutator(this, mesh, std, spiral_bnd, psib, commpsib, async)
apply the commutator between the non-local potential and the position to the wave functions.
subroutine, public nonlocal_pseudopotential_rebind_projectors(this, epot)
Rebind projector matrix pointers (map, position) to a target epot.
subroutine nonlocal_pseudopotential_build_accel_buffers(this, space, mesh)
Build accelerator buffers for projectors from host-side projector matrices.
subroutine znonlocal_pseudopotential_r_vnlocal(this, mesh, std, spiral_bnd, psib, commpsib)
Accumulates to commpsib the result of x V_{nl} | psib >
logical pure function nonlocal_pseudopotential_self_overlap(this)
Returns .true. if the Hamiltonian contains projectors, which overlap with themself.
subroutine nonlocal_pseudopotential_init(this)
initialize the nonlocal_pseudopotential_t object
subroutine dnonlocal_pseudopotential_r_vnlocal(this, mesh, std, spiral_bnd, psib, commpsib)
Accumulates to commpsib the result of x V_{nl} | psib >
subroutine znonlocal_pseudopotential_start(this, mesh, std, spiral_bnd, psib, projection, async)
Start application of non-local potentials (stored in the Hamiltonian) to the wave functions.
subroutine nonlocal_pseudopotential_build_projector_phase_accel_buffer(this)
Rebuild projector phase accelerator buffer from host-side projector phases.
subroutine nonlocal_pseudopotential_build_proj(this, space, mesh, epot)
build the projectors for the application of pseudo-potentials
subroutine znonlocal_pseudopotential_finish(this, mesh, spiral_bnd, std, projection, vpsib)
finish the application of non-local potentials.
subroutine, public profiling_out(label)
Increment out counter and sum up difference between entry and exit time.
Definition: profiling.F90:668
subroutine, public profiling_in(label, exclude)
Increment in counter and save entry time.
Definition: profiling.F90:600
subroutine, public projector_matrix_deallocate(this)
subroutine, public projector_matrix_allocate(this, nprojs, sphere, has_mix_matrix, is_cmplx)
logical elemental function, public projector_is(p, type)
Definition: projector.F90:211
logical elemental function, public projector_is_null(p)
Definition: projector.F90:204
Definition: ps.F90:116
integer, parameter, public proj_hgh
Definition: ps.F90:171
integer, parameter, public proj_rkb
Definition: ps.F90:171
integer, parameter, public proj_none
Definition: ps.F90:171
integer, parameter, public proj_kb
Definition: ps.F90:171
This module handles spin dimensions of the states and the k-point distribution.
logical function, public submesh_overlap(sm1, sm2, space)
Definition: submesh.F90:742
type(type_t), parameter, public type_cmplx
Definition: types.F90:137
type(type_t), parameter, public type_integer
Definition: types.F90:138
type(type_t), parameter, public type_float
Definition: types.F90:136
Describes mesh distribution to nodes.
Definition: mesh.F90:188
Class for projections of wave functions.
A set of projectors defined on a submesh.
The rkb_projector data type holds the KB projectors build with total angular momentum eigenfunctions....
int true(void)