et_rot_isco.C

00001 /*
00002  * Method of class Etoile_rot to compute the location of the ISCO
00003  *
00004  * (see file etoile.h for documentation).
00005  *
00006  */
00007 
00008 /*
00009  *   Copyright (c) 2000-2001 Eric Gourgoulhon
00010  *   Copyright (c) 2000-2001 J. Leszek Zdunik
00011  *
00012  *   This file is part of LORENE.
00013  *
00014  *   LORENE is free software; you can redistribute it and/or modify
00015  *   it under the terms of the GNU General Public License as published by
00016  *   the Free Software Foundation; either version 2 of the License, or
00017  *   (at your option) any later version.
00018  *
00019  *   LORENE is distributed in the hope that it will be useful,
00020  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00021  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00022  *   GNU General Public License for more details.
00023  *
00024  *   You should have received a copy of the GNU General Public License
00025  *   along with LORENE; if not, write to the Free Software
00026  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00027  *
00028  */
00029 
00030 
00031 char et_rot_isco_C[] = "$Header: /cvsroot/Lorene/C++/Source/Etoile/et_rot_isco.C,v 1.3 2011/01/07 18:20:08 m_bejger Exp $" ;
00032 
00033 /*
00034  * $Id: et_rot_isco.C,v 1.3 2011/01/07 18:20:08 m_bejger Exp $
00035  * $Log: et_rot_isco.C,v $
00036  * Revision 1.3  2011/01/07 18:20:08  m_bejger
00037  * Correcting for the case of stiff EOS, in which ISCO may be farther than the first domain outside the star - now searching all non-compactified domains
00038  *
00039  * Revision 1.2  2001/12/06 15:11:43  jl_zdunik
00040  * Introduction of the new function f_eq() in the class Etoile_rot
00041  *
00042  * Revision 1.1.1.1  2001/11/20 15:19:28  e_gourgoulhon
00043  * LORENE
00044  *
00045  * Revision 2.2  2001/03/26  09:31:13  jlz
00046  * New functions: espec_isco() and lspec_isco().
00047  *
00048  * Revision 2.1  2000/11/18  23:18:08  eric
00049  * Ajout de l'argument ost a Etoile_rot::r_isco. Ajout de l'argument ost a Etoile_rot::r_isco.
00050  *
00051  * Revision 2.0  2000/11/18  21:10:41  eric
00052  * *** empty log message ***
00053  *
00054  *
00055  * $Header: /cvsroot/Lorene/C++/Source/Etoile/et_rot_isco.C,v 1.3 2011/01/07 18:20:08 m_bejger Exp $
00056  *
00057  */
00058 
00059 // Headers C
00060 #include <math.h>
00061 
00062 // Headers Lorene
00063 #include "etoile.h"
00064 #include "param.h"
00065 #include "utilitaires.h"
00066 
00067 double fonct_etoile_rot_isco(double, const Param&) ;
00068 
00069 
00070 //=============================================================================
00071 //      r_isco()
00072 //=============================================================================
00073 
00074 double Etoile_rot::r_isco(ostream* ost) const {
00075 
00076     if (p_r_isco == 0x0) {    // a new computation is required
00077 
00078     // First and second derivatives of metric functions
00079     // ------------------------------------------------
00080 
00081     int nzm1 = mp.get_mg()->get_nzone() - 1 ;
00082     Cmp dnphi = nphi().dsdr() ;
00083     dnphi.annule(nzm1) ;
00084     Cmp ddnphi = dnphi.dsdr() ;     // d^2/dr^2 N^phi
00085 
00086     Cmp tmp = nnn().dsdr() ;
00087     tmp.annule(nzm1) ;
00088     Cmp ddnnn = tmp.dsdr() ;        // d^2/dr^2 N
00089 
00090     tmp = bbb().dsdr() ;
00091     tmp.annule(nzm1) ;
00092     Cmp ddbbb = tmp.dsdr() ;        // d^2/dr^2 B
00093 
00094     // Constructing the velocity of a particle corotating with the star
00095     // ----------------------------------------------------------------
00096 
00097     Cmp bdlog = bbb().dsdr() / bbb() ;
00098     Cmp ndlog = nnn().dsdr() / nnn() ;
00099     Cmp bsn = bbb() / nnn() ;
00100 
00101     Cmp r(mp) ;
00102     r = mp.r ;
00103 
00104     Cmp r2= r*r ;
00105 
00106     bdlog.annule(nzm1) ;
00107     ndlog.annule(nzm1) ;
00108     bsn.annule(nzm1) ;
00109     r2.annule(nzm1) ;
00110 
00111     // ucor_plus - the velocity of corotating particle on the circular orbit
00112     Cmp ucor_plus = (r2 * bsn * dnphi +
00113         sqrt ( r2 * r2 * bsn *bsn * dnphi * dnphi +
00114         4 * r2 * bdlog * ndlog + 4 * r * ndlog) ) /
00115         2 / (1 + r * bdlog ) ;
00116 
00117     Cmp factor_u2 = r2 * (2 * ddbbb / bbb() - 2 * bdlog * bdlog +
00118                           4 * bdlog * ndlog ) +
00119        2 * r2 * r2 * bsn * bsn * dnphi * dnphi +
00120        4 * r * ( ndlog - bdlog ) - 6 ;
00121 
00122     Cmp factor_u1 = 2 * r * r2 * bsn * ( 2 * ( ndlog - bdlog ) *
00123                     dnphi - ddnphi ) ;
00124 
00125     Cmp factor_u0 = - r2 * ( 2 * ddnnn / nnn() - 2 * ndlog * ndlog +
00126                      4 * bdlog * ndlog ) ;
00127 
00128     // Scalar field the zero of which will give the marginally stable orbit
00129     Cmp orbit = factor_u2 * ucor_plus * ucor_plus +
00130                 factor_u1 * ucor_plus + factor_u0 ;
00131     orbit.std_base_scal() ;
00132     
00133     // Search for the zero
00134     // -------------------
00135 
00136     double r_ms, theta_ms, phi_ms, xi_ms, 
00137            xi_min = -1, xi_max = 1;  
00138     int l_ms = nzet, l ;
00139     bool find_status = false ; 
00140 
00141     const Valeur& vorbit = orbit.va ;
00142     
00143     for(l = nzet; l <= nzm1; l++) { 
00144 
00145     // Preliminary location of the zero
00146     // of the orbit function with an error = 0.01
00147     theta_ms = M_PI / 2. ; // pi/2
00148     phi_ms = 0. ;
00149 
00150     xi_min = -1. ;
00151     xi_max = 1. ;
00152 
00153     double resloc_old ;
00154     double xi_f = xi_min;
00155     
00156     double resloc = vorbit.val_point(l, xi_min, theta_ms, phi_ms) ;
00157     
00158     for (int iloc=0; iloc<200; iloc++) {
00159         xi_f = xi_f + 0.01 ;
00160         resloc_old = resloc ;
00161         resloc = vorbit.val_point(l, xi_f, theta_ms, phi_ms) ;
00162         if ( resloc * resloc_old < double(0) ) {
00163             xi_min = xi_f - 0.01 ;
00164             xi_max = xi_f ;
00165             l_ms = l ; 
00166             find_status = true ;  
00167             break ;
00168         } 
00169         
00170       }
00171     
00172     } 
00173     
00174     Param par_ms ;
00175     par_ms.add_int(l_ms) ;
00176     par_ms.add_cmp(orbit) ;
00177 
00178     if(find_status) { 
00179     
00180         double precis_ms = 1.e-13 ;    // precision in the determination of xi_ms
00181         int nitermax_ms = 200 ;        // max number of iterations
00182         
00183         int niter ;
00184         xi_ms = zerosec(fonct_etoile_rot_isco, par_ms, xi_min, xi_max,
00185                         precis_ms, nitermax_ms, niter) ;
00186 
00187         if (ost != 0x0) {
00188             * ost <<
00189             "    number of iterations used in zerosec to locate the ISCO : "
00190              << niter << endl ;
00191             *ost << "    zero found at xi = " << xi_ms << endl ;
00192         }
00193 
00194         r_ms = mp.val_r(l_ms, xi_ms, theta_ms, phi_ms) ;
00195     
00196     } else { 
00197         
00198         // assuming the ISCO is under the surface of a star 
00199         r_ms = ray_eq() ; 
00200         xi_ms = -1 ; 
00201         l_ms = nzet ; 
00202         
00203     } 
00204 
00205     p_r_isco = new double ((bbb().va).val_point(l_ms, xi_ms, theta_ms, phi_ms)
00206              * r_ms ) ;
00207 
00208     // Determination of the frequency at the marginally stable orbit
00209     // -------------------------------------------------------------                
00210 
00211     ucor_plus.std_base_scal() ;
00212     double ucor_msplus = (ucor_plus.va).val_point(l_ms, xi_ms, theta_ms,
00213                                                   phi_ms) ;
00214     double nobrs = (bsn.va).val_point(l_ms, xi_ms, theta_ms, phi_ms) ;
00215     double nphirs = (nphi().va).val_point(l_ms, xi_ms, theta_ms, phi_ms) ;
00216     
00217     p_f_isco = new double ( ( ucor_msplus / nobrs / r_ms + nphirs ) /
00218                                 (double(2) * M_PI) ) ;
00219 
00220     // Specific angular momentum on ms orbit
00221     // -------------------------------------                
00222     p_lspec_isco=new double (ucor_msplus/sqrt(1.-ucor_msplus*ucor_msplus)*
00223     ((bbb().va).val_point(l_ms, xi_ms, theta_ms, phi_ms)) * r_ms );
00224 
00225     // Specific energy on ms orbit
00226     // ---------------------------          
00227     p_espec_isco=new double (( 1./nobrs / r_ms / ucor_msplus  + nphirs) *
00228     (ucor_msplus/sqrt(1.-ucor_msplus*ucor_msplus)*
00229     ((bbb().va).val_point(l_ms, xi_ms, theta_ms, phi_ms)) * r_ms ));
00230 
00231     // Determination of the Keplerian frequency at the equator
00232     // -------------------------------------------------------------
00233 
00234     double ucor_eqplus = (ucor_plus.va).val_point(l_ms, -1, theta_ms, phi_ms) ;
00235     double nobeq = (bsn.va).val_point(l_ms, -1, theta_ms, phi_ms) ;
00236     double nphieq = (nphi().va).val_point(l_ms, -1, theta_ms, phi_ms) ;
00237 
00238     p_f_eq = new double ( ( ucor_eqplus / nobeq / ray_eq() + nphieq ) /
00239                   (double(2) * M_PI) ) ;
00240 
00241     }  // End of computation
00242 
00243     return *p_r_isco ;
00244 
00245 }
00246 
00247 //=============================================================================
00248 //      f_isco()
00249 //=============================================================================
00250 
00251 double Etoile_rot::f_isco() const {
00252 
00253     if (p_f_isco == 0x0) {    // a new computation is required
00254 
00255         r_isco() ;      // f_isco is computed in the method r_isco()
00256 
00257         assert(p_f_isco != 0x0) ;
00258     }
00259 
00260     return *p_f_isco ;
00261 
00262 }
00263 
00264 //=============================================================================
00265 //      lspec_isco()
00266 //=============================================================================
00267 
00268 double Etoile_rot::lspec_isco() const {
00269 
00270     if (p_lspec_isco == 0x0) {    // a new computation is required
00271 
00272         r_isco() ;  // lspec_isco is computed in the method r_isco()
00273 
00274         assert(p_lspec_isco != 0x0) ;
00275     }
00276 
00277     return *p_lspec_isco ;
00278 
00279 }
00280 
00281 //=============================================================================
00282 //      espec_isco()
00283 //=============================================================================
00284 
00285 double Etoile_rot::espec_isco() const {
00286 
00287     if (p_espec_isco == 0x0) {    // a new computation is required
00288 
00289         r_isco() ;  // espec_isco is computed in the method r_isco()
00290 
00291         assert(p_espec_isco != 0x0) ;
00292     }
00293 
00294     return *p_espec_isco ;
00295 
00296 }
00297 
00298 
00299 //=============================================================================
00300 //              f_eq()
00301 //=============================================================================
00302 
00303 double Etoile_rot::f_eq() const {
00304   
00305   if (p_f_eq == 0x0) {    // a new computation is required
00306 
00307     r_isco() ;              // f_eq is computed in the method r_isco()
00308 
00309     assert(p_f_eq != 0x0) ;
00310   }
00311 
00312   return *p_f_eq ;
00313 
00314 }
00315 
00316 
00317 //=============================================================================
00318 //  Function used to locate the MS orbit
00319 //=============================================================================
00320 
00321 
00322 double fonct_etoile_rot_isco(double xi, const Param& par){
00323 
00324     // Retrieval of the information:
00325     int l_ms = par.get_int() ;
00326     const Cmp& orbit = par.get_cmp() ;
00327     const Valeur& vorbit = orbit.va ;
00328 
00329     // Value et the desired point
00330     double theta = M_PI / 2. ;
00331     double phi = 0 ;
00332     return vorbit.val_point(l_ms, xi, theta, phi) ;
00333 
00334 }
00335 

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