ESPResSo 3.2.0-11-g9950804-git
Extensible Simulation Package for Soft Matter Research
verlet.c
Go to the documentation of this file.
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