Exemplo n.º 1
0
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();
	}
}
Exemplo n.º 2
0
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();
}
Exemplo n.º 3
0
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;
        }
    }
}