Equation of State Sub-Library: Version 0.910
tov_solve.h
00001 /*
00002   -------------------------------------------------------------------
00003   
00004   Copyright (C) 2006-2012, Andrew W. Steiner
00005   
00006   This file is part of O2scl.
00007   
00008   O2scl 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 3 of the License, or
00011   (at your option) any later version.
00012   
00013   O2scl 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 O2scl. If not, see <http://www.gnu.org/licenses/>.
00020 
00021   -------------------------------------------------------------------
00022 */
00023 #ifndef O2SCL_TOV_SOLVE_H
00024 #define O2SCL_TOV_SOLVE_H
00025 
00026 #include <o2scl/tov_eos.h>
00027 #include <o2scl/smart_interp.h>
00028 #include <o2scl/table_units.h>
00029 #include <o2scl/shared_ptr.h>
00030 
00031 #ifndef DOXYGENP
00032 namespace o2scl {
00033 #endif
00034 
00035   /** \brief Class to solve the Tolman-Oppenheimer-Volkov equations
00036 
00037       \hline
00038       <b>Mathematical background:</b>
00039 
00040       In units where \f$ c=1 \f$, the TOV equations (i.e. Einstein's
00041       equations for a static spherically symmetric object) are
00042       \f[
00043       \frac{d m}{d r} = 4 \pi r^2 \varepsilon
00044       \f]
00045       \f[
00046       \frac{d P}{d r} = - \frac{G \varepsilon m}{r^2}
00047       \left( 1+\frac{P}{\varepsilon}\right)
00048       \left( 1+\frac{4 \pi P r^3}{m} \right)
00049       \left( 1-\frac{2 G m}{r}\right)^{-1}
00050       \f]
00051       where \f$r\f$ is the radial coordinate, \f$m(r)\f$ is the
00052       gravitational mass enclosed within a radius \f$r\f$, and
00053       \f$\varepsilon(r)\f$ and \f$P(r)\f$ are the energy density and
00054       pressure at \f$r\f$, and \f$G\f$ is the gravitational constant.
00055       The boundary conditions are \f$m(r=0)=0\f$ the condition
00056       \f$P(r=R)=0\f$ for some fixed radius \f$R\f$. These boundary
00057       conditions give a series of solutions to the TOV equations as a
00058       function of the radius, although they do not necessarily have a
00059       solution for all radii.
00060 
00061       The gravitational mass is given by
00062       \f[
00063       M_G = \int_0^R 4 \pi r^2 \varepsilon d r
00064       \f]
00065 
00066       The gravitational potential, \f$\Phi(r)\f$ can be determined from
00067       \f[
00068       \frac{d \Phi}{d r} = - \frac{1}{\varepsilon}
00069       \frac{ d P}{d r} \left(1+\frac{P}{\varepsilon}\right)^{-1}
00070       \f]
00071 
00072       The proper boundary condition for the gravitational potential
00073       is 
00074       \f[
00075       \Phi(r=R) = \frac{1}{2} \ln \left(1-\frac{2 G M}{R} \right)
00076       \f]
00077       which ensures that \f$ \phi(r) \rightarrow 0 \f$ as 
00078       \f$ r \rightarrow \infty \f$ .
00079 
00080       The surface gravity is
00081       \f[
00082       g = \frac{G m}{r^2}\left(1-\frac{2 G m}{r}\right)^{-1/2}
00083       \f]
00084       which is given in inverse kilometers and the redshift is
00085       \f[
00086       z = \left(1-\frac{2 G m}{r}\right)^{-1/2} - 1
00087       \f]
00088       which is unitless.
00089 
00090       The baryonic mass is typically defined by
00091       \f[
00092       M_B = \int_0^R 4 \pi r^2 n_B m_B 
00093       \left(1-\frac{2 G m}{r}\right)^{-1/2} d r
00094       \f]
00095       where \f$ n_B(r) \f$ is the baryon number density at radius 
00096       \f$ r \f$ and \f$ m_B \f$ is the mass of one baryon. Then the
00097       "binding energy" of the neutron star is defined to be \f$ M_B -
00098       M_G \f$ . If you can specify the product \f$ n_B m_B \f$ in the
00099       EOS (analogous to the rest mass energy density), it will compute
00100       the associated baryonic mass for you.
00101 
00102       In the case of slow rigid rotation with angular velocity
00103       \f$ \Omega \f$, the moment of inertia is
00104       \f[
00105       I = \frac{8 \pi}{3} \int_0^R dr~r^4\left(\varepsilon+P\right)
00106       e^{\Phi} \left(\frac{\bar{\omega}}{\Omega}\right)
00107       \left(1-\frac{2 G m}{r}\right)^{-1/2}
00108       \f]
00109       where the function \f$ \bar{\omega}(r) \f$ is the solution of 
00110       \f[
00111       \frac{d}{dr} \left( r^4 j \frac{d \bar{\omega}}{dr}\right)
00112       + 4 r^3 \frac{d j}{dr} \bar{\omega} = 0
00113       \f]
00114       and the function \f$ j(r) \f$ is defined by 
00115       \f[
00116       j = \left( 1-\frac{2 G m}{r} \right) e^{-\Phi}
00117       \f]
00118       The boundary conditions for \f$ \bar{\omega} \f$ are
00119       \f$ d \bar{\omega}/dr = 0 \f$ at \f$ r=0 \f$ and 
00120       \f[
00121       \bar{\omega}(R) = \Omega - \left(\frac{R}{3}\right)
00122       \left(\frac{d \bar{\omega}}{dr}\right)_{r=R} \, .
00123       \f]
00124 
00125       \hline
00126       <b>General usage notes:</b>
00127 
00128       The equation of state may be changed at any time, by specifying
00129       the appropriate tov_eos object 
00130       
00131       Screen output:
00132       - \c verbose=0 - Nothing
00133       - \c verbose=1 - Basic information
00134       - \c verbose=2 - For each profile computation, report solution
00135       information at every kilometer.
00136       - \c verbose=3 - Report profile information at every 20 grid points. A 
00137       keypress is required after each profile.
00138 
00139       \hline
00140       <b>Output tables:</b>
00141 
00142       The functions fixed() and max() produce output tables which
00143       represent the profile of the neutron star of the requested mass.
00144       The columns are
00145       - \c gm, the enclosed gravitational mass in solar masses
00146       - \c r, the radial coordinate in \f$ \mathrm{km} \f$
00147       - \c gp, the gravitational potential (unitless) when
00148       \ref calcgpot is true
00149       - \c bm, the baryonic mass in solar masses (when 
00150       \ref tov_eos::baryon_column is true). 
00151       - \c pr, the pressure
00152       - \c ed, the energy density
00153       - \c nb, the baryon density (if \ref tov_eos::baryon_column
00154       is true)
00155       - \c sg, the local surface gravity 
00156       (in \f$ \mathrm{g}/\mathrm{cm}^{2} \f$ )
00157       - \c rs, the local redshift (unitless),
00158       - \c dmdr, the derivative of the enclosed gravitational mass
00159       in \f$ \mathrm{M}_{\odot}/\mathrm{km} \f$
00160       - \c dlogpdr, the derivative of the natural logarithm of the 
00161       pressure
00162       - \c dgpdr, the derivative of the gravitational potential
00163       in \f$ 1/\mathrm{km} \f$ (if \ref calcgpot is true)
00164       - \c dbmdr, the derivative of the enclosed baryonic mass
00165       (if \ref tov_eos::baryon_column is true). \n
00166       The remaining columns are given by the user-defined columns from
00167       the equation of state as determined by \ref tov_eos::get_names_units()
00168       and \ref tov_eos::get_aux().
00169 
00170       The function mvsr() produces a different kind of output table
00171       corresponding to the mass versus radius curve. Some points on
00172       the curve may correspond to unstable branches.
00173       - \c gm, the total gravitational mass in solar masses
00174       - \c r, the radius in \f$ \mathrm{km} \f$
00175       - \c gp, the gravitational potential at the surface (unitless) when
00176       \ref calcgpot is true
00177       - \c bm, total the baryonic mass in solar masses (when 
00178       \ref tov_eos::baryon_column is true). 
00179       - \c pr, the central pressure
00180       - \c ed, the central energy density
00181       - \c nb, the central baryon density (if \ref tov_eos::baryon_column
00182       is true)
00183       - \c sg, the surface gravity 
00184       (in \f$ \mathrm{g}/\mathrm{cm}^{2} \f$ )
00185       - \c rs, the redshift at the surface,
00186       - \c dmdr, the derivative of the gravitational mass
00187       - \c dlogpdr, the derivative of the natural logarithm of the 
00188       pressure
00189       - \c dgpdr, the derivative of the gravitational potential
00190       in \f$ 1/\mathrm{km} \f$ (if \ref calcgpot is true)
00191       - \c dbmdr, the derivative of the enclosed baryonic mass
00192       (if \ref tov_eos::baryon_column is true). \n
00193       The remaining columns are given by the user-defined columns from
00194       the equation of state as determined by \ref tov_eos::get_names_units()
00195       and \ref tov_eos::get_aux().
00196       
00197       \hline
00198       <b>Accuracy:</b>
00199 
00200       The present code, as demonstrated in the tests, gives the
00201       correct central pressure and energy density of the analytical
00202       solution by Buchdahl to within less than 1 \part in \f$ 10^8 \f$.
00203 
00204       \hline
00205       <b>Other details and todos:</b>
00206 
00207       \note The function star_fun() returns <tt>gsl_efailed</tt>
00208       without calling the error handler in the case that the solver
00209       can recover gracefully from, for example, a negative pressure.
00210       
00211       \todo
00212       - baryon mass doesn't work for fixed() (This may be fixed. We should
00213       make sure it's tested.)
00214       - Combine maxoutsize and kmax?
00215       - Document column naming issues
00216       - Document surface gravity and redshift
00217       - Standardize \c xmev_kg, etc. 
00218       - Use convert_units? 
00219       - Double check that fixed() doesn't give a solution on the
00220       unstable branch
00221       - Ensure that this class copies over the units of the 
00222       user-specified columns to the table
00223 
00224       \comment
00225       To solve the calling of the error handler, I need to rewrite the
00226       adaptive stepper to simply stop if the base stepper makes a step
00227       which is too large. That demands creating a new version of
00228       gsl_astep::evolve_apply(). The question is how to communicate
00229       the information from the tov derivs() function to the new
00230       version of gsl_astep::evolve_apply(). An easy way would be to
00231       just create a new return value which indicates the step should
00232       be shortened, and just stop if the step becomes too short.
00233       Alternatively, instead of modifying evolve_apply(), we could
00234       just ensure the adaptive stepper bails out correctly if the
00235       stepper returns a nonzero value and then have the caller
00236       (starfun) take care of it. This would probably be better. We
00237       might have to make sure that gsl_astep does not set yout if the
00238       step fails. (3/27/09 - It looks like this might be fixed now?)
00239       \endcomment
00240 
00241       \hline
00242   */
00243   class tov_solve {
00244 
00245 #ifndef DOXYGEN_INTERNAL
00246 
00247   protected:
00248 
00249     /// To convert MeV to kilograms
00250     double mev_kg;
00251 
00252     /// To convert \f$ MeV/fm{^3} \f$ to solar masses per cubic kilometer
00253     double mev_per_fm3_msun_km3;
00254     
00255     /** \brief Target mass
00256         
00257         Negative values to indicate a mass measured relative to the
00258         maximum mass. For example, if the EOS has a maximum mass of 2.0, then
00259         -0.15 will give the profile of a 1.85 solar mass star.
00260     */
00261     double tmass;
00262 
00263     /** \brief Ensure \c col does not match strings in \c cnames
00264         
00265         Underscores are added to \c col until it matches none of
00266         the strings in \c cnames.
00267     */
00268     int make_unique_name(std::string &col, 
00269                          std::vector<std::string> &cnames);
00270     
00271     /// The EOS
00272     tov_eos *te;
00273 
00274     /// True if the EOS has been set
00275     bool eos_set;
00276 
00277     /// \name User EOS units
00278     //@{
00279     /// Units for energy density
00280     std::string eunits;
00281     /// Units for pressure
00282     std::string punits;
00283     /// Units for baryon density
00284     std::string nunits;
00285     /// unit conversion factor for energy density (default 1.0)
00286     double efactor;
00287     /// unit conversion factor for pressure (default 1.0)
00288     double pfactor;
00289     /// unit conversion factor for baryon density (default 1.0)
00290     double nfactor;
00291     //@}
00292     
00293     /// maximum storage size (default 40000)
00294     int kmax;
00295     /// maximum size of output file (default 400)
00296     int maxoutsize;
00297 
00298     /** \brief Smallest allowed pressure for integration (default: -100)
00299    
00300         This quantity can't be much smaller than -100 since we need to
00301         compute numbers near \f$ e^{-presmin} \f$
00302     */
00303     double presmin;
00304 
00305     /// \name Integration storage
00306     //@{
00307     /** \brief ODE functions
00308 
00309         The vector \c rky[0] is the gravitational mass in solar
00310         masses, and the vector \c rky[1] is the natural logarithm of
00311         the pressure in solar masses per cubic kilometer. When \ref
00312         calcgpot is true, the next vector in this list is the
00313         gravitational potential (which is unitless), and when \ref
00314         tov_eos::baryon_column is true, the next vector in this 
00315         list is the baryonic mass in solar masses.
00316     */
00317     ovector rky[6];
00318     /// Radial coordinate (in kilometers)
00319     ovector rkx;
00320     /// The derivatives of the ODE functions
00321     ovector rkdydx[6];
00322     //@}
00323     
00324     /// Compute the angular velocity
00325     int ang_vel();
00326 
00327     /// Interpolation object for derivs_ang_vel()
00328     sm_interp smi;
00329 
00330     /// The output table
00331     o2_shared_ptr<table_units>::type out_table;
00332 
00333     /// The solver
00334     mroot<mm_funct<> > *mroot_ptr;
00335 
00336     /// The minimizer
00337     minimize<funct> *min_ptr;
00338     
00339     /// The adaptive stepper
00340     adapt_step<ode_funct<> > *as_ptr;
00341 
00342     /// The ODE step function
00343     virtual int derivs(double x, size_t nv, const ovector_base &y,
00344                        ovector_base &dydx);
00345     
00346     /// The ODE step function for the angular velocity
00347     virtual int derivs_ang_vel(double x, size_t nv, const ovector_base &y,
00348                                ovector_base &dydx);
00349     
00350     /** \brief Construct a stellar profile
00351 
00352         This function constructs a stellar profile in \ref out_table
00353         from the information in \ref rkx and \ref rky.
00354      */
00355     virtual int profile_out(double xx);
00356     
00357     /// The minimizer function to compute the maximum mass
00358     virtual double maxfun(double maxx);
00359 
00360     /** \brief The solver function to compute the stellar profile
00361      */
00362     virtual int starfun(size_t ndvar, const ovector_base &ndx, 
00363                         ovector_base &ndy);
00364     
00365     /// The schwarzchild radius in km
00366     double schwarz_km;
00367     
00368 #endif
00369 
00370   public:
00371 
00372     tov_solve();
00373 
00374     virtual ~tov_solve();
00375     
00376     /// \name Basic properties
00377     //@{
00378     /// mass
00379     double mass;
00380     /// radius
00381     double rad;
00382     /// baryonic mass
00383     double bmass;
00384     /// gravitational potential
00385     double gpot;
00386     //@}
00387 
00388     /** \name Solution parameters
00389         
00390         These parameters can be changed at any time.
00391     */
00392     //@{
00393     /// Use general relativistic version (default true)
00394     bool generel;
00395     /** \brief calculate the gravitational potential and the enclosed 
00396         baryon mass (default false)
00397     */
00398     bool calcgpot;
00399     /// smallest allowed radial stepsize (default 1.0e-4)
00400     double hmin;
00401     /// largest allowed radial stepsize (default 0.05)
00402     double hmax;
00403     /// initial radial stepsize (default 4.0e-3)
00404     double hstart;
00405     /// control for output (default 1)
00406     int verbose;
00407     /// maximum radius for integration in km (default 60)
00408     double maxradius;
00409     //@}
00410 
00411     /// \name Mass versus radius parameters
00412 
00413     //@{
00414     /// Beginning pressure (default 7.0e-7)
00415     double prbegin;
00416     /// Ending pressure (default 8.0e-3)
00417     double prend;
00418     /// Increment for pressure (default 1.1)
00419     double princ;
00420     /// Use 'princ' as a multiplier, not an additive increment (default true)
00421     bool logmode;
00422     /** \brief Guess for central pressure in solar masses per km3 
00423         (default \f$ 5.2 \times 10^{-5} \f$)
00424 
00425         This guess is used in the function fixed().
00426     */
00427     double prguess;
00428     /// Beginning pressure for maximum mass guess (default 7.0e-5)
00429     double max_begin;
00430     /// Ending pressure for maximum mass guess (default 5.0e-3)
00431     double max_end;
00432     /// Increment for pressure for maximum mass guess (default 1.3)
00433     double max_inc;
00434     //@}
00435 
00436     /// \name Basic operation
00437     //@{
00438     /// Set the EOS to use
00439     int set_eos(tov_eos &ter) {
00440       te=&ter;
00441       eos_set=true;
00442       return 0;
00443     }
00444 
00445     /// Set units
00446     int set_units(double s_efactor=1.0, double s_pfactor=1.0, 
00447                   double s_nbfactor=1.0);
00448 
00449     /** \brief Set units
00450         
00451         Valid entries for the units of energy density and pressure are:
00452         - "g/cm^3"
00453         - "erg/cm^3"
00454         - "MeV/fm^3"
00455         - "1/fm^4"
00456         - "Msun/km^3" (i.e. solar masses per cubic kilometer)
00457         
00458         Valid entries for the units of baryon density are:
00459         - "1/m^3"
00460         - "1/cm^3"
00461         - "1/fm^3"
00462     */
00463     int set_units(std::string eunits="", std::string punits="", 
00464                   std::string nunits="");
00465 
00466     /// Calculate the mass vs. radius curve
00467     virtual int mvsr();
00468 
00469     /// Calculate the profile of a star with fixed mass
00470     virtual int fixed(double d_tmass);
00471 
00472     /// Calculate the profile of the maximum mass star
00473     virtual int max();
00474 
00475     /** \brief Return the results data table
00476      */
00477     o2_shared_ptr<table_units>::type get_results() {
00478       return out_table;
00479     }
00480 
00481     /** \brief Check the solution (unfinished)
00482      */
00483     int solution_check();
00484     //@}
00485     
00486     /// \name Control numerical methods
00487     //@{
00488     /** \brief Set maximum storage for integration
00489         
00490         The variable \c s_kmax is the maximum number of radial
00491         integration stepsk while \c s_maxoutsize is the maximum number
00492         of points that will be output for any profile.
00493         
00494         If \c s_kmax is less than zero, there is no limit on
00495         the number of radial steps.
00496     */
00497     int set_kmax(int s_maxoutsize=400, int s_kmax=80000);
00498 
00499     /** \brief Set solver
00500     */
00501     int set_mroot(mroot<mm_funct<> > &s_mrp) 
00502     {mroot_ptr=&s_mrp; return 0;};
00503     
00504     /** \brief Set minimizer
00505     */
00506     int set_minimize(minimize<funct > &s_mp) 
00507     {min_ptr=&s_mp; return 0;};
00508 
00509     /** \brief Set the adaptive stepper
00510     */
00511     int set_stepper(adapt_step<ode_funct<> > &sap)
00512     {as_ptr=&sap; return 0;};
00513     //@}
00514 
00515     /// The default minimizer
00516     gsl_min_brent<funct > def_min;
00517     
00518     /// The default solver
00519     gsl_mroot_hybrids<mm_funct<> > def_solver;
00520 
00521     /// The default adaptive stepper
00522     gsl_astep<ode_funct<> > def_stepper;
00523 
00524     /// If true, compute the angular velocity (default false)
00525     bool compute_ang_vel;
00526     
00527     /// The angular velocity
00528     double cap_omega;
00529 
00530   };
00531 
00532 #ifndef DOXYGENP
00533 }
00534 #endif
00535 
00536 #endif
00537 
00538 
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Friends

Documentation generated with Doxygen. Provided under the GNU Free Documentation License (see License Information).

Get Object-oriented Scientific Computing
Lib at SourceForge.net. Fast, secure and Free Open Source software
downloads.