GeographicLib  1.21
SphericalHarmonic1.hpp
Go to the documentation of this file.
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