00001
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "dyn.h"
00015
00016 #ifdef TOOLBOX
00017
00018 #define BUFF_LENGTH 128
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #define NBODY_MAX 10
00029 #define NNODE_MAX (2 * NBODY_MAX - 1)
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 #define N_ADMIN (3 + NBODY_MAX)
00046
00047 #define Ndaughter(ptr, offset) ((ptr)[(offset)][0])
00048
00049 #define Visibility(ptr, offset) ((ptr)[(offset)][1])
00050 #define COVERED 1
00051 #define VISIBLE 2
00052
00053 #define Stability(ptr, offset) ((ptr)[(offset)][2])
00054 #define STABLE 1
00055 #define UNSTABLE 2
00056 #define BARELY_UNBOUND 3
00057 #define STRONGLY_UNBOUND 4
00058 #define UNKNOWN 5
00059
00060 #define Daughter(ptr, offset, i) ((ptr)[(offset)][3 + (i)])
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071 #define N_STRUCT 3
00072
00073 #define Radius(ptr, offset) ((ptr)[(offset)][0])
00074 #define Apair(ptr, offset) ((ptr)[(offset)][1])
00075 #define Epair(ptr, offset) ((ptr)[(offset)][2])
00076
00077 local void append_object(char hier_string[BUFF_LENGTH],
00078 char tmp_string[BUFF_LENGTH]);
00079 local int count_visible_nodes(int admin_table[NNODE_MAX][N_ADMIN],
00080 int nnode);
00081 local void dissolve_node(dyn * b, int * nnodeptr, int i,
00082 int admin_table[NNODE_MAX][N_ADMIN],
00083 real struct_table[NNODE_MAX][N_STRUCT],
00084 real dist_table[NNODE_MAX][NNODE_MAX]);
00085 local bool dissolve_visible_strongly_unbound_nodes(dyn *b, int *nnodeptr,
00086 int admin_table[NNODE_MAX][N_ADMIN],
00087 real struct_table[NNODE_MAX][N_STRUCT],
00088 real dist_table[NNODE_MAX][NNODE_MAX]);
00089 local void drop_tailnode(int * nnodeptr,
00090 int admin_table[NNODE_MAX][N_ADMIN]);
00091 local char *end_of_string(char * the_string);
00092 local void find_namenumbers(dyn *, char **);
00093 local bool find_new_node(dyn * b, int * nnodeptr,
00094 int admin_table[NNODE_MAX][N_ADMIN],
00095 real struct_table[NNODE_MAX][N_STRUCT],
00096 real dist_table[NNODE_MAX][NNODE_MAX], int k);
00097 local void get_binary_parameters(dyn *g1, dyn *g2, real * aptr, real * eptr);
00098 local void init_admin_table(int admin_table[NNODE_MAX][N_ADMIN]);
00099 local void init_dist_table(dyn *b, real dist_table[NNODE_MAX][NNODE_MAX]);
00100 local void init_struct_table(real struct_table[NNODE_MAX][N_STRUCT]);
00101 local void init_tuple(int tuple[NBODY_MAX],
00102 int admin_table[NNODE_MAX][N_ADMIN], int n);
00103 local void install_com_dynamics(dyn * b, int nnode,
00104 int tuple[NBODY_MAX], int k);
00105 local void install_node(int tuple[NBODY_MAX], dyn * b, int * nnodeptr,
00106 int admin_table[NNODE_MAX][N_ADMIN],
00107 real struct_table[NNODE_MAX][N_STRUCT],
00108 real dist_table[NNODE_MAX][NNODE_MAX],
00109 real radius, int k);
00110 local bool is_approximately_isolated_tuple(int tuple[NBODY_MAX], int nnode,
00111 int admin_table[NNODE_MAX][N_ADMIN],
00112 real dist_table[NNODE_MAX][NNODE_MAX],
00113 int k);
00114 local bool is_isolated_tuple(int tuple[NBODY_MAX], dyn * b, int nnode,
00115 int admin_table[NNODE_MAX][N_ADMIN],
00116 real struct_table[NNODE_MAX][N_STRUCT],
00117 real * radiusptr, int k);
00118 local bool is_new_node(int tuple[NBODY_MAX], dyn * b, int * nnodeptr,
00119 int admin_table[NNODE_MAX][N_ADMIN],
00120 real struct_table[NNODE_MAX][N_STRUCT],
00121 real dist_table[NNODE_MAX][NNODE_MAX], int k);
00122 local void iterate_dissolve_visible_strongly_unbound_nodes(dyn * b,
00123 int * nnodeptr,
00124 int admin_table[NNODE_MAX][N_ADMIN],
00125 real struct_table[NNODE_MAX][N_STRUCT],
00126 real dist_table[NNODE_MAX][NNODE_MAX]);
00127 local void iterate_find_new_node(dyn * b, int * nnodeptr,
00128 int admin_table[NNODE_MAX][N_ADMIN],
00129 real struct_table[NNODE_MAX][N_STRUCT],
00130 real dist_table[NNODE_MAX][NNODE_MAX],int k);
00131 local void map_to_integers(char hier_string[BUFF_LENGTH],
00132 int unordered[BUFF_LENGTH], int * nptr);
00133 local int next_element(int element, int tuple[NBODY_MAX], int n);
00134 local bool next_tuple(int tuple[NBODY_MAX], int k, int n,
00135 int ordered_tuple[NBODY_MAX]);
00136 local int old_ranking(int old_array[BUFF_LENGTH],
00137 int new_array[BUFF_LENGTH], int i, int n);
00138 local void print_binary_parameters(char node_report[BUFF_LENGTH],
00139 real struct_table[NNODE_MAX][N_STRUCT],
00140 int member);
00141 local void print_group_internal_structure(int nnode,
00142 int admin_table[NNODE_MAX][N_ADMIN],
00143 real struct_table[NNODE_MAX][N_STRUCT],
00144 char * name_table[NNODE_MAX]);
00145 local void print_node(char node_report[BUFF_LENGTH],
00146 int admin_table[NNODE_MAX][N_ADMIN],
00147 real struct_table[NNODE_MAX][N_STRUCT],
00148 char * name_table[NNODE_MAX],
00149 int member);
00150 local void print_radius(char node_report[BUFF_LENGTH],
00151 real struct_table[NNODE_MAX][N_STRUCT], int member);
00152 local void select_object(char tmp_string[BUFF_LENGTH],
00153 char hier_string[BUFF_LENGTH], int member);
00154 local void sort_int_array(int old_array[BUFF_LENGTH],
00155 int new_array[BUFF_LENGTH], int n);
00156 local void swap_body_nodes(dyn *, dyn *);
00157 local void swap_nodes(dyn * b, int nnode, int i1, int i2,
00158 int admin_table[NNODE_MAX][N_ADMIN],
00159 real struct_table[NNODE_MAX][N_STRUCT],
00160 real dist_table[NNODE_MAX][NNODE_MAX]);
00161 local real tuple_kin_energy(int tuple[NBODY_MAX], dyn * b, int k);
00162 local real tuple_pot_energy(int tuple[NBODY_MAX], dyn * b,
00163 real dist_table[NNODE_MAX][NNODE_MAX], int k);
00164 local real tuple_radius(int tuple[NBODY_MAX], dyn * b,
00165 real struct_table[NNODE_MAX][N_STRUCT],
00166 vector & com_pos, int k);
00167 local void unwrap_string(char substring[BUFF_LENGTH],
00168 char * head_ptr, char * tail_ptr);
00169 local void update_admin_table(int tuple[NBODY_MAX], dyn * b, int nnode,
00170 int admin_table[NNODE_MAX][N_ADMIN],
00171 real struct_table[NNODE_MAX][N_STRUCT],
00172 real dist_table[NNODE_MAX][NNODE_MAX], int k);
00173 local void update_dist_table(dyn * b, int nnode,
00174 real dist_table[NNODE_MAX][NNODE_MAX]);
00175 local void update_struct_table(int nnode,
00176 real struct_table[NNODE_MAX][N_STRUCT],
00177 real radius, real a, real e, int k);
00178 local void wrap_string(char substring[BUFF_LENGTH],
00179 char head_char, char tail_char);
00180
00181
00182
00183
00184
00185 void find_group_internal_structure(dyn * b
00186
00187 )
00188
00189 {
00190
00191 int nnode;
00192 int *nnodeptr;
00193 int admin_table[NNODE_MAX][N_ADMIN];
00194 char *name_table[NNODE_MAX];
00195 real struct_table[NNODE_MAX][N_STRUCT];
00196 real dist_table[NNODE_MAX][NNODE_MAX];
00197 dyn *bi;
00198
00199 for (nnode = 0, bi = b->get_oldest_daughter(); bi != NULL;
00200 bi = bi->get_younger_sister())
00201 nnode++;
00202
00203 if (nnode > NBODY_MAX)
00204 {
00205 cerr << "find_group_internal_structure: n = " << nnode
00206 << " > NBODY_MAX = " << NBODY_MAX << "\n";
00207 exit(1);
00208 }
00209
00210 find_namenumbers(b, name_table);
00211
00212 init_dist_table(b, dist_table);
00213 init_admin_table(admin_table);
00214 init_struct_table(struct_table);
00215
00216 nnodeptr = &nnode;
00217
00218 iterate_find_new_node(b, nnodeptr, admin_table, struct_table, dist_table,
00219 2);
00220
00221 iterate_dissolve_visible_strongly_unbound_nodes(b, nnodeptr, admin_table,
00222 struct_table, dist_table);
00223
00224
00225
00226
00227 print_group_internal_structure(nnode, admin_table, struct_table,
00228 name_table);
00229 for (int i = 0; i < NNODE_MAX; i++)
00230 if (name_table[i])
00231 delete name_table[i];
00232 }
00233
00234
00235
00236
00237
00238
00239 local void find_namenumbers(dyn * b, char * name_table[NNODE_MAX])
00240 {
00241 int i;
00242 dyn * bi;
00243
00244 for (i = 0, bi = b->get_oldest_daughter(); bi != NULL;
00245 i++, bi = bi->get_younger_sister())
00246 {
00247 if (bi->get_index() >= 0)
00248 {
00249 name_table[i] = new char[BUFF_LENGTH];
00250 sprintf(name_table[i], "%d", bi->get_index());
00251 }
00252 else
00253 name_table[i] = NULL;
00254 }
00255 }
00256
00257
00258
00259
00260
00261 local void iterate_find_new_node(dyn * b, int * nnodeptr,
00262 int admin_table[NNODE_MAX][N_ADMIN],
00263 real struct_table[NNODE_MAX][N_STRUCT],
00264 real dist_table[NNODE_MAX][NNODE_MAX], int k)
00265 {
00266 int n_visible_nodes;
00267
00268 n_visible_nodes = count_visible_nodes(admin_table, *nnodeptr);
00269 if (k > n_visible_nodes)
00270 return;
00271
00272 if (find_new_node(b, nnodeptr, admin_table, struct_table, dist_table,
00273 k) == TRUE)
00274 iterate_find_new_node(b, nnodeptr, admin_table, struct_table,
00275 dist_table, 2);
00276 else
00277 iterate_find_new_node(b, nnodeptr, admin_table, struct_table,
00278 dist_table, k+1);
00279 }
00280
00281
00282
00283
00284
00285 local bool find_new_node(dyn * b, int * nnodeptr,
00286 int admin_table[NNODE_MAX][N_ADMIN],
00287 real struct_table[NNODE_MAX][N_STRUCT],
00288 real dist_table[NNODE_MAX][NNODE_MAX], int k)
00289 {
00290 int i;
00291 int n;
00292 int tuple[NBODY_MAX];
00293 int ordered_tuple[NBODY_MAX];
00294
00295 n = count_visible_nodes(admin_table, *nnodeptr);
00296 if (k > n)
00297 return(FALSE);
00298
00299 init_tuple(tuple, admin_table, n);
00300 for (i = 0; i < n; i++)
00301 ordered_tuple[i] = tuple[i];
00302
00303 do
00304 if (is_new_node(tuple, b, nnodeptr, admin_table, struct_table,
00305 dist_table, k) == TRUE)
00306 return(TRUE);
00307 while
00308 (next_tuple(tuple, k, n, ordered_tuple) == TRUE);
00309
00310 return(FALSE);
00311 }
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325 local bool is_new_node(int tuple[NBODY_MAX], dyn * b, int * nnodeptr,
00326 int admin_table[NNODE_MAX][N_ADMIN],
00327 real struct_table[NNODE_MAX][N_STRUCT],
00328 real dist_table[NNODE_MAX][NNODE_MAX], int k)
00329 {
00330 real radius;
00331
00332 if (k < 2)
00333 {
00334 cerr << "is_new_node: k = " << k << " < 2\n";
00335 exit(1);
00336 }
00337
00338 if (is_approximately_isolated_tuple(tuple, *nnodeptr, admin_table,
00339 dist_table, k) == FALSE)
00340 return(FALSE);
00341
00342 if (is_isolated_tuple(tuple, b, *nnodeptr, admin_table, struct_table,
00343 &radius, k) == FALSE)
00344 return(FALSE);
00345
00346 install_node(tuple, b, nnodeptr, admin_table, struct_table, dist_table,
00347 radius, k);
00348
00349 return(TRUE);
00350 }
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360 local bool is_approximately_isolated_tuple(int tuple[NBODY_MAX], int nnode,
00361 int admin_table[NNODE_MAX][N_ADMIN],
00362 real dist_table[NNODE_MAX][NNODE_MAX],
00363 int k)
00364 {
00365 int i, j, jt;
00366 real max_internal_pair_distance;
00367 int visible_non_tuple[NBODY_MAX];
00368 int n_visible_non_tuple;
00369
00370 if (k < 2)
00371 {
00372 cerr << "is_approximately_isolated_tuple: k = " << k << " < 2\n";
00373 exit(1);
00374 }
00375
00376 max_internal_pair_distance = 0.0;
00377
00378 for (i = 0; i < k - 1; i++)
00379 for (j = i + 1; j < k; j++)
00380 if (dist_table[tuple[i]][tuple[j]] > max_internal_pair_distance)
00381 max_internal_pair_distance = dist_table[tuple[i]][tuple[j]];
00382
00383 jt = 0;
00384 j = 0;
00385 for (i = 0; i < nnode; i++)
00386 if (Visibility(admin_table, i) == VISIBLE)
00387 if (jt >= k)
00388 visible_non_tuple[j++] = i;
00389 else if (i < tuple[jt])
00390 visible_non_tuple[j++] = i;
00391 else if (i == tuple[jt])
00392 jt++;
00393 else
00394 {
00395 cerr <<
00396 "is_approximately_isolated_tuple: non-visible tuple?\n";
00397 exit(1);
00398 }
00399
00400 n_visible_non_tuple = j;
00401
00402 for (i = 0; i < n_visible_non_tuple; i++)
00403 for (j = 0; j < k; j++)
00404 if (dist_table[visible_non_tuple[i]][tuple[j]]
00405 < max_internal_pair_distance)
00406 return(FALSE);
00407
00408 return(TRUE);
00409 }
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424 local bool is_isolated_tuple(int tuple[NBODY_MAX], dyn * b, int nnode,
00425 int admin_table[NNODE_MAX][N_ADMIN],
00426 real struct_table[NNODE_MAX][N_STRUCT],
00427 real * radiusptr, int k)
00428 {
00429 int i, j, jt;
00430 real radius;
00431 real radius_i;
00432 vector com_pos;
00433 real distance_to_com;
00434 int visible_non_tuple[NBODY_MAX];
00435 int n_visible_non_tuple;
00436 int pi_offset;
00437 dyn * bi;
00438
00439 radius = tuple_radius(tuple, b, struct_table, com_pos, k);
00440 *radiusptr = radius;
00441
00442 jt = 0;
00443 j = 0;
00444
00445 for (i = 0; i < nnode; i++)
00446 if (Visibility(admin_table, i) == VISIBLE)
00447 if (jt >= k)
00448 visible_non_tuple[j++] = i;
00449 else if (i < tuple[jt])
00450 visible_non_tuple[j++] = i;
00451 else if (i == tuple[jt])
00452 jt++;
00453 else
00454 {
00455 cerr << "is_isolated_tuple: non-visible tuple?\n";
00456 exit(1);
00457 }
00458
00459 n_visible_non_tuple = j;
00460 for (i = 0; i < n_visible_non_tuple; i++)
00461 {
00462 bi = b->get_oldest_daughter();
00463 pi_offset = visible_non_tuple[i];
00464 while (pi_offset--)
00465 bi = bi->get_younger_sister();
00466 distance_to_com = abs(bi->get_pos() - com_pos);
00467 radius_i = Radius(struct_table, visible_non_tuple[i]);
00468 if (distance_to_com < radius + radius_i + 2.0 * max(radius, radius_i))
00469 return(FALSE);
00470 }
00471
00472 return(TRUE);
00473 }
00474
00475
00476
00477
00478
00479 local void how_bound_tuple(int tuple[NBODY_MAX], dyn * b,
00480 real dist_table[NNODE_MAX][NNODE_MAX],
00481 int k, bool * isbound, bool * isbarelyunbound)
00482 {
00483 real kinetic_energy;
00484 real abs_potential_energy;
00485
00486 kinetic_energy = tuple_kin_energy(tuple, b, k);
00487 abs_potential_energy = -tuple_pot_energy(tuple, b, dist_table, k);
00488
00489 *isbound = *isbarelyunbound = FALSE;
00490
00491 if (kinetic_energy < abs_potential_energy)
00492 *isbound = TRUE;
00493 else if (kinetic_energy < 1.5 * abs_potential_energy)
00494 *isbarelyunbound = TRUE;
00495 }
00496
00497
00498
00499
00500
00501
00502
00503 local real tuple_pot_energy(int tuple[NBODY_MAX], dyn * b,
00504 real dist_table[NNODE_MAX][NNODE_MAX], int k)
00505 {
00506 int i, j;
00507 real pot_energy;
00508 int pi_offset;
00509 int pj_offset;
00510 dyn * bi;
00511 dyn * bj;
00512
00513 pot_energy = 0.0;
00514
00515 for (i = 0; i < k - 1; i++)
00516 {
00517 bi = b->get_oldest_daughter();
00518 pi_offset = tuple[i];
00519 while (pi_offset--)
00520 bi = bi->get_younger_sister();
00521
00522 for (j = i + 1; j < k; j++)
00523 {
00524 bj = b->get_oldest_daughter();
00525 pj_offset = tuple[j];
00526 while (pj_offset--)
00527 bj = bj->get_younger_sister();
00528
00529 pot_energy -= ( bi->get_mass() * bj->get_mass() )
00530 / dist_table[ tuple[i] ][ tuple[j] ];
00531 }
00532 }
00533
00534 return(pot_energy);
00535 }
00536
00537
00538
00539
00540
00541
00542 local real tuple_kin_energy(int tuple[NBODY_MAX], dyn * b, int k)
00543 {
00544 int i;
00545 real velocity_squared;
00546 real kin_energy;
00547 real total_mass;
00548 vector mass_times_vel;
00549 vector rel_vel;
00550 vector com_vel;
00551 int pi_offset;
00552 dyn * bi;
00553
00554 total_mass = 0;
00555
00556 com_vel = 0;
00557 for (i = 0; i < k; i++)
00558 {
00559 bi = b->get_oldest_daughter();
00560 pi_offset = tuple[i];
00561 while (pi_offset--)
00562 bi = bi->get_younger_sister();
00563
00564 total_mass += bi->get_mass();
00565 mass_times_vel = bi->get_mass() * bi->get_vel();
00566 com_vel += mass_times_vel;
00567 }
00568 com_vel /= total_mass;
00569
00570 kin_energy = 0;
00571
00572 for (i = 0; i < k; i++)
00573 {
00574 bi = b->get_oldest_daughter();
00575 pi_offset = tuple[i];
00576 while (pi_offset--)
00577 bi = bi->get_younger_sister();
00578
00579 rel_vel = bi->get_vel() - com_vel;
00580 velocity_squared = rel_vel * rel_vel;
00581 kin_energy += bi->get_mass() * velocity_squared;
00582 }
00583
00584 kin_energy *= 0.5;
00585
00586 return(kin_energy);
00587 }
00588
00589 #define LARGE_INTEGER 100000
00590
00591
00592
00593
00594
00595 local int representative_body(int admin_table[NNODE_MAX][N_ADMIN], int i)
00596 {
00597 int j;
00598 int number_of_daughters;
00599 int daughter_j_representative;
00600 int lowest_number;
00601
00602 number_of_daughters = Ndaughter(admin_table, i);
00603
00604 if (number_of_daughters != 0)
00605 {
00606 lowest_number = LARGE_INTEGER;
00607 for (j = 0; j < number_of_daughters; j++)
00608 {
00609 daughter_j_representative = representative_body(admin_table,
00610 Daughter(admin_table,i,j));
00611 if (lowest_number > daughter_j_representative)
00612 lowest_number = daughter_j_representative;
00613 }
00614 return(lowest_number);
00615 }
00616 else
00617 return(i);
00618 }
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632 local void init_dist_table(dyn * b, real dist_table[NNODE_MAX][NNODE_MAX])
00633 {
00634 int i, j;
00635 dyn *bi, *bj;
00636 real distance;
00637
00638 for (i = 0, bi = b->get_oldest_daughter(); bi != NULL;
00639 i++, bi = bi->get_younger_sister())
00640 dist_table[i][i] = 0.0;
00641
00642 for (i = 0, bi = b->get_oldest_daughter(); bi != NULL;
00643 i++, bi = bi->get_younger_sister())
00644 for (j = i+1, bj = bi->get_younger_sister(); bj != NULL;
00645 j++, bj = bj->get_younger_sister())
00646 {
00647 distance = abs(bi->get_pos() - bj->get_pos());
00648 dist_table[i][j] = dist_table[j][i] = distance;
00649 }
00650 }
00651
00652
00653
00654
00655
00656 local void init_admin_table(int admin_table[NNODE_MAX][N_ADMIN])
00657 {
00658 int i;
00659
00660 for (i = 0; i < NNODE_MAX; i++)
00661 {
00662 Ndaughter(admin_table, i) = 0;
00663 Visibility(admin_table, i) = VISIBLE;
00664 Stability(admin_table, i) = STABLE;
00665 }
00666 }
00667
00668
00669
00670
00671
00672 local void init_struct_table(real struct_table[NNODE_MAX][N_STRUCT])
00673 {
00674 int i;
00675
00676 for (i = 0; i < NNODE_MAX; i++)
00677 Radius(struct_table, i) = 0.0;
00678 }
00679
00680
00681
00682
00683
00684 local int count_visible_nodes(int admin_table[NNODE_MAX][N_ADMIN], int nnode)
00685 {
00686 int i;
00687 int n_visible_nodes;
00688
00689 n_visible_nodes = 0;
00690
00691 for (i = 0; i < nnode; i++)
00692 if (Visibility(admin_table, i) == VISIBLE)
00693 n_visible_nodes++;
00694
00695 return( n_visible_nodes );
00696 }
00697
00698
00699
00700
00701
00702
00703 local void init_tuple(int tuple[NBODY_MAX],
00704 int admin_table[NNODE_MAX][N_ADMIN], int n)
00705 {
00706 int i, j;
00707
00708 if (n > NBODY_MAX)
00709 {
00710 cerr << "init_tuple: n = " << n << " > NBODY_MAX = "
00711 << NBODY_MAX << "\n";
00712 exit(1);
00713 }
00714
00715 i = j = 0;
00716
00717 while(i < NNODE_MAX && j < n)
00718 {
00719 if (Visibility(admin_table, i) == VISIBLE)
00720 tuple[j++] = i;
00721 i++;
00722 }
00723 if (j != n)
00724 {
00725 cerr << "init_tuple: j = " << j << " != n = " << n << "\n";
00726 exit(1);
00727 }
00728 }
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743 local bool next_tuple(int tuple[NBODY_MAX], int k, int n,
00744 int ordered_tuple[NBODY_MAX])
00745 {
00746 if (k > n)
00747 {
00748 cerr << "next_tuple: k = " << k << " > n = " << n << "\n";
00749 exit(1);
00750 }
00751
00752 if (k < 1)
00753 return(FALSE);
00754
00755 if (tuple[k-1] < ordered_tuple[n-1])
00756 {
00757 tuple[k-1] = next_element(tuple[k-1], ordered_tuple, n);
00758 return(TRUE);
00759 }
00760 else if (next_tuple(tuple, k-1, n-1, ordered_tuple) == TRUE)
00761 {
00762 tuple[k-1] = next_element(tuple[k-2], ordered_tuple, n);
00763 return(TRUE);
00764 }
00765 else
00766 return(FALSE);
00767 }
00768
00769
00770
00771
00772
00773 local int next_element(int element, int tuple[NBODY_MAX], int n)
00774 {
00775 int i;
00776
00777 for (i = 0; i < n - 1; i++)
00778 if (element == tuple[i])
00779 return(tuple[i+1]);
00780
00781 int shhh = 1;
00782
00783 if (element == tuple[n-1])
00784 {
00785 cerr <<
00786 "next_element: element provided is the last element of tuple\n";
00787 exit(1);
00788 }
00789 else if (shhh)
00790 {
00791 cerr << "next_element: element provided is not an element of tuple\n";
00792 exit(1);
00793 }
00794 else
00795 return 0;
00796
00797 return 0;
00798 }
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819 local real tuple_radius(int tuple[NBODY_MAX], dyn * b,
00820 real struct_table[NNODE_MAX][N_STRUCT],
00821 vector & com_pos, int k)
00822 {
00823 int i;
00824 real member_radius;
00825 real max_member_radius;
00826 real total_mass;
00827 real lever_arm_factor;
00828 vector mass_times_pos;
00829 real a, e;
00830 int member_offset;
00831 int g0_offset;
00832 int g1_offset;
00833 dyn * member;
00834 dyn * g0;
00835 dyn * g1;
00836
00837 total_mass = 0.0;
00838 com_pos = 0;
00839 for (i = 0; i < k; i++)
00840 {
00841 member = b->get_oldest_daughter();
00842 member_offset = tuple[i];
00843 while (member_offset--)
00844 member = member->get_younger_sister();
00845
00846 total_mass += member->get_mass();
00847 mass_times_pos = member->get_mass() * member->get_pos();
00848 com_pos += mass_times_pos;
00849 }
00850 com_pos /= total_mass;
00851
00852 if (k == 2)
00853 {
00854 g0 = g1 = b->get_oldest_daughter();
00855 g0_offset = tuple[0];
00856 g1_offset = tuple[1];
00857 while (g0_offset--)
00858 g0 = g0->get_younger_sister();
00859 while (g1_offset--)
00860 g1 = g1->get_younger_sister();
00861
00862 get_binary_parameters(g0, g1, &a, &e);
00863 }
00864
00865 max_member_radius = 0.0;
00866
00867 for (i = 0; i < k; i++)
00868 {
00869 if (k == 2 && a > 0.0)
00870 {
00871 if (i == 0)
00872 lever_arm_factor = g1->get_mass() / total_mass;
00873 else
00874 lever_arm_factor = g0->get_mass() / total_mass;
00875 member_radius = a * (1.0 + e) * lever_arm_factor;
00876 }
00877 else
00878 {
00879 member = b->get_oldest_daughter();
00880 member_offset = tuple[i];
00881 while (member_offset--)
00882 member = member->get_younger_sister();
00883
00884 member_radius = abs(member->get_pos() - com_pos);
00885 }
00886 member_radius += Radius(struct_table, tuple[i]);
00887 if (member_radius > max_member_radius)
00888 max_member_radius = member_radius;
00889 }
00890
00891 return(max_member_radius);
00892 }
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907 local void install_node(int tuple[NBODY_MAX], dyn * b, int * nnodeptr,
00908 int admin_table[NNODE_MAX][N_ADMIN],
00909 real struct_table[NNODE_MAX][N_STRUCT],
00910 real dist_table[NNODE_MAX][NNODE_MAX],
00911 real radius, int k)
00912 {
00913 real a;
00914 real e;
00915 int g0_offset;
00916 int g1_offset;
00917 dyn * g0;
00918 dyn * g1;
00919
00920 if (*nnodeptr >= NNODE_MAX)
00921 {
00922 cerr << "install_node: *nnodeptr = " << *nnodeptr
00923 << " >= NNODE_MAX = " << NNODE_MAX << "\n";
00924 exit(1);
00925 }
00926
00927 if (k == 2)
00928 {
00929 g0 = g1 = b->get_oldest_daughter();
00930 g0_offset = tuple[0];
00931 g1_offset = tuple[1];
00932 while (g0_offset--)
00933 g0 = g0->get_younger_sister();
00934 while (g1_offset--)
00935 g1 = g1->get_younger_sister();
00936
00937 get_binary_parameters(g0, g1, &a, &e);
00938 }
00939
00940 install_com_dynamics(b, *nnodeptr, tuple, k);
00941
00942 update_dist_table(b, *nnodeptr, dist_table);
00943 update_struct_table(*nnodeptr, struct_table, radius, a, e, k);
00944 update_admin_table(tuple, b, *nnodeptr, admin_table, struct_table,
00945 dist_table, k);
00946 *nnodeptr += 1;
00947 }
00948
00949
00950
00951
00952
00953 local void update_dist_table(dyn * b, int nnode,
00954 real dist_table[NNODE_MAX][NNODE_MAX])
00955 {
00956 int i;
00957 real distance;
00958 dyn * bi;
00959 dyn * glast;
00960
00961 dist_table[nnode][nnode] = 0.0;
00962
00963 glast = b->get_oldest_daughter();
00964 for (i = 0; i < nnode; i++)
00965 glast = glast->get_younger_sister();
00966
00967 for (i = 0, bi = b->get_oldest_daughter(); i < nnode;
00968 i++, bi = bi->get_younger_sister())
00969 {
00970 distance = abs(bi->get_pos() - glast->get_pos());
00971 dist_table[i][nnode] = dist_table[nnode][i] = distance;
00972 }
00973 }
00974
00975 #define STABLE_SEPARATION_FACTOR 2.0
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996 local void update_admin_table(int tuple[NBODY_MAX], dyn * b, int nnode,
00997 int admin_table[NNODE_MAX][N_ADMIN],
00998 real struct_table[NNODE_MAX][N_STRUCT],
00999 real dist_table[NNODE_MAX][NNODE_MAX], int k)
01000 {
01001 int i;
01002 bool isbound;
01003 bool isbarelyunbound;
01004 real pericenter_distance;
01005 real sum_of_radii;
01006
01007 Ndaughter(admin_table, nnode) = k;
01008 Visibility(admin_table, nnode) = VISIBLE;
01009
01010 for (i = 0; i < k; i++)
01011 {
01012 Daughter(admin_table, nnode, i) = tuple[i];
01013 Visibility(admin_table, tuple[i]) = COVERED;
01014 }
01015
01016 how_bound_tuple(tuple, b, dist_table, k, &isbound, &isbarelyunbound);
01017
01018 if (isbarelyunbound == TRUE)
01019 Stability(admin_table, nnode) = BARELY_UNBOUND;
01020 else if (isbound == FALSE)
01021 Stability(admin_table, nnode) = STRONGLY_UNBOUND;
01022 else if (k > 2)
01023 Stability(admin_table, nnode) = UNSTABLE;
01024 else
01025 {
01026 Stability(admin_table, nnode) = STABLE;
01027 for (i = 0; i < k; i++)
01028 if (Ndaughter(admin_table, Daughter(admin_table, nnode, i)) > 0)
01029 if (Stability(admin_table, Daughter(admin_table, nnode, i))
01030 != STABLE)
01031 Stability(admin_table, nnode) = UNSTABLE;
01032
01033 pericenter_distance =
01034 Apair(struct_table, nnode) * (1.0 - Epair(struct_table, nnode));
01035 sum_of_radii = Radius(struct_table, Daughter(admin_table, nnode, 0))
01036 + Radius(struct_table, Daughter(admin_table, nnode, 1));
01037
01038 if (pericenter_distance < STABLE_SEPARATION_FACTOR * sum_of_radii)
01039 Stability(admin_table, nnode) = UNSTABLE;
01040 }
01041 }
01042
01043
01044
01045
01046
01047 local void update_struct_table(int nnode,
01048 real struct_table[NNODE_MAX][N_STRUCT],
01049 real radius, real a, real e, int k)
01050 {
01051 Radius(struct_table, nnode) = radius;
01052
01053 if (k == 2)
01054 {
01055 Apair(struct_table, nnode) = a;
01056 Epair(struct_table, nnode) = e;
01057 }
01058 }
01059
01060
01061
01062
01063
01064 local void get_binary_parameters(dyn *g1, dyn *g2, real * aptr, real * eptr)
01065
01066
01067 {
01068 real delta_r, delta_v, m_sum;
01069 vector r_rel, v_rel, r_out_v;
01070 real r_out_v_squared;
01071
01072 delta_r = abs(g1->get_pos() - g2->get_pos());
01073 delta_v = abs(g1->get_vel() - g2->get_vel());
01074 m_sum = g1->get_mass() + g2->get_mass();
01075
01076 *aptr = 1.0 / (2.0/delta_r - delta_v*delta_v / m_sum);
01077
01078 r_rel = g1->get_pos() - g2->get_pos();
01079 v_rel = g1->get_vel() - g2->get_vel();
01080 r_out_v = r_rel ^ v_rel;
01081 r_out_v_squared = r_out_v * r_out_v;
01082
01083 *eptr = sqrt(max(0.0, 1.0 - (r_out_v_squared / (m_sum * *aptr))));
01084 }
01085
01086
01087
01088
01089
01090 local void iterate_dissolve_visible_strongly_unbound_nodes(dyn * b,
01091 int * nnodeptr,
01092 int admin_table[NNODE_MAX][N_ADMIN],
01093 real struct_table[NNODE_MAX][N_STRUCT],
01094 real dist_table[NNODE_MAX][NNODE_MAX])
01095 {
01096 while (dissolve_visible_strongly_unbound_nodes(b, nnodeptr,admin_table,
01097 struct_table, dist_table))
01098 ;
01099 }
01100
01101
01102
01103
01104
01105 local bool dissolve_visible_strongly_unbound_nodes(dyn * b, int * nnodeptr,
01106 int admin_table[NNODE_MAX][N_ADMIN],
01107 real struct_table[NNODE_MAX][N_STRUCT],
01108 real dist_table[NNODE_MAX][NNODE_MAX])
01109 {
01110 int i;
01111 bool new_activity;
01112
01113 new_activity = FALSE;
01114 for (i = 0; i < *nnodeptr; i++)
01115 if (Visibility(admin_table, i) == VISIBLE &&
01116 Stability(admin_table, i) == STRONGLY_UNBOUND)
01117 {
01118 dissolve_node(b, nnodeptr, i, admin_table, struct_table,
01119 dist_table);
01120 new_activity = TRUE;
01121 break;
01122 }
01123
01124 return(new_activity);
01125 }
01126
01127
01128
01129
01130
01131 local void dissolve_node(dyn * b, int * nnodeptr, int i,
01132 int admin_table[NNODE_MAX][N_ADMIN],
01133 real struct_table[NNODE_MAX][N_STRUCT],
01134 real dist_table[NNODE_MAX][NNODE_MAX])
01135 {
01136 if (i != *nnodeptr-1)
01137 swap_nodes(b, *nnodeptr, i, *nnodeptr-1, admin_table, struct_table,
01138 dist_table);
01139
01140 drop_tailnode(nnodeptr, admin_table);
01141 }
01142
01143
01144
01145
01146
01147 local void swap_nodes(dyn * b, int nnode, int i1, int i2,
01148 int admin_table[NNODE_MAX][N_ADMIN],
01149 real struct_table[NNODE_MAX][N_STRUCT],
01150 real dist_table[NNODE_MAX][NNODE_MAX])
01151 {
01152 int tmp_int;
01153 real tmp_real;
01154 int j;
01155 int i;
01156 dyn * bi1;
01157 dyn * bi2;
01158
01159 if (i1 >= nnode)
01160 {
01161 cerr << "swap_nodes: i1 = " << i1 << " > nnode = " << nnode << "\n";
01162 exit(1);
01163 }
01164 if (i2 >= nnode)
01165 {
01166 cerr << "swap_nodes: i2 = " << i2 << " > nnode = " << nnode << "\n";
01167 exit(1);
01168 }
01169
01170 bi1 = bi2 = b->get_oldest_daughter();
01171 while (i1--)
01172 bi1 = bi1->get_younger_sister();
01173 while (i2--)
01174 bi2 = bi2->get_younger_sister();
01175
01176 swap_body_nodes(bi1, bi2);
01177
01178 tmp_int = Ndaughter(admin_table, i1);
01179 Ndaughter(admin_table, i1) = Ndaughter(admin_table, i2);
01180 Ndaughter(admin_table, i2) = tmp_int;
01181
01182 tmp_int = Visibility(admin_table, i1);
01183 Visibility(admin_table, i1) = Visibility(admin_table, i2);
01184 Visibility(admin_table, i2) = tmp_int;
01185
01186 tmp_int = Stability(admin_table, i1);
01187 Stability(admin_table, i1) = Stability(admin_table, i2);
01188 Stability(admin_table, i2) = tmp_int;
01189
01190 j = max(Ndaughter(admin_table, i1), Ndaughter(admin_table, i2));
01191 while (j-- > 0)
01192 {
01193 tmp_int = Daughter(admin_table, i1, j);
01194 Daughter(admin_table, i1, j) = Daughter(admin_table, i2, j);
01195 Daughter(admin_table, i2, j) = tmp_int;
01196 }
01197
01198
01199
01200
01201 for (i = 0; i < nnode; i++)
01202 if (Ndaughter(admin_table, i) > 0)
01203 for (j = 0; j < Ndaughter(admin_table, i); j++)
01204 {
01205 if (Daughter(admin_table, i, j) == i1)
01206 Daughter(admin_table, i, j) = i2;
01207 else if (Daughter(admin_table, i, j) == i2)
01208 Daughter(admin_table, i, j) = i1;
01209 }
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223 tmp_real = Radius(struct_table, i1);
01224 Radius(struct_table, i1) = Radius(struct_table, i2);
01225 Radius(struct_table, i2) = tmp_real;
01226
01227 tmp_real = Apair(struct_table, i1);
01228 Apair(struct_table, i1) = Apair(struct_table, i2);
01229 Apair(struct_table, i2) = tmp_real;
01230
01231 tmp_real = Epair(struct_table, i1);
01232 Epair(struct_table, i1) = Epair(struct_table, i2);
01233 Epair(struct_table, i2) = tmp_real;
01234
01235 for (i = 0; i < nnode; i++)
01236 {
01237 tmp_real = dist_table[i][i1];
01238 dist_table[i][i1] = dist_table[i][i2];
01239 dist_table[i][i2] = tmp_real;
01240 }
01241
01242 for (j = 0; j < nnode; j++)
01243 {
01244 tmp_real = dist_table[i1][j];
01245 dist_table[i1][j] = dist_table[i2][j];
01246 dist_table[i2][j] = tmp_real;
01247 }
01248 }
01249
01250
01251
01252
01253
01254 local void swap_body_nodes(dyn * bi, dyn * bj)
01255 {
01256 dyn *bir, *bil, *bjr, *bjl, *bb;
01257
01258 if ((bb = bi->get_parent()) == NULL)
01259 {
01260 cerr << "swap_body_nodes: node #" << bi << " has no parent\n";
01261 exit(1);
01262 }
01263
01264 if (bi->get_parent() != bj->get_parent())
01265 {
01266 cerr << "nodes #" << bi << " and #" << bj
01267 << " have different parents\n";
01268 exit(1);
01269 }
01270
01271 if (bi == bj)
01272 return;
01273
01274 bir = bi->get_younger_sister();
01275 bil = bi->get_elder_sister();
01276 bjr = bj->get_younger_sister();
01277 bjl = bj->get_elder_sister();
01278
01279 if (bil == bj)
01280 {
01281 bj->set_elder_sister(bi);
01282 bi->set_younger_sister(bj);
01283
01284 bi->set_elder_sister(bjl);
01285 if (bjl)
01286 bjl->set_younger_sister(bi);
01287 else
01288 bb->set_oldest_daughter(bi);
01289
01290 bj->set_younger_sister(bir);
01291 if (bir)
01292 bir->set_elder_sister(bj);
01293 }
01294 else if (bjl == bi)
01295 {
01296 bi->set_elder_sister(bj);
01297 bj->set_younger_sister(bi);
01298
01299 bj->set_elder_sister(bil);
01300 if (bil)
01301 bil->set_younger_sister(bj);
01302 else
01303 bb->set_oldest_daughter(bj);
01304
01305 bi->set_younger_sister(bjr);
01306 if (bjr)
01307 bjr->set_elder_sister(bi);
01308 }
01309 else
01310 {
01311 bi->set_elder_sister(bjl);
01312 bi->set_younger_sister(bjr);
01313 bj->set_elder_sister(bil);
01314 bj->set_younger_sister(bir);
01315
01316 if (bil)
01317 bil->set_younger_sister(bj);
01318 else
01319 bb->set_oldest_daughter(bj);
01320
01321 if (bjl)
01322 bjl->set_younger_sister(bi);
01323 else
01324 bb->set_oldest_daughter(bi);
01325
01326 if (bir)
01327 bir->set_elder_sister(bj);
01328
01329 if (bjr)
01330 bjr->set_elder_sister(bi);
01331 }
01332 }
01333
01334
01335
01336
01337
01338 local void drop_tailnode(int * nnodeptr, int admin_table[NNODE_MAX][N_ADMIN])
01339 {
01340 int j;
01341
01342 if (Visibility(admin_table, *nnodeptr-1) != VISIBLE)
01343 {
01344 cerr << "drop_tailnode: can't drop an invisible tail\n";
01345 exit(1);
01346 }
01347
01348 for (j = 0; j < Ndaughter(admin_table, *nnodeptr-1); j++)
01349 Visibility(admin_table, Daughter(admin_table, *nnodeptr-1, j))
01350 = VISIBLE;
01351
01352 (*nnodeptr)--;
01353 }
01354
01355
01356
01357
01358
01359 local void tail_insert(dyn * b, dyn * new_node)
01360 {
01361 dyn *bi, *b_prev;
01362
01363 b_prev = b->get_oldest_daughter();
01364
01365 if (b_prev == NULL)
01366 {
01367 cerr << "tail_insert: b_prev == NULL\n";
01368 exit(1);
01369 }
01370
01371 while (bi = b_prev->get_younger_sister())
01372 b_prev = bi;
01373
01374 b_prev->set_younger_sister(new_node);
01375 }
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385 local void install_com_dynamics(dyn * b, int nnode,
01386 int tuple[NBODY_MAX], int k)
01387 {
01388 int i;
01389 real total_mass;
01390 vector com_pos;
01391 vector com_vel;
01392 vector mass_times_pos;
01393 vector mass_times_vel;
01394 int member_offset;
01395 dyn * member;
01396 dyn * new_node;
01397
01398
01399 nnode++; nnode--;
01400
01401 total_mass = 0.0;
01402 com_pos = com_vel = 0;
01403 for (i = 0; i < k; i++)
01404 {
01405 member = b->get_oldest_daughter();
01406 member_offset = tuple[i];
01407 while (member_offset--)
01408 member = member->get_younger_sister();
01409
01410 total_mass += member->get_mass();
01411 mass_times_pos = member->get_mass() * member->get_pos();
01412 com_pos += mass_times_pos;
01413 mass_times_vel = member->get_mass() * member->get_vel();
01414 com_vel += mass_times_vel;
01415 }
01416 com_pos /= total_mass;
01417 com_vel /= total_mass;
01418
01419 new_node = new dyn;
01420 new_node->set_mass(total_mass);
01421 new_node->set_pos(com_pos);
01422 new_node->set_vel(com_vel);
01423
01424 tail_insert(b, new_node);
01425 }
01426
01427
01428
01429
01430
01431 local void print_group_internal_structure(int nnode,
01432 int admin_table[NNODE_MAX][N_ADMIN],
01433 real struct_table[NNODE_MAX][N_STRUCT],
01434 char * name_table[NNODE_MAX])
01435 {
01436 int i;
01437 char node_report[BUFF_LENGTH];
01438
01439 for (i = 0; i < nnode; i++)
01440 if (Ndaughter(admin_table, i) > 0)
01441 {
01442 sprintf(node_report, " ", i);
01443
01444 print_node(node_report, admin_table, struct_table, name_table, i);
01445
01446 if ((Ndaughter(admin_table, i) == 2))
01447 print_binary_parameters(node_report, struct_table, i);
01448 else
01449 print_radius(node_report, struct_table, i);
01450
01451 printf(node_report);
01452 }
01453 }
01454
01455
01456
01457
01458
01459 local void print_node(char node_report[BUFF_LENGTH],
01460 int admin_table[NNODE_MAX][N_ADMIN],
01461 real struct_table[NNODE_MAX][N_STRUCT],
01462 char * name_table[NNODE_MAX],
01463 int member)
01464 {
01465 int i;
01466
01467 if (Ndaughter(admin_table, member) == 0)
01468 {
01469 if (name_table[member])
01470 {
01471 sprintf(end_of_string(node_report), "%s", name_table[member]);
01472
01473 }
01474 }
01475 else
01476 {
01477 if (Stability(admin_table, member) == STABLE)
01478 sprintf(end_of_string(node_report), "[");
01479 else if (Stability(admin_table, member) == UNSTABLE)
01480 sprintf(end_of_string(node_report), "(");
01481 else if (Stability(admin_table, member) == BARELY_UNBOUND)
01482 sprintf(end_of_string(node_report), "<");
01483 else if (Stability(admin_table, member) == STRONGLY_UNBOUND)
01484 sprintf(end_of_string(node_report), "{");
01485 else if (Stability(admin_table, member) == UNKNOWN)
01486 cerr << "print_node: stability of member " << member
01487 << " is UNKNOWN\n";
01488 else
01489 cerr << "print_node: invalid value "
01490 << Stability(admin_table, member)
01491 << " for stability of member " << member << "\n";
01492
01493 for (i = 0; i < Ndaughter(admin_table, member); i++)
01494 {
01495 if (i > 0)
01496 sprintf(end_of_string(node_report), ", ");
01497 print_node(node_report, admin_table, struct_table, name_table,
01498 Daughter(admin_table, member, i));
01499 }
01500
01501 if (Stability(admin_table, member) == STABLE)
01502 sprintf(end_of_string(node_report), "]");
01503 else if (Stability(admin_table, member) == UNSTABLE)
01504 sprintf(end_of_string(node_report), ")");
01505 else if (Stability(admin_table, member) == BARELY_UNBOUND)
01506 sprintf(end_of_string(node_report), ">");
01507 else if (Stability(admin_table, member) == STRONGLY_UNBOUND)
01508 sprintf(end_of_string(node_report), "}");
01509 else if (Stability(admin_table, member) == UNKNOWN)
01510 cerr << "print_node: stability of member " << member
01511 << " is UNKNOWN\n";
01512 else
01513 cerr << "print_node: invalid value "
01514 << Stability(admin_table, member)
01515 << " for stability of member " << member << "\n";
01516 }
01517 }
01518
01519
01520
01521
01522
01523 local void print_binary_parameters(char node_report[BUFF_LENGTH],
01524 real struct_table[NNODE_MAX][N_STRUCT],
01525 int member)
01526 {
01527 int offset_in_node_report;
01528 real semimajor_axis;
01529
01530 offset_in_node_report = end_of_string(node_report) - node_report;
01531
01532
01533
01534
01535 while (offset_in_node_report < 49)
01536 node_report[offset_in_node_report++] = ' ';
01537
01538 semimajor_axis = Apair(struct_table, member);
01539
01540 #if 0
01541
01542 if (semimajor_axis < 10.0 && semimajor_axis > 0.0)
01543 sprintf(node_report + offset_in_node_report,"a = %.16f ; e = %.16f\n",
01544 semimajor_axis, Epair(struct_table, member));
01545 else if (semimajor_axis < 100.0 && semimajor_axis > -10.0)
01546 sprintf(node_report + offset_in_node_report,"a = %.15f ; e = %.16f\n",
01547 semimajor_axis, Epair(struct_table, member));
01548 else if (semimajor_axis < 1000.0 && semimajor_axis > -100.0)
01549 sprintf(node_report + offset_in_node_report,"a = %.14f ; e = %.16f\n",
01550 semimajor_axis, Epair(struct_table, member));
01551 else if (semimajor_axis < 10000.0 && semimajor_axis > -1000.0)
01552 sprintf(node_report + offset_in_node_report,"a = %.13f ; e = %.16f\n",
01553 semimajor_axis, Epair(struct_table, member));
01554 else if (semimajor_axis < 100000.0 && semimajor_axis > -10000.0)
01555 sprintf(node_report + offset_in_node_report,"a = %.12f ; e = %.16f\n",
01556 semimajor_axis, Epair(struct_table, member));
01557 else if (semimajor_axis < 1000000.0 && semimajor_axis > -100000.0)
01558 sprintf(node_report + offset_in_node_report,"a = %.11f ; e = %.16f\n",
01559 semimajor_axis, Epair(struct_table, member));
01560 else
01561 sprintf(node_report + offset_in_node_report,"a = %.10f ; e = %.16f\n",
01562 semimajor_axis, Epair(struct_table, member));
01563
01564 #else
01565
01566
01567 if (semimajor_axis < 10.0 && semimajor_axis > 0.0)
01568 sprintf(node_report + offset_in_node_report,"a = %.6f ; e = %8f\n",
01569 semimajor_axis, Epair(struct_table, member));
01570 else if (semimajor_axis < 100.0 && semimajor_axis > -10.0)
01571 sprintf(node_report + offset_in_node_report,"a = %.5f ; e = %8f\n",
01572 semimajor_axis, Epair(struct_table, member));
01573 else if (semimajor_axis < 1000.0 && semimajor_axis > -100.0)
01574 sprintf(node_report + offset_in_node_report,"a = %.4f ; e = %8f\n",
01575 semimajor_axis, Epair(struct_table, member));
01576 else if (semimajor_axis < 10000.0 && semimajor_axis > -1000.0)
01577 sprintf(node_report + offset_in_node_report,"a = %.3f ; e = %8f\n",
01578 semimajor_axis, Epair(struct_table, member));
01579 else if (semimajor_axis < 100000.0 && semimajor_axis > -10000.0)
01580 sprintf(node_report + offset_in_node_report,"a = %.2f ; e = %8f\n",
01581 semimajor_axis, Epair(struct_table, member));
01582 else if (semimajor_axis < 1000000.0 && semimajor_axis > -100000.0)
01583 sprintf(node_report + offset_in_node_report,"a = %.1f ; e = %8f\n",
01584 semimajor_axis, Epair(struct_table, member));
01585 else
01586 sprintf(node_report + offset_in_node_report,"a = %.0f ; e = %8f\n",
01587 semimajor_axis, Epair(struct_table, member));
01588
01589 #endif
01590 }
01591
01592
01593
01594
01595
01596
01597 local void print_radius(char node_report[BUFF_LENGTH],
01598 real struct_table[NNODE_MAX][N_STRUCT], int member)
01599 {
01600 int offset_in_node_report;
01601 real r_node;
01602
01603 offset_in_node_report = end_of_string(node_report) - node_report;
01604
01605
01606
01607
01608 while (offset_in_node_report < 49)
01609 node_report[offset_in_node_report++] = ' ';
01610
01611 r_node = Radius(struct_table, member);
01612 if (r_node < 10.0)
01613 sprintf(node_report + offset_in_node_report, "R = %.6f\n", r_node);
01614 else if (r_node < 100.0)
01615 sprintf(node_report + offset_in_node_report, "R = %.5f\n", r_node);
01616 else if (r_node < 1000.0)
01617 sprintf(node_report + offset_in_node_report, "R = %.4f\n", r_node);
01618 else if (r_node < 10000.0)
01619 sprintf(node_report + offset_in_node_report, "R = %.3f\n", r_node);
01620 else if (r_node < 100000.0)
01621 sprintf(node_report + offset_in_node_report, "R = %.2f\n", r_node);
01622 else if (r_node < 1000000.0)
01623 sprintf(node_report + offset_in_node_report, "R = %.1f\n", r_node);
01624 else
01625 sprintf(node_report + offset_in_node_report, "R = %.0f\n", r_node);
01626 }
01627
01628
01629
01630
01631
01632
01633 local int how_much_offspring(int admin_table[NNODE_MAX][N_ADMIN], int member)
01634 {
01635 int i, k, n_total;
01636
01637 k = Ndaughter(admin_table, member);
01638 n_total = 0;
01639
01640 if (k > 0)
01641 for (i = 0; i < k; i++)
01642 n_total += how_much_offspring(admin_table,
01643 Daughter(admin_table, member, i));
01644 else
01645 n_total = 1;
01646
01647 return(n_total);
01648 }
01649
01650 #define BUFF_SAFETY_MARGIN 28
01651
01652
01653
01654
01655
01656 local char *end_of_string(char * the_string)
01657 {
01658 int char_position;
01659
01660 char_position = 0;
01661 while(the_string[char_position] != '\0')
01662 char_position++;
01663
01664 if(char_position > BUFF_LENGTH - 1 - BUFF_SAFETY_MARGIN)
01665 {
01666 cerr << "end_of_string: too little room left in buffer\n";
01667 exit(1);
01668 }
01669
01670 return(the_string + char_position);
01671 }
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687 local void bring_to_normal_form(char old_hier_string[BUFF_LENGTH])
01688 {
01689 int i, j;
01690 int number_of_objects;
01691 int ordered[BUFF_LENGTH];
01692 int unordered[BUFF_LENGTH];
01693 char new_hier_string[BUFF_LENGTH];
01694 char substring[BUFF_LENGTH];
01695 char head_char, tail_char;
01696
01697 if (old_hier_string[1] == ';')
01698 return;
01699
01700 new_hier_string[0] = '\0';
01701 substring[0] = '\0';
01702
01703 map_to_integers(old_hier_string, unordered, &number_of_objects);
01704
01705 sort_int_array(unordered, ordered, number_of_objects);
01706
01707 for (i = 0; i < number_of_objects; i++)
01708 {
01709 j = old_ranking(unordered, ordered, i, number_of_objects);
01710 select_object(substring, old_hier_string, j);
01711 unwrap_string(substring, &head_char, &tail_char);
01712 bring_to_normal_form(substring);
01713 wrap_string(substring, head_char, tail_char);
01714 append_object(new_hier_string, substring);
01715 }
01716
01717
01718
01719 i = 0;
01720 while (new_hier_string[i] != '\0' && i < BUFF_LENGTH)
01721 {
01722 old_hier_string[i] = new_hier_string[i];
01723 i++;
01724 }
01725 if (i >= BUFF_LENGTH)
01726 {
01727 cerr << "bring_to_normal_form: buffer length exceeded\n";
01728 exit(1);
01729 }
01730 if (old_hier_string[i] != '\0')
01731 {
01732 cerr <<
01733 "bring_to_normal_form: new and old hier. string diff. length\n";
01734 exit(1);
01735 }
01736 }
01737
01738
01739
01740
01741
01742
01743
01744 local void map_to_integers(char hier_string[BUFF_LENGTH],
01745 int unordered[BUFF_LENGTH], int * nptr)
01746
01747 {
01748 int i;
01749 int lowest_number;
01750 int level;
01751 char c;
01752
01753 *nptr = 0;
01754 level = 0;
01755 lowest_number = 10;
01756 i = 0;
01757 while (i < BUFF_LENGTH)
01758 {
01759 c = hier_string[i++];
01760
01761 if (c >= '0' && c <= '9')
01762 {
01763 if (c - '0' < lowest_number)
01764 lowest_number = c - '0';
01765 }
01766 else if (c == '(' || c == '[' || c == '{' || c == '<')
01767 level++;
01768 else if (c == ')' || c == ']' || c == '}' || c == '>')
01769 level--;
01770 else if (level == 0 && (c == ',' || c == ';'))
01771 {
01772 unordered[*nptr] = lowest_number;
01773 (*nptr)++;
01774 lowest_number = 10;
01775 }
01776
01777 if (c == ';')
01778 break;
01779 }
01780 if (i >= BUFF_LENGTH)
01781 {
01782 cerr << "map_to_integers: buffer length exceeded\n";
01783 exit(1);
01784 }
01785 }
01786
01787
01788
01789
01790
01791
01792
01793 local void sort_int_array(int old_array[BUFF_LENGTH],
01794 int new_array[BUFF_LENGTH], int n)
01795 {
01796 int i, j;
01797 int dummy;
01798
01799 for (i = 0; i < n; i++)
01800 new_array[i] = old_array[i];
01801
01802 for (i = 0; i < n - 1; i++)
01803 for (j = i+1; j < n; j++)
01804 if (new_array[j] < new_array[i])
01805 {
01806 dummy = new_array[i];
01807 new_array[i] = new_array[j];
01808 new_array[j] = dummy;
01809 }
01810 }
01811
01812
01813
01814
01815
01816
01817
01818 local int old_ranking(int old_array[BUFF_LENGTH], int new_array[BUFF_LENGTH],
01819 int i, int n)
01820 {
01821 int j;
01822
01823 j = 0;
01824 while (j < n)
01825 if (old_array[j++] == new_array[i])
01826 break;
01827 if (j > n)
01828 {
01829 cerr << "old_ranking: used buffer length exceeded\n";
01830 exit(1);
01831 }
01832
01833 return(--j);
01834 }
01835
01836
01837
01838
01839
01840
01841
01842 local void select_object(char tmp_string[BUFF_LENGTH],
01843 char hier_string[BUFF_LENGTH], int member)
01844 {
01845 int i, j;
01846 int level;
01847 char c;
01848
01849 level = 0;
01850 i = 0;
01851 while (member > 0)
01852 {
01853 c = hier_string[i];
01854 if (c == '(' || c == '[' || c == '{' || c == '<')
01855 level++;
01856 else if (c == ')' || c == ']' || c == '}' || c == '>')
01857 level--;
01858 else if (c == ',' && level == 0)
01859 member--;
01860 else if (c == ';')
01861 cerr << "select_object: reached end of string\n";
01862 if (++i >= BUFF_LENGTH)
01863 cerr << "select_object: at position #1: buffer length exceeded\n";
01864 }
01865
01866 if (level != 0)
01867 {
01868 cerr << "select_object: number of (,[,{,< and of ),],},> unbalanced\n";
01869 exit(1);
01870 }
01871 j = 0;
01872 while (c = hier_string[i])
01873 {
01874 if (c == '(' || c == '[' || c == '{' || c == '<')
01875 level++;
01876 else if (c == ')' || c == ']' || c == '}' || c == '>')
01877 level--;
01878 else if ((c == ',' && level == 0) || c == ';')
01879 {
01880 sprintf(tmp_string + j, ";");
01881 if (level != 0)
01882 {
01883 cerr << "select_object: number of (,[, etc. unbalanced\n";
01884 exit(1);
01885 }
01886 break;
01887 }
01888 tmp_string[j++] = c;
01889
01890 if (++i >= BUFF_LENGTH)
01891 cerr << "select_object: at position #2: buffer length exceeded\n";
01892 }
01893 }
01894
01895
01896
01897
01898
01899
01900
01901 local void append_object(char hier_string[BUFF_LENGTH],
01902 char tmp_string[BUFF_LENGTH])
01903 {
01904 char *last_endptr;
01905 char *new_startingptr;
01906 char *end_of_string(char *);
01907
01908 if (hier_string[0] == '\0')
01909 new_startingptr = hier_string;
01910 else
01911 {
01912 last_endptr = end_of_string(hier_string) - 1;
01913 if (*last_endptr == ';')
01914 *last_endptr = ',';
01915 else
01916 cerr << "append_object: hier_string not properly terminated\n";
01917 new_startingptr = last_endptr + 1;
01918 }
01919
01920 sprintf(new_startingptr, tmp_string);
01921 }
01922
01923
01924
01925
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935 local void unwrap_string(char substring[BUFF_LENGTH],
01936 char * head_ptr, char * tail_ptr)
01937 {
01938 int i;
01939 int level;
01940 char c;
01941
01942 c = substring[0];
01943
01944 if (c == '(' || c == '[' || c == '{' || c == '<')
01945 *head_ptr = c;
01946 else
01947 {
01948 *head_ptr = *tail_ptr = '*';
01949 return;
01950 }
01951
01952 level = 1;
01953 i = 1;
01954 for (;;)
01955 {
01956 c = substring[i];
01957 if (c == '(' || c == '[' || c == '{' || c == '<')
01958 level++;
01959 else if (c == ')' || c == ']' || c == '}' || c == '>')
01960 level--;
01961
01962 if (level == 0)
01963 {
01964 if (substring[i+1] != ';')
01965 {
01966 *head_ptr = *tail_ptr = '*';
01967 return;
01968 }
01969 else
01970 break;
01971 }
01972
01973 if (++i >= BUFF_LENGTH)
01974 cerr << "unwrap_string: buffer length exceeded\n";
01975 }
01976
01977 i = 1;
01978 while ((c = substring[i]) != ';')
01979 {
01980 substring[i-1] = c;
01981 i++;
01982 }
01983 *tail_ptr = substring[i-2];
01984 substring[i-2] = ';';
01985 substring[i-1] = '\0';
01986 }
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997 local void wrap_string(char substring[BUFF_LENGTH],
01998 char head_char, char tail_char)
01999 {
02000 int i;
02001 char last_c;
02002 char c;
02003
02004 if (head_char == '*')
02005 return;
02006
02007 last_c = head_char;
02008 i = 0;
02009 while((c = substring[i]) != ';')
02010 {
02011 substring[i] = last_c;
02012 last_c = c;
02013 i++;
02014 }
02015 substring[i] = last_c;
02016 substring[++i] = tail_char;
02017 substring[++i] = ';';
02018 substring[++i] = '\0';
02019 }
02020
02021 main(int argc, char ** argv)
02022 {
02023
02024 char dummy = **argv;
02025
02026 check_help();
02027
02028 if (argc != 1) {
02029 cerr << "molecules: no arguments allowed\n";
02030 exit(1);
02031 }
02032
02033 dyn *b = get_dyn(cin);
02034
02035 printf("\n");
02036
02037 while (b) {
02038
02039 dyn *bi;
02040
02041 for (bi = b->get_oldest_daughter(); bi != NULL;
02042 bi = bi->get_younger_sister())
02043 if (bi->get_oldest_daughter() != NULL)
02044 {
02045 cerr << "molecules: flat tree required, sorry!\n";
02046 exit(1);
02047 }
02048
02049 if (find_qmatch(b->get_dyn_story(), "t"))
02050 printf("Time = %15g \n", getrq(b->get_dyn_story(), "t"));
02051
02052 find_group_internal_structure(b);
02053
02054 bi = b->get_oldest_daughter();
02055 while (bi) {
02056 dyn * tmp = bi->get_younger_sister();
02057 delete bi;
02058 bi = tmp;
02059 }
02060 delete b;
02061
02062 b = get_dyn(cin);
02063 }
02064 }
02065
02066 #endif
02067
02068