et_rot_mag_equil.C

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

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