00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "hdyn.h"
00029 #include "grape6.h"
00030 #include "hdyn_inline.C"
00031
00032
00033
00034
00035
00036 #define DEBUG 0
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 #define INLINE
00048
00049 #define ONE2 0.5
00050 #define ONE6 0.16666666666666666667
00051
00052 #define NRETRY 10
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 static int cluster_id = 0;
00064 static real grape_time_offset = 0;
00065
00066
00067
00068 static hdyn **node_list = NULL;
00069
00070
00071 static hdyn **current_nodes = NULL;
00072 static hdyn **previous_nodes = NULL;
00073
00074
00075
00076
00077 static int grape_nj_max = 0;
00078 static int n_previous_nodes = 0;
00079
00080
00081
00082 static bool grape_is_open = false;
00083 static bool grape_first_attach = true;
00084 static bool grape_was_used_to_calculate_potential = false;
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102 local void reattach_grape(real time, char *id, kira_options *ko)
00103
00104
00105
00106
00107
00108
00109
00110 {
00111 cerr << id << ": ";
00112 if (!grape_first_attach) cerr << "re";
00113 cerr << "attaching GRAPE at time "
00114 << time << endl << flush;
00115
00116 g6_open_(&cluster_id);
00117 if (ko) ko->grape_last_cpu = cpu_time();
00118 grape_is_open = true;
00119
00120 if (DEBUG) {
00121 cerr << "GRAPE successfully attached"
00122 << endl << flush;
00123 }
00124 }
00125
00126
00127
00128 local INLINE void send_j_node_to_grape(hdyn *b, bool predict = false)
00129
00130
00131
00132
00133
00134
00135
00136 {
00137 if (DEBUG > 1) {
00138 cerr << " send_j_node_to_grape: ";
00139 PRC(b->format_label()); PRL(predict);
00140 }
00141
00142 int grape_index = b->get_grape_index();
00143
00144 real t = b->get_time() - grape_time_offset;
00145 real dt = b->get_timestep();
00146 if (dt <= 0) dt = 1;
00147 real m = b->get_mass();
00148
00149 vector pos;
00150 if (predict)
00151
00152
00153
00154
00155 pos = hdyn_something_relative_to_root(b, &hdyn::get_pred_pos);
00156
00157 else
00158 pos = b->get_pos();
00159
00160 vector vel = b->get_vel();
00161
00162 vector a2 = ONE2 * b->get_acc();
00163 vector j6 = ONE6 * b->get_jerk();
00164
00165 vector k18 = b->get_k_over_18();
00166
00167 if (DEBUG > 1) {
00168 PRI(4); PRC(cluster_id); PRL(grape_index);
00169 PRI(4); PRC(t); PRC(dt); PRL(m);
00170 PRI(4); PRL(j6);
00171 PRI(4); PRL(a2);
00172 PRI(4); PRL(vel);
00173 PRI(4); PRL(pos);
00174 }
00175
00176 g6_set_j_particle_(&cluster_id,
00177 &grape_index,
00178 &grape_index,
00179 &t, &dt, &m,
00180 &k18[0],
00181 &j6[0],
00182 &a2[0],
00183 &vel[0],
00184 &pos[0]);
00185
00186 if (DEBUG > 1) {
00187 cerr << " ...sent to GRAPE-6" << endl << flush;
00188 }
00189 }
00190
00191
00192
00193 local int initialize_grape_arrays(hdyn *b,
00194 bool reset_counters = true,
00195 bool predict = false)
00196
00197
00198
00199
00200
00201
00202
00203 {
00204 if (DEBUG) {
00205 cerr << "initialize_grape_arrays at time "
00206 << b->get_real_system_time()<< ": ";
00207 PRC(reset_counters); PRL(predict);
00208 }
00209
00210 int nj = b->n_daughters();
00211
00212 if (DEBUG)
00213 PRL(nj);
00214
00215 if (grape_nj_max <= 0 || grape_nj_max < nj) {
00216
00217
00218
00219 if (node_list) delete [] node_list;
00220 if (current_nodes) delete [] current_nodes;
00221 if (previous_nodes) delete [] previous_nodes;
00222
00223 grape_nj_max = 3*nj + 10;
00224 node_list = NULL;
00225 }
00226
00227 if (!node_list) {
00228
00229 if (DEBUG)
00230 PRL(grape_nj_max);
00231
00232 node_list = new hdynptr[grape_nj_max];
00233 current_nodes = new hdynptr[grape_nj_max];
00234 previous_nodes = new hdynptr[grape_nj_max];
00235 }
00236
00237
00238
00239 if (b->get_real_system_time() - grape_time_offset > 1)
00240 grape_time_offset += 1;
00241
00242
00243
00244 nj = 0;
00245 for_all_daughters(hdyn, b, bb) {
00246
00247
00248
00249 bb->set_grape_index(nj);
00250 node_list[nj++] = bb;
00251
00252
00253
00254 send_j_node_to_grape(bb, predict);
00255
00256 if (reset_counters)
00257 bb->set_grape_nb_count(0);
00258 }
00259
00260 if (DEBUG) {
00261 cerr << endl << "Initialized GRAPE-6 arrays, "; PRL(nj);
00262 cerr << "...leaving initialize_grape_arrays" << endl;
00263 }
00264
00265 return nj;
00266 }
00267
00268
00269
00270 local hdyn *find_and_print_nn(hdyn *b)
00271 {
00272 real d2min = VERY_LARGE_NUMBER;
00273 hdyn *bmin = NULL;
00274 for_all_daughters(hdyn, b->get_root(), bb) {
00275 if (bb != b) {
00276 real d2 = square(bb->get_pred_pos() - b->get_pred_pos());
00277 if (d2 < d2min) {
00278 d2min = d2;
00279 bmin = bb;
00280 }
00281 }
00282 }
00283 if (bmin) {
00284 cerr << " found true nn of " << b->format_label();
00285 cerr << " = " << bmin->format_label()
00286 << "; grape_index = " << bmin->get_grape_index()
00287 << " at distance " << sqrt(d2min) << endl;
00288 } else
00289 cerr << " can't find true nn for " << b->format_label() << endl;
00290
00291 return bmin;
00292 }
00293
00294
00295
00296 local void reset_grape(hdyn *b)
00297
00298
00299
00300
00301
00302
00303 {
00304
00305
00306
00307 g6_reset_(&cluster_id);
00308 g6_reset_fofpga_(&cluster_id);
00309
00310 g6_close_(&cluster_id);
00311 g6_open_(&cluster_id);
00312
00313 cerr << endl << "*** Reset GRAPE-6 at time "
00314 << b->get_real_system_time() << endl;
00315
00316
00317
00318 initialize_grape_arrays(b, false);
00319 }
00320
00321
00322
00323
00324
00325
00326 static int *iindex = NULL;
00327 static vector *ipos = NULL;
00328 static vector *ivel = NULL;
00329 static vector *iacc = NULL;
00330 static vector *ijerk = NULL;
00331 static real *ipot = NULL;
00332 static real *ih2 = NULL;
00333 static int *inn = NULL;
00334 static real eps2 = 0;
00335
00336
00337
00338 local INLINE int force_by_grape(xreal xtime,
00339 hdyn *nodes[], int ni,
00340 int nj, int n_pipes,
00341 bool pot_only = false,
00342 int level = 0)
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352 {
00353 static char *func = "force_by_grape";
00354
00355 if (ni <= 0) return 0;
00356 if (ni > n_pipes) err_exit("force_by_grape: ni too large\n");
00357
00358 if (DEBUG > 1) {
00359 cerr << " " << func << ": ";
00360 PRC(xtime); PRC(ni); PRC(nj); PRL(pot_only);
00361 }
00362
00363 if (!iindex) {
00364
00365
00366
00367 iindex = new int[n_pipes];
00368 ipos = new vector[n_pipes];
00369 ivel = new vector[n_pipes];
00370 iacc = new vector[n_pipes];
00371 ijerk = new vector[n_pipes];
00372 ipot = new real[n_pipes];
00373 ih2 = new real[n_pipes];
00374 inn = new int[n_pipes];
00375 eps2 = nodes[0]->get_eps2();
00376 }
00377
00378
00379
00380 real time = xtime - grape_time_offset;
00381 g6_set_ti_(&cluster_id, &time);
00382
00383
00384
00385 if (DEBUG > 1) {
00386 cerr << " loading nodes..."
00387 << endl << flush;
00388 }
00389
00390
00391
00392 for (int i = 0; i < ni; i++) {
00393
00394
00395
00396 iindex[i] = nodes[i]->get_grape_index();
00397
00398 #if 0
00399
00400
00401 if (pot_only)
00402
00403
00404
00405 ipos[i] = hdyn_something_relative_to_root(nodes[i],
00406 &hdyn::get_pred_pos);
00407 else
00408 ipos[i] = nodes[i]->get_pred_pos();
00409
00410 ivel[i] = nodes[i]->get_pred_vel();
00411 iacc[i] = nodes[i]->get_old_acc();
00412 ijerk[i] = ONE6*nodes[i]->get_old_jerk();
00413 ipot[i] = nodes[i]->get_pot();
00414 ih2[i] = nodes[i]->get_grape_rnb_sq();
00415
00416 #else
00417
00418
00419
00420
00421
00422
00423 if (pot_only) {
00424
00425
00426
00427 ipos[i] = hdyn_something_relative_to_root(nodes[i],
00428 &hdyn::get_pred_pos);
00429
00430 #if 0
00431
00432
00433
00434 iacc[i] = vector(1);
00435 ijerk[i] = vector(1);
00436 #endif
00437
00438 } else {
00439
00440 ipos[i] = nodes[i]->get_pred_pos();
00441 #if 0
00442 iacc[i] = nodes[i]->get_old_acc();
00443 ijerk[i] = ONE6*nodes[i]->get_old_jerk();
00444
00445
00446
00447
00448
00449
00450 if (abs(iacc[i]) <= VERY_SMALL_NUMBER ||
00451 abs(ijerk[i]) <= VERY_SMALL_NUMBER) {
00452 cerr << "WARNING: Initializing acc and jerk from zero."
00453 << endl;
00454 iacc[i] = vector(1);
00455 ijerk[i] = vector(1);
00456 }
00457 #endif
00458
00459 }
00460
00461 ivel[i] = nodes[i]->get_pred_vel();
00462 ih2[i] = nodes[i]->get_grape_rnb_sq();
00463 iacc[i] = nodes[i]->get_old_acc();
00464 ijerk[i] = ONE6*nodes[i]->get_old_jerk();
00465 ipot[i] = nodes[i]->get_pot();
00466
00467
00468
00469
00470
00471
00472
00473 if (abs(ipot[i]) <= VERY_SMALL_NUMBER
00474 || abs(abs(iacc[i][0])) <= VERY_SMALL_NUMBER) {
00475
00476 ipot[i] = 1;
00477 if (abs(iacc[i]) <= VERY_SMALL_NUMBER ||
00478 abs(ijerk[i]) <= VERY_SMALL_NUMBER) {
00479
00480
00481 iacc[i] = vector(1);
00482 ijerk[i] = vector(1);
00483 }
00484 }
00485
00486 #endif
00487
00488 if (DEBUG > 1) {
00489 if (i > 0) cerr << endl;
00490 PRI(4); PRC(i); PRC(iindex[i]); PRL(nodes[i]->format_label());
00491 PRI(4); PRL(ipos[i]);
00492 PRI(4); PRL(ivel[i]);
00493 PRI(4); PRL(iacc[i]);
00494 PRI(4); PRL(ijerk[i]);
00495 }
00496 }
00497
00498
00499
00500 for (int i = ni; i < n_pipes; i++)
00501 ih2[i] = 0;
00502
00503 g6calc_firsthalf_(&cluster_id, &nj, &ni, iindex,
00504 ipos, ivel, iacc, ijerk, ipot,
00505 &eps2, ih2);
00506
00507 int error = g6calc_lasthalf2_(&cluster_id, &nj, &ni, iindex,
00508 ipos, ivel, &eps2, ih2,
00509 iacc, ijerk, ipot, inn);
00510
00511 if (DEBUG > 1) {
00512 cerr << endl << " ...results:"
00513 << endl << flush;
00514 }
00515
00516 if (!error) {
00517
00518 for (int i = 0; i < ni; i++) {
00519
00520
00521
00522
00523
00524
00525 if (inn[i] < 0 || inn[i] >= nj || ipot[i] > 0) {
00526 error = 42;
00527 break;
00528 }
00529
00530 if (pot_only)
00531
00532 nodes[i]->set_pot(ipot[i]);
00533
00534 else {
00535
00536 hdyn *nn = node_list[inn[i]];
00537 real d_nn_sq = 0;
00538
00539 if (DEBUG > 1) {
00540 if (i > 0) cerr << endl;
00541 PRI(4); PRC(i); PRC(iindex[i]);
00542 PRL(nodes[i]->format_label());
00543 PRI(4); PRL(iacc[i]);
00544 PRI(4); PRL(ijerk[i]);
00545 PRI(4); PRL(ipot[i]);
00546 PRI(4); PRC(inn[i]); PR(nn);
00547 }
00548
00549 if (nn) {
00550
00551 d_nn_sq = square(ipos[i] - nn->get_pred_pos());
00552
00553 if (DEBUG > 1) {
00554 PRI(2); PRL(nn->format_label());
00555 }
00556
00557 } else {
00558
00559
00560
00561 nn = nodes[i];
00562
00563 if (DEBUG > 1)
00564 cerr << endl;
00565 }
00566
00567 if (DEBUG > 1) {
00568 hdyn *true_nn = find_and_print_nn(nodes[i]);
00569 if (true_nn != nn)
00570 cerr << " *** error: nn != true_nn" << endl;
00571 }
00572
00573 nodes[i]->set_acc_and_jerk_and_pot(iacc[i], ijerk[i], ipot[i]);
00574 nodes[i]->set_nn(nn);
00575 nodes[i]->set_d_nn_sq(d_nn_sq);
00576
00577
00578 #if 0000
00579 if (nodes[i]->name_is("(5394,21337)")
00580 || nodes[i]->name_is("(21337,5394)")) {
00581 cerr << func << ": ";
00582 PRC(nodes[i]); PRC(inn[i]); PRC(nn); PRL(d_nn_sq);
00583 }
00584 #endif
00585
00586
00587 if (DEBUG > 1) {
00588
00589
00590
00591 bool found_index = false;
00592 for_all_daughters(hdyn, nodes[0]->get_root(), bb)
00593 if (bb->get_grape_index() == inn[i]) {
00594 cerr << " check: found grape_index = " << inn[i]
00595 << " for node " << bb->format_label()
00596 << endl;
00597 found_index = true;
00598 if (bb != nn)
00599 cerr << " *** error: nn mismatch" << endl;
00600 }
00601 if (!found_index)
00602 cerr << " *** error: grape_index " << inn[i]
00603 << " not found" << endl;
00604 }
00605 }
00606 }
00607 }
00608
00609
00610
00611 if (error) {
00612
00613
00614
00615
00616 cerr << "*** " << func << "(" << level << "): hardware error "
00617 << error << " at time " << time << ", ni = " << ni << endl;
00618
00619 if (level < NRETRY) {
00620
00621 cerr << "Resetting GRAPE and retrying..." << endl;
00622 reset_grape(nodes[0]->get_root());
00623
00624 error = force_by_grape(xtime, nodes, ni, nj, n_pipes, pot_only,
00625 level+1);
00626 }
00627 }
00628
00629 if (DEBUG > 1) {
00630 cerr << " ...leaving " << func << "(" << level <<"): ";
00631 PRL(error);
00632 }
00633
00634 return error;
00635 }
00636
00637
00638
00639 local void hw_err_exit(char *func, int id, hdyn *b)
00640
00641
00642
00643
00644
00645
00646
00647 {
00648 char buf[256];
00649 sprintf(buf, "%s[%d]: time to call Jun!", func, id);
00650
00651
00652
00653 char *dumpfile = "hw_error_dump";
00654
00655 ofstream dump(dumpfile);
00656 if (dump) {
00657 put_node(dump, *b->get_root(), b->get_kira_options()->print_xreal);
00658 dump.close();
00659 cerr << "Data written to file " << dumpfile << endl;
00660 }
00661
00662 err_exit(buf);
00663 }
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683 void check_release_grape(kira_options *ko, xreal time, bool verbose)
00684 {
00685 #ifdef SHARE_GRAPE
00686
00687 if (DEBUG) {
00688 cerr << "GRAPE CPU check: ";
00689 PRL(cpu_time());
00690 }
00691
00692 if (cpu_time() - ko->grape_last_cpu > ko->grape_max_cpu) {
00693
00694 int p = cerr.precision(STD_PRECISION);
00695 cerr << endl << "Releasing GRAPE-6 at time " << time << " after ";
00696 cerr.precision(2);
00697 cerr << cpu_time() - ko->grape_last_cpu <<" CPU sec" << endl;
00698 cerr.precision(p);
00699
00700 g6_close_(&cluster_id);
00701 grape_is_open = false;
00702 grape_first_attach = false;
00703
00704 cerr << endl;
00705 }
00706
00707 #endif
00708 }
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719 local inline bool use_cm_approx(hdyn *bb)
00720 {
00721 if (bb->get_kepler()) {
00722
00723
00724
00725
00726
00727
00728 return true;
00729 }
00730 return false;
00731 }
00732
00733
00734
00735 local int send_all_leaves_to_grape(hdyn *b,
00736 real& e_unpert,
00737 bool cm = false)
00738
00739
00740
00741
00742
00743
00744
00745 {
00746
00747
00748 if (DEBUG) {
00749 cerr << " send_all_leaves_to_grape"
00750 << endl << flush;
00751 }
00752
00753 int nj = 0;
00754 e_unpert = 0;
00755
00756
00757
00758
00759 if (!cm) {
00760 for_all_leaves(hdyn, b, bb) {
00761
00762
00763
00764
00765
00766
00767
00768
00769 bool reset_bb = false;
00770
00771
00772
00773
00774 while (use_cm_approx(bb)) {
00775 hdyn *sis = bb->get_younger_sister();
00776 hdyn *par = bb->get_parent();
00777 real reduced_mass = bb->get_mass() * sis->get_mass()
00778 / par->get_mass();
00779 e_unpert += reduced_mass * bb->get_kepler()->get_energy();
00780 bb = par;
00781 reset_bb = true;
00782 }
00783
00784
00785
00786
00787
00788
00789
00790 if (reset_bb) {
00791
00792
00793 bb = bb->get_oldest_daughter()->get_younger_sister()
00794 ->next_node(b);
00795
00796 if (!bb) break;
00797
00798 }
00799
00800
00801
00802
00803
00804
00805 bb->set_grape_index(nj++);
00806
00807
00808
00809 send_j_node_to_grape(bb, true);
00810 }
00811
00812 } else {
00813
00814 for_all_daughters(hdyn, b, bb) {
00815
00816
00817
00818 bb->set_grape_index(nj++);
00819
00820
00821
00822
00823
00824
00825 send_j_node_to_grape(bb, true);
00826 }
00827 }
00828
00829 if (DEBUG) {
00830
00831 cerr << " ...leaving send_all_leaves_to_grape: ";
00832 PRL(nj);
00833 }
00834
00835 return nj;
00836 }
00837
00838
00839
00840 local bool force_by_grape_on_all_leaves(hdyn *b,
00841 int nj,
00842 bool cm = false)
00843
00844
00845
00846
00847
00848
00849 {
00850 if (DEBUG) {
00851 cerr << " force_by_grape_on_all_leaves: ";
00852 PRL(nj);
00853 }
00854
00855 int n_pipes = g6_npipes_();
00856 hdyn **ilist = new hdynptr[n_pipes];
00857
00858
00859
00860 bool status = false;
00861
00862 int ip = 0;
00863 if (!cm) {
00864 for_all_leaves(hdyn, b, bb) {
00865 ilist[ip++] = bb;
00866 if (ip == n_pipes) {
00867 status |= force_by_grape(b->get_system_time(),
00868 ilist, ip, nj, n_pipes,
00869 true);
00870 ip = 0;
00871 }
00872 }
00873 } else {
00874 for_all_daughters(hdyn, b, bb) {
00875 ilist[ip++] = bb;
00876 if (ip == n_pipes) {
00877 status |= force_by_grape(b->get_system_time(),
00878 ilist, ip, nj, n_pipes,
00879 true);
00880 ip = 0;
00881 }
00882 }
00883 }
00884
00885 if (ip)
00886 status |= force_by_grape(b->get_system_time(),
00887 ilist, ip, nj, n_pipes,
00888 true);
00889
00890 if (DEBUG) {
00891 cerr << " ...leaving force_by_grape_on_all_leaves: ";
00892 PRL(status);
00893 }
00894
00895 delete [] ilist;
00896 return status;
00897 }
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910 void grape_calculate_energies(hdyn *b,
00911 real &epot,
00912 real &ekin,
00913 real &etot,
00914 bool cm)
00915 {
00916 if (DEBUG) {
00917 cerr << endl << "grape_calculate_energies..."
00918 << endl << flush;
00919 }
00920
00921 if (!grape_is_open)
00922 reattach_grape(b->get_real_system_time(),
00923 "grape_calculate_energies", b->get_kira_options());
00924
00925 real e_unpert;
00926 int nj = send_all_leaves_to_grape(b, e_unpert, cm);
00927
00928 if (force_by_grape_on_all_leaves(b, nj, cm)) {
00929
00930 cerr << "grape_calculate_energies: "
00931 << "error on return from force_by_grape_on_all_leaves()"
00932 << endl;
00933
00934 hw_err_exit("grape_calculate_energies", 1, b);
00935 }
00936
00937 grape_was_used_to_calculate_potential = true;
00938
00939
00940 epot = ekin = etot = 0;
00941
00942 if (!cm) {
00943 for_all_leaves(hdyn, b, bb) {
00944
00945
00946
00947 bool reset_bb = false;
00948
00949 while (use_cm_approx(bb)) {
00950 bb = bb->get_parent();
00951 reset_bb = true;
00952 }
00953 if (reset_bb) {
00954 bb = bb->get_oldest_daughter()->get_younger_sister()
00955 ->next_node(b);
00956 if (!bb) break;
00957 }
00958
00959 real mi = bb->get_mass();
00960 epot += 0.5*mi*bb->get_pot();
00961 vector vel = hdyn_something_relative_to_root(bb, &hdyn::get_vel);
00962 ekin += 0.5*mi*vel*vel;
00963 }
00964 } else {
00965 for_all_daughters(hdyn, b, bb) {
00966 real mi = bb->get_mass();
00967 epot += 0.5*mi*bb->get_pot();
00968 vector vel = bb->get_vel();
00969 ekin += 0.5*mi*vel*vel;
00970 }
00971 }
00972 etot = ekin + epot + e_unpert;
00973
00974 if (DEBUG) {
00975 cerr << "...leaving grape_calculate_energies... ";
00976 PRL(etot);
00977 cerr << endl;
00978 }
00979 }
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991 local INLINE bool set_grape_neighbor_radius(hdyn * b, int nj_on_grape)
00992
00993
00994
00995
00996
00997 {
00998 static char *func = "set_grape_neighbor_radius";
00999
01000 b->set_grape_rnb_sq(0.0);
01001
01002 if (b->is_leaf()) {
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016 if (b->get_grape_nb_count() == 0 && b->get_radius() > 0) {
01017
01018 real rnb_sq = 4*b->get_radius()*b->get_radius();
01019
01020
01021
01022
01023 if (b->get_nn() && b->get_nn() != b
01024 && b->get_d_nn_sq() < 0.1*VERY_LARGE_NUMBER) {
01025
01026 rnb_sq = max(rnb_sq, b->get_d_nn_sq());
01027
01028 } else {
01029
01030
01031
01032
01033 real r90_sq = b->get_d_min_sq() / square(b->get_d_min_fac());
01034 real rnn_sq = r90_sq * pow((real)nj_on_grape, 4.0/3);
01035
01036
01037
01038 rnb_sq = max(rnb_sq, rnn_sq);
01039 }
01040
01041 b->set_grape_rnb_sq(rnb_sq);
01042 }
01043
01044 } else {
01045
01046
01047
01048
01049
01050
01051 if (b->get_grape_nb_count() == 0 || !b->get_valid_perturbers()) {
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068 real r_pert2 = perturbation_scale_sq(b, b->get_gamma23());
01069
01070 hdyn *nn = b->get_nn();
01071 if (nn && nn != b && b->get_d_nn_sq() < 0.1* VERY_LARGE_NUMBER)
01072 r_pert2 = max(r_pert2, b->get_d_nn_sq());
01073
01074
01075
01076 b->set_grape_rnb_sq(r_pert2);
01077
01078
01079
01080
01081 }
01082 }
01083
01084 return (b->get_grape_rnb_sq() > 0);
01085 }
01086
01087
01088
01089 local INLINE bool get_force_and_neighbors(xreal xtime,
01090 hdyn *nodes[], int ni,
01091 int nj_on_grape, int n_pipes,
01092 bool need_neighbors,
01093 int level = 0)
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103 {
01104 static char *func = "get_force_and_neighbors";
01105
01106 if (ni <= 0) return false;
01107
01108
01109
01110
01111
01112 if (force_by_grape(xtime, nodes, ni, nj_on_grape, n_pipes)) {
01113
01114
01115
01116
01117 hw_err_exit(func, 1, nodes[0]);
01118 }
01119
01120 bool error = false;
01121
01122 if (need_neighbors) {
01123
01124
01125
01126
01127 int status = 0;
01128 #ifndef NO_G6_NEIGHBOUR_LIST
01129 status = g6_read_neighbour_list_(&cluster_id);
01130 #endif
01131 if (status) {
01132
01133
01134
01135 cerr << func << ": error getting GRAPE neighbor data: ";
01136 PRL(status);
01137
01138 if (status > 0) {
01139
01140
01141
01142
01143
01144 error = true;
01145
01146 } else {
01147
01148
01149
01150
01151
01152
01153
01154
01155 cerr << "*** " << func << "(" << level
01156 << "): hardware error " << error << " at time "
01157 << xtime << ", ni = " << ni << endl;
01158
01159 if (level < NRETRY) {
01160
01161 cerr << "Resetting GRAPE and retrying..." << endl;
01162 reset_grape(nodes[0]->get_root());
01163
01164 error = get_force_and_neighbors(xtime, nodes, ni,
01165 nj_on_grape, n_pipes,
01166 need_neighbors,
01167 level+1);
01168 } else
01169
01170 hw_err_exit(func, 2, nodes[0]);
01171 }
01172 }
01173 }
01174
01175 return error;
01176 }
01177
01178
01179
01180 local INLINE void swap(hdynptr ilist[], int i, int j)
01181 {
01182 hdyn *tmp = ilist[i];
01183 ilist[i] = ilist[j];
01184 ilist[j] = tmp;
01185 }
01186
01187 local INLINE int sort_nodes_and_reduce_rnb(hdynptr ilist[], int ni)
01188
01189
01190
01191
01192
01193
01194
01195 {
01196 static char *func = "sort_nodes_and_reduce_rnb";
01197
01198 cerr << "In " << func << "() after neighbor-list overflow at time "
01199 << ilist[0]->get_system_time() << endl;
01200
01201 int inext = ni;
01202
01203
01204
01205
01206 int imax = ni;
01207 real rnb_max = 0;
01208 for (int i = ni-1; i >= 0; i--) {
01209 if (ilist[i]->get_grape_rnb_sq() > 0) {
01210 if (i < --inext) swap(ilist, i, inext);
01211 if (ilist[inext]->get_grape_rnb_sq() > rnb_max) {
01212 imax = inext;
01213 rnb_max = ilist[inext]->get_grape_rnb_sq();
01214 }
01215 }
01216 }
01217
01218
01219
01220
01221 if (imax != inext) swap(ilist, inext, imax);
01222
01223
01224
01225
01226
01227 for (int i = inext; i < ni; i++) {
01228 if (ilist[i]->is_leaf() || i == inext)
01229 ilist[i]->set_grape_rnb_sq(0.5*ilist[i]->get_grape_rnb_sq());
01230 }
01231
01232
01233 return inext;
01234 }
01235
01236
01237
01238
01239
01240
01241 #define MAX_NEIGHBORS (16*MAX_PERTURBERS)
01242 #define RNB_INCREASE_FAC 2.0
01243 #define RNB_DECREASE_FAC 0.8
01244
01245 static int max_neighbors = MAX_NEIGHBORS;
01246 static int neighbor_list[MAX_NEIGHBORS];
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256 local INLINE int get_neighbors_and_adjust_h2(hdyn * b, int pipe)
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270 {
01271 static char *func = "get_neighbors_and_adjust_h2";
01272
01273
01274
01275 int n_neighbors = 0;
01276 int status = 0;
01277
01278 #ifndef NO_G6_NEIGHBOUR_LIST
01279 status = g6_get_neighbour_list_(&cluster_id,
01280 &pipe,
01281 &max_neighbors,
01282 &n_neighbors,
01283 neighbor_list);
01284 #endif
01285
01286 if (status) {
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300 if (n_neighbors >= max_neighbors) {
01301
01302
01303
01304
01305 b->set_grape_rnb_sq(0.25*b->get_grape_rnb_sq());
01306
01307 #if 0
01308 cerr << func << ": neighbor list overflow for "
01309 << b->format_label() << " (pipe "
01310 << pipe << ")" << endl;
01311 cerr << " at time " << b->get_system_time() << " ";
01312 PRC(n_neighbors); PRL(max_neighbors);
01313 cerr << " new rnb = " << sqrt(b->get_grape_rnb_sq())
01314 << " status = 1" << endl;
01315 #else
01316
01317
01318 cerr << func << ": node " << b->format_label()
01319 << " time " << b->get_system_time()
01320 << " n_n " << n_neighbors
01321 << endl << flush;
01322 #endif
01323
01324 return 1;
01325 }
01326 }
01327
01328
01329 #if 0000
01330 if (b->name_is("(5394,21337)") || b->name_is("(21337,5394)")) {
01331 cerr << func << ": "; PRL(b);
01332 PRI(4); PRC(b->get_grape_rnb_sq()); PRL(n_neighbors);
01333 }
01334 #endif
01335
01336
01337 status = 2;
01338
01339 if (n_neighbors > 0) {
01340
01341
01342
01343
01344
01345
01346
01347 status = 0;
01348
01349 real dmin_sq = VERY_LARGE_NUMBER;
01350 hdyn *bmin = NULL;
01351 real dcmin_sq = VERY_LARGE_NUMBER;
01352 hdyn *cmin = NULL;
01353
01354 int npl = 0;
01355 hdyn **pl = NULL;
01356 real rpfac = 0;
01357
01358 if (b->is_parent() && b->get_valid_perturbers()) {
01359
01360 if (b->get_oldest_daughter()->get_slow())
01361 clear_perturbers_slow_perturbed(b);
01362
01363 b->new_perturber_list();
01364
01365
01366
01367 pl = b->get_perturber_list();
01368 rpfac = b->get_perturbation_radius_factor();
01369 }
01370
01371 for (int j = 0; j < n_neighbors; j++) {
01372
01373 hdyn *bb = node_list[neighbor_list[j]];
01374
01375
01376
01377 if (bb != b) {
01378
01379 vector diff = b->get_pred_pos() - bb->get_pred_pos();
01380 real d2 = diff * diff;
01381
01382 real sum_of_radii = get_sum_of_radii(b, bb);
01383 update_nn_coll(b, 100,
01384 d2, bb, dmin_sq, bmin,
01385 sum_of_radii,
01386 dcmin_sq, cmin);
01387
01388
01389
01390
01391
01392 if (b->is_parent() && b->get_valid_perturbers()) {
01393
01394 if (is_perturber(b, bb->get_mass(),
01395 d2, rpfac)) {
01396
01397 if (npl < MAX_PERTURBERS)
01398 pl[npl] = bb;
01399
01400 npl++;
01401 }
01402 }
01403 }
01404 }
01405
01406 if (b->is_parent() && b->get_valid_perturbers()) {
01407
01408 b->set_n_perturbers(npl);
01409
01410 if (npl > MAX_PERTURBERS) {
01411 b->remove_perturber_list();
01412
01413
01414
01415
01416
01417 }
01418 }
01419
01420 if (bmin) {
01421 b->set_nn(bmin);
01422 b->set_d_nn_sq(dmin_sq);
01423
01424
01425 #if 0000
01426 if (b->name_is("(5394,21337)") || b->name_is("(21337,5394)")) {
01427 cerr << "get_nbrs: ";
01428 PRC(b); PRC(bmin); PRL(dmin_sq);
01429 }
01430 #endif
01431
01432
01433 } else
01434 status = 2;
01435
01436 if (cmin) {
01437 b->set_coll(cmin);
01438 b->set_d_coll_sq(dcmin_sq);
01439 } else
01440 status = 2;
01441 }
01442
01443
01444 #if 0000
01445 if (b->name_is("(5394,21337)") || b->name_is("(21337,5394)")) {
01446 cerr << func << ": ";
01447 PRC(b->get_grape_rnb_sq()); PRL(n_neighbors);
01448 }
01449 #endif
01450
01451
01452
01453
01454
01455 if (status)
01456 b->set_grape_rnb_sq(RNB_INCREASE_FAC*b->get_grape_rnb_sq());
01457
01458 return status;
01459 }
01460
01461
01462
01463 #define MAX_FORCE_COUNT 20
01464
01465 local INLINE int get_coll_and_perturbers(xreal xtime,
01466 hdynptr *ilist, int ni,
01467 real h2_crit,
01468 int nj_on_grape, int n_pipes)
01469
01470
01471
01472
01473
01474
01475
01476 {
01477 static char *func = "get_coll_and_perturbers";
01478
01479 int inext = 0;
01480
01481
01482
01483 for (int ip = 0; ip < ni; ip++) {
01484
01485 int pipe = ip;
01486 hdyn *bb = ilist[ip];
01487
01488 if (bb->get_grape_rnb_sq() > 0) {
01489
01490 int count_force = 1;
01491 int status;
01492
01493 while ((status = get_neighbors_and_adjust_h2(bb, pipe))) {
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507 if (count_force > MAX_FORCE_COUNT
01508 || (status == 2 && bb->get_grape_rnb_sq() > h2_crit)) {
01509
01510
01511
01512
01513
01514 bb->set_nn(bb);
01515
01516 bb->set_d_nn_sq(2*h2_crit);
01517
01518 if (bb->is_parent())
01519 bb->set_valid_perturbers(false);
01520
01521
01522 #if 0000
01523 if (bb->name_is("(5394,21337)")
01524 || bb->name_is("(21337,5394)")) {
01525 cerr << func << ": setting nn = bb for ";
01526 PRC(bb); PRL(bb->get_d_nn_sq());
01527 PRC(status); PRL(count_force);
01528 }
01529 #endif
01530
01531
01532 break;
01533
01534 } else {
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546 if (status == 1 && bb->is_parent())
01547 bb->set_valid_perturbers(false);
01548
01549
01550 #if 00000
01551 if (bb->name_is("(5394,21337)")
01552 || bb->name_is("(21337,5394)")) {
01553 cerr << func << ": recomputing force for ";
01554 PRC(ip); PRL(bb);
01555 PRL(ilist[ip]);
01556 }
01557 #endif
01558
01559
01560
01561
01562 pipe = 0;
01563 ip = ni;
01564
01565 while (get_force_and_neighbors(xtime,
01566 &bb,
01567 1,
01568 nj_on_grape, n_pipes,
01569 true)) {
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582 bb->set_grape_rnb_sq(RNB_DECREASE_FAC
01583 * bb->get_grape_rnb_sq());
01584 count_force++;
01585
01586 if (bb->is_parent())
01587 bb->set_valid_perturbers(false);
01588
01589 }
01590
01591 }
01592
01593
01594 #if 0000
01595 if (bb->name_is("(5394,21337)")
01596 || bb->name_is("(21337,5394)")) {
01597 cerr << func << ": repeating while loop with ";
01598 PRL(bb->get_grape_rnb_sq());
01599 }
01600 #endif
01601
01602
01603 }
01604
01605 }
01606
01607 inext++;
01608 }
01609
01610 return inext;
01611 }
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624 void grape_calculate_acc_and_jerk(hdyn **next_nodes,
01625 int n_next,
01626 xreal xtime,
01627 bool restart)
01628
01629
01630
01631
01632 {
01633 static char *func = "grape_calculate_acc_and_jerk";
01634
01635 static int n_pipes = 0;
01636
01637 static int nj_on_grape;
01638
01639
01640 if (DEBUG) {
01641 cerr << endl << func << "..." << endl << flush;
01642 }
01643
01644 if (n_pipes == 0) n_pipes = g6_npipes_();
01645
01646 if (n_next <= 0) return;
01647 hdyn *root = next_nodes[0]->get_root();
01648 kira_options *ko = root->get_kira_options();
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667 bool grape_reattached = false;
01668
01669 if (!grape_is_open) {
01670
01671 reattach_grape((real)xtime, func, ko);
01672
01673 if (!restart) grape_reattached = true;
01674
01675
01676
01677 restart = true;
01678 }
01679
01680 if (grape_was_used_to_calculate_potential) {
01681 restart = true;
01682 grape_was_used_to_calculate_potential = false;
01683 }
01684
01685 if (restart) {
01686
01687 nj_on_grape = initialize_grape_arrays(root, !grape_reattached);
01688 n_previous_nodes = 0;
01689 }
01690
01691
01692
01693
01694
01695
01696 for (int i = 0; i < n_previous_nodes; i++)
01697 send_j_node_to_grape(previous_nodes[i]);
01698
01699
01700
01701 int i, n_top;
01702
01703
01704
01705 for (n_top = i = 0; i < n_next; i++)
01706 if (next_nodes[i]->is_top_level_node())
01707 current_nodes[n_top++] = next_nodes[i];
01708
01709
01710
01711
01712
01713
01714 n_previous_nodes = n_top;
01715 bool need_neighbors = false;
01716
01717 for (i = 0; i < n_top; i++) {
01718
01719 hdyn *bb = previous_nodes[i] = current_nodes[i];
01720
01721
01722
01723 need_neighbors |= set_grape_neighbor_radius(bb, nj_on_grape);
01724
01725
01726
01727
01728 if (bb->is_parent())
01729 bb->set_valid_perturbers(true);
01730 }
01731
01732 if (DEBUG) {
01733 cerr << func << ": ";
01734 PRC(xtime); PRC(n_next); PRL(n_top);
01735 }
01736
01737
01738
01739
01740
01741 real h2_crit = 8192 * current_nodes[0]->get_d_min_sq();
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757 i = 0;
01758 while (i < n_top) {
01759
01760 int ni = min(n_pipes, n_top - i);
01761
01762 need_neighbors = false;
01763 for (int ip = 0; ip < ni; ip++)
01764 if (current_nodes[i+ip]->get_grape_rnb_sq() > 0) {
01765 need_neighbors = true;
01766 break;
01767 }
01768
01769 if (DEBUG > 1) {
01770 PRI(2); PRC(i); PRC(ni); PRL(need_neighbors);
01771 }
01772
01773
01774
01775
01776
01777
01778 if (get_force_and_neighbors(xtime, current_nodes + i, ni,
01779 nj_on_grape, n_pipes, need_neighbors))
01780
01781
01782
01783
01784
01785
01786 i += sort_nodes_and_reduce_rnb(current_nodes+i, ni);
01787
01788 else if (need_neighbors) {
01789
01790
01791
01792 i += get_coll_and_perturbers(xtime, current_nodes+i, ni,
01793 h2_crit, nj_on_grape, n_pipes);
01794 } else
01795
01796 i += ni;
01797
01798 }
01799
01800
01801
01802
01803
01804 for (i = 0; i < n_top ; i++) {
01805
01806 hdyn *bb = current_nodes[i];
01807
01808
01809 #if 0000
01810 if (bb->name_is("(5394,21337)")
01811 || bb->name_is("(21337,5394)"))
01812 cerr << "leaving " << func << endl << endl << flush;
01813 #endif
01814
01815
01816
01817
01818
01819 if (bb->is_leaf())
01820 bb->set_grape_nb_count((bb->get_grape_nb_count() + 1)%4);
01821 else
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835 bb->set_grape_nb_count(0);
01836 }
01837
01838 if (DEBUG) {
01839 cerr << "...leaving " << func << endl << endl << flush;
01840 }
01841 }
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858 local INLINE void set_grape_density_radius(hdyn *b, real rnn_sq)
01859
01860
01861
01862
01863
01864
01865 {
01866 if (b->get_nn() != NULL && b->get_nn() != b
01867 && b->get_d_nn_sq() < 0.1* VERY_LARGE_NUMBER
01868 && b->get_d_nn_sq() > 0) {
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880 if (DEBUG) {
01881 cerr << "nn OK for " << b->format_label() << ", ";
01882 PRC(rnn_sq); PRL(sqrt(b->get_d_nn_sq()));
01883 PRL(b->get_nn()->format_label());
01884 }
01885
01886 #if 0
01887 if (b->get_d_nn_sq() < rnn_sq)
01888 rnn_sq = sqrt(rnn_sq * b->get_d_nn_sq());
01889 else
01890 rnn_sq = b->get_d_nn_sq();
01891 #endif
01892
01893 rnn_sq = 5*b->get_d_nn_sq();
01894
01895 } else {
01896
01897
01898
01899
01900
01901
01902
01903
01904 rnn_sq = 4*max(rnn_sq, b->get_d_nn_sq());
01905
01906 if (DEBUG)
01907 cerr << "no nn for " << b->format_label() << ", ";
01908 }
01909
01910 b->set_grape_rnb_sq(rnn_sq);
01911 if (DEBUG) PRL(sqrt(b->get_grape_rnb_sq()));
01912 }
01913
01914
01915
01916 local void check_neighbors(hdyn *b, real rnb_sq, int indent = 0)
01917
01918
01919
01920 {
01921 int nn = 0;
01922 b = b->get_top_level_node();
01923 for_all_daughters(hdyn, b->get_root(), bb)
01924 if (bb != b)
01925 if (square(bb->get_pos() - b->get_pos()) < rnb_sq) nn++;
01926 PRI(indent);
01927 cerr << "check: " << nn << " neighbors within " << sqrt(rnb_sq)
01928 << " of " << b->format_label() << endl;
01929 }
01930
01931
01932
01933 #define N_DENS 12 // density is based on the 12th nearest neighbor
01934
01935 local INLINE bool count_neighbors_and_adjust_h2(hdyn * b, int pipe)
01936
01937
01938
01939
01940
01941
01942 {
01943
01944
01945 int n_neighbors = 0;
01946 int status = 0;
01947 #ifndef NO_G6_NEIGHBOUR_LIST
01948 status = g6_get_neighbour_list_(&cluster_id,
01949 &pipe,
01950 &max_neighbors,
01951 &n_neighbors,
01952 neighbor_list);
01953 #endif
01954
01955
01956
01957
01958 if (status) {
01959
01960
01961
01962
01963
01964
01965 if (n_neighbors >= max_neighbors) {
01966
01967 real rnb_fac = pow(10*N_DENS/(real)n_neighbors, 0.6666667);
01968 b->set_grape_rnb_sq(rnb_fac*b->get_grape_rnb_sq());
01969
01970 cerr << "count_neighbors_and_adjust_h2: "
01971 << "neighbor list overflow for "
01972 << b->format_label() << " (pipe "
01973 << pipe << ")" << endl;
01974 PRC(n_neighbors); PRC(max_neighbors);
01975 cerr << "new grape_rnb = " << sqrt(b->get_grape_rnb_sq())
01976 << endl;
01977
01978 return false;
01979 }
01980 }
01981
01982 if (n_neighbors < N_DENS) {
01983
01984
01985
01986 if (DEBUG > 1) {
01987 cerr << " increasing grape_rnb_sq for " << b->format_label()
01988 << " (n_neighbors = " << n_neighbors << ", grape_rnb = "
01989 << sqrt(b->get_grape_rnb_sq()) << ")" << endl;
01990 }
01991
01992
01993
01994
01995
01996
01997 #if 0
01998 real fac = 1.25;
01999 if (n_neighbors < 12) fac *= 1.25;
02000 if (n_neighbors < 8) fac *= 1.6;
02001 if (n_neighbors < 4) fac *= 1.6;
02002 if (n_neighbors < 2) fac *= 1.6;
02003 #endif
02004
02005 real fac = min(2.0, pow((N_DENS+3.0)/(1.0+n_neighbors), 1.5));
02006
02007 b->set_grape_rnb_sq(fac * b->get_grape_rnb_sq());
02008 return false;
02009 }
02010
02011
02012
02013 dyn **dynlist = new dynptr[n_neighbors];
02014
02015 real d_max = 0;
02016 for (int j = 0; j < n_neighbors; j++) {
02017
02018 hdyn *bb = node_list[neighbor_list[j]];
02019 dynlist[j] = (dyn*)bb;
02020
02021
02022
02023 if (DEBUG > 1) {
02024 if (bb != b) {
02025 vector diff = b->get_pred_pos() - bb->get_pred_pos();
02026 real d2 = diff * diff;
02027 d_max = max(d_max, d2);
02028 }
02029 }
02030 }
02031
02032 if (DEBUG > 1) {
02033 real grape_rnb = sqrt(b->get_grape_rnb_sq());
02034 d_max = sqrt(d_max);
02035 cerr << " " << b->format_label() << ": ";
02036 PRC(n_neighbors), PRC(grape_rnb), PRL(d_max);
02037 }
02038
02039 compute_density(b, N_DENS, dynlist, n_neighbors);
02040
02041
02042
02043
02044 if (DEBUG > 1) {
02045 if (find_qmatch(b->get_dyn_story(), "density_time")
02046 && find_qmatch(b->get_dyn_story(), "density_k_level")
02047 && find_qmatch(b->get_dyn_story(), "density")) {
02048
02049 real density_time = getrq(b->get_dyn_story(), "density_time");
02050 int density_k = getiq(b->get_dyn_story(), "density_k_level");
02051 real density = getrq(b->get_dyn_story(), "density");
02052
02053 PRI(4); cerr << b->format_label() << ": ";
02054 PRC(density_time); PRC(density_k); PRL(density);
02055 PRI(4); PRL(b->get_pos());
02056 check_neighbors(b, b->get_grape_rnb_sq(), 4);
02057
02058 } else {
02059
02060 PRI(4); cerr << "density data unavailable for "
02061 << b->format_label() << endl;
02062 }
02063 }
02064
02065 delete [] dynlist;
02066 return true;
02067 }
02068
02069
02070
02071 local INLINE bool get_densities(xreal xtime, hdyn *nodes[],
02072 int ni, real h2_crit,
02073 int nj_on_grape, int n_pipes)
02074 {
02075
02076
02077
02078
02079 static char *func = "get_densities";
02080 bool error = false;
02081
02082 if (DEBUG)
02083 cerr << func << "..." << nodes[0]->format_label()
02084 << " " << nodes[0]->get_grape_rnb_sq() << endl << flush;
02085
02086 if (ni < 0) return error;
02087
02088
02089
02090 int status = 0;
02091 if (status = get_force_and_neighbors(xtime, nodes, ni,
02092 nj_on_grape, n_pipes, true)) {
02093
02094
02095
02096
02097 cerr << func << ": " << "error 1 getting GRAPE neighbor data: ";
02098 PRL(status);
02099
02100 error = true;
02101
02102 } else {
02103
02104
02105
02106 for (int ip = 0; ip < ni; ip++) {
02107
02108 int n_retry = 0;
02109 hdyn *bb = nodes[ip];
02110
02111 if (bb->get_grape_rnb_sq() > 0) {
02112
02113 while (!count_neighbors_and_adjust_h2(bb, ip)) {
02114
02115
02116
02117 if (bb->get_grape_rnb_sq() > h2_crit) {
02118
02119
02120
02121 putrq(bb->get_dyn_story(), "density_time",
02122 (real)bb->get_system_time());
02123 putrq(bb->get_dyn_story(), "density", 0.0);
02124
02125 if (DEBUG > 1) {
02126 PRI(2); PR(bb->get_grape_rnb_sq());
02127 cerr << " too large for "
02128 << bb->format_label() << endl;
02129 PRI(2); PRL(bb->get_pos());
02130 check_neighbors(bb, bb->get_grape_rnb_sq(), 2);
02131 }
02132
02133 break;
02134
02135 } else {
02136
02137
02138
02139
02140
02141
02142
02143
02144
02145
02146 if (++n_retry > 20)
02147 hw_err_exit(func, 2, nodes[0]);
02148
02149 if (DEBUG > 1
02150 || (DEBUG > 0 && n_retry > 4 && n_retry%5 == 0)
02151 || (n_retry > 9 && n_retry%10 == 0) ) {
02152 PRI(2); cerr << func << ": recomputing forces for "
02153 << nodes[0]->format_label() << " + " << ni-1
02154 << endl;
02155 cerr << " first rnb_sq = "
02156 << nodes[0]->get_grape_rnb_sq()
02157 << ", n_retry = " << n_retry << endl;
02158 }
02159
02160 int status = 0;
02161 if (status = get_force_and_neighbors(xtime, nodes, ni,
02162 nj_on_grape, n_pipes, true)) {
02163
02164 cerr << func << ": "
02165 << "error 2 getting GRAPE neighbor data: ";
02166 PRL(status);
02167
02168 error = true;
02169
02170 ip = ni;
02171 break;
02172 }
02173 }
02174 }
02175
02176 if (!error)
02177 bb->set_grape_rnb_sq(0);
02178 }
02179 }
02180 }
02181
02182 if (DEBUG) {
02183 cerr << "leaving " << func << "...";
02184 PRL(error);
02185 }
02186
02187 return error;
02188 }
02189
02190
02191
02192
02193
02194
02195
02196
02197
02198
02199
02200
02201 void grape_calculate_densities(hdyn* b,
02202 real h2_crit)
02203 {
02204 static char *func = "grape_calculate_densities";
02205
02206 if (DEBUG) {
02207 cerr << endl << func << "..."; PRL(h2_crit);
02208 }
02209
02210 #ifdef NO_G6_NEIGHBOUR_LIST
02211 cerr << "No hardware neighbor list available..." << endl;
02212 return;
02213 #endif
02214
02215 static int max_neighbors = MAX_PERTURBERS;
02216 static int neighbor_list[MAX_PERTURBERS];
02217
02218 if (!grape_is_open)
02219 reattach_grape(b->get_real_system_time(), func, b->get_kira_options());
02220
02221
02222
02223 int nj_on_grape = initialize_grape_arrays(b,
02224 true,
02225 true);
02226
02227
02228
02229 hdyn **top_nodes = new hdynptr[nj_on_grape];
02230
02231 int n_top = 0;
02232 for_all_daughters(hdyn, b, bb)
02233 top_nodes[n_top++] = bb;
02234
02235
02236
02237
02238
02239
02240
02241
02242
02243 real r90_sq = b->get_d_min_sq() / square(b->get_d_min_fac());
02244 real rnn_sq = r90_sq * pow((real)nj_on_grape, 4.0/3);
02245
02246 for (int j = 0; j < n_top; j++)
02247
02248 set_grape_density_radius(top_nodes[j], rnn_sq);
02249
02250 int n_pipes = g6_npipes_();
02251
02252 int n_retry = 0;
02253 int count = 0;
02254
02255
02256
02257 int i = 0;
02258
02259 while (i < n_top) {
02260
02261 int inext = i;
02262 int ni = min(n_pipes, n_top - i);
02263
02264 #ifdef SPZ_GRAPE6
02265
02266
02267
02268
02269
02270 ni = 1;
02271 #endif
02272
02273
02274
02275
02276
02277
02278
02279 if (get_densities(b->get_system_time(),
02280 top_nodes + i, ni, h2_crit,
02281 nj_on_grape, n_pipes)) {
02282
02283
02284
02285
02286 if (DEBUG) {
02287 cerr << "reducing neighbor radii: i = " << i
02288 << ", first rnb_sq = " << top_nodes[i]->get_grape_rnb_sq()
02289 << endl;
02290 }
02291
02292
02293
02294 for (int j = i; j < i + ni; j++) {
02295 hdyn *bb = top_nodes[j];
02296 bb->set_grape_rnb_sq(0.9 * bb->get_grape_rnb_sq());
02297 }
02298
02299 n_retry++;
02300 if (++count > 20) {
02301
02302
02303
02304 cerr << func << ": "
02305 << "error getting GRAPE neighbor data: " << endl;
02306
02307 hw_err_exit(func, 1, b);
02308 }
02309
02310 } else {
02311
02312
02313
02314 i += ni;
02315 count = 0;
02316 }
02317 }
02318
02319
02320
02321 putrq(b->get_dyn_story(), "density_time", (real)b->get_system_time());
02322
02323 if (n_retry > 10) {
02324 cerr << func << ": ";
02325 PRL(n_retry);
02326 }
02327
02328 if (DEBUG)
02329 cerr << "...leaving " << func << endl << endl << flush;
02330
02331
02332
02333 grape_was_used_to_calculate_potential = true;
02334 delete [] top_nodes;
02335 }
02336
02337
02338
02339
02340
02341
02342
02343
02344
02345 void clean_up_hdyn_grape()
02346
02347
02348
02349 {
02350
02351
02352 if (node_list) delete [] node_list;
02353 if (current_nodes) delete [] current_nodes;
02354 if (previous_nodes) delete [] previous_nodes;
02355
02356
02357
02358 if (iindex) delete [] iindex;
02359 if (ipos) delete [] ipos;
02360 if (ivel) delete [] ivel;
02361 if (iacc) delete [] iacc;
02362 if (ijerk) delete [] ijerk;
02363 if (ipot) delete [] ipot;
02364 if (ih2) delete [] ih2;
02365 if (inn) delete [] inn;
02366 }