LCOV - code coverage report
Current view: top level - src/78_effpot - m_supercell_maker.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 50.7 % 211 107
Test Date: 2026-11-11 08:14:47 Functions: 55.6 % 27 15
Branches: 37.0 % 576 213

             Branch data     Line data    Source code
       1                 :             : !!****m* ABINIT/m_supercell_maker
       2                 :             : !! NAME
       3                 :             : !! m_supercell_maker
       4                 :             : !!
       5                 :             : !! FUNCTION
       6                 :             : !! This module define the supercell_maker file, which provide functions to help build
       7                 :             : !! potentials in supercell.
       8                 :             : !! Note: This module works at lower level than m_supercell. The purpose is not to get
       9                 :             : !! an supercell of crystal structure, but it provide the functions to help building such thing (but not limited to).
      10                 :             : !!
      11                 :             : !! TODO: update m_supercell based on this so that it can use non-diagonal supercell matrix.
      12                 :             : !! Then this need to be moved to level same as m_supercell.
      13                 :             : !!
      14                 :             : !! Datatypes:
      15                 :             : !!  supercell_maker_t
      16                 :             : !!
      17                 :             : !! Subroutines:
      18                 :             : !!
      19                 :             : !!
      20                 :             : !! COPYRIGHT
      21                 :             : !! Copyright (C) 2001-2026 ABINIT group (hexu)
      22                 :             : !! This file is distributed under the terms of the
      23                 :             : !! GNU General Public License, see ~abinit/COPYING
      24                 :             : !! or http://www.gnu.org/copyleft/gpl.txt .
      25                 :             : !! For the initials of contributors, see ~abinit/doc/developers/contributors.txt .
      26                 :             : !!
      27                 :             : !! SOURCE
      28                 :             : 
      29                 :             : 
      30                 :             : #if defined HAVE_CONFIG_H
      31                 :             : #include "config.h"
      32                 :             : #endif
      33                 :             : #include "abi_common.h"
      34                 :             : 
      35                 :             : module m_supercell_maker
      36                 :             :   use defs_basis
      37                 :             :   use m_abicore
      38                 :             :   use m_errors
      39                 :             :   use m_xmpi
      40                 :             :   use m_mathfuncs,     only: binsearch_left_integerlist, rotate_by_angle_around_axis
      41                 :             :   use m_matrix,        only: matr3inv, mat33det
      42                 :             :   use m_mpi_scheduler, only: init_mpi_info
      43                 :             :   use m_supercell
      44                 :             :   implicit none
      45                 :             :   private
      46                 :             : !!***
      47                 :             :   !-----------------------------------------------------------------------
      48                 :             :   !> @brief A helper type to build supercell and potentials from primitive
      49                 :             :   !> It keep the information of the supercell matrix, and the R-vectors (R1~Rn),
      50                 :             :   !> so that the potentials in
      51                 :             :   !> For a list of indices in primitive cell (e.g. (i, j, k)), it will become
      52                 :             :   !> (i,R0), (j, R0), (k, R0), (i, R1), (i, R1), ... (i, Rn), (j,Rn), (k, Rn)
      53                 :             :   !-----------------------------------------------------------------------
      54                 :             :   type ,public :: supercell_maker_t
      55                 :             :      integer :: scmat(3,3)  ! supercell matrix
      56                 :             :      real(dp) :: inv_scmat(3,3) ! inverse of supercell matrix
      57                 :             :      integer :: ncells         ! number of cells in supercell
      58                 :             :      integer, allocatable :: rvecs(:,:) ! R vectors for cells in supercell. dim:(3, ncells)
      59                 :             :    contains
      60                 :             :      procedure :: initialize
      61                 :             :      procedure :: finalize
      62                 :             :      procedure :: to_red_sc
      63                 :             :      procedure :: build_rvec
      64                 :             :      procedure :: sc_cell
      65                 :             :      procedure :: R_to_sc
      66                 :             : 
      67                 :             :      ! Translations: from one primitive cell element to ncell supercell elements
      68                 :             :      ! with values unchanged (therefore just repeat ncells times)
      69                 :             :      generic :: repeat => repeat_int1d, repeat_real1d, repeat_real2d, repeat_realmat
      70                 :             :      procedure :: repeat_int1d
      71                 :             :      procedure :: repeat_int1d_noalloc
      72                 :             :      procedure :: repeat_real1d
      73                 :             :      procedure :: repeat_real2d
      74                 :             :      procedure :: repeat_realmat
      75                 :             : 
      76                 :             :      ! Translations: from one primitive cell element to ncell supercell elements
      77                 :             :      ! with values changed (different from repeat)
      78                 :             :      procedure :: trans_xred
      79                 :             :      procedure :: trans_xcart
      80                 :             :      procedure :: trans_i
      81                 :             :      procedure :: trans_i_noalloc
      82                 :             :      procedure :: trans_ilist
      83                 :             :      procedure :: trans_j_and_Rj
      84                 :             :      procedure :: trans_j_and_Rj_noalloc
      85                 :             :      procedure :: trans_jlist_and_Rj
      86                 :             :      procedure :: rvec_for_each
      87                 :             : 
      88                 :             :      ! Wave like quantities:
      89                 :             :      procedure :: generate_wave_scalar   ! s=s0*e^{ikR}
      90                 :             :      procedure :: generate_spin_wave_vectorlist  !vector with rotation angle= 2pi k * R
      91                 :             :   end type supercell_maker_t
      92                 :             : 
      93                 :             :   public :: scmaker_unittest
      94                 :             : contains
      95                 :             : 
      96                 :             :   !-----------------------------------------------------------------------
      97                 :             :   !> @brief initialize
      98                 :             :   !> @param [in] sc_matrix: the supercell matrix which maps the primitive cell to sc
      99                 :             :   !>       it does not have to be diagonal.
     100                 :             :   !-----------------------------------------------------------------------
     101                 :           6 :   subroutine initialize(self, sc_matrix)
     102                 :             :     class(supercell_maker_t), intent(inout) :: self
     103                 :             :     integer, intent(in) :: sc_matrix(3, 3)
     104                 :             :     real(dp) :: tmp(3,3)
     105                 :             :     integer :: master, my_rank, comm, nproc, ierr
     106                 :             :     logical :: iam_master
     107                 :           6 :     call init_mpi_info(master, iam_master, my_rank, comm, nproc)
     108                 :             : 
     109   [ +  +  +  + ]:          78 :     self%scmat(:,:)=sc_matrix
     110                 :           6 :     call xmpi_bcast(self%scmat, master, comm, ierr)
     111                 :           6 :     self%ncells=abs(mat33det(self%scmat))
     112                 :             :     ! call xmpi_bcast(self%ncells, master, comm, ierr)
     113   [ -  +  +  -  :          18 :     ABI_MALLOC(self%rvecs, (3, self%ncells))
          +  -  +  -  -  
             +  -  +  -  
                      + ]
     114                 :             :     ! Why transpose?
     115   [ +  +  +  + ]:          78 :     tmp(:,:)=transpose(self%scmat)
     116                 :             : 
     117                 :             :     ! save inverse of matrix so A^{-1} x can be easily calculated.
     118                 :           6 :     call matr3inv(tmp, self%inv_scmat)
     119                 :           6 :     call self%build_rvec()
     120                 :             :     !call xmpi_bcast(self%inv_scmat, master, comm, ierr)
     121                 :             :     !call xmpi_bcast(self%ncells, master, comm, ierr)
     122                 :             :     !call xmpi_bcast(self%rvecs, master, comm, ierr)
     123                 :           6 :   end subroutine initialize
     124                 :             : 
     125                 :             :   !-----------------------------------------------------------------------
     126                 :             :   !> @brief Finalize
     127                 :             :   !-----------------------------------------------------------------------
     128                 :           6 :   subroutine finalize(self)
     129                 :             :     class(supercell_maker_t), intent(inout) :: self
     130   [ +  +  +  + ]:          78 :     self%scmat=0
     131                 :           6 :     self%ncells=0
     132         [ +  - ]:           6 :     if (allocated(self%rvecs)) then
     133                 :           6 :        ABI_FREE(self%rvecs)
     134                 :             :     end if
     135                 :           6 :   end subroutine finalize
     136                 :             : 
     137                 :             :   !-----------------------------------------------------------------------
     138                 :             :   !> @brief from reduced coordinate in primitive cell to that insupercell
     139                 :             :   !>  This does not use translation symmetry, so it is a ONE to ONE convert.
     140                 :             :   !> @param [in] pos (reduced position in primitive cell)
     141                 :             :   !> @param [out] ret reduce position in supercell
     142                 :             :   !-----------------------------------------------------------------------
     143         [ -  + ]:     3619346 :   function to_red_sc(self, pos) result(ret)
     144                 :             :     class(supercell_maker_t), intent(inout) :: self
     145                 :             :     real(dp), intent(in) :: pos(3)
     146                 :             :     real(dp) :: ret(3)
     147   [ +  +  +  +  :    61528882 :     ret(:)=matmul(pos, self%inv_scmat)
                   +  + ]
     148                 :     3619346 :   end function to_red_sc
     149                 :             : 
     150                 :             :   !-----------------------------------------------------------------------
     151                 :             :   !> @brief build R vectors for supercells.
     152                 :             :   !-----------------------------------------------------------------------
     153                 :           6 :   subroutine build_rvec(self)
     154                 :             :     class(supercell_maker_t), intent(inout) :: self
     155                 :             :     real(dp):: scorners_newcell(8,3), corners(8,3), x(3), tmp(3)
     156                 :             :     integer :: minr(3), maxr(3), ix, iy, iz, counter
     157                 :             :     real(dp) :: eps=1d-9
     158                 :           6 :     counter=0
     159                 :             :     ! cornors
     160                 :             :     scorners_newcell=transpose(reshape([0., 0., 0., 0., 0., 1., 0., 1., 0., &
     161                 :             :          0., 1., 1., 1., 0., 0., 1., 0., 1.,  &
     162                 :           6 :          1., 1., 0., 1., 1., 1.],[3,8]))
     163   [ +  +  +  +  :         582 :     corners = matmul(scorners_newcell, self%scmat)
          +  +  +  +  +  
                      + ]
     164                 :             :     !rep=ceiling(maxval(corners, dim=1) - minval(corners, dim=1))
     165   [ +  +  -  + ]:          24 :     minr=floor(minval(corners, dim=1))
     166   [ +  +  -  + ]:          24 :     maxr=ceiling(maxval(corners, dim=1))
     167                 :             :     ! NOTE: DO NOT CHANGE THE ORDER. It is used in the binary search.
     168         [ +  + ]:          48 :     do ix = minr(1), maxr(1)
     169         [ +  + ]:         350 :        do iy = minr(2), maxr(2)
     170         [ +  + ]:        2570 :           do iz = minr(3), maxr(3)
     171         [ +  + ]:        8904 :              x(:)=[ix, iy, iz]
     172         [ +  + ]:        8904 :              tmp=self%to_red_sc(x)
     173                 :             :              if ( (.not. any(tmp<=-1.0*eps)) &
     174   [ +  +  +  -  :       14234 :                   .and. (.not. any(tmp>1.0-eps)) ) then
          +  +  +  +  +  
                      + ]
     175                 :        1440 :                 counter=counter+1
     176         [ +  + ]:        5760 :                 self%rvecs(:,counter)=nint(x)
     177                 :             :              end if
     178                 :             :           end do
     179                 :             :        end do
     180                 :             :     end do
     181         [ -  + ]:           6 :     if (counter /= self%ncells ) then
     182                 :           0 :        ABI_ERROR("Bug found. supercell_maker: Wrong number of supercell found in build_rvec. ")
     183                 :             :     end if
     184                 :           6 :   end subroutine build_rvec
     185                 :             : 
     186                 :             :   !-----------------------------------------------------------------------
     187                 :             :   !> @brief cell parameters from unitcell to supercell
     188                 :             :   !> @param [in] cell: cell parameter in primitive cell
     189                 :             :   !> @param [out] sccell: supercell cell parameter
     190                 :             :   !-----------------------------------------------------------------------
     191         [ -  + ]:           8 :   function sc_cell(self, cell) result(sccell)
     192                 :             :     class(supercell_maker_t), intent(inout) :: self
     193                 :             :     real(dp), intent(in) :: cell(3,3)
     194                 :             :     real(dp) :: sccell(3,3)
     195   [ +  +  +  +  :         528 :     sccell=matmul(self%scmat, cell)
          +  +  +  +  +  
             +  +  +  +  
                      + ]
     196                 :           8 :   end function sc_cell
     197                 :             : 
     198                 :             :   !-----------------------------------------------------------------------
     199                 :             :   !> @brief reduced position in primitive cell to supercell.
     200                 :             :   !>    It use translation symmetry. so (3,n) -> (3, n*ncells)
     201                 :             :   !> Note that allocation will be done if not already allocated.
     202                 :             :   !> @param [in] xred: reduced coordinates in primitive cell
     203                 :             :   !> @param [out] sccell: reduced coordinates in supercell
     204                 :             :   !-----------------------------------------------------------------------
     205         [ #  # ]:           0 :   subroutine trans_xred(self, xred, scxred)
     206                 :             :     class(supercell_maker_t), intent(inout) :: self
     207                 :             :     real(dp), intent(in) :: xred(:,:)
     208                 :             :     real(dp), allocatable, intent(inout) :: scxred(:, :)
     209                 :             :     integer :: npos, icell, ipos, counter=0
     210                 :           0 :     npos=size(xred, dim=2)
     211         [ #  # ]:           0 :     if (.not. allocated(scxred)) then
     212   [ #  #  #  #  :           0 :        ABI_MALLOC(scxred, (3,size(xred, dim=2)*self%ncells))
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     213                 :             :     end if
     214         [ #  # ]:           0 :     do icell = 1, self%ncells
     215         [ #  # ]:           0 :        do ipos=1 , npos
     216                 :           0 :           counter=counter+1
     217   [ #  #  #  #  :           0 :           scxred(:, counter) = self%to_red_sc(xred(:, ipos)+ self%rvecs(:, icell))
                   #  # ]
     218                 :             :        end do
     219                 :             :     end do
     220                 :           0 :   end subroutine trans_xred
     221                 :             : 
     222                 :             :   !-----------------------------------------------------------------------
     223                 :             :   !> @brief cartesion position in primitive cell to supercell.
     224                 :             :   !>    It use translation symmetry. so (3,n) -> (3, n*ncells)
     225                 :             :   !> Note that allocation will be done if not already allocated.
     226                 :             :   !> @param [in] primcell: cell parameter in primitive cell
     227                 :             :   !> @param [in] xcart: cartesion coordinates in primitive cell
     228                 :             :   !> @param [out] scxcart:cartesion coordinates in supercell
     229                 :             :   !-----------------------------------------------------------------------
     230         [ -  + ]:           8 :   subroutine trans_xcart(self, primcell, xcart, scxcart)
     231                 :             :     class(supercell_maker_t), intent(inout) :: self
     232                 :             :     real(dp), intent(in) :: xcart(:,:), primcell(3,3)
     233                 :             :     real(dp), allocatable, intent(inout) :: scxcart(:,:)
     234                 :             :     integer :: npos, icell, ipos, counter
     235                 :           8 :     counter =0
     236                 :           8 :     npos=size(xcart, dim=2)
     237         [ +  + ]:           8 :     if (.not. allocated(scxcart)) then
     238   [ -  +  +  -  :          18 :        ABI_MALLOC(scxcart, (3,npos*self%ncells))
          +  -  +  -  -  
             +  -  +  -  
                      + ]
     239                 :             :     end if
     240         [ +  + ]:        1880 :     do icell = 1, self%ncells
     241         [ +  + ]:       10024 :        do ipos=1 , npos
     242                 :        8144 :           counter=counter+1
     243   [ +  +  +  -  :      189184 :           scxcart(:, counter) = matmul(self%rvecs(:, icell), primcell) + xcart(:,ipos)
          +  +  +  +  +  
          +  +  -  +  -  
                   +  + ]
     244                 :             :        end do
     245                 :             :     end do
     246                 :           8 :   end subroutine trans_xcart
     247                 :             : 
     248                 :             : 
     249                 :             :   !-----------------------------------------------------------------------
     250                 :             :   !> @brief Find a R vector in primitive cell unit to a R vector in supercell unit
     251                 :             :   !>  Here is an example:
     252                 :             :   !>   A Rp for a 1*1*1 primitive cell. Rp=(0,0, 3)
     253                 :             :   !>   For a supercell of 1*1*2, Rp = (0, 0, 1) * supercell + (0, 0, 1) * primcell
     254                 :             :   !> @param [in] R index using primitive cell parameter
     255                 :             :   !> @param [out] R index using supercell parameter
     256                 :             :   !> @param [out] index of cell INSIDE supercell in primitive cell.
     257                 :             :   !-----------------------------------------------------------------------
     258                 :     3617120 :   subroutine R_to_sc(self, R, R_sc, ind_sc)
     259                 :             :     class(supercell_maker_t), intent(inout) :: self
     260                 :             :     integer, intent(in) :: R(3)
     261                 :             :     integer, intent(inout) :: ind_sc, R_sc(3)
     262                 :             :     integer :: rprim(3)
     263   [ +  +  +  +  :    25319840 :     R_sc=floor(self%to_red_sc(R*1.0d0)+1.0d-8)
                   +  + ]
     264   [ +  +  +  +  :    61491040 :     rprim(:)= R-matmul(R_sc, self%scmat)
                   +  + ]
     265                 :     3617120 :     ind_sc=binsearch_left_integerlist(self%rvecs, rprim)
     266         [ -  + ]:     3617120 :     if (ind_sc==0) then
     267                 :             :        !print *, "R: " , R
     268                 :             :        !print *, "Rredsc:", self%to_red_sc(R*1.0d0)
     269                 :             :        !print *, "R_sc: " , R_sc
     270                 :             :        !print *, "rprim", rprim
     271                 :           0 :        ABI_ERROR("Bug found. supercell_maker%R_to_sc: Cannot find rprim")
     272                 :             :     end if
     273                 :     3617120 :   end subroutine R_to_sc
     274                 :             : 
     275                 :             : 
     276                 :             : 
     277                 :             :   !-----------------------------------------------------------------------
     278                 :             :   !> @brief generate a wave like quantity. A_sc(R) = A(0)* exp(ikR)
     279                 :             :   !>  The A_sc will be allocated. size : (ncells)
     280                 :             :   !> @param [in] A: a scalar quantity.
     281                 :             :   !> @param [in] kpoint: the wave vector
     282                 :             :   !> @param [out] A_sc: indices in supercell.
     283                 :             :   !-----------------------------------------------------------------------
     284                 :           0 :   subroutine generate_wave_scalar(self, A, kpoint, A_sc)
     285                 :             :     class(supercell_maker_t), intent(inout) :: self
     286                 :             :     real(dp), intent(in) :: A
     287                 :             :     real(dp), intent(in) ::  kpoint(3)
     288                 :             :     real(dp), allocatable, intent(inout) :: A_sc(:)
     289                 :             :     integer :: i
     290         [ #  # ]:           0 :     if(.not. allocated(A_sc)) then
     291   [ #  #  #  #  :           0 :        ABI_MALLOC(A_sc, (self%ncells))
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     292                 :             :     end if
     293         [ #  # ]:           0 :     do i=1, self%ncells
     294                 :             :        A_sc(i) = real(A*exp(cmplx(0.0,two_pi, kind=dp) * &
     295         [ #  # ]:           0 :             &dot_product(kpoint, self%rvecs(:, i))), kind=dp)
     296                 :             :     end do
     297                 :           0 :   end subroutine generate_wave_scalar
     298                 :             : 
     299                 :             :   !-----------------------------------------------------------------------
     300                 :             :   !> @brief generate a wave like quantity. A_sc(R) = A(0)* exp(ikR)
     301                 :             :   !>  The A_sc will be allocated. size : (nA*ncells)
     302                 :             :   !> @param [in] A: a list scalar quantity in primitive cell.
     303                 :             :   !> @param [in] kpoint: the wave vector
     304                 :             :   !> @param [out] A_sc: indices in supercell.
     305                 :             :   !-----------------------------------------------------------------------
     306                 :             :   subroutine generate_wave_scalarlist(self, A, kpoint, A_sc)
     307                 :             :     class(supercell_maker_t), intent(inout) :: self
     308                 :             :     real(dp), intent(in) :: A(:)
     309                 :             :     real(dp), intent(in) ::  kpoint(3)
     310                 :             :     real(dp), allocatable, intent(inout) :: A_sc(:)
     311                 :             :     integer :: icell, iA, nA, counter
     312                 :             :     nA=size(A)
     313                 :             :     if(.not. allocated(A_sc)) then
     314                 :             :        ABI_MALLOC(A_sc, (nA*self%ncells))
     315                 :             :     end if
     316                 :             :     counter=0
     317                 :             :     do icell = 1, self%ncells
     318                 :             :        do iA=1 , nA
     319                 :             :           counter=counter+1
     320                 :             :           A_sc(counter) = real(A(iA)*exp(cmplx(0.0,two_pi, kind=dp) * &
     321                 :             :                &dot_product(kpoint, self%rvecs(:, icell))), kind=dp)
     322                 :             :        end do
     323                 :             :     end do
     324                 :             :   end subroutine generate_wave_scalarlist
     325                 :             : 
     326                 :             : 
     327                 :             :   !-----------------------------------------------------------------------
     328                 :             :   !> @brief generate a wave like quantity. A_sc(R) = A(0)* exp(ikR)
     329                 :             :   !>  The A_sc will be allocated. size : (ndim, nA*ncells)
     330                 :             :   !>   NOTE: This generate a density wave. For a spin wave,
     331                 :             :   !>         use generate_spin_wave_vectorlist.
     332                 :             :   !> @param [in] A: a vector quantity. dimension (xyz, iA)
     333                 :             :   !> @param [in] kpoint: the wave vector
     334                 :             :   !> @param [out] A_sc: indices in supercell.
     335                 :             :   !-----------------------------------------------------------------------
     336                 :             :   subroutine generate_wave_vectorlist(self, A, kpoint, A_sc)
     337                 :             :     class(supercell_maker_t), intent(inout) :: self
     338                 :             :     real(dp), intent(in) :: A(:, :)
     339                 :             :     real(dp), intent(in) ::  kpoint(3)
     340                 :             :     real(dp), allocatable, intent(inout) :: A_sc(:, :)
     341                 :             :     integer :: icell, iA, nA, counter, ndim
     342                 :             :     ndim=size(A, 1)
     343                 :             :     nA=size(A,2)
     344                 :             :     if(.not. allocated(A_sc)) then
     345                 :             :        ABI_MALLOC(A_sc, (ndim, nA*self%ncells))
     346                 :             :     end if
     347                 :             :     counter=0
     348                 :             :     do icell = 1, self%ncells
     349                 :             :        do iA=1 , nA
     350                 :             :           counter=counter+1
     351                 :             :           A_sc(:,counter) = real(A(:,iA)*exp(cmplx(0.0,two_pi, kind=dp) * &
     352                 :             :                &dot_product(kpoint, self%rvecs(:, icell))), kind=dp)
     353                 :             :        end do
     354                 :             :     end do
     355                 :             :   end subroutine generate_wave_vectorlist
     356                 :             : 
     357                 :             : 
     358                 :             :   !-----------------------------------------------------------------------
     359                 :             :   !> @brief generate a spin wave  quantity.
     360                 :             :   !>  rotate by theta(R) = 2pi * k.dot.R, around axis.
     361                 :             :   !>  The A_sc will be allocated. size : (ndim, nA*ncells)
     362                 :             :   !> @param [in] A: a vector quantity. dimension (xyz, iA)
     363                 :             :   !> @param [in] kpoint: the wave vector
     364                 :             :   !> @param [in] axis: the axis to rotate around
     365                 :             :   !> @param [out] A_sc: indices in supercell.
     366                 :             :   !-----------------------------------------------------------------------
     367         [ -  + ]:           2 :   subroutine generate_spin_wave_vectorlist(self, A, kpoint, axis, A_sc)
     368                 :             :     class(supercell_maker_t), intent(inout) :: self
     369                 :             :     real(dp), intent(in) :: A(:, :) !(3, dimension of primitive cell)
     370                 :             :     real(dp), intent(in) ::  kpoint(3)
     371                 :             :     real(dp), intent(in) ::  axis(3)
     372                 :             :     real(dp), allocatable, intent(inout) :: A_sc(:, :) !(3, dimension of supercell)
     373                 :             :     integer :: icell, iA, nA, counter, ndim
     374                 :             :     real(dp):: angle
     375                 :           2 :     ndim=size(A, 1)
     376                 :           2 :     nA=size(A,2)
     377         [ -  + ]:           2 :     if(.not. allocated(A_sc)) then
     378   [ #  #  #  #  :           0 :        ABI_MALLOC(A_sc, (ndim, nA*self%ncells))
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     379                 :             :     end if
     380                 :           2 :     counter=0
     381         [ +  + ]:         434 :     do icell = 1, self%ncells
     382         [ +  + ]:         866 :        do iA=1, nA
     383                 :         432 :           counter=counter+1
     384         [ +  + ]:        1728 :           angle=two_pi* DOT_PRODUCT(kpoint,  self%rvecs(:, icell))
     385   [ -  +  -  -  :        2160 :           A_sc(:,counter) = rotate_by_angle_around_axis(angle=angle, axis=axis, vec=A(:, iA))
          -  -  -  +  +  
                      + ]
     386                 :             :        end do
     387                 :             :     end do
     388                 :           2 :   end subroutine generate_spin_wave_vectorlist
     389                 :             : 
     390                 :             : 
     391                 :             :   !-----------------------------------------------------------------------
     392                 :             :   !> @brief Get the indices of all the supercell repeat of an index in primitive cell
     393                 :             :   !> @param [in] nbasis: total number of indices in the primitive cell (eg. natom in a cell)
     394                 :             :   !>  Note that if the dimension xyz is also in the index, then use 3*natom.
     395                 :             :   !>  i_sc array will be allocated if not already done
     396                 :             :   !> This function is mostly useful for building supercell potential with such format H_ij(R_j)
     397                 :             :   !> @param [in] i: index in primitive cell
     398                 :             :   !> @param [out] i_sc: indices in supercell.
     399                 :             :   !-----------------------------------------------------------------------
     400                 :        8309 :   subroutine trans_i(self, nbasis, i, i_sc)
     401                 :             :     class(supercell_maker_t), intent(inout) :: self
     402                 :             :     integer, intent(in) :: i, nbasis
     403                 :             :     integer, allocatable, intent(inout) :: i_sc(:)
     404         [ +  + ]:        8309 :     if(.not. allocated(i_sc)) then
     405   [ -  +  +  -  :       16347 :        ABI_MALLOC(i_sc, (self%ncells))
          +  -  +  -  -  
             +  -  +  -  
                      + ]
     406                 :             :     end if
     407                 :        8309 :     call self%trans_i_noalloc(nbasis, i, i_sc)
     408                 :        8309 :   end subroutine trans_i
     409                 :             : 
     410                 :             :   !-----------------------------------------------------------------------
     411                 :             :   !> @brief Get the indices of all the supercell repeat of an index in primitive cell
     412                 :             :   !> @param [in] nbasis: total number of indices in the primitive cell (eg. natom in a cell)
     413                 :             :   !>  Note that if the dimension xyz is also in the index, then use 3*natom.
     414                 :             :   !>  i_sc array will NOT be allocated.
     415                 :             :   !> This function is mostly useful for building supercell potential with such format H_ij(R_j)
     416                 :             :   !> @param [in] i: index in primitive cell
     417                 :             :   !> @param [out] i_sc: indices in supercell.
     418                 :             :   !-----------------------------------------------------------------------
     419         [ -  + ]:        8309 :   subroutine trans_i_noalloc(self, nbasis, i, i_sc)
     420                 :             :     class(supercell_maker_t), intent(inout) :: self
     421                 :             :     integer, intent(in) :: i, nbasis
     422                 :             :     integer, intent(inout) :: i_sc(:)
     423                 :             :     integer :: icell
     424         [ +  + ]:     1757397 :     do icell =1, self%ncells
     425                 :     1757397 :        i_sc(icell)=nbasis*(icell-1)+i
     426                 :             :     end do
     427                 :        8309 :   end subroutine trans_i_noalloc
     428                 :             : 
     429                 :             : 
     430                 :             :   !-----------------------------------------------------------------------
     431                 :             :   !> @brief Get the indices of all the supercell repeat of an LIST of indices in primitive cell
     432                 :             :   !> @param [in] nbasis: total number of indices in the primitive cell (eg. natom in a cell)
     433                 :             :   !>  Note that if the dimension xyz is also in the index, then use 3*natom.
     434                 :             :   !>  i_sc array will be allocated if not already done.
     435                 :             :   !> This function is mostly useful for building supercell potential with such format H_ij(R_j)
     436                 :             :   !> @param [in] ilist: list of indices in primitive cell
     437                 :             :   !> @param [out] ilist_sc: list of indices in supercell.
     438                 :             :   !-----------------------------------------------------------------------
     439         [ #  # ]:           0 :   subroutine trans_ilist(self, nbasis, ilist, ilist_sc)
     440                 :             :     class(supercell_maker_t), intent(inout) :: self
     441                 :             :     integer, intent(in) :: ilist(:), nbasis
     442                 :             :     integer, allocatable,  intent(inout) :: ilist_sc(:)
     443                 :             :     integer :: i
     444         [ #  # ]:           0 :     if(.not. allocated(ilist_sc)) then
     445   [ #  #  #  #  :           0 :        ABI_MALLOC(ilist_sc, (size(ilist)*self%ncells))
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     446                 :             :     end if
     447         [ #  # ]:           0 :     do i =1, size(ilist)
     448                 :           0 :        call trans_i_noalloc(self,nbasis, ilist(i), ilist_sc(self%ncells*(i-1)+1:self%ncells*i ))
     449                 :             :     end do
     450                 :           0 :   end subroutine trans_ilist
     451                 :             : 
     452                 :             :   !-----------------------------------------------------------------------
     453                 :             :   !> @brief Get the indices and R vector for a index of j displaced by a R vector.
     454                 :             :   !>  This is often used to represent a vector outside the primitive cell.
     455                 :             :   !>      i.e. its position is (r_j + R_j) in primitive cell unit. Then it will have
     456                 :             :   !>      periodical repeats, which has index of j_sc inside supercell, and a R_sc vector to shift it.
     457                 :             :   !> @param [in] nbasis: total number of indices in the primitive cell (eg. natom in a cell)
     458                 :             :   !>  Note that if the dimension xyz is also in the index, then use 3*natom.
     459                 :             :   !>  i_sc array will be allocated if not already done.
     460                 :             :   !> This function is mostly useful for building supercell potential with such format H_ij(R_j)
     461                 :             :   !> @param [in] j: index in primitive cell
     462                 :             :   !> @param [in] Rj: R vector in primitive cell unit
     463                 :             :   !> @param [out] j_sc: index in supercell
     464                 :             :   !> @param [out] Rj_sc: R' vector in supercell unit.
     465                 :             :   !-----------------------------------------------------------------------
     466                 :       15121 :   subroutine trans_j_and_Rj(self, nbasis, j, Rj, j_sc, Rj_sc)
     467                 :             :     class(supercell_maker_t), intent(inout) :: self
     468                 :             :     integer, intent(in) :: j, Rj(3), nbasis
     469                 :             :     integer, allocatable , intent(inout) :: j_sc(:), Rj_sc(:, :)
     470         [ +  + ]:       15121 :     if(.not. allocated(j_sc)) then
     471   [ -  +  +  -  :       36783 :        ABI_MALLOC(j_sc, (self%ncells))
          +  -  +  -  -  
             +  -  +  -  
                      + ]
     472                 :             :     endif
     473         [ +  + ]:       15121 :     if(.not. allocated(Rj_sc)) then
     474   [ -  +  +  -  :       36783 :        ABI_MALLOC(Rj_sc, (3, self%ncells))
          +  -  +  -  -  
             +  -  +  -  
                      + ]
     475                 :             :     endif
     476                 :       15121 :     call self%trans_j_and_Rj_noalloc(nbasis, j, Rj, j_sc, Rj_sc)
     477                 :       15121 :   end subroutine trans_j_and_Rj
     478                 :             : 
     479                 :             :   !-----------------------------------------------------------------------
     480                 :             :   !> @brief same as trans_j_and_Rj, but it does not allocate data.
     481                 :             :   !-----------------------------------------------------------------------
     482   [ -  +  -  + ]:       15121 :   subroutine trans_j_and_Rj_noalloc(self, nbasis, j, Rj, j_sc, Rj_sc)
     483                 :             :     class(supercell_maker_t), intent(inout) :: self
     484                 :             :     integer, intent(in) :: j, Rj(3), nbasis
     485                 :             :     integer, intent(inout) :: j_sc(:), Rj_sc(:, :)
     486                 :             :     integer :: i,jj
     487         [ +  + ]:     3632241 :     do i =1, self%ncells
     488   [ +  +  -  +  :    14468480 :        call self%R_to_sc(Rj + self%rvecs(:,i), Rj_sc(:,i), jj)
          -  -  -  -  -  
                +  -  - ]
     489                 :     3632241 :        j_sc(i)=nbasis*(jj-1)+j
     490                 :             :     end do
     491                 :       15121 :   end subroutine trans_j_and_Rj_noalloc
     492                 :             : 
     493                 :             :   !-----------------------------------------------------------------------
     494                 :             :   !> @brief same as trans_j_and_Rj, but it loop over a list of j with the
     495                 :             :   !>    same Rj
     496                 :             :   !-----------------------------------------------------------------------
     497         [ #  # ]:           0 :   subroutine trans_jlist_and_Rj(self, nbasis, jlist, Rj, ind_sc, R_sc)
     498                 :             :     class(supercell_maker_t), intent(inout) :: self
     499                 :             :     integer, intent(in) :: jlist(:), Rj(3), nbasis
     500                 :             :     integer, allocatable, intent(inout) :: ind_sc(:), R_sc(:,:)
     501                 :             :     integer :: i,jj, counter, indj
     502         [ #  # ]:           0 :     if (.not. allocated(ind_sc)) then
     503   [ #  #  #  #  :           0 :        ABI_MALLOC(ind_sc, (self%ncells*size(jlist)) )
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     504                 :             :     endif
     505         [ #  # ]:           0 :     if (.not. allocated(R_sc)) then
     506   [ #  #  #  #  :           0 :        ABI_MALLOC(R_sc, (3, self%ncells))
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     507                 :             :     endif
     508                 :           0 :     counter=0
     509         [ #  # ]:           0 :     do i =1, self%ncells
     510         [ #  # ]:           0 :        call self%R_to_sc(Rj + self%rvecs(:,i), R_sc(:,i), jj)
     511         [ #  # ]:           0 :        do indj=1, size(jlist)
     512                 :           0 :           counter=counter+1
     513                 :           0 :           ind_sc(counter)=nbasis*(jj-1)+jlist(indj)
     514                 :             :        end do
     515                 :             :     end do
     516                 :           0 :   end subroutine trans_jlist_and_Rj
     517                 :             : 
     518                 :             :   !-----------------------------------------------------------------------
     519                 :             :   !> @brief same as trans_j_and_Rj, but it loop over a list of j with the
     520                 :             :   !>    same Rj
     521                 :             :   !-----------------------------------------------------------------------
     522                 :             :   subroutine trans_jlist_and_Rj_noalloc(self, nbasis, jlist, Rj, ind_sc, R_sc)
     523                 :             :     class(supercell_maker_t), intent(inout) :: self
     524                 :             :     integer, optional, intent(in) :: jlist(:)
     525                 :             :     integer, intent(in) :: Rj(3), nbasis
     526                 :             :     integer, intent(inout) :: ind_sc(:), R_sc(:,:)
     527                 :             :     integer :: i,jj, counter, indj, n
     528                 :             :     counter=0
     529                 :             :     if (present(jlist)) then
     530                 :             :        n=size(jlist)
     531                 :             :     else
     532                 :             :        n=nbasis
     533                 :             :     end if
     534                 :             :     do i =1, self%ncells
     535                 :             :        call self%R_to_sc(Rj + self%rvecs(:,i), R_sc(:,i), jj)
     536                 :             :        do indj=1, n
     537                 :             :           counter=counter+1
     538                 :             :           ind_sc(counter)=nbasis*(jj-1)+jlist(indj)
     539                 :             :        end do
     540                 :             :     end do
     541                 :             :   end subroutine trans_jlist_and_Rj_noalloc
     542                 :             : 
     543                 :             : 
     544                 :             : 
     545                 :             :   !-----------------------------------------------------------------------
     546                 :             :   !> @brief same as trans_j_and_Rj, but it loop over a list of j with the
     547                 :             :   !>    same Rj
     548                 :             :   !-----------------------------------------------------------------------
     549                 :             :   subroutine trans_ijR(self, nbasis_i, nbasis_j, ilist, jlist, Rj, i_sc, j_sc, R_sc)
     550                 :             :     class(supercell_maker_t), intent(inout) :: self
     551                 :             :     integer, intent(in) ::ilist(:), jlist(:), Rj(3), nbasis_i, nbasis_j
     552                 :             :     integer, allocatable, intent(inout) :: i_sc(:), j_sc(:), R_sc(:,:)
     553                 :             :     integer :: icell,jj, counter, indj
     554                 :             :     if (.not. allocated(i_sc)) then
     555                 :             :        ABI_MALLOC(i_sc, (self%ncells*size(jlist)) )
     556                 :             :     endif
     557                 :             :     if (.not. allocated(j_sc)) then
     558                 :             :        ABI_MALLOC(j_sc, (self%ncells*size(jlist)) )
     559                 :             :     endif
     560                 :             :     if (.not. allocated(R_sc)) then
     561                 :             :        ABI_MALLOC(R_sc, (3, self%ncells))
     562                 :             :     endif
     563                 :             :     counter=0
     564                 :             :     do icell =1, self%ncells
     565                 :             :        call self%R_to_sc(Rj + self%rvecs(:,icell), R_sc(:,icell), jj)
     566                 :             :        do indj=1, size(jlist)
     567                 :             :           counter=counter+1
     568                 :             :           i_sc(counter)=nbasis_i*(icell-1)+ilist(indj)
     569                 :             :           j_sc(counter)=nbasis_j*(jj-1)+jlist(indj)
     570                 :             :        end do
     571                 :             :     end do
     572                 :             :   end subroutine trans_ijR
     573                 :             : 
     574                 :             : 
     575                 :             : 
     576                 :             :   !-----------------------------------------------------------------------
     577                 :             :   !> @brief repeat a quantity (which is a scalar for each index)
     578                 :             :   !>  memory will be allocated if not already done
     579                 :             :   !> @param [in] a: the quantity to be repeated (loop over index i in primcell)
     580                 :             :   !> @param [out] ret: the repeat. also a 1D matrix. (loop over index in supercell)
     581                 :             :   !-----------------------------------------------------------------------
     582         [ -  + ]:           9 :   subroutine repeat_int1d(self, a, ret)
     583                 :             :     class(supercell_maker_t), intent(inout) :: self
     584                 :             :     integer, intent(in) :: a(:)
     585                 :             :     integer, allocatable :: ret(:)
     586                 :             :     integer :: n, i
     587                 :           9 :     n=size(a)
     588         [ +  + ]:           9 :     if (.not. allocated(ret)) then
     589   [ -  +  +  -  :          21 :        ABI_MALLOC(ret, (n*self%ncells))
          +  -  +  -  -  
             +  -  +  -  
                      + ]
     590                 :             :     end if
     591         [ +  + ]:        2393 :     do i =1, self%ncells
     592         [ +  + ]:       11561 :        ret((i-1)*n+1: i*n) = a(:)
     593                 :             :     end do
     594                 :           9 :   end subroutine repeat_int1d
     595                 :             : 
     596                 :             :   !-----------------------------------------------------------------------
     597                 :             :   !> @brief repeat a quantity (which is a scalar for each index)
     598                 :             :   !> memory will NOT be allocated.
     599                 :             :   !> @param [in] a: the quantity to be repeated (loop over index i in primcell)
     600                 :             :   !> @param [out] ret: the repeat. also a 1D matrix. (loop over index in supercell)
     601                 :             :   !-----------------------------------------------------------------------
     602   [ #  #  #  # ]:           0 :   subroutine repeat_int1d_noalloc(self, a, ret)
     603                 :             :     class(supercell_maker_t), intent(inout) :: self
     604                 :             :     integer, intent(in) :: a(:)
     605                 :             :     integer :: ret(:)
     606                 :             :     integer :: n, i
     607                 :           0 :     n=size(a)
     608         [ #  # ]:           0 :     do i =1, self%ncells
     609         [ #  # ]:           0 :        ret((i-1)*n+1: i*n) = a(:)
     610                 :             :     end do
     611                 :           0 :   end subroutine repeat_int1d_noalloc
     612                 :             : 
     613                 :             :   !-----------------------------------------------------------------------
     614                 :             :   !> @brief repeat a quantity (which is a 1D matrix for each index)
     615                 :             :   !>  memory will be allocated if not already done
     616                 :             :   !> @param [in] a: the quantity to be repeated (loop over index i in primcell)
     617                 :             :   !> @param [out] ret: the repeat. also a 1D matrix. (loop over index in supercell)
     618                 :             :   !-----------------------------------------------------------------------
     619         [ -  + ]:          13 :   subroutine repeat_real1d(self, a, ret)
     620                 :             :     class(supercell_maker_t), intent(inout) :: self
     621                 :             :     real(dp), intent(in) :: a(:)
     622                 :             :     real(dp), allocatable:: ret(:)
     623                 :             :     integer :: n, i
     624                 :          13 :     n=size(a)
     625         [ +  + ]:          13 :     if (.not. allocated(ret)) then
     626   [ -  +  +  -  :          21 :        ABI_MALLOC(ret, (n*self%ncells))
          +  -  +  -  -  
             +  -  +  -  
                      + ]
     627                 :             :     end if
     628         [ +  + ]:        3261 :     do i =1, self%ncells
     629         [ +  + ]:       13293 :        ret((i-1)*n+1: i*n) = a(:)
     630                 :             :     end do
     631                 :          13 :   end subroutine repeat_real1d
     632                 :             : 
     633                 :             :   !-----------------------------------------------------------------------
     634                 :             :   !> @brief repeat a quantity (which is a 1D matrix for each index)
     635                 :             :   !>  memory will be allocated if not already done
     636                 :             :   !> @param [in] a: the quantity to be repeated ( 2nd dim loop over index i in primcell)
     637                 :             :   !> @param [out] ret: the repeat. also a 2D matrix. (2nd dim loop over index in supercell)
     638                 :             :   !-----------------------------------------------------------------------
     639         [ #  # ]:           0 :   subroutine repeat_real2d(self, a, ret)
     640                 :             :     class(supercell_maker_t), intent(inout) :: self
     641                 :             :     real(dp), intent(in) :: a(:,:)
     642                 :             :     real(dp), allocatable:: ret(:, :)
     643                 :             :     integer :: n1, n2, i
     644                 :           0 :     n1=size(a, dim=1)
     645                 :           0 :     n2=size(a,dim=2)
     646         [ #  # ]:           0 :     if (.not. allocated(ret)) then
     647   [ #  #  #  #  :           0 :        ABI_MALLOC(ret, (n1, n2*self%ncells))
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
     648                 :             :     end if
     649         [ #  # ]:           0 :     do i =1, self%ncells
     650   [ #  #  #  # ]:           0 :        ret(:,(i-1)*n2+1: i*n2) = a(:,:)
     651                 :             :     end do
     652                 :           0 :   end subroutine repeat_real2d
     653                 :             : 
     654                 :             :   !-----------------------------------------------------------------------
     655                 :             :   !> @brief repeat a quantity (which is a 2D matrix for each index)
     656                 :             :   !>  memory will be allocated if not already done
     657                 :             :   !> @param [in] a: the quantity to be repeated ( 3rd dim loop over index i in primcell)
     658                 :             :   !> @param [out] ret: the repeat. also a 2D matrix. (3rd dim loop over index in supercell)
     659                 :             :   !-----------------------------------------------------------------------
     660         [ #  # ]:           0 :   subroutine repeat_realmat(self, a, ret)
     661                 :             :     class(supercell_maker_t), intent(inout) :: self
     662                 :             :     real(dp), intent(in) :: a(:,:,:)
     663                 :             :     real(dp), allocatable, intent(inout) :: ret(:,:,:)
     664                 :             :     integer :: n,  i
     665                 :           0 :     n=size(a, 3)
     666         [ #  # ]:           0 :     if (.not. allocated(ret)) then
     667   [ #  #  #  #  :           0 :        ABI_MALLOC(ret, (size(a, dim=1), size(a, dim=2), n*self%ncells))
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                #  #  # ]
     668                 :             :     end if
     669         [ #  # ]:           0 :     do i=1, self%ncells
     670   [ #  #  #  #  :           0 :        ret(:,:,(i-1)*n+1: i*n)=a(:, :, :)
                   #  # ]
     671                 :             :     end do
     672                 :           0 :   end subroutine repeat_realmat
     673                 :             : 
     674                 :             :   !-----------------------------------------------------------------------
     675                 :             :   !> @brief  a list of R vectors for all the indices in supercell
     676                 :             :   !> memory will be allocated if not already done.
     677                 :             :   !> @param [in] nbasis: number of indices in primitivecell
     678                 :             :   !> @param [ret]  A R vector for each index in supercell mat(3, nbasis*ncells)
     679                 :             :   !-----------------------------------------------------------------------
     680                 :           3 :   subroutine rvec_for_each(self, nbasis, ret)
     681                 :             :     class(supercell_maker_t), intent(inout) :: self
     682                 :             :     integer, intent(in) :: nbasis
     683                 :             :     integer, allocatable, intent(inout) :: ret(:,:)
     684                 :             :     integer :: icell, ibasis
     685         [ +  + ]:           3 :     if (.not. allocated(ret)) then
     686   [ -  +  +  -  :           3 :        ABI_MALLOC(ret, (3, nbasis*self%ncells))
          +  -  +  -  -  
             +  -  +  -  
                      + ]
     687                 :             :     end if
     688         [ +  + ]:         947 :     do icell=1, self%ncells
     689         [ +  + ]:        2403 :        do ibasis=1, nbasis
     690         [ +  + ]:        6768 :           ret(:, (icell-1)*nbasis+ibasis)= self%rvecs(:, icell)
     691                 :             :        end do
     692                 :             :     end do
     693                 :           3 :   end subroutine rvec_for_each
     694                 :             : 
     695                 :             :   !============================Unit test=====================================
     696                 :             : 
     697                 :           0 :   function test1() result(err)
     698                 :           0 :     type(supercell_maker_t) :: maker
     699                 :             :     integer :: err
     700                 :             :     integer :: scmat(3,3)
     701                 :           0 :     integer, allocatable :: ind_sc(:)
     702                 :             :     integer :: R(3), R_sc(3), ind_sc2
     703                 :           0 :     integer, allocatable ::  j_sc(:), R_sc3(:, :)
     704                 :           0 :     scmat=reshape([2,0, 0, 0,2, 0, 0,0,2], [3,3])
     705                 :           0 :     call maker%initialize(scmat)
     706                 :           0 :     err=0
     707                 :           0 :     call maker%trans_i(nbasis=3, i=1, i_sc=ind_sc)
     708                 :           0 :     R=[0,0,0]
     709                 :           0 :     call maker%R_to_sc(R, R_sc, ind_sc2)
     710   [ #  #  #  #  :           0 :     if (.not.( (all(R_sc==[0,0,0])) .and. (ind_sc2==1 )))  then
             #  #  #  # ]
     711                 :           0 :        ABI_ERROR("R_to_sc is wrong")
     712                 :             :     end if
     713                 :             : 
     714                 :           0 :     R=[0,0,3]
     715                 :           0 :     call maker%trans_j_and_Rj(nbasis=3, j=1, Rj=R, j_sc=j_sc, Rj_sc=R_sc3  )
     716   [ #  #  #  #  :           0 :     if (.not. (  all(j_sc(1:3)==[4,1,10]) &
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     717                 :             :          .and. all(R_sc3(:,1)==[0,0,1]) &
     718                 :             :          .and. all(R_sc3(:,3)==[0,0,1]) ) ) then
     719                 :           0 :        ABI_ERROR("Wrong trans_j_and_Rj")
     720                 :           0 :        err=1
     721                 :             :     end if
     722         [ #  # ]:           0 :     ABI_FREE(ind_sc)
     723         [ #  # ]:           0 :     ABI_FREE(j_sc)
     724         [ #  # ]:           0 :     ABI_FREE(R_sc3)
     725         [ #  # ]:           0 :   end function test1
     726                 :             : 
     727                 :           0 :   function test2() result(err)
     728                 :           0 :     type(supercell_maker_t) :: maker
     729                 :             :     integer :: err
     730                 :             :     integer :: scmat(3,3)
     731                 :             :     real(dp) :: sccell(3,3)
     732                 :           0 :     real(dp), allocatable :: scxred(:, :)
     733                 :           0 :     integer, allocatable :: rep1(:)
     734                 :           0 :     real(dp), allocatable :: rep2(:)
     735                 :           0 :     scmat=transpose(reshape([1,2, 3, 4,5,6,7,8,6], [3,3]))
     736                 :             :     !scmat=reshape([1,2, 3, 4,5,6,7,8,6], [3,3])
     737                 :           0 :     call maker%initialize(scmat)
     738                 :             : 
     739                 :           0 :     err=0
     740                 :             : 
     741                 :             :     ! test build_rvecs
     742   [ #  #  #  #  :           0 :     if (.not. all(maker%rvecs==reshape([0,  0,  0,  2,  3,  4,  3,  4,  4, &
             #  #  #  # ]
     743                 :             :          3,  4,  5,  4,  5,  5,  5,  6, 5, &
     744                 :             :          5,  6,  6,  6,  7, 6,  8, 10, 10], [3, 8]))) then
     745                 :           0 :        ABI_ERROR("Wrong Rvecs found !")
     746                 :           0 :        err=1
     747                 :             :     end if
     748                 :             : 
     749                 :             :     ! test sc_cell
     750                 :           0 :     sccell(:,:)=maker%sc_cell(transpose(reshape([1.d0,2.d0,3.d0,4.d0,5.d0,6.d0,3.d0,2.d0,3.d0], [3,3])))
     751   [ #  #  #  #  :           0 :     if (.not. all(abs(sccell-transpose(reshape([18,18, 24, 42, 45, 60, 57, 66, 87], [3,3])))<1e-4)) then
             #  #  #  # ]
     752                 :           0 :        ABI_ERROR("Wrong cell paramter found !")
     753                 :           0 :        err=1
     754                 :             :     end if
     755                 :             : 
     756                 :             : 
     757                 :             :     ! test trans_xred
     758                 :           0 :     call maker%trans_xred(reshape([0.1d0, 0.2d0, 0.3d0, 0.1d0, 0.4d0, 0.6d0], [3, 2]), scxred)
     759   [ #  #  #  #  :           0 :     if (.not. all(abs(scxred(:,18)-[1.0666666666666684,0.53333333333333277,0.70000000000000040])<1e-4)) then
                   #  # ]
     760                 :           0 :        ABI_ERROR("Wrong sc_xred !")
     761                 :           0 :        err=1
     762                 :             :     end if
     763                 :             : 
     764                 :             :     ! test repeat
     765                 :           0 :     call maker%repeat([1,2], rep1)
     766                 :             : 
     767                 :           0 :     call maker%repeat([1.0d0,2.0d0], rep2)
     768                 :             : 
     769   [ #  #  #  #  :           0 :   end function test2
             #  #  #  # ]
     770                 :             : 
     771                 :           0 :   subroutine scmaker_unittest()
     772         [ #  # ]:           0 :     if (test1()/=0) ABI_ERROR("Supercell maker: Test1 Failed")
     773         [ #  # ]:           0 :     if (test2()/=0) ABI_ERROR("Supercell maker: Test2 Failed")
     774                 :           0 :   end subroutine scmaker_unittest
     775                 :             : 
     776                 :             : 
     777                 :             : !===================================================================================
     778                 :             : ! The functions below are deprecated!!!
     779                 :             : ! ! They are used with the m_supercell module.
     780                 :             : !
     781                 :             : !   ! R (in term of primitive cell) to R_sc(in term of supercell) + R_prim
     782                 :             : !   subroutine find_R_PBC(scell, R, R_sc, R_prim)
     783                 :             : !     type(supercell_type) , intent(in):: scell
     784                 :             : !     integer, intent(in):: R(3)
     785                 :             : !     integer, intent(out):: R_sc(3), R_prim(3)
     786                 :             : !     real(dp) :: R_sc_d(3), sc_mat(3,3)
     787                 :             : 
     788                 :             : !     integer:: ipriv(3), info
     789                 :             : !     !call dgesv( n, nrhs, a, lda, ipiv, b, ldb, info )
     790                 :             : !     sc_mat(:,:)=scell%rlatt
     791                 :             : !     R_sc_d(:)=R(:)
     792                 :             : !     call dgesv(3, 1, sc_mat, 3, ipriv, R_sc_d, 3, info)
     793                 :             : !     if ( info/=0 ) then
     794                 :             : !        ABI_ERROR("Failed to find R_sc")
     795                 :             : !     end if
     796                 :             : 
     797                 :             : !     ! if only diagonal of rlatt works.
     798                 :             : !     !R_sc_d(1)= real(R(1))/real(scell%rlatt(1,1))
     799                 :             : !     !R_sc_d(2)= real(R(2))/real(scell%rlatt(2,2))
     800                 :             : !     !R_sc_d(3)= real(R(3))/real(scell%rlatt(3,3))
     801                 :             : !     ! TODO hexu: R_prim should be non-negative, which is assumed in m_supercell.
     802                 :             : !     ! But should we make it more general?
     803                 :             : !     R_sc(1)=floor(R_sc_d(1))
     804                 :             : !     R_sc(2)=floor(R_sc_d(2))
     805                 :             : !     R_sc(3)=floor(R_sc_d(3))
     806                 :             : !     R_prim(1)=(R(1)-R_sc(1)*scell%rlatt(1,1))
     807                 :             : !     R_prim(2)=(R(2)-R_sc(2)*scell%rlatt(2,2))
     808                 :             : !     R_prim(3)=(R(3)-R_sc(3)*scell%rlatt(3,3))
     809                 :             : !   end subroutine find_R_PBC
     810                 :             : 
     811                 :             : !   ! TODO hexu: move this to m_supercell?
     812                 :             : !   ! find the spercelll atom index from index of atom in primitive cell and R vector
     813                 :             : !   function find_supercell_index(scell, iatom_prim, rvec) result(iatom_supercell)
     814                 :             : !     type(supercell_type) , intent(in):: scell
     815                 :             : !     integer, intent(in) :: iatom_prim, rvec(3)
     816                 :             : !     integer  :: iatom_supercell
     817                 :             : !     integer :: i
     818                 :             : !     iatom_supercell=-1
     819                 :             : !     do i=1, scell%natom, 1
     820                 :             : !        if ( scell%atom_indexing(i) == iatom_prim .and. &
     821                 :             : !             all(scell%uc_indexing(:,i)==rvec) ) then
     822                 :             : !           iatom_supercell=i
     823                 :             : !           return
     824                 :             : !        end if
     825                 :             : !     end do
     826                 :             : !     ABI_ERROR("BUG found. supercell_maker%find_supercell_index cannot find iatom_prim, rvec pair in supercell")
     827                 :             : !   end function find_supercell_index
     828                 :             : 
     829                 :             : !   !i0, j0+R0 shifted by R to i1=i0+0+R->periodic, j1=j0+R0+R->periodic
     830                 :             : !   subroutine find_supercell_ijR(scell, i0, j0, R0, R, i1, j1, R1, R_sc)
     831                 :             : 
     832                 :             : !     type(supercell_type) , intent(in):: scell
     833                 :             : !     integer, intent(in) :: i0, j0, R0(3), R(3)
     834                 :             : !     integer, intent(out) :: i1, j1, R1(3), R_sc(3)
     835                 :             : !     i1=find_supercell_index(scell,i0,R)
     836                 :             : !     call find_R_PBC(scell,R0+R,R_sc,R1)
     837                 :             : !     j1=find_supercell_index(scell, j0, R1)
     838                 :             : !   end subroutine find_supercell_ijR
     839                 :             : 
     840                 :             : 
     841   [ #  #  #  #  :           0 :  end module m_supercell_maker
          #  #  #  #  #  
                #  #  # ]
        

Generated by: LCOV version 2.3-1