LCOV - code coverage report
Current view: top level - src/77_ddb - m_ddb_elast.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 87.2 % 266 232
Test Date: 2026-11-12 14:41:44 Functions: 100.0 % 1 1
Branches: 79.0 % 334 264

             Branch data     Line data    Source code
       1                 :             : !!****m* ABINIT/m_ddb_elast
       2                 :             : !! NAME
       3                 :             : !!  m_ddb_elast
       4                 :             : !!
       5                 :             : !! FUNCTION
       6                 :             : !!  Elastic properties (clamped-ions and relaxed-ions).
       7                 :             : !!
       8                 :             : !! COPYRIGHT
       9                 :             : !!  Copyright (C) 1999-2026 ABINIT group (XW, DW)
      10                 :             : !!  This file is distributed under the terms of the
      11                 :             : !!  GNU General Public License, see ~abinit/COPYING
      12                 :             : !!  or http://www.gnu.org/copyleft/gpl.txt .
      13                 :             : !!
      14                 :             : !! SOURCE
      15                 :             : 
      16                 :             : #if defined HAVE_CONFIG_H
      17                 :             : #include "config.h"
      18                 :             : #endif
      19                 :             : 
      20                 :             : #include "abi_common.h"
      21                 :             : 
      22                 :             : module m_ddb_elast
      23                 :             : 
      24                 :             :  use defs_basis
      25                 :             :  use m_abicore
      26                 :             :  use m_errors
      27                 :             :  use m_crystal
      28                 :             :  use m_ddb
      29                 :             :  use m_nctk
      30                 :             :  use netcdf
      31                 :             : 
      32                 :             :  use m_fstrings,       only : itoa, sjoin
      33                 :             :  use m_hide_lapack,    only : matrginv
      34                 :             :  use m_dynmat,         only : asria_corr
      35                 :             :  use m_anaddb_dataset, only : anaddb_dataset_type
      36                 :             : 
      37                 :             :  implicit none
      38                 :             : 
      39                 :             :  private
      40                 :             : !!***
      41                 :             : 
      42                 :             :  public :: ddb_elast
      43                 :             : !!***
      44                 :             : 
      45                 :             : contains
      46                 :             : !!***
      47                 :             : 
      48                 :             : !!****f* ABINIT/ddb_elast
      49                 :             : !!
      50                 :             : !! NAME
      51                 :             : !! ddb_elast
      52                 :             : !!
      53                 :             : !! FUNCTION
      54                 :             : !! Get the elastic and compliance tensors, both clamped ion and relaxed ion,
      55                 :             : !! under the fixed electric field boundary condition; in which realxed ion
      56                 :             : !! tensors can generate two output tensors one is conventional, the other
      57                 :             : !! considers the sress correction.
      58                 :             : !!
      59                 :             : !! INPUTS
      60                 :             : !! inp= (derived datatype) contains all the input variables
      61                 :             : !! crystal<crystal_t>=Info on crystalline structure.
      62                 :             : !! blkval(2,3,mpert,3,mpert,nblok)=
      63                 :             : !!   second derivatives of total energy with respect to electric fields
      64                 :             : !!   atom displacements, strain,...... all in cartesian coordinates
      65                 :             : !! d2asr= ASR correction to the dynamical matrix at Gamma
      66                 :             : !! iblok= bolk number in DDB file
      67                 :             : !! iblok_stress= blok number which contain stress tensor
      68                 :             : !! instrain=force response internal strain tensor
      69                 :             : !! iout=out file number
      70                 :             : !! mpert=maximum number of ipert
      71                 :             : !! natom=number of atoms in unit cell
      72                 :             : !! nblok=number of total bloks in DDB file
      73                 :             : !! ncid=NC file handle (open in the caller)
      74                 :             : !!
      75                 :             : !! OUTPUT
      76                 :             : !! elast=relaxed-ion elastic tensor (without stress correction) (6*6) in Voigt notation
      77                 :             : !! elast_clamped=clamped-ion elastic tensor (without stress correction) (6*6) in Voigt notation
      78                 :             : !! elast_stress=relaxed-ion elastic tensor (with stress correction) (6*6) in Voigt notation
      79                 :             : !!
      80                 :             : !! NOTES
      81                 :             : !! The elastic (compliance) tensors calculated here are under boundary conditions of
      82                 :             : !! fixed Electric Field, different from those in ddb_piezo.F90 which are under fixed
      83                 :             : !! Displacement Field and incorporate piezoelectric corrections.
      84                 :             : !!
      85                 :             : !! SOURCE
      86                 :             : 
      87                 :           6 : subroutine ddb_elast(inp,crystal,blkval,compl,compl_clamped,compl_stress,d2asr,&
      88                 :             : &            elast,elast_clamped,elast_stress,iblok,iblok_stress,&
      89                 :           6 : &            instrain,iout,mpert,natom,nblok,ncid)
      90                 :             : 
      91                 :             : !Arguments -------------------------------------------
      92                 :             : !scalars
      93                 :             :  integer,intent(in) :: iblok,iblok_stress,iout,mpert,natom,nblok,ncid
      94                 :             : !integer,intent(in) :: msize
      95                 :             :  type(crystal_t),intent(in) :: crystal
      96                 :             :  type(anaddb_dataset_type),intent(in) :: inp
      97                 :             : !arrays
      98                 :             :  real(dp),intent(in) :: blkval(2,3,mpert,3,mpert,nblok),instrain(3*natom,6)
      99                 :             :  real(dp),intent(in) :: d2asr(2,3,natom,3,natom)
     100                 :             :  real(dp),intent(out) :: compl(6,6), compl_clamped(6,6),compl_stress(6,6)
     101                 :             :  real(dp),intent(out) :: elast(6,6), elast_clamped(6,6),elast_stress(6,6)
     102                 :             : 
     103                 :             : !Local variables------------------------------------
     104                 :             : !scalars
     105                 :             :  integer :: ier,ii1,ii2,ipert1,ipert2,ivarA,ivarB,ncerr
     106                 :             :  real(dp) :: ucvol
     107                 :             :  logical :: iwrite
     108                 :             :  character(len=500) :: message
     109                 :             : !arrays
     110                 :          12 :  real(dp) :: Amatr(3*natom-3,3*natom-3),Apmatr(3*natom,3*natom)
     111                 :          12 :  real(dp) :: Bmatr(2,((3*natom-3)*(3*natom-2))/2)
     112                 :          12 :  real(dp) :: Bpmatr(2,(3*natom*(3*natom+1))/2),Cmatr(3*natom-3,3*natom-3)
     113                 :          12 :  real(dp) :: Cpmatr(3*natom,3*natom),Nmatr(3*natom,3*natom)
     114                 :          12 :  real(dp) :: compl_relaxed(6,6),eigval(3*natom-3)
     115                 :          12 :  real(dp) :: eigvalp(3*natom),eigvec(2,3*natom-3,3*natom-3)
     116                 :          12 :  real(dp) :: eigvecp(2,3*natom,3*natom),elast_relaxed(6,6)
     117                 :          12 :  real(dp) :: kmatrix(3*natom,3*natom)
     118                 :          12 :  real(dp) :: new2(6,6),stress(6),zhpev1(2,2*3*natom-4),zhpev1p(2,2*3*natom-1)
     119                 :          12 :  real(dp) :: zhpev2(3*3*natom-5),zhpev2p(3*3*natom-2)
     120                 :          12 :  real(dp) :: d2cart(2,3*natom,3*natom)
     121                 :             : 
     122                 :             : !***************************************************************************
     123                 :           6 :  compl = zero; compl_clamped = zero; compl_stress = zero
     124                 :           6 :  elast = zero; elast_clamped = zero; elast_stress = zero
     125                 :             : 
     126                 :           6 :  ucvol = crystal%ucvol
     127                 :           6 :  iwrite = iout > 0
     128                 :             : 
     129                 :             : !extraction of the elastic constants from the blkvals
     130                 :             : 
     131         [ +  + ]:          42 :  do ivarA=1,6
     132         [ +  + ]:         258 :    do ivarB=1,6
     133                 :             : !    because the elastic constant is 6*6,
     134                 :             : !    so we should judge if the idir is larger than 3 or not
     135         [ +  + ]:         216 :      if(ivarA>3) then
     136                 :         108 :        ii1=ivarA-3
     137                 :         108 :        ipert1=natom+4  !for the shear modulus
     138                 :             :      else if(ivarA<=3) then
     139                 :         108 :        ii1=ivarA
     140                 :         108 :        ipert1=natom+3  !for the diagonal part
     141                 :             :      end if
     142         [ +  + ]:         216 :      if(ivarB>3) then
     143                 :         108 :        ii2=ivarB-3
     144                 :         108 :        ipert2=natom+4  !for the shear modulus
     145                 :             :      else if(ivarB<=3) then
     146                 :         108 :        ii2=ivarB
     147                 :         108 :        ipert2=natom+3  !for the diagonal part
     148                 :             :      end if
     149                 :         252 :      elast(ivarA,ivarB)=blkval(1,ii1,ipert1,ii2,ipert2,iblok)
     150                 :             :    end do
     151                 :             :  end do
     152                 :             : 
     153                 :             : !then consider the volume, because the unit above is in
     154                 :             : !Hartree, in fact the elastic constant should be in
     155                 :             : !the units of pressure, the energy/volume
     156                 :             : !And then transform the unit to si unit using GPa from Hartree/Bohr^3
     157                 :             : 
     158         [ +  + ]:          42 :  do ivarA=1,6
     159         [ +  + ]:         258 :    do ivarB=1,6
     160                 :         252 :      elast(ivarA,ivarB)=(elast(ivarA,ivarB)/ucvol)*HaBohr3_GPa
     161                 :             :    end do
     162                 :             :  end do
     163                 :             : 
     164                 :             : !then should consider the two situations: clamped and relaxed
     165                 :             : !ions respectively, give the initial value of elast_clamped
     166                 :           6 :  elast_clamped(:,:)=elast(:,:)
     167                 :           6 :  elast_relaxed(:,:)=elast(:,:)
     168                 :             : 
     169                 :             : !then do the matrix mulplication of instrain*K*instrain to get the
     170                 :             : !correction of the relaxed ion quantities, in case natom/=1
     171                 :             : 
     172   [ +  -  +  - ]:           6 :  if( (inp%elaflag==2 .or. inp%elaflag==3 .or. inp%elaflag==4 .or. inp%elaflag==5) .and. natom/=1 )then
     173                 :             : !  extracting force matrix at gamma
     174   [ +  +  +  +  :         498 :    d2cart(1,:,:) = RESHAPE(blkval(1,1:3,1:natom,1:3,1:natom,iblok), (/3*natom,3*natom/))
                   +  + ]
     175   [ +  +  +  + ]:         486 :    d2cart(2,:,:) = zero
     176                 :             : 
     177                 :             : !  Eventually impose the acoustic sum rule
     178                 :             : !  FIXME: this might depend on ifcflag: impose that it is 0 or generalize
     179                 :             :    !call asrq0_apply(asrq0, natom, mpert, msize, crystal%xcart, d2cart)
     180                 :           6 :    call asria_corr(inp%asr,d2asr,d2cart,natom,natom)
     181   [ +  +  +  + ]:         486 :    kmatrix = d2cart(1,:,:)
     182                 :             : 
     183                 :             : !  write(std_out,'(/,a,/)')'the k matrix before inverse'
     184                 :             : !  do ii1=1,3*natom
     185                 :             : !  write(std_out,'(6es16.3)')kmatrix(ii1,1),kmatrix(ii1,2),kmatrix(ii1,3),&
     186                 :             : !  & kmatrix(ii1,4),kmatrix(ii1,5),kmatrix(ii1,6)
     187                 :             : !  end do
     188                 :             : 
     189                 :             : !  according to formula, invert the kmatrix(3natom,3natom)
     190                 :             : 
     191                 :             : !  NOTE: MJV 13/3/2011 This is just the 3x3 unit matrix copied throughout the dynamical matrix
     192   [ +  +  +  + ]:         486 :    Nmatr(:,:)=zero
     193         [ +  + ]:          22 :    do ivarB=0,natom-1
     194         [ +  + ]:          70 :      do ivarA=0,natom-1
     195                 :          48 :        Nmatr(3*ivarA+1, 3*ivarB+1) = one
     196                 :          48 :        Nmatr(3*ivarA+2, 3*ivarB+2) = one
     197                 :          64 :        Nmatr(3*ivarA+3, 3*ivarB+3) = one
     198                 :             :      end do
     199                 :             :    end do
     200                 :             : 
     201                 :             : !  The k matrix is not the inverse here - it has not been changed!
     202                 :             : !  write(std_out,'(/,a,/)')'the direct inverse of the Kmatrix'
     203                 :             : !  do ivarA=1,3*natom
     204                 :             : !  write(std_out,'(/)')
     205                 :             : !  do ivarB=1,3*natom
     206                 :             : !  write(std_out,'(es16.6)')kmatrix(ivarA,ivarB)
     207                 :             : !  end do
     208                 :             : !  end do
     209                 :             : 
     210                 :             : 
     211                 :             : !  starting the pseudo-inverse processes then get the eigenvectors of the big matrix,give values to matrixBp
     212                 :             : !  Pack the Nmatr matrix in Hermitian form
     213                 :             :    ii1=1
     214         [ +  + ]:          54 :    do ivarA=1,3*natom
     215         [ +  + ]:         294 :      do ivarB=1,ivarA
     216                 :         240 :        Bpmatr(1,ii1)=Nmatr(ivarB,ivarA)
     217                 :         288 :        ii1=ii1+1
     218                 :             :      end do
     219                 :             :    end do
     220         [ +  + ]:         246 :    Bpmatr(2,:)=zero  !the imaginary part of the force matrix
     221                 :             : !  then call the subroutines CHPEV and ZHPEV to get the eigenvectors
     222                 :             : !  NOTE: MJV there is a huge indeterminacy in this matrix, which has all identical 3x3 block lines
     223                 :             : !  this means the orientation of the 0-eigenvalue eigenvectors is kind of random...
     224                 :             : !  Is the usage just to get out the translational modes? We know what the eigenvectors look like already!
     225                 :             : !  The translational modes are the last 3 with eigenvalue 6
     226                 :             : !
     227                 :           6 :    call ZHPEV ('V','U',3*natom,Bpmatr,eigvalp,eigvecp,3*natom,zhpev1p,zhpev2p,ier)
     228         [ -  + ]:           6 :    ABI_CHECK(ier == 0, sjoin("ZHPEV returned:", itoa(ier)))
     229                 :             : 
     230                 :             : !  the eigenval and eigenvec
     231                 :             : !  write(std_out,'(/,a,/)')'the eigenvalues and eigenvectors'
     232                 :             : !  do ivarA=1,3*natom
     233                 :             : !  write(std_out,'(/)')
     234                 :             : !  write(std_out,'(es16.6)')eigvalp(ivarA)
     235                 :             : !  end do
     236                 :             : !  do ivarA=1,3*natom
     237                 :             : !  write(std_out,'(/)')
     238                 :             : !  do ivarB=1,3*natom
     239                 :             : !  write(std_out,'(es16.6)')eigvecp(1,ivarB,ivarA)
     240                 :             : !  end do
     241                 :             : !  end do
     242                 :             : 
     243                 :             : !  do the multiplication to get the reduced matrix,in two steps
     244                 :             : !  rotate to eigenbasis constructed above to isolate acoustic modes
     245   [ -  +  +  -  :       14904 :    Apmatr(:,:) = MATMUL(TRANSPOSE(eigvecp(1,:,:)), MATMUL(kmatrix(:,:), eigvecp(1,:,:)))
          -  +  +  -  +  
          -  +  -  -  +  
          -  +  +  +  +  
          +  +  +  +  +  
          +  +  +  -  +  
          +  +  +  +  +  
          +  +  +  +  +  
             -  +  -  +  
                      - ]
     246                 :             : 
     247                 :             : !  the blok diagonal parts
     248                 :             : !  write(std_out,'(/,a,/)')'Apmatr'
     249                 :             : !  do ivarA=1,3*natom
     250                 :             : !  write(std_out,'(/)')
     251                 :             : !  do ivarB=1,3*natom
     252                 :             : !  write(std_out,'(es16.6)')Apmatr(ivarA,ivarB)
     253                 :             : !  end do
     254                 :             : !  end do
     255                 :             : 
     256                 :             : !  check the last three eigenvalues whether too large
     257                 :           6 :    ivarB=0
     258         [ +  + ]:          24 :    do ivarA=3*natom-2,3*natom
     259         [ -  + ]:          24 :      if (ABS(Apmatr(ivarA,ivarA))>tol6) ivarB=1
     260                 :             :    end do
     261         [ -  + ]:           6 :    if(ivarB==1)then
     262                 :           0 :      write(message,'(a,a,a,a,a,a,a,a,3es16.6)')ch10,&
     263                 :           0 : &     '  Acoustic sum rule violation met : the eigenvalues of accoustic mode',ch10,&
     264                 :           0 : &     '  are too large at Gamma point',ch10,&
     265                 :           0 : &     '  increase cutoff energy or k-points sampling.',ch10,&
     266                 :           0 : &     '  The three eigenvalues are:',Apmatr(3*natom-2,3*natom-2),&
     267                 :           0 : &     Apmatr(3*natom-1,natom-1),Apmatr(3*natom,3*natom)
     268                 :           0 :      ABI_WARNING(message)
     269                 :           0 :      call wrtout(iout,message,'COLL')
     270                 :             :    end if
     271                 :             : !  then give the value of reduced matrix form Apmatr to Amatr
     272   [ +  +  +  + ]:         234 :    Amatr(:,:) = Apmatr(1:3*natom-3, 1:3*natom-3)
     273                 :             : 
     274                 :             : !  now the reduced matrix is in the Amatr, the convert it
     275                 :             : !  first give the give the value of Bmatr from Amatr
     276                 :             :    ii1=1
     277         [ +  + ]:          36 :    do ivarA=1,3*natom-3
     278         [ +  + ]:         150 :      do ivarB=1,ivarA
     279                 :         114 :        Bmatr(1,ii1)=Amatr(ivarB,ivarA)
     280                 :         144 :        ii1=ii1+1
     281                 :             :      end do
     282                 :             :    end do
     283         [ +  + ]:         120 :    Bmatr(2,:)=zero
     284                 :             : !  then call the subroutines CHPEV and ZHPEV to get the eigenvectors and the eigenvalues
     285                 :           6 :    call ZHPEV ('V','U',3*natom-3,Bmatr,eigval,eigvec,3*natom-3,zhpev1,zhpev2,ier)
     286         [ -  + ]:           6 :    ABI_CHECK(ier == 0, sjoin("ZHPEV returned:", itoa(ier)))
     287                 :             : 
     288                 :             : !  check the unstable phonon modes, if the first is negative then print warning message
     289         [ -  + ]:           6 :    if(eigval(1)<-1.0*tol8)then
     290                 :           0 :      write(message,'(a,a,a,a)') ch10,&
     291                 :           0 :      'Unstable eigenvalue detected in force constant matrix at Gamma point.',ch10,&
     292                 :           0 :      'The system under calculation is physically unstable.'
     293                 :           0 :      ABI_WARNING(message)
     294                 :           0 :      call wrtout(iout,message,'COLL')
     295                 :             :    end if
     296                 :             : 
     297                 :             : !  the do the matrix muplication to get pseudoinverse inverse matrix
     298   [ +  +  +  + ]:         234 :    Cmatr(:,:)=zero
     299         [ +  + ]:          36 :    do ivarA=1,3*natom-3
     300                 :          36 :      Cmatr(ivarA,ivarA)=1.0_dp/eigval(ivarA)
     301                 :             :    end do
     302   [ -  +  +  -  :        5634 :    Amatr(:,:) = MATMUL(MATMUL(eigvec(1,:,:), Cmatr(:,:)), TRANSPOSE(eigvec(1,:,:)))
          -  +  +  -  +  
          -  +  -  -  +  
          -  +  +  +  +  
          +  +  +  +  +  
          +  +  +  -  +  
          +  +  +  +  +  
          +  +  +  +  +  
             -  +  -  +  
                      - ]
     303                 :             : 
     304                 :             : !  write(std_out,'(/,a,/)')'the pseudo inverse of the force matrix'
     305                 :             : !  do ivarA=1,3*natom
     306                 :             : !  write(std_out,'(/)')
     307                 :             : !  do ivarB=1,3*natom
     308                 :             : !  write(std_out,'(es16.6)')Cmatr(ivarA,ivarB)
     309                 :             : !  end do
     310                 :             : !  end do
     311                 :             : 
     312                 :             : !  so now the inverse of the reduced matrix is in the matrixA
     313                 :             : !  now do another mulplication to get the pseudoinverse of the original
     314   [ +  +  +  + ]:         486 :    Cpmatr(:,:)=zero
     315   [ +  +  +  + ]:         486 :    Apmatr(:,:)=zero
     316         [ +  + ]:          36 :    do ivarA=1,3*natom-3
     317         [ +  + ]:         234 :      do ivarB=1,3*natom-3
     318                 :         228 :        Cpmatr(ivarA,ivarB)=Amatr(ivarA,ivarB)
     319                 :             :      end do
     320                 :             :    end do
     321                 :             : 
     322                 :             : !  times the eigvecp
     323         [ +  + ]:          54 :    do ivarA=1,3*natom
     324         [ +  + ]:         486 :      do ivarB=1,3*natom
     325         [ +  + ]:        4800 :        do ii1=1,3*natom
     326                 :        4752 :          Apmatr(ivarA,ivarB)=Apmatr(ivarA,ivarB)+eigvecp(1,ivarA,ii1)*Cpmatr(ii1,ivarB)
     327                 :             :        end do
     328                 :             :      end do
     329                 :             :    end do
     330   [ +  +  +  + ]:         486 :    Cpmatr(:,:)=zero
     331         [ +  + ]:          54 :    do ivarA=1,3*natom
     332         [ +  + ]:         486 :      do ivarB=1,3*natom
     333         [ +  + ]:        4800 :        do ii1=1,3*natom
     334                 :        4752 :          Cpmatr(ivarA,ivarB)=Cpmatr(ivarA,ivarB)+Apmatr(ivarA,ii1)*eigvecp(1,ivarB,ii1)
     335                 :             :        end do
     336                 :             :      end do
     337                 :             :    end do
     338                 :             : 
     339                 :             : !  now the inverse in in Cpmatr
     340   [ +  +  +  + ]:         486 :    kmatrix(:,:)=Cpmatr(:,:)
     341                 :             : !  transfer the inverse of k-matrix back to the k matrix
     342                 :             : !  so now the inverse of k matrix is in the kmatrix
     343                 :             : !  ending the part for pseudoinversing the K matrix
     344   [ -  +  +  -  :        7050 :    new2(:,:) = MATMUL(MATMUL(TRANSPOSE(instrain), kmatrix), instrain(:,:))
          +  -  +  -  -  
          +  -  +  +  +  
          +  +  +  +  +  
          +  +  +  +  -  
          +  +  +  +  +  
          +  +  -  +  -  
                   +  - ]
     345                 :             : 
     346                 :             : 
     347                 :             : !  then finish the matrix mupl., consider the unit cell volume and the unit change next step
     348   [ +  +  +  + ]:         258 :    new2(:,:)=(new2(:,:)/ucvol)*HaBohr3_GPa
     349                 :             : 
     350                 :             : !  then the relaxed one should be the previous one minus the new2 element
     351   [ +  +  +  + ]:         258 :    elast_relaxed(:,:)=elast_relaxed(:,:)-new2(:,:)
     352                 :             :  end if
     353                 :             : !the above end if end if for elaflag=2 or elafalg=3 or elafalg=4, or elafalg=5 in line 125
     354                 :             : 
     355                 :             : !write(std_out,'(/,a,/)')'debug the unit cell volume'
     356                 :             : !write(std_out,'(2es16.6)')ucvol,HaBohr3_GPa
     357                 :             : 
     358                 :             : !then give the initial value of the compl_relaxed(6,6)
     359                 :           6 :  compl_relaxed(:,:)=elast_relaxed(:,:)
     360                 :             : 
     361                 :             : !*******************************************************************
     362         [ +  + ]:           6 :  if(inp%elaflag==1.or. inp%elaflag==3)then
     363                 :             : !  print out the clamped-ion elastic constants to output file
     364                 :           3 :    write(message,'(3a)')ch10,' Elastic Tensor (clamped ion) (unit:10^2GP):',ch10
     365                 :           3 :    call wrtout(std_out,message,'COLL')
     366         [ +  + ]:          21 :    do ivarA=1,6
     367                 :          18 :      write(std_out,'(6f12.7)')elast(ivarA,1)/100.00_dp,elast(ivarA,2)/100.00_dp,&
     368                 :          18 : &     elast(ivarA,3)/100.00_dp,elast(ivarA,4)/100.00_dp,&
     369                 :          39 : &     elast(ivarA,5)/100.00_dp,elast(ivarA,6)/100.00_dp
     370                 :             :    end do
     371                 :             : 
     372                 :           3 :    call wrtout(iout,message,'COLL')
     373         [ +  - ]:           3 :    if (iwrite) then
     374         [ +  + ]:          21 :      do ivarA=1,6
     375                 :          18 :        write(iout,'(6f12.7)')elast(ivarA,1)/100.00_dp,elast(ivarA,2)/100.00_dp,&
     376                 :          18 : &       elast(ivarA,3)/100.00_dp,elast(ivarA,4)/100.00_dp,&
     377                 :          39 : &       elast(ivarA,5)/100.00_dp,elast(ivarA,6)/100.00_dp
     378                 :             :      end do
     379                 :             :    end if
     380                 :             :  end if
     381                 :             : 
     382         [ +  - ]:           6 :  if(inp%elaflag==2.or.inp%elaflag==3 .or. inp%elaflag==4.or. inp%elaflag==5)then
     383         [ -  + ]:           6 :    if(inp%instrflag==0)then
     384                 :           0 :      write(message,'(a,a,a,a,a,a,a,a)' )ch10,&
     385                 :           0 : &     'in order to get the elastic  tensor(relaxed ion), ',ch10,&
     386                 :           0 : &     'one needs information about internal strain ',ch10,&
     387                 :           0 : &     'one should set  instrflag==1;',ch10,&
     388                 :           0 : &     'otherwise the program will continue but give wrong values.'
     389                 :           0 :      ABI_WARNING(message)
     390                 :           0 :      call wrtout(iout,message,'COLL')
     391                 :             :    end if
     392                 :             : 
     393                 :           6 :    write(message,'(5a)')ch10,&
     394                 :           6 : &   ' Elastic Tensor (relaxed ion) (unit:10^2GP):',ch10,&
     395                 :          12 : &   '  (at fixed electric field boundary condition)',ch10
     396                 :           6 :    call wrtout(std_out,message,'COLL')
     397         [ +  + ]:          42 :    do ivarA=1,6
     398                 :          36 :      write(std_out,'(6f12.7)')elast_relaxed(ivarA,1)/100.00_dp,&
     399                 :          36 : &     elast_relaxed(ivarA,2)/100.00_dp,elast_relaxed(ivarA,3)/100.00_dp,&
     400                 :          36 : &     elast_relaxed(ivarA,4)/100.00_dp,elast_relaxed(ivarA,5)/100.00_dp,&
     401                 :          78 : &     elast_relaxed(ivarA,6)/100.00_dp
     402                 :             :    end do
     403                 :             : 
     404                 :           6 :    call wrtout(iout,message,'COLL')
     405         [ +  - ]:           6 :    if (iwrite) then
     406         [ +  + ]:          42 :      do ivarA=1,6
     407                 :          36 :        write(iout,'(6f12.7)')elast_relaxed(ivarA,1)/100.00_dp,&
     408                 :          36 : &       elast_relaxed(ivarA,2)/100.00_dp,elast_relaxed(ivarA,3)/100.00_dp,&
     409                 :          36 : &       elast_relaxed(ivarA,4)/100.00_dp,elast_relaxed(ivarA,5)/100.00_dp,&
     410                 :          78 : &       elast_relaxed(ivarA,6)/100.00_dp
     411                 :             :      end do
     412                 :             :    end if
     413                 :             :  end if
     414                 :             : 
     415                 :             : !then print the corresponding compliances
     416                 :             : 
     417         [ +  + ]:           6 :  if(inp%elaflag==1.or.inp%elaflag==3)then
     418                 :             : !  compl(:,:)=elast_clamped(:,:) !convert the elastic tensor
     419                 :           3 :    compl_clamped(:,:)=elast_clamped(:,:)
     420                 :           3 :    call matrginv(compl_clamped,6,6)
     421                 :           3 :    write(message,'(a,a,a)')ch10,' Compliance Tensor (clamped ion) (unit: 10^-2GP^-1):',ch10
     422                 :           3 :    call wrtout(std_out,message,'COLL')
     423                 :             : 
     424         [ +  + ]:          21 :    do ivarB=1,6
     425                 :          18 :      write(std_out,'(6f12.7)')compl_clamped(ivarB,1)*100.00_dp,&
     426                 :          18 : &     compl_clamped(ivarB,2)*100.00_dp,&
     427                 :          18 : &     compl_clamped(ivarB,3)*100.00_dp,compl_clamped(ivarB,4)*100.00_dp,&
     428                 :          18 : &     compl_clamped(ivarB,5)*100.00_dp,&
     429                 :          39 : &     compl_clamped(ivarB,6)*100.00_dp
     430                 :             :    end do
     431                 :             : 
     432                 :           3 :    call wrtout(iout,message,'COLL')
     433                 :             : 
     434         [ +  - ]:           3 :    if (iwrite) then
     435         [ +  + ]:          21 :      do ivarB=1,6
     436                 :          18 :        write(iout,'(6f12.7)')compl_clamped(ivarB,1)*100.00_dp,&
     437                 :          18 : &       compl_clamped(ivarB,2)*100.00_dp,&
     438                 :          18 : &       compl_clamped(ivarB,3)*100.00_dp,compl_clamped(ivarB,4)*100.00_dp,&
     439                 :          18 : &       compl_clamped(ivarB,5)*100.00_dp,&
     440                 :          39 : &       compl_clamped(ivarB,6)*100.00_dp
     441                 :             :      end do
     442                 :             :    end if
     443                 :             :  end if
     444                 :             : 
     445         [ +  - ]:           6 :  if(inp%elaflag==2.or.inp%elaflag==3 .or. inp%elaflag==4 .or. inp%elaflag==5)then
     446                 :             : !  compl(:,:)=elast_relaxed(:,:)
     447                 :           6 :    call matrginv(compl_relaxed,6,6)
     448         [ -  + ]:           6 :    if(inp%instrflag==0)then
     449                 :           0 :      write(message,'(a,a,a,a,a,a,a,a)' )ch10,&
     450                 :           0 : &     'in order to get the compliance tensor(relaxed ion), ',ch10,&
     451                 :           0 : &     'one needs information about internal strain ',ch10,&
     452                 :           0 : &     'one should set  instrflag==1;',ch10,&
     453                 :           0 : &     'otherwise the program will continue but give wrong values.'
     454                 :           0 :      ABI_WARNING(message)
     455                 :           0 :      call wrtout(iout,message,'COLL')
     456                 :             :    end if
     457                 :           6 :    write(message,'(5a)')ch10,&
     458                 :           6 : &   ' Compliance Tensor (relaxed ion)  (unit: 10^-2GP^-1):',ch10,&
     459                 :          12 : &   '  (at fixed electric field boundary condition)',ch10
     460                 :           6 :    call wrtout(std_out,message,'COLL')
     461                 :             : 
     462         [ +  + ]:          42 :    do ivarB=1,6
     463                 :          36 :      write(std_out,'(6f12.7)')compl_relaxed(ivarB,1)*100.00_dp,&
     464                 :          36 : &     compl_relaxed(ivarB,2)*100.00_dp,&
     465                 :          36 : &     compl_relaxed(ivarB,3)*100.00_dp,compl_relaxed(ivarB,4)*100.00_dp,&
     466                 :          36 : &     compl_relaxed(ivarB,5)*100.00_dp,&
     467                 :          78 : &     compl_relaxed(ivarB,6)*100.00_dp
     468                 :             :    end do
     469                 :           6 :    call wrtout(iout,message,'COLL')
     470                 :             : 
     471         [ +  - ]:           6 :    if (iwrite) then
     472         [ +  + ]:          42 :      do ivarB=1,6
     473                 :          36 :        write(iout,'(6f12.7)')compl_relaxed(ivarB,1)*100.00,&
     474                 :          36 : &       compl_relaxed(ivarB,2)*100.00_dp,&
     475                 :          36 : &       compl_relaxed(ivarB,3)*100.00_dp,compl_relaxed(ivarB,4)*100.00_dp,&
     476                 :          36 : &       compl_relaxed(ivarB,5)*100.00_dp,&
     477                 :          78 : &       compl_relaxed(ivarB,6)*100.00_dp
     478                 :             :      end do
     479                 :             :    end if
     480                 :             :  end if
     481                 :             : 
     482                 :             : !befor the end , make sure the tensor elast(6,6)
     483                 :             : !will have the relaxed ion values and tensor elast_clamped has the clamped ion
     484                 :             : !values, and similarily for the corresponding compliance tensors
     485                 :           6 :  elast_clamped(:,:)=elast(:,:)
     486                 :           6 :  elast(:,:)=elast_relaxed(:,:)
     487                 :           6 :  compl(:,:)=compl_relaxed(:,:)
     488                 :             : 
     489                 :             : !begin the part of computing stress corrected elastic tensors
     490         [ +  + ]:           6 :  if(inp%elaflag==5)then
     491                 :             : 
     492                 :             : !  check the iblok number of first derivative of energy
     493                 :             : !  write(std_out,'(/,a,/)')'iblok number at 8:00Pm'
     494                 :             : !  write(std_out,'(i)')iblok_stress
     495                 :             : !  write(std_out,'(a,f12.7)')'the total energy', blkval(1,1,1)
     496                 :             : !  write(std_out,*)'',blkval(1,:,:,:,:,iblok_stress)
     497                 :             : !  write(std_out,*)'',blkval(1,:,7,1,1,iblok_stress)
     498                 :             : 
     499                 :             : !  firts give the corect stress values diagonal parts
     500                 :           1 :    stress(1)=blkval(1,1,natom+3,1,1,iblok_stress)
     501                 :           1 :    stress(2)=blkval(1,2,natom+3,1,1,iblok_stress)
     502                 :           1 :    stress(3)=blkval(1,3,natom+3,1,1,iblok_stress)
     503                 :             : !  the shear parts
     504                 :           1 :    stress(4)=blkval(1,1,natom+4,1,1,iblok_stress)
     505                 :           1 :    stress(5)=blkval(1,2,natom+4,1,1,iblok_stress)
     506                 :           1 :    stress(6)=blkval(1,3,natom+4,1,1,iblok_stress)
     507                 :             : !  then convert the unit from atomic to the GPa unit
     508         [ +  + ]:           7 :    do ivarA=1,6
     509                 :           7 :      stress(ivarA)=stress(ivarA)*HaBohr3_GPa
     510                 :             :    end do
     511                 :             : !  give the initial values of elast_stress tensor
     512                 :           1 :    elast_stress(:,:)=elast_relaxed(:,:)
     513                 :             : !  notice that only the first three rows need to be corrected
     514         [ +  + ]:           4 :    do ivarA=1,3
     515         [ +  + ]:          22 :      do ivarB=1,6
     516                 :          21 :        elast_stress(ivarA,ivarB)=elast_stress(ivarA,ivarB)-stress(ivarB)
     517                 :             :      end do
     518                 :             :    end do
     519                 :             : !  then compute the values of compliance tensor with stress correction
     520                 :           1 :    compl_stress(:,:)=elast_stress(:,:)
     521                 :           1 :    call matrginv(compl_stress,6,6)
     522                 :             : !  then print out the results of stress corrected elastic and compliance tensors
     523         [ -  + ]:           1 :    if(inp%instrflag==0)then
     524                 :           0 :      write(message,'(a,a,a,a,a,a,a,a)' )ch10,&
     525                 :           0 : &     'In order to get the elastic tensor (relaxed ion with stress correction), ',ch10,&
     526                 :           0 : &     'one needs information about internal strain ',ch10,&
     527                 :           0 : &     'one should set  instrflag==1;',ch10,&
     528                 :           0 : &     'otherwise the program will continue but give wrong values.'
     529                 :           0 :      ABI_WARNING(message)
     530                 :           0 :      call wrtout(iout,message,'COLL')
     531                 :             :    end if
     532                 :           1 :    write(message,'(5a)')ch10,&
     533                 :           1 : &   ' Elastic Tensor (relaxed ion with stress corrected) (unit:10^2GP)',ch10,&
     534                 :           2 : &   '  (at fixed electric field boundary condition)',ch10
     535                 :           1 :    call wrtout(std_out,message,'COLL')
     536                 :           1 :    call wrtout(iout,message,'COLL')
     537         [ +  + ]:           7 :    do ivarA=1,6
     538                 :           6 :      write(std_out,'(6f12.7)')elast_stress(ivarA,1)/100.00_dp,elast_stress(ivarA,2)/100.00_dp,&
     539                 :           6 : &     elast_stress(ivarA,3)/100.00_dp,elast_stress(ivarA,4)/100.00_dp,&
     540                 :          13 : &     elast_stress(ivarA,5)/100.00_dp,elast_stress(ivarA,6)/100.00_dp
     541                 :             :    end do
     542         [ +  - ]:           1 :    if (iwrite) then
     543         [ +  + ]:           7 :      do ivarA=1,6
     544                 :           6 :        write(iout,'(6f12.7)')elast_stress(ivarA,1)/100.00_dp,elast_stress(ivarA,2)/100.00_dp,&
     545                 :           6 : &       elast_stress(ivarA,3)/100.00_dp,elast_stress(ivarA,4)/100.00_dp,&
     546                 :          13 : &       elast_stress(ivarA,5)/100.00_dp,elast_stress(ivarA,6)/100.00_dp
     547                 :             :      end do
     548                 :             :    end if
     549                 :             : 
     550                 :             : !  then the compliance tensors with stress correction
     551                 :           1 :    write(message,'(5a)')ch10,&
     552                 :           1 : &   ' Compliance Tensor (relaxed ion with stress correction) (unit: 10^-2(GP)^-1):',ch10,&
     553                 :           2 : &   '  (at fixed electric field boundary condition)',ch10
     554                 :           1 :    call wrtout(std_out,message,'COLL')
     555                 :           1 :    call wrtout(iout,message,'COLL')
     556         [ +  + ]:           7 :    do ivarB=1,6
     557                 :           6 :      write(std_out,'(6f12.7)')compl_stress(ivarB,1)*100.00_dp,&
     558                 :           6 : &     compl_stress(ivarB,2)*100.00_dp,&
     559                 :           6 : &     compl_stress(ivarB,3)*100.00_dp,compl_stress(ivarB,4)*100.00_dp,&
     560                 :           6 : &     compl_stress(ivarB,5)*100.00_dp,&
     561                 :          13 : &     compl_stress(ivarB,6)*100.00_dp
     562                 :             :    end do
     563         [ +  - ]:           1 :    if (iwrite) then
     564         [ +  + ]:           7 :      do ivarB=1,6
     565                 :           6 :        write(iout,'(6f12.7)')compl_stress(ivarB,1)*100.00_dp,&
     566                 :           6 : &       compl_stress(ivarB,2)*100.00_dp,&
     567                 :           6 : &       compl_stress(ivarB,3)*100.00_dp,compl_stress(ivarB,4)*100.00_dp,&
     568                 :           6 : &       compl_stress(ivarB,5)*100.00_dp,&
     569                 :          13 : &       compl_stress(ivarB,6)*100.00_dp
     570                 :             :      end do
     571                 :             :    end if
     572                 :             :  end if
     573                 :             : !end the if 510th line
     574                 :             : !end the part of stress corrected elastic and compliance tensors
     575                 :             : 
     576                 :             : 
     577                 :             :  ! Writes the elastic constants tensors (clamped-ion, relaxed-ion with and
     578                 :             :  ! without stress corrections) to a netCDF file.
     579                 :             :  !
     580                 :             :  ! compl=relaxed-ion compliance tensor(without stress correction) (6*6) in Voigt notation
     581                 :             :  ! compl_clamped=clamped-ion compliance tensor(without stress correction) (6*6) in Voigt notation
     582                 :             :  ! compl_stress=relaxed-ion compliance tensor(with stress correction) (6*6) in Voigt notation
     583                 :             :  ! elast=relaxed-ion elastic tensor(without stress correction) (6*6) in Voigt notation
     584                 :             :  ! elast_clamped=clamped-ion elastic tensor(without stress correction) (6*6) in Voigt notation
     585                 :             :  ! elast_stress=relaxed-ion elastic tensor(with stress correction) (6*6) in Voigt notation
     586                 :             :  ! Units are GPa for elastic constants and GPa^-1 for compliance constants
     587                 :             : 
     588         [ +  - ]:           6 :  if (ncid /= nctk_noid) then
     589                 :             :    ! Define dimensions
     590         [ -  + ]:           6 :    NCF_CHECK(nctk_def_basedims(ncid, defmode=.True.))
     591                 :             : 
     592         [ +  + ]:          24 :    ncerr = nctk_def_iscalars(ncid, [character(len=nctk_slen) :: "asr", "elaflag", "instrflag"])
     593         [ -  + ]:           6 :    NCF_CHECK(ncerr)
     594                 :             : 
     595                 :             :    !arrays
     596                 :             :    ncerr = nctk_def_arrays(ncid, [&
     597                 :             :      nctkarr_t('internal_strain_tensor', "dp", 'natom3, six'), &
     598                 :             :      nctkarr_t('compliance_constants_relaxed_ion', "dp", 'six, six'), &
     599                 :             :      nctkarr_t('compliance_constants_clamped_ion', "dp", 'six, six'), &
     600                 :             :      nctkarr_t('compliance_constants_relaxed_ion_stress_corrected', "dp", "six, six"), &
     601                 :             :      nctkarr_t('elastic_constants_relaxed_ion', "dp", 'six, six'), &
     602                 :             :      nctkarr_t('elastic_constants_clamped_ion', "dp", 'six, six'), &
     603         [ +  + ]:          48 :      nctkarr_t('elastic_constants_relaxed_ion_stress_corrected', "dp", 'six, six')])
     604         [ -  + ]:           6 :    NCF_CHECK(ncerr)
     605                 :             : 
     606                 :             :    ! Write variables.
     607         [ -  + ]:           6 :    NCF_CHECK(nctk_set_datamode(ncid))
     608         [ -  + ]:           6 :    NCF_CHECK(nf90_put_var(ncid, vid('asr'), inp%asr))
     609         [ -  + ]:           6 :    NCF_CHECK(nf90_put_var(ncid, vid('elaflag'), inp%elaflag))
     610         [ -  + ]:           6 :    NCF_CHECK(nf90_put_var(ncid, vid('instrflag'), inp%instrflag))
     611         [ -  + ]:           6 :    NCF_CHECK(nf90_put_var(ncid, vid('internal_strain_tensor'), instrain))
     612         [ -  + ]:           6 :    NCF_CHECK(nf90_put_var(ncid, vid('compliance_constants_relaxed_ion'), compl))
     613         [ -  + ]:           6 :    NCF_CHECK(nf90_put_var(ncid, vid('compliance_constants_clamped_ion'), compl_clamped))
     614         [ -  + ]:           6 :    NCF_CHECK(nf90_put_var(ncid, vid('compliance_constants_relaxed_ion_stress_corrected'), compl_stress))
     615         [ -  + ]:           6 :    NCF_CHECK(nf90_put_var(ncid, vid('elastic_constants_relaxed_ion'), elast))
     616         [ -  + ]:           6 :    NCF_CHECK(nf90_put_var(ncid, vid('elastic_constants_clamped_ion'), elast_clamped))
     617         [ -  + ]:           6 :    NCF_CHECK(nf90_put_var(ncid, vid('elastic_constants_relaxed_ion_stress_corrected'), elast_stress))
     618                 :             :  end if
     619                 :             : 
     620                 :             : contains
     621                 :             : 
     622                 :          60 :  integer function vid(vname)
     623                 :             :    character(len=*),intent(in) :: vname
     624                 :          60 :    vid = nctk_idname(ncid, vname)
     625                 :             :  end function vid
     626                 :             : 
     627                 :             : end subroutine ddb_elast
     628                 :             : !!***
     629                 :             : 
     630   [ +  -  +  -  :          18 : end module m_ddb_elast
                   +  - ]
     631                 :             : !!***
        

Generated by: LCOV version 2.3-1