subroutine aptetru (ax, ay, az, bx, by, bz, iunit, anga, angb, & tol, ux, uy, uz, nerr) ccbeg. cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c c SUBROUTINE APTETRU c c call aptetru (ax, ay, az, bx, by, bz, iunit, anga, angb, c & tol, ux, uy, uz, nerr) c c Version: aptetru Updated 2001 March 28 11:20. c aptetru Originated 2001 March 28 11:20. c c Author: Arthur L. Edwards, LLNL, L-298, Telephone (925) 422-4123. c c c Purpose: Given vectors a = (ax, ay, az) and b = (bx, by, bz), to find c unit vector u = (ux, uy, uz) at angle anga from vector "a" and c at angle angb from vector "b". Angles anga and angb are in c degrees (iunit = 0) or in radians (iunit = 1). These vectors c may represent the edge vectors at the vertex of a polyhedron. c c No solution is possible if vectors "a" and "b" are parallel, c or if the angles anga and angb are too close to zero or 180 c degrees (zero or pi radians), relative to the angle between c vectors "a" and "b". c c Otherwise, two solutions are possible, with vector "u" on either c side of a plane containing vectors "a" and "b". The solution c returned here is that for which the vectors "a", "b" and "u" c firm a positive triple, like the thumb, first finger and middle c finger of the right hand, respectively. To get the other c solution, exchange vectors "a" and "b" and exchange angles anga c and angb. c c Flag nerr indicates any input error. c c Input: anga, angb, ax, ay, az, bx, by, bz, iunit, tol. c c Output: ux, uy, uz, nerr. c c Calls: aptvdot, aptvuna, aptvunb, aptvxun c c Glossary: c c anga Input The angle between vector "a" and vector "u", c in degrees (iunit = 0) or in radians (iunit = 1). c c angb Input The angle between vector "b" and vector "u", c in degrees (iunit = 0) or in radians (iunit = 1). c c ax,ay,az Input The x, y, z components of vector "a". c c bx,by,bz Input The x, y, z components of vector "b". c c nerr Output Indicates an input error, if not 0. c 1 if vector "a" has zero length. c 2 if vector "b" has zero length. c 3 if vectors "a" and "b" are parallel. c 4 if angles anga and angb allow no solution. c c ux,uy,uz Output The x, y, z components of vector "u". c Vectors "a", "b" and "u" form a positive triple, c i.e,: "a" cross "b" dot "u" > 0. c c tol Input Numerical tolerance limit. c On computers with 64-bit floating vector numbers, c recommend 1.e-5 to 1.e-11. c cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc ccend. implicit none integer iunit ! Unit for angles, 0 for degrees. integer nerr ! Error indicator. integer nerra ! Error indicator. real anga ! Angle between vector "a" and vector "u". real angb ! Angle between vector "b" and vector "u". real arg ! Temporary term, square of a sine? real ax ! Component x of vector "a". real ay ! Component y of vector "a". real az ! Component z of vector "a". real bx ! Component x of vector "b". real by ! Component y of vector "b". real bz ! Component z of vector "b". real cosab ! Cosine of angle between "a" and "b". real cosa ! Cosine of angle between "a" and "u". real cosb ! Cosine of angle between "b" and "u". real ux ! Component x of vector "u". real uy ! Component y of vector "u". real uz ! Component z of vector "u". real dab ! Length of vector ua cross ub. real dlena ! Length of vector "a". real dlenb ! Length of vector "b". real dlenu ! Length of vector "u". real erra ! Relative error in calculating fa. real errb ! Relative error in calculating fb. real fa ! Coefficient of vector ua. real fab ! Coefficient of vector uab. real fb ! Coefficient of vector ub. real pi ! Math constant 3.14159265358979324... real sinab2 ! Sine**2 of angle between "a" and "b", real tol ! Precision constant. real uabx ! Component x of vector uab. real uaby ! Component y of vector uab. real uabz ! Component z of vector uab. real uax ! Component x of vector ua. real uay ! Component y of vector ua. real uaz ! Component z of vector ua. real ubx ! Component x of vector ub. real uby ! Component y of vector ub. real ubz ! Component z of vector ub. cbugc***DEBUG begins. cbug 9901 format (/ 'aptetru finding a vertex edge. tol = ',1pe22.14 / cbug & ' ax,ay,az =',1p3e22.14 / cbug & ' bx,by,bz =',1p3e22.14 / cbug & ' anga,angb =',1p2e22.14 / cbug & ' iunit =',i3 ) cbug write (3, 9901) tol, ax, ay, az, bx, by, bz, cbug & anga, angb, iunit cbugc***DEBUG ends. c.... initialize. pi = 3.14159265358979324 nerr = 0 ux = -1.e99 uy = -1.e99 uz = -1.e99 c.... Find the unit vector parallel to vector "a". call aptvunb (ax, ay, az, 1, tol, uax, uay, uaz, dlena, nerra) if (dlena .eq. 0.0) then nerr = 1 go to 140 endif c.... Find the unit vector parallel to vector "b". call aptvunb (bx, by, bz, 1, tol, ubx, uby, ubz, dlenb, nerra) if (dlenb .eq. 0.0) then nerr = 2 go to 140 endif c.... Find the cosine and sine**2 of the angle between side "a" and side "b" c.... (vectors "a" and "b"). call aptvdot (uax, uay, uaz, ubx, uby, ubz, 1, tol, cosab, nerra) if (abs (cosab - 1.0) .le. tol) then nerr = 3 go to 140 endif sinab2 = 1.0 - cosab**2 c.... Find the unit vector "uab" perpendicular to vectors "a" and "b". call aptvxun (uax, uay, uaz, ubx, uby, ubz, 1, tol, & uabx, uaby, uabz, dab, nerra) c.... Find the cosines of the angles between vector "u" and vectors "a" and "b". if (iunit .eq. 0) then cosa = cos (anga * pi / 180.0) cosb = cos (angb * pi / 180.0) else cosa = cos (anga) cosb = cos (angb) endif c.... Find the unit vector "u" at angle anga from "a", angle angb from "b". c.... Assume unit vector u = fa * ua + fb * ub + fab * uab, c.... with unknowns fa, fb and fab. Then: c.... u dot ua = cosa = fa + fb * cosab c.... u dot ub = cosb = fa * cosab + fb c.... u dot u = 1 = fa**2 + fb**2 + fab**2 + 2.0 * fa * fb * cosab c.... Solving for fa, fb, fab, with truncation tests: fa = (cosa - cosb * cosab) / sinab2 erra = tol * (abs (cosa) + abs (cosb * cosab)) / sinab2 if (abs (fa) .le. erra) fa = 0.0 fb = (cosb - cosa * cosab) / sinab2 errb = tol * (abs (cosb) + abs (cosa * cosab)) / sinab2 if (abs (fb) .le. errb) fb = 0.0 arg = fa**2 + fb**2 + 2.0 * fa * fb * cosab if (abs (arg - 1.0) .le. tol) arg = 1.0 if (arg .gt. 1.0) then nerr = 4 go to 140 endif fab = sqrt (1.0 - arg) call aptvdot (fa, fb, fab, uax, ubx, uabx, 1, tol, ux, nerra) call aptvdot (fa, fb, fab, uay, uby, uaby, 1, tol, uy, nerra) call aptvdot (fa, fb, fab, uaz, ubz, uabz, 1, tol, uz, nerra) c.... Truncate small components to zero. call aptvuna (ux, uy, uz, 1, tol, dlenu, nerra) 140 continue cbugc***DEBUG begins. cbug 9902 format (/ 'aptetru results. nerr = ',i3 / cbug & ' ux,uy,uz =',1p3e22.14 ) cbug write ( 3, 9902) nerr, ux, uy, uz cbugc***DEBUG ends. 210 return c.... End of subroutine aptetru. (+1 line.) end UCRL-WEB-209832