double mindist(IntList *set1, IntList *set2) { double mindist, pt[3]; int i, j, in_set; mindist = SQR(box_l[0] + box_l[1] + box_l[2]); updatePartCfg(WITHOUT_BONDS); for (j=0; j<n_part-1; j++) { pt[0] = partCfg[j].r.p[0]; pt[1] = partCfg[j].r.p[1]; pt[2] = partCfg[j].r.p[2]; /* check which sets particle j belongs to bit 0: set1, bit1: set2 */ in_set = 0; if (!set1 || intlist_contains(set1, partCfg[j].p.type)) in_set = 1; if (!set2 || intlist_contains(set2, partCfg[j].p.type)) in_set |= 2; if (in_set == 0) continue; for (i=j+1; i<n_part; i++) /* accept a pair if particle j is in set1 and particle i in set2 or vice versa. */ if (((in_set & 1) && (!set2 || intlist_contains(set2, partCfg[i].p.type))) || ((in_set & 2) && (!set1 || intlist_contains(set1, partCfg[i].p.type)))) mindist = dmin(mindist, min_distance2(pt, partCfg[i].r.p)); } mindist = sqrt(mindist); return mindist; }
void calc_part_distribution(int *p1_types, int n_p1, int *p2_types, int n_p2, double r_min, double r_max, int r_bins, int log_flag, double *low, double *dist) { int i,j,t1,t2,ind,cnt=0; double inv_bin_width=0.0; double min_dist,min_dist2=0.0,start_dist2,act_dist2; start_dist2 = SQR(box_l[0] + box_l[1] + box_l[2]); /* bin preparation */ *low = 0.0; for(i=0;i<r_bins;i++) dist[i] = 0.0; if(log_flag == 1) inv_bin_width = (double)r_bins/(log(r_max)-log(r_min)); else inv_bin_width = (double)r_bins / (r_max-r_min); /* particle loop: p1_types*/ for(i=0; i<n_part; i++) { for(t1=0; t1<n_p1; t1++) { if(partCfg[i].p.type == p1_types[t1]) { min_dist2 = start_dist2; /* particle loop: p2_types*/ for(j=0; j<n_part; j++) { if(j != i) { for(t2=0; t2<n_p2; t2++) { if(partCfg[j].p.type == p2_types[t2]) { act_dist2 = min_distance2(partCfg[i].r.p, partCfg[j].r.p); if(act_dist2 < min_dist2) { min_dist2 = act_dist2; } } } } } min_dist = sqrt(min_dist2); if(min_dist <= r_max) { if(min_dist >= r_min) { /* calculate bin index */ if(log_flag == 1) ind = (int) ((log(min_dist) - log(r_min))*inv_bin_width); else ind = (int) ((min_dist - r_min)*inv_bin_width); if(ind >= 0 && ind < r_bins) { dist[ind] += 1.0; } } else { *low += 1.0; } } cnt++; } } } /* normalization */ *low /= (double)cnt; for(i=0;i<r_bins;i++) dist[i] /= (double)cnt; }
/** * updates the histogram */ void updateHistogram() { double max_distance2 = 2. * (L/2.) * (L/2.); double distance2; int historyIndex; #pragma omp parallel for for(int i=0; i<Nx*Ny; i++) { for(int j=0; j<i; j++) { // get the minimal distance distance2 = min_distance2(discs[i], discs[j]); // increment the histogram value that this corresponds to historyIndex = (distance2/max_distance2) * (M-1); assert(historyIndex < M && historyIndex >= 0); histogram[historyIndex]++; } } }
int aggregation(double dist_criteria2, int min_contact, int s_mol_id, int f_mol_id, int *head_list, int *link_list, int *agg_id_list, int *agg_num, int *agg_size, int *agg_max, int *agg_min, int *agg_avg, int *agg_std, int charge) { int c, np, n, i; Particle *p1, *p2, **pairs; double dist2; int target1; int p1molid, p2molid; int *contact_num, ind; if (min_contact > 1) { contact_num = (int *) malloc(n_molecules*n_molecules *sizeof(int)); for (i = 0; i < n_molecules *n_molecules; i++) contact_num[i]=0; } else { contact_num = (int *) 0; /* Just to keep the compiler happy */ } on_observable_calc(); build_verlet_lists(); for (i = s_mol_id; i <= f_mol_id; i++) { head_list[i]=i; link_list[i]=-1; agg_id_list[i]=i; agg_size[i]=0; } /* Loop local cells */ for (c = 0; c < local_cells.n; c++) { /* 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 */ p1molid = p1->p.mol_id; p2molid = p2->p.mol_id; if (((p1molid <= f_mol_id) && (p1molid >= s_mol_id)) && ((p2molid <= f_mol_id) && (p2molid >= s_mol_id))) { if (agg_id_list[p1molid] != agg_id_list[p2molid]) { dist2 = min_distance2(p1->r.p, p2->r.p); #ifdef ELECTROSTATICS if (charge && (p1->p.q * p2->p.q >= 0)) {continue;} #endif if (dist2 < dist_criteria2) { if ( p1molid > p2molid ) { ind=p1molid*n_molecules + p2molid;} else { ind=p2molid*n_molecules +p1molid;} if (min_contact > 1) { contact_num[ind] ++; if (contact_num[ind] >= min_contact) { merge_aggregate_lists( head_list, agg_id_list, p1molid, p2molid, link_list); } } else { merge_aggregate_lists( head_list, agg_id_list, p1molid, p2molid, link_list); } } } } } } } /* count number of aggregates find aggregate size find max and find min size, and std */ for (i = s_mol_id ; i <= f_mol_id ; i++) { if (head_list[i] != -2) { (*agg_num)++; agg_size[*agg_num -1]++; target1= head_list[i]; while( link_list[target1] != -1) { target1= link_list[target1]; agg_size[*agg_num -1]++; } } } for (i = 0 ; i < *agg_num; i++) { *agg_avg += agg_size[i]; *agg_std += agg_size[i] * agg_size[i]; if (*agg_min > agg_size[i]) { *agg_min = agg_size[i]; } if (*agg_max < agg_size[i]) { *agg_max = agg_size[i]; } } return 0; }
/** returns the minimal distance between two positions in the perhaps periodic simulation box. * \param pos1 Position one. * \param pos2 Position two. */ inline double min_distance(double pos1[3], double pos2[3]) { return sqrt(min_distance2(pos1, pos2)); }