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