subroutine aptrotq (rotm, ku, tol, theta, ux, uy, uz, & thx, thy, thz, nerr) ccbeg. cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c c SUBROUTINE APTROTQ c c call aptrotq (rotm, ku, tol, theta, ux, uy, uz, c & thx, thy, thz, nerr) c c Version: aptrotq Updated 1990 January 18 14:20. c aptrotq Originated 1989 November 2 14:10. c c Author: Arthur L. Edwards, LLNL, L-298, Telephone (925) 422-4123. c c c Purpose: To analyse the rotation operator rotm, to find the single c rotation angle theta and the axis of rotation u = (ux, uy, uz), c and the sequential rotation angles thx, thy, thz, around the c x, y, and z axes, respectively. c The operator rotm must be a unitary 3 x 3 matrix. c The 3 row vectors must form a positive unit vector triple. c The 3 column vectors must form a positive unit vector triple. c The trace (sum of the diagonal elements) must be equal to c trace = 1.0 + 2.0 * cos (theta). c Angles may be in degrees (ku = 0) or radians (ku = 1). c Sines and cosines less than tol will be treated as zero. c Flag nerr indicates any errors in rotm or ku. c c Input: rotm, ku, tol. c c Output: theta, ux, uy, uz, thx, thy, thz, nerr. c c Glossary: c c ku Input Indicates angle units are degrees (0) or radians (1). c c nerr Output Indicates an input error, if not 0. c 1 if matrix trace is bad. c 2 if ku is not 0 or 1. c c rotm Output Rotation operator (a unitary 3 x 3 matrix). c Must be sized rotm(3,3). c c theta Output Angle of rotation around axis (ux, uy, uz), c counterclockwise when rotation axis is pointed at c observer. Units are degrees (ku = 0) or radians c (ku = 1). c c tol Input Numerical tolerance limit. Used to test and adjust c unit vector components and point coordinates. c On Cray computers, recommend 1.e-5 to 1.e-11. c c thx Output Angle of rotation around x axis. See theta. c c thy Output Angle of rotation around y ayis. See theta. c c thz Output Angle of rotation around z azis. See theta. c c ux,uy,uz Output The x, y, z components of the unit vector parallel c to the rotation axis. c cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc ccend. c.... Dimensioned arguments. c---- Rotation matrix. dimension rotm (3,3) c.... Local variables. c---- Single axis rotation angle. common /laptrotq/ angle c---- Is x axis rotation angle. common /laptrotq/ angx c---- Is y axis rotation angle. common /laptrotq/ angy c---- Is z axis rotation angle. common /laptrotq/ angz c---- Cosine of rotation angle. common /laptrotq/ costh c---- Cosine of x axis rotation angle. common /laptrotq/ cthx c---- Cosine of y axis rotation angle. common /laptrotq/ cthy c---- Cosine of z axis rotation angle. common /laptrotq/ cthz c---- A very small number. common /laptrotq/ fuz c---- Mathematical constant, pi. common /laptrotq/ pi c---- Sine of rotation angle. common /laptrotq/ sinth c---- Sine of x axis rotation angle. common /laptrotq/ sthx c---- Sine of y axis rotation angle. common /laptrotq/ sthy c---- Sine of z axis rotation angle. common /laptrotq/ sthz c---- Sum of squares of sine, cosine. common /laptrotq/ sumsq cbugc***DEBUG begins. cbugc---- Array index. cbug common /laptrotq/ i cbugc---- Array index. cbug common /laptrotq/ j cbugc---- Array index. cbug common /laptrotq/ n cbugc---- Square of magnitude of row vector. cbug common /laptrotq/ sumrow (3) cbugc---- Square of magnitude of column vector. cbug common /laptrotq/ sumcol (3) cbugc---- 1.0 + 2.0 * costh. cbug common /laptrotq/ trace cbug 9901 format (/ 'aptrotq rotm=',3(/ 2x,1p3e22.14)) cbug 9902 format (' sumrow=',1p3e22.14 / cbug & ' sumcol=',1p3e22.14) cbug 9903 format (' trace= ',1pe22.14) cbug write ( 3, 9901) ((rotm(i,j), j = 1, 3), i = 1, 3) cbug do 981 n = 1, 3 cbug sumrow(n) = rotm(n,1)**2 + rotm(n,2)**2 + rotm(n,3)**2 cbug sumcol(n) = rotm(1,n)**2 + rotm(2,n)**2 + rotm(3,n)**2 cbug 981 continue cbug write ( 3, 9902) (sumrow(n), n = 1, 3), (sumcol(n), n = 1, 3) cbug trace = rotm(1,1) + rotm(2,2) + rotm(3,3) cbug write ( 3, 9903) trace cbugc***DEBUG ends. c.... Initialize. c---- A very small number. fuz = 1.e-99 c---- Mathematical constant, pi. pi = 3.14159265358979323 nerr = 0 theta = -1.e+99 ux = -1.e+99 uy = -1.e+99 uz = -1.e+99 thx = -1.e+99 thy = -1.e+99 thz = -1.e+99 c.... Find the single-axis angle of rotation, and the axis of rotation. costh = 0.5 * (rotm(1,1) + rotm(2,2) + rotm(3,3) - 1.0) if (abs (1.0 - costh) .le. tol) then costh = 1.0 sinth = 0.0 elseif (abs (1.0 + costh) .le. tol) then costh = -1.0 sinth = 0.0 elseif (abs (costh) .le. tol) then costh = 0.0 sinth = 1.0 c++++ Matrix trace is bad. elseif (abs (costh) .gt. 1.0) then nerr = 1 cbugc***DEBUG begins. cbug 9911 format ('aptrotq error. costh=',1pe22.14) cbug write ( 3, 9911) costh cbugc***DEBUG ends. go to 210 else sinth = sqrt ((1.0 - costh) * (1.0 + costh)) endif angle = acos (costh) c.... Get rotation angle in radians. if (ku .eq. 0) then theta = angle * 180.0 / pi elseif (ku .eq. 1) then theta = angle else nerr = 2 cbugc***DEBUG begins. cbug 9921 format ('aptrotq error. ku=',i6) cbug write ( 3, 9921) ku cbugc***DEBUG ends. go to 210 endif if (sinth .gt. tol) then ux = 0.5 * (rotm(3,2) - rotm(2,3)) / sinth uy = 0.5 * (rotm(1,3) - rotm(3,1)) / sinth uz = 0.5 * (rotm(2,1) - rotm(1,2)) / sinth c---- If theta is 0 or 180 degrees. else ux = sqrt (0.5 * (rotm(1,1) + 1.0)) c++++ Sign may change. uy = sqrt (0.5 * (rotm(2,2) + 1.0)) c++++ Sign may change. uz = sqrt (0.5 * (rotm(3,3) + 1.0)) if ((ux .ge. uy) .and. (ux .ge. uz)) then uy = 0.5 * rotm(1,2) / ux uz = 0.5 * rotm(1,3) / ux elseif ((uy .ge. uz) .and. (uy .ge. ux)) then ux = 0.5 * rotm(1,2) / uy uz = 0.5 * rotm(2,3) / uy elseif ((uz .ge. ux) .and. (uz .ge. uy)) then ux = 0.5 * rotm(1,3) / uz uy = 0.5 * rotm(2,3) / uz endif endif cbugc***DEBUG begins. cbug 9931 format (5x,'theta=',f12.6,' costh=',f10.6,' sinth=',f10.6 / cbug & ' ux,uy,uz=',1p3e22.14) cbug write ( 3, 9931) theta, costh, sinth, ux, uy, uz cbugc***DEBUG ends. c.... Find the 3 angles for sequential rotation around the x, y, and z axes. sthy = -rotm(3,1) if (abs (1.0 - sthy) .le. tol) then sthy = 1.0 cthy = 0.0 elseif (abs (1.0 + sthy) .le. tol) then sthy = -1.0 cthy = 0.0 elseif (abs (sthy) .le. tol) then sthy = 0.0 cthy = 1.0 c++++ Matrix trace is bad. elseif (abs (sthy) .gt. 1.0) then nerr = 1 cbugc***DEBUG begins. cbug 9941 format ('aptrotq error. sthy=',1pe22.14) cbug write ( 3, 9941) sthy cbugc***DEBUG ends. go to 210 else cthy = sqrt ((1.0 - sthy) * (1.0 + sthy)) endif if (cthy .gt. tol) then sthx = rotm(3,2) / cthy cthx = rotm(3,3) / cthy sthz = rotm(2,1) / cthy cthz = rotm(1,1) / cthy c---- If y angle is 90 or -90 degrees. else cthx = 1.0 sthx = 0.0 cthz = rotm(2,2) sthz = -rotm(1,2) endif sumsq = sthx**2 + cthx**2 if (abs (sumsq - 1.0) .gt. tol) then nerr = 1 cbugc***DEBUG begins. cbug 9951 format ('aptrotq error. sthx**2 + cthx**2=',1pe22.14) cbug write ( 3, 9951) sumsq cbugc***DEBUG ends. go to 210 endif sumsq = sthz**2 + cthz**2 if (abs (sumsq - 1.0) .gt. tol) then nerr = 1 cbugc***DEBUG begins. cbug 9961 format ('aptrotq error. sthz**2 + cthz**2=',1pe22.14) cbug write ( 3, 9961) sumsq cbugc***DEBUG ends. go to 210 endif c.... Get rotation angles in radians. angx = atan2 (sthx, (cthx + fuz)) angy = atan2 (sthy, (cthy + fuz)) angz = atan2 (sthz, (cthz + fuz)) if (ku .eq. 0) then thx = angx * 180.0 / pi thy = angy * 180.0 / pi thz = angz * 180.0 / pi elseif (ku .eq. 1) then thx = angx thy = angy thz = angz else nerr = 2 cbugc***DEBUG begins. cbugc____ 9921 format ("aptrotq error. ku=",i6) cbug write ( 3, 9921) ku cbugc***DEBUG ends. go to 210 endif cbugc***DEBUG begins. cbug 9971 format (5x,'th(x,y,z)=',3f12.6 / cbug & ' cth,sth(x,y,z)=',6f10.6) cbug write ( 3, 9971) thx, thy, thz, cbug & cthx, sthx, cthy, sthy, cthz, sthz cbugc***DEBUG ends. 210 return c.... End of subroutine aptrotq. (+1 line.) end UCRL-WEB-209832