The Elk Code
rotaxang.f90
Go to the documentation of this file.
1 
2 ! Copyright (C) 2006 J. K. Dewhurst, S. Sharma and C. Ambrosch-Draxl.
3 ! This file is distributed under the terms of the GNU Lesser General Public
4 ! License. See the file COPYING for license details.
5 
6 !BOP
7 ! !ROUTINE: rotaxang
8 ! !INTERFACE:
9 subroutine rotaxang(eps,rot,det,v,th)
10 ! !INPUT/OUTPUT PARAMETERS:
11 ! eps : zero vector tolerance (in,real)
12 ! rot : rotation matrix (in,real(3,3))
13 ! det : matrix determinant (out,real)
14 ! v : normalised axis vector (out,real(3))
15 ! th : rotation angle (out,real)
16 ! !DESCRIPTION:
17 ! Given a rotation matrix
18 ! $$ R(\hat{\bf v},\theta)=
19 ! \left(\begin{matrix}
20 ! \cos\theta+x^2(1-\cos\theta) &
21 ! xy(1-\cos\theta)+z\sin\theta &
22 ! xz(1-\cos\theta)-y\sin\theta \\
23 ! xy(1-\cos\theta)-z\sin\theta &
24 ! \cos\theta+y^2(1-\cos\theta) &
25 ! yz(1-\cos\theta)+x\sin\theta \\
26 ! xz(1-\cos\theta)+y\sin\theta &
27 ! yz(1-\cos\theta)-x\sin\theta &
28 ! \cos\theta+z^2(1-\cos\theta)
29 ! \end{matrix}\right), $$
30 ! this routine determines the axis of rotation $\hat{\bf v}$ and the angle of
31 ! rotation $\theta$. If $R$ corresponds to an improper rotation then only the
32 ! proper part is used and {\tt det} is set to $-1$. The rotation convention
33 ! follows the `right-hand rule'.
34 !
35 ! !REVISION HISTORY:
36 ! Created December 2006 (JKD)
37 !EOP
38 !BOC
39 implicit none
40 ! arguments
41 real(8), intent(in) :: eps,rot(3,3)
42 real(8), intent(out) :: det,v(3),th
43 ! local variables
44 real(8), parameter :: pi=3.1415926535897932385d0
45 real(8) rotp(3,3),t1,t2
46 ! find the determinant and proper rotation matrix
47 det=rot(1,1)*(rot(2,2)*rot(3,3)-rot(3,2)*rot(2,3)) &
48  +rot(2,1)*(rot(3,2)*rot(1,3)-rot(1,2)*rot(3,3)) &
49  +rot(3,1)*(rot(1,2)*rot(2,3)-rot(2,2)*rot(1,3))
50 if (abs(det-1.d0) < eps) then
51  det=1.d0
52  rotp(1:3,1:3)=rot(1:3,1:3)
53 else if (abs(det+1.d0) < eps) then
54  det=-1.d0
55  rotp(1:3,1:3)=-rot(1:3,1:3)
56 else
57  goto 10
58 end if
59 v(1)=0.5d0*(rotp(2,3)-rotp(3,2))
60 v(2)=0.5d0*(rotp(3,1)-rotp(1,3))
61 v(3)=0.5d0*(rotp(1,2)-rotp(2,1))
62 t1=sqrt(v(1)**2+v(2)**2+v(3)**2)
63 t2=0.5d0*(rotp(1,1)+rotp(2,2)+rotp(3,3)-1.d0)
64 if (abs(abs(t2)-1.d0) > eps) then
65 ! theta not equal to 0 or pi
66  th=-atan2(t1,t2)
67  v(1:3)=v(1:3)/t1
68 else
69 ! special case of sin(th)=0
70  if (t2 > 0.d0) then
71 ! zero angle: axis arbitrary
72  th=0.d0
73  v(1)=0.d0; v(2)=0.d0; v(3)=1.d0
74  else
75 ! rotation by pi
76  th=pi
77  if ((rotp(1,1) >= rotp(2,2)).and.(rotp(1,1) >= rotp(3,3))) then
78  if (rotp(1,1) < (-1.d0+eps)) goto 10
79  v(1)=sqrt(0.5d0*abs(rotp(1,1)+1.d0))
80  v(2)=(rotp(2,1)+rotp(1,2))/(4.d0*v(1))
81  v(3)=(rotp(3,1)+rotp(1,3))/(4.d0*v(1))
82  else if ((rotp(2,2) >= rotp(1,1)).and.(rotp(2,2) >= rotp(3,3))) then
83  if (rotp(2,2) < (-1.d0+eps)) goto 10
84  v(2)=sqrt(0.5d0*abs(rotp(2,2)+1.d0))
85  v(3)=(rotp(3,2)+rotp(2,3))/(4.d0*v(2))
86  v(1)=(rotp(1,2)+rotp(2,1))/(4.d0*v(2))
87  else
88  if (rotp(3,3) < (-1.d0+eps)) goto 10
89  v(3)=sqrt(0.5d0*abs(rotp(3,3)+1.d0))
90  v(1)=(rotp(1,3)+rotp(3,1))/(4.d0*v(3))
91  v(2)=(rotp(2,3)+rotp(3,2))/(4.d0*v(3))
92  end if
93  end if
94 end if
95 return
96 10 continue
97 write(*,*)
98 write(*,'("Error(rotaxang): invalid rotation matrix:")')
99 write(*,'(3G18.10)') rot(1,1:3)
100 write(*,'(3G18.10)') rot(2,1:3)
101 write(*,'(3G18.10)') rot(3,1:3)
102 write(*,*)
103 stop
104 end subroutine
105 !EOC
106 
subroutine rotaxang(eps, rot, det, v, th)
Definition: rotaxang.f90:10