void reset_XYZ(void) { int i; double cx=0.0,cy=0.0,cz=0.0; //Find the center of mass for each component for(i=0;i<N;i++) { cx+=x[i]; cy+=y[i]; cz+=z[i]; }; cx*=invN; cy*=invN; cz*=invN; //fprintf(stderr,"%g\t%g\t%g\n",cmass(),currEtot,currnonbondE); for(i=0;i<N;i++) { x[i]=x[i]-cx; y[i]=y[i]-cy; z[i]=z[i]-cz; }; //Recalculate the overall energies currEtot=Etot(); currnonbondE=nonbondEnergy(); //fprintf(stderr,"%g\t%g\t%g\n",cmass(),currEtot,currnonbondE); }
/*Monte Carlo bond fluctuation algorithm Similar to mcpivot, but rotates monomers betwee two randomly chosen monomers by a small amount axis of rotation is between the two chosen monomers NOTE this algorithm should NOT change the bond lengths, use checkbonds() to check, but should change one bond angle at a time */ void mccrankshaft(void) { int i=0,j=0,m1=0,m2=0,start=0,end=0; double Ei=0.0,Ef=0.0; //intial and final energies (before and after diffusion) double Ebondi=0.0,Ebondf=0.0,Enblocali=0.0,Enblocalf=0.0; //local energy variables double rx=0.0,ry=0.0,rz=0.0; double distr=0.0,rangle=0.0,c=0.0,s=0.0,u=0.0; double ttx=0.0,tty=0.0,ttz=0.0; //set temporary positions for(j=0;j<N;++j) { tx[j]=x[j]; ty[j]=y[j]; tz[j]=z[j]; }; //randomly choose two monomers m1=(int) (randd1()*N); m2=(int) (randd1()*N); //choose random rotation angle rangle=DC*2.0*M_PI*(2.0*randd1()-1.0); //below are the cases where the move wouldn't change anything while( (m1==m2) || (abs(m1-m2)==N-1) || (abs(m1-m2)==1) ) { m1=(int) (randd1()*N); m2=(int) (randd1()*N); }; //set indices for energy calculation if( m1<m2 ) { start=m1; end=m2; } else { start=m2; end=m1; }; //Set initial energies Ei=currEtot; //////////Rotation //rotation axis is the vector between m1 and m2 distr = sqrt( (x[m1]-x[m2])*(x[m1]-x[m2]) + (y[m1]-y[m2])*(y[m1]-y[m2]) + (z[m1]-z[m2])*(z[m1]-z[m2]) ); rx = (x[m1]-x[m2])/distr; ry = (y[m1]-y[m2])/distr; rz = (z[m1]-z[m2])/distr; //angle constants c=cos(rangle); s=sin(rangle); u=1.0-c; //Calculate the initial local bond energy /* for(i=start;i<end;i++) { distr = sqrt( (x[i]-x[i+1])*(x[i]-x[i+1]) + (y[i]-y[i+1])*(y[i]-y[i+1]) + (z[i]-z[i+1])*(z[i]-z[i+1]) ); Ebondi = Ebondi + bondpot(distr); }; */ //Local bond and bond angle energy - assumes the above in unecessary Ebondi = localE(m1) + localE(m2); /////Rotation //now we perform the rotation for(i=start+1;i<end;i++) { //calculate initial local nonbonded energy for(j=0;j<N;j++) if( (j<start) || (j>end) ) { distr = sqrt( (x[i]-x[j])*(x[i]-x[j]) + (y[i]-y[j])*(y[i]-y[j]) + (z[i]-z[j])*(z[i]-z[j]) ); Enblocali = Enblocali + nonbondpot(distr); //fprintf(stderr,"%d\t%d\t%20.16f\t%20.16f\t%20.16f\n",i,j,distr,nonbondpot(distr),Enblocali); }; //translate the rotation segment to the origin x[i] -= x[start]; y[i] -= y[start]; z[i] -= z[start]; //store old vector for the rotation matrix below ttx=x[i]; tty=y[i]; ttz=z[i]; //Perform the rotation on the selected segment x[i] = (u*rx*rx + c)*ttx + (u*ry*rx - s*rz)*tty + (u*rz*rx + ry*s)*ttz; y[i] = (u*rx*ry + rz*s)*ttx + (u*ry*ry + c)*tty + (u*rz*ry - rx*s)*ttz; z[i] = (u*rx*rz - ry*s)*ttx + (u*ry*rz + rx*s)*tty + (u*rz*rz + c)*ttz; //translate the rotation segment back to the original reference frame x[i] += x[start]; y[i] += y[start]; z[i] += z[start]; //calculate final local nonbonded energy for(j=0;j<N;j++) if( (j<start) || (j>end) ) { distr = sqrt( (x[i]-x[j])*(x[i]-x[j]) + (y[i]-y[j])*(y[i]-y[j]) + (z[i]-z[j])*(z[i]-z[j]) ); Enblocalf = Enblocalf + nonbondpot(distr); //fprintf(stderr,"%d\t%d\t%20.16f\t%20.16f\t%20.16f\n",i,j,distr,nonbondpot(distr),Enblocalf); }; }; //Calculate the initial local bond energy /* for(i=start;i<end;i++) { distr = sqrt( (x[i]-x[i+1])*(x[i]-x[i+1]) + (y[i]-y[i+1])*(y[i]-y[i+1]) + (z[i]-z[i+1])*(z[i]-z[i+1]) ); Ebondf = Ebondf + bondpot(distr); }; */ //Local bond and bond angle energy - assumes the above in unecessary Ebondf = localE(m1) + localE(m2); //Bond-angles should be unaffected by this move Ef = Ei + (Ebondf - Ebondi) + (Enblocalf - Enblocali); attemptside+=1; if(Metropolis(Ei,Ef)==1) { acceptside+=1; if( (acceptside%1000) == 0 ) { currEtot = Etot(); }; } else { //reject for(j=0;j<N;++j) { x[j]=tx[j]; y[j]=ty[j]; z[j]=tz[j]; }; }; }
/* Monte Carlo pivot around a random direction Random direction generated using the Marsaglia method NOTE this algorithm should NOT change the bond lengths, use checkbonds() to check, but should change one bond angle at a time */ void mcrandpivot(void) { int m=0,i=0,j=0,direction=0,start=0,end1=0,end2=0; double Ei=0.0,Ef=0.0; //intial and final energies (before and after diffusion) double Ebondi=0.0,Ebondf=0.0,Enblocali=0.0,Enblocalf=0.0; //local energy variables double eta1=0.0,eta2=0.0,etasq=0.0,rx=0.0,ry=0.0,rz=0.0; double distr=0.0,rangle=0.0,c=0.0,s=0.0,u=0.0; double ttx=0.0,tty=0.0,ttz=0.0; //set temperorary variables for(j=0;j<N;++j) { tx[j]=x[j]; ty[j]=y[j]; tz[j]=z[j]; }; //choose random monomer m=(int) (randd1()*(N-2)+1.0); //note, never choses monomers on the ends, as this would do nothing to the internal degrees of freedom //choose random rotation angle rangle=DC*2.0*M_PI*(2.0*randd1()-1.0); //select the shortest portion of the chain to the left or right of the random monomer if(m < N/2.0) { direction = -1; start=m; end1=0; end2=N-1; } else { direction = 1; start=m; end1=N-1; end2=0; }; //choose a random direction using the Marsaglia method etasq = 2.0; //simply set to a value greater than 1.0 (the while condition below) while( etasq > 1.0 ) { eta1 = 1.0 - 2.0*randd1(); eta2 = 1.0 - 2.0*randd1(); etasq = eta1*eta1 + eta2*eta2; }; //these are the new unit vectors rx = 2.0*eta1*sqrt(1.0-etasq); ry = 2.0*eta2*sqrt(1.0-etasq); rz = 1.0 - 2.0*etasq; //angle constants c=cos(rangle); s=sin(rangle); u=1.0-c; //set energies Ei=currEtot; //Calculate the initial local bond energy (NOTE: this cannot go in the rotation loop) /* i=start; while( i != end1 ) { i=i+direction; j=i-direction; distr = sqrt( (x[i]-x[j])*(x[i]-x[j]) + (y[i]-y[j])*(y[i]-y[j]) + (z[i]-z[j])*(z[i]-z[j]) ); Ebondi = Ebondi + bondpot(distr); //fprintf(stderr,"%d\t%d\t%d\t%f\t%f\n",m,i,i-direction,distr,bondpot(distr)); }; */ //Local bond and bond angle energy - assumes bond lengths don't change (unlike above commented out section) Ebondi = Ebondi + localE(m); /////Rotation //now we perform the rotation i=start; while( i != end1 ) { i=i+direction; //Calculate the initial local nonbond energy for(j=end2;j!=start;j+=direction) { distr = sqrt( (x[i]-x[j])*(x[i]-x[j]) + (y[i]-y[j])*(y[i]-y[j]) + (z[i]-z[j])*(z[i]-z[j]) ); Enblocali = Enblocali + nonbondpot(distr); //fprintf(stderr,"%d\t%d\n",i,j); }; //translate the rotation segment to the origin x[i] -= x[start]; y[i] -= y[start]; z[i] -= z[start]; //store old vector for the rotation matrix below ttx=x[i]; tty=y[i]; ttz=z[i]; //Perform the rotation on the selected segment x[i] = (u*rx*rx + c)*ttx + (u*ry*rx - s*rz)*tty + (u*rz*rx + ry*s)*ttz; y[i] = (u*rx*ry + rz*s)*ttx + (u*ry*ry + c)*tty + (u*rz*ry - rx*s)*ttz; z[i] = (u*rx*rz - ry*s)*ttx + (u*ry*rz + rx*s)*tty + (u*rz*rz + c)*ttz; //translate the rotation segment back to the original reference frame x[i] += x[start]; y[i] += y[start]; z[i] += z[start]; //Final local nonbond energy for(j=end2;j!=start;j+=direction) { distr = sqrt( (x[i]-x[j])*(x[i]-x[j]) + (y[i]-y[j])*(y[i]-y[j]) + (z[i]-z[j])*(z[i]-z[j]) ); Enblocalf = Enblocalf + nonbondpot(distr); //fprintf(stderr,"%d\t%d\n",i,j); }; }; //Calculate the final local bond energy (NOTE: this cannot go in the rotation loop) /* i=start; while( i != end1 ) { i=i+direction; j=i-direction; distr = sqrt( (x[i]-x[j])*(x[i]-x[j]) + (y[i]-y[j])*(y[i]-y[j]) + (z[i]-z[j])*(z[i]-z[j]) ); Ebondf = Ebondf + bondpot(distr); //fprintf(stderr,"%d\t%d\t%d\t%f\t%f\n",m,i,i-direction,distr,bondpot(distr)); }; */ //Local bond and bond angle energy - assumes bond lengths don't change (unlike above commented out section) Ebondf = Ebondf + localE(m); Ef = Ei + (Ebondf - Ebondi) + (Enblocalf - Enblocali); //Ef=Etot(); attemptpivot+=1; if(Metropolis(Ei,Ef)==1) { acceptpivot+=1; if( (acceptpivot%1000) == 0 ) //this insures that errors do not accumulate over time { currEtot = Etot(); }; } else { //reject for(j=0;j<N;++j) { x[j]=tx[j]; y[j]=ty[j]; z[j]=tz[j]; }; }; }
double Planet::Etotal(int i){ return Etot(i); }
//initialize the polymer chain with one end at the origin //and all nn bonds at the ground state, in the x-y plane void initialize(void) { int i; double a=1.0; //for relatively big jumps D=0.05; DC=1.0; DD=0.1; //precalculations for chain length invN=1.0/(1.0*N); rootinvN = 1.0/sqrt(1.0*N); //term used to set the FENE+LJ potential's minimum at 1.0 sigmaFENE = pow((0.5+sqrt(23.0/44.0)),(1.0/6.0)); //precalculation for the LJ potential sigmaLJ=pow(0.5,1.0/6.0); //term used to shift the LJ potential such that it is zero at r=1.0 shiftLJ = pow((1.0/Rcutnonbond),12.0) - 2.0*pow((1.0/Rcutnonbond),6.0); //precalculations for the nn bond angle potentials PI=2.0*acos(0.0); ANG=PI; COSANG=cos(ANG); T=5.0; //Dynamic Memory Allocation - this has to be done because an input file is used. //x,y,z coordinates x = malloc( N * sizeof(double) ); y = malloc( N * sizeof(double) ); z = malloc( N * sizeof(double) ); if ( (x == NULL) || (y == NULL) || (z == NULL) ) { fprintf(stderr,"\nFailure to allocate memory for 'x,y, or z'. See 'initialize()'.\n"); exit(1); }; //tx,ty,tz - used as temporary coordinates in many of the "move" functions tx = malloc( N * sizeof(double) ); ty = malloc( N * sizeof(double) ); tz = malloc( N * sizeof(double) ); if ( (tx == NULL) || (ty == NULL) || (tz == NULL) ) { fprintf(stderr,"\nFailure to allocate memory for 'tx,ty, or tz'. See 'initialize()'.\n"); exit(1); }; //Initialize the tmp coordinates for(i=0;i++;i<N) { tx[i]=0.0; ty[i]=0.0; tz[i]=0.0; }; //Initializing the chain //One end starts at the origin x[0]=0.0; y[0]=0.0; z[0]=0.0; //Initialize the rest of the chain for(i=1;i<N;++i) { x[i]=x[i-1]+1.0; y[i]=0.0; z[i]=0.0; }; currEtot=Etot(); currnonbondE=nonbondEnergy(); }