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