Line data Source code
1 :
2 : #if defined HAVE_CONFIG_H
3 : #include "config.h"
4 : #endif
5 :
6 : #include "abi_common.h"
7 :
8 : module m_tdep_phi2
9 :
10 : use defs_basis
11 : use m_errors
12 : use m_abicore
13 : use m_xmpi
14 : use m_io_tools
15 : use m_tdep_dataset, only : atdep_dataset_type, MPI_enreg_type
16 : use m_tdep_shell, only : Shell_type
17 : use m_tdep_sym, only : Symmetries_type
18 : use m_tdep_qpt, only : Qpoints_type
19 : use m_tdep_sampling, only : tdep_Sampling_type
20 : use m_tdep_solver, only : tdep_Solver_type
21 : use m_tdep_model, only : tdep_Model_type
22 :
23 : implicit none
24 :
25 : type Eigen_type
26 :
27 : double precision, allocatable :: eigenval(:,:)
28 : double precision, allocatable :: eigenvec(:,:,:,:,:,:)
29 : double precision, allocatable :: dynmat(:,:,:,:,:,:)
30 :
31 : end type Eigen_type
32 :
33 : public :: tdep_calc_ftot2
34 : public :: tdep_calc_phi1
35 : public :: tdep_write_phi1
36 : public :: tdep_calc_phi2
37 : public :: tdep_write_phi2
38 : public :: tdep_build_phi2_33
39 : public :: tdep_calc_dij
40 : public :: tdep_write_dij
41 : public :: tdep_init_eigen2nd
42 : public :: tdep_destroy_eigen2nd
43 : public :: tdep_write_yaml
44 :
45 : contains
46 :
47 : !====================================================================================================
48 49 : subroutine tdep_calc_ftot2(Model,Invar,Phi2,ucart)
49 :
50 : type(tdep_Model_type),intent(inout) :: Model
51 : type(atdep_dataset_type),intent(in) :: Invar
52 : double precision, intent(in) :: Phi2(3*Invar%natom,3*Invar%natom)
53 : double precision, intent(in) :: ucart(3,Invar%natom,Invar%my_nstep)
54 :
55 : integer :: jj,istep,jatom
56 49 : double precision, allocatable :: ucart_blas(:)
57 49 : double precision, allocatable :: ftot2(:)
58 :
59 : ! Compute Forces of the model TDEP
60 23003 : ABI_CALLOC(ucart_blas,(3*Invar%natom))
61 22905 : ABI_CALLOC(ftot2 ,(3*Invar%natom))
62 1101 : do istep=1,Invar%my_nstep
63 460748 : ucart_blas(:)=0.d0
64 460748 : ftot2 (:)=0.d0
65 154284 : do jatom=1,Invar%natom
66 613980 : do jj=1,3
67 612928 : ucart_blas(3*(jatom-1)+jj)=ucart(jj,jatom,istep)
68 : end do
69 : end do
70 460748 : Model%Phi1Ui(istep)=sum(Model%Phi1(:)*ucart_blas(:))
71 1052 : call DGEMM('N','N',3*Invar%natom,1,3*Invar%natom,1.d0,Phi2,3*Invar%natom,ucart_blas,3*Invar%natom,0.d0,ftot2(:),3*Invar%natom)
72 1052 : call DGEMM('T','N',1,1,3*Invar%natom,1./2.d0,ftot2,3*Invar%natom,ucart_blas,3*Invar%natom,0.d0,Model%Phi2UiUj(istep),3*Invar%natom)
73 460797 : Model%Forces(3*Invar%natom*(istep-1)+1:3*Invar%natom*istep)=-Model%Phi1(:)-ftot2(:)
74 : end do !istep
75 49 : ABI_FREE(ucart_blas)
76 49 : ABI_FREE(ftot2)
77 :
78 49 : end subroutine tdep_calc_ftot2
79 :
80 : !=====================================================================================================
81 43 : subroutine tdep_calc_phi1(Solver,Shell1at,Sym,Phi1)
82 :
83 : type(tdep_Solver_type),intent(in) :: Solver
84 : type(Shell_type),intent(in) :: Shell1at
85 : type(Symmetries_type),intent(in) :: Sym
86 : double precision,intent(out) :: Phi1(3*Solver%natom)
87 :
88 : integer :: ishell,isym,iatom,ncoeff,ncoeff_prev
89 : integer :: nshell,ii,iatshell,iat_mod
90 43 : double precision,allocatable :: Phi1_coeff(:)
91 43 : double precision,allocatable :: Phi1_3(:),Phi1_ref(:,:)
92 :
93 43 : nshell=Shell1at%nshell
94 129 : ABI_MALLOC(Phi1_coeff,(Solver%ncoeff1st))
95 43 : Phi1_coeff(:) = Solver%theta(1:Solver%ncoeff1st)
96 377 : ABI_MALLOC(Phi1_ref,(3,nshell)); Phi1_ref(:,:)=zero
97 215 : ABI_MALLOC(Phi1_3,(3)) ; Phi1_3(:)=0.d0
98 105 : do ishell=1,nshell
99 : ! Build the 3x3 IFC per shell
100 62 : ncoeff =Shell1at%ncoeff(ishell)
101 62 : ncoeff_prev=Shell1at%ncoeff_prev(ishell)
102 248 : do ii=1,3
103 248 : Phi1_ref(ii,ishell)=sum(Shell1at%proj(ii,1:ncoeff,ishell)*Phi1_coeff(ncoeff_prev+1:ncoeff_prev+ncoeff))
104 : end do
105 : ! Build the vector-IFC of an atom in this shell
106 62 : if (Shell1at%neighbours(1,ishell)%n_interactions.eq.0) cycle
107 43 : do iatshell=1,Shell1at%neighbours(1,ishell)%n_interactions
108 0 : iatom=Shell1at%neighbours(1,ishell)%atomj_in_shell(iatshell)
109 0 : isym =Shell1at%neighbours(1,ishell)%sym_in_shell(iatshell)
110 0 : do ii=1,3
111 0 : Phi1_3(ii)=sum(Sym%S_ref(ii,:,isym,1)*Phi1_ref(:,ishell))
112 : end do
113 62 : Phi1((iatom-1)*3+1:(iatom-1)*3+3)=Phi1_3(:)
114 : end do !iatshell
115 : end do !ishell
116 : ! Acoustic sum rule
117 172 : do ii=1,3
118 19282 : do iatom=1,Solver%natom
119 19110 : iat_mod=mod(iatom+Solver%natom_unitcell-1,Solver%natom_unitcell)+1
120 19110 : if (iat_mod==1) cycle
121 19239 : Phi1((iatom-iat_mod+1)*3+ii)=Phi1((iatom-iat_mod+1)*3+ii)-Phi1((iatom-1)*3+ii)
122 : end do
123 : end do
124 43 : ABI_FREE(Phi1_coeff)
125 43 : ABI_FREE(Phi1_3)
126 43 : ABI_FREE(Phi1_ref)
127 :
128 : ! Remove the rounding errors before writing (for non regression testing purposes)
129 19153 : do ii=1,3*Solver%natom
130 19153 : if (abs(Phi1(ii)).lt.tol8) Phi1(ii)=zero
131 : end do
132 :
133 43 : end subroutine tdep_calc_phi1
134 :
135 : !=====================================================================================================
136 44 : subroutine tdep_write_phi1(Invar,Phi1)
137 :
138 : type(atdep_dataset_type),intent(in) :: Invar
139 : double precision,intent(in) :: Phi1(3*Invar%natom)
140 :
141 : integer :: iatcell,ii
142 :
143 44 : write(Invar%stdout,*) ' '
144 44 : write(Invar%stdout,*) '#############################################################################'
145 44 : write(Invar%stdout,*) '#### For each shell, list of coefficients (IFC), number of neighbours... ####'
146 44 : write(Invar%stdout,*) '#############################################################################'
147 :
148 : ! Write the IFCs in the data.out file (with others specifications:
149 : ! number of atoms in a shell, distance, Trace...)
150 150 : do iatcell=1,Invar%natom_unitcell
151 106 : write(Invar%stdout,'(a,i4)') ' ############# List of (first order) IFC for the reference atom=',iatcell
152 424 : write(Invar%stdout,'(2x,3(f9.6,1x))') (Phi1((iatcell-1)*3+ii),ii=1,3)
153 150 : write(Invar%stdout,*) ' '
154 : end do !iatcell
155 :
156 44 : end subroutine tdep_write_phi1
157 :
158 : !=====================================================================================================
159 43 : subroutine tdep_calc_phi2(Solver,Shell2at,Sym,Phi2)
160 :
161 : type(tdep_Solver_type),intent(in) :: Solver
162 : type(Shell_type),intent(in) :: Shell2at
163 : type(Symmetries_type),intent(in) :: Sym
164 : double precision,intent(out) :: Phi2(3*Solver%natom,3*Solver%natom)
165 :
166 : integer :: ishell,isym,eatom,fatom,ncoeff,ncoeff_prev
167 : integer :: nshell,ii,jj,kk,kappa,iatshell,itrans
168 43 : double precision,allocatable :: Phi2_33(:,:),Phi2_ref(:,:,:)
169 43 : double precision,allocatable :: Phi2_coeff(:)
170 :
171 43 : nshell=Shell2at%nshell
172 129 : ABI_MALLOC(Phi2_coeff,(Solver%ncoeff2nd))
173 1968 : Phi2_coeff(:) = Solver%theta(Solver%ncoeff1st+1:Solver%ncoeff1st+Solver%ncoeff2nd)
174 6356 : ABI_MALLOC(Phi2_ref,(3,3,nshell)); Phi2_ref(:,:,:)=zero
175 602 : ABI_MALLOC(Phi2_33,(3,3)) ; Phi2_33(:,:)=0.d0
176 522 : do ishell=1,nshell
177 : ! Build the 3x3 IFC per shell
178 479 : ncoeff =Shell2at%ncoeff(ishell)
179 479 : ncoeff_prev=Shell2at%ncoeff_prev(ishell)
180 479 : kappa=0
181 1916 : do ii=1,3
182 6227 : do jj=1,3
183 4311 : kappa=kappa+1
184 23073 : Phi2_ref(ii,jj,ishell)=sum(Shell2at%proj(kappa,1:ncoeff,ishell)*Phi2_coeff(ncoeff_prev+1:ncoeff_prev+ncoeff))
185 : end do
186 : end do
187 68344 : do eatom=1,Solver%natom
188 : ! Build the 3x3 IFC of an atom in this shell
189 67822 : if (Shell2at%neighbours(eatom,ishell)%n_interactions.eq.0) cycle
190 462411 : do iatshell=1,Shell2at%neighbours(eatom,ishell)%n_interactions
191 405630 : fatom=Shell2at%neighbours(eatom,ishell)%atomj_in_shell(iatshell)
192 405630 : isym =Shell2at%neighbours(eatom,ishell)%sym_in_shell(iatshell)
193 405630 : itrans=Shell2at%neighbours(eatom,ishell)%transpose_in_shell(iatshell)
194 405630 : if (fatom.lt.eatom) cycle
195 206000 : call tdep_build_phi2_33(isym,Phi2_ref(:,:,ishell),Phi2_33,Sym,itrans)
196 : ! Symetrization of the Phi2 matrix
197 2678000 : Phi2((eatom-1)*3+1:(eatom-1)*3+3,3*(fatom-1)+1:3*(fatom-1)+3)=Phi2_33(:,:)
198 891822 : do ii=1,3
199 2877630 : do jj=1,3
200 2472000 : Phi2((fatom -1)*3+ii,3*(eatom-1)+jj)=Phi2_33(jj,ii)
201 : end do
202 : end do
203 : end do !iatshell
204 : end do !eatom
205 : end do !ishell
206 : ! Acoustic sum rule
207 6413 : do eatom=1,Solver%natom
208 25523 : do jj=1,3
209 82810 : do kk=1,3
210 10967916 : do fatom=1,Solver%natom
211 10891476 : if (fatom==eatom) cycle
212 : Phi2((eatom-1)*3+jj,(eatom-1)*3+kk)=Phi2((eatom-1)*3+jj,3*(eatom-1)+kk)&
213 10948806 : & -Phi2((eatom-1)*3+jj,3*(fatom-1)+kk)
214 : enddo
215 : enddo
216 : enddo
217 : enddo
218 43 : ABI_FREE(Phi2_coeff)
219 43 : ABI_FREE(Phi2_33)
220 43 : ABI_FREE(Phi2_ref)
221 :
222 : ! Remove the rounding errors before writing (for non regression testing purposes)
223 19153 : do ii=1,3*Solver%natom
224 10910629 : do jj=1,3*Solver%natom
225 10910586 : if (abs(Phi2(ii,jj)).lt.tol8) Phi2(ii,jj)=zero
226 : end do
227 : end do
228 :
229 43 : end subroutine tdep_calc_phi2
230 :
231 : !=====================================================================================================
232 44 : subroutine tdep_write_phi2(distance,Invar,MPIdata,Phi2,Shell2at)
233 :
234 : type(atdep_dataset_type),intent(in) :: Invar
235 : type(Shell_type),intent(in) :: Shell2at
236 : type(MPI_enreg_type), intent(in) :: MPIdata
237 : double precision,intent(in) :: distance(Invar%natom,Invar%natom,4)
238 : double precision,intent(in) :: Phi2(3*Invar%natom,3*Invar%natom)
239 :
240 : integer :: iatcell,ishell,jshell,jatom
241 : integer :: nshell,ii,this_shell,iatshell
242 : double precision :: max_bound,min_bound,dist_shell,tmp1,tmp2,tmp3
243 44 : integer,allocatable :: tab_shell(:)
244 :
245 44 : write(Invar%stdout,*) ' '
246 44 : write(Invar%stdout,*) '#############################################################################'
247 44 : write(Invar%stdout,*) '#### For each shell, list of coefficients (IFC), number of neighbours... ####'
248 44 : write(Invar%stdout,*) '#############################################################################'
249 :
250 44 : nshell=Shell2at%nshell
251 : ! Write the IFCs in the data.out file (with others specifications:
252 : ! number of atoms in a shell, distance, Trace...)
253 632 : ABI_MALLOC(tab_shell,(nshell)); tab_shell(:)=0
254 150 : do iatcell=1,Invar%natom_unitcell
255 2392 : tab_shell(:)=0
256 106 : write(Invar%stdout,'(a,i4)') ' ############# List of (second order) IFC for the reference atom=',iatcell
257 : ! Sort the IFC with distance in increasing order
258 106 : min_bound=-1.d0
259 2436 : do ishell=1,nshell
260 113058 : do jshell=1,nshell
261 113058 : if ((distance(Shell2at%iatref(jshell),Shell2at%jatref(jshell),1).ge.min_bound).and.(tab_shell(jshell).eq.0)) then
262 56529 : max_bound=distance(Shell2at%iatref(jshell),Shell2at%jatref(jshell),1)
263 56529 : this_shell=jshell
264 : end if
265 : end do
266 :
267 113058 : do jshell=1,nshell
268 : if ((distance(Shell2at%iatref(jshell),Shell2at%jatref(jshell),1).lt.max_bound).and.&
269 : & (distance(Shell2at%iatref(jshell),Shell2at%jatref(jshell),1).ge.min_bound).and.&
270 : & (distance(Shell2at%iatref(jshell),Shell2at%jatref(jshell),1).ne.&
271 110772 : & distance(Shell2at%iatref(this_shell),Shell2at%jatref(this_shell),1)).and.&
272 2286 : & (tab_shell(jshell).eq.0)) then
273 4843 : max_bound=distance(Shell2at%iatref(jshell),Shell2at%jatref(jshell),1)
274 4843 : this_shell=jshell
275 : end if
276 : end do
277 2286 : tab_shell(this_shell)=1
278 2286 : min_bound=max_bound
279 2286 : dist_shell=distance(Shell2at%iatref(this_shell),Shell2at%jatref(this_shell),1)
280 :
281 : ! Write the IFC properly
282 2392 : if (Shell2at%neighbours(iatcell,this_shell)%n_interactions.ne.0) then
283 1099 : write(Invar%stdout,'(a,i4,a,i4,a,f9.6)') ' ======== NEW SHELL (ishell=',this_shell,&
284 2198 : & '): There are',Shell2at%neighbours(iatcell,this_shell)%n_interactions,' atoms on this shell at distance=',dist_shell
285 6367 : do iatshell=1,Shell2at%neighbours(iatcell,this_shell)%n_interactions
286 5268 : jatom=Shell2at%neighbours(iatcell,this_shell)%atomj_in_shell(iatshell)
287 5268 : write(Invar%stdout,'(a,i4,a,i4)') ' For jatom=',jatom,' ,with type=',mod(jatom-1,Invar%natom_unitcell)+1
288 21072 : do ii=1,3
289 15804 : if (abs(Phi2((iatcell-1)*3+ii,(jatom-1)*3+1)).lt.5.d-7) then
290 2660 : tmp1=0.d0
291 : else
292 13144 : tmp1=Phi2((iatcell-1)*3+ii,(jatom-1)*3+1)
293 : end if
294 15804 : if (abs(Phi2((iatcell-1)*3+ii,(jatom-1)*3+2)).lt.5.d-7) then
295 2622 : tmp2=0.d0
296 : else
297 13182 : tmp2=Phi2((iatcell-1)*3+ii,(jatom-1)*3+2)
298 : end if
299 15804 : if (abs(Phi2((iatcell-1)*3+ii,(jatom-1)*3+3)).lt.5.d-7) then
300 2864 : tmp3=0.d0
301 : else
302 12940 : tmp3=Phi2((iatcell-1)*3+ii,(jatom-1)*3+3)
303 : end if
304 21072 : write(Invar%stdout,'(2x,3(f9.6,1x))') tmp1,tmp2,tmp3
305 : end do
306 5268 : write(Invar%stdout,'(a,3(1x,f11.6))') ' The components of the vector are:', distance(iatcell,jatom,2:4)
307 5268 : write(Invar%stdout,'(a,(1x,f9.6))') ' Trace=',Phi2((iatcell-1)*3+1,(jatom-1)*3+1)+Phi2((iatcell-1)*3+2,&
308 10536 : & (jatom-1)*3+2)+Phi2((iatcell-1)*3+3,(jatom-1)*3+3)
309 6367 : write(Invar%stdout,*) ' '
310 : end do
311 : end if
312 : end do !ishell
313 : end do !iatcell
314 44 : ABI_FREE(tab_shell)
315 :
316 : ! Write the Phi2_unitcell.dat and Phi2.dat files
317 44 : if (Invar%debug.and.MPIdata%iam_master) then
318 2 : write(Invar%stdout,'(a)') ' See the Phi2*.dat file'
319 2 : open(unit=52,file=trim(Invar%output_prefix)//'_Phi2_unitcell.dat')
320 2 : open(unit=55,file=trim(Invar%output_prefix)//'_Phi2.dat')
321 674 : do jatom=1,3*Invar%natom
322 672 : if (jatom.le.3*Invar%natom_unitcell) then
323 30 : write(52,'(10000(f10.6,1x))') Phi2(jatom,:)
324 : end if
325 674 : write(55,'(10000(f10.6,1x))') Phi2(jatom,:)
326 : end do
327 2 : close(52)
328 2 : close(55)
329 : end if
330 :
331 44 : end subroutine tdep_write_phi2
332 :
333 : !=====================================================================================================
334 0 : subroutine tdep_calc_dij(dij,eigenV,iqpt,Invar,omega,Phi2,qpt_cart,Rlatt_cart)
335 :
336 : type(atdep_dataset_type),intent(in) :: Invar
337 : integer,intent(in) :: iqpt
338 : double precision,intent(in) :: Phi2(3*Invar%natom,3*Invar%natom)
339 : double precision,intent(in) :: Rlatt_cart(3,Invar%natom_unitcell,Invar%natom)
340 : double precision,intent(in) :: qpt_cart(3)
341 : double precision,intent(out) :: omega (3*Invar%natom_unitcell)
342 : double complex ,intent(out) :: dij (3*Invar%natom_unitcell,3*Invar%natom_unitcell)
343 : double complex ,intent(out) :: eigenV(3*Invar%natom_unitcell,3*Invar%natom_unitcell)
344 :
345 : integer :: LWORK,ii,jj,kk,iatom,jatom,iatcell,jatcell,itypat,jtypat,iat_mod,INFO,itemp,imode,nmode
346 : double precision :: phase
347 : double complex :: norm
348 0 : double precision, allocatable :: RWORK(:)
349 0 : double complex, allocatable :: WORKC(:)
350 : ! double complex, allocatable :: mass_mat(:,:)
351 :
352 : ! Calculation of the dynamical matrix (Dij)
353 0 : do iatcell=1,Invar%natom_unitcell
354 0 : do jatom=1,Invar%natom
355 0 : iat_mod=mod(jatom+Invar%natom_unitcell-1,Invar%natom_unitcell)+1
356 0 : phase=0.d0
357 0 : do kk=1,3
358 0 : phase=phase+2*pi*Rlatt_cart(kk,iatcell,jatom)*qpt_cart(kk)
359 : end do
360 0 : do ii=1+(iatcell-1)*3,3+(iatcell-1)*3
361 0 : do jj=1,3
362 0 : dij(ii,3*(iat_mod-1)+jj)=dij(ii,3*(iat_mod-1)+jj)+dcmplx(Phi2(ii,3*(jatom-1)+jj),0.d0)*exp(dcmplx(0.d0,phase))
363 : end do !jj
364 : end do !ii
365 : end do !jatom
366 : end do !iatcell
367 :
368 : ! The Dij has to be an hermitian matrix
369 0 : itemp=0
370 0 : do ii=1,3*Invar%natom_unitcell
371 0 : do jj=ii,3*Invar%natom_unitcell
372 0 : if ((abs(real(dij(ii,jj))-real(dij(jj,ii))).gt.tol10).or.(abs(aimag(dij(ii,jj))+aimag(dij(jj,ii))).gt.tol10)) then
373 0 : if (Invar%debug) then
374 0 : write (Invar%stdout,'(a,1x,2(i4,1x))') 'for ii,jj=',ii,jj
375 0 : write (Invar%stdout,'(a,1x,1(f12.8,1x))') 'abs(realij-realji)=',abs(real(dij(ii,jj))-real(dij(jj,ii)))
376 0 : write (Invar%stdout,'(a,1x,1(f12.8,1x))') 'abs(imagij+imagji)=',abs(aimag(dij(ii,jj))+aimag(dij(jj,ii)))
377 : end if
378 0 : itemp=itemp+1
379 : end if
380 : end do
381 : end do
382 0 : if (itemp.ne.0.and.iqpt.eq.1) then
383 0 : write(Invar%stdout,*) 'WARNING: The Dij matrix is not hermitian'
384 0 : write(Invar%stdout,*) ' Probably: one shell may not have the whole number of atoms'
385 0 : write(Invar%stdout,*) ' The Dij matrix is symetrized'
386 : end if
387 :
388 : ! Diagonalization of dynamical matrix Dij/sqrt(Mi*Mj)
389 0 : LWORK=2*3*Invar%natom_unitcell-1
390 0 : ABI_MALLOC(WORKC,(LWORK)); WORKC(:)=czero
391 0 : ABI_MALLOC(RWORK,(3*3*Invar%natom_unitcell-2)); RWORK(:)=zero
392 0 : do iatcell=1,Invar%natom_unitcell
393 0 : itypat=Invar%typat_unitcell(iatcell)
394 0 : do jatcell=1,Invar%natom_unitcell
395 0 : jtypat=Invar%typat_unitcell(jatcell)
396 0 : do ii=1,3
397 0 : do jj=1,3
398 : eigenV(ii+(iatcell-1)*3,jj+(jatcell-1)*3)=dij(ii+(iatcell-1)*3,jj+(jatcell-1)*3)/&
399 0 : & dcmplx(dsqrt(Invar%amu(itypat)*Invar%amu(jtypat))*amu_emass,0.d0)
400 : end do !jj
401 : end do !ii
402 : end do !jatcell
403 : end do !iatcell
404 0 : call ZHEEV('V','U',3*Invar%natom_unitcell,eigenV(:,:),3*Invar%natom_unitcell,omega(:),WORKC,LWORK,RWORK,INFO)
405 :
406 : ! Normalization of the eigenvectors
407 0 : nmode=3*Invar%natom_unitcell
408 0 : do imode=1,nmode
409 : norm=zero
410 0 : do iatom=1,Invar%natom_unitcell
411 0 : do ii=1,3
412 0 : norm=norm+eigenV(3*(iatom-1)+ii,imode)*conjg(eigenV(3*(iatom-1)+ii,imode))
413 : end do
414 : end do
415 0 : eigenV(:,imode)=eigenV(:,imode)/dsqrt(real(norm))
416 : end do
417 :
418 : ! Remove the squared-negative frequencies
419 0 : do ii=1,Invar%natom_unitcell
420 0 : do jj=1,3
421 0 : if (omega((ii-1)*3+jj).lt.0.d0) then
422 0 : omega((ii-1)*3+jj)=-dsqrt(-omega((ii-1)*3+jj))
423 : else
424 0 : omega((ii-1)*3+jj)=dsqrt(omega((ii-1)*3+jj))
425 : end if
426 : end do
427 : end do
428 0 : ABI_FREE(WORKC)
429 0 : ABI_FREE(RWORK)
430 :
431 0 : end subroutine tdep_calc_dij
432 :
433 : !=====================================================================================================
434 : !FB subroutine tdep_write_dij(Eigen2nd,iqpt,Invar,qpt_cart)
435 22588 : subroutine tdep_write_dij(Eigen2nd,iqpt,Invar,qpt)
436 :
437 : type(atdep_dataset_type),intent(in) :: Invar
438 : integer,intent(in) :: iqpt
439 : !FB double precision,intent(in) :: qpt_cart(3)
440 : double precision,intent(in) :: qpt(3)
441 : type(Eigen_type),intent(in) :: Eigen2nd
442 :
443 22588 : double precision, allocatable :: omega (:)
444 22588 : double complex, allocatable :: dij (:,:)
445 22588 : double complex, allocatable :: eigenV(:,:)
446 : double precision :: norm_eigenV
447 : integer :: ii,jj,iatcell,jatcell
448 :
449 221145 : ABI_MALLOC(omega ,(3*Invar%natom_unitcell)) ; omega(:) = zero
450 2053372 : ABI_MALLOC(dij ,(3*Invar%natom_unitcell,3*Invar%natom_unitcell)); dij(:,:) =czero
451 2030784 : ABI_MALLOC(eigenV,(3*Invar%natom_unitcell,3*Invar%natom_unitcell)); eigenV(:,:)=czero
452 175969 : omega(:)=Eigen2nd%eigenval(:,iqpt)
453 73715 : do iatcell=1,Invar%natom_unitcell
454 274786 : do jatcell=1,Invar%natom_unitcell
455 855411 : do jj=1,3
456 603213 : norm_eigenV = 0.0d0
457 2412852 : do ii=1,3
458 : dij ((iatcell-1)*3+ii,(jatcell-1)*3+jj)=dcmplx(Eigen2nd%dynmat (1,ii,iatcell,jj,jatcell,iqpt),&
459 1809639 : & Eigen2nd%dynmat (2,ii,iatcell,jj,jatcell,iqpt))
460 : eigenV((iatcell-1)*3+ii,(jatcell-1)*3+jj)=dcmplx(Eigen2nd%eigenvec(1,ii,iatcell,jj,jatcell,iqpt),&
461 1809639 : & Eigen2nd%eigenvec(2,ii,iatcell,jj,jatcell,iqpt))
462 : norm_eigenV = norm_eigenV + real(eigenV((iatcell-1)*3+ii, (jatcell-1)*3+jj))**2 + &
463 2412852 : aimag(eigenV((iatcell-1)*3+ii, (jatcell-1)*3+jj))**2
464 : end do !ii
465 603213 : norm_eigenV = dsqrt(norm_eigenV)
466 : ! if (norm_eigenV.lt.tol8) then
467 : ! write(6,*) "iqpt, norm=",iqpt,norm_eigenV
468 : ! ABI_ERROR(' STOP: THE NORM OF EIGENVECTOR IS ZERO')
469 : ! end if
470 804284 : if (norm_eigenV.gt.tol8) then
471 2390116 : do ii=1,3
472 2390116 : eigenV((iatcell-1)*3+ii, (jatcell-1)*3+jj) = eigenV((iatcell-1)*3+ii, (jatcell-1)*3+jj) / dcmplx(norm_eigenV,0.d0)
473 : end do !ii
474 : end if
475 : end do !jj
476 : end do !jatcell
477 : end do !iatcell
478 :
479 : ! Print the dynamical matrix (Dij)
480 22588 : write(52,'(a,1x,3(f10.6,1x))') 'For qpt=',qpt(:)
481 22588 : write(52,'(a,i4,a)') ' Dij(',iqpt,'real)='
482 73715 : do iatcell=1,Invar%natom_unitcell
483 654340 : write(52,'(100(f10.6,1x))') real(dij(1+(iatcell-1)*3,:))
484 654340 : write(52,'(100(f10.6,1x))') real(dij(2+(iatcell-1)*3,:))
485 676928 : write(52,'(100(f10.6,1x))') real(dij(3+(iatcell-1)*3,:))
486 : end do
487 22588 : write(52,'(a,i4,a)') ' Dij(',iqpt,'imag)='
488 73715 : do iatcell=1,Invar%natom_unitcell
489 654340 : write(52,'(100(f10.6,1x))') aimag(dij(1+(iatcell-1)*3,:))
490 654340 : write(52,'(100(f10.6,1x))') aimag(dij(2+(iatcell-1)*3,:))
491 676928 : write(52,'(100(f10.6,1x))') aimag(dij(3+(iatcell-1)*3,:))
492 : end do
493 22588 : write(52,*)' '
494 :
495 : ! Print the frequencies (omega)
496 58192 : if (Invar%enunit.eq.0) write(53,'(i5,1x,100(f15.3,1x))') iqpt,(omega(ii)*Ha_eV*1000,ii=1,3*Invar%natom_unitcell)
497 124216 : if (Invar%enunit.eq.1) write(53,'(i5,1x,100(f15.3,1x))') iqpt,(omega(ii)*Ha_cmm1 ,ii=1,3*Invar%natom_unitcell)
498 24022 : if (Invar%enunit.eq.2) write(53,'(i5,1x,100(f15.3,1x))') iqpt,(omega(ii)*1000 ,ii=1,3*Invar%natom_unitcell)
499 37303 : if (Invar%enunit.eq.3) write(53,'(i5,1x,100(f15.3,1x))') iqpt,(omega(ii)*Ha_THz ,ii=1,3*Invar%natom_unitcell)
500 :
501 : ! Print the eigenvectors (eigenV)
502 : ! write(51,*) 'For iqpt=',iqpt
503 : ! do ii=1,3*Invar%natom_unitcell
504 : ! write(51,*) 'Mode number',ii,' energy',omega(ii)
505 : ! write(51,*) ' Real:'
506 : ! write(51,*) real(eigenV(:,ii))
507 : ! write(51,*) ' Imag:'
508 : ! write(51,*) aimag(eigenV(:,ii))
509 : ! end do
510 : ! write(51,*) ' '
511 :
512 22588 : write(51,'(a,4x,i3,4(f15.6,1x))') 'q-pt=',iqpt,(qpt(ii),ii=1,3),qpt(1)*qpt(2)*qpt(3)
513 :
514 175969 : do ii=1,3*Invar%natom_unitcell
515 175969 : write(51,'(i5,5x,f15.6)') ii,omega(ii)*Ha_cmm1
516 : enddo
517 22588 : write(51,*) 'Phonon Eigenvectors'
518 22588 : write(51,'(a,17x,a,33x,a,34x,a)') 'Mode Ion','X','Y','Z'
519 175969 : do ii=1,3*Invar%natom_unitcell
520 779182 : do jj=1,Invar%natom_unitcell
521 603213 : write(51,'(i2,3x,i2,3x,6(f15.12,1x))') ii,jj,real(eigenV(3*(jj-1)+1,ii)),&
522 603213 : & aimag(eigenV(3*(jj-1)+1,ii)),&
523 603213 : & real(eigenV(3*(jj-1)+2,ii)),&
524 603213 : & aimag(eigenV(3*(jj-1)+2,ii)),&
525 603213 : & real(eigenV(3*(jj-1)+3,ii)),&
526 1359807 : & aimag(eigenV(3*(jj-1)+3,ii))
527 : enddo
528 : enddo
529 :
530 :
531 22588 : ABI_FREE(omega)
532 22588 : ABI_FREE(dij)
533 22588 : ABI_FREE(eigenV)
534 :
535 22588 : end subroutine tdep_write_dij
536 :
537 : !=====================================================================================================
538 300160 : subroutine tdep_build_phi2_33(isym,Phi2_ref,Phi2_33,Sym,itrans)
539 :
540 : type(Symmetries_type),intent(in) :: Sym
541 : ! type(atdep_dataset_type),intent(in) :: Invar
542 : double precision, intent(in) :: Phi2_ref(3,3)
543 : double precision, intent(out) :: Phi2_33(3,3)
544 : integer,intent(in) :: isym,itrans
545 :
546 : double precision :: Phi2_tmp(3,3),tmp1(3,3)
547 :
548 : ! Transform in the new basis wrt S_ref
549 300160 : call DGEMM('N','N',3,3,3,1.d0,Sym%S_ref(:,:,isym,1),3,Phi2_ref,3,0.d0,Phi2_tmp,3)
550 300160 : call DGEMM('N','N',3,3,3,1.d0,Phi2_tmp,3,Sym%S_inv(:,:,isym,1),3,0.d0,Phi2_33,3)
551 :
552 300160 : if ((itrans.lt.1).or.(itrans.gt.2)) then
553 0 : ABI_BUG('This value of the symmetry index is not permitted')
554 : end if
555 : ! Transpose the 3x3 matrix if required
556 300160 : if (itrans.eq.2) then
557 46327 : tmp1(:,:)=Phi2_33(:,:)
558 46327 : Phi2_33(1,2)=tmp1(2,1)
559 46327 : Phi2_33(1,3)=tmp1(3,1)
560 46327 : Phi2_33(2,3)=tmp1(3,2)
561 46327 : Phi2_33(2,1)=tmp1(1,2)
562 46327 : Phi2_33(3,1)=tmp1(1,3)
563 46327 : Phi2_33(3,2)=tmp1(2,3)
564 : end if
565 :
566 300160 : end subroutine tdep_build_phi2_33
567 :
568 : !=====================================================================================================
569 88 : subroutine tdep_init_eigen2nd(Eigen2nd,natom_unitcell,nqpt)
570 :
571 : integer, intent(in) :: natom_unitcell,nqpt
572 : type(Eigen_type),intent(out) :: Eigen2nd
573 :
574 309521 : ABI_MALLOC(Eigen2nd%eigenval,(3*natom_unitcell,nqpt)); Eigen2nd%eigenval(:,:) =zero
575 13432522 : ABI_MALLOC(Eigen2nd%eigenvec,(2,3,natom_unitcell,3,natom_unitcell,nqpt)); Eigen2nd%eigenvec(:,:,:,:,:,:)=zero
576 13432346 : ABI_MALLOC(Eigen2nd%dynmat ,(2,3,natom_unitcell,3,natom_unitcell,nqpt)); Eigen2nd%dynmat (:,:,:,:,:,:)=zero
577 :
578 88 : end subroutine tdep_init_eigen2nd
579 :
580 : !=====================================================================================================
581 88 : subroutine tdep_destroy_eigen2nd(Eigen2nd)
582 :
583 : type(Eigen_type),intent(inout) :: Eigen2nd
584 :
585 88 : ABI_FREE(Eigen2nd%eigenval)
586 88 : ABI_FREE(Eigen2nd%eigenvec)
587 88 : ABI_FREE(Eigen2nd%dynmat)
588 :
589 88 : end subroutine tdep_destroy_eigen2nd
590 :
591 : !=====================================================================================================
592 44 : subroutine tdep_write_yaml(Eigen2nd,Qpt,Prefix)
593 :
594 : type(Eigen_type),intent(in) :: Eigen2nd
595 : type(Qpoints_type),intent(in) :: Qpt
596 : character(len=*) :: Prefix
597 :
598 : integer :: ii,jj,iatcell,jatcell,iqpt,imode,nmode
599 : double precision :: distance
600 44 : double complex, allocatable :: eigenV(:,:)
601 :
602 44 : nmode=size(Eigen2nd%eigenval,dim=1)
603 44 : open(unit=52,file=trim(Prefix)//'_phonon-bands.yaml')
604 44 : write(52,'(a,i4)') 'nqpoint:',Qpt%nqpt
605 44 : write(52,'(a,i4)') 'npath:',Qpt%qpt_tot-1
606 44 : write(52,'(a)') 'segment_nqpoint:'
607 270 : do ii=1,Qpt%qpt_tot-1
608 270 : write(52,'(a,i4)') '- ',Qpt%lgth_segments(ii)
609 : end do
610 44 : write(52,'(a,i4)') 'natom:',nmode/3
611 44 : write(52,'(a)') 'phonon:'
612 44 : distance=0.d0
613 22632 : do iqpt=1,Qpt%nqpt
614 22588 : write(52,'(a,3(f15.6,1x,a))') '- q-position: [',Qpt%qpt_red(1,iqpt),',',Qpt%qpt_red(2,iqpt),',',Qpt%qpt_red(3,iqpt),']'
615 90220 : if (iqpt.gt.1) distance=distance+sqrt(sum((Qpt%qpt_cart(:,iqpt)-Qpt%qpt_cart(:,iqpt-1))**2))
616 22588 : write(52,'(a,f15.6)') ' distance:',distance
617 178068 : do ii=1,Qpt%qpt_tot
618 645318 : if (sum(abs(Qpt%qpt_red(:,iqpt)-Qpt%special_red(ii,:))).lt.tol8) then
619 270 : write(52,'(3a)') " label: '",trim(Qpt%special_qpt(ii)),"'"
620 270 : exit
621 : end if
622 : end do !ii
623 2053372 : ABI_MALLOC(eigenV,(nmode,nmode)); eigenV(:,:)=czero
624 73715 : do iatcell=1,nmode/3
625 274786 : do jatcell=1,nmode/3
626 855411 : do ii=1,3
627 2613923 : do jj=1,3
628 : eigenV((iatcell-1)*3+ii,(jatcell-1)*3+jj)=dcmplx(Eigen2nd%eigenvec(1,ii,iatcell,jj,jatcell,iqpt),&
629 2412852 : & Eigen2nd%eigenvec(2,ii,iatcell,jj,jatcell,iqpt))
630 : end do !ii
631 : end do !jj
632 : end do !jatcell
633 : end do !iatcell
634 22588 : write(52,'(a)') ' band:'
635 175969 : do imode=1,nmode
636 153381 : write(52,'(a,i4)') ' - #',imode
637 153381 : write(52,'(a,f15.6)') ' frequency:',Eigen2nd%eigenval(imode,iqpt)*Ha_THz
638 153381 : write(52,'(a)') ' eigenvector:'
639 779182 : do iatcell=1,nmode/3
640 603213 : write(52,'(a,i4)') " - # atom ", iatcell
641 2566233 : do ii=1,3
642 1809639 : write(52,'(a,f18.9,a,f18.9,a)') " - [",real(eigenV((iatcell-1)*3+ii,imode)),','&
643 4222491 : & ,aimag(eigenV((iatcell-1)*3+ii,imode)),']'
644 : end do
645 : end do
646 : end do !nmode
647 22588 : ABI_FREE(eigenV)
648 22632 : write(52,'(a)') ''
649 : end do
650 :
651 44 : close(52)
652 :
653 :
654 44 : end subroutine tdep_write_yaml
655 :
656 : !=====================================================================================================
657 0 : end module m_tdep_phi2
|