![]() |
ESPResSo 3.2.0-11-g9950804-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 verlet.c Verlet list. 00022 * For more information see \ref verlet.h "verlet.h" 00023 */ 00024 #include <stdio.h> 00025 #include <stdlib.h> 00026 #include <string.h> 00027 #include "utils.h" 00028 #include "verlet.h" 00029 #include "cells.h" 00030 #include "integrate.h" 00031 #include "particle_data.h" 00032 #include "interaction_data.h" 00033 #include "communication.h" 00034 #include "grid.h" 00035 #include "forces.h" 00036 #include "energy.h" 00037 #include "pressure.h" 00038 #include "domain_decomposition.h" 00039 #include "constraint.h" 00040 00041 /** Granularity of the verlet list */ 00042 #define LIST_INCREMENT 20 00043 00044 /***************************************** 00045 * Variables 00046 *****************************************/ 00047 00048 /** \name Privat Functions */ 00049 /************************************************************/ 00050 /*@{*/ 00051 00052 /** Add a particle pair to a verlet pair list. 00053 Checks verlet pair list size and reallocates memory if necessary. 00054 * \param p1 Pointer to particle one. 00055 * \param p2 Pointer to particle two. 00056 * \param pl Pointer to the verlet pair list. 00057 */ 00058 MDINLINE void add_pair(PairList *pl, Particle *p1, Particle *p2) 00059 { 00060 /* check size of verlet List */ 00061 if(pl->n+1 >= pl->max) { 00062 pl->max += LIST_INCREMENT; 00063 pl->pair = (Particle **)realloc(pl->pair, 2*pl->max*sizeof(Particle *)); 00064 } 00065 /* add pair */ 00066 pl->pair[(2*pl->n) ] = p1; 00067 pl->pair[(2*pl->n)+1] = p2; 00068 /* increase number of pairs */ 00069 pl->n++; 00070 } 00071 00072 /** Resizes a verlet pair list according to the actual content (*vl).n. 00073 \param pl Pointer to the verlet pair list. */ 00074 void resize_verlet_list(PairList *pl); 00075 00076 /*@}*/ 00077 00078 /******************* exported functions *******************/ 00079 00080 void init_pairList(PairList *list) 00081 { 00082 list->n = 0; 00083 list->max = 0; 00084 list->pair = NULL; 00085 } 00086 00087 void free_pairList(PairList *list) 00088 { 00089 list->n = 0; 00090 list->max = 0; 00091 list->pair = (Particle **)realloc(list->pair, 0); 00092 } 00093 00094 void build_verlet_lists() 00095 { 00096 int c, np1, n, np2, i ,j, j_start; 00097 Cell *cell; 00098 IA_Neighbor *neighbor; 00099 Particle *p1, *p2; 00100 PairList *pl; 00101 double dist2; 00102 #ifdef VERLET_DEBUG 00103 double max_range_nonbonded2 = SQR(max_cut_nonbonded + skin); 00104 00105 int estimate, sum=0; 00106 fprintf(stderr,"%d: build_verlet_list_and_force_calc:\n",this_node); 00107 /* estimate number of interactions: (0.5*n_part*ia_volume*density)/n_nodes */ 00108 estimate = 0.5*n_total_particles*(4.0/3.0*PI*pow(max_range_nonbonded2,1.5))*(n_total_particles/(box_l[0]*box_l[1]*box_l[2]))/n_nodes; 00109 00110 if (!dd.use_vList) { fprintf(stderr, "%d: build_verlet_lists, but use_vList == 0\n", this_node); errexit(); } 00111 #endif 00112 00113 /* Loop local cells */ 00114 for (c = 0; c < local_cells.n; c++) { 00115 VERLET_TRACE(fprintf(stderr,"%d: cell %d with %d neighbors\n",this_node,c, dd.cell_inter[c].n_neighbors)); 00116 00117 cell = local_cells.cell[c]; 00118 p1 = cell->part; 00119 np1 = cell->n; 00120 /* Loop cell neighbors */ 00121 for (n = 0; n < dd.cell_inter[c].n_neighbors; n++) { 00122 neighbor = &dd.cell_inter[c].nList[n]; 00123 p2 = neighbor->pList->part; 00124 np2 = neighbor->pList->n; 00125 /* init pair list */ 00126 pl = &neighbor->vList; 00127 pl->n = 0; 00128 00129 /* no interaction set, Verlet list stays empty */ 00130 if (max_cut_nonbonded == 0.0) 00131 continue; 00132 00133 /* Loop cell particles */ 00134 for(i=0; i < np1; i++) { 00135 j_start = 0; 00136 /* Tasks within cell: store old position, avoid double counting */ 00137 if(n == 0) { 00138 memcpy(p1[i].l.p_old, p1[i].r.p, 3*sizeof(double)); 00139 j_start = i+1; 00140 } 00141 /* Loop neighbor cell particles */ 00142 for(j = j_start; j < np2; j++) { 00143 #ifdef EXCLUSIONS 00144 if(do_nonbonded(&p1[i], &p2[j])) 00145 #endif 00146 { 00147 dist2 = distance2(p1[i].r.p, p2[j].r.p); 00148 if(dist2 <= SQR(get_ia_param(p1[i].p.type, p2[j].p.type)->max_cut + skin)) 00149 add_pair(pl, &p1[i], &p2[j]); 00150 } 00151 } 00152 } 00153 resize_verlet_list(pl); 00154 VERLET_TRACE(fprintf(stderr,"%d: neighbor %d has %d particles\n",this_node,n,pl->n)); 00155 VERLET_TRACE(sum += pl->n); 00156 } 00157 } 00158 00159 rebuild_verletlist = 0; 00160 00161 VERLET_TRACE(fprintf(stderr,"%d: total number of interaction pairs: %d (should be around %d)\n",this_node,sum,estimate)); 00162 } 00163 00164 void calculate_verlet_ia() 00165 { 00166 int c, np, n, i; 00167 Cell *cell; 00168 Particle *p1, *p2, **pairs; 00169 double dist2, vec21[3]; 00170 00171 /* Loop local cells */ 00172 for (c = 0; c < local_cells.n; c++) { 00173 cell = local_cells.cell[c]; 00174 p1 = cell->part; 00175 np = cell->n; 00176 /* calculate bonded interactions (loop local particles) */ 00177 for(i = 0; i < np; i++) { 00178 add_bonded_force(&p1[i]); 00179 #ifdef CONSTRAINTS 00180 add_constraints_forces(&p1[i]); 00181 #endif 00182 } 00183 00184 /* Loop cell neighbors */ 00185 for (n = 0; n < dd.cell_inter[c].n_neighbors; n++) { 00186 pairs = dd.cell_inter[c].nList[n].vList.pair; 00187 np = dd.cell_inter[c].nList[n].vList.n; 00188 /* verlet list loop */ 00189 for(i=0; i<2*np; i+=2) { 00190 p1 = pairs[i]; /* pointer to particle 1 */ 00191 p2 = pairs[i+1]; /* pointer to particle 2 */ 00192 dist2 = distance2vec(p1->r.p, p2->r.p, vec21); 00193 add_non_bonded_pair_force(p1, p2, vec21, sqrt(dist2), dist2); 00194 } 00195 } 00196 } 00197 } 00198 00199 void build_verlet_lists_and_calc_verlet_ia() 00200 { 00201 int c, np1, n, np2, i ,j, j_start; 00202 Cell *cell; 00203 IA_Neighbor *neighbor; 00204 Particle *p1, *p2; 00205 PairList *pl; 00206 double dist2, vec21[3]; 00207 00208 #ifdef VERLET_DEBUG 00209 int estimate, sum=0; 00210 double max_range_nonbonded2 = SQR(max_cut_nonbonded + skin); 00211 00212 fprintf(stderr,"%d: build_verlet_list_and_calc_verlet_ia:\n",this_node); 00213 /* estimate number of interactions: (0.5*n_part*ia_volume*density)/n_nodes */ 00214 estimate = 0.5*n_total_particles*(4.0/3.0*PI*pow(max_range_nonbonded2,1.5))*(n_total_particles/(box_l[0]*box_l[1]*box_l[2]))/n_nodes; 00215 00216 if (!dd.use_vList) { fprintf(stderr, "%d: build_verlet_lists, but use_vList == 0\n", this_node); errexit(); } 00217 #endif 00218 00219 /* Loop local cells */ 00220 for (c = 0; c < local_cells.n; c++) { 00221 VERLET_TRACE(fprintf(stderr,"%d: cell %d with %d neighbors\n",this_node,c, dd.cell_inter[c].n_neighbors)); 00222 00223 cell = local_cells.cell[c]; 00224 p1 = cell->part; 00225 np1 = cell->n; 00226 00227 /* Loop cell neighbors */ 00228 for (n = 0; n < dd.cell_inter[c].n_neighbors; n++) { 00229 neighbor = &dd.cell_inter[c].nList[n]; 00230 p2 = neighbor->pList->part; 00231 np2 = neighbor->pList->n; 00232 VERLET_TRACE(fprintf(stderr,"%d: neighbor %d contains %d parts\n",this_node,n,np2)); 00233 /* init pair list */ 00234 pl = &neighbor->vList; 00235 pl->n = 0; 00236 /* Loop cell particles */ 00237 for(i=0; i < np1; i++) { 00238 j_start = 0; 00239 /* Tasks within cell: bonded forces, store old position, avoid double counting */ 00240 if(n == 0) { 00241 add_bonded_force(&p1[i]); 00242 #ifdef CONSTRAINTS 00243 add_constraints_forces(&p1[i]); 00244 #endif 00245 memcpy(p1[i].l.p_old, p1[i].r.p, 3*sizeof(double)); 00246 j_start = i+1; 00247 } 00248 00249 /* no interaction set, no need for particle pairs */ 00250 if (max_cut_nonbonded == 0.0) 00251 continue; 00252 00253 /* Loop neighbor cell particles */ 00254 for(j = j_start; j < np2; j++) { 00255 #ifdef EXCLUSIONS 00256 if(do_nonbonded(&p1[i], &p2[j])) 00257 #endif 00258 { 00259 dist2 = distance2vec(p1[i].r.p, p2[j].r.p, vec21); 00260 00261 VERLET_TRACE(fprintf(stderr,"%d: pair %d %d has distance %f\n",this_node,p1[i].p.identity,p2[j].p.identity,sqrt(dist2))); 00262 00263 if(dist2 <= SQR(get_ia_param(p1[i].p.type, p2[j].p.type)->max_cut + skin)) { 00264 ONEPART_TRACE(if(p1[i].p.identity==check_id) fprintf(stderr,"%d: OPT: Verlet Pair %d %d (Cells %d,%d %d,%d dist %f)\n",this_node,p1[i].p.identity,p2[j].p.identity,c,i,n,j,sqrt(dist2))); 00265 ONEPART_TRACE(if(p2[j].p.identity==check_id) fprintf(stderr,"%d: OPT: Verlet Pair %d %d (Cells %d %d dist %f)\n",this_node,p1[i].p.identity,p2[j].p.identity,c,n,sqrt(dist2))); 00266 00267 add_pair(pl, &p1[i], &p2[j]); 00268 /* calc non bonded interactions */ 00269 add_non_bonded_pair_force(&(p1[i]), &(p2[j]), vec21, sqrt(dist2), dist2); 00270 } 00271 } 00272 } 00273 } 00274 resize_verlet_list(pl); 00275 VERLET_TRACE(fprintf(stderr,"%d: neighbor %d has %d pairs\n",this_node,n,pl->n)); 00276 VERLET_TRACE(sum += pl->n); 00277 } 00278 } 00279 00280 VERLET_TRACE(fprintf(stderr,"%d: total number of interaction pairs: %d (should be around %d)\n",this_node,sum,estimate)); 00281 00282 rebuild_verletlist = 0; 00283 } 00284 00285 /************************************************************/ 00286 00287 void calculate_verlet_energies() 00288 { 00289 int c, np, n, i; 00290 Cell *cell; 00291 Particle *p1, *p2, **pairs; 00292 double dist2, vec21[3]; 00293 00294 VERLET_TRACE(fprintf(stderr,"%d: calculate verlet energies\n",this_node)); 00295 00296 /* Loop local cells */ 00297 for (c = 0; c < local_cells.n; c++) { 00298 cell = local_cells.cell[c]; 00299 p1 = cell->part; 00300 np = cell->n; 00301 /* calculate bonded interactions (loop local particles) */ 00302 for(i = 0; i < np; i++) { 00303 add_kinetic_energy(&p1[i]); 00304 add_bonded_energy(&p1[i]); 00305 #ifdef CONSTRAINTS 00306 add_constraints_energy(&p1[i]); 00307 #endif 00308 } 00309 00310 /* no interaction set */ 00311 if (max_cut_nonbonded == 0.0) 00312 continue; 00313 00314 VERLET_TRACE(fprintf(stderr,"%d: cell %d with %d neighbors\n",this_node,c, dd.cell_inter[c].n_neighbors)); 00315 /* Loop cell neighbors */ 00316 for (n = 0; n < dd.cell_inter[c].n_neighbors; n++) { 00317 pairs = dd.cell_inter[c].nList[n].vList.pair; 00318 np = dd.cell_inter[c].nList[n].vList.n; 00319 VERLET_TRACE(fprintf(stderr,"%d: neighbor %d has %d particles\n",this_node,n,np)); 00320 00321 /* verlet list loop */ 00322 for(i=0; i<2*np; i+=2) { 00323 p1 = pairs[i]; /* pointer to particle 1 */ 00324 p2 = pairs[i+1]; /* pointer to particle 2 */ 00325 dist2 = distance2vec(p1->r.p, p2->r.p, vec21); 00326 VERLET_TRACE(fprintf(stderr, "%d: %d <-> %d: dist2 dist2\n",this_node,p1->p.identity,p2->p.identity)); 00327 add_non_bonded_pair_energy(p1, p2, vec21, sqrt(dist2), dist2); 00328 } 00329 } 00330 } 00331 } 00332 00333 /************************************************************/ 00334 00335 void calculate_verlet_virials(int v_comp) 00336 { 00337 int c, np, n, i; 00338 Cell *cell; 00339 Particle *p1, *p2, **pairs; 00340 double dist2, vec21[3]; 00341 00342 VERLET_TRACE(fprintf(stderr,"%d: calculate verlet pressure\n",this_node)); 00343 00344 /* Loop local cells */ 00345 for (c = 0; c < local_cells.n; c++) { 00346 cell = local_cells.cell[c]; 00347 p1 = cell->part; 00348 np = cell->n; 00349 /* calculate bonded interactions (loop local particles) */ 00350 for(i = 0; i < np; i++) { 00351 add_kinetic_virials(&p1[i],v_comp); 00352 add_bonded_virials(&p1[i]); 00353 #ifdef BOND_ANGLE_OLD 00354 add_three_body_bonded_stress(&p1[i]); 00355 #endif 00356 #ifdef BOND_ANGLE 00357 add_three_body_bonded_stress(&p1[i]); 00358 #endif 00359 } 00360 00361 /* no interaction set */ 00362 if (max_cut_nonbonded == 0.0) 00363 continue; 00364 00365 VERLET_TRACE(fprintf(stderr,"%d: cell %d with %d neighbors\n",this_node,c, dd.cell_inter[c].n_neighbors)); 00366 /* Loop cell neighbors */ 00367 for (n = 0; n < dd.cell_inter[c].n_neighbors; n++) { 00368 pairs = dd.cell_inter[c].nList[n].vList.pair; 00369 np = dd.cell_inter[c].nList[n].vList.n; 00370 VERLET_TRACE(fprintf(stderr,"%d: neighbor %d has %d particles\n",this_node,n,np)); 00371 00372 /* verlet list loop */ 00373 for(i=0; i<2*np; i+=2) { 00374 p1 = pairs[i]; /* pointer to particle 1 */ 00375 p2 = pairs[i+1]; /* pointer to particle 2 */ 00376 dist2 = distance2vec(p1->r.p, p2->r.p, vec21); 00377 add_non_bonded_pair_virials(p1, p2, vec21, sqrt(dist2), dist2); 00378 } 00379 } 00380 } 00381 } 00382 00383 /************************************************************/ 00384 00385 void resize_verlet_list(PairList *pl) 00386 { 00387 int diff; 00388 diff = pl->max - pl->n; 00389 if( diff > 2*LIST_INCREMENT ) { 00390 diff = (diff/LIST_INCREMENT)-1; 00391 pl->max -= diff*LIST_INCREMENT; 00392 pl->pair = (Particle **)realloc(pl->pair, 2*pl->max*sizeof(Particle *)); 00393 } 00394 } 00395
1.7.5.1