/*! \param cfg Configuration Paramaters */ stop_on_ejection_params(const config &cfg) { rmax = cfg.optional("rmax",std::numeric_limits<float>::max()); deactivate_on = cfg.optional("deactivate_on_ejection",false); log_on = cfg.optional("log_on_ejection",false); verbose_on = cfg.optional("verbose_on_ejection",false); }
bool validate_configuration(config& cfg){ bool valid = true; // Indicates whether cfg parameters are valid int nsystems = cfg.optional("nsys",1000); int nbodypersystem = cfg.optional("nbod",3); // WARNING: blocksize isn't being used as the block size. Trying to remove this. // int bs = cfg.optional("blocksize",16); // Check that parameters from command line are ok // if((bs<ENSEMBLE_CHUNK_SIZE)||(bs>64)) valid =false; // if( bs % ENSEMBLE_CHUNK_SIZE != 0 ) valid = false; if(!(nsystems>=1)||!(nsystems<=256000)) valid = false; if(!(nbodypersystem>=3)||!(nbodypersystem<=MAX_NBODIES)) valid = false; return valid; }
void stability_test() { defaultEnsemble &ens = current_ens; double begin_time = ens.time_ranges().median; double destination_time = cfg.optional("destination_time", begin_time + 10 * M_PI ); double interval = cfg.optional("interval", (destination_time-begin_time) ) ; double logarithmic = cfg.optional("logarithmic", 0 ) ; double allowed_deltaE = cfg.optional("allowed_deltaE", 0.01 ); if(destination_time < begin_time ) ERROR("Destination time should be larger than begin time"); if(interval < 0) ERROR("Interval cannot be negative"); if(interval < 0.001) ERROR("Interval too small"); if(logarithmic != 0 && logarithmic <= 1) ERROR("logarithm base should be greater than 1"); std::cout << "Time, Energy Conservation Factor (delta E/E), Active Systems" << std::endl; for(double time = begin_time; time < destination_time; ) { if(logarithmic > 1) time = (time > 0) ? time * logarithmic : interval; else time += interval; double effective_time = min(time,destination_time); integ->set_destination_time ( effective_time ); DEBUG_OUTPUT(2, "Integrator ensemble" ); integ->integrate(); SYNC; DEBUG_OUTPUT(2, "Check energy conservation" ); ensemble::range_t deltaE_range = energy_conservation_error_range(ens, initial_ens ); int active_systems = ens.nsys() - number_of_disabled_systems( ens ); std::cout << effective_time << ", " << deltaE_range.max << ", " << deltaE_range.median << ", " << active_systems << std::endl; if(deltaE_range.median > allowed_deltaE){ INFO_OUTPUT(0, "At least half of systems are too unstable to conserve energy. dE/E: " << deltaE_range.median << std::endl ); exit(1); } } }
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; }
/** * This procedure was copied from the other Monte Carlo simulation code * * I had to change all the floats to double because in the new swarm we * use double for masses. Also, our ensemble classes now use reference * counted pointers and we create them in a functional way than old * fill-this-for-me-please pointers(references). The generate name * makes more sense that the set_initial_conditions. I only added * one line for generating the ensemble. In the other monte carlo, * the ensemble is generated first and then passed to this function * to fill it in. * * */ defaultEnsemble generate_ensemble_with_randomized_initial_conditions(const config& cfg) { defaultEnsemble ens = defaultEnsemble::create( cfg.require("nbod",0), cfg.require("nsys",0) ); std::cerr << "# nsystems = " << ens.nsys() << " nbodies/system = " << ens.nbod() << "\n"; // std::cerr << "# Set initial time for all systems = "; double time_init = cfg.optional("time_init", 0.0); // std::cerr << time_init << ".\n"; 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 for(unsigned int sys=0;sys<ens.nsys();++sys) { generate_initial_conditions_for_system(cfg,ens,sys,sys); } // end loop over systems return ens; }
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); } }
Pwriter writer::create(const config& cfg) { Pwriter w; std::string name = cfg.optional(std::string("log_writer") , std::string("null") ); std::string plugin_name = "writer_" + name; try { w.reset( (writer*) (plugin::instance(plugin_name,cfg)) ); }catch(plugin_not_found& e){ ERROR("Log writer " + name + " not found."); } return w; }
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 print_system(const swarm::ensemble& ens, const int systemid, std::ostream &os = std::cout) { enum { JACOBI, BARYCENTRIC, ASTROCENTRIC } COORDINATE_SYSTEM = BARYCENTRIC; const bool use_jacobi = cfg.optional("use_jacobi", 0); if(use_jacobi) COORDINATE_SYSTEM = JACOBI; std::streamsize cout_precision_old = os.precision(); os.precision(10); os << "sys_idx= " << systemid << " sys_id= " << ens[systemid].id() << " time= " << ens.time(systemid) << "\n"; double star_mass = ens.mass(systemid,0); double mass_effective = star_mass; double bx, by, bz, bvx, bvy, bvz; switch(COORDINATE_SYSTEM) { case JACOBI: ens.get_barycenter(systemid,bx,by,bz,bvx,bvy,bvz,0); break; case BARYCENTRIC: ens.get_barycenter(systemid,bx,by,bz,bvx,bvy,bvz); break; case ASTROCENTRIC: ens.get_body(systemid,0,star_mass,bx,by,bz,bvx,bvy,bvz); break; } for(unsigned int bod=1;bod<ens.nbod();++bod) // Skip star since printing orbits { // std::cout << "pos= (" << ens.x(systemid, bod) << ", " << ens.y(systemid, bod) << ", " << ens.z(systemid, bod) << ") vel= (" << ens.vx(systemid, bod) << ", " << ens.vy(systemid, bod) << ", " << ens.vz(systemid, bod) << ").\n"; double mass = ens.mass(systemid,bod); switch(COORDINATE_SYSTEM) { case JACOBI: ens.get_barycenter(systemid,bx,by,bz,bvx,bvy,bvz,bod-1); mass_effective += mass; break; case BARYCENTRIC: mass_effective = star_mass + mass; break; case ASTROCENTRIC: mass_effective = star_mass + mass; break; } double x = ens.x(systemid,bod)-bx; double y = ens.y(systemid,bod)-by; double z = ens.z(systemid,bod)-bz; double vx = ens.vx(systemid,bod)-bvx; double vy = ens.vy(systemid,bod)-bvy; double vz = ens.vz(systemid,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; // os << " b= " << bod << " m= " << mass << " a= " << a << " e= " << e << " i= " << i << " Omega= " << O << " omega= " << w << " M= " << M << "\n"; os << ens[systemid].id() << " " << bod << " " << mass << " " << a << " " << e << " " << i << " " << O << " " << w << " " << M << "\n"; } os.precision(cout_precision_old); os << std::flush; }
int main(int argc, char* argv[]){ // Command line and Config file parse_commandline_and_config(argc,argv); // outputConfigSummary(std::cout,cfg); base_cfg = cfg; command = argvars_map["command"].as< string >(); // Set some variables pos_threshold = cfg.optional("pos_threshold", 1e-10); vel_threshold = cfg.optional("vel_threshold", 1e-10); time_threshold = cfg.optional("time_threshold", 1e-10); // Branch based on COMMAND if(command == "integrate"){ init_cuda(); run_integration(); }else if(command == "test-cpu"){ // init_cuda(); // removed so CPU tests would work, but then broke GPU tests when needed to set cuda device output_test(); }else if(command == "test"){ init_cuda(); output_test(); }else if(command == "benchmark" || command == "verify") { init_cuda(); if(command == "verify") verify_mode = true; if(argvars_map.count("range") > 0) { parameter_range pr = argvars_map["range"].as<parameter_range>(); benchmark(pr); }else cerr << "A parameter-value range is missing" << endl; if(command == "verify") { cout << (verification_results ? "Verify success" : "Verify failed") << endl; return verification_results ? 0 : 1; } } else if(command == "query" ) { if (!argvars_map.count("logfile")) { cerr << "Name of input log file is missing \n"; return 1; } time_range_t T; sys_range_t sys, body_range; if (argvars_map.count("time")) { T = argvars_map["time"].as<time_range_t>(); } if (argvars_map.count("system")) { sys = argvars_map["system"].as<sys_range_t>(); } if (argvars_map.count("body")) { body_range = argvars_map["body"].as<sys_range_t>(); } if (argvars_map.count("keplerian")) { query::set_keplerian_output(); } if (argvars_map.count("origin")) { query::set_coordinate_system(query::origin); } if (argvars_map.count("astrocentric")) { query::set_coordinate_system(query::astrocentric); } if (argvars_map.count("barycentric")) { query::set_coordinate_system(query::barycentric); } if (argvars_map.count("jacobi")) { query::set_coordinate_system(query::jacobi); } std::cout.flush(); cerr << "# Systems: " << sys << " Bodies: " << body_range << " Times: " << T << endl; if (argvars_map.count("keplerian")) { std::cerr << "# Output in Keplerian coordinates "; } else { std::cerr << "# Output in Cartesian coordinates "; } #if 0 switch(query::planets_coordinate_system) { case astrocentric: std::cerr << "(astrocentric)"; break; case barycentric: std::cerr << "(barycentric)"; break; case jacobi: std::cerr << "(jacobi)"; break; case origin: std::cerr << "(origin)"; break; } #endif std::cerr << "\n"; std::string datafile(argvars_map["logfile"].as<std::string>()); query::execute(datafile, T, sys, body_range); } else if(command == "generate" ) { srand(time(NULL)); INFO_OUTPUT(1, "Generating new ensemble: " << cfg["nsys"] << ", " << cfg["nbod"] << endl); current_ens = generate_ensemble(cfg); save_ensemble(); } else if(command == "convert" ) { if( read_input_file(current_ens,cfg) && save_ensemble() ) { INFO_OUTPUT(1,"Converted!"); }else{ INFO_OUTPUT(1,"Convertion failed"); exit(1); } } else std::cerr << "Valid commands are: integrate, benchmark, verify, test, test-cpu, query, generate " << std::endl; return 0; }
stop_on_collision_param(const config &cfg) { dmin_squared = cfg.optional("collision_radius",0.); dmin_squared *= dmin_squared; }
/** * Read in Keplerian coordinates from a text file * */ defaultEnsemble generate_ensemble_with_initial_conditions_keplerian_from_file(const config& cfg) { defaultEnsemble ens = defaultEnsemble::create( cfg.require("nbod",0), cfg.require("nsys",0) ); std::cerr << "# nsystems = " << ens.nsys() << " nbodies/system = " << ens.nbod() << "\n"; // std::cerr << "# Set initial time for all systems = "; double time_init = cfg.optional("time_init", 0.0); // std::cerr << time_init << ".\n"; const bool use_jacobi = cfg.optional("use_jacobi", 0); // std::cerr << "# Writing stable system ids\n"; ifstream jacobi_input( cfg.optional("input_mcmc_keplerian", string("mcmc.out")).c_str() ); for(unsigned int sysid=0;sysid<ens.nsys();++sysid) { assert(jacobi_input.good()); string id; double mass_star; jacobi_input >> id >> mass_star; ens[sysid].id() = sysid; ens[sysid].time() = time_init; ens[sysid].set_active(); double x=0, y=0, z=0, vx=0, vy=0, vz=0; ens.set_body(sysid, 0, mass_star, x, y, z, vx, vy, vz); double mass_enclosed = mass_star; for(unsigned int bod=1;bod<ens.nbod();++bod) { double mass_planet, a, e, i, O, w, M; jacobi_input >> mass_planet >> a >> e >> i >> w >> O >> M; // a = pow((period/365.25)*(period/365.25)*mass_enclosed,1.0/3.0); i *= M_PI/180.; O *= M_PI/180.; w *= M_PI/180.; M *= M_PI/180.; mass_enclosed += mass_planet; 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", sysid, bod, mass_planet, x,y,z,vx,vy,vz); if(use_jacobi) { double bx, by, bz, bvx, bvy, bvz; ens.get_barycenter(sysid,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(sysid, bod, mass_planet, x, y, z, vx, vy, vz); if(cfg.count("verbose")&&(sysid<10)) { double x_t = ens.x(sysid,bod); double y_t = ens.y(sysid,bod); double z_t = ens.z(sysid,bod); double vx_t = ens.vx(sysid,bod); double vy_t = ens.vy(sysid,bod); double vz_t = ens.vz(sysid,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(sysid,x,y,z,vx,vy,vz); for(unsigned int bod=0;bod<ens.nbod();++bod) { ens.set_body(sysid, bod, ens.mass(sysid,bod), ens.x(sysid,bod)-x, ens.y(sysid,bod)-y, ens.z(sysid,bod)-z, ens.vx(sysid,bod)-vx, ens.vy(sysid,bod)-vy, ens.vz(sysid,bod)-vz); } // end loop over bodies } // end loop over systems return ens; }
/** * Read in Cartesian coordinates from a text file * */ defaultEnsemble generate_ensemble_with_initial_conditions_cartesian_from_file(const config& cfg) { defaultEnsemble ens = defaultEnsemble::create( cfg.require("nbod",0), cfg.require("nsys",0) ); std::cerr << "# nsystems = " << ens.nsys() << " nbodies/system = " << ens.nbod() << "\n"; // std::cerr << "# Set initial time for all systems = "; double time_init = cfg.optional("time_init", 0.0); // std::cerr << time_init << ".\n"; const bool use_jacobi = cfg.optional("use_jacobi", 0); // std::cerr << "# Writing stable system ids\n"; ifstream mcmc_input( cfg.optional("input_mcmc_cartesian", string("mcmc.out")).c_str() ); assert(mcmc_input.good()); const int lines_to_skip = cfg.optional("lines_to_skip", 0); for(int i=0;i<lines_to_skip;++i) { assert(mcmc_input.good()); char junk[1024]; mcmc_input.getline(junk,1024); } for(unsigned int sysid=0;sysid<ens.nsys();++sysid) { assert(mcmc_input.good()); #if 1 std::vector<double> masses(ens.nbod(),0.0); for(unsigned int bod=0;bod<ens.nbod();++bod) { mcmc_input >> masses[bod]; } // end loop over bodies ens[sysid].id() = sysid; ens[sysid].time() = time_init; ens[sysid].set_active(); double x=0, y=0, z=0, vx=0, vy=0, vz=0; ens.set_body(sysid, 0, masses[0], x, y, z, vx, vy, vz); double mass_enclosed = masses[0]; for(unsigned int bod=1;bod<ens.nbod();++bod) { mcmc_input >> x >> y >> z >> vx >> vy >> vz; mass_enclosed += masses[bod]; double mass = use_jacobi ? mass_enclosed : masses[0]+masses[bod]; if(cfg.count("verbose")&&(sysid<10)) std::cout << "# Drawing sysid= " << sysid << " bod= " << bod << ' ' << masses[bod] << " " << x << ' ' << y << ' ' << z << ' ' << vx << ' ' << vy << ' ' << vz << '\n'; if(use_jacobi) { double bx, by, bz, bvx, bvy, bvz; ens.get_barycenter(sysid,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(sysid, bod, masses[bod], x, y, z, vx, vy, vz); if(cfg.count("verbose")&&(sysid<10)) { double x_t = ens.x(sysid,bod); double y_t = ens.y(sysid,bod); double z_t = ens.z(sysid,bod); double vx_t = ens.vx(sysid,bod); double vy_t = ens.vy(sysid,bod); double vz_t = ens.vz(sysid,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"; } #else std::vector<double> masses(ens.nbod(),0.0); double x=0, y=0, z=0, vx=0, vy=0, vz=0; double mass_enclosed = 0.0; ens[sysid].id() = sysid; ens[sysid].time() = time_init; ens[sysid].set_active(); for(unsigned int bod=0;bod<ens.nbod();++bod) { mcmc_input >> masses[bod]; mcmc_input >> x >> y >> z >> vx >> vy >> vz; mass_enclosed += masses[bod]; double mass = use_jacobi ? mass_enclosed : masses[0]+masses[bod]; if(cfg.count("verbose")&&(sysid<10)) std::cout << "# Drawing sysid= " << sysid << " bod= " << bod << ' ' << masses[bod] << " " << x << ' ' << y << ' ' << z << ' ' << vx << ' ' << vy << ' ' << vz << '\n'; if(use_jacobi) { double bx, by, bz, bvx, bvy, bvz; ens.get_barycenter(sysid,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(sysid, bod, masses[bod], x, y, z, vx, vy, vz); if(cfg.count("verbose")&&(sysid<10)) { double x_t = ens.x(sysid,bod); double y_t = ens.y(sysid,bod); double z_t = ens.z(sysid,bod); double vx_t = ens.vx(sysid,bod); double vy_t = ens.vy(sysid,bod); double vz_t = ens.vz(sysid,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"; } #endif } // end loop over bodies // Shift into barycentric frame ens.get_barycenter(sysid,x,y,z,vx,vy,vz); for(unsigned int bod=0;bod<ens.nbod();++bod) { ens.set_body(sysid, bod, ens.mass(sysid,bod), ens.x(sysid,bod)-x, ens.y(sysid,bod)-y, ens.z(sysid,bod)-z, ens.vx(sysid,bod)-vx, ens.vy(sysid,bod)-vy, ens.vz(sysid,bod)-vz); } // end loop over bodies } // end loop over systems return ens; } void print_system(const swarm::ensemble& ens, const int systemid, std::ostream &os = std::cout) { enum { JACOBI, BARYCENTRIC, ASTROCENTRIC } COORDINATE_SYSTEM = BARYCENTRIC; const bool use_jacobi = cfg.optional("use_jacobi_output", 0); if(use_jacobi) COORDINATE_SYSTEM = JACOBI; std::streamsize cout_precision_old = os.precision(); os.precision(10); os << "sys_idx= " << systemid << " sys_id= " << ens[systemid].id() << " time= " << ens.time(systemid) << "\n"; double star_mass = ens.mass(systemid,0); double mass_effective = star_mass; double bx, by, bz, bvx, bvy, bvz; switch(COORDINATE_SYSTEM) { case JACOBI: ens.get_barycenter(systemid,bx,by,bz,bvx,bvy,bvz,0); break; case BARYCENTRIC: ens.get_barycenter(systemid,bx,by,bz,bvx,bvy,bvz); break; case ASTROCENTRIC: ens.get_body(systemid,0,star_mass,bx,by,bz,bvx,bvy,bvz); break; } for(unsigned int bod=1;bod<ens.nbod();++bod) // Skip star since printing orbits { // std::cout << "pos= (" << ens.x(systemid, bod) << ", " << ens.y(systemid, bod) << ", " << ens.z(systemid, bod) << ") vel= (" << ens.vx(systemid, bod) << ", " << ens.vy(systemid, bod) << ", " << ens.vz(systemid, bod) << ").\n"; double mass = ens.mass(systemid,bod); switch(COORDINATE_SYSTEM) { case JACOBI: ens.get_barycenter(systemid,bx,by,bz,bvx,bvy,bvz,bod-1); mass_effective += mass; break; case BARYCENTRIC: mass_effective = star_mass + mass; break; case ASTROCENTRIC: mass_effective = star_mass + mass; break; } double x = ens.x(systemid,bod)-bx; double y = ens.y(systemid,bod)-by; double z = ens.z(systemid,bod)-bz; double vx = ens.vx(systemid,bod)-bvx; double vy = ens.vy(systemid,bod)-bvy; double vz = ens.vz(systemid,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; // os << " b= " << bod << " m= " << mass << " a= " << a << " e= " << e << " i= " << i << " Omega= " << O << " omega= " << w << " M= " << M << "\n"; os << ens[systemid].id() << " " << bod << " " << mass << " " << a << " " << e << " " << i << " " << O << " " << w << " " << M << "\n"; } os.precision(cout_precision_old); os << std::flush; } void print_selected_systems(swarm::ensemble& ens, std::vector<unsigned int> systemindices, std::ostream &os = std::cout) { for(unsigned int i=0; i<systemindices.size(); ++i) print_system(ens,systemindices[i], os); } void print_selected_systems_for_demo(swarm::ensemble& ens, unsigned int nprint, std::ostream &os = std::cout) { if(nprint>ens.nsys()) nprint = ens.nsys(); for(unsigned int systemid = 0; systemid< nprint; ++systemid) print_system(ens,systemid,os); } 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); } }
stop_on_ejection_params(const config &cfg) { rmax = cfg.optional("rmax",std::numeric_limits<float>::max()); }
int main(int argc, char* argv[] ) { // We keep it simple, later on one can use boost::program_options to // have more options // but now we only use two configuration files. It is because the // initial conditions configuration file can get really big and // it has very little to do with other configuration options. if(argc < 3) cout << "Usage: montecarlo_ecclimit <integration configuration> <initial conditions configuration>" << endl; // First one is the configuration for integration string integ_configfile = argv[1]; // the second one is the configuration for generating // initial conditions it is used by \ref generate_ensemble_with_randomized_initial_conditions string initc_configfile = argv[2]; cfg = config::load(integ_configfile); // 1.read keplerian coordinates from a file // 2.generate guesses based on the keplerian coordinates // 3.convert keplerian coordinates to an ensemble // The following line that is taken from swarm_tutorial_montecarlo.cpp // does the first three steps. Its pretty amazing. defaultEnsemble ens ; if( cfg.count("input") ) { ens = snapshot::load(cfg["input"]); } else { ens = generate_ensemble_with_randomized_initial_conditions( config::load(initc_configfile) ); } // save the ensemble as a snapshot if(cfg.count("initial_snapshot")) { snapshot::save( ens, cfg["initial_snapshot"] ); } defaultEnsemble ens_init = ens.clone() ; std::vector<std::vector<double> > semimajor_axes_init = calc_semimajor_axes(ens); // We want to find the ones that are really stable, so we integrate for // a really long time and over time we get rid of unstable ones. double destination_time = cfg.optional("destination_time", 1.0E6); swarm::init(cfg); Pintegrator integ = integrator::create(cfg); integ->set_ensemble(ens); integ->set_destination_time ( destination_time ); // We can set the following two items if we really need // longer integrations before we stop for checking the // ensemble and saving snapshots. // one kernel call to allow for prompt CPU pruning of unstable systems int max_kernel_calls_per_integrate = cfg.optional("max_kernel_calls_per_integrate",1); // 10^2 inner orbits at 200 time steps per inner orbit int max_itterations_per_kernel_call = cfg.optional("max_itterations_per_kernel_call",20000); integ->set_max_attempts( max_kernel_calls_per_integrate ); integ->set_max_iterations ( max_itterations_per_kernel_call ); SYNC; // integrate ensemble // - drop the unstable ones as you go // - redistribute the systems for better efficiency // - save the results periodically // This can be an infitie loop. but we can always get out of this // the best way to do it is to use Ctrl-C. Further wecan // define Ctrl-C signal handler to get out // of this loop in a safe way. But we really want this loop // to run for a long time reactivate_systems(ens); // EBF Experiment trying to expose host log. swarm::log::ensemble(*(swarm::log::manager::default_log()->get_hostlog()),ens); integ->flush_log(); catch_ctrl_c(); while( number_of_active_systems(ens) > 0 && integration_loop_not_aborted_yet ) { // 1. Integrate, we could use core_integrate but the general integrate // saves all the headache. We should only use core_integrate if we are // going to do everything on GPU, but since we are saving a snapshot in // the middle, there's no point. It also has a nice for loop and can // to several kernel calls. integ->integrate(); // 2. CPU-based tests to identify systems that can be terminated int active_ones = number_of_active_systems(ens); const double deltaa_frac_threshold = cfg.optional("deltaa_frac_threshold", 0.5); disable_unstable_systems( ens, semimajor_axes_init, deltaa_frac_threshold ); // double med_deltaE = find_median_energy_conservation_error(ens, ens_init ); double max_deltaE = find_max_energy_conservation_error(ens, ens_init ); std::cerr << "# Time: " << ens.time_ranges().min << " " << ens.time_ranges().median << " " << ens.time_ranges().max << " Systems: " << ens.nsys() << ", " << active_ones << ", "; active_ones = number_of_active_systems(ens); std::cerr << active_ones << " max|dE/E|= " << max_deltaE << "\n"; // EBF Experiment trying to expose host log. swarm::log::ensemble_enabled(*(swarm::log::manager::default_log()->get_hostlog()),ens); integ->flush_log(); if (!cfg.count("input") && cfg.count("replace_unstable") ) { int nsys_to_replace = number_of_disabled_systems( ens ) ; if( nsys_to_replace >0 ) { replace_disabled_systems( ens ); integ->set_ensemble( ens ); } } else { // 3. Now we need to get rid of the inactive ones. There // should be some criteria, whatever it is we are // going to put it in a function and call it \ref needs_shrinking if ( needs_shrinking( ens ) ) { // Now this function will take care of trimming for us // We need to create a new ensemble of a smaller size // thats why we need to call set_ensemble again. because // the GPU ensemble should get recreated for us. // we need better memory management to safely allow // the following statement. Right now we don't have a // very good automatic memory management // std::cerr << "# Removing disabled systems\n"; ens = trim_disabled_systems( ens ); // std::cerr << "# Testing if ens has any systems left.\n"; if(ens.nsys()>0) { // std::cerr << "# Setting ensemble for integrator\n"; // WARNING: This appears to be the cause of SEGFAULT // if the ensemble is empty. integ->set_ensemble( ens ); } // std::cerr << "# Time: " << ens.time_ranges() << " Total Systems: " << ens.nsys() << " Active Systems: " << active_ones << ", "; // active_ones = number_of_active_systems(ens); // std::cerr << active_ones << "\n"; } } // std::cerr << std::endl; // 4. We need to save a snapshot in case system crashes or someone // gets tired of it and hits Ctrl-C // std::cerr << "# Saving snapshot\n"; save_snapshot( ens ); write_stable_systems(ens,ens_init); } // Now we are at the end of the system, before we examine // the output we need to // std::cerr << "# Removing disabled systems\n"; if(number_of_active_systems(ens)>0) { ens = trim_disabled_systems( ens ); // std::cerr << "# Saving snapshot\n"; save_snapshot( ens ); } write_stable_systems(ens,ens_init); }
stop_on_all_but_two_at_large_distance_params(const config &cfg) { double rmax = cfg.optional("rmax",std::numeric_limits<float>::max()); }
stop_on_any_large_distance_params(const config &cfg) { rmax = cfg.optional("rmax",std::numeric_limits<float>::max()); stop = cfg.optional("stop_on_rmax",false); }