LCOV - code coverage report
Current view: top level - src/57_iovars - m_ingeo.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 73.5 % 1027 755
Test Date: 2026-09-20 15:27:41 Functions: 100.0 % 5 5

            Line data    Source code
       1              : !!****m* ABINIT/m_ingeo
       2              : !! NAME
       3              : !!  m_ingeo
       4              : !!
       5              : !! FUNCTION
       6              : !! Initialize geometry variables for the ABINIT code.
       7              : !!
       8              : !! COPYRIGHT
       9              : !!  Copyright (C) 1998-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_ingeo
      23              : 
      24              :  use defs_basis
      25              :  use m_abicore
      26              :  use m_errors
      27              :  use m_atomdata
      28              :  use m_sort
      29              :  use m_dtset
      30              : 
      31              :  use m_matrix,        only : mati3inv, mati3det
      32              :  use m_symtk,         only : chkorthsy, symrelrot, chkprimit, symatm, &
      33              : &                            symmetrize_rprimd, symmetrize_tnons,symmetrize_xred
      34              :  use m_spgbuilder,    only : gensymspgr, gensymshub, gensymshub4
      35              :  use m_symfind,       only : symfind, symfind_expert, symanal, symlatt
      36              :  use m_geometry,      only : mkradim, mkrdim, xcart2xred, xred2xcart, &
      37              : &                            randomcellpos, metric, reduce2primitive, cart2spinaxis
      38              :  use m_parser,        only : intagm, intagm_img, geo_t, geo_from_abivar_string, get_acell_rprim
      39              :  use m_numeric_tools, only : geteuler
      40              : 
      41              :  implicit none
      42              : 
      43              :  private
      44              : !!***
      45              : 
      46              :  public :: ingeo        ! Initialize geometry variables for the ABINIT code.
      47              :  public :: invacuum     ! Determine whether there is vacuum along some of the primitive directions
      48              :  public :: checkspvec   ! Check the consistency of spin-related input vectors with the spin quantization axis
      49              : !!***
      50              : 
      51              : contains
      52              : !!***
      53              : 
      54              : !!****f* m_ingeo/ingeo
      55              : !!
      56              : !! NAME
      57              : !! ingeo
      58              : !!
      59              : !! FUNCTION
      60              : !! Initialize geometry variables for the ABINIT code.
      61              : !! 1) set up unit cell: acell, rprim and rprimd ; deduce Bravais lattice
      62              : !! 2) (removed)
      63              : !! 3) Set up the number of atoms (natrd) in the primitive set, to be read.
      64              : !! 4) Read the type of each atom in the primitive set
      65              : !! 5) Read coordinates for each atom in the primitive set
      66              : !! 6) Eventually read the symmetries
      67              : !! 7) Checks whether the geometry builder must be used,
      68              : !!    and call it if needed. Call eventually the symmetry builder and analyser
      69              : !!    Make the adequate transfers if the geometry
      70              : !!    builder is not needed.
      71              : !! 8) Initialize the fixing of atoms, the initial velocities, and the initial atomic spin
      72              : !!
      73              : !! INPUTS
      74              : !! berryopt == 4/14: electric field is on; berryopt = 6/7/16/17: electric displacement field is on
      75              : !! iimage= index of the current image
      76              : !! iout=unit number of output file
      77              : !! jdtset=number of the dataset looked for
      78              : !! lenstr=actual length of the string
      79              : !! msym=default maximal number of symmetries
      80              : !! natom=number of atoms
      81              : !! nimage=number of images
      82              : !! npsp=number of pseudopotentials (needed for the dimension of znucl)
      83              : !! nspden=number of spin-density components
      84              : !! nsppol=number of independent spin polarizations
      85              : !! ntypat=number of type of atoms
      86              : !! nzchempot=defines the use of a spatially-varying chemical potential along z
      87              : !! pawspnorb=1 when spin-orbit is activated within PAW
      88              : !! ratsph(1:ntypat)=radius of the atomic sphere
      89              : !! string*(*)=character string containing all the input data. Initialized previously in instrng.
      90              : !! supercell_latt(3)=supercell lattice
      91              : !! comm: MPI communicator
      92              : !!
      93              : !! OUTPUT
      94              : !! acell(3)=length of primitive vectors
      95              : !! amu(ntypat)=mass of each atomic type
      96              : !! bravais(11)=characteristics of Bravais lattice (see symlatt.F90)
      97              : !! chrgat(natom)=target charge for each atom. Not always used, it depends on the value of constraint_kind
      98              : !! field_red(3)=applied field direction in reduced coordinates
      99              : !! field_red_axial(3) = direction of applied axial (pseudo-)vector field
     100              : !!                      (e.g., magnetic field) expressed in reduced coordinates
     101              : !! genafm(3)=magnetic translation generator (in case of Shubnikov group type IV)
     102              : !! iatfix(3,natom)=indices for atoms fixed along some (or all) directions
     103              : !! jellslab=not zero if jellslab keyword is activated
     104              : !! slabzbeg, slabzend= the z coordinates of beginning / end of the jellium slab
     105              : !! mixalch(npspalch,ntypalch)=alchemical mixing factors
     106              : !! nsym=actual number of symmetries
     107              : !! nucdipmom(3,natom)=nuclear magnetic dipole moment of each atom in atomic units
     108              : !! ptgroupma = magnetic point group number
     109              : !! rprim(3,3)=dimensionless real space primitive translations
     110              : !! spgroup=symmetry space group
     111              : !! spinat(3,natom)=initial spin of each atom, in unit of hbar/2.
     112              : !! symafm(1:msym)=(anti)ferromagnetic part of symmetry operations
     113              : !! symmorphi=if 0, only allows symmorphic symmetry operations
     114              : !! symrel(3,3,1:msym)=symmetry operations in real space in terms
     115              : !!  of primitive translations
     116              : !! tnons(3,1:msym)=nonsymmorphic translations for symmetry operations
     117              : !! tolsym=tolerance for the symmetry operations
     118              : !! typat(natom)=type integer for each atom in cell
     119              : !! vel(3,natom)=initial velocity of atoms in bohr/atomic time units
     120              : !! vel_cell(3,3)=initial velocity of cell parameters in bohr/atomic time units
     121              : !! xred(3,natom)=reduced dimensionless atomic coordinates
     122              : !! znucl(1:npsp)=nuclear number of atom as specified in psp file
     123              : !!
     124              : !! SIDE EFFECTS
     125              : !!
     126              : !! NOTES
     127              : !! the parameters ntypat and natom have already been read in indims,
     128              : !! and were used to dimension the arrays needed here.
     129              : !!
     130              : !! TODO
     131              : !! The dtset datastructure should NOT be an argument of this routine ... !
     132              : !!
     133              : !! MG: I completely agree. Abinit developers must learn that Fortran does not allow for aliasing!
     134              : !!
     135              : !! SOURCE
     136              : 
     137         7228 : subroutine ingeo (acell,amu,atndlist,bravais,chrgat,dtset,field_red,field_red_axial,&
     138         7228 :   genafm,iatfix,iatnd,icoulomb,iimage,iout,jdtset,jellslab,lenstr,mixalch,&
     139              :   msym,natnd,natom,nimage,npsp,npspalch,nspden,nsym,ntypalch,ntypat,&
     140         7228 :   nucdipmom,nzchempot,pawspnorb,&
     141         7228 :   ptgroupma,ratsph,rprim,slabzbeg,slabzend,spgroup,spinat,spinat_cart,string,supercell_lattice,symafm,&
     142         7228 :   symmorphi,symrel,tnons,tolsym,typat,vel,vel_cell,xred,znucl,comm)
     143              : 
     144              : !Arguments ------------------------------------
     145              : !scalars
     146              :  integer,intent(in) :: iimage,iout,jdtset,lenstr,msym
     147              :  integer,intent(in) :: natnd,nimage,npsp,npspalch,nspden
     148              :  integer,intent(in) :: ntypalch,ntypat,nzchempot,pawspnorb,comm
     149              :  integer,intent(inout) :: natom,symmorphi
     150              :  integer,intent(out) :: icoulomb,jellslab,ptgroupma,spgroup !vz_i
     151              :  integer,intent(inout) :: nsym !vz_i
     152              :  real(dp),intent(out) :: slabzbeg,slabzend,tolsym
     153              :  character(len=*),intent(in) :: string
     154              : !arrays
     155              :  integer,intent(in) :: supercell_lattice(3)
     156              :  integer,intent(out) :: bravais(11),iatfix(3,natom) !vz_i
     157              :  integer,intent(inout) :: iatnd(natnd),symafm(msym) !vz_i
     158              :  integer,intent(inout) :: symrel(3,3,msym) !vz_i
     159              :  integer,intent(out) :: typat(natom)
     160              :  real(dp),intent(inout) :: atndlist(3,natnd),chrgat(natom)
     161              :  real(dp),intent(inout) :: nucdipmom(3,natom),ratsph(ntypat)
     162              :  real(dp),intent(inout) :: spinat(3,natom), spinat_cart(3,natom)
     163              :  real(dp),intent(out) :: acell(3),amu(ntypat),field_red(3),field_red_axial(3)
     164              :  real(dp),intent(out) :: genafm(3),mixalch(npspalch,ntypalch)
     165              :  real(dp),intent(inout) :: rprim(3,3),tnons(3,msym) !vz_i
     166              :  real(dp),intent(out) :: vel(3,natom),vel_cell(3,3),xred(3,natom)
     167              :  real(dp),intent(in) :: znucl(npsp)
     168              :  type(dataset_type),intent(inout) :: dtset
     169              : 
     170              : !Local variables-------------------------------
     171              :  character(len=*), parameter :: format01110 ="(1x,a6,1x,(t9,8i8) )"
     172              :  character(len=*), parameter :: format01160 ="(1x,a6,1x,1p,(t9,3g18.10)) "
     173              : !scalars
     174              :  integer :: bckbrvltt,brvltt,chkprim,chkprim_fake,expert_user
     175              :  integer :: fixed_mismatch,i1,i2,i3,iatom,iatom_supercell,idir,ierr,iexit,ii
     176              :  integer :: invar_z,ipsp,irreducible,isym,itranslat,itypat,jsym,marr,mismatch_fft_tnons,multi,multiplicity,natom_uc,natfix,natrd
     177              :  integer :: nobj,noncoll,nptsym,nsym_now,ntranslat,ntyppure,random_atpos,shubnikov,spgaxor,spgorig
     178              :  integer :: spgroupma,tgenafm,tnatrd,tread,try_primitive,tscalecart,tspgroupma,tread_geo,tread_cart
     179              :  integer :: txcart,txred,txrandom,use_inversion
     180              :  real(dp) :: amu_default,ucvol,sumalch
     181              :  character(len=1000) :: msg
     182         7228 :  character(len=lenstr) :: geo_string
     183              :  type(atomdata_t) :: atom
     184         7228 :  type(geo_t) :: geo
     185              : !arrays
     186              :  integer :: bravais_reduced(11)
     187         7228 :  integer,allocatable :: intarr(:)
     188         7228 :  integer,allocatable :: is_translation(:)
     189         7228 :  integer,allocatable :: ptsymrel(:,:,:),typat_read(:)
     190              :  real(dp) :: angdeg(3), field_xred(3),gmet(3,3),gprimd(3,3),rmet(3,3),rcm(3)
     191              :  real(dp) :: rprimd(3,3),rprimd_read(3,3),rprimd_new(3,3),rprimd_primitive(3,3),scalecart(3)
     192         7228 :  real(dp),allocatable :: mass_psp(:),tnons_cart(:,:),tnons_new(:,:),translations(:,:)
     193         7228 :  real(dp),allocatable :: xcart(:,:),xcart_read(:,:),xred_read(:,:),dprarr(:)
     194              : 
     195              : ! *************************************************************************
     196              : 
     197              : !DEBUG
     198              : !write(std_out,'(a)')' m_ingeo%ingeo : enter '
     199              : !call flush(std_out)
     200              : !ENDDEBUG
     201              : 
     202         7228 :  marr=max(12,3*natom,9*msym)
     203        21684 :  ABI_MALLOC(intarr,(marr))
     204        21684 :  ABI_MALLOC(dprarr,(marr))
     205              : 
     206              :  ! Try from geo_string
     207         7228 :  call intagm(dprarr, intarr, jdtset, marr, 1, string(1:lenstr), 'structure', tread_geo, 'KEY', key_value=geo_string)
     208              : 
     209         7228 :  if (tread_geo /= 0) then
     210              :    ! Set up unit cell from external file.
     211           55 :    geo = geo_from_abivar_string(geo_string, comm)
     212          220 :    acell = one
     213          715 :    rprim = geo%rprimd
     214              :    !call exclude(lenstr, string, jdtset, iimage, "acell, rprim, angdeg, scalecar")
     215              : 
     216              :  else
     217              :    ! Set up unit cell from acell, rprim, angdeg
     218         7173 :    call get_acell_rprim(lenstr, string, jdtset, iimage, nimage, marr, acell, rprim)
     219              :  end if ! geo% or (acell, rprim, angdeg)
     220              : 
     221              :  ! Rescale rprim using scalecart (and set scalecart to one)
     222        28912 :  scalecart(1:3)=one
     223         7228 :  call intagm(dprarr,intarr,jdtset,marr,3,string(1:lenstr),'scalecart',tscalecart,'LEN')
     224         7258 :  if(tscalecart==1) scalecart(1:3)=dprarr(1:3)
     225         7228 :  call intagm_img(scalecart,iimage,jdtset,lenstr,nimage,3,string,"scalecart",tscalecart,'LEN')
     226              : 
     227        28912 :  rprim(:,1)=scalecart(:)*rprim(:,1)
     228        28912 :  rprim(:,2)=scalecart(:)*rprim(:,2)
     229        28912 :  rprim(:,3)=scalecart(:)*rprim(:,3)
     230        28912 :  scalecart(:)=one
     231              : 
     232              :  ! Compute the multiplicity of the supercell
     233         7228 :  multiplicity=supercell_lattice(1)*supercell_lattice(2)*supercell_lattice(3)
     234              : 
     235         7228 :  if (tread_geo == 0) then
     236              :    ! Get the number of atom in the unit cell. Read natom from string
     237         7173 :    call intagm(dprarr,intarr,jdtset,marr,1,string(1:lenstr),'natom',tread,'INT')
     238              : 
     239              :    ! Might initialize natom from XYZ file
     240         7173 :    if (tread==0) call intagm(dprarr,intarr,jdtset,marr,1,string(1:lenstr),'_natom',tread,'INT')
     241              : 
     242         7173 :    if(tread==1) natom_uc=intarr(1)
     243              :  else
     244           55 :    natom_uc = geo%natom
     245              :  end if
     246              : 
     247              :  ! Store the rprimd of the unit cell
     248         7228 :  call mkrdim(acell,rprim,rprimd_read)
     249              : 
     250              :  ! Multiply the rprim to get the rprim of the supercell
     251         7228 :  if(multiplicity > 1)then
     252            4 :    rprim(:,1) = rprim(:,1) * supercell_lattice(1)
     253            4 :    rprim(:,2) = rprim(:,2) * supercell_lattice(2)
     254            4 :    rprim(:,3) = rprim(:,3) * supercell_lattice(3)
     255              :  end if
     256              : 
     257              :  ! Compute different matrices in real and reciprocal space, also checks whether ucvol is positive.
     258         7228 :  call mkrdim(acell, rprim, rprimd)
     259         7228 :  call metric(gmet, gprimd, -1, rmet, rprimd, ucvol)
     260              : 
     261         7228 :  if (dtset%berryopt ==4) then
     262          104 :    do ii=1,3
     263          338 :      field_red(ii)=dot_product(dtset%efield(:),gprimd(:,ii))
     264              :    end do
     265              :  else if (dtset%berryopt == 6 ) then
     266            0 :    do ii=1,3
     267            0 :      field_red(ii)=dot_product(dtset%dfield(:),gprimd(:,ii))
     268            0 :      field_red(ii)=field_red(ii)+ dot_product(dtset%efield(:),gprimd(:,ii)) ! note: symmetry broken by D and E
     269              :    end do
     270              :  else if (dtset%berryopt == 14) then
     271            0 :    do ii=1,3
     272            0 :      field_red(ii)=dot_product(dtset%red_efieldbar(:),gmet(:,ii))
     273              :    end do
     274              :  else if (dtset%berryopt == 16) then
     275            0 :    do ii=1,3
     276            0 :      field_red(ii)=dtset%red_dfield(ii)+dtset%red_efield(ii)  ! symmetry broken by reduced d and e
     277              :    end do
     278              :  else if (dtset%berryopt == 17) then
     279            0 :    do ii=1,3
     280            0 :      field_red(ii)=dot_product(dtset%red_efieldbar(:),gmet(:,ii))
     281            0 :      if(dtset%jfielddir(ii)==2) field_red(ii)=dtset%red_dfield(ii)
     282              :    end do
     283              : end if
     284              : 
     285        28912 : do ii = 1, 3
     286        93964 :   if (norm2(dtset%hspinfield_cart) > tol8) then
     287          144 :     field_red_axial(ii) = dot_product(dtset%hspinfield_cart(:), gprimd(:, ii))
     288              :   end if
     289              : end do
     290              : 
     291              : !tolsym = tol8
     292              : !XG20200801 New default value for tolsym. This default value is also defined in m_invars1.F90
     293         7228 :  tolsym = tol5
     294              :  !if (tread_geo /= 0 .and. geo%filetype == "poscar") then
     295              :  !  tolsym = tol4
     296              :  !  ABI_COMMENT("Reading structure from POSCAR --> default value of tolsym is set to 1e-4")
     297              :  !end if
     298              : 
     299         7228 :  call intagm(dprarr,intarr,jdtset,marr,1,string(1:lenstr),'tolsym',tread,'DPR')
     300         7228 :  if(tread==1) tolsym=dprarr(1)
     301              : 
     302              :  ! Find a tentative Bravais lattice and its point symmetries (might not use them)
     303              :  ! Note that the Bravais lattice might not be the correct one yet (because the
     304              :  ! actual atomic locations might lower the symmetry obtained from the lattice parameters only)
     305        21684 :  ABI_MALLOC(ptsymrel,(3,3,msym))
     306         7228 :  call symlatt(bravais,dev_null,msym,nptsym,ptsymrel,rprimd,tolsym)
     307              : 
     308              :  ! 3) Possibly, initialize a jellium slab
     309         7228 :  jellslab=0
     310         7228 :  call intagm(dprarr,intarr,jdtset,marr,1,string(1:lenstr),'jellslab',tread,'INT')
     311         7228 :  if(tread==1) jellslab=intarr(1)
     312              : 
     313         7228 :  slabzbeg=zero
     314         7228 :  slabzend=zero
     315         7228 :  if(jellslab/=0)then
     316            6 :    call intagm(dprarr,intarr,jdtset,marr,1,string(1:lenstr),'slabzbeg',tread,'DPR')
     317            6 :    if(tread==1) slabzbeg=dprarr(1)
     318              : 
     319            6 :    call intagm(dprarr,intarr,jdtset,marr,1,string(1:lenstr),'slabzend',tread,'DPR')
     320            6 :    if(tread==1) slabzend=dprarr(1)
     321              :  end if
     322              : 
     323              :  ! 4) Set up the number of atoms in the primitive set, to be read.
     324              :  ! This is the default
     325         7228 :  natrd=natom
     326         7228 :  if(multiplicity > 1) natrd = natom_uc
     327              : 
     328         7228 :  call intagm(dprarr,intarr,jdtset,marr,1,string(1:lenstr),'natrd',tnatrd,'INT')
     329         7228 :  if(tnatrd==1) natrd=intarr(1)
     330              : 
     331         7228 :  if(natrd<1 .or. natrd>natom)then
     332            0 :    if(natrd>1 .and. multiplicity > 1) then
     333            0 :      if(natrd < natom)then
     334              :        write(msg, '(3a)' )&
     335            0 :         'The number of atoms to be read (natrd) can not be used with supercell_latt.',ch10,&
     336            0 :         'Action: Remove natrd or supercell_latt in your input file.'
     337            0 :        ABI_ERROR(msg)
     338              :      else
     339              :        write(msg,'(3a,I0,a,I0,a,I0,2a)')&
     340            0 :        'The input variable supercell_latt is present',ch10,&
     341            0 :        'thus a supercell ',supercell_lattice(1),' ',supercell_lattice(2),&
     342            0 :        ' ',supercell_lattice(3),' is generated',ch10
     343            0 :        ABI_WARNING(msg)
     344              :      end if
     345              :    else
     346              :      write(msg, '(3a,i0,a,i0,2a,a)' )&
     347            0 :       'The number of atoms to be read (natrd) must be positive and not bigger than natom.',ch10,&
     348            0 :       'This is not the case: natrd=',natrd,', natom=',natom,ch10,&
     349            0 :       'Action: correct natrd or natom in your input file.'
     350            0 :      ABI_ERROR(msg)
     351              :    end if
     352              :  end if
     353              : 
     354              :  ! 5) Read the type and initial spin of each atom in the primitive set--------
     355        21684 :  ABI_MALLOC(typat_read,(natrd))
     356         7228 :  typat_read(1)=1
     357              : 
     358         7228 :  if (tread_geo == 0) then
     359         7173 :    call intagm(dprarr,intarr,jdtset,marr,natrd,string(1:lenstr),'typat',tread,'INT')
     360              : 
     361              :    ! If not read, try the XYZ data
     362         7173 :    if(tread==0) call intagm(dprarr,intarr,jdtset,marr,natrd,string(1:lenstr),'_typat',tread,'INT')
     363        23209 :    if(tread==1) typat_read(1:natrd)=intarr(1:natrd)
     364              : 
     365              :  else
     366          385 :    typat_read = geo%typat
     367              :  end if
     368              : 
     369        23563 :  do iatom=1,natrd
     370        23563 :    if(typat_read(iatom)<1 .or. typat_read(iatom)>ntypat )then
     371              :      write(msg,'(a,i0,a,i0,a,a,a,i0,a,a,a)')&
     372            0 :       'The input type of atom number ',iatom,' is equal to ',typat_read(iatom),',',ch10,&
     373            0 :       'while it should be between 1 and ntypat= ',ntypat,'.',ch10,&
     374            0 :       'Action: change either the variable typat or the variable ntypat.'
     375            0 :      ABI_ERROR(msg)
     376              :    end if
     377              :  end do
     378              : 
     379              :  ! 6) Read coordinates for each atom in the primitive set--------
     380              : 
     381        21684 :  ABI_MALLOC(xcart_read,(3,natrd))
     382        14456 :  ABI_MALLOC(xred_read,(3,natrd))
     383              : 
     384         7228 :  random_atpos=0
     385         7228 :  call intagm(dprarr,intarr,jdtset,marr,1,string(1:lenstr),'random_atpos',txrandom,'INT')
     386         7228 :  if(txrandom==1) random_atpos=intarr(1)
     387         7228 :  if (random_atpos < 0 .or. random_atpos > 5) then
     388              :    write(msg,'(3a)')&
     389            0 :     'Random positions is a variable defined between 0 and 5. Error in the input file. ',ch10,&
     390            0 :     'Action: define one of these in your input file.'
     391            0 :    ABI_ERROR(msg)
     392              :  end if
     393              : 
     394              :  !if(nimage/=1 .and. iimage/=1)then
     395              :  !FIXME: should this be called outside the above end if?
     396              :  call randomcellpos(natom,npsp,ntypat,random_atpos,ratsph,rprim,rprimd_read,typat_read,&
     397         7228 :                     xred_read(:,1:natrd),znucl,acell)
     398              :  !This should not be printed if randomcellpos did nothing - it contains garbage. Spurious output anyway
     399              :  !end if
     400              : 
     401         7228 :  if (tread_geo /= 0) then
     402           55 :    txcart = 0; txrandom = 0; txred = 1
     403         1210 :    xred_read = geo%xred
     404              : 
     405              :  else
     406         7173 :    call intagm(dprarr,intarr,jdtset,marr,3*natrd,string(1:lenstr),'xred',txred,'DPR')
     407        19807 :    if (txred==1 .and. txrandom == 0) xred_read(:,1:natrd) = reshape(dprarr(1:3*natrd) , [3, natrd])
     408         7173 :    call intagm_img(xred_read,iimage,jdtset,lenstr,nimage,3,natrd,string,"xred",txred,'DPR')
     409              : 
     410         7173 :    call intagm(dprarr,intarr,jdtset,marr,3*natrd,string(1:lenstr),'xcart',txcart,'LEN')
     411         8863 :    if (txcart==1 .and. txrandom==0) xcart_read(:,1:natrd) = reshape(dprarr(1:3*natrd), [3, natrd])
     412         7173 :    call intagm_img(xcart_read,iimage,jdtset,lenstr,nimage,3,natrd,string,"xcart",txcart,'LEN')
     413              : 
     414              :    ! Might initialize xred from XYZ file
     415         7173 :    if (txred+txcart+txrandom==0) then
     416            1 :      call intagm(dprarr,intarr,jdtset,marr,3*natrd,string(1:lenstr),'_xred',txred,'DPR')
     417            1 :      if (txred==1 .and. txrandom==0) xred_read(:,1:natrd) = reshape(dprarr(1:3*natrd), [3, natrd])
     418              : 
     419            1 :      call intagm(dprarr,intarr,jdtset,marr,3*natrd,string(1:lenstr),'_xcart',txcart,'DPR')
     420            3 :      if (txcart==1 .and. txrandom==0) xcart_read(:,1:natrd) = reshape(dprarr(1:3*natrd), [3, natrd])
     421              :    end if
     422              : 
     423              :    !TODO: Might initialize xred from getxred/xcart: NOT POSSIBLE YET. NEEDS INTER DTSET COMMUNICATION AT INVARS1 TIME
     424              : !   if (txred+txcart+txrandom==0) then
     425              : !     call intagm(dprarr,intarr,jdtset,marr,1,string(1:lenstr),'getxred',txred,'INT')
     426              : !     if (txred==1 .and. txrandom==0) xred_read(:,1:natrd) =
     427              : !
     428              : !     call intagm(dprarr,intarr,jdtset,marr,1,string(1:lenstr),'getxcart',txcart,'INT')
     429              : !     if (txcart==1 .and. txrandom==0) xcart_read(:,1:natrd) =
     430              : !   end if
     431              :  end if
     432              : 
     433         7228 :  if (txred + txcart + txrandom == 0) then
     434              :    write(msg, '(3a)' )&
     435            0 :     'Neither xred nor xcart are present in input file. ',ch10,&
     436            0 :     'Action: define one of these in your input file.'
     437            0 :    ABI_ERROR(msg)
     438              :  end if
     439              : 
     440         7228 :  if (txred==1)   write(msg, '(a)' ) '  xred   is defined in input file'
     441         7228 :  if (txcart ==1) write(msg, '(a)' ) '  xcart  is defined in input file (possibly in Angstrom)'
     442         7228 :  if (txrandom ==1) write(msg, '(a)' ) '  xred  as random positions in the unit cell'
     443         7228 :  if (txrandom ==1) write(msg, '(a)' ) '  xcart  are defined from a random distribution '
     444         7228 :  call wrtout(std_out, msg)
     445              : 
     446         7228 :  if (txred + txcart + txrandom > 1)then
     447              :    write(msg, '(3a)' )&
     448            0 :     'Too many input channels for atomic positions are defined.',ch10,&
     449            0 :     'Action: choose to define only one of these.'
     450            0 :    ABI_ERROR(msg)
     451              :  end if
     452              : 
     453         7228 :  if (txred==1 .or. txrandom /=0 ) then
     454         6382 :    call wrtout(std_out,' ingeo: takes atomic coordinates from input array xred ')
     455         6382 :    call xred2xcart(natrd,rprimd_read,xcart_read,xred_read)
     456              :  else
     457          846 :    call wrtout(std_out,' ingeo: takes atomic coordinates from input array xcart')
     458          846 :    txcart=1
     459              :  end if
     460              : 
     461              :  !At this stage, the cartesian coordinates are known, for the atoms whose coordinates where read.
     462              : 
     463              :  ! Here, allocate the variable that will contain the completed
     464              :  ! sets of xcart, after the use of the geometry builder or the symmetry builder
     465        21684 :  ABI_MALLOC(xcart,(3,natom))
     466              : 
     467              :  !7) Eventually read the symmetries
     468              :  !Take care of the symmetries
     469              : 
     470         7228 :  call intagm(dprarr,intarr,jdtset,marr,1,string(1:lenstr),'nsym',tread,'INT')
     471         7228 :  if(tread==1) nsym=intarr(1)
     472              : 
     473              :  ! Check that nsym is not negative
     474         7228 :  if (nsym<0) then
     475              :    write(msg, '(a,i0,4a)' )&
     476            0 :     'Input nsym must be positive or 0, but was ',nsym,ch10,&
     477            0 :     'This is not allowed.',ch10,'Action: correct nsym in your input file.'
     478            0 :    ABI_ERROR(msg)
     479              :  end if
     480              :  ! Check that nsym is not bigger than msym
     481         7228 :  if (nsym>msym) then
     482              :    write(msg, '(2(a,i0),5a)')&
     483            0 :     'Input nsym = ',nsym,' exceeds msym = ',msym,'.',ch10,&
     484            0 :     'This is not allowed.',ch10,'Action: correct nsym in your input file.'
     485            0 :    ABI_ERROR(msg)
     486              :  end if
     487         7228 :  if (multiplicity>1) then
     488            1 :    nsym = 1
     489            1 :    ABI_WARNING('Input nsym is now set to one due to the supercell_latt input')
     490              :  end if
     491              : 
     492              :  ! Read symmorphi
     493         7228 :  call intagm(dprarr,intarr,jdtset,marr,1,string(1:lenstr),'symmorphi',tread,'INT')
     494         7228 :  if(tread==1) symmorphi=intarr(1)
     495              : 
     496              :  ! Now, read the symmetry operations
     497         7228 :  if(nsym>0)then
     498         1270 :    call intagm(dprarr,intarr,jdtset,marr,9*nsym,string(1:lenstr),'symrel',tread,'INT')
     499         1270 :    if(nsym>1 .and. tread==0)then
     500              :      write(msg,'(3a)')&
     501            0 :        'When nsym>1, symrel must be defined in the input file.',ch10,&
     502            0 :        'Action: either change nsym, or define symrel in your input file.'
     503            0 :      ABI_ERROR(msg)
     504              :    end if
     505         3106 :    if(tread==1) symrel(:,:,1:nsym)=reshape( intarr(1:9*nsym) , [3, 3, nsym])
     506              : 
     507              :    ! Take care of tnons
     508        41726 :    tnons(:,1:nsym)=zero
     509         1270 :    call intagm(dprarr,intarr,jdtset,marr,3*nsym,string(1:lenstr),'tnons',tread,'DPR')
     510         2348 :    if(tread==1) tnons(:,1:nsym)=reshape( dprarr(1:3*nsym), [3, nsym])
     511              : 
     512         1270 :    if(symmorphi==0)then
     513           58 :      do isym=1,nsym
     514          145 :        if(sum(tnons(:,isym)**2)>tol6)then
     515              :          write(msg, '(5a,i0,a,3f8.4,3a)' )&
     516            0 :          'When symmorphi /= 1, the vectors of translation (tnons)',ch10,&
     517            0 :          'a symmetry operation must vanish.',ch10,&
     518            0 :          'However, for the symmetry operation number ',isym,', tnons =',tnons(:,isym),'.',ch10,&
     519            0 :          'Action: either change your list of allowed symmetry operations, or use the symmetry finder (nsym=0).'
     520            0 :          ABI_ERROR(msg)
     521              :        end if
     522              :      end do
     523              :    end if
     524              : 
     525              :    ! Take care of symafm
     526         1270 :    call intagm(dprarr,intarr,jdtset,marr,nsym,string(1:lenstr),'symafm',tread,'INT')
     527         1318 :    if(tread==1) symafm(1:nsym)=intarr(1:nsym)
     528              :  end if
     529              : 
     530              : 
     531              :  !8) Checks whether the geometry builder must be used, and call it if needed.
     532              :  !Call the symmetry builder and analyzer if needed.
     533              : 
     534              :  ! At this stage, nsym might still contain the default 0, msym contains the default dtset%maxnsym.
     535              :  ! The cartesian coordinates of the atoms of the primitive set are contained in xcart_read.
     536              : 
     537         7228 :  nobj=0
     538         7228 :  call intagm(dprarr,intarr,jdtset,marr,1,string(1:lenstr),'nobj',tread,'INT')
     539         7228 :  if(tread==1) nobj=intarr(1)
     540         7228 :  if(nobj /= 0 .and. multiplicity > 1)then
     541              :    write(msg, '(3a)' )&
     542            0 :     'nobj can not be used with supercell_latt.',ch10,&
     543            0 :     'Action: Remove nobj or supercell_latt in your input file.'
     544            0 :    ABI_ERROR(msg)
     545              :  end if
     546              : 
     547              : !If there are objects, chkprim will not be used immediately
     548              : !But, if there are no objects, but a space group, it will be used directly.
     549              : !Need first to check the value of expert_user
     550         7228 :  expert_user=0
     551         7228 :  call intagm(dprarr,intarr,jdtset,marr,1,string(1:lenstr),'expert_user',tread,'INT')
     552         7228 :  if(tread==1) expert_user=intarr(1)
     553           25 :  if(expert_user==0)then
     554         7203 :    chkprim=1
     555         7203 :    call intagm(dprarr,intarr,jdtset,marr,1,string(1:lenstr),'chkprim',tread,'INT')
     556         7203 :    if(tread==1) chkprim=intarr(1)
     557              :  else
     558           25 :    chkprim=0
     559              :  endif
     560              : 
     561         7228 :  if(nobj/=0)then
     562              : 
     563              :    ! chrgat is read for each atom, from 1 to natom
     564            4 :    call intagm(dprarr,intarr,jdtset,marr,natom,string(1:lenstr),'chrgat',tread,'DPR')
     565            4 :    if(tread==1) then
     566            0 :      chrgat(1:natom) = dprarr(1:natom)
     567              :    end if
     568              : 
     569              :    ! Spinat is read for each atom, from 1 to natom
     570            4 :    call intagm(dprarr,intarr,jdtset,marr,3*natom,string(1:lenstr),'spinat',tread,'DPR')
     571            4 :    if(tread==1) then
     572            0 :      spinat(1:3,1:natom) = reshape( dprarr(1:3*natom) , [3, natom])
     573            0 :      dtset%spinat_in(1:3,1:natom) = spinat(1:3,1:natom)
     574              :    end if
     575              : 
     576            4 :    call intagm(dprarr,intarr,jdtset,marr,3*natom,string(1:lenstr),'spinat_cart',tread_cart,'DPR')
     577            4 :    if(tread_cart==1) spinat_cart(1:3,1:natom) = reshape( dprarr(1:3*natom) , [3, natom])
     578              :    
     579            4 :    call checkspvec('spinat',natom,dtset%spinaxis,tread,tread_cart,spinat,spinat_cart)
     580            4 :    if (tread == 0 .and. tread_cart == 1) dtset%spinat_in(1:3,1:natom) = spinat(1:3,1:natom) 
     581              : 
     582              :    ! nucdipmom is read for each irreducible atom, from 1 to natom
     583         1360 :    nucdipmom=zero
     584            4 :    if(natnd > 0) then
     585            0 :      call intagm(dprarr,intarr,jdtset,marr,natnd,string(1:lenstr),'iatnd',tread,'INT')
     586            0 :      if(tread==1) iatnd(1:natnd)=intarr(1:natnd)
     587            0 :      call intagm(dprarr,intarr,jdtset,marr,3*natnd,string(1:lenstr),'atndlist',tread,'DPR')
     588            0 :      if(tread==1) atndlist(1:3,1:natnd)=reshape(dprarr(1:3*natnd),[3,natnd])
     589            0 :      do ii=1,natnd
     590            0 :        nucdipmom(1:3,iatnd(ii))=atndlist(1:3,ii)
     591              :      end do
     592              :    else
     593            4 :      call intagm(dprarr,intarr,jdtset,marr,3*natom,string(1:lenstr),'nucdipmom',tread,'DPR')
     594            4 :      if(tread==1)nucdipmom(1:3,1:natom) = reshape( dprarr(1:3*natom) , [3, natom])
     595              :    end if
     596              : 
     597              :    ! Will use the geometry builder
     598            4 :    if(tnatrd/=1 .and. nobj/=0)then
     599              :      write(msg, '(3a,i0,5a)' )&
     600            0 :       'The number of atoms to be read (natrd) must be initialized',ch10,&
     601            0 :       'in the input file, when nobj= ',nobj,'.',ch10,&
     602            0 :       'This is not the case.',ch10,&
     603            0 :       'Action: initialize natrd in your input file.'
     604            0 :      ABI_ERROR(msg)
     605              :    end if
     606              : 
     607            4 :    if(jellslab/=0)then
     608              :      write(msg, '(a,i0,3a)' )&
     609            0 :       'A jellium slab cannot be used when nobj= ',nobj,'.',ch10,&
     610            0 :       'Action: change one of the input variables jellslab or nobj in your input file.'
     611            0 :      ABI_ERROR(msg)
     612              :    end if
     613              : 
     614            4 :    call ingeobld (iout,jdtset,lenstr,natrd,natom,nobj,string,typat,typat_read,xcart,xcart_read)
     615              : 
     616              :    ! Finalize the computation of coordinates: produce xred.
     617            4 :    call xcart2xred(natom,rprimd,xcart,xred)
     618              : 
     619              :  else
     620              :    ! nobj==0
     621              : 
     622              :    ! chrgat is read for each irreducible atom, from 1 to natrd
     623         7224 :    call intagm(dprarr,intarr,jdtset,marr,natrd,string(1:lenstr),'chrgat',tread,'DPR')
     624         7286 :    if(tread==1)chrgat(1:natrd) = dprarr(1:natrd)
     625              : 
     626              :    ! Spinat is read for each irreducible atom, from 1 to natrd
     627         7224 :    call intagm(dprarr,intarr,jdtset,marr,3*natrd,string(1:lenstr),'spinat',tread,'DPR')
     628         7224 :    if(tread==1) then
     629         5082 :      spinat(1:3,1:natrd) = reshape( dprarr(1:3*natrd) , [3, natrd])
     630        10190 :      dtset%spinat_in(1:3,1:natrd) = spinat(1:3,1:natrd)
     631              :    end if
     632              : 
     633         7224 :    call intagm(dprarr,intarr,jdtset,marr,3*natrd,string(1:lenstr),'spinat_cart',tread_cart,'DPR')
     634         7226 :    if(tread_cart==1) spinat_cart(1:3,1:natrd) = reshape( dprarr(1:3*natrd) , [3, natom])
     635         7224 :    call checkspvec('spinat',natrd,dtset%spinaxis,tread,tread_cart,spinat,spinat_cart) 
     636         7228 :    if (tread == 0 .and. tread_cart == 1) dtset%spinat_in(1:3,1:natrd) = spinat(1:3,1:natrd) 
     637              :     
     638              :    ! nucdipmom is read for each irreducible atom, from 1 to natrd
     639       160832 :    nucdipmom=zero
     640         7224 :    if(natnd > 0) then
     641           14 :      call intagm(dprarr,intarr,jdtset,marr,natnd,string(1:lenstr),'iatnd',tread,'INT')
     642           32 :      if(tread==1) iatnd(1:natnd)=intarr(1:natnd)
     643           14 :      call intagm(dprarr,intarr,jdtset,marr,3*natnd,string(1:lenstr),'atndlist',tread,'DPR')
     644           42 :      if(tread==1) atndlist(1:3,1:natnd)=reshape(dprarr(1:3*natnd),[3,natnd])
     645           32 :      do ii=1,natnd
     646           86 :        nucdipmom(1:3,iatnd(ii))=atndlist(1:3,ii)
     647              :      end do
     648              :    else
     649         7210 :      call intagm(dprarr,intarr,jdtset,marr,3*natrd,string(1:lenstr),'nucdipmom',tread,'DPR')
     650         7264 :      if(tread==1)nucdipmom(1:3,1:natrd) = reshape( dprarr(1:3*natrd) , [3, natrd])
     651              :    end if
     652              : 
     653              :    ! Compute xred/typat and spinat for the supercell
     654         7224 :    if(multiplicity > 1)then
     655            1 :      iatom_supercell = 0
     656            3 :      do i1 = 1, supercell_lattice(1)
     657            7 :        do i2 = 1, supercell_lattice(2)
     658           14 :          do i3 = 1, supercell_lattice(3)
     659           52 :            do iatom = 1, natom_uc
     660           40 :              iatom_supercell = iatom_supercell + 1
     661          880 :              xcart(:,iatom_supercell) = xcart_read(:,iatom) + matmul(rprimd_read,(/i1-1,i2-1,i3-1/))
     662           40 :              chrgat(iatom_supercell) = chrgat(iatom)
     663          160 :              spinat(1:3,iatom_supercell) = spinat(1:3,iatom)
     664          160 :              dtset%spinat_in(1:3,iatom_supercell) = dtset%spinat_in(1:3,iatom)
     665           48 :              typat(iatom_supercell) = typat_read(iatom)
     666              :            end do
     667              :          end do
     668              :        end do
     669              :      end do
     670            1 :      call xcart2xred(natom,rprimd,xcart,xred)
     671              :    else
     672              :      ! No supercell
     673         7223 :      call xcart2xred(natrd,rprimd,xcart_read,xred)
     674              :    end if
     675              : 
     676         7224 :    spgroup=0
     677         7224 :    call intagm(dprarr,intarr,jdtset,marr,1,string(1:lenstr),'spgroup',tread,'INT')
     678         7224 :    if(tread==1) spgroup=intarr(1)
     679              : 
     680         7224 :    if(spgroup/=0 .or. nsym/=0)then
     681              : 
     682         2889 :      if(jellslab/=0 .and. nsym/=1 .and. spgroup/=1)then
     683              :        write(msg, '(5a)' )&
     684            0 :         'For the time being, a jellium slab can only be used',ch10,&
     685            0 :         'either with the symmetry finder (nsym=0) or with the space group 1 (nsym=1)',ch10,&
     686            0 :         'Action: change one of the input variables jellslab or nsym or spgroup in your input file.'
     687            0 :        ABI_ERROR(msg)
     688              :      end if
     689              : 
     690         2889 :      if(nzchempot/=0 .and. nsym/=1 .and. spgroup/=1)then
     691              :        write(msg, '(5a)' )&
     692            0 :         'For the time being, a spatially-varying chemical potential can only be used',ch10,&
     693            0 :         'either with the symmetry finder (nsym=0) or with the space group 1 (nsym=1)',ch10,&
     694            0 :         'Action: change one of the input variables nzchempot or nsym or spgroup in your input file.'
     695            0 :        ABI_ERROR(msg)
     696              :      end if
     697              : 
     698         7586 :      typat(1:natrd)=typat_read(1:natrd)
     699              : 
     700         2889 :      if(spgroup/=0 .and. nsym/=0)then
     701              :        write(msg, '(a,i0,a,a,i0,a,a,a,a,a,a,a,a)' )&
     702            0 :          'The spatial group number spgroup= ',spgroup,ch10,&
     703            0 :          'is specified, as well as the number of symmetries nsym= ',nsym,ch10,&
     704            0 :          'This is not allowed, as you can define the symmetries',ch10,&
     705            0 :          'either using spgroup OR using nsym, but not both.',ch10,&
     706            0 :          'Action: modify your input file',ch10,&
     707            0 :          '(either set spgroup to 0, or nsym to 0)'
     708            0 :        ABI_ERROR(msg)
     709              :      end if
     710              : 
     711         2889 :      brvltt=0
     712              : 
     713         2889 :      if(spgroup/=0)then
     714              : 
     715              :        ! Will generate the spatial group using spgroup
     716              :        ! Assign default values
     717         1623 :        spgaxor=1
     718         1623 :        spgorig=1
     719         1623 :        call intagm(dprarr,intarr,jdtset,marr,1,string(1:lenstr),'brvltt',tread,'INT')
     720         1623 :        if(tread==1) brvltt=intarr(1)
     721         1623 :        call intagm(dprarr,intarr,jdtset,marr,1,string(1:lenstr),'spgaxor',tread,'INT')
     722         1623 :        if(tread==1) spgaxor=intarr(1)
     723         1623 :        call intagm(dprarr,intarr,jdtset,marr,1,string(1:lenstr),'spgorig',tread,'INT')
     724         1623 :        if(tread==1) spgorig=intarr(1)
     725              : 
     726              :        ! Treat the case of magnetic groups
     727         1623 :        call intagm(dprarr,intarr,jdtset,marr,1,string(1:lenstr),'spgroupma',tspgroupma,'INT')
     728         1623 :        if(tspgroupma==1) spgroupma=intarr(1)
     729         1623 :        call intagm(dprarr,intarr,jdtset,marr,3,string(1:lenstr),'genafm',tgenafm,'DPR')
     730         1626 :        if(tgenafm==1) genafm(1:3)=dprarr(1:3)
     731         1623 :        if(tspgroupma/=0 .and. tgenafm/=0)then
     732              :          write(msg, '(a,i0,a,a,3es9.2,a,a,a,a,a,a,a,a)' )&
     733            0 :            'The spatial group number spgroupma= ',spgroupma,ch10,&
     734            0 :            'is specified, as well as the antiferromagnetic generator genafm=',genafm(1:3),ch10,&
     735            0 :            'This is not allowed, as you can define the magnetic space group',ch10,&
     736            0 :            'either using spgroupma OR using genafm, but not both.',ch10,&
     737            0 :            'Action: modify your input file',ch10,&
     738            0 :            '(either define spgroupma or genafm)'
     739            0 :          ABI_ERROR(msg)
     740              :        end if
     741              : 
     742              :        ! TODO: all the symmetry generation operations should be in one big routine
     743              : 
     744              :        ! If spgroupma is defined, check whether it is consistent
     745              :        ! with spgroup, determine the Shubnikov type,
     746              :        ! and, for type IV, find the corresponding genafm
     747         1623 :        shubnikov=1
     748         1623 :        if(tspgroupma==1)then
     749         1192 :          call gensymshub(genafm,spgroup,spgroupma,shubnikov)
     750          431 :        else if(tgenafm==1)then
     751            1 :          shubnikov=4
     752              :        end if
     753              : 
     754              :        ! Generate the spatial group of symmetries in a conventional cell
     755              :        ! In case of Shubnikov space group type IV, only generate the
     756              :        ! Fedorov (non-magnetic) group. For Shubnikov type III space group,
     757              :        ! the magnetic part is generated here.
     758         1623 :        bckbrvltt=brvltt
     759         1623 :        if(brvltt==-1)brvltt=0
     760         1623 :        call gensymspgr(brvltt,msym,nsym,shubnikov,spgaxor,spgorig,spgroup,spgroupma,symafm,symrel,tnons)
     761              : 
     762              :        ! For shubnikov type IV groups,
     763              :        ! double the space group, using the antiferromagnetic translation generator
     764         1623 :        if(shubnikov==4)then
     765          519 :          call gensymshub4(genafm,msym,nsym,symafm,symrel,tnons)
     766              :        end if
     767              : 
     768              :        !write(std_out,*)' after gensymshub4, nsym =',nsym
     769              :        !write(std_out,*)' Describe the different symmetry operations (index,symrel,tnons,symafm)'
     770              :        !do ii=1,nsym
     771              :        !write(std_out,'(i3,2x,9i3,3es12.2,i3)')ii,symrel(:,:,ii),tnons(:,ii),symafm(ii)
     772              :        !end do
     773              : 
     774              :        ! If brvltt was -1 at input, one should now change the conventional cell
     775              :        ! to a primitive one, if brvltt/=1
     776         1623 :        if(bckbrvltt==-1 .and. brvltt/=1)then
     777              :          ! Will work with rprim only
     778          384 :          rprim(:,:)=rprimd(:,:)
     779          384 :          rprimd_new(:,:)=rprimd(:,:)
     780         1536 :          acell(:)=1.0_dp
     781              :          select case(brvltt)
     782              :          case(5)
     783          112 :            rprimd_new(:,2)=(rprim(:,2)+rprim(:,3))*0.5_dp
     784          112 :            rprimd_new(:,3)=(rprim(:,3)-rprim(:,2))*0.5_dp
     785              :          case(6)
     786            0 :            rprimd_new(:,1)=(rprim(:,1)+rprim(:,3))*0.5_dp
     787            0 :            rprimd_new(:,3)=(rprim(:,3)-rprim(:,1))*0.5_dp
     788              :          case(4)
     789          456 :            rprimd_new(:,1)=(rprim(:,1)+rprim(:,2))*0.5_dp
     790          456 :            rprimd_new(:,2)=(rprim(:,2)-rprim(:,1))*0.5_dp
     791              :          case(3)
     792          248 :            rprimd_new(:,1)=(rprim(:,2)+rprim(:,3))*0.5_dp
     793          248 :            rprimd_new(:,2)=(rprim(:,1)+rprim(:,3))*0.5_dp
     794          248 :            rprimd_new(:,3)=(rprim(:,1)+rprim(:,2))*0.5_dp
     795              :          case(2)
     796          720 :            rprimd_new(:,1)=(-rprim(:,1)+rprim(:,2)+rprim(:,3))*0.5_dp
     797          720 :            rprimd_new(:,2)=( rprim(:,1)-rprim(:,2)+rprim(:,3))*0.5_dp
     798          720 :            rprimd_new(:,3)=( rprim(:,1)+rprim(:,2)-rprim(:,3))*0.5_dp
     799              :          case(7)
     800            0 :            rprimd_new(:,1)=( rprim(:,1)*2.0_dp+rprim(:,2)+rprim(:,3))/3.0_dp
     801            0 :            rprimd_new(:,2)=(-rprim(:,1)      +rprim(:,2)+rprim(:,3))/3.0_dp
     802          384 :            rprimd_new(:,3)=(-rprim(:,1)-rprim(:,2)*2.0_dp+rprim(:,3))/3.0_dp
     803              :          end select
     804          384 :          call symrelrot(nsym,rprimd,rprimd_new,symrel,tolsym)
     805              : !        Produce xred in the new system of coordinates
     806          384 :          call xred2xcart(natrd,rprimd,xcart,xred)
     807          384 :          call xcart2xred(natrd,rprimd_new,xcart,xred)
     808              : !        Produce tnons in the new system of coordinates
     809         1152 :          ABI_MALLOC(tnons_cart,(3,nsym))
     810          384 :          call xred2xcart(nsym,rprimd,tnons_cart,tnons)
     811          384 :          call xcart2xred(nsym,rprimd_new,tnons_cart,tnons)
     812          384 :          ABI_FREE(tnons_cart)
     813              : 
     814              :          ! write(std_out,*)' after change of coordinates, nsym =',nsym
     815              :          ! write(std_out,*)' Describe the different symmetry operations (index,symrel,tnons,symafm)'
     816              :          ! do ii=1,nsym
     817              :          ! write(std_out,'(i3,2x,9i3,3es12.2,i3)')ii,symrel(:,:,ii),tnons(:,ii),symafm(ii)
     818              :          ! end do
     819              : 
     820              :          ! Prune the symmetry operations: suppress those with
     821              :          ! exactly the same point and magnetic part
     822          384 :          nsym_now=1
     823        14784 :          do isym=2,nsym
     824       263592 :            irreducible=1
     825       263592 :            do jsym=1,nsym_now
     826      3366168 :              if(sum(abs(symrel(:,:,isym)-symrel(:,:,jsym)))==0 .and. symafm(isym)==symafm(jsym)) then
     827              :                irreducible=0
     828              :                exit
     829              :              end if
     830              :            end do
     831        14784 :            if(irreducible==1)then
     832         5044 :              nsym_now=nsym_now+1
     833        65572 :              symrel(:,:,nsym_now)=symrel(:,:,isym)
     834        20176 :              tnons(:,nsym_now)=tnons(:,isym)
     835         5044 :              symafm(nsym_now)=symafm(isym)
     836              :            end if
     837              :          end do
     838          384 :          nsym=nsym_now
     839              : !        Translate tnons in the ]-0.5,0.5] interval
     840        22096 :          tnons(:,1:nsym)=tnons(:,1:nsym)-nint(tnons(:,1:nsym)-1.0d-8)
     841              : 
     842              :          ! DEBUG
     843              :          ! write(std_out,*)' after reduction, nsym =',nsym
     844              :          ! write(std_out,*)' Describe the different symmetry operations (index,symrel,tnons,symafm)'
     845              :          ! do ii=1,nsym
     846              :          ! write(std_out,'(i3,2x,9i3,3es12.2,i3)')ii,symrel(:,:,ii),tnons(:,ii),symafm(ii)
     847              :          ! end do
     848              :          ! ENDDEBUG
     849              : 
     850              :          ! Now that symrel, tnons and xred are expressed in the primitive
     851              :          ! axis system, update the geometric quantities
     852          384 :          rprimd(:,:)=rprimd_new(:,:)
     853          384 :          rprim(:,:)=rprimd_new(:,:)
     854          384 :          call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
     855          384 :          call symlatt(bravais,std_out,msym,nptsym,ptsymrel,rprimd,tolsym)
     856              :        end if
     857              : 
     858              :      end if
     859              : 
     860         2889 :     if(natom/=natrd.and.multiplicity == 1)then
     861              :       ! Generate the full set of atoms from its knowledge in the irreducible part.
     862         1588 :        call fillcell(chrgat,natom,natrd,nsym,nucdipmom,spinat,spinat_cart,symafm,symrel,tnons,tolsym,typat,xred)
     863              :       ! Keep spinat_in consistent with symmetry-expanded spinat for output/printing.
     864        98048 :       dtset%spinat_in(1:3,1:natom) = spinat(1:3,1:natom)
     865              :     end if
     866              : 
     867              :      ! Check whether the symmetry operations are consistent with the lattice vectors
     868         2889 :      iexit=0
     869              : 
     870         2889 :      call chkorthsy(gprimd,iexit,nsym,rmet,rprimd,symrel,tolsym)
     871              : 
     872              :    else
     873              :      ! spgroup==0 and nsym==0
     874              : 
     875              :      ! Here, spgroup==0 as well as nsym==0, so must generate
     876              :      ! the spatial group of symmetry. However, all the atom
     877              :      ! positions must be known, so the number
     878              :      ! of atoms to be read must equal the total number of atoms.
     879         4335 :      if(natrd/=natom .and. multiplicity== 1)then
     880              :        write(msg, '(a,i0,a,a,i0,a,a,a,a,a,a,a,a,a)' )&
     881            0 :          'The number of atoms to be read (natrd)= ',natrd,ch10,&
     882            0 :          'differs from the total number of atoms (natom)= ',natom,ch10,&
     883            0 :          'while spgroup=0 and nsym=0.',&
     884            0 :          'This is not allowed, since the information needed to',ch10,&
     885            0 :          'generate the missing atomic coordinates is not available.',ch10,&
     886            0 :          'Action: modify your input file',ch10,&
     887            0 :          '(either natrd, or natom, or spgroup, or nsym)'
     888            0 :        ABI_ERROR(msg)
     889              :      endif
     890        15884 :      if (multiplicity==1) typat(:)=typat_read(:)
     891              : 
     892              :      ! Find the symmetry operations: nsym, symafm, symrel and tnons.
     893              :      ! Use nptsym and ptsymrel, as determined by symlatt
     894              :      ! Will possibly correct xred and tnons.
     895              : 
     896         4335 :      noncoll=0; if (nspden == 4) noncoll=1
     897              : 
     898         4335 :      use_inversion=1
     899         4335 :      if (dtset%usepaw == 1 .and. (nspden==4.or.pawspnorb>0)) then
     900          135 :        ABI_COMMENT("Removing inversion and improper rotations from initial space group because of PAW + SOC")
     901              :        ! MMignolet: PAW can be used with inversion, however it results in seg faults in the dmft code. To enable when this is fixed...
     902          135 :        use_inversion=0
     903              :      end if
     904              : 
     905              :      ! Get field in reduced coordinates (reduced e/d field)
     906              : 
     907              :      field_xred(:)=zero
     908              :      if (dtset%berryopt ==4) then
     909              :        do ii=1,3
     910              :          field_xred(ii)=dot_product(dtset%efield(:),gprimd(:,ii))
     911              :        end do
     912              :      else if (dtset%berryopt == 6 ) then
     913              :        do ii=1,3
     914              :          field_xred(ii)=dot_product(dtset%dfield(:),gprimd(:,ii))
     915              :          field_xred(ii)=field_xred(ii)+ dot_product(dtset%efield(:),gprimd(:,ii)) ! note: symmetry broken by D and E
     916              :        end do
     917              :      else if (dtset%berryopt == 14) then
     918              :        do ii=1,3
     919              :          field_xred(ii)=dot_product(dtset%red_efieldbar(:),gmet(:,ii))
     920              :        end do
     921              :      else if (dtset%berryopt == 16) then
     922              :        do ii=1,3
     923              :          field_xred(ii)=dtset%red_dfield(ii)+dtset%red_efield(ii)  ! symmetry broken by reduced d and e
     924              :        end do
     925              :      else if (dtset%berryopt == 17) then
     926              :        do ii=1,3
     927              :          field_xred(ii)=dot_product(dtset%red_efieldbar(:),gmet(:,ii))
     928              :          if(dtset%jfielddir(ii)==2) field_xred(ii)=dtset%red_dfield(ii)
     929              :        end do
     930              :      end if
     931              : 
     932              :      ! Loop on trials to generate better point symmetries by relying on a primitive cell instead (possibly) of a non-primitive one,
     933              :      ! This loop has been disactivated, because it is not clear that one can generate a more complete set of point symmetries
     934              :      ! WITH INTEGER components of symrel from a primitive cell. One should allow non-integer components, but this would
     935              :      ! be a large departure from the current implementation. Still, the detection of the existence of the primitive cell
     936              :      ! and the corresponding Bravais lattice is activated.
     937         4373 :      do try_primitive=1,1
     938              : 
     939         4335 :        invar_z=0 ; if(jellslab/=0 .or. nzchempot/=0)invar_z=2
     940              :        call symfind_expert(gprimd,msym,natom,nptsym,nspden,nsym,&
     941              :        pawspnorb,dtset%prtvol,ptsymrel,spinat,symafm,symrel,tnons,tolsym,typat,dtset%usepaw,xred,&
     942         4335 :        chrgat=chrgat,nucdipmom=nucdipmom,invardir_red=dtset%field_red,invaraxial_red=dtset%field_red_axial,invar_z=invar_z)
     943              : 
     944         4335 :        chkprim_fake=-1
     945        13005 :        ABI_MALLOC(is_translation,(nsym))
     946         4335 :        call chkprimit(chkprim_fake, multi, nsym, symafm, symrel, is_translation)
     947              : 
     948         4373 :        if(multi/=1)then ! The cell is not primitive, get the point symmetries from a primitive cell.
     949          117 :          ntranslat=multi
     950          351 :          ABI_MALLOC(translations,(3,ntranslat))
     951          117 :          itranslat=0
     952        17301 :          do isym=1,nsym
     953        17301 :            if(is_translation(isym)==1)then
     954          414 :              itranslat=itranslat+1
     955         1656 :              translations(:,itranslat)=tnons(:,isym)
     956              :            endif
     957              :          enddo
     958          117 :          ABI_FREE(is_translation)
     959          117 :          call reduce2primitive(ntranslat, rprimd, rprimd_primitive, tolsym, translations)
     960          117 :          ABI_FREE(translations)
     961              :          !Find the Bravais lattice of the primitive cell, and the point symmetries (however, in the primitive basis)
     962          117 :          call symlatt(bravais_reduced,dev_null,msym,nptsym,ptsymrel,rprimd_primitive,tolsym)
     963              :          write(msg,'(2a,3(3es16.8,a),2(a,i4,a),3(a,3i4,a),a,i4)')&
     964          117 : &          ' The cell is not primitive. One could obtain a primitive cell using the following primitive vectors (rprimd) :',ch10,&
     965          117 : &          rprimd_primitive(1:3,1),ch10,&
     966          117 : &          rprimd_primitive(1:3,2),ch10,&
     967          117 : &          rprimd_primitive(1:3,3),ch10,&
     968          117 : &          ' This Bravais lattice has iholohedry   =',bravais(1),ch10,&
     969          117 : &          '                          center       =',bravais(2),ch10,&
     970          117 : &          '                          bravais(3:5) =',bravais(3:5),ch10,&
     971          117 : &          '                          bravais(6:8) =',bravais(6:8),ch10,&
     972          117 : &          '                          bravais(9:11)=',bravais(9:11),ch10,&
     973          234 : &          ' The number of point symmetries would be nptsym=',nptsym
     974          117 :          ABI_COMMENT(msg)
     975              : 
     976              :          !Convert the point symmetries to the non-primitive reduced coordinates
     977          117 :          call symrelrot(nsym, rprimd_primitive, rprimd, ptsymrel, tolsym, ierr)
     978              :          !Perhaps not all components of symrel are integers. This generates a return code, and precludes upgrading ptsymrel.
     979          117 :          if(ierr/=0)then
     980              :            write(msg,'(a)')&
     981           79 : &           ' Not all components of symrel are integers in the primitive cell coordinate system.'
     982           79 :            ABI_COMMENT(msg)
     983           79 :            exit
     984              :          endif
     985              :        else ! The cell is primitive
     986         4218 :          ABI_FREE(is_translation)
     987         4218 :          exit
     988              :        endif
     989              : 
     990              :      enddo ! try_primitive
     991              : 
     992              :    end if ! spgroup==0 and nsym==0
     993              : 
     994              :    ! Finalize the computation of coordinates: produce xcart
     995         7224 :    call xred2xcart(natom,rprimd,xcart,xred)
     996              : 
     997              :  end if ! check of existence of an object
     998              : 
     999         7228 :  ABI_FREE(ptsymrel)
    1000         7228 :  ABI_FREE(xcart_read)
    1001         7228 :  ABI_FREE(xcart)
    1002         7228 :  ABI_FREE(xred_read)
    1003         7228 :  ABI_FREE(typat_read)
    1004              : 
    1005         7228 :  call geo%free()
    1006              : 
    1007              :  ! Correct the default nsym value, if a symmetry group has not been generated.
    1008         7228 :  if (nsym==0) nsym=1
    1009              : 
    1010              : !--------------------------------------------------------------------------------------------------------
    1011              : 
    1012         7228 :  icoulomb=0
    1013         7228 :  call intagm(dprarr,intarr,jdtset,marr,1,string(1:lenstr),'icoulomb',tread,'INT')
    1014         7228 :  if(tread==1)icoulomb=intarr(1)
    1015              : 
    1016              :  ! calculate the center of the atomic system such as to put the
    1017              :  ! atoms in the middle of the simulation box for the free BC case.
    1018         7228 :  if (icoulomb == 1) then
    1019            0 :    rcm(:)=zero
    1020            0 :    do iatom=1,natom
    1021            0 :      rcm(:)=rcm(:)+xred(:,iatom)
    1022              :    end do
    1023            0 :    rcm(:)=rcm(:)/real(natom,dp)-half
    1024            0 :    do iatom=1,natom
    1025            0 :      xred(:,iatom)=xred(:,iatom)-rcm(:)
    1026              :    end do
    1027              :    ! Also modify the tnons
    1028            0 :    do isym=1,nsym
    1029            0 :      tnons(:,isym)=matmul(symrel(:,:,isym),rcm(:))-rcm(:)+tnons(:,isym)
    1030              :    end do
    1031              : 
    1032            0 :    ABI_WARNING('icoulomb is 1 --> the average center of coordinates has been translated to (0.5,0.5,0.5)')
    1033              :  end if
    1034              : 
    1035              :  !========================================================================================================
    1036              :  !
    1037              :  ! At this stage, the cell parameters and atomic coordinates are known, as well as the symmetry operations
    1038              :  ! There has been a preliminary analysis of the holohedry (not definitive, though ...)
    1039              :  !
    1040              :  !========================================================================================================
    1041              : 
    1042              : !DEBUG
    1043              : !write(std_out,'(a)')' m_ingeo%ingeo : before symanal '
    1044              : !call flush(std_out)
    1045              : !ENDDEBUG
    1046              : 
    1047              :  ! Here, determine correctly the Bravais lattice and other space group or shubnikov group characteristics
    1048         7228 :  call symanal(bravais,chkprim,genafm,msym,nsym,ptgroupma,rprimd,spgroup,symafm,symrel,tnons,tolsym)
    1049              : 
    1050              : !DEBUG
    1051              : !write(std_out,'(a)')' m_ingeo%ingeo : after symanal '
    1052              : !call flush(std_out)
    1053              : !ENDDEBUG
    1054              : 
    1055              :  ! If the tolerance on symmetries is bigger than 1.e-8, symmetrize the rprimd. Keep xred fixed.
    1056         7228 :  if(tolsym>1.00001e-8)then
    1057              :    ! Check whether the symmetry operations are consistent with the lattice vectors
    1058         7200 :    iexit=1
    1059              : 
    1060         7200 :    call chkorthsy(gprimd,iexit,nsym,rmet,rprimd,symrel,tol8)
    1061              : 
    1062         7200 :    if(iexit==-1)then
    1063              :       write(msg,'(5a,es11.3,15a)')&
    1064           29 :         'It is observed that the input primitive vectors are not accurate:',ch10,&
    1065           29 :         'the lattice is not left invariant within 1.0e-8 when applying symmetry operations.',ch10,&
    1066           29 :         'However, they are only slightly inaccurate, as inaccuracies are within the input tolsym=', tolsym,ch10,&
    1067           29 :         'In order to avoid spurious effects, the primitive vectors have been',ch10,&
    1068           29 :         'symmetrized before storing them in the dataset internal variable.',ch10,&
    1069           29 :         'So, do not be surprised by the fact that your input variables (acell, rprim, xcart, xred, ...)',ch10,&
    1070           29 :         'do not correspond exactly to the ones echoed by ABINIT, the latter being used to do the calculations.',ch10,&
    1071           29 : &       'This is not a problem per se.',ch10,&
    1072           29 : &       'Still, in order to avoid this symmetrization (e.g. for specific debugging/development),',&
    1073           29 : &       ' decrease tolsym to 1.0e-8 or lower.',ch10,&
    1074           58 :         'or (much preferred) use input primitive vectors that are accurate to better than 1.0e-8.'
    1075           29 :      ABI_WARNING(msg)
    1076              : 
    1077           29 :      call symmetrize_rprimd(bravais,nsym,rprimd,symrel,tol8)
    1078           29 :      call mkradim(acell,rprim,rprimd)
    1079              : 
    1080              :      !Needs one more resymmetrization, for the tnons
    1081           87 :      ABI_MALLOC(tnons_new,(3,nsym))
    1082              :      call symmetrize_xred(natom,nsym,symrel,tnons,xred,&
    1083           29 : &          fixed_mismatch=fixed_mismatch,mismatch_fft_tnons=mismatch_fft_tnons,tnons_new=tnons_new,tolsym=tolsym)
    1084         2141 :      tnons(:,1:nsym)=tnons_new(:,:)
    1085           58 :      ABI_FREE(tnons_new)
    1086              : 
    1087              :    end if
    1088              : 
    1089              :  end if
    1090              : 
    1091         7228 :  call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
    1092              :  angdeg(1)=180.0_dp/pi * acos(rmet(2,3)/sqrt(rmet(2,2)*rmet(3,3)))
    1093              :  angdeg(2)=180.0_dp/pi * acos(rmet(1,3)/sqrt(rmet(1,1)*rmet(3,3)))
    1094              :  angdeg(3)=180.0_dp/pi * acos(rmet(1,2)/sqrt(rmet(1,1)*rmet(2,2)))
    1095              : !write(std_out,'(a,3f14.8)') ' ingeo: angdeg(1:3)=',angdeg(1:3)
    1096              : 
    1097              : !--------------------------------------------------------------------------------------
    1098              : 
    1099              :  !Finally prune the set of symmetry in case non-symmorphic operations must be excluded
    1100         7228 :  if(symmorphi==0)then
    1101           93 :    jsym=0
    1102         2050 :    do isym=1,nsym
    1103         7921 :      if(sum(tnons(:,isym)**2)<tol6)then
    1104         1177 :        jsym=jsym+1
    1105              :        ! This symmetry operation is non-symmorphic, and can be kept
    1106         1177 :        if(isym/=jsym)then
    1107         9568 :          symrel(:,:,jsym)=symrel(:,:,isym)
    1108         2944 :          tnons(:,jsym)=tnons(:,isym)
    1109          736 :          symafm(jsym)=symafm(isym)
    1110              :        end if
    1111              :      end if
    1112              :    end do
    1113           93 :    nsym=jsym
    1114              :  end if
    1115              : 
    1116              :  !call symmultsg(nsym,symafm,symrel,tnons)
    1117              : 
    1118              :  ! 9) initialize the list of fixed atoms, and initial velocities -----------------
    1119              :  ! Note: these inputs do not influence the previous generation of
    1120              :  ! symmetry operations. This might be changed in the future
    1121              : 
    1122              :  ! idir=0 is for iatfix , idir=1 is for iatfixx,
    1123              :  ! idir=2 is for iatfixy, idir=3 is for iatfixz
    1124       162192 :  iatfix(:,:)=0
    1125              : 
    1126        36140 :  do idir=0,3
    1127              : 
    1128        28912 :    if(idir==0)then
    1129         7228 :      call intagm(dprarr,intarr,jdtset,marr,1,string(1:lenstr),'natfix',tread,'INT')
    1130        21684 :    else if(idir==1)then
    1131         7228 :      call intagm(dprarr,intarr,jdtset,marr,1,string(1:lenstr),'natfixx',tread,'INT')
    1132        14456 :    else if(idir==2)then
    1133         7228 :      call intagm(dprarr,intarr,jdtset,marr,1,string(1:lenstr),'natfixy',tread,'INT')
    1134         7228 :    else if(idir==3)then
    1135         7228 :      call intagm(dprarr,intarr,jdtset,marr,1,string(1:lenstr),'natfixz',tread,'INT')
    1136              :    end if
    1137              : 
    1138              :    ! Use natfix also for natfixx,natfixy,natfixz
    1139        28912 :    natfix=0
    1140        28912 :    if(tread==1) natfix=intarr(1)
    1141              : 
    1142              :    ! Check the validity of natfix
    1143        28912 :    if (natfix<0 .or. natfix>natom) then
    1144              :      write(msg, '(a,a,a,i0,a,i4,a,a,a)' )&
    1145            0 :        'The input variables natfix, natfixx, natfixy and natfixz must be',ch10,&
    1146            0 :        'between 0 and natom (= ',natom,'), while one of them is ',natfix,'.',ch10,&
    1147            0 :        'Action: correct that occurrence in your input file.'
    1148            0 :      ABI_ERROR(msg)
    1149              :    end if
    1150              : 
    1151              :    !Read iatfix
    1152        28912 :    if(idir==0)then
    1153         7228 :      call intagm(dprarr,intarr,jdtset,marr,natfix,string(1:lenstr),'iatfix',tread,'INT')
    1154        21684 :    else if(idir==1)then
    1155         7228 :      call intagm(dprarr,intarr,jdtset,marr,natfix,string(1:lenstr),'iatfixx',tread,'INT')
    1156        14456 :    else if(idir==2)then
    1157         7228 :      call intagm(dprarr,intarr,jdtset,marr,natfix,string(1:lenstr),'iatfixy',tread,'INT')
    1158         7228 :    else if(idir==3)then
    1159         7228 :      call intagm(dprarr,intarr,jdtset,marr,natfix,string(1:lenstr),'iatfixz',tread,'INT')
    1160              :    end if
    1161              : 
    1162              :    ! If some iatfix was read, natfix must vanish
    1163        28912 :    if (natfix==0 .and. tread==1)then
    1164              :      write(msg, '(a,i1,5a)' )&
    1165            0 :        'For direction ',idir,' the corresponding natfix is zero,',ch10,&
    1166            0 :        'while iatfix specifies some atoms to be fixed.',ch10,&
    1167            0 :        'Action: either specify a non-zero natfix(x,y,z) or suppress iatfix(x,y,z).'
    1168            0 :      ABI_ERROR(msg)
    1169              :    end if
    1170              : 
    1171              :    ! If natfix is non-zero, iatfix must be defined
    1172        28912 :    if (natfix>0 .and. tread==0)then
    1173              :      write(msg, '(a,i1,3a,i0,3a)' )&
    1174            0 :        'For direction ',idir,' no iatfix has been specified,',ch10,&
    1175            0 :        'while natfix specifies that some atoms to be fixed, natfix= ',natfix,'.',ch10,&
    1176            0 :        'Action: either set natfix(x,y,z) to zero or define iatfix(x,y,z).'
    1177            0 :      ABI_ERROR(msg)
    1178              :    end if
    1179              : 
    1180        36140 :    if(tread==1)then
    1181          593 :      do ii=1,natfix
    1182              :        ! Checks the validity of the input iatfix
    1183          326 :        if (intarr(ii)<1 .or. intarr(ii)>natom) then
    1184              :          write(msg, '(a,a,a,i0,a,a,a)' )&
    1185            0 :            'The input variables iatfix, iatfixx, iatfixy and iatfixz must be',ch10,&
    1186            0 :            'between 1 and natom, while one of them is ',intarr(ii),'.',ch10,&
    1187            0 :            'Action: correct that occurrence in your input file.'
    1188            0 :          ABI_ERROR(msg)
    1189              :        end if
    1190              :        ! Finally set the value of the internal iatfix array
    1191         1695 :        do iatom=1,natom
    1192         1428 :          if(intarr(ii)==iatom)then
    1193         1217 :            if(idir==0)iatfix(1:3,iatom)=1
    1194          326 :            if(idir/=0)iatfix(idir,iatom)=1
    1195              :          end if
    1196              :        end do
    1197              :      end do
    1198              :    end if
    1199              : 
    1200              :  end do
    1201              : 
    1202       162192 :  vel(:,:)=zero
    1203         7228 :  call intagm(dprarr,intarr,jdtset,marr,3*natom,string(1:lenstr),'vel',tread,'DPR')
    1204         7234 :  if(tread==1)vel(:,:)=reshape( dprarr(1:3*natom), [3, natom])
    1205         7228 :  call intagm_img(vel,iimage,jdtset,lenstr,nimage,3,natom,string,"vel",tread,'DPR')
    1206              : 
    1207         7228 :  vel_cell(:,:)=zero
    1208         7228 :  call intagm(dprarr,intarr,jdtset,marr,3*3,string(1:lenstr),'vel_cell',tread,'DPR')
    1209         7228 :  if(tread==1)vel_cell(:,:)=reshape( dprarr(1:9), [3,3])
    1210         7228 :  call intagm_img(vel_cell,iimage,jdtset,lenstr,nimage,3,3,string,"vel_cell",tread,'DPR')
    1211              : 
    1212              :  ! mixalch
    1213         7228 :  if(ntypalch>0)then
    1214           26 :    call intagm(dprarr,intarr,jdtset,marr,npspalch*ntypalch,string(1:lenstr),'mixalch',tread,'DPR')
    1215           78 :    if(tread==1) mixalch(1:npspalch,1:ntypalch)= reshape(dprarr(1:npspalch*ntypalch), [npspalch, ntypalch])
    1216           52 :    do itypat=1,ntypalch
    1217           78 :      sumalch=sum(mixalch(1:npspalch,itypat))
    1218           52 :      if(abs(sumalch-one)>tol10)then
    1219              :        write(msg, '(a,i0,2a,f8.2,4a)' )&
    1220            0 :          'For the alchemical atom number ',itypat,ch10,&
    1221            0 :          'the sum of the pseudopotential coefficients is',sumalch,ch10,&
    1222            0 :          'while it should be one.',ch10,&
    1223            0 :          'Action: check the content of the input variable mixalch.'
    1224            0 :        ABI_ERROR(msg)
    1225              :      end if
    1226              :    end do
    1227           26 :    call intagm_img(mixalch,iimage,jdtset,lenstr,nimage,npspalch,ntypalch,string,"mixalch",tread,'DPR')
    1228              :  end if
    1229              : 
    1230              :  ! amu (needs mixalch to be initialized ...)
    1231              :  ! Find the default mass
    1232        21684 :  ABI_MALLOC(mass_psp,(npsp))
    1233        16321 :  do ipsp=1,npsp
    1234         9093 :    call atomdata_from_znucl(atom,znucl(ipsp))
    1235         9093 :    amu_default = atom%amu
    1236        16321 :    mass_psp(ipsp)=amu_default
    1237              :  end do
    1238              :  ! When the pseudo-atom is pure, simple copy
    1239         7228 :  ntyppure=ntypat-ntypalch
    1240         7228 :  if(ntyppure>0)then
    1241        16259 :    amu(1:ntyppure)=mass_psp(1:ntyppure)
    1242              :  end if
    1243              :  ! When the pseudo-atom is alchemical, must make mixing
    1244         7228 :  if(ntypalch>0)then
    1245           52 :    do itypat=ntyppure+1,ntypat
    1246           26 :      amu(itypat)=zero
    1247          104 :      do ipsp=ntyppure+1,npsp
    1248           78 :        amu(itypat)=amu(itypat)+mixalch(ipsp-ntyppure,itypat-ntyppure)*mass_psp(ipsp)
    1249              :      end do
    1250              :    end do
    1251              :  end if
    1252         7228 :  ABI_FREE(mass_psp)
    1253              : 
    1254         7228 :  call intagm(dprarr,intarr,jdtset,marr,ntypat,string(1:lenstr),'amu',tread,'DPR')
    1255         7760 :  if(tread==1)amu(:)=dprarr(1:ntypat)
    1256         7228 :  call intagm_img(amu,iimage,jdtset,lenstr,nimage,ntypat,string,"amu",tread,'DPR')
    1257              : 
    1258         7228 :  ABI_FREE(intarr)
    1259         7228 :  ABI_FREE(dprarr)
    1260              : 
    1261              : !DEBUG
    1262              : !write(std_out,'(a)')' m_ingeo%ingeo : exit '
    1263              : !call flush(std_out)
    1264              : !ENDDEBUG
    1265              : 
    1266        14456 : end subroutine ingeo
    1267              : !!***
    1268              : 
    1269              : !!****f* m_ingeo/ingeobld
    1270              : !! NAME
    1271              : !! ingeobld
    1272              : !!
    1273              : !! FUNCTION
    1274              : !! The geometry builder.
    1275              : !! Start from the types and coordinates of the primitive atoms
    1276              : !! and produce the completed set of atoms, by using the definition
    1277              : !! of objects, then application of rotation, translation and repetition.
    1278              : !!
    1279              : !! INPUTS
    1280              : !! iout=unit number of output file
    1281              : !! jdtset=number of the dataset looked for
    1282              : !! lenstr=actual length of the string
    1283              : !! natrd=number of atoms that have been read in the calling routine
    1284              : !! natom=number of atoms
    1285              : !! nobj=the number of objects
    1286              : !! string*(*)=character string containing all the input data. Initialized previously in instrng.
    1287              : !! typat_read(natrd)=type integer for each atom in the primitive set
    1288              : !! xcart_read(3,natrd)=cartesian coordinates of atoms (bohr), in the primitive set
    1289              : !!
    1290              : !! OUTPUT
    1291              : !! typat(natom)=type integer for each atom in cell
    1292              : !! xcart(3,natom)=cartesian coordinates of atoms (bohr)
    1293              : !!
    1294              : !! SOURCE
    1295              : 
    1296            4 : subroutine ingeobld (iout,jdtset,lenstr,natrd,natom,nobj,string,typat,typat_read,xcart,xcart_read)
    1297              : 
    1298              : !Arguments ------------------------------------
    1299              : !scalars
    1300              :  integer,intent(in) :: iout,jdtset,lenstr,natom,natrd,nobj
    1301              :  character(len=*),intent(in) :: string
    1302              : !arrays
    1303              :  integer,intent(in) :: typat_read(natrd)
    1304              :  integer,intent(out) :: typat(natom)
    1305              :  real(dp),intent(in) :: xcart_read(3,natrd)
    1306              :  real(dp),intent(out) :: xcart(3,natom)
    1307              : 
    1308              : !Local variables-------------------------------
    1309              :  character(len=*), parameter :: format01110 ="(1x,a6,1x,(t9,8i8) )"
    1310              :  character(len=*), parameter :: format01160 ="(1x,a6,1x,1p,(t9,3g18.10)) "
    1311              : !scalars
    1312              :  integer :: belonga,belongb,iatom,iatrd,ii,irep,irep1,irep2,irep3,ivac,marr
    1313              :  integer :: natom_toberead,nread,objan,objbn,rotate,shift,tread,vacnum
    1314              :  real(dp) :: angle,cosine,norm2per,norma,normb,normper,project,sine
    1315              :  character(len=500) :: msg
    1316              : !arrays
    1317              :  integer :: objarf(3),objbrf(3)
    1318            4 :  integer,allocatable :: objaat(:),objbat(:),typat_full(:),vaclst(:)
    1319              :  real(dp) :: axis2(3),axis3(3),axisa(3),axisb(3),objaax(6),objaro(4),objatr(12)
    1320              :  real(dp) :: objbax(6),objbro(4),objbtr(12),parall(3),perpen(3),rotated(3)
    1321              :  real(dp) :: vectora(3),vectorb(3)
    1322            4 :  real(dp),allocatable :: xcart_full(:,:)
    1323            4 :  integer,allocatable :: intarr(:)
    1324            4 :  real(dp),allocatable :: dprarr(:)
    1325              : 
    1326              : ! *************************************************************************
    1327              : 
    1328            4 :  marr=max(12,3*natom)
    1329           12 :  ABI_MALLOC(intarr,(marr))
    1330           12 :  ABI_MALLOC(dprarr,(marr))
    1331              : 
    1332              : !1) Set up the number of vacancies.
    1333              : 
    1334              : !This is the default
    1335            4 :  vacnum=0
    1336            4 :  call intagm(dprarr,intarr,jdtset,marr,1,string(1:lenstr),'vacnum',tread,'INT')
    1337            4 :  if(tread==1) vacnum=intarr(1)
    1338              : 
    1339            4 :  if (vacnum>0)then
    1340            3 :    ABI_MALLOC(vaclst,(vacnum))
    1341              : !  Read list of atoms to be suppressed to create vacancies
    1342            1 :    call intagm(dprarr,intarr,jdtset,marr,vacnum,string(1:lenstr),'vaclst',tread,'INT')
    1343            2 :    if(tread==1) vaclst(:)=intarr(1:vacnum)
    1344            1 :    if(tread/=1)then
    1345              :      write(msg, '(a,a,a,a,a)' )&
    1346            0 : &     'The array vaclst MUST be initialized in the input file',ch10,&
    1347            0 : &     'when vacnum is non-zero.',ch10,&
    1348            0 : &     'Action: initialize vaclst in your input file.'
    1349            0 :      ABI_ERROR(msg)
    1350              :    end if
    1351              :  end if
    1352              : 
    1353            4 :  natom_toberead=natom+vacnum
    1354              : 
    1355              : !2) Set up list and number of atoms in objects, and the --------------
    1356              : !operations to be performed on objects.
    1357              : 
    1358          324 :  write(msg,'(80a,a)')('=',ii=1,80),ch10
    1359            4 :  call wrtout(std_out,msg)
    1360            4 :  call wrtout(iout,msg)
    1361              : 
    1362            4 :  write(msg, '(a,a)' )'--ingeobld: echo values of variables connected to objects --------',ch10
    1363            4 :  call wrtout(std_out,msg)
    1364            4 :  call wrtout(iout,msg)
    1365              : 
    1366            4 :  if(vacnum>0)then
    1367            1 :    write(iout,format01110) 'vacnum',vacnum
    1368            1 :    write(std_out,format01110) 'vacnum',vacnum
    1369            1 :    write(iout,'(1x,a6,1x,(t9,20i3))') 'vaclst',vaclst(:)
    1370            1 :    write(std_out,'(1x,a6,1x,(t9,20i3))') 'vaclst',vaclst(:)
    1371            1 :    write(iout, '(a)' ) ' '
    1372            1 :    write(std_out,'(a)' ) ' '
    1373              :  end if
    1374              : 
    1375            4 :  write(iout,format01110) 'nobj',nobj
    1376            4 :  write(std_out,format01110) 'nobj',nobj
    1377              : 
    1378            4 :  if(nobj/=1 .and. nobj/=2)then
    1379              :    write(msg, '(a,a,a,i8,a,a,a)' )&
    1380            0 : &   'The number of object (nobj) must be either 1 or 2,',ch10,&
    1381            0 : &   'while the input file has  nobj=',nobj,'.',ch10,&
    1382            0 : &   'Action: correct nobj in your input file.'
    1383            0 :    ABI_ERROR(msg)
    1384              :  end if
    1385              : 
    1386            4 :  if(nobj==1 .or. nobj==2)then
    1387              : 
    1388              : !  Read the number of atoms of the object a
    1389            4 :    call intagm(dprarr,intarr,jdtset,marr,1,string(1:lenstr),'objan',tread,'INT')
    1390            4 :    if(tread==1) objan=intarr(1)
    1391              : 
    1392            4 :    if(tread/=1)then
    1393              :      write(msg, '(a,a,a,i8,a,a,a,a,a)' )&
    1394            0 : &     'The number of atoms in object a (objan) must be initialized',ch10,&
    1395            0 : &     'in the input file, when nobj=',nobj,'.',ch10,&
    1396            0 : &     'This is not the case.',ch10,&
    1397            0 : &     'Action: correct objan in your input file.'
    1398            0 :      ABI_ERROR(msg)
    1399              :    end if
    1400              : 
    1401            4 :    write(iout, '(a)' ) ' '
    1402            4 :    write(std_out,'(a)' ) ' '
    1403            4 :    write(iout,format01110) 'objan',objan
    1404            4 :    write(std_out,format01110) 'objan',objan
    1405              : 
    1406            4 :    if(objan<=1 .or. objan>natom)then
    1407              :      write(msg, '(a,a,a,a,a,i8,a,a,a)' )&
    1408            0 : &     'The number of atoms in object a (objan) must be larger than 0',ch10,&
    1409            0 : &     'and smaller than natom.',ch10,&
    1410            0 : &     'It is equal to ',objan,', an unacceptable value.',ch10,&
    1411            0 : &     'Action: correct objan in your input file.'
    1412            0 :      ABI_ERROR(msg)
    1413              :    end if
    1414              : 
    1415              : !  Read list of atoms in object a
    1416            4 :    call intagm(dprarr,intarr,jdtset,marr,objan,string(1:lenstr),'objaat',tread,'INT')
    1417           12 :    ABI_MALLOC(objaat,(objan))
    1418           26 :    if(tread==1) objaat(1:objan)=intarr(1:objan)
    1419              : 
    1420            4 :    if(tread/=1)then
    1421              :      write(msg, '(a,a,a,i8,a,a,a,a,a)' )&
    1422            0 : &     'The list of atoms in object a (objaat) must be initialized',ch10,&
    1423            0 : &     'in the input file, when nobj=',nobj,'.',ch10,&
    1424            0 : &     'This is not the case.',ch10,&
    1425            0 : &     'Action: initialize objaat in your input file.'
    1426            0 :      ABI_ERROR(msg)
    1427              :    end if
    1428              : 
    1429            4 :    write(iout,'(1x,a6,1x,(t9,20i3))') 'objaat',objaat(:)
    1430            4 :    write(std_out,'(1x,a6,1x,(t9,20i3))') 'objaat',objaat(:)
    1431              : 
    1432           26 :    do iatom=1,objan
    1433           26 :      if(objaat(iatom)<1 .or. objaat(iatom)>natom)then
    1434              :        write(msg, '(a,i8,a,a,i8,4a)' )&
    1435            0 : &       'The input value of objaat for atom number ',iatom,ch10,&
    1436            0 : &       'is equal to ',objaat(iatom),', an unacceptable value :',ch10,&
    1437            0 : &       'it should be between 1 and natom. ',&
    1438            0 : &       'Action: correct the array objaat in your input file.'
    1439            0 :        ABI_ERROR(msg)
    1440              :      end if
    1441              :    end do
    1442              : 
    1443            4 :    if(objan>1)then
    1444           22 :      do iatom=1,objan-1
    1445           22 :        if( objaat(iatom)>=objaat(iatom+1) )then
    1446              :          write(msg, '(a,i8,a,a,a,a,a,a)' )&
    1447            0 : &         'The input value of objaat for atom number ',iatom,ch10,&
    1448            0 : &         'is larger or equal to the one of the next atom,',ch10,&
    1449            0 : &         'while this list should be ordered, and an atom cannot be repeated.',ch10,&
    1450            0 : &         'Action: correct the array objaat in your input file.'
    1451            0 :          ABI_ERROR(msg)
    1452              :        end if
    1453              :      end do
    1454              :    end if
    1455              : 
    1456              : !  Read repetition factors
    1457           16 :    objarf(1:3)=1
    1458            4 :    call intagm(dprarr,intarr,jdtset,marr,3,string(1:lenstr),'objarf',tread,'INT')
    1459           16 :    if(tread==1) objarf(1:3)=intarr(1:3)
    1460            4 :    write(iout,'(1x,a6,1x,(t9,20i3))') 'objarf',objarf(:)
    1461            4 :    write(std_out,'(1x,a6,1x,(t9,20i3))') 'objarf',objarf(:)
    1462              : 
    1463            4 :    if(tread==1)then
    1464           16 :      do irep=1,3
    1465           16 :        if(objarf(irep)<1)then
    1466              :          write(msg, '(a,a,a,3i8,a,a,a)' )&
    1467            0 : &         'The input values of objarf(1:3) must be positive,',ch10,&
    1468            0 : &         'while it is ',objarf(1:3),'.',ch10,&
    1469            0 : &         'Action: correct objarf in your input file.'
    1470            0 :          ABI_ERROR(msg)
    1471              :        end if
    1472              :      end do
    1473              :    end if
    1474              : 
    1475              : !  Modify the number of atoms to be read
    1476            4 :    natom_toberead=natom_toberead-objan*(objarf(1)*objarf(2)*objarf(3)-1)
    1477              : 
    1478              : !  Read rotations angles and translations
    1479            4 :    objaro(1:4)=0.0_dp
    1480            4 :    objatr(1:12)=0.0_dp
    1481            4 :    if (objarf(1)*objarf(2)*objarf(3) ==1) then
    1482            0 :      nread=1
    1483            4 :    else if (objarf(2)*objarf(3) ==1) then
    1484            2 :      nread=2
    1485            2 :    else if (objarf(3) ==1) then
    1486            0 :      nread=3
    1487              :    else
    1488            2 :      nread=4
    1489              :    end if
    1490            4 :    call intagm(dprarr,intarr,jdtset,marr,nread,string(1:lenstr),'objaro',tread,'DPR')
    1491            8 :    if(tread==1) objaro(1:nread)=dprarr(1:nread)
    1492              : 
    1493            4 :    call intagm(dprarr,intarr,jdtset,marr,3*nread,string(1:lenstr),'objatr',tread,'LEN')
    1494              : 
    1495           40 :    if(tread==1) objatr(1:3*nread)=dprarr(1:3*nread)
    1496            4 :    write(iout,format01160) 'objaro',objaro(1:4)
    1497            4 :    write(std_out,format01160) 'objaro',objaro(1:4)
    1498            4 :    write(iout,format01160) 'objatr',objatr(1:12)
    1499            4 :    write(std_out,format01160) 'objatr',objatr(1:12)
    1500              : !  If needed, read axes, but default to the x-axis to avoid errors later
    1501            4 :    objaax(1:6)=0.0_dp ; objaax(4)=1.0_dp
    1502              : 
    1503            4 :    if(abs(objaro(1))+abs(objaro(2))+abs(objaro(3))+abs(objaro(4)) > 1.0d-10) then
    1504            2 :      call intagm(dprarr,intarr,jdtset,marr,6,string(1:lenstr),'objaax',tread,'LEN')
    1505           14 :      if(tread==1) objaax(1:6)=dprarr(1:6)
    1506            2 :      if(tread/=1)then
    1507              :        write(msg, '(a,a,a,a,a,a,a)' )&
    1508            0 : &       'The axis of object a (objaax) must be initialized',ch10,&
    1509            0 : &       'in the input file, when rotations (objaro) are present.',ch10,&
    1510            0 : &       'This is not the case.',ch10,&
    1511            0 : &       'Action: initialize objaax in your input file.'
    1512            0 :        ABI_ERROR(msg)
    1513              :      end if
    1514            2 :      write(iout,format01160) 'objaax',objaax(1:6)
    1515            2 :      write(std_out,format01160) 'objaax',objaax(1:6)
    1516              :    end if
    1517              : 
    1518           16 :    axisa(1:3)=objaax(4:6)-objaax(1:3)
    1519            4 :    norma=axisa(1)**2+axisa(2)**2+axisa(3)**2
    1520              : 
    1521            4 :    if(norma<1.0d-10)then
    1522              :      write(msg, '(5a)' )&
    1523            0 : &     'The two points defined by the input array objaax are too',ch10,&
    1524            0 : &     'close to each other, and will not be used to define an axis.',ch10,&
    1525            0 : &     'Action: correct objaax in your input file.'
    1526            0 :      ABI_ERROR(msg)
    1527              :    end if
    1528           16 :    axisa(1:3)=axisa(1:3)/sqrt(norma)
    1529              :  end if !  End condition of existence of a first object
    1530              : 
    1531            4 :  if(nobj==2)then
    1532              : 
    1533              : !  Read the number of atoms of the object b
    1534            3 :    call intagm(dprarr,intarr,jdtset,marr,1,string(1:lenstr),'objbn',tread,'INT')
    1535            3 :    if(tread==1) objbn=intarr(1)
    1536              : 
    1537            3 :    if(tread/=1)then
    1538              :      write(msg, '(a,a,a,i8,a,a,a,a,a)' )&
    1539            0 : &     'The number of atoms in object b (objbn) must be initialized',ch10,&
    1540            0 : &     'in the input file, when nobj=',nobj,'.',ch10,&
    1541            0 : &     'This is not the case.',ch10,&
    1542            0 : &     'Action: initialize objbn in your input file.'
    1543            0 :      ABI_ERROR(msg)
    1544              :    end if
    1545              : 
    1546            3 :    write(iout, '(a)' ) ' '
    1547            3 :    write(std_out,'(a)' ) ' '
    1548            3 :    write(iout,format01110) 'objbn',objbn
    1549            3 :    write(std_out,format01110) 'objbn',objbn
    1550              : 
    1551            3 :    if(objbn<=1 .or. objbn>natom)then
    1552              :      write(msg, '(a,a,a,a,a,i8,a,a,a)' )&
    1553            0 : &     'The number of atoms in object b (objbn) must be larger than 0',ch10,&
    1554            0 : &     'and smaller than natom.',ch10,&
    1555            0 : &     'It is equal to ',objbn,', an unacceptable value.',ch10,&
    1556            0 : &     'Action: correct objbn in your input file.'
    1557            0 :      ABI_ERROR(msg)
    1558              :    end if
    1559              : 
    1560              : !  Read list of atoms in object b
    1561            3 :    call intagm(dprarr,intarr,jdtset,marr,objbn,string(1:lenstr),'objbat',tread,'INT')
    1562            9 :    ABI_MALLOC(objbat,(objbn))
    1563              : 
    1564           22 :    if(tread==1) objbat(1:objbn)=intarr(1:objbn)
    1565            3 :    if(tread/=1)then
    1566              :      write(msg, '(a,a,a,i8,a,a,a,a,a)' )&
    1567            0 : &     'The list of atoms in object b (objbat) must be initialized',ch10,&
    1568            0 : &     'in the input file, when nobj=',nobj,'.',ch10,&
    1569            0 : &     'This is not the case.',ch10,&
    1570            0 : &     'Action: initialize objbat in your input file.'
    1571            0 :      ABI_ERROR(msg)
    1572              :    end if
    1573              : 
    1574            3 :    write(iout,'(1x,a6,1x,(t9,20i3))') 'objbat',objbat(:)
    1575            3 :    write(std_out,'(1x,a6,1x,(t9,20i3))') 'objbat',objbat(:)
    1576              : 
    1577           22 :    do iatom=1,objbn
    1578           22 :      if(objbat(iatom)<1 .or. objbat(iatom)>natom)then
    1579              :        write(msg, '(a,i8,a,a,i8,a,a,a,a,a)' )&
    1580            0 : &       'The input value of objbat for atom number ',iatom,ch10,&
    1581            0 : &       'is equal to ',objbat(iatom),', an unacceptable value :',ch10,&
    1582            0 : &       'it should be between 1 and natom. ',ch10,&
    1583            0 : &       'Action: correct objbat in your input file.'
    1584            0 :        ABI_ERROR(msg)
    1585              :      end if
    1586              :    end do
    1587              : 
    1588            3 :    if(objbn>1)then
    1589           19 :      do iatom=1,objbn-1
    1590           19 :        if( objbat(iatom)>=objbat(iatom+1) )then
    1591              :          write(msg, '(a,i8,a,a,a,a,a,a)' )&
    1592            0 : &         'The input value of objbat for atom number ',iatom,ch10,&
    1593            0 : &         'is larger or equal to the one of the next atom,',ch10,&
    1594            0 : &         'while this list should be ordered, and an atom cannot be repeated.',ch10,&
    1595            0 : &         'Action: correct the array objbat in the input file.'
    1596            0 :          ABI_ERROR(msg)
    1597              :        end if
    1598              :      end do
    1599              :    end if
    1600              : 
    1601              : !  Read repetition factors
    1602           12 :    objbrf(1:3)=1
    1603            3 :    call intagm(dprarr,intarr,jdtset,marr,3,string(1:lenstr),'objbrf',tread,'INT')
    1604           12 :    if(tread==1) objbrf(1:3)=intarr(1:3)
    1605            3 :    write(iout,'(1x,a6,1x,(t9,20i3))') 'objbrf',objbrf(:)
    1606            3 :    write(std_out,'(1x,a6,1x,(t9,20i3))') 'objbrf',objbrf(:)
    1607              : 
    1608            3 :    if(tread==1)then
    1609           12 :      do irep=1,3
    1610           12 :        if(objbrf(irep)<1)then
    1611              :          write(msg, '(a,a,a,3i8,a,a,a)' )&
    1612            0 : &         'The input values of objbrf(1:3) must be positive,',ch10,&
    1613            0 : &         'while it is ',objbrf(1:3),'.',ch10,&
    1614            0 : &         'Action: correct objbrf in your input file.'
    1615            0 :          ABI_ERROR(msg)
    1616              :        end if
    1617              :      end do
    1618              :    end if
    1619              : 
    1620              : !  Modify the number of atoms to be read
    1621            3 :    natom_toberead=natom_toberead-objbn*(objbrf(1)*objbrf(2)*objbrf(3)-1)
    1622              : !  Read rotations angles and translations
    1623            3 :    objbro(1:4)=0.0_dp
    1624            3 :    objbtr(1:12)=0.0_dp
    1625            3 :    if (objbrf(1)*objbrf(2)*objbrf(3) ==1) then
    1626            0 :      nread=1
    1627            3 :    else if (objbrf(2)*objbrf(3) ==1) then
    1628            1 :      nread=2
    1629            2 :    else if (objbrf(3) ==1) then
    1630            0 :      nread=3
    1631              :    else
    1632            2 :      nread=4
    1633              :    end if
    1634            3 :    call intagm(dprarr,intarr,jdtset,marr,nread,string(1:lenstr),'objbro',tread,'DPR')
    1635            5 :    if(tread==1) objbro(1:nread)=dprarr(1:nread)
    1636              : 
    1637            3 :    call intagm(dprarr,intarr,jdtset,marr,3*nread,string(1:lenstr),'objbtr',tread,'LEN')
    1638           33 :    if(tread==1) objbtr(1:3*nread)=dprarr(1:3*nread)
    1639              : 
    1640            3 :    write(iout,format01160) 'objbro',objbro(1:4)
    1641            3 :    write(std_out,format01160) 'objbro',objbro(1:4)
    1642            3 :    write(iout,format01160) 'objbtr',objbtr(1:12)
    1643            3 :    write(std_out,format01160) 'objbtr',objbtr(1:12)
    1644              : 
    1645              : !  If needed, read axes, but default to the x-axis to avoid errors later
    1646            3 :    objbax(1:6)=0.0_dp ; objbax(4)=1.0_dp
    1647            3 :    if(abs(objbro(1))+abs(objbro(2))+abs(objbro(3))+abs(objbro(4)) > 1.0d-10) then
    1648            1 :      call intagm(dprarr,intarr,jdtset,marr,6,string(1:lenstr),'objbax',tread,'LEN')
    1649            7 :      if(tread==1) objbax(1:6)=dprarr(1:6)
    1650            1 :      if(tread/=1)then
    1651              :        write(msg, '(a,a,a,a,a,a,a)' )&
    1652            0 : &       'The axis of object b (objbax) must be initialized',ch10,&
    1653            0 : &       'in the input file, when rotations (objbro) are present.',ch10,&
    1654            0 : &       'This is not the case.',ch10,&
    1655            0 : &       'Action: initialize objbax in your input file.'
    1656            0 :        ABI_ERROR(msg)
    1657              :      end if
    1658            1 :      write(iout,format01160) 'objbax',objbax(1:6)
    1659            1 :      write(std_out,format01160) 'objbax',objbax(1:6)
    1660              :    end if
    1661           12 :    axisb(1:3)=objbax(4:6)-objbax(1:3)
    1662            3 :    normb=axisb(1)**2+axisb(2)**2+axisb(3)**2
    1663            3 :    if(normb<1.0d-10)then
    1664              :      write(msg, '(5a)' )&
    1665            0 : &     'The two points defined by the input array objbax are too',ch10,&
    1666            0 : &     'close to each other, and will not be used to define an axis.',ch10,&
    1667            0 : &     'Action: correct objbax in your input file.'
    1668            0 :      ABI_ERROR(msg)
    1669              :    end if
    1670           12 :    axisb(1:3)=axisb(1:3)/sqrt(normb)
    1671              : 
    1672              : !  Check whether both lists are disjoints. Use a very primitive algorithm.
    1673           17 :    do iatom=1,objan
    1674           89 :      do ii=1,objbn
    1675           86 :        if(objaat(iatom)==objbat(ii))then
    1676              :          write(msg, '(6a,i8,a,i8,3a)' )&
    1677            0 : &         'The objects a and b cannot have a common atom, but it is',ch10,&
    1678            0 : &         'found that the values of objaat and objbat ',&
    1679            0 : &         ' are identical, for their',ch10,&
    1680            0 : &         'atoms number ',iatom,' and ',ii,'.',ch10,&
    1681            0 : &         'Action: change objaat and/or objbat so that they have no common atom anymore.'
    1682            0 :          ABI_ERROR(msg)
    1683              :        end if
    1684              :      end do
    1685              :    end do
    1686              :  end if !  End condition of existence of a second object
    1687              : 
    1688              : !Check whether the number of atoms to be read obtained by relying
    1689              : !on natom, vacnum and the object definitions, or from natrd coincide
    1690            4 :  if(natrd/=natom_toberead)then
    1691              :    write(msg,'(11a,i0,a,i0,2a,i0,a)' )&
    1692            0 : &   ' ingeobld : ERROR -- ',ch10,&
    1693            0 : &   '  The number of atoms to be read (natrd) must be equal',ch10,&
    1694            0 : &   '  to the total number of atoms (natom), plus',ch10,&
    1695            0 : &   '  the number of vacancies (vacnum), minus',ch10,&
    1696            0 : &   '  the number of atoms added by the repetition of objects.',ch10,&
    1697            0 : &   '  This is not the case : natrd= ',natrd,', natom= ',natom,ch10,&
    1698            0 : &   ', vacnum= ',vacnum,';'
    1699            0 :    call wrtout(std_out,msg)
    1700              : 
    1701            0 :    if(nobj==1 .or. nobj==2) then
    1702              :      write(msg,'(a,i3,a,3i3,a,i5,a)' )&
    1703            0 : &     '   object a : objan=',objan,', objarf(1:3)=',objarf(1:3),&
    1704            0 : &     ' => adds ',objan*(objarf(1)*objarf(2)*objarf(3)-1),' atoms.'
    1705            0 :      call wrtout(std_out,msg)
    1706              :    end if
    1707              : 
    1708            0 :    if(nobj==2) then
    1709              :      write(msg,'(a,i3,a,3i3,a,i5,a)' )&
    1710            0 : &     '   object b : objbn=',objbn,', objbrf(1:3)=',objbrf(1:3),&
    1711            0 : &     ' => adds ',objbn*(objbrf(1)*objbrf(2)*objbrf(3)-1),' atoms.'
    1712            0 :      call wrtout(std_out,msg)
    1713              :    end if
    1714              : 
    1715              :    write(msg,'(3a)' )&
    1716            0 : &   '  Action : check the correspondence between natom+vacnum on one side,',ch10,&
    1717            0 : &   '           and natrd, objan, objbn, objarf and objbrf on the other side.'
    1718            0 :    ABI_ERROR(msg)
    1719              :  end if
    1720              : 
    1721              : !6) Produce full set of atoms
    1722              : 
    1723              : !Print the initial atom coordinates if the geometry builder is used
    1724            4 :  write(iout, '(/,a)' )  ' Cartesian coordinates of the primitive atoms '
    1725            4 :  write(std_out,'(/,a)' )' Cartesian coordinates of the primitive atoms '
    1726            4 :  write(iout,format01160) '      ',xcart_read(:,:)
    1727            4 :  write(std_out,format01160) '      ',xcart_read(:,:)
    1728              : 
    1729           12 :  ABI_MALLOC(typat_full,(natom+vacnum))
    1730           12 :  ABI_MALLOC(xcart_full,(3,natom+vacnum))
    1731              : 
    1732              : !Use the work array xcart_full to produce full set of atoms,
    1733              : !including those coming from repeated objects.
    1734            4 :  iatom=1
    1735           93 :  do iatrd=1,natrd
    1736              : 
    1737           89 :    belonga=0 ; belongb=0
    1738           89 :    if(nobj==1 .or. nobj==2)then
    1739              : !    Determine whether the atom belongs to object a
    1740          531 :      do ii=1,objan
    1741          531 :        if(iatrd==objaat(ii))belonga=ii
    1742              :      end do
    1743              :    end if
    1744           89 :    if(nobj==2)then
    1745              : !    Determine whether the atom belong to object b
    1746          594 :      do ii=1,objbn
    1747          594 :        if(iatrd==objbat(ii))belongb=ii
    1748              :      end do
    1749              :    end if
    1750              : 
    1751              :    !write(std_out,'(a,i5,a,i2,i2,a)' )' ingeobld : treating iatrd=',iatrd,', belong(a,b)=',belonga,belongb,'.'
    1752              : 
    1753              : !  In case it does not belong to an object
    1754           93 :    if(belonga==0 .and. belongb==0)then
    1755          192 :      xcart_full(1:3,iatom)=xcart_read(1:3,iatrd)
    1756           48 :      typat_full(iatom)=typat_read(iatrd)
    1757           48 :      iatom=iatom+1
    1758              :    else
    1759              : 
    1760              : !    Repeat, rotate and translate this atom
    1761           41 :      if(belonga/=0)then
    1762              : 
    1763              : !      Treat object a
    1764              : !      Compute the relative coordinate of atom with respect to first point of axis
    1765           88 :        vectora(1:3)=xcart_read(1:3,iatrd)-objaax(1:3)
    1766              : !      Project on axis
    1767           22 :        project=vectora(1)*axisa(1)+vectora(2)*axisa(2)+vectora(3)*axisa(3)
    1768              : !      Get the parallel part
    1769           88 :        parall(1:3)=project*axisa(1:3)
    1770              : !      Get the perpendicular part, to be rotated
    1771           88 :        perpen(1:3)=vectora(1:3)-parall(1:3)
    1772              : !      Compute the norm of the perpendicular part
    1773           22 :        norm2per=perpen(1)**2+perpen(2)**2+perpen(3)**2
    1774              : !      Initialisation to avoid warnings even if used behind if rotate == 1.
    1775           22 :        normper = 0
    1776              : !      It the norm is too small, there is not need to rotate
    1777           22 :        rotate=0
    1778           22 :        if(norm2per>=1.0d-18)then
    1779           18 :          rotate=1
    1780           18 :          normper=sqrt(norm2per)
    1781           72 :          axis2(1:3)=perpen(1:3)/normper
    1782              : !        Get the vector perpendicular to axisa and axisa2
    1783           18 :          axis3(1)=axisa(2)*axis2(3)-axisa(3)*axis2(2)
    1784           18 :          axis3(2)=axisa(3)*axis2(1)-axisa(1)*axis2(3)
    1785           18 :          axis3(3)=axisa(1)*axis2(2)-axisa(2)*axis2(1)
    1786              :        end if
    1787              : 
    1788              : !      Here the repetition loop
    1789           60 :        do irep3=1,objarf(3)
    1790          130 :          do irep2=1,objarf(2)
    1791          260 :            do irep1=1,objarf(1)
    1792              : !            Here the rotation
    1793          152 :              if(rotate==1)then
    1794              : !              Compute the angle of rotation
    1795              :                angle=objaro(1)+(irep1-1)*objaro(2) + &
    1796          128 : &               (irep2-1)*objaro(3)+(irep3-1)*objaro(4)
    1797          128 :                cosine=cos(angle/180.0*pi)
    1798          128 :                sine=sin(angle/180.0*pi)
    1799              :                rotated(1:3)=objaax(1:3)+parall(1:3)+&
    1800          512 : &               normper*(cosine*axis2(1:3)+sine*axis3(1:3))
    1801              :              else
    1802           24 :                rotated(1:3)=vectora(1:3)
    1803              :              end if
    1804              : !            Here the translation
    1805              :              xcart_full(1:3,iatom)=rotated(1:3)+objatr(1:3)+&
    1806          608 : &             (irep1-1)*objatr(4:6)+(irep2-1)*objatr(7:9)+(irep3-1)*objatr(10:12)
    1807          152 :              typat_full(iatom)=typat_read(iatrd)
    1808          222 :              iatom=iatom+1
    1809              :            end do
    1810              :          end do
    1811              :        end do ! End the repetition loop
    1812              : 
    1813              :      else
    1814              : !      If the atom belong to object b
    1815              : !      Compute the relative coordinate of atom with respect to first point of axis
    1816           76 :        vectorb(1:3)=xcart_read(1:3,iatrd)-objbax(1:3)
    1817              : !      Project on axis
    1818           19 :        project=vectorb(1)*axisb(1)+vectorb(2)*axisb(2)+vectorb(3)*axisb(3)
    1819              : !      Get the parallel part
    1820           76 :        parall(1:3)=project*axisb(1:3)
    1821              : !      Get the perpendicular part, to be rotated
    1822           76 :        perpen(1:3)=vectorb(1:3)-parall(1:3)
    1823              : !      Compute the norm of the perpendicular part
    1824           19 :        norm2per=perpen(1)**2+perpen(2)**2+perpen(3)**2
    1825              : !      Initialisation to avoid warnings even if used behind if rotate == 1.
    1826           19 :        normper = 0
    1827              : !      It the norm is too small, there is not need to rotate
    1828           19 :        rotate=0
    1829           19 :        if(norm2per>=1.0d-18)then
    1830           16 :          rotate=1
    1831           16 :          normper=sqrt(norm2per)
    1832           64 :          axis2(1:3)=perpen(1:3)/normper
    1833              : !        Get the vector perpendicular to axisb and axis2
    1834           16 :          axis3(1)=axisb(2)*axis2(3)-axisb(3)*axis2(2)
    1835           16 :          axis3(2)=axisb(3)*axis2(1)-axisb(1)*axis2(3)
    1836           16 :          axis3(3)=axisb(1)*axis2(2)-axisb(2)*axis2(1)
    1837              :        end if
    1838              : !      Here the repetition loop
    1839           54 :        do irep3=1,objbrf(3)
    1840          121 :          do irep2=1,objbrf(2)
    1841          242 :            do irep1=1,objbrf(1)
    1842              : !            Here the rotation
    1843          140 :              if(rotate==1)then
    1844              : !              Compute the angle of rotation
    1845              :                angle=objbro(1)+(irep1-1)*objbro(2) + &
    1846          120 : &               (irep2-1)*objbro(3)+ (irep3-1)*objbro(4)
    1847          120 :                cosine=cos(angle/180.0*pi)
    1848          120 :                sine=sin(angle/180.0*pi)
    1849              :                rotated(1:3)=objbax(1:3)+parall(1:3)+&
    1850          480 : &               normper*(cosine*axis2(1:3)+sine*axis3(1:3))
    1851              :              else
    1852           20 :                rotated(1:3)=vectorb(1:3)
    1853              :              end if
    1854              : !            Here the translation
    1855              :              xcart_full(1:3,iatom)=rotated(1:3)+objbtr(1:3)+&
    1856          560 : &             (irep1-1)*objbtr(4:6)+(irep2-1)*objbtr(7:9)+(irep3-1)*objbtr(10:12)
    1857          140 :              typat_full(iatom)=typat_read(iatrd)
    1858          207 :              iatom=iatom+1
    1859              :            end do
    1860              :          end do
    1861              :        end do ! End the repetition loop
    1862              :      end if ! Condition of belonging to object b
    1863              :    end if ! Condition of belonging to an object
    1864              :  end do ! Loop on atoms
    1865              : 
    1866              : !Create the vacancies here
    1867            4 :  if(vacnum/=0)then
    1868              : !  First label the vacant atoms as belonging to typat 0
    1869            2 :    do ivac=1,vacnum
    1870            2 :      typat_full(vaclst(ivac))=0
    1871              :    end do
    1872              : !  Then compact the arrays
    1873            1 :    shift=0
    1874           64 :    do iatom=1,natom
    1875           63 :      if(typat_full(iatom+shift)==0) shift=shift+1
    1876           64 :      if(shift/=0)then
    1877          252 :        xcart_full(1:3,iatom)=xcart_full(1:3,iatom+shift)
    1878           63 :        typat_full(iatom)=typat_full(iatom+shift)
    1879              :      end if
    1880              :    end do
    1881              :  end if
    1882              : 
    1883              : !Transfer the content of xcart_full and typat_full to the proper location
    1884         1360 :  xcart(:,1:natom)=xcart_full(:,1:natom)
    1885          343 :  typat(1:natom)=typat_full(1:natom)
    1886              : 
    1887            4 :  ABI_FREE(typat_full)
    1888            4 :  ABI_FREE(xcart_full)
    1889            4 :  if(allocated(objaat)) then
    1890            4 :    ABI_FREE(objaat)
    1891              :  end if
    1892            4 :  if(allocated(objbat)) then
    1893            3 :    ABI_FREE(objbat)
    1894              :  end if
    1895              : 
    1896            4 :  ABI_FREE(intarr)
    1897            4 :  ABI_FREE(dprarr)
    1898            4 :  if (vacnum>0)  then
    1899            1 :    ABI_FREE(vaclst)
    1900              :  end if
    1901              : 
    1902            4 : end subroutine ingeobld
    1903              : !!***
    1904              : 
    1905              : !!****f* m_ingeo/fillcell
    1906              : !! NAME
    1907              : !! fillcell
    1908              : !!
    1909              : !! FUNCTION
    1910              : !! Computes the atomic position of all the atoms in the unit cell starting
    1911              : !! with the symmetry operations and the atoms from the asymmetric unit cell.
    1912              : !!
    1913              : !! INPUTS
    1914              : !!  chrgat(natom)=target charge for each atom. Not always used, it depends on the value of constraint_kind
    1915              : !!  natrd = number of atoms in the asymmetric unit cell
    1916              : !!  natom = total number of atoms (to be checked)
    1917              : !!  nsym = number of symmetry operations
    1918              : !!  symafm(nsym)=(anti)ferromagnetic part of symmetry operations
    1919              : !!  symrel(3,3,nsym)=symmetry operations in real space in terms
    1920              : !!   of primitive translations
    1921              : !!  tnons(3,nsym)=nonsymmorphic translations for symmetry operations
    1922              : !!  tolsym=tolerance on symmetries
    1923              : !!  typat(1:natrd)=type integer for each atom in cell
    1924              : !!  xred(3,1:natrd)=reduced dimensionless atomic coordinates
    1925              : !!
    1926              : !! OUTPUT
    1927              : !!
    1928              : !! SIDE EFFECTS
    1929              : !!  At input, for the asymmetric unit cell
    1930              : !!  nucdipmom(3,1:natrd)=nuclear magnetic dipole moments of the atoms
    1931              : !!  spinat(3,1:natrd)=spin-magnetization of the atoms
    1932              : !!  spinat_cart(3,1:natrd)=spin-magnetization of the atoms (Cartesian)
    1933              : !!  typat(1:natrd)=type integer for each atom in cell
    1934              : !!  xred(3,1:natrd)=reduced dimensionless atomic coordinates
    1935              : !!
    1936              : !!  At output, for the complete unit cell
    1937              : !!  nucdipmom(3,1:natom)=nuclear magnetic dipole moments of the atoms
    1938              : !!  spinat(3,1:natom)=spin-magnetization of the atoms
    1939              : !!  spinat_cart(3,1:natom)=spin-magnetization of the atoms (Cartesian)
    1940              : !!  typat(1:natom)=type integer for each atom in cell
    1941              : !!  xred(3,1:natom)=reduced dimensionless atomic coordinates
    1942              : !!
    1943              : !! SOURCE
    1944              : 
    1945         1588 : subroutine fillcell(chrgat,natom,natrd,nsym,nucdipmom,spinat,spinat_cart,symafm,symrel,tnons,tolsym,typat,xred)
    1946              : 
    1947              : !Arguments ------------------------------------
    1948              : !scalars
    1949              :  integer,intent(in) :: natom,natrd,nsym
    1950              : !arrays
    1951              :  integer,intent(in) :: symafm(nsym),symrel(3,3,nsym)
    1952              :  integer,intent(inout) :: typat(natom)
    1953              :  real(dp),intent(in) :: tolsym
    1954              :  real(dp),intent(in) :: tnons(3,nsym)
    1955              :  real(dp),intent(inout) :: chrgat(natom),nucdipmom(3,natom),spinat(3,natom),spinat_cart(3,natom),xred(3,natom)
    1956              : 
    1957              : !Local variables ------------------------------
    1958              : !scalars
    1959              :  integer :: curat,flagch,flageq,ii,iij,jj,kk
    1960              :  character(len=500) :: msg
    1961              : !arrays
    1962         3176 :  integer :: bcktypat(nsym*natrd)
    1963         3176 :  real(dp) :: bckat(3),bcknucdipmom(3,nsym*natrd)
    1964         3176 :  real(dp) :: bckchrgat(nsym*natrd),bckspinat(3,nsym*natrd),bckspinat_cart(3,nsym*natrd),bckxred(3,nsym*natrd)
    1965              : 
    1966              : ! *************************************************************************
    1967              : 
    1968              : !DEBUG
    1969              : !write(std_out,*)' fillcell : enter with nsym, natrd= ',nsym,natrd
    1970              : !write(std_out,*)' Describe the different symmetry operations (index,symrel,tnons,symafm)'
    1971              : !do ii=1,nsym
    1972              : !write(std_out,'(i3,2x,9i3,3es12.2,i3)')ii,symrel(:,:,ii),tnons(:,ii),symafm(ii)
    1973              : !end do
    1974              : !write(std_out,*)' Describe the input atoms (index,typat,xred,spinat)'
    1975              : !do jj=1,natrd
    1976              : !write(std_out,'(i3,2x,i3,6es12.2)')jj,typat(jj),xred(:,jj),spinat(:,jj)
    1977              : !end do
    1978              : !ENDDEBUG
    1979              : 
    1980         1588 :  curat=0
    1981              : 
    1982              : !Cycle over all the symmetry operations
    1983        23822 :  do ii=1,nsym
    1984              : 
    1985              : !  Cycle over all the atoms in the asymmetric unit cell
    1986        49344 :    do jj=1,natrd
    1987              : 
    1988              : !    Symmetry operation application
    1989       714616 :      bckat(:)=matmul(symrel(:,:,ii),xred(:,jj))+tnons(:,ii)
    1990              : 
    1991              : !    Normalization of the coordinates in [0,1)
    1992       102088 :      do iij=1,3
    1993       101094 :        do while (bckat(iij)<-tolsym)
    1994       101094 :          bckat(iij)=bckat(iij)+1.0d0
    1995              :        end do
    1996       104263 :        do while (bckat(iij)>=1.0d0-tolsym)
    1997         2175 :          bckat(iij)=bckat(iij)-1.0d0
    1998              :        end do
    1999              :      end do
    2000              : 
    2001              : !    Check for duplicate atoms
    2002        25522 :      flagch=0
    2003       324532 :      do kk=1,curat
    2004       300417 :        flageq=0
    2005              :        if ( abs(bckxred(1,kk)-bckat(1))<tolsym  .and. &
    2006       300417 : &       abs(bckxred(2,kk)-bckat(2))<tolsym  .and. &
    2007              : &       abs(bckxred(3,kk)-bckat(3))<tolsym       ) exit
    2008       324532 :        flagch=flagch+1
    2009              :      end do
    2010              : 
    2011        47756 :      if (flagch==curat) then
    2012              : !      Add the obtained atom to the bckxred list
    2013        24115 :        curat=curat+1
    2014        96460 :        bckxred(:,curat)=bckat
    2015        24115 :        bcktypat(curat)=typat(jj)
    2016        24115 :        bckchrgat(curat)=chrgat(jj)
    2017        96460 :        bcknucdipmom(:,curat)=nucdipmom(:,jj)
    2018        96460 :        bckspinat(:,curat)=spinat(:,jj)*symafm(ii)
    2019        96460 :        bckspinat_cart(:,curat)=spinat_cart(:,jj)*symafm(ii)
    2020              :      end if
    2021              : 
    2022              :    end do
    2023              :  end do
    2024              : 
    2025              : !DEBUG
    2026              : !write(std_out,*)' fillcell : Proposed coordinates ='
    2027              : !do ii=1,curat
    2028              : !write(std_out,'(i4,3es16.6)' )ii,bckxred(:,ii)
    2029              : !end do
    2030              : !ENDDEBUG
    2031              : 
    2032         1588 :  if (curat>natom) then
    2033              :    write(msg, '(a,i3,a,a,i7,a,a,a,a)' )&
    2034            0 : &   'The number of atoms obtained from symmetries, ',curat,ch10,&
    2035            0 : &   'is greater than the input number of atoms, natom=',natom,ch10,&
    2036            0 : &   'This is not allowed.',ch10,&
    2037            0 : &   'Action: modify natom or the symmetry data in the input file.'
    2038            0 :    ABI_ERROR(msg)
    2039              :  end if
    2040              : 
    2041         1588 :  if (curat<natom) then
    2042              :    write(msg, '(a,i3,a,a,i7,a,a,a,a)' )&
    2043            0 : &   'The number of atoms obtained from symmetries, ',curat,ch10,&
    2044            0 : &   'is lower than the input number of atoms, natom=',natom,ch10,&
    2045            0 : &   'This is not allowed.',ch10,&
    2046            0 : &   'Action: modify natom or the symmetry data in the input file.'
    2047            0 :    ABI_ERROR(msg)
    2048              :  end if
    2049              : 
    2050              : !Assignment of symmetry to xred
    2051        98048 :  xred(:,1:natom)=bckxred(:,1:natom)
    2052        25703 :  typat(1:natom)=bcktypat(1:natom)
    2053        25703 :  chrgat(1:natom)=bckchrgat(1:natom)
    2054        98048 :  nucdipmom(1:3,1:natom)=bcknucdipmom(1:3,1:natom)
    2055        98048 :  spinat(1:3,1:natom)=bckspinat(1:3,1:natom)
    2056        98048 :  spinat_cart(1:3,1:natom)=bckspinat_cart(1:3,1:natom)
    2057              : 
    2058              : !DEBUG
    2059              : !write(std_out,*)' fillcell : exit with natom=',natom
    2060              : !write(std_out,*)' Describe the output atoms (index,typat,xred,spinat)'
    2061              : !do jj=1,natom
    2062              : !write(std_out,'(i3,2x,i3,6es12.2)')jj,typat(jj),xred(:,jj),spinat(:,jj)
    2063              : !end do
    2064              : !ENDDEBUG
    2065              : 
    2066         1588 : end subroutine fillcell
    2067              : !!***
    2068              : 
    2069              : !!****f* m_ingeo/invacuum
    2070              : !!
    2071              : !! NAME
    2072              : !! invacuum
    2073              : !!
    2074              : !! FUNCTION
    2075              : !! Determine whether there is vacuum along some of the primitive directions in real space.
    2076              : !!
    2077              : !! INPUTS
    2078              : !! jdtset=number of the dataset looked for
    2079              : !! lenstr=actual length of the string
    2080              : !! natom=number of atoms
    2081              : !! rprimd(3,3)=dimensional real space primitive translations (bohr)
    2082              : !! string*(*)=character string containing all the input data.
    2083              : !!  Initialized previously in instrng.
    2084              : !! xred(3,natom)=reduced dimensionless atomic coordinates
    2085              : !!
    2086              : !! OUTPUT
    2087              : !! vacuum(3)= for each direction, 0 if no vacuum, 1 if vacuum
    2088              : !!
    2089              : !! SOURCE
    2090              : 
    2091        13923 : subroutine invacuum(jdtset,lenstr,natom,rprimd,string,vacuum,xred)
    2092              : 
    2093              : !Arguments ------------------------------------
    2094              : !scalars
    2095              :  integer,intent(in) :: jdtset,lenstr,natom
    2096              :  character(len=*),intent(in) :: string
    2097              : !arrays
    2098              :  integer,intent(out) :: vacuum(3)
    2099              :  real(dp),intent(in) :: rprimd(3,3),xred(3,natom)
    2100              : 
    2101              : !Local variables-------------------------------
    2102              : !scalars
    2103              :  integer :: ia,ii,marr,tread
    2104              :  real(dp) :: max_diff_xred,ucvol,vacwidth,vacxred
    2105              : !arrays
    2106        13923 :  integer,allocatable :: list(:)
    2107        13923 :  integer,allocatable :: intarr(:)
    2108              :  real(dp) :: gmet(3,3),gprimd(3,3),rmet(3,3)
    2109        13923 :  real(dp),allocatable :: xred_sorted(:)
    2110        13923 :  real(dp),allocatable :: dprarr(:)
    2111              : 
    2112              : ! *************************************************************************
    2113              : 
    2114              : !Compute the maximum size of arrays intarr and dprarr
    2115        13923 :  marr=3
    2116        13923 :  ABI_MALLOC(intarr,(marr))
    2117        13923 :  ABI_MALLOC(dprarr,(marr))
    2118              : 
    2119              : !Get metric quantities
    2120        13923 :  call metric(gmet,gprimd,-1,rmet,rprimd,ucvol)
    2121              : 
    2122              : !Read vacwidth, or set the default
    2123        13923 :  vacwidth=10.0_dp
    2124        13923 :  call intagm(dprarr,intarr,jdtset,marr,1,string(1:lenstr),'vacwidth',tread,'LEN')
    2125        13923 :  if(tread==1) vacwidth=dprarr(1)
    2126              : 
    2127              : !Read vacuum, or compute it using the atomic coordinates and vacwidth.
    2128        13923 :  vacuum(1:3)=0
    2129        13923 :  call intagm(dprarr,intarr,jdtset,marr,3,string(1:lenstr),'vacuum',tread,'INT')
    2130              : 
    2131        13923 :  if(tread==1)then
    2132            8 :    vacuum(1:3)=intarr(1:3)
    2133              :  else
    2134              : !  For each direction, determine whether a vacuum space exists
    2135        41763 :    ABI_MALLOC(list,(natom))
    2136        41763 :    ABI_MALLOC(xred_sorted,(natom))
    2137        55684 :    do ii=1,3
    2138              : !    This is the minimum xred difference needed to have vacwidth
    2139       167052 :      vacxred=vacwidth*sqrt(sum(gprimd(:,ii)**2))
    2140              : !    Project the reduced coordinate in the [0.0_dp,1.0_dp[ interval
    2141       270141 :      xred_sorted(:)=mod(xred(ii,:),1.0_dp)
    2142              : !    list is dummy
    2143       270141 :      list(:)=0
    2144              : !    Sort xred_sorted
    2145        41763 :      call sort_dp(natom,xred_sorted,list,tol14)
    2146        41763 :      if(natom==1)then
    2147              :        max_diff_xred=1.0_dp
    2148              :      else
    2149              : !      Compute the difference between each pair of atom in the sorted order
    2150              :        max_diff_xred=0.0_dp
    2151       220398 :        do ia=1,natom-1
    2152       220398 :          max_diff_xred=max(max_diff_xred,xred_sorted(ia+1)-xred_sorted(ia))
    2153              :        end do
    2154              : !      Do not forget the image of the first atom in the next cell
    2155        33783 :        max_diff_xred=max(max_diff_xred,1.0_dp+xred_sorted(1)-xred_sorted(ia))
    2156              :      end if
    2157        55684 :      if(vacxred<max_diff_xred+tol10)vacuum(ii)=1
    2158              :    end do
    2159        13921 :    ABI_FREE(list)
    2160        13921 :    ABI_FREE(xred_sorted)
    2161              :  end if
    2162              : 
    2163              : !DEBUG
    2164              : !write(std_out,*)' invacuum : vacuum=',vacuum(1:3)
    2165              : !ENDDEBUG
    2166              : 
    2167        13923 :  ABI_FREE(intarr)
    2168        13923 :  ABI_FREE(dprarr)
    2169              : 
    2170        13923 : end subroutine invacuum
    2171              : !!***
    2172              : 
    2173              : !!****f* m_ingeo/checkspvec
    2174              : !!
    2175              : !! NAME
    2176              : !! checkspvec
    2177              : !!
    2178              : !! FUNCTION
    2179              : !! Check the consistency of spin-related input vectors (such as spinat or
    2180              : !! hspinfield) with the spin quantization axis (spinaxis), and convert
    2181              : !! Cartesian coordnate to the local spinaxis coordinate when needed
    2182              : !!
    2183              : !! INPUTS
    2184              : !! name=character string identifying the spin-related quantity: 'spinat' or 'hspinfield'
    2185              : !! nitem=number of spin vectors to be treated: natom for spinat, 1 for hspinfield
    2186              : !! spinaxis_in(3)=spin quantization axis
    2187              : !! tread=integer flag (0 or 1), set to 1 if the local-frame quantity
    2188              : !!       (spinat or hspinfield) is provided in the input
    2189              : !! tread_cart=integer flag (0 or 1), set to 1 if the Cartesian quantity
    2190              : !!            (spinat_cart or hspinfield_cart) is provided in the input 
    2191              : !! vec_local(nvec,nitem)=spin vectors defined in the local spin reference coordinates
    2192              : !! vec_cart(nvec,nitem)=spin vectors defined in Cartesian coordinates
    2193              : !!
    2194              : !! OUTPUT
    2195              : !! vec_local=updated consistent spin vectors in local spin reference coordinate
    2196              : !! vec_cart=updated consistent spin vectors in cartesian coordinate
    2197              : !!
    2198              : !! SOURCE
    2199              : 
    2200        14196 : subroutine checkspvec(name,nitem,spinaxis_in,tread,tread_cart,vec_local,vec_cart)
    2201              : 
    2202              : !Arguments ------------------------------------
    2203              : !scalars
    2204              :  integer,intent(in) :: nitem, tread, tread_cart
    2205              :  character(len=*),intent(in) :: name
    2206              : !arrays
    2207              :  real(dp),intent(in) :: spinaxis_in(3)
    2208              :  real(dp),intent(inout) :: vec_local(3,nitem), vec_cart(3,nitem) 
    2209              : 
    2210              : !Local variables-------------------------------
    2211              : !scalars
    2212              :  integer :: i, icase
    2213              :  real(dp) :: alpha, beta, norm
    2214              : !arrays
    2215              :  real(dp) :: spinaxis(3), R(3,3), RT(3,3), v_cart(3), v_local(3)
    2216              :  logical  :: trivial_axis
    2217              :  character(len=1000) :: msg
    2218              : 
    2219              : ! *************************************************************************
    2220              : 
    2221              : ! case 0: nothing provided
    2222        15903 :  if (tread == 0 .and. tread_cart == 0) return
    2223              : 
    2224         1707 :  spinaxis(:) = spinaxis_in(:)
    2225         6828 :  norm = sqrt(dot_product(spinaxis, spinaxis))
    2226         1707 :  if (norm <= tol8) then
    2227            0 :    spinaxis(:) = [zero, zero, one]
    2228            0 :    trivial_axis = .true.
    2229              :  else
    2230         6828 :    spinaxis(:) = spinaxis(:) / norm
    2231         6825 :    trivial_axis = all(abs(spinaxis(:) - [zero, zero, one]) < tol8)
    2232              :  end if
    2233              : 
    2234         1707 :  R(:,:) = zero
    2235         1707 :  R(1,1) = one; R(2,2) = one; R(3,3) = one
    2236              : 
    2237         1707 :  if (.not. trivial_axis) then
    2238            1 :    call geteuler(spinaxis, alpha, beta)
    2239            1 :    call cart2spinaxis(alpha, beta, R)
    2240              :  end if
    2241        22191 :  RT(:,:) = transpose(R)
    2242              : 
    2243              :  ! 3 cases: (tread, tread_cart)
    2244         1707 :  icase = 2*tread + tread_cart
    2245              :  
    2246              :  select case (icase)
    2247              :  
    2248              :  case (1) ! case 1: only _cart provided (tread = 0, tread_cart = 1)
    2249            2 :    do i = 1, nitem
    2250           17 :      vec_local(:,i) = matmul(R, vec_cart(:,i))
    2251              :      end do
    2252         1706 :    return
    2253              : 
    2254              :  case (2) ! case 2: only local provided (tread = 1, tread_cart = 0)
    2255         1706 :    if (.not. trivial_axis) then
    2256              :      write(msg,'(a)') 'Spinaxis is defined, but only ' // trim(name) // ' is present.' // ch10 // &
    2257              :                       'Action: please use ' // trim(name) // '_cart (Cartesian) instead of ' // trim(name) // &
    2258            0 :                       'when spinaxis is set.'
    2259            0 :      ABI_ERROR(msg)
    2260              :    end if
    2261         3842 :    do i = 1, nitem    
    2262        10250 :      vec_cart(:,i) = vec_local(:,i)
    2263              :    end do
    2264              :    return
    2265              : 
    2266              :  case (3) ! case 3: both provided and check consistency: (tread = tread_cart = 1) 
    2267            0 :    do i = 1, nitem
    2268            0 :      v_cart(:) = matmul(RT, vec_local(:,i))
    2269            0 :      v_local(:) = matmul(R, vec_cart(:,i))
    2270              : 
    2271            0 :      if (maxval(abs(v_local(:) - vec_local(:, i))) > tol8 .or. &
    2272            0 :          maxval(abs(v_cart(:) - vec_cart(:, i))) > tol8) then
    2273              :        write(msg,'(a,a,a,a,a,a,a,3(1x,es16.8),a,a,3(1x,es16.8),a,a,3(1x,es16.8),a,a)') &
    2274            0 :         'Both ', trim(name), ' and ', trim(name), '_cart are set but inconsistent.', ch10, &
    2275            0 :         'spinaxis =', spinaxis_in(1), spinaxis_in(2), spinaxis_in(3), ch10, &
    2276            0 :          trim(name)//' (local) =', vec_local(1,i), vec_local(2,i), vec_local(3,i), ch10, &
    2277            0 :          trim(name)//'_cart (cart) =', vec_cart(1,i), vec_cart(2,i), vec_cart(3,i), ch10, &
    2278            0 :         'Action: make them consistent or provide only one of them.'
    2279            0 :        ABI_ERROR(msg)
    2280              :      end if
    2281              :    end do
    2282         1707 :    return
    2283              : 
    2284              :  end select
    2285              : 
    2286              : end subroutine checkspvec
    2287              : !!***
    2288              : 
    2289              : end module m_ingeo
    2290              : !!***
        

Generated by: LCOV version 2.3-1