LORENE
strot_dirac_equilibrium.C
1/*
2 * Function Star_rot_Dirac::equilibrium
3 *
4 * (see file star_rot_dirac.h for documentation).
5 *
6 */
7
8/*
9 * Copyright (c) 2005 Lap-Ming Lin & Jerome Novak
10 *
11 * This file is part of LORENE.
12 *
13 * LORENE is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License version 2
15 * as published by the Free Software Foundation.
16 *
17 * LORENE is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with LORENE; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 */
27
28
29
30/*
31 * $Id: strot_dirac_equilibrium.C,v 1.14 2016/12/05 16:18:15 j_novak Exp $
32 * $Log: strot_dirac_equilibrium.C,v $
33 * Revision 1.14 2016/12/05 16:18:15 j_novak
34 * Suppression of some global variables (file names, loch, ...) to prevent redefinitions
35 *
36 * Revision 1.13 2014/10/13 08:53:40 j_novak
37 * Lorene classes and functions now belong to the namespace Lorene.
38 *
39 * Revision 1.12 2014/10/06 15:13:18 j_novak
40 * Modified #include directives to use c++ syntax.
41 *
42 * Revision 1.11 2009/10/26 10:54:33 j_novak
43 * Added the case of a NONSYM base in theta.
44 *
45 * Revision 1.10 2008/02/25 10:40:52 j_novak
46 * Added the flag mer_hij to control the step from which the equation for h^{ij}
47 * is being solved.
48 *
49 * Revision 1.9 2006/03/14 15:18:21 lm_lin
50 *
51 * Add convergence to a given baryon mass.
52 *
53 * Revision 1.8 2005/11/28 14:45:16 j_novak
54 * Improved solution of the Poisson tensor equation in the case of a transverse
55 * tensor.
56 *
57 * Revision 1.7 2005/09/16 14:04:49 j_novak
58 * The equation for hij is now solved only for mer > mer_fix_omega. It uses the
59 * Poisson solver of the class Sym_tensor_trans.
60 *
61 * Revision 1.6 2005/04/20 14:26:29 j_novak
62 * Removed some outputs.
63 *
64 * Revision 1.5 2005/04/05 09:24:05 j_novak
65 * minor modifs
66 *
67 * Revision 1.4 2005/03/10 09:39:19 j_novak
68 * The order of resolution has been changed in the iteration step.
69 *
70 * Revision 1.3 2005/02/17 17:30:09 f_limousin
71 * Change the name of some quantities to be consistent with other classes
72 * (for instance nnn is changed to nn, shift to beta, beta to lnq...)
73 *
74 * Revision 1.2 2005/02/09 13:36:42 lm_lin
75 *
76 * Calculate GRV2 during iterations.
77 *
78 * Revision 1.1 2005/01/31 08:51:48 j_novak
79 * New files for rotating stars in Dirac gauge (still under developement).
80 *
81 *
82 * $Header: /cvsroot/Lorene/C++/Source/Star/strot_dirac_equilibrium.C,v 1.14 2016/12/05 16:18:15 j_novak Exp $
83 *
84 */
85
86
87// C headers
88#include <cmath>
89#include <cassert>
90
91// Lorene headers
92#include "star_rot_dirac.h"
93
94#include "utilitaires.h"
95#include "unites.h"
96
97namespace Lorene {
98void Star_rot_Dirac::equilibrium(double ent_c, double omega0,
99 double fact_omega, int , const Tbl& ent_limit,
100 const Itbl& icontrol, const Tbl& control,
101 double mbar_wanted, double aexp_mass, Tbl& diff){
102
103
104 // Fundamental constants and units
105 // --------------------------------
106 using namespace Unites ;
107
108 // For the display
109 // ---------------
110 char display_bold[]="x[1m" ; display_bold[0] = 27 ;
111 char display_normal[] = "x[0m" ; display_normal[0] = 27 ;
112
113
114 // Grid parameters
115 // ----------------
116
117 const Mg3d* mg = mp.get_mg() ;
118 int nz = mg->get_nzone() ; // total number of domains
119 int nzm1 = nz - 1 ;
120
121 // Index of the point at phi=0, theta=pi/2 at the surface of the star:
122 int type_t = mg->get_type_t() ;
123 assert( ( type_t == SYM) || (type_t == NONSYM) ) ;
124 int l_b = nzet - 1 ;
125 int i_b = mg->get_nr(l_b) - 1 ;
126 int j_b = (type_t == SYM ? mg->get_nt(l_b) - 1 : mg->get_nt(l_b)/2 ) ;
127 int k_b = 0 ;
128
129 // Value of the enthalpy defining the surface of the star
130 double ent_b = ent_limit(nzet-1) ;
131
132 // Parameters to control the iteration
133 // -----------------------------------
134
135 int mer_max = icontrol(0) ;
136 int mer_rot = icontrol(1) ;
137 int mer_change_omega = icontrol(2) ;
138 int mer_fix_omega = icontrol(3) ;
139 int mer_mass = icontrol(4) ;
140 int delta_mer_kep = icontrol(5) ;
141 int mer_hij = icontrol(6) ;
142
143 // Protections:
144 if (mer_change_omega < mer_rot) {
145 cout << "Star_rot_Dirac::equilibrium: mer_change_omega < mer_rot !"
146 << endl ;
147 cout << " mer_change_omega = " << mer_change_omega << endl ;
148 cout << " mer_rot = " << mer_rot << endl ;
149 abort() ;
150 }
151 if (mer_fix_omega < mer_change_omega) {
152 cout << "Star_rot_Dirac::equilibrium: mer_fix_omega < mer_change_omega !"
153 << endl ;
154 cout << " mer_fix_omega = " << mer_fix_omega << endl ;
155 cout << " mer_change_omega = " << mer_change_omega << endl ;
156 abort() ;
157 }
158
159 // In order to converge to a given baryon mass, shall the central
160 // enthalpy be varied or Omega ?
161 bool change_ent = true ;
162 if (mer_mass < 0) {
163 change_ent = false ;
164 mer_mass = abs(mer_mass) ;
165 }
166
167
168 double precis = control(0) ;
169 double omega_ini = control(1) ;
170 double relax = control(2) ;
171 double relax_prev = double(1) - relax ;
172
173 // Error indicators
174 // ----------------
175
176 diff.annule_hard() ;
177 double& diff_ent = diff.set(0) ;
178
179 double alpha_r = 1 ;
180
181 // Initializations
182 // ---------------
183
184 // Initial angular velocities
185 omega = 0 ;
186
187 double accrois_omega = (omega0 - omega_ini) /
188 double(mer_fix_omega - mer_change_omega) ;
189
190
191 update_metric() ; //update of the metric quantities
192
193 equation_of_state() ; // update of the density, pressure,...etc
194
195 hydro_euler() ; //update of the hydro quantities relative to the
196 // Eulerian observer
197
198 // Quantities at the previous step :
199 Scalar ent_prev = ent ;
200 Scalar logn_prev = logn ;
201 Scalar qqq_prev = qqq ;
202 // Vector beta_prev = beta ;
203 // Sym_tensor_trans hh_prev = hh ;
204
205 // Output files
206 // -------------
207
208 ofstream fichconv("convergence.d") ; // Output file for diff_ent
209 fichconv << "# diff_ent GRV2 max_triax vit_triax" << endl ;
210
211 ofstream fichfreq("frequency.d") ; // Output file for omega
212 fichfreq << "# f [Hz]" << endl ;
213
214 ofstream fichevol("evolution.d") ; // Output file for various quantities
215 fichevol <<
216 "# |dH/dr_eq/dH/dr_pole| r_pole/r_eq ent_c"
217 << endl ;
218
219 diff_ent = 1 ;
220 double err_grv2 = 1 ;
221
222
223
224//=========================================================================
225// Start of iteration
226//=========================================================================
227
228 for(int mer=0 ; (diff_ent > precis) && (mer<mer_max) ; mer++) {
229
230 cout << "-----------------------------------------------" << endl ;
231 cout << "step: " << mer << endl ;
232 cout << "diff_ent = " << display_bold << diff_ent << display_normal
233 << endl ;
234 cout << "err_grv2 = " << err_grv2 << endl ;
235 fichconv << mer ;
236 fichfreq << mer ;
237 fichevol << mer ;
238
239
240 // switch on rotation
241 if (mer >= mer_rot) {
242
243 if (mer < mer_change_omega) {
244 omega = omega_ini ;
245 }
246 else {
247 if (mer <= mer_fix_omega) {
248 omega = omega_ini + accrois_omega *
249 (mer - mer_change_omega) ;
250 }
251 }
252
253
254 }
255
256
257 //---------------------------------------------------//
258 // Resolution of the Poisson equation for logn //
259 // Note: ln_f is due to the fluid part //
260 // ln_q is due to the quadratic metric part //
261 //---------------------------------------------------//
262
263 Scalar ln_f_new(mp) ;
264 Scalar ln_q_new(mp) ;
265
266 solve_logn_f( ln_f_new ) ;
267 solve_logn_q( ln_q_new ) ;
268
269 ln_f_new.std_spectral_base() ;
270 ln_q_new.std_spectral_base() ;
271
272
273 //--------------------------------------------------//
274 // Resolution of the Poisson equation for shift //
275 //--------------------------------------------------//
276
277 Vector beta_new(mp, CON, mp.get_bvect_spher()) ;
278
279 solve_shift( beta_new ) ;
280
281 //------------------------------------
282 // Determination of the fluid velocity
283 //------------------------------------
284
285 if (mer > mer_fix_omega + delta_mer_kep) {
286
287 omega *= fact_omega ; // Increase of the angular velocity if
288 } // fact_omega != 1
289
290 bool omega_trop_grand = false ;
291 bool kepler = true ;
292
293 while ( kepler ) {
294
295 // Possible decrease of Omega to ensure a velocity < c
296
297 bool superlum = true ;
298
299 while ( superlum ){
300
301 // New fluid velocity :
302 //
303
304 u_euler.set(1).set_etat_zero() ;
305 u_euler.set(2).set_etat_zero() ;
306
307 u_euler.set(3) = omega ;
308 u_euler.set(3).annule(nzet,nzm1) ; // nzet is defined in class Star
309 u_euler.set(3).std_spectral_base() ;
310 u_euler.set(3).mult_rsint() ;
311 u_euler.set(3) += beta(3) ;
312 u_euler.set(3).annule(nzet,nzm1) ;
313
314 u_euler = u_euler / nn ;
315
316
317 // v2 (square of norm of u_euler)
318 // -------------------------------
319
320 v2 = contract(contract(gamma.cov(), 0, u_euler, 0), 0, u_euler, 0) ;
321
322 // Is the new velocity larger than c in the equatorial plane ?
323
324 superlum = false ;
325
326 for (int l=0; l<nzet; l++) {
327 for (int i=0; i<mg->get_nr(l); i++) {
328
329 double u2 = v2.val_grid_point(l, 0, j_b, i) ;
330 if (u2 >= 1.) { // superluminal velocity
331 superlum = true ;
332 cout << "U > c for l, i : " << l << " " << i
333 << " U = " << sqrt( u2 ) << endl ;
334 }
335 }
336 }
337 if ( superlum ) {
338 cout << "**** VELOCITY OF LIGHT REACHED ****" << endl ;
339 omega /= fact_omega ; // Decrease of Omega
340 cout << "New rotation frequency : "
341 << omega/(2.*M_PI) * f_unit << " Hz" << endl ;
342 omega_trop_grand = true ;
343 }
344 } // end of while ( superlum )
345
346
347 // New computation of U (this time is not superluminal)
348 // as well as of gam_euler, ener_euler,...etc
349
350 hydro_euler() ;
351
352
353
354 //--------------------------------//
355 // First integral of motion //
356 //--------------------------------//
357
358 Scalar mlngamma(mp) ; // -log( gam_euler )
359
360 mlngamma = - log( gam_euler ) ;
361
362 // Equatorial values of various potentials :
363 double ln_f_b = ln_f_new.val_grid_point(l_b, k_b, j_b, i_b) ;
364 double ln_q_b = ln_q_new.val_grid_point(l_b, k_b, j_b, i_b) ;
365 double mlngamma_b = mlngamma.val_grid_point(l_b, k_b, j_b, i_b) ;
366
367 // Central values of various potentials :
368 double ln_f_c = ln_f_new.val_grid_point(0,0,0,0) ;
369 double ln_q_c = ln_q_new.val_grid_point(0,0,0,0) ;
370 double mlngamma_c = 0 ;
371
372 // Scale factor to ensure that the (log of) enthalpy is equal to
373 // ent_b at the equator
374 double alpha_r2 = ( ent_c - ent_b + mlngamma_c - mlngamma_b
375 + ln_q_c - ln_q_b) / ( ln_f_b - ln_f_c ) ;
376
377 alpha_r = sqrt(alpha_r2) ;
378
379 cout << "alpha_r = " << alpha_r << endl ;
380
381 // Rescaling of the grid (no adaptation!)
382 //---------------------------------------
383 mp.homothetie(alpha_r) ;
384
385 // Readjustment of logn :
386 // -----------------------
387
388 logn = alpha_r2 * ln_f_new + ln_q_new ;
389
390 double logn_c = logn.val_grid_point(0,0,0,0) ;
391
392 // First integral of motion -> (log of) enthalpy in all space
393 // ----------------------------------------------------------
394
395 ent = (ent_c + logn_c + mlngamma_c) - logn - mlngamma ;
396
397
398 // --------------------------------------------------------------
399 // Test: is the enthalpy negative somewhere in the equatorial plane
400 // inside the star?
401 // --------------------------------------------------------
402
403 kepler = false ;
404 for (int l=0; l<nzet; l++) {
405 int imax = mg->get_nr(l) - 1 ;
406 if (l == l_b) imax-- ; // The surface point is skipped
407 for (int i=0; i<imax; i++) {
408 if ( ent.val_grid_point(l, 0, j_b, i) < 0. ) {
409 kepler = true ;
410 cout << "ent < 0 for l, i : " << l << " " << i
411 << " ent = " << ent.val_grid_point(l, 0, j_b, i) << endl ;
412 }
413 }
414 }
415
416 if ( kepler ) {
417 cout << "**** KEPLERIAN VELOCITY REACHED ****" << endl ;
418 omega /= fact_omega ; // Omega is decreased
419 cout << "New rotation frequency : "
420 << omega/(2.*M_PI) * f_unit << " Hz" << endl ;
421 omega_trop_grand = true ;
422 }
423
424 } // End of while ( kepler )
425
426 if ( omega_trop_grand ) { // fact_omega is decreased for the
427 // next step
428 fact_omega = sqrt( fact_omega ) ;
429 cout << "**** New fact_omega : " << fact_omega << endl ;
430 }
431
432
433//---------------------------------
434 // Equation of state
435 //---------------------------------
436
437 equation_of_state() ; // computes new values for nbar (n), ener (e),
438 // and press (p) from the new ent (H)
439
440 hydro_euler() ;
441
442 //---------------------------------------------//
443 // Resolution of the Poisson equation for qqq //
444 //---------------------------------------------//
445
446 Scalar q_new(mp) ;
447
448 solve_qqq( q_new ) ;
449
450 q_new.std_spectral_base() ;
451
452 //----------------------------------------------//
453 // Resolution of the Poisson equation for hh //
454 //----------------------------------------------//
455
456 Sym_tensor_trans hij_new(mp, mp.get_bvect_spher(), flat) ;
457
458 if (mer > mer_hij )
459 solve_hij( hij_new ) ;
460 else
461 hij_new.set_etat_zero() ;
462
463 hh = hij_new ;
464 qqq = q_new ;
465 beta = beta_new ;
466
467 //---------------------------------------
468 // Calculate error of the GRV2 identity
469 //---------------------------------------
470
471 err_grv2 = grv2() ;
472
473
474 //--------------------------------------
475 // Relaxations on some quantities....?
476 //
477 // ** On logn and qqq?
478 //--------------------------------------
479
480 if (mer >= 10) {
481 logn = relax * logn + relax_prev * logn_prev ;
482
483 qqq = relax * qqq + relax_prev * qqq_prev ;
484
485 }
486
487 // Update of the metric quantities :
488
489 update_metric() ;
490
491 //---------------------------
492 // Informations display
493 // More to come later......
494 //---------------------------
495
496 // partial_display(cout) ; // What is partial_display(cout) ?
497 fichfreq << " " << omega / (2*M_PI) * f_unit ;
498 fichevol << " " << ent_c ;
499
500
501 //-----------------------------------------
502 // Convergence towards a given baryon mass
503 //-----------------------------------------
504
505 if (mer > mer_mass) {
506
507 double xx ;
508 if (mbar_wanted > 0.) {
509 xx = mass_b() / mbar_wanted - 1. ;
510 cout << "Discrep. baryon mass <-> wanted bar. mass : " << xx
511 << endl ;
512 }
513 else{
514 xx = mass_g() / fabs(mbar_wanted) - 1. ;
515 cout << "Discrep. grav. mass <-> wanted grav. mass : " << xx
516 << endl ;
517 }
518 double xprog = ( mer > 2*mer_mass) ? 1. :
519 double(mer-mer_mass)/double(mer_mass) ;
520 xx *= xprog ;
521 double ax = .5 * ( 2. + xx ) / (1. + xx ) ;
522 double fact = pow(ax, aexp_mass) ;
523 cout << " xprog, xx, ax, fact : " << xprog << " " <<
524 xx << " " << ax << " " << fact << endl ;
525
526 if ( change_ent ) {
527 ent_c *= fact ;
528 }
529 else {
530 if (mer%4 == 0) omega *= fact ;
531 }
532 }
533
534
535 //-----------------------------------------------------------
536 // Relative change in enthalpy with respect to previous step
537 // ** Check: Is diffrel(ent, ent_prev) ok?
538 //-----------------------------------------------------------
539
540 Tbl diff_ent_tbl = diffrel( ent, ent_prev ) ;
541 diff_ent = diff_ent_tbl(0) ;
542 for (int l=1; l<nzet; l++) {
543 diff_ent += diff_ent_tbl(l) ;
544 }
545 diff_ent /= nzet ;
546
547 fichconv << " " << log10( fabs(diff_ent) + 1.e-16 ) ;
548 fichconv << " " << log10( fabs(err_grv2) + 1.e-16 ) ;
549
550 //------------------------------
551 // Recycling for the next step
552 //------------------------------
553
554 ent_prev = ent ;
555 logn_prev = logn ;
556 qqq_prev = qqq ;
557
558 fichconv << endl ;
559 fichfreq << endl ;
560 fichevol << endl ;
561 fichconv.flush() ;
562 fichfreq.flush() ;
563 fichevol.flush() ;
564
565
566 } // End of main loop
567
568 //=================================================
569 // End of iteration
570 //=================================================
571
572 fichconv.close() ;
573 fichfreq.close() ;
574 fichevol.close() ;
575
576
577}
578}
Basic integer array class.
Definition itbl.h:122
Multi-domain grid.
Definition grilles.h:279
int get_type_t() const
Returns the type of sampling in the direction: SYM : : symmetry with respect to the equatorial pl...
Definition grilles.h:502
int get_nt(int l) const
Returns the number of points in the co-latitude direction ( ) in domain no. l.
Definition grilles.h:474
int get_nzone() const
Returns the number of domains.
Definition grilles.h:465
int get_nr(int l) const
Returns the number of points in the radial direction ( ) in domain no. l.
Definition grilles.h:469
Tensor field of valence 0 (or component of a tensorial field).
Definition scalar.h:393
virtual void std_spectral_base()
Sets the spectral bases of the Valeur va to the standard ones for a scalar field.
Definition scalar.C:790
double val_grid_point(int l, int k, int j, int i) const
Returns the value of the field at a specified grid point.
Definition scalar.h:643
virtual double mass_g() const
Gravitational mass.
Sym_tensor_trans hh
is defined by .
double omega
Rotation angular velocity ([f_unit] ).
const Metric_flat & flat
flat metric (spherical components)
void solve_logn_f(Scalar &ln_f_new) const
Solution of the two scalar Poisson equations for rotating stars in Dirac gauge.
void solve_qqq(Scalar &q_new) const
Solution of the two scalar Poisson equations for rotating stars in Dirac gauge.
void update_metric()
Computes metric quantities from known potentials.
void solve_hij(Sym_tensor_trans &hij_new) const
Solution of the tensor Poisson equation for rotating stars in Dirac gauge.
virtual void hydro_euler()
Computes the hydrodynamical quantities relative to the Eulerian observer from those in the fluid fram...
void solve_logn_q(Scalar &ln_q_new) const
Solution of the two scalar Poisson equations for rotating stars in Dirac gauge.
virtual double mass_b() const
Baryonic mass.
void equilibrium(double ent_c, double omega0, double fact_omega, int nzadapt, const Tbl &ent_limit, const Itbl &icontrol, const Tbl &control, double mbar_wanted, double aexp_mass, Tbl &diff)
Computes an equilibrium configuration.
void solve_shift(Vector &shift_new) const
Solution of the shift equation for rotating stars in Dirac gauge.
virtual double grv2() const
Error on the virial identity GRV2.
Scalar logn
Logarithm of the lapse N .
Definition star.h:222
Scalar nn
Lapse function N .
Definition star.h:225
void equation_of_state()
Computes the proper baryon and energy density, as well as pressure from the enthalpy.
Definition star.C:465
Scalar gam_euler
Lorentz factor between the fluid and Eulerian observers.
Definition star.h:204
Metric gamma
3-metric
Definition star.h:235
Scalar ent
Log-enthalpy.
Definition star.h:190
Vector u_euler
Fluid 3-velocity with respect to the Eulerian observer.
Definition star.h:207
Map & mp
Mapping associated with the star.
Definition star.h:180
int nzet
Number of domains of *mp occupied by the star.
Definition star.h:183
Vector beta
Shift vector.
Definition star.h:228
Transverse symmetric tensors of rank 2.
Definition sym_tensor.h:611
Basic array class.
Definition tbl.h:161
void annule_hard()
Sets the Tbl to zero in a hard way.
Definition tbl.C:375
double & set(int i)
Read/write of a particular element (index i) (1D case).
Definition tbl.h:281
Tensor field of valence 1.
Definition vector.h:188
Cmp sqrt(const Cmp &)
Square root.
Definition cmp_math.C:223
Cmp log10(const Cmp &)
Basis 10 logarithm.
Definition cmp_math.C:325
Tbl diffrel(const Cmp &a, const Cmp &b)
Relative difference between two Cmp (norme version).
Definition cmp_math.C:507
Cmp pow(const Cmp &, int)
Power .
Definition cmp_math.C:351
Cmp abs(const Cmp &)
Absolute value.
Definition cmp_math.C:413
Cmp log(const Cmp &)
Neperian logarithm.
Definition cmp_math.C:299
virtual void set_etat_zero()
Sets the logical state of all components to ETATZERO (zero state).
Definition tensor.C:506
Tenseur contract(const Tenseur &, int id1, int id2)
Self contraction of two indices of a Tenseur .
Lorene prototypes.
Definition app_hor.h:67
Standard units of space, time and mass.