GeographicLib  1.35
SphericalHarmonic2.hpp
Go to the documentation of this file.
1 /**
2  * \file SphericalHarmonic2.hpp
3  * \brief Header for GeographicLib::SphericalHarmonic2 class
4  *
5  * Copyright (c) Charles Karney (2011-2012) <charles@karney.com> and licensed
6  * under the MIT/X11 License. For more information, see
7  * http://geographiclib.sourceforge.net/
8  **********************************************************************/
9 
10 #if !defined(GEOGRAPHICLIB_SPHERICALHARMONIC2_HPP)
11 #define GEOGRAPHICLIB_SPHERICALHARMONIC2_HPP 1
12 
13 #include <vector>
17 
18 namespace GeographicLib {
19 
20  /**
21  * \brief Spherical harmonic series with two corrections to the coefficients
22  *
23  * This classes is similar to SphericalHarmonic, except that the coefficients
24  * \e C<sub>\e nm</sub> are replaced by \e C<sub>\e nm</sub> + \e tau'
25  * C'<sub>\e nm</sub> + \e tau'' C''<sub>\e nm</sub> (and similarly for \e
26  * S<sub>\e nm</sub>).
27  *
28  * Example of use:
29  * \include example-SphericalHarmonic2.cpp
30  **********************************************************************/
31 
32  // Don't include the GEOGRPAHIC_EXPORT because this header-only class isn't
33  // used by any other classes in the library.
34  class /*GEOGRAPHICLIB_EXPORT*/ SphericalHarmonic2 {
35  public:
36  /**
37  * Supported normalizations for associate Legendre polynomials.
38  **********************************************************************/
40  /**
41  * Fully normalized associated Legendre polynomials. See
42  * SphericalHarmonic::FULL for documentation.
43  *
44  * @hideinitializer
45  **********************************************************************/
47  /**
48  * Schmidt semi-normalized associated Legendre polynomials. See
49  * SphericalHarmonic::SCHMIDT for documentation.
50  *
51  * @hideinitializer
52  **********************************************************************/
54  /// \cond SKIP
55  // These are deprecated...
56  full = FULL,
57  schmidt = SCHMIDT,
58  /// \endcond
59  };
60 
61  private:
62  typedef Math::real real;
64  real _a;
65  unsigned _norm;
66 
67  public:
68  /**
69  * Constructor with a full set of coefficients specified.
70  *
71  * @param[in] C the coefficients \e C<sub>\e nm</sub>.
72  * @param[in] S the coefficients \e S<sub>\e nm</sub>.
73  * @param[in] N the maximum degree and order of the sum
74  * @param[in] C1 the coefficients \e C'<sub>\e nm</sub>.
75  * @param[in] S1 the coefficients \e S'<sub>\e nm</sub>.
76  * @param[in] N1 the maximum degree and order of the first correction
77  * coefficients \e C'<sub>\e nm</sub> and \e S'<sub>\e nm</sub>.
78  * @param[in] C2 the coefficients \e C''<sub>\e nm</sub>.
79  * @param[in] S2 the coefficients \e S''<sub>\e nm</sub>.
80  * @param[in] N2 the maximum degree and order of the second correction
81  * coefficients \e C'<sub>\e nm</sub> and \e S'<sub>\e nm</sub>.
82  * @param[in] a the reference radius appearing in the definition of the
83  * sum.
84  * @param[in] norm the normalization for the associated Legendre
85  * polynomials, either SphericalHarmonic2::FULL (the default) or
86  * SphericalHarmonic2::SCHMIDT.
87  * @exception GeographicErr if \e N and \e N1 do not satisfy \e N &ge;
88  * \e N1 &ge; &minus;1, and similarly for \e N2.
89  * @exception GeographicErr if any of the vectors of coefficients is not
90  * large enough.
91  *
92  * See SphericalHarmonic for the way the coefficients should be stored. \e
93  * N1 and \e N2 should satisfy \e N1 &le; \e N and \e N2 &le; \e N.
94  *
95  * The class stores <i>pointers</i> to the first elements of \e C, \e S, \e
96  * C', \e S', \e C'', and \e S''. These arrays should not be altered or
97  * destroyed during the lifetime of a SphericalHarmonic object.
98  **********************************************************************/
99  SphericalHarmonic2(const std::vector<real>& C,
100  const std::vector<real>& S,
101  int N,
102  const std::vector<real>& C1,
103  const std::vector<real>& S1,
104  int N1,
105  const std::vector<real>& C2,
106  const std::vector<real>& S2,
107  int N2,
108  real a, unsigned norm = FULL)
109  : _a(a)
110  , _norm(norm) {
111  if (!(N1 <= N && N2 <= N))
112  throw GeographicErr("N1 and N2 cannot be larger that N");
113  _c[0] = SphericalEngine::coeff(C, S, N);
114  _c[1] = SphericalEngine::coeff(C1, S1, N1);
115  _c[2] = SphericalEngine::coeff(C2, S2, N2);
116  }
117 
118  /**
119  * Constructor with a subset of coefficients specified.
120  *
121  * @param[in] C the coefficients \e C<sub>\e nm</sub>.
122  * @param[in] S the coefficients \e S<sub>\e nm</sub>.
123  * @param[in] N the degree used to determine the layout of \e C and \e S.
124  * @param[in] nmx the maximum degree used in the sum. The sum over \e n is
125  * from 0 thru \e nmx.
126  * @param[in] mmx the maximum order used in the sum. The sum over \e m is
127  * from 0 thru min(\e n, \e mmx).
128  * @param[in] C1 the coefficients \e C'<sub>\e nm</sub>.
129  * @param[in] S1 the coefficients \e S'<sub>\e nm</sub>.
130  * @param[in] N1 the degree used to determine the layout of \e C' and \e
131  * S'.
132  * @param[in] nmx1 the maximum degree used for \e C' and \e S'.
133  * @param[in] mmx1 the maximum order used for \e C' and \e S'.
134  * @param[in] C2 the coefficients \e C''<sub>\e nm</sub>.
135  * @param[in] S2 the coefficients \e S''<sub>\e nm</sub>.
136  * @param[in] N2 the degree used to determine the layout of \e C'' and \e
137  * S''.
138  * @param[in] nmx2 the maximum degree used for \e C'' and \e S''.
139  * @param[in] mmx2 the maximum order used for \e C'' and \e S''.
140  * @param[in] a the reference radius appearing in the definition of the
141  * sum.
142  * @param[in] norm the normalization for the associated Legendre
143  * polynomials, either SphericalHarmonic2::FULL (the default) or
144  * SphericalHarmonic2::SCHMIDT.
145  * @exception GeographicErr if the parameters do not satisfy \e N &ge; \e
146  * nmx &ge; \e mmx &ge; &minus;1; \e N1 &ge; \e nmx1 &ge; \e mmx1 &ge;
147  * &minus;1; \e N &ge; \e N1; \e nmx &ge; \e nmx1; \e mmx &ge; \e mmx1;
148  * and similarly for \e N2, \e nmx2, and \e mmx2.
149  * @exception GeographicErr if any of the vectors of coefficients is not
150  * large enough.
151  *
152  * The class stores <i>pointers</i> to the first elements of \e C, \e S, \e
153  * C', \e S', \e C'', and \e S''. These arrays should not be altered or
154  * destroyed during the lifetime of a SphericalHarmonic object.
155  **********************************************************************/
156  SphericalHarmonic2(const std::vector<real>& C,
157  const std::vector<real>& S,
158  int N, int nmx, int mmx,
159  const std::vector<real>& C1,
160  const std::vector<real>& S1,
161  int N1, int nmx1, int mmx1,
162  const std::vector<real>& C2,
163  const std::vector<real>& S2,
164  int N2, int nmx2, int mmx2,
165  real a, unsigned norm = FULL)
166  : _a(a)
167  , _norm(norm) {
168  if (!(nmx1 <= nmx && nmx2 <= nmx))
169  throw GeographicErr("nmx1 and nmx2 cannot be larger that nmx");
170  if (!(mmx1 <= mmx && mmx2 <= mmx))
171  throw GeographicErr("mmx1 and mmx2 cannot be larger that mmx");
172  _c[0] = SphericalEngine::coeff(C, S, N, nmx, mmx);
173  _c[1] = SphericalEngine::coeff(C1, S1, N1, nmx1, mmx1);
174  _c[2] = SphericalEngine::coeff(C2, S2, N2, nmx2, mmx2);
175  }
176 
177  /**
178  * A default constructor so that the object can be created when the
179  * constructor for another object is initialized. This default object can
180  * then be reset with the default copy assignment operator.
181  **********************************************************************/
183 
184  /**
185  * Compute a spherical harmonic sum with two correction terms.
186  *
187  * @param[in] tau1 multiplier for correction coefficients \e C' and \e S'.
188  * @param[in] tau2 multiplier for correction coefficients \e C'' and \e S''.
189  * @param[in] x cartesian coordinate.
190  * @param[in] y cartesian coordinate.
191  * @param[in] z cartesian coordinate.
192  * @return \e V the spherical harmonic sum.
193  *
194  * This routine requires constant memory and thus never throws an
195  * exception.
196  **********************************************************************/
197  Math::real operator()(real tau1, real tau2, real x, real y, real z)
198  const throw() {
199  real f[] = {1, tau1, tau2};
200  real v = 0;
201  real dummy;
202  switch (_norm) {
203  case FULL:
204  v = SphericalEngine::Value<false, SphericalEngine::FULL, 3>
205  (_c, f, x, y, z, _a, dummy, dummy, dummy);
206  break;
207  case SCHMIDT:
208  v = SphericalEngine::Value<false, SphericalEngine::SCHMIDT, 3>
209  (_c, f, x, y, z, _a, dummy, dummy, dummy);
210  break;
211  }
212  return v;
213  }
214 
215  /**
216  * Compute a spherical harmonic sum with two correction terms and its
217  * gradient.
218  *
219  * @param[in] tau1 multiplier for correction coefficients \e C' and \e S'.
220  * @param[in] tau2 multiplier for correction coefficients \e C'' and \e S''.
221  * @param[in] x cartesian coordinate.
222  * @param[in] y cartesian coordinate.
223  * @param[in] z cartesian coordinate.
224  * @param[out] gradx \e x component of the gradient
225  * @param[out] grady \e y component of the gradient
226  * @param[out] gradz \e z component of the gradient
227  * @return \e V the spherical harmonic sum.
228  *
229  * This is the same as the previous function, except that the components of
230  * the gradients of the sum in the \e x, \e y, and \e z directions are
231  * computed. This routine requires constant memory and thus never throws
232  * an exception.
233  **********************************************************************/
234  Math::real operator()(real tau1, real tau2, real x, real y, real z,
235  real& gradx, real& grady, real& gradz) const throw() {
236  real f[] = {1, tau1, tau2};
237  real v = 0;
238  switch (_norm) {
239  case FULL:
240  v = SphericalEngine::Value<true, SphericalEngine::FULL, 3>
241  (_c, f, x, y, z, _a, gradx, grady, gradz);
242  break;
243  case SCHMIDT:
244  v = SphericalEngine::Value<true, SphericalEngine::SCHMIDT, 3>
245  (_c, f, x, y, z, _a, gradx, grady, gradz);
246  break;
247  }
248  return v;
249  }
250 
251  /**
252  * Create a CircularEngine to allow the efficient evaluation of several
253  * points on a circle of latitude at fixed values of \e tau1 and \e tau2.
254  *
255  * @param[in] tau1 multiplier for correction coefficients \e C' and \e S'.
256  * @param[in] tau2 multiplier for correction coefficients \e C'' and \e S''.
257  * @param[in] p the radius of the circle.
258  * @param[in] z the height of the circle above the equatorial plane.
259  * @param[in] gradp if true the returned object will be able to compute the
260  * gradient of the sum.
261  * @exception std::bad_alloc if the memory for the CircularEngine can't be
262  * allocated.
263  * @return the CircularEngine object.
264  *
265  * SphericalHarmonic2::operator()() exchanges the order of the sums in the
266  * definition, i.e., &sum;<sub>n = 0..N</sub> &sum;<sub>m = 0..n</sub>
267  * becomes &sum;<sub>m = 0..N</sub> &sum;<sub>n = m..N</sub>..
268  * SphericalHarmonic2::Circle performs the inner sum over degree \e n
269  * (which entails about <i>N</i><sup>2</sup> operations). Calling
270  * CircularEngine::operator()() on the returned object performs the outer
271  * sum over the order \e m (about \e N operations).
272  *
273  * See SphericalHarmonic::Circle for an example of its use.
274  **********************************************************************/
275  CircularEngine Circle(real tau1, real tau2, real p, real z, bool gradp)
276  const {
277  real f[] = {1, tau1, tau2};
278  switch (_norm) {
279  case FULL:
280  return gradp ?
281  SphericalEngine::Circle<true, SphericalEngine::FULL, 3>
282  (_c, f, p, z, _a) :
283  SphericalEngine::Circle<false, SphericalEngine::FULL, 3>
284  (_c, f, p, z, _a);
285  break;
286  case SCHMIDT:
287  default: // To avoid compiler warnings
288  return gradp ?
289  SphericalEngine::Circle<true, SphericalEngine::SCHMIDT, 3>
290  (_c, f, p, z, _a) :
291  SphericalEngine::Circle<false, SphericalEngine::SCHMIDT, 3>
292  (_c, f, p, z, _a);
293  break;
294  }
295  }
296 
297  /**
298  * @return the zeroth SphericalEngine::coeff object.
299  **********************************************************************/
300  const SphericalEngine::coeff& Coefficients() const throw()
301  { return _c[0]; }
302  /**
303  * @return the first SphericalEngine::coeff object.
304  **********************************************************************/
305  const SphericalEngine::coeff& Coefficients1() const throw()
306  { return _c[1]; }
307  /**
308  * @return the second SphericalEngine::coeff object.
309  **********************************************************************/
310  const SphericalEngine::coeff& Coefficients2() const throw()
311  { return _c[2]; }
312  };
313 
314 } // namespace GeographicLib
315 
316 #endif // GEOGRAPHICLIB_SPHERICALHARMONIC2_HPP
GeographicLib::Math::real real
Definition: GeodSolve.cpp:40
Package up coefficients for SphericalEngine.
const SphericalEngine::coeff & Coefficients1() const
const SphericalEngine::coeff & Coefficients2() const
Spherical harmonic series with two corrections to the coefficients.
CircularEngine Circle(real tau1, real tau2, real p, real z, bool gradp) const
SphericalHarmonic2(const std::vector< real > &C, const std::vector< real > &S, int N, int nmx, int mmx, const std::vector< real > &C1, const std::vector< real > &S1, int N1, int nmx1, int mmx1, const std::vector< real > &C2, const std::vector< real > &S2, int N2, int nmx2, int mmx2, real a, unsigned norm=FULL)
Header for GeographicLib::CircularEngine class.
Spherical harmonic sums for a circle.
Exception handling for GeographicLib.
Definition: Constants.hpp:320
Header for GeographicLib::Constants class.
SphericalHarmonic2(const std::vector< real > &C, const std::vector< real > &S, int N, const std::vector< real > &C1, const std::vector< real > &S1, int N1, const std::vector< real > &C2, const std::vector< real > &S2, int N2, real a, unsigned norm=FULL)
Header for GeographicLib::SphericalEngine class.
Math::real operator()(real tau1, real tau2, real x, real y, real z, real &gradx, real &grady, real &gradz) const
const SphericalEngine::coeff & Coefficients() const
Math::real operator()(real tau1, real tau2, real x, real y, real z) const