Sie sind auf Seite 1von 36

Gravity gradient tensor of a nite line of mass of arbitrary orientation

Mark Gettings U.S. Geological Survey, 520 N. Park Ave. Rm 355 Tucson, AZ 85719, USA. (mgetting@usgs.gov)

Abstract

Analytical expressions for the gravitational attraction and gravity gradient tensor are given for a model consisting of a nite length line of mass of arbitrary orientation. The expressions are valid for all points outside the line of mass. Expressions for the tensor magnitude and three standard invariants of a 3x3 tensor are also given. Fortran code to evaluate the gravitational attraction, the gravity gradient tensor, tensor magnitude, tensor invarients, and tensor eigenvalues and eigenvectors for an xyz grid of eld points is listed in an appendix. For the example presented, the tensor magnitude and second tensor invariant are essentially mirror images of each other, and the third tensor invariant is useful for dening the location of the line of mass. The model is useful for studying the gravitational eects of approximately linear mass concentrations, tunnels, and o-axis gravitational eects of cylinders.

Introduction

There is a continuing interest in gravity gradiometry from several areas of interest, especially mineral exploration geophysics and tunnel detection. Continuing eorts in airborne gravity gradiometry in mineral exploration has led to steady improvements in instrumentation [Lee , 2001; Dranseld et al., 2001; Hinks et al., 2004; DiFrancesco et al., 2008] and analysis techniques [Mickus and Hinojosa , 2001; Li , 2001; Heath et al., 2005; Saad , 2006; Murphy , 2007]. Interest in tunnel and underground void detection [Romaides et al., 2001; Maier , 2002] is increasing due to the renewed eorts at border security. Previous model studies have focused on a point source [Maier , 2002], a horizontal line of mass of xed or innite length [Romaides et al., 2001], or using voxels computed from the gravitational eects of right rectangular prisms [Montana et al., 1992]. The voxel model is very exible but requires computation of very large numbers of voxels for realistic models [Heath et al., 2005]. For some modeling problems, it would be convenient to have an analytic model of a line of mass of arbitrary 1

orientation in order to model eects such as a dipping shaft, the o-axis gravity eld of a cylinder, or any approximately linear density contrast. In this report, a model for the gravitational attraction and gravity gradient tensor of a nite length line of mass of arbitrary orientation is presented along with computer code for routine calculation. Expressions for some invariant quantities of the gradient tensor (quantities that are constant regardless of the coordinate system) are also given in order to develop exploration schemes independent of the orientation of the target body. As shown by both Romaides et al. [2001] and Maier [2002], the eects for typical underground tunnels or structures is quite small and either very low level airborne or ground based measurements are required for detection. Moreover, geologic noise due to local geologic variations are of the same order or larger in amplitude [Heath et al., 2005; Dranseld et al., 2001; Murphy , 2007]. If a grid of observations is available, a pattern recognition algorithm would be the most reliable form of detection. In the case of prole only data, detection is more dicult, and is the subject of ongoing research.

The potential

