GeographicLib 2.5
GravityModel.hpp
Go to the documentation of this file.
1/**
2 * \file GravityModel.hpp
3 * \brief Header for GeographicLib::GravityModel class
4 *
5 * Copyright (c) Charles Karney (2011-2022) <karney@alum.mit.edu> and licensed
6 * under the MIT/X11 License. For more information, see
7 * https://geographiclib.sourceforge.io/
8 **********************************************************************/
9
10#if !defined(GEOGRAPHICLIB_GRAVITYMODEL_HPP)
11#define GEOGRAPHICLIB_GRAVITYMODEL_HPP 1
12
17
18#if defined(_MSC_VER)
19// Squelch warnings about dll vs vector
20# pragma warning (push)
21# pragma warning (disable: 4251)
22#endif
23
24namespace GeographicLib {
25
26 class GravityCircle;
27
28 /**
29 * \brief Model of the earth's gravity field
30 *
31 * Evaluate the earth's gravity field according to a model. The supported
32 * models treat only the gravitational field exterior to the mass of the
33 * earth. When computing the field at points near (but above) the surface of
34 * the earth a small correction can be applied to account for the mass of the
35 * atmosphere above the point in question; see \ref gravityatmos.
36 * Determining the height of the geoid above the ellipsoid entails correcting
37 * for the mass of the earth above the geoid. The egm96 and egm2008 include
38 * separate correction terms to account for this mass.
39 *
40 * Definitions and terminology (from Heiskanen and Moritz, Sec 2-13):
41 * - \e V = gravitational potential;
42 * - &Phi; = rotational potential;
43 * - \e W = \e V + &Phi; = \e T + \e U = total potential;
44 * - <i>V</i><sub>0</sub> = normal gravitation potential;
45 * - \e U = <i>V</i><sub>0</sub> + &Phi; = total normal potential;
46 * - \e T = \e W &minus; \e U = \e V &minus; <i>V</i><sub>0</sub> = anomalous
47 * or disturbing potential;
48 * - <b>g</b> = &nabla;\e W = <b>&gamma;</b> + <b>&delta;</b>;
49 * - <b>f</b> = &nabla;&Phi;;
50 * - <b>&Gamma;</b> = &nabla;<i>V</i><sub>0</sub>;
51 * - <b>&gamma;</b> = &nabla;\e U;
52 * - <b>&delta;</b> = &nabla;\e T = gravity disturbance vector
53 * = <b>g</b><sub><i>P</i></sub> &minus; <b>&gamma;</b><sub><i>P</i></sub>;
54 * - &delta;\e g = gravity disturbance = <i>g</i><sub><i>P</i></sub> &minus;
55 * &gamma;<sub><i>P</i></sub>;
56 * - &Delta;<b>g</b> = gravity anomaly vector = <b>g</b><sub><i>P</i></sub>
57 * &minus; <b>&gamma;</b><sub><i>Q</i></sub>; here the line \e PQ is
58 * perpendicular to ellipsoid and the potential at \e P equals the normal
59 * potential at \e Q;
60 * - &Delta;\e g = gravity anomaly = <i>g</i><sub><i>P</i></sub> &minus;
61 * &gamma;<sub><i>Q</i></sub>;
62 * - (&xi;, &eta;) deflection of the vertical, the difference in
63 * directions of <b>g</b><sub><i>P</i></sub> and
64 * <b>&gamma;</b><sub><i>Q</i></sub>, &xi; = NS, &eta; = EW.
65 * - \e X, \e Y, \e Z, geocentric coordinates;
66 * - \e x, \e y, \e z, local cartesian coordinates used to denote the east,
67 * north and up directions.
68 *
69 * See \ref gravity for details of how to install the gravity models and the
70 * data format.
71 *
72 * References:
73 * - W. A. Heiskanen and H. Moritz, Physical Geodesy (Freeman, San
74 * Francisco, 1967).
75 *
76 * Example of use:
77 * \include example-GravityModel.cpp
78 *
79 * <a href="Gravity.1.html">Gravity</a> is a command-line utility providing
80 * access to the functionality of GravityModel and GravityCircle.
81 **********************************************************************/
82
84 private:
85 typedef Math::real real;
86 friend class GravityCircle;
87 static const int idlength_ = 8;
88 std::string _name, _dir, _description, _date, _filename, _id;
89 real _amodel, _gGMmodel, _zeta0, _corrmult;
90 int _nmx, _mmx;
92 NormalGravity _earth;
93 std::vector<real> _cCx, _sSx, _cCC, _cCS, _zonal;
94 real _dzonal0; // A left over contribution to _zonal.
95 SphericalHarmonic _gravitational;
96 SphericalHarmonic1 _disturbing;
97 SphericalHarmonic _correction;
98 void ReadMetadata(const std::string& name);
99 Math::real InternalT(real X, real Y, real Z,
100 real& deltaX, real& deltaY, real& deltaZ,
101 bool gradp, bool correct) const;
102 GravityModel(const GravityModel&) = delete; // copy constructor not allowed
103 // nor copy assignment
104 GravityModel& operator=(const GravityModel&) = delete;
105
106 enum captype {
107 CAP_NONE = 0U,
108 CAP_G = 1U<<0, // implies potentials W and V
109 CAP_T = 1U<<1,
110 CAP_DELTA = 1U<<2 | CAP_T, // delta implies T?
111 CAP_C = 1U<<3,
112 CAP_GAMMA0 = 1U<<4,
113 CAP_GAMMA = 1U<<5,
114 CAP_ALL = 0x3FU,
115 };
116
117 public:
118
119 /**
120 * Bit masks for the capabilities to be given to the GravityCircle object
121 * produced by Circle.
122 **********************************************************************/
123 enum mask {
124 /**
125 * No capabilities.
126 * @hideinitializer
127 **********************************************************************/
128 NONE = 0U,
129 /**
130 * Allow calls to GravityCircle::Gravity, GravityCircle::W, and
131 * GravityCircle::V.
132 * @hideinitializer
133 **********************************************************************/
134 GRAVITY = CAP_G,
135 /**
136 * Allow calls to GravityCircle::Disturbance and GravityCircle::T.
137 * @hideinitializer
138 **********************************************************************/
139 DISTURBANCE = CAP_DELTA,
140 /**
141 * Allow calls to GravityCircle::T(real lon) (i.e., computing the
142 * disturbing potential and not the gravity disturbance vector).
143 * @hideinitializer
144 **********************************************************************/
145 DISTURBING_POTENTIAL = CAP_T,
146 /**
147 * Allow calls to GravityCircle::SphericalAnomaly.
148 * @hideinitializer
149 **********************************************************************/
150 SPHERICAL_ANOMALY = CAP_DELTA | CAP_GAMMA,
151 /**
152 * Allow calls to GravityCircle::GeoidHeight.
153 * @hideinitializer
154 **********************************************************************/
155 GEOID_HEIGHT = CAP_T | CAP_C | CAP_GAMMA0,
156 /**
157 * All capabilities.
158 * @hideinitializer
159 **********************************************************************/
160 ALL = CAP_ALL,
161 };
162
163 /**
164 * Move constructs a gravity model.
165 **********************************************************************/
167
168 /**
169 * Move assigns a gravity model.
170 **********************************************************************/
172
173 /** \name Setting up the gravity model
174 **********************************************************************/
175 ///@{
176 /**
177 * Construct a gravity model.
178 *
179 * @param[in] name the name of the model.
180 * @param[in] path (optional) directory for data file.
181 * @param[in] Nmax (optional) if non-negative, truncate the degree of the
182 * model this value.
183 * @param[in] Mmax (optional) if non-negative, truncate the order of the
184 * model this value.
185 * @exception GeographicErr if the data file cannot be found, is
186 * unreadable, or is corrupt, or if \e Mmax > \e Nmax.
187 * @exception std::bad_alloc if the memory necessary for storing the model
188 * can't be allocated.
189 *
190 * A filename is formed by appending ".egm" (World Gravity Model) to the
191 * name. If \e path is specified (and is non-empty), then the file is
192 * loaded from directory, \e path. Otherwise the path is given by
193 * DefaultGravityPath().
194 *
195 * This file contains the metadata which specifies the properties of the
196 * model. The coefficients for the spherical harmonic sums are obtained
197 * from a file obtained by appending ".cof" to metadata file (so the
198 * filename ends in ".egm.cof").
199 *
200 * If \e Nmax &ge; 0 and \e Mmax < 0, then \e Mmax is set to \e Nmax.
201 * After the model is loaded, the maximum degree and order of the model can
202 * be found by the Degree() and Order() methods.
203 **********************************************************************/
204 explicit GravityModel(const std::string& name,
205 const std::string& path = "",
206 int Nmax = -1, int Mmax = -1);
207 ///@}
208
209 /** \name Compute gravity in geodetic coordinates
210 **********************************************************************/
211 ///@{
212 /**
213 * Evaluate the gravity at an arbitrary point above (or below) the
214 * ellipsoid.
215 *
216 * @param[in] lat the geographic latitude (degrees).
217 * @param[in] lon the geographic longitude (degrees).
218 * @param[in] h the height above the ellipsoid (meters).
219 * @param[out] gx the easterly component of the acceleration
220 * (m s<sup>&minus;2</sup>).
221 * @param[out] gy the northerly component of the acceleration
222 * (m s<sup>&minus;2</sup>).
223 * @param[out] gz the upward component of the acceleration
224 * (m s<sup>&minus;2</sup>); this is usually negative.
225 * @return \e W the sum of the gravitational and centrifugal potentials
226 * (m<sup>2</sup> s<sup>&minus;2</sup>).
227 *
228 * The function includes the effects of the earth's rotation.
229 **********************************************************************/
230 Math::real Gravity(real lat, real lon, real h,
231 real& gx, real& gy, real& gz) const;
232
233 /**
234 * Evaluate the gravity disturbance vector at an arbitrary point above (or
235 * below) the ellipsoid.
236 *
237 * @param[in] lat the geographic latitude (degrees).
238 * @param[in] lon the geographic longitude (degrees).
239 * @param[in] h the height above the ellipsoid (meters).
240 * @param[out] deltax the easterly component of the disturbance vector
241 * (m s<sup>&minus;2</sup>).
242 * @param[out] deltay the northerly component of the disturbance vector
243 * (m s<sup>&minus;2</sup>).
244 * @param[out] deltaz the upward component of the disturbance vector
245 * (m s<sup>&minus;2</sup>).
246 * @return \e T the corresponding disturbing potential
247 * (m<sup>2</sup> s<sup>&minus;2</sup>).
248 **********************************************************************/
249 Math::real Disturbance(real lat, real lon, real h,
250 real& deltax, real& deltay, real& deltaz)
251 const;
252
253 /**
254 * Evaluate the geoid height.
255 *
256 * @param[in] lat the geographic latitude (degrees).
257 * @param[in] lon the geographic longitude (degrees).
258 * @return \e N the height of the geoid above the ReferenceEllipsoid()
259 * (meters).
260 *
261 * This calls NormalGravity::U for ReferenceEllipsoid(). Some
262 * approximations are made in computing the geoid height so that the
263 * results of the NGA codes are reproduced accurately. Details are given
264 * in \ref gravitygeoid.
265 **********************************************************************/
266 Math::real GeoidHeight(real lat, real lon) const;
267
268 /**
269 * Evaluate the components of the gravity anomaly vector using the
270 * spherical approximation.
271 *
272 * @param[in] lat the geographic latitude (degrees).
273 * @param[in] lon the geographic longitude (degrees).
274 * @param[in] h the height above the ellipsoid (meters).
275 * @param[out] Dg01 the gravity anomaly (m s<sup>&minus;2</sup>).
276 * @param[out] xi the northerly component of the deflection of the vertical
277 * (degrees).
278 * @param[out] eta the easterly component of the deflection of the vertical
279 * (degrees).
280 *
281 * The spherical approximation (see Heiskanen and Moritz, Sec 2-14) is used
282 * so that the results of the NGA codes are reproduced accurately.
283 * approximations used here. Details are given in \ref gravitygeoid.
284 **********************************************************************/
285 void SphericalAnomaly(real lat, real lon, real h,
286 real& Dg01, real& xi, real& eta) const;
287 ///@}
288
289 /** \name Compute gravity in geocentric coordinates
290 **********************************************************************/
291 ///@{
292 /**
293 * Evaluate the components of the acceleration due to gravity and the
294 * centrifugal acceleration in geocentric coordinates.
295 *
296 * @param[in] X geocentric coordinate of point (meters).
297 * @param[in] Y geocentric coordinate of point (meters).
298 * @param[in] Z geocentric coordinate of point (meters).
299 * @param[out] gX the \e X component of the acceleration
300 * (m s<sup>&minus;2</sup>).
301 * @param[out] gY the \e Y component of the acceleration
302 * (m s<sup>&minus;2</sup>).
303 * @param[out] gZ the \e Z component of the acceleration
304 * (m s<sup>&minus;2</sup>).
305 * @return \e W = \e V + &Phi; the sum of the gravitational and
306 * centrifugal potentials (m<sup>2</sup> s<sup>&minus;2</sup>).
307 *
308 * This calls NormalGravity::U for ReferenceEllipsoid().
309 **********************************************************************/
310 Math::real W(real X, real Y, real Z,
311 real& gX, real& gY, real& gZ) const;
312
313 /**
314 * Evaluate the components of the acceleration due to gravity in geocentric
315 * coordinates.
316 *
317 * @param[in] X geocentric coordinate of point (meters).
318 * @param[in] Y geocentric coordinate of point (meters).
319 * @param[in] Z geocentric coordinate of point (meters).
320 * @param[out] GX the \e X component of the acceleration
321 * (m s<sup>&minus;2</sup>).
322 * @param[out] GY the \e Y component of the acceleration
323 * (m s<sup>&minus;2</sup>).
324 * @param[out] GZ the \e Z component of the acceleration
325 * (m s<sup>&minus;2</sup>).
326 * @return \e V = \e W - &Phi; the gravitational potential
327 * (m<sup>2</sup> s<sup>&minus;2</sup>).
328 **********************************************************************/
329 Math::real V(real X, real Y, real Z,
330 real& GX, real& GY, real& GZ) const;
331
332 /**
333 * Evaluate the components of the gravity disturbance in geocentric
334 * coordinates.
335 *
336 * @param[in] X geocentric coordinate of point (meters).
337 * @param[in] Y geocentric coordinate of point (meters).
338 * @param[in] Z geocentric coordinate of point (meters).
339 * @param[out] deltaX the \e X component of the gravity disturbance
340 * (m s<sup>&minus;2</sup>).
341 * @param[out] deltaY the \e Y component of the gravity disturbance
342 * (m s<sup>&minus;2</sup>).
343 * @param[out] deltaZ the \e Z component of the gravity disturbance
344 * (m s<sup>&minus;2</sup>).
345 * @return \e T = \e W - \e U the disturbing potential (also called the
346 * anomalous potential) (m<sup>2</sup> s<sup>&minus;2</sup>).
347 **********************************************************************/
348 Math::real T(real X, real Y, real Z,
349 real& deltaX, real& deltaY, real& deltaZ) const
350 { return InternalT(X, Y, Z, deltaX, deltaY, deltaZ, true, true); }
351
352 /**
353 * Evaluate disturbing potential in geocentric coordinates.
354 *
355 * @param[in] X geocentric coordinate of point (meters).
356 * @param[in] Y geocentric coordinate of point (meters).
357 * @param[in] Z geocentric coordinate of point (meters).
358 * @return \e T = \e W - \e U the disturbing potential (also called the
359 * anomalous potential) (m<sup>2</sup> s<sup>&minus;2</sup>).
360 **********************************************************************/
361 Math::real T(real X, real Y, real Z) const {
362 real dummy;
363 return InternalT(X, Y, Z, dummy, dummy, dummy, false, true);
364 }
365
366 /**
367 * Evaluate the components of the acceleration due to normal gravity and
368 * the centrifugal acceleration in geocentric coordinates.
369 *
370 * @param[in] X geocentric coordinate of point (meters).
371 * @param[in] Y geocentric coordinate of point (meters).
372 * @param[in] Z geocentric coordinate of point (meters).
373 * @param[out] gammaX the \e X component of the normal acceleration
374 * (m s<sup>&minus;2</sup>).
375 * @param[out] gammaY the \e Y component of the normal acceleration
376 * (m s<sup>&minus;2</sup>).
377 * @param[out] gammaZ the \e Z component of the normal acceleration
378 * (m s<sup>&minus;2</sup>).
379 * @return \e U = <i>V</i><sub>0</sub> + &Phi; the sum of the
380 * normal gravitational and centrifugal potentials
381 * (m<sup>2</sup> s<sup>&minus;2</sup>).
382 *
383 * This calls NormalGravity::U for ReferenceEllipsoid().
384 **********************************************************************/
385 Math::real U(real X, real Y, real Z,
386 real& gammaX, real& gammaY, real& gammaZ) const
387 { return _earth.U(X, Y, Z, gammaX, gammaY, gammaZ); }
388
389 /**
390 * Evaluate the centrifugal acceleration in geocentric coordinates.
391 *
392 * @param[in] X geocentric coordinate of point (meters).
393 * @param[in] Y geocentric coordinate of point (meters).
394 * @param[out] fX the \e X component of the centrifugal acceleration
395 * (m s<sup>&minus;2</sup>).
396 * @param[out] fY the \e Y component of the centrifugal acceleration
397 * (m s<sup>&minus;2</sup>).
398 * @return &Phi; the centrifugal potential (m<sup>2</sup>
399 * s<sup>&minus;2</sup>).
400 *
401 * This calls NormalGravity::Phi for ReferenceEllipsoid().
402 **********************************************************************/
403 Math::real Phi(real X, real Y, real& fX, real& fY) const
404 { return _earth.Phi(X, Y, fX, fY); }
405 ///@}
406
407 /** \name Compute gravity on a circle of constant latitude
408 **********************************************************************/
409 ///@{
410 /**
411 * Create a GravityCircle object to allow the gravity field at many points
412 * with constant \e lat and \e h and varying \e lon to be computed
413 * efficiently.
414 *
415 * @param[in] lat latitude of the point (degrees).
416 * @param[in] h the height of the point above the ellipsoid (meters).
417 * @param[in] caps bitor'ed combination of GravityModel::mask values
418 * specifying the capabilities of the resulting GravityCircle object.
419 * @exception std::bad_alloc if the memory necessary for creating a
420 * GravityCircle can't be allocated.
421 * @return a GravityCircle object whose member functions computes the
422 * gravitational field at a particular values of \e lon.
423 *
424 * The GravityModel::mask values are
425 * - \e caps |= GravityModel::GRAVITY
426 * - \e caps |= GravityModel::DISTURBANCE
427 * - \e caps |= GravityModel::DISTURBING_POTENTIAL
428 * - \e caps |= GravityModel::SPHERICAL_ANOMALY
429 * - \e caps |= GravityModel::GEOID_HEIGHT
430 * .
431 * The default value of \e caps is GravityModel::ALL which turns on all the
432 * capabilities. If an unsupported function is invoked, it will return
433 * NaNs. Note that GravityModel::GEOID_HEIGHT will only be honored if \e h
434 * = 0.
435 *
436 * If the field at several points on a circle of latitude need to be
437 * calculated then creating a GravityCircle object and using its member
438 * functions will be substantially faster, especially for high-degree
439 * models. See \ref gravityparallel for an example of using GravityCircle
440 * (together with OpenMP) to speed up the computation of geoid heights.
441 **********************************************************************/
442 GravityCircle Circle(real lat, real h, unsigned caps = ALL) const;
443 ///@}
444
445 /** \name Inspector functions
446 **********************************************************************/
447 ///@{
448
449 /**
450 * @return the NormalGravity object for the reference ellipsoid.
451 **********************************************************************/
452 const NormalGravity& ReferenceEllipsoid() const { return _earth; }
453
454 /**
455 * @return the description of the gravity model, if available, in the data
456 * file; if absent, return "NONE".
457 **********************************************************************/
458 const std::string& Description() const { return _description; }
459
460 /**
461 * @return date of the model; if absent, return "UNKNOWN".
462 **********************************************************************/
463 const std::string& DateTime() const { return _date; }
464
465 /**
466 * @return full file name used to load the gravity model.
467 **********************************************************************/
468 const std::string& GravityFile() const { return _filename; }
469
470 /**
471 * @return "name" used to load the gravity model (from the first argument
472 * of the constructor, but this may be overridden by the model file).
473 **********************************************************************/
474 const std::string& GravityModelName() const { return _name; }
475
476 /**
477 * @return directory used to load the gravity model.
478 **********************************************************************/
479 const std::string& GravityModelDirectory() const { return _dir; }
480
481 /**
482 * @return \e a the equatorial radius of the ellipsoid (meters).
483 **********************************************************************/
484 Math::real EquatorialRadius() const { return _earth.EquatorialRadius(); }
485
486 /**
487 * @return \e GM the mass constant of the model (m<sup>3</sup>
488 * s<sup>&minus;2</sup>); this is the product of \e G the gravitational
489 * constant and \e M the mass of the earth (usually including the mass of
490 * the earth's atmosphere).
491 **********************************************************************/
492 Math::real MassConstant() const { return _gGMmodel; }
493
494 /**
495 * @return \e GM the mass constant of the ReferenceEllipsoid()
496 * (m<sup>3</sup> s<sup>&minus;2</sup>).
497 **********************************************************************/
499 { return _earth.MassConstant(); }
500
501 /**
502 * @return &omega; the angular velocity of the model and the
503 * ReferenceEllipsoid() (rad s<sup>&minus;1</sup>).
504 **********************************************************************/
506 { return _earth.AngularVelocity(); }
507
508 /**
509 * @return \e f the flattening of the ellipsoid.
510 **********************************************************************/
511 Math::real Flattening() const { return _earth.Flattening(); }
512
513 /**
514 * @return \e Nmax the maximum degree of the components of the model.
515 **********************************************************************/
516 int Degree() const { return _nmx; }
517
518 /**
519 * @return \e Mmax the maximum order of the components of the model.
520 **********************************************************************/
521 int Order() const { return _mmx; }
522 ///@}
523
524 /**
525 * @return the default path for gravity model data files.
526 *
527 * This is the value of the environment variable
528 * GEOGRAPHICLIB_GRAVITY_PATH, if set; otherwise, it is
529 * $GEOGRAPHICLIB_DATA/gravity if the environment variable
530 * GEOGRAPHICLIB_DATA is set; otherwise, it is a compile-time default
531 * (/usr/local/share/GeographicLib/gravity on non-Windows systems and
532 * C:/ProgramData/GeographicLib/gravity on Windows systems).
533 **********************************************************************/
534 static std::string DefaultGravityPath();
535
536 /**
537 * @return the default name for the gravity model.
538 *
539 * This is the value of the environment variable
540 * GEOGRAPHICLIB_GRAVITY_NAME, if set; otherwise, it is "egm96". The
541 * GravityModel class does not use this function; it is just provided as a
542 * convenience for a calling program when constructing a GravityModel
543 * object.
544 **********************************************************************/
545 static std::string DefaultGravityName();
546 };
547
548} // namespace GeographicLib
549
550#if defined(_MSC_VER)
551# pragma warning (pop)
552#endif
553
554#endif // GEOGRAPHICLIB_GRAVITYMODEL_HPP
Header for GeographicLib::Constants class.
#define GEOGRAPHICLIB_EXPORT
Definition Constants.hpp:67
GeographicLib::Math::real real
Definition GeodSolve.cpp:28
Header for GeographicLib::NormalGravity class.
Header for GeographicLib::SphericalHarmonic1 class.
Header for GeographicLib::SphericalHarmonic class.
Gravity on a circle of latitude.
Model of the earth's gravity field.
Math::real ReferenceMassConstant() const
Math::real Flattening() const
Math::real T(real X, real Y, real Z, real &deltaX, real &deltaY, real &deltaZ) const
Math::real MassConstant() const
const std::string & GravityModelName() const
const std::string & GravityModelDirectory() const
const std::string & GravityFile() const
GravityModel & operator=(GravityModel &&)=default
Math::real EquatorialRadius() const
Math::real Phi(real X, real Y, real &fX, real &fY) const
const std::string & Description() const
GravityModel(GravityModel &&)=default
const std::string & DateTime() const
Math::real U(real X, real Y, real Z, real &gammaX, real &gammaY, real &gammaZ) const
Math::real T(real X, real Y, real Z) const
Math::real AngularVelocity() const
const NormalGravity & ReferenceEllipsoid() const
The normal gravity of the earth.
Math::real EquatorialRadius() const
Math::real AngularVelocity() const
Math::real Phi(real X, real Y, real &fX, real &fY) const
Math::real MassConstant() const
Math::real U(real X, real Y, real Z, real &gammaX, real &gammaY, real &gammaZ) const
Spherical harmonic series with a correction to the coefficients.
Namespace for GeographicLib.