subroutine aptdirt (ax, ay, az, npa, bx, by, bz, npb, tol, & ux, uy, uz, dab, ndir, nerr) ccbeg. cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc c c SUBROUTINE APTDIRT c c call aptdirt (ax, ay, az, npa, bx, by, bz, npb, tol, c & ux, uy, uz, dab, ndir, nerr) c c Version: aptdirt Updated 2003 June 10 12:00. c aptdirt Originated 2003 May 21 17:30. c c Authors: Arthur L. Edwards, LLNL, L-298, Telephone (925) 422-4123. c c c Purpose: To find all unique direction vectors from each point c a(na) = (ax(na), ay(na), az(na)), na = 1, npa, to each point c b(nb) = (bx(nb), by(nb), bz(nb)), nb = 1, npb, within precision c tol, and return them as unit direction vectors c v(nab) = (vx(nab), vy(nab), vz(nab)), with minimum distances c dab(nab), nab = 1, ndir, sorted in order of increasing distance. c Flag nerr indicates any input error. c c Input: ax, ay, az, npa, bx, by, bz, npb, tol c c Output: ux, uy, uz, dab, ndir, nerr c c Calls: aptdist, aptvaxb c c Glossary: c c ax,ay,az Input The x, y and z coordinates of each point c a(na) = (ax(na), ay(na), az(na)), na = 1, npa. c Size npa or greater. c If array b is sufficiently regular, all unique c directions in b may be found by using only one c or two points in b as array a. c c bx,by,bz Input The x, y and z coordinates of each point c b(nb) = (bx(nb), by(nb), bz(nb)), nb = 1, npb. c Size npb or greater, c c dab(nab) Output The minimum distance between pairs of points for each c unique direction vector u(nab), nab = 1, ndir. c Size npa * npb is sufficient, but see ndir. c c ndir Output The number of unique unit direction vectors u(nab), c n = 1, ndir, connecting pairs of points. c The maximum possible value of ndir is npa * npb. c c For a rectangular array of nx points in the c x direction and ny <= nx points in the y direction, c the maximum possible value of ndir is ndir(max) = c 2 * nx * ny - 2 * nx - 4 * ny + 8. c The minimum possible value is about F * ndir(max), c where F is given by the product of all the terms c (1 - 1/n**2), where n ranges over all of the prime c numbers from 2 to the largest possible common prime c factor of na and nb. c For very large nx and ny, F = 0.607927565940. c c nerr Output Indicates an input error, if not zero: c 1 if npa is less than 1. c 2 if npb is less than 1. c c npa Input The number of points a(na) = (ax(na), ay(na), az(na)). c c npb Input The number of points b(nb) = (bx(nb), by(nb), bz(nb)). c c tol Input Numerical precision limit. Used to determine if c points are coincident, or if components of vectors c are zero. c For 64-bit real numbers, recommend 1.e-5 to 1.e-11. c c ux,uy,uz Output The x, y and z components of each unique unit direction c vector u(nab) = (ux(nab), uy(nab), uz(nab), c nab = 1, ndir, connecting any point "a" to any point c "b". c The components ux, uy and ux are the cosines of the c angles between the direction vectors and the positive c x, y and z axes, respectively. The sign of each c vector is arbitrary chosen to make the last c non-zero component of ux, uy, uz positive. c Size npa * npb is sufficient, but see ndir. c cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc ccend. c.... Declarations for arguments. dimension ax(1) ! Coordinate x of point a. dimension ay(1) ! Coordinate y of point a. dimension az(1) ! Coordinate z of point a. dimension bx(1) ! Coordinate x of point b. dimension by(1) ! Coordinate y of point b. dimension bz(1) ! Coordinate z of point b. dimension ux(1) ! Component x of unit direction vector u. dimension uy(1) ! Component y of unit direction vector u. dimension uz(1) ! Component z of unit direction vector u. dimension dab(1) ! Minimum distance between points. cbugc***DEBUG begins. cbug 9901 format (/ 'aptdirt finding unique directions between points.', cbug & ' npa =',i8,', npb =',i8,'.') cbug 9902 format (/ ('n,ax,ay,az=',i6,1p3e20.12)) cbug 9912 format (/ ('n,bx,by,bz=',i6,1p3e20.12)) cbug write ( 3, 9901) npa, npb cbug write ( 3, 9902) (n, ax(n), ay(n), az(n), n = 1, npa) cbug write ( 3, 9912) (n, bx(n), by(n), bz(n), n = 1, npb) cbugc***DEBUG ends. c.... Initialize. ndir = 0 c.... Test for input errors. nerr = 0 if (npa .lt. 1) then nerr = 1 go to 210 endif if (npb .le. 1) then nerr = 2 go to 210 endif c.... Find the unique unit direction vectors between points. do 140 na = 1, npa ! Loop over the first point. do 130 nb = 1, npb ! Loop over the second point. c.... Find the unit direction vector and distance between the two points. call aptdist (0, 1, ax(na), ay(na), az(na), & bx(nb), by(nb), bz(nb), 1, tol, & abx, aby, abz, dabt, nerr) if (dabt .eq. 0.0) go to 130 ! Points are coincident. if (ndir .eq. 0) go to 120 do 110 nd = 1, ndir ! Loop over unique directions. c.... See if directions are the same (cross product zero). call aptvaxb (abx, aby, abz, ux(nd), uy(nd), uz(nd), 1, tol, & cx, cy, cz, vlen, nerr) if (vlen .eq. 0.0) then ! Directions are the same. c.... See if the new distance is shorter. if (dabt .lt. dab(nd)) then ! New distance is shorter. dab(nd) = dabt endif ! New distance is shorter. go to 130 endif ! Directions are the same. 110 continue ! End of loop over unique directions. c.... Found a new direction. 120 ndir = ndir + 1 ux(ndir) = abx uy(ndir) = aby uz(ndir) = abz dab(ndir) = dabt c.... Reverse direction if last non-zero component of ux, uy, uz is < 0. if ((uz(ndir) .lt. 0.0) .or. & ((uz(ndir) .eq. 0.0) .and. & (uy(ndir) .lt. 0.0)) .or. & ((uz(ndir) .eq. 0.0) .and. & (uy(ndir) .eq. 0.0) .and. & (ux(ndir) .lt. 0.0))) then ux(ndir) = -ux(ndir) uy(ndir) = -uy(ndir) uz(ndir) = -uz(ndir) endif 130 continue ! End of loop over the first point. 140 continue ! End of loop over the second point. c.... Reorder in order of increasing minimum distance between points, c.... or if that distance is the same, in order of increasing angle from the c.... positive z direction, or if that angle is zero, in order of increasing c.... angle from the positive y direction. do 160 ns1 = 1, ndir - 1 ! Loop over directions. do 150 ns2 = ns1 + 1, ndir ! Loop over rest of directions. if ( (dab(ns2) .lt. dab(ns1)) .or. & ((dab(ns2) .eq. dab(ns1)) .and. & ((uz(ns2) .gt. uz(ns1) ) .or. & ((uz(ns2) .eq. uz(ns1) ) .and. & (uy(ns2) .gt. uy(ns1) ))))) then uxsave = ux(ns1) uysave = uy(ns1) uzsave = uz(ns1) dabsave = dab(ns1) ux(ns1) = ux(ns2) uy(ns1) = uy(ns2) uz(ns1) = uz(ns2) dab(ns1) = dab(ns2) ux(ns2) = uxsave uy(ns2) = uysave uz(ns2) = uzsave dab(ns2) = dabsave endif 150 continue ! End of loop over directions. 160 continue ! End of loop over rest of directions. 210 continue cbugc***DEBUG begins. cbug 9903 format (/ 'aptdirt results: ndir=',i6, cbug & ', nerr=',i2,'.' / ) cbug 9904 format ('n,ux,y,z,dab=',i6,1p4e15.7) cbug write ( 3, 9903) ndir, nerr cbug if (ndir .gt. 0) then cbug write ( 3, 9904) (n, ux(n), uy(n), uz(n), dab(n), n = 1, ndir) cbug endif cbugc***DEBUG ends. return c.... End of subroutine aptdirt. (+1 line.) end UCRL-WEB-209832