![]() |
ESPResSo 3.2.0-11-g9950804-git
Extensible Simulation Package for Soft Matter Research
|
00001 /* 00002 Copyright (C) 2010,2011,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 statistics.c 00022 This is the place for analysis (so far...). 00023 Implementation of statistics.h 00024 */ 00025 #include <stdlib.h> 00026 #include <string.h> 00027 #include "utils.h" 00028 #include "statistics.h" 00029 #include "statistics_chain.h" 00030 #include "statistics_molecule.h" 00031 #include "statistics_cluster.h" 00032 #include "statistics_fluid.h" 00033 //#include "statistics_correlation.h" 00034 #include "energy.h" 00035 #include "modes.h" 00036 #include "pressure.h" 00037 #include "communication.h" 00038 #include "grid.h" 00039 #include "particle_data.h" 00040 #include "interaction_data.h" 00041 #include "domain_decomposition.h" 00042 #include "verlet.h" 00043 #include "lb.h" 00044 #include "virtual_sites.h" 00045 #include "initialize.h" 00046 00047 /** Previous particle configurations (needed for offline analysis and 00048 correlation analysis in \ref tclcommand_analyze) */ 00049 double **configs = NULL; int n_configs = 0; int n_part_conf = 0; 00050 00051 /**************************************************************************************** 00052 * helper functions 00053 ****************************************************************************************/ 00054 00055 double min_distance2(double pos1[3], double pos2[3]) 00056 { 00057 double diff[3]; 00058 get_mi_vector(diff, pos1, pos2); 00059 return sqrlen(diff); 00060 } 00061 00062 00063 /**************************************************************************************** 00064 * basic observables calculation 00065 ****************************************************************************************/ 00066 00067 double mindist(IntList *set1, IntList *set2) 00068 { 00069 double mindist, pt[3]; 00070 int i, j, in_set; 00071 00072 mindist = SQR(box_l[0] + box_l[1] + box_l[2]); 00073 00074 updatePartCfg(WITHOUT_BONDS); 00075 for (j=0; j<n_total_particles-1; j++) { 00076 pt[0] = partCfg[j].r.p[0]; 00077 pt[1] = partCfg[j].r.p[1]; 00078 pt[2] = partCfg[j].r.p[2]; 00079 /* check which sets particle j belongs to 00080 bit 0: set1, bit1: set2 00081 */ 00082 in_set = 0; 00083 if (!set1 || intlist_contains(set1, partCfg[j].p.type)) 00084 in_set = 1; 00085 if (!set2 || intlist_contains(set2, partCfg[j].p.type)) 00086 in_set |= 2; 00087 if (in_set == 0) 00088 continue; 00089 00090 for (i=j+1; i<n_total_particles; i++) 00091 /* accept a pair if particle j is in set1 and particle i in set2 or vice versa. */ 00092 if (((in_set & 1) && (!set2 || intlist_contains(set2, partCfg[i].p.type))) || 00093 ((in_set & 2) && (!set1 || intlist_contains(set1, partCfg[i].p.type)))) 00094 mindist = dmin(mindist, min_distance2(pt, partCfg[i].r.p)); 00095 } 00096 mindist = sqrt(mindist); 00097 return mindist; 00098 } 00099 00100 void merge_aggregate_lists(int *head_list, int *agg_id_list, int p1molid, int p2molid, int *link_list) 00101 { 00102 int target1, target2, head_p1; 00103 /* merge list containing p2molid into list containing p1molid*/ 00104 target1=head_list[agg_id_list[p2molid]]; 00105 head_list[agg_id_list[p2molid]]=-2; 00106 head_p1=head_list[agg_id_list[p1molid]]; 00107 head_list[agg_id_list[p1molid]]=target1; 00108 agg_id_list[target1]=agg_id_list[p1molid]; 00109 target2=link_list[target1]; 00110 while(target2 != -1) { 00111 target1=target2; 00112 target2=link_list[target1]; 00113 agg_id_list[target1]=agg_id_list[p1molid]; 00114 } 00115 agg_id_list[target1]=agg_id_list[p1molid]; 00116 link_list[target1]=head_p1; 00117 } 00118 00119 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) 00120 { 00121 int c, np, n, i; 00122 Particle *p1, *p2, **pairs; 00123 double dist2; 00124 int target1; 00125 int p1molid, p2molid; 00126 int *contact_num, ind; 00127 00128 if (min_contact > 1) { 00129 contact_num = (int *) malloc(n_molecules*n_molecules *sizeof(int)); 00130 for (i = 0; i < n_molecules *n_molecules; i++) contact_num[i]=0; 00131 } else { 00132 contact_num = (int *) 0; /* Just to keep the compiler happy */ 00133 } 00134 00135 on_observable_calc(); 00136 build_verlet_lists(); 00137 00138 for (i = s_mol_id; i <= f_mol_id; i++) { 00139 head_list[i]=i; 00140 link_list[i]=-1; 00141 agg_id_list[i]=i; 00142 agg_size[i]=0; 00143 } 00144 00145 /* Loop local cells */ 00146 for (c = 0; c < local_cells.n; c++) { 00147 /* Loop cell neighbors */ 00148 for (n = 0; n < dd.cell_inter[c].n_neighbors; n++) { 00149 pairs = dd.cell_inter[c].nList[n].vList.pair; 00150 np = dd.cell_inter[c].nList[n].vList.n; 00151 /* verlet list loop */ 00152 for(i=0; i<2*np; i+=2) { 00153 p1 = pairs[i]; /* pointer to particle 1 */ 00154 p2 = pairs[i+1]; /* pointer to particle 2 */ 00155 p1molid = p1->p.mol_id; 00156 p2molid = p2->p.mol_id; 00157 if (((p1molid <= f_mol_id) && (p1molid >= s_mol_id)) && ((p2molid <= f_mol_id) && (p2molid >= s_mol_id))) { 00158 if (agg_id_list[p1molid] != agg_id_list[p2molid]) { 00159 dist2 = min_distance2(p1->r.p, p2->r.p); 00160 00161 #ifdef ELECTROSTATICS 00162 if (charge && (p1->p.q * p2->p.q >= 0)) {continue;} 00163 #endif 00164 if (dist2 < dist_criteria2) { 00165 if ( p1molid > p2molid ) { ind=p1molid*n_molecules + p2molid;} 00166 else { ind=p2molid*n_molecules +p1molid;} 00167 if (min_contact > 1) { 00168 contact_num[ind] ++; 00169 if (contact_num[ind] >= min_contact) { 00170 merge_aggregate_lists( head_list, agg_id_list, p1molid, p2molid, link_list); 00171 } 00172 } else { 00173 merge_aggregate_lists( head_list, agg_id_list, p1molid, p2molid, link_list); 00174 } 00175 } 00176 } 00177 } 00178 } 00179 } 00180 } 00181 00182 /* count number of aggregates 00183 find aggregate size 00184 find max and find min size, and std */ 00185 for (i = s_mol_id ; i <= f_mol_id ; i++) { 00186 if (head_list[i] != -2) { 00187 (*agg_num)++; 00188 agg_size[*agg_num -1]++; 00189 target1= head_list[i]; 00190 while( link_list[target1] != -1) { 00191 target1= link_list[target1]; 00192 agg_size[*agg_num -1]++; 00193 } 00194 } 00195 } 00196 00197 for (i = 0 ; i < *agg_num; i++) { 00198 *agg_avg += agg_size[i]; 00199 *agg_std += agg_size[i] * agg_size[i]; 00200 if (*agg_min > agg_size[i]) { *agg_min = agg_size[i]; } 00201 if (*agg_max < agg_size[i]) { *agg_max = agg_size[i]; } 00202 } 00203 00204 return 0; 00205 } 00206 00207 /** Calculate momentum of all particles in the local domain 00208 * @param result Result for this processor (Output) 00209 */ 00210 void predict_momentum_particles(double *result) 00211 { 00212 Cell *cell; 00213 Particle *p; 00214 int i, c, np; 00215 00216 double momentum[3] = { 0.0, 0.0, 0.0 }; 00217 00218 for (c = 0; c < local_cells.n; c++) { 00219 cell = local_cells.cell[c]; 00220 np = cell->n; 00221 p = cell->part; 00222 00223 for(i=0; i < np; i++) { 00224 momentum[0] += p[i].m.v[0] + p[i].f.f[0]; 00225 momentum[1] += p[i].m.v[1] + p[i].f.f[1]; 00226 momentum[2] += p[i].m.v[2] + p[i].f.f[2]; 00227 } 00228 } 00229 00230 momentum[0] /= time_step; 00231 momentum[1] /= time_step; 00232 momentum[2] /= time_step; 00233 00234 MPI_Reduce(momentum, result, 3, MPI_DOUBLE, MPI_SUM, 0, comm_cart); 00235 } 00236 00237 /** Calculate total momentum of the system (particles & LB fluid) 00238 * @param momentum Rsult for this processor (Output) 00239 */ 00240 void momentum_calc(double *momentum) 00241 { 00242 double momentum_fluid[3] = { 0., 0., 0. }; 00243 double momentum_particles[3] = { 0., 0., 0. }; 00244 00245 mpi_gather_stats(4, momentum_particles, NULL, NULL, NULL); 00246 #ifdef LB 00247 mpi_gather_stats(6, momentum_fluid, NULL, NULL, NULL); 00248 #endif 00249 00250 momentum[0] = momentum_fluid[0] + momentum_particles[0]; 00251 momentum[1] = momentum_fluid[1] + momentum_particles[1]; 00252 momentum[2] = momentum_fluid[2] + momentum_particles[2]; 00253 00254 } 00255 00256 void centermass(int type, double *com) 00257 { 00258 int i, j; 00259 double M = 0.0; 00260 com[0]=com[1]=com[2]=0.; 00261 00262 updatePartCfg(WITHOUT_BONDS); 00263 for (j=0; j<n_total_particles; j++) { 00264 if ((partCfg[j].p.type == type) || (type == -1)) { 00265 for (i=0; i<3; i++) { 00266 com[i] += partCfg[j].r.p[i]*PMASS(partCfg[j]); 00267 } 00268 M += PMASS(partCfg[j]); 00269 } 00270 } 00271 00272 for (i=0; i<3; i++) { 00273 com[i] /= M; 00274 } 00275 return; 00276 } 00277 00278 void centermass_vel(int type, double *com) 00279 { 00280 /*center of mass velocity scaled with time_step*/ 00281 int i, j; 00282 int count = 0; 00283 com[0]=com[1]=com[2]=0.; 00284 00285 updatePartCfg(WITHOUT_BONDS); 00286 for (j=0; j<n_total_particles; j++) { 00287 if (type == partCfg[j].p.type) { 00288 for (i=0; i<3; i++) { 00289 com[i] += partCfg[j].m.v[i]; 00290 } 00291 count++; 00292 } 00293 } 00294 00295 for (i=0; i<3; i++) { 00296 com[i] /= count; 00297 } 00298 return; 00299 } 00300 00301 void angularmomentum(int type, double *com) 00302 { 00303 int i, j; 00304 double tmp[3]; 00305 double pre_factor; 00306 com[0]=com[1]=com[2]=0.; 00307 00308 updatePartCfg(WITHOUT_BONDS); 00309 for (j=0; j<n_total_particles; j++) 00310 { 00311 if (type == partCfg[j].p.type) 00312 { 00313 vector_product(partCfg[j].r.p,partCfg[j].m.v,tmp); 00314 pre_factor=PMASS(partCfg[j]); 00315 for (i=0; i<3; i++) { 00316 com[i] += tmp[i]*pre_factor; 00317 } 00318 } 00319 } 00320 return; 00321 } 00322 00323 void momentofinertiamatrix(int type, double *MofImatrix) 00324 { 00325 int i,j,count; 00326 double p1[3],com[3],massi; 00327 00328 count=0; 00329 updatePartCfg(WITHOUT_BONDS); 00330 for(i=0;i<9;i++) MofImatrix[i]=0.; 00331 centermass(type, com); 00332 for (j=0; j<n_total_particles; j++) { 00333 if (type == partCfg[j].p.type) { 00334 count ++; 00335 for (i=0; i<3; i++) { 00336 p1[i] = partCfg[j].r.p[i] - com[i]; 00337 } 00338 massi= PMASS(partCfg[j]); 00339 MofImatrix[0] += massi * (p1[1] * p1[1] + p1[2] * p1[2]) ; 00340 MofImatrix[4] += massi * (p1[0] * p1[0] + p1[2] * p1[2]); 00341 MofImatrix[8] += massi * (p1[0] * p1[0] + p1[1] * p1[1]); 00342 MofImatrix[1] -= massi * (p1[0] * p1[1]); 00343 MofImatrix[2] -= massi * (p1[0] * p1[2]); 00344 MofImatrix[5] -= massi * (p1[1] * p1[2]); 00345 } 00346 } 00347 /* use symmetry */ 00348 MofImatrix[3] = MofImatrix[1]; 00349 MofImatrix[6] = MofImatrix[2]; 00350 MofImatrix[7] = MofImatrix[5]; 00351 return; 00352 } 00353 00354 void calc_gyration_tensor(int type, double **_gt) 00355 { 00356 int i, j, count; 00357 double com[3]; 00358 double eva[3],eve0[3],eve1[3],eve2[3]; 00359 double *gt=NULL, tmp; 00360 double Smatrix[9],p1[3]; 00361 00362 for (i=0; i<9; i++) Smatrix[i] = 0; 00363 *_gt = gt = realloc(gt,16*sizeof(double)); /* 3*ev, rg, b, c, kappa, eve0[3], eve1[3], eve2[3]*/ 00364 00365 updatePartCfg(WITHOUT_BONDS); 00366 00367 /* Calculate the position of COM */ 00368 centermass(type,com); 00369 00370 /* Calculate the gyration tensor Smatrix */ 00371 count=0; 00372 for (i=0;i<n_total_particles;i++) { 00373 if ((partCfg[i].p.type == type) || (type == -1)) { 00374 for ( j=0; j<3 ; j++ ) { 00375 p1[j] = partCfg[i].r.p[j] - com[j]; 00376 } 00377 count ++; 00378 Smatrix[0] += p1[0]*p1[0]; 00379 Smatrix[1] += p1[0]*p1[1]; 00380 Smatrix[2] += p1[0]*p1[2]; 00381 Smatrix[4] += p1[1]*p1[1]; 00382 Smatrix[5] += p1[1]*p1[2]; 00383 Smatrix[8] += p1[2]*p1[2]; 00384 } 00385 } 00386 /* use symmetry */ 00387 Smatrix[3]=Smatrix[1]; 00388 Smatrix[6]=Smatrix[2]; 00389 Smatrix[7]=Smatrix[5]; 00390 for (i=0;i<9;i++){ 00391 Smatrix[i] /= count; 00392 } 00393 00394 /* Calculate the eigenvalues of Smatrix */ 00395 i=calc_eigenvalues_3x3(Smatrix, eva); 00396 tmp=0.0; 00397 for (i=0;i<3;i++) { 00398 /* Eigenvalues */ 00399 gt[i] = eva[i]; 00400 tmp += eva[i]; 00401 } 00402 00403 i=calc_eigenvector_3x3(Smatrix,eva[0],eve0); 00404 i=calc_eigenvector_3x3(Smatrix,eva[1],eve1); 00405 i=calc_eigenvector_3x3(Smatrix,eva[2],eve2); 00406 gt[3] = tmp; /* Squared Radius of Gyration */ 00407 gt[4] = eva[0]-0.5*(eva[1]+eva[2]); /* Asphericity */ 00408 gt[5] = eva[1]-eva[2]; /* Acylindricity */ 00409 gt[6] = (gt[4]*gt[4]+0.75*gt[5]*gt[5])/(gt[3]*gt[3]); /* Relative shape anisotropy */ 00410 /* Eigenvectors */ 00411 for (j=0;j<3;j++) { 00412 gt[7+j]=eve0[j]; 00413 gt[10+j]=eve1[j]; 00414 gt[13+j]=eve2[j]; 00415 } 00416 } 00417 00418 00419 void nbhood(double pt[3], double r, IntList *il, int planedims[3] ) 00420 { 00421 double d[3]; 00422 int i,j; 00423 double r2; 00424 00425 r2 = r*r; 00426 00427 init_intlist(il); 00428 00429 updatePartCfg(WITHOUT_BONDS); 00430 00431 for (i = 0; i<n_total_particles; i++) { 00432 if ( (planedims[0] + planedims[1] + planedims[2]) == 3 ) { 00433 get_mi_vector(d, pt, partCfg[i].r.p); 00434 } else { 00435 /* Calculate the in plane distance */ 00436 for ( j= 0 ; j < 3 ; j++ ) { 00437 d[j] = planedims[j]*(partCfg[i].r.p[j]-pt[j]); 00438 } 00439 } 00440 00441 if (sqrlen(d) < r2) { 00442 realloc_intlist(il, il->n + 1); 00443 il->e[il->n] = partCfg[i].p.identity; 00444 il->n++; 00445 } 00446 } 00447 } 00448 00449 double distto(double p[3], int pid) 00450 { 00451 int i; 00452 double d[3]; 00453 double mindist; 00454 00455 updatePartCfg(WITHOUT_BONDS); 00456 00457 /* larger than possible */ 00458 mindist=SQR(box_l[0] + box_l[1] + box_l[2]); 00459 for (i=0; i<n_total_particles; i++) { 00460 if (pid != partCfg[i].p.identity) { 00461 get_mi_vector(d, p, partCfg[i].r.p); 00462 mindist = dmin(mindist, sqrlen(d)); 00463 } 00464 } 00465 return sqrt(mindist); 00466 } 00467 00468 void calc_cell_gpb(double xi_m, double Rc, double ro, double gacc, int maxtry, double *result) { 00469 double LOG,xi_min, RM, gamma,g1,g2,gmid=0,dg,ig, f,fmid, rtb; 00470 int i; 00471 LOG = log(Rc/ro); 00472 xi_min = LOG/(1+LOG); 00473 if(maxtry < 1) maxtry = 1; 00474 00475 /* determine which of the regimes we are in: */ 00476 if(xi_m > 1) { 00477 ig = 1.0; 00478 g1 = PI / LOG; 00479 g2 = PI / (LOG + xi_m/(xi_m-1.0)); } 00480 else if(xi_m == 1) { 00481 ig = 1.0; 00482 g1 = (PI/2.0) / LOG; 00483 g2 = (PI/2.0) / (LOG + 1.0); } 00484 else if(xi_m == xi_min) { 00485 ig = 1.0; 00486 g1 = g2 = 0.0; } 00487 else if(xi_m > xi_min) { 00488 ig = 1.0; 00489 g1 = (PI/2.0) / LOG; 00490 g2 = sqrt(3.0*(LOG-xi_m/(1.0-xi_m))/(1-pow((1.0-xi_m),-3.0))); } 00491 else if(xi_m > 0.0) { 00492 ig = -1.0; 00493 g1 = 1-xi_m; 00494 g2 = xi_m*(6.0-(3.0-xi_m)*xi_m)/(3.0*LOG); } 00495 else if(xi_m == 0.0) { 00496 ig = -1.0; 00497 g1 = g2 = 1-xi_m; } 00498 else { 00499 result[2]=-5.0; return; 00500 } 00501 00502 /* decide which method to use (if any): */ 00503 if(xi_m == xi_min) { 00504 gamma = 0.0; 00505 RM = 0.0; } 00506 else if(xi_m == 0.0) { 00507 gamma = 1-xi_m; 00508 RM = -1.0; } 00509 else if(ig == 1.0) { 00510 /* determine gamma via a bisection-search: */ 00511 f = atan(1.0/g1) + atan( (xi_m-1.0) / g1 ) - g1 * LOG; 00512 fmid = atan(1.0/g2) + atan( (xi_m-1.0) / g2 ) - g2 * LOG; 00513 if (f*fmid >= 0.0) { 00514 /* failed to bracket function value with intial guess - abort: */ 00515 result[0]=f; result[1]=fmid; result[2]=-3.0; return; } 00516 00517 /* orient search such that the positive part of the function lies to the right of the zero */ 00518 rtb = f < 0.0 ? (dg=g2-g1,g1) : (dg=g1-g2,g2); 00519 for (i = 1; i <= maxtry; i++) { 00520 gmid = rtb + (dg *= 0.5); 00521 fmid = atan(1.0/gmid) + atan((xi_m-1.0)/gmid) - gmid*LOG; 00522 if (fmid <= 0.0) rtb = gmid; 00523 if (fabs(dg) < gacc || fmid == 0.0) break; 00524 } 00525 00526 if (fabs(dg) > gacc) { 00527 /* too many iterations without success - abort: */ 00528 result[0]=gmid; result[1]=dg; result[2]=-2.0; return; } 00529 00530 /* So, these are the values for gamma and Manning-radius: */ 00531 gamma = gmid; 00532 RM = Rc * exp( -(1.0/gamma) * atan(1.0/gamma) ); } 00533 else if(ig == -1.0) { 00534 /* determine -i*gamma: */ 00535 f = -1.0*(atanh(g2) + atanh(g2/(xi_m-1))) - g2*LOG; 00536 00537 /* modified orient search, this time starting from the upper bound backwards: */ 00538 if (f < 0.0) { 00539 rtb = g1; dg = g1-g2; } 00540 else { 00541 fprintf(stderr,"WARNING: Lower boundary is actually larger than l.h.s, flipping!\n"); 00542 rtb = g1; dg = g1; } 00543 for (i = 1; i <= maxtry; i++) { 00544 gmid = rtb - (dg *= 0.5); 00545 fmid = -1.0*(atanh(gmid) + atanh(gmid/(xi_m-1))) - gmid*LOG; 00546 if (fmid >= 0.0) rtb = gmid; 00547 if (fabs(dg) < gacc || fmid == 0.0) break; 00548 } 00549 00550 if (fabs(dg) > gacc) { 00551 /* too many iterations without success - abort: */ 00552 result[0]=gmid; result[1]=dg; result[2]=-2.0; return; } 00553 00554 /* So, these are the values for -i*gamma and Manning-radius: */ 00555 gamma = gmid; 00556 RM = Rc * exp( atan(1.0/gamma)/gamma ); } 00557 else { 00558 result[2]=-5.0; return; 00559 } 00560 00561 result[0]=gamma; 00562 result[1]=RM; 00563 result[2]=ig; 00564 return; 00565 } 00566 00567 void calc_part_distribution(int *p1_types, int n_p1, int *p2_types, int n_p2, 00568 double r_min, double r_max, int r_bins, int log_flag, 00569 double *low, double *dist) 00570 { 00571 int i,j,t1,t2,ind,cnt=0; 00572 double inv_bin_width=0.0; 00573 double min_dist,min_dist2=0.0,start_dist2,act_dist2; 00574 00575 start_dist2 = SQR(box_l[0] + box_l[1] + box_l[2]); 00576 /* bin preparation */ 00577 *low = 0.0; 00578 for(i=0;i<r_bins;i++) dist[i] = 0.0; 00579 if(log_flag == 1) inv_bin_width = (double)r_bins/(log(r_max)-log(r_min)); 00580 else inv_bin_width = (double)r_bins / (r_max-r_min); 00581 00582 /* particle loop: p1_types*/ 00583 for(i=0; i<n_total_particles; i++) { 00584 for(t1=0; t1<n_p1; t1++) { 00585 if(partCfg[i].p.type == p1_types[t1]) { 00586 min_dist2 = start_dist2; 00587 /* particle loop: p2_types*/ 00588 for(j=0; j<n_total_particles; j++) { 00589 if(j != i) { 00590 for(t2=0; t2<n_p2; t2++) { 00591 if(partCfg[j].p.type == p2_types[t2]) { 00592 act_dist2 = min_distance2(partCfg[i].r.p, partCfg[j].r.p); 00593 if(act_dist2 < min_dist2) { min_dist2 = act_dist2; } 00594 } 00595 } 00596 } 00597 } 00598 min_dist = sqrt(min_dist2); 00599 if(min_dist <= r_max) { 00600 if(min_dist >= r_min) { 00601 /* calculate bin index */ 00602 if(log_flag == 1) ind = (int) ((log(min_dist) - log(r_min))*inv_bin_width); 00603 else ind = (int) ((min_dist - r_min)*inv_bin_width); 00604 if(ind >= 0 && ind < r_bins) { 00605 dist[ind] += 1.0; 00606 } 00607 } 00608 else { 00609 *low += 1.0; 00610 } 00611 } 00612 cnt++; 00613 } 00614 } 00615 } 00616 00617 /* normalization */ 00618 *low /= (double)cnt; 00619 for(i=0;i<r_bins;i++) dist[i] /= (double)cnt; 00620 } 00621 00622 00623 void calc_rdf(int *p1_types, int n_p1, int *p2_types, int n_p2, 00624 double r_min, double r_max, int r_bins, double *rdf) 00625 { 00626 long int cnt=0; 00627 int i,j,t1,t2,ind; 00628 int mixed_flag=0,start; 00629 double inv_bin_width=0.0,bin_width=0.0, dist; 00630 double volume, bin_volume, r_in, r_out; 00631 00632 if(n_p1 == n_p2) { 00633 for(i=0;i<n_p1;i++) 00634 if( p1_types[i] != p2_types[i] ) mixed_flag=1; 00635 } 00636 else mixed_flag=1; 00637 00638 bin_width = (r_max-r_min) / (double)r_bins; 00639 inv_bin_width = 1.0 / bin_width; 00640 for(i=0;i<r_bins;i++) rdf[i] = 0.0; 00641 /* particle loop: p1_types*/ 00642 for(i=0; i<n_total_particles; i++) { 00643 for(t1=0; t1<n_p1; t1++) { 00644 if(partCfg[i].p.type == p1_types[t1]) { 00645 /* distinguish mixed and identical rdf's */ 00646 if(mixed_flag == 1) start = 0; 00647 else start = (i+1); 00648 /* particle loop: p2_types*/ 00649 for(j=start; j<n_total_particles; j++) { 00650 for(t2=0; t2<n_p2; t2++) { 00651 if(partCfg[j].p.type == p2_types[t2]) { 00652 dist = min_distance(partCfg[i].r.p, partCfg[j].r.p); 00653 if(dist > r_min && dist < r_max) { 00654 ind = (int) ( (dist - r_min)*inv_bin_width ); 00655 rdf[ind]++; 00656 } 00657 cnt++; 00658 } 00659 } 00660 } 00661 } 00662 } 00663 } 00664 00665 /* normalization */ 00666 volume = box_l[0]*box_l[1]*box_l[2]; 00667 for(i=0; i<r_bins; i++) { 00668 r_in = i*bin_width + r_min; 00669 r_out = r_in + bin_width; 00670 bin_volume = (4.0/3.0) * PI * ((r_out*r_out*r_out) - (r_in*r_in*r_in)); 00671 rdf[i] *= volume / (bin_volume * cnt); 00672 } 00673 } 00674 00675 void calc_rdf_av(int *p1_types, int n_p1, int *p2_types, int n_p2, 00676 double r_min, double r_max, int r_bins, double *rdf, int n_conf) 00677 { 00678 long int cnt=0; 00679 int i,j,k,l,t1,t2,ind,cnt_conf=1; 00680 int mixed_flag=0,start; 00681 double inv_bin_width=0.0,bin_width=0.0, dist; 00682 double volume, bin_volume, r_in, r_out; 00683 double *rdf_tmp, p1[3],p2[3]; 00684 00685 rdf_tmp = malloc(r_bins*sizeof(double)); 00686 00687 if(n_p1 == n_p2) { 00688 for(i=0;i<n_p1;i++) 00689 if( p1_types[i] != p2_types[i] ) mixed_flag=1; 00690 } 00691 else mixed_flag=1; 00692 bin_width = (r_max-r_min) / (double)r_bins; 00693 inv_bin_width = 1.0 / bin_width; 00694 volume = box_l[0]*box_l[1]*box_l[2]; 00695 for(l=0;l<r_bins;l++) rdf_tmp[l]=rdf[l] = 0.0; 00696 00697 while(cnt_conf<=n_conf) { 00698 for(l=0;l<r_bins;l++) rdf_tmp[l]=0.0; 00699 cnt=0; 00700 k=n_configs-cnt_conf; 00701 for(i=0; i<n_total_particles; i++) { 00702 for(t1=0; t1<n_p1; t1++) { 00703 if(partCfg[i].p.type == p1_types[t1]) { 00704 // distinguish mixed and identical rdf's 00705 if(mixed_flag == 1) start = 0; 00706 else start = (i+1); 00707 //particle loop: p2_types 00708 for(j=start; j<n_total_particles; j++) { 00709 for(t2=0; t2<n_p2; t2++) { 00710 if(partCfg[j].p.type == p2_types[t2]) { 00711 p1[0]=configs[k][3*i ];p1[1]=configs[k][3*i+1];p1[2]=configs[k][3*i+2]; 00712 p2[0]=configs[k][3*j ];p2[1]=configs[k][3*j+1];p2[2]=configs[k][3*j+2]; 00713 dist =min_distance(p1, p2); 00714 if(dist > r_min && dist < r_max) { 00715 ind = (int) ( (dist - r_min)*inv_bin_width ); 00716 rdf_tmp[ind]++; 00717 } 00718 cnt++; 00719 } 00720 } 00721 } 00722 } 00723 } 00724 } 00725 // normalization 00726 00727 for(i=0; i<r_bins; i++) { 00728 r_in = i*bin_width + r_min; 00729 r_out = r_in + bin_width; 00730 bin_volume = (4.0/3.0) * PI * ((r_out*r_out*r_out) - (r_in*r_in*r_in)); 00731 rdf[i] += rdf_tmp[i]*volume / (bin_volume * cnt); 00732 } 00733 00734 cnt_conf++; 00735 } //cnt_conf loop 00736 for(i=0; i<r_bins; i++) { 00737 rdf[i] /= (cnt_conf-1); 00738 } 00739 free(rdf_tmp); 00740 00741 } 00742 00743 void calc_rdf_intermol_av(int *p1_types, int n_p1, int *p2_types, int n_p2, 00744 double r_min, double r_max, int r_bins, double *rdf, int n_conf) 00745 { 00746 int i,j,k,l,t1,t2,ind,cnt=0,cnt_conf=1; 00747 int mixed_flag=0,start; 00748 double inv_bin_width=0.0,bin_width=0.0, dist; 00749 double volume, bin_volume, r_in, r_out; 00750 double *rdf_tmp, p1[3],p2[3]; 00751 00752 rdf_tmp = malloc(r_bins*sizeof(double)); 00753 00754 if(n_p1 == n_p2) { 00755 for(i=0;i<n_p1;i++) 00756 if( p1_types[i] != p2_types[i] ) mixed_flag=1; 00757 } 00758 else mixed_flag=1; 00759 bin_width = (r_max-r_min) / (double)r_bins; 00760 inv_bin_width = 1.0 / bin_width; 00761 volume = box_l[0]*box_l[1]*box_l[2]; 00762 for(l=0;l<r_bins;l++) rdf_tmp[l]=rdf[l] = 0.0; 00763 00764 while(cnt_conf<=n_conf) { 00765 for(l=0;l<r_bins;l++) rdf_tmp[l]=0.0; 00766 cnt=0; 00767 k=n_configs-cnt_conf; 00768 for(i=0; i<n_total_particles; i++) { 00769 for(t1=0; t1<n_p1; t1++) { 00770 if(partCfg[i].p.type == p1_types[t1]) { 00771 // distinguish mixed and identical rdf's 00772 if(mixed_flag == 1) start = 0; 00773 else start = (i+1); 00774 //particle loop: p2_types 00775 for(j=start; j<n_total_particles; j++) { 00776 for(t2=0; t2<n_p2; t2++) { 00777 if(partCfg[j].p.type == p2_types[t2]) { 00778 /*see if particles i and j belong to different molecules*/ 00779 if(partCfg[i].p.mol_id!=partCfg[j].p.mol_id) { 00780 p1[0]=configs[k][3*i ];p1[1]=configs[k][3*i+1];p1[2]=configs[k][3*i+2]; 00781 p2[0]=configs[k][3*j ];p2[1]=configs[k][3*j+1];p2[2]=configs[k][3*j+2]; 00782 dist =min_distance(p1, p2); 00783 if(dist > r_min && dist < r_max) { 00784 ind = (int) ( (dist - r_min)*inv_bin_width ); 00785 rdf_tmp[ind]++; 00786 } 00787 cnt++; 00788 } 00789 } 00790 } 00791 } 00792 } 00793 } 00794 } 00795 // normalization 00796 00797 for(i=0; i<r_bins; i++) { 00798 r_in = i*bin_width + r_min; 00799 r_out = r_in + bin_width; 00800 bin_volume = (4.0/3.0) * PI * ((r_out*r_out*r_out) - (r_in*r_in*r_in)); 00801 rdf[i] += rdf_tmp[i]*volume / (bin_volume * cnt); 00802 } 00803 00804 cnt_conf++; 00805 } //cnt_conf loop 00806 for(i=0; i<r_bins; i++) { 00807 rdf[i] /= (cnt_conf-1); 00808 } 00809 free(rdf_tmp); 00810 00811 } 00812 00813 /*addes this line*/ 00814 void calc_rdf_adress(int *p1_types, int n_p1, int *p2_types, int n_p2, 00815 double x_min, double x_max, double r_min, double r_max, int r_bins, double *rdf, int n_conf) 00816 { 00817 int i,j,k,l,t1,t2,ind,cnt=0,cnt_conf=1; 00818 int mixed_flag=0,start; 00819 double inv_bin_width=0.0,bin_width=0.0, dist; 00820 double volume, bin_volume, r_in, r_out; 00821 double *rdf_tmp, p1[3],p2[3]; 00822 00823 rdf_tmp = malloc(r_bins*sizeof(double)); 00824 00825 if(n_p1 == n_p2) { 00826 for(i=0;i<n_p1;i++) 00827 if( p1_types[i] != p2_types[i] ) mixed_flag=1; 00828 } 00829 else mixed_flag=1; 00830 bin_width = (r_max-r_min) / (double)r_bins; 00831 inv_bin_width = 1.0 / bin_width; 00832 volume = (x_max-x_min)*box_l[1]*box_l[2]; 00833 //volume = box_l[0]*box_l[1]*box_l[2]; 00834 for(l=0;l<r_bins;l++) rdf_tmp[l]=rdf[l] = 0.0; 00835 00836 while(cnt_conf<=n_conf) { 00837 for(l=0;l<r_bins;l++) rdf_tmp[l]=0.0; 00838 cnt=0; 00839 k=n_configs-cnt_conf; 00840 for(i=0; i<n_total_particles; i++) { 00841 for(t1=0; t1<n_p1; t1++) { 00842 if(partCfg[i].p.type == p1_types[t1]) { 00843 //accepts particles i's contained in explicit region 00844 if(configs[k][3*i]<x_max && configs[k][3*i]>=x_min) { 00845 // distinguish mixed and identical rdf's 00846 if(mixed_flag == 1) start = 0; 00847 else start = (i+1); 00848 //particle loop: p2_types 00849 for(j=start; j<n_total_particles; j++) { 00850 for(t2=0; t2<n_p2; t2++) { 00851 if(partCfg[j].p.type == p2_types[t2]) { 00852 //accepts particles j's contained in explicit region 00853 if(configs[k][3*j]<x_max && configs[k][3*j]>=x_min) { 00854 /*see if particles i and j belong to different molecules*/ 00855 if(partCfg[i].p.mol_id!=partCfg[j].p.mol_id) { 00856 p1[0]=configs[k][3*i ];p1[1]=configs[k][3*i+1];p1[2]=configs[k][3*i+2]; 00857 p2[0]=configs[k][3*j ];p2[1]=configs[k][3*j+1];p2[2]=configs[k][3*j+2]; 00858 dist =min_distance(p1, p2); 00859 if(dist > r_min && dist < r_max) { 00860 ind = (int) ( (dist - r_min)*inv_bin_width ); 00861 rdf_tmp[ind]++; 00862 } 00863 cnt++; 00864 } 00865 } 00866 } 00867 } 00868 } 00869 } 00870 } 00871 } 00872 } 00873 // normalization 00874 00875 for(i=0; i<r_bins; i++) { 00876 r_in = i*bin_width + r_min; 00877 r_out = r_in + bin_width; 00878 bin_volume = (4.0/3.0) * PI * ((r_out*r_out*r_out) - (r_in*r_in*r_in)); 00879 rdf[i] += rdf_tmp[i]*volume / (bin_volume * cnt); 00880 } 00881 00882 cnt_conf++; 00883 } //cnt_conf loop 00884 for(i=0; i<r_bins; i++) { 00885 rdf[i] /= (cnt_conf-1); 00886 } 00887 free(rdf_tmp); 00888 00889 } 00890 /*Up to here*/ 00891 00892 void calc_structurefactor(int type, int order, double **_ff) { 00893 int i, j, k, n, qi, p, order2; 00894 double qr, twoPI_L, C_sum, S_sum, *ff=NULL; 00895 00896 order2 = order*order; 00897 *_ff = ff = realloc(ff,2*order2*sizeof(double)); 00898 twoPI_L = 2*PI/box_l[0]; 00899 00900 if ((type < 0) || (type > n_particle_types)) { fprintf(stderr,"WARNING: Type %i does not exist!",type); fflush(NULL); errexit(); } 00901 else if (order < 1) { fprintf(stderr,"WARNING: parameter \"order\" has to be a whole positive number"); fflush(NULL); errexit(); } 00902 else { 00903 for(qi=0; qi<2*order2; qi++) { 00904 ff[qi] = 0.0; 00905 } 00906 for(i=0; i<=order; i++) { 00907 for(j=-order; j<=order; j++) { 00908 for(k=-order; k<=order; k++) { 00909 n = i*i + j*j + k*k; 00910 if ((n<=order2) && (n>=1)) { 00911 C_sum = S_sum = 0.0; 00912 for(p=0; p<n_total_particles; p++) { 00913 if (partCfg[p].p.type == type) { 00914 qr = twoPI_L * ( i*partCfg[p].r.p[0] + j*partCfg[p].r.p[1] + k*partCfg[p].r.p[2] ); 00915 C_sum+= cos(qr); 00916 S_sum+= sin(qr); 00917 } 00918 } 00919 ff[2*n-2]+= C_sum*C_sum + S_sum*S_sum; 00920 ff[2*n-1]++; 00921 } 00922 } 00923 } 00924 } 00925 n = 0; 00926 for(p=0; p<n_total_particles; p++) { 00927 if (partCfg[p].p.type == type) n++; 00928 } 00929 for(qi=0; qi<order2; qi++) 00930 if (ff[2*qi+1]!=0) ff[2*qi]/= n*ff[2*qi+1]; 00931 } 00932 } 00933 00934 //calculates average density profile in dir direction over last n_conf configurations 00935 void density_profile_av(int n_conf, int n_bin, double density, int dir, double *rho_ave, int type) 00936 { 00937 int i,j,k,m,n; 00938 double r; 00939 double r_bin; 00940 double pos[3]; 00941 int image_box[3]; 00942 00943 //calculation over last n_conf configurations 00944 00945 //bin width 00946 r_bin = box_l[dir]/(double)(n_bin); 00947 00948 for (i=0; i<n_bin; i++) 00949 rho_ave[i]=0; 00950 00951 k=n_configs-n_conf; 00952 00953 while(k<n_configs) { 00954 r = 0; 00955 j = 0; 00956 while (r < box_l[dir]) { 00957 n = 0; 00958 for(i=0; i<n_total_particles; i++) { 00959 //com particles 00960 if(partCfg[i].p.type == type) { 00961 for(m=0; m<3; m++) { 00962 pos[m] = configs[k][3*i+m]; 00963 image_box[m] = 0; 00964 } 00965 fold_coordinate(pos, image_box, dir); 00966 if (pos[dir] <= r+r_bin && pos[dir] > r) 00967 n++; 00968 } 00969 } 00970 00971 rho_ave[j] += (double)(n)/(box_l[1]*box_l[2]*r_bin)/density; 00972 j++; 00973 r += r_bin; 00974 } 00975 k++; 00976 } //k loop 00977 00978 // normalization 00979 for (i=0; i<n_bin; i++) 00980 rho_ave[i]/=n_conf; 00981 } 00982 00983 void calc_diffusion_profile(int dir, double xmin, double xmax, int nbins, int n_part, int n_conf, int time, int type, double *bins) 00984 { 00985 int i,t, count,index; 00986 double tcount=0; 00987 double xpos; 00988 double tpos[3]; 00989 int img_box[3] = {0,0,0}; 00990 //double delta_x = (box_l[0])/((double) nbins); 00991 00992 /* create and initialize the array of bins */ 00993 00994 // double *bins; 00995 00996 int *label; 00997 label = malloc(n_part*sizeof(int)); 00998 00999 /* calculation over last n_conf configurations */ 01000 t=n_configs-n_conf; 01001 01002 while (t<n_configs-time) { 01003 /* check initial condition */ 01004 count = 0; 01005 01006 for (i=0;i<n_total_particles;i++) { 01007 if(partCfg[i].p.type == type) { 01008 tpos[0] = configs[t][3*i]; 01009 tpos[1] = configs[t][3*i+1]; 01010 tpos[2] = configs[t][3*i+2]; 01011 fold_coordinate(tpos, img_box,dir); 01012 xpos = tpos[dir]; 01013 if(xpos > xmin && xpos < xmax) { 01014 label[count] = i; 01015 } 01016 else label[count] = -1; 01017 count ++; 01018 } 01019 } 01020 01021 /* check at time 'time' */ 01022 for (i=0;i<n_part;i++) { 01023 if (label[i]>0) { 01024 tpos[0] = configs[t+time][3*label[i]]; 01025 tpos[1] = configs[t+time][3*label[i]+1]; 01026 tpos[2] = configs[t+time][3*label[i]+2]; 01027 fold_coordinate(tpos, img_box,dir); 01028 xpos = tpos[dir]; 01029 01030 index = (int)(xpos/box_l[dir]*nbins); 01031 bins[index]++; 01032 } 01033 } 01034 t++; 01035 tcount++; 01036 } 01037 01038 /* normalization */ 01039 for (i=0;i<nbins;i++) { 01040 bins[i]=bins[i]/(tcount); 01041 } 01042 free(label); 01043 } 01044 01045 01046 int calc_radial_density_map (int xbins,int ybins,int thetabins,double xrange,double yrange, double axis[3], double center[3], IntList *beadids, DoubleList *density_map, DoubleList *density_profile) { 01047 int i,j,t; 01048 int pi,bi; 01049 int nbeadtypes; 01050 int beadcount; 01051 double vectprod[3]; 01052 double pvector[3]; 01053 double xdist,ydist,rdist,xav,yav,theta; 01054 double xbinwidth,ybinwidth,binvolume; 01055 double thetabinwidth; 01056 double *thetaradii; 01057 int *thetacounts; 01058 int xindex,yindex,tindex; 01059 xbinwidth = xrange/(double)(xbins); 01060 ybinwidth = yrange/(double)(ybins); 01061 01062 nbeadtypes = beadids->n; 01063 /* Update particles */ 01064 updatePartCfg(WITHOUT_BONDS); 01065 01066 /*Make sure particles are folded */ 01067 for (i = 0 ; i < n_total_particles ; i++) { 01068 fold_coordinate(partCfg[i].r.p,partCfg[i].l.i,0); 01069 fold_coordinate(partCfg[i].r.p,partCfg[i].l.i,1); 01070 fold_coordinate(partCfg[i].r.p,partCfg[i].l.i,2); 01071 } 01072 01073 beadcount = 0; 01074 xav = 0.0; 01075 yav = 0.0; 01076 for ( pi = 0 ; pi < n_total_particles ; pi++ ) { 01077 for ( bi = 0 ; bi < nbeadtypes ; bi++ ) { 01078 if ( beadids->e[bi] == partCfg[pi].p.type ) { 01079 01080 01081 /* Find the vector from the point to the center */ 01082 vecsub(center,partCfg[pi].r.p,pvector); 01083 01084 /* Work out x and y coordinates with respect to rotation axis */ 01085 01086 /* Find the minimum distance of the point from the axis */ 01087 vector_product(axis,pvector,vectprod); 01088 xdist = sqrt(sqrlen(vectprod)/sqrlen(axis)); 01089 01090 /* Find the projection of the vector from the point to the center 01091 onto the axis vector */ 01092 ydist = scalar(axis,pvector)/sqrt(sqrlen(axis)); 01093 01094 01095 /* Work out relevant indices for x and y */ 01096 xindex = (int)(floor(xdist/xbinwidth)); 01097 yindex = (int)(floor((ydist+yrange*0.5)/ybinwidth)); 01098 /* 01099 printf("x %d y %d \n",xindex,yindex); 01100 printf("p %f %f %f \n",partCfg[pi].r.p[0],partCfg[pi].r.p[1],partCfg[pi].r.p[2]); 01101 printf("pvec %f %f %f \n",pvector[0],pvector[1],pvector[2]); 01102 printf("axis %f %f %f \n",axis[0],axis[1],axis[2]); 01103 printf("dists %f %f \n",xdist,ydist); 01104 fflush(stdout); 01105 */ 01106 /* Check array bounds */ 01107 if ( (xindex < xbins && xindex > 0) && (yindex < ybins && yindex > 0) ) { 01108 density_map[bi].e[ybins*xindex+yindex] += 1; 01109 xav += xdist; 01110 yav += ydist; 01111 beadcount += 1; 01112 } else { 01113 // fprintf(stderr,"ERROR: outside array bounds in calc_radial_density_map"); fflush(NULL); errexit(); 01114 } 01115 } 01116 01117 } 01118 } 01119 01120 01121 /* Now turn counts into densities for the density map */ 01122 for ( bi = 0 ; bi < nbeadtypes ; bi++ ) { 01123 for ( i = 0 ; i < xbins ; i++ ) { 01124 /* All bins are cylinders and therefore constant in yindex */ 01125 binvolume = PI*(2*i*xbinwidth + xbinwidth*xbinwidth)*yrange; 01126 for ( j = 0 ; j < ybins ; j++ ) { 01127 density_map[bi].e[ybins*i+j] /= binvolume; 01128 } 01129 } 01130 } 01131 01132 01133 /* if required calculate the theta density profile */ 01134 if ( thetabins > 0 ) { 01135 /* Convert the center to an output of the density center */ 01136 xav = xav/(double)(beadcount); 01137 yav = yav/(double)(beadcount); 01138 thetabinwidth = 2*PI/(double)(thetabins); 01139 thetaradii = malloc(thetabins*nbeadtypes*sizeof(double)); 01140 thetacounts = malloc(thetabins*nbeadtypes*sizeof(int)); 01141 for ( bi = 0 ; bi < nbeadtypes ; bi++ ) { 01142 for ( t = 0 ; t < thetabins ; t++ ) { 01143 thetaradii[bi*thetabins+t] = 0.0; 01144 thetacounts[bi*thetabins+t] = 0.0; 01145 } 01146 } 01147 /* Maybe there is a nicer way to do this but now I will just repeat the loop over all particles */ 01148 for ( pi = 0 ; pi < n_total_particles ; pi++ ) { 01149 for ( bi = 0 ; bi < nbeadtypes ; bi++ ) { 01150 if ( beadids->e[bi] == partCfg[pi].p.type ) { 01151 vecsub(center,partCfg[pi].r.p,pvector); 01152 vector_product(axis,pvector,vectprod); 01153 xdist = sqrt(sqrlen(vectprod)/sqrlen(axis)); 01154 ydist = scalar(axis,pvector)/sqrt(sqrlen(axis)); 01155 /* Center the coordinates */ 01156 01157 xdist = xdist - xav; 01158 ydist = ydist - yav; 01159 rdist = sqrt(xdist*xdist+ydist*ydist); 01160 if ( ydist >= 0 ) { 01161 theta = acos(xdist/rdist); 01162 } else { 01163 theta = 2*PI-acos(xdist/rdist); 01164 } 01165 tindex = (int)(floor(theta/thetabinwidth)); 01166 thetaradii[bi*thetabins+tindex] += xdist + xav; 01167 thetacounts[bi*thetabins+tindex] += 1; 01168 if ( tindex >= thetabins ) { 01169 fprintf(stderr,"ERROR: outside density_profile array bounds in calc_radial_density_map"); fflush(NULL); errexit(); 01170 } else { 01171 density_profile[bi].e[tindex] += 1; 01172 } 01173 } 01174 } 01175 } 01176 01177 01178 01179 /* normalize the theta densities*/ 01180 for ( bi = 0 ; bi < nbeadtypes ; bi++ ) { 01181 for ( t = 0 ; t < thetabins ; t++ ) { 01182 rdist = thetaradii[bi*thetabins+t]/(double)(thetacounts[bi*thetabins+t]); 01183 density_profile[bi].e[t] /= rdist*rdist; 01184 } 01185 } 01186 01187 01188 01189 free(thetaradii); 01190 free(thetacounts); 01191 01192 } 01193 01194 01195 01196 01197 01198 01199 01200 // printf("done \n"); 01201 return ES_OK; 01202 } 01203 01204 double calc_vanhove(int ptype, double rmin, double rmax, int rbins, int tmax, double *msd, double **vanhove) 01205 { 01206 int i, c1, c3, c3_max, ind, np=0; 01207 double p1[3],p2[3],dist; 01208 double bin_width, inv_bin_width; 01209 IntList p; 01210 01211 /* create particle list */ 01212 init_intlist(&p); 01213 for(i=0; i<n_total_particles; i++) { if( partCfg[i].p.type == ptype ) { np ++; } } 01214 if(np==0) { return 0; } 01215 alloc_intlist(&p,np); 01216 for(i=0; i<n_total_particles; i++) { if( partCfg[i].p.type == ptype ) { p.e[p.n]=i; p.n++; } } 01217 01218 /* preparation */ 01219 bin_width = (rmax-rmin) / (double)rbins; 01220 inv_bin_width = 1.0 / bin_width; 01221 01222 /* calculate msd and store distribution in vanhove */ 01223 for(c1=0; c1<n_configs; c1++) { 01224 c3_max=(c1+tmax+1)>n_configs ? n_configs : c1+tmax+1; 01225 for(c3=(c1+1); c3<c3_max; c3++) { 01226 for(i=0; i<p.n; i++) { 01227 p1[0]=configs[c1][3*p.e[i] ]; p1[1]=configs[c1][3*p.e[i]+1]; p1[2]=configs[c1][3*p.e[i]+2]; 01228 p2[0]=configs[c3][3*p.e[i] ]; p2[1]=configs[c3][3*p.e[i]+1]; p2[2]=configs[c3][3*p.e[i]+2]; 01229 dist = distance(p1, p2); 01230 if(dist > rmin && dist < rmax) { 01231 ind = (int) ( (dist - rmin)*inv_bin_width ); 01232 vanhove[(c3-c1-1)][ind]++; 01233 } 01234 msd[(c3-c1-1)] += dist*dist; 01235 } 01236 } 01237 } 01238 01239 /* normalize */ 01240 for(c1=0; c1<(tmax); c1++) { 01241 for(i=0; i<rbins; i++) { vanhove[c1][i] /= (double) (n_configs-c1-1)*p.n; } 01242 msd[c1] /= (double) (n_configs-c1-1)*p.n; 01243 } 01244 01245 realloc_intlist(&p,0); 01246 return np; 01247 } 01248 01249 /**************************************************************************************** 01250 * config storage functions 01251 ****************************************************************************************/ 01252 01253 void analyze_append() { 01254 int i; 01255 n_part_conf = n_total_particles; 01256 configs = realloc(configs,(n_configs+1)*sizeof(double *)); 01257 configs[n_configs] = (double *) malloc(3*n_part_conf*sizeof(double)); 01258 for(i=0; i<n_part_conf; i++) { 01259 configs[n_configs][3*i] = partCfg[i].r.p[0]; 01260 configs[n_configs][3*i+1] = partCfg[i].r.p[1]; 01261 configs[n_configs][3*i+2] = partCfg[i].r.p[2]; 01262 } 01263 n_configs++; 01264 } 01265 01266 void analyze_push() { 01267 int i; 01268 n_part_conf = n_total_particles; 01269 free(configs[0]); 01270 for(i=0; i<n_configs-1; i++) { 01271 configs[i]=configs[i+1]; 01272 } 01273 configs[n_configs-1] = (double *) malloc(3*n_part_conf*sizeof(double)); 01274 for(i=0; i<n_part_conf; i++) { 01275 configs[n_configs-1][3*i] = partCfg[i].r.p[0]; 01276 configs[n_configs-1][3*i+1] = partCfg[i].r.p[1]; 01277 configs[n_configs-1][3*i+2] = partCfg[i].r.p[2]; 01278 } 01279 } 01280 01281 void analyze_replace(int ind) { 01282 int i; 01283 n_part_conf = n_total_particles; 01284 for(i=0; i<n_part_conf; i++) { 01285 configs[ind][3*i] = partCfg[i].r.p[0]; 01286 configs[ind][3*i+1] = partCfg[i].r.p[1]; 01287 configs[ind][3*i+2] = partCfg[i].r.p[2]; 01288 } 01289 } 01290 01291 void analyze_remove(int ind) { 01292 int i; 01293 free(configs[ind]); 01294 for(i=ind; i<n_configs-1; i++) { 01295 configs[i]=configs[i+1]; 01296 } 01297 n_configs--; 01298 configs = realloc(configs,n_configs*sizeof(double *)); 01299 if (n_configs == 0) n_part_conf = 0; 01300 } 01301 01302 void analyze_configs(double *tmp_config, int count) { 01303 int i; 01304 n_part_conf = count; 01305 configs = realloc(configs,(n_configs+1)*sizeof(double *)); 01306 configs[n_configs] = (double *) malloc(3*n_part_conf*sizeof(double)); 01307 for(i=0; i<n_part_conf; i++) { 01308 configs[n_configs][3*i] = tmp_config[3*i]; 01309 configs[n_configs][3*i+1] = tmp_config[3*i+1]; 01310 configs[n_configs][3*i+2] = tmp_config[3*i+2]; 01311 } 01312 n_configs++; 01313 } 01314 01315 void analyze_activate(int ind) { 01316 int i; 01317 double pos[3]; 01318 n_part_conf = n_total_particles; 01319 01320 for(i=0; i<n_part_conf; i++) { 01321 pos[0] = configs[ind][3*i]; 01322 pos[1] = configs[ind][3*i+1]; 01323 pos[2] = configs[ind][3*i+2]; 01324 if (place_particle(i, pos)==ES_ERROR) { 01325 char *errtxt = runtime_error(128 + ES_INTEGER_SPACE); 01326 ERROR_SPRINTF(errtxt, "{057 failed upon replacing particle %d in Espresso} ", i); 01327 } 01328 } 01329 } 01330 01331 01332 /**************************************************************************************** 01333 * Observables handling 01334 ****************************************************************************************/ 01335 01336 void obsstat_realloc_and_clear(Observable_stat *stat, int n_pre, int n_bonded, int n_non_bonded, 01337 int n_coulomb, int n_dipolar, int c_size) 01338 { 01339 int i, total = c_size*(n_pre + n_bonded_ia + n_non_bonded + n_coulomb + n_dipolar); 01340 01341 realloc_doublelist(&(stat->data), stat->data.n = total); 01342 stat->chunk_size = c_size; 01343 stat->n_coulomb = n_coulomb; 01344 stat->n_dipolar = n_dipolar; 01345 stat->n_non_bonded = n_non_bonded; 01346 stat->bonded = stat->data.e + c_size*n_pre; 01347 stat->non_bonded = stat->bonded + c_size*n_bonded_ia; 01348 stat->coulomb = stat->non_bonded + c_size*n_non_bonded; 01349 stat->dipolar = stat->coulomb + c_size*n_coulomb; 01350 01351 for(i = 0; i < total; i++) 01352 stat->data.e[i] = 0.0; 01353 } 01354 01355 void obsstat_realloc_and_clear_non_bonded(Observable_stat_non_bonded *stat_nb, int n_nonbonded, int c_size) 01356 { 01357 int i, total = c_size*(n_nonbonded + n_nonbonded); 01358 01359 realloc_doublelist(&(stat_nb->data_nb), stat_nb->data_nb.n = total); 01360 stat_nb->chunk_size_nb = c_size; 01361 stat_nb->n_nonbonded = n_nonbonded; 01362 stat_nb->non_bonded_intra = stat_nb->data_nb.e; 01363 stat_nb->non_bonded_inter = stat_nb->non_bonded_intra + c_size*n_nonbonded; 01364 01365 for(i = 0; i < total; i++) 01366 stat_nb->data_nb.e[i] = 0.0; 01367 } 01368 01369 void invalidate_obs() 01370 { 01371 total_energy.init_status = 0; 01372 total_pressure.init_status = 0; 01373 } 01374 01375 01376 //subfunction: mark all neighbors of a particle and their neighbors (recursiv!) 01377 void mark_neighbours(int type,int pa_nr,double dist,int *list){ 01378 int k; 01379 for (k=0;k<n_total_particles;k++){ 01380 //only unmarked and particles with right distance 01381 if ( (partCfg[k].p.type == type) && (list[k] == 0) && (min_distance(partCfg[pa_nr].r.p,partCfg[k].r.p) < dist) ){ 01382 //mark particle with same number as calling particle 01383 list[k]=list[pa_nr]; 01384 mark_neighbours(type,k,dist,list); 01385 } 01386 } 01387 } 01388 01389 01390 void centermass_conf(int k, int type_1, double *com) 01391 { 01392 int i, j; 01393 double M = 0.0; 01394 com[0]=com[1]=com[2]=0.; 01395 01396 for (j=0; j<n_total_particles; j++) { 01397 if ((partCfg[j].p.type == type_1) || (type_1 == -1)) 01398 { 01399 for (i=0; i<3; i++) 01400 { 01401 com[i] += configs[k][3*j+i]*PMASS(partCfg[j]); 01402 } 01403 M += PMASS(partCfg[j]); 01404 } 01405 } 01406 for (i=0; i<3; i++) 01407 { 01408 com[i] /= M; 01409 } 01410 return; 01411 }
1.7.5.1