head	1.4;
access;
symbols;
locks; strict;
comment	@# @;


1.4
date	2002.09.07.01.50.37;	author curt;	state Exp;
branches;
next	1.3;

1.3
date	2002.08.31.19.01.53;	author curt;	state Exp;
branches;
next	1.2;

1.2
date	2002.08.31.18.54.00;	author curt;	state Exp;
branches;
next	1.1;

1.1
date	2002.02.15.17.21.55;	author curt;	state Exp;
branches;
next	;


desc
@@


1.4
log
@Updated doxygen docs.
@
text
@<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>coremag.cxx Source File</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.2.16 -->
<center>
<a class="qindex" href="index.html">Main Page</a> &nbsp; <a class="qindex" href="hierarchy.html">Class Hierarchy</a> &nbsp; <a class="qindex" href="annotated.html">Compound List</a> &nbsp; <a class="qindex" href="files.html">File List</a> &nbsp; <a class="qindex" href="functions.html">Compound Members</a> &nbsp; <a class="qindex" href="globals.html">File Members</a> &nbsp; </center>
<hr><h1>coremag.cxx</h1><div class="fragment"><pre>00001 <font class="comment">// coremag.cxx -- compute local magnetic variation given position,</font>
00002 <font class="comment">//                altitude, and date</font>
00003 <font class="comment">//</font>
00004 <font class="comment">// This is an implementation of the NIMA (formerly DMA) WMM2000</font>
00005 <font class="comment">//</font>
00006 <font class="comment">//    http://www.nima.mil/GandG/ngdc-wmm2000.html</font>
00007 <font class="comment">//</font>
00008 <font class="comment">// Copyright (C) 2000  Edward A Williams &lt;Ed_Williams@@compuserve.com&gt;</font>
00009 <font class="comment">//</font>
00010 <font class="comment">// Adapted from Excel 3.0 version 3/27/94 EAW</font>
00011 <font class="comment">// Recoded in C++ by Starry Chan</font>
00012 <font class="comment">// WMM95 added and rearranged in ANSI-C EAW 7/9/95</font>
00013 <font class="comment">// Put shell around program and made Borland &amp; GCC compatible EAW 11/22/95</font>
00014 <font class="comment">// IGRF95 added 2/96 EAW</font>
00015 <font class="comment">// WMM2000 IGR2000 added 2/00 EAW</font>
00016 <font class="comment">// Released under GPL 3/26/00 EAW</font>
00017 <font class="comment">// Adaptions and modifications for the SimGear project  3/27/2000 CLO</font>
00018 <font class="comment">//</font>
00019 <font class="comment">// Removed all pow() calls and made static roots[][] arrays to</font>
00020 <font class="comment">// save many sqrt() calls on subsequent invocations</font>
00021 <font class="comment">// left old code as SGMagVarOrig() for testing purposes</font>
00022 <font class="comment">// 3/28/2000  Norman Vine -- nhv@@yahoo.com</font>
00023 <font class="comment">//</font>
00024 <font class="comment">// Put in some bullet-proofing to handle magnetic and geographic poles.</font>
00025 <font class="comment">// 3/28/2000 EAW</font>
00026 
00027 <font class="comment">//  The routine uses a spherical harmonic expansion of the magnetic</font>
00028 <font class="comment">// potential up to twelfth order, together with its time variation, as</font>
00029 <font class="comment">// described in Chapter 4 of "Geomagnetism, Vol 1, Ed. J.A.Jacobs,</font>
00030 <font class="comment">// Academic Press (London 1987)". The program first converts geodetic</font>
00031 <font class="comment">// coordinates (lat/long on elliptic earth and altitude) to spherical</font>
00032 <font class="comment">// geocentric (spherical lat/long and radius) coordinates. Using this,</font>
00033 <font class="comment">// the spherical (B_r, B_theta, B_phi) magnetic field components are</font>
00034 <font class="comment">// computed from the model. These are finally referred to surface (X, Y,</font>
00035 <font class="comment">// Z) coordinates.</font>
00036 <font class="comment">//</font>
00037 <font class="comment">//   Fields are accurate to better than 200nT, variation and dip to</font>
00038 <font class="comment">// better than 0.5 degrees, with the exception of the declination near</font>
00039 <font class="comment">// the magnetic poles (where it is ill-defined) where the error may reach</font>
00040 <font class="comment">// 4 degrees or more.</font>
00041 <font class="comment">//</font>
00042 <font class="comment">//   Variation is undefined at both the geographic and  </font>
00043 <font class="comment">// magnetic poles, even though the field itself is well-behaved. To</font>
00044 <font class="comment">// avoid the routine blowing up, latitude entries corresponding to</font>
00045 <font class="comment">// the geographic poles are slightly offset. At the magnetic poles,</font>
00046 <font class="comment">// the routine returns zero variation.</font>
00047 
00048 
00049 <font class="comment">//</font>
00050 <font class="comment">// This library is free software; you can redistribute it and/or</font>
00051 <font class="comment">// modify it under the terms of the GNU Library General Public</font>
00052 <font class="comment">// License as published by the Free Software Foundation; either</font>
00053 <font class="comment">// version 2 of the License, or (at your option) any later version.</font>
00054 <font class="comment">//</font>
00055 <font class="comment">// This library is distributed in the hope that it will be useful,</font>
00056 <font class="comment">// but WITHOUT ANY WARRANTY; without even the implied warranty of</font>
00057 <font class="comment">// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU</font>
00058 <font class="comment">// Library General Public License for more details.</font>
00059 <font class="comment">//</font>
00060 <font class="comment">// You should have received a copy of the GNU Library General Public</font>
00061 <font class="comment">// License along with this library; if not, write to the</font>
00062 <font class="comment">// Free Software Foundation, Inc., 59 Temple Place - Suite 330,</font>
00063 <font class="comment">// Boston, MA  02111-1307, USA.</font>
00064 <font class="comment">//</font>
00065 <font class="comment">// $Id: coremag.cxx,v 1.2 2001/04/22 14:57:08 curt Exp $</font>
00066 
00067 
00068 <font class="preprocessor">#include &lt;stdio.h&gt;</font>
00069 <font class="preprocessor">#include &lt;stdlib.h&gt;</font>
00070 <font class="preprocessor">#include &lt;math.h&gt;</font>
00071 
00072 <font class="preprocessor">#include &lt;<a class="code" href="constants_8h.html">simgear/constants.h</a>&gt;</font>
00073 <font class="preprocessor">#include &lt;<a class="code" href="sg__inlines_8h.html">simgear/sg_inlines.h</a>&gt;</font>
00074 
00075 <font class="preprocessor">#include "coremag.hxx"</font>
00076 
00077 
00078 <font class="keyword">static</font> <font class="keyword">const</font> <font class="keywordtype">double</font> pi = 3.14159265358979;
00079 <font class="keyword">static</font> <font class="keyword">const</font> <font class="keywordtype">double</font> a = 6378.16;        <font class="comment">/* major radius (km) IAU66 ellipsoid */</font>
00080 <font class="keyword">static</font> <font class="keyword">const</font> <font class="keywordtype">double</font> f = 1.0 / 298.25;   <font class="comment">/* inverse flattening IAU66 ellipsoid */</font>
00081 <font class="keyword">static</font> <font class="keyword">const</font> <font class="keywordtype">double</font> b = 6378.16 * (1.0 -1.0 / 298.25 );
00082 <font class="comment">/* minor radius b=a*(1-f) */</font>
00083 <font class="keyword">static</font> <font class="keyword">const</font> <font class="keywordtype">double</font> r_0 = 6371.2;       <font class="comment">/* "mean radius" for spherical harmonic expansion */</font>
00084 
00085 <font class="keyword">static</font> <font class="keywordtype">double</font> gnm_wmm2000[13][13] =
00086 {
00087     {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00088     {-29616.0, -1722.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00089     {-2266.7, 3070.2, 1677.6, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00090     {1322.4, -2291.5, 1255.9, 724.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00091     {932.1, 786.3, 250.6, -401.5, 106.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00092     {-211.9, 351.6, 220.8, -134.5, -168.8, -13.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00093     {73.8, 68.2, 74.1, -163.5, -3.8, 17.1, -85.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00094     {77.4, -73.9, 2.2, 35.7, 7.3, 5.2, 8.4, -1.5, 0.0, 0.0, 0.0, 0.0, 0.0},
00095     {23.3, 7.3, -8.5, -6.6, -16.9, 8.6, 4.9, -7.8, -7.6, 0.0, 0.0, 0.0, 0.0},
00096     {5.7, 8.5, 2.0, -9.8, 7.6, -7.0, -2.0, 9.2, -2.2, -6.6, 0.0, 0.0, 0.0},
00097     {-2.2, -5.7, 1.6, -3.7, -0.6, 4.1, 2.2, 2.2, 4.6, 2.3, 0.1, 0.0, 0.0},
00098     {3.3, -1.1, -2.4, 2.6, -1.3, -1.7, -0.6, 0.4, 0.7, -0.3, 2.3, 4.2, 0.0},
00099     {-1.5, -0.2, -0.3, 0.5, 0.2, 0.9, -1.4, 0.6, -0.6, -1.0, -0.3, 0.3, 0.4},
00100 };
00101 
00102 <font class="keyword">static</font> <font class="keywordtype">double</font> hnm_wmm2000[13][13]=
00103 {
00104     {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00105     {0.0, 5194.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00106     {0.0, -2484.8, -467.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00107     {0.0, -224.7, 293.0, -486.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00108     {0.0, 273.3, -227.9, 120.9, -302.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00109     {0.0, 42.0, 173.8, -135.0, -38.6, 105.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00110     {0.0, -17.4, 61.2, 63.2, -62.9, 0.2, 43.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00111     {0.0, -62.3, -24.5, 8.9, 23.4, 15.0, -27.6, -7.8, 0.0, 0.0, 0.0, 0.0, 0.0},
00112     {0.0, 12.4, -20.8, 8.4, -21.2, 15.5, 9.1, -15.5, -5.4, 0.0, 0.0, 0.0, 0.0},
00113     {0.0, -20.4, 13.9, 12.0, -6.2, -8.6, 9.4, 5.0, -8.4, 3.2, 0.0, 0.0, 0.0},
00114     {0.0, 0.9, -0.7, 3.9, 4.8, -5.3, -1.0, -2.4, 1.3, -2.3, -6.4, 0.0, 0.0},
00115     {0.0, -1.5, 0.7, -1.1, -2.3, 1.3, -0.6, -2.8, -1.6, -0.1, -1.9, 1.4, 0.0},
00116     {0.0, -1.0, 0.7, 2.2, -2.5, -0.2, 0.0, -0.2, 0.0, 0.2, -0.9, -0.2, 1.0},
00117 };
00118 
00119 <font class="keyword">static</font> <font class="keywordtype">double</font> gtnm_wmm2000[13][13]=
00120 {
00121     {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00122     {14.7, 11.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00123     {-13.6, -0.7, -1.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00124     {0.3, -4.3, 0.9, -8.4, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00125     {-1.6, 0.9, -7.6, 2.2, -3.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00126     {-0.9, -0.2, -2.5, -2.7, -0.9, 1.7, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00127     {1.2, 0.2, 1.7, 1.6, -0.1, -0.3, 0.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00128     {-0.4, -0.8, -0.2, 1.1, 0.4, 0.0, -0.2, -0.2, 0.0, 0.0, 0.0, 0.0, 0.0},
00129     {-0.3, 0.6, -0.8, 0.3, -0.2, 0.5, 0.0, -0.6, 0.1, 0.0, 0.0, 0.0, 0.0},
00130     {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00131     {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00132     {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00133     {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00134 };
00135 
00136 <font class="keyword">static</font> <font class="keywordtype">double</font> htnm_wmm2000[13][13]=
00137 {
00138     {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00139     {0.0, -20.4, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00140     {0.0, -21.5, -9.6, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00141     {0.0, 6.4, -1.3, -13.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00142     {0.0, 2.3, 0.7, 3.7, -0.5, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00143     {0.0, 0.0, 2.1, 2.3, 3.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00144     {0.0, -0.3, -1.7, -0.9, -1.0, -0.1, 1.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00145     {0.0, 1.4, 0.2, 0.7, 0.4, -0.3, -0.8, -0.1, 0.0, 0.0, 0.0, 0.0, 0.0},
00146     {0.0, -0.5, 0.1, -0.2, 0.0, 0.1, -0.1, 0.3, 0.2, 0.0, 0.0, 0.0, 0.0},
00147     {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00148     {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00149     {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00150     {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
00151 };
00152 
00153 <font class="keyword">static</font> <font class="keyword">const</font> <font class="keywordtype">int</font> nmax = 12;
00154 
00155 <font class="keyword">static</font> <font class="keywordtype">double</font> P[13][13];
00156 <font class="keyword">static</font> <font class="keywordtype">double</font> DP[13][13];
00157 <font class="keyword">static</font> <font class="keywordtype">double</font> gnm[13][13];
00158 <font class="keyword">static</font> <font class="keywordtype">double</font> hnm[13][13];
00159 <font class="keyword">static</font> <font class="keywordtype">double</font> sm[13];
00160 <font class="keyword">static</font> <font class="keywordtype">double</font> cm[13];
00161 
00162 <font class="keyword">static</font> <font class="keywordtype">double</font> root[13];
00163 <font class="keyword">static</font> <font class="keywordtype">double</font> roots[13][13][2];
00164 
00165 <font class="comment">/* Convert date to Julian day    1950-2049 */</font>
00166 <font class="keywordtype">unsigned</font> <font class="keywordtype">long</font> <font class="keywordtype">int</font> yymmdd_to_julian_days( <font class="keywordtype">int</font> yy, <font class="keywordtype">int</font> mm, <font class="keywordtype">int</font> dd )
00167 {
00168     <font class="keywordtype">unsigned</font> <font class="keywordtype">long</font> jd;
00169  
00170     yy = (yy &lt; 50) ? (2000 + yy) : (1900 + yy);
00171     jd = dd - 32075L + 1461L * (yy + 4800L + (mm - 14) / 12 ) / 4;
00172     jd = jd + 367L * (mm - 2 - (mm - 14) / 12*12) / 12;
00173     jd = jd - 3 * ((yy + 4900L + (mm - 14) / 12) / 100) / 4;
00174 
00175     <font class="comment">/* printf("julian date = %d\n", jd ); */</font>
00176     <font class="keywordflow">return</font> jd;
00177 } 
00178 
00179 
00180 <font class="comment">/*</font>
00181 <font class="comment"> * return variation (in radians) given geodetic latitude (radians),</font>
00182 <font class="comment"> * longitude(radians), height (km) and (Julian) date</font>
00183 <font class="comment"> * N and E lat and long are positive, S and W negative</font>
00184 <font class="comment">*/</font>
00185 
00186 <font class="keywordtype">double</font> calc_magvar( <font class="keywordtype">double</font> lat, <font class="keywordtype">double</font> lon, <font class="keywordtype">double</font> h, <font class="keywordtype">long</font> dat, <font class="keywordtype">double</font>* field )
00187 {
00188     <font class="comment">/* output field B_r,B_th,B_phi,B_x,B_y,B_z */</font>
00189     <font class="keywordtype">int</font> n,m;
00190     <font class="comment">/* reference dates */</font>
00191     <font class="keywordtype">long</font> date0_wmm2000 = yymmdd_to_julian_days(0,1,1);
00192 
00193     <font class="keywordtype">double</font> yearfrac,sr,r,theta,c,s,psi,fn,fn_0,B_r,B_theta,B_phi,X,Y,Z;
00194     <font class="keywordtype">double</font> sinpsi, cospsi, inv_s;
00195 
00196     <font class="keyword">static</font> <font class="keywordtype">int</font> been_here = 0;
00197 
00198     <font class="keywordtype">double</font> sinlat = sin(lat);
00199     <font class="keywordtype">double</font> coslat = cos(lat);
00200 
00201     <font class="comment">/* convert to geocentric coords: */</font>
00202     <font class="comment">// sr = sqrt(pow(a*coslat,2.0)+pow(b*sinlat,2.0));</font>
00203     sr = sqrt(a*a*coslat*coslat + b*b*sinlat*sinlat);
00204     <font class="comment">/* sr is effective radius */</font>
00205     theta = atan2(coslat * (h*sr + a*a),
00206                   sinlat * (h*sr + b*b));
00207     <font class="comment">/* theta is geocentric co-latitude */</font>
00208 
00209     r = h*h + 2.0*h * sr +
00210         (a*a*a*a - ( a*a*a*a - b*b*b*b ) * sinlat*sinlat ) / 
00211         (a*a - (a*a - b*b) * sinlat*sinlat );
00212 
00213     r = sqrt(r);
00214 
00215     <font class="comment">/* r is geocentric radial distance */</font>
00216     c = cos(theta);
00217     s = sin(theta);
00218     <font class="comment">/* protect against zero divide at geographic poles */</font>
00219     inv_s =  1.0 / (s + (s == 0.)*1.0e-8); 
00220 
00221     <font class="comment">/* zero out arrays */</font>
00222     <font class="keywordflow">for</font> ( n = 0; n &lt;= nmax; n++ ) {
00223         <font class="keywordflow">for</font> ( m = 0; m &lt;= n; m++ ) {
00224             P[n][m] = 0;
00225             DP[n][m] = 0;
00226         }
00227     }
00228 
00229     <font class="comment">/* diagonal elements */</font>
00230     P[0][0] = 1;
00231     P[1][1] = s;
00232     DP[0][0] = 0;
00233     DP[1][1] = c;
00234     P[1][0] = c ;
00235     DP[1][0] = -s;
00236 
00237     <font class="comment">// these values will not change for subsequent function calls</font>
00238     <font class="keywordflow">if</font>( !been_here ) {
00239         <font class="keywordflow">for</font> ( n = 2; n &lt;= nmax; n++ ) {
00240             root[n] = sqrt((2.0*n-1) / (2.0*n));
00241         }
00242 
00243         <font class="keywordflow">for</font> ( m = 0; m &lt;= nmax; m++ ) {
00244             <font class="keywordtype">double</font> mm = m*m;
00245             <font class="keywordflow">for</font> ( n = SG_MAX2(m + 1, 2); n &lt;= nmax; n++ ) {
00246                 roots[m][n][0] = sqrt((n-1)*(n-1) - mm);
00247                 roots[m][n][1] = 1.0 / sqrt( n*n - mm);
00248             }
00249         }
00250         been_here = 1;
00251     }
00252 
00253     <font class="keywordflow">for</font> ( n=2; n &lt;= nmax; n++ ) {
00254         <font class="comment">// double root = sqrt((2.0*n-1) / (2.0*n));</font>
00255         P[n][n] = P[n-1][n-1] * s * root[n];
00256         DP[n][n] = (DP[n-1][n-1] * s + P[n-1][n-1] * c) *
00257             root[n];
00258     }
00259 
00260     <font class="comment">/* lower triangle */</font>
00261     <font class="keywordflow">for</font> ( m = 0; m &lt;= nmax; m++ ) {
00262         <font class="comment">// double mm = m*m;</font>
00263         <font class="keywordflow">for</font> ( n = SG_MAX2(m + 1, 2); n &lt;= nmax; n++ ) {
00264             <font class="comment">// double root1 = sqrt((n-1)*(n-1) - mm);</font>
00265             <font class="comment">// double root2 = 1.0 / sqrt( n*n - mm);</font>
00266             P[n][m] = (P[n-1][m] * c * (2.0*n-1) -
00267                        P[n-2][m] * roots[m][n][0]) *
00268                 roots[m][n][1];
00269 
00270             DP[n][m] = ((DP[n-1][m] * c - P[n-1][m] * s) *
00271                         (2.0*n-1) - DP[n-2][m] * roots[m][n][0]) *
00272                 roots[m][n][1];
00273         }
00274     }
00275 
00276     <font class="comment">/* compute gnm, hnm at dat */</font>
00277     <font class="comment">/* WMM2000 */</font>
00278     yearfrac = (dat - date0_wmm2000) / 365.25;
00279     <font class="keywordflow">for</font> ( n = 1; n &lt;= nmax; n++ ) {
00280         <font class="keywordflow">for</font> ( m = 0; m &lt;= nmax; m++ ) {
00281             gnm[n][m] = gnm_wmm2000[n][m] + yearfrac * gtnm_wmm2000[n][m];
00282             hnm[n][m] = hnm_wmm2000[n][m] + yearfrac * htnm_wmm2000[n][m];
00283         }
00284     }
00285 
00286     <font class="comment">/* compute sm (sin(m lon) and cm (cos(m lon)) */</font>
00287     <font class="keywordflow">for</font> ( m = 0; m &lt;= nmax; m++ ) {
00288         sm[m] = sin(m * lon);
00289         cm[m] = cos(m * lon);
00290     }
00291 
00292     <font class="comment">/* compute B fields */</font>
00293     B_r = 0.0;
00294     B_theta = 0.0;
00295     B_phi = 0.0;
00296     fn_0 = r_0/r;
00297     fn = fn_0 * fn_0;
00298 
00299     <font class="keywordflow">for</font> ( n = 1; n &lt;= nmax; n++ ) {
00300         <font class="keywordtype">double</font> c1_n=0;
00301         <font class="keywordtype">double</font> c2_n=0;
00302         <font class="keywordtype">double</font> c3_n=0;
00303         <font class="keywordflow">for</font> ( m = 0; m &lt;= n; m++ ) {
00304             <font class="keywordtype">double</font> tmp = (gnm[n][m] * cm[m] + hnm[n][m] * sm[m]); 
00305             c1_n=c1_n + tmp * P[n][m];
00306             c2_n=c2_n + tmp * DP[n][m];
00307             c3_n=c3_n + m * (gnm[n][m] * sm[m] - hnm[n][m] * cm[m]) * P[n][m];
00308         }
00309         <font class="comment">// fn=pow(r_0/r,n+2.0);</font>
00310         fn *= fn_0;
00311         B_r = B_r + (n + 1) * c1_n * fn;
00312         B_theta = B_theta - c2_n * fn;
00313         B_phi = B_phi + c3_n * fn * inv_s;
00314     }
00315 
00316     <font class="comment">/* Find geodetic field components: */</font>
00317     psi = theta - ((pi / 2.0) - lat);
00318     sinpsi = sin(psi);
00319     cospsi = cos(psi);
00320     X = -B_theta * cospsi - B_r * sinpsi;
00321     Y = B_phi;
00322     Z = B_theta * sinpsi - B_r * cospsi;
00323 
00324     field[0]=B_r;
00325     field[1]=B_theta;
00326     field[2]=B_phi;
00327     field[3]=X;
00328     field[4]=Y;
00329     field[5]=Z;   <font class="comment">/* output fields */</font>
00330 
00331     <font class="comment">/* find variation in radians */</font>
00332     <font class="comment">/* return zero variation at magnetic pole X=Y=0. */</font>
00333     <font class="comment">/* E is positive */</font>
00334     <font class="keywordflow">return</font> (X != 0. || Y != 0.) ? atan2(Y, X) : (double) 0.;  
00335 }
00336 
00337 
00338 <font class="preprocessor">#ifdef TEST_NHV_HACKS</font>
00339 <font class="preprocessor"></font><font class="keywordtype">double</font> SGMagVarOrig( <font class="keywordtype">double</font> lat, <font class="keywordtype">double</font> lon, <font class="keywordtype">double</font> h, <font class="keywordtype">long</font> dat, <font class="keywordtype">double</font>* field )
00340 {
00341     <font class="comment">/* output field B_r,B_th,B_phi,B_x,B_y,B_z */</font>
00342     <font class="keywordtype">int</font> n,m;
00343     <font class="comment">/* reference dates */</font>
00344     <font class="keywordtype">long</font> date0_wmm2000 = yymmdd_to_julian_days(0,1,1);
00345 
00346     <font class="keywordtype">double</font> yearfrac,sr,r,theta,c,s,psi,fn,B_r,B_theta,B_phi,X,Y,Z;
00347 
00348     <font class="comment">/* convert to geocentric coords: */</font>
00349     sr = sqrt(pow(a*cos(lat),2.0)+pow(b*sin(lat),2.0));
00350     <font class="comment">/* sr is effective radius */</font>
00351     theta = atan2(cos(lat) * (h * sr + a * a),
00352                   sin(lat) * (h * sr + b * b));
00353     <font class="comment">/* theta is geocentric co-latitude */</font>
00354 
00355     r = h * h + 2.0*h * sr +
00356         (pow(a,4.0) - (pow(a,4.0) - pow(b,4.0)) * pow(sin(lat),2.0)) / 
00357         (a * a - (a * a - b * b) * pow(sin(lat),2.0));
00358 
00359     r = sqrt(r);
00360 
00361     <font class="comment">/* r is geocentric radial distance */</font>
00362     c = cos(theta);
00363     s = sin(theta);
00364 
00365     <font class="comment">/* zero out arrays */</font>
00366     <font class="keywordflow">for</font> ( n = 0; n &lt;= nmax; n++ ) {
00367         <font class="keywordflow">for</font> ( m = 0; m &lt;= n; m++ ) {
00368             P[n][m] = 0;
00369             DP[n][m] = 0;
00370         }
00371     }
00372 
00373     <font class="comment">/* diagonal elements */</font>
00374     P[0][0] = 1;
00375     P[1][1] = s;
00376     DP[0][0] = 0;
00377     DP[1][1] = c;
00378     P[1][0] = c ;
00379     DP[1][0] = -s;
00380 
00381     <font class="keywordflow">for</font> ( n = 2; n &lt;= nmax; n++ ) {
00382         P[n][n] = P[n-1][n-1] * s * sqrt((2.0*n-1) / (2.0*n));
00383         DP[n][n] = (DP[n-1][n-1] * s + P[n-1][n-1] * c) *
00384             sqrt((2.0*n-1) / (2.0*n));
00385     }
00386 
00387     <font class="comment">/* lower triangle */</font>
00388     <font class="keywordflow">for</font> ( m = 0; m &lt;= nmax; m++ ) {
00389         <font class="keywordflow">for</font> ( n = SG_MAX2(m + 1, 2); n &lt;= nmax; n++ ) {
00390             P[n][m] = (P[n-1][m] * c * (2.0*n-1) - P[n-2][m] *
00391                        sqrt(1.0*(n-1)*(n-1) - m * m)) /
00392                 sqrt(1.0* n * n - m * m);
00393             DP[n][m] = ((DP[n-1][m] * c - P[n-1][m] * s) *
00394                         (2.0*n-1) - DP[n-2][m] *
00395                         sqrt(1.0*(n-1) * (n-1) - m * m)) /
00396                 sqrt(1.0* n * n - m * m);
00397         }
00398     }
00399 
00400     <font class="comment">/* compute gnm, hnm at dat */</font>
00401     <font class="comment">/* WMM2000 */</font>
00402     yearfrac = (dat - date0_wmm2000) / 365.25;
00403     <font class="keywordflow">for</font> ( n = 1; n &lt;= nmax; n++ ) {
00404         <font class="keywordflow">for</font> ( m = 0; m &lt;= nmax; m++ ) {
00405             gnm[n][m] = gnm_wmm2000[n][m] + yearfrac * gtnm_wmm2000[n][m];
00406             hnm[n][m] = hnm_wmm2000[n][m] + yearfrac * htnm_wmm2000[n][m];
00407         }
00408     }
00409 
00410     <font class="comment">/* compute sm (sin(m lon) and cm (cos(m lon)) */</font>
00411     <font class="keywordflow">for</font> ( m = 0; m &lt;= nmax; m++ ) {
00412         sm[m] = sin(m * lon);
00413         cm[m] = cos(m * lon);
00414     }
00415 
00416     <font class="comment">/* compute B fields */</font>
00417     B_r = 0.0;
00418     B_theta = 0.0;
00419     B_phi = 0.0;
00420 
00421     <font class="keywordflow">for</font> ( n = 1; n &lt;= nmax; n++ ) {
00422         <font class="keywordtype">double</font> c1_n=0;
00423         <font class="keywordtype">double</font> c2_n=0;
00424         <font class="keywordtype">double</font> c3_n=0;
00425         <font class="keywordflow">for</font> ( m = 0; m &lt;= n; m++ ) {
00426             c1_n=c1_n + (gnm[n][m] * cm[m] + hnm[n][m] * sm[m]) * P[n][m];
00427             c2_n=c2_n + (gnm[n][m] * cm[m] + hnm[n][m] * sm[m]) * DP[n][m];
00428             c3_n=c3_n + m * (gnm[n][m] * sm[m] - hnm[n][m] * cm[m]) * P[n][m];
00429         }
00430         fn=pow(r_0/r,n+2.0);
00431         B_r = B_r + (n + 1) * c1_n * fn;
00432         B_theta = B_theta - c2_n * fn;
00433         B_phi = B_phi + c3_n * fn / s;
00434     }
00435 
00436     <font class="comment">/* Find geodetic field components: */</font>
00437     psi = theta - (pi / 2.0 - lat);
00438     X = -B_theta * cos(psi) - B_r * sin(psi);
00439     Y = B_phi;
00440     Z = B_theta * sin(psi) - B_r * cos(psi);
00441 
00442     field[0]=B_r;
00443     field[1]=B_theta;
00444     field[2]=B_phi;
00445     field[3]=X;
00446     field[4]=Y;
00447     field[5]=Z;   <font class="comment">/* output fields */</font>
00448 
00449     <font class="comment">/* find variation, leave in radians! */</font>
00450     <font class="keywordflow">return</font> atan2(Y, X);  <font class="comment">/* E is positive */</font>
00451 }
00452 <font class="preprocessor">#endif // TEST_NHV_HACKS</font>
</pre></div><hr><address align="right"><small>Generated on Fri Sep 6 20:46:33 2002 for SimGear by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 
width=110 height=53></a>1.2.16 </small></address>
</body>
</html>
@


1.3
log
@Oops, try again.
@
text
@d461 1
a461 1
</pre></div><hr><address align="right"><small>Generated on Sat Aug 31 13:59:37 2002 for SimGear by
@


1.2
log
@Regenerated doxygen files.
@
text
@d461 1
a461 1
</pre></div><hr><address align="right"><small>Generated on Sat Aug 31 13:45:08 2002 for SimGear by
@


1.1
log
@More web page updates (added doxygen docs to repository.)
@
text
@d5 2
a6 2
</head><body bgcolor="#ffffff">
<!-- Generated by Doxygen 1.2.12 -->
d461 1
a461 1
</font></pre></div><hr><address><small>Generated on Fri Feb 15 11:15:30 2002 for SimGear by
d463 2
a464 3
<img src="doxygen.gif" alt="doxygen" align="middle" border=0 
width=110 height=53></a>1.2.12 written by <a href="mailto:dimitri@@stack.nl">Dimitri van Heesch</a>,
 &copy;&nbsp;1997-2001</small></address>
@

