wigner.h

Go to the documentation of this file.
00001 /*
00002  *  This file is part of libcxxsupport.
00003  *
00004  *  libcxxsupport is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  libcxxsupport is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with libcxxsupport; if not, write to the Free Software
00016  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00017  */
00018 
00019 /*
00020  *  libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
00021  *  and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
00022  *  (DLR).
00023  */
00024 
00025 /*! \file wigner.h
00026  *  Several C++ classes for calculating Wigner matrices
00027  *
00028  *  Copyright (C) 2009-2011 Max-Planck-Society
00029  *  \author Martin Reinecke and others (see individual classes)
00030  */
00031 
00032 #ifndef PLANCK_WIGNER_H
00033 #define PLANCK_WIGNER_H
00034 
00035 #include <cmath>
00036 #include "arr.h"
00037 
00038 #include "sse_utils_cxx.h"
00039 
00040 /*! Class for calculation of the Wigner matrix at pi/2, using Risbo recursion
00041     in a way that cannot easily be parallelised, but is fairly efficient on
00042     scalar machines. */
00043 class wigner_d_halfpi_risbo_scalar
00044   {
00045   private:
00046     double pq;
00047     arr<double> sqt;
00048     arr2<double> d;
00049     int n;
00050 
00051     void do_line0 (double *l1, int j);
00052     void do_line (const double *l1, double *l2, int j, int k);
00053 
00054   public:
00055     wigner_d_halfpi_risbo_scalar(int lmax);
00056 
00057     const arr2<double> &recurse ();
00058   };
00059 
00060 /*! Class for calculation of the Wigner matrix at arbitrary angles, using Risbo
00061     recursion in a way that cannot easily be parallelised, but is fairly
00062     efficient on scalar machines. */
00063 class wigner_d_risbo_scalar
00064   {
00065   private:
00066     double p,q;
00067     arr<double> sqt;
00068     arr2<double> d;
00069     int n;
00070 
00071     void do_line0 (double *l1, int j);
00072     void do_line (const double *l1, double *l2, int j, int k);
00073 
00074   public:
00075     wigner_d_risbo_scalar(int lmax, double ang);
00076 
00077     const arr2<double> &recurse ();
00078   };
00079 
00080 /*! Class for calculation of the Wigner matrix at pi/2, using Risbo recursion
00081     in a way that can be OpenMP-parallelised. This approach uses more memory
00082     and is slightly slower than wigner_d_halfpi_risbo_scalar. */
00083 class wigner_d_halfpi_risbo_openmp
00084   {
00085   private:
00086     double pq;
00087     arr<double> sqt;
00088     arr2<double> d,dd;
00089     int n;
00090 
00091   public:
00092     wigner_d_halfpi_risbo_openmp(int lmax);
00093 
00094     const arr2<double> &recurse ();
00095   };
00096 
00097 /*! Class for calculation of the Wigner matrix at arbitrary angles, using Risbo
00098     recursion in a way that can be OpenMP-parallelised. This approach uses more
00099     memory and is slightly slower than wigner_d_risbo_scalar. */
00100 class wigner_d_risbo_openmp
00101   {
00102   private:
00103     double p,q;
00104     arr<double> sqt;
00105     arr2<double> d, dd;
00106     int n;
00107 
00108   public:
00109     wigner_d_risbo_openmp(int lmax, double ang);
00110 
00111     const arr2<double> &recurse ();
00112   };
00113 
00114 /*! Class for calculation of the Wigner matrix elements by l-recursion.
00115     For details, see Prezeau & Reinecke 2010, http://arxiv.org/pdf/1002.1050 */
00116 class wignergen_scalar
00117   {
00118   protected:
00119     typedef double dbl3[3];
00120 
00121     // members set in the constructor and kept fixed afterwards
00122     double fsmall, fbig, eps;
00123     int lmax;
00124     arr<long double> logsum, lc05, ls05;
00125     arr<double> flm1, flm2, cf, costh, xl;
00126     arr<bool> thetaflip;
00127 
00128     // members depending on m and m'
00129     int m1, m2, am1, am2, mlo, mhi, cosPow, sinPow;
00130     long double prefactor;
00131     arr<dbl3> fx;
00132     bool preMinus;
00133 
00134     // members depending on theta
00135     arr<double> result;
00136 
00137     enum { large_exponent2=90, minscale=-4, maxscale=14 };
00138 
00139   public:
00140     /*! Constructs an object that can compute Wigner matrix elements up
00141         to a maximum \a l value of \a lmax_, at the colatitudes provided
00142         in \a thetas. The generator will be allowed to regard values with
00143         absolute magnitudes smaller than \a epsilon as zero; a typical value
00144         is 1e-30. */
00145     wignergen_scalar (int lmax_, const arr<double> &thetas, double epsilon);
00146 
00147     /*! Prepares the object to produce Wigner matrix elements with \a m=m1_
00148         and \a m'=m2_ in subsequent calls to calc(). This operation is not cheap
00149         so it is recommended to use calc() for many different colatitudes after
00150         every call to prepare(), if possible. */
00151     void prepare (int m1_, int m2_);
00152 
00153     /*! Computes the Wigner matrix elements for the values of \a m and \a m'
00154         set by the preceding call to prepare(), for all \a l up to \a lmax
00155         (set in the constructor), and for the \a nth colatitude passed to the
00156         constructor. On return, \a firstl contains the index of the first
00157         matrix element larger than \a epsilon; all values with smaller indices
00158         in the result array are undefined. */
00159     const arr<double> &calc (int nth, int &firstl);
00160     void calc (int nth, int &firstl, arr<double> &resx) const;
00161   };
00162 
00163 class wignergen: public wignergen_scalar
00164   {
00165 #ifdef __SSE2__
00166   private:
00167     arr_align<V2df,16> result2;
00168 
00169   public:
00170     wignergen (int lmax_, const arr<double> &thetas, double epsilon)
00171       : wignergen_scalar (lmax_,thetas,epsilon), result2(lmax_+1) {}
00172 
00173     using wignergen_scalar::calc;
00174     const arr_align<V2df,16> &calc (int nth1, int nth2, int &firstl);
00175     void calc (int nth1, int nth2, int &firstl, arr_align<V2df,16> &resx) const;
00176 #else
00177   public:
00178     wignergen (int lmax_, const arr<double> &thetas, double epsilon)
00179       : wignergen_scalar (lmax_,thetas,epsilon) {}
00180 #endif
00181   };
00182 
00183 class wigner_estimator
00184   {
00185   private:
00186     int lmax, m1, m2, mbig;
00187     double xlmax, epsPow, cosm1m2;
00188 
00189   public:
00190     wigner_estimator (int lmax_, double epsPow_);
00191 
00192     void prepare_m (int m1_, int m2_);
00193     bool canSkip (double theta) const;
00194   };
00195 
00196 #endif

Generated on Thu Oct 8 14:48:51 2015 for LevelS C++ support library