Branch data Line data Source code
1 : : !{\src2tex{textfont=tt}}
2 : : !!****m* ABINIT/m_ddb_magpen
3 : : !! NAME
4 : : !! m_ddb_magpen
5 : : !!
6 : : !! FUNCTION
7 : : !! Convert second- and -third (Berry curvatures) order total energy derivatives
8 : : !! calculated with the magnetic penalty (constrained-B functional) into the
9 : : !! corresponding quantities of different magnetic functionals:
10 : : !! --constrained-M (fixed-spin)
11 : : !! --constrained-H (relaxed spin)
12 : : !! Calculate and write the ensuing clamped-ion susceptibilities. Lattice-mediated
13 : : !! contributions are incorporated in m_ddb_omega_interpol.
14 : : !!
15 : : !! COPYRIGHT
16 : : !! Copyright (C) 2023 ABINIT group (MR and MS)
17 : : !! This file is distributed under the terms of the
18 : : !! GNU General Public License, see ~abinit/COPYING
19 : : !! or http://www.gnu.org/copyleft/gpl.txt .
20 : : !!
21 : : !! NOTES
22 : : !!
23 : : !! PARENTS
24 : : !!
25 : : !! CHILDREN
26 : : !!
27 : : !! SOURCE
28 : :
29 : : #if defined HAVE_CONFIG_H
30 : : #include "config.h"
31 : : #endif
32 : :
33 : : #include "abi_common.h"
34 : :
35 : : module m_ddb_magpen
36 : :
37 : : use defs_basis
38 : : use m_abicore
39 : : use m_profiling_abi
40 : : use m_errors
41 : : use m_ddb
42 : : use m_fstrings, only : itoa, sjoin
43 : : use m_macroave, only : POLINT
44 : : use m_io_tools, only : open_file
45 : : use m_cgtools, only : fxphas_seq
46 : : use m_dynmat, only : pheigvec_normalize
47 : : use m_numeric_tools, only : polcoe
48 : :
49 : : implicit none
50 : :
51 : : public :: ddb_magpen ! Convert the derivatives calculated with the magnetic penalty into the physically relevant ones.
52 : : public :: local_spinsus ! Treat local spin susceptibility (2nd-order magnetic derivatives)
53 : : public :: magmom ! Treat first-order magnetic moments (2nd-order mixed derivatives)
54 : : public :: mp_d2etot ! Treat 2nd-order nonmagnetic derivatives
55 : : public :: asrw0 ! Apply the ASR correction calculated at w=0 at any value of w
56 : :
57 : : private
58 : :
59 : : ! *************************************************************************
60 : :
61 : : contains
62 : : !!***
63 : :
64 : : !!****f* m_ddb_magpen/ddb_magpen
65 : : !! NAME
66 : : !! ddb_magpen
67 : : !!
68 : : !! FUNCTION
69 : : !! Convert the second- and possibly third-order derivatives calculated with the magnetic penalty
70 : : !! into physically relevant quantities.
71 : : !!
72 : : !! INPUTS
73 : : !! ddb (INOUT) = ddb block datastructure
74 : : !! ddb_lw (INOUT) = ddb_lw block datastructure
75 : : !! magpen = amplitude (in Ha) of the applied magnetic penalty
76 : : !! mpatpol(2) = Atoms on which the magnetic penalty has been applied
77 : : !! mpdir(3) = Directions along which the spin-degrees of freedom have been stiffened
78 : : !! mpert = maximum number of ipert
79 : : !! mpopt = 1 calculate the frozen-magnetic second-order quantities
80 : : !! 2 calculate the spin-relaxed second-order quantities
81 : : !! natom= number of atoms in unit cell
82 : : !! ntypat= number of atom types
83 : : !! timdisp= 1 calculate the third-order Berry curvatures
84 : : !! ucvol= unit cell volume
85 : : !!
86 : : !! OUTPUT
87 : : !! ddb= ddb%val updated with the corrected second-order derivatives
88 : : !!
89 : : !! SOURCE
90 : :
91 : 3 : subroutine ddb_magpen(ddb,ddb_lw,&
92 : : & magpen,mpatpol,mpdir,mpert,mpopt,natom, &
93 : 3 : & prtvol,rftyp,ucvol,timdisp,xred)
94 : :
95 : : !Arguments -------------------------------
96 : : !scalars
97 : : integer,intent(in) :: mpert,mpopt,natom,prtvol,rftyp,timdisp
98 : : real(dp),intent(in) :: magpen,ucvol
99 : : !arrays
100 : : type(ddb_type),intent(inout) :: ddb,ddb_lw
101 : : integer,intent(in) :: mpatpol(2),mpdir(3)
102 : : real(dp),intent(in) :: xred(3,natom)
103 : :
104 : : !Local variables -------------------------
105 : : !scalars
106 : : integer :: iblok,ii,jblok,kblok,lblok,nblok,ndim
107 : : integer :: nmat,nmdir,optgb,prtopt
108 : : character(len=500) :: msg
109 : : logical :: qeq0
110 : : !arrays
111 : : integer :: rfelfd(4),rfphon(4),rfstrs(4),rfmagn(4),rffreq(4)
112 : : real(dp) :: omega(3),qphnrm(3),qphon(3,3),qpt(3)
113 : 3 : complex(dpc), allocatable :: barmagsus(:,:),invbarmagsus(:,:)
114 : 3 : complex(dpc), allocatable :: invmagsus(:,:), magsus(:,:), invhmat(:,:)
115 : 3 : complex(dpc), allocatable :: barmmom(:,:),barmmom_tr(:,:),mmom(:,:),mmom_tr(:,:)
116 : 3 : complex(dpc), allocatable :: zfield(:,:), zfield_tr(:,:)
117 : 3 : complex(dpc), allocatable :: bc_barmagsus(:,:),bc_ss(:,:),bc_sp(:,:)
118 : 3 : complex(dpc), allocatable :: ifcmat(:,:),ifcmat_fm(:,:),zeff(:,:),zeff_tr(:,:)
119 : 3 : complex(dpc), allocatable :: fmzeff(:,:),fmzeff_tr(:,:)
120 : 3 : complex(dpc), allocatable :: lm_epsilon(:,:),dum_phongreen(:,:)
121 : :
122 : : ! *********************************************************************
123 [ + + ]: 246 : write(msg, '(2a,(80a),6a)' ) ch10,('=',ii=1,80),ch10,ch10,&
124 : 3 : ' Constrained DFPT section ',ch10,ch10,&
125 [ + - ]: 249 : ' (Quantities are in atomic units and along Cartesian directions)'
126 [ + + ]: 9 : call wrtout([std_out, ab_out], msg)
127 : :
128 : 3 : prtopt=1
129 [ + - ]: 3 : if (magpen<zero) then
130 : : nmat= 1
131 [ + - ]: 3 : else if (magpen>zero) then
132 : 3 : nmat= mpatpol(2) - mpatpol(1) + 1
133 : : end if
134 [ + + ]: 12 : nmdir=sum(mpdir(:))
135 : 3 : ndim=nmat*nmdir
136 : 3 : optgb=1
137 [ - + + - : 12 : ABI_MALLOC(barmagsus,(ndim,ndim))
- + + - +
- + - - +
- + ]
138 [ - + + - : 9 : ABI_MALLOC(magsus,(ndim,ndim))
- + + - -
+ - + ]
139 [ - + + - : 9 : ABI_MALLOC(invbarmagsus,(ndim,ndim))
- + + - -
+ - + ]
140 [ - + + - : 9 : ABI_MALLOC(invmagsus,(ndim,ndim))
- + + - -
+ - + ]
141 [ - + + - : 9 : ABI_MALLOC(invhmat,(ndim,ndim))
- + + - -
+ - + ]
142 [ - + + - : 12 : ABI_MALLOC(barmmom,(ndim,(natom+5)*3))
+ - - + +
- + - + -
- + - + ]
143 [ - + + - : 9 : ABI_MALLOC(barmmom_tr,((natom+5)*3,ndim))
- + + - -
+ - + ]
144 [ - + + - : 9 : ABI_MALLOC(mmom,(ndim,(natom+5)*3))
- + + - -
+ - + ]
145 [ - + + - : 9 : ABI_MALLOC(mmom_tr,((natom+5)*3,ndim))
- + + - -
+ - + ]
146 [ - + + - : 9 : ABI_MALLOC(zfield,(ndim,(natom+5)*3))
- + + - -
+ - + ]
147 [ - + + - : 9 : ABI_MALLOC(zfield_tr,((natom+5)*3,ndim))
- + + - -
+ - + ]
148 : :
149 [ - + + - : 12 : ABI_MALLOC(ddb%val_fs,(2,ddb%msize,ddb%nblok))
- + + - +
- + - - +
- + - + ]
150 : : ! if (mpopt==2) ABI_MALLOC(ddb%val_rs,(2,ddb%msize,ddb%nblok))
151 [ - + + - : 9 : ABI_MALLOC(ddb%val_rs,(2,ddb%msize,ddb%nblok))
- + + - -
+ - + -
+ ]
152 : :
153 [ + - - + : 15 : ABI_MALLOC(ifcmat,(3*natom,3*natom))
+ - - + +
- + - + -
- + - + ]
154 [ - + + - : 9 : ABI_MALLOC(ifcmat_fm,(3*natom,3*natom))
- + + - -
+ - + ]
155 [ - + + - : 9 : ABI_MALLOC(fmzeff,(3,3*natom))
+ - + - -
+ - + ]
156 [ - + + - : 9 : ABI_MALLOC(fmzeff_tr,(3*natom,3))
+ - - + -
+ ]
157 [ - + + - : 6 : ABI_MALLOC(zeff,(3,3*natom))
- + - + ]
158 [ - + + - : 6 : ABI_MALLOC(zeff_tr,(3*natom,3))
- + - + ]
159 [ - + ]: 3 : ABI_MALLOC(lm_epsilon,(3,3))
160 [ - + + - : 9 : ABI_MALLOC(dum_phongreen,(3*natom,3*natom))
- + + - -
+ - + ]
161 : :
162 : 3 : nblok=ddb%nblok
163 [ + + ]: 7 : do kblok=1,nblok
164 : :
165 : : ! Look for the local spin-susceptibility block in the DDB
166 : 4 : omega=zero
167 : 4 : qphon=zero
168 [ + + ]: 16 : qphon(:,1)=ddb%qpt(1:3,kblok)
169 [ + + ]: 16 : qpt=qphon(:,1)
170 [ + + ]: 16 : qeq0=(sqrt(sum(qphon(:,1)**2))<tol8)
171 [ + + ]: 16 : qphnrm(:)=ddb%nrm(1,kblok)
172 : 4 : omega(1)=ddb%omega(1,kblok)
173 [ + + ]: 12 : rfphon(1:2)=0
174 [ + + ]: 12 : rfelfd(1:2)=0
175 [ + + ]: 12 : rfstrs(1:2)=0
176 [ - + ]: 4 : if (magpen<zero) then
177 [ # # ]: 0 : rfmagn(1:2)= 1
178 [ + - ]: 4 : else if (magpen>zero) then
179 [ + + ]: 12 : rfmagn(1:2)= 2
180 : : end if
181 : :
182 [ + + ]: 328 : write(msg, '(1a,(80a),2a,3f16.8,2a,f16.8,a)' ) ch10,('-',ii=1,80),ch10, &
183 : 4 : ' q point ', qphon(:,1),ch10,&
184 [ + - ]: 332 : ' frequency', ddb%omega(1,kblok), ch10
185 [ + + ]: 12 : call wrtout([std_out, ab_out], msg)
186 : :
187 : : call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, &
188 : 4 : & mpatpol=mpatpol,mpdir=mpdir,omega=omega,rfmagn=rfmagn)
189 : :
190 : : ! Calculate and write the spin-susceptibility matrices
191 [ + - ]: 4 : if (iblok /= 0) then
192 [ + - ]: 4 : if (prtvol>1) then
193 [ - + ]: 4 : if (magpen<zero) then
194 : 0 : write(msg, '(2a)' ) ' Spin susceptibility (Uniform Zeeman) ',ch10
195 [ # # ]: 0 : call wrtout([std_out, ab_out], msg)
196 [ + - ]: 4 : else if (magpen>zero) then
197 : 4 : write(msg, '(2a)' ) ' Spin susceptibility (Local Zeeman) ',ch10
198 [ + + ]: 12 : call wrtout([std_out, ab_out], msg)
199 : : end if
200 : : end if
201 : :
202 : : call local_spinsus(barmagsus,ddb,iblok,invbarmagsus,invmagsus,invhmat,magpen,magsus,&
203 : 4 : & mpatpol,mpdir,mpert,natom,ndim,nmdir,prtopt,prtvol,qpt,xred)
204 : :
205 : : end if
206 : :
207 : : ! Calculate and write the induced magnetic moments
208 [ + - ]: 4 : if (prtvol>1) then
209 [ + + ]: 328 : write(msg, '(2a,(80a),4a)' ) ch10,('-',ii=1,80),ch10,ch10,&
210 [ + - ]: 332 : ' First-order magnetic moments ',ch10
211 [ + + ]: 12 : call wrtout([std_out, ab_out], msg)
212 : : end if
213 : :
214 : : ! First atomic-displacement
215 : 4 : rfphon(2)=1
216 [ + + ]: 12 : rfelfd(1:2)=0
217 [ + + ]: 12 : rfstrs(1:2)=0
218 : 4 : rfmagn(:)=0
219 [ - + ]: 4 : if (magpen<zero) then
220 : 0 : rfmagn(1)= 1
221 [ + - ]: 4 : else if (magpen>zero) then
222 : 4 : rfmagn(1)= 2
223 : : end if
224 : :
225 : : call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, &
226 : 4 : & mpatpol=mpatpol,mpdir=mpdir,omega=omega,rfmagn=rfmagn)
227 : :
228 : : ! Then electric field
229 : : ! Look for the induced magnetic moments block in the DDB
230 : 4 : jblok=0
231 [ + + ]: 4 : if (qeq0) then
232 : 3 : rfphon(2)=0
233 : 3 : rfelfd(2)=2
234 [ + + ]: 9 : rfstrs(1:2)=0
235 : 3 : rfmagn(:)=0
236 [ - + ]: 3 : if (magpen<zero) then
237 : 0 : rfmagn(1)= 1
238 [ + - ]: 3 : else if (magpen>zero) then
239 : 3 : rfmagn(1)= 2
240 : : end if
241 : :
242 : : call ddb%get_block(jblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, &
243 : 3 : & mpatpol=mpatpol,mpdir=mpdir,omega=omega,rfmagn=rfmagn)
244 : : end if
245 : :
246 : : ! Then macroscopic Zeeman field
247 : : ! Look for the induced magnetic moments block in the DDB
248 : : lblok=0
249 : 4 : rfphon(:)=0
250 : 4 : rfelfd(:)=0
251 [ + + ]: 12 : rfstrs(1:2)=0
252 : 4 : rfmagn(2)=1
253 [ - + ]: 4 : if (magpen<zero) then
254 : 0 : rfmagn(1)= 1
255 [ + - ]: 4 : else if (magpen>zero) then
256 : 4 : rfmagn(1)= 2
257 : : end if
258 : :
259 : : call ddb%get_block(lblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, &
260 : 4 : & mpatpol=mpatpol,mpdir=mpdir,omega=omega,rfmagn=rfmagn)
261 : :
262 [ - + - - : 4 : if (iblok /= 0 .or. jblok /=0 .or. lblok/=0) then
- - ]
263 : : call magmom(barmmom,barmmom_tr,ddb,invbarmagsus,invhmat,iblok,jblok,lblok,magpen,magsus,mmom,mmom_tr,&
264 : 4 : & mpatpol,mpdir,mpert,natom,ndim,nmdir,prtopt,prtvol,qpt,xred,zfield,zfield_tr)
265 : : end if
266 : :
267 : : !Now calculate the non-magnetic second-order quantities
268 [ + + ]: 328 : write(msg, '(2a,(80a),4a)' ) ch10,('-',ii=1,80),ch10,ch10,&
269 [ + - ]: 332 : ' Second-order linear-response tensors ',ch10
270 [ + + ]: 12 : call wrtout([std_out, ab_out], msg)
271 : :
272 : : !Convert ddb%val to second-order energies
273 : 4 : call ddb%to_d2etot(ddb%val,kblok,0,qeq0,qphon,qphnrm,ucvol,optgb,omega=omega)
274 : :
275 : : !Convert second-order derivatives to diferent magnetic boundary conditions
276 : : call mp_d2etot(barmagsus,ddb,kblok,magsus,mpert,mpopt,natom, &
277 : 4 : & ndim,zfield,zfield_tr)
278 : :
279 : : !Convert second-order energies to the physical quantities of ddb%val
280 : 4 : call ddb%to_d2etot(ddb%val,kblok,1,qeq0,qphon,qphnrm,ucvol,optgb,omega=omega)
281 : 4 : call ddb%to_d2etot(ddb%val_fs,kblok,1,qeq0,qphon,qphnrm,ucvol,optgb,omega=omega)
282 [ + - ]: 4 : if (mpopt==2) call ddb%to_d2etot(ddb%val_rs,kblok,1,qeq0,qphon,qphnrm,ucvol,optgb,omega=omega)
283 : :
284 : : !Print the physical quantities in the new magnetic boundary conditions
285 : : if (prtopt==1) then
286 [ - + ]: 4 : if (mpopt==1) then
287 : 0 : call mp_d2etot_print(ddb,ddb%val_fs,kblok,mpert,natom,nblok,1,omega,qeq0,qphnrm,qphon,ddb%msize)
288 [ + - ]: 4 : else if (mpopt==2) then
289 : 4 : call mp_d2etot_print(ddb,ddb%val_rs,kblok,mpert,natom,nblok,2,omega,qeq0,qphnrm,qphon,ddb%msize)
290 : : end if
291 : : end if
292 : :
293 : 4 : rfmagn(:)=0
294 : 4 : rfelfd(:)=0
295 : 7 : rfphon(:)=0
296 : :
297 : : end do
298 : :
299 : : ! BERRY CURVATURES
300 [ + + ]: 3 : if (timdisp==1) then
301 : :
302 [ - + + - : 8 : ABI_MALLOC(ddb_lw%val_fs,(2,ddb_lw%msize,ddb_lw%nblok))
- + + - +
- + - - +
- + - + ]
303 : :
304 [ - + + - : 6 : ABI_MALLOC(bc_barmagsus,(ndim,ndim))
- + + - -
+ - + ]
305 [ - + + - : 6 : ABI_MALLOC(bc_ss,(ndim,ndim))
- + + - -
+ - + ]
306 [ - + + - : 6 : ABI_MALLOC(bc_sp,(ndim,(natom+5)*3))
- + + - -
+ - + ]
307 : :
308 [ + + ]: 164 : write(msg, '(2a,(80a),4a)' ) ch10,('=',ii=1,80),ch10,ch10,&
309 [ + - ]: 166 : ' Frequency-derivatives (Berry curvatures) constrained DFPT section ',ch10
310 [ + + ]: 6 : call wrtout([std_out, ab_out], msg)
311 : :
312 : 2 : rffreq(:)=0
313 : 2 : nblok=ddb_lw%nblok
314 [ + + ]: 6 : do kblok=1,nblok
315 : :
316 [ + + ]: 4 : if (ddb_lw%typ(kblok)/=33) cycle
317 : :
318 : : !Berry curvature of the penalized spin-susceptibility
319 : 2 : qphon=zero
320 [ + + ]: 8 : qphon(:,1)=ddb_lw%qpt(1:3,kblok)
321 [ + + ]: 8 : qpt= qphon(:,1)
322 [ + + ]: 8 : qphnrm(:)=ddb_lw%nrm(1,kblok)
323 [ + + ]: 8 : omega(:)=ddb_lw%omega(:,kblok)
324 [ + + ]: 8 : rfphon(1:3)=0
325 [ + + ]: 8 : rfelfd(1:3)=0
326 [ + + ]: 8 : rfstrs(1:3)=0
327 : 2 : rffreq(3)=1
328 : 2 : iblok=0
329 [ - + ]: 2 : if (magpen<zero) then
330 [ # # ]: 0 : rfmagn(1:2)= 1
331 [ + - ]: 2 : else if (magpen>zero) then
332 [ + + ]: 6 : rfmagn(1:2)= 2
333 : : end if
334 : :
335 [ + + ]: 164 : write(msg, '(a,(80a),a,3(a,3f16.8,a),3(a,f16.8,a))' ) ch10,('-',ii=1,80),ch10, &
336 : 2 : ' q point 1 ', qphon(:,1),ch10,&
337 : 2 : ' q point 2 ', qphon(:,2),ch10,&
338 : 2 : ' q point 3 ', qphon(:,3),ch10,&
339 : 2 : ' frequency 1', ddb_lw%omega(1,kblok), ch10,&
340 : 2 : ' frequency 2', ddb_lw%omega(2,kblok), ch10,&
341 [ + - ]: 166 : ' frequency 3', ddb_lw%omega(3,kblok), ch10
342 [ + + ]: 6 : call wrtout([std_out, ab_out], msg)
343 : :
344 : : call ddb_lw%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, 33, &
345 : 2 : & mpatpol=mpatpol,mpdir=mpdir,omega=omega,rfmagn=rfmagn,rffreq=rffreq)
346 : :
347 [ + - ]: 2 : if (iblok /= 0) then
348 : : call berrycurv_ss(bc_barmagsus,bc_ss,ddb_lw,iblok,invbarmagsus,mpatpol,mpdir,mpert,&
349 : 2 : & natom,ndim,nmdir,prtvol,qpt,xred)
350 : : end if
351 : :
352 : : !Berry curvature of the induced Zeeman fields
353 : :
354 : : !First atomic-displacement
355 : : iblok=0
356 : 2 : rfphon(2)=1
357 : 2 : rfmagn(:)=0
358 [ - + ]: 2 : if (magpen<zero) then
359 : 0 : rfmagn(1)= 1
360 [ + - ]: 2 : else if (magpen>zero) then
361 : 2 : rfmagn(1)= 2
362 : : end if
363 : :
364 : : call ddb_lw%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, 33, &
365 : 2 : & mpatpol=mpatpol,mpdir=mpdir,omega=omega,rfmagn=rfmagn,rffreq=rffreq)
366 : :
367 : : ! Then electric field
368 : 2 : jblok=0
369 [ + + ]: 2 : if (qeq0) then
370 : 1 : rfphon(2)=0
371 : 1 : rfelfd(2)=2
372 : :
373 : : call ddb_lw%get_block(jblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, 33, &
374 : 1 : & mpatpol=mpatpol,mpdir=mpdir,omega=omega,rfmagn=rfmagn,rffreq=rffreq)
375 : : end if
376 : :
377 : : ! Then macroscopic Zeeman field
378 : 2 : lblok=0
379 [ + + ]: 2 : if (qeq0) then
380 : 1 : rfelfd(2)=0
381 : 1 : rfmagn(2)=1
382 : :
383 : : call ddb_lw%get_block(lblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, 33, &
384 : 1 : & mpatpol=mpatpol,mpdir=mpdir,omega=omega,rfmagn=rfmagn,rffreq=rffreq)
385 : : end if
386 : :
387 [ - + - - : 2 : if (iblok /= 0 .or. jblok /=0 .or. lblok /= 0) then
- - ]
388 : : call berrycurv_sp(barmmom,bc_sp,bc_ss,ddb_lw,iblok,invbarmagsus,jblok,lblok, &
389 : 2 : & mpatpol,mpdir,mpert,natom,ndim,nmdir,prtvol,qpt,xred)
390 : : end if
391 : :
392 : : !Berry curvature of other second-order quantites
393 : : call berrycurv_pp(barmagsus,bc_barmagsus,bc_sp,ddb_lw,kblok, &
394 : 2 : & mpert,natom,ndim,qeq0,ucvol,zfield)
395 : :
396 : : !Print them
397 : : call mp_d3etot_print(ddb_lw,ddb_lw%val_fs,kblok,mpert,natom,nblok,1,omega,&
398 : 6 : & prtvol,qeq0,qphnrm,qphon,ucvol,ddb_lw%msize)
399 : :
400 : : end do
401 [ - + ]: 2 : ABI_FREE(bc_ss)
402 [ - + ]: 2 : ABI_FREE(bc_sp)
403 [ - + ]: 2 : ABI_FREE(bc_barmagsus)
404 : : end if
405 : :
406 : : !Deallocations
407 [ - + ]: 3 : ABI_FREE(barmagsus)
408 [ - + ]: 3 : ABI_FREE(barmmom)
409 [ - + ]: 3 : ABI_FREE(barmmom_tr)
410 [ - + ]: 3 : ABI_FREE(magsus)
411 [ - + ]: 3 : ABI_FREE(invbarmagsus)
412 [ - + ]: 3 : ABI_FREE(invmagsus)
413 [ - + ]: 3 : ABI_FREE(mmom)
414 [ - + ]: 3 : ABI_FREE(mmom_tr)
415 [ - + ]: 3 : ABI_FREE(zfield)
416 [ - + ]: 3 : ABI_FREE(zfield_tr)
417 [ - + ]: 3 : ABI_FREE(ifcmat)
418 [ - + ]: 3 : ABI_FREE(ifcmat_fm)
419 [ - + ]: 3 : ABI_FREE(zeff)
420 [ - + ]: 3 : ABI_FREE(zeff_tr)
421 [ - + ]: 3 : ABI_FREE(fmzeff)
422 [ - + ]: 3 : ABI_FREE(fmzeff_tr)
423 [ - + ]: 3 : ABI_FREE(lm_epsilon)
424 [ - + ]: 3 : ABI_FREE(dum_phongreen)
425 [ - + ]: 3 : ABI_FREE(invhmat)
426 : :
427 : 3 : end subroutine ddb_magpen
428 : : !!***
429 : :
430 : : !!****f* m_ddb_magpen/local_spinsus
431 : : !! NAME
432 : : !! local_spinsus
433 : : !!
434 : : !! FUNCTION
435 : : !! Calculate the spin-susceptibility matrix and its inverse
436 : : !!
437 : : !! INPUTS
438 : : !! ddb= Second-order derivative arrais
439 : : !! iblok= index of the current block
440 : : !! magpen = amplitude (in Ha) of the applied magnetic penalty
441 : : !! mpatpol(2) = Atoms on which the magnetic penalty has been applied
442 : : !! mpdir(3) = Directions along which the spin-degrees of freedom have been stiffened
443 : : !! mpert =maximum number of ipert
444 : : !! natom= number of atoms in unit cell
445 : : !! nblok= number of blocks in the DDB
446 : : !! nmdir= number of directions along which the magnetic penalty was applied
447 : : !! ndim= dimension of the square susceptibilities
448 : : !! prtvol= control the volume of information written on output
449 : : !! fs2rs= (optional) if 1, the routine starts from a precalculated blkval_fs
450 : : !! blkval_fs(2,3,mpert,3,mpert)= fixed-spin 2nd-order derivatives
451 : : !! xred(3,natom)= reduced atomic coordinates
452 : : !!
453 : : !! OUTPUT
454 : : !! barmagsus(ndim,ndim)= Penalized spin-sussceptibility tensor
455 : : !! invbarmagsus(ndim,ndim)= Inverse of the penalized spin-sussceptibility tensor
456 : : !! magsus(ndim,ndim)= Spin-sussceptibility tensor
457 : : !! invmagsus(ndim,ndim)= Inverse of spin-sussceptibility tensor
458 : : !!
459 : : !! SOURCE
460 : :
461 : 68 : subroutine local_spinsus(barmagsus,ddb,iblok,invbarmagsus,invmagsus,invhmat,magpen,magsus, &
462 : 34 : & mpatpol,mpdir,mpert,natom,ndim,nmdir,prtopt,prtvol,qphon,xred, &
463 : 30 : & fs2rs,blkval_fs) !optional
464 : :
465 : : !Arguments -------------------------------
466 : : !scalars
467 : : integer,intent(in) :: iblok,mpert,natom,ndim,nmdir
468 : : integer,intent(in) :: prtopt,prtvol
469 : : integer,intent(in),optional :: fs2rs
470 : : real(dp),intent(in) :: magpen
471 : : !arrays
472 : : type(ddb_type),intent(inout) :: ddb
473 : : integer,intent(in) :: mpatpol(2),mpdir(3)
474 : : real(dp),intent(in),optional :: blkval_fs(2,3,mpert,3,mpert,1)
475 : : real(dp),intent(in) :: qphon(3),xred(3,natom)
476 : : complex(dpc),intent(out) :: barmagsus(ndim,ndim)
477 : : complex(dpc),intent(out) :: invbarmagsus(ndim,ndim)
478 : : complex(dpc),intent(out) :: invhmat(ndim,ndim)
479 : : complex(dpc),intent(out) :: magsus(ndim,ndim)
480 : : complex(dpc),intent(out) :: invmagsus(ndim,ndim)
481 : :
482 : : !Local variables -------------------------
483 : : !scalars
484 : : integer :: fs2rs_
485 : : integer :: iat1,iat2,icol,idir1,idir2,index,info,ipert1,ipert2,irow,lwork
486 : : integer :: ipert1_red,ipert2_red,idir1_red,idir2_red
487 : : !real(dp) :: fac
488 : : character(len=1000) :: msg
489 : : !arrays
490 : 68 : complex(dpc) :: idty(ndim,ndim)
491 : 34 : integer :: indexat(ndim),indexdir(ndim)
492 : 34 : integer, allocatable :: ipiv(:)
493 : 34 : complex(dpc),allocatable :: work(:),work1(:,:),work2(:,:)
494 : : character(len=1) :: cart(3)=(/'x','y','z'/)
495 : :
496 : : ! *********************************************************************
497 : :
498 : : !If fixed-spin case has been precalculated do less stuff
499 [ + + ]: 34 : fs2rs_=0; if (present(fs2rs)) fs2rs_=fs2rs
500 [ + - ]: 30 : if (fs2rs_==1) then
501 [ - + ]: 30 : if (.not.present(blkval_fs)) then
502 : 0 : write(msg, '(3a)' )' No fixed-spin array has been passed to local_spinsus', &
503 : 0 : & ' but fs2rs=1 ',ch10
504 : 0 : ABI_ERROR(msg)
505 : : end if
506 : : end if
507 : :
508 : : !Extract the penalized susceptibility
509 [ + + + + ]: 714 : idty=(zero,zero)
510 : 34 : ipert2_red= 0
511 [ + + ]: 102 : do iat2= mpatpol(1), mpatpol(2)
512 : 68 : ipert2= natom + 11 + iat2
513 : 68 : ipert2_red= ipert2_red + 1
514 : 68 : idir2_red= 0
515 [ + + ]: 306 : do idir2= 1, 3
516 [ + + ]: 204 : if (mpdir(idir2)==0) cycle
517 : 136 : idir2_red= idir2_red + 1
518 : 136 : icol=idir2_red+(ipert2_red-1)*nmdir
519 : 136 : indexat(icol)=iat2
520 : 136 : indexdir(icol)=idir2
521 : 136 : idty(icol,icol)=(one,zero)
522 : 136 : ipert1_red=0
523 [ + + ]: 476 : do iat1= mpatpol(1), mpatpol(2)
524 : 272 : ipert1= natom + 11 + iat1
525 : 272 : ipert1_red= ipert1_red + 1
526 : 272 : idir1_red= 0
527 [ + + ]: 1292 : do idir1= 1, 3
528 [ + + ]: 816 : if (mpdir(idir1)==0) cycle
529 : 544 : idir1_red=idir1_red+1
530 : 544 : irow=idir1_red+(ipert1_red-1)*nmdir
531 : 544 : index= idir1 + 3*((ipert1-1)+mpert*((idir2-1)+3*(ipert2-1)))
532 : :
533 : : !Apply a phase factor to adopt the same Gonze&Lee convention as for atomic
534 : : !displacements at finite q (See M. Stengel PRB 2013).
535 [ + + ]: 816 : if (fs2rs_==0) then
536 : : barmagsus(irow,icol)= &
537 : : & cmplx(ddb%val(1,index,iblok),ddb%val(2,index,iblok),kind=dpc) &
538 [ + + ]: 256 : & * exp(two_pi*(0.d0,1.d0)*dot_product(qphon,xred(:,iat1)-xred(:,iat2)))
539 [ - + ]: 480 : else if (fs2rs_==1) then
540 : : invmagsus(irow,icol)= &
541 : : & cmplx(blkval_fs(1,idir1,ipert1,idir2,ipert2,iblok), &
542 [ + - ]: 480 : & blkval_fs(2,idir1,ipert1,idir2,ipert2,iblok),kind=dpc)
543 : : end if
544 : :
545 : : end do
546 : : end do
547 : : end do
548 : : end do
549 : :
550 : : !Use magsus to store the intermediate array
551 [ + + + + ]: 714 : magsus=idty-magpen*barmagsus
552 : :
553 : : !Invert the arrays
554 [ - + + - : 136 : ABI_MALLOC(work1,(ndim,ndim))
- + + - +
- + - - +
- + ]
555 [ - + + - : 102 : ABI_MALLOC(work2,(ndim,ndim))
- + + - -
+ - + ]
556 [ + + ]: 34 : if (fs2rs_==0) then
557 [ - + + + : 88 : work1=barmagsus
+ + ]
558 [ + - ]: 30 : else if (fs2rs_==1) then
559 [ - + + + : 660 : work1=invmagsus
+ + ]
560 : : end if
561 [ - + + + : 748 : work2=magsus
+ + ]
562 : :
563 [ - + + - : 102 : ABI_MALLOC(ipiv,(ndim))
+ - + - -
+ - + ]
564 : 34 : call zgetrf( ndim, ndim, work1, ndim, ipiv, info )
565 [ - + ]: 34 : ABI_CHECK(info == 0, sjoin('zgetrf returned:', itoa(info)))
566 : :
567 [ - + ]: 34 : ABI_MALLOC(work,(2))
568 : 34 : call zgetri( ndim, work1, ndim, ipiv, work, -1, info )
569 [ - + ]: 34 : ABI_CHECK(info == 0, sjoin('zgetri returned:', itoa(info)))
570 : 34 : lwork=int(work(1))
571 : :
572 [ - + + - : 102 : ABI_REMALLOC(work,(lwork))
+ - + - -
+ - + -
+ ]
573 : 34 : call zgetri( ndim, work1, ndim, ipiv, work, lwork, info )
574 [ - + ]: 34 : ABI_CHECK(info == 0, sjoin('zgetri returned:', itoa(info)))
575 : :
576 [ + + ]: 34 : if (fs2rs_==1) then
577 [ + + + + ]: 630 : magsus=work1
578 [ + - ]: 30 : ABI_SFREE(ipiv)
579 [ + - ]: 30 : ABI_SFREE(work1)
580 [ + - ]: 30 : ABI_SFREE(work2)
581 [ + - ]: 30 : ABI_SFREE(work)
582 : 30 : return
583 : : end if
584 : :
585 : 4 : call zgetrf( ndim, ndim, work2, ndim, ipiv, info )
586 [ - + ]: 4 : ABI_CHECK(info == 0, sjoin('zgetrf returned:', itoa(info)))
587 : :
588 : 4 : call zgetri( ndim, work2, ndim, ipiv, work, -1, info )
589 [ - + ]: 4 : ABI_CHECK(info == 0, sjoin('zgetri returned:', itoa(info)))
590 : 4 : lwork=int(work(1))
591 : :
592 [ - + + - : 12 : ABI_REMALLOC(work,(lwork))
+ - + - -
+ - + -
+ ]
593 : 4 : call zgetri( ndim, work2, ndim, ipiv, work, lwork, info )
594 [ - + ]: 4 : ABI_CHECK(info == 0, sjoin('zgetri returned:', itoa(info)))
595 [ - + ]: 4 : ABI_FREE(work)
596 : :
597 : : !Write the results in meaningfull arrays
598 [ + + + + ]: 84 : invbarmagsus=work1
599 : :
600 : : !At last, calculate the susceptibility and its inverse
601 [ + + + + ]: 84 : invhmat=work2
602 [ + - + + : 420 : magsus=matmul(work2,barmagsus)
+ + + + +
+ + + ]
603 [ + + + + ]: 84 : invmagsus=invbarmagsus-magpen*idty
604 : :
605 [ - + ]: 4 : ABI_FREE(ipiv)
606 [ - + ]: 4 : ABI_FREE(work1)
607 [ - + ]: 4 : ABI_FREE(work2)
608 : :
609 [ + - + - ]: 4 : if (prtopt==1.and.prtvol>1) then
610 : :
611 : : !Write results in output
612 [ + - ]: 4 : if (magpen > zero) then
613 [ + + ]: 12 : call wrtout([ab_out,std_out], ' Local spin susceptibility ')
614 [ + + ]: 12 : call wrtout([ab_out,std_out], ' atom1 dir atom2 dir Real Imag')
615 [ + + ]: 20 : do irow=1, ndim
616 [ + + ]: 84 : do icol=1, ndim
617 : : write(msg,'(2(i4,4x,a2,2x),2x,2es18.9)' ) &
618 : 64 : & indexat(irow), cart(indexdir(irow)), indexat(icol), cart(indexdir(icol)), &
619 : 128 : & real(magsus(irow,icol)), aimag(magsus(irow,icol))
620 [ + + ]: 208 : call wrtout([ab_out,std_out], msg)
621 : : end do
622 : : end do
623 [ + + ]: 12 : call wrtout([ab_out,std_out], ' ')
624 : :
625 [ + + ]: 12 : call wrtout([ab_out,std_out], ' Inverse of local spin susceptibility ')
626 [ + + ]: 12 : call wrtout([ab_out,std_out], ' atom1 dir atom2 dir Real Imag')
627 [ + + ]: 20 : do irow=1, ndim
628 [ + + ]: 84 : do icol=1, ndim
629 : : write(msg,'(2(i4,4x,a2,2x),2x,2es18.9)' ) &
630 : 64 : & indexat(irow), cart(indexdir(irow)), indexat(icol), cart(indexdir(icol)), &
631 : 128 : & real(invmagsus(irow,icol)), aimag(invmagsus(irow,icol))
632 [ + + ]: 208 : call wrtout([ab_out,std_out], msg)
633 : : end do
634 : : end do
635 [ + + ]: 12 : call wrtout([ab_out,std_out], ' ')
636 : :
637 [ + - ]: 4 : if (prtvol > 2) then
638 [ + + ]: 12 : call wrtout([ab_out,std_out], ' Penalized local spin susceptibility ')
639 [ + + ]: 12 : call wrtout([ab_out,std_out], ' atom1 dir atom2 dir Real Imag')
640 [ + + ]: 20 : do irow=1, ndim
641 [ + + ]: 84 : do icol=1, ndim
642 : : write(msg,'(2(i4,4x,a2,2x),2x,2es18.9)' ) &
643 : 64 : & indexat(irow), cart(indexdir(irow)), indexat(icol), cart(indexdir(icol)), &
644 : 128 : & real(barmagsus(irow,icol)), aimag(barmagsus(irow,icol))
645 [ + + ]: 208 : call wrtout([ab_out,std_out], msg)
646 : : end do
647 : : end do
648 [ + + ]: 12 : call wrtout([ab_out,std_out], ' ')
649 : :
650 [ + + ]: 12 : call wrtout([ab_out,std_out], ' Inverse of penalized local spin susceptibility ')
651 [ + + ]: 12 : call wrtout([ab_out,std_out], ' atom1 dir atom2 dir Real Imag')
652 [ + + ]: 20 : do irow=1, ndim
653 [ + + ]: 84 : do icol=1, ndim
654 : : write(msg,'(2(i4,4x,a2,2x),2x,2es18.9)' ) &
655 : 64 : & indexat(irow), cart(indexdir(irow)), indexat(icol), cart(indexdir(icol)), &
656 : 128 : & real(invbarmagsus(irow,icol)), aimag(invbarmagsus(irow,icol))
657 [ + + ]: 208 : call wrtout([ab_out,std_out], msg)
658 : : end do
659 : : end do
660 [ + + ]: 12 : call wrtout([ab_out,std_out], ' ')
661 : :
662 [ + + ]: 12 : call wrtout([ab_out,std_out], ' Inverse of H matrix (I-alpha barchi)^{-1} ')
663 [ + + ]: 12 : call wrtout([ab_out,std_out], ' atom1 dir atom2 dir Real Imag')
664 [ + + ]: 20 : do irow=1, ndim
665 [ + + ]: 84 : do icol=1, ndim
666 : : write(msg,'(2(i4,4x,a2,2x),2x,2es18.9)' ) &
667 : 64 : & indexat(irow), cart(indexdir(irow)), indexat(icol), cart(indexdir(icol)), &
668 : 128 : & real(invhmat(irow,icol)), aimag(invhmat(irow,icol))
669 [ + + ]: 208 : call wrtout([ab_out,std_out], msg)
670 : : end do
671 : : end do
672 [ + + ]: 12 : call wrtout([ab_out,std_out], ' ')
673 : : end if
674 : :
675 : : end if !magpen>zero
676 : :
677 : : end if !prtopt
678 : :
679 : : !Store the FS and RS flavors on the DDB array
680 : : ipert2_red= 0
681 [ + + ]: 12 : do iat2= mpatpol(1), mpatpol(2)
682 : 8 : ipert2= natom + 11 + iat2
683 : 8 : ipert2_red= ipert2_red + 1
684 : 8 : idir2_red= 0
685 [ + + ]: 36 : do idir2= 1, 3
686 [ + + ]: 24 : if (mpdir(idir2)==0) cycle
687 : 16 : idir2_red= idir2_red + 1
688 : 16 : icol=idir2_red+(ipert2_red-1)*nmdir
689 : 16 : ipert1_red=0
690 [ + + ]: 56 : do iat1= mpatpol(1), mpatpol(2)
691 : 32 : ipert1= natom + 11 + iat1
692 : 32 : ipert1_red= ipert1_red + 1
693 : 32 : idir1_red= 0
694 [ + + ]: 152 : do idir1= 1, 3
695 [ + + ]: 96 : if (mpdir(idir1)==0) cycle
696 : 64 : idir1_red=idir1_red+1
697 : 64 : irow=idir1_red+(ipert1_red-1)*nmdir
698 : 64 : index= idir1 + 3*((ipert1-1)+mpert*((idir2-1)+3*(ipert2-1)))
699 : :
700 : 64 : ddb%val_fs(1,index,iblok)=real(invmagsus(irow,icol))
701 : 64 : ddb%val_fs(2,index,iblok)=aimag(invmagsus(irow,icol))
702 : :
703 : 64 : ddb%val_rs(1,index,iblok)=real(magsus(irow,icol))
704 : 128 : ddb%val_rs(2,index,iblok)=aimag(magsus(irow,icol))
705 : :
706 : : end do
707 : : end do
708 : : end do
709 : : end do
710 : :
711 [ + + + - ]: 64 : end subroutine local_spinsus
712 : : !!***
713 : :
714 : : !!****f* m_ddb_magpen/magmom
715 : : !! NAME
716 : : !! magmom
717 : : !!
718 : : !! FUNCTION
719 : : !! Calculate the first-order magnetic moments and the constrained
720 : : !! Zeeman fields
721 : : !!
722 : : !! INPUTS
723 : : !! ddb= Second-order derivative arrais
724 : : !! invbarmagsus(ndim,ndim)= Inverse of the penalized spin-sussceptibility tensor
725 : : !! iblok= index of the atomic displacement block
726 : : !! jblok= index of the electric field block
727 : : !! magsus(ndim,ndim)= Spin-sussceptibility tensor
728 : : !! magpen = amplitude (in Ha) of the applied magnetic penalty
729 : : !! mpatpol(2) = Atoms on which the magnetic penalty has been applied
730 : : !! mpdir(3) = Directions along which the spin-degrees of freedom have been stiffened
731 : : !! mpert =maximum number of ipert
732 : : !! natom= number of atoms in unit cell
733 : : !! nblok= number of blocks in the DDB
734 : : !! nmdir= number of directions along which the magnetic penalty was applied
735 : : !! ndim= dimension of the square susceptibilities
736 : : !! prtvol= control the volume of information written on output
737 : : !! fs2rs= (optional) if 1, the routine starts from a precalculated blkval_fs
738 : : !! blkval_fs(2,3,mpert,3,mpert)= fixed-spin 2nd-order derivatives
739 : : !!
740 : : !! OUTPUT
741 : : !! barmmom(ndim,(natom+2)*3)= penalized first order magnetic moments on the atoms and
742 : : !! directions of the penalty induced by atomic displacements and/or electric fields.
743 : : !! mmom(ndim,(natom+2)*3)= first order magnetic moments on the atoms and
744 : : !! directions of the penalty induced by atomic displacements and/or electric fields.
745 : : !! zfield(ndim,(natom+2)*3)= Zeeman fields at constrained magnetic moments.
746 : : !!
747 : : !! SOURCE
748 : :
749 : 68 : subroutine magmom(barmmom,barmmom_tr,ddb,invbarmagsus,invhmat,iblok,jblok,lblok,magpen,magsus,mmom,mmom_tr,&
750 : 34 : & mpatpol,mpdir,mpert,natom,ndim,nmdir,prtopt,prtvol,qphon,xred,zfield,zfield_tr, &
751 : 30 : & fs2rs,blkval_fs) !optional
752 : :
753 : : !Arguments -------------------------------
754 : : !scalars
755 : : integer,intent(in) :: iblok,jblok,lblok,mpert,natom,ndim,nmdir,prtopt,prtvol
756 : : integer,intent(in),optional :: fs2rs
757 : : real(dp),intent(in) :: magpen
758 : : !arrays
759 : : type(ddb_type),intent(inout) :: ddb
760 : : real(dp),intent(in) :: qphon(3),xred(3,natom)
761 : : integer,intent(in) :: mpatpol(2),mpdir(3)
762 : : real(dp),intent(in),optional :: blkval_fs(2,3,mpert,3,mpert,1)
763 : : complex(dpc),intent(out) :: barmmom(ndim,(natom+5)*3)
764 : : complex(dpc),intent(out) :: barmmom_tr((natom+5)*3,ndim)
765 : : complex(dpc),intent(in) :: invbarmagsus(ndim,ndim)
766 : : complex(dpc),intent(in) :: invhmat(ndim,ndim)
767 : : complex(dpc),intent(in) :: magsus(ndim,ndim)
768 : : complex(dpc),intent(out) :: mmom(ndim,(natom+5)*3)
769 : : complex(dpc),intent(out) :: mmom_tr((natom+5)*3,ndim)
770 : : complex(dpc),intent(out) :: zfield(ndim,(natom+5)*3)
771 : : complex(dpc),intent(out) :: zfield_tr((natom+5)*3,ndim)
772 : : !Local variables -------------------------
773 : : !scalars
774 : : integer :: fs2rs_
775 : : integer :: iat1,icol,idir1,idir2,index,ipert1,ipert2,irow
776 : : integer :: ipert1_red,idir1_red,jndex,zblok
777 : : complex(dpc) :: qfac, qfac_tr
778 : : character(len=1000) :: msg
779 : : !arrays
780 : 68 : integer :: indexat1(ndim),indexdir1(ndim)
781 : 68 : integer :: indexat2((natom+5)*3),indexdir2((natom+5)*3)
782 : 34 : complex(dpc) :: mmom_alt(ndim,(natom+5)*3)
783 : : character(len=1) :: cart(3)=(/'x','y','z'/)
784 : :
785 : : ! *********************************************************************
786 : :
787 : : !If fixed-spin case has been precalculated do less stuff
788 [ + + ]: 34 : fs2rs_=0; if (present(fs2rs)) fs2rs_=fs2rs
789 [ + - ]: 30 : if (fs2rs_==1) then
790 [ - + ]: 30 : if (.not.present(blkval_fs)) then
791 : 0 : write(msg, '(3a)' )' No fixed-spin array has been passed to magmom', &
792 : 0 : & ' but fs2rs=1 ',ch10
793 : 0 : ABI_ERROR(msg)
794 : : end if
795 : : end if
796 : :
797 : : !Extract the penalized moments
798 [ + + ]: 408 : do ipert2=1,natom+5
799 : : !exclude strain perturbation
800 [ + + + + ]: 374 : if (ipert2==natom+3.or.ipert2==natom+4) cycle
801 [ + + ]: 1258 : do idir2=1,3
802 : 918 : icol=idir2+(ipert2-1)*3
803 : 918 : indexat2(icol)=ipert2
804 : 918 : indexdir2(icol)=idir2
805 : :
806 : 918 : ipert1_red= 0
807 [ + + ]: 3128 : do iat1= mpatpol(1), mpatpol(2)
808 : 1836 : ipert1= natom + 11 + iat1
809 : 1836 : ipert1_red= ipert1_red + 1
810 : 1836 : idir1_red= 0
811 : :
812 : : !Apply a phase factor to adopt the same Gonze&Lee convention as for atomic
813 : : !displacements at finite q (See M. Stengel PRB 2013).
814 [ + + ]: 7344 : qfac= exp(two_pi*(0.d0,1.d0)* dot_product(qphon,xred(:,iat1)))
815 [ + + ]: 7344 : qfac_tr= exp(-two_pi*(0.d0,1.d0)* dot_product(qphon,xred(:,iat1)))
816 [ + + ]: 8262 : do idir1= 1, 3
817 [ + + ]: 5508 : if (mpdir(idir1)==0) cycle
818 : 3672 : idir1_red= idir1_red + 1
819 : 3672 : irow=idir1_red+(ipert1_red-1)*nmdir
820 : 3672 : indexat1(irow)=iat1
821 : 3672 : indexdir1(irow)=idir1
822 : 3672 : index= idir1 + 3*((ipert1-1)+mpert*((idir2-1)+3*(ipert2-1)))
823 : 3672 : jndex= idir2 + 3*((ipert2-1)+mpert*((idir1-1)+3*(ipert1-1)))
824 : :
825 [ + + ]: 5508 : if (fs2rs_==0) then
826 [ + - + + ]: 432 : if (iblok /=0 .and. ipert2 <= natom) then
827 : 288 : barmmom(irow,icol)= cmplx(ddb%val(1,index,iblok),ddb%val(2,index,iblok),kind=dpc) * qfac
828 : 288 : barmmom_tr(icol,irow)= cmplx(ddb%val(1,jndex,iblok),ddb%val(2,jndex,iblok),kind=dpc) * qfac_tr
829 [ + + + + ]: 144 : else if (jblok /=0 .and. ipert2 == natom+2) then
830 : 36 : barmmom(irow,icol)= cmplx(ddb%val(1,index,jblok),ddb%val(2,index,jblok),kind=dpc)
831 : 36 : barmmom_tr(icol,irow)= cmplx(ddb%val(1,jndex,jblok),ddb%val(2,jndex,jblok),kind=dpc)
832 [ - + + + ]: 108 : else if (lblok /=0 .and. ipert2 == natom+5) then
833 : 48 : barmmom(irow,icol)= cmplx(ddb%val(1,index,lblok),ddb%val(2,index,lblok),kind=dpc) * qfac
834 : 48 : barmmom_tr(icol,irow)= cmplx(ddb%val(1,jndex,lblok),ddb%val(2,jndex,lblok),kind=dpc) * qfac_tr
835 : : end if
836 [ - + ]: 3240 : else if (fs2rs_==1) then
837 : : zfield(irow,icol)= &
838 : : & cmplx(blkval_fs(1,idir1,ipert1,idir2,ipert2,iblok), &
839 [ + - ]: 3240 : & blkval_fs(2,idir1,ipert1,idir2,ipert2,iblok),kind=dpc)
840 : : zfield_tr(icol,irow)= &
841 : : & cmplx(blkval_fs(1,idir2,ipert2,idir1,ipert1,iblok), &
842 : 3240 : & blkval_fs(2,idir2,ipert2,idir1,ipert1,iblok),kind=dpc)
843 : : end if
844 : :
845 : : end do
846 : : end do
847 : : end do
848 : : end do
849 : :
850 : : !Compute the Zeeman fields
851 [ + + ]: 34 : if (fs2rs_==0) then
852 [ - + + - : 4112 : zfield=-matmul(invbarmagsus,barmmom)
- + + - +
- + - - +
- + + + +
+ + + + +
+ + + + +
+ + - ]
853 [ - + + - : 3300 : zfield_tr=-matmul(barmmom_tr,invbarmagsus)
- + + - +
- + - - +
- + + + +
+ + + + +
+ + + + +
+ + - ]
854 : : end if
855 : :
856 : : !Compute the moments
857 : : if (fs2rs_==0) then
858 [ - + + - : 4112 : mmom=-matmul(magsus,zfield)
- + + - +
- + - - +
- + + + +
+ + + + +
+ + + + +
+ + - ]
859 [ + - + + : 3436 : mmom_alt=matmul(invhmat,barmmom)
+ + + + +
+ + + ]
860 [ + - + + : 2740 : mmom_tr=matmul(barmmom_tr,invhmat)
+ + + + +
+ + + ]
861 [ + - ]: 30 : else if (fs2rs_==1) then
862 [ - + + - : 30840 : mmom=-matmul(magsus,zfield)
- + + - +
- + - - +
- + + + +
+ + + + +
+ + + + +
+ + - ]
863 [ - + + - : 24750 : mmom_tr=-matmul(zfield_tr,magsus)
- + + - +
- + - - +
- + + + +
+ + + + +
+ + + + +
+ + - ]
864 : : return
865 : : end if
866 : :
867 [ + - + - ]: 4 : if (prtopt==1.and.prtvol>1) then
868 : :
869 : : !Write the results
870 [ + - ]: 4 : if (magpen > zero) then
871 : :
872 : : !Atomic displacements
873 [ + - ]: 4 : if (iblok /= 0) then
874 [ + + ]: 12 : call wrtout([ab_out,std_out], ' Local Zeeman fields induced by atomic displacements (at constrained magnetic moments)')
875 [ + + ]: 12 : call wrtout([ab_out,std_out], ' atom1 dir atom2 dir Real Imag')
876 [ + + ]: 20 : do irow=1, ndim
877 [ + + ]: 308 : do icol=1, natom*3
878 : : write(msg,'(2(i4,4x,a2,2x),2x,2es18.9)' ) &
879 : 288 : & indexat1(irow), cart(indexdir1(irow)), indexat2(icol), cart(indexdir2(icol)), &
880 : 576 : & real(zfield(irow,icol)), aimag(zfield(irow,icol))
881 [ + + ]: 880 : call wrtout([ab_out,std_out], msg)
882 : : end do
883 : : end do
884 [ + + ]: 12 : call wrtout([ab_out,std_out], ' ')
885 : :
886 [ + + ]: 12 : call wrtout([ab_out,std_out], ' Local magnetic moments induced by atomic displacements (from induced Zeeman fields)')
887 [ + + ]: 12 : call wrtout([ab_out,std_out], ' atom1 dir atom2 dir Real Imag')
888 [ + + ]: 20 : do irow=1, ndim
889 [ + + ]: 308 : do icol=1, natom*3
890 : : write(msg,'(2(i4,4x,a2,2x),2x,2es18.9)' ) &
891 : 288 : & indexat1(irow), cart(indexdir1(irow)), indexat2(icol), cart(indexdir2(icol)), &
892 : 576 : & real(mmom(irow,icol)), aimag(mmom(irow,icol))
893 [ + + ]: 880 : call wrtout([ab_out,std_out], msg)
894 : : end do
895 : : end do
896 [ + + ]: 12 : call wrtout([ab_out,std_out], ' ')
897 : :
898 [ + + ]: 12 : call wrtout([ab_out,std_out], ' Local magnetic moments induced by atomic displacements (from induced penalized moments)')
899 [ + + ]: 12 : call wrtout([ab_out,std_out], ' atom1 dir atom2 dir Real Imag')
900 [ + + ]: 20 : do irow=1, ndim
901 [ + + ]: 308 : do icol=1, natom*3
902 : : write(msg,'(2(i4,4x,a2,2x),2x,2es18.9)' ) &
903 : 288 : & indexat1(irow), cart(indexdir1(irow)), indexat2(icol), cart(indexdir2(icol)), &
904 : 576 : & real(mmom_alt(irow,icol)), aimag(mmom_alt(irow,icol))
905 [ + + ]: 880 : call wrtout([ab_out,std_out], msg)
906 : : end do
907 : : end do
908 [ + + ]: 12 : call wrtout([ab_out,std_out], ' ')
909 : : end if
910 : :
911 : : !Electric field
912 [ + + ]: 4 : if (jblok /= 0) then
913 [ + + ]: 9 : call wrtout([ab_out,std_out], ' Local Zeeman fields induced by electric field (at constrained magnetic moments)')
914 [ + + ]: 9 : call wrtout([ab_out,std_out], ' atom1 dir E-dir Real Imag')
915 [ + + ]: 15 : do irow=1, ndim
916 [ + + ]: 51 : do icol=(natom+1)*3+1, (natom+2)*3
917 : : write(msg,'(i4,4x,a2,4x,a2,6x,2es18.9)' ) &
918 : 36 : & indexat1(irow), cart(indexdir1(irow)), cart(indexdir2(icol)), &
919 : 72 : & real(zfield(irow,icol)), aimag(zfield(irow,icol))
920 [ + + ]: 120 : call wrtout([ab_out,std_out], msg)
921 : : end do
922 : : end do
923 [ + + ]: 9 : call wrtout([ab_out,std_out], ' ')
924 [ + + ]: 9 : call wrtout([ab_out,std_out], ' Local magnetic moments induced by electric field (from induced Zeeman fields)')
925 [ + + ]: 9 : call wrtout([ab_out,std_out], ' atom1 dir E-dir Real Imag')
926 [ + + ]: 15 : do irow=1, ndim
927 [ + + ]: 51 : do icol=(natom+1)*3+1, (natom+2)*3
928 : : write(msg,'(i4,4x,a2,4x,a2,6x,2es18.9)' ) &
929 : 36 : & indexat1(irow), cart(indexdir1(irow)), cart(indexdir2(icol)), &
930 : 72 : & real(mmom(irow,icol)), aimag(mmom(irow,icol))
931 [ + + ]: 120 : call wrtout([ab_out,std_out], msg)
932 : : end do
933 : : end do
934 [ + + ]: 9 : call wrtout([ab_out,std_out], ' ')
935 [ + + ]: 9 : call wrtout([ab_out,std_out], ' Local magnetic moments induced by electric field (from induced penalized moments)')
936 [ + + ]: 9 : call wrtout([ab_out,std_out], ' atom1 dir E-dir Real Imag')
937 [ + + ]: 15 : do irow=1, ndim
938 [ + + ]: 51 : do icol=(natom+1)*3+1, (natom+2)*3
939 : : write(msg,'(i4,4x,a2,4x,a2,6x,2es18.9)' ) &
940 : 36 : & indexat1(irow), cart(indexdir1(irow)), cart(indexdir2(icol)), &
941 : 72 : & real(mmom_alt(irow,icol)), aimag(mmom_alt(irow,icol))
942 [ + + ]: 120 : call wrtout([ab_out,std_out], msg)
943 : : end do
944 : : end do
945 [ + + ]: 9 : call wrtout([ab_out,std_out], ' ')
946 : : end if
947 : :
948 : : !Macroscopic Zeeman
949 [ + - ]: 4 : if (lblok /= 0) then
950 [ + + ]: 12 : call wrtout([ab_out,std_out], ' Local Zeeman fields induced by macroscopic Zeeman field (at constrained magnetic moments)')
951 [ + + ]: 12 : call wrtout([ab_out,std_out], ' atom1 dir B-dir Real Imag')
952 [ + + ]: 20 : do irow=1, ndim
953 [ + + ]: 68 : do icol=(natom+4)*3+1, (natom+5)*3
954 : : write(msg,'(i4,4x,a2,4x,a2,6x,2es18.9)' ) &
955 : 48 : & indexat1(irow), cart(indexdir1(irow)), cart(indexdir2(icol)), &
956 : 96 : & real(zfield(irow,icol)), aimag(zfield(irow,icol))
957 [ + + ]: 160 : call wrtout([ab_out,std_out], msg)
958 : : end do
959 : : end do
960 [ + + ]: 12 : call wrtout([ab_out,std_out], ' ')
961 [ + + ]: 12 : call wrtout([ab_out,std_out], ' Local magnetic moments induced by macroscopic Zeeman field (from induced Zeeman fields)')
962 [ + + ]: 12 : call wrtout([ab_out,std_out], ' atom1 dir B-dir Real Imag')
963 [ + + ]: 20 : do irow=1, ndim
964 [ + + ]: 68 : do icol=(natom+4)*3+1, (natom+5)*3
965 : : write(msg,'(i4,4x,a2,4x,a2,6x,2es18.9)' ) &
966 : 48 : & indexat1(irow), cart(indexdir1(irow)), cart(indexdir2(icol)), &
967 : 96 : & real(mmom(irow,icol)), aimag(mmom(irow,icol))
968 [ + + ]: 160 : call wrtout([ab_out,std_out], msg)
969 : : end do
970 : : end do
971 [ + + ]: 12 : call wrtout([ab_out,std_out], ' ')
972 [ + + ]: 12 : call wrtout([ab_out,std_out], ' Local magnetic moments induced by macroscopic Zeeman field (from induced penalized moments)')
973 [ + + ]: 12 : call wrtout([ab_out,std_out], ' atom1 dir B-dir Real Imag')
974 [ + + ]: 20 : do irow=1, ndim
975 [ + + ]: 68 : do icol=(natom+4)*3+1, (natom+5)*3
976 : : write(msg,'(i4,4x,a2,4x,a2,6x,2es18.9)' ) &
977 : 48 : & indexat1(irow), cart(indexdir1(irow)), cart(indexdir2(icol)), &
978 : 96 : & real(mmom_alt(irow,icol)), aimag(mmom_alt(irow,icol))
979 [ + + ]: 160 : call wrtout([ab_out,std_out], msg)
980 : : end do
981 : : end do
982 [ + + ]: 12 : call wrtout([ab_out,std_out], ' ')
983 : : end if
984 : :
985 [ + - ]: 4 : if (prtvol > 2) then
986 [ + - ]: 4 : if (iblok /= 0) then
987 [ + + ]: 12 : call wrtout([ab_out,std_out], ' Penalized local magnetic moments induced by atomic displacements ')
988 [ + + ]: 12 : call wrtout([ab_out,std_out], ' atom1 dir atom2 dir Real Imag')
989 [ + + ]: 20 : do irow=1, ndim
990 [ + + ]: 308 : do icol=1, natom*3
991 : : write(msg,'(2(i4,4x,a2,2x),2x,2es18.9)' ) &
992 : 288 : & indexat1(irow), cart(indexdir1(irow)), indexat2(icol), cart(indexdir2(icol)), &
993 : 576 : & real(barmmom(irow,icol)), aimag(barmmom(irow,icol))
994 [ + + ]: 880 : call wrtout([ab_out,std_out], msg)
995 : : end do
996 : : end do
997 [ + + ]: 12 : call wrtout([ab_out,std_out], ' ')
998 : : end if
999 [ + + ]: 4 : if (jblok /= 0) then
1000 [ + + ]: 9 : call wrtout([ab_out,std_out], ' Penalized local magnetic moments induced by electric field ')
1001 [ + + ]: 9 : call wrtout([ab_out,std_out], ' atom1 dir E-dir Real Imag')
1002 [ + + ]: 15 : do irow=1, ndim
1003 [ + + ]: 51 : do icol=(natom+1)*3+1, (natom+2)*3
1004 : : write(msg,'(i4,4x,a2,4x,a2,6x,2es18.9)' ) &
1005 : 36 : & indexat1(irow), cart(indexdir1(irow)), cart(indexdir2(icol)), &
1006 : 72 : & real(barmmom(irow,icol)), aimag(barmmom(irow,icol))
1007 [ + + ]: 120 : call wrtout([ab_out,std_out], msg)
1008 : : end do
1009 : : end do
1010 [ + + ]: 9 : call wrtout([ab_out,std_out], ' ')
1011 : : end if
1012 [ + - ]: 4 : if (lblok /= 0) then
1013 [ + + ]: 12 : call wrtout([ab_out,std_out], ' Penalized local magnetic moments induced by macroscopic Zeeman field ')
1014 [ + + ]: 12 : call wrtout([ab_out,std_out], ' atom1 dir B-dir Real Imag')
1015 [ + + ]: 20 : do irow=1, ndim
1016 [ + + ]: 68 : do icol=(natom+4)*3+1, (natom+5)*3
1017 : : write(msg,'(i4,4x,a2,4x,a2,6x,2es18.9)' ) &
1018 : 48 : & indexat1(irow), cart(indexdir1(irow)), cart(indexdir2(icol)), &
1019 : 96 : & real(barmmom(irow,icol)), aimag(barmmom(irow,icol))
1020 [ + + ]: 160 : call wrtout([ab_out,std_out], msg)
1021 : : end do
1022 : : end do
1023 [ + + ]: 12 : call wrtout([ab_out,std_out], ' ')
1024 : : end if
1025 : : end if
1026 : : end if
1027 : : end if
1028 : :
1029 : : !Store the FS and RS flavors on the DDB array
1030 [ + + ]: 48 : do ipert2=1,natom+5
1031 [ + + ]: 180 : do idir2=1,3
1032 : 132 : icol=idir2+(ipert2-1)*3
1033 : 132 : indexat2(icol)=ipert2
1034 : 132 : indexdir2(icol)=idir2
1035 : :
1036 : 132 : ipert1_red= 0
1037 [ + + ]: 440 : do iat1= mpatpol(1), mpatpol(2)
1038 : 264 : ipert1= natom + 11 + iat1
1039 : 264 : ipert1_red= ipert1_red + 1
1040 : 264 : idir1_red= 0
1041 [ + + ]: 1188 : do idir1= 1, 3
1042 [ + + ]: 792 : if (mpdir(idir1)==0) cycle
1043 : 528 : idir1_red= idir1_red + 1
1044 : 528 : irow=idir1_red+(ipert1_red-1)*nmdir
1045 : 528 : indexat1(irow)=iat1
1046 : 528 : indexdir1(irow)=idir1
1047 : 528 : index= idir1 + 3*((ipert1-1)+mpert*((idir2-1)+3*(ipert2-1)))
1048 : 528 : jndex= idir2 + 3*((ipert2-1)+mpert*((idir1-1)+3*(ipert1-1)))
1049 : :
1050 : 528 : zblok= 0
1051 [ - + + + ]: 528 : if (iblok /=0 .and. ipert2 <= natom) zblok= iblok
1052 [ + + + + ]: 528 : if (jblok /=0 .and. ipert2 == natom+2) zblok= jblok
1053 [ - + + + ]: 528 : if (lblok /=0 .and. ipert2 == natom+5) zblok= lblok
1054 [ + + ]: 792 : if (zblok /= 0) then
1055 : 372 : ddb%val_fs(1,index,zblok)=real(zfield(irow,icol))
1056 : 372 : ddb%val_fs(2,index,zblok)=aimag(zfield(irow,icol))
1057 : 372 : ddb%val_fs(1,jndex,zblok)=real(zfield_tr(icol,irow))
1058 : 372 : ddb%val_fs(2,jndex,zblok)=aimag(zfield_tr(icol,irow))
1059 : :
1060 : 372 : ddb%val_rs(1,index,zblok)=real(mmom(irow,icol))
1061 : 372 : ddb%val_rs(2,index,zblok)=aimag(mmom(irow,icol))
1062 : 372 : ddb%val_rs(1,jndex,zblok)=real(mmom_tr(icol,irow))
1063 : 372 : ddb%val_rs(2,jndex,zblok)=aimag(mmom_tr(icol,irow))
1064 : : end if
1065 : :
1066 : : end do
1067 : : end do
1068 : : end do
1069 : : end do
1070 : :
1071 [ + + ]: 34 : end subroutine magmom
1072 : : !!***
1073 : :
1074 : : !!****f* m_ddb_magpen/mp_d2etot
1075 : : !! NAME
1076 : : !! mp_d2etot
1077 : : !!
1078 : : !! FUNCTION
1079 : : !! Calculate the different magnetic flavors (see mpopt below) of the second-
1080 : : !! order derivatives of total energy
1081 : : !!
1082 : : !! INPUTS
1083 : : !! barmagsus(ndim,ndim)= Penalized spin-sussceptibility tensor (\bar{\chi})
1084 : : !! (equal to barmom^{\dagger} in the nondissipative regime)
1085 : : !! ddb= the ddb object
1086 : : !! iblok= index of the IFCs block
1087 : : !! invhmat(ndim,ndim)= (I-\alpha\bar{\chi})^-1 matrix
1088 : : !! magsus(ndim,ndim)= Spin-sussceptibility tensor
1089 : : !! magpen= magnetic penalty amplitude
1090 : : !! mpert =maximum number of ipert
1091 : : !! mpopt = 1 calculate the frozen-spin second-order quantities
1092 : : !! 2 calculate the relaxed-spin second-order quantities
1093 : : !! natom= number of atoms in unit cell
1094 : : !! nblok= number of blocks in the DDB
1095 : : !! ndim= number of local magnetic degres of freedom
1096 : : !! qphon= momentum wave-vector
1097 : : !! xred(3,natom)= reduced atomic coordinates
1098 : : !! zfield(ndim,(natom+2)*3)= First-order induced Zeeman fields
1099 : : !! zfield_tr(natom+2)*3,ndim)= Linear-responses to external Zeeman fields
1100 : : !! (equal to zfield^{\dagger} in the nondissipative regime)
1101 : : !! fs2rs= (optional) if 1, the routine starts from a precalculated blkval_fs
1102 : : !! blkval_fs(2,3,mpert,3,mpert,1)= fixed-spin 2nd-order derivatives
1103 : : !!
1104 : : !! OUTPUT
1105 : : !! ddb%val_fs(2,msize,nblok)= second-order derivatives at fixed spin.
1106 : : !! ddb%val_rs(2,msize,nblok)= second-order derivatives at relaxed spin.
1107 : : !! blkval_rs(2,3,mpert,3,mpert,1)= (optional) relaxed-spin 2nd-order derivatives
1108 : : !!
1109 : : !! SOURCE
1110 : :
1111 : 68 : subroutine mp_d2etot(barmagsus,ddb,&
1112 : 34 : & iblok,magsus,mpert,mpopt,&
1113 : 34 : & natom,ndim,zfield,zfield_tr,&
1114 : 60 : & fs2rs,blkval_fs,blkval_rs) !optional
1115 : :
1116 : : !Arguments -------------------------------
1117 : : !scalars
1118 : : integer,intent(in) :: iblok,mpert,mpopt,natom,ndim
1119 : : integer,intent(in),optional :: fs2rs
1120 : : ! real(dp),intent(in) :: magpen
1121 : : !arrays
1122 : : type(ddb_type),intent(inout) :: ddb
1123 : : real(dp),intent(in),optional :: blkval_fs(2,3,mpert,3,mpert,1)
1124 : : real(dp),intent(out),optional :: blkval_rs(2,3,mpert,3,mpert,1)
1125 : : complex(dpc),intent(in) :: barmagsus(ndim,ndim)
1126 : : ! complex(dpc),intent(in) :: invhmat(ndim,ndim)
1127 : : complex(dpc),intent(in) :: magsus(ndim,ndim)
1128 : : complex(dpc),intent(in) :: zfield(ndim,(natom+5)*3)
1129 : : complex(dpc),intent(in) :: zfield_tr((natom+5)*3,ndim)
1130 : : !Local variables -------------------------
1131 : : !scalars
1132 : : integer :: fs2rs_
1133 : : integer :: idir1,idir2,ipert1,ipert2,index,irow,icol
1134 : : complex(dpc) :: val_ps,val_fs, val_rs
1135 : : character(len=1000) :: msg
1136 : : !arrays
1137 : :
1138 : : ! *********************************************************************
1139 : :
1140 : : !If fixed-spin case has been precalculated do less stuff
1141 [ + + ]: 34 : fs2rs_=0; if (present(fs2rs)) fs2rs_=fs2rs
1142 [ + - ]: 30 : if (fs2rs_==1) then
1143 [ - + ]: 30 : if (.not.present(blkval_fs)) then
1144 : 0 : write(msg, '(3a)' )' No fixed-spin array has been passed to mp_d2etot', &
1145 : 0 : & ' but fs2rs=1 ',ch10
1146 : 0 : ABI_ERROR(msg)
1147 : : end if
1148 [ - + ]: 30 : if (.not.present(blkval_rs)) then
1149 : 0 : write(msg, '(3a)' )' No relaxed-spin array has been passed to mp_d2etot', &
1150 : 0 : & ' but fs2rs=1 ',ch10
1151 : 0 : ABI_ERROR(msg)
1152 : : end if
1153 : : end if
1154 : :
1155 : : !Extract the penalized/constrained quantities
1156 [ + + ]: 408 : do ipert2= 1, natom+5
1157 [ + + ]: 1530 : do idir2= 1, 3
1158 : 1122 : icol= (ipert2-1)*3 + idir2
1159 [ + + ]: 13838 : do ipert1= 1, natom+5
1160 [ + + ]: 50490 : do idir1= 1, 3
1161 : 37026 : irow= (ipert1-1)*3 + idir1
1162 : 37026 : index= idir1 + 3*((ipert1-1)+mpert*((idir2-1)+3*(ipert2-1)))
1163 : :
1164 [ + + ]: 37026 : if (fs2rs_==0) then
1165 : : !Extract the penalized second-order derivatives
1166 : 4356 : val_ps= cmplx(ddb%val(1,index,iblok),ddb%val(2,index,iblok),kind=dpc)
1167 : : !Calculate the fixed-spin flavor
1168 : : val_fs= val_ps + &
1169 [ + - + - : 139392 : & sum( zfield_tr(irow,:) * matmul( barmagsus,zfield(:,icol) ) )
+ - - + -
+ + + + +
+ + + + +
- ]
1170 : 4356 : ddb%val_fs(1,index,iblok)= real(val_fs)
1171 : 4356 : ddb%val_fs(2,index,iblok)= aimag(val_fs)
1172 [ + - ]: 32670 : else if (fs2rs_==1) then
1173 : : val_fs= &
1174 : : & cmplx(blkval_fs(1,idir1,ipert1,idir2,ipert2,iblok), &
1175 [ + - ]: 32670 : & blkval_fs(2,idir1,ipert1,idir2,ipert2,iblok),kind=dpc)
1176 : : end if
1177 : :
1178 [ + - ]: 49368 : if (mpopt==2) then
1179 : : !Calculate the relaxed-spin flavor
1180 : : val_rs= val_fs - &
1181 [ + - + - : 1184832 : & sum( zfield_tr(irow,:) * matmul( magsus,zfield(:,icol) ) )
+ - - + -
+ + + + +
+ + + + +
- ]
1182 [ + + ]: 37026 : if (fs2rs_==0) then
1183 : 4356 : ddb%val_rs(1,index,iblok)= real(val_rs)
1184 : 4356 : ddb%val_rs(2,index,iblok)= aimag(val_rs)
1185 [ + - ]: 32670 : else if (fs2rs_==1) then
1186 : 32670 : blkval_rs(1,idir1,ipert1,idir2,ipert2,iblok)=real(val_rs)
1187 : 32670 : blkval_rs(2,idir1,ipert1,idir2,ipert2,iblok)=aimag(val_rs)
1188 : : end if
1189 : : end if
1190 : :
1191 : : end do
1192 : : end do
1193 : : end do
1194 : : end do
1195 : :
1196 [ + + + + ]: 64 : end subroutine mp_d2etot
1197 : : !!***
1198 : :
1199 : : !!****f* m_ddb_magpen/mp_d2etot_print
1200 : : !! NAME
1201 : : !! mp_d2etot_print
1202 : : !!
1203 : : !! FUNCTION
1204 : : !! Write on output file the fixed- and relaxed-spin susceptibilities
1205 : : !!
1206 : : !! INPUTS
1207 : : !! blkval= 2nd-order susceptibilities matrix
1208 : : !! kblok= index of the current block
1209 : : !! opt= 1 write the frozen-spin second-order quantities
1210 : : !! 2 write the relaxed-spin second-order quantities
1211 : : !! omega= frequency of the perturbation
1212 : : !! qphon= momentum wave-vector
1213 : : !! ucvol= unit-cell volume
1214 : : !!
1215 : : !! OUTPUT
1216 : : !!
1217 : : !! SOURCE
1218 : :
1219 : 16 : subroutine mp_d2etot_print(ddb,blkval,kblok,mpert,natom,nblok,opt,omega,qeq0,qphnrm,qphon,msize)
1220 : :
1221 : : !Arguments -------------------------------
1222 : : !scalars
1223 : : class(ddb_type),intent(in) :: ddb
1224 : : integer,intent(in) :: kblok,mpert,natom,nblok,opt,msize
1225 : : logical,intent(in) :: qeq0
1226 : : !arrays
1227 : : real(dp),intent(in) :: omega(3)
1228 : : real(dp),intent(in) :: blkval(2,msize,nblok)
1229 : : real(dp),intent(inout) :: qphnrm(3),qphon(3,3)
1230 : :
1231 : : !Local variables -------------------------
1232 : : !scalars
1233 : : integer :: iblok,idir1,idir2,ipert1,ipert2,irow,icol
1234 : : integer :: rftyp,index
1235 : : character(len=1000) :: msg
1236 : : !arrays
1237 : : integer :: rfelfd(4),rfmagn(4),rfphon(4),rfstrs(4)
1238 : : real(dp) :: val(2)
1239 : : character(len=1) :: cart(3)=(/'x','y','z'/)
1240 : :
1241 : : ! *********************************************************************
1242 : :
1243 : 4 : rfelfd(:)=0
1244 : 4 : rfphon(:)=0
1245 : 4 : rfstrs(:)=0
1246 : 4 : rfmagn(:)=0
1247 : 4 : rftyp = 1
1248 : :
1249 : : !IFCs
1250 [ + + ]: 12 : rfphon(1:2)=1
1251 : 4 : call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, omega=omega)
1252 [ + - + - ]: 4 : if (iblok/=0.and.iblok==kblok) then
1253 [ - + ]: 4 : if (opt==1) then
1254 [ # # ]: 0 : call wrtout([ab_out,std_out], ' Frozen-spin interatomic force constants')
1255 [ + - ]: 4 : else if (opt==2) then
1256 [ + + ]: 12 : call wrtout([ab_out,std_out], ' Relaxed-spin interatomic force constants')
1257 : : end if
1258 [ + + ]: 12 : call wrtout([ab_out,std_out], ' atom1 dir atom2 dir Real Imag')
1259 [ + + ]: 28 : do ipert1= 1, natom
1260 [ + + ]: 100 : do idir1= 1, 3
1261 : 72 : irow=( ipert1-1)*3 + idir1
1262 [ + + ]: 504 : do ipert2= 1, natom
1263 [ + + ]: 1800 : do idir2= 1, 3
1264 : 1296 : icol=( ipert2-1)*3 + idir2
1265 : 1296 : index= idir1 + 3*((ipert1-1)+mpert*((idir2-1)+3*(ipert2-1)))
1266 [ + + ]: 3888 : val(:)=blkval(:,index,kblok)
1267 : : write(msg,'(2(i4,4x,a2,2x),2x,2es18.9)') &
1268 : 1296 : & ipert1, cart(idir1), ipert2, cart(idir2), val(1), val(2)
1269 [ + + ]: 4320 : call wrtout([ab_out,std_out], msg)
1270 : : end do
1271 : : end do
1272 [ + + ]: 240 : call wrtout([ab_out,std_out], ' ')
1273 : : end do
1274 : : end do
1275 : : end if
1276 : :
1277 [ + + ]: 4 : if (qeq0) then
1278 : :
1279 : : !Born charges
1280 [ + + ]: 9 : rfphon(1:2)=1
1281 [ + + ]: 9 : rfelfd(1:2)=2
1282 : 3 : call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, omega=omega)
1283 [ + - + - ]: 3 : if (iblok/=0.and.iblok==kblok) then
1284 [ - + ]: 3 : if (opt==1) then
1285 [ # # ]: 0 : call wrtout([ab_out,std_out], ' Frozen-spin Born effective charges')
1286 [ + - ]: 3 : else if (opt==2) then
1287 [ + + ]: 9 : call wrtout([ab_out,std_out], ' Relaxed-spin Born effective charges')
1288 : : end if
1289 [ + + ]: 9 : call wrtout([ab_out,std_out], ' E-dir atom dir Real Imag')
1290 : 3 : ipert1= natom + 2
1291 [ + + ]: 12 : do idir1= 1, 3
1292 [ + + ]: 63 : do ipert2= 1, natom
1293 [ + + ]: 225 : do idir2= 1, 3
1294 : 162 : index= idir1 + 3*((ipert1-1)+mpert*((idir2-1)+3*(ipert2-1)))
1295 [ + + ]: 486 : val(:)=blkval(:,index,kblok)
1296 : : write(msg,'(3x,a2,7x,i3,4x,a2,2x,2es18.9)') &
1297 : 162 : & cart(idir1), ipert2, cart(idir2), val(1), val(2)
1298 [ + + ]: 540 : call wrtout([ab_out,std_out], msg)
1299 : : end do
1300 : : end do
1301 [ + + ]: 30 : call wrtout([ab_out,std_out], ' ')
1302 : : end do
1303 : : end if
1304 : :
1305 : : !Dielectric tensor
1306 : : iblok=0
1307 : 3 : rfphon(:)=0
1308 [ + + ]: 9 : rfelfd(1:2)=2
1309 : 3 : call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, omega=omega)
1310 [ + - + - ]: 3 : if (iblok/=0.and.iblok==kblok) then
1311 [ - + ]: 3 : if (opt==1) then
1312 [ # # ]: 0 : call wrtout([ab_out,std_out], ' Frozen-spin clamped-ion dielectric tensor')
1313 [ + - ]: 3 : else if (opt==2) then
1314 [ + + ]: 9 : call wrtout([ab_out,std_out], ' Relaxed-spin clamped-ion dielectric tensor')
1315 : : end if
1316 [ + + ]: 9 : call wrtout([ab_out,std_out], ' dir dir Real Imag')
1317 : 3 : ipert1= ddb%natom + 2
1318 : 3 : ipert2= ddb%natom + 2
1319 [ + + ]: 12 : do idir2= 1, 3
1320 [ + + ]: 36 : do idir1= 1, 3
1321 : 27 : index= idir1 + 3*((ipert1-1)+mpert*((idir2-1)+3*(ipert2-1)))
1322 [ + + ]: 81 : val(:)=blkval(:,index,kblok)
1323 : 27 : write(msg,'(2x,a2,3x,a2,2x,2es18.9)' ) cart(idir1), cart(idir2), &
1324 : 54 : & val(1), val(2)
1325 [ + + ]: 90 : call wrtout([ab_out,std_out], msg)
1326 : : end do
1327 [ + + ]: 30 : call wrtout([ab_out,std_out], ' ')
1328 : : end do
1329 : : end if
1330 : :
1331 : : !Magnetoelectric susceptibility
1332 : : iblok=0
1333 : 3 : rfphon(:)=0
1334 : 3 : rfelfd(1)=0
1335 : 3 : rfelfd(2)=2
1336 : 3 : rfmagn(1)=1
1337 : : rfmagn(2)=0
1338 : : call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, omega=omega, &
1339 : 3 : & rfmagn=rfmagn)
1340 [ + - + - ]: 3 : if (iblok/=0.and.iblok==kblok) then
1341 [ - + ]: 3 : if (opt==1) then
1342 [ # # ]: 0 : call wrtout([ab_out,std_out], ' Frozen-spin clamped-ion magnetoelectric susceptibility')
1343 [ + - ]: 3 : else if (opt==2) then
1344 [ + + ]: 9 : call wrtout([ab_out,std_out], ' Relaxed-spin clamped-ion magnetoelectric susceptibility')
1345 : : end if
1346 [ + + ]: 9 : call wrtout([ab_out,std_out], ' M-dir E-dir Real Imag')
1347 : 3 : ipert1= ddb%natom + 5
1348 : 3 : ipert2= ddb%natom + 2
1349 [ + + ]: 12 : do idir2= 1, 3
1350 [ + + ]: 36 : do idir1= 1, 3
1351 : 27 : index= idir1 + 3*((ipert1-1)+mpert*((idir2-1)+3*(ipert2-1)))
1352 [ + + ]: 81 : val(:)=blkval(:,index,kblok)
1353 : 27 : write(msg,'(2x,a2,3x,a2,2x,2es18.9)' ) cart(idir1), cart(idir2), &
1354 : 54 : & val(1), val(2)
1355 [ + + ]: 90 : call wrtout([ab_out,std_out], msg)
1356 : : end do
1357 [ + + ]: 30 : call wrtout([ab_out,std_out], ' ')
1358 : : end do
1359 [ + + ]: 9 : call wrtout([ab_out,std_out], ' P-dir H-dir Real Imag')
1360 : 3 : ipert1= ddb%natom + 2
1361 : 3 : ipert2= ddb%natom + 5
1362 [ + + ]: 12 : do idir2= 1, 3
1363 [ + + ]: 36 : do idir1= 1, 3
1364 : 27 : index= idir1 + 3*((ipert1-1)+mpert*((idir2-1)+3*(ipert2-1)))
1365 [ + + ]: 81 : val(:)=blkval(:,index,kblok)
1366 : 27 : write(msg,'(2x,a2,3x,a2,2x,2es18.9)' ) cart(idir1), cart(idir2), &
1367 : 54 : & val(1), val(2)
1368 [ + + ]: 90 : call wrtout([ab_out,std_out], msg)
1369 : : end do
1370 [ + + ]: 30 : call wrtout([ab_out,std_out], ' ')
1371 : : end do
1372 : : end if
1373 : :
1374 : : end if
1375 : :
1376 : : !Magnetic susceptibility
1377 : : iblok=0
1378 : 4 : rfphon(:)=0
1379 : 4 : rfelfd(:)=0
1380 : 4 : rfmagn(1)=1
1381 : 4 : rfmagn(2)=1
1382 : : call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, omega=omega, &
1383 : 4 : & rfmagn=rfmagn)
1384 [ + - + - ]: 4 : if (iblok/=0.and.iblok==kblok) then
1385 [ - + ]: 4 : if (opt==1) then
1386 [ # # ]: 0 : call wrtout([ab_out,std_out], ' Frozen-spin clamped-ion magnetic susceptibility')
1387 [ + - ]: 4 : else if (opt==2) then
1388 [ + + ]: 12 : call wrtout([ab_out,std_out], ' Relaxed-spin clamped-ion magnetic susceptibility')
1389 : : end if
1390 [ + + ]: 12 : call wrtout([ab_out,std_out], ' dir dir Real Imag')
1391 : 4 : ipert1= ddb%natom + 5
1392 : 4 : ipert2= ddb%natom + 5
1393 [ + + ]: 16 : do idir2= 1, 3
1394 [ + + ]: 48 : do idir1= 1, 3
1395 : 36 : index= idir1 + 3*((ipert1-1)+mpert*((idir2-1)+3*(ipert2-1)))
1396 [ + + ]: 108 : val(:)=blkval(:,index,kblok)
1397 : 36 : write(msg,'(2x,a2,3x,a2,2x,2es18.9)' ) cart(idir1), cart(idir2), &
1398 : 72 : & val(1), val(2)
1399 [ + + ]: 120 : call wrtout([ab_out,std_out], msg)
1400 : : end do
1401 [ + + ]: 40 : call wrtout([ab_out,std_out], ' ')
1402 : : end do
1403 : : end if
1404 : :
1405 : : !Magnetic Born effective charges
1406 : : iblok=0
1407 : 4 : rfphon(1)=1
1408 : 4 : rfelfd(:)=0
1409 : 4 : rfmagn(1)=0
1410 : : rfmagn(2)=1
1411 : : call ddb%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, omega=omega, &
1412 : 4 : & rfmagn=rfmagn)
1413 [ + - + - ]: 4 : if (iblok/=0.and.iblok==kblok) then
1414 [ - + ]: 4 : if (opt==1) then
1415 [ # # ]: 0 : call wrtout([ab_out,std_out], ' Frozen-spin magnetic Born effective charges')
1416 [ + - ]: 4 : else if (opt==2) then
1417 [ + + ]: 12 : call wrtout([ab_out,std_out], ' Relaxed-spin magnetic Born effective charges')
1418 : : end if
1419 [ + + ]: 12 : call wrtout([ab_out,std_out], ' B-dir atom dir Real Imag')
1420 : :
1421 : 4 : ipert1= ddb%natom + 5
1422 [ + + ]: 16 : do idir1= 1, 3
1423 [ + + ]: 84 : do ipert2= 1, natom
1424 [ + + ]: 300 : do idir2= 1, 3
1425 : 216 : index= idir1 + 3*((ipert1-1)+mpert*((idir2-1)+3*(ipert2-1)))
1426 [ + + ]: 648 : val(:)=blkval(:,index,kblok)
1427 : : write(msg,'(3x,a2,7x,i3,4x,a2,2x,2es18.9)') &
1428 : 216 : & cart(idir1), ipert2, cart(idir2), val(1), val(2)
1429 [ + + ]: 720 : call wrtout([ab_out,std_out], msg)
1430 : : end do
1431 : : end do
1432 [ + + ]: 40 : call wrtout([ab_out,std_out], ' ')
1433 : : end do
1434 : : end if
1435 : :
1436 : 4 : end subroutine mp_d2etot_print
1437 : : !!***
1438 : :
1439 : : !!****f* m_ddb_magpen/asrw0
1440 : : !! NAME
1441 : : !! asrw0
1442 : : !!
1443 : : !! FUNCTION
1444 : : !! Impose the Acoustic Sum Rule from the w=0 IFCs
1445 : : !!
1446 : : !! INPUTS
1447 : : !! natom= namber of atoms
1448 : : !! option= if 0, this is the w=0 case, calculate delta_asrw0
1449 : : ! if 1, use the previously calculated delta_asrw0
1450 : : !!
1451 : : !! OUTPUT
1452 : : !! ifcmat(3*natom,3*natom)= IFC matrix after ASR has been applied.
1453 : : !! delta_asrw0(3*natom,3)= Amount to remove in order to enforce ASR.
1454 : : !!
1455 : : !! SOURCE
1456 : :
1457 : 0 : subroutine asrw0(delta_asrw0,ifcmat,natom,option)
1458 : :
1459 : : !Arguments -------------------------------
1460 : : !scalars
1461 : : integer,intent(in) :: natom,option
1462 : : !arrays
1463 : : real(dp),intent(inout) :: delta_asrw0(3*natom,3)
1464 : : complex(dpc),intent(inout) :: ifcmat(3*natom,3*natom)
1465 : : !Local variables -------------------------
1466 : : !scalars
1467 : : integer :: icol,idir1,idir2,ipert1,ipert2,irow
1468 : : !arrays
1469 : :
1470 : : ! *********************************************************************
1471 : :
1472 : : !Calculate the ASR correction
1473 [ # # ]: 0 : if (option == 0) then
1474 [ # # # # ]: 0 : delta_asrw0= zero
1475 [ # # ]: 0 : do idir1= 1, 3
1476 [ # # ]: 0 : do ipert1= 1, natom
1477 : 0 : irow= (ipert1-1)*3 + idir1
1478 [ # # ]: 0 : do idir2= 1, 3
1479 [ # # ]: 0 : do ipert2= 1, natom
1480 : 0 : icol= (ipert2-1)*3 + idir2
1481 : : delta_asrw0(irow,idir2)=delta_asrw0(irow,idir2) + &
1482 : 0 : & real(ifcmat(irow,icol))
1483 : : end do
1484 : : end do
1485 : : end do
1486 : : end do
1487 : : end if
1488 : :
1489 : : !Apply the ASR
1490 [ # # ]: 0 : do idir1= 1, 3
1491 [ # # ]: 0 : do ipert1= 1, natom
1492 : 0 : irow= (ipert1-1)*3 + idir1
1493 [ # # ]: 0 : do idir2= 1, 3
1494 : 0 : icol= (ipert1-1)*3 + idir2
1495 : 0 : ifcmat(irow,icol)= ifcmat(irow,icol) - delta_asrw0(irow,idir2)
1496 : : end do
1497 : : end do
1498 : : end do
1499 : :
1500 : 0 : end subroutine asrw0
1501 : : !!***
1502 : :
1503 : : !!****f* m_ddb_magpen/berrycurv_ss
1504 : : !! NAME
1505 : : !! berrycurv_ss
1506 : : !!
1507 : : !! FUNCTION
1508 : : !! Calculate the Berry curvature of the inverse magnetic susceptibility
1509 : : !! (this is equivalent to the G^(ss) matrix of S.Ren et al.)
1510 : : !!
1511 : : !! INPUTS
1512 : : !! blkval(2,3*mpert*3*mpert*3*mpert,nblok)= Third-order derivative matrices
1513 : : !! In our case, the nblok is restricted to iblok
1514 : : !! iblok= index of the current block
1515 : : !! invbarmagsus(ndim,ndim)= Inverse of the penalized spin-sussceptibility tensor
1516 : : !! mpatpol(2) = Atoms on which the magnetic penalty has been applied
1517 : : !! mpdir(3) = Directions along which the spin-degrees of freedom have been stiffened
1518 : : !! mpert =maximum number of ipert
1519 : : !! natom= number of atoms in unit cell
1520 : : !! nblok= number of blocks in the DDB
1521 : : !! nmdir= number of directions along which the magnetic penalty was applied
1522 : : !! ndim= dimension of the square susceptibilities
1523 : : !! prtvol= control the volume of information written on output
1524 : : !!
1525 : : !! OUTPUT
1526 : : !! bc_ss(ndim,ndim)= Berry-curvature of the inverse local-spin susceptibility
1527 : : !!
1528 : : !! SOURCE
1529 : :
1530 : 2 : subroutine berrycurv_ss(bc_barmagsus,bc_ss,ddb_lw,iblok,invbarmagsus,&
1531 : 2 : & mpatpol,mpdir,mpert,natom,ndim,nmdir,prtvol,qphon,xred)
1532 : :
1533 : : !Arguments -------------------------------
1534 : : !scalars
1535 : : integer,intent(in) :: iblok,mpert,natom,ndim,nmdir,prtvol
1536 : : !arrays
1537 : : type(ddb_type),intent(inout) :: ddb_lw
1538 : : integer,intent(in) :: mpatpol(2),mpdir(3)
1539 : : real(dp),intent(in) :: qphon(3),xred(3,natom)
1540 : : complex(dpc),intent(in) :: invbarmagsus(ndim,ndim)
1541 : : complex(dpc),intent(out) :: bc_ss(ndim,ndim)
1542 : : complex(dpc),intent(out) :: bc_barmagsus(ndim,ndim)
1543 : : !Local variables -------------------------
1544 : : !scalars
1545 : : integer :: iat1,iat2,icol,idir1,idir2,idir3,index
1546 : : integer :: ipert1,ipert2,ipert3,irow
1547 : : integer :: ipert1_red,ipert2_red,idir1_red,idir2_red
1548 : : complex(dpc), parameter :: ione=(0.d0,1.d0)
1549 : : character(len=1000) :: msg
1550 : : !arrays
1551 : 4 : complex(dpc) :: idty(ndim,ndim)
1552 : 2 : integer :: indexat(ndim),indexdir(ndim)
1553 : : character(len=1) :: cart(3)=(/'x','y','z'/)
1554 : :
1555 : : ! *********************************************************************
1556 : :
1557 : : !Extract the Berry-curvature of the penalized susceptibility
1558 [ + + + + ]: 42 : idty=(zero,zero)
1559 : 2 : ipert3= natom + 9
1560 : 2 : idir3= 1
1561 : 2 : ipert2_red= 0
1562 [ + + ]: 6 : do iat2= mpatpol(1), mpatpol(2)
1563 : 4 : ipert2= natom + 11 + iat2
1564 : 4 : ipert2_red= ipert2_red + 1
1565 : 4 : idir2_red= 0
1566 [ + + ]: 18 : do idir2= 1, 3
1567 [ + + ]: 12 : if (mpdir(idir2)==0) cycle
1568 : 8 : idir2_red= idir2_red + 1
1569 : 8 : icol=idir2_red+(ipert2_red-1)*nmdir
1570 : 8 : indexat(icol)=iat2
1571 : 8 : indexdir(icol)=idir2
1572 : 8 : idty(icol,icol)=(one,zero)
1573 : 8 : ipert1_red=0
1574 [ + + ]: 28 : do iat1= mpatpol(1), mpatpol(2)
1575 : 16 : ipert1= natom + 11 + iat1
1576 : 16 : ipert1_red= ipert1_red + 1
1577 : 16 : idir1_red= 0
1578 [ + + ]: 76 : do idir1= 1, 3
1579 [ + + ]: 48 : if (mpdir(idir1)==0) cycle
1580 : 32 : idir1_red=idir1_red+1
1581 : 32 : irow=idir1_red+(ipert1_red-1)*nmdir
1582 : : index = idir1 + &
1583 : : & 3*((ipert1 - 1) + mpert*((idir2 - 1) + &
1584 : 32 : & 3*((ipert2 -1 ) + mpert*((idir3 - 1) + 3*(ipert3 - 1)))))
1585 : :
1586 : : !Apply a phase factor to adopt the same Gonze&Lee convention as for atomic
1587 : : !displacements at finite q (See M. Stengel PRB 2013).
1588 : : bc_barmagsus(irow,icol)= -one* & !To convert from d3etot to local susc.
1589 : : & cmplx(ddb_lw%val(1,index,iblok),ddb_lw%val(2,index,iblok),kind=dpc) &
1590 [ + + ]: 160 : & * exp(two_pi*(0.d0,1.d0)*dot_product(qphon,xred(:,iat1)-xred(:,iat2)))
1591 : :
1592 : : end do
1593 : : end do
1594 : : end do
1595 : : end do
1596 : :
1597 : : !Calculate the Berry-curvature of the inverse magnetic susceptibility
1598 [ - + + - : 600 : bc_ss=-matmul(invbarmagsus,matmul(bc_barmagsus,invbarmagsus))
- + + - +
- + - - +
- + + + +
+ + + + +
+ + + - -
+ + - - +
+ - + - +
- - + - +
+ + + + +
+ + + + +
+ - + - +
- + + + +
+ - ]
1599 : :
1600 [ + - ]: 2 : if (prtvol>1) then
1601 [ + + ]: 6 : call wrtout([ab_out,std_out], ' Fixed-spin Berry curvature of the inverse spin susceptibility ')
1602 [ + + ]: 6 : call wrtout([ab_out,std_out], ' atom1 dir atom2 dir Real Imag')
1603 [ + + ]: 10 : do irow=1, ndim
1604 [ + + ]: 42 : do icol=1, ndim
1605 : : write(msg,'(2(i4,4x,a2,2x),2x,2es18.9)' ) &
1606 : 32 : & indexat(irow), cart(indexdir(irow)), indexat(icol), cart(indexdir(icol)), &
1607 : 64 : & real(bc_ss(irow,icol)), aimag(bc_ss(irow,icol))
1608 [ + + ]: 104 : call wrtout([ab_out,std_out], msg)
1609 : : end do
1610 : : end do
1611 [ + + ]: 6 : call wrtout([ab_out,std_out], ' ')
1612 : : end if
1613 : :
1614 : : !Store the FM flavor in the DDB object
1615 : : ipert2_red= 0
1616 [ + + ]: 6 : do iat2= mpatpol(1), mpatpol(2)
1617 : 4 : ipert2= natom + 11 + iat2
1618 : 4 : ipert2_red= ipert2_red + 1
1619 : 4 : idir2_red= 0
1620 [ + + ]: 18 : do idir2= 1, 3
1621 [ + + ]: 12 : if (mpdir(idir2)==0) cycle
1622 : 8 : idir2_red= idir2_red + 1
1623 : 8 : icol=idir2_red+(ipert2_red-1)*nmdir
1624 : 8 : ipert1_red=0
1625 [ + + ]: 28 : do iat1= mpatpol(1), mpatpol(2)
1626 : 16 : ipert1= natom + 11 + iat1
1627 : 16 : ipert1_red= ipert1_red + 1
1628 : 16 : idir1_red= 0
1629 [ + + ]: 76 : do idir1= 1, 3
1630 [ + + ]: 48 : if (mpdir(idir1)==0) cycle
1631 : 32 : idir1_red=idir1_red+1
1632 : 32 : irow=idir1_red+(ipert1_red-1)*nmdir
1633 : : index = idir1 + &
1634 : : & 3*((ipert1 - 1) + mpert*((idir2 - 1) + &
1635 : 32 : & 3*((ipert2 -1 ) + mpert*((idir3 - 1) + 3*(ipert3 - 1)))))
1636 : :
1637 : 32 : ddb_lw%val_fs(1,index,iblok)= real(bc_ss(irow,icol))
1638 : 64 : ddb_lw%val_fs(2,index,iblok)= aimag(bc_ss(irow,icol))
1639 : : end do
1640 : : end do
1641 : : end do
1642 : : end do
1643 : :
1644 : 2 : end subroutine berrycurv_ss
1645 : : !!***
1646 : :
1647 : : !!****f* m_ddb_magpen/berrycurv_sp
1648 : : !! NAME
1649 : : !! berrycurv_sp
1650 : : !!
1651 : : !! FUNCTION
1652 : : !! Calculate the Berry curvature of the spin-phonon Hessian
1653 : : !! (equivalent to the Berry curvature of the induced Zeeman fields at constrained
1654 : : !! magnetic moments)
1655 : : !!
1656 : : !! INPUTS
1657 : : !! ddb_lw= Third-order derivative ddb
1658 : : !! In our case, the nblok is restricted to iblok
1659 : : !! iblok= index of the current block
1660 : : !! invbarmagsus(ndim,ndim)= Inverse of the penalized spin-sussceptibility tensor
1661 : : !! mpatpol(2) = Atoms on which the magnetic penalty has been applied
1662 : : !! mpdir(3) = Directions along which the spin-degrees of freedom have been stiffened
1663 : : !! mpert =maximum number of ipert
1664 : : !! natom= number of atoms in unit cell
1665 : : !! nblok= number of blocks in the DDB
1666 : : !! nmdir= number of directions along which the magnetic penalty was applied
1667 : : !! ndim= dimension of the square susceptibilities
1668 : : !! prtvol= control the volume of information written on output
1669 : : !!
1670 : : !! OUTPUT
1671 : : !!
1672 : : !! SOURCE
1673 : :
1674 : 2 : subroutine berrycurv_sp(barmmom,bc_sp,bc_ss,ddb_lw,iblok,invbarmagsus,&
1675 : 2 : & jblok,lblok,mpatpol,mpdir,mpert,natom,ndim,nmdir,prtvol,qphon,xred)
1676 : :
1677 : : !Arguments -------------------------------
1678 : : !scalars
1679 : : integer,intent(in) :: iblok,jblok,lblok,mpert,natom,ndim,nmdir,prtvol
1680 : : !arrays
1681 : : type(ddb_type),intent(inout) :: ddb_lw
1682 : : integer,intent(in) :: mpatpol(2),mpdir(3)
1683 : : real(dp),intent(in) :: qphon(3),xred(3,natom)
1684 : : complex(dpc),intent(in) :: barmmom(ndim,(natom+5)*3)
1685 : : complex(dpc),intent(in) :: bc_ss(ndim,ndim)
1686 : : complex(dpc),intent(in) :: invbarmagsus(ndim,ndim)
1687 : : complex(dpc),intent(out) :: bc_sp(ndim,(natom+5)*3)
1688 : : !Local variables -------------------------
1689 : : !scalars
1690 : : integer :: iat1,icol,idir1,idir2,idir3,index,ipert1,ipert2,ipert3,irow
1691 : : integer :: ipert1_red,idir1_red,jndex
1692 : : complex(dpc), parameter :: ione=(0.d0,1.d0)
1693 : : complex(dpc) :: qfac
1694 : : character(len=1000) :: msg
1695 : : !arrays
1696 : 4 : integer :: indexat1(ndim),indexdir1(ndim)
1697 : 4 : integer :: indexat2((natom+5)*3),indexdir2((natom+5)*3)
1698 : 2 : complex(dpc) :: bc_barsp(ndim,(natom+5)*3)
1699 : : ! complex(dpc) :: bc_ps((natom+2)*3,ndim)
1700 : : character(len=1) :: cart(3)=(/'x','y','z'/)
1701 : :
1702 : : ! *********************************************************************
1703 : :
1704 : : !Extract the berry curvature of the penalized moments
1705 [ + + + + ]: 332 : bc_barsp=(zero,zero)
1706 : : ipert3= natom + 9
1707 : : idir3= 1
1708 [ + + ]: 24 : do ipert2=1,natom+5
1709 [ + + ]: 90 : do idir2=1,3
1710 : 66 : icol=idir2+(ipert2-1)*3
1711 : 66 : indexat2(icol)=ipert2
1712 : 66 : indexdir2(icol)=idir2
1713 : :
1714 : 66 : ipert1_red= 0
1715 [ + + ]: 220 : do iat1= mpatpol(1), mpatpol(2)
1716 : 132 : ipert1= natom + 11 + iat1
1717 : 132 : ipert1_red= ipert1_red + 1
1718 : 132 : idir1_red= 0
1719 : :
1720 : : !Apply a phase factor to adopt the same Gonze&Lee convention as for atomic
1721 : : !displacements at finite q (See M. Stengel PRB 2013).
1722 [ + + ]: 528 : qfac= exp(two_pi*(0.d0,1.d0)* dot_product(qphon,xred(:,iat1)))
1723 [ + + ]: 594 : do idir1= 1, 3
1724 [ + + ]: 396 : if (mpdir(idir1)==0) cycle
1725 : 264 : idir1_red= idir1_red + 1
1726 : 264 : irow=idir1_red+(ipert1_red-1)*nmdir
1727 : 264 : indexat1(irow)=iat1
1728 : 264 : indexdir1(irow)=idir1
1729 : : index = idir1 + &
1730 : : & 3*((ipert1 - 1) + mpert*((idir2 - 1) + &
1731 : 264 : & 3*((ipert2 -1 ) + mpert*((idir3 - 1) + 3*(ipert3 - 1)))))
1732 : :
1733 [ + - + + ]: 396 : if (iblok /=0 .and. ipert2 <= natom) then
1734 : : bc_barsp(irow,icol)= -one* & !To go from d3etot to induced local field
1735 : 144 : & cmplx(ddb_lw%val(1,index,iblok),ddb_lw%val(2,index,iblok),kind=dpc) * qfac
1736 [ + + + + ]: 120 : else if (jblok /=0 .and. ipert2 == natom+2) then
1737 : : bc_barsp(irow,icol)= -one* &
1738 : 12 : & cmplx(ddb_lw%val(1,index,jblok),ddb_lw%val(2,index,jblok),kind=dpc)
1739 [ + + + + ]: 108 : else if (lblok /=0 .and. ipert2 == natom+5) then
1740 : : bc_barsp(irow,icol)= -one* &
1741 : 12 : & cmplx(ddb_lw%val(1,index,lblok),ddb_lw%val(2,index,lblok),kind=dpc) * qfac
1742 : : end if
1743 : :
1744 : : end do
1745 : : end do
1746 : : end do
1747 : : end do
1748 : :
1749 : : !Calculate the Berry curvature of the induced Zeeman fields
1750 [ + - + + : 3774 : bc_sp= -matmul(bc_ss,barmmom) - matmul(invbarmagsus,bc_barsp)
+ + + + +
+ + + - +
+ - - + +
- + - + -
- + - + +
+ + + + +
+ + + + +
+ + + +
- ]
1751 : :
1752 [ + - ]: 2 : if (prtvol > 1) then
1753 [ + - ]: 2 : if (iblok /= 0) then
1754 [ + + ]: 6 : call wrtout([ab_out,std_out], ' Fixed-spin Berry curvature of the Zeeman fields induced by atomic displacements')
1755 [ + + ]: 6 : call wrtout([ab_out,std_out], ' atom1 dir E-dir Real Imag')
1756 [ + + ]: 10 : do irow=1, ndim
1757 [ + + ]: 154 : do icol=1, natom*3
1758 : : write(msg,'(2(i4,4x,a2,2x),2x,2es18.9)' ) &
1759 : 144 : & indexat1(irow), cart(indexdir1(irow)), indexat2(icol), cart(indexdir2(icol)), &
1760 : 288 : & real(bc_sp(irow,icol)), aimag(bc_sp(irow,icol))
1761 [ + + ]: 440 : call wrtout([ab_out,std_out], msg)
1762 : : end do
1763 : : end do
1764 [ + + ]: 6 : call wrtout([ab_out,std_out], ' ')
1765 : : end if
1766 [ + + ]: 2 : if (jblok /= 0) then
1767 [ + + ]: 3 : call wrtout([ab_out,std_out], ' Fixed-spin Berry curvature of the Zeeman fields induced by electric field')
1768 [ + + ]: 3 : call wrtout([ab_out,std_out], ' atom1 dir E-dir Real Imag')
1769 [ + + ]: 5 : do irow=1, ndim
1770 [ + + ]: 17 : do icol=(natom+1)*3+1, (natom+2)*3
1771 : : write(msg,'(i4,4x,a2,4x,a2,6x,2es18.9)' ) &
1772 : 12 : & indexat1(irow), cart(indexdir1(irow)), cart(indexdir2(icol)), &
1773 : 24 : & real(bc_sp(irow,icol)), aimag(bc_sp(irow,icol))
1774 [ + + ]: 40 : call wrtout([ab_out,std_out], msg)
1775 : : end do
1776 : : end do
1777 [ + + ]: 3 : call wrtout([ab_out,std_out], ' ')
1778 : : end if
1779 [ + + ]: 2 : if (lblok /= 0) then
1780 [ + + ]: 3 : call wrtout([ab_out,std_out], ' Fixed-spin Berry curvature of the Zeeman fields induced by macroscopic Zeeman field')
1781 [ + + ]: 3 : call wrtout([ab_out,std_out], ' atom1 dir B-dir Real Imag')
1782 [ + + ]: 5 : do irow=1, ndim
1783 [ + + ]: 17 : do icol=(natom+4)*3+1, (natom+5)*3
1784 : : write(msg,'(i4,4x,a2,4x,a2,6x,2es18.9)' ) &
1785 : 12 : & indexat1(irow), cart(indexdir1(irow)), cart(indexdir2(icol)), &
1786 : 24 : & real(bc_sp(irow,icol)), aimag(bc_sp(irow,icol))
1787 [ + + ]: 40 : call wrtout([ab_out,std_out], msg)
1788 : : end do
1789 : : end do
1790 [ + + ]: 3 : call wrtout([ab_out,std_out], ' ')
1791 : : end if
1792 : : end if
1793 : :
1794 : : !Store the FM flavor in the DDB object
1795 [ + + ]: 24 : do ipert2=1,natom+5
1796 [ + + ]: 90 : do idir2=1,3
1797 : 66 : icol=idir2+(ipert2-1)*3
1798 : 66 : indexat2(icol)=ipert2
1799 : 66 : indexdir2(icol)=idir2
1800 : :
1801 : 66 : ipert1_red= 0
1802 [ + + ]: 220 : do iat1= mpatpol(1), mpatpol(2)
1803 : 132 : ipert1= natom + 11 + iat1
1804 : 132 : ipert1_red= ipert1_red + 1
1805 : 132 : idir1_red= 0
1806 [ + + ]: 594 : do idir1= 1, 3
1807 [ + + ]: 396 : if (mpdir(idir1)==0) cycle
1808 : 264 : idir1_red= idir1_red + 1
1809 : 264 : irow=idir1_red+(ipert1_red-1)*nmdir
1810 : : index = idir1 + &
1811 : : & 3*((ipert1 - 1) + mpert*((idir2 - 1) + &
1812 : 264 : & 3*((ipert2 -1 ) + mpert*((idir3 - 1) + 3*(ipert3 - 1)))))
1813 : : jndex = idir2 + &
1814 : : & 3*((ipert2 - 1) + mpert*((idir1 - 1) + &
1815 : 264 : & 3*((ipert1 -1 ) + mpert*((idir3 - 1) + 3*(ipert3 - 1)))))
1816 : :
1817 [ + - + + ]: 396 : if (iblok /=0 .and. ipert2 <= natom) then
1818 : 144 : ddb_lw%val_fs(1,index,iblok)=real(bc_sp(irow,icol))
1819 : 144 : ddb_lw%val_fs(2,index,iblok)=aimag(bc_sp(irow,icol))
1820 : 144 : ddb_lw%val_fs(1,jndex,iblok)=real(bc_sp(irow,icol))
1821 : 144 : ddb_lw%val_fs(2,jndex,iblok)=-aimag(bc_sp(irow,icol))
1822 [ + + + + ]: 120 : else if (jblok /=0 .and. ipert2 == natom+2) then
1823 : 12 : ddb_lw%val_fs(1,index,jblok)=real(bc_sp(irow,icol))
1824 : 12 : ddb_lw%val_fs(2,index,jblok)=aimag(bc_sp(irow,icol))
1825 : 12 : ddb_lw%val_fs(1,jndex,jblok)=real(bc_sp(irow,icol))
1826 : 12 : ddb_lw%val_fs(2,jndex,jblok)=-aimag(bc_sp(irow,icol))
1827 [ + + + + ]: 108 : else if (lblok /=0 .and. ipert2 == natom+5) then
1828 : 12 : ddb_lw%val_fs(1,index,lblok)=real(bc_sp(irow,icol))
1829 : 12 : ddb_lw%val_fs(2,index,lblok)=aimag(bc_sp(irow,icol))
1830 : 12 : ddb_lw%val_fs(1,jndex,lblok)=real(bc_sp(irow,icol))
1831 : 12 : ddb_lw%val_fs(2,jndex,lblok)=-aimag(bc_sp(irow,icol))
1832 : : end if
1833 : :
1834 : : end do
1835 : : end do
1836 : : end do
1837 : : end do
1838 : :
1839 : 2 : end subroutine berrycurv_sp
1840 : : !!***
1841 : :
1842 : : !!****f* m_ddb_magpen/berrycurv_pp
1843 : : !! NAME
1844 : : !! berrycurv_pp
1845 : : !!
1846 : : !! FUNCTION
1847 : : !! Calculate the Berry curvature of the phonon-phonon Hessian
1848 : : !! (at constrained magnetic moments)
1849 : : !!
1850 : : !! INPUTS
1851 : : !! blkval(2,3*mpert*3*mpert*3*mpert,nblok)= Third-order derivative matrices
1852 : : !! In our case, the nblok is restricted to iblok
1853 : : !! kblok= index of the current block
1854 : : !! invbarmagsus(ndim,ndim)= Inverse of the penalized spin-sussceptibility tensor
1855 : : !! mpatpol(2) = Atoms on which the magnetic penalty has been applied
1856 : : !! mpdir(3) = Directions along which the spin-degrees of freedom have been stiffened
1857 : : !! mpert =maximum number of ipert
1858 : : !! natom= number of atoms in unit cell
1859 : : !! nblok= number of blocks in the DDB
1860 : : !! nmdir= number of directions along which the magnetic penalty was applied
1861 : : !! ndim= dimension of the square susceptibilities
1862 : : !! prtvol= control the volume of information written on output
1863 : : !!
1864 : : !! OUTPUT
1865 : : !!
1866 : : !! SOURCE
1867 : :
1868 : 2 : subroutine berrycurv_pp(barmagsus,bc_barmagsus,bc_sp,ddb_lw,kblok,&
1869 : 2 : & mpert,natom,ndim,qeq0,ucvol,zfield)
1870 : :
1871 : : !Arguments -------------------------------
1872 : : !scalars
1873 : : integer,intent(in) :: kblok,mpert,natom,ndim
1874 : : real(dp),intent(in) :: ucvol
1875 : : logical,intent(in) :: qeq0
1876 : : !arrays
1877 : : type(ddb_type),intent(inout) :: ddb_lw
1878 : : complex(dpc),intent(in) :: barmagsus(ndim,ndim)
1879 : : complex(dpc),intent(in) :: bc_barmagsus(ndim,ndim)
1880 : : complex(dpc),intent(in) :: bc_sp(ndim,(natom+5)*3)
1881 : : complex(dpc),intent(in) :: zfield(ndim,(natom+5)*3)
1882 : : !Local variables -------------------------
1883 : : !scalars
1884 : : integer :: icol,idir1,idir2,idir3,index,ipert1,ipert2,ipert3,irow
1885 : : complex(dpc), parameter :: ione=(0.d0,1.d0)
1886 : : complex(dpc) :: cval
1887 : : !arrays
1888 : 4 : complex(dpc) :: bc_barpp((natom+5)*3,(natom+5)*3), bc_pp((natom+5)*3,(natom+5)*3)
1889 : 4 : complex(dpc) :: term((natom+5)*3,(natom+5)*3,3)
1890 : :
1891 : : ! *********************************************************************
1892 : :
1893 : : !Extract the frequency derivative of the penalized 2nd order nonmagnetic quantities
1894 : 2 : ipert3= natom + 9
1895 : 2 : idir3= 1
1896 [ + + ]: 24 : do ipert2= 1, natom+5
1897 [ + + ]: 90 : do idir2= 1, 3
1898 : 66 : icol=( ipert2-1)*3 + idir2
1899 [ + + ]: 814 : do ipert1= 1, natom+5
1900 [ + + ]: 2970 : do idir1= 1, 3
1901 : 2178 : irow=( ipert1-1)*3 + idir1
1902 : : index = idir1 + &
1903 : : & 3*((ipert1 - 1) + mpert*((idir2 - 1) + &
1904 : 2178 : & 3*((ipert2 -1 ) + mpert*((idir3 - 1) + 3*(ipert3 - 1)))))
1905 : :
1906 : 2904 : bc_barpp(irow,icol)= cmplx(ddb_lw%val(1,index,kblok),ddb_lw%val(2,index,kblok),kind=dpc)
1907 : :
1908 : : end do
1909 : : end do
1910 : : end do
1911 : : end do
1912 : :
1913 : : !Calculate the different terms entering the Berry curvature
1914 [ - + + - : 23646 : term(:,:,1)=matmul(transpose(conjg(bc_sp)),matmul(barmagsus,zfield))
- + + - +
- + - - +
- + + + +
+ + + + +
+ + + - +
+ + + + +
+ + + + +
- + - - -
- - - - +
- ]
1915 [ - + + - : 23644 : term(:,:,2)=matmul(transpose(conjg(zfield)),matmul(bc_barmagsus,zfield))
- + + - +
- + - - +
- + + + +
+ + + + +
+ + + - +
+ + + + +
+ + + + +
- + - - -
- - - - +
- ]
1916 [ - + + - : 23644 : term(:,:,3)=matmul(transpose(conjg(zfield)),matmul(barmagsus,bc_sp))
- + + - +
- + - - +
- + + + +
+ + + + +
+ + + - +
+ + + + +
+ + + + +
- + - - -
- - - - +
- ]
1917 : :
1918 [ + + + + ]: 2246 : bc_pp(:,:)= bc_barpp(:,:) + term(:,:,1) + term(:,:,2) + term(:,:,3)
1919 : :
1920 : : !Apply factors to convert derivatives of energy into susceptibilities
1921 : : !Born charges
1922 [ + + ]: 2 : if (qeq0) then
1923 : 7 : ipert1= natom + 2
1924 [ + + ]: 7 : do ipert2= 1, natom
1925 [ + + ]: 25 : do idir2= 1, 3
1926 : 18 : icol=(ipert2-1)*3 + idir2
1927 [ + + ]: 78 : do idir1= 1, 3
1928 : 54 : irow=(ipert1-1)*3 + idir1
1929 : 54 : cval=bc_pp(irow,icol)
1930 : 54 : bc_pp(irow,icol)=-one*cval
1931 : 54 : cval=bc_pp(icol,irow)
1932 : 72 : bc_pp(icol,irow)=-one*cval
1933 : : end do
1934 : : end do
1935 : : end do
1936 : : end if
1937 : :
1938 : : !MR: Not sure why this is different from the electrical charges, | --------------------------------------------------------------------------------
1939 : : !but is needed to reproduce freqflag=3 numbers
1940 : : !Magnetic charges induced by atomic displacement
1941 : : ! ipert1= natom + 5
1942 : : ! do ipert2= 1, natom
1943 : : ! do idir2= 1, 3
1944 : : ! icol=( ipert2-1)*3 + idir2
1945 : : ! do idir1= 1, 3
1946 : : ! irow=( ipert1-1)*3 + idir1
1947 : : ! cval=bc_pp(irow,icol)
1948 : : ! bc_pp(irow,icol)=-cval
1949 : : ! cval=bc_pp(icol,irow)
1950 : : ! bc_pp(icol,irow)=-cval
1951 : : ! end do
1952 : : ! end do
1953 : : ! end do
1954 : :
1955 : : !Dielectric tensor
1956 [ + + ]: 2 : if (qeq0) then
1957 : 4 : ipert1= natom + 2
1958 : 4 : ipert2= natom + 2
1959 [ + + ]: 4 : do idir2= 1, 3
1960 : 3 : icol=( ipert2-1)*3 + idir2
1961 [ + + ]: 13 : do idir1= 1, 3
1962 : 9 : irow=( ipert1-1)*3 + idir1
1963 : 9 : cval=bc_pp(irow,icol)
1964 : 12 : bc_pp(irow,icol)=-four_pi/ucvol*cval
1965 : : end do
1966 : : end do
1967 : : end if
1968 : :
1969 : : !Magnetoelectric susceptibility
1970 [ + + ]: 2 : if (qeq0) then
1971 : 4 : ipert1= natom + 5
1972 : 4 : ipert2= natom + 2
1973 [ + + ]: 4 : do idir2= 1, 3
1974 : 3 : icol=( ipert2-1)*3 + idir2
1975 [ + + ]: 13 : do idir1= 1, 3
1976 : 9 : irow=( ipert1-1)*3 + idir1
1977 : 9 : cval=bc_pp(irow,icol)
1978 : 9 : bc_pp(irow,icol)=-cval/ucvol
1979 : 9 : cval=bc_pp(icol,irow)
1980 : 12 : bc_pp(icol,irow)=-cval/ucvol
1981 : : end do
1982 : : end do
1983 : : end if
1984 : :
1985 : : !Magnetic susceptibility
1986 : 8 : ipert1= natom + 5
1987 : 8 : ipert2= natom + 5
1988 [ + + ]: 8 : do idir2= 1, 3
1989 : 6 : icol=( ipert2-1)*3 + idir2
1990 [ + + ]: 26 : do idir1= 1, 3
1991 : 18 : irow=( ipert1-1)*3 + idir1
1992 : 18 : cval=bc_pp(irow,icol)
1993 : 24 : bc_pp(irow,icol)=-cval/ucvol
1994 : : end do
1995 : : end do
1996 : :
1997 : : !Store the FM flavor in the DDB object
1998 [ + + ]: 24 : do ipert2= 1, natom+5
1999 [ + + ]: 90 : do idir2= 1, 3
2000 : 66 : icol=( ipert2-1)*3 + idir2
2001 [ + + ]: 814 : do ipert1= 1, natom+5
2002 [ + + ]: 2970 : do idir1= 1, 3
2003 : 2178 : irow=( ipert1-1)*3 + idir1
2004 : : index = idir1 + &
2005 : : & 3*((ipert1 - 1) + mpert*((idir2 - 1) + &
2006 : 2178 : & 3*((ipert2 -1 ) + mpert*((idir3 - 1) + 3*(ipert3 - 1)))))
2007 : 2178 : ddb_lw%val_fs(1,index,kblok)=real(bc_pp(irow,icol))
2008 : 2904 : ddb_lw%val_fs(2,index,kblok)=aimag(bc_pp(irow,icol))
2009 : : end do
2010 : : end do
2011 : : end do
2012 : : end do
2013 : :
2014 : 2 : end subroutine berrycurv_pp
2015 : : !!***
2016 : :
2017 : : !!****f* m_ddb_magpen/mp_d3etot_print
2018 : : !! NAME
2019 : : !! mp_d3etot_print
2020 : : !!
2021 : : !! FUNCTION
2022 : : !! Write on output file the fixed- and relaxed-spin susceptibilities
2023 : : !! Only macroscopic quantities are printed if prtvol=1
2024 : : !!
2025 : : !! INPUTS
2026 : : !! blkval= 2nd-order susceptibilities matrix
2027 : : !! kblok= index of the current block
2028 : : !! opt= 1 write the frozen-spin second-order quantities
2029 : : !! 2 write the relaxed-spin second-order quantities
2030 : : !! omega= frequency of the perturbation
2031 : : !! qphon= momentum wave-vector
2032 : : !! ucvol= unit-cell volume
2033 : : !!
2034 : : !! OUTPUT
2035 : : !!
2036 : : !! SOURCE
2037 : :
2038 : 6 : subroutine mp_d3etot_print(ddb_lw,blkval,kblok,mpert,natom,nblok,opt,omega,prtvol,qeq0,qphnrm,qphon,ucvol,msize)
2039 : :
2040 : : !Arguments -------------------------------
2041 : : !scalars
2042 : : class(ddb_type),intent(in) :: ddb_lw
2043 : : integer,intent(in) :: kblok,mpert,natom,nblok,opt,prtvol,msize
2044 : : logical,intent(in) :: qeq0
2045 : : real(dp),intent(in) :: ucvol
2046 : : !arrays
2047 : : real(dp),intent(in) :: omega(3)
2048 : : real(dp),intent(in) :: blkval(2,msize,nblok)
2049 : : real(dp),intent(inout) :: qphnrm(3),qphon(3,3)
2050 : :
2051 : : !Local variables -------------------------
2052 : : !scalars
2053 : : integer :: iblok,idir1,idir2,idir3,ipert1,ipert2,ipert3,irow,icol
2054 : : integer :: rftyp,index,tmp
2055 : : character(len=1000) :: msg
2056 : : !arrays
2057 : : integer :: rfelfd(4),rfmagn(4),rfphon(4),rfstrs(4),rffreq(4)
2058 : : real(dp) :: val(2)
2059 : : character(len=1) :: cart(3)=(/'x','y','z'/)
2060 : :
2061 : : ! *********************************************************************
2062 : :
2063 : 2 : rfelfd(:)=0
2064 : 2 : rfphon(:)=0
2065 : 2 : rfstrs(:)=0
2066 : 2 : rfmagn(:)=0
2067 : 2 : rffreq(:)=0
2068 : 2 : rffreq(3)=1
2069 : 2 : rftyp = 33
2070 : :
2071 : 2 : ipert3= natom + 9
2072 : 2 : idir3= 1
2073 : 2 : tmp=opt !
2074 : : !IFCs
2075 [ + - ]: 2 : if (prtvol>1) then
2076 [ + + ]: 6 : rfphon(1:2)=1
2077 : : call ddb_lw%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, omega=omega, &
2078 : 2 : & rffreq=rffreq)
2079 [ + - + - ]: 2 : if (iblok/=0.and.iblok==kblok) then
2080 : : ! if (opt==1) then
2081 [ + + ]: 6 : call wrtout([ab_out,std_out], ' Frozen-spin Berry curvature of interatomic force constants')
2082 : : ! else if (opt==2) then
2083 : : ! call wrtout([ab_out,std_out], ' Relaxed-spin Berry curvature of interatomic force constants')
2084 : : ! end if
2085 [ + + ]: 6 : call wrtout([ab_out,std_out], ' atom1 dir atom2 dir Real Imag')
2086 [ + + ]: 14 : do ipert1= 1, natom
2087 [ + + ]: 50 : do idir1= 1, 3
2088 : 36 : irow=( ipert1-1)*3 + idir1
2089 [ + + ]: 252 : do ipert2= 1, natom
2090 [ + + ]: 900 : do idir2= 1, 3
2091 : 648 : icol=( ipert2-1)*3 + idir2
2092 : : index = idir1 + &
2093 : : & 3*((ipert1 - 1) + mpert*((idir2 - 1) + &
2094 : 648 : & 3*((ipert2 -1 ) + mpert*((idir3 - 1) + 3*(ipert3 - 1)))))
2095 [ + + ]: 1944 : val(:)=blkval(:,index,kblok)
2096 : : write(msg,'(2(i4,4x,a2,2x),2x,2es18.9)') &
2097 : 648 : & ipert1, cart(idir1), ipert2, cart(idir2), val(1), val(2)
2098 [ + + ]: 2160 : call wrtout([ab_out,std_out], msg)
2099 : : end do
2100 : : end do
2101 [ + + ]: 120 : call wrtout([ab_out,std_out], ' ')
2102 : : end do
2103 : : end do
2104 : : end if
2105 : : end if
2106 : :
2107 [ + + ]: 2 : if (qeq0) then
2108 : :
2109 : : !Born charges
2110 [ + + ]: 3 : rfphon(1:2)=1
2111 [ + + ]: 3 : rfelfd(1:2)=2
2112 : : call ddb_lw%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, omega=omega, &
2113 : 1 : & rffreq=rffreq)
2114 [ + - + - ]: 1 : if (iblok/=0.and.iblok==kblok) then
2115 : : ! if (opt==1) then
2116 [ + + ]: 3 : call wrtout([ab_out,std_out], ' Frozen-spin Berry curvature of Born effective charges')
2117 : : ! else if (opt==2) then
2118 : : ! call wrtout([ab_out,std_out], ' Relaxed-spin Berry curvature of Born effective charges')
2119 : : ! end if
2120 [ + + ]: 3 : call wrtout([ab_out,std_out], ' E-dir atom dir Real Imag')
2121 : 1 : ipert1= natom + 2
2122 [ + + ]: 4 : do idir1= 1, 3
2123 [ + + ]: 21 : do ipert2= 1, natom
2124 [ + + ]: 75 : do idir2= 1, 3
2125 : : index = idir1 + &
2126 : : & 3*((ipert1 - 1) + mpert*((idir2 - 1) + &
2127 : 54 : & 3*((ipert2 -1 ) + mpert*((idir3 - 1) + 3*(ipert3 - 1)))))
2128 [ + + ]: 162 : val(:)=blkval(:,index,kblok)
2129 : : write(msg,'(3x,a2,7x,i3,4x,a2,2x,2es18.9)') &
2130 : 54 : & cart(idir1), ipert2, cart(idir2), val(1), val(2)
2131 [ + + ]: 180 : call wrtout([ab_out,std_out], msg)
2132 : : end do
2133 : : end do
2134 [ + + ]: 10 : call wrtout([ab_out,std_out], ' ')
2135 : : end do
2136 : : end if
2137 : :
2138 : : !Dielectric tensor
2139 : : iblok=0
2140 : 1 : rfphon(:)=0
2141 [ + + ]: 3 : rfelfd(1:2)=2
2142 : : call ddb_lw%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, omega=omega, &
2143 : 1 : & rffreq=rffreq)
2144 [ + - + - ]: 1 : if (iblok/=0.and.iblok==kblok) then
2145 : : ! if (opt==1) then
2146 [ + + ]: 3 : call wrtout([ab_out,std_out], ' Frozen-spin Berry curvature of clamped-ion dielectric tensor')
2147 : : ! else if (opt==2) then
2148 : : ! call wrtout([ab_out,std_out], ' Relaxed-spin Berry curvature of clamped-ion dielectric tensor')
2149 : : ! end if
2150 [ + + ]: 3 : call wrtout([ab_out,std_out], ' dir dir Real Imag')
2151 : 1 : ipert1= ddb_lw%natom + 2
2152 : 1 : ipert2= ddb_lw%natom + 2
2153 [ + + ]: 4 : do idir2= 1, 3
2154 [ + + ]: 12 : do idir1= 1, 3
2155 : : index = idir1 + &
2156 : : & 3*((ipert1 - 1) + mpert*((idir2 - 1) + &
2157 : 9 : & 3*((ipert2 -1 ) + mpert*((idir3 - 1) + 3*(ipert3 - 1)))))
2158 [ + + ]: 27 : val(:)=blkval(:,index,kblok)
2159 : 9 : write(msg,'(2x,a2,3x,a2,2x,2es18.9)' ) cart(idir1), cart(idir2), &
2160 : 18 : & val(1), val(2)
2161 [ + + ]: 30 : call wrtout([ab_out,std_out], msg)
2162 : : end do
2163 [ + + ]: 10 : call wrtout([ab_out,std_out], ' ')
2164 : : end do
2165 : : end if
2166 : :
2167 : : !Magnetoelectric susceptibility
2168 : : iblok=0
2169 : 1 : rfphon(:)=0
2170 : 1 : rfelfd(1)=0
2171 : 1 : rfelfd(2)=2
2172 : 1 : rfmagn(1)=1
2173 : : rfmagn(2)=0
2174 : : call ddb_lw%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, omega=omega, &
2175 : 1 : & rfmagn=rfmagn,rffreq=rffreq)
2176 [ + - + - ]: 1 : if (iblok/=0.and.iblok==kblok) then
2177 : : ! if (opt==1) then
2178 [ + + ]: 3 : call wrtout([ab_out,std_out], ' Frozen-spin Berry curvature of clamped-ion magnetoelectric susceptibility')
2179 : : ! else if (opt==2) then
2180 : : ! call wrtout([ab_out,std_out], ' Relaxed-spin Berry curvature of clamped-ion magnetoelectric susceptibility')
2181 : : ! end if
2182 [ + + ]: 3 : call wrtout([ab_out,std_out], ' M-dir E-dir Real Imag')
2183 : 1 : ipert1= ddb_lw%natom + 5
2184 : 1 : ipert2= ddb_lw%natom + 2
2185 [ + + ]: 4 : do idir2= 1, 3
2186 [ + + ]: 12 : do idir1= 1, 3
2187 : : index = idir1 + &
2188 : : & 3*((ipert1 - 1) + mpert*((idir2 - 1) + &
2189 : 9 : & 3*((ipert2 -1 ) + mpert*((idir3 - 1) + 3*(ipert3 - 1)))))
2190 [ + + ]: 27 : val(:)=blkval(:,index,kblok)/ucvol
2191 : 9 : write(msg,'(2x,a2,3x,a2,2x,2es18.9)' ) cart(idir1), cart(idir2), &
2192 : 18 : & val(1), val(2)
2193 [ + + ]: 30 : call wrtout([ab_out,std_out], msg)
2194 : : end do
2195 [ + + ]: 10 : call wrtout([ab_out,std_out], ' ')
2196 : : end do
2197 : : end if
2198 : :
2199 : : end if
2200 : :
2201 : : !Magnetic susceptibility
2202 : : iblok=0
2203 : 2 : rfphon(:)=0
2204 : 2 : rfelfd(:)=0
2205 : 2 : rfmagn(1)=1
2206 : 2 : rfmagn(2)=1
2207 : : call ddb_lw%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, omega=omega, &
2208 : 2 : & rfmagn=rfmagn,rffreq=rffreq)
2209 [ + - + - ]: 2 : if (iblok/=0.and.iblok==kblok) then
2210 : : ! if (opt==1) then
2211 [ + + ]: 6 : call wrtout([ab_out,std_out], ' Frozen-spin Berry curvature of clamped-ion magnetic susceptibility')
2212 : : ! else if (opt==2) then
2213 : : ! call wrtout([ab_out,std_out], ' Relaxed-spin Berry curvature of clamped-ion magnetic susceptibility')
2214 : : ! end if
2215 [ + + ]: 6 : call wrtout([ab_out,std_out], ' dir dir Real Imag')
2216 : 2 : ipert1= ddb_lw%natom + 5
2217 : 2 : ipert2= ddb_lw%natom + 5
2218 [ + + ]: 8 : do idir2= 1, 3
2219 [ + + ]: 24 : do idir1= 1, 3
2220 : : index = idir1 + &
2221 : : & 3*((ipert1 - 1) + mpert*((idir2 - 1) + &
2222 : 18 : & 3*((ipert2 -1 ) + mpert*((idir3 - 1) + 3*(ipert3 - 1)))))
2223 [ + + ]: 54 : val(:)=blkval(:,index,kblok)/ucvol
2224 : 18 : write(msg,'(2x,a2,3x,a2,2x,2es18.9)' ) cart(idir1), cart(idir2), &
2225 : 36 : & val(1), val(2)
2226 [ + + ]: 60 : call wrtout([ab_out,std_out], msg)
2227 : : end do
2228 [ + + ]: 20 : call wrtout([ab_out,std_out], ' ')
2229 : : end do
2230 : : end if
2231 : :
2232 : : !Magnetic Born effective charges
2233 : : iblok=0
2234 : 2 : rfphon(1)=1
2235 : 2 : rfelfd(:)=0
2236 : 2 : rfmagn(1)=0
2237 : : rfmagn(2)=1
2238 : : call ddb_lw%get_block(iblok, qphon, qphnrm, rfphon, rfelfd, rfstrs, rftyp, omega=omega, &
2239 : 2 : & rfmagn=rfmagn,rffreq=rffreq)
2240 [ + - + - ]: 2 : if (iblok/=0.and.iblok==kblok) then
2241 : : ! if (opt==1) then
2242 [ + + ]: 6 : call wrtout([ab_out,std_out], ' Frozen-spin Berry curvature of magnetic Born effective charges')
2243 : : ! else if (opt==2) then
2244 : : ! call wrtout([ab_out,std_out], ' Relaxed-spin Berry curvature of magnetic Born effective charges')
2245 : : ! end if
2246 [ + + ]: 6 : call wrtout([ab_out,std_out], ' atom dir B-dir Real Imag')
2247 : :
2248 : 2 : ipert2= ddb_lw%natom + 5
2249 [ + + ]: 14 : do ipert1= 1, natom
2250 [ + + ]: 48 : do idir1= 1, 3
2251 [ + + ]: 156 : do idir2= 1, 3
2252 : : index = idir1 + &
2253 : : & 3*((ipert1 - 1) + mpert*((idir2 - 1) + &
2254 : 108 : & 3*((ipert2 -1 ) + mpert*((idir3 - 1) + 3*(ipert3 - 1)))))
2255 [ + + ]: 324 : val(:)=blkval(:,index,kblok)
2256 : : write(msg,'(i3,4x,a2,7x,a2,2x,2es18.9)') &
2257 : 108 : & ipert1, cart(idir1), cart(idir2), val(1), val(2)
2258 [ + + ]: 360 : call wrtout([ab_out,std_out], msg)
2259 : : end do
2260 : : end do
2261 [ + + ]: 38 : call wrtout([ab_out,std_out], ' ')
2262 : : end do
2263 : : end if
2264 : :
2265 : 2 : end subroutine mp_d3etot_print
2266 : : !!***
2267 : :
2268 [ + - + - : 41464 : end module m_ddb_magpen
+ - + - +
- - + - +
+ - + - +
- + - +
- ]
2269 : : !!***
|