void calculate_verlet_ia() { int c, np, n, i; Cell *cell; Particle *p1, *p2, **pairs; double dist2, vec21[3]; /* Loop local cells */ for (c = 0; c < local_cells.n; c++) { cell = local_cells.cell[c]; p1 = cell->part; np = cell->n; /* calculate bonded interactions (loop local particles) */ for(i = 0; i < np; i++) { add_bonded_force(&p1[i]); #ifdef CONSTRAINTS add_constraints_forces(&p1[i]); #endif add_external_potential_forces(&p1[i]); } /* Loop cell neighbors */ for (n = 0; n < dd.cell_inter[c].n_neighbors; n++) { pairs = dd.cell_inter[c].nList[n].vList.pair; np = dd.cell_inter[c].nList[n].vList.n; /* verlet list loop */ for(i=0; i<2*np; i+=2) { p1 = pairs[i]; /* pointer to particle 1 */ p2 = pairs[i+1]; /* pointer to particle 2 */ dist2 = distance2vec(p1->r.p, p2->r.p, vec21); add_non_bonded_pair_force(p1, p2, vec21, sqrt(dist2), dist2); } } } }
void build_verlet_lists_and_calc_verlet_ia() { int c, np1, n, np2, i ,j, j_start; Cell *cell; IA_Neighbor *neighbor; Particle *p1, *p2; PairList *pl; double dist2, vec21[3]; #ifdef VERLET_DEBUG int estimate, sum=0; double max_range_nonbonded2 = SQR(max_cut_nonbonded + skin); fprintf(stderr,"%d: build_verlet_list_and_calc_verlet_ia:\n",this_node); /* estimate number of interactions: (0.5*n_part*ia_volume*density)/n_nodes */ estimate = 0.5*n_part*(4.0/3.0*PI*pow(max_range_nonbonded2,1.5))*(n_part/(box_l[0]*box_l[1]*box_l[2]))/n_nodes; if (!dd.use_vList) { fprintf(stderr, "%d: build_verlet_lists, but use_vList == 0\n", this_node); errexit(); } #endif /* Loop local cells */ for (c = 0; c < local_cells.n; c++) { VERLET_TRACE(fprintf(stderr,"%d: cell %d with %d neighbors\n",this_node,c, dd.cell_inter[c].n_neighbors)); cell = local_cells.cell[c]; p1 = cell->part; np1 = cell->n; /* Loop cell neighbors */ for (n = 0; n < dd.cell_inter[c].n_neighbors; n++) { neighbor = &dd.cell_inter[c].nList[n]; p2 = neighbor->pList->part; np2 = neighbor->pList->n; VERLET_TRACE(fprintf(stderr,"%d: neighbor %d contains %d parts\n",this_node,n,np2)); /* init pair list */ pl = &neighbor->vList; pl->n = 0; /* Loop cell particles */ for(i=0; i < np1; i++) { j_start = 0; /* Tasks within cell: bonded forces, store old position, avoid double counting */ if(n == 0) { #ifdef MULTI_TIMESTEP if (p1[i].p.smaller_timestep==current_time_step_is_small || smaller_time_step < 0.) #endif { add_bonded_force(&p1[i]); #ifdef CONSTRAINTS add_constraints_forces(&p1[i]); #endif add_external_potential_forces(&p1[i]); memcpy(p1[i].l.p_old, p1[i].r.p, 3*sizeof(double)); j_start = i+1; } } /* no interaction set, no need for particle pairs */ if (max_cut_nonbonded == 0.0) continue; /* Loop neighbor cell particles */ for(j = j_start; j < np2; j++) { #ifdef EXCLUSIONS if(do_nonbonded(&p1[i], &p2[j])) #endif { dist2 = distance2vec(p1[i].r.p, p2[j].r.p, vec21); VERLET_TRACE(fprintf(stderr,"%d: pair %d %d has distance %f\n",this_node,p1[i].p.identity,p2[j].p.identity,sqrt(dist2))); if(dist2 <= SQR(get_ia_param(p1[i].p.type, p2[j].p.type)->max_cut + skin)) { 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))); 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))); add_pair(pl, &p1[i], &p2[j]); #ifdef MULTI_TIMESTEP if (smaller_time_step < 0. || (p1[i].p.smaller_timestep==0 && p2[j].p.smaller_timestep==0 && current_time_step_is_small==0) || (!(p1[i].p.smaller_timestep==0 && p2[j].p.smaller_timestep==0) && current_time_step_is_small==1)) #endif { /* calc non bonded interactions */ add_non_bonded_pair_force(&(p1[i]), &(p2[j]), vec21, sqrt(dist2), dist2); } } } } } resize_verlet_list(pl); VERLET_TRACE(fprintf(stderr,"%d: neighbor %d has %d pairs\n",this_node,n,pl->n)); VERLET_TRACE(sum += pl->n); }
// Detect a collision between the given particles. // Add it to the queue in case virtual sites should be added at the point of collision void detect_collision(Particle* p1, Particle* p2) { // The check, whether collision detection is actually turned on is performed in forces.h double dist_betw_part, vec21[3]; int part1, part2, size; // Obtain distance between particles dist_betw_part = distance2vec(p1->r.p, p2->r.p, vec21); if (dist_betw_part > collision_distance) return; part1 = p1->p.identity; part2 = p2->p.identity; // Retrieving the particles from local_particles is necessary, because the particle might be a // ghost, and those don't contain bonding info p1 = local_particles[part1]; p2 = local_particles[part2]; #ifdef VIRTUAL_SITES_RELATIVE // Ignore virtual particles if ((p1->p.isVirtual) || (p2->p.isVirtual)) return; #endif // Check, if there's already a bond between the particles // First check the bonds of p1 int i = 0; while(i < p1->bl.n) { size = bonded_ia_params[p1->bl.e[i]].num; if (p1->bl.e[i] == collision_detection_bond_centers && p1->bl.e[i + 1] == part2) { // There's a bond, already. Nothing to do for these particles return; } i += size + 1; } // Check, if a bond is already stored in p2 i = 0; while(i < p2->bl.n) { size = bonded_ia_params[p2->bl.e[i]].num; /* COMPARE P2 WITH P1'S BONDED PARTICLES*/ if (p2->bl.e[i] == collision_detection_bond_centers && p2->bl.e[i + 1] == part1) { return; } i += size + 1; } // If we're still here, there is no previous bond between the particles // Create the bond between the particles int bondG[2]; bondG[0]=collision_detection_bond_centers; bondG[1]=part2; local_change_bond(part1, bondG, 0); // If we also create virtual sites, we add the collision to the que to later add vs if (collision_detection_mode==2) { // Insert collision info into the queue // Point of collision double new_position[3]; for (i=0;i<3;i++) { new_position[i] =p1->r.p[i] - vec21[i] * 0.50; } number_of_collisions = number_of_collisions+1; // Allocate mem for the new collision info collision_queue = (collision_struct *) realloc (collision_queue, (number_of_collisions) * sizeof(collision_struct)); // Save the collision collision_queue[number_of_collisions-1].pp1 = part1; collision_queue[number_of_collisions-1].pp2 = part2; for (i=0;i<3;i++) { collision_queue[number_of_collisions-1].point_of_collision[i] = new_position[i]; } } }