int mindist3(int part_id, double r_catch, int *ids) { Particle *partCfgMD; double dx,dy,dz; int i, me, caught=0; partCfgMD = (Particle*)malloc(n_part*sizeof(Particle)); mpi_get_particles(partCfgMD, NULL); me = -1; /* Since 'mpi_get_particles' returns the particles unsorted, it's most likely that 'partCfgMD[i].p.identity != i' --> prevent that! */ for(i=0; i<n_part; i++) if (partCfgMD[i].p.identity == part_id) me = i; if (me == -1) { ostringstream msg; msg <<"failed to find desired particle " << part_id; runtimeError(msg); return 0; } for (i=0; i<n_part; i++) { if (i != me) { dx = partCfgMD[me].r.p[0] - partCfgMD[i].r.p[0]; dx -= dround(dx/box_l[0])*box_l[0]; dy = partCfgMD[me].r.p[1] - partCfgMD[i].r.p[1]; dy -= dround(dy/box_l[1])*box_l[1]; dz = partCfgMD[me].r.p[2] - partCfgMD[i].r.p[2]; dz -= dround(dz/box_l[2])*box_l[2]; if (sqrt(SQR(dx)+SQR(dy)+SQR(dz)) < r_catch) ids[caught++]=partCfgMD[i].p.identity; } } free(partCfgMD); return (caught); }
void ion_to_cylinder_r(double** xyz,double* Q, int pndx, double* fx, double* fy) { double rpi2=0; double dpix=0; double dpiy=0; for (int t1=0;t1<NP;t1++) { dpix=pxy[pndx][0]-xyz[t1][0]; dpix-=dround(dpix/Ls[0])*Ls[0]; dpiy=pxy[pndx][1]-xyz[t1][1]; dpiy-=dround(dpiy/Ls[1])*Ls[1]; rpi2=(SQR(dpix)+SQR(dpiy)); //e1(x)=-ei(-x) if (rpi2<=rmax2) { *fx+=2*Q[t1]*prefactor*taus[pndx]*exp(-SQR(alpha)*(rpi2))*(dpix/rpi2); *fy+=2*Q[t1]*prefactor*taus[pndx]*exp(-SQR(alpha)*(rpi2))*(dpiy/rpi2); //*fx+=Q[t1]*prefactor*taus[pndx]*dpix/(rpi2)*(exp(-SQR(alpha)*(rpi2))*2*alpha/sqrt(PI)+erfc(alpha*sqrt(rpi2))/sqrt(rpi2)); //*fy+=Q[t1]*prefactor*taus[pndx]*dpiy/(rpi2)*(exp(-SQR(alpha)*(rpi2))*2*alpha/sqrt(PI)+erfc(alpha*sqrt(rpi2))/sqrt(rpi2)); } } }
//-------------------------------------------------------------------- int update_ionpress(int Npol, int Nions,double* Qs, double** xyz, double* rpol, double** polcoord, double* rions,int*** press_extrap,double* box, int setzero) { double dr[]={0.01,0.015,0.02,0.025,0.03,0.035,0.04,0.045,0.05,0.055,0.06,0.065,0.07,0.075,0.08, 0.085, 0.09, 0.095, 0.1,0.105,0.11,0.115,0.12, 0.125,0.130}; double dx=0; double dy=0; double r2=0; double r=0; double angle=0; if (setzero==1) { for (int i=0;i<Npol;i++) for (int j=0;j<ANGLEBINS;j++) for (int k=0;k<50;k++) press_extrap[i][j][k]=0; return 1; } else { for (int i=0;i<Npol;i++) { //Note, distance not corrected with hard sphere radius, convenient for ploting // Angle wrt positive x-axis (1,0,0) for (int j=0;j<Nions; j++) { dx = xyz[j][0] - polcoord[i][0]; dx -= dround(dx/box[0])*box[0]; dy = xyz[j][1] - polcoord[i][1]; dy -= dround(dy/box[1])*box[1]; r2 = SQR(dx) + SQR(dy); r=sqrt(r2); //going through quadrats of coordinate system, scaling acos 0,pi->0,2pi angle=acos(dx/r); if (dx>0 && dy<0) angle=2*PI-angle; else if (dx<0 && dy<0) angle=(PI-angle)+PI; for (int k=0;k<25;k++) { if (Qs[j]>0 && r<rions[0]+rpol[i]+dr[k]) press_extrap[i][(int)(angle/(2*PI)*ANGLEBINS)][k]++; if (Qs[j]<0 && r<rions[1]+rpol[i]+dr[k]) press_extrap[i][(int)(angle/(2*PI)*ANGLEBINS)][k+25]++; } } } return 0; } }
double buf_mindist4(double pos[3], int n_add, double *add) { double mindist=30000.0, dx,dy,dz; int i; if (n_add == 0) return (dmin(dmin(box_l[0],box_l[1]),box_l[2])); for (i=0; i<n_add; i++) { dx = pos[0] - add[3*i + 0]; dx -= dround(dx/box_l[0])*box_l[0]; dy = pos[1] - add[3*i + 1]; dy -= dround(dy/box_l[1])*box_l[1]; dz = pos[2] - add[3*i + 2]; dz -= dround(dz/box_l[2])*box_l[2]; mindist = dmin(mindist, SQR(dx)+SQR(dy)+SQR(dz)); } if (mindist<30000.0) return (sqrt(mindist)); return (-1.0); }
int overlap_pol(double px, double py, double x, double y, double rpol, double r_ion, double* box) { double dx=x-px; double dy=y-py; dx -= dround(dx/box[0])*box[0]; dy -= dround(dy/box[1])*box[1]; int temp=0; if (sqrt((dy)*(dy)+(dx)*(dx))<(r_ion+rpol)) temp=1; return temp; }
void Lattice::set_data_for_global_position_with_periodic_image(double* pos, void* data) { index_t replica[3]; index_t global_index[3]; index_t halo_index[3]; for (int i = 0; i<3; i++) { global_index[i] = (int)dround((pos[i]-this->offset[i])/this->agrid[i]); } for (int i=-this->halo_size; i<=this->halo_size; i++) { for (int j=-this->halo_size; j<=this->halo_size; j++) { for (int k=-this->halo_size; k<=this->halo_size; k++) { replica[0]=global_index[0]+i*this->global_grid[0]; replica[1]=global_index[1]+j*this->global_grid[1]; replica[2]=global_index[2]+k*this->global_grid[2]; if (map_global_index_to_halo_index(replica, halo_index)) { set_data_for_local_halo_grid_index(halo_index, data); } } } } }
int Lattice::global_pos_to_lattice_halo_index(double* pos, index_t* ind) { for (int i = 0; i<3; i++) { ind[i] = (int)dround((pos[i]-this->local_offset[i])/this->agrid[i])+this->halo_size; if (ind[i] < 0 || ind[i] >= this->halo_grid[i]) return 0; } return 1; }
int overlap_ion(int Np, double** xyz, int move_ndx, double* rions, double* Qs, double x, double y, double z, double* box) { int moved_ion_type; int ion_type; double dx; double dy; double dz; /*printf("box %lf %lf %lf\n", box[0],box[1],box[2]); printf("rions %lf %lf\n", rions[0],rions[1]); printf("Np %d", Np);*/ if (Qs[move_ndx]>0) moved_ion_type=0; else moved_ion_type=1; for (int i=0;i<Np;i++) { if (Qs[i]>0) ion_type=0; else ion_type=1; //printf("distance %lf limit %lf\n", SQR(xyz[i][0]-xyz[move_ndx][0])+SQR(xyz[i][1]-xyz[move_ndx][1])+SQR(xyz[i][2]-xyz[move_ndx][2]),SQR(rions[ion_type]+rions[moved_ion_type])); //printf("x %lf y %lf z %lf\n", xyz[i][0], xyz[i][1],xyz[i][2]); dx=xyz[i][0]-x; dy=xyz[i][1]-y; dz=xyz[i][2]-z; dx -= dround(dx/box[0])*box[0]; dy -= dround(dy/box[1])*box[1]; dz -= dround(dz/box[2])*box[2]; if (move_ndx!=i && (SQR(dx)+SQR(dy)+SQR(dz)<SQR(rions[ion_type]+rions[moved_ion_type]))) { return 1; } } return 0; }
double Ewald_r_space_part_line(double** xyz, double *Q, double *MCcoord, double MCQ, int MCion) { int t2; double dx,dy,dz,r,r2,ar, dpix, dpiy, rpi2; double d1,d2,d3=0.0; double d3_ci=0; //cylinder-ion contribution for (int l=0;l<Npol;l++) { dpix=pxy[l][0]-MCcoord[0]; dpix-=dround(dpix/Ls[0])*Ls[0]; dpiy=pxy[l][1]-MCcoord[1]; dpiy-=dround(dpiy/Ls[1])*Ls[1]; rpi2=(SQR(dpix)+SQR(dpiy)); if (rpi2<=rmax2) d3_ci-= MCQ*prefactor*taus[l]*Exponential_Integral_Ei(-SQR(alpha)*(rpi2)); } for (t2 = 0; t2<NP; t2++) { if ( t2 != MCion ) { dx = MCcoord[0] - xyz[t2][0]; dx -= dround(dx/Ls[0])*Ls[0]; dy = MCcoord[1] - xyz[t2][1]; dy -= dround(dy/Ls[1])*Ls[1]; dz = MCcoord[2] - xyz[t2][2]; dz -= dround(dz/Ls[2])*Ls[2]; r2 = SQR(dx) + SQR(dy) + SQR(dz); if (r2 <= rmax2) { ar = alpha * (r = sqrt(r2)); d3 += ( d2 = (d1 = MCQ * Q[t2] * prefactor) * erfc(ar) / r ); } } } return d3+d3_ci; // return d3; }
double mindist4(double pos[3]) { Particle *partCfgMD; double mindist=30000.0, dx,dy,dz; int i; if (n_part ==0) return (dmin(dmin(box_l[0],box_l[1]),box_l[2])); partCfgMD = (Particle*)malloc(n_part*sizeof(Particle)); mpi_get_particles(partCfgMD, NULL); for (i=0; i<n_part; i++) { dx = pos[0] - partCfgMD[i].r.p[0]; dx -= dround(dx/box_l[0])*box_l[0]; dy = pos[1] - partCfgMD[i].r.p[1]; dy -= dround(dy/box_l[1])*box_l[1]; dz = pos[2] - partCfgMD[i].r.p[2]; dz -= dround(dz/box_l[2])*box_l[2]; mindist = dmin(mindist, SQR(dx)+SQR(dy)+SQR(dz)); } free(partCfgMD); if (mindist<30000.0) return (sqrt(mindist)); return (-1.0); }
double vrelaxQuality(TVertex* v0, TVertex* v1,TVertex* v2,TVertex* v3) { double qlty , // Calculo el volumen x21,y21,z21,x31,y31,z31,x41,y41,z41 , d1,d2,d3,vol , // Calculo la calidad dx,dy,dz , maxleng2, leng2 ; float4 p1,p2,p3, p4 ; p1 = v0->fPos; p2 = v1->fPos; p3 = v2->fPos; p4 = v3->fPos; x21 = p2.x-p1.x; y21 = p2.y-p1.y; z21 = p2.z-p1.z; x31 = p3.x-p1.x; y31 = p3.y-p1.y; z31 = p3.z-p1.z; x41 = p4.x-p1.x; y41 = p4.y-p1.y; z41 = p4.z-p1.z; d1 = y31*z41 - z31*y41; d2 = y41*z21 - z41*y21; d3 = y21*z31 - z21*y31; vol = (x21 * d1 + x31 * d2 + x41 * d3) / 6.0; qlty = vol; dx = p2.x-p1.x; dy = p2.y-p1.y; dz = p2.z-p1.z; maxleng2=dx*dx+dy*dy+dz*dz; dx = p3.x-p1.x; dy = p3.y-p1.y; dz = p3.z-p1.z; leng2=dx*dx+dy*dy+dz*dz; if(leng2 > maxleng2) maxleng2=leng2; dx = p4.x-p1.x; dy = p4.y-p1.y; dz = p4.z-p1.z; leng2=dx*dx+dy*dy+dz*dz; if(leng2 > maxleng2) maxleng2=leng2; dx = p3.x-p2.x; dy = p3.y-p2.y; dz = p3.z-p2.z; leng2=dx*dx+dy*dy+dz*dz; if(leng2 > maxleng2) maxleng2=leng2; dx = p4.x-p2.x; dy = p4.y-p2.y; dz = p4.z-p2.z; leng2=dx*dx+dy*dy+dz*dz; if(leng2 > maxleng2) maxleng2=leng2; dx = p4.x-p3.x; dy = p4.y-p3.y; dz = p4.z-p3.z; leng2=dx*dx+dy*dy+dz*dz; if(leng2 > maxleng2) maxleng2=leng2; if (vol>0) qlty =(vol*(vol))/(maxleng2*maxleng2*maxleng2); else qlty =(vol*(-vol))/(maxleng2*maxleng2*maxleng2); int iqlty =dround( qlty * PRECISSION); //return qlty; return 72.0 * ( (double)(iqlty)/(double)(PRECISSION)); //calcula fast quality }
void *subRound(void *hnd, c4snet_data_t *sd, c4snet_data_t*sk, int c, int size) { char *D = (char*) C4SNetGetData(sd); char *K = (char *) C4SNetGetData(sk); int i; for (i = 0; i < size; i++) { dround(&D[i * 8], &K[i * 7], c); } c++; C4SNetOut(hnd, 1, sd, sk, c, size); return hnd; }
//int Lattice::init(double *agrid, double* offset, int halo_size, size_t dim) { int Lattice::init(double *agrid, double* offset, int halo_size, size_t dim) { this->dim=dim; /* determine the number of local lattice nodes */ for (int d=0; d<3; d++) { this->agrid[d] = agrid[d]; this->global_grid[d] = (int)dround(box_l[d]/agrid[d]); this->offset[d]=offset[d]; this->local_index_offset[d]=(int) ceil((my_left[d]-this->offset[d])/this->agrid[d]); this->local_offset[d] = this->offset[d] + this->local_index_offset[d]*this->agrid[d]; this->grid[d] = (int) ceil ( ( my_right[d] - this->local_offset[d]-ROUND_ERROR_PREC ) / this->agrid[d]); } // sanity checks for (int dir=0;dir<3;dir++) { // check if local_box_l is compatible with lattice spacing if (fabs(local_box_l[dir]-this->grid[dir]*agrid[dir]) > ROUND_ERROR_PREC*box_l[dir]) { char *errtxt = runtime_error(256); ERROR_SPRINTF(errtxt, \ "{097 Lattice spacing agrid[%d]=%f " \ "is incompatible with local_box_l[%d]=%f " \ "(box_l[%d]=%f node_grid[%d]=%d)} ", \ dir, agrid[dir], \ dir, local_box_l[dir], \ dir, box_l[dir], \ dir, node_grid[dir]); } } this->element_size = this->dim*sizeof(double); LATTICE_TRACE(fprintf(stderr,"%d: box_l (%.3f,%.3f,%.3f) grid (%d,%d,%d) node_neighbors (%d,%d,%d,%d,%d,%d)\n",this_node,local_box_l[0],local_box_l[1],local_box_l[2],this->grid[0],this->grid[1],this->grid[2],node_neighbors[0],node_neighbors[1],node_neighbors[2],node_neighbors[3],node_neighbors[4],node_neighbors[5])); this->halo_size = halo_size; /* determine the number of total nodes including halo */ this->halo_grid[0] = this->grid[0] + 2*halo_size ; this->halo_grid[1] = this->grid[1] + 2*halo_size ; this->halo_grid[2] = this->grid[2] + 2*halo_size ; this->grid_volume = this->grid[0]*this->grid[1]*this->grid[2] ; this->halo_grid_volume = this->halo_grid[0]*this->halo_grid[1]*this->halo_grid[2] ; this->halo_grid_surface = this->halo_grid_volume - this->grid_volume ; this->halo_offset = get_linear_index(halo_size,halo_size,halo_size,this->halo_grid) ; this->interpolation_type = INTERPOLATION_LINEAR; allocate_memory(); return ES_OK; }
//The original ewald function for testing double Ewald_r_space(double** xyz, double *Q, double** F) { int t1,t2; double dx,dy,dz,r,r2,ar,ar2; double d1,d2,d3=0.0,d4; double Li=1/Ls[0]; double Ltmp=Ls[0]; //printf("L %lf Li %lf pre %lf rmax2 %lf\n", Ltmp,Li, prefactor, rmax2); static double wupi = 1.77245385090551602729816748334; for (t1 = 0; t1 < NP-1; t1++) /* Quick and Dirty N^2 loop */ for (t2 = t1 + 1; t2<NP; t2++) { dx = xyz[t1][0] - xyz[t2][0]; dx -= dround(dx*Li)*Ltmp; dy = xyz[t1][1] - xyz[t2][1]; dy -= dround(dy*Li)*Ltmp; dz = xyz[t1][2] - xyz[t2][2]; dz -= dround(dz*Li)*Ltmp; r2 = SQR(dx) + SQR(dy) + SQR(dz); /* printf("%d %d %le \n",t1+1,t2+1,sqrt(r2));*/ /* printf("%d %d %le %le\n",t1+1,t2+1,r2,rmax2);*/ if (r2 <= rmax2) { //printf("Forces"); ar2 = SQR(ar = alpha * (r = sqrt(r2))); d3 += ( d2 = (d1 = Q[t1] * Q[t2] * prefactor) * erfc(ar) / r ); printf("alpha %lf t1 %d t2 %d ar2 %lf d3 %lf\n", alpha, t1,t2,ar2,d3); if (F) { /* if forces should be computed... */ d4 = ( d2 + d1*2.0*alpha*exp(-ar2)/wupi) / r2; F[t1][0] += d4*dx; F[t1][1] += d4*dy; F[t1][2] += d4*dz; F[t2][0] -= d4*dx; F[t2][1] -= d4*dy; F[t2][2] -= d4*dz; } } } return d3; }
static int proc_line(struct prln_ctx_s ctx, char *line, size_t llen) { struct dt_dt_s d; char *sp = NULL; char *ep = NULL; int rc = 0; do { /* check if line matches, */ d = dt_io_find_strpdt2( line, llen, ctx.ndl, &sp, &ep, ctx.fromz); if (!dt_unk_p(d)) { if (UNLIKELY(d.fix) && !ctx.quietp) { rc = 2; } /* perform addition now */ d = dround(d, ctx.st->durs, ctx.st->ndurs, ctx.nextp); if (ctx.hackz == NULL && ctx.fromz != NULL) { /* fixup zone */ d = dtz_forgetz(d, ctx.fromz); } if (ctx.sed_mode_p) { __io_write(line, sp - line, stdout); dt_io_write(d, ctx.ofmt, ctx.outz, '\0'); llen -= (ep - line); line = ep; } else { dt_io_write(d, ctx.ofmt, ctx.outz, '\n'); break; } } else if (ctx.sed_mode_p) { line[llen] = '\n'; __io_write(line, llen + 1, stdout); break; } else { /* obviously unmatched, warn about it in non -q mode */ if (!ctx.quietp) { dt_io_warn_strpdt(line); rc = 2; } break; } } while (1); return rc; }
main(int argc, char *argv[]) { double f, lf; char *dummy; while (--argc) { f = strtod((const char *)(*(++argv)), &dummy); if (0.0 == f) { puts("0! = 0"); continue; } if (-1.0 == (lf = log10factorial(f))) { printf(">>> ERROR: %g! is not a valid expression\n", f); continue; } if (171.0 > f) printf("%.14g! = %.14g\n", f, pow(10.0, lf)); else { printf("%.14g! = %.14ge+%ld\n", f, pow(10.0, dfrac(lf)), (long)dround(lf)); } } lf = log10C(1000000L,750000L); printf("\nJust to dazzle with you with big numbers:\n" "C(1000000,750000) = %.14ge+%ld\n", pow(10.0, dfrac(lf)), (long)dround(lf)); lf = log10P(1000000L,750000L); printf("\n...once more:\n" "P(1000000,750000) = %.14ge+%ld\n", pow(10.0, dfrac(lf)), (long)dround(lf)); return EXIT_SUCCESS; }
int main( int argc, char **argv ) { if( argc < 3 ) { std::cout << "usage: " << argv[0] << " test.stl test.res" << std::endl; return 100; } int rez = 0; try { Mesh m; m.load( argv[1] ); std::ifstream res( argv[2] ); for( double z = m.min().z(); z <= m.max().z(); z+=0.5 ) { std::ostringstream os; os << "z=" << dround( z ); auto p = m.slice( z ); for( const auto &pl : p ) { os << " polygon: ["; for( const auto &pt : pl ) os << pt; os << "]"; } std::string sres; if( !std::getline( res, sres ) ) throw std::runtime_error( "unexpected end of result file" ); if( os.str() != sres ) { std::cerr << "error: expected \"" << sres << "\"" << std::endl; std::cerr << " got \"" << os.str() << "\"" << std::endl; rez = 102; } } } catch( const std::exception &ex ) { std::cerr << "error: " << ex.what() << std::endl; return 101; } return rez; }
/** Calculates the dihedral angle between particle quadruple p1, p2, p3 and p4. The dihedral angle is the angle between the planes specified by the particle triples (p1,p2,p3) and (p2,p3,p4). Vectors a, b and c are the bond vectors between consequtive particles. If the a,b or b,c are parallel the dihedral angle is not defined in which case the routine returns phi=-1. Calling functions should check for that (Written by: Arijit Maitra) */ inline void calc_dihedral_angle(Particle *p1, Particle *p2, Particle *p3, Particle *p4, double a[3], double b[3], double c[3], double aXb[3], double *l_aXb, double bXc[3], double *l_bXc, double *cosphi, double *phi) { int i; get_mi_vector(a, p2->r.p, p1->r.p); get_mi_vector(b, p3->r.p, p2->r.p); get_mi_vector(c, p4->r.p, p3->r.p); /* calculate vector product a X b and b X c */ vector_product(a, b, aXb); vector_product(b, c, bXc); /* calculate the unit vectors */ *l_aXb = sqrt(sqrlen(aXb)); *l_bXc = sqrt(sqrlen(bXc)); /* catch case of undefined dihedral angle */ if ( *l_aXb <= TINY_LENGTH_VALUE || *l_bXc <= TINY_LENGTH_VALUE ) { *phi = -1.0; *cosphi = 0; return;} for (i=0;i<3;i++) { aXb[i] /= *l_aXb; bXc[i] /= *l_bXc; } *cosphi = scalar(aXb, bXc); if ( fabs(fabs(*cosphi)-1) < TINY_SIN_VALUE ) *cosphi = dround(*cosphi); /* Calculate dihedral angle */ *phi = acos(*cosphi); if( scalar(aXb, c) < 0.0 ) *phi = (2.0*PI) - *phi; }
/*----------------------------------------------------------------------*/ double Ewald_r_space_line_parts(double** xyz, double *Q, double* e_ii, double* e_pi, double* e_pp) { int t1,t2; double dx,dy,dz,r,r2,ar, dpix, dpiy; double d1,d2,d3=0.0, d3_ci=0, d3_cc=0; double rpi2=0; for (t1 = 0; t1 < NP-1; t1++) /* Quick and Dirty N^2 loop */ { //cylinder-ion contribution for (int l=0;l<Npol;l++) { dpix=pxy[l][0]-xyz[t1][0]; dpix-=dround(dpix/Ls[0])*Ls[0]; dpiy=pxy[l][1]-xyz[t1][1]; dpiy-=dround(dpiy/Ls[1])*Ls[1]; rpi2=(SQR(dpix)+SQR(dpiy)); //e1(x)=-ei(-x) if (rpi2<=rmax2) d3_ci-= Q[t1]*prefactor*taus[l]*Exponential_Integral_Ei(-SQR(alpha)*(rpi2)); } for (t2 = t1 + 1; t2<NP; t2++) { dx = xyz[t1][0] - xyz[t2][0]; dx -= dround(dx/Ls[0])*Ls[0]; dy = xyz[t1][1] - xyz[t2][1]; dy -= dround(dy/Ls[1])*Ls[1]; dz = xyz[t1][2] - xyz[t2][2]; dz -= dround(dz/Ls[2])*Ls[2]; r2 = SQR(dx) + SQR(dy) + SQR(dz); /* printf("%d %d %le \n",t1+1,t2+1,sqrt(r2));*/ /* printf("%d %d %le %le\n",t1+1,t2+1,r2,rmax2);*/ if (r2 <= rmax2) { //printf("Forces"); ar = alpha * (r = sqrt(r2)); d3 += ( d2 = (d1 = Q[t1] * Q[t2] * prefactor) * erfc(ar) / r ); } } } //final ion, look at the loop indices t1=NP-1; for (int l=0;l<Npol;l++) { dpix=pxy[l][0]-xyz[t1][0]; dpix-=dround(dpix/Ls[0])*Ls[0]; dpiy=pxy[l][1]-xyz[t1][1]; dpiy-=dround(dpiy/Ls[1])*Ls[1]; rpi2=(SQR(dpix)+SQR(dpiy)); //e1(x)=-ei(-x) if (rpi2<=rmax2) d3_ci-= Q[t1]*prefactor*taus[l]*Exponential_Integral_Ei(-SQR(alpha)*(rpi2)); } //cylinder-cylinder as a function of their separation //should there be a cutoff here too, think about periodicity, will they always be l/2? if (Npol==2) d3_cc=-prefactor*taus[1]*taus[0]*Ls[2]*Exponential_Integral_Ei(-SQR(alpha)*(SQR(pxy[1][0]-pxy[0][0])+SQR(pxy[1][1]-pxy[0][1]))); printf("real d3 %lf d3_ci %lf d3_cc %lf\n", d3,d3_ci,d3_cc); *e_ii=d3; *e_pi=d3_ci; *e_pp=d3_cc; return d3+d3_ci+d3_cc; //return d3; }
/*-------------------------------------------------------------------------------------------------------*/ void update_verlet (void) { // define necessary variables: i, j and temporary position variables, double xi, yi, xj, yj; double dx, dy, sig_y; double r_squared; // count how many values there are in the list int k; // iterate over all particles, read positions for (int i=0; i<N; i++) { xi = position[2*i]; yi = position[2*i+1]; // save the amount of neighbors to particle i in k k = 0; for (int j=0; j<N; j+=2) { // ignore entry where particle i itself is inspected if (i == j) continue; // get the position of particle j xj = position[2*j]; yj = position[2*j+1]; // get the distance between both particles dx = xi - xj; dy = yi - yj; // alter dx, this accounts for Lees-Edwards conditions sig_y = dround(dy*Li); dx += sig_y * box_A; // find images through altering dx and dy dx -= dround(dx*Li)*L; dy -= sig_y * L; // find out squared distance and check against the verlet cutoff r_squared = dx*dx + dy*dy; // squaring is a strict monotonous function, thus we can check with the squares of the values (saves N*N sqrt()-calls) if(cutoff_squared >= r_squared) { // check whether there is enough space in the verlet list if (k == N_Verlet -1) { fprintf(stderr, "Verlet list is too short!!\n"); fprintf(stderr, "N: %d, N_Verlet: %d, k: %d\n", N, N_Verlet, k); exit(EXIT_FAILURE); } // add neighbor and signums into verlet and sign list verlet[N_Verlet*i+k] = j; k++; } } for (int j=1; j<N; j+=2) { // ignore entry where particle i itself is inspected if (i == j) continue; // get the position of particle j xj = position[2*j]; yj = position[2*j+1]; // get the distance between both particles dx = xi - xj; dy = yi - yj; // alter dx, this accounts for Lees-Edwards conditions sig_y = dround(dy*Li); dx += sig_y * box_B; // find images through altering dx and dy dx -= dround(dx*Li)*L; dy -= sig_y * L; // find out squared distance and check against the verlet cutoff r_squared = dx*dx + dy*dy; // squaring is a strict monotonous function, thus we can check with the squares of the values (saves N*N sqrt()-calls) if(cutoff_squared >= r_squared) { // check whether there is enough space in the verlet list if (k == N_Verlet -1) { fprintf(stderr, "Verlet list is too short!!\n"); fprintf(stderr, "N: %d, N_Verlet: %d, k: %d\n", N, N_Verlet, k); exit(EXIT_FAILURE); } // add neighbor and signums into verlet and sign list verlet[N_Verlet*i+k] = j; k++; } } // edit last entry of row, here we store how many neighbors particle i has, and reset distance counting vector verlet[N_Verlet*(i+1)-1] = k; verlet_distance[2*i] = 0; verlet_distance[2*i+1] = 0; } // reset thread specific verlet counter for (int i=0; i<thread_number; i++) { verlet_max[2*i] = 0; verlet_max[2*i+1] = 0; } }
/*-------------------------------------------------------------------------------------------------------*/ static void *iteration (int *no) { // Define necessary variables double xi, xj, yi, yj; double dx, dy, sig_y; double r_squared; double temp_force; double temp; double u1, u2, g1, g2; int min = borders[*no]; int max = borders[*no+1]; int iterate; int j; double m_i_one; double m_i_two; double weigh_brown_one; double weigh_brown_two; double D_kT_one; double D_kT_two; double shear_one; double shear_two; double* box_one; double* box_two; double m_j; if (min%2 == 0){ // get the relation of all even values, this is basically the interaction relation this particle will have with other particles m_i_one = 1.0; m_i_two = m; // set the appropriate diffusion parameters according to index of particle weigh_brown_one = weigh_brown_A; weigh_brown_two = weigh_brown_B; D_kT_one = D_Brown_A/kT; D_kT_two = D_Brown_B/kT; // assign the right box displacement parameter box_one = &box_A; box_two = &box_B; // shear_one = v_s / (D_kT_one * L) * delta_t; // shear_two = v_s / (D_kT_two * L) * delta_t; shear_one = v_A / (L) * delta_t; shear_two = v_B / (L) * delta_t; } else { // get the relation of all even values, this is basically the interaction relation this particle will have with other particles m_i_one = m; m_i_two = 1.0; // set the appropriate diffusion parameters according to index of particle weigh_brown_one = weigh_brown_B; weigh_brown_two = weigh_brown_A; D_kT_one = D_Brown_B/kT; D_kT_two = D_Brown_A/kT; // assign the right box displacement parameter box_one = &box_B; box_two = &box_A; // shear_one = v_s / (D_kT_one * L) * delta_t; // shear_two = v_s / (D_kT_two * L) * delta_t; shear_one = v_B / (L) * delta_t; shear_two = v_A / (L) * delta_t; } // let the simulation run until the thread is terminated while(cont == 1) { // iterate 2D-forces over all particles A in Verlet-List for (int i=min; i<max; i+=2) { // get the position of the current particle xi = position[2*i]; yi = position[2*i+1]; // initiate forces for this round force[2*i] = 0; force[2*i+1] = 0; // get the amount of particles we have to iterate iterate = verlet[N_Verlet*(i+1)-1]; // iterate to number given in last entry of i in Verlet-List for (int k=0; k<iterate; k+=1) { // get the next particle and it's position within the root box j = verlet[N_Verlet*i+k]; xj = position[2*j]; yj = position[2*j+1]; // assign the appropriate interaction relation to the particle, depending whether it has even or uneven index m_j = (j%2)*m + (j+1)%2; // Get the distance between both particles dx = xi - xj; dy = yi - yj; // alter dx, this accounts for Lees-Edwards conditions sig_y = dround(dy*Li); dx += sig_y * (*box_one); // find images through altering dx and dy dx -= dround(dx*Li)*L; dy -= sig_y * L; // get square of distance and compute force in x and y direction r_squared = dx*dx + dy*dy; temp_force = (m_i_one*m_j/sqrt(r_squared))*(3*Gamma_A/(r_squared*r_squared)-force_cutoff); // WARNING: this is F/r force[2*i] += temp_force*dx; // equals F*x/r = F*cos(phi) (x-component) force[2*i+1] += temp_force*dy; // equals F*y/r = F*sin(phi) (y-component) } } // iterate 2D-forces over all particles B in Verlet-List for (int i=min+1; i<max; i+=2) { // get the position of the current particle xi = position[2*i]; yi = position[2*i+1]; // initiate forces for this round force[2*i] = 0; force[2*i+1] = 0; // get the amount of particles we have to iterate iterate = verlet[N_Verlet*(i+1)-1]; // iterate to number given in last entry of i in Verlet-List for (int k=0; k<iterate; k+=1) { // get the next particle and it's position within the root box j = verlet[N_Verlet*i+k]; xj = position[2*j]; yj = position[2*j+1]; // assign the appropriate interaction relation to the particle, depending whether it has even or uneven number m_j = (j%2)*m + (j+1)%2; // Get the distance between both particles dx = xi - xj; dy = yi - yj; // alter dx, this accounts for Lees-Edwards conditions sig_y = dround(dy*Li); dx += sig_y * (*box_two); // find images through altering dx and dy dx -= dround(dx*Li)*L; dy -= sig_y * L; // get square of distance and compute force in x and y direction r_squared = dx*dx + dy*dy; temp_force = (m_i_two*m_j/sqrt(r_squared))*(3*Gamma_A/(r_squared*r_squared)-force_cutoff); // WARNING: this is F/r force[2*i] += temp_force*dx; // equals F*x/r = F*cos(phi) (x-component) force[2*i+1] += temp_force*dy; // equals F*y/r = F*sin(phi) (y-component) } } // wait for all threads to finish iteration of forces, then continue with writing position data pthread_barrier_wait(&barrier_internal); // compute new positions for particles A from forces, remember periodic boundary conditions for (int i=min; i<max; i+=2) { xi = position[2*i]; yi = position[2*i+1]; // use Box-Muller-method in order to obtain two independent standard normal values do { u1 = rand()/(double)RAND_MAX; } while (u1 == 0.0); do { u2 = rand()/(double)RAND_MAX; } while (u2 == 0.0); temp = sqrt(-2*log(u1)); g1 = temp*cos(TWO_PI*u2); g2 = temp*sin(TWO_PI*u2); // Calculate next positions and total displacement for all particles dx = D_kT_one*delta_t*force[2*i] + weigh_brown_one * g1 + position[2*i+1]*shear_one; dy = D_kT_one*delta_t*force[2*i+1] + weigh_brown_one * g2; position[2*i] += dx; position[2*i+1] += dy; displacement[2*i] += dx; displacement[2*i+1] += dy; // update list of total displacement for each particle after last verlet-list update verlet_distance[2*i] += (xi - position[2*i]); verlet_distance[2*i+1] += (yi - position[2*i+1]); if ((temp = sqrt(verlet_distance[2*i]*verlet_distance[2*i] + verlet_distance[2*i+1]*verlet_distance[2*i+1])) > verlet_max[2*(*no)]) { verlet_max[2*(*no)+1] = verlet_max[2*(*no)]; verlet_max[2*(*no)] = temp; } else if (temp > verlet_max[2*(*no)+1]) { verlet_max[2*(*no)+1] = temp; } // Calculate x positions with periodic boundary conditions, check whether the particle moved from one row to another position[2*i] -= floor(position[2*i]*Li)*L; position[2*i] -= (floor((position[2*i+1]+L)*Li)-1)*(*box_one); // WTF?!? // Calculate y positions with periodic boundary conditions position[2*i+1] -= floor(position[2*i+1]*Li)*L; } // compute new positions for particles B from forces, remember periodic boundary conditions for (int i=min+1; i<max; i+=2) { xi = position[2*i]; yi = position[2*i+1]; // use Box-Muller-method in order to obtain two independent standard normal values do { u1 = rand()/(double)RAND_MAX; } while (u1 == 0.0); do { u2 = rand()/(double)RAND_MAX; } while (u2 == 0.0); temp = sqrt(-2*log(u1)); g1 = temp*cos(TWO_PI*u2); g2 = temp*sin(TWO_PI*u2); // Calculate next positions and total displacement for all particles dx = D_kT_two*delta_t*force[2*i] + weigh_brown_two * g1 + position[2*i+1]*shear_two; dy = D_kT_two*delta_t*force[2*i+1] + weigh_brown_two * g2; position[2*i] += dx; position[2*i+1] += dy; displacement[2*i] += dx; displacement[2*i+1] += dy; // update list of total displacement for each particle after last verlet-list update verlet_distance[2*i] += (xi - position[2*i]); verlet_distance[2*i+1] += (yi - position[2*i+1]); if ((temp = sqrt(verlet_distance[2*i]*verlet_distance[2*i] + verlet_distance[2*i+1]*verlet_distance[2*i+1])) > verlet_max[2*(*no)]) { verlet_max[2*(*no)+1] = verlet_max[2*(*no)]; verlet_max[2*(*no)] = temp; } else if (temp > verlet_max[2*(*no)+1]) { verlet_max[2*(*no)+1] = temp; } // Calculate x positions with periodic boundary conditions, check whether the particle moved from one row to another position[2*i] -= floor(position[2*i]*Li)*L; position[2*i] -= (floor((position[2*i+1]+L)*Li)-1)*(*box_two); // Calculate y positions with periodic boundary conditions position[2*i+1] -= floor(position[2*i+1]*Li)*L; } // Signal to main thread, that all threads have finished their iteration pthread_barrier_wait(&barrier_main_one); // thread is done with one iteration, it will now wait for a signal from the main thread to continue pthread_barrier_wait(&barrier_main_two); } return NULL; }
/** Calculate lj-angle force between particle p1 and p2 Involves 6 particles total */ inline void add_ljangle_force(Particle *p1, Particle *p2, IA_parameters *ia_params, double d[3], double dist) { if(!CUTOFF_CHECK(dist < ia_params->LJANGLE_cut)) return; int j; double frac2=0.0, frac10=0.0, rad=0.0, radprime=0.0; double r31[3], r41[3], r52[3], r62[3], rij[3], rik[3], rkn[3]; double l_rij, l_rik, l_rkn, l_rij2, l_rik2, l_rkn2; double cos_jik, cos_ikn; double angular_jik, angular_ikn, angular_jik_prime, angular_ikn_prime; /* Recreate angular dependence of potential by including 6 particles instead of 2. */ Particle *p3=NULL, *p4=NULL, *p5=NULL, *p6=NULL; int part1p, part1n, part2p, part2n; /* Optional 2nd environment */ double effective_eps=ia_params->LJANGLE_eps, z1, z2, z_middle, z_ref, z_ref5, localz0=ia_params->LJANGLE_z0, localdz2=ia_params->LJANGLE_dz/2., localkappa6=pow(1/ia_params->LJANGLE_kappa,6); /* Retrieve the bonded partners from parsing */ if (ia_params->LJANGLE_bonded1type == p1->p.type) { part1p = p1->p.identity + ia_params->LJANGLE_bonded1pos; part1n = p1->p.identity + ia_params->LJANGLE_bonded1neg; part2p = p2->p.identity + ia_params->LJANGLE_bonded2pos; part2n = p2->p.identity + ia_params->LJANGLE_bonded2neg; } else { part1p = p1->p.identity + ia_params->LJANGLE_bonded2pos; part1n = p1->p.identity + ia_params->LJANGLE_bonded2neg; part2p = p2->p.identity + ia_params->LJANGLE_bonded1pos; part2n = p2->p.identity + ia_params->LJANGLE_bonded1neg; } if (part1p >= 0 && part1p < n_part && part1n >= 0 && part1n < n_part && part2p >= 0 && part2p < n_part && part2n >= 0 && part2n < n_part ) { p3 = local_particles[part1p]; p4 = local_particles[part1n]; p5 = local_particles[part2p]; p6 = local_particles[part2n]; /* Check whether pointers have been allocated. * Otherwise, there's a communication error (verlet skin too small). */ if (p3==NULL ||p4==NULL ||p5==NULL ||p6==NULL) fprintf(stderr, "LJANGLE - Communication error, all particles cannot be reached locally.\n"); get_mi_vector(r31, p1->r.p, p3->r.p); get_mi_vector(r41, p1->r.p, p4->r.p); get_mi_vector(r52, p2->r.p, p5->r.p); get_mi_vector(r62, p2->r.p, p6->r.p); /* Bead i represents the central particle of monomer 1. * Bead j is the virtual particle that gives the orientation of monomer 1. * Bead k represents the central particle of monomer 2. * Bead n is the virtual particle that gives the orientation of monomer 2. */ for(j=0; j<3; ++j) { rij[j] = r31[j] + r41[j]; rik[j] = -d[j]; /* At this point, rik[3] has length dist */ rkn[j] = r52[j] + r62[j]; } l_rij2 = sqrlen(rij); l_rik2 = dist*dist; l_rkn2 = sqrlen(rkn); l_rij = sqrt(l_rij2); l_rik = dist; l_rkn = sqrt(l_rkn2); cos_jik = scalar(rij,rik)/(l_rij*l_rik); cos_ikn = -scalar(rik,rkn)/(l_rik*l_rkn); if(cos_jik>0. && cos_ikn>0.) { angular_jik = pow(cos_jik,2); angular_ikn = pow(cos_ikn,2); angular_jik_prime = -2*cos_jik; angular_ikn_prime = -2*cos_ikn; /* Optional 2nd environment */ if (localdz2 > 0.) { /* calculate center position of the interaction (calculate minimal distance) */ z1 = p1->r.p[2]; z2 = p2->r.p[2]; z_middle = z1 + z2; z_middle /= 2.; if (PERIODIC(2)) if (z_middle > box_l[2] || z_middle < 0.) z_middle -= dround(z_middle *box_l_i[2])*box_l[2]; /* If we're in the environment #2 region, calculate the new interaction strength */ if (z_middle > localz0 - localdz2 && z_middle <= localz0) { z_ref = z_middle - localz0 + localdz2; z_ref5 = pow(z_ref,5); effective_eps += (ia_params->LJANGLE_epsprime - ia_params->LJANGLE_eps) * localkappa6*z_ref5*fabs(z_ref) / (1 + localkappa6*z_ref5*z_ref); } else if (z_middle > localz0 && z_middle < localz0 + localdz2) { z_ref = z_middle - localz0 - localdz2; z_ref5 = pow(z_ref,5); effective_eps -= (ia_params->LJANGLE_epsprime - ia_params->LJANGLE_eps) * localkappa6*z_ref5*fabs(z_ref) / (1 + localkappa6*z_ref5*z_ref); } } /* normal case: resulting force/energy smaller than capping. */ if(dist > ia_params->LJANGLE_capradius) { frac2 = SQR(ia_params->LJANGLE_sig/dist); frac10 = frac2*frac2*frac2*frac2*frac2; rad = effective_eps * frac10*(5.0 * frac2 - 6.0); radprime = 60.0 * effective_eps * frac10*(1.0 - frac2) / dist; #ifdef LJ_WARN_WHEN_CLOSE if(radprime > 1000) fprintf(stderr,"%d: LJANGLE-Warning: Pair (%d-%d) force=%f dist=%f\n", this_node,p1->p.identity,p2->p.identity,radprime,dist); #endif } /* capped part of lj-angle potential. */ else if(dist > 0.0) { /* set the length of rik to capradius */ for (j=0; j<3; ++j) rik[j] *= ia_params->LJANGLE_capradius/dist; l_rik = ia_params->LJANGLE_capradius; frac2 = SQR(ia_params->LJANGLE_sig/ia_params->LJANGLE_capradius); frac10 = frac2*frac2*frac2*frac2*frac2; rad = effective_eps * frac10*(5.0 * frac2 - 6.0); radprime = 60.0 * effective_eps * frac10*(1.0 - frac2) / (ia_params->LJANGLE_capradius); } /* Regroup the last two cases in one */ /* Propagate all forces in this function rather than in the forces.hpp file */ if (dist > 0.0) { for(j=0; j<3; ++j) { p1->f.f[j] += angular_jik * angular_ikn * rik[j]/l_rik *radprime + angular_ikn * rad * angular_jik_prime * ( ( 2*rik[j]-rij[j] )/( l_rij*l_rik ) - cos_jik*( 2*rij[j]/l_rij2 - rik[j]/l_rik2 ) ) + angular_jik * rad * angular_ikn_prime * ( rkn[j]/( l_rik*l_rkn ) + cos_ikn*rik[j]/l_rik2 ); p2->f.f[j] += -angular_jik * angular_ikn * rik[j]/l_rik *radprime + angular_ikn * rad * angular_jik_prime * ( rij[j]/( l_rij*l_rik ) - cos_jik*rik[j]/l_rik2 ) + angular_jik * rad * angular_ikn_prime * ( -(2*rik[j]+rkn[j])/(l_rik*l_rkn) - cos_ikn*( 2*rkn[j]/l_rkn2 + rik[j]/l_rik2 ) ); p3->f.f[j] += angular_ikn * rad * angular_jik_prime * ( -rik[j]/(l_rij*l_rik) + cos_jik*rij[j]/l_rij2 ); p4->f.f[j] += angular_ikn * rad * angular_jik_prime * ( -rik[j]/(l_rij*l_rik) + cos_jik*rij[j]/l_rij2 ); p5->f.f[j] += angular_jik * rad * angular_ikn_prime * ( rik[j]/(l_rik*l_rkn) + cos_ikn*rkn[j]/l_rkn2 ); p6->f.f[j] += angular_jik * rad * angular_ikn_prime * ( rik[j]/(l_rik*l_rkn) + cos_ikn*rkn[j]/l_rkn2 ); } } /* this should not happen! In this case consider only radial potential*/ else { LJ_TRACE(fprintf(stderr, "%d: LJ-angle warning: Particles id1=%d id2=%d exactly on top of each other\n",this_node,p1->p.identity,p2->p.identity)); frac2 = SQR(ia_params->LJANGLE_sig/ia_params->LJANGLE_capradius); frac10 = frac2*frac2*frac2*frac2*frac2; rad = effective_eps * frac10*(5.0 * frac2 - 6.0) / ia_params->LJANGLE_capradius; p1->f.f[0] += rad * ia_params->LJANGLE_capradius; } ONEPART_TRACE(if(p1->p.identity==check_id) fprintf(stderr,"%d: OPT: LJANGLE f = (%.3e,%.3e,%.3e) with part id=%d at dist %f fac %.3e\n",this_node,p1->f.f[0],p1->f.f[1],p1->f.f[2],p2->p.identity,dist,radprime)); ONEPART_TRACE(if(p2->p.identity==check_id) fprintf(stderr,"%d: OPT: LJANGLE f = (%.3e,%.3e,%.3e) with part id=%d at dist %f fac %.3e\n",this_node,p2->f.f[0],p2->f.f[1],p2->f.f[2],p1->p.identity,dist,radprime)); LJ_TRACE(fprintf(stderr,"%d: LJANGLE: Pair (%d-%d) dist=%.3f: force+-: (%.3e,%.3e,%.3e)\n", this_node,p1->p.identity,p2->p.identity,dist,rad*d[0],rad*d[1],rad*d[2])); }
//--------------------------------------------------------------------------------------// // Optimized ewald functions for two particle move: // Quick and ditry implementation double Ewald_r_space_doublemove(double** xyz, double *Q, double *MCcoord, double MCQ, int MCion,double *MCcoord2, double MCQ2, int MCion2) { int t2; double dx,dy,dz,r,r2,ar, dpix, dpiy, rpi2,rpi2_2, dx2,dy2,dz2,r2_2; double d1,d2,d3=0.0; double d3_ci=0; //cylinder-ion contributions for (int l=0;l<Npol;l++) { dpix=pxy[l][0]-MCcoord[0]; dpix-=dround(dpix/Ls[0])*Ls[0]; dpiy=pxy[l][1]-MCcoord[1]; dpiy-=dround(dpiy/Ls[1])*Ls[1]; rpi2=(SQR(dpix)+SQR(dpiy)); if (rpi2<=rmax2) d3_ci-= MCQ*prefactor*taus[l]*Exponential_Integral_Ei(-SQR(alpha)*(rpi2)); dpix=pxy[l][0]-MCcoord2[0]; dpix-=dround(dpix/Ls[0])*Ls[0]; dpiy=pxy[l][1]-MCcoord2[1]; dpiy-=dround(dpiy/Ls[1])*Ls[1]; rpi2_2=(SQR(dpix)+SQR(dpiy)); if (rpi2_2<=rmax2) d3_ci-= MCQ2*prefactor*taus[l]*Exponential_Integral_Ei(-SQR(alpha)*(rpi2_2)); } for (t2 = 0; t2<NP; t2++) { //mutual contribution of ions dont have to be counted if we only use the difference if ( t2 != MCion && t2!=MCion2 ) { dx = MCcoord[0] - xyz[t2][0]; dx -= dround(dx/Ls[0])*Ls[0]; dy = MCcoord[1] - xyz[t2][1]; dy -= dround(dy/Ls[1])*Ls[1]; dz = MCcoord[2] - xyz[t2][2]; dz -= dround(dz/Ls[2])*Ls[2]; r2 = SQR(dx) + SQR(dy) + SQR(dz); dx2 = MCcoord2[0] - xyz[t2][0]; dx2 -= dround(dx2/Ls[0])*Ls[0]; dy2 = MCcoord2[1] - xyz[t2][1]; dy2 -= dround(dy2/Ls[1])*Ls[1]; dz2 = MCcoord2[2] - xyz[t2][2]; dz2 -= dround(dz2/Ls[2])*Ls[2]; r2_2 = SQR(dx2) + SQR(dy2) + SQR(dz2); if (r2 <= rmax2) { ar = alpha * (r = sqrt(r2)); d3 += ( d2 = (d1 = MCQ * Q[t2] * prefactor) * erfc(ar) / r ); } if (r2_2 <= rmax2) { ar = alpha * (r = sqrt(r2_2)); d3 += ( d2 = (d1 = MCQ2 * Q[t2] * prefactor) * erfc(ar) / r ); } } } return d3+d3_ci; // return d3; }
/** Metadynamics main function: * - Calculate reaction coordinate * - Update profile and biased force * - apply external force */ void meta_perform() { if(meta_switch == META_OFF) return; double ppos1[3] = {0,0,0}, ppos2[3] = {0,0,0}, factor; int img1[3], img2[3], c, i, np, flag1 = 0, flag2 = 0; Particle *p, *p1 = NULL, *p2 = NULL; Cell *cell; for (c = 0; c < local_cells.n; c++) { cell = local_cells.cell[c]; p = cell->part; np = cell->n; for(i = 0; i < np; i++) { if (p[i].p.identity == meta_pid1) { flag1 = 1; p1 = &p[i]; memcpy(ppos1, p[i].r.p, 3*sizeof(double)); memcpy(img1, p[i].l.i, 3*sizeof(int)); #ifdef LEES_EDWARDS { double pv[3]; memcpy(pv, part[i].m.v, 3*sizeof(double)); unfold_position(ppos1, pv, img1); } #else unfold_position(ppos1, img1); #endif if (flag1 && flag2) { /* vector r2-r1 - Not a minimal image! Unfolded position */ vector_subt(meta_cur_xi,ppos2,ppos1); break; } } if (p[i].p.identity == meta_pid2) { flag2 = 1; p2 = &p[i]; memcpy(ppos2, p[i].r.p, 3*sizeof(double)); memcpy(img2, p[i].l.i, 3*sizeof(int)); #ifdef LEES_EDWARDS { double pv[3]; memcpy(pv, part[i].m.v, 3*sizeof(double)); unfold_position(ppos2, pv, img2); } #else unfold_position(ppos2, img2); #endif if (flag1 && flag2) { /* vector r2-r1 - Not a minimal image! Unfolded position */ vector_subt(meta_cur_xi,ppos2,ppos1); break; } } } } if (flag1 == 0 || flag2 == 0) { ostringstream msg; msg <<"Metadynamics: can't find pid1 or pid2.\n"; runtimeError(msg); return; } /* Now update free energy profile * Here, we're following the functional form of * Marsili etal., J Comp. Chem, 31 (2009). * Instead of gaussians, we use so-called Lucy's functions */ for (i = 0; i < meta_xi_num_bins; ++i) { if (meta_switch == META_DIST) { // reaction coordinate value meta_val_xi = sqrt(sqrlen(meta_cur_xi)); // Update free energy profile and biased force meta_acc_fprofile[i] -= calculate_lucy(meta_xi_min+i*meta_xi_step,meta_val_xi); meta_acc_force[i] -= calculate_deriv_lucy(meta_xi_min+i*meta_xi_step,meta_val_xi); // direction of the bias force unit_vector(meta_cur_xi,meta_apply_direction); } else if (meta_switch == META_REL_Z) { // reaction coordinate value: relative height of z_pid1 with respect to z_pid2 meta_val_xi = -1.*meta_cur_xi[2]; // Update free energy profile and biased force meta_acc_fprofile[i] -= calculate_lucy(meta_xi_min+i*meta_xi_step,meta_val_xi); meta_acc_force[i] -= calculate_deriv_lucy(meta_xi_min+i*meta_xi_step,meta_val_xi); // direction of the bias force (-1 to be consistent with META_DIST: from 1 to 2) meta_apply_direction[0] = meta_apply_direction[1] = 0.; meta_apply_direction[2] = -1.; } else { ostringstream msg; msg <<"Undefined metadynamics scheme.\n"; runtimeError(msg); return; } } /** Apply force */ // Calculate the strength of the applied force if (meta_val_xi < meta_xi_min) { // below the lower bound factor = -1. * meta_f_bound * (meta_xi_min-meta_val_xi)/meta_xi_step; } else if (meta_val_xi > meta_xi_max) { // above the upper bound factor = meta_f_bound * (meta_val_xi-meta_xi_max)/meta_xi_step; } else { // within the RC interval i = (int) dround((meta_val_xi-meta_xi_min)/meta_xi_step); if (i < 0) i = 0; if (i >= meta_xi_num_bins) i=meta_xi_num_bins-1; factor = meta_acc_force[i]; } /* cancel previous force to external force of particle */ for (i = 0; i<3; ++i) { p1->f.f[i] += factor * meta_apply_direction[i]; p2->f.f[i] += -1. * factor * meta_apply_direction[i]; } }
double Ewald_r_space_line(double** xyz, double *Q, double *Fx, double *Fy, double *Fz) { int t1,t2; double dx,dy,dz,r,r2,ar,ar2, dpix, dpiy; double d1,d2,d3=0.0,d4, d3_ci=0, d3_cc=0; double rpi2=0; static double wupi = 1.77245385090551602729816748334; for (t1 = 0; t1 < NP-1; t1++) /* Quick and Dirty N^2 loop */ { //cylinder-ion contribution for (int l=0;l<Npol;l++) { dpix=pxy[l][0]-xyz[t1][0]; dpix-=dround(dpix/Ls[0])*Ls[0]; dpiy=pxy[l][1]-xyz[t1][1]; dpiy-=dround(dpiy/Ls[1])*Ls[1]; rpi2=(SQR(dpix)+SQR(dpiy)); //e1(x)=-ei(-x) if (rpi2<=rmax2) d3_ci-= Q[t1]*prefactor*taus[l]*Exponential_Integral_Ei(-SQR(alpha)*(rpi2)); } for (t2 = t1 + 1; t2<NP; t2++) { dx = xyz[t1][0] - xyz[t2][0]; dx -= dround(dx/Ls[0])*Ls[0]; dy = xyz[t1][1] - xyz[t2][1]; dy -= dround(dy/Ls[1])*Ls[1]; dz = xyz[t1][2] - xyz[t2][2]; dz -= dround(dz/Ls[2])*Ls[2]; r2 = SQR(dx) + SQR(dy) + SQR(dz); /* printf("%d %d %le \n",t1+1,t2+1,sqrt(r2));*/ /* printf("%d %d %le %le\n",t1+1,t2+1,r2,rmax2);*/ if (r2 <= rmax2) { //printf("Forces"); ar2 = SQR(ar = alpha * (r = sqrt(r2))); d3 += ( d2 = (d1 = Q[t1] * Q[t2] * prefactor) * erfc(ar) / r ); if (Fx||Fy||Fz) { /* if forces should be computed... */ d4 = ( d2 + d1*2.0*alpha*exp(-ar2)/wupi) / r2; Fx[t1] += d4*dx; Fy[t1] += d4*dy; Fz[t1] += d4*dz; Fx[t2] -= d4*dx; Fy[t2] -= d4*dy; Fz[t2] -= d4*dz; } } } } //final ion, look at the loop indices t1=NP-1; for (int l=0;l<Npol;l++) { dpix=pxy[l][0]-xyz[t1][0]; dpix-=dround(dpix/Ls[0])*Ls[0]; dpiy=pxy[l][1]-xyz[t1][1]; dpiy-=dround(dpiy/Ls[1])*Ls[1]; rpi2=(SQR(dpix)+SQR(dpiy)); //e1(x)=-ei(-x) if (rpi2<=rmax2) d3_ci-= Q[t1]*prefactor*taus[l]*Exponential_Integral_Ei(-SQR(alpha)*(rpi2)); } //cylinder-cylinder as a function of their separation //should there be a cutoff here too, think about periodicity, will they always be l/2? if (Npol==2) d3_cc=-prefactor*taus[1]*taus[0]*Ls[2]*Exponential_Integral_Ei(-SQR(alpha)*(SQR(pxy[1][0]-pxy[0][0])+SQR(pxy[1][1]-pxy[0][1]))); printf("real line d3 %lf d3_ci %lf d3_cc %lf\n", d3,d3_ci,d3_cc); return d3+d3_ci+d3_cc; //return d3; }