LCOV - code coverage report
Current view: top level - src/77_ddb - m_relaxpol.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 92.5 % 307 284
Test Date: 2026-11-06 11:53:17 Functions: 100.0 % 1 1
Branches: 72.8 % 452 329

             Branch data     Line data    Source code
       1                 :             : !!****m* ABINIT/m_relaxpol
       2                 :             : !! NAME
       3                 :             : !!  m_relaxpol
       4                 :             : !!
       5                 :             : !! FUNCTION
       6                 :             : !!
       7                 :             : !! COPYRIGHT
       8                 :             : !!  Copyright (C) 1999-2026 ABINIT group (MVeithen)
       9                 :             : !!  This file is distributed under the terms of the
      10                 :             : !!  GNU General Public License, see ~abinit/COPYING
      11                 :             : !!  or http://www.gnu.org/copyleft/gpl.txt .
      12                 :             : !!
      13                 :             : !! SOURCE
      14                 :             : 
      15                 :             : #if defined HAVE_CONFIG_H
      16                 :             : #include "config.h"
      17                 :             : #endif
      18                 :             : 
      19                 :             : #include "abi_common.h"
      20                 :             : 
      21                 :             : module m_relaxpol
      22                 :             : 
      23                 :             :  use defs_basis
      24                 :             :  use m_abicore
      25                 :             :  use m_errors
      26                 :             : 
      27                 :             :  use m_fstrings,  only : sjoin, itoa
      28                 :             :  use m_matrix,    only : matr3inv
      29                 :             :  use m_berrytk,   only : polcart
      30                 :             :  use m_hide_lapack,   only : dzgedi, dzgefa
      31                 :             :  use m_geometry,  only : xcart2xred
      32                 :             :  use m_dynmat,    only : symdyma
      33                 :             :  use m_crystal,   only : crystal_t
      34                 :             : 
      35                 :             :  implicit none
      36                 :             : 
      37                 :             :  private
      38                 :             : !!***
      39                 :             : 
      40                 :             :  public :: relaxpol
      41                 :             : !!***
      42                 :             : 
      43                 :             : contains
      44                 :             : !!***
      45                 :             : 
      46                 :             : !!****f* ABINIT/relaxpol
      47                 :             : !! NAME
      48                 :             : !! relaxpol
      49                 :             : !!
      50                 :             : !! FUNCTION
      51                 :             : !! 1) Compute polarization in cartesian coordinates
      52                 :             : !! 2) Structural relaxation at fixed polarization: this routine
      53                 :             : !!    solves the linear system of equations Eq.(13)
      54                 :             : !!    of Na Sai et al., PRB 66, 104108 (2002) [[cite:Sai2002]].
      55                 :             : !!
      56                 :             : !! INPUTS
      57                 :             : !! blkflg(msize) = flag for every matrix element (0=> the element
      58                 :             : !!   is not in the data block), (1=> the element is in the data blok)
      59                 :             : !! blkval(2,msize) = matrix that contains the second-order energy derivatives
      60                 :             : !! etotal = Kohn-Sham energy at zero electric field
      61                 :             : !! gred(3,natom) = -1 times the forces in reduced coordinates
      62                 :             : !! iatfix(natom) = indices of the atoms that are held fixed in the relaxation
      63                 :             : !! iout = unit number for output
      64                 :             : !! istrfix(6) = indices of the elements of the strain tensor that
      65                 :             : !!   are held fixed in the relaxation
      66                 :             : !!      1 = xx
      67                 :             : !!      2 = yy
      68                 :             : !!      3 = zz
      69                 :             : !!      4 = yz & zy
      70                 :             : !!      5 = xz & zx
      71                 :             : !!      6 = xy & yx
      72                 :             : !! mpert = maximum number of ipert
      73                 :             : !! msize = dimension of blkflg and blkval
      74                 :             : !! natfix = number of atoms that are held fixed in the relaxation
      75                 :             : !! natom = number of atoms in the unit cell
      76                 :             : !! nstrfix = number of elements of the strain tensor that are held fixed in the relaxation
      77                 :             : !! pel(3) = electronic polarization not taking into account the factor 1/ucvol
      78                 :             : !!  red_ptot(3) = total polarization reduced units   !!REC
      79                 :             : !! relaxat = 1: relax atomic positions
      80                 :             : !!         = 0: do not relax atomic positions
      81                 :             : !! relaxstr = 1: relax cell parameters
      82                 :             : !!          = 0: do not relax cell parameters
      83                 :             : !! strten(6) = stress tensor in cartesian coordinates
      84                 :             : !! targetpol(3) = target value of the polarization
      85                 :             : !!
      86                 :             : !! OUTPUT
      87                 :             : !!
      88                 :             : !! NOTES
      89                 :             : !! - The elements of the dynamical matrix stored in blkval
      90                 :             : !!   are symmetrized before computing the new atomic positions and cell parameters.
      91                 :             : !! - In case relaxat = 0 and relaxstr = 0, the routine only
      92                 :             : !!   computes the polarization in cartesian coordinates.
      93                 :             : !!
      94                 :             : !! SOURCE
      95                 :             : 
      96                 :           3 : subroutine relaxpol(Crystal,blkflg,blkval,etotal,gred,iatfix,iout,istrfix,&
      97                 :             : & mpert,msize,natfix,natom,nstrfix,pel,red_ptot,relaxat,relaxstr,&
      98                 :             : & strten,targetpol)
      99                 :             : 
     100                 :             : !Arguments -------------------------------
     101                 :             : !scalars
     102                 :             :  integer,intent(in) :: iout,mpert,msize,natfix,natom,nstrfix
     103                 :             :  integer,intent(in) :: relaxat,relaxstr
     104                 :             :  real(dp),intent(in) :: etotal
     105                 :             :  type(crystal_t),intent(in) :: Crystal
     106                 :             : !arrays
     107                 :             :  integer,intent(in) :: blkflg(msize),iatfix(natom)
     108                 :             :  integer,intent(in) :: istrfix(6)
     109                 :             :  real(dp),intent(in) :: gred(3,natom),pel(3),strten(6)
     110                 :             :  real(dp),intent(in) :: red_ptot(3)
     111                 :             :  real(dp),intent(inout) :: blkval(2,msize),targetpol(3)
     112                 :             : 
     113                 :             : !Local variables -------------------------
     114                 :             : !scalars
     115                 :             :  integer :: flag,iatom,idir,ii,index,index1,index_tild,info,ipert,istrain
     116                 :             :  integer :: itypat,jdir,job,jpert,polunit,posi,posj,sizef
     117                 :             :  integer :: usepaw
     118                 :             :  logical :: iwrite
     119                 :             :  real(dp) :: e1,fmax,poltmp,sigmax,tol,value,ucvol
     120                 :             :  character(len=500) :: message
     121                 :             : !arrays
     122                 :             :  integer :: irelaxstrain(6)
     123                 :           3 :  integer,allocatable :: ipvt(:),irelaxat(:),rfpert(:,:)
     124                 :           6 :  real(dp) :: acell_new(3),delta_eta(6),delta_xcart(3,natom),det(2,2),diffpol(3),rprimd(3,3)
     125                 :             :  real(dp) :: diffsig(6),favg(3),gprimd(3,3),lambda(3),pel_cart(3),pelev(3)
     126                 :             :  real(dp) :: pion(3),pion_cart(3),ptot_cart(3),qphon(3),rprim(3,3)
     127                 :             :  real(dp) :: rprimd_new(3,3),sigelfd(6),strainmat(3,3)
     128                 :           6 :  real(dp) :: xcart_new(3,natom),xred_new(3,natom)
     129                 :           3 :  real(dp),allocatable :: cfac(:,:),delta(:),dymati(:),fcart(:,:),fcmat(:,:,:)
     130                 :           3 :  real(dp),allocatable :: fdiff(:,:),felfd(:,:),ifcmat(:,:,:),vec(:),zgwork(:,:)
     131                 :             : 
     132                 :             : ! *********************************************************************
     133                 :             : 
     134                 :           3 :  usepaw = 0
     135   [ +  +  +  + ]:          39 :  rprimd = Crystal%rprimd
     136                 :           3 :  ucvol = Crystal%ucvol
     137                 :           3 :  iwrite = iout > 0
     138                 :             : 
     139                 :             : !Check if some degrees of freedom remain fixed during the optimization
     140                 :             : 
     141   [ -  +  +  -  :           9 :  ABI_MALLOC(irelaxat,(natom))
          +  -  +  -  -  
                +  -  + ]
     142   [ +  +  +  + ]:          30 :  irelaxat(:) = 1   ; irelaxstrain(:) = 1
     143         [ -  + ]:           3 :  if (natfix > 0) then
     144         [ #  # ]:           0 :    do ii = 1, natfix
     145                 :           0 :      iatom = iatfix(ii)
     146   [ #  #  #  # ]:           0 :      if ((iatom > natom).or.(iatom < 0)) then
     147                 :             :        write(message, '(a,i0,a,i0,a,a,a,a,a)')&
     148                 :           0 : &       'The value of iatfix(',ii,') is ',iatom,', which is not allowed.',ch10,&
     149                 :           0 : &       'iatfix must be larger than 0 and smaller than natom.',ch10,&
     150                 :           0 : &       'Action: correct iatfix in your input file.'
     151                 :           0 :        ABI_ERROR(message)
     152                 :             :      end if
     153                 :           0 :      irelaxat(iatom) = 0
     154                 :             :    end do
     155                 :             :  end if
     156                 :             : 
     157         [ +  + ]:           3 :  if (nstrfix > 0) then
     158         [ +  + ]:           3 :    do ii = 1, nstrfix
     159                 :           2 :      istrain = istrfix(ii)
     160         [ -  + ]:           2 :      if ((istrain > 6).or.(istrain < 0)) then
     161                 :             :        write(message, '(a,i0,a,i0,a,a,a,a,a)')&
     162                 :           0 : &       'istrfix(',ii,') is',istrain,', which is not allowed.',ch10,&
     163                 :           0 : &       'istrfix must be larger than 0 and smaller than 6.',ch10,&
     164                 :           0 : &       'Action : correct istrfix in your input file.'
     165                 :           0 :        ABI_ERROR(message)
     166                 :             :      end if
     167                 :           3 :      irelaxstrain(istrain) = 0
     168                 :             :    end do
     169                 :             :  end if
     170                 :             : 
     171                 :             : 
     172   [ -  +  +  -  :           9 :  ABI_MALLOC(rfpert,(mpert,3))
          +  -  +  -  -  
                +  -  + ]
     173   [ -  +  +  -  :          12 :  ABI_MALLOC(cfac,(mpert,mpert))
          -  +  +  -  +  
          -  +  -  -  +  
                   -  + ]
     174                 :           3 :  call matr3inv(rprimd,gprimd)
     175                 :             : 
     176                 :             : !Compute the size of the matrix that contains the second-order derivatives
     177                 :             : 
     178                 :           3 :  sizef = 3
     179   [ +  +  +  + ]:         165 :  rfpert(:,:) = 0
     180         [ +  + ]:          12 :  rfpert(natom+2,1:3) = 1
     181         [ +  + ]:           3 :  if (relaxat == 1) then
     182         [ +  + ]:           9 :    do iatom = 1, natom
     183         [ +  - ]:           9 :      if (irelaxat(iatom) == 1) then
     184                 :           7 :        sizef = sizef + 3
     185         [ +  + ]:          28 :        rfpert(iatom,1:3) = 1
     186                 :             :      end if
     187                 :             :    end do
     188                 :             :  end if
     189                 :           3 :  ii = natom + 2
     190         [ +  + ]:           3 :  if (relaxstr == 1) then
     191                 :           2 :    istrain = 0
     192         [ +  + ]:           6 :    do ipert = (natom+3), (natom+4)
     193         [ +  + ]:          18 :      do idir = 1, 3
     194                 :          12 :        istrain = istrain + 1
     195         [ +  + ]:          16 :        if (irelaxstrain(istrain) == 1) then
     196                 :          10 :          sizef = sizef + 1
     197                 :          10 :          rfpert(ipert,idir) = 1
     198                 :             :        end if
     199                 :             :      end do
     200                 :             :    end do
     201                 :             :  end if
     202                 :             : 
     203   [ -  +  +  -  :          12 :  ABI_MALLOC(fcmat,(2,sizef,sizef))
          -  +  +  -  +  
          -  +  -  -  +  
                   -  + ]
     204   [ -  +  +  -  :           9 :  ABI_MALLOC(ifcmat,(2,sizef,sizef))
          -  +  +  -  -  
                +  -  + ]
     205   [ -  +  +  -  :           9 :  ABI_MALLOC(vec,(sizef))
          +  -  +  -  -  
                +  -  + ]
     206   [ -  +  +  -  :           6 :  ABI_MALLOC(delta,(sizef))
             -  +  -  + ]
     207   [ -  +  +  -  :           9 :  ABI_MALLOC(ipvt,(sizef))
          +  -  +  -  -  
                +  -  + ]
     208   [ -  +  +  -  :           9 :  ABI_MALLOC(zgwork,(2,sizef))
          +  -  +  -  -  
                +  -  + ]
     209   [ -  +  +  -  :           9 :  ABI_MALLOC(fcart,(3,natom))
          +  -  +  -  -  
                +  -  + ]
     210   [ -  +  +  -  :           6 :  ABI_MALLOC(felfd,(3,natom))
             -  +  -  + ]
     211   [ -  +  +  -  :           6 :  ABI_MALLOC(fdiff,(3,natom))
             -  +  -  + ]
     212                 :             : 
     213                 :             : !Build the vector that stores the forces, sigma and the polarization
     214                 :             : 
     215         [ +  + ]:          43 :  vec(:) = zero
     216                 :           3 :  posi = 0
     217                 :             : 
     218         [ +  + ]:           3 :  if (relaxat == 1) then
     219                 :             : 
     220                 :             : !  Note conversion to cartesian coordinates (bohr) AND
     221                 :             : !  negation to make a force out of a gradient
     222                 :             : !  Also subtract off average force from each force
     223                 :             : !  component to avoid spurious drifting of atoms across cell.
     224                 :           2 :    favg(:) = zero
     225         [ +  + ]:           9 :    do iatom = 1, natom
     226         [ +  + ]:          30 :      do idir = 1, 3
     227                 :             :        fcart(idir,iatom) = -(gprimd(idir,1)*gred(1,iatom) + &
     228                 :             : &       gprimd(idir,2)*gred(2,iatom) + &
     229                 :          21 : &       gprimd(idir,3)*gred(3,iatom))
     230                 :          28 :        favg(idir) = favg(idir) + fcart(idir,iatom)
     231                 :             :      end do
     232                 :             :    end do
     233         [ +  + ]:           8 :    favg(:) = favg(:)/dble(natom)
     234         [ +  + ]:           9 :    do iatom = 1, natom
     235         [ +  + ]:          30 :      fcart(:,iatom) = fcart(:,iatom) - favg(:)
     236                 :             :    end do
     237                 :             : 
     238         [ +  + ]:           9 :    do iatom = 1, natom
     239         [ +  - ]:           9 :      if (irelaxat(iatom) == 1) then
     240         [ +  + ]:          28 :        do idir = 1, 3
     241                 :          21 :          posi = posi + 1
     242                 :          28 :          vec(posi) = fcart(idir,iatom)
     243                 :             :        end do
     244                 :             :      end if
     245                 :             :    end do
     246                 :             : 
     247                 :             :  end if    ! relaxat == 1
     248                 :             : 
     249                 :             : !DEBUG
     250                 :             : !write(std_out,*)'Forces in cartesian coords'
     251                 :             : !do iatom = 1, natom
     252                 :             : !write(std_out,'(3(2x,e16.9))')(fcart(idir,iatom),idir = 1, 3)
     253                 :             : !end do
     254                 :             : !stop
     255                 :             : !ENDDEBUG
     256                 :             : 
     257                 :             : !Transform target polarization to atomic units
     258         [ +  + ]:          12 :  targetpol(:) = targetpol(:)*((Bohr_Ang*1.0d-10)**2)/e_Cb
     259                 :             : 
     260                 :             : !Compute ionic polarization
     261                 :           3 :  pion(:) = zero
     262         [ +  + ]:          12 :  do iatom = 1, natom
     263                 :           9 :    itypat = Crystal%typat(iatom)
     264         [ +  + ]:          39 :    do idir = 1, 3
     265                 :          27 :      poltmp = Crystal%zion(itypat) * Crystal%xred(idir,iatom)
     266                 :          27 :      poltmp = poltmp - two*nint(poltmp/two)   ! fold into [-1,1]
     267                 :          36 :      pion(idir) = pion(idir) + poltmp
     268                 :             :    end do
     269                 :             :  end do
     270         [ +  + ]:          12 :  do idir = 1, 3
     271                 :          12 :    pion(idir) = pion(idir) - two*nint(pion(idir)/two) ! fold into [-1,1]
     272                 :             :  end do
     273                 :             : 
     274                 :             : !Transform the polarization to cartesian coordinates
     275                 :           3 :  polunit = 3
     276                 :           3 :  pelev=zero  ! This is a PAW-related quantity, which we ignore here.
     277                 :             :  call polcart(red_ptot,pel,pel_cart,pelev,pion,pion_cart,polunit,&
     278                 :           3 : & ptot_cart,rprimd,ucvol,iout,usepaw)
     279                 :             : 
     280         [ +  + ]:          12 :  do idir = 1, 3
     281                 :           9 :    posi = posi + 1
     282                 :          12 :    vec(posi) = ptot_cart(idir) - targetpol(idir)
     283                 :             :  end do
     284                 :             : 
     285                 :             : 
     286         [ +  + ]:           3 :  if (relaxstr == 1) then
     287         [ +  + ]:          14 :    do istrain = 1, 6
     288         [ +  + ]:          14 :      if (irelaxstrain(istrain) == 1) then
     289                 :          10 :        posi = posi + 1
     290                 :          10 :        vec(posi) = -1._dp*strten(istrain)*ucvol
     291                 :             :      end if
     292                 :             :    end do
     293                 :             :  end if
     294                 :             : 
     295                 :             : 
     296                 :             : !Symmetrize the dynamical matrix
     297                 :             : 
     298   [ +  -  -  +  :           9 :  ABI_MALLOC(dymati,(2*3*natom*3*natom))
          +  -  +  -  +  
             -  -  +  -  
                      + ]
     299                 :             : !by the symdyma routine
     300         [ +  + ]:          12 :  do ipert = 1, natom
     301         [ +  + ]:          39 :    do idir = 1, 3
     302         [ +  + ]:         135 :      do jpert = 1, natom
     303         [ +  + ]:         423 :        do jdir = 1, 3
     304                 :         297 :          index  = jdir +3*((jpert - 1) + mpert*((idir - 1) + 3*(ipert - 1)))
     305                 :         297 :          index1 = jdir +3*((jpert - 1) + natom*((idir - 1) + 3*(ipert - 1)))
     306                 :         297 :          dymati(2*index1 - 1) = blkval(1,index)
     307                 :         396 :          dymati(2*index1    ) = blkval(2,index)
     308                 :             :        end do
     309                 :             :      end do
     310                 :             :    end do
     311                 :             :  end do
     312                 :             : 
     313                 :           3 :  qphon(:) = zero
     314                 :           3 :  call symdyma(dymati,Crystal%indsym,natom,Crystal%nsym,qphon,rprimd,Crystal%symrel,Crystal%symafm)
     315                 :             : 
     316         [ +  + ]:          12 :  do ipert = 1, natom
     317         [ +  + ]:          39 :    do idir = 1, 3
     318         [ +  + ]:         135 :      do jpert = 1, natom
     319         [ +  + ]:         423 :        do jdir = 1, 3
     320                 :         297 :          index  = jdir +3*((jpert - 1) + mpert*((idir - 1) + 3*(ipert - 1)))
     321                 :         297 :          index1 = jdir +3*((jpert - 1) + natom*((idir - 1) + 3*(ipert - 1)))
     322                 :         297 :          blkval(1,index) = dymati(2*index1 - 1)
     323                 :         396 :          blkval(2,index) = dymati(2*index1    )
     324                 :             :        end do
     325                 :             :      end do
     326                 :             :    end do
     327                 :             :  end do
     328                 :             : 
     329         [ -  + ]:           3 :  ABI_FREE(dymati)
     330                 :             : 
     331                 :             : !Define conversion factors for blkval
     332   [ +  +  +  + ]:         945 :  cfac(:,:) = 1._dp
     333         [ +  + ]:          12 :  cfac(1:natom,natom+2) = -1._dp/ucvol
     334         [ +  + ]:          12 :  cfac(natom+2,1:natom) = -1._dp/ucvol
     335         [ +  + ]:           9 :  cfac(natom+3:natom+4,natom+2) = -1._dp
     336         [ +  + ]:           9 :  cfac(natom+2,natom+3:natom+4) = -1._dp
     337                 :             : 
     338                 :             : 
     339                 :             : !Build the matrix that contains the second-order derivatives
     340                 :             : !ipert = natom + 1 corresponds to the ddk perturbation, that
     341                 :             : !is not needed; so skip it
     342                 :             : 
     343   [ +  +  +  +  :        2197 :  fcmat(:,:,:) = zero
                   +  + ]
     344                 :             : 
     345                 :           3 :  posi = 0
     346                 :           3 :  flag = 0
     347                 :             : ! When fcmat has been build, flag = 0 if all elements were available.
     348                 :             : ! Otherwise, it will be 1. In case one element is missing, check if
     349                 :             : ! it can be obtained by changing the order of the perturbations
     350                 :             : 
     351         [ +  + ]:          54 :  do ipert = 1, mpert
     352         [ +  + ]:         207 :    do idir = 1, 3
     353         [ +  + ]:         204 :      if (rfpert(ipert,idir) == 1) then
     354                 :          40 :        posi = posi + 1
     355                 :          40 :        posj = 0
     356                 :             : 
     357         [ +  + ]:         772 :        do jpert = 1, mpert
     358         [ +  + ]:        2968 :          do jdir = 1, 3
     359         [ +  + ]:        2928 :            if (rfpert(jpert,jdir) == 1) then
     360                 :         718 :              index = jdir +3*((jpert - 1) + mpert*((idir - 1) + 3*(ipert - 1)))
     361                 :         718 :              index_tild = idir +3*((ipert - 1) + mpert*((jdir - 1) + 3*(jpert - 1)))
     362                 :         718 :              posj = posj + 1
     363   [ +  +  +  + ]:         718 :              if ((ipert /= natom + 2).or.(jpert /= natom + 2)) then
     364         [ +  - ]:         691 :                if (blkflg(index) == 1) then
     365         [ +  + ]:        2073 :                  fcmat(:,posi,posj) = blkval(:,index)*cfac(ipert,jpert)
     366         [ #  # ]:           0 :                else if (blkflg(index_tild) == 1) then
     367         [ #  # ]:           0 :                  fcmat(:,posi,posj) = blkval(:,index_tild)*cfac(ipert,jpert)
     368         [ #  # ]:           0 :                  blkval(:,index) = blkval(:,index_tild)
     369                 :             :                else
     370                 :           0 :                  flag = 1
     371                 :           0 :                  write(std_out,'(a,4(2x,i3))')'relaxpol: could not find element:',idir,ipert,jdir,jpert
     372                 :             :                end if
     373                 :             :              end if
     374                 :             : !            DEBUG
     375                 :             : !            write(100,'(4(2x,i3),5x,f16.9)')idir,ipert,jdir,jpert,fcmat(1,posi,posj)
     376                 :             : !            ENDDEBUG
     377                 :             :            end if
     378                 :             :          end do
     379                 :             :        end do
     380                 :             : 
     381                 :             :      end if
     382                 :             :    end do
     383                 :             :  end do
     384                 :             : 
     385         [ -  + ]:           3 :  if (flag == 1) then
     386                 :             :    write(message, '(a,a,a,i0,a,i0,a,a,a,a)' )&
     387                 :           0 : &   'Some of the second order derivatives required to deal with the case',ch10,&
     388                 :           0 : &   'relaxat = ',relaxat,', relaxstr = ', relaxstr, ch10,&
     389                 :           0 : &   'are missing in the DDB.',ch10,&
     390                 :           0 : &   'Action: correct your DDB or change your input file.'
     391                 :           0 :    ABI_ERROR(message)
     392                 :             :  end if
     393                 :             : 
     394                 :             : 
     395                 :             : !Compute the inverse of the force constant matrix
     396                 :             : 
     397   [ +  +  -  + ]:           3 :  if ((relaxat /= 0).or.(relaxstr /= 0)) then
     398                 :             : 
     399                 :           2 :    job = 1          ! compute inverse only
     400   [ +  +  +  +  :        2166 :    ifcmat(:,:,:) = fcmat(:,:,:)
                   +  + ]
     401                 :             : 
     402                 :           2 :    call dzgefa(ifcmat,sizef,sizef,ipvt,info)
     403         [ -  + ]:           2 :    ABI_CHECK(info == 0, sjoin("dzgefa returned:", itoa(info)))
     404                 :           2 :    call dzgedi(ifcmat,sizef,sizef,ipvt,det,zgwork,job)
     405                 :             : 
     406                 :             : !  DEBUG
     407                 :             : !  write(100,*)'relaxat = ',relaxat
     408                 :             : !  write(100,*)'relaxstr = ',relaxstr
     409                 :             : !  write(100,*)'irelaxat = '
     410                 :             : !  write(100,*)irelaxat(:)
     411                 :             : !  write(100,*)'irelaxstrain = '
     412                 :             : !  write(100,*)irelaxstrain(:)
     413                 :             : !  write(100,*)'sizef = ',sizef
     414                 :             : !  write(100,*)'targetpol ='
     415                 :             : !  write(100,*)targetpol(:)
     416                 :             : !  do ipert = 1, sizef
     417                 :             : !  do jpert = 1, sizef
     418                 :             : !  write(100,'(2(2x,i3),2x,e16.9)')ipert,jpert,fcmat(1,ipert,jpert)
     419                 :             : !  end do
     420                 :             : !  end do
     421                 :             : !  stop
     422                 :             : !  ENDDEBUG
     423                 :             : 
     424                 :             : !  Compute \delta R, \delta \eta and \lambda
     425         [ +  + ]:          39 :    delta(:) = zero
     426         [ +  + ]:          39 :    do ipert = 1, sizef
     427         [ +  + ]:         748 :      do jpert = 1, sizef
     428                 :         746 :        delta(ipert) = delta(ipert) + ifcmat(1,ipert,jpert)*vec(jpert)
     429                 :             :      end do
     430                 :             :    end do
     431                 :             : 
     432                 :             : 
     433                 :             : !  Update atomic positions
     434                 :           2 :    posi = 0
     435         [ +  - ]:           2 :    if (relaxat == 1) then
     436                 :             : 
     437   [ +  +  +  + ]:          30 :      delta_xcart(:,:) = zero
     438   [ +  +  +  + ]:          30 :      xcart_new(:,:) = zero
     439         [ +  + ]:           9 :      do iatom = 1, natom
     440         [ +  - ]:           9 :        if (irelaxat(iatom) == 1) then
     441         [ +  + ]:          28 :          do idir = 1, 3
     442                 :          21 :            posi = posi + 1
     443                 :          28 :            delta_xcart(idir,iatom) = delta(posi)
     444                 :             :          end do
     445                 :             :        end if
     446                 :             :      end do
     447                 :             : 
     448                 :             : !    Drop unsignificant digits in order to eleminate numerical noise
     449                 :           2 :      tol = 10000000._dp
     450         [ +  + ]:           9 :      do iatom = 1, natom
     451         [ +  + ]:          30 :        do idir = 1, 3
     452                 :          21 :          value = delta_xcart(idir,iatom)
     453                 :          21 :          ii = log10(abs(value))
     454         [ +  - ]:          21 :          if (ii <= 0) then
     455                 :          21 :            ii = abs(ii) + 1
     456                 :          21 :            value = one*int(tol*value*10.0_dp**ii)/(tol*10.0_dp**ii) !vz_d
     457                 :             :          else
     458                 :           0 :            value = one*int(tol*value/(10.0_dp**ii))*(10.0_dp**ii)/tol !vz_d
     459                 :             :          end if
     460                 :          28 :          delta_xcart(idir,iatom) = value
     461                 :             :        end do
     462                 :             :      end do
     463                 :             : 
     464   [ +  +  +  + ]:          30 :      xcart_new(:,:) = Crystal%xcart(:,:) + delta_xcart(:,:)
     465                 :           2 :      call xcart2xred(natom,rprimd,xcart_new,xred_new)
     466                 :             :    end if  ! relaxat == 1
     467                 :             : 
     468                 :             : ! Compute lambda and the value of the energy functional F - \lambda \cdot P$
     469                 :             : 
     470                 :           2 :    e1 = etotal
     471         [ +  + ]:           8 :    do idir = 1, 3
     472                 :           6 :      posi = posi + 1
     473                 :           6 :      lambda(idir) = delta(posi)
     474                 :           8 :      e1 = e1 - lambda(idir)*ptot_cart(idir)
     475                 :             :    end do
     476                 :             : 
     477                 :             : !  Update cell parameters
     478         [ +  - ]:           2 :    if (relaxstr == 1) then
     479                 :           2 :      delta_eta(:) = zero
     480         [ +  + ]:          14 :      do istrain = 1, 6
     481         [ +  + ]:          14 :        if (irelaxstrain(istrain) == 1) then
     482                 :          10 :          posi = posi + 1
     483                 :          10 :          delta_eta(istrain) = delta(posi)
     484                 :             :        end if
     485                 :             :      end do
     486                 :             : 
     487         [ +  + ]:           8 :      do istrain = 1, 3
     488                 :           8 :        strainmat(istrain,istrain) = delta_eta(istrain)
     489                 :             :      end do
     490                 :           2 :      strainmat(2,3) = delta_eta(4)/2._dp ; strainmat(3,2) = delta_eta(4)/2._dp
     491                 :           2 :      strainmat(1,3) = delta_eta(5)/2._dp ; strainmat(3,1) = delta_eta(5)/2._dp
     492                 :           2 :      strainmat(2,1) = delta_eta(6)/2._dp ; strainmat(1,2) = delta_eta(6)/2._dp
     493                 :             : 
     494                 :           2 :      rprimd_new(:,:) = 0._dp
     495         [ +  + ]:           8 :      do idir = 1, 3
     496         [ +  + ]:          26 :        do jdir = 1, 3
     497         [ +  + ]:          78 :          do ii = 1, 3
     498                 :             :            rprimd_new(jdir,idir) = rprimd_new(jdir,idir) + &
     499                 :          72 : &           rprimd(ii,idir)*strainmat(ii,jdir)
     500                 :             :          end do
     501                 :             :        end do
     502                 :             :      end do
     503   [ +  +  +  + ]:          26 :      rprimd_new(:,:) = rprimd_new(:,:) + rprimd(:,:)
     504                 :             : 
     505                 :           2 :      acell_new(:) = zero
     506         [ +  + ]:           8 :      do idir = 1, 3
     507         [ +  + ]:          24 :        do jdir = 1, 3
     508                 :             :          acell_new(idir) = acell_new(idir) + &
     509                 :          24 : &         rprimd_new(jdir,idir)*rprimd_new(jdir,idir)
     510                 :             :        end do
     511                 :           6 :        acell_new(idir) = sqrt(acell_new(idir))
     512         [ +  + ]:          26 :        rprim(:,idir) = rprimd_new(:,idir)/acell_new(idir)
     513                 :             :      end do
     514                 :             : 
     515                 :             :    end if          ! relaxstr == 1
     516                 :             : 
     517                 :             : !  Write out the results
     518                 :             : 
     519         [ +  - ]:           2 :    if (iwrite) then
     520                 :           2 :      write(iout,*)
     521   [ +  -  +  + ]:         162 :      write(iout,'(a,80a,a)') ch10,('=',ii=1,80),ch10
     522                 :           2 :      write(iout,*)
     523                 :           2 :      write(iout,*)'Relaxation of the geometry at fixed polarization:'
     524                 :           2 :      write(iout,*)
     525                 :           2 :      write(iout,'(a,3(2x,f16.9))')' Lambda = ',(lambda(idir),idir = 1, 3)
     526                 :           2 :      write(iout,'(a,e16.9)')' Value of the energy functional E_1 = ',e1
     527                 :           2 :      write(iout,*)
     528                 :           2 :      write(iout,*)'Difference between actual value of the Polarization (C/m^2)'
     529                 :           2 :      write(iout,*)'and the target value:'
     530                 :             :    end if
     531         [ +  + ]:           8 :    diffpol(:) = (ptot_cart(:) - targetpol(:))*e_Cb/((Bohr_Ang*1.0d-10)**2)
     532         [ +  - ]:           2 :    if (iwrite) write(iout,'(3(3x,f16.9))')(diffpol(idir),idir = 1, 3)
     533                 :             : 
     534         [ +  - ]:           2 :    if (relaxat == 1) then
     535                 :             : !    Compute the forces induced on the atoms by the electric field
     536                 :             : !    The strength of the field is determined by lambda
     537   [ +  +  +  + ]:          30 :      felfd(:,:) = zero
     538         [ +  + ]:           9 :      do iatom = 1, natom
     539         [ +  + ]:          30 :        do idir = 1, 3
     540         [ +  + ]:          91 :          do jdir = 1, 3
     541                 :          63 :            index = idir +3*((iatom - 1) + mpert*((jdir - 1) + 3*(natom + 1)))
     542                 :          84 :            felfd(idir,iatom) = felfd(idir,iatom) - lambda(jdir)*blkval(1,index)/ucvol
     543                 :             :          end do
     544                 :             :        end do
     545                 :             :      end do
     546                 :             : 
     547                 :             : !    Compute remaining forces and write them out
     548                 :             : 
     549   [ +  +  +  + ]:          30 :      fdiff(:,:) = fcart(:,:) - felfd(:,:)
     550         [ +  - ]:           2 :      if (iwrite) then
     551                 :           2 :        write(iout,*)
     552                 :           2 :        write(iout,*)'Difference between the Hellmann-Feynman forces'
     553                 :           2 :        write(iout,*)'and the forces induced by the electric field'
     554                 :           2 :        write(iout,*)'(cartesian coordinates, hartree/bohr)'
     555                 :             :      end if
     556                 :           2 :      fmax = zero
     557         [ +  + ]:           9 :      do iatom = 1, natom
     558         [ +  - ]:           7 :        if (iwrite) write(iout,'(3(3x,es16.9))')(fdiff(idir,iatom),idir = 1, 3)
     559         [ +  + ]:          30 :        do idir = 1, 3
     560         [ +  + ]:          28 :          if (abs(fdiff(idir,iatom)) > fmax) fmax = abs(fdiff(idir,iatom))
     561                 :             :        end do
     562                 :             :      end do
     563                 :             : 
     564         [ +  - ]:           2 :      if (iwrite) then
     565                 :           2 :        write(iout,'(a,3x,es16.9)')' fmax = ',fmax
     566                 :           2 :        write(iout,*)
     567                 :           2 :        write(iout,*)'Change of cartesian coordinates (delta_xcart):'
     568         [ +  + ]:           9 :        do iatom = 1, natom
     569                 :           9 :          write(iout,'(5x,i3,3(2x,f16.9))')iatom,(delta_xcart(idir,iatom),idir = 1, 3)
     570                 :             :        end do
     571                 :           2 :        write(iout,*)
     572                 :           2 :        write(iout,*)'New cartesian coordinates (xcart_new):'
     573                 :           2 :        write(iout,*)'  xcart'
     574         [ +  + ]:           9 :        do iatom = 1, natom
     575                 :           9 :          write(iout,'(3(3x,d22.14))')(xcart_new(idir,iatom),idir = 1, 3)
     576                 :             :        end do
     577                 :           2 :        write(iout,*)
     578                 :           2 :        write(iout,*)'New reduced coordinates (xred_new):'
     579                 :           2 :        write(iout,*)'  xred'
     580         [ +  + ]:           9 :        do iatom = 1, natom
     581                 :           9 :          write(iout,'(3(3x,d22.14))')(xred_new(idir,iatom),idir = 1, 3)
     582                 :             :        end do
     583                 :             :      end if
     584                 :             : 
     585                 :             :    end if         ! relaxat == 1
     586                 :             : 
     587         [ +  - ]:           2 :    if (relaxstr == 1) then
     588                 :             : 
     589                 :             : !    Compute the stresses induced by the electric field
     590                 :           2 :      sigelfd(:) = zero
     591                 :           2 :      istrain = 0
     592         [ +  + ]:           6 :      do ipert = 1, 2
     593                 :           4 :        jpert = natom + 2 + ipert
     594         [ +  + ]:          18 :        do idir = 1, 3
     595                 :          12 :          istrain = istrain + 1
     596         [ +  + ]:          48 :          do jdir = 1, 3
     597                 :          36 :            index = idir +3*((jpert - 1) + mpert*((jdir - 1) + 3*(natom + 1)))
     598                 :          48 :            sigelfd(istrain) = sigelfd(istrain) + lambda(jdir)*blkval(1,index)
     599                 :             :          end do
     600                 :          16 :          sigelfd(istrain) = sigelfd(istrain)/ucvol
     601                 :             :        end do
     602                 :             :      end do
     603                 :             : 
     604                 :             : !    Compute the remaining stresses and write them out
     605         [ +  + ]:          14 :      diffsig(:) = strten(:) - sigelfd(:)
     606                 :           2 :      sigmax = zero
     607         [ +  + ]:          14 :      do istrain = 1, 6
     608         [ +  + ]:          14 :        if (abs(diffsig(istrain)) > sigmax) sigmax = abs(diffsig(istrain))
     609                 :             :      end do
     610         [ +  - ]:           2 :      if (iwrite) then
     611                 :           2 :        write(iout,*)
     612                 :           2 :        write(iout,*)'Difference between the Hellmann-Feynman stresses'
     613                 :           2 :        write(iout,*)'and the stresses induced by the electric field'
     614                 :           2 :        write(iout,*)'(cartesian coordinates, hartree/bohr^3)'
     615                 :           2 :        write(iout,'(2x,a,f16.9,5x,a,f16.9)')'diffsig(1) = ',diffsig(1),'diffsig(4) = ',diffsig(4)
     616                 :           2 :        write(iout,'(2x,a,f16.9,5x,a,f16.9)')'diffsig(2) = ',diffsig(2),'diffsig(5) = ',diffsig(5)
     617                 :           2 :        write(iout,'(2x,a,f16.9,5x,a,f16.9)')'diffsig(3) = ',diffsig(3),'diffsig(6) = ',diffsig(6)
     618                 :           2 :        write(iout,'(a,3x,es16.9)')' sigmax = ',sigmax
     619                 :           2 :        write(iout,*)
     620                 :           2 :        write(iout,*)'Induced strain (delta_eta):'
     621                 :           2 :        write(iout,'(2x,a,f16.9,5x,a,f16.9)')'delta_eta(1) = ',delta_eta(1),'delta_eta(4) = ',delta_eta(4)
     622                 :           2 :        write(iout,'(2x,a,f16.9,5x,a,f16.9)')'delta_eta(2) = ',delta_eta(2),'delta_eta(5) = ',delta_eta(5)
     623                 :           2 :        write(iout,'(2x,a,f16.9,5x,a,f16.9)')'delta_eta(3) = ',delta_eta(3),'delta_eta(6) = ',delta_eta(6)
     624                 :           2 :        write(iout,*)
     625                 :           2 :        write(iout,*)'New lattice constants (acell_new):'
     626                 :           2 :        write(iout,*)'  acell'
     627                 :           2 :        write(iout,'(3(2x,d22.14))')(acell_new(idir),idir = 1, 3)
     628                 :           2 :        write(iout,*)
     629                 :           2 :        write(iout,*)'New primitive vectors (rprim_new):'
     630                 :           2 :        write(iout,*)'  rprim'
     631                 :           2 :        write(iout,'(3(2x,d22.14))')(rprim(idir,1),idir = 1, 3)
     632                 :           2 :        write(iout,'(3(2x,d22.14))')(rprim(idir,2),idir = 1, 3)
     633                 :           2 :        write(iout,'(3(2x,d22.14))')(rprim(idir,3),idir = 1, 3)
     634                 :             :      end if
     635                 :             :    end if         ! relaxstr /= 0
     636                 :             : 
     637                 :             :  end if    !  (relaxat /= 0).or.(relaxstr /= 0)
     638                 :             : 
     639         [ -  + ]:           3 :  ABI_FREE(cfac)
     640         [ -  + ]:           3 :  ABI_FREE(fdiff)
     641         [ -  + ]:           3 :  ABI_FREE(felfd)
     642         [ -  + ]:           3 :  ABI_FREE(delta)
     643         [ -  + ]:           3 :  ABI_FREE(fcart)
     644         [ -  + ]:           3 :  ABI_FREE(fcmat)
     645         [ -  + ]:           3 :  ABI_FREE(ifcmat)
     646         [ -  + ]:           3 :  ABI_FREE(ipvt)
     647         [ -  + ]:           3 :  ABI_FREE(rfpert)
     648         [ -  + ]:           3 :  ABI_FREE(vec)
     649         [ -  + ]:           3 :  ABI_FREE(zgwork)
     650         [ -  + ]:           3 :  ABI_FREE(irelaxat)
     651                 :             : 
     652                 :           3 : end subroutine relaxpol
     653                 :             : !!***
     654                 :             : 
     655                 :             : end module m_relaxpol
     656                 :             : !!***
        

Generated by: LCOV version 2.3-1