![]() |
ESPResSo 3.2.0-11-g9950804-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 /** \file layered.c 00022 Implementation of \ref layered.h "layered.h". 00023 */ 00024 #include <mpi.h> 00025 #include <string.h> 00026 #include "utils.h" 00027 #include "cells.h" 00028 #include "integrate.h" 00029 #include "layered.h" 00030 #include "global.h" 00031 #include "communication.h" 00032 #include "ghosts.h" 00033 #include "forces.h" 00034 #include "pressure.h" 00035 #include "energy.h" 00036 #include "constraint.h" 00037 #include "domain_decomposition.h" 00038 00039 /* Organization: Layers only in one direction. 00040 ghost_bottom 00041 c1 00042 c2 00043 c3 00044 . 00045 . 00046 . 00047 cn 00048 ghost_top 00049 00050 First, all nodes send downwards, then upwards. Within these actions, 00051 first the odd nodes send. For even n_nodes, this algorithm is straight 00052 forward: first the odd nodes send, the even receive, then vice versa. 00053 For odd n_nodes, we have 00054 1) 1->2 3->4 5->1 00055 2) 2->3 4->5 00056 So in the first round node 5 has to wait for node 1 to 00057 complete the send and get ready to receive. In other words, 00058 what physically happens is: 00059 1) 1->2 3->4 5->* 00060 2) *->1 2->3 4->* 00061 3) *->5 00062 This means that one pending receive has to be done in addition 00063 provided that all other transmissions can happen in parallel. 00064 00065 */ 00066 00067 /** wether we are the lowest node */ 00068 #define LAYERED_BOTTOM 1 00069 /** wether we are the highest node */ 00070 #define LAYERED_TOP 2 00071 /** same as PERIODIC(2) */ 00072 #define LAYERED_PERIODIC 4 00073 #define LAYERED_BTM_MASK (LAYERED_BOTTOM|LAYERED_PERIODIC) 00074 #define LAYERED_TOP_MASK (LAYERED_TOP|LAYERED_PERIODIC) 00075 /** node has a neighbor above (modulo n_nodes) */ 00076 #define LAYERED_TOP_NEIGHBOR ((layered_flags & LAYERED_TOP_MASK) != LAYERED_TOP) 00077 /** node has a neighbor below (modulo n_nodes) */ 00078 #define LAYERED_BTM_NEIGHBOR ((layered_flags & LAYERED_BTM_MASK) != LAYERED_BOTTOM) 00079 00080 int layered_flags = 0; 00081 int n_layers = -1, determine_n_layers = 1; 00082 double layer_h = 0, layer_h_i = 0; 00083 00084 static int btm, top; 00085 00086 void layered_get_mi_vector(double res[3], double a[3], double b[3]) 00087 { 00088 int i; 00089 00090 for(i=0;i<2;i++) { 00091 res[i] = a[i] - b[i]; 00092 #ifdef PARTIAL_PERIODIC 00093 if (PERIODIC(i)) 00094 #endif 00095 res[i] -= dround(res[i]*box_l_i[i])*box_l[i]; 00096 } 00097 res[2] = a[2] - b[2]; 00098 } 00099 00100 Cell *layered_position_to_cell(double pos[3]) 00101 { 00102 int cpos = (int)((pos[2] - my_left[2])*layer_h_i) + 1; 00103 if (cpos < 1) { 00104 if (!LAYERED_BTM_NEIGHBOR) 00105 cpos = 1; 00106 else 00107 return NULL; 00108 } 00109 else if (cpos > n_layers) { 00110 /* not periodic, but at top */ 00111 if (!LAYERED_TOP_NEIGHBOR) 00112 cpos = n_layers; 00113 else 00114 return NULL; 00115 } 00116 return &(cells[cpos]); 00117 } 00118 00119 void layered_topology_release() 00120 { 00121 CELL_TRACE(fprintf(stderr,"%d: layered_topology_release:\n", this_node)); 00122 free_comm(&cell_structure.ghost_cells_comm); 00123 free_comm(&cell_structure.exchange_ghosts_comm); 00124 free_comm(&cell_structure.update_ghost_pos_comm); 00125 free_comm(&cell_structure.collect_ghost_force_comm); 00126 } 00127 00128 static void layered_prepare_comm(GhostCommunicator *comm, int data_parts) 00129 { 00130 int even_odd; 00131 int c, n; 00132 00133 if (n_nodes > 1) { 00134 /* more than one node => no local transfers */ 00135 00136 /* how many communications to do: up even/odd, down even/odd */ 00137 n = 4; 00138 /* one communication missing if not periodic but on border */ 00139 if (!LAYERED_TOP_NEIGHBOR) 00140 n -= 2; 00141 if (!LAYERED_BTM_NEIGHBOR) 00142 n -= 2; 00143 00144 prepare_comm(comm, data_parts, n); 00145 00146 /* always sending/receiving 1 cell per time step */ 00147 for(c = 0; c < n; c++) { 00148 comm->comm[c].part_lists = malloc(sizeof(ParticleList *)); 00149 comm->comm[c].n_part_lists = 1; 00150 comm->comm[c].mpi_comm = comm_cart; 00151 } 00152 00153 c = 0; 00154 00155 CELL_TRACE(fprintf(stderr, "%d: ghostrec new comm of size %d\n", this_node, n)); 00156 /* downwards */ 00157 for (even_odd = 0; even_odd < 2; even_odd++) { 00158 /* send */ 00159 if (this_node % 2 == even_odd && LAYERED_BTM_NEIGHBOR) { 00160 comm->comm[c].type = GHOST_SEND; 00161 /* round 1 uses prefetched data and stores delayed data */ 00162 if (c == 1) 00163 comm->comm[c].type |= GHOST_PREFETCH | GHOST_PSTSTORE; 00164 comm->comm[c].node = btm; 00165 if (data_parts == GHOSTTRANS_FORCE) { 00166 comm->comm[c].part_lists[0] = &cells[0]; 00167 CELL_TRACE(fprintf(stderr, "%d: ghostrec send force to %d btmg\n", this_node, btm)); 00168 } 00169 else { 00170 comm->comm[c].part_lists[0] = &cells[1]; 00171 00172 /* if periodic and bottom or top, send shifted */ 00173 comm->comm[c].shift[0] = comm->comm[c].shift[1] = 0; 00174 if (((layered_flags & LAYERED_BTM_MASK) == LAYERED_BTM_MASK) && 00175 (data_parts & GHOSTTRANS_POSITION)) { 00176 comm->data_parts |= GHOSTTRANS_POSSHFTD; 00177 comm->comm[c].shift[2] = box_l[2]; 00178 } 00179 else 00180 comm->comm[c].shift[2] = 0; 00181 CELL_TRACE(fprintf(stderr, "%d: ghostrec send to %d shift %f btml\n", this_node, btm, comm->comm[c].shift[2])); 00182 } 00183 c++; 00184 } 00185 /* recv. Note we test r_node as we always have to test the sender 00186 as for odd n_nodes maybe we send AND receive. */ 00187 if (top % 2 == even_odd && LAYERED_TOP_NEIGHBOR) { 00188 comm->comm[c].type = GHOST_RECV; 00189 /* round 0 prefetch send for round 1 and delay recvd data processing */ 00190 if (c == 0) 00191 comm->comm[c].type |= GHOST_PREFETCH | GHOST_PSTSTORE; 00192 comm->comm[c].node = top; 00193 if (data_parts == GHOSTTRANS_FORCE) { 00194 comm->comm[c].part_lists[0] = &cells[n_layers]; 00195 CELL_TRACE(fprintf(stderr, "%d: ghostrec get force from %d topl\n", this_node, top)); 00196 } 00197 else { 00198 comm->comm[c].part_lists[0] = &cells[n_layers + 1]; 00199 CELL_TRACE(fprintf(stderr, "%d: ghostrec recv from %d topg\n", this_node, top)); 00200 } 00201 c++; 00202 } 00203 } 00204 00205 CELL_TRACE(fprintf(stderr, "%d: ghostrec upwards\n", this_node)); 00206 /* upwards */ 00207 for (even_odd = 0; even_odd < 2; even_odd++) { 00208 /* send */ 00209 if (this_node % 2 == even_odd && LAYERED_TOP_NEIGHBOR) { 00210 comm->comm[c].type = GHOST_SEND; 00211 /* round 1 use prefetched data from round 0. 00212 But this time there may already have been two transfers downwards */ 00213 if (c % 2 == 1) 00214 comm->comm[c].type |= GHOST_PREFETCH | GHOST_PSTSTORE; 00215 comm->comm[c].node = top; 00216 if (data_parts == GHOSTTRANS_FORCE) { 00217 comm->comm[c].part_lists[0] = &cells[n_layers + 1]; 00218 CELL_TRACE(fprintf(stderr, "%d: ghostrec send force to %d topg\n", this_node, top)); 00219 } 00220 else { 00221 comm->comm[c].part_lists[0] = &cells[n_layers]; 00222 00223 /* if periodic and bottom or top, send shifted */ 00224 comm->comm[c].shift[0] = comm->comm[c].shift[1] = 0; 00225 if (((layered_flags & LAYERED_TOP_MASK) == LAYERED_TOP_MASK) && 00226 (data_parts & GHOSTTRANS_POSITION)) { 00227 comm->data_parts |= GHOSTTRANS_POSSHFTD; 00228 comm->comm[c].shift[2] = -box_l[2]; 00229 } 00230 else 00231 comm->comm[c].shift[2] = 0; 00232 CELL_TRACE(fprintf(stderr, "%d: ghostrec send to %d shift %f topl\n", this_node, top, comm->comm[c].shift[2])); 00233 } 00234 c++; 00235 } 00236 /* recv. Note we test r_node as we always have to test the sender 00237 as for odd n_nodes maybe we send AND receive. */ 00238 if (btm % 2 == even_odd && LAYERED_BTM_NEIGHBOR) { 00239 comm->comm[c].type = GHOST_RECV; 00240 /* round 0 prefetch. But this time there may already have been two transfers downwards */ 00241 if (c % 2 == 0) 00242 comm->comm[c].type |= GHOST_PREFETCH | GHOST_PSTSTORE; 00243 comm->comm[c].node = btm; 00244 if (data_parts == GHOSTTRANS_FORCE) { 00245 comm->comm[c].part_lists[0] = &cells[1]; 00246 CELL_TRACE(fprintf(stderr, "%d: ghostrec get force from %d btml\n", this_node, btm)); 00247 } 00248 else { 00249 comm->comm[c].part_lists[0] = &cells[0]; 00250 CELL_TRACE(fprintf(stderr, "%d: ghostrec recv from %d btmg\n", this_node, btm)); 00251 } 00252 c++; 00253 } 00254 } 00255 } 00256 else { 00257 /* one node => local transfers, either 2 (up and down, periodic) or zero*/ 00258 00259 n = (layered_flags & LAYERED_PERIODIC) ? 2 : 0; 00260 00261 prepare_comm(comm, data_parts, n); 00262 00263 if (n != 0) { 00264 /* two cells: from and to */ 00265 for(c = 0; c < n; c++) { 00266 comm->comm[c].part_lists = malloc(2*sizeof(ParticleList *)); 00267 comm->comm[c].n_part_lists = 2; 00268 comm->comm[c].mpi_comm = comm_cart; 00269 comm->comm[c].node = this_node; 00270 } 00271 00272 c = 0; 00273 00274 /* downwards */ 00275 comm->comm[c].type = GHOST_LOCL; 00276 if (data_parts == GHOSTTRANS_FORCE) { 00277 comm->comm[c].part_lists[0] = &cells[0]; 00278 comm->comm[c].part_lists[1] = &cells[n_layers]; 00279 } 00280 else { 00281 comm->comm[c].part_lists[0] = &cells[1]; 00282 comm->comm[c].part_lists[1] = &cells[n_layers + 1]; 00283 /* here it is periodic */ 00284 if (data_parts & GHOSTTRANS_POSITION) 00285 comm->data_parts |= GHOSTTRANS_POSSHFTD; 00286 comm->comm[c].shift[0] = comm->comm[c].shift[1] = 0; 00287 comm->comm[c].shift[2] = box_l[2]; 00288 } 00289 c++; 00290 00291 /* upwards */ 00292 comm->comm[c].type = GHOST_LOCL; 00293 if (data_parts == GHOSTTRANS_FORCE) { 00294 comm->comm[c].part_lists[0] = &cells[n_layers + 1]; 00295 comm->comm[c].part_lists[1] = &cells[1]; 00296 } 00297 else { 00298 comm->comm[c].part_lists[0] = &cells[n_layers]; 00299 comm->comm[c].part_lists[1] = &cells[0]; 00300 /* here it is periodic */ 00301 if (data_parts & GHOSTTRANS_POSITION) 00302 comm->data_parts |= GHOSTTRANS_POSSHFTD; 00303 comm->comm[c].shift[0] = comm->comm[c].shift[1] = 0; 00304 comm->comm[c].shift[2] = -box_l[2]; 00305 } 00306 } 00307 } 00308 } 00309 00310 void layered_topology_init(CellPList *old) 00311 { 00312 Particle *part; 00313 int c, p, np; 00314 00315 CELL_TRACE(fprintf(stderr, "%d: layered_topology_init, %d old particle lists\n", this_node, old->n)); 00316 00317 cell_structure.type = CELL_STRUCTURE_LAYERED; 00318 cell_structure.position_to_node = map_position_node_array; 00319 cell_structure.position_to_cell = layered_position_to_cell; 00320 00321 /* check node grid. All we can do is 1x1xn. */ 00322 if (node_grid[0] != 1 || node_grid[1] != 1) { 00323 char *errtxt = runtime_error(128 + ES_INTEGER_SPACE); 00324 ERROR_SPRINTF(errtxt, "{016 selected node grid is not suitable for layered cell structure (needs 1x1x%d grid)} ", n_nodes); 00325 node_grid[0] = node_grid[1] = 1; 00326 node_grid[2] = n_nodes; 00327 } 00328 00329 if (this_node == 0 && determine_n_layers) { 00330 if (max_range > 0) { 00331 n_layers = (int)floor(local_box_l[2]/max_range); 00332 if (n_layers < 1) { 00333 char *errtxt = runtime_error(128 + 2*ES_DOUBLE_SPACE); 00334 ERROR_SPRINTF(errtxt, "{017 layered: maximal interaction range %g larger than local box length %g} ", max_range, local_box_l[2]); 00335 n_layers = 1; 00336 } 00337 if (n_layers > max_num_cells - 2) 00338 n_layers = imax(max_num_cells - 2, 0); 00339 } 00340 else 00341 n_layers = 1; 00342 } 00343 MPI_Bcast(&n_layers, 1, MPI_INT, 0, comm_cart); 00344 00345 top = this_node + 1; 00346 if (top == n_nodes && (layered_flags & LAYERED_PERIODIC)) 00347 top = 0; 00348 btm = this_node - 1; 00349 if (btm == -1 && (layered_flags & LAYERED_PERIODIC)) 00350 btm = n_nodes - 1; 00351 00352 layer_h = local_box_l[2]/(double)(n_layers); 00353 layer_h_i = 1/layer_h; 00354 00355 if (layer_h < max_range) { 00356 char *errtxt = runtime_error(128 + 2*ES_DOUBLE_SPACE); 00357 ERROR_SPRINTF(errtxt, "{018 layered: maximal interaction range %g larger than layer height %g} ", max_range, layer_h); 00358 } 00359 00360 /* check wether node is top and/or bottom */ 00361 layered_flags = 0; 00362 if (this_node == 0) 00363 layered_flags |= LAYERED_BOTTOM; 00364 if (this_node == n_nodes - 1) 00365 layered_flags |= LAYERED_TOP; 00366 00367 if (PERIODIC(2)) 00368 layered_flags |= LAYERED_PERIODIC; 00369 00370 CELL_TRACE(fprintf(stderr, "%d: layered_flags tn %d bn %d \n", this_node, LAYERED_TOP_NEIGHBOR, LAYERED_BTM_NEIGHBOR)); 00371 00372 /* allocate cells and mark them */ 00373 realloc_cells(n_layers + 2); 00374 realloc_cellplist(&local_cells, local_cells.n = n_layers); 00375 for (c = 0; c < n_layers; c++) 00376 local_cells.cell[c] = &cells[c + 1]; 00377 realloc_cellplist(&ghost_cells, ghost_cells.n = 2); 00378 ghost_cells.cell[0] = &cells[0]; 00379 ghost_cells.cell[1] = &cells[n_layers + 1]; 00380 00381 /* create communicators */ 00382 layered_prepare_comm(&cell_structure.ghost_cells_comm, GHOSTTRANS_PARTNUM); 00383 layered_prepare_comm(&cell_structure.exchange_ghosts_comm, GHOSTTRANS_PROPRTS | GHOSTTRANS_POSITION); 00384 layered_prepare_comm(&cell_structure.update_ghost_pos_comm, GHOSTTRANS_POSITION); 00385 layered_prepare_comm(&cell_structure.collect_ghost_force_comm, GHOSTTRANS_FORCE); 00386 00387 /* copy particles */ 00388 for (c = 0; c < old->n; c++) { 00389 part = old->cell[c]->part; 00390 np = old->cell[c]->n; 00391 for (p = 0; p < np; p++) { 00392 Cell *nc = layered_position_to_cell(part[p].r.p); 00393 /* particle does not belong to this node. Just stow away 00394 somewhere for the moment */ 00395 if (nc == NULL) 00396 nc = local_cells.cell[0]; 00397 append_unindexed_particle(nc, &part[p]); 00398 } 00399 } 00400 for (c = 1; c <= n_layers; c++) 00401 update_local_particles(&cells[c]); 00402 00403 CELL_TRACE(fprintf(stderr, "%d: layered_topology_init done\n", this_node)); 00404 } 00405 00406 static void layered_append_particles(ParticleList *pl, ParticleList *up, ParticleList *dn) 00407 { 00408 int p; 00409 00410 CELL_TRACE(fprintf(stderr, "%d: sorting in %d\n", this_node, pl->n)); 00411 for(p = 0; p < pl->n; p++) { 00412 fold_position(pl->part[p].r.p, pl->part[p].l.i); 00413 if (LAYERED_BTM_NEIGHBOR && pl->part[p].r.p[2] < my_left[2]) { 00414 CELL_TRACE(fprintf(stderr, "%d: leaving part %d for node below\n", this_node, pl->part[p].p.identity)); 00415 move_indexed_particle(dn, pl, p); 00416 } 00417 else if (LAYERED_TOP_NEIGHBOR && pl->part[p].r.p[2] >= my_right[2]) { 00418 CELL_TRACE(fprintf(stderr, "%d: leaving part %d for node above\n", this_node, pl->part[p].p.identity)); 00419 move_indexed_particle(up, pl, p); 00420 } 00421 else 00422 move_indexed_particle(layered_position_to_cell(pl->part[p].r.p), pl, p); 00423 /* same particle again, as this is now a new one */ 00424 if (p < pl->n) p--; 00425 } 00426 CELL_TRACE(fprintf(stderr, "%d: left over %d\n", this_node, pl->n)); 00427 } 00428 00429 void layered_exchange_and_sort_particles(int global_flag) 00430 { 00431 Particle *part; 00432 Cell *nc, *oc; 00433 int c, p, flag, redo; 00434 ParticleList send_buf_dn, send_buf_up; 00435 ParticleList recv_buf; 00436 00437 CELL_TRACE(fprintf(stderr, "%d:layered exchange and sort %d\n", this_node, global_flag)); 00438 00439 init_particlelist(&send_buf_dn); 00440 init_particlelist(&send_buf_up); 00441 00442 init_particlelist(&recv_buf); 00443 00444 /* sort local particles */ 00445 for (c = 1; c <= n_layers; c++) { 00446 oc = &cells[c]; 00447 00448 for (p = 0; p < oc->n; p++) { 00449 part = &oc->part[p]; 00450 00451 if (n_nodes != 1 && LAYERED_BTM_NEIGHBOR && part->r.p[2] < my_left[2]) { 00452 CELL_TRACE(fprintf(stderr, "%d: send part %d down\n", this_node, part->p.identity)); 00453 move_indexed_particle(&send_buf_dn, oc, p); 00454 if (p < oc->n) p--; 00455 } 00456 else if (n_nodes != 1 && LAYERED_TOP_NEIGHBOR && part->r.p[2] >= my_right[2]) { 00457 CELL_TRACE(fprintf(stderr, "%d: send part %d up\n", this_node, part->p.identity)); 00458 move_indexed_particle(&send_buf_up, oc, p); 00459 if (p < oc->n) p--; 00460 } 00461 else { 00462 /* particle stays here. Fold anyways to get x,y correct */ 00463 fold_position(part->r.p, part->l.i); 00464 nc = layered_position_to_cell(part->r.p); 00465 if (nc != oc) { 00466 move_indexed_particle(nc, oc, p); 00467 if (p < oc->n) p--; 00468 } 00469 } 00470 } 00471 } 00472 00473 for (;;) { 00474 /* transfer */ 00475 if (n_nodes > 1) { 00476 if (this_node % 2 == 0) { 00477 /* send down */ 00478 if (LAYERED_BTM_NEIGHBOR) { 00479 CELL_TRACE(fprintf(stderr,"%d: send dn\n",this_node)); 00480 send_particles(&send_buf_dn, btm); 00481 } 00482 if (LAYERED_TOP_NEIGHBOR) { 00483 CELL_TRACE(fprintf(stderr,"%d: recv up\n",this_node)); 00484 recv_particles(&recv_buf, top); 00485 } 00486 /* send up */ 00487 if (LAYERED_TOP_NEIGHBOR) { 00488 CELL_TRACE(fprintf(stderr,"%d: send up\n",this_node)); 00489 send_particles(&send_buf_up, top); 00490 } 00491 if (LAYERED_BTM_NEIGHBOR) { 00492 CELL_TRACE(fprintf(stderr,"%d: recv dn\n",this_node)); 00493 recv_particles(&recv_buf, btm); 00494 } 00495 } 00496 else { 00497 if (LAYERED_TOP_NEIGHBOR) { 00498 CELL_TRACE(fprintf(stderr,"%d: recv up\n",this_node)); 00499 recv_particles(&recv_buf, top); 00500 } 00501 if (LAYERED_BTM_NEIGHBOR) { 00502 CELL_TRACE(fprintf(stderr,"%d: send dn\n",this_node)); 00503 send_particles(&send_buf_dn, btm); 00504 } 00505 if (LAYERED_BTM_NEIGHBOR) { 00506 CELL_TRACE(fprintf(stderr,"%d: recv dn\n",this_node)); 00507 recv_particles(&recv_buf, btm); 00508 } 00509 if (LAYERED_TOP_NEIGHBOR) { 00510 CELL_TRACE(fprintf(stderr,"%d: send up\n",this_node)); 00511 send_particles(&send_buf_up, top); 00512 } 00513 } 00514 } 00515 #ifdef ADDITIONAL_CHECKS 00516 else { 00517 if (recv_buf.n != 0 || send_buf_dn.n != 0 || send_buf_up.n != 0) { 00518 fprintf(stderr, "1 node but transfer buffers are not empty. send up %d, down %d, recv %d\n", 00519 send_buf_up.n, send_buf_dn.n, recv_buf.n); 00520 errexit(); 00521 } 00522 } 00523 #endif 00524 layered_append_particles(&recv_buf, &send_buf_up, &send_buf_dn); 00525 00526 /* handshake redo */ 00527 flag = (send_buf_up.n != 0 || send_buf_dn.n != 0); 00528 00529 CELL_TRACE(if (flag) fprintf(stderr, "%d: requesting another exchange round\n", this_node)); 00530 00531 if (global_flag == CELL_GLOBAL_EXCHANGE) { 00532 MPI_Allreduce(&flag, &redo, 1, MPI_INT, MPI_MAX, comm_cart); 00533 if (!redo) 00534 break; 00535 CELL_TRACE(fprintf(stderr, "%d: another exchange round\n", this_node)); 00536 } 00537 else { 00538 if (flag) { 00539 char *errtxt = runtime_error(128 + ES_DOUBLE_SPACE); 00540 ERROR_SPRINTF(errtxt,"{019 layered_exchange_and_sort_particles: particle moved more than one cell} "); 00541 00542 /* sort left over particles into border cells */ 00543 CELL_TRACE(fprintf(stderr, "%d: emergency sort\n", this_node)); 00544 while (send_buf_up.n > 0) 00545 move_indexed_particle(&cells[1], &send_buf_up, 0); 00546 while (send_buf_dn.n > 0) 00547 move_indexed_particle(&cells[n_layers], &send_buf_dn, 0); 00548 } 00549 break; 00550 } 00551 } 00552 00553 realloc_particlelist(&recv_buf, 0); 00554 } 00555 00556 /** nonbonded and bonded force calculation using the verlet list */ 00557 void layered_calculate_ia() 00558 { 00559 int c, i, j; 00560 Cell *celll, *cellb; 00561 int npl, npb; 00562 Particle *pl, *pb, *p1; 00563 double dist2, d[3]; 00564 00565 CELL_TRACE(fprintf(stderr, "%d: rebuild_v=%d\n", this_node, rebuild_verletlist)); 00566 00567 for (c = 1; c <= n_layers; c++) { 00568 celll = &cells[c]; 00569 pl = celll->part; 00570 npl = celll->n; 00571 00572 cellb = &cells[c-1]; 00573 pb = cellb->part; 00574 npb = cellb->n; 00575 00576 for(i = 0; i < npl; i++) { 00577 p1 = &pl[i]; 00578 00579 if (rebuild_verletlist) 00580 memcpy(p1->l.p_old, p1->r.p, 3*sizeof(double)); 00581 00582 add_bonded_force(p1); 00583 #ifdef CONSTRAINTS 00584 add_constraints_forces(p1); 00585 #endif 00586 00587 /* cell itself and bonded / constraints */ 00588 for(j = i+1; j < npl; j++) { 00589 layered_get_mi_vector(d, p1->r.p, pl[j].r.p); 00590 dist2 = sqrlen(d); 00591 #ifdef EXCLUSIONS 00592 if (do_nonbonded(p1, &pl[j])) 00593 #endif 00594 add_non_bonded_pair_force(p1, &pl[j], d, sqrt(dist2), dist2); 00595 } 00596 00597 /* bottom neighbor */ 00598 for(j = 0; j < npb; j++) { 00599 layered_get_mi_vector(d, p1->r.p, pb[j].r.p); 00600 dist2 = sqrlen(d); 00601 #ifdef EXCLUSIONS 00602 if (do_nonbonded(p1, &pb[j])) 00603 #endif 00604 add_non_bonded_pair_force(p1, &pb[j], d, sqrt(dist2), dist2); 00605 } 00606 } 00607 } 00608 rebuild_verletlist = 0; 00609 } 00610 00611 void layered_calculate_energies() 00612 { 00613 int c, i, j; 00614 Cell *celll, *cellb; 00615 int npl, npb; 00616 Particle *pl, *pb, *p1; 00617 double dist2, d[3]; 00618 00619 CELL_TRACE(fprintf(stderr, "%d: rebuild_v=%d\n", this_node, rebuild_verletlist)); 00620 00621 for (c = 1; c <= n_layers; c++) { 00622 celll = &cells[c]; 00623 pl = celll->part; 00624 npl = celll->n; 00625 00626 cellb = &cells[c-1]; 00627 pb = cellb->part; 00628 npb = cellb->n; 00629 00630 for(i = 0; i < npl; i++) { 00631 p1 = &pl[i]; 00632 00633 if (rebuild_verletlist) 00634 memcpy(p1->l.p_old, p1->r.p, 3*sizeof(double)); 00635 00636 add_kinetic_energy(p1); 00637 00638 add_bonded_energy(p1); 00639 #ifdef CONSTRAINTS 00640 add_constraints_energy(p1); 00641 #endif 00642 00643 /* cell itself and bonded / constraints */ 00644 for(j = i+1; j < npl; j++) { 00645 layered_get_mi_vector(d, p1->r.p, pl[j].r.p); 00646 dist2 = sqrlen(d); 00647 #ifdef EXCLUSIONS 00648 if (do_nonbonded(p1, &pl[j])) 00649 #endif 00650 add_non_bonded_pair_energy(p1, &pl[j], d, sqrt(dist2), dist2); 00651 } 00652 00653 /* bottom neighbor */ 00654 for(j = 0; j < npb; j++) { 00655 layered_get_mi_vector(d, p1->r.p, pb[j].r.p); 00656 dist2 = sqrlen(d); 00657 #ifdef EXCLUSIONS 00658 if (do_nonbonded(p1, &pb[j])) 00659 #endif 00660 add_non_bonded_pair_energy(p1, &pb[j], d, sqrt(dist2), dist2); 00661 } 00662 } 00663 } 00664 rebuild_verletlist = 0; 00665 } 00666 00667 void layered_calculate_virials(int v_comp) 00668 { 00669 int c, i, j; 00670 Cell *celll, *cellb; 00671 int npl, npb; 00672 Particle *pl, *pb, *p1; 00673 double dist2, d[3]; 00674 00675 for (c = 1; c <= n_layers; c++) { 00676 celll = &cells[c]; 00677 pl = celll->part; 00678 npl = celll->n; 00679 00680 cellb = &cells[c-1]; 00681 pb = cellb->part; 00682 npb = cellb->n; 00683 00684 for(i = 0; i < npl; i++) { 00685 p1 = &pl[i]; 00686 00687 if (rebuild_verletlist) 00688 memcpy(p1->l.p_old, p1->r.p, 3*sizeof(double)); 00689 00690 add_kinetic_virials(p1,v_comp); 00691 00692 add_bonded_virials(p1); 00693 #ifdef BOND_ANGLE_OLD 00694 add_three_body_bonded_stress(p1); 00695 #endif 00696 #ifdef BOND_ANGLE 00697 add_three_body_bonded_stress(p1); 00698 #endif 00699 00700 /* cell itself and bonded / constraints */ 00701 for(j = i+1; j < npl; j++) { 00702 layered_get_mi_vector(d, p1->r.p, pl[j].r.p); 00703 dist2 = sqrlen(d); 00704 #ifdef EXCLUSIONS 00705 if (do_nonbonded(p1, &pl[j])) 00706 #endif 00707 add_non_bonded_pair_virials(p1, &pl[j], d, sqrt(dist2), dist2); 00708 } 00709 00710 /* bottom neighbor */ 00711 for(j = 0; j < npb; j++) { 00712 layered_get_mi_vector(d, p1->r.p, pb[j].r.p); 00713 dist2 = sqrlen(d); 00714 #ifdef EXCLUSIONS 00715 if (do_nonbonded(p1, &pb[j])) 00716 #endif 00717 add_non_bonded_pair_virials(p1, &pb[j], d, sqrt(dist2), dist2); 00718 } 00719 } 00720 } 00721 rebuild_verletlist = 0; 00722 }
1.7.5.1