Branch data Line data Source code
1 : : !!****f* ABINIT/m_harmonics_terms
2 : : !!
3 : : !! NAME
4 : : !! m_harmonics_term
5 : : !!
6 : : !! FUNCTION
7 : : !! Module with datatype and tools for the harmonics terms
8 : : !!
9 : : !! COPYRIGHT
10 : : !! Copyright (C) 2010-2026 ABINIT group (AM)
11 : : !! This file is distributed under the terms of the
12 : : !! GNU General Public Licence, see ~abinit/COPYING
13 : : !! or http://www.gnu.org/copyleft/gpl.txt .
14 : : !! For the initials of contributors, see ~abinit/doc/developers/contributors.txt .
15 : : !!
16 : : !! SOURCE
17 : :
18 : :
19 : : #if defined HAVE_CONFIG_H
20 : : #include "config.h"
21 : : #endif
22 : :
23 : : #include "abi_common.h"
24 : :
25 : : module m_harmonics_terms
26 : :
27 : : use defs_basis
28 : : use m_errors
29 : : use m_abicore
30 : : use m_supercell,only: getPBCIndexes_supercell
31 : : use m_xmpi,only : xmpi_sum
32 : : use m_ifc
33 : :
34 : : implicit none
35 : :
36 : : public :: harmonics_terms_init
37 : : public :: harmonics_terms_free
38 : : public :: harmonics_terms_applySumRule
39 : : public :: harmonics_terms_evaluateIFC
40 : : public :: harmonics_terms_evaluateElastic
41 : : public :: harmonics_terms_setEffectiveCharges
42 : : public :: harmonics_terms_setDynmat
43 : : public :: harmonics_terms_setInternalStrain
44 : : !!***
45 : :
46 : : !!****t* m_harmonics_terms/harmonics_terms_type
47 : : !! NAME
48 : : !! harmonics_terms_type
49 : : !!
50 : : !! FUNCTION
51 : : !! datatype for harmonic part of effective potential.
52 : : !!
53 : : !! SOURCE
54 : :
55 : : type, public :: harmonics_terms_type
56 : :
57 : : integer :: nqpt
58 : : ! Number of qpoints
59 : :
60 : : real(dp) :: epsilon_inf(3,3)
61 : : ! epsilon_inf(3,3)
62 : : ! Dielectric tensor
63 : :
64 : : real(dp) :: elastic_constants(6,6)
65 : : ! elastic_constant(6,6)
66 : : ! Elastic tensor Hartree
67 : :
68 : : real(dp), allocatable :: strain_coupling(:,:,:)
69 : : ! strain_coupling(6,3,natom)
70 : : ! internal strain tensor
71 : :
72 : : real(dp), allocatable :: zeff(:,:,:)
73 : : ! zeff(3,3,natom) Effective charges
74 : :
75 : : type(ifc_type) :: ifcs
76 : : ! type with ifcs constants (short + ewald)
77 : : ! also contains the number of cell and the indexes
78 : :
79 : : real(dp), allocatable :: qpoints(:,:)
80 : : ! qph1l(3,nqpt)
81 : : ! List of qpoints wavevectors
82 : :
83 : : real(dp), allocatable :: dynmat(:,:,:,:,:,:)
84 : : ! dynmat(2,3,natom,3,natom,nqpt)
85 : : ! dynamical matrix for each q points
86 : :
87 : : real(dp), allocatable :: phfrq(:,:)
88 : : ! phfrq(3*natom,nqpt)
89 : : ! array with all phonons frequencies for each q points in Hartree/cm
90 : :
91 : : end type harmonics_terms_type
92 : : !!***
93 : :
94 : : CONTAINS !===========================================================================================
95 : :
96 : :
97 : : !!****f* m_harmonics_terms/harmonics_terms_init
98 : : !!
99 : : !! NAME
100 : : !! harmonics_terms_init
101 : : !!
102 : : !! FUNCTION
103 : : !! Initialize harmonics_terms datatype
104 : : !!
105 : : !! INPUTS
106 : : !! ifc<type(ifc_type)> = interatomic forces constants
107 : : !! natom = number of atoms in primitive cell
108 : : !! nrpt = number rpt (cell) in the ifc
109 : : !! dynmat(2,3,natom,3,natom,3,nqpt) = optional, dynamical matricies for each q-point
110 : : !! epsilon_inf(3,3) = optional, dielectric tensor
111 : : !! elastic_constant(6,6) = optional, elastic constant
112 : : !! strain_coupling(6,3,natom) = optional, internal strain coupling parameters
113 : : !! nqpt = optional, number of q-points
114 : : !! phfrq(3*natom,nqpt) = optional,phonons frequencies for each q points in Hartree/cm
115 : : !! qpoints(3,nqpt) = list of qpoints wavevectors
116 : : !! zeff(3,3,natom) = optional,effective charges
117 : : !!
118 : : !! OUTPUT
119 : : !! harmonics_terms<type(harmonics_terms_type)> = harmonics_terms datatype to be initialized
120 : : !!
121 : : !! SOURCE
122 : :
123 [ - + - + : 608 : subroutine harmonics_terms_init(harmonics_terms,ifcs,natom,nrpt,&
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
+ + + + ]
124 [ - + - - : 76 : & dynmat,epsilon_inf,elastic_constants,strain_coupling,&
- - ]
125 [ - + - + ]: 76 : & nqpt,phfrq,qpoints,zeff)
126 : :
127 : : implicit none
128 : :
129 : : !Arguments ------------------------------------
130 : : !scalars
131 : : integer, intent(in) :: natom,nrpt
132 : : !arrays
133 : : type(ifc_type),intent(in) :: ifcs
134 : : type(harmonics_terms_type), intent(out) :: harmonics_terms
135 : : integer, optional,intent(in) :: nqpt
136 : : real(dp),optional,intent(in) :: epsilon_inf(3,3),dynmat(:,:,:,:,:,:)
137 : : real(dp),optional,intent(in) :: elastic_constants(6,6)
138 : : real(dp),optional,intent(in) :: strain_coupling(6,3,natom),zeff(3,3,natom)
139 : : real(dp),optional,intent(in) :: phfrq(:,:),qpoints(:,:)
140 : : !Local variables-------------------------------
141 : : !scalar
142 : : !arrays
143 : : character(len=500) :: msg
144 : :
145 : : ! *************************************************************************
146 : :
147 : 76 : call harmonics_terms_free(harmonics_terms)
148 : :
149 : : ! Do some Checks
150 [ - + ]: 76 : if (natom < 1) then
151 : : write(msg, '(a,a,a,i10,a)' )&
152 : 0 : & 'The cell must have at least one atom.',ch10,&
153 : 0 : & 'The number of atom is ',natom,'.'
154 : 0 : ABI_BUG(msg)
155 : : end if
156 : :
157 [ - + ]: 76 : if (nrpt < 1) then
158 : : write(msg, '(a,a,a,i10,a)' )&
159 : 0 : & 'The cell must have at least one rpt point.',ch10,&
160 : 0 : & 'The number of rpt points is ',nrpt,'.'
161 : 0 : ABI_BUG(msg)
162 : : end if
163 : :
164 [ - + ]: 76 : if (nrpt /= ifcs%nrpt) then
165 : : write(msg, '(3a,i5,a,i5,a)' )&
166 : 0 : & 'nrpt must have the same dimension as ifcs.',ch10,&
167 : 0 : & 'The number of cell is ',nrpt,' instead of ',ifcs%nrpt,'.'
168 : 0 : ABI_BUG(msg)
169 : : end if
170 : :
171 [ + - - - : 76 : if(present(nqpt).and.(.not.present(dynmat).or.&
- - ]
172 : : & .not.present(qpoints) .or.&
173 : : & .not.present(phfrq)))then
174 : : write(msg, '(a)' )&
175 : 0 : & 'nqpt is specified but dynamt,qpoints or phfrq are not.'
176 : 0 : ABI_BUG(msg)
177 : : end if
178 : :
179 [ + - - + ]: 76 : if(.not.present(nqpt).and.(present(dynmat).or.&
180 : : & present(qpoints) .or.&
181 : : & present(phfrq)))then
182 : : write(msg, '(a)' )&
183 : 0 : & ' dynamt,qpoints or phfrq are specified but nqpt is not.'
184 : 0 : ABI_BUG(msg)
185 : : end if
186 : :
187 : : !Set number of cell
188 : 76 : harmonics_terms%ifcs%nrpt = nrpt
189 : :
190 : : !Allocation of total ifc
191 [ - + + - : 456 : ABI_MALLOC(harmonics_terms%ifcs%atmfrc,(3,natom,3,natom,nrpt))
+ - - + +
- - + + -
+ - + - -
+ - + -
+ ]
192 [ + + + + : 922666 : harmonics_terms%ifcs%atmfrc(:,:,:,:,:) = ifcs%atmfrc(:,:,:,:,:)
+ + + + +
+ ]
193 : :
194 : : !Allocation of ewald part of ifc
195 [ - + + - : 304 : ABI_MALLOC(harmonics_terms%ifcs%ewald_atmfrc,(3,natom,3,natom,nrpt))
- + + - -
+ + - - +
- + - + ]
196 [ + + + + : 922666 : harmonics_terms%ifcs%ewald_atmfrc(:,:,:,:,:) = ifcs%ewald_atmfrc(:,:,:,:,:)
+ + + + +
+ ]
197 : :
198 : : !Allocation of short range part of ifc
199 [ - + + - : 304 : ABI_MALLOC(harmonics_terms%ifcs%short_atmfrc,(3,natom,3,natom,nrpt))
- + + - -
+ + - - +
- + - + ]
200 [ + + + + : 922666 : harmonics_terms%ifcs%short_atmfrc(:,:,:,:,:) = ifcs%short_atmfrc(:,:,:,:,:)
+ + + + +
+ ]
201 : :
202 : : !Allocation of cell of ifc
203 [ - + + - : 228 : ABI_MALLOC(harmonics_terms%ifcs%cell,(3,nrpt))
+ - + - -
+ - + -
+ ]
204 [ + + + + ]: 8772 : harmonics_terms%ifcs%cell(:,:) = ifcs%cell(:,:)
205 : :
206 : : !Allocation of the dynamical matrix
207 : 76 : harmonics_terms%nqpt = 0
208 [ - + - - ]: 76 : if(present(nqpt).and.present(dynmat).and.present(qpoints).and.present(phfrq))then
209 : : call harmonics_terms_setDynmat(dynmat,harmonics_terms,natom,nqpt,&
210 : 0 : & harmonics_terms%phfrq,harmonics_terms%qpoints)
211 : : end if
212 : :
213 : : !Allocation of the elastic constants
214 [ + + + + ]: 3268 : harmonics_terms%elastic_constants = zero
215 [ - + ]: 76 : if (present(elastic_constants)) then
216 [ # # # # ]: 0 : harmonics_terms%elastic_constants = elastic_constants
217 : : end if
218 : :
219 : : !Allication of the dielectric tensor
220 [ + + + + ]: 988 : harmonics_terms%epsilon_inf = zero
221 [ - + ]: 76 : if (present(epsilon_inf)) then
222 [ # # # # ]: 0 : harmonics_terms%epsilon_inf = epsilon_inf
223 : : end if
224 : :
225 : : !Allocation of Effective charges array
226 [ - + + - : 228 : ABI_MALLOC(harmonics_terms%zeff,(3,3,natom))
+ - + - -
+ - + -
+ ]
227 [ + + + + : 5198 : harmonics_terms%zeff = zero
+ + ]
228 [ - + ]: 76 : if (present(zeff)) then
229 : 0 : call harmonics_terms_setEffectiveCharges(harmonics_terms,natom,zeff)
230 [ # # # # : 0 : harmonics_terms%zeff = zeff
# # # # #
# # # # #
# # ]
231 : : end if
232 : :
233 : : !Allocation of internal strain tensor
234 [ - + + - : 228 : ABI_MALLOC(harmonics_terms%strain_coupling,(6,3,natom))
+ - + - -
+ - + -
+ ]
235 [ + + + + : 8744 : harmonics_terms%strain_coupling = zero
+ + ]
236 [ - + ]: 76 : if (present(strain_coupling)) then
237 : 0 : call harmonics_terms_setInternalStrain(harmonics_terms,natom,strain_coupling)
238 : : end if
239 : :
240 [ - + - + ]: 76 : end subroutine harmonics_terms_init
241 : : !!***
242 : :
243 : :
244 : : !****f* m_harmonics_terms/harmonics_terms_free
245 : : !!
246 : : !! NAME
247 : : !! harmonics_terms_free
248 : : !!
249 : : !! FUNCTION
250 : : !! deallocate all dynamic memory for this harmonic datatype
251 : : !!
252 : : !! INPUTS
253 : : !! harmonics_terms<type(harmonics_terms_type)> = harmonics_terms datatype to be free
254 : : !!
255 : : !! OUTPUT
256 : : !! harmonics_terms<type(harmonics_terms_type)> = harmonics_terms datatype to be free
257 : : !!
258 : : !! SOURCE
259 : :
260 : 610 : subroutine harmonics_terms_free(harmonics_terms)
261 : :
262 : : implicit none
263 : :
264 : : !Arguments ------------------------------------
265 : : !scalars
266 : : !array
267 : : type(harmonics_terms_type), intent(inout) :: harmonics_terms
268 : : !Local variables-------------------------------
269 : : !scalars
270 : : !array
271 : :
272 : : ! *************************************************************************
273 : :
274 : 610 : harmonics_terms%nqpt = 0
275 [ + + + + ]: 26230 : harmonics_terms%elastic_constants = zero
276 [ + + + + ]: 7930 : harmonics_terms%epsilon_inf = zero
277 : :
278 [ + + ]: 610 : if(allocated(harmonics_terms%zeff))then
279 [ + + + + : 7203 : harmonics_terms%zeff=zero
+ + ]
280 : 105 : ABI_FREE(harmonics_terms%zeff)
281 : : end if
282 : :
283 [ + + ]: 610 : if(allocated(harmonics_terms%strain_coupling)) then
284 [ + + + + : 12117 : harmonics_terms%strain_coupling=zero
+ + ]
285 : 105 : ABI_FREE(harmonics_terms%strain_coupling)
286 : : end if
287 : :
288 [ + + ]: 610 : if(allocated(harmonics_terms%dynmat))then
289 [ + + + + : 185742 : harmonics_terms%dynmat=zero
+ + + + +
+ + + ]
290 : 105 : ABI_FREE(harmonics_terms%dynmat)
291 : : end if
292 : :
293 [ + + ]: 610 : if(allocated(harmonics_terms%phfrq))then
294 [ + + + + ]: 3904 : harmonics_terms%phfrq=zero
295 : 105 : ABI_FREE(harmonics_terms%phfrq)
296 : : end if
297 : :
298 [ + + ]: 610 : if(allocated(harmonics_terms%qpoints))then
299 [ + + + + ]: 1165 : harmonics_terms%qpoints=zero
300 : 105 : ABI_FREE(harmonics_terms%qpoints)
301 : : end if
302 : :
303 : 610 : call harmonics_terms%ifcs%free()
304 : :
305 : 610 : end subroutine harmonics_terms_free
306 : : !!***
307 : :
308 : : !****f* m_harmonics_terms/harmonics_terms_setInternalStrain
309 : : !!
310 : : !! NAME
311 : : !! harmonics_terms_setInternalStrain
312 : : !!
313 : : !! FUNCTION
314 : : !! Set the internal strain to the harmonics_terms
315 : : !!
316 : : !! INPUTS
317 : : !! natom = number of atoms
318 : : !! strain_coupling(6,3,natom) = internal strain coupling parameters
319 : : !!
320 : : !! OUTPUT
321 : : !! harmonics_terms<type(harmonics_terms_type)> = harmonics_terms datatype
322 : : !!
323 : : !! SOURCE
324 : :
325 [ - + ]: 76 : subroutine harmonics_terms_setInternalStrain(harmonics_terms,natom,strain_coupling)
326 : :
327 : : implicit none
328 : :
329 : : !Arguments ------------------------------------
330 : : !scalars
331 : : integer,intent(in) :: natom
332 : : !array
333 : : real(dp),intent(in) :: strain_coupling(:,:,:)
334 : : type(harmonics_terms_type), intent(inout) :: harmonics_terms
335 : : !Local variables-------------------------------
336 : : !scalars
337 : : !array
338 : : character(len=500) :: msg
339 : :
340 : : ! *************************************************************************
341 : :
342 : : ! 0-Checks inputs
343 [ - + ]: 76 : if(natom /= size(strain_coupling,3)) then
344 : : write(msg, '(a)' )&
345 : 0 : & ' natom has not the same size strain_coupling array. '
346 : 0 : ABI_BUG(msg)
347 : : end if
348 : :
349 : : ! 1-deallocate old array
350 [ + - ]: 76 : if(allocated(harmonics_terms%strain_coupling))then
351 : 76 : ABI_FREE(harmonics_terms%strain_coupling)
352 : : end if
353 : :
354 : : ! 2-allocate and copy the new array
355 [ - + + - : 228 : ABI_MALLOC(harmonics_terms%strain_coupling,(6,3,natom))
+ - + - -
+ - + -
+ ]
356 [ + + + + : 8744 : harmonics_terms%strain_coupling(:,:,:) = strain_coupling(:,:,:)
+ + ]
357 : :
358 : 76 : end subroutine harmonics_terms_setInternalStrain
359 : : !!***
360 : :
361 : :
362 : : !****f* m_harmonics_terms/harmonics_terms_setEffectiveCharges
363 : : !!
364 : : !! NAME
365 : : !! harmonics_terms_setEffectiveCharges
366 : : !!
367 : : !! FUNCTION
368 : : !! Set the effectives charges to the harmonics_terms
369 : : !!
370 : : !! INPUTS
371 : : !! natom = number of atoms
372 : : !! zeff(3,natom) = effective charges
373 : : !!
374 : : !! OUTPUT
375 : : !! harmonics_terms<type(harmonics_terms_type)> = harmonics_terms datatype
376 : : !!
377 : : !! SOURCE
378 : :
379 [ - + ]: 76 : subroutine harmonics_terms_setEffectiveCharges(harmonics_terms,natom,zeff)
380 : :
381 : : implicit none
382 : :
383 : : !Arguments ------------------------------------
384 : : !scalars
385 : : integer,intent(in) :: natom
386 : : !array
387 : : real(dp),intent(in) :: zeff(:,:,:)
388 : : type(harmonics_terms_type), intent(inout) :: harmonics_terms
389 : : !Local variables-------------------------------
390 : : !scalars
391 : : !array
392 : : character(len=500) :: msg
393 : : ! *************************************************************************
394 : :
395 : : ! 0-Checks inputs
396 [ - + ]: 76 : if(natom /= size(zeff,3)) then
397 : : write(msg, '(a)' )&
398 : 0 : & ' natom has not the same size zeff array. '
399 : 0 : ABI_BUG(msg)
400 : : end if
401 : :
402 : : ! 1-deallocate old array
403 [ + - ]: 76 : if(allocated(harmonics_terms%zeff))then
404 : 76 : ABI_FREE(harmonics_terms%zeff)
405 : : end if
406 : :
407 : : ! 2-allocate and copy the new array
408 [ - + + - : 228 : ABI_MALLOC(harmonics_terms%zeff,(3,3,natom))
+ - + - -
+ - + -
+ ]
409 [ + + + + : 5198 : harmonics_terms%zeff(:,:,:) = zeff(:,:,:)
+ + ]
410 : :
411 : :
412 : 76 : end subroutine harmonics_terms_setEffectiveCharges
413 : : !!***
414 : :
415 : : !****f* m_harmonics_terms/harmonics_terms_setDynmat
416 : : !!
417 : : !! NAME
418 : : !! harmonics_terms_setDynmat
419 : : !!
420 : : !! FUNCTION
421 : : !! Set the dynamical matricies to the harmonics_terms
422 : : !!
423 : : !! INPUTS
424 : : !! natom = number of atoms
425 : : !! nqpt = number of qpoints
426 : : !! dynmat(2,3,natom,3,natom,nqpt) = dynamical matrix in cartesian coordinates
427 : : !! phfrq(3*natom,nqpt) = frequency in hartree
428 : : !! qpoints(3,nqpt) = list of qpoints
429 : : !!
430 : : !! OUTPUT
431 : : !! harmonics_terms<type(harmonics_terms_type)> = harmonics_terms datatype
432 : : !!
433 : : !! SOURCE
434 : :
435 [ - + - + : 76 : subroutine harmonics_terms_setDynmat(dynmat,harmonics_terms,natom,nqpt,phfrq,qpoints)
- + ]
436 : :
437 : : implicit none
438 : :
439 : : !Arguments ------------------------------------
440 : : !scalars
441 : : integer,intent(in) :: natom,nqpt
442 : : !array
443 : : real(dp),intent(in) :: dynmat(:,:,:,:,:,:)
444 : : real(dp),intent(in) :: qpoints(:,:)
445 : : real(dp),intent(in) :: phfrq(:,:)
446 : : type(harmonics_terms_type), intent(inout) :: harmonics_terms
447 : : !Local variables-------------------------------
448 : : !scalars
449 : : !array
450 : : character(len=500) :: msg
451 : : ! *************************************************************************
452 : :
453 : : ! 0-Checks inputs
454 [ + - - + ]: 76 : if((natom /= size(dynmat,3)).or.(natom /= size(dynmat,5))) then
455 : : write(msg, '(a)' )&
456 : 0 : & ' natom has not the same size dynmat array. '
457 : 0 : ABI_BUG(msg)
458 : : end if
459 : :
460 [ - + ]: 76 : if (nqpt /= size(dynmat,6))then
461 : : write(msg, '(a)' )&
462 : 0 : & ' nqpt has not the same size dynmat array. '
463 : 0 : ABI_BUG(msg)
464 : : end if
465 : :
466 [ - + ]: 76 : if (nqpt /= size(qpoints,2))then
467 : : write(msg, '(a)' )&
468 : 0 : & ' nqpt has not the same size qpoints array. '
469 : 0 : ABI_BUG(msg)
470 : : end if
471 : :
472 [ - + ]: 76 : if (nqpt /= size(phfrq,2))then
473 : : write(msg, '(a)' )&
474 : 0 : & ' nqpt has not the same size phfrq array. '
475 : 0 : ABI_BUG(msg)
476 : : end if
477 : :
478 : : ! 1-deallocate old array
479 [ - + ]: 76 : if(allocated(harmonics_terms%dynmat))then
480 : 0 : ABI_FREE(harmonics_terms%dynmat)
481 : : end if
482 : :
483 [ - + ]: 76 : if(allocated(harmonics_terms%phfrq))then
484 : 0 : ABI_FREE(harmonics_terms%phfrq)
485 : : end if
486 : :
487 [ - + ]: 76 : if(allocated(harmonics_terms%qpoints))then
488 : 0 : ABI_FREE(harmonics_terms%qpoints)
489 : : end if
490 : :
491 : : ! 2-allocate and copy the new array
492 : 76 : harmonics_terms%nqpt = nqpt
493 : :
494 [ - + + - : 456 : ABI_MALLOC(harmonics_terms%dynmat,(2,3,natom,3,natom,nqpt))
+ - - + +
- + + + -
+ - + + -
+ - + -
+ ]
495 [ + + + + : 126404 : harmonics_terms%dynmat(:,:,:,:,:,:) = dynmat(:,:,:,:,:,:)
+ + + + +
+ + + ]
496 : :
497 [ + - - + : 304 : ABI_MALLOC(harmonics_terms%phfrq,(3*natom,nqpt))
+ - + + +
- + - + +
- + - + -
+ ]
498 [ + + + + ]: 2662 : harmonics_terms%phfrq(:,:) = phfrq(:,:)
499 : :
500 [ + + + - : 228 : ABI_MALLOC(harmonics_terms%qpoints,(3,nqpt))
+ - + + -
+ - + -
+ ]
501 [ + + + + ]: 796 : harmonics_terms%qpoints(:,:) = qpoints(:,:)
502 : :
503 : 76 : end subroutine harmonics_terms_setDynmat
504 : : !!***
505 : : !!****f* m_harmonics_terms/harmonics_terms_evaluateIFC
506 : : !! NAME
507 : : !! harmonics_terms_evaluateIFC
508 : : !!
509 : : !! FUNCTION
510 : : !! This fonction compute the contribution of the ifc harmonic part of
511 : : !! the energy and forces.
512 : : !!
513 : : !! INPUTS
514 : : !! atmfrc(3,natom_uc,3,natom_uc,nrpt) = atomic force constants
515 : : !! disp(3,natom_sc) = atomics displacement between configuration and the reference
516 : : !! ncell = total number of cell to treat
517 : : !! nrpt = total number of rpt to treat
518 : : !! natom_sc = number of atoms in the supercell
519 : : !! natom_uc = number of atoms in the unit cell
520 : : !! nrpt = number of rpt
521 : : !! atmrpt_index(nrpt,cell) = For each cell in the supercell and each rpt,
522 : : !! give the index of the first atoms in the rpt cell
523 : : !! rpt(nrpt) = index of rpt in atmfrc (6th dimension)
524 : : !! index_cells(3,ncell) = indexes of the cells into supercell (-1 -1 -1 ,...,1 1 1)
525 : : !! comm=MPI communicator
526 : : !!
527 : : !! OUTPUT
528 : : !! energy = contribution of the ifc to the energy
529 : : !! fcart(3,natom) = contribution of the ifc to the forces
530 : : !!
531 : : !! PARENT
532 : : !! effective_potential_evaluate
533 : : !!
534 : : !! SOURCE
535 : :
536 : 27038 : subroutine harmonics_terms_evaluateIFC(atmfrc,disp,energy,fcart,natom_sc,natom_uc,&
537 : 13519 : & ncell,nrpt,atmrpt_index,index_cells,sc_size,rpt,comm)
538 : :
539 : : implicit none
540 : :
541 : : !Arguments -------------------------------
542 : : ! scalars
543 : : real(dp),intent(out) :: energy
544 : : integer,intent(in) :: natom_uc,natom_sc,ncell,nrpt
545 : : integer,intent(in) :: comm
546 : : ! array
547 : : integer,intent(in) :: sc_size(3),atmrpt_index(nrpt,ncell)
548 : : integer,intent(in) :: index_cells(4,ncell),rpt(nrpt)
549 : : real(dp),intent(in) :: atmfrc(3,natom_uc,3,natom_uc,nrpt)
550 : : real(dp),intent(in) :: disp(3,natom_sc)
551 : : real(dp),intent(out) :: fcart(3,natom_sc)
552 : :
553 : : !Local variables-------------------------------
554 : : ! scalar
555 : : integer :: i1,i2,i3,ia,ib,icell,ierr,irpt,irpt_tmp,ii,jj,kk,ll
556 : : integer :: mu,nu
557 : : real(dp):: disp1,disp2,ifc,tmp_etot1,tmp_etot2
558 : : !Variables for separation of short and dipdip ifc contribution
559 : : !real(dp):: short_ifc,ewald_ifc
560 : : !real(dp):: tmp_ewald1,tmp_ewald2,tmp_short1,tmp_short2
561 : : ! array
562 : : character(500) :: msg
563 : :
564 : : ! *************************************************************************
565 : :
566 [ + + + - : 54076 : if (any(sc_size <= 0)) then
- + ]
567 : 0 : write(msg,'(a,a)')' sc_size can not be inferior or equal to zero'
568 : 0 : ABI_ERROR(msg)
569 : : end if
570 : :
571 : : ! Initialisation of variables
572 : 13519 : energy = zero
573 [ + + + + ]: 36076719 : fcart(:,:) = zero
574 : :
575 [ + + ]: 1786383 : do icell = 1,ncell
576 : 1772864 : i1 = index_cells(1,icell)
577 : 1772864 : i2 = index_cells(2,icell)
578 : 1772864 : i3 = index_cells(3,icell)
579 : : ! index of the first atom in the current cell
580 : 1772864 : ii = index_cells(4,icell)
581 [ + + ]: 377817063 : do irpt_tmp = 1,nrpt
582 : 376030680 : irpt = rpt(irpt_tmp)
583 : : ! index of the first atom in the irpt cell
584 : 376030680 : jj = atmrpt_index(irpt_tmp,icell)
585 : : ! Loop over the atom in the cell
586 [ + + ]: 2264040144 : do ib = 1, natom_uc
587 : 1886236600 : ll = jj + ib
588 [ + + ]: 7920977080 : do nu=1,3
589 : 5658709800 : disp2 = disp(nu,ll)
590 [ + + ]: 36206405800 : do ia = 1, natom_uc
591 : 28661459400 : kk = ii + ia
592 [ + + ]: >12030*10^7 : do mu=1,3
593 : 85984378200 : disp1 = disp(mu,kk)
594 : 85984378200 : ifc = atmfrc(mu,ia,nu,ib,irpt)
595 : :
596 : : ! if(abs(ifc) > tol10)then
597 : 85984378200 : tmp_etot1 = disp2 * ifc
598 : : ! accumule energy
599 : 85984378200 : tmp_etot2 = disp1*tmp_etot1
600 : 85984378200 : energy = energy + tmp_etot2
601 : : ! accumule forces
602 : >11464*10^7 : fcart(mu,kk) = fcart(mu,kk) + tmp_etot1
603 : : ! end if
604 : : end do
605 : : end do
606 : : end do
607 : : end do
608 : : end do
609 : : end do
610 : :
611 : 13519 : energy = half * energy
612 : : ! MPI_SUM
613 : 13519 : call xmpi_sum(energy, comm, ierr)
614 : 13519 : call xmpi_sum(fcart , comm, ierr)
615 : :
616 : 13519 : end subroutine harmonics_terms_evaluateIFC
617 : : !!***
618 : :
619 : : !!****f* m_harmonics_terms/harmonics_terms_evaluateElastic
620 : : !! NAME
621 : : !! harmonics_terms_evaluateElastic
622 : : !!
623 : : !! FUNCTION
624 : : !! Compute the energy, forces and stresses related to the application of strain
625 : : !!
626 : : !! INPUTS
627 : : !! elastic_constants(6,6) = elastic constants in Hartree
628 : : !! disp(3,natom_sc) = atomics displacement between configuration and the reference
629 : : !! natom = number of atoms in the supercell
630 : : !! natom_uc = number of atoms in the unit cell
631 : : !! ncell = total number of cell
632 : : !! strain_coupling(6,3,natom) = internal strain coupling parameters
633 : : !! strain(6) = strain between configuration and the reference
634 : : !!
635 : : !! OUTPUT
636 : : !! energy = contribution to the energy
637 : : !! fcart(3,natom) = contribution to the forces
638 : : !! strten(6) = contribution to the stress tensor
639 : : !!
640 : : !! SOURCE
641 : : !!
642 : 13519 : subroutine harmonics_terms_evaluateElastic(elastic_constants,disp,energy,fcart,natom,natom_uc,ncell,&
643 : 13519 : & strain_coupling,strten,strain)
644 : :
645 : : real(dp),intent(out):: energy
646 : : integer, intent(in) :: natom,natom_uc,ncell
647 : : ! array
648 : : real(dp),intent(in) :: elastic_constants(6,6),strain_coupling(6,3,natom)
649 : : real(dp),intent(out):: strten(6)
650 : : real(dp),intent(out):: fcart(3,natom)
651 : : real(dp),intent(in) :: disp(3,natom)
652 : : real(dp),intent(in) :: strain(6)
653 : :
654 : : !Local variables-------------------------------
655 : : ! scalar
656 : : integer :: ia,ii,mu,alpha,beta
657 : : real(dp):: cij
658 : : ! array
659 : : ! *************************************************************************
660 : :
661 : 13519 : energy = zero
662 [ + + + + ]: 36076719 : fcart = zero
663 : 13519 : strten = zero
664 : :
665 : : ! write(*,*) "----- STRAIN -----"
666 : : ! write(*,*) strain
667 : :
668 : : !1- Part due to elastic constants
669 [ + + ]: 94633 : do alpha=1,6
670 [ + + ]: 581317 : do beta=1,6
671 : : ! write(*,*) "--- cij --- alpha: ", alpha, " beta: ", beta
672 : 486684 : cij = ncell*elastic_constants(alpha,beta)
673 : : ! write(*,*) cij
674 : 486684 : energy = energy + half*cij*strain(alpha)*strain(beta)
675 : 567798 : strten(alpha) = strten(alpha) + cij*strain(beta)
676 : : end do
677 : : ! write(*,*) "strten(",alpha,"): ", strten(alpha)
678 : : end do
679 : :
680 : : !2-Part due to the internal strain coupling parameters
681 : : ii = 1
682 [ + + ]: 9029319 : do ia = 1,natom
683 [ + + ]: 36063200 : do mu = 1,3
684 [ + + ]: 198347600 : do alpha=1,6
685 : 162284400 : cij = strain_coupling(alpha,mu,ii)
686 : : ! Accumulte for this atom
687 : 162284400 : energy = energy + half*cij*strain(alpha)*disp(mu,ia)
688 : 162284400 : fcart(mu,ia) = fcart(mu,ia) + half*cij*strain(alpha)
689 : 189331800 : strten(alpha) = strten(alpha) + half*cij*disp(mu,ia)
690 : : end do
691 : : end do
692 : 9015800 : ii = ii +1
693 : : ! Reset to 1 if the number of atoms is superior than in the initial cell
694 [ + + ]: 9029319 : if(ii==natom_uc+1) ii = 1
695 : : end do
696 : :
697 : : ! write(*,*) "--- STRTEN at the end --- "
698 : : ! write(*,*) strten(:)
699 : :
700 : 13519 : end subroutine harmonics_terms_evaluateElastic
701 : : !!***
702 : :
703 : : !****f* m_harmonics_terms/harmonics_terms_applySumRule
704 : : !!
705 : : !! NAME
706 : : !! harmonics_terms_applySumRule
707 : : !!
708 : : !! FUNCTION
709 : : !! Apply the acoustic sum rule on the inter-atomic force constants
710 : : !!
711 : : !! INPUTS
712 : : !! ifc<type(ifc_type)> = interatomic forces constants
713 : : !! asr = acoustic sum rule option (see anaddb help)
714 : : !! natom = number of atoms
715 : : !! option = optional if |no present asr is done on total ifc
716 : : !! |present and 1 asr is done on short part
717 : : !! |present and 2 asr is done on ewald part
718 : : !!
719 : : !! OUTPUT
720 : : !! ifc<type(ifc_type)> = interatomic forces constants
721 : : !!
722 : : !! SOURCE
723 : :
724 : 67 : subroutine harmonics_terms_applySumRule(asr,ifc,natom,option)
725 : :
726 : : implicit none
727 : :
728 : : !Arguments ------------------------------------
729 : : !scalars
730 : : integer,intent(in) :: asr
731 : : integer,intent(in) :: natom
732 : : integer,optional,intent(in) :: option
733 : : !array
734 : : type(ifc_type),target,intent(inout) :: ifc
735 : : !Local variables-------------------------------
736 : : !scalar
737 : : integer :: ia,ib,irpt,irpt_ref
738 : : integer :: mu,nu
739 : : real(dp) :: sum
740 : : character(500) :: msg
741 : : !array
742 : 67 : real(dp),pointer :: atmfrc(:,:,:,:,:)
743 : : ! *************************************************************************
744 : :
745 : 67 : irpt_ref = 0
746 : : ! Found the cell of reference
747 [ + + ]: 6494 : do irpt = 1,ifc%nrpt
748 : : if(ifc%cell(1,irpt)==0.and.&
749 [ + + + + : 6427 : & ifc%cell(2,irpt)==0.and.&
+ + ]
750 : 67 : & ifc%cell(3,irpt)==0) then
751 : 6427 : irpt_ref = irpt
752 : : cycle
753 : : end if
754 : : end do
755 : :
756 [ - + ]: 67 : if (irpt_ref<=0) then
757 : 0 : write(msg,'(a,a)')' Unable to find the cell of reference in IFC'
758 : 0 : ABI_ERROR(msg)
759 : : end if
760 : :
761 : 67 : atmfrc => ifc%atmfrc
762 [ - + ]: 67 : if (present(option)) then
763 [ # # ]: 0 : if (option == 1) then
764 : 0 : nullify(atmfrc)
765 : 0 : atmfrc => ifc%short_atmfrc
766 : 0 : write(msg,'(3a)') ch10," Impose acoustic sum rule on short range"
767 [ # # ]: 0 : else if (option == 2) then
768 : 0 : nullify(atmfrc)
769 : 0 : atmfrc => ifc%ewald_atmfrc
770 : 0 : write(msg,'(3a)') ch10," Impose acoustic sum rule on long range"
771 : : end if
772 : : else
773 : 67 : write(msg,'(3a)') ch10," Impose acoustic sum rule on total ifc"
774 : : end if
775 : 67 : call wrtout(ab_out,msg,'COLL')
776 : 67 : call wrtout(std_out,msg,'COLL')
777 : :
778 : : !impose acoustic sum rule:
779 [ + + ]: 268 : do mu=1,3
780 [ + + ]: 871 : do nu=1,3
781 [ + + ]: 4008 : do ia=1,natom
782 : : sum=zero
783 [ + + ]: 26460 : do ib=1,natom
784 : : ! Get the sum of interatomic forces acting on the atom ia,
785 : : ! either in a symmetrical manner, or an unsymmetrical one.
786 [ - + ]: 26460 : if(asr==1)then
787 [ # # ]: 0 : do irpt=1, ifc%nrpt
788 : 0 : sum=sum+atmfrc(mu,ia,nu,ib,irpt)
789 : : end do
790 [ + - ]: 23256 : else if(asr==2)then
791 [ + + ]: 1842957 : do irpt=1, ifc%nrpt
792 : : sum=sum+&
793 : : & (atmfrc(mu,ia,nu,ib,irpt)+&
794 : 1842957 : & atmfrc(nu,ia,mu,ib,irpt))/2
795 : : end do
796 : : end if
797 : : end do
798 : :
799 : : ! Correct the self-interaction in order to fulfill the ASR
800 : : atmfrc(mu,ia,nu,ia,irpt_ref)=&
801 : 3204 : & atmfrc(mu,ia,nu,ia,irpt_ref)-sum
802 [ + - ]: 3807 : if(asr==2)then
803 : : atmfrc(nu,ia,mu,ia,irpt_ref)=&
804 : 3204 : & atmfrc(mu,ia,nu,ia,irpt_ref)
805 : : end if
806 : : end do
807 : : end do
808 : : end do
809 : :
810 [ - + ]: 67 : if (present(option)) then
811 [ # # ]: 0 : if (option == 1) then
812 [ # # # # : 0 : ifc%short_atmfrc = atmfrc(:,:,:,:,:)
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
813 [ # # ]: 0 : else if (option == 2) then
814 [ # # # # : 0 : ifc%ewald_atmfrc = atmfrc(:,:,:,:,:)
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
815 : : end if
816 : : else
817 [ + - + + : 5134332 : ifc%atmfrc(:,:,:,:,:) = atmfrc(:,:,:,:,:)
+ + + + +
+ + + + +
+ + + + +
+ + + ]
818 : : end if
819 : :
820 : 67 : end subroutine harmonics_terms_applySumRule
821 : : !!***
822 : :
823 [ # # # # : 0 : end module m_harmonics_terms
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
824 : : !!***
|