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