44 int nbod, num_max_iter;
45 bool log_on_transit, log_on_occultation;
50 nbod = cfg.
require<
int>(
"nbod");
51 num_max_iter = cfg.
optional(
"num_max_transit_iter", 2);
52 tol = cfg.
optional(
"log_transit_tol", 2.e-8);
54 dt = cfg.
require(
"time_step", 0.0);
55 log_on_transit = cfg.
optional(
"log_transits",
true);
56 log_on_occultation = cfg.
optional(
"log_occultations",
false);
82 ensemble::SystemRef& _sys;
88 static GENERIC int thread_per_system(T compile_time_param){
93 static GENERIC int shmem_per_system(T compile_time_param) {
96 GPUAPI
bool is_deactivate_on() {
return false; };
97 GPUAPI
bool is_log_on() {
return _params.tol!=0.; };
98 GPUAPI
bool is_verbose_on() {
return false; };
99 GPUAPI
bool is_any_on() {
return is_deactivate_on() || is_log_on() || is_verbose_on() ; }
100 GPUAPI
bool is_condition_met () {
return ( condition_met ); }
101 GPUAPI
bool need_to_log_system ()
102 {
return (is_log_on() && is_condition_met() ); }
103 GPUAPI
bool need_to_deactivate ()
104 {
return ( is_deactivate_on() && is_condition_met() ); }
106 GPUAPI
void log_system() {
log::system(_log, _sys); }
110 pass_one(thread_in_system);
111 pass_two(thread_in_system);
112 if(need_to_log_system() && (thread_in_system==0) )
116 GPUAPI
bool pass_one (
const int thread_in_system)
118 condition_met =
false;
123 GPUAPI
double square(
const double x) {
return x*
x; }
128 GPUAPI
void calc_transit_time(
const int& thread_in_system,
const int& i,
const int& j,
const double& dt,
double dx[2],
double dv[2],
const double& b2begin,
double& db2dt,
const double& pos_step_end,
const double& vel_step_end,
double& dt_min_b2,
double& b,
double & vproj)
130 extern __shared__
char shared_mem[];
133 typedef typename calcForces_t::shared_data grav_t;
140 double pos = pos_step_end, vel = vel_step_end;
142 #if USING_INTEGRATOR_THAT_OVER_WRITES_SHARED_DATA || 1
143 calcForces(thread_in_system,bid,cid,pos,vel,acc,jerk);
150 double acc_ix, acc_jx, acc_iy, acc_jy, jerk_ix, jerk_jx, jerk_iy, jerk_jy;
151 calcForces.sum(i,0,acc_ix,jerk_ix);
152 calcForces.sum(i,1,acc_iy,jerk_iy);
153 calcForces.sum(j,0,acc_jx,jerk_jx);
154 calcForces.sum(j,1,acc_jy,jerk_jy);
155 double da[2] = { acc_jx - acc_ix, acc_jy- acc_iy };
156 double dj[2] = { jerk_jx-jerk_ix, jerk_jy-jerk_iy };
157 double d2b2dt2 = 2.*(dv[0]*dv[0]+dv[1]*dv[1]+dx[0]*da[0]+dx[1]*da[1]);
158 double d3b2dt3 = 6.*(dv[0]*da[0]+dv[1]*da[1])+2.*(dx[0]*dj[0]+dx[1]*dj[1]);
159 double dt_try = -db2dt/d2b2dt2;
160 dt_try = -db2dt/(d2b2dt2+0.5*dt_try*d3b2dt3);
164 if((dt_try<=-0.5*dt) || (dt_try>0.5*dt) )
165 { dt_min_b2 = dt_try; b=-1.; vproj = -1.;
return; }
166 double dt_cum = dt_try;
168 for(
int iter=0;iter<_params.num_max_iter;++iter)
171 pos = pos + dt_try*(vel+(dt_try*0.5)*(acc+(dt_try/3.0)*jerk));
172 vel = vel + dt_try*(acc+(dt_try*0.5)*jerk);
173 calcForces(thread_in_system,bid,cid,pos,vel,acc,jerk);
174 dx[0] = _sys[j][0].pos()-_sys[i][0].pos();
175 dx[1] = _sys[j][1].pos()-_sys[i][1].pos();
176 dv[0] = _sys[j][0].vel()-_sys[i][0].vel();
177 dv[1] = _sys[j][1].vel()-_sys[i][1].vel();
178 b2 = dx[0]*dx[0]+dx[1]*dx[1];
179 db2dt = 2.*(dx[0]*dv[0]+dx[1]*dv[1]);
180 calcForces.sum(i,0,acc_ix,jerk_ix);
181 calcForces.sum(i,1,acc_iy,jerk_iy);
182 calcForces.sum(j,0,acc_jx,jerk_jx);
183 calcForces.sum(j,1,acc_jy,jerk_jy);
184 da[0] = acc_jx - acc_ix; da[1] = acc_jy- acc_iy;
185 dj[0] = jerk_jx-jerk_ix, dj[1] = jerk_jy-jerk_iy;
186 d2b2dt2 = 2.*(dv[0]*dv[0]+dv[1]*dv[1]+dx[0]*da[0]+dx[1]*da[1]);
187 d3b2dt3 = 6.*(dv[0]*da[0]+dv[1]*da[1])+2.*(dx[0]*dj[0]+dx[1]*dj[1]);
188 double dt_try2 = -db2dt/d2b2dt2;
189 dt_try2 = -db2dt/(d2b2dt2+0.5*dt_try2*d3b2dt3);
193 if(dt_try2>_params.tol)
continue;
194 b2 += dt_try2*(db2dt+0.5*dt_try2*(d2b2dt2+dt_try2*d3b2dt3/3.));
195 dv[0] += dt_try2*(da[0]+0.5*dt_try2*dj[0]);
196 dv[1] += dt_try2*(da[1]+0.5*dt_try2*dj[1]);
197 if(dt_try2<=_params.tol)
break;
201 if((dt_try<=-0.5*dt) || (dt_try>0.5*dt) )
202 { dt_min_b2 = dt_try; b=-1.; vproj = -1.;
return; }
205 double min_b2 = b2begin;
206 if(b2<min_b2) { min_b2 = b2; dt_min_b2 = dt_try; }
207 b = (min_b2>=0) ? sqrt(min_b2) : -sqrt(-min_b2);
208 vproj = sqrt(dv[0]*dv[0]+dv[1]*dv[1]);
214 GPUAPI
void calc_transit_time_works(
const int& i,
const int& j,
const double& dt,
double dx[2],
double dv[2],
const double& b2begin,
double& db2dt,
double& dt_min_b2,
double& b,
double & vproj)
216 extern __shared__
char shared_mem[];
219 typedef typename calcForces_t::shared_data grav_t;
223 double acc_ix, acc_jx, acc_iy, acc_jy, jerk_ix, jerk_jx, jerk_iy, jerk_jy;
224 calcForces.sum(i,0,acc_ix,jerk_ix);
225 calcForces.sum(i,1,acc_iy,jerk_iy);
226 calcForces.sum(j,0,acc_jx,jerk_jx);
227 calcForces.sum(j,1,acc_jy,jerk_jy);
228 double da[2] = { acc_jx - acc_ix, acc_jy- acc_iy };
229 double dj[2] = { jerk_jx-jerk_ix, jerk_jy-jerk_iy };
230 double d2b2dt2 = 2.*(dv[0]*dv[0]+dv[1]*dv[1]+dx[0]*da[0]+dx[1]*da[1]);
231 double d3b2dt3 = 6.*(dv[0]*da[0]+dv[1]*da[1])+2.*(dx[0]*dj[0]+dx[1]*dj[1]);
232 double dt_try = -db2dt/d2b2dt2;
233 dt_try = -db2dt/(d2b2dt2+0.5*dt_try*d3b2dt3);
237 if((dt_try<-0.5*dt) || (dt_try>0.5*dt) )
238 { dt_min_b2 = dt_try; b=-1.; vproj = -1.;
return; }
241 double min_b2 = b2begin;
243 dx[0] += dt_try*(dv[0]+dt_try*0.5*(da[0]+dt_try*dj[0]/3.));
244 dx[1] += dt_try*(dv[1]+dt_try*0.5*(da[1]+dt_try*dj[1]/3.));
245 double b2 = (dx[0]*dx[0]+dx[1]*dx[1]);
246 if(b2<min_b2) { min_b2 = b2; dt_min_b2 = dt_try; }
248 b = (min_b2>0) ? sqrt(min_b2) : -sqrt(-min_b2);
249 dv[0] += dt_min_b2*(da[0]+0.5*dt_min_b2*dj[0]);
250 dv[1] += dt_min_b2*(da[1]+0.5*dt_min_b2*dj[1]);
251 vproj = sqrt(dv[0]*dv[0]+dv[1]*dv[1]);
256 GPUAPI
bool check_in_transit(
const int& thread_in_system,
const int& i,
const int& j,
const double dt)
258 double depth = _sys[j][2].pos()-_sys[i][2].pos();
259 if(!_params.log_on_occultation && (depth < 0.))
return false;
260 if(!_params.log_on_transit && (depth > 0.))
return false;
262 double dx[2] = { _sys[j][0].pos()-_sys[i][0].pos(), _sys[j][1].pos()-_sys[i][1].pos() };
263 double dv[2] = { _sys[j][0].vel()-_sys[i][0].vel(), _sys[j][1].vel()-_sys[i][1].vel() };
264 double b2begin = dx[0]*dx[0]+dx[1]*dx[1];
265 double db2dt = 2.*(dx[0]*dv[0]+dx[1]*dv[1]);
267 double radi = (_sys.num_body_attributes()>=1) ? _sys[i].attribute(0) : 0.;
268 double radj = (_sys.num_body_attributes()>=1) ? _sys[j].attribute(0) : 0.;
270 if( min(b2begin-0.5*dt*db2dt,b2begin+0.5*dt*db2dt)>square((radi+radj)*(1.+_params.tol)) )
274 const int nbod = _params.nbod;
277 double pos_step_end, vel_step_end;
278 if( (bid < nbod) && (cid < 3) ) {
279 pos_step_end = _sys[bid][cid].pos();
280 vel_step_end = _sys[bid][cid].vel();
284 double dt_min_b2, b, vproj;
285 if((nbod==3) && (nbod<=MAX_NBODIES))
287 const int nbod_hardwired = 3;
289 if(thread_in_system==0)
290 calc_transit_time_works<nbod_hardwired> (i,j,dt,dx,dv,b2begin,db2dt,dt_min_b2,b,vproj);
292 calc_transit_time<nbod_hardwired> (
thread_in_system,i,j,dt,dx,dv,b2begin,db2dt,pos_step_end,vel_step_end,dt_min_b2,b,vproj);
295 #if 1 // Can be set to zero to reduce compile times when testing
296 else if((nbod==4) && (nbod<=MAX_NBODIES))
298 const int nbod_hardwired = 4;
300 if(thread_in_system==0)
301 calc_transit_time_works<nbod_hardwired> (i,j,dt,dx,dv,b2begin,db2dt,dt_min_b2,b,vproj);
303 calc_transit_time<nbod_hardwired> (
thread_in_system,i,j,dt,dx,dv,b2begin,db2dt,pos_step_end,vel_step_end,dt_min_b2,b,vproj);
308 const int nbod_hardwired = 5;
310 if(thread_in_system==0)
311 calc_transit_time_works<nbod_hardwired> (i,j,dt,dx,dv,b2begin,db2dt,dt_min_b2,b,vproj);
313 calc_transit_time<nbod_hardwired> (
thread_in_system,i,j,dt,dx,dv,b2begin,db2dt,pos_step_end,vel_step_end,dt_min_b2,b,vproj);
316 else if((nbod==6) && (nbod<=MAX_NBODIES))
318 const int nbod_hardwired = 6;
320 if(thread_in_system==0)
321 calc_transit_time_works<nbod_hardwired> (i,j,dt,dx,dv,b2begin,db2dt,dt_min_b2,b,vproj);
323 calc_transit_time<nbod_hardwired> (
thread_in_system,i,j,dt,dx,dv,b2begin,db2dt,pos_step_end,vel_step_end,dt_min_b2,b,vproj);
326 else if((nbod==7) && (nbod<=MAX_NBODIES))
328 const int nbod_hardwired = 7;
330 if(thread_in_system==0)
331 calc_transit_time_works<nbod_hardwired> (i,j,dt,dx,dv,b2begin,db2dt,dt_min_b2,b,vproj);
333 calc_transit_time<nbod_hardwired> (
thread_in_system,i,j,dt,dx,dv,b2begin,db2dt,pos_step_end,vel_step_end,dt_min_b2,b,vproj);
336 else if((nbod==8) && (nbod<=MAX_NBODIES))
338 const int nbod_hardwired = 8;
340 if(thread_in_system==0)
341 calc_transit_time_works<nbod_hardwired> (i,j,dt,dx,dv,b2begin,db2dt,dt_min_b2,b,vproj);
343 calc_transit_time<nbod_hardwired> (
thread_in_system,i,j,dt,dx,dv,b2begin,db2dt,pos_step_end,vel_step_end,dt_min_b2,b,vproj);
351 if( (bid < nbod) && (cid < 3) ) {
352 _sys[bid][cid].pos() = pos_step_end;
353 _sys[bid][cid].vel() = vel_step_end;
359 if((thread_in_system==0) && (vproj>=0.) )
361 if(_sys.num_body_attributes()>=1)
363 if (depth>0.) { b /= radi; vproj /= radi; }
364 else { b /= radj; vproj /= radj; }
367 if((dt_min_b2>=-0.5*dt)&&(dt_min_b2<0.5*dt))
369 double tout = _sys.time()+dt_min_b2;
371 log::event(_log,event_id,tout,_sys.id(),j,b,vproj);
377 if( (bid < nbod) && (cid < 3) ) {
378 _sys[bid][cid].pos() = pos_step_end;
379 _sys[bid][cid].vel() = vel_step_end;
382 if((thread_in_system==0) && (vproj>=0.) )
389 GPUAPI
int pass_two (
const int thread_in_system)
394 for(
int b = 1; b < _sys.nbod(); b++)
396 condition_met = condition_met ||
397 check_in_transit(thread_in_system,0,b,_params.dt);
401 return condition_met;
406 GPUAPI log_transit(
const params& p,ensemble::SystemRef& s,log_t& l)
407 :_params(p),_sys(s),_log(l) {}