citcos.C

00001 /*
00002  *   Copyright (c) 1999-2001 Eric Gourgoulhon
00003  *   Copyright (c) 2002 Jerome Novak
00004  *   
00005  *
00006  *   This file is part of LORENE.
00007  *
00008  *   LORENE is free software; you can redistribute it and/or modify
00009  *   it under the terms of the GNU General Public License as published by
00010  *   the Free Software Foundation; either version 2 of the License, or
00011  *   (at your option) any later version.
00012  *
00013  *   LORENE is distributed in the hope that it will be useful,
00014  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  *   GNU General Public License for more details.
00017  *
00018  *   You should have received a copy of the GNU General Public License
00019  *   along with LORENE; if not, write to the Free Software
00020  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  */
00023 
00024 
00025 /*
00026  * Transformation en cos(l*theta) inverse sur le deuxieme indice (theta)
00027  *  d'un tableau 3-D representant une fonction quelconque (theta variant de 0
00028  *  a pi). Utilise la bibliotheque fftw.
00029  *
00030  * Entree:
00031  * -------
00032  *   int* deg   : tableau du nombre effectif de degres de liberte dans chacune 
00033  *        des 3 dimensions: le nombre de points de collocation
00034  *        en theta est  nt = deg[1] et doit etre de la forme
00035  *          nt = 2*p + 1 
00036  *   int* dimc  : tableau du nombre d'elements de cc dans chacune des trois 
00037  *            dimensions.
00038  *        On doit avoir  dimc[1] >= deg[1] = nt. 
00039  *        NB: pour dimc[0] = 1 (un seul point en phi), la transformation
00040  *            est bien effectuee.
00041  *            pour dimc[0] > 1 (plus d'un point en phi), la
00042  *            transformation n'est effectuee que pour les indices (en phi)
00043  *            j != 1 et j != dimc[0]-1 (cf. commentaires sur borne_phi).
00044  *
00045  *   double* cf :   tableau des coefficients c_l de la fonction definis
00046  *            comme suit (a r et phi fixes)
00047  *
00048  *             f(theta) = som_{l=0}^{nt-1} c_l cos( l theta ) . 
00049  *
00050  *            L'espace memoire correspondant a ce
00051  *                        pointeur doit etre dimc[0]*dimc[1]*dimc[2] et doit 
00052  *            avoir ete alloue avant l'appel a la routine.   
00053  *           Le coefficient c_l (0 <= l <= nt-1) doit etre stoke dans
00054  *           le tableau cf comme suit
00055  *                c_l = cf[ dimc[1]*dimc[2] * j + k + dimc[2] * l ]
00056  *           ou j et k sont les indices correspondant a
00057  *           phi et r respectivement.
00058  *
00059  *   int* dimf  : tableau du nombre d'elements de ff dans chacune des trois 
00060  *            dimensions.
00061  *        On doit avoir  dimf[1] >= deg[1] = nt. 
00062  *
00063  * Sortie:
00064  * -------
00065  *   double* ff : tableau des valeurs de la fonction aux nt points de
00066  *                        de collocation
00067  *
00068  *            theta_l =  pi l/(nt-1)       0 <= l <= nt-1 
00069  *
00070  *            L'espace memoire correspondant a ce
00071  *                        pointeur doit etre dimf[0]*dimf[1]*dimf[2] et doit 
00072  *            avoir ete alloue avant l'appel a la routine.   
00073  *            Les valeurs de la fonction sont stokees
00074  *            dans le tableau ff comme suit
00075  *          f( theta_l ) = ff[ dimf[1]*dimf[2] * j + k + dimf[2] * l ]
00076  *           ou j et k sont les indices correspondant a
00077  *           phi et r respectivement.
00078  *
00079  * NB: Si le pointeur cf est egal a ff, la routine ne travaille que sur un 
00080  *     seul tableau, qui constitue une entree/sortie.
00081  *
00082  */
00083 
00084 char citcos_C[] = "$Header: /cvsroot/Lorene/C++/Source/Non_class_members/Coef/FFTW3/citcos.C,v 1.1 2004/12/21 17:06:03 j_novak Exp $" ;
00085 
00086 /*
00087  * $Id: citcos.C,v 1.1 2004/12/21 17:06:03 j_novak Exp $
00088  * $Log: citcos.C,v $
00089  * Revision 1.1  2004/12/21 17:06:03  j_novak
00090  * Added all files for using fftw3.
00091  *
00092  * Revision 1.2  2003/01/31 10:31:23  e_gourgoulhon
00093  * Suppressed the directive #include <malloc.h> for malloc is defined
00094  * in <stdlib.h>
00095  *
00096  * Revision 1.1  2002/11/12 17:43:53  j_novak
00097  * Added transformatin functions for T_COS basis.
00098  *
00099  *
00100  * $Header: /cvsroot/Lorene/C++/Source/Non_class_members/Coef/FFTW3/citcos.C,v 1.1 2004/12/21 17:06:03 j_novak Exp $
00101  *
00102  */
00103 
00104 
00105 // headers du C
00106 #include <stdlib.h>
00107 #include <fftw3.h>
00108 
00109 //Lorene prototypes
00110 #include "tbl.h"
00111 
00112 // Prototypage des sous-routines utilisees:
00113 fftw_plan back_fft(int, Tbl*&) ;
00114 double* cheb_ini(const int) ;
00115 //*****************************************************************************
00116 
00117 void citcos(const int* deg, const int* dimc, double* cf, const int* dimf,
00118            double* ff)
00119 {
00120 
00121 int i, j, k ;
00122 
00123 // Dimensions des tableaux ff et cf  :
00124     int n1f = dimf[0] ;
00125     int n2f = dimf[1] ;
00126     int n3f = dimf[2] ;
00127     int n1c = dimc[0] ;
00128     int n2c = dimc[1] ;
00129     int n3c = dimc[2] ;
00130 
00131 // Nombres de degres de liberte en theta :    
00132     int nt = deg[1] ;
00133     
00134 // Tests de dimension:
00135     if (nt > n2f) {
00136     cout << "citcos: nt > n2f : nt = " << nt << " ,  n2f = " 
00137     << n2f << endl ;
00138     abort () ;
00139     exit(-1) ;
00140     }
00141     if (nt > n2c) {
00142     cout << "citcos: nt > n2c : nt = " << nt << " ,  n2c = " 
00143     << n2c << endl ;
00144     abort () ;
00145     exit(-1) ;
00146     }
00147     if ( (n1f > 1) && (n1c > n1f) ) {
00148     cout << "citcos: n1c > n1f : n1c = " << n1c << " ,  n1f = " 
00149     << n1f << endl ;
00150     abort () ;
00151     exit(-1) ;
00152     }
00153     if (n3c > n3f) {
00154     cout << "citcos: n3c > n3f : n3c = " << n3c << " ,  n3f = " 
00155     << n3f << endl ;
00156     abort () ;
00157     exit(-1) ;
00158     }
00159 
00160 // Nombre de points pour la FFT:
00161     int nm1 = nt - 1;
00162     int nm1s2 = nm1 / 2;
00163 
00164 // Recherche des tables pour la FFT:
00165     Tbl* pg = 0x0 ;
00166     fftw_plan p = back_fft(nm1, pg) ;
00167     Tbl& g = *pg ;
00168 
00169 // Recherche de la table des sin(psi) :
00170     double* sinp = cheb_ini(nt);    
00171     
00172 // boucle sur phi et r (les boucles vont resp. de 0 a max(dimc[0]-2,0) et 
00173 //          0 a dimc[2]-1 )
00174 
00175     int n2n3f = n2f * n3f ;
00176     int n2n3c = n2c * n3c ;
00177     
00178 /*   
00179  * Borne de la boucle sur phi: 
00180  *    si n1f = 1, on effectue la boucle une fois seulement.
00181  *    si n1f > 1, on va jusqu'a j = n1c-2 en sautant j = 1 (les coefficients
00182  *  j=n1c-1 et j=0 ne sont pas consideres car nuls). 
00183  */
00184     int borne_phi =  n1c-1  ;
00185     if (n1f == 1) borne_phi = 1 ; 
00186 
00187     for (j=0; j< borne_phi; j++) {
00188     
00189     if (j==1) continue ;    // on ne traite pas le terme en sin(0 phi)
00190 
00191     for (k=0; k<n3c; k++) {
00192 
00193         int i0 = n2n3c * j + k ; // indice de depart 
00194         double* cf0 = cf + i0 ;    // tableau des donnees a transformer
00195 
00196         i0 = n2n3f * j + k ; // indice de depart 
00197         double* ff0 = ff + i0 ;    // tableau resultat
00198          
00199 /*
00200  * NB: dans les commentaires qui suivent, psi designe la variable de [0, pi]
00201  *     reliee a theta par psi = 2 theta   et F(psi) = f(theta(psi)).  
00202  */
00203  
00204 // Calcul des coefficients de Fourier de la fonction 
00205 //   G(psi) = F+(psi) + F_(psi) sin(psi)
00206 // en fonction des coefficients en cos(2l theta) de f:
00207 
00208 // Coefficients impairs de G
00209 //--------------------------
00210  
00211         double c1 = cf0[n3c] ;
00212 
00213             double som = 0;
00214         ff0[n3f] = 0 ;
00215             for ( i = 3; i < nt; i += 2 ) {
00216             ff0[ n3f*i ] = cf0[ n3c*i ] - c1 ;
00217         som += ff0[ n3f*i ] ;
00218             }   
00219 
00220 // Valeur en psi=0 de la partie antisymetrique de F, F_ :
00221         double fmoins0 = nm1s2 * c1 + som ;
00222 
00223 // Coef. impairs de G
00224 // NB: le facteur 0.25 est du a la normalisation de fftw; si fftw
00225 //     donnait exactement les coef. des sinus, ce facteur serait -0.5.
00226             for ( i = 3; i < nt; i += 2 ) {
00227         g.set(nm1-i/2) = 0.25 * ( ff0[ n3f*i ] - ff0[ n3f*(i-2) ] ) ;
00228             }
00229 
00230 
00231 // Coefficients pairs de G
00232 //------------------------
00233 //  Ces coefficients sont egaux aux coefficients pairs du developpement de
00234 //   f.
00235 // NB: le facteur 0.5 est du a la normalisation de fftw; si fftw
00236 //     donnait exactement les coef. des cosinus, ce facteur serait 1.
00237 
00238         g.set(0) = cf0[0] ;
00239             for (i=1; i<nm1s2; i++ ) g.set(i) = 0.5 * cf0[ n3c*2*i ] ;  
00240             g.set(nm1s2) = cf0[ n3c*nm1 ] ;
00241 
00242 // Transformation de Fourier inverse de G 
00243 //---------------------------------------
00244 
00245 // FFT inverse
00246         fftw_execute(p) ;
00247 
00248 // Valeurs de f deduites de celles de G
00249 //-------------------------------------
00250 
00251             for ( i = 1; i < nm1s2 ; i++ ) {
00252 // ... indice du pt symetrique de psi par rapport a pi/2:
00253         int isym = nm1 - i ; 
00254     
00255         double fp = 0.5 * ( g(i) + g(isym) ) ;
00256         double fm = 0.5 * ( g(i) - g(isym) ) / sinp[i] ;
00257         ff0[ n3f*i ] = fp + fm ;
00258         ff0[ n3f*isym ] = fp - fm ;
00259             }
00260     
00261 //... cas particuliers:
00262         ff0[0] = g(0) + fmoins0 ;
00263         ff0[ n3f*nm1 ] = g(0) - fmoins0 ;
00264         ff0[ n3f*nm1s2 ] = g(nm1s2) ;
00265 
00266 
00267     }   // fin de la boucle sur r 
00268    }    // fin de la boucle sur phi
00269 
00270     
00271 }

Generated on Tue Feb 7 01:35:15 2012 for LORENE by  doxygen 1.4.6