Line data Source code
1 : !!****m* ABINIT/m_harmonic_thermo
2 : !! NAME
3 : !! m_harmonic_thermo
4 : !!
5 : !! FUNCTION
6 : !! This routine to calculate phonon density of states,
7 : !! thermodynamical properties, Debye-Waller factor, and atomic mean square velocity
8 : !!
9 : !! COPYRIGHT
10 : !! Copyright (C) 2008-2026 ABINIT group (CL, XG)
11 : !! This file is distributed under the terms of the
12 : !! GNU General Public License, see ~abinit/COPYING
13 : !! or http://www.gnu.org/copyleft/gpl.txt .
14 : !!
15 : !! SOURCE
16 :
17 : #if defined HAVE_CONFIG_H
18 : #include "config.h"
19 : #endif
20 :
21 : #include "abi_common.h"
22 :
23 : module m_harmonic_thermo
24 :
25 : use defs_basis
26 : use m_errors
27 : use m_abicore
28 : use m_sortph
29 : use m_xmpi
30 :
31 : use m_io_tools, only : open_file
32 : use m_matrix, only : matr3inv
33 : use m_dynmat, only : gtdyn9
34 : use m_geometry, only : mkrdim
35 : use m_crystal, only : crystal_t
36 : use m_anaddb_dataset, only : anaddb_dataset_type
37 : use m_ifc, only : ifc_type
38 : use m_kpts, only : smpbz
39 : use m_symkpt, only : symkpt
40 :
41 : implicit none
42 :
43 : private
44 : !!***
45 :
46 : public :: harmonic_thermo
47 : !!***
48 :
49 : contains
50 : !!***
51 :
52 : !!****f* m_harmonic_thermo/harmonic_thermo
53 : !!
54 : !! NAME
55 : !! harmonic_thermo
56 : !!
57 : !! FUNCTION
58 : !! This routine to calculate phonon density of states,
59 : !! thermodynamical properties, Debye-Waller factor, and atomic mean square velocity
60 : !!
61 : !! INPUTS
62 : !! Crystal<crystal_t>=data type gathering info on the crystalline structure.
63 : !! Ifc<ifc_type>=Object containing the interatomic force constants.
64 : !! %atmfrc(2,3,natom,3,natom,nrpt) = Interatomic Forces in real space
65 : !! %dyewq0(3,3,natom)=Ewald part of the dynamical matrix, at q=0.
66 : !! %rpt(3,nrpt)=canonical coordinates of the R points in the unit cell These coordinates are normalized (=> * acell(3)!!)
67 : !! %nrpt=number of R points in the Big Box
68 : !! %trans(3,natom)=atomic translations : xred = rcan + trans
69 : !! %wghatm(natom,natom,nrpt)=weights associated to a pair of atoms and to a R vector
70 : !! amu(ntypat)=mass of the atoms (atomic mass unit)
71 : !! anaddb_dtset= (derived datatype) contains all the input variables
72 : !! iout =unit number for output
73 : !! natom=number of atoms in the unit cell
74 : !! outfilename_radix=radix of anaddb output file name: append _THERMO for thermodynamic quantities
75 : !! comm=MPI communicator
76 : !!
77 : !! OUTPUT
78 : !!
79 : !! NOTES
80 : !! dosinc=increment between the channels for the phonon DOS in cm-1
81 : !!
82 : !! SOURCE
83 :
84 4 : subroutine harmonic_thermo(Ifc,Crystal,amu,anaddb_dtset,iout,outfilename_radix,comm,thmflag)
85 :
86 : !Arguments -------------------------------
87 : !scalars
88 : integer,intent(in) :: iout,comm
89 : integer,intent(in),optional :: thmflag
90 : character(len=*),intent(in) :: outfilename_radix
91 : type(anaddb_dataset_type),intent(in) :: anaddb_dtset
92 : type(crystal_t),intent(in) :: Crystal
93 : type(ifc_type),intent(in) :: Ifc
94 : !arrays
95 : real(dp),intent(in) :: amu(Crystal%ntypat)
96 :
97 : !Local variables -------------------------
98 : !scalars
99 : integer,parameter :: master=0
100 : integer :: convth,facbrv,iatom,ichan,icomp,igrid,iii,iiii,ij,ind
101 : integer :: iqpt2,isym,itemper,iwchan,jjj,mqpt2,nchan,ngrids,natom
102 : integer :: nqpt2,nspqpt,ntemper,nwchan,option,timrev
103 : integer :: thermal_unit
104 : integer :: bij_unit
105 : integer :: vij_unit
106 : integer :: nomega, iomega
107 : real(dp) :: change,cothx,diffbb,dosinc,expm2x,factor,factorw,factorv,gerr
108 : real(dp) :: ggsum,ggsumsum,ggrestsum
109 : real(dp) :: gijerr,gijsum,gnorm,ln2shx,qphnrm,relchg,tmp,wovert,thmtol
110 : logical :: part1,part2
111 : character(len=500) :: msg
112 : character(len=fnlen) :: thermal_filename
113 : character(len=fnlen) :: bij_filename
114 : character(len=fnlen) :: vij_filename
115 : !arrays
116 8 : integer :: symrec(3,3,Crystal%nsym),symrel(3,3,Crystal%nsym)
117 8 : real(dp) :: symrec_cart(3,3,Crystal%nsym)
118 : integer :: igqpt2(3),ii(6),jj(6),qptrlatt(3,3)
119 4 : integer,allocatable :: indqpt1(:),nchan2(:),bz2ibz_smap(:,:)
120 : real(dp) :: gprimd(3,3),qphon(3),rprimd(3,3),tens1(3,3),tens2(3,3)
121 8 : real(dp) :: displ(2*3*Crystal%natom*3*Crystal%natom)
122 8 : real(dp) :: eigvec(2,3,Crystal%natom,3*Crystal%natom)
123 4 : real(dp) :: phfrq(3*Crystal%natom)
124 4 : real(dp),allocatable :: bbij(:,:,:),bij(:,:,:),energy(:),energy0(:),entropy(:)
125 4 : real(dp),allocatable :: entropy0(:),free(:),free0(:),gdos(:,:),gg(:,:),gg_sum(:,:),gg_rest(:,:)
126 4 : real(dp),allocatable :: ggij(:,:,:,:),gij(:,:,:,:),gw(:,:),qpt2(:,:),spheat(:)
127 4 : real(dp),allocatable :: spheat0(:),spqpt2(:,:),wme(:),wtq(:),wtq2(:)
128 4 : real(dp),allocatable :: wtq_folded(:),vij(:,:,:)
129 4 : real(dp),allocatable :: phon_dos(:)
130 4 : logical,allocatable :: wgcnv(:),wgijcnv(:)
131 :
132 : ! *********************************************************************
133 :
134 : ! For the time being, this routine can use only 1 MPI process
135 4 : if (xmpi_comm_rank(comm) /= master) return
136 :
137 4 : natom = Crystal%natom
138 784 : symrel = Crystal%symrel
139 784 : symrec = Crystal%symrec
140 :
141 4 : call mkrdim(Ifc%acell,Ifc%rprim,rprimd)
142 4 : call matr3inv(rprimd,gprimd)
143 64 : do isym = 1, Crystal%nsym
144 6184 : symrec_cart(:,:,isym) = matmul( gprimd, matmul(dble(symrec(:,:,isym)), transpose(rprimd)) )
145 : ! net result is tens1 = rprimd symrec^T gprimd^T tens1 gprimd symrec rprimd^T
146 : end do
147 :
148 4 : thermal_filename=trim(outfilename_radix)//"_THERMO"
149 4 : if (open_file(thermal_filename, msg, newunit=thermal_unit) /= 0) then
150 0 : ABI_ERROR(msg)
151 : end if
152 :
153 4 : write(thermal_unit,*) '#'
154 4 : write(thermal_unit,*) '# Thermodynamical quantities calculated by ANADDB'
155 4 : write(thermal_unit,*) '#'
156 :
157 4 : bij_filename=trim(outfilename_radix)//"_DEBYE_WALLER"
158 4 : if (open_file(bij_filename, msg, newunit=bij_unit) /= 0) then
159 0 : ABI_ERROR(msg)
160 : end if
161 :
162 4 : vij_filename=trim(outfilename_radix)//"_VELOC_SQUARED"
163 4 : if (open_file(vij_filename, msg, newunit=vij_unit) /= 0) then
164 0 : ABI_ERROR(msg)
165 : end if
166 :
167 4 : thmtol = anaddb_dtset%thmtol
168 4 : nchan=anaddb_dtset%nchan
169 4 : ntemper=anaddb_dtset%ntemper
170 4 : nwchan=anaddb_dtset%nwchan
171 4 : ngrids=anaddb_dtset%ngrids
172 :
173 16 : ABI_MALLOC(bbij,(6,natom,ntemper))
174 12 : ABI_MALLOC(bij,(6,natom,ntemper))
175 12 : ABI_MALLOC(vij,(6,natom,ntemper))
176 12 : ABI_MALLOC(energy,(ntemper))
177 8 : ABI_MALLOC(energy0,(ntemper))
178 8 : ABI_MALLOC(entropy,(ntemper))
179 8 : ABI_MALLOC(entropy0,(ntemper))
180 8 : ABI_MALLOC(free,(ntemper))
181 8 : ABI_MALLOC(free0,(ntemper))
182 : !Doubling the size (nchan) of gg_sum is needed, because the maximum sum frequency is the double
183 : !the for maximum frequency. However, for the write statement, it is better to double
184 : !also the size of the other arrays ...
185 16 : ABI_MALLOC(gdos,(2*nchan,nwchan))
186 12 : ABI_MALLOC(gg,(2*nchan,nwchan))
187 12 : ABI_MALLOC(gg_sum,(2*nchan,nwchan))
188 12 : ABI_MALLOC(gg_rest,(2*nchan,nwchan))
189 20 : ABI_MALLOC(ggij,(6,natom,nchan,nwchan))
190 16 : ABI_MALLOC(gij,(6,natom,nchan,nwchan))
191 12 : ABI_MALLOC(nchan2,(nwchan))
192 8 : ABI_MALLOC(spheat,(ntemper))
193 8 : ABI_MALLOC(spheat0,(ntemper))
194 8 : ABI_MALLOC(wgcnv,(nwchan))
195 8 : ABI_MALLOC(wgijcnv,(nwchan))
196 8 : ABI_MALLOC(wme,(ntemper))
197 16 : ABI_MALLOC(gw,(nchan,nwchan))
198 :
199 :
200 : !initialize ii and jj arrays
201 4 : ii(1)=1 ; ii(2)=2 ; ii(3)=3
202 4 : ii(4)=1 ; ii(5)=1 ; ii(6)=2
203 4 : jj(1)=1 ; jj(2)=2 ; jj(3)=3
204 4 : jj(4)=2 ; jj(5)=3 ; jj(6)=3
205 :
206 : !Put zeros in the bins of channels of frequencies
207 53529 : gdos(:,:)=0._dp
208 53529 : gg_sum(:,:)=0._dp
209 53529 : gg_rest(:,:)=0._dp
210 1013779 : gij(:,:,:,:)=0._dp
211 :
212 : !Neither part1 nor part2 are assumed converged initially
213 : !None of the channel widths are assumed converged initially
214 :
215 29 : part1=.false.
216 29 : part2=.false.
217 :
218 29 : wgcnv(:)=.false.
219 29 : wgijcnv(:)=.false.
220 :
221 : !Thermodynamic quantities are put to zero.
222 : !(If exactly zero, initial convergence tests will fail.)
223 :
224 44 : free0(:)=1.d-05
225 44 : energy0(:)=1.d-05
226 44 : entropy0(:)=1.d-05
227 44 : spheat0(:)=1.d-05
228 1584 : bij(:,:,:)=1.d-05
229 1584 : vij(:,:,:)=1.d-05
230 :
231 : !Number of actual channels set
232 29 : do iwchan=1,nwchan
233 29 : nchan2(iwchan)=(nchan-1)/iwchan+1
234 : end do
235 :
236 : !For different types of Bravais lattices
237 4 : facbrv=1
238 4 : if(anaddb_dtset%brav==2)facbrv=2
239 4 : if(anaddb_dtset%brav==3)facbrv=4
240 :
241 : !Loops on the q point grids
242 16 : do igrid=1,ngrids
243 :
244 56 : igqpt2(:)=max((anaddb_dtset%ng2qpt(:)*igrid)/ngrids, 1)
245 14 : mqpt2=(igqpt2(1)*igqpt2(2)*igqpt2(3))/facbrv
246 42 : ABI_MALLOC(qpt2,(3,mqpt2))
247 28 : ABI_MALLOC(spqpt2,(3,mqpt2))
248 :
249 14 : option=1
250 14 : qptrlatt(:,:)=0
251 14 : qptrlatt(1,1)=igqpt2(1)
252 14 : qptrlatt(2,2)=igqpt2(2)
253 14 : qptrlatt(3,3)=igqpt2(3)
254 14 : call smpbz(anaddb_dtset%brav,iout,qptrlatt,mqpt2,nspqpt,1,option,anaddb_dtset%q2shft,spqpt2)
255 :
256 42 : ABI_MALLOC(indqpt1,(nspqpt))
257 42 : ABI_MALLOC(wtq,(nspqpt))
258 28 : ABI_MALLOC(wtq_folded,(nspqpt))
259 42 : ABI_MALLOC(bz2ibz_smap,(6, nspqpt))
260 :
261 : ! Reduce the number of such points by symmetrization
262 31918 : wtq(:)=1.0_dp
263 :
264 14 : timrev=1
265 : call symkpt(0,Crystal%gmet,indqpt1,ab_out,spqpt2,nspqpt,nqpt2,Crystal%nsym,symrec,timrev,wtq,wtq_folded, &
266 14 : bz2ibz_smap, xmpi_comm_self)
267 :
268 14 : ABI_FREE(bz2ibz_smap)
269 :
270 42 : ABI_MALLOC(wtq2,(nqpt2))
271 1760 : do iqpt2=1,nqpt2
272 1746 : wtq2(iqpt2)=wtq_folded(indqpt1(iqpt2))
273 6998 : qpt2(:,iqpt2)=spqpt2(:,indqpt1(iqpt2))
274 : !write(std_out,*)' harmonic_thermo : iqpt2, wtq2 :',iqpt2,wtq2(iqpt2)
275 : end do
276 14 : ABI_FREE(wtq_folded)
277 :
278 : ! Temporary counters are put zero.
279 :
280 192609 : gg(:,:)=zero
281 2668859 : ggij(:,:,:,:)=zero
282 96359 : gw(:,:)=zero
283 :
284 : ! Sum over the sampled q points
285 1760 : do iqpt2=1,nqpt2
286 :
287 6984 : qphon(:)=qpt2(:,iqpt2)
288 1746 : qphnrm=1.0_dp
289 :
290 : ! Fourier Interpolation
291 1746 : call ifc%fourq(Crystal,qphon,phfrq,displ,out_eigvec=eigvec)
292 :
293 1746 : if (present(thmflag)) then
294 0 : if (thmflag ==2)then
295 0 : call sortph(eigvec,displ,outfilename_radix,natom,phfrq)
296 : end if
297 : end if
298 :
299 : ! Sum over the phonon modes
300 33782 : do iii=1,3*natom
301 :
302 : ! Slightly negative frequencies are put to zero
303 : ! Imaginary frequencies are also put to zero
304 32022 : if(phfrq(iii)<0._dp) phfrq(iii)=0._dp
305 :
306 : ! Note: frequencies are now in cm-1
307 :
308 : ! Sort frequencies into channels of frequencies for each channel width of frequency
309 198432 : do iwchan=nwchan,1,-1
310 198432 : if (.not.wgcnv(iwchan))then
311 164874 : dosinc=dble(iwchan)
312 164874 : ichan=int(phfrq(iii)*Ha_cmm1/dosinc)+1
313 :
314 164874 : if(ichan>nchan2(iwchan)) then
315 : write(msg, '(a,es16.6,a,a,a,i7,a,a,a)' )&
316 0 : & 'There is a phonon frequency,',phfrq(iii),' larger than the maximum one,',ch10,&
317 0 : & 'as defined by the number of channels of width 1 cm-1, nchan=',nchan,'.',ch10,&
318 0 : & 'Action: increase nchan (suggestion : double it).'
319 0 : ABI_ERROR(msg)
320 : end if
321 :
322 164874 : gg(ichan,iwchan)=gg(ichan,iwchan)+wtq2(iqpt2)
323 :
324 164874 : gw(ichan,iwchan)=gw(ichan,iwchan)+wtq2(iqpt2)*phfrq(iii)*Ha_cmm1
325 :
326 : ! to calculate two phonon DOS for qshift = 0.0
327 4062828 : do iiii=1,3*natom
328 3897954 : if(phfrq(iiii)<0.d0) phfrq(iiii)=0.d0
329 :
330 3897954 : ichan=int(abs(phfrq(iii)+phfrq(iiii))*Ha_cmm1/dosinc)+1
331 3897954 : gg_sum(ichan,iwchan)=gg_sum(ichan,iwchan)+wtq2(iqpt2)
332 :
333 3897954 : ichan=int(abs(phfrq(iii)-phfrq(iiii))*Ha_cmm1/dosinc)+1
334 4062828 : gg_rest(ichan,iwchan)=gg_rest(ichan,iwchan)+wtq2(iqpt2)
335 : end do ! end loop for iiii
336 :
337 : end if
338 : end do
339 :
340 200178 : do iwchan=nwchan,1,-1
341 198432 : if (.not.wgijcnv(iwchan))then
342 :
343 105660 : dosinc=dble(iwchan)
344 105660 : ichan=int(phfrq(iii)*Ha_cmm1/dosinc)+1
345 :
346 105660 : if(ichan>nchan2(iwchan)) then
347 : write(msg, '(a,a,a,a,a)' )&
348 0 : & 'Phonon frequencies larger than the maximum one,',ch10,&
349 0 : & 'as defined by the number of channels of width 1 cm-1.',ch10,&
350 0 : & 'Action: increase nchan (suggestion : double it).'
351 0 : ABI_ERROR(msg)
352 : end if
353 :
354 1054080 : do iatom=1,natom
355 6744600 : do ij=1,6
356 : ggij(ij,iatom,ichan,iwchan)=ggij(ij,iatom,ichan,iwchan)&
357 : & +wtq2(iqpt2)*&
358 : & (eigvec(1,ii(ij),iatom,iii)*eigvec(1,jj(ij),iatom,iii)+&
359 6638940 : & eigvec(2,ii(ij),iatom,iii)*eigvec(2,jj(ij),iatom,iii) )
360 : end do
361 : end do
362 :
363 : end if
364 : end do
365 :
366 : end do ! End of the sum over the phonon modes
367 : end do ! End of the sum over q-points in the irreducible zone
368 :
369 : ! deallocate sortph array
370 14 : call end_sortph()
371 :
372 : ! Symmetrize the gij
373 15264 : do ichan=1,nchan
374 111514 : do iwchan=nwchan,1,-1
375 463750 : do iatom=1,natom
376 2668750 : do ij=1,6
377 : ! Uses bbij as work space
378 2205000 : bbij(ij,iatom,1)=ggij(ij,iatom,ichan,iwchan)
379 2572500 : ggij(ij,iatom,ichan,iwchan)=0.0_dp
380 : end do
381 : end do
382 479000 : do iatom=1,natom
383 5137500 : do isym=1,Crystal%nsym
384 : ! Find the atom that will be applied on atom iatom
385 4770000 : ind=Crystal%indsym(4,isym,iatom)
386 33390000 : do ij=1,6
387 33390000 : tens1(ii(ij),jj(ij))=bbij(ij,ind,1)
388 : end do
389 : ! complete the 3x3 tensor from the upper triangle
390 4770000 : tens1(2,1)=tens1(1,2)
391 4770000 : tens1(3,1)=tens1(1,3)
392 4770000 : tens1(3,2)=tens1(2,3)
393 : ! Here acomplishes the tensorial operations
394 : !! make this a BLAS call, or better yet batch the whole thing?
395 : ! 2) Apply the symmetry operation on both indices USING symrec in
396 : ! cartesian coordinates
397 19080000 : do iii=1,3
398 62010000 : do jjj=1,3
399 : tens2(iii,jjj)=tens1(iii,1)*symrec_cart(1,jjj,isym)&
400 : & +tens1(iii,2)*symrec_cart(2,jjj,isym)&
401 57240000 : & +tens1(iii,3)*symrec_cart(3,jjj,isym)
402 : end do
403 : end do
404 19080000 : do jjj=1,3
405 62010000 : do iii=1,3
406 : tens1(iii,jjj)=tens2(1,jjj)*symrec_cart(1,iii,isym)&
407 : & +tens2(2,jjj)*symrec_cart(2,iii,isym)&
408 57240000 : & +tens2(3,jjj)*symrec_cart(3,iii,isym)
409 : end do
410 : end do
411 : ! net result is tens1 = rprimd symrec^T gprimd^T tens1 gprimd symrec rprimd^T
412 :
413 : ! This accumulates over atoms, to account for all symmetric ones
414 33757500 : do ij=1,6
415 33390000 : ggij(ij,iatom,ichan,iwchan)=ggij(ij,iatom,ichan,iwchan) + tens1(ii(ij),jj(ij))
416 : end do
417 :
418 : end do
419 : ! Each one will be replicated nsym times in the end:
420 2668750 : do ij=1,6
421 2572500 : ggij(ij,iatom,ichan,iwchan)=ggij(ij,iatom,ichan,iwchan)/dble(Crystal%nsym)
422 : end do
423 : end do
424 : end do
425 : end do
426 :
427 14 : call wrtout(std_out,' harmonic_thermo: g(w) and gij(k|w) calculated given a q sampling grid.','COLL')
428 :
429 : ! Sum up the counts in the channels to check the normalization
430 : ! and test convergence with respect to q sampling
431 14 : gnorm=(igqpt2(1)*igqpt2(2)*igqpt2(3)*3*natom)/facbrv
432 :
433 14 : if(.not.part1)then
434 87 : do iwchan=nwchan,1,-1
435 :
436 : !write(msg,'(a,i0)' )' harmonic_thermo : iwchan=',iwchan
437 : !call wrtout(std_out,msg,'COLL')
438 :
439 77 : if (wgcnv(iwchan)) cycle
440 : !call wrtout(std_out,' harmonic_thermo : compute g, f, e, s, c','COLL')
441 :
442 : ! Calculate g(w) and F,E,S,C
443 :
444 76 : ggsum=0.0_dp
445 76 : ggsumsum=0.0_dp
446 76 : ggrestsum=0.0_dp
447 27881 : do ichan=1,nchan2(iwchan)
448 27805 : ggsum=ggsum+gg(ichan,iwchan)
449 27805 : ggsumsum=ggsumsum+gg_sum(ichan,iwchan)
450 27881 : ggrestsum=ggrestsum+gg_rest(ichan,iwchan)
451 : end do
452 :
453 76 : if(ggsum/=gnorm)then
454 : write(msg, '(a,es14.6,i6,a,a,es14.6,a)' )&
455 0 : & 'Frequencies are missing in g(w) : ggsum,iwchan=',ggsum,iwchan,ch10,&
456 0 : & 'gnorm=',gnorm,'.'
457 0 : ABI_BUG(msg)
458 : end if
459 :
460 : ! Check if the density of states changed by more than dostol
461 :
462 76 : gerr=zero
463 76 : if (ngrids>1) then
464 27630 : do ichan=1,nchan2(iwchan)
465 27630 : gerr=gerr+abs(gg(ichan,iwchan)/ggsum-gdos(ichan,iwchan))
466 : end do
467 : end if
468 :
469 76 : if(gerr>anaddb_dtset%dostol.and.ngrids>1) then
470 69 : wgcnv(iwchan)=.false.
471 : else
472 7 : wgcnv(iwchan)=.true.
473 : end if
474 :
475 : ! g(w) is updated
476 27881 : do ichan=1,nchan2(iwchan)
477 27805 : gdos(ichan,iwchan)=gg(ichan,iwchan)/ggsum
478 27805 : gg_sum(ichan,iwchan)=gg_sum(ichan,iwchan)/ggsumsum
479 27881 : gg_rest(ichan,iwchan)=gg_rest(ichan,iwchan)/ggrestsum
480 : end do
481 27881 : do ichan=1,nchan2(iwchan)
482 27881 : gw(ichan,iwchan)=gw(ichan,iwchan)/ggsum
483 : end do
484 :
485 : ! Write gerr for each q sampling and w width
486 76 : write(msg,'(a,a,i3,3i6,f10.1,f10.5)') ch10, &
487 152 : & 'harmonic_thermo: iwchan,igqpt(:),norm,error=',iwchan,igqpt2(1),igqpt2(2),igqpt2(3),ggsum+tol8,gerr+tol10
488 76 : call wrtout(std_out,msg,'COLL')
489 :
490 : ! If the DOS with a channel width is newly converged,
491 : ! print it out and calculate the thermodynamic functions.
492 76 : convth=0
493 76 : if(wgcnv(iwchan)) then
494 7 : if (ngrids==1) then
495 1 : if (anaddb_dtset%dossum /= 0 ) then
496 0 : write(msg,'(a65,i5,a16)') ' DOS, SUM AND DIFFERENCE OF TWO PHONON DOS with channel width= ',iwchan,':'
497 : else
498 1 : write(msg,'(a25,i5,a16)') ' DOS with channel width= ',iwchan,':'
499 : end if
500 : else
501 6 : if (anaddb_dtset%dossum /= 0 ) then
502 : write(msg,'(a65,i5,a16)')&
503 2 : & ' DOS, SUM AND DIFFERENCE OF TWO PHONON DOS with channel width= ',iwchan,' newly converged'
504 : else
505 4 : write(msg,'(a25,i5,a16)') ' DOS with channel width= ',iwchan,' newly converged'
506 : end if
507 : end if
508 :
509 7 : call wrtout(std_out,msg,'COLL')
510 7 : call wrtout(iout,msg,'COLL')
511 1552 : do ichan=1,nchan2(iwchan)
512 1545 : if (anaddb_dtset%dossum /= 0 ) then
513 563 : write(msg,'(i8,f11.1,3(f12.5,3x))') ichan,gg(ichan,iwchan)+tol10,&
514 563 : & gdos(ichan,iwchan)+tol10, gg_sum(ichan,iwchan)*(3.0*natom*3.0*natom)+tol10, &
515 1126 : & gg_rest(ichan,iwchan)*(3.0*natom*(3.0*natom-1))+tol10
516 : else
517 982 : write(msg,'(i8,f11.1,1x,f12.5)') ichan,gg(ichan,iwchan)+tol10,&
518 1964 : & gdos(ichan,iwchan)+tol10
519 : end if
520 1552 : call wrtout(std_out,msg,'COLL')
521 : end do
522 :
523 7 : if (ngrids>1) then
524 6 : write(msg,'(a24,f10.5)')' with maximal error = ',gerr+tol10
525 6 : call wrtout(std_out,msg,'COLL')
526 6 : call wrtout(iout,msg,'COLL')
527 : end if
528 :
529 7 : nomega = nchan2(iwchan)
530 7 : dosinc=dble(iwchan)
531 :
532 21 : ABI_MALLOC(phon_dos,(nomega))
533 1559 : phon_dos = gdos(1:nomega,iwchan)
534 :
535 : !Put zeroes for F, E, S, Cv
536 77 : free(:)=zero
537 77 : energy(:)=zero
538 77 : entropy(:)=zero
539 77 : spheat(:)=zero
540 77 : wme(:)=zero
541 :
542 77 : do itemper=1,ntemper
543 :
544 70 : tmp=anaddb_dtset%tempermin+anaddb_dtset%temperinc*dble(itemper-1)
545 : ! The temperature (tmp) is given in Kelvin
546 70 : if (tmp < tol6) cycle
547 :
548 15520 : do iomega=1,nomega
549 :
550 : ! wovert= hbar*w / 2kT dimensionless
551 15450 : wovert=dosinc*(dble(iomega)-0.5_dp)/Ha_cmm1/(2._dp*kb_HaK*tmp)
552 15450 : expm2x=exp(-2.0_dp*wovert)
553 15450 : ln2shx=wovert+log(1.0_dp-expm2x)
554 15450 : cothx=(1.0_dp+expm2x)/(1.0_dp-expm2x)
555 15450 : factor=dble(3*natom)*phon_dos(iomega)
556 15450 : factorw=3*natom*gw(iomega,iwchan)
557 :
558 : ! This matches the equations published in Lee & Gonze, PRB 51, 8610 (1995) [[cite:Lee1995]]
559 15450 : free(itemper)=free(itemper) +factor*kb_HaK*tmp*ln2shx
560 15450 : energy(itemper)=energy(itemper) + factor*kb_HaK*tmp*wovert*cothx
561 15450 : entropy(itemper)=entropy(itemper) + factor*kb_HaK*(wovert*cothx - ln2shx)
562 :
563 : ! The contribution is much lower than 1.0d-16 when wovert<100.0_dp
564 15450 : if(wovert<100.0_dp)then
565 15450 : spheat(itemper)=spheat(itemper)+factor*kb_HaK*wovert**2/sinh(wovert)**2
566 : end if
567 15520 : wme(itemper)=wme(itemper)+factorw*kb_HaK*wovert**2/sinh(wovert)**2
568 :
569 : end do ! iomega
570 :
571 77 : if (abs(spheat(itemper))>tol8) wme(itemper)=wme(itemper)/spheat(itemper)
572 : end do ! itemper
573 7 : ABI_FREE(phon_dos)
574 :
575 : ! Check if the thermodynamic functions change within tolerance,
576 7 : if (ngrids>1) then
577 : write(msg,'(a,a,a)')&
578 6 : & ' harmonic_thermo : check if the thermodynamic functions',ch10,&
579 12 : & ' change within tolerance.'
580 6 : call wrtout(std_out,msg,'COLL')
581 6 : convth=1
582 :
583 36 : do itemper=1,ntemper
584 33 : change=free(itemper)-free0(itemper)
585 33 : relchg=change/free0(itemper)
586 33 : if(change>1d-14*dble(mqpt2) .and. relchg>thmtol)then
587 : write(msg,'(a,es14.4,a,a,es14.4)' )&
588 3 : & ' harmonic_thermo : free energy relative changes ',relchg,ch10,&
589 6 : & ' are larger than thmtol ',thmtol
590 3 : call wrtout(std_out,msg,'COLL')
591 3 : convth=0
592 : end if
593 33 : change=energy(itemper)-energy0(itemper)
594 33 : relchg=change/energy0(itemper)
595 33 : if(change>1d-14*dble(mqpt2) .and. relchg>thmtol)then
596 : write(msg,'(a,es14.4,a,a,es14.4)' )&
597 3 : & ' harmonic_thermo : energy relative changes ',relchg,ch10,&
598 6 : & ' are larger than thmtol ',thmtol
599 3 : call wrtout(std_out,msg,'COLL')
600 3 : convth=0
601 : end if
602 33 : change=entropy(itemper)-entropy0(itemper)
603 33 : relchg=change/entropy0(itemper)
604 33 : if(change>1d-14*dble(mqpt2) .and. relchg>thmtol)then
605 : write(msg,'(a,es14.4,a,a,es14.4)' )&
606 1 : & ' harmonic_thermo : entropy relative changes ',relchg,ch10,&
607 2 : & ' are larger than thmtol ',thmtol
608 1 : call wrtout(std_out,msg,'COLL')
609 1 : convth=0
610 : end if
611 33 : change=spheat(itemper)-spheat0(itemper)
612 33 : relchg=change/spheat0(itemper)
613 33 : if(change>1d-14*dble(mqpt2) .and. relchg>thmtol)then
614 : write(msg,'(a,es14.4,a,a,es14.4)' )&
615 1 : & ' harmonic_thermo : specific heat relative changes ',relchg,ch10,&
616 2 : & ' are larger than thmtol ',thmtol
617 1 : call wrtout(std_out,msg,'COLL')
618 : convth=0
619 : end if
620 :
621 35 : if(convth==0)exit
622 : end do ! End of check if the thermodynamic functions change within tolerance
623 :
624 : else
625 : convth=1
626 : end if
627 :
628 : ! Update F,E,S,C and eventually write them if converged
629 6 : if(convth==1)then
630 4 : part1=.true.
631 4 : write(msg,'(a,a,a)') ch10,&
632 8 : & ' # At T F(J/mol-c) E(J/mol-c) S(J/(mol-c.K)) C(J/(mol-c.K)) Omega_mean(cm-1)'
633 4 : call wrtout(iout,msg,'COLL')
634 4 : call wrtout(thermal_unit,msg,'COLL')
635 4 : msg = ' # (A mol-c is the abbreviation of a mole-cell, that is, the'
636 4 : call wrtout(iout,msg,'COLL')
637 4 : call wrtout(thermal_unit,msg,'COLL')
638 4 : msg = ' # number of Avogadro times the atoms in a unit cell)'
639 4 : call wrtout(iout,msg,'COLL')
640 4 : call wrtout(thermal_unit,msg,'COLL')
641 :
642 : write(msg, '(a,a,a)' )&
643 4 : & ' harmonic_thermo : thermodynamic functions have converged',ch10,&
644 8 : & ' see main output file ...'
645 4 : call wrtout(std_out,msg,'COLL')
646 : end if
647 :
648 77 : do itemper=1,ntemper
649 70 : free0(itemper)=free(itemper)
650 70 : energy0(itemper)=energy(itemper)
651 70 : entropy0(itemper)=entropy(itemper)
652 70 : spheat0(itemper)=spheat(itemper)
653 :
654 77 : if(convth==1)then
655 40 : tmp=anaddb_dtset%tempermin+anaddb_dtset%temperinc*dble(itemper-1)
656 40 : write(msg,'(es11.3,5es15.7)') tmp+tol8,&
657 40 : & Ha_eV*e_Cb*Avogadro*free(itemper),&
658 40 : & Ha_eV*e_Cb*Avogadro*energy(itemper),&
659 40 : & Ha_eV*e_Cb*Avogadro*entropy(itemper),&
660 40 : & Ha_eV*e_Cb*Avogadro*spheat(itemper),&
661 80 : & wme(itemper)
662 40 : call wrtout(iout,msg,'COLL')
663 40 : call wrtout(thermal_unit,msg,'COLL')
664 : end if
665 : end do
666 : end if
667 :
668 17 : if(convth==1)exit
669 : end do
670 : end if
671 :
672 14 : if(.not.part2)then
673 : ! Atomic temperature factor calculation
674 65 : do iwchan=nwchan,1,-1
675 55 : if (wgijcnv(iwchan))cycle
676 :
677 : ! Calculate gij(k|w) and Bij(k)
678 : ! Check if the density of states changed by more than dostol
679 25 : gijsum =zero
680 25 : wgijcnv(iwchan)=.true.
681 25 : if (ngrids>1) then
682 95 : do iatom=1,natom
683 545 : do ij=1,6
684 450 : gijerr=zero
685 217020 : do ichan=1,nchan2(iwchan)
686 216570 : gijsum = gijsum + gij(ij,iatom,ichan,iwchan)
687 : gijerr=gijerr&
688 : & +abs(ggij(ij,iatom,ichan,iwchan)/gnorm&
689 217020 : & - gij(ij,iatom,ichan,iwchan))
690 : end do
691 525 : if(gijerr>anaddb_dtset%dostol) then
692 0 : wgijcnv(iwchan)=.false.
693 0 : exit
694 : end if
695 : end do
696 : end do
697 : else
698 : gijerr=0.d0
699 : end if
700 :
701 : ! gij(k|w) is updated
702 :
703 10935 : do ichan=1,nchan2(iwchan)
704 72725 : do iatom=1,natom
705 443440 : do ij=1,6
706 432530 : gij(ij,iatom,ichan,iwchan)=ggij(ij,iatom,ichan,iwchan)/(gnorm/(3*natom))
707 : end do
708 : !if (iwchan==1) write (200+iatom,'(I6,6(E20.10,2x))') ichan, gij(1:6,iatom,ichan,iwchan)
709 : end do
710 : end do
711 :
712 : ! Write gijerr for each q sampling and w width
713 :
714 25 : write(msg,'(a,a,i3,3i6,f10.5,f10.5)') ch10,&
715 25 : & ' iwchan,igqpt(i),gijsum, gij error= ',&
716 50 : & iwchan,igqpt2(1),igqpt2(2),igqpt2(3),gijsum,gijerr+tol10
717 25 : call wrtout(std_out,msg,'COLL')
718 :
719 : ! If the generalized DOS with a channel width is newly converged,
720 : ! print it out and calculate Bij(k).
721 35 : if(wgijcnv(iwchan)) then
722 :
723 25 : if (ngrids==1) then
724 5 : write(msg,'(a,i5,a)') ' gij with channel width= ',iwchan,':'
725 : else
726 20 : write(msg,'(a,i5,a)') ' gij with channel width= ',iwchan,' newly converged'
727 : end if
728 25 : call wrtout(iout,msg,'COLL')
729 :
730 25 : write(msg,'(a,2i3,3i6,f10.5)')'iatom,iwchan,igqpt2(i),gij error= ',&
731 50 : & iatom,iwchan,igqpt2(1),igqpt2(2),igqpt2(3),gijerr+tol10
732 25 : call wrtout(iout,msg,'COLL')
733 :
734 275 : do itemper=1,ntemper
735 :
736 : ! Put zeroes for Bij(k)
737 1450 : do iatom=1,natom
738 8650 : do ij=1,6
739 7200 : bbij(ij,iatom,itemper)=0._dp
740 8400 : vij(ij,iatom,itemper)=0._dp
741 : end do
742 : end do
743 :
744 250 : tmp=anaddb_dtset%tempermin+anaddb_dtset%temperinc*dble(itemper-1)
745 : ! tmp in K
746 250 : if (tmp < tol6) cycle
747 :
748 250 : dosinc=dble(iwchan)
749 : !
750 109375 : do ichan=1,nchan2(iwchan)
751 : !
752 : !$wovert= \hbar*w / 2kT$, dimensionless
753 109100 : wovert=dosinc*(dble(ichan)-half)/Ha_cmm1/(two*kb_HaK*tmp)
754 109100 : expm2x=exp(-two*wovert)
755 727250 : do iatom=1,natom
756 : ! factor contains 1 / (2 omega)
757 : factor=Ha_cmm1/(two*dosinc*(dble(ichan)-half)) &
758 617900 : & *(one+expm2x)/(one-expm2x) /amu(Crystal%typat(iatom))/amu_emass
759 :
760 : ! this becomes * 0.5 * omega for the velocities
761 : factorv=(half*dosinc*(dble(ichan)-half)/Ha_cmm1) &
762 617900 : & *(one+expm2x)/(one-expm2x) /amu(Crystal%typat(iatom))/amu_emass
763 :
764 4434400 : do ij=1,6
765 3707400 : bbij(ij,iatom,itemper)=bbij(ij,iatom,itemper) + factor*gij(ij,iatom,ichan,iwchan)
766 4325300 : vij(ij,iatom,itemper)=vij(ij,iatom,itemper) + factorv*gij(ij,iatom,ichan,iwchan)
767 : end do
768 : end do
769 :
770 : end do
771 :
772 : end do
773 :
774 : ! B matrix is now in atomic unit in the Cartesian coordinates.
775 : ! Check if Bij(k) changed within tolerance.
776 25 : convth=1
777 25 : if (ngrids>1) then
778 112 : do itemper=1,ntemper
779 309 : do iatom=1,natom
780 1467 : do ij=1,6
781 1261 : diffbb=bbij(ij,iatom,itemper)-bij(ij,iatom,itemper)
782 : !if (diffbb > 1d-10 .and. diffbb/bij(ij,iatom,itemper) > thmtol) then
783 : ! write(msg,'(a)' )' harmonic_thermo : Bij changes are larger than thmtol '
784 : ! call wrtout(std_out,msg,'COLL')
785 : ! convth=0
786 : !end if
787 1261 : if (diffbb > 1d-10) then
788 409 : if (bij(ij,iatom,itemper) /= zero) then
789 409 : if (diffbb/bij(ij,iatom,itemper) > thmtol) then
790 11 : write(msg,'(a)' )' harmonic_thermo : Bij changes are larger than thmtol '
791 11 : call wrtout(std_out,msg,'COLL')
792 : convth=0
793 : end if
794 : end if
795 : end if
796 206 : if(convth==0)exit
797 : end do
798 309 : if(convth==0)exit
799 : end do
800 112 : if(convth==0)exit
801 : end do
802 : end if
803 :
804 8700 : bij=bbij ! save for next iteration
805 :
806 : !Update Bij(k) and write them. B matrix printed in angstrom^2
807 : !TODO : get rid of this version in the log and output file. Prefer
808 : !external files
809 25 : if (convth==1) then
810 : write(msg, '(a,a,a)' )&
811 14 : & ' B matrix elements as a function of T',ch10,&
812 28 : & ' Angstrom^2, cartesian coordinates'
813 14 : call wrtout(std_out,msg,'COLL')
814 14 : call wrtout(iout,msg,'COLL')
815 :
816 154 : do itemper=1,ntemper
817 : ! tmp in K
818 140 : tmp=anaddb_dtset%tempermin+anaddb_dtset%temperinc*dble(itemper-1)
819 784 : do iatom=1,natom
820 : write(iout,'(2i3,es11.3,6es12.4)')&
821 630 : & iwchan,iatom,tmp+tol10,&
822 630 : & Bohr_Ang**2*bij(1,iatom,itemper)+tol10,&
823 630 : & Bohr_Ang**2*bij(2,iatom,itemper)+tol10,&
824 630 : & Bohr_Ang**2*bij(3,iatom,itemper)+tol10,&
825 630 : & Bohr_Ang**2*bij(4,iatom,itemper)+tol10,&
826 630 : & Bohr_Ang**2*bij(5,iatom,itemper)+tol10,&
827 1400 : & Bohr_Ang**2*bij(6,iatom,itemper)+tol10
828 : end do ! end loop over natom
829 : end do ! end loop over ntemper
830 :
831 : ! Mean square velocity matrix printed in angstrom^2/picosec^2
832 : write(msg, '(a,a,a)' )&
833 14 : & ' <vel^2> matrix elements as a function of T',ch10,&
834 28 : & ' Angstrom^2/(picosec)^2, cartesian coordinates'
835 14 : call wrtout(std_out,msg,'COLL')
836 14 : call wrtout(iout,msg,'COLL')
837 :
838 154 : do itemper=1,ntemper
839 : ! tmp in K
840 140 : tmp=anaddb_dtset%tempermin+anaddb_dtset%temperinc*float(itemper-1)
841 784 : do iatom=1,natom
842 4410 : vij(:,iatom,itemper)=Bohr_Ang**2*vij(:,iatom,itemper)/(Time_Sec*1.0e12)**2
843 : ! The following check zeros out <v^2> if it is very small, in order to
844 : ! avoid numerical noise being interpreted by the automatic tests as
845 : ! something real. Note also that we compare it in
846 : ! absolute value, that's because if any of the phonon frequencies are
847 : ! computed as negative, <v^2> can take a negative value.
848 4410 : do icomp=1, 6
849 4410 : if (abs(vij(icomp,iatom,itemper)) < 1.0e-12) vij(icomp,iatom,itemper)=zero
850 : end do
851 : write(iout,'(2i3,es11.3,6es12.4)')&
852 630 : & iwchan,iatom,tmp+tol10,&
853 630 : & vij(1,iatom,itemper),&
854 630 : & vij(2,iatom,itemper),&
855 630 : & vij(3,iatom,itemper),&
856 630 : & vij(4,iatom,itemper),&
857 630 : & vij(5,iatom,itemper),&
858 1400 : & vij(6,iatom,itemper)
859 : end do ! end loop over natom
860 : end do ! end loop over ntemper
861 : end if ! end check on convergence
862 :
863 :
864 : ! keep this one !!!!!!!!!!!!!!!!!!
865 : if (convth==1) then
866 : write(msg, '(a,a,a)' )&
867 14 : & '# B matrix elements as a function of T, for each atom, and smallest omega channel width',ch10,&
868 28 : & '# Angstrom^2, cartesian coordinates'
869 14 : call wrtout(bij_unit,msg,'COLL')
870 77 : do iatom=1,natom
871 63 : write(msg, '(2a,i10)' ) ch10, '# for atom ', iatom
872 63 : call wrtout(bij_unit,msg,'COLL')
873 707 : do itemper=1,ntemper
874 : ! tmp in K
875 630 : tmp=anaddb_dtset%tempermin+anaddb_dtset%temperinc*dble(itemper-1)
876 : write(msg,'(es11.3,6es12.4)')&
877 630 : & tmp,&
878 630 : & Bohr_Ang**2*bij(1,iatom,itemper),&
879 630 : & Bohr_Ang**2*bij(2,iatom,itemper),&
880 630 : & Bohr_Ang**2*bij(3,iatom,itemper),&
881 630 : & Bohr_Ang**2*bij(4,iatom,itemper),&
882 630 : & Bohr_Ang**2*bij(5,iatom,itemper),&
883 1260 : & Bohr_Ang**2*bij(6,iatom,itemper)
884 693 : call wrtout(bij_unit,msg,'COLL')
885 : end do ! end loop over ntemper
886 : end do ! end loop over natom
887 :
888 : ! Mean square velocity matrix printed in angstrom^2/picosec^2
889 : write(msg, '(a,a,a)' )&
890 14 : & '# <vel^2> matrix elements as a function of T, for each atom, and smallest channel width',ch10,&
891 28 : & '# Angstrom^2/(picosec)^2, cartesian coordinates'
892 14 : call wrtout(vij_unit,msg,'COLL')
893 :
894 77 : do iatom=1,natom
895 63 : write(msg, '(2a,i10)' ) ch10, '# for atom ', iatom
896 63 : call wrtout(vij_unit,msg,'COLL')
897 707 : do itemper=1,ntemper
898 : ! tmp in K
899 630 : tmp=anaddb_dtset%tempermin+anaddb_dtset%temperinc*float(itemper-1)
900 4410 : vij(:,iatom,itemper)=Bohr_Ang**2*vij(:,iatom,itemper)/(Time_Sec*1.0e12)**2
901 :
902 : ! The following check zeros out <v^2> if it is very small, in order to
903 : ! avoid numerical noise being interpreted by the automatic tests as
904 : ! something real. Note also that we compare it in
905 : ! absolute value, that's because if any of the phonon frequencies are
906 : ! computed as negative, <v^2> can take a negative value.
907 4410 : do icomp=1, 6
908 4410 : if (abs(vij(icomp,iatom,itemper)) < 1.0e-12) vij(icomp,iatom,itemper)=zero
909 : end do
910 : write(vij_unit,'(es11.3,6es12.4)')&
911 630 : & tmp,&
912 630 : & vij(1,iatom,itemper),&
913 630 : & vij(2,iatom,itemper),&
914 630 : & vij(3,iatom,itemper),&
915 630 : & vij(4,iatom,itemper),&
916 630 : & vij(5,iatom,itemper),&
917 1323 : & vij(6,iatom,itemper)
918 : end do ! end loop over ntemper
919 : end do ! end loop over natom
920 : end if ! end check on convergence
921 :
922 : if(convth==1)part2=.true.
923 :
924 : end if ! End of test on wgijcnv
925 : end do ! End of loop over iwchan
926 : end if ! End of part2
927 :
928 14 : if(part1.and.part2)exit
929 :
930 12 : ABI_FREE(indqpt1)
931 12 : ABI_FREE(qpt2)
932 12 : ABI_FREE(spqpt2)
933 12 : ABI_FREE(wtq)
934 16 : ABI_FREE(wtq2)
935 :
936 : end do ! End of the Loop on the q point grids
937 :
938 4 : ABI_FREE(bbij)
939 4 : ABI_FREE(bij)
940 4 : ABI_FREE(energy)
941 4 : ABI_FREE(energy0)
942 4 : ABI_FREE(entropy)
943 4 : ABI_FREE(entropy0)
944 4 : ABI_FREE(free)
945 4 : ABI_FREE(free0)
946 4 : ABI_FREE(gdos)
947 4 : ABI_FREE(gg)
948 4 : ABI_FREE(gg_sum)
949 4 : ABI_FREE(gg_rest)
950 4 : ABI_FREE(ggij)
951 4 : ABI_FREE(gij)
952 4 : ABI_FREE(nchan2)
953 4 : ABI_FREE(spheat)
954 4 : ABI_FREE(spheat0)
955 4 : ABI_FREE(vij)
956 4 : ABI_FREE(wgcnv)
957 4 : ABI_FREE(wgijcnv)
958 4 : if(allocated(indqpt1)) then
959 2 : ABI_FREE(indqpt1)
960 : end if
961 4 : if(allocated(qpt2)) then
962 2 : ABI_FREE(qpt2)
963 : end if
964 4 : if(allocated(spqpt2)) then
965 2 : ABI_FREE(spqpt2)
966 : end if
967 4 : if(allocated(wtq)) then
968 2 : ABI_FREE(wtq)
969 : end if
970 4 : if(allocated(wtq2)) then
971 2 : ABI_FREE(wtq2)
972 : end if
973 4 : ABI_FREE(gw)
974 4 : ABI_FREE(wme)
975 :
976 4 : if(.not.part1)then
977 : write(msg, '(a,a,a,a,a,a,a,a,a)' )&
978 0 : & 'No thermodynamical function is printed out :',ch10,&
979 0 : & 'the tolerance level that was asked ',ch10,&
980 0 : & 'has not been match with the grids specified.',ch10,&
981 0 : & 'Action: in the input file, increase the resolution',ch10,&
982 0 : & 'of grids ng2qpt, or decrease the accuracy requirement thmtol.'
983 0 : ABI_ERROR(msg)
984 : end if
985 :
986 4 : if(.not.part2)then
987 : write(msg,'(a,a,a,a,a,a,a,a,a)')&
988 2 : & 'No atomic factor tensor is printed out :',ch10,&
989 2 : & 'the tolerance level that was asked ',ch10,&
990 2 : & 'has not been match with the grids specified.',ch10,&
991 2 : & 'Action: in the input file, increase the resolution',ch10,&
992 4 : & 'of grids ng2qpt, or decrease the accuracy requirement thmtol.'
993 2 : ABI_WARNING(msg)
994 : end if
995 :
996 4 : close (thermal_unit)
997 4 : close (bij_unit)
998 4 : close (vij_unit)
999 :
1000 : end subroutine harmonic_thermo
1001 : !!***
1002 :
1003 : end module m_harmonic_thermo
1004 : !!***
|