COSMOS core  1.0.2 (beta)
Comprehensive Open-architecture Solution for Mission Operations Systems
geomag.cpp File Reference
#include "support/geomag.h"
#include "support/datalib.h"
#include <stdio.h>
#include <stdlib.h>
#include <cstring>
#include <cmath>
Include dependency graph for geomag.cpp:

Macros

#define NaN   log(-1.0)
 

Functions

int32_t E0000 (int IENTRY, int *maxdeg, float alt, float rlat, float rlon, float time, float *dec, float *dip, float *ti, float *gv)
 
int32_t geomag (int *maxdeg)
 
int32_t geomg1 (float alt, float rlat, float rlon, float time, float *dec, float *dip, float *ti, float *gv, float *bx, float *by, float *bz)
 
char geomag_introduction (float epochlowlim)
 
int32_t geomag_front (gvector pos, double time, rvector &comp)
 
int32_t E0000 (int IENTRY, int *maxdeg, float alt, float rlat, float rlon, float time, float *dec, float *dip, float *ti, float *gv, float *bx, float *by, float *bz)
 

Variables

static int initialized = 0
 
static char fname [100]
 

Macro Definition Documentation

#define NaN   log(-1.0)

Function Documentation

int32_t E0000 ( int  IENTRY,
int *  maxdeg,
float  alt,
float  rlat,
float  rlon,
float  time,
float *  dec,
float *  dip,
float *  ti,
float *  gv 
)
int32_t geomag ( int *  maxdeg)
477 {
478  return E0000(0,maxdeg,0.0,0.0,0.0,0.0,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
479 }
int32_t E0000(int IENTRY, int *maxdeg, float alt, float rlat, float rlon, float time, float *dec, float *dip, float *ti, float *gv)
int32_t geomg1 ( float  alt,
float  rlat,
float  rlon,
float  time,
float *  dec,
float *  dip,
float *  ti,
float *  gv,
float *  bx,
float *  by,
float *  bz 
)
484 {
485  return E0000(1,NULL,alt,rlat,rlon,time,dec,dip,ti,gv,bx,by,bz);
486 }
int32_t E0000(int IENTRY, int *maxdeg, float alt, float rlat, float rlon, float time, float *dec, float *dip, float *ti, float *gv)
char geomag_introduction ( float  epochlowlim)
491 {
492  char help;
493  static char ans;
494  int iretn;
495 
496  printf("\n\n Welcome to the World Magnetic Model (WMM) %4.0f C-Program\n\n", epochlowlim);
497  printf(" --- Version 2.0, September 2005 ---\n\n");
498  printf("\n This program estimates the strength and direction of ");
499  printf("\n Earth's main magnetic field for a given point/area.");
500  printf("\n Enter h for help and contact information or c to continue.");
501  printf ("\n >");
502  iretn = scanf("%c%*[^\n]",&help);
503  if (!iretn)
504  {
505  ans = 'y';
506  return ans;
507  }
508  getchar();
509 
510  if ((help == 'h') || (help == 'H'))
511  {
512  printf("\n Help information ");
513 
514  printf("\n The World Magnetic Model (WMM) for %7.2f", epochlowlim);
515  printf("\n is a model of Earth's main magnetic field. The WMM");
516  printf("\n is recomputed every five (5) years, in years divisible by ");
517  printf("\n five (i.e. 2005, 2010). See the contact information below");
518  printf("\n to obtain more information on the WMM and associated software.");
519  printf("\n ");
520  printf("\n Input required is the location in geodetic latitude and");
521  printf("\n longitude (positive for northern latitudes and eastern ");
522  printf("\n longitudes), geodetic altitude in meters, and the date of ");
523  printf("\n interest in years.");
524 
525  printf("\n\n\n The program computes the estimated magnetic Declination");
526  printf("\n (D) which is sometimes called MAGVAR, Inclination (I), Total");
527  printf("\n Intensity (F or TI), Horizontal Intensity (H or HI), Vertical");
528  printf("\n Intensity (Z), and Grid Variation (GV). Declination and Grid");
529  printf("\n Variation are measured in units of degrees and are considered");
530  printf("\n positive when east or north. Inclination is measured in units");
531  printf("\n of degrees and is considered positive when pointing down (into");
532  printf("\n the Earth). The WMM is reference to the WGS-84 ellipsoid and");
533  printf("\n is valid for 5 years after the base epoch.");
534 
535  printf("\n\n\n It is very important to note that a degree and order 12 model,");
536  printf("\n such as WMM, describes only the long wavelength spatial magnetic ");
537  printf("\n fluctuations due to Earth's core. Not included in the WMM series");
538  printf("\n models are intermediate and short wavelength spatial fluctuations ");
539  printf("\n that originate in Earth's mantle and crust. Consequently, isolated");
540  printf("\n angular errors at various positions on the surface (primarily over");
541  printf("\n land, incontinental margins and over oceanic seamounts, ridges and");
542  printf("\n trenches) of several degrees may be expected. Also not included in");
543  printf("\n the model are temporal fluctuations of magnetospheric and ionospheric");
544  printf("\n origin. On the days during and immediately following magnetic storms,");
545  printf("\n temporal fluctuations can cause substantial deviations of the geomagnetic");
546  printf("\n field from model values. If the required declination accuracy is");
547  printf("\n more stringent than the WMM series of models provide, the user is");
548  printf("\n advised to request special (regional or local) surveys be performed");
549  printf("\n and models prepared. Please make requests of this nature to the");
550  printf("\n National Geospatial-Intelligence Agency (NGA) at the address below.");
551 
552  printf("\n\n\n Contact Information");
553 
554  printf("\n Software and Model Support");
555  printf("\n National Geophysical Data Center");
556  printf("\n NOAA EGC/2");
557  printf("\n 325 Broadway");
558  printf("\n Boulder, CO 80303 USA");
559  printf("\n Attn: Susan McLean or Stefan Maus");
560  printf("\n Phone: (303) 497-6478 or -6522");
561  printf("\n Email: Susan.McLean@noaa.gov or Stefan.Maus@noaa.gov ");
562 
563  printf("\n\n\n Continue with program? (y or n) ");
564  iretn = scanf("%c%*[^\n]", &ans);
565  if (!iretn)
566  {
567  ans = 'y';
568  return ans;
569  }
570  getchar();
571  }
572  else
573  {
574  ans = 'y';
575  }
576 
577  return(ans);
578 }
int iretn
Definition: rw_test.cpp:37
int32_t E0000 ( int  IENTRY,
int *  maxdeg,
float  alt,
float  rlat,
float  rlon,
float  time,
float *  dec,
float *  dip,
float *  ti,
float *  gv,
float *  bx,
float *  by,
float *  bz 
)
179 {
180  register int n,m,D3,D4;
181  static int maxord,i,icomp,j,D1,D2,in,im;
182  static float c[13][13],cd[13][13],tc[13][13],dp[13][13],snorm[169],
183  sp[13],cp[13],fn[13],fm[13],pp[13],k[13][13],dtr,a,b,re,
184  a2,b2,c2,a4,b4,c4,epoch=0.,gnm,hnm,dgnm,dhnm,flnmj,otime,oalt,
185  olat,olon,dt,glon,glat,srlon,srlat,crlon,crlat,srlat2,
186  crlat2,q,q1,q2,ct,st,r2,r,d,ca,sa,aor,ar,br,bt,bp,bpp,
187  par,temp1,temp2,parp,bh;
188  static char model[20], c_str[81], c_new[5];
189  static float *p = snorm;
190  //char answer;
191 
192  FILE *wmmdat;
193  char* ichar;
194 
195  switch(IENTRY){case 0: goto GEOMAG; case 1: goto GEOMG1;}
196 
197 GEOMAG:
198  if ((wmmdat=fopen(fname,"r")) == NULL)
199  {
200  return GEOMAG_ERROR_NOTFOUND;
201  }
202 
203 
204  /* INITIALIZE CONSTANTS */
205  maxord = *maxdeg;
206  sp[0] = 0.0;
207  cp[0] = *p = pp[0] = 1.0;
208  dp[0][0] = 0.0;
209  a = (float)6378.137;
210  b = (float)6356.7523142;
211  re = (float)6371.2;
212  a2 = a*a;
213  b2 = b*b;
214  c2 = a2-b2;
215  a4 = a2*a2;
216  b4 = b2*b2;
217  c4 = a4 - b4;
218 
219  /* READ WORLD MAGNETIC MODEL SPHERICAL HARMONIC COEFFICIENTS */
220  c[0][0] = 0.0;
221  cd[0][0] = 0.0;
222 
223  ichar = fgets(c_str, 80, wmmdat);
224  if (ichar != NULL)
225  {
226  sscanf(c_str,"%f%s",&epoch,model);
227  }
228 S3:
229  ichar = fgets(c_str, 80, wmmdat);
230  /* CHECK FOR LAST LINE IN FILE */
231  for (i=0; i<4 && (c_str[i] != '\0'); i++)
232  {
233  c_new[i] = c_str[i];
234  c_new[i+1] = '\0';
235  }
236  icomp = strcmp("9999", c_new);
237  if (icomp == 0) goto S4;
238  /* END OF FILE NOT ENCOUNTERED, GET VALUES */
239  sscanf(c_str,"%d%d%f%f%f%f",&in,&im,&gnm,&hnm,&dgnm,&dhnm);
240  if (im <= in)
241  {
242  c[im][in] = gnm;
243  cd[im][in] = dgnm;
244  if (im != 0)
245  {
246  c[in][im-1] = hnm;
247  cd[in][im-1] = dhnm;
248  }
249  }
250  goto S3;
251 
252  /* CONVERT SCHMIDT NORMALIZED GAUSS COEFFICIENTS TO UNNORMALIZED */
253 S4:
254  *snorm = 1.0;
255  for (n=1; n<=maxord; n++)
256  {
257  *(snorm+n) = *(snorm+n-1)*(float)(2*n-1)/(float)n;
258  j = 2;
259  for (m=0,D1=1,D2=(n-m+D1)/D1; D2>0; D2--,m+=D1)
260  {
261  k[m][n] = (float)(((n-1)*(n-1))-(m*m))/(float)((2*n-1)*(2*n-3));
262  if (m > 0)
263  {
264  flnmj = (float)((n-m+1)*j)/(float)(n+m);
265  *(snorm+n+m*13) = *(snorm+n+(m-1)*13)*sqrt(flnmj);
266  j = 1;
267  c[n][m-1] = *(snorm+n+m*13)*c[n][m-1];
268  cd[n][m-1] = *(snorm+n+m*13)*cd[n][m-1];
269  }
270  c[m][n] = *(snorm+n+m*13)*c[m][n];
271  cd[m][n] = *(snorm+n+m*13)*cd[m][n];
272  }
273  fn[n] = (float)(n+1);
274  fm[n] = (float)n;
275  }
276  k[1][1] = 0.0;
277 
278  otime = oalt = olat = olon = -1000.0;
279  fclose(wmmdat);
280  return 0;
281 
282  /*************************************************************************/
283 
284 GEOMG1:
285  dt = time - epoch;
286  if (otime < 0.0 && (dt < 0.0 || dt > 15.0))
287  {
288  /*
289  printf("\n\n WARNING - TIME EXTENDS BEYOND MODEL 5-YEAR LIFE SPAN");
290  printf("\n CONTACT NGDC FOR PRODUCT UPDATES:");
291  printf("\n National Geophysical Data Center");
292  printf("\n NOAA EGC/2");
293  printf("\n 325 Broadway");
294  printf("\n Boulder, CO 80303 USA");
295  printf("\n Attn: Susan McLean or Stefan Maus");
296  printf("\n Phone: (303) 497-6478 or -6522");
297  printf("\n Email: Susan.McLean@noaa.gov");
298  printf("\n or");
299  printf("\n Stefan.Maus@noaa.gov");
300  printf("\n Web: http://www.ngdc.noaa.gov/seg/WMM/");
301  printf("\n\n EPOCH = %.3f",epoch);
302  printf("\n TIME = %.3f",time);
303  */
304  *bx = *by =*bz = *dec = *dip = *ti = *gv = 0.;
306  /*
307  printf("\n Do you wish to continue? (y or n) ");
308  scanf("%c%*[^\n]",&answer);
309  getchar();
310  if ((answer == 'n') || (answer == 'N'))
311  {
312  printf("\n Do you wish to enter more point data? (y or n) ");
313  scanf("%c%*[^\n]",&answer);
314  getchar();
315  if ((answer == 'y')||(answer == 'Y')) goto GEOMG1;
316  else exit (0);
317  }
318  */
319  }
320 
321  dtr = (float)(DPI/180.0);
322  glon = rlon/dtr;
323  glat = rlat/dtr;
324  srlon = sin(rlon);
325  srlat = sin(rlat);
326  crlon = cos(rlon);
327  crlat = cos(rlat);
328  srlat2 = srlat*srlat;
329  crlat2 = crlat*crlat;
330  sp[1] = srlon;
331  cp[1] = crlon;
332 
333  /* CONVERT FROM GEODETIC COORDS. TO SPHERICAL COORDS. */
334  if (alt != oalt || glat != olat)
335  {
336  q = sqrt(a2-c2*srlat2);
337  q1 = alt*q;
338  q2 = ((q1+a2)/(q1+b2))*((q1+a2)/(q1+b2));
339  ct = srlat/sqrt(q2*crlat2+srlat2);
340  st = (float)sqrt(1.0-(ct*ct));
341  r2 = (float)((alt*alt)+2.0*q1+(a4-c4*srlat2)/(q*q));
342  r = sqrt(r2);
343  d = sqrt(a2*crlat2+b2*srlat2);
344  ca = (alt+d)/r;
345  sa = c2*crlat*srlat/(r*d);
346  }
347  if (glon != olon)
348  {
349  for (m=2; m<=maxord; m++)
350  {
351  sp[m] = sp[1]*cp[m-1]+cp[1]*sp[m-1];
352  cp[m] = cp[1]*cp[m-1]-sp[1]*sp[m-1];
353  }
354  }
355  aor = re/r;
356  ar = aor*aor;
357  br = bt = bp = bpp = 0.0;
358  for (n=1; n<=maxord; n++)
359  {
360  ar = ar*aor;
361  for (m=0,D3=1,D4=(n+m+D3)/D3; D4>0; D4--,m+=D3)
362  {
363  /*
364  COMPUTE UNNORMALIZED ASSOCIATED LEGENDRE POLYNOMIALS
365  AND DERIVATIVES VIA RECURSION RELATIONS
366 */
367  if (alt != oalt || glat != olat)
368  {
369  if (n == m)
370  {
371  *(p+n+m*13) = st**(p+n-1+(m-1)*13);
372  dp[m][n] = st*dp[m-1][n-1]+ct**(p+n-1+(m-1)*13);
373  goto S50;
374  }
375  if (n == 1 && m == 0)
376  {
377  *(p+n+m*13) = ct**(p+n-1+m*13);
378  dp[m][n] = ct*dp[m][n-1]-st**(p+n-1+m*13);
379  goto S50;
380  }
381  if (n > 1 && n != m)
382  {
383  if (m > n-2) *(p+n-2+m*13) = 0.0;
384  if (m > n-2) dp[m][n-2] = 0.0;
385  *(p+n+m*13) = ct**(p+n-1+m*13)-k[m][n]**(p+n-2+m*13);
386  dp[m][n] = ct*dp[m][n-1] - st**(p+n-1+m*13)-k[m][n]*dp[m][n-2];
387  }
388  }
389 S50:
390  /*
391  TIME ADJUST THE GAUSS COEFFICIENTS
392 */
393  if (time != otime)
394  {
395  tc[m][n] = c[m][n]+dt*cd[m][n];
396  if (m != 0) tc[n][m-1] = c[n][m-1]+dt*cd[n][m-1];
397  }
398  /*
399  ACCUMULATE TERMS OF THE SPHERICAL HARMONIC EXPANSIONS
400 */
401  par = ar**(p+n+m*13);
402  if (m == 0)
403  {
404  temp1 = tc[m][n]*cp[m];
405  temp2 = tc[m][n]*sp[m];
406  }
407  else
408  {
409  temp1 = tc[m][n]*cp[m]+tc[n][m-1]*sp[m];
410  temp2 = tc[m][n]*sp[m]-tc[n][m-1]*cp[m];
411  }
412  bt = bt-ar*temp1*dp[m][n];
413  bp += (fm[m]*temp2*par);
414  br += (fn[n]*temp1*par);
415  /*
416  SPECIAL CASE: NORTH/SOUTH GEOGRAPHIC POLES
417 */
418  if (st == 0.0 && m == 1)
419  {
420  if (n == 1) pp[n] = pp[n-1];
421  else pp[n] = ct*pp[n-1]-k[m][n]*pp[n-2];
422  parp = ar*pp[n];
423  bpp += (fm[m]*temp2*parp);
424  }
425  }
426  }
427  if (st == 0.0) bp = bpp;
428  else bp /= st;
429  /*
430  ROTATE MAGNETIC VECTOR COMPONENTS FROM SPHERICAL TO
431  GEODETIC COORDINATES
432 */
433  *bx = -bt*ca-br*sa;
434  *by = bp;
435  *bz = bt*sa-br*ca;
436  // EJP: 1.) switch from LH to RH coordinates, 2.) reverse direction of field to represent actual direction
437  /*
438  *bx = bt*ca+br*sa;
439  *by = -bp;
440  *bz = bt*sa-br*ca;
441  */
442  /*
443  COMPUTE DECLINATION (DEC), INCLINATION (DIP) AND
444  TOTAL INTENSITY (TI)
445 */
446  bh = sqrt((*bx**bx)+(*by**by));
447  *ti = sqrt((bh*bh)+(*bz**bz));
448  *dec = atan2(*by,*bx);
449  *dip = atan2(*bz,bh);
450  /*
451  COMPUTE MAGNETIC GRID VARIATION IF THE CURRENT
452  GEODETIC POSITION IS IN THE ARCTIC OR ANTARCTIC
453  (I.E. GLAT > +55 DEGREES OR GLAT < -55 DEGREES)
454 
455  OTHERWISE, SET MAGNETIC GRID VARIATION TO -999.0
456 */
457  *gv = -999.0;
458  if (fabs(glat) >= 55.)
459  {
460  if (glat > 0.0 && glon >= 0.0) *gv = (*dec-rlon)/dtr;
461  if (glat > 0.0 && glon < 0.0) *gv = (*dec+fabs(rlon))/dtr;
462  if (glat < 0.0 && glon >= 0.0) *gv = (*dec+rlon)/dtr;
463  if (glat < 0.0 && glon < 0.0) *gv = (*dec-fabs(rlon))/dtr;
464  if (*gv > +180.0) *gv -= 360.0;
465  if (*gv < -180.0) *gv += 360.0;
466  }
467  otime = time;
468  oalt = alt;
469  olat = glat;
470  olon = glon;
471  return 0;
472 }
static double re
Definition: nrlmsise-00.cpp:67
ElapsedTime dt
Definition: agent_file3.cpp:183
int i
Definition: rw_test.cpp:37
long b
Definition: jpegint.h:371
static double * p
Definition: gauss_jackson_test.cpp:42
static uint16_t model
Definition: add_radio.cpp:19
static char fname[100]
Definition: geomag.cpp:89
Definition: eci2kep_test.cpp:33
const double DPI
Double precision PI.
Definition: math/constants.h:14
#define GEOMAG_ERROR_OUTOFRANGE
Definition: cosmos-errno.h:247
#define GEOMAG_ERROR_NOTFOUND
Definition: cosmos-errno.h:246

Variable Documentation

int initialized = 0
static
char fname[100]
static