Branch data Line data Source code
1 : : !!****m* ABINIT/m_ddb_flexo
2 : : !! NAME
3 : : !! m_ddb_flexo
4 : : !!
5 : : !! FUNCTION
6 : : !! FIXME: add description.
7 : : !!
8 : : !! COPYRIGHT
9 : : !! Copyright (C) 2019-2026 ABINIT group (MR,MS)
10 : : !! This file is distributed under the terms of the
11 : : !! GNU General Public License, see ~abinit/COPYING
12 : : !! or http://www.gnu.org/copyleft/gpl.txt .
13 : : !!
14 : : !! NOTES
15 : : !!
16 : : !! SOURCE
17 : :
18 : : #if defined HAVE_CONFIG_H
19 : : #include "config.h"
20 : : #endif
21 : :
22 : : #include "abi_common.h"
23 : :
24 : : module m_ddb_flexo
25 : :
26 : : use defs_basis
27 : : use m_abicore
28 : : use m_profiling_abi
29 : : use m_errors
30 : :
31 : : use m_fstrings, only : itoa,sjoin
32 : : use m_ddb_hdr
33 : : use m_ddb
34 : : use m_crystal, only : crystal_t
35 : : use m_dynmat, only : asria_corr,cart39
36 : :
37 : : implicit none
38 : :
39 : : private
40 : :
41 : : public :: ddb_flexo
42 : : public :: ddb_phi1
43 : : ! *************************************************************************
44 : :
45 : : contains
46 : : !!***
47 : :
48 : : !!****f* ABINIT/m_ddb_flexo/ddb_flexo
49 : : !! NAME
50 : : !! ddb_flexo
51 : : !!
52 : : !! FUNCTION
53 : : !! Get all the contributions to the flexoelectric tensor
54 : : !!
55 : : !! INPUTS
56 : : !! asr= if /=0 acustic sume rule is imposed on the dynamical matrix
57 : : !! d2asr(2,3,natom,3,natom)=ASR-correction
58 : : !! ddb<type(ddb_type)>=2nd order derivative database.
59 : : !! ddb_lw<type(ddb_type)>=Long wave 3rd order derivative database.
60 : : !! ddb_version = 8 digit integer giving date. To mantain compatibility with old DDB files.
61 : : !! Crystal<type(crystal_t)>=Crystal structure parameters
62 : : !! filnamddb = name of the ddb file
63 : : !! flexoflg= 1 -> Computes all contributions to FxE
64 : : !! 2 -> Computes electronic (clamped ion) contribution to FxE
65 : : !! 3 -> Computes mixed contribution to FxE
66 : : !! 4 -> Computes lattice contribution to FxE
67 : : !! prtvol= if > 1 print all individual quantities of the lattice contribution FxE
68 : : !! zeff(3,3,natom)= Born Effective charges
69 : : !!
70 : : !! OUTPUT
71 : : !!
72 : : !! SIDE EFFECTS
73 : : !!
74 : : !! NOTES
75 : : !!
76 : : !! SOURCE
77 : :
78 : 2 : subroutine ddb_flexo(asr,d2asr,ddb,ddb_lw,ddb_version,crystal,filnamddb,flexoflg,prtvol,zeff)
79 : :
80 : : !Arguments ------------------------------------
81 : : !scalars
82 : : integer,intent(in) :: ddb_version
83 : : integer , intent(in) :: asr,flexoflg,prtvol
84 : : class(ddb_type),intent(in) :: ddb,ddb_lw
85 : : type(crystal_t),intent(in) :: crystal
86 : : character(len=fnlen) :: filnamddb
87 : : !arrays
88 : : real(dp),intent(in) :: d2asr(2,3,ddb%natom,3,ddb%natom)
89 : : real(dp),intent(in) :: zeff(3,3,ddb%natom)
90 : :
91 : : !Local variables-------------------------------
92 : : integer :: elfd,iblok,ivar,jblok,kblok,lblok,lwsym,qvecd
93 : : logical :: intstrn_only,iwrite
94 : : character(len=500) :: msg
95 : :
96 : : !arrays
97 : : integer,parameter :: alpha(6)=(/1,2,3,2,1,1/),beta(6)=(/1,2,3,3,3,2/)
98 : : integer :: rfelfd(4),rfphon(4),rfstrs(4)
99 : : integer :: rfqvec(4)
100 : : real(dp) :: qphnrm(3),qphon(3,3)
101 : : real(dp) :: ciflexo(3,3,3,3)
102 : 4 : real(dp) :: intstrn(3,3,3,ddb%natom)
103 : 4 : real(dp) :: piezofr(3,ddb%natom,3,3)
104 : : real(dp) :: lattflexo(3,3,3,3)
105 : : real(dp) :: mixflexo(3,3,3,3)
106 : 4 : real(dp) :: pol1(3,3,3,ddb%natom)
107 : 4 : real(dp) :: psinvdm(3*ddb%natom,3*ddb%natom)
108 : : real(dp) :: totflexo(3,3,3,3)
109 : : character(len=2) :: voigt(9)=(/'xx','yy','zz','yz','xz','xy','zy','zx','yx'/)
110 : :
111 : : ! *************************************************************************
112 : :
113 : : DBG_ENTER("COLL")
114 : :
115 : : ! First get the clamped-ion flexoelectric tensor
116 : 2 : ciflexo(:,:,:,:)=zero
117 [ + - ]: 2 : if (flexoflg==1.or.flexoflg==2) then
118 : :
119 : : rfphon(:)=0
120 : 2 : rfelfd(:)=0
121 : 2 : rfstrs(:)=0
122 : 2 : rfqvec(:)=0
123 : :
124 : : ! Look for the Gamma Block in the DDB
125 : 2 : qphon(:,:)=zero
126 [ + + ]: 8 : qphnrm(:)=one
127 : 2 : rfphon(:)=0
128 : 2 : rfelfd(1)=2
129 : 2 : rfstrs(2)=3
130 : 2 : rfqvec(3)=1
131 : :
132 : 2 : write(msg, '(2a)' ) ch10," Extract the electronic flexoelectric coeficients from 3DTE"
133 : 2 : call wrtout(std_out,msg,'COLL')
134 : 2 : call ddb_lw%get_block(iblok,qphon,qphnrm,rfphon,rfelfd,rfstrs,BLKTYP_d3E_lw,rfqvec=rfqvec)
135 : :
136 [ - + ]: 2 : if (iblok == 0) then
137 : 0 : call wrtout(std_out, " ")
138 : 0 : call wrtout(std_out, "--- !WARNING")
139 : 0 : call wrtout(std_out, sjoin("- Cannot find clamped ion FxE tensor in DDB file:", filnamddb))
140 : 0 : call wrtout(std_out, " flexoflag=1 or 2 requires the DDB file to include the corresponding long wave 3rd derivatives")
141 : : else
142 : 2 : call dtciflexo(ddb_lw%val(:,:,iblok),ddb_version,ddb%mpert,ddb%natom,ciflexo,crystal%ucvol)
143 : : end if
144 : :
145 : : end if
146 : :
147 : : ! Then get the mixed contribution to the flexoelectric tensor
148 : : !Activate the calculation of internal strain necessary for lattice mediated contribution.
149 [ - + ]: 2 : intstrn_only=.false.;if (flexoflg==4) intstrn_only=.true.
150 : 2 : mixflexo(:,:,:,:)=zero
151 [ - + - - ]: 2 : if (flexoflg==1.or.flexoflg==3.or.intstrn_only) then
152 : :
153 : : ! Extract the P^(1) tensor from the DDB
154 [ + - ]: 2 : if (.not.intstrn_only) then
155 : 2 : lwsym=0
156 : 2 : iblok = ddb_lw%get_quadrupoles(ddb_version,lwsym,BLKTYP_d3E_lw,pol1)
157 : : end if
158 : :
159 : 2 : rfphon(:)=0
160 : 2 : rfelfd(:)=0
161 : 2 : rfstrs(:)=0
162 : 2 : rfqvec(:)=0
163 : :
164 : : ! Look for the Gamma Block of the Phi^(1) tensor in the DDB
165 : 2 : qphon(:,:)=zero
166 [ + + ]: 8 : qphnrm(:)=one
167 : 2 : rfphon(1)=1
168 : 2 : rfphon(2)=1
169 : 2 : rfqvec(3)=1
170 : :
171 : 2 : write(msg, '(2a)' ) ch10," Extract the Phi^(1) coeficients from 3DTE"
172 : 2 : call wrtout(std_out,msg,'COLL')
173 : 2 : call ddb_lw%get_block(iblok,qphon,qphnrm,rfphon,rfelfd,rfstrs,BLKTYP_d3E_lw,rfqvec=rfqvec)
174 : :
175 [ - + ]: 2 : if (iblok == 0) then
176 : 0 : call wrtout(std_out, " ")
177 : 0 : call wrtout(std_out, "--- !WARNING")
178 : 0 : call wrtout(std_out, sjoin("- Cannot find Phi^(1) tensor in DDB file:", filnamddb))
179 : 0 : call wrtout(std_out, " flexoflag=1 or 3 requires the DDB file to include the corresponding long wave 3rd derivatives")
180 : : end if
181 : :
182 : : ! Look for th block that contains the forces
183 : 2 : qphon(:,:)=zero
184 [ + + ]: 8 : qphnrm(:)=one
185 : 2 : rfphon(:)=0
186 : 2 : rfphon(4)=1
187 : :
188 : 2 : write(msg, '(2a)' ) ch10," Extract the forces from 1DTE"
189 : 2 : call wrtout(std_out,msg,'COLL')
190 : 2 : call ddb%get_block(kblok,qphon,qphnrm,rfphon,rfelfd,rfstrs,4)
191 : :
192 [ - + ]: 2 : if (kblok == 0) then
193 : 0 : call wrtout(std_out, " ")
194 : 0 : call wrtout(std_out, "--- !WARNING")
195 : 0 : call wrtout(std_out, sjoin("- Cannot find forces in DDB file:", filnamddb))
196 : 0 : call wrtout(std_out, " If there are nonzero residual atomic forces on the structure")
197 : 0 : call wrtout(std_out, " flexoflag=1 or 3 will produce an improper piezoelectric force response tensor")
198 : 0 : call wrtout(std_out, " and a wrong value for the mixed contribution to the flexoelectric tensor")
199 : : end if
200 : :
201 : : ! Look for the Gamma Block of the dynamical matrix in the DDB
202 : 2 : qphon(:,:)=zero
203 [ + + ]: 8 : qphnrm(:)=one
204 : 2 : rfphon(:)=0
205 [ + + ]: 6 : rfphon(1:2)=1
206 : :
207 : 2 : write(msg, '(2a)' ) ch10," Extract the Dynamical Matrix from 2DTE"
208 : 2 : call wrtout(std_out,msg,'COLL')
209 : 2 : call ddb%get_block(jblok,qphon,qphnrm,rfphon,rfelfd,rfstrs,1)
210 : :
211 [ - + ]: 2 : if (jblok == 0) then
212 : 0 : call wrtout(std_out, " ")
213 : 0 : call wrtout(std_out, "--- !WARNING")
214 : 0 : call wrtout(std_out, sjoin("- Cannot find Gamma point Dynamical Matrix in DDB file:", filnamddb))
215 : 0 : call wrtout(std_out, " flexoflag=1 or 3 requires the DDB file to include the corresponding 2nd derivatives")
216 : : end if
217 : :
218 [ + - + - ]: 2 : if (iblok/=0.and.jblok/=0) then
219 : : call dtmixflexo(asr,d2asr,ddb%val(:,:,kblok),ddb%val(:,:,jblok),ddb_lw%val(:,:,iblok),ddb_version,crystal%gprimd,&
220 : 2 : & intstrn,intstrn_only,mixflexo,ddb%mpert,ddb%natom,piezofr,pol1,psinvdm,crystal%rprimd,crystal%ucvol)
221 : : end if
222 : :
223 : : end if
224 : :
225 : : ! Finally get the lattice mediated contribution to the flexoelectric tensor
226 : 2 : lattflexo(:,:,:,:)=zero
227 [ + - ]: 2 : if (flexoflg==1.or.flexoflg==4) then
228 : :
229 : 2 : rfphon(:)=0
230 : 2 : rfelfd(:)=0
231 : 2 : rfstrs(:)=0
232 : 2 : rfqvec(:)=0
233 : :
234 : : ! Look for the Gamma Block of the Phi^(1) tensor in the DDB
235 : 2 : qphon(:,:)=zero
236 [ + + ]: 8 : qphnrm(:)=one
237 : 2 : rfphon(1)=1
238 : 2 : rfphon(2)=1
239 : 2 : rfqvec(3)=1
240 : :
241 : 2 : write(msg, '(2a)' ) ch10," Extract the Phi^(1) coeficients from 3DTE"
242 : 2 : call wrtout(std_out,msg,'COLL')
243 : 2 : call ddb_lw%get_block(iblok,qphon,qphnrm,rfphon,rfelfd,rfstrs,BLKTYP_d3E_lw,rfqvec=rfqvec)
244 : :
245 [ - + ]: 2 : if (iblok == 0) then
246 : 0 : call wrtout(std_out, " ")
247 : 0 : call wrtout(std_out, "--- !WARNING")
248 : 0 : call wrtout(std_out, sjoin("- Cannot find Phi^(1) tensor in DDB file:", filnamddb))
249 : 0 : call wrtout(std_out, " flexoflag=1 or 4 requires the DDB file to include the corresponding long wave 3rd derivatives")
250 : : end if
251 : :
252 : : ! Look for the Gamma Block of the flexoelectric force response tensor in the DDB
253 : 2 : qphon(:,:)=zero
254 [ + + ]: 8 : qphnrm(:)=one
255 : 2 : rfphon(:)=0
256 : 2 : rfphon(1)=1
257 : 2 : rfstrs(2)=3
258 : : rfqvec(3)=1
259 : :
260 : 2 : write(msg, '(2a)' ) ch10," Extract the FxE force response coeficients from 3DTE"
261 : 2 : call wrtout(std_out,msg,'COLL')
262 : 2 : call ddb_lw%get_block(jblok,qphon,qphnrm,rfphon,rfelfd,rfstrs,BLKTYP_d3E_lw,rfqvec=rfqvec)
263 : :
264 [ - + ]: 2 : if (jblok == 0) then
265 : 0 : call wrtout(std_out, " ")
266 : 0 : call wrtout(std_out, "--- !WARNING")
267 : 0 : call wrtout(std_out, sjoin("- Cannot find FxE force response tensor in DDB file:", filnamddb))
268 : 0 : call wrtout(std_out, " flexoflag=1 or 4 requires the DDB file to include the corresponding long wave 3rd derivatives")
269 : : end if
270 : :
271 : : ! Look for the stress tensor in the DDB
272 : 2 : qphon(:,:)=zero
273 [ + + ]: 8 : qphnrm(:)=one
274 : 2 : rfphon(:)=0
275 : 2 : rfstrs(:)=0
276 : 2 : rfqvec(:)=0
277 : 2 : rfstrs(4)=3
278 : :
279 : 2 : write(msg, '(2a)' ) ch10," Extract the stress tensor from 1DTE"
280 : 2 : call wrtout(std_out,msg,'COLL')
281 : 2 : call ddb%get_block(lblok,qphon,qphnrm,rfphon,rfelfd,rfstrs,4)
282 : :
283 [ - + ]: 2 : if (lblok == 0) then
284 : 0 : call wrtout(std_out, " ")
285 : 0 : call wrtout(std_out, "--- !WARNING")
286 : 0 : call wrtout(std_out, sjoin("- Cannot find stress tensor in DDB file:", filnamddb))
287 : 0 : call wrtout(std_out, " flexoflag=1 or 4 requires the DDB file to include the corresponding 2nd derivatives")
288 : 0 : call wrtout(std_out, " to compute the Lagrange Elastic Tensor ")
289 : : end if
290 : :
291 [ + - + - ]: 2 : if (iblok/=0.and.jblok/=0) then
292 : : call dtlattflexo(ddb%amu,ddb%val(:,:,lblok),ddb_lw%val(:,:,jblok),ddb_lw%val(:,:,iblok),ddb_version,&
293 : 2 : & intstrn,lattflexo,ddb%mpert,ddb%natom,crystal%ntypat,piezofr,prtvol,psinvdm,crystal%typat,crystal%ucvol,zeff)
294 : : end if
295 : : end if
296 : :
297 : : !Merge the three contributions and print the total FxE tensor
298 [ + + + + : 242 : totflexo(:,:,:,:)=ciflexo(:,:,:,:)+mixflexo(:,:,:,:)+lattflexo(:,:,:,:)
+ + + + ]
299 : :
300 : 2 : iwrite = ab_out > 0
301 [ + - ]: 2 : if (iwrite) then
302 : 2 : write(msg,'(3a)')ch10,' TOTAL flexoelectric tensor (units= nC/m) ',ch10
303 [ + + ]: 6 : call wrtout([ab_out,std_out],msg,'COLL')
304 : 2 : write(msg,*)' xx yy zz yz xz xy'
305 [ + + ]: 6 : call wrtout([ab_out,std_out],msg,'COLL')
306 [ + + ]: 14 : do ivar=1,6
307 : 12 : elfd=alpha(ivar)
308 : 12 : qvecd=beta(ivar)
309 : 12 : write(msg,'(3x,a2,6f12.6)') voigt(ivar),totflexo(elfd,qvecd,1,1),totflexo(elfd,qvecd,2,2),totflexo(elfd,qvecd,3,3),&
310 : 24 : totflexo(elfd,qvecd,2,3),totflexo(elfd,qvecd,1,3),totflexo(elfd,qvecd,1,2)
311 [ + + ]: 38 : call wrtout([ab_out,std_out],msg,'COLL')
312 : : end do
313 [ + + ]: 8 : do ivar=4,6
314 : 6 : elfd=beta(ivar)
315 : 6 : qvecd=alpha(ivar)
316 : 6 : write(msg,'(3x,a2,6f12.6)') voigt(ivar+3),totflexo(elfd,qvecd,1,1),totflexo(elfd,qvecd,2,2),totflexo(elfd,qvecd,3,3),&
317 : 12 : totflexo(elfd,qvecd,2,3),totflexo(elfd,qvecd,1,3),totflexo(elfd,qvecd,1,2)
318 [ + + ]: 20 : call wrtout([ab_out,std_out],msg,'COLL')
319 : : end do
320 : : end if
321 : :
322 : :
323 : : DBG_EXIT("COLL")
324 : :
325 : 2 : end subroutine ddb_flexo
326 : : !!***
327 : :
328 : : !!****f* m_ddb/dtciflexo
329 : : !! NAME
330 : : !! dtciflexo
331 : : !!
332 : : !! FUNCTION
333 : : !! Reads the Clamped Ion Flexoelectric Tensor
334 : : !! in the Gamma Block coming from the Derivative Data Base
335 : : !! (long wave third-order derivatives).
336 : : !!
337 : : !! INPUTS
338 : : !! blkval(2,3*mpert*3*mpert*3*mpert)= matrix of third-order energies
339 : : !! mpert =maximum number of ipert
340 : : !! natom= number of atoms in unit cell
341 : : !! ddb_version = 8 digit integer giving date. To mantain compatibility with old DDB files.
342 : : !! ucvol= unit cell volume
343 : : !!
344 : : !! OUTPUT
345 : : !! ciflexo(3,3,3,3) = type-II Clamped Ion Flexoelectric Tensor
346 : : !!
347 : : !! SOURCE
348 : :
349 : 2 : subroutine dtciflexo(blkval,ddb_version,mpert,natom,ciflexo,ucvol)
350 : :
351 : : !Arguments -------------------------------
352 : : !scalars
353 : : integer,intent(in) :: ddb_version,mpert,natom
354 : : real(dp),intent(in) :: ucvol
355 : : !arrays
356 : : real(dp),intent(in) :: blkval(2,3*mpert*3*mpert*3*mpert)
357 : : real(dp),intent(out) :: ciflexo(3,3,3,3)
358 : :
359 : : !Local variables -------------------------
360 : : !scalars
361 : : integer,parameter :: cvrsio8=20100401
362 : : integer :: elfd,istrs,ivarA,ri,strsd,strsd1,strsd2,strst,qvecd
363 : : logical :: iwrite
364 : : real(dp) :: fac
365 : : character(len=500) :: msg
366 : : real(dp),parameter :: confac=e_Cb/Bohr_meter*1.d9
367 : : !arrays
368 : : integer,parameter :: alpha(6)=(/1,2,3,2,1,1/),beta(6)=(/1,2,3,3,3,2/)
369 : 4 : real(dp) :: d3cart(2,3,mpert,3,mpert,3,mpert)
370 : : character(len=2) :: voigt(9)=(/'xx','yy','zz','yz','xz','xy','zy','zx','yx'/)
371 : :
372 : : ! *********************************************************************
373 : :
374 : : DBG_ENTER("COLL")
375 : :
376 [ + + + + : 375606 : d3cart(1,:,:,:,:,:,:) = reshape(blkval(1,:),shape = (/3,mpert,3,mpert,3,mpert/))
+ + + + +
+ + + +
+ ]
377 [ + + + + : 375606 : d3cart(2,:,:,:,:,:,:) = reshape(blkval(2,:),shape = (/3,mpert,3,mpert,3,mpert/))
+ + + + +
+ + + +
+ ]
378 : :
379 : : !Define the factors to apply if DDB file has been created with the old version of
380 : : !the longwave driver.
381 [ + + ]: 2 : if (ddb_version <= cvrsio8) then
382 : 1 : fac=-two/ucvol
383 : 1 : ri=2
384 : : else
385 : 1 : fac=one/ucvol
386 : 1 : ri=1
387 : : end if
388 : :
389 : : !Extraction of the clamped-ion flexoelectric coeficients
390 [ + + ]: 8 : do qvecd=1,3
391 [ + + ]: 44 : do istrs=1,6
392 : 36 : strsd1=alpha(istrs)
393 : 36 : strsd2=beta(istrs)
394 [ + + ]: 36 : strst=natom+3; if (istrs>3) strst=natom+4
395 : 18 : strsd=istrs; if (istrs>3) strsd=istrs-3
396 [ + + ]: 150 : do elfd=1,3
397 : 108 : ciflexo(elfd,qvecd,strsd1,strsd2)=fac*d3cart(ri,elfd,natom+2,strsd,strst,qvecd,natom+8)*confac
398 [ + + ]: 144 : if (istrs>3) ciflexo(elfd,qvecd,strsd2,strsd1)=ciflexo(elfd,qvecd,strsd1,strsd2)
399 : : end do
400 : : end do
401 : : end do
402 : :
403 : : !Print results
404 : 2 : iwrite = ab_out > 0
405 [ + - ]: 2 : if (iwrite) then
406 : 2 : write(msg,'(3a)')ch10,' Type-II electronic (clamped ion) flexoelectric tensor (units= nC/m) ',ch10
407 [ + + ]: 6 : call wrtout([ab_out,std_out],msg,'COLL')
408 : 2 : write(msg,*)' xx yy zz yz xz xy'
409 [ + + ]: 6 : call wrtout([ab_out,std_out],msg,'COLL')
410 [ + + ]: 14 : do ivarA=1,6
411 : 12 : elfd=alpha(ivarA)
412 : 12 : qvecd=beta(ivarA)
413 : 12 : write(msg,'(3x,a2,6f12.6)') voigt(ivarA), ciflexo(elfd,qvecd,1,1),ciflexo(elfd,qvecd,2,2), &
414 : 12 : ciflexo(elfd,qvecd,3,3), ciflexo(elfd,qvecd,2,3), &
415 : 24 : ciflexo(elfd,qvecd,1,3),ciflexo(elfd,qvecd,1,2)
416 [ + + ]: 38 : call wrtout([ab_out,std_out],msg,'COLL')
417 : : end do
418 [ + + ]: 8 : do ivarA=4,6
419 : 6 : elfd=beta(ivarA)
420 : 6 : qvecd=alpha(ivarA)
421 : 6 : write(msg,'(3x,a2,6f12.6)') voigt(ivarA+3), ciflexo(elfd,qvecd,1,1),ciflexo(elfd,qvecd,2,2), &
422 : 6 : ciflexo(elfd,qvecd,3,3), ciflexo(elfd,qvecd,2,3), &
423 : 12 : ciflexo(elfd,qvecd,1,3),ciflexo(elfd,qvecd,1,2)
424 [ + + ]: 20 : call wrtout([ab_out,std_out],msg,'COLL')
425 : : end do
426 : : end if
427 : :
428 : : DBG_EXIT("COLL")
429 : :
430 : 2 : end subroutine dtciflexo
431 : : !!***
432 : :
433 : : !!****f* m_ddb/dtmixflexo
434 : : !! NAME
435 : : !! dtmixflexo
436 : : !!
437 : : !! FUNCTION
438 : : !! Reads the P^(1) and Phi^(1) tensors
439 : : !! in the Gamma Block coming from the Derivative Data Base
440 : : !! (long wave third-order derivatives). And computes the mixed
441 : : !! contribution to the flexoelectric tensor.
442 : : !!
443 : : !! INPUTS
444 : : !! asr= if /=0 acustic sume rule is imposed on the dynamical matrix
445 : : !! d2asr(2,3,natom,3,natom)=ASR-correction
446 : : !! blkval1d(2,3,mpert,3,mpert)= 1st derivative wrt atom displacements (at least)
447 : : !! blkval2d(2,3,mpert,3,mpert)= 2nd derivatives wrt two atom displacements (at least)
448 : : !! blkval(2,3*mpert*3*mpert*3*mpert)= matrix of third-order energies for Phi^(1) tensor
449 : : !! ddb_version = 8 digit integer giving date. To mantain compatibility with old DDB files.
450 : : !! gprimd(3,3)= basis vectors in the reciprocal space
451 : : !! intstrn_only= activates only the calculation of the internal strain tensor
452 : : !! mpert =maximum number of ipert
453 : : !! natom= number of atoms in unit cell
454 : : !! piezofr(3,natom,3,3)= piezoelectric force response tensor
455 : : !! pol1(3,3,3,natom)= tensor with the polarization induced by an atomic displacement (P^(1))
456 : : !! rprimd(3,3)= basis vectors in the real space
457 : : !! ucvol= unit cell volume
458 : : !!
459 : : !! OUTPUT
460 : : !! mixflexo(3,3,3,3) = type-II mixed contribution to the Flexoelectric Tensor
461 : : !! intstrn(3,3,3,natom) = relaxed-ion internal strain tensor
462 : : !! psinvdm(3*natom,3*natom) = pseudo inverse of dynamical matrix
463 : : !!
464 : : !! SOURCE
465 : :
466 : 2 : subroutine dtmixflexo(asr,d2asr,blkval1d,blkval2d,blkval,ddb_version,gprimd,intstrn,intstrn_only, &
467 : 2 : & mixflexo,mpert,natom,piezofr,pol1,psinvdm,rprimd,ucvol)
468 : :
469 : : !Arguments -------------------------------
470 : : !scalars
471 : : integer,intent(in) :: asr,ddb_version,mpert,natom
472 : : real(dp),intent(in) :: ucvol
473 : : logical,intent(in) :: intstrn_only
474 : : !arrays
475 : : real(dp),intent(in) :: d2asr(2,3,mpert,3,mpert)
476 : : real(dp),intent(in) :: blkval1d(2,3,mpert,3,mpert)
477 : : real(dp),intent(in) :: blkval2d(2,3,mpert,3,mpert)
478 : : real(dp),intent(in) :: blkval(2,3*mpert*3*mpert*3*mpert)
479 : : real(dp),intent(in) :: gprimd(3,3)
480 : : real(dp),intent(out) :: intstrn(3,3,3,natom)
481 : : real(dp),intent(out) :: piezofr(3,natom,3,3)
482 : : real(dp),intent(inout) :: pol1(3,3,3,natom)
483 : : real(dp),intent(out) :: psinvdm(3*natom,3*natom)
484 : : real(dp),intent(in) :: rprimd(3,3)
485 : : real(dp),intent(out) :: mixflexo(3,3,3,3)
486 : :
487 : : !Local variables -------------------------
488 : : !scalars
489 : : integer,parameter :: cvrsio8=20100401
490 : : integer :: elfd,iat,iatd,ivar,jat,jatd,jvar,katd,qvecd,qvecd2
491 : : logical :: iwrite
492 : : real(dp),parameter :: confac=e_Cb/Bohr_meter*1.d9
493 : : real(dp) :: fac
494 : : character(len=500) :: msg
495 : : !arrays
496 : : integer,parameter :: alpha(6)=(/1,2,3,2,1,1/),beta(6)=(/1,2,3,3,3,2/)
497 : 4 : real(dp) :: d3cart(2,3,mpert,3,mpert,3,mpert)
498 : 4 : real(dp) :: redforces(3,natom),forces(3,natom)
499 : 4 : real(dp) :: phi1(3,natom,3,natom,3)
500 : : integer :: flg1(3),flg2(3)
501 : : real(dp) :: vec1(3),vec2(3)
502 : : character(len=2) :: voigt(9)=(/'xx','yy','zz','yz','xz','xy','zy','zx','yx'/)
503 : :
504 : : ! *********************************************************************
505 : :
506 : : DBG_ENTER("COLL")
507 : :
508 [ + + + + : 375606 : d3cart(1,:,:,:,:,:,:) = reshape(blkval(1,:),shape = (/3,mpert,3,mpert,3,mpert/))
+ + + + +
+ + + +
+ ]
509 [ + + + + : 375606 : d3cart(2,:,:,:,:,:,:) = reshape(blkval(2,:),shape = (/3,mpert,3,mpert,3,mpert/))
+ + + + +
+ + + +
+ ]
510 : :
511 : : !P^(1) lacks the 1/ucvol factor
512 [ + + + + : 242 : pol1=pol1/ucvol
+ + + + ]
513 : :
514 : : !Define the factors to apply if DDB file has been created with the old version of
515 : : !the longwave driver.
516 [ + + ]: 2 : if (ddb_version <= cvrsio8) then
517 : : fac=-two
518 : : else
519 : 1 : fac=-one
520 : : end if
521 : :
522 : : !Extraction of Phi^(1) tensor
523 : : phi1(:,:,:,:,:) = fac*RESHAPE(d3cart(2,1:3,1:natom,1:3,1:natom,1:3,natom+8), &
524 [ + + + + : 812 : & SHAPE=[3,natom,3,natom,3])
+ + + + +
+ + + ]
525 : :
526 : : !Extraction of the forces and conversion to cartesian coordinates
527 : : !to acount for the improper contribution
528 [ + + + + ]: 26 : redforces(:,:)=-blkval1d(1,1:3,1:natom,1,1)
529 : :
530 [ + + + + ]: 26 : forces(:,:)=redforces(:,:)
531 [ + + ]: 8 : flg1(:)=1
532 [ + + ]: 8 : do iat=1,natom
533 [ + + ]: 24 : vec1(:)=forces(:,iat)
534 : 6 : call cart39(flg1,flg2,gprimd,iat,natom,rprimd,vec1,vec2)
535 [ + + ]: 26 : forces(:,iat)=vec2(:)
536 : : end do
537 : :
538 : : !Calculate the piezoelectric force-response tensor including the improper contribution
539 [ + + + + : 782 : piezofr(:,:,:,:) = SUM(phi1(1:3,1:natom,1:3,1:natom,1:3), DIM=4)
+ + + + +
+ ]
540 [ + + ]: 8 : do iatd=1,3
541 [ + + + + ]: 80 : piezofr(iatd,:,:,iatd) = piezofr(iatd,:,:,iatd) + TRANSPOSE(forces(:,:))
542 : : end do
543 : :
544 : : !Calculate the ion-relaxed internal strain tensor
545 : : !First we need to obtain the pseudo-inverse of the dynamical matrix
546 : 2 : call dm_psinv(asr,blkval2d,d2asr,ab_out,psinvdm,mpert,natom)
547 : :
548 : : !Perfom the product with the piezo force-response
549 [ + + + + : 242 : intstrn(:,:,:,:)=zero
+ + + + ]
550 [ + + ]: 8 : do qvecd=1,3
551 [ + + ]: 26 : do katd=1,3
552 [ + + ]: 78 : do iatd=1,3
553 [ + + ]: 234 : do iat=1,natom
554 : 162 : ivar=(iat-1)*3+iatd
555 [ + + ]: 702 : do jatd=1,3
556 [ + + ]: 2268 : do jat=1,natom
557 : 1620 : jvar=(jat-1)*3+jatd
558 : :
559 : : intstrn(qvecd,katd,iatd,iat)= intstrn(qvecd,katd,iatd,iat) + &
560 : 2106 : psinvdm(ivar,jvar)*piezofr(jatd,jat,katd,qvecd)
561 : :
562 : : end do
563 : : end do
564 : : end do
565 : : end do
566 : : end do
567 : : end do
568 : :
569 [ + - ]: 2 : if (.not.intstrn_only) then
570 : : !Finally calculate the mixed contribution to the FxE tensor
571 : 2 : mixflexo(:,:,:,:)=zero
572 [ + + ]: 8 : do elfd=1,3
573 [ + + ]: 26 : do qvecd=1,3
574 [ + + ]: 78 : do katd=1,3
575 [ + + ]: 234 : do qvecd2=1,3
576 [ + + ]: 702 : do iatd=1,3
577 [ + + ]: 2106 : do iat=1,natom
578 : :
579 : : mixflexo(elfd,qvecd,katd,qvecd2)=mixflexo(elfd,qvecd,katd,qvecd2) - &
580 : 1944 : pol1(elfd,qvecd,iatd,iat)*intstrn(qvecd2,katd,iatd,iat)*confac
581 : :
582 : : end do
583 : : end do
584 : : end do
585 : : end do
586 : : end do
587 : : end do
588 : : end if
589 : :
590 : : !Print results
591 : 2 : iwrite = ab_out > 0
592 [ + - ]: 2 : if (iwrite) then
593 : 2 : write(msg,'(3a)')ch10,' Force-response internal strain tensor from long-wave magnitudes (units: Hartree/Bohr)',ch10
594 [ + + ]: 6 : call wrtout([ab_out,std_out],msg,'COLL')
595 : 2 : write(msg,*)' atom dir xx yy zz yz xz xy'
596 [ + + ]: 6 : call wrtout([ab_out,std_out],msg,'COLL')
597 [ + + ]: 8 : do iat=1,natom
598 : 6 : write(msg,'(2x,i3,3x,a3,2x,6f12.6)') iat, 'x', piezofr(1,iat,1,1),piezofr(1,iat,2,2),piezofr(1,iat,3,3),&
599 : 12 : piezofr(1,iat,2,3),piezofr(1,iat,1,3),piezofr(1,iat,1,2)
600 [ + + ]: 18 : call wrtout([ab_out,std_out],msg,'COLL')
601 : 6 : write(msg,'(2x,i3,3x,a3,2x,6f12.6)') iat, 'y', piezofr(2,iat,1,1),piezofr(2,iat,2,2),piezofr(2,iat,3,3),&
602 : 12 : piezofr(2,iat,2,3),piezofr(2,iat,1,3),piezofr(2,iat,1,2)
603 [ + + ]: 18 : call wrtout([ab_out,std_out],msg,'COLL')
604 : 6 : write(msg,'(2x,i3,3x,a3,2x,6f12.6)') iat, 'z', piezofr(3,iat,1,1),piezofr(3,iat,2,2),piezofr(3,iat,3,3),&
605 : 12 : piezofr(3,iat,2,3),piezofr(3,iat,1,3),piezofr(3,iat,1,2)
606 [ + + ]: 20 : call wrtout([ab_out,std_out],msg,'COLL')
607 : : end do
608 : :
609 : 2 : write(msg,'(3a)')ch10,' Displacement-response internal strain tensor from long-wave magnitudes (units: Bohr)',ch10
610 [ + + ]: 6 : call wrtout([ab_out,std_out],msg,'COLL')
611 : 2 : write(msg,*)' atom dir xx yy zz yz xz xy'
612 [ + + ]: 6 : call wrtout([ab_out,std_out],msg,'COLL')
613 [ + + ]: 8 : do iat=1,natom
614 : 6 : write(msg,'(2x,i3,3x,a3,2x,6f12.6)') iat, 'x', intstrn(1,1,1,iat),intstrn(2,2,1,iat),intstrn(3,3,1,iat),&
615 : 12 : intstrn(2,3,1,iat),intstrn(1,3,1,iat),intstrn(1,2,1,iat)
616 [ + + ]: 18 : call wrtout([ab_out,std_out],msg,'COLL')
617 : 6 : write(msg,'(2x,i3,3x,a3,2x,6f12.6)') iat, 'y', intstrn(1,1,2,iat),intstrn(2,2,2,iat),intstrn(3,3,2,iat),&
618 : 12 : intstrn(2,3,2,iat),intstrn(1,3,2,iat),intstrn(1,2,2,iat)
619 [ + + ]: 18 : call wrtout([ab_out,std_out],msg,'COLL')
620 : 6 : write(msg,'(2x,i3,3x,a3,2x,6f12.6)') iat, 'z', intstrn(1,1,3,iat),intstrn(2,2,3,iat),intstrn(3,3,3,iat),&
621 : 12 : intstrn(2,3,3,iat),intstrn(1,3,3,iat),intstrn(1,2,3,iat)
622 [ + + ]: 20 : call wrtout([ab_out,std_out],msg,'COLL')
623 : : end do
624 : :
625 [ + - ]: 2 : if (.not.intstrn_only) then
626 : 2 : write(msg,'(3a)')ch10,' Type-II mixed contribution to flexoelectric tensor (units: nC/m)',ch10
627 [ + + ]: 6 : call wrtout([ab_out,std_out],msg,'COLL')
628 : 2 : write(msg,*)' xx yy zz yz xz xy'
629 [ + + ]: 6 : call wrtout([ab_out,std_out],msg,'COLL')
630 [ + + ]: 14 : do ivar=1,6
631 : 12 : elfd=alpha(ivar)
632 : 12 : qvecd=beta(ivar)
633 : 12 : write(msg,'(3x,a2,6f12.6)') voigt(ivar),mixflexo(elfd,qvecd,1,1),mixflexo(elfd,qvecd,2,2),mixflexo(elfd,qvecd,3,3),&
634 : 24 : mixflexo(elfd,qvecd,2,3),mixflexo(elfd,qvecd,1,3),mixflexo(elfd,qvecd,1,2)
635 [ + + ]: 38 : call wrtout([ab_out,std_out],msg,'COLL')
636 : : end do
637 [ + + ]: 8 : do ivar=4,6
638 : 6 : elfd=beta(ivar)
639 : 6 : qvecd=alpha(ivar)
640 : 6 : write(msg,'(3x,a2,6f12.6)') voigt(ivar+3),mixflexo(elfd,qvecd,1,1),mixflexo(elfd,qvecd,2,2),mixflexo(elfd,qvecd,3,3),&
641 : 12 : mixflexo(elfd,qvecd,2,3),mixflexo(elfd,qvecd,1,3),mixflexo(elfd,qvecd,1,2)
642 [ + + ]: 20 : call wrtout([ab_out,std_out],msg,'COLL')
643 : : end do
644 : : end if
645 : : end if
646 : :
647 : : DBG_EXIT("COLL")
648 : :
649 : 2 : end subroutine dtmixflexo
650 : : !!***
651 : :
652 : : !!****f* m_ddb/dtlattflexo
653 : : !! NAME
654 : : !! dtlattflexo
655 : : !!
656 : : !! FUNCTION
657 : : !! Reads Phi^(1), flexoelectric force response and internal strain tensors
658 : : !! in the Gamma Block coming from the Derivative Data Base
659 : : !! (long wave third-order derivatives). And computes the lattice mediated
660 : : !! contribution to the flexoelectric tensor.
661 : : !! It also computes and writes the Lagrangian Elastic tensor.
662 : : !!
663 : : !! INPUTS
664 : : !! amu(ntypat)=mass each atom type in the unit cell
665 : : !! blkval1d(2,3,mpert,3,mpert)= 1st derivative wrt stress (at least)
666 : : !! blkval2d(2,3,mpert,3,mpert)= 2nd derivatives wrt atom displacements and electric field (at least)
667 : : !! blkvalA(2,3*mpert*3*mpert*3*mpert)= matrix of third-order energies for FxE force response tensor
668 : : !! blkvalB(2,3*mpert*3*mpert*3*mpert)= matrix of third-order energies for Phi^(1) tensor
669 : : !! ddb_version = 8 digit integer giving date. To mantain compatibility with old DDB files.
670 : : !! intstrn(3,3,3,natom)= relaxed-ion internal strain tensor
671 : : !! mpert= maximum number of ipert
672 : : !! natom= number of atoms in unit cell
673 : : !! piezofr(3,natom,3,3)= piezoelectric force response tensor (required to compute the Lagrange elastic tensor)
674 : : !! prtvol= if >1 print all tensors entering the structure of lattflexo
675 : : !! psinvdm(3*natom,3*natom) = pseudo inverse of dynamical matrix
676 : : !! typat(natom)= Type of each atom in the unit cell
677 : : !! ucvol= unit cell volume
678 : : !!
679 : : !! OUTPUT
680 : : !! lattflexo(3,3,3,3) = type-II lattice contribution to the Flexoelectric Tensor
681 : : !!
682 : : !! SOURCE
683 : :
684 : 2 : subroutine dtlattflexo(amu,blkval1d,blkvalA,blkvalB,ddb_version,intstrn,lattflexo,mpert,natom,&
685 : 2 : & ntypat,piezofr,prtvol,psinvdm,typat,ucvol,zeff)
686 : :
687 : : !Arguments -------------------------------
688 : : !scalars
689 : : integer,intent(in) :: ddb_version,mpert,natom,ntypat,prtvol
690 : : real(dp),intent(in) :: ucvol
691 : :
692 : : !arrays
693 : : integer,intent(in) :: typat(natom)
694 : : real(dp),intent(in) :: amu(ntypat)
695 : : real(dp),intent(in) :: blkval1d(2,3,mpert,3,mpert)
696 : : real(dp),intent(in) :: blkvalA(2,3*mpert*3*mpert*3*mpert)
697 : : real(dp),intent(in) :: blkvalB(2,3*mpert*3*mpert*3*mpert)
698 : : real(dp),intent(in) :: intstrn(3,3,3,natom)
699 : : real(dp),intent(in) :: piezofr(3,natom,3,3)
700 : : real(dp),intent(in) :: psinvdm(3*natom,3*natom)
701 : : real(dp),intent(in) :: zeff(3,3,natom)
702 : : real(dp),intent(out) :: lattflexo(3,3,3,3)
703 : :
704 : : !Local variables -------------------------
705 : : !scalars
706 : : integer,parameter :: cvrsio8=20100401
707 : : integer :: elfd,iat,iatd,istrs,ivar,jat,jatd,jvar,kat,katd,strsd
708 : : integer :: strsd1,strsd2,strst,qvecd,qvecd2
709 : : logical :: iwrite
710 : : real(dp) :: fac,mtot
711 : : real(dp),parameter :: confac=e_Cb/Bohr_meter*1.d9
712 : : character(len=500) :: msg
713 : : !arrays
714 : : integer,parameter :: alpha(6)=(/1,2,3,2,1,1/),beta(6)=(/1,2,3,3,3,2/)
715 : : real(dp) :: frcelast_t2(3,3,3,3)
716 : 4 : real(dp) :: Csupkap(3,natom,3,3,3),Csupkapsum(3,3,3,3)
717 : 4 : real(dp) :: d3cart(2,3,mpert,3,mpert,3,mpert)
718 : 4 : real(dp) :: flexois(3,natom,3,3,3)
719 : 4 : real(dp) :: flexofr(3,natom,3,3,3)
720 : 4 : real(dp) :: hatCsupkap(3,natom,3,3,3)
721 : : real(dp) :: lmcelast(3,3,3,3)
722 : 4 : real(dp) :: phi1(3,natom,3,natom,3)
723 : : real(dp) :: ricelast_t2(3,3,3,3)
724 : 4 : real(dp) :: roundbkt_k(3,3,3,3,natom)
725 : : real(dp) :: sqrbkt_t1(3,3,3,3)
726 : : real(dp) :: stress(3,3)
727 : : character(len=2) :: voigt(9)=(/'xx','yy','zz','yz','xz','xy','zy','zx','yx'/)
728 : :
729 : : ! MR: Kept for testing
730 : : ! integer :: i,j,k,l
731 : : ! real(dp) :: delik,deljk,delil,deljl
732 : :
733 : : ! *********************************************************************
734 : :
735 : : DBG_ENTER("COLL")
736 : :
737 : : !Extraction of the stress tensor
738 : 2 : stress(1,1)=blkval1d(1,1,natom+3,1,1)
739 : 2 : stress(2,2)=blkval1d(1,2,natom+3,1,1)
740 : 2 : stress(3,3)=blkval1d(1,3,natom+3,1,1)
741 : 2 : stress(2,3)=blkval1d(1,1,natom+4,1,1);stress(3,2)=stress(2,3)
742 : 2 : stress(1,3)=blkval1d(1,2,natom+4,1,1);stress(3,1)=stress(1,3)
743 : 2 : stress(1,2)=blkval1d(1,3,natom+4,1,1);stress(2,1)=stress(1,2)
744 : :
745 : : !Calculate the sublattice-dependent round bracket tensor of PRB 88,174106 (2013)
746 : : !First we need to extract the Phi^(1) tensor
747 [ + + + + : 375606 : d3cart(1,:,:,:,:,:,:) = reshape(blkvalB(1,:),shape = (/3,mpert,3,mpert,3,mpert/))
+ + + + +
+ + + +
+ ]
748 [ + + + + : 375606 : d3cart(2,:,:,:,:,:,:) = reshape(blkvalB(2,:),shape = (/3,mpert,3,mpert,3,mpert/))
+ + + + +
+ + + +
+ ]
749 : :
750 : : !Define the factors to apply if DDB file has been created with the old version of
751 : : !the longwave driver.
752 [ + + ]: 2 : if (ddb_version <= cvrsio8) then
753 : : fac=-two
754 : : else
755 : 1 : fac=-one
756 : : end if
757 : :
758 : : phi1(:,:,:,:,:) = fac*RESHAPE(d3cart(2,1:3,1:natom,1:3,1:natom,1:3,natom+8), &
759 [ + + + + : 812 : & SHAPE=[3,natom,3,natom,3])
+ + + + +
+ + + ]
760 : :
761 : : !Now perform the multiplication with the internal strain
762 [ + + + + : 728 : roundbkt_k(:,:,:,:,:)=zero
+ + + + +
+ ]
763 [ + + ]: 8 : do iat=1,natom
764 [ + + ]: 26 : do iatd=1,3
765 [ + + ]: 78 : do qvecd2=1,3
766 [ + + ]: 234 : do jatd=1,3
767 [ + + ]: 702 : do qvecd=1,3
768 [ + + ]: 2106 : do katd=1,3
769 [ + + ]: 6804 : do kat=1,natom
770 : : roundbkt_k(iatd,qvecd,jatd,qvecd2,iat)=roundbkt_k(iatd,qvecd,jatd,qvecd2,iat) &
771 : 6318 : + phi1(iatd,iat,katd,kat,qvecd)*intstrn(qvecd2,jatd,katd,kat)
772 : : end do
773 : : end do
774 : : ! write(100,'(5i3,1x,f12.6)') iat, iatd,qvecd,jatd,qvecd2,roundbkt_k(iatd,qvecd,jatd,qvecd2,iat)
775 : : end do
776 : : end do
777 : : end do
778 : : end do
779 : : end do
780 : :
781 : : !Calculate now the Lagrange elastic tensors
782 : : !First we need to extract the clamped-ion flexoelectric force response tensor
783 [ + + + + : 375606 : d3cart(1,:,:,:,:,:,:) = reshape(blkvalA(1,:),shape = (/3,mpert,3,mpert,3,mpert/))
+ + + + +
+ + + +
+ ]
784 [ + + + + : 375606 : d3cart(2,:,:,:,:,:,:) = reshape(blkvalA(2,:),shape = (/3,mpert,3,mpert,3,mpert/))
+ + + + +
+ + + +
+ ]
785 : :
786 : : !Define the factors to apply if DDB file has been created with the old version of
787 : : !the longwave driver.
788 [ + + ]: 2 : if (ddb_version <= cvrsio8) then
789 : : fac=-two
790 : : else
791 : 1 : fac=one
792 : : end if
793 : :
794 [ + + ]: 14 : do istrs=1,6
795 : 12 : strsd1=alpha(istrs)
796 : 12 : strsd2=beta(istrs)
797 [ + + ]: 12 : strst=natom+3; if (istrs>3) strst=natom+4
798 : 6 : strsd=istrs; if (istrs>3) strsd=istrs-3
799 [ + + ]: 50 : do qvecd=1,3
800 [ + + ]: 156 : do iat=1,natom
801 [ + + ]: 468 : do iatd=1,3
802 : 324 : flexofr(iatd,iat,qvecd,strsd1,strsd2)=fac*d3cart(1,iatd,iat,strsd,strst,qvecd,natom+8)
803 [ + + ]: 432 : if (istrs>3) flexofr(iatd,iat,qvecd,strsd2,strsd1)=flexofr(iatd,iat,qvecd,strsd1,strsd2)
804 : : end do
805 : : end do
806 : : end do
807 : : end do
808 : :
809 : : !Now compute the type-II frozen-ion elastic tensor (without stress corrected)
810 : 2 : fac=one/ucvol
811 [ + + + + : 728 : frcelast_t2(:,:,:,:) = fac*SUM(flexofr(1:3,1:natom,1:3,1:3,1:3), DIM=2)
+ + + + +
+ ]
812 : :
813 : : !Now convert to type-I to obtain the square bracketed tensor of Born and Huang
814 [ + + ]: 8 : do qvecd=1,3
815 [ + + ]: 26 : do strsd2=1,3
816 [ + + ]: 78 : do strsd1=1,3
817 : : sqrbkt_t1(1:3,strsd1,strsd2,qvecd)=half*(frcelast_t2(1:3,qvecd,strsd1,strsd2) + &
818 [ + + ]: 234 : & frcelast_t2(1:3,strsd2,strsd1,qvecd))
819 : : end do
820 : : end do
821 : : end do
822 : :
823 : : !Now correct the stress in the square bracketed tesnor tensor
824 [ + + ]: 8 : do qvecd=1,3
825 [ + + ]: 26 : do strsd2=1,3
826 [ + + ]: 78 : do strsd1=1,3
827 [ + + ]: 234 : do iatd=1,3
828 [ + + ]: 216 : if (iatd==strsd1) then
829 : 54 : sqrbkt_t1(iatd,strsd1,strsd2,qvecd)=sqrbkt_t1(iatd,strsd1,strsd2,qvecd) - stress(strsd2,qvecd)
830 : : endif
831 : : end do
832 : : end do
833 : : end do
834 : : end do
835 : :
836 : : !Now convert back to type-II in order to obtain the frozen ion Lagrange elastic tensor.
837 : 2 : frcelast_t2(:,:,:,:)=zero
838 [ + + ]: 8 : do iatd=1,3
839 [ + + ]: 26 : do qvecd=1,3
840 [ + + ]: 78 : do strsd1=1,3
841 [ + + ]: 234 : do strsd2=1,3
842 : : frcelast_t2(iatd,qvecd,strsd1,strsd2)=sqrbkt_t1(iatd,strsd1,qvecd,strsd2) + &
843 : 216 : & sqrbkt_t1(iatd,strsd2,strsd1,qvecd)-sqrbkt_t1(iatd,qvecd,strsd2,strsd1)
844 : : end do
845 : : end do
846 : : end do
847 : : end do
848 : :
849 : : !MR: kept for testing only. If uncommented the resulting elastic tensors must agree with HWRV's ones
850 : : ! write(ab_out,*)
851 : : ! write(ab_out,*) "Stress tensor"
852 : : ! do i=1,3
853 : : ! write(ab_out,*) stress(i,:)
854 : : ! end do
855 : : ! do i=1,3
856 : : ! do j=1,3
857 : : ! do k=1,3
858 : : ! delik=0.d0; if(i==k) delik=1.d0
859 : : ! deljk=0.d0; if(j==k) deljk=1.d0
860 : : ! do l=1,3
861 : : ! delil=0.d0; if(i==l) delil=1.d0
862 : : ! deljl=0.d0; if(j==l) deljl=1.d0
863 : :
864 : : ! frcelast_t2(i,j,k,l)=frcelast_t2(i,j,k,l) + &
865 : : ! & 0.5d0*( deljk*stress(i,l) + delik*stress(j,l) + delil*stress(j,k) &
866 : : ! & + deljl*stress(i,k) )
867 : :
868 : : ! end do
869 : : ! end do
870 : : ! end do
871 : : ! end do
872 : :
873 : : !Now compute the contribution to the elastic tensor due to ion relaxations
874 : : !and sum with the clamped ion elastic tensor to obtain the relaxed ion one
875 : 2 : lmcelast(:,:,:,:)=zero
876 [ + + ]: 8 : do strsd2=1,3
877 [ + + ]: 26 : do strsd1=1,3
878 [ + + ]: 78 : do qvecd=1,3
879 [ + + ]: 234 : do jatd=1,3
880 [ + + ]: 702 : do iatd=1,3
881 [ + + ]: 2106 : do iat=1,natom
882 : : lmcelast(jatd,qvecd,strsd1,strsd2)=lmcelast(jatd,qvecd,strsd1,strsd2) - &
883 : 1944 : intstrn(jatd,qvecd,iatd,iat)*piezofr(iatd,iat,strsd1,strsd2)*fac
884 : : end do
885 : : end do
886 : : end do
887 : : end do
888 : : end do
889 : : end do
890 [ + + + + : 242 : ricelast_t2(:,:,:,:) = frcelast_t2(:,:,:,:) + lmcelast(:,:,:,:)
+ + + + ]
891 : :
892 : : !In last place compute the lattice contribution to the FxE tensor
893 : : !First obtain the C^{\kappa} tensor of Eq. 59 of PRB 88,174106 (2013)
894 : : !and its sublattice summation
895 : 2 : Csupkapsum(:,:,:,:)=zero
896 [ + + ]: 8 : do strsd2=1,3
897 [ + + ]: 26 : do strsd1=1,3
898 [ + + ]: 78 : do qvecd=1,3
899 [ + + ]: 234 : do iatd=1,3
900 [ + + ]: 702 : do iat=1,natom
901 : : Csupkap(iatd,iat,qvecd,strsd1,strsd2)=flexofr(iatd,iat,qvecd,strsd1,strsd2) + &
902 : 486 : & roundbkt_k(iatd,qvecd,strsd1,strsd2,iat)
903 : : Csupkapsum(iatd,qvecd,strsd1,strsd2)=Csupkapsum(iatd,qvecd,strsd1,strsd2) + &
904 : 648 : & Csupkap(iatd,iat,qvecd,strsd1,strsd2)
905 : : end do
906 : : end do
907 : : end do
908 : : end do
909 : : end do
910 : :
911 : : !Then separate the mass-dependent part
912 : 2 : mtot=zero
913 [ + + ]: 8 : do iat=1,natom
914 : 8 : mtot=mtot + amu(typat(iat))
915 : : end do
916 : :
917 [ + + ]: 8 : do strsd2=1,3
918 [ + + ]: 26 : do strsd1=1,3
919 [ + + ]: 78 : do qvecd=1,3
920 [ + + ]: 234 : do iatd=1,3
921 [ + + ]: 702 : do iat=1,natom
922 : : hatCsupkap(iatd,iat,qvecd,strsd1,strsd2)=Csupkap(iatd,iat,qvecd,strsd1,strsd2) - &
923 : 648 : & amu(typat(iat))/mtot*Csupkapsum(iatd,qvecd,strsd1,strsd2)
924 : : end do
925 : : end do
926 : : end do
927 : : end do
928 : : end do
929 : :
930 : : !Now compute the type-II flexoelectric internal strain tensor
931 [ + + + + : 728 : flexois(:,:,:,:,:)=zero
+ + + + +
+ ]
932 [ + + ]: 8 : do strsd2=1,3
933 [ + + ]: 26 : do strsd1=1,3
934 [ + + ]: 78 : do qvecd=1,3
935 [ + + ]: 234 : do iat=1,natom
936 [ + + ]: 702 : do iatd=1,3
937 : 486 : ivar=(iat-1)*3+iatd
938 [ + + ]: 2268 : do jat=1,natom
939 [ + + ]: 6966 : do jatd=1,3
940 : 4860 : jvar=(jat-1)*3+jatd
941 : : flexois(iatd,iat,qvecd,strsd1,strsd2)=flexois(iatd,iat,qvecd,strsd1,strsd2) + &
942 : 6480 : & psinvdm(ivar,jvar)*hatCsupkap(jatd,jat,qvecd,strsd1,strsd2)
943 : : end do
944 : : end do
945 : : end do
946 : : end do
947 : : end do
948 : : end do
949 : : end do
950 : :
951 : : !Finally multiply by the effective charges to obtain the FxE tensor
952 : 2 : lattflexo(:,:,:,:)=zero
953 [ + + ]: 8 : do strsd2=1,3
954 [ + + ]: 26 : do strsd1=1,3
955 [ + + ]: 78 : do qvecd=1,3
956 [ + + ]: 234 : do elfd=1,3
957 [ + + ]: 702 : do iat=1,natom
958 [ + + ]: 2106 : do iatd=1,3
959 : : lattflexo(elfd,qvecd,strsd1,strsd2)=lattflexo(elfd,qvecd,strsd1,strsd2) + &
960 : 1944 : & zeff(elfd,iatd,iat)*flexois(iatd,iat,qvecd,strsd1,strsd2)/ucvol*confac
961 : : end do
962 : : end do
963 : : end do
964 : : end do
965 : : end do
966 : : end do
967 : :
968 : :
969 : 2 : iwrite = ab_out > 0
970 [ + - ]: 2 : if (iwrite) then
971 : 2 : write(msg,'(3a)')ch10,' Lagrange elastic tensor from long wave magnitudes (clamped ion) (units= 10^2 GPa) ',ch10
972 [ + + ]: 6 : call wrtout([ab_out,std_out],msg,'COLL')
973 : 2 : write(msg,*)' xx yy zz yz xz xy'
974 [ + + ]: 6 : call wrtout([ab_out,std_out],msg,'COLL')
975 [ + + + + : 242 : frcelast_t2(:,:,:,:)=frcelast_t2(:,:,:,:)*HaBohr3_GPa/100.00_dp
+ + + + ]
976 [ + + ]: 14 : do ivar=1,6
977 : 12 : iatd=alpha(ivar)
978 : 12 : qvecd=beta(ivar)
979 : 12 : write(msg,'(9f12.6)') frcelast_t2(iatd,qvecd,1,1), frcelast_t2(iatd,qvecd,2,2),frcelast_t2(iatd,qvecd,3,3), &
980 : 24 : frcelast_t2(iatd,qvecd,2,3), frcelast_t2(iatd,qvecd,1,3),frcelast_t2(iatd,qvecd,1,2)
981 : :
982 [ + + ]: 38 : call wrtout([ab_out,std_out],msg,'COLL')
983 : : end do
984 : :
985 : 2 : write(msg,'(3a)')ch10,' Lagrange elastic tensor from long wave magnitudes (relaxed ion) (units= 10^2 GPa) ',ch10
986 [ + + ]: 6 : call wrtout([ab_out,std_out],msg,'COLL')
987 : 2 : write(msg,*)' xx yy zz yz xz xy'
988 [ + + ]: 6 : call wrtout([ab_out,std_out],msg,'COLL')
989 [ + + + + : 242 : ricelast_t2(:,:,:,:)=ricelast_t2(:,:,:,:)*HaBohr3_GPa/100.00_dp
+ + + + ]
990 [ + + ]: 14 : do ivar=1,6
991 : 12 : iatd=alpha(ivar)
992 : 12 : qvecd=beta(ivar)
993 : 12 : write(msg,'(9f12.6)') ricelast_t2(iatd,qvecd,1,1), ricelast_t2(iatd,qvecd,2,2),ricelast_t2(iatd,qvecd,3,3), &
994 : 24 : ricelast_t2(iatd,qvecd,2,3), ricelast_t2(iatd,qvecd,1,3),ricelast_t2(iatd,qvecd,1,2)
995 : :
996 [ + + ]: 38 : call wrtout([ab_out,std_out],msg,'COLL')
997 : : end do
998 [ - + ]: 2 : if (prtvol > 1) then
999 : 0 : write(msg,'(3a)')ch10,' (...)^kappa contribution to the flexoelectric force-response tensor (units: eV)',ch10
1000 [ # # ]: 0 : call wrtout([ab_out,std_out],msg,'COLL')
1001 : 0 : write(msg,*)' atom dir xx yy zz yz xz xy'
1002 [ # # ]: 0 : call wrtout([ab_out,std_out],msg,'COLL')
1003 [ # # # # : 0 : roundbkt_k(:,:,:,:,:)=roundbkt_k(:,:,:,:,:)*Ha_eV
# # # # #
# ]
1004 [ # # ]: 0 : do iat=1,natom
1005 : 0 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'xx', roundbkt_k(1,1,1,1,iat), roundbkt_k(1,1,2,2,iat), &
1006 : 0 : & roundbkt_k(1,1,3,3,iat),roundbkt_k(1,1,2,3,iat),roundbkt_k(1,1,1,3,iat),roundbkt_k(1,1,1,2,iat)
1007 [ # # ]: 0 : call wrtout([ab_out,std_out],msg,'COLL')
1008 : 0 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'yy', roundbkt_k(2,2,1,1,iat), roundbkt_k(2,2,2,2,iat), &
1009 : 0 : & roundbkt_k(2,2,3,3,iat),roundbkt_k(2,2,2,3,iat),roundbkt_k(2,2,1,3,iat),roundbkt_k(2,2,1,2,iat)
1010 [ # # ]: 0 : call wrtout([ab_out,std_out],msg,'COLL')
1011 : 0 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'zz', roundbkt_k(3,3,1,1,iat), roundbkt_k(3,3,2,2,iat), &
1012 : 0 : & roundbkt_k(3,3,3,3,iat),roundbkt_k(3,3,2,3,iat),roundbkt_k(3,3,1,3,iat),roundbkt_k(3,3,1,2,iat)
1013 [ # # ]: 0 : call wrtout([ab_out,std_out],msg,'COLL')
1014 : 0 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'yz', roundbkt_k(2,3,1,1,iat), roundbkt_k(2,3,2,2,iat), &
1015 : 0 : & roundbkt_k(2,3,3,3,iat),roundbkt_k(2,3,2,3,iat),roundbkt_k(2,3,1,3,iat),roundbkt_k(2,3,1,2,iat)
1016 [ # # ]: 0 : call wrtout([ab_out,std_out],msg,'COLL')
1017 : 0 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'xz', roundbkt_k(1,3,1,1,iat), roundbkt_k(1,3,2,2,iat), &
1018 : 0 : & roundbkt_k(1,3,3,3,iat),roundbkt_k(1,3,2,3,iat),roundbkt_k(1,3,1,3,iat),roundbkt_k(1,3,1,2,iat)
1019 [ # # ]: 0 : call wrtout([ab_out,std_out],msg,'COLL')
1020 : 0 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'xy', roundbkt_k(1,2,1,1,iat), roundbkt_k(1,2,2,2,iat), &
1021 : 0 : & roundbkt_k(1,2,3,3,iat),roundbkt_k(1,2,2,3,iat),roundbkt_k(1,2,1,3,iat),roundbkt_k(1,2,1,2,iat)
1022 [ # # ]: 0 : call wrtout([ab_out,std_out],msg,'COLL')
1023 : 0 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'zy', roundbkt_k(3,2,1,1,iat), roundbkt_k(3,2,2,2,iat), &
1024 : 0 : & roundbkt_k(3,2,3,3,iat),roundbkt_k(3,2,2,3,iat),roundbkt_k(3,2,1,3,iat),roundbkt_k(3,2,1,2,iat)
1025 [ # # ]: 0 : call wrtout([ab_out,std_out],msg,'COLL')
1026 : 0 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'zx', roundbkt_k(3,1,1,1,iat), roundbkt_k(3,1,2,2,iat), &
1027 : 0 : & roundbkt_k(3,1,3,3,iat),roundbkt_k(3,1,2,3,iat),roundbkt_k(3,1,1,3,iat),roundbkt_k(3,1,1,2,iat)
1028 [ # # ]: 0 : call wrtout([ab_out,std_out],msg,'COLL')
1029 : 0 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'yx', roundbkt_k(2,1,1,1,iat), roundbkt_k(2,1,2,2,iat), &
1030 : 0 : & roundbkt_k(2,1,3,3,iat),roundbkt_k(2,1,2,3,iat),roundbkt_k(2,1,1,3,iat),roundbkt_k(2,1,1,2,iat)
1031 [ # # ]: 0 : call wrtout([ab_out,std_out],msg,'COLL')
1032 : : end do
1033 : :
1034 : 0 : write(msg,'(3a)')ch10,' [...]^kappa contribution to the flexoelectric force-response tensor (units: eV)',ch10
1035 [ # # ]: 0 : call wrtout([ab_out,std_out],msg,'COLL')
1036 : 0 : write(msg,*)' atom dir xx yy zz yz xz xy'
1037 [ # # ]: 0 : call wrtout([ab_out,std_out],msg,'COLL')
1038 [ # # # # : 0 : flexofr(:,:,:,:,:)=flexofr(:,:,:,:,:)*Ha_eV
# # # # #
# ]
1039 [ # # ]: 0 : do iat=1,natom
1040 : 0 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'xx', flexofr(1,iat,1,1,1),flexofr(1,iat,1,2,2),flexofr(1,iat,1,3,3),&
1041 : 0 : & flexofr(1,iat,1,2,3),flexofr(1,iat,1,1,3),flexofr(1,iat,1,1,2)
1042 [ # # ]: 0 : call wrtout([ab_out,std_out],msg,'COLL')
1043 : 0 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'yy', flexofr(2,iat,2,1,1),flexofr(2,iat,2,2,2),flexofr(2,iat,2,3,3),&
1044 : 0 : & flexofr(2,iat,2,2,3),flexofr(2,iat,2,1,3),flexofr(2,iat,2,1,2)
1045 [ # # ]: 0 : call wrtout([ab_out,std_out],msg,'COLL')
1046 : 0 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'zz', flexofr(3,iat,3,1,1),flexofr(3,iat,3,2,2),flexofr(3,iat,3,3,3),&
1047 : 0 : & flexofr(3,iat,3,2,3),flexofr(3,iat,3,1,3),flexofr(3,iat,3,1,2)
1048 [ # # ]: 0 : call wrtout([ab_out,std_out],msg,'COLL')
1049 : 0 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'yz', flexofr(2,iat,3,1,1),flexofr(2,iat,3,2,2),flexofr(2,iat,3,3,3),&
1050 : 0 : & flexofr(2,iat,3,2,3),flexofr(2,iat,3,1,3),flexofr(2,iat,3,1,2)
1051 [ # # ]: 0 : call wrtout([ab_out,std_out],msg,'COLL')
1052 : 0 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'xz', flexofr(1,iat,3,1,1),flexofr(1,iat,3,2,2),flexofr(1,iat,3,3,3),&
1053 : 0 : & flexofr(1,iat,3,2,3),flexofr(1,iat,3,1,3),flexofr(1,iat,3,1,2)
1054 [ # # ]: 0 : call wrtout([ab_out,std_out],msg,'COLL')
1055 : 0 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'xy', flexofr(1,iat,2,1,1),flexofr(1,iat,2,2,2),flexofr(1,iat,2,3,3),&
1056 : 0 : & flexofr(1,iat,2,2,3),flexofr(1,iat,2,1,3),flexofr(1,iat,2,1,2)
1057 [ # # ]: 0 : call wrtout([ab_out,std_out],msg,'COLL')
1058 : 0 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'zy', flexofr(3,iat,2,1,1),flexofr(3,iat,2,2,2),flexofr(3,iat,2,3,3),&
1059 : 0 : & flexofr(3,iat,2,2,3),flexofr(3,iat,2,1,3),flexofr(3,iat,2,1,2)
1060 [ # # ]: 0 : call wrtout([ab_out,std_out],msg,'COLL')
1061 : 0 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'zx', flexofr(3,iat,1,1,1),flexofr(3,iat,1,2,2),flexofr(3,iat,1,3,3),&
1062 : 0 : & flexofr(3,iat,1,2,3),flexofr(3,iat,1,1,3),flexofr(3,iat,1,1,2)
1063 [ # # ]: 0 : call wrtout([ab_out,std_out],msg,'COLL')
1064 : 0 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'yx', flexofr(2,iat,1,1,1),flexofr(2,iat,1,2,2),flexofr(2,iat,1,3,3),&
1065 : 0 : & flexofr(2,iat,1,2,3),flexofr(2,iat,1,1,3),flexofr(2,iat,1,1,2)
1066 [ # # ]: 0 : call wrtout([ab_out,std_out],msg,'COLL')
1067 : : end do
1068 : : end if
1069 : :
1070 : 2 : write(msg,'(3a)')ch10,' Flexoelectric force-response tensor (units: eV)',ch10
1071 [ + + ]: 6 : call wrtout([ab_out,std_out],msg,'COLL')
1072 : 2 : write(msg,*)' atom dir xx yy zz yz xz xy'
1073 [ + + ]: 6 : call wrtout([ab_out,std_out],msg,'COLL')
1074 [ + + + + : 728 : Csupkap(:,:,:,:,:)=Csupkap(:,:,:,:,:)*Ha_eV
+ + + + +
+ ]
1075 [ + + ]: 8 : do iat=1,natom
1076 : 6 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'xx', Csupkap(1,iat,1,1,1),Csupkap(1,iat,1,2,2),Csupkap(1,iat,1,3,3),&
1077 : 12 : & Csupkap(1,iat,1,2,3),Csupkap(1,iat,1,1,3),Csupkap(1,iat,1,1,2)
1078 [ + + ]: 18 : call wrtout([ab_out,std_out],msg,'COLL')
1079 : 6 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'yy', Csupkap(2,iat,2,1,1),Csupkap(2,iat,2,2,2),Csupkap(2,iat,2,3,3),&
1080 : 12 : & Csupkap(2,iat,2,2,3),Csupkap(2,iat,2,1,3),Csupkap(2,iat,2,1,2)
1081 [ + + ]: 18 : call wrtout([ab_out,std_out],msg,'COLL')
1082 : 6 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'zz', Csupkap(3,iat,3,1,1),Csupkap(3,iat,3,2,2),Csupkap(3,iat,3,3,3),&
1083 : 12 : & Csupkap(3,iat,3,2,3),Csupkap(3,iat,3,1,3),Csupkap(3,iat,3,1,2)
1084 [ + + ]: 18 : call wrtout([ab_out,std_out],msg,'COLL')
1085 : 6 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'yz', Csupkap(2,iat,3,1,1),Csupkap(2,iat,3,2,2),Csupkap(2,iat,3,3,3),&
1086 : 12 : & Csupkap(2,iat,3,2,3),Csupkap(2,iat,3,1,3),Csupkap(2,iat,3,1,2)
1087 [ + + ]: 18 : call wrtout([ab_out,std_out],msg,'COLL')
1088 : 6 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'xz', Csupkap(1,iat,3,1,1),Csupkap(1,iat,3,2,2),Csupkap(1,iat,3,3,3),&
1089 : 12 : & Csupkap(1,iat,3,2,3),Csupkap(1,iat,3,1,3),Csupkap(1,iat,3,1,2)
1090 [ + + ]: 18 : call wrtout([ab_out,std_out],msg,'COLL')
1091 : 6 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'xy', Csupkap(1,iat,2,1,1),Csupkap(1,iat,2,2,2),Csupkap(1,iat,2,3,3),&
1092 : 12 : & Csupkap(1,iat,2,2,3),Csupkap(1,iat,2,1,3),Csupkap(1,iat,2,1,2)
1093 [ + + ]: 18 : call wrtout([ab_out,std_out],msg,'COLL')
1094 : 6 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'zy', Csupkap(3,iat,2,1,1),Csupkap(3,iat,2,2,2),Csupkap(3,iat,2,3,3),&
1095 : 12 : & Csupkap(3,iat,2,2,3),Csupkap(3,iat,2,1,3),Csupkap(3,iat,2,1,2)
1096 [ + + ]: 18 : call wrtout([ab_out,std_out],msg,'COLL')
1097 : 6 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'zx', Csupkap(3,iat,1,1,1),Csupkap(3,iat,1,2,2),Csupkap(3,iat,1,3,3),&
1098 : 12 : & Csupkap(3,iat,1,2,3),Csupkap(3,iat,1,1,3),Csupkap(3,iat,1,1,2)
1099 [ + + ]: 18 : call wrtout([ab_out,std_out],msg,'COLL')
1100 : 6 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'yx', Csupkap(2,iat,1,1,1),Csupkap(2,iat,1,2,2),Csupkap(2,iat,1,3,3),&
1101 : 12 : & Csupkap(2,iat,1,2,3),Csupkap(2,iat,1,1,3),Csupkap(2,iat,1,1,2)
1102 [ + + ]: 20 : call wrtout([ab_out,std_out],msg,'COLL')
1103 : : end do
1104 [ - + ]: 2 : if (prtvol > 1) then
1105 : 0 : write(msg,'(3a)')ch10,' Flexoelectric force-response tensor minus mass dependent part (units: eV)',ch10
1106 [ # # ]: 0 : call wrtout([ab_out,std_out],msg,'COLL')
1107 : 0 : write(msg,*)' atom dir xx yy zz yz xz xy'
1108 [ # # ]: 0 : call wrtout([ab_out,std_out],msg,'COLL')
1109 [ # # # # : 0 : hatCsupkap(:,:,:,:,:)=hatCsupkap(:,:,:,:,:)*Ha_eV
# # # # #
# ]
1110 [ # # ]: 0 : do iat=1,natom
1111 : 0 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat,'xx',hatCsupkap(1,iat,1,1,1),hatCsupkap(1,iat,1,2,2),hatCsupkap(1,iat,1,3,3),&
1112 : 0 : & hatCsupkap(1,iat,1,2,3),hatCsupkap(1,iat,1,1,3),hatCsupkap(1,iat,1,1,2)
1113 [ # # ]: 0 : call wrtout([ab_out,std_out],msg,'COLL')
1114 : 0 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat,'yy',hatCsupkap(2,iat,2,1,1),hatCsupkap(2,iat,2,2,2),hatCsupkap(2,iat,2,3,3),&
1115 : 0 : & hatCsupkap(2,iat,2,2,3),hatCsupkap(2,iat,2,1,3),hatCsupkap(2,iat,2,1,2)
1116 [ # # ]: 0 : call wrtout([ab_out,std_out],msg,'COLL')
1117 : 0 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat,'zz',hatCsupkap(3,iat,3,1,1),hatCsupkap(3,iat,3,2,2),hatCsupkap(3,iat,3,3,3),&
1118 : 0 : & hatCsupkap(3,iat,3,2,3),hatCsupkap(3,iat,3,1,3),hatCsupkap(3,iat,3,1,2)
1119 [ # # ]: 0 : call wrtout([ab_out,std_out],msg,'COLL')
1120 : 0 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat,'yz',hatCsupkap(2,iat,3,1,1),hatCsupkap(2,iat,3,2,2),hatCsupkap(2,iat,3,3,3),&
1121 : 0 : & hatCsupkap(2,iat,3,2,3),hatCsupkap(2,iat,3,1,3),hatCsupkap(2,iat,3,1,2)
1122 [ # # ]: 0 : call wrtout([ab_out,std_out],msg,'COLL')
1123 : 0 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat,'xz',hatCsupkap(1,iat,3,1,1),hatCsupkap(1,iat,3,2,2),hatCsupkap(1,iat,3,3,3),&
1124 : 0 : & hatCsupkap(1,iat,3,2,3),hatCsupkap(1,iat,3,1,3),hatCsupkap(1,iat,3,1,2)
1125 [ # # ]: 0 : call wrtout([ab_out,std_out],msg,'COLL')
1126 : 0 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat,'xy',hatCsupkap(1,iat,2,1,1),hatCsupkap(1,iat,2,2,2),hatCsupkap(1,iat,2,3,3),&
1127 : 0 : & hatCsupkap(1,iat,2,2,3),hatCsupkap(1,iat,2,1,3),hatCsupkap(1,iat,2,1,2)
1128 [ # # ]: 0 : call wrtout([ab_out,std_out],msg,'COLL')
1129 : 0 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat,'zy',hatCsupkap(3,iat,2,1,1),hatCsupkap(3,iat,2,2,2),hatCsupkap(3,iat,2,3,3),&
1130 : 0 : & hatCsupkap(3,iat,2,2,3),hatCsupkap(3,iat,2,1,3),hatCsupkap(3,iat,2,1,2)
1131 [ # # ]: 0 : call wrtout([ab_out,std_out],msg,'COLL')
1132 : 0 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat,'zx',hatCsupkap(3,iat,1,1,1),hatCsupkap(3,iat,1,2,2),hatCsupkap(3,iat,1,3,3),&
1133 : 0 : & hatCsupkap(3,iat,1,2,3),hatCsupkap(3,iat,1,1,3),hatCsupkap(3,iat,1,1,2)
1134 [ # # ]: 0 : call wrtout([ab_out,std_out],msg,'COLL')
1135 : 0 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat,'yx',hatCsupkap(2,iat,1,1,1),hatCsupkap(2,iat,1,2,2),hatCsupkap(2,iat,1,3,3),&
1136 : 0 : & hatCsupkap(2,iat,1,2,3),hatCsupkap(2,iat,1,1,3),hatCsupkap(2,iat,1,1,2)
1137 [ # # ]: 0 : call wrtout([ab_out,std_out],msg,'COLL')
1138 : : end do
1139 : : end if
1140 : :
1141 : 2 : write(msg,'(3a)')ch10,' Displacement-response flexoelectric internal strain tensor (units: Bohr^2)',ch10
1142 [ + + ]: 6 : call wrtout([ab_out,std_out],msg,'COLL')
1143 : 2 : write(msg,*)' atom dir xx yy zz yz xz xy'
1144 [ + + ]: 6 : call wrtout([ab_out,std_out],msg,'COLL')
1145 [ + + ]: 8 : do iat=1,natom
1146 : 6 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'xx', flexois(1,iat,1,1,1),flexois(1,iat,1,2,2),flexois(1,iat,1,3,3),&
1147 : 12 : & flexois(1,iat,1,2,3),flexois(1,iat,1,1,3),flexois(1,iat,1,1,2)
1148 [ + + ]: 18 : call wrtout([ab_out,std_out],msg,'COLL')
1149 : 6 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'yy', flexois(2,iat,2,1,1),flexois(2,iat,2,2,2),flexois(2,iat,2,3,3),&
1150 : 12 : & flexois(2,iat,2,2,3),flexois(2,iat,2,1,3),flexois(2,iat,2,1,2)
1151 [ + + ]: 18 : call wrtout([ab_out,std_out],msg,'COLL')
1152 : 6 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'zz', flexois(3,iat,3,1,1),flexois(3,iat,3,2,2),flexois(3,iat,3,3,3),&
1153 : 12 : & flexois(3,iat,3,2,3),flexois(3,iat,3,1,3),flexois(3,iat,3,1,2)
1154 [ + + ]: 18 : call wrtout([ab_out,std_out],msg,'COLL')
1155 : 6 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'yz', flexois(2,iat,3,1,1),flexois(2,iat,3,2,2),flexois(2,iat,3,3,3),&
1156 : 12 : & flexois(2,iat,3,2,3),flexois(2,iat,3,1,3),flexois(2,iat,3,1,2)
1157 [ + + ]: 18 : call wrtout([ab_out,std_out],msg,'COLL')
1158 : 6 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'xz', flexois(1,iat,3,1,1),flexois(1,iat,3,2,2),flexois(1,iat,3,3,3),&
1159 : 12 : & flexois(1,iat,3,2,3),flexois(1,iat,3,1,3),flexois(1,iat,3,1,2)
1160 [ + + ]: 18 : call wrtout([ab_out,std_out],msg,'COLL')
1161 : 6 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'xy', flexois(1,iat,2,1,1),flexois(1,iat,2,2,2),flexois(1,iat,2,3,3),&
1162 : 12 : & flexois(1,iat,2,2,3),flexois(1,iat,2,1,3),flexois(1,iat,2,1,2)
1163 [ + + ]: 18 : call wrtout([ab_out,std_out],msg,'COLL')
1164 : 6 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'zy', flexois(3,iat,2,1,1),flexois(3,iat,2,2,2),flexois(3,iat,2,3,3),&
1165 : 12 : & flexois(3,iat,2,2,3),flexois(3,iat,2,1,3),flexois(3,iat,2,1,2)
1166 [ + + ]: 18 : call wrtout([ab_out,std_out],msg,'COLL')
1167 : 6 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'zx', flexois(3,iat,1,1,1),flexois(3,iat,1,2,2),flexois(3,iat,1,3,3),&
1168 : 12 : & flexois(3,iat,1,2,3),flexois(3,iat,1,1,3),flexois(3,iat,1,1,2)
1169 [ + + ]: 18 : call wrtout([ab_out,std_out],msg,'COLL')
1170 : 6 : write(msg,'(2x,i3,3x,a3,2x,6(f12.6,1x))') iat, 'yx', flexois(2,iat,1,1,1),flexois(2,iat,1,2,2),flexois(2,iat,1,3,3),&
1171 : 12 : & flexois(2,iat,1,2,3),flexois(2,iat,1,1,3),flexois(2,iat,1,1,2)
1172 [ + + ]: 20 : call wrtout([ab_out,std_out],msg,'COLL')
1173 : : end do
1174 : :
1175 : 2 : write(msg,'(3a)')ch10,' Type-II lattice contribution to flexoelectric tensor (units= nC/m) ',ch10
1176 [ + + ]: 6 : call wrtout([ab_out,std_out],msg,'COLL')
1177 : 2 : write(msg,*)' xx yy zz yz xz xy'
1178 [ + + ]: 6 : call wrtout([ab_out,std_out],msg,'COLL')
1179 [ + + ]: 14 : do ivar=1,6
1180 : 12 : elfd=alpha(ivar)
1181 : 12 : qvecd=beta(ivar)
1182 : 12 : write(msg,'(3x,a2,6f12.6)') voigt(ivar),lattflexo(elfd,qvecd,1,1),lattflexo(elfd,qvecd,2,2),lattflexo(elfd,qvecd,3,3),&
1183 : 24 : lattflexo(elfd,qvecd,2,3),lattflexo(elfd,qvecd,1,3),lattflexo(elfd,qvecd,1,2)
1184 [ + + ]: 38 : call wrtout([ab_out,std_out],msg,'COLL')
1185 : : end do
1186 [ + + ]: 8 : do ivar=4,6
1187 : 6 : elfd=beta(ivar)
1188 : 6 : qvecd=alpha(ivar)
1189 : 6 : write(msg,'(3x,a2,6f12.6)') voigt(ivar+3),lattflexo(elfd,qvecd,1,1),lattflexo(elfd,qvecd,2,2),lattflexo(elfd,qvecd,3,3),&
1190 : 12 : lattflexo(elfd,qvecd,2,3),lattflexo(elfd,qvecd,1,3),lattflexo(elfd,qvecd,1,2)
1191 [ + + ]: 20 : call wrtout([ab_out,std_out],msg,'COLL')
1192 : : end do
1193 : :
1194 : : end if
1195 : : DBG_EXIT("COLL")
1196 : :
1197 : 2 : end subroutine dtlattflexo
1198 : : !!***
1199 : :
1200 : : !!****f* m_ddb/dm_psinv
1201 : : !! NAME
1202 : : !! dm_psinv
1203 : : !!
1204 : : !! FUNCTION
1205 : : !! Computes the pseudoinverse of the dynamical matrix (PRB 72, 035105 (2005)).
1206 : : !! This piece of code is copied from m_ddb_internalstr.F90.
1207 : : !!
1208 : : !! INPUTS
1209 : : !! asr= if /=0 acustic sume rule is imposed on the dynamical matrix
1210 : : !! blkval(2,3,mpert,3,mpert)= 2nd derivatives wrt two atom displacements (at least)
1211 : : !! d2asr(2,3,natom,3,natom)=ASR-correction
1212 : : !! iout=out file number
1213 : : !! mpert=maximum number of ipert
1214 : : !! natom=number of atoms in unit cell
1215 : : !!
1216 : : !! OUTPUT
1217 : : !! kmatrix(3*natom,3*natom) = array with the pseudo-inverse of dynamical matrix
1218 : : !!
1219 : : !! SOURCE
1220 : :
1221 : 2 : subroutine dm_psinv(asr,blkval,d2asr,iout,kmatrix,mpert,natom)
1222 : :
1223 : : !Arguments -------------------------------
1224 : : !scalars
1225 : : integer,intent(in) :: asr,iout,mpert,natom
1226 : : !arrays
1227 : : real(dp),intent(in) :: blkval(2,3,mpert,3,mpert)
1228 : : real(dp),intent(in) :: d2asr(2,3,natom,3,natom)
1229 : : real(dp),intent(out) :: kmatrix(3*natom,3*natom)
1230 : :
1231 : : !Local variables -------------------------
1232 : : !scalars
1233 : : integer :: ii1,ivarA
1234 : : integer :: ivarB
1235 : : integer :: ier
1236 : : character(len=500) :: message
1237 : : !arrays
1238 : 4 : real(dp) :: Amatr(3*natom-3,3*natom-3),Apmatr(3*natom,3*natom)
1239 : 4 : real(dp) :: Bmatr(2,((3*natom-3)*(3*natom-2))/2)
1240 : 4 : real(dp) :: Bpmatr(2,(3*natom*(3*natom+1))/2),Cmatr(3*natom-3,3*natom-3)
1241 : 4 : real(dp) :: Cpmatr(3*natom,3*natom),Nmatr(3*natom,3*natom)
1242 : 4 : real(dp) :: eigval(3*natom-3),eigvalp(3*natom),eigvec(2,3*natom-3,3*natom-3)
1243 : 4 : real(dp) :: eigvecp(2,3*natom,3*natom)
1244 : 4 : real(dp) :: zhpev1(2,2*3*natom-4)
1245 : 4 : real(dp) :: zhpev1p(2,2*3*natom-1),zhpev2(3*3*natom-5),zhpev2p(3*3*natom-2)
1246 : 4 : real(dp) :: d2cart(2,3*natom,3*natom)
1247 : :
1248 : : ! *********************************************************************
1249 : :
1250 : : DBG_ENTER("COLL")
1251 : :
1252 [ + + + + : 204 : d2cart(1,:,:) = RESHAPE(blkval(1,1:3,1:natom,1:3,1:natom), SHAPE=[3*natom,3*natom])
+ + ]
1253 [ + + + + ]: 200 : d2cart(2,:,:) = zero
1254 : :
1255 : : !Eventually impose the acoustic sum rule
1256 : : !FIXME: this might depend on ifcflag: impose that it is 0 or generalize
1257 : 2 : call asria_corr(asr,d2asr,d2cart,natom,natom)
1258 : : !call asrq0_apply(asrq0, natom, mpert, msize, crystal%xcart, d2cart)
1259 [ + + + + ]: 200 : kmatrix(:,:) = d2cart(1,:,:)
1260 : :
1261 : : !DEBUG
1262 : : !write(std_out,'(/,a,/)')'the force constant matrix'
1263 : : !do ivarA=1,3*natom
1264 : : !write(std_out,'(/)')
1265 : : !do ivarB=1,3*natom
1266 : : !write(std_out,'(es16.6)')kmatrix(ivarB,ivarA)
1267 : : !end do
1268 : : !end do
1269 : : !ENDDEBUG
1270 : :
1271 [ + + + + ]: 200 : Nmatr(:,:)=0.0_dp
1272 [ + + ]: 8 : do ivarB=0,natom-1
1273 [ + + ]: 28 : do ivarA=0,natom-1
1274 : 20 : Nmatr(3*ivarA+1,3*ivarB+1) = one
1275 : 20 : Nmatr(3*ivarA+2,3*ivarB+2) = one
1276 : 26 : Nmatr(3*ivarA+3,3*ivarB+3) = one
1277 : : end do
1278 : : end do
1279 : :
1280 : : !DEBUG
1281 : : !do ivarA=1,3*natom
1282 : : !write(std_out,'(/)')
1283 : : !do ivarB=1,3*natom
1284 : : !write(std_out,'(es16.6)')Nmatr(ivarB,ivarA)
1285 : : !end do
1286 : : !end do
1287 : : !ENDDEBUG
1288 : :
1289 : : !starting the pseudoinverting processes
1290 : : !then get the eigenvectors of the big matrix,give values to matrixBp
1291 [ + + + + ]: 299 : Bpmatr=0.0_dp
1292 : : ii1=1
1293 [ + + ]: 20 : do ivarA=1,3*natom
1294 [ + + ]: 119 : do ivarB=1,ivarA
1295 : 99 : Bpmatr(1,ii1)=Nmatr(ivarB,ivarA)
1296 : 117 : ii1=ii1+1
1297 : : end do
1298 : : end do
1299 : :
1300 : : !Bpmatr(2,:) is the imaginary part of the force matrix
1301 : : !then call the subroutines CHPEV and ZHPEV to get the eigenvectors
1302 : 2 : call ZHPEV ('V','U',3*natom,Bpmatr,eigvalp,eigvecp,3*natom,zhpev1p,zhpev2p,ier)
1303 [ - + ]: 2 : ABI_CHECK(ier == 0, sjoin("ZHPEV returned:", itoa(ier)))
1304 : :
1305 : : !DEBUG
1306 : : !the eigenval and eigenvec
1307 : : !write(std_out,'(/,a,/)')'the eigenvalues and eigenvectors'
1308 : : !do ivarA=1,3*natom
1309 : : !write(std_out,'(/)')
1310 : : !write(std_out,'(es16.6)')eigvalp(ivarA)
1311 : : !end do
1312 : : !do ivarA=1,3*natom
1313 : : !write(std_out,'(/)')
1314 : : !do ivarB=1,3*natom
1315 : : !write(std_out,'(es16.6)')eigvecp(1,ivarB,ivarA)
1316 : : !end do
1317 : : !end do
1318 : : !ENDDEBUG
1319 : :
1320 : : !Then do the multiplication to get the reduced matrix,in two steps
1321 : : !After this the force constant matrix is decouple in two bloks,
1322 : : !acoustic and optical ones
1323 [ - + + - : 6632 : Apmatr(:,:) = MATMUL(TRANSPOSE(eigvecp(1,:,:)), MATMUL(kmatrix, eigvecp(1,:,:)))
- + + - +
- + - - +
- + + + +
+ + + + +
+ + + - +
+ + + + +
+ + + + +
- + - +
- ]
1324 : :
1325 : : !DEBUG
1326 : : !the blok diago
1327 : : !write(std_out,'(/,a,/)')'matrixAp'
1328 : : !do ivarA=1,3*natom
1329 : : !write(std_out,'(/)')
1330 : : !do ivarB=1,3*natom
1331 : : !write(std_out,'(es16.6)')Apmatr(ivarA,ivarB)
1332 : : !end do
1333 : : !end do
1334 : : !ENDDEBUG
1335 : :
1336 : : !Check the last three eigenvalues whether too large or not
1337 : 2 : ivarB=0
1338 [ + + ]: 8 : do ivarA=3*natom-2,3*natom
1339 [ - + ]: 8 : if (ABS(Apmatr(ivarA,ivarA))>tol6)then
1340 : 0 : ivarB=1
1341 : : end if
1342 : : end do
1343 : :
1344 [ - + ]: 2 : if(ivarB==1)then
1345 : 0 : write(message,'(a,a,a,a,a,a,a,a,3es16.6)')ch10,&
1346 : 0 : & ' Acoustic sum rule violation met : the eigenvalues of accoustic mode',ch10,&
1347 : 0 : & ' are too large at Gamma point.',ch10,&
1348 : 0 : & ' Increase cutoff energy or k-points sampling.',ch10,&
1349 : 0 : & ' The three eigenvalues are:',Apmatr(3*natom-2,3*natom-2),Apmatr(3*natom-1,natom-1),Apmatr(3*natom,3*natom)
1350 : 0 : ABI_WARNING(message)
1351 : 0 : call wrtout(iout,message,'COLL')
1352 : : end if
1353 : :
1354 : : !Give the value of reduced matrix form Apmatr to Amatr
1355 [ + + + + ]: 104 : Amatr(:,:) = Apmatr(1:3*natom-3, 1:3*natom-3)
1356 : :
1357 : : !Now the reduced matrix is in the matrixA, the convert it
1358 : : !first give the give the value of matixB from matrixA
1359 : : ii1=1
1360 [ + + ]: 14 : do ivarA=1,3*natom-3
1361 [ + + ]: 65 : do ivarB=1,ivarA
1362 : 51 : Bmatr(1,ii1)=Amatr(ivarB,ivarA)
1363 : 63 : ii1=ii1+1
1364 : : end do
1365 : : end do
1366 [ + + ]: 53 : Bmatr(2,:)=0.0_dp
1367 : :
1368 : : !Call the subroutines CHPEV and ZHPEV to get the eigenvectors and the eigenvalues
1369 : 2 : call ZHPEV ('V','U',3*natom-3,Bmatr,eigval,eigvec,3*natom-3,zhpev1,zhpev2,ier)
1370 [ - + ]: 2 : ABI_CHECK(ier == 0, sjoin("ZHPEV returned:", itoa(ier)))
1371 : :
1372 : : !Check the unstable phonon modes, if the first is negative then print
1373 : : !warning message
1374 [ - + ]: 2 : if(eigval(1)<-1.0*tol8)then
1375 : 0 : write(message,'(9a)') ch10,&
1376 : 0 : & ' --- !WARNING',ch10,&
1377 : 0 : & ' Unstable eigenvalue detected in force constant matrix at Gamma point',ch10,&
1378 : 0 : & ' The system under calculation is physically unstable.',ch10,&
1379 : 0 : & ' ---',ch10
1380 : 0 : call wrtout(std_out,message,'COLL')
1381 : : end if
1382 : :
1383 : : !Do the matrix mutiplication to get pseudoinverse inverse matrix
1384 [ + + + + ]: 104 : Amatr(:,:)=0.0_dp
1385 [ + + ]: 14 : do ivarA=1,3*natom-3
1386 : 14 : Amatr(ivarA,ivarA)=1.0_dp/eigval(ivarA)
1387 : : end do
1388 : :
1389 [ - + + - : 2684 : Cmatr(:,:) = MATMUL(eigvec(1,:,:), MATMUL(Amatr, TRANSPOSE(eigvec(1,:,:))))
- + + - +
- + - - +
- + + + +
+ + + + +
+ + + - +
+ + + + +
+ + + + +
- + - +
- ]
1390 : :
1391 : : !DEBUG
1392 : : !write(std_out,'(/,a,/)')'the pseudo inverse of the force matrix'
1393 : : !do ivarA=1,3*natom
1394 : : !write(std_out,'(/)')
1395 : : !do ivarB=1,3*natom
1396 : : !write(std_out,'(es16.6)')Cmatr(ivarA,ivarB)
1397 : : !end do
1398 : : !end do
1399 : : !ENDDEBUG
1400 : :
1401 : : !So now the inverse of the reduced matrix is in the matrixC
1402 : : !now do another mutilplication to get the pseudoinverse of the original
1403 [ + + + + ]: 200 : Cpmatr(:,:)=0.0_dp
1404 [ + + + + ]: 104 : Cpmatr(1:3*natom-3,1:3*natom-3) = Cmatr(:,:)
1405 : :
1406 [ - + + - : 6632 : Apmatr(:,:) = MATMUL(eigvecp(1,:,:), MATMUL(Cpmatr, TRANSPOSE(eigvecp(1,:,:))))
- + + - +
- + - - +
- + + + +
+ + + + +
+ + + - +
+ + + + +
+ + + + +
- + - +
- ]
1407 : :
1408 : : !Now the inverse is in Cpmatr
1409 [ + + + + ]: 200 : kmatrix(:,:)=Apmatr(:,:)
1410 : : !transfer the inverse of k-matrix back to the k matrix
1411 : : !so now the inverse of k matrix is in the kmatrix
1412 : : !ending the part for pseudoinversing the K matrix
1413 : :
1414 : : DBG_EXIT("COLL")
1415 : :
1416 : 2 : end subroutine dm_psinv
1417 : : !!***
1418 : :
1419 : : !!****f* ABINIT/m_ddb_flexo/ddb_phi1
1420 : : !! NAME
1421 : : !! ddb_phi1
1422 : : !!
1423 : : !! FUNCTION
1424 : : !! Return the moment of IFCs Phi^(1) and \sum_k Phi^(2)
1425 : : !!
1426 : : !! INPUTS
1427 : : !! ddb<type(ddb_type)>=Long wave 3rd order derivative database.
1428 : : !! ddb_version = 8 digit integer giving date. To mantain compatibility with old DDB files.
1429 : : !! Crystal<type(crystal_t)>=Crystal structure parameters
1430 : : !! filnamddb = name of the ddb file
1431 : : !!
1432 : : !! OUTPUT
1433 : : !! phi1(3,natom,3,natom,3)=First Moment of IFCs Phi^(1)
1434 : : !! phi2(3,natom,3,3,3)=Second Moment of IFCs Phi^(2) summed over atoms
1435 : : !!
1436 : : !! SIDE EFFECTS
1437 : : !!
1438 : : !! NOTES
1439 : : !!
1440 : : !! SOURCE
1441 : :
1442 : 1 : subroutine ddb_phi1(ddb,ddb_lw,ddb_version,filnamddb,phi1,phi2,natom)
1443 : :
1444 : : implicit none
1445 : :
1446 : : !Arguments ------------------------------------
1447 : : !scalars
1448 : : integer,intent(in) :: ddb_version, natom
1449 : : class(ddb_type),intent(in) :: ddb,ddb_lw
1450 : : character(len=fnlen) :: filnamddb
1451 : : !arrays
1452 : : real(dp), intent(out) :: phi1(3,natom,3,natom,3)
1453 : : real(dp), intent(out) :: phi2(3,natom,3,3,3)
1454 : :
1455 : : !Local variables-------------------------------
1456 : : integer,parameter :: cvrsio8=20100401
1457 : : integer :: iblok,istrs,strsd1,strsd2,strst,strsd,qvecd
1458 : : character(len=500) :: msg
1459 : :
1460 : : !arrays
1461 : : integer :: rfelfd(4),rfphon(4),rfstrs(4),iat,iatd
1462 : : integer,parameter :: alpha(6)=(/1,2,3,2,1,1/),beta(6)=(/1,2,3,3,3,2/)
1463 : : integer :: rfqvec(4)
1464 : : real(dp) :: qphnrm(3),qphon(3,3),fac
1465 : 2 : real(dp) :: sqrbkt_t1(3,natom,3,3,3)
1466 : 2 : real(dp) :: d3cart(2,3,ddb%mpert,3,ddb%mpert,3,ddb%mpert)
1467 : 2 : real(dp) :: phi2tmp(3,ddb%mpert,3,3,3)
1468 : :
1469 : : ! *********************************************************************
1470 : :
1471 : : DBG_ENTER("COLL")
1472 : :
1473 : 1 : qphon(:,:)=zero
1474 [ + + ]: 4 : qphnrm(:)=one
1475 : 1 : rfphon(:)=0
1476 : 1 : rfelfd(:)=0
1477 : 1 : rfstrs(:)=0
1478 : 1 : rfqvec(:)=0
1479 : :
1480 : 1 : rfphon(1)=1
1481 : 1 : rfphon(2)=1
1482 : 1 : rfqvec(3)=1
1483 : :
1484 : 1 : write(msg, '(2a)' ) ch10," Extract the Phi^(1) coeficients from 3DTE"
1485 : 1 : call wrtout(std_out,msg,'COLL')
1486 : 1 : call ddb_lw%get_block(iblok,qphon,qphnrm,rfphon,rfelfd,rfstrs,BLKTYP_d3E_lw,rfqvec=rfqvec)
1487 : :
1488 [ - + ]: 1 : if (iblok == 0) then
1489 : 0 : call wrtout(std_out, " ")
1490 : 0 : call wrtout(std_out, "--- !WARNING")
1491 : 0 : call wrtout(std_out, sjoin("- Cannot find Phi^(1) tensor in DDB file:", filnamddb))
1492 : 0 : call wrtout(std_out, " flexoflag=1 or 3 requires the DDB file to include the corresponding long wave 3rd derivatives")
1493 : : end if
1494 : :
1495 [ + + + + : 251339 : d3cart(1,:,:,:,:,:,:) = reshape(ddb_lw%val(1,:,iblok),shape = (/3,ddb%mpert,3,ddb%mpert,3,ddb%mpert/))
+ + + + +
+ + + +
+ ]
1496 [ + + + + : 251339 : d3cart(2,:,:,:,:,:,:) = reshape(ddb_lw%val(2,:,iblok),shape = (/3,ddb%mpert,3,ddb%mpert,3,ddb%mpert/))
+ + + + +
+ + + +
+ ]
1497 : :
1498 : : !Define the factors to apply if DDB file has been created with the old version of
1499 : : !the longwave driver.
1500 [ - + ]: 1 : if (ddb_version <= cvrsio8) then
1501 : : fac=two
1502 : : else
1503 : 0 : fac=one
1504 : : end if
1505 : :
1506 : : !Extraction of dC/dq and d2C/dqdq
1507 : : phi1(:,:,:,:,:) = fac*RESHAPE(d3cart(2,1:3,1:ddb%natom,1:3,1:ddb%natom,1:3,ddb%natom+8), &
1508 [ + + + + : 634 : & SHAPE=[3,ddb%natom,3,ddb%natom,3])
+ + + + +
+ + + ]
1509 : :
1510 : : !Define the factors to apply if DDB file has been created with the old version of
1511 : : !the longwave driver. Note that there is a factor -1 to go to the derivatives
1512 [ - + ]: 1 : if (ddb_version <= cvrsio8) then
1513 : : fac=two
1514 : : else
1515 : 0 : fac=-one
1516 : : end if
1517 : :
1518 [ + + + + : 472 : phi2 = zero
+ + + + +
+ ]
1519 [ + + ]: 7 : do istrs=1,6
1520 : 6 : strsd1=alpha(istrs)
1521 : 6 : strsd2=beta(istrs)
1522 [ + + ]: 6 : strst=ddb%natom+3; if (istrs>3) strst=ddb%natom+4
1523 : 3 : strsd=istrs; if (istrs>3) strsd=istrs-3
1524 [ + + ]: 25 : do qvecd=1,3
1525 [ + + ]: 96 : do iat=1,ddb%natom
1526 [ + + ]: 306 : do iatd=1,3
1527 : 216 : phi2tmp(iatd,iat,qvecd,strsd1,strsd2)=fac*d3cart(1,iatd,iat,strsd,strst,qvecd,ddb%natom+8)
1528 [ + + ]: 288 : if (istrs>3) phi2tmp(iatd,iat,qvecd,strsd2,strsd1)=phi2tmp(iatd,iat,qvecd,strsd1,strsd2)
1529 : : end do
1530 : : end do
1531 : : end do
1532 : : end do
1533 [ + + ]: 4 : do qvecd=1,3
1534 [ + + ]: 13 : do strsd2=1,3
1535 [ + + ]: 39 : do strsd1=1,3
1536 [ + + ]: 144 : do iat=1,ddb%natom
1537 : : sqrbkt_t1(1:3,iat,strsd1,strsd2,qvecd)=half*(phi2tmp(1:3,iat,qvecd,strsd1,strsd2) + &
1538 [ + + ]: 459 : & phi2tmp(1:3,iat,strsd2,strsd1,qvecd))
1539 : : end do
1540 : : end do
1541 : : end do
1542 : : end do
1543 : :
1544 : : !Now correct the stress in the square bracketed tesnor tensor
1545 : : ! do qvecd=1,3
1546 : : ! do strsd2=1,3
1547 : : ! do strsd1=1,3
1548 : : ! do iatd=1,3
1549 : : ! if (iatd==strsd1) then
1550 : : ! sqrbkt_t1(iatd,strsd1,strsd2,qvecd)=sqrbkt_t1(iatd,strsd1,strsd2,qvecd) - stress(strsd2,qvecd)
1551 : : ! endif
1552 : : ! end do
1553 : : ! end do
1554 : : ! end do
1555 : : ! end do
1556 : :
1557 : : !Now convert back to type-II in order to obtain the frozen ion Lagrange elastic tensor.
1558 [ + + + + : 472 : phi2(:,:,:,:,:)=zero
+ + + + +
+ ]
1559 [ + + ]: 4 : do iatd=1,3
1560 [ + + ]: 13 : do qvecd=1,3
1561 [ + + ]: 39 : do strsd1=1,3
1562 [ + + ]: 117 : do strsd2=1,3
1563 [ + + ]: 432 : do iat=1,ddb%natom
1564 : : phi2(iatd,iat,qvecd,strsd1,strsd2)=sqrbkt_t1(iatd,iat,strsd1,qvecd,strsd2) + &
1565 : 405 : & sqrbkt_t1(iatd,iat,strsd2,strsd1,qvecd)-sqrbkt_t1(iatd,iat,qvecd,strsd2,strsd1)
1566 : : end do
1567 : : end do
1568 : : end do
1569 : : end do
1570 : : end do
1571 : : DBG_EXIT("COLL")
1572 : 1 : end subroutine ddb_phi1
1573 : : !!***
1574 [ + - + - : 6 : end module m_ddb_flexo
+ - ]
|