The Elk Code
 
Loading...
Searching...
No Matches
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:
9subroutine findprimcell
10! !USES:
11use 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
23implicit none
24! local variables
25integer is,js,ia,ja,ka,na
26integer i1,i2,i3,i,j,n
27real(8) v1(3),v2(3),v3(3)
28real(8) t1,t2
29! allocatable arrays
30real(8), allocatable :: dp(:),vp(:,:)
31do 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
38end do
39! find the smallest set of atoms
40is=1
41do 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
45end do
46n=27*natoms(is)
47allocate(dp(n),vp(3,n))
48! generate set of possible lattice vectors
49n=0
50do 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
7310 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)
8020 continue
81 end do
82 end do
83 end do
84end do
85if (n == 0) then
86 write(*,*)
87 write(*,'("Error(findprimcell): cannot find any lattice vectors")')
88 write(*,*)
89 stop
90end if
91! find the shortest lattice vector
92j=1
93t1=1.d8
94do i=1,n
95 if (dp(i) < t1+epslat) then
96 j=i
97 t1=dp(i)
98 end if
99end do
100avec(:,1)=vp(:,j)
101! find the next shortest lattice vector not parallel to the first
102j=1
103t1=1.d8
104do 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
113end do
114avec(:,2)=vp(:,j)
115! find the next shortest lattice vector which gives non-zero unit cell volume
116call r3cross(avec(:,1),avec(:,2),v1)
117j=1
118t1=1.d8
119do 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
127end do
128avec(:,3)=vp(:,j)
129call r3minv(avec,ainv)
130! remove redundant atoms
131do 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)
14730 continue
148 end do
149 natoms(is)=na
150end do
151deallocate(dp,vp)
152end subroutine
153!EOC
154
subroutine findprimcell
real(8), dimension(3, maxatoms, maxspecies) atposc
Definition modmain.f90:54
integer, dimension(maxspecies) natoms
Definition modmain.f90:36
real(8), dimension(3, 3) avec
Definition modmain.f90:12
real(8) epslat
Definition modmain.f90:24
real(8), dimension(3, maxatoms, maxspecies) mommtfix
Definition modmain.f90:259
real(8), dimension(3, 3) ainv
Definition modmain.f90:14
integer nspecies
Definition modmain.f90:34
real(8), dimension(3, maxatoms, maxspecies) atposl
Definition modmain.f90:51
real(8), dimension(3, maxatoms, maxspecies) bfcmt0
Definition modmain.f90:275
pure subroutine r3cross(x, y, z)
Definition r3cross.f90:10
pure subroutine r3frac(eps, v)
Definition r3frac.f90:10
subroutine r3minv(a, b)
Definition r3minv.f90:10
pure subroutine r3mv(a, x, y)
Definition r3mv.f90:10