void fold_all ( void ) { int i ; for (i = 0 ; i < n_total_particles ; i++) { fold_coordinate(partCfg[i].r.p,partCfg[i].l.i,xdir); fold_coordinate(partCfg[i].r.p,partCfg[i].l.i,ydir); fold_coordinate(partCfg[i].r.p,partCfg[i].l.i,zdir); } }
//calculates average density profile in dir direction over last n_conf configurations void density_profile_av(int n_conf, int n_bin, double density, int dir, double *rho_ave, int type) { int i,j,k,m,n; double r; double r_bin; double pos[3]; int image_box[3]; //calculation over last n_conf configurations //bin width r_bin = box_l[dir]/(double)(n_bin); for (i=0; i<n_bin; i++) rho_ave[i]=0; k=n_configs-n_conf; while(k<n_configs) { r = 0; j = 0; while (r < box_l[dir]) { n = 0; for(i=0; i<n_part; i++) { //com particles if(partCfg[i].p.type == type) { for(m=0; m<3; m++) { pos[m] = configs[k][3*i+m]; image_box[m] = 0; } fold_coordinate(pos, image_box, dir); if (pos[dir] <= r+r_bin && pos[dir] > r) n++; } } rho_ave[j] += (double)(n)/(box_l[1]*box_l[2]*r_bin)/density; j++; r += r_bin; } k++; } //k loop // normalization for (i=0; i<n_bin; i++) rho_ave[i]/=n_conf; }
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) { int i,j,t; int pi,bi; int nbeadtypes; int beadcount; double vectprod[3]; double pvector[3]; double xdist,ydist,rdist,xav,yav,theta; double xbinwidth,ybinwidth,binvolume; double thetabinwidth; double *thetaradii; int *thetacounts; int xindex,yindex,tindex; xbinwidth = xrange/(double)(xbins); ybinwidth = yrange/(double)(ybins); nbeadtypes = beadids->n; /* Update particles */ updatePartCfg(WITHOUT_BONDS); /*Make sure particles are folded */ for (i = 0 ; i < n_part ; i++) { fold_coordinate(partCfg[i].r.p,partCfg[i].l.i,0); fold_coordinate(partCfg[i].r.p,partCfg[i].l.i,1); fold_coordinate(partCfg[i].r.p,partCfg[i].l.i,2); } beadcount = 0; xav = 0.0; yav = 0.0; for ( pi = 0 ; pi < n_part ; pi++ ) { for ( bi = 0 ; bi < nbeadtypes ; bi++ ) { if ( beadids->e[bi] == partCfg[pi].p.type ) { /* Find the vector from the point to the center */ vecsub(center,partCfg[pi].r.p,pvector); /* Work out x and y coordinates with respect to rotation axis */ /* Find the minimum distance of the point from the axis */ vector_product(axis,pvector,vectprod); xdist = sqrt(sqrlen(vectprod)/sqrlen(axis)); /* Find the projection of the vector from the point to the center onto the axis vector */ ydist = scalar(axis,pvector)/sqrt(sqrlen(axis)); /* Work out relevant indices for x and y */ xindex = (int)(floor(xdist/xbinwidth)); yindex = (int)(floor((ydist+yrange*0.5)/ybinwidth)); /* printf("x %d y %d \n",xindex,yindex); printf("p %f %f %f \n",partCfg[pi].r.p[0],partCfg[pi].r.p[1],partCfg[pi].r.p[2]); printf("pvec %f %f %f \n",pvector[0],pvector[1],pvector[2]); printf("axis %f %f %f \n",axis[0],axis[1],axis[2]); printf("dists %f %f \n",xdist,ydist); fflush(stdout); */ /* Check array bounds */ if ( (xindex < xbins && xindex > 0) && (yindex < ybins && yindex > 0) ) { density_map[bi].e[ybins*xindex+yindex] += 1; xav += xdist; yav += ydist; beadcount += 1; } else { // fprintf(stderr,"ERROR: outside array bounds in calc_radial_density_map"); fflush(NULL); errexit(); } } } } /* Now turn counts into densities for the density map */ for ( bi = 0 ; bi < nbeadtypes ; bi++ ) { for ( i = 0 ; i < xbins ; i++ ) { /* All bins are cylinders and therefore constant in yindex */ binvolume = PI*(2*i*xbinwidth + xbinwidth*xbinwidth)*yrange; for ( j = 0 ; j < ybins ; j++ ) { density_map[bi].e[ybins*i+j] /= binvolume; } } } /* if required calculate the theta density profile */ if ( thetabins > 0 ) { /* Convert the center to an output of the density center */ xav = xav/(double)(beadcount); yav = yav/(double)(beadcount); thetabinwidth = 2*PI/(double)(thetabins); thetaradii = (double*)malloc(thetabins*nbeadtypes*sizeof(double)); thetacounts = (int*)malloc(thetabins*nbeadtypes*sizeof(int)); for ( bi = 0 ; bi < nbeadtypes ; bi++ ) { for ( t = 0 ; t < thetabins ; t++ ) { thetaradii[bi*thetabins+t] = 0.0; thetacounts[bi*thetabins+t] = 0.0; } } /* Maybe there is a nicer way to do this but now I will just repeat the loop over all particles */ for ( pi = 0 ; pi < n_part ; pi++ ) { for ( bi = 0 ; bi < nbeadtypes ; bi++ ) { if ( beadids->e[bi] == partCfg[pi].p.type ) { vecsub(center,partCfg[pi].r.p,pvector); vector_product(axis,pvector,vectprod); xdist = sqrt(sqrlen(vectprod)/sqrlen(axis)); ydist = scalar(axis,pvector)/sqrt(sqrlen(axis)); /* Center the coordinates */ xdist = xdist - xav; ydist = ydist - yav; rdist = sqrt(xdist*xdist+ydist*ydist); if ( ydist >= 0 ) { theta = acos(xdist/rdist); } else { theta = 2*PI-acos(xdist/rdist); } tindex = (int)(floor(theta/thetabinwidth)); thetaradii[bi*thetabins+tindex] += xdist + xav; thetacounts[bi*thetabins+tindex] += 1; if ( tindex >= thetabins ) { fprintf(stderr,"ERROR: outside density_profile array bounds in calc_radial_density_map"); fflush(NULL); errexit(); } else { density_profile[bi].e[tindex] += 1; } } } } /* normalize the theta densities*/ for ( bi = 0 ; bi < nbeadtypes ; bi++ ) { for ( t = 0 ; t < thetabins ; t++ ) { rdist = thetaradii[bi*thetabins+t]/(double)(thetacounts[bi*thetabins+t]); density_profile[bi].e[t] /= rdist*rdist; } } free(thetaradii); free(thetacounts); } // printf("done \n"); return ES_OK; }
void calc_diffusion_profile(int dir, double xmin, double xmax, int nbins, int n_part, int n_conf, int time, int type, double *bins) { int i,t, count,index; double tcount=0; double xpos; double tpos[3]; int img_box[3] = {0,0,0}; //double delta_x = (box_l[0])/((double) nbins); /* create and initialize the array of bins */ // double *bins; int *label; label = (int*)malloc(n_part*sizeof(int)); /* calculation over last n_conf configurations */ t=n_configs-n_conf; while (t<n_configs-time) { /* check initial condition */ count = 0; for (i=0;i<n_part;i++) { if(partCfg[i].p.type == type) { tpos[0] = configs[t][3*i]; tpos[1] = configs[t][3*i+1]; tpos[2] = configs[t][3*i+2]; fold_coordinate(tpos, img_box,dir); xpos = tpos[dir]; if(xpos > xmin && xpos < xmax) { label[count] = i; } else label[count] = -1; count ++; } } /* check at time 'time' */ for (i=0;i<n_part;i++) { if (label[i]>0) { tpos[0] = configs[t+time][3*label[i]]; tpos[1] = configs[t+time][3*label[i]+1]; tpos[2] = configs[t+time][3*label[i]+2]; fold_coordinate(tpos, img_box,dir); xpos = tpos[dir]; index = (int)(xpos/box_l[dir]*nbins); bins[index]++; } } t++; tcount++; } /* normalization */ for (i=0;i<nbins;i++) { bins[i]=bins[i]/(tcount); } free(label); }
int calc_cylindrical_average(std::vector<double> center, std::vector<double> direction, double length, double radius, int bins_axial, int bins_radial, std::vector<int> types, std::map<std::string, std::vector<std::vector<std::vector<double> > > > &distribution) { int index_axial; int index_radial; double binwd_axial = length / bins_axial; double binwd_radial = radius / bins_radial; // Select all particle types if the only entry in types is -1 bool all_types = false; if (types.size() == 1 && types[0] == -1) all_types = true; distribution.insert( std::pair<std::string, std::vector<std::vector<std::vector<double> > > > ("density", std::vector<std::vector<std::vector<double> > >(types.size())) ); distribution.insert( std::pair<std::string, std::vector<std::vector<std::vector<double> > > > ("v_r", std::vector<std::vector<std::vector<double> > >(types.size())) ); distribution.insert( std::pair<std::string, std::vector<std::vector<std::vector<double> > > > ("v_t", std::vector<std::vector<std::vector<double> > >(types.size())) ); for (unsigned int type = 0; type < types.size(); type++) { distribution["density"][type].resize(bins_radial); distribution["v_r"][type].resize(bins_radial); distribution["v_t"][type].resize(bins_radial); for (int index_radial = 0; index_radial < bins_radial; index_radial++) { distribution["density"][type][index_radial].assign(bins_axial, 0.0); distribution["v_r"][type][index_radial].assign(bins_axial, 0.0); distribution["v_t"][type][index_radial].assign(bins_axial, 0.0); } } // Update particles updatePartCfg(WITHOUT_BONDS); // Make sure particles are folded for (int i = 0 ; i < n_part ; i++) { fold_coordinate(partCfg[i].r.p,partCfg[i].m.v,partCfg[i].l.i,0); fold_coordinate(partCfg[i].r.p,partCfg[i].m.v,partCfg[i].l.i,1); fold_coordinate(partCfg[i].r.p,partCfg[i].m.v,partCfg[i].l.i,2); } // Declare variables for the density calculation double height, dist, v_radial, v_axial; double norm_direction = utils::veclen(direction); std::vector<double> pos(3), vel(3), diff, hat; for (int part_id = 0; part_id < n_part; part_id++) { for (unsigned int type_id = 0; type_id < types.size(); type_id++) { if ( types[type_id] == partCfg[part_id].p.type || all_types) { pos[0] = partCfg[part_id].r.p[0]; pos[1] = partCfg[part_id].r.p[1]; pos[2] = partCfg[part_id].r.p[2]; vel[0] = partCfg[part_id].m.v[0]; vel[1] = partCfg[part_id].m.v[1]; vel[2] = partCfg[part_id].m.v[2]; // Find the vector from center to the current particle diff = utils::vecsub(pos,center); // Find the height of the particle above the axis (height) and // the distance from the center point (dist) hat = utils::cross_product(direction,diff); height = utils::veclen(hat); dist = utils::dot_product(direction,diff) / norm_direction; // Determine the components of the velocity parallel and // perpendicular to the direction vector if ( height == 0 ) v_radial = utils::veclen(utils::cross_product(vel,direction)) / norm_direction; else v_radial = utils::dot_product(vel,hat) / height; v_axial = utils::dot_product(vel,direction) / norm_direction; // Work out relevant indices for x and y index_radial = static_cast<int>( floor(height / binwd_radial) ); index_axial = static_cast<int>( floor((dist + 0.5*length) / binwd_axial) ); if ( (index_radial < bins_radial && index_radial >= 0) && (index_axial < bins_axial && index_axial >= 0) ) { distribution["density"][type_id][index_radial][index_axial] += 1; distribution["v_r"][type_id][index_radial][index_axial] += v_radial; distribution["v_t"][type_id][index_radial][index_axial] += v_axial; } } } } // Now we turn the counts into densities by dividing by one radial // bin (binvolume). We also divide the velocites by the counts. double binvolume; for (unsigned int type_id = 0; type_id < types.size(); type_id++) { for (int index_radial = 0 ; index_radial < bins_radial ; index_radial++) { // All bins are cylindrical shells of thickness binwd_radial. // The volume is thus: binvolume = pi*(r_outer - r_inner)^2 * length if ( index_radial == 0 ) binvolume = M_PI * binwd_radial*binwd_radial * length; else binvolume = M_PI * (index_radial*index_radial + 2*index_radial) * binwd_radial*binwd_radial * length; for (int index_axial = 0 ; index_axial < bins_axial ; index_axial++) { if ( distribution["density"][type_id][index_radial][index_axial] != 0 ) { distribution["v_r"][type_id][index_radial][index_axial] /= distribution["density"][type_id][index_radial][index_axial]; distribution["v_t"][type_id][index_radial][index_axial] /= distribution["density"][type_id][index_radial][index_axial]; distribution["density"][type_id][index_radial][index_axial] /= binvolume; } } } } return ES_OK; }