dal_inverse.C

00001 /*
00002  *   Copyright (c) 2000-2001 Jerome Novak
00003  *
00004  *   This file is part of LORENE.
00005  *
00006  *   LORENE is free software; you can redistribute it and/or modify
00007  *   it under the terms of the GNU General Public License as published by
00008  *   the Free Software Foundation; either version 2 of the License, or
00009  *   (at your option) any later version.
00010  *
00011  *   LORENE is distributed in the hope that it will be useful,
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *   GNU General Public License for more details.
00015  *
00016  *   You should have received a copy of the GNU General Public License
00017  *   along with LORENE; if not, write to the Free Software
00018  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00021 
00022 
00023 char dal_inverse_C[] = "$Header: /cvsroot/Lorene/C++/Source/Non_class_members/PDE/dal_inverse.C,v 1.7 2008/08/27 08:51:15 jl_cornou Exp $" ;
00024 
00025 /*
00026  * $Id: dal_inverse.C,v 1.7 2008/08/27 08:51:15 jl_cornou Exp $
00027  * $Log: dal_inverse.C,v $
00028  * Revision 1.7  2008/08/27 08:51:15  jl_cornou
00029  * Added Jacobi(0,2) polynomials
00030  *
00031  * Revision 1.6  2008/02/18 13:53:43  j_novak
00032  * Removal of special indentation instructions.
00033  *
00034  * Revision 1.5  2004/10/05 15:44:21  j_novak
00035  * Minor speed enhancements.
00036  *
00037  * Revision 1.4  2002/01/03 15:30:28  j_novak
00038  * Some comments modified.
00039  *
00040  * Revision 1.3  2002/01/03 13:18:41  j_novak
00041  * Optimization: the members set(i,j) and operator(i,j) of class Matrice are
00042  * now defined inline. Matrice is a friend class of Tbl.
00043  *
00044  * Revision 1.2  2002/01/02 14:07:57  j_novak
00045  * Dalembert equation is now solved in the shells. However, the number of
00046  * points in theta and phi must be the same in each domain. The solver is not
00047  * completely tested (beta version!).
00048  *
00049  * Revision 1.1.1.1  2001/11/20 15:19:28  e_gourgoulhon
00050  * LORENE
00051  *
00052  * Revision 1.1  2000/12/04  16:37:03  novak
00053  * Initial revision
00054  *
00055  *
00056  * $Header: /cvsroot/Lorene/C++/Source/Non_class_members/PDE/dal_inverse.C,v 1.7 2008/08/27 08:51:15 jl_cornou Exp $
00057  *
00058  */
00059 
00060 //fichiers includes
00061 #include <math.h>
00062 
00063 //Headers LORENE
00064 #include "param.h"
00065 #include "matrice.h"
00066 #include "proto.h"
00067 
00068 /***************************************************************************
00069  *
00070  *      Set of routines to invert the dalembertian operator given
00071  * by get_operateur. The matrix is put into a banded form, following
00072  * the type of the operator (type_dal) and the odd/even decomposition 
00073  * base (base_r).
00074  * type_dal is supposed to be given by get_operateur (see the various cases
00075  * there and in type_parite.h).
00076  * part is a boolean saying wether one is looking for a particular sol.
00077  * of the system defined by operateur (i.e. X such as operateur*X = source),
00078  * part = true, or a homogeneous one (part = false).
00079  *
00080  ***************************************************************************/
00081 
00082         //------------------------------------
00083         // Routine pour les cas non prevus --
00084         //------------------------------------
00085 Tbl _dal_inverse_pas_prevu (const Matrice&, const Tbl&, const bool) {
00086     cout << " Inversion du dalembertien pas prevue ..... : "<< endl ;
00087     abort() ;
00088     exit(-1) ;
00089     Tbl res(1) ;
00090     return res;
00091 }
00092     
00093     
00094         //-------------------
00095            //--  R_CHEB    -----
00096           //-------------------
00097 
00098 Tbl _dal_inverse_r_cheb_o2d_s(const Matrice &op, const Tbl &source, 
00099                    const bool part) {
00100 
00101   // Operator and source are copied and prepared
00102   Matrice barre(op) ;
00103   int nr = op.get_dim(0) ;
00104   Tbl aux(source) ;
00105 
00106   // Operator is put into banded form (changing the image base)
00107 
00108   int dirac = 2 ; // Don't forget the factor 2 for T_0!!
00109   for (int i=0; i<nr-4; i++) {
00110     int nrmin = (i>1 ? i-1 : 0) ;
00111     int nrmax = (i<nr-9 ? i+10 : nr) ;
00112     for (int j=nrmin; j<nrmax; j++) 
00113       barre.set(i,j) = (op(i+2,j) - dirac*op(i,j))/(i+1) ;
00114     if (part)
00115       aux.set(i) = (source(i+2) - dirac*source(i))/(i+1) ;
00116     if (i==0) dirac = 1 ;
00117   }
00118   for (int i=0; i<nr-4; i++) {
00119     int nrmin = (i>1 ? i-1 : 0) ;
00120     int nrmax = (i<nr-9 ? i+10 : nr) ;
00121     for (int j=nrmin; j<nrmax; j++) 
00122       barre.set(i,j) = barre(i+2,j) - barre(i,j) ;
00123     if (part) aux.set(i) = aux(i+2) - aux(i) ;
00124   }
00125 
00126   // 6 over-diagonals and 2 under...
00127   barre.set_band(5,1) ;
00128 
00129   // LU decomposition
00130   barre.set_lu() ;
00131 
00132   // Inversion using LAPACK
00133 
00134   return barre.inverse(aux) ;
00135 }
00136 
00137 Tbl _dal_inverse_r_cheb_o2d_l(const Matrice &op, const Tbl &source, 
00138                    const bool part) {
00139 
00140   // Operator and source are copied and prepared
00141   Matrice barre(op) ;
00142   int nr = op.get_dim(0) ;
00143   Tbl aux(source) ;
00144 
00145   // Operator is put into banded form (changing the image base)
00146 
00147   int dirac = 2 ; // Don't forget the factor 2 for T_0!!
00148   for (int i=0; i<nr-4; i++) {
00149     int nrmin = (i>1 ? i-1 : 0) ;
00150     int nrmax = (i<nr-9 ? i+10 : nr) ;
00151     for (int j=nrmin; j<nrmax; j++) 
00152       barre.set(i,j) = (op(i+2,j) - dirac*op(i,j))/(i+1) ;
00153     if (part)
00154       aux.set(i) = (source(i+2) - dirac*source(i))/(i+1) ;
00155     if (i==0) dirac = 1 ;
00156   }
00157   for (int i=0; i<nr-4; i++) {
00158     int nrmin = (i>1 ? i-1 : 0) ;
00159     int nrmax = (i<nr-9 ? i+10 : nr) ;
00160     for (int j=nrmin; j<nrmax; j++) 
00161       barre.set(i,j) = barre(i+2,j) - barre(i,j) ;
00162     if (part) aux.set(i) = aux(i+2) - aux(i) ;
00163   }
00164 
00165   // In this case the time-step is too large for the number of points
00166   // (or the number of points too large for the time-step!)
00167   // the matrix is ill-conditionned: the last lines are put as first
00168   // ones and all the others are shifted.
00169 
00170   double temp1, temp2 ;
00171   temp1 = aux(nr-1) ;
00172   temp2 = aux(nr-2) ;
00173   for (int i=nr-3; i>=0; i--) {
00174     int nrmin = (i>1 ? i-1 : 0) ;
00175     int nrmax = (i<nr-9 ? i+10 : nr) ;
00176     for (int j=nrmin; j<nrmax; j++) 
00177       barre.set(i+2,j) = barre(i,j) ;
00178     aux.set(i+2) = aux(i) ;
00179   }
00180   aux.set(0) = temp2 ;
00181   aux.set(1) = temp1 ;
00182   
00183   barre.set(0,0) = 0.5 ;
00184   barre.set(0,1) = 1. ;
00185   barre.set(0,2) = 1. ;
00186   barre.set(0,3) = 1. ;
00187   barre.set(0,4) = 0. ;
00188   
00189   barre.set(1,0) = 0. ;
00190   barre.set(1,1) = 0.5 ;
00191   barre.set(1,2) = 1. ;
00192   barre.set(1,3) = -1. ;
00193   barre.set(1,4) = 1. ;
00194   barre.set(1,5) = 0. ;
00195 
00196   // 3 over diagonals and 3 under ...
00197   barre.set_band(3,3) ;
00198 
00199   // LU decomposition
00200   barre.set_lu() ;
00201 
00202   // Inversion using LAPACK
00203 
00204   return barre.inverse(aux) ;
00205 }
00206 
00207 Tbl _dal_inverse_r_cheb_o2_s(const Matrice &op, const Tbl &source, 
00208                    const bool part) {
00209 
00210   // Operator and source are copied and prepared
00211   Matrice barre(op) ;
00212   int nr = op.get_dim(0) ;
00213   Tbl aux(source) ;
00214 
00215   // Operator is put into banded form (changing the image base)
00216 
00217   int dirac = 2 ; // Don't forget the factor 2 for T_0!!
00218   for (int i=0; i<nr-4; i++) {
00219     int nrmin = (i>2 ? i-2 : 0) ;
00220     int nrmax = (i<nr-10 ? i+11 : nr) ;
00221     for (int j=nrmin; j<nrmax; j++) 
00222       barre.set(i,j) = (op(i+2,j) - dirac*op(i,j))/(i+1) ;
00223     if (part)
00224       aux.set(i) = (source(i+2) - dirac*source(i))/(i+1) ;
00225     if (i==0) dirac = 1 ;
00226   }
00227   for (int i=0; i<nr-4; i++) {
00228     int nrmin = (i>2 ? i-2 : 0) ;
00229     int nrmax = (i<nr-10 ? i+11 : nr) ;
00230     for (int j=nrmin; j<nrmax; j++) 
00231       barre.set(i,j) = barre(i+2,j) - barre(i,j) ;
00232     if (part) aux.set(i) = aux(i+2) - aux(i) ;
00233   }
00234 
00235   // 6 over-diagonals and 2 under...
00236   barre.set_band(6,2) ;
00237 
00238   // LU decomposition
00239   barre.set_lu() ;
00240 
00241   // Inversion using LAPACK
00242 
00243   return barre.inverse(aux) ;
00244 }
00245 
00246 Tbl _dal_inverse_r_cheb_o2_l(const Matrice &op, const Tbl &source, 
00247                    const bool part) {
00248 
00249   // Operator and source are copied and prepared
00250   Matrice barre(op) ;
00251   int nr = op.get_dim(0) ;
00252   Tbl aux(source) ;
00253 
00254   // Operator is put into banded form (changing the image base)
00255 
00256   int dirac = 2 ; // Don't forget the factor 2 for T_0!!
00257   for (int i=0; i<nr-4; i++) {
00258     int nrmin = (i>2 ? i-2 : 0) ;
00259     int nrmax = (i<nr-10 ? i+11 : nr) ;
00260     for (int j=nrmin; j<nrmax; j++) 
00261       barre.set(i,j) = (op(i+2,j) - dirac*op(i,j))/(i+1) ;
00262     if (part)
00263       aux.set(i) = (source(i+2) - dirac*source(i))/(i+1) ;
00264     if (i==0) dirac = 1 ;
00265   }
00266   for (int i=0; i<nr-4; i++) {
00267     int nrmin = (i>2 ? i-2 : 0) ;
00268     int nrmax = (i<nr-10 ? i+11 : nr) ;
00269     for (int j=nrmin; j<nrmax; j++) 
00270       barre.set(i,j) = barre(i+2,j) - barre(i,j) ;
00271     if (part) aux.set(i) = aux(i+2) - aux(i) ;
00272   }
00273 
00274   // In this case the time-step is too large for the number of points
00275   // (or the number of points too large for the time-step!)
00276   // the matrix is ill-conditionned: the last lines are put as first
00277   // ones and all the others are shifted.
00278 
00279   double temp1, temp2 ;
00280   temp1 = aux(nr-1) ;
00281   temp2 = aux(nr-2) ;
00282   for (int i=nr-3; i>=0; i--) {
00283     int nrmin = (i>2 ? i-2 : 0) ;
00284     int nrmax = (i<nr-10 ? i+11 : nr) ;
00285     for (int j=nrmin; j<nrmax; j++) 
00286       barre.set(i+2,j) = barre(i,j) ;
00287     aux.set(i+2) = aux(i) ;
00288   }
00289   aux.set(0) = temp2 ;
00290   aux.set(1) = temp1 ;
00291   
00292   barre.set(0,0) = 0.5 ;
00293   barre.set(0,1) = 1. ;
00294   barre.set(0,2) = 1. ;
00295   barre.set(0,3) = 1. ;
00296   barre.set(0,4) = 1. ;
00297   barre.set(0,5) = 0. ;
00298   
00299   barre.set(1,0) = 0. ;
00300   barre.set(1,1) = 0.5 ;
00301   barre.set(1,2) = -1. ;
00302   barre.set(1,3) = 1. ;
00303   barre.set(1,4) = -1. ;
00304   barre.set(1,5) = 1. ;
00305   barre.set(1,6) = 0. ;
00306 
00307   // 4 over diagonals and 4 under ...
00308   barre.set_band(4,4) ;
00309 
00310   // LU decomposition
00311   barre.set_lu() ;
00312 
00313   // Inversion using LAPACK
00314 
00315   return barre.inverse(aux) ;
00316 }
00317     
00318         //-------------------
00319            //--  R_CHEBP   -----
00320           //-------------------
00321 
00322 Tbl _dal_inverse_r_chebp_o2d_s(const Matrice &op, const Tbl &source, 
00323                    const bool part) {
00324 
00325   // Operator and source are copied and prepared
00326   Matrice barre(op) ;
00327   int nr = op.get_dim(0) ;
00328   Tbl aux(nr) ;
00329   if (part) {
00330     aux = source ;
00331     aux.set(nr-1) = 0. ;
00332   }
00333   else {
00334     aux.annule_hard() ;
00335     aux.set(nr-1) = 1. ;
00336   }
00337 
00338   // Operator is put into banded form (changing the image base)
00339 
00340   int dirac = 2 ; // Don't forget the factor 2 for T_0!!
00341   for (int i=0; i<nr-4; i++) {
00342     int nrmax = (i<nr-7 ? i+8 : nr) ;
00343     for (int j=i; j<nrmax; j++) 
00344       barre.set(i,j) = (op(i+2,j) - dirac*op(i,j))/(i+1) ;
00345     if (part)
00346       aux.set(i) = (source(i+2) - dirac*source(i))/(i+1) ;
00347     if (i==0) dirac = 1 ;
00348   }
00349   for (int i=0; i<nr-4; i++) {
00350     int nrmax = (i<nr-7 ? i+8 : nr) ;
00351     for (int j=i; j<nrmax; j++) barre.set(i,j) = barre(i+1,j) - barre(i,j) ;
00352     if (part) aux.set(i) = aux(i+1) - aux(i) ;
00353   }
00354   if (fabs(barre(nr-5,nr-1)) >= 1.e-16) {
00355     if (fabs(barre(nr-5,nr-1)) > fabs(barre(nr-2,nr-1))) {
00356       double lambda = barre(nr-2,nr-1)/barre(nr-5,nr-1) ; 
00357       for (int j=nr-5; j<nr; j++) barre.set(nr-5,j) = barre(nr-5,j)*lambda
00358                  -barre(nr-2,j) ;
00359       if (part) aux.set(nr-5) = aux(nr-5)*lambda - aux(nr-2) ;
00360     }
00361     else {
00362       double lambda = barre(nr-5,nr-1)/barre(nr-2,nr-1) ; 
00363       for (int j=nr-5; j<nr; j++) barre.set(nr-5,j) -= lambda*barre(nr-2,j) ;
00364       if (part) aux.set(nr-5) -= lambda*aux(nr-2) ;
00365     }
00366   }
00367 
00368   // 3 over-diagonals and 0 under...
00369   barre.set_band(3,0) ;
00370 
00371   // LU decomposition
00372   barre.set_lu() ;
00373 
00374   // Inversion using LAPACK
00375 
00376   return barre.inverse(aux) ;
00377 }
00378 
00379 
00380 
00381 Tbl _dal_inverse_r_chebp_o2d_l(const Matrice &op, const Tbl &source, 
00382                    const bool part) {
00383 
00384   // Operator and source are copied and prepared
00385   Matrice barre(op) ;
00386   int nr = op.get_dim(0) ;
00387   Tbl aux(nr) ;
00388   if (part) {
00389     aux = source ;
00390     aux.set(nr-1) = 0. ;
00391   }
00392   else {
00393     aux.annule_hard() ;
00394     aux.set(0) = 1. ;
00395   }
00396 
00397   // Operator is put into banded form (changing the image base)
00398 
00399   int dirac = 2 ; // Don't forget the factor 2 for T_0!!
00400   for (int i=0; i<nr-4; i++) {
00401     int nrmax = (i<nr-7 ? i+8 : nr) ;
00402     for (int j=i; j<nrmax; j++) 
00403       barre.set(i,j) = (op(i+2,j) - dirac*op(i,j))/(i+1) ;
00404     if (part)
00405       aux.set(i) = (source(i+2) - dirac*source(i))/(i+1) ;
00406     if (i==0) dirac = 1 ;
00407   }
00408   for (int i=0; i<nr-4; i++) {
00409     int nrmax = (i<nr-7 ? i+8 : nr) ;
00410     for (int j=i; j<nrmax; j++) barre.set(i,j) = barre(i+1,j) - barre(i,j) ;
00411     if (part) aux.set(i) = aux(i+1) - aux(i) ;
00412   }
00413   if (fabs(barre(nr-5,nr-1)) >= 1.e-16) {
00414     if (fabs(barre(nr-5,nr-1)) > fabs(barre(nr-2,nr-1))) {
00415       double lambda = barre(nr-2,nr-1)/barre(nr-5,nr-1) ; 
00416       for (int j=nr-5; j<nr; j++) barre.set(nr-5,j) = barre(nr-5,j)*lambda
00417                  -barre(nr-2,j) ;
00418       if (part) aux.set(nr-5) = aux(nr-5)*lambda - aux(nr-2) ;
00419     }
00420     else {
00421       double lambda = barre(nr-5,nr-1)/barre(nr-2,nr-1) ; 
00422       for (int j=nr-5; j<nr; j++) barre.set(nr-5,j) -= lambda*barre(nr-2,j) ;
00423       if (part) aux.set(nr-5) -= lambda*aux(nr-2) ;
00424     }
00425   }
00426   
00427   // In this case the time-step is too large for the number of points
00428   // (or the number of points too large for the time-step!)
00429   // the matrix is ill-conditionned: the last line is put as the first
00430   // one and all the others are shifted.
00431 
00432   for (int i=nr-2; i>=0; i--) {
00433     for (int j=i; j<((i+5 > nr) ? nr : i+5); j++) 
00434       barre.set(i+1,j) = barre(i,j) ;
00435     if (part) aux.set(i+1) = aux(i) ;
00436   }
00437   barre.set(0,0) = 0.5 ;
00438   barre.set(0,1) = 1. ;
00439   barre.set(0,2) = 1. ;
00440   barre.set(0,3) = 0. ;
00441   
00442   if (part) aux.set(0) = 0 ;
00443   
00444   // 2 over diagonals and one under ...
00445   barre.set_band(2,1) ;
00446 
00447   // LU decomposition
00448   barre.set_lu() ;
00449 
00450   // Inversion using LAPACK
00451 
00452   return barre.inverse(aux);
00453 }
00454 
00455 
00456 
00457 Tbl _dal_inverse_r_chebp_o2_s(const Matrice &op, const Tbl &source, 
00458                   const bool part) {
00459   
00460   // Operator and source are copied and prepared
00461   Matrice barre(op) ;
00462   int nr = op.get_dim(0) ;
00463   Tbl aux(nr-1) ;
00464   if (part) {
00465     aux.set_etat_qcq() ;
00466     for (int i=nr-4; i<nr-1; i++) aux.set(i) = source(i) ; 
00467   }
00468   else {
00469     aux.annule_hard() ;
00470     aux.set(nr-2) = 1. ;
00471   }
00472 
00473   // Operator is put into banded form (changing the image base ...)
00474 
00475   int dirac = 2 ;// Don't forget the factor 2 for T_0!!
00476   for (int i=0; i<nr-4; i++) {
00477     int nrmax = (i<nr-7 ? i+8 : nr) ;
00478     for (int j=i; j<nrmax; j++) 
00479       barre.set(i,j) = (op(i+2,j) - dirac*op(i,j))/(i+1) ;
00480     if (part)
00481       aux.set(i) = (source(i+2) - dirac*source(i))/(i+1) ;
00482     if (i==0) dirac = 1 ;
00483   }
00484   for (int i=0; i<nr-4; i++) {
00485     int nrmax = (i<nr-7 ? i+8 : nr) ;
00486     for (int j=i; j<nrmax; j++) barre.set(i,j) = barre(i+1,j) - barre(i,j) ;
00487     if (part) aux.set(i) = aux(i+1) - aux(i) ;
00488   }
00489 
00490   // ... and changing the starting base (the last column is quit) ... 
00491   
00492   Matrice tilde(nr-1,nr-1) ;
00493   tilde.set_etat_qcq() ;
00494   for (int i=0; i<nr-1; i++) 
00495     for (int j=0; j<nr-1;j++) 
00496       tilde.set(i,j) = barre(i,j+1) + barre(i,j) ;
00497   
00498   // 3 over-diagonals and 1 under...
00499   tilde.set_band(3,1) ;
00500 
00501   // LU decomposition
00502   tilde.set_lu() ;
00503 
00504   // Inversion using LAPACK
00505   Tbl res0(tilde.inverse(aux)) ;
00506   Tbl res(nr) ;
00507   res.set_etat_qcq() ;
00508 
00509   // ... finally, one has to recover the original starting base
00510   res.set(0) = res0(0) ;
00511   res.set(nr-1) = res0(nr-2) ;
00512   for (int i=1; i<nr-1; i++) res.set(i) = res0(i-1) + res0(i);
00513   
00514   return res ;
00515   
00516   
00517 }
00518     
00519 Tbl _dal_inverse_r_chebp_o2_l(const Matrice &op, const Tbl &source, 
00520                   const bool part) {
00521 
00522   // Operator and source are copied and prepared
00523   Matrice barre(op) ;
00524   int nr = op.get_dim(0) ;
00525   Tbl aux(nr-1) ;
00526   if (part) {
00527     aux.set_etat_qcq() ;
00528     for (int i=nr-4; i<nr-1; i++) aux.set(i) = source(i) ;
00529   }
00530   else {
00531     aux.annule_hard() ;
00532     aux.set(0) = 1 ;
00533   }
00534 
00535   // Operator is put into banded form (changing the image base ...)
00536 
00537   int dirac = 2 ;// Don't forget the factor 2 for T_0!!
00538   for (int i=0; i<nr-4; i++) {
00539     int nrmax = (i<nr-7 ? i+8 : nr) ;
00540     for (int j=i; j<nrmax; j++) {
00541       barre.set(i,j) = (op(i+2,j) - dirac*op(i,j))/(i+1) ;
00542     }
00543     if (part) 
00544       aux.set(i) = (source(i+2) - dirac*source(i))/(i+1) ;
00545     if (i==0) dirac = 1 ;
00546   }
00547   for (int i=0; i<nr-4; i++) {
00548     int nrmax = (i<nr-7 ? i+8 : nr) ;
00549     for (int j=i; j<nrmax; j++) barre.set(i,j) = barre(i+1,j) - barre(i,j) ;
00550     if (part) aux.set(i) = aux(i+1) - aux(i) ;
00551   }
00552   
00553   // ... and changing the starting base (the last column is quit) ... 
00554   
00555   Matrice tilde(nr-1,nr-1) ;
00556   tilde.set_etat_qcq() ;
00557   for (int i=0; i<nr-1; i++) 
00558     for (int j=0; j<nr-1;j++) 
00559       tilde.set(i,j) = barre(i,j+1) + barre(i,j) ;
00560 
00561   // In this case the time-step is too large for the number of points
00562   // (or the number of points too large for the time-step!)
00563   // the matrix is ill-conditionned: the last line is put as the first
00564   // one and all the others are shifted.
00565 
00566   for (int i=nr-3; i>=0; i--) {
00567     for (int j=((i>0) ? i-1 : 0); j<((i+5 > nr-1) ? nr-1 : i+5); j++) 
00568       tilde.set(i+1,j) = tilde(i,j) ;
00569     if (part) aux.set(i+1) = aux(i) ;
00570   }
00571   tilde.set(0,0) = 0.5 ;
00572   tilde.set(0,1) = 1. ;
00573   tilde.set(0,2) = 1. ;
00574   tilde.set(0,3) = 0. ;
00575   
00576   if (part) aux.set(0) = 0 ;
00577       
00578   // 2 over-diagonals and 2 under...
00579   tilde.set_band(2,2) ;
00580   
00581   // LU decomposition
00582   tilde.set_lu() ;
00583   
00584   // Inversion using LAPACK
00585   Tbl res0(tilde.inverse(aux)) ;
00586   Tbl res(nr) ;
00587   res.set_etat_qcq() ;
00588 
00589   // ... finally, one has to recover the original starting base
00590 
00591   res.set(0) = res0(0) ;
00592   res.set(nr-1) = res0(nr-2) ;
00593   for (int i=1; i<nr-1; i++) res.set(i) = res0(i-1) + res0(i);
00594   
00595   return res ;
00596 
00597     
00598 }
00599         //-------------------
00600            //--  R_CHEBI   -----
00601           //-------------------
00602 
00603 Tbl _dal_inverse_r_chebi_o2d_s(const Matrice &op, const Tbl &source, 
00604                    const bool part) {
00605 
00606   // Operator and source are copied and prepared
00607   int nr = op.get_dim(0) ;
00608   Matrice barre(nr-1,nr-1) ;
00609   barre.set_etat_qcq() ;
00610   for (int i=0; i<nr-1; i++) 
00611     for (int j=0; j<nr-1; j++)
00612       barre.set(i,j) = op(i,j) ;
00613   Tbl aux(nr-1) ;
00614   if (part) {
00615     aux.set_etat_qcq() ;
00616     for (int i=nr-4; i<nr-1; i++) aux.set(i) = source(i) ; 
00617   }
00618   else {
00619     aux.annule_hard() ;
00620     aux.set(nr-2) = 1 ;
00621   }
00622 
00623   // Operator is put into banded form (changing the image base )
00624   // Last column is quit.
00625 
00626   for (int i=0; i<nr-4; i++) {
00627     for (int j=i; j<nr-1; j++) {
00628       barre.set(i,j) = (op(i+1,j) - op(i,j))/(i+1) ;
00629     }
00630     if (part) aux.set(i) = (source(i+1) - source(i))/(i+1) ;
00631   }
00632   for (int i=0; i<nr-5; i++) {
00633     for (int j=i; j<nr-1; j++) barre.set(i,j) = barre(i+2,j) - barre(i,j) ;
00634     if (part) aux.set(i) = aux(i+2) - aux(i) ;
00635   }
00636   if (fabs(barre(nr-6,nr-2)) >= 1.e-16) {
00637     if (fabs(barre(nr-6,nr-2)) > fabs(barre(nr-3,nr-2))) {
00638       double lambda = barre(nr-3,nr-2)/barre(nr-6,nr-2) ; 
00639       for (int j=0; j<nr-1; j++) barre.set(nr-6,j) = barre(nr-6,j)*lambda
00640                    -barre(nr-3,j) ;
00641       if (part) aux.set(nr-6) = aux(nr-6)*lambda - aux(nr-3) ;
00642     }
00643     else {
00644       double lambda = barre(nr-6,nr-2)/barre(nr-3,nr-2) ; 
00645       for (int j=0; j<nr-1; j++) barre.set(nr-6,j) -= lambda*barre(nr-3,j) ;
00646       if (part) aux.set(nr-6) -= lambda*aux(nr-3) ;
00647     }
00648   }
00649 
00650   // 3 over-diagonals and 0 under...
00651   barre.set_band(3,0) ;
00652 
00653   // LU decomposition
00654   barre.set_lu() ;
00655 
00656   // Inversion using LAPACK
00657   Tbl res0(barre.inverse(aux)) ;
00658   Tbl res(nr) ;
00659   res.set_etat_qcq() ;
00660   for (int i=0; i<nr-1; i++) res.set(i) = res0(i) ;
00661   res.set(nr-1) = 0 ;
00662 
00663   return res ;
00664 }
00665 
00666 Tbl _dal_inverse_r_chebi_o2d_l(const Matrice &op, const Tbl &source, 
00667                    const bool part) {
00668 
00669   // Operator and source are copied and prepared
00670   Matrice barre(op) ;
00671   int nr = op.get_dim(0) ;
00672   Tbl aux(nr-1) ;
00673   if (part) {
00674     aux.set_etat_qcq() ;
00675     for (int i=0; i<nr-2; i++) aux.set(i) = source(i) ;
00676     aux.set(nr-2) = 0 ;
00677   }
00678   else {
00679     aux.annule_hard() ;
00680     aux.set(0) = 1 ;
00681   }
00682   // Operator is put into banded form (changing the image base)
00683   // Last column is quit.
00684 
00685   for (int i=0; i<nr-4; i++) {
00686     for (int j=i; j<nr-1; j++) {
00687       barre.set(i,j) = (op(i+1,j) - op(i,j))/(i+1) ;
00688     }
00689     if (part) aux.set(i) = (source(i+1) - source(i))/(i+1) ;
00690   }
00691   for (int i=0; i<nr-5; i++) {
00692     for (int j=i; j<nr-1; j++) barre.set(i,j) = barre(i+2,j) - barre(i,j) ;
00693     if (part) aux.set(i) = aux(i+2) - aux(i) ;
00694   }
00695   if (fabs(barre(nr-6,nr-2)) >= 1.e-16) {
00696     if (fabs(barre(nr-6,nr-2)) > fabs(barre(nr-3,nr-2))) {
00697       double lambda = barre(nr-3,nr-2)/barre(nr-6,nr-2) ; 
00698       for (int j=0; j<nr-1; j++) barre.set(nr-6,j) = barre(nr-6,j)*lambda
00699                    -barre(nr-3,j) ;
00700       if (part) aux.set(nr-6) = aux(nr-6)*lambda - aux(nr-3) ;
00701     }
00702     else {
00703       double lambda = barre(nr-6,nr-2)/barre(nr-3,nr-2) ; 
00704       for (int j=0; j<nr-1; j++) barre.set(nr-6,j) -= lambda*barre(nr-3,j) ;
00705       aux.set(nr-6) -= lambda*aux(nr-3) ;
00706     }
00707   }
00708 
00709   // In this case the time-step is too large for the number of points
00710   // (or the number of points too large for the time-step!)
00711   // the matrix is ill-conditionned: the last line is put as the first
00712   // one and all the others are shifted.
00713 
00714   Matrice tilde(nr-1,nr-1) ;
00715   tilde.set_etat_qcq() ;
00716   for (int i=nr-3; i>=0; i--) {
00717     for (int j=0; j<nr-1; j++) 
00718       tilde.set(i+1,j) = barre(i,j) ;
00719     if (part) aux.set(i+1) = aux(i) ;
00720   }
00721   tilde.set(0,0) = 1. ;
00722   tilde.set(0,1) = 1. ;
00723   tilde.set(0,2) = 1. ;
00724   tilde.set(0,3) = 0. ;
00725   
00726   if (part) aux.set(0) = 0 ;
00727       
00728 
00729   // 2 over-diagonals and 1 under...
00730   tilde.set_band(2,1) ;
00731 
00732   // LU decomposition
00733   tilde.set_lu() ;
00734 
00735   // Inversion using LAPACK
00736   Tbl res0(tilde.inverse(aux)) ;
00737   Tbl res(nr) ;
00738   res.set_etat_qcq() ;
00739   for (int i=0; i<nr-1; i++) res.set(i) = res0(i) ;
00740   res.set(nr-1) = 0 ;
00741 
00742   return res ;    
00743 }
00744     
00745 Tbl _dal_inverse_r_chebi_o2_s(const Matrice &op, const Tbl &source, 
00746                   const bool part) {
00747 
00748   // Operator and source are copied and prepared
00749   Matrice barre(op) ;
00750   int nr = op.get_dim(0) ;
00751   Tbl aux(nr-2) ;
00752   if (part) {
00753     aux.set_etat_qcq() ;
00754     aux.set(nr-4) = source(nr-4) ;
00755     aux.set(nr-3) = 0 ;
00756   }
00757   else {
00758     aux.annule_hard() ;
00759     aux.set(nr-3) = 1. ;
00760   }
00761 
00762   // Operator is put into banded form (changing the image base ...)
00763 
00764   for (int i=0; i<nr-4; i++) {
00765     for (int j=i; j<nr; j++) {
00766       barre.set(i,j) = (op(i+1,j) - op(i,j))/(i+1) ;
00767     }
00768     if (part)
00769       aux.set(i) = (source(i+1) - source(i))/(i+1) ;
00770   }
00771   for (int i=0; i<nr-5; i++) {
00772     for (int j=i; j<nr; j++) barre.set(i,j) = barre(i+2,j) - barre(i,j) ;
00773     if (part) aux.set(i) = aux(i+2) - aux(i) ;
00774   }
00775   
00776   // ... and changing the starting base (first and last columns are quit)... 
00777   
00778   Matrice tilde(nr-2,nr-2) ;
00779   tilde.set_etat_qcq() ;
00780   for (int i=0; i<nr-2; i++) 
00781     for (int j=0; j<nr-2;j++) 
00782       tilde.set(i,j) = barre(i,j+1)*(2*j+1) + barre(i,j)*(2*j+3) ;
00783   
00784   // 3 over-diagonals and 1 under...
00785   tilde.set_band(3,1) ;
00786   
00787   // LU decomposition
00788   tilde.set_lu() ;
00789 
00790   // Inversion using LAPACK
00791   Tbl res0(tilde.inverse(aux)) ;
00792   Tbl res(nr) ;
00793   res.set_etat_qcq() ;
00794 
00795   // ... finally, one has to recover the original starting base
00796 
00797   res.set(0) = 3*res0(0) ;
00798   for (int i=1; i<nr-2; i++) res.set(i) = res0(i-1)*(2*i-1) 
00799                    + res0(i)*(2*i+3) ;
00800   res.set(nr-2) = res0(nr-3)*(2*nr-5) ;
00801   res.set(nr-1) = 0 ;
00802 
00803   return res ;
00804 }
00805 
00806 Tbl _dal_inverse_r_chebi_o2_l(const Matrice &op, const Tbl &source, 
00807                   const bool part) {
00808 
00809   // Operator and source are copied and prepared
00810   Matrice barre(op) ;
00811   int nr = op.get_dim(0) ;
00812   Tbl aux(nr-2) ;
00813   if (part) {
00814     aux.set_etat_qcq() ;
00815     aux.set(nr-4) = source(nr-4) ;
00816     aux.set(nr-3) = 0 ;
00817   }
00818   else {
00819     aux.annule_hard() ;
00820     aux.set(0) = 1. ;
00821   }
00822 
00823   // Operator is put into banded form (changing the image base ...)
00824 
00825   for (int i=0; i<nr-4; i++) {
00826     for (int j=i; j<nr; j++) {
00827       barre.set(i,j) = (op(i+1,j) - op(i,j))/(i+1) ;
00828     }
00829     if (part)
00830       aux.set(i) = (source(i+1) - source(i))/(i+1) ;
00831     }
00832   for (int i=0; i<nr-5; i++) {
00833     for (int j=i; j<nr; j++) barre.set(i,j) = barre(i+2,j) - barre(i,j) ;
00834     if (part) aux.set(i) = aux(i+2) - aux(i) ;
00835   }
00836     
00837   // ... and changing the starting base (first and last columns are quit) ... 
00838   
00839   Matrice tilde(nr-2,nr-2) ;
00840   tilde.set_etat_qcq() ;
00841   for (int i=0; i<nr-2; i++) 
00842     for (int j=0; j<nr-2;j++) 
00843       tilde.set(i,j) = barre(i,j+1)*(2*j+1) + barre(i,j)*(2*j+3) ;
00844   
00845   // In this case the time-step is too large for the number of points
00846   // (or the number of points too large for the time-step!)
00847   // the matrix is ill-conditionned: the last line is put as the first
00848   // one and all the others are shifted.
00849 
00850   for (int i=nr-4; i>=0; i--) {
00851     for (int j=((i>0) ? i-1 : 0); j<((i+5 > nr-2) ? nr-2 : i+5); j++) 
00852       tilde.set(i+1,j) = tilde(i,j) ;
00853     if (part) aux.set(i+1) = aux(i) ;
00854   }
00855   tilde.set(0,0) = 1. ;
00856   tilde.set(0,1) = 1. ;
00857   tilde.set(0,2) = 1. ;
00858   tilde.set(0,3) = 0. ;
00859   
00860   if (part) aux.set(0) = 0 ;
00861       
00862 
00863   // 2 over-diagonals and 2 under...
00864   tilde.set_band(2,2) ;
00865 
00866   // LU decomposition
00867   tilde.set_lu() ;
00868   
00869   // Inversion using LAPACK
00870   Tbl res0(tilde.inverse(aux)) ;
00871   Tbl res(nr) ;
00872   res.set_etat_qcq() ;
00873   // ... finally, one has to recover the original starting base
00874   res.set(0) = 3*res0(0) ;
00875   for (int i=1; i<nr-2; i++) res.set(i) = res0(i-1)*(2*i-1) 
00876                    + res0(i)*(2*i+3) ;
00877   res.set(nr-2) = res0(nr-3)*(2*nr-5) ;
00878   res.set(nr-1) = 0 ;
00879   
00880   return res ;
00881 }
00882 
00883 Tbl _dal_inverse_r_jaco02(const Matrice &op, const Tbl &source, 
00884                   const bool part) {
00885 
00886   // Operator and source are copied and prepared
00887   Matrice barre(op) ;
00888   int nr = op.get_dim(0) ;
00889   Tbl aux(nr) ;
00890   if (part) {
00891     aux.set_etat_qcq() ;
00892     aux.set(nr-2) = source(nr-2) ;
00893     aux.set(nr-1) = 0 ;
00894   }
00895   else {
00896     aux.annule_hard() ;
00897     aux.set(0) = 1. ;
00898   }
00899 
00900   // Operator is put into banded form (changing the image base ...)
00901 
00902   for (int i=0; i<nr; i++) {
00903     for (int j=0; j<nr; j++) {
00904       barre.set(i,j) = (op(i,j)) ;
00905     }
00906     if (part)
00907       aux.set(i) = (source(i));
00908     }
00909   for (int i=0; i<nr; i++) {
00910     for (int j=0; j<nr; j++) barre.set(i,j) = barre(i,j) ;
00911     if (part) aux.set(i) = aux(i) ;
00912   }
00913     
00914   // ... and changing the starting base (first and last columns are quit) ... 
00915   
00916   Matrice tilde(nr,nr) ;
00917   tilde.set_etat_qcq() ;
00918   for (int i=0; i<nr; i++) 
00919     for (int j=0; j<nr;j++) 
00920       tilde.set(i,j) = barre(i,j) ;
00921   
00922   // LU decomposition
00923   tilde.set_lu() ;
00924   
00925   // Inversion using LAPACK
00926   Tbl res0(tilde.inverse(aux)) ;
00927   Tbl res(nr) ;
00928   res.set_etat_qcq() ;
00929   // ... finally, one has to recover the original starting base
00930   for (int i=0; i<nr; i++) res.set(i) = res0(i) ;
00931   
00932   return res ;
00933 }
00934 
00935 
00936 
00937             //----------------------------
00938            //--  Fonction a appeler   ---
00939           //----------------------------
00940           
00941           
00942 Tbl dal_inverse(const int& base_r, const int& type_dal, const 
00943         Matrice& operateur, const Tbl& source, const bool part) {
00944 
00945         // Routines de derivation
00946     static Tbl (*dal_inverse[MAX_BASE][MAX_DAL])(const Matrice&, const Tbl&, 
00947                          const bool) ;
00948     static int nap = 0 ;
00949 
00950         // Premier appel
00951     if (nap==0) {
00952     nap = 1 ;
00953     for (int i=0 ; i<MAX_DAL ; i++) {
00954       for (int j=0; j<MAX_BASE; j++) 
00955         dal_inverse[i][j] = _dal_inverse_pas_prevu ;
00956     }
00957         // Les routines existantes
00958 //      dal_inverse[R_CHEB >> TRA_R] = _dal_inverse_r_cheb ; not good!!
00959 //      dal_inverse[ORDRE1_SMALL][R_CHEB >> TRA_R] = 
00960 //        _dal_inverse_r_cheb_o1_s ;
00961 //      dal_inverse[ORDRE1_LARGE][R_CHEB >> TRA_R] = 
00962 //        _dal_inverse_r_cheb_o1_l ;
00963     dal_inverse[O2DEGE_SMALL][R_CHEB >> TRA_R] = 
00964       _dal_inverse_r_cheb_o2d_s ;
00965     dal_inverse[O2DEGE_LARGE][R_CHEB >> TRA_R] = 
00966       _dal_inverse_r_cheb_o2d_l ;
00967     dal_inverse[O2NOND_SMALL][R_CHEB >> TRA_R] = 
00968       _dal_inverse_r_cheb_o2_s ;
00969     dal_inverse[O2NOND_LARGE][R_CHEB >> TRA_R] = 
00970       _dal_inverse_r_cheb_o2_l ;
00971 //      dal_inverse[R_CHEB >> TRA_R] = _dal_inverse_r_cheb ; not good!!
00972 //      dal_inverse[ORDRE1_SMALL][R_CHEBP >> TRA_R] = 
00973 //        _dal_inverse_r_chebp_o1_s ;
00974 //      dal_inverse[ORDRE1_LARGE][R_CHEBP >> TRA_R] = 
00975 //        _dal_inverse_r_chebp_o1_l ;
00976     dal_inverse[O2DEGE_SMALL][R_CHEBP >> TRA_R] = 
00977       _dal_inverse_r_chebp_o2d_s ;
00978     dal_inverse[O2DEGE_LARGE][R_CHEBP >> TRA_R] = 
00979       _dal_inverse_r_chebp_o2d_l ;
00980     dal_inverse[O2NOND_SMALL][R_CHEBP >> TRA_R] = 
00981       _dal_inverse_r_chebp_o2_s ;
00982     dal_inverse[O2NOND_LARGE][R_CHEBP >> TRA_R] = 
00983       _dal_inverse_r_chebp_o2_l ;
00984 //      dal_inverse[ORDRE1_SMALL][R_CHEBI >> TRA_R] = 
00985 //        _dal_inverse_r_chebi_o1_s ;
00986 //      dal_inverse[ORDRE1_LARGE][R_CHEBI >> TRA_R] = 
00987 //        _dal_inverse_r_chebi_o1_l ;
00988     dal_inverse[O2DEGE_SMALL][R_CHEBI >> TRA_R] = 
00989       _dal_inverse_r_chebi_o2d_s ;
00990     dal_inverse[O2DEGE_LARGE][R_CHEBI >> TRA_R] = 
00991       _dal_inverse_r_chebi_o2d_l ;
00992     dal_inverse[O2NOND_SMALL][R_CHEBI >> TRA_R] = 
00993       _dal_inverse_r_chebi_o2_s ;
00994     dal_inverse[O2NOND_LARGE][R_CHEBI >> TRA_R] = 
00995       _dal_inverse_r_chebi_o2_l ;
00996 //  Only one routine pour Jacobi(0,2) polynomials
00997     dal_inverse[O2DEGE_SMALL][R_JACO02 >> TRA_R] = 
00998       _dal_inverse_r_jaco02 ;
00999     dal_inverse[O2DEGE_LARGE][R_JACO02 >> TRA_R] = 
01000       _dal_inverse_r_jaco02 ;
01001     dal_inverse[O2NOND_SMALL][R_JACO02 >> TRA_R] = 
01002       _dal_inverse_r_jaco02 ;
01003     dal_inverse[O2NOND_LARGE][R_JACO02 >> TRA_R] = 
01004       _dal_inverse_r_jaco02 ;    
01005 }
01006     
01007     return dal_inverse[type_dal][base_r](operateur,  source, part) ;
01008 }

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