28 namespace swarm {
namespace gpu {
namespace bppt {
32 const static bool adaptive_time_step =
false;
33 const static bool conditional_accept_step =
false;
38 const static bool adaptive_time_step =
true;
39 const static bool conditional_accept_step =
true;
50 template<
class AdaptationStyle,
class Monitor,
template<
class T>
class Gravitation >
53 typedef Monitor monitor_t;
54 typedef typename monitor_t::params mon_params_t;
56 double _min_time_step;
57 double _max_time_step;
58 double _error_tolerance;
60 mon_params_t _mon_params;
63 rkck(
const config& cfg):
base(cfg),_min_time_step(0.001),_max_time_step(0.1), _mon_params(cfg) {
64 if(!cfg.count(
"min_time_step")) ERROR(
"Integrator rkck requires a min timestep ('min time step' keyword in the config file).");
65 _min_time_step = atof(cfg.at(
"min_time_step").c_str());
66 if(!cfg.count(
"max_time_step")) ERROR(
"Integrator rkck requires a max timestep ('max time step' keyword in the config file).");
67 _max_time_step = atof(cfg.at(
"max_time_step").c_str());
69 if(!cfg.count(
"error_tolerance")) ERROR(
"Integrator rkck requires a error tolerance ('error tolerance' keyword in the config file).");
70 _error_tolerance = atof(cfg.at(
"error_tolerance").c_str());
86 GPUAPI
bool is_in_body_component_grid(
const int b,
const int c,
const int nbod)
87 {
return ((b < nbod) && (c < 3)); }
91 __device__
void kernel(T compile_time_param){
96 const double b1 = 1.0 / 5.0;
98 const double b2[] = { 3.0 / 40.0, 9.0 / 40.0 };
100 const double b3[] = { 0.3, -0.9, 1.2 };
102 const double b4[] = { -11.0 / 54.0, 2.5, -70.0 / 27.0, 35.0 / 27.0 };
104 const double b5[] = { 1631.0 / 55296.0, 175.0 / 512.0, 575.0 / 13824.0, 44275.0 / 110592.0, 253.0 / 4096.0 };
106 const double b6[] = { 37.0 / 378.0, 0, 250.0 / 621.0, 125.0 / 594.0, 0 , 512.0 / 1771.0 } ;
108 const double ecc[] = { 37.0 / 378.0 - 2825.0 / 27648.0, 0.0, 250.0 / 621.0 - 18575.0 / 48384.0, 125.0 / 594.0 - 13525.0 / 55296.0, -277.00 / 14336.0, 512.0 / 1771.0 - 0.25 };
113 typedef Gravitation<T> Grav;
114 typedef typename Grav::shared_data grav_t;
118 const int nbod = T::n;
125 monitor_t montest(_mon_params,sys,*
_log) ;
133 double time_step = _max_time_step;
136 double pos = 0, vel = 0 ;
137 if( is_in_body_component_grid(b,c,nbod) )
138 pos = sys[b][c].pos() , vel = sys[b][
c].vel();
143 for(
int iter = 0 ; (iter < _iteration_count) && sys.is_active() ; iter ++ ) {
145 double h = time_step;
152 double p0 = pos, v0 = vel;
158 double p1 = pos + h * b1 * k1_vel;
159 double v1 = vel + h * b1 * k1_acc;
165 double p2 = pos + h * ( b2[0] * k1_vel + b2[1] * k2_vel );
166 double v2 = vel + h * ( b2[0] * k1_acc + b2[1] * k2_acc );
172 double p3 = pos + h * ( b3[0] * k1_vel + b3[1] * k2_vel + b3[2] * k3_vel );
173 double v3 = vel + h * ( b3[0] * k1_acc + b3[1] * k2_acc + b3[2] * k3_acc );
179 double p4 = pos + h * ( b4[0] * k1_vel + b4[1] * k2_vel + b4[2] * k3_vel + b4[3] * k4_vel );
180 double v4 = vel + h * ( b4[0] * k1_acc + b4[1] * k2_acc + b4[2] * k3_acc + b4[3] * k4_acc );
186 double p5 = pos + h * ( b5[0] * k1_vel + b5[1] * k2_vel + b5[2] * k3_vel + b5[3] * k4_vel + b5[4] * k5_vel );
187 double v5 = vel + h * ( b5[0] * k1_acc + b5[1] * k2_acc + b5[2] * k3_acc + b5[3] * k4_acc + b5[4] * k5_acc );
193 double p6 = pos + h * ( b6[0] * k1_vel + b6[1] * k2_vel + b6[2] * k3_vel + b6[3] * k4_vel + b6[4] * k5_vel + b6[5] * k6_vel );
194 double v6 = vel + h * ( b6[0] * k1_acc + b6[1] * k2_acc + b6[2] * k3_acc + b6[3] * k4_acc + b6[4] * k5_acc + b6[5] * k6_acc );
198 double pos_error = h * ( ecc[0] * k1_vel + ecc[1] * k2_vel + ecc[2] * k3_vel + ecc[3] * k4_vel + ecc[4] * k5_vel + ecc[5] * k6_vel );
199 double vel_error = h * ( ecc[0] * k1_acc + ecc[1] * k2_acc + ecc[2] * k3_acc + ecc[3] * k4_acc + ecc[4] * k5_acc + ecc[5] * k6_acc );
202 bool accept_step =
true;
204 if( AdaptationStyle::adaptive_time_step ) {
206 const int integrator_order = 5;
208 const float step_grow_power = -1./(integrator_order+1.);
210 const float step_shrink_power = -1./integrator_order;
212 const float step_guess_safety_factor = 0.9;
214 const float step_grow_max_factor = 5.0;
216 const float step_shrink_min_factor = 0.2;
219 if( is_in_body_component_grid(b,c,nbod) ) {
221 sys[b][
c].pos() = p6 * p6 , sys[b][
c].vel() = v6 * v6;
222 shared_mag[0][b][
c].value() = pos_error * pos_error;
223 shared_mag[1][b][
c].value() = vel_error * vel_error;
227 if( is_in_body_component_grid(b,c,nbod) ) {
228 if ( (c == 0) && (b == 0) ) {
230 double max_error = 0;
231 for(
int i = 0; i < nbod ; i++){
232 double pos_error_mag = shared_mag[0][i][0].value() + shared_mag[0][i][1].value() + shared_mag[0][i][2].value();
233 double pos_mag = sys[i][0].pos() + sys[i][1].pos() + sys[i][2].pos();
234 double pe = pos_error_mag / pos_mag ;
236 double vel_error_mag = shared_mag[1][i][0].value() + shared_mag[1][i][1].value() + shared_mag[1][i][2].value();
237 double vel_mag = sys[i][0].vel() + sys[i][1].vel() + sys[i][2].vel();
238 double ve = vel_error_mag / vel_mag ;
240 max_error = max ( max( pe, ve) , max_error );
243 double normalized_error = max_error / _error_tolerance;
246 double step_guess_power = (normalized_error<1.) ? step_grow_power : step_shrink_power;
250 double step_change_factor = ((normalized_error<0.5)||(normalized_error>1.0)) ? step_guess_safety_factor*pow(normalized_error,0.5*step_guess_power) : 1.0;
254 double new_time_step = (normalized_error>1.) ? max( time_step * max(step_change_factor,step_shrink_min_factor), _min_time_step )
255 : min( time_step * max(min(step_change_factor,step_grow_max_factor),1.0), _max_time_step );
257 bool accept = ( normalized_error < 1.0 ) || (abs(time_step - new_time_step) < 1e-10) ;
259 shared_mag[0][0][0].value() = accept ? 0.0 : 1.0;
260 shared_mag[0][0][1].value() = new_time_step;
266 time_step = shared_mag[0][0][1].value();
267 accept_step = AdaptationStyle::conditional_accept_step ? (shared_mag[0][0][0].value() == 0.0) :
true;
278 if( is_in_body_component_grid(b,c,nbod) )
279 sys[b][
c].pos() = pos , sys[b][
c].vel() = vel;
286 { sys.set_inactive(); }