bool read_output_file(defaultEnsemble& ens, config& cfg){ if(cfg.valid("output") ) { INFO_OUTPUT(1, "Loading from binary file " << cfg["output"]); ens = swarm::snapshot::load(cfg["output"]); INFO_OUTPUT(1,", time = " << ens.time_ranges() << endl); return true; }else if(cfg.valid("text_output")) { INFO_OUTPUT(1, "Loading from text file " << cfg["text_output"]); ens = swarm::snapshot::load_text(cfg["text_output"]); INFO_OUTPUT(1,", time = " << ens.time_ranges() << endl); return true; }else return false; }
void prepare_integrator () { // Initialize Integrator DEBUG_OUTPUT(2, "Initializing integrator" ); double begin_time = initial_ens.time_ranges().average; double destination_time = cfg.optional("destination_time", begin_time + 10 * M_PI ); integ = integrator::create(cfg); integ->set_ensemble(current_ens); integ->set_destination_time ( destination_time ); SYNC; }
/** * ***************TODO*********** */ void replace_disabled_systems( defaultEnsemble& ens ) { int nsys = ens.nsys(); // Replace the systems that have been disabled for(int i = 0; i < nsys; i++) { if( ens[i].is_disabled() ) { generate_initial_conditions_for_system(cfg,ens,i,maxsysid+1); } } }
bool needs_shrinking( const defaultEnsemble& ens ) { // This is the ratio we use when we are shrinking // if the ratio of active ones to all is less // than this number then we trim the fat const double critical_ratio = 0.75; int count_disabled = number_of_disabled_systems( ens ) ; double ratio = double(count_disabled) / double( ens.nsys() ); return ratio > critical_ratio; }
/** * This is a very crucial part of the Monte Carlo simulation * We remove the disabled ones and make a smaller ensemble. * We don't really need to make another ensemble. But keeping * the same ensemble is a lot of trouble. * */ defaultEnsemble trim_disabled_systems( const defaultEnsemble& ens ) { int nsys = ens.nsys(); int active_nsys = nsys - number_of_disabled_systems( ens ) ; // WARNING: Needed to add this to prevent segfaults. TODO: Figure out why. if(active_nsys==0) return ens; int nbod = ens.nbod(); defaultEnsemble active_ens = defaultEnsemble::create( nbod, active_nsys ); // Copy the active ones to the new ensemble for(int i = 0, j = 0; (i < nsys) && (j < active_nsys); i++) { if( !ens[i].is_disabled() ) { ens[i].copyTo( active_ens[j] ); j++; } } return active_ens; }
void benchmark_item(const string& param, const string& value) { //outputConfigSummary(std::cout,cfg); if(!validate_configuration(cfg) ) ERROR( "Invalid configuration" ); if(param == "input" || param == "nsys" || param == "nbod" || cfg.count("reinitialize")) load_generate_ensemble(); DEBUG_OUTPUT(2, "Make a copy of ensemble for energy conservation test" ); current_ens = initial_ens.clone(); double init_time = watch_time( prepare_integrator ); double integration_time = watch_time( generic_integrate ); double max_deltaE = find_max_energy_conservation_error(current_ens, initial_ens ); // Compare with reneference ensemble for integrator verification double pos_diff = 0, vel_diff = 0, time_diff = 0; bool comparison = compare_ensembles( current_ens, reference_ens , pos_diff, vel_diff, time_diff ); /// CSV output for use in spreadsheet software std::cout << param << ", " << value << ", " << current_ens.time_ranges() << ", " << max_deltaE << ", " << pos_diff << ", " << vel_diff << ", " << time_diff << ", " << integration_time << ", " << init_time << std::endl; if( !comparison || pos_diff > pos_threshold || vel_diff > vel_threshold || time_diff > time_threshold ){ fail_verify(); } }
void run_integration(){ if(!validate_configuration(cfg) ) ERROR( "Invalid configuration" ); load_generate_ensemble(); DEBUG_OUTPUT(2, "Make a copy of ensemble for energy conservation test" ); current_ens = initial_ens.clone(); prepare_integrator(); double integration_time = watch_time ( cfg.valid("interval") ? stability_test : generic_integrate ); save_ensemble(); INFO_OUTPUT( 1, "Integration time: " << integration_time << " ms " << std::endl); }
void write_stable_systems(defaultEnsemble &ens, defaultEnsemble &ens_init) { // find the stable ones and output the initial conditions for the stable // ones in keplerian coordinates // std::cerr << "# Finding stable system ids\n"; std::vector<unsigned int> stable_system_indices, unstable_system_indices; for(int i = 0; i < ens.nsys() ; i++ ) { if(ens[i].is_disabled()) unstable_system_indices.push_back(i); else stable_system_indices.push_back(i); } // std::cerr << "# Writing stable system ids\n"; if(cfg.count("stable_init_output")) { ofstream stable_init_output( cfg.optional("stable_init_output", string("stable_init_output.txt")).c_str() ); print_selected_systems(ens_init,stable_system_indices, stable_init_output); } if(cfg.count("stable_final_output")) { ofstream stable_final_output( cfg.optional("stable_final_output", string("stable_final_output.txt")).c_str() ); print_selected_systems(ens,stable_system_indices, stable_final_output); } if(cfg.count("unstable_init_output")) { ofstream unstable_init_output( cfg.optional("unstable_init_output", string("unstable_init_output.txt")).c_str() ); print_selected_systems(ens_init,unstable_system_indices, unstable_init_output); } if(cfg.count("unstable_final_output")) { ofstream unstable_final_output( cfg.optional("unstable_final_output", string("unstable_final_output.txt")).c_str() ); print_selected_systems(ens,unstable_system_indices, unstable_final_output); } }
void output_test() { if(!validate_configuration(cfg) ) ERROR( "Invalid configuration" ); if(!read_input_file(initial_ens, cfg) ) { ERROR("you should have a tested input file"); } DEBUG_OUTPUT(2, "Make a copy of ensemble for energy conservation test" ); current_ens = initial_ens.clone(); prepare_integrator(); double integration_time = watch_time ( cfg.valid("interval") ? stability_test : generic_integrate ); if(read_output_file(reference_ens,cfg)){ // Compare with reneference ensemble for integrator verification double pos_diff = 0, vel_diff = 0, time_diff = 0; bool comparison = compare_ensembles( current_ens, reference_ens , pos_diff, vel_diff, time_diff ); INFO_OUTPUT(1,"\tPosition difference: " << pos_diff << endl << "\tVelocity difference: " << vel_diff << endl << "\tTime difference: " << time_diff << endl ); if( !comparison || pos_diff > pos_threshold || vel_diff > vel_threshold || time_diff > time_threshold ){ INFO_OUTPUT(0, "Test failed" << endl); exit(1); }else { INFO_OUTPUT(0, "Test success" << endl); } }else{ ERROR("You should provide a test output file"); } INFO_OUTPUT( 1, "Integration time: " << integration_time << " ms " << std::endl); }
void generate_initial_conditions_for_system(const config& cfg, defaultEnsemble &ens, const int sysidx, const int sysid) { double time_init = cfg.optional("time_init", 0.0); const bool use_jacobi = cfg.optional("use_jacobi", 0); bool keplerian_ephemeris = cfg.optional("use_keplerian", 1); bool transit_ephemeris = cfg.optional("use_transit", 0); if(transit_ephemeris) keplerian_ephemeris = 0; assert(!(keplerian_ephemeris && transit_ephemeris)); // find a better way ens[sysidx].id() = sysid; ens[sysidx].time() = time_init; ens[sysidx].set_active(); if(sysid>maxsysid) maxsysid = sysid; // set sun to unit mass and at origin double mass_star = draw_value_from_config(cfg,"mass_star",0.00003,100.); double x=0, y=0, z=0, vx=0, vy=0, vz=0; ens.set_body(sysidx, 0, mass_star, x, y, z, vx, vy, vz); // If omitted or value of zero, then default to cycling through body id to make eccentric int ecc_body = cfg.optional("ecc_body", 0); if(ecc_body==0) { ecc_body = 1+(sysid*(ens.nbod()-1))/ens.nsys(); } double mass_enclosed = mass_star; for(unsigned int bod=1;bod<ens.nbod();++bod) { double mass_planet = draw_value_from_config(cfg,"mass",bod,0.,mass_star); mass_enclosed += mass_planet; double a, e, i, O, w, M; if(transit_ephemeris) { double period = draw_value_from_config(cfg,"period",bod,0.2,365250.); double epoch = draw_value_from_config(cfg,"epoch",bod,0.2,365250.); a = pow((period/365.25)*(period/365.25)*mass_enclosed,1.0/3.0); if(bod==ecc_body) e = draw_value_from_config(cfg,"ecc",bod,0.,1.); else e = 0.; i = draw_value_from_config(cfg,"inc",bod,-180.,180.); O = draw_value_from_config(cfg,"node",bod,-720.,720.); w = draw_value_from_config(cfg,"omega",bod,-720.,720.); i *= M_PI/180.; O *= M_PI/180.; w *= M_PI/180.; double T = (0.5*M_PI-w)+2.0*M_PI*((epoch/period)-floor(epoch/period)); double E = atan2(sqrt(1.-e)*(1.+e)*sin(T),e+cos(T)); M = E-e*sin(E); } else if (keplerian_ephemeris) { a = draw_value_from_config(cfg,"a",bod,0.001,10000.); if(bod==ecc_body) e = draw_value_from_config(cfg,"ecc",bod,0.,1.); else e = 0.; i = draw_value_from_config(cfg,"inc",bod,-180.,180.); O = draw_value_from_config(cfg,"node",bod,-720.,720.); w = draw_value_from_config(cfg,"omega",bod,-720.,720.); M = draw_value_from_config(cfg,"meananom",bod,-720.,720.); i *= M_PI/180.; O *= M_PI/180.; w *= M_PI/180.; M *= M_PI/180.; } double mass = use_jacobi ? mass_enclosed : mass_star+mass_planet; if(cfg.count("verbose")&&(sysid<10)) std::cout << "# Drawing sysid= " << sysid << " bod= " << bod << ' ' << mass_planet << " " << a << ' ' << e << ' ' << i*180./M_PI << ' ' << O*180./M_PI << ' ' << w*180./M_PI << ' ' << M*180./M_PI << '\n'; calc_cartesian_for_ellipse(x,y,z,vx,vy,vz, a, e, i, O, w, M, mass); // printf("%d %d: %lg (%lg %lg %lg) (%lg %lg %lg) \n", sysidx, bod, mass_planet, x,y,z,vx,vy,vz); if(use_jacobi) { double bx, by, bz, bvx, bvy, bvz; ens.get_barycenter(sysidx,bx,by,bz,bvx,bvy,bvz,bod-1); x += bx; y += by; z += bz; vx += bvx; vy += bvy; vz += bvz; } // assign body a mass, position and velocity ens.set_body(sysidx, bod, mass_planet, x, y, z, vx, vy, vz); if(cfg.count("verbose")&&(sysid<10)) { double x_t = ens.x(sysidx,bod); double y_t = ens.y(sysidx,bod); double z_t = ens.z(sysidx,bod); double vx_t = ens.vx(sysidx,bod); double vy_t = ens.vy(sysidx,bod); double vz_t = ens.vz(sysidx,bod); std::cout << " x= " << x << "=" << x_t << " "; std::cout << " y= " << y << "=" << y_t << " "; std::cout << " z= " << z << "=" << z_t << " "; std::cout << "vx= " << vx << "=" << vx_t << " "; std::cout << "vy= " << vy << "=" << vy_t << " "; std::cout << "vz= " << vz << "=" << vz_t << "\n"; } } // end loop over bodies // Shift into barycentric frame ens.get_barycenter(sysidx,x,y,z,vx,vy,vz); for(unsigned int bod=0;bod<ens.nbod();++bod) { ens.set_body(sysidx, bod, ens.mass(sysidx,bod), ens.x(sysidx,bod)-x, ens.y(sysidx,bod)-y, ens.z(sysidx,bod)-z, ens.vx(sysidx,bod)-vx, ens.vy(sysidx,bod)-vy, ens.vz(sysidx,bod)-vz); } // end loop over bodies }
void disable_unstable_systems(defaultEnsemble& ens, const std::vector<std::vector<double> >& semimajor_axes_init, const double deltaa_threshold ) { for(int sys_idx = 0; sys_idx < ens.nsys() ; sys_idx++) { if(ens[sys_idx].is_disabled() ) continue; bool disable = false; int sys_id = ens[sys_idx].id(); double star_mass = ens.mass(sys_idx,0); double mass_effective = star_mass; double bx, by, bz, bvx, bvy, bvz; ens.get_barycenter(sys_idx,bx,by,bz,bvx,bvy,bvz,0); for(unsigned int bod=1;bod<ens.nbod();++bod) // Skip star since calculating orbits { // std::cout << "body= " << bod << ": "; // std::cout << "pos= (" << ens.x(sys_idx, bod) << ", " << ens.y(sys_idx, bod) << ", " << ens.z(sys_idx, bod) << ") vel= (" << ens.vx(sys_idx, bod) << ", " << ens.vy(sys_idx, bod) << ", " << ens.vz(sys_idx, bod) << ").\n"; double mass = ens.mass(sys_idx,bod); mass_effective += mass; ens.get_barycenter(sys_idx,bx,by,bz,bvx,bvy,bvz,bod-1); double x = ens.x(sys_idx,bod)-bx; double y = ens.y(sys_idx,bod)-by; double z = ens.z(sys_idx,bod)-bz; double vx = ens.vx(sys_idx,bod)-bvx; double vy = ens.vy(sys_idx,bod)-bvy; double vz = ens.vz(sys_idx,bod)-bvz; double a, e, i, O, w, M; calc_keplerian_for_cartesian(a,e,i,O,w,M, x,y,z,vx,vy,vz, mass_effective); i *= 180/M_PI; O *= 180/M_PI; w *= 180/M_PI; M *= 180/M_PI; if(!((e>=0.)&&(e<1.0))) { disable = true; } if(!((a>0.)&&(a<10.0))) { disable = true; } assert(sys_id>=0); assert(sys_id<semimajor_axes_init.size()); assert(bod-1>=0); assert(bod-1<semimajor_axes_init[sys_id].size()); double da = a - semimajor_axes_init[sys_id][bod-1]; if(fabs(da) >= deltaa_threshold * semimajor_axes_init[sys_id][bod-1]) { disable = true; } if(disable) { if(cfg.count("verbose")) std::cout << "# Disabling idx=" << sys_idx << " id=" << sys_id << " b=" << bod << " a= " << a << " e= " << e << " i= " << i << " Omega= " << O << " omega= " << w << " M= " << M << "\n"; break; } } if(disable) ens[sys_idx].set_disabled(); } }
std::vector<std::vector<double> > calc_semimajor_axes(defaultEnsemble& ens) { std::vector<std::vector<double> > semimajor_axes(ens.nsys(),std::vector<double>(ens.nbod(),0.)); for(int sys_idx = 0; sys_idx < ens.nsys() ; sys_idx++) { int sys_id = ens[sys_idx].id(); assert(sys_id>=0); assert(sys_id<ens.nsys()); double star_mass = ens.mass(sys_idx,0); double mass_effective = star_mass; double bx, by, bz, bvx, bvy, bvz; ens.get_barycenter(sys_idx,bx,by,bz,bvx,bvy,bvz,0); for(unsigned int bod=1;bod<ens.nbod();++bod) // Skip star since calculating orbits { double mass = ens.mass(sys_idx,bod); mass_effective += mass; ens.get_barycenter(sys_idx,bx,by,bz,bvx,bvy,bvz,bod-1); double x = ens.x(sys_idx,bod)-bx; double y = ens.y(sys_idx,bod)-by; double z = ens.z(sys_idx,bod)-bz; double vx = ens.vx(sys_idx,bod)-bvx; double vy = ens.vy(sys_idx,bod)-bvy; double vz = ens.vz(sys_idx,bod)-bvz; double a, e, i, O, w, M; calc_keplerian_for_cartesian(a,e,i,O,w,M, x,y,z,vx,vy,vz, mass_effective); semimajor_axes[sys_id][bod-1] = a; } } return semimajor_axes; }
int number_of_disabled_systems(defaultEnsemble ens) { int count_running = 0; for(int i = 0; i < ens.nsys() ; i++) if( ens[i].is_disabled() ) count_running++; return count_running; }