LCOV - code coverage report
Current view: top level - src/78_effpot - m_anharmonics_terms.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 43.5 % 186 81
Test Date: 2026-09-20 18:56:22 Functions: 58.3 % 12 7

            Line data    Source code
       1              : !!****f* ABINIT/m_anharmonics_terms
       2              : !!
       3              : !! NAME
       4              : !! m_anharmonics_term
       5              : !!
       6              : !! FUNCTION
       7              : !! Module with datatype and tools for the anharmonics 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_anharmonics_terms
      26              : 
      27              :  use defs_basis
      28              :  use m_errors
      29              :  use m_abicore
      30              :  use m_polynomial_coeff
      31              :  use m_ifc, only : ifc_type
      32              :  use m_supercell, only: getPBCIndexes_supercell
      33              :  use m_xmpi
      34              : 
      35              :  implicit none
      36              : 
      37              :  public :: anharmonics_terms_init
      38              :  public :: anharmonics_terms_free
      39              :  public :: anharmonics_terms_freeCoeffs
      40              :  public :: anharmonics_terms_evaluateElastic
      41              :  public :: anharmonics_terms_evaluateIFCStrainCoupling
      42              :  public :: anharmonics_terms_setCoeffs
      43              :  public :: anharmonics_terms_setElastic3rd
      44              :  public :: anharmonics_terms_setElastic4th
      45              :  public :: anharmonics_terms_setElasticDispCoupling
      46              :  public :: anharmonics_terms_setStrainPhononCoupling
      47              : 
      48              : !!***
      49              : 
      50              : !!****t* defs_abitypes/anharmonics_terms_type
      51              : !! NAME
      52              : !! anharmonics_terms_type
      53              : !!
      54              : !! FUNCTION
      55              : !! datatype for a effective potential constructed.
      56              : !!
      57              : !! SOURCE
      58              : 
      59              :  type, public :: anharmonics_terms_type
      60              : 
      61              :    integer :: ncoeff = 0
      62              : !    nterm store the number of coefficients
      63              : 
      64              :    logical ::  has_elastic3rd
      65              : !   Flag to know if the 3rd derivatives with respect to strain is present
      66              : 
      67              :    logical ::  has_elastic4th
      68              : !   Flag to know if the 3rd derivatives with respect to strain is present
      69              : 
      70              :    logical ::  has_strain_coupling
      71              : !   Flag to know if the 3rd derivatives with respect to strain and 2 atom disp is present
      72              : 
      73              :    logical ::  has_elastic_displ
      74              : !   Flag to know if the 3rd derivatives with respect to 2 strain and 3 atom disp is present
      75              : 
      76              :    logical :: bounded
      77              : !   True : the model is bounded
      78              : 
      79              :    type(polynomial_coeff_type),dimension(:),allocatable :: coefficients
      80              : !    array with all the coefficients from  polynomial coefficients
      81              : 
      82              :    real(dp) :: elastic3rd(6,6,6)
      83              : !    elastic_constant(6,6,6)
      84              : !    Elastic tensor Hartree
      85              : 
      86              :    real(dp) :: elastic4th(6,6,6,6)
      87              : !    elastic_constant(6,6,6)
      88              : !    Elastic tensor Hartree
      89              : 
      90              :    real(dp), allocatable :: elastic_displacement(:,:,:,:)
      91              : !    elastic_displacement(6,6,3,natom)
      92              : !    internal strain tensor
      93              : 
      94              :    type(ifc_type),dimension(:),allocatable :: phonon_strain
      95              : !   Array of ifc with phonon_strain coupling for each strain
      96              : 
      97              :  end type anharmonics_terms_type
      98              : !!***
      99              : 
     100              : CONTAINS  !===========================================================================================
     101              : 
     102              : 
     103              : !!****f* m_anharmonics_terms/anharmonics_terms_init
     104              : !!
     105              : !! NAME
     106              : !! anharmonics_terms_init
     107              : !!
     108              : !! FUNCTION
     109              : !! Initialize anharmonics_terms datatype
     110              : !!
     111              : !! INPUTS
     112              : !! natom  = number of atoms in primitive cell
     113              : !! ncoeff = number of coefficient for the fited polynome
     114              : !! bounded = optional, flag to now if the model in bounded
     115              : !! elastic3rd(6,6,6) = optional,3rd order of the elastic constants
     116              : !! elastic4th(6,6,6,6) = optional,4st order of the elastic constants
     117              : !! elastic_displacement(6,6,3,natom) = optional,elastic constant - force coupling
     118              : !! phonon_strain<type(ifc_type)>(6) = optional,phonon strain couling
     119              : !! coeffs<type(polynomial_coeff_type)>(ncoeff) = optional,datatype with polynomial coefficients
     120              : !!
     121              : !! OUTPUT
     122              : !! anharmonics_terms<type(anharmonics_terms_type)> = anharmonics_terms datatype to be initialized
     123              : !!
     124              : !! SOURCE
     125              : 
     126           76 : subroutine anharmonics_terms_init(anharmonics_terms,natom,ncoeff,&
     127              : &                                 bounded,elastic3rd,elastic4th,elastic_displacement,&
     128            0 : &                                 phonon_strain,coeffs)
     129              : 
     130              : !Arguments ------------------------------------
     131              : !scalars
     132              :  integer, intent(in) :: natom,ncoeff
     133              :  type(anharmonics_terms_type), intent(out) :: anharmonics_terms
     134              :  real(dp),optional,intent(in) :: elastic_displacement(6,6,3,natom)
     135              :  real(dp),optional,intent(in) :: elastic3rd(6,6,6),elastic4th(6,6,6,6)
     136              :  type(polynomial_coeff_type),optional :: coeffs(ncoeff)
     137              :  type(ifc_type),optional,intent(in) :: phonon_strain(6)
     138              :  logical,optional,intent(in) :: bounded
     139              : !arrays
     140              : !Local variables-------------------------------
     141              : !scalar
     142              : !arrays
     143              :  character(len=500) :: msg
     144              : 
     145              : ! *************************************************************************
     146              : 
     147           76 :  call anharmonics_terms_free(anharmonics_terms)
     148              : 
     149              : ! Check the number of atoms
     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              : !Allocation of phonon strain coupling array (3rd order)
     158           76 :  if(present(phonon_strain)) then
     159            0 :    call anharmonics_terms_setStrainPhononCoupling(anharmonics_terms,natom,phonon_strain)
     160              :  end if
     161              : 
     162              : !Set the 3rd order elastic tensor
     163        19684 :  anharmonics_terms%elastic3rd = zero
     164           76 :  anharmonics_terms%has_elastic3rd = .FALSE.
     165           76 :  if(present(elastic3rd))then
     166            0 :    call anharmonics_terms_setElastic3rd(anharmonics_terms,elastic3rd)
     167              :  end if
     168              : 
     169              : !Set the 3rd order elastic tensor
     170       118180 :  anharmonics_terms%elastic4th = zero
     171           76 :  anharmonics_terms%has_elastic4th = .FALSE.
     172           76 :  if(present(elastic4th))then
     173            0 :    call anharmonics_terms_setElastic4th(anharmonics_terms,elastic4th)
     174              :  end if
     175              : 
     176              : !Allocation of 3rd order with respecto to 2 strain and 1 atomic displacement
     177           76 :  if(present(elastic_displacement))then
     178            0 :    call anharmonics_terms_setElasticDispCoupling(anharmonics_terms,natom,elastic_displacement)
     179              :  end if
     180              : 
     181           76 :  anharmonics_terms%ncoeff = 0
     182              : 
     183              : !Allocation of the coefficient
     184           76 :   if(present(coeffs))then
     185            0 :    if(ncoeff /= size(coeffs))then
     186              :      write(msg, '(a)' )&
     187            0 : &        ' ncoeff has not the same size than coeffs array, '
     188            0 :      ABI_BUG(msg)
     189              :    end if
     190            0 :    call anharmonics_terms_setCoeffs(coeffs,anharmonics_terms,ncoeff)
     191              :  end if
     192              : 
     193              : !Set the flag bounded
     194           76 :  if(present(bounded))then
     195            0 :    anharmonics_terms%bounded = bounded
     196              :  else
     197           76 :    anharmonics_terms%bounded = .FALSE.
     198              :  end if
     199              : 
     200           76 : end subroutine anharmonics_terms_init
     201              : !!***
     202              : 
     203              : !****f* m_anharmonics_terms/anharmonics_terms_free
     204              : !!
     205              : !! NAME
     206              : !! anharmonics_terms_free
     207              : !!
     208              : !! FUNCTION
     209              : !! deallocate all dynamic memory for this anharmonics_terms datatype
     210              : !!
     211              : !! INPUTS
     212              : !! anharmonics_terms<type(anharmonics_terms_type)> = anharmonics_terms datatype to be free
     213              : !!
     214              : !! OUTPUT
     215              : !! anharmonics_terms<type(anharmonics_terms_type)> = anharmonics_terms datatype to be free
     216              : !!
     217              : !! SOURCE
     218              : 
     219          610 : subroutine anharmonics_terms_free(anharmonics_terms)
     220              : 
     221              : !Arguments ------------------------------------
     222              : !scalars
     223              : !array
     224              :   type(anharmonics_terms_type), intent(inout) :: anharmonics_terms
     225              : 
     226              : !Local variables-------------------------------
     227              : !scalars
     228              :   integer :: ii
     229              : !array
     230              : 
     231              : ! *************************************************************************
     232              : 
     233          610 :    anharmonics_terms%has_elastic3rd = .FALSE.
     234          610 :    anharmonics_terms%has_strain_coupling  = .FALSE.
     235          610 :    anharmonics_terms%has_elastic_displ = .FALSE.
     236          610 :    anharmonics_terms%bounded = .FALSE.
     237              : 
     238          610 :   if(allocated(anharmonics_terms%elastic_displacement)) then
     239            0 :     anharmonics_terms%elastic_displacement=zero
     240            0 :     ABI_SFREE(anharmonics_terms%elastic_displacement)
     241              :   end if
     242              : 
     243          610 :   if(allocated(anharmonics_terms%phonon_strain))then
     244          315 :     do ii = 1,6
     245          315 :        call anharmonics_terms%phonon_strain(ii)%free()
     246              :     end do
     247          315 :     ABI_SFREE(anharmonics_terms%phonon_strain)
     248              :   end if
     249              : 
     250          610 :   call anharmonics_terms_freeCoeffs(anharmonics_terms)
     251              : 
     252       157990 :   anharmonics_terms%elastic3rd = zero
     253              : 
     254              : 
     255          610 : end subroutine anharmonics_terms_free
     256              : !!***
     257              : 
     258              : !****f* m_anharmonics_terms/anharmonics_terms_freeCoeffs
     259              : !!
     260              : !! NAME
     261              : !! anharmonics_terms_freeCoeffs
     262              : !!
     263              : !! FUNCTION
     264              : !! deallocate all dynamic memory for the coefficients
     265              : !! of this  anharmonics_terms datatype
     266              : !!
     267              : !! INPUTS
     268              : !! anharmonics_terms<type(anharmonics_terms_type)> = anharmonics_terms datatype to be free
     269              : !!
     270              : !! OUTPUT
     271              : !! anharmonics_terms<type(anharmonics_terms_type)> = anharmonics_terms datatype to be free
     272              : !!
     273              : !!
     274              : !! SOURCE
     275              : 
     276          686 : subroutine anharmonics_terms_freeCoeffs(anharmonics_terms)
     277              : 
     278              : !Arguments ------------------------------------
     279              : !scalars
     280              : !array
     281              :   type(anharmonics_terms_type), intent(inout) :: anharmonics_terms
     282              : !Local variables-------------------------------
     283              : !scalars
     284              :   integer :: ii
     285              : !array
     286              : 
     287              : ! *************************************************************************
     288              : 
     289          686 :   if(allocated(anharmonics_terms%coefficients))then
     290         2146 :     do ii=1,anharmonics_terms%ncoeff
     291         2146 :       call polynomial_coeff_free(anharmonics_terms%coefficients(ii))
     292              :     end do
     293         2146 :     ABI_SFREE(anharmonics_terms%coefficients)
     294              :   end if
     295              : 
     296          686 :   anharmonics_terms%ncoeff = 0
     297              : 
     298          686 : end subroutine anharmonics_terms_freeCoeffs
     299              : !!***
     300              : 
     301              : !****f* m_anharmonics_terms/anharmonics_terms_setCoeffs
     302              : !!
     303              : !! NAME
     304              : !! anharmonics_terms_setCoeffs
     305              : !!
     306              : !! FUNCTION
     307              : !! Set the coefficients
     308              : !!
     309              : !! INPUTS
     310              : !! coeffs(ncoeff)<type(polynomial_coeff_type)> = array with datatype polynomial_coeff_type
     311              : !! ncoeff = number of coefficient
     312              : !!
     313              : !! OUTPUT
     314              : !! anharmonics_terms<type(anharmonics_terms_type)> = anharmonics_terms datatype
     315              : !!
     316              : !!
     317              : !! SOURCE
     318              : 
     319          192 : subroutine anharmonics_terms_setCoeffs(coeffs,anharmonics_terms,ncoeff)
     320              : 
     321              :  use m_polynomial_coeff
     322              : 
     323              : !Arguments ------------------------------------
     324              : !scalars
     325              :   integer,intent(in) :: ncoeff
     326              : !array
     327              :   type(anharmonics_terms_type),intent(inout) :: anharmonics_terms
     328              :   type(polynomial_coeff_type),intent(in) :: coeffs(ncoeff)
     329              : !Local variables-------------------------------
     330              : !scalar
     331              :   integer :: ii
     332              :   character(len=500) :: msg
     333              : !array
     334              : ! *************************************************************************
     335              : 
     336           96 :   if(ncoeff /= size(coeffs))then
     337              :     write(msg, '(a)' )&
     338            0 : &        ' ncoeff has not the same size than coeffs array, '
     339            0 :     ABI_BUG(msg)
     340              :   end if
     341              : 
     342              : ! 1-deallocation of the previous value
     343           96 :   if(allocated(anharmonics_terms%coefficients))then
     344            9 :     do ii=1,anharmonics_terms%ncoeff
     345            9 :       call polynomial_coeff_free(anharmonics_terms%coefficients(ii))
     346              :     end do
     347            9 :     ABI_SFREE(anharmonics_terms%coefficients)
     348              :   end if
     349              : 
     350              : ! Allocation of the new array
     351           96 :   anharmonics_terms%ncoeff = ncoeff
     352         2347 :   ABI_MALLOC(anharmonics_terms%coefficients,(ncoeff))
     353         2155 :   do ii=1,anharmonics_terms%ncoeff
     354              :     call polynomial_coeff_init(coeffs(ii)%coefficient,coeffs(ii)%nterm,&
     355              :       &                              anharmonics_terms%coefficients(ii),&
     356              :       &                              coeffs(ii)%terms, &
     357         2155 :       &                              name=coeffs(ii)%name)
     358              :   end do
     359              : 
     360           96 : end subroutine anharmonics_terms_setCoeffs
     361              : !!***
     362              : 
     363              : !****f* m_anharmonics_terms/anharmonics_terms_setElastic3rd
     364              : !!
     365              : !! NAME
     366              : !! anharmonics_terms_setElastic3rd
     367              : !!
     368              : !! FUNCTION
     369              : !! Set the 3rd order derivative of with respect to 3 strain
     370              : !!
     371              : !! INPUTS
     372              : !! elastics(6,6,6) = 3d order of elastics constant
     373              : !!
     374              : !! OUTPUT
     375              : !! anharmonics_terms<type(anharmonics_terms_type)> = anharmonics_terms datatype
     376              : !!
     377              : !! SOURCE
     378              : 
     379           45 : subroutine anharmonics_terms_setElastic3rd(anharmonics_terms,elastics)
     380              : 
     381              : !Arguments ------------------------------------
     382              : !scalars
     383              : !array
     384              :   type(anharmonics_terms_type),intent(inout) :: anharmonics_terms
     385              :   real(dp),intent(in) :: elastics(6,6,6)
     386              : !Local variables-------------------------------
     387              : !scalar
     388              : !array
     389              : ! *************************************************************************
     390              : 
     391              : ! 1-reinitialise the previous value
     392        11655 :   anharmonics_terms%elastic3rd(:,:,:) = zero
     393           45 :   anharmonics_terms%has_elastic3rd = .FALSE.
     394              : 
     395              : ! 2-Allocation of the new array
     396        11655 :   anharmonics_terms%elastic3rd(:,:,:) = elastics(:,:,:)
     397              : 
     398              : ! 3-Set the flag
     399        11655 :   if(any(abs(anharmonics_terms%elastic3rd)> tol15)) then
     400            0 :     anharmonics_terms%has_elastic3rd = .TRUE.
     401              :   end if
     402              : 
     403           96 : end subroutine anharmonics_terms_setElastic3rd
     404              : !!***
     405              : 
     406              : !****f* m_anharmonics_terms/anharmonics_terms_setElastic4th
     407              : !!
     408              : !! NAME
     409              : !! anharmonics_terms_setElastic4th
     410              : !!
     411              : !! FUNCTION
     412              : !! Set the 4th order derivative of with respect to 4 strain
     413              : !!
     414              : !! INPUTS
     415              : !! elastics = 4th order of elastics constant
     416              : !!
     417              : !! OUTPUT
     418              : !! anharmonics_terms<type(anharmonics_terms_type)> = anharmonics_terms datatype
     419              : !!
     420              : !!
     421              : !! SOURCE
     422              : 
     423            0 : subroutine anharmonics_terms_setElastic4th(anharmonics_terms,elastics)
     424              : 
     425              : !Arguments ------------------------------------
     426              : !scalars
     427              : !array
     428              :   type(anharmonics_terms_type),intent(inout) :: anharmonics_terms
     429              :   real(dp),intent(in) :: elastics(6,6,6,6)
     430              : !Local variables-------------------------------
     431              : !scalar
     432              : !array
     433              : ! *************************************************************************
     434              : 
     435              : ! 1-reinitialise the previous value
     436            0 :   anharmonics_terms%elastic4th(:,:,:,:) = zero
     437            0 :   anharmonics_terms%has_elastic4th = .FALSE.
     438              : 
     439              : ! 2-Allocation of the new array
     440            0 :   anharmonics_terms%elastic4th(:,:,:,:) = elastics(:,:,:,:)
     441              : 
     442              : ! 3-Set the flag
     443            0 :   if(any(abs(anharmonics_terms%elastic4th)> tol15)) then
     444            0 :     anharmonics_terms%has_elastic4th = .TRUE.
     445              :   end if
     446              : 
     447            0 : end subroutine anharmonics_terms_setElastic4th
     448              : !!***
     449              : 
     450              : 
     451              : !****f* m_anharmonics_terms/anharmonics_terms_setStrainPhononCoupling
     452              : !!
     453              : !! NAME
     454              : !! anharmonics_terms_setStrainPhononCoupling
     455              : !!
     456              : !! FUNCTION
     457              : !! Set the strain-phonon coupling
     458              : !!
     459              : !! INPUTS
     460              : !! strain_phonon(6)<type(ifc_type) = strain-phonon coupling
     461              : !! natom = number of atoms
     462              : !!
     463              : !! OUTPUT
     464              : !! anharmonics_terms<type(anharmonics_terms_type)> = anharmonics_terms datatype
     465              : !!
     466              : !! SOURCE
     467              : 
     468           45 : subroutine anharmonics_terms_setStrainPhononCoupling(anharmonics_terms,natom,phonon_strain)
     469              : 
     470              : !Arguments ------------------------------------
     471              : !scalars
     472              :   integer, intent(in) :: natom
     473              : !array
     474              :   type(anharmonics_terms_type),intent(inout) :: anharmonics_terms
     475              :   type(ifc_type),intent(in) :: phonon_strain(6)
     476              : !Local variables-------------------------------
     477              : !scalar
     478              :   integer :: ii,nrpt
     479              :   character(500) :: msg
     480              : !array
     481              : ! *************************************************************************
     482              : 
     483              : ! 1-Do some check
     484          315 :   do ii=1,6
     485              : !PROBLEM eos_gnu_13.2_openmpi
     486              : !   if(natom /= size(phonon_strain(ii)%atmfrc,2).or.&
     487          270 :     if( &
     488              : !ENDPROBLEM
     489           45 : &      phonon_strain(ii)%nrpt < 0)then
     490              :       write(msg, '(a)' )&
     491            0 : &        ' natom or/and nrpt have not the same size than phonon_strain array. '
     492            0 :       ABI_BUG(msg)
     493              :     end if
     494              :   end do
     495              : 
     496              : ! 1-reinitialise the previous value
     497           45 :   anharmonics_terms%has_strain_coupling  = .FALSE.
     498           45 :   if(allocated(anharmonics_terms%phonon_strain))then
     499            0 :     do ii = 1,6
     500            0 :        call anharmonics_terms%phonon_strain(ii)%free()
     501              :     end do
     502            0 :     ABI_SFREE(anharmonics_terms%phonon_strain)
     503              :   end if
     504              : 
     505              : ! 2-Allocation of the new array and filling
     506          585 :  ABI_MALLOC(anharmonics_terms%phonon_strain,(6))
     507          315 :  do ii = 1,6
     508          270 :    nrpt = phonon_strain(ii)%nrpt
     509         1620 :    ABI_MALLOC(anharmonics_terms%phonon_strain(ii)%atmfrc,(3,natom,3,natom,nrpt))
     510          810 :    ABI_MALLOC(anharmonics_terms%phonon_strain(ii)%cell,(3,nrpt))
     511          270 :    anharmonics_terms%phonon_strain(ii)%nrpt   = phonon_strain(ii)%nrpt
     512          270 :    anharmonics_terms%phonon_strain(ii)%atmfrc(:,:,:,:,:) = phonon_strain(ii)%atmfrc(:,:,:,:,:)
     513          270 :    anharmonics_terms%phonon_strain(ii)%cell(:,:)   = phonon_strain(ii)%cell(:,:)
     514              : 
     515              : !3-Set the flag
     516          315 :    if(any(abs(anharmonics_terms%phonon_strain(ii)%atmfrc)> tol15)) then
     517            0 :      anharmonics_terms%has_strain_coupling  = .TRUE.
     518              : !  If there is no value inside the array,
     519              : !  We don't need to store it
     520              :    else
     521          270 :      ABI_SFREE(anharmonics_terms%phonon_strain(ii)%atmfrc)
     522          270 :      ABI_SFREE(anharmonics_terms%phonon_strain(ii)%cell)
     523          270 :      anharmonics_terms%phonon_strain(ii)%nrpt = 0
     524              :    end if
     525              :  end do
     526              : 
     527           45 : end subroutine anharmonics_terms_setStrainPhononCoupling
     528              : !!***
     529              : 
     530              : !****f* m_anharmonics_terms/anharmonics_terms_setElasticDispCoupling
     531              : !!
     532              : !! NAME
     533              : !! anharmonics_terms_setElasticDispCoupling
     534              : !!
     535              : !! FUNCTION
     536              : !! Set the Elastic displacement coupling
     537              : !!
     538              : !! INPUTS
     539              : !! elastic_displacement(6,6,3,natom) = elastic displacement coupling
     540              : !! natom = number of atom
     541              : !!
     542              : !! OUTPUT
     543              : !! anharmonics_terms<type(anharmonics_terms_type)> = anharmonics_terms datatype
     544              : !!
     545              : !!
     546              : !! SOURCE
     547              : 
     548           38 : subroutine anharmonics_terms_setElasticDispCoupling(anharmonics_terms,natom,elastic_displacement)
     549              : 
     550              : !Arguments ------------------------------------
     551              : !scalars
     552              :   integer, intent(in) :: natom
     553              : !array
     554              :   type(anharmonics_terms_type),intent(inout) :: anharmonics_terms
     555              :   real(dp),intent(in) :: elastic_displacement(6,6,3,natom)
     556              : !Local variables-------------------------------
     557              : !scalar
     558              :   character(500) :: msg
     559              : !array
     560              : ! *************************************************************************
     561              : 
     562              : ! 1-Do some check
     563           38 :   if(natom /= size(elastic_displacement,4)) then
     564              :     write(msg, '(a)' )&
     565            0 : &        ' natom has not the same size elastic_displacement array. '
     566            0 :     ABI_BUG(msg)
     567              :   end if
     568              : 
     569              : ! 1-reinitialise the previous value
     570           38 :   anharmonics_terms%has_elastic_displ = .FALSE.
     571           38 :   if(allocated(anharmonics_terms%elastic_displacement))then
     572            0 :     ABI_SFREE(anharmonics_terms%elastic_displacement)
     573              :   end if
     574              : 
     575              : ! 2-Allocation of the new array and filling
     576          114 :   ABI_MALLOC(anharmonics_terms%elastic_displacement,(6,6,3,natom))
     577        26558 :   anharmonics_terms%elastic_displacement(:,:,:,:) = elastic_displacement(:,:,:,:)
     578              : 
     579              : ! 3-Set the flag
     580        26558 :   if(any(abs(anharmonics_terms%elastic_displacement)> tol15)) then
     581            0 :     anharmonics_terms%has_elastic_displ = .TRUE.
     582              :   else
     583              : !   If there is no value inside the array,
     584              : !   We don't need to store it
     585           38 :     ABI_SFREE(anharmonics_terms%elastic_displacement)
     586              :   end if
     587              : 
     588           38 : end subroutine anharmonics_terms_setElasticDispCoupling
     589              : !!***
     590              : 
     591              : !!****f* m_effective_potential/anharmonics_terms_evaluateElastic
     592              : !! NAME
     593              : !!  anharmonics_terms_evaluateElastic
     594              : !!
     595              : !! FUNCTION
     596              : !! Compute the energy, stresses and forces related to the application of strain
     597              : !!
     598              : !! INPUTS
     599              : !! disp(3,natom_sc) = atomics displacement between configuration and the reference
     600              : !! natom = number of atom in the supercell
     601              : !! natom_uc = number of atom in the unit cell
     602              : !! ncell  = number of cell
     603              : !! strain(6) =  strain to apply
     604              : !! elastic3rd(6,6,6) = 3 order derivatives with respect to to 3 strain
     605              : !! elastic4th(6,6,66,) = 4 order derivatives with respect to to 4 strain
     606              : !! elastic_displacement(6,6,3,natom) = 3 order derivatives with respect to 2 strain and 1 Atom disp
     607              : !!
     608              : !! OUTPUT
     609              : !!   energy = contribution of the ifc to the energy
     610              : !!   fcart(3,natom) = contribution of the ifc to the forces
     611              : !!   strten(6) = contribution to the stress tensor
     612              : !!
     613              : !! SOURCE
     614              : !!
     615            0 : subroutine anharmonics_terms_evaluateElastic(disp,energy,fcart,natom,natom_uc,ncell,strten,strain,&
     616              : &                                            elastic3rd,elastic4th,elastic_displacement)
     617              : 
     618              :  real(dp),intent(out):: energy
     619              :  integer, intent(in) :: natom,natom_uc,ncell
     620              : ! array
     621              :  real(dp),optional,intent(in) :: elastic3rd(6,6,6),elastic4th(6,6,6,6)
     622              :  real(dp),optional,intent(in) :: elastic_displacement(6,6,3,natom)
     623              :  real(dp),intent(out):: strten(6)
     624              :  real(dp),intent(out):: fcart(3,natom)
     625              :  real(dp),intent(in) :: disp(3,natom)
     626              :  real(dp),intent(in) :: strain(6)
     627              : 
     628              :  !Local variables-------------------------------
     629              : ! scalar
     630              :  integer :: ia,ii,mu,alpha,beta,gamma,delta,d1,d2
     631              :  real(dp):: cijk
     632              :  logical :: has_elastic3rd,has_elastic4th,has_elastic_displ
     633              : ! array
     634              : ! *************************************************************************
     635              : 
     636              : !Reset output and flags
     637            0 :  energy = zero
     638            0 :  fcart = zero
     639            0 :  strten = zero
     640            0 :  has_elastic3rd    = .FALSE.
     641            0 :  has_elastic4th    = .FALSE.
     642            0 :  has_elastic_displ = .FALSE.
     643            0 :  d1=0;d2=0
     644              : 
     645              : !Set the flags
     646            0 :  if(present(elastic3rd)) has_elastic3rd = .TRUE.
     647            0 :  if(present(elastic4th)) then
     648            0 :    has_elastic4th = .TRUE.
     649            0 :    d1=1;d2=6
     650              :  end if
     651            0 :  if(present(elastic_displacement)) has_elastic_displ = .TRUE.
     652              : 
     653              : !1-Treat 3rd order elastic constants
     654            0 :  if (has_elastic3rd.or.has_elastic4th) then
     655            0 :    do alpha=1,6
     656            0 :      do beta=1,6
     657            0 :        do gamma=1,6
     658            0 :          cijk = ncell*elastic3rd(alpha,beta,gamma)
     659              : !        Accumulate energy
     660            0 :          energy = energy + sixth*cijk*strain(alpha)*strain(beta)*strain(gamma)
     661              : !        Accumulate stresses contributions
     662            0 :          strten(alpha)=strten(alpha)+ half*cijk*strain(beta)*strain(gamma)
     663            0 :          do delta=d1,d2
     664            0 :            cijk = ncell*elastic4th(alpha,beta,gamma,delta)
     665              : !          Accumulate energy
     666              :            energy = energy + (1/24.)*cijk*strain(alpha)*strain(beta)*&
     667            0 : &                                                  strain(gamma)*strain(delta)
     668              : !          Accumulate stresses contributions
     669              :            strten(alpha)=strten(alpha)+ sixth*cijk*strain(beta)*strain(gamma)*&
     670            0 : &                                                           strain(delta)
     671              :          end do
     672              :        end do
     673              :      end do
     674              :    end do
     675              :  end if
     676              : 
     677              : !2-Part due to the internat strain
     678            0 :  if(has_elastic_displ)then
     679              :    ii = 1
     680            0 :    do ia = 1,natom
     681            0 :      do mu = 1,3
     682            0 :        do beta=1,6
     683            0 :          do alpha=1,6
     684            0 :            cijk = elastic_displacement(alpha,beta,mu,ii)
     685              : !          Accumulte for this atom
     686            0 :            energy = energy + sixth*cijk*strain(alpha)*strain(beta)*disp(mu,ia)
     687            0 :            fcart(mu,ia) = fcart(mu,ia)   +  half*cijk*strain(alpha)*strain(beta)
     688            0 :            strten(alpha) = strten(alpha) +  half*cijk*strain(beta)*disp(mu,ia)
     689              :          end do
     690              :        end do
     691              :      end do
     692            0 :      ii = ii +1
     693              : !    Reset to 1 if the number of atoms is superior than in the initial cell
     694            0 :      if(ii==natom_uc+1) ii = 1
     695              :    end do
     696              :  end if
     697              : 
     698            0 : end subroutine anharmonics_terms_evaluateElastic
     699              : !!***
     700              : 
     701              : !!****f* m_anharmonics_terms/anharmonics_terms_evaluateIFCStrainCoupling
     702              : !! NAME
     703              : !!  anharmonics_terms_evaluateIFCStrainCoupling
     704              : !!
     705              : !! FUNCTION
     706              : !!  This fonction compute the harmonic part of the energy
     707              : !!  of the supercell in the eff_pot
     708              : !! INPUTS
     709              : !!  strain_phonon(6)<type(ifc_type) = strain-phonon coupling
     710              : !!  disp(3,natom_sc) = atomics displacement between configuration and the reference
     711              : !!  natom = number of atoms in the supercell
     712              : !!  natom_uc = number of atoms in the unit cell
     713              : !!  sc_size(3) = size of the supercell
     714              : !!  cells(ncell) = number of the cells into the supercell (1,2,3,4,5)
     715              : !!  ncell  = total number of cell to treat
     716              : !!  index_cells(3,ncell) = indexes of the cells into  supercell (-1 -1 -1 ,...,1 1 1)
     717              : !!  comm=MPI communicator
     718              : !!
     719              : !! OUTPUT
     720              : !!   energy = contribution of the ifc to the energy
     721              : !!   fcart(3,natom) = contribution of the ifc to the forces
     722              : !!   strten(6) = contribution to the stress tensor
     723              : !!
     724              : !! PARENT
     725              : !!   effective_potential_evaluate
     726              : !!
     727              : !! SOURCE
     728              : 
     729            0 : subroutine anharmonics_terms_evaluateIFCStrainCoupling(phonon_strain,disp,energy,fcart,natom,natom_uc,&
     730            0 : &                                                      sc_size,strain,strten,cells,ncell,&
     731            0 : &                                                      index_cells,comm)
     732              : 
     733              : !Arguments -------------------------------
     734              : ! scalars
     735              :   real(dp),intent(out) :: energy
     736              :   integer,intent(in) :: natom,natom_uc,ncell
     737              :   integer,intent(in) :: comm
     738              : ! array
     739              :   integer,intent(in) ::   cells(ncell),index_cells(ncell,3)
     740              :   integer,intent(in) :: sc_size(3)
     741              :   type(ifc_type),intent(in) :: phonon_strain(6)
     742              :   real(dp),intent(in) :: disp(3,natom)
     743              :   real(dp),intent(out) :: fcart(3,natom)
     744              :   real(dp),intent(out) :: strten(6)
     745              :   real(dp),intent(in) :: strain(6)
     746              : !Local variables-------------------------------
     747              : ! scalar
     748              :   integer :: alpha
     749              :   integer :: i1,i2,i3,ia,ib,icell,ii
     750              :   integer :: irpt,jj,kk,ll,mu,nu
     751              :   integer :: ierr
     752              :   real(dp):: ifc
     753              : ! array
     754              :   integer :: cell_atom2(3)
     755              :   character(500) :: msg
     756              : 
     757              : ! *************************************************************************
     758              : 
     759            0 :   if (any(sc_size <= 0)) then
     760            0 :     write(msg,'(a,a)')' sc_size can not be inferior or equal to zero'
     761            0 :     ABI_ERROR(msg)
     762              :   end if
     763              : 
     764              : ! Initialisation of variables
     765            0 :   energy   = zero
     766            0 :   fcart(:,:) = zero
     767            0 :   strten(:) = zero
     768              : 
     769            0 :   do icell = 1,ncell
     770            0 :     ii = (cells(icell)-1)*natom_uc
     771            0 :     i1=index_cells(icell,1); i2=index_cells(icell,2); i3=index_cells(icell,3)
     772            0 :     do alpha=1,6
     773            0 :       do irpt = 1,phonon_strain(alpha)%nrpt
     774              : !       get the cell of atom2  (0 0 0, 0 0 1...)
     775            0 :         cell_atom2(1) =  i1 + phonon_strain(alpha)%cell(1,irpt)
     776            0 :         cell_atom2(2) =  i2 + phonon_strain(alpha)%cell(2,irpt)
     777            0 :         cell_atom2(3) =  i3 + phonon_strain(alpha)%cell(3,irpt)
     778            0 :         call getPBCIndexes_supercell(cell_atom2(1:3),sc_size(1:3))
     779              : !       index of the second atom in the displacement array
     780              :         jj = (cell_atom2(1)-1)*sc_size(2)*sc_size(3)*natom_uc+&
     781              : &            (cell_atom2(2)-1)*sc_size(3)*natom_uc+&
     782            0 : &            (cell_atom2(3)-1)*natom_uc
     783            0 :         do ib = 1, natom_uc
     784            0 :           ll = jj + ib
     785            0 :           do nu=1,3
     786            0 :             do ia = 1, natom_uc
     787            0 :               kk = ii + ia
     788            0 :               do mu=1,3
     789            0 :                 ifc = phonon_strain(alpha)%atmfrc(mu,ia,nu,ib,irpt)
     790              : !               accumule energy
     791            0 :                 energy =  energy + sixth*strain(alpha)*disp(mu,kk)*disp(nu,ll)*ifc
     792              : !               accumule forces
     793            0 :                 fcart(mu,kk) = fcart(mu,kk) + half*strain(alpha)*disp(nu,ll)*ifc
     794              : !               accumule stresses
     795            0 :                 strten(alpha) = strten(alpha) + half*disp(mu,kk)*disp(nu,ll)*ifc
     796              :               end do
     797              :             end do
     798              :           end do
     799              :         end do
     800              :       end do
     801              :     end do
     802              :   end do
     803              : 
     804              : ! MPI_SUM
     805            0 :   call xmpi_sum(energy, comm, ierr)
     806            0 :   call xmpi_sum(fcart , comm, ierr)
     807            0 :   call xmpi_sum(strten, comm, ierr)
     808              : 
     809            0 : end subroutine anharmonics_terms_evaluateIFCStrainCoupling
     810              : !!***
     811            0 : end module m_anharmonics_terms
     812              : !!***
        

Generated by: LCOV version 2.3-1