00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifdef USE_MPI
00021 #include "mpi++.h"
00022 #else
00023 #include "localmpi++.h"
00024 #endif
00025
00026 #include "scatter.h"
00027 #include "sigma.h"
00028
00029
00030
00031
00032 #ifndef TOOLBOX
00033
00034
00035 ostream& operator<<(ostream& s, scatter_input& i) {
00036
00037 s << "Scatter_input: " << endl;
00038 s << "Input string: " << i.init_string << endl;
00039 s << " i.dt = " << i.delta_t << " " << i.dt_out << " " << i.dt_snap << endl;
00040 s << " eta= " << i.eta << endl;
00041 s << " tol= " << i.tidal_tol_factor << endl;
00042 s << " Cs= " << i.snap_cube_size << " dt cpu= " << i.cpu_time_check << endl;
00043 s << " e_exp= " << i.n_experiments << endl;
00044 s << " rnd= " << i.seed << " "<< i.n_rand <<" "<<i.n_rand_inc<<" "
00045 << i.pipe << " "<< i.debug;
00046
00047 return s;
00048
00049 }
00050
00051 void ppn(sdyn* b, ostream & s, int level) {
00052
00053 s.precision(3);
00054
00055 for (int i = 0; i < 2*level; i++) s << " ";
00056
00057 if(b != b->get_root()) {
00058 b->pretty_print_node(s);
00059 cerr << endl;
00060 s << " "<< b->get_mass() << " "
00061 << b->get_pos() << " (r= " << abs(b->get_pos()) << ") "
00062 << b->get_vel() << " (v= " << abs(b->get_vel()) << ")" << endl;
00063
00064
00065 }
00066
00067 for (sdyn * daughter = b->get_oldest_daughter();
00068 daughter != NULL;
00069 daughter = daughter->get_younger_sister())
00070 ppn(daughter, s, level + 1);
00071 }
00072
00073
00074 #define DT_CHECK 20
00075
00076
00077
00078
00079
00080 void scatter(sdyn* b, scatter_input input,
00081 scatter_exp &experiment) {
00082
00083 scatter(b, input.eta,
00084 input.delta_t, input.dt_out, input.cpu_time_check,
00085 input.dt_snap, input.tidal_tol_factor, input.snap_cube_size,
00086 input.debug,
00087 experiment);
00088
00089 }
00090
00091 void scatter(sdyn* b, real eta,
00092 real delta_t, real dt_out, real cpu_time_check,
00093 real dt_snap, real ttf, real snap_cube_size,
00094 int debug,
00095 scatter_exp &experiment) {
00096
00097 experiment.init_scatter_exp(b);
00098
00099 real de_merge = 0;
00100 int stop_at_cpu = 0;
00101 real cpu_save = cpu_time();
00102 bool terminate = false;
00103
00104 real t_out = b->get_time_offset();
00105 real t_end = delta_t + (real)b->get_time_offset();
00106
00107 char previous_form[255];
00108 char current_form[255];
00109 strcpy(current_form, get_normal_form(b));
00110
00111 real kin=0, pot=0;
00112 b->flatten_node();
00113 real etot_init = calculate_energy_from_scratch(b, kin, pot);
00114 make_tree(b, DYNAMICS, STABILITY, K_MAX, debug);
00115
00116
00117
00118 for (real t = 0; t <= VERY_LARGE_NUMBER; t += DT_CHECK) {
00119
00120 terminate = tree_evolve(b, DT_CHECK, dt_out, dt_snap,
00121 snap_cube_size,
00122 eta, cpu_time_check);
00123
00124 calculate_energy(b, kin, pot);
00125 if (debug) {
00126 cerr.precision(6), cerr << "\nStatus at time " << b->get_time();
00127 cerr.precision(9), cerr << " (energy = " << kin + pot << "):\n";
00128 cerr.precision(6);
00129 }
00130
00131
00132
00133
00134 if (cpu_time_check < 0
00135 && cpu_time() - cpu_save > abs(cpu_time_check)) {
00136 cerr <<" tcpu>tcpu_check"<<endl;
00137 return;
00138 }
00139
00140 if(t>=dt_out) {
00141
00142 real ekin, epot;
00143 calculate_energy(b, ekin, epot);
00144 if(debug==1) {
00145 cerr << "Time = " << b->get_time()
00146 << " Etot = " << ekin + epot
00147 << " Tinf = " << ekin/epot << endl;
00148 }
00149 put_sdyn(cout, *b);
00150 t_out += dt_out;
00151 }
00152
00153 if(t>=t_end) {
00154 cerr << "Early termination"<<endl;
00155
00156 experiment.set_scatter_discriptor(stopped);
00157 experiment.set_stop(true);
00158 real ekin, epot;
00159 calculate_energy(b, ekin, epot);
00160 cerr << "Time = " << b->get_time()
00161 << " Etot = " << ekin + epot << endl;
00162 break;
00163 }
00164
00165 int coll_flag = 2;
00166 de_merge += merge_collisions(b, coll_flag);
00167
00168 make_tree(b, DYNAMICS, STABILITY, K_MAX, false);
00169
00170 int unbound = extend_or_end_scatter(b, ttf, false);
00171 if(unbound==2) {
00172 experiment.set_final_bound(true);
00173 unbound = 1;
00174 }
00175
00176
00177 if (unbound || terminate) break;
00178
00179
00180
00181 strcpy(previous_form, current_form);
00182 strcpy(current_form, get_normal_form(b));
00183 if(strcmp(previous_form, current_form))
00184 experiment.inc_form_changes();
00185
00186
00187 }
00188
00189 b->flatten_node();
00190 real etot_error = calculate_energy_from_scratch(b, kin, pot)
00191 - etot_init - de_merge;
00192 experiment.set_energy_error(etot_error);
00193
00194
00195 make_tree(b, DYNAMICS, STABILITY, K_MAX, debug);
00196
00197
00198 experiment.final_scatter_exp(b);
00199
00200
00201 }
00202
00203
00204 #else
00205
00206 void slave_part_of_experiment(scatter_input input,
00207 scatter_exp &experiment) {
00208
00209 int random_seed = srandinter(input.seed, input.n_rand);
00210
00211 cerr << "Random seed = " << get_initial_seed()
00212 << " n_rand = " << get_n_rand() << flush << "\n";
00213
00214 sdyn *b = mkscat(input.init_string);
00215
00216 b->flatten_node();
00217
00218 real kin, pot;
00219 real etot_init = calculate_energy_from_scratch(b, kin, pot);
00220 cerr << "Time = " << 0
00221 << " Etot = " << kin + pot
00222 << " (" << kin << ", " << pot
00223 << ") Tinf = " << kin/pot << endl;
00224 make_tree(b, !DYNAMICS, STABILITY, K_MAX, input.debug);
00225
00226
00227 b->set_name("root");
00228
00229 #if 0
00230 cerr << "*** Initial configuration (random seed = "
00231 << get_initial_seed() << "):\n";
00232 print_normal_form(b, cerr);
00233
00234 vector center = b->get_pos();
00235 print_structure_recursive(b, 0., center, true, true, 4);
00236 #endif
00237
00238
00239 scatter(b, input, experiment);
00240
00241 cerr.precision(6);
00242 if (input.debug) cerr << endl;
00243
00244 #if 0
00245 cerr << "*** Final system configuration (time = "
00246 << b->get_time() << "):\n";
00247 print_normal_form(b, cerr);
00248
00249 ppn(b, cerr);
00250
00251 print_structure_recursive(b, 0., center, true, true, 4);
00252
00253 cerr << "Energy error = " << experiment.get_energy_error() << endl;
00254
00255 cerr << "Final Normal form: ";
00256 print_normal_form(b, cerr);
00257 #endif
00258
00259 delete b;
00260
00261 }
00262
00263 void slave_process(int master,
00264 scatter_input &input, MPI_Datatype inputtype,
00265 scatter_exp &experiment, MPI_Datatype scatter_exp_type) {
00266
00267 int myid = MPI::COMM_WORLD.Get_rank();
00268
00269 int length = 1;
00270
00271 int request_for_data = 1;
00272 int data_available;
00273 int sending_data;
00274
00275 do {
00276
00277 request_for_data = myid;
00278 MPI::COMM_WORLD.Send(&request_for_data, length, MPI::INT, master,
00279 DATA_REQUEST_TAG);
00280 MPI::COMM_WORLD.Recv(&data_available, length, MPI::INT, master,
00281 DATA_REQUEST_TAG);
00282
00283 if(data_available<=0) {
00284 cerr << "Terminate slave "<< myid<<endl;
00285 return;
00286 }
00287
00288 MPI::COMM_WORLD.Recv(&input, length, inputtype, master,
00289 DATA_COMING_TAG);
00290 MPI::COMM_WORLD.Recv(&experiment, length, scatter_exp_type, master,
00291 DATA_COMING_TAG);
00292
00293 slave_part_of_experiment(input, experiment);
00294
00295 cerr << "Send by slave "<<flush;
00296 PRL(experiment.get_final_form());
00297
00298 sending_data = myid;
00299 MPI::COMM_WORLD.Send(&sending_data, length, MPI::INT, master,
00300 DATA_COMING_TAG);
00301 MPI::COMM_WORLD.Send(&experiment, length, scatter_exp_type,
00302 master, DATA_COMING_TAG);
00303 }
00304 while(true);
00305
00306 }
00307
00308 void master_process(scatter_input &input, MPI_Datatype inputtype,
00309 scatter_exp &experiment, MPI_Datatype scatter_exp_type) {
00310
00311 int myid = MPI::COMM_WORLD.Get_rank();
00312 int nproc = MPI::COMM_WORLD.Get_size();
00313
00314 int accept_all_senders = MPI::ANY_SOURCE;
00315
00316
00317 int random_seed = srandinter(input.seed, input.n_rand);
00318 input.n_rand_inc = get_n_rand() - input.n_rand;
00319
00320
00321 sdyn *b = mkscat(input.init_string);
00322 scatter_hist *hi = initialize_scatter_hist(b);
00323 delete b;
00324 b = NULL;
00325
00326 input.n_rand_inc = get_n_rand() - input.n_rand;
00327
00328 int length = 1;
00329 int nsend = 0;
00330 int i;
00331
00332 int n_exp = 0;
00333
00334 int slave;
00335 int request_for_data;
00336 int data_available = 1;
00337 int slave_sends_data;
00338
00339 do {
00340
00341 MPI::COMM_WORLD.Recv(&request_for_data, length, MPI::INT,
00342 accept_all_senders, DATA_REQUEST_TAG);
00343 slave = request_for_data;
00344 MPI::COMM_WORLD.Send(&data_available, length, MPI::INT, slave,
00345 DATA_REQUEST_TAG);
00346
00347 if (input.n_experiments > 1) cerr << "Experiment #" << n_exp
00348 << ": " << "\n";
00349
00350 input.n_rand += input.n_rand_inc;
00351 PRC(input.n_rand);PRL(input.n_rand_inc);
00352
00353 MPI::COMM_WORLD.Send(&input, length, inputtype, slave,
00354 DATA_COMING_TAG);
00355 MPI::COMM_WORLD.Send(&experiment, length, scatter_exp_type, slave,
00356 DATA_COMING_TAG);
00357 nsend++;
00358
00359 MPI::COMM_WORLD.Recv(&slave_sends_data, length, MPI::INT,
00360 accept_all_senders, DATA_COMING_TAG);
00361 slave = slave_sends_data;
00362 MPI::COMM_WORLD.Recv(&experiment, length, scatter_exp_type,
00363 slave, DATA_COMING_TAG);
00364
00365
00366
00367 hi->add_scatter_hist(experiment, 0);
00368
00369
00370
00371
00372 n_exp++;
00373 }
00374 while(n_exp < input.n_experiments);
00375
00376 cerr << "Start terminating all processes"<<endl;
00377
00378 data_available = 0;
00379 for(i=1; i<nproc; i++) {
00380
00381 nsend++;
00382
00383 MPI::COMM_WORLD.Recv(&request_for_data, length, MPI::INT,
00384 accept_all_senders, DATA_REQUEST_TAG);
00385
00386 slave = request_for_data;
00387 cerr << "Send termination signal to slave " << slave << endl;
00388 MPI::COMM_WORLD.Send(&data_available, length, MPI::INT, slave,
00389 DATA_REQUEST_TAG);
00390 }
00391
00392 cerr << "scatter history" << flush << endl;
00393 hi->put_scatter_hist(cerr, false);
00394 cerr << "Master ends"<<endl;
00395 }
00396
00397 void execute_scatter_experiment(scatter_input input) {
00398
00399 int argc = 0;
00400 char ** argv = NULL;
00401 MPI::Init(argc, argv);
00402 int myid = MPI::COMM_WORLD.Get_rank();
00403 int nproc = MPI::COMM_WORLD.Get_size();
00404
00405
00406 int inputblockcounts[3] = {255, 7, 6};
00407 MPI_Datatype ntypes[3];
00408 MPI::Aint displs[3];
00409 MPI_Datatype inputtype;
00410
00411 MPI_Address(&input.init_string, &displs[0]);
00412 MPI_Address(&input.delta_t, &displs[1]);
00413 MPI_Address(&input.n_experiments, &displs[2]);
00414 ntypes[0] = MPI::CHAR;
00415 ntypes[1] = MPI::DOUBLE;
00416 ntypes[2] = MPI::INT;
00417 displs[1] -= displs[0];
00418 displs[2] -= displs[0];
00419 displs[0] = 0;
00420
00421 MPI_Type_struct(3, inputblockcounts, displs, ntypes, &inputtype);
00422 MPI_Type_commit(&inputtype);
00423
00424 scatter_exp experiment;
00425
00426
00427 int charlength = 255 + 255;
00428 int reallength = 4;
00429 int intlength = 10 + 2*N_RHO_ZONE_MAX + N_STEP_BIN + N_OSC_BIN;
00430 int boolength = 3 + intlength;
00431 int blockcounts[3] = {charlength, reallength, boolength};
00432 MPI::Aint exp_displs[3];
00433 MPI_Datatype scatter_exp_type;
00434
00435 MPI_Address(experiment.get_initial_form(), &exp_displs[0]);
00436 MPI_Address(experiment.get_time_ptr(), &exp_displs[1]);
00437 MPI_Address(experiment.get_scatter_discriptor_ptr(), &exp_displs[2]);
00438 MPI_Datatype nexp_types[3] = {MPI::CHAR, MPI::DOUBLE, MPI::INT};
00439 exp_displs[1] -= exp_displs[0];
00440
00441 exp_displs[2] -= exp_displs[0];
00442 exp_displs[0] = 0;
00443
00444 MPI_Type_struct(3, blockcounts, exp_displs, nexp_types, &scatter_exp_type);
00445 MPI_Type_commit(&scatter_exp_type);
00446
00447 int master = 0;
00448 if(myid==master) {
00449 master_process(input, inputtype,
00450 experiment, scatter_exp_type);
00451 }
00452 else {
00453 slave_process(master,
00454 input, inputtype,
00455 experiment, scatter_exp_type);
00456 }
00457
00458 MPI::Finalize();
00459
00460 }
00461
00462 main(int argc, char **argv) {
00463
00464 scatter_input input;
00465 char* default_init
00466 = "-M 0.879 -rm 3 -v 2 -r 1 -t -r1 0.0508 -r2 0.0348 -e 0 -q 0.567 -p -a 1 -q 1 -r1 0.0394 -r2 0.0394";
00467
00468 strcpy(&input.init_string[0], default_init);
00469
00470
00471 bool D_flag = false;
00472 check_help();
00473
00474 extern char *poptarg;
00475 int c;
00476 char* param_string = "A:c:C:d:D:g:i:n:N:ps:t:v";
00477
00478 while ((c = pgetopt(argc, argv, param_string)) != -1)
00479 switch(c) {
00480
00481 case 'A': input.eta = atof(poptarg);
00482 break;
00483 case 'c': input.cpu_time_check = atof(poptarg);
00484 break;
00485 case 'C': input.snap_cube_size = atof(poptarg);
00486 break;
00487 case 'd': input.dt_out = atof(poptarg);
00488 break;
00489 case 'D': D_flag = TRUE;
00490 input.dt_snap = atof(poptarg);
00491 break;
00492 case 'g': input.tidal_tol_factor = atof(poptarg);
00493 break;
00494 case 'i': strcpy(&input.init_string[0], poptarg);
00495 break;
00496 case 'n': input.n_experiments = atoi(poptarg);
00497 break;
00498 case 'N': input.n_rand = atoi(poptarg);
00499 break;
00500 case 'p': input.pipe = 1 - input.pipe;
00501 break;
00502 case 't': input.delta_t = atof(poptarg);
00503 break;
00504 case 'v': input.debug = 1 - input.debug;
00505 break;
00506 case 's': input.seed = atoi(poptarg);
00507 break;
00508 case '?': params_to_usage(cerr, argv[0], param_string);
00509 get_help();
00510 }
00511
00512 cerr << input << endl;
00513
00514 if (!D_flag) input.dt_snap = input.delta_t;
00515
00516 execute_scatter_experiment(input);
00517
00518 }
00519 #endif
00520
00521
00522
00523
00524
00525
00526
00527