LCOV - code coverage report
Current view: top level - src/41_geometry - m_symfind.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 89.6 % 1130 1013
Test Date: 2026-09-21 13:49:52 Functions: 100.0 % 6 6

            Line data    Source code
       1              : !!****m* ABINIT/m_symfind
       2              : !! NAME
       3              : !!  m_symfind
       4              : !!
       5              : !! FUNCTION
       6              : !!  Symmetry finder high-level API.
       7              : !!
       8              : !! COPYRIGHT
       9              : !!  Copyright (C) 2000-2026 ABINIT group (XG, RC)
      10              : !!  This file is distributed under the terms of the
      11              : !!  GNU General Public License, see ~abinit/COPYING
      12              : !!  or http://www.gnu.org/copyleft/gpl.txt .
      13              : !!
      14              : !! SOURCE
      15              : 
      16              : #if defined HAVE_CONFIG_H
      17              : #include "config.h"
      18              : #endif
      19              : 
      20              : #include "abi_common.h"
      21              : 
      22              : module m_symfind
      23              : 
      24              :  use defs_basis
      25              :  use m_errors
      26              :  use m_abicore
      27              :  use m_symlist
      28              : 
      29              : 
      30              :  use m_matrix,    only : mati3inv, matr3inv, mati3det
      31              :  use m_symtk,     only : chkprimit, symrelrot, symdet, symcharac, holocell, symatm, &
      32              :                          smallprim, print_symmetries, sg_multable, symmetrize_tnons, symmetrize_xred
      33              :  use m_geometry,  only : acrossb, xred2xcart
      34              :  use m_spgdata,   only : getptgroupma, symptgroup, spgdata
      35              : 
      36              :  implicit none
      37              : 
      38              :  private
      39              : !!***
      40              : 
      41              :  public :: symfind     ! From the symmetries of the Bravais lattice,
      42              :                        ! select those that leave invariant the system, and generate tnons. Not always robust.
      43              :  public :: symfind_expert  ! Wrap symfind to provide robust determination of the symmetries,
      44              :                            ! for which resymmetrization of atomic positions and tnons is needed.
      45              :  public :: symanal     ! Find the space group from the list of symmetries and lattice parameters
      46              :  public :: symbrav     ! Determine the Bravais information from the list of symmetry operations, and the lattice vectors.
      47              :  public :: symlatt     ! Find the Bravais lattice and its symmetry operations (ptsymrel).
      48              :                        ! From the unit cell vectors (rprimd) and the corresponding metric tensor.
      49              : 
      50              : contains
      51              : !!***
      52              : 
      53              : !!****f* m_symfind/symfind
      54              : !! NAME
      55              : !! symfind
      56              : !!
      57              : !! FUNCTION
      58              : !! Symmetry finder.
      59              : !! From the symmetries of the Bravais lattice (ptsymrel),
      60              : !! select those that leave invariant the system, and generate
      61              : !! the corresponding tnons vectors and symafm information.
      62              : !! Unlike symfind_expert, does NOT resymmetrize atomic positions and tnons for more robust determination of the symmetries.
      63              : !! The algorithm is explained in T.G. Worlton and J.L. Warren, Comp. Phys. Comm. 3, 88 (1972) [[cite:Worlton1972]]
      64              : !!
      65              : !! INPUTS
      66              : !! chrgat(natom) (optional)=target charge for each atom. Not always used, it depends on the value of constraint_kind
      67              : !! invardir_red (optional)=reduced coordinates of an invariant direction (only acting with symrel - not tnons)
      68              : !! invaraxial_red (optional)=reduced coordinates of an axial vector, similar to invardir_red, but transforms with an additional
      69              : !!                           deteminant factor under symrel operations
      70              : !! invar_z (optional)= if 1, the z direction must stay invariant for all symrel applied ;
      71              : !!                     if 2, z must stay invariant and also there cannot be any associated tnons along z.
      72              : !! gprimd(3,3)=dimensional primitive translations for reciprocal space
      73              : !! msym=default maximal number of symmetries
      74              : !! natom=number of atoms in cell.
      75              : !! nptsym=number of point symmetries of the Bravais lattice
      76              : !! nspden= number of spin-density components. When 4, the three components of spinat are taken into account, instead of only z-component.
      77              : !! nucdipmom(3,natom) (optional) array of nuclear dipole moments
      78              : !! ptsymrel(3,3,1:msym)= nptsym point-symmetry operations
      79              : !!   of the Bravais lattice in real space in terms
      80              : !!   of primitive translations.
      81              : !! spinat(3,natom)=initial spin of each atom, in unit of hbar/2.
      82              : !! tolsym=tolerance for the symmetries
      83              : !! typat(natom)=integer identifying type of atom.
      84              : !! use_inversion=1 if inversion and improper rotations can be included in set of symmetries
      85              : !! xred(3,natom)=reduced coordinates of atoms in terms of real space
      86              : !!   primitive translations
      87              : !!
      88              : !! OUTPUT
      89              : !! ierr (optional)=if non-zero, the symmetry operations do not form a group
      90              : !! nsym=actual number of symmetries
      91              : !! symafm(1:msym)=(anti)ferromagnetic part of nsym symmetry operations
      92              : !! symrel(3,3,1:msym)= nsym symmetry operations in real space in terms
      93              : !!  of primitive translations
      94              : !! tnons(3,1:msym)=nonsymmorphic translations for each symmetry (would
      95              : !!  be 0 0 0 each for a symmorphic space group)
      96              : !!
      97              : !! SOURCE
      98              : 
      99        18005 :  subroutine symfind(gprimd,msym,natom,nptsym,nspden,nsym,&
     100        18005 :                     prtvol, ptsymrel,spinat,symafm,symrel,tnons,tolsym,typat,use_inversion,xred,&
     101        35586 :                     chrgat,ierr,nucdipmom,invardir_red,invaraxial_red,invar_z)  ! Optional
     102              : 
     103              : !Arguments ------------------------------------
     104              : !scalars
     105              :  integer,intent(in) :: msym,natom,nptsym,nspden,use_inversion
     106              :  integer,intent(in) :: prtvol
     107              :  integer,optional,intent(in) :: invar_z
     108              :  integer,optional,intent(out) :: ierr
     109              :  integer,intent(out) :: nsym
     110              :  real(dp),intent(in) :: tolsym
     111              : !arrays
     112              :  integer,intent(in) :: ptsymrel(3,3,msym),typat(natom)
     113              :  integer,intent(inout) :: symafm(msym),symrel(3,3,msym) !vz_i
     114              :  real(dp),intent(in) :: gprimd(3,3),spinat(3,natom),xred(3,natom)
     115              :  real(dp),optional,intent(in) :: invardir_red(3),invaraxial_red(3),chrgat(natom)
     116              :  real(dp),optional, intent(in) :: nucdipmom(3,natom)
     117              :  real(dp),intent(inout) :: tnons(3,msym) !vz_i
     118              : 
     119              : !Local variables-------------------------------
     120              : !scalars
     121              :  integer :: found3,foundcl,iatom,iatom0,iatom1,iatom2,iatom3,iclass,iclass0,ierr_,ii
     122              :  integer :: isym,jj,kk,natom0,nclass,ntrial,printed,trialafm,trialok
     123              :  integer :: mm(3,3), detR
     124              :  real(dp) :: det,diff1,diff2,diff3,diffr1,diffr2,diffr3,ndnorm,nucdipmomcl2,nucdipmomcl20
     125              :  real(dp) :: spinat2,spinatcl2,spinatcl20,tolsym2
     126              : ! TRUE if antiferro symmetries are used with non-collinear magnetism.
     127              :  integer :: afm_noncoll=1 !For nspden==4.  If 1, all symops are permitted ; if 0 symafm must be 1.
     128              : !For nspden=4. If noncoll_orthorhombic1, require the symmetry operations to be a subset of the orthorhombic symmetries, except if all spinat=0..
     129              :  integer :: noncoll_orthorhombic=0
     130              :  logical :: test_sameabsspin,test_samechrg
     131              :  logical :: test_samenucdipmom
     132              :  character(len=500) :: msg
     133              : !arrays
     134        18005 :  integer,allocatable :: class(:,:),natomcl(:),typecl(:)
     135              :  real(dp) :: diff(3),invardir_red_rot(3),invaraxial_red_rot(3),hand2(3),hand3(3),ndtest(3),rprimd(3,3),spinat0(3),xred0(3)
     136              :  !real(dp) :: symnucdipmom2(3)
     137              :  real(dp) :: symnucdipmom2cart(3,3),symnucdipmom2red(3,3)
     138              :  real(dp) :: symspinat1(3),symspinat2(3),symxred2(3),trialnons(3)
     139        18005 :  real(dp),allocatable :: chrgat_(:)
     140        18005 :  real(dp),allocatable :: chrgatcl(:)
     141        18005 :  real(dp),allocatable :: local_nucdipmom(:,:,:),nucdipmomcl(:,:),nucdipmomred(:,:,:)
     142        18005 :  real(dp),allocatable :: spinatcl(:,:),spinatred(:,:)
     143              : !**************************************************************************
     144              : 
     145              : !write(std_out,'(a)')' m_symfind%symfind : enter '; call flush(std_out)
     146              : 
     147        54015 :  ABI_MALLOC(local_nucdipmom,(3,3,natom))
     148       596765 :  local_nucdipmom(:,:,:) = zero
     149        18005 :  if(present(nucdipmom)) then
     150       193265 :     local_nucdipmom(1:3,1,:) = nucdipmom(1:3,:)
     151              :  end if
     152              : !DEBUG
     153              : ! if (prtvol>1) msg="remove me later"
     154              : ! write(std_out,*)' symfind : enter'
     155              : ! call flush(6)
     156              : ! write(std_out,*)'   ptsymrel matrices are :'
     157              : ! do isym=1,nptsym
     158              : ! write(std_out,'(i4,4x,9i4)' )isym,ptsymrel(:,:,isym)
     159              : ! end do
     160              : ! write(std_out,*)' symfind : natom=',natom
     161              : ! do iatom=1,natom
     162              : ! write(std_out,*)'  atom number',iatom
     163              : ! write(std_out,*)'   typat   =',typat(iatom)
     164              : ! write(std_out,*)'   spinat  =',spinat(:,iatom)
     165              : ! write(std_out,*)'   xred    =',xred(:,iatom)
     166              : ! if (ANY(ABS(local_nucdipmom)>tol8)) then
     167              : ! write(std_out,*)'   nucdipmom = ',local_nucdipmom(:,1,iatom)
     168              : ! end if
     169              : ! end do
     170              : ! write(std_out,*)' '
     171              : ! call flush(6)
     172              : !ENDDEBUG
     173              : 
     174              :  ABI_UNUSED(prtvol)
     175              : 
     176              : !Find the number of classes of atoms (type, chrg and spinat must be identical,
     177              : !spinat might differ by a sign, if aligned with the z direction, or,
     178              : ! type and nucdipmom must be identical)
     179              : !natomcl(iclass) will contain the number of atoms in the class
     180              : !typecl(iclass) will contain the type of the atoms in the class
     181              : !chrgcl(iclass) will contain the charge of the atoms in the class
     182              : !spinatcl(1:3,iclass) will contain the spinat of the atoms in the class
     183              : !class(1:natomclass(iclass),iclass) will contain the index of the
     184              : !atoms belonging to the class
     185        72020 :  ABI_MALLOC(class,(natom+3,natom))
     186        54015 :  ABI_MALLOC(natomcl,(natom))
     187        36010 :  ABI_MALLOC(typecl,(natom))
     188        54015 :  ABI_MALLOC(chrgat_,(natom))
     189        36010 :  ABI_MALLOC(chrgatcl,(natom))
     190        54015 :  ABI_MALLOC(spinatcl,(3,natom))
     191        36010 :  ABI_MALLOC(nucdipmomcl,(3,natom))
     192              : 
     193        18005 :  tolsym2=tolsym**2
     194              : 
     195        62525 :  chrgat_(:)=zero
     196        18005 :  if(present(chrgat))then
     197        61661 :    chrgat_(:)=chrgat(:)
     198              :  endif
     199              : 
     200              :  ! for each nuclear dipole we need a local right handed coord system, so we can
     201              :  ! test later for whether a symmetry operation preserves the circulation induced
     202              :  ! by the dipole
     203        62525 :  do iatom=1, natom
     204       178080 :     ndnorm=sqrt(DOT_PRODUCT(local_nucdipmom(1:3,1,iatom),local_nucdipmom(1:3,1,iatom)))
     205              : 
     206              :     ! if nuclear dipole has effectively zero size, move on to the next atom
     207        44520 :     if (ndnorm < tol8) cycle
     208              : 
     209              :     ! for testing purposes, we care only about direction so renormalize to unity
     210          496 :     local_nucdipmom(1:3,1,iatom) = local_nucdipmom(1:3,1,iatom)/ndnorm
     211              : 
     212              :     ! make a random vector, each component is (0,1]
     213          124 :     call random_number(ndtest)
     214              : 
     215              :     ! vector 2 is constructed to be orthogonal to original nuclear dipole moment vector
     216          124 :     call acrossb(local_nucdipmom(1:3,1,iatom),ndtest(1:3),local_nucdipmom(1:3,2,iatom))
     217              : 
     218              :     ! vector 3 is orthogonal to 1 and 2, and 1,2,3 form a right-handed set
     219        62525 :     call acrossb(local_nucdipmom(1:3,1,iatom),local_nucdipmom(1:3,2,iatom),local_nucdipmom(1:3,3,iatom))
     220              :  end do
     221              : 
     222              :  ! need rprimd later to transform back to cart coords
     223        18005 :  call matr3inv(gprimd,rprimd)
     224              : 
     225              : !write(std_out,'(a)')' m_symfind%symfind : before initialise with the first atom '; call flush(std_out)
     226              : 
     227              : !Initialise with the first atom
     228        18005 :  nclass=1
     229        18005 :  natomcl(1)=1
     230        18005 :  typecl(1)=typat(1)
     231        18005 :  chrgatcl(1)=chrgat_(1)
     232        72020 :  spinatcl(:,1)=spinat(:,1)
     233        72020 :  nucdipmomcl(:,1)=local_nucdipmom(:,1,1)
     234        18005 :  class(1,1)=1
     235        18005 :  if(natom>1)then
     236        40135 :    do iatom=2,natom
     237              : !    DEBUG
     238              : !    write(std_out,*)' '
     239              : !    write(std_out,*)' symfind : examine iatom=',iatom
     240              : !    ENDDEBUG
     241        38751 :      foundcl=0
     242        38751 :      do iclass=1,nclass
     243              : !      Compare the typat, chrg and spinat of atom iatom with existing ones.
     244              : !      At this stage, admit either identical spinat, or spin-flip spinat.
     245        38751 :        if( typat(iatom)==typecl(iclass)) then
     246        20612 :          test_samechrg= (abs(chrgat_(iatom)-chrgatcl(iclass))<tolsym)
     247        20612 :          if(nspden/=4)then
     248        19968 :            test_sameabsspin=(abs(abs(spinat(3,iatom))-abs(spinatcl(3,iclass)))<tolsym)
     249              :          else if(nspden==4)then
     250          644 :            spinat2  =spinat(1,iatom)**2+spinat(2,iatom)**2+spinat(3,iatom)**2
     251          644 :            spinatcl2=spinatcl(1,iclass)**2+spinatcl(2,iclass)**2+spinatcl(3,iclass)**2
     252          644 :            test_sameabsspin=abs(spinat2-spinatcl2)<tolsym
     253              :          endif
     254              :          test_samenucdipmom= &
     255              : &             abs(local_nucdipmom(1,1,iatom)-nucdipmomcl(1,iclass))<tolsym .and. &
     256              : &             abs(local_nucdipmom(2,1,iatom)-nucdipmomcl(2,iclass))<tolsym .and. &
     257        20612 : &             abs(local_nucdipmom(3,1,iatom)-nucdipmomcl(3,iclass))<tolsym
     258              :          ! note in the following test, m_chkinp/chkinp has already prevented nucdipmom to be
     259              :          ! nonzero when spinat is nonzero
     260        20612 :          if( test_samechrg .and. test_sameabsspin .and. test_samenucdipmom ) then
     261              : !          write(std_out,*)' symfind : find it belongs to class iclass=',iclass
     262              : !          write(std_out,*)' symfind : spinat(:,iatom)=',spinat(:,iatom)
     263              : !          write(std_out,*)' symfind : spinatcl(:,iclass)=',spinatcl(:,iclass)
     264              : !          write(std_out,*)' symfind : test_sameabsspin=',test_sameabsspin
     265              : !          write(std_out,*)' '
     266        20530 :            natomcl(iclass)=natomcl(iclass)+1
     267        20530 :            class(natomcl(iclass),iclass)=iatom
     268              :            foundcl=1
     269              :            exit
     270              :          end if
     271              :        end if
     272              :      end do
     273              : !    If no class with these characteristics exist, create one
     274        13620 :      if(foundcl==0)then
     275         5985 :        nclass=nclass+1
     276         5985 :        natomcl(nclass)=1
     277         5985 :        typecl(nclass)=typat(iatom)
     278         5985 :        chrgatcl(nclass)=chrgat_(iatom)
     279        23940 :        spinatcl(:,nclass)=spinat(:,iatom)
     280        23940 :        nucdipmomcl(:,nclass)=local_nucdipmom(:,1,iatom)
     281         5985 :        class(1,nclass)=iatom
     282              :      end if
     283              :    end do
     284              :  end if
     285              : 
     286              : !write(std_out,*)' '
     287              : !write(std_out,*)' symfind : found ',nclass,' nclass of atoms'
     288              : !do iclass=1,nclass
     289              : !write(std_out,*)'  class number',iclass
     290              : !write(std_out,*)'   natomcl =',natomcl(iclass)
     291              : !write(std_out,*)'   typecl  =',typecl(iclass)
     292              : !write(std_out,*)'   spinatcl=',spinatcl(:,iclass)
     293              : !write(std_out,*)'   class   =',(class(iatom,iclass),iatom=1,natomcl(iclass))
     294              : !end do
     295              : !write(std_out,*)' '
     296              : 
     297              : !write(std_out,'(a)')' m_symfind%symfind : before select the class '; call flush(std_out)
     298              : 
     299              : !Select the class with the least number of atoms, and non-zero spinat if any
     300              : !It is important to select a magnetic class of atom, if any, otherwise
     301              : !the determination of the initial (inclusive) set of symmetries takes only
     302              : !non-magnetic symmetries, and not both magnetic and non-magnetic ones, see later.
     303              : !On the contrary, the chrgat_ data does not play any role, it is invariant upon atomic-centered  symmetries
     304        18005 :  iclass0=1
     305        18005 :  natom0=natomcl(1)
     306        18005 :  spinatcl20=spinatcl(1,1)**2+spinatcl(2,1)**2+spinatcl(3,1)**2
     307        18005 :  nucdipmomcl20=nucdipmomcl(1,1)**2+nucdipmomcl(2,1)**2+nucdipmomcl(3,1)**2
     308        18005 :  if(nclass>1)then
     309        11602 :    do iclass=2,nclass
     310         5985 :      spinatcl2=spinatcl(1,iclass)**2+spinatcl(2,iclass)**2+spinatcl(3,iclass)**2
     311         5985 :      nucdipmomcl2=nucdipmomcl(1,iclass)**2+nucdipmomcl(2,iclass)**2+nucdipmomcl(3,iclass)**2
     312              :      if( (natomcl(iclass)<natom0 &
     313              : &          .and. .not. (spinatcl20>tolsym .and. spinatcl2<tolsym) &
     314              : &          .and. .not. (nucdipmomcl20>tolsym .and. nucdipmomcl2<tolsym) )  &
     315              : &     .or. (spinatcl20<tolsym .and. spinatcl2>tolsym) &
     316        11602 : &     .or. (nucdipmomcl20<tolsym .and. nucdipmomcl2>tolsym)) then
     317         5985 :        iclass0=iclass
     318         5985 :        natom0=natomcl(iclass)
     319         5985 :        spinatcl20=spinatcl2
     320         5985 :        nucdipmomcl20=nucdipmomcl2
     321              :      end if
     322              :    end do
     323              :  end if
     324              : 
     325        18005 :  printed=0
     326              : 
     327              : !If non-collinear spinat have to be used, transfer them in reduced coordinates
     328        18005 :  if (nspden==4) then
     329         1068 :    ABI_MALLOC(spinatred,(3,natom))
     330         1866 :    do iatom=1,natom
     331         5862 :      do ii=1,3
     332         5328 :        spinatred(1:3,iatom)=MATMUL(TRANSPOSE(gprimd),spinat(1:3,iatom))
     333              :      end do
     334              :    end do
     335              :  end if
     336              : 
     337              : !write(std_out,*)' '
     338              : !write(std_out,*)' symfind : has selected iclass0=',iclass0
     339              : !write(std_out,*)'  # iatom  xred                          spinat       (spinatred if nspden=4) '
     340              : !do iatom0=1,natomcl(iclass0)
     341              : !iatom=class(iatom0,iclass0)
     342              : !if(nspden/=4)then
     343              : !  write(std_out,'(2i4,6f10.4)' )iatom0,iatom,xred(:,iatom),spinat(:,iatom)
     344              : !else if(nspden==4)then
     345              : !  write(std_out,'(2i4,9f10.4)' )iatom0,iatom,xred(:,iatom),spinat(:,iatom),spinatred(:,iatom)
     346              : !endif
     347              : !end do
     348              : !write(std_out,*)' '
     349              : 
     350              :  !represent nuclear dipole moments in reduced coords
     351        36010 :  ABI_MALLOC(nucdipmomred,(3,3,natom))
     352        62525 :  do iatom=1,natom
     353       196085 :     do ii=1,3
     354       178080 :        nucdipmomred(1:3,ii,iatom)=MATMUL(TRANSPOSE(gprimd),local_nucdipmom(1:3,ii,iatom))
     355              :     end do
     356              :  end do
     357              : 
     358              : !write(std_out,'(a)')' m_symfind%symfind : before big loop '; call flush(std_out)
     359              : 
     360              : !Big loop over each symmetry operation of the Bravais lattice
     361        18005 :  nsym=0
     362       754453 :  do isym=1,nptsym
     363              : 
     364              : !write(std_out,'(a,i4)')' m_symfind%symfind : enter loop isym=',isym; call flush(std_out)
     365              : 
     366       736448 :    if(present(invardir_red))then
     367              : !    ji: Check whether symmetry operation leaves invardir_red invariant
     368              :      invardir_red_rot(:) = ptsymrel(:,1,isym)*invardir_red(1) +  &
     369              : &     ptsymrel(:,2,isym)*invardir_red(2) +  &
     370      2910688 : &     ptsymrel(:,3,isym)*invardir_red(3)
     371      2910688 :      diff(:)=invardir_red(:)-invardir_red_rot(:)
     372       727672 :      if( (diff(1)**2+diff(2)**2+diff(3)**2) > tolsym**2 ) cycle
     373              :    endif
     374              : 
     375              : ! check whether symmetry operation leaves invaraxial_red invariant (axial vector)
     376       733488 :   if(present(invaraxial_red))then
     377              : !!    CALL MatrixHyb_getDet(symref_hyb(isym), detR)
     378      9421256 :     mm(:,:) = ptsymrel(:,:,isym)
     379       724712 :     call mati3det(mm,detR)
     380              :     invaraxial_red_rot(:) = detR * (&
     381              :       ptsymrel(:,1,isym)*invaraxial_red(1) +  &
     382              : &     ptsymrel(:,2,isym)*invaraxial_red(2) +  &
     383      2898848 : &     ptsymrel(:,3,isym)*invaraxial_red(3) )
     384      2898848 :     diff(:)=invaraxial_red(:)-invaraxial_red_rot(:)
     385              : 
     386       724712 :     if( (diff(1)**2+diff(2)**2+diff(3)**2) > tolsym**2 ) cycle
     387              :    endif
     388              : 
     389              : !write(std_out,'(a,i4)')' m_symfind%symfind : 1'; call flush(std_out)
     390              : 
     391              :    det=ptsymrel(1,1,isym)*ptsymrel(2,2,isym)*ptsymrel(3,3,isym)+&
     392              : &     ptsymrel(2,1,isym)*ptsymrel(3,2,isym)*ptsymrel(1,3,isym)+&
     393              : &     ptsymrel(1,2,isym)*ptsymrel(2,3,isym)*ptsymrel(3,1,isym) - &
     394              : &     (ptsymrel(3,1,isym)*ptsymrel(2,2,isym)*ptsymrel(1,3,isym)+&
     395              : &     ptsymrel(2,1,isym)*ptsymrel(1,2,isym)*ptsymrel(3,3,isym)+&
     396       732704 : &     ptsymrel(3,2,isym)*ptsymrel(2,3,isym)*ptsymrel(1,1,isym))
     397       732704 :    if(use_inversion==0 .and. det==-1) cycle
     398              : 
     399              : !write(std_out,'(a,i4)')' m_symfind%symfind : 2'; call flush(std_out)
     400              : 
     401              : !  jellium slab and spatially varying chemical potential cases:
     402              : !  (actually, an inversion symmetry/mirror plane perpendicular to z symmetry operation might still be allowed... TO BE DONE !)
     403       722436 :    if(present(invar_z))then
     404       713668 :      if (invar_z/=0) then
     405              : !      check whether symmetry operation produce a rotation only in the xy plane
     406              :        if (ptsymrel(1,3,isym)/=0 .or. ptsymrel(2,3,isym)/=0 .or. &
     407         1856 :            ptsymrel(3,1,isym)/=0 .or. ptsymrel(3,2,isym)/=0 ) cycle
     408              : !      check whether symmetry operation does not change the z
     409          832 :        if( ptsymrel(3,3,isym)/=1 ) cycle
     410              :      end if
     411              :    end if
     412              : 
     413              : !write(std_out,'(a,i4)')' m_symfind%symfind : 3'; call flush(std_out)
     414              : 
     415              : !  If noncoll_orthorhombic=1, require orthorhombic operations of symmetries, except if spinat=0.
     416       720996 :    if (nspden==4 .and. noncoll_orthorhombic==1)then
     417            0 :      if(sum(abs(spinat(:,:)))>tol14)then
     418              :        if( ptsymrel(1,3,isym)/=0 .or. ptsymrel(2,3,isym)/=0 .or. &
     419              : &          ptsymrel(1,2,isym)/=0 .or. ptsymrel(3,2,isym)/=0 .or. &
     420            0 : &          ptsymrel(2,1,isym)/=0 .or. ptsymrel(3,2,isym)/=0 ) cycle
     421              :      endif
     422              :    endif
     423              : 
     424              : !write(std_out,'(a,i4)')' m_symfind%symfind : 4'; call flush(std_out)
     425              : 
     426              : !  Select a tentative set of associated translations
     427              : !  First compute the symmetric of the first atom in the smallest class,
     428              : !  using the point symmetry, and also the symmetric of spinat(red).
     429       720996 :    iatom0=class(1,iclass0)
     430              :    xred0(:)=ptsymrel(:,1,isym)*xred(1,iatom0)+ &
     431              :             ptsymrel(:,2,isym)*xred(2,iatom0)+ &
     432      2883984 :             ptsymrel(:,3,isym)*xred(3,iatom0)
     433       720996 :    if (nspden/=4) then
     434      2831344 :      spinat0(:)=spinat(:,iatom0)
     435              :    else
     436              :      spinat0(:)=det*(&
     437              :             ptsymrel(:,1,isym)*spinatred(1,iatom0)+ &
     438              : &           ptsymrel(:,2,isym)*spinatred(2,iatom0)+ &
     439        52640 : &           ptsymrel(:,3,isym)*spinatred(3,iatom0))
     440              :      ! spinat should be treated as an axial vector
     441              :      ! i.e. the improper part of a symm. op. has no effect on spinat
     442              :    endif
     443              : 
     444              : !write(std_out,'(a,i4)')' m_symfind%symfind : 5'; call flush(std_out)
     445              : 
     446              : !  From the set of possible images, deduce tentative translations,
     447              : !  and magnetic factor then test whether it send each atom on a symmetric one
     448              :    ntrial=0
     449      2012161 :    do ii=1,natom0
     450              :      !write(std_out,'(a,2i4)')' symfind : loop isym,ii=',isym,ii
     451      1273160 :      iatom1=class(ii,iclass0)
     452              : 
     453              : !    The tentative translation is found
     454      5092640 :      trialnons(:)=xred(:,iatom1)-xred0(:)
     455              : !    Compare the spinat vectors
     456      1273160 :      if (nspden/=4) then
     457      5013808 :        symspinat1(:)=spinat(:,iatom1)
     458              :      else
     459        78832 :        symspinat1(:)=spinatred(:,iatom1)
     460              :      end if
     461              : 
     462              :      !write(std_out,'(a,6f10.4)')' symspinat1,spinat0=',symspinat1(:),spinat0(:)
     463              : 
     464      1273160 :      trialafm=1
     465      5092640 :      if(sum(abs(symspinat1(:)-spinat0(:)))>tolsym)then
     466        16318 :        trialafm=-1
     467        16318 :        if(nspden==4 .and. afm_noncoll==0)cycle
     468        65272 :        if(sum(abs(symspinat1(:)+spinat0(:)))>tolsym)cycle
     469              :      endif
     470              : 
     471      5055360 :      if(sum(abs(local_nucdipmom(:,1,iatom1)-local_nucdipmom(:,1,iatom0)))>tolsym)then
     472              :        write(msg,'(3a,3i5)')&
     473            0 :        'Problem with matching the nuclear dipole moment within a class.',ch10,&
     474            0 :        'isym,iatom0,iatom1=',isym,iatom0,iatom1
     475            0 :        ABI_ERROR(msg)
     476              :      end if
     477              : 
     478              : !    jellium slab case: check whether symmetry operation has no translational
     479              : !    component along z
     480      1263840 :      if(present(invar_z))then
     481      1250772 :        if( invar_z==2 .and. abs(trialnons(3)) > tolsym ) cycle
     482              :      endif
     483              :      trialok=1
     484              : 
     485              : !     write(std_out, '(a,i3,a,i3,a,i3,a,3f12.4,i3)') ' Try isym=',isym,' sending iatom0 ',iatom0,' to iatom1 ',iatom1,' with trialnons(:),trialafm =',trialnons(:),trialafm
     486              : 
     487              : !    Loop over all classes, then all atoms in the class,
     488              : !    to find whether they have a symmetric
     489      2070394 :      do iclass=1,nclass
     490      4162874 :        do jj=1,natomcl(iclass)
     491              : 
     492      3356320 :          iatom2=class(jj,iclass)
     493              : !        Generate the tentative symmetric position of iatom2
     494              :          symxred2(:)=ptsymrel(:,1,isym)*xred(1,iatom2)+ &
     495              : &         ptsymrel(:,2,isym)*xred(2,iatom2)+ &
     496     13425280 : &         ptsymrel(:,3,isym)*xred(3,iatom2)+ trialnons(:)
     497              : !        Generate the tentative symmetric spinat of iatom2
     498      3356320 :          if (nspden/=4) then
     499     13327616 :            symspinat2(:)=trialafm*spinat(:,iatom2)
     500              :          else
     501              :            symspinat2(:)=trialafm*det*(ptsymrel(:,1,isym)*spinatred(1,iatom2)+ &
     502              : &           ptsymrel(:,2,isym)*spinatred(2,iatom2)+ &
     503        97664 : &           ptsymrel(:,3,isym)*spinatred(3,iatom2))
     504              :          end if
     505              :          !        Generate the tentative symmetric nucdipmom of iatom2
     506     13425280 :          do kk = 1, 3
     507              :             symnucdipmom2red(:,kk)=ptsymrel(:,1,isym)*nucdipmomred(1,kk,iatom2)+ &
     508              :                  &           ptsymrel(:,2,isym)*nucdipmomred(2,kk,iatom2)+ &
     509     40275840 :                  &           ptsymrel(:,3,isym)*nucdipmomred(3,kk,iatom2)
     510              :             ! transform back to cart coords for final comparison to nucdipmom
     511    164459680 :             symnucdipmom2cart(:,kk)=MATMUL(rprimd,symnucdipmom2red(:,kk))
     512              :          end do
     513              : 
     514              : !        write(std_out,'(a,i4,a,3f8.4,a,3f8.4,a,3f8.4)')&
     515              : !           ' Test iatom2=',iatom2,' at xred=',xred(:,iatom2),'. Is sent to',symxred2(:),' with symspinat2=',symspinat2(:)
     516              : !        write(std_out,'(a,3f8.4)')' and nucdipmom2=',symnucdipmom2cart(:,1)
     517              : 
     518              : !        Check whether there exists an atom of the same class at the
     519              : !        same location, with the correct spinat and nuclear dipole moment circulation
     520     28436716 :          do kk=1,natomcl(iclass)
     521              : 
     522     27760693 :            found3=1
     523     27760693 :            iatom3=class(kk,iclass)
     524              : !          Check the location
     525     27760693 :            diffr1=xred(1,iatom3)-symxred2(1)
     526     27760693 :            diff1=diffr1-nint(diffr1)
     527     27760693 :            if(diff1**2>tolsym2)then
     528              :              found3=0 ; cycle
     529              :            else
     530      6100390 :              diffr2=xred(2,iatom3)-symxred2(2)
     531      6100390 :              diff2=diffr2-nint(diffr2)
     532      6100390 :              if(diff2**2>tolsym2)then
     533              :                found3=0 ; cycle
     534              :              else
     535      3300059 :                diffr3=xred(3,iatom3)-symxred2(3)
     536      3300059 :                diff3=diffr3-nint(diffr3)
     537      3300059 :                if( (diff1**2+diff2**2+diff3**2) > tolsym**2 )then
     538              :                  found3=0 ; cycle
     539              :                endif
     540              :              endif
     541              :            endif
     542              : !          Check the spinat
     543      2682689 :            if (nspden/=4) then
     544     10650892 :              diff(:)=spinat(:,iatom3)-symspinat2(:)
     545              :            else
     546        79864 :              diff(:)=spinatred(:,iatom3)-symspinat2(:)
     547              :            end if
     548      2682689 :            if( (diff(1)**2+diff(2)**2+diff(3)**2) > tolsym**2 )then
     549              :              found3=0
     550              :              cycle
     551              :            endif
     552              :            ! Check the nucdipmom
     553              :            ! hand3 gives original circulation sense of nuclear dipole
     554      2682497 :            call acrossb(local_nucdipmom(1:3,2,iatom3),local_nucdipmom(1:3,3,iatom3),hand3)
     555              : 
     556              :            ! hand2 gives circulation sense of tentative, symmetry equivalent nuclear dipole
     557      2682497 :            call acrossb(symnucdipmom2cart(1:3,2),symnucdipmom2cart(1:3,3),hand2)
     558              : 
     559     10729988 :            diff(:)=hand3(:)-hand2(:)
     560     10723804 :            if( any(abs(diff)>tolsym) )found3=0
     561              : 
     562              :            !diff(:)=symnucdipmom2cart(:,1) - local_nucdipmom(:,1,iatom3)
     563              :            !if ( any(abs(diff)>tolsym) ) found3=0
     564              : 
     565       676023 :            if(found3==1)exit
     566              :          end do ! End loop over iatom3
     567              : 
     568      4162874 :          if(found3==0)then
     569              :            trialok=0
     570              :            exit
     571              :          end if
     572              :        end do ! End loop over iatom2
     573              : 
     574      2070394 :        if(trialok==0)exit
     575              :      end do ! End loop over all classes
     576              : 
     577              :      !write(std_out,*)' For trial isym=',isym,', trialok = ',trialok
     578              :      !write(std_out,*)' '
     579              : 
     580      2000288 :      if(trialok==1)then
     581       587817 :        nsym=nsym+1
     582       587817 :        if(nsym>msym)then
     583              :          write(msg,'(a,i0,2a,i0,4a)')&
     584            0 :          'The number of symmetries (including non-symmorphic translations) is: ', nsym, ch10,&
     585            0 :          'is larger than maxnsym: ',msym,ch10,&
     586            0 :          'Action: increase maxnsym in the input, or take a cell that is primitive, ',ch10,&
     587            0 :          'or at least smaller than the present one.'
     588            0 :         ABI_ERROR(msg)
     589              :        end if
     590              :        ntrial=ntrial+1
     591      7641621 :        symrel(:,:,nsym)=ptsymrel(:,:,isym)
     592       587817 :        symafm(nsym)=trialafm
     593      2351268 :        tnons(:,nsym)=trialnons(:)-nint(trialnons(:)-tolsym)
     594              :      end if
     595              : 
     596              :    end do ! End the loop on tentative translations
     597              :  end do ! End big loop over each symmetry operation of the Bravais lattice
     598              : 
     599              : !write(std_out,'(a)')' m_symfind%symfind : after big loop, will call ABI_FREE '; call flush(std_out)
     600              : 
     601        18005 :  ABI_FREE(class)
     602        18005 :  ABI_FREE(natomcl)
     603        18005 :  ABI_FREE(chrgat_)
     604        18005 :  ABI_FREE(chrgatcl)
     605        18005 :  ABI_FREE(spinatcl)
     606        18005 :  ABI_FREE(typecl)
     607        18005 :  ABI_FREE(local_nucdipmom)
     608        18005 :  ABI_FREE(nucdipmomcl)
     609        18005 :  ABI_FREE(nucdipmomred)
     610        18005 :  if (nspden==4)   then
     611          534 :    ABI_FREE(spinatred)
     612              :  end if
     613              : 
     614              : !write(std_out,'(a,i6)')' m_symfind%symfind : call sg_multable, nsym= ',nsym; call flush(std_out)
     615              : 
     616              : ! The algorithm in sg_multable is still cubic in nsym, so avoid calling it uselessly when nsym is too large
     617        18005 :  if(present(ierr) .or. nsym<=384)then
     618        18005 :    call sg_multable(nsym, symafm, symrel, ierr_, tnons=tnons, tnons_tol=tolsym)
     619              :  else
     620            0 :    ierr_=0
     621              :  endif
     622              : 
     623              : !write(std_out,'(a)')' m_symfind%symfind : call print_symmetries, ierr_= ',ierr_; call flush(std_out)
     624              : 
     625        18006 :  if (ierr_/=0) call print_symmetries([std_out], nsym, symrel, tnons, symafm)
     626              : 
     627        18005 :  if(.not.present(ierr))then
     628         9080 :    ABI_CHECK(ierr_==0,"Error in group closure")
     629              :  else
     630         8925 :    ierr=ierr_
     631              :  endif
     632              : 
     633              : !write(msg,'(a,I0,es16.6,a)')' symfind : exit, nsym, tolsym=',nsym,tolsym,ch10
     634              : !write(msg,'(2a)') trim(msg),'   symrel matrices, symafm and tnons are :'
     635              : !call wrtout(std_out,msg)
     636              : !do isym=1,nsym
     637              : !  write(msg,'(i4,4x,3i4,2x,3i4,2x,3i4,4x,i4,4x,3f8.4)' ) isym,symrel(:,:,isym),symafm(isym),tnons(:,isym)
     638              : !  call wrtout(std_out,msg)
     639              : !end do
     640              : !stop
     641              : 
     642              : !write(std_out,'(a)')' m_symfind%symfind : exit '; call flush(std_out)
     643              : 
     644        53803 : end subroutine symfind
     645              : !!***
     646              : 
     647              : !!****f* m_symfind/symfind_expert
     648              : !! NAME
     649              : !! symfind_expert
     650              : !!
     651              : !! FUNCTION
     652              : !! Symmetry finder, with an added layer of robustness compared to symfind,
     653              : !! and for which resymmetrization of atomic positions and tnons is needed..
     654              : !! From the symmetries of the Bravais lattice (ptsymrel),
     655              : !! select those that leave invariant the system, and generate
     656              : !! the corresponding tnons vectors and symafm information.
     657              : !! Unlike symfind_expert, does NOT resymmetrize atomic positions and tnons for more robust determination of the symmetries.
     658              : !! The algorithm is explained in T.G. Worlton and J.L. Warren, Comp. Phys. Comm. 3, 88 (1972) [[cite:Worton1972]]
     659              : !!
     660              : !! INPUTS
     661              : !! chrgat(natom) (optional)=target charge for each atom. Not always used, it depends on the value of constraint_kind
     662              : !! invardir_red (optional)=reduced coordinates of an invariant direction (only acting with symrel - not tnons)
     663              : !! invaraxial_red (optional)=reduced coordinates of an axial vector, similar to invardir_red, but transforms with an additional
     664              : !!                           deteminant factor under symrel operations
     665              : !! invar_z (optional)= if 1, the z direction must stay invariant for all symrel applied ;
     666              : !!                     if 2, z must stay invariant and also there cannot be any associated tnons along z.
     667              : !! gprimd(3,3)=dimensional primitive translations for reciprocal space
     668              : !! msym=default maximal number of symmetries
     669              : !! natom=number of atoms in cell.
     670              : !! nptsym=number of point symmetries of the Bravais lattice
     671              : !! nspden= number of spin-density components. When 4, the three components of spinat are taken into account, instead of only z-component.
     672              : !! nucdipmom(3,natom) (optional) array of nuclear dipole moments
     673              : !  pawspnorb=flag: 1 if spin-orbit coupling is activated
     674              : !! ptsymrel(3,3,1:msym)= nptsym point-symmetry operations
     675              : !!   of the Bravais lattice in real space in terms of primitive translations.
     676              : !! spinat(3,natom)=initial spin of each atom, in unit of hbar/2.
     677              : !! tolsym=tolerance for the symmetries
     678              : !! typat(natom)=integer identifying type of atom.
     679              : !! usepaw= 0 for non paw calculation; =1 for paw calculation
     680              : !!
     681              : !! OUTPUT
     682              : !! nsym=actual number of symmetries
     683              : !! symafm(1:msym)=(anti)ferromagnetic part of nsym symmetry operations
     684              : !! symrel(3,3,1:msym)= nsym symmetry operations in real space in terms of primitive translations
     685              : !! tnons(3,1:msym)=nonsymmorphic translations for each symmetry (would be 0 0 0 each for a symmorphic space group)
     686              : !!
     687              : !! SIDE EFFECTS
     688              : !! xred(3,natom)=reduced coordinates of atoms in terms of real space
     689              : !!   primitive translations. Might be changed during the resymmetrization.
     690              : !!
     691              : !! SOURCE
     692              : 
     693         8924 : subroutine symfind_expert(gprimd,msym,natom,nptsym,nspden,nsym,&
     694         8924 :   pawspnorb,prtvol,ptsymrel,spinat,symafm,symrel,tnons,tolsym,typat,usepaw,xred,&
     695              :   chrgat,nucdipmom,invardir_red,invaraxial_red,invar_z)  ! Optional - although for the time being all are required ...
     696              : 
     697              : !Arguments ------------------------------------
     698              : !scalars
     699              :  integer,intent(in) :: msym,natom,nptsym,nspden,pawspnorb,usepaw
     700              :  integer,intent(in) :: prtvol
     701              :  integer,optional,intent(in) :: invar_z
     702              :  integer,intent(out) :: nsym
     703              :  real(dp),intent(in) :: tolsym
     704              : !arrays
     705              :  integer,intent(in) :: ptsymrel(3,3,msym),typat(natom)
     706              :  integer,intent(inout) :: symafm(msym),symrel(3,3,msym) !vz_i
     707              :  real(dp),intent(in) :: gprimd(3,3),spinat(3,natom)
     708              :  real(dp),intent(inout) :: xred(3,natom)
     709              :  real(dp),optional,intent(in) :: invardir_red(3),invaraxial_red(3),chrgat(natom)
     710              :  real(dp),optional, intent(in) :: nucdipmom(3,natom)
     711              :  real(dp),intent(inout) :: tnons(3,msym) !vz_i
     712              : 
     713              : !Local variables-------------------------------
     714              : !scalars
     715              :  integer, save :: print_comment_tolsym=1
     716              :  integer :: fixed_mismatch,mismatch_fft_tnons
     717              :  integer :: ierr,isym,use_inversion
     718              :  character(len=1000) :: msg
     719              : !arrays
     720         8924 :  integer,allocatable :: indsym(:,:,:),symrec(:,:,:)
     721         8924 :  real(dp),allocatable :: tnons_new(:,:)
     722              : !**************************************************************************
     723              : 
     724              : ! write(std_out,*)' m_symfind%symfind_expert : enter '
     725              : 
     726         8924 :  use_inversion=1
     727         8924 :  if (usepaw == 1 .and. (nspden==4.or.pawspnorb>0)) then
     728          237 :    ABI_COMMENT("Removing inversion and improper rotations from initial space group because of PAW + SOC")
     729              :    ! MMignolet: PAW can be used with inversion, however it results in seg faults in the dmft code. To enable when this is fixed...
     730          237 :    use_inversion=0
     731              :  end if
     732              : 
     733              :  ! write(std_out,*)' m_symfind%symfind_expert : before call symfind (1) '
     734              : 
     735              :  call symfind(gprimd,msym,natom,nptsym,nspden,nsym,&
     736              :    prtvol,ptsymrel,spinat,symafm,symrel,tnons,tolsym,typat,use_inversion,xred,&
     737         8924 :    chrgat=chrgat,nucdipmom=nucdipmom,ierr=ierr,invardir_red=invardir_red,invaraxial_red=invaraxial_red,invar_z=invar_z)
     738              : 
     739              :   ! write(std_out,*)' m_symfind%symfind_expert : after call symfind (1) '
     740              : 
     741              :   !If the group closure is not obtained, which should be exceptional, try with a larger tolsym (three times larger)
     742         8924 :   if(ierr/=0)then
     743            1 :     ABI_WARNING('Will try to obtain group closure by using a tripled tolsym.')
     744              :     call symfind(gprimd,msym,natom,nptsym,nspden,nsym,&
     745              :       prtvol,ptsymrel,spinat,symafm,symrel,tnons,three*tolsym,typat,use_inversion,xred,&
     746            1 :       chrgat=chrgat,nucdipmom=nucdipmom,ierr=ierr,invardir_red=invardir_red,invaraxial_red=invaraxial_red,invar_z=invar_z)
     747            1 :     ABI_CHECK(ierr==0,"Error in group closure")
     748            1 :     ABI_WARNING('Succeeded to obtain group closure by using a tripled tolsym.')
     749              :   endif
     750              : 
     751              :   ! If the tolerance on symmetries is bigger than 1.e-8, symmetrize tnons for gliding or screw operations,
     752              :   ! symmetrize the atomic positions and recompute the symmetry operations
     753         8924 :   if(tolsym>1.00001e-8)then
     754              : 
     755         8868 :     call symmetrize_tnons(nsym,symrel,tnons,tolsym)
     756        35472 :     ABI_MALLOC(indsym,(4,natom,nsym))
     757        26604 :     ABI_MALLOC(symrec,(3,3,nsym))
     758       298124 :     do isym=1,nsym
     759       298124 :       call mati3inv(symrel(:,:,isym),symrec(:,:,isym))
     760              :     end do
     761         8868 :     call symatm(indsym,natom,nsym,symrec,tnons,tolsym,typat,xred)
     762         8868 :     call symmetrize_xred(natom,nsym,symrel,tnons,xred,indsym=indsym)
     763         8868 :     ABI_FREE(indsym)
     764         8868 :     ABI_FREE(symrec)
     765              : 
     766         8868 :     if(print_comment_tolsym==1)then
     767              :       write(msg,'(a,es12.3,18a)')&
     768         1360 :         'The tolerance on symmetries =',tolsym,' is bigger than 1.0e-8.',ch10,&
     769         1360 :         'In order to avoid spurious effects, the atomic coordinates have been',ch10,&
     770         1360 :         'symmetrized before storing them in the dataset internal variable.',ch10,&
     771         1360 :         'So, do not be surprised by the fact that your input variables (xcart, xred, ...)',ch10,&
     772         1360 :         'do not correspond exactly to the ones echoed by ABINIT, the latter being used to do the calculations.',ch10,&
     773         1360 :         'This is not a problem per se.',ch10,&
     774         1360 :         'Still, in order to avoid this symmetrization (e.g. for specific debugging/development),',&
     775         1360 :         ' decrease tolsym to 1.0e-8 or lower,',ch10,&
     776         1360 :         'or (much preferred) use input primitive vectors that are accurate to better than 1.0e-8.',ch10,&
     777         2720 :         'This message will only be printed once, even if there are other datasets where tolsym is bigger than 1.0e-8.'
     778         1360 :       ABI_COMMENT(msg)
     779         1360 :       print_comment_tolsym=0
     780              :     endif
     781              : 
     782              : !write(std_out,*)' m_symfind%symfind_expert : before call symfind (3) '
     783              : 
     784              :     call symfind(gprimd,msym,natom,nptsym,nspden,nsym,&
     785              :       prtvol,ptsymrel,spinat,symafm,symrel,tnons,tolsym,typat,use_inversion,xred,&
     786         8868 :       chrgat=chrgat,nucdipmom=nucdipmom,invardir_red=invardir_red,invaraxial_red=invaraxial_red,invar_z=invar_z)
     787              : 
     788              : ! write(std_out,*)' m_symfind%symfind_expert : after call symfind (3) '
     789              : 
     790              :     !Needs one more resymmetrization, for the tnons
     791        26604 :     ABI_MALLOC(tnons_new,(3,nsym))
     792              : 
     793              :     call symmetrize_xred(natom,nsym,symrel,tnons,xred,&
     794         8868 :       fixed_mismatch=fixed_mismatch,mismatch_fft_tnons=mismatch_fft_tnons,tnons_new=tnons_new,tolsym=tolsym)
     795      1165892 :     tnons(:,1:nsym)=tnons_new(:,:)
     796        26604 :     ABI_FREE(tnons_new)
     797              :   end if ! tolsym >1.00001e-8
     798              : 
     799              : ! write(std_out,*)' m_symfind%symfind_expert : exit '
     800              : 
     801         8924 : end subroutine symfind_expert
     802              : !!***
     803              : 
     804              : !!****f* m_symfind/symanal
     805              : !! NAME
     806              : !! symanal
     807              : !!
     808              : !! FUNCTION
     809              : !! Find the space group, Bravais lattice, including Shubnikov characteristics
     810              : !! from the list of symmetries (including magnetic characteristics), and lattice parameters
     811              : !! Warning: the recognition of the space group might not yet work for the
     812              : !! Shubnikov group of type IV
     813              : !!
     814              : !! INPUTS
     815              : !! chkprim= if 1 then stop if the cell is not primitive
     816              : !! msym=default maximal number of symmetries
     817              : !! nsym=actual number of symmetries
     818              : !! rprimd(3,3)=dimensional primitive translations for real space (bohr)
     819              : !! symafm(1:msym)=(anti)ferromagnetic part of symmetry operations
     820              : !! symrel(3,3,1:msym)=symmetry operations in real space in terms
     821              : !!  of primitive translations
     822              : !! tnons(3,1:msym)=nonsymmorphic translations for symmetry operations
     823              : !! tolsym=tolerance for the symmetry operations
     824              : !! [verbose]= if true, will list the symmetry operation labels
     825              : !!
     826              : !! OUTPUT
     827              : !! bravais(11)=characteristics of Bravais lattice (see symlatt.F90)
     828              : !! genafm(3)=magnetic translation generator (in case of Shubnikov group type IV)
     829              : !! ptgroupma = magnetic point group number
     830              : !! spgroup=symmetry space group
     831              : !!
     832              : !! SOURCE
     833              : 
     834        11934 : subroutine symanal(bravais,chkprim,genafm,msym,nsym,ptgroupma,rprimd,spgroup,symafm,symrel,tnons,tolsym, &
     835              :                    verbose) ! optional
     836              : 
     837              : !Arguments ------------------------------------
     838              : !scalars
     839              :  integer,intent(in) :: chkprim,msym,nsym
     840              :  integer,intent(out) :: ptgroupma,spgroup
     841              :  real(dp),intent(in) :: tolsym
     842              :  logical,optional,intent(in) :: verbose
     843              : !arrays
     844              :  integer,intent(out) :: bravais(11)
     845              :  integer,intent(in) :: symafm(msym),symrel(3,3,msym)
     846              :  real(dp),intent(in) :: rprimd(3,3), tnons(3,msym)
     847              :  real(dp),intent(out) :: genafm(3)
     848              : 
     849              : !Local variables-------------------------------
     850              : !scalars
     851              :  integer, parameter :: maxsym=192
     852              : ! In this routine, maxsym is used either to determine the ptsymrel from the rprimd (routine symlatt),
     853              : ! so, it might be up to 192 = 4*48 for FCC, and also to define the maximum number of symmetry operation labels,
     854              : ! but only in case the cell is primitive, which gives the same upper bound. Thus in this routine, msym might
     855              : ! be equal to nsym.
     856              :  integer :: iholohedry_nomagn,isym,isym_nomagn,multi, nptsym,nsym_nomagn,shubnikov
     857              :  logical :: verbose_
     858              :  character(len=5) :: ptgroup,ptgroupha
     859              :  character(len=500) :: msg
     860              : !arrays
     861              :  integer :: identity(3,3)
     862        11934 :  integer,allocatable :: ptsymrel(:,:,:),symrel_nomagn(:,:,:)
     863        11934 :  real(dp),allocatable :: tnons_nomagn(:,:)
     864              :  character(len=128) :: labels(maxsym)
     865              : ! *************************************************************************
     866              : 
     867              : !write(std_out,*)' symanal : enter'
     868              : !write(std_out,*)' symanal : chkprim =',chkprim
     869              : !write(std_out,*)' symanal : nsym=',nsym
     870              : !do isym=1,nsym
     871              : !  write(std_out,*)' symanal : symrel=',symrel(1:3,1:3,isym)
     872              : !enddo
     873              : 
     874        11934 :  verbose_=.false.
     875        11934 :  if (present(verbose)) verbose_=verbose
     876              : 
     877              : !This routine finds the Bravais characteristics, without actually looking at the symmetry operations.
     878        11934 :  ABI_MALLOC(ptsymrel,(3,3,maxsym))
     879        11934 :  call symlatt(bravais,dev_null,maxsym,nptsym,ptsymrel,rprimd,tolsym)
     880        11934 :  ABI_FREE(ptsymrel)
     881              : 
     882              :  ! Check whether the cell is primitive or not.
     883        11934 :  call chkprimit(chkprim,multi,nsym,symafm,symrel)
     884              : 
     885        11934 :  spgroup=0 ; ptgroupma=0 ; genafm(:)=zero
     886              : 
     887        11934 :  if (multi>1) then ! Modify bravais if the cell is not primitive ; no determination of the space group
     888          289 :    bravais(1)=-bravais(1)
     889              :  else
     890              : 
     891              :    ! The cell is primitive, so that the space group can be
     892              :    ! determined. Need to distinguish Fedorov and Shubnikov groups.
     893              :    ! Do not distinguish Shubnikov types I and II.
     894              :    ! Also identify genafm, in case of Shubnikov type IV
     895        11645 :    identity(:,:)=reshape((/1,0,0,0,1,0,0,0,1/),(/3,3/))
     896        11645 :    shubnikov=1
     897       297715 :    do isym=1,nsym
     898       297715 :      if(symafm(isym)==-1)then
     899         5740 :        shubnikov=3
     900        74620 :        if(sum(abs(symrel(:,:,isym)-identity(:,:)))==0)then
     901          607 :          shubnikov=4
     902         2428 :          genafm(:)=tnons(:,isym)
     903              :          !write(std_out,*)' isym=',isym
     904              :          !write(std_out,*)' symrel(:,:,isym)',symrel(:,:,isym)
     905              :          !write(std_out,*)' tnons(:,isym)',tnons(:,isym)
     906              :          !write(std_out,*)' symafm(isym)',symafm(isym)
     907              :          exit
     908              :        end if
     909              :      end if
     910              :    end do
     911              : 
     912        11645 :    if(shubnikov/=1)then
     913         1505 :      if(shubnikov==3)write(msg, '(a)' )' Shubnikov space group type III'
     914         1505 :      if(shubnikov==4)write(msg, '(a)' )' Shubnikov space group type IV'
     915         1505 :      call wrtout(std_out,msg)
     916              :    end if
     917              : 
     918        11645 :    if(shubnikov==1 .or. shubnikov==3)then
     919              :      ! Find the correct Bravais characteristics and point group
     920              :      ! Should also be used for Shubnikov groups of type IV ...
     921        11038 :      call symbrav(bravais,msym,nsym,ptgroup,rprimd,symrel,tolsym)
     922              : 
     923              :      ! Find the space group
     924        11038 :      call symspgr(bravais,labels,nsym,spgroup,symrel,tnons,tolsym)
     925              : 
     926        11038 :      if (verbose_) then
     927         2275 :        do isym=1,nsym
     928         2203 :          write(msg,'(a,i3,2a)')' symanal : the symmetry operation no. ',isym,' is ',trim(labels(isym))
     929         2275 :          call wrtout(std_out,msg)
     930              :        enddo
     931              :      endif
     932              : 
     933              :    end if
     934              : 
     935        11038 :    if (shubnikov/=1) then
     936              : 
     937              :      ! Determine nonmagnetic symmetry operations
     938         1505 :      nsym_nomagn=nsym/2
     939         4515 :      ABI_MALLOC(symrel_nomagn,(3,3,nsym_nomagn))
     940         4515 :      ABI_MALLOC(tnons_nomagn,(3,nsym_nomagn))
     941         1505 :      isym_nomagn=0
     942        23661 :      do isym=1,nsym
     943        23661 :        if(symafm(isym)==1)then
     944        11078 :          isym_nomagn=isym_nomagn+1
     945       144014 :          symrel_nomagn(:,:,isym_nomagn)=symrel(:,:,isym)
     946        44312 :          tnons_nomagn(:,isym_nomagn)=tnons(:,isym)
     947              :        end if
     948              :      end do
     949              : 
     950         1505 :      if (shubnikov==3) then
     951              : 
     952              :        ! write(std_out,*)' symanal : will enter symbrav with halved symmetry set'
     953              :        ! write(std_out,*)' Describe the different symmetry operations (index,symrel,tnons,symafm)'
     954              :        ! do isym=1,nsym_nomagn
     955              :        ! write(std_out,'(i3,2x,9i3,3es12.2,i3)')isym,symrel_nomagn(:,:,isym),tnons_nomagn(:,isym)
     956              :        ! end do
     957              : 
     958              :        ! Find the point group of the halved symmetry set
     959          898 :        call symptgroup(iholohedry_nomagn,nsym_nomagn,ptgroupha,symrel_nomagn)
     960              : 
     961              :        ! Deduce the magnetic point group (ptgroupma) from ptgroup and ptgroupha
     962          898 :        call getptgroupma(ptgroup,ptgroupha,ptgroupma)
     963              : 
     964          607 :      else if(shubnikov==4)then
     965              : 
     966              :        ! Find the Fedorov space group of the halved symmetry set
     967          607 :        call symspgr(bravais,labels,nsym_nomagn,spgroup,symrel_nomagn,tnons_nomagn,tolsym)
     968              : 
     969              :        ! The magnetic translation generator genafm has already been determined
     970              :        ! write(std_out,*)' genafm =',genafm, ' spgroup=',spgroup
     971          607 :        if (verbose_) then
     972            0 :          write(msg, '(a)' )' Select only the non-magnetic symmetry operations '
     973            0 :          call wrtout(std_out,msg)
     974              : 
     975            0 :          do isym=1,nsym
     976            0 :            if(symafm(isym)==1)then
     977            0 :              isym_nomagn=isym_nomagn+1
     978            0 :              write(msg,'(a,i3,2a)')' symspgr : the symmetry operation no. ',isym,' is ',trim(labels(isym_nomagn))
     979            0 :              call wrtout(std_out,msg)
     980              :            endif
     981              :          enddo
     982              :        endif
     983              : 
     984              :      end if
     985              : 
     986         1505 :      ABI_FREE(symrel_nomagn)
     987         1505 :      ABI_FREE(tnons_nomagn)
     988              :    end if ! Shubnikov groups
     989              : 
     990              :  end if
     991              : 
     992        11934 : end subroutine symanal
     993              : !!***
     994              : 
     995              : !!****f* m_symfind/symbrav
     996              : !! NAME
     997              : !! symbrav
     998              : !!
     999              : !! FUNCTION
    1000              : !! From the list of symmetry operations, and the lattice vectors,
    1001              : !! determine the Bravais information (including the holohedry, the centering,
    1002              : !! the coordinate of the primitive vectors in the conventional vectors),
    1003              : !! as well as the point group.
    1004              : !!
    1005              : !! INPUTS
    1006              : !! msym=dimension of symrel
    1007              : !! nsym=actual number of symmetries
    1008              : !! rprimd(3,3)=dimensional primitive translations for real space (bohr)
    1009              : !! symrel(3,3,msym)=symmetry operations in real space in terms
    1010              : !!                  of primitive translations
    1011              : !! tolsym=tolerance for the symmetries
    1012              : !!
    1013              : !! OUTPUT
    1014              : !! bravais(11): bravais(1)=iholohedry
    1015              : !!              bravais(2)=center
    1016              : !!              bravais(3:11)=coordinates of rprimd in the axes
    1017              : !!              of the conventional bravais lattice (*2 if center/=0)
    1018              : !! ptgroup=symmetry point group
    1019              : !! [axis(3)]=Invariant axis in the conventional vector coordinates
    1020              : !!   Set to (/0,0,0/) if the lattice belongs to the same holohedry as the lattice+atoms (+electric field + ...).
    1021              : !!
    1022              : !! SOURCE
    1023              : 
    1024        11038 : subroutine symbrav(bravais,msym,nsym,ptgroup,rprimd,symrel,tolsym,axis)
    1025              : 
    1026              : !Arguments ------------------------------------
    1027              : !scalars
    1028              :  integer,intent(in) :: msym,nsym
    1029              :  real(dp),intent(in) :: tolsym
    1030              :  character(len=5),intent(out) :: ptgroup
    1031              : !arrays
    1032              :  integer,intent(in) :: symrel(3,3,msym)
    1033              :  integer,optional,intent(out) :: axis(3)
    1034              :  integer,intent(out) :: bravais(11)
    1035              :  real(dp),intent(in) :: rprimd(3,3)
    1036              : 
    1037              : !Local variables-------------------------------
    1038              : !scalars
    1039              :  integer :: iaxis,ii,bravais1now,ideform,iholohedry,invariant,isym
    1040              :  integer :: jaxis,next_stage,nptsym,problem,maxsym
    1041              :  integer, parameter :: naxes_ortho=22, naxes_hexa=7
    1042              :  real(dp) :: norm,scprod
    1043              :  character(len=500) :: msg
    1044              : !arrays
    1045              :  integer :: identity(3,3),axis_trial(3),hexa_axes(3,naxes_hexa),ortho_axes(3,naxes_ortho)
    1046        11038 :  integer,allocatable :: ptsymrel(:,:,:),symrelconv(:,:,:)
    1047              :  real(dp) :: axes(3,3),axis_cart(3),axis_red(3)
    1048              :  real(dp) :: rprimdconv(3,3),rprimdtry(3,3),rprimdnow(3,3)
    1049              :  real(dp) :: rprimdconv_invt(3,3)
    1050              : !**************************************************************************
    1051              : 
    1052              : !DEBUG
    1053              : !write(std_out,*)' symbrav : enter '
    1054              : !call flush(std_out)
    1055              : !ENDDEBUG
    1056              : 
    1057              :  identity(:,:)=0
    1058        11038 :  identity(1,1)=1 ; identity(2,2)=1 ; identity(3,3)=1
    1059              : 
    1060        11038 :  ortho_axes(:,:)=0
    1061        11038 :  ortho_axes(1,1)=1
    1062        11038 :  ortho_axes(2,2)=1
    1063        11038 :  ortho_axes(3,3)=1
    1064        44152 :  ortho_axes(:,4)=(/0,1,1/)
    1065        44152 :  ortho_axes(:,5)=(/1,0,1/)
    1066        44152 :  ortho_axes(:,6)=(/1,1,0/)
    1067        44152 :  ortho_axes(:,7)=(/0,1,-1/)
    1068        44152 :  ortho_axes(:,8)=(/-1,0,1/)
    1069        44152 :  ortho_axes(:,9)=(/1,-1,0/)
    1070        44152 :  ortho_axes(:,10)=(/0,1,2/)
    1071        44152 :  ortho_axes(:,11)=(/2,0,1/)
    1072        44152 :  ortho_axes(:,12)=(/1,2,0/)
    1073        44152 :  ortho_axes(:,13)=(/1,1,1/)
    1074        44152 :  ortho_axes(:,14)=(/-1,1,1/)
    1075        44152 :  ortho_axes(:,15)=(/1,-1,1/)
    1076        44152 :  ortho_axes(:,16)=(/1,1,-1/)
    1077        44152 :  ortho_axes(:,17)=(/2,1,1/)
    1078        44152 :  ortho_axes(:,18)=(/1,2,1/)
    1079        44152 :  ortho_axes(:,19)=(/1,1,2/)
    1080        44152 :  ortho_axes(:,20)=(/2,1,-1/)
    1081        44152 :  ortho_axes(:,21)=(/-1,2,1/)
    1082        44152 :  ortho_axes(:,22)=(/1,-1,2/)
    1083              : 
    1084        11038 :  hexa_axes(:,:)=0
    1085        11038 :  hexa_axes(1,1)=1
    1086        11038 :  hexa_axes(2,2)=1
    1087        11038 :  hexa_axes(3,3)=1
    1088        44152 :  hexa_axes(:,4)=(/1,-1,0/)
    1089        44152 :  hexa_axes(:,5)=(/2,1,0/)
    1090        44152 :  hexa_axes(:,6)=(/1,1,0/)
    1091        44152 :  hexa_axes(:,7)=(/1,2,0/)
    1092              : 
    1093              : !Determine the point group from the list of symmetry operations.
    1094              : !Also determine the holohedry, up to one undeterminacy : hR versus hP
    1095        11038 :  call symptgroup(iholohedry,nsym,ptgroup,symrel)
    1096              : 
    1097              : !DEBUG
    1098              : !write(std_out,*)' symbrav, after symptgroup: nsym=',nsym
    1099              : !call flush(std_out)
    1100              : !write(std_out,*)' symbrav: symrel='
    1101              : !do isym=1,nsym
    1102              : !  write(std_out,'(9i4)')symrel(:,:,isym)
    1103              : !enddo
    1104              : !write(std_out,*)' symbrav: iholohedry=',iholohedry
    1105              : !call flush(std_out)
    1106              : !ENDDEBUG
    1107              : 
    1108              : !Loop over trial deformations
    1109              : !This is needed in case the Bravais lattice determination from the lattice vectors
    1110              : !has a higher holohedry than the real one, in which the symmetry
    1111              : !operations for the atoms (or electric field, etc) are taken into account
    1112        11038 :  iaxis=0
    1113        11038 :  invariant=0
    1114        11038 :  next_stage=0
    1115        11038 :  rprimdnow(:,:)=rprimd(:,:)
    1116        11038 :  rprimdtry(:,:)=rprimd(:,:)
    1117        33114 :  ABI_MALLOC(symrelconv,(3,3,nsym))
    1118              : 
    1119              : !At most will have to try naxes_ortho*5 deformations (naxes_ortho axes, five stages)
    1120              : !First, test whether the current recognition of Bravais lattice is problematic (iholohedry differs from bravais(1)).
    1121              : !Then, if there is a problem, test different deformations of rprimd, one after the other.
    1122              : !For each try, there is a new rprimdtry from the different set of deformation, that is generated later in the loop
    1123              : !Also bravais1now and rprimdnow might changed (and progressively lowered).
    1124              : !The latter change induces at most 5 stages for the computation (cubic->tetragonal->orthorhombic->monoclinic->triclinic).
    1125              : !After an upgrade of bravais1now and rprimdnow, one has to restart the full set of deformations.
    1126              : !Not sure that this procedure resolves all cases, but seems to work on >40000 inaccurate POSCAR files.
    1127        15432 :  do ideform=1,naxes_ortho*5
    1128              : 
    1129        15432 :    maxsym=max(192,msym)
    1130        46296 :    ABI_MALLOC(ptsymrel,(3,3,maxsym))
    1131        15432 :    call symlatt(bravais,std_out,maxsym,nptsym,ptsymrel,rprimdtry,tolsym)
    1132        15432 :    ABI_FREE(ptsymrel)
    1133              : 
    1134              : !DEBUG
    1135              : !write(std_out,*)' symbrav: inside loop with ideform,iaxis=',ideform,iaxis
    1136              : !write(std_out,'(a,9f12.6)')' rprimdtry=',rprimdtry(:,:)
    1137              : !write(std_out,'(a,2i4)')' bravais(1:2)=',bravais(1:2)
    1138              : !call flush(std_out)
    1139              : !ENDDEBUG
    1140              : 
    1141              : 
    1142              : !  Examine the agreement with bravais(1)
    1143              : !  Warning : might change Bravais lattice hR to hP, if hexagonal axes
    1144        15432 :    problem=0
    1145        23334 :    select case (bravais(1))
    1146              :    case (7)
    1147         7902 :      if(iholohedry<6)problem=1
    1148         7902 :      if(iholohedry==6)problem=2
    1149              :    case (6)
    1150          668 :      if(iholohedry<4)problem=1
    1151          668 :      if(iholohedry==7 .or. iholohedry==4)problem=2
    1152              : !      Here, change hR into hP
    1153          668 :      if(iholohedry==5)iholohedry=6
    1154              :    case (5)
    1155          806 :      if(iholohedry<4)problem=1
    1156          806 :      if(iholohedry==7 .or. iholohedry==6 .or. iholohedry==4)problem=2
    1157              :    case (4)
    1158         2040 :      if(iholohedry<4)problem=1
    1159         2040 :      if(iholohedry>4)problem=2
    1160              :    case (3)
    1161          898 :      if(iholohedry<3)problem=1
    1162          898 :      if(iholohedry>3)problem=2
    1163              :    case (2)
    1164         1721 :      if(iholohedry<2)problem=1
    1165         1721 :      if(iholohedry>2)problem=2
    1166              :    case (1)
    1167        15432 :      if(iholohedry>1)problem=2
    1168              :    end select
    1169              : 
    1170              : !  This is the usual situation, in which the lattice belong to the same holohedry
    1171              : !  as the lattice+atoms (+electric field + ...)
    1172        15432 :    if(problem==0)exit
    1173              : 
    1174         4394 :    if(problem==2)then
    1175            0 :      if(iaxis==0)then
    1176              :        write(msg, '(3a,i3,3a,i3,7a)' )&
    1177            0 :         'The Bravais lattice determined only from the primitive',ch10,&
    1178            0 :         'vectors (rprim or angdeg), bravais(1)=',bravais(1),', is not compatible',ch10,&
    1179            0 :         'with the real one, iholohedry=',iholohedry,', obtained by taking into',ch10,&
    1180            0 :         'account the symmetry operations. This might be due to an insufficient',ch10,&
    1181            0 :         'number of digits in the specification of rprim (at least 10),',ch10,&
    1182            0 :         'or to an erroneous rprim or angdeg. If this is not the case, then ...'
    1183            0 :        ABI_BUG(msg)
    1184              :      end if
    1185            0 :      if(iaxis==1)then
    1186              :        write(msg, '(3a,3i3,2a,i3,2a,i3)' )&
    1187            0 :        'Could not succeed to determine the bravais lattice',ch10,&
    1188            0 :        'problem,iaxis,invariant=',problem,iaxis,invariant,ch10,&
    1189            0 :        'bravais(1)=',bravais(1),ch10,&
    1190            0 :        'iholohedry=',iholohedry
    1191            0 :        ABI_BUG(msg)
    1192              :      end if
    1193              : !    Try to increase tolsym to find the Bravais lattice.
    1194              :      maxsym=max(192,msym)
    1195            0 :      ABI_MALLOC(ptsymrel,(3,3,maxsym))
    1196              : !DEBUG
    1197              : !    write(6,*)' symbrav : will call symlatt, 3*tolsym=',3*tolsym
    1198              : !ENDDEBUG
    1199            0 :      call symlatt(bravais,std_out,maxsym,nptsym,ptsymrel,rprimdtry,3*tolsym)
    1200            0 :      ABI_FREE(ptsymrel)
    1201            0 :      if(bravais(1)==iholohedry)then
    1202              : !      Succeeded
    1203              :        exit
    1204              :      else
    1205              :        write(msg, '(3a,3i3,2a,i3,2a,i3)' )&
    1206            0 :        'Could not succeed to determine the bravais lattice, even after considering a larger tolsym',ch10,&
    1207            0 :        'problem,iaxis,invariant=',problem,iaxis,invariant,ch10,&
    1208            0 :        'bravais(1)=',bravais(1),ch10,&
    1209            0 :        'iholohedry=',iholohedry
    1210            0 :        ABI_BUG(msg)
    1211              :      end if
    1212              :    end if
    1213              : 
    1214         4394 :    if(problem==1)then  ! One is left with the problem=1 case, basically iholohedry is lower than bravais(1)
    1215         4394 :      if(iaxis==0)then
    1216              :        write(msg, '(a,a,a,i3,a,a,a,i3,a,a,a)' )&
    1217         2878 :        'The Bravais lattice determined only from the primitive',ch10,&
    1218         2878 :        'vectors, bravais(1)=',bravais(1),', is more symmetric',ch10,&
    1219         2878 :        'than the real one, iholohedry=',iholohedry,', obtained by taking into',ch10,&
    1220         5756 :        'account the atomic positions. Start deforming the primitive vector set.'
    1221         2878 :        ABI_COMMENT(msg)
    1222              :        next_stage=1
    1223              :      else if(iaxis/=0)then
    1224         1516 :        if(bravais(1)<bravais1now)then
    1225              :          write(msg, '(3a,i3,3a,i3,2a)' )&
    1226         1301 :          'The Bravais lattice determined from modified primitive',ch10,&
    1227         1301 :          'vectors, bravais(1)=',bravais(1),', has a lower symmetry than before,',ch10,&
    1228         1301 :          'but is still more symmetric than the real one, iholohedry=',iholohedry,ch10,&
    1229         2602 :          'obtained by taking into account the atomic positions.'
    1230         1301 :          ABI_COMMENT(msg)
    1231              :          next_stage=1
    1232          215 :        else if(iaxis==1)then
    1233              :          write(msg, '(3a,3i3,2a,i3,2a,i3)' )&
    1234            0 :          'Could not succeed to determine the bravais lattice',ch10,&
    1235            0 :          'problem,iaxis,invariant=',problem,iaxis,invariant,ch10,&
    1236            0 :          'bravais(1)=',bravais(1),ch10,&
    1237            0 :          'iholohedry=',iholohedry
    1238            0 :          ABI_BUG(msg)
    1239              :        end if
    1240              :      end if
    1241              :    end if ! problem==1
    1242              : 
    1243              : !  One is here when problem=1 (iholohedry < bravais(1)) and either
    1244              : !  - iaxis=0 (no deformation has been tried yet),
    1245              : !  - some deformation iaxis has been tried giving bravais(1), but iholohedry < bravais(1) < bravais1now
    1246              : !  - some deformation iaxis has been tried giving bravais(1), but iholohedry < bravais(1) = bravais1now and iaxis/=1 .
    1247              : !  Also, note that next_stage is still 0 when bravais(1)=bravais1now .
    1248              : !  The loop has been ended (so, the search failed) when bravais(1)=bravais1now and iaxis==1.
    1249              : 
    1250              :    if(next_stage==1)then
    1251         4179 :      bravais1now=bravais(1)
    1252         4179 :      rprimdnow(:,:)=rprimdtry(:,:)
    1253              : !    Generate the symmetry operations in the conventional vector coordinates
    1254        16716 :      rprimdconv(:,1)=bravais(3:5)
    1255        16716 :      rprimdconv(:,2)=bravais(6:8)
    1256        16716 :      rprimdconv(:,3)=bravais(9:11)
    1257         4179 :      axes(:,:)=zero
    1258         4179 :      axes(1,1)=one ; axes(2,2)=one ; axes(3,3)=one
    1259       209397 :      symrelconv(:,:,1:nsym)=symrel(:,:,1:nsym)
    1260         4179 :      call symrelrot(nsym,rprimdconv,axes,symrelconv,tolsym)
    1261         4179 :      if(bravais(1)/=6)then
    1262         4162 :        iaxis=naxes_ortho+1
    1263              :      else
    1264           17 :        iaxis=naxes_hexa+1
    1265              :      end if
    1266              :      next_stage=0
    1267              : !DEBUG
    1268              : !    write(std_out,*)' symbrav: next stage, bravais(1), bravais(2) and symrelconv'
    1269              : !    write(std_out,'(a,2i4)')' bravais(1:2)=',bravais(1:2)
    1270              : !    write(std_out,'(a,9f12.6)')' rprimdconv=',rprimdconv(:,:)
    1271              : !    do isym=1,nsym
    1272              : !      write(std_out,'(9i4)')symrelconv(:,:,isym)
    1273              : !    enddo
    1274              : !    call flush(std_out)
    1275              : !ENDDEBUG
    1276              :    end if
    1277              : 
    1278              : !  Go to the next iaxis that will be left invariant
    1279         4394 :    iaxis=iaxis-1
    1280        24832 :    do jaxis=iaxis,1,-1
    1281        24832 :      if(bravais(1)/=6)then
    1282        99252 :        axis_trial(:)=ortho_axes(:,jaxis)
    1283              :      else
    1284           76 :        axis_trial(:)=hexa_axes(:,jaxis)
    1285              :      end if
    1286              : !    DEBUG
    1287              : !    write(std_out,*)' symbrav : ixaxis, trial jaxis=',iaxis,jaxis
    1288              : !    write(std_out,*)' axis_trial=',axis_trial
    1289              : !    ENDDEBUG
    1290        24832 :      invariant=1
    1291              : !    Examine whether all symmetry operations leave the axis invariant (might be reversed, though)
    1292       224594 :      do isym=1,nsym
    1293      1797858 :        if(sum(abs(matmul(symrelconv(:,:,isym),axis_trial)+(-axis_trial(:))))/=0 .and. &
    1294      7016502 :        sum(abs(matmul(symrelconv(:,:,isym),axis_trial)+axis_trial(:)))/=0 )invariant=0
    1295              :      end do
    1296        24832 :      if(invariant==1)then
    1297         4394 :        iaxis=jaxis
    1298              : !DEBUG
    1299              : !      write(msg, '(2a,i3)' )ch10,' symbrav : found invariant axis, jaxis=',jaxis
    1300              : !      call wrtout(std_out,msg)
    1301              : !ENDDEBUG
    1302         4394 :        exit
    1303              :      end if
    1304              :    end do
    1305              : 
    1306         4394 :    if(invariant==0)then
    1307              : !    Not a single axis was invariant with respect to all operations ?!
    1308              : !    do isym=1,nsym; write(std_out, '(a,10i4)' )' isym,symrelconv=',isym,symrelconv(:,:,isym); enddo
    1309              :      write(msg, '(3a,3i3,2a,i3,2a,i3)' )&
    1310            0 :      'Could not succeed to determine the bravais lattice (not a single invariant)',ch10,&
    1311            0 :      'problem,iaxis,invariant=',problem,iaxis,invariant,ch10,&
    1312            0 :      'bravais(1)=',bravais(1),ch10,&
    1313            0 :      'iholohedry=',iholohedry
    1314            0 :      ABI_BUG(msg)
    1315              :    end if
    1316              : 
    1317         4394 :    call matr3inv(rprimdconv,rprimdconv_invt)
    1318              :    axis_red(:)=axis_trial(1)*rprimdconv_invt(1,:)+ &
    1319              : &   axis_trial(2)*rprimdconv_invt(2,:)+ &
    1320        17576 : &   axis_trial(3)*rprimdconv_invt(3,:)
    1321              :    axis_cart(:)=axis_red(1)*rprimdnow(:,1)+ &
    1322              : &   axis_red(2)*rprimdnow(:,2)+ &
    1323        17576 : &   axis_red(3)*rprimdnow(:,3)
    1324        17576 :    norm=sum(axis_cart(:)**2)
    1325              : !DEBUG
    1326              : !  write(6,*)' axis_trial =',axis_trial
    1327              : !  write(6,*)' axis_red =',axis_red
    1328              : !  write(6,*)' axis_cart =',axis_cart
    1329              : !  write(6,*)' rprimdnow=',rprimdnow
    1330              : !ENDDEBUG
    1331              : !  Expand by a uniform, quite arbitrary, dilatation, along the invariant axis
    1332              : !  Note : make these dilatation different, according to ideform
    1333              : !  XG 20151221  : Still, the interplay between the size of the deformation and the tolsym is not easy to address.
    1334              : !  Indeed the deformation must be sufficiently large to be perceived by symlatt as a real breaking of the
    1335              : !  symmetry of the lattice. In order to deal with all the small values od tolsym, it has been set at a minimum of tol3,
    1336              : !  but it must also be larger than tolsym. Moreover, for some axis choice, the deformation is not aligned with the axis, decreasing
    1337              : !  the effective deformation length. An additional factor of three is thus included, actually increased to six just to be sure...
    1338        44046 :    do ii=1,3
    1339        13182 :      scprod=axis_cart(1)*rprimdnow(1,ii)+axis_cart(2)*rprimdnow(2,ii)+axis_cart(3)*rprimdnow(3,ii)
    1340        57122 :      rprimdtry(:,ii)=rprimdnow(:,ii)+ideform*(max(tol3,six*tolsym)-tol6)*scprod/norm*axis_cart(:)
    1341              :    end do
    1342              : 
    1343              : !DEBUG
    1344              : !  write(6,*)' rprimdtry=',rprimdtry
    1345              : !ENDDEBUG
    1346              : 
    1347              :  end do ! ideform
    1348              : 
    1349        11038 :  if(bravais(1)/=iholohedry)then
    1350              :    write(msg, '(3a,3i3,2a,i3,2a,i3)' )&
    1351            0 :    'Despite efforts, Could not succeed to determine the bravais lattice :',ch10,&
    1352            0 :    'bravais(1)=',bravais(1),ch10,&
    1353            0 :    'iholohedry=',iholohedry
    1354            0 :    ABI_BUG(msg)
    1355              :  end if
    1356              : 
    1357        11038 :  ABI_FREE(symrelconv)
    1358              : 
    1359        11038 :  if (PRESENT(axis)) then  ! Return symmetry axis.
    1360            0 :    axis=(/0,0,0/)
    1361            0 :    if (iaxis/=0) then
    1362            0 :      if(bravais(1)/=6)then
    1363            0 :        axis=ortho_axes(:,iaxis)
    1364              :      else
    1365            0 :        axis=hexa_axes(:,iaxis)
    1366              :      end if
    1367              :    end if
    1368              :  end if
    1369              : 
    1370              : !DEBUG
    1371              : !write(std_out,'(a)')' symbrav : exit '
    1372              : !ENDDEBUG
    1373              : 
    1374        11038 : end subroutine symbrav
    1375              : !!***
    1376              : 
    1377              : !!****f* m_symfind/symspgr
    1378              : !! NAME
    1379              : !! symspgr
    1380              : !!
    1381              : !! FUNCTION
    1382              : !! Find the type of each symmetry operation (calling symcharac):
    1383              : !!   proper symmetries 1,2,2_1,3,3_1,3_2,4,4_1,4_2,4_3,6,6_1,...6_5
    1384              : !!   improper symmetries -1,m,a,b,c,d,n,g,-3,-4,-6 ,
    1385              : !! Then, build an array with the number of such operations.
    1386              : !! Then, call symlist to identify the space group.
    1387              : !!
    1388              : !! INPUTS
    1389              : !! bravais(11): bravais(1)=iholohedry
    1390              : !!              bravais(2)=center
    1391              : !!              bravais(3:11)=coordinates of rprimd in the axes
    1392              : !!              of the conventional bravais lattice (*2 if center/=0)
    1393              : !! nsym=actual number of symmetries
    1394              : !! symrel(3,3,nsym)= nsym symmetry operations in real space in terms
    1395              : !!   of primitive translations
    1396              : !! tnons(3,nsym)=nonsymmorphic translations for each symmetry (would
    1397              : !!   be 0 0 0 each for a symmorphic space group)
    1398              : !!
    1399              : !! OUTPUT
    1400              : !! labels(maxsym=192)= labels of the symmetry operations
    1401              : !! spgroup=symmetry space group number
    1402              : !!
    1403              : !! NOTES
    1404              : !! It is assumed that the symmetry operations will be entered in the
    1405              : !! symrel tnons arrays, for the PRIMITIVE cell. The matrix of transformation
    1406              : !! from the primitive cell to the conventional cell is described
    1407              : !! in the array "bravais" (see symlatt.F90).
    1408              : !! The present routine first make the transformation from the
    1409              : !! primitive coordinates to the conventional ones, then eventually
    1410              : !! generate additional symmetries, taking into account the
    1411              : !! centering translations.
    1412              : !! Then, the order and determinant of each symmetry operation
    1413              : !! is determined.
    1414              : !!
    1415              : !! For proper symmetries (rotations), the
    1416              : !! associated translation is also determined.
    1417              : !! However, left or right handed screw rotations are
    1418              : !! not (presently) distinguished, and will be attributed equally
    1419              : !! to left or right.
    1420              : !!
    1421              : !! For the detailed description of the labelling of the axes, see symaxes.f and symplanes.f
    1422              : !!
    1423              : !! SOURCE
    1424              : 
    1425        11645 : subroutine symspgr(bravais,labels,nsym,spgroup,symrel,tnons,tolsym)
    1426              : 
    1427              :  use m_numeric_tools, only : OPERATOR(.x.)
    1428              : 
    1429              : !Arguments ------------------------------------
    1430              : !scalars
    1431              :  integer,intent(in) :: nsym
    1432              :  integer,intent(out) :: spgroup
    1433              :  real(dp),intent(in) :: tolsym
    1434              : !arrays
    1435              :  integer,intent(in) :: bravais(11),symrel(3,3,nsym)
    1436              :  real(dp),intent(in) :: tnons(3,nsym)
    1437              :  character(len=128),intent(out) :: labels(192) ! 192 = maxsym
    1438              : 
    1439              : !Local variables-------------------------------
    1440              : !scalars
    1441              : ! logical,parameter :: verbose=.FALSE.
    1442              :  integer :: additional_info,brvltt,center,direction=0,found,iholohedry,ii
    1443              :  integer :: ishift,isym,jj,nshift,nsymconv,spgaxor,spgorig,sporder
    1444              :  character(len=1) :: brvsb
    1445              :  character(len=15) :: intsb,ptintsb,ptschsb,schsb
    1446              :  character(len=35) :: intsbl
    1447              :  character(len=500) :: msg
    1448              : !arrays
    1449              :  integer :: ivec1(3), ivec2(3)
    1450              :  integer :: n_axes(31),n_axest(31),prime(5),test_direction(3),symrel_uni(3,3)
    1451              :  integer :: uniaxis(3),uniaxis_try(3)
    1452        11645 :  integer,allocatable :: determinant(:),symrelconv(:,:,:),t_axes(:)
    1453              :  real(dp) :: axes(3,3),rprimdconv(3,3),vect(3,3)
    1454        11645 :  real(dp),allocatable :: shift(:,:),tnonsconv(:,:)
    1455              : !**************************************************************************
    1456              : 
    1457              :  DBG_ENTER("COLL")
    1458              : 
    1459              : !Initialize brvltt, from bravais(2) and bravais(1)
    1460        11645 :  center=bravais(2)
    1461        11645 :  iholohedry=bravais(1)
    1462        11645 :  brvltt=1
    1463        11645 :  if(center==-1)brvltt=2  ! Inner centering
    1464        11645 :  if(center==-3)brvltt=3  ! Face centering
    1465        11645 :  if(center==1)brvltt=5  ! A-Face centering
    1466        11645 :  if(center==2)brvltt=6  ! B-Face centering
    1467        11645 :  if(center==3)brvltt=4  ! C-Face centering
    1468        11645 :  if(iholohedry==5)brvltt=7  ! Rhombohedral
    1469              : 
    1470              : !Produce the symmetry operations, in the axis of the conventional cell
    1471        11645 :  nsymconv=nsym
    1472        11645 :  if(center/=0)nsymconv=2*nsymconv
    1473        11645 :  if(center==-3)nsymconv=4*nsym
    1474        34935 :  ABI_MALLOC(symrelconv,(3,3,nsymconv))
    1475        34935 :  ABI_MALLOC(tnonsconv,(3,nsymconv))
    1476              : 
    1477              : !Produce symrel and tnons in conventional axes,
    1478              : !name them symrelconv and tnonsconv
    1479        46580 :  rprimdconv(:,1)=bravais(3:5)
    1480        46580 :  rprimdconv(:,2)=bravais(6:8)
    1481        46580 :  rprimdconv(:,3)=bravais(9:11)
    1482              : 
    1483        79241 :  if(center/=0)rprimdconv(:,:)=rprimdconv(:,:)*half
    1484              : 
    1485        11645 :  axes(:,:)=zero
    1486        11645 :  axes(1,1)=one ; axes(2,2)=one ; axes(3,3)=one
    1487      3748326 :  symrelconv(:,:,1:nsym)=symrel(:,:,1:nsym)
    1488              : !Note that the number of symmetry operations is still nsym
    1489        11645 :  call symrelrot(nsym,rprimdconv,axes,symrelconv,tolsym)
    1490              : 
    1491        11645 :  call xred2xcart(nsym,rprimdconv,tnonsconv,tnons)
    1492              : !Gives the associated translation, with components in the interval ]-0.5,0.5] .
    1493      1161393 :  tnonsconv(:,1:nsym)=tnonsconv(:,1:nsym)-nint(tnonsconv(:,1:nsym)-tol6)
    1494              : 
    1495              : !If the Bravais lattice is centered, duplicate or quadruplicate
    1496              : !the number of symmetry operations, using the Bravais lattice shifts
    1497        11645 :  nshift=1
    1498        11645 :  if(center/=0)nshift=2
    1499        11645 :  if(center==-3)nshift=4
    1500        23290 :  ABI_MALLOC(shift,(3,nshift))
    1501        46580 :  shift(:,1)=zero
    1502        11645 :  if(center/=0 .and. center/=-3)then
    1503         5164 :    shift(:,2)=half
    1504         1291 :    if(center==1)shift(1,2)=zero
    1505         1291 :    if(center==2)shift(2,2)=zero
    1506         1291 :    if(center==3)shift(3,2)=zero
    1507        10354 :  else if(center==-3)then
    1508        17368 :    shift(:,2)=half ; shift(1,2)=zero
    1509        17368 :    shift(:,3)=half ; shift(2,3)=zero
    1510        17368 :    shift(:,4)=half ; shift(3,4)=zero
    1511              :  end if ! center/=0 or -3
    1512        11645 :  if(nshift/=1)then
    1513        19950 :    do ishift=2,nshift
    1514     14757877 :      symrelconv(:,:,(ishift-1)*nsym+1:ishift*nsym)=symrelconv(:,:,1:nsym)
    1515       587010 :      do isym=1,nsym
    1516      2282557 :        tnonsconv(:,(ishift-1)*nsym+isym)=tnonsconv(:,isym)+shift(:,ishift)
    1517              :      end do
    1518              :    end do ! ishift
    1519              :  end if ! nshift/=1
    1520              : 
    1521              : !At this stage, all the symmetry operations are available,
    1522              : !expressed in the conventional axis, and also include
    1523              : !the Bravais lattive translations, and associated operations...
    1524              : 
    1525        11645 :  n_axes(:)=0
    1526              : 
    1527        34935 :  ABI_MALLOC(determinant,(nsymconv))
    1528              : 
    1529              : !Get the determinant
    1530        11645 :  call symdet(determinant,nsymconv,symrelconv)
    1531              : 
    1532              : !Get the order of each the symmetry operation, as well as the maximal order
    1533              : !Also, examine whether each symmetry operation is the inversion, or a root of the inversion (like -3)
    1534              : !Decide which kind of point symmetry operation it is
    1535              : !Finally assign tnonsconv order and decide the space symmetry operation
    1536              : 
    1537        23290 :  ABI_MALLOC(t_axes,(nsymconv))
    1538              : 
    1539       866142 :  do isym=1,nsymconv
    1540              : 
    1541              : !  Note : nsymconv might be bigger than 192, but only for non-primitive cells, in which case labels will not be echoed anywhere.
    1542              : !  192 is the fixed dimension of labels, so this avoids possible memory problems.
    1543              :    call symcharac(center, determinant(isym), iholohedry, isym, labels(mod(isym-1,192)+1), &
    1544       854497 :    symrelconv(:,:,isym), tnonsconv(:,isym), t_axes(isym))
    1545       854497 :    if (t_axes(isym) == -1) then
    1546            0 :      write(msg, '(a,a,i3,a,3(a,3i4,a),a,3es22.12,a,a,3es22.12)' )ch10,&
    1547            0 :      ' symspgr: problem with isym=',isym,ch10,&
    1548            0 :      '  symrelconv(:,1,isym)=',symrelconv(:,1,isym),ch10,&
    1549            0 :      '  symrelconv(:,2,isym)=',symrelconv(:,2,isym),ch10,&
    1550            0 :      '  symrelconv(:,3,isym)=',symrelconv(:,3,isym),ch10,&
    1551            0 :      '  tnonsconv(:,isym)=',tnonsconv(:,isym)
    1552            0 :      call wrtout(std_out,msg)
    1553            0 :      write(msg, '(a,i0,2a)' )'The space symmetry operation number',isym,ch10,'is not a (translated) root of unity'
    1554            0 :      ABI_BUG(msg)
    1555       854497 :    else if (t_axes(isym) == -2) then
    1556            0 :      write(msg, '(a,i0,a)' )'The symmetry operation number ',isym,' is not a root of unity'
    1557            0 :      ABI_BUG(msg)
    1558              :    end if
    1559              : 
    1560       866142 :    n_axes(t_axes(isym))=n_axes(t_axes(isym))+1
    1561              :  end do ! isym=1,nsymconv
    1562              : 
    1563       372640 :  if (sum(n_axes)-nsymconv/=0) then
    1564              :    write(msg, '(7a)' )&
    1565            0 :    'Not all the symmetries have been recognized. ',ch10,&
    1566            0 :    'This might be due either to an error in the input file',ch10,&
    1567            0 :    'or to a BUG in ABINIT',ch10,&
    1568            0 :    'Please contact the ABINIT group.'
    1569            0 :    ABI_WARNING(msg)
    1570              :  end if
    1571              : 
    1572              :  !write(std_out,*)' symspgr : brvltt,nsymconv=',brvltt,nsymconv
    1573              :  !write(std_out,*)' n_axes(1:10)=',n_axes(1:10)
    1574              :  !write(std_out,*)' n_axes(11:20)=',n_axes(11:20)
    1575              :  !write(std_out,*)' n_axes(21:31)=',n_axes(21:31)
    1576              : 
    1577              : !Treat cases in which the space group cannot be identified on the
    1578              : !basis of n_axes one need additional information
    1579        11645 :  if(brvltt==1)then
    1580              : !  If the bravais lattice is primitive
    1581         5204 :    if(nsymconv==4)then
    1582          309 :      n_axest=(/0,0,0,0,0,0,0,1,1,0,  0,0,0,0,0,2,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0/)
    1583         9888 :      if(sum((n_axes-n_axest)**2)==0)then    ! Spgroup 27 (Pcc2) or 32 (Pba2)
    1584           16 :        write(std_out,*)' symspgr: 27 or 32'
    1585           16 :        additional_info=2
    1586              : !      Select binary axis
    1587           80 :        do isym=1,nsymconv
    1588           80 :          if(t_axes(isym)==8)then
    1589              : !          Find direction of binary axis
    1590           16 :            if(symrelconv(1,1,isym)==1)direction=1
    1591           16 :            if(symrelconv(2,2,isym)==1)direction=2
    1592           16 :            if(symrelconv(3,3,isym)==1)direction=3
    1593              :          end if
    1594              :        end do
    1595              : !      Examine the projection of the translation vector of the a, b or c mirror planes onto the binary axis
    1596           80 :        do isym=1,nsymconv
    1597           80 :          if(t_axes(isym)==16)then
    1598           32 :            if(abs(tnonsconv(direction,isym))>tol8)additional_info=1
    1599              :          end if
    1600              :        end do
    1601              :      end if
    1602         4895 :    else if(nsymconv==8)then
    1603          879 :      n_axest=(/0,0,0,0,1,0,0,1,1,0,  0,0,0,0,1,2,0,0,0,2,  0,0,0,0,0,0,0,0,0,0,0/)
    1604        28128 :      if(sum((n_axes-n_axest)**2)==0)then    ! Spgroup 55 (Pbam) or 57 (Pbcm)
    1605           26 :        write(std_out,*)' symspgr: 55 or 57'
    1606           26 :        additional_info=1
    1607              : !      Select mirror plane m
    1608          234 :        do isym=1,nsymconv
    1609          234 :          if(t_axes(isym)==15)then
    1610              : !          Find direction of mirror plane
    1611           26 :            if(symrelconv(1,1,isym)==-1)direction=1
    1612           26 :            if(symrelconv(2,2,isym)==-1)direction=2
    1613           26 :            if(symrelconv(3,3,isym)==-1)direction=3
    1614              :          end if
    1615              :        end do
    1616              : !      Examine the projection of the translation vector of the a, b, or c mirror planes
    1617              : !      onto the binary axis
    1618          234 :        do isym=1,nsymconv
    1619          234 :          if(t_axes(isym)==16)then
    1620           52 :            if(abs(tnonsconv(direction,isym))>tol8)additional_info=2
    1621              :          end if
    1622              :        end do
    1623              :      end if
    1624          879 :      n_axest=(/0,0,0,0,1,0,0,1,1,0,  0,0,0,0,0,2,0,1,0,2,  0,0,0,0,0,0,0,0,0,0,0/)
    1625        28128 :      if(sum((n_axes-n_axest)**2)==0)then    ! Spgroup 56 (Pccn) or 60 (Pbcn)
    1626           26 :        write(std_out,*)' symspgr: 56 or 60'
    1627           26 :        additional_info=1
    1628              : !      Select mirror plane n
    1629          234 :        do isym=1,nsymconv
    1630          234 :          if(t_axes(isym)==18)then
    1631              : !          Find direction of mirror plane
    1632           26 :            if(symrelconv(1,1,isym)==-1)direction=1
    1633           26 :            if(symrelconv(2,2,isym)==-1)direction=2
    1634           26 :            if(symrelconv(3,3,isym)==-1)direction=3
    1635              :          end if
    1636              :        end do
    1637              : !      Examine the projection of the translation vector of the a, b, or c mirror planes
    1638              : !      onto the binary axis
    1639          234 :        do isym=1,nsymconv
    1640          234 :          if(t_axes(isym)==16)then
    1641           52 :            if(abs(tnonsconv(direction,isym))<tol8)additional_info=2
    1642              :          end if
    1643              :        end do
    1644              :      end if
    1645              :    end if
    1646         6441 :  else if(brvltt==2)then
    1647              : !  In the few next lines, use additional_info as a flag
    1648          698 :    additional_info=0
    1649              : !  If the bravais lattice is inner-centered
    1650          698 :    if(nsymconv==8)then
    1651              : !    Test spgroup 23 (I222) or 24 (I2_{1}2_{1}2_{1})
    1652          105 :      n_axest=(/0,0,0,0,0,0,1,1,3,0,  0,0,0,0,0,0,0,0,0,3,  0,0,0,0,0,0,0,0,0,0,0/)
    1653         3360 :      if(sum((n_axes-n_axest)**2)==0) additional_info=1
    1654          593 :    else if(nsymconv==24)then
    1655              : !    Test spgroup 197 (I23) or 199 (I2_{1}3)
    1656            2 :      n_axest=(/0,0,0,0,0,0,1,1,3,16, 0,0,0,0,0,0,0,0,0,3,  0,0,0,0,0,0,0,0,0,0,0/)
    1657           64 :      if(sum((n_axes-n_axest)**2)==0) additional_info=1
    1658              :    end if
    1659          698 :    if(additional_info==1)then
    1660            8 :      write(std_out,*)' symspgr: (23 or 24) or (197 or 199)'
    1661              : !    Select the three binary axes (they might be 2 or 2_1 !)
    1662            8 :      test_direction(:)=0
    1663          104 :      do isym=1,nsymconv
    1664          104 :        if(t_axes(isym)==20)then
    1665              : !        Find direction of axis
    1666           96 :          do direction=1,3
    1667           96 :            if(symrelconv(direction,direction,isym)==1)then
    1668           24 :              test_direction(direction)=1
    1669           24 :              if(abs(tnonsconv(direction,isym))<tol8)then
    1670            0 :                vect(:,direction)=tnonsconv(:,isym)
    1671              :              else
    1672           96 :                vect(:,direction)=tnonsconv(:,isym)+half
    1673              :              end if
    1674           96 :              vect(:,direction)=vect(:,direction)-nint(vect(:,direction)-tol8)
    1675           24 :              vect(direction,direction)=zero
    1676              :            end if
    1677              :          end do ! direction=1,3
    1678              :        end if ! if binary axis
    1679              :      end do ! isym
    1680            8 :      if(test_direction(1)/=1 .or. test_direction(2)/=1 .and. test_direction(3)/=1)then
    1681              :        write(msg, '(5a,3i4)' )&
    1682            0 :        'For space groups 23, 24, 197 or 197, the three binary axes',ch10,&
    1683            0 :        'are not equally partitioned along the x, y and z directions',ch10,&
    1684            0 :        'test_direction(1:3)=',test_direction(:)
    1685            0 :        ABI_BUG(msg)
    1686              :      end if
    1687            8 :      additional_info=1
    1688            8 :      if(abs(vect(1,2)-vect(1,3))>tol8 .or. abs(vect(2,1)-vect(2,3))>tol8 .or. &
    1689            4 :         abs(vect(3,1)-vect(3,2))>tol8) additional_info=2
    1690              :    end if ! additional information are needed
    1691              :  end if ! brvltt==1
    1692              : 
    1693        11645 :  if (brvltt==0 .or. brvltt==1) then ! Primitive
    1694         5204 :    call symlist_prim(additional_info,nsymconv,n_axes,spgroup)
    1695         6441 :  else if(brvltt==2)then
    1696          698 :    call symlist_bcc(additional_info,nsymconv,n_axes,spgroup)
    1697         5743 :  else if(brvltt==3)then
    1698         4342 :    call symlist_fcc(nsymconv,n_axes,spgroup)
    1699              :  else
    1700         1401 :    call symlist_others(brvltt,nsymconv,n_axes,spgroup)
    1701              :  end if
    1702              : 
    1703        11645 :  if(spgroup==0) then
    1704              :    write(msg, '(5a)' )&
    1705           17 :    'Could not find the space group.',ch10,&
    1706           17 :    'This often happens when the user selects a restricted set of symmetries ',ch10,&
    1707           34 :    'in the input file, instead of letting the code automatically find symmetries.'
    1708           17 :    ABI_WARNING(msg)
    1709              :  end if
    1710              : 
    1711        11645 :  spgorig=1 ; spgaxor=1
    1712        11645 :  call spgdata(brvsb,intsb,intsbl,ptintsb,ptschsb,schsb,spgaxor,spgroup,sporder,spgorig)
    1713              : 
    1714        11645 :  if(spgroup/=0)then
    1715        11628 :    write(msg, '(a,i4,2x,a,a,a,a,a)' ) ' symspgr: spgroup=',spgroup,trim(brvsb),trim(intsb),'   (=',trim(schsb),')'
    1716        11628 :    call wrtout(std_out,msg)
    1717              :  end if
    1718              : 
    1719        11645 :  if(bravais(1)==7)then
    1720         5589 :    write(msg, '(a)' ) ' symspgr: optical characteristics = isotropic '
    1721         5589 :    call wrtout(std_out,msg)
    1722         6056 :  else if(bravais(1)==4 .or. bravais(1)==5 .or. bravais(1)==6)then
    1723         3053 :    write(msg, '(a)' ) ' symspgr: optical characteristics = uniaxial '
    1724         3053 :    call wrtout(std_out,msg)
    1725              :    ! Identify the first symmetry operation that is order 3, 4 or 6
    1726         3053 :    found=0
    1727        16561 :    do isym=1,nsym
    1728       231529 :      if( minval( abs( t_axes(isym)-(/10,12,14,22,23,24,25,26,27,28,29,30,31/) ))==0) then
    1729              :        ! Proper rotations
    1730              :        found=1 ; exit
    1731              : 
    1732        58004 :      else if( minval( abs( t_axes(isym)-(/1,2,3/) ))==0) then
    1733              :        ! Improper symmetry operations
    1734          993 :        found=-1 ; exit
    1735              :      end if
    1736              :    end do
    1737         3053 :    if(found==-1 .or. found==1)then
    1738        39364 :      symrel_uni=symrel(:,:,isym)
    1739        14944 :      if(found==-1)symrel_uni=-symrel_uni
    1740              :      ! Now, symrel_uni is a rotation of order 3, 4, 6, for which the axis must be identified
    1741              :      ! It is actually the only eigenvector with eigenvalue 1. It can be found by cross products
    1742              :      ! Subtract the unit matrix.
    1743        12112 :      do ii=1,3
    1744        12112 :        symrel_uni(ii,ii)=symrel_uni(ii,ii)-1
    1745              :      end do
    1746         3641 :      found=0
    1747         3641 :      do ii=1,3
    1748         3641 :        jj=ii+1 ; if(jj==4)jj=1
    1749              :        ! Cross product
    1750        25487 :        ivec1 = symrel_uni(ii,:); ivec2 = symrel_uni(jj,:)
    1751         3641 :        uniaxis = ivec1 .x. ivec2
    1752        14564 :        if(sum(uniaxis**2)/=0)then
    1753              :          found=1 ; exit
    1754              :        end if
    1755              :      end do
    1756         3028 :      if(found==1)then
    1757              :        ! Try to reduce the length, by an integer factor (try only primes 2, 3, 5, 7, 11)
    1758         3028 :        prime=(/2,3,5,7,11/)
    1759         3028 :        ii=1
    1760        19736 :        do while (ii<6)
    1761        66832 :          uniaxis_try=uniaxis/prime(ii)
    1762        69860 :          if(sum(abs(uniaxis_try*prime(ii)-uniaxis))==0)then
    1763         1568 :            uniaxis=uniaxis_try
    1764              :          else
    1765        15140 :            ii=ii+1
    1766              :          end if
    1767              :        end do
    1768         3028 :        write(msg, '(a,3i4)' ) ' Optical axis (in reduced coordinates, real space ) :',uniaxis
    1769              :      end if
    1770              :    end if
    1771              :    if(found==0)then
    1772           25 :      write(msg, '(a)' ) ' However, the axis has not been found. Sorry for this.'
    1773              :    end if
    1774         3053 :    call wrtout(std_out,msg)
    1775              :  end if
    1776              : 
    1777        11645 :  ABI_FREE(determinant)
    1778        11645 :  ABI_FREE(shift)
    1779        11645 :  ABI_FREE(symrelconv)
    1780        11645 :  ABI_FREE(tnonsconv)
    1781        11645 :  ABI_FREE(t_axes)
    1782              : 
    1783              :  DBG_EXIT("COLL")
    1784              : 
    1785        11645 : end subroutine symspgr
    1786              : !!***
    1787              : 
    1788              : !!****f* m_symfind/symlatt
    1789              : !! NAME
    1790              : !! symlatt
    1791              : !!
    1792              : !! FUNCTION
    1793              : !! From the unit cell vectors (rprimd) and the corresponding metric tensor,
    1794              : !! find the Bravais lattice and its symmetry operations (ptsymrel).
    1795              : !! 1) Find the shortest possible primitive vectors for the lattice
    1796              : !! 2) Determines the holohedral group of the lattice, and the
    1797              : !!    axes to be used for the conventional cell
    1798              : !!    (this is a delicate part, in which the centering of the
    1799              : !!    reduced cell must be taken into account)
    1800              : !!    The idea is to determine the basis vectors of the conventional
    1801              : !!    cell from the reduced cell basis vectors.
    1802              : !! 3) Generate the symmetry operations of the holohedral group
    1803              : !!
    1804              : !! INPUTS
    1805              : !! iout=unit number of output file
    1806              : !! msym=default maximal number of symmetries. WARNING : cannot be simply set to nsym, because
    1807              : !!   the number of symmetries found here will likely be bigger than sym !
    1808              : !! rprimd(3,3)=dimensional primitive translations for real space (bohr)
    1809              : !! tolsym=tolerance for the symmetries
    1810              : !!
    1811              : !! OUTPUT
    1812              : !!  bravais(11): bravais(1)=iholohedry
    1813              : !!               bravais(2)=center
    1814              : !!               bravais(3:11)=coordinates of rprim in the axes
    1815              : !!               of the conventional bravais lattice (*2 if center/=0)
    1816              : !! nptsym=number of point symmetries of the Bravais lattice
    1817              : !! ptsymrel(3,3,1:msym)= nptsym point-symmetry operations
    1818              : !! of the Bravais lattice in real space in terms of primitive translations.
    1819              : !!
    1820              : !! NOTES
    1821              : !! WARNING: bravais(1) might be given a negative value in another
    1822              : !! routine, if the cell is non-primitive.
    1823              : !! The holohedral groups are numbered as follows
    1824              : !! (see international tables for crystallography (1983), p. 13)
    1825              : !! iholohedry=1   triclinic      1bar
    1826              : !! iholohedry=2   monoclinic     2/m
    1827              : !! iholohedry=3   orthorhombic   mmm
    1828              : !! iholohedry=4   tetragonal     4/mmm
    1829              : !! iholohedry=5   trigonal       3bar m
    1830              : !! iholohedry=6   hexagonal      6/mmm
    1831              : !! iholohedry=7   cubic          m3bar m
    1832              : !! Centering
    1833              : !! center=0        no centering
    1834              : !! center=-1       body-centered
    1835              : !! center=-3       face-centered
    1836              : !! center=1        A-face centered
    1837              : !! center=2        B-face centered
    1838              : !! center=3        C-face centered
    1839              : !!
    1840              : !! SOURCE
    1841              : 
    1842        39896 : subroutine symlatt(bravais,iout,msym,nptsym,ptsymrel,rprimd,tolsym)
    1843              : 
    1844              : !Arguments ------------------------------------
    1845              : !scalars
    1846              :  integer,intent(in) :: iout,msym
    1847              :  integer,intent(out) :: nptsym
    1848              :  real(dp),intent(in) :: tolsym
    1849              : !arrays
    1850              :  integer,intent(out) :: bravais(11),ptsymrel(3,3,msym)
    1851              :  real(dp),intent(in) :: rprimd(3,3)
    1852              : 
    1853              : !Local variables-------------------------------
    1854              : !scalars
    1855              :  integer,parameter :: mgen=4
    1856              :  integer :: center,fact,found,foundc,ia,iaxis1,iaxis2
    1857              :  integer :: isign1,isign2,ib,icase,igen,iholohedry,ii,index,isym
    1858              :  integer :: itrial,jj,jsym,ngen=0,orthogonal,sign12,sign13,sign23,sumsign
    1859              :  real(dp) :: determinant,norm2a,norm2b,norm2c,norm2trial,reduceda,reducedb,sca
    1860              :  real(dp) :: scalarprod,scb,trace,trace_best,val
    1861              :  character(len=500) :: msg
    1862              : !arrays
    1863              :  integer,parameter :: list_holo(7)=(/7,6,4,3,5,2,1/)
    1864              :  integer :: ang90(3),equal(3),gen(3,3,mgen),gen2xy(3,3),gen2y(3,3),gen2z(3,3)
    1865              :  integer :: gen3(3,3),gen6(3,3),icoord(3,3),identity(3,3),nvecta(3),nvectb(3)
    1866              :  integer :: order(mgen)
    1867              :  real(dp) :: axes(3,3),axesinvt(3,3),axes_best(3,3),axes_try(3,3)
    1868              :  real(dp) :: cell_base(3,3),coord(3,3),metmin(3,3)
    1869              :  real(dp) :: minim(3,3),scprods(3,3),vecta(3),vectb(3),vectc(3),vin1(3),vin2(3),vext(3)
    1870              : !**************************************************************************
    1871              : 
    1872              : !DEBUG
    1873              : !write(std_out,'(a,es14.6)') ' m_symfind%symlatt : enter, tolsym= ',tolsym
    1874              : !call flush(std_out)
    1875              : !ENDDEBUG
    1876              : 
    1877        39896 :  identity(:,:)=0 ; identity(1,1)=1 ; identity(2,2)=1 ; identity(3,3)=1
    1878        39896 :  nvecta(1)=2 ; nvectb(1)=3
    1879        39896 :  nvecta(2)=1 ; nvectb(2)=3
    1880        39896 :  nvecta(3)=1 ; nvectb(3)=2
    1881              : 
    1882              : !--------------------------------------------------------------------------
    1883              : !Reduce the input vectors to a set of minimal vectors
    1884        39896 :  call smallprim(metmin,minim,rprimd)
    1885              : 
    1886              : !DEBUG
    1887              : !write(std_out,*)' symlatt : minim(:,1)=',minim(:,1)
    1888              : !write(std_out,*)' symlatt : minim(:,2)=',minim(:,2)
    1889              : !write(std_out,*)' symlatt : minim(:,3)=',minim(:,3)
    1890              : !call flush(std_out)
    1891              : !ENDDEBUG
    1892              : 
    1893              : !--------------------------------------------------------------------------
    1894              : !Examine the angles and vector lengths
    1895        39896 :  ang90(:)=0
    1896        39896 :  if(metmin(1,2)**2<tolsym**2*metmin(1,1)*metmin(2,2))ang90(3)=1
    1897        39896 :  if(metmin(1,3)**2<tolsym**2*metmin(1,1)*metmin(3,3))ang90(2)=1
    1898        39896 :  if(metmin(2,3)**2<tolsym**2*metmin(2,2)*metmin(3,3))ang90(1)=1
    1899        39896 :  equal(:)=0
    1900        39896 :  if(abs(metmin(1,1)-metmin(2,2))<tolsym*half*(metmin(1,1)+metmin(2,2)))equal(3)=1
    1901        39896 :  if(abs(metmin(1,1)-metmin(3,3))<tolsym*half*(metmin(1,1)+metmin(3,3)))equal(2)=1
    1902        39896 :  if(abs(metmin(2,2)-metmin(3,3))<tolsym*half*(metmin(2,2)+metmin(3,3)))equal(1)=1
    1903              : 
    1904              : !DEBUG
    1905              : !write(std_out,*)' ang90=',ang90(:)
    1906              : !write(std_out,*)' equal=',equal(:)
    1907              : !call flush(std_out)
    1908              : !ENDDEBUG
    1909              : 
    1910              : !-----------------------------------------------------------------------
    1911              : !Identification of the centering
    1912              : 
    1913        39896 :  foundc=0
    1914              : !Default values
    1915        39896 :  fact=1 ; center=0
    1916        39896 :  cell_base(:,:)=minim(:,:)
    1917              : 
    1918              : !Examine each holohedral group
    1919              : !This search is ordered : should not be happy with tetragonal,
    1920              : !while there is FCC ...
    1921       125500 :  do index=1,6
    1922              : 
    1923              : !  If the holohedry is already found, exit
    1924       121802 :    if(foundc==1)exit
    1925              : 
    1926              : !  Initialize the target holohedry
    1927        85604 :    iholohedry=list_holo(index)
    1928              : 
    1929              : !  DEBUG
    1930              : !  write(std_out,*)
    1931              : !  write(std_out,*)' symlatt : trial holohedry',iholohedry
    1932              : !  ENDDEBUG
    1933              : 
    1934        85604 :    orthogonal=0
    1935        85604 :    if(iholohedry==7 .or. iholohedry==4 .or. iholohedry==3)orthogonal=1
    1936              : 
    1937              : !  Now, will examine different working hypothesis.
    1938              : !  The set of these hypothesis is thought to cover all possible cases ...
    1939              : 
    1940              : !  Working hypothesis : the basis is orthogonal
    1941        85604 :    if(ang90(1)+ang90(2)+ang90(3)==3 .and. orthogonal==1)then
    1942        21452 :      fact=1 ; center=0
    1943        21452 :      cell_base(:,:)=minim(:,:)
    1944              : !    Checks that the basis vectors are OK for the target holohedry
    1945        21452 :      call holocell(cell_base,0,foundc,iholohedry,tolsym)
    1946              :    end if
    1947              : 
    1948              : !  Select one trial direction
    1949       300247 :    do itrial=1,3
    1950              : 
    1951              : !    If the holohedry is already found, exit
    1952       209399 :      if(foundc==1)exit
    1953              : 
    1954       174747 :      ia=nvecta(itrial) ; ib=nvectb(itrial)
    1955              : 
    1956              : !    This is in case of hexagonal holohedry
    1957       174747 :      if(foundc==0 .and. iholohedry==6 .and. ang90(ia)==1 .and. ang90(ib)==1 .and. equal(itrial)==1 )then
    1958         7401 :        reduceda=metmin(ib,ia)/metmin(ia,ia)
    1959         7401 :        fact=1 ; center=0
    1960         7401 :        if(abs(reduceda+0.5d0)<tolsym)then
    1961         8508 :          cell_base(:,1)=minim(:,ia)
    1962         8508 :          cell_base(:,2)=minim(:,ib)
    1963         8508 :          cell_base(:,3)=minim(:,itrial)
    1964              : !DEBUG
    1965              : !      write(std_out,*)' cell_base(:,1)=',cell_base(:,1)
    1966              : !      write(std_out,*)' cell_base(:,2)=',cell_base(:,2)
    1967              : !      write(std_out,*)' cell_base(:,3)=',cell_base(:,3)
    1968              : !ENDDEBUG
    1969              : !        Checks that the basis vectors are OK for the target holohedry
    1970         2127 :          call holocell(cell_base,0,foundc,iholohedry,tolsym)
    1971         5274 :        else if(abs(reduceda-0.5d0)<tolsym)then
    1972          276 :          cell_base(:,1)=minim(:,ia)
    1973          276 :          cell_base(:,2)=minim(:,ib)-minim(:,ia)
    1974          276 :          cell_base(:,3)=minim(:,itrial)
    1975              : !        Checks that the basis vectors are OK for the target holohedry
    1976           69 :          call holocell(cell_base,0,foundc,iholohedry,tolsym)
    1977              :        end if
    1978              :      end if
    1979              : 
    1980              : !    Working hypothesis : the conventional cell is orthogonal,
    1981              : !    and the two other vectors are axes of the conventional cell
    1982       174747 :      if(foundc==0 .and. orthogonal==1 .and. ang90(itrial)==1)then
    1983              : 
    1984              : !      Compute the reduced coordinate of trial vector in the basis
    1985              : !      of the two other vectors
    1986        37462 :        reduceda=metmin(itrial,ia)/metmin(ia,ia)
    1987        37462 :        reducedb=metmin(itrial,ib)/metmin(ib,ib)
    1988       149848 :        cell_base(:,ia)=minim(:,ia)
    1989       149848 :        cell_base(:,ib)=minim(:,ib)
    1990        37462 :        if( (abs(abs(reduceda)-0.5d0)<tolsym .and. abs(reducedb)<tolsym ) .or. &
    1991        37462 : &       ( abs(reduceda)<tolsym .and. abs(abs(reducedb)-0.5d0)<tolsym)       )then
    1992         4596 :          if(abs(abs(reduceda)-0.5d0)<tolsym)center=ib
    1993         4596 :          if(abs(abs(reducedb)-0.5d0)<tolsym)center=ia
    1994         4596 :          fact=2
    1995              :          cell_base(:,itrial)= &
    1996        18384 : &         (minim(:,itrial)-reduceda*minim(:,ia)-reducedb*minim(:,ib) )*2.0d0
    1997         4596 :          call holocell(cell_base,0,foundc,iholohedry,tolsym)
    1998        32866 :        else if( abs(abs(reduceda)-0.5d0)<tolsym .and.&
    1999              : &         abs(abs(reducedb)-0.5d0)<tolsym       ) then
    2000          553 :          fact=2 ; center=-1
    2001              :          cell_base(:,itrial)= &
    2002         2212 : &         (minim(:,itrial)-reduceda*minim(:,ia)-reducedb*minim(:,ib) )*2.0d0
    2003          553 :          call holocell(cell_base,0,foundc,iholohedry,tolsym)
    2004              :        end if
    2005              :      end if
    2006              : 
    2007              : !    Working hypothesis : the conventional cell is orthogonal, and
    2008              : !    the trial vector is one of the future axes, and the face perpendicular to it is centered
    2009              :      if(foundc==0 .and. iholohedry==3 .and. &
    2010       174747 : &     ang90(ia)==1 .and. ang90(ib)==1 .and. equal(itrial)==1 )then
    2011          460 :        fact=2 ; center=itrial
    2012         1840 :        cell_base(:,ia)=minim(:,ia)+minim(:,ib)
    2013         1840 :        cell_base(:,ib)=minim(:,ia)-minim(:,ib)
    2014         1840 :        cell_base(:,itrial)=minim(:,itrial)
    2015              : !      Checks that the basis vectors are OK for the target holohedry
    2016          460 :        call holocell(cell_base,0,foundc,iholohedry,tolsym)
    2017              :      end if
    2018              : 
    2019              : !    DEBUG
    2020              : !    write(std_out,*)' after test_b, foundc=',foundc
    2021              : !    ENDDEBUG
    2022              : 
    2023              : !    Working hypothesis : the conventional cell is orthogonal, and
    2024              : !    the trial vector is one of the future axes
    2025       174747 :      if(foundc==0 .and. orthogonal==1)then
    2026              : !      Compute the projection of the two other vectors on the trial vector
    2027       105793 :        reduceda=metmin(itrial,ia)/metmin(itrial,itrial)
    2028       105793 :        reducedb=metmin(itrial,ib)/metmin(itrial,itrial)
    2029              : !      If both projections are half-integer, one might have found an axis
    2030       105793 :        if( abs(abs(reduceda)-0.5d0)<tolsym .and.&
    2031              : &       abs(abs(reducedb)-0.5d0)<tolsym       ) then
    2032        95468 :          vecta(:)=minim(:,ia)-reduceda*minim(:,itrial)
    2033        95468 :          vectb(:)=minim(:,ib)-reducedb*minim(:,itrial)
    2034        23867 :          norm2a=vecta(1)**2+vecta(2)**2+vecta(3)**2
    2035        23867 :          norm2b=vectb(1)**2+vectb(2)**2+vectb(3)**2
    2036        23867 :          scalarprod=vecta(1)*vectb(1)+vecta(2)*vectb(2)+vecta(3)*vectb(3)
    2037              : !        Note the order of selection : body-centered is prefered
    2038              : !        over face centered, which is correct for the tetragonal case
    2039        23867 :          if(abs(norm2a-norm2b)<tolsym*half*(norm2a+norm2b))then
    2040              : !          The lattice is body centered
    2041        17042 :            fact=2 ; center=-1
    2042        68168 :            cell_base(:,ia)=vecta(:)+vectb(:)
    2043        68168 :            cell_base(:,ib)=vecta(:)-vectb(:)
    2044        68168 :            cell_base(:,itrial)=minim(:,itrial)
    2045        17042 :            call holocell(cell_base,0,foundc,iholohedry,tolsym)
    2046         6825 :          else if(abs(scalarprod)<tolsym*half*(norm2a+norm2b))then
    2047              : !          The lattice is face centered
    2048            0 :            fact=2 ; center=-3
    2049            0 :            cell_base(:,ia)=2.0d0*vecta(:)
    2050            0 :            cell_base(:,ib)=2.0d0*vectb(:)
    2051            0 :            cell_base(:,itrial)=minim(:,itrial)
    2052            0 :            call holocell(cell_base,0,foundc,iholohedry,tolsym)
    2053              :          end if
    2054              :        end if
    2055              :      end if
    2056              : 
    2057              : !    DEBUG
    2058              : !    write(std_out,*)' after test_c, foundc=',foundc
    2059              : !    ENDDEBUG
    2060              : 
    2061              : !    Working hypothesis : the conventional cell is orthogonal,
    2062              : !    and body centered with no basis vector being an axis,
    2063              : !    in which case the basis vectors must be equal (even for orthorhombic)
    2064              :      if(foundc==0 .and. orthogonal==1 .and. &
    2065       174747 : &     equal(1)==1 .and. equal(2)==1 .and. equal(3)==1 )then
    2066              : !      Compute the combination of the two other vectors
    2067        92488 :        vecta(:)=minim(:,ia)+minim(:,ib)
    2068        92488 :        vectb(:)=minim(:,ia)-minim(:,ib)
    2069        23122 :        norm2a=vecta(1)**2+vecta(2)**2+vecta(3)**2
    2070        23122 :        norm2b=vectb(1)**2+vectb(2)**2+vectb(3)**2
    2071              : !      Project the trial vector on the first of the two vectors
    2072              :        reduceda=( minim(1,itrial)*vecta(1)+       &
    2073              : &       minim(2,itrial)*vecta(2)+       &
    2074        23122 : &       minim(3,itrial)*vecta(3) )/norm2a
    2075              :        reducedb=( minim(1,itrial)*vectb(1)+       &
    2076              : &       minim(2,itrial)*vectb(2)+       &
    2077        23122 : &       minim(3,itrial)*vectb(3) )/norm2b
    2078        23122 :        if( abs(abs(reduceda)-0.5d0)<tolsym )then
    2079              : !        The first vector is an axis
    2080         3653 :          fact=2 ; center=-1
    2081        14612 :          cell_base(:,ia)=vecta(:)
    2082        14612 :          vecta(:)=minim(:,itrial)-reduceda*vecta(:)
    2083        14612 :          vectb(:)=0.5d0*vectb(:)
    2084        14612 :          cell_base(:,ib)=vecta(:)+vectb(:)
    2085        14612 :          cell_base(:,itrial)=vecta(:)-vectb(:)
    2086         3653 :          call holocell(cell_base,0,foundc,iholohedry,tolsym)
    2087        19469 :        else if( abs(abs(reducedb)-0.5d0)<tolsym )then
    2088              : !        The second vector is an axis
    2089           84 :          fact=2 ; center=-1
    2090          336 :          cell_base(:,ib)=vectb(:)
    2091          336 :          vectb(:)=minim(:,itrial)-reducedb*vectb(:)
    2092          336 :          vecta(:)=0.5d0*vecta(:)
    2093          336 :          cell_base(:,ia)=vectb(:)+vecta(:)
    2094          336 :          cell_base(:,itrial)=vectb(:)-vecta(:)
    2095           84 :          call holocell(cell_base,0,foundc,iholohedry,tolsym)
    2096              :        end if
    2097              :      end if
    2098              : 
    2099              : !    Working hypothesis : the conventional cell is orthogonal,
    2100              : !    and face centered, in the case where two minimal vectors are equal
    2101       174747 :      if(foundc==0 .and. orthogonal==1 .and. equal(itrial)==1 ) then
    2102              : !      Compute the combination of these two vectors
    2103       155408 :        vecta(:)=minim(:,ia)+minim(:,ib)
    2104       155408 :        vectb(:)=minim(:,ia)-minim(:,ib)
    2105        38852 :        norm2a=vecta(1)**2+vecta(2)**2+vecta(3)**2
    2106        38852 :        norm2b=vectb(1)**2+vectb(2)**2+vectb(3)**2
    2107              : !      Project the trial vector on the two vectors
    2108              :        reduceda=( minim(1,itrial)*vecta(1)+       &
    2109              : &       minim(2,itrial)*vecta(2)+       &
    2110        38852 : &       minim(3,itrial)*vecta(3) )/norm2a
    2111              :        reducedb=( minim(1,itrial)*vectb(1)+       &
    2112              : &       minim(2,itrial)*vectb(2)+       &
    2113        38852 : &       minim(3,itrial)*vectb(3) )/norm2b
    2114        38852 :        if( (abs(abs(reduceda)-0.5d0)<tolsym .and. abs(reducedb)<tolsym ) .or. &
    2115        38852 : &       ( abs(reduceda)<tolsym .and. abs(abs(reducedb)-0.5d0)<tolsym)       )then
    2116          978 :          fact=2 ; center=-3
    2117              :          cell_base(:,itrial)= &
    2118         3912 : &         (minim(:,itrial)-reduceda*vecta(:)-reducedb*vectb(:) )*2.0d0
    2119         3912 :          cell_base(:,ia)=vecta(:)
    2120         3912 :          cell_base(:,ib)=vectb(:)
    2121          978 :          call holocell(cell_base,0,foundc,iholohedry,tolsym)
    2122              :        end if
    2123              :      end if
    2124              : 
    2125              : !    Working hypothesis : the conventional cell is orthogonal,
    2126              : !    face centered, but no two vectors are on the same "square"
    2127       174747 :      if(foundc==0 .and. orthogonal==1)then
    2128              : !      Compute the combination of these two vectors
    2129       414892 :        vecta(:)=minim(:,ia)+minim(:,ib)
    2130       414892 :        vectb(:)=minim(:,ia)-minim(:,ib)
    2131       103723 :        norm2a=vecta(1)**2+vecta(2)**2+vecta(3)**2
    2132       103723 :        norm2b=vectb(1)**2+vectb(2)**2+vectb(3)**2
    2133              : !      The trial vector length must be equal to one of these lengths
    2134       103723 :        if(abs(metmin(itrial,itrial)-norm2a)<tolsym*norm2a)then
    2135         1211 :          fact=2 ; center=-3
    2136         4844 :          cell_base(:,ia)=vecta(:)+minim(:,itrial)
    2137         4844 :          cell_base(:,ib)=vecta(:)-minim(:,itrial)
    2138              : !        Project vectb perpendicular to cell_base(:,ia) and cell_base(:,ib)
    2139         1211 :          norm2a=cell_base(1,ia)**2+cell_base(2,ia)**2+cell_base(3,ia)**2
    2140         1211 :          norm2b=cell_base(1,ib)**2+cell_base(2,ib)**2+cell_base(3,ib)**2
    2141              :          reduceda=( cell_base(1,ia)*vectb(1)+       &
    2142              : &         cell_base(2,ia)*vectb(2)+       &
    2143         1211 : &         cell_base(3,ia)*vectb(3) )/norm2a
    2144              :          reducedb=( cell_base(1,ib)*vectb(1)+       &
    2145              : &         cell_base(2,ib)*vectb(2)+       &
    2146         1211 : &         cell_base(3,ib)*vectb(3) )/norm2b
    2147         1211 :          if( abs(abs(reduceda)-0.5d0)<tolsym .and.         &
    2148              : &         abs(abs(reducedb)-0.5d0)<tolsym      )then
    2149            0 :            cell_base(:,itrial)=vectb(:)-reduceda*cell_base(:,ia)-reducedb*cell_base(:,ib)
    2150            0 :            call holocell(cell_base,0,foundc,iholohedry,tolsym)
    2151              :          end if
    2152       102512 :        else if(abs(metmin(itrial,itrial)-norm2b)<tolsym*norm2b)then
    2153        17144 :          fact=2 ; center=-3
    2154        68576 :          cell_base(:,ia)=vectb(:)+minim(:,itrial)
    2155        68576 :          cell_base(:,ib)=vectb(:)-minim(:,itrial)
    2156              : !        Project vecta perpendicular to cell_base(:,ia) and cell_base(:,ib)
    2157        17144 :          norm2a=cell_base(1,ia)**2+cell_base(2,ia)**2+cell_base(3,ia)**2
    2158        17144 :          norm2b=cell_base(1,ib)**2+cell_base(2,ib)**2+cell_base(3,ib)**2
    2159              :          reduceda=( cell_base(1,ia)*vecta(1)+       &
    2160              : &         cell_base(2,ia)*vecta(2)+       &
    2161        17144 : &         cell_base(3,ia)*vecta(3) )/norm2a
    2162              :          reducedb=( cell_base(1,ib)*vecta(1)+       &
    2163              : &         cell_base(2,ib)*vecta(2)+       &
    2164        17144 : &         cell_base(3,ib)*vecta(3) )/norm2b
    2165        17144 :          if( abs(abs(reduceda)-0.5d0)<tolsym .and.         &
    2166              : &         abs(abs(reducedb)-0.5d0)<tolsym      )then
    2167        65624 :            cell_base(:,itrial)=vecta(:)-reduceda*cell_base(:,ia)-reducedb*cell_base(:,ib)
    2168        16406 :            call holocell(cell_base,0,foundc,iholohedry,tolsym)
    2169              :          end if
    2170              :        end if
    2171              :      end if
    2172              : 
    2173              : !    Working hypothesis : the cell is rhombohedral, and
    2174              : !    the three minimal vectors have same length and same absolute scalar product
    2175              :      if(foundc==0 .and. iholohedry==5 .and. &
    2176       174747 : &     equal(1)==1 .and. equal(2)==1 .and. equal(3)==1 )then
    2177          347 :        if( abs(abs(metmin(1,2))-abs(metmin(1,3)))<tolsym*metmin(1,1) .and.     &
    2178          347 : &       abs(abs(metmin(1,2))-abs(metmin(2,3)))<tolsym*metmin(2,2)      )then
    2179          323 :          fact=1 ; center=0
    2180          323 :          cell_base(:,:)=minim(:,:)
    2181              : !        One might have to change the sign of one of the vectors
    2182          323 :          sign12=1 ; sign13=1 ; sign23=1
    2183          323 :          if(metmin(1,2)<0.0d0)sign12=-1
    2184          323 :          if(metmin(1,3)<0.0d0)sign13=-1
    2185          323 :          if(metmin(2,3)<0.0d0)sign23=-1
    2186          323 :          sumsign=sign12+sign13+sign23
    2187          323 :          if(sumsign==-1)then
    2188           50 :            if(sign12==1)cell_base(:,3)=-cell_base(:,3)
    2189           50 :            if(sign13==1)cell_base(:,2)=-cell_base(:,2)
    2190          200 :            if(sign23==1)cell_base(:,1)=-cell_base(:,1)
    2191          273 :          else if(sumsign==1)then
    2192            4 :            if(sign12==-1)cell_base(:,3)=-cell_base(:,3)
    2193            4 :            if(sign13==-1)cell_base(:,2)=-cell_base(:,2)
    2194           16 :            if(sign23==-1)cell_base(:,1)=-cell_base(:,1)
    2195              :          end if
    2196          323 :          call holocell(cell_base,0,foundc,iholohedry,tolsym)
    2197              :        end if
    2198              :      end if
    2199              : 
    2200              : !    DEBUG
    2201              : !    write(std_out,*)' after test_3a, foundc=',foundc
    2202              : !    write(std_out,*)' after test_3a, itrial=',itrial
    2203              : !    write(std_out,*)' after test_3a, equal(:)=',equal(:)
    2204              : !    ENDDEBUG
    2205              : 
    2206              : !    Working hypothesis : the cell is rhombohedral, one vector
    2207              : !    is parallel to the trigonal axis
    2208       174747 :      if(foundc==0 .and. iholohedry==5 .and. equal(itrial)==1 )then
    2209        20496 :        vecta(:)=minim(:,ia) ; vectb(:)=minim(:,ib)
    2210         2928 :        norm2trial=minim(1,itrial)**2+minim(2,itrial)**2+minim(3,itrial)**2
    2211              :        reduceda=( minim(1,itrial)*vecta(1)+       &
    2212              : &       minim(2,itrial)*vecta(2)+       &
    2213         2928 : &       minim(3,itrial)*vecta(3) )/norm2trial
    2214              :        reducedb=( minim(1,itrial)*vectb(1)+       &
    2215              : &       minim(2,itrial)*vectb(2)+       &
    2216         2928 : &       minim(3,itrial)*vectb(3) )/norm2trial
    2217              : !      DEBUG
    2218              : !      write(std_out,*)' reduceda,reducedb=',reduceda,reducedb
    2219              : !      ENDDEBUG
    2220         2928 :        if(abs(abs(reduceda)-1.0d0/3.0d0)<tolsym .and.      &
    2221              : &       abs(abs(reducedb)-1.0d0/3.0d0)<tolsym      ) then
    2222              : !        Possibly change of sign to make positive the scalar product with
    2223              : !        the vector parallel to the trigonal axis
    2224           82 :          if(reduceda<zero)vecta(:)=-vecta(:)
    2225          130 :          if(reducedb<zero)vectb(:)=-vectb(:)
    2226              : !        Projection on the orthogonal plane
    2227          148 :          vecta(:)=vecta(:)-abs(reduceda)*cell_base(:,itrial)
    2228          148 :          vectb(:)=vectb(:)-abs(reducedb)*cell_base(:,itrial)
    2229              : !        These two vectors should have an angle of 120 degrees
    2230           37 :          norm2a=vecta(1)**2+vecta(2)**2+vecta(3)**2
    2231           37 :          scalarprod=vecta(1)*vectb(1)+vecta(2)*vectb(2)+vecta(3)*vectb(3)
    2232              : !        DEBUG
    2233              : !        write(std_out,*)' norm2a,scalarprod=',norm2a,scalarprod
    2234              : !        ENDDEBUG
    2235           37 :          if(abs(two*scalarprod+norm2a)<tolsym*norm2a)then
    2236           12 :            fact=1 ; center=0
    2237           12 :            if(scalarprod>0.0d0)vectb(:)=-vectb(:)
    2238              : !          Now vecta and vectb have an angle of 120 degrees
    2239           48 :            cell_base(:,1)=cell_base(:,itrial)/3.0d0+vecta(:)
    2240           48 :            cell_base(:,2)=cell_base(:,itrial)/3.0d0+vectb(:)
    2241           48 :            cell_base(:,3)=cell_base(:,itrial)/3.0d0-vecta(:)-vectb(:)
    2242              : !          DEBUG
    2243              : !          write(std_out,*)' cell_base(:,1)=',cell_base(:,1)
    2244              : !          write(std_out,*)' cell_base(:,2)=',cell_base(:,2)
    2245              : !          write(std_out,*)' cell_base(:,3)=',cell_base(:,3)
    2246              : !          ENDDEBUG
    2247           12 :            call holocell(cell_base,0,foundc,iholohedry,tolsym)
    2248              :          end if
    2249              :        end if
    2250              :      end if
    2251              : 
    2252              : !    Working hypothesis : the cell is rhombohedral, one vector
    2253              : !    is in the plane perpendicular to the trigonal axis
    2254       174747 :      if(foundc==0 .and. iholohedry==5 .and. equal(itrial)==1 ) then
    2255        11664 :        vecta(:)=minim(:,ia)+minim(:,ib)
    2256        11664 :        vectb(:)=minim(:,ia)-minim(:,ib)
    2257         2916 :        norm2trial=cell_base(1,itrial)**2+cell_base(2,itrial)**2+cell_base(3,itrial)**2
    2258         2916 :        norm2a=vecta(1)**2+vecta(2)**2+vecta(3)**2
    2259         2916 :        norm2b=vecta(1)**2+vecta(2)**2+vecta(3)**2
    2260              :        reduceda=( cell_base(1,itrial)*vecta(1)+       &
    2261              : &       cell_base(2,itrial)*vecta(2)+       &
    2262         2916 : &       cell_base(3,itrial)*vecta(3) )/norm2trial
    2263              :        reducedb=( cell_base(1,itrial)*vectb(1)+       &
    2264              : &       cell_base(2,itrial)*vectb(2)+       &
    2265         2916 : &       cell_base(3,itrial)*vectb(3) )/norm2trial
    2266         2916 :        if(abs(norm2trial-norm2a)<tolsym*norm2a .and. &
    2267              : &       abs(abs(2*reduceda)-norm2trial)<tolsym*norm2trial    )then
    2268            0 :          fact=1 ; center=0
    2269            0 :          cell_base(:,1)=minim(:,ia)
    2270            0 :          cell_base(:,2)=-minim(:,ib)
    2271            0 :          cell_base(:,3)=-minim(:,ib)+2*reduceda*minim(:,itrial)
    2272            0 :          call holocell(cell_base,0,foundc,iholohedry,tolsym)
    2273         2916 :        else if (abs(norm2trial-norm2b)<tolsym*norm2b .and. &
    2274              : &         abs(abs(2*reducedb)-norm2trial)<tolsym*norm2trial    )then
    2275            0 :          fact=1 ; center=0
    2276            0 :          cell_base(:,1)=minim(:,ia)
    2277            0 :          cell_base(:,2)=minim(:,ib)
    2278            0 :          cell_base(:,3)=minim(:,ib)+2*reducedb*minim(:,itrial)
    2279            0 :          call holocell(cell_base,0,foundc,iholohedry,tolsym)
    2280              :        end if
    2281              :      end if
    2282              : 
    2283              : !    Working hypothesis : the cell is rhombohedral, two vectors
    2284              : !    are in the plane perpendicular to the trigonal axis
    2285       174747 :      if(foundc==0 .and. iholohedry==5 .and. equal(itrial)==1 ) then
    2286        20412 :        vecta(:)=minim(:,ia) ; vectb(:)=minim(:,ib)
    2287         2916 :        norm2a=vecta(1)**2+vecta(2)**2+vecta(3)**2
    2288         2916 :        norm2b=vectb(1)**2+vectb(2)**2+vectb(3)**2
    2289         2916 :        scalarprod=vecta(1)*vectb(1)+vecta(2)*vectb(2)+vecta(3)*vectb(3)
    2290         2916 :        if(abs(abs(2*scalarprod)-norm2a)<tolsym*norm2a)then
    2291              : !        This is in order to have 120 angle between vecta and vectb
    2292         1949 :          if(scalarprod>0.0d0)vectb(:)=-vectb(:)
    2293              :          reduceda=( cell_base(1,itrial)*vecta(1)+        &
    2294              : &         cell_base(2,itrial)*vecta(2)+        &
    2295         1238 : &         cell_base(3,itrial)*vecta(3) )/norm2a
    2296              :          reducedb=( cell_base(1,itrial)*vectb(1)+        &
    2297              : &         cell_base(2,itrial)*vectb(2)+        &
    2298         1238 : &         cell_base(3,itrial)*vectb(3) )/norm2b
    2299         1238 :          fact=1 ; center=0
    2300         4952 :          cell_base(:,1)=minim(:,itrial)
    2301         1238 :          if(abs(reduceda-0.5d0)<tolsym .and. abs(reducedb)<tolsym )then
    2302          900 :            cell_base(:,2)=minim(:,itrial)-vecta(:)
    2303          900 :            cell_base(:,3)=minim(:,itrial)-vecta(:)-vectb(:)
    2304          225 :            call holocell(cell_base,0,foundc,iholohedry,tolsym)
    2305         1013 :          else if(abs(reduceda-0.5d0)<tolsym.and. abs(reducedb+0.5d0)<tolsym )then
    2306           24 :            cell_base(:,2)=minim(:,itrial)-vecta(:)
    2307           24 :            cell_base(:,3)=minim(:,itrial)+vectb(:)
    2308            6 :            call holocell(cell_base,0,foundc,iholohedry,tolsym)
    2309         1007 :          else if(abs(reduceda)<tolsym .and. abs(reducedb+0.5d0)<tolsym )then
    2310            0 :            cell_base(:,2)=minim(:,itrial)+vectb(:)
    2311            0 :            cell_base(:,3)=minim(:,itrial)+vecta(:)+vectb(:)
    2312            0 :            call holocell(cell_base,0,foundc,iholohedry,tolsym)
    2313         1007 :          else if(abs(reduceda+0.5d0)<tolsym .and. abs(reducedb)<tolsym)then
    2314           24 :            cell_base(:,2)=minim(:,itrial)+vecta(:)
    2315           24 :            cell_base(:,3)=minim(:,itrial)+vecta(:)+vectb(:)
    2316            6 :            call holocell(cell_base,0,foundc,iholohedry,tolsym)
    2317         1001 :          else if(abs(reduceda+0.5d0)<tolsym .and. abs(reducedb-0.5d0)<tolsym)then
    2318         4004 :            cell_base(:,2)=minim(:,itrial)+vecta(:)
    2319         4004 :            cell_base(:,3)=minim(:,itrial)-vectb(:)
    2320         1001 :            call holocell(cell_base,0,foundc,iholohedry,tolsym)
    2321            0 :          else if(abs(reduceda)<tolsym .and. abs(reducedb-0.5d0)<tolsym )then
    2322            0 :            cell_base(:,2)=minim(:,itrial)-vectb(:)
    2323            0 :            cell_base(:,3)=minim(:,itrial)-vecta(:)-vectb(:)
    2324            0 :            call holocell(cell_base,0,foundc,iholohedry,tolsym)
    2325              :          end if
    2326              :        end if
    2327              :      end if
    2328              : 
    2329              : !    Working hypothesis : monoclinic holohedry, primitive. Then, two angles are 90 degrees
    2330              :      if(foundc==0 .and. iholohedry==2 .and. &
    2331       174747 : &     ang90(ia)==1 .and. ang90(ib)==1 ) then
    2332          297 :        fact=1 ; center=0
    2333         1188 :        cell_base(:,1)=minim(:,ia)
    2334         1188 :        cell_base(:,2)=minim(:,itrial)
    2335         1188 :        cell_base(:,3)=minim(:,ib)
    2336              : !      Checks that the basis vectors are OK for the target holohedry
    2337          297 :        call holocell(cell_base,0,foundc,iholohedry,tolsym)
    2338              :      end if
    2339              : 
    2340              : !    Monoclinic holohedry, one-face-centered cell
    2341              : !    Working hypothesis, two vectors have equal length.
    2342      1048482 :      do icase=1,5
    2343      1048482 :        if(foundc==0 .and. iholohedry==2 .and. equal(itrial)==1 ) then
    2344        14692 :          vecta(:)=cell_base(:,ia)+cell_base(:,ib)
    2345        14692 :          vectb(:)=cell_base(:,ia)-cell_base(:,ib)
    2346         3673 :          norm2a=vecta(1)**2+vecta(2)**2+vecta(3)**2
    2347         3673 :          norm2b=vectb(1)**2+vectb(2)**2+vectb(3)**2
    2348              : !        The minim(:,trial) vector belongs to the
    2349              : !        plane parallel to the cell_base(:,ia),cell_base(:,ib) plane
    2350              : !        In that plane, must try minim(:,itrial),
    2351              : !        as well as the 4 different combinations of
    2352              : !        minim(:,itrial) with the vectors in the plane
    2353         6850 :          if(icase==1)vectc(:)=minim(:,itrial)
    2354         5644 :          if(icase==2)vectc(:)=minim(:,itrial)+cell_base(:,ia)
    2355         5638 :          if(icase==3)vectc(:)=minim(:,itrial)+cell_base(:,ib)
    2356         5626 :          if(icase==4)vectc(:)=minim(:,itrial)-cell_base(:,ia)
    2357         5626 :          if(icase==5)vectc(:)=minim(:,itrial)-cell_base(:,ib)
    2358         3673 :          norm2c=vectc(1)**2+vectc(2)**2+vectc(3)**2
    2359              :          sca=vectc(1)*vecta(1)+&
    2360              : &         vectc(2)*vecta(2)+&
    2361         3673 : &         vectc(3)*vecta(3)
    2362              :          scb=vectc(1)*vectb(1)+&
    2363              : &         vectc(2)*vectb(2)+&
    2364         3673 : &         vectc(3)*vectb(3)
    2365              : !        DEBUG
    2366              : !        write(std_out,*)' symlatt : test iholohedry=2, sca,scb=',sca,scb
    2367              : !        ENDDEBUG
    2368         3673 :          if(abs(sca)<tolsym*sqrt(norm2c*norm2a) .or. abs(scb)<tolsym*sqrt(norm2c*norm2b))then
    2369          408 :            fact=2 ; center=3
    2370              : !          The itrial direction is centered
    2371         1632 :            cell_base(:,3)=vectc(:)
    2372          408 :            if(abs(sca)<tolsym*sqrt(norm2c*norm2a))then
    2373          560 :              cell_base(:,2)=vecta(:)
    2374          560 :              cell_base(:,1)=vectb(:)
    2375          140 :              call holocell(cell_base,0,foundc,iholohedry,tolsym)
    2376          268 :            else if(abs(scb)<tolsym*sqrt(norm2c*norm2b))then
    2377         1072 :              cell_base(:,2)=vectb(:)
    2378         1072 :              cell_base(:,1)=vecta(:)
    2379          268 :              call holocell(cell_base,0,foundc,iholohedry,tolsym)
    2380              :            end if
    2381              :          end if
    2382              :        end if
    2383              :      end do ! icase=1,5
    2384              : 
    2385              : !    Monoclinic holohedry, one-face-centered cell, but non equivalent.
    2386              : !    This case, one pair of vectors is orthogonal
    2387       174747 :      if(foundc==0 .and. iholohedry==2 .and. ang90(itrial)==1) then
    2388         4520 :        vecta(:)=minim(:,ia)
    2389         4520 :        vectb(:)=minim(:,ib)
    2390         1130 :        norm2a=vecta(1)**2+vecta(2)**2+vecta(3)**2
    2391         1130 :        norm2b=vectb(1)**2+vectb(2)**2+vectb(3)**2
    2392              : !      Project the trial vector on the two vectors
    2393              :        reduceda=( minim(1,itrial)*vecta(1)+       &
    2394              : &       minim(2,itrial)*vecta(2)+       &
    2395         1130 : &       minim(3,itrial)*vecta(3) )/norm2a
    2396              :        reducedb=( minim(1,itrial)*vectb(1)+       &
    2397              : &       minim(2,itrial)*vectb(2)+       &
    2398         1130 : &       minim(3,itrial)*vectb(3) )/norm2b
    2399         1130 :        if(abs(abs(reduceda)-0.5d0)<tolsym .or. abs(abs(reducedb)-0.5d0)<tolsym) then
    2400          713 :          fact=2 ; center=3
    2401          713 :          if(abs(abs(reduceda)-0.5d0)<tolsym)then
    2402           20 :            cell_base(:,2)=vecta(:)
    2403           20 :            cell_base(:,3)=vectb(:)
    2404           20 :            cell_base(:,1)=2*(minim(:,itrial)-reduceda*vecta(:))
    2405            5 :            call holocell(cell_base,0,foundc,iholohedry,tolsym)
    2406          708 :          else if(abs(abs(reducedb)-0.5d0)<tolsym)then
    2407         2832 :            cell_base(:,2)=vectb(:)
    2408         2832 :            cell_base(:,3)=vecta(:)
    2409         2832 :            cell_base(:,1)=2*(minim(:,itrial)-reducedb*vectb(:))
    2410          708 :            call holocell(cell_base,0,foundc,iholohedry,tolsym)
    2411              :          end if
    2412              :        end if
    2413              :      end if
    2414              : 
    2415              : !    Monoclinic holohedry, one-face-centered cell, but non equivalent.
    2416              : !    This case, no pair of vectors is orthogonal, no pair of vector of equal lentgh
    2417       260351 :      if(foundc==0 .and. iholohedry==2)then
    2418              : !      Try to find a vector that belongs to the mediator plane, or the binary vector.
    2419              : !      There must be one such vector, if centered monoclinic and no pair of vectors of equal length,
    2420              : !      either among the three vectors, or among one of their differences or sums.
    2421              : !      And there must be, among the two other vectors, one vector whose projection
    2422              : !      on this vector is half the length of this vector.
    2423        28768 :        vecta(:)=minim(:,ia)
    2424        28768 :        vectb(:)=minim(:,ib)
    2425              : !      Try the different possibilities for the vector on which the projection will be half ...
    2426        31919 :        do ii=1,5
    2427        48956 :          if(ii==1)vectc(:)=minim(:,itrial)
    2428        46817 :          if(ii==2)vectc(:)=minim(:,itrial)+vecta(:)
    2429        41126 :          if(ii==3)vectc(:)=minim(:,itrial)-vecta(:)
    2430        41126 :          if(ii==4)vectc(:)=minim(:,itrial)+vectb(:)
    2431        41015 :          if(ii==5)vectc(:)=minim(:,itrial)-vectb(:)
    2432        27380 :          norm2trial=vectc(1)**2+vectc(2)**2+vectc(3)**2
    2433              : !        Project the two vectors on the trial vector
    2434        27380 :          reduceda=( vectc(1)*vecta(1)+vectc(2)*vecta(2)+vectc(3)*vecta(3) )/norm2trial
    2435        27380 :          reducedb=( vectc(1)*vectb(1)+vectc(2)*vectb(2)+vectc(3)*vectb(3) )/norm2trial
    2436        27380 :          found=0
    2437        27380 :          if(abs(abs(reduceda)-0.5d0)<tolsym)then
    2438         1967 :            vin1(:)=vectc(:)
    2439         7868 :            vin2(:)=2.0d0*(vecta(:)-reduceda*vectc(:))
    2440         1967 :            vext(:)=vectb(:)
    2441              :            found=1
    2442        25413 :          else if(abs(abs(reducedb)-0.5d0)<tolsym)then
    2443          686 :            vin1(:)=vectc(:)
    2444         2744 :            vin2(:)=2.0d0*(vectb(:)-reduceda*vectc(:))
    2445          686 :            vext(:)=vecta(:)
    2446              :            found=1
    2447              :          end if
    2448         4539 :          if(found==1)exit
    2449              :        end do
    2450              : !      Now, vin1 and vin2 are perpendicular to each other, and in the plane that contains the binary vector.
    2451              : !      One of them must be the binary vector if any.
    2452              : !      On the other hand, vext is out-of-plane. Might belong to the mediator plane or not.
    2453              : !      If C monoclinc, then the projection of this vext on the binary vector will be either 0 or +1/2 or -1/2.
    2454              : !      The binary axis must be stored in cell_base(:,2) for conventional C-cell
    2455         7192 :        if(found==1)then
    2456         2653 :          found=0
    2457              : 
    2458              : !        Test vin1 being the binary axis
    2459         2653 :          norm2trial=vin1(1)**2+vin1(2)**2+vin1(3)**2
    2460         2653 :          reduceda=(vext(1)*vin1(1)+vext(2)*vin1(2)+vext(3)*vin1(3))/norm2trial
    2461         2653 :          if(abs(reduceda)<tolsym)then  ! vin1 is the binary axis and vext is in the mediator plane
    2462         4868 :            found=1
    2463         4868 :            cell_base(:,1)=vin2(:)
    2464         4868 :            cell_base(:,2)=vin1(:)
    2465         4868 :            cell_base(:,3)=vext(:)
    2466         1436 :          else if(abs(abs(reduceda)-0.5d0)<tolsym)then  ! vin1 is the binary axis and vext has +1/2 or -1/2 as projection
    2467          144 :            found=1
    2468          144 :            cell_base(:,1)=vin2(:)
    2469          144 :            cell_base(:,2)=vin1(:)
    2470          144 :            cell_base(:,3)=vext(:)-reduceda*vin1(:)+vin2(:)*half
    2471              :          else
    2472              : !          Test vin2 being the binary axis
    2473         1400 :            norm2trial=vin2(1)**2+vin2(2)**2+vin2(3)**2
    2474         1400 :            reduceda=(vext(1)*vin2(1)+vext(2)*vin2(2)+vext(3)*vin2(3))/norm2trial
    2475         1400 :            if(abs(reduceda)<tolsym)then  ! vin2 is the binary axis and vext is in the mediator plane
    2476          328 :              found=1
    2477          328 :              cell_base(:,1)=vin1(:)
    2478          328 :              cell_base(:,2)=vin2(:)
    2479          328 :              cell_base(:,3)=vext(:)
    2480         1318 :            else if(abs(abs(reduceda)-0.5d0)<tolsym)then  ! vin2 is the binary axis and vext has +1/2 or -1/2 as projection
    2481            0 :              found=1
    2482            0 :              cell_base(:,1)=vin1(:)
    2483            0 :              cell_base(:,2)=vin2(:)
    2484            0 :              cell_base(:,3)=vext(:)-reduceda*vin2(:)+vin1(:)*half
    2485              :            end if
    2486              :          end if
    2487              : 
    2488              :          if(found==1)then
    2489         1335 :            fact=2 ; center=3
    2490         1335 :            call holocell(cell_base,0,foundc,iholohedry,tolsym)
    2491              :          end if
    2492              :        end if
    2493              :      end if
    2494              : 
    2495              :    end do ! Do-loop on three different directions
    2496              :  end do !  Do-loop on different target holohedries
    2497              : 
    2498        39896 :  if(foundc==0)then
    2499         1601 :    iholohedry=1 ; fact=1 ; center=0
    2500         1601 :    cell_base(:,:)=minim(:,:)
    2501              :  end if
    2502              : 
    2503              : !DEBUG
    2504              : !write(std_out,*)' symlatt : done with centering tests, foundc=',foundc
    2505              : !write(std_out,*)'  center=',center
    2506              : !write(std_out,*)'  iholohedry=',iholohedry
    2507              : !call flush(std_out)
    2508              : !ENDDEBUG
    2509              : 
    2510              : !--------------------------------------------------------------------------
    2511              : !Final check on the Bravais lattice, using the basis vectors
    2512              : 
    2513              : !Recompute the metric tensor
    2514        39896 :  if(foundc==1)then
    2515       153180 :    do ii=1,3
    2516              :      metmin(:,ii)=cell_base(1,:)*cell_base(1,ii)+&
    2517              : &     cell_base(2,:)*cell_base(2,ii)+&
    2518       497835 : &     cell_base(3,:)*cell_base(3,ii)
    2519              :    end do
    2520              :  end if
    2521              : 
    2522              : !Examine the angles and vector lengths
    2523        39896 :  ang90(:)=0
    2524        39896 :  if(metmin(1,2)**2<tolsym**2*metmin(1,1)*metmin(2,2))ang90(3)=1
    2525        39896 :  if(metmin(1,3)**2<tolsym**2*metmin(1,1)*metmin(3,3))ang90(2)=1
    2526        39896 :  if(metmin(2,3)**2<tolsym**2*metmin(2,2)*metmin(3,3))ang90(1)=1
    2527        39896 :  equal(:)=0
    2528        39896 :  if(abs(metmin(1,1)-metmin(2,2))<tolsym*half*(metmin(1,1)+metmin(2,2)))equal(3)=1
    2529        39896 :  if(abs(metmin(1,1)-metmin(3,3))<tolsym*half*(metmin(1,1)+metmin(3,3)))equal(2)=1
    2530        39896 :  if(abs(metmin(2,2)-metmin(3,3))<tolsym*half*(metmin(2,2)+metmin(3,3)))equal(1)=1
    2531              : 
    2532              : !DEBUG
    2533              : !write(std_out,*)' symlatt : recompute the  metric tensor '
    2534              : !write(std_out,*)'  ang90=',ang90
    2535              : !write(std_out,*)'  equal=',equal
    2536              : !call flush(std_out)
    2537              : !ENDDEBUG
    2538              : 
    2539              : !The axes will be aligned with the previously determined
    2540              : !basis vectors, EXCEPT for the tetragonal cell, see later
    2541        39896 :  axes(:,:)=cell_base(:,:)
    2542              : 
    2543        39896 :  found=0
    2544              : !Check orthogonal conventional cells
    2545        39896 :  if(ang90(1)+ang90(2)+ang90(3)==3)then
    2546              : 
    2547              : !  Cubic system
    2548        32432 :    if(equal(1)+equal(2)+equal(3)==3)then
    2549              : !    However, one-face centered is not admitted
    2550        24402 :      if(center==0 .or. center==-1 .or. center==-3)then
    2551        16502 :        iholohedry=7 ; found=1
    2552         7900 :        if(center==0)then
    2553         6709 :          write(msg,'(a,a)')ch10,' symlatt: the Bravais lattice is cP (primitive cubic)'
    2554        17693 :        else if(center==-1)then
    2555         1191 :          write(msg,'(a,a)')ch10,' symlatt: the Bravais lattice is cI (body-centered cubic)'
    2556              :        else if(center==-3)then
    2557        16502 :          write(msg,'(a,a)')ch10,' symlatt: the Bravais lattice is cF (face-centered cubic)'
    2558              :        end if
    2559              :      end if
    2560              :    end if
    2561              : 
    2562              : !  Tetragonal system
    2563         8030 :    if(found==0 .and. &
    2564              : &   (equal(1)==1 .or. equal(2)==1 .or. equal(3)==1) )then
    2565              : !    However, one-face centered or face-centered is not admitted
    2566         5429 :      if(center==0 .or. center==-1)then
    2567         5351 :        iholohedry=4 ; found=1
    2568         5351 :        if(equal(1)==1)then
    2569        24540 :          axes(:,3)=cell_base(:,1) ; axes(:,1)=cell_base(:,2) ; axes(:,2)=cell_base(:,3)
    2570         2897 :        else if(equal(2)==1)then
    2571         1260 :          axes(:,3)=cell_base(:,2) ; axes(:,2)=cell_base(:,1) ; axes(:,1)=cell_base(:,3)
    2572         2771 :        else if(equal(3)==1)then
    2573         2771 :          axes(:,:)=cell_base(:,:)
    2574              :        end if
    2575         5351 :        if(center==0)then
    2576         4745 :          write(msg,'(a,a)')ch10,' symlatt: the Bravais lattice is tP (primitive tetragonal)'
    2577              :        else if(center==-1)then
    2578          606 :          write(msg,'(a,a)')ch10,' symlatt: the Bravais lattice is tI (body-centered tetragonal)'
    2579              :        end if
    2580              :      end if
    2581              :    end if
    2582              : 
    2583              : !  Orthorhombic system
    2584              :    if(found==0)then
    2585         2679 :      iholohedry=3 ; found=1
    2586         2679 :      axes(:,:)=cell_base(:,:)
    2587         2679 :      if(center==0)then
    2588         1751 :        write(msg,'(a,a)')ch10,' symlatt: the Bravais lattice is oP (primitive orthorhombic)'
    2589          928 :      else if(center==-1)then
    2590          302 :        write(msg,'(a,a)')ch10,' symlatt: the Bravais lattice is oI (body-centered orthorhombic)'
    2591          626 :      else if(center==1 .or. center==2 .or. center==3)then
    2592          526 :        write(msg,'(a,a)')ch10,' symlatt: the Bravais lattice is oC (one-face-centered orthorhombic)'
    2593          100 :      else if(center==-3)then
    2594          100 :        write(msg,'(a,a)')ch10,' symlatt: the Bravais lattice is oF (face-centered orthorhombic)'
    2595              :      end if
    2596              :    end if
    2597              : 
    2598              :  else
    2599              : 
    2600              : !  Hexagonal system
    2601         7464 :    if(found==0 .and. ang90(1)==1 .and. ang90(2)==1 .and. equal(3)==1 .and. (2*metmin(2,1)+metmin(1,1))<tolsym*metmin(1,1))then
    2602         2193 :      iholohedry=6 ; found=1
    2603         2193 :      write(msg,'(a,a)')ch10,' symlatt: the Bravais lattice is hP (primitive hexagonal)'
    2604              :    end if
    2605              : 
    2606              : !  Rhombohedral system
    2607              :    if(found==0 .and. equal(1)+equal(2)+equal(3)==3 .and.       &
    2608         5271 : &   abs(metmin(2,1)-metmin(3,2))<tolsym*metmin(2,2)             .and.       &
    2609              : &   abs(metmin(2,1)-metmin(3,1))<tolsym*metmin(1,1) )then
    2610         1573 :      iholohedry=5 ; found=1
    2611         1573 :      write(msg,'(a,a)')ch10,' symlatt: the Bravais lattice is hR (rhombohedral)'
    2612              :    end if
    2613              : 
    2614              : !  Monoclinic system
    2615         3698 :    if(found==0 .and. ang90(1)+ang90(2)+ang90(3)==2 )then
    2616         2097 :      iholohedry=2 ; found=1
    2617         2097 :      if(center==0)then
    2618          297 :        write(msg,'(a,a)')ch10,' symlatt: the Bravais lattice is mP (primitive monoclinic)'
    2619         1800 :      else if(center==3)then
    2620         1800 :        write(msg,'(a,a)')ch10,' symlatt: the Bravais lattice is mC (one-face-centered monoclinic)'
    2621              :      end if
    2622              :    end if
    2623              : 
    2624              : !  Triclinic system
    2625              :    if(found==0)then
    2626         1601 :      iholohedry=1 ; found=1
    2627         1601 :      write(msg,'(a,a)')ch10,' symlatt: the Bravais lattice is aP (primitive triclinic)'
    2628              :    end if
    2629              : 
    2630              :  end if
    2631              : 
    2632        39896 :  call wrtout(iout,msg)
    2633              : 
    2634              : !DEBUG
    2635              : !write(std_out,*)' symlatt : after checking conventional orthogonal cell '
    2636              : !call flush(std_out)
    2637              : !ENDDEBUG
    2638              : 
    2639              : !--------------------------------------------------------------------------
    2640              : !Make sure that axes form a right-handed coordinate system
    2641              : !(Note : this should be done in the body of the routine,
    2642              : !by making changes that leave the sign of the mixed product of the three
    2643              : !vectors invariant)
    2644              :  determinant=axes(1,1)*axes(2,2)*axes(3,3) &
    2645              : & +axes(1,2)*axes(2,3)*axes(3,1) &
    2646              : & +axes(1,3)*axes(3,2)*axes(2,1) &
    2647              : & -axes(1,1)*axes(3,2)*axes(2,3) &
    2648              : & -axes(1,3)*axes(2,2)*axes(3,1) &
    2649        39896 : & -axes(1,2)*axes(2,1)*axes(3,3)
    2650        39896 :  if(determinant<zero)then
    2651        70356 :    axes(:,:)=-axes(:,:)
    2652              :  end if
    2653              : 
    2654              : !DEBUG
    2655              : !write(std_out,'(a,i4)')' symlatt : before itrial do loop, iholohedry= ',iholohedry
    2656              : !write(std_out,'(a,3es14.6,a,3es14.6,a,3es14.6)')' rprimd=',&
    2657              : !&  rprimd(:,1),ch10,rprimd(:,2),ch10,rprimd(:,3)
    2658              : !call flush(std_out)
    2659              : !ENDDEBUG
    2660              : 
    2661              : !--------------------------------------------------------------------------
    2662              : !Prefer symmetry axes on the same side as the primitive axes,
    2663              : !when the changes are allowed
    2664        63189 :  do itrial=1,100
    2665              : 
    2666              : !  DEBUG
    2667              : !  write(std_out,'(a)')' '
    2668              : !  write(std_out,'(a,i5)')' symlatt : itrial do loop, itrial= ',itrial
    2669              : !  write(std_out,'(a,3es14.6,a,3es14.6,a,3es14.6)')' axes  =',&
    2670              : !  &  axes(:,1),ch10,axes(:,2),ch10,axes(:,3)
    2671              : !  call flush(std_out)
    2672              : !  ENDDEBUG
    2673              : 
    2674       252756 :    do ia=1,3
    2675              :      scprods(ia,:)=axes(1,ia)*rprimd(1,:)+&
    2676              : &     axes(2,ia)*rprimd(2,:)+&
    2677       758268 : &     axes(3,ia)*rprimd(3,:)
    2678       758268 :      norm2trial=sum(axes(:,ia)**2)
    2679       821457 :      scprods(ia,:)=scprods(ia,:)/sqrt(norm2trial)
    2680              :    end do
    2681       252756 :    do ia=1,3
    2682       758268 :      norm2trial=sum(rprimd(:,ia)**2)
    2683       821457 :      scprods(:,ia)=scprods(:,ia)/sqrt(norm2trial)
    2684              :    end do
    2685              : 
    2686              : !DEBUG
    2687              : !  write(std_out,'(a,3f12.6)')' diagonal scalar products ',scprods(1,1),scprods(2,2),scprods(3,3)
    2688              : !  call flush(std_out)
    2689              : !ENDDEBUG
    2690              : 
    2691              : !  One should now try all the generators of the
    2692              : !  proper rotations of each Bravais lattice, coupled with change of
    2693              : !  signs of each vector. This is not done systematically in what follows ...
    2694              : !  Here, the third axis is left unchanged
    2695        63189 :    if(iholohedry/=5)then
    2696        58811 :      if(scprods(1,1)<-tolsym .and. scprods(2,2)<-tolsym)then
    2697        16408 :        axes(:,1)=-axes(:,1) ; axes(:,2)=-axes(:,2)
    2698              :        cycle
    2699              :      end if
    2700              :    end if
    2701              : !  The first (or second) axis is left unchanged
    2702        60845 :    if(iholohedry/=5 .and. iholohedry/=6)then
    2703        54274 :      if(scprods(2,2)<-tolsym .and. scprods(3,3)<-tolsym)then
    2704         8757 :        axes(:,2)=-axes(:,2) ; axes(:,3)=-axes(:,3)
    2705              :        cycle
    2706              :      end if
    2707        53023 :      if(scprods(1,1)<-tolsym .and. scprods(3,3)<-tolsym)then
    2708         3318 :        axes(:,1)=-axes(:,1) ; axes(:,3)=-axes(:,3)
    2709              :        cycle
    2710              :      end if
    2711              :    end if
    2712              : !  Permutation of the three axis
    2713        59120 :    if(iholohedry==5 .or. iholohedry==7)then
    2714        45199 :      trace=scprods(1,1)+scprods(2,2)+scprods(3,3)
    2715        45199 :      if(trace+tolsym< scprods(1,2)+scprods(2,3)+scprods(3,1))then
    2716         3591 :        vecta(:)=axes(:,1) ; axes(:,1)=axes(:,3)
    2717         3591 :        axes(:,3)=axes(:,2); axes(:,2)=vecta(:)
    2718              :        cycle
    2719              :      end if
    2720        44686 :      if(trace+tolsym < scprods(1,3)+scprods(2,1)+scprods(3,2))then
    2721       121933 :        vecta(:)=axes(:,1) ; axes(:,1)=axes(:,2)
    2722       121933 :        axes(:,2)=axes(:,3); axes(:,3)=vecta(:)
    2723              :        cycle
    2724              :      end if
    2725              : !    This case is observed when the three new vectors
    2726              : !    are pointing opposite to the three original vectors
    2727              : !    One takes their opposite, then switch two of them, then process
    2728              : !    them again in the loop
    2729       354471 :      if(sum(scprods(:,:))<-tolsym)then
    2730         5168 :        axes(:,1)=-axes(:,1)
    2731         5168 :        vecta(:)=-axes(:,2)
    2732         5168 :        axes(:,2)=-axes(:,3)
    2733         5168 :        axes(:,3)=vecta(:)
    2734              :        cycle
    2735              :      end if
    2736              :    end if
    2737              : 
    2738              : !  Actually, for iholohedry==7, can test specifically all possibilities
    2739              : !  and take the best one.
    2740              : !  Not activated, because changing the order of symmetries in many tests !
    2741              :    if(iholohedry==7 .and. .false.)then
    2742              : !  if(iholohedry==7)then
    2743              : 
    2744              : !DEBUG
    2745              : !write(std_out,'(a,a)')ch10,' enter search of all possibilities for iholohedry==7 '
    2746              : !write(std_out,'(a,3es14.6,a,3es14.6,a,3es14.6)')' axes  =',&
    2747              : !&  axes(:,1),ch10,axes(:,2),ch10,axes(:,3)
    2748              : !call flush(std_out)
    2749              : !ENDDEBUG
    2750              : 
    2751              :      do iaxis1=1,3
    2752              :        axes_try(:,1)=axes(:,iaxis1)
    2753              :        do iaxis2=1,2
    2754              :          if(iaxis1==1)axes_try(:,2)=axes(:,1+iaxis2)
    2755              :          if(iaxis1==2)axes_try(:,2)=axes(:,2*iaxis2-1)
    2756              :          if(iaxis1==3)axes_try(:,2)=axes(:,iaxis2)
    2757              :          if(iaxis2==1)axes_try(:,3)=axes(:,3)
    2758              :          if(iaxis2==2)axes_try(:,3)=axes(:,1)
    2759              :          if(iaxis1==1.and.iaxis2==2)axes_try(:,3)=axes(:,2)
    2760              :          if(iaxis1==3.and.iaxis2==1)axes_try(:,3)=axes(:,2)
    2761              :          do isign1=1,-1,-2
    2762              :            axes_try(:,1)=-axes_try(:,1)
    2763              :            do isign2=1,-1,-2
    2764              :              axes_try(:,2)=-axes_try(:,2)
    2765              :              determinant=axes_try(1,1)*axes_try(2,2)*axes_try(3,3) &
    2766              : &                       +axes_try(1,2)*axes_try(2,3)*axes_try(3,1) &
    2767              : &                       +axes_try(1,3)*axes_try(3,2)*axes_try(2,1) &
    2768              : &                       -axes_try(1,1)*axes_try(3,2)*axes_try(2,3) &
    2769              : &                       -axes_try(1,3)*axes_try(2,2)*axes_try(3,1) &
    2770              : &                       -axes_try(1,2)*axes_try(2,1)*axes_try(3,3)
    2771              :              if(determinant<zero)axes_try(:,3)=-axes_try(:,3)
    2772              :              do ia=1,3
    2773              :                scprods(ia,:)=axes_try(1,ia)*rprimd(1,:)+&
    2774              : &                            axes_try(2,ia)*rprimd(2,:)+&
    2775              : &                            axes_try(3,ia)*rprimd(3,:)
    2776              :                norm2trial=sum(axes_try(:,ia)**2)
    2777              :                scprods(ia,:)=scprods(ia,:)/sqrt(norm2trial)
    2778              :              end do
    2779              :              do ia=1,3
    2780              :                norm2trial=sum(rprimd(:,ia)**2)
    2781              :                scprods(:,ia)=scprods(:,ia)/sqrt(norm2trial)
    2782              :              end do
    2783              :              trace=scprods(1,1)+scprods(2,2)+scprods(3,3)
    2784              :              if(iaxis1==1.and.iaxis2==1.and.isign1==1.and.isign2==1)then
    2785              :                trace_best=trace
    2786              :                axes_best=axes_try
    2787              :              else if (trace>trace_best+tolsym)then
    2788              :                trace_best=trace
    2789              :                axes_best=axes_try
    2790              :              endif
    2791              :            enddo ! isign2
    2792              :          enddo ! isign1
    2793              :        enddo ! iaxes2
    2794              :      enddo ! iaxes1
    2795              :      axes=axes_best
    2796              :    endif ! iholohedry=7
    2797            0 :    exit
    2798              :  end do
    2799              : 
    2800              : !--------------------------------------------------------------------------
    2801              : 
    2802              : !DEBUG
    2803              : !write(std_out,'(a,a)')ch10,' after order/sign optimization do-loop '
    2804              : !write(std_out,'(a,3es14.6,a,3es14.6,a,3es14.6)')' rprimd=',&
    2805              : !&  rprimd(:,1),ch10,rprimd(:,2),ch10,rprimd(:,3)
    2806              : !write(std_out,'(a,3es14.6,a,3es14.6,a,3es14.6)')' axes  =',&
    2807              : !&  axes(:,1),ch10,axes(:,2),ch10,axes(:,3)
    2808              : !call flush(std_out)
    2809              : !ENDDEBUG
    2810              : 
    2811              : !Compute the coordinates of rprimd in the system defined by axes(:,:)
    2812        39896 :  call matr3inv(axes,axesinvt)
    2813       159584 :  do ii=1,3
    2814              :    coord(:,ii)=rprimd(1,ii)*axesinvt(1,:)+ &
    2815              : &   rprimd(2,ii)*axesinvt(2,:)+ &
    2816       518648 : &   rprimd(3,ii)*axesinvt(3,:)
    2817              :  end do
    2818              : 
    2819              : !Check that the coordinates are integers, or half-integer in
    2820              : !the case there is a centering, and generate integer coordinates
    2821       159584 :  do ii=1,3
    2822       518648 :    do jj=1,3
    2823       359064 :      val=coord(ii,jj)*fact
    2824       359064 :      if(abs(val-nint(val))>fact*two*tolsym)then
    2825              :        write(msg,'(4a,a,3es18.10,a,a,3es18.10,a,a,3es18.10,a,a,i4)')&
    2826            0 :        'One of the coordinates of rprimd in axes is non-integer,',ch10,&
    2827            0 :        'or non-half-integer (if centering), within 2*tolsym.',ch10,&
    2828            0 :        'coord=',coord(:,1),ch10,&
    2829            0 :        '      ',coord(:,2),ch10,&
    2830            0 :        '      ',coord(:,3),ch10,&
    2831            0 :        'fact=',fact
    2832            0 :        ABI_BUG(msg)
    2833              :      end if
    2834       478752 :      icoord(ii,jj)=nint(val)
    2835              :    end do
    2836              :  end do
    2837              : 
    2838              : !Store the bravais lattice characteristics
    2839        39896 :  bravais(1)=iholohedry
    2840        39896 :  bravais(2)=center
    2841       159584 :  bravais(3:5)=icoord(1:3,1)
    2842       159584 :  bravais(6:8)=icoord(1:3,2)
    2843       159584 :  bravais(9:11)=icoord(1:3,3)
    2844              : 
    2845              : !--------------------------------------------------------------------------
    2846              : !Initialize the set of symmetries
    2847              : !Bravais lattices are always invariant under identity and inversion
    2848              : 
    2849              : !Identity and inversion
    2850       997400 :  ptsymrel(:,:,1)=identity(:,:) ; ptsymrel(:,:,2)=-identity(:,:)
    2851        39896 :  nptsym=2
    2852              : 
    2853              : !Keep this for IFCv70 compiler
    2854              :  if(nptsym/=2)then
    2855              :    write(msg,'(a,a,a,a)')ch10,&
    2856              :    ' symlatt : BUG -',ch10,&
    2857              :    '  Crazy error, compiler bug '
    2858              :    call wrtout(std_out,msg)
    2859              :  end if
    2860              : 
    2861              : !--------------------------------------------------------------------------
    2862              : !Initialize some generators
    2863              : !gen6 is defined in a coordinated system with gamma=120 degrees
    2864        39896 :  gen6(:,:)=0  ; gen6(3,3)=1  ; gen6(1,1)=1  ; gen6(1,2)=-1 ; gen6(2,1)=1
    2865        39896 :  gen3(:,:)=0  ; gen3(1,2)=1  ; gen3(2,3)=1  ; gen3(3,1)=1
    2866        39896 :  gen2xy(:,:)=0 ; gen2xy(2,1)=1 ; gen2xy(1,2)=1; gen2xy(3,3)=1
    2867        39896 :  gen2y(:,:)=0 ; gen2y(1,1)=-1; gen2y(2,2)=1 ; gen2y(3,3)=-1
    2868        39896 :  gen2z(:,:)=0 ; gen2z(1,1)=-1; gen2z(2,2)=-1; gen2z(3,3)=1
    2869              : 
    2870              : !--------------------------------------------------------------------------
    2871              : 
    2872              : !Define the generators for each holohedry (inversion is already included)
    2873        39896 :  if(iholohedry==6)then
    2874         2193 :    ngen=2
    2875        28509 :    gen(:,:,1)=gen2xy(:,:) ; order(1)=2
    2876        28509 :    gen(:,:,2)=gen6(:,:)   ; order(2)=6
    2877        37703 :  else if(iholohedry==5)then
    2878         1573 :    ngen=2
    2879        20449 :    gen(:,:,1)=gen2xy(:,:) ; order(1)=2
    2880        20449 :    gen(:,:,2)=gen3(:,:)   ; order(2)=3
    2881              :  else
    2882       469690 :    gen(:,:,1)=gen2y(:,:)  ; order(1)=2
    2883       469690 :    gen(:,:,2)=gen2z(:,:)  ; order(2)=2
    2884       469690 :    gen(:,:,3)=gen2xy(:,:) ; order(3)=2
    2885       469690 :    gen(:,:,4)=gen3(:,:)   ; order(4)=3
    2886        36130 :    if(iholohedry<=4)ngen=iholohedry-1
    2887        36130 :    if(iholohedry==7)ngen=4
    2888              :  end if
    2889              : 
    2890              : !Build the point symmetry operations from generators, in the reduced system
    2891              : !of coordinates defined by axes(:,:)
    2892        39896 :  if(ngen/=0)then
    2893       166943 :    do igen=1,ngen
    2894      1410298 :      do isym=1+nptsym,order(igen)*nptsym
    2895      1281650 :        jsym=isym-nptsym
    2896      5255248 :        do ii=1,3
    2897              :          ptsymrel(:,ii,isym)=gen(:,1,igen)*ptsymrel(1,ii,jsym)+ &
    2898              : &         gen(:,2,igen)*ptsymrel(2,ii,jsym)+ &
    2899     16661450 : &         gen(:,3,igen)*ptsymrel(3,ii,jsym)
    2900              :        end do
    2901              :      end do
    2902       166943 :      nptsym=order(igen)*nptsym
    2903              : 
    2904              :    end do
    2905              :  end if
    2906              : 
    2907              : !--------------------------------------------------------------------------
    2908              : 
    2909              : !Transform symmetry matrices in the system defined by rprimd
    2910        39896 :  call symrelrot(nptsym,axes,rprimd,ptsymrel,tolsym)
    2911              : 
    2912              : !DEBUG
    2913              : !write(std_out,'(a)') ' symlatt : exit '
    2914              : !call flush(std_out)
    2915              : !stop
    2916              : !ENDDEBUG
    2917              : 
    2918        39896 : end subroutine symlatt
    2919              : !!***
    2920              : 
    2921       199762 : end module m_symfind
    2922              : !!***
        

Generated by: LCOV version 2.3-1