void momentofinertiamatrix(int type, double *MofImatrix) { int i,j,count; double p1[3],com[3],massi; count=0; updatePartCfg(WITHOUT_BONDS); for(i=0;i<9;i++) MofImatrix[i]=0.; centermass(type, com); for (j=0; j<n_part; j++) { if (type == partCfg[j].p.type) { count ++; for (i=0; i<3; i++) { p1[i] = partCfg[j].r.p[i] - com[i]; } massi= PMASS(partCfg[j]); MofImatrix[0] += massi * (p1[1] * p1[1] + p1[2] * p1[2]) ; MofImatrix[4] += massi * (p1[0] * p1[0] + p1[2] * p1[2]); MofImatrix[8] += massi * (p1[0] * p1[0] + p1[1] * p1[1]); MofImatrix[1] -= massi * (p1[0] * p1[1]); MofImatrix[2] -= massi * (p1[0] * p1[2]); MofImatrix[5] -= massi * (p1[1] * p1[2]); } } /* use symmetry */ MofImatrix[3] = MofImatrix[1]; MofImatrix[6] = MofImatrix[2]; MofImatrix[7] = MofImatrix[5]; return; }
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 nbhood(double pt[3], double r, IntList *il, int planedims[3] ) { double d[3]; int i,j; double r2; r2 = r*r; init_intlist(il); updatePartCfg(WITHOUT_BONDS); for (i = 0; i<n_part; i++) { if ( (planedims[0] + planedims[1] + planedims[2]) == 3 ) { get_mi_vector(d, pt, partCfg[i].r.p); } else { /* Calculate the in plane distance */ for ( j= 0 ; j < 3 ; j++ ) { d[j] = planedims[j]*(partCfg[i].r.p[j]-pt[j]); } } if (sqrlen(d) < r2) { realloc_intlist(il, il->n + 1); il->e[il->n] = partCfg[i].p.identity; il->n++; } } }
int updatePartCfg(int bonds_flag) { int j; if(partCfg) return 1; partCfg = (Particle*)malloc(n_part*sizeof(Particle)); if (bonds_flag != WITH_BONDS) mpi_get_particles(partCfg, NULL); else mpi_get_particles(partCfg,&partCfg_bl); for(j=0; j<n_part; j++) unfold_position(partCfg[j].r.p,partCfg[j].l.i); partCfgSorted = 0; #ifdef VIRTUAL_SITES if (!sortPartCfg()) { char *errtxt = runtime_error(128); ERROR_SPRINTF(errtxt,"{094 could not sort partCfg} "); return 0; } if (!updatePartCfg(bonds_flag)) { char *errtxt = runtime_error(128); ERROR_SPRINTF(errtxt,"{094 could not update positions of virtual sites in partcfg } "); return 0; } #endif return 1; }
/* Get a complete list of the orientations of every lipid assuming a bilayer structure. Requires grid*/ int get_lipid_orients(IntList* l_orient) { int i,gi,gj, atom; double zreflocal,zref; double dir[3]; double refdir[3] = {0,0,1}; double grid_size[2]; double* height_grid; if ( xdir + ydir + zdir == -3 || mode_grid_3d[xdir] <= 0 || mode_grid_3d[ydir] <= 0 ) { char *errtxt = runtime_error(128); ERROR_SPRINTF(errtxt,"{036 cannot calculate lipid orientations with uninitialized grid} "); return ES_ERROR; } /* Allocate memory for height grid arrays and initialize these arrays */ height_grid = (double*) malloc((mode_grid_3d[xdir])*sizeof(double)*mode_grid_3d[ydir]); /* Calculate physical size of grid mesh */ grid_size[xdir] = box_l[xdir]/(double)mode_grid_3d[xdir]; grid_size[ydir] = box_l[ydir]/(double)mode_grid_3d[ydir]; /* Update particles */ updatePartCfg(WITHOUT_BONDS); //Make sure particles are sorted if (!sortPartCfg()) { fprintf(stderr,"%d,could not sort partCfg \n",this_node); return -1; } if ( !calc_fluctuations(height_grid, 1) ) { char *errtxt = runtime_error(128); ERROR_SPRINTF(errtxt,"{034 calculation of height grid failed } "); return -1; } zref = calc_zref( zdir ); for ( i = 0 ; i < n_molecules ; i++) { atom = topology[i].part.e[0]; gi = floor( partCfg[atom].r.p[xdir]/grid_size[xdir] ); gj = floor( partCfg[atom].r.p[ydir]/grid_size[ydir] ); zreflocal = height_grid[gj+gi*mode_grid_3d[xdir]] + zref; l_orient->e[i] = lipid_orientation(atom,partCfg,zreflocal,dir,refdir); } free(height_grid); return 1; }
int tclcommand_analyze_parse_cwvac(Tcl_Interp *interp, int argc, char **argv) { /* 'analyze { cwvac } <maxtau> <interval> [<chain_start> <n_chains> <chain_length>]' */ /***********************************************************************************************************/ char buffer[4*TCL_DOUBLE_SPACE+7]; int i, maxtau, interval; double *avac, *evac; if (argc < 2) { Tcl_AppendResult(interp, "Wrong # of args! Usage: analyze gkmobility <maxtau> <interval> [<chain_start> <n_chains> <chain_length>]", (char *)NULL); return (TCL_ERROR); } else { if (!ARG0_IS_I(maxtau)) return (TCL_ERROR); if (!ARG1_IS_I(interval)) return (TCL_ERROR); argc-=2; argv+=2; } if (tclcommand_analyze_set_parse_chain_topology_check(interp, argc, argv) == TCL_ERROR) return TCL_ERROR; if ((chain_n_chains == 0) || (chain_length == 0)) { Tcl_AppendResult(interp, "The chain topology has not been set",(char *)NULL); return TCL_ERROR; } if (maxtau <=0) { Tcl_AppendResult(interp, "Nothing to be done - choose <maxtau> greater zero!",(char *)NULL); return TCL_ERROR; } if (interval <= 0) { Tcl_AppendResult(interp, "<interval> has to be positive", (char *)NULL); return TCL_ERROR; } updatePartCfg(WITHOUT_BONDS); analyze_cwvac(maxtau, interval, &avac, &evac); // create return string sprintf(buffer, "{ "); Tcl_AppendResult(interp, buffer, (char *)NULL); for(i=0;i<=maxtau;i++) { sprintf(buffer,"%e ",avac[i]); Tcl_AppendResult(interp, buffer, (char *)NULL); } sprintf(buffer, "} { "); Tcl_AppendResult(interp, buffer, (char *)NULL); for(i=0;i<=maxtau;i++) { sprintf(buffer,"%e ",evac[i]); Tcl_AppendResult(interp, buffer, (char *)NULL); } sprintf(buffer, "}"); Tcl_AppendResult(interp, buffer, (char *)NULL); free(avac); free(evac); return (TCL_OK); }
int tclcommand_analyze_parse_rdfchain(Tcl_Interp *interp, int argc, char **argv) { /* 'analyze { rdfchain } <r_min> <r_max> <r_bins> [<chain_start> <n_chains> <chain_length>]' */ /***********************************************************************************************************/ char buffer[4*TCL_DOUBLE_SPACE+7]; int i, r_bins; double r_min, r_max, *f1, *f2, *f3; double bin_width, r; if (argc < 3) { Tcl_AppendResult(interp, "Wrong # of args! Usage: analyze rdfchain <r_min> <r_max> <r_bins> [<chain_start> <n_chains> <chain_length>]", (char *)NULL); return (TCL_ERROR); } else { if (!ARG0_IS_D(r_min)) return (TCL_ERROR); if (!ARG1_IS_D(r_max)) return (TCL_ERROR); if (!ARG_IS_I(2, r_bins)) return (TCL_ERROR); argc-=3; argv+=3; } if (tclcommand_analyze_set_parse_chain_topology_check(interp, argc, argv) == TCL_ERROR) return TCL_ERROR; if ((chain_n_chains == 0) || (chain_length == 0)) { Tcl_AppendResult(interp, "The chain topology has not been set",(char *)NULL); return TCL_ERROR; } if (r_bins <=0) { Tcl_AppendResult(interp, "Nothing to be done - choose <r_bins> greater zero!",(char *)NULL); return TCL_ERROR; } if (r_min <= 0.) { Tcl_AppendResult(interp, "<r_min> has to be positive", (char *)NULL); return TCL_ERROR; } if (r_max <= r_min) { Tcl_AppendResult(interp, "<r_max> has to be larger than <r_min>", (char *)NULL); return TCL_ERROR; } updatePartCfg(WITHOUT_BONDS); analyze_rdfchain(r_min, r_max, r_bins, &f1, &f2, &f3); bin_width = (r_max - r_min) / (double)r_bins; r = r_min + bin_width/2.0; for(i=0; i<r_bins; i++) { sprintf(buffer,"{%f %f %f %f} ",r,f1[i],f2[i],f3[i]); Tcl_AppendResult(interp, buffer, (char *)NULL); r+= bin_width; } free(f1); free(f2); free(f3); return (TCL_OK); }
int tclcommand_analyze_parse_and_print_pressure_mol(Tcl_Interp *interp,int argc, char **argv) { char buffer[TCL_DOUBLE_SPACE]; int type1, type2; double psum; #ifdef ELECTROSTATICS #ifndef INTER_RF Tcl_ResetResult(interp); Tcl_AppendResult(interp, "parse_and_print_pressure_mol is only possible with INTER_RF ", (char *)NULL); return (TCL_ERROR); #endif #endif updatePartCfg(WITHOUT_BONDS); if (!sortPartCfg()) { char *errtxt = runtime_error(128); ERROR_SPRINTF(errtxt, "{059 parse_and_print_pressure_mol: could not sort particle config, particle ids not consecutive?} "); return TCL_ERROR; } if (argc < 2) { Tcl_ResetResult(interp); Tcl_AppendResult(interp, "usage: analyze pressure_mol <type1> <type2>", (char *)NULL); return (TCL_ERROR); } if (!ARG0_IS_I(type1)) { Tcl_ResetResult(interp); Tcl_AppendResult(interp, "usage: analyze pressure_mol <type1> <type2>", (char *)NULL); return (TCL_ERROR); } if (!ARG1_IS_I(type2)) { Tcl_ResetResult(interp); Tcl_AppendResult(interp, "usage: analyze pressure_mol <type1> <type2>", (char *)NULL); return (TCL_ERROR); } argc-=2; argv+=2; if (n_molecules==0) { Tcl_ResetResult(interp); Tcl_AppendResult(interp, "No molecules defined !", (char *)NULL); return (TCL_ERROR); } psum=calc_pressure_mol(type1,type2); //sprintf(buffer,"%i",type1); //Tcl_AppendResult(interp,"{ analyze pressure_mol ",buffer," ",(char *)NULL); //sprintf(buffer,"%i",type2); //Tcl_AppendResult(interp,buffer," ",(char *)NULL); sprintf(buffer,"%e",psum); Tcl_AppendResult(interp, buffer,(char *)NULL); return TCL_OK; }
std::vector<double> centerofmass(int type) { std::vector<double> com (3); double mass = 0.0; updatePartCfg(WITHOUT_BONDS); for (int i=0; i<n_part; i++) { if ((partCfg[i].p.type == type) || (type == -1)) { for (int j=0; j<3; j++) { com[j] += partCfg[i].r.p[j]*(partCfg[i]).p.mass; } mass += (partCfg[i]).p.mass; } } for (int j=0; j<3; j++) com[j] /= mass; return com; }
double distto(double p[3], int pid) { int i; double d[3]; double mindist; updatePartCfg(WITHOUT_BONDS); /* larger than possible */ mindist=SQR(box_l[0] + box_l[1] + box_l[2]); for (i=0; i<n_part; i++) { if (pid != partCfg[i].p.identity) { get_mi_vector(d, p, partCfg[i].r.p); mindist = dmin(mindist, sqrlen(d)); } } return sqrt(mindist); }
int tclcommand_analyze_parse_and_print_energy_kinetic_mol(Tcl_Interp *interp,int argc, char **argv) { char buffer[TCL_DOUBLE_SPACE]; int type; double Ekin; updatePartCfg(WITHOUT_BONDS); if (!sortPartCfg()) { char *errtxt = runtime_error(128); ERROR_SPRINTF(errtxt, "{059 parse_and_print_energy_kinetic_mol: could not sort particle config, particle ids not consecutive?} "); return TCL_ERROR; } if (argc < 1) { Tcl_ResetResult(interp); Tcl_AppendResult(interp, "usage: analyze energy_kinetic <type>", (char *)NULL); return (TCL_ERROR); } if (!ARG0_IS_I(type)) { Tcl_ResetResult(interp); Tcl_AppendResult(interp, "usage: analyze energy_kinetic <type>", (char *)NULL); return (TCL_ERROR); } argc-=1; argv+=1; if (n_molecules==0) { Tcl_ResetResult(interp); Tcl_AppendResult(interp, "No molecules defined !", (char *)NULL); return (TCL_ERROR); } Ekin=calc_energy_kinetic_mol(type); if (Ekin < 0.0) { Tcl_ResetResult(interp); sprintf(buffer,"%i",-(int)Ekin); Tcl_AppendResult(interp,"Could not fetch com in calc_energy_kinetic_mol! From mol_id",buffer, (char *)NULL); return (TCL_ERROR); } //sprintf(buffer,"%i",type); //Tcl_AppendResult(interp,"{ analyze pressure_mol ",buffer," ",(char *)NULL); sprintf(buffer,"%e",Ekin); Tcl_AppendResult(interp, buffer,(char *)NULL); return TCL_OK; }
void centermass(int type, double *com) { int i, j; double M = 0.0; com[0]=com[1]=com[2]=0.; updatePartCfg(WITHOUT_BONDS); for (j=0; j<n_part; j++) { if ((partCfg[j].p.type == type) || (type == -1)) { for (i=0; i<3; i++) { com[i] += partCfg[j].r.p[i]*PMASS(partCfg[j]); } M += PMASS(partCfg[j]); } } for (i=0; i<3; i++) { com[i] /= M; } return; }
void angularmomentum(int type, double *com) { int i, j; double tmp[3]; double pre_factor; com[0]=com[1]=com[2]=0.; updatePartCfg(WITHOUT_BONDS); for (j=0; j<n_part; j++) { if (type == partCfg[j].p.type) { vector_product(partCfg[j].r.p,partCfg[j].m.v,tmp); pre_factor=PMASS(partCfg[j]); for (i=0; i<3; i++) { com[i] += tmp[i]*pre_factor; } } } return; }
int update_particle_array(int type) { updatePartCfg(WITHOUT_BONDS); if (!partCfg) return ES_ERROR; int t_c = 0; for (int i=0; i<n_part; i++) { if (partCfg[i].p.type == type ) { type_array[Index.type[type]].id_list[t_c++] = partCfg[i].p.identity; } if ( t_c > (double) type_array[Index.type[type]].cur_size/2.0 ) { if ( reallocate_type_array(type) == ES_ERROR ) return ES_ERROR; } } type_array[Index.type[type]].max_entry = t_c; for ( int i = t_c; i<type_array[Index.type[type]].cur_size; i++) type_array[Index.type[type]].id_list[i] = -1; return ES_OK; }
int tclcommand_analyze_parse_and_print_check_mol(Tcl_Interp *interp,int argc, char **argv){ int j,count=0; double dist; char buffer[TCL_DOUBLE_SPACE]; Particle p; updatePartCfg(WITHOUT_BONDS); for(j=0; j<n_total_particles; j++){ if (!ifParticleIsVirtual(&partCfg[j])) continue; get_particle_data(j,&p); //dist=min_distance(partCfg[j].r.p,p.r.p); unfold_position(p.r.p,p.l.i); dist=distance(partCfg[j].r.p,p.r.p); if (dist > 0.01){ if (count==0) Tcl_AppendResult(interp,"BEGIN Particle Missmatch: \n", (char *)NULL); sprintf(buffer,"%i",j); Tcl_AppendResult(interp,"Particle ",buffer, (char *)NULL); Tcl_PrintDouble(interp,partCfg[j].r.p[0] , buffer); Tcl_AppendResult(interp," partCfg x ",buffer, (char *)NULL); Tcl_PrintDouble(interp,partCfg[j].r.p[1] , buffer); Tcl_AppendResult(interp," y ",buffer, (char *)NULL); Tcl_PrintDouble(interp,partCfg[j].r.p[2] , buffer); Tcl_AppendResult(interp," z ",buffer, (char *)NULL); Tcl_PrintDouble(interp,p.r.p[0] , buffer); Tcl_AppendResult(interp," my_partCfg x ",buffer, (char *)NULL); Tcl_PrintDouble(interp,p.r.p[1] , buffer); Tcl_AppendResult(interp," y ",buffer, (char *)NULL); Tcl_PrintDouble(interp,p.r.p[2] , buffer); Tcl_AppendResult(interp," z ",buffer, (char *)NULL); Tcl_PrintDouble(interp, dist, buffer); Tcl_AppendResult(interp," dist ",buffer,"\n", (char *)NULL); count++; } } if (count!=0){ Tcl_AppendResult(interp,"END Particle Missmatch\n", (char *)NULL); return(TCL_ERROR); } return(TCL_OK); }
void centermass_vel(int type, double *com) { /*center of mass velocity scaled with time_step*/ int i, j; int count = 0; com[0]=com[1]=com[2]=0.; updatePartCfg(WITHOUT_BONDS); for (j=0; j<n_part; j++) { if (type == partCfg[j].p.type) { for (i=0; i<3; i++) { com[i] += partCfg[j].m.v[i]; } count++; } } for (i=0; i<3; i++) { com[i] /= count; } return; }
std::vector<double> centerofmass_vel(int type) { /*center of mass velocity scaled with time_step*/ std::vector<double> com_vel (3); int i, j; int count = 0; updatePartCfg(WITHOUT_BONDS); for (j=0; j<n_part; j++) { if (type == partCfg[j].p.type) { for (i=0; i<3; i++) { com_vel[i] += partCfg[j].m.v[i]; } count++; } } for (i=0; i<3; i++) { com_vel[i] /= count; } return com_vel; }
int updatePartCfg(int bonds_flag) { int j; if(partCfg) return 1; partCfg = (Particle*)malloc(n_part*sizeof(Particle)); if (bonds_flag != WITH_BONDS) mpi_get_particles(partCfg, NULL); else mpi_get_particles(partCfg,&partCfg_bl); for(j=0; j<n_part; j++) #ifdef LEES_EDWARDS unfold_position(partCfg[j].r.p, partCfg[j].m.v, partCfg[j].l.i); #else unfold_position(partCfg[j].r.p, partCfg[j].l.i); #endif partCfgSorted = 0; #ifdef VIRTUAL_SITES if (!sortPartCfg()) { ostringstream msg; msg <<"could not sort partCfg"; runtimeError(msg); return 0; } if (!updatePartCfg(bonds_flag)) { ostringstream msg; msg <<"could not update positions of virtual sites in partcfg"; runtimeError(msg); return 0; } #endif return 1; }
int sortPartCfg() { int i; Particle *sorted; if (!partCfg) updatePartCfg(WITHOUT_BONDS); if (partCfgSorted) return 1; if (n_part != max_seen_particle + 1) return 0; sorted = (Particle*)malloc(n_part*sizeof(Particle)); for(i = 0; i < n_part; i++) memcpy(&sorted[partCfg[i].p.identity], &partCfg[i], sizeof(Particle)); free(partCfg); partCfg = sorted; partCfgSorted = 1; return 1; }
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; }
int init_type_array(int type){ if (init_gc() == ES_ERROR) return ES_ERROR; updatePartCfg(WITHOUT_BONDS); if (!partCfg) return ES_ERROR; int type_index=-1; type_index= (Type.max_entry++); if ( type_index == number_of_type_lists ) { reallocate_global_type_list(number_of_type_lists*2); } Type.index = (int *) realloc ( (void *) Type.index, sizeof(int)*Type.max_entry); //reallocate the array that holds the particle type and points to the type index used for the type_list if ( type >= Index.max_entry ) { Index.type= (int * ) realloc( (void *) Index.type, (type+1)*sizeof(int)); Index.max_entry = type + 1; } for (int i=0; i<Type.max_entry; i++) Index.type[i]=-1; if (Type.index == (int *) 0 || Index.type == (int *) 0) return ES_ERROR; //allocates a list for ids for as many entries as there are particles right now if ( !(partCfg) || type < 0 ) { return ES_ERROR; } Type.index[type_index]=type; //fill in array type_index_of_type for (int i=0; i<Type.max_entry; i++ ) { Index.type[Type.index[i]] = i; } int t_c = 0; //index type_array[Index.type[type]].id_list = (int *) malloc (sizeof (int) * n_part); for (int i=0; i<n_part; i++) { if ( partCfg[i].p.type==type ) type_array[Index.type[type]].id_list[t_c++]=partCfg[i].p.identity; } int max_size=n_part; if ( t_c != 0 ) { while ( t_c < (double) max_size/4.0) { max_size= floor( (double ) max_size/2.0); } // now the array is shrinked to at least 4 times the highest entry type_array[Index.type[type]].id_list= (int *) realloc( (void *) type_array[Index.type[type]].id_list, sizeof(int)*2*max_size); type_array[Index.type[type]].max_entry = t_c; type_array[Index.type[type]].cur_size = max_size*2; } else { //no particles of the given type were found, so leave array size fixed at a reasonable start entry 64 ints in this case type_array[Index.type[type]].id_list= (int *) realloc( (void *) type_array[Index.type[type]].id_list, sizeof(int)*64); type_array[Index.type[type]].max_entry = t_c; type_array[Index.type[type]].cur_size = 64; } //fill remaining entries with -1 for (int i=type_array[Index.type[type]].max_entry; i<type_array[Index.type[type]].cur_size; i++) { type_array[Index.type[type]].id_list[i] = -1; } Type_array_init = 1; return ES_OK; }
void calc_gyration_tensor(int type, double **_gt) { int i, j, count; double com[3]; double eva[3],eve0[3],eve1[3],eve2[3]; double *gt=NULL, tmp; double Smatrix[9],p1[3]; for (i=0; i<9; i++) Smatrix[i] = 0; /* 3*ev, rg, b, c, kappa, eve0[3], eve1[3], eve2[3]*/ *_gt = gt = (double*)realloc(gt,16*sizeof(double)); updatePartCfg(WITHOUT_BONDS); /* Calculate the position of COM */ centermass(type,com); /* Calculate the gyration tensor Smatrix */ count=0; for (i=0;i<n_part;i++) { if ((partCfg[i].p.type == type) || (type == -1)) { for ( j=0; j<3 ; j++ ) { p1[j] = partCfg[i].r.p[j] - com[j]; } count ++; Smatrix[0] += p1[0]*p1[0]; Smatrix[1] += p1[0]*p1[1]; Smatrix[2] += p1[0]*p1[2]; Smatrix[4] += p1[1]*p1[1]; Smatrix[5] += p1[1]*p1[2]; Smatrix[8] += p1[2]*p1[2]; } } /* use symmetry */ Smatrix[3]=Smatrix[1]; Smatrix[6]=Smatrix[2]; Smatrix[7]=Smatrix[5]; for (i=0;i<9;i++){ Smatrix[i] /= count; } /* Calculate the eigenvalues of Smatrix */ i=calc_eigenvalues_3x3(Smatrix, eva); tmp=0.0; for (i=0;i<3;i++) { /* Eigenvalues */ gt[i] = eva[i]; tmp += eva[i]; } i=calc_eigenvector_3x3(Smatrix,eva[0],eve0); i=calc_eigenvector_3x3(Smatrix,eva[1],eve1); i=calc_eigenvector_3x3(Smatrix,eva[2],eve2); gt[3] = tmp; /* Squared Radius of Gyration */ gt[4] = eva[0]-0.5*(eva[1]+eva[2]); /* Asphericity */ gt[5] = eva[1]-eva[2]; /* Acylindricity */ gt[6] = (gt[4]*gt[4]+0.75*gt[5]*gt[5])/(gt[3]*gt[3]); /* Relative shape anisotropy */ /* Eigenvectors */ for (j=0;j<3;j++) { gt[7+j]=eve0[j]; gt[10+j]=eve1[j]; gt[13+j]=eve2[j]; } }
/** This routine calculates the orientational order parameter for a lipid bilayer. */ int orient_order(double* result, double* stored_dirs) { double dir[3]; double refdir[3] = {0,0,1}; double sumdir[3] = {0,0,0}; double zref; int bilayer_cnt; int i,atom,tmpzdir; double dp; double len; IntList l_orient; init_intlist(&l_orient); realloc_intlist(&l_orient, n_molecules); bilayer_cnt = 0; *result = 0; // Check to see if the grid has been set and if not then interpret if ( xdir + ydir + zdir == -3 ) { tmpzdir = 2; } else { tmpzdir = zdir; }; /* Update particles */ updatePartCfg(WITHOUT_BONDS); /* Make sure particles are sorted */ if (!sortPartCfg()) { char *errtxt = runtime_error(128); ERROR_SPRINTF(errtxt, "{035 could not sort partCfg, particles have to start at 0 and have consecutive identities} "); return ES_ERROR; } /* Calculate the reference z position as its mean.*/ zref = calc_zref( tmpzdir ); /* Calculate the orientation of all the lipids in turn and include only UP or DOWN lipids in a calculation of the overall orientation direction of the bilayer .. ie the reference vector from which we can calculate the orientational order. */ for ( i = 0 ; i < n_molecules ; i++) { atom = topology[i].part.e[0]; l_orient.e[i] = lipid_orientation(atom,partCfg,zref,dir,refdir); stored_dirs[i*3] = dir[0]; stored_dirs[i*3+1] = dir[1]; stored_dirs[i*3+2] = dir[2]; if ( l_orient.e[i] == LIPID_UP ) { sumdir[0] += dir[0]; sumdir[1] += dir[1]; sumdir[2] += dir[2]; bilayer_cnt++; } if ( l_orient.e[i] == LIPID_DOWN ) { sumdir[0] -= dir[0]; sumdir[1] -= dir[1]; sumdir[2] -= dir[2]; bilayer_cnt++; } } /* Normalise the bilayer normal vector */ len = 0.0; for ( i = 0 ; i < 3 ; i++) { sumdir[i] = sumdir[i]/(double)(bilayer_cnt); len += sumdir[i]*sumdir[i]; } for ( i = 0 ; i < 3 ; i++) { sumdir[i] = sumdir[i]/sqrt(len); } /* Calculate the orientational order */ for ( i = 0 ; i < n_molecules ; i++ ) { dir[0] = stored_dirs[i*3]; dir[1] = stored_dirs[i*3+1]; dir[2] = stored_dirs[i*3+2]; if ( l_orient.e[i] != LIPID_STRAY && l_orient.e[i] != REAL_LIPID_STRAY ) { dp = scalar(dir,sumdir); *result += dp*dp*1.5-0.5; } } realloc_intlist(&l_orient, 0); *result = *result/(double)(bilayer_cnt); return ES_OK; }
/** This routine performs must of the work involved in the analyze modes2d command. A breakdown of what the routine does is as follows \li fftw plans and in / out arrays are initialized as required \li calculate height function is called \li The height function is fourier transformed using the fftw library. Note: argument switch_fluc switch_fluc == 1 for height grid switch_fluc == 0 for thickness */ int modes2d(fftw_complex* modes, int switch_fluc) { /* All these variables need to be static so that the fftw3 plan can be initialised and reused */ static fftw_plan mode_analysis_plan; // height grid /** Input values for the fft */ static double* height_grid; /** Output values for the fft */ static fftw_complex* result; /** Every time a change is made to the grid calculate the fftw plan for the subsequent fft and destroy any existing plans */ if ( mode_grid_changed ) { STAT_TRACE(fprintf(stderr,"%d,initializing fftw for mode analysis \n",this_node)); if ( xdir + ydir + zdir == -3 ) { char *errtxt = runtime_error(128); ERROR_SPRINTF(errtxt,"{092 attempt to perform mode analysis with uninitialized grid} "); return -1; } STAT_TRACE(fprintf(stderr,"%d,destroying old fftw plan \n",this_node)); /* Make sure all memory is free and old plan is destroyed. It's ok to call these functions on uninitialised pointers I think */ fftw_free(result); fftw_free(height_grid); fftw_destroy_plan(mode_analysis_plan); fftw_cleanup(); /* Allocate memory for input and output arrays */ height_grid = (double*) malloc((mode_grid_3d[xdir])*sizeof(double)*mode_grid_3d[ydir]); result = (fftw_complex*) malloc((mode_grid_3d[ydir]/2+1)*(mode_grid_3d[xdir])*sizeof(fftw_complex)); mode_analysis_plan = fftw_plan_dft_r2c_2d(mode_grid_3d[xdir],mode_grid_3d[ydir],height_grid, result,FFTW_ESTIMATE); STAT_TRACE(fprintf(stderr,"%d,created new fftw plan \n",this_node)); mode_grid_changed = 0; } /* Update particles */ updatePartCfg(WITHOUT_BONDS); //Make sure particles are sorted if (!sortPartCfg()) { fprintf(stderr,"%d,could not sort partCfg \n",this_node); return -1; } if ( !calc_fluctuations(height_grid, switch_fluc)) { char *errtxt = runtime_error(128); ERROR_SPRINTF(errtxt,"{034 calculation of height grid failed } "); return -1; } STAT_TRACE(fprintf(stderr,"%d,calling fftw \n",this_node)); fftw_execute(mode_analysis_plan); /* Copy result to modes */ memcpy(modes, result, mode_grid_3d[xdir]*(mode_grid_3d[ydir]/2 + 1)*sizeof(fftw_complex)); STAT_TRACE(fprintf(stderr,"%d,called fftw \n",this_node)); return 1; }
/** This routine calculates density profiles for given bead types as a function of height relative to the bilayer midplane where the bilayer is assumed to wrap around a sphere of radius r and center cx,cy,cz. \li The radius value of each bead is then calculated relative to the colloid radius and the population of the relevant bin is increased. **/ int bilayer_density_profile_sphere (IntList *beadids, double rrange , DoubleList *density_profile, double radius, double center[3]) { int i,j; int thisbin,nbins; double binwidth; int nbeadtypes,l_orient; double relativeradius; double rvec[3]; double direction[3]; double innerr; double outerr; double binvolume; double piconst; double rs; nbins = density_profile[0].max; nbeadtypes=beadids->max; binwidth = 2*rrange/(double)nbins; /* Update particles */ updatePartCfg(WITHOUT_BONDS); //Make sure particles are sorted if (!sortPartCfg()) { char *errtxt = runtime_error(128); ERROR_SPRINTF(errtxt,"{094 could not sort partCfg} "); return -1; } if ( density_profile == NULL ) { char *errtxt = runtime_error(128); ERROR_SPRINTF(errtxt,"{095 density_profile not initialized in calc_bilayer_density_profile } "); return -1; } // Do this to fold the particles fold_all( ); for (i = 0 ; i < n_total_particles ; i++) { for ( j = 0 ; j < nbeadtypes ; j++ ) { if ( beadids->e[j] == partCfg[i].p.type ) { /* What is the relative height compared to the grid */ get_mi_vector(rvec,partCfg[i].r.p,center); relativeradius = sqrt(sqrlen(rvec)) - radius; /* If the particle is within our zrange then add it to the profile */ if ( ( -rrange < relativeradius) && ( relativeradius < rrange) ) { thisbin = (int)(floor((relativeradius+rrange)/binwidth)); if ( thisbin < 0 || thisbin >= density_profile[j].max ) { char *errtxt = runtime_error(128); ERROR_SPRINTF(errtxt,"{095 bin is outside range } "); return -1; } l_orient = lipid_orientation(i,partCfg,0.0,direction,rvec); /* Distinguish between lipids that are in the top and bottom layers */ if ( l_orient == LIPID_UP ) { density_profile[j].e[thisbin] += 1.0; } if ( l_orient == LIPID_DOWN ) { density_profile[2*nbeadtypes-j-1].e[thisbin] += 1.0; } } } } } /* Normalize the density profile */ piconst = (4.0*3.141592)/(3.0); rs = radius - rrange; for ( i = 0 ; i < 2*nbeadtypes ; i++ ) { for ( j = 0 ; j < nbins ; j++ ) { innerr = j*binwidth+rs; outerr = (j+1)*binwidth + rs; binvolume = piconst*(outerr*outerr*outerr - innerr*innerr*innerr); density_profile[i].e[j] = density_profile[i].e[j]/binvolume; } } return 1; }
/* parser for hole cluster analyzation: analyze holes <prob_part_type_number> <mesh_size>. Needs feature LENNARD_JONES compiled in. */ int tclcommand_analyze_parse_holes(Tcl_Interp *interp, int argc, char **argv) { int i,j; int probe_part_type; int mesh_size=1, meshdim[3]; double freevol=0.0; char buffer[TCL_INTEGER_SPACE+TCL_DOUBLE_SPACE]; IntList mesh; int n_holes; int **holes; int max_size=0; int *surface; #ifndef LENNARD_JONES Tcl_AppendResult(interp, "analyze holes needs feature LENNARD_JONES compiled in.\n", (char *)NULL); return TCL_ERROR; #endif /* check # of parameters */ if (argc < 2) { Tcl_AppendResult(interp, "analyze holes needs 2 parameters:\n", (char *)NULL); Tcl_AppendResult(interp, "<prob_part_type_number> <mesh_size>", (char *)NULL); return TCL_ERROR; } /* check parameter types */ if( (! ARG_IS_I(0, probe_part_type)) || (! ARG_IS_I(1, mesh_size)) ) { Tcl_AppendResult(interp, "analyze holes needs 2 parameters of type and meaning:\n", (char *)NULL); Tcl_AppendResult(interp, "INT INT\n", (char *)NULL); Tcl_AppendResult(interp, "<prob_part_type_number> <mesh_size>", (char *)NULL); return TCL_ERROR; } /* check parameter values */ if( probe_part_type > n_particle_types || probe_part_type < 0 ) { Tcl_AppendResult(interp, "analyze holes: probe particle type number does not exist", (char *)NULL); return TCL_ERROR; } if( mesh_size < 1 ) { Tcl_AppendResult(interp, "analyze holes: mesh size must be positive (min=1)", (char *)NULL); return TCL_ERROR; } /* preparation */ updatePartCfg(WITHOUT_BONDS); meshdim[0]=mesh_size; meshdim[1]=mesh_size; meshdim[2]=mesh_size; alloc_intlist(&mesh, (meshdim[0]*meshdim[1]*meshdim[2])); /* perform free space identification*/ create_free_volume_grid(mesh, meshdim, probe_part_type); /* perfrom hole cluster algorithm */ n_holes = cluster_free_volume_grid(mesh, meshdim, &holes); /* surface to volume ratio */ surface = (int *) malloc(sizeof(int)*(n_holes+1)); cluster_free_volume_surface(mesh, meshdim, n_holes, holes, surface); /* calculate accessible volume / max size*/ for ( i=0; i<=n_holes; i++ ) { freevol += holes[i][0]; if ( holes[i][0]> max_size ) max_size = holes[i][0]; } /* Append result to tcl interpreter */ Tcl_AppendResult(interp, "{ n_holes mean_hole_size max_hole_size free_volume_fraction { sizes } { surfaces } { element_lists } } ", (char *)NULL); Tcl_AppendResult(interp, "{", (char *)NULL); /* number of holes */ sprintf(buffer,"%d ",n_holes+1); Tcl_AppendResult(interp, buffer, " ", (char *)NULL); /* mean hole size */ sprintf(buffer,"%f ",freevol/(n_holes+1.0)); Tcl_AppendResult(interp, buffer, " ", (char *)NULL); /* max hole size */ sprintf(buffer,"%d ",max_size); Tcl_AppendResult(interp, buffer, " ", (char *)NULL); /* free volume fraction */ sprintf(buffer,"%f ",freevol/(meshdim[0]*meshdim[1]*meshdim[2])); Tcl_AppendResult(interp, buffer, " ", (char *)NULL); /* hole sizes */ Tcl_AppendResult(interp, "{ ", (char *)NULL); for ( i=0; i<=n_holes; i++ ) { sprintf(buffer,"%d ",holes[i][0]); Tcl_AppendResult(interp, buffer, " ", (char *)NULL); } Tcl_AppendResult(interp, "} ", (char *)NULL); /* hole surfaces */ Tcl_AppendResult(interp, "{ ", (char *)NULL); for ( i=0; i<=n_holes; i++ ) { sprintf(buffer,"%d ",surface[i]); Tcl_AppendResult(interp, buffer, " ", (char *)NULL); } Tcl_AppendResult(interp, "} ", (char *)NULL); /* hole elements */ Tcl_AppendResult(interp, "{ ", (char *)NULL); for ( i=0; i<=n_holes; i++ ) { Tcl_AppendResult(interp, "{ ", (char *)NULL); for ( j=1; j <= holes[i][0]; j++ ) { sprintf(buffer,"%d",holes[i][j]); Tcl_AppendResult(interp, buffer, " ",(char *)NULL); } Tcl_AppendResult(interp, "} ", (char *)NULL); } Tcl_AppendResult(interp, "} ", (char *)NULL); Tcl_AppendResult(interp, "}", (char *)NULL); /* free allocated memory */ realloc_intlist(&mesh, 0); free(surface); for ( i=0; i<=n_holes; i++ ) { free(holes[i]); } free(holes); return (TCL_OK); }
int tclcommand_imd_parse_pos(Tcl_Interp *interp, int argc, char **argv) { enum flag {NONE, UNFOLDED, FOLD_CHAINS}; double shift[3] = {0.0,0.0,0.0}; //double part_selected=n_total_particles; float *coord; int flag = NONE; int i, j; // Determine how many arguments we have and set the value of flag switch (argc) { case 2: flag = NONE; break; case 3: { if (ARG_IS_S(2,"-unfolded")) {flag = UNFOLDED;} else if (ARG_IS_S(2,"-fold_chains")) {flag = FOLD_CHAINS;} else{ Tcl_AppendResult(interp, "wrong flag to",argv[0], " positions: should be \" -fold_chains or -unfolded \"", (char *) NULL); return (TCL_ERROR); } } break; default: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " positions [-flag]\"", (char *) NULL); return (TCL_ERROR); } if (!initsock) { Tcl_AppendResult(interp, "no connection", (char *) NULL); return (TCL_OK); } if (!sock) { if (tclcommand_imd_print_check_connect(interp) == TCL_ERROR) return (TCL_ERROR); /* no VMD is ok, but tell the user */ if (!sock) { Tcl_AppendResult(interp, "no connection", (char *) NULL); return (TCL_OK); } } if (tclcommand_imd_print_drain_socket(interp) == TCL_ERROR) return (TCL_ERROR); /* we do not consider a non connected VMD as error, but tell the user */ if (!sock) { Tcl_AppendResult(interp, "no connection", (char *) NULL); return (TCL_OK); } if (!(vmdsock_selwrite(sock, 60) > 0)) { Tcl_AppendResult(interp, "could not write to IMD socket.", (char *) NULL); return (TCL_ERROR); } if (n_part != max_seen_particle + 1) { Tcl_AppendResult(interp, "for IMD, store particles consecutively starting with 0.", (char *) NULL); return (TCL_ERROR); } updatePartCfg(WITH_BONDS); coord = (float*)Utils::malloc(n_part*3*sizeof(float)); /* sort partcles according to identities */ for (i = 0; i < n_part; i++) { int dummy[3] = {0,0,0}; double tmpCoord[3]; tmpCoord[0] = partCfg[i].r.p[0]; tmpCoord[1] = partCfg[i].r.p[1]; tmpCoord[2] = partCfg[i].r.p[2]; if (flag == NONE) { // perform folding by particle fold_position(tmpCoord, dummy); } j = 3*partCfg[i].p.identity; coord[j ] = tmpCoord[0]; coord[j + 1] = tmpCoord[1]; coord[j + 2] = tmpCoord[2]; } // Use information from the analyse set command to fold chain molecules if ( flag == FOLD_CHAINS ){ if(analyze_fold_molecules(coord, shift ) != TCL_OK){ Tcl_AppendResult(interp, "could not fold chains: \"analyze set chains <chain_start> <n_chains> <chain_length>\" must be used first", (char *) NULL); return (TCL_ERROR); } } if (imd_send_fcoords(sock, n_part, coord)) { Tcl_AppendResult(interp, "could not write to IMD socket.", (char *) NULL); return (TCL_ERROR); } free(coord); Tcl_AppendResult(interp, "connected", (char *) NULL); return (TCL_OK); }
int calc_fluctuations ( double* height_grid, int switch_fluc ) { if (switch_fluc == 1){ STAT_TRACE(fprintf(stderr,"%d,calculating height grid \n",this_node)); } else { if (switch_fluc == 0) { STAT_TRACE(fprintf(stderr,"%d,calculating thickness \n",this_node)); } else { char *errtxt = runtime_error(128); ERROR_SPRINTF(errtxt,"{097 Wrong argument in calc_fluctuations function} "); return -1; } } int i, j, gi, gj; double grid_size[2]; double direction[3]; double refdir[3] = {0,0,1}; double* height_grid_up; double* height_grid_down; int* grid_parts; int* grid_parts_up; int* grid_parts_down; double zreflocal, zref; int nup; int ndown; int nstray; int nrealstray; int l_orient; double norm; int xi, yi; double meanval; int nonzerocnt, gapcnt; if ( xdir + ydir + zdir == -3 ) { char *errtxt = runtime_error(128); ERROR_SPRINTF(errtxt,"{092 attempt to calculate height grid / thickness with uninitialized grid} "); return -1; } if ( height_grid == NULL ) { char *errtxt = runtime_error(128); ERROR_SPRINTF(errtxt,"{093 you must allocate memory for the height grid / thickness first} "); return -1; } /* Allocate memory for height grid / thickness arrays and initialize these arrays */ height_grid_up = (double*) malloc((mode_grid_3d[xdir])*sizeof(double)*mode_grid_3d[ydir]); height_grid_down = (double*) malloc((mode_grid_3d[xdir])*sizeof(double)*mode_grid_3d[ydir]); grid_parts_up = (int*) malloc((mode_grid_3d[xdir])*sizeof(int)*mode_grid_3d[ydir]); grid_parts_down = (int*) malloc((mode_grid_3d[xdir])*sizeof(int)*mode_grid_3d[ydir]); grid_parts = (int*) malloc((mode_grid_3d[xdir])*sizeof(int)*mode_grid_3d[ydir]); for ( i = 0 ; i < mode_grid_3d[xdir] ; i++) { for ( j = 0 ; j < mode_grid_3d[ydir] ; j++) { height_grid[j+i*mode_grid_3d[xdir]] = 0; grid_parts[j+i*mode_grid_3d[xdir]] = 0; height_grid_up[j+i*mode_grid_3d[xdir]] = 0; grid_parts_up[j+i*mode_grid_3d[xdir]] = 0; height_grid_down[j+i*mode_grid_3d[xdir]] = 0; grid_parts_down[j+i*mode_grid_3d[xdir]] = 0; } } /* Calculate physical size of grid mesh */ grid_size[xdir] = box_l[xdir]/(double)mode_grid_3d[xdir]; grid_size[ydir] = box_l[ydir]/(double)mode_grid_3d[ydir]; /* Update particles */ updatePartCfg(WITHOUT_BONDS); //Make sure particles are sorted if (!sortPartCfg()) { char *errtxt = runtime_error(128); ERROR_SPRINTF(errtxt,"{094 could not sort partCfg} "); return -1; } /* Find the mean z position of folded coordinates*/ zref = calc_zref( zdir ); /* Calculate an initial height function of all particles */ for (i = 0 ; i < n_total_particles ; i++) { gi = floor( partCfg[i].r.p[xdir]/grid_size[xdir] ); gj = floor( partCfg[i].r.p[ydir]/grid_size[ydir] ); height_grid[gj + gi*mode_grid_3d[xdir]] += partCfg[i].r.p[zdir]; grid_parts[gj + gi*mode_grid_3d[xdir]] += 1; } /* Normalise the initial height function */ for ( i = 0 ; i < mode_grid_3d[xdir] ; i++) { for ( j = 0 ; j < mode_grid_3d[ydir] ; j++) { if ( grid_parts[j+i*mode_grid_3d[xdir]] > 0 ) { height_grid[j+i*mode_grid_3d[xdir]] = height_grid[j+i*mode_grid_3d[xdir]]/(double)(grid_parts[j+i*mode_grid_3d[xdir]]); } else { height_grid[j+i*mode_grid_3d[xdir]] = zref; } } } /* We now use this initial height function to calculate the lipid_orientation and thereby calculate populations in upper and lower leaflets */ /* Calculate the non normalized height function based on all lipids */ nup = ndown = nstray = nrealstray = 0; for (i = 0 ; i < n_total_particles ; i++) { gi = floor( partCfg[i].r.p[xdir]/grid_size[xdir] ); gj = floor( partCfg[i].r.p[ydir]/grid_size[ydir] ); zreflocal = height_grid[gj+gi*mode_grid_3d[xdir]]; l_orient = lipid_orientation(i,partCfg,zreflocal,direction,refdir); if ( l_orient != LIPID_STRAY && l_orient != REAL_LIPID_STRAY) { if ( l_orient == LIPID_UP ) { nup++; height_grid_up[gj + gi*mode_grid_3d[xdir]] += partCfg[i].r.p[zdir] - zref; grid_parts_up[gj + gi*mode_grid_3d[xdir]] += 1; } else if ( l_orient == LIPID_DOWN ) { ndown++; height_grid_down[gj + gi*mode_grid_3d[xdir]] += partCfg[i].r.p[zdir] - zref; grid_parts_down[gj + gi*mode_grid_3d[xdir]] += 1; } } else { if ( l_orient == REAL_LIPID_STRAY ) { nrealstray++; } } } /* if ( nrealstray > 0 || nstray > 0) { printf("Warning: there were %d stray lipid particles in height calculation \n", nrealstray); } printf(" Lipid particles up = %d , Lipid particles down = %d \n",nup, ndown); */ STAT_TRACE(fprintf(stderr,"%d, Lipids up = %d , Lipids down = %d \n",this_node, nup, ndown)); /* Reinitialise the height grid */ for ( i = 0 ; i < mode_grid_3d[xdir] ; i++) { for ( j = 0 ; j < mode_grid_3d[ydir] ; j++) { height_grid[j+i*mode_grid_3d[xdir]] = 0.0; grid_parts[j+i*mode_grid_3d[xdir]] = 0; } } /* Norm we normalize the height function according the number of points in each grid cell */ norm = 1.0; for ( i = 0 ; i < mode_grid_3d[xdir] ; i++) { for ( j = 0 ; j < mode_grid_3d[ydir] ; j++) { if ( ( grid_parts_up[j + i*mode_grid_3d[xdir]] > 0 ) && ( grid_parts_down[j + i*mode_grid_3d[xdir]] > 0 ) ) { /* This is where we distinguish between height_grid and thickness: h = .5*(h_up + h_down) t = h_up - h_down */ if (switch_fluc == 1) height_grid[j+i*mode_grid_3d[xdir]] = 0.5*norm*((height_grid_up[j+i*mode_grid_3d[xdir]])/(double)(grid_parts_up[j + i*mode_grid_3d[xdir]]) + (height_grid_down[j+i*mode_grid_3d[xdir]])/(double)(grid_parts_down[j + i*mode_grid_3d[xdir]])); else height_grid[j+i*mode_grid_3d[xdir]] = norm*((height_grid_up[j+i*mode_grid_3d[xdir]])/(double)(grid_parts_up[j + i*mode_grid_3d[xdir]]) - (height_grid_down[j+i*mode_grid_3d[xdir]])/(double)(grid_parts_down[j + i*mode_grid_3d[xdir]])); grid_parts[j+i*mode_grid_3d[xdir]] = grid_parts_up[j + i*mode_grid_3d[xdir]] + grid_parts_down[j + i*mode_grid_3d[xdir]]; } else { // Either upper or lower layer has no lipids height_grid[j+i*mode_grid_3d[xdir]] = 0.0; grid_parts[j+i*mode_grid_3d[xdir]] = 0; } } } /* Check height grid for zero values and substitute mean of surrounding cells */ gapcnt = 0; for ( i = 0 ; i < mode_grid_3d[xdir] ; i++) { for ( j = 0 ; j < mode_grid_3d[ydir] ; j++) { if ( grid_parts[j + i*mode_grid_3d[xdir]] == 0) { meanval = 0.0; nonzerocnt = 0; for ( xi = (i-1) ; xi <= (i+1) ; xi++) { for ( yi = (j-1) ; yi <= (j+1) ; yi++) { if ( height_grid[yi+xi*mode_grid_3d[xdir]] != 0 ) { meanval += height_grid[yi+xi*mode_grid_3d[xdir]]; nonzerocnt++; } } } if ( nonzerocnt == 0 ) { char *errtxt = runtime_error(128); ERROR_SPRINTF(errtxt,"{095 hole in membrane} "); return -1; } gapcnt++; } } } if ( gapcnt != 0 ) { fprintf(stderr,"Warning: %d, gridpoints with no particles \n",gapcnt); fflush(stdout); } free(grid_parts); free(height_grid_up); free(height_grid_down); free(grid_parts_up); free(grid_parts_down); return 1; }
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; }
int tclcommand_analyze_parse_and_print_dipmom_mol(Tcl_Interp *interp,int argc, char **argv) { #ifndef ELECTROSTATICS Tcl_ResetResult(interp); Tcl_AppendResult(interp, "calc_dipole_mol is not possible without ELECTROSTATICS", (char *)NULL); return (TCL_ERROR); #else int k,type; char buffer[TCL_DOUBLE_SPACE]; double dipole[4]; updatePartCfg(WITHOUT_BONDS); if (!sortPartCfg()) { char *errtxt = runtime_error(128); ERROR_SPRINTF(errtxt, "{059 parse_and_print_dipole: could not sort particle config, particle ids not consecutive?} "); return TCL_ERROR; } if (n_molecules==0) { Tcl_ResetResult(interp); Tcl_AppendResult(interp, "No molecules defined !", (char *)NULL); return (TCL_ERROR); } if (argc < 2) { Tcl_ResetResult(interp); Tcl_AppendResult(interp, "usage: analyze parse_and_print_dipole_mol <type>", (char *)NULL); return (TCL_ERROR); } if (!ARG1_IS_I(type)) { Tcl_ResetResult(interp); Tcl_AppendResult(interp, "usage: analyze parse_and_print_dipole_mol <type>", (char *)NULL); return (TCL_ERROR); } if (ARG0_IS_S("total")){ calc_total_dipolmoment_mol(type,dipole); sprintf(buffer,"%i ",type); Tcl_AppendResult(interp,"{ dipolemoment_mol total ",buffer,(char *)NULL); for (k=0;k<3;k++) { sprintf(buffer,"%e ",dipole[k]); Tcl_AppendResult(interp, buffer,(char *)NULL); } sprintf(buffer,"%e",dipole[3]); Tcl_AppendResult(interp,buffer,"}",(char *)NULL); } else if (ARG0_IS_S("absolute")){ calc_absolute_dipolmoment_mol(type,dipole); sprintf(buffer,"%i ",type); Tcl_AppendResult(interp,"{ dipolemoment_mol absolute ",buffer,(char *)NULL); sprintf(buffer,"%e ",dipole[0]); Tcl_AppendResult(interp, buffer,(char *)NULL); sprintf(buffer,"%e",dipole[1]); Tcl_AppendResult(interp,buffer,"}",(char *)NULL); } else { Tcl_ResetResult(interp); Tcl_AppendResult(interp, "Feature not implemented", (char *)NULL); return (TCL_ERROR); } argc-=2; argv+=2; return TCL_OK; #endif }