bhole_pseudo_kerr.C

00001 /*
00002  *   Copyright (c) 2000-2001 Philippe Grandclement
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 bhole_pseudo_kerr_C[] = "$Header: /cvsroot/Lorene/C++/Source/Bhole/bhole_pseudo_kerr.C,v 1.5 2008/08/19 06:41:59 j_novak Exp $" ;
00024 
00025 /*
00026  * $Id: bhole_pseudo_kerr.C,v 1.5 2008/08/19 06:41:59 j_novak Exp $
00027  * $Log: bhole_pseudo_kerr.C,v $
00028  * Revision 1.5  2008/08/19 06:41:59  j_novak
00029  * Minor modifications to avoid warnings with gcc 4.3. Most of them concern
00030  * cast-type operations, and constant strings that must be defined as const char*
00031  *
00032  * Revision 1.4  2004/03/25 10:28:57  j_novak
00033  * All LORENE's units are now defined in the namespace Unites (in file unites.h).
00034  *
00035  * Revision 1.3  2003/10/03 15:58:43  j_novak
00036  * Cleaning of some headers
00037  *
00038  * Revision 1.2  2002/10/16 14:36:32  j_novak
00039  * Reorganization of #include instructions of standard C++, in order to
00040  * use experimental version 3 of gcc.
00041  *
00042  * Revision 1.1.1.1  2001/11/20 15:19:27  e_gourgoulhon
00043  * LORENE
00044  *
00045  * Revision 2.9  2001/05/16  14:51:36  phil
00046  * correction calcul de kij
00047  *
00048  * Revision 2.8  2001/05/07  12:24:30  phil
00049  * correction calcul de J
00050  *
00051  * Revision 2.7  2001/05/07  09:28:33  phil
00052  * *** empty log message ***
00053  *
00054  * Revision 2.6  2001/02/12  15:36:58  phil
00055  * ajout calcul de J a l infini
00056  *
00057  * Revision 2.5  2000/12/14  14:11:54  phil
00058  * correction cl sur psi
00059  *
00060  * Revision 2.4  2000/12/14  12:41:54  phil
00061  * on met les bases dans les sources
00062  *
00063  * Revision 2.3  2000/12/14  10:57:47  phil
00064  * corections diverses et sans importances
00065  *
00066  * Revision 2.2  2000/12/14  10:45:00  phil
00067  * ATTENTION : PASSAGE DE PHI A PSI
00068  *
00069  * Revision 2.1  2000/11/03  12:56:33  phil
00070  * ajout de const
00071  *
00072  * Revision 2.0  2000/10/20  09:19:09  phil
00073  * *** empty log message ***
00074  *
00075  *
00076  * $Header: /cvsroot/Lorene/C++/Source/Bhole/bhole_pseudo_kerr.C,v 1.5 2008/08/19 06:41:59 j_novak Exp $
00077  *
00078  */
00079 
00080 //standard
00081 #include <stdlib.h>
00082 #include <math.h>
00083 
00084 // Lorene
00085 #include "tenseur.h"
00086 #include "bhole.h"
00087 #include "proto.h"
00088 
00089 //Resolution pour le lapse pour 1 seul trou
00090 void Bhole::solve_lapse_seul (double relax) {
00091     
00092     assert ((relax>0) && (relax<=1)) ;
00093     
00094     cout << "Resolution LAPSE" << endl ;
00095     
00096     // Pour la relaxation ...
00097     Cmp lapse_old (n_auto()) ;
00098     Tenseur auxi (flat_scalar_prod(tkij_auto, tkij_auto)) ;
00099     Tenseur kk (mp) ;
00100     kk = 0 ;
00101     Tenseur work(mp) ;
00102     work.set_etat_qcq() ;
00103     for (int i=0 ; i<3 ; i++) {
00104     work.set() = auxi(i, i) ;
00105     kk = kk + work ;
00106     }
00107     
00108     // La source
00109     Cmp source 
00110     (-2*flat_scalar_prod(psi_auto.gradient(), n_auto.gradient())()/psi_auto()
00111     +pow(psi_auto(), 4.)*n_auto()*kk()) ;
00112     source.std_base_scal() ;
00113      
00114     // On resout pour N-1 :
00115     Valeur limite (mp.get_mg()->get_angu()) ;
00116     limite = -1 ;
00117     limite.std_base_scal() ;
00118     
00119     Cmp soluce (source.poisson_dirichlet(limite, 0)) ;
00120     soluce = soluce + 1 ;   // Permet de trouver N
00121     soluce.raccord(1) ;
00122     
00123     n_auto.set() = relax*soluce + (1-relax)*lapse_old ;
00124 }
00125 
00126 
00127 // Resolution sur Psi :
00128 void Bhole::solve_psi_seul (double relax) {
00129     
00130     assert ((relax>0) && (relax<=1)) ;
00131     
00132     cout << "Resolution PSI" << endl ;
00133     
00134     Cmp psi_old (psi_auto()) ;
00135     Tenseur auxi (flat_scalar_prod(tkij_auto, tkij_auto)) ;
00136     Tenseur kk (mp) ;
00137     kk = 0 ;
00138     Tenseur work(mp) ;
00139     work.set_etat_qcq() ;
00140     for (int i=0 ; i<3 ; i++) {
00141     work.set() = auxi(i, i) ;
00142     kk = kk + work ;
00143     }
00144     
00145     // La source :
00146     Cmp source (-pow(psi_auto(), 5.)*kk()/8.) ;
00147     source.std_base_scal() ;
00148     
00149     // La condition limite de type neumann :
00150     int np = mp.get_mg()->get_np(1) ;
00151     int nt = mp.get_mg()->get_nt(1) ;
00152     Valeur limite (mp.get_mg()->get_angu()) ;
00153     limite = 1 ;
00154     for (int k=0 ; k<np ; k++)
00155     for (int j=0 ; j<nt ; j++)
00156         limite.set(0, k, j, 0) = -0.5/rayon*psi_auto()(1, k, j, 0) ;
00157     limite.std_base_scal() ;
00158     
00159     Cmp soluce (source.poisson_neumann(limite, 0)) ;
00160     soluce = soluce + 1 ;
00161     soluce.raccord(1) ;
00162     
00163     psi_auto.set() = relax*soluce + (1-relax)*psi_old ;
00164     
00165 }
00166 
00167 
00168 // Le shift. Processus iteratif pour cause de CL.
00169 void Bhole::solve_shift_seul (double precision, double relax) {
00170     
00171     assert (precision > 0) ;
00172     assert ((relax>0) && (relax<=1)) ;
00173     
00174     cout << "resolution SHIFT" << endl ;
00175     
00176     Tenseur shift_old (shift_auto) ;
00177     
00178     Tenseur source (-6*flat_scalar_prod(taij_auto, psi_auto.gradient())/psi_auto
00179             + 2*flat_scalar_prod(tkij_auto, n_auto.gradient())) ;
00180     source.set_std_base() ;
00181     
00182     // On verifie si les 3 composantes ne sont pas nulles :
00183     if (source.get_etat() == ETATQCQ) {
00184     int indic = 0 ;
00185     for (int i=0 ; i<3 ; i++)
00186         if (source(i).get_etat() == ETATQCQ)
00187         indic = 1 ;
00188     if (indic ==0)
00189         source.set_etat_zero() ;
00190     }
00191     
00192     // On filtre les hautes frequences pour raison de stabilite :
00193     if (source.get_etat() == ETATQCQ)
00194     for (int i=0 ; i<3 ; i++)
00195             source.set(i).filtre(4) ;
00196     
00197     
00198     // On determine les conditions limites en fonction du omega et du boost :
00199     int np = mp.get_mg()->get_np(1) ;
00200     int nt = mp.get_mg()->get_nt(1) ;
00201     
00202     Mtbl x_mtbl (mp.get_mg()) ;
00203     x_mtbl.set_etat_qcq() ;
00204     Mtbl y_mtbl (mp.get_mg()) ;
00205     y_mtbl.set_etat_qcq() ;
00206     x_mtbl = mp.x ;
00207     y_mtbl = mp.y ;
00208     
00209     // Les bases pour les conditions limites :
00210     Base_val** bases = mp.get_mg()->std_base_vect_cart() ;
00211     
00212     Valeur lim_x (mp.get_mg()->get_angu()) ;
00213     lim_x = 1 ;
00214     for (int k=0 ; k<np ; k++)
00215     for (int j=0 ; j<nt ; j++)
00216         lim_x.set(0, k, j, 0) = omega*y_mtbl(1, k, j, 0)-boost[0] ;
00217     lim_x.base = *bases[0] ;
00218     
00219     Valeur lim_y (mp.get_mg()->get_angu()) ;
00220     lim_y = 1 ;
00221     for (int k=0 ; k<np ; k++)
00222     for (int j=0 ; j<nt ; j++)
00223         lim_y.set(0, k, j, 0) = - omega*x_mtbl(1, k, j, 0)-boost[1] ;
00224     lim_y.base = *bases[1] ;
00225    
00226     Valeur lim_z (mp.get_mg()->get_angu()) ;
00227     lim_z = 1 ;
00228     for (int k=0 ; k<np ; k++)
00229     for (int j=0 ; j<nt ; j++)
00230         lim_z.set(0, k, j, 0) = -boost[2] ;
00231     lim_z.base = *bases[2] ;
00232      
00233      // On n'en a plus besoin
00234     for (int i=0 ; i<3 ; i++)
00235     delete bases[i] ;
00236     delete [] bases ;
00237     
00238     // On resout :
00239     poisson_vect_frontiere(1./3., source, shift_auto, lim_x, lim_y, 
00240                     lim_z, 0, precision, 20) ;
00241       
00242     shift_auto = relax*shift_auto + (1-relax)*shift_old ;
00243 }
00244 
00245 
00246 // La regularisation si un seul trou noir :
00247 void Bhole::regularise_seul () {
00248     
00249     // Le vecteur B (non tournant et non boostant)
00250     Tenseur tbi (shift_auto) ;
00251     for (int i=0 ; i<3 ; i++) {
00252     tbi.set(i).va.coef_i() ;
00253     tbi.set(i).va.set_etat_c_qcq() ;
00254     }
00255     
00256     for (int i=0 ; i<3 ; i++)
00257     shift_auto(i).va.coef_i() ;
00258     
00259     tbi.set(0) = *shift_auto(0).va.c - omega*shift_auto.get_mp()->y + boost[0];
00260     tbi.set(1) = *shift_auto(1).va.c + omega*shift_auto.get_mp()->x + boost[1];
00261     tbi.set(2) = *shift_auto(2).va.c + boost[2];
00262     tbi.set_std_base() ;
00263     
00264     // On evite soucis a l'infini (on a besoin que de la valeur sur horizon
00265     tbi.set(0).annule(mp.get_mg()->get_nzone()-1) ;
00266     tbi.set(1).annule(mp.get_mg()->get_nzone()-1) ;
00267       
00268     Tenseur derive_r (mp, 1, CON, mp.get_bvect_cart()) ;
00269     derive_r.set_etat_qcq() ;
00270     for (int i=0 ; i<3 ; i++)
00271     derive_r.set(i) = tbi(i).dsdr() ;
00272     
00273     Valeur val_hor (mp.get_mg()) ;
00274     Valeur fonction_radiale (mp.get_mg()) ;
00275     Cmp enleve (mp) ;
00276     
00277     double erreur = 0 ;
00278     int nz = mp.get_mg()->get_nzone() ;
00279     int np = mp.get_mg()->get_np(1) ;
00280     int nt = mp.get_mg()->get_nt(1) ;
00281     int nr = mp.get_mg()->get_nr(1) ;
00282     
00283     double r_0 = mp.val_r(1, -1, 0, 0) ;
00284     double r_1 = mp.val_r(1, 1, 0, 0) ;
00285     
00286     for (int comp=0 ; comp<3 ; comp++) {
00287     val_hor.annule_hard() ;
00288     for (int k=0 ; k<np ; k++)
00289         for (int j=0 ; j<nt ; j++)
00290         for (int i=0 ; i<nr ; i++)
00291             val_hor.set(1, k, j, i) = derive_r(comp)(1, k, j, 0) ;
00292     
00293     fonction_radiale = pow(r_1-mp.r, 3.)* (mp.r-r_0)/pow(r_1-r_0, 3.) ;
00294     fonction_radiale.annule(0) ;
00295     fonction_radiale.annule(2, nz-1) ;
00296     
00297     enleve = fonction_radiale*val_hor ;
00298     enleve.va.base = shift_auto(comp).va.base ;
00299     
00300     // Ca devrai annuler la derivee de B sur H et donc rendre K regulier
00301     Cmp copie (shift_auto(comp)) ;
00302     shift_auto.set(comp) = shift_auto(comp)-enleve ;
00303     
00304     assert (shift_auto(comp).check_dzpuis(0)) ;
00305     
00306     // On regarde l'intensite de la correction si non nul !
00307         Tbl norm (norme(shift_auto(comp))) ;
00308         if (norm(1) > 1e-5) {
00309         Tbl diff (diffrelmax (copie, shift_auto(comp))) ;
00310         if (erreur<diff(1))
00311             erreur = diff(1) ;
00312         }
00313     }
00314     regul = erreur ;
00315 }
00316 
00317 // On calcul Kij sachant que la regulatisation sur le shift doit 
00318 // etre faite avant.
00319 void Bhole::fait_tkij () {
00320     
00321     fait_taij_auto() ;
00322     
00323     Cmp lapse_non_sing (division_xpun(n_auto(), 0)) ;
00324     Cmp auxi (mp) ;
00325     
00326     tkij_auto.set_etat_qcq() ;
00327     for (int i=0 ; i<3 ; i++)
00328     for (int j=i ; j<3 ; j++) {
00329         auxi = taij_auto(i, j) ;
00330         auxi = division_xpun (auxi, 0) ;
00331         tkij_auto.set(i, j) = auxi/lapse_non_sing/2. ;
00332         tkij_auto.set(i, j).raccord(1) ;
00333     }
00334 }
00335 
00336 // Calcul masse ADM via valeur asymptotiques
00337 double Bhole::masse_adm_seul () const {
00338     
00339     Cmp integrant (psi_auto().dsdr()) ;
00340     double masse = mp.integrale_surface_infini (integrant) ;
00341     masse /= -2*M_PI ;
00342     return masse ;
00343 }
00344 
00345 double Bhole::masse_komar_seul() const {
00346     
00347     Cmp integrant (n_auto().dsdr()) ;
00348     double masse = mp.integrale_surface_infini (integrant) ;
00349     masse /= 4*M_PI ;
00350     return masse ;
00351 }
00352 
00353 // Calcul du moment angulaire via integrale a l infini
00354 // Non valable si le boost != 0 ;
00355 
00356 double Bhole::moment_seul_inf() const {
00357 
00358     // On verifie si le boost est bien nul :
00359     double indic = 0 ;
00360     for (int i=0 ; i<3 ; i++)
00361     if (boost[i] != 0)
00362         indic = 1 ;
00363     if (indic == 1) {
00364     cout << "Calcul du moment non valable pour un boost != 0" << endl ;
00365     abort() ;
00366     }
00367     
00368     if (omega == 0)
00369     return 0 ;
00370     else {
00371     Tenseur vecteur_un (mp, 1, CON, mp.get_bvect_cart()) ;
00372     vecteur_un.set_etat_qcq() ;
00373     for (int i=0 ; i<3 ; i++)
00374         vecteur_un.set(i) = tkij_auto(0, i) ;
00375     vecteur_un.change_triad (mp.get_bvect_spher()) ;
00376     Cmp integrant_un (vecteur_un(0)) ;
00377     integrant_un.mult_r_zec() ;
00378     
00379     Tenseur vecteur_deux (mp, 1, CON, mp.get_bvect_cart()) ;
00380     vecteur_deux.set_etat_qcq() ;
00381     for (int i=0 ; i<3 ; i++)
00382         vecteur_deux.set(i) = tkij_auto(1, i) ;
00383     vecteur_deux.change_triad (mp.get_bvect_spher()) ;
00384     Cmp integrant_deux (vecteur_deux(0)) ;
00385     integrant_deux.mult_r_zec() ;
00386     
00387     // On multiplie par y et x :
00388     integrant_un.va = integrant_un.va.mult_st() ;
00389     integrant_un.va = integrant_un.va.mult_sp() ;
00390     
00391     integrant_deux.va = integrant_deux.va.mult_st() ;
00392     integrant_deux.va = integrant_deux.va.mult_cp() ;
00393     
00394     double moment = mp.integrale_surface_infini (-integrant_un+integrant_deux) ;
00395     moment /= 8*M_PI ;
00396     return moment ;
00397     }
00398 }
00399 
00400 // Calcul du moment angulaire via integrale sur l horizon
00401 // Non valable si le boost != 0 ;
00402 
00403 double Bhole::moment_seul_hor() const {
00404 
00405     // On verifie si le boost est bien nul :
00406     double indic = 0 ;
00407     for (int i=0 ; i<3 ; i++)
00408     if (boost[i] != 0)
00409         indic = 1 ;
00410     if (indic == 1) {
00411     cout << "Calcul du moment non valable pour un boost != 0" << endl ;
00412     abort() ;
00413     }
00414     
00415     if (omega == 0)
00416     return 0 ;
00417     else {
00418     // Integrale sur l horizon :
00419     Cmp xa (mp) ;
00420     xa = mp.xa ;
00421     xa.std_base_scal() ;
00422     
00423     Cmp ya (mp) ;
00424     ya = mp.ya ;
00425     ya.std_base_scal() ;
00426     
00427     Tenseur vecteur (mp, 1, CON, mp.get_bvect_cart()) ;
00428     vecteur.set_etat_qcq() ;
00429     for (int i=0 ; i<3 ; i++)
00430         vecteur.set(i) = (-ya*tkij_auto(0, i)+xa * tkij_auto(1, i)) ;
00431     vecteur.set_std_base() ;
00432     vecteur.annule(mp.get_mg()->get_nzone()-1) ;
00433     vecteur.change_triad (mp.get_bvect_spher()) ;
00434     
00435     Cmp integrant (pow(psi_auto(), 6)*vecteur(0)) ;
00436     integrant.std_base_scal() ;
00437     double moment = mp.integrale_surface (integrant, rayon)/8/M_PI ;
00438     return moment ;
00439     }
00440 }
00441 

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