star_rot_isco.C

00001 /*
00002  * Method of class Star_rot to compute the location of the ISCO
00003  *
00004  * (see file star_rot.h for documentation).
00005  *
00006  */
00007 
00008 /*
00009  *   Copyright (c) 2010 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 star_rot_isco_C[] = "$Header: /cvsroot/Lorene/C++/Source/Star/star_rot_isco.C,v 1.3 2011/01/07 18:20:21 m_bejger Exp $" ;
00032 
00033 /*
00034  * $Id: star_rot_isco.C,v 1.3 2011/01/07 18:20:21 m_bejger Exp $
00035  * $Log: star_rot_isco.C,v $
00036  * Revision 1.3  2011/01/07 18:20:21  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  2010/01/25 22:33:04  e_gourgoulhon
00040  * First implementation.
00041  *
00042  * Revision 1.1  2010/01/25 18:15:52  e_gourgoulhon
00043  * First version.
00044  *
00045  *
00046  * $Header: /cvsroot/Lorene/C++/Source/Star/star_rot_isco.C,v 1.3 2011/01/07 18:20:21 m_bejger Exp $
00047  *
00048  */
00049 
00050 // Headers C
00051 #include <math.h>
00052 
00053 // Headers Lorene
00054 #include "star_rot.h"
00055 #include "param.h"
00056 #include "utilitaires.h"
00057 
00058 double funct_star_rot_isco(double, const Param& ) ; 
00059 
00060 //=============================================================================
00061 //      r_isco()
00062 //=============================================================================
00063 
00064 double Star_rot::r_isco(ostream* ost) const {
00065 
00066     if (p_r_isco == 0x0) {    // a new computation is required
00067 
00068     // First and second derivatives of metric functions
00069     // ------------------------------------------------
00070 
00071     int nzm1 = mp.get_mg()->get_nzone() - 1 ;
00072     Scalar dnphi = nphi.dsdr() ;
00073     dnphi.annule_domain(nzm1) ;
00074     Scalar ddnphi = dnphi.dsdr() ;      // d^2/dr^2 N^phi
00075 
00076     Scalar tmp = nn.dsdr() ;
00077     tmp.annule_domain(nzm1) ;
00078     Scalar ddnnn = tmp.dsdr() ;         // d^2/dr^2 N
00079 
00080     tmp = bbb.dsdr() ;
00081     tmp.annule_domain(nzm1) ;
00082     Scalar ddbbb = tmp.dsdr() ;         // d^2/dr^2 B
00083 
00084     // Constructing the velocity of a particle corotating with the star
00085     // ----------------------------------------------------------------
00086 
00087     Scalar bdlog = bbb.dsdr() / bbb ;
00088     Scalar ndlog = nn.dsdr() / nn ;
00089     Scalar bsn = bbb / nn ;
00090 
00091     Scalar r(mp) ;
00092     r = mp.r ;
00093 
00094     Scalar r2= r*r ;
00095 
00096     bdlog.annule_domain(nzm1) ;
00097     ndlog.annule_domain(nzm1) ;
00098     bsn.annule_domain(nzm1) ;
00099     r2.annule_domain(nzm1) ;
00100 
00101     // ucor_plus - the velocity of corotating particle on the circular orbit
00102     Scalar ucor_plus = (r2 * bsn * dnphi +
00103         sqrt ( r2 * r2 * bsn *bsn * dnphi * dnphi +
00104         4 * r2 * bdlog * ndlog + 4 * r * ndlog) ) /
00105         2 / (1 + r * bdlog ) ;
00106 
00107     Scalar factor_u2 = r2 * (2 * ddbbb / bbb - 2 * bdlog * bdlog +
00108                           4 * bdlog * ndlog ) +
00109        2 * r2 * r2 * bsn * bsn * dnphi * dnphi +
00110        4 * r * ( ndlog - bdlog ) - 6 ;
00111 
00112     Scalar factor_u1 = 2 * r * r2 * bsn * ( 2 * ( ndlog - bdlog ) *
00113                     dnphi - ddnphi ) ;
00114 
00115     Scalar factor_u0 = - r2 * ( 2 * ddnnn / nn - 2 * ndlog * ndlog +
00116                      4 * bdlog * ndlog ) ;
00117 
00118     // Scalar field the zero of which will give the marginally stable orbit
00119     Scalar orbit = factor_u2 * ucor_plus * ucor_plus +
00120                 factor_u1 * ucor_plus + factor_u0 ;
00121     orbit.std_spectral_base() ;
00122     
00123     // Search for the zero
00124     // -------------------
00125 
00126     double r_ms, theta_ms, phi_ms, xi_ms, 
00127            xi_min = -1, xi_max = 1; 
00128     int l_ms = nzet, l ;
00129     bool find_status = false ; 
00130 
00131     const Valeur& vorbit = orbit.get_spectral_va() ;
00132         
00133     for(l = nzet; l <= nzm1; l++) { 
00134 
00135     // Preliminary location of the zero
00136     // of the orbit function with an error = 0.01
00137     theta_ms = M_PI / 2. ; // pi/2
00138     phi_ms = 0. ;
00139 
00140     xi_min = -1. ;
00141     xi_max = 1. ;
00142 
00143     double resloc_old ;
00144     double xi_f = xi_min;
00145     
00146     double resloc = vorbit.val_point(l, xi_min, theta_ms, phi_ms) ;
00147     
00148     for (int iloc=0; iloc<200; iloc++) {
00149         xi_f = xi_f + 0.01 ;
00150         resloc_old = resloc ;
00151         resloc = vorbit.val_point(l, xi_f, theta_ms, phi_ms) ;
00152         if ( resloc * resloc_old < double(0) ) {
00153             xi_min = xi_f - 0.01 ;
00154             xi_max = xi_f ;
00155             l_ms = l ; 
00156             find_status = true ;  
00157             break ;
00158         } 
00159         
00160       }
00161     
00162     } 
00163     
00164     Param par_ms ;
00165     par_ms.add_int(l_ms) ;
00166     par_ms.add_scalar(orbit) ;
00167     
00168     if(find_status) { 
00169                             
00170         double precis_ms = 1.e-12 ;    // precision in the determination 
00171                                        // of xi_ms
00172         int nitermax_ms = 100 ;        // max number of iterations
00173 
00174         int niter ;
00175         xi_ms = zerosec(funct_star_rot_isco, par_ms, xi_min, xi_max,
00176                         precis_ms, nitermax_ms, niter) ;                        
00177         if (ost != 0x0) {
00178             * ost <<
00179             "    number of iterations used in zerosec to locate the ISCO : "
00180              << niter << endl ;
00181             *ost << "    zero found at xi = " << xi_ms << endl ;
00182         }
00183 
00184         r_ms = mp.val_r(l_ms, xi_ms, theta_ms, phi_ms) ;
00185     
00186     } else { 
00187         
00188         // assuming the ISCO is under the surface of a star 
00189         r_ms = ray_eq() ; 
00190         xi_ms = -1 ; 
00191         l_ms = nzet ; 
00192         
00193     } 
00194     
00195     p_r_isco = new double (
00196         (bbb.get_spectral_va()).val_point(l_ms, xi_ms, theta_ms, phi_ms) * r_ms
00197                           ) ;
00198 
00199     // Determination of the frequency at the marginally stable orbit
00200     // -------------------------------------------------------------                
00201 
00202     ucor_plus.std_spectral_base() ;
00203     double ucor_msplus = (ucor_plus.get_spectral_va()).val_point(l_ms, xi_ms, theta_ms,
00204                                                   phi_ms) ;
00205     double nobrs = (bsn.get_spectral_va()).val_point(l_ms, xi_ms, theta_ms, phi_ms) ;
00206     double nphirs = (nphi.get_spectral_va()).val_point(l_ms, xi_ms, theta_ms, phi_ms) ;
00207     
00208     p_f_isco = new double ( ( ucor_msplus / nobrs / r_ms + nphirs ) /
00209                                 (double(2) * M_PI) ) ;
00210 
00211     // Specific angular momentum on ms orbit
00212     // -------------------------------------                
00213     p_lspec_isco=new double (ucor_msplus/sqrt(1.-ucor_msplus*ucor_msplus)*
00214     ((bbb.get_spectral_va()).val_point(l_ms, xi_ms, theta_ms, phi_ms)) * r_ms );
00215 
00216     // Specific energy on ms orbit
00217     // ---------------------------          
00218     p_espec_isco=new double (( 1./nobrs / r_ms / ucor_msplus  + nphirs) *
00219     (ucor_msplus/sqrt(1.-ucor_msplus*ucor_msplus)*
00220     ((bbb.get_spectral_va()).val_point(l_ms, xi_ms, theta_ms, phi_ms)) * r_ms ));
00221 
00222         // Determination of the Keplerian frequency at the equator
00223     // -------------------------------------------------------------
00224 
00225 
00226     double ucor_eqplus = (ucor_plus.get_spectral_va()).val_point(l_ms, -1, theta_ms,phi_ms)
00227       ;
00228     double nobeq = (bsn.get_spectral_va()).val_point(l_ms, -1, theta_ms, phi_ms) ;
00229     double nphieq = (nphi.get_spectral_va()).val_point(l_ms, -1, theta_ms, phi_ms) ;
00230 
00231     p_f_eq = new double ( ( ucor_eqplus / nobeq / ray_eq() + nphieq ) /
00232                   (double(2) * M_PI) ) ;
00233 
00234     
00235 
00236     }  // End of computation
00237 
00238     return *p_r_isco ;
00239 
00240 }
00241 
00242 
00243 
00244 //=============================================================================
00245 //      f_isco()
00246 //=============================================================================
00247 
00248 double Star_rot::f_isco() const {
00249 
00250     if (p_f_isco == 0x0) {    // a new computation is required
00251 
00252         r_isco() ;      // f_isco is computed in the method r_isco()
00253 
00254         assert(p_f_isco != 0x0) ;
00255     }
00256 
00257     return *p_f_isco ;
00258 
00259 }
00260 
00261 //=============================================================================
00262 //      lspec_isco()
00263 //=============================================================================
00264 
00265 double Star_rot::lspec_isco() const {
00266 
00267     if (p_lspec_isco == 0x0) {    // a new computation is required
00268 
00269         r_isco() ;  // lspec_isco is computed in the method r_isco()
00270 
00271         assert(p_lspec_isco != 0x0) ;
00272     }
00273 
00274     return *p_lspec_isco ;
00275 
00276 }
00277 
00278 //=============================================================================
00279 //      espec_isco()
00280 //=============================================================================
00281 
00282 double Star_rot::espec_isco() const {
00283 
00284     if (p_espec_isco == 0x0) {    // a new computation is required
00285 
00286         r_isco() ;  // espec_isco is computed in the method r_isco()
00287 
00288         assert(p_espec_isco != 0x0) ;
00289     }
00290 
00291     return *p_espec_isco ;
00292 
00293 }
00294 
00295 
00296 //=============================================================================
00297 //              f_eq()
00298 //=============================================================================
00299 
00300 double Star_rot::f_eq() const {
00301   
00302   if (p_f_eq == 0x0) {    // a new computation is required
00303 
00304     r_isco() ;              // f_eq is computed in the method r_isco()
00305 
00306     assert(p_f_eq != 0x0) ;
00307   }
00308 
00309   return *p_f_eq ;
00310 
00311 }
00312 
00313 
00314 //=============================================================================
00315 //  Function used to locate the MS orbit
00316 //=============================================================================
00317 
00318 
00319 double funct_star_rot_isco(double xi, const Param& par){
00320 
00321     // Retrieval of the information:
00322     int l_ms = par.get_int() ;
00323     const Scalar& orbit = par.get_scalar() ;
00324     const Valeur& vorbit = orbit.get_spectral_va() ;
00325 
00326     // Value et the desired point
00327     double theta = M_PI / 2. ;
00328     double phi = 0 ;
00329     return vorbit.val_point(l_ms, xi, theta, phi) ;
00330 
00331 }
00332 
00333 
00334 
00335 
00336 
00337 

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