![]() |
ESPResSo 3.2.0-159-gf5c8922-git
Extensible Simulation Package for Soft Matter Research
|
00001 /* 00002 Copyright (C) 2010,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 cells.c 00022 * 00023 * This file contains functions for the cell system. 00024 * 00025 * For more information on cells, see cells.h 00026 * */ 00027 #include <stdio.h> 00028 #include <stdlib.h> 00029 #include <string.h> 00030 #include "utils.h" 00031 #include "cells.h" 00032 #include "grid.h" 00033 #include "particle_data.h" 00034 #include "interaction_data.h" 00035 #include "integrate.h" 00036 #include "initialize.h" 00037 #include "communication.h" 00038 #include "verlet.h" 00039 #include "ghosts.h" 00040 #include "domain_decomposition.h" 00041 #include "nsquare.h" 00042 #include "layered.h" 00043 00044 /* Variables */ 00045 00046 /** list of all cells. */ 00047 Cell *cells = NULL; 00048 /** size of \ref cells */ 00049 int n_cells = 0; 00050 /** list of pointers to all cells containing particles physically on the local node. */ 00051 CellPList local_cells = { NULL, 0, 0 }; 00052 /** list of pointers to all cells containing ghosts. */ 00053 CellPList ghost_cells = { NULL, 0, 0 }; 00054 00055 /** Type of cell structure in use */ 00056 CellStructure cell_structure = { CELL_STRUCTURE_NONEYET }; 00057 00058 double max_range = 0.0; 00059 00060 int rebuild_verletlist = 0; 00061 00062 /************************************************************/ 00063 /** \name Privat Functions */ 00064 /************************************************************/ 00065 /*@{*/ 00066 00067 #ifdef ADDITIONAL_CHECKS 00068 /** Extensive Debug function to check the consistency of the cells and 00069 the particles therein. Use with care! */ 00070 static void check_cells_consistency() 00071 { 00072 int c, index; 00073 IntList used; 00074 alloc_intlist(&used, n_cells); 00075 memset(used.e, 0, n_cells*sizeof(int)); 00076 00077 for (c = 0; c < local_cells.n; c++) { 00078 index = (void *)local_cells.cell[c] - (void *)cells; 00079 if ((index % sizeof(Cell)) != 0) { 00080 fprintf(stderr, "%d: local cell pointer not even aligned, certainly wrong (local_cell[%d], index=%d).\n", this_node, c, index); 00081 errexit(); 00082 } 00083 index /= sizeof(Cell); 00084 if (index < 0 || index >= n_cells) { 00085 fprintf(stderr, "%d: local cell pointer out of range, maybe old leftover (local_cell[%d]).\n", this_node, c); 00086 errexit(); 00087 } 00088 if (used.e[index]) { 00089 fprintf(stderr, "%d: local cell is already pointed to (local_cell[%d]).\n", this_node, c); 00090 errexit(); 00091 } 00092 used.e[index] = 1; 00093 } 00094 00095 for (c = 0; c < ghost_cells.n; c++) { 00096 index = (void *)ghost_cells.cell[c] - (void *)cells; 00097 if ((index % sizeof(Cell)) != 0) { 00098 fprintf(stderr, "%d: ghost cell pointer not even aligned, certainly wrong (ghost_cell[%d], index=%d).\n", this_node, c, index); 00099 errexit(); 00100 } 00101 index /= sizeof(Cell); 00102 if (index < 0 || index >= n_cells) { 00103 fprintf(stderr, "%d: ghost cell pointer out of range, maybe old leftover (ghost_cell[%d]).\n", this_node, c); 00104 errexit(); 00105 } 00106 if (used.e[index]) { 00107 fprintf(stderr, "%d: ghost cell is already pointed to (ghost_cell[%d]).\n", this_node, c); 00108 errexit(); 00109 } 00110 used.e[index] = 1; 00111 } 00112 for (c = 0; c < n_cells; c++) 00113 if (!used.e[c]) { 00114 fprintf(stderr, "%d: cell %d is not used anywhere.\n", this_node, c); 00115 errexit(); 00116 } 00117 realloc_intlist(&used, 0); 00118 } 00119 #endif 00120 00121 /** Switch for choosing the topology release function of a certain 00122 cell system. */ 00123 static void topology_release(int cs) { 00124 switch (cs) { 00125 case CELL_STRUCTURE_NONEYET: 00126 break; 00127 case CELL_STRUCTURE_CURRENT: 00128 topology_release(cell_structure.type); 00129 break; 00130 case CELL_STRUCTURE_DOMDEC: 00131 dd_topology_release(); 00132 break; 00133 case CELL_STRUCTURE_NSQUARE: 00134 nsq_topology_release(); 00135 break; 00136 case CELL_STRUCTURE_LAYERED: 00137 layered_topology_release(); 00138 break; 00139 default: 00140 fprintf(stderr, "INTERNAL ERROR: attempting to sort the particles in an unknown way (%d)\n", cs); 00141 errexit(); 00142 } 00143 } 00144 00145 /** Switch for choosing the topology init function of a certain 00146 cell system. */ 00147 static void topology_init(int cs, CellPList *local) { 00148 switch (cs) { 00149 case CELL_STRUCTURE_NONEYET: 00150 break; 00151 case CELL_STRUCTURE_CURRENT: 00152 topology_init(cell_structure.type, local); 00153 break; 00154 case CELL_STRUCTURE_DOMDEC: 00155 dd_topology_init(local); 00156 break; 00157 case CELL_STRUCTURE_NSQUARE: 00158 nsq_topology_init(local); 00159 break; 00160 case CELL_STRUCTURE_LAYERED: 00161 layered_topology_init(local); 00162 break; 00163 default: 00164 fprintf(stderr, "INTERNAL ERROR: attempting to sort the particles in an unknown way (%d)\n", cs); 00165 errexit(); 00166 } 00167 } 00168 00169 /*@}*/ 00170 00171 /************************************************************ 00172 * Exported Functions * 00173 ************************************************************/ 00174 00175 /************************************************************/ 00176 00177 void cells_re_init(int new_cs) 00178 { 00179 CellPList tmp_local; 00180 Cell *tmp_cells; 00181 int tmp_n_cells,i; 00182 00183 CELL_TRACE(fprintf(stderr, "%d: cells_re_init: convert type (%d->%d)\n", this_node, cell_structure.type, new_cs)); 00184 00185 invalidate_ghosts(); 00186 00187 /* 00188 CELL_TRACE({ 00189 int p; 00190 for (p = 0; p < n_total_particles; p++) 00191 if (local_particles[p]) 00192 fprintf(stderr, "%d: cells_re_init: got particle %d\n", this_node, p); 00193 } 00194 ); 00195 */ 00196 00197 topology_release(cell_structure.type); 00198 /* MOVE old local_cell list to temporary buffer */ 00199 memcpy(&tmp_local,&local_cells,sizeof(CellPList)); 00200 init_cellplist(&local_cells); 00201 00202 /* MOVE old cells to temporary buffer */ 00203 tmp_cells = cells; 00204 tmp_n_cells = n_cells; 00205 cells = NULL; 00206 n_cells = 0; 00207 00208 topology_init(new_cs, &tmp_local); 00209 00210 particle_invalidate_part_node(); 00211 00212 /* finally deallocate the old cells */ 00213 realloc_cellplist(&tmp_local,0); 00214 for(i=0;i<tmp_n_cells;i++) 00215 realloc_particlelist(&tmp_cells[i],0); 00216 00217 free(tmp_cells); 00218 CELL_TRACE(fprintf(stderr, "%d: old cells deallocated\n",this_node)); 00219 00220 /* 00221 CELL_TRACE({ 00222 int p; 00223 for (p = 0; p < n_total_particles; p++) 00224 if (local_particles[p]) 00225 fprintf(stderr, "%d: cells_re_init: now got particle %d\n", this_node, p); 00226 } 00227 ); 00228 */ 00229 00230 /* to enforce initialization of the ghost cells */ 00231 resort_particles = 1; 00232 00233 #ifdef ADDITIONAL_CHECKS 00234 check_cells_consistency(); 00235 #endif 00236 00237 on_cell_structure_change(); 00238 } 00239 00240 /************************************************************/ 00241 00242 void realloc_cells(int size) 00243 { 00244 int i; 00245 CELL_TRACE(fprintf(stderr, "%d: realloc_cells %d\n", this_node, size)); 00246 /* free all memory associated with cells to be deleted. */ 00247 for(i=size; i<n_cells; i++) { 00248 realloc_particlelist(&cells[i],0); 00249 } 00250 /* resize the cell list */ 00251 if(size != n_cells) { 00252 cells = (Cell *) realloc(cells, sizeof(Cell)*size); 00253 } 00254 /* initialize new cells */ 00255 for(i=n_cells; i<size; i++) { 00256 init_particlelist(&cells[i]); 00257 } 00258 n_cells = size; 00259 } 00260 00261 /*************************************************/ 00262 00263 void announce_resort_particles() 00264 { 00265 int sum; 00266 00267 MPI_Allreduce(&resort_particles, &sum, 1, MPI_INT, MPI_SUM, comm_cart); 00268 resort_particles = (sum > 0) ? 1 : 0; 00269 00270 INTEG_TRACE(fprintf(stderr,"%d: announce_resort_particles: resort_particles=%d\n", 00271 this_node, resort_particles)); 00272 } 00273 00274 /*************************************************/ 00275 00276 int cells_get_n_particles() 00277 { 00278 int c, cnt = 0; 00279 for (c = 0; c < local_cells.n; c++) 00280 cnt += local_cells.cell[c]->n; 00281 return cnt; 00282 } 00283 00284 /*************************************************/ 00285 00286 void print_local_particle_positions() 00287 { 00288 Cell *cell; 00289 int c,i,np,cnt=0; 00290 Particle *part; 00291 00292 for (c = 0; c < local_cells.n; c++) { 00293 cell = local_cells.cell[c]; 00294 part = cell->part; 00295 np = cell->n; 00296 for(i=0 ; i < np; i++) { 00297 fprintf(stderr,"%d: local cell %d contains part id=%d pos=(%f,%f,%f)\n", 00298 this_node, c, part[i].p.identity, 00299 part[i].r.p[0], part[i].r.p[1], part[i].r.p[2]); 00300 cnt++; 00301 } 00302 } 00303 fprintf(stderr,"%d: found %d particles\n",this_node,cnt); 00304 } 00305 00306 /*************************************************/ 00307 00308 void cells_resort_particles(int global_flag) 00309 { 00310 CELL_TRACE(fprintf(stderr, "%d: entering cells_resort_particles %d\n", this_node, global_flag)); 00311 00312 invalidate_ghosts(); 00313 00314 particle_invalidate_part_node(); 00315 n_verlet_updates++; 00316 00317 switch (cell_structure.type) { 00318 case CELL_STRUCTURE_LAYERED: 00319 layered_exchange_and_sort_particles(global_flag); 00320 break; 00321 case CELL_STRUCTURE_NSQUARE: 00322 nsq_balance_particles(global_flag); 00323 break; 00324 case CELL_STRUCTURE_DOMDEC: 00325 dd_exchange_and_sort_particles(global_flag); 00326 break; 00327 } 00328 00329 #ifdef ADDITIONAL_CHECKS 00330 /* at the end of the day, everything should be consistent again */ 00331 check_particle_consistency(); 00332 #endif 00333 00334 ghost_communicator(&cell_structure.ghost_cells_comm); 00335 ghost_communicator(&cell_structure.exchange_ghosts_comm); 00336 00337 resort_particles = 0; 00338 rebuild_verletlist = 1; 00339 00340 on_resort_particles(); 00341 00342 CELL_TRACE(fprintf(stderr, "%d: leaving cells_resort_particles\n", this_node)); 00343 } 00344 00345 /*************************************************/ 00346 00347 void cells_on_geometry_change(int flags) 00348 { 00349 if (max_cut > 0.0) { 00350 if (skin >= 0.0) 00351 max_range = max_cut + skin; 00352 else 00353 /* if the skin is not yet set, assume zero. */ 00354 max_range = max_cut; 00355 } 00356 else 00357 /* if no interactions yet, we also don't need a skin */ 00358 max_range = 0.0; 00359 00360 CELL_TRACE(fprintf(stderr,"%d: on_geometry_change with max range %f\n", this_node, max_range)); 00361 00362 switch (cell_structure.type) { 00363 case CELL_STRUCTURE_DOMDEC: 00364 dd_on_geometry_change(flags); 00365 break; 00366 case CELL_STRUCTURE_LAYERED: 00367 /* there is no fast version, always redo everything. */ 00368 cells_re_init(CELL_STRUCTURE_LAYERED); 00369 break; 00370 case CELL_STRUCTURE_NSQUARE: 00371 /* this cell system doesn't need to react, just tell 00372 the others */ 00373 on_boxl_change(); 00374 break; 00375 } 00376 } 00377 00378 /*************************************************/ 00379 00380 void check_resort_particles() 00381 { 00382 int i, c, np; 00383 Cell *cell; 00384 Particle *p; 00385 double skin2 = SQR(skin/2.0); 00386 00387 for (c = 0; c < local_cells.n; c++) { 00388 cell = local_cells.cell[c]; 00389 p = cell->part; 00390 np = cell->n; 00391 for(i = 0; i < np; i++) { 00392 /* Verlet criterion check */ 00393 if(distance2(p[i].r.p, p[i].l.p_old) > skin2) resort_particles = 1; 00394 } 00395 } 00396 announce_resort_particles(); 00397 } 00398 00399 /*************************************************/ 00400 void cells_update_ghosts() 00401 { 00402 /* if dd.use_vList is set, it so far means we want EXACT sorting of the particles.*/ 00403 if (dd.use_vList == 0) 00404 resort_particles = 1; 00405 00406 if (resort_particles) { 00407 /* Communication step: number of ghosts and ghost information */ 00408 cells_resort_particles(CELL_NEIGHBOR_EXCHANGE); 00409 } 00410 else 00411 /* Communication step: ghost information */ 00412 ghost_communicator(&cell_structure.update_ghost_pos_comm); 00413 } 00414 00415 /*************************************************/ 00416 00417 void print_ghost_positions() 00418 { 00419 Cell *cell; 00420 int c,i,np,cnt=0; 00421 Particle *part; 00422 00423 for (c = 0; c < ghost_cells.n; c++) { 00424 cell = ghost_cells.cell[c]; 00425 part = cell->part; 00426 np = cell->n; 00427 for(i=0 ; i < np; i++) { 00428 fprintf(stderr,"%d: local cell %d contains ghost id=%d pos=(%f,%f,%f)\n", 00429 this_node, c, part[i].p.identity, 00430 part[i].r.p[0], part[i].r.p[1], part[i].r.p[2]); 00431 cnt++; 00432 } 00433 } 00434 fprintf(stderr,"%d: found %d ghosts\n",this_node,cnt); 00435 }
1.7.5.1