Branch data Line data Source code
1 : : !!****m* ABINIT/m_ddb_diel
2 : : !! NAME
3 : : !! m_ddb_diel
4 : : !!
5 : : !! FUNCTION
6 : : !! This module provides routines for the calculation of the dielectric constant (anaddb)
7 : : !!
8 : : !! COPYRIGHT
9 : : !! Copyright (C) 1999-2026 ABINIT group (XG,XW, MVeithen, EB)
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_diel
23 : :
24 : : use defs_basis
25 : : use m_errors
26 : : use m_xmpi
27 : : use m_abicore
28 : : use m_ddb
29 : : use m_nctk
30 : : use netcdf
31 : :
32 : : use m_anaddb_dataset, only : anaddb_dataset_type
33 : : use m_crystal, only : crystal_t
34 : :
35 : : implicit none
36 : :
37 : : private
38 : : !!***
39 : :
40 : : public :: ddb_diel
41 : : public :: alignph
42 : : !!***
43 : :
44 : : contains
45 : : !!***
46 : :
47 : : !!****f* ABINIT/ddb_diel
48 : : !!
49 : : !! NAME
50 : : !! ddb_diel
51 : : !!
52 : : !! FUNCTION
53 : : !! Get the frequency-dependent dielectric matrix, as well as the
54 : : !! oscillator strengths and mode effective charges,
55 : : !! and reflectivities (without damping)
56 : : !! See the definitions Eq.(53-54) in PRB55, 10355 (1997) [[cite:Gonze1997a]].
57 : : !!
58 : : !! INPUTS
59 : : !! amu(ntypat)=mass of the atoms (atomic mass unit)
60 : : !! anaddb_dtset= (derived datatype) contains all the input variables
61 : : !! matrix (diagonal in the atoms)
62 : : !! displ(2,3*natom,3*natom)=
63 : : !! the displacements of atoms in cartesian coordinates.
64 : : !! The first index means either the real or the imaginary part,
65 : : !! The second index runs on the direction and the atoms displaced
66 : : !! The third index runs on the modes.
67 : : !! d2cart(2,3,mpert,3,mpert)=dynamical matrix, effective charges, dielectric tensor,... all in cartesian coordinates
68 : : !! iout=unit number for outputs
69 : : !! lst(3*nph2l)=log. of product of frequencies**2, needed to calculate
70 : : !! the generalized Lyddane-Sachs-Teller relation at zero frequency
71 : : !! mpert =maximum number of ipert
72 : : !! natom=number of atoms in unit cell
73 : : !! nph2l=input variable from anaddb_dtset, needed to dimension lst
74 : : !! phfrq(3*natom)=phonon frequencies (square root of the dynamical
75 : : !! matrix eigenvalues, except if these are negative, and in this
76 : : !! case, give minus the square root of the absolute value
77 : : !! of the matrix eigenvalues). Hartree units.
78 : : !! comm=MPI communicator.
79 : : !! ncid=the id of the open NetCDF file. Set to nctk_noid if netcdf output is not wanted.
80 : : !!
81 : : !! OUTPUT
82 : : !! fact_oscstr(2,3,3*natom)=oscillator strengths for the different eigenmodes,
83 : : !! for different direction of the electric field;
84 : : !! dielt_rlx(3,3) relaxed ion (zero frequency) dielectric tensor.
85 : : !!
86 : : !! NOTES
87 : : !! 1. The phonon frequencies phfrq should correspond to the
88 : : !! wavevector at Gamma, without any non-analyticities.
89 : : !! 2. Should clean for no imaginary part ...
90 : : !! This routine should be used only by one processor.
91 : : !! 3. frdiel(3,3,nfreq)= frequency-dependent dielectric tensor
92 : : !! mode effective charges for the different eigenmodes,
93 : : !! for different direction of the electric field
94 : : !!
95 : : !! SOURCE
96 : :
97 : 26 : subroutine ddb_diel(Crystal,amu,anaddb_dtset,dielt_rlx,displ,d2cart,epsinf,fact_oscstr,&
98 : 26 : & iout,lst,mpert,natom,nph2l,phfrq,comm,ncid)
99 : :
100 : : !Arguments -------------------------------
101 : : !scalars
102 : : integer,intent(in) :: iout,mpert,natom,nph2l,comm,ncid
103 : : type(crystal_t),intent(in) :: Crystal
104 : : type(anaddb_dataset_type),intent(in) :: anaddb_dtset
105 : : real(dp),intent(in) :: lst(nph2l+1)
106 : :
107 : : !arrays
108 : : real(dp),intent(in) :: amu(Crystal%ntypat),d2cart(2,3,mpert,3,mpert)
109 : : real(dp),intent(in) :: phfrq(3*natom),epsinf(3,3)
110 : : real(dp),intent(inout) :: displ(2,3*natom,3*natom)
111 : : real(dp),intent(out) :: dielt_rlx(3,3),fact_oscstr(2,3,3*natom)
112 : :
113 : : !Local variables -------------------------
114 : : !scalars
115 : : integer,parameter :: master=0
116 : : integer :: dieflag,idir1,idir2,ifreq,ii,imode,iphl2,nfreq
117 : : integer :: nprocs,my_rank,ncerr
118 : : real(dp) :: afreq,difffr,eps,q2,ucvol
119 : : character(len=500) :: message
120 : : !arrays
121 : : real(dp) :: qphon(3),refl(3)
122 : 26 : real(dp),allocatable :: frdiel(:,:,:),modez(:,:,:),oscstr(:,:,:,:),dielt_modedecompo(:,:,:)
123 : :
124 : : ! *********************************************************************
125 : :
126 : 26 : nprocs = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
127 : :
128 : 26 : dieflag=anaddb_dtset%dieflag
129 : 26 : nfreq=anaddb_dtset%nfreq
130 : :
131 : 26 : ucvol = Crystal%ucvol
132 : :
133 : :
134 : : ! frdiel(3,3,nfreq)= frequency-dependent dielectric tensor
135 : : ! modez=mode effective charge
136 [ - + + - : 78 : ABI_MALLOC(frdiel,(3,3,nfreq))
+ - + - -
+ - + ]
137 [ + - - + : 104 : ABI_MALLOC(oscstr,(2,3,3,3*natom))
+ - + - +
- - + -
+ ]
138 [ - + + - : 78 : ABI_MALLOC(modez,(2,3,3*natom))
+ - + - -
+ - + ]
139 [ - + + - : 78 : ABI_MALLOC(dielt_modedecompo,(3,3,3*natom))
+ - + - -
+ - + ]
140 : :
141 : : !In case only the electronic dielectric constant should be printed
142 [ + + ]: 26 : if (dieflag==2) then
143 : 7 : call ddb_diel_elec(iout,epsinf)
144 : : else
145 : : ! In case the ionic contribution to the dielectric tensor is asked
146 [ + + ]: 19 : if (dieflag/=2 .and. nph2l==0) then
147 : : ! Check if the alignement of phonon modes eigenvector is requested from the input flag alphon;
148 : : ! useful in case of degenerate modes
149 [ + + ]: 10 : if (anaddb_dtset%alphon > 0) then
150 : : write(message, '(3a)' )&
151 : 3 : ' The alphon input variable is non-zero, will mix the degenerate phonon modes',ch10,&
152 : 6 : ' in order to align the mode effective charges with the cartesian axes.'
153 : 3 : call wrtout(std_out,message,'COLL')
154 : 3 : call wrtout(iout,message,'COLL')
155 : 3 : call alignph(amu,displ,d2cart,mpert,natom,Crystal%ntypat,phfrq,Crystal%typat)
156 : : end if ! alignment of the phonon eigenvectors
157 : :
158 : : ! Compute the mode effective charge and oscillator strength
159 : 10 : call ddb_oscstr(displ,d2cart,fact_oscstr,oscstr,modez,iout,mpert,natom,phfrq,ncid,my_rank)
160 : :
161 : : ! Calculation of epsilon_r (Eq.55 PRB 55, 10355)
162 : : ! Check the acousticity of the three lowest modes, assuming
163 : : ! that they are ordered correctly
164 [ - + ]: 10 : if (abs(phfrq(1))>abs(phfrq(4)))then
165 : : ! This means that there is at least one mode with truly negative frequency
166 : : write(message, '(12a,4es16.8)' )&
167 : 0 : 'The lowest mode appears to be a "true" negative mode,',ch10,&
168 : 0 : 'and not an acoustic mode. This precludes the computation',ch10,&
169 : 0 : 'of the frequency-dependent dielectric tensor.',ch10,&
170 : 0 : 'Action : likely there is no action to be taken, although you,',ch10,&
171 : 0 : 'could try to raise your convergence parameters (ecut and k-points).',ch10,&
172 : 0 : 'For your information, here are the four lowest frequencies :',ch10,&
173 : 0 : (phfrq(ii),ii=1,4)
174 : 0 : ABI_ERROR(message)
175 : : end if
176 : :
177 : : ! Compute the relaxed ion dielectric tensor
178 [ + + ]: 40 : do idir1=1,3
179 [ + + ]: 130 : do idir2=1,3
180 : : ! The electronic contribution to epsilon is added
181 : 90 : dielt_rlx(idir1,idir2)=epsinf(idir1,idir2)
182 : : ! calculation of the phonon contribution (ionic) to epsilon
183 [ + + ]: 1227 : do imode=4,3*natom
184 : : ! Note that the acoustic modes are not included : their
185 : : ! oscillator strength should be exactly zero
186 : : ! Also, only the real part of oscstr is taken into account:
187 : : ! the possible imaginary parts of degenerate modes
188 : : ! will cancel.
189 : : dielt_rlx(idir1,idir2)=dielt_rlx(idir1,idir2)+&
190 : 1107 : & oscstr(1,idir1,idir2,imode) / (phfrq(imode)**2)*four_pi/ucvol
191 : : ! Mode decomposition of epsilon
192 [ - + ]: 1197 : if (dieflag==3)then
193 : 0 : dielt_modedecompo(idir1,idir2,imode)=oscstr(1,idir1,idir2,imode) / (phfrq(imode)**2)*four_pi/ucvol
194 : : endif ! mode decompo of epsilon
195 : : !DEBUG
196 : : ! if(idir1==1 .and. idir2==2)then
197 : : ! write(std_out,'(a,i4,a,3es16.6)')'imode=',imode,' dielt_rlx(idir1,idir2),oscstr(1,idir1,idir2,imode),phfrq(imode)=',&
198 : : !& dielt_rlx(idir1,idir2),oscstr(1,idir1,idir2,imode),phfrq(imode)
199 : : ! endif
200 : : !ENDDEBUG
201 : : end do ! imode
202 : : end do ! idir2
203 : : end do ! idir1
204 : :
205 : : ! Print the electronic dielectric tensor
206 : 10 : call ddb_diel_elec(iout,epsinf)
207 : :
208 : : ! Print the relaxed ion dielectric tensor
209 : 10 : write(message,'(a,a)') ch10,' Relaxed ion dielectric tensor'
210 : 10 : call wrtout(std_out,message,'COLL')
211 : 10 : call wrtout(iout,message,'COLL')
212 : :
213 [ + + ]: 40 : do idir1=1,3
214 : 30 : write(message,'(3f16.8)')(dielt_rlx(idir1,idir2),idir2=1,3)
215 : 30 : call wrtout(std_out,message,'COLL')
216 : 40 : call wrtout(iout,message,'COLL')
217 : : end do
218 : 10 : call wrtout(iout, " ",'COLL')
219 : 10 : call wrtout(std_out, " ",'COLL')
220 : :
221 : : ! Mode decompo of epsilon
222 [ - + ]: 10 : if (dieflag==3) then
223 : 0 : write(message,'(a,a,a,a)') ch10,' Mode by mode decomposition of the ionic dielectric tensor',&
224 : 0 : ch10,' (the electronic contribution is not included)'
225 : 0 : call wrtout(std_out,message,'COLL')
226 : 0 : call wrtout(iout,message,'COLL')
227 [ # # ]: 0 : do imode=4,3*natom
228 : 0 : write(message,'(a,a,i4,a,es14.6,a,a,3f8.3)') ch10,' Mode number ',imode, ' freq = ',phfrq(imode),' Ha', &
229 [ # # # # ]: 0 : ' Mode Z* (|x|, |y|, |z|)', (abs(modez(1,idir1,imode)),idir1=1,3)
230 : 0 : call wrtout(std_out,message,'COLL')
231 : 0 : call wrtout(iout,message,'COLL')
232 [ # # ]: 0 : do idir1=1,3
233 : : ! write(message,'(a,a,i4)') ch10,' Mode number 2',imode
234 : 0 : write(message,'(3f16.8)')(dielt_modedecompo(idir1,idir2,imode),idir2=1,3)
235 : 0 : call wrtout(std_out,message,'COLL')
236 : 0 : call wrtout(iout,message,'COLL')
237 : : end do
238 : : end do
239 : : endif ! mode decompo of epsilon
240 : :
241 : : ! write the relaxed ion dielectric tensor to the netcdf
242 [ + - ]: 10 : if (ncid /= nctk_noid) then
243 : : ncerr = nctk_def_arrays(ncid, [nctkarr_t("emacro_cart_rlx", "dp", &
244 [ + + ]: 20 : "number_of_cartesian_directions, number_of_cartesian_directions")],defmode=.True.)
245 [ - + ]: 10 : NCF_CHECK(ncerr)
246 [ - + ]: 10 : NCF_CHECK(nctk_set_datamode(ncid))
247 [ - + ]: 10 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "emacro_cart_rlx"), dielt_rlx))
248 : : end if
249 : :
250 : : ! Frequency-dependent dielectric tensor case
251 [ + + ]: 10 : if(dieflag==1) then
252 : 8 : write(message,'(4a)') ch10,ch10,' Calculate the freq. dep. dielectric constant',ch10
253 : 8 : call wrtout(std_out,message,'COLL')
254 : 8 : write(message,'(3a)') ch10,' Frequency dependent dielectric constant:',ch10
255 : 8 : call wrtout(iout,message,'COLL')
256 : :
257 : : ! Check the possibility of asking the frequency-dependent
258 : : ! dielectric tensor (there should be more than one atom in the unit cell)
259 : : ! EB: this check is not in any automatic test
260 [ - + ]: 8 : if(natom==1)then
261 : : write(message, '(6a)' )&
262 : 0 : ' ddb_diel : WARNING -',ch10,&
263 : 0 : ' When there is only one atom in the unit cell',ch10,&
264 : 0 : ' cell, the dielectric tensor is frequency-independent.'!,&
265 : : ! ' Consequently, dieflag has been reset to 2 . '
266 : 0 : call wrtout(std_out,message,'COLL')
267 : 0 : call wrtout(iout,message,'COLL')
268 : : end if
269 : :
270 : 8 : difffr=zero
271 [ + + ]: 8 : if(nfreq>1)difffr=(anaddb_dtset%frmax-anaddb_dtset%frmin)/(nfreq-1)
272 : :
273 [ - + - + ]: 2 : if (nfreq>10 .and. my_rank == master) then
274 : : write(iout, '(a,a,a,a,a,a,a,a)' )&
275 : 2 : ' ddb_diel : the number of frequencies is larger',&
276 : 2 : ' than 10 => I will consider only',ch10,&
277 : 2 : ' the three principal directions, assume that the tensor',ch10,&
278 : 2 : ' is diagonalized, and give dielectric constant and ',ch10,&
279 : 4 : ' reflectivities.'
280 : : write(iout, '(a,a)' )&
281 : 2 : ' Frequency(Hartree) Dielectric constant ',&
282 : 4 : ' Reflectivity '
283 : : write(iout, '(a,a)' )&
284 : 2 : ' x y z',&
285 : 4 : ' x y z'
286 : : end if
287 : :
288 : : ! Loop on frequencies
289 [ + + ]: 214 : do ifreq=1,nfreq
290 : 206 : afreq=anaddb_dtset%frmin+difffr*(ifreq-1)
291 [ + + ]: 824 : do idir1=1,3
292 [ + + ]: 2678 : do idir2=1,3
293 : 1854 : frdiel(idir1,idir2,ifreq)=epsinf(idir1,idir2)
294 [ + + ]: 8817 : do imode=4,3*natom
295 : : ! Note that the acoustic modes are not included : their
296 : : ! oscillator strength should be exactly zero
297 : : ! Also, only the real part of oscstr is taken into account:
298 : : ! the possible imaginary parts of degenerate modes
299 : : ! will cancel.
300 : : frdiel(idir1,idir2,ifreq)=frdiel(idir1,idir2,ifreq)+&
301 : 8199 : & oscstr(1,idir1,idir2,imode) / (phfrq(imode)**2-afreq**2)*four_pi/ucvol
302 : : end do
303 : : end do
304 : : end do
305 : :
306 : : ! Write all this information (actually, there should be a choice of units for the frequencies ...
307 [ + + ]: 214 : if (nfreq>10) then
308 [ + + ]: 800 : do idir1=1,3
309 [ + + ]: 800 : if(frdiel(idir1,idir1,ifreq)<=zero)then
310 : 24 : refl(idir1)=one
311 : : else
312 : : ! See Gervais and Piriou PRB11,3944(1975) [[cite:Gervais1975]].
313 : 576 : refl(idir1)=( (sqrt(frdiel(idir1,idir1,ifreq)) -one) /(sqrt(frdiel(idir1,idir1,ifreq)) +one) )**2
314 : : end if
315 : : end do
316 [ + - ]: 200 : if (my_rank == master) then
317 [ + - + + ]: 800 : write(iout, '(7es12.4)' )afreq,(frdiel(idir1,idir1,ifreq),idir1=1,3),(refl(idir1),idir1=1,3)
318 : : end if
319 : :
320 : : else
321 [ + - ]: 6 : if (my_rank == master) then
322 : 6 : write(iout, '(a,es12.4,a)' )' Full dielectric tensor at frequency',afreq,' Hartree'
323 [ + + ]: 24 : do idir1=1,3
324 : 24 : write(iout, '(3f16.8)' ) (frdiel(idir1,idir2,ifreq),idir2=1,3)
325 : : end do
326 : 6 : write(iout, '(a)' )' '
327 : : end if
328 : : end if
329 : :
330 : : end do ! End of the loop on frequencies
331 : : end if ! End the condition on frequency-dependent dielectric tensor (dieflag=1)
332 : : end if ! dieflag/=2 .and. nph2l==0
333 : : end if
334 : :
335 : : !Calculation of the Lyddane-Sachs-Teller value of the dielectric constant at zero frequency
336 [ + + + - ]: 26 : if(nph2l/=0 .and. dieflag/=2) then
337 : :
338 : : ! Prepare the output
339 : 9 : write(message, '(a,a,a,a)' ) ch10,&
340 : 9 : ' Generalized Lyddane-Sachs-Teller relation at zero frequency :',ch10,&
341 : 18 : ' Direction Dielectric constant'
342 : 9 : call wrtout(std_out,message,'COLL')
343 : 9 : call wrtout(iout,message,'COLL')
344 : :
345 : : ! Examine every wavevector in the phonon list
346 [ + + ]: 23 : do iphl2=1,anaddb_dtset%nph2l
347 : :
348 [ + + ]: 56 : qphon(1:3)=anaddb_dtset%qph2l(1:3,iphl2)
349 : :
350 [ + + + + : 23 : if(abs(qphon(1))>DDB_QTOL .or. abs(qphon(2))>DDB_QTOL .or. abs(qphon(3))>DDB_QTOL)then
+ - ]
351 : 14 : q2=qphon(1)**2+qphon(2)**2+qphon(3)**2
352 : : eps=qphon(1)**2*epsinf(1,1)+qphon(2)**2*epsinf(2,2)+&
353 : : & qphon(3)**2*epsinf(3,3)+ 2* ( qphon(1)*qphon(2)*epsinf(1,2)+&
354 : 14 : & qphon(1)*qphon(3)*epsinf(1,3)+qphon(2)*qphon(3)*epsinf(2,3))
355 : 14 : eps=eps/q2*exp(lst(iphl2)-lst(anaddb_dtset%nph2l+1))
356 [ + - ]: 14 : if (my_rank == master) then
357 : 14 : write(iout, '(3f10.5,f16.8)' )qphon,eps
358 : 14 : write(std_out,'(3f10.5,f16.8)' )qphon,eps
359 : : end if
360 : : end if
361 : : end do
362 : : end if ! End of the condition of nph2l does not vanish for Lyddane-Sachs-Teller
363 : :
364 : :
365 [ - + ]: 26 : ABI_FREE(frdiel)
366 [ - + ]: 26 : ABI_FREE(modez)
367 [ - + ]: 26 : ABI_FREE(oscstr)
368 [ - + ]: 26 : ABI_FREE(dielt_modedecompo)
369 : :
370 : 26 : end subroutine ddb_diel
371 : : !!***
372 : :
373 : :
374 : :
375 : : !!****f* ABINIT/ddb_diel_elec
376 : : !!
377 : : !! NAME
378 : : !! ddb_diel_elec
379 : : !!
380 : : !! FUNCTION
381 : : !! Print the electronic dielectric constant (clamped ions)
382 : : !!
383 : : !! INPUTS
384 : : !! iout=unit number for outputs
385 : : !! epsinf(3,3)= epsilon^infty = electronic contribution to the
386 : : !! dielectric tensor
387 : : !!
388 : : !! OUTPUT
389 : : !!
390 : : !! SOURCE
391 : :
392 : 17 : subroutine ddb_diel_elec(iout,epsinf)
393 : :
394 : : !Arguments -------------------------------
395 : : !scalars
396 : : integer,intent(in) :: iout
397 : : !arrays
398 : : real(dp),intent(in) :: epsinf(3,3)
399 : :
400 : : !Local variables -------------------------
401 : : !scalars
402 : : integer :: idir1,idir2
403 : : character(len=500) :: message
404 : : !arrays
405 : :
406 : 17 : write(message, '(a,a)' ) ch10,' Electronic dielectric tensor'
407 : 17 : call wrtout(std_out,message,'COLL')
408 : 17 : call wrtout(iout,message,'COLL')
409 : :
410 : : !Compute the electronic contribution to the dielectric tensor
411 : : !Needs only the perturbations with E-field from the DDB
412 [ + + ]: 68 : do idir1=1,3
413 : : ! do idir2=1,3
414 : : ! epsinf(idir1,idir2)=d2cart(1,idir1,natom+2,idir2,natom+2)
415 : : ! end do
416 : 51 : write(message, '(3f16.8)' )(epsinf(idir1,idir2),idir2=1,3)
417 : 51 : call wrtout(std_out,message,'COLL')
418 : 68 : call wrtout(iout,message,'COLL')
419 : : end do
420 : 17 : call wrtout(iout, " ",'COLL')
421 : 17 : call wrtout(std_out, " ",'COLL')
422 : :
423 : 17 : end subroutine ddb_diel_elec
424 : : !!***
425 : :
426 : :
427 : :
428 : : !!****f* ABINIT/ddb_oscstr
429 : : !!
430 : : !! NAME
431 : : !! ddb_oscstr
432 : : !!
433 : : !! FUNCTION
434 : : !! Compute the oscillator strength and the mode effective charge
435 : : !!
436 : : !! INPUTS
437 : : !! displ(2,3*natom,3*natom)=
438 : : !! the displacements of atoms in cartesian coordinates.
439 : : !! The first index means either the real or the imaginary part,
440 : : !! The second index runs on the direction and the atoms displaced
441 : : !! The third index runs on the modes.
442 : : !! d2cart(2,3,mpert,3,mpert)=
443 : : !! dynamical matrix, effective charges, dielectric tensor,....
444 : : !! all in cartesian coordinates
445 : : !! iout=unit number for outputs
446 : : !! mpert =maximum number of ipert
447 : : !! natom=number of atoms in unit cell
448 : : !! phfrq(3*natom)=phonon frequencies (square root of the dynamical
449 : : !! matrix eigenvalues, except if these are negative, and in this
450 : : !! case, give minus the square root of the absolute value
451 : : !! of the matrix eigenvalues). Hartree units.
452 : : !!
453 : : !! OUTPUT
454 : : !! fact_oscstr(2,3,3*natom)=oscillator strengths for the different eigenmodes,
455 : : !! for different direction of the electric field.
456 : : !! modez(2,3,3*natom)=mode effective charges for the different eigenmodes,
457 : : !! for different directions of the electric field, following
458 : : !! the definition Eq.(53) in PRB55, 10355 (1997) [[cite:Gonze1997a]]
459 : : !! oscstr(2,3,3,3*natom)=oscillator strengths, following
460 : : !! the definition Eq.(54) in PRB55, 10355 (1997) [[cite:Gonze1997a]]
461 : : !!
462 : : !! SOURCE
463 : :
464 : 10 : subroutine ddb_oscstr(displ,d2cart,fact_oscstr,oscstr,modez,iout,mpert,natom,phfrq,ncid,my_rank)
465 : :
466 : : !Arguments -------------------------------
467 : : !scalars
468 : : integer,intent(in) :: iout,mpert,natom,ncid,my_rank
469 : : !arrays
470 : : real(dp),intent(in) :: d2cart(2,3,mpert,3,mpert)
471 : : real(dp),intent(in) :: phfrq(3*natom)
472 : : real(dp),intent(inout) :: displ(2,3*natom,3*natom)
473 : : real(dp),intent(out) :: fact_oscstr(2,3,3*natom),oscstr(2,3,3,3*natom),modez(2,3,3*natom)
474 : :
475 : : !Local variables -------------------------
476 : : !scalars
477 : : integer,parameter :: master=0
478 : : integer :: i1,idir1,idir2,imode,ipert1
479 : : integer :: ncerr
480 : : real(dp) :: usquare
481 : : logical :: t_degenerate
482 : : !arrays
483 : 10 : character(len=1),allocatable :: metacharacter(:)
484 : :
485 : : ! *********************************************************************
486 : :
487 : : ! Get the factors of the oscillator strength, and the mode effective charge for each mode
488 [ + + ]: 163 : do imode=1,3*natom
489 : : usquare=zero
490 [ + + ]: 3438 : do i1=1,3*natom
491 : 3438 : usquare=usquare+displ(1,i1,imode)*displ(1,i1,imode)+displ(2,i1,imode)*displ(2,i1,imode)
492 : : end do
493 [ + + ]: 622 : do idir2=1,3
494 [ + + ]: 1377 : fact_oscstr(:,idir2,imode)=zero
495 [ + + ]: 1377 : modez(:,idir2,imode)=zero
496 [ + + ]: 1989 : do idir1=1,3
497 [ + + ]: 11691 : do ipert1=1,natom
498 : 9855 : i1=idir1+(ipert1-1)*3
499 : : fact_oscstr(:,idir2,imode)=fact_oscstr(:,idir2,imode)+&
500 [ + + ]: 29565 : & displ(:,i1,imode)*d2cart(1,idir1,ipert1,idir2,natom+2)
501 : : modez(:,idir2,imode)=modez(:,idir2,imode)+&
502 : : & displ(:,i1,imode)*&
503 [ + + ]: 30942 : & d2cart(1,idir1,ipert1,idir2,natom+2)/sqrt(usquare)
504 : : end do
505 : : end do
506 : : end do
507 : : end do
508 : :
509 : : ! Examine the degeneracy of each mode. The portability of the echo of the mode effective
510 : : ! charges and oscillator strengths is very hard to guarantee. On the contrary,
511 : : ! the scalar reductions of these quantities are OK.
512 [ + - - + : 40 : ABI_MALLOC(metacharacter,(3*natom))
+ - + - -
+ - + ]
513 [ + + ]: 163 : do imode=1,3*natom
514 : : ! The degenerate modes are not portable
515 : 153 : t_degenerate=.false.
516 [ + + ]: 153 : if(imode>1)then
517 [ + + ]: 143 : if(phfrq(imode)-phfrq(imode-1)<tol6)t_degenerate=.true.
518 : : end if
519 [ + + ]: 153 : if(imode<3*natom)then
520 [ + + ]: 143 : if(phfrq(imode+1)-phfrq(imode)<tol6)t_degenerate=.true.
521 : : end if
522 : 153 : metacharacter(imode)=';'
523 [ + + ]: 163 : if(t_degenerate)metacharacter(imode)='-'
524 : : end do
525 : :
526 [ + - ]: 10 : if (my_rank == master) then
527 : : ! Write the mode effective charge for each mode
528 : 10 : write(iout, '(a)' )' '
529 : 10 : write(iout, '(a)' )' Mode effective charges '
530 : 10 : write(iout, '(a)' )' Mode number. x y z length '
531 [ + + ]: 163 : do imode=1,3*natom
532 : 153 : write(iout, '(a,i6,a,4f13.6)' )metacharacter(imode),imode,' ',(modez(1,idir1,imode),idir1=1,3),&
533 : 316 : & (sqrt(modez(1,1,imode)**2+modez(1,2,imode)**2+modez(1,3,imode)**2))
534 : : end do
535 : : end if ! master
536 : :
537 : : ! Get the oscillator strengths
538 [ + + ]: 163 : do imode=1,3*natom
539 [ + + ]: 622 : do idir1=1,3
540 [ + + ]: 1989 : do idir2=1,3
541 : : oscstr(1,idir1,idir2,imode)= &
542 : : & fact_oscstr(1,idir1,imode)*fact_oscstr(1,idir2,imode) +&
543 : 1377 : & fact_oscstr(2,idir1,imode)*fact_oscstr(2,idir2,imode)
544 [ + + ]: 1377 : if(abs(oscstr(1,idir1,idir2,imode))<tol14)oscstr(1,idir1,idir2,imode)=zero
545 : :
546 : : !DEBUG
547 : : ! if(idir1==1 .and. idir2==2)then
548 : : ! write(std_out,'(a,i4,a,5es16.6)')'imode=',imode,&
549 : : !& ' oscstr(1,idir1,idir2,imode), fact_oscstr(:,idir1,imode),fact_oscstr(:,idir2,imode)=',&
550 : : !& oscstr(1,idir1,idir2,imode), fact_oscstr(:,idir1,imode),fact_oscstr(:,idir2,imode)
551 : : ! endif
552 : : !ENDDEBUG
553 : :
554 : : oscstr(2,idir1,idir2,imode)= &
555 : : & fact_oscstr(1,idir1,imode)*fact_oscstr(2,idir2,imode) -&
556 : 1377 : & fact_oscstr(2,idir1,imode)*fact_oscstr(1,idir2,imode)
557 [ + - ]: 1836 : if(abs(oscstr(2,idir1,idir2,imode))<tol14)oscstr(2,idir1,idir2,imode)=zero
558 : : end do
559 : : end do
560 : : end do
561 : :
562 [ + - ]: 10 : if (my_rank == master) then
563 : : ! Write the oscillator strength for each mode
564 : 10 : write(iout, '(a)' )' '
565 : 10 : write(iout, '(a)' )' Oscillator strengths (in a.u. ; 1 a.u.=253.2638413 m3/s2). Set to zero if abs()<tol14.'
566 : 10 : write(iout, '(a)' )' Mode number. xx yy zz xy xz yz trace'
567 [ + + ]: 163 : do imode=1,3*natom
568 : : write(iout, '(a,i4,a,7es12.4)' )&
569 [ + + ]: 765 : & metacharacter(imode),imode,' Real ',(oscstr(1,idir1,idir1,imode),idir1=1,3),&
570 : 153 : & oscstr(1,1,2,imode), oscstr(1,1,3,imode),oscstr(1,2,3,imode),&
571 [ + - ]: 918 : & ((oscstr(1,1,1,imode)+oscstr(1,2,2,imode)+oscstr(1,3,3,imode)))
572 : : write(iout, '(a,a,6es12.4)' )&
573 [ + + ]: 765 : & metacharacter(imode),' Imag ',(oscstr(2,idir1,idir1,imode),idir1=1,3),&
574 [ + - ]: 928 : & oscstr(2,1,2,imode),oscstr(2,1,3,imode),oscstr(2,2,3,imode)
575 : : end do
576 : :
577 : : ! write the oscillator strength to the netcdf
578 [ + - ]: 10 : if (ncid /= nctk_noid) then
579 : : ncerr = nctk_def_arrays(ncid, [nctkarr_t("oscillator_strength", "dp", &
580 : : "complex, number_of_cartesian_directions, number_of_cartesian_directions, number_of_phonon_modes")], &
581 [ + + ]: 20 : defmode=.True.)
582 [ - + ]: 10 : NCF_CHECK(ncerr)
583 [ - + ]: 10 : NCF_CHECK(nctk_set_datamode(ncid))
584 [ - + ]: 10 : NCF_CHECK(nf90_put_var(ncid, nctk_idname(ncid, "oscillator_strength"), oscstr))
585 : : end if
586 : : end if
587 : :
588 [ - + ]: 10 : ABI_FREE(metacharacter)
589 : :
590 : 10 : end subroutine ddb_oscstr
591 : : !!***
592 : :
593 : :
594 : :
595 : : !!****f* ABINIT/alignph
596 : : !!
597 : : !! NAME
598 : : !! alignph
599 : : !!
600 : : !! FUNCTION
601 : : !! Construct linear combinations of the phonon eigendisplacements
602 : : !! of degenerate modes in order to align the mode effective charges
603 : : !! along the axes of the cartesian frame.
604 : : !!
605 : : !! INPUTS
606 : : !! amu(ntypat)=mass of the atoms (atomic mass unit)
607 : : !! displ(2,3*natom,3*natom)=
608 : : !! the displacements of atoms in cartesian coordinates.
609 : : !! The first index means either the real or the imaginary part,
610 : : !! The second index runs on the direction and the atoms displaced
611 : : !! The third index runs on the modes.
612 : : !! d2cart(2,3,mpert,3,mpert)=
613 : : !! dynamical matrix, effective charges, dielectric tensor,....
614 : : !! all in cartesian coordinates
615 : : !! mpert =maximum number of ipert
616 : : !! natom=number of atoms in unit cell
617 : : !! ntypat=number of types of atoms
618 : : !! phfrq(3*natom)=phonon frequencies (square root of the dynamical
619 : : !! matrix eigenvalues, except if these are negative, and in this
620 : : !! case, give minus the square root of the absolute value
621 : : !! of the matrix eigenvalues). Hartree units.
622 : : !! typat(natom)=integer label of each type of atom (1,2,...)
623 : : !!
624 : : !! OUTPUT
625 : : !! displ(2,3*natom,3*natom)=
626 : : !! the displacements of atoms in cartesian coordinates.
627 : : !! The eigendisplacements of degenerate modes have been aligned along
628 : : !! the cartesian axes.
629 : : !!
630 : : !! SOURCE
631 : :
632 : 33 : subroutine alignph(amu,displ,d2cart,mpert,natom,ntypat,phfrq,typat, &
633 : : silent) !optional
634 : :
635 : : !Arguments -------------------------------
636 : : !scalars
637 : : integer,intent(in) :: mpert,natom,ntypat
638 : : integer,optional,intent(in) :: silent
639 : : !arrays
640 : : integer,intent(in) :: typat(natom)
641 : : real(dp),intent(in) :: amu(ntypat),d2cart(2,3,mpert,3,mpert),phfrq(3*natom)
642 : : real(dp),intent(inout) :: displ(2,3*natom,3*natom)
643 : :
644 : : !Local variables -------------------------
645 : : !scalars
646 : : integer,parameter :: master=0
647 : : integer :: i1,idir1,idir2,ii,imode,imodex,imodey,imodez,ipert1,silent_
648 : : real(dp) :: theta
649 : : !arrays
650 : 33 : integer,allocatable :: deg(:)
651 : : real(dp) :: zvec(3,3),zvect(3,3)
652 : 33 : real(dp),allocatable :: modez(:,:,:),modezabs(:),oscstr(:,:,:),vec(:,:),vect(:,:)
653 : :
654 : : ! *********************************************************************
655 : :
656 : : !Reduce verbosity
657 : 33 : silent_=0
658 [ + + ]: 33 : if (present(silent)) silent_=silent
659 : :
660 : : !Get the oscillator strength and mode effective charge for each mode
661 [ + - - + : 132 : ABI_MALLOC(oscstr,(2,3,3*natom))
+ - + - +
- - + -
+ ]
662 [ - + + - : 66 : ABI_MALLOC(modez,(2,3,3*natom))
- + - + ]
663 [ - + + - : 99 : ABI_MALLOC(modezabs,(3*natom))
+ - + - -
+ - + ]
664 [ - + + - : 132 : ABI_MALLOC(vec,(3*natom,3))
+ - + - +
- - + -
+ ]
665 [ - + + - : 66 : ABI_MALLOC(vect,(3*natom,3))
- + - + ]
666 [ - + + - : 99 : ABI_MALLOC(deg,(3*natom))
+ - + - -
+ - + ]
667 : :
668 [ + + ]: 33 : if (silent_/=1) then
669 : 3 : write(std_out,'(a,a)')ch10,' alignph : before modifying the eigenvectors, mode number and mode effective charges :'
670 : : end if
671 [ + + ]: 591 : do imode=1,3*natom
672 : 558 : modezabs(imode)=zero
673 [ + + ]: 1674 : do ii=1,2
674 [ + + ]: 5022 : do idir2=1,3
675 : 3348 : oscstr(ii,idir2,imode)=zero
676 : 3348 : modez(ii,idir2,imode)=zero
677 [ + + ]: 13392 : do idir1=1,3
678 [ + + ]: 72360 : do ipert1=1,natom
679 : 58968 : i1=idir1+(ipert1-1)*3
680 : : oscstr(ii,idir2,imode)=oscstr(ii,idir2,imode)+&
681 : : & displ(ii,i1,imode)*&
682 : 58968 : & d2cart(1,idir1,ipert1,idir2,natom+2)
683 : : modez(ii,idir2,imode)=modez(ii,idir2,imode)+&
684 : : & displ(ii,i1,imode)*&
685 : : & d2cart(1,idir1,ipert1,idir2,natom+2)*&
686 : 69012 : & sqrt(amu(typat(ipert1))*amu_emass)
687 : : end do
688 : : end do
689 [ + + ]: 4464 : if(abs(modez(ii,idir2,imode))>modezabs(imode))modezabs(imode)=abs(modez(ii,idir2,imode))
690 : : end do
691 : : end do
692 [ + + ]: 591 : if (silent_/=1) write(std_out,'(i4,3f16.6)')imode,modez(1,:,imode)
693 : : end do
694 : :
695 : : !Find degenerate modes with non-zero mode effective charge
696 : 33 : imode = 0
697 [ + + ]: 482 : do while (imode < 3*natom)
698 : 449 : imode = imode + 1
699 [ + + ]: 482 : if (imode == 3*natom) then
700 : 10 : deg(imode) = 1
701 [ + + + + : 439 : else if (abs(phfrq(imode) - phfrq(imode+1)) > tol6 .or. modezabs(imode)<tol8 .or. modezabs(imode+1)<tol8) then
- + ]
702 : : ! Differ by phonon frequency or zero mode effective charge
703 : 336 : deg(imode) = 1
704 : : else
705 : 103 : deg(imode) = 2
706 [ + + ]: 103 : if (imode < 3*natom - 1) then
707 [ + + + - ]: 83 : if (abs(phfrq(imode) - phfrq(imode+2)) < tol6 .and. modezabs(imode+2)>tol8) then
708 : 6 : deg(imode) = 3
709 : 6 : imode = imode + 1
710 : : end if
711 : : end if
712 : 103 : imode = imode + 1
713 : : end if
714 : : end do
715 : :
716 : :
717 : : !In case of a degenerate mode, with non-zero mode effective charge, align the mode effective charge vector along
718 : : !the axes of the cartesian frame
719 : 33 : imode = 1
720 [ + + ]: 482 : do while (imode <= 3*natom)
721 : :
722 [ + + ]: 449 : if (silent_/=1) then
723 : 6 : write(std_out,'(a,a,i4,a,i2)')ch10,' Mode number ',imode,' has degeneracy ',deg(imode)
724 : 6 : write(std_out,'(a,3es16.6)') ' Mode effective charge of this mode =',modez(1,:,imode)
725 : : end if
726 : :
727 [ + + ]: 449 : if (deg(imode) == 2) then
728 : :
729 : : ! Optimize on the x direction
730 [ - + ]: 97 : if (silent_/=1) then
731 : 0 : write(std_out,'(a,3es16.6)') ' Mode effective charge of next mode =',modez(1,:,imode+1)
732 : : end if
733 [ + + ]: 97 : if (abs(modez(1,1,imode)) > tol8) then
734 : 95 : theta = atan(-modez(1,1,imode+1)/modez(1,1,imode))
735 [ + + ]: 1805 : vec(:,1) = displ(1,:,imode)
736 [ + + ]: 1805 : vec(:,2) = displ(1,:,imode+1)
737 [ + + ]: 1805 : displ(1,:,imode) = cos(theta)*vec(:,1) - sin(theta)*vec(:,2)
738 [ + + ]: 1805 : displ(1,:,imode+1) = sin(theta)*vec(:,1) + cos(theta)*vec(:,2)
739 : :
740 : : ! MR: Rotate also the imaginary part
741 [ + + ]: 1805 : vec(:,1) = displ(2,:,imode)
742 [ + + ]: 1805 : vec(:,2) = displ(2,:,imode+1)
743 [ + + ]: 1805 : displ(2,:,imode) = cos(theta)*vec(:,1) - sin(theta)*vec(:,2)
744 [ + + ]: 1805 : displ(2,:,imode+1) = sin(theta)*vec(:,1) + cos(theta)*vec(:,2)
745 : :
746 : : end if
747 : :
748 [ + + ]: 352 : else if (deg(imode) == 3) then
749 : :
750 [ + - ]: 6 : if (silent_/=1) then
751 : 6 : write(std_out,'(a,3es16.6)') ' Mode effective charge of next mode =',modez(1,:,imode+1)
752 : 6 : write(std_out,'(a,3es16.6)') ' Mode effective charge of next-next mode =',modez(1,:,imode+2)
753 : : end if
754 : :
755 : : ! Before mixing them, select the mode-effective charge vectors as being predominently "x", "y" or "z" type.
756 [ # # ]: 0 : if(abs(modez(1,1,imode))>abs(modez(1,2,imode))-tol12 .and. &
757 [ - + ]: 6 : & abs(modez(1,1,imode))>abs(modez(1,3,imode))-tol12) then
758 : 0 : imodex=imode
759 [ # # ]: 0 : if(abs(modez(1,2,imode+1))>abs(modez(1,3,imode+1))-tol12)then
760 : 0 : imodey=imode+1 ; imodez=imode+2
761 : : else
762 : 0 : imodez=imode+1 ; imodey=imode+2
763 : : end if
764 [ - + ]: 6 : else if(abs(modez(1,2,imode))>abs(modez(1,1,imode))-tol12 .and. &
765 [ + - ]: 6 : & abs(modez(1,2,imode))>abs(modez(1,3,imode))-tol12) then
766 : 0 : imodey=imode
767 [ # # ]: 0 : if(abs(modez(1,1,imode+1))>abs(modez(1,3,imode+1))-tol12)then
768 : 0 : imodex=imode+1 ; imodez=imode+2
769 : : else
770 : 0 : imodez=imode+1 ; imodex=imode+2
771 : : end if
772 : : else
773 : 6 : imodez=imode
774 [ - + ]: 6 : if(abs(modez(1,1,imode+1))>abs(modez(1,2,imode+1))-tol12)then
775 : 0 : imodex=imode+1 ; imodey=imode+2
776 : : else
777 : 6 : imodey=imode+1 ; imodex=imode+2
778 : : end if
779 : : end if
780 [ + + ]: 42 : vec(:,1)=displ(1,:,imodex)
781 [ + + ]: 42 : vec(:,2)=displ(1,:,imodey)
782 [ + + ]: 42 : vec(:,3)=displ(1,:,imodez)
783 [ + + ]: 24 : zvec(:,1)=modez(1,:,imodex)
784 [ + + ]: 24 : zvec(:,2)=modez(1,:,imodey)
785 [ + + ]: 24 : zvec(:,3)=modez(1,:,imodez)
786 : :
787 : :
788 : : ! Optimize along x : does the first vector has a component along x ?
789 [ + - ]: 6 : if (abs(zvec(1,1)) > tol8) then
790 : : ! Optimize on the (1,2) pair of modes along x
791 : 6 : theta = atan(-zvec(1,2)/zvec(1,1))
792 : 6 : zvect(:,:)=zvec(:,:)
793 [ + + ]: 24 : zvec(:,1) = cos(theta)*zvect(:,1) - sin(theta)*zvect(:,2)
794 [ + + ]: 24 : zvec(:,2) = sin(theta)*zvect(:,1) + cos(theta)*zvect(:,2)
795 [ + + + + ]: 132 : vect(:,:)=vec(:,:)
796 [ + + ]: 42 : vec(:,1) = cos(theta)*vect(:,1) - sin(theta)*vect(:,2)
797 [ + + ]: 42 : vec(:,2) = sin(theta)*vect(:,1) + cos(theta)*vect(:,2)
798 : : ! Optimize on the (1,3) pair of modes along x
799 : 6 : theta = atan(-zvec(1,3)/zvec(1,1))
800 : 6 : zvect(:,:)=zvec(:,:)
801 [ + + ]: 24 : zvec(:,1) = cos(theta)*zvect(:,1) - sin(theta)*zvect(:,3)
802 [ + + ]: 24 : zvec(:,3) = sin(theta)*zvect(:,1) + cos(theta)*zvect(:,3)
803 [ + + + + ]: 132 : vect(:,:)=vec(:,:)
804 [ + + ]: 42 : vec(:,1) = cos(theta)*vect(:,1) - sin(theta)*vect(:,3)
805 [ + + ]: 42 : vec(:,3) = sin(theta)*vect(:,1) + cos(theta)*vect(:,3)
806 [ + - ]: 6 : if (abs(zvec(2,2)) > tol8) then
807 : : ! Optimize on the (2,3) pair of modes along y
808 : 6 : theta = atan(-zvec(2,3)/zvec(2,2))
809 : 6 : zvect(:,:)=zvec(:,:)
810 [ + + ]: 24 : zvec(:,2) = cos(theta)*zvect(:,2) - sin(theta)*zvect(:,3)
811 [ + + ]: 24 : zvec(:,3) = sin(theta)*zvect(:,2) + cos(theta)*zvect(:,3)
812 [ + + + + ]: 132 : vect(:,:)=vec(:,:)
813 [ + + ]: 42 : vec(:,2) = cos(theta)*vect(:,2) - sin(theta)*vect(:,3)
814 [ + + ]: 42 : vec(:,3) = sin(theta)*vect(:,2) + cos(theta)*vect(:,3)
815 : : end if
816 : : ! Likely, the remaining is not needed ... because the vectors have been ordered in x, y, and z major component ...
817 : : ! Optimize along x : does the second vector has a component along x ?
818 [ # # ]: 0 : else if(abs(zvec(1,2)) > tol8) then
819 : : ! Optimize on the (2,3) pair of modes along x
820 : 0 : theta = atan(-zvec(1,3)/zvec(1,2))
821 : 0 : zvect(:,:)=zvec(:,:)
822 [ # # ]: 0 : zvec(:,2) = cos(theta)*zvect(:,2) - sin(theta)*zvect(:,3)
823 [ # # ]: 0 : zvec(:,3) = sin(theta)*zvect(:,2) + cos(theta)*zvect(:,3)
824 [ # # # # ]: 0 : vect(:,:)=vec(:,:)
825 [ # # ]: 0 : vec(:,2) = cos(theta)*vect(:,2) - sin(theta)*vect(:,3)
826 [ # # ]: 0 : vec(:,3) = sin(theta)*vect(:,2) + cos(theta)*vect(:,3)
827 : : ! Optimize on the (1,3) pair of modes along y
828 [ # # ]: 0 : if (abs(zvec(2,1)) > tol8) then
829 : 0 : theta = atan(-zvec(2,3)/zvec(2,1))
830 : 0 : zvect(:,:)=zvec(:,:)
831 [ # # ]: 0 : zvec(:,1) = cos(theta)*zvect(:,1) - sin(theta)*zvect(:,3)
832 [ # # ]: 0 : zvec(:,3) = sin(theta)*zvect(:,1) + cos(theta)*zvect(:,3)
833 [ # # # # ]: 0 : vect(:,:)=vec(:,:)
834 [ # # ]: 0 : vec(:,1) = cos(theta)*vect(:,1) - sin(theta)*vect(:,3)
835 [ # # ]: 0 : vec(:,3) = sin(theta)*vect(:,1) + cos(theta)*vect(:,3)
836 : : end if
837 : : ! We are left with the pair of vectors (2,3)
838 [ # # ]: 0 : else if (abs(zvec(2,2)) > tol8) then
839 : : ! Optimize on the (2,3) pair of modes along y
840 : 0 : theta = atan(-zvec(2,3)/zvec(2,2))
841 : 0 : zvect(:,:)=zvec(:,:)
842 [ # # ]: 0 : zvec(:,2) = cos(theta)*zvect(:,2) - sin(theta)*zvect(:,3)
843 [ # # ]: 0 : zvec(:,3) = sin(theta)*zvect(:,2) + cos(theta)*zvect(:,3)
844 [ # # # # ]: 0 : vect(:,:)=vec(:,:)
845 [ # # ]: 0 : vec(:,2) = cos(theta)*vect(:,2) - sin(theta)*vect(:,3)
846 [ # # ]: 0 : vec(:,3) = sin(theta)*vect(:,2) + cos(theta)*vect(:,3)
847 : : end if
848 : :
849 [ + + ]: 42 : displ(1,:,imodex)=vec(:,1)
850 [ + + ]: 42 : displ(1,:,imodey)=vec(:,2)
851 [ + + ]: 42 : displ(1,:,imodez)=vec(:,3)
852 : :
853 : : ! Previous coding, from Marek. Apparently, break the orthogonalization of vectors ...
854 : : ! do ii = 1,3
855 : : ! coeff(:) = 0._dp
856 : : ! if (ii == 1) then
857 : : ! jj = 2 ; kk = 3
858 : : ! else if (ii == 2) then
859 : : ! jj = 1 ; kk = 3
860 : : ! else
861 : : ! jj = 1 ; kk = 2
862 : : ! end if
863 : : ! coeff(ii) = 1._dp
864 : : ! c1 = modez(1,jj,imode+ii-1)
865 : : ! c2 = modez(1,jj,imode+jj-1)
866 : : ! c3 = modez(1,jj,imode+kk-1)
867 : : ! c4 = modez(1,kk,imode+ii-1)
868 : : ! c5 = modez(1,kk,imode+jj-1)
869 : : ! c6 = modez(1,kk,imode+kk-1)
870 : : ! dtm = c2*c6 - c3*c5
871 : : ! if (abs(dtm) > tol8) then
872 : : ! coeff(jj) = (c3*c4 - c1*c6)/dtm
873 : : ! coeff(kk) = (c1*c5 - c2*c4)/dtm
874 : : ! end if
875 : : ! mod_ = sqrt(1._dp + coeff(jj)*coeff(jj) + coeff(kk)*coeff(kk))
876 : : ! coeff(:) = coeff(:)/mod_
877 : : ! displ(1,:,imode+ii-1) = coeff(1)*vec(1,:) + coeff(2)*vec(2,:) + &
878 : : !& coeff(3)*vec(3,:)
879 : : ! end do
880 : :
881 : : end if ! if deg mode
882 : :
883 : 449 : imode = imode + deg(imode)
884 : :
885 : : end do
886 : :
887 [ + + ]: 33 : if (silent_/=1) then
888 : 3 : write(std_out,'(a,a)')ch10,' alignph : after modifying the eigenvectors, mode number and mode effective charges :'
889 : : end if
890 [ + + ]: 591 : do imode=1,3*natom
891 [ + + ]: 1674 : do ii=1,2
892 [ + + ]: 5022 : do idir2=1,3
893 : 3348 : modez(ii,idir2,imode)=zero
894 [ + + ]: 14508 : do idir1=1,3
895 [ + + ]: 72360 : do ipert1=1,natom
896 : 58968 : i1=idir1+(ipert1-1)*3
897 : : modez(ii,idir2,imode)=modez(ii,idir2,imode)+&
898 : : & displ(ii,i1,imode)*&
899 : : & d2cart(1,idir1,ipert1,idir2,natom+2)*&
900 : 69012 : & sqrt(amu(typat(ipert1))*amu_emass)
901 : : end do
902 : : end do
903 : : end do
904 : : end do
905 [ + + ]: 591 : if (silent_/=1) write(std_out,'(i4,3f16.6)')imode,modez(1,:,imode)
906 : : end do
907 : :
908 [ - + ]: 33 : ABI_FREE(deg)
909 [ - + ]: 33 : ABI_FREE(oscstr)
910 [ - + ]: 33 : ABI_FREE(modez)
911 [ - + ]: 33 : ABI_FREE(modezabs)
912 [ - + ]: 33 : ABI_FREE(vec)
913 [ - + ]: 33 : ABI_FREE(vect)
914 : :
915 : 33 : end subroutine alignph
916 : : !!***
917 : :
918 : : end module m_ddb_diel
919 : : !!***
|