Branch data Line data Source code
1 : : !!****m* ABINIT/m_matlu
2 : : !! NAME
3 : : !! m_matlu
4 : : !!
5 : : !! FUNCTION
6 : : !!
7 : : !! COPYRIGHT
8 : : !! Copyright (C) 2006-2026 ABINIT group (BAmadon)
9 : : !! This file is distributed under the terms of the
10 : : !! GNU General Public License, see ~abinit/COPYING
11 : : !! or http://www.gnu.org/copyleft/gpl.txt .
12 : : !!
13 : : !! INPUTS
14 : : !!
15 : : !! OUTPUT
16 : : !!
17 : : !! NOTES
18 : : !! subroutines in this module must never call
19 : : !! a subroutine of m_oper, m_green, m_self
20 : : !! in order to avoid circular dependancies
21 : : !!
22 : : !! SOURCE
23 : :
24 : : #if defined HAVE_CONFIG_H
25 : : #include "config.h"
26 : : #endif
27 : :
28 : :
29 : : #include "abi_common.h"
30 : :
31 : : MODULE m_matlu
32 : :
33 : : use, intrinsic :: iso_c_binding, only: c_size_t, c_loc
34 : : use defs_basis
35 : : use m_errors
36 : : use m_abicore
37 : : use m_gputk
38 : : use m_abi_linalg
39 : :
40 : : #ifdef HAVE_GPU
41 : : use m_gpu_toolbox
42 : : #endif
43 : :
44 : : use m_abi_linalg, only : abi_xgemm
45 : : use m_fstrings, only : int2char4
46 : : use m_hide_lapack, only : xginv
47 : : use m_io_tools, only : flush_unit
48 : : use m_matrix, only : blockdiago_fordsyev,blockdiago_forzheev
49 : : use m_paw_dmft, only : paw_dmft_type
50 : : use m_xmpi, only : xmpi_bcast,xmpi_sum
51 : :
52 : : implicit none
53 : :
54 : : private
55 : :
56 : : public :: init_matlu
57 : : public :: inverse_matlu
58 : : public :: destroy_matlu
59 : : public :: diff_matlu
60 : : public :: add_matlu
61 : : public :: print_matlu
62 : : public :: sym_matlu
63 : : public :: copy_matlu
64 : : public :: copy_matlu_from_ndat
65 : : public :: copy_matlu_to_ndat
66 : : public :: gather_matlu
67 : : public :: zero_matlu
68 : : public :: trace_matlu
69 : : public :: diag_matlu
70 : : public :: rotate_matlu
71 : : public :: shift_matlu
72 : : public :: checkdiag_matlu
73 : : public :: checkreal_matlu
74 : : public :: prod_matlu
75 : : public :: conjg_matlu
76 : : public :: ln_matlu
77 : : public :: slm2ylm_matlu
78 : : public :: fac_matlu
79 : : public :: printplot_matlu
80 : : public :: identity_matlu
81 : : public :: magmomforb_matlu
82 : : public :: magmomfspin_matlu
83 : : public :: magmomfzeeman_matlu
84 : : public :: chi_matlu
85 : : public :: trace_prod_matlu
86 : : public :: xmpi_matlu
87 : : public :: symmetrize_matlu
88 : : public :: ylm2jmj_matlu
89 : : public :: magnfield_matlu
90 : : public :: magmomjmj_matlu
91 : : !!***
92 : :
93 : : !!****t* m_matlu/matlu_type
94 : : !! NAME
95 : : !! matlu_type
96 : : !!
97 : : !! FUNCTION
98 : : !! This structured datatype contains a matrix for the correlated subspace
99 : : !!
100 : : !! SOURCE
101 : :
102 : : type, public :: matlu_type ! for each atom
103 : :
104 : : integer :: lpawu
105 : : ! Value of the angular momentum for each correlated electrons
106 : :
107 : : ! integer :: natom
108 : : ! number of atoms (given for each atom, not useful..could be changed)
109 : : !
110 : : ! integer :: mband
111 : : ! ! Number of bands
112 : : !
113 : : ! integer :: mbandc
114 : : ! ! Total number of bands in the Kohn-Sham Basis for PAW+DMFT
115 : : !
116 : : ! integer :: natpawu ! Number of correlated atoms
117 : : !
118 : : ! integer :: nkpt
119 : : ! ! Number of k-point in the IBZ.
120 : : !character(len=12) :: whichmatlu
121 : : ! describe the type of local matrix computed (greenDFT, etc..)
122 : : !
123 : : integer :: gpu_option
124 : : ! Wether ks and matlu are stored on GPU
125 : : !
126 : : integer :: ndat
127 : : ! Number of elements computed in batch
128 : : !
129 : : integer :: nspinor
130 : : ! Number of spinorial components
131 : : !
132 : : integer :: nsppol
133 : : ! Number of polarizations
134 : :
135 : : complex(dp), allocatable :: mat(:,:,:)
136 : : ! Local quantity
137 : :
138 : : end type matlu_type
139 : :
140 : : !----------------------------------------------------------------------
141 : :
142 : :
143 : : CONTAINS !========================================================================================
144 : : !!***
145 : :
146 : : !!****f* m_matlu/init_matlu
147 : : !! NAME
148 : : !! init_matlu
149 : : !!
150 : : !! FUNCTION
151 : : !! Allocate variables used in type matlu_type.
152 : : !!
153 : : !! INPUTS
154 : : !! natom = number of atoms
155 : : !! nspinor = number of spinorial components
156 : : !! nsppol = number of polarisation components
157 : : !! lpawu_natom(natom) = value of lpawu for every atom
158 : : !! matlu <type(matlu_type)>= density matrix in the local orbital basis and related variables
159 : : !!
160 : : !! OUTPUTS
161 : : !! matlu <type(matlu_type)>= density matrix in the local orbital basis and related variables
162 : : !!
163 : : !! SOURCE
164 : :
165 : 361373 : subroutine init_matlu(natom,nspinor,nsppol,lpawu_natom,matlu,gpu_option,ndat)
166 : :
167 : : !Arguments ------------------------------------
168 : : integer, intent(in) :: natom,nspinor,nsppol
169 : : integer, intent(in) :: lpawu_natom(natom)
170 : : integer, intent(in), optional :: gpu_option,ndat
171 : : type(matlu_type), target, intent(inout) :: matlu(natom)
172 : : !Local variables ------------------------------------
173 : : integer :: iatom,lpawu,ndim,l_gpu_option,l_ndat
174 : : !************************************************************************
175 : :
176 [ + + ]: 361373 : l_gpu_option=ABI_GPU_DISABLED; if(present(gpu_option)) l_gpu_option=gpu_option
177 [ - + ]: 361373 : l_ndat=1; if(present(ndat)) l_ndat=ndat
178 : : ! matlu%mband = mband
179 : : ! matlu%dmftbandf = dmftbandf
180 : : ! matlu%dmftbandi = dmftbandi
181 : : ! matlu%nkpt = nkpt
182 : : ! matlu%mbandc = 0
183 [ + + ]: 980224 : do iatom=1,natom
184 : :
185 : 618851 : lpawu = lpawu_natom(iatom)
186 : 618851 : matlu(iatom)%lpawu = lpawu
187 : 618851 : matlu(iatom)%nspinor = nspinor
188 : 618851 : matlu(iatom)%nsppol = nsppol
189 : 618851 : matlu(iatom)%ndat = l_ndat
190 : 618851 : matlu(iatom)%gpu_option = l_gpu_option
191 [ + + ]: 618851 : if (lpawu == -1) cycle
192 : 369523 : ndim = (2*lpawu+1) * nspinor
193 [ - + + - : 1847615 : ABI_MALLOC(matlu(iatom)%mat,(ndim,ndim,nsppol))
- + + - -
+ + - + -
+ - - + -
+ - + ]
194 [ + - ]: 730896 : if(l_gpu_option==ABI_GPU_DISABLED) then
195 [ + + + + : 19895802 : matlu(iatom)%mat(:,:,:) = czero
+ + ]
196 [ # # ]: 0 : else if(l_gpu_option==ABI_GPU_OPENMP) then
197 [ # # # # : 0 : matlu(iatom)%mat(:,:,:) = czero
# # ]
198 : : #ifdef HAVE_OPENMP_OFFLOAD
199 : : call matlu_ompgpu_map_alloc(matlu(iatom)%mat)
200 : : #endif
201 : 0 : call gpu_set_to_zero_complex(matlu(iatom)%mat, int(nsppol,c_size_t)*ndim*ndim)
202 : : end if
203 : :
204 : : end do ! iatom
205 : :
206 : : #if defined HAVE_OPENMP_OFFLOAD
207 : : contains
208 : : ! mat is located in an array of structs,
209 : : ! which syntax is loosely supported in OpenMP directives
210 : : subroutine matlu_ompgpu_map_alloc(mat)
211 : : complex(dp),intent(inout) :: mat(:,:,:)
212 : : !$OMP TARGET ENTER DATA MAP(alloc:mat)
213 : : end subroutine matlu_ompgpu_map_alloc
214 : : #endif
215 : 361373 : end subroutine init_matlu
216 : : !!***
217 : :
218 : : !!****f* m_matlu/zero_matlu
219 : : !! NAME
220 : : !! zero_matlu
221 : : !!
222 : : !! FUNCTION
223 : : !! Set the elements of matlu to 0.
224 : : !!
225 : : !! INPUTS
226 : : !! matlu <type(matlu_type)>= density matrix in the local orbital basis and related variables
227 : : !! natom = number of atoms
228 : : !! onlynondiag = set all the off-diagonal elements to 0
229 : : !! onlyimag = set the imaginary part to 0
230 : : !!
231 : : !! OUTPUT
232 : : !! matlu <type(matlu_type)>= density matrix in the local orbital basis and related variables
233 : : !! err = maximal off-diagonal/imaginary element that is neglected
234 : : !!
235 : : !! SOURCE
236 : :
237 : 18975 : subroutine zero_matlu(matlu,natom,onlynondiag,onlyimag,err)
238 : :
239 : : !Arguments ------------------------------------
240 : : integer, intent(in) :: natom
241 : : type(matlu_type), intent(inout) :: matlu(natom)
242 : : integer, optional, intent(in) :: onlyimag,onlynondiag
243 : : real(dp), optional, intent(out) :: err
244 : : !Local variables-------------------------------
245 : : integer :: iatom,im,im1,isppol
246 : : integer :: lpawu,ndim,nspinor,nsppol,tndim
247 : : real(dp) :: err_
248 : : !*********************************************************************
249 : :
250 : 18975 : nspinor = matlu(1)%nspinor
251 : 18975 : nsppol = matlu(1)%nsppol
252 : :
253 [ - + ]: 18975 : if (present(err)) err = zero
254 : :
255 [ + + ]: 42949 : do iatom=1,natom
256 : 23974 : lpawu = matlu(iatom)%lpawu
257 [ + + ]: 23974 : if (lpawu == -1) cycle
258 [ + + ]: 38142 : if (present(onlynondiag)) then
259 : 17929 : ndim = 2*lpawu + 1
260 : 17929 : tndim = nspinor * ndim
261 [ + + ]: 52527 : do isppol=1,nsppol
262 [ + + ]: 225685 : do im1=1,tndim
263 [ + + ]: 1084130 : do im=1,tndim
264 [ + + ]: 1049532 : if (im /= im1) then
265 [ - + ]: 703216 : if (present(err)) then
266 : 0 : err_ = abs(matlu(iatom)%mat(im,im1,isppol))
267 [ # # ]: 0 : if (err_ > err) err = err_
268 : : end if
269 : 703216 : matlu(iatom)%mat(im,im1,isppol) = czero
270 : : end if ! im/=im1
271 : : end do ! im
272 : : end do ! im1
273 : : end do ! isppol
274 [ - + ]: 1238 : else if (present(onlyimag)) then
275 [ # # # # : 0 : if (present(err)) err = maxval(abs(aimag(matlu(iatom)%mat(:,:,:))))
# # # # #
# # # # #
# # ]
276 [ # # # # : 0 : matlu(iatom)%mat(:,:,:) = cmplx(dble(matlu(iatom)%mat(:,:,:)),zero,kind=dp)
# # ]
277 : : else
278 [ + + + + : 61355 : matlu(iatom)%mat(:,:,:) = czero
+ + ]
279 : : end if ! onlynondiag
280 : : end do ! iatom
281 : :
282 : 18975 : end subroutine zero_matlu
283 : : !!***
284 : :
285 : : !!****f* m_matlu/destroy_matlu
286 : : !! NAME
287 : : !! destroy_matlu
288 : : !!
289 : : !! FUNCTION
290 : : !! Deallocate matlu
291 : : !!
292 : : !! INPUTS
293 : : !! matlu <type(matlu_type)>= density matrix in the local orbital basis and related variables
294 : : !! natom = number of atoms
295 : : !!
296 : : !! OUTPUT
297 : : !!
298 : : !! SOURCE
299 : :
300 : 361373 : subroutine destroy_matlu(matlu,natom)
301 : :
302 : : !Arguments ------------------------------------
303 : : integer, intent(in) :: natom
304 : : type(matlu_type),target, intent(inout) :: matlu(natom)
305 : : !Local variables-------------------------------
306 : : integer :: iatom
307 : : ! *********************************************************************
308 : :
309 [ + + ]: 980224 : do iatom=1,natom
310 : : if(matlu(iatom)%gpu_option==ABI_GPU_OPENMP) then
311 : : #ifdef HAVE_OPENMP_OFFLOAD
312 : : call matlu_ompgpu_map_delete(matlu(iatom)%mat)
313 : : #endif
314 : : end if
315 [ + + ]: 980224 : ABI_SFREE(matlu(iatom)%mat)
316 : : end do ! iatom
317 : :
318 : : #if defined HAVE_OPENMP_OFFLOAD
319 : : contains
320 : : ! mat is located in an array of structs,
321 : : ! which syntax is loosely supported in OpenMP directives
322 : : subroutine matlu_ompgpu_map_delete(mat)
323 : : complex(dp),intent(inout) :: mat(:,:,:)
324 : : !$OMP TARGET EXIT DATA MAP(delete:mat)
325 : : end subroutine matlu_ompgpu_map_delete
326 : : #endif
327 : 361373 : end subroutine destroy_matlu
328 : : !!***
329 : :
330 : : !!****f* m_matlu/copy_matlu
331 : : !! NAME
332 : : !! copy_matlu
333 : : !!
334 : : !! FUNCTION
335 : : !! Copy mat1 into mat2
336 : : !!
337 : : !! INPUTS
338 : : !! mat1 <type(matlu_type)>= density matrix nmat1 in the local orbital basis and related variables
339 : : !! natom = number of atoms
340 : : !! opt_diag = if present, only copy the diagonal elements (the off-diagonal elements are not set to 0)
341 : : !! opt_non_diag = if present, only copy the off-diagonal elements
342 : : !! opt_re = if present, only copy the real part
343 : : !!
344 : : !! OUTPUT
345 : : !! mat2 <type(matlu_type)>= density matrix nmat2 in the local orbital basis and related variables
346 : : !!
347 : : !! SOURCE
348 : :
349 : 170189 : subroutine copy_matlu(mat1,mat2,natom,opt_diag,opt_non_diag,opt_re)
350 : :
351 : : !Arguments ------------------------------------
352 : : integer, intent(in) :: natom
353 : : type(matlu_type), intent(in) :: mat1(natom)
354 : : type(matlu_type), intent(inout) :: mat2(natom) !vz_i
355 : : integer, optional, intent(in) :: opt_diag,opt_non_diag,opt_re
356 : : !Local variables-------------------------------
357 : : integer :: iatom,im,im1,isppol,lpawu,ndim,nspinor,nsppol
358 : : ! *********************************************************************
359 : :
360 : 170189 : nspinor = mat1(1)%nspinor
361 : 170189 : nsppol = mat1(1)%nsppol
362 : :
363 [ + + ]: 442556 : do iatom=1,natom
364 : :
365 : 272367 : lpawu = mat1(iatom)%lpawu
366 [ + + ]: 272367 : if (lpawu == -1) cycle
367 : 174413 : ndim = (2*lpawu+1) * nspinor
368 : :
369 : : !if both matrix are on GPU and no opt is provided, perform copy on GPU
370 : : !Other cases can be handled through OpenMP kernels on GPU but no use case exists.
371 : : if(mat1(iatom)%gpu_option==ABI_GPU_OPENMP .and. mat2(iatom)%gpu_option==ABI_GPU_OPENMP &
372 [ - + - - : 174413 : & .and. .not. (present(opt_diag) .or. present(opt_non_diag) .or. present(opt_re))) then
- - - - ]
373 : : #ifdef HAVE_OPENMP_OFFLOAD
374 : : call gpu_copy_complex(mat2(iatom)%mat, mat1(iatom)%mat, int(nsppol, c_size_t)*ndim*ndim)
375 : : #endif
376 : : cycle
377 : : end if
378 : :
379 : :
380 : : #ifdef HAVE_OPENMP_OFFLOAD
381 : : !$OMP TARGET UPDATE FROM(mat1(iatom)%mat) IF(mat1(iatom)%gpu_option==ABI_GPU_OPENMP)
382 : : !$OMP TARGET UPDATE FROM(mat2(iatom)%mat) IF(mat2(iatom)%gpu_option==ABI_GPU_OPENMP)
383 : : #endif
384 [ - + ]: 344602 : if (present(opt_diag)) then
385 [ # # ]: 0 : do isppol=1,nsppol
386 [ # # ]: 0 : do im=1,ndim
387 : 0 : mat2(iatom)%mat(im,im,isppol) = mat1(iatom)%mat(im,im,isppol)
388 : : end do ! im
389 : : end do ! isppol
390 [ - + ]: 174413 : else if (present(opt_non_diag)) then
391 [ # # ]: 0 : do isppol=1,nsppol
392 [ # # ]: 0 : do im1=1,ndim
393 [ # # ]: 0 : do im=1,ndim
394 [ # # ]: 0 : if (im /= im1) mat2(iatom)%mat(im,im1,isppol) = mat1(iatom)%mat(im,im1,isppol)
395 : : end do ! im
396 : : end do ! im1
397 : : end do ! isppol
398 [ + + ]: 174413 : else if (present(opt_re)) then
399 [ + + + + : 6438 : mat2(iatom)%mat(:,:,:) = cmplx(dble(mat1(iatom)%mat(:,:,:)),zero,kind=dp)
+ + ]
400 : : else
401 [ + + + + : 10115265 : mat2(iatom)%mat(:,:,:) = mat1(iatom)%mat(:,:,:)
+ + ]
402 : : end if ! opt
403 : : #ifdef HAVE_OPENMP_OFFLOAD
404 : : !$OMP TARGET UPDATE TO(mat2(iatom)%mat) IF(mat2(iatom)%gpu_option==ABI_GPU_OPENMP)
405 : : #endif
406 : :
407 : : end do ! iatom
408 : :
409 : : ! do iatom=1,natom
410 : : ! lpawu=nmat1(iatom)%lpawu
411 : : ! if(lpawu.ne.-1) then
412 : : ! nmat2(iatom)%mat=nmat1(iatom)%mat
413 : : ! endif
414 : : ! enddo
415 : :
416 : 170189 : end subroutine copy_matlu
417 : : !!***
418 : :
419 : : !!****f* m_matlu/copy_matlu_from_ndat
420 : : !! NAME
421 : : !! copy_matlu_from_ndat
422 : : !!
423 : : !! FUNCTION
424 : : !! Copy matlu1 into matlu2
425 : : !!
426 : : !! INPUTS
427 : : !! maltu1 <type(matlu_type)>= density matrix matlu1 in the local orbital basis and related variables
428 : : !! natom = number of atoms
429 : : !!
430 : : !! OUTPUT
431 : : !! maltu2 <type(matlu_type)>= density matrix matlu2 in the local orbital basis and related variables
432 : : !!
433 : : !! SOURCE
434 : :
435 : 0 : subroutine copy_matlu_from_ndat(mat1,mat2,natom,ndat,idat,opt_diag,opt_non_diag,opt_re)
436 : :
437 : : !Arguments ------------------------------------
438 : : !type
439 : : integer, intent(in) :: natom,ndat,idat
440 : : type(matlu_type),intent(in) :: mat1(natom)
441 : : type(matlu_type),intent(inout) :: mat2(natom) !vz_i
442 : : integer, optional, intent(in) :: opt_diag,opt_non_diag,opt_re
443 : :
444 : : !Local variables-------------------------------
445 : : integer :: iatom,isppol,im1,im,ndim,nsppol,nspinor,lpawu
446 : : ! *********************************************************************
447 : :
448 [ # # ]: 0 : ABI_CHECK(mat1(1)%nsppol==mat2(1)%nsppol*ndat, "bad ndat value")
449 : 0 : nspinor = mat1(1)%nspinor
450 : 0 : nsppol = mat2(1)%nsppol
451 [ # # ]: 0 : do iatom=1,natom
452 : 0 : lpawu = mat1(iatom)%lpawu
453 [ # # ]: 0 : if (lpawu == -1) cycle
454 : 0 : ndim = (2*lpawu+1) * nspinor
455 : :
456 [ # # ]: 0 : if (present(opt_diag)) then
457 [ # # ]: 0 : do isppol=1,nsppol
458 [ # # ]: 0 : do im=1,ndim
459 : 0 : mat2(iatom)%mat(im,im,isppol) = mat1(iatom)%mat(im,im,(isppol-1)*ndat+idat)
460 : : end do ! im
461 : : end do ! isppol
462 [ # # ]: 0 : else if (present(opt_non_diag)) then
463 [ # # ]: 0 : do isppol=1,nsppol
464 [ # # ]: 0 : do im1=1,ndim
465 [ # # ]: 0 : do im=1,ndim
466 [ # # ]: 0 : if (im /= im1) mat2(iatom)%mat(im,im1,isppol) = mat1(iatom)%mat(im,im1,(isppol-1)*ndat+idat)
467 : : end do ! im
468 : : end do ! im1
469 : : end do ! isppol
470 : :
471 [ # # ]: 0 : else if (present(opt_re)) then
472 [ # # ]: 0 : do isppol=1,nsppol
473 [ # # # # ]: 0 : mat2(iatom)%mat(:,:,isppol) = cmplx(dble(mat1(iatom)%mat(:,:,(isppol-1)*ndat+idat)),zero,kind=dp)
474 : : end do ! isppol
475 : : else
476 [ # # ]: 0 : do isppol=1,nsppol
477 [ # # # # ]: 0 : mat2(iatom)%mat(:,:,isppol) = mat1(iatom)%mat(:,:,(isppol-1)*ndat+idat)
478 : : end do ! isppol
479 : : end if ! opt
480 : : enddo ! iatom
481 : :
482 : 0 : end subroutine copy_matlu_from_ndat
483 : : !!***
484 : :
485 : : !!****f* m_matlu/copy_matlu_to_ndat
486 : : !! NAME
487 : : !! copy_matlu_to_ndat
488 : : !!
489 : : !! FUNCTION
490 : : !! Copy matlu1 into matlu2
491 : : !!
492 : : !! INPUTS
493 : : !! maltu1 <type(matlu_type)>= density matrix matlu1 in the local orbital basis and related variables
494 : : !! natom = number of atoms
495 : : !!
496 : : !! OUTPUT
497 : : !! maltu2 <type(matlu_type)>= density matrix matlu2 in the local orbital basis and related variables
498 : : !!
499 : : !! SOURCE
500 : :
501 : 0 : subroutine copy_matlu_to_ndat(mat1,mat2,natom,ndat,idat,opt_diag,opt_non_diag,opt_re)
502 : :
503 : : !Arguments ------------------------------------
504 : : !type
505 : : integer, intent(in) :: natom,ndat,idat
506 : : type(matlu_type),intent(in) :: mat1(natom)
507 : : type(matlu_type),intent(inout) :: mat2(natom) !vz_i
508 : : integer, optional, intent(in) :: opt_diag,opt_non_diag,opt_re
509 : :
510 : : !Local variables-------------------------------
511 : : integer :: iatom,isppol,im1,im,ndim,nsppol,nspinor,lpawu
512 : : ! *********************************************************************
513 : :
514 : :
515 [ # # ]: 0 : ABI_CHECK(mat1(1)%nsppol*ndat==mat2(1)%nsppol, "bad ndat value")
516 : 0 : nspinor = mat1(1)%nspinor
517 : 0 : nsppol = mat1(1)%nsppol
518 [ # # ]: 0 : do iatom=1,natom
519 : 0 : lpawu = mat1(iatom)%lpawu
520 [ # # ]: 0 : if (lpawu == -1) cycle
521 : 0 : ndim = (2*lpawu+1) * nspinor
522 : :
523 [ # # ]: 0 : if (present(opt_diag)) then
524 [ # # ]: 0 : do isppol=1,nsppol
525 [ # # ]: 0 : do im=1,ndim
526 : 0 : mat2(iatom)%mat(im,im,(isppol-1)*ndat+idat) = mat1(iatom)%mat(im,im,isppol)
527 : : end do ! im
528 : : end do ! isppol
529 [ # # ]: 0 : else if (present(opt_non_diag)) then
530 [ # # ]: 0 : do isppol=1,nsppol
531 [ # # ]: 0 : do im1=1,ndim
532 [ # # ]: 0 : do im=1,ndim
533 [ # # ]: 0 : if (im /= im1) mat2(iatom)%mat(im,im1,(isppol-1)*ndat+idat) = mat1(iatom)%mat(im,im1,isppol)
534 : : end do ! im
535 : : end do ! im1
536 : : end do ! isppol
537 : :
538 [ # # ]: 0 : else if (present(opt_re)) then
539 [ # # ]: 0 : do isppol=1,nsppol
540 [ # # # # ]: 0 : mat2(iatom)%mat(:,:,(isppol-1)*ndat+idat) = cmplx(dble(mat1(iatom)%mat(:,:,isppol)),zero,kind=dp)
541 : : end do ! isppol
542 : : else
543 [ # # ]: 0 : do isppol=1,nsppol
544 [ # # # # ]: 0 : mat2(iatom)%mat(:,:,(isppol-1)*ndat+idat) = mat1(iatom)%mat(:,:,isppol)
545 : : end do ! isppol
546 : : end if ! opt
547 : : enddo ! iatom
548 : :
549 : 0 : end subroutine copy_matlu_to_ndat
550 : : !!***
551 : :
552 : : !!****f* m_matlu/print_matlu
553 : : !! NAME
554 : : !! print_matlu
555 : : !!
556 : : !! FUNCTION
557 : : !! Print matlu
558 : : !!
559 : : !! INPUTS
560 : : !! matlu <type(matlu_type)>= density matrix in the local orbital basis and related variables
561 : : !! natom= number of atoms
562 : : !! prtopt= /=0 print matlu
563 : : !! >=5 print matlu in n,mx,my,mz representation
564 : : !! opt_diag= 0 print non diagonal matrix (real or complex according to nspinor)
565 : : !! -1 print non diagonal complex matrix
566 : : !! >=1 print diagonal matrix (real or complex according to nspinor)
567 : : !! opt_ab_out= 0 print matrix on std_out
568 : : !! /=0 print matrix on ab_out
569 : : !! opt_exp= write in exponent format if present
570 : : !! argout= output unit
571 : : !! compl= 1 print complex matrix
572 : : !! /=1 only print complex matrix if nspinor=2
573 : : !!
574 : : !! OUTPUT
575 : : !!
576 : : !! SOURCE
577 : :
578 : 4835 : subroutine print_matlu(matlu,natom,prtopt,opt_diag,opt_ab_out,opt_exp,argout,compl)
579 : :
580 : : !Arguments ------------------------------------
581 : : integer, intent(in):: natom,prtopt
582 : : type(matlu_type), intent(in) :: matlu(natom)
583 : : integer, optional, intent(in) :: opt_diag,opt_ab_out,opt_exp,argout,compl
584 : : !Local variables-------------------------------
585 : : integer :: arg_out,iatom,im,im1,ispinor,ispinor1,isppol,lpawu
586 : : integer :: ndim,nspinor,nsppol,optab_out,optdiag
587 : : logical :: testcmplx,testcmplx_
588 : 4835 : complex(dp), allocatable :: mat_nmrep(:,:)
589 : : character(len=500) :: message
590 : : character(len=4) :: mode_paral,tag_at
591 : : character(len=9), parameter :: dspinm(2,2) = RESHAPE((/"n ","mx ","my ","mz "/),(/2,2/))
592 : : ! *********************************************************************
593 : :
594 : 4835 : arg_out = ab_out
595 : 4835 : mode_paral = 'COLL'
596 : 4835 : optab_out = 0
597 : 4835 : optdiag = 0
598 : :
599 [ + + ]: 4835 : if (present(opt_diag)) optdiag = opt_diag
600 [ + + ]: 4835 : if (present(opt_ab_out)) optab_out = opt_ab_out
601 [ - + ]: 4835 : if (optab_out == 0) arg_out = std_out
602 : :
603 [ - + ]: 4835 : if (present(argout)) then
604 : 0 : arg_out = argout
605 : 0 : mode_paral = 'PERS'
606 : : end if
607 : :
608 : 4835 : nspinor = matlu(1)%nspinor
609 : 4835 : nsppol = matlu(1)%nsppol
610 : 4835 : testcmplx_ = (nspinor == 2)
611 [ + + + + : 4835 : if (present(compl)) testcmplx_ = (nspinor == 2) .or. (compl == 1)
+ - ]
612 : :
613 [ + + ]: 19929 : do iatom=1,natom
614 : :
615 : 15094 : lpawu = matlu(iatom)%lpawu
616 [ + + ]: 15094 : if (lpawu == -1) cycle
617 : 5495 : ndim = 2*lpawu + 1
618 : :
619 : 5495 : write(tag_at,'(i4)') iatom
620 : 5495 : write(message,'(3a)') ch10,' -------> For Correlated Atom ',adjustl(tag_at)
621 : 5495 : call wrtout(arg_out,message,mode_paral)
622 : :
623 : 5495 : testcmplx = testcmplx_
624 [ + + + + : 255524 : if (maxval(abs(aimag(matlu(iatom)%mat(:,:,:)))) > tol5) testcmplx = .true.
+ + + + +
- + - +
+ ]
625 : :
626 : : !do isppol=1,nsppol
627 : : ! if (present(opt_ab_out) .and. nsppol == 2) then
628 : : ! noccspin = zero
629 : : ! do im=1,ndim
630 : : ! noccspin = noccspin + REAL(matlu(iatom)%mat(im,im,isppol))
631 : : ! end do
632 : : !write(message,fmt='(7x,a,i3,a,f10.5)') ". Occ. for lpawu and for spin",isppol," =",noccspin
633 : : !call wrtout(arg_out, message,mode_paral)
634 : : ! end if
635 : : !end do ! isppol
636 : :
637 [ + + ]: 18405 : do isppol=1,nsppol
638 [ + + ]: 8075 : if (nspinor == 1) then
639 : 7996 : write(message,'(a,10x,a,1x,i1)') ch10,'-- polarization spin component',isppol
640 : 7996 : call wrtout(arg_out,message,mode_paral)
641 : : end if ! nspinor=1
642 [ + + ]: 16229 : do ispinor=1,nspinor
643 [ + + ]: 24541 : do ispinor1=1,nspinor
644 [ + + ]: 8312 : if (nspinor == 2) then
645 : 316 : write(message,'(a,10x,a,i1,1x,i1)') ch10,'-- spin components ',ispinor,ispinor1
646 : 316 : call wrtout(arg_out,message,mode_paral)
647 : : end if
648 [ + - ]: 16466 : if (optdiag <= 0) then
649 [ + + ]: 47940 : do im1=1,ndim
650 [ + + ]: 39628 : if (optdiag == 0) then
651 [ + + + + ]: 34926 : if ((.not. testcmplx) .and. (abs(prtopt) > 0)) then
652 [ + + ]: 21653 : if (present(opt_exp)) then
653 [ + - + + ]: 6328 : write(message,'(5x,20e24.14)') (dble(matlu(iatom)%mat(im1+(ispinor-1)*ndim,im+(ispinor1-1)*ndim,isppol)),im=1,ndim)
654 : : ! call wrtout(arg_out, message,mode_paral)
655 : : ! write(message,'(5x,20e20.14)') (REAL(sqrt(matlu(iatom)%mat(m1,m,isppol,ispinor,ispinor1))),m=1,2*lpawu+1)
656 : : ! call wrtout(arg_out, message,mode_paral)
657 : : ! write(message,'(5x,20e20.14)') (REAL(1.d0/sqrt(matlu(iatom)%mat(m,m,isppol,ispinor,ispinor1))),m=1,2*lpawu+1)
658 : : else
659 [ + - + + ]: 122804 : write(message,'(5x,20f10.5)') (dble(matlu(iatom)%mat(im1+(ispinor-1)*ndim,im+(ispinor1-1)*ndim,isppol)),im=1,ndim)
660 : : end if ! opt_exp
661 [ + - ]: 13201 : else if (testcmplx .and. (abs(prtopt) > 0)) then
662 [ + + ]: 13201 : if (present(opt_exp)) then
663 [ - + ]: 2170 : if (opt_exp == 2) then
664 [ # # # # ]: 0 : write(message,'(5x,14(2e18.10,1x))') ((matlu(iatom)%mat(im1+(ispinor-1)*ndim,im+(ispinor1-1)*ndim,isppol)),im=1,ndim)
665 : : else
666 [ + - + + ]: 13464 : write(message,'(5x,14(2e14.4,2x))') ((matlu(iatom)%mat(im1+(ispinor-1)*ndim,im+(ispinor1-1)*ndim,isppol)),im=1,ndim)
667 : : end if ! opt_exp=2
668 : : else
669 [ + - + + ]: 72100 : write(message,'(5x,14(2f9.5,2x))') ((matlu(iatom)%mat(im1+(ispinor-1)*ndim,im+(ispinor1-1)*ndim,isppol)),im=1,ndim)
670 : : end if ! opt_exp
671 : : !& write(message,'(5x,14(2f15.11,2x))')((matlu(iatom)%mat(m1,m,isppol,ispinor,ispinor1)),m=1,2*lpawu+1)
672 : : end if ! testcmplx
673 [ + - ]: 4702 : else if (optdiag == -1) then
674 [ + - + + ]: 28076 : write(message,'(5x,14(2f10.5,2x))') ((matlu(iatom)%mat(im1+(ispinor-1)*ndim,im+(ispinor1-1)*ndim,isppol)),im=1,ndim)
675 : : end if ! optdiag
676 : 47940 : call wrtout(arg_out,message,mode_paral)
677 : : end do ! im1
678 : : else if (optdiag >= 1) then
679 [ # # # # ]: 0 : if ((.not. testcmplx) .and. (abs(prtopt) > 0)) write(message,'(5x,20f10.5)') &
680 [ # # # # ]: 0 : & (dble(matlu(iatom)%mat(im+(ispinor-1)*ndim,im+(ispinor1-1)*ndim,isppol)),im=1,ndim)
681 [ # # ]: 0 : if (testcmplx .and. (abs(prtopt) > 0)) write(message,'(5x,14(2f9.5,2x))') &
682 [ # # # # ]: 0 : & ((matlu(iatom)%mat(im+(ispinor-1)*ndim,im+(ispinor1-1)*ndim,isppol)),im=1,ndim)
683 : : ! write(std_out,'(5x,14(2f9.5,2x))')((matlu(iatom)%mat(m1,m,isppol,ispinor,ispinor1)),m=1,2*lpawu+1)
684 : 0 : call wrtout(arg_out,message,mode_paral)
685 : : end if ! optdiag
686 : : end do ! ispinor1
687 : : end do ! ispinor
688 [ + + - + ]: 23169 : if (nspinor == 2 .and. prtopt >= 5) then
689 [ # # # # : 0 : ABI_MALLOC(mat_nmrep,(2*ndim,2*ndim)) ! Put matlu in n,mx,my,mz representation
# # # # #
# # # # #
# # # # ]
690 [ # # ]: 0 : do im=1,ndim
691 [ # # ]: 0 : do im1=1,ndim
692 : 0 : mat_nmrep(im1,im) = matlu(iatom)%mat(im1,im,isppol) + matlu(iatom)%mat(im1+ndim,im+ndim,isppol) ! n
693 : 0 : mat_nmrep(im1+ndim,im+ndim) = matlu(iatom)%mat(im1,im,isppol) - matlu(iatom)%mat(im1+ndim,im+ndim,isppol) ! mz
694 : 0 : mat_nmrep(im1+ndim,im) = matlu(iatom)%mat(im1,im+ndim,isppol) + matlu(iatom)%mat(im1+ndim,im,isppol) ! mx
695 : 0 : mat_nmrep(im1,im+ndim) = (matlu(iatom)%mat(im1,im+ndim,isppol)-matlu(iatom)%mat(im+ndim,im,isppol)) * j_dpc ! my
696 : : end do ! im1
697 : : end do ! im
698 [ # # ]: 0 : do ispinor=1,nspinor
699 [ # # ]: 0 : do ispinor1=1,nspinor
700 : 0 : write(message,'(a,10x,2a)') ch10,'-- spin components',dspinm(ispinor1,ispinor)
701 : 0 : call wrtout(arg_out,message,mode_paral)
702 [ # # ]: 0 : do im1=1,ndim
703 [ # # # # ]: 0 : write(message,'(5x,14(2f9.5,2x))') ((mat_nmrep(im1+(ispinor1-1)*ndim,im+(ispinor-1)*ndim)),im=1,ndim)
704 : 0 : call wrtout(arg_out,message,mode_paral)
705 : : end do ! im1
706 : : end do ! ispinor1
707 : : end do ! ispinor
708 [ # # ]: 0 : ABI_FREE(mat_nmrep)
709 : : end if ! nspinor=2 and prtopt >=5
710 : : end do ! isppol
711 : : ! if(nsppol==1.and.nspinor==1) then
712 : : ! write(message,'(a,10x,a,i3,a)') ch10,'-- polarization spin component',isppol+1,' is identical'
713 : : ! call wrtout(arg_out, message,mode_paral)
714 : : ! endif
715 : : end do ! iatom
716 : :
717 : 4835 : end subroutine print_matlu
718 : : !!***
719 : :
720 : : !!****f* m_matlu/sym_matlu
721 : : !! NAME
722 : : !! sym_matlu
723 : : !!
724 : : !! FUNCTION
725 : : !! Symmetrize local quantity.
726 : : !!
727 : : !! COPYRIGHT
728 : : !! Copyright (C) 2005-2026 ABINIT group (BAmadon)
729 : : !! This file is distributed under the terms of the
730 : : !! GNU General Public License, see ~abinit/COPYING
731 : : !! or http://www.gnu.org/copyleft/gpl.txt .
732 : : !!
733 : : !! INPUTS
734 : : !! gloc(natom) <type(matlu_type)>= density matrix in the local orbital basis and related variables
735 : : !! paw_dmft <type(paw_dmft_type)>= paw+dmft related data
736 : : !!
737 : : !! OUTPUT
738 : : !! gloc(natom) <type(matlu_type)>= density matrix symmetrized in the local orbital basis and related variables
739 : : !!
740 : : !! SIDE EFFECTS
741 : : !!
742 : : !! NOTES
743 : : !!
744 : : !! SOURCE
745 : :
746 : 87632 : subroutine sym_matlu(gloc,paw_dmft)
747 : :
748 : : !Arguments ------------------------------------
749 : : type(paw_dmft_type), target, intent(in) :: paw_dmft
750 : : type(matlu_type), target, intent(inout) :: gloc(paw_dmft%natom)
751 : : !Local variables-------------------------------
752 : : integer :: at_indx,iatom,irot,isppol,lpawu,m1,m2,mu,natom
753 : : integer :: ndim,ndim_max,nspinor,nsppol,nsym,nu,gpu_option
754 : 87632 : complex(dp), target, allocatable :: gloc_tmp(:,:,:),gloc_tmp2(:,:,:)
755 : 87632 : complex(dp), target, allocatable :: gloc_tmp3(:,:,:,:),gloc_tmp4(:,:,:,:)
756 : 87632 : type(matlu_type), allocatable, target :: gloc_nmrep(:),glocsym(:)
757 : 87632 : complex(dp), ABI_CONTIGUOUS pointer :: zarot(:,:,:,:),gloc_mat(:,:,:),glocsym_mat(:,:,:)
758 : 87632 : real(dp), ABI_CONTIGUOUS pointer :: symrec_cart(:,:,:)
759 : : complex(dp) :: ratio
760 : :
761 : 87632 : natom = paw_dmft%natom
762 : 87632 : ndim_max = 2*paw_dmft%maxlpawu + 1
763 : 87632 : nspinor = paw_dmft%nspinor
764 : 87632 : nsppol = gloc(1)%nsppol
765 : 87632 : nsym = paw_dmft%nsym
766 : 87632 : gpu_option = gloc(1)%gpu_option
767 : 87632 : zarot => paw_dmft%zarot
768 : 87632 : ratio = dcmplx(1.0_dp/nsym,0.0_dp)
769 : :
770 : : !zarot => paw_dmft%zarot(:,1:ndim,irot,lpawu+1)
771 [ + - + - : 402075 : ABI_MALLOC(glocsym,(natom))
+ - - + -
+ + + ]
772 : : #ifdef HAVE_OPENMP_OFFLOAD
773 : : !$OMP TARGET ENTER DATA MAP(alloc:zarot) IF(gpu_option==ABI_GPU_OPENMP)
774 : : !$OMP TARGET UPDATE TO(zarot) IF(gpu_option==ABI_GPU_OPENMP)
775 : : #else
776 : : ABI_UNUSED((/m1,m2/))
777 : : #endif
778 : :
779 : : !========= Case nspinor ==1 ========================
780 : :
781 [ + + ]: 87632 : if (nspinor == 1) then
782 : :
783 [ - + + - : 434015 : ABI_MALLOC(gloc_tmp,(ndim_max,ndim_max*nsppol,nsym))
- + + - -
+ + - + -
+ - - + -
+ ]
784 : : #ifdef HAVE_OPENMP_OFFLOAD
785 : : !$OMP TARGET ENTER DATA MAP(alloc:gloc_tmp) IF(gpu_option==ABI_GPU_OPENMP)
786 : : #endif
787 : :
788 : 86803 : call init_matlu(natom,nspinor,nsppol,paw_dmft%lpawu(:),glocsym(:),gpu_option=gpu_option)
789 : :
790 [ + + ]: 225153 : do iatom=1,natom
791 : :
792 : 138350 : lpawu = gloc(iatom)%lpawu
793 [ + + ]: 138350 : if (lpawu == -1) cycle
794 : 88683 : ndim = 2*lpawu + 1
795 : 88683 : glocsym_mat => glocsym(iatom)%mat
796 : :
797 [ - + + - : 443415 : ABI_MALLOC(gloc_tmp2,(ndim,ndim*nsppol,nsym))
- + + - -
+ + - + -
+ - - + -
+ ]
798 : : #ifdef HAVE_OPENMP_OFFLOAD
799 : : !$OMP TARGET ENTER DATA MAP(alloc:gloc_tmp2) IF(gpu_option==ABI_GPU_OPENMP)
800 : : #endif
801 : :
802 : :
803 [ + - ]: 88683 : if(gpu_option==ABI_GPU_DISABLED) then
804 : :
805 [ + + ]: 4241643 : do irot=1,nsym
806 : 4152960 : at_indx = paw_dmft%indsym(irot,iatom)
807 : 4152960 : gloc_mat => gloc(at_indx)%mat
808 : :
809 [ + + ]: 11637504 : do isppol=1,nsppol
810 : : call abi_xgemm("n","n",ndim,ndim,ndim,cone,gloc_mat(:,:,isppol),ndim,&
811 : 11637504 : & zarot(:,1:ndim,irot,lpawu+1),ndim_max,czero,gloc_tmp(:,1+ndim*(isppol-1):ndim*isppol,irot),ndim_max)
812 : : end do ! isppol
813 : :
814 : : call abi_xgemm("t","n",ndim,ndim*nsppol,ndim,cone,zarot(:,1:ndim,irot,lpawu+1),ndim_max,&
815 : 4152960 : & gloc_tmp(:,:,irot),ndim_max,czero,gloc_tmp2(:,:,irot),ndim)
816 : :
817 [ + + ]: 11726187 : do isppol=1,nsppol
818 [ + - + + : 461281152 : glocsym_mat(:,:,isppol) = glocsym_mat(:,:,isppol) + gloc_tmp2(:,1+ndim*(isppol-1):ndim*isppol,irot)
+ + + + +
+ ]
819 : : end do ! isppol
820 : :
821 : : end do ! irot
822 : :
823 [ + + + + : 4984541 : glocsym_mat(:,:,:) = glocsym_mat(:,:,:) / dble(nsym)
+ + ]
824 : :
825 : : else if(gpu_option==ABI_GPU_OPENMP) then
826 : : #ifdef HAVE_OPENMP_OFFLOAD
827 : :
828 : : do irot=1,nsym
829 : : at_indx = paw_dmft%indsym(irot,iatom)
830 : : gloc_mat => gloc(at_indx)%mat
831 : :
832 : : !$OMP TARGET DATA USE_DEVICE_ADDR(gloc_tmp,zarot,gloc_mat)
833 : : call abi_gpu_xgemm_strided(2,"n","n",ndim,ndim,ndim,cone,&
834 : : & c_loc(gloc_mat(:,:,:)),ndim,ndim*ndim,&
835 : : & c_loc(zarot(:,1:ndim,irot,lpawu+1)),ndim_max,0,czero,&
836 : : & c_loc(gloc_tmp(:,:,irot)),ndim_max,ndim*ndim,nsppol,async=.true.,stream_id=irot)
837 : : !$OMP END TARGET DATA
838 : : end do ! irot
839 : : call gpu_device_synchronize()
840 : :
841 : : !$OMP TARGET DATA USE_DEVICE_ADDR(gloc_tmp,zarot,gloc_tmp2)
842 : : call abi_gpu_xgemm_strided(2,"t","n",ndim,ndim*nsppol,ndim,cone,&
843 : : & c_loc(zarot(:,:,:,lpawu+1)),ndim_max,ndim_max*ndim_max,&
844 : : & c_loc(gloc_tmp(:,:,:)),ndim_max,ndim_max*ndim_max*nsppol,czero,&
845 : : & c_loc(gloc_tmp2(:,:,:)),ndim,ndim*ndim*nsppol,nsym)
846 : : !$OMP END TARGET DATA
847 : :
848 : : !$OMP TARGET TEAMS DISTRIBUTE MAP(to:glocsym_mat,gloc_tmp2) PRIVATE(isppol)
849 : : do isppol=1,nsppol
850 : : !$OMP PARALLEL DO COLLAPSE(2) PRIVATE(m1,m2,irot)
851 : : do m2=1,ndim
852 : : do m1=1,ndim
853 : : do irot=1,nsym
854 : : glocsym_mat(m1,m2,isppol) = glocsym_mat(m1,m2,isppol) + gloc_tmp2(m1,m2+ndim*(isppol-1),irot)
855 : : end do ! irot
856 : : end do ! m1
857 : : end do ! m2
858 : : end do ! isppol
859 : :
860 : : call abi_xscal(ndim*ndim*nsppol, ratio, glocsym_mat, 1, gpu_option=gpu_option)
861 : :
862 : : #endif
863 : : end if
864 : :
865 : : #ifdef HAVE_OPENMP_OFFLOAD
866 : : !$OMP TARGET EXIT DATA MAP(delete:gloc_tmp2) IF(gpu_option==ABI_GPU_OPENMP)
867 : : #endif
868 [ - + ]: 225153 : ABI_FREE(gloc_tmp2)
869 : :
870 : : end do ! iatom
871 : :
872 : : !== Put glocsym into gloc
873 : 86803 : call copy_matlu(glocsym(:),gloc(:),natom)
874 : :
875 : : #ifdef HAVE_OPENMP_OFFLOAD
876 : : !$OMP TARGET EXIT DATA MAP(delete:gloc_tmp) IF(gpu_option==ABI_GPU_OPENMP)
877 : : #endif
878 [ - + ]: 86803 : ABI_FREE(gloc_tmp)
879 : : !========= Case nspinor ==2 ========================
880 : :
881 : : else
882 : :
883 : 829 : symrec_cart => paw_dmft%symrec_cart(:,:,:)
884 : : #ifdef HAVE_OPENMP_OFFLOAD
885 : : !$OMP TARGET ENTER DATA MAP(to:symrec_cart) IF(gpu_option==ABI_GPU_OPENMP)
886 : : #endif
887 : : !== Allocate temporary arrays
888 [ - + + - : 2487 : ABI_MALLOC(gloc_nmrep,(natom))
- + - + +
+ ]
889 : 829 : call init_matlu(natom,1,4*nsppol,paw_dmft%lpawu(:),glocsym(:),gpu_option=gpu_option)
890 : 829 : call init_matlu(natom,1,4*nsppol,paw_dmft%lpawu(:),gloc_nmrep(:),gpu_option=gpu_option)
891 : :
892 : : ! Put gloc into gloc_nmrep (density and magnetization representation)
893 : : ! gloc_nmrep(iatom)%mat(:,:,i) = n,mx,my,mz for i=1,2,3,4 respectively
894 : 829 : call chg_repr_matlu(gloc(:),gloc_nmrep(:),natom,1,1)
895 : :
896 : : !== Do the sum over symmetrized density matrix (in n,m repr)
897 [ + + ]: 1658 : do iatom=1,natom
898 : :
899 : 829 : lpawu = gloc(iatom)%lpawu
900 [ - + ]: 829 : if (lpawu == -1) cycle
901 : 829 : ndim = 2*lpawu + 1
902 : 829 : glocsym_mat => glocsym(iatom)%mat
903 : :
904 : :
905 [ - + + - : 5803 : ABI_MALLOC(gloc_tmp3,(ndim,ndim,4*nsppol,nsym))
- + + - +
- - + + -
- + + - +
- + - - +
- + ]
906 [ - + + - : 4145 : ABI_MALLOC(gloc_tmp4,(ndim,ndim,4*nsppol,nsym))
- + + - -
+ + - - +
+ - - + -
+ ]
907 : :
908 [ + - ]: 829 : if(gpu_option==ABI_GPU_DISABLED) then
909 [ + + ]: 20725 : do irot=1,nsym
910 : :
911 : 19896 : at_indx = paw_dmft%indsym(irot,iatom)
912 : 19896 : gloc_mat => gloc_nmrep(at_indx)%mat
913 : :
914 [ + + ]: 40621 : do isppol=1,nsppol
915 [ + + ]: 119376 : do mu=1,4 ! Symmetrize density and magnetization
916 : :
917 : : call abi_xgemm("n","n",ndim,ndim,ndim,cone,gloc_mat(:,:,mu+(isppol-1)*4),ndim, &
918 : 99480 : & zarot(:,1:ndim,irot,lpawu+1),ndim_max,czero,gloc_tmp3(:,:,mu+(isppol-1)*4,irot),ndim)
919 : :
920 : : end do ! mu
921 : : end do ! isppol
922 : : end do ! irot
923 : :
924 [ + + ]: 20725 : do irot=1,nsym
925 : : call abi_zgemm_2dd("t","n",ndim,ndim*4*nsppol,ndim,cone,zarot(:,1:ndim,irot,lpawu+1),ndim_max,&
926 : 20725 : & gloc_tmp3(:,:,:,irot),ndim,czero,gloc_tmp4(:,:,:,irot),ndim)
927 : :
928 : : end do ! irot
929 : :
930 [ + + ]: 20725 : do irot=1,nsym
931 [ + + ]: 40621 : do isppol=1,nsppol
932 [ + - + + : 2288040 : glocsym_mat(:,:,1+(isppol-1)*4) = glocsym_mat(:,:,1+(isppol-1)*4) + gloc_tmp4(:,:,1+(isppol-1)*4,irot)
+ + + + +
+ ]
933 : : end do ! isppol
934 : : end do ! irot
935 : :
936 : : ! Symmetrize magnetization
937 : :
938 [ + + ]: 20725 : do irot=1,nsym
939 [ + + ]: 40621 : do isppol=1,nsppol
940 [ + + ]: 99480 : do nu=2,4
941 [ + + ]: 258648 : do mu=2,4
942 : : glocsym_mat(:,:,mu+(isppol-1)*4) = glocsym_mat(:,:,mu+(isppol-1)*4) + &
943 [ + - + + : 20472984 : & symrec_cart(mu-1,nu-1,irot)*gloc_tmp4(:,:,nu+(isppol-1)*4,irot)
+ + + + +
+ ]
944 : : end do ! mu
945 : : end do ! nu
946 : : end do ! isppol
947 : : end do ! irot
948 : :
949 : : ! == Normalize sum
950 [ + + + + : 189841 : glocsym_mat(:,:,:) = glocsym_mat(:,:,:) / dble(nsym)
+ + ]
951 : :
952 : : else if(gpu_option==ABI_GPU_OPENMP) then
953 : : #ifdef HAVE_OPENMP_OFFLOAD
954 : : !$OMP TARGET ENTER DATA MAP(alloc:gloc_tmp3,gloc_tmp4)
955 : :
956 : : do irot=1,nsym
957 : :
958 : : at_indx = paw_dmft%indsym(irot,iatom)
959 : : gloc_mat => gloc_nmrep(at_indx)%mat
960 : :
961 : : !$OMP TARGET DATA USE_DEVICE_ADDR(gloc_tmp3,zarot,gloc_mat)
962 : : call abi_gpu_xgemm_strided(2,"n","n",ndim,ndim,ndim,cone,&
963 : : & c_loc(gloc_mat(:,:,:)),ndim,ndim*ndim,&
964 : : & c_loc(zarot(:,1:ndim,irot,lpawu+1)),ndim_max,0,czero,&
965 : : & c_loc(gloc_tmp3(:,:,:,irot)),ndim,ndim*ndim,4*nsppol,async=.true.,stream_id=irot)
966 : : !$OMP END TARGET DATA
967 : : end do ! irot
968 : : call gpu_device_synchronize()
969 : :
970 : :
971 : : !$OMP TARGET DATA USE_DEVICE_ADDR(gloc_tmp3,zarot,gloc_tmp4)
972 : : call abi_gpu_xgemm_strided(2,"t","n",ndim,ndim*4*nsppol,ndim,cone,&
973 : : & c_loc(zarot(:,:,:,lpawu+1)),ndim_max,ndim_max*ndim_max,&
974 : : & c_loc(gloc_tmp3(:,:,:,:)),ndim,ndim*ndim*4*nsppol,czero,&
975 : : & c_loc(gloc_tmp4(:,:,:,:)),ndim,ndim*ndim*4*nsppol,nsym)
976 : : !$OMP END TARGET DATA
977 : :
978 : :
979 : : !$OMP TARGET TEAMS DISTRIBUTE MAP(to:glocsym_mat,gloc_tmp4) PRIVATE(isppol)
980 : : do isppol=1,nsppol
981 : : !$OMP PARALLEL DO COLLAPSE(2) PRIVATE(m1,m2,irot)
982 : : do m2=1,ndim
983 : : do m1=1,ndim
984 : : do irot=1,nsym
985 : : glocsym_mat(m1,m2,1+(isppol-1)*4) = glocsym_mat(m1,m2,1+(isppol-1)*4) + gloc_tmp4(m1,m2,1+(isppol-1)*4,irot)
986 : : end do ! irot
987 : : end do ! m1
988 : : end do ! m2
989 : : end do ! isppol
990 : :
991 : : ! Symmetrize magnetization
992 : :
993 : : !$OMP TARGET TEAMS DISTRIBUTE MAP(to:glocsym_mat,gloc_tmp4,symrec_cart) PRIVATE(isppol,irot)
994 : : do isppol=1,nsppol
995 : : !$OMP PARALLEL DO COLLAPSE(3) PRIVATE(nu,mu,m2,m1)
996 : : do mu=2,4
997 : : do m2=1,ndim
998 : : do m1=1,ndim
999 : : do irot=1,nsym
1000 : : do nu=2,4
1001 : : glocsym_mat(m1,m2,mu+(isppol-1)*4) = glocsym_mat(m1,m2,mu+(isppol-1)*4) + &
1002 : : & symrec_cart(mu-1,nu-1,irot)*gloc_tmp4(m1,m2,nu+(isppol-1)*4,irot)
1003 : : end do ! m1
1004 : : end do ! m2
1005 : : end do ! mu
1006 : : end do ! nu
1007 : : end do ! isppol
1008 : : end do ! irot
1009 : :
1010 : : ! == Normalize sum
1011 : : call abi_xscal(ndim*ndim*4*nsppol, ratio, glocsym_mat, 1, gpu_option=gpu_option)
1012 : :
1013 : : !$OMP TARGET EXIT DATA MAP(delete:gloc_tmp3,gloc_tmp4)
1014 : : #endif
1015 : : end if ! gpu_option
1016 : :
1017 [ - + ]: 829 : ABI_FREE(gloc_tmp3)
1018 [ - + ]: 1658 : ABI_FREE(gloc_tmp4)
1019 : :
1020 : : end do ! iatom
1021 : :
1022 : : !== Compute back density matrix in upup dndn updn dnup representation
1023 : 829 : call chg_repr_matlu(gloc(:),glocsym(:),natom,-1,1)
1024 : :
1025 : 829 : call destroy_matlu(gloc_nmrep(:),natom)
1026 [ + - + + : 1658 : ABI_FREE(gloc_nmrep)
- + - + ]
1027 : :
1028 : : #ifdef HAVE_OPENMP_OFFLOAD
1029 : : !$OMP TARGET EXIT DATA MAP(delete:symrec_cart) IF(gpu_option==ABI_GPU_OPENMP)
1030 : : #endif
1031 : : !==============end of nspinor=2 case ===========
1032 : : end if ! nspinor
1033 : :
1034 : 87632 : call destroy_matlu(glocsym(:),natom)
1035 [ + - + + : 226811 : ABI_FREE(glocsym)
- + - + ]
1036 : : #ifdef HAVE_OPENMP_OFFLOAD
1037 : : !$OMP TARGET EXIT DATA MAP(delete:zarot) IF(gpu_option==ABI_GPU_OPENMP)
1038 : : #endif
1039 : :
1040 : : !mt2g(1)=1
1041 : : !mt2g(2)=2
1042 : : !mt2g(3)=4
1043 : : !mx2my2d=5
1044 : : !t2g=paw_dmft%dmftqmc_t2g
1045 : : !x2my2d=paw_dmft%dmftqmc_x2my2d
1046 : :
1047 : : ! DBG_ENTER("COLL")
1048 : :
1049 : : !ci=cone
1050 : : !nspinor=gloc(1)%nspinor
1051 : : !nsppol=gloc(1)%nsppol
1052 : : !natom=cryst_struc%natom
1053 : :
1054 : : !ABI_MALLOC(glocnm,(natom))
1055 : : !ABI_MALLOC(glocnms,(natom))
1056 : : !ABI_MALLOC(glocsym,(natom))
1057 : : !ABI_MALLOC(lpawu_natom,(natom))
1058 : : !lpawu_natom(1:natom)=gloc(1:natom)%lpawu ! If gloc(1:natom)%lpawu is directly used in the next three lines, warnings are generated by some compilers.
1059 : : !call init_matlu(natom,nspinor,nsppol,lpawu_natom,glocnm)
1060 : : !call init_matlu(natom,nspinor,nsppol,lpawu_natom,glocnms)
1061 : : !call init_matlu(natom,nspinor,nsppol,lpawu_natom,glocsym)
1062 : : !ABI_FREE(lpawu_natom)
1063 : :
1064 : : !========= Case nspinor ==1 ========================
1065 : :
1066 : : !if (nspinor==1) then
1067 : : ! ispinor=1
1068 : : ! ispinor1=1
1069 : : ! do iatom=1,cryst_struc%natom
1070 : : ! do isppol=1,nsppol
1071 : : ! if(gloc(iatom)%lpawu/=-1) then
1072 : : ! lpawu=gloc(iatom)%lpawu
1073 : : ! do m1=1, 2*lpawu+1
1074 : : ! do m2=1, 2*lpawu+1
1075 : : ! do irot=1,cryst_struc%nsym
1076 : : ! at_indx=cryst_struc%indsym(4,irot,iatom)
1077 : : ! do m3=1, 2*lpawu+1
1078 : : ! do m4=1, 2*lpawu+1
1079 : : ! if(t2g==1) then
1080 : : ! m1s=mt2g(m1)
1081 : : ! m2s=mt2g(m2)
1082 : : ! m3s=mt2g(m3)
1083 : : ! m4s=mt2g(m4)
1084 : : ! lpawu_zarot=2
1085 : : ! else if (x2my2d==1) then
1086 : : ! m1s=mx2my2d
1087 : : ! m2s=mx2my2d
1088 : : ! m3s=mx2my2d
1089 : : ! m4s=mx2my2d
1090 : : ! lpawu_zarot=2
1091 : : ! else
1092 : : ! m1s=m1
1093 : : ! m2s=m2
1094 : : ! m3s=m3
1095 : : ! m4s=m4
1096 : : ! lpawu_zarot=lpawu
1097 : : ! endif
1098 : : ! zarot2=pawang%zarot(m3s,m1s,lpawu_zarot+1,irot)*pawang%zarot(m4s,m2s,lpawu_zarot+1,irot)
1099 : : ! glocsym(iatom)%mat(m1,m2,isppol,ispinor,ispinor1)=&
1100 : : !& glocsym(iatom)%mat(m1,m2,isppol,ispinor,ispinor1)&
1101 : : !& +gloc(at_indx)%mat(m3,m4,isppol,ispinor,ispinor1)*zarot2
1102 : : ! end do ! m3
1103 : : ! end do ! m4
1104 : : ! end do ! irot
1105 : : ! glocsym(iatom)%mat(m1,m2,isppol,ispinor,ispinor1)=&
1106 : : !& glocsym(iatom)%mat(m1,m2,isppol,ispinor,ispinor1)/real(cryst_struc%nsym,kind=dp)
1107 : : ! end do ! m2
1108 : : ! end do ! m1
1109 : : ! endif ! lpawu/=-1
1110 : : ! end do ! isppol
1111 : : ! end do ! iatom
1112 : : !== Put glocsym into gloc
1113 : : ! do iatom=1,cryst_struc%natom
1114 : : ! if(gloc(iatom)%lpawu/=-1) then
1115 : : ! gloc(iatom)%mat=glocsym(iatom)%mat
1116 : : ! gloc(iatom)%mat(:,:,1,:,:)=(glocsym(iatom)%mat(:,:,1,:,:) &
1117 : : !& + glocsym(iatom)%mat(:,:,2,:,:))/two
1118 : : ! gloc(iatom)%mat(:,:,2,:,:)= gloc(iatom)%mat(:,:,1,:,:)
1119 : : ! write(std_out,*) "WARNING: SYM non mag"
1120 : : ! write(ab_out,*) "WARNING: SYM non mag"
1121 : : ! endif
1122 : : ! end do ! iatom
1123 : :
1124 : : !========= Case nspinor ==2 ========================
1125 : :
1126 : : ! else if (nspinor==2) then
1127 : :
1128 : : !== Allocate temporary arrays
1129 : : ! do iatom=1,cryst_struc%natom
1130 : : ! if(gloc(iatom)%lpawu/=-1) then
1131 : : ! ndim=2*gloc(iatom)%lpawu+1
1132 : : ! ABI_FREE(glocnm(iatom)%mat)
1133 : : ! ABI_FREE(glocnms(iatom)%mat)
1134 : : ! ABI_FREE(glocsym(iatom)%mat)
1135 : : ! ABI_MALLOC(glocnm(iatom)%mat,(ndim,ndim,nsppol,4,1))
1136 : : ! ABI_MALLOC(glocnms(iatom)%mat,(ndim,ndim,nsppol,4,1))
1137 : : ! ABI_MALLOC(glocsym(iatom)%mat,(ndim,ndim,nsppol,2,2))
1138 : : ! endif
1139 : : ! enddo
1140 : : ! ABI_MALLOC(symrec_cart,(3,3,cryst_struc%nsym))
1141 : :
1142 : : !== Compute symrec_cart
1143 : : ! do irot=1,cryst_struc%nsym
1144 : : ! call symredcart(cryst_struc%gprimd,cryst_struc%rprimd,symrec_cart(:,:,irot),cryst_struc%symrec(:,:,irot))
1145 : : ! end do
1146 : :
1147 : : !== Compute density matrix in density and magnetization representation
1148 : : ! call chg_repr_matlu(gloc,glocnm,cryst_struc%natom,option=1,prtopt=1)
1149 : :
1150 : : !== Do the sum over symetrized density matrix (in n,m repr)
1151 : : ! isppol=1
1152 : : ! do iatom=1,cryst_struc%natom
1153 : : ! if(gloc(iatom)%lpawu/=-1) then
1154 : : ! lpawu=gloc(iatom)%lpawu
1155 : : ! ndim=2*gloc(iatom)%lpawu+1
1156 : : ! do m1=1, 2*lpawu+1
1157 : : ! do m2=1, 2*lpawu+1
1158 : : ! sumrho=czero
1159 : : ! rotmag=czero
1160 : : ! do irot=1,cryst_struc%nsym
1161 : : ! summag=czero
1162 : : ! at_indx=cryst_struc%indsym(4,irot,iatom)
1163 : : ! do m3=1, 2*lpawu+1
1164 : : ! do m4=1, 2*lpawu+1
1165 : : ! if(t2g==1) then
1166 : : ! m1s=mt2g(m1)
1167 : : ! m2s=mt2g(m2)
1168 : : ! m3s=mt2g(m3)
1169 : : ! m4s=mt2g(m4)
1170 : : ! lpawu_zarot=2
1171 : : !! else if (x2my2d==1) then
1172 : : ! m1s=mx2my2d
1173 : : ! m2s=mx2my2d
1174 : : ! m3s=mx2my2d
1175 : : ! m4s=mx2my2d
1176 : : ! lpawu_zarot=2
1177 : : ! else
1178 : : ! m1s=m1
1179 : : ! m2s=m2
1180 : : ! m3s=m3
1181 : : ! m4s=m4
1182 : : ! lpawu_zarot=lpawu
1183 : : ! endif
1184 : : ! zarot2=pawang%zarot(m3s,m2s,lpawu_zarot+1,irot)*pawang%zarot(m4s,m1s,lpawu_zarot+1,irot)
1185 : : ! sumrho=sumrho + glocnm(at_indx)%mat(m4,m3,isppol,1,1) * zarot2
1186 : : ! do mu=1,3
1187 : : ! summag(mu)=summag(mu) + glocnm(at_indx)%mat(m4,m3,isppol,mu+1,1) * zarot2
1188 : : ! enddo
1189 : : ! end do ! m3
1190 : : ! end do !m4
1191 : :
1192 : : ! == special case of magnetization
1193 : : ! do nu=1,3
1194 : : ! do mu=1,3
1195 : : ! rotmag(mu)=rotmag(mu)+symrec_cart(mu,nu,irot)*summag(nu)
1196 : : ! end do
1197 : : ! end do
1198 : : ! write(std_out,'(a,3i4,2x,3(2f10.5,2x))') "rotmag",irot,m1,m2,(rotmag(mu),mu=1,3)
1199 : : ! end do ! irot
1200 : :
1201 : : ! == Normalizes sum
1202 : : ! sumrho=sumrho/real(cryst_struc%nsym,kind=dp)
1203 : : ! sumrho=glocnm(isppol,1,iatom,m1,m2) ! test without sym
1204 : : ! glocnms(iatom)%mat(m1,m2,isppol,1,1)=sumrho
1205 : : ! do mu=1,3
1206 : : ! rotmag(mu)=rotmag(mu)/real(cryst_struc%nsym,kind=dp)
1207 : : ! rotmag(mu)=glocnm(isppol,mu+1,iatom,m1,m2) ! test without sym
1208 : : ! glocnms(iatom)%mat(m1,m2,isppol,mu+1,1)=rotmag(mu)
1209 : : ! enddo
1210 : : ! end do ! m2
1211 : : ! end do ! m1
1212 : : ! endif ! lpawu/=-1
1213 : : ! end do ! iatom
1214 : :
1215 : : !== Compute back density matrix in upup dndn updn dnup representation
1216 : : ! call chg_repr_matlu(glocsym,glocnms,cryst_struc%natom,option=-1,prtopt=1)
1217 : :
1218 : : !== Put glocsym into gloc
1219 : : ! do iatom=1,cryst_struc%natom
1220 : : ! if(gloc(iatom)%lpawu/=-1) then
1221 : : ! gloc(iatom)%mat=glocsym(iatom)%mat
1222 : : ! gloc(iatom)%mat(:,:,1,:,:)=(glocsym(iatom)%mat(:,:,1,:,:) &
1223 : : !& + glocsym(iatom)%mat(:,:,2,:,:))/two
1224 : : ! gloc(iatom)%mat(:,:,2,:,:)= gloc(iatom)%mat(:,:,1,:,:)
1225 : : ! write(std_out,*) "WARNING: SYM non mag"
1226 : : ! write(ab_out,*) "WARNING: SYM non mag"
1227 : : ! endif
1228 : : ! end do ! iatom
1229 : :
1230 : : ! ABI_FREE(symrec_cart)
1231 : : ! endif
1232 : :
1233 : : ! call destroy_matlu(glocnm,cryst_struc%natom)
1234 : : ! call destroy_matlu(glocnms,cryst_struc%natom)
1235 : : ! call destroy_matlu(glocsym,cryst_struc%natom)
1236 : : ! ABI_FREE(glocnm)
1237 : : ! ABI_FREE(glocnms)
1238 : : ! ABI_FREE(glocsym)
1239 : :
1240 [ - + ]: 87632 : end subroutine sym_matlu
1241 : : !!***
1242 : :
1243 : : !!****f* m_matlu/inverse_matlu
1244 : : !! NAME
1245 : : !! inverse_matlu
1246 : : !!
1247 : : !! FUNCTION
1248 : : !! Inverse local quantity.
1249 : : !!
1250 : : !! COPYRIGHT
1251 : : !! Copyright (C) 2005-2026 ABINIT group (BAmadon)
1252 : : !! This file is distributed under the terms of the
1253 : : !! GNU General Public License, see ~abinit/COPYING
1254 : : !! or http://www.gnu.org/copyleft/gpl.txt .
1255 : : !!
1256 : : !! INPUTS
1257 : : !! matlu(natom) :: input quantity to inverse
1258 : : !! natom=number of atoms in cell.
1259 : : !!
1260 : : !! OUTPUT
1261 : : !! matlu(natom) :: inverse of input matrix
1262 : : !!
1263 : : !! SIDE EFFECTS
1264 : : !!
1265 : : !! NOTES
1266 : : !!
1267 : : !! SOURCE
1268 : :
1269 : 48249 : subroutine inverse_matlu(matlu,natom)
1270 : :
1271 : : !Arguments ------------------------------------
1272 : : integer, intent(in) :: natom
1273 : : type(matlu_type), intent(inout) :: matlu(natom)
1274 : : !Local variables-------------------------------
1275 : : integer :: iatom,isppol,lpawu,ndim,nspinor,nsppol
1276 : : !************************************************************************
1277 : :
1278 : 48249 : nspinor = matlu(1)%nspinor
1279 : 48249 : nsppol = matlu(1)%nsppol
1280 : :
1281 [ + + ]: 124066 : do iatom=1,natom
1282 : 75817 : lpawu = matlu(iatom)%lpawu
1283 [ + + ]: 75817 : if (lpawu == -1) cycle
1284 : 49401 : ndim = nspinor * (2*lpawu+1)
1285 [ + + ]: 188712 : do isppol=1,nsppol
1286 : 166879 : call xginv(matlu(iatom)%mat(:,:,isppol),ndim)
1287 : : end do ! isppol
1288 : : end do ! iatom
1289 : :
1290 : : !if(prtopt>0) then
1291 : : !endif
1292 : : !ABI_MALLOC(gathermatlu,(natom))
1293 : : !do iatom=1,natom
1294 : : ! if(matlu(iatom)%lpawu.ne.-1) then
1295 : : ! tndim=nsppol*nspinor*(2*matlu(iatom)%lpawu+1)
1296 : : ! ABI_MALLOC(gathermatlu(iatom)%value,(tndim,tndim))
1297 : : ! gathermatlu(iatom)%value=czero
1298 : : ! endif
1299 : : !enddo
1300 : :
1301 : : !call gather_matlu(matlu,gathermatlu,natom,option=1,prtopt=1)
1302 : : !do iatom=1,natom
1303 : : ! if(matlu(iatom)%lpawu.ne.-1) then
1304 : : ! tndim=nsppol*nspinor*(2*matlu(iatom)%lpawu+1)
1305 : : !call matcginv_dpc(gathermatlu(iatom)%value,tndim,tndim)
1306 : : ! call xginv(gathermatlu(iatom)%value,tndim)
1307 : : ! endif
1308 : : !enddo
1309 : : !call gather_matlu(matlu,gathermatlu,natom,option=-1,prtopt=1)
1310 : :
1311 : : !do iatom=1,natom
1312 : : ! if(matlu(iatom)%lpawu.ne.-1) then
1313 : : ! ABI_FREE(gathermatlu(iatom)%value)
1314 : : ! endif
1315 : : !enddo
1316 : : !ABI_FREE(gathermatlu)
1317 : :
1318 : 48249 : end subroutine inverse_matlu
1319 : : !!***
1320 : :
1321 : : !!****f* m_matlu/diff_matlu
1322 : : !! NAME
1323 : : !! diff_matlu
1324 : : !!
1325 : : !! FUNCTION
1326 : : !!
1327 : : !! INPUTS
1328 : : !! char1 = character describing matlu1
1329 : : !! char2 = character describing matlu2
1330 : : !! matlu1(natom) <type(matlu_type)>= density matrix 1 in the local orbital basis and related variables
1331 : : !! matlu2(natom) <type(matlu_type)>= density matrix 2 in the local orbital basis and related variables
1332 : : !! natom = number of atoms
1333 : : !! option =1 if diff > toldiff , stop
1334 : : !! 0 print diff and toldiff
1335 : : !! else do not test and do not print
1336 : : !! toldiff = threshold for the difference between matlu1 and matlu2
1337 : : !! zero_or_one = useful when comparing the overlap of Wannier functions at one kpt with the identity
1338 : : !!
1339 : : !! OUTPUT
1340 : : !! ierr = 0 if diff < toldiff
1341 : : !! = -1 otherwise
1342 : : !!
1343 : : !! SOURCE
1344 : :
1345 : 926 : subroutine diff_matlu(char1,char2,matlu1,matlu2,natom,option,toldiff,ierr,zero_or_one)
1346 : :
1347 : : !Arguments ------------------------------------
1348 : : integer, intent(in) :: natom,option
1349 : : type(matlu_type), intent(in) :: matlu1(natom),matlu2(natom)
1350 : : character(len=*), intent(in) :: char1,char2
1351 : : real(dp), intent(in) :: toldiff
1352 : : integer, optional, intent(out) :: ierr
1353 : : integer, optional, intent(in) :: zero_or_one
1354 : : !Local variables-------------------------------
1355 : : integer :: iatom,idiff,lpawu,nspinor,nsppol
1356 : : real(dp) :: matludiff
1357 : : character(len=500) :: message
1358 : : ! *********************************************************************
1359 : :
1360 [ + + ]: 926 : if (option /= 1 .and. option /= 0) return
1361 : :
1362 : 918 : idiff = 0
1363 : 918 : matludiff = zero
1364 : 918 : nspinor = matlu1(1)%nspinor
1365 : 918 : nsppol = matlu1(1)%nsppol
1366 : :
1367 [ + + ]: 3984 : do iatom=1,natom
1368 : 3066 : lpawu = matlu1(iatom)%lpawu
1369 [ + + ]: 3066 : if (lpawu == -1) cycle
1370 [ + + + + : 45413 : matludiff = matludiff + sum(abs(matlu1(iatom)%mat(:,:,:)-matlu2(iatom)%mat(:,:,:)))
+ + ]
1371 : 3984 : idiff = idiff + (2*lpawu+1)**2
1372 : : end do ! iatom
1373 : 918 : idiff = idiff * (nspinor**2) * nsppol
1374 : :
1375 [ + + ]: 918 : if (.not. present(zero_or_one)) matludiff = matludiff / dble(idiff)
1376 : :
1377 [ + + ]: 918 : if (matludiff < toldiff) then
1378 : 845 : write(message,'(5a,6x,3a,4x,e12.4,a,e12.4)') ch10,' ** Differences between ',trim(char1),' and ',&
1379 : 1690 : & ch10,trim(char2),' are small enough:',ch10,matludiff,' is lower than',toldiff
1380 : 845 : call wrtout(std_out,message,'COLL')
1381 [ + + ]: 845 : if (present(ierr)) ierr = 0
1382 : : else
1383 : 73 : write(message,'(5a,3x,3a,3x,e12.4,a,e12.4)') ch10,'Differences between ',trim(char1),' and ',&
1384 : 146 : & ch10,trim(char2),' is too large:',ch10,matludiff,' is larger than',toldiff
1385 : 73 : ABI_WARNING(message)
1386 : : ! write(message,'(8a,4x,e12.4,a,e12.4)') ch10," Matrix for ",trim(char1)
1387 : 73 : write(message,'(a,3x,a)') ch10,trim(char1)
1388 : 73 : call wrtout(std_out,message,'COLL')
1389 : 73 : call print_matlu(matlu1(:),natom,1,opt_diag=-1)
1390 : 73 : write(message,'(a,3x,a)') ch10,trim(char2)
1391 : 73 : call wrtout(std_out,message,'COLL')
1392 : 73 : call print_matlu(matlu2(:),natom,1,opt_diag=-1)
1393 [ - + - - ]: 73 : if (present(zero_or_one) .and. (mod(matludiff,one) < toldiff)) then
1394 : 0 : write(message,'(a,3x,a)') ch10," The norm is not identity for this k-point &
1395 : 0 : & but is compatible with a high symmetry point"
1396 : 0 : call wrtout(std_out,message,'COLL')
1397 : : else if (present(zero_or_one)) then
1398 : 0 : write(message,'(a,3x,a)') ch10," The norm is not identity for this k-point but might be compatible &
1399 : 0 : & with a high symmetry point: it should be checked"
1400 : 0 : call wrtout(std_out,message,'COLL')
1401 [ - + ]: 73 : else if (option == 1) then
1402 : 0 : call flush_unit(std_out)
1403 : 0 : write(message,'(5a,6x,3a,4x,e12.4,a,e12.4)') ch10,' ** Differences between ',trim(char1),' and ',&
1404 : 0 : & ch10,trim(char2),' are too high:',ch10,matludiff,' is greater than',toldiff
1405 : 0 : ABI_ERROR(message)
1406 : : end if ! zero_or_one
1407 [ + + ]: 73 : if (present(ierr)) ierr = -1
1408 : : end if ! matludiff < toldiff
1409 : :
1410 : : end subroutine diff_matlu
1411 : : !!***
1412 : :
1413 : : !!****f* m_matlu/add_matlu
1414 : : !! NAME
1415 : : !! add_matlu
1416 : : !!
1417 : : !! FUNCTION
1418 : : !!
1419 : : !! INPUTS
1420 : : !! matlu1 <type(matlu_type)>= density matrix matlu1 in the local orbital basis and related variables
1421 : : !! matlu2 <type(matlu_type)>= density matrix matlu2 in the local orbital basis and related variables
1422 : : !! natom = number of atoms
1423 : : !! sign_matlu2= 1 add matlu1 and matlu2
1424 : : !! -1 substract matlu2 to matlu1
1425 : : !!
1426 : : !! OUTPUT
1427 : : !! matlu3 <type(matlu_type)>= density matrix matlu3, sum/substract matlu1 and matlu2
1428 : : !!
1429 : : !! SOURCE
1430 : :
1431 : 974058 : subroutine add_matlu(matlu1,matlu2,matlu3,natom,sign_matlu2,idat,ndat)
1432 : :
1433 : : !Arguments ------------------------------------
1434 : : integer, intent(in) :: natom,sign_matlu2
1435 : : integer, optional,intent(in) :: idat,ndat
1436 : : type(matlu_type), intent(in) :: matlu1(natom),matlu2(natom)
1437 : : type(matlu_type), intent(inout) :: matlu3(natom) !vz_i
1438 : : !Local variables-------------------------------
1439 : : integer :: iatom,lpawu,isppol
1440 : : ! *********************************************************************
1441 : :
1442 [ + - ]: 974058 : if(present(idat) .and. present(ndat)) then
1443 [ # # ]: 0 : do iatom=1,natom
1444 : 0 : lpawu = matlu1(iatom)%lpawu
1445 [ # # ]: 0 : if (lpawu == -1) cycle
1446 [ # # ]: 0 : do isppol=1,matlu1(iatom)%nsppol
1447 [ # # ]: 0 : if (sign_matlu2 == 1) then
1448 [ # # # # ]: 0 : matlu3(iatom)%mat(:,:,(isppol-1)*ndat+idat) = matlu1(iatom)%mat(:,:,isppol) + matlu2(iatom)%mat(:,:,isppol)
1449 [ # # ]: 0 : else if (sign_matlu2 == -1) then
1450 [ # # # # ]: 0 : matlu3(iatom)%mat(:,:,(isppol-1)*ndat+idat) = matlu1(iatom)%mat(:,:,isppol) - matlu2(iatom)%mat(:,:,isppol)
1451 : : end if
1452 : : end do ! isppol
1453 : : end do ! iatom
1454 : : else
1455 [ + + ]: 3085443 : do iatom=1,natom
1456 : 2111385 : lpawu = matlu1(iatom)%lpawu
1457 [ + + ]: 2111385 : if (lpawu == -1) cycle
1458 [ + + ]: 1968768 : if (sign_matlu2 == 1) then
1459 [ + + + + : 489568 : matlu3(iatom)%mat(:,:,:) = matlu1(iatom)%mat(:,:,:) + matlu2(iatom)%mat(:,:,:)
+ + ]
1460 [ + - ]: 986294 : else if (sign_matlu2 == -1) then
1461 [ + + + + : 50089479 : matlu3(iatom)%mat(:,:,:) = matlu1(iatom)%mat(:,:,:) - matlu2(iatom)%mat(:,:,:)
+ + ]
1462 : : end if
1463 : : end do ! iatom
1464 : : end if
1465 : :
1466 : 974058 : end subroutine add_matlu
1467 : : !!***
1468 : :
1469 : : !!****f* m_matlu/chg_repr_matlu
1470 : : !! NAME
1471 : : !! chg_repr_matlu
1472 : : !!
1473 : : !! FUNCTION
1474 : : !! Change representation of density matrix (useful for nspinor=2)
1475 : : !!
1476 : : !! COPYRIGHT
1477 : : !! Copyright (C) 2005-2026 ABINIT group (BAmadon)
1478 : : !! This file is distributed under the terms of the
1479 : : !! GNU General Public License, see ~abinit/COPYING
1480 : : !! or http://www.gnu.org/copyleft/gpl.txt .
1481 : : !!
1482 : : !! INPUTS
1483 : : !! glocspsp(natom) :: density matrix in the spin spin representation
1484 : : !! glocnm(natom) :: density matrix in the magnetization representation
1485 : : !! natom=number of atoms in cell.
1486 : : !! option= 1 glocspsp is input, glocnm is computed
1487 : : !! = -1 glocspsp is computed, glocnm is input
1488 : : !! prtopt= abs(prtopt) >= 3 : print in magnetization representation
1489 : : !!
1490 : : !! OUTPUT
1491 : : !! glocspsp(natom) :: density matrix in the spin spin representation
1492 : : !! glocnm(natom) :: density matrix in the magnetization representation
1493 : : !!
1494 : : !! SIDE EFFECTS
1495 : : !!
1496 : : !! NOTES
1497 : : !!
1498 : : !! SOURCE
1499 : :
1500 : 1658 : subroutine chg_repr_matlu(glocspsp,glocnm,natom,option,prtopt)
1501 : :
1502 : : !Arguments ------------------------------------
1503 : : integer, intent(in) :: natom,option,prtopt
1504 : : type(matlu_type), intent(inout), target :: glocnm(natom),glocspsp(natom)
1505 : : !Local variables-------------------------------
1506 : : integer :: iatom,lpawu,m1,m2,mu,ndim,nsppol,isppol,gpu_option
1507 : 1658 : complex(dp), ABI_CONTIGUOUS pointer :: glocnm_mat(:,:,:),glocspsp_mat(:,:,:)
1508 : : character(len=500) :: message
1509 : :
1510 : : ! DBG_ENTER("COLL")
1511 : 0 : ABI_CHECK(glocspsp(1)%nsppol*4==glocnm(1)%nsppol, "Mismatch in nsppol between glocspsp and glocnm")
1512 [ - + ]: 1658 : ABI_CHECK(glocspsp(1)%gpu_option==glocnm(1)%gpu_option, "Mismatch in gpu_option between glocspsp and glocnm")
1513 : 1658 : nsppol=glocspsp(1)%nsppol
1514 : 1658 : gpu_option=glocspsp(1)%gpu_option
1515 : :
1516 : : !== Compute density matrix in density magnetization representation
1517 [ + + ]: 1658 : if (option == 1) then
1518 [ + + ]: 1658 : do iatom=1,natom
1519 : 829 : lpawu = glocspsp(iatom)%lpawu
1520 [ + - ]: 829 : if (lpawu == -1) cycle
1521 : 829 : ndim = 2*lpawu + 1
1522 : 829 : glocnm_mat => glocnm(iatom)%mat
1523 : 829 : glocspsp_mat => glocspsp(iatom)%mat
1524 : :
1525 : : #ifdef HAVE_OPENMP_OFFLOAD
1526 : : !$OMP TARGET TEAMS DISTRIBUTE PRIVATE(isppol) MAP(to:glocnm_mat,glocspsp_mat) &
1527 : : !$OMP& IF(gpu_option==ABI_GPU_OPENMP)
1528 : : #endif
1529 [ + + ]: 1658 : do isppol=1,nsppol
1530 : : !$OMP PARALLEL DO COLLAPSE(2) PRIVATE(m1,m2)
1531 [ + + ]: 7461 : do m2=1,ndim
1532 [ + + ]: 47253 : do m1=1,ndim
1533 : 40621 : glocnm_mat(m1,m2,1+(isppol-1)*4) = glocspsp_mat(m1,m2, isppol) + glocspsp_mat(m1+ndim,m2+ndim,isppol)
1534 : 40621 : glocnm_mat(m1,m2,4+(isppol-1)*4) = glocspsp_mat(m1,m2, isppol) - glocspsp_mat(m1+ndim,m2+ndim,isppol)
1535 : 40621 : glocnm_mat(m1,m2,2+(isppol-1)*4) = glocspsp_mat(m1,m2+ndim,isppol) + glocspsp_mat(m1+ndim,m2,isppol)
1536 : 46424 : glocnm_mat(m1,m2,3+(isppol-1)*4) = (glocspsp_mat(m1,m2+ndim,isppol) - glocspsp_mat(m1+ndim,m2,isppol)) * j_dpc
1537 : : end do ! m1
1538 : : end do ! m2
1539 : : end do ! isppol
1540 : :
1541 [ - + ]: 1658 : if (abs(prtopt) >= 3) then
1542 : : #ifdef HAVE_OPENMP_OFFLOAD
1543 : : !$OMP TARGET UPDATE FROM(glocnm) IF(gpu_option==ABI_GPU_OPENMP)
1544 : : #endif
1545 : 0 : write(message,'(a)') " -- in n, m repr "
1546 : 0 : call wrtout(std_out,message,'COLL')
1547 [ # # ]: 0 : do mu=1,4
1548 [ # # ]: 0 : do m1=1,ndim
1549 [ # # # # ]: 0 : write(message,'(8x,(14(2f9.5,2x)))') (glocnm(iatom)%mat(m1,m2,isppol+mu-1),m2=1,ndim)
1550 : 0 : call wrtout(std_out,message,'COLL')
1551 : : end do ! m1
1552 : 0 : write(message,'(a)') ch10
1553 : 0 : call wrtout(std_out,message,'COLL')
1554 : : end do ! mu
1555 : : end if ! prtopt >3
1556 : : end do ! iatom
1557 : :
1558 : : !== Compute back density matrix in upup dndn updn dnup representation
1559 [ + - ]: 829 : else if (option == -1) then
1560 : :
1561 [ + + ]: 1658 : do iatom=1,natom
1562 : 829 : lpawu = glocnm(iatom)%lpawu
1563 [ + - ]: 829 : if (lpawu == -1) cycle
1564 : 829 : ndim = 2*lpawu + 1
1565 : 829 : glocnm_mat => glocnm(iatom)%mat
1566 : 829 : glocspsp_mat => glocspsp(iatom)%mat
1567 : :
1568 : : #ifdef HAVE_OPENMP_OFFLOAD
1569 : : !$OMP TARGET TEAMS DISTRIBUTE PRIVATE(isppol) MAP(to:glocnm_mat,glocspsp_mat) &
1570 : : !$OMP& IF(gpu_option==ABI_GPU_OPENMP)
1571 : : #endif
1572 [ + + ]: 2487 : do isppol=1,nsppol
1573 : : !$OMP PARALLEL DO COLLAPSE(2) PRIVATE(m1,m2)
1574 [ + + ]: 7461 : do m2=1,ndim
1575 [ + + ]: 47253 : do m1=1,ndim
1576 : : glocspsp_mat(m1,m2,isppol) = &
1577 : 40621 : & half * (glocnm_mat(m1,m2,1+(isppol-1)*4)+glocnm_mat(m1,m2,4+(isppol-1)*4))
1578 : : glocspsp_mat(m1+ndim,m2+ndim,isppol) = &
1579 : 40621 : & half * (glocnm_mat(m1,m2,1+(isppol-1)*4)-glocnm_mat(m1,m2,4+(isppol-1)*4))
1580 : : glocspsp_mat(m1,m2+ndim,isppol) = &
1581 : 40621 : & half * (glocnm_mat(m1,m2,2+(isppol-1)*4)-j_dpc*glocnm_mat(m1,m2,3+(isppol-1)*4))
1582 : : glocspsp_mat(m1+ndim,m2,isppol) = &
1583 : 46424 : & half * (glocnm_mat(m1,m2,2+(isppol-1)*4)+j_dpc*glocnm_mat(m1,m2,3+(isppol-1)*4))
1584 : : end do ! m1
1585 : : end do ! m2
1586 : : end do ! isppol
1587 : : !if (abs(prtopt) > 6) then
1588 : : ! write(message,'(a)') " -- in spin spin repr "
1589 : : ! call wrtout(std_out,message,'COLL')
1590 : : ! do mu=1,4
1591 : : ! do m1=1,ndim
1592 : : ! write(message,'(8x,14(2f9.5,2x))') (glocspsp(iatom)%mat(m1,m2,isppol,mu,1),m2=1,ndim)
1593 : : ! call wrtout(std_out, message,'COLL')
1594 : : ! end do ! m1
1595 : : ! write(message,'(a)') ch10
1596 : : ! call wrtout(std_out,message,'COLL')
1597 : : ! end do
1598 : : !end if ! prtopt>6
1599 : : end do ! iatom
1600 : : else
1601 : 0 : message = "stop in chg_repr_matlu"
1602 : 0 : ABI_ERROR(message)
1603 : : end if ! option
1604 : :
1605 : : ! DBG_EXIT("COLL")
1606 : :
1607 [ - + ]: 1658 : end subroutine chg_repr_matlu
1608 : : !!***
1609 : :
1610 : : !!****f* m_matlu/trace_matlu
1611 : : !! NAME
1612 : : !! trace_matlu
1613 : : !!
1614 : : !! FUNCTION
1615 : : !! Compute the trace of the matlu matrix
1616 : : !!
1617 : : !! INPUTS
1618 : : !! matlu(natom) <type(matlu_type)>= density matrix in the
1619 : : !! local orbital basis and related variables
1620 : : !! natom = number of atoms
1621 : : !! itau = flag for print
1622 : : !! not present (default) : occupations from G(iw)
1623 : : !! = 1 : occupations from G(tau)
1624 : : !! = -1 : occupations from G0(tau)
1625 : : !! = 4 : trace of matlu
1626 : : !!
1627 : : !! OUTPUT
1628 : : !! trace_loc(nsppol+1,natom)= trace for each atom and each polarization,
1629 : : !! trace_loc(iatom,nsppol+1) is
1630 : : !! the full trace over all polarizations
1631 : : !! trace= trace over all correlated atoms
1632 : : !!
1633 : : !! SOURCE
1634 : :
1635 : 779 : subroutine trace_matlu(matlu,natom,trace_loc,itau,trace)
1636 : :
1637 : : !Arguments ------------------------------------
1638 : : integer, intent(in) :: natom
1639 : : type(matlu_type), intent(in) :: matlu(natom)
1640 : : real(dp), target, optional, intent(inout) :: trace_loc(matlu(1)%nsppol+1,natom)
1641 : : integer, optional, intent(in) :: itau
1642 : : complex(dp), optional, intent(out) :: trace
1643 : : !Local variables-------------------------------
1644 : : integer :: iatom,im,isppol,lpawu,ndim,nspinor,nsppol
1645 : : complex(dp) :: trace_tmp,trace_tmp2
1646 : : real(dp), ABI_CONTIGUOUS pointer :: traceloc(:,:) => null()
1647 : : character(len=4) :: tag
1648 : : character(len=12) :: tag_nb_elec
1649 : : character(len=500) :: message
1650 : : ! *********************************************************************
1651 : :
1652 : 780 : nspinor = matlu(1)%nspinor
1653 : 780 : nsppol = matlu(1)%nsppol
1654 : :
1655 [ + + ]: 780 : if (present(trace_loc)) then
1656 : 779 : traceloc => trace_loc(:,:)
1657 : : else
1658 [ + - - + : 4 : ABI_MALLOC(traceloc,(nsppol+1,natom))
+ - - + +
- + - + -
- + - + ]
1659 : : end if
1660 : :
1661 : 780 : trace_tmp = czero
1662 [ + + + + ]: 9893 : traceloc(:,:) = zero
1663 : :
1664 [ + + ]: 3489 : do iatom=1,natom
1665 : :
1666 : 2709 : lpawu = matlu(iatom)%lpawu
1667 [ + + ]: 2709 : if (lpawu == -1) cycle
1668 : :
1669 : 912 : ndim = nspinor * (2*lpawu+1)
1670 : 912 : write(tag,'(i4)') iatom
1671 : 912 : write(message,'(3a)') ch10,' -------> For Correlated Atom ',adjustl(tag)
1672 [ + + ]: 912 : if (.not. present(itau)) then
1673 : 911 : call wrtout(std_out,message,'COLL')
1674 : : end if
1675 : :
1676 : : if (present(itau)) then
1677 [ - + ]: 1 : if (itau > 0) then
1678 : 1 : call wrtout(std_out,message,'COLL')
1679 : : end if
1680 : : end if ! present(itau)
1681 : :
1682 [ + + ]: 2293 : do isppol=1,nsppol
1683 : : trace_tmp2 = czero
1684 [ + + ]: 7809 : do im=1,ndim
1685 : 7809 : trace_tmp2 = trace_tmp2 + matlu(iatom)%mat(im,im,isppol)
1686 : : end do ! im
1687 : 1381 : trace_tmp = trace_tmp + trace_tmp2
1688 : 1381 : traceloc(isppol,iatom) = dble(trace_tmp2)
1689 : 2293 : traceloc(nsppol+1,iatom) = traceloc(nsppol+1,iatom) + traceloc(isppol,iatom)
1690 : : end do ! isppol
1691 [ + + ]: 912 : if (nsppol == 1 .and. nspinor == 1) traceloc(nsppol+1,iatom) = traceloc(nsppol+1,iatom) * two
1692 : 912 : write(tag_nb_elec,'(f12.6)') traceloc(nsppol+1,iatom)
1693 : 912 : tag_nb_elec = adjustl(tag_nb_elec)
1694 [ + + ]: 912 : if (.not. present(itau)) then
1695 : 911 : write(message,'(8x,2a)') 'Nb of Corr. elec. from G(iw) is: ',tag_nb_elec
1696 : 911 : call wrtout(std_out,message,'COLL')
1697 : : end if ! not present(itau)
1698 : 780 : if (present(itau)) then
1699 [ + - ]: 1 : if (itau == 1) then
1700 : 1 : write(message,'(8x,2a)') 'Nb of Corr. elec. from G(tau=0-) is: ',tag_nb_elec
1701 : 1 : call wrtout(std_out,message,'COLL')
1702 [ # # ]: 0 : else if (itau == -1) then
1703 : 0 : write(message,'(8x,2a)') 'Nb: Sum of the values of G0(tau=0-) is: ',tag_nb_elec
1704 : 0 : call wrtout(std_out,message,'COLL')
1705 [ # # ]: 0 : else if (itau == 4) then
1706 : 0 : write(message,'(8x,2a)') 'Trace of matlu matrix is: ',tag_nb_elec
1707 : 0 : call wrtout(std_out,message,'COLL')
1708 : : end if ! itau
1709 : : end if ! present(itau)
1710 : : end do ! iatom
1711 : :
1712 [ - + ]: 780 : if (present(trace)) then
1713 [ # # ]: 0 : if (nsppol == 1 .and. nspinor == 1) trace_tmp = trace_tmp * two
1714 : 0 : trace = trace_tmp
1715 : : end if ! present(trace)
1716 : :
1717 [ + + ]: 780 : if (nsppol > 1 .and. (.not. present(trace))) then
1718 [ + + ]: 1323 : do iatom=1,natom
1719 : 986 : lpawu = matlu(iatom)%lpawu
1720 [ + + ]: 986 : if (lpawu == -1) cycle
1721 : : !! MAG
1722 : : ! if(nsppol>1.and.present(itau)) then
1723 : : ! if(itau==1) then
1724 : 469 : write(tag_nb_elec,'(f12.6)') traceloc(2,iatom) - traceloc(1,iatom)
1725 : 469 : write(message,'(8x,2a)') 'DMFT Corr. Elec. Mag.: ',adjustl(tag_nb_elec)
1726 : 1323 : call wrtout(std_out,message,'COLL')
1727 : : ! endif
1728 : : end do ! iatom
1729 : : end if ! nsppol>1
1730 : :
1731 [ + + ]: 780 : if (.not. present(trace_loc)) then
1732 [ - + ]: 1 : ABI_FREE(traceloc)
1733 : : end if
1734 : 780 : traceloc => null()
1735 : :
1736 [ + + ]: 780 : end subroutine trace_matlu
1737 : : !!***
1738 : :
1739 : : !!****f* m_matlu/gather_matlu
1740 : : !! NAME
1741 : : !! gather_matlu
1742 : : !!
1743 : : !! FUNCTION
1744 : : !! Create new array from matlu
1745 : : !!
1746 : : !! COPYRIGHT
1747 : : !! Copyright (C) 2005-2026 ABINIT group (BAmadon)
1748 : : !! This file is distributed under the terms of the
1749 : : !! GNU General Public License, see ~abinit/COPYING
1750 : : !! or http://www.gnu.org/copyleft/gpl.txt .
1751 : : !!
1752 : : !! INPUTS
1753 : : !! gloc(natom) <type(matlu_type)> = density matrix in the spin spin representation
1754 : : !! gatherloc(natom) <type(coeff2c_type)> = density matrix where spin and angular momentum are gathered in the same index
1755 : : !! natom=number of atoms in cell.
1756 : : !! option= 1 go from gloc to gathergloc
1757 : : !! option= -1 go from gathergloc to gloc
1758 : : !! prtopt= option to define level of printing
1759 : : !!
1760 : : !! OUTPUT
1761 : : !! gloc(natom) <type(matlu_type)> = density matrix in the spin spin representation
1762 : : !! gatherloc(natom) <type(coeff2c_type)> = density matrix where spin and angular momentum are gathered in the same index
1763 : : !!
1764 : : !! SIDE EFFECTS
1765 : : !!
1766 : : !! SOURCE
1767 : 0 : subroutine gather_matlu(gloc,gathergloc,natom,option,prtopt)
1768 : :
1769 : : use defs_wvltypes
1770 : : use m_crystal, only : crystal_t
1771 : :
1772 : : ! type matlus_type
1773 : : ! SEQUENCE
1774 : : ! complex(dp), pointer :: mat(:,:)
1775 : : ! end type matlus_type
1776 : :
1777 : : !Arguments ------------------------------------
1778 : : !scalars
1779 : : integer,intent(in) :: natom,option,prtopt
1780 : : type(coeff2c_type), intent(inout) :: gathergloc(natom)
1781 : : type(matlu_type),intent(inout) :: gloc(natom)
1782 : : !Local variables-------------------------------
1783 : : !scalars
1784 : : integer :: iatom,im1,im2,ispinor,ispinor1,isppol,isppol1
1785 : : integer :: jc1,jc2,ml1,ml2,ndim,nspinor,nsppol,tndim
1786 : : character(len=500) :: message
1787 : :
1788 : : ! DBG_ENTER("COLL")
1789 : 0 : nsppol=gloc(1)%nsppol
1790 : 0 : nspinor=gloc(1)%nspinor
1791 : :
1792 [ # # ]: 0 : do iatom=1,natom
1793 [ # # ]: 0 : if(gloc(iatom)%lpawu.ne.-1) then
1794 : : !==-------------------------------------
1795 : :
1796 : 0 : ndim=2*gloc(iatom)%lpawu+1
1797 : 0 : tndim=nsppol*nspinor*ndim
1798 : :
1799 : : !== Put norm into array "gathergloc"
1800 : 0 : jc1=0
1801 [ # # ]: 0 : do isppol=1,nsppol
1802 [ # # ]: 0 : do ispinor=1,nspinor
1803 [ # # ]: 0 : do ml1=1,ndim
1804 : 0 : jc1=jc1+1
1805 : 0 : jc2=0
1806 [ # # ]: 0 : do isppol1=1,nsppol
1807 [ # # ]: 0 : do ispinor1=1,nspinor
1808 [ # # ]: 0 : do ml2=1,ndim
1809 : 0 : jc2=jc2+1
1810 [ # # ]: 0 : if(option==1) then
1811 [ # # ]: 0 : if(isppol==isppol1) then
1812 : 0 : gathergloc(iatom)%value(jc1,jc2)=gloc(iatom)%mat(ml1+(ispinor-1)*ndim,ml2+(ispinor1-1)*ndim,isppol)
1813 : : endif
1814 [ # # ]: 0 : else if(option==-1) then
1815 [ # # ]: 0 : if(isppol==isppol1) then
1816 : 0 : gloc(iatom)%mat(ml1+(ispinor-1)*ndim,ml2+(ispinor1-1)*ndim,isppol)=gathergloc(iatom)%value(jc1,jc2)
1817 : : endif
1818 : : endif
1819 : : enddo
1820 : : enddo ! ispinor1
1821 : : enddo ! isppol1
1822 : : enddo
1823 : : enddo !ispinor
1824 : : enddo ! isppol
1825 : : endif
1826 : : enddo ! iatom
1827 [ # # # # ]: 0 : if(option==1.and.prtopt==3) then
1828 [ # # ]: 0 : do iatom=1,natom
1829 [ # # ]: 0 : if(gloc(iatom)%lpawu.ne.-1) then
1830 : 0 : tndim=nsppol*nspinor*(2*gloc(iatom)%lpawu+1)
1831 : 0 : write(message,'(2a,i5)') ch10,' (gathermatlu:) For atom', iatom
1832 : 0 : call wrtout(std_out,message,'COLL')
1833 [ # # ]: 0 : do im1=1,tndim
1834 : : write(message,'(12(1x,18(1x,"(",f9.3,",",f9.3,")")))')&
1835 [ # # # # ]: 0 : & (gathergloc(iatom)%value(im1,im2),im2=1,tndim)
1836 : 0 : call wrtout(std_out,message,'COLL')
1837 : : end do
1838 : : endif
1839 : : enddo ! iatom
1840 [ # # # # ]: 0 : else if(option==-1.and.prtopt==3) then
1841 : 0 : call print_matlu(gloc,natom,prtopt)
1842 : : endif
1843 : :
1844 : :
1845 : :
1846 : : ! DBG_EXIT("COLL")
1847 : :
1848 : 0 : end subroutine gather_matlu
1849 : : !!***
1850 : :
1851 : : !!****f* m_matlu/diag_matlu
1852 : : !! NAME
1853 : : !! diag_matlu
1854 : : !!
1855 : : !! FUNCTION
1856 : : !! Diagonalize hermitian matlu matrix
1857 : : !!
1858 : : !! COPYRIGHT
1859 : : !! Copyright (C) 2005-2026 ABINIT group (BAmadon)
1860 : : !! This file is distributed under the terms of the
1861 : : !! GNU General Public License, see ~abinit/COPYING
1862 : : !! or http://www.gnu.org/copyleft/gpl.txt .
1863 : : !!
1864 : : !! INPUTS
1865 : : !! matlu(natom) :: input quantity to diagonalize (careful, matlu must be hermitian)
1866 : : !! natom=number of atoms
1867 : : !! prtopt: >=3 : print eigenvectors
1868 : : !! >=4 : print matlu before diagonalization
1869 : : !! nsppol_imp= if 1, one can diagonalize with the same matrix the Up
1870 : : !! and Dn matlu matrix. It is convenient because one can thus have the
1871 : : !! same interaction matrix for up and dn spins. Default is nsppol.
1872 : : !! checkstop= if true (default), print the matrix for spin down in the diagonalization basis of spin up
1873 : : !! (useful when nsppol=2 and nsppol_imp=1)
1874 : : !! optreal= diagonalize the real matrix if max(imag(matlu)) < 1e-6
1875 : : !! test= if 8 or 10, use the block diagonalization algorithm (8 for real and 10 for complex)
1876 : : !!
1877 : : !! OUTPUT
1878 : : !! matlu_diag(natom) :: diagonalized density matrix
1879 : : !! eigvectmatlu(natom) = Eigenvectors corresponding to the diagonalization
1880 : : !!
1881 : : !! SIDE EFFECTS
1882 : : !!
1883 : : !! NOTES
1884 : : !!
1885 : : !! SOURCE
1886 : :
1887 : 189 : subroutine diag_matlu(matlu,matlu_diag,natom,prtopt,eigvectmatlu,nsppol_imp,checkstop,opt_real,test)
1888 : :
1889 : : !Arguments ------------------------------------
1890 : : integer, intent(in) :: natom,prtopt
1891 : : type(matlu_type), intent(in) :: matlu(natom)
1892 : : type(matlu_type), intent(inout) :: eigvectmatlu(natom),matlu_diag(natom) !vz_i
1893 : : integer, optional, intent(in) :: nsppol_imp,opt_real,test
1894 : : logical, optional, intent(in) :: checkstop
1895 : : !Local variables-------------------------------
1896 : : integer :: iatom,im1,im2,info,isppol,lpawu,lwork,lworkr
1897 : : integer :: nspinor,nsppol,nsppolimp,optreal,tndim
1898 : : logical :: blockdiag,blockdiagc,checkstop_in,print_temp_mat2
1899 : : character(len=4) :: tag
1900 : : character(len=500) :: message
1901 : 189 : real(dp), allocatable :: eig(:),rwork(:),valuer(:,:),work(:)!,valuer2(:,:)
1902 : : !real(dp),allocatable :: valuer3(:,:),valuer4(:,:)
1903 : : ! real(dp),allocatable :: eigvec(:,:)
1904 : 189 : complex(dp), allocatable :: temp_mat(:,:),zwork(:)
1905 : : !debug complex(dp),allocatable :: temp_mat3(:,:)
1906 : : !************************************************************************
1907 : :
1908 : 189 : blockdiag = .false.
1909 : 189 : blockdiagc = .false.
1910 : 189 : checkstop_in = .true.
1911 : 189 : nspinor = matlu(1)%nspinor
1912 : 189 : nsppol = matlu(1)%nsppol
1913 : 189 : nsppolimp = nsppol
1914 : 189 : optreal = 0
1915 : :
1916 [ + + ]: 189 : if (present(nsppol_imp)) nsppolimp = nsppol_imp
1917 [ + + ]: 189 : if (present(checkstop)) checkstop_in = checkstop
1918 [ + + ]: 189 : if (present(test)) blockdiag = (test == 8 )
1919 : 175 : if (present(test)) blockdiagc = ( test == 10)
1920 [ + + ]: 189 : if (present(opt_real)) optreal = opt_real
1921 : :
1922 : 189 : call zero_matlu(matlu_diag(:),natom)
1923 : 189 : call copy_matlu(matlu(:),eigvectmatlu(:),natom)
1924 : :
1925 : : !donotdiag=.true.
1926 : : !donotdiag=.false.
1927 : : ! ===========================
1928 : : ! Check is diagonalization is necessary and how
1929 : : ! ===========================
1930 : : !do isppol=1,matlu(1)%nsppol
1931 : : ! do iatom=1,natom
1932 : : ! if(matlu(iatom)%lpawu.ne.-1) then
1933 : : ! tndim=(2*matlu(iatom)%lpawu+1)
1934 : : ! do im1=1,tndim
1935 : : ! do im2=1,tndim
1936 : : ! do ispinor=1,nspinor
1937 : : ! do ispinor1=1,nspinor
1938 : : ! if(abs(matlu(iatom)%mat(im1,im2,isppol,ispinor,ispinor1))>tol8.and.&
1939 : : !& (im1/=im2.or.ispinor/=ispinor1)) then
1940 : : ! if matrix is diagonal: do not diagonalize
1941 : : ! donotdiag=.false.
1942 : : ! exit
1943 : : ! endif
1944 : : ! enddo
1945 : : ! enddo
1946 : : ! enddo
1947 : : ! enddo
1948 : : ! endif
1949 : : ! enddo
1950 : : !enddo
1951 : :
1952 : : !if(donotdiag) then
1953 : : ! do isppol=1,matlu(1)%nsppol
1954 : : ! do iatom=1,natom
1955 : : ! if(matlu(iatom)%lpawu.ne.-1) then
1956 : : ! tndim=(2*matlu(iatom)%lpawu+1)
1957 : : ! eigvectmatlu(iatom,isppol)%value(:,:)=czero
1958 : : ! do im1=1,tndim
1959 : : ! eigvectmatlu(iatom,isppol)%value(im1,im1)=cone
1960 : : ! enddo
1961 : : ! endif
1962 : : ! enddo
1963 : : ! enddo
1964 : : ! call copy_matlu(matlu,matlu_diag,natom)
1965 : : ! write(message,'(a)') " Diagonalisation of matlu will not be performed"
1966 : : ! call wrtout(std_out,message,'COLL')
1967 : : ! return
1968 : : !endif
1969 : :
1970 : : ! For nsppol=2, and if nsppolimp=1, the eigenvectors are computed for isppol=1, and applied through
1971 : : ! rotate_matlu to isppol=2. It is the reason why the sum below is only from 1 to nsppolimp !
1972 : :
1973 [ + + ]: 875 : do iatom=1,natom
1974 : :
1975 : 686 : lpawu = matlu(iatom)%lpawu
1976 [ + + ]: 686 : if (lpawu == -1) cycle
1977 : 237 : write(tag,'(i4)') iatom
1978 : 237 : tndim = nspinor * (2*lpawu+1)
1979 : 237 : lwork = 2*tndim - 1
1980 : 237 : lworkr = tndim * (tndim+2) * 2
1981 [ - + + - : 711 : ABI_MALLOC(eig,(tndim))
+ - + - -
+ - + ]
1982 : :
1983 : : ! ===========================
1984 : : ! Define gathermatlu
1985 : : ! ===========================
1986 : : !ABI_MALLOC(gathermatlu,(natom))
1987 : : !do iatom=1,natom
1988 : : ! if(matlu(iatom)%lpawu.ne.-1) then
1989 : : ! tndim=nspinor*(2*matlu(iatom)%lpawu+1)
1990 : : ! ABI_MALLOC(gathermatlu(iatom)%value,(tndim,tndim))
1991 : : ! gathermatlu(iatom)%value=czero
1992 : : ! endif
1993 : : !enddo
1994 : : !if(nsppol==1.and.nspinor==2) then
1995 : : ! call gather_matlu(matlu,gathermatlu,natom,option=1,prtopt=1)
1996 : : !else if((nsppol==2.or.nsppol==1).and.nspinor==1) then
1997 : : ! do iatom=1,natom
1998 : : ! if(matlu(iatom)%lpawu.ne.-1) then
1999 : : ! tndim=nspinor*(2*matlu(iatom)%lpawu+1)
2000 : : ! do im1=1,tndim
2001 : : ! do im2=1,tndim
2002 : : ! gathermatlu(iatom)%value(im1,im2)=matlu(iatom)%mat(im1,im2,isppol,1,1)
2003 : : ! enddo
2004 : : ! enddo
2005 : : ! endif
2006 : : ! enddo
2007 : : !endif
2008 : :
2009 : : ! ===========================
2010 : : ! Diagonalize
2011 : : ! ===========================
2012 [ + + ]: 599 : do isppol=1,nsppolimp
2013 : : !debug allocate(temp_mat2(tndim,tndim))
2014 : : !debug temp_mat2=zero
2015 : : ! ABI_MALLOC(valuer2,(tndim,tndim))
2016 : : ! ABI_MALLOC(valuer3,(tndim,tndim))
2017 : : ! ABI_MALLOC(valuer4,(tndim,tndim))
2018 : : ! valuer2=zero
2019 : : ! valuer3=zero
2020 : : ! valuer4=zero
2021 [ + + ]: 362 : if (prtopt >= 4) then
2022 : 14 : write(message,'(a,i4,a,i4)') " BEFORE DIAGONALIZATION for atom",iatom," and isppol",isppol
2023 : 14 : call wrtout(std_out,message,'COLL')
2024 [ + + ]: 112 : do im1=1,tndim
2025 [ + - + + ]: 784 : write(message,'(12(1x,18(1x,"(",f9.3,",",f9.3,")")))') (matlu(iatom)%mat(im1,im2,isppol),im2=1,tndim)
2026 : 112 : call wrtout(std_out,message,'COLL')
2027 : : end do ! im1
2028 : : end if ! prtopt>=4
2029 : : !debug temp_mat2(:,:)=gathermatlu(iatom)%value(:,:)
2030 : : ! write(std_out,*)"diag"
2031 : :
2032 [ + + + + : 11186 : if (optreal == 1 .and. maxval(abs(aimag(matlu(iatom)%mat(:,:,isppol)))) < tol6 ) then
+ + + - -
+ - - + +
+ + ]
2033 : 142 : write(message,'(a,2x,a,e9.3,a)') ch10,"Imaginary part of Local Hamiltonian is lower than ",&
2034 : 284 : & tol6,": the real matrix is used"
2035 : 142 : call wrtout(std_out,message,'COLL')
2036 [ - + + - : 568 : ABI_MALLOC(valuer,(tndim,tndim))
- + + - +
- + - - +
- + ]
2037 [ + + + + ]: 3786 : valuer(:,:) = dble(matlu(iatom)%mat(:,:,isppol))
2038 : : ! write(message,'(a)') ch10
2039 : : ! call wrtout(std_out,message,'COLL')
2040 : : ! write(message,'(a,i4,a,i4)') "BEFORE valuer for atom",iatom," and isppol",isppol
2041 : : ! call wrtout(std_out,message,'COLL')
2042 : : ! do im1=1,tndim
2043 : : ! write(message,'(2(1x,18(1x,"(",f20.15,",",f20.15,")")))')&
2044 : : !& (valuer(im1,im2),im2=1,tndim)
2045 : : ! call wrtout(std_out,message,'COLL')
2046 : : ! end do
2047 : : ! do im1=1,tndim
2048 : : ! valuer(im1,im1)=real(im1,kind=dp)*0.00000000001_dp+valuer(im1,im1)
2049 : : ! enddo
2050 : : ! write(message,'(a)') ch10
2051 : : ! call wrtout(std_out,message,'COLL')
2052 : : ! write(message,'(a,i4,a,i4)') "BEFORE valuer for atom",iatom," and isppol",isppol
2053 : : ! call wrtout(std_out,message,'COLL')
2054 : : ! do im1=1,tndim
2055 : : ! write(message,'(2(1x,18(1x,f20.15,f20.15)))')&
2056 : : !& (valuer(im1,im2),im2=1,tndim)
2057 : : ! call wrtout(std_out,message,'COLL')
2058 : : ! end do
2059 : : !call dsyev('v','u',tndim,valuer,tndim,eig,work,lworkr,info)
2060 [ - + ]: 142 : if (blockdiag .or. blockdiagc) then
2061 : 0 : call blockdiago_fordsyev(valuer(:,:),tndim,eig(:))
2062 : : else
2063 [ - + + - : 426 : ABI_MALLOC(work,(lworkr))
+ - + - -
+ - + ]
2064 : 142 : call dsyev('v','u',tndim,valuer(:,:),tndim,eig(:),work(:),lworkr,info)
2065 [ - + ]: 142 : ABI_FREE(work)
2066 : : end if ! blockdiag
2067 : : !! For reproductibility
2068 : : ! ! valuer2: eigenvector for the perturb matrix
2069 : : ! valuer2=real(gathermatlu(iatom)%value,kind=dp)
2070 : : ! do im1=1,tndim
2071 : : ! valuer2(im1,im1)=float(im1)*0.00000000001+valuer2(im1,im1)
2072 : : ! enddo
2073 : : ! call dsyev('v','u',tndim,valuer2,tndim,eig,work,lworkr,info)
2074 : : ! write(message,'(a)') ch10
2075 : : ! call wrtout(std_out,message,'COLL')
2076 : : ! write(message,'(a,i4,a,i4)') " valuer2 for atom",iatom," and isppol",isppol
2077 : : ! call wrtout(std_out,message,'COLL')
2078 : : ! do im1=1,tndim
2079 : : ! write(message,'(12(1x,18(1x,"(",f9.3,",",f9.3,")")))')&
2080 : : !& (valuer2(im1,im2),im2=1,tndim)
2081 : : ! call wrtout(std_out,message,'COLL')
2082 : : ! end do
2083 : : ! call dgemm('n','n',tndim,tndim,tndim,cone,valuer,tndim,&
2084 : : !& valuer2,tndim,czero,valuer3 ,tndim)
2085 : : ! call dgemm('c','n',tndim,tndim,tndim,cone,valuer2,tndim,&
2086 : : !& valuer3 ,tndim,czero,valuer4,tndim)
2087 : : ! ! valuer4: compute unpert matrix in the basis of the
2088 : : ! ! perturb basis
2089 : : ! write(message,'(a)') ch10
2090 : : ! call wrtout(std_out,message,'COLL')
2091 : : ! write(message,'(a,i4,a,i4)') "BEFORE valuer4 for atom",iatom," and isppol",isppol
2092 : : ! call wrtout(std_out,message,'COLL')
2093 : : ! do im1=1,tndim
2094 : : ! write(message,'(12(1x,18(1x,"(",f9.3,",",f9.3,")")))')&
2095 : : !& (valuer4(im1,im2),im2=1,tndim)
2096 : : ! call wrtout(std_out,message,'COLL')
2097 : : ! end do
2098 : : ! call dsyev('v','u',tndim,valuer4,tndim,eig,work,lworkr,info)
2099 : : ! ! valuer4: Diago valuer4 (nearly diag)
2100 : : ! write(message,'(a)') ch10
2101 : : ! call wrtout(std_out,message,'COLL')
2102 : : ! write(message,'(a,i4,a,i4)') "AFTER valuer4 for atom",iatom," and isppol",isppol
2103 : : ! call wrtout(std_out,message,'COLL')
2104 : : ! do im1=1,tndim
2105 : : ! write(message,'(12(1x,18(1x,"(",f9.3,",",f9.3,")")))')&
2106 : : !& (valuer4(im1,im2),im2=1,tndim)
2107 : : ! call wrtout(std_out,message,'COLL')
2108 : : ! end do
2109 : : ! call dgemm('n','n',tndim,tndim,tndim,cone,valuer2,tndim,&
2110 : : !& valuer4,tndim,czero,valuer ,tndim)
2111 : : !write(6,*) "INFO",info
2112 [ + + + + ]: 3786 : eigvectmatlu(iatom)%mat(:,:,isppol) = cmplx(valuer(:,:),zero,kind=dp)
2113 [ - + ]: 142 : ABI_FREE(valuer)
2114 : : ! write(message,'(a,i4,a,i4)') "AFTER valuer for atom",iatom," and isppol",isppol
2115 : : ! call wrtout(std_out,message,'COLL')
2116 : : ! do im1=1,tndim
2117 : : ! write(message,'(2(1x,18(1x,"(",f20.15,",",f20.15,")")))')&
2118 : : !& (valuer(im1,im2),im2=1,tndim)
2119 : : ! call wrtout(std_out,message,'COLL')
2120 : : ! end do
2121 : : else
2122 : :
2123 [ - + ]: 220 : if (blockdiagc) then
2124 : 0 : write(message,'(a,a,a)') ch10, " == The local Hamiltonian in Ylm basis is complex.&
2125 : 0 : & The complex matrix is used for the diagonalisation. Printing real and imaginary part of rotation matrix: "
2126 : 0 : call wrtout(std_out,message,'COLL')
2127 : :
2128 [ # # # # ]: 0 : eigvectmatlu(iatom)%mat(:,:,isppol) = matlu(iatom)%mat(:,:,isppol)
2129 : :
2130 : 0 : call blockdiago_forzheev(eigvectmatlu(iatom)%mat(:,:,isppol),tndim,eig(:))
2131 : :
2132 : : !ABI_MALLOC(zwork,(lwork))
2133 : : !ABI_MALLOC(rwork,(3*tndim-2))
2134 : : !call zheev('v','u',tndim,eigvectmatlu(iatom)%mat(:,:,isppol),tndim,eig(:),zwork(:),lwork,rwork(:),info)
2135 : : !ABI_FREE(zwork)
2136 : : !ABI_FREE(rwork)
2137 : : else
2138 [ + + + + : 7400 : if (optreal == 1 .and. maxval(abs(aimag(matlu(iatom)%mat(:,:,isppol)))) > tol8 ) then
+ + + - -
+ - - + +
+ - ]
2139 : 2 : write(message,'(a)') " Local hamiltonian in correlated basis is complex"
2140 : 2 : ABI_COMMENT(message)
2141 : : end if
2142 : : !eigvectmatlu(iatom)%mat(:,:,isppol) = matlu(iatom)%mat(:,:,isppol)
2143 [ - + + - : 660 : ABI_MALLOC(zwork,(lwork))
+ - + - -
+ - + ]
2144 [ + - - + : 660 : ABI_MALLOC(rwork,(3*tndim-2))
+ - + - +
- - + -
+ ]
2145 : 220 : call zheev('v','u',tndim,eigvectmatlu(iatom)%mat(:,:,isppol),tndim,eig(:),zwork(:),lwork,rwork(:),info)
2146 [ - + ]: 220 : ABI_FREE(zwork)
2147 [ - + ]: 220 : ABI_FREE(rwork)
2148 : : endif !blockdiag
2149 : : end if ! present(optreal)
2150 [ + + ]: 362 : if (prtopt >= 3) then
2151 [ + - ]: 56 : write(message,'(3a,i1)') " EIGENVECTORS for atom ",trim(adjustl(tag))," and isppol ",isppol
2152 : 56 : call wrtout(std_out,message,'COLL')
2153 [ + + ]: 302 : do im1=1,tndim
2154 : : !write(message,'(12(1x,18(1x,"(",f9.3,",",f9.3,")")))') (eigvectmatlu(iatom)%mat(im1,im2,isppol),im2=1,tndim)
2155 [ + - + + ]: 1684 : write(message,'(12(1x,18(1x,f6.3,1x,f6.3)))') (eigvectmatlu(iatom)%mat(im1,im2,isppol),im2=1,tndim)
2156 : 302 : call wrtout(std_out,message,'COLL')
2157 : : end do ! im1
2158 : : ! do im1=1,tndim
2159 : : ! xcheck=czero
2160 : : ! do im3=1,tndim
2161 : : ! do im2=1,tndim
2162 : : ! xcheck=xcheck+gathermatlu(iatom)%value(im1,im2)*conjg(gathermatlu(iatom)%value(im2,im3))
2163 : : ! end do
2164 : : ! end do
2165 : : ! write(6,*) "check",im3,im1,xcheck
2166 : : ! end do
2167 : : end if ! prtopt>=3
2168 : : ! write(std_out,*) "eig",eig
2169 : : ! ===========================
2170 : : ! Put eigenvalue in matlu_diag
2171 : : ! ===========================
2172 [ + + ]: 2092 : do im1=1,tndim
2173 : 2092 : matlu_diag(iatom)%mat(im1,im1,isppol) = cmplx(eig(im1),zero,kind=dp)
2174 : : end do ! im1
2175 : : !if(prtopt>=2) then
2176 : : ! write(message,'(a,12(1x,18(1x,"(",f9.3,",",f9.3,")")))')&
2177 : : !& ch10,(eig(im1),im1=1,tndim)
2178 : : ! call wrtout(std_out,message,'COLL')
2179 : : !call wrtout(std_out,message,'COLL')
2180 : : !write(std_out,*) "EIG", eig
2181 : : !endif
2182 : : ! ABI_FREE(valuer2)
2183 : : ! ABI_FREE(valuer3)
2184 : : ! ABI_FREE(valuer4)
2185 : : ! endif
2186 : : ! enddo
2187 : : ! ===========================
2188 : : ! Keep eigenvectors gathermatlu
2189 : : ! ===========================
2190 : : !if (present(eigvectmatlu)) then
2191 : : ! tndim=nspinor*(2*matlu(iatom)%lpawu+1)
2192 : : ! eigvectmatlu(iatom,isppol)%value(:,:)=gathermatlu(iatom)%value(:,:)
2193 : : ! write(std_out,*) "eigvect in diag_matlu"
2194 : : ! do im1=1,tndim
2195 : : ! write(message,'(12(1x,18(1x,"(",f9.3,",",f9.3,")")))')&
2196 : : !& (gathermatlu(iatom)%value(im1,im2),im2=1,tndim)
2197 : : ! call wrtout(std_out,message,'COLL')
2198 : : ! end do
2199 : : !endif
2200 : :
2201 [ - + ]: 599 : if (nsppolimp == 1 .and. nsppol == 2) then
2202 : : ! ==================================================================
2203 : : ! If necessary rotate levels for this other spin, assuming the same
2204 : : ! rotation matrix: it has to be checked afterwards that the matrix is
2205 : : ! diagonal
2206 : : ! ===================================================================
2207 : :
2208 : : ! input matrix: gathermatlu
2209 : : ! rotation matrix: eigvectmatlu
2210 : : ! intermediate matrix: temp_mat
2211 : : ! result matrix: temp_mat2
2212 : : !do im1=1,tndim
2213 : : ! do im2=1,tndim
2214 : : ! gathermatlu(iatom)%value(im1,im2)=matlu(iatom)%mat(im1,im2,2,1,1)
2215 : : ! enddo
2216 : : !enddo
2217 : :
2218 [ # # ]: 0 : if (prtopt >= 3) then
2219 : 0 : write(message,'(a,i4,a,i4)') " MATLU for atom",iatom," inside if nsppolimp==1"
2220 : 0 : call wrtout(std_out,message,'COLL')
2221 [ # # ]: 0 : do im1=1,tndim
2222 [ # # # # ]: 0 : write(message,'(12(1x,18(1x,"(",f9.3,",",f9.3,")")))') (matlu(iatom)%mat(im1,im2,2),im2=1,tndim)
2223 : 0 : call wrtout(std_out,message,'COLL')
2224 : : end do ! im1
2225 : : end if ! prtopt>=3
2226 : :
2227 [ # # # # : 0 : ABI_MALLOC(temp_mat,(tndim,tndim))
# # # # #
# # # # #
# # ]
2228 : :
2229 : : call abi_xgemm('n','n',tndim,tndim,tndim,cone,matlu(iatom)%mat(:,:,2),tndim,&
2230 : 0 : & eigvectmatlu(iatom)%mat(:,:,1),tndim,czero,temp_mat(:,:),tndim)
2231 : :
2232 : : call abi_xgemm('c','n',tndim,tndim,tndim,cone,eigvectmatlu(iatom)%mat(:,:,1),tndim,&
2233 : 0 : & temp_mat(:,:),tndim,czero,matlu_diag(iatom)%mat(:,:,2),tndim)
2234 : :
2235 [ # # ]: 0 : ABI_FREE(temp_mat)
2236 : :
2237 [ # # # # ]: 0 : eigvectmatlu(iatom)%mat(:,:,2) = eigvectmatlu(iatom)%mat(:,:,1)
2238 : : print_temp_mat2 = .false.
2239 [ # # ]: 0 : do im2=1,tndim
2240 [ # # ]: 0 : do im1=1,tndim
2241 [ # # # # ]: 0 : if (im1 /= im2 .and. abs(matlu_diag(iatom)%mat(im1,im2,2)) > tol5) then
2242 : 0 : write(message,'(3a,i4,2f16.4)') ch10,'diag_matlu= Matrix for spin number 2 obtained with', &
2243 : 0 : & ' eigenvectors from diagonalization for spin nb 1 is non diagonal for atom:',iatom,&
2244 : 0 : & abs(matlu_diag(iatom)%mat(im1,im2,2)),tol5
2245 : 0 : call wrtout(std_out,message,'COLL')
2246 [ # # # # ]: 0 : if (abs(matlu_diag(iatom)%mat(im1,im2,2)) > tol1 .or. checkstop_in) print_temp_mat2 = .true.
2247 : : end if
2248 : : end do ! im1
2249 : : end do ! im2
2250 : :
2251 [ # # # # ]: 0 : if (print_temp_mat2 .and. prtopt >= 3) then
2252 : 0 : write(message,'(a)') " temp_mat2"
2253 : 0 : call wrtout(std_out,message,'COLL')
2254 [ # # ]: 0 : do im1=1,tndim
2255 [ # # # # ]: 0 : write(message,'(12(1x,18(1x,"(",f9.3,",",f9.3,")")))') (matlu_diag(iatom)%mat(im1,im2,2),im2=1,tndim)
2256 : 0 : call wrtout(std_out,message,'COLL')
2257 : : end do ! im1
2258 [ # # ]: 0 : if (iatom == 2) ABI_ERROR("iatom==2")
2259 : : end if ! print_temp_mat2
2260 : : end if ! nsppol_imp=1 and nsppol=2
2261 : : end do ! isppol
2262 : :
2263 [ - + ]: 875 : ABI_FREE(eig)
2264 : :
2265 : : !! for check only
2266 : : !debug if(matlu(iatom)%lpawu.ne.-1) then
2267 : : !debug allocate(temp_mat(tndim,tndim))
2268 : : !debug allocate(temp_mat3(tndim,tndim))
2269 : : !debug do im1=1,tndim
2270 : : !debug do im2=1,tndim
2271 : : !debug! rot_mat(iatom,isppol)%value(im1,im2)=rot_mat_orig(iatom,isppol)%value(im1,im2)
2272 : : !debug temp_mat3(im1,im2)=conjg(gathermatlu(iatom)%value(im2,im1))
2273 : : !debug enddo
2274 : : !debug enddo
2275 : : !debug temp_mat(:,:)=czero
2276 : : !debug! input matrix: temp_mat2
2277 : : !debug! rotation matrix: gathermatlu
2278 : : !debug! intermediate matrix: temp_mat
2279 : : !debug! result matrix: temp_mat2
2280 : : !debug call zgemm('n','c',tndim,tndim,tndim,cone,temp_mat2 ,tndim,&
2281 : : !debug& temp_mat3,tndim,czero,temp_mat ,tndim)
2282 : : !debug call zgemm('n','n',tndim,tndim,tndim,cone,temp_mat3,tndim,&
2283 : : !debug& temp_mat ,tndim,czero,temp_mat2,tndim)
2284 : : !debug! call zgemm('n','c',tndim,tndim,tndim,cone,temp_mat2 ,tndim,&
2285 : : !debug!& gathermatlu(iatom)%value,tndim,czero,temp_mat ,tndim)
2286 : : !debug! call zgemm('n','n',tndim,tndim,tndim,cone,gathermatlu(iatom)%value,tndim,&
2287 : : !debug!& temp_mat ,tndim,czero,temp_mat2,tndim)
2288 : : !debug write(std_out,*) "result"
2289 : : !debug do im1=1,tndim
2290 : : !debug write(message,'(12(1x,18(1x,"(",f9.3,",",f9.3,")")))')&
2291 : : !debug& (temp_mat2(im1,im2),im2=1,tndim)
2292 : : !debug call wrtout(std_out,message,'COLL')
2293 : : !debug end do
2294 : : !debug deallocate(temp_mat)
2295 : : !debug deallocate(temp_mat3)
2296 : : !debug endif ! lpawu
2297 : :
2298 : : end do ! iatom
2299 : : ! End loop over atoms
2300 : : ! ===========================
2301 : :
2302 : 0 : end subroutine diag_matlu
2303 : : !!***
2304 : :
2305 : : !!****f* m_matlu/rotate_matlu
2306 : : !! NAME
2307 : : !! rotate_matlu
2308 : : !!
2309 : : !! FUNCTION
2310 : : !! Rotate matlu matrix
2311 : : !!
2312 : : !! COPYRIGHT
2313 : : !! Copyright (C) 2005-2026 ABINIT group (BAmadon)
2314 : : !! This file is distributed under the terms of the
2315 : : !! GNU General Public License, see ~abinit/COPYING
2316 : : !! or http://www.gnu.org/copyleft/gpl.txt .
2317 : : !!
2318 : : !! INPUTS
2319 : : !! matlu_inp(natom) :: input quantity to rotate
2320 : : !! rot_mat(natom) :: Rotation matrix (usually from diag_matlu)
2321 : : !! natom=number of atoms in cell.
2322 : : !! inverse= 1: rot_mat^H * matlu * rot_mat (from original basis to diagonal basis)
2323 : : !! /=1: rot_mat * matlu * rot_mat^H (from diagonal basis to original basis)
2324 : : !!
2325 : : !! OUTPUT
2326 : : !!
2327 : : !! SIDE EFFECTS
2328 : : !!
2329 : : !! NOTES
2330 : : !!
2331 : : !! SOURCE
2332 : :
2333 : 21879 : subroutine rotate_matlu(matlu_inp,rot_mat,natom,inverse)
2334 : :
2335 : : !Arguments ------------------------------------
2336 : : integer, intent(in) :: inverse,natom
2337 : : type(matlu_type), intent(inout) :: matlu_inp(natom)
2338 : : type(matlu_type), intent(in) :: rot_mat(natom)
2339 : : !Local variables-------------------------------
2340 : : integer :: iatom,isppol,lpawu,nspinor,nsppol,tndim
2341 : 21879 : complex(dp), allocatable :: temp_mat(:,:)
2342 : : character(len=1) :: c1,c2
2343 : : !************************************************************************
2344 : :
2345 : 21879 : nspinor = matlu_inp(1)%nspinor
2346 : 21879 : nsppol = matlu_inp(1)%nsppol
2347 : :
2348 [ + + ]: 21879 : if (inverse == 1) then
2349 : 10581 : c1 = "n" ; c2 = "c"
2350 : : else
2351 : 11298 : c1 = "c" ; c2 = "n"
2352 : : end if ! inverse
2353 : :
2354 [ + + ]: 69726 : do iatom=1,natom
2355 : 47847 : lpawu = matlu_inp(iatom)%lpawu
2356 [ + + ]: 47847 : if (lpawu == -1) cycle
2357 : 23031 : tndim = nspinor * (2*lpawu+1)
2358 [ - + + - : 92124 : ABI_MALLOC(temp_mat,(tndim,tndim))
- + + - +
- + - - +
+ - ]
2359 [ + + ]: 54190 : do isppol=1,nsppol
2360 : : call abi_xgemm('n',c1,tndim,tndim,tndim,cone,matlu_inp(iatom)%mat(:,:,isppol),tndim,&
2361 : 31159 : & rot_mat(iatom)%mat(:,:,isppol),tndim,czero,temp_mat(:,:),tndim)
2362 : : call abi_xgemm(c2,'n',tndim,tndim,tndim,cone,rot_mat(iatom)%mat(:,:,isppol),tndim,&
2363 : 54190 : & temp_mat(:,:),tndim,czero,matlu_inp(iatom)%mat(:,:,isppol),tndim)
2364 : : end do ! isppol
2365 [ - + ]: 69726 : ABI_FREE(temp_mat)
2366 : : end do ! iatom
2367 : :
2368 : : !do isppol=1,nsppol
2369 : :
2370 : : ! ===========================
2371 : : ! Define gathermatlu and rot_mat_orig and allocate
2372 : : ! ===========================
2373 : : !ABI_MALLOC(rot_mat_orig,(natom))
2374 : : !ABI_MALLOC(gathermatlu,(natom))
2375 : : !do iatom=1,natom
2376 : : ! if(matlu(iatom)%lpawu.ne.-1) then
2377 : : ! tndim=nspinor*(2*matlu(iatom)%lpawu+1)
2378 : : ! ABI_MALLOC(gathermatlu(iatom)%value,(tndim,tndim))
2379 : : ! gathermatlu(iatom)%value=czero
2380 : : ! ABI_MALLOC(rot_mat_orig(iatom,isppol)%value,(tndim,tndim))
2381 : : ! rot_mat_orig(iatom,isppol)%value(:,:)=rot_mat(iatom,isppol)%value(:,:)
2382 : : ! ABI_MALLOC(rot_mat_orig(iatom)%value,(tndim,tndim))
2383 : : ! rot_mat_orig(iatom)%value(:,:)=rot_mat(iatom,isppol)%value(:,:)
2384 : : ! endif
2385 : : !enddo
2386 : : !if(nsppol==1.and.nspinor==2) then
2387 : : ! call gather_matlu(matlu,gathermatlu,natom,option=1,prtopt=1)
2388 : : !else if((nsppol==2.or.nsppol==1).and.nspinor==1) then
2389 : : ! do iatom=1,natom
2390 : : ! if(matlu(iatom)%lpawu.ne.-1) then
2391 : : ! tndim=nspinor*(2*matlu(iatom)%lpawu+1)
2392 : : ! do im1=1,tndim
2393 : : ! do im2=1,tndim
2394 : : ! gathermatlu(iatom)%value(im1,im2)=matlu(iatom)%mat(im1,im2,isppol,1,1)
2395 : : ! enddo
2396 : : ! enddo
2397 : : ! endif
2398 : : ! enddo
2399 : : !endif
2400 : : ! write(std_out,*) "gathermatlu in rotate matlu"
2401 : : ! do im1=1,tndim
2402 : : ! write(message,'(12(1x,18(1x,"(",e17.10,",",e17.10,")")))')&
2403 : : ! (gathermatlu(1)%value(im1,im2),im2=1,tndim)
2404 : : ! call wrtout(std_out,message,'COLL')
2405 : : ! end do
2406 : :
2407 : : ! ===========================
2408 : : ! If necessary, invert rot_mat
2409 : : ! ===========================
2410 : : !if(inverse==1) then
2411 : : ! do iatom=1,natom
2412 : : ! if(matlu(iatom)%lpawu.ne.-1) then
2413 : : ! tndim=nspinor*(2*matlu(iatom)%lpawu+1)
2414 : : ! do im1=1,tndim
2415 : : ! do im2=1,tndim
2416 : : ! rot_mat(iatom,isppol)%value(im1,im2)=conjg(rot_mat_orig(iatom,isppol)%value(im2,im1))
2417 : : ! rot_mat(iatom,isppol)%value(im1,im2)=conjg(rot_mat_orig(iatom)%value(im2,im1))
2418 : : ! enddo
2419 : : ! enddo
2420 : : ! endif ! lpawu
2421 : : ! enddo ! iatom
2422 : : !endif
2423 : : ! write(std_out,*) "rot_mat_orig "
2424 : : ! do im1=1,tndim
2425 : : ! write(message,'(12(1x,18(1x,"(",e18.10,",",e18.10,")")))')&
2426 : : ! & (rot_mat_orig(1)%value(im1,im2),im2=1,tndim)
2427 : : ! call wrtout(std_out,message,'COLL')
2428 : : ! end do
2429 : : ! write(std_out,*) "rot_mat "
2430 : : ! do im1=1,tndim
2431 : : ! write(message,'(12(1x,18(1x,"(",e18.10,",",e18.10,")")))')&
2432 : : ! & (rot_mat(1,1)%value(im1,im2),im2=1,tndim)
2433 : : ! call wrtout(std_out,message,'COLL')
2434 : : ! end do
2435 : :
2436 : : ! ===========================
2437 : : ! Rotate
2438 : : ! ===========================
2439 : : !ABI_MALLOC(temp_mat,(tndim,tndim))
2440 : : !do iatom=1,natom
2441 : : ! if(matlu(iatom)%lpawu.ne.-1) then
2442 : : ! tndim=nspinor*(2*matlu(iatom)%lpawu+1)
2443 : : ! temp_mat(:,:)=czero
2444 : : ! input matrix: gathermatlu
2445 : : ! rotation matrix: rot_mat
2446 : : ! intermediate matrix: temp_mat
2447 : : ! result matrix: gathermatlu
2448 : : ! temp_mat = gathermatlu * conjg(rot_mat)
2449 : : ! call zgemm('n','c',tndim,tndim,tndim,cone,gathermatlu(iatom)%value
2450 : : ! ,tndim,&
2451 : : !& rot_mat(iatom,isppol)%value,tndim,czero,temp_mat
2452 : : !,tndim)
2453 : : ! gathermatlu = rot_mat * temp_mat = rot_mat * gathermatlu *
2454 : : ! conjg(rot_mat)
2455 : : ! call
2456 : : ! zgemm('n','n',tndim,tndim,tndim,cone,rot_mat(iatom,isppol)%value,tndim,&
2457 : : !& temp_mat
2458 : : !,tndim,czero,gathermatlu(iatom)%value,tndim)
2459 : : ! endif ! lpawu
2460 : : ! enddo ! iatom
2461 : : !do iatom=1,natom
2462 : : ! if(matlu(iatom)%lpawu.ne.-1) then
2463 : : ! write(std_out,*) "temp_mat in rotate_matlu 2"
2464 : : ! do im1=1,tndim
2465 : : ! write(message,'(12(1x,18(1x,"(",f17.10,",",f17.10,")")))')&
2466 : : !& (temp_mat(im1,im2),im2=1,tndim)
2467 : : ! call wrtout(std_out,message,'COLL')
2468 : : ! end do
2469 : : ! endif
2470 : : !enddo
2471 : : !do iatom=1,natom
2472 : : ! if(matlu(iatom)%lpawu.ne.-1) then
2473 : : ! write(std_out,*) "gathermatlu in rotate_matlu 2"
2474 : : ! do im1=1,tndim
2475 : : ! write(message,'(12(1x,18(1x,"(",f17.10,",",f17.10,")")))')&
2476 : : !& (gathermatlu(iatom)%value(im1,im2),im2=1,tndim)
2477 : : ! call wrtout(std_out,message,'COLL')
2478 : : ! end do
2479 : : ! endif
2480 : : !enddo
2481 : : ! ABI_FREE(temp_mat)
2482 : : !ABI_ERROR("Aborting now")
2483 : :
2484 : : ! Choose inverse rotation: reconstruct correct rot_mat from rot_mat_orig
2485 : : ! ========================================================================
2486 : : !if(inverse==1) then
2487 : : ! do iatom=1,natom
2488 : : ! if(matlu(iatom)%lpawu.ne.-1) then
2489 : : ! tndim=nspinor*(2*matlu(iatom)%lpawu+1)
2490 : : ! do im1=1,tndim
2491 : : ! do im2=1,tndim
2492 : : ! !
2493 : : ! rot_mat(iatom,isppol)%value(im1,im2)=rot_mat_orig(iatom,isppol)%value(im1,im2)
2494 : : ! rot_mat(iatom,isppol)%value(im1,im2)=rot_mat_orig(iatom)%value(im1,im2)
2495 : : ! enddo
2496 : : ! enddo
2497 : : ! endif ! lpawu
2498 : : ! enddo ! iatom
2499 : : !endif
2500 : :
2501 : : ! ===========================
2502 : : ! Put data into matlu(iatom)
2503 : : ! ===========================
2504 : : !if(nsppol==1.and.nspinor==2) then
2505 : : ! call gather_matlu(matlu,gathermatlu,natom,option=-1,prtopt=1)
2506 : : !else if((nsppol==2.or.nsppol==1).and.nspinor==1) then
2507 : : ! do iatom=1,natom
2508 : : ! if(matlu(iatom)%lpawu.ne.-1) then
2509 : : ! tndim=nspinor*(2*matlu(iatom)%lpawu+1)
2510 : : ! do im1=1,tndim
2511 : : ! do im2=1,tndim
2512 : : ! matlu(iatom)%mat(im1,im2,isppol,1,1)=
2513 : : ! gathermatlu(iatom)%value(im1,im2)
2514 : : ! enddo
2515 : : ! enddo
2516 : : ! endif
2517 : : ! enddo
2518 : : !endif ! test nsppol/nspinor
2519 : : ! ===========================
2520 : : ! Deallocations
2521 : : ! ===========================
2522 : : !do iatom=1,natom
2523 : : ! if(matlu(iatom)%lpawu.ne.-1) then
2524 : : ! ABI_FREE(gathermatlu(iatom)%value)
2525 : : ! ABI_FREE(rot_mat_orig(iatom,isppol)%value)
2526 : : ! ABI_FREE(rot_mat_orig(iatom)%value)
2527 : : ! endif
2528 : : !enddo
2529 : : !ABI_FREE(gathermatlu)
2530 : : !ABI_FREE(rot_mat_orig)
2531 : : !enddo ! isppol
2532 : :
2533 : 21879 : end subroutine rotate_matlu
2534 : : !!***
2535 : :
2536 : : !!****f* m_matlu/shift_matlu
2537 : : !! NAME
2538 : : !! shift_matlu
2539 : : !!
2540 : : !! FUNCTION
2541 : : !! Add/subtract a scalar to the diagonal part
2542 : : !!
2543 : : !! COPYRIGHT
2544 : : !! Copyright (C) 2005-2026 ABINIT group (BAmadon)
2545 : : !! This file is distributed under the terms of the
2546 : : !! GNU General Public License, see ~abinit/COPYING
2547 : : !! or http://www.gnu.org/copyleft/gpl.txt .
2548 : : !!
2549 : : !! INPUTS
2550 : : !! matlu(natom) :: input quantity to shift
2551 : : !! natom=number of atoms in cell.
2552 : : !! shift= shift of the diagonal part.
2553 : : !! signe= 1 (default) : the shift is substracted
2554 : : !! = -1 : the shift is added
2555 : : !!
2556 : : !! OUTPUT
2557 : : !! matlu(natom) :: shifted matrix
2558 : : !!
2559 : : !! SIDE EFFECTS
2560 : : !!
2561 : : !! NOTES
2562 : : !!
2563 : : !! SOURCE
2564 : :
2565 : 18679 : subroutine shift_matlu(matlu,natom,shift,signe)
2566 : :
2567 : : !Arguments ------------------------------------
2568 : : integer, intent(in) :: natom
2569 : : type(matlu_type), intent(inout) :: matlu(natom)
2570 : : complex(dp), intent(in) :: shift(natom)
2571 : : integer, optional, intent(in) :: signe
2572 : : !Local variables-------------------------------
2573 : : integer :: iatom,im,lpawu,ndim,nspinor,nsppol,signe_used
2574 : : ! character(len=500) :: message
2575 : : !************************************************************************
2576 : :
2577 : 18679 : nspinor = matlu(1)%nspinor
2578 : 18679 : nsppol = matlu(1)%nsppol
2579 : 18679 : signe_used = 1
2580 : :
2581 [ + + ]: 18679 : if (present(signe)) then
2582 [ - + ]: 682 : if (signe == -1) signe_used = -1
2583 : : end if ! present(signe)
2584 : :
2585 [ + + ]: 41462 : do iatom=1,natom
2586 : 22783 : lpawu = matlu(iatom)%lpawu
2587 [ + + ]: 22783 : if (lpawu == -1) cycle
2588 : 18799 : ndim = nspinor * (2*lpawu+1)
2589 [ + + ]: 132501 : do im=1,ndim
2590 [ + + + + ]: 300836 : matlu(iatom)%mat(im,im,:) = matlu(iatom)%mat(im,im,:) + merge(-shift(iatom),shift(iatom),signe_used==1)
2591 : : end do ! im
2592 : : end do ! iatom
2593 : :
2594 : 18679 : end subroutine shift_matlu
2595 : : !!***
2596 : :
2597 : : !!****f* m_matlu/checkreal_matlu
2598 : : !! NAME
2599 : : !! checkreal_matlu
2600 : : !!
2601 : : !! FUNCTION
2602 : : !! Check that matlu is real and diagonal with given precision
2603 : : !!
2604 : : !! COPYRIGHT
2605 : : !! Copyright (C) 2005-2026 ABINIT group (BAmadon)
2606 : : !! This file is distributed under the terms of the
2607 : : !! GNU General Public License, see ~abinit/COPYING
2608 : : !! or http://www.gnu.org/copyleft/gpl.txt .
2609 : : !!
2610 : : !! INPUTS
2611 : : !! dmft_solv :: impurity solver
2612 : : !! matlu(natom) :: input quantity to check
2613 : : !! natom=number of atoms in cell.
2614 : : !! tol : threshold. Print a warning if max(abs(imag(off diagonal elements))) > tol or
2615 : : !! max(abs(off diagonal elements)) > tol, and throws an error if max(abs(imag(diagonal elements))) > tol
2616 : : !!
2617 : : !! SIDE EFFECTS
2618 : : !!
2619 : : !! NOTES
2620 : : !!
2621 : : !! SOURCE
2622 : :
2623 : 0 : subroutine checkreal_matlu(matlu,natom,tol)
2624 : :
2625 : : !Arguments ------------------------------------
2626 : : real(dp), intent(in) :: tol
2627 : : integer, intent(in) :: natom
2628 : : type(matlu_type), intent(in) :: matlu(natom)
2629 : : !Local variables-------------------------------
2630 : : integer :: iatom,im,im1,isppol,lpawu,ndim,nspinor,nsppol
2631 : : character(len=500) :: message
2632 : : real(dp) :: elem,maximag,maximagdiag,maxoffdiag
2633 : : !************************************************************************
2634 : :
2635 : 0 : maximag = zero
2636 : 0 : maximagdiag = zero
2637 : 0 : maxoffdiag = zero
2638 : 0 : nspinor = matlu(1)%nspinor
2639 : 0 : nsppol = matlu(1)%nsppol
2640 : :
2641 [ # # ]: 0 : do iatom=1,natom
2642 : 0 : lpawu = matlu(iatom)%lpawu
2643 [ # # ]: 0 : if (lpawu == -1) cycle
2644 : 0 : ndim = nspinor * (2*lpawu+1)
2645 [ # # ]: 0 : do isppol=1,nsppol
2646 [ # # ]: 0 : do im1=1,ndim
2647 [ # # ]: 0 : do im=1,ndim
2648 : 0 : elem = abs(aimag(matlu(iatom)%mat(im,im1,isppol)))
2649 [ # # ]: 0 : if (elem > maximag) maximag = elem
2650 [ # # ]: 0 : if (im == im1) then
2651 [ # # ]: 0 : if (elem > maximagdiag) maximagdiag = elem
2652 : : else
2653 : 0 : elem = abs(matlu(iatom)%mat(im,im1,isppol))
2654 [ # # ]: 0 : if (elem > maxoffdiag) maxoffdiag = elem
2655 : : end if ! im/=im1
2656 : : end do ! im
2657 : : end do ! im1
2658 : : end do ! isppol
2659 : : end do ! iatom
2660 : :
2661 [ # # ]: 0 : if (maximagdiag > tol) then
2662 : 0 : write(message,'(3x,2a,e12.4,a,e12.4,2a)') ch10,&
2663 : 0 : & ' Diagonal part of the occupation matrix is complex: the imaginary part ',&
2664 : 0 : & maximagdiag,' is larger than',tol,ch10, &
2665 : 0 : & "The calculation cannot handle it : check that your calculation is meaningful"
2666 : 0 : ABI_ERROR(message)
2667 : : end if ! maximagdiag > tol
2668 [ # # ]: 0 : if (maximag > tol) then
2669 : 0 : write(message,'(3x,2a,e12.4,a,e12.4,2a)') ch10,&
2670 : 0 : & ' The off diagonal occupation matrix is complex: the imaginary part ',maximag,' is larger than',tol,ch10,&
2671 : 0 : & "Check that your calculation is meaningful"
2672 : 0 : ABI_WARNING(message)
2673 : : end if ! maximag > tol
2674 [ # # ]: 0 : if (maxoffdiag > tol) then
2675 : 0 : write(message,'(3x,2a,e12.4,a,e12.4,6a)') ch10,&
2676 : 0 : & ' Occupation matrix is non diagonal : the maximum off-diag part ',maxoffdiag,' is larger than',tol,ch10,&
2677 : 0 : & "The corresponding non diagonal elements will be neglected in the Weiss/Hybridization functions",ch10,&
2678 : 0 : & "(Except if dmft_solv=8,9 where these elements are taken into account)",ch10,"This is an approximation."
2679 : 0 : ABI_WARNING(message)
2680 : : else
2681 : 0 : write(message,'(3x,2a,e12.4,a,e12.4,2a)') ch10,' Occupation matrix is diagonal : the off-diag part ',&
2682 : 0 : & maxoffdiag,' is lower than',tol
2683 : 0 : ABI_COMMENT(message)
2684 : : end if ! maxoffdiag > tol
2685 : :
2686 : 0 : end subroutine checkreal_matlu
2687 : : !!***
2688 : :
2689 : : !!****f* m_matlu/checkdiag_matlu
2690 : : !! NAME
2691 : : !! checkdiag_matlu
2692 : : !!
2693 : : !! FUNCTION
2694 : : !! Check that matlu is diagonal in the orbital index with given precision
2695 : : !!
2696 : : !! COPYRIGHT
2697 : : !! Copyright (C) 2005-2026 ABINIT group (BAmadon)
2698 : : !! This file is distributed under the terms of the
2699 : : !! GNU General Public License, see ~abinit/COPYING
2700 : : !! or http://www.gnu.org/copyleft/gpl.txt .
2701 : : !!
2702 : : !! INPUTS
2703 : : !! matlu(natom) :: input quantity to check
2704 : : !! natom=number of atoms in cell.
2705 : : !! tol : precision
2706 : : !!
2707 : : !! OUTPUT
2708 : : !! nondiag= true if max(abs(off diagonal elements)) > tol
2709 : : !!
2710 : : !! SIDE EFFECTS
2711 : : !!
2712 : : !! NOTES
2713 : : !!
2714 : : !! SOURCE
2715 : :
2716 : 140 : subroutine checkdiag_matlu(matlu,natom,tol,nondiag)
2717 : :
2718 : : !Arguments ------------------------------------
2719 : : real(dp), intent(in) :: tol
2720 : : integer, intent(in) :: natom
2721 : : logical, intent(out) :: nondiag
2722 : : type(matlu_type), intent(in) :: matlu(natom)
2723 : : !Local variables-------------------------------
2724 : : integer :: iatom,im,im1,isppol,lpawu,ndim,nsppol,nspinor
2725 : : !************************************************************************
2726 : :
2727 : 140 : nondiag = .false.
2728 : 140 : nspinor = matlu(1)%nspinor
2729 : 140 : nsppol = matlu(1)%nsppol
2730 : :
2731 [ + + ]: 572 : do iatom=1,natom
2732 : 432 : lpawu = matlu(iatom)%lpawu
2733 [ + + ]: 432 : if (lpawu == -1) cycle
2734 : 164 : ndim = nspinor * (2*lpawu+1)
2735 [ + + ]: 562 : do isppol=1,nsppol
2736 [ + + ]: 1926 : do im1=1,ndim
2737 [ + + ]: 7966 : do im=1,ndim
2738 : : ! if(im/=im1) write(std_out,*) "im,im1",im,im1,matlu(iatom)%mat(im,im1,isppol,ispinor,ispinor)
2739 : : ! if(present(nondiag).eqv..false.) then
2740 : : ! if(im/=im1.and.(abs(matlu(iatom)%mat(im,im1,isppol,ispinor,ispinor))>tol)) then
2741 : : ! write(message,'(5i5)') im,im1,isppol,ispinor,ispinor
2742 : : ! call wrtout(std_out,message,'COLL')
2743 : : ! write(message,'(a,3e16.5)')" checkdiag_matlu: Warning ",matlu(iatom)%mat(im,im1,isppol,ispinor,ispinor),tol
2744 : : ! call wrtout(std_out,message,'COLL')
2745 : : ! if(.not.present(opt)) ABI_ERROR("not present(opt)")
2746 : : ! if(matlu(1)%nspinor==1) ABI_ERROR("matlu%nspinor==1")
2747 : : ! endif
2748 : : ! endif
2749 : : ! if(present(nondiag)) then
2750 [ + + + + ]: 7708 : if ((im /= im1) .and. abs(dble(matlu(iatom)%mat(im,im1,isppol))) > tol) nondiag = .true.
2751 : : ! write(6,*) "NONDIAG", matlu(iatom)%mat(im,im1,isppol,ispinor,ispinor1)
2752 : : !if(ispinor/=ispinor1.and.(abs(matlu(iatom)%mat(im,im1,isppol,ispinor,ispinor1))>tol)) then
2753 : : ! write(message,'(a,3e16.5)')" checkdiag_matlu :i Warning ",matlu(iatom)%mat(im,im1,isppol,ispinor,ispinor1),tol
2754 : : ! call wrtout(std_out,message,'COLL')
2755 : : ! write(message,'(5i5)') im,im1,isppol,ispinor,ispinor
2756 : : ! call wrtout(std_out,message,'COLL')
2757 : : ! if(matlu(1)%nspinor==1) ABI_ERROR("matlu%nspinor==1")
2758 : : !endif
2759 : : end do ! im
2760 : : end do ! im1
2761 : : end do ! isppol
2762 : : end do ! iatom
2763 : :
2764 : 140 : end subroutine checkdiag_matlu
2765 : : !!***
2766 : :
2767 : : !!****f* m_matlu/prod_matlu
2768 : : !! NAME
2769 : : !! prod_matlu
2770 : : !!
2771 : : !! FUNCTION
2772 : : !! Matrix product of two matlus
2773 : : !!
2774 : : !! COPYRIGHT
2775 : : !! Copyright (C) 2005-2026 ABINIT group (BAmadon)
2776 : : !! This file is distributed under the terms of the
2777 : : !! GNU General Public License, see ~abinit/COPYING
2778 : : !! or http://www.gnu.org/copyleft/gpl.txt .
2779 : : !!
2780 : : !! INPUTS
2781 : : !! matlu1(natom) :: input quantity
2782 : : !! matlu2(natom) :: input quantity
2783 : : !!
2784 : : !! OUTPUT
2785 : : !! matlu3(natom) :: output quantity
2786 : : !!
2787 : : !! SIDE EFFECTS
2788 : : !!
2789 : : !! NOTES
2790 : : !!
2791 : : !! SOURCE
2792 : :
2793 : 68 : subroutine prod_matlu(matlu1,matlu2,matlu3,natom)
2794 : :
2795 : : !Arguments ------------------------------------
2796 : : integer, intent(in) :: natom
2797 : : type(matlu_type), intent(in) :: matlu1(natom),matlu2(natom)
2798 : : type(matlu_type), intent(inout) :: matlu3(natom)
2799 : : !Local variables-------------------------------
2800 : : integer :: iatom,isppol,lpawu,ndim,nspinor,nsppol
2801 : : !************************************************************************
2802 : :
2803 : 68 : nspinor = matlu1(1)%nspinor
2804 : 68 : nsppol = matlu1(1)%nsppol
2805 : :
2806 [ + + ]: 192 : do iatom=1,natom
2807 : 124 : lpawu = matlu1(iatom)%lpawu
2808 [ + + ]: 124 : if (lpawu == -1) cycle
2809 : 68 : ndim = nspinor * (2*lpawu+1)
2810 [ + + ]: 244 : do isppol=1,nsppol
2811 : : call abi_xgemm("n","n",ndim,ndim,ndim,cone,matlu1(iatom)%mat(:,:,isppol),ndim,&
2812 : 232 : & matlu2(iatom)%mat(:,:,isppol),ndim,czero,matlu3(iatom)%mat(:,:,isppol),ndim)
2813 : : end do ! isppol
2814 : : end do ! iatom
2815 : :
2816 : : !call zero_matlu(matlu3,natom)
2817 : : !do iatom=1,natom
2818 : : ! lpawu=matlu1(iatom)%lpawu
2819 : : ! if(lpawu.ne.-1) then
2820 : : ! do isppol=1,matlu1(1)%nsppol
2821 : : ! do ispinor1=1,matlu1(1)%nspinor
2822 : : ! do ispinor2=1,matlu1(1)%nspinor
2823 : : ! do ispinor3=1,matlu1(1)%nspinor
2824 : : ! do im1=1,2*lpawu+1
2825 : : ! do im2=1,2*lpawu+1
2826 : : ! do im3=1,2*lpawu+1
2827 : : ! matlu3(iatom)%mat(im1,im2,isppol,ispinor1,ispinor2)= &
2828 : : !& matlu3(iatom)%mat(im1,im2,isppol,ispinor1,ispinor2)+ &
2829 : : !& matlu1(iatom)%mat(im1,im3,isppol,ispinor1,ispinor3)*&
2830 : : !& matlu2(iatom)%mat(im3,im2,isppol,ispinor3,ispinor2)
2831 : : ! enddo ! im3
2832 : : ! enddo ! im2
2833 : : ! enddo ! im1
2834 : : ! enddo ! ispinor3
2835 : : ! enddo ! ispinor2
2836 : : ! enddo ! ispinor1
2837 : : ! enddo ! isppol
2838 : : ! endif ! lpawu
2839 : : !enddo ! iatom
2840 : :
2841 : 68 : end subroutine prod_matlu
2842 : : !!***
2843 : :
2844 : : !!****f* m_matlu/conjg_matlu
2845 : : !! NAME
2846 : : !! conjg_matlu
2847 : : !!
2848 : : !! FUNCTION
2849 : : !! conjugate of input matlu
2850 : : !!
2851 : : !! COPYRIGHT
2852 : : !! Copyright (C) 2005-2026 ABINIT group (BAmadon)
2853 : : !! This file is distributed under the terms of the
2854 : : !! GNU General Public License, see ~abinit/COPYING
2855 : : !! or http://www.gnu.org/copyleft/gpl.txt .
2856 : : !!
2857 : : !! INPUTS
2858 : : !! matlu1(natom)%(nsppol,nspinor,nspinor,ndim,ndim) :: input quantity
2859 : : !!
2860 : : !! SIDE EFFECTS
2861 : : !!
2862 : : !! NOTES
2863 : : !!
2864 : : !! SOURCE
2865 : 0 : subroutine conjg_matlu(matlu1,natom)
2866 : : use defs_wvltypes
2867 : :
2868 : : !Arguments ------------------------------------
2869 : : !scalars
2870 : : integer, intent(in) :: natom
2871 : : !arrays
2872 : : type(matlu_type), intent(inout) :: matlu1(natom)
2873 : : !Local variables-------------------------------
2874 : : !scalars
2875 : : integer :: iatom,im1,im2,ispinor2,ispinor1,isppol
2876 : : integer :: lpawu,ndim
2877 : : !arrays
2878 : : !************************************************************************
2879 [ # # ]: 0 : do iatom=1,natom
2880 : 0 : lpawu=matlu1(iatom)%lpawu
2881 [ # # ]: 0 : if(lpawu.ne.-1) then
2882 : 0 : ndim=2*lpawu+1
2883 [ # # ]: 0 : do isppol=1,matlu1(1)%nsppol
2884 [ # # ]: 0 : do ispinor1=1,matlu1(1)%nspinor
2885 [ # # ]: 0 : do ispinor2=1,matlu1(1)%nspinor
2886 [ # # ]: 0 : do im1=1,2*lpawu+1
2887 [ # # ]: 0 : do im2=1,2*lpawu+1
2888 : : matlu1(iatom)%mat(im1+(ispinor1-1)*ndim,im2+(ispinor2-1)*ndim,isppol)= &
2889 : 0 : & conjg(matlu1(iatom)%mat(im1+(ispinor1-1)*ndim,im2+(ispinor2-1)*ndim,isppol))
2890 : : enddo ! im2
2891 : : enddo ! im1
2892 : : enddo ! ispinor2
2893 : : enddo ! ispinor1
2894 : : enddo ! isppol
2895 : : endif ! lpawu
2896 : : enddo ! iatom
2897 : :
2898 : 0 : end subroutine conjg_matlu
2899 : : !!***
2900 : :
2901 : : !!****f* m_matlu/ln_matlu
2902 : : !! NAME
2903 : : !! ln_matlu
2904 : : !!
2905 : : !! FUNCTION
2906 : : !! Compute the logarithm of matlu (only if diagonal for the moment)
2907 : : !!
2908 : : !! COPYRIGHT
2909 : : !! Copyright (C) 2005-2026 ABINIT group (BAmadon)
2910 : : !! This file is distributed under the terms of the
2911 : : !! GNU General Public License, see ~abinit/COPYING
2912 : : !! or http://www.gnu.org/copyleft/gpl.txt .
2913 : : !!
2914 : : !! INPUTS
2915 : : !! matlu1(natom)%(nsppol,nspinor,nspinor,ndim,ndim) :: input quantity
2916 : :
2917 : : !! SIDE EFFECTS
2918 : : !!
2919 : : !! NOTES
2920 : : !!
2921 : : !! SOURCE
2922 : 0 : subroutine ln_matlu(matlu1,natom)
2923 : : use defs_wvltypes
2924 : :
2925 : : !Arguments ------------------------------------
2926 : : !scalars
2927 : : integer, intent(in) :: natom
2928 : : !arrays
2929 : : type(matlu_type), intent(inout) :: matlu1(natom)
2930 : : !Local variables-------------------------------
2931 : : !scalars
2932 : : integer :: iatom,im,ispinor,isppol
2933 : : integer :: lpawu,ndim
2934 : : character(len=500) :: message
2935 : : !arrays
2936 : : !************************************************************************
2937 : : !call checkdiag_matlu(matlu1,natom,tol8)
2938 [ # # ]: 0 : do iatom=1,natom
2939 : 0 : lpawu=matlu1(iatom)%lpawu
2940 [ # # ]: 0 : if(lpawu.ne.-1) then
2941 : 0 : ndim=2*lpawu+1
2942 [ # # ]: 0 : do isppol=1,matlu1(1)%nsppol
2943 [ # # ]: 0 : do ispinor=1,matlu1(1)%nspinor
2944 [ # # ]: 0 : do im=1,2*lpawu+1
2945 [ # # ]: 0 : if( real(matlu1(iatom)%mat(im+(ispinor-1)*ndim,im+(ispinor-1)*ndim,isppol))<zero) then
2946 : 0 : write(message,'(2a,2es13.5,a)') ch10," ln_matlu: PROBLEM " &
2947 : 0 : & , matlu1(iatom)%mat(im+(ispinor-1)*ndim,im+(ispinor-1)*ndim,isppol)
2948 : 0 : ABI_ERROR(message)
2949 : : endif
2950 : : matlu1(iatom)%mat(im+(ispinor-1)*ndim,im+(ispinor-1)*ndim,isppol)= &
2951 : 0 : & log(matlu1(iatom)%mat(im+(ispinor-1)*ndim,im+(ispinor-1)*ndim,isppol))
2952 : : enddo ! im
2953 : : enddo ! ispinor
2954 : : enddo ! isppol
2955 : : endif ! lpawu
2956 : : enddo ! iatom
2957 : :
2958 : 0 : end subroutine ln_matlu
2959 : : !!***
2960 : :
2961 : : !!****f* m_matlu/slm2ylm_matlu
2962 : : !! NAME
2963 : : !! slm2ylm_matlu
2964 : : !!
2965 : : !! FUNCTION
2966 : : !! Transform mat from Slm to Ylm basis or vice versa
2967 : : !!
2968 : : !! COPYRIGHT
2969 : : !! Copyright (C) 2005-2026 ABINIT group (BAmadon)
2970 : : !! This file is distributed under the terms of the
2971 : : !! GNU General Public License, see ~abinit/COPYING
2972 : : !! or http://www.gnu.org/copyleft/gpl.txt .
2973 : : !!
2974 : : !! INPUTS
2975 : : !! matlu1(natom) :: input quantity
2976 : : !! natom :: number of atoms
2977 : : !! paw_dmft <type(paw_dmft_type)>= paw+dmft related data
2978 : : !! option=1 go from Slm to Ylm basis
2979 : : !! option=2 go from Ylm to Slm basis
2980 : : !! SIDE EFFECTS
2981 : : !!
2982 : : !! NOTES
2983 : : !!
2984 : : !! SOURCE
2985 : :
2986 : 0 : subroutine slm2ylm_matlu(matlu,natom,paw_dmft,option,optprt)
2987 : :
2988 : : !Arguments ------------------------------------
2989 : : integer, intent(in) :: natom,option,optprt
2990 : : type(matlu_type), target, intent(inout) :: matlu(natom)
2991 : : type(paw_dmft_type), target, intent(in) :: paw_dmft
2992 : : !Local variables-------------------------------
2993 : : integer :: iatom,im1,im2,ispin,ispinor1,ispinor2,isppol
2994 : : integer :: lpawu,ndim,ndim_max,nspin,nspinor,nsppol
2995 : : complex(dp), pointer :: mat_out(:,:) => null(), slm2ylm(:,:) => null()
2996 : 0 : complex(dp), allocatable :: mat_inp(:,:),mat_tmp(:,:)
2997 : 0 : complex(dp), target, allocatable :: mat_tmp2(:,:)
2998 : : character(len=1) :: c1,c2
2999 : : character(len=500) :: message
3000 : : !************************************************************************
3001 : :
3002 : 0 : ndim_max = 2*paw_dmft%maxlpawu + 1
3003 : 0 : nspinor = paw_dmft%nspinor
3004 : 0 : nsppol = paw_dmft%nsppol
3005 : 0 : nspin = nsppol * (nspinor**2)
3006 : :
3007 [ # # ]: 0 : if (option == 1) then
3008 : 0 : c1 = "n" ; c2 = "c"
3009 [ # # ]: 0 : else if (option == 2) then
3010 : 0 : c1 = "c" ; c2 = "n"
3011 : : end if
3012 : :
3013 [ # # ]: 0 : do iatom=1,natom
3014 : :
3015 : 0 : lpawu = paw_dmft%lpawu(iatom)
3016 [ # # ]: 0 : if (lpawu == -1) cycle
3017 : 0 : ndim = 2*lpawu + 1
3018 : 0 : slm2ylm => paw_dmft%slm2ylm(:,:,lpawu+1)
3019 : :
3020 [ # # ]: 0 : if (optprt > 2) then
3021 : 0 : write(message,'(2a)') ch10,"SLM2YLM matrix"
3022 : 0 : call wrtout(std_out,message,'COLL')
3023 [ # # ]: 0 : do im1=1,ndim
3024 : 0 : write(message,'(12(1x,9(1x,"(",f9.5,",",f9.5,")")))') (slm2ylm(im1,im2),im2=1,ndim)
3025 : 0 : call wrtout(std_out,message,'COLL')
3026 : : end do ! im1
3027 : : end if ! optprt>2
3028 : :
3029 [ # # # # : 0 : ABI_MALLOC(mat_inp,(ndim,ndim))
# # # # #
# # # # #
# # ]
3030 [ # # # # : 0 : ABI_MALLOC(mat_tmp,(ndim,nspin*ndim))
# # # # #
# # # # #
# # ]
3031 [ # # # # : 0 : ABI_MALLOC(mat_tmp2,(ndim,nspin*ndim))
# # # # #
# # # ]
3032 : :
3033 : 0 : ispin = 0
3034 : :
3035 [ # # ]: 0 : do isppol=1,nsppol
3036 [ # # ]: 0 : do ispinor2=1,nspinor
3037 [ # # ]: 0 : do ispinor1=1,nspinor
3038 : :
3039 : 0 : ispin = ispin + 1
3040 : :
3041 : : ! Make copy here instead of creating a temporary when calling zgemm in order to please -fcheck
3042 [ # # # # ]: 0 : mat_inp(:,:) = matlu(iatom)%mat(1+(ispinor1-1)*ndim:ndim*ispinor1,1+(ispinor2-1)*ndim:ispinor2*ndim,isppol)
3043 : :
3044 [ # # ]: 0 : if (optprt > 2) then
3045 : 0 : write(message,'(2a,i2,a,i2,a,i2)') ch10,"SLM input matrix,&
3046 : 0 : & isppol=",isppol,", ispinor1=",ispinor1,", ispinor2=",ispinor2
3047 : 0 : call wrtout(std_out,message,'COLL')
3048 [ # # ]: 0 : do im1=1,ndim
3049 : : write(message,'(12(1x,9(1x,"(",f9.5,",",f9.5,")")))') &
3050 : 0 : & (mat_inp(im1,im2),im2=1,ndim)
3051 : 0 : call wrtout(std_out,message,'COLL')
3052 : : end do ! im1
3053 : : end if ! optprt>2
3054 : :
3055 : : call abi_xgemm("n",c2,ndim,ndim,ndim,cone,mat_inp(:,:),ndim,slm2ylm(:,1:ndim), &
3056 [ # # ]: 0 : & ndim_max,czero,mat_tmp(:,1+(ispin-1)*ndim:ndim*ispin),ndim)
3057 : :
3058 : : end do ! ispinor2
3059 : : end do ! ispinor1
3060 : : end do ! isppol
3061 : :
3062 : : call abi_xgemm(c1,"n",ndim,ndim*nspin,ndim,cone,slm2ylm(:,1:ndim),ndim_max,mat_tmp(:,:),ndim, &
3063 [ # # ]: 0 : & czero,mat_tmp2(:,:),ndim)
3064 : :
3065 : 0 : ispin = 0
3066 : :
3067 [ # # ]: 0 : do isppol=1,nsppol
3068 [ # # ]: 0 : do ispinor2=1,nspinor
3069 [ # # ]: 0 : do ispinor1=1,nspinor
3070 : :
3071 : 0 : ispin = ispin + 1
3072 : :
3073 : 0 : mat_out => mat_tmp2(:,1+(ispin-1)*ndim:ndim*ispin)
3074 : :
3075 [ # # # # : 0 : matlu(iatom)%mat(1+(ispinor1-1)*ndim:ndim*ispinor1,1+(ispinor2-1)*ndim:ispinor2*ndim,isppol) = mat_out(:,:)
# # # # #
# ]
3076 : :
3077 [ # # ]: 0 : if (optprt > 2) then
3078 : 0 : write(message,'(2a,i2,a,i2,a,i2)') ch10,"YLM output matrix, isppol=",isppol,", ispinor=",ispinor1,&
3079 : 0 : & ", ispinor2=",ispinor2
3080 : 0 : call wrtout(std_out,message,'COLL')
3081 [ # # ]: 0 : do im1=1,ndim
3082 : 0 : write(message,'(12(1x,9(1x,"(",f9.5,",",f9.5,")")))') (mat_out(im1,im2),im2=1,ndim)
3083 : 0 : call wrtout(std_out,message,'COLL')
3084 : : end do ! im1
3085 : : end if ! optprt>2
3086 : :
3087 : : end do ! ispinor1
3088 : : end do ! ispinor2
3089 : : end do ! isppol
3090 : :
3091 [ # # ]: 0 : ABI_FREE(mat_inp)
3092 [ # # ]: 0 : ABI_FREE(mat_tmp)
3093 [ # # ]: 0 : ABI_FREE(mat_tmp2)
3094 : :
3095 : : end do ! iatom
3096 : :
3097 : 0 : mat_out => null()
3098 : 0 : slm2ylm => null()
3099 : :
3100 : : !do iatom=1,natom
3101 : : ! lpawu=matlu(iatom)%lpawu
3102 : : ! if(lpawu.ne.-1) then
3103 : : ! ndim=2*lpawu+1
3104 : : ! ll=lpawu
3105 : : ! ABI_MALLOC(slm2ylm,(2*ll+1,2*ll+1))
3106 : : ! slm2ylm=czero
3107 : : ! do im=1,2*ll+1
3108 : : ! mm=im-ll-1;jm=-mm+ll+1
3109 : : ! onem=dble((-1)**mm)
3110 : : ! if (mm> 0) then
3111 : : ! slm2ylm(im,im)= cmplx(onem*invsqrt2,zero,kind=dp)
3112 : : ! slm2ylm(jm,im)= cmplx(invsqrt2, zero,kind=dp)
3113 : : ! end if
3114 : : ! if (mm==0) then
3115 : : ! slm2ylm(im,im)=cone
3116 : : ! end if
3117 : : ! if (mm< 0) then
3118 : : ! slm2ylm(im,im)= cmplx(zero, invsqrt2,kind=dp)
3119 : : ! slm2ylm(jm,im)=-cmplx(zero,onem*invsqrt2,kind=dp)
3120 : : ! end if
3121 : : ! end do
3122 : : ! if(optprt>2) then
3123 : : ! write(message,'(2a)') ch10,"SLM2YLM matrix"
3124 : : ! call wrtout(std_out,message,'COLL')
3125 : : ! do im1=1,ll*2+1
3126 : : ! write(message,'(12(1x,9(1x,"(",f9.5,",",f9.5,")")))')&
3127 : : !& (slm2ylm(im1,im2),im2=1,ll*2+1)
3128 : : ! call wrtout(std_out,message,'COLL')
3129 : : ! end do
3130 : : ! endif
3131 : : ! do isppol=1,matlu(1)%nsppol
3132 : : ! do ispinor=1,matlu(1)%nspinor
3133 : : ! do ispinor2=1,matlu(1)%nspinor
3134 : : ! ABI_MALLOC(mat_out_c,(2*ll+1,2*ll+1))
3135 : : ! ABI_MALLOC(mat_inp_c,(2*ll+1,2*ll+1))
3136 : : ! mat_inp_c(:,:) = matlu(iatom)%mat(1+(ispinor-1)*ndim:ndim+(ispinor-1)*ndim,1+(ispinor2-1)*ndim:ndim+(ispinor2-1)*ndim,isppol)
3137 : : ! mat_out_c=czero
3138 : :
3139 : : ! if(optprt>2) then
3140 : : ! write(message,'(2a, i2, a, i2, a, i2)') ch10,"SLM input matrix, isppol=", isppol, ", ispinor=", ispinor,&
3141 : : !& ", ispinor2=", ispinor2
3142 : : ! call wrtout(std_out,message,'COLL')
3143 : : ! do im1=1,ll*2+1
3144 : : ! write(message,'(12(1x,9(1x,"(",f9.5,",",f9.5,")")))')&
3145 : : !& (mat_inp_c(im1,im2),im2=1,ll*2+1)
3146 : : ! call wrtout(std_out,message,'COLL')
3147 : : ! end do
3148 : : ! endif
3149 : :
3150 : : ! do jm=1,2*ll+1
3151 : : ! do im=1,2*ll+1
3152 : : ! tmp2=czero
3153 : : ! do ii=1,2*ll+1
3154 : : ! do jj=1,2*ll+1
3155 : : ! if(option==1) then
3156 : : ! tmp2=tmp2+mat_inp_c(ii,jj)*(slm2ylm(im,ii))*CONJG(slm2ylm(jm,jj))
3157 : : ! else if(option==2) then
3158 : : ! tmp2=tmp2+mat_inp_c(ii,jj)*CONJG(slm2ylm(ii,im))*(slm2ylm(jj,jm))
3159 : : ! end if
3160 : : ! end do
3161 : : ! end do
3162 : : ! mat_out_c(im,jm)=tmp2
3163 : : ! end do
3164 : : ! end do
3165 : :
3166 : : ! if(optprt>2) then
3167 : : ! write(message,'(2a, i2, a, i2, a, i2)') ch10,"YLM output matrix, isppol=", isppol, ", ispinor=", ispinor,&
3168 : : !& ", ispinor2=", ispinor2
3169 : : ! call wrtout(std_out,message,'COLL')
3170 : : ! do im1=1,ll*2+1
3171 : : ! write(message,'(12(1x,9(1x,"(",f9.5,",",f9.5,")")))')&
3172 : : ! & (mat_out_c(im1,im2),im2=1,ll*2+1)
3173 : : ! call wrtout(std_out,message,'COLL')
3174 : : ! end do
3175 : : ! endif
3176 : :
3177 : : ! matlu(iatom)%mat(1+(ispinor-1)*ndim:ndim+(ispinor-1)*ndim,1+(ispinor2-1)*ndim:ndim+(ispinor2-1)*ndim,isppol)=mat_out_c(:,:)
3178 : : ! ABI_FREE(mat_out_c)
3179 : : ! ABI_FREE(mat_inp_c)
3180 : : ! enddo ! im
3181 : : ! enddo ! ispinor
3182 : : ! enddo ! isppol
3183 : : ! ABI_FREE(slm2ylm)
3184 : : ! endif ! lpawu
3185 : : !enddo ! iatom
3186 : :
3187 : 0 : end subroutine slm2ylm_matlu
3188 : : !!***
3189 : :
3190 : : !!****f* m_matlu/fac_matlu
3191 : : !! NAME
3192 : : !! fac_matlu
3193 : : !!
3194 : : !! FUNCTION
3195 : : !! Multiply matlu by a scalar
3196 : : !!
3197 : : !! COPYRIGHT
3198 : : !! Copyright (C) 2005-2026 ABINIT group (BAmadon)
3199 : : !! This file is distributed under the terms of the
3200 : : !! GNU General Public License, see ~abinit/COPYING
3201 : : !! or http://www.gnu.org/copyleft/gpl.txt .
3202 : : !!
3203 : : !! INPUTS
3204 : : !! matlu(natom) :: input quantity
3205 : : !! natom=number of atoms in cell.
3206 : : !! fac= factor
3207 : : !!
3208 : : !! OUTPUT
3209 : : !! matlu(natom) :: fac * matlu
3210 : : !!
3211 : : !! SIDE EFFECTS
3212 : : !!
3213 : : !! NOTES
3214 : : !!
3215 : : !! SOURCE
3216 : :
3217 : 19177 : subroutine fac_matlu(matlu,natom,fac)
3218 : :
3219 : : !Arguments ------------------------------------
3220 : : integer, intent(in) :: natom
3221 : : type(matlu_type), intent(inout) :: matlu(natom)
3222 : : complex(dp), intent(in) :: fac
3223 : : !Local variables-------------------------------
3224 : : integer :: iatom,lpawu
3225 : : ! character(len=500) :: message
3226 : : !************************************************************************
3227 : :
3228 [ + + ]: 40706 : do iatom=1,natom
3229 : 21529 : lpawu = matlu(iatom)%lpawu
3230 [ + + ]: 21529 : if (lpawu == -1) cycle
3231 [ + + + + : 1163524 : matlu(iatom)%mat(:,:,:) = fac * matlu(iatom)%mat(:,:,:)
+ + ]
3232 : : end do ! iatom
3233 : :
3234 : 19177 : end subroutine fac_matlu
3235 : : !!***
3236 : :
3237 : : !!****f* m_matlu/printplot_matlu
3238 : : !! NAME
3239 : : !! printplot_matlu
3240 : : !!
3241 : : !! FUNCTION
3242 : : !! Write matlu for a given frequency
3243 : : !!
3244 : : !! COPYRIGHT
3245 : : !! Copyright (C) 2005-2026 ABINIT group (BAmadon)
3246 : : !! This file is distributed under the terms of the
3247 : : !! GNU General Public License, see ~abinit/COPYING
3248 : : !! or http://www.gnu.org/copyleft/gpl.txt .
3249 : : !!
3250 : : !! INPUTS
3251 : : !! matlu(natom) :: input quantity to write
3252 : : !! natom=number of atoms in cell.
3253 : : !! freq :: frequency
3254 : : !! char1 :: name of the file on which to write
3255 : : !! units :: unit of the file
3256 : : !! imre :: if present, write real and imaginary parts in two different files
3257 : : !!
3258 : : !! OUTPUT
3259 : : !!
3260 : : !! SIDE EFFECTS
3261 : : !!
3262 : : !! NOTES
3263 : : !!
3264 : : !! SOURCE
3265 : :
3266 : 0 : subroutine printplot_matlu(matlu,natom,freq,char1,units,imre)
3267 : :
3268 : : !Arguments ------------------------------------
3269 : : !scalars
3270 : : integer, intent(in) :: natom,units
3271 : : integer, optional, intent(in) :: imre
3272 : : real(dp), intent(in) :: freq
3273 : : !arrays
3274 : : type(matlu_type), intent(in) :: matlu(natom)
3275 : : character(len=*), intent(in) :: char1
3276 : : !Local variables-------------------------------
3277 : : !scalars
3278 : : integer :: iatom,im,im1,ispinor,ispinor1,isppol
3279 : : integer :: lpawu,ndim,nspinor,nsppol,unitnb
3280 : : character(len=4) :: tag_at
3281 : : character(len=fnlen) :: tmpfil,tmpfilim,tmpfilre
3282 : : ! character(len=500) :: message
3283 : : !arrays
3284 : : !************************************************************************
3285 : :
3286 : 0 : nspinor = matlu(1)%nspinor
3287 : 0 : nsppol = matlu(1)%nsppol
3288 : :
3289 : : ! not yet tested and used
3290 [ # # ]: 0 : do iatom=1,natom
3291 : 0 : lpawu = matlu(iatom)%lpawu
3292 [ # # ]: 0 : if (lpawu == -1) cycle
3293 : 0 : ndim = 2*lpawu + 1
3294 : 0 : unitnb = units + iatom
3295 : 0 : call int2char4(iatom,tag_at)
3296 [ # # ]: 0 : if (present(imre)) then
3297 [ # # ]: 0 : tmpfilre = trim(char1)//tag_at//"re"
3298 [ # # ]: 0 : tmpfilim = trim(char1)//tag_at//"im"
3299 : 0 : open(unit=unitnb+10,file=trim(tmpfilre),status='unknown',form='formatted')
3300 : 0 : open(unit=unitnb+20,file=trim(tmpfilim),status='unknown',form='formatted')
3301 : 0 : write(unitnb+10,'(400e26.16)') freq,(((((dble(matlu(iatom)%mat(im+(ispinor-1)*ndim,im1+(ispinor1-1)*ndim,isppol)),&
3302 [ # # # # : 0 : & im=1,ndim),ispinor=1,nspinor),im1=1,ndim),ispinor1=1,nspinor),isppol=1,nsppol)
# # # # #
# # # # #
# # # # #
# ]
3303 : 0 : write(unitnb+20,'(400e26.16)') freq,(((((aimag(matlu(iatom)%mat(im+(ispinor-1)*ndim,im1+(ispinor1-1)*ndim,isppol)),&
3304 [ # # # # : 0 : & im=1,ndim),ispinor=1,nspinor),im1=1,ndim),ispinor1=1,nspinor),isppol=1,nsppol)
# # # # #
# # # # #
# # # # #
# ]
3305 : : else
3306 [ # # ]: 0 : tmpfil = trim(char1)//tag_at
3307 : 0 : open(unit=unitnb,file=trim(tmpfil),status='unknown',form='formatted')
3308 : 0 : write(unitnb,'(400e26.16)') freq,(((((matlu(iatom)%mat(im+(ispinor-1)*ndim,im1+(ispinor1-1)*ndim,isppol),&
3309 [ # # # # : 0 : & im=1,ndim),ispinor=1,nspinor),im1=1,ndim),ispinor1=1,nspinor),isppol=1,nsppol)
# # # # #
# # # # #
# # # # #
# ]
3310 : : end if ! present(imre)
3311 : : end do ! iatom
3312 : :
3313 : 0 : end subroutine printplot_matlu
3314 : : !!***
3315 : :
3316 : : !!****f* m_matlu/identity_matlu
3317 : : !! NAME
3318 : : !! identity_matlu
3319 : : !!
3320 : : !! FUNCTION
3321 : : !! Set the diagonal elements to 1 (the off-diagonal are not set to 0)
3322 : : !!
3323 : : !! COPYRIGHT
3324 : : !! Copyright (C) 2005-2026 ABINIT group (BAmadon)
3325 : : !! This file is distributed under the terms of the
3326 : : !! GNU General Public License, see ~abinit/COPYING
3327 : : !! or http://www.gnu.org/copyleft/gpl.txt .
3328 : : !!
3329 : : !! INPUTS
3330 : : !! matlu(natom) :: input quantity
3331 : : !! natom=number of atoms in cell.
3332 : : !!
3333 : : !! OUTPUT
3334 : : !!
3335 : : !! SIDE EFFECTS
3336 : : !!
3337 : : !! NOTES
3338 : : !!
3339 : : !! SOURCE
3340 : :
3341 : 267 : subroutine identity_matlu(matlu,natom)
3342 : :
3343 : : !Arguments ------------------------------------
3344 : : integer, intent(in) :: natom
3345 : : type(matlu_type), intent(inout) :: matlu(natom)
3346 : : !Local variables-------------------------------
3347 : : integer :: iatom,im,lpawu,ndim,nspinor
3348 : : ! character(len=500) :: message
3349 : : !arrays
3350 : : !************************************************************************
3351 : :
3352 : 267 : nspinor = matlu(1)%nspinor
3353 : :
3354 [ + + ]: 1215 : do iatom=1,natom
3355 : 948 : lpawu = matlu(iatom)%lpawu
3356 [ + + ]: 948 : if (lpawu == -1) cycle
3357 : 303 : ndim = nspinor * (2*lpawu+1)
3358 [ + + ]: 1926 : do im=1,ndim
3359 [ + + ]: 4300 : matlu(iatom)%mat(im,im,:) = cone
3360 : : end do ! im
3361 : : end do ! iatom
3362 : :
3363 : 267 : end subroutine identity_matlu
3364 : : !!***
3365 : :
3366 : : !!***
3367 : : !!****f* m_matlu/magmomforb_matlu
3368 : : !! NAME
3369 : : !! magmomforb_matlu
3370 : : !!
3371 : : !! FUNCTION
3372 : : !! return the product of occupation matrix of dimension [(2*ll+1)]**4 in the Ylm basis
3373 : : !! with the matrix of orbital angular momentum element for the x,y and z direction.
3374 : : !! Option gives the direction of the magnetic moment x==1, y==2 and z==3.
3375 : : !!
3376 : : !!
3377 : : !! COPYRIGHT
3378 : : !! Copyright (C) 2005-2026 ABINIT group (FGendron)
3379 : : !! This file is distributed under the terms of the
3380 : : !! GNU General Public License, see ~abinit/COPYING
3381 : : !! or http://www.gnu.org/copyleft/gpl.txt .
3382 : : !!
3383 : : !! INPUTS
3384 : : !! matlu1(natom)%(nsppol,nspinor,nspinor,ndim,ndim) :: input quantity in Ylm basis
3385 : : !! natom :: number of atoms
3386 : : !! option = 1 :: x axis
3387 : : !! = 2 :: y axis
3388 : : !! = 3 :: z axis
3389 : : !! optptr > 2 :: print orbital angular matrix elements and resulting product
3390 : : !!
3391 : : !! OUTPUT
3392 : : !! matlu(natom)%(nsppol,nspinor,nspinor,ndim,ndim) :: product
3393 : : !!
3394 : : !! SIDE EFFECTS
3395 : : !!
3396 : : !! NOTES
3397 : : !!
3398 : : !! SOURCE
3399 : 0 : subroutine magmomforb_matlu(matlu,mu,natom,option,optprt)
3400 : : use defs_wvltypes
3401 : :
3402 : : !Arguments ------------------------------------
3403 : : !scalars
3404 : : integer, intent(in) :: natom,option,optprt
3405 : : complex(dp), allocatable, intent(inout) :: mu(:)
3406 : : !arrays
3407 : : type(matlu_type), intent(inout) :: matlu(natom)
3408 : : !Local variables-------------------------------
3409 : : !scalars
3410 : : integer :: iatom,im,ispinor,isppol,ispinor2
3411 : : integer :: lpawu,ll,jm,ml1,jc1,ms1,lcor,im1,im2,tndim,ndim
3412 : : character(len=500) :: message
3413 : : real(dp) :: xj
3414 : : !arrays
3415 : 0 : complex(dp),allocatable :: mat_out_c(:,:)
3416 : : ! integer, allocatable :: ind_msml(:,:)
3417 : 0 : complex(dp), allocatable :: temp_mat(:,:)
3418 : 0 : type(coeff2c_type), allocatable :: gathermatlu(:)
3419 : 0 : type(coeff2c_type), allocatable :: muorb(:)
3420 : : !************************************************************************
3421 : :
3422 : : !=====================================
3423 : : ! Allocate matrices
3424 : : !=====================================
3425 : :
3426 [ # # # # : 0 : ABI_MALLOC(gathermatlu,(natom))
# # # # #
# # # #
# ]
3427 [ # # # # : 0 : ABI_MALLOC(muorb,(natom))
# # # # #
# ]
3428 [ # # ]: 0 : do iatom=1,natom
3429 [ # # ]: 0 : if(matlu(iatom)%lpawu.ne.-1) then
3430 : 0 : tndim=2*(2*matlu(iatom)%lpawu+1)
3431 [ # # # # : 0 : ABI_MALLOC(gathermatlu(iatom)%value,(tndim,tndim))
# # # # #
# # # # #
# # # # ]
3432 [ # # # # ]: 0 : gathermatlu(iatom)%value=czero
3433 [ # # # # : 0 : ABI_MALLOC(muorb(iatom)%value,(tndim,tndim))
# # # # #
# # # #
# ]
3434 [ # # # # ]: 0 : muorb(iatom)%value=czero
3435 : : end if
3436 : : end do
3437 : :
3438 [ # # ]: 0 : do iatom=1,natom
3439 : 0 : lpawu=matlu(iatom)%lpawu
3440 [ # # ]: 0 : if(lpawu.ne.-1) then
3441 : :
3442 : 0 : ll=lpawu
3443 : 0 : lcor=lpawu
3444 : : !=====================================
3445 : : !build orbital angular momentum matrix along x axis
3446 : : !=====================================
3447 [ # # ]: 0 : if(option==1) then
3448 : :
3449 : : jc1=0
3450 [ # # ]: 0 : do ms1 =-1,1
3451 : 0 : xj=float(ms1)+half
3452 [ # # ]: 0 : do ml1 = -ll,ll
3453 : 0 : jc1=jc1+1
3454 [ # # ]: 0 : if(jc1 == 1) then
3455 : 0 : muorb(iatom)%value(jc1,jc1+1) = sqrt(float((lcor*(lcor+1)) - ml1*(ml1 + 1)))*0.5
3456 : : endif
3457 [ # # # # ]: 0 : if(jc1 > 1 .and. jc1 < 2*(2*ll+1)) then
3458 : 0 : muorb(iatom)%value(jc1,jc1+1) = sqrt(float((lcor*(lcor+1)) - ml1*(ml1 + 1)))*0.5
3459 : 0 : muorb(iatom)%value(jc1,jc1-1) = sqrt(float((lcor*(lcor+1)) - ml1*(ml1 - 1)))*0.5
3460 [ # # ]: 0 : else if(jc1== 2*(2*ll+1)) then
3461 : 0 : muorb(iatom)%value(jc1,jc1-1) = sqrt(float((lcor*(lcor+1)) - ml1*(ml1 - 1)))*0.5
3462 : : end if
3463 : : end do
3464 : : end do
3465 : :
3466 : : !=====================================
3467 : : !build orbital angular momentum matrix along y axis
3468 : : !=====================================
3469 [ # # ]: 0 : else if(option==2) then
3470 : :
3471 : : jc1=0
3472 [ # # ]: 0 : do ms1 =-1,1
3473 : 0 : xj=float(ms1)+half
3474 [ # # ]: 0 : do ml1 = -ll,ll
3475 : 0 : jc1=jc1+1
3476 [ # # ]: 0 : if(jc1 == 1) then
3477 : 0 : muorb(iatom)%value(jc1,jc1+1) = cmplx(zero,sqrt(float((lcor*(lcor+1)) - ml1*(ml1 + 1)))*0.5,kind=dp)
3478 : : endif
3479 [ # # # # ]: 0 : if(jc1 > 1 .and. jc1 < 2*(2*ll+1)) then
3480 : 0 : muorb(iatom)%value(jc1,jc1+1) = cmplx(zero,sqrt(float((lcor*(lcor+1)) - ml1*(ml1 + 1)))*0.5,kind=dp)
3481 : 0 : muorb(iatom)%value(jc1,jc1-1) = cmplx(zero,-sqrt(float((lcor*(lcor+1)) - ml1*(ml1 - 1)))*0.5,kind=dp)
3482 [ # # ]: 0 : else if(jc1 == 2*(2*ll+1)) then
3483 : 0 : muorb(iatom)%value(jc1,jc1-1) = cmplx(zero,-sqrt(float((lcor*(lcor+1)) - ml1*(ml1 - 1)))*0.5,kind=dp)
3484 : : end if
3485 : : end do
3486 : : end do
3487 : :
3488 : : !=====================================
3489 : : !build orbital angular momentum matrix along z axis
3490 : : !=====================================
3491 [ # # ]: 0 : else if(option==3) then
3492 : : jc1=0
3493 [ # # ]: 0 : do ms1=-1,1
3494 [ # # ]: 0 : do ml1=-ll,ll
3495 : 0 : jc1=jc1+1
3496 [ # # ]: 0 : if(jc1 < tndim+1) then
3497 : 0 : muorb(iatom)%value(jc1,jc1) = ml1
3498 : : endif
3499 : : end do
3500 : : end do
3501 : : end if
3502 : :
3503 [ # # ]: 0 : if(optprt>2) then
3504 : 0 : write(message,'(a,i4)') "Orbital angular momentum matrix elements in |m_l,m_s> basis for axis=", option
3505 : 0 : call wrtout(std_out,message,"COLL")
3506 [ # # ]: 0 : do im=1,2*(ll*2+1)
3507 [ # # # # ]: 0 : write(message,'(6(1x,9(1x,f4.1,",",f4.1)))') (muorb(iatom)%value(im,jm),jm=1,2*(ll*2+1))
3508 : 0 : call wrtout(std_out,message,"COLL")
3509 : : end do
3510 : : end if
3511 : :
3512 : : end if !lpawu
3513 : : end do !atom
3514 : :
3515 : : !=====================================
3516 : : ! Reshape input Ylm matlu in one 14x14 matrix
3517 : : !=====================================
3518 : :
3519 : 0 : call gather_matlu(matlu,gathermatlu,natom,option=1,prtopt=1)
3520 : :
3521 : : !!printing for debug
3522 : : ! write(std_out,*) "gathermatlu in magmomforb"
3523 : : ! do im1=1,tndim
3524 : : ! write(message,'(12(1x,9(1x,"(",f9.5,",",f9.5,")")))')&
3525 : : ! (gathermatlu(1)%value(im1,im2),im2=1,tndim)
3526 : : ! call wrtout(std_out,message,'COLL')
3527 : : ! end do
3528 : :
3529 : : !=====================================
3530 : : ! Matrix product of Occ and muorb
3531 : : !=====================================
3532 [ # # ]: 0 : do iatom=1,natom
3533 [ # # ]: 0 : if(matlu(iatom)%lpawu.ne.-1) then
3534 : 0 : tndim=2*(2*matlu(iatom)%lpawu+1)
3535 [ # # # # : 0 : ABI_MALLOC(temp_mat,(tndim,tndim))
# # # # #
# # # # #
# # ]
3536 : :
3537 : : call abi_zgemm('n','n',tndim,tndim,tndim,cone,&
3538 : : & gathermatlu(iatom)%value,tndim,&
3539 : : & muorb(iatom)%value,tndim,czero,&
3540 : 0 : & temp_mat,tndim)
3541 : :
3542 [ # # # # : 0 : gathermatlu(iatom)%value=temp_mat
# # # # #
# # # ]
3543 [ # # ]: 0 : ABI_FREE(temp_mat)
3544 : :
3545 : : !=====================================
3546 : : ! Trace of matrix product
3547 : : !=====================================
3548 : :
3549 [ # # ]: 0 : do im1=1,tndim
3550 [ # # ]: 0 : do im2=1,tndim
3551 [ # # ]: 0 : if(im1==im2) then
3552 : 0 : mu(iatom) = mu(iatom) + gathermatlu(iatom)%value(im1,im2)
3553 : : end if
3554 : : end do
3555 : : end do
3556 : :
3557 : :
3558 : : !=====================================
3559 : : ! Reshape product matrix into matlu format
3560 : : !=====================================
3561 : :
3562 : : !call gather_matlu(matlu,gathermatlu,natom,option=-1,prtopt=1)
3563 : :
3564 : :
3565 [ # # ]: 0 : if(optprt>2) then
3566 [ # # # # : 0 : ABI_MALLOC(mat_out_c,(2*ll+1,2*ll+1))
# # # # #
# # # # #
# # # # ]
3567 : 0 : ndim = 2*ll+1
3568 [ # # ]: 0 : do isppol=1,matlu(1)%nsppol
3569 [ # # ]: 0 : do ispinor=1,matlu(1)%nspinor
3570 [ # # ]: 0 : do ispinor2=1,matlu(1)%nspinor
3571 [ # # # # ]: 0 : mat_out_c(:,:) = matlu(iatom)%mat(1+(ispinor-1)*ndim:ndim+(ispinor-1)*ndim,1+(ispinor2-1)*ndim:ndim+(ispinor2-1)*ndim,isppol)
3572 : :
3573 : 0 : write(message,'(2a, i2, a, i2, a, i2)') ch10,"Orbital angular momentum matrix, isppol=", isppol, ", ispinor=",&
3574 : 0 : & ispinor,", ispinor2=", ispinor2
3575 : 0 : call wrtout(std_out,message,'COLL')
3576 [ # # ]: 0 : do im1=1,ll*2+1
3577 : : write(message,'(12(1x,9(1x,"(",f9.5,",",f9.5,")")))')&
3578 : 0 : & (mat_out_c(im1,im2),im2=1,ll*2+1)
3579 : 0 : call wrtout(std_out,message,'COLL')
3580 : : end do
3581 : :
3582 : : end do ! ispinor2
3583 : : end do ! ispinor
3584 : : end do ! isppol
3585 [ # # ]: 0 : ABI_FREE(mat_out_c)
3586 : : endif
3587 : :
3588 : : end if !lpawu
3589 : : end do !atom
3590 : :
3591 : : !=====================================
3592 : : ! Deallocate gathermatlu
3593 : : !=====================================
3594 : :
3595 [ # # ]: 0 : do iatom=1,natom
3596 [ # # ]: 0 : if(matlu(iatom)%lpawu.ne.-1) then
3597 [ # # ]: 0 : ABI_FREE(gathermatlu(iatom)%value)
3598 [ # # ]: 0 : ABI_FREE(muorb(iatom)%value)
3599 : : end if
3600 : : end do
3601 [ # # # # : 0 : ABI_FREE(gathermatlu)
# # # # ]
3602 [ # # # # : 0 : ABI_FREE(muorb)
# # # # ]
3603 : :
3604 : 0 : end subroutine magmomforb_matlu
3605 : :
3606 : : !!***
3607 : :
3608 : :
3609 : : !!***
3610 : : !!****f* m_matlu/magmomfspin_matlu
3611 : : !! NAME
3612 : : !! magmomfspin_matlu
3613 : : !!
3614 : : !! FUNCTION
3615 : : !! return the product of occupation matrix of dimension [(2*ll+1)]**4 in the Ylm basis
3616 : : !! with the matrix of spin angular momentum element for the x,y and z direction.
3617 : : !! Option gives the direction of the magnetic moment x==1, y==2 and z==3.
3618 : : !!
3619 : : !!
3620 : : !! COPYRIGHT
3621 : : !! Copyright (C) 2005-2026 ABINIT group (FGendron)
3622 : : !! This file is distributed under the terms of the
3623 : : !! GNU General Public License, see ~abinit/COPYING
3624 : : !! or http://www.gnu.org/copyleft/gpl.txt .
3625 : : !!
3626 : : !! INPUTS
3627 : : !! matlu1(natom)%(nsppol,nspinor,nspinor,ndim,ndim) :: input quantity in Ylm basis
3628 : : !! natom :: number of atoms
3629 : : !! option = 1 :: x axis
3630 : : !! = 2 :: y axis
3631 : : !! = 3 :: z axis
3632 : : !! optptr > 2 :: print spin angular matrix elements and resulting product
3633 : : !!
3634 : : !! OUTPUT
3635 : : !! matlu(natom)%(nsppol,nspinor,nspinor,ndim,ndim) :: product
3636 : : !!
3637 : : !! SIDE EFFECTS
3638 : : !!
3639 : : !! NOTES
3640 : : !!
3641 : : !! SOURCE
3642 : 0 : subroutine magmomfspin_matlu(matlu,mu,natom,option,optprt)
3643 : : use defs_wvltypes
3644 : :
3645 : : !Arguments ------------------------------------
3646 : : !scalars
3647 : : integer, intent(in) :: natom,option,optprt
3648 : : complex(dp), allocatable, intent(inout) :: mu(:)
3649 : : !arrays
3650 : : type(matlu_type), intent(inout) :: matlu(natom)
3651 : : !Local variables-------------------------------
3652 : : !scalars
3653 : : integer :: iatom,im,ispinor,isppol,ispinor2
3654 : : integer :: lpawu,ll,jm,ml1,jc1,ms1,lcor,im1,im2,tndim,ndim
3655 : : character(len=500) :: message
3656 : : real(dp) :: xj
3657 : : !arrays
3658 : 0 : complex(dp),allocatable :: mat_out_c(:,:)
3659 : 0 : integer, allocatable :: ind_msml(:,:)
3660 : 0 : complex(dp), allocatable :: temp_mat(:,:)
3661 : 0 : type(coeff2c_type), allocatable :: gathermatlu(:)
3662 : 0 : type(coeff2c_type), allocatable :: muspin(:)
3663 : : !************************************************************************
3664 : :
3665 : : !=====================================
3666 : : ! Allocate matrices
3667 : : !=====================================
3668 : :
3669 [ # # # # : 0 : ABI_MALLOC(gathermatlu,(natom))
# # # # #
# # # #
# ]
3670 [ # # # # : 0 : ABI_MALLOC(muspin,(natom))
# # # # #
# ]
3671 [ # # ]: 0 : do iatom=1,natom
3672 [ # # ]: 0 : if(matlu(iatom)%lpawu.ne.-1) then
3673 : 0 : tndim=2*(2*matlu(iatom)%lpawu+1)
3674 [ # # # # : 0 : ABI_MALLOC(gathermatlu(iatom)%value,(tndim,tndim))
# # # # #
# # # # #
# # # # ]
3675 [ # # # # ]: 0 : gathermatlu(iatom)%value=czero
3676 [ # # # # : 0 : ABI_MALLOC(muspin(iatom)%value,(tndim,tndim))
# # # # #
# # # #
# ]
3677 [ # # # # ]: 0 : muspin(iatom)%value=czero
3678 : : end if
3679 : : end do
3680 : :
3681 [ # # ]: 0 : do iatom=1,natom
3682 : 0 : lpawu=matlu(iatom)%lpawu
3683 [ # # ]: 0 : if(lpawu.ne.-1) then
3684 : 0 : ll=lpawu
3685 : 0 : lcor=lpawu
3686 [ # # # # : 0 : ABI_MALLOC(ind_msml,(2,-ll:ll))
# # # # #
# # # ]
3687 [ # # # # ]: 0 : ind_msml=czero
3688 : : !=====================================
3689 : : !build spin angular momentum matrix along x axis
3690 : : !=====================================
3691 [ # # ]: 0 : if(option==1) then
3692 : : jc1=0
3693 [ # # ]: 0 : do ms1=1,2
3694 [ # # ]: 0 : do ml1=-ll,ll
3695 : 0 : jc1=jc1+1
3696 : 0 : ind_msml(ms1,ml1)=jc1
3697 : : end do
3698 : : end do
3699 : :
3700 : : jc1=0
3701 [ # # ]: 0 : do ms1 =-1,1
3702 : 0 : xj=float(ms1)+half
3703 [ # # ]: 0 : do ml1 = -ll,ll
3704 : 0 : jc1=jc1+1
3705 [ # # ]: 0 : if(xj < 0.0 ) then
3706 : 0 : muspin(iatom)%value(ind_msml(2,ml1),jc1) = 0.5
3707 [ # # ]: 0 : else if(xj > 0.0) then
3708 : 0 : muspin(iatom)%value(ind_msml(1,ml1),ind_msml(2,ml1)) = 0.5
3709 : : end if
3710 : : end do
3711 : : end do
3712 : :
3713 : : !=====================================
3714 : : !build spin angular momentum matrix along y axis
3715 : : !up spin is first
3716 : : !=====================================
3717 [ # # ]: 0 : else if(option==2) then
3718 : : jc1=0
3719 [ # # ]: 0 : do ms1=1,2
3720 [ # # ]: 0 : do ml1=-ll,ll
3721 : 0 : jc1=jc1+1
3722 : 0 : ind_msml(ms1,ml1)=jc1
3723 : : end do
3724 : : end do
3725 : :
3726 : : jc1=0
3727 [ # # ]: 0 : do ms1 =-1,1
3728 : 0 : xj=float(ms1)+half
3729 [ # # ]: 0 : do ml1 = -ll,ll
3730 : 0 : jc1=jc1+1
3731 [ # # ]: 0 : if(xj < 0.0 ) then
3732 : 0 : muspin(iatom)%value(ind_msml(2,ml1),jc1) = cmplx(zero,0.5,kind=dp)
3733 [ # # ]: 0 : else if(xj > 0.0) then
3734 : 0 : muspin(iatom)%value(ind_msml(1,ml1),ind_msml(2,ml1)) = cmplx(zero,-0.5,kind=dp)
3735 : : end if
3736 : : end do
3737 : : end do
3738 : :
3739 : : !=====================================
3740 : : !build spin angular momentum matrix along z axis
3741 : : !up spin is first
3742 : : !=====================================
3743 [ # # ]: 0 : else if(option==3) then
3744 : : jc1=0
3745 [ # # ]: 0 : do ms1=-1,1
3746 : 0 : xj=float(ms1)+half
3747 [ # # ]: 0 : do ml1=-ll,ll
3748 : 0 : jc1=jc1+1
3749 [ # # ]: 0 : if(jc1 < tndim+1) then
3750 [ # # ]: 0 : if(xj < 0.0 ) then
3751 : 0 : muspin(iatom)%value(jc1,jc1) = -xj
3752 [ # # ]: 0 : else if(xj > 0.0) then
3753 : 0 : muspin(iatom)%value(jc1,jc1) = -xj
3754 : : end if
3755 : : endif
3756 : : end do
3757 : : end do
3758 : : end if
3759 : :
3760 [ # # ]: 0 : if(optprt>2) then
3761 : 0 : write(message,'(a,i4)') "Spin angular momentum matrix elements in |m_l,m_s> basis for axis", option
3762 : 0 : call wrtout(std_out,message,"COLL")
3763 [ # # ]: 0 : do im=1,2*(ll*2+1)
3764 [ # # # # ]: 0 : write(message,'(6(1x,9(1x,f4.1,",",f4.1)))') (muspin(iatom)%value(im,jm),jm=1,2*(ll*2+1))
3765 : 0 : call wrtout(std_out,message,"COLL")
3766 : : end do
3767 : : end if
3768 : :
3769 [ # # ]: 0 : ABI_FREE(ind_msml)
3770 : : end if !lpawu
3771 : : end do !atom
3772 : :
3773 : : !=====================================
3774 : : ! Reshape input Ylm matlu in one 14x14 matrix
3775 : : !=====================================
3776 : :
3777 : 0 : call gather_matlu(matlu,gathermatlu,natom,option=1,prtopt=1)
3778 : :
3779 : : !!printing for debug
3780 : : !! write(std_out,*) "gathermatlu in magmomfspin"
3781 : : !! do im1=1,tndim
3782 : : !! write(message,'(12(1x,9(1x,"(",f9.5,",",f9.5,")")))')&
3783 : : !! (gathermatlu(1)%value(im1,im2),im2=1,tndim)
3784 : : !! call wrtout(std_out,message,'coll')
3785 : : !! end do
3786 : :
3787 : : !=====================================
3788 : : ! Matrix product of Occ and muspin
3789 : : !=====================================
3790 [ # # ]: 0 : do iatom=1,natom
3791 [ # # ]: 0 : if(matlu(iatom)%lpawu.ne.-1) then
3792 : 0 : tndim=2*(2*matlu(iatom)%lpawu+1)
3793 [ # # # # : 0 : ABI_MALLOC(temp_mat,(tndim,tndim))
# # # # #
# # # # #
# # ]
3794 : :
3795 : : call zgemm('n','n',tndim,tndim,tndim,cone,&
3796 : : & gathermatlu(iatom)%value,tndim,&
3797 : : & muspin(iatom)%value,tndim,czero,&
3798 : 0 : & temp_mat,tndim)
3799 : :
3800 [ # # # # : 0 : gathermatlu(iatom)%value=temp_mat
# # # # #
# # # ]
3801 [ # # ]: 0 : ABI_FREE(temp_mat)
3802 : :
3803 : : !!printing for debug
3804 : : !!write(std_out,*) "gathermatlu in magmomfspin after product"
3805 : : !!do im1=1,tndim
3806 : : !! write(message,'(12(1x,9(1x,"(",f9.5,",",f9.5,")")))')&
3807 : : !! (gathermatlu(1)%value(im1,im2),im2=1,tndim)
3808 : : !! call wrtout(std_out,message,'coll')
3809 : : !!end do
3810 : :
3811 : : !=====================================
3812 : : ! Trace of matrix product
3813 : : !=====================================
3814 : :
3815 [ # # ]: 0 : do im1=1,tndim
3816 [ # # ]: 0 : do im2=1,tndim
3817 [ # # ]: 0 : if(im1==im2) then
3818 : 0 : mu(iatom) = mu(iatom) + gathermatlu(iatom)%value(im1,im2)
3819 : : end if
3820 : : end do
3821 : : end do
3822 : :
3823 : : !=====================================
3824 : : ! Reshape product matrix into matlu format
3825 : : !=====================================
3826 : :
3827 : : !call gather_matlu(matlu,gathermatlu,natom,option=-1,prtopt=1)
3828 : :
3829 : :
3830 : : !=====================================
3831 : : ! Print matlu
3832 : : !=====================================
3833 [ # # ]: 0 : if(optprt>2) then
3834 [ # # # # : 0 : ABI_MALLOC(mat_out_c,(2*ll+1,2*ll+1))
# # # # #
# # # # #
# # # # ]
3835 : 0 : ndim = 2*ll+1
3836 [ # # ]: 0 : do isppol=1,matlu(1)%nsppol
3837 [ # # ]: 0 : do ispinor=1,matlu(1)%nspinor
3838 [ # # ]: 0 : do ispinor2=1,matlu(1)%nspinor
3839 [ # # # # ]: 0 : mat_out_c(:,:) = matlu(iatom)%mat(1+(ispinor-1)*ndim:ndim+(ispinor-1)*ndim,1+(ispinor2-1)*ndim:ndim+(ispinor2-1)*ndim,isppol)
3840 : :
3841 : 0 : write(message,'(2a, i2, a, i2, a, i2)') ch10,"Spin angular momentum matrix, isppol=", isppol, ", ispinor=", ispinor,&
3842 : 0 : & ", ispinor2=", ispinor2
3843 : 0 : call wrtout(std_out,message,'COLL')
3844 [ # # ]: 0 : do im1=1,ll*2+1
3845 : : write(message,'(12(1x,9(1x,"(",f9.5,",",f9.5,")")))')&
3846 : 0 : & (mat_out_c(im1,im2),im2=1,ll*2+1)
3847 : 0 : call wrtout(std_out,message,'COLL')
3848 : : end do
3849 : :
3850 : : end do ! im
3851 : : end do ! ispinor
3852 : : end do ! isppol
3853 [ # # ]: 0 : ABI_FREE(mat_out_c)
3854 : : endif
3855 : :
3856 : : end if !lpawu
3857 : : end do !atom
3858 : :
3859 : : !=====================================
3860 : : ! Deallocate gathermatlu
3861 : : !=====================================
3862 : :
3863 [ # # ]: 0 : do iatom=1,natom
3864 [ # # ]: 0 : if(matlu(iatom)%lpawu.ne.-1) then
3865 [ # # ]: 0 : ABI_FREE(gathermatlu(iatom)%value)
3866 [ # # ]: 0 : ABI_FREE(muspin(iatom)%value)
3867 : : end if
3868 : : end do
3869 [ # # # # : 0 : ABI_FREE(gathermatlu)
# # # # ]
3870 [ # # # # : 0 : ABI_FREE(muspin)
# # # # ]
3871 : :
3872 : 0 : end subroutine magmomfspin_matlu
3873 : :
3874 : : !!***
3875 : :
3876 : :
3877 : : !!***
3878 : : !!****f* m_matlu/magmomfzeeman_matlu
3879 : : !! NAME
3880 : : !! magmomfspin_matlu
3881 : : !!
3882 : : !! FUNCTION
3883 : : !! return the product of occupation matrix of dimension [(2*ll+1)]**4 in the Ylm basis
3884 : : !! with the matrix of Zeeman angular momentum element (L_u + 2*S_u) for the x,y and z direction.
3885 : : !! Option gives the direction of the magnetic moment x==1, y==2 and z==3.
3886 : : !!
3887 : : !!
3888 : : !! COPYRIGHT
3889 : : !! Copyright (C) 2005-2026 ABINIT group (FGendron)
3890 : : !! This file is distributed under the terms of the
3891 : : !! GNU General Public License, see ~abinit/COPYING
3892 : : !! or http://www.gnu.org/copyleft/gpl.txt .
3893 : : !!
3894 : : !! INPUTS
3895 : : !! matlu1(natom)%(nsppol,nspinor,nspinor,ndim,ndim) :: input quantity in Ylm basis
3896 : : !! natom :: number of atoms
3897 : : !! option = 1 :: x axis
3898 : : !! = 2 :: y axis
3899 : : !! = 3 :: z axis
3900 : : !! optptr > 2 :: print Zeeman angular matrix elements and resulting product
3901 : : !!
3902 : : !! OUTPUT
3903 : : !! matlu(natom)%(nsppol,nspinor,nspinor,ndim,ndim) :: product
3904 : : !!
3905 : : !! SIDE EFFECTS
3906 : : !!
3907 : : !! NOTES
3908 : : !!
3909 : : !! SOURCE
3910 : 0 : subroutine magmomfzeeman_matlu(matlu,mu,natom,option,optprt)
3911 : : use defs_wvltypes
3912 : :
3913 : : !Arguments ------------------------------------
3914 : : !scalars
3915 : : integer, intent(in) :: natom,option,optprt
3916 : : complex(dp), allocatable, intent(inout) :: mu(:)
3917 : : !arrays
3918 : : type(matlu_type), intent(inout) :: matlu(natom)
3919 : : !Local variables-------------------------------
3920 : : !scalars
3921 : : integer :: iatom,im,ispinor,isppol,ispinor2
3922 : : integer :: lpawu,ll,jm,ml1,jc1,ms1,lcor,im1,im2,tndim,ndim
3923 : : character(len=500) :: message
3924 : : real(dp) :: xj
3925 : : !arrays
3926 : 0 : complex(dp),allocatable :: mat_out_c(:,:)
3927 : 0 : integer, allocatable :: ind_msml(:,:)
3928 : 0 : complex(dp), allocatable :: temp_mat(:,:)
3929 : 0 : type(coeff2c_type), allocatable :: gathermatlu(:)
3930 : 0 : type(coeff2c_type), allocatable :: muzeeman(:)
3931 : : !************************************************************************
3932 : :
3933 : : !=====================================
3934 : : ! Allocate matrices
3935 : : !=====================================
3936 : :
3937 [ # # # # : 0 : ABI_MALLOC(gathermatlu,(natom))
# # # # #
# # # #
# ]
3938 [ # # # # : 0 : ABI_MALLOC(muzeeman,(natom))
# # # # #
# ]
3939 [ # # ]: 0 : do iatom=1,natom
3940 [ # # ]: 0 : if(matlu(iatom)%lpawu.ne.-1) then
3941 : 0 : tndim=2*(2*matlu(iatom)%lpawu+1)
3942 [ # # # # : 0 : ABI_MALLOC(gathermatlu(iatom)%value,(tndim,tndim))
# # # # #
# # # # #
# # # # ]
3943 [ # # # # ]: 0 : gathermatlu(iatom)%value=czero
3944 [ # # # # : 0 : ABI_MALLOC(muzeeman(iatom)%value,(tndim,tndim))
# # # # #
# # # #
# ]
3945 [ # # # # ]: 0 : muzeeman(iatom)%value=czero
3946 : : end if
3947 : : end do
3948 : :
3949 [ # # ]: 0 : do iatom=1,natom
3950 : 0 : lpawu=matlu(iatom)%lpawu
3951 [ # # ]: 0 : if(lpawu.ne.-1) then
3952 : 0 : ll=lpawu
3953 : 0 : lcor=lpawu
3954 [ # # # # : 0 : ABI_MALLOC(ind_msml,(2,-ll:ll))
# # # # #
# # # ]
3955 [ # # # # ]: 0 : ind_msml=czero
3956 : : !=====================================
3957 : : !build Zeeman angular momentum matrix along x axis
3958 : : !=====================================
3959 [ # # ]: 0 : if(option==1) then
3960 : : jc1=0
3961 [ # # ]: 0 : do ms1=1,2
3962 [ # # ]: 0 : do ml1=-ll,ll
3963 : 0 : jc1=jc1+1
3964 : 0 : ind_msml(ms1,ml1)=jc1
3965 : : end do
3966 : : end do
3967 : :
3968 : : jc1=0
3969 [ # # ]: 0 : do ms1 =-1,1
3970 : 0 : xj=float(ms1)+half
3971 [ # # ]: 0 : do ml1 = -ll,ll
3972 : 0 : jc1=jc1+1
3973 [ # # ]: 0 : if(xj < 0.0 ) then
3974 : 0 : muzeeman(iatom)%value(ind_msml(2,ml1),jc1) = 2*0.5
3975 [ # # ]: 0 : else if(xj > 0.0) then
3976 : 0 : muzeeman(iatom)%value(ind_msml(1,ml1),ind_msml(2,ml1)) = 2*0.5
3977 : : end if
3978 [ # # ]: 0 : if(jc1 == 1) then
3979 : 0 : muzeeman(iatom)%value(jc1,jc1+1) = sqrt(float((lcor*(lcor+1)) - ml1*(ml1 + 1)))*0.5
3980 : : endif
3981 [ # # # # ]: 0 : if(jc1 > 1 .and.jc1 < 2*(2*ll+1)) then
3982 : 0 : muzeeman(iatom)%value(jc1,jc1+1) = sqrt(float((lcor*(lcor+1)) - ml1*(ml1 + 1)))*0.5
3983 : 0 : muzeeman(iatom)%value(jc1,jc1-1) = sqrt(float((lcor*(lcor+1)) - ml1*(ml1 - 1)))*0.5
3984 [ # # ]: 0 : else if(jc1 == 2*(2*ll+1)) then
3985 : 0 : muzeeman(iatom)%value(jc1,jc1-1) = sqrt(float((lcor*(lcor+1)) - ml1*(ml1 - 1)))*0.5
3986 : : end if
3987 : : end do
3988 : : end do
3989 : :
3990 : : !=====================================
3991 : : !build Zeeman angular momentum matrix along y axis
3992 : : !up spin is first
3993 : : !=====================================
3994 [ # # ]: 0 : else if(option==2) then
3995 : : jc1=0
3996 [ # # ]: 0 : do ms1=1,2
3997 [ # # ]: 0 : do ml1=-ll,ll
3998 : 0 : jc1=jc1+1
3999 : 0 : ind_msml(ms1,ml1)=jc1
4000 : : end do
4001 : : end do
4002 : :
4003 : : jc1=0
4004 [ # # ]: 0 : do ms1 =-1,1
4005 : 0 : xj=float(ms1)+half
4006 [ # # ]: 0 : do ml1 = -ll,ll
4007 : 0 : jc1=jc1+1
4008 [ # # ]: 0 : if(xj < 0.0 ) then
4009 : 0 : muzeeman(iatom)%value(ind_msml(2,ml1),jc1) = 2*cmplx(zero,0.5,kind=dp)
4010 [ # # ]: 0 : else if(xj > 0.0) then
4011 : 0 : muzeeman(iatom)%value(ind_msml(1,ml1),ind_msml(2,ml1)) = 2*cmplx(zero,-0.5,kind=dp)
4012 : : end if
4013 [ # # ]: 0 : if(jc1 == 1) then
4014 : 0 : muzeeman(iatom)%value(jc1,jc1+1) = cmplx(zero,sqrt(float((lcor*(lcor+1)) - ml1*(ml1 + 1)))*0.5,kind=dp)
4015 : : endif
4016 [ # # # # ]: 0 : if(jc1 > 1 .and. jc1 < 2*(2*ll+1)) then
4017 : 0 : muzeeman(iatom)%value(jc1,jc1+1) = cmplx(zero,sqrt(float((lcor*(lcor+1)) - ml1*(ml1 + 1)))*0.5,kind=dp)
4018 : 0 : muzeeman(iatom)%value(jc1,jc1-1) = cmplx(zero,-sqrt(float((lcor*(lcor+1)) - ml1*(ml1 - 1)))*0.5,kind=dp)
4019 [ # # ]: 0 : else if(jc1== 2*(2*ll+1)) then
4020 : 0 : muzeeman(iatom)%value(jc1,jc1-1) = cmplx(zero,-sqrt(float((lcor*(lcor+1)) - ml1*(ml1 - 1)))*0.5,kind=dp)
4021 : : end if
4022 : : end do
4023 : : end do
4024 : :
4025 : :
4026 : : !=====================================
4027 : : !build Zeeman angular momentum matrix along z axis
4028 : : !up spin is first
4029 : : !=====================================
4030 [ # # ]: 0 : else if(option==3) then
4031 : : jc1=0
4032 [ # # ]: 0 : do ms1=-1,1
4033 : 0 : xj=float(ms1)+half
4034 [ # # ]: 0 : do ml1=-ll,ll
4035 : 0 : jc1=jc1+1
4036 [ # # ]: 0 : if(jc1 < tndim+1) then
4037 [ # # ]: 0 : if(xj < 0.0 ) then
4038 : 0 : muzeeman(iatom)%value(jc1,jc1) = ml1-2*xj
4039 [ # # ]: 0 : else if(xj > 0.0) then
4040 : 0 : muzeeman(iatom)%value(jc1,jc1) = ml1-2*xj
4041 : : end if
4042 : : endif
4043 : : end do
4044 : : end do
4045 : : end if
4046 : :
4047 : :
4048 [ # # ]: 0 : if(optprt>2) then
4049 : 0 : write(message,'(a,i4)') "Zeeman angular momentum matrix elements in |m_l,m_s> basis for axis", option
4050 : 0 : call wrtout(std_out,message,"COLL")
4051 [ # # ]: 0 : do im=1,2*(ll*2+1)
4052 [ # # # # ]: 0 : write(message,'(6(1x,9(1x,f4.1,",",f4.1)))') (muzeeman(iatom)%value(im,jm),jm=1,2*(ll*2+1))
4053 : 0 : call wrtout(std_out,message,"COLL")
4054 : : end do
4055 : : end if
4056 : :
4057 [ # # ]: 0 : ABI_FREE(ind_msml)
4058 : : end if !lpawu
4059 : : end do !atom
4060 : :
4061 : : !=====================================
4062 : : ! Reshape input Ylm matlu in one 14x14 matrix
4063 : : !=====================================
4064 : :
4065 : : !ABI_MALLOC(gathermatlu,(natom))
4066 : : !do iatom=1,natom
4067 : : ! if(matlu(iatom)%lpawu.ne.-1) then
4068 : : ! tndim=2*(2*matlu(iatom)%lpawu+1)
4069 : : ! ABI_MALLOC(gathermatlu(iatom)%value,(tndim,tndim))
4070 : : ! gathermatlu(iatom)%value=czero
4071 : : ! end if
4072 : : !end do
4073 : :
4074 : 0 : call gather_matlu(matlu,gathermatlu,natom,option=1,prtopt=1)
4075 : :
4076 : : !!printing for debug
4077 : : !! write(std_out,*) "gathermatlu in magmomfspin"
4078 : : !! do im1=1,tndim
4079 : : !! write(message,'(12(1x,9(1x,"(",f9.5,",",f9.5,")")))')&
4080 : : !! (gathermatlu(1)%value(im1,im2),im2=1,tndim)
4081 : : !! call wrtout(std_out,message,'coll')
4082 : : !! end do
4083 : :
4084 : : !=====================================
4085 : : ! Matrix product of Occ and muzeeman
4086 : : !=====================================
4087 [ # # ]: 0 : do iatom=1,natom
4088 [ # # ]: 0 : if(matlu(iatom)%lpawu.ne.-1) then
4089 : 0 : tndim=2*(2*matlu(iatom)%lpawu+1)
4090 [ # # # # : 0 : ABI_MALLOC(temp_mat,(tndim,tndim))
# # # # #
# # # # #
# # ]
4091 : :
4092 : : call abi_zgemm('n','n',tndim,tndim,tndim,cone,&
4093 : : & gathermatlu(iatom)%value,tndim,&
4094 : : & muzeeman(iatom)%value,tndim,czero,&
4095 : 0 : & temp_mat,tndim)
4096 : :
4097 [ # # # # : 0 : gathermatlu(iatom)%value=temp_mat
# # # # #
# # # ]
4098 [ # # ]: 0 : ABI_FREE(temp_mat)
4099 : :
4100 : : !!printing for debug
4101 : : !!write(std_out,*) "gathermatlu in magmomfspin after product"
4102 : : !!do im1=1,tndim
4103 : : !! write(message,'(12(1x,9(1x,"(",f9.5,",",f9.5,")")))')&
4104 : : !! (gathermatlu(1)%value(im1,im2),im2=1,tndim)
4105 : : !! call wrtout(std_out,message,'coll')
4106 : : !!end do
4107 : :
4108 : : !=====================================
4109 : : ! Trace of matrix product
4110 : : !=====================================
4111 : :
4112 [ # # ]: 0 : do im1=1,tndim
4113 [ # # ]: 0 : do im2=1,tndim
4114 [ # # ]: 0 : if(im1==im2) then
4115 : 0 : mu(iatom) = mu(iatom) + gathermatlu(iatom)%value(im1,im2)
4116 : : end if
4117 : : end do
4118 : : end do
4119 : :
4120 : : !=====================================
4121 : : ! Reshape product matrix into matlu format
4122 : : !=====================================
4123 : :
4124 : : !call gather_matlu(matlu,gathermatlu,natom,option=-1,prtopt=1)
4125 : :
4126 : :
4127 : : !=====================================
4128 : : ! Print matlu
4129 : : !=====================================
4130 [ # # ]: 0 : if(optprt>2) then
4131 [ # # # # : 0 : ABI_MALLOC(mat_out_c,(2*ll+1,2*ll+1))
# # # # #
# # # # #
# # # # ]
4132 : 0 : ndim = 2*ll+1
4133 [ # # ]: 0 : do isppol=1,matlu(1)%nsppol
4134 [ # # ]: 0 : do ispinor=1,matlu(1)%nspinor
4135 [ # # ]: 0 : do ispinor2=1,matlu(1)%nspinor
4136 [ # # # # ]: 0 : mat_out_c(:,:) = matlu(iatom)%mat(1+(ispinor-1)*ndim:ndim+(ispinor-1)*ndim,1+(ispinor2-1)*ndim:ndim+(ispinor2-1)*ndim,isppol)
4137 : :
4138 : 0 : write(message,'(2a, i2, a, i2, a, i2)') ch10,"Zeeman angular momentum matrix, isppol=", isppol, ", ispinor=",&
4139 : 0 : & ispinor,", ispinor2=", ispinor2
4140 : 0 : call wrtout(std_out,message,'COLL')
4141 [ # # ]: 0 : do im1=1,ll*2+1
4142 : : write(message,'(12(1x,9(1x,"(",f9.5,",",f9.5,")")))')&
4143 : 0 : & (mat_out_c(im1,im2),im2=1,ll*2+1)
4144 : 0 : call wrtout(std_out,message,'COLL')
4145 : : end do
4146 : :
4147 : : end do ! im
4148 : : end do ! ispinor
4149 : : end do ! isppol
4150 [ # # ]: 0 : ABI_FREE(mat_out_c)
4151 : : endif ! optprt
4152 : :
4153 : : end if !lpawu
4154 : : end do !atom
4155 : :
4156 : : !=====================================
4157 : : ! Deallocate gathermatlu
4158 : : !=====================================
4159 : :
4160 [ # # ]: 0 : do iatom=1,natom
4161 [ # # ]: 0 : if(matlu(iatom)%lpawu.ne.-1) then
4162 [ # # ]: 0 : ABI_FREE(gathermatlu(iatom)%value)
4163 [ # # ]: 0 : ABI_FREE(muzeeman(iatom)%value)
4164 : : end if
4165 : : end do
4166 [ # # # # : 0 : ABI_FREE(gathermatlu)
# # # # ]
4167 [ # # # # : 0 : ABI_FREE(muzeeman)
# # # # ]
4168 : 0 : end subroutine magmomfzeeman_matlu
4169 : :
4170 : : !!***
4171 : :
4172 : : !!***
4173 : : !!****f* m_matlu/chi_matlu
4174 : : !! NAME
4175 : : !! chi_matlu
4176 : : !!
4177 : : !! FUNCTION
4178 : : !! return the matrix of dimension [(2*ll+1)]**4 in the Ylm basis
4179 : : !! with the matrix elements of the orbital (option=1), spin (option=2) and
4180 : : !! total (option=3) angular momentum for z direction. It is used by the
4181 : : !! QMC for the correlation function of the magnetic moment
4182 : : !!
4183 : : !!
4184 : : !! COPYRIGHT
4185 : : !! Copyright (C) 2005-2026 ABINIT group (FGendron)
4186 : : !! This file is distributed under the terms of the
4187 : : !! GNU General Public License, see ~abinit/COPYING
4188 : : !! or http://www.gnu.org/copyleft/gpl.txt .
4189 : : !!
4190 : : !! INPUTS
4191 : : !! matlu1(natom)%(nsppol,nspinor,nspinor,ndim,ndim) ::
4192 : : !! natom :: number of atoms
4193 : : !! option = 1 :: Orbital angular momentum along z axis
4194 : : !! = 2 :: 2*Spin angluar momentum alonf z axis
4195 : : !! = 3 :: total angular momentum along z axis
4196 : : !! optptr > 2 :: print angular matrix elements
4197 : : !!
4198 : : !! OUTPUT
4199 : : !! matlu(natom)%(nsppol,nspinor,nspinor,ndim,ndim) :: quantity in Ylm basis
4200 : : !!
4201 : : !! SIDE EFFECTS
4202 : : !!
4203 : : !! NOTES
4204 : : !!
4205 : : !! SOURCE
4206 : 0 : subroutine chi_matlu(matlu,natom,option,optprt)
4207 : : use defs_wvltypes
4208 : :
4209 : : !Arguments ------------------------------------
4210 : : !scalars
4211 : : integer, intent(in) :: natom,option,optprt
4212 : : !arrays
4213 : : type(matlu_type), intent(inout) :: matlu(natom)
4214 : : !Local variables-------------------------------
4215 : : !scalars
4216 : : integer :: iatom,im
4217 : : integer :: lpawu,ll,jm,ml1,jc1,ms1,lcor,tndim
4218 : : character(len=500) :: message
4219 : : real(dp) :: xj
4220 : : !arrays
4221 : 0 : integer, allocatable :: ind_msml(:,:)
4222 : : ! type(coeff2c_type), allocatable :: gathermatlu(:)
4223 : 0 : type(coeff2c_type), allocatable :: muchi(:)
4224 : : !************************************************************************
4225 : :
4226 : : !=====================================
4227 : : ! Allocate matrices
4228 : : !=====================================
4229 : :
4230 [ # # # # : 0 : ABI_MALLOC(muchi,(natom))
# # # # #
# # # #
# ]
4231 [ # # ]: 0 : do iatom=1,natom
4232 : : !if(matlu(iatom)%lpawu.ne.-1) then
4233 : 0 : tndim=2*(2*matlu(iatom)%lpawu+1)
4234 [ # # # # : 0 : ABI_MALLOC(muchi(iatom)%value,(tndim,tndim))
# # # # #
# # # # #
# # # # ]
4235 [ # # # # ]: 0 : muchi(iatom)%value=czero
4236 : : !end if
4237 : : end do
4238 : :
4239 [ # # ]: 0 : do iatom=1,natom
4240 : 0 : lpawu=matlu(iatom)%lpawu
4241 [ # # ]: 0 : if(lpawu.ne.-1) then
4242 : 0 : ll=lpawu
4243 : 0 : lcor=lpawu
4244 [ # # # # : 0 : ABI_MALLOC(ind_msml,(2,-ll:ll))
# # # # #
# # # ]
4245 [ # # # # ]: 0 : ind_msml=czero
4246 : : !=====================================
4247 : : !Orbital angular momentum matrix along z axis
4248 : : !=====================================
4249 [ # # ]: 0 : if(option==1) then
4250 : : jc1=0
4251 [ # # ]: 0 : do ms1=1,2
4252 [ # # ]: 0 : do ml1=-ll,ll
4253 : 0 : jc1=jc1+1
4254 : 0 : ind_msml(ms1,ml1)=jc1
4255 : : end do
4256 : : end do
4257 : :
4258 : : jc1=0
4259 [ # # ]: 0 : do ms1=-1,1
4260 [ # # ]: 0 : do ml1=-ll,ll
4261 : 0 : jc1=jc1+1
4262 [ # # ]: 0 : if(jc1 <tndim+1) then
4263 : 0 : muchi(iatom)%value(jc1,jc1) = ml1
4264 : : endif
4265 : : end do
4266 : : end do
4267 : :
4268 : : !=====================================
4269 : : !Spin angular momentum matrix along z axis
4270 : : !up spin is first
4271 : : !=====================================
4272 [ # # ]: 0 : else if(option==2) then
4273 : : jc1=0
4274 [ # # ]: 0 : do ms1=1,2
4275 [ # # ]: 0 : do ml1=-ll,ll
4276 : 0 : jc1=jc1+1
4277 : 0 : ind_msml(ms1,ml1)=jc1
4278 : : end do
4279 : : end do
4280 : :
4281 : : jc1=0
4282 [ # # ]: 0 : do ms1=-1,1
4283 : 0 : xj=float(ms1)+half
4284 [ # # ]: 0 : do ml1=-ll,ll
4285 : 0 : jc1=jc1+1
4286 [ # # ]: 0 : if(jc1<tndim+1) then
4287 [ # # ]: 0 : if(xj < 0.0 ) then
4288 : 0 : muchi(iatom)%value(jc1,jc1) = -2*xj
4289 [ # # ]: 0 : else if(xj > 0.0) then
4290 : 0 : muchi(iatom)%value(jc1,jc1) = -2*xj
4291 : :
4292 : : end if
4293 : : endif
4294 : : end do
4295 : : end do
4296 : :
4297 : : !=====================================
4298 : : !Total angular momentum matrix along z axis
4299 : : !up spin is first
4300 : : !=====================================
4301 [ # # ]: 0 : else if(option==3) then
4302 : : jc1=0
4303 [ # # ]: 0 : do ms1=-1,1
4304 : 0 : xj=float(ms1)+half
4305 [ # # ]: 0 : do ml1=-ll,ll
4306 : 0 : jc1=jc1+1
4307 [ # # ]: 0 : if(jc1<tndim+1) then
4308 [ # # ]: 0 : if(xj < 0.0 ) then
4309 : 0 : muchi(iatom)%value(jc1,jc1) = ml1-2*xj
4310 [ # # ]: 0 : else if(xj > 0.0) then
4311 : 0 : muchi(iatom)%value(jc1,jc1) = ml1-2*xj
4312 : : end if
4313 : : endif
4314 : : end do
4315 : : end do
4316 : : end if
4317 : :
4318 [ # # ]: 0 : if(optprt>2) then
4319 [ # # ]: 0 : if(option==1) then
4320 : 0 : write(message,'(a)') "Orbital angular momentum matrix elements in |m_l,m_s> basis"
4321 [ # # ]: 0 : else if(option==2) then
4322 : 0 : write(message,'(a)') "Spin angular momentum matrix elements in |m_l,m_s> basis"
4323 [ # # ]: 0 : else if(option==3) then
4324 : 0 : write(message,'(a)') "Zeeman angular momentum matrix elements in |m_l,m_s> basis"
4325 : : end if
4326 : 0 : call wrtout(std_out,message,"COLL")
4327 [ # # ]: 0 : do im=1,2*(ll*2+1)
4328 [ # # # # ]: 0 : write(message,'(6(1x,9(1x,f4.1,",",f4.1)))') (muchi(iatom)%value(im,jm),jm=1,2*(ll*2+1))
4329 : 0 : call wrtout(std_out,message,"COLL")
4330 : : end do
4331 : : end if
4332 : :
4333 [ # # ]: 0 : ABI_FREE(ind_msml)
4334 : :
4335 : : !=====================================
4336 : : ! Reshape matrix into matlu format
4337 : : !=====================================
4338 : :
4339 : : ! call gather_matlu(matlu,muchi(iatom),natom=1,option=-1,prtopt=1)
4340 : :
4341 : :
4342 : : end if !lpawu
4343 : : end do !atom
4344 : :
4345 : : !=====================================
4346 : : ! Reshape matrix into matlu format
4347 : : !=====================================
4348 : :
4349 : 0 : call gather_matlu(matlu,muchi,natom,option=-1,prtopt=1)
4350 : :
4351 : : !=====================================
4352 : : ! Deallocate gathermatlu
4353 : : !=====================================
4354 : :
4355 [ # # ]: 0 : do iatom=1,natom
4356 [ # # ]: 0 : if(matlu(iatom)%lpawu.ne.-1) then
4357 [ # # ]: 0 : ABI_FREE(muchi(iatom)%value)
4358 : : end if
4359 : : end do
4360 [ # # # # : 0 : ABI_FREE(muchi)
# # # # ]
4361 : :
4362 : 0 : end subroutine chi_matlu
4363 : :
4364 : : !!***
4365 : :
4366 : : !!****f* m_matlu/trace_prod_matlu
4367 : : !! NAME
4368 : : !! trace_prod_matlu
4369 : : !!
4370 : : !! FUNCTION
4371 : : !! Computes Tr(matlu1*matlu2) for each atom. It is NOT assumed
4372 : : !! that either matlu1 or matlu2 is symmetric, so this routine is
4373 : : !! suboptimal if this is the case.
4374 : : !!
4375 : : !! COPYRIGHT
4376 : : !! Copyright (C) 2005-2026 ABINIT group (BAmadon)
4377 : : !! This file is distributed under the terms of the
4378 : : !! GNU General Public License, see ~abinit/COPYING
4379 : : !! or http://www.gnu.org/copyleft/gpl.txt .
4380 : : !!
4381 : : !! INPUTS
4382 : : !! matlu1(natom),matlu2(natom) :: input quantity
4383 : : !! natom=number of atoms in cell.
4384 : : !! opt_add = if present, add the result to trace
4385 : : !! trace_tot = if present, computes the trace over all atoms
4386 : : !! iatom = if present, only computes the contribution of iatom
4387 : : !! if <=0, add all contributions as usual
4388 : : !!
4389 : : !! OUTPUT
4390 : : !! trace(natom) :: Tr(matlu1*matlu2) for each atom
4391 : : !!
4392 : : !! SIDE EFFECTS
4393 : : !!
4394 : : !! NOTES
4395 : : !!
4396 : : !! SOURCE
4397 : :
4398 : 8138 : subroutine trace_prod_matlu(matlu1,matlu2,natom,trace,trace_tot,iatom)
4399 : :
4400 : : !Arguments ------------------------------------
4401 : : integer, intent(in) :: natom
4402 : : type(matlu_type), intent(in) :: matlu1(natom),matlu2(natom)
4403 : : complex(dp), intent(inout) :: trace(natom)
4404 : : complex(dp), optional, intent(out) :: trace_tot
4405 : : integer, optional, intent(in) :: iatom
4406 : : !Local variables-------------------------------
4407 : : integer :: ia1,ia2,iatom_,isppol,lpawu,nspinor,nsppol
4408 : : !************************************************************************
4409 : :
4410 : 8138 : nspinor = matlu1(1)%nspinor
4411 : 8138 : nsppol = matlu1(1)%nsppol
4412 : :
4413 [ + + ]: 24172 : trace(:) = czero
4414 : :
4415 : 8138 : ia1 = 1 ; ia2 = natom
4416 [ + + ]: 8138 : if (present(iatom)) then
4417 [ + - ]: 8032 : if (iatom > 0) then
4418 : 8138 : ia1 = iatom ; ia2 = iatom
4419 : : end if
4420 : : end if ! present(iatom)
4421 : :
4422 [ + + ]: 24172 : do iatom_=ia1,ia2
4423 : 16034 : lpawu = matlu1(iatom_)%lpawu
4424 [ + + ]: 16034 : if (lpawu == -1) cycle
4425 [ + + ]: 23662 : do isppol=1,nsppol
4426 [ + + + + ]: 495878 : trace(iatom_) = trace(iatom_) + sum(matlu1(iatom_)%mat(:,:,isppol)*transpose(matlu2(iatom_)%mat(:,:,isppol)))
4427 : : end do ! isppol
4428 [ + + ]: 16684 : if (nsppol == 1 .and. nspinor == 1) trace(iatom_) = trace(iatom_) * two
4429 : : end do ! iatom
4430 : :
4431 [ - + - - ]: 8138 : if (present(trace_tot)) trace_tot = sum(trace(:))
4432 : :
4433 : 8138 : end subroutine trace_prod_matlu
4434 : : !!***
4435 : :
4436 : : !!****f* m_matlu/xmpi_matlu
4437 : : !! NAME
4438 : : !! xmpi_sum_matlu
4439 : : !!
4440 : : !! FUNCTION
4441 : : !! Put matlu into a buffer and perform the required MPI operation
4442 : : !! (xmpi_sum or xmpi_bcast) on the input communicator.
4443 : : !!
4444 : : !! INPUTS
4445 : : !! matlu <type(matlu_type)>= density matrix in the local orbital basis and related variables
4446 : : !! natom = number of atoms
4447 : : !! comm = communicator on which to perform the required communication
4448 : : !! master = master node (only used in the case of xmpi_bcast, default is 0)
4449 : : !! option = 1 (default) : xmpi_sum
4450 : : !! = 2 : xmpi_bcast
4451 : : !!
4452 : : !! OUTPUT
4453 : : !!
4454 : : !! SOURCE
4455 : :
4456 : 2134 : subroutine xmpi_matlu(matlu,natom,comm,master,option)
4457 : :
4458 : : !Arguments ------------------------------------
4459 : : integer, intent(in) :: comm,natom
4460 : : type(matlu_type), intent(inout) :: matlu(natom)
4461 : : integer, optional, intent(in) :: master,option
4462 : : !Local variables-------------------------------
4463 : : integer :: iatom,ibuf,im1,ierr,isppol,lpawu
4464 : : integer :: master_node,ndim,nspinor,nsppol,opt,siz_buf
4465 : 2134 : complex(dp), allocatable :: buffer(:)
4466 : : !************************************************************************
4467 : :
4468 : 2134 : nspinor = matlu(1)%nspinor
4469 : 2134 : nsppol = matlu(1)%nsppol
4470 : 2134 : opt = 1
4471 [ + + ]: 2134 : if (present(option)) opt = option
4472 : 2134 : master_node = 0
4473 [ + + ]: 2134 : if (present(master)) master_node = master
4474 : :
4475 : 2134 : siz_buf = 0
4476 [ + + ]: 9549 : do iatom=1,natom
4477 : 7415 : lpawu = matlu(iatom)%lpawu
4478 [ + + ]: 7415 : if (lpawu == -1) cycle
4479 : 9549 : siz_buf = siz_buf + (2*lpawu+1)**2
4480 : : end do ! iatom
4481 : :
4482 : 2134 : siz_buf = siz_buf * (nspinor**2) * nsppol
4483 : :
4484 [ - + + - : 6402 : ABI_MALLOC(buffer,(siz_buf))
+ - + - -
+ - + ]
4485 : :
4486 : 2134 : ibuf = 0
4487 [ + + ]: 9549 : do iatom=1,natom
4488 : 7415 : lpawu = matlu(iatom)%lpawu
4489 [ + + ]: 7415 : if (lpawu == -1) cycle
4490 : 2482 : ndim = nspinor * (2*lpawu+1)
4491 [ + + ]: 8345 : do isppol=1,nsppol
4492 [ + + ]: 28466 : do im1=1,ndim
4493 [ + + ]: 106114 : buffer(ibuf+1:ibuf+ndim) = matlu(iatom)%mat(:,im1,isppol)
4494 : 21051 : ibuf = ibuf + ndim
4495 : : end do ! im1
4496 : : end do ! isppol
4497 : : end do ! iatom
4498 : :
4499 [ + + ]: 2134 : if (opt == 1) then
4500 : 2096 : call xmpi_sum(buffer(:),comm,ierr)
4501 [ + - ]: 38 : else if (opt == 2) then
4502 : 38 : call xmpi_bcast(buffer(:),master_node,comm,ierr)
4503 : : end if ! opt
4504 : :
4505 : : ibuf = 0
4506 [ + + ]: 9549 : do iatom=1,natom
4507 : 7415 : lpawu = matlu(iatom)%lpawu
4508 [ + + ]: 7415 : if (lpawu == -1) cycle
4509 : 2482 : ndim = nspinor * (2*lpawu+1)
4510 [ + + ]: 8345 : do isppol=1,nsppol
4511 [ + + ]: 28466 : do im1=1,ndim
4512 [ + + ]: 106114 : matlu(iatom)%mat(:,im1,isppol) = buffer(ibuf+1:ibuf+ndim)
4513 : 21051 : ibuf = ibuf + ndim
4514 : : end do ! im1
4515 : : end do ! isppol
4516 : : end do ! iatom
4517 : :
4518 [ - + ]: 2134 : ABI_FREE(buffer)
4519 : :
4520 : 2134 : end subroutine xmpi_matlu
4521 : : !!***
4522 : :
4523 : : !!****f* m_matlu/symmetrize_matlu
4524 : : !! NAME
4525 : : !! symmetrize_matlu
4526 : : !!
4527 : : !! FUNCTION
4528 : : !! Symmetrizes matlu (A = (A+A^T)/2
4529 : : !!
4530 : : !! INPUTS
4531 : : !! matlu <type(matlu_type)>= density matrix in the local orbital basis and related variables
4532 : : !! natom = number of atoms
4533 : : !!
4534 : : !! OUTPUT
4535 : : !! err = difference between A and symmetrized A
4536 : : !!
4537 : : !! SOURCE
4538 : :
4539 : 0 : subroutine symmetrize_matlu(matlu,natom,err)
4540 : :
4541 : : !Arguments ------------------------------------
4542 : : integer, intent(in) :: natom
4543 : : type(matlu_type), intent(inout) :: matlu(natom)
4544 : : real(dp), optional, intent(out) :: err
4545 : : !Local variables-------------------------------
4546 : : integer :: iatom,isppol,lpawu,nspinor,nsppol,tndim
4547 : : real(dp) :: err_
4548 : 0 : complex(dp), allocatable :: mat_tmp(:,:)
4549 : : !************************************************************************
4550 : :
4551 : 0 : nspinor = matlu(1)%nspinor
4552 : 0 : nsppol = matlu(1)%nsppol
4553 : :
4554 [ # # ]: 0 : if (present(err)) err = zero
4555 : :
4556 [ # # ]: 0 : do iatom=1,natom
4557 : 0 : lpawu = matlu(iatom)%lpawu
4558 [ # # ]: 0 : if (lpawu == -1) cycle
4559 : 0 : tndim = nspinor * (2*lpawu+1)
4560 [ # # # # : 0 : ABI_MALLOC(mat_tmp,(tndim,tndim))
# # # # #
# # # # #
# # ]
4561 [ # # ]: 0 : do isppol=1,nsppol
4562 : : mat_tmp(:,:) = half * (matlu(iatom)%mat(:,:,isppol)+ &
4563 [ # # # # ]: 0 : & transpose(matlu(iatom)%mat(:,:,isppol)))
4564 [ # # ]: 0 : if (present(err)) then
4565 [ # # # # ]: 0 : err_ = sum(abs(mat_tmp(:,:)-matlu(iatom)%mat(:,:,isppol)))
4566 [ # # ]: 0 : if (err_ > err) err = err_
4567 : : end if ! present(err)
4568 [ # # # # ]: 0 : matlu(iatom)%mat(:,:,isppol) = mat_tmp(:,:)
4569 : : end do ! isppol
4570 [ # # ]: 0 : ABI_FREE(mat_tmp)
4571 : : end do ! iatom
4572 : :
4573 : 0 : end subroutine symmetrize_matlu
4574 : : !!***
4575 : :
4576 : : !!****f* m_matlu/ylm2jmj_matlu
4577 : : !! NAME
4578 : : !! ylm2jmj_matlu
4579 : : !!
4580 : : !! FUNCTION
4581 : : !! Transform mat from Ylm to JmJ basis or vice versa
4582 : : !!
4583 : : !! COPYRIGHT
4584 : : !! Copyright (C) 2005-2026 ABINIT group (BAmadon)
4585 : : !! This file is distributed under the terms of the
4586 : : !! GNU General Public License, see ~abinit/COPYING
4587 : : !! or http://www.gnu.org/copyleft/gpl.txt .
4588 : : !!
4589 : : !! INPUTS
4590 : : !! matlu(natom) :: input quantity
4591 : : !! natom :: number of atoms
4592 : : !! option=1 go from Ylm to JmJ basis
4593 : : !! option=2 go from JmJ to Ylm basis
4594 : : !! paw_dmft <type(paw_dmft_type)>= paw+dmft related data
4595 : : !! SIDE EFFECTS
4596 : : !!
4597 : : !! NOTES
4598 : : !!
4599 : : !! SOURCE
4600 : :
4601 : 0 : subroutine ylm2jmj_matlu(matlu,natom,option,paw_dmft)
4602 : :
4603 : : !Arguments ------------------------------------
4604 : : integer, intent(in) :: natom,option
4605 : : type(matlu_type), intent(inout) :: matlu(natom)
4606 : : type(paw_dmft_type), intent(in) :: paw_dmft
4607 : : !Local variables-------------------------------
4608 : : integer :: iatom,lpawu,nspinor,tndim,tndim_max
4609 : 0 : complex(dp), allocatable :: mat_tmp(:,:)
4610 : : character(len=1) :: c1,c2
4611 : : !************************************************************************
4612 : :
4613 : 0 : nspinor = paw_dmft%nspinor
4614 [ # # ]: 0 : if (nspinor == 1) ABI_BUG("nspinor should be equal to 2")
4615 : :
4616 : 0 : tndim_max = nspinor * (2*paw_dmft%maxlpawu+1)
4617 : :
4618 [ # # ]: 0 : if (option == 1) then
4619 : 0 : c1 = "c" ; c2 = "n"
4620 : : else
4621 : 0 : c1 = "n" ; c2 = "c"
4622 : : end if
4623 : :
4624 [ # # # # : 0 : ABI_MALLOC(mat_tmp,(tndim_max,tndim_max))
# # # # #
# # # # #
# # ]
4625 : :
4626 [ # # ]: 0 : do iatom=1,natom
4627 : 0 : lpawu = paw_dmft%lpawu(iatom)
4628 [ # # ]: 0 : if (lpawu == -1) cycle
4629 [ # # ]: 0 : if (lpawu == 0) ABI_BUG("l should not be equal to 0")
4630 : 0 : tndim = nspinor * (2*lpawu+1)
4631 : :
4632 : : call abi_xgemm("n",c2,tndim,tndim,tndim,cone,matlu(iatom)%mat(:,:,1),tndim, &
4633 : 0 : & paw_dmft%jmj2ylm(:,1:tndim,lpawu+1),tndim_max,czero,mat_tmp(:,1:tndim),tndim_max)
4634 : :
4635 : : call abi_xgemm(c1,"n",tndim,tndim,tndim,cone,paw_dmft%jmj2ylm(:,1:tndim,lpawu+1), &
4636 : 0 : & tndim_max,mat_tmp(:,1:tndim),tndim_max,czero,matlu(iatom)%mat(:,:,1),tndim)
4637 : :
4638 : : end do ! iatom
4639 : :
4640 [ # # ]: 0 : ABI_FREE(mat_tmp)
4641 : :
4642 : 0 : end subroutine ylm2jmj_matlu
4643 : : !!***
4644 : :
4645 : : !!***
4646 : : !!****f* m_matlu/magnfield_matlu
4647 : : !! NAME
4648 : : !! magnfield_matlu
4649 : : !!
4650 : : !! FUNCTION
4651 : : !! return the matrix of magnetic moment mz times Bz
4652 : : !!
4653 : : !!
4654 : : !! COPYRIGHT
4655 : : !! Copyright (C) 2005-2026 ABINIT group (FGendron)
4656 : : !! This file is distributed under the terms of the
4657 : : !! GNU General Public License, see ~abinit/COPYING
4658 : : !! or http://www.gnu.org/copyleft/gpl.txt .
4659 : : !!
4660 : : !! INPUTS
4661 : : !! matlu1(natom)%(nsppol,nspinor,nspinor,ndim,ndim) :: input quantity in Ylm basis
4662 : : !! natom :: number of atoms
4663 : : !! bfield :: value of magnetic field in Tesla
4664 : : !! option = 1 :: scalar spin angular momentum along z axis
4665 : : !! option = 2 :: SOC total angular momentum (L+2S) along z axis
4666 : : !!
4667 : : !! OUTPUT
4668 : : !! matlu(natom)%(nsppol,nspinor,nspinor,ndim,ndim) :: product
4669 : : !!
4670 : : !! SIDE EFFECTS
4671 : : !!
4672 : : !! NOTES
4673 : : !!
4674 : : !! SOURCE
4675 : 8 : subroutine magnfield_matlu(matlu,natom,bfield,option)
4676 : : use defs_basis
4677 : : use defs_wvltypes
4678 : : implicit none
4679 : :
4680 : : !Arguments ------------------------------------
4681 : : !scalars
4682 : : integer, intent(in) :: natom,option
4683 : : real(dp) :: bfield
4684 : : !arrays
4685 : : type(matlu_type), intent(inout) :: matlu(natom)
4686 : : !Local variables-------------------------------
4687 : : !scalars
4688 : : integer :: iatom,im,ndim,isppol
4689 : : integer :: ll,ml1,jc1,ms1,tndim
4690 : : real(dp) :: xj
4691 : : !arrays
4692 : 8 : type(coeff2c_type), allocatable :: magnmatb(:)
4693 : : !************************************************************************
4694 : :
4695 : : !================================
4696 : : ! Allocate matrices
4697 : : !================================
4698 : :
4699 [ - + + - : 32 : ABI_MALLOC(magnmatb,(natom))
+ - + - -
+ - + +
+ ]
4700 [ + + ]: 16 : do iatom=1,natom
4701 [ + - ]: 16 : if(matlu(iatom)%lpawu .ne. -1) then
4702 : 8 : tndim=2*(2*matlu(iatom)%lpawu+1)
4703 [ - + + - : 32 : ABI_MALLOC(magnmatb(iatom)%value,(tndim,tndim))
- + + - +
- + - - +
- + - + ]
4704 [ + + + + ]: 888 : magnmatb(iatom)%value=czero
4705 : : endif
4706 : : enddo
4707 : :
4708 [ + - ]: 8 : if(option .eq. 1) then
4709 : :
4710 : : !================================
4711 : : ! Scalar magnetism (Spin only case)
4712 : : ! H = mu_B*g_e*S_Z*B_z
4713 : : !================================
4714 : :
4715 [ + + ]: 16 : do iatom=1,natom
4716 [ + - ]: 16 : if(matlu(iatom)%lpawu .ne. -1) then
4717 : 8 : ndim=2*matlu(iatom)%lpawu+1
4718 [ + + ]: 24 : do isppol=1,matlu(iatom)%nsppol
4719 [ + + ]: 104 : do im=1,ndim
4720 [ + + ]: 96 : if (isppol .eq. 1) then
4721 : 40 : matlu(iatom)%mat(im,im,isppol) = half*bfield
4722 : : else
4723 : 40 : matlu(iatom)%mat(im,im,isppol) = -half*bfield
4724 : : endif
4725 : : enddo ! im
4726 : : enddo ! isppol
4727 : : endif ! lpawu
4728 : : enddo ! natom
4729 : :
4730 : :
4731 [ # # ]: 0 : elseif(option .eq. 2) then
4732 : :
4733 : : !================================
4734 : : ! Spin-orbit magnetism
4735 : : ! H = mu_B*(L_z+g_e*S_Z)*B_z
4736 : : !================================
4737 : :
4738 [ # # ]: 0 : do iatom=1,natom
4739 [ # # ]: 0 : if(matlu(iatom)%lpawu .ne. -1) then
4740 : 0 : tndim=2*(2*matlu(iatom)%lpawu+1)
4741 : 0 : ll=matlu(iatom)%lpawu
4742 : :
4743 : 0 : jc1=0
4744 [ # # ]: 0 : do ms1=-1,1
4745 : 0 : xj=float(ms1)+half
4746 [ # # ]: 0 : do ml1=-ll,ll
4747 : 0 : jc1=jc1+1
4748 [ # # ]: 0 : if(jc1 < tndim+1) then
4749 [ # # ]: 0 : if (xj < 0.0) then
4750 : 0 : magnmatb(iatom)%value(jc1,jc1) = half*(ml1-2*xj)*bfield
4751 [ # # ]: 0 : elseif(xj > 0.0) then
4752 : 0 : magnmatb(iatom)%value(jc1,jc1) = half*(ml1-2*xj)*bfield
4753 : : endif
4754 : : endif
4755 : : enddo !ml1
4756 : : enddo ! ms1
4757 : : endif !lpawu
4758 : : enddo !natom
4759 : : endif !option
4760 : :
4761 : : !=======================
4762 : : ! reshape matrix
4763 : : !=======================
4764 : :
4765 [ - + ]: 8 : if(option .eq. 2) then
4766 : 0 : call gather_matlu(matlu,magnmatb(natom),natom,option=-1,prtopt=1)
4767 : : endif
4768 : :
4769 : : !================================
4770 : : ! Deallocate matrices
4771 : : !================================
4772 : :
4773 [ + + ]: 16 : do iatom=1,natom
4774 [ + - ]: 16 : if(matlu(iatom)%lpawu .ne. -1) then
4775 [ - + ]: 8 : ABI_FREE(magnmatb(iatom)%value)
4776 : : endif
4777 : : enddo
4778 : :
4779 [ + - + + : 16 : ABI_FREE(magnmatb)
- + - + ]
4780 : :
4781 : 8 : end subroutine magnfield_matlu
4782 : : !!***
4783 : :
4784 : :
4785 : : !!****f* m_matlu/magmomjmj_matlu
4786 : : !! NAME
4787 : : !! magmomjmj_matlu
4788 : : !!
4789 : : !! FUNCTION
4790 : : !! return the matrix of magnetic moments in the Jmj basis
4791 : : !!
4792 : : !!
4793 : : !! COPYRIGHT
4794 : : !! Copyright (C) 2005-2026 ABINIT group (FGendron)
4795 : : !! This file is distributed under the terms of the
4796 : : !! GNU General Public License, see ~abinit/COPYING
4797 : : !! or http://www.gnu.org/copyleft/gpl.txt .
4798 : : !!
4799 : : !! INPUTS
4800 : : !!
4801 : : !! OUTPUT
4802 : : !!
4803 : : !! SIDE EFFECTS
4804 : : !!
4805 : : !! NOTES
4806 : : !!
4807 : : !! SOURCE
4808 : 0 : subroutine magmomjmj_matlu(matlu,natom)
4809 : : use defs_basis
4810 : : use defs_wvltypes
4811 : : implicit none
4812 : :
4813 : : !Arguments ------------------------------------
4814 : : !scalars
4815 : : integer, intent(in) :: natom
4816 : : !arrays
4817 : : type(matlu_type), intent(inout) :: matlu(natom)
4818 : : !Local variables-------------------------------
4819 : : !scalars
4820 : : integer :: iatom,lpawu,ll,ml1,ms1,jm,jc1,tndim,jj
4821 : : real(dp) :: xj,xmj
4822 : : !arrays
4823 : 0 : integer, allocatable :: ind_msml(:,:)
4824 : 0 : type(coeff2c_type), allocatable :: gathermatlu(:)
4825 : 0 : complex(dpc),allocatable :: mlms2jmj(:,:)
4826 : : !************************************************************************
4827 : :
4828 : : !=====================================
4829 : : ! Allocate Matrices
4830 : : !=====================================
4831 : :
4832 [ # # # # : 0 : ABI_MALLOC(gathermatlu,(natom))
# # # # #
# # # #
# ]
4833 : :
4834 [ # # ]: 0 : do iatom=1,natom
4835 : 0 : lpawu=matlu(iatom)%lpawu
4836 [ # # ]: 0 : if(lpawu.ne.-1) then
4837 : 0 : ll=lpawu
4838 : 0 : tndim=2*(2*ll+1)
4839 : :
4840 [ # # # # : 0 : ABI_MALLOC(gathermatlu(iatom)%value,(tndim,tndim))
# # # # #
# # # # #
# # # # ]
4841 [ # # # # ]: 0 : gathermatlu(iatom)%value=czero
4842 [ # # # # : 0 : ABI_MALLOC(mlms2jmj,(tndim,tndim))
# # # # #
# # # #
# ]
4843 [ # # # # ]: 0 : mlms2jmj=czero
4844 [ # # # # : 0 : ABI_MALLOC(ind_msml,(2,-ll:ll))
# # # # #
# # # #
# ]
4845 [ # # # # ]: 0 : mlms2jmj=czero
4846 : :
4847 : : !=====================================
4848 : : ! Build J,M_J matrix
4849 : : !=====================================
4850 : :
4851 : : jc1=0
4852 [ # # ]: 0 : do ms1=1,2
4853 [ # # ]: 0 : do ml1=-ll,ll
4854 : 0 : jc1=jc1+1
4855 : 0 : ind_msml(ms1,ml1)=jc1
4856 : : end do
4857 : : end do
4858 : :
4859 : 0 : jc1=0
4860 [ # # ]: 0 : do jj=ll,ll+1
4861 : 0 : xj=float(jj)-half ! xj is in {ll-0.5, ll+0.5}
4862 [ # # ]: 0 : do jm=-jj,jj-1
4863 : 0 : xmj=float(jm)+half ! xmj is in {-xj,xj}
4864 : 0 : jc1=jc1+1 ! Global index for JMJ
4865 [ # # ]: 0 : if(nint(xj+0.5)==ll+1) then ! if xj=ll+0.5
4866 : 0 : mlms2jmj(jc1,jc1)=xmj ! J=L+0.5 and m_J=L+0.5
4867 [ # # ]: 0 : else if(nint(xj-0.5)==ll-1) then
4868 : 0 : mlms2jmj(jc1,jc1)=xmj ! J=L+0.5 and m_J=-L-0.5
4869 : : end if
4870 : : end do
4871 : : end do
4872 : :
4873 : : !print to debug
4874 : : !write(message,'(3a)') ch10,"JMJ Matrix"
4875 : : !call wrtout(std_out,message,"COLL")
4876 : : !do im=1,2*(ll*2+1)
4877 : : ! write(message,'(12(1x,18(1x,f5.2,f5.2)))') (mlms2jmj(im,jm),jm=1,2*(ll*2+1))
4878 : : ! call wrtout(std_out,message,"COLL")
4879 : : !end do
4880 : :
4881 : : !=====================================
4882 : : ! Put back into matlu format
4883 : : !=====================================
4884 : :
4885 [ # # # # : 0 : gathermatlu(iatom)%value=mlms2jmj
# # # # #
# # # ]
4886 : :
4887 : 0 : call gather_matlu(matlu,gathermatlu(iatom),natom=1,option=-1,prtopt=0)
4888 : :
4889 : : !=====================================
4890 : : ! Deallocate Matrices
4891 : : !=====================================
4892 : :
4893 [ # # ]: 0 : ABI_FREE(gathermatlu(iatom)%value)
4894 : : end if !lpawu
4895 : : end do !natom
4896 : :
4897 [ # # ]: 0 : ABI_FREE(mlms2jmj)
4898 [ # # ]: 0 : ABI_FREE(ind_msml)
4899 [ # # # # : 0 : ABI_FREE(gathermatlu)
# # # # ]
4900 : :
4901 : 0 : end subroutine magmomjmj_matlu
4902 : :
4903 : :
4904 [ # # # # : 0 : END MODULE m_matlu
# # # # #
# # # ]
4905 : : !!***
|