00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "dyn.h"
00010 #include "chydro.h"
00011
00012 #ifdef TOOLBOX
00013
00014 void accumulate_acceleration(dyn& bj,
00015 dyn& bi,
00016 real eps_squared,
00017 dyn *& bm)
00018
00019 {
00020 bm = NULL;
00021 if(bj.get_oldest_daughter() != NULL){
00022 for(dyn * bb = bj.get_oldest_daughter();bb != NULL;
00023 bb = bb->get_younger_sister()){
00024 accumulate_acceleration(*bb,bi,eps_squared, bm);
00025 if (bm != NULL)
00026 return;
00027 }
00028 }else{
00029 if(&bi != &bj){
00030 vector d_pos = bi.get_pos() - bj.get_pos();
00031 real d_pos_squared = d_pos * d_pos;
00032 real sum_of_stellar_r_eff =
00033 get_effective_radius(&bi) + get_effective_radius(&bj);
00034 if (sum_of_stellar_r_eff * sum_of_stellar_r_eff > d_pos_squared)
00035 {
00036 bm = &bj;
00037 return;
00038 }
00039
00040 real soft_d_pos_squared = d_pos_squared + eps_squared;
00041
00042 real inverse_d_pos_cubed =
00043 1 / ( soft_d_pos_squared * sqrt( soft_d_pos_squared ));
00044
00045 bi.inc_acc(-inverse_d_pos_cubed * bj.get_mass() * d_pos);
00046 }
00047 }
00048 }
00049
00050
00051 void calculate_acceleration(dyn & bj,
00052 dyn & b,
00053 real eps_squared,
00054 dyn *& bm1,
00055 dyn *& bm2)
00056 {
00057 bm1 = bm2 = NULL;
00058 if(b.get_oldest_daughter() != NULL){
00059 for(dyn * bb = b.get_oldest_daughter();bb != NULL;
00060 bb = bb->get_younger_sister()){
00061 calculate_acceleration(bj,*bb,eps_squared, bm1, bm2);
00062 if (bm1 != NULL)
00063 return;
00064 }
00065 }else{
00066 b.clear_acc();
00067 dyn * bm;
00068 accumulate_acceleration(bj,b,eps_squared, bm);
00069 if (bm != NULL)
00070 {
00071 bm1 = &b;
00072 bm2 = bm;
00073 }
00074 }
00075 }
00076
00077 void predict_step( dyn &b,
00078 real dt)
00079 {
00080 if(b.get_oldest_daughter() !=NULL){
00081 for(dyn * bb = b.get_oldest_daughter();bb != NULL;
00082 bb = bb->get_younger_sister()){
00083 predict_step(*bb,dt);
00084 }
00085 }else{
00086 b.inc_vel( 0.5 * dt * b.get_acc() );
00087 b.inc_pos( dt * b.get_vel() );
00088 }
00089 }
00090
00091 void old_correct_step( dyn &b,
00092 real dt)
00093 {
00094
00095
00096
00097 if(b.get_oldest_daughter() != NULL){
00098 old_correct_step(*b.get_oldest_daughter(),dt);
00099 }else{
00100 b.inc_vel( 0.5 * dt * b.get_acc() );
00101 }
00102 if(b.get_younger_sister() != NULL){
00103 old_correct_step(*b.get_younger_sister(),dt);
00104 }
00105 }
00106
00107 void correct_step( dyn &b,
00108 real dt)
00109 {
00110
00111
00112
00113 if(b.get_oldest_daughter() !=NULL){
00114 for(dyn * bb = b.get_oldest_daughter();bb != NULL;
00115 bb = bb->get_younger_sister()){
00116 correct_step(*bb,dt);
00117 }
00118 }else{
00119 b.inc_vel( 0.5 * dt * b.get_acc() );
00120 }
00121 }
00122
00123
00124
00125
00126
00127 void detach_node_from_general_tree(dyn & b)
00128 {
00129 if(&b == NULL){
00130 cerr << "Warning: detach_node_from_general_tree, b is null\n";
00131 return;
00132 }
00133
00134 dyn * parent = b.get_parent();
00135
00136
00137 if(parent == NULL){
00138 cerr << "Warning: detach_node_from_general_tree, b has no parent\n";
00139 return;
00140 }
00141
00142 b.set_parent(NULL);
00143
00144 dyn * elder_sister = b.get_elder_sister();
00145 dyn * younger_sister = b.get_younger_sister();
00146
00147 if (parent->get_oldest_daughter() == &b){
00148 parent->set_oldest_daughter(younger_sister);
00149 }
00150
00151 if(elder_sister != NULL){
00152 elder_sister->set_younger_sister(younger_sister);
00153 }
00154 if(younger_sister != NULL){
00155 younger_sister->set_elder_sister(elder_sister);
00156 }
00157 }
00158
00159
00160
00161
00162
00163
00164 void add_node(dyn &b, dyn & parent)
00165 {
00166 if(&b == NULL){
00167 cerr << "Warning:add_node, b is null\n";
00168 return;
00169 }
00170
00171 if(&parent == NULL){
00172 cerr << "Warning:add_node, parent is null\n";
00173 return;
00174 }
00175
00176
00177 dyn * ex = parent.get_oldest_daughter();
00178 if(ex != NULL){
00179 ex->set_elder_sister(&b);
00180 }
00181
00182 parent.set_oldest_daughter(&b);
00183
00184 b.set_elder_sister(NULL);
00185 b.set_younger_sister(ex);
00186 b.set_parent(&parent);
00187 }
00188
00189 void merge(dyn * bm1,
00190 dyn * bm2,
00191 real t)
00192 {
00193 dyn * bm = new dyn();
00194
00195 cerr << "entering merge(" << bm1->get_index() << ", " << bm2->get_index()
00196 << ") with r1 = " << bm1->get_pos() << "\n "
00197 << " and r2 = " << bm2->get_pos() << "\n "
00198 << " at t = " << t << endl;
00199
00200 real m1 = bm1->get_mass();
00201 real m2 = bm2->get_mass();
00202 real m_tot = m1 + m2;
00203
00204 bm->set_mass(m_tot);
00205 bm->set_pos((m1*bm1->get_pos() + m2*bm2->get_pos())/m_tot);
00206 bm->set_vel((m1*bm1->get_vel() + m2*bm2->get_vel())/m_tot);
00207
00208 real new_r_eff = get_effective_radius(bm1) + get_effective_radius(bm2);
00209
00210 real new_r_core = get_core_radius(bm1) + get_core_radius(bm2);
00211 real new_m_core = get_core_mass(bm1) + get_core_mass(bm2);
00212
00213 addchydro(bm, new_r_eff, new_r_core, new_m_core);
00214
00215 dyn * root = bm1->get_parent();
00216
00217 detach_node_from_general_tree(*bm1);
00218 detach_node_from_general_tree(*bm2);
00219
00220 add_node(*bm, *root);
00221 }
00222
00223 void calculate_acc_and_merge(dyn & bj,
00224 dyn & b,
00225 real eps_squared,
00226 real t)
00227 {
00228 dyn * bm1;
00229 dyn * bm2;
00230
00231 calculate_acceleration(bj, b, eps_squared, bm1, bm2);
00232
00233 while (bm1 != NULL)
00234 {
00235 merge(bm1, bm2, t);
00236 calculate_acceleration(bj, b, eps_squared, bm1, bm2);
00237 }
00238 }
00239
00240 void step(real& t,
00241 dyn* b,
00242 real dt,
00243 real eps)
00244 {
00245 t += dt;
00246
00247 predict_step(*b,dt);
00248
00249 calculate_acc_and_merge(*b,*b, eps*eps, t);
00250
00251 correct_step(*b,dt);
00252 }
00253
00254 void evolve(real& t,
00255 dyn* b,
00256 real delta_t,
00257 real dt,
00258 real dt_out,
00259 real dt_snap,
00260 real eps)
00261 {
00262 real t_end = t + delta_t;
00263 real t_out = t + dt_out;
00264 real t_snap = t + dt_snap;
00265 int steps = 0;
00266
00267 calculate_acc_and_merge(*b, *b, eps*eps, t);
00268
00269 while (t < t_end) {
00270 step(t, b, dt, eps);
00271 steps++;
00272
00273
00274
00275 if (t >= t_out) {
00276 cerr << "Time = " << t << " steps = " << steps << endl;
00277 t_out += dt_out;
00278 }
00279
00280
00281
00282 if (t >= t_snap || t >= t_end) {
00283 cerr<<"time = "<<t<<endl;
00284 put_node(cout, *b);
00285 cout << flush;
00286 t_snap += dt_snap;
00287 }
00288 }
00289 }
00290
00291 main(int argc, char **argv)
00292 {
00293 dyn* b;
00294 real t = 0;
00295
00296 real delta_t = 1;
00297 real dt = 0.02;
00298 real dt_out;
00299 real dt_snap;
00300 real eps = 0.05;
00301 char *comment;
00302
00303 extern char *poptarg;
00304 int pgetopt(int, char **, char *), c;
00305
00306 bool a_flag = FALSE;
00307 bool c_flag = FALSE;
00308 bool d_flag = FALSE;
00309 bool D_flag = FALSE;
00310 bool e_flag = FALSE;
00311 bool q_flag = FALSE;
00312 bool t_flag = FALSE;
00313
00314 while ((c = pgetopt(argc, argv, "c:t:d:D:e:")) != -1)
00315 switch(c)
00316 {
00317 case 'a': a_flag = TRUE;
00318 dt = atof(poptarg);
00319 break;
00320 case 'c': c_flag = TRUE;
00321 comment = poptarg;
00322 break;
00323 case 'd': d_flag = TRUE;
00324 dt_out = atof(poptarg);
00325 break;
00326 case 'D': D_flag = TRUE;
00327 dt_snap = atof(poptarg);
00328 break;
00329 case 'e': e_flag = TRUE;
00330 eps = atof(poptarg);
00331 break;
00332 case 'q': q_flag = TRUE;
00333 break;
00334 case 't': t_flag = TRUE;
00335 delta_t = atof(poptarg);
00336 break;
00337 case '?': cerr <<
00338 "usage: chydro_leapfrog -t # -a # -e # -D # -d # " <<
00339 "[-c \"..\"]\n" <<
00340 "for t (time span), a (time step length), " <<
00341 "d (output interval) D (snapshot output interval) " <<
00342 "and e (softening length)\n";
00343 exit(1);
00344 }
00345
00346 if (!q_flag) {
00347
00348
00349
00350 if (!t_flag) cerr << "default delta_t = " << delta_t << "\n";
00351 if (!a_flag) cerr << "default dt = " << dt << "\n";
00352 if (!d_flag) cerr << "default dt_out = " << dt_out << "\n";
00353 if (!e_flag) cerr << "default eps = " << eps << "\n";
00354 }
00355
00356 if (!D_flag) dt_snap = delta_t;
00357
00358 b = get_dyn(cin, new_hydro);
00359
00360 if (c_flag == TRUE) b->log_comment(comment);
00361 b->log_history(argc, argv);
00362
00363 evolve(t, b, delta_t, dt, dt_out, dt_snap, eps);
00364 }
00365
00366 #endif