From b235ba3004e7581fe543d9ce89d643a58bc0ae2f Mon Sep 17 00:00:00 2001 From: Joey Dumont Date: Sun, 10 Nov 2013 14:07:48 -0500 Subject: [PATCH] Remove test files. --- src/fortranLinkage.h | 10 - src/testWigner.cpp | 221 ----------- src/wignerSymbols.cpp | 463 ---------------------- src/wignerSymbols.f | 867 ------------------------------------------ src/wignerSymbols.h | 166 -------- src/wignerTest.f90 | 11 - src/wigner_wrap.f90 | 51 --- 7 files changed, 1789 deletions(-) delete mode 100644 src/fortranLinkage.h delete mode 100644 src/testWigner.cpp delete mode 100644 src/wignerSymbols.cpp delete mode 100644 src/wignerSymbols.f delete mode 100644 src/wignerSymbols.h delete mode 100644 src/wignerTest.f90 delete mode 100644 src/wigner_wrap.f90 diff --git a/src/fortranLinkage.h b/src/fortranLinkage.h deleted file mode 100644 index be4973e..0000000 --- a/src/fortranLinkage.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef FORTRANLINKAGE_H -#define FORTRANLINKAGE_H - -extern "C" -{ - extern void drc3jj_wrap(double,double,double,double,double*,double*,double*,int,int*); - extern void drc6j_wrap(double,double,double,double,double*,double*,double*,int,int*); -} - -#endif // FORTRANLINKAGE_H \ No newline at end of file diff --git a/src/testWigner.cpp b/src/testWigner.cpp deleted file mode 100644 index 5cb7d94..0000000 --- a/src/testWigner.cpp +++ /dev/null @@ -1,221 +0,0 @@ -#include "wignerSymbols.h" - -#include -#include -#include -#include - -#define EPS 1.0e-10 - -using namespace std; -using namespace arma; - -// This is a test. -// Orthogonality relations and sum rules for the 3j symbols [Brink & Satchler, pp. 136+139]. -double firstOrthoRelation3j(double l1, double l2, double l3, double m3); -double sumOverM23j(double l1, double l2, double l3, double m3); - -// Orthogonality relations for the 6j symbols [Brink & Satchler pp. 142-3]. -double firstSumOverL3(double l1, double l2, double l6); -double seconSumOverL3(double l1, double l2, double l6); - -// Timing computation of Wigner symbols. -double timingWignerSymbols(double l2, double l3, double m1, double m2, double m3); -double timingWignerSymbolsF(double l2, double l3, double m1, double m2, double m3); - -int main(int argc, char* argv[]) -{ - // We time the computation for different sizes. - int N = 500; - double l2(500.0),m1(-10.0),m2(60.0),m3(-50.0); - mat times(N,2); - mat timesF(N,2); - - for (int i=0;i::max(); - double srhuge = sqrt(huge); - double tiny = std::numeric_limits::min(); - double srtiny = sqrt(tiny); - double eps = std::numeric_limits::epsilon(); - - // We enforce the selection rules. - bool select(true); - select = ( - std::fabs(m1+m2+m3)(1); - - // We compute the limits of l1. - double l1min = std::max(std::fabs(l2-l3),std::fabs(m1)); - double l1max = l2+l3; - - // We compute the size of the resulting array. - int size = (int)std::floor(l1max-l1min+1.0+eps); - arma::colvec thrcof(size); - - // If l1min=l1max, we have an analytical formula. - if (size==1) - { - thrcof(0) = pow(-1.0,std::floor(std::fabs(l2+m2-l3+m3)))/sqrt(l1min+l2+l3+1.0); - } - - // Another special case where the recursion relation fails. - else - { - // We start with an arbitrary value. - thrcof(0) = srtiny; - - // From now on, we check the variation of |alpha(l1)|. - double alphaOld, alphaNew, beta, l1(l1min); - if (l1min==0.0) - alphaNew = -(m3-m2+2.0*c_wigner3j_auxB(l1,l2,l3,m1,m2,m3))/c_wigner3j_auxA(1.0,l2,l3,m1,m2,m3); - else - alphaNew = -c_wigner3j_auxB(l1min,l2,l3,m1,m2,m3) - /(l1min*c_wigner3j_auxA(l1min+1.0,l2,l3,m1,m2,m3)); - - // We compute the two-term recursion. - thrcof(1) = alphaNew*thrcof(0); - - // If size > 2, we start the forward recursion. - if (size>2) - { - // We start with an arbitrary value. - thrcof(0) = srtiny; - - // From now on, we check the variation of |alpha(l1)|. - double alphaOld, alphaNew, beta, l1(l1min); - if (l1min==0.0) - alphaNew = -(m3-m2+2.0*c_wigner3j_auxB(l1,l2,l3,m1,m2,m3))/c_wigner3j_auxA(1.0,l2,l3,m1,m2,m3); - else - alphaNew = -c_wigner3j_auxB(l1min,l2,l3,m1,m2,m3) - /(l1min*c_wigner3j_auxA(l1min+1.0,l2,l3,m1,m2,m3)); - - // We compute the two-term recursion. - thrcof(1) = alphaNew*thrcof(0); - - // We compute the rest of the recursion. - int i = 1; - bool alphaVar = false; - do - { - // Bookkeeping: - i++; // Next term in recursion - alphaOld = alphaNew; // Monitoring of |alpha(l1)|. - l1 += 1.0; // l1 = l1+1 - - // New coefficients in recursion. - alphaNew = -c_wigner3j_auxB(l1,l2,l3,m1,m2,m3) - /(l1*c_wigner3j_auxA(l1+1.0,l2,l3,m1,m2,m3)); - - beta = -(l1+1.0)*c_wigner3j_auxA(l1,l2,l3,m1,m2,m3) - /(l1*c_wigner3j_auxA(l1+1.0,l2,l3,m1,m2,m3)); - - // Application of the recursion. - thrcof(i) = alphaNew*thrcof(i-1)+beta*thrcof(i-2); - - // We check if we are overflowing. - if (std::fabs(thrcof(i))>srhuge) - { - std::cout << "We renormalized the forward recursion." << std::endl; - thrcof(arma::span(0,i)) /= srhuge; - } - - // This piece of code checks whether we have reached - // the classical region. If we have, the second if - // sets alphaVar to true and we break this loop at the - // next iteration because we need thrcof(l1mid+1) to - // compute the scalar. - if (alphaVar) break; - - if (std::fabs(alphaNew)-std::fabs(alphaOld)>0.0) - alphaVar=true; - - } while (i<(size-1)); // Loop stops when we have computed all values. - - // If this is the case, we have stumbled upon a classical region. - // We start the backwards recursion. - if (i!=size-1) - { - // We keep the two terms around l1mid to compute the factor later. - double l1midm1(thrcof(i-2)),l1mid(thrcof(i-1)),l1midp1(thrcof(i)); - - // We compute the backward recursion by providing an arbitrary - // startint value. - thrcof(size-1) = srtiny; - - // We compute the two-term recursion. - l1 = l1max; - alphaNew = -c_wigner3j_auxB(l1,l2,l3,m1,m2,m3) - /((l1+1.0)*c_wigner3j_auxA(l1,l2,l3,m1,m2,m3)); - thrcof(size-2) = alphaNew*thrcof(size-1); - - // We compute the rest of the backward recursion. - int j = size-2; - do - { - // Bookkeeping - j--; // Previous term in recursion. - l1 -= 1.0; // l1 = l1-1 - - // New coefficients in recursion. - alphaNew = -c_wigner3j_auxB(l1,l2,l3,m1,m2,m3) - /((l1+1.0)*c_wigner3j_auxA(l1,l2,l3,m1,m2,m3)); - beta = -l1*c_wigner3j_auxA(l1+1.0,l2,l3,m1,m2,m3) - /((l1+1.0)*c_wigner3j_auxA(l1,l2,l3,m1,m2,m3)); - - // Application of the recursion. - thrcof(j) = alphaNew*thrcof(j+1)+beta*thrcof(j+2); - - // We check if we are overflowing. - if (std::fabs(thrcof(j)>srhuge)) - { - std::cout << "We renormalized the backward recursion." << std::endl; - thrcof(arma::span(j,size-1)) /= srhuge; - } - - } while (j>(i-2)); // Loop stops when we are at l1=l1mid-1. - - // We now compute the scaling factor for the forward recursion. - double lambda = (l1midp1*thrcof(j+2)+l1mid*thrcof(j+1)+l1midm1*thrcof(j)) - /(l1midp1*l1midp1+l1mid*l1mid+l1midm1*l1midm1); - - // We scale the forward recursion. - thrcof(arma::span(0,j-1)) *= lambda; - } - } - } - - // We compute the overall factor. - double sum = 0.0; - for (int k=0;k= std::fabs(l1-l2) - && l3 <= l1+l2 - && std::fabs(m1) <= l1 - && std::fabs(m2) <= l2 - && std::fabs(m3) <= l3 - ); - - if (!select) return 0.0; - - // We compute l1min and the position of the array we will want. - double l1min = std::max(std::fabs(l2-l3),std::fabs(m1)); - - // We fetch the proper value in the array. - int index = (int)l1-l1min; - - return c_wigner3j(l2,l3,m1,m2,m3)(index); -} - -arma::colvec c_wigner6j(double l2, double l3, - double l4, double l5, double l6) -{ - // We compute the numeric limits of double precision. - double huge = std::numeric_limits::max(); - double srhuge = sqrt(huge); - double tiny = std::numeric_limits::min(); - double srtiny = sqrt(tiny); - double eps = std::numeric_limits::epsilon(); - - // We enforce the selection rules. - bool select(true); - - // Triangle relations for the four tryads - select = ( - std::fabs(l4-l2) <= l6 && l6 <= l4+l2 - && std::fabs(l4-l5) <= l3 && l3 <= l4+l5 - ); - - // Sum rule of the tryads - select = ( - std::floor(l4+l2+l6)==(l4+l2+l6) - && std::floor(l4+l5+l3)==(l4+l5+l3) - ); - - if (!select) return arma::zeros(1); - - // We compute the limits of l1. - double l1min = std::max(std::fabs(l2-l3),std::fabs(l5-l6)); - double l1max = std::min(l2+l3,l5+l6); - - // We compute the size of the resulting array. - unsigned int size = (int)std::floor(l1max-l1min+1.0+eps); - arma::colvec sixcof(size); - - // If l1min=l1max, we have an analytical formula. - if (size==1) - { - sixcof(0) = 1.0/sqrt((l1min+l1min+1.0)*(l4+l4+1.0)); - sixcof(0) *= ((int)std::floor(l2+l3+l5+l6+eps) & 1 ? -1.0 : 1.0); - } - - // Otherwise, we start the forward recursion. - else - { - // We start with an arbitrary value. - sixcof(0) = srtiny; - - // From now on, we check the variation of |alpha(l1)|. - double alphaOld, alphaNew, beta, l1(l1min); - - if (l1min==0) - alphaNew = -(l2*(l2+1.0)+l3*(l3+1.0)+l5*(l5+1.0)+l6*(l6+1.0)-2.0*l4*(l4+1.0))/c_wigner6j_auxA(1.0,l2,l3,l4,l5,l6); - - else - alphaNew = -c_wigner6j_auxB(l1,l2,l3,l4,l5,l6) - /(l1min*c_wigner6j_auxA(l1+1.0,l2,l3,l4,l5,l6)); - - // We compute the two-term recursion. - sixcof(1) = alphaNew*sixcof(0); - - if (size>2) - { - // We start with an arbitrary value. - sixcof(0) = srtiny; - - // From now on, we check the variation of |alpha(l1)|. - double alphaOld, alphaNew, beta, l1(l1min); - if (l1min==0) - alphaNew = -(l2*(l2+1.0)+l3*(l3+1.0)+l5*(l5+1.0)+l6*(l6+1.0)-2.0*l4*(l4+1.0))/c_wigner6j_auxA(1.0,l2,l3,l4,l5,l6); - - else - alphaNew = -c_wigner6j_auxB(l1,l2,l3,l4,l5,l6) - /(l1min*c_wigner6j_auxA(l1+1.0,l2,l3,l4,l5,l6)); - - // We compute the two-term recursion. - sixcof(1) = alphaNew*sixcof(0); - - // We compute the rest of the recursion. - int i = 1; - bool alphaVar = false; - do - { - // Bookkeeping: - i++; // Next term in recursion - alphaOld = alphaNew; // Monitoring of |alpha(l1)|. - l1 += 1.0; // l1 = l1+1 - - // New coefficients in recursion. - alphaNew = -c_wigner6j_auxB(l1,l2,l3,l4,l5,l6) - /(l1*c_wigner6j_auxA(l1+1.0,l2,l3,l4,l5,l6)); - - beta = -(l1+1.0)*c_wigner6j_auxA(l1,l2,l3,l4,l5,l6) - /(l1*c_wigner6j_auxA(l1+1.0,l2,l3,l4,l5,l6)); - - // Application of the recursion. - sixcof(i) = alphaNew*sixcof(i-1)+beta*sixcof(i-2); - - // We check if we are overflowing. - if (std::fabs(sixcof(i)>srhuge)) - { - std::cout << "We renormalized the forward recursion." << std::endl; - sixcof(arma::span(0,i)) /= srhuge; - } - - // This piece of code checks whether we have reached - // the classical region. If we have, the second if - // sets alphaVar to true and we break this loop at the - // next iteration because we need sixcof(l1mid+1) to - // compute the scalar. - if (alphaVar) break; - - if (std::fabs(alphaNew)-std::fabs(alphaOld)>0.0) - alphaVar=true; - - } while (i<(size-1)); // Loop stops when we have computed all values. - - // If this is the case, we have stumbled upon a classical region. - // We start the backwards recursion. - if (i!=size-1) - { - // We keep the two terms around l1mid to compute the factor later. - double l1midm1(sixcof(i-2)),l1mid(sixcof(i-1)),l1midp1(sixcof(i)); - - // We compute the backward recursion by providing an arbitrary - // startint value. - sixcof(size-1) = srtiny; - - // We compute the two-term recursion. - l1 = l1max; - alphaNew = -c_wigner6j_auxB(l1,l2,l3,l4,l5,l6) - /((l1+1.0)*c_wigner6j_auxA(l1,l2,l3,l4,l5,l6)); - sixcof(size-2) = alphaNew*sixcof(size-1); - - // We compute the rest of the backward recursion. - int j = size-2; - do - { - // Bookkeeping - j--; // Previous term in recursion. - l1 -= 1.0; // l1 = l1-1 - - // New coefficients in recursion. - alphaNew = -c_wigner6j_auxB(l1,l2,l3,l4,l5,l6) - /((l1+1.0)*c_wigner6j_auxA(l1,l2,l3,l4,l5,l6)); - beta = -l1*c_wigner6j_auxA(l1+1.0,l2,l3,l4,l5,l6) - /((l1+1.0)*c_wigner6j_auxA(l1,l2,l3,l4,l5,l6)); - - // Application of the recursion. - sixcof(j) = alphaNew*sixcof(j+1)+beta*sixcof(j+2); - - // We check if we are overflowing. - if (std::fabs(sixcof(j)>srhuge)) - { - std::cout << "We renormalized the backward recursion." << std::endl; - sixcof(arma::span(j,size-1)) /= srhuge; - } - - } while (j>(i-2)); // Loop stops when we are at l1=l1mid-1. - - // We now compute the scaling factor for the forward recursion. - double lambda = (l1midp1*sixcof(j+2)+l1mid*sixcof(j+1)+l1midm1*sixcof(j)) - /(l1midp1*l1midp1+l1mid*l1mid+l1midm1*l1midm1); - - // We scale the forward recursion. - sixcof(arma::span(0,j-1)) *= lambda; - } - } - } - - // We compute the overall factor. - double sum = 0.0; - for (int k=0;k - * - * \since 2013-08-16 - * - * \brief Defines utility functions for the evaluation of Wigner-3j and -6j symbols. - * - * We use modified SLATEC (http://netlib.org/slatec) Fortran subroutines to compute - * Wigner-3j and -6j symbols. We modified the subroutines so that they do not depend - * d1mach, r1mach or i1mach as these are obsolete routines. They have been replaced - * by intrinsics such as huge(), tiny(), epsilon() and spacing(), which are guaranteed - * to work. The files wignerSymbols.f90 and utils.f contain the subroutines and their - * dependencies. - * - * We rely on the ISO C Binding to bind the Fortran subroutines to C++. This method - * of working insures that proper type casts are performed, among other things. We - * then use the same method as we did before (extern "C"). - * - */ - -#include -#include -#include -#include - -namespace varPhase { -/** @name Fortran Linkage - * We link the Fortran subroutines to our C++ code. - * Because of the ISO C Binding (see file wigner_wrap.f90), - * some arguments are passed by value rather than by reference. - */ -///@{ -extern "C" -{ - /*! Wigner-3j symbols. */ - extern void drc3jj_wrap(double,double,double,double,double*,double*,double*,int,int*); - - /*! Wigner-6j symbols. */ - extern void drc6j_wrap(double,double,double,double,double,double*,double*,double*,int,int*); -} -///@} - -/*! @name Evaluation of Wigner-3j and -6j symbols. - * We implement the Fortran subroutines in C++. - */ -///@{ -arma::colvec c_wigner3j(double l2, double l3, - double m1, double m2, double m3); - -double c_wigner3j(double l1, double l2, double l3, - double m1, double m2, double m3); - -double c_wigner3j_auxA(double l1, double l2, double l3, - double m1, double m2, double m3); -double c_wigner3j_auxB(double l1, double l2, double l3, - double m1, double m2, double m3); - -arma::colvec c_wigner6j(double l2, double l3, - double l4, double l5, double l6); - -double c_wigner6j(double l1, double l2, double l3, - double l4, double l5, double l6); - -double c_wigner6j_auxA(double l1, double l2, double l3, - double l4, double l5, double l6); - -double c_wigner6j_auxB(double l1, double l2, double l3, - double l4, double l5, double l6); - -/*! Computes the Wigner-3j symbol for given l1,l2,l3,m1,m2,m3. We - * explicitly enforce the selection rules. */ -inline double wigner3j(double l1, double l2, double l3, - double m1, double m2, double m3) -{ - // We enforce the selection rules. - bool select(true); - select = ( - m1+m2+m3==0.0 - && std::floor(l1+l2+l3)==(l1+l2+l3) - && l3 >= std::fabs(l1-l2) - && l3 <= l1+l2 - && std::fabs(m1) <= l1 - && std::fabs(m2) <= l2 - && std::fabs(m3) <= l3 - ); - - if (!select) return 0.0; - - // We compute the size of the resulting array. - int size = (int)std::ceil(l2+l3-std::max(std::fabs(l2-l3),std::fabs(m1)))+1; - - // We prepare the output values. - double l1min, l1max; - double thrcof [size]; - int ierr; - - // External function call. - drc3jj_wrap(l2,l3,m2,m3,&l1min,&l1max,thrcof,size,&ierr); - - // We fetch and return the value with the proper l1 value. - int index = (int)l1-l1min; - return thrcof[index]; -} - -/*! Computes the Clebsch-Gordan coefficient by relating it to the - * Wigner 3j symbol. It sometimes eases the notation to use the - * Clebsch-Gordan coefficients directly. */ -inline double clebschGordan(double l1, double l2, double l3, - double m1, double m2, double m3) -{ - // We simply compute it via the 3j symbol. - return (pow(-1.0,l1-l2+m3)*sqrt(2.0*l3+1.0)*wigner3j(l1,l2,l3,m1,m2,-m3)); -} - -/*! Computes the Wigner-6j symbol for given, l1, l2, l3, l4, l5, l6. - * We explicitly enforce the selection rules. */ -inline double wigner6j(double l1, double l2, double l3, - double l4, double l5, double l6) -{ - // We enforce the selection rules. - bool select(true); - - // Triangle relations for the four tryads - select = ( - std::fabs(l1-l2) <= l3 && l3 <= l1+l2 - && std::fabs(l1-l5) <= l6 && l6 <= l1+l5 - && std::fabs(l4-l2) <= l6 && l6 <= l4+l2 - && std::fabs(l4-l5) <= l3 && l3 <= l4+l5 - ); - - // Sum rule of the tryads - select = ( - std::floor(l1+l2+l3)==(l1+l2+l3) - && std::floor(l1+l5+l6)==(l1+l5+l6) - && std::floor(l4+l2+l6)==(l4+l2+l6) - && std::floor(l4+l5+l3)==(l4+l5+l3) - ); - - if (!select) return 0.0; - - // We compute the size of the resulting array. - int size = (int)std::ceil(std::min(l2+l3,l5+l6)-std::max(std::fabs(l2-l3),std::fabs(l5-l6)))+1; - - // We prepare the output values - double l1min, l1max; - double sixcof [size]; - int ierr; - - // External function call - drc6j_wrap(l2,l3,l4,l5,l6,&l1min,&l1max,sixcof,size,&ierr); - - // We fetch and return the coefficient with the proper l1 value. - int index = (int)l1-l1min; - return sixcof[index]; -} - -template double sgn(T val) { - return (T(0) < val) - (val < T(0)); -} -} - -#endif // WIGNER_SYMBOLS_H \ No newline at end of file diff --git a/src/wignerTest.f90 b/src/wignerTest.f90 deleted file mode 100644 index 81b161b..0000000 --- a/src/wignerTest.f90 +++ /dev/null @@ -1,11 +0,0 @@ - PROGRAM WIGNER -! Declarations for the main program. - INTEGER IER, I1 - DOUBLE PRECISION L1MIN, L1MAX, THRCOF(200), L2, L3, M1, M2, M3 - READ *, L2, L3, M1, M2, M3 - CALL DRC3JJ(L2,L3,M2,M3,L1MIN,L1MAX,THRCOF,200,IER) - - DO 10 I = 1,15 - PRINT *, THRCOF(I) -10 CONTINUE - END \ No newline at end of file diff --git a/src/wigner_wrap.f90 b/src/wigner_wrap.f90 deleted file mode 100644 index c6b32ed..0000000 --- a/src/wigner_wrap.f90 +++ /dev/null @@ -1,51 +0,0 @@ -! ---------------------------------------------------------------- -! - Author: Joey Dumont - -! - Date created: 2013-08-15 - -! - Date modded: 2013-08-15 - -! - Desc.: ISO C Binding wrapper for Wigner-3j and - -! - -6j symbols. This will allow the use of - -! - Fortran subroutines drc3jj, drc3jm and - -! - drc6jj. - -! ---------------------------------------------------------------- - -subroutine drc3jj_wrap(l2, l3, m2, m3, l1min, l1max, thrcof, ndim, ier) bind(C) - - use iso_c_binding - implicit none - - real(c_double), value, intent(in) :: l2, l3, m2, m3 - real(c_double), intent(out) :: l1min, l1max - real(c_double), dimension(ndim), intent(out):: thrcof - integer (c_int), value, intent(in) :: ndim - integer (c_int), intent(out) :: ier - - interface - SUBROUTINE DRC3JJ (L2, L3, M2, M3, L1MIN, L1MAX, THRCOF, NDIM, IER) - INTEGER NDIM, IER - DOUBLE PRECISION L2, L3, M2, M3, L1MIN, L1MAX, THRCOF(NDIM) - end SUBROUTINE DRC3JJ - end interface - - call DRC3JJ(l2, l3, m2, m3, l1min, l1max, thrcof, ndim, ier) - -end subroutine drc3jj_wrap - -subroutine drc6j_wrap(l2, l3, l4, l5, l6, l1min, l1max, sixcof, ndim, ier) bind(C) - use iso_c_binding - implicit none - - real(c_double), value, intent(in) :: l2, l3, l4, l5, l6 - real(c_double), intent(out) :: l1min, l1max - real(c_double), dimension(ndim), intent(out):: sixcof - integer(c_int), value, intent(in) :: ndim - integer(c_int), intent(out) :: ier - - interface - SUBROUTINE DRC6J(L2, L3, L4, L5, L6, L1MIN, L1MAX, SIXCOF, NDIM, IER) - INTEGER NDIM, IER - DOUBLE PRECISION L2, L3, L4, L5, L6, L1MIN, L1MAX, SIXCOF(NDIM) - END SUBROUTINE DRC6J - end interface - - call DRC6J(l2, l3, l4, l5, l6, l1min, l1max, sixcof, ndim, ier) -end subroutine drc6j_wrap \ No newline at end of file