/** First, we test whether body b is far from the origin * (which may be COM or star) and moving farther away. * If both of those are passed, then we check that the * orbit is parabolic or hyperbolic. * */ GPUAPI bool test_body(const int& b) { double x,y,z,vx,vy,vz; _sys[b].get(x,y,z,vx,vy,vz); // double r = sqrt(_sys[b].radius_squared()); // WARNING: Deceiving function name double r = _sys[b].radius(); // WARNING: Deceiving function name if( r < _params.rmax ) return false; double rdotv = x*vx+y*vy+z*vz; if( rdotv <= 0. ) return false; bool stopit = false; double speed_sq = _sys[b].speed_squared(); // WARNING: Deceiving function name double epp = 0.5*speed_sq*r/_sys[b].mass()-1.; if( fabs(epp) < 1e-4 ) { double energy = 0.5*speed_sq-_sys[b].mass()/r; if(is_verbose_on() ) lprintf(_log, "Orbit is nearly parabolic: _sys=%d, bod=%d, T=%lg r=%lg energy=%lg energy*r/GM=%lg.\n" , _sys.number(), b, _sys.time() , r, energy, epp ); stopit = true; }else if ( epp > 0 ){ double energy = 0.5*speed_sq-_sys[b].mass()/r; if(is_verbose_on() ) lprintf(_log, "Orbit is hyperbolic: _sys=%d, bod=%d, T=%lg r=%lg energy=%lg energy*r/GM=%lg.\n" , _sys.number(), b, _sys.time() , r, energy, epp ); // TODO: Make sure that planet is not near another body // This is very unlikely to be an issue, provided that rmax // is set to be well beyond the initial semi-major axes stopit = true; } return stopit; }
GPUAPI int pass_two (int thread_in_system) { int new_state = _sys.state(); if(is_any_on() && need_full_test) // implies thread_in_system==0 { // Check for distance from other bodies int num_body_far_from_all = 0; for(int b = 0 ; b < _sys.nbod(); b ++ ) { if(_sys.radius_squared(b) <= _params.rmax*_params.rmax ) continue; // WARNING: Confusing function name bool is_far_from_every_body = true; for(int bb = 0 ; bb < _sys.nbod(); bb ++ ){ if(b == bb) continue; if(_sys.distance_squared_between(b,bb) < _params.rmax*_params.rmax ) { is_far_from_every_body = false; break; } } if(is_far_from_every_body) { num_body_far_from_all++; } } if(num_body_far_from_all+2>=_sys.nbod()) { condition_met = true; if(is_verbose_on()) lprintf(_log, "No more than two bodies are within rmax of other bodies: _sys=%d, bod1=%d, bod2=%d, T=%lg r=%lg rmax=%lg.\n" , _sys.number(), id1, id2, _sys.time() , r, _params.rmax); if(is_deactivate_on() && (_sys.state()>=0) ) { _sys.set_disabled(); new_state = _sys.state(); } } } return new_state; }
// GPUAPI void operator () () { GPUAPI void operator () (int thread_in_system) { if(!is_any_on()) return; if(thread_in_system==0) { // Check for distance from origin int num_body_near_origin = 0, id1 = -1, id2 = -2; for(int b = 0 ; b < _sys.nbod(); b ++ ){ if(_sys.radius_squared(b) <= _params.rmax*_params.rmax ) // WARNING: Confusing function name { if(num_body_near_origin==0) id1 = b; if(num_body_near_origin==1) id2 = b; num_body_near_origin++; } } if( num_body_near_origin > 2 ) return; // Check for distance from other bodies int num_body_far_from_all = 0; for(int b = 0 ; b < _sys.nbod(); b ++ ){ if(_sys.radius_squared(b) <= _params.rmax*_params.rmax ) continue; // WARNING: Confusing function name bool is_far_from_every_body = true; for(int bb = 0 ; bb < _sys.nbod(); bb ++ ){ if(b == bb) continue; if(_sys.distance_squared_between(b,bb) < _params.rmax*_params.rmax ) { is_far_from_every_body = false; break; } } if(is_far_from_every_body) { num_body_far_from_all++; } } if(num_body_far_from_all+2>=_sys.nbod()) { if(is_verbose_on()) lprintf(_log, "No more than two bodies are within rmax of other bodies: _sys=%d, bod1=%d, bod2=%d, T=%lg r=%lg rmax=%lg.\n" , _sys.number(), id1, id2, _sys.time() , r, _params.rmax); if(is_log_on()) log::system(_log, _sys); if(is_deactivate_on()) _sys.set_disabled(); } } }
GPUAPI bool pass_one (int thread_in_system) { need_full_test = false; condition_met = false; if(is_any_on()&&(thread_in_system==0)) { bool is_any_body_far_from_origin = false; for(int b = 0 ; b < _sys.nbod(); b ++ ) { if(_sys.radius_squared(b) > _params.rmax * _params.rmax ) is_any_body_far_from_origin = true; } if(!is_any_body_far_from_origin) break; bool need_to_log = false; for(int b = 0 ; b < _sys.nbod(); b ++ ) { if(_sys.radius_squared(b) >= _params.rmax * _params.rmax ) { bool is_far_from_every_body = true; for(int bb = 0 ; bb < _sys.nbod(); bb ++ ) if(b != bb) { double r2 = _sys.distance_squared_between(b,bb); if(r2 < _params.rmax*_params.rmax ) is_far_from_every_body = false; } if(is_far_from_every_body) { condition_met = true; if( is_log_on() ) need_full_test = true; if(is_verbose_on() ) lprintf(_log, "Distance from all bodies exceeds rmax: _sys=%d, bod=%d, T=%lg r=%lg rmax=%lg.\n", _sys.number(), b, _sys.time() , sqrt(r2), _params.rmax); } } // if far from origin } // for bodies } return need_full_test; }
// GPUAPI void operator () () { GPUAPI void operator () (int thread_in_system) { if(!is_any_on()) return; if(thread_in_system==0) { bool is_any_body_far_from_origin = false; for(int b = 0 ; b < _sys.nbod(); b ++ ){ if(_sys.radius_squared(b) > _params.rmax * _params.rmax ) is_any_body_far_from_origin = true; } if(!is_any_body_far_from_origin) return; bool need_to_log = false; for(int b = 0 ; b < _sys.nbod(); b ++ ){ if(_sys.radius_squared(b) >= _params.rmax * _params.rmax ) { bool is_far_from_every_body = true; for(int bb = 0 ; bb < _sys.nbod(); bb ++ ) if(b != bb) { double r2 = _sys.distance_squared_between(b,bb); if(r2 < _params.rmax*_params.rmax ) is_far_from_every_body = false; } if(is_far_from_every_body) { if(is_verbose_on() ) lprintf(_log, "Distance from all bodies exceeds rmax: _sys=%d, bod=%d, T=%lg r=%lg rmax=%lg.\n", _sys.number(), b, _sys.time() , sqrt(r2), _params.rmax); if(is_log_on() ) need_to_log = true; if(is_deactivate_on() ) a_sys.set_disabled(); } } } if(need_to_log) log::system(_log, _sys); } }
GPUAPI bool is_any_on() { return is_deactivate_on() || is_log_on() || is_verbose_on() ; }