strot_dirac_diff_equil.C

00001 /*
00002  *  Function Star_rot_Dirac_diff::equilibrium
00003  *
00004  *    (see file star_rot_dirac_diff.h for documentation).
00005  *
00006  */
00007 
00008 /*
00009  *   Copyright (c) 2005 Motoyuki Saijo
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 version 2
00015  *   as published by the Free Software Foundation.
00016  *
00017  *   LORENE is distributed in the hope that it will be useful,
00018  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020  *   GNU General Public License for more details.
00021  *
00022  *   You should have received a copy of the GNU General Public License
00023  *   along with LORENE; if not, write to the Free Software
00024  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025  *
00026  */
00027 
00028 char strot_dirac_diff_equil_C[] = "$Header: /cvsroot/Lorene/C++/Source/Star/strot_dirac_diff_equil.C,v 1.1 2005/08/13 19:48:19 m_saijo Exp $" ;
00029 
00030 /*
00031  * $Header: /cvsroot/Lorene/C++/Source/Star/strot_dirac_diff_equil.C,v 1.1 2005/08/13 19:48:19 m_saijo Exp $
00032  *
00033  */
00034 
00035 
00036 // C headers
00037 #include <math.h>
00038 #include <assert.h>
00039 
00040 // Lorene headers
00041 #include "star_rot_dirac_diff.h"
00042 #include "param.h"
00043 #include "utilitaires.h"
00044 #include "unites.h" 
00045 
00046 void Star_rot_Dirac_diff::equilibrium(double ent_c, double omega_c0, 
00047              double fact_omega, int , const Tbl& ent_limit,
00048          const Itbl& icontrol, const Tbl& control,
00049          double, double, Tbl& diff){    
00050     
00051 
00052   // Fundamental constants and units
00053   // --------------------------------
00054   using namespace Unites ;
00055 
00056   // For the display 
00057   // ---------------
00058   char display_bold[]="x[1m" ; display_bold[0] = 27 ;
00059   char display_normal[] = "x[0m" ; display_normal[0] = 27 ;
00060 
00061 
00062   // Grid parameters
00063   // ----------------
00064 
00065   const Mg3d* mg = mp.get_mg() ;
00066   int nz = mg->get_nzone() ;    // total number of domains
00067   int nzm1 = nz - 1 ;
00068 
00069   // Index of the point at phi=0, theta=pi/2 at the surface of the star:
00070   assert(mg->get_type_t() == SYM) ; 
00071   int l_b = nzet - 1 ; 
00072   int i_b = mg->get_nr(l_b) - 1 ; 
00073   int j_b = mg->get_nt(l_b) - 1 ; 
00074   int k_b = 0 ;
00075 
00076   // Value of the enthalpy defining the surface of the star
00077   double ent_b = ent_limit(nzet-1) ;
00078 
00079   // Parameters to control the iteration
00080   // -----------------------------------
00081 
00082   int mer_max = icontrol(0) ;
00083   int mer_rot = icontrol(1) ;
00084   int mer_change_omega = icontrol(2) ; 
00085   int mer_fix_omega = icontrol(3) ; 
00086   //int mer_mass = icontrol(4) ; 
00087   int delta_mer_kep = icontrol(5) ; 
00088   
00089   // Protections:
00090   if (mer_change_omega < mer_rot) {
00091     cout << "Star_rot_Dirac_diff::equilibrium: mer_change_omega < mer_rot !" 
00092      << '\n' ;
00093     cout << " mer_change_omega = " << mer_change_omega << '\n' ; 
00094     cout << " mer_rot = " << mer_rot << '\n' ; 
00095     abort() ; 
00096   }
00097   if (mer_fix_omega < mer_change_omega) {
00098     cout << "Star_rot_Dirac_diff::equilibrium: mer_fix_omega < mer_change_omega !" 
00099      << '\n' ;
00100     cout << " mer_fix_omega = " << mer_fix_omega << '\n' ; 
00101     cout << " mer_change_omega = " << mer_change_omega << '\n' ; 
00102     abort() ; 
00103   }
00104 
00105   double precis = control(0) ; 
00106   double omega_ini = control(1) ; 
00107   double relax = control(2) ;
00108   double relax_prev = double(1) - relax ;  
00109       
00110   // Error indicators
00111   // ----------------
00112 
00113   diff.set_etat_qcq() ;
00114   double& diff_ent = diff.set(0) ; 
00115 
00116   double alpha_r = 1 ;
00117 
00118   // Initializations
00119   // ---------------
00120 
00121   // Initial angular velocities 
00122   double omega_c = 0 ;
00123   
00124   double accrois_omega = (omega_c0 - omega_ini) / 
00125                 double(mer_fix_omega - mer_change_omega) ; 
00126  
00127 
00128   update_metric() ;    //update of the metric quantities 
00129 
00130   equation_of_state() ;  // update of the density, pressure,...etc
00131 
00132   hydro_euler() ; //update of the hydro quantities relative to the 
00133                   //  Eulerian observer
00134 
00135   // Quantities at the previous step :
00136   Scalar ent_prev = ent ;
00137   Scalar logn_prev = logn ;
00138   Scalar qqq_prev = qqq ;
00139   //  Vector beta_prev = beta ;
00140   // Sym_tensor_trans hh_prev = hh ;
00141 
00142   // Output files
00143   // -------------
00144 
00145   ofstream fichconv("convergence.d") ;    // Output file for diff_ent
00146   fichconv << "#     diff_ent    GRV2    max_triax   vit_triax" << '\n' ;   
00147 
00148   ofstream fichfreq("frequency.d") ;    // Output file for  omega
00149   fichfreq << "#       f [Hz]" << '\n' ; 
00150 
00151   ofstream fichevol("evolution.d") ;    // Output file for various quantities
00152   fichevol << 
00153     "#       |dH/dr_eq/dH/dr_pole|      r_pole/r_eq ent_c" 
00154        << '\n' ; 
00155 
00156   diff_ent = 1 ;
00157   double err_grv2 = 1 ;
00158 
00159 
00160 
00161 //=========================================================================
00162 //                   Start of iteration
00163 //=========================================================================
00164 
00165   for(int mer=0 ; (diff_ent > precis) && (mer<mer_max) ; mer++) {
00166 
00167  cout << "-----------------------------------------------" << '\n' ;
00168  cout << "step: " << mer << '\n' ;
00169  cout << "ent_c = " << display_bold << ent_c << display_normal
00170       << '\n' ;    
00171  cout << "diff_ent = " << display_bold << diff_ent << display_normal
00172       << '\n' ;    
00173  cout << "err_grv2 = " << err_grv2 << '\n' ;    
00174  fichconv << mer ;
00175  fichfreq << mer ;
00176  fichevol << mer ;
00177 
00178 
00179  // switch on rotation 
00180  if (mer >= mer_rot) {
00181           
00182    if (mer < mer_change_omega) {
00183      omega_c = omega_ini ; 
00184    }
00185    else {
00186      if (mer <= mer_fix_omega) {
00187        omega_c = omega_ini + accrois_omega * 
00188      (mer - mer_change_omega) ;
00189      }
00190    }
00191 
00192 
00193  }
00194 
00195 
00196  //---------------------------------------------------//
00197  // Resolution of the Poisson equation for logn       //
00198  // Note: ln_f is due to the fluid part               //
00199  //       ln_q is due to the quadratic metric part    //
00200  //---------------------------------------------------//
00201 
00202  Scalar ln_f_new(mp) ;
00203  Scalar ln_q_new(mp) ;
00204 
00205  solve_logn_f( ln_f_new ) ;
00206  solve_logn_q( ln_q_new ) ;
00207 
00208  ln_f_new.std_spectral_base() ;
00209  ln_q_new.std_spectral_base() ;
00210 
00211 
00212  //--------------------------------------------------//
00213  // Resolution of the Poisson equation for shift     //
00214  //--------------------------------------------------//
00215 
00216  Vector beta_new(mp, CON, mp.get_bvect_spher()) ;
00217 
00218  solve_shift( beta_new ) ;
00219 
00220  //------------------------------------
00221  // Determination of the fluid velocity
00222  //------------------------------------
00223 
00224  if (mer > mer_fix_omega + delta_mer_kep) {
00225               
00226    omega_c *= fact_omega ;  // Increase of the angular velocity if 
00227  }              //  fact_omega != 1
00228  
00229  bool omega_trop_grand = false ;
00230  bool kepler = true ;
00231 
00232  while ( kepler ) {
00233 
00234    // Possible decrease of Omega to ensure a velocity < c
00235 
00236    bool superlum = true ;
00237 
00238    while ( superlum ){
00239    
00240      // Computation of Omega(r,theta)
00241 
00242     if (omega_c == 0.) {
00243         omega_field = 0 ; 
00244     }
00245     else {
00246         par_frot.set(0) = omega_c ; 
00247         if (par_frot(2) != double(0)) {  // fixed a = R_eq / R_0
00248         par_frot.set(1) = ray_eq() / par_frot(2) ; 
00249         }
00250         double omeg_min = 0 ; 
00251         double omeg_max = omega_c ; 
00252         double precis1 = 1.e-14 ;
00253         int nitermax1 = 200 ; 
00254 
00255         fait_omega_field(omeg_min, omeg_max, precis1, nitermax1) ;
00256     }
00257 
00258      // New fluid velocity :
00259      //
00260 
00261      u_euler.set(1).set_etat_zero() ;
00262      u_euler.set(2).set_etat_zero() ;
00263 
00264      u_euler.set(3) = omega_field ;
00265      u_euler.set(3).annule(nzet,nzm1) ;   // nzet is defined in class Star
00266      u_euler.set(3).std_spectral_base() ;
00267      u_euler.set(3).mult_rsint() ;
00268      u_euler.set(3) += beta(3) ;
00269      u_euler.set(3).annule(nzet,nzm1) ;
00270      
00271      u_euler = u_euler / nn ; 
00272 
00273 
00274      // v2 (square of norm of u_euler)
00275      // -------------------------------
00276 
00277      v2 = contract(contract(gamma.cov(), 0, u_euler, 0), 0, u_euler, 0) ;
00278 
00279      // Is the new velocity larger than c in the equatorial plane ?
00280 
00281      superlum = false ;
00282      
00283      for (int l=0; l<nzet; l++) {
00284        for (int i=0; i<mg->get_nr(l); i++) {
00285       
00286      double u2 = v2.val_grid_point(l, 0, j_b, i) ; 
00287      if (u2 >= 1.) {     // superluminal velocity
00288        superlum = true ; 
00289        cout << "U > c  for l, i : " << l << "  " << i 
00290         << "   U = " << sqrt( u2 ) << '\n' ;  
00291      }
00292        }
00293      }
00294      if ( superlum ) {
00295        cout << "**** VELOCITY OF LIGHT REACHED ****" << '\n' ; 
00296        omega /= fact_omega ;    // Decrease of Omega
00297        cout << "New rotation frequency : " 
00298         << omega/(2.*M_PI) * f_unit <<  " Hz" << '\n' ; 
00299        omega_trop_grand = true ;  
00300      }
00301    }    // end of while ( superlum )
00302 
00303 
00304    // New computation of U (this time is not superluminal)
00305    // as well as of gam_euler, ener_euler,...etc
00306 
00307    hydro_euler() ;
00308 
00309 
00310 
00311  //--------------------------------//
00312  // First integral of motion       //
00313  //--------------------------------//
00314 
00315  Scalar mlngamma(mp) ;  //  -log( gam_euler )
00316 
00317  mlngamma = - log( gam_euler ) ;
00318 
00319  // Equatorial values of various potentials :
00320  double ln_f_b = ln_f_new.val_grid_point(l_b, k_b, j_b, i_b) ; 
00321  double ln_q_b = ln_q_new.val_grid_point(l_b, k_b, j_b, i_b) ;
00322  double mlngamma_b = mlngamma.val_grid_point(l_b, k_b, j_b, i_b) ;
00323  double primf_b = prim_field.val_grid_point(l_b, k_b, j_b, i_b) ;
00324 
00325  // Central values of various potentials :
00326  double ln_f_c = ln_f_new.val_grid_point(0,0,0,0) ;
00327  double ln_q_c = ln_q_new.val_grid_point(0,0,0,0) ;
00328  double mlngamma_c = 0 ;
00329  double primf_c = prim_field.val_grid_point(0,0,0,0) ; 
00330 
00331  // Scale factor to ensure that the (log of) enthalpy is equal to 
00332  // ent_b at the equator
00333  double alpha_r2 = ( ent_c - ent_b + mlngamma_c - mlngamma_b
00334              + ln_q_c - ln_q_b + primf_c - primf_b) 
00335                      / ( ln_f_b - ln_f_c  ) ;
00336 
00337  alpha_r = sqrt(alpha_r2) ;
00338 
00339  cout << "alpha_r = " << alpha_r << '\n' ; 
00340 
00341  // Rescaling of the grid (no adaptation!)
00342  //---------------------------------------
00343  mp.homothetie(alpha_r) ;
00344 
00345  // Readjustment of logn :
00346  // -----------------------
00347 
00348  logn = alpha_r2 * ln_f_new + ln_q_new ;
00349 
00350  double logn_c = logn.val_grid_point(0,0,0,0) ;
00351 
00352  // First integral of motion -> (log of) enthalpy in all space
00353  // ----------------------------------------------------------
00354 
00355  ent = (ent_c + logn_c + mlngamma_c) - logn - mlngamma - prim_field;
00356 
00357 
00358  // --------------------------------------------------------------
00359  // Test: is the enthalpy negative somewhere in the equatorial plane
00360  //       inside the star?
00361  // --------------------------------------------------------
00362 
00363  kepler = false ; 
00364  for (int l=0; l<nzet; l++) {
00365    int imax = mg->get_nr(l) - 1 ;
00366    if (l == l_b) imax-- ;  // The surface point is skipped
00367    for (int i=0; i<imax; i++) { 
00368      if ( ent.val_grid_point(l, 0, j_b, i) < 0. ) {
00369        kepler = true ;
00370        cout << "ent < 0 for l, i : " << l << "  " << i 
00371         << "   ent = " << ent.val_grid_point(l, 0, j_b, i) << '\n' ;  
00372      } 
00373    }
00374  }
00375 
00376  if ( kepler ) {
00377    cout << "**** KEPLERIAN VELOCITY REACHED ****" << '\n' ; 
00378    omega /= fact_omega ;    // Omega is decreased
00379    cout << "New central rotation frequency : " 
00380     << omega_c/(2.*M_PI) * f_unit << " Hz" << '\n' ; 
00381    omega_trop_grand = true ;  
00382  }
00383 
00384  } // End of while ( kepler )
00385 
00386  if ( omega_trop_grand ) {   // fact_omega is decreased for the
00387                              //  next step 
00388    fact_omega = sqrt( fact_omega ) ; 
00389    cout << "**** New fact_omega : " << fact_omega << '\n' ; 
00390  }
00391 
00392 
00393 //---------------------------------
00394  // Equation of state
00395  //---------------------------------
00396 
00397  equation_of_state() ;  // computes new values for nbar (n), ener (e),
00398                         // and press (p) from the new ent (H)
00399 
00400  hydro_euler() ;
00401 
00402  //---------------------------------------------//
00403  // Resolution of the Poisson equation for qqq  //
00404  //---------------------------------------------//
00405 
00406  Scalar q_new(mp) ;
00407 
00408  solve_qqq( q_new ) ;
00409 
00410  q_new.std_spectral_base() ;
00411 
00412  //----------------------------------------------//
00413  // Resolution of the Poisson equation for hh    //
00414  //----------------------------------------------//
00415 
00416  Sym_tensor_trans hij_new(mp, mp.get_bvect_spher(), flat) ;
00417 
00418  solve_hij( hij_new ) ;
00419 
00420  hh = hij_new ; 
00421  qqq = q_new ;
00422  beta = beta_new ; 
00423 
00424  //---------------------------------------
00425  // Calculate error of the GRV2 identity 
00426  //---------------------------------------
00427 
00428  err_grv2 = grv2() ;
00429 
00430 
00431  //--------------------------------------
00432  // Relaxations on some quantities....?
00433  //
00434  // ** On logn and qqq?
00435  //--------------------------------------
00436 
00437  if (mer >= 10) {
00438    logn = relax * logn + relax_prev * logn_prev ;
00439 
00440    qqq = relax * qqq + relax_prev * qqq_prev ;
00441 
00442  }
00443 
00444  // Update of the metric quantities :
00445 
00446    update_metric() ;
00447 
00448  //---------------------------
00449  //  Informations display
00450  // More to come later......
00451  //---------------------------
00452 
00453  // partial_display(cout) ;    // What is partial_display(cout) ? 
00454  fichfreq << "  " << omega_c / (2*M_PI) * f_unit ; 
00455  fichevol << "  " << ent_c ; 
00456 
00457  //-----------------------------------------------------------
00458  // Relative change in enthalpy with respect to previous step
00459  // ** Check:  Is diffrel(ent, ent_prev) ok?  
00460  //-----------------------------------------------------------
00461 
00462  Tbl diff_ent_tbl = diffrel( ent, ent_prev ) ;
00463  diff_ent = diff_ent_tbl(0) ;
00464  for (int l=1; l<nzet; l++) {
00465    diff_ent += diff_ent_tbl(l) ;
00466  }
00467  diff_ent /= nzet ;
00468 
00469  fichconv << " " << log10( fabs(diff_ent) + 1.e-16 ) ;
00470  fichconv << " " << log10( fabs(err_grv2) + 1.e-16 ) ;
00471 
00472  //------------------------------
00473  // Recycling for the next step
00474  //------------------------------
00475 
00476  ent_prev = ent ;
00477  logn_prev = logn ;
00478  qqq_prev = qqq ;
00479 
00480  fichconv << '\n' ;     
00481  fichfreq << '\n' ;     
00482  fichevol << '\n' ;
00483  fichconv.flush() ; 
00484  fichfreq.flush() ; 
00485  fichevol.flush() ; 
00486       
00487      
00488   } // End of main loop              
00489  
00490   //=================================================
00491   //             End of iteration
00492   //=================================================
00493 
00494   fichconv.close() ; 
00495   fichfreq.close() ; 
00496   fichevol.close() ; 
00497 
00498 
00499 }

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