LCOV - code coverage report
Current view: top level - src/80_tdep - m_tdep_sym.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 87.5 % 319 279
Test Date: 2026-11-08 00:10:28 Functions: 88.9 % 9 8
Branches: 76.2 % 560 427

             Branch data     Line data    Source code
       1                 :             : !!****m* ABINIT/m_tdep_sym
       2                 :             : !! NAME
       3                 :             : !!  m_tdep_sym
       4                 :             : !!
       5                 :             : !! FUNCTION
       6                 :             : !!  This module contains the TDEP Symmetries data type, which holds the
       7                 :             : !!  symmetry operations of the crystal (in reduced and cartesian
       8                 :             : !!  coordinates), and the routines that find the symmetry operations
       9                 :             : !!  relating atoms, pairs, triplets and quadruplets of atoms of the supercell.
      10                 :             : !!
      11                 :             : !! COPYRIGHT
      12                 :             : !! Copyright (C) 2011-2026 ABINIT group (GA,FB,JB)
      13                 :             : !! This file is distributed under the terms of the
      14                 :             : !! GNU General Public License, see ~abinit/COPYING
      15                 :             : !! or http://www.gnu.org/copyleft/gpl.txt .
      16                 :             : !!
      17                 :             : !! SOURCE
      18                 :             : 
      19                 :             : #if defined HAVE_CONFIG_H
      20                 :             : #include "config.h"
      21                 :             : #endif
      22                 :             : 
      23                 :             : #include "abi_common.h"
      24                 :             : 
      25                 :             : module m_tdep_sym
      26                 :             : 
      27                 :             :  use defs_basis
      28                 :             :  use m_abicore
      29                 :             :  use m_errors
      30                 :             :  use m_xmpi
      31                 :             :  use m_matrix,           only : mati3inv
      32                 :             :  use m_symtk,            only : symatm
      33                 :             :  use m_crystal,          only : crystal_t
      34                 :             :  use m_tdep_dataset,     only : atdep_dataset_type, MPI_enreg_type
      35                 :             :  use m_tdep_latt,        only : Lattice_type, tdep_make_inbox
      36                 :             :  use m_tdep_supercell,   only : tdep_Supercell_type
      37                 :             : 
      38                 :             :  implicit none
      39                 :             : !!***
      40                 :             : 
      41                 :             : !----------------------------------------------------------------------
      42                 :             : 
      43                 :             : !!****t* m_tdep_sym/Symmetries_type
      44                 :             : !! NAME
      45                 :             : !! Symmetries_type
      46                 :             : !!
      47                 :             : !! FUNCTION
      48                 :             : !!  Holds the symmetry operations of the crystal, in reduced and cartesian
      49                 :             : !!  coordinates, and the action of each of them on the atoms of the supercell.
      50                 :             : !!
      51                 :             : !! SOURCE
      52                 :             : 
      53                 :             :  type,public :: Symmetries_type
      54                 :             : 
      55                 :             :    integer :: nsym
      56                 :             :    ! Number of symmetry operations of the crystal
      57                 :             : 
      58                 :             :    integer :: spgroup
      59                 :             :    ! Space group number
      60                 :             : 
      61                 :             :    integer, allocatable :: symrec(:,:,:)
      62                 :             :    ! symrec(3,3,nsym)
      63                 :             :    ! Symmetry operations in reciprocal space, in reduced coordinates
      64                 :             :    ! (inverse of the transpose of symrel)
      65                 :             : 
      66                 :             :    integer, allocatable :: symrel(:,:,:)
      67                 :             :    ! symrel(3,3,nsym)
      68                 :             :    ! Symmetry operations in real space, in reduced coordinates
      69                 :             : 
      70                 :             :    integer, allocatable :: symafm(:)
      71                 :             :    ! symafm(nsym)
      72                 :             :    ! Ferromagnetic (1) or antiferromagnetic (-1) character of each symmetry operation
      73                 :             : 
      74                 :             :    integer, allocatable :: indsym(:,:,:)
      75                 :             :    ! indsym(4,nsym,natom)
      76                 :             :    ! For the symmetry operation isym applied to the atom iatom of the supercell,
      77                 :             :    ! indsym(4,isym,iatom) gives the equivalent atom in the reference unitcell,
      78                 :             :    ! and indsym(1:3,isym,iatom) the corresponding lattice vector
      79                 :             :    ! (see tdep_SearchS_1at).
      80                 :             : 
      81                 :             :    double precision, allocatable :: S_ref(:,:,:,:)
      82                 :             :    ! S_ref(3,3,nsym,2)
      83                 :             :    ! Symmetry operations in cartesian coordinates (only S_ref(:,:,:,1) is used)
      84                 :             : 
      85                 :             :    double precision, allocatable :: S_inv(:,:,:,:)
      86                 :             :    ! S_inv(3,3,nsym,2)
      87                 :             :    ! Inverse (i.e. transpose) of S_ref (only S_inv(:,:,:,1) is used)
      88                 :             : 
      89                 :             :    double precision, allocatable :: tnons(:,:)
      90                 :             :    ! tnons(3,nsym)
      91                 :             :    ! Non-symmorphic translations, in reduced coordinates
      92                 :             : 
      93                 :             :    double precision, allocatable :: xred_zero(:,:)
      94                 :             :    ! xred_zero(3,natom_unitcell)
      95                 :             :    ! Copy of Invar%xred_unitcell (atoms anchored so atom 1 sits at the
      96                 :             :    ! origin (0,0,0), wrapped into [0,1); see tdep_read_input). This
      97                 :             :    ! anchor-on-atom-1 convention is not local to symmetry-finding: it is
      98                 :             :    ! also the convention used for the reference unitcell throughout the
      99                 :             :    ! rest of atdep (Crystal and Supercell objects are built from this same
     100                 :             :    ! array, see tdep_init_crystal).
     101                 :             : 
     102                 :             :  contains
     103                 :             : 
     104                 :             :    procedure :: init => tdep_make_sym
     105                 :             :    procedure :: free => tdep_destroy_sym
     106                 :             : 
     107                 :             :  end type Symmetries_type
     108                 :             : !!***
     109                 :             : 
     110                 :             :  public :: tdep_SearchS_1at
     111                 :             :  public :: tdep_SearchS_2at
     112                 :             :  public :: tdep_SearchS_3at
     113                 :             :  public :: tdep_SearchS_4at
     114                 :             :  public :: tdep_destroy_sym
     115                 :             :  public :: tdep_calc_indsym2
     116                 :             : 
     117                 :             : contains
     118                 :             : 
     119                 :             : !=====================================================================================================
     120                 :             : 
     121                 :             : !!****f* m_tdep_sym/tdep_make_sym
     122                 :             : !! NAME
     123                 :             : !!  tdep_make_sym
     124                 :             : !!
     125                 :             : !! FUNCTION
     126                 :             : !!  Initialize the Symmetries object: copy the symmetry operations of the
     127                 :             : !!  crystal and the space group from the Crystal object, check that the Bravais
     128                 :             : !!  lattice of its primitive vectors is the one used to build the Lattice object,
     129                 :             : !!  and compute the corresponding operations in reciprocal space (symrec). Finally, transform
     130                 :             : !!  the symmetry operations into cartesian coordinates (S_ref), compute their
     131                 :             : !!  inverse (S_inv), check that they are orthogonal, and write them in the
     132                 :             : !!  _sym.dat file.
     133                 :             : !!
     134                 :             : !! INPUTS
     135                 :             : !!  Invar = Input object containing the input variables.
     136                 :             : !!  MPIdata = Info on MPI parallelism.
     137                 :             : !!  Crystal = Crystal object describing the unitcell (see tdep_init_crystal).
     138                 :             : !!  Lattice = Lattice object describing the ideal structure.
     139                 :             : !!  bravais_lattice(11) = Bravais lattice of the primitive vectors of Crystal
     140                 :             : !!                        (see Crystal%find_bravais).
     141                 :             : !!
     142                 :             : !! OUTPUT
     143                 :             : !!  Sym = Symmetries object, initialized (except Sym%indsym, which is
     144                 :             : !!        computed in tdep_SearchS_1at).
     145                 :             : !!
     146                 :             : !! SOURCE
     147                 :             : 
     148                 :          46 :  subroutine tdep_make_sym(Sym,Invar,MPIdata,Crystal,Lattice,bravais_lattice)
     149                 :             : 
     150                 :             :   class(Symmetries_type),intent(out) :: Sym
     151                 :             :   type(atdep_dataset_type),intent(in) :: Invar
     152                 :             :   type(MPI_enreg_type), intent(in) :: MPIdata
     153                 :             :   type(crystal_t),intent(in) :: Crystal
     154                 :             :   type(Lattice_type),intent(in) :: Lattice
     155                 :             :   integer,intent(in) :: bravais_lattice(11)
     156                 :             : 
     157                 :             :   integer :: isym,ii,jj
     158         [ +  - ]:          46 :   double precision, allocatable :: tmp1(:,:)
     159                 :             :   character(len=500) :: msg
     160                 :             : 
     161                 :          46 :   write(ab_out,'(a,1x,11(i4,1x))')' bravais=',bravais_lattice(:)
     162   [ +  +  +  -  :         138 :   if (any(bravais_lattice(1:2) /= Lattice%bravais(1:2))) then
                   -  + ]
     163                 :           0 :     write(msg,'(a,2i4,2a,2i4,3a)') 'The Bravais lattice of the ideal unitcell (',bravais_lattice(1:2),')',ch10,&
     164                 :           0 :      'differs from the one of the unitcell given in input (',Lattice%bravais(1:2),').',ch10,&
     165                 :           0 :      'ACTION: give the primitive vectors (rprimd) with more digits.'
     166                 :           0 :     ABI_ERROR(msg)
     167                 :             :   end if
     168                 :             : 
     169                 :             : ! The symmetry operations of the crystal (see tdep_init_crystal).
     170                 :          46 :   Sym%nsym=Crystal%nsym
     171                 :          46 :   Sym%spgroup=Crystal%space_group
     172   [ -  +  +  -  :       22160 :   ABI_MALLOC(Sym%symrel,(3,3,Sym%nsym)) ; Sym%symrel(:,:,:)=Crystal%symrel(:,:,:)
          +  -  +  -  -  
          +  -  +  -  +  
          +  +  +  +  +  
                      + ]
     173   [ -  +  +  -  :        6914 :   ABI_MALLOC(Sym%tnons   ,(3,Sym%nsym)) ; Sym%tnons   (:,:)=Crystal%tnons(:,:)
          +  -  +  -  -  
          +  -  +  -  +  
             +  +  +  + ]
     174   [ -  +  +  -  :        1832 :   ABI_MALLOC(Sym%symafm    ,(Sym%nsym)) ; Sym%symafm    (:)=Crystal%symafm(:)
          +  -  +  -  -  
          +  -  +  -  +  
                   +  + ]
     175                 :             : 
     176                 :             : ! Crystal%xred is Invar%xred_unitcell, anchored on atom 1 (see tdep_init_crystal).
     177   [ -  +  +  -  :         138 :   ABI_MALLOC(Sym%xred_zero,(3,Invar%natom_unitcell))
          +  -  +  -  -  
             +  -  +  -  
                      + ]
     178   [ +  +  +  + ]:         486 :   Sym%xred_zero(:,:) = Crystal%xred(:,:)
     179                 :             : 
     180                 :             : ! Calculation of symrec
     181   [ -  +  +  -  :       22160 :   ABI_MALLOC(Sym%symrec,(3,3,Sym%nsym)); Sym%symrec(:,:,:)=0
          +  -  +  -  -  
          +  -  +  -  +  
          +  +  +  +  +  
                      + ]
     182         [ +  + ]:        1740 :   do isym=1,Sym%nsym
     183                 :        1740 :     call mati3inv(Sym%symrel(:,:,isym),Sym%symrec(:,:,isym))
     184                 :             :   end do
     185                 :             : 
     186                 :          46 :   write(ab_out,'(a)') ' Writing symmetries in file sym.dat'
     187                 :             : 
     188                 :             : ! Transform S_ref in cartesian coordinates
     189   [ -  +  +  -  :       22206 :   ABI_MALLOC(Sym%S_ref,(3,3,Sym%nsym,2)) ; Sym%S_ref(:,:,:,1)=real(Sym%symrel(:,:,1:Sym%nsym))
          +  -  +  -  +  
          -  -  +  -  +  
          -  +  +  +  +  
                +  +  + ]
     190   [ -  +  +  -  :       22114 :   ABI_MALLOC(Sym%S_inv,(3,3,Sym%nsym,2)) ; Sym%S_inv(:,:,:,1)=zero
          -  +  -  +  -  
          +  +  +  +  +  
                   +  + ]
     191   [ -  +  +  +  :         598 :   ABI_MALLOC(tmp1,(3,3)); tmp1(:,:)=0.d0
                   +  + ]
     192         [ +  - ]:          46 :   if (MPIdata%iam_master) open(unit=75,file=trim(Invar%output_prefix)//'_sym.dat')
     193         [ +  + ]:        1740 :   do isym=1,Sym%nsym
     194         [ +  - ]:        1694 :     if (MPIdata%iam_master) then
     195                 :        1694 :       write(75,*) ' '
     196                 :        1694 :       write(75,*) 'For isym=',isym
     197                 :        1694 :       write(75,*) 'In reduced coordinates:'
     198                 :        1694 :       write(75,'(3(f5.2,1x))') Sym%S_ref(1,1,isym,1),Sym%S_ref(1,2,isym,1),Sym%S_ref(1,3,isym,1)
     199                 :        1694 :       write(75,'(3(f5.2,1x))') Sym%S_ref(2,1,isym,1),Sym%S_ref(2,2,isym,1),Sym%S_ref(2,3,isym,1)
     200                 :        1694 :       write(75,'(3(f5.2,1x))') Sym%S_ref(3,1,isym,1),Sym%S_ref(3,2,isym,1),Sym%S_ref(3,3,isym,1)
     201                 :             :     end if
     202                 :        1694 :     call DGEMM('N','N',3,3,3,1.d0,Lattice%rprimdt,3,Sym%S_ref(:,:,isym,1),3,0.d0,tmp1,3)
     203                 :        1694 :     call DGEMM('N','N',3,3,3,1.d0,tmp1,3,Lattice%rprimdtm1,3,0.d0,Sym%S_ref(:,:,isym,1),3)
     204         [ +  + ]:        6776 :     do ii=1,3
     205         [ +  + ]:       22022 :       do jj=1,3
     206         [ +  + ]:       20328 :         if (abs(Sym%S_ref(ii,jj,isym,1)).lt.tol8) Sym%S_ref(ii,jj,isym,1)=zero
     207                 :             :       end do
     208                 :             :     end do
     209                 :             : !   Inversion of S_ref (which is equivalent to the transposition)
     210         [ +  + ]:        6776 :     do ii=1,3
     211         [ +  + ]:       22022 :       do jj=1,3
     212                 :       20328 :         Sym%S_inv(ii,jj,isym,1)=Sym%S_ref(jj,ii,isym,1)
     213                 :             :       end do
     214                 :             :     end do
     215         [ +  - ]:        1740 :     if (MPIdata%iam_master) then
     216                 :        1694 :       write(75,*) 'In cartesian coordinates:'
     217                 :        1694 :       write(75,'(3(f5.2,1x))') Sym%S_ref(1,1,isym,1),Sym%S_ref(1,2,isym,1),Sym%S_ref(1,3,isym,1)
     218                 :        1694 :       write(75,'(3(f5.2,1x))') Sym%S_ref(2,1,isym,1),Sym%S_ref(2,2,isym,1),Sym%S_ref(2,3,isym,1)
     219                 :        1694 :       write(75,'(3(f5.2,1x))') Sym%S_ref(3,1,isym,1),Sym%S_ref(3,2,isym,1),Sym%S_ref(3,3,isym,1)
     220                 :             :     end if
     221                 :             :   end do
     222         [ +  - ]:          46 :   if (MPIdata%iam_master) close(75)
     223                 :             : 
     224                 :             : ! We verify that S.S^T = Id
     225   [ +  +  +  + ]:         598 :   tmp1(:,:)=zero
     226         [ +  + ]:        1740 :   do isym=1,Sym%nsym
     227                 :        1694 :     call DGEMM('T','N',3,3,3,1.d0,Sym%S_ref(:,:,isym,1),3,Sym%S_ref(:,:,isym,1),3,0.d0,tmp1,3)
     228         [ +  + ]:        6822 :     do ii=1,3
     229         [ +  + ]:       22022 :       do jj=1,3
     230   [ +  +  +  -  :       20328 :         if ((ii/=jj.and.abs(tmp1(ii,jj)).gt.tol8).or.(ii==jj.and.abs(tmp1(ii,jj)-1.d0).gt.tol8)) then
             +  +  -  + ]
     231                 :           0 :           write(ab_out,'(a)') ' STOP : the matrix is not orthogonal : '
     232                 :           0 :           write(ab_out,'(a,1x,i3,1x,i3,1x,f15.10)') ' ii, jj, sym(ii,jj)=',ii,jj,tmp1(ii,jj)
     233                 :           0 :           ABI_ERROR('The matrix is not orthogonal')
     234                 :             :         end if
     235                 :             :       end do
     236                 :             :     end do
     237                 :             :   end do
     238                 :             : 
     239         [ -  + ]:          46 :   ABI_FREE(tmp1)
     240                 :             : 
     241                 :          46 :  end subroutine tdep_make_sym
     242                 :             : !!***
     243                 :             : 
     244                 :             : !=====================================================================================================
     245                 :             : 
     246                 :             : !!****f* m_tdep_sym/tdep_SearchS_1at
     247                 :             : !! NAME
     248                 :             : !!  tdep_SearchS_1at
     249                 :             : !!
     250                 :             : !! FUNCTION
     251                 :             : !!  Find, for every atom of the supercell SC and every symmetry operation,
     252                 :             : !!  the equivalent atom of the reference unitcell and the lattice vector
     253                 :             : !!  connecting them, and store the result in Sym%indsym.
     254                 :             : !!
     255                 :             : !!  Concretely, this routine, in order:
     256                 :             : !!   1) Calls symatm to compute indsym for the natom_unitcell atoms of the
     257                 :             : !!      reference unitcell only (Sym%indsym(:,:,1:SC%natom_unitcell)), from
     258                 :             : !!      the symmetry operations (Sym%symrec/tnons) and the "zeroed"
     259                 :             : !!      unitcell positions Sym%xred_zero (computed once in tdep_make_sym).
     260                 :             : !!   2) Extends indsym to every atom of the supercell: the unitcell atom
     261                 :             : !!      equivalent to a supercell atom iatom is trivially
     262                 :             : !!      mod(iatom-1,natom_unitcell)+1 (SC's natural ordering repeats the
     263                 :             : !!      unitcell motif atom-by-atom, cell-by-cell), and the lattice vector
     264                 :             : !!      connecting the two is recovered by comparing the ideal position of
     265                 :             : !!      iatom against that of its unitcell-equivalent site (the "motif"),
     266                 :             : !!      both expressed in unitcell-reduced coordinates.
     267                 :             : !!   3) For every pair of atoms (iatom,jatom) and every symmetry operation,
     268                 :             : !!      combines the above into indsym2, an 8-component vector describing
     269                 :             : !!      how the operation maps both atoms at once (the first four
     270                 :             : !!      components as in indsym for iatom, the last four for jatom).
     271                 :             : !!      This quantity is only used, in this routine, for the optional debug
     272                 :             : !!      output controlled by the internal debug parameter: it is not
     273                 :             : !!      returned nor stored in Sym. Elsewhere in the code, the equivalent per-pair, per-symmetry
     274                 :             : !!      quantity is instead computed on the fly by tdep_calc_indsym2.
     275                 :             : !!
     276                 :             : !! INPUTS
     277                 :             : !!  Invar = Input object containing the input variables.
     278                 :             : !!  MPIdata = Info on MPI parallelism.
     279                 :             : !!  SC = Supercell object describing the ideal structure. Its atoms provide
     280                 :             : !!       the reference ordering used throughout the rest of the code, so
     281                 :             : !!       this routine must be called after tdep_match_supercell.
     282                 :             : !!
     283                 :             : !! OUTPUT
     284                 :             : !!
     285                 :             : !! SIDE EFFECTS
     286                 :             : !!  Sym = Symmetries object. Sym%indsym(4,nsym,natom) is allocated and
     287                 :             : !!        filled: for symmetry operation isym applied to atom iatom,
     288                 :             : !!        indsym(4,isym,iatom) gives the equivalent atom iat_sym in the
     289                 :             : !!        reference unitcell, and indsym(1:3,isym,iatom) gives the lattice
     290                 :             : !!        vector R_0 such that
     291                 :             : !!          R^{-1} (xred(:,iatom)-tau) = xred(:,iat_sym) + R_0 .
     292                 :             : !!
     293                 :             : !! SOURCE
     294                 :             : 
     295                 :          46 :  subroutine tdep_SearchS_1at(Invar,MPIdata,Sym,SC)
     296                 :             : 
     297                 :             :   type(atdep_dataset_type), intent(in) :: Invar
     298                 :             :   type(Symmetries_type), intent(inout) :: Sym
     299                 :             :   type(MPI_enreg_type), intent(in) :: MPIdata
     300                 :             :   type(tdep_Supercell_type), intent(in) :: SC
     301                 :             : 
     302                 :             :   logical :: debug
     303                 :             :   integer :: isym,jatom,mu
     304                 :             :   integer :: iatom_unitcell,jatom_unitcell,iatom
     305                 :          92 :   integer :: vecti(3),vectj(3),vectsym(4,Sym%nsym)
     306                 :          46 :   integer, allocatable :: indsym2(:,:,:,:)
     307                 :             :   double precision :: temp3(3)
     308                 :             :   double precision :: xred_unit_i(3),xred_unit_j(3)
     309                 :          92 :   double precision :: xred_unit_motif(3,SC%natom_unitcell)
     310                 :             :   double precision :: origin(3)
     311                 :          46 :   double precision, allocatable :: xred_ideal(:,:)
     312                 :             : 
     313                 :          46 :   debug = (Invar%prtvol > 1)
     314                 :             : 
     315                 :          46 :   write(ab_out,*) ' '
     316                 :          46 :   write(ab_out,*) '#############################################################################'
     317                 :          46 :   write(ab_out,*) '################ Find symmetry operations in the supercell ##################'
     318                 :          46 :   write(ab_out,*) '#############################################################################'
     319                 :             : 
     320                 :             : !  write(ab_out,'(a)') 'Begining SearchS'
     321                 :             : ! TODO: Initialize the local variables at 0
     322                 :             : 
     323                 :             : ! Positions are anchored on atom 1 (as Sym%xred_zero is, see tdep_make_sym)
     324                 :             : ! before wrapping, since wrapping does not commute with a shift of origin.
     325                 :          46 :   origin = SC%get_xred_scaled(1)
     326                 :             : 
     327                 :             : ! Cache the wrapped ideal position of every atom: it is used
     328                 :             : ! repeatedly below, in a loop over all pairs of atoms.
     329   [ -  +  +  -  :         138 :   ABI_MALLOC(xred_ideal,(3,SC%natom))
          +  -  +  -  -  
                +  -  + ]
     330         [ +  + ]:        7324 :   do iatom=1,SC%natom
     331         [ +  + ]:       29158 :     xred_ideal(:,iatom) = SC%wrap_inbox(SC%get_xred_scaled(iatom) - origin)
     332                 :             :   end do
     333                 :             : 
     334                 :             : ! Compute the indsym fundamental quantity
     335                 :             : ! === Obtain a list of rotated atoms ===
     336                 :             : ! $ R^{-1} (xred(:,iat)-\tau) = xred(:,iat_sym) + R_0 $
     337                 :             : ! * indsym(4,  isym,iat) gives iat_sym in the original unit cell.
     338                 :             : ! * indsym(1:3,isym,iat) gives the lattice vector $R_0$.
     339                 :          46 :   write(ab_out,'(a)') ' Search the matrix transformation going from (k) to (i)...'
     340   [ -  +  +  -  :     1281382 :   ABI_MALLOC(Sym%indsym,(4,Sym%nsym,SC%natom)); Sym%indsym(:,:,:)=zero
          -  +  +  -  +  
          -  +  -  -  +  
          -  +  -  +  +  
             +  +  +  +  
                      + ]
     341                 :             :   call symatm(Sym%indsym(:,:,1:SC%natom_unitcell),SC%natom_unitcell,Sym%nsym,&
     342                 :          46 : &   Sym%symrec,Sym%tnons,tol8,SC%typat_unitcell,Sym%xred_zero)
     343                 :             : 
     344                 :             : ! Store the positions of the atoms in the motif, in unitcell-reduced coordinates
     345         [ +  + ]:         156 :   do iatom=1,SC%natom_unitcell
     346                 :         156 :     xred_unit_motif(:,iatom) = SC%scaled_to_unit(xred_ideal(:,iatom))
     347                 :             :   end do
     348                 :             : ! Write the Indsym of the atoms included in the (reference) unitcell (i.e.: the motif)
     349   [ -  +  -  - ]:          46 :   if (debug.and.MPIdata%iam_master) then
     350                 :           0 :     write(ab_out,'(a)') ' Writing file Indsym-unitcell.dat'
     351                 :           0 :     open(unit=40,file=trim(Invar%output_prefix)//'_Indsym-unitcell.dat')
     352         [ #  # ]:           0 :     do iatom=1,SC%natom_unitcell
     353                 :           0 :       write(40,*) '=========================================='
     354                 :           0 :       write(40,'(a,i4,a,3(f10.5,1x))') 'For iatom=',iatom,' with xred (supercell)=',xred_ideal(:,iatom)
     355         [ #  # ]:           0 :       do isym=1,Sym%nsym
     356                 :           0 :         write(40,'(a,i2,a,i4,a,3(i4,1x),a,i2,a,3(f10.5,1x))') '  indsym(isym=',isym,',',iatom,')=',&
     357                 :           0 : &         Sym%indsym(1:3,isym,iatom),'|iat=',Sym%indsym(4,isym,iatom),'| with tnons=',Sym%tnons(:,isym)
     358                 :             :       end do
     359                 :             :     end do
     360                 :           0 :     close(40)
     361                 :             :   end if
     362                 :             : 
     363                 :             : ! Search the matrix transformation going from (k,l) to (i,j)
     364                 :          46 :   write(ab_out,'(a)') ' Search the matrix transformation going from (k,l) to (i,j)...'
     365   [ -  +  +  -  :   431985816 :   ABI_MALLOC(indsym2,(8,Sym%nsym,SC%natom,SC%natom)); indsym2(:,:,:,:)=0
          -  +  +  -  -  
          +  +  -  +  -  
          +  -  -  +  -  
          +  +  +  +  +  
             +  +  +  + ]
     366         [ +  + ]:        7324 :   do iatom=1,SC%natom
     367                 :             : !   For a single iatom
     368                 :        7278 :     xred_unit_i = SC%scaled_to_unit(xred_ideal(:,iatom))
     369                 :             : 
     370                 :             :     ! GA: TODO  This operation could be refactored using SC's logic,
     371                 :             :     !           simply storing icell.
     372                 :             :     !           and work with integers for arrays like.
     373                 :        7278 :     iatom_unitcell=mod(iatom-1,SC%natom_unitcell)+1
     374         [ +  + ]:       29112 :     vecti(:)=nint(xred_unit_i(:)-xred_unit_motif(:,iatom_unitcell))
     375         [ +  + ]:      262108 :     do isym=1,Sym%nsym
     376   [ +  +  +  + ]:    72617024 :       vectsym(:,:)=0
     377         [ +  + ]:     1019136 :       do mu=1,3 ! Apply inverse transformation to original coordinates. Note transpose of symrec.
     378                 :     1019136 :         vectsym(mu,isym) = Sym%symrec(1,mu,isym)*vecti(1)+Sym%symrec(2,mu,isym)*vecti(2)+Sym%symrec(3,mu,isym)*vecti(3)
     379                 :             :       end do
     380         [ +  + ]:     1273920 :       Sym%indsym(1:4,isym,iatom)=Sym%indsym(1:4,isym,iatom_unitcell)+vectsym(1:4,isym)
     381         [ +  + ]:    48087278 :       do jatom=1,SC%natom
     382         [ +  + ]:   239380864 :         indsym2(1:4,isym,iatom,jatom)=Sym%indsym(1:4,isym,iatom_unitcell)+vectsym(1:4,isym)
     383                 :             :       end do
     384                 :             :     end do
     385                 :             :   end do
     386   [ -  +  -  - ]:          46 :   if (debug.and.MPIdata%iam_master) then
     387                 :           0 :     write(ab_out,'(a)') ' Writing file Indsym-supercell.dat'
     388                 :           0 :     open(unit=40,file=trim(Invar%output_prefix)//'_Indsym-supercell.dat')
     389         [ #  # ]:           0 :     do iatom=1,SC%natom
     390                 :           0 :       write(40,*) '=========================================='
     391                 :           0 :       write(40,'(a,i4,a,3(f10.5,1x))') 'For iatom=',iatom,' with xred (supercell)=',xred_ideal(:,iatom)
     392         [ #  # ]:           0 :       do isym=1,Sym%nsym
     393                 :           0 :         write(40,'(a,i2,a,i4,a,3(i4,1x),a,i2,a,3(f10.5,1x))') '  indsym(isym=',isym,',',iatom,')=',&
     394                 :           0 : &         Sym%indsym(1:3,isym,iatom),'|iat=',Sym%indsym(4,isym,iatom),'| with tnons=',Sym%tnons(:,isym)
     395                 :             :       end do
     396                 :           0 :       write(40,'(a,i4)') ' '
     397                 :             :     end do
     398                 :           0 :     close(40)
     399                 :             :   end if
     400                 :             : 
     401                 :             : ! For a couple of (iatom,jatom). The (iatom,jatom) vector depends on the position of iatom (due to PBC)
     402         [ +  + ]:        7324 :   do iatom=1,SC%natom
     403         [ +  + ]:     1558688 :     do jatom=1,SC%natom
     404         [ +  + ]:     6205456 :       temp3(:)=xred_ideal(:,jatom)-xred_ideal(:,iatom)
     405                 :     1551364 :       call tdep_make_inbox(temp3,1,1d-3,temp3)
     406         [ +  + ]:     6205456 :       temp3(:)=xred_ideal(:,iatom)+temp3(:)
     407                 :     1551364 :       xred_unit_j = SC%scaled_to_unit(temp3)
     408                 :     1551364 :       jatom_unitcell=mod(jatom-1,SC%natom_unitcell)+1
     409         [ +  + ]:     6205456 :       vectj(:)=nint(xred_unit_j(:)-xred_unit_motif(:,jatom_unitcell))
     410         [ +  + ]:    49383858 :       do isym=1,Sym%nsym
     411   [ +  +  +  + ]: 11929973056 :         vectsym(:,:)=0
     412         [ +  + ]:   191300864 :         do mu=1,3 ! Apply inverse transformation to original coordinates. Note transpose of symrec.
     413                 :   191300864 :           vectsym(mu,isym) = Sym%symrec(1,mu,isym)*vectj(1)+Sym%symrec(2,mu,isym)*vectj(2)+Sym%symrec(3,mu,isym)*vectj(3)
     414                 :             :         end do
     415         [ +  + ]:   240677444 :         indsym2(5:8,isym,iatom,jatom)=Sym%indsym(1:4,isym,jatom_unitcell)+vectsym(1:4,isym)
     416                 :             :       end do
     417                 :             :     end do
     418                 :             :   end do
     419   [ -  +  -  - ]:          46 :   if (debug.and.MPIdata%iam_master) then
     420                 :           0 :     write(ab_out,'(a)') ' Writing file Indsym-2atoms.dat'
     421                 :           0 :     open(unit=40,file=trim(Invar%output_prefix)//'_Indsym-2atoms.dat')
     422         [ #  # ]:           0 :     do iatom=1,SC%natom
     423                 :           0 :       write(40,*) '=========================================='
     424                 :           0 :       write(40,'(a,i4,a,3(f10.5,1x))') 'For iatom=',iatom,' with xred (supercell)=',xred_ideal(:,iatom)
     425         [ #  # ]:           0 :       do jatom=1,SC%natom
     426                 :           0 :         write(40,*) '  =========================================='
     427                 :           0 :         write(40,'(a,i4,a,3(f10.5,1x))') '  For jatom=',jatom,' with xred (supercell)=',xred_ideal(:,jatom)
     428         [ #  # ]:           0 :         do isym=1,Sym%nsym
     429                 :           0 :           write(40,'(a,i2,a,i4,a,i4,a,3(i4,1x),a,i2,a,3(i4,1x),a,i2,a)') '  indsym2(isym=',isym,',',iatom,',',jatom,')=',&
     430                 :           0 : &           indsym2(1:3,isym,iatom,jatom),&
     431                 :           0 : &           '|iat=',indsym2(4,isym,iatom,jatom),'|',indsym2(5:7,isym,iatom,jatom),'|iat=',indsym2(8,isym,iatom,jatom),'|'
     432                 :             :         end do
     433                 :             :       end do
     434                 :           0 :       write(40,'(a,i4)') ' '
     435                 :             :     end do
     436                 :           0 :     close(40)
     437                 :             :   end if
     438         [ -  + ]:          46 :   ABI_FREE(indsym2)
     439         [ -  + ]:          46 :   ABI_FREE(xred_ideal)
     440                 :             : 
     441                 :          46 :  end subroutine tdep_SearchS_1at
     442                 :             : !!***
     443                 :             : 
     444                 :             : !=====================================================================================================
     445                 :             : 
     446                 :             : !!****f* m_tdep_sym/tdep_SearchS_2at
     447                 :             : !! NAME
     448                 :             : !!  tdep_SearchS_2at
     449                 :             : !!
     450                 :             : !! FUNCTION
     451                 :             : !!  Search the symmetry operation that transforms the pair of atoms (e,f)
     452                 :             : !!  into the reference pair of atoms (i,j), i.e. such that e and f are
     453                 :             : !!  respectively equivalent to i and j, and that the lattice vectors
     454                 :             : !!  connecting them are consistent (same bond, modulo a lattice translation).
     455                 :             : !!  The first symmetry operation found is retained.
     456                 :             : !!  Only the direct transformation is searched here: the reversed bond
     457                 :             : !!  (j,i) is handled by the caller (see tdep_init_shell2at).
     458                 :             : !!
     459                 :             : !! INPUTS
     460                 :             : !!  SC = Supercell object describing the ideal structure.
     461                 :             : !!  iatom, jatom = Atoms of the reference pair (iatom in the unitcell).
     462                 :             : !!  eatom, fatom = Atoms of the pair to be transformed.
     463                 :             : !!  Sym = Symmetries object describing all the symmetry operations of the crystal.
     464                 :             : !!
     465                 :             : !! OUTPUT
     466                 :             : !!
     467                 :             : !! SIDE EFFECTS
     468                 :             : !!  Isym2at(natom,natom,2) = If a symmetry operation isym is found,
     469                 :             : !!                           Isym2at(eatom,fatom,1)=isym and
     470                 :             : !!                           Isym2at(eatom,fatom,2)=1 (direct transformation).
     471                 :             : !!                           Unchanged otherwise.
     472                 :             : !!
     473                 :             : !! SOURCE
     474                 :             : 
     475                 :      330346 :  subroutine tdep_SearchS_2at(SC,iatom,jatom,eatom,fatom,Isym2at,Sym)
     476                 :             : 
     477                 :             :   integer, intent(in) :: iatom,jatom,eatom,fatom
     478                 :             :   type(tdep_Supercell_type),intent(in) :: SC
     479                 :             :   type(Symmetries_type),intent(in) :: Sym
     480                 :             :   integer, intent(inout) :: Isym2at(SC%natom,SC%natom,2)
     481                 :             : 
     482                 :             :   integer :: isym,ee,ff,ii
     483                 :             :   integer :: iatom_unitcell,jatom_unitcell
     484                 :             :   integer :: vecti(3),vectj(3),latte(3),lattf(3),indsym2(8)
     485                 :             :   double precision :: xred_i(3),xred_j(3),temp(3)
     486                 :             :   double precision :: xred_unit_i(3),xred_unit_j(3)
     487                 :      660692 :   double precision :: xred_unit_motif(3,SC%natom_unitcell)
     488                 :             :   double precision :: origin(3)
     489                 :             :   logical :: ok
     490                 :             : 
     491                 :             : ! Search the couple of atoms (e,f) obtained through the transformation (R+t)
     492                 :             : ! starting from (i,j)
     493                 :             : ! In that case, note that two cases are possible:
     494                 :             : ! - The bond is just transformed, so indsym(4,e)=i and indsym(4,f)=j
     495                 :             : ! - The bond is transformed and reversed, so indsym(4,e)=j and indsym(4,f)=i
     496                 :             : 
     497                 :             : ! Positions are anchored on atom 1 (as Sym%xred_zero is, see tdep_make_sym)
     498                 :             : ! before wrapping, since wrapping does not commute with a shift of origin.
     499                 :      330346 :   origin = SC%get_xred_scaled(1)
     500                 :             : 
     501                 :             : ! Store the positions of the atoms in the motif, in unitcell-reduced coordinates
     502         [ +  + ]:     1002474 :   do ii=1,SC%natom_unitcell
     503         [ +  + ]:     3018858 :     xred_unit_motif(:,ii) = SC%scaled_to_unit(SC%wrap_inbox(SC%get_xred_scaled(ii) - origin))
     504                 :             :   end do
     505                 :             : 
     506                 :             : ! Search the atom equivalent to iatom in the (reference) unitcell
     507                 :             : ! Note that in the (present) particular case : iatom_unitcell=iatom and vecti(:)=zero
     508         [ +  + ]:     1321384 :   xred_i = SC%wrap_inbox(SC%get_xred_scaled(iatom) - origin)
     509                 :      330346 :   xred_unit_i = SC%scaled_to_unit(xred_i)
     510                 :      330346 :   iatom_unitcell=mod(iatom-1,SC%natom_unitcell)+1
     511         [ +  + ]:     1321384 :   vecti(:)=nint(xred_unit_i(:)-xred_unit_motif(:,iatom_unitcell))
     512                 :             : 
     513                 :             : ! Search the atom equivalent to jatom in the (reference) unitcell.
     514                 :             : ! jatom can be outside the box (according to the value of iatom)
     515                 :             : ! so we use the inbox procedure to put the distance within [-0.5,0.5[
     516         [ +  + ]:     1321384 :   xred_j = SC%wrap_inbox(SC%get_xred_scaled(jatom) - origin)
     517         [ +  + ]:     1321384 :   temp(:)=xred_j(:)-xred_i(:)
     518                 :      330346 :   call tdep_make_inbox(temp,1,1d-3,temp)
     519         [ +  + ]:     1321384 :   temp(:)=xred_i(:)+temp(:)
     520                 :      330346 :   xred_unit_j = SC%scaled_to_unit(temp)
     521                 :      330346 :   jatom_unitcell=mod(jatom-1,SC%natom_unitcell)+1
     522         [ +  + ]:     1321384 :   vectj(:)=nint(xred_unit_j(:)-xred_unit_motif(:,jatom_unitcell))
     523                 :             : 
     524                 :             : ! To understand the meaning of "latt", see SearchS_1at
     525                 :      330346 :   ok=.false.
     526         [ +  + ]:     5722998 :   do isym=1,Sym%nsym
     527                 :     5666528 :     indsym2(:)=0
     528                 :     5666528 :     call tdep_calc_indsym2(SC,eatom,fatom,indsym2,isym,Sym)
     529                 :     5666528 :     ee=indsym2(4)
     530                 :     5666528 :     ff=indsym2(8)
     531         [ +  + ]:    22666112 :     latte(:)=indsym2(1:3)
     532         [ +  + ]:    22666112 :     lattf(:)=indsym2(5:7)
     533         [ +  + ]:     5666528 :     if (ee==iatom_unitcell.and.ff==jatom_unitcell) then
     534   [ +  +  +  + ]:    11854000 :       if (sum(abs((vecti(:)-latte(:))-(vectj(:)-lattf(:)))).lt.tol8) then
     535                 :      273876 :         Isym2at(eatom,fatom,1)=isym
     536                 :      273876 :         Isym2at(eatom,fatom,2)=1
     537                 :             :         ok=.true.
     538                 :             :       end if
     539                 :             :     end if
     540                 :       56470 :     if (ok) exit
     541                 :             :   end do
     542                 :             : 
     543                 :      330346 :  end subroutine tdep_SearchS_2at
     544                 :             : !!***
     545                 :             : 
     546                 :             : !=====================================================================================================
     547                 :             : 
     548                 :             : !!****f* m_tdep_sym/tdep_SearchS_3at
     549                 :             : !! NAME
     550                 :             : !!  tdep_SearchS_3at
     551                 :             : !!
     552                 :             : !! FUNCTION
     553                 :             : !!  Search the symmetry operation that transforms the triplet of atoms
     554                 :             : !!  (e,f,g) into the reference triplet of atoms (i,j,k), i.e. such that
     555                 :             : !!  e, f and g are respectively equivalent to i, j and k, and that the
     556                 :             : !!  lattice vectors connecting each pair of atoms are consistent.
     557                 :             : !!  The first symmetry operation found is retained.
     558                 :             : !!  The permutations of the triplet are handled by the caller
     559                 :             : !!  (see tdep_init_shell3at).
     560                 :             : !!
     561                 :             : !! INPUTS
     562                 :             : !!  SC = Supercell object describing the ideal structure.
     563                 :             : !!  iatom, jatom, katom = Atoms of the reference triplet (iatom in the unitcell).
     564                 :             : !!  eatom, fatom, gatom = Atoms of the triplet to be transformed.
     565                 :             : !!  Sym = Symmetries object describing all the symmetry operations of the crystal.
     566                 :             : !!
     567                 :             : !! OUTPUT
     568                 :             : !!
     569                 :             : !! SIDE EFFECTS
     570                 :             : !!  Isym3at(2) = If a symmetry operation isym is found, Isym3at(1)=isym
     571                 :             : !!               and Isym3at(2)=1. Unchanged otherwise.
     572                 :             : !!
     573                 :             : !! SOURCE
     574                 :             : 
     575                 :       43178 :  subroutine tdep_SearchS_3at(SC,iatom,jatom,katom,eatom,fatom,gatom,Isym3at,Sym)
     576                 :             : 
     577                 :             :   integer, intent(in) :: iatom,jatom,katom,eatom,fatom,gatom
     578                 :             :   type(tdep_Supercell_type),intent(in) :: SC
     579                 :             :   type(Symmetries_type),intent(in) :: Sym
     580                 :             :   integer, intent(inout) :: Isym3at(2)
     581                 :             : 
     582                 :             :   integer :: isym,ee,ff,gg,ii
     583                 :             :   integer :: iatom_unitcell,jatom_unitcell,katom_unitcell
     584                 :             :   integer :: vecti(3),vectj(3),vectk(3),indsym2(8)
     585                 :             :   integer :: lattef(3),lattfg(3),lattge(3),lattfe(3),lattgf(3),latteg(3)
     586                 :             :   double precision :: xred_i(3),xred_j(3),xred_k(3),temp(3)
     587                 :             :   double precision :: xred_unit_i(3),xred_unit_j(3),xred_unit_k(3)
     588                 :       86356 :   double precision :: xred_unit_motif(3,SC%natom_unitcell)
     589                 :             :   double precision :: origin(3)
     590                 :             :   logical :: ok
     591                 :             : 
     592                 :             : ! Search the couple of atoms (e,f) obtained through the transformation (R+t)
     593                 :             : ! starting from (i,j)
     594                 :             : ! In that case, note that two cases are possible:
     595                 :             : ! - The bond is just transformed, so indsym(4,e)=i and indsym(4,f)=j
     596                 :             : ! - The bond is transformed and reversed, so indsym(4,e)=j and indsym(4,f)=i
     597                 :             : 
     598                 :             : ! Positions are anchored on atom 1 (as Sym%xred_zero is, see tdep_make_sym)
     599                 :             : ! before wrapping, since wrapping does not commute with a shift of origin.
     600                 :       43178 :   origin = SC%get_xred_scaled(1)
     601                 :             : 
     602                 :             : ! Store the positions of the atoms in the motif, in unitcell-reduced coordinates
     603         [ +  + ]:      143022 :   do ii=1,SC%natom_unitcell
     604         [ +  + ]:      442554 :     xred_unit_motif(:,ii) = SC%scaled_to_unit(SC%wrap_inbox(SC%get_xred_scaled(ii) - origin))
     605                 :             :   end do
     606                 :             : 
     607                 :             : ! Search the atom equivalent to iatom in the (reference) unitcell
     608                 :             : ! Note that in the (present) particular case : iatom_unitcell=iatom and vecti(:)=zero
     609         [ +  + ]:      172712 :   xred_i = SC%wrap_inbox(SC%get_xred_scaled(iatom) - origin)
     610                 :       43178 :   xred_unit_i = SC%scaled_to_unit(xred_i)
     611                 :       43178 :   iatom_unitcell=mod(iatom-1,SC%natom_unitcell)+1
     612         [ +  + ]:      172712 :   vecti(:)=nint(xred_unit_i(:)-xred_unit_motif(:,iatom_unitcell))
     613                 :             : 
     614                 :             : ! Search the atom equivalent to jatom in the (reference) unitcell.
     615                 :             : ! jatom can be outside the box (according to the value of iatom)
     616                 :             : ! so we use the inbox procedure to put the distance within [-0.5,0.5[
     617         [ +  + ]:      172712 :   xred_j = SC%wrap_inbox(SC%get_xred_scaled(jatom) - origin)
     618         [ +  + ]:      172712 :   temp(:)=xred_j(:)-xred_i(:)
     619                 :       43178 :   call tdep_make_inbox(temp,1,1d-3,temp)
     620         [ +  + ]:      172712 :   temp(:)=xred_i(:)+temp(:)
     621                 :       43178 :   xred_unit_j = SC%scaled_to_unit(temp)
     622                 :       43178 :   jatom_unitcell=mod(jatom-1,SC%natom_unitcell)+1
     623         [ +  + ]:      172712 :   vectj(:)=nint(xred_unit_j(:)-xred_unit_motif(:,jatom_unitcell))
     624                 :             : 
     625                 :             : ! Search the atom equivalent to katom in the (reference) unitcell.
     626                 :             : ! katom can be outside the box (according to the value of iatom)
     627                 :             : ! so we use the inbox procedure to put the distance within [-0.5,0.5[
     628         [ +  + ]:      172712 :   xred_k = SC%wrap_inbox(SC%get_xred_scaled(katom) - origin)
     629         [ +  + ]:      172712 :   temp(:)=xred_k(:)-xred_i(:)
     630                 :       43178 :   call tdep_make_inbox(temp,1,1d-3,temp)
     631         [ +  + ]:      172712 :   temp(:)=xred_i(:)+temp(:)
     632                 :       43178 :   xred_unit_k = SC%scaled_to_unit(temp)
     633                 :       43178 :   katom_unitcell=mod(katom-1,SC%natom_unitcell)+1
     634         [ +  + ]:      172712 :   vectk(:)=nint(xred_unit_k(:)-xred_unit_motif(:,katom_unitcell))
     635                 :             : 
     636                 :             : ! To understand the meaning of "latt", see SearchS_1at
     637                 :       43178 :   ok=.false.
     638         [ +  + ]:      975613 :   do isym=1,Sym%nsym
     639                 :             : !   TODO : A CHECKER!!!!!!!!!!!!!!!!!
     640                 :      959861 :     indsym2(:)=zero
     641                 :      959861 :     call tdep_calc_indsym2(SC,eatom,fatom,indsym2,isym,Sym)
     642                 :      959861 :     ee=indsym2(4)
     643         [ +  + ]:     3839444 :     lattef(:)=indsym2(1:3)
     644         [ +  + ]:     3839444 :     lattfe(:)=indsym2(5:7)
     645                 :             : 
     646                 :      959861 :     indsym2(:)=zero
     647                 :      959861 :     call tdep_calc_indsym2(SC,fatom,gatom,indsym2,isym,Sym)
     648                 :      959861 :     ff=indsym2(4)
     649         [ +  + ]:     3839444 :     lattfg(:)=indsym2(1:3)
     650         [ +  + ]:     3839444 :     lattgf(:)=indsym2(5:7)
     651                 :             : 
     652                 :      959861 :     indsym2(:)=zero
     653                 :      959861 :     call tdep_calc_indsym2(SC,gatom,eatom,indsym2,isym,Sym)
     654                 :      959861 :     gg=indsym2(4)
     655         [ +  + ]:     3839444 :     lattge(:)=indsym2(1:3)
     656         [ +  + ]:     3839444 :     latteg(:)=indsym2(5:7)
     657   [ +  +  +  + ]:      959861 :     if (ee==iatom_unitcell.and.ff==jatom_unitcell.and.gg==katom_unitcell) then
     658                 :             :       if ((sum(abs((vecti(:)-lattef(:))-(vectj(:)-lattfe(:)))).lt.tol8).and.&
     659   [ +  +  +  +  :     1963720 : &         (sum(abs((vectj(:)-lattfg(:))-(vectk(:)-lattgf(:)))).lt.tol8).and.&
          +  +  +  +  +  
                      - ]
     660                 :             : &         (sum(abs((vectk(:)-lattge(:))-(vecti(:)-latteg(:)))).lt.tol8)) then
     661                 :       27426 :         Isym3at(1)=isym
     662                 :       27426 :         Isym3at(2)=1
     663                 :             :         ok=.true.
     664                 :             :       end if
     665                 :             :     end if
     666                 :       15752 :     if (ok) exit
     667                 :             :   end do
     668                 :             : 
     669                 :       43178 :  end subroutine tdep_SearchS_3at
     670                 :             : !!***
     671                 :             : 
     672                 :             : !=====================================================================================================
     673                 :             : 
     674                 :             : !!****f* m_tdep_sym/tdep_SearchS_4at
     675                 :             : !! NAME
     676                 :             : !!  tdep_SearchS_4at
     677                 :             : !!
     678                 :             : !! FUNCTION
     679                 :             : !!  Search the symmetry operation that transforms the quadruplet of atoms
     680                 :             : !!  (e,f,g,h) into the reference quadruplet of atoms (i,j,k,l), i.e. such
     681                 :             : !!  that e, f, g and h are respectively equivalent to i, j, k and l, and
     682                 :             : !!  that the lattice vectors connecting each pair of atoms are consistent.
     683                 :             : !!  The first symmetry operation found is retained.
     684                 :             : !!  The permutations of the quadruplet are handled by the caller
     685                 :             : !!  (see tdep_init_shell4at).
     686                 :             : !!
     687                 :             : !! INPUTS
     688                 :             : !!  SC = Supercell object describing the ideal structure.
     689                 :             : !!  iatom, jatom, katom, latom = Atoms of the reference quadruplet
     690                 :             : !!                               (iatom in the unitcell).
     691                 :             : !!  eatom, fatom, gatom, hatom = Atoms of the quadruplet to be transformed.
     692                 :             : !!  Sym = Symmetries object describing all the symmetry operations of the crystal.
     693                 :             : !!
     694                 :             : !! OUTPUT
     695                 :             : !!
     696                 :             : !! SIDE EFFECTS
     697                 :             : !!  Isym4at(2) = If a symmetry operation isym is found, Isym4at(1)=isym
     698                 :             : !!               and Isym4at(2)=1. Unchanged otherwise.
     699                 :             : !!
     700                 :             : !! SOURCE
     701                 :             : 
     702                 :       68388 :  subroutine tdep_SearchS_4at(SC,iatom,jatom,katom,latom,eatom,fatom,gatom,hatom,Isym4at,Sym)
     703                 :             : 
     704                 :             :   integer, intent(in) :: iatom,jatom,katom,latom,eatom,fatom,gatom,hatom
     705                 :             :   type(tdep_Supercell_type),intent(in) :: SC
     706                 :             :   type(Symmetries_type),intent(in) :: Sym
     707                 :             :   integer, intent(inout) :: Isym4at(2)
     708                 :             : 
     709                 :             :   integer :: isym,ee,ff,gg,hh,ii
     710                 :             :   integer :: iatom_unitcell,jatom_unitcell,katom_unitcell,latom_unitcell
     711                 :             :   integer :: vecti(3),vectj(3),vectk(3),vectl(3),indsym2(8)
     712                 :             :   integer :: lattef(3),lattfe(3)
     713                 :             :   integer :: latteg(3),lattge(3)
     714                 :             :   integer :: latteh(3),latthe(3)
     715                 :             :   integer :: lattfg(3),lattgf(3)
     716                 :             :   integer :: lattfh(3),latthf(3)
     717                 :             :   integer :: lattgh(3),latthg(3)
     718                 :             :   double precision :: xred_i(3),xred_j(3),xred_k(3),xred_l(3),temp(3)
     719                 :             :   double precision :: xred_unit_i(3),xred_unit_j(3),xred_unit_k(3),xred_unit_l(3)
     720                 :      136776 :   double precision :: xred_unit_motif(3,SC%natom_unitcell)
     721                 :             :   double precision :: origin(3)
     722                 :             :   logical :: ok
     723                 :             : 
     724                 :             : ! Search the couple of atoms (e,f) obtained through the transformation (R+t)
     725                 :             : ! starting from (i,j)
     726                 :             : ! In that case, note that two cases are possible:
     727                 :             : ! - The bond is just transformed, so indsym(4,e)=i and indsym(4,f)=j
     728                 :             : ! - The bond is transformed and reversed, so indsym(4,e)=j and indsym(4,f)=i
     729                 :             : 
     730                 :             : ! Positions are anchored on atom 1 (as Sym%xred_zero is, see tdep_make_sym)
     731                 :             : ! before wrapping, since wrapping does not commute with a shift of origin.
     732                 :       68388 :   origin = SC%get_xred_scaled(1)
     733                 :             : 
     734                 :             : ! Store the positions of the atoms in the motif, in unitcell-reduced coordinates
     735         [ +  + ]:      230744 :   do ii=1,SC%natom_unitcell
     736         [ +  + ]:      717812 :     xred_unit_motif(:,ii) = SC%scaled_to_unit(SC%wrap_inbox(SC%get_xred_scaled(ii) - origin))
     737                 :             :   end do
     738                 :             : 
     739                 :             : ! Search the atom equivalent to iatom in the (reference) unitcell
     740                 :             : ! Note that in the (present) particular case : iatom_unitcell=iatom and vecti(:)=zero
     741         [ +  + ]:      273552 :   xred_i = SC%wrap_inbox(SC%get_xred_scaled(iatom) - origin)
     742                 :       68388 :   xred_unit_i = SC%scaled_to_unit(xred_i)
     743                 :       68388 :   iatom_unitcell=mod(iatom-1,SC%natom_unitcell)+1
     744         [ +  + ]:      273552 :   vecti(:)=nint(xred_unit_i(:)-xred_unit_motif(:,iatom_unitcell))
     745                 :             : 
     746                 :             : ! Search the atom equivalent to jatom in the (reference) unitcell.
     747                 :             : ! jatom can be outside the box (according to the value of iatom)
     748                 :             : ! so we use the inbox procedure to put the distance within [-0.5,0.5[
     749         [ +  + ]:      273552 :   xred_j = SC%wrap_inbox(SC%get_xred_scaled(jatom) - origin)
     750         [ +  + ]:      273552 :   temp(:)=xred_j(:)-xred_i(:)
     751                 :       68388 :   call tdep_make_inbox(temp,1,1d-3,temp)
     752         [ +  + ]:      273552 :   temp(:)=xred_i(:)+temp(:)
     753                 :       68388 :   xred_unit_j = SC%scaled_to_unit(temp)
     754                 :       68388 :   jatom_unitcell=mod(jatom-1,SC%natom_unitcell)+1
     755         [ +  + ]:      273552 :   vectj(:)=nint(xred_unit_j(:)-xred_unit_motif(:,jatom_unitcell))
     756                 :             : 
     757                 :             : ! Search the atom equivalent to katom in the (reference) unitcell.
     758                 :             : ! katom can be outside the box (according to the value of iatom)
     759                 :             : ! so we use the inbox procedure to put the distance within [-0.5,0.5[
     760         [ +  + ]:      273552 :   xred_k = SC%wrap_inbox(SC%get_xred_scaled(katom) - origin)
     761         [ +  + ]:      273552 :   temp(:)=xred_k(:)-xred_i(:)
     762                 :       68388 :   call tdep_make_inbox(temp,1,1d-3,temp)
     763         [ +  + ]:      273552 :   temp(:)=xred_i(:)+temp(:)
     764                 :       68388 :   xred_unit_k = SC%scaled_to_unit(temp)
     765                 :       68388 :   katom_unitcell=mod(katom-1,SC%natom_unitcell)+1
     766         [ +  + ]:      273552 :   vectk(:)=nint(xred_unit_k(:)-xred_unit_motif(:,katom_unitcell))
     767                 :             : 
     768                 :             : ! Search the atom equivalent to latom in the (reference) unitcell.
     769                 :             : ! latom can be outside the box (according to the value of iatom)
     770                 :             : ! so we use the inbox procedure to put the distance within [-0.5,0.5[
     771         [ +  + ]:      273552 :   xred_l = SC%wrap_inbox(SC%get_xred_scaled(latom) - origin)
     772         [ +  + ]:      273552 :   temp(:)=xred_l(:)-xred_i(:)
     773                 :       68388 :   call tdep_make_inbox(temp,1,1d-3,temp)
     774         [ +  + ]:      273552 :   temp(:)=xred_i(:)+temp(:)
     775                 :       68388 :   xred_unit_l = SC%scaled_to_unit(temp)
     776                 :       68388 :   latom_unitcell=mod(latom-1,SC%natom_unitcell)+1
     777         [ +  + ]:      273552 :   vectl(:)=nint(xred_unit_l(:)-xred_unit_motif(:,latom_unitcell))
     778                 :             : 
     779                 :             : ! To understand the meaning of "latt", see SearchS_1at
     780                 :       68388 :   ok=.false.
     781         [ +  + ]:     2086763 :   do isym=1,Sym%nsym
     782                 :             : !   TODO : A CHECKER!!!!!!!!!!!!!!!!!
     783                 :     2050751 :     indsym2(:)=zero
     784                 :     2050751 :     call tdep_calc_indsym2(SC,eatom,fatom,indsym2,isym,Sym)
     785                 :     2050751 :     ee=indsym2(4)
     786                 :     2050751 :     ff=indsym2(8)
     787         [ +  + ]:     8203004 :     lattef(:)=indsym2(1:3)
     788         [ +  + ]:     8203004 :     lattfe(:)=indsym2(5:7)
     789                 :             : 
     790                 :     2050751 :     indsym2(:)=zero
     791                 :     2050751 :     call tdep_calc_indsym2(SC,eatom,gatom,indsym2,isym,Sym)
     792                 :     2050751 :     gg=indsym2(8)
     793         [ +  + ]:     8203004 :     latteg(:)=indsym2(1:3)
     794         [ +  + ]:     8203004 :     lattge(:)=indsym2(5:7)
     795                 :             : 
     796                 :     2050751 :     indsym2(:)=zero
     797                 :     2050751 :     call tdep_calc_indsym2(SC,eatom,hatom,indsym2,isym,Sym)
     798                 :     2050751 :     hh=indsym2(8)
     799         [ +  + ]:     8203004 :     latteh(:)=indsym2(1:3)
     800         [ +  + ]:     8203004 :     latthe(:)=indsym2(5:7)
     801                 :             : 
     802                 :     2050751 :     indsym2(:)=zero
     803                 :     2050751 :     call tdep_calc_indsym2(SC,fatom,gatom,indsym2,isym,Sym)
     804         [ +  + ]:     8203004 :     lattfg(:)=indsym2(1:3)
     805         [ +  + ]:     8203004 :     lattgf(:)=indsym2(5:7)
     806                 :             : 
     807                 :     2050751 :     indsym2(:)=zero
     808                 :     2050751 :     call tdep_calc_indsym2(SC,fatom,hatom,indsym2,isym,Sym)
     809         [ +  + ]:     8203004 :     lattfh(:)=indsym2(1:3)
     810         [ +  + ]:     8203004 :     latthf(:)=indsym2(5:7)
     811                 :             : 
     812                 :     2050751 :     indsym2(:)=zero
     813                 :     2050751 :     call tdep_calc_indsym2(SC,gatom,hatom,indsym2,isym,Sym)
     814         [ +  + ]:     8203004 :     lattgh(:)=indsym2(1:3)
     815         [ +  + ]:     8203004 :     latthg(:)=indsym2(5:7)
     816                 :             : 
     817   [ +  +  +  + ]:     2050751 :     if (ee==iatom_unitcell.and.ff==jatom_unitcell.and.gg==katom_unitcell.and.hh==latom_unitcell) then
     818                 :             :       if ((sum(abs((vecti(:)-lattef(:))-(vectj(:)-lattfe(:)))).lt.tol8).and.&
     819                 :             : &         (sum(abs((vecti(:)-latteg(:))-(vectk(:)-lattge(:)))).lt.tol8).and.&
     820                 :             : &         (sum(abs((vecti(:)-latteh(:))-(vectl(:)-latthe(:)))).lt.tol8).and.&
     821                 :             : &         (sum(abs((vectj(:)-lattfg(:))-(vectk(:)-lattgf(:)))).lt.tol8).and.&
     822   [ +  +  +  +  :     5374606 : &         (sum(abs((vectj(:)-lattfh(:))-(vectl(:)-latthf(:)))).lt.tol8).and.&
          +  +  +  +  +  
          +  +  +  +  +  
             +  +  +  - ]
     823                 :             : &         (sum(abs((vectk(:)-lattgh(:))-(vectl(:)-latthg(:)))).lt.tol8)) then
     824                 :       32376 :         Isym4at(1)=isym
     825                 :       32376 :         Isym4at(2)=1
     826                 :             :         ok=.true.
     827                 :             :       end if
     828                 :             :     end if
     829                 :       36012 :     if (ok) exit
     830                 :             :   end do
     831                 :             : 
     832                 :       68388 :  end subroutine tdep_SearchS_4at
     833                 :             : !!***
     834                 :             : 
     835                 :             : !=====================================================================================================
     836                 :             : 
     837                 :             : !!****f* m_tdep_sym/tdep_calc_indsym2
     838                 :             : !! NAME
     839                 :             : !!  tdep_calc_indsym2
     840                 :             : !!
     841                 :             : !! FUNCTION
     842                 :             : !!  Compute, for a pair of atoms (iatom,jatom) of the supercell and a given
     843                 :             : !!  symmetry operation, the equivalent atoms in the reference unitcell and
     844                 :             : !!  the corresponding lattice vectors (as in Sym%indsym, see
     845                 :             : !!  tdep_SearchS_1at). The position of jatom is taken as its periodic image
     846                 :             : !!  closest to iatom, so that the (iatom,jatom) bond is preserved.
     847                 :             : !!
     848                 :             : !! INPUTS
     849                 :             : !!  SC = Supercell object describing the ideal structure.
     850                 :             : !!  iatom, jatom = Atoms of the pair.
     851                 :             : !!  isym = Index of the symmetry operation.
     852                 :             : !!  Sym = Symmetries object. Sym%indsym must already be computed
     853                 :             : !!        (see tdep_SearchS_1at).
     854                 :             : !!
     855                 :             : !! OUTPUT
     856                 :             : !!  indsym2(8) = indsym2(1:3) and indsym2(4) are the lattice vector and the
     857                 :             : !!               equivalent unitcell atom for iatom; indsym2(5:7) and
     858                 :             : !!               indsym2(8) are the same quantities for jatom.
     859                 :             : !!
     860                 :             : !! SOURCE
     861                 :             : 
     862                 :    20850617 :  subroutine tdep_calc_indsym2(SC,iatom,jatom,indsym2,isym,Sym)
     863                 :             : 
     864                 :             :   integer, intent(in) :: iatom,jatom
     865                 :             :   type(tdep_Supercell_type),intent(in) :: SC
     866                 :             :   type(Symmetries_type),intent(in) :: Sym
     867                 :             :   integer, intent(out) :: indsym2(8)
     868                 :             : 
     869                 :             :   integer :: isym,mu,ii
     870                 :             :   integer :: iatom_unitcell,jatom_unitcell
     871                 :    41701234 :   integer :: vecti(3),vectj(3),vectsym(4,Sym%nsym)
     872                 :             :   double precision :: xred_i(3),xred_j(3),temp3(3)
     873                 :             :   double precision :: xred_unit_i(3),xred_unit_j(3)
     874                 :    41701234 :   double precision :: xred_unit_motif(3,SC%natom_unitcell)
     875                 :             :   double precision :: origin(3)
     876                 :             : 
     877                 :             : ! Positions are anchored on atom 1 (as Sym%xred_zero is, see tdep_make_sym)
     878                 :             : ! before wrapping, since wrapping does not commute with a shift of origin.
     879                 :    20850617 :   origin = SC%get_xred_scaled(1)
     880                 :             : 
     881                 :             : ! Store the positions of the atoms in the motif, in unitcell-reduced coordinates
     882         [ +  + ]:    69177220 :   do ii=1,SC%natom_unitcell
     883         [ +  + ]:   214157029 :     xred_unit_motif(:,ii) = SC%scaled_to_unit(SC%wrap_inbox(SC%get_xred_scaled(ii) - origin))
     884                 :             :   end do
     885                 :             : 
     886                 :             : ! For a single iatom
     887         [ +  + ]:    83402468 :   xred_i = SC%wrap_inbox(SC%get_xred_scaled(iatom) - origin)
     888                 :    20850617 :   xred_unit_i = SC%scaled_to_unit(xred_i)
     889                 :    20850617 :   iatom_unitcell=mod(iatom-1,SC%natom_unitcell)+1
     890         [ +  + ]:    83402468 :   vecti(:)=nint(xred_unit_i(:)-xred_unit_motif(:,iatom_unitcell))
     891   [ +  +  +  + ]:  4850947337 :   vectsym(:,:)=0
     892         [ +  + ]:    83402468 :   do mu=1,3 ! Apply inverse transformation to original coordinates. Note transpose of symrec.
     893                 :    83402468 :     vectsym(mu,isym) = Sym%symrec(1,mu,isym)*vecti(1)+Sym%symrec(2,mu,isym)*vecti(2)+Sym%symrec(3,mu,isym)*vecti(3)
     894                 :             :   end do
     895         [ +  + ]:   104253085 :   indsym2(1:4)=Sym%indsym(1:4,isym,iatom_unitcell)+vectsym(1:4,isym)
     896                 :             : 
     897                 :             : ! For a couple of (iatom,jatom). The (iatom,jatom) vector depends on the position of iatom (due to PBC)
     898         [ +  + ]:    83402468 :   xred_j = SC%wrap_inbox(SC%get_xred_scaled(jatom) - origin)
     899         [ +  + ]:    83402468 :   temp3(:)=xred_j(:)-xred_i(:)
     900                 :    20850617 :   call tdep_make_inbox(temp3,1,1d-3,temp3)
     901         [ +  + ]:    83402468 :   temp3(:)=xred_i(:)+temp3(:)
     902                 :    20850617 :   xred_unit_j = SC%scaled_to_unit(temp3)
     903                 :    20850617 :   jatom_unitcell=mod(jatom-1,SC%natom_unitcell)+1
     904         [ +  + ]:    83402468 :   vectj(:)=nint(xred_unit_j(:)-xred_unit_motif(:,jatom_unitcell))
     905   [ +  +  +  + ]:  4850947337 :   vectsym(:,:)=0
     906         [ +  + ]:    83402468 :   do mu=1,3 ! Apply inverse transformation to original coordinates. Note transpose of symrec.
     907                 :    83402468 :     vectsym(mu,isym) = Sym%symrec(1,mu,isym)*vectj(1)+Sym%symrec(2,mu,isym)*vectj(2)+Sym%symrec(3,mu,isym)*vectj(3)
     908                 :             :   end do
     909         [ +  + ]:   104253085 :   indsym2(5:8)=Sym%indsym(1:4,isym,jatom_unitcell)+vectsym(1:4,isym)
     910                 :             : 
     911                 :    20850617 :  end subroutine tdep_calc_indsym2
     912                 :             : !!***
     913                 :             : 
     914                 :             : !=====================================================================================================
     915                 :             : 
     916                 :             : !!****f* m_tdep_sym/tdep_destroy_sym
     917                 :             : !! NAME
     918                 :             : !!  tdep_destroy_sym
     919                 :             : !!
     920                 :             : !! FUNCTION
     921                 :             : !!  Free the memory allocated in the Symmetries object.
     922                 :             : !!
     923                 :             : !! SIDE EFFECTS
     924                 :             : !!  Sym = Symmetries object. All its allocated arrays are deallocated.
     925                 :             : !!
     926                 :             : !! SOURCE
     927                 :             : 
     928                 :          46 :  subroutine tdep_destroy_sym(Sym)
     929                 :             : 
     930                 :             :   class(Symmetries_type),intent(inout) :: Sym
     931                 :             : 
     932         [ -  + ]:          46 :   ABI_FREE(Sym%S_ref)
     933         [ -  + ]:          46 :   ABI_FREE(Sym%S_inv)
     934         [ -  + ]:          46 :   ABI_FREE(Sym%xred_zero)
     935         [ -  + ]:          46 :   ABI_FREE(Sym%tnons)
     936         [ -  + ]:          46 :   ABI_FREE(Sym%symafm)
     937         [ -  + ]:          46 :   ABI_FREE(Sym%symrec)
     938         [ -  + ]:          46 :   ABI_FREE(Sym%symrel)
     939         [ -  + ]:          46 :   ABI_FREE(Sym%indsym)
     940                 :             : 
     941                 :          46 :  end subroutine tdep_destroy_sym
     942                 :             : !!***
     943                 :             : 
     944                 :             : !=====================================================================================================
     945                 :             : 
     946   [ -  +  -  -  :         138 : end module m_tdep_sym
          +  +  -  +  +  
          -  -  +  -  +  
          +  -  -  +  -  
          +  -  +  -  +  
             -  +  -  + ]
     947                 :             : !!***
        

Generated by: LCOV version 2.3-1