LCOV - code coverage report
Current view: top level - src/78_effpot - m_harmonics_terms.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 75.0 % 212 159
Test Date: 2026-09-19 17:42:43 Functions: 80.0 % 10 8

            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              : !!***
        

Generated by: LCOV version 2.3-1