LCOV - code coverage report
Current view: top level - src/80_tdep - m_tdep_phi2.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 82.8 % 326 270
Test Date: 2026-09-21 22:40:37 Functions: 76.9 % 13 10

            Line data    Source code
       1              : 
       2              : #if defined HAVE_CONFIG_H
       3              : #include "config.h"
       4              : #endif
       5              : 
       6              : #include "abi_common.h"
       7              : 
       8              : module m_tdep_phi2
       9              : 
      10              :   use defs_basis
      11              :   use m_errors
      12              :   use m_abicore
      13              :   use m_xmpi
      14              :   use m_io_tools
      15              :   use m_tdep_dataset,     only : atdep_dataset_type, MPI_enreg_type
      16              :   use m_tdep_shell,       only : Shell_type
      17              :   use m_tdep_sym,         only : Symmetries_type
      18              :   use m_tdep_qpt,         only : Qpoints_type
      19              :   use m_tdep_sampling,    only : tdep_Sampling_type
      20              :   use m_tdep_solver,      only : tdep_Solver_type
      21              :   use m_tdep_model,       only : tdep_Model_type
      22              : 
      23              :   implicit none
      24              : 
      25              :   type Eigen_type
      26              : 
      27              :     double precision, allocatable :: eigenval(:,:)
      28              :     double precision, allocatable :: eigenvec(:,:,:,:,:,:)
      29              :     double precision, allocatable :: dynmat(:,:,:,:,:,:)
      30              : 
      31              :   end type Eigen_type
      32              : 
      33              :   public :: tdep_calc_ftot2
      34              :   public :: tdep_calc_phi1
      35              :   public :: tdep_write_phi1
      36              :   public :: tdep_calc_phi2
      37              :   public :: tdep_write_phi2
      38              :   public :: tdep_build_phi2_33
      39              :   public :: tdep_calc_dij
      40              :   public :: tdep_write_dij
      41              :   public :: tdep_init_eigen2nd
      42              :   public :: tdep_destroy_eigen2nd
      43              :   public :: tdep_write_yaml
      44              : 
      45              : contains
      46              : 
      47              : !====================================================================================================
      48           49 :  subroutine tdep_calc_ftot2(Model,Invar,Phi2,ucart)
      49              : 
      50              :   type(tdep_Model_type),intent(inout) :: Model
      51              :   type(atdep_dataset_type),intent(in) :: Invar
      52              :   double precision, intent(in)  :: Phi2(3*Invar%natom,3*Invar%natom)
      53              :   double precision, intent(in)  :: ucart(3,Invar%natom,Invar%my_nstep)
      54              : 
      55              :   integer :: jj,istep,jatom
      56           49 :   double precision, allocatable :: ucart_blas(:)
      57           49 :   double precision, allocatable :: ftot2(:)
      58              : 
      59              : ! Compute Forces of the model TDEP
      60        23003 :   ABI_CALLOC(ucart_blas,(3*Invar%natom))
      61        22905 :   ABI_CALLOC(ftot2     ,(3*Invar%natom))
      62         1101 :   do istep=1,Invar%my_nstep
      63       460748 :     ucart_blas(:)=0.d0
      64       460748 :     ftot2     (:)=0.d0
      65       154284 :     do jatom=1,Invar%natom
      66       613980 :       do jj=1,3
      67       612928 :         ucart_blas(3*(jatom-1)+jj)=ucart(jj,jatom,istep)
      68              :       end do
      69              :     end do
      70       460748 :     Model%Phi1Ui(istep)=sum(Model%Phi1(:)*ucart_blas(:))
      71         1052 :     call DGEMM('N','N',3*Invar%natom,1,3*Invar%natom,1.d0,Phi2,3*Invar%natom,ucart_blas,3*Invar%natom,0.d0,ftot2(:),3*Invar%natom)
      72         1052 :     call DGEMM('T','N',1,1,3*Invar%natom,1./2.d0,ftot2,3*Invar%natom,ucart_blas,3*Invar%natom,0.d0,Model%Phi2UiUj(istep),3*Invar%natom)
      73       460797 :     Model%Forces(3*Invar%natom*(istep-1)+1:3*Invar%natom*istep)=-Model%Phi1(:)-ftot2(:)
      74              :   end do !istep
      75           49 :   ABI_FREE(ucart_blas)
      76           49 :   ABI_FREE(ftot2)
      77              : 
      78           49 :  end subroutine tdep_calc_ftot2
      79              : 
      80              : !=====================================================================================================
      81           43 : subroutine tdep_calc_phi1(Solver,Shell1at,Sym,Phi1)
      82              : 
      83              :   type(tdep_Solver_type),intent(in) :: Solver
      84              :   type(Shell_type),intent(in) :: Shell1at
      85              :   type(Symmetries_type),intent(in) :: Sym
      86              :   double precision,intent(out) :: Phi1(3*Solver%natom)
      87              : 
      88              :   integer :: ishell,isym,iatom,ncoeff,ncoeff_prev
      89              :   integer :: nshell,ii,iatshell,iat_mod
      90           43 :   double precision,allocatable :: Phi1_coeff(:)
      91           43 :   double precision,allocatable :: Phi1_3(:),Phi1_ref(:,:)
      92              : 
      93           43 :   nshell=Shell1at%nshell
      94          129 :   ABI_MALLOC(Phi1_coeff,(Solver%ncoeff1st))
      95           43 :   Phi1_coeff(:) = Solver%theta(1:Solver%ncoeff1st)
      96          377 :   ABI_MALLOC(Phi1_ref,(3,nshell)); Phi1_ref(:,:)=zero
      97          215 :   ABI_MALLOC(Phi1_3,(3)) ; Phi1_3(:)=0.d0
      98          105 :   do ishell=1,nshell
      99              : !   Build the 3x3 IFC per shell
     100           62 :     ncoeff     =Shell1at%ncoeff(ishell)
     101           62 :     ncoeff_prev=Shell1at%ncoeff_prev(ishell)
     102          248 :     do ii=1,3
     103          248 :       Phi1_ref(ii,ishell)=sum(Shell1at%proj(ii,1:ncoeff,ishell)*Phi1_coeff(ncoeff_prev+1:ncoeff_prev+ncoeff))
     104              :     end do
     105              : !   Build the vector-IFC of an atom in this shell
     106           62 :     if (Shell1at%neighbours(1,ishell)%n_interactions.eq.0) cycle
     107           43 :     do iatshell=1,Shell1at%neighbours(1,ishell)%n_interactions
     108            0 :       iatom=Shell1at%neighbours(1,ishell)%atomj_in_shell(iatshell)
     109            0 :       isym =Shell1at%neighbours(1,ishell)%sym_in_shell(iatshell)
     110            0 :       do ii=1,3
     111            0 :         Phi1_3(ii)=sum(Sym%S_ref(ii,:,isym,1)*Phi1_ref(:,ishell))
     112              :       end do
     113           62 :       Phi1((iatom-1)*3+1:(iatom-1)*3+3)=Phi1_3(:)
     114              :     end do !iatshell
     115              :   end do !ishell
     116              : ! Acoustic sum rule
     117          172 :   do ii=1,3
     118        19282 :     do iatom=1,Solver%natom
     119        19110 :       iat_mod=mod(iatom+Solver%natom_unitcell-1,Solver%natom_unitcell)+1
     120        19110 :       if (iat_mod==1) cycle
     121        19239 :       Phi1((iatom-iat_mod+1)*3+ii)=Phi1((iatom-iat_mod+1)*3+ii)-Phi1((iatom-1)*3+ii)
     122              :     end do
     123              :   end do
     124           43 :   ABI_FREE(Phi1_coeff)
     125           43 :   ABI_FREE(Phi1_3)
     126           43 :   ABI_FREE(Phi1_ref)
     127              : 
     128              : ! Remove the rounding errors before writing (for non regression testing purposes)
     129        19153 :   do ii=1,3*Solver%natom
     130        19153 :     if (abs(Phi1(ii)).lt.tol8) Phi1(ii)=zero
     131              :   end do
     132              : 
     133           43 : end subroutine tdep_calc_phi1
     134              : 
     135              : !=====================================================================================================
     136           44 : subroutine tdep_write_phi1(Invar,Phi1)
     137              : 
     138              :   type(atdep_dataset_type),intent(in) :: Invar
     139              :   double precision,intent(in) :: Phi1(3*Invar%natom)
     140              : 
     141              :   integer :: iatcell,ii
     142              : 
     143           44 :   write(Invar%stdout,*) ' '
     144           44 :   write(Invar%stdout,*) '#############################################################################'
     145           44 :   write(Invar%stdout,*) '#### For each shell, list of coefficients (IFC), number of neighbours... ####'
     146           44 :   write(Invar%stdout,*) '#############################################################################'
     147              : 
     148              : ! Write the IFCs in the data.out file (with others specifications:
     149              : ! number of atoms in a shell, distance, Trace...)
     150          150 :   do iatcell=1,Invar%natom_unitcell
     151          106 :     write(Invar%stdout,'(a,i4)') ' ############# List of (first order) IFC for the reference atom=',iatcell
     152          424 :     write(Invar%stdout,'(2x,3(f9.6,1x))') (Phi1((iatcell-1)*3+ii),ii=1,3)
     153          150 :     write(Invar%stdout,*) ' '
     154              :   end do !iatcell
     155              : 
     156           44 : end subroutine tdep_write_phi1
     157              : 
     158              : !=====================================================================================================
     159           43 : subroutine tdep_calc_phi2(Solver,Shell2at,Sym,Phi2)
     160              : 
     161              :   type(tdep_Solver_type),intent(in) :: Solver
     162              :   type(Shell_type),intent(in) :: Shell2at
     163              :   type(Symmetries_type),intent(in) :: Sym
     164              :   double precision,intent(out) :: Phi2(3*Solver%natom,3*Solver%natom)
     165              : 
     166              :   integer :: ishell,isym,eatom,fatom,ncoeff,ncoeff_prev
     167              :   integer :: nshell,ii,jj,kk,kappa,iatshell,itrans
     168           43 :   double precision,allocatable :: Phi2_33(:,:),Phi2_ref(:,:,:)
     169           43 :   double precision,allocatable :: Phi2_coeff(:)
     170              : 
     171           43 :   nshell=Shell2at%nshell
     172          129 :   ABI_MALLOC(Phi2_coeff,(Solver%ncoeff2nd))
     173         1968 :   Phi2_coeff(:) = Solver%theta(Solver%ncoeff1st+1:Solver%ncoeff1st+Solver%ncoeff2nd)
     174         6356 :   ABI_MALLOC(Phi2_ref,(3,3,nshell)); Phi2_ref(:,:,:)=zero
     175          602 :   ABI_MALLOC(Phi2_33,(3,3)) ; Phi2_33(:,:)=0.d0
     176          522 :   do ishell=1,nshell
     177              : !   Build the 3x3 IFC per shell
     178          479 :     ncoeff     =Shell2at%ncoeff(ishell)
     179          479 :     ncoeff_prev=Shell2at%ncoeff_prev(ishell)
     180          479 :     kappa=0
     181         1916 :     do ii=1,3
     182         6227 :       do jj=1,3
     183         4311 :         kappa=kappa+1
     184        23073 :         Phi2_ref(ii,jj,ishell)=sum(Shell2at%proj(kappa,1:ncoeff,ishell)*Phi2_coeff(ncoeff_prev+1:ncoeff_prev+ncoeff))
     185              :       end do
     186              :     end do
     187        68344 :     do eatom=1,Solver%natom
     188              : !     Build the 3x3 IFC of an atom in this shell
     189        67822 :       if (Shell2at%neighbours(eatom,ishell)%n_interactions.eq.0) cycle
     190       462411 :       do iatshell=1,Shell2at%neighbours(eatom,ishell)%n_interactions
     191       405630 :         fatom=Shell2at%neighbours(eatom,ishell)%atomj_in_shell(iatshell)
     192       405630 :         isym =Shell2at%neighbours(eatom,ishell)%sym_in_shell(iatshell)
     193       405630 :         itrans=Shell2at%neighbours(eatom,ishell)%transpose_in_shell(iatshell)
     194       405630 :         if (fatom.lt.eatom) cycle
     195       206000 :         call tdep_build_phi2_33(isym,Phi2_ref(:,:,ishell),Phi2_33,Sym,itrans)
     196              : !       Symetrization of the Phi2 matrix
     197      2678000 :         Phi2((eatom-1)*3+1:(eatom-1)*3+3,3*(fatom-1)+1:3*(fatom-1)+3)=Phi2_33(:,:)
     198       891822 :         do ii=1,3
     199      2877630 :           do jj=1,3
     200      2472000 :             Phi2((fatom  -1)*3+ii,3*(eatom-1)+jj)=Phi2_33(jj,ii)
     201              :           end do
     202              :         end do
     203              :       end do !iatshell
     204              :     end do !eatom
     205              :   end do !ishell
     206              : ! Acoustic sum rule
     207         6413 :   do eatom=1,Solver%natom
     208        25523 :     do jj=1,3
     209        82810 :       do kk=1,3
     210     10967916 :         do fatom=1,Solver%natom
     211     10891476 :           if (fatom==eatom) cycle
     212              :           Phi2((eatom-1)*3+jj,(eatom-1)*3+kk)=Phi2((eatom-1)*3+jj,3*(eatom-1)+kk)&
     213     10948806 : &                                               -Phi2((eatom-1)*3+jj,3*(fatom-1)+kk)
     214              :         enddo
     215              :       enddo
     216              :     enddo
     217              :   enddo
     218           43 :   ABI_FREE(Phi2_coeff)
     219           43 :   ABI_FREE(Phi2_33)
     220           43 :   ABI_FREE(Phi2_ref)
     221              : 
     222              : ! Remove the rounding errors before writing (for non regression testing purposes)
     223        19153 :   do ii=1,3*Solver%natom
     224     10910629 :     do jj=1,3*Solver%natom
     225     10910586 :       if (abs(Phi2(ii,jj)).lt.tol8) Phi2(ii,jj)=zero
     226              :     end do
     227              :   end do
     228              : 
     229           43 : end subroutine tdep_calc_phi2
     230              : 
     231              : !=====================================================================================================
     232           44 : subroutine tdep_write_phi2(distance,Invar,MPIdata,Phi2,Shell2at)
     233              : 
     234              :   type(atdep_dataset_type),intent(in) :: Invar
     235              :   type(Shell_type),intent(in) :: Shell2at
     236              :   type(MPI_enreg_type), intent(in) :: MPIdata
     237              :   double precision,intent(in) :: distance(Invar%natom,Invar%natom,4)
     238              :   double precision,intent(in) :: Phi2(3*Invar%natom,3*Invar%natom)
     239              : 
     240              :   integer :: iatcell,ishell,jshell,jatom
     241              :   integer :: nshell,ii,this_shell,iatshell
     242              :   double precision :: max_bound,min_bound,dist_shell,tmp1,tmp2,tmp3
     243           44 :   integer,allocatable :: tab_shell(:)
     244              : 
     245           44 :   write(Invar%stdout,*) ' '
     246           44 :   write(Invar%stdout,*) '#############################################################################'
     247           44 :   write(Invar%stdout,*) '#### For each shell, list of coefficients (IFC), number of neighbours... ####'
     248           44 :   write(Invar%stdout,*) '#############################################################################'
     249              : 
     250           44 :   nshell=Shell2at%nshell
     251              : ! Write the IFCs in the data.out file (with others specifications:
     252              : ! number of atoms in a shell, distance, Trace...)
     253          632 :   ABI_MALLOC(tab_shell,(nshell)); tab_shell(:)=0
     254          150 :   do iatcell=1,Invar%natom_unitcell
     255         2392 :     tab_shell(:)=0
     256          106 :     write(Invar%stdout,'(a,i4)') ' ############# List of (second order) IFC for the reference atom=',iatcell
     257              : !   Sort the IFC with distance in increasing order
     258          106 :     min_bound=-1.d0
     259         2436 :     do ishell=1,nshell
     260       113058 :       do jshell=1,nshell
     261       113058 :         if ((distance(Shell2at%iatref(jshell),Shell2at%jatref(jshell),1).ge.min_bound).and.(tab_shell(jshell).eq.0)) then
     262        56529 :           max_bound=distance(Shell2at%iatref(jshell),Shell2at%jatref(jshell),1)
     263        56529 :           this_shell=jshell
     264              :         end if
     265              :       end do
     266              : 
     267       113058 :       do jshell=1,nshell
     268              :         if ((distance(Shell2at%iatref(jshell),Shell2at%jatref(jshell),1).lt.max_bound).and.&
     269              : &           (distance(Shell2at%iatref(jshell),Shell2at%jatref(jshell),1).ge.min_bound).and.&
     270              : &           (distance(Shell2at%iatref(jshell),Shell2at%jatref(jshell),1).ne.&
     271       110772 : &            distance(Shell2at%iatref(this_shell),Shell2at%jatref(this_shell),1)).and.&
     272         2286 : &            (tab_shell(jshell).eq.0)) then
     273         4843 :           max_bound=distance(Shell2at%iatref(jshell),Shell2at%jatref(jshell),1)
     274         4843 :           this_shell=jshell
     275              :         end if
     276              :       end do
     277         2286 :       tab_shell(this_shell)=1
     278         2286 :       min_bound=max_bound
     279         2286 :       dist_shell=distance(Shell2at%iatref(this_shell),Shell2at%jatref(this_shell),1)
     280              : 
     281              : !     Write the IFC properly
     282         2392 :       if (Shell2at%neighbours(iatcell,this_shell)%n_interactions.ne.0) then
     283         1099 :         write(Invar%stdout,'(a,i4,a,i4,a,f9.6)') ' ======== NEW SHELL (ishell=',this_shell,&
     284         2198 : &            '): There are',Shell2at%neighbours(iatcell,this_shell)%n_interactions,' atoms on this shell at distance=',dist_shell
     285         6367 :         do iatshell=1,Shell2at%neighbours(iatcell,this_shell)%n_interactions
     286         5268 :           jatom=Shell2at%neighbours(iatcell,this_shell)%atomj_in_shell(iatshell)
     287         5268 :           write(Invar%stdout,'(a,i4,a,i4)') '  For jatom=',jatom,' ,with type=',mod(jatom-1,Invar%natom_unitcell)+1
     288        21072 :           do ii=1,3
     289        15804 :             if (abs(Phi2((iatcell-1)*3+ii,(jatom-1)*3+1)).lt.5.d-7) then
     290         2660 :               tmp1=0.d0
     291              :             else
     292        13144 :               tmp1=Phi2((iatcell-1)*3+ii,(jatom-1)*3+1)
     293              :             end if
     294        15804 :             if (abs(Phi2((iatcell-1)*3+ii,(jatom-1)*3+2)).lt.5.d-7) then
     295         2622 :               tmp2=0.d0
     296              :             else
     297        13182 :               tmp2=Phi2((iatcell-1)*3+ii,(jatom-1)*3+2)
     298              :             end if
     299        15804 :             if (abs(Phi2((iatcell-1)*3+ii,(jatom-1)*3+3)).lt.5.d-7) then
     300         2864 :               tmp3=0.d0
     301              :             else
     302        12940 :               tmp3=Phi2((iatcell-1)*3+ii,(jatom-1)*3+3)
     303              :             end if
     304        21072 :             write(Invar%stdout,'(2x,3(f9.6,1x))') tmp1,tmp2,tmp3
     305              :           end do
     306         5268 :           write(Invar%stdout,'(a,3(1x,f11.6))') '  The components of the vector are:', distance(iatcell,jatom,2:4)
     307         5268 :           write(Invar%stdout,'(a,(1x,f9.6))') '  Trace=',Phi2((iatcell-1)*3+1,(jatom-1)*3+1)+Phi2((iatcell-1)*3+2,&
     308        10536 : &           (jatom-1)*3+2)+Phi2((iatcell-1)*3+3,(jatom-1)*3+3)
     309         6367 :           write(Invar%stdout,*) ' '
     310              :         end do
     311              :       end if
     312              :     end do !ishell
     313              :   end do !iatcell
     314           44 :   ABI_FREE(tab_shell)
     315              : 
     316              : ! Write the Phi2_unitcell.dat and Phi2.dat files
     317           44 :   if (Invar%debug.and.MPIdata%iam_master) then
     318            2 :     write(Invar%stdout,'(a)') ' See the Phi2*.dat file'
     319            2 :     open(unit=52,file=trim(Invar%output_prefix)//'_Phi2_unitcell.dat')
     320            2 :     open(unit=55,file=trim(Invar%output_prefix)//'_Phi2.dat')
     321          674 :     do jatom=1,3*Invar%natom
     322          672 :       if (jatom.le.3*Invar%natom_unitcell) then
     323           30 :         write(52,'(10000(f10.6,1x))') Phi2(jatom,:)
     324              :       end if
     325          674 :       write(55,'(10000(f10.6,1x))') Phi2(jatom,:)
     326              :     end do
     327            2 :     close(52)
     328            2 :     close(55)
     329              :   end if
     330              : 
     331           44 : end subroutine tdep_write_phi2
     332              : 
     333              : !=====================================================================================================
     334            0 : subroutine tdep_calc_dij(dij,eigenV,iqpt,Invar,omega,Phi2,qpt_cart,Rlatt_cart)
     335              : 
     336              :   type(atdep_dataset_type),intent(in) :: Invar
     337              :   integer,intent(in) :: iqpt
     338              :   double precision,intent(in) :: Phi2(3*Invar%natom,3*Invar%natom)
     339              :   double precision,intent(in) :: Rlatt_cart(3,Invar%natom_unitcell,Invar%natom)
     340              :   double precision,intent(in) :: qpt_cart(3)
     341              :   double precision,intent(out) :: omega (3*Invar%natom_unitcell)
     342              :   double complex  ,intent(out) :: dij   (3*Invar%natom_unitcell,3*Invar%natom_unitcell)
     343              :   double complex  ,intent(out) :: eigenV(3*Invar%natom_unitcell,3*Invar%natom_unitcell)
     344              : 
     345              :   integer :: LWORK,ii,jj,kk,iatom,jatom,iatcell,jatcell,itypat,jtypat,iat_mod,INFO,itemp,imode,nmode
     346              :   double precision :: phase
     347              :   double complex :: norm
     348            0 :   double precision, allocatable :: RWORK(:)
     349            0 :   double complex, allocatable :: WORKC(:)
     350              : ! double complex, allocatable :: mass_mat(:,:)
     351              : 
     352              : ! Calculation of the dynamical matrix (Dij)
     353            0 :   do iatcell=1,Invar%natom_unitcell
     354            0 :     do jatom=1,Invar%natom
     355            0 :       iat_mod=mod(jatom+Invar%natom_unitcell-1,Invar%natom_unitcell)+1
     356            0 :       phase=0.d0
     357            0 :       do kk=1,3
     358            0 :         phase=phase+2*pi*Rlatt_cart(kk,iatcell,jatom)*qpt_cart(kk)
     359              :       end do
     360            0 :       do ii=1+(iatcell-1)*3,3+(iatcell-1)*3
     361            0 :         do jj=1,3
     362            0 :           dij(ii,3*(iat_mod-1)+jj)=dij(ii,3*(iat_mod-1)+jj)+dcmplx(Phi2(ii,3*(jatom-1)+jj),0.d0)*exp(dcmplx(0.d0,phase))
     363              :         end do !jj
     364              :       end do !ii
     365              :     end do !jatom
     366              :   end do !iatcell
     367              : 
     368              : ! The Dij has to be an hermitian matrix
     369            0 :   itemp=0
     370            0 :   do ii=1,3*Invar%natom_unitcell
     371            0 :     do jj=ii,3*Invar%natom_unitcell
     372            0 :       if ((abs(real(dij(ii,jj))-real(dij(jj,ii))).gt.tol10).or.(abs(aimag(dij(ii,jj))+aimag(dij(jj,ii))).gt.tol10)) then
     373            0 :         if (Invar%debug) then
     374            0 :           write (Invar%stdout,'(a,1x,2(i4,1x))') 'for ii,jj=',ii,jj
     375            0 :           write (Invar%stdout,'(a,1x,1(f12.8,1x))') 'abs(realij-realji)=',abs(real(dij(ii,jj))-real(dij(jj,ii)))
     376            0 :           write (Invar%stdout,'(a,1x,1(f12.8,1x))') 'abs(imagij+imagji)=',abs(aimag(dij(ii,jj))+aimag(dij(jj,ii)))
     377              :         end if
     378            0 :         itemp=itemp+1
     379              :       end if
     380              :     end do
     381              :   end do
     382            0 :   if (itemp.ne.0.and.iqpt.eq.1) then
     383            0 :     write(Invar%stdout,*) 'WARNING: The Dij matrix is not hermitian'
     384            0 :     write(Invar%stdout,*) '  Probably: one shell may not have the whole number of atoms'
     385            0 :     write(Invar%stdout,*) '  The Dij matrix is symetrized'
     386              :   end if
     387              : 
     388              : ! Diagonalization of dynamical matrix Dij/sqrt(Mi*Mj)
     389            0 :   LWORK=2*3*Invar%natom_unitcell-1
     390            0 :   ABI_MALLOC(WORKC,(LWORK)); WORKC(:)=czero
     391            0 :   ABI_MALLOC(RWORK,(3*3*Invar%natom_unitcell-2)); RWORK(:)=zero
     392            0 :   do iatcell=1,Invar%natom_unitcell
     393            0 :     itypat=Invar%typat_unitcell(iatcell)
     394            0 :     do jatcell=1,Invar%natom_unitcell
     395            0 :       jtypat=Invar%typat_unitcell(jatcell)
     396            0 :       do ii=1,3
     397            0 :         do jj=1,3
     398              :           eigenV(ii+(iatcell-1)*3,jj+(jatcell-1)*3)=dij(ii+(iatcell-1)*3,jj+(jatcell-1)*3)/&
     399            0 : &                              dcmplx(dsqrt(Invar%amu(itypat)*Invar%amu(jtypat))*amu_emass,0.d0)
     400              :         end do !jj
     401              :       end do !ii
     402              :     end do !jatcell
     403              :   end do !iatcell
     404            0 :   call ZHEEV('V','U',3*Invar%natom_unitcell,eigenV(:,:),3*Invar%natom_unitcell,omega(:),WORKC,LWORK,RWORK,INFO)
     405              : 
     406              : ! Normalization of the eigenvectors
     407            0 :   nmode=3*Invar%natom_unitcell
     408            0 :   do imode=1,nmode
     409              :     norm=zero
     410            0 :     do iatom=1,Invar%natom_unitcell
     411            0 :       do ii=1,3
     412            0 :         norm=norm+eigenV(3*(iatom-1)+ii,imode)*conjg(eigenV(3*(iatom-1)+ii,imode))
     413              :       end do
     414              :     end do
     415            0 :     eigenV(:,imode)=eigenV(:,imode)/dsqrt(real(norm))
     416              :   end do
     417              : 
     418              : ! Remove the squared-negative frequencies
     419            0 :   do ii=1,Invar%natom_unitcell
     420            0 :     do jj=1,3
     421            0 :       if (omega((ii-1)*3+jj).lt.0.d0) then
     422            0 :         omega((ii-1)*3+jj)=-dsqrt(-omega((ii-1)*3+jj))
     423              :       else
     424            0 :         omega((ii-1)*3+jj)=dsqrt(omega((ii-1)*3+jj))
     425              :       end if
     426              :     end do
     427              :   end do
     428            0 :   ABI_FREE(WORKC)
     429            0 :   ABI_FREE(RWORK)
     430              : 
     431            0 : end subroutine tdep_calc_dij
     432              : 
     433              : !=====================================================================================================
     434              : !FB subroutine tdep_write_dij(Eigen2nd,iqpt,Invar,qpt_cart)
     435        22588 : subroutine tdep_write_dij(Eigen2nd,iqpt,Invar,qpt)
     436              : 
     437              :   type(atdep_dataset_type),intent(in) :: Invar
     438              :   integer,intent(in) :: iqpt
     439              : !FB  double precision,intent(in) :: qpt_cart(3)
     440              :   double precision,intent(in) :: qpt(3)
     441              :   type(Eigen_type),intent(in) :: Eigen2nd
     442              : 
     443        22588 :   double precision, allocatable :: omega (:)
     444        22588 :   double complex, allocatable   :: dij   (:,:)
     445        22588 :   double complex, allocatable   :: eigenV(:,:)
     446              :   double precision :: norm_eigenV
     447              :   integer :: ii,jj,iatcell,jatcell
     448              : 
     449       221145 :   ABI_MALLOC(omega ,(3*Invar%natom_unitcell))                       ; omega(:)   = zero
     450      2053372 :   ABI_MALLOC(dij   ,(3*Invar%natom_unitcell,3*Invar%natom_unitcell)); dij(:,:)   =czero
     451      2030784 :   ABI_MALLOC(eigenV,(3*Invar%natom_unitcell,3*Invar%natom_unitcell)); eigenV(:,:)=czero
     452       175969 :   omega(:)=Eigen2nd%eigenval(:,iqpt)
     453        73715 :   do iatcell=1,Invar%natom_unitcell
     454       274786 :     do jatcell=1,Invar%natom_unitcell
     455       855411 :       do jj=1,3
     456       603213 :         norm_eigenV = 0.0d0
     457      2412852 :         do ii=1,3
     458              :           dij   ((iatcell-1)*3+ii,(jatcell-1)*3+jj)=dcmplx(Eigen2nd%dynmat  (1,ii,iatcell,jj,jatcell,iqpt),&
     459      1809639 : &                                                          Eigen2nd%dynmat  (2,ii,iatcell,jj,jatcell,iqpt))
     460              :           eigenV((iatcell-1)*3+ii,(jatcell-1)*3+jj)=dcmplx(Eigen2nd%eigenvec(1,ii,iatcell,jj,jatcell,iqpt),&
     461      1809639 : &                                                          Eigen2nd%eigenvec(2,ii,iatcell,jj,jatcell,iqpt))
     462              :           norm_eigenV = norm_eigenV + real(eigenV((iatcell-1)*3+ii, (jatcell-1)*3+jj))**2 + &
     463      2412852 :                                       aimag(eigenV((iatcell-1)*3+ii, (jatcell-1)*3+jj))**2
     464              :         end do !ii
     465       603213 :         norm_eigenV = dsqrt(norm_eigenV)
     466              : !        if (norm_eigenV.lt.tol8) then
     467              : !          write(6,*) "iqpt, norm=",iqpt,norm_eigenV
     468              : !          ABI_ERROR(' STOP: THE NORM OF EIGENVECTOR IS ZERO')
     469              : !        end if
     470       804284 :         if (norm_eigenV.gt.tol8) then
     471      2390116 :           do ii=1,3
     472      2390116 :             eigenV((iatcell-1)*3+ii, (jatcell-1)*3+jj) = eigenV((iatcell-1)*3+ii, (jatcell-1)*3+jj) / dcmplx(norm_eigenV,0.d0)
     473              :           end do !ii
     474              :         end if
     475              :       end do !jj
     476              :     end do !jatcell
     477              :   end do !iatcell
     478              : 
     479              : ! Print the dynamical matrix (Dij)
     480        22588 :   write(52,'(a,1x,3(f10.6,1x))') 'For qpt=',qpt(:)
     481        22588 :   write(52,'(a,i4,a)') '  Dij(',iqpt,'real)='
     482        73715 :   do iatcell=1,Invar%natom_unitcell
     483       654340 :     write(52,'(100(f10.6,1x))') real(dij(1+(iatcell-1)*3,:))
     484       654340 :     write(52,'(100(f10.6,1x))') real(dij(2+(iatcell-1)*3,:))
     485       676928 :     write(52,'(100(f10.6,1x))') real(dij(3+(iatcell-1)*3,:))
     486              :   end do
     487        22588 :   write(52,'(a,i4,a)') '  Dij(',iqpt,'imag)='
     488        73715 :   do iatcell=1,Invar%natom_unitcell
     489       654340 :     write(52,'(100(f10.6,1x))') aimag(dij(1+(iatcell-1)*3,:))
     490       654340 :     write(52,'(100(f10.6,1x))') aimag(dij(2+(iatcell-1)*3,:))
     491       676928 :     write(52,'(100(f10.6,1x))') aimag(dij(3+(iatcell-1)*3,:))
     492              :   end do
     493        22588 :   write(52,*)' '
     494              : 
     495              : ! Print the frequencies (omega)
     496        58192 :   if (Invar%enunit.eq.0) write(53,'(i5,1x,100(f15.3,1x))') iqpt,(omega(ii)*Ha_eV*1000,ii=1,3*Invar%natom_unitcell)
     497       124216 :   if (Invar%enunit.eq.1) write(53,'(i5,1x,100(f15.3,1x))') iqpt,(omega(ii)*Ha_cmm1   ,ii=1,3*Invar%natom_unitcell)
     498        24022 :   if (Invar%enunit.eq.2) write(53,'(i5,1x,100(f15.3,1x))') iqpt,(omega(ii)*1000      ,ii=1,3*Invar%natom_unitcell)
     499        37303 :   if (Invar%enunit.eq.3) write(53,'(i5,1x,100(f15.3,1x))') iqpt,(omega(ii)*Ha_THz    ,ii=1,3*Invar%natom_unitcell)
     500              : 
     501              : ! Print the eigenvectors (eigenV)
     502              : !  write(51,*) 'For iqpt=',iqpt
     503              : !  do ii=1,3*Invar%natom_unitcell
     504              : !    write(51,*) 'Mode number',ii,' energy',omega(ii)
     505              : !    write(51,*) '  Real:'
     506              : !    write(51,*) real(eigenV(:,ii))
     507              : !    write(51,*) '  Imag:'
     508              : !    write(51,*) aimag(eigenV(:,ii))
     509              : !  end do
     510              : !  write(51,*) ' '
     511              : 
     512        22588 :   write(51,'(a,4x,i3,4(f15.6,1x))') 'q-pt=',iqpt,(qpt(ii),ii=1,3),qpt(1)*qpt(2)*qpt(3)
     513              : 
     514       175969 :   do ii=1,3*Invar%natom_unitcell
     515       175969 :     write(51,'(i5,5x,f15.6)') ii,omega(ii)*Ha_cmm1
     516              :   enddo
     517        22588 :   write(51,*) 'Phonon Eigenvectors'
     518        22588 :   write(51,'(a,17x,a,33x,a,34x,a)') 'Mode Ion','X','Y','Z'
     519       175969 :   do ii=1,3*Invar%natom_unitcell
     520       779182 :     do jj=1,Invar%natom_unitcell
     521       603213 :       write(51,'(i2,3x,i2,3x,6(f15.12,1x))') ii,jj,real(eigenV(3*(jj-1)+1,ii)),&
     522       603213 : &                                                 aimag(eigenV(3*(jj-1)+1,ii)),&
     523       603213 : &                                                  real(eigenV(3*(jj-1)+2,ii)),&
     524       603213 : &                                                 aimag(eigenV(3*(jj-1)+2,ii)),&
     525       603213 : &                                                  real(eigenV(3*(jj-1)+3,ii)),&
     526      1359807 : &                                                 aimag(eigenV(3*(jj-1)+3,ii))
     527              :     enddo
     528              :   enddo
     529              : 
     530              : 
     531        22588 :   ABI_FREE(omega)
     532        22588 :   ABI_FREE(dij)
     533        22588 :   ABI_FREE(eigenV)
     534              : 
     535        22588 : end subroutine tdep_write_dij
     536              : 
     537              : !=====================================================================================================
     538       300160 : subroutine tdep_build_phi2_33(isym,Phi2_ref,Phi2_33,Sym,itrans)
     539              : 
     540              :   type(Symmetries_type),intent(in) :: Sym
     541              : ! type(atdep_dataset_type),intent(in) :: Invar
     542              :   double precision, intent(in) :: Phi2_ref(3,3)
     543              :   double precision, intent(out) :: Phi2_33(3,3)
     544              :   integer,intent(in) :: isym,itrans
     545              : 
     546              :   double precision :: Phi2_tmp(3,3),tmp1(3,3)
     547              : 
     548              : ! Transform in the new basis wrt S_ref
     549       300160 :   call DGEMM('N','N',3,3,3,1.d0,Sym%S_ref(:,:,isym,1),3,Phi2_ref,3,0.d0,Phi2_tmp,3)
     550       300160 :   call DGEMM('N','N',3,3,3,1.d0,Phi2_tmp,3,Sym%S_inv(:,:,isym,1),3,0.d0,Phi2_33,3)
     551              : 
     552       300160 :   if ((itrans.lt.1).or.(itrans.gt.2)) then
     553            0 :     ABI_BUG('This value of the symmetry index is not permitted')
     554              :   end if
     555              : ! Transpose the 3x3 matrix if required
     556       300160 :   if (itrans.eq.2) then
     557        46327 :     tmp1(:,:)=Phi2_33(:,:)
     558        46327 :     Phi2_33(1,2)=tmp1(2,1)
     559        46327 :     Phi2_33(1,3)=tmp1(3,1)
     560        46327 :     Phi2_33(2,3)=tmp1(3,2)
     561        46327 :     Phi2_33(2,1)=tmp1(1,2)
     562        46327 :     Phi2_33(3,1)=tmp1(1,3)
     563        46327 :     Phi2_33(3,2)=tmp1(2,3)
     564              :   end if
     565              : 
     566       300160 : end subroutine tdep_build_phi2_33
     567              : 
     568              : !=====================================================================================================
     569           88 : subroutine tdep_init_eigen2nd(Eigen2nd,natom_unitcell,nqpt)
     570              : 
     571              :   integer, intent(in) :: natom_unitcell,nqpt
     572              :   type(Eigen_type),intent(out) :: Eigen2nd
     573              : 
     574       309521 :   ABI_MALLOC(Eigen2nd%eigenval,(3*natom_unitcell,nqpt));                    Eigen2nd%eigenval(:,:)        =zero
     575     13432522 :   ABI_MALLOC(Eigen2nd%eigenvec,(2,3,natom_unitcell,3,natom_unitcell,nqpt)); Eigen2nd%eigenvec(:,:,:,:,:,:)=zero
     576     13432346 :   ABI_MALLOC(Eigen2nd%dynmat  ,(2,3,natom_unitcell,3,natom_unitcell,nqpt)); Eigen2nd%dynmat  (:,:,:,:,:,:)=zero
     577              : 
     578           88 : end subroutine tdep_init_eigen2nd
     579              : 
     580              : !=====================================================================================================
     581           88 : subroutine tdep_destroy_eigen2nd(Eigen2nd)
     582              : 
     583              :   type(Eigen_type),intent(inout) :: Eigen2nd
     584              : 
     585           88 :   ABI_FREE(Eigen2nd%eigenval)
     586           88 :   ABI_FREE(Eigen2nd%eigenvec)
     587           88 :   ABI_FREE(Eigen2nd%dynmat)
     588              : 
     589           88 : end subroutine tdep_destroy_eigen2nd
     590              : 
     591              : !=====================================================================================================
     592           44 : subroutine tdep_write_yaml(Eigen2nd,Qpt,Prefix)
     593              : 
     594              :   type(Eigen_type),intent(in) :: Eigen2nd
     595              :   type(Qpoints_type),intent(in) :: Qpt
     596              :   character(len=*) :: Prefix
     597              : 
     598              :   integer :: ii,jj,iatcell,jatcell,iqpt,imode,nmode
     599              :   double precision :: distance
     600           44 :   double complex, allocatable   :: eigenV(:,:)
     601              : 
     602           44 :   nmode=size(Eigen2nd%eigenval,dim=1)
     603           44 :   open(unit=52,file=trim(Prefix)//'_phonon-bands.yaml')
     604           44 :   write(52,'(a,i4)') 'nqpoint:',Qpt%nqpt
     605           44 :   write(52,'(a,i4)') 'npath:',Qpt%qpt_tot-1
     606           44 :   write(52,'(a)')    'segment_nqpoint:'
     607          270 :   do ii=1,Qpt%qpt_tot-1
     608          270 :     write(52,'(a,i4)') '- ',Qpt%lgth_segments(ii)
     609              :   end do
     610           44 :   write(52,'(a,i4)')    'natom:',nmode/3
     611           44 :   write(52,'(a)')    'phonon:'
     612           44 :   distance=0.d0
     613        22632 :   do iqpt=1,Qpt%nqpt
     614        22588 :     write(52,'(a,3(f15.6,1x,a))') '- q-position: [',Qpt%qpt_red(1,iqpt),',',Qpt%qpt_red(2,iqpt),',',Qpt%qpt_red(3,iqpt),']'
     615        90220 :     if (iqpt.gt.1) distance=distance+sqrt(sum((Qpt%qpt_cart(:,iqpt)-Qpt%qpt_cart(:,iqpt-1))**2))
     616        22588 :     write(52,'(a,f15.6)') '  distance:',distance
     617       178068 :     do ii=1,Qpt%qpt_tot
     618       645318 :       if (sum(abs(Qpt%qpt_red(:,iqpt)-Qpt%special_red(ii,:))).lt.tol8) then
     619          270 :         write(52,'(3a)') "  label: '",trim(Qpt%special_qpt(ii)),"'"
     620          270 :         exit
     621              :       end if
     622              :     end do !ii
     623      2053372 :     ABI_MALLOC(eigenV,(nmode,nmode)); eigenV(:,:)=czero
     624        73715 :     do iatcell=1,nmode/3
     625       274786 :       do jatcell=1,nmode/3
     626       855411 :         do ii=1,3
     627      2613923 :           do jj=1,3
     628              :             eigenV((iatcell-1)*3+ii,(jatcell-1)*3+jj)=dcmplx(Eigen2nd%eigenvec(1,ii,iatcell,jj,jatcell,iqpt),&
     629      2412852 : &                                                            Eigen2nd%eigenvec(2,ii,iatcell,jj,jatcell,iqpt))
     630              :           end do !ii
     631              :         end do !jj
     632              :       end do !jatcell
     633              :     end do !iatcell
     634        22588 :     write(52,'(a)')    '  band:'
     635       175969 :     do imode=1,nmode
     636       153381 :       write(52,'(a,i4)')    '  - #',imode
     637       153381 :       write(52,'(a,f15.6)') '    frequency:',Eigen2nd%eigenval(imode,iqpt)*Ha_THz
     638       153381 :       write(52,'(a)') '    eigenvector:'
     639       779182 :       do iatcell=1,nmode/3
     640       603213 :         write(52,'(a,i4)') "    - # atom ", iatcell
     641      2566233 :         do ii=1,3
     642      1809639 :           write(52,'(a,f18.9,a,f18.9,a)') "      - [",real(eigenV((iatcell-1)*3+ii,imode)),','&
     643      4222491 : &           ,aimag(eigenV((iatcell-1)*3+ii,imode)),']'
     644              :         end do
     645              :       end do
     646              :     end do !nmode
     647        22588 :     ABI_FREE(eigenV)
     648        22632 :     write(52,'(a)') ''
     649              :   end do
     650              : 
     651           44 :   close(52)
     652              : 
     653              : 
     654           44 : end subroutine tdep_write_yaml
     655              : 
     656              : !=====================================================================================================
     657            0 : end module m_tdep_phi2
        

Generated by: LCOV version 2.3-1