void heartbeat(struct reb_simulation* const r){ if (reb_output_check(r, 1000.*r->dt)){ reb_output_timing(r, tmax); } if (reb_output_check(r, 362.)){ // Output the time and the MEGNO to the screen and a file. FILE* f = fopen("Y.txt","a+"); fprintf(f," %.20e %.20e\n",r->t, reb_tools_calculate_megno(r)); //printf(" %.20e %.20e\n",r->t, reb_tools_calculate_megno(r)); fclose(f); } }
void reb_tools_megno_init(struct reb_simulation* const r, double delta){ int N_var = r->N; r->calculate_megno = 1; r->megno_Ys = 0.; r->megno_Yss = 0.; r->megno_cov_Yt = 0.; r->megno_var_t = 0.; r->megno_n = 0; r->megno_mean_Y = 0; r->megno_mean_t = 0; for (int i=0;i<N_var;i++){ struct reb_particle megno = { .m = r->particles[i].m, .x = reb_random_normal(1.), .y = reb_random_normal(1.), .z = reb_random_normal(1.), .vx = reb_random_normal(1.), .vy = reb_random_normal(1.), .vz = reb_random_normal(1.) }; double deltad = delta/sqrt(megno.x*megno.x + megno.y*megno.y + megno.z*megno.z + megno.vx*megno.vx + megno.vy*megno.vy + megno.vz*megno.vz); // rescale megno.x *= deltad; megno.y *= deltad; megno.z *= deltad; megno.vx *= deltad; megno.vy *= deltad; megno.vz *= deltad; reb_add(r, megno); } r->N_var = N_var; } double reb_tools_calculate_megno(struct reb_simulation* r){ // Returns the MEGNO <Y> if (r->t==0.) return 0.; return r->megno_Yss/r->t; } double reb_tools_calculate_lyapunov(struct reb_simulation* r){ // Returns the largest Lyapunov characteristic number (LCN), or maximal Lyapunov exponent if (r->t==0.) return 0.; return r->megno_cov_Yt/r->megno_var_t; } double reb_tools_megno_deltad_delta(struct reb_simulation* const r){ const struct reb_particle* restrict const particles = r->particles; const int N = r->N; const int N_var = r->N_var; double deltad = 0; double delta2 = 0; for (int i=N-N_var;i<N;i++){ deltad += particles[i].vx * particles[i].x; deltad += particles[i].vy * particles[i].y; deltad += particles[i].vz * particles[i].z; deltad += particles[i].ax * particles[i].vx; deltad += particles[i].ay * particles[i].vy; deltad += particles[i].az * particles[i].vz; delta2 += particles[i].x * particles[i].x; delta2 += particles[i].y * particles[i].y; delta2 += particles[i].z * particles[i].z; delta2 += particles[i].vx * particles[i].vx; delta2 += particles[i].vy * particles[i].vy; delta2 += particles[i].vz * particles[i].vz; } return deltad/delta2; } void reb_tools_megno_update(struct reb_simulation* r, double dY){ // Calculate running Y(t) r->megno_Ys += dY; double Y = r->megno_Ys/r->t; // Calculate averge <Y> r->megno_Yss += Y * r->dt; // Update covariance of (Y,t) and variance of t r->megno_n++; double _d_t = r->t - r->megno_mean_t; r->megno_mean_t += _d_t/(double)r->megno_n; double _d_Y = reb_tools_calculate_megno(r) - r->megno_mean_Y; r->megno_mean_Y += _d_Y/(double)r->megno_n; r->megno_cov_Yt += ((double)r->megno_n-1.)/(double)r->megno_n *(r->t-r->megno_mean_t) *(reb_tools_calculate_megno(r)-r->megno_mean_Y); r->megno_var_t += ((double)r->megno_n-1.)/(double)r->megno_n *(r->t-r->megno_mean_t) *(r->t-r->megno_mean_t); }