/* * This file is part of libcxxsupport. * * libcxxsupport is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * libcxxsupport is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with libcxxsupport; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* * libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt * (DLR). */ /*! \file wigner.h * Several C++ classes for calculating Wigner matrices * * Copyright (C) 2009,2010 Max-Planck-Society * \author Martin Reinecke and others (see individual classes) */ #ifndef PLANCK_WIGNER_H #define PLANCK_WIGNER_H #include #include "arr.h" #include "sse_utils.h" /*! Class for calculation of the Wigner matrix at pi/2, using Risbo recursion in a way that cannot easily be parallelised, but is fairly efficient on scalar machines. */ class wigner_d_halfpi_risbo_scalar { private: double pq; arr sqt; arr2 d; int n; void do_line0 (double *l1, int j); void do_line (const double *l1, double *l2, int j, int k); public: wigner_d_halfpi_risbo_scalar(int lmax); const arr2 &recurse (); }; /*! Class for calculation of the Wigner matrix at arbitrary angles, using Risbo recursion in a way that cannot easily be parallelised, but is fairly efficient on scalar machines. */ class wigner_d_risbo_scalar { private: double p,q; arr sqt; arr2 d; int n; void do_line0 (double *l1, int j); void do_line (const double *l1, double *l2, int j, int k); public: wigner_d_risbo_scalar(int lmax, double ang); const arr2 &recurse (); }; /*! Class for calculation of the Wigner matrix at pi/2, using Risbo recursion in a way that can be OpenMP-parallelised. This approach uses more memory and is slightly slower than wigner_d_halfpi_risbo_scalar. */ class wigner_d_halfpi_risbo_openmp { private: double pq; arr sqt; arr2 d,dd; int n; public: wigner_d_halfpi_risbo_openmp(int lmax); const arr2 &recurse (); }; /*! Class for calculation of the Wigner matrix at arbitrary angles, using Risbo recursion in a way that can be OpenMP-parallelised. This approach uses more memory and is slightly slower than wigner_d_risbo_scalar. */ class wigner_d_risbo_openmp { private: double p,q; arr sqt; arr2 d, dd; int n; public: wigner_d_risbo_openmp(int lmax, double ang); const arr2 &recurse (); }; /*! Class for calculation of the Wigner matrix elements by l-recursion. For details, see Prezeau & Reinecke 2010, http://arxiv.org/pdf/1002.1050 */ class wignergen { private: typedef double dbl3[3]; // members set in the constructor and kept fixed afterwards double fsmall, fbig, eps; int lmax; arr logsum, lc05, ls05; arr flm1, flm2, cf, costh, xl; arr thetaflip; // members depending on m and m' int m1, m2, am1, am2, mlo, mhi, cosPow, sinPow; long double prefactor; arr fx; bool preMinus; // members depending on theta arr result; #ifdef PLANCK_HAVE_SSE2 arr_align result2; #endif enum { large_exponent2=90, minscale=-4, maxscale=14 }; public: /*! Constructs an object that can compute Wigner matrix elements up to a maximum \a l value of \a lmax_, at the colatitudes provided in \a thetas. The generator will be allowed to regard values with absolute magnitudes smaller than \a epsilon as zero; a typical value is 1e-30. */ wignergen (int lmax_, const arr &thetas, double epsilon); /*! Prepares the object to produce Wigner matrix elements with \a m=m1_ and \a m'=m2_ in subsequent calls to calc(). This operation is not cheap so it is recommended to use calc() for many different colatitudes after every call to prepare(), if possible. */ void prepare (int m1_, int m2_); /*! Computes the Wigner matrix elements for the values of \a m and \a m' set by the preceding call to prepare(), for all \a l up to \a lmax (set in the constructor), and for the \a nth colatitude passed to the constructor. On return, \a firstl contains the index of the first matrix element larger than \a epsilon; all values with smaller indices in the result array are undefined. */ const arr &calc (int nth, int &firstl); #ifdef PLANCK_HAVE_SSE2 const arr_align &calc (int nth1, int nth2, int &firstl); #endif }; #endif