Branch data Line data Source code
1 : : !!****m* ABINIT/m_ddb_elast
2 : : !! NAME
3 : : !! m_ddb_elast
4 : : !!
5 : : !! FUNCTION
6 : : !! Elastic properties (clamped-ions and relaxed-ions).
7 : : !!
8 : : !! COPYRIGHT
9 : : !! Copyright (C) 1999-2026 ABINIT group (XW, DW)
10 : : !! This file is distributed under the terms of the
11 : : !! GNU General Public License, see ~abinit/COPYING
12 : : !! or http://www.gnu.org/copyleft/gpl.txt .
13 : : !!
14 : : !! SOURCE
15 : :
16 : : #if defined HAVE_CONFIG_H
17 : : #include "config.h"
18 : : #endif
19 : :
20 : : #include "abi_common.h"
21 : :
22 : : module m_ddb_elast
23 : :
24 : : use defs_basis
25 : : use m_abicore
26 : : use m_errors
27 : : use m_crystal
28 : : use m_ddb
29 : : use m_nctk
30 : : use netcdf
31 : :
32 : : use m_fstrings, only : itoa, sjoin
33 : : use m_hide_lapack, only : matrginv
34 : : use m_dynmat, only : asria_corr
35 : : use m_anaddb_dataset, only : anaddb_dataset_type
36 : :
37 : : implicit none
38 : :
39 : : private
40 : : !!***
41 : :
42 : : public :: ddb_elast
43 : : !!***
44 : :
45 : : contains
46 : : !!***
47 : :
48 : : !!****f* ABINIT/ddb_elast
49 : : !!
50 : : !! NAME
51 : : !! ddb_elast
52 : : !!
53 : : !! FUNCTION
54 : : !! Get the elastic and compliance tensors, both clamped ion and relaxed ion,
55 : : !! under the fixed electric field boundary condition; in which realxed ion
56 : : !! tensors can generate two output tensors one is conventional, the other
57 : : !! considers the sress correction.
58 : : !!
59 : : !! INPUTS
60 : : !! inp= (derived datatype) contains all the input variables
61 : : !! crystal<crystal_t>=Info on crystalline structure.
62 : : !! blkval(2,3,mpert,3,mpert,nblok)=
63 : : !! second derivatives of total energy with respect to electric fields
64 : : !! atom displacements, strain,...... all in cartesian coordinates
65 : : !! d2asr= ASR correction to the dynamical matrix at Gamma
66 : : !! iblok= bolk number in DDB file
67 : : !! iblok_stress= blok number which contain stress tensor
68 : : !! instrain=force response internal strain tensor
69 : : !! iout=out file number
70 : : !! mpert=maximum number of ipert
71 : : !! natom=number of atoms in unit cell
72 : : !! nblok=number of total bloks in DDB file
73 : : !! ncid=NC file handle (open in the caller)
74 : : !!
75 : : !! OUTPUT
76 : : !! elast=relaxed-ion elastic tensor (without stress correction) (6*6) in Voigt notation
77 : : !! elast_clamped=clamped-ion elastic tensor (without stress correction) (6*6) in Voigt notation
78 : : !! elast_stress=relaxed-ion elastic tensor (with stress correction) (6*6) in Voigt notation
79 : : !!
80 : : !! NOTES
81 : : !! The elastic (compliance) tensors calculated here are under boundary conditions of
82 : : !! fixed Electric Field, different from those in ddb_piezo.F90 which are under fixed
83 : : !! Displacement Field and incorporate piezoelectric corrections.
84 : : !!
85 : : !! SOURCE
86 : :
87 : 6 : subroutine ddb_elast(inp,crystal,blkval,compl,compl_clamped,compl_stress,d2asr,&
88 : : & elast,elast_clamped,elast_stress,iblok,iblok_stress,&
89 : 6 : & instrain,iout,mpert,natom,nblok,ncid)
90 : :
91 : : !Arguments -------------------------------------------
92 : : !scalars
93 : : integer,intent(in) :: iblok,iblok_stress,iout,mpert,natom,nblok,ncid
94 : : !integer,intent(in) :: msize
95 : : type(crystal_t),intent(in) :: crystal
96 : : type(anaddb_dataset_type),intent(in) :: inp
97 : : !arrays
98 : : real(dp),intent(in) :: blkval(2,3,mpert,3,mpert,nblok),instrain(3*natom,6)
99 : : real(dp),intent(in) :: d2asr(2,3,natom,3,natom)
100 : : real(dp),intent(out) :: compl(6,6), compl_clamped(6,6),compl_stress(6,6)
101 : : real(dp),intent(out) :: elast(6,6), elast_clamped(6,6),elast_stress(6,6)
102 : :
103 : : !Local variables------------------------------------
104 : : !scalars
105 : : integer :: ier,ii1,ii2,ipert1,ipert2,ivarA,ivarB,ncerr
106 : : real(dp) :: ucvol
107 : : logical :: iwrite
108 : : character(len=500) :: message
109 : : !arrays
110 : 12 : real(dp) :: Amatr(3*natom-3,3*natom-3),Apmatr(3*natom,3*natom)
111 : 12 : real(dp) :: Bmatr(2,((3*natom-3)*(3*natom-2))/2)
112 : 12 : real(dp) :: Bpmatr(2,(3*natom*(3*natom+1))/2),Cmatr(3*natom-3,3*natom-3)
113 : 12 : real(dp) :: Cpmatr(3*natom,3*natom),Nmatr(3*natom,3*natom)
114 : 12 : real(dp) :: compl_relaxed(6,6),eigval(3*natom-3)
115 : 12 : real(dp) :: eigvalp(3*natom),eigvec(2,3*natom-3,3*natom-3)
116 : 12 : real(dp) :: eigvecp(2,3*natom,3*natom),elast_relaxed(6,6)
117 : 12 : real(dp) :: kmatrix(3*natom,3*natom)
118 : 12 : real(dp) :: new2(6,6),stress(6),zhpev1(2,2*3*natom-4),zhpev1p(2,2*3*natom-1)
119 : 12 : real(dp) :: zhpev2(3*3*natom-5),zhpev2p(3*3*natom-2)
120 : 12 : real(dp) :: d2cart(2,3*natom,3*natom)
121 : :
122 : : !***************************************************************************
123 : 6 : compl = zero; compl_clamped = zero; compl_stress = zero
124 : 6 : elast = zero; elast_clamped = zero; elast_stress = zero
125 : :
126 : 6 : ucvol = crystal%ucvol
127 : 6 : iwrite = iout > 0
128 : :
129 : : !extraction of the elastic constants from the blkvals
130 : :
131 [ + + ]: 42 : do ivarA=1,6
132 [ + + ]: 258 : do ivarB=1,6
133 : : ! because the elastic constant is 6*6,
134 : : ! so we should judge if the idir is larger than 3 or not
135 [ + + ]: 216 : if(ivarA>3) then
136 : 108 : ii1=ivarA-3
137 : 108 : ipert1=natom+4 !for the shear modulus
138 : : else if(ivarA<=3) then
139 : 108 : ii1=ivarA
140 : 108 : ipert1=natom+3 !for the diagonal part
141 : : end if
142 [ + + ]: 216 : if(ivarB>3) then
143 : 108 : ii2=ivarB-3
144 : 108 : ipert2=natom+4 !for the shear modulus
145 : : else if(ivarB<=3) then
146 : 108 : ii2=ivarB
147 : 108 : ipert2=natom+3 !for the diagonal part
148 : : end if
149 : 252 : elast(ivarA,ivarB)=blkval(1,ii1,ipert1,ii2,ipert2,iblok)
150 : : end do
151 : : end do
152 : :
153 : : !then consider the volume, because the unit above is in
154 : : !Hartree, in fact the elastic constant should be in
155 : : !the units of pressure, the energy/volume
156 : : !And then transform the unit to si unit using GPa from Hartree/Bohr^3
157 : :
158 [ + + ]: 42 : do ivarA=1,6
159 [ + + ]: 258 : do ivarB=1,6
160 : 252 : elast(ivarA,ivarB)=(elast(ivarA,ivarB)/ucvol)*HaBohr3_GPa
161 : : end do
162 : : end do
163 : :
164 : : !then should consider the two situations: clamped and relaxed
165 : : !ions respectively, give the initial value of elast_clamped
166 : 6 : elast_clamped(:,:)=elast(:,:)
167 : 6 : elast_relaxed(:,:)=elast(:,:)
168 : :
169 : : !then do the matrix mulplication of instrain*K*instrain to get the
170 : : !correction of the relaxed ion quantities, in case natom/=1
171 : :
172 [ + - + - ]: 6 : if( (inp%elaflag==2 .or. inp%elaflag==3 .or. inp%elaflag==4 .or. inp%elaflag==5) .and. natom/=1 )then
173 : : ! extracting force matrix at gamma
174 [ + + + + : 498 : d2cart(1,:,:) = RESHAPE(blkval(1,1:3,1:natom,1:3,1:natom,iblok), (/3*natom,3*natom/))
+ + ]
175 [ + + + + ]: 486 : d2cart(2,:,:) = zero
176 : :
177 : : ! Eventually impose the acoustic sum rule
178 : : ! FIXME: this might depend on ifcflag: impose that it is 0 or generalize
179 : : !call asrq0_apply(asrq0, natom, mpert, msize, crystal%xcart, d2cart)
180 : 6 : call asria_corr(inp%asr,d2asr,d2cart,natom,natom)
181 [ + + + + ]: 486 : kmatrix = d2cart(1,:,:)
182 : :
183 : : ! write(std_out,'(/,a,/)')'the k matrix before inverse'
184 : : ! do ii1=1,3*natom
185 : : ! write(std_out,'(6es16.3)')kmatrix(ii1,1),kmatrix(ii1,2),kmatrix(ii1,3),&
186 : : ! & kmatrix(ii1,4),kmatrix(ii1,5),kmatrix(ii1,6)
187 : : ! end do
188 : :
189 : : ! according to formula, invert the kmatrix(3natom,3natom)
190 : :
191 : : ! NOTE: MJV 13/3/2011 This is just the 3x3 unit matrix copied throughout the dynamical matrix
192 [ + + + + ]: 486 : Nmatr(:,:)=zero
193 [ + + ]: 22 : do ivarB=0,natom-1
194 [ + + ]: 70 : do ivarA=0,natom-1
195 : 48 : Nmatr(3*ivarA+1, 3*ivarB+1) = one
196 : 48 : Nmatr(3*ivarA+2, 3*ivarB+2) = one
197 : 64 : Nmatr(3*ivarA+3, 3*ivarB+3) = one
198 : : end do
199 : : end do
200 : :
201 : : ! The k matrix is not the inverse here - it has not been changed!
202 : : ! write(std_out,'(/,a,/)')'the direct inverse of the Kmatrix'
203 : : ! do ivarA=1,3*natom
204 : : ! write(std_out,'(/)')
205 : : ! do ivarB=1,3*natom
206 : : ! write(std_out,'(es16.6)')kmatrix(ivarA,ivarB)
207 : : ! end do
208 : : ! end do
209 : :
210 : :
211 : : ! starting the pseudo-inverse processes then get the eigenvectors of the big matrix,give values to matrixBp
212 : : ! Pack the Nmatr matrix in Hermitian form
213 : : ii1=1
214 [ + + ]: 54 : do ivarA=1,3*natom
215 [ + + ]: 294 : do ivarB=1,ivarA
216 : 240 : Bpmatr(1,ii1)=Nmatr(ivarB,ivarA)
217 : 288 : ii1=ii1+1
218 : : end do
219 : : end do
220 [ + + ]: 246 : Bpmatr(2,:)=zero !the imaginary part of the force matrix
221 : : ! then call the subroutines CHPEV and ZHPEV to get the eigenvectors
222 : : ! NOTE: MJV there is a huge indeterminacy in this matrix, which has all identical 3x3 block lines
223 : : ! this means the orientation of the 0-eigenvalue eigenvectors is kind of random...
224 : : ! Is the usage just to get out the translational modes? We know what the eigenvectors look like already!
225 : : ! The translational modes are the last 3 with eigenvalue 6
226 : : !
227 : 6 : call ZHPEV ('V','U',3*natom,Bpmatr,eigvalp,eigvecp,3*natom,zhpev1p,zhpev2p,ier)
228 [ - + ]: 6 : ABI_CHECK(ier == 0, sjoin("ZHPEV returned:", itoa(ier)))
229 : :
230 : : ! the eigenval and eigenvec
231 : : ! write(std_out,'(/,a,/)')'the eigenvalues and eigenvectors'
232 : : ! do ivarA=1,3*natom
233 : : ! write(std_out,'(/)')
234 : : ! write(std_out,'(es16.6)')eigvalp(ivarA)
235 : : ! end do
236 : : ! do ivarA=1,3*natom
237 : : ! write(std_out,'(/)')
238 : : ! do ivarB=1,3*natom
239 : : ! write(std_out,'(es16.6)')eigvecp(1,ivarB,ivarA)
240 : : ! end do
241 : : ! end do
242 : :
243 : : ! do the multiplication to get the reduced matrix,in two steps
244 : : ! rotate to eigenbasis constructed above to isolate acoustic modes
245 [ - + + - : 14904 : Apmatr(:,:) = MATMUL(TRANSPOSE(eigvecp(1,:,:)), MATMUL(kmatrix(:,:), eigvecp(1,:,:)))
- + + - +
- + - - +
- + + + +
+ + + + +
+ + + - +
+ + + + +
+ + + + +
- + - +
- ]
246 : :
247 : : ! the blok diagonal parts
248 : : ! write(std_out,'(/,a,/)')'Apmatr'
249 : : ! do ivarA=1,3*natom
250 : : ! write(std_out,'(/)')
251 : : ! do ivarB=1,3*natom
252 : : ! write(std_out,'(es16.6)')Apmatr(ivarA,ivarB)
253 : : ! end do
254 : : ! end do
255 : :
256 : : ! check the last three eigenvalues whether too large
257 : 6 : ivarB=0
258 [ + + ]: 24 : do ivarA=3*natom-2,3*natom
259 [ - + ]: 24 : if (ABS(Apmatr(ivarA,ivarA))>tol6) ivarB=1
260 : : end do
261 [ - + ]: 6 : if(ivarB==1)then
262 : 0 : write(message,'(a,a,a,a,a,a,a,a,3es16.6)')ch10,&
263 : 0 : & ' Acoustic sum rule violation met : the eigenvalues of accoustic mode',ch10,&
264 : 0 : & ' are too large at Gamma point',ch10,&
265 : 0 : & ' increase cutoff energy or k-points sampling.',ch10,&
266 : 0 : & ' The three eigenvalues are:',Apmatr(3*natom-2,3*natom-2),&
267 : 0 : & Apmatr(3*natom-1,natom-1),Apmatr(3*natom,3*natom)
268 : 0 : ABI_WARNING(message)
269 : 0 : call wrtout(iout,message,'COLL')
270 : : end if
271 : : ! then give the value of reduced matrix form Apmatr to Amatr
272 [ + + + + ]: 234 : Amatr(:,:) = Apmatr(1:3*natom-3, 1:3*natom-3)
273 : :
274 : : ! now the reduced matrix is in the Amatr, the convert it
275 : : ! first give the give the value of Bmatr from Amatr
276 : : ii1=1
277 [ + + ]: 36 : do ivarA=1,3*natom-3
278 [ + + ]: 150 : do ivarB=1,ivarA
279 : 114 : Bmatr(1,ii1)=Amatr(ivarB,ivarA)
280 : 144 : ii1=ii1+1
281 : : end do
282 : : end do
283 [ + + ]: 120 : Bmatr(2,:)=zero
284 : : ! then call the subroutines CHPEV and ZHPEV to get the eigenvectors and the eigenvalues
285 : 6 : call ZHPEV ('V','U',3*natom-3,Bmatr,eigval,eigvec,3*natom-3,zhpev1,zhpev2,ier)
286 [ - + ]: 6 : ABI_CHECK(ier == 0, sjoin("ZHPEV returned:", itoa(ier)))
287 : :
288 : : ! check the unstable phonon modes, if the first is negative then print warning message
289 [ - + ]: 6 : if(eigval(1)<-1.0*tol8)then
290 : 0 : write(message,'(a,a,a,a)') ch10,&
291 : 0 : 'Unstable eigenvalue detected in force constant matrix at Gamma point.',ch10,&
292 : 0 : 'The system under calculation is physically unstable.'
293 : 0 : ABI_WARNING(message)
294 : 0 : call wrtout(iout,message,'COLL')
295 : : end if
296 : :
297 : : ! the do the matrix muplication to get pseudoinverse inverse matrix
298 [ + + + + ]: 234 : Cmatr(:,:)=zero
299 [ + + ]: 36 : do ivarA=1,3*natom-3
300 : 36 : Cmatr(ivarA,ivarA)=1.0_dp/eigval(ivarA)
301 : : end do
302 [ - + + - : 5634 : Amatr(:,:) = MATMUL(MATMUL(eigvec(1,:,:), Cmatr(:,:)), TRANSPOSE(eigvec(1,:,:)))
- + + - +
- + - - +
- + + + +
+ + + + +
+ + + - +
+ + + + +
+ + + + +
- + - +
- ]
303 : :
304 : : ! write(std_out,'(/,a,/)')'the pseudo inverse of the force matrix'
305 : : ! do ivarA=1,3*natom
306 : : ! write(std_out,'(/)')
307 : : ! do ivarB=1,3*natom
308 : : ! write(std_out,'(es16.6)')Cmatr(ivarA,ivarB)
309 : : ! end do
310 : : ! end do
311 : :
312 : : ! so now the inverse of the reduced matrix is in the matrixA
313 : : ! now do another mulplication to get the pseudoinverse of the original
314 [ + + + + ]: 486 : Cpmatr(:,:)=zero
315 [ + + + + ]: 486 : Apmatr(:,:)=zero
316 [ + + ]: 36 : do ivarA=1,3*natom-3
317 [ + + ]: 234 : do ivarB=1,3*natom-3
318 : 228 : Cpmatr(ivarA,ivarB)=Amatr(ivarA,ivarB)
319 : : end do
320 : : end do
321 : :
322 : : ! times the eigvecp
323 [ + + ]: 54 : do ivarA=1,3*natom
324 [ + + ]: 486 : do ivarB=1,3*natom
325 [ + + ]: 4800 : do ii1=1,3*natom
326 : 4752 : Apmatr(ivarA,ivarB)=Apmatr(ivarA,ivarB)+eigvecp(1,ivarA,ii1)*Cpmatr(ii1,ivarB)
327 : : end do
328 : : end do
329 : : end do
330 [ + + + + ]: 486 : Cpmatr(:,:)=zero
331 [ + + ]: 54 : do ivarA=1,3*natom
332 [ + + ]: 486 : do ivarB=1,3*natom
333 [ + + ]: 4800 : do ii1=1,3*natom
334 : 4752 : Cpmatr(ivarA,ivarB)=Cpmatr(ivarA,ivarB)+Apmatr(ivarA,ii1)*eigvecp(1,ivarB,ii1)
335 : : end do
336 : : end do
337 : : end do
338 : :
339 : : ! now the inverse in in Cpmatr
340 [ + + + + ]: 486 : kmatrix(:,:)=Cpmatr(:,:)
341 : : ! transfer the inverse of k-matrix back to the k matrix
342 : : ! so now the inverse of k matrix is in the kmatrix
343 : : ! ending the part for pseudoinversing the K matrix
344 [ - + + - : 7050 : new2(:,:) = MATMUL(MATMUL(TRANSPOSE(instrain), kmatrix), instrain(:,:))
+ - + - -
+ - + + +
+ + + + +
+ + + + -
+ + + + +
+ + - + -
+ - ]
345 : :
346 : :
347 : : ! then finish the matrix mupl., consider the unit cell volume and the unit change next step
348 [ + + + + ]: 258 : new2(:,:)=(new2(:,:)/ucvol)*HaBohr3_GPa
349 : :
350 : : ! then the relaxed one should be the previous one minus the new2 element
351 [ + + + + ]: 258 : elast_relaxed(:,:)=elast_relaxed(:,:)-new2(:,:)
352 : : end if
353 : : !the above end if end if for elaflag=2 or elafalg=3 or elafalg=4, or elafalg=5 in line 125
354 : :
355 : : !write(std_out,'(/,a,/)')'debug the unit cell volume'
356 : : !write(std_out,'(2es16.6)')ucvol,HaBohr3_GPa
357 : :
358 : : !then give the initial value of the compl_relaxed(6,6)
359 : 6 : compl_relaxed(:,:)=elast_relaxed(:,:)
360 : :
361 : : !*******************************************************************
362 [ + + ]: 6 : if(inp%elaflag==1.or. inp%elaflag==3)then
363 : : ! print out the clamped-ion elastic constants to output file
364 : 3 : write(message,'(3a)')ch10,' Elastic Tensor (clamped ion) (unit:10^2GP):',ch10
365 : 3 : call wrtout(std_out,message,'COLL')
366 [ + + ]: 21 : do ivarA=1,6
367 : 18 : write(std_out,'(6f12.7)')elast(ivarA,1)/100.00_dp,elast(ivarA,2)/100.00_dp,&
368 : 18 : & elast(ivarA,3)/100.00_dp,elast(ivarA,4)/100.00_dp,&
369 : 39 : & elast(ivarA,5)/100.00_dp,elast(ivarA,6)/100.00_dp
370 : : end do
371 : :
372 : 3 : call wrtout(iout,message,'COLL')
373 [ + - ]: 3 : if (iwrite) then
374 [ + + ]: 21 : do ivarA=1,6
375 : 18 : write(iout,'(6f12.7)')elast(ivarA,1)/100.00_dp,elast(ivarA,2)/100.00_dp,&
376 : 18 : & elast(ivarA,3)/100.00_dp,elast(ivarA,4)/100.00_dp,&
377 : 39 : & elast(ivarA,5)/100.00_dp,elast(ivarA,6)/100.00_dp
378 : : end do
379 : : end if
380 : : end if
381 : :
382 [ + - ]: 6 : if(inp%elaflag==2.or.inp%elaflag==3 .or. inp%elaflag==4.or. inp%elaflag==5)then
383 [ - + ]: 6 : if(inp%instrflag==0)then
384 : 0 : write(message,'(a,a,a,a,a,a,a,a)' )ch10,&
385 : 0 : & 'in order to get the elastic tensor(relaxed ion), ',ch10,&
386 : 0 : & 'one needs information about internal strain ',ch10,&
387 : 0 : & 'one should set instrflag==1;',ch10,&
388 : 0 : & 'otherwise the program will continue but give wrong values.'
389 : 0 : ABI_WARNING(message)
390 : 0 : call wrtout(iout,message,'COLL')
391 : : end if
392 : :
393 : 6 : write(message,'(5a)')ch10,&
394 : 6 : & ' Elastic Tensor (relaxed ion) (unit:10^2GP):',ch10,&
395 : 12 : & ' (at fixed electric field boundary condition)',ch10
396 : 6 : call wrtout(std_out,message,'COLL')
397 [ + + ]: 42 : do ivarA=1,6
398 : 36 : write(std_out,'(6f12.7)')elast_relaxed(ivarA,1)/100.00_dp,&
399 : 36 : & elast_relaxed(ivarA,2)/100.00_dp,elast_relaxed(ivarA,3)/100.00_dp,&
400 : 36 : & elast_relaxed(ivarA,4)/100.00_dp,elast_relaxed(ivarA,5)/100.00_dp,&
401 : 78 : & elast_relaxed(ivarA,6)/100.00_dp
402 : : end do
403 : :
404 : 6 : call wrtout(iout,message,'COLL')
405 [ + - ]: 6 : if (iwrite) then
406 [ + + ]: 42 : do ivarA=1,6
407 : 36 : write(iout,'(6f12.7)')elast_relaxed(ivarA,1)/100.00_dp,&
408 : 36 : & elast_relaxed(ivarA,2)/100.00_dp,elast_relaxed(ivarA,3)/100.00_dp,&
409 : 36 : & elast_relaxed(ivarA,4)/100.00_dp,elast_relaxed(ivarA,5)/100.00_dp,&
410 : 78 : & elast_relaxed(ivarA,6)/100.00_dp
411 : : end do
412 : : end if
413 : : end if
414 : :
415 : : !then print the corresponding compliances
416 : :
417 [ + + ]: 6 : if(inp%elaflag==1.or.inp%elaflag==3)then
418 : : ! compl(:,:)=elast_clamped(:,:) !convert the elastic tensor
419 : 3 : compl_clamped(:,:)=elast_clamped(:,:)
420 : 3 : call matrginv(compl_clamped,6,6)
421 : 3 : write(message,'(a,a,a)')ch10,' Compliance Tensor (clamped ion) (unit: 10^-2GP^-1):',ch10
422 : 3 : call wrtout(std_out,message,'COLL')
423 : :
424 [ + + ]: 21 : do ivarB=1,6
425 : 18 : write(std_out,'(6f12.7)')compl_clamped(ivarB,1)*100.00_dp,&
426 : 18 : & compl_clamped(ivarB,2)*100.00_dp,&
427 : 18 : & compl_clamped(ivarB,3)*100.00_dp,compl_clamped(ivarB,4)*100.00_dp,&
428 : 18 : & compl_clamped(ivarB,5)*100.00_dp,&
429 : 39 : & compl_clamped(ivarB,6)*100.00_dp
430 : : end do
431 : :
432 : 3 : call wrtout(iout,message,'COLL')
433 : :
434 [ + - ]: 3 : if (iwrite) then
435 [ + + ]: 21 : do ivarB=1,6
436 : 18 : write(iout,'(6f12.7)')compl_clamped(ivarB,1)*100.00_dp,&
437 : 18 : & compl_clamped(ivarB,2)*100.00_dp,&
438 : 18 : & compl_clamped(ivarB,3)*100.00_dp,compl_clamped(ivarB,4)*100.00_dp,&
439 : 18 : & compl_clamped(ivarB,5)*100.00_dp,&
440 : 39 : & compl_clamped(ivarB,6)*100.00_dp
441 : : end do
442 : : end if
443 : : end if
444 : :
445 [ + - ]: 6 : if(inp%elaflag==2.or.inp%elaflag==3 .or. inp%elaflag==4 .or. inp%elaflag==5)then
446 : : ! compl(:,:)=elast_relaxed(:,:)
447 : 6 : call matrginv(compl_relaxed,6,6)
448 [ - + ]: 6 : if(inp%instrflag==0)then
449 : 0 : write(message,'(a,a,a,a,a,a,a,a)' )ch10,&
450 : 0 : & 'in order to get the compliance tensor(relaxed ion), ',ch10,&
451 : 0 : & 'one needs information about internal strain ',ch10,&
452 : 0 : & 'one should set instrflag==1;',ch10,&
453 : 0 : & 'otherwise the program will continue but give wrong values.'
454 : 0 : ABI_WARNING(message)
455 : 0 : call wrtout(iout,message,'COLL')
456 : : end if
457 : 6 : write(message,'(5a)')ch10,&
458 : 6 : & ' Compliance Tensor (relaxed ion) (unit: 10^-2GP^-1):',ch10,&
459 : 12 : & ' (at fixed electric field boundary condition)',ch10
460 : 6 : call wrtout(std_out,message,'COLL')
461 : :
462 [ + + ]: 42 : do ivarB=1,6
463 : 36 : write(std_out,'(6f12.7)')compl_relaxed(ivarB,1)*100.00_dp,&
464 : 36 : & compl_relaxed(ivarB,2)*100.00_dp,&
465 : 36 : & compl_relaxed(ivarB,3)*100.00_dp,compl_relaxed(ivarB,4)*100.00_dp,&
466 : 36 : & compl_relaxed(ivarB,5)*100.00_dp,&
467 : 78 : & compl_relaxed(ivarB,6)*100.00_dp
468 : : end do
469 : 6 : call wrtout(iout,message,'COLL')
470 : :
471 [ + - ]: 6 : if (iwrite) then
472 [ + + ]: 42 : do ivarB=1,6
473 : 36 : write(iout,'(6f12.7)')compl_relaxed(ivarB,1)*100.00,&
474 : 36 : & compl_relaxed(ivarB,2)*100.00_dp,&
475 : 36 : & compl_relaxed(ivarB,3)*100.00_dp,compl_relaxed(ivarB,4)*100.00_dp,&
476 : 36 : & compl_relaxed(ivarB,5)*100.00_dp,&
477 : 78 : & compl_relaxed(ivarB,6)*100.00_dp
478 : : end do
479 : : end if
480 : : end if
481 : :
482 : : !befor the end , make sure the tensor elast(6,6)
483 : : !will have the relaxed ion values and tensor elast_clamped has the clamped ion
484 : : !values, and similarily for the corresponding compliance tensors
485 : 6 : elast_clamped(:,:)=elast(:,:)
486 : 6 : elast(:,:)=elast_relaxed(:,:)
487 : 6 : compl(:,:)=compl_relaxed(:,:)
488 : :
489 : : !begin the part of computing stress corrected elastic tensors
490 [ + + ]: 6 : if(inp%elaflag==5)then
491 : :
492 : : ! check the iblok number of first derivative of energy
493 : : ! write(std_out,'(/,a,/)')'iblok number at 8:00Pm'
494 : : ! write(std_out,'(i)')iblok_stress
495 : : ! write(std_out,'(a,f12.7)')'the total energy', blkval(1,1,1)
496 : : ! write(std_out,*)'',blkval(1,:,:,:,:,iblok_stress)
497 : : ! write(std_out,*)'',blkval(1,:,7,1,1,iblok_stress)
498 : :
499 : : ! firts give the corect stress values diagonal parts
500 : 1 : stress(1)=blkval(1,1,natom+3,1,1,iblok_stress)
501 : 1 : stress(2)=blkval(1,2,natom+3,1,1,iblok_stress)
502 : 1 : stress(3)=blkval(1,3,natom+3,1,1,iblok_stress)
503 : : ! the shear parts
504 : 1 : stress(4)=blkval(1,1,natom+4,1,1,iblok_stress)
505 : 1 : stress(5)=blkval(1,2,natom+4,1,1,iblok_stress)
506 : 1 : stress(6)=blkval(1,3,natom+4,1,1,iblok_stress)
507 : : ! then convert the unit from atomic to the GPa unit
508 [ + + ]: 7 : do ivarA=1,6
509 : 7 : stress(ivarA)=stress(ivarA)*HaBohr3_GPa
510 : : end do
511 : : ! give the initial values of elast_stress tensor
512 : 1 : elast_stress(:,:)=elast_relaxed(:,:)
513 : : ! notice that only the first three rows need to be corrected
514 [ + + ]: 4 : do ivarA=1,3
515 [ + + ]: 22 : do ivarB=1,6
516 : 21 : elast_stress(ivarA,ivarB)=elast_stress(ivarA,ivarB)-stress(ivarB)
517 : : end do
518 : : end do
519 : : ! then compute the values of compliance tensor with stress correction
520 : 1 : compl_stress(:,:)=elast_stress(:,:)
521 : 1 : call matrginv(compl_stress,6,6)
522 : : ! then print out the results of stress corrected elastic and compliance tensors
523 [ - + ]: 1 : if(inp%instrflag==0)then
524 : 0 : write(message,'(a,a,a,a,a,a,a,a)' )ch10,&
525 : 0 : & 'In order to get the elastic tensor (relaxed ion with stress correction), ',ch10,&
526 : 0 : & 'one needs information about internal strain ',ch10,&
527 : 0 : & 'one should set instrflag==1;',ch10,&
528 : 0 : & 'otherwise the program will continue but give wrong values.'
529 : 0 : ABI_WARNING(message)
530 : 0 : call wrtout(iout,message,'COLL')
531 : : end if
532 : 1 : write(message,'(5a)')ch10,&
533 : 1 : & ' Elastic Tensor (relaxed ion with stress corrected) (unit:10^2GP)',ch10,&
534 : 2 : & ' (at fixed electric field boundary condition)',ch10
535 : 1 : call wrtout(std_out,message,'COLL')
536 : 1 : call wrtout(iout,message,'COLL')
537 [ + + ]: 7 : do ivarA=1,6
538 : 6 : write(std_out,'(6f12.7)')elast_stress(ivarA,1)/100.00_dp,elast_stress(ivarA,2)/100.00_dp,&
539 : 6 : & elast_stress(ivarA,3)/100.00_dp,elast_stress(ivarA,4)/100.00_dp,&
540 : 13 : & elast_stress(ivarA,5)/100.00_dp,elast_stress(ivarA,6)/100.00_dp
541 : : end do
542 [ + - ]: 1 : if (iwrite) then
543 [ + + ]: 7 : do ivarA=1,6
544 : 6 : write(iout,'(6f12.7)')elast_stress(ivarA,1)/100.00_dp,elast_stress(ivarA,2)/100.00_dp,&
545 : 6 : & elast_stress(ivarA,3)/100.00_dp,elast_stress(ivarA,4)/100.00_dp,&
546 : 13 : & elast_stress(ivarA,5)/100.00_dp,elast_stress(ivarA,6)/100.00_dp
547 : : end do
548 : : end if
549 : :
550 : : ! then the compliance tensors with stress correction
551 : 1 : write(message,'(5a)')ch10,&
552 : 1 : & ' Compliance Tensor (relaxed ion with stress correction) (unit: 10^-2(GP)^-1):',ch10,&
553 : 2 : & ' (at fixed electric field boundary condition)',ch10
554 : 1 : call wrtout(std_out,message,'COLL')
555 : 1 : call wrtout(iout,message,'COLL')
556 [ + + ]: 7 : do ivarB=1,6
557 : 6 : write(std_out,'(6f12.7)')compl_stress(ivarB,1)*100.00_dp,&
558 : 6 : & compl_stress(ivarB,2)*100.00_dp,&
559 : 6 : & compl_stress(ivarB,3)*100.00_dp,compl_stress(ivarB,4)*100.00_dp,&
560 : 6 : & compl_stress(ivarB,5)*100.00_dp,&
561 : 13 : & compl_stress(ivarB,6)*100.00_dp
562 : : end do
563 [ + - ]: 1 : if (iwrite) then
564 [ + + ]: 7 : do ivarB=1,6
565 : 6 : write(iout,'(6f12.7)')compl_stress(ivarB,1)*100.00_dp,&
566 : 6 : & compl_stress(ivarB,2)*100.00_dp,&
567 : 6 : & compl_stress(ivarB,3)*100.00_dp,compl_stress(ivarB,4)*100.00_dp,&
568 : 6 : & compl_stress(ivarB,5)*100.00_dp,&
569 : 13 : & compl_stress(ivarB,6)*100.00_dp
570 : : end do
571 : : end if
572 : : end if
573 : : !end the if 510th line
574 : : !end the part of stress corrected elastic and compliance tensors
575 : :
576 : :
577 : : ! Writes the elastic constants tensors (clamped-ion, relaxed-ion with and
578 : : ! without stress corrections) to a netCDF file.
579 : : !
580 : : ! compl=relaxed-ion compliance tensor(without stress correction) (6*6) in Voigt notation
581 : : ! compl_clamped=clamped-ion compliance tensor(without stress correction) (6*6) in Voigt notation
582 : : ! compl_stress=relaxed-ion compliance tensor(with stress correction) (6*6) in Voigt notation
583 : : ! elast=relaxed-ion elastic tensor(without stress correction) (6*6) in Voigt notation
584 : : ! elast_clamped=clamped-ion elastic tensor(without stress correction) (6*6) in Voigt notation
585 : : ! elast_stress=relaxed-ion elastic tensor(with stress correction) (6*6) in Voigt notation
586 : : ! Units are GPa for elastic constants and GPa^-1 for compliance constants
587 : :
588 [ + - ]: 6 : if (ncid /= nctk_noid) then
589 : : ! Define dimensions
590 [ - + ]: 6 : NCF_CHECK(nctk_def_basedims(ncid, defmode=.True.))
591 : :
592 [ + + ]: 24 : ncerr = nctk_def_iscalars(ncid, [character(len=nctk_slen) :: "asr", "elaflag", "instrflag"])
593 [ - + ]: 6 : NCF_CHECK(ncerr)
594 : :
595 : : !arrays
596 : : ncerr = nctk_def_arrays(ncid, [&
597 : : nctkarr_t('internal_strain_tensor', "dp", 'natom3, six'), &
598 : : nctkarr_t('compliance_constants_relaxed_ion', "dp", 'six, six'), &
599 : : nctkarr_t('compliance_constants_clamped_ion', "dp", 'six, six'), &
600 : : nctkarr_t('compliance_constants_relaxed_ion_stress_corrected', "dp", "six, six"), &
601 : : nctkarr_t('elastic_constants_relaxed_ion', "dp", 'six, six'), &
602 : : nctkarr_t('elastic_constants_clamped_ion', "dp", 'six, six'), &
603 [ + + ]: 48 : nctkarr_t('elastic_constants_relaxed_ion_stress_corrected', "dp", 'six, six')])
604 [ - + ]: 6 : NCF_CHECK(ncerr)
605 : :
606 : : ! Write variables.
607 [ - + ]: 6 : NCF_CHECK(nctk_set_datamode(ncid))
608 [ - + ]: 6 : NCF_CHECK(nf90_put_var(ncid, vid('asr'), inp%asr))
609 [ - + ]: 6 : NCF_CHECK(nf90_put_var(ncid, vid('elaflag'), inp%elaflag))
610 [ - + ]: 6 : NCF_CHECK(nf90_put_var(ncid, vid('instrflag'), inp%instrflag))
611 [ - + ]: 6 : NCF_CHECK(nf90_put_var(ncid, vid('internal_strain_tensor'), instrain))
612 [ - + ]: 6 : NCF_CHECK(nf90_put_var(ncid, vid('compliance_constants_relaxed_ion'), compl))
613 [ - + ]: 6 : NCF_CHECK(nf90_put_var(ncid, vid('compliance_constants_clamped_ion'), compl_clamped))
614 [ - + ]: 6 : NCF_CHECK(nf90_put_var(ncid, vid('compliance_constants_relaxed_ion_stress_corrected'), compl_stress))
615 [ - + ]: 6 : NCF_CHECK(nf90_put_var(ncid, vid('elastic_constants_relaxed_ion'), elast))
616 [ - + ]: 6 : NCF_CHECK(nf90_put_var(ncid, vid('elastic_constants_clamped_ion'), elast_clamped))
617 [ - + ]: 6 : NCF_CHECK(nf90_put_var(ncid, vid('elastic_constants_relaxed_ion_stress_corrected'), elast_stress))
618 : : end if
619 : :
620 : : contains
621 : :
622 : 60 : integer function vid(vname)
623 : : character(len=*),intent(in) :: vname
624 : 60 : vid = nctk_idname(ncid, vname)
625 : : end function vid
626 : :
627 : : end subroutine ddb_elast
628 : : !!***
629 : :
630 [ + - + - : 18 : end module m_ddb_elast
+ - ]
631 : : !!***
|