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