00001
00002
00003
00004
00005
00006 #include "sdyn.h"
00007
00008 local int code_collision_flag(sdyn *bi, sdyn *bj) {
00009
00010 #if 0
00011 if(bi==bj) {
00012 cerr << "bi==bj in code_collision_flag()" << endl;
00013 exit(-1);
00014 }
00015
00016
00017
00018 real r = abs(bi->get_pos() - bj->get_pos());
00019
00020
00021
00022 int imin = min(bi->get_index(), bj->get_index());
00023 int imax = max(bi->get_index(), bj->get_index());
00024 if(imin==imax) {
00025 cerr << "imin==imax in code_collision_flag()"<< endl;
00026 exit(-1);
00027 }
00028
00029 int ci = -1;
00030 switch(imin) {
00031 case 1: if(imax==2) ci = 1;
00032 else if(imax==3) ci = 2;
00033 else ci = 3;
00034 break;
00035 case 2: if(imax==3) ci = 4;
00036 else ci = 5;
00037 break;
00038 case 3: ci = 6;
00039 break;
00040 default: cerr << "No default value in code_collision_flag()" << endl;
00041 exit(-1);
00042 };
00043
00044 #endif
00045 int ci = 2;
00046 return ci;
00047 }
00048
00049
00050 local void pp(sdyn* b, ostream & s, int level = 0) {
00051
00052 s.precision(4);
00053
00054 for (int i = 0; i < 2*level; i++) s << " ";
00055
00056 b->pretty_print_node(s);
00057 s << " \t"<< b->get_mass() << " \t"
00058 << b->get_pos() << " "
00059 << b->get_vel() <<endl;
00060
00061 for (sdyn * daughter = b->get_oldest_daughter();
00062 daughter != NULL;
00063 daughter = daughter->get_younger_sister())
00064 pp(daughter, s, level + 1);
00065 }
00066
00067 void sdyn::accumulate_new_acc_and_jerk_from_new(
00068 sdyn * bj,
00069 real eps2,
00070 int no_diag_flag,
00071 int & collision_flag)
00072 {
00073 if(bj->get_oldest_daughter() != NULL)
00074 for_all_daughters(sdyn, bj, bb)
00075 accumulate_new_acc_and_jerk_from_new(bb, eps2,
00076 no_diag_flag, collision_flag);
00077 else
00078 if(this != bj)
00079 {
00080 vector d_pos = new_pos - bj->get_new_pos();
00081 vector d_vel = new_vel - bj->get_new_vel();
00082 real r2 = d_pos*d_pos;
00083 if (r2 < (radius + bj->get_radius())
00084 * (radius + bj->get_radius())) {
00085 collision_flag = code_collision_flag(this, bj);
00086
00087
00088
00089 }
00090
00091 real r2inv = 1.0/(r2 + eps2);
00092 real a3 = -3.0*(d_pos*d_vel)*r2inv;
00093 real rinv = sqrt(r2inv);
00094 real mrinv = bj->get_mass() * rinv;
00095 new_pot -= mrinv;
00096 real mr3inv = mrinv * r2inv;
00097 new_acc -= mr3inv*d_pos;
00098 new_jerk -= mr3inv*(d_vel + a3*d_pos);
00099
00100 if (! no_diag_flag)
00101 {
00102 if (nn_dr2 > r2)
00103 {
00104 nn_dr2 = r2;
00105 nn_label = bj->get_index();
00106 }
00107 if (min_nn_dr2 > r2)
00108 {
00109 min_nn_dr2 = r2;
00110 min_nn_label = bj->get_index();
00111 }
00112 }
00113
00114 real encounter_time_squared = 1 / (r2inv * d_vel * d_vel);
00115 if (min_encounter_time_sq > encounter_time_squared)
00116 min_encounter_time_sq = encounter_time_squared;
00117
00118 real inverse_free_fall_time_squared =
00119 r2inv * rinv * (mass + bj->get_mass());
00120 if (min_free_fall_time_sq == VERY_LARGE_NUMBER ||
00121 min_free_fall_time_sq * inverse_free_fall_time_squared > 1)
00122 min_free_fall_time_sq = 1/inverse_free_fall_time_squared;
00123 }
00124 }
00125
00126 void sdyn::calculate_new_acc_and_jerk_from_new(sdyn * b, real eps_squared,
00127 int no_diag_flag,
00128 int & collision_flag) {
00129
00130 if(oldest_daughter != NULL)
00131 {
00132 collision_flag = 0;
00133
00134 if (! no_diag_flag)
00135 {
00136 nn_label = 0;
00137 for_all_daughters(sdyn, this, c)
00138 c->set_nn_dr2(VERY_LARGE_NUMBER);
00139 }
00140
00141 for_all_daughters(sdyn, this, bb)
00142 bb->calculate_new_acc_and_jerk_from_new(b, eps_squared,
00143 no_diag_flag,
00144 collision_flag);
00145 if (! no_diag_flag)
00146 {
00147 for_all_daughters(sdyn, this, d)
00148 {
00149 if (d->get_init_nn_label() <= 0)
00150 d->set_init_nn_label(d->get_nn_label());
00151 if (d->get_init_nn_label() != d->get_nn_label())
00152 d->set_nn_change_flag(1);
00153 }
00154
00155 real e_tot = 0;
00156 for_all_daughters(sdyn, this, bbb)
00157 e_tot += 0.5 * bbb->get_mass() * (bbb->get_new_pot()
00158 + bbb->get_new_vel() * bbb->get_new_vel());
00159 if (de_tot_abs_max < abs(e_tot - e_tot_init))
00160 de_tot_abs_max = abs(e_tot - e_tot_init);
00161 }
00162 }
00163 else
00164 {
00165 new_pot = 0;
00166 new_acc = new_jerk = 0;
00167 min_encounter_time_sq = min_free_fall_time_sq = VERY_LARGE_NUMBER;
00168 accumulate_new_acc_and_jerk_from_new(b, eps_squared, no_diag_flag,
00169 collision_flag);
00170 }
00171 }
00172
00173 void sdyn::taylor_pred_new_pos_and_vel(const real dt)
00174 {
00175 taylor_pred_new_pos(dt);
00176 taylor_pred_new_vel(dt);
00177 }
00178
00179 void sdyn::correct_new_acc_and_jerk(const real new_dt, const real prev_new_dt)
00180 {
00181 if (new_dt == prev_new_dt)
00182 return;
00183
00184 real dt_off = new_dt - 0.5 * prev_new_dt;
00185
00186 real theta = 0.5 * prev_new_dt;
00187 real tau = dt_off / theta;
00188
00189 real inv_theta = 1 / theta;
00190 real tau2 = tau * tau;
00191 real tau3 = tau2 * tau;
00192 vector prev_new_acc = new_acc;
00193 vector prev_new_jerk = new_jerk;
00194
00195 new_acc = 0.25 * (
00196 acc * (2 - 3 * tau + tau3)
00197 + prev_new_acc * (2 + 3 * tau - tau3)
00198 + jerk * theta * (1 - tau - tau2 + tau3)
00199 + prev_new_jerk * theta * (-1 - tau + tau2 + tau3)
00200 );
00201
00202 new_jerk = 0.25 * (
00203 acc * inv_theta * 3 * (-1 + tau2)
00204 + prev_new_acc * inv_theta * 3 * (1 - tau2)
00205 + jerk * (-1 - 2*tau + 3*tau2)
00206 + prev_new_jerk * (-1 + 2*tau + 3*tau2)
00207 );
00208 }
00209
00210 void sdyn::correct_new_pos_and_vel(const real new_dt)
00211 {
00212 real new_dt2 = new_dt * new_dt;
00213 real new_dt3 = new_dt2 * new_dt;
00214
00215 new_vel = vel + new_dt * (new_acc + acc)/2
00216 - new_dt2 * (new_jerk - jerk)/12;
00217
00218 new_pos = pos + new_dt * (new_vel + vel)/2
00219 - new_dt2 * (new_acc - acc)/12;
00220 }
00221
00222