The line of mass is taken along the x-axis extending from L to L in a right handed coordinate system (Fig. 1). The body vector r0 is (, 0, 0) (along the x-axis) and the position vector for the observation point in the line of mass system is r = (x, y, z ). The line of mass has density/unit length of and G is the universal constant of gravitation. The gravitational potential is then [Grant and West , 1965] U ( r)= and thus L x + (L x)2 + y 2 + z 2 r) U ( ] = ln[ G L x + (L + x)2 + y 2 + z 2 (2)
L L

Gd (x )2 + y 2 + z 2

(1)

Gravity vector

The gravity vector components were calculated both manually and using the dierentiation and simplication features of Mathematica 5.1 [Wolfram Research , 2004] in order to insure there were no errors. 1 U ( r) = G x 1 (L x)2 + y2 + z2 1 (L + x)2 + y2 + z 2

(3)

Figure 1: Geometry of the nite line of mass in the body-centered system

r) y 1 U ( (x( = 2 G y y + z2 L(

(L

)+ + + (L + + y2 + z 2 1 1 + )) 2 2 2 2 (L x) + y + z (L + x) + y 2 + z 2 (4) x)2 y2 z2 x)2 1 1 (L + x)2 + y 2 + z 2 1

1 U ( r) z = 2 (x( G z y + z2 L(

(L x)2 + y 2 + z 2 1

+ +

)+

(L x)2 + y 2 + z 2

)) (L + x)2 + y 2 + z 2 (5)

Gravity gradient tensor components

The algebra involved in calculating the tensor components is tedious though straightforward; one component was calculated both manually and using Mathematica 5.1. The remaining components were calculated with Mathematica 5.1 and some nal simplication and factoring was done manually. r) y 1 2 U ( y = G xy ((L x)2 + y 2 + z 2 )3/2 ((L + x)2 + y 2 + z 2 )3/2 3

(6)

r) z 1 2 U ( z = G xz ((L x)2 + y 2 + z 2 )3/2 ((L + x)2 + y 2 + z 2 )3/2 r) (L x)(y 2 + z 2 ) 1 1 2 U ( ( yz ( = 2 + G yz (y + z 2 )2 ((L x)2 + y 2 + z 2 )3/2 (L + x)(y 2 + z 2 ) + ((L + x)2 + y 2 + z 2 )3/2

(7)

2(L x) + (L x)2 + y 2 + z 2 2(L + x) (L + x)2 + y 2 + z 2 (8) ))

1 2 U ( r) (L x) (L + x) = 2 G x ((L x)2 + y 2 + z 2 )3/2 ((L + x)2 + y 2 + z 2 )3/2 r) 1 (L x)y 2 (y 2 + z 2 ) 1 2 U ( = 2 ( + 2 2 2 G y (y + z ) ((L x)2 + y 2 + z 2 )3/2 y 2 (y 2 + z 2 )(L + x) + ((L + x)2 + y 2 + z 2 )3/2 (y 2 z 2 )(L x)

(9)

(L x)2 + y 2 + z 2 (L + x)(y 2 z 2 )

) (L + x)2 + y 2 + z 2 (10)

r) 1 z 2 (y 2 + z 2 )(L x) 1 2 U ( = ( G z 2 (y 2 + z 2 )2 ((L x)2 + y 2 + z 2 )3/2 z 2 (y 2 + z 2 )(L + x) + ((L + x)2 + y 2 + z 2 )3/2

(L x)(z 2 y 2 ) (L x)2 + y 2 + z 2 (L + x)(z 2 y 2 )

) (L + x)2 + y 2 + z 2 (11)

Coordinate transformations

The above expressions were derived in the body-centered system with the line of mass centered along the x-axis (Fig. 1). To use the formulae in general, we need to dene the coordinate transformation between the eld or Earth system and the body-centered system (Fig. 2). Right-handed coordinate systems were assumed for this study. A north-east-down (positive x, y , and z directions) was used for the eld system, and the line of mass lies along the x axis centered at the (x , y , z ) body-centered system origin, as above. We have that ) x = A( x x 0 (12)

is the position where x is the position vector of P (x, y, z ) in the eld system, x 0 vector in the eld system of the origin of the (x , y , z ) system (center of the 4

line of mass), and x is the position vector of the point P in the body-centered system. The angle is the angle between the +x direction and the projection of the +x axis on the xy plane, measured counterclockwise from north (x axis). The angle is the dip of the +x axis relative to the xy plane measured positive counterclockwise in the x z plane (Fig. 2). Thus a horizontal line of mass would have a of zero and a strike of , and a vertical line of mass would have a of 90 . In the vertical case, is not dened and taken as zero. The rotation matrix A thus dened is independent of the observation point and is unchanged for all observations of a given source. It is given by cos cos cos sin sin cos 0 A = sin (13) sin cos sin sin cos and the inverse transformation matrix A1 is given by the transpose A1 = At (14)

The calculation therefore proceeds with the following steps for each observation (eld) point: 1. Transform the eld point coordinates P (x, y, z ) to the body-centered sys ) tem (x , y , z ) with x = A( x x 0 2. Calculate the three gravitation vector components g (equations 3-5 above) and the six gradient tensor components (equations 6-11 above) and form the gradient tensor g . 3. Transform back to the eld system using [Butkov , 1968; Spiegel , 1959] g = At g and g = At g A to obtain the desired gravity vector and gravity gradient tensor. These formulae are exact outside the body for any geometry symmetric about the x axis, for example a circular tunnel or rod, with the density per unit length appropriately calculated (R2 for a circular cross section of density and radius R, etc.) Example applications are a dipping tunnel and o-axis gravity eects of a buried vertical cylinder or shaft. The gravity gradient tensor components all depend on the coordinate system and the orientation of the line of mass relative to it. It is thus useful to calculate quantities that are invariant with regard to the coordinate system for some studies. The quantities that are typically calculated include the tensor magnitude, the three tensor invariants, and the eigenvalues and associated eigenvectors of the tensor. The tensor magnitude for a tensor Tij is given by the square root of half the tensor double dot product [Dutton , 2002; Anonymous , 2001] | Tij |= 1 2 5
2 Tij i j

(15)

Figure 2: Geometry of the eld (right-handed (x,y,z); e.g. north-east-down) and body-centered coordinate systems (x,y,z). P(x,y,z) is the observation point, and the blue line shows the nite line of mass. The orientation of the line of mass is specied by a strike and a dip in the eldpoint system. The symbol x means parallel to the x-axis.

The three standard invariants for a 3 3 tensor are [Wikipedia , 2008; Zhukov et al., undated] Ig = gxx + gyy + gzz (16)
2 2 2 IIg = gxx gyy + gyy gzz + gzz gxx gxy gyz gxz

(17) (18)

and IIIg = det (g ) Ig is identically zero for a gravitational eld in free space by virtue of Laplaces equation. In addition, it is useful to compute the eigenvalues and eigenvectors which can be used for principal components analysis, trends analysis and other schemes in modeling. A computer code was written to compute the quantities dened above and is given in the appendix. Eignvalues and eigenvectors were computed using the open-source subroutine library described by Kopp [2008].

Example of a dipping line of mass

As an example, the vertical gravity component and gradient tensor magnitude and invariants for a line of mass 30m long striking 60 east of north and dipping 30 to the northeast are shown in gures 3-6. The model was computed at the nodes of a 5 m grid extending 100m north-south and 150 m east west with measurements made at an altitude of 1m above the ground. The center of the line of mass is at 50 m north and 75 m east, at a depth of 7.5 m. The southwest end of the line of mass just reaches the surface. For this model, the linear density was 6283 kg/m corresponding to a 1m radius line with a density of 2000 kg/m3 . Examination of Fig. 4 and Fig. 5 shows that the tensor magnitude and second tensor invariant are essentially mirror images of each other; the tensor magnitude extends over the map to larger distances from the source line than the second tensor invariant resulting in a slightly larger map area of the tensor magnitude. The third tensor invariant (Fig.6) contains negative lobes o the ends of the mass line that might be helpful in estimating the location of the ends of the mass line, particularly the shallow end. This invariant is also more local in its positive signature near the mass line than the other two measures (Figs. 4 and 5), with steeper gradients and a more restricted map area about the source. This sharper anomaly shape of the third tensor invariant could make it more useful in identifying the mass line location in a noisy environment. Murphy [2007] has shown the utility of two invarients of the horizontal components of the gradient tensor in mineral and hydrocarbon exploration using airborne gravity gradiometer data.

Figure 3: Gravity eect (z-component of the gravity vector) of a nite line of mass striking 60 east of north and dipping 30 to NE. Bold black line is the projection of the line of mass on the surface. Line of mass is at the surface on the southeast end and the observation plane is 1m above the surface. Contour interval is 0.0002 mgal.

Figure 4: Tensor magnitude (equation 15) of a nite line of mass striking 60 east of north and dipping 30 to NE. Bold black line is the projection of the line of mass on the surface. Line of mass is at the surface on the southeast end and the observation plane is 1m above the surface. Contour inerval is 20 Eotvos units

Figure 5: The second tensor invariant (equation 17) of a nite line of mass striking 60 east of north and dipping 30 to NE. Bold black line is the projection of the line of mass on the surface. Line of mass is at the surface on the southeast end and the observation plane is 1m above the surface. Contour interval is 20,000 Eotvos2.

10

Figure 6: Third tensor invariant (equation 18) of a nite line of mass striking 60 east of north and dipping 30 to NE. Bold black line is the projection of the line of mass on the surface. Line of mass is at the surface on the southeast end and the observation plane is 1m above the surface. Contour interval is 100,000 Eotvos3.

11

Acknowledgments

The author thanks Je Phillips and Je Wynn of the U.S. Geological Survey for helpful reviews of the manuscript. Publication of this report was approved by the Director, U.S. Geological Survey.

References
Anonymous, Vector and tensor mathematics, [Online www.polymerprocessing.com/notes/root92a.pdf; accessed 6-November2008], 2001. Butkov, E., Mathematical Physics, Addison Wesley Publishing Co., 735 p., 1968. DiFrancesco, D., D. Kaputa, and T. Meyer, Gravity gradiometer systems; advances and challenges, Preview, 133, 3036, 39, 2008. Dranseld, M. H., A. N. Christensen, M. Rose, P. M. Stone, and P. Diorio, FALCON test results from the Bathurst Mining camp, Exploration Geophysics, 32 (3-4), 243246, 2001. Dutton, J. A., The Ceaseless Wind: An Introduction to the Theory of Atmospheric Motion, Courier Dover Publications, 2002. Grant, F. S., and G. F. West, Interpretation Theory in Applied Geophysics, McGraw-Hill Book Company, 583 pp., 1965. Heath, P. J., S. Greenhalgh, and N. G. Direen, Modelling gravity and magnetic gradient tensor responses for exploration within the regolith, Exploration Geophysics, 36 (4), 357364, 2005. Hinks, D., S. McIntosh, and R. Lane, A comparison of the FALCON and Air-FTG airborne gravity gradiometer systems at the kokong test block, botswana, in Airborne gravity 2004- Abstracts from the ASEG-PESA airborne gravity 2004 workshop, edited by R. Lane, pp. 125134, Geoscience Australia Record 2004/18, 2004. Kopp, J., Ecient numerical diagonalization of hermitian 3x3 matrices, International Journal of Modern Physics C, 19, 523548, 2008. Lee, J. B., FALCON gravity gradiometer technology, Exploration Geophysics, 32 (3-4), 247250, 2001. Li, X., Vertical resolution; gravity versus vertical gravity gradient, The Leading Edge, 20 (8), 901904, 2001. Maier, M. W., Underground structures and gravity gradiometry, Tech. Rep. ADA400252, AEROSPACE CORP EL SEGUNDO CA RECONNAISSANCE SYSTEMS DIV, 2002. 12

Mickus, K. L., and J. H. Hinojosa, The complete gravity gradient tensor derived from the vertical component of gravity; a fourier transform technique, Journal of Applied Geophysics, 46 (3), 159174, 2001. Montana, C. J., K. L. Mickus, and W. J. Peeples, Program to calculate the gravitational eld and gravity gradient tensor resulting from a system of right rectangular prisms, Computers and Geosciences, 18 (5), 587602, 1992. Murphy, C. A., Interpreting FTG gravity data using horizontal tensor components, EGM 2007 International Workshop - Innovation in EM, Grav and Mag Methods: a new perspective for exploration, Capri, Italy, April 2007, 2007. Romaides, A. J., J. C. Battis, R. W. Sands, A. Zorn, D. O. B. Jr., and D. J. DiFrancesco, A comparison of gravimetric techniques for measuring subsurface void signals, J. Phys. D: Appl. Phys., 34, 433443, 2001. Saad, A. H., Understanding gravity gradients; a tutorial, The Leading Edge, 25 (8), 942949, 2006. Spiegel, M. R., Vector Analysis and an Introduction to Tensor Analysis, Schaums Outline Series, McGraw-Hill Book Co., 225 p., 1959. Wikipedia, Invariants of tensors wikipedia, the free encyclopedia, [Online; accessed 20-November-2008], 2008. Wolfram Research, Mathematica, version 5.1 ed., Wolfram Research, Inc., Champaign, Illinois, 2004. Zhukov, L., K. Museth, D. Breen, R. Whitaker, and A. H. Barr, Tensor invariants for modeling and segmentation of diusion weighted MRI data, department of Computer Science,California Institute of Technology, undated.

Appendix - Fortran computer code


c Main program module and all associated subroutines c Calculate gravity vector and gravity gradient tensor c for a finite line of mass of arbitrary orientation c MEG/Sep08; Nov 08 add invariants and eigen vals/vecs; c and output file single ascii lines c Although this code has been tested and verified, it is not c guaranteed to perform correctly in all cases, and may contain c bugs that have not been identified c real*4 a(9),ai(9),x(3),xp(3),x0(3),theta,phi,hl,lamda real*4 strike, dip, xin(3), g(3), gp(3), gmn(9), gmnp(9) real*4 Gcons, tmag, tinvar(3), teval(3), tevec(3,3) real*4 unitsg, unitst 13

character qu*80,qr*1,dflt1*1,fnam1*80,df80*80,fmt*80,fnam2*80 character(8) date character(10) time logical verify ittin=5 ittout=6 io1 = 10 io2 = 11 verify=.false. Gcons = 6.674e-11 call date_and_time(DATE=date,TIME=time) c c get line of mass parameters, filenames, set up transform matrices c write(ittout,200) 200 format(Enter line of mass parameters, units m, degrees,, 1 kg/m**3) qu=Enter x0: call ttinr4(qu,x0(1),-999.,ittin,ittout,verify) if(x(1).le.-999.) go to 900 qu=Enter y0: call ttinr4(qu,x0(2),-999.,ittin,ittout,verify) qu=Enter z0: call ttinr4(qu,x0(3),-999.,ittin,ittout,verify) qu=Enter strike(deg CL off N, 0-360)[0]: call ttinr4(qu,strike,0.,ittin,ittout,verify) theta = 360. - strike qu=Enter dip(deg, + down, -90 to 90)[0]: call ttinr4(qu,dip,0.,ittin,ittout,verify) phi = -dip call matfrm(1,theta,phi,a) call mattra(a,ai,3,3) qu=Enter half length of line of mass(m)[10]: call ttinr4(qu,hl,10.,ittin,ittout,verify) qu=Enter lamda (density/unit length kg/m)[1000]: call ttinr4(qu,lamda,1000.,ittin,ittout,verify) qu=Enter 1 for mks, 2 for mgal,eotvos, 3 for gu,SI units[1]: call ttini4(qu,iunit, 1, ittin, ittout, verify) if(iunit.eq.1) then unitsg=1.0 unitst=1.0 elseif(iunit.eq.2) then unitsg=1.0e5 unitst=1.0e9 elseif(iunit.eq.3) then unitsg=1.0e6 14

unitst=1.0e9 endif qu=Filename of field point coordinates (<81c)[fieldpoint.dat] df80 = fieldpoint.dat call ttinaa(qu,fnam1,80,df80,ittin,ittout,verify) open(unit=io1,file=fnam1, status=old) qu=Format of field point coordinates (<81c)[(3f10.0)]: df80 = (3F10.0) call ttinaa(qu,fmt,80,df80,ittin,ittout,verify) qu=Filename of output file (<81c)[linemass.out] df80 = linemass.out call ttinaa(qu,fnam2,80,df80,ittin,ittout,verify) open(unit=io2,file=fnam2, status=unknown) c c write parameters c write(ittout,202) date,time,x0, strike, dip, hl, lamda 202 format(ID:,a,;,a,x0: ,3f10.3, strike, dip,deg:,2f10.1/ 1 half length, lamda:, 2f10.1) write(ittout,204) fnam1,fmt,fnam2 204 format(Datapoint file:,a/Format:,a/Outfile:,a) write(ittout,217) 217 format(Rotation matrix and inverse by column) do 38 i=1,9 38 write(ittout,218) a(i), ai(i) 218 format(2e11.3) c c loop over each fieldpoint first, header record with ID c date;time c write(io2, 209)date,time 209 format(a,;,a, 1 x,y,z,gx,gy,gz,gxx,gyy,gzz,gxy,gxz,gyz,tmag,tinv1,, 2 tinv2,tinv3,evl1,evl2,evl3,evc1x,y,z,evc2x,y,z,evc3x,y,z) 500 read(io1,fmt, end=900) xin(1),xin(2),xin(3) c c transform to body system c do 50 i=1,3 50 x(i) = xin(i)-x0(i) call matmul(a,x,xp,3,3,1) c c calculate gravity vector and gradient tensor c call flinmass(xp,hl,gp,gmnp) c write(io2,220)(xp(i),gp(i),(gmnp((i-1)*3+j),j=1,3),i=1,3) 15

220 format(body system:,0pf10.1,1p4e11.3) c c transform g back to fieldpoint system c call matmul(ai,gp,g,3,3,1) c c gradient tensor transform to fieldpoint system c use loop 52 to mult g by G*lamda c c write(io2,222) (g(k),k=1,3) 222 format(>>>,1p3e11.3) do 52 jc=1,3 g(jc) = g(jc)*Gcons*lamda*unitsg 52 continue call matmul(ai,gmnp,gmn,3,3,3) call matmul(gmn,a,gmnp,3,3,3) do 58 jr=1,9 gmn(jr) = gmnp(jr)*Gcons*lamda*unitst 58 continue c c calculate tensor invariants, eigenvalues and eigenvectors c call tinvar3x3(gmn, tmag, tinvar, teval, tevec) c c output to io2 c write(io2, 210) xin,g,gmn(1),gmn(5),gmn(9),gmn(4),gmn(7), 1 gmn(8),tmag,tinvar,teval,((tevec(i,j),i=1,3),j=1,3) 210 format(1p28e11.3) go to 500 900 close(io1) close(io2) stop end subroutine flinmass(xc,hl,gp,gmnp) c c Finite line of mass from -L to +L on x axis c Calculate gravity vector and gradient tensor in body system c vector xc contains (x,y,z) of field pointin body system c on return g contains (gx,gy,gz) components of gravitation c array gmn contains gradient tensor gmn(i), stored by column, c so gmn(1)=gxx, gmn(3)=gzx, gmn(4)=gxy,gmn(7)=gxz, gmn(9)=gzz c Units of G*lamda (gravconst, density/unit length) c MEG/Aug2008 c c Although this code has been tested and verified, it is not 16

c guaranteed to perform correctly in all cases, and may contain c bugs that have not been identified c real*4 xc(3),L,g(3),gmn(9),hl,gp(3),gmnp(9) real*4 x,y,z,lmx,lpx L=hl x=xc(1) y=xc(2) z=xc(3) lmx=sqrt((L-x)**2+y**2+z**2) lpx=sqrt((L+x)**2+y**2+z**2) c gravity vector g(1) = 1/lpx-1/lmx g(2) = (x*(1/lpx-1/lmx)+L*(1/lmx+1/lpx))*(-y)/(y*y+z*z) g(3) = (x*(1/lpx-1/lmx)+L*(1/lmx+1/lpx))*(-z)/(y*y+z*z) c gravity gradient tensor gmn(4) = y/lmx**3-y/lpx**3 gmn(7) = z/lmx**3-z/lpx**3 gmn(8) = L*(y*y+z*z)/lmx**3-x*(y*y+z*z)/lmx**3+2*L/lmx1 2*x/lmx+L*(y*y+z*z)/lpx**3+x*(y*y+z*z)/lpx**3+2*L/lpx+2*x/lpx gmn(8) = gmn(8)*y*z/(y*y+z*z) c diagonal components gxx, gyy, gzz gmn(1) = (x-L)/lmx**3-(L+x)/lpx**3 gmn(5) = (L-x)*y*y*(y*y+z*z)/lmx**3+((L-x)*y*y-(L-x)*z*z)/lmx 1 +(L+x)*y*y*(y*y+z*z)/lpx**3+((L+x)*y*y-(L+x)*z*z)/lpx gmn(5) = gmn(5)/(y*y+z*z)**2 gmn(9) = (L-x)*z*z*(y*y+z*z)/lmx**3-((L-x)*y*y-(L-x)*z*z)/lmx 1 +(L+x)*z*z*(y*y+z*z)/lpx**3-((L+x)*y*y-(L+x)*z*z)/lpx gmn(9) = gmn(9)/(y*y+z*z)**2 gmn(2) = gmn(4) gmn(3) = gmn(7) gmn(6) = gmn(8) c write(6,200) g c write(6,200) gmn 200 format(*,1p3e11.3) do 50 i=1,3 50 gp(i)=g(i) do 52 i=1,9 52 gmnp(i) = gmn(i) return end subroutine tinvar3x3(gmn, tmag, tinvar, teval, tevec) c c calculate for a 3x3 cartesian tensor gmn: tensor magnitude tmag c the 3 invariants tinvar, the eigenvalues teval, and the eigen 17

c vectors tevec, store xyz by column - 1st vector is tevec(1,1) c tevec(2,1),tevec(3,1), 2nd in col 2, 3rd in col3 c uses Kopps routines for eigensolution c arXiv:physics/0610206v3 [physics,comp-ph] 4 Jul 2008 c Efficient numerical diagonalization of hermitian 3 x 3 matrices c Gettings Nov 2008 c c Although this code has been tested and verified, it is not c guaranteed to perform correctly in all cases, and may contain c bugs that have not been identified c real*4 gmn(9), tmag, tinvar(3), teval(3), tevec(3,3) real*8 sum, g(3,3), eval(3), evec(3,3) c c store tensor in 2D array, calculate tensor magnitude and invariants c sum = 0.0 do 50 j=1,3 do 50 i=1,3 k = (j-1)*3+i g(i,j) = gmn(k) sum = sum + gmn(k)*gmn(k) 50 continue tmag = dsqrt(sum * 0.5) tinvar(1) = g(1,1) + g(2,2) + g(3,3) tinvar(2) = g(1,1)*g(2,2) + g(2,2)*g(3,3) + g(1,1)*g(3,3) 1 g(1,2)*g(1,2) - g(2,3)*g(2,3) - g(1,3)*g(1,3) tinvar(3) = gmn(1)*gmn(5)*gmn(9) + gmn(4)*gmn(8)*gmn(3) + 1 gmn(7)*gmn(2)*gmn(6) - gmn(3)*gmn(5)*gmn(7) 2 gmn(6)*gmn(8)*gmn(1) - gmn(9)*gmn(2)*gmn(4) c c calculate eigenvalues and eigenvectors c call dsyevh3(g,evec,eval) do 60 i=1,3 teval(i) = eval(i) do 60 j=1,3 tevec(i,j) = evec(i,j) 60 continue return end function cosin(theta) c ** computes cosine of any angle(in degrees) between 0 and 360. c Although this code has been tested and verified, it is not c guaranteed to perform correctly in all cases, and may contain c bugs that have not been identified 18

c tol=1.0e-8 pi=acos(-1.0) dgr=pi/180.0 if(abs(theta-90.0).le.tol.or.abs(theta-270.).le.tol) go to 50 if(theta.lt.0)theta=360.0+theta thetar=theta*dgr itheta=theta/90.0+1. go to (10,20,30,40),itheta 10 cosin=cos(thetar) return 20 thetar=pi-thetar cosin=-cos(thetar) return 30 thetar=thetar-pi cosin=-cos(thetar) return 40 thetar=2*pi-thetar cosin=cos(thetar) return 50 cosin=0.0 return end function sine(theta) ** computes sine of any angle(in degrees) between 0 and 360. Although this code has been tested and verified, it is not guaranteed to perform correctly in all cases, and may contain bugs that have not been identified tol=1.0e-8 pi=acos(-1.0) dgr=pi/180.0 if(abs(theta).le.tol.or.abs(theta-180.0).le.tol) go to 50 if(abs(theta-360.0).le.tol) go to 50 if(theta.lt.0)theta=360.0+theta thetar=theta*dgr itheta=theta/90.+1 go to (10,20,30,40),itheta 10 sine=sin(thetar) return 20 thetar=pi-thetar sine=sin(thetar) return 30 thetar=thetar-pi sine=-sin(thetar) return 19

c c c c c

40 thetar=2*pi-thetar sine=-sin(thetar) return 50 sine=0.0 return end subroutine matfrm(k,theta,phi,a) c**subroutine to set up rotation transformation matrices, using c**right-handed systems;k=0 for 2-dimension,k=1 for 3-dimensions. c**matrix stored by column (col1,col2, etc.) c Although this code has been tested and verified, it is not c guaranteed to perform correctly in all cases, and may contain c bugs that have not been identified c dimension a(*) cst=cosin(theta) snt=sine(theta) if(k.eq.1)go to 10 a(1)=cst a(2)=snt a(3)=0.0 a(4)=-snt a(5)=cst a(6)=0.0 a(7)=0.0 a(8)=0.0 a(9)=1.0 go to 20 10 csp=cosin(phi) snp=sine(phi) a(1)=csp*cst a(2)= snt a(3)= cst*snp a(4)=-csp*snt a(5)= cst a(6)=-snt*snp a(7)=-snp a(8)=0.0 a(9)= csp 20 return end subroutine mattra(a,r,n,m) c Although this code has been tested and verified, it is not c guaranteed to perform correctly in all cases, and may contain c bugs that have not been identified c 20

c c c c c

dimension a(*),r(*) ir=0 do 10 i=1,n ij=i-n do 10 j=1,m ij=ij+n ir=ir+1 10 r(ir)=a(ij) return end subroutine matmul(a,b,r,n,m,l) matrices are stored with column varying fastest (column 1, col2 next, etc) Although this code has been tested and verified, it is not guaranteed to perform correctly in all cases, and may contain bugs that have not been identified dimension a(*),b(*),r(*) ir=0 ik=-m do 10 k=1,l ik=ik+m do 11 j=1,n ir=ir+1 ji=j-n ib=ik r(ir)=0.0 do 12 i=1,m ji=ji+n ib=ib+1 r(ir)=r(ir)+a(ji)*b(ib) continue continue continue return end subroutine ttinr4(qu, r4, defalt, itin,itout, verify) Terminal entry of real*4 variable - F77 version qu - Character string prompt que,80 C long. r4 - variable to be input defalt - default value if <cr> only given itin,itout - read, write LUNs of terminal verify - if true, asks for verification of input if false no verification typical call: call ttinr4(que,a,1.67,itin,itout,verify) MEG/ Feb 86; SUN conversion Jul 89/ MEG 21

12 11 10

c c c c c c c c c c

c c Although this code has been tested and verified, it is not c guaranteed to perform correctly in all cases, and may contain c bugs that have not been identified c logical verify character ans*10, blank*10, qu*80 character que(80)*1, qr*1 real r4, defalt blank = read(unit=qu, fmt=200) que 200 format(80a1) call lnnobl(que, nq, 80) 300 write(unit=itout, fmt=204) 204 format(1h ,$) do 40 i = 1, nq 40 write(unit=itout, fmt=201) que(i) 201 format(a,$) read(unit=itin, fmt=101, err=300) ans 101 format(a) if (ans .eq. blank) goto 910 read(unit=ans, fmt=100) r4 100 format(bn,f10.0) if (.not. verify) goto 900 write(unit=itout, fmt=202) r4 202 format(1x,6hValue ,1pe14.7,5h ok? ,$) read(unit=itin, fmt=101) qr if ((qr .eq. n) .or. (qr .eq. N)) goto 300 900 return 910 r4 = defalt goto 900 end subroutine lnnobl(a, na, lngth) c determine length of string of max length lngth with no blanks on left c changed to specify string max length from 80 by MEG/10Jan91 c Although this code has been tested and verified, it is not c guaranteed to perform correctly in all cases, and may contain c bugs that have not been identified c character a(lngth), bl bl = do 50 i = lngth, 1, -1 na = i if (a(i) .ne. bl) goto 60 50 continue na = 0 22

c c c c c c c c c c c c Although this code has been tested and verified, it is not c guaranteed to perform correctly in all cases, and may contain c bugs that have not been identified c logical verify character ans*16, blank*16, qu*80 character que(80)*1, qr*1 double precision r8, defalt blank = read(unit=qu, fmt=200) que 200 format(80a1) call lnnobl(que, nq, 80) 300 write(unit=itout, fmt=204) 204 format(1h ,$) do 40 i = 1, nq 40 write(unit=itout, fmt=201) que(i) 201 format(a,$) read(unit=itin, fmt=101, err=300) ans 101 format(a) if (ans .eq. blank) goto 910 read(unit=ans, fmt=100) r8 100 format(bn,f16.0) if (.not. verify) goto 900 write(unit=itout, fmt=202) r8 202 format(1x,6hValue ,1pd24.17,5h ok? ,$) read(unit=itin, fmt=101) qr if ((qr .eq. n) .or. (qr .eq. N)) goto 300 900 return 910 r8 = defalt goto 900 end subroutine ttini4(qu, i4, defalt, itin,itout, verify) 23

60 return end subroutine ttinr8(qu, r8, defalt, itin,itout, verify) Terminal entry of real*8 variable - F77 version qu - Character string prompt que,80 C long. r8 - variable to be input def - default value if <cr> only given itin,itout - read, write LUNs of terminal verify - if true, asks for verification of input if false no verification typical call: call ttinr8(que,a,1.67d-03,itin,itout,verify) MEG/ Feb 86; SUN conversion Jul 89/ MEG

c Terminal entry of integer*4 variable - F77 version c qu - Character string prompt que,80 C long. c i4 - variable to be input c defalt - default value if <cr> only given c itin,itout - read, write LUNs of terminal c verify - if true, asks for verification of input c if false no verification c typical call: c call ttini4(que,k,16,itin,itout,verify) c MEG/ Feb 86; SUN conversion Jul 89/ MEG c c Although this code has been tested and verified, it is not c guaranteed to perform correctly in all cases, and may contain c bugs that have not been identified c logical verify character ans*16, blank*16, qu*80 character que(80)*1, qr*1 integer*4 i4, defalt blank = read(unit=qu, fmt=200) que 200 format(80a1) call lnnobl(que, nq, 80) 300 write(unit=itout, fmt=204) 204 format(1h ,$) do 40 i = 1, nq 40 write(unit=itout, fmt=201) que(i) 201 format(a,$) read(unit=itin, fmt=101, err=300) ans 101 format(a) if (ans .eq. blank) goto 910 read(unit=ans, fmt=100) i4 100 format(bn,i16) if (.not. verify) goto 900 write(unit=itout, fmt=202) i4 202 format(1x,6hValue ,i16,5h ok? ,$) read(unit=itin, fmt=101) qr if ((qr .eq. n) .or. (qr .eq. N)) goto 300 900 return 910 i4 = defalt goto 900 end subroutine ttini2(qu, i2, defalt, itin,itout, verify) c Terminal entry of integer*2 variable - F77 version c qu - Character string prompt que,80 C long. c i2 - variable to be input 24

c defalt - default value if <cr> only given c itin,itout - read, write LUNs of terminal c verify - if true, asks for verification of input c if false no verification c typical call: c call ttini2(que,k,16,itin,itout,verify) c MEG/ Feb 86; SUN conversion Jul 89/ MEG c c Although this code has been tested and verified, it is not c guaranteed to perform correctly in all cases, and may contain c bugs that have not been identified c logical verify character ans*6, blank*6, qu*80 character que(80)*1, qr*1 integer*2 i2, defalt blank = read(unit=qu, fmt=200) que 200 format(80a1) call lnnobl(que, nq, 80) 300 write(unit=itout, fmt=204) 204 format(1h ,$) do 40 i = 1, nq 40 write(unit=itout, fmt=201) que(i) 201 format(a,$) read(unit=itin, fmt=101, err=300) ans 101 format(a) if (ans .eq. blank) goto 910 read(unit=ans, fmt=100) i2 100 format(bn,i6) if (.not. verify) goto 900 write(unit=itout, fmt=202) i2 202 format(1x,6hValue ,i6,5h ok? ,$) read(unit=itin, fmt=101) qr if ((qr .eq. n) .or. (qr .eq. N)) goto 300 900 return 910 i2 = defalt goto 900 end subroutine ttinaa(qu, cs, ncs, defalt, itin,itout, verify) c Terminal entry of character string - F77 version c qu - 80C string of prompt que c cs - character string to be input-array of c*1 but can c be equivalenced to char string in calling pgm c ncs - # characters in cs c defalt - default string for cs 25

c itin,itout - read, write LUNs of terminal c verify - if true, asks for verification of input c if false no verification c typical call: c call ttinaa(que,fnam,16,defalt,itin,itout,verify) c MEG/ Dec 85; SUN conversion Jul 89/ MEG c c Although this code has been tested and verified, it is not c guaranteed to perform correctly in all cases, and may contain c bugs that have not been identified c logical verify character css(80) character qu*80 character que(80)*1, qr*1 c character defalt(*), cs(*) replaced with following: character*(*) cs,defalt read(unit=qu, fmt=200) que 200 format(80a1) call lnnobl(que, nq, 80) 300 write(unit=itout, fmt=204) 204 format( ,$) do 40 i = 1, nq 40 write(unit=itout, fmt=201) que(i) 201 format(a1,$) read(unit=itin, fmt=101, err=300) css 101 format(80a1) call lnnobl(css, kcss, 80) c <cr> go to default if (kcss .eq. 0) goto 910 write(cs,(80a))(css(i),i=1,ncs) if (.not. verify) goto 900 write(unit=itout, fmt=202) (css(i),i = 1, ncs) 202 format(1x,17hCharacter string /1x,80a:) write(unit=itout, fmt=203) 203 format(5h ok? ,$) read(unit=itin, fmt=101) qr if ((qr .eq. n) .or. (qr .eq. N)) goto 300 900 return 910 cs = defalt goto 900 end * ---------------------------------------------------------------------------* Numerical diagonalization of 3x3 matrcies * Copyright (C) 2006 Joachim Kopp * ---------------------------------------------------------------------------26

* * * * * * * * * * * * * *

This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ----------------------------------------------------------------------------

* ---------------------------------------------------------------------------SUBROUTINE DSYEVH3(A, Q, W) * ---------------------------------------------------------------------------* Calculates the eigenvalues and normalized eigenvectors of a symmetric 3x3 * matrix A using Cardanos method for the eigenvalues and an analytical * method based on vector cross products for the eigenvectors. However, * if conditions are such that a large error in the results is to be * expected, the routine falls back to using the slower, but more * accurate QL algorithm. Only the diagonal and upper triangular parts of A need * to contain meaningful values. Access to A is read-only. * ---------------------------------------------------------------------------* Parameters: * A: The symmetric input matrix * Q: Storage buffer for eigenvectors * W: Storage buffer for eigenvalues * ---------------------------------------------------------------------------* Dependencies: * DSYEVC3(), DSYTRD3(), DSYEVQ3() * ---------------------------------------------------------------------------* .. Arguments .. DOUBLE PRECISION A(3,3) DOUBLE PRECISION Q(3,3) DOUBLE PRECISION W(3) * .. Parameters .. DOUBLE PRECISION EPS PARAMETER ( EPS = 2.2204460492503131D-16 ) .. Local Variables .. DOUBLE PRECISION NORM, N1, N2 27

DOUBLE PRECISION ERROR DOUBLE PRECISION T, U INTEGER J * .. External Functions .. EXTERNAL DSYEVC3, DSYEVQ3 Calculate eigenvalues CALL DSYEVC3(A, W) --- The rest of this subroutine can be omitted if only the eigenvalues are desired Prepare N1 N2 T U ERROR Q(1, 2) Q(2, 2) Q(3, 2) calculation of eigenvectors = A(1, 1)**2 + A(1, 2)**2 + A(1, 3)**2 = A(1, 2)**2 + A(2, 2)**2 + A(2, 3)**2 = MAX(ABS(W(1)), ABS(W(2)), ABS(W(3))) = MAX(T, T**2) = 256.0D0 * EPS * (N1 + U) * (N2 + U) = A(1, 2) * A(2, 3) - A(1, 3) * A(2, 2) = A(1, 3) * A(1, 2) - A(2, 3) * A(1, 1) = A(1, 2)**2 by the formula x (A - lambda[0]).e2 * W(1) * W(1) (A(2,2) - W(1)) - Q(3,2) 1)**2 + Q(3, 1)**2

