TABLE OF CONTENTS


ABINIT/randomcellpos [ Functions ]

[ Top ] [ Functions ]

NAME

  randomcellpos

FUNCTION

  FIXME: This subroutine creates a unit cell with random atomic positions. It is
         assumed that the cell parameters are given and fixed. Several methods are
        used to generate the cell.

COPYRIGHT

  Copyright (C) 2010-2017 ABINIT group (AHR)
  This file is distributed under the terms of the
  GNU General Public License, see ~abinit/COPYING
  or http://www.gnu.org/copyleft/gpl.txt .

INPUTS

 natom=number of atoms
 npsp=number of pseudopotentials (needed for the dimension of znucl)
 ntypat=number of type of atoms
 random_atpos=input variable  
   0 no generation of random atomic potision
   1 completely random atomic potisions
   2 random atomic positions, avoiding too close atoms (prevent coming closer than a fraction of the sum of covalent radii)
   3 same than 2 but also generates the rprim and acell randomly within some given ranges (angles between 50 and 130)
 ratsph(1:ntypat)=radius of the atomic sphere
 rprimd(3,3)=dimensional primitive translations in real space (bohr)
 typat(1:natom)= input variable giving the type of each atom
 znucl(1:npsp)=nuclear number of atom as specified in psp file

OUTPUT

 xred(3,natom)=reduced dimensionless atomic coordinates

SIDE EFFECTS

NOTES

PARENTS

      ingeo

CHILDREN

      atomdata_from_znucl,mkrdim,xred2xcart

SOURCE

 46 #if defined HAVE_CONFIG_H
 47 #include "config.h"
 48 #endif
 49 
 50 #include "abi_common.h"
 51 
 52 
 53 subroutine randomcellpos(natom,npsp,ntypat,random_atpos,ratsph,rprim,rprimd,typat,xred,znucl,acell)
 54 
 55  use defs_basis
 56  use m_profiling_abi
 57  use m_errors
 58  use m_atomdata
 59 
 60 !This section has been created automatically by the script Abilint (TD).
 61 !Do not modify the following lines by hand.
 62 #undef ABI_FUNC
 63 #define ABI_FUNC 'randomcellpos'
 64  use interfaces_28_numeric_noabirule
 65  use interfaces_41_geometry, except_this_one => randomcellpos
 66 !End of the abilint section
 67 
 68  implicit none
 69 
 70 !Arguments ------------------------------------
 71 !scalars
 72  integer,intent(in) :: natom,npsp,ntypat,random_atpos
 73 !arrays
 74  integer, intent(in)   :: typat(natom)
 75  real(dp),intent(in)   :: ratsph(ntypat)
 76  real(dp), intent(inout)  :: rprim(3,3)
 77  real(dp), intent(inout)  :: rprimd(3,3)
 78  real(dp), intent(inout) :: xred(3,natom)
 79  real(dp), intent(in) :: znucl(npsp)
 80  real(dp), intent(inout) :: acell(3)
 81 
 82 !Local variables-------------------------------
 83  integer ::   iatom=0,ii,idum=-20
 84  real(dp) ::  rij(3), rijd(3), radiuscovi, radiuscovj, dist, rati, ratj, angdeg(3)
 85  real(dp) ::  cosang,aa,cc,a2
 86  character(len=500) :: message            
 87  type(atomdata_t) :: atom
 88  
 89 ! *************************************************************************
 90  
 91 !DEBUG
 92 !For the time being, print rprimd to keep it as an argument, in spite of abirule checking.
 93 !write (std_out,*) ' randomcellpos : enter'
 94 !write(std_out,*)' rprimd=',rprimd
 95 !write(std_out,*)' znucl=',znucl
 96 !write(std_out,*)' typat=',typat
 97 !write(std_out,*)' random_atpos=',random_atpos
 98 !ENDDEBUG
 99 
100  if(random_atpos==2 .and. npsp/=ntypat)then
101    write(message, '(a,i5,2a,i5,a,i5,4a)' )&
102 &   'Input variable random_atpos= ',random_atpos,ch10,&
103 &   'However, the number of pseudopotentials ',npsp,', is not equal to the number of type of atoms ',ntypat,ch10,&
104 &   'The use of alchemical mixing cannot be combined with the constraint based on the mixing of covalent radii.',ch10,&
105 &   'Action : switch to another value of random_atpos.'
106    MSG_ERROR(message)
107  end if
108 
109 !random_atpos = 0   Default value, no random initialisation
110 !random_atpos = 1   Fully random (Is it really useful ???)
111 !random_atpos = 2   Random, but the sum of the two covalent radii is  
112 !less than the interatomic distance
113 !random_atpos = 3   Random, but the sum of the two (other type of)  
114 !radii is less than the interatomic distance
115 !random_atpos = 4   Random, but the sum of the two pseudopotential  
116 !radii is less than the interatomic distance
117 !random_atpos = 5   Random, but the interatomic distance must be bigger  
118 !than the sum of
119 !some input variable (well, instead of defining a new variable, why  
120 !not use ratsph ?)
121 !Right now we are not using a factor for the tested distance.. something to be done, after a new variable has been defined
122 
123  if (random_atpos /= 0) then
124    select case (random_atpos)
125    case (1)
126      do ii=1,natom 
127        xred(1,ii)=uniformrandom(idum) 
128        xred(2,ii)=uniformrandom(idum) 
129        xred(3,ii)=uniformrandom(idum) 
130      end do
131    case (2)
132      iatom=0
133      do
134        iatom=iatom+1
135        xred(1,iatom)=uniformrandom(idum) 
136        xred(2,iatom)=uniformrandom(idum) 
137        xred(3,iatom)=uniformrandom(idum) 
138        call atomdata_from_znucl(atom,znucl(typat(iatom)))
139        radiuscovi = atom%rcov
140        do ii=1,iatom-1
141          rij=xred(:,iatom)-xred(:,ii)
142 !          periodic boundary conditions
143          rij = rij - 0.5
144          rij = rij - anint (rij)
145 !          coming back to cube between (0,1)
146          rij = rij + 0.5
147 !          convert reduced coordinates to cartesian coordinates
148          call xred2xcart(1,rprimd,rijd,rij)
149          dist=dot_product(rijd,rijd)
150          call atomdata_from_znucl(atom,znucl(typat(ii)))
151          radiuscovj = atom%rcov
152          if (dist<(radiuscovj+radiuscovi)) then
153            iatom = iatom -1
154            EXIT
155          end if
156        end do
157        if (iatom>=natom) EXIT
158      end do 
159    case(3)
160      iatom=0
161      do
162        iatom=iatom+1
163        xred(1,iatom)=uniformrandom(idum) 
164        xred(2,iatom)=uniformrandom(idum) 
165        xred(3,iatom)=uniformrandom(idum) 
166        call atomdata_from_znucl(atom,znucl(typat(iatom)))
167        radiuscovi = atom%rcov
168        do ii=1,iatom-1
169          rij=xred(:,iatom)-xred(:,ii)
170 !          periodic boundary conditions
171          rij = rij - 0.5
172          rij = rij - anint (rij)
173 !          coming back to cube between (0,1)
174          rij = rij + 0.5
175 !          convert reduced coordinates to cartesian coordinates
176          call xred2xcart(1,rprimd,rijd,rij)
177          dist=dot_product(rijd,rijd)
178          call atomdata_from_znucl(atom,znucl(typat(ii)))
179          radiuscovj = atom%rcov
180          if (dist<(radiuscovj+radiuscovi)) then
181            iatom = iatom -1
182            EXIT
183          end if
184        end do
185        if (iatom>=natom) EXIT
186      end do 
187      do ii=1,3
188 !        generates cells with angles between 60 and 120 degrees
189        angdeg(ii)=60_dp+uniformrandom(idum)*60.0_dp
190      end do
191      if (angdeg(1)+angdeg(2)+angdeg(3)>360._dp) then
192        angdeg(3)=360._dp-angdeg(1)-angdeg(2)
193      end if
194 !      check if angles are between the limits and create rprim
195      if( abs(angdeg(1)-angdeg(2))<tol12 .and. &
196 &     abs(angdeg(2)-angdeg(3))<tol12 .and. &
197 &     abs(angdeg(1)-90._dp)+abs(angdeg(2)-90._dp)+abs(angdeg(3)-90._dp)>tol12 )then
198 !        Treat the case of equal angles (except all right angles) :
199 !        generates trigonal symmetry wrt third axis
200        cosang=cos(pi*angdeg(1)/180.0_dp)
201        a2=2.0_dp/3.0_dp*(1.0_dp-cosang)
202        aa=sqrt(a2)
203        cc=sqrt(1.0_dp-a2)
204        rprim(1,1)=aa        ; rprim(2,1)=0.0_dp                 ; rprim(3,1)=cc
205        rprim(1,2)=-0.5_dp*aa ; rprim(2,2)= sqrt(3.0_dp)*0.5_dp*aa ; rprim(3,2)=cc
206        rprim(1,3)=-0.5_dp*aa ; rprim(2,3)=-sqrt(3.0_dp)*0.5_dp*aa ; rprim(3,3)=cc
207 !        DEBUG
208 !        write(std_out,*)' ingeo : angdeg=',angdeg(1:3)
209 !        write(std_out,*)' ingeo : aa,cc=',aa,cc
210 !        ENDDEBUG
211      else
212 !        Treat all the other cases
213        rprim(:,:)=0.0_dp
214        rprim(1,1)=1.0_dp
215        rprim(1,2)=cos(pi*angdeg(3)/180.0_dp)
216        rprim(2,2)=sin(pi*angdeg(3)/180.0_dp)
217        rprim(1,3)=cos(pi*angdeg(2)/180.0_dp)
218        rprim(2,3)=(cos(pi*angdeg(1)/180.0_dp)-rprim(1,2)*rprim(1,3))/rprim(2,2)
219        rprim(3,3)=sqrt(1.0_dp-rprim(1,3)**2-rprim(2,3)**2)
220      end if
221 !      generate acell
222      aa=zero
223      do ii=1,npsp
224        aa=znucl(ii)
225      end do
226      do ii=1,3
227        acell(ii)=aa+uniformrandom(idum)*4.0
228      end do 
229      call mkrdim(acell,rprim,rprimd)
230    case(4)
231      write(std_out,*) 'Not implemented yet'
232    case(5)
233      iatom=0
234      do
235        iatom=iatom+1
236        xred(1,iatom)=uniformrandom(idum) 
237        xred(2,iatom)=uniformrandom(idum) 
238        xred(3,iatom)=uniformrandom(idum) 
239        rati=ratsph(typat(iatom))
240        do ii=1,iatom-1
241          ratj=ratsph(typat(ii))
242 !          apply periodic boundary conditions
243          rij=(xred(:,iatom)-xred(:,ii))-0.5
244          rij = rij - ANINT ( rij )
245          rij = rij + 0.5
246          call xred2xcart(natom,rprimd,rijd,rij)
247          dist=dot_product(rijd,rijd)
248          if (dist<(rati+ratj)) EXIT
249        end do
250        if (iatom==natom) EXIT
251        if (ii<(iatom-1)) iatom=iatom-1
252      end do 
253    end select
254  end if 
255 
256 end subroutine randomcellpos