void problem_output(){ //conditions for entering loops int output_var=0; if(output_check(tmax/10000.)) output_var = 1; //Used to be 100,000 else if(t < tide_delay && output_check(100.)) output_var = 1; //used to be 100 int tide_go = 0; if(tides_on == 1 && tide_force == 0 && t > tide_delay) tide_go = 1; //**Main Loop** if(output_var == 1 || tide_go == 1){ //Calculate Orbital Elements struct particle com = particles[0]; double r_nrgy[N]; //calculating energy of particle double v2_nrgy[N]; double m_nrgy[N]; for(int i=1;i<N;i++){ struct particle* par = &(particles[i]); const double m = par->m; const double mu = G*(com.m + m); const double rp = par->r*0.00464913; //Rp from Solar Radii to AU, G=1, [t]=yr/2pi, [m]=m_star const double Qp = par->k2/(par->Q); const double dvx = par->vx-com.vx; const double dvy = par->vy-com.vy; const double dvz = par->vz-com.vz; const double dx = par->x-com.x; const double dy = par->y-com.y; const double dz = par->z-com.z; const double v = sqrt ( dvx*dvx + dvy*dvy + dvz*dvz ); const double r = sqrt ( dx*dx + dy*dy + dz*dz ); const double rinv = 1./r; //some extra terms to speed up code const double vr = (dx*dvx + dy*dvy + dz*dvz)*rinv; const double muinv = 1./mu; const double term1 = v*v-mu*rinv; const double term2 = r*vr; const double ex = muinv*( term1*dx - term2*dvx ); const double ey = muinv*( term1*dy - term2*dvy ); const double ez = muinv*( term1*dz - term2*dvz ); double e = sqrt( ex*ex + ey*ey + ez*ez ); // eccentricity // true anomaly + periapse (wiki, Fund. of Astrodyn. and App., by Vallado, 2007) const double rdote = dx*ex + dy*ey + dz*ez; double cosf = rdote/(e*r); if(cosf >= 1.) cosf = 1.; if(cosf <= -1.) cosf = -1.; double sinf = sqrt(1. - cosf*cosf); if(vr < 0.) sinf *= -1.; double sinwf = dy*rinv; double coswf = dx*rinv; double a = r*(1. + e*cosf)/(1. - e*e); double n; //Test for collision if(N < _N+1 && collision_print == 0){ printf("\n\n system %s with e_ini=%f,e_now=%f had a collision!! \n\n",Keplername,e_ini,e); FILE *append; append=fopen("python_scripts/Kepler_e_coll.txt", "a"); fprintf(append,"%s,%e,%e\n",Keplername,e_ini,t); fclose(append); collision_print = 1; } //Energy calculation - values may be updated via tides, but probably won't matter r_nrgy[i] = r; v2_nrgy[i] = v*v; m_nrgy[i] = m; //Tides if(tide_go == 1 && i<=planets_with_tides){ const double a2 = a*a; const double rp2 = rp*rp; const double R5a5 = rp2*rp2*rp/(a2*a2*a); const double GM3a3 = sqrt(G*com.m*com.m*com.m/(a2*a)); const double de = -dt*(9.*M_PI*0.5)*Qp*GM3a3*R5a5*e/m; //Tidal change for e const double da = 2.*a*e*de; //Tidal change for a a += da; e += de; integrator_whfast_particles_modified = 1; /* //Test repulsion vs. tugging (change w to put planets out of res) if(repuls_v_tugg_on == 0 && i==1 && p_suppress == 0){ repuls_v_tugg_on = 1; double angle_change = 0.34*(M_PI/180.); double costemp = coswf; double sintemp = sinwf; coswf = costemp*cos(angle_change) - sintemp*sin(angle_change); sinwf = sintemp*cos(angle_change) - costemp*sin(angle_change); printf("\n ***Testing Repulsion vs. tugging. Planets put out of resonance.*** \n"); }*/ //Re-update coords. const double r_new = a*(1. - e*e)/(1. + e*cosf); const double x_new = r_new*coswf + com.x; const double y_new = r_new*sinwf + com.y; n = sqrt(mu/(a*a*a)); const double term = n*a/sqrt(1.- e*e); const double rdot = term*e*sinf; const double rfdot = term*(1. + e*cosf); const double vx_new = rdot*coswf - rfdot*sinwf + com.vx; const double vy_new = rdot*sinwf + rfdot*coswf + com.vy; // ******NOTE NO VZ_NEW CURRENTLY. NEED THIS FOR PLANETESIMALS //Stop program if nan values being produced. if(x_new!=x_new || y_new!=y_new || vx_new!=vx_new ||vy_new!=vy_new){ printf("\n !!Failed run for: %s \n",Keplername); printf("cartesian before: dx=%f,dy=%f,dz=%f,ex=%f,ey=%f,ez=%f,r=%f,vx=%f,vy=%f,com.vx=%f,com.vy=%f,v=%f \n",dx,dy,dz,ex,ey,ez,r,par->vx,par->vy,com.vx,com.vy,v); printf("Orbital elements: mu=%f,e=%f,a=%f,cosf=%.15f,sinf=%.15f,dt=%f,de=%f,da=%f,GM3a3=%f,R5a5=%f \n",mu,e,a,cosf,sinf,dt,de,da,GM3a3,R5a5); printf("\n cartesian after: x_new=%f,y_new=%f,vx_new=%f,vy_new=%f,term=%f,rdot=%f,rfdot=%f \n",x_new,y_new,vx_new,vy_new,term,rdot,rfdot); exit(0); } par->x = x_new; par->y = y_new; par->vx = vx_new; par->vy = vy_new; com = tools_get_center_of_mass(com,particles[i]); //print message if(tide_print == 0 && p_suppress == 0){ printf("\n\n ***Tides (a', e') have just been turned on at t=%f years***\n\n",t); tide_print = 1; } } else { n = sqrt(mu/(a*a*a)); //Still need to calc this for period. } if(output_var == 1){ omega[i] = atan2(ey,ex); if(ey < 0.) omega[i] += 2*M_PI; double cosE = (a - r)/(a*e); double E; if(cosf > 1. || cosf < -1.){ E = M_PI - M_PI*cosE; } else { E = acos(cosE); } if(vr < 0.) E = 2.*M_PI - E; double MA = E - e*sin(E); lambda[i] = MA + omega[i]; double phi = 0., phi2 = 0., phi3 = 0.; //resonant angles if(i>1){//tailored for 2:1 resonance, between inner/outer planet phi = 2.*lambda[i] - lambda[i-phi_i[i]] - omega[i-phi_i[i]]; phi2 = 2.*lambda[i] - lambda[i-phi_i[i]] - omega[i]; phi3 = omega[i-phi_i[i]] - omega[i]; } while(phi >= 2*M_PI) phi -= 2*M_PI; while(phi < 0.) phi += 2*M_PI; while(phi2 >= 2*M_PI) phi2 -= 2*M_PI; while(phi2 < 0.) phi2 += 2*M_PI; while(phi3 >= 2*M_PI) phi3 -= 2*M_PI; while(phi3 < 0.) phi3 += 2*M_PI; //Calculate total Energy and ang. mom. of the system double Etot = 0; double L = 0; if(i==N-1){//Total energy, wait till array values are filled. for(int j=1;j<N;j++){ Etot += 0.5*m*v2_nrgy[j]; //kinetic Etot -= com.m*m/r_nrgy[j]; //star-planet potential for(int k=1;k<j;k++) Etot -= m_nrgy[k]*m_nrgy[j]/(r_nrgy[k] - r_nrgy[j]); //interaction potential } } L = sqrt(G*com.m*a*(1-e*e)); //integrator_synchronize(); //if synchronize_manual = 1, then call this before each output to synchronize x and vx. //output orbits in txt_file. FILE *append; append=fopen(txt_file, "a"); //output order = time(yr/2pi),a(AU),e,P(days),arg. of peri., mean anomaly, // eccentric anomaly, mean longitude, resonant angle, de/dt, phi1 phi2 phi3 fprintf(append,"%e\t%.10e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\n",t,a,e,365./n,omega[i],MA,E,lambda[i],phi,phi2,phi3,L,Etot); fclose(append); if (integrator != WH){ // The WH integrator assumes a heliocentric coordinate system. tools_move_to_center_of_momentum(); } } } } if(output_check(10000.*dt)){ output_timing(); } }
void display(){ if (display_pause) return; #ifdef TREE if (display_tree){ tree_update(); #ifdef GRAVITY_TREE tree_update_gravity_data(); #endif } #endif if (display_clear){ glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } if (!display_wire) { if (display_spheres){ glDisable(GL_BLEND); glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); GLfloat lightpos[] = {0, boxsize_max, boxsize_max, 0.f}; glLightfv(GL_LIGHT0, GL_POSITION, lightpos); }else{ glEnable(GL_BLEND); glDepthMask(GL_FALSE); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glDisable(GL_LIGHT0); } } glEnable(GL_POINT_SMOOTH); glVertexPointer(3, GL_DOUBLE, sizeof(struct particle), particles); int _N_active = (N_active==-1)?N:N_active; if (display_reference>=0){ glTranslatef(-particles[display_reference].x,-particles[display_reference].y,-particles[display_reference].z); } glRotatef(display_rotate_x,1,0,0); glRotatef(display_rotate_z,0,0,1); for (int i=-display_ghostboxes*nghostx;i<=display_ghostboxes*nghostx;i++){ for (int j=-display_ghostboxes*nghosty;j<=display_ghostboxes*nghosty;j++){ for (int k=-display_ghostboxes*nghostz;k<=display_ghostboxes*nghostz;k++){ struct ghostbox gb = boundaries_get_ghostbox(i,j,k); glTranslatef(gb.shiftx,gb.shifty,gb.shiftz); if (!(!display_clear&&display_wire)){ if (display_spheres){ // Drawing Spheres glColor4f(1.0,1.0,1.0,1.0); #ifndef COLLISIONS_NONE for (int i=0;i<N;i++){ struct particle p = particles[i]; glTranslatef(p.x,p.y,p.z); glScalef(p.r,p.r,p.r); #ifdef _APPLE glCallList(display_dlist_sphere); #else //_APPLE glutSolidSphere(1,40,10); #endif //_APPLE glScalef(1./p.r,1./p.r,1./p.r); glTranslatef(-p.x,-p.y,-p.z); } #endif // COLLISIONS_NONE }else{ // Drawing Points glEnableClientState(GL_VERTEX_ARRAY); glPointSize(3.); glColor4f(1.0,1.0,1.0,0.5); glDrawArrays(GL_POINTS, _N_active, N-_N_active); glColor4f(1.0,1.0,0.0,0.9); glPointSize(5.); glDrawArrays(GL_POINTS, 0, _N_active); glDisableClientState(GL_VERTEX_ARRAY); } } // Drawing wires if (display_wire){ #ifndef INTEGRATOR_SEI double radius = 0; struct particle com = particles[0]; for (int i=1;i<N;i++){ struct particle p = particles[i]; if (N_active>0){ // Different colors for active/test particles if (i>=N_active){ glColor4f(0.9,1.0,0.9,0.9); }else{ glColor4f(1.0,0.9,0.0,0.9); } }else{ // Alternating colors if (i%2 == 1){ glColor4f(0.0,1.0,0.0,0.9); }else{ glColor4f(0.0,0.0,1.0,0.9); } } struct orbit o = tools_p2orbit(p,com); glPushMatrix(); glTranslatef(com.x,com.y,com.z); glRotatef(o.Omega/DEG2RAD,0,0,1); glRotatef(o.inc/DEG2RAD,1,0,0); glRotatef(o.omega/DEG2RAD,0,0,1); glBegin(GL_LINE_LOOP); for (double trueAnom=0; trueAnom < 2.*M_PI; trueAnom+=M_PI/100.) { //convert degrees into radians radius = o.a * (1. - o.e*o.e) / (1. + o.e*cos(trueAnom)); glVertex3f(radius*cos(trueAnom),radius*sin(trueAnom),0); } glEnd(); glPopMatrix(); com = tools_get_center_of_mass(p,com); } #else // INTEGRATOR_SEI for (int i=1;i<N;i++){ struct particle p = particles[i]; glBegin(GL_LINE_LOOP); for (double _t=-100.*dt;_t<=100.*dt;_t+=20.*dt){ double frac = 1.-fabs(_t/(120.*dt)); glColor4f(1.0,(_t+100.*dt)/(200.*dt),0.0,frac); glVertex3f(p.x+p.vx*_t, p.y+p.vy*_t, p.z+p.vz*_t); } glEnd(); } #endif // INTEGRATOR_SEI } // Drawing Tree glColor4f(1.0,0.0,0.0,0.4); #ifdef TREE if (display_tree){ glColor4f(1.0,0.0,0.0,0.4); display_entire_tree(); } #endif // TREE glTranslatef(-gb.shiftx,-gb.shifty,-gb.shiftz); } } } glColor4f(1.0,0.0,0.0,0.4); glScalef(boxsize_x,boxsize_y,boxsize_z); glutWireCube(1); glScalef(1./boxsize_x,1./boxsize_y,1./boxsize_z); glRotatef(-display_rotate_z,0,0,1); glRotatef(-display_rotate_x,1,0,0); if (display_reference>=0){ glTranslatef(particles[display_reference].x,particles[display_reference].y,particles[display_reference].z); } glutSwapBuffers(); }
void problem_migration_forces(){ if(mig_forces==1){ int print = 1; struct particle com = particles[0]; // calculate migration forces with respect to center of mass; for(int i=1;i<N;i++){ // N = _N + 1 = total number of planets + star double t_migend = t_mig[i] + t_damp[i]; //when migration ends if (t > t_mig[i] && t < t_migend) { //ramp down the migration force (by increasing the migration timescale) tau_a[i] *= expf(dt/expmigfac[i]); tau_e[i] = tau_a[i]/K; } else if(t > t_migend){ tau_a[i]=0.; tau_e[i]=0.; double sum = 0; for(int j=0;j<N;j++) sum += tau_a[j]; if(sum < 0.1){ mig_forces = 0; //turn migration loop off altogether, save calcs if(p_suppress == 0 && print == 1) printf("\n\n **migration loop off at t=%f** \n\n",t); print = 0; } } if (tau_e[i]!=0||tau_a[i]!=0){ struct particle* p = &(particles[i]); const double dvx = p->vx-com.vx; const double dvy = p->vy-com.vy; const double dvz = p->vz-com.vz; if (tau_a[i]!=0){ // Migration double const term = 1/(2.*tau_a[i]); p->ax -= dvx*term; p->ay -= dvy*term; p->az -= dvz*term; } if (tau_e[i]!=0){ // Eccentricity damping const double mu = G*(com.m + p->m); const double dx = p->x-com.x; const double dy = p->y-com.y; const double dz = p->z-com.z; const double hx = dy*dvz - dz*dvy; const double hy = dz*dvx - dx*dvz; const double hz = dx*dvy - dy*dvx; const double h = sqrt ( hx*hx + hy*hy + hz*hz ); const double v = sqrt ( dvx*dvx + dvy*dvy + dvz*dvz ); const double r = sqrt ( dx*dx + dy*dy + dz*dz ); const double vr = (dx*dvx + dy*dvy + dz*dvz)/r; const double ex = 1./mu*( (v*v-mu/r)*dx - r*vr*dvx ); const double ey = 1./mu*( (v*v-mu/r)*dy - r*vr*dvy ); const double ez = 1./mu*( (v*v-mu/r)*dz - r*vr*dvz ); const double e = sqrt( ex*ex + ey*ey + ez*ez ); // eccentricity const double a = -mu/( v*v - 2.*mu/r ); // semi major axis, AU //TESTP5m*********************** to get them all starting off in line together /** //if(a < 0.091432 && t > 500 && i==2){ if(a < 0.078 && t > 500 && i==2){ mig_forces = 0; if(p_suppress == 0) printf("\n\n **migration loop off (abrupt) at t=%f** \n\n",t); } **/ const double prefac1 = 1./(1.-e*e) /tau_e[i]/1.5; const double prefac2 = 1./(r*h) * sqrt(mu/a/(1.-e*e)) /tau_e[i]/1.5; p->ax += -dvx*prefac1 + (hy*dz-hz*dy)*prefac2; p->ay += -dvy*prefac1 + (hz*dx-hx*dz)*prefac2; p->az += -dvz*prefac1 + (hx*dy-hy*dx)*prefac2; } } com = tools_get_center_of_mass(com,particles[i]); } } //This calculates the tau_e for tides as forces, now that we have the resonance eccentricities if(tautide_force_calc == 0 && mig_forces == 0. && tide_force == 1 && tides_on == 1){ tautide_force_calc = 1; //only do this process once struct particle com = particles[0]; for(int i=1;i<N;i++){ struct particle* par = &(particles[i]); const double m = par->m; const double mu = G*(com.m + m); const double rp = par->r*0.00464913; //Rp from Solar Radii to AU const double Qp = par->k2/(par->Q); const double dvx = par->vx-com.vx; const double dvy = par->vy-com.vy; const double dvz = par->vz-com.vz; const double dx = par->x-com.x; const double dy = par->y-com.y; const double dz = par->z-com.z; const double v = sqrt ( dvx*dvx + dvy*dvy + dvz*dvz ); const double r = sqrt ( dx*dx + dy*dy + dz*dz ); const double vr = (dx*dvx + dy*dvy + dz*dvz)/r; const double ex = 1./mu*( (v*v-mu/r)*dx - r*vr*dvx ); const double ey = 1./mu*( (v*v-mu/r)*dy - r*vr*dvy ); const double ez = 1./mu*( (v*v-mu/r)*dz - r*vr*dvz ); const double e = sqrt( ex*ex + ey*ey + ez*ez ); // eccentricity const double a = -mu/( v*v - 2.*mu/r ); // semi major axis, AU double a5r5 = pow(a/rp, 5); tidetauinv_e[i] = 1.0/(2./(9*M_PI)*(1./Qp)*sqrt(a*a*a/com.m/com.m/com.m)*a5r5*m); //tidetau_a[i] = tidetau_e[i]*K; //Dan uses a K factor instead. if(p_suppress == 0) printf("planet %i: tau_e,=%.1f Myr, a=%f,e=%f \n",i,1.0/(tidetauinv_e[i]*1e6),a,e); } } if(tides_on == 1 && tide_force == 1 && t > tide_delay){ struct particle com = particles[0]; // calculate add. forces w.r.t. center of mass for(int i=1;i<N;i++){ struct particle* p = &(particles[i]); const double dvx = p->vx - com.vx; const double dvy = p->vy - com.vy; const double dvz = p->vz - com.vz; //if(i==1){ /*Papaloizou & Larwood (2000) - Unlike the orbital elements version of tides, tidetau_e already induces an a' (Gold&Schlich2015), and so the tidetau_a is an additional migration on top... don't think I need it. */ /* if (tidetau_a[i] != 0.){ p->ax += -dvx/(2.*tidetau_a[i]); p->ay += -dvy/(2.*tidetau_a[i]); p->az += -dvz/(2.*tidetau_a[i]); } */ //Papaloizou & Larwood (2000) if (tidetauinv_e[i] != 0. ){ // need h and e vectors for both types const double dx = p->x-com.x; const double dy = p->y-com.y; const double dz = p->z-com.z; const double rinv = 1/sqrt ( dx*dx + dy*dy + dz*dz ); const double vr = (dx*dvx + dy*dvy + dz*dvz)*rinv; const double term = -2.*tidetauinv_e[i]*vr*rinv; p->ax += term*dx; p->ay += term*dy; p->az += term*dz; } com = tools_get_center_of_mass(com,particles[i]); //} } //print message if(tide_print == 0 && p_suppress == 0){ printf("\n\n ***Tides (forces!) have just been turned on at t=%f years***\n\n",t); tide_print = 1; } } }