![]() |
ESPResSo 3.2.0-167-g2c9ead1-git
Extensible Simulation Package for Soft Matter Research
|
00001 /* 00002 Copyright (C) 2010,2011,2012,2013 The ESPResSo project 00003 Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010 00004 Max-Planck-Institute for Polymer Research, Theory Group 00005 00006 This file is part of ESPResSo. 00007 00008 ESPResSo is free software: you can redistribute it and/or modify 00009 it under the terms of the GNU General Public License as published by 00010 the Free Software Foundation, either version 3 of the License, or 00011 (at your option) any later version. 00012 00013 ESPResSo is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 GNU General Public License for more details. 00017 00018 You should have received a copy of the GNU General Public License 00019 along with this program. If not, see <http://www.gnu.org/licenses/>. 00020 */ 00021 #include <mpi.h> 00022 #include <stdio.h> 00023 #include <stdlib.h> 00024 #include <string.h> 00025 #include "utils.h" 00026 #include "communication.h" 00027 #include "interaction_data.h" 00028 #include "particle_data.h" 00029 #include "integrate.h" 00030 #include "cells.h" 00031 #include "global.h" 00032 #include "grid.h" 00033 #include "initialize.h" 00034 #include "forces.h" 00035 #include "rotation.h" 00036 #include "p3m.h" 00037 #include "statistics.h" 00038 #include "energy.h" 00039 #include "pressure.h" 00040 #include "random.h" 00041 #include "lj.h" 00042 #include "lb.h" 00043 #include "lb-boundaries.h" 00044 #include "morse.h" 00045 #include "buckingham.h" 00046 #include "tab.h" 00047 #include "overlap.h" 00048 #include "ljcos.h" 00049 #include "ljangle.h" 00050 #include "gb.h" 00051 #include "mmm1d.h" 00052 #include "mmm2d.h" 00053 #include "maggs.h" 00054 #include "elc.h" 00055 #include "iccp3m.h" 00056 #include "statistics_chain.h" 00057 #include "statistics_fluid.h" 00058 #include "virtual_sites.h" 00059 #include "topology.h" 00060 #include "errorhandling.h" 00061 #include "molforces.h" 00062 #include "mdlc_correction.h" 00063 #include "reaction.h" 00064 #include "galilei.h" 00065 #include "cuda_common.h" 00066 00067 00068 int this_node = -1; 00069 int n_nodes = -1; 00070 MPI_Comm comm_cart; 00071 /********************************************** 00072 * slave callbacks. 00073 **********************************************/ 00074 typedef void (SlaveCallback)(int node, int param); 00075 00076 // if you want to add a callback, add it here, and here only 00077 #define CALLBACK_LIST \ 00078 CB(mpi_stop_slave) \ 00079 CB(mpi_bcast_parameter_slave) \ 00080 CB(mpi_who_has_slave) \ 00081 CB(mpi_bcast_event_slave) \ 00082 CB(mpi_place_particle_slave) \ 00083 CB(mpi_send_v_slave) \ 00084 CB(mpi_send_f_slave) \ 00085 CB(mpi_send_q_slave) \ 00086 CB(mpi_send_type_slave) \ 00087 CB(mpi_send_bond_slave) \ 00088 CB(mpi_recv_part_slave) \ 00089 CB(mpi_integrate_slave) \ 00090 CB(mpi_bcast_ia_params_slave) \ 00091 CB(mpi_bcast_n_particle_types_slave) \ 00092 CB(mpi_gather_stats_slave) \ 00093 CB(mpi_set_time_step_slave) \ 00094 CB(mpi_get_particles_slave) \ 00095 CB(mpi_bcast_coulomb_params_slave) \ 00096 CB(mpi_send_ext_force_slave) \ 00097 CB(mpi_send_ext_torque_slave) \ 00098 CB(mpi_place_new_particle_slave) \ 00099 CB(mpi_remove_particle_slave) \ 00100 CB(mpi_bcast_constraint_slave) \ 00101 CB(mpi_random_seed_slave) \ 00102 CB(mpi_random_stat_slave) \ 00103 CB(mpi_cap_forces_slave) \ 00104 CB(mpi_bit_random_seed_slave) \ 00105 CB(mpi_bit_random_stat_slave) \ 00106 CB(mpi_get_constraint_force_slave) \ 00107 CB(mpi_rescale_particles_slave) \ 00108 CB(mpi_bcast_cell_structure_slave) \ 00109 CB(mpi_send_quat_slave) \ 00110 CB(mpi_send_omega_slave) \ 00111 CB(mpi_send_torque_slave) \ 00112 CB(mpi_send_mol_id_slave) \ 00113 CB(mpi_bcast_nptiso_geom_slave) \ 00114 CB(mpi_update_mol_ids_slave) \ 00115 CB(mpi_sync_topo_part_info_slave) \ 00116 CB(mpi_send_mass_slave) \ 00117 CB(mpi_send_solvation_slave) \ 00118 CB(mpi_gather_runtime_errors_slave) \ 00119 CB(mpi_send_exclusion_slave) \ 00120 CB(mpi_bcast_lb_params_slave) \ 00121 CB(mpi_bcast_cuda_global_part_vars_slave) \ 00122 CB(mpi_send_dip_slave) \ 00123 CB(mpi_send_dipm_slave) \ 00124 CB(mpi_send_fluid_slave) \ 00125 CB(mpi_recv_fluid_slave) \ 00126 CB(mpi_local_stress_tensor_slave) \ 00127 CB(mpi_send_virtual_slave) \ 00128 CB(mpi_bcast_tf_params_slave) \ 00129 CB(mpi_iccp3m_iteration_slave) \ 00130 CB(mpi_iccp3m_init_slave) \ 00131 CB(mpi_send_rotational_inertia_slave) \ 00132 CB(mpi_bcast_lbboundary_slave) \ 00133 CB(mpi_send_mu_E_slave) \ 00134 CB(mpi_bcast_max_mu_slave) \ 00135 CB(mpi_send_vs_relative_slave) \ 00136 CB(mpi_recv_fluid_populations_slave) \ 00137 CB(mpi_send_fluid_populations_slave) \ 00138 CB(mpi_recv_fluid_boundary_flag_slave) \ 00139 CB(mpi_set_particle_temperature_slave) \ 00140 CB(mpi_set_particle_gamma_slave) \ 00141 CB(mpi_kill_particle_motion_slave) \ 00142 CB(mpi_kill_particle_forces_slave) \ 00143 CB(mpi_system_CMS_slave) \ 00144 CB(mpi_system_CMS_velocity_slave) \ 00145 CB(mpi_galilei_transform_slave) \ 00146 CB(mpi_setup_reaction_slave) \ 00147 CB(mpi_send_rotation_slave) \ 00148 00149 // create the forward declarations 00150 #define CB(name) void name(int node, int param); 00151 CALLBACK_LIST 00152 00153 // create the list of callbacks 00154 #undef CB 00155 #define CB(name) name, 00156 static SlaveCallback *slave_callbacks[] = { 00157 CALLBACK_LIST 00158 }; 00159 00160 const int N_CALLBACKS = sizeof(slave_callbacks)/sizeof(SlaveCallback*); 00161 00162 // create the list of names 00163 #undef CB 00164 #define CB(name) #name, 00165 00166 char *names[] = { 00167 CALLBACK_LIST 00168 }; 00169 00170 // tag which is used by MPI send/recv inside the slave functions 00171 #define SOME_TAG 42 00172 00173 00174 /** The requests are compiled statically here, so that after a crash 00175 you can get the last issued request from the debugger. */ 00176 static int request[3]; 00177 00178 /********************************************** 00179 * procedures 00180 **********************************************/ 00181 00182 #ifdef MPI_CORE 00183 void mpi_core(MPI_Comm *comm, int *errcode,...) { 00184 int len; 00185 char string[1024]; 00186 MPI_Error_string(*errcode, string, &len); 00187 fprintf(stderr, "%d: Aborting due to MPI error %d: %s. Forcing core dump.\n", this_node, *errcode, string); 00188 core(); 00189 } 00190 #endif 00191 00192 void mpi_init(int *argc, char ***argv) 00193 { 00194 #ifdef MPI_CORE 00195 MPI_Errhandler mpi_errh; 00196 #endif 00197 00198 MPI_Init(argc, argv); 00199 00200 MPI_Comm_size(MPI_COMM_WORLD, &n_nodes); 00201 00202 int periodic[3]={1,1,1}, reorder = 1; 00203 MPI_Dims_create(n_nodes, 3, node_grid); 00204 00205 MPI_Cart_create(MPI_COMM_WORLD, 3, node_grid, periodic, reorder, &comm_cart); 00206 00207 MPI_Comm_rank(comm_cart, &this_node); 00208 00209 MPI_Cart_coords(comm_cart, this_node, 3, node_pos); 00210 00211 #ifdef MPI_CORE 00212 MPI_Errhandler_create((MPI_Handler_function *)mpi_core, &mpi_errh); 00213 MPI_Errhandler_set(comm_cart, mpi_errh); 00214 #endif 00215 } 00216 00217 static void mpi_call(SlaveCallback cb, int node, int param) { 00218 // find req number in callback array 00219 int reqcode; 00220 for (reqcode = 0; reqcode < N_CALLBACKS; reqcode++) { 00221 if (cb == slave_callbacks[reqcode]) break; 00222 } 00223 00224 if (reqcode >= N_CALLBACKS) { 00225 fprintf(stderr, "%d: INTERNAL ERROR: unknown callback %d called\n", this_node, reqcode); 00226 errexit(); 00227 } 00228 00229 request[0] = reqcode; 00230 request[1] = node; 00231 request[2] = param; 00232 00233 COMM_TRACE(fprintf(stderr, "%d: issuing %s %d %d\n", 00234 this_node, names[reqcode], node, param)); 00235 #ifdef ASYNC_BARRIER 00236 MPI_Barrier(comm_cart); 00237 #endif 00238 MPI_Bcast(request, 3, MPI_INT, 0, comm_cart); 00239 COMM_TRACE(fprintf(stderr, "%d: finished sending.\n", this_node)); 00240 } 00241 00242 /**************** REQ_TERM ************/ 00243 00244 static int terminated = 0; 00245 00246 void mpi_stop() 00247 { 00248 if (terminated) 00249 return; 00250 00251 mpi_call(mpi_stop_slave, -1, 0); 00252 00253 MPI_Barrier(comm_cart); 00254 MPI_Finalize(); 00255 regular_exit = 1; 00256 terminated = 1; 00257 } 00258 00259 void mpi_stop_slave(int node, int param) 00260 { 00261 COMM_TRACE(fprintf(stderr, "%d: exiting\n", this_node)); 00262 00263 MPI_Barrier(comm_cart); 00264 MPI_Finalize(); 00265 regular_exit = 1; 00266 exit(0); 00267 } 00268 00269 /*************** REQ_BCAST_PAR ************/ 00270 static void common_bcast_parameter(int i) 00271 { 00272 switch (fields[i].type) { 00273 case TYPE_INT: 00274 MPI_Bcast((int *)fields[i].data, fields[i].dimension, 00275 MPI_INT, 0, comm_cart); 00276 break; 00277 case TYPE_BOOL: 00278 MPI_Bcast((int *)fields[i].data, 1, 00279 MPI_INT, 0, comm_cart); 00280 break; 00281 case TYPE_DOUBLE: 00282 MPI_Bcast((double *)fields[i].data, fields[i].dimension, 00283 MPI_DOUBLE, 0, comm_cart); 00284 break; 00285 default: break; 00286 } 00287 00288 on_parameter_change(i); 00289 } 00290 00291 int mpi_bcast_parameter(int i) 00292 { 00293 mpi_call(mpi_bcast_parameter_slave, -1, i); 00294 00295 common_bcast_parameter(i); 00296 00297 return check_runtime_errors(); 00298 } 00299 00300 void mpi_bcast_parameter_slave(int node, int i) 00301 { 00302 common_bcast_parameter(i); 00303 check_runtime_errors(); 00304 } 00305 00306 /*************** REQ_WHO_HAS ****************/ 00307 00308 void mpi_who_has() 00309 { 00310 Cell *cell; 00311 int *sizes = malloc(sizeof(int)*n_nodes); 00312 int *pdata = NULL; 00313 int pdata_s = 0, i, c; 00314 int pnode; 00315 int n_part; 00316 00317 mpi_call(mpi_who_has_slave, -1, 0); 00318 00319 n_part = cells_get_n_particles(); 00320 /* first collect number of particles on each node */ 00321 MPI_Gather(&n_part, 1, MPI_INT, sizes, 1, MPI_INT, 0, comm_cart); 00322 00323 for (i = 0; i <= max_seen_particle; i++) 00324 particle_node[i] = -1; 00325 00326 /* then fetch particle locations */ 00327 for (pnode = 0; pnode < n_nodes; pnode++) { 00328 COMM_TRACE(fprintf(stderr, "node %d reports %d particles\n", 00329 pnode, sizes[pnode])); 00330 if (pnode == this_node) { 00331 for (c = 0; c < local_cells.n; c++) { 00332 cell = local_cells.cell[c]; 00333 for (i = 0; i < cell->n; i++) 00334 particle_node[cell->part[i].p.identity] = this_node; 00335 } 00336 } 00337 else if (sizes[pnode] > 0) { 00338 if (pdata_s < sizes[pnode]) { 00339 pdata_s = sizes[pnode]; 00340 pdata = (int *)realloc(pdata, sizeof(int)*pdata_s); 00341 } 00342 MPI_Recv(pdata, sizes[pnode], MPI_INT, pnode, SOME_TAG, 00343 comm_cart, MPI_STATUS_IGNORE); 00344 for (i = 0; i < sizes[pnode]; i++) 00345 particle_node[pdata[i]] = pnode; 00346 } 00347 } 00348 00349 free(pdata); 00350 free(sizes); 00351 } 00352 00353 void mpi_who_has_slave(int node, int param) 00354 { 00355 Cell *cell; 00356 int npart, i, c; 00357 int *sendbuf; 00358 int n_part; 00359 00360 n_part = cells_get_n_particles(); 00361 MPI_Gather(&n_part, 1, MPI_INT, NULL, 0, MPI_INT, 0, comm_cart); 00362 if (n_part == 0) 00363 return; 00364 00365 sendbuf = malloc(sizeof(int)*n_part); 00366 npart = 0; 00367 for (c = 0; c < local_cells.n; c++) { 00368 cell = local_cells.cell[c]; 00369 for (i = 0; i < cell->n; i++) 00370 sendbuf[npart++] = cell->part[i].p.identity; 00371 } 00372 MPI_Send(sendbuf, npart, MPI_INT, 0, SOME_TAG, comm_cart); 00373 free(sendbuf); 00374 } 00375 00376 /**************** REQ_CHTOPL ***********/ 00377 void mpi_bcast_event(int event) 00378 { 00379 mpi_call(mpi_bcast_event_slave, -1, event); 00380 mpi_bcast_event_slave(-1, event); 00381 } 00382 00383 void mpi_bcast_event_slave(int node, int event) 00384 { 00385 switch (event) { 00386 #ifdef ELECTROSTATICS 00387 #ifdef P3M 00388 case P3M_COUNT_CHARGES: 00389 p3m_count_charged_particles(); 00390 break; 00391 #endif 00392 case MAGGS_COUNT_CHARGES: 00393 maggs_count_charged_particles(); 00394 break; 00395 #endif 00396 case INVALIDATE_SYSTEM: 00397 local_invalidate_system(); 00398 break; 00399 #ifdef ADDITIONAL_CHECKS 00400 case CHECK_PARTICLES: 00401 check_particles(); 00402 break; 00403 #endif 00404 00405 #ifdef DP3M 00406 case P3M_COUNT_DIPOLES: 00407 dp3m_count_magnetic_particles(); 00408 break; 00409 #endif 00410 00411 default:; 00412 } 00413 } 00414 00415 /****************** REQ_PLACE/REQ_PLACE_NEW ************/ 00416 00417 void mpi_place_particle(int pnode, int part, double p[3]) 00418 { 00419 mpi_call(mpi_place_particle_slave, pnode, part); 00420 00421 if (pnode == this_node) 00422 local_place_particle(part, p, 0); 00423 else 00424 MPI_Send(p, 3, MPI_DOUBLE, pnode, SOME_TAG, comm_cart); 00425 00426 on_particle_change(); 00427 } 00428 00429 void mpi_place_particle_slave(int pnode, int part) 00430 { 00431 double p[3]; 00432 00433 if (pnode == this_node) { 00434 MPI_Recv(p, 3, MPI_DOUBLE, 0, SOME_TAG, comm_cart, MPI_STATUS_IGNORE); 00435 local_place_particle(part, p, 0); 00436 } 00437 00438 on_particle_change(); 00439 } 00440 00441 void mpi_place_new_particle(int pnode, int part, double p[3]) 00442 { 00443 mpi_call(mpi_place_new_particle_slave, pnode, part); 00444 added_particle(part); 00445 00446 if (pnode == this_node) 00447 local_place_particle(part, p, 1); 00448 else 00449 MPI_Send(p, 3, MPI_DOUBLE, pnode, SOME_TAG, comm_cart); 00450 00451 on_particle_change(); 00452 } 00453 00454 00455 void mpi_place_new_particle_slave(int pnode, int part) 00456 { 00457 double p[3]; 00458 00459 added_particle(part); 00460 00461 if (pnode == this_node) { 00462 MPI_Recv(p, 3, MPI_DOUBLE, 0, SOME_TAG, comm_cart, MPI_STATUS_IGNORE); 00463 local_place_particle(part, p, 1); 00464 } 00465 00466 on_particle_change(); 00467 } 00468 00469 /****************** REQ_SET_V ************/ 00470 void mpi_send_v(int pnode, int part, double v[3]) 00471 { 00472 mpi_call(mpi_send_v_slave, pnode, part); 00473 00474 if (pnode == this_node) { 00475 Particle *p = local_particles[part]; 00476 memcpy(p->m.v, v, 3*sizeof(double)); 00477 } 00478 else 00479 MPI_Send(v, 3, MPI_DOUBLE, pnode, SOME_TAG, comm_cart); 00480 00481 on_particle_change(); 00482 } 00483 00484 void mpi_send_v_slave(int pnode, int part) 00485 { 00486 if (pnode == this_node) { 00487 Particle *p = local_particles[part]; 00488 MPI_Recv(p->m.v, 3, MPI_DOUBLE, 0, SOME_TAG, 00489 comm_cart, MPI_STATUS_IGNORE); 00490 } 00491 00492 on_particle_change(); 00493 } 00494 00495 /****************** REQ_SET_F ************/ 00496 void mpi_send_f(int pnode, int part, double F[3]) 00497 { 00498 mpi_call(mpi_send_f_slave, pnode, part); 00499 00500 if (pnode == this_node) { 00501 Particle *p = local_particles[part]; 00502 memcpy(p->f.f, F, 3*sizeof(double)); 00503 } 00504 else 00505 MPI_Send(F, 3, MPI_DOUBLE, pnode, SOME_TAG, comm_cart); 00506 00507 on_particle_change(); 00508 } 00509 00510 void mpi_send_f_slave(int pnode, int part) 00511 { 00512 if (pnode == this_node) { 00513 Particle *p = local_particles[part]; 00514 MPI_Recv(p->f.f, 3, MPI_DOUBLE, 0, SOME_TAG, 00515 comm_cart, MPI_STATUS_IGNORE); 00516 } 00517 00518 on_particle_change(); 00519 } 00520 00521 /********************* REQ_SET_Q ********/ 00522 void mpi_send_q(int pnode, int part, double q) 00523 { 00524 #ifdef ELECTROSTATICS 00525 mpi_call(mpi_send_q_slave, pnode, part); 00526 00527 if (pnode == this_node) { 00528 Particle *p = local_particles[part]; 00529 p->p.q = q; 00530 } 00531 else { 00532 MPI_Send(&q, 1, MPI_DOUBLE, pnode, SOME_TAG, comm_cart); 00533 } 00534 00535 on_particle_change(); 00536 #endif 00537 } 00538 00539 void mpi_send_q_slave(int pnode, int part) 00540 { 00541 #ifdef ELECTROSTATICS 00542 if (pnode == this_node) { 00543 Particle *p = local_particles[part]; 00544 MPI_Recv(&p->p.q, 1, MPI_DOUBLE, 0, SOME_TAG, 00545 comm_cart, MPI_STATUS_IGNORE); 00546 } 00547 00548 on_particle_change(); 00549 #endif 00550 } 00551 00552 /********************* REQ_SET_MU_E ********/ 00553 void mpi_send_mu_E(int pnode, int part, double mu_E[3]) 00554 { 00555 #ifdef LB_ELECTROHYDRODYNAMICS 00556 mpi_call(mpi_send_mu_E_slave, pnode, part); 00557 00558 if (pnode == this_node) { 00559 Particle *p = local_particles[part]; 00560 p->p.mu_E[0] = mu_E[0]; 00561 p->p.mu_E[1] = mu_E[1]; 00562 p->p.mu_E[2] = mu_E[2]; 00563 } 00564 else { 00565 MPI_Send(&mu_E, 3, MPI_DOUBLE, pnode, SOME_TAG, comm_cart); 00566 } 00567 00568 on_particle_change(); 00569 #endif 00570 } 00571 00572 void mpi_send_mu_E_slave(int pnode, int part) 00573 { 00574 #ifdef LB_ELECTROHYDRODYNAMICS 00575 if (pnode == this_node) { 00576 Particle *p = local_particles[part]; 00577 MPI_Recv(&p->p.mu_E, 3, MPI_DOUBLE, 0, SOME_TAG, 00578 comm_cart, MPI_STATUS_IGNORE); 00579 } 00580 00581 on_particle_change(); 00582 #endif 00583 } 00584 00585 /********************* REQ_SET_SOLV ********/ 00586 void mpi_send_solvation(int pnode, int part, double* solvation) 00587 { 00588 #ifdef SHANCHEN 00589 int ii; 00590 mpi_call(mpi_send_solvation_slave, pnode, part); 00591 00592 if (pnode == this_node) { 00593 Particle *p = local_particles[part]; 00594 for(ii=0;ii<2*LB_COMPONENTS;ii++) 00595 p->p.solvation[ii]= solvation[ii]; 00596 } 00597 else { 00598 MPI_Send(&solvation, LB_COMPONENTS, MPI_DOUBLE, pnode, SOME_TAG, comm_cart); 00599 } 00600 00601 on_particle_change(); 00602 #endif 00603 } 00604 00605 void mpi_send_solvation_slave(int pnode, int part) 00606 { 00607 #ifdef SHANCHEN 00608 if (pnode == this_node) { 00609 Particle *p = local_particles[part]; 00610 MPI_Recv(&p->p.solvation, 2*LB_COMPONENTS, MPI_DOUBLE, 0, SOME_TAG, 00611 comm_cart, MPI_STATUS_IGNORE); 00612 } 00613 00614 on_particle_change(); 00615 #endif 00616 } 00617 00618 /********************* REQ_SET_M ********/ 00619 void mpi_send_mass(int pnode, int part, double mass) 00620 { 00621 #ifdef MASS 00622 mpi_call(mpi_send_mass_slave, pnode, part); 00623 00624 if (pnode == this_node) { 00625 Particle *p = local_particles[part]; 00626 p->p.mass = mass; 00627 } 00628 else { 00629 MPI_Send(&mass, 1, MPI_DOUBLE, pnode, SOME_TAG, comm_cart); 00630 } 00631 00632 on_particle_change(); 00633 #endif 00634 } 00635 00636 void mpi_send_mass_slave(int pnode, int part) 00637 { 00638 #ifdef MASS 00639 if (pnode == this_node) { 00640 Particle *p = local_particles[part]; 00641 MPI_Recv(&p->p.mass, 1, MPI_DOUBLE, 0, SOME_TAG, 00642 comm_cart, MPI_STATUS_IGNORE); 00643 } 00644 00645 on_particle_change(); 00646 #endif 00647 } 00648 00649 /********************* REQ_SET_RINERTIA ********/ 00650 00651 void mpi_send_rotational_inertia(int pnode, int part, double rinertia[3]) 00652 { 00653 #ifdef ROTATIONAL_INERTIA 00654 mpi_call(mpi_send_rotational_inertia_slave, pnode, part); 00655 00656 if (pnode == this_node) { 00657 Particle *p = local_particles[part]; 00658 p->p.rinertia[0] = rinertia[0]; 00659 p->p.rinertia[1] = rinertia[1]; 00660 p->p.rinertia[2] = rinertia[2]; 00661 } 00662 else { 00663 MPI_Send(rinertia, 3, MPI_DOUBLE, pnode, SOME_TAG, comm_cart); 00664 } 00665 00666 on_particle_change(); 00667 #endif 00668 } 00669 00670 void mpi_send_rotational_inertia_slave(int pnode, int part) 00671 { 00672 #ifdef ROTATIONAL_INERTIA 00673 if (pnode == this_node) { 00674 Particle *p = local_particles[part]; 00675 MPI_Recv(p->p.rinertia, 3, MPI_DOUBLE, 0, SOME_TAG, 00676 comm_cart, MPI_STATUS_IGNORE); 00677 } 00678 00679 on_particle_change(); 00680 #endif 00681 } 00682 00683 /********************* REQ_SET_TYPE ********/ 00684 void mpi_send_type(int pnode, int part, int type) 00685 { 00686 mpi_call(mpi_send_type_slave, pnode, part); 00687 00688 if (pnode == this_node) { 00689 Particle *p = local_particles[part]; 00690 p->p.type = type; 00691 } 00692 else 00693 MPI_Send(&type, 1, MPI_INT, pnode, SOME_TAG, comm_cart); 00694 00695 on_particle_change(); 00696 } 00697 00698 void mpi_send_type_slave(int pnode, int part) 00699 { 00700 if (pnode == this_node) { 00701 Particle *p = local_particles[part]; 00702 MPI_Recv(&p->p.type, 1, MPI_INT, 0, SOME_TAG, 00703 comm_cart, MPI_STATUS_IGNORE); 00704 } 00705 00706 on_particle_change(); 00707 } 00708 00709 /********************* REQ_SET_MOLID ********/ 00710 void mpi_send_mol_id(int pnode, int part, int mid) 00711 { 00712 mpi_call(mpi_send_mol_id_slave, pnode, part); 00713 00714 if (pnode == this_node) { 00715 Particle *p = local_particles[part]; 00716 p->p.mol_id = mid; 00717 } 00718 else 00719 MPI_Send(&mid, 1, MPI_INT, pnode, SOME_TAG, comm_cart); 00720 00721 on_particle_change(); 00722 } 00723 00724 void mpi_send_mol_id_slave(int pnode, int part) 00725 { 00726 if (pnode == this_node) { 00727 Particle *p = local_particles[part]; 00728 MPI_Recv(&p->p.mol_id, 1, MPI_INT, 0, SOME_TAG, 00729 comm_cart, MPI_STATUS_IGNORE); 00730 } 00731 00732 on_particle_change(); 00733 } 00734 00735 /********************* REQ_SET_QUAT ********/ 00736 00737 void mpi_send_quat(int pnode, int part, double quat[4]) 00738 { 00739 #ifdef ROTATION 00740 mpi_call(mpi_send_quat_slave, pnode, part); 00741 00742 if (pnode == this_node) { 00743 Particle *p = local_particles[part]; 00744 p->r.quat[0] = quat[0]; 00745 p->r.quat[1] = quat[1]; 00746 p->r.quat[2] = quat[2]; 00747 p->r.quat[3] = quat[3]; 00748 convert_quat_to_quatu(p->r.quat, p->r.quatu); 00749 #ifdef DIPOLES 00750 convert_quatu_to_dip(p->r.quatu, p->p.dipm, p->r.dip); 00751 #endif 00752 } 00753 else { 00754 MPI_Send(quat, 4, MPI_DOUBLE, pnode, SOME_TAG, comm_cart); 00755 } 00756 00757 on_particle_change(); 00758 #endif 00759 } 00760 00761 void mpi_send_quat_slave(int pnode, int part) 00762 { 00763 #ifdef ROTATION 00764 if (pnode == this_node) { 00765 Particle *p = local_particles[part]; 00766 MPI_Recv(p->r.quat, 4, MPI_DOUBLE, 0, SOME_TAG, 00767 comm_cart, MPI_STATUS_IGNORE); 00768 convert_quat_to_quatu(p->r.quat, p->r.quatu); 00769 #ifdef DIPOLES 00770 convert_quatu_to_dip(p->r.quatu, p->p.dipm, p->r.dip); 00771 #endif 00772 } 00773 00774 on_particle_change(); 00775 #endif 00776 } 00777 00778 /********************* REQ_SET_OMEGA ********/ 00779 00780 void mpi_send_omega(int pnode, int part, double omega[3]) 00781 { 00782 #ifdef ROTATION 00783 mpi_call(mpi_send_omega_slave, pnode, part); 00784 00785 if (pnode == this_node) { 00786 Particle *p = local_particles[part]; 00787 /* memcpy(p->omega, omega, 3*sizeof(double));*/ 00788 p->m.omega[0] = omega[0]; 00789 p->m.omega[1] = omega[1]; 00790 p->m.omega[2] = omega[2]; 00791 } 00792 else { 00793 MPI_Send(omega, 3, MPI_DOUBLE, pnode, SOME_TAG, comm_cart); 00794 } 00795 00796 on_particle_change(); 00797 #endif 00798 } 00799 00800 void mpi_send_omega_slave(int pnode, int part) 00801 { 00802 #ifdef ROTATION 00803 if (pnode == this_node) { 00804 Particle *p = local_particles[part]; 00805 MPI_Recv(p->m.omega, 3, MPI_DOUBLE, 0, SOME_TAG, 00806 comm_cart, MPI_STATUS_IGNORE); 00807 } 00808 00809 on_particle_change(); 00810 #endif 00811 } 00812 00813 /********************* REQ_SET_TORQUE ********/ 00814 00815 void mpi_send_torque(int pnode, int part, double torque[3]) 00816 { 00817 #ifdef ROTATION 00818 mpi_call(mpi_send_torque_slave, pnode, part); 00819 00820 if (pnode == this_node) { 00821 Particle *p = local_particles[part]; 00822 p->f.torque[0] = torque[0]; 00823 p->f.torque[1] = torque[1]; 00824 p->f.torque[2] = torque[2]; 00825 } 00826 else { 00827 MPI_Send(torque, 3, MPI_DOUBLE, pnode, SOME_TAG, comm_cart); 00828 } 00829 00830 on_particle_change(); 00831 #endif 00832 } 00833 00834 void mpi_send_torque_slave(int pnode, int part) 00835 { 00836 #ifdef ROTATION 00837 if (pnode == this_node) { 00838 Particle *p = local_particles[part]; 00839 MPI_Recv(p->f.torque, 3, MPI_DOUBLE, 0, SOME_TAG, 00840 comm_cart, MPI_STATUS_IGNORE); 00841 } 00842 00843 on_particle_change(); 00844 #endif 00845 } 00846 00847 /********************* REQ_SET_DIP ********/ 00848 00849 void mpi_send_dip(int pnode, int part, double dip[3]) 00850 { 00851 #ifdef DIPOLES 00852 mpi_call(mpi_send_dip_slave, pnode, part); 00853 00854 if (pnode == this_node) { 00855 Particle *p = local_particles[part]; 00856 p->r.dip[0] = dip[0]; 00857 p->r.dip[1] = dip[1]; 00858 p->r.dip[2] = dip[2]; 00859 #ifdef ROTATION 00860 convert_dip_to_quat(p->r.dip, p->r.quat, &p->p.dipm); 00861 convert_quat_to_quatu(p->r.quat, p->r.quatu); 00862 #else 00863 p->p.dipm = sqrt(p->r.dip[0]*p->r.dip[0] + p->r.dip[1]*p->r.dip[1] + p->r.dip[2]*p->r.dip[2]); 00864 #endif 00865 } 00866 else { 00867 MPI_Send(dip, 3, MPI_DOUBLE, pnode, SOME_TAG, comm_cart); 00868 } 00869 00870 on_particle_change(); 00871 #endif 00872 } 00873 00874 void mpi_send_dip_slave(int pnode, int part) 00875 { 00876 #ifdef DIPOLES 00877 if (pnode == this_node) { 00878 Particle *p = local_particles[part]; 00879 MPI_Recv(p->r.dip, 3, MPI_DOUBLE, 0, SOME_TAG, 00880 comm_cart, MPI_STATUS_IGNORE); 00881 #ifdef ROTATION 00882 convert_dip_to_quat(p->r.dip, p->r.quat, &p->p.dipm); 00883 convert_quat_to_quatu(p->r.quat, p->r.quatu); 00884 #else 00885 p->p.dipm = sqrt(p->r.dip[0]*p->r.dip[0] + p->r.dip[1]*p->r.dip[1] + p->r.dip[2]*p->r.dip[2]); 00886 #endif 00887 } 00888 00889 on_particle_change(); 00890 #endif 00891 } 00892 00893 /********************* REQ_SET_DIPM ********/ 00894 00895 void mpi_send_dipm(int pnode, int part, double dipm) 00896 { 00897 #ifdef DIPOLES 00898 mpi_call(mpi_send_dipm_slave, pnode, part); 00899 00900 if (pnode == this_node) { 00901 Particle *p = local_particles[part]; 00902 p->p.dipm = dipm; 00903 #ifdef ROTATION 00904 convert_quatu_to_dip(p->r.quatu, p->p.dipm, p->r.dip); 00905 #endif 00906 } 00907 else { 00908 MPI_Send(&dipm, 1, MPI_DOUBLE, pnode, SOME_TAG, comm_cart); 00909 } 00910 00911 on_particle_change(); 00912 #endif 00913 } 00914 00915 void mpi_send_dipm_slave(int pnode, int part) 00916 { 00917 #ifdef DIPOLES 00918 if (pnode == this_node) { 00919 Particle *p = local_particles[part]; 00920 MPI_Recv(&p->p.dipm, 1, MPI_DOUBLE, 0, SOME_TAG, 00921 comm_cart, MPI_STATUS_IGNORE); 00922 #ifdef ROTATION 00923 convert_quatu_to_dip(p->r.quatu, p->p.dipm, p->r.dip); 00924 #endif 00925 } 00926 00927 on_particle_change(); 00928 #endif 00929 } 00930 00931 /********************* REQ_SET_ISVI ********/ 00932 00933 void mpi_send_virtual(int pnode, int part, int isVirtual) 00934 { 00935 #ifdef VIRTUAL_SITES 00936 mpi_call(mpi_send_virtual_slave, pnode, part); 00937 00938 if (pnode == this_node) { 00939 Particle *p = local_particles[part]; 00940 p->p.isVirtual = isVirtual; 00941 } 00942 else { 00943 MPI_Send(&isVirtual, 1, MPI_INT, pnode, SOME_TAG, comm_cart); 00944 } 00945 00946 on_particle_change(); 00947 #endif 00948 } 00949 00950 void mpi_send_virtual_slave(int pnode, int part) 00951 { 00952 #ifdef VIRTUAL_SITES 00953 if (pnode == this_node) { 00954 Particle *p = local_particles[part]; 00955 MPI_Recv(&p->p.isVirtual, 1, MPI_INT, 0, SOME_TAG, 00956 comm_cart, MPI_STATUS_IGNORE); 00957 } 00958 00959 on_particle_change(); 00960 #endif 00961 } 00962 00963 /********************* REQ_SET_BOND ********/ 00964 00965 void mpi_send_vs_relative(int pnode, int part, int vs_relative_to, double vs_distance) 00966 { 00967 #ifdef VIRTUAL_SITES_RELATIVE 00968 mpi_call(mpi_send_vs_relative_slave, pnode, part); 00969 00970 // If the particle is on the node on which this function was called 00971 // set the values locally 00972 if (pnode == this_node) { 00973 Particle *p = local_particles[part]; 00974 p->p.vs_relative_to_particle_id = vs_relative_to; 00975 p->p.vs_relative_distance = vs_distance; 00976 } 00977 else { 00978 MPI_Send(&vs_relative_to, 1, MPI_INT, pnode, SOME_TAG, comm_cart); 00979 MPI_Send(&vs_distance, 1, MPI_DOUBLE, pnode, SOME_TAG, comm_cart); 00980 } 00981 00982 on_particle_change(); 00983 #endif 00984 } 00985 00986 void mpi_send_vs_relative_slave(int pnode, int part) 00987 { 00988 #ifdef VIRTUAL_SITES_RELATIVE 00989 if (pnode == this_node) { 00990 Particle *p = local_particles[part]; 00991 MPI_Recv(&p->p.vs_relative_to_particle_id, 1, MPI_INT, 0, SOME_TAG, 00992 comm_cart, MPI_STATUS_IGNORE); 00993 MPI_Recv(&p->p.vs_relative_distance, 1, MPI_DOUBLE, 0, SOME_TAG, 00994 comm_cart, MPI_STATUS_IGNORE); 00995 } 00996 00997 on_particle_change(); 00998 #endif 00999 } 01000 01001 // ******************************** 01002 01003 void mpi_send_rotation(int pnode, int part, int rot) 01004 { 01005 #ifdef ROTATION_PER_PARTICLE 01006 mpi_call(mpi_send_rotation_slave, pnode, part); 01007 01008 if (pnode == this_node) { 01009 Particle *p = local_particles[part]; 01010 p->p.rotation = rot; 01011 } 01012 else { 01013 MPI_Send(&rot, 1, MPI_INT, pnode, SOME_TAG, MPI_COMM_WORLD); 01014 } 01015 01016 on_particle_change(); 01017 #endif 01018 } 01019 01020 void mpi_send_rotation_slave(int pnode, int part) 01021 { 01022 #ifdef ROTATION_PER_PARTICLE 01023 if (pnode == this_node) { 01024 Particle *p = local_particles[part]; 01025 MPI_Status status; 01026 MPI_Recv(&p->p.rotation, 1, MPI_INT, 0, SOME_TAG, 01027 MPI_COMM_WORLD, &status); 01028 } 01029 01030 on_particle_change(); 01031 #endif 01032 } 01033 01034 /********************* REQ_SET_BOND ********/ 01035 01036 01037 int mpi_send_bond(int pnode, int part, int *bond, int delete) 01038 { 01039 int bond_size, stat=0; 01040 01041 mpi_call(mpi_send_bond_slave, pnode, part); 01042 01043 bond_size = (bond) ? bonded_ia_params[bond[0]].num + 1 : 0; 01044 01045 if (pnode == this_node) { 01046 stat = local_change_bond(part, bond, delete); 01047 on_particle_change(); 01048 return stat; 01049 } 01050 /* else */ 01051 MPI_Send(&bond_size, 1, MPI_INT, pnode, SOME_TAG, comm_cart); 01052 if (bond_size) 01053 MPI_Send(bond, bond_size, MPI_INT, pnode, SOME_TAG, comm_cart); 01054 MPI_Send(&delete, 1, MPI_INT, pnode, SOME_TAG, comm_cart); 01055 MPI_Recv(&stat, 1, MPI_INT, pnode, SOME_TAG, comm_cart, MPI_STATUS_IGNORE); 01056 on_particle_change(); 01057 return stat; 01058 } 01059 01060 void mpi_send_bond_slave(int pnode, int part) 01061 { 01062 int bond_size=0, *bond, delete=0, stat; 01063 01064 if (pnode == this_node) { 01065 MPI_Recv(&bond_size, 1, MPI_INT, 0, SOME_TAG, comm_cart, MPI_STATUS_IGNORE); 01066 if (bond_size) { 01067 bond = (int *)malloc(bond_size*sizeof(int)); 01068 MPI_Recv(bond, bond_size, MPI_INT, 0, SOME_TAG, comm_cart, MPI_STATUS_IGNORE); 01069 } 01070 else 01071 bond = NULL; 01072 MPI_Recv(&delete, 1, MPI_INT, 0, SOME_TAG, comm_cart, MPI_STATUS_IGNORE); 01073 stat = local_change_bond(part, bond, delete); 01074 if (bond) 01075 free(bond); 01076 MPI_Send(&stat, 1, MPI_INT, 0, SOME_TAG, comm_cart); 01077 } 01078 01079 on_particle_change(); 01080 } 01081 01082 /****************** REQ_GET_PART ************/ 01083 void mpi_recv_part(int pnode, int part, Particle *pdata) 01084 { 01085 IntList *bl = &(pdata->bl); 01086 #ifdef EXCLUSIONS 01087 IntList *el = &(pdata->el); 01088 #endif 01089 01090 /* fetch fixed data */ 01091 if (pnode == this_node) 01092 memcpy(pdata, local_particles[part], sizeof(Particle)); 01093 else { 01094 mpi_call(mpi_recv_part_slave, pnode, part); 01095 MPI_Recv(pdata, sizeof(Particle), MPI_BYTE, pnode, 01096 SOME_TAG, comm_cart, MPI_STATUS_IGNORE); 01097 } 01098 01099 /* copy dynamic data */ 01100 /* bonds */ 01101 bl->max = bl->n; 01102 if (bl->n > 0) { 01103 alloc_intlist(bl, bl->n); 01104 if (pnode == this_node) 01105 memcpy(bl->e, local_particles[part]->bl.e, sizeof(int)*bl->n); 01106 else 01107 MPI_Recv(bl->e, bl->n, MPI_INT, pnode, 01108 SOME_TAG, comm_cart, MPI_STATUS_IGNORE); 01109 } 01110 else 01111 bl->e = NULL; 01112 01113 #ifdef EXCLUSIONS 01114 /* exclusions */ 01115 el->max = el->n; 01116 if (el->n > 0) { 01117 alloc_intlist(el, el->n); 01118 if (pnode == this_node) 01119 memcpy(el->e, local_particles[part]->el.e, sizeof(int)*el->n); 01120 else 01121 MPI_Recv(el->e, el->n, MPI_INT, pnode, 01122 SOME_TAG, comm_cart, MPI_STATUS_IGNORE); 01123 } 01124 else 01125 el->e = NULL; 01126 #endif 01127 } 01128 01129 void mpi_recv_part_slave(int pnode, int part) 01130 { 01131 Particle *p; 01132 if (pnode != this_node) 01133 return; 01134 01135 p = local_particles[part]; 01136 01137 MPI_Send(p, sizeof(Particle), MPI_BYTE, 0, SOME_TAG, 01138 comm_cart); 01139 if (p->bl.n > 0) 01140 MPI_Send(p->bl.e, p->bl.n, MPI_INT, 0, SOME_TAG, 01141 comm_cart); 01142 #ifdef EXCLUSIONS 01143 if (p->el.n > 0) 01144 MPI_Send(p->el.e, p->el.n, MPI_INT, 0, SOME_TAG, 01145 comm_cart); 01146 #endif 01147 } 01148 01149 /****************** REQ_REM_PART ************/ 01150 void mpi_remove_particle(int pnode, int part) 01151 { 01152 mpi_call(mpi_remove_particle_slave, pnode, part); 01153 mpi_remove_particle_slave(pnode, part); 01154 } 01155 01156 void mpi_remove_particle_slave(int pnode, int part) 01157 { 01158 if (part != -1) { 01159 n_total_particles--; 01160 01161 if (pnode == this_node) 01162 local_remove_particle(part); 01163 01164 remove_all_bonds_to(part); 01165 } 01166 else 01167 local_remove_all_particles(); 01168 01169 on_particle_change(); 01170 } 01171 01172 /********************* REQ_INTEGRATE ********/ 01173 int mpi_integrate(int n_steps) 01174 { 01175 mpi_call(mpi_integrate_slave, -1, n_steps); 01176 01177 integrate_vv(n_steps); 01178 01179 COMM_TRACE(fprintf(stderr, "%d: integration task %d done.\n", this_node, n_steps)); 01180 01181 return check_runtime_errors(); 01182 } 01183 01184 void mpi_integrate_slave(int pnode, int task) 01185 { 01186 integrate_vv(task); 01187 COMM_TRACE(fprintf(stderr, "%d: integration task %d done.\n", this_node, task)); 01188 01189 check_runtime_errors(); 01190 } 01191 01192 /*************** REQ_BCAST_IA ************/ 01193 void mpi_bcast_ia_params(int i, int j) 01194 { 01195 mpi_call(mpi_bcast_ia_params_slave, i, j); 01196 #ifdef TABULATED 01197 int tablesize = tabulated_forces.max; 01198 #endif 01199 #ifdef INTERFACE_CORRECTION 01200 int adress_tablesize = adress_tab_forces.max; 01201 #endif 01202 01203 if (j>=0) { 01204 /* non-bonded interaction parameters */ 01205 /* INCOMPATIBLE WHEN NODES USE DIFFERENT ARCHITECTURES */ 01206 MPI_Bcast(get_ia_param(i, j), sizeof(IA_parameters), MPI_BYTE, 01207 0, comm_cart); 01208 01209 copy_ia_params(get_ia_param(j, i), get_ia_param(i, j)); 01210 01211 #ifdef TABULATED 01212 /* If there are tabulated forces broadcast those as well */ 01213 if ( get_ia_param(i,j)->TAB_maxval > 0) { 01214 /* First let all nodes know the new size for force and energy tables */ 01215 MPI_Bcast(&tablesize, 1, MPI_INT, 0, comm_cart); 01216 01217 /* Communicate the data */ 01218 MPI_Bcast(tabulated_forces.e,tablesize, MPI_DOUBLE, 0 , comm_cart); 01219 MPI_Bcast(tabulated_energies.e,tablesize, MPI_DOUBLE, 0 , comm_cart); 01220 } 01221 #endif 01222 #ifdef INTERFACE_CORRECTION 01223 if(get_ia_param(i,j)->ADRESS_TAB_maxval > 0) { 01224 MPI_Bcast(&adress_tablesize, 1, MPI_INT, 0, comm_cart); 01225 01226 /* Communicate the data */ 01227 MPI_Bcast(adress_tab_forces.e, adress_tablesize, MPI_DOUBLE, 0, comm_cart); 01228 MPI_Bcast(adress_tab_energies.e, adress_tablesize, MPI_DOUBLE, 0, comm_cart); 01229 } 01230 /* NO IC FOR TABULATED BONDED INTERACTIONS YET!! */ 01231 #endif 01232 } 01233 else { 01234 /* bonded interaction parameters */ 01235 /* INCOMPATIBLE WHEN NODES USE DIFFERENT ARCHITECTURES */ 01236 MPI_Bcast(&(bonded_ia_params[i]),sizeof(Bonded_ia_parameters), MPI_BYTE, 01237 0, comm_cart); 01238 #ifdef TABULATED 01239 /* For tabulated potentials we have to send the tables extra */ 01240 if(bonded_ia_params[i].type == BONDED_IA_TABULATED) { 01241 int size = bonded_ia_params[i].p.tab.npoints; 01242 MPI_Bcast(bonded_ia_params[i].p.tab.f, size, MPI_DOUBLE, 0 , comm_cart); 01243 MPI_Bcast(bonded_ia_params[i].p.tab.e, size, MPI_DOUBLE, 0 , comm_cart); 01244 } 01245 #endif 01246 #ifdef OVERLAPPED 01247 /* For overlapped potentials we have to send the ovelapped-functions extra */ 01248 if(bonded_ia_params[i].type == BONDED_IA_OVERLAPPED) { 01249 int size = bonded_ia_params[i].p.overlap.noverlaps; 01250 MPI_Bcast(bonded_ia_params[i].p.overlap.para_a, size, MPI_DOUBLE, 0 , comm_cart); 01251 MPI_Bcast(bonded_ia_params[i].p.overlap.para_b, size, MPI_DOUBLE, 0 , comm_cart); 01252 MPI_Bcast(bonded_ia_params[i].p.overlap.para_c, size, MPI_DOUBLE, 0 , comm_cart); 01253 } 01254 #endif 01255 } 01256 01257 on_short_range_ia_change(); 01258 } 01259 01260 void mpi_bcast_ia_params_slave(int i, int j) 01261 { 01262 if(j >= 0) { /* non-bonded interaction parameters */ 01263 /* INCOMPATIBLE WHEN NODES USE DIFFERENT ARCHITECTURES */ 01264 MPI_Bcast(get_ia_param(i, j), sizeof(IA_parameters), MPI_BYTE, 01265 0, comm_cart); 01266 01267 copy_ia_params(get_ia_param(j, i), get_ia_param(i, j)); 01268 01269 #ifdef TABULATED 01270 { 01271 int tablesize=0; 01272 /* If there are tabulated forces broadcast those as well */ 01273 if ( get_ia_param(i,j)->TAB_maxval > 0) { 01274 /* Determine the new size for force and energy tables */ 01275 MPI_Bcast(&tablesize,1,MPI_INT,0,comm_cart); 01276 /* Allocate sizes accordingly */ 01277 realloc_doublelist(&tabulated_forces, tablesize); 01278 realloc_doublelist(&tabulated_energies, tablesize); 01279 /* Now communicate the data */ 01280 MPI_Bcast(tabulated_forces.e,tablesize, MPI_DOUBLE, 0 , comm_cart); 01281 MPI_Bcast(tabulated_energies.e,tablesize, MPI_DOUBLE, 0 , comm_cart); 01282 } 01283 } 01284 #endif 01285 #ifdef INTERFACE_CORRECTION 01286 { 01287 int adress_tabsize=0; 01288 if ( get_ia_param(i,j)->ADRESS_TAB_maxval > 0) { 01289 MPI_Bcast(&adress_tabsize,1,MPI_INT,0,comm_cart); 01290 realloc_doublelist(&adress_tab_forces, adress_tabsize); 01291 realloc_doublelist(&adress_tab_energies, adress_tabsize); 01292 MPI_Bcast(adress_tab_forces.e,adress_tabsize, MPI_DOUBLE, 0, comm_cart); 01293 MPI_Bcast(adress_tab_energies.e,adress_tabsize, MPI_DOUBLE, 0, comm_cart); 01294 } 01295 } 01296 #endif 01297 } 01298 else { /* bonded interaction parameters */ 01299 make_bond_type_exist(i); /* realloc bonded_ia_params on slave nodes! */ 01300 MPI_Bcast(&(bonded_ia_params[i]),sizeof(Bonded_ia_parameters), MPI_BYTE, 01301 0, comm_cart); 01302 #ifdef TABULATED 01303 /* For tabulated potentials we have to send the tables extra */ 01304 if(bonded_ia_params[i].type == BONDED_IA_TABULATED) { 01305 int size = bonded_ia_params[i].p.tab.npoints; 01306 /* alloc force and energy tables on slave nodes! */ 01307 bonded_ia_params[i].p.tab.f = (double*)malloc(size*sizeof(double)); 01308 bonded_ia_params[i].p.tab.e = (double*)malloc(size*sizeof(double)); 01309 MPI_Bcast(bonded_ia_params[i].p.tab.f, size, MPI_DOUBLE, 0 , comm_cart); 01310 MPI_Bcast(bonded_ia_params[i].p.tab.e, size, MPI_DOUBLE, 0 , comm_cart); 01311 } 01312 #endif 01313 #ifdef OVERLAPPED 01314 /* For overlapped potentials we have to send the ovelapped-functions extra */ 01315 if(bonded_ia_params[i].type == BONDED_IA_OVERLAPPED) { 01316 int size = bonded_ia_params[i].p.overlap.noverlaps; 01317 /* alloc overlapped parameter arrays on slave nodes! */ 01318 bonded_ia_params[i].p.overlap.para_a = (double*)malloc(size*sizeof(double)); 01319 bonded_ia_params[i].p.overlap.para_b = (double*)malloc(size*sizeof(double)); 01320 bonded_ia_params[i].p.overlap.para_c = (double*)malloc(size*sizeof(double)); 01321 MPI_Bcast(bonded_ia_params[i].p.overlap.para_a, size, MPI_DOUBLE, 0 , comm_cart); 01322 MPI_Bcast(bonded_ia_params[i].p.overlap.para_b, size, MPI_DOUBLE, 0 , comm_cart); 01323 MPI_Bcast(bonded_ia_params[i].p.overlap.para_c, size, MPI_DOUBLE, 0 , comm_cart); 01324 } 01325 #endif 01326 } 01327 01328 on_short_range_ia_change(); 01329 } 01330 01331 /*************** REQ_BCAST_IA_SIZE ************/ 01332 01333 /* #ifdef THERMODYNAMIC_FORCE */ 01334 void mpi_bcast_tf_params(int i) 01335 { 01336 #ifdef ADRESS 01337 int tablesize=0; 01338 01339 mpi_call(mpi_bcast_tf_params_slave, i, i); 01340 tablesize = thermodynamic_forces.max; 01341 01342 /* thermodynamic force parameters */ 01343 /* non-bonded interaction parameters */ 01344 /* INCOMPATIBLE WHEN NODES USE DIFFERENT ARCHITECTURES */ 01345 MPI_Bcast(get_tf_param(i), sizeof(TF_parameters), MPI_BYTE, 01346 0, comm_cart); 01347 01348 /* If there are tabulated forces broadcast those as well */ 01349 if ( get_tf_param(i)->TF_TAB_maxval > 0) { 01350 /* First let all nodes know the new size for force and energy tables */ 01351 MPI_Bcast(&tablesize, 1, MPI_INT, 0, comm_cart); 01352 MPI_Barrier(comm_cart); // Don't do anything until all nodes have this information 01353 01354 /* Communicate the data */ 01355 MPI_Bcast(thermodynamic_forces.e,tablesize, MPI_DOUBLE, 0 , comm_cart); 01356 MPI_Bcast(thermodynamic_f_energies.e,tablesize, MPI_DOUBLE, 0 , comm_cart); 01357 //MPI_Bcast(TF_prefactor, 1, MPI_DOUBLE, 0, comm_cart); 01358 } 01359 01360 //on_short_range_ia_change(); 01361 #endif 01362 } 01363 01364 void mpi_bcast_tf_params_slave(int i, int j) 01365 { 01366 #ifdef ADRESS 01367 int tablesize; 01368 /* INCOMPATIBLE WHEN NODES USE DIFFERENT ARCHITECTURES */ 01369 MPI_Bcast(get_tf_param(i), sizeof(TF_parameters), MPI_BYTE, 01370 0, comm_cart); 01371 tablesize=0; 01372 /* If there are tabulated forces broadcast those as well */ 01373 if ( get_tf_param(i)->TF_TAB_maxval > 0) { 01374 /* Determine the new size for force and energy tables */ 01375 MPI_Bcast(&tablesize,1,MPI_INT,0,comm_cart); 01376 MPI_Barrier(comm_cart); 01377 /* Allocate sizes accordingly */ 01378 realloc_doublelist(&thermodynamic_forces, tablesize); 01379 realloc_doublelist(&thermodynamic_f_energies, tablesize); 01380 /* Now communicate the data */ 01381 MPI_Bcast(thermodynamic_forces.e,tablesize, MPI_DOUBLE, 0 , comm_cart); 01382 MPI_Bcast(thermodynamic_f_energies.e,tablesize, MPI_DOUBLE, 0 , comm_cart); 01383 } 01384 #endif 01385 } 01386 01387 01388 void mpi_bcast_n_particle_types(int ns) 01389 { 01390 mpi_call(mpi_bcast_n_particle_types_slave, -1, ns); 01391 mpi_bcast_n_particle_types_slave(-1, ns); 01392 01393 } 01394 01395 void mpi_bcast_n_particle_types_slave(int pnode, int ns) 01396 { 01397 #ifdef ADRESS 01398 /* #ifdef THERMODYNAMIC_FORCE */ 01399 realloc_tf_params(ns); 01400 /* #endif */ 01401 #endif 01402 realloc_ia_params(ns); 01403 } 01404 01405 /*************** REQ_GATHER ************/ 01406 void mpi_gather_stats(int job, void *result, void *result_t, void *result_nb, void *result_t_nb) 01407 { 01408 switch (job) { 01409 case 1: 01410 mpi_call(mpi_gather_stats_slave, -1, 1); 01411 energy_calc(result); 01412 break; 01413 case 2: 01414 /* calculate and reduce (sum up) virials for 'analyze pressure' or 'analyze stress_tensor'*/ 01415 mpi_call(mpi_gather_stats_slave, -1, 2); 01416 pressure_calc(result,result_t,result_nb,result_t_nb,0); 01417 break; 01418 case 3: 01419 mpi_call(mpi_gather_stats_slave, -1, 3); 01420 pressure_calc(result,result_t,result_nb,result_t_nb,1); 01421 break; 01422 case 4: 01423 mpi_call(mpi_gather_stats_slave, -1, 4); 01424 predict_momentum_particles(result); 01425 break; 01426 #ifdef LB 01427 case 5: 01428 mpi_call(mpi_gather_stats_slave, -1, 5); 01429 lb_calc_fluid_mass(result); 01430 break; 01431 case 6: 01432 mpi_call(mpi_gather_stats_slave, -1, 6); 01433 lb_calc_fluid_momentum(result); 01434 break; 01435 case 7: 01436 mpi_call(mpi_gather_stats_slave, -1, 7); 01437 lb_calc_fluid_temp(result); 01438 break; 01439 #ifdef LB_BOUNDARIES 01440 case 8: 01441 mpi_call(mpi_gather_stats_slave, -1, 8); 01442 lb_collect_boundary_forces(result); 01443 break; 01444 #endif 01445 #endif 01446 default: 01447 fprintf(stderr, "%d: INTERNAL ERROR: illegal request %d for mpi_gather_stats_slave\n", this_node, job); 01448 errexit(); 01449 } 01450 } 01451 01452 void mpi_gather_stats_slave(int ana_num, int job) 01453 { 01454 switch (job) { 01455 case 1: 01456 /* calculate and reduce (sum up) energies */ 01457 energy_calc(NULL); 01458 break; 01459 case 2: 01460 /* calculate and reduce (sum up) virials for 'analyze pressure' or 'analyze stress_tensor'*/ 01461 pressure_calc(NULL,NULL,NULL,NULL,0); 01462 break; 01463 case 3: 01464 /* calculate and reduce (sum up) virials, revert velocities half a timestep for 'analyze p_inst' */ 01465 pressure_calc(NULL,NULL,NULL,NULL,1); 01466 break; 01467 case 4: 01468 predict_momentum_particles(NULL); 01469 break; 01470 #ifdef LB 01471 case 5: 01472 lb_calc_fluid_mass(NULL); 01473 break; 01474 case 6: 01475 lb_calc_fluid_momentum(NULL); 01476 break; 01477 case 7: 01478 lb_calc_fluid_temp(NULL); 01479 break; 01480 #ifdef LB_BOUNDARIES 01481 case 8: 01482 lb_collect_boundary_forces(NULL); 01483 break; 01484 #endif 01485 #endif 01486 default: 01487 fprintf(stderr, "%d: INTERNAL ERROR: illegal request %d for mpi_gather_stats_slave\n", this_node, job); 01488 errexit(); 01489 } 01490 } 01491 01492 /*************** REQ_GET_LOCAL_STRESS_TENSOR ************/ 01493 void mpi_local_stress_tensor(DoubleList *TensorInBin, int bins[3], int periodic[3], double range_start[3], double range[3]) { 01494 01495 int i,j; 01496 DoubleList *TensorInBin_; 01497 PTENSOR_TRACE(fprintf(stderr,"%d: mpi_local_stress_tensor: Broadcasting local_stress_tensor parameters\n",this_node)); 01498 01499 01500 mpi_call(mpi_local_stress_tensor_slave,-1,0); 01501 01502 TensorInBin_ = malloc(bins[0]*bins[1]*bins[2]*sizeof(DoubleList)); 01503 for ( i = 0 ; i < bins[0]*bins[1]*bins[2]; i++ ) { 01504 init_doublelist(&TensorInBin_[i]); 01505 alloc_doublelist(&TensorInBin_[i],9); 01506 for ( j = 0 ; j < 9 ; j++ ) { 01507 TensorInBin_[i].e[j] = TensorInBin[i].e[j]; 01508 TensorInBin[i].e[j] = 0; 01509 } 01510 } 01511 01512 MPI_Bcast(bins, 3, MPI_INT, 0, comm_cart); 01513 MPI_Bcast(periodic, 3, MPI_INT, 0, comm_cart); 01514 MPI_Bcast(range_start, 3, MPI_DOUBLE, 0, comm_cart); 01515 MPI_Bcast(range, 3, MPI_DOUBLE, 0, comm_cart); 01516 01517 PTENSOR_TRACE(fprintf(stderr,"%d: mpi_local_stress_tensor: Call local_stress_tensor_calc\n",this_node)); 01518 local_stress_tensor_calc(TensorInBin_, bins, periodic, range_start, range); 01519 01520 PTENSOR_TRACE(fprintf(stderr,"%d: mpi_local_stress_tensor: Reduce local stress tensors with MPI_Reduce\n",this_node)); 01521 for (i=0;i<bins[0]*bins[1]*bins[2];i++) { 01522 MPI_Reduce(TensorInBin_[i].e, TensorInBin[i].e, 9, MPI_DOUBLE, MPI_SUM, 0, comm_cart); 01523 } 01524 01525 } 01526 01527 void mpi_local_stress_tensor_slave(int ana_num, int job) { 01528 int bins[3] = {0,0,0}; 01529 int periodic[3]= {0,0,0}; 01530 double range_start[3]= {0,0,0}; 01531 double range[3]= {0,0,0}; 01532 DoubleList *TensorInBin; 01533 int i, j; 01534 01535 MPI_Bcast(bins, 3, MPI_INT, 0, comm_cart); 01536 MPI_Bcast(periodic, 3, MPI_INT, 0, comm_cart); 01537 MPI_Bcast(range_start, 3, MPI_DOUBLE, 0, comm_cart); 01538 MPI_Bcast(range, 3, MPI_DOUBLE, 0, comm_cart); 01539 01540 TensorInBin = malloc(bins[0]*bins[1]*bins[2]*sizeof(DoubleList)); 01541 for ( i = 0 ; i < bins[0]*bins[1]*bins[2]; i++ ) { 01542 init_doublelist(&TensorInBin[i]); 01543 alloc_doublelist(&TensorInBin[i],9); 01544 for ( j = 0 ; j < 9 ; j++ ) { 01545 TensorInBin[i].e[j] = 0.0; 01546 } 01547 } 01548 01549 local_stress_tensor_calc(TensorInBin, bins, periodic, range_start, range); 01550 01551 for (i=0;i<bins[0]*bins[1]*bins[2];i++) { 01552 MPI_Reduce(TensorInBin[i].e, NULL, 9, MPI_DOUBLE, MPI_SUM, 0, comm_cart); 01553 PTENSOR_TRACE(fprintf(stderr,"%d: mpi_local_stress_tensor: Tensor sent in bin %d is {",this_node,i)); 01554 for (j=0; j<9;j++) { 01555 PTENSOR_TRACE(fprintf(stderr,"%f ",TensorInBin[i].e[j])); 01556 } 01557 PTENSOR_TRACE(fprintf(stderr,"}\n")); 01558 } 01559 01560 for ( i = 0 ; i < bins[0]*bins[1]*bins[2] ; i++ ) { 01561 realloc_doublelist(&TensorInBin[i],0); 01562 } 01563 free(TensorInBin); 01564 } 01565 01566 /*************** REQ_GETPARTS ************/ 01567 void mpi_get_particles(Particle *result, IntList *bi) 01568 { 01569 IntList local_bi; 01570 int n_part; 01571 int tot_size, i, g, pnode; 01572 int *sizes; 01573 Cell *cell; 01574 int c; 01575 01576 mpi_call(mpi_get_particles_slave, -1, bi != NULL); 01577 01578 sizes = malloc(sizeof(int)*n_nodes); 01579 n_part = cells_get_n_particles(); 01580 01581 /* first collect number of particles on each node */ 01582 MPI_Gather(&n_part, 1, MPI_INT, sizes, 1, MPI_INT, 0, comm_cart); 01583 tot_size = 0; 01584 for (i = 0; i < n_nodes; i++) 01585 tot_size += sizes[i]; 01586 01587 if (tot_size!=n_total_particles) { 01588 fprintf(stderr,"%d: ERROR: mpi_get_particles: n_total_particles %d, but I counted %d. Exiting...\n", 01589 this_node, n_total_particles, tot_size); 01590 errexit(); 01591 } 01592 01593 /* fetch particle informations into 'result' */ 01594 init_intlist(&local_bi); 01595 g = 0; 01596 for (pnode = 0; pnode < n_nodes; pnode++) { 01597 if (sizes[pnode] > 0) { 01598 if (pnode == this_node) { 01599 for (c = 0; c < local_cells.n; c++) { 01600 Particle *part; 01601 int npart; 01602 cell = local_cells.cell[c]; 01603 part = cell->part; 01604 npart = cell->n; 01605 memcpy(&result[g], part, npart*sizeof(Particle)); 01606 g += npart; 01607 if (bi) { 01608 int pc; 01609 for (pc = 0; pc < npart; pc++) { 01610 Particle *p = &part[pc]; 01611 realloc_intlist(&local_bi, local_bi.n + p->bl.n); 01612 memcpy(&local_bi.e[local_bi.n], p->bl.e, p->bl.n*sizeof(int)); 01613 local_bi.n += p->bl.n; 01614 } 01615 } 01616 } 01617 } 01618 else { 01619 MPI_Recv(&result[g], sizes[pnode]*sizeof(Particle), MPI_BYTE, pnode, SOME_TAG, 01620 comm_cart, MPI_STATUS_IGNORE); 01621 g += sizes[pnode]; 01622 } 01623 } 01624 } 01625 01626 /* perhaps add some debugging output */ 01627 #ifdef ELECTROSTATICS 01628 COMM_TRACE(for(i = 0; i < tot_size; i++) { 01629 printf("%d: %d -> %d %d %f (%f, %f, %f)\n", this_node, i, result[i].p.identity, result[i].p.type, 01630 result[i].p.q, result[i].r.p[0], result[i].r.p[1], result[i].r.p[2]); 01631 }); 01632 #endif 01633 01634 #ifdef DIPOLES 01635 COMM_TRACE(for(i = 0; i < tot_size; i++) { 01636 printf("%d: %d -> %d %d (%f, %f, %f) (%f, %f, %f)\n", this_node, i, result[i].p.identity, result[i].p.type, 01637 result[i].r.p[0], result[i].r.p[1], result[i].r.p[2], result[i].r.dip[0], 01638 result[i].r.dip[1], result[i].r.dip[2]); 01639 }); 01640 #endif 01641 01642 /* gather bonding information */ 01643 if (bi) { 01644 int *bonds; 01645 01646 init_intlist(bi); 01647 MPI_Gather(&local_bi.n, 1, MPI_INT, sizes, 1, MPI_INT, 0, comm_cart); 01648 for (pnode = 0; pnode < n_nodes; pnode++) { 01649 if (sizes[pnode] > 0) { 01650 realloc_intlist(bi, bi->n + sizes[pnode]); 01651 01652 if (pnode == this_node) 01653 memcpy(&bi->e[bi->n], local_bi.e, sizes[pnode]*sizeof(int)); 01654 else 01655 MPI_Recv(&bi->e[bi->n], sizes[pnode], MPI_INT, pnode, SOME_TAG, 01656 comm_cart, MPI_STATUS_IGNORE); 01657 01658 bi->n += sizes[pnode]; 01659 } 01660 } 01661 01662 /* setup particle bond pointers into bi */ 01663 bonds = bi->e; 01664 for (i = 0; i < tot_size; i++) { 01665 result[i].bl.e = bonds; 01666 bonds += result[i].bl.n; 01667 COMM_TRACE(if (result[i].bl.n > 0) { 01668 printf("(%d) part %d: bonds ", i, result[i].p.identity); 01669 for(g = 0; g < result[i].bl.n; g++) printf("%d ", result[i].bl.e[g]); 01670 printf("\n"); 01671 }); 01672 } 01673 realloc_intlist(&local_bi, 0); 01674 } 01675 01676 COMM_TRACE(fprintf(stderr, "%d: finished\n", this_node)); 01677 01678 free(sizes); 01679 } 01680 01681 void mpi_get_particles_slave(int pnode, int bi) 01682 { 01683 int n_part; 01684 int g; 01685 Particle *result; 01686 Cell *cell; 01687 int c; 01688 01689 n_part = cells_get_n_particles(); 01690 01691 COMM_TRACE(fprintf(stderr, "%d: get_particles_slave, %d particles\n", this_node, n_part)); 01692 01693 /* first collect number of particles on each node */ 01694 MPI_Gather(&n_part, 1, MPI_INT, NULL, 1, MPI_INT, 01695 0, comm_cart); 01696 01697 if (n_part > 0) { 01698 IntList local_bi; 01699 01700 /* get (unsorted) particle informations as an array of type 'particle' */ 01701 /* then get the particle information */ 01702 result = malloc(n_part*sizeof(Particle)); 01703 01704 init_intlist(&local_bi); 01705 01706 g = 0; 01707 for (c = 0; c < local_cells.n; c++) { 01708 Particle *part; 01709 int npart; 01710 cell = local_cells.cell[c]; 01711 part = cell->part; 01712 npart = cell->n; 01713 memcpy(&result[g],part,npart*sizeof(Particle)); 01714 g+=cell->n; 01715 if (bi) { 01716 int pc; 01717 for (pc = 0; pc < npart; pc++) { 01718 Particle *p = &part[pc]; 01719 realloc_intlist(&local_bi, local_bi.n + p->bl.n); 01720 memcpy(&local_bi.e[local_bi.n], p->bl.e, p->bl.n*sizeof(int)); 01721 local_bi.n += p->bl.n; 01722 } 01723 } 01724 } 01725 /* and send it back to the master node */ 01726 MPI_Send(result, n_part*sizeof(Particle), MPI_BYTE, 0, SOME_TAG, comm_cart); 01727 free(result); 01728 01729 if (bi) { 01730 COMM_TRACE(fprintf(stderr, "%d: sending bonds\n", this_node)); 01731 01732 MPI_Gather(&local_bi.n, 1, MPI_INT, NULL, 1, MPI_INT, 0, comm_cart); 01733 if (local_bi.n > 0) 01734 MPI_Send(local_bi.e, local_bi.n, MPI_INT, 0, SOME_TAG, comm_cart); 01735 realloc_intlist(&local_bi, 0); 01736 } 01737 } 01738 else { 01739 if (bi) { 01740 /* inform master node that we do not have bonds (as we don't have particles) */ 01741 g = 0; 01742 MPI_Gather(&g, 1, MPI_INT, NULL, 1, MPI_INT, 0, comm_cart); 01743 } 01744 } 01745 } 01746 01747 /*************** REQ_SET_TIME_STEP ************/ 01748 void mpi_set_time_step(double time_s) 01749 { 01750 double old_ts = time_step; 01751 01752 mpi_call(mpi_set_time_step_slave, -1, 0); 01753 01754 time_step = time_s; 01755 01756 time_step_squared=time_step * time_step; 01757 time_step_squared_half = time_step_squared /2.; 01758 time_step_half= time_step / 2.; 01759 01760 MPI_Bcast(&time_step, 1, MPI_DOUBLE, 0, comm_cart); 01761 01762 rescale_velocities(time_step / old_ts); 01763 on_parameter_change(FIELD_TIMESTEP); 01764 } 01765 01766 void mpi_set_time_step_slave(int node, int i) 01767 { 01768 double old_ts = time_step; 01769 01770 MPI_Bcast(&time_step, 1, MPI_DOUBLE, 0, comm_cart); 01771 rescale_velocities(time_step / old_ts); 01772 on_parameter_change(FIELD_TIMESTEP); 01773 time_step_squared=time_step * time_step; 01774 time_step_squared_half = time_step_squared /2.; 01775 time_step_half= time_step / 2.; 01776 } 01777 01778 /*************** REQ_BCAST_COULOMB ************/ 01779 void mpi_bcast_coulomb_params() 01780 { 01781 #if defined(ELECTROSTATICS) || defined(DIPOLES) 01782 mpi_call(mpi_bcast_coulomb_params_slave, 1, 0); 01783 mpi_bcast_coulomb_params_slave(-1, 0); 01784 #endif 01785 } 01786 01787 void mpi_bcast_coulomb_params_slave(int node, int parm) 01788 { 01789 #if defined(ELECTROSTATICS) || defined(DIPOLES) 01790 MPI_Bcast(&coulomb, sizeof(Coulomb_parameters), MPI_BYTE, 0, comm_cart); 01791 01792 #ifdef ELECTROSTATICS 01793 switch (coulomb.method) { 01794 case COULOMB_NONE: 01795 break; 01796 #ifdef P3M 01797 case COULOMB_ELC_P3M: 01798 MPI_Bcast(&elc_params, sizeof(ELC_struct), MPI_BYTE, 0, comm_cart); 01799 // fall through 01800 case COULOMB_P3M_GPU: 01801 case COULOMB_P3M: 01802 MPI_Bcast(&p3m.params, sizeof(p3m_parameter_struct), MPI_BYTE, 0, comm_cart); 01803 break; 01804 #endif 01805 case COULOMB_DH: 01806 case COULOMB_DH_PW: 01807 MPI_Bcast(&dh_params, sizeof(Debye_hueckel_params), MPI_BYTE, 0, comm_cart); 01808 break; 01809 case COULOMB_MMM1D: 01810 MPI_Bcast(&mmm1d_params, sizeof(MMM1D_struct), MPI_BYTE, 0, comm_cart); 01811 break; 01812 case COULOMB_MMM2D: 01813 MPI_Bcast(&mmm2d_params, sizeof(MMM2D_struct), MPI_BYTE, 0, comm_cart); 01814 break; 01815 case COULOMB_MAGGS: 01816 MPI_Bcast(&maggs, sizeof(MAGGS_struct), MPI_BYTE, 0, comm_cart); 01817 break; 01818 case COULOMB_RF: 01819 case COULOMB_INTER_RF: 01820 MPI_Bcast(&rf_params, sizeof(Reaction_field_params), MPI_BYTE, 0, comm_cart); 01821 break; 01822 default: 01823 fprintf(stderr, "%d: INTERNAL ERROR: cannot bcast coulomb params for unknown method %d\n", this_node, coulomb.method); 01824 errexit(); 01825 } 01826 #endif 01827 01828 #ifdef DIPOLES 01829 switch (coulomb.Dmethod) { 01830 case DIPOLAR_NONE: 01831 break; 01832 #ifdef DP3M 01833 case DIPOLAR_MDLC_P3M: 01834 MPI_Bcast(&dlc_params, sizeof(DLC_struct), MPI_BYTE, 0, comm_cart); 01835 // fall through 01836 case DIPOLAR_P3M: 01837 MPI_Bcast(&dp3m.params, sizeof(p3m_parameter_struct), MPI_BYTE, 0, comm_cart); 01838 break; 01839 #endif 01840 case DIPOLAR_ALL_WITH_ALL_AND_NO_REPLICA : 01841 break; 01842 case DIPOLAR_MDLC_DS: 01843 //fall trough 01844 case DIPOLAR_DS: 01845 break; 01846 default: 01847 fprintf(stderr, "%d: INTERNAL ERROR: cannot bcast dipolar params for unknown method %d\n", this_node, coulomb.Dmethod); 01848 errexit(); 01849 } 01850 01851 #endif 01852 01853 on_coulomb_change(); 01854 #endif 01855 } 01856 01857 /****************** REQ_SET_EXT ************/ 01858 01859 void mpi_send_ext_torque(int pnode, int part, int flag, int mask, double torque[3]) 01860 { 01861 #ifdef EXTERNAL_FORCES 01862 #ifdef ROTATION 01863 int s_buf[2]; 01864 mpi_call(mpi_send_ext_torque_slave, pnode, part); 01865 01866 if (pnode == this_node) { 01867 Particle *p = local_particles[part]; 01868 /* mask out old flags */ 01869 p->l.ext_flag &= ~mask; 01870 /* set new values */ 01871 p->l.ext_flag |= flag; 01872 01873 if (mask & PARTICLE_EXT_TORQUE) 01874 memcpy(p->l.ext_torque, torque, 3*sizeof(double)); 01875 } 01876 else { 01877 s_buf[0] = flag; s_buf[1] = mask; 01878 MPI_Send(s_buf, 2, MPI_INT, pnode, SOME_TAG, comm_cart); 01879 if (mask & PARTICLE_EXT_TORQUE) 01880 MPI_Send(torque, 3, MPI_DOUBLE, pnode, SOME_TAG, comm_cart); 01881 } 01882 01883 on_particle_change(); 01884 #endif 01885 #endif 01886 } 01887 01888 void mpi_send_ext_torque_slave(int pnode, int part) 01889 { 01890 #ifdef EXTERNAL_FORCES 01891 #ifdef ROTATION 01892 int s_buf[2]={0,0}; 01893 if (pnode == this_node) { 01894 Particle *p = local_particles[part]; 01895 MPI_Recv(s_buf, 2, MPI_INT, 0, SOME_TAG, comm_cart, MPI_STATUS_IGNORE); 01896 /* mask out old flags */ 01897 p->l.ext_flag &= ~s_buf[1]; 01898 /* set new values */ 01899 p->l.ext_flag |= s_buf[0]; 01900 01901 if (s_buf[1] & PARTICLE_EXT_TORQUE) 01902 MPI_Recv(p->l.ext_torque, 3, MPI_DOUBLE, 0, SOME_TAG, comm_cart, MPI_STATUS_IGNORE); 01903 } 01904 01905 on_particle_change(); 01906 #endif 01907 #endif 01908 } 01909 01910 void mpi_send_ext_force(int pnode, int part, int flag, int mask, double force[3]) 01911 { 01912 #ifdef EXTERNAL_FORCES 01913 int s_buf[2]; 01914 mpi_call(mpi_send_ext_force_slave, pnode, part); 01915 01916 if (pnode == this_node) { 01917 Particle *p = local_particles[part]; 01918 /* mask out old flags */ 01919 p->l.ext_flag &= ~mask; 01920 /* set new values */ 01921 p->l.ext_flag |= flag; 01922 if (mask & PARTICLE_EXT_FORCE) 01923 memcpy(p->l.ext_force, force, 3*sizeof(double)); 01924 } 01925 else { 01926 s_buf[0] = flag; s_buf[1] = mask; 01927 MPI_Send(s_buf, 2, MPI_INT, pnode, SOME_TAG, comm_cart); 01928 if (mask & PARTICLE_EXT_FORCE) 01929 MPI_Send(force, 3, MPI_DOUBLE, pnode, SOME_TAG, comm_cart); 01930 } 01931 01932 on_particle_change(); 01933 #endif 01934 } 01935 01936 void mpi_send_ext_force_slave(int pnode, int part) 01937 { 01938 #ifdef EXTERNAL_FORCES 01939 int s_buf[2]={0,0}; 01940 if (pnode == this_node) { 01941 Particle *p = local_particles[part]; 01942 MPI_Recv(s_buf, 2, MPI_INT, 0, SOME_TAG, comm_cart, MPI_STATUS_IGNORE); 01943 /* mask out old flags */ 01944 p->l.ext_flag &= ~s_buf[1]; 01945 /* set new values */ 01946 p->l.ext_flag |= s_buf[0]; 01947 01948 if (s_buf[1] & PARTICLE_EXT_FORCE) 01949 MPI_Recv(p->l.ext_force, 3, MPI_DOUBLE, 0, SOME_TAG, comm_cart, MPI_STATUS_IGNORE); 01950 } 01951 01952 on_particle_change(); 01953 #endif 01954 } 01955 01956 /*************** REQ_BCAST_CONSTR ************/ 01957 void mpi_bcast_constraint(int del_num) 01958 { 01959 #ifdef CONSTRAINTS 01960 mpi_call(mpi_bcast_constraint_slave, 0, del_num); 01961 01962 if (del_num == -1) { 01963 /* bcast new constraint */ 01964 MPI_Bcast(&constraints[n_constraints-1], sizeof(Constraint), MPI_BYTE, 0, comm_cart); 01965 } 01966 else if (del_num == -2) { 01967 /* delete all constraints */ 01968 n_constraints = 0; 01969 constraints = realloc(constraints,n_constraints*sizeof(Constraint)); 01970 } 01971 else { 01972 memcpy(&constraints[del_num],&constraints[n_constraints-1],sizeof(Constraint)); 01973 n_constraints--; 01974 constraints = realloc(constraints,n_constraints*sizeof(Constraint)); 01975 } 01976 01977 on_constraint_change(); 01978 #endif 01979 } 01980 01981 void mpi_bcast_constraint_slave(int node, int parm) 01982 { 01983 #ifdef CONSTRAINTS 01984 if(parm == -1) { 01985 n_constraints++; 01986 constraints = realloc(constraints,n_constraints*sizeof(Constraint)); 01987 MPI_Bcast(&constraints[n_constraints-1], sizeof(Constraint), MPI_BYTE, 0, comm_cart); 01988 } 01989 else if (parm == -2) { 01990 /* delete all constraints */ 01991 n_constraints = 0; 01992 constraints = realloc(constraints,n_constraints*sizeof(Constraint)); 01993 } 01994 else { 01995 memcpy(&constraints[parm],&constraints[n_constraints-1],sizeof(Constraint)); 01996 n_constraints--; 01997 constraints = realloc(constraints,n_constraints*sizeof(Constraint)); 01998 } 01999 02000 on_constraint_change(); 02001 #endif 02002 } 02003 02004 /*************** REQ_BCAST_LBBOUNDARY ************/ 02005 void mpi_bcast_lbboundary(int del_num) 02006 { 02007 #if defined(LB_BOUNDARIES) || defined(LB_BOUNDARIES_GPU) 02008 mpi_call(mpi_bcast_lbboundary_slave, 0, del_num); 02009 02010 if (del_num == -1) { 02011 /* bcast new boundaries */ 02012 MPI_Bcast(&lb_boundaries[n_lb_boundaries-1], sizeof(LB_Boundary), MPI_BYTE, 0, comm_cart); 02013 } 02014 else if (del_num == -2) { 02015 /* delete all boundaries */ 02016 n_lb_boundaries = 0; 02017 lb_boundaries = realloc(lb_boundaries,n_lb_boundaries*sizeof(LB_Boundary)); 02018 } 02019 #if defined(LB_BOUNDARIES_GPU) 02020 else if (del_num == -3) { 02021 //nothing, GPU code just requires to call on_lbboundary_change() 02022 } 02023 #endif 02024 else { 02025 memcpy(&lb_boundaries[del_num],&lb_boundaries[n_lb_boundaries-1],sizeof(LB_Boundary)); 02026 n_lb_boundaries--; 02027 lb_boundaries = realloc(lb_boundaries,n_lb_boundaries*sizeof(LB_Boundary)); 02028 } 02029 02030 on_lbboundary_change(); 02031 #endif 02032 } 02033 02034 void mpi_bcast_lbboundary_slave(int node, int parm) 02035 { 02036 #if defined(LB_BOUNDARIES) || defined(LB_BOUNDARIES_GPU) 02037 02038 #if defined(LB_BOUNDARIES) 02039 if(parm == -1) { 02040 n_lb_boundaries++; 02041 lb_boundaries = realloc(lb_boundaries,n_lb_boundaries*sizeof(LB_Boundary)); 02042 MPI_Bcast(&lb_boundaries[n_lb_boundaries-1], sizeof(LB_Boundary), MPI_BYTE, 0, comm_cart); 02043 } 02044 else if (parm == -2) { 02045 /* delete all boundaries */ 02046 n_lb_boundaries = 0; 02047 lb_boundaries = realloc(lb_boundaries,n_lb_boundaries*sizeof(LB_Boundary)); 02048 } 02049 #if defined(LB_BOUNDARIES_GPU) 02050 else if (parm == -3) { 02051 //nothing, GPU code just requires to call on_lbboundary_change() 02052 } 02053 #endif 02054 else { 02055 memcpy(&lb_boundaries[parm],&lb_boundaries[n_lb_boundaries-1],sizeof(LB_Boundary)); 02056 n_lb_boundaries--; 02057 lb_boundaries = realloc(lb_boundaries,n_lb_boundaries*sizeof(LB_Boundary)); 02058 } 02059 #endif 02060 02061 on_lbboundary_change(); 02062 #endif 02063 } 02064 02065 /*************** REQ_RANDOM_SEED ************/ 02066 void mpi_random_seed(int cnt, long *seed) { 02067 long this_idum = print_random_seed(); 02068 02069 mpi_call(mpi_random_seed_slave, -1, cnt); 02070 02071 if (cnt==0) { 02072 RANDOM_TRACE(printf("%d: Have seed %ld\n",this_node,this_idum)); 02073 MPI_Gather(&this_idum,1,MPI_LONG,seed,1,MPI_LONG,0,comm_cart); } 02074 else { 02075 MPI_Scatter(seed,1,MPI_LONG,&this_idum,1,MPI_LONG,0,comm_cart); 02076 RANDOM_TRACE(printf("%d: Received seed %ld\n",this_node,this_idum)); 02077 init_random_seed(this_idum); 02078 } 02079 } 02080 02081 void mpi_random_seed_slave(int pnode, int cnt) { 02082 long this_idum = print_random_seed(); 02083 02084 if (cnt==0) { 02085 RANDOM_TRACE(printf("%d: Have seed %ld\n",this_node,this_idum)); 02086 MPI_Gather(&this_idum,1,MPI_LONG,NULL,0,MPI_LONG,0,comm_cart); } 02087 else { 02088 MPI_Scatter(NULL,1,MPI_LONG,&this_idum,1,MPI_LONG,0,comm_cart); 02089 RANDOM_TRACE(printf("%d: Received seed %ld\n",this_node,this_idum)); 02090 init_random_seed(this_idum); 02091 } 02092 } 02093 02094 /*************** REQ_RANDOM_STAT ************/ 02095 void mpi_random_stat(int cnt, RandomStatus *stat) { 02096 RandomStatus this_stat = print_random_stat(); 02097 02098 mpi_call(mpi_random_stat_slave, -1, cnt); 02099 02100 if (cnt==0) { 02101 RANDOM_TRACE(printf("%d: Have status %ld/%ld/...\n",this_node,this_stat.idum,this_stat.iy)); 02102 MPI_Gather(&this_stat,1*sizeof(RandomStatus),MPI_BYTE,stat,1*sizeof(RandomStatus),MPI_BYTE,0,comm_cart); } 02103 else { 02104 MPI_Scatter(stat,1*sizeof(RandomStatus),MPI_BYTE,&this_stat,1*sizeof(RandomStatus),MPI_BYTE,0,comm_cart); 02105 RANDOM_TRACE(printf("%d: Received status %ld/%ld/...\n",this_node,this_stat.idum,this_stat.iy)); 02106 init_random_stat(this_stat); 02107 } 02108 } 02109 02110 void mpi_random_stat_slave(int pnode, int cnt) { 02111 RandomStatus this_stat = print_random_stat(); 02112 02113 if (cnt==0) { 02114 RANDOM_TRACE(printf("%d: Have status %ld/%ld/...\n",this_node,this_stat.idum,this_stat.iy)); 02115 MPI_Gather(&this_stat,1*sizeof(RandomStatus),MPI_BYTE,NULL,0,MPI_BYTE,0,comm_cart); } 02116 else { 02117 MPI_Scatter(NULL,0,MPI_BYTE,&this_stat,1*sizeof(RandomStatus),MPI_BYTE,0,comm_cart); 02118 RANDOM_TRACE(printf("%d: Received status %ld/%ld/...\n",this_node,this_stat.idum,this_stat.iy)); 02119 init_random_stat(this_stat); 02120 } 02121 } 02122 02123 /*************** REQ_BCAST_LJFORCECAP ************/ 02124 /*************** REQ_BCAST_LJANGLEFORCECAP ************/ 02125 /*************** REQ_BCAST_MORSEFORCECAP ************/ 02126 /*************** REQ_BCAST_BUCKFORCECAP ************/ 02127 /*************** REQ_BCAST_TABFORCECAP ************/ 02128 void mpi_cap_forces(double fc) 02129 { 02130 force_cap = fc; 02131 mpi_call(mpi_cap_forces_slave, 1, 0); 02132 mpi_cap_forces_slave(1, 0); 02133 } 02134 02135 void mpi_cap_forces_slave(int node, int parm) 02136 { 02137 #ifdef LENNARD_JONES 02138 MPI_Bcast(&force_cap, 1, MPI_DOUBLE, 0, comm_cart); 02139 calc_lj_cap_radii(); 02140 #ifdef LENNARD_JONES_GENERIC 02141 calc_ljgen_cap_radii(); 02142 #endif 02143 #ifdef LJCOS2 02144 calc_ljcos2_cap_radii(); 02145 #endif 02146 on_short_range_ia_change(); 02147 #endif 02148 #ifdef LJ_ANGLE 02149 MPI_Bcast(&force_cap, 1, MPI_DOUBLE, 0, comm_cart); 02150 calc_ljangle_cap_radii(); 02151 on_short_range_ia_change(); 02152 #endif 02153 #ifdef MORSE 02154 MPI_Bcast(&force_cap, 1, MPI_DOUBLE, 0, comm_cart); 02155 calc_morse_cap_radii(); 02156 on_short_range_ia_change(); 02157 #endif 02158 #ifdef BUCKINGHAM 02159 MPI_Bcast(&force_cap, 1, MPI_DOUBLE, 0, comm_cart); 02160 calc_buck_cap_radii(); 02161 on_short_range_ia_change(); 02162 #endif 02163 #ifdef TABULATED 02164 MPI_Bcast(&force_cap, 1, MPI_DOUBLE, 0, comm_cart); 02165 /* to do: check if "check_tab_forcecap" is still useful since force capping 02166 is defined globally now -- the cap for other forces would be removed too! 02167 check_tab_forcecap(force_cap); 02168 */ 02169 on_short_range_ia_change(); 02170 #endif 02171 } 02172 02173 /*************** REQ_GET_CONSFOR ************/ 02174 void mpi_get_constraint_force(int cons, double force[3]) 02175 { 02176 #ifdef CONSTRAINTS 02177 mpi_call(mpi_get_constraint_force_slave, -1, cons); 02178 MPI_Reduce(constraints[cons].part_rep.f.f, force, 3, MPI_DOUBLE, MPI_SUM, 0, comm_cart); 02179 #endif 02180 } 02181 02182 void mpi_get_constraint_force_slave(int node, int parm) 02183 { 02184 #ifdef CONSTRAINTS 02185 MPI_Reduce(constraints[parm].part_rep.f.f, NULL, 3, MPI_DOUBLE, MPI_SUM, 0, comm_cart); 02186 #endif 02187 } 02188 02189 /*************** REQ_BIT_RANDOM_SEED ************/ 02190 void mpi_bit_random_seed(int cnt, int *seed) { 02191 int this_idum = print_bit_random_seed(); 02192 02193 mpi_call(mpi_bit_random_seed_slave, -1, cnt); 02194 02195 if (cnt==0) { 02196 RANDOM_TRACE(printf("%d: Have seed %d\n",this_node,this_idum)); 02197 MPI_Gather(&this_idum,1,MPI_INT,seed,1,MPI_INT,0,comm_cart); } 02198 else { 02199 MPI_Scatter(seed,1,MPI_INT,&this_idum,1,MPI_INT,0,comm_cart); 02200 RANDOM_TRACE(printf("%d: Received seed %d\n",this_node,this_idum)); 02201 init_bit_random_generator(this_idum); 02202 } 02203 } 02204 02205 void mpi_bit_random_seed_slave(int pnode, int cnt) { 02206 int this_idum = print_bit_random_seed(); 02207 02208 if (cnt==0) { 02209 RANDOM_TRACE(printf("%d: Have seed %d\n",this_node,this_idum)); 02210 MPI_Gather(&this_idum,1,MPI_INT,NULL,0,MPI_INT,0,comm_cart); } 02211 else { 02212 MPI_Scatter(NULL,1,MPI_INT,&this_idum,1,MPI_INT,0,comm_cart); 02213 RANDOM_TRACE(printf("%d: Received seed %d\n",this_node,this_idum)); 02214 init_bit_random_generator(this_idum); 02215 } 02216 } 02217 02218 /*************** REQ_BIT_RANDOM_STAT ************/ 02219 void mpi_bit_random_stat(int cnt, BitRandomStatus *stat) { 02220 BitRandomStatus this_stat = print_bit_random_stat(); 02221 02222 mpi_call(mpi_bit_random_stat_slave, -1, cnt); 02223 02224 if (cnt==0) { 02225 RANDOM_TRACE(printf("%d: Have status %d/%d/...\n",this_node,this_stat.random_pointer_1,this_stat.random_pointer_2)); 02226 MPI_Gather(&this_stat,1*sizeof(BitRandomStatus),MPI_BYTE,stat,1*sizeof(BitRandomStatus),MPI_BYTE,0,comm_cart); } 02227 else { 02228 MPI_Scatter(stat,1*sizeof(BitRandomStatus),MPI_BYTE,&this_stat,1*sizeof(BitRandomStatus),MPI_BYTE,0,comm_cart); 02229 RANDOM_TRACE(printf("%d: Received status %d/%d/...\n",this_node,this_stat.random_pointer_1,this_stat.random_pointer_2)); 02230 init_bit_random_stat(this_stat); 02231 } 02232 } 02233 02234 void mpi_bit_random_stat_slave(int pnode, int cnt) { 02235 BitRandomStatus this_stat = print_bit_random_stat(); 02236 02237 if (cnt==0) { 02238 RANDOM_TRACE(printf("%d: Have status %d/%d/...\n",this_node,this_stat.random_pointer_1,this_stat.random_pointer_2)); 02239 MPI_Gather(&this_stat,1*sizeof(BitRandomStatus),MPI_BYTE,NULL,0,MPI_BYTE,0,comm_cart); } 02240 else { 02241 MPI_Scatter(NULL,0,MPI_BYTE,&this_stat,1*sizeof(BitRandomStatus),MPI_BYTE,0,comm_cart); 02242 RANDOM_TRACE(printf("%d: Received status %d/%d/...\n",this_node,this_stat.random_pointer_1,this_stat.random_pointer_2)); 02243 init_bit_random_stat(this_stat); 02244 } 02245 } 02246 02247 /****************** REQ_RESCALE_PART ************/ 02248 02249 void mpi_rescale_particles(int dir, double scale) { 02250 int pnode; 02251 02252 mpi_call(mpi_rescale_particles_slave, -1, dir); 02253 for (pnode = 0; pnode < n_nodes; pnode++) { 02254 if (pnode == this_node) { 02255 local_rescale_particles(dir, scale); } 02256 else { 02257 MPI_Send(&scale, 1, MPI_DOUBLE, pnode, SOME_TAG, comm_cart); } 02258 } 02259 on_particle_change(); 02260 } 02261 02262 void mpi_rescale_particles_slave(int pnode, int dir) { 02263 double scale=0.0; 02264 MPI_Recv(&scale, 1, MPI_DOUBLE, 0, SOME_TAG, comm_cart, MPI_STATUS_IGNORE); 02265 local_rescale_particles(dir, scale); 02266 on_particle_change(); 02267 } 02268 02269 /*************** REQ_BCAST_CS *****************/ 02270 02271 void mpi_bcast_cell_structure(int cs) 02272 { 02273 mpi_call(mpi_bcast_cell_structure_slave, -1, cs); 02274 cells_re_init(cs); 02275 } 02276 02277 void mpi_bcast_cell_structure_slave(int pnode, int cs) 02278 { 02279 cells_re_init(cs); 02280 } 02281 02282 /*************** REQ_BCAST_NPTISO_GEOM *****************/ 02283 02284 void mpi_bcast_nptiso_geom() 02285 { 02286 mpi_call(mpi_bcast_nptiso_geom_slave, -1 , 0); 02287 mpi_bcast_nptiso_geom_slave(-1,0); 02288 02289 } 02290 02291 void mpi_bcast_nptiso_geom_slave(int node,int parm) 02292 { 02293 MPI_Bcast(&nptiso.geometry, 1,MPI_INT, 0, comm_cart); 02294 MPI_Bcast(&nptiso.dimension, 1,MPI_INT, 0, comm_cart); 02295 MPI_Bcast(&nptiso.cubic_box, 1,MPI_INT, 0, comm_cart); 02296 MPI_Bcast(&nptiso.non_const_dim, 1,MPI_INT, 0, comm_cart); 02297 02298 } 02299 02300 /***************REQ_UPDATE_MOL_IDS *********************/ 02301 02302 void mpi_update_mol_ids() 02303 { 02304 mpi_call(mpi_update_mol_ids_slave, -1, 0); 02305 mpi_update_mol_ids_slave(-1, 0); 02306 } 02307 02308 void mpi_update_mol_ids_slave(int node,int parm) 02309 { 02310 update_mol_ids_setchains(); 02311 } 02312 02313 /******************* REQ_SYNC_TOPO ********************/ 02314 int mpi_sync_topo_part_info() { 02315 int i; 02316 int molsize=0; 02317 int moltype=0; 02318 int n_mols=0; 02319 02320 mpi_call(mpi_sync_topo_part_info_slave,-1,0); 02321 n_mols = n_molecules; 02322 MPI_Bcast(&n_mols,1,MPI_INT,0,comm_cart); 02323 02324 for ( i = 0 ; i < n_molecules ; i++) { 02325 molsize = topology[i].part.n; 02326 moltype = topology[i].type; 02327 02328 #ifdef MOLFORCES 02329 MPI_Bcast(&(topology[i].trap_flag),1,MPI_INT,0,comm_cart); 02330 MPI_Bcast(topology[i].trap_center,3,MPI_DOUBLE,0,comm_cart); 02331 MPI_Bcast(&(topology[i].trap_spring_constant),1,MPI_DOUBLE,0,comm_cart); 02332 MPI_Bcast(&(topology[i].drag_constant),1,MPI_DOUBLE,0,comm_cart); 02333 MPI_Bcast(&(topology[i].noforce_flag),1,MPI_INT,0,comm_cart); 02334 MPI_Bcast(&(topology[i].isrelative),1,MPI_INT,0,comm_cart); 02335 MPI_Bcast(&(topology[i].favcounter),1,MPI_INT,0,comm_cart); 02336 if (topology[i].favcounter == -1) 02337 MPI_Bcast(topology[i].fav,3,MPI_DOUBLE,0,comm_cart); 02338 /* check if any molecules are trapped */ 02339 if ((topology[i].trap_flag != 32) && (topology[i].noforce_flag != 32)) { 02340 IsTrapped = 1; 02341 } 02342 #endif 02343 02344 MPI_Bcast(&molsize,1,MPI_INT,0,comm_cart); 02345 MPI_Bcast(&moltype,1,MPI_INT,0,comm_cart); 02346 MPI_Bcast(topology[i].part.e,topology[i].part.n,MPI_INT,0,comm_cart); 02347 MPI_Bcast(&topology[i].type,1,MPI_INT,0,comm_cart); 02348 02349 } 02350 02351 sync_topo_part_info(); 02352 02353 return 1; 02354 } 02355 02356 void mpi_sync_topo_part_info_slave(int node,int parm ) { 02357 int i; 02358 int molsize=0; 02359 int moltype=0; 02360 int n_mols=0; 02361 02362 MPI_Bcast(&n_mols,1,MPI_INT,0,comm_cart); 02363 realloc_topology(n_mols); 02364 for ( i = 0 ; i < n_molecules ; i++) { 02365 02366 #ifdef MOLFORCES 02367 MPI_Bcast(&(topology[i].trap_flag),1,MPI_INT,0,comm_cart); 02368 MPI_Bcast(topology[i].trap_center,3,MPI_DOUBLE,0,comm_cart); 02369 MPI_Bcast(&(topology[i].trap_spring_constant),1,MPI_DOUBLE,0,comm_cart); 02370 MPI_Bcast(&(topology[i].drag_constant),1,MPI_DOUBLE,0,comm_cart); 02371 MPI_Bcast(&(topology[i].noforce_flag),1,MPI_INT,0,comm_cart); 02372 MPI_Bcast(&(topology[i].isrelative),1,MPI_INT,0,comm_cart); 02373 MPI_Bcast(&(topology[i].favcounter),1,MPI_INT,0,comm_cart); 02374 if (topology[i].favcounter == -1) 02375 MPI_Bcast(topology[i].fav,3,MPI_DOUBLE,0,comm_cart); 02376 /* check if any molecules are trapped */ 02377 if ((topology[i].trap_flag != 32) && (topology[i].noforce_flag != 32)) { 02378 IsTrapped = 1; 02379 } 02380 #endif 02381 02382 MPI_Bcast(&molsize,1,MPI_INT,0,comm_cart); 02383 MPI_Bcast(&moltype,1,MPI_INT,0,comm_cart); 02384 topology[i].type = moltype; 02385 realloc_intlist(&topology[i].part,topology[i].part.n = molsize); 02386 02387 MPI_Bcast(topology[i].part.e,topology[i].part.n,MPI_INT,0,comm_cart); 02388 MPI_Bcast(&topology[i].type,1,MPI_INT,0,comm_cart); 02389 02390 } 02391 02392 02393 sync_topo_part_info(); 02394 02395 } 02396 02397 /******************* REQ_BCAST_LBPAR ********************/ 02398 02399 void mpi_bcast_lb_params(int field) 02400 { 02401 #ifdef LB 02402 mpi_call(mpi_bcast_lb_params_slave, -1, field); 02403 mpi_bcast_lb_params_slave(-1, field); 02404 #endif 02405 } 02406 02407 void mpi_bcast_lb_params_slave(int node, int field) 02408 { 02409 #ifdef LB 02410 MPI_Bcast(&lbpar, sizeof(LB_Parameters), MPI_BYTE, 0, comm_cart); 02411 on_lb_params_change(field); 02412 #endif 02413 } 02414 02415 02416 /******************* REQ_BCAST_CUDA_GLOBAL_PART_VARS ********************/ 02417 02418 void mpi_bcast_cuda_global_part_vars() { 02419 #ifdef CUDA 02420 mpi_call(mpi_bcast_cuda_global_part_vars_slave, 1, 0); // third parameter is meaningless 02421 mpi_bcast_cuda_global_part_vars_slave(-1,0); 02422 #endif 02423 } 02424 02425 void mpi_bcast_cuda_global_part_vars_slave(int node, int dummy) 02426 { 02427 #ifdef CUDA 02428 MPI_Bcast(gpu_get_global_particle_vars_pointer_host(), sizeof(CUDA_global_part_vars), MPI_BYTE, 0, comm_cart); 02429 #endif 02430 } 02431 02432 02433 02434 /******************* REQ_GET_ERRS ********************/ 02435 02436 int mpi_gather_runtime_errors(char **errors) 02437 { 02438 // Tell other processors to send their erros 02439 mpi_call(mpi_gather_runtime_errors_slave, -1, 0); 02440 02441 // If no processor encountered an error, return 02442 if (!check_runtime_errors()) 02443 return ES_OK; 02444 02445 // gather the maximum length of the error messages 02446 int *errcnt = malloc(n_nodes*sizeof(int)); 02447 MPI_Gather(&n_error_msg, 1, MPI_INT, errcnt, 1, MPI_INT, 0, comm_cart); 02448 02449 for (int node = 0; node < n_nodes; node++) { 02450 if (errcnt[node] > 0) { 02451 errors[node] = (char *)malloc(errcnt[node]); 02452 02453 if (node == 0) 02454 strcpy(errors[node], error_msg); 02455 else 02456 MPI_Recv(errors[node], errcnt[node], MPI_CHAR, node, 0, comm_cart, MPI_STATUS_IGNORE); 02457 } 02458 else 02459 errors[node] = NULL; 02460 } 02461 02462 /* reset error message on master node */ 02463 error_msg = realloc(error_msg, n_error_msg = 0); 02464 02465 free(errcnt); 02466 02467 return ES_ERROR; 02468 } 02469 02470 void mpi_gather_runtime_errors_slave(int node, int parm) 02471 { 02472 if (!check_runtime_errors()) 02473 return; 02474 02475 MPI_Gather(&n_error_msg, 1, MPI_INT, NULL, 0, MPI_INT, 0, comm_cart); 02476 if (n_error_msg > 0) { 02477 MPI_Send(error_msg, n_error_msg, MPI_CHAR, 0, 0, comm_cart); 02478 /* reset error message on slave node */ 02479 error_msg = realloc(error_msg, n_error_msg = 0); 02480 } 02481 } 02482 02483 /********************* REQ_SET_EXCL ********/ 02484 void mpi_send_exclusion(int part1, int part2, int delete) 02485 { 02486 #ifdef EXCLUSIONS 02487 mpi_call(mpi_send_exclusion_slave, part1, part2); 02488 02489 MPI_Bcast(&delete, 1, MPI_INT, 0, comm_cart); 02490 local_change_exclusion(part1, part2, delete); 02491 on_particle_change(); 02492 #endif 02493 } 02494 02495 void mpi_send_exclusion_slave(int part1, int part2) 02496 { 02497 #ifdef EXCLUSIONS 02498 int delete=0; 02499 MPI_Bcast(&delete, 1, MPI_INT, 0, comm_cart); 02500 local_change_exclusion(part1, part2, delete); 02501 on_particle_change(); 02502 #endif 02503 } 02504 02505 /************** REQ_SET_FLUID **************/ 02506 void mpi_send_fluid(int node, int index, double rho, double *j, double *pi) { 02507 #ifdef LB 02508 if (node==this_node) { 02509 lb_calc_n_equilibrium(index, rho, j, pi); 02510 } else { 02511 double data[10] = { rho, j[0], j[1], j[2], pi[0], pi[1], pi[2], pi[3], pi[4], pi[5] }; 02512 mpi_call(mpi_send_fluid_slave, node, index); 02513 MPI_Send(data, 10, MPI_DOUBLE, node, SOME_TAG, comm_cart); 02514 } 02515 #endif 02516 } 02517 02518 void mpi_send_fluid_slave(int node, int index) { 02519 #ifdef LB 02520 if (node==this_node) { 02521 double data[10]; 02522 MPI_Recv(data, 10, MPI_DOUBLE, 0, SOME_TAG, comm_cart, MPI_STATUS_IGNORE); 02523 02524 lb_calc_n_equilibrium(index, data[0], &data[1], &data[4]); 02525 } 02526 #endif 02527 } 02528 02529 /************** REQ_GET_FLUID **************/ 02530 void mpi_recv_fluid(int node, int index, double *rho, double *j, double *pi) { 02531 #ifdef LB 02532 if (node==this_node) { 02533 lb_calc_local_fields(index, rho, j, pi); 02534 } else { 02535 double data[10]; 02536 mpi_call(mpi_recv_fluid_slave, node, index); 02537 MPI_Recv(data, 10, MPI_DOUBLE, node, SOME_TAG, comm_cart, MPI_STATUS_IGNORE); 02538 *rho = data[0]; 02539 j[0] = data[1]; 02540 j[1] = data[2]; 02541 j[2] = data[3]; 02542 pi[0] = data[4]; 02543 pi[1] = data[5]; 02544 pi[2] = data[6]; 02545 pi[3] = data[7]; 02546 pi[4] = data[8]; 02547 pi[5] = data[9]; 02548 02549 } 02550 #endif 02551 } 02552 02553 void mpi_recv_fluid_slave(int node, int index) { 02554 #ifdef LB 02555 if (node==this_node) { 02556 double data[10]; 02557 lb_calc_local_fields(index, &data[0], &data[1], &data[4]); 02558 MPI_Send(data, 10, MPI_DOUBLE, 0, SOME_TAG, comm_cart); 02559 } 02560 #endif 02561 } 02562 02563 /************** REQ_LB_GET_BOUNDARY_FLAG **************/ 02564 void mpi_recv_fluid_boundary_flag(int node, int index, int *boundary) { 02565 #ifdef LB_BOUNDARIES 02566 if (node==this_node) { 02567 lb_local_fields_get_boundary_flag(index, boundary); 02568 } else { 02569 int data = 0; 02570 mpi_call(mpi_recv_fluid_boundary_flag_slave, node, index); 02571 MPI_Recv(&data, 1, MPI_INT, node, SOME_TAG, comm_cart, MPI_STATUS_IGNORE); 02572 *boundary = data; 02573 } 02574 #endif 02575 } 02576 02577 void mpi_recv_fluid_boundary_flag_slave(int node, int index) { 02578 #ifdef LB_BOUNDARIES 02579 if (node==this_node) { 02580 int data; 02581 lb_local_fields_get_boundary_flag(index, &data); 02582 MPI_Send(&data, 1, MPI_INT, 0, SOME_TAG, comm_cart); 02583 } 02584 #endif 02585 } 02586 02587 /********************* REQ_ICCP3M_ITERATION ********/ 02588 int mpi_iccp3m_iteration(int dummy) 02589 { 02590 #ifdef ELECTROSTATICS 02591 mpi_call(mpi_iccp3m_iteration_slave, -1, 0); 02592 02593 iccp3m_iteration(); 02594 02595 COMM_TRACE(fprintf(stderr, "%d: iccp3m iteration task %d done.\n", this_node, dummy)); 02596 02597 return check_runtime_errors(); 02598 #else 02599 return 0; 02600 #endif 02601 02602 } 02603 02604 void mpi_iccp3m_iteration_slave(int dummy, int dummy2) 02605 { 02606 #ifdef ELECTROSTATICS 02607 iccp3m_iteration(); 02608 COMM_TRACE(fprintf(stderr, "%d: iccp3m iteration task %d done.\n", dummy, dummy2)); 02609 02610 check_runtime_errors(); 02611 #endif 02612 } 02613 02614 /********************* REQ_ICCP3M_INIT********/ 02615 int mpi_iccp3m_init(int n_induced_charges) 02616 { 02617 #ifdef ELECTROSTATICS 02618 /* nothing has to be done on the master node, this 02619 * passes only the number of induced charges, in order for 02620 * slaves to allocate memory */ 02621 02622 mpi_call(mpi_iccp3m_init_slave, -1, n_induced_charges); 02623 02624 bcast_iccp3m_cfg(); 02625 02626 COMM_TRACE(fprintf(stderr, "%d: iccp3m init task %d done.\n", this_node, n_induced_charges)); 02627 02628 return check_runtime_errors(); 02629 #else 02630 return 0; 02631 #endif 02632 02633 } 02634 02635 void mpi_iccp3m_init_slave(int node, int dummy) 02636 { 02637 #ifdef ELECTROSTATICS 02638 COMM_TRACE(fprintf(stderr, "%d: iccp3m iteration task %d done.\n", this_node, dummy)); 02639 02640 if(iccp3m_initialized==0){ 02641 iccp3m_init(); 02642 iccp3m_initialized=1; 02643 } 02644 02645 bcast_iccp3m_cfg(); 02646 02647 check_runtime_errors(); 02648 #endif 02649 } 02650 02651 void mpi_recv_fluid_populations(int node, int index, double *pop) { 02652 #ifdef LB 02653 if (node==this_node) { 02654 lb_get_populations(index, pop); 02655 } else { 02656 mpi_call(mpi_recv_fluid_populations_slave, node, index); 02657 MPI_Recv(pop, 19, MPI_DOUBLE, node, SOME_TAG, comm_cart, MPI_STATUS_IGNORE); 02658 } 02659 lbpar.resend_halo=1; 02660 #endif 02661 } 02662 02663 void mpi_recv_fluid_populations_slave(int node, int index) { 02664 #ifdef LB 02665 if (node==this_node) { 02666 double data[19]; 02667 lb_get_populations(index, data); 02668 MPI_Send(data, 19, MPI_DOUBLE, 0, SOME_TAG, comm_cart); 02669 } 02670 lbpar.resend_halo=1; 02671 #endif 02672 } 02673 02674 void mpi_send_fluid_populations(int node, int index, double *pop) { 02675 #ifdef LB 02676 if (node==this_node) { 02677 lb_set_populations(index, pop); 02678 } else { 02679 mpi_call(mpi_send_fluid_populations_slave, node, index); 02680 MPI_Send(pop, 19, MPI_DOUBLE, node, SOME_TAG, comm_cart); 02681 } 02682 #endif 02683 } 02684 02685 void mpi_send_fluid_populations_slave(int node, int index) { 02686 #ifdef LB 02687 if (node==this_node) { 02688 double data[19]; 02689 MPI_Recv(data, 19, MPI_DOUBLE, 0, SOME_TAG, comm_cart, MPI_STATUS_IGNORE); 02690 lb_set_populations(index, data); 02691 } 02692 #endif 02693 } 02694 02695 /****************************************************/ 02696 02697 void mpi_bcast_max_mu() { 02698 #ifdef DIPOLES 02699 mpi_call(mpi_bcast_max_mu_slave, -1, 0); 02700 02701 calc_mu_max(); 02702 02703 #endif 02704 } 02705 02706 void mpi_bcast_max_mu_slave(int node, int dummy) { 02707 #ifdef DIPOLES 02708 02709 calc_mu_max(); 02710 02711 #endif 02712 } 02713 02714 #ifdef LANGEVIN_PER_PARTICLE 02715 02716 /******************** REQ_SEND_PARTICLE_T ********************/ 02717 void mpi_set_particle_temperature(int pnode, int part, double _T) 02718 { 02719 mpi_call(mpi_set_particle_temperature_slave, pnode, part); 02720 02721 if (pnode == this_node) { 02722 Particle *p = local_particles[part]; 02723 /* here the setting actually happens, if the particle belongs to the local node */ 02724 p->p.T = _T; 02725 } 02726 else { 02727 MPI_Send(&_T, 1, MPI_DOUBLE, pnode, SOME_TAG, comm_cart); 02728 } 02729 02730 on_particle_change(); 02731 } 02732 #endif 02733 02734 void mpi_set_particle_temperature_slave(int pnode, int part) 02735 { 02736 #ifdef LANGEVIN_PER_PARTICLE 02737 double s_buf = 0.; 02738 if (pnode == this_node) { 02739 Particle *p = local_particles[part]; 02740 MPI_Status status; 02741 MPI_Recv(&s_buf, 1, MPI_DOUBLE, 0, SOME_TAG, comm_cart, &status); 02742 /* here the setting happens for nonlocal nodes */ 02743 p->p.T = s_buf; 02744 } 02745 02746 on_particle_change(); 02747 #endif 02748 } 02749 02750 #ifdef LANGEVIN_PER_PARTICLE 02751 void mpi_set_particle_gamma(int pnode, int part, double gamma) 02752 { 02753 mpi_call(mpi_set_particle_gamma_slave, pnode, part); 02754 02755 if (pnode == this_node) { 02756 Particle *p = local_particles[part]; 02757 /* here the setting actually happens, if the particle belongs to the local node */ 02758 p->p.gamma = gamma; 02759 } 02760 else { 02761 MPI_Send(&gamma, 1, MPI_DOUBLE, pnode, SOME_TAG, comm_cart); 02762 } 02763 02764 on_particle_change(); 02765 } 02766 #endif 02767 02768 void mpi_set_particle_gamma_slave(int pnode, int part) 02769 { 02770 #ifdef LANGEVIN_PER_PARTICLE 02771 double s_buf = 0.; 02772 if (pnode == this_node) { 02773 Particle *p = local_particles[part]; 02774 MPI_Status status; 02775 MPI_Recv(&s_buf, 1, MPI_DOUBLE, 0, SOME_TAG, comm_cart, &status); 02776 /* here the setting happens for nonlocal nodes */ 02777 p->p.gamma = s_buf; 02778 } 02779 02780 on_particle_change(); 02781 #endif 02782 } 02783 02784 /***** GALILEI TRANSFORM AND ASSOCIATED FUNCTIONS ****/ 02785 02786 void mpi_kill_particle_motion( int rotation ) 02787 { 02788 mpi_call(mpi_kill_particle_motion_slave, -1, rotation ); 02789 local_kill_particle_motion( rotation ); 02790 on_particle_change(); 02791 } 02792 02793 void mpi_kill_particle_motion_slave(int pnode, int rotation ) 02794 { 02795 local_kill_particle_motion( rotation ); 02796 on_particle_change(); 02797 } 02798 02799 void mpi_kill_particle_forces( int torque ) 02800 { 02801 mpi_call(mpi_kill_particle_forces_slave, -1, torque ); 02802 local_kill_particle_forces( torque ); 02803 on_particle_change(); 02804 } 02805 02806 void mpi_kill_particle_forces_slave(int pnode, int torque) 02807 { 02808 local_kill_particle_forces( torque ); 02809 on_particle_change(); 02810 } 02811 02812 void mpi_system_CMS() { 02813 int pnode; 02814 double data[4]; 02815 double rdata[4]; 02816 double *pdata = rdata; 02817 02818 data[0] = 0.0; 02819 data[1] = 0.0; 02820 data[2] = 0.0; 02821 data[3] = 0.0; 02822 02823 mpi_call(mpi_system_CMS_slave, -1, 0); 02824 02825 for (pnode = 0; pnode < n_nodes; pnode++) { 02826 if (pnode==this_node) { 02827 local_system_CMS( pdata ); 02828 data[0] += rdata[0]; 02829 data[1] += rdata[1]; 02830 data[2] += rdata[2]; 02831 data[3] += rdata[3]; 02832 } else { 02833 MPI_Recv(rdata, 4, MPI_DOUBLE, MPI_ANY_SOURCE, SOME_TAG, comm_cart, MPI_STATUS_IGNORE); 02834 data[0] += rdata[0]; 02835 data[1] += rdata[1]; 02836 data[2] += rdata[2]; 02837 data[3] += rdata[3]; 02838 } 02839 } 02840 02841 gal.cms[0] = data[0]/data[3]; 02842 gal.cms[1] = data[1]/data[3]; 02843 gal.cms[2] = data[2]/data[3]; 02844 } 02845 02846 void mpi_system_CMS_slave(int node, int index) { 02847 double rdata[4]; 02848 double *pdata = rdata; 02849 local_system_CMS( pdata ); 02850 MPI_Send(rdata, 4, MPI_DOUBLE, 0, SOME_TAG, comm_cart); 02851 } 02852 02853 void mpi_system_CMS_velocity() { 02854 int pnode; 02855 double data[4]; 02856 double rdata[4]; 02857 double *pdata = rdata; 02858 02859 data[0] = 0.0; 02860 data[1] = 0.0; 02861 data[2] = 0.0; 02862 data[3] = 0.0; 02863 02864 mpi_call(mpi_system_CMS_velocity_slave, -1, 0); 02865 02866 for (pnode = 0; pnode < n_nodes; pnode++) { 02867 if (pnode==this_node) { 02868 local_system_CMS_velocity( pdata ); 02869 data[0] += rdata[0]; 02870 data[1] += rdata[1]; 02871 data[2] += rdata[2]; 02872 data[3] += rdata[3]; 02873 } else { 02874 MPI_Recv(rdata, 4, MPI_DOUBLE, MPI_ANY_SOURCE, SOME_TAG, comm_cart, MPI_STATUS_IGNORE); 02875 data[0] += rdata[0]; 02876 data[1] += rdata[1]; 02877 data[2] += rdata[2]; 02878 data[3] += rdata[3]; 02879 } 02880 } 02881 02882 gal.cms_vel[0] = data[0]/data[3]; 02883 gal.cms_vel[1] = data[1]/data[3]; 02884 gal.cms_vel[2] = data[2]/data[3]; 02885 } 02886 02887 void mpi_system_CMS_velocity_slave(int node, int index) { 02888 double rdata[4]; 02889 double *pdata = rdata; 02890 local_system_CMS_velocity( pdata ); 02891 MPI_Send(rdata, 4, MPI_DOUBLE, 0, SOME_TAG, comm_cart); 02892 } 02893 02894 void mpi_galilei_transform() 02895 { 02896 double cmsvel[3]; 02897 02898 mpi_system_CMS_velocity(); 02899 memcpy(cmsvel, gal.cms_vel, 3*sizeof(double)); 02900 02901 mpi_call(mpi_galilei_transform_slave, -1, 0); 02902 MPI_Bcast(cmsvel, 3, MPI_DOUBLE, 0, comm_cart); 02903 02904 local_galilei_transform( cmsvel ); 02905 02906 on_particle_change(); 02907 } 02908 02909 void mpi_galilei_transform_slave(int pnode, int i) 02910 { 02911 double cmsvel[3]; 02912 MPI_Bcast(cmsvel, 3, MPI_DOUBLE, 0, comm_cart); 02913 02914 local_galilei_transform( cmsvel ); 02915 on_particle_change(); 02916 } 02917 02918 /******************** REQ_CATALYTIC_REACTIONS ********************/ 02919 02920 void mpi_setup_reaction() 02921 { 02922 #ifdef CATALYTIC_REACTIONS 02923 mpi_call(mpi_setup_reaction_slave, -1, 0); 02924 local_setup_reaction(); 02925 #endif 02926 } 02927 02928 void mpi_setup_reaction_slave(int pnode, int i) 02929 { 02930 #ifdef CATALYTIC_REACTIONS 02931 local_setup_reaction(); 02932 #endif 02933 } 02934 02935 /*********************** MAIN LOOP for slaves ****************/ 02936 02937 void mpi_loop() 02938 { 02939 for (;;) { 02940 #ifdef ASYNC_BARRIER 02941 MPI_Barrier(comm_cart); 02942 #endif 02943 MPI_Bcast(request, 3, MPI_INT, 0, comm_cart); 02944 COMM_TRACE(fprintf(stderr, "%d: processing %s %d %d...\n", this_node, 02945 names[request[0]], request[1], request[2])); 02946 if ((request[0] < 0) || (request[0] >= N_CALLBACKS)) { 02947 fprintf(stderr, "%d: INTERNAL ERROR: unknown request %d\n", this_node, request[0]); 02948 errexit(); 02949 } 02950 slave_callbacks[request[0]](request[1], request[2]); 02951 COMM_TRACE(fprintf(stderr, "%d: finished %s %d %d\n", this_node, 02952 names[request[0]], request[1], request[2])); 02953 } 02954 } 02955
1.7.5.1