* *

* *

Calculate first eigenvector v[0] = (A - lambda[0]).e1 Q(1, 1) = Q(1, 2) + A(1, 3) Q(2, 1) = Q(2, 2) + A(2, 3) Q(3, 1) = (A(1,1) - W(1)) * NORM = Q(1, 1)**2 + Q(2,

* * * * * *

If vectors are nearly linearly dependent, or if there might have been large cancellations in the calculation of A(I,I) - W(1), fall back to QL algorithm Note that this simultaneously ensures that multiple eigenvalues do not cause problems: If W(1) = W(2), then A - W(1) * I has rank 1, i.e. all columns of A - W(1) * I are linearly dependent. IF (NORM .LE. ERROR) THEN CALL DSYEVQ3(A, Q, W) RETURN This is the standard branch ELSE NORM = SQRT(1.0D0 / NORM) DO 20, J = 1, 3 Q(J, 1) = Q(J, 1) * NORM 20 CONTINUE END IF

28

* *

Calculate second eigenvector by the formula v[1] = (A - lambda[1]).e1 x (A - lambda[1]).e2 Q(1, 2) = Q(1, 2) + A(1, 3) * W(2) Q(2, 2) = Q(2, 2) + A(2, 3) * W(2) Q(3, 2) = (A(1,1) - W(2)) * (A(2,2) - W(2)) - Q(3, 2) NORM = Q(1, 2)**2 + Q(2, 2)**2 + Q(3, 2)**2 IF (NORM .LE. ERROR) THEN CALL DSYEVQ3(A, Q, W) RETURN ELSE NORM = SQRT(1.0D0 / NORM) DO 40, J = 1, 3 Q(J, 2) = Q(J, 2) * NORM 40 CONTINUE END IF Calculate third eigenvector v[2] = v[0] x v[1] 80 Q(1, 3) = Q(2, 1) * Q(3, 2) Q(2, 3) = Q(3, 1) * Q(1, 2) Q(3, 3) = Q(1, 1) * Q(2, 2) according to - Q(3, 1) * Q(2, 2) - Q(1, 1) * Q(3, 2) - Q(2, 1) * Q(1, 2)

* *

END SUBROUTINE * End of subroutine DSYEVH3 * * * * * * * * * * * * * * * * * * ---------------------------------------------------------------------------Numerical diagonalization of 3x3 matrcies Copyright (C) 2006 Joachim Kopp ---------------------------------------------------------------------------This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ----------------------------------------------------------------------------

* ---------------------------------------------------------------------------29

* * * * * * * * * * *

SUBROUTINE DSYEVC3(A, W) ---------------------------------------------------------------------------Calculates the eigenvalues of a symmetric 3x3 matrix A using Cardanos analytical algorithm. Only the diagonal and upper triangular parts of A are accessed. The access is read-only. ---------------------------------------------------------------------------Parameters: A: The symmetric input matrix W: Storage buffer for eigenvalues ---------------------------------------------------------------------------.. Arguments .. DOUBLE PRECISION A(3,3) DOUBLE PRECISION W(3) .. Parameters .. DOUBLE PRECISION SQRT3 PARAMETER ( SQRT3 = 1.73205080756887729352744634151D0 ) .. Local Variables .. DOUBLE PRECISION M, C1, C0 DOUBLE PRECISION DE, DD, EE, FF DOUBLE PRECISION P, SQRTP, Q, C, S, PHI Determine coefficients of characteristic poynomial. We write | A D F | A = | D* B E | | F* E* C | DE = A(1,2) * A(2,3) DD = A(1,2)**2 EE = A(2,3)**2 FF = A(1,3)**2 M = A(1,1) + A(2,2) + A(3,3) C1 = ( A(1,1)*A(2,2) + A(1,1)*A(3,3) + A(2,2)*A(3,3) ) $ - (DD + EE + FF) C0 = A(3,3)*DD + A(1,1)*EE + A(2,2)*FF - A(1,1)*A(2,2)*A(3,3) $ - 2.0D0 * A(1,3)*DE P = M**2 - 3.0D0 * C1 Q = M*(P - (3.0D0/2.0D0)*C1) - (27.0D0/2.0D0)*C0 SQRTP = SQRT(ABS(P)) PHI $ PHI = 27.0D0 * ( 0.25D0 * C1**2 * (P - C1) + C0 * (Q + (27.0D0/4.0D0)*C0) ) = (1.0D0/3.0D0) * ATAN2(SQRT(ABS(PHI)), Q)

* * * *

30

C S W(2) W(3) W(1) W(2) = = = =

= SQRTP * COS(PHI) = (1.0D0/SQRT3) * SQRTP * SIN(PHI) (1.0D0/3.0D0) * (M - C) W(2) + S W(2) + C W(2) - S

END SUBROUTINE * End of subroutine DSYEVC3 * * * * * * * * * * * * * * * * * * ---------------------------------------------------------------------------Numerical diagonalization of 3x3 matrcies Copyright (C) 2006 Joachim Kopp ---------------------------------------------------------------------------This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ----------------------------------------------------------------------------

* ---------------------------------------------------------------------------SUBROUTINE DSYTRD3(A, Q, D, E) * ---------------------------------------------------------------------------* Reduces a symmetric 3x3 matrix to real tridiagonal form by applying * (unitary) Householder transformations: * [ D[1] E[1] ] * A = Q . [ E[1] D[2] E[2] ] . Q^T * [ E[2] D[3] ] * The function accesses only the diagonal and upper triangular parts of * A. The access is read-only. * --------------------------------------------------------------------------* .. Arguments .. DOUBLE PRECISION A(3,3) DOUBLE PRECISION Q(3,3) DOUBLE PRECISION D(3) 31

DOUBLE PRECISION E(2) * .. Parameters .. INTEGER N PARAMETER ( N = 3 ) .. Local Variables .. DOUBLE PRECISION U(N), P(N) DOUBLE PRECISION OMEGA, F DOUBLE PRECISION K, H, G INTEGER I, J Initialize Q to the identitity matrix --- This loop can be omitted if only the eigenvalues are desired --DO 10 I = 1, N Q(I,I) = 1.0D0 DO 11, J = 1, I-1 Q(I, J) = 0.0D0 Q(J, I) = 0.0D0 11 CONTINUE 10 CONTINUE Bring first row and column to the desired form H = A(1,2)**2 + A(1,3)**2 IF (A(1,2) .GT. 0.0D0) THEN G = -SQRT(H) ELSE G = SQRT(H) END IF E(1) = G F = G * A(1,2) U(2) = A(1,2) - G U(3) = A(1,3) OMEGA = H - F IF (OMEGA > 0.0D0) THEN OMEGA = 1.0D0 / OMEGA K = 0.0D0 DO 20 I = 2, N F = A(2,I)*U(2) + A(I,3)*U(3) P(I) = OMEGA * F K = K + U(I) * F CONTINUE K = 0.5D0 * K * OMEGA**2 DO 30 I = 2, N 32

* *

20

30

P(I) = P(I) - K * U(I) CONTINUE D(1) = A(1,1) D(2) = A(2,2) - 2.0D0 * P(2) * U(2) D(3) = A(3,3) - 2.0D0 * P(3) * U(3)

* *

41 40 *

Store inverse Householder transformation in Q --- This loop can be omitted if only the eigenvalues are desired --DO 40, J = 2, N F = OMEGA * U(J) DO 41 I = 2, N Q(I,J) = Q(I,J) - F * U(I) CONTINUE CONTINUE Calculated updated A(2, 3) and store it in E(2) E(2) = A(2, 3) - P(2) * U(3) - U(2) * P(3) ELSE DO 50 I = 1, N D(I) = A(I, I) CONTINUE E(2) = A(2, 3) END IF

50

END SUBROUTINE * End of subroutine DSYTRD3 * * * * * * * * * * * * * * * * * * ---------------------------------------------------------------------------Numerical diagonalization of 3x3 matrcies Copyright (C) 2006 Joachim Kopp ---------------------------------------------------------------------------This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ---------------------------------------------------------------------------33

* ---------------------------------------------------------------------------SUBROUTINE DSYEVQ3(A, Q, W) * ---------------------------------------------------------------------------* Calculates the eigenvalues and normalized eigenvectors of a symmetric 3x3 * matrix A using the QL algorithm with implicit shifts, preceded by a * Householder reduction to real tridiagonal form. * The function accesses only the diagonal and upper triangular parts of * A. The access is read-only. * ---------------------------------------------------------------------------* Parameters: * A: The symmetric input matrix * Q: Storage buffer for eigenvectors * W: Storage buffer for eigenvalues * ---------------------------------------------------------------------------* Dependencies: * DSYTRD3() * ---------------------------------------------------------------------------* .. Arguments .. DOUBLE PRECISION A(3,3) DOUBLE PRECISION Q(3,3) DOUBLE PRECISION W(3) * .. Parameters .. INTEGER N PARAMETER ( N = 3 ) .. Local Variables .. DOUBLE PRECISION E(3) DOUBLE PRECISION G, R, P, F, B, S, C, T INTEGER NITER INTEGER L, M, I, J, K .. External Functions .. EXTERNAL DSYTRD3 Transform A to real tridiagonal form by the Householder method CALL DSYTRD3(A, Q, W, E) Calculate eigensystem of the remaining real symmetric tridiagonal matrix with the QL method Loop over all off-diagonal elements DO 10 L = 1, N-1 NITER = 0 34

* * * *

* * *

20 30

Iteration loop DO 11 I = 1, 50 Check for convergence and exit iteration loop if off-diagonal element E(L) is zero DO 20 M = L, N-1 G = ABS(W(M)) + ABS(W(M+1)) IF (ABS(E(M)) + G .EQ. G) THEN GO TO 30 END IF CONTINUE IF (M .EQ. L) THEN GO TO 10 END IF NITER = NITER + 1 IF (NITER >= 30) THEN PRINT *, DSYEVQ3: No convergence. RETURN END IF

Calculate G = D(M) - K G = (W(L+1) - W(L)) / (2.0D0 * E(L)) R = SQRT(1.0D0 + G**2) IF (G .GE. 0.0D0) THEN G = W(M) - W(L) + E(L)/(G + R) ELSE G = W(M) - W(L) + E(L)/(G - R) END IF S = 1.0D0 C = 1.0D0 P = 0.0D0 DO 40 J = M - 1, L, -1 F = S * E(J) B = C * E(J) IF (ABS(F) .GT. ABS(G)) THEN C = G / F R = SQRT(1.0D0 + C**2) E(J+1) = F * R S = 1.0D0 / R C = C * S ELSE S = F / G R = SQRT(1.0D0 + S**2) E(J+1) = G * R 35

C S END IF G R P W(J+1) G * * = = = = =

= 1.0D0 / R = S * C

W(J+1) - P (W(J) - G) * S + 2.0D0 * C * B S * R G + P C * R - B

50 40

11 10

Form eigenvectors --- This loop can be omitted if only the eigenvalues are desired --DO 50 K = 1, N T = Q(K, J+1) Q(K, J+1) = S * Q(K, J) + C * T Q(K, J) = C * Q(K, J) - S * T CONTINUE CONTINUE W(L) = W(L) - P E(L) = G E(M) = 0.0D0 CONTINUE CONTINUE

END SUBROUTINE * End of subroutine DSYEVQ3

36

Das könnte Ihnen auch gefallen