void reset_vel(PARAMS *p,double f,SSDATA *d) { VECTOR r_hat,vr_vec,t_hat,vt_vec; double v,vr,vt; /* set speed scaled by desired virial fraction */ SCALE_VEC(d->vel,sqrt(f)); /* adjust radial and tangential components as desired */ if (p->radf < 0) return; COPY_VEC(d->pos,r_hat); NORM_VEC(r_hat,MAG(r_hat)); /* radial unit vector */ vr = DOT(d->vel,r_hat); COPY_VEC(r_hat,vr_vec); SCALE_VEC(vr_vec,vr); /* current radial component of vel */ SUB_VEC(d->vel,vr_vec,t_hat); NORM_VEC(t_hat,MAG(t_hat)); /* tangential unit vector */ v = MAG(d->vel); vr = sqrt(p->radf)*v; vt = sqrt(1 - p->radf)*v; COPY_VEC(r_hat,vr_vec); SCALE_VEC(vr_vec,vr); /* new radial component */ COPY_VEC(t_hat,vt_vec); SCALE_VEC(vt_vec,vt); /* new tangential component */ ADD_VEC(vr_vec,vt_vec,d->vel); }
static void adj_com_vel(SSDATA *d,int n,PROPERTIES *p,VECTOR v) { int i; for (i=0;i<n;i++) { SUB_VEC(d[i].vel,p->com_vel,d[i].vel); ADD_VEC(d[i].vel,v,d[i].vel); } }
static void adj_com_pos(SSDATA *d,int n,PROPERTIES *p,VECTOR v) { int i; for (i=0;i<n;i++) { SUB_VEC(d[i].pos,p->com_pos,d[i].pos); ADD_VEC(d[i].pos,v,d[i].pos); } }
void MakeBasis(VECTOR v1, VECTOR v2, VECTOR v3) { /* * Uses the Gram-Schmidt process to convert the spanning set v1, v2, v3 * into an orthonormal basis set. * */ VECTOR n, v; double proj; /* Construct first basis vector */ NORM_VEC(v1, MAG(v1)); /* Construct second basis vector */ COPY_VEC(v1, n); proj = DOT(v2, n); SCALE_VEC(n, proj); SUB_VEC(v2, n, v2); NORM_VEC(v2, MAG(v2)); /* Construct third basis vector */ COPY_VEC(v3, v); COPY_VEC(v2, n); proj = DOT(v, n); SCALE_VEC(n, proj); SUB_VEC(v3, n, v3); COPY_VEC(v1, n); proj = DOT(v, n); SCALE_VEC(n, proj); SUB_VEC(v3, n, v3); NORM_VEC(v3, MAG(v3)); }
static void scale_vel_dsp(SSDATA *d,int n,PROPERTIES *p,VECTOR v) { int i,k; for (i=0;i<n;i++) { SUB_VEC(d[i].vel,p->com_vel,d[i].vel); for (k=0;k<N_DIM;k++) d[i].vel[k] *= v[k]; } for (i=0;i<n;i++) { ADD_VEC(d[i].vel,p->com_vel,d[i].vel); } }
static void adj_ang_mom(SSDATA *d,int n,PROPERTIES *p,VECTOR v) { VECTOR u,w; int i; invert(p->inertia); SUB_VEC(v,p->ang_mom,v); Transform(p->inertia,v,u); SCALE_VEC(u,p->total_mass); for (i=0;i<n;i++) { CROSS(u,d[i].pos,w); ADD_VEC(d[i].vel,w,d[i].vel); } }
/* invariant: no sharing between returned term and *any* arguments. the caller must free the result. */ term* substitute(variable* from, term* to, term* haystack) { if (haystack == NULL) return NULL; check(from != NULL && to != NULL, "substitute requires non-NULL arguments"); check(term_locally_well_formed(to), "substitute requires %W to be locally well-formed", to, print_term); check(term_locally_well_formed(haystack),"substitute requires %W to be locally well-formed", haystack, print_term); switch(haystack->tag) { case VAR: if (variable_equal(from, haystack->var)) { return term_dup(to); } else { return term_dup(haystack); } case HOLE: return term_dup(haystack); case LAM: if (variable_equal(from, haystack->var)) { return make_lambda(variable_dup(haystack->var), substitute(from, to, haystack->left), term_dup(haystack->right)); } else { if (is_free(haystack->var, to)) { variable *g = gensym(haystack->var->name); term *tg = make_var(g); term* new_haystack = make_lambda(variable_dup(g), term_dup(haystack->left), substitute(haystack->var, tg, haystack->right)); free_term(tg); term* ans = substitute(from, to, new_haystack); free_term(new_haystack); return ans; } return make_lambda(variable_dup(haystack->var), substitute(from, to, haystack->left), substitute(from, to, haystack->right)); } case PI: if (variable_equal(from, haystack->var)) { return make_pi(variable_dup(haystack->var), substitute(from, to, haystack->left), term_dup(haystack->right)); } else { if (is_free(haystack->var, to)) { variable *g = gensym(haystack->var->name); term *tg = make_var(g); term* new_haystack = make_pi(variable_dup(g), term_dup(haystack->left), substitute(haystack->var, tg, haystack->right)); free_term(tg); term* ans = substitute(from, to, new_haystack); free_term(new_haystack); return ans; } return make_pi(variable_dup(haystack->var), substitute(from, to, haystack->left), substitute(from, to, haystack->right)); } case APP: return make_app(substitute(from, to, haystack->left), substitute(from, to, haystack->right)); case TYPE: return term_dup(haystack); case DATATYPE: { term* ans = make_datatype_term(variable_dup(haystack->var), haystack->num_params, haystack->num_indices); #define SUB_VEC(dst, src, n) do { \ int __i; \ for (__i = 0; __i < n; __i++) { \ dst[__i] = substitute(from, to, src[__i]); \ } \ } while(0) SUB_VEC(ans->params, haystack->params, haystack->num_params); SUB_VEC(ans->indices, haystack->indices, haystack->num_indices); return ans; } case INTRO: { term* ans = make_intro(variable_dup(haystack->var), substitute(from, to, haystack->left), haystack->num_args, haystack->num_params, haystack->num_indices); SUB_VEC(ans->args, haystack->args, haystack->num_args); SUB_VEC(ans->params, haystack->params, haystack->num_params); SUB_VEC(ans->indices, haystack->indices, haystack->num_indices); return ans; } case ELIM: { term* ans = make_elim(variable_dup(haystack->var), haystack->num_args, haystack->num_params, haystack->num_indices); SUB_VEC(ans->args, haystack->args, haystack->num_args); SUB_VEC(ans->params, haystack->params, haystack->num_params); SUB_VEC(ans->indices, haystack->indices, haystack->num_indices); return ans; } case IMPLICIT: return term_dup(haystack); default: sentinel("malformed term with tag %d", haystack->tag); } error: return NULL; }
static void show_encounter(RUBBLE_PILE *rp,int n,BOOLEAN sim_units) { VECTOR rel_pos,rel_vel,ang_mom; double m,sr,r,v,eb,a,e,q,Q,vq,vQ; assert(n == 2); m = rp[0].mass + rp[1].mass; sr = rp[0].radius + rp[1].radius; SUB_VEC(rp[1].pos,rp[0].pos,rel_pos); SUB_VEC(rp[1].vel,rp[0].vel,rel_vel); CROSS(rel_pos,rel_vel,ang_mom); r = MAG(rel_pos); v = MAG(rel_vel); if (r == 0) eb = 0; else eb = 0.5*SQ(v) - m/r; if (eb == 0) { a = 0; e = 1; } else { a = -0.5*m/eb; e = sqrt(1 - MAG_SQ(ang_mom)/(a*m)); } q = (1 - e)*a; Q = (1 + e)*a; (void) printf("2-body encounter parameters:\n"); (void) printf("Binding energy per unit reduced mass = %g sim units\n",eb); (void) printf("Semi-major axis a = "); if (sim_units) (void) printf("%g AU",a); else (void) printf("%g km",a*0.001*L_SCALE); (void) printf("\n"); (void) printf("Eccentricity e = %g\n",e); (void) printf("Close-approach distance q = "); if (sim_units) (void) printf("%g AU",q); else (void) printf("%g km",q*0.001*L_SCALE); if (q <= sr) (void) printf(" (impact possible)"); (void) printf("\n"); (void) printf("Initial relative speed v = "); if (sim_units) (void) printf("%g x 30 km/s",v); else (void) printf("%g m/s",v*V_SCALE); (void) printf("\n"); (void) printf("Relative speed at "); if (eb < 0) { vQ = sqrt(2*(eb + m/Q)); (void) printf("apoapse vQ = "); } else { vQ = sqrt(2*eb); (void) printf("infinity v_inf = "); } if (sim_units) (void) printf("%g x 30 km/s",vQ); else (void) printf("%g m/s",vQ*V_SCALE); (void) printf("\n"); (void) printf("Relative speed at "); if (q <= sr) { if (r > sr) q = sr; (void) printf("impact (approx)"); } else (void) printf("periapse"); (void) printf(" vq = "); if (q < sr) vq = v; else vq = sqrt(2*(eb + m/q)); if (sim_units) (void) printf("%g x 30 km/s",vq); else (void) printf("%g m/s",vq*V_SCALE); (void) printf("\n"); (void) printf("Relative orb. ang. mom. per unit reduced mass h = " "(%g,%g,%g) sim units\n",ang_mom[X],ang_mom[Y],ang_mom[Z]); }
int main(int argc,char *argv[]) { FILE *fp; BOOLEAN sim_units; RUBBLE_PILE rp[MAX_NUM_FILES],*p; char infile[MAXPATHLEN],last_infile[MAXPATHLEN],outfile[MAXPATHLEN]; double time = 0.0,old_time = 0.0; int n_files; setbuf(stdout,(char *)NULL); srand(getpid()); if (argc > 1) { (void) fprintf(stderr,"%s takes no arguments\n",argv[0]); return 1; } fp = fopen(LOG_FILE,"r"); if (fp) { (void) fclose(fp); if (!get_yn("Overwrite log file","y")) return 0; } fp = fopen(LOG_FILE,"w"); if (!fp) { (void) fprintf(stderr,"Unable to open %s for writing\n",LOG_FILE); return 1; } sim_units = get_yn("Use simulation units (AU, M_sun, etc.)","n"); n_files = 0; while (n_files < MAX_NUM_FILES) { infile[0] = '\0'; (void) printf("File %i [or RETURN to quit]: ",n_files + 1); (void) fgets(infile,MAXPATHLEN,stdin); assert(strlen(infile)); infile[strlen(infile) - 1] = '\0'; /* get rid of newline at end */ if (!strlen(infile)) break; p = &rp[n_files]; if (process(infile,p,sim_units,&time)) continue; if (n_files == 0) old_time = time; else if (time != old_time) time = 0.0; /* unless all times are the same, set to zero */ (void) fprintf(fp, "File number\t\t%i\n" "Filename\t\t%s\n" "Mass\t\t\t%e\n" "Bulk radius\t\t%e\n" "Bulk density\t\t%e\n" "Position\t\t%+e\t%+e\t%+e\n" "Velocity\t\t%+e\t%+e\t%+e\n" "Spin\t\t\t%+e\t%+e\t%+e\n" "Major axis\t\t%+f\t%+f\t%+f\n" "Inter axis\t\t%+f\t%+f\t%+f\n" "Minor axis\t\t%+f\t%+f\t%+f\n" "Color\t\t\t%i\n" "Aggregate ID\t\t%i\n\n", n_files,infile,p->mass,p->radius,p->density, p->pos[X],p->pos[Y],p->pos[Z], p->vel[X],p->vel[Y],p->vel[Z], p->spin[X],p->spin[Y],p->spin[Z], p->axes[rp->axis_ord[X]][X], p->axes[rp->axis_ord[X]][Y], p->axes[rp->axis_ord[X]][Z], p->axes[rp->axis_ord[Y]][X], p->axes[rp->axis_ord[Y]][Y], p->axes[rp->axis_ord[Y]][Z], p->axes[rp->axis_ord[Z]][X], p->axes[rp->axis_ord[Z]][Y], p->axes[rp->axis_ord[Z]][Z], p->color,p->agg_id); (void) strcpy(last_infile,infile); if (++n_files == MAX_NUM_FILES) (void) printf("File limit reached\n"); } if (n_files == 0) { (void) fprintf(stderr,"No files specified!\n"); return 1; } if (get_yn("Recenter barycentric position and velocity","y")) { VECTOR pos,vel,r,v; double total_mass; int i; total_mass = 0; ZERO_VEC(pos); ZERO_VEC(vel); for (i=0;i<n_files;i++) { COPY_VEC(rp[i].pos,r); SCALE_VEC(rp[i].pos,-1); rpuApplyPos(&rp[i]); SCALE_VEC(r,rp[i].mass); ADD_VEC(pos,r,pos); COPY_VEC(rp[i].vel,v); SCALE_VEC(rp[i].vel,-1); rpuApplyVel(&rp[i]); SCALE_VEC(v,rp[i].mass); ADD_VEC(vel,v,vel); total_mass += rp[i].mass; } NORM_VEC(pos,total_mass); NORM_VEC(vel,total_mass); for (i=0;i<n_files;i++) { SCALE_VEC(rp[i].pos,-1); SUB_VEC(rp[i].pos,pos,rp[i].pos); rpuApplyPos(&rp[i]); SCALE_VEC(rp[i].vel,-1); SUB_VEC(rp[i].vel,vel,rp[i].vel); rpuApplyVel(&rp[i]); } (void) fprintf(fp,"BARYCENTRIC CORRECTION APPLIED\n"); } (void) fclose(fp); if (n_files == 2) show_encounter(rp,n_files,sim_units); do { (void) printf("Output file [default %s]: ",last_infile); (void) fgets(outfile,MAXPATHLEN,stdin); assert(strlen(outfile)); outfile[strlen(outfile) - 1] = '\0'; if (!strlen(outfile)) (void) strcpy(outfile,last_infile); outfile[MAXPATHLEN - 1] = '\0'; if ((fp = fopen(outfile,"r"))) { (void) fclose(fp); if (!get_yn("Output file already exists...overwrite","n")) continue; } break; } while (/*CONSTCOND*/1); write_data(outfile,rp,n_files,time); for (--n_files;n_files>=0;n_files--) rpuFree(&rp[n_files]); (void) printf("Done!\n"); return 0; }
static void ss_analyze(SSDATA *data,int n_data,PROPERTIES *p) { SSDATA *d; VECTOR r,v,l; int i,k,nc[NUM_COLORS],ncmax; assert(n_data > 0); p->total_mass = 0; ZERO_VEC(p->bnd_min); ZERO_VEC(p->bnd_max); ZERO_VEC(p->com_pos); ZERO_VEC(p->com_vel); ZERO_VEC(p->ang_mom); ZERO_VEC(p->vel_dsp); p->color = 0; for (i=0;i<NUM_COLORS;i++) nc[i] = 0; for (i=0;i<n_data;i++) { d = &data[i]; p->total_mass += d->mass; COPY_VEC(d->pos,r); COPY_VEC(d->vel,v); if (i==0) { COPY_VEC(r,p->bnd_min); COPY_VEC(r,p->bnd_max); } else for (k=0;k<N_DIM;k++) { if (r[k] < p->bnd_min[k]) p->bnd_min[k] = r[k]; if (r[k] > p->bnd_max[k]) p->bnd_max[k] = r[k]; } SCALE_VEC(r,d->mass); ADD_VEC(p->com_pos,r,p->com_pos); SCALE_VEC(v,d->mass); ADD_VEC(p->com_vel,v,p->com_vel); CROSS(d->pos,d->vel,l); SCALE_VEC(l,d->mass); ADD_VEC(p->ang_mom,l,p->ang_mom); ++nc[(int) d->color]; } if (p->total_mass == 0) { (void) printf("WARNING: total mass = 0...will divide by N\n"); p->total_mass = n_data; } NORM_VEC(p->com_pos,p->total_mass); NORM_VEC(p->com_vel,p->total_mass); NORM_VEC(p->ang_mom,p->total_mass); for (i=0;i<n_data;i++) { d = &data[i]; SUB_VEC(d->vel,p->com_vel,v); for (k=0;k<N_DIM;k++) p->vel_dsp[k] += d->mass*SQ(v[k]); } for (k=0;k<N_DIM;k++) p->vel_dsp[k] = sqrt(p->vel_dsp[k]/p->total_mass); ncmax = 0; for (i=0;i<NUM_COLORS;i++) if (nc[i] > ncmax) { p->color = i; ncmax = nc[i]; } calc_inertia(data,n_data,p->inertia); }