GeographicLib
1.21
|
00001 /** 00002 * \file SphericalHarmonic1.hpp 00003 * \brief Header for GeographicLib::SphericalHarmonic1 class 00004 * 00005 * Copyright (c) Charles Karney (2011) <charles@karney.com> and licensed under 00006 * the MIT/X11 License. For more information, see 00007 * http://geographiclib.sourceforge.net/ 00008 **********************************************************************/ 00009 00010 #if !defined(GEOGRAPHICLIB_SPHERICALHARMONIC1_HPP) 00011 #define GEOGRAPHICLIB_SPHERICALHARMONIC1_HPP \ 00012 "$Id: 9dd895ded08db0f7fdd82159399da511f40a17e1 $" 00013 00014 #include <vector> 00015 #include <GeographicLib/Constants.hpp> 00016 #include <GeographicLib/SphericalEngine.hpp> 00017 #include <GeographicLib/CircularEngine.hpp> 00018 00019 namespace GeographicLib { 00020 00021 /** 00022 * \brief Spherical Harmonic series with a correction to the coefficients. 00023 * 00024 * This classes is similar to SphericalHarmonic, except that the coefficients 00025 * \e C<sub>\e nm</sub> are replaced by \e C<sub>\e nm</sub> + \e tau 00026 * C'<sub>\e nm</sub> (and similarly for \e S<sub>\e nm</sub>). 00027 * 00028 * Example of use: 00029 * \include example-SphericalHarmonic1.cpp 00030 **********************************************************************/ 00031 00032 class GEOGRAPHIC_EXPORT SphericalHarmonic1 { 00033 public: 00034 /** 00035 * Supported normalizations for associate Legendre polynomials. 00036 **********************************************************************/ 00037 enum normalization { 00038 /** 00039 * Fully normalized associated Legendre polynomials. See 00040 * SphericalHarmonic::FULL for documentation. 00041 * 00042 * @hideinitializer 00043 **********************************************************************/ 00044 FULL = SphericalEngine::FULL, 00045 /** 00046 * Schmidt semi-normalized associated Legendre polynomials. See 00047 * SphericalHarmonic::SCHMIDT for documentation. 00048 * 00049 * @hideinitializer 00050 **********************************************************************/ 00051 SCHMIDT = SphericalEngine::SCHMIDT, 00052 /// \cond SKIP 00053 // These are deprecated... 00054 full = FULL, 00055 schmidt = SCHMIDT, 00056 /// \endcond 00057 }; 00058 00059 private: 00060 typedef Math::real real; 00061 SphericalEngine::coeff _c[2]; 00062 real _a; 00063 unsigned _norm; 00064 00065 public: 00066 /** 00067 * Constructor with a full set of coefficients specified. 00068 * 00069 * @param[in] C the coefficients \e C<sub>\e nm</sub>. 00070 * @param[in] S the coefficients \e S<sub>\e nm</sub>. 00071 * @param[in] N the maximum degree and order of the sum 00072 * @param[in] C1 the coefficients \e C'<sub>\e nm</sub>. 00073 * @param[in] S1 the coefficients \e S'<sub>\e nm</sub>. 00074 * @param[in] N1 the maximum degree and order of the correction 00075 * coefficients \e C'<sub>\e nm</sub> and \e S'<sub>\e nm</sub>. 00076 * @param[in] a the reference radius appearing in the definition of the 00077 * sum. 00078 * @param[in] norm the normalization for the associated Legendre 00079 * polynomials, either SphericalHarmonic1::FULL (the default) or 00080 * SphericalHarmonic1::SCHMIDT. 00081 * 00082 * See SphericalHarmonic for the way the coefficients should be stored. \e 00083 * N1 should satisfy \e N1 <= \e N. 00084 * 00085 * The class stores <i>pointers</i> to the first elements of \e C, \e S, \e 00086 * C', and \e S'. These arrays should not be altered or destroyed during 00087 * the lifetime of a SphericalHarmonic object. 00088 **********************************************************************/ 00089 SphericalHarmonic1(const std::vector<real>& C, 00090 const std::vector<real>& S, 00091 int N, 00092 const std::vector<real>& C1, 00093 const std::vector<real>& S1, 00094 int N1, 00095 real a, unsigned norm = FULL) 00096 : _a(a) 00097 , _norm(norm) { 00098 if (!(N1 <= N)) 00099 throw GeographicErr("N1 cannot be larger that N"); 00100 _c[0] = SphericalEngine::coeff(C, S, N); 00101 _c[1] = SphericalEngine::coeff(C1, S1, N1); 00102 } 00103 00104 /** 00105 * Constructor with a subset of coefficients specified. 00106 * 00107 * @param[in] C the coefficients \e C<sub>\e nm</sub>. 00108 * @param[in] S the coefficients \e S<sub>\e nm</sub>. 00109 * @param[in] N the degree used to determine the layout of \e C and \e S. 00110 * @param[in] nmx the maximum degree used in the sum. The sum over \e n is 00111 * from 0 thru \e nmx. 00112 * @param[in] mmx the maximum order used in the sum. The sum over \e m is 00113 * from 0 thru min(\e n, \e mmx). 00114 * @param[in] C1 the coefficients \e C'<sub>\e nm</sub>. 00115 * @param[in] S1 the coefficients \e S'<sub>\e nm</sub>. 00116 * @param[in] N1 the degree used to determine the layout of \e C' and \e 00117 * S'. 00118 * @param[in] nmx1 the maximum degree used for \e C' and \e S'. 00119 * @param[in] mmx1 the maximum order used for \e C' and \e S'. 00120 * @param[in] a the reference radius appearing in the definition of the 00121 * sum. 00122 * @param[in] norm the normalization for the associated Legendre 00123 * polynomials, either SphericalHarmonic1::FULL (the default) or 00124 * SphericalHarmonic1::SCHMIDT. 00125 * 00126 * The class stores <i>pointers</i> to the first elements of \e C, \e S, \e 00127 * C', and \e S'. These arrays should not be altered or destroyed during 00128 * the lifetime of a SphericalHarmonic object. 00129 **********************************************************************/ 00130 SphericalHarmonic1(const std::vector<real>& C, 00131 const std::vector<real>& S, 00132 int N, int nmx, int mmx, 00133 const std::vector<real>& C1, 00134 const std::vector<real>& S1, 00135 int N1, int nmx1, int mmx1, 00136 real a, unsigned norm = FULL) 00137 : _a(a) 00138 , _norm(norm) { 00139 if (!(nmx1 <= nmx)) 00140 throw GeographicErr("nmx1 cannot be larger that nmx"); 00141 if (!(mmx1 <= mmx)) 00142 throw GeographicErr("mmx1 cannot be larger that mmx"); 00143 _c[0] = SphericalEngine::coeff(C, S, N, nmx, mmx); 00144 _c[1] = SphericalEngine::coeff(C1, S1, N1, nmx1, mmx1); 00145 } 00146 00147 /** 00148 * A default constructor so that the object can be created when the 00149 * constructor for another object is initialized. This default object can 00150 * then be reset with the default copy assignment operator. 00151 **********************************************************************/ 00152 SphericalHarmonic1() {} 00153 00154 /** 00155 * Compute a spherical harmonic sum with a correction term. 00156 * 00157 * @param[in] tau multiplier for correction coefficients \e C' and \e S'. 00158 * @param[in] x cartesian coordinate. 00159 * @param[in] y cartesian coordinate. 00160 * @param[in] z cartesian coordinate. 00161 * @return \e V the spherical harmonic sum. 00162 * 00163 * This routine requires constant memory and thus never throws 00164 * an exception. 00165 **********************************************************************/ 00166 Math::real operator()(real tau, real x, real y, real z) const throw() { 00167 real f[] = {1, tau}; 00168 real v = 0; 00169 real dummy; 00170 switch (_norm) { 00171 case FULL: 00172 v = SphericalEngine::Value<false, SphericalEngine::FULL, 2> 00173 (_c, f, x, y, z, _a, dummy, dummy, dummy); 00174 break; 00175 case SCHMIDT: 00176 v = SphericalEngine::Value<false, SphericalEngine::SCHMIDT, 2> 00177 (_c, f, x, y, z, _a, dummy, dummy, dummy); 00178 break; 00179 } 00180 return v; 00181 } 00182 00183 /** 00184 * Compute a spherical harmonic sum with a correction term and its 00185 * gradient. 00186 * 00187 * @param[in] tau multiplier for correction coefficients \e C' and \e S'. 00188 * @param[in] x cartesian coordinate. 00189 * @param[in] y cartesian coordinate. 00190 * @param[in] z cartesian coordinate. 00191 * @param[out] gradx \e x component of the gradient 00192 * @param[out] grady \e y component of the gradient 00193 * @param[out] gradz \e z component of the gradient 00194 * @return \e V the spherical harmonic sum. 00195 * 00196 * This is the same as the previous function, except that the components of 00197 * the gradients of the sum in the \e x, \e y, and \e z directions are 00198 * computed. This routine requires constant memory and thus never throws 00199 * an exception. 00200 **********************************************************************/ 00201 Math::real operator()(real tau, real x, real y, real z, 00202 real& gradx, real& grady, real& gradz) const throw() { 00203 real f[] = {1, tau}; 00204 real v = 0; 00205 switch (_norm) { 00206 case FULL: 00207 v = SphericalEngine::Value<true, SphericalEngine::FULL, 2> 00208 (_c, f, x, y, z, _a, gradx, grady, gradz); 00209 break; 00210 case SCHMIDT: 00211 v = SphericalEngine::Value<true, SphericalEngine::SCHMIDT, 2> 00212 (_c, f, x, y, z, _a, gradx, grady, gradz); 00213 break; 00214 } 00215 return v; 00216 } 00217 00218 /** 00219 * Create a CircularEngine to allow the efficient evaluation of several 00220 * points on a circle of latitude at a fixed value of \e tau. 00221 * 00222 * @param[in] tau the multiplier for the correction coefficients. 00223 * @param[in] p the radius of the circle. 00224 * @param[in] z the height of the circle above the equatorial plane. 00225 * @param[in] gradp if true the returned object will be able to compute the 00226 * gradient of the sum. 00227 * @return the CircularEngine object. 00228 * 00229 * SphericalHarmonic1::operator()() exchanges the order of the sums in the 00230 * definition, i.e., sum(n = 0..N)[sum(m = 0..n)[...]] becomes sum(m = 00231 * 0..N)[sum(n = m..N)[...]]. SphericalHarmonic1::Circle performs the 00232 * inner sum over degree \e n (which entails about <i>N</i><sup>2</sup> 00233 * operations). Calling CircularEngine::operator()() on the returned 00234 * object performs the outer sum over the order \e m (about \e N 00235 * operations). This routine may throw a bad_alloc exception in the 00236 * CircularEngine constructor. 00237 * 00238 * See SphericalHarmonic::Circle for an example of its use. 00239 **********************************************************************/ 00240 CircularEngine Circle(real tau, real p, real z, bool gradp) const { 00241 real f[] = {1, tau}; 00242 switch (_norm) { 00243 case FULL: 00244 return gradp ? 00245 SphericalEngine::Circle<true, SphericalEngine::FULL, 2> 00246 (_c, f, p, z, _a) : 00247 SphericalEngine::Circle<false, SphericalEngine::FULL, 2> 00248 (_c, f, p, z, _a); 00249 break; 00250 case SCHMIDT: 00251 default: // To avoid compiler warnings 00252 return gradp ? 00253 SphericalEngine::Circle<true, SphericalEngine::SCHMIDT, 2> 00254 (_c, f, p, z, _a) : 00255 SphericalEngine::Circle<false, SphericalEngine::SCHMIDT, 2> 00256 (_c, f, p, z, _a); 00257 break; 00258 } 00259 } 00260 00261 /** 00262 * @return the zeroth SphericalEngine::coeff object. 00263 **********************************************************************/ 00264 const SphericalEngine::coeff& Coefficients() const throw() 00265 { return _c[0]; } 00266 /** 00267 * @return the first SphericalEngine::coeff object. 00268 **********************************************************************/ 00269 const SphericalEngine::coeff& Coefficients1() const throw() 00270 { return _c[1]; } 00271 }; 00272 00273 } // namespace GeographicLib 00274 00275 #endif // GEOGRAPHICLIB_SPHERICALHARMONIC1_HPP