The Elk Code
findprimcell.f90
Go to the documentation of this file.
1 
2 ! Copyright (C) 2007 J. K. Dewhurst, S. Sharma and C. Ambrosch-Draxl.
3 ! This file is distributed under the terms of the GNU General Public License.
4 ! See the file COPYING for license details.
5 
6 !BOP
7 ! !ROUTINE: findprimcell
8 ! !INTERFACE:
9 subroutine findprimcell
10 ! !USES:
11 use modmain
12 ! !DESCRIPTION:
13 ! This routine finds the smallest primitive cell which produces the same
14 ! crystal structure as the conventional cell. This is done by searching
15 ! through all the vectors which connect atomic positions and finding those
16 ! which leave the crystal structure invariant. Of these, the three shortest
17 ! which produce a non-zero unit cell volume are chosen.
18 !
19 ! !REVISION HISTORY:
20 ! Created April 2007 (JKD)
21 !EOP
22 !BOC
23 implicit none
24 ! local variables
25 integer is,js,ia,ja,ka,na
26 integer i1,i2,i3,i,j,n
27 real(8) v1(3),v2(3),v3(3)
28 real(8) t1,t2
29 ! allocatable arrays
30 real(8), allocatable :: dp(:),vp(:,:)
31 do is=1,nspecies
32  do ia=1,natoms(is)
33 ! make sure all atomic coordinates are in [0,1)
34  call r3frac(epslat,atposl(:,ia,is))
35 ! determine atomic Cartesian coordinates
36  call r3mv(avec,atposl(:,ia,is),atposc(:,ia,is))
37  end do
38 end do
39 ! find the smallest set of atoms
40 is=1
41 do js=1,nspecies
42 ! if a species has only one atom the cell must be primitive
43  if (natoms(js) == 1) return
44  if (natoms(js) < natoms(is)) is=js
45 end do
46 n=27*natoms(is)
47 allocate(dp(n),vp(3,n))
48 ! generate set of possible lattice vectors
49 n=0
50 do ia=1,natoms(is)
51  v1(:)=atposl(:,ia,is)-atposl(:,1,is)
52  do i1=-1,1
53  v2(1)=v1(1)+dble(i1)
54  do i2=-1,1
55  v2(2)=v1(2)+dble(i2)
56  do i3=-1,1
57  v2(3)=v1(3)+dble(i3)
58  t1=abs(v2(1))+abs(v2(2))+abs(v2(3))
59  if (t1 < epslat) goto 20
60 ! check if vector v2 leaves conventional cell invariant
61  do js=1,nspecies
62  do ja=1,natoms(js)
63  v3(:)=atposl(:,ja,js)+v2(:)
64  call r3frac(epslat,v3)
65  do ka=1,natoms(js)
66 ! check both positions and magnetic fields are the same
67  t1=sum(abs(atposl(:,ka,js)-v3(:)))
68  t2=sum(abs(bfcmt0(:,ja,js)-bfcmt0(:,ka,js)))
69  if ((t1 < epslat).and.(t2 < epslat)) goto 10
70  end do
71 ! atom ja has no equivalent under translation by v2
72  goto 20
73 10 continue
74  end do
75  end do
76 ! cell invariant under translation by v2, so add to list
77  n=n+1
78  call r3mv(avec,v2,vp(:,n))
79  dp(n)=sqrt(vp(1,n)**2+vp(2,n)**2+vp(3,n)**2)
80 20 continue
81  end do
82  end do
83  end do
84 end do
85 if (n == 0) then
86  write(*,*)
87  write(*,'("Error(findprimcell): cannot find any lattice vectors")')
88  write(*,*)
89  stop
90 end if
91 ! find the shortest lattice vector
92 j=1
93 t1=1.d8
94 do i=1,n
95  if (dp(i) < t1+epslat) then
96  j=i
97  t1=dp(i)
98  end if
99 end do
100 avec(:,1)=vp(:,j)
101 ! find the next shortest lattice vector not parallel to the first
102 j=1
103 t1=1.d8
104 do i=1,n
105  call r3cross(avec(:,1),vp(:,i),v1)
106  t2=sqrt(v1(1)**2+v1(2)**2+v1(3)**2)
107  if (t2 > epslat) then
108  if (dp(i) < t1+epslat) then
109  j=i
110  t1=dp(i)
111  end if
112  end if
113 end do
114 avec(:,2)=vp(:,j)
115 ! find the next shortest lattice vector which gives non-zero unit cell volume
116 call r3cross(avec(:,1),avec(:,2),v1)
117 j=1
118 t1=1.d8
119 do i=1,n
120  t2=dot_product(vp(:,i),v1(:))
121  if (abs(t2) > epslat) then
122  if (dp(i) < t1+epslat) then
123  j=i
124  t1=dp(i)
125  end if
126  end if
127 end do
128 avec(:,3)=vp(:,j)
129 call r3minv(avec,ainv)
130 ! remove redundant atoms
131 do is=1,nspecies
132  na=0
133  do ia=1,natoms(is)
134  call r3mv(ainv,atposc(:,ia,is),v1)
135  call r3frac(epslat,v1)
136  do ja=1,na
137  t1=sum(abs(atposl(:,ja,is)-v1(:)))
138  if (t1 < epslat) goto 30
139  end do
140  na=na+1
141  atposl(:,na,is)=v1(:)
142  call r3mv(avec,atposl(:,na,is),atposc(:,na,is))
143 ! re-index external magnetic fields
144  bfcmt0(:,na,is)=bfcmt0(:,ia,is)
145 ! re-index fixed spin moment vectors
146  mommtfix(:,na,is)=mommtfix(:,ia,is)
147 30 continue
148  end do
149  natoms(is)=na
150 end do
151 deallocate(dp,vp)
152 end subroutine
153 !EOC
154 
real(8), dimension(3, maxatoms, maxspecies) bfcmt0
Definition: modmain.f90:275
subroutine findprimcell
real(8), dimension(3, 3) ainv
Definition: modmain.f90:14
subroutine r3minv(a, b)
Definition: r3minv.f90:10
real(8), dimension(3, maxatoms, maxspecies) atposl
Definition: modmain.f90:51
real(8), dimension(3, 3) avec
Definition: modmain.f90:12
pure subroutine r3frac(eps, v)
Definition: r3frac.f90:10
real(8), dimension(3, maxatoms, maxspecies) mommtfix
Definition: modmain.f90:259
integer, dimension(maxspecies) natoms
Definition: modmain.f90:36
real(8) epslat
Definition: modmain.f90:24
integer nspecies
Definition: modmain.f90:34
pure subroutine r3cross(x, y, z)
Definition: r3cross.f90:10
pure subroutine r3mv(a, x, y)
Definition: r3mv.f90:10
real(8), dimension(3, maxatoms, maxspecies) atposc
Definition: modmain.f90:54