Branch data Line data Source code
1 : : !!****m* ABINIT/m_spin_current
2 : : !! NAME
3 : : !! m_spin_current
4 : : !!
5 : : !! FUNCTION
6 : : !!
7 : : !!
8 : : !! COPYRIGHT
9 : : !! Copyright (C) 2005-2026 ABINIT group (Mver)
10 : : !! This file is distributed under the terms of the
11 : : !! GNU General Public License, see ~abinit/COPYING
12 : : !! or http://www.gnu.org/copyleft/gpl.txt .
13 : : !!
14 : : !! SOURCE
15 : :
16 : : #if defined HAVE_CONFIG_H
17 : : #include "config.h"
18 : : #endif
19 : :
20 : : #include "abi_common.h"
21 : :
22 : : module m_spin_current
23 : :
24 : : use m_errors
25 : : use m_abicore
26 : : use m_splines
27 : : use m_hdr
28 : : use m_dtset
29 : : use m_dtfil
30 : :
31 : : use defs_datatypes, only : pseudopotential_type
32 : : use defs_abitypes, only : MPI_type
33 : : use m_io_tools, only : open_file
34 : : use m_pptools, only : printxsf
35 : : use m_geometry, only : xred2xcart
36 : : use m_fftcore, only : sphereboundary
37 : : use m_special_funcs, only : gamma_function
38 : : use m_fft, only : fourwf
39 : :
40 : : implicit none
41 : :
42 : : private
43 : : !!***
44 : :
45 : : public :: spin_current
46 : : !!***
47 : :
48 : : contains
49 : : !!***
50 : :
51 : : !!****f* m_spin_current/spin_current
52 : : !! NAME
53 : : !! spin_current
54 : : !!
55 : : !! FUNCTION
56 : : !!
57 : : !! INPUTS
58 : : !! atindx(natom)=index table for atoms (see gstate.f)
59 : : !! atindx1(natom)=inverse of atindx
60 : : !! cg(2,mcg)=wavefunctions (may be read from disk instead of input)
61 : : !! dtfil <type(datafiles_type)>=variables related to files
62 : : !! dtset <type(dataset_type)>=all input variables in this dataset
63 : : !! eigen(mband*nkpt*nsppol)=array for holding eigenvalues (hartree)
64 : : !! gmet = reciprocal space metric
65 : : !! gprimd = dimensionful reciprocal space vectors
66 : : !! hdr <type(hdr_type)>=the header of wf, den and pot files
67 : : !! kg(3,mpw*mkmem)=reduced (integer) coordinates of G vecs in basis sphere
68 : : !! mcg=size of wave-functions array (cg) =mpw*nspinor*mband*mkmem*nsppol
69 : : !! mpi_enreg=information about MPI parallelization
70 : : !! nattyp(dtset%ntypat)=number of atoms of each type
71 : : !! nfftf = fft grid dimensions for fine grid
72 : : !! ph1d = phase factors in 1 radial dimension
73 : : !! psps <type(pseudopotential_type)>=variables related to pseudopotentials
74 : : !! | mpsang= 1+maximum angular momentum
75 : : !! rhog(2,nfftf)=Fourier transform of total electron density (including compensation density in PAW)
76 : : !! rhor(nfftf,nspden)=total electron density (including compensation density in PAW)
77 : : !! rmet = real space metric tensor
78 : : !! symrec(3,3,nsym)=symmetries in reciprocal space, reduced coordinates
79 : : !! ucvol = unit cell volume
80 : : !! wffnow=unit number for current wf disk file
81 : : !! ylm(mpw*mkmem,mpsang*mpsang*useylm)= real spherical harmonics for each G and k point
82 : : !! ylmgr(mpw*mkmem,3,mpsang*mpsang*useylm)= gradients of real spherical harmonics
83 : : !!
84 : : !! OUTPUT
85 : : !! only output to file
86 : : !!
87 : : !! SOURCE
88 : :
89 : 1 : subroutine spin_current(cg,dtfil,dtset,gprimd,hdr,kg,mcg,mpi_enreg,psps)
90 : :
91 : : !Arguments ------------------------------------
92 : : !scalars
93 : : !integer,intent(in) :: nfftf
94 : : !real(dp),intent(in) :: ucvol
95 : : integer,intent(in) :: mcg
96 : : type(MPI_type),intent(in) :: mpi_enreg
97 : : type(datafiles_type),intent(in) :: dtfil
98 : : type(dataset_type),intent(in) :: dtset
99 : : type(hdr_type),intent(inout) :: hdr
100 : : type(pseudopotential_type),intent(in) :: psps
101 : : !type(wffile_type),intent(in) :: wffnow
102 : : !arrays
103 : : !integer,intent(in) :: atindx(dtset%natom),atindx1(dtset%natom)
104 : : integer,intent(in) :: kg(3,dtset%mpw*dtset%mkmem)
105 : : !integer,intent(in) :: nattyp(dtset%ntypat)
106 : : !integer,intent(in) :: symrec(3,3,dtset%nsym)
107 : : real(dp),intent(in) :: cg(2,mcg)
108 : : !real(dp),intent(in) :: eigen(dtset%mband*dtset%nkpt*dtset%nsppol),gmet(3,3)
109 : : real(dp),intent(in) :: gprimd(3,3)
110 : : !real(dp),intent(in) :: rhog(2,nfftf),rhor(nfftf,dtset%nspden)
111 : : !real(dp),intent(in) :: rmet(3,3)
112 : : !real(dp),intent(in) :: ylm(dtset%mpw*dtset%mkmem,psps%mpsang*psps%mpsang*psps%useylm)
113 : : !real(dp),intent(in) :: ylmgr(dtset%mpw*dtset%mkmem,3,psps%mpsang*psps%mpsang*psps%useylm)
114 : : !real(dp),intent(inout) :: ph1d(2,3*(2*dtset%mgfft+1)*dtset%natom)
115 : :
116 : : !Local variables-------------------------------
117 : : !scalars
118 : : integer :: cplex,fft_option,i1
119 : : integer :: i2,i3,iband,icartdir,icg,ig
120 : : integer :: ikg,ikpt,iocc,irealsp,ispindir,ispinor,ispinorp
121 : : integer :: npw
122 : : integer :: icplex
123 : : integer :: realrecip
124 : : integer :: iatom,spcur_unit
125 : : real(dp) :: prefact_nk
126 : : real(dp) :: rescale_current
127 : : character(len=500) :: message
128 : : character(len=fnlen) :: filnam
129 : : !arrays
130 : 1 : integer,allocatable :: gbound(:,:),kg_k(:,:)
131 : 1 : real(dp),allocatable :: dpsidr(:,:,:,:,:,:)
132 : 1 : real(dp),allocatable :: density(:,:,:,:)
133 : 1 : real(dp),allocatable :: dummy_denpot(:,:,:)
134 : 1 : real(dp),allocatable :: gpsi(:,:,:,:),kgcart(:,:)
135 : 1 : real(dp),allocatable :: position_op(:,:,:,:)
136 : 1 : real(dp),allocatable :: psi(:,:,:),psi_r(:,:,:,:,:)
137 : 1 : real(dp),allocatable :: spincurrent(:,:,:,:,:)
138 : 1 : real(dp),allocatable :: vso_realspace(:,:,:,:,:),datagrid(:)
139 : : real(dp) :: dummy_fofgout(0,0)
140 : 1 : real(dp),allocatable :: xcart(:,:)
141 : : character :: spin_symbol(3)
142 : : character :: spinor_sym(2)
143 : : character(len=2) :: realimag(2)
144 : : !no_abirules
145 : : !real(dp),allocatable :: density_matrix(:,:,:,:,:)
146 : : !real(dp),allocatable :: vso_realspace_nl(:,:,:,:,:)
147 : :
148 : : ! *************************************************************************
149 : :
150 : : !write(std_out,*) ' Entering subroutine spin_current '
151 : : !write(std_out,*) ' dtset%ngfft = ', dtset%ngfft
152 : : !write(std_out,*) ' hdr%istwfk = ', hdr%istwfk
153 : :
154 : : !===================== init and checks ============================
155 : : !check if nspinor is 2
156 [ - + ]: 1 : if (dtset%nspinor /= 2) then
157 : 0 : write(message, '(a,i0)' )' nspinor must be 2, but it is ',dtset%nspinor
158 : 0 : ABI_ERROR(message)
159 : : end if
160 : :
161 [ - + ]: 1 : if (dtset%nsppol /= 1) then
162 : 0 : write(message, '(a,i0)' )' spin_current: nsppol must be 1 but it is ',dtset%nsppol
163 : 0 : ABI_ERROR(message)
164 : : end if
165 : :
166 [ - + ]: 1 : if (dtset%mkmem /= dtset%nkpt) then
167 : : write(message, '(a,i6,a,i6,a,a)' )&
168 : 0 : & ' mkmem = ',dtset%mkmem,' must be equal to nkpt ',dtset%nkpt,ch10,&
169 : 0 : & ' keep all kpt in memory'
170 : 0 : ABI_ERROR(message)
171 : : end if
172 : :
173 [ - + ]: 1 : if (dtset%usepaw /= 0) then
174 : : write(message, '(a,i0,a,a,a)' )&
175 : 0 : & 'usepaw = ',dtset%usepaw,' must be equal to 0 ',ch10,&
176 : 0 : & 'Not functional for PAW case yet.'
177 : 0 : ABI_ERROR(message)
178 : : end if
179 : :
180 : 1 : cplex=2
181 : 1 : fft_option = 0 ! just do direct fft
182 [ + + ]: 4 : spin_symbol = (/'x','y','z'/)
183 [ + + ]: 3 : spinor_sym = (/'u','d'/)
184 [ + + ]: 3 : realimag = (/'Re','Im'/)
185 : :
186 : 1 : write(std_out,*) ' psps%mpsang,psps%mpssoang ', psps%mpsang,psps%mpssoang
187 : :
188 : : !======================= main code ================================
189 : : !-----------------------------------------------------------------------------------------
190 : : !-----------------------------------------------------------------------------------------
191 : : !first get normal contribution to current, as psi tau dpsidr + dpsidr tau psi
192 : : !where tau are 1/2 the pauli matrices
193 : : !-----------------------------------------------------------------------------------------
194 : : !-----------------------------------------------------------------------------------------
195 : :
196 : : !init plane wave coeff counter
197 : 1 : icg = 0
198 : : !init plane wave counter
199 : 1 : ikg = 0
200 : : !init occupation/band counter
201 : 1 : iocc = 1
202 : :
203 : : !rspace point, cartesian direction, spin pol=x,y,z
204 [ - + + - : 7 : ABI_MALLOC(spincurrent,(dtset%ngfft(4),dtset%ngfft(5),dtset%ngfft(6),3,3))
- + + - -
+ + - + -
+ - + - +
- - + -
+ ]
205 [ + + + + : 32548 : spincurrent = zero
+ + + + +
+ ]
206 : :
207 [ - + + - : 5 : ABI_MALLOC(dummy_denpot,(cplex*dtset%ngfft(4),dtset%ngfft(5),dtset%ngfft(6)))
- + + - -
+ + - + -
+ - - + -
+ ]
208 : :
209 [ + - - + : 4 : ABI_MALLOC(gbound,(2*dtset%mgfft+8,2))
+ - + - +
- + - - +
- + ]
210 : :
211 : : !allocate (density_matrix(2,dtset%ngfft(1)*dtset%ngfft(2)*dtset%ngfft(3),dtset%nspinor,&
212 : : !& dtset%ngfft(1)*dtset%ngfft(2)*dtset%ngfft(3),dtset%nspinor))
213 : : !density_matrix= zero
214 [ - + + - : 5 : ABI_MALLOC(density,(2,dtset%ngfft(1)*dtset%ngfft(2)*dtset%ngfft(3),dtset%nspinor,dtset%nspinor))
- + + - -
+ + - + -
+ - - + -
+ ]
215 [ + + + + : 40507 : density= zero
+ + + + ]
216 : :
217 [ - + + - : 7 : ABI_MALLOC(dpsidr,(2,dtset%ngfft(4),dtset%ngfft(5),dtset%ngfft(6),dtset%nspinor,3))
- + + - -
+ + - - +
+ - + - +
- + - - +
- + ]
218 [ - + + - : 6 : ABI_MALLOC(psi_r,(2,dtset%ngfft(4),dtset%ngfft(5),dtset%ngfft(6),dtset%nspinor))
- + + - -
+ + - - +
+ - + - +
- - + -
+ ]
219 : :
220 : : !loop over kpoints
221 [ + + ]: 2 : do ikpt=1,dtset%nkpt
222 : :
223 : : ! number of plane waves for this kpt
224 : 1 : npw = hdr%npwarr(ikpt)
225 : :
226 : : ! allocate arrays dep on number of pw
227 [ - + + - : 3 : ABI_MALLOC(kg_k,(3,npw))
+ - + - -
+ - + ]
228 [ - + + - : 5 : ABI_MALLOC(gpsi,(2,npw,dtset%nspinor,3))
- + + - +
- + - + -
- + - + ]
229 [ - + + - : 4 : ABI_MALLOC(psi,(2,npw,dtset%nspinor))
- + + - +
- + - - +
- + ]
230 [ - + + - : 3 : ABI_MALLOC(kgcart,(3,npw))
+ - + - -
+ - + ]
231 : :
232 : : ! get cartesian coordinates of k+G vectors around this kpoint
233 [ + + ]: 172 : do ig=1,npw
234 [ + + + + : 3249 : kgcart(:,ig) = matmul(gprimd(:,:),dtset%kpt(:,ikpt)+kg(:,ikg+ig))
+ + + + +
- ]
235 [ + + ]: 685 : kg_k (:,ig) = kg(:,ikg+ig)
236 : : end do
237 : :
238 : : ! get gbound
239 : 1 : call sphereboundary(gbound,dtset%istwfk(ikpt),kg_k,dtset%mgfft,npw)
240 : :
241 : : ! loop over bands
242 [ + + ]: 11 : do iband=1,dtset%nband(ikpt)
243 : :
244 : : ! prefactor for sum over bands and kpoints
245 : 10 : prefact_nk = hdr%occ(iocc) * dtset%wtk(ikpt)
246 : :
247 : : ! initialize this wf
248 [ + + + + : 30880 : gpsi=zero
+ + + + ]
249 [ + + + + : 10290 : psi=zero
+ + ]
250 [ + + + + ]: 5140 : psi(:,1:npw,1) = cg(:,icg+1:icg+npw)
251 : :
252 : : ! multiply psi by - i 2 pi G
253 [ + + ]: 1720 : do ig=1,npw
254 [ + + ]: 5130 : gpsi(1,ig,:,1) = two_pi * kgcart(1,ig)*psi(2,ig,:)
255 [ + + ]: 5130 : gpsi(2,ig,:,1) = -two_pi * kgcart(1,ig)*psi(1,ig,:)
256 [ + + ]: 5130 : gpsi(1,ig,:,2) = two_pi * kgcart(2,ig)*psi(2,ig,:)
257 [ + + ]: 5130 : gpsi(2,ig,:,2) = -two_pi * kgcart(2,ig)*psi(1,ig,:)
258 [ + + ]: 5130 : gpsi(1,ig,:,3) = two_pi * kgcart(3,ig)*psi(2,ig,:)
259 [ + + ]: 5140 : gpsi(2,ig,:,3) = -two_pi * kgcart(3,ig)*psi(1,ig,:)
260 : : end do
261 : :
262 : : ! loop over spinorial components
263 [ + + ]: 30 : do ispinor=1,dtset%nspinor
264 : : ! FT Gpsi_x to real space
265 : : call fourwf(cplex,dummy_denpot,gpsi(:,:,ispinor,1),dummy_fofgout,&
266 : : & dpsidr(:,:,:,:,ispinor,1),gbound,gbound,&
267 : : & hdr%istwfk(ikpt),kg_k,kg_k,dtset%mgfft,mpi_enreg,1,dtset%ngfft,npw,&
268 : : & npw,dtset%ngfft(4),dtset%ngfft(5),dtset%ngfft(6),&
269 : 20 : & fft_option,0,one,one,gpu_option=dtset%gpu_option)
270 : :
271 : : ! FT Gpsi_y to real space
272 : : call fourwf(cplex,dummy_denpot,gpsi(:,:,ispinor,2),dummy_fofgout,&
273 : : & dpsidr(:,:,:,:,ispinor,2),gbound,gbound,&
274 : : & hdr%istwfk(ikpt),kg_k,kg_k,dtset%mgfft,mpi_enreg,1,dtset%ngfft,npw,&
275 : : & npw,dtset%ngfft(4),dtset%ngfft(5),dtset%ngfft(6),&
276 : 20 : & fft_option,0,one,one,gpu_option=dtset%gpu_option)
277 : :
278 : : ! FT Gpsi_z to real space
279 : : call fourwf(cplex,dummy_denpot,gpsi(:,:,ispinor,3),dummy_fofgout,&
280 : : & dpsidr(:,:,:,:,ispinor,3),gbound,gbound,&
281 : : & hdr%istwfk(ikpt),kg_k,kg_k,dtset%mgfft,mpi_enreg,1,dtset%ngfft,npw,&
282 : : & npw,dtset%ngfft(4),dtset%ngfft(5),dtset%ngfft(6),&
283 : 20 : & fft_option,0,one,one,gpu_option=dtset%gpu_option)
284 : :
285 : : ! FT psi to real space
286 : : call fourwf(cplex,dummy_denpot,psi(:,:,ispinor),dummy_fofgout,&
287 : : & psi_r(:,:,:,:,ispinor),gbound,gbound,&
288 : : & hdr%istwfk(ikpt),kg_k,kg_k,dtset%mgfft,mpi_enreg,1,dtset%ngfft,npw,&
289 : : & npw,dtset%ngfft(4),dtset%ngfft(5),dtset%ngfft(6),&
290 : 30 : & fft_option,0,one,one,gpu_option=dtset%gpu_option)
291 : :
292 : : end do ! ispinor
293 : :
294 : : ! dpsidr now contains the full derivative of psi wrt space (gradient) in cartesian coordinates
295 : :
296 : : ! get 3 pauli matrix contributions to the current: x,y,z, cart dir, spin dir
297 [ + + ]: 40 : do icartdir=1,3
298 : :
299 : : ! x pauli spin matrix
300 : : ! sigma_x = | 0 1 |
301 : : ! | 1 0 |
302 : : spincurrent(:,:,:,icartdir,1) = spincurrent(:,:,:,icartdir,1) + prefact_nk * &
303 : : ! Re(psi_r(up)^* dpsidr(down))
304 : : & real(psi_r(1,:,:,:,1)*dpsidr(1,:,:,:,2,icartdir) &
305 : : & + psi_r(2,:,:,:,1)*dpsidr(2,:,:,:,2,icartdir) &
306 : : ! Re(psi_r(down)^* dpsidr(up))
307 : : & + psi_r(1,:,:,:,2)*dpsidr(1,:,:,:,1,icartdir) &
308 [ + + + + : 108480 : & + psi_r(2,:,:,:,2)*dpsidr(2,:,:,:,1,icartdir))
+ + ]
309 : :
310 : : ! y pauli spin matrix
311 : : ! sigma_y = | 0 -i |
312 : : ! | i 0 |
313 : : spincurrent(:,:,:,icartdir,2) = spincurrent(:,:,:,icartdir,2) + prefact_nk * &
314 : : ! Re(-i psi_r(up)^* dpsidr(down))
315 : : & real(psi_r(1,:,:,:,1)*dpsidr(2,:,:,:,2,icartdir) &
316 : : & - psi_r(2,:,:,:,1)*dpsidr(1,:,:,:,2,icartdir) &
317 : : ! Re(i psi_r(down)^* dpsidr(up))
318 : : & - psi_r(1,:,:,:,2)*dpsidr(2,:,:,:,1,icartdir) &
319 [ + + + + : 108480 : & + psi_r(2,:,:,:,2)*dpsidr(1,:,:,:,1,icartdir))
+ + ]
320 : :
321 : : ! z pauli spin matrix
322 : : ! sigma_z = | 1 0 |
323 : : ! | 0 -1 |
324 : : spincurrent(:,:,:,icartdir,3) = spincurrent(:,:,:,icartdir,3) + prefact_nk * &
325 : : ! Re(psi_r(up)^* dpsidr(up))
326 : : & real(psi_r(1,:,:,:,1)*dpsidr(1,:,:,:,1,icartdir) &
327 : : & - psi_r(2,:,:,:,1)*dpsidr(2,:,:,:,1,icartdir) &
328 : : ! Re(-psi_r(down)^* dpsidr(down))
329 : : & - psi_r(1,:,:,:,2)*dpsidr(1,:,:,:,2,icartdir) &
330 [ + + + + : 108490 : & + psi_r(2,:,:,:,2)*dpsidr(2,:,:,:,2,icartdir))
+ + ]
331 : : end do ! end icartdir
332 : :
333 : : !
334 : : ! accumulate non local density matrix in real space
335 : : ! NOTE: if we are only using the local part of the current, this becomes the
336 : : ! density spinor matrix! (much lighter to calculate) rho(r, sigma, sigmaprime)
337 : : !
338 [ + + ]: 30 : do ispinor=1,dtset%nspinor
339 [ + + ]: 330 : do i3=1,dtset%ngfft(3)
340 [ + + ]: 4820 : do i2=1,dtset%ngfft(2)
341 [ + + ]: 72300 : do i1=1,dtset%ngfft(1)
342 : 67500 : irealsp = i1 + (i2-1)*dtset%ngfft(1) + (i3-1)*dtset%ngfft(2)*dtset%ngfft(1)
343 : :
344 [ + + ]: 207000 : do ispinorp=1,dtset%nspinor
345 : : density(1,irealsp,ispinor,ispinorp) = &
346 : : & density(1,irealsp,ispinor,ispinorp) + &
347 : : & prefact_nk * (psi_r(1,i1,i2,i3,ispinor)*psi_r(1,i1,i2,i3,ispinorp)&
348 : 135000 : & + psi_r(2,i1,i2,i3,ispinor)*psi_r(2,i1,i2,i3,ispinorp))
349 : : density(2,irealsp,ispinor,ispinorp) = &
350 : : & density(2,irealsp,ispinor,ispinorp) + &
351 : : & prefact_nk * (psi_r(1,i1,i2,i3,ispinor)*psi_r(2,i1,i2,i3,ispinorp)&
352 : 202500 : & - psi_r(2,i1,i2,i3,ispinor)*psi_r(1,i1,i2,i3,ispinorp))
353 : :
354 : : ! do i3p=1,dtset%ngfft(3)
355 : : ! do i2p=1,dtset%ngfft(2)
356 : : ! do i1p=1,dtset%ngfft(1)
357 : : ! irealsp_p = i1p + (i2p-1)*dtset%ngfft(1) + (i3p-1)*dtset%ngfft(2)*dtset%ngfft(1)
358 : : !
359 : : ! NOTE : sign changes in second terms below because rho = psi*(r) psi(rprime)
360 : : !
361 : : ! density_matrix(1,irealsp,ispinor,irealsp_p,ispinorp) = &
362 : : ! & density_matrix(1,irealsp,ispinor,irealsp_p,ispinorp) + &
363 : : ! & prefact_nk * (psi_r(1,i1,i2,i3,ispinor)*psi_r(1,i1p,i2p,i3p,ispinorp)&
364 : : ! & + psi_r(2,i1,i2,i3,ispinor)*psi_r(2,i1p,i2p,i3p,ispinorp))
365 : : ! density_matrix(2,irealsp,ispinor,irealsp_p,ispinorp) = &
366 : : ! & density_matrix(2,irealsp,ispinor,irealsp_p,ispinorp) + &
367 : : ! & prefact_nk * (psi_r(1,i1,i2,i3,ispinor)*psi_r(2,i1p,i2p,i3p,ispinorp)&
368 : : ! & - psi_r(2,i1,i2,i3,ispinor)*psi_r(1,i1p,i2p,i3p,ispinorp))
369 : : ! end do
370 : : ! end do
371 : : ! end do ! end irealspprime
372 : :
373 : : end do !end ispinorp do
374 : :
375 : : end do
376 : : end do
377 : : end do ! end irealsp
378 : : end do !end ispinor do
379 : :
380 : : ! update pw counter
381 : 10 : icg=icg+npw
382 : 11 : iocc=iocc+1
383 : : end do ! iband
384 : :
385 : 1 : ikg=ikg+npw
386 : :
387 : : ! deallocate arrays dep on npw for this kpoint
388 [ - + ]: 1 : ABI_FREE(kg_k)
389 [ - + ]: 1 : ABI_FREE(gpsi)
390 [ - + ]: 1 : ABI_FREE(psi)
391 [ - + ]: 2 : ABI_FREE(kgcart)
392 : :
393 : : end do ! ikpt
394 : :
395 [ - + ]: 1 : ABI_FREE(dpsidr)
396 [ - + ]: 1 : ABI_FREE(psi_r)
397 [ - + ]: 1 : ABI_FREE(dummy_denpot)
398 [ - + ]: 1 : ABI_FREE(gbound)
399 : :
400 : : !prefactor for contribution to spin current
401 : : !prefactor is 1/2 * 1/2 * 2 Re(.):
402 : : !1/2 from the formula for the current
403 : : !1/2 from the use of the normalized Pauli matrices
404 : : !2 from the complex conjugate part
405 : : !total = 1/2
406 [ + + + + : 32548 : spincurrent = half * spincurrent
+ + + + +
+ ]
407 : :
408 : : !make array of positions for all points on grid
409 [ - + + - : 5 : ABI_MALLOC(position_op,(3,dtset%ngfft(1),dtset%ngfft(2),dtset%ngfft(3)))
- + + - -
+ + - + -
+ - - + -
+ ]
410 [ + + ]: 16 : do i3=1,dtset%ngfft(3)
411 [ + + ]: 241 : do i2=1,dtset%ngfft(2)
412 [ + + ]: 3615 : do i1=1,dtset%ngfft(1)
413 : : position_op(:,i1,i2,i3) = matmul(hdr%rprimd,(/i1-one,i2-one,i3-one/))&
414 [ + + + + : 74475 : & /(/dtset%ngfft(1),dtset%ngfft(2),dtset%ngfft(3)/)
+ + + + +
+ ]
415 : : end do
416 : : end do
417 : : end do
418 : :
419 : : !-----------------------------------------------------------------------------------------
420 : : !-----------------------------------------------------------------------------------------
421 : : !add electric field term to current. Non local term in case of pseudopotential SO
422 : : !present theory is that it is equal to A(r,r') = (W_SO(r,r') + W_SO(r',r))
423 : : !For the strictly local part of the current, this becomes 2 W_SO(r,r)
424 : : !
425 : : !W_SO is the prefactor in the spinorbit part of the potential, such that it
426 : : !can be written V_SO = W_SO . p (momentum operator)
427 : : !decomposed from V_SO = v_SO(r,r') L.S = v_SO(r,r') (rxp).S = v_SO(r,r') (Sxr).p
428 : : !and ensuring symmetrization for the r operator wrt the two arguments of v_SO(r,r')
429 : : !Hence:
430 : : !W_SO(r,r) = v_SO(r,r) (Sxr)
431 : : !-----------------------------------------------------------------------------------------
432 : : !-----------------------------------------------------------------------------------------
433 : :
434 : : !allocate (vso_realspace_nl(2,dtset%ngfft(1)*dtset%ngfft(2)*dtset%ngfft(3),dtset%nspinor,&
435 : : !& dtset%ngfft(1)*dtset%ngfft(2)*dtset%ngfft(3),dtset%nspinor))
436 : :
437 : : !call vso_realspace_nonlop(atindx,atindx1,dtfil,dtset,gmet,gprimd,hdr,kg,&
438 : : !& mpi_enreg,nattyp,ph1d,position_op,psps,rmet,ucvol,vso_realspace_nl,ylm,ylmgr)
439 : : !anticommutator of VSO with position operator
440 : : !--- not needed in local spin current case ---
441 : :
442 [ - + + - : 6 : ABI_MALLOC(vso_realspace,(2,dtset%ngfft(1)*dtset%ngfft(2)*dtset%ngfft(3),dtset%nspinor,dtset%nspinor,3))
- + + - -
+ + - + -
+ - + - -
+ - + ]
443 : :
444 : 1 : call vso_realspace_local(dtset,hdr,position_op,psps,vso_realspace)
445 : :
446 : :
447 : : !multiply by density (or density matrix for nonlocal case)
448 : : !and add to spin current
449 : :
450 : :
451 : :
452 [ - + ]: 1 : ABI_FREE(density)
453 : :
454 : 1 : realrecip = 0 ! real space for xsf output
455 [ - + + - : 3 : ABI_MALLOC(xcart,(3,dtset%natom))
+ - + - -
+ - + ]
456 : 1 : call xred2xcart(dtset%natom,hdr%rprimd,xcart,hdr%xred)
457 : :
458 : : !-----------------------------------------------------------------------------------------
459 : : !-----------------------------------------------------------------------------------------
460 : : !output 3 components of current for each real space point
461 : : !-----------------------------------------------------------------------------------------
462 : : !-----------------------------------------------------------------------------------------
463 [ + + ]: 4 : do ispindir=1, 3
464 : : ! choose rescale_current such that the maximum current component printed out
465 : : ! is 1 percent of lattice distance
466 : : ! By default XCrysDen multiplies by 200 to get something comparable to a distance in real space.
467 [ + + + + : 32547 : rescale_current = maxval(abs(spincurrent(:, :, :, :, ispindir)))
+ + + + +
+ + - -
+ ]
468 [ + + ]: 3 : if (abs(rescale_current) < tol8) then
469 : : rescale_current = one
470 : : else
471 : : rescale_current = 0.001_dp * sqrt(max(sum(hdr%rprimd(:,1)**2), &
472 [ + + + + : 10 : & sum(hdr%rprimd(:,2)**2), sum(hdr%rprimd(:,3)**2)))
+ + ]
473 : : end if
474 : :
475 [ + - ]: 3 : filnam=trim(dtfil%fnameabo_spcur)//spin_symbol(ispindir)//".xsf"
476 [ - + ]: 3 : if (open_file(filnam,message,newunit=spcur_unit,status='unknown') /= 0) then
477 : 0 : ABI_ERROR(message)
478 : : end if
479 : :
480 : : ! print header
481 : 3 : write (spcur_unit,'(a)') '#'
482 : 3 : write (spcur_unit,'(a)') '# Xcrysden format file'
483 : 3 : write (spcur_unit,'(a)') '# spin current density, for all real space points'
484 : 3 : write (spcur_unit,'(a,3(I5,1x))') '# fft grid is ', dtset%ngfft(1), dtset%ngfft(2), dtset%ngfft(3)
485 : 3 : write (spcur_unit,'(a,a,a)') '# ', spin_symbol(ispindir), '-spin current, full vector '
486 : :
487 : 3 : write (spcur_unit,'(a)') 'ATOMS'
488 [ + + ]: 6 : do iatom = 1, dtset%natom
489 : 6 : write (spcur_unit,'(I4, 2x, 3(E16.6, 1x))') int(dtset%znucl(dtset%typat(iatom))), xcart(:,iatom)
490 : : end do
491 : :
492 [ + + ]: 48 : do i3=1,dtset%ngfft(3)
493 [ + + ]: 723 : do i2=1,dtset%ngfft(2)
494 [ + + ]: 10845 : do i1=1,dtset%ngfft(1)
495 : 10125 : write (spcur_unit,'(a, 3(E10.3),2x, 3(E20.10))') 'X ', &
496 [ + + ]: 51300 : & position_op(:, i1, i2, i3), spincurrent(i1, i2, i3, :, ispindir)*rescale_current
497 : : end do
498 : : end do
499 : : end do
500 : 4 : close (spcur_unit)
501 : :
502 : : end do ! end ispindir
503 : :
504 : : !-----------------------------------------------------------------------------------------
505 : : !-----------------------------------------------------------------------------------------
506 : : !output 3 spin components of V_SO matrices, for each real space point
507 : : !-----------------------------------------------------------------------------------------
508 : : !-----------------------------------------------------------------------------------------
509 [ - + + - : 3 : ABI_MALLOC(datagrid, (dtset%ngfft(1)*dtset%ngfft(2)*dtset%ngfft(3)))
+ - + - -
+ - + ]
510 : :
511 [ + + ]: 4 : do ispindir=1,3
512 [ + + ]: 10 : do icplex=1,2
513 [ + + ]: 21 : do ispinor=1,dtset%nspinor
514 [ + + ]: 42 : do ispinorp=1,dtset%nspinor
515 : :
516 : : ! for the moment only print out if non zero
517 [ + + + + ]: 81024 : if (abs(sum(vso_realspace(icplex, :, ispinor, ispinorp, ispindir))) < tol8) cycle
518 : :
519 : : filnam=trim(dtfil%fnameabo_vso)//"_spin_"//spin_symbol(ispindir)//"_"//&
520 [ + - ]: 12 : & spinor_sym(ispinor)//spinor_sym(ispinorp)//"_"//realimag(icplex)//".xsf"
521 : :
522 [ - + ]: 12 : if (open_file(filnam,message,newunit=spcur_unit,status='unknown') /= 0) then
523 : 0 : ABI_ERROR(message)
524 : : end if
525 : :
526 : : ! print header
527 : 12 : write (spcur_unit,'(a)') '#'
528 : 12 : write (spcur_unit,'(a)') '# Xcrysden format file'
529 : 12 : write (spcur_unit,'(a)') '# spin-orbit potential (space diagonal), for all real space points'
530 : 12 : write (spcur_unit,'(a)') '# Real part first, then imaginary part'
531 : 12 : write (spcur_unit,'(a,3(I5,1x))') '# fft grid is ', dtset%ngfft(1), dtset%ngfft(2), dtset%ngfft(3)
532 : 12 : write (spcur_unit,'(a,a,a)') '# ', spin_symbol(ispindir), '-spin contribution '
533 : 12 : write (spcur_unit,'(a,a,a)') '# ', spinor_sym(ispinor)//spinor_sym(ispinorp), &
534 : 24 : '-spin element of the spinor 2x2 matrix '
535 : 12 : write (spcur_unit,'(a,a)') '# cart x * cart y * cart z ***',&
536 : 24 : & ' up-up component * up-down * down-up * down-down '
537 : :
538 : : ! Build contiguous array
539 [ - + + + ]: 40524 : datagrid = vso_realspace(icplex,:,ispinor, ispinorp, ispindir)
540 : :
541 : : call printxsf(dtset%ngfft(1),dtset%ngfft(2),dtset%ngfft(3),&
542 : : & datagrid,hdr%rprimd,(/zero,zero,zero/), dtset%natom, dtset%ntypat, &
543 : 12 : & dtset%typat, xcart, dtset%znucl, spcur_unit,realrecip)
544 : :
545 : : !
546 : : ! NOTE: have chosen actual dims of grid (n123) instead of fft box, for which n45
547 : : ! may be different
548 : : !
549 : : ! do i3_dum=1,dtset%ngfft(3)+1
550 : : ! i3 = mod(i3_dum-1,dtset%ngfft(3)) + 1
551 : : ! do i2_dum=1,dtset%ngfft(2)+1
552 : : ! i2 = mod(i2_dum-1,dtset%ngfft(2)) + 1
553 : : ! do i1_dum=1,dtset%ngfft(1)+1
554 : : ! i1 = mod(i1_dum-1,dtset%ngfft(1)) + 1
555 : : !
556 : : ! irealsp = i1 + (i2-1)*dtset%ngfft(1) + (i3-1)*dtset%ngfft(2)*dtset%ngfft(1)
557 : : ! write (spcur_unit,'(E20.10,1x)')&
558 : : ! & vso_realspace(icplex,irealsp, ispinor, ispinorp, ispindir)
559 : : ! end do
560 : : ! end do
561 : : ! end do
562 : :
563 : 36 : close (spcur_unit)
564 : :
565 : : end do ! ispinorp
566 : : end do ! ispinor
567 : : end do ! icplex
568 : : end do ! end ispindir
569 : :
570 [ - + ]: 1 : ABI_FREE(datagrid)
571 [ - + ]: 1 : ABI_FREE(vso_realspace)
572 : : !deallocate (vso_realspace_nl)
573 [ - + ]: 1 : ABI_FREE(position_op)
574 [ - + ]: 1 : ABI_FREE(spincurrent)
575 [ - + ]: 1 : ABI_FREE(xcart)
576 : :
577 : 1 : write(std_out,*) ' Exiting subroutine spin_current '
578 : :
579 : 1 : end subroutine spin_current
580 : : !!***
581 : :
582 : : !!****f* m_spin_current/vso_realspace_local
583 : : !! NAME
584 : : !! vso_realspace_local
585 : : !!
586 : : !! FUNCTION
587 : : !! Calculate real space (local - (r,r)) values of the SO part of the
588 : : !! pseudopotential. Reconstructed explicitly in the HGH/GTH case.
589 : : !!
590 : : !! INPUTS
591 : : !!
592 : : !! OUTPUT
593 : : !!
594 : : !! SIDE EFFECTS
595 : : !!
596 : : !! NOTES
597 : : !!
598 : : !! SOURCE
599 : :
600 : 1 : subroutine vso_realspace_local(dtset,hdr,position_op,psps,vso_realspace)
601 : :
602 : : !Arguments -------------------------------
603 : : type(hdr_type),intent(inout) :: hdr
604 : : type(dataset_type),intent(in) :: dtset
605 : : type(pseudopotential_type),intent(in) :: psps
606 : : real(dp),intent(in) :: position_op(3,dtset%ngfft(1),dtset%ngfft(2),dtset%ngfft(3))
607 : : real(dp),intent(out) :: vso_realspace(2,dtset%ngfft(1)*dtset%ngfft(2)*dtset%ngfft(3),&
608 : : & dtset%nspinor,dtset%nspinor,3)
609 : :
610 : : !Local variables -------------------------
611 : : !scalars
612 : : integer :: i,j,l, lmax,ipsp,iatom, ir1,ir2,ir3
613 : : integer :: rcexponent,irealsp
614 : : integer :: nradgrid,iradgrid
615 : : real(dp) :: gammai, gammaj, relative_position(3), radial_cutoff, norm_rel_pos
616 : : real(dp) :: expfact,lfact, vso_interpol, x,y,z
617 : : !arrays
618 : 2 : real(dp) :: xcart(3,dtset%natom),splint_x(1),splint_y(1)
619 : 1 : real(dp), allocatable :: radial_grid(:)
620 : 1 : real(dp), allocatable :: prefact_ijl(:,:,:,:),tmpvso(:),tmpvso_pp(:)
621 : 1 : real(dp), allocatable :: vso_radial(:,:),vso_radial_pp(:,:),tmp_spline(:)
622 : 1 : real(dp), allocatable :: offdiag_l_fact(:,:,:),kpar_matrix(:,:)
623 : :
624 : : ! *********************************************************************
625 : :
626 : : !recalculate xcart (option = 1)
627 : 1 : call xred2xcart(dtset%natom,hdr%rprimd,xcart,hdr%xred)
628 : :
629 : 1 : lmax = psps%mpsang-1
630 : :
631 : : !content of gth pseudo type:
632 : : !These are {rloc, C(1...4)} coefficients for psppar(0, :, :) indices,
633 : : !Followed by the h coefficients for psppar(1:2, 1:, :) indices.
634 : : !size (0:2, 0:4, npsp)
635 : : !potential radius r_l is in psppar(l+1,0,ipsp)
636 : : !real(dp), pointer :: psppar(:, :, :)
637 : : !The covalence radii for each pseudo (?) size (npsp)
638 : : !real(dp), pointer :: radii_cov(:)
639 : : !Cut-off radii for core part and long-range part.
640 : : !radii_cf(:, 1) is for the long-range cut-off and
641 : : !radii_cf(:, 2) is for the core cut-off.
642 : : !size (npsp, 2)
643 : : !real(dp), pointer :: radii_cf(:, :)
644 : : !Spin orbit coefficients in HGH/GTH formats: k11p
645 : : !etc... see psp3ini.F90
646 : : !dimension = num l channels, 3 coeffs, num psp =
647 : : !(1:lmax+1,1:3,npsp)
648 : : !real(dp), pointer :: psp_k_par(:, :, :)
649 : :
650 : : !v_SO^l (r,r') = sum_i sum_j sum_m Y_{lm} (\hat{r}) p_i^l (r) k_{ij}^l p_j^l(r') Y^{*}_lm (\hat{r'})
651 : : !
652 : : !v_SO^l (r,r) = sum_ij p_i^l (r) k_{ij}^l p_j^l(r) sum_m Y_{lm} (\hat{r}) Y^{*}_lm (\hat{r})
653 : : != (2l+1)/4\pi sum_ij p_i^l (r) k_{ij}^l p_j^l(r) (eq B.17 Patrick Rinke thesis)
654 : : !p are gaussian projectors (from HGH paper prb 58 3641) [[cite:Hartwigsen1998]]
655 : : !sum_l v_SO^l (r,r) is a purely radial quantity (function of |r|), so spline it
656 : :
657 : : !maximum distance needed in unit cell
658 [ + + + + : 7 : radial_cutoff = four * maxval(psps%gth_params%psppar(:, 0, :))
+ + + - -
+ - - ]
659 : :
660 : : !setup radial grid; Should we use a logarithmic grid? The spline functions can
661 : : !take it...
662 : 1 : nradgrid = 201 ! this is heuristic
663 [ - + ]: 1 : ABI_MALLOC(radial_grid,(nradgrid))
664 [ + + ]: 202 : do iradgrid=1,nradgrid
665 : 202 : radial_grid(iradgrid) = (iradgrid-1)*radial_cutoff/(nradgrid-1)
666 : : end do
667 : :
668 : : !calculate prefactors independent of r
669 [ - + + - : 4 : ABI_MALLOC(prefact_ijl,(3,3,0:lmax,psps%npsp))
- + + - +
- + - - +
- + ]
670 [ - + + - : 3 : ABI_MALLOC(offdiag_l_fact,(3,3,0:lmax))
+ - + - -
+ - + ]
671 [ - + ]: 1 : ABI_MALLOC(kpar_matrix,(3,3))
672 : :
673 : : !these factors complete the full 3x3 matrix of k (or h) parameters for the
674 : : !HGH pseudos
675 [ + + + + : 40 : offdiag_l_fact = zero
+ + ]
676 : : !l=0
677 : 1 : offdiag_l_fact(1,2,0) = -half*sqrt(three/five)
678 : 1 : offdiag_l_fact(1,3,0) = half*sqrt(five/21._dp)
679 : 1 : offdiag_l_fact(2,3,0) = -half*sqrt(100._dp/63._dp)
680 : : !l=1
681 : 1 : offdiag_l_fact(1,2,1) = -half*sqrt(five/seven)
682 : 1 : offdiag_l_fact(1,3,1) = sixth*sqrt(35._dp/11._dp)
683 : 1 : offdiag_l_fact(2,3,1) = -sixth*14._dp/sqrt(11._dp)
684 : : !l=2
685 [ + - ]: 1 : if (lmax >= 2) then
686 : 1 : offdiag_l_fact(1,2,2) = -half*sqrt(seven/nine)
687 : 1 : offdiag_l_fact(1,3,2) = half*sqrt(63._dp/143._dp)
688 : 1 : offdiag_l_fact(2,3,2) = -half*18._dp /sqrt(143._dp)
689 : : end if
690 : : !l=3
691 [ - + ]: 1 : if (lmax >= 3) then
692 : 0 : offdiag_l_fact(1,2,3) = zero
693 : 0 : offdiag_l_fact(1,3,3) = zero
694 : 0 : offdiag_l_fact(2,3,3) = zero
695 : : end if
696 : : !get prefactors for evaluation of V_SO: terms that do not depend on r
697 [ + + + + : 41 : prefact_ijl = zero
+ + + + ]
698 [ + + ]: 4 : do l=0,lmax
699 : : ! first the diagonal i=j term
700 [ + + ]: 12 : do i=1,3
701 : 9 : call gamma_function(l+(4._dp*i-1._dp)*0.5_dp, gammai)
702 : 9 : gammai = sqrt(gammai)
703 : 9 : rcexponent = 2*l+2*i+2*i-1
704 [ + + ]: 21 : do ipsp=1,psps%npsp
705 : : prefact_ijl(i,i,l,ipsp) = psps%gth_params%psp_k_par(l+1,i,ipsp) &
706 : : & / ( (psps%gth_params%psppar(l+1,0,ipsp))**(rcexponent) &
707 : 18 : & * gammai * gammai)
708 : : end do
709 : : end do
710 : : ! now the off diagonal elements
711 [ + + ]: 6 : do ipsp=1,psps%npsp
712 : 3 : kpar_matrix(1,2) = offdiag_l_fact (1,2,l)* psps%gth_params%psp_k_par(l+1,2,ipsp)
713 : 3 : kpar_matrix(2,1) = kpar_matrix(1,2)
714 : 3 : kpar_matrix(1,3) = offdiag_l_fact (1,3,l)* psps%gth_params%psp_k_par(l+1,3,ipsp)
715 : 3 : kpar_matrix(3,1) = kpar_matrix(1,3)
716 : 3 : kpar_matrix(2,3) = offdiag_l_fact (2,3,l)* psps%gth_params%psp_k_par(l+1,3,ipsp)
717 : 6 : kpar_matrix(3,2) = kpar_matrix(2,3)
718 : : end do
719 : :
720 : : ! for the f case only the 1,1 matrix element is non 0 - it is done above and
721 : : ! all these terms are actually 0
722 [ + - ]: 3 : if (l > 2) cycle
723 : :
724 [ + + ]: 13 : do i=1,3
725 : 9 : call gamma_function(l+(4._dp*i-1._dp)*0.5_dp, gammai)
726 : 9 : gammai = sqrt(gammai)
727 [ + + ]: 39 : do j=1,3
728 [ + + ]: 27 : if (j==i) cycle
729 : 18 : rcexponent = 2*l+2*i+2*j-1
730 : 18 : call gamma_function(l+(4._dp*j-1._dp)*0.5_dp,gammaj)
731 : 18 : gammaj = sqrt(gammaj)
732 [ + + ]: 45 : do ipsp=1,psps%npsp
733 : : prefact_ijl(i,j,l,ipsp) = kpar_matrix(i,j) &
734 : : & / ( (psps%gth_params%psppar(l+1,0,ipsp))**rcexponent &
735 : 45 : & * gammai * gammaj )
736 : : end do
737 : : end do
738 : : end do
739 : : end do
740 : :
741 [ - + ]: 1 : ABI_FREE(kpar_matrix)
742 : 1 : ABI_FREE(offdiag_l_fact)
743 : :
744 [ + + + + : 41 : prefact_ijl = prefact_ijl * two
+ + + + ]
745 : :
746 : : !calculate v_SO on radial grid
747 : : ! MGNAG Runtime Error: *** Arithmetic exception: Floating invalid operation - aborting
748 [ - + + - : 3 : ABI_MALLOC(vso_radial,(nradgrid,psps%npsp))
+ - + - -
+ - + ]
749 [ + + + + ]: 203 : vso_radial = zero
750 [ + + ]: 4 : do l=0,lmax
751 : 606 : lfact=(2._dp*l+1._dp)/four/pi
752 [ + + ]: 607 : do iradgrid=1,nradgrid
753 : 603 : norm_rel_pos = radial_grid(iradgrid)
754 [ + + ]: 1209 : do ipsp=1,psps%npsp
755 : 603 : expfact = exp(-norm_rel_pos**2 / (psps%gth_params%psppar(l+1,0,ipsp))**2)
756 : :
757 [ + + ]: 3015 : do i=1,3
758 [ + + ]: 7839 : do j=1,3
759 : 5427 : rcexponent = 2*l +2*i+2*j-4
760 [ + + ]: 7236 : if(prefact_ijl(i,j,l,ipsp)/=0) then !vz_d 0**0
761 : : vso_radial(iradgrid,ipsp) = vso_radial(iradgrid,ipsp) + &
762 : 1005 : & prefact_ijl(i,j,l,ipsp)*(norm_rel_pos**rcexponent) * expfact
763 : : end if !vz_d
764 : : end do ! j
765 : : end do ! i
766 : : end do ! ipsp
767 : : end do ! iradgrid
768 : : end do ! lmax
769 : :
770 : : !spline v_SO(radial coord): get second derivative coefficients
771 [ - + + - : 2 : ABI_MALLOC(vso_radial_pp,(nradgrid,psps%npsp))
- + - + ]
772 : :
773 [ - + ]: 1 : ABI_MALLOC(tmp_spline,(nradgrid))
774 [ - + ]: 1 : ABI_MALLOC(tmpvso,(nradgrid))
775 [ - + ]: 1 : ABI_MALLOC(tmpvso_pp,(nradgrid))
776 [ + + ]: 2 : do ipsp=1,psps%npsp
777 [ - + + + ]: 203 : tmpvso = vso_radial(:,ipsp)
778 : 1 : call spline( radial_grid, tmpvso, nradgrid, zero, radial_grid(nradgrid), tmpvso_pp )
779 [ + + ]: 203 : vso_radial_pp(:,ipsp) = tmpvso_pp
780 : : end do
781 [ - + ]: 1 : ABI_FREE(tmp_spline)
782 [ - + ]: 1 : ABI_FREE(tmpvso)
783 [ - + ]: 1 : ABI_FREE(tmpvso_pp)
784 : :
785 : : !to optimize this I should precalculate the distances which are actually needed by
786 : : !symmetry, or only sum over irreducible points in space and use weights
787 : :
788 : : !for each physical atom present in unit cell
789 [ + + + + : 121522 : vso_realspace = zero
+ + + + +
+ ]
790 [ + + ]: 2 : do iatom=1,dtset%natom
791 : : ! atom type will be dtset%typat(iatom)
792 : :
793 : : ! for each point on grid
794 [ + + ]: 17 : do ir3=1,dtset%ngfft(3)
795 [ + + ]: 241 : do ir2=1,dtset%ngfft(2)
796 [ + + ]: 3615 : do ir1=1,dtset%ngfft(1)
797 : 3375 : irealsp = ir1 + (ir2-1)*dtset%ngfft(1) + (ir3-1)*dtset%ngfft(2)*dtset%ngfft(1)
798 : :
799 : : ! relative position from atom to point
800 [ + + ]: 13500 : relative_position = position_op(:,ir1,ir2,ir3) - xcart(:,iatom)
801 : 3375 : x=relative_position(1)
802 : 3375 : y=relative_position(2)
803 : 3375 : z=relative_position(3)
804 : :
805 : : ! calculate norm^2
806 : 3375 : norm_rel_pos = relative_position(1)**2+relative_position(2)**2+relative_position(3)**2
807 : :
808 : : ! if norm^2 is too large, skip this point
809 [ + + ]: 3375 : if (norm_rel_pos > radial_cutoff*radial_cutoff) cycle
810 : :
811 : : ! calculate norm
812 : 459 : splint_x(1) = sqrt(norm_rel_pos)
813 : :
814 : : ! spline interpolate vso only depends on position (through pos - atomic position)
815 : : call splint (nradgrid,radial_grid,vso_radial(:,dtset%typat(iatom)),&
816 : 459 : & vso_radial_pp(:,dtset%typat(iatom)),1,splint_x,splint_y)
817 : 459 : vso_interpol=splint_y(1)
818 : :
819 : : ! multiply by vectorial spin factor (S x r)
820 : : ! NOTE: this r is taken relative to atom center. It could be that the r operator should
821 : : ! applied in an absolute way wrt the origin...
822 : : !
823 : : ! Is this correct: accumulated sum over atoms ?
824 : : vso_realspace(1,irealsp,:,:,1) = vso_realspace(1,irealsp,:,:,1) + &
825 [ + + + + : 5049 : & vso_interpol * reshape((/y, zero,zero,-y/),(/2,2/))
+ + ]
826 : : vso_realspace(2,irealsp,:,:,1) = vso_realspace(2,irealsp,:,:,1) + &
827 [ + + + + : 5049 : & vso_interpol * reshape((/zero,z, -z, zero/),(/2,2/))
+ + ]
828 : :
829 : : vso_realspace(1,irealsp,:,:,2) = vso_realspace(1,irealsp,:,:,2) + &
830 [ + + + + : 5049 : & vso_interpol * reshape((/-x, z, z, x/),(/2,2/))
+ + ]
831 : : vso_realspace(2,irealsp,:,:,2) = vso_realspace(2,irealsp,:,:,2) + &
832 [ + + + + ]: 3213 : & vso_interpol * reshape((/zero,zero,zero,zero/),(/2,2/))
833 : :
834 : : vso_realspace(1,irealsp,:,:,3) = vso_realspace(1,irealsp,:,:,3) + &
835 [ + + + + : 5049 : & vso_interpol * reshape((/zero,-y, -y, zero/),(/2,2/))
+ + ]
836 : : vso_realspace(2,irealsp,:,:,3) = vso_realspace(2,irealsp,:,:,3) + &
837 [ + + + + : 8190 : & vso_interpol * reshape((/zero,-x, -x, zero/),(/2,2/))
+ + ]
838 : :
839 : : end do ! ir3
840 : : end do ! ir2
841 : : end do ! ir1
842 : : end do ! iatom
843 : :
844 [ - + ]: 1 : ABI_FREE(prefact_ijl)
845 [ - + ]: 1 : ABI_FREE(vso_radial)
846 [ - + ]: 1 : ABI_FREE(vso_radial_pp)
847 [ - + ]: 1 : ABI_FREE(radial_grid)
848 : :
849 : 1 : end subroutine vso_realspace_local
850 : : !!***
851 : :
852 : 171 : end module m_spin_current
853 : : !!***
|