et_rot_diff_equil.C

00001 /*
00002  * Function Et_rot_diff::equilibrium
00003  *
00004  * (see file etoile.h for documentation)
00005  *
00006  */
00007 
00008 /*
00009  *   Copyright (c) 2001-2003 Eric Gourgoulhon
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 et_rot_diff_equil_C[] = "$Header: /cvsroot/Lorene/C++/Source/Etoile/et_rot_diff_equil.C,v 1.7 2005/10/05 15:15:30 j_novak Exp $" ;
00031 
00032 /*
00033  * $Id: et_rot_diff_equil.C,v 1.7 2005/10/05 15:15:30 j_novak Exp $
00034  * $Log: et_rot_diff_equil.C,v $
00035  * Revision 1.7  2005/10/05 15:15:30  j_novak
00036  * Added a Param* as parameter of Etoile_rot::equilibrium
00037  *
00038  * Revision 1.6  2004/03/25 10:29:05  j_novak
00039  * All LORENE's units are now defined in the namespace Unites (in file unites.h).
00040  *
00041  * Revision 1.5  2003/11/19 22:01:57  e_gourgoulhon
00042  * -- Relaxation on logn and dzeta performed only if mer >= 10.
00043  * -- err_grv2 is now evaluated also in the Newtonian case.
00044  *
00045  * Revision 1.4  2003/10/27 10:54:43  e_gourgoulhon
00046  * Changed local variable name lambda_grv2 to lbda_grv2 in order not
00047  * to shadow method name.
00048  *
00049  * Revision 1.3  2003/05/25 19:59:02  e_gourgoulhon
00050  * Added the possibility to choose the factor a = R_eq / R0, instead of R0
00051  * in the differential rotation law.
00052  *
00053  * Revision 1.2  2002/10/16 14:36:36  j_novak
00054  * Reorganization of #include instructions of standard C++, in order to
00055  * use experimental version 3 of gcc.
00056  *
00057  * Revision 1.1.1.1  2001/11/20 15:19:28  e_gourgoulhon
00058  * LORENE
00059  *
00060  * Revision 1.1  2001/10/19  08:18:16  eric
00061  * Initial revision
00062  *
00063  *
00064  * $Header: /cvsroot/Lorene/C++/Source/Etoile/et_rot_diff_equil.C,v 1.7 2005/10/05 15:15:30 j_novak Exp $
00065  *
00066  */
00067 
00068 
00069 
00070 // Headers C
00071 #include <math.h>
00072 
00073 // Headers Lorene
00074 #include "et_rot_diff.h"
00075 #include "param.h"
00076 
00077 #include "graphique.h"
00078 #include "utilitaires.h"
00079 #include "unites.h"     
00080 
00081 void Et_rot_diff::equilibrium(double ent_c, double omega_c0, double fact_omega, 
00082                  int nzadapt, const Tbl& ent_limit, 
00083                  const Itbl& icontrol,
00084                  const Tbl& control, double mbar_wanted, 
00085                  double aexp_mass, Tbl& diff, Param*) {
00086                  
00087     // Fundamental constants and units
00088     // -------------------------------
00089   using namespace Unites ;
00090     
00091     // For the display 
00092     // ---------------
00093     char display_bold[]="x[1m" ; display_bold[0] = 27 ;
00094     char display_normal[] = "x[0m" ; display_normal[0] = 27 ;
00095 
00096     // Grid parameters
00097     // ---------------
00098     
00099     const Mg3d* mg = mp.get_mg() ; 
00100     int nz = mg->get_nzone() ;      // total number of domains
00101     int nzm1 = nz - 1 ; 
00102     
00103     // The following is required to initialize mp_prev as a Map_et:
00104     Map_et& mp_et = dynamic_cast<Map_et&>(mp) ; 
00105         
00106     // Index of the point at phi=0, theta=pi/2 at the surface of the star:
00107     assert(mg->get_type_t() == SYM) ; 
00108     int l_b = nzet - 1 ; 
00109     int i_b = mg->get_nr(l_b) - 1 ; 
00110     int j_b = mg->get_nt(l_b) - 1 ; 
00111     int k_b = 0 ; 
00112     
00113     // Value of the enthalpy defining the surface of the star
00114     double ent_b = ent_limit(nzet-1) ;
00115     
00116     // Parameters to control the iteration
00117     // -----------------------------------
00118     
00119     int mer_max = icontrol(0) ; 
00120     int mer_rot = icontrol(1) ;
00121     int mer_change_omega = icontrol(2) ; 
00122     int mer_fix_omega = icontrol(3) ; 
00123     int mer_mass = icontrol(4) ; 
00124     int mermax_poisson = icontrol(5) ; 
00125     int mer_triax = icontrol(6) ; 
00126     int delta_mer_kep = icontrol(7) ; 
00127 
00128     // Protections:
00129     if (mer_change_omega < mer_rot) {
00130     cout << "Et_rot_diff::equilibrium: mer_change_omega < mer_rot !" << endl ;
00131     cout << " mer_change_omega = " << mer_change_omega << endl ; 
00132     cout << " mer_rot = " << mer_rot << endl ; 
00133     abort() ; 
00134     }
00135     if (mer_fix_omega < mer_change_omega) {
00136     cout << "Et_rot_diff::equilibrium: mer_fix_omega < mer_change_omega !" 
00137          << endl ;
00138     cout << " mer_fix_omega = " << mer_fix_omega << endl ; 
00139     cout << " mer_change_omega = " << mer_change_omega << endl ; 
00140     abort() ; 
00141     }
00142 
00143     // In order to converge to a given baryon mass, shall the central
00144     // enthalpy be varied or Omega ?
00145     bool change_ent = true ; 
00146     if (mer_mass < 0) {
00147     change_ent = false ; 
00148     mer_mass = abs(mer_mass) ;
00149     }
00150 
00151     double precis = control(0) ; 
00152     double omega_ini = control(1) ; 
00153     double relax = control(2) ;
00154     double relax_prev = double(1) - relax ;  
00155     double relax_poisson = control(3) ; 
00156     double thres_adapt = control(4) ; 
00157     double ampli_triax = control(5) ; 
00158     double precis_adapt = control(6) ; 
00159 
00160 
00161     // Error indicators
00162     // ----------------
00163     
00164     diff.set_etat_qcq() ; 
00165     double& diff_ent = diff.set(0) ; 
00166     double& diff_nuf = diff.set(1) ; 
00167     double& diff_nuq = diff.set(2) ; 
00168 //    double& diff_dzeta = diff.set(3) ; 
00169 //    double& diff_ggg = diff.set(4) ; 
00170     double& diff_shift_x = diff.set(5) ; 
00171     double& diff_shift_y = diff.set(6) ; 
00172     double& vit_triax = diff.set(7) ; 
00173     
00174     // Parameters for the function Map_et::adapt
00175     // -----------------------------------------
00176     
00177     Param par_adapt ; 
00178     int nitermax = 100 ;  
00179     int niter ; 
00180     int adapt_flag = 1 ;    //  1 = performs the full computation, 
00181                 //  0 = performs only the rescaling by 
00182                 //      the factor alpha_r
00183     int nz_search = nzet + 1 ;  // Number of domains for searching the enthalpy
00184                 //  isosurfaces
00185     double alpha_r ; 
00186     double reg_map = 1. ; // 1 = regular mapping, 0 = contracting mapping
00187 
00188     par_adapt.add_int(nitermax, 0) ; // maximum number of iterations to
00189                      // locate zeros by the secant method
00190     par_adapt.add_int(nzadapt, 1) ; // number of domains where the adjustment 
00191                     // to the isosurfaces of ent is to be 
00192                     // performed
00193     par_adapt.add_int(nz_search, 2) ;   // number of domains to search for
00194                     // the enthalpy isosurface
00195     par_adapt.add_int(adapt_flag, 3) ; //  1 = performs the full computation, 
00196                        //  0 = performs only the rescaling by 
00197                        //      the factor alpha_r
00198     par_adapt.add_int(j_b, 4) ; //  theta index of the collocation point 
00199                     //  (theta_*, phi_*)
00200     par_adapt.add_int(k_b, 5) ; //  theta index of the collocation point 
00201                     //  (theta_*, phi_*)
00202 
00203     par_adapt.add_int_mod(niter, 0) ;  //  number of iterations actually used in 
00204                        //  the secant method
00205     
00206     par_adapt.add_double(precis_adapt, 0) ; // required absolute precision in 
00207                          // the determination of zeros by 
00208                          // the secant method
00209     par_adapt.add_double(reg_map, 1)    ;  // 1. = regular mapping, 0 = contracting mapping
00210     
00211     par_adapt.add_double(alpha_r, 2) ;  // factor by which all the radial 
00212                        // distances will be multiplied 
00213            
00214     par_adapt.add_tbl(ent_limit, 0) ;   // array of values of the field ent 
00215                         // to define the isosurfaces.              
00216 
00217     // Parameters for the function Map_et::poisson for nuf
00218     // ----------------------------------------------------
00219 
00220     double precis_poisson = 1.e-16 ;     
00221 
00222     Param par_poisson_nuf ; 
00223     par_poisson_nuf.add_int(mermax_poisson,  0) ;  // maximum number of iterations
00224     par_poisson_nuf.add_double(relax_poisson,  0) ; // relaxation parameter
00225     par_poisson_nuf.add_double(precis_poisson, 1) ; // required precision
00226     par_poisson_nuf.add_int_mod(niter, 0) ;  //  number of iterations actually used 
00227     par_poisson_nuf.add_cmp_mod( ssjm1_nuf ) ; 
00228                        
00229     Param par_poisson_nuq ; 
00230     par_poisson_nuq.add_int(mermax_poisson,  0) ;  // maximum number of iterations
00231     par_poisson_nuq.add_double(relax_poisson,  0) ; // relaxation parameter
00232     par_poisson_nuq.add_double(precis_poisson, 1) ; // required precision
00233     par_poisson_nuq.add_int_mod(niter, 0) ;  //  number of iterations actually used 
00234     par_poisson_nuq.add_cmp_mod( ssjm1_nuq ) ; 
00235                        
00236     Param par_poisson_tggg ; 
00237     par_poisson_tggg.add_int(mermax_poisson,  0) ;  // maximum number of iterations
00238     par_poisson_tggg.add_double(relax_poisson,  0) ; // relaxation parameter
00239     par_poisson_tggg.add_double(precis_poisson, 1) ; // required precision
00240     par_poisson_tggg.add_int_mod(niter, 0) ;  //  number of iterations actually used 
00241     par_poisson_tggg.add_cmp_mod( ssjm1_tggg ) ; 
00242     double lambda_tggg ;
00243     par_poisson_tggg.add_double_mod( lambda_tggg ) ; 
00244     
00245     Param par_poisson_dzeta ; 
00246     double lbda_grv2 ;
00247     par_poisson_dzeta.add_double_mod( lbda_grv2 ) ; 
00248                        
00249     // Parameters for the function Tenseur::poisson_vect
00250     // -------------------------------------------------
00251 
00252     Param par_poisson_vect ; 
00253 
00254     par_poisson_vect.add_int(mermax_poisson,  0) ;  // maximum number of iterations
00255     par_poisson_vect.add_double(relax_poisson,  0) ; // relaxation parameter
00256     par_poisson_vect.add_double(precis_poisson, 1) ; // required precision
00257     par_poisson_vect.add_cmp_mod( ssjm1_khi ) ; 
00258     par_poisson_vect.add_tenseur_mod( ssjm1_wshift ) ; 
00259     par_poisson_vect.add_int_mod(niter, 0) ;   
00260 
00261                        
00262     // Initializations
00263     // ---------------
00264 
00265     // Initial central angular velocity
00266     double omega_c = 0 ; 
00267   
00268     double accrois_omega = (omega_c0 - omega_ini) / 
00269                 double(mer_fix_omega - mer_change_omega) ; 
00270 
00271 
00272     update_metric() ;   // update of the metric coefficients
00273 
00274     equation_of_state() ;   // update of the density, pressure, etc...
00275     
00276     hydro_euler() ; // update of the hydro quantities relative to the 
00277             //  Eulerian observer
00278 
00279     // Quantities at the previous step :    
00280     Map_et mp_prev = mp_et ; 
00281     Tenseur ent_prev = ent ;        
00282     Tenseur logn_prev = logn ;      
00283     Tenseur dzeta_prev = dzeta ;        
00284     
00285     // Creation of uninitialized tensors:
00286     Tenseur source_nuf(mp) ;    // source term in the equation for nuf
00287     Tenseur source_nuq(mp) ;    // source term in the equation for nuq
00288     Tenseur source_dzf(mp) ;    // matter source term in the eq. for dzeta
00289     Tenseur source_dzq(mp) ;    // quadratic source term in the eq. for dzeta
00290     Tenseur source_tggg(mp) ;   // source term in the eq. for tggg
00291     Tenseur source_shift(mp, 1, CON, mp.get_bvect_cart()) ;  
00292                             // source term for shift
00293     Tenseur mlngamma(mp) ;  // centrifugal potential
00294     
00295     // Preparations for the Poisson equations:
00296     // --------------------------------------
00297     if (nuf.get_etat() == ETATZERO) {
00298     nuf.set_etat_qcq() ; 
00299     nuf.set() = 0 ; 
00300     }
00301     
00302     if (relativistic) {
00303     if (nuq.get_etat() == ETATZERO) {
00304         nuq.set_etat_qcq() ; 
00305         nuq.set() = 0 ; 
00306     }
00307 
00308     if (tggg.get_etat() == ETATZERO) {
00309         tggg.set_etat_qcq() ; 
00310         tggg.set() = 0 ; 
00311     }
00312     
00313     if (dzeta.get_etat() == ETATZERO) {
00314         dzeta.set_etat_qcq() ; 
00315         dzeta.set() = 0 ; 
00316     }
00317     }
00318             
00319     ofstream fichconv("convergence.d") ;    // Output file for diff_ent
00320     fichconv << "#     diff_ent     GRV2       max_triax      vit_triax" << endl ; 
00321     
00322     ofstream fichfreq("frequency.d") ;    // Output file for  omega_c
00323     fichfreq << "#       f [Hz]" << endl ; 
00324     
00325     ofstream fichevol("evolution.d") ;    // Output file for various quantities
00326     fichevol << 
00327     "#       |dH/dr_eq/dH/dr_pole|      r_pole/r_eq ent_c" 
00328     << endl ; 
00329     
00330     diff_ent = 1 ; 
00331     double err_grv2 = 1 ; 
00332     double max_triax_prev = 0 ;     // Triaxial amplitude at previous step
00333     
00334     //=========================================================================
00335     //          Start of iteration
00336     //=========================================================================
00337 
00338     for(int mer=0 ; (diff_ent > precis) && (mer<mer_max) ; mer++ ) {
00339 
00340     cout << "-----------------------------------------------" << endl ;
00341     cout << "step: " << mer << endl ;
00342     cout << "diff_ent = " << display_bold << diff_ent << display_normal
00343          << endl ;    
00344     cout << "err_grv2 = " << err_grv2 << endl ;    
00345     fichconv << mer ;
00346     fichfreq << mer ;
00347     fichevol << mer ;
00348 
00349     if (mer >= mer_rot) {
00350     
00351         if (mer < mer_change_omega) {
00352         omega_c = omega_ini ; 
00353         }
00354         else {
00355         if (mer <= mer_fix_omega) {
00356             omega_c = omega_ini + accrois_omega * 
00357                   (mer - mer_change_omega) ;
00358         }
00359         }
00360 
00361     }
00362 
00363     //-----------------------------------------------
00364     //  Sources of the Poisson equations
00365     //-----------------------------------------------
00366     
00367     // Source for nu
00368     // -------------
00369     Tenseur beta = log(bbb) ; 
00370     beta.set_std_base() ; 
00371 
00372     if (relativistic) {
00373         source_nuf =  qpig * a_car *( ener_euler + s_euler ) ; 
00374 
00375         source_nuq = ak_car - flat_scalar_prod(logn.gradient_spher(), 
00376             logn.gradient_spher() + beta.gradient_spher()) ; 
00377     }
00378     else {
00379         source_nuf = qpig * nbar ; 
00380 
00381         source_nuq = 0 ; 
00382     }
00383     source_nuf.set_std_base() ;     
00384     source_nuq.set_std_base() ;     
00385 
00386     // Source for dzeta
00387     // ----------------
00388     source_dzf = 2 * qpig * a_car * (press + (ener_euler+press) * uuu*uuu ) ;
00389     source_dzf.set_std_base() ; 
00390   
00391     source_dzq = 1.5 * ak_car - flat_scalar_prod(logn.gradient_spher(),
00392                              logn.gradient_spher() ) ;      
00393     source_dzq.set_std_base() ;     
00394     
00395     // Source for tggg
00396     // ---------------
00397     
00398     source_tggg = 4 * qpig * nnn * a_car * bbb * press ;
00399     source_tggg.set_std_base() ; 
00400     
00401     (source_tggg.set()).mult_rsint() ; 
00402     
00403 
00404     // Source for shift
00405     // ----------------
00406         
00407     // Matter term: 
00408     source_shift = (-4*qpig) * nnn * a_car  * (ener_euler + press)
00409                 * u_euler ;
00410 
00411     // Quadratic terms:
00412     Tenseur vtmp =  6 * beta.gradient_spher() - 2 * logn.gradient_spher() ;
00413     vtmp.change_triad(mp.get_bvect_cart()) ; 
00414 
00415     Tenseur squad  = nnn * flat_scalar_prod(tkij, vtmp) ;     
00416 
00417     // The addition of matter terms and quadratic terms is performed
00418     //  component by component because u_euler is contravariant,
00419     //  while squad is covariant. 
00420         
00421     if (squad.get_etat() == ETATQCQ) {
00422         for (int i=0; i<3; i++) {
00423         source_shift.set(i) += squad(i) ; 
00424         }
00425     }
00426 
00427     source_shift.set_std_base() ;   
00428 
00429     //----------------------------------------------
00430     // Resolution of the Poisson equation for nuf 
00431     //----------------------------------------------
00432 
00433     source_nuf().poisson(par_poisson_nuf, nuf.set()) ; 
00434     
00435     cout << "Test of the Poisson equation for nuf :" << endl ; 
00436     Tbl err = source_nuf().test_poisson(nuf(), cout, true) ; 
00437     diff_nuf = err(0, 0) ; 
00438     
00439     //---------------------------------------
00440     // Triaxial perturbation of nuf
00441     //---------------------------------------
00442     
00443     if (mer == mer_triax) {
00444     
00445         if ( mg->get_np(0) == 1 ) {
00446         cout << 
00447         "Et_rot_diff::equilibrium: np must be stricly greater than 1"
00448         << endl << " to set a triaxial perturbation !" << endl ; 
00449         abort() ; 
00450         }
00451     
00452         const Coord& phi = mp.phi ; 
00453         const Coord& sint = mp.sint ; 
00454         Cmp perturb(mp) ; 
00455         perturb = 1 + ampli_triax * sint*sint * cos(2*phi) ;
00456         nuf.set() = nuf() * perturb ;  
00457         
00458         nuf.set_std_base() ;    // set the bases for spectral expansions
00459                     //  to be the standard ones for a 
00460                     //  scalar field
00461 
00462     }
00463     
00464     // Monitoring of the triaxial perturbation
00465     // ---------------------------------------
00466     
00467     Valeur& va_nuf = nuf.set().va ; 
00468     va_nuf.coef() ;     // Computes the spectral coefficients
00469     double max_triax = 0 ; 
00470 
00471     if ( mg->get_np(0) > 1 ) {
00472 
00473         for (int l=0; l<nz; l++) {  // loop on the domains
00474         for (int j=0; j<mg->get_nt(l); j++) {
00475             for (int i=0; i<mg->get_nr(l); i++) {
00476         
00477             // Coefficient of cos(2 phi) : 
00478             double xcos2p = (*(va_nuf.c_cf))(l, 2, j, i) ; 
00479 
00480             // Coefficient of sin(2 phi) : 
00481             double xsin2p = (*(va_nuf.c_cf))(l, 3, j, i) ; 
00482             
00483             double xx = sqrt( xcos2p*xcos2p + xsin2p*xsin2p ) ; 
00484             
00485             max_triax = ( xx > max_triax ) ? xx : max_triax ;           
00486             }
00487         } 
00488         }
00489         
00490     }
00491     
00492     cout << "Triaxial part of nuf : " << max_triax << endl ; 
00493 
00494     if (relativistic) {
00495         
00496         //----------------------------------------------
00497         // Resolution of the Poisson equation for nuq 
00498         //----------------------------------------------
00499 
00500         source_nuq().poisson(par_poisson_nuq, nuq.set()) ; 
00501         
00502         cout << "Test of the Poisson equation for nuq :" << endl ; 
00503         err = source_nuq().test_poisson(nuq(), cout, true) ;
00504         diff_nuq = err(0, 0) ; 
00505     
00506         //---------------------------------------------------------
00507         // Resolution of the vector Poisson equation for the shift
00508         //---------------------------------------------------------
00509 
00510 
00511         if (source_shift.get_etat() != ETATZERO) {
00512 
00513         for (int i=0; i<3; i++) {
00514             if(source_shift(i).dz_nonzero()) {
00515             assert( source_shift(i).get_dzpuis() == 4 ) ; 
00516             }
00517             else{
00518             (source_shift.set(i)).set_dzpuis(4) ; 
00519             }
00520         }
00521 
00522         }
00523         //##
00524         // source_shift.dec2_dzpuis() ;    // dzpuis 4 -> 2
00525 
00526         double lambda_shift = double(1) / double(3) ; 
00527 
00528         if ( mg->get_np(0) == 1 ) {
00529         lambda_shift = 0 ; 
00530         }
00531     
00532         source_shift.poisson_vect(lambda_shift, par_poisson_vect, 
00533                       shift, w_shift, khi_shift) ;      
00534         
00535         cout << "Test of the Poisson equation for shift_x :" << endl ; 
00536         err = source_shift(0).test_poisson(shift(0), cout, true) ;
00537         diff_shift_x = err(0, 0) ; 
00538     
00539         cout << "Test of the Poisson equation for shift_y :" << endl ; 
00540         err = source_shift(1).test_poisson(shift(1), cout, true) ;
00541         diff_shift_y = err(0, 0) ; 
00542         
00543         // Computation of tnphi and nphi from the Cartesian components
00544         //  of the shift
00545         // -----------------------------------------------------------
00546         
00547         fait_nphi() ; 
00548     
00549     }
00550 
00551     //-----------------------------------------
00552     // Determination of the fluid velociy U
00553     //-----------------------------------------
00554     
00555     if (mer > mer_fix_omega + delta_mer_kep) {
00556         
00557             omega_c *= fact_omega ;  // Increase of the angular velocity if 
00558     }              //  fact_omega != 1
00559     
00560     
00561     bool omega_trop_grand = false ; 
00562     bool kepler = true ; 
00563 
00564     while ( kepler ) {
00565     
00566         // Possible decrease of Omega to ensure a velocity < c 
00567     
00568         bool superlum = true ; 
00569     
00570         while ( superlum ) {
00571     
00572         // Computation of Omega(r,theta)
00573 
00574         if (omega_c == 0.) {
00575             omega_field = 0 ; 
00576         }
00577         else {
00578             par_frot.set(0) = omega_c ; 
00579             if (par_frot(2) != double(0)) {  // fixed a = R_eq / R_0
00580             par_frot.set(1) = ray_eq() / par_frot(2) ; 
00581             }
00582             double omeg_min = 0 ; 
00583             double omeg_max = omega_c ; 
00584             double precis1 = 1.e-14 ;
00585             int nitermax1 = 100 ; 
00586 
00587             fait_omega_field(omeg_min, omeg_max, precis1, nitermax1) ;
00588         }
00589 
00590         // New fluid velocity U :
00591     
00592         Cmp tmp = omega_field() - nphi() ; 
00593         tmp.annule(nzm1) ; 
00594         tmp.std_base_scal() ;
00595     
00596         tmp.mult_rsint() ;      //  Multiplication by r sin(theta)
00597 
00598         uuu = bbb() / nnn() * tmp ; 
00599     
00600         if (uuu.get_etat() == ETATQCQ) {
00601             // Same basis as (Omega -N^phi) r sin(theta) :
00602             ((uuu.set()).va).set_base( (tmp.va).base ) ;   
00603         }
00604 
00605 
00606         // Is the new velocity larger than c in the equatorial plane ?
00607     
00608         superlum = false ; 
00609     
00610         for (int l=0; l<nzet; l++) {
00611             for (int i=0; i<mg->get_nr(l); i++) {
00612         
00613             double u1 = uuu()(l, 0, j_b, i) ; 
00614             if (u1 >= 1.) {     // superluminal velocity
00615                 superlum = true ; 
00616                 cout << "U > c  for l, i : " << l << "  " << i 
00617                  << "   U = " << u1 << endl ;  
00618             }
00619             }
00620         }
00621         if ( superlum ) {
00622             cout << "**** VELOCITY OF LIGHT REACHED ****" << endl ; 
00623             omega_c /= fact_omega ;    // Decrease of Omega_c
00624             cout << "New central rotation frequency : " 
00625              << omega/(2.*M_PI) * f_unit <<  " Hz" << endl ; 
00626             omega_trop_grand = true ;  
00627         }
00628         }   // end of while ( superlum )
00629 
00630     
00631         // New computation of U (which this time is not superluminal)
00632         //  as well as of gam_euler, ener_euler, etc...
00633         // -----------------------------------
00634 
00635         hydro_euler() ; 
00636     
00637 
00638         //------------------------------------------------------
00639         //  First integral of motion 
00640         //------------------------------------------------------
00641     
00642         // Centrifugal potential : 
00643         if (relativistic) {
00644         mlngamma = - log( gam_euler ) ;
00645         }
00646         else {
00647         mlngamma = - 0.5 * uuu*uuu ; 
00648         }
00649     
00650         // Equatorial values of various potentials :
00651         double nuf_b  = nuf()(l_b, k_b, j_b, i_b) ; 
00652         double nuq_b  = nuq()(l_b, k_b, j_b, i_b) ; 
00653         double mlngamma_b  = mlngamma()(l_b, k_b, j_b, i_b) ; 
00654         double primf_b = prim_field()(l_b, k_b, j_b, i_b) ;
00655         
00656         
00657         // Central values of various potentials :
00658         double nuf_c = nuf()(0,0,0,0) ; 
00659         double nuq_c = nuq()(0,0,0,0) ; 
00660         double mlngamma_c = 0 ;
00661         double primf_c = prim_field()(0,0,0,0) ; 
00662     
00663         // Scale factor to ensure that the enthalpy is equal to ent_b at 
00664         //  the equator
00665         double alpha_r2 = ( ent_c - ent_b + mlngamma_c - mlngamma_b
00666                 + nuq_c - nuq_b + primf_c - primf_b) 
00667                 / ( nuf_b - nuf_c  ) ;
00668         alpha_r = sqrt(alpha_r2) ;
00669         cout << "alpha_r = " << alpha_r << endl ; 
00670 
00671         // Readjustment of nu :
00672         // -------------------
00673 
00674         logn = alpha_r2 * nuf + nuq ;
00675         double nu_c =  logn()(0,0,0,0) ;
00676 
00677         // First integral   --> enthalpy in all space
00678         //-----------------
00679 
00680         ent = (ent_c + nu_c + mlngamma_c) - logn - mlngamma - prim_field ;
00681 
00682         // Test: is the enthalpy negative somewhere in the equatorial plane
00683         //  inside the star ? If yes, this means that the Keplerian velocity
00684         //  has been overstep.
00685 
00686         kepler = false ; 
00687         for (int l=0; l<nzet; l++) {
00688         int imax = mg->get_nr(l) - 1 ;
00689         if (l == l_b) imax-- ;  // The surface point is skipped
00690         for (int i=0; i<imax; i++) { 
00691             if ( ent()(l, 0, j_b, i) < 0. ) {
00692             kepler = true ;
00693             cout << "ent < 0 for l, i : " << l << "  " << i 
00694                  << "   ent = " << ent()(l, 0, j_b, i) << endl ;  
00695             } 
00696         }
00697         }
00698     
00699         if ( kepler ) {
00700         cout << "**** KEPLERIAN VELOCITY REACHED ****" << endl ; 
00701         omega_c /= fact_omega ;    // Omega is decreased
00702         cout << "New central rotation frequency : " 
00703              << omega_c/(2.*M_PI) * f_unit << " Hz" << endl ; 
00704         omega_trop_grand = true ;  
00705         }
00706 
00707     }   // End of while ( kepler )
00708     
00709     if ( omega_trop_grand ) {   // fact_omega is decreased for the
00710                     //  next step 
00711         fact_omega = sqrt( fact_omega ) ; 
00712         cout << "**** New fact_omega : " << fact_omega << endl ; 
00713     }
00714 
00715 
00716     //----------------------------------------------------
00717     // Adaptation of the mapping to the new enthalpy field
00718     //----------------------------------------------------
00719     
00720     // Shall the adaptation be performed (cusp) ?
00721     // ------------------------------------------
00722     
00723     double dent_eq = ent().dsdr()(l_b, k_b, j_b, i_b) ; 
00724     double dent_pole = ent().dsdr()(l_b, k_b, 0, i_b) ;
00725     double rap_dent = fabs( dent_eq / dent_pole ) ; 
00726     cout << "| dH/dr_eq / dH/dr_pole | = " << rap_dent << endl ; 
00727     
00728     if ( rap_dent < thres_adapt ) {
00729         adapt_flag = 0 ;    // No adaptation of the mapping 
00730         cout << "******* FROZEN MAPPING  *********" << endl ; 
00731     }
00732     else{
00733         adapt_flag = 1 ;    // The adaptation of the mapping is to be
00734                 //  performed
00735     }
00736 
00737     mp_prev = mp_et ; 
00738 
00739     mp.adapt(ent(), par_adapt) ; 
00740 
00741     //----------------------------------------------------
00742     // Computation of the enthalpy at the new grid points
00743     //----------------------------------------------------
00744     
00745     mp_prev.homothetie(alpha_r) ; 
00746     
00747     mp.reevaluate(&mp_prev, nzet+1, ent.set()) ; 
00748 
00749 
00750     //----------------------------------------------------
00751     // Equation of state  
00752     //----------------------------------------------------
00753     
00754     equation_of_state() ;   // computes new values for nbar (n), ener (e) 
00755                 // and press (p) from the new ent (H)
00756     
00757     //---------------------------------------------------------
00758     // Matter source terms in the gravitational field equations 
00759     //---------------------------------------------------------
00760 
00761     //## Computation of tnphi and nphi from the Cartesian components
00762     //  of the shift for the test in hydro_euler():
00763         
00764         fait_nphi() ; 
00765 
00766     hydro_euler() ;     // computes new values for ener_euler (E), 
00767                 // s_euler (S) and u_euler (U^i)
00768 
00769     if (relativistic) {
00770 
00771         //-------------------------------------------------------
00772         //  2-D Poisson equation for tggg
00773         //-------------------------------------------------------
00774 
00775         mp.poisson2d(source_tggg(), mp.cmp_zero(), par_poisson_tggg,
00776              tggg.set()) ; 
00777         
00778         //-------------------------------------------------------
00779         //  2-D Poisson equation for dzeta
00780         //-------------------------------------------------------
00781 
00782         mp.poisson2d(source_dzf(), source_dzq(), par_poisson_dzeta,
00783              dzeta.set()) ; 
00784         
00785         err_grv2 = lbda_grv2 - 1; 
00786         cout << "GRV2: " << err_grv2 << endl ; 
00787         
00788     }
00789     else {
00790         err_grv2 = grv2() ; 
00791     }
00792 
00793 
00794     //---------------------------------------
00795     // Computation of the metric coefficients (except for N^phi)
00796     //---------------------------------------
00797 
00798     // Relaxations on nu and dzeta :  
00799 
00800     if (mer >= 10) {
00801         logn = relax * logn + relax_prev * logn_prev ;
00802 
00803         dzeta = relax * dzeta + relax_prev * dzeta_prev ; 
00804     }
00805     
00806     // Update of the metric coefficients N, A, B and computation of K_ij :
00807 
00808     update_metric() ; 
00809     
00810     //-----------------------
00811     //  Informations display
00812     //-----------------------
00813 
00814     partial_display(cout) ; 
00815     fichfreq << "  " << omega_c / (2*M_PI) * f_unit ; 
00816     fichevol << "  " << rap_dent ; 
00817     fichevol << "  " << ray_pole() / ray_eq() ; 
00818     fichevol << "  " << ent_c ; 
00819 
00820     //-----------------------------------------
00821     // Convergence towards a given baryon mass 
00822     //-----------------------------------------
00823 
00824     if (mer > mer_mass) {
00825         
00826         double xx ; 
00827         if (mbar_wanted > 0.) {
00828         xx = mass_b() / mbar_wanted - 1. ;
00829         cout << "Discrep. baryon mass <-> wanted bar. mass : " << xx 
00830              << endl ; 
00831         }
00832         else{
00833         xx = mass_g() / fabs(mbar_wanted) - 1. ;
00834         cout << "Discrep. grav. mass <-> wanted grav. mass : " << xx 
00835              << endl ; 
00836         }
00837         double xprog = ( mer > 2*mer_mass) ? 1. : 
00838                  double(mer-mer_mass)/double(mer_mass) ; 
00839         xx *= xprog ; 
00840         double ax = .5 * ( 2. + xx ) / (1. + xx ) ; 
00841         double fact = pow(ax, aexp_mass) ; 
00842         cout << "  xprog, xx, ax, fact : " << xprog << "  " <<
00843             xx << "  " << ax << "  " << fact << endl ; 
00844 
00845         if ( change_ent ) {
00846         ent_c *= fact ; 
00847         }
00848         else {
00849         if (mer%4 == 0) omega_c *= fact ; 
00850         }
00851     }
00852     
00853 
00854     //------------------------------------------------------------
00855     //  Relative change in enthalpy with respect to previous step 
00856     //------------------------------------------------------------
00857 
00858     Tbl diff_ent_tbl = diffrel( ent(), ent_prev() ) ; 
00859     diff_ent = diff_ent_tbl(0) ; 
00860     for (int l=1; l<nzet; l++) {
00861         diff_ent += diff_ent_tbl(l) ; 
00862     }
00863     diff_ent /= nzet ; 
00864     
00865     fichconv << "  " << log10( fabs(diff_ent) + 1.e-16 ) ;
00866     fichconv << "  " << log10( fabs(err_grv2) + 1.e-16 ) ;
00867     fichconv << "  " << log10( fabs(max_triax) + 1.e-16 ) ;
00868 
00869     vit_triax = 0 ;
00870     if ( (mer > mer_triax+1) && (max_triax_prev > 1e-13) ) {
00871         vit_triax = (max_triax - max_triax_prev) / max_triax_prev ; 
00872     }
00873 
00874     fichconv << "  " << vit_triax ;
00875     
00876     //------------------------------
00877     //  Recycling for the next step
00878     //------------------------------
00879     
00880     ent_prev = ent ; 
00881     logn_prev = logn ; 
00882     dzeta_prev = dzeta ; 
00883     max_triax_prev = max_triax ; 
00884     
00885     fichconv << endl ;
00886     fichfreq << endl ;
00887     fichevol << endl ;
00888     fichconv.flush() ; 
00889     fichfreq.flush() ; 
00890     fichevol.flush() ; 
00891 
00892     } // End of main loop
00893     
00894     //=========================================================================
00895     //          End of iteration
00896     //=========================================================================
00897 
00898     fichconv.close() ; 
00899     fichfreq.close() ; 
00900     fichevol.close() ; 
00901     
00902 
00903 }

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