star_equil_spher.C

00001 /*
00002  * Method of class Star to compute a static spherical configuration.
00003  *
00004  * (see file star.h for documentation).
00005  *
00006  */
00007 
00008 /*
00009  *   Copyright (c) 2004 Francois Limousin
00010  *
00011  *   This file is part of LORENE.
00012  *
00013  *   LORENE is free software; you can redistribute it and/or modify
00014  *   it under the terms of the GNU General Public License as published by
00015  *   the Free Software Foundation; either version 2 of the License, or
00016  *   (at your option) any later version.
00017  *
00018  *   LORENE is distributed in the hope that it will be useful,
00019  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00020  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021  *   GNU General Public License for more details.
00022  *
00023  *   You should have received a copy of the GNU General Public License
00024  *   along with LORENE; if not, write to the Free Software
00025  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00026  *
00027  */
00028 
00029 
00030 char star_equil_spher_C[] = "$Header: /cvsroot/Lorene/C++/Source/Star/star_equil_spher.C,v 1.14 2010/10/18 20:16:10 m_bejger Exp $" ;
00031 
00032 /*
00033  * $Id: star_equil_spher.C,v 1.14 2010/10/18 20:16:10 m_bejger Exp $
00034  * $Log: star_equil_spher.C,v $
00035  * Revision 1.14  2010/10/18 20:16:10  m_bejger
00036  * Commented-out the reevaluation of the mapping for the case of many domains inside the star
00037  *
00038  * Revision 1.13  2010/10/18 18:56:33  m_bejger
00039  * Changed to allow initial data with more than one domain in the star
00040  *
00041  * Revision 1.12  2005/09/14 12:30:52  f_limousin
00042  * Saving of fields lnq and logn in class Star.
00043  *
00044  * Revision 1.11  2005/09/13 19:38:31  f_limousin
00045  * Reintroduction of the resolution of the equations in cartesian coordinates.
00046  *
00047  * Revision 1.10  2005/02/17 17:32:35  f_limousin
00048  * Change the name of some quantities to be consistent with other classes
00049  * (for instance nnn is changed to nn, shift to beta, beta to lnq...)
00050  *
00051  * Revision 1.9  2004/06/22 12:45:31  f_limousin
00052  * Improve the convergence
00053  *
00054  * Revision 1.8  2004/06/07 16:27:47  f_limousin
00055  * Add the computation of virial error.
00056  *
00057  * Revision 1.6  2004/04/08 16:33:42  f_limousin
00058  * The new variable is ln(Q) instead of Q=psi^2*N. It improves the
00059  * convergence of the code.
00060  *
00061  * Revision 1.5  2004/03/25 10:29:26  j_novak
00062  * All LORENE's units are now defined in the namespace Unites (in file unites.h).
00063  *
00064  * Revision 1.4  2004/02/27 09:57:55  f_limousin
00065  * We now update the metric gamma at the end of this routine for
00066  * the calculus of mass_b and mass_g.
00067  *
00068  * Revision 1.3  2004/02/21 17:05:13  e_gourgoulhon
00069  * Method Scalar::point renamed Scalar::val_grid_point.
00070  * Method Scalar::set_point renamed Scalar::set_grid_point.
00071  *
00072  * Revision 1.2  2004/01/20 15:20:35  f_limousin
00073  * First version
00074  *
00075  *
00076  * $Header: /cvsroot/Lorene/C++/Source/Star/star_equil_spher.C,v 1.14 2010/10/18 20:16:10 m_bejger Exp $
00077  *
00078  */
00079 
00080 // Headers C
00081 #include "math.h"
00082 
00083 // Headers Lorene
00084 #include "tenseur.h"
00085 #include "star.h"
00086 #include "param.h"
00087 #include "graphique.h"
00088 #include "nbr_spx.h"
00089 #include "unites.h"     
00090 
00091 void Star::equilibrium_spher(double ent_c, 
00092                              double precis, 
00093                              const Tbl* pent_limit){
00094     
00095     // Fundamental constants and units
00096     // -------------------------------
00097     using namespace Unites ;
00098     
00099     // Initializations
00100     // ---------------
00101     
00102     const Mg3d* mg = mp.get_mg() ; 
00103     int nz = mg->get_nzone() ;      // total number of domains
00104     
00105     // Index of the point at phi=0, theta=pi/2 at the surface of the star:
00106     int l_b = nzet - 1 ; 
00107     int i_b = mg->get_nr(l_b) - 1 ; 
00108     int j_b = mg->get_nt(l_b) - 1 ; 
00109     int k_b = 0 ; 
00110     
00111     // Value of the enthalpy defining the surface of the star
00112     double ent_b = 0 ; 
00113     
00114     // Initialization of the enthalpy field to the constant value ent_c :
00115     
00116     ent = ent_c ; 
00117     ent.annule(nzet, nz-1) ; 
00118     
00119     
00120     // Corresponding profiles of baryon density, energy density and pressure
00121     
00122     equation_of_state() ; 
00123 
00124     Scalar a_car(mp) ;
00125     a_car = 1 ;     
00126     lnq = 0 ;
00127     lnq.std_spectral_base() ;
00128 
00129     // Auxiliary quantities
00130     // --------------------
00131     
00132     // Affine mapping for solving the Poisson equations
00133     Map_af mpaff(mp);   
00134         
00135     Param par_nul   ;    // Param (null) for Map_af::poisson.
00136 
00137     Scalar ent_jm1(mp) ;    // Enthalpy at previous step
00138     ent_jm1 = 0 ; 
00139     
00140     Scalar source(mp) ; 
00141     Scalar logn_quad(mp) ; 
00142     Scalar logn_mat(mp) ;
00143     logn_mat = 0 ;
00144     logn = 0 ; 
00145     logn_quad = 0 ; 
00146 
00147     Scalar dlogn(mp) ; 
00148     Scalar dlnq(mp) ; 
00149     
00150     double diff_ent = 1 ;     
00151     int mermax = 200 ;      // Max number of iterations
00152     
00153     //=========================================================================
00154     //          Start of iteration
00155     //=========================================================================
00156 
00157     for(int mer=0 ; (diff_ent > precis) && (mer<mermax) ; mer++ ) {
00158 
00159       double alpha_r = 1 ; 
00160     
00161     cout << "-----------------------------------------------" << endl ;
00162     cout << "step: " << mer << endl ;
00163     cout << "alpha_r: " << alpha_r << endl ;
00164     cout << "diff_ent = " << diff_ent << endl ;    
00165 
00166     //-----------------------------------------------------
00167     // Resolution of Poisson equation for ln(N)
00168     //-----------------------------------------------------
00169 
00170     // Matter part of ln(N)
00171     // --------------------
00172     
00173     source = a_car * (ener + 3.*press) ;
00174         
00175     source.set_dzpuis(4) ; 
00176     
00177     Cmp source_logn_mat (source) ;
00178     Cmp logn_mat_cmp (logn_mat) ;
00179     logn_mat_cmp.set_etat_qcq() ;
00180     
00181     mpaff.poisson(source_logn_mat, par_nul, logn_mat_cmp) ; 
00182 
00183     logn_mat = logn_mat_cmp ;
00184 
00185     // NB: at this stage logn is in machine units, not in c^2
00186 
00187     // Quadratic part of ln(N)
00188     // -----------------------
00189 
00190     mpaff.dsdr(logn, dlogn) ;
00191     mpaff.dsdr(lnq, dlnq) ;
00192         
00193     source = - dlogn * dlnq ; 
00194 
00195     Cmp source_logn_quad (source) ;
00196     Cmp logn_quad_cmp (logn_quad) ;
00197     logn_quad_cmp.set_etat_qcq() ;
00198         
00199     mpaff.poisson(source_logn_quad, par_nul, logn_quad_cmp) ; 
00200 
00201     logn_quad = logn_quad_cmp ;
00202 
00203                 
00204     //-----------------------------------------------------
00205     // Computation of the new radial scale
00206     //-----------------------------------------------------
00207 
00208     // alpha_r (r = alpha_r r') is determined so that the enthalpy
00209     // takes the requested value ent_b at the stellar surface
00210     
00211     double nu_mat0_b  = logn_mat.val_grid_point(l_b, k_b, j_b, i_b) ; 
00212     double nu_mat0_c  = logn_mat.val_grid_point(0, 0, 0, 0) ; 
00213 
00214     double nu_quad0_b  = logn_quad.val_grid_point(l_b, k_b, j_b, i_b) ; 
00215     double nu_quad0_c  = logn_quad.val_grid_point(0, 0, 0, 0) ; 
00216 
00217     double alpha_r2 = ( ent_c - ent_b - nu_quad0_b + nu_quad0_c )
00218                 / ( qpig*(nu_mat0_b - nu_mat0_c) ) ;
00219 
00220     alpha_r = sqrt(alpha_r2) ;
00221     
00222     // One domain inside the star:
00223     // --------------------------- 
00224     if(nzet==1)  mpaff.homothetie( alpha_r ) ; 
00225 
00226     //--------------------
00227     // First integral
00228     //--------------------
00229 
00230     // Gravitation potential in units c^2 :
00231     logn_mat = alpha_r2*qpig * logn_mat ;
00232     logn = logn_mat + logn_quad ;
00233 
00234     // Enthalpy in all space
00235     double logn_c = logn.val_grid_point(0, 0, 0, 0) ;
00236     ent = ent_c - logn + logn_c ;
00237 
00238     // Two or more domains inside the star:
00239     // ------------------------------------ 
00240 
00241     if(nzet>1) { 
00242 
00243     // Parameters for the function Map_et::adapt
00244     // -----------------------------------------
00245     
00246     Param par_adapt ; 
00247     int nitermax = 100 ;  
00248     int niter ; 
00249     int adapt_flag = 1 ;    //  1 = performs the full computation, 
00250                 //  0 = performs only the rescaling by 
00251                 //      the factor alpha_r
00252     int nz_search = nzet + 1 ;  // Number of domains for searching the enthalpy
00253                 //  isosurfaces
00254 
00255     int nzadapt = nzet ; 
00256 
00257     //cout << "no. of domains where the ent adjustment will be done: " << nzet << endl ;
00258     //cout << "ent limits: " << ent_limit << endl ; 
00259 
00260     double precis_adapt = 1.e-14 ; 
00261  
00262     double reg_map = 1. ; // 1 = regular mapping, 0 = contracting mapping
00263 
00264     par_adapt.add_int(nitermax, 0) ;   // maximum number of iterations to
00265                        // locate zeros by the secant method
00266     par_adapt.add_int(nzadapt, 1) ;    // number of domains where the adjustment 
00267                        // to the isosurfaces of ent is to be 
00268                        // performed
00269     par_adapt.add_int(nz_search, 2) ;  // number of domains to search for
00270                        // the enthalpy isosurface
00271     par_adapt.add_int(adapt_flag, 3) ; // 1 = performs the full computation, 
00272                        // 0 = performs only the rescaling by 
00273                        // the factor alpha_r
00274     par_adapt.add_int(j_b, 4) ;        // theta index of the collocation point 
00275                            // (theta_*, phi_*)
00276     par_adapt.add_int(k_b, 5) ;        // theta index of the collocation point 
00277                            // (theta_*, phi_*)
00278 
00279     par_adapt.add_int_mod(niter, 0) ;  // number of iterations actually used in 
00280                        // the secant method
00281     
00282     par_adapt.add_double(precis_adapt, 0) ; // required absolute precision in 
00283                     // the determination of zeros by 
00284                     // the secant method
00285     par_adapt.add_double(reg_map, 1) ;  // 1. = regular mapping, 0 = contracting mapping
00286     
00287     par_adapt.add_double(alpha_r, 2) ;  // factor by which all the radial 
00288                     // distances will be multiplied 
00289            
00290     // Enthalpy values for the adaptation
00291     Tbl ent_limit(nzet) ; 
00292     if (pent_limit != 0x0) ent_limit = *pent_limit ; 
00293            
00294     par_adapt.add_tbl(ent_limit, 0) ;   // array of values of the field ent 
00295                         // to define the isosurfaces.              
00296 
00297       double* bornes = new double[nz+1] ;
00298       bornes[0] = 0. ; 
00299 
00300       for(int l=0; l<nz; l++) {
00301  
00302     bornes[l+1] = mpaff.get_alpha()[l]  + mpaff.get_beta()[l] ;     
00303 
00304       } 
00305       bornes[nz] = __infinity ; 
00306  
00307       Map_et mp0(*mg, bornes) ;
00308  
00309         mp0 = mpaff; 
00310         mp0.adapt(ent, par_adapt) ; 
00311 
00312         //Map_af mpaff_prev (mpaff) ; 
00313 
00314         double alphal, betal ; 
00315 
00316         for(int l=0; l<nz; l++) { 
00317 
00318             alphal = mp0.get_alpha()[l] ; 
00319             betal  = mp0.get_beta()[l] ;
00320  
00321             mpaff.set_alpha(alphal, l) ; 
00322             mpaff.set_beta(betal, l) ;
00323 
00324         } 
00325  
00326 
00327         // testing printout    
00328         //int num_r1 = mg->get_nr(0) - 1;        
00329         //cout << "Pressure difference:" << press.val_grid_point(0,0,0,num_r1) 
00330         //- press.val_grid_point(1,0,0,0) << endl ; 
00331         //cout << "Difference in enthalpies at the domain boundary:" << endl ;
00332         //cout << ent.val_grid_point(0,0,0,num_r1) << endl ; 
00333         //cout << ent.val_grid_point(1,0,0,0) << endl ;
00334 
00335         //cout << "Enthalpy difference: " << ent.val_grid_point(0,0,0,num_r1)
00336         //- ent.val_grid_point(1,0,0,0) << endl ;
00337 
00338         // Computation of the enthalpy at the new grid points
00339         //----------------------------------------------------                     
00340         //mpaff.reevaluate(&mpaff_prev, nzet+1, ent) ;
00341 
00342     } 
00343 
00344 
00345     //---------------------
00346     // Equation of state
00347     //---------------------
00348     
00349     equation_of_state() ; 
00350     
00351     //---------------------
00352     // Equation for lnq_auto
00353     //---------------------
00354     
00355     mpaff.dsdr(logn, dlogn) ;
00356     mpaff.dsdr(lnq, dlnq) ;
00357     
00358     source = 3 * qpig * a_car * press ;
00359     
00360     source = source - 0.5 * ( dlnq * dlnq + dlogn * dlogn ) ;
00361 
00362     source.std_spectral_base() ;
00363     Cmp source_lnq (source) ;
00364     Cmp lnq_cmp (logn_quad) ;
00365     lnq_cmp.set_etat_qcq() ;
00366 
00367     mpaff.poisson(source_lnq, par_nul, lnq_cmp) ; 
00368 
00369     lnq = lnq_cmp ;
00370 
00371     // Metric coefficient psi4 update
00372     
00373     nn = exp( logn ) ; 
00374 
00375     Scalar qq = exp( lnq ) ;
00376     qq.std_spectral_base() ;
00377 
00378     a_car = qq * qq / ( nn * nn ) ;
00379     a_car.std_spectral_base() ;
00380 
00381     // Relative difference with enthalpy at the previous step
00382     // ------------------------------------------------------
00383     
00384     diff_ent = norme( diffrel(ent, ent_jm1) ) / nzet ; 
00385 
00386     // Next step
00387     // ---------
00388     
00389     ent_jm1 = ent ; 
00390 
00391 
00392     }  // End of iteration loop 
00393     
00394     //=========================================================================
00395     //          End of iteration
00396     //=========================================================================
00397  
00398     // The mapping is transfered to that of the star:
00399     // ----------------------------------------------
00400     mp = mpaff ; 
00401 
00402     // Sets value to all the Tenseur's of the star
00403     // -------------------------------------------
00404     
00405     nn = exp( logn ) ; 
00406    
00407     Scalar qq = exp( lnq ) ;
00408     qq.std_spectral_base() ;
00409     
00410     a_car = qq * qq / ( nn * nn ) ;
00411    
00412     Sym_tensor gamma_cov(mp, COV, mp.get_bvect_cart()) ;
00413     gamma_cov.set_etat_zero() ;
00414 
00415     for (int i=1; i<=3; i++){
00416     gamma_cov.set(i,i) = a_car ;
00417     }
00418     gamma = gamma_cov ;
00419 
00420     // ... hydro 
00421     ent.annule(nzet, nz-1) ;    // enthalpy set to zero at the exterior of 
00422                 // the star
00423     ener_euler = ener ; 
00424     s_euler = 3 * press ;
00425     gam_euler = 1 ;  
00426     for(int i=1; i<=3; i++) u_euler.set(i) = 0 ; 
00427     
00428     // Info printing
00429     // -------------
00430     
00431     cout << endl 
00432      << "Characteristics of the star obtained by Etoile::equilibrium_spher : " 
00433      << endl 
00434      << "-----------------------------------------------------------------" 
00435      << endl ; 
00436 
00437     double ray = mp.val_r(l_b, 1., M_PI/2., 0) ; 
00438     cout << "Coordinate radius  :       " << ray / km << " km" << endl ; 
00439 
00440     double rcirc = ray * sqrt(a_car.val_grid_point(l_b, k_b, j_b, i_b) ) ; 
00441     
00442     double compact = qpig/(4.*M_PI) * mass_g() / rcirc ; 
00443 
00444     cout << "Circumferential radius R : " << rcirc/km  << " km" << endl ;
00445     cout << "Baryon mass :       " << mass_b()/msol << " Mo" << endl ;
00446     cout << "Gravitational mass M :  " << mass_g()/msol << " Mo" << endl ;
00447     cout << "Compacity parameter GM/(c^2 R) : " << compact << endl ;
00448      
00449     //-----------------
00450     // Virial theorem
00451     //-----------------
00452     
00453     //... Pressure term
00454 
00455     source = qpig * a_car * sqrt(a_car) * s_euler ; 
00456     source.std_spectral_base() ;        
00457     double vir_mat = source.integrale() ; 
00458     
00459     //... Gravitational term
00460 
00461     Scalar tmp = lnq - logn ; 
00462 
00463     source =  - ( logn.dsdr() * logn.dsdr() 
00464               - 0.5 * tmp.dsdr() * tmp.dsdr() ) 
00465             * sqrt(a_car)  ; 
00466 
00467     source.std_spectral_base() ;        
00468     double vir_grav = source.integrale() ; 
00469 
00470     //... Relative error on the virial identity GRV3
00471     
00472     double grv3 = ( vir_mat + vir_grav ) / vir_mat ;
00473 
00474     cout << "Virial theorem GRV3 : " << endl ; 
00475     cout << "     3P term    : " << vir_mat << endl ; 
00476     cout << "     grav. term : " << vir_grav << endl ; 
00477     cout << "     relative error : " << grv3 << endl ; 
00478     
00479     // To be compatible with class Etoile :
00480     //logn = logn - logn_quad ;
00481 
00482  
00483 }

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