-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwmm2020.h
511 lines (385 loc) · 17.6 KB
/
wmm2020.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
/* WMM Subroutine library was tested in the following environments
*
* 1. Red Hat Linux with GCC Compiler
* 2. MS Windows XP with CodeGear C++ compiler
* 3. Sun Solaris with GCC Compiler
*
*
* Revision Number: $Revision: 1437 $
* Last changed by: $Author: awoods $
* Last changed on: $Date: 2016-03-01 10:49:40 -0700 (Tue, 01 Mar 2016) $
*
*
*/
#ifndef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE
#endif
/*
#ifndef EPOCHRANGE
#define EPOCHRANGE (int)5
#endif
*/
#ifndef GEOMAGHEADER_H
#define GEOMAGHEADER_H
#define READONLYMODE "r"
#define MAXLINELENGTH (1024)
#define NOOFPARAMS (15)
#define NOOFCOEFFICIENTS (7)
#define _DEGREE_NOT_FOUND (-2)
#define CALCULATE_NUMTERMS(N) (N * ( N + 1 ) / 2 + N)
/*These error values come from the ISCWSA error model:
*http://www.copsegrove.com/Pages/MWDGeomagneticModels.aspx
*/
#define INCL_ERROR_BASE (0.20)
#define DECL_ERROR_OFFSET_BASE (0.36)
#define F_ERROR_BASE (130)
#define DECL_ERROR_SLOPE_BASE (5000)
#define WMM_ERROR_MULTIPLIER 1.21
#define IGRF_ERROR_MULTIPLIER 1.21
/*These error values are the NCEI error model
*
*/
#define WMM_UNCERTAINTY_F 145
#define WMM_UNCERTAINTY_H 128
#define WMM_UNCERTAINTY_X 131
#define WMM_UNCERTAINTY_Y 94
#define WMM_UNCERTAINTY_Z 157
#define WMM_UNCERTAINTY_I 0.21
#define WMM_UNCERTAINTY_D_OFFSET 0.26
#define WMM_UNCERTAINTY_D_COEF 5625
#ifndef M_PI
#define M_PI ((2)*(acos(0.0)))
#endif
#define RAD2DEG(rad) ((rad)*(180.0L/M_PI))
#define DEG2RAD(deg) ((deg)*(M_PI/180.0L))
#define ATanH(x) (0.5 * log((1 + x) / (1 - x)))
#ifndef TRUE
#define TRUE ((int)1)
#endif
#ifndef FALSE
#define FALSE ((int)0)
#endif
#define MAG_PS_MIN_LAT_DEGREE -55 /* Minimum Latitude for Polar Stereographic projection in degrees */
#define MAG_PS_MAX_LAT_DEGREE 55 /* Maximum Latitude for Polar Stereographic projection in degrees */
#define MAG_UTM_MIN_LAT_DEGREE -80.5 /* Minimum Latitude for UTM projection in degrees */
#define MAG_UTM_MAX_LAT_DEGREE 84.5 /* Maximum Latitude for UTM projection in degrees */
#define MAG_GEO_POLE_TOLERANCE 1e-5
#define MAG_USE_GEOID 1 /* 1 Geoid - Ellipsoid difference should be corrected, 0 otherwise */
#define LAT_BOUND_MIN -90
#define LAT_BOUND_MAX 90
#define LON_BOUND_MIN -180
#define LON_BOUND_MAX 360
#define ALT_BOUND_MIN -10
#define NO_ALT_MAX -99999
#define USER_GAVE_UP -1
#define WGS84ON 1
#define MSLON 2
/*
Data types and prototype declaration for
World Magnetic Model (WMM) subroutines.
July 28, 2009
#define MODEL_RELEASE_DATE "10 Dec 2019"
#define VERSIONDATE_LARGE "$Date: 2019-12-10 10:40:43 -0700 (Tue, 10 Dec 2019) $"
typedef enum {
DECLINATION,
INCLINATION,
HOR_INTENSITY,
TOTAL_INTENSITY,
X_COMPONENT,
Y_COMPONENT,
Z_COMPONENT,
ALL
} MAGenum_Comp;
typedef struct {
double EditionDate;
double epoch; /*Base time of Geomagnetic model epoch (yrs)*/
char ModelName[32];
double *Main_Field_Coeff_G; /* C - Gauss coefficients of main geomagnetic model (nT) Index is (n * (n + 1) / 2 + m) */
double *Main_Field_Coeff_H; /* C - Gauss coefficients of main geomagnetic model (nT) */
double *Secular_Var_Coeff_G; /* CD - Gauss coefficients of secular geomagnetic model (nT/yr) */
double *Secular_Var_Coeff_H; /* CD - Gauss coefficients of secular geomagnetic model (nT/yr) */
int nMax; /* Maximum degree of spherical harmonic model */
int nMaxSecVar; /* Maximum degree of spherical harmonic secular model */
int SecularVariationUsed; /* Whether or not the magnetic secular variation vector will be needed by program*/
double CoefficientFileEndDate;
} MAGtype_MagneticModel;
typedef struct {
double a; /*semi-major axis of the ellipsoid*/
double b; /*semi-minor axis of the ellipsoid*/
double fla; /* flattening */
double epssq; /*first eccentricity squared */
double eps; /* first eccentricity */
double re; /* mean radius of ellipsoid*/
} MAGtype_Ellipsoid;
typedef struct {
double lambda; /* longitude */
double phi; /* geodetic latitude */
double HeightAboveEllipsoid; /* height above the ellipsoid (HaE) */
double HeightAboveGeoid; /* (height above the EGM96 geoid model ) */
int UseGeoid;
} MAGtype_CoordGeodetic;
typedef struct {
double lambda; /* longitude*/
double phig; /* geocentric latitude*/
double r; /* distance from the center of the ellipsoid*/
} MAGtype_CoordSpherical;
typedef struct {
int Year;
int Month;
int Day;
double DecimalYear; /* decimal years */
} MAGtype_Date;
typedef struct {
double *Pcup; /* Legendre Function */
double *dPcup; /* Derivative of Legendre fcn */
} MAGtype_LegendreFunction;
typedef struct {
double Bx; /* North */
double By; /* East */
double Bz; /* Down */
} MAGtype_MagneticResults;
typedef struct {
double *RelativeRadiusPower; /* [earth_reference_radius_km / sph. radius ]^n */
double *cos_mlambda; /*cp(m) - cosine of (m*spherical coord. longitude)*/
double *sin_mlambda; /* sp(m) - sine of (m*spherical coord. longitude) */
} MAGtype_SphericalHarmonicVariables;
typedef struct {
double Decl; /* 1. Angle between the magnetic field vector and true north, positive east*/
double Incl; /*2. Angle between the magnetic field vector and the horizontal plane, positive down*/
double F; /*3. Magnetic Field Strength*/
double H; /*4. Horizontal Magnetic Field Strength*/
double X; /*5. Northern component of the magnetic field vector*/
double Y; /*6. Eastern component of the magnetic field vector*/
double Z; /*7. Downward component of the magnetic field vector*/
double GV; /*8. The Grid Variation*/
double Decldot; /*9. Yearly Rate of change in declination*/
double Incldot; /*10. Yearly Rate of change in inclination*/
double Fdot; /*11. Yearly rate of change in Magnetic field strength*/
double Hdot; /*12. Yearly rate of change in horizontal field strength*/
double Xdot; /*13. Yearly rate of change in the northern component*/
double Ydot; /*14. Yearly rate of change in the eastern component*/
double Zdot; /*15. Yearly rate of change in the downward component*/
double GVdot; /*16. Yearly rate of change in grid variation*/
} MAGtype_GeoMagneticElements;
typedef struct {
int NumbGeoidCols; /* 360 degrees of longitude at 15 minute spacing */
int NumbGeoidRows; /* 180 degrees of latitude at 15 minute spacing */
int NumbHeaderItems; /* min, max lat, min, max long, lat, long spacing*/
int ScaleFactor; /* 4 grid cells per degree at 15 minute spacing */
float *GeoidHeightBuffer;
int NumbGeoidElevs;
int Geoid_Initialized; /* indicates successful initialization */
int UseGeoid; /*Is the Geoid being used?*/
} MAGtype_Geoid;
typedef struct {
int UseGradient;
MAGtype_GeoMagneticElements GradPhi; /* phi */
MAGtype_GeoMagneticElements GradLambda; /* lambda */
MAGtype_GeoMagneticElements GradZ;
} MAGtype_Gradient;
typedef struct {
char Longitude[40];
char Latitude[40];
} MAGtype_CoordGeodeticStr;
typedef struct {
double Easting; /* (X) in meters*/
double Northing; /* (Y) in meters */
int Zone; /*UTM Zone*/
char HemiSphere;
double CentralMeridian;
double ConvergenceOfMeridians;
double PointScale;
} MAGtype_UTMParameters;
enum PARAMS {
SHDF,
MODELNAME,
PUBLISHER,
RELEASEDATE,
DATACUTOFF,
MODELSTARTYEAR,
MODELENDYEAR,
EPOCH,
INTSTATICDEG,
INTSECVARDEG,
EXTSTATICDEG,
EXTSECVARDEG,
GEOMAGREFRAD,
NORMALIZATION,
SPATBASFUNC
};
enum COEFFICIENTS {
IE,
N,
M,
GNM,
HNM,
DGNM,
DHNM
};
enum YYYYMMDD {
YEAR,
MONTH,
DAY
};
extern double WMM_COF[90][6];
/*Prototypes */
/*Functions that should be Magnetic Model member functions*/
/*Wrapper Functions*/
int MAG_Geomag(MAGtype_Ellipsoid Ellip,
MAGtype_CoordSpherical CoordSpherical,
MAGtype_CoordGeodetic CoordGeodetic,
MAGtype_MagneticModel *TimedMagneticModel,
MAGtype_GeoMagneticElements *GeoMagneticElements);
void MAG_Gradient(MAGtype_Ellipsoid Ellip,
MAGtype_CoordGeodetic CoordGeodetic,
MAGtype_MagneticModel *TimedMagneticModel,
MAGtype_Gradient *Gradient);
int MAG_robustReadMagneticModel_Large(char *filename, char* filenameSV, MAGtype_MagneticModel **MagneticModel);
int MAG_robustReadMagModels(char *filename, MAGtype_MagneticModel *(*magneticmodels)[], int array_size);
int MAG_GetMagneticModel(double wmm_cof[90][6], MAGtype_MagneticModel * MagneticModel);
int MAG_SetDefaults(MAGtype_Ellipsoid *Ellip, MAGtype_Geoid *Geoid);
/*User Interface*/
void MAG_Error(int control);
int MAG_GetUserGrid(MAGtype_CoordGeodetic *minimum,
MAGtype_CoordGeodetic *maximum,
double *step_size,
double *a_step_size,
double *step_time,
MAGtype_Date *StartDate,
MAGtype_Date *EndDate,
int *ElementOption,
int *PrintOption,
char *OutputFile,
MAGtype_Geoid *Geoid);
int MAG_GetUserInput(MAGtype_MagneticModel *MagneticModel,
MAGtype_Geoid *Geoid,
MAGtype_CoordGeodetic *CoordGeodetic,
MAGtype_Date *MagneticDate);
void MAG_PrintGradient(MAGtype_Gradient Gradient);
void MAG_PrintUserData(MAGtype_GeoMagneticElements GeomagElements,
MAGtype_CoordGeodetic SpaceInput,
MAGtype_Date TimeInput,
MAGtype_MagneticModel *MagneticModel,
MAGtype_Geoid *Geoid);
int MAG_ValidateDMSstring(char *input, int min, int max, char *Error);
int MAG_Warnings(int control, double value, MAGtype_MagneticModel *MagneticModel);
/*Memory and File Processing*/
MAGtype_LegendreFunction *MAG_AllocateLegendreFunctionMemory(int NumTerms);
MAGtype_MagneticModel *MAG_AllocateModelMemory(int NumTerms);
MAGtype_SphericalHarmonicVariables *MAG_AllocateSphVarMemory(int nMax);
void MAG_AssignHeaderValues(MAGtype_MagneticModel *model, char values[][MAXLINELENGTH]);
void MAG_AssignMagneticModelCoeffs(MAGtype_MagneticModel *Assignee, MAGtype_MagneticModel *Source, int nMax, int nMaxSecVar);
int MAG_FreeMemory(MAGtype_MagneticModel *MagneticModel, MAGtype_MagneticModel *TimedMagneticModel, MAGtype_LegendreFunction *LegendreFunction);
int MAG_FreeLegendreMemory(MAGtype_LegendreFunction *LegendreFunction);
int MAG_FreeMagneticModelMemory(MAGtype_MagneticModel *MagneticModel);
int MAG_FreeSphVarMemory(MAGtype_SphericalHarmonicVariables *SphVar);
void MAG_PrintWMMFormat(char *filename, MAGtype_MagneticModel *MagneticModel);
void MAG_PrintEMMFormat(char *filename, char *filenameSV, MAGtype_MagneticModel *MagneticModel);
void MAG_PrintSHDFFormat(char *filename, MAGtype_MagneticModel *(*MagneticModel)[], int epochs);
int MAG_readMagneticModel(char *filename, MAGtype_MagneticModel *MagneticModel);
int MAG_readMagneticModel_Large(char *filename, char *filenameSV, MAGtype_MagneticModel *MagneticModel);
int MAG_readMagneticModel_SHDF(char *filename, MAGtype_MagneticModel *(*magneticmodels)[], int array_size);
char *MAG_Trim(char *str);
/*Conversions, Transformations, and other Calculations*/
void MAG_BaseErrors(double DeclCoef, double DeclBaseline, double InclOffset, double FOffset, double Multiplier, double H, double* DeclErr, double* InclErr, double* FErr);
int MAG_CalculateGeoMagneticElements(MAGtype_MagneticResults *MagneticResultsGeo, MAGtype_GeoMagneticElements *GeoMagneticElements);
void MAG_CalculateGradientElements(MAGtype_MagneticResults GradResults, MAGtype_GeoMagneticElements MagneticElements, MAGtype_GeoMagneticElements *GradElements);
int MAG_CalculateSecularVariationElements(MAGtype_MagneticResults MagneticVariation, MAGtype_GeoMagneticElements *MagneticElements);
int MAG_CalculateGridVariation(MAGtype_CoordGeodetic location, MAGtype_GeoMagneticElements *elements);
void MAG_CartesianToGeodetic(MAGtype_Ellipsoid Ellip, double x, double y, double z, MAGtype_CoordGeodetic *CoordGeodetic);
MAGtype_CoordGeodetic MAG_CoordGeodeticAssign(MAGtype_CoordGeodetic CoordGeodetic);
int MAG_DateToYear(MAGtype_Date *Calendar_Date, char *Error);
void MAG_DegreeToDMSstring(double DegreesOfArc, int UnitDepth, char *DMSstring);
void MAG_DMSstringToDegree(char *DMSstring, double *DegreesOfArc);
void MAG_ErrorCalc(MAGtype_GeoMagneticElements B, MAGtype_GeoMagneticElements* Errors);
int MAG_GeodeticToSpherical(MAGtype_Ellipsoid Ellip, MAGtype_CoordGeodetic CoordGeodetic, MAGtype_CoordSpherical *CoordSpherical);
MAGtype_GeoMagneticElements MAG_GeoMagneticElementsAssign(MAGtype_GeoMagneticElements Elements);
MAGtype_GeoMagneticElements MAG_GeoMagneticElementsScale(MAGtype_GeoMagneticElements Elements, double factor);
MAGtype_GeoMagneticElements MAG_GeoMagneticElementsSubtract(MAGtype_GeoMagneticElements minuend, MAGtype_GeoMagneticElements subtrahend);
int MAG_GetTransverseMercator(MAGtype_CoordGeodetic CoordGeodetic, MAGtype_UTMParameters *UTMParameters);
int MAG_GetUTMParameters(double Latitude,
double Longitude,
int *Zone,
char *Hemisphere,
double *CentralMeridian);
int MAG_isNaN(double d);
int MAG_RotateMagneticVector(MAGtype_CoordSpherical,
MAGtype_CoordGeodetic CoordGeodetic,
MAGtype_MagneticResults MagneticResultsSph,
MAGtype_MagneticResults *MagneticResultsGeo);
void MAG_SphericalToCartesian(MAGtype_CoordSpherical CoordSpherical, double *x, double *y, double *z);
void MAG_SphericalToGeodetic(MAGtype_Ellipsoid Ellip, MAGtype_CoordSpherical CoordSpherical, MAGtype_CoordGeodetic *CoordGeodetic);
void MAG_TMfwd4(double Eps, double Epssq, double K0R4, double K0R4oa,
double Acoeff[], double Lam0, double K0, double falseE,
double falseN, int XYonly, double Lambda, double Phi,
double *X, double *Y, double *pscale, double *CoM);
int MAG_YearToDate(MAGtype_Date *Date);
/*Spherical Harmonics*/
int MAG_AssociatedLegendreFunction(MAGtype_CoordSpherical CoordSpherical, int nMax, MAGtype_LegendreFunction *LegendreFunction);
int MAG_CheckGeographicPole(MAGtype_CoordGeodetic *CoordGeodetic);
int MAG_ComputeSphericalHarmonicVariables(MAGtype_Ellipsoid Ellip,
MAGtype_CoordSpherical CoordSpherical,
int nMax,
MAGtype_SphericalHarmonicVariables * SphVariables);
void MAG_GradY(MAGtype_Ellipsoid Ellip, MAGtype_CoordSpherical CoordSpherical, MAGtype_CoordGeodetic CoordGeodetic,
MAGtype_MagneticModel *TimedMagneticModel, MAGtype_GeoMagneticElements GeoMagneticElements, MAGtype_GeoMagneticElements *GradYElements);
void MAG_GradYSummation(MAGtype_LegendreFunction *LegendreFunction, MAGtype_MagneticModel *MagneticModel, MAGtype_SphericalHarmonicVariables SphVariables, MAGtype_CoordSpherical CoordSpherical, MAGtype_MagneticResults *GradY);
int MAG_PcupHigh(double *Pcup, double *dPcup, double x, int nMax);
int MAG_PcupLow(double *Pcup, double *dPcup, double x, int nMax);
int MAG_SecVarSummation(MAGtype_LegendreFunction *LegendreFunction,
MAGtype_MagneticModel *MagneticModel,
MAGtype_SphericalHarmonicVariables SphVariables,
MAGtype_CoordSpherical CoordSpherical,
MAGtype_MagneticResults *MagneticResults);
int MAG_SecVarSummationSpecial(MAGtype_MagneticModel *MagneticModel,
MAGtype_SphericalHarmonicVariables SphVariables,
MAGtype_CoordSpherical CoordSpherical,
MAGtype_MagneticResults *MagneticResults);
int MAG_Summation(MAGtype_LegendreFunction *LegendreFunction,
MAGtype_MagneticModel *MagneticModel,
MAGtype_SphericalHarmonicVariables SphVariables,
MAGtype_CoordSpherical CoordSpherical,
MAGtype_MagneticResults *MagneticResults);
int MAG_SummationSpecial(MAGtype_MagneticModel *MagneticModel,
MAGtype_SphericalHarmonicVariables SphVariables,
MAGtype_CoordSpherical CoordSpherical,
MAGtype_MagneticResults *MagneticResults);
int MAG_TimelyModifyMagneticModel(MAGtype_Date UserDate, MAGtype_MagneticModel *MagneticModel, MAGtype_MagneticModel *TimedMagneticModel);
/*Geoid*/
int MAG_ConvertGeoidToEllipsoidHeight(MAGtype_CoordGeodetic *CoordGeodetic, MAGtype_Geoid *Geoid);
/*
* The function Convert_Geoid_To_Ellipsoid_Height converts the specified WGS84
* geoid height at the specified geodetic coordinates to the equivalent
* ellipsoid height, using the EGM96 gravity model.
*
* Latitude : Geodetic latitude in radians (input)
* Longitude : Geodetic longitude in radians (input)
* Geoid_Height : Geoid height, in meters (input)
* Ellipsoid_Height : Ellipsoid height, in meters. (output)
*
*/
int MAG_GetGeoidHeight(double Latitude, double Longitude, double *DeltaHeight, MAGtype_Geoid *Geoid);
/*
* The private function Get_Geoid_Height returns the height of the
* WGS84 geiod above or below the WGS84 ellipsoid,
* at the specified geodetic coordinates,
* using a grid of height adjustments from the EGM96 gravity model.
*
* Latitude : Geodetic latitude in radians (input)
* Longitude : Geodetic longitude in radians (input)
* DeltaHeight : Height Adjustment, in meters. (output)
*
*/
void MAG_EquivalentLatLon(double lat, double lon, double *repairedLat, double *repairedLon);
void MAG_WMMErrorCalc(double H, MAGtype_GeoMagneticElements *Uncertainty);
void MAG_PrintUserDataWithUncertainty(MAGtype_GeoMagneticElements GeomagElements,
MAGtype_GeoMagneticElements Errors,
MAGtype_CoordGeodetic SpaceInput,
MAGtype_Date TimeInput,
MAGtype_MagneticModel *MagneticModel,
MAGtype_Geoid *Geoid);
void GetDecInc(double *decl, double *incl, double lat, double lon, int year, int mon);
void MAG_GetDeg(char* Query_String, double* latitude, double bounds[2]);
int MAG_GetAltitude(char* Query_String, MAGtype_Geoid *Geoid, MAGtype_CoordGeodetic* coords, int bounds[2], int AltitudeSetting);
#endif /*GEOMAGHEADER_H*/