//Diffuses a single monomer void mcdiff(void) { int i=0; double ox=0.0,oy=0.0,oz=0.0; //old positions of the monomer 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 //randomly choose a monomer i=(int) (randd1()*N); //Set initial energies //Ei=Etot(); Ei=currEtot; Ebondi=localE(i); Enblocali=localnonbondEnergy(i); //diffuse the ith monomer ox=x[i]; oy=y[i]; oz=z[i]; x[i]+=DD*(2.0*randd1()-1.0); y[i]+=DD*(2.0*randd1()-1.0); z[i]+=DD*(2.0*randd1()-1.0); //Calculate the final energy //Ef=Etot(); Ebondf=localE(i); Enblocalf=localnonbondEnergy(i); Ef = Ei + (Ebondf - Ebondi) + (Enblocalf - Enblocali); attemptdiff+=1; if(Metropolis(Ei,Ef)==1) { acceptdiff+=1; } else { //reject - return monomer to old position x[i]=ox; y[i]=oy; z[i]=oz; }; }
/*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]; }; }; }
//performs one slithering snake MC attempt void mcreptation(void) { int i=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,bondr=0.0; //used for random direction reptated monomer double eta1=0.0,eta2=0.0,etasq=0.0; //store the temporary positions for(i=0;i<N;i++) { tx[i]=x[i]; ty[i]=y[i]; tz[i]=z[i]; }; //choose a random direction using the Marsaglia method //give random unit vectors for the relative position of the moved endpoint 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; //Set initial energies //Ei=Etot(); Ei=currEtot; //choose whether to move the 0 monomer or N-1 monomer if(randd1()<0.5) { //move the 0th monomer //measure the bond length of 0-1 bond bondr=sqrt( (x[0]-x[1])*(x[0]-x[1]) + (y[0]-y[1])*(y[0]-y[1]) + (z[0]-z[1])*(z[0]-z[1]) ); //store local bond energy of the 0th monomer (even though there shouldn't be any change) Ebondi = localE(0); //store local non-bond energy Enblocali=localnonbondEnergy(0); //move x[1] to x[0], etc... for(i=0;i<N-1;i++) { x[i]=tx[i+1]; y[i]=ty[i+1]; z[i]=tz[i+1]; }; //new tail has random direction, but same bond length x[N-1]=x[N-2]+bondr*rx; y[N-1]=y[N-2]+bondr*ry; z[N-1]=z[N-2]+bondr*rz; //Calculate new bond energy Ebondf=localE(N-1); //Calculate new non-bond energy Enblocalf=localnonbondEnergy(N-1); } else { //move the N-1 monomer //measure the bond length of (N-2) to (N-1) bond bondr=sqrt( (x[N-2]-x[N-1])*(x[N-2]-x[N-1]) + (y[N-2]-y[N-1])*(y[N-2]-y[N-1]) + (z[N-2]-z[N-1])*(z[N-2]-z[N-1]) ); //store local energy change of the N-1 monomer (even though it will not change) Ebondi = localE(N-1); //store local non-bond energy Enblocali=localnonbondEnergy(N-1); //move x[1] to x[0], etc... for(i=1;i<N;i++) { x[i]=tx[i-1]; y[i]=ty[i-1]; z[i]=tz[i-1]; }; //new tail has random direction, but same bond length x[0]=x[1]+bondr*rx; y[0]=y[1]+bondr*ry; z[0]=z[1]+bondr*rz; //Calculate new change in bond energy Ebondf=localE(0); //Calculate new non-bond energy Enblocalf=localnonbondEnergy(0); } //Calculate the final energy (Note: the bond energy should not change, so it isn't calculated) //Ef=Etot(); Ef = Ei + (Ebondf - Ebondi) + (Enblocalf - Enblocali); attemptsnake+=1; if(Metropolis(Ei,Ef)==1) { acceptsnake+=1; } else { //reject - return monomer to old position for(i=0;i<N;i++) { x[i]=tx[i]; y[i]=ty[i]; z[i]=tz[i]; }; }; }
/***************************************************************************** Copy a polymer structure from a replica to another *****************************************************************************/ int ExchangePol(struct s_polymer *polymer, struct s_polymer *replica, struct s_polymer *oldp, struct s_mc_parms *parms, struct s_potential *u, int iproc, int ntemp, int even, int *ex_count, int *ex_acc, MPI_Datatype Backtype, MPI_Datatype Sidetype, MPI_Datatype Rottype, MPI_Status astatus,unsigned long long istep) { int i,j,k,l, position,a=0; int x[ntemp]; double delta,denomT; double E[ntemp]; int nback = polymer->nback; int buffer_back_size=sizeof(struct s_back)*nback; int nosidechains=parms->nosidechains; int ipolymer; E[iproc]=polymer->etot; if(iproc==0) CountContacts(stderr,polymer,parms,istep); MPI_Barrier(MPI_COMM_WORLD); for(i=0;i<ntemp;i++) MPI_Bcast(&(E[i]),1,MPI_DOUBLE,i,MPI_COMM_WORLD); //exchanging energy values between replicas MPI_Barrier(MPI_COMM_WORLD); //DEBUG /* if(iproc==0) for(i=0;i<ntemp;i++) { // fprintf(stderr,"step %llu E[%d]=\t%lf\n",istep,i,E[i]); } */ for(i=even;i<ntemp-1;i=i+2) { if(iproc==i) //sender { delta = -(E[i]-E[i+1]); denomT = (parms->T[i]*parms->T[i+1])/(parms->T[i+1]-parms->T[i]) ; if(Metropolis(delta,denomT,polymer->tables)==1) a=1; MPI_Send(&a, 1, MPI_INT, i+1, 1000000+i, MPI_COMM_WORLD); #ifdef DEBUG if(parms->debug>2) fprintf(stderr,"i=%d\tT(i)=%f\tT(i+1)=%f\tdelta=%f\tacc=%d\n",i,parms->T[i],parms->T[i+1],delta,a); #endif } if(iproc==i+1) MPI_Recv(&a, 1, MPI_INT, i, 1000000+i, MPI_COMM_WORLD, &astatus); //receiver MPI_Barrier(MPI_COMM_WORLD); if(a==1) //confirmed exchange { if(iproc==i) fprintf(stderr,"[EX]\t%llu\t%d\t%d\n",istep,i,i+1); for(ipolymer=0;ipolymer<parms->npol;ipolymer++) { nback=(polymer+ipolymer)->nback; buffer_back_size=sizeof(struct s_back)*nback; char *buffer_back=malloc(buffer_back_size); if(iproc==i) { position=0; for(j=0;j<nback;j++) MPI_Pack(((polymer+ipolymer)->back)+j,1,Backtype,buffer_back,buffer_back_size,&position,MPI_COMM_WORLD); MPI_Send(buffer_back,position,MPI_PACKED,i+1, 10000+100*i, MPI_COMM_WORLD); } if(iproc==i+1) { MPI_Recv(buffer_back,buffer_back_size,MPI_PACKED,i,10000+100*i, MPI_COMM_WORLD, &astatus); position=0; for(j=0;j<nback;j++) MPI_Unpack(buffer_back,buffer_back_size,&position,((replica+ipolymer)->back)+j,1,Backtype,MPI_COMM_WORLD); position=0; for(j=0;j<nback;j++) MPI_Pack(((polymer+ipolymer)->back)+j,1,Backtype,buffer_back,buffer_back_size,&position,MPI_COMM_WORLD); MPI_Send(buffer_back,position,MPI_PACKED,i, 20000+100*i, MPI_COMM_WORLD); } if(iproc==i) { MPI_Recv(buffer_back,buffer_back_size,MPI_PACKED,i+1, 20000+100*i, MPI_COMM_WORLD, &astatus); position=0; for(j=0;j<nback;j++) MPI_Unpack(buffer_back,buffer_back_size,&position,((replica+ipolymer)->back)+j,1,Backtype,MPI_COMM_WORLD); } if(!nosidechains) { int side_dims[nback]; int rot_dims[nback]; int buffer_side_size,sidechains=0; int rotamersl=0; for(j=0;j<nback;j++) { side_dims[j]=(((polymer+ipolymer)->back)+j)->nside; rot_dims[j]=(((polymer+ipolymer)->back)+j)->nrot; sidechains+=side_dims[j]; rotamersl+=rot_dims[j]; } buffer_side_size=sizeof(struct s_side)*sidechains; char *buffer_side=malloc(buffer_side_size); if(iproc==i) { position=0; for(j=0; j<nback;j++) for(k=0; k<side_dims[j];k++) MPI_Pack(((((polymer+ipolymer)->back)+j)->side)+k,1,Sidetype,buffer_side,buffer_side_size,&position,MPI_COMM_WORLD); MPI_Send(buffer_side,position,MPI_PACKED,i+1, 1000000+100*i, MPI_COMM_WORLD); } if(iproc==i+1) { MPI_Recv(buffer_side,buffer_side_size,MPI_PACKED,i,1000000+100*i, MPI_COMM_WORLD, &astatus); position=0; for(j=0; j<nback;j++) for(k=0; k<side_dims[j];k++) MPI_Unpack(buffer_side,buffer_side_size,&position,((((replica+ipolymer)->back)+j)->side)+k,1,Sidetype,MPI_COMM_WORLD); } //rotamers i -> i+1 if(iproc==i) { // position=0; for(j=0; j<nback;j++) for(k=0; k<side_dims[j];k++) for(l=0; l<rot_dims[j]; l++) // MPI_Pack((((((polymer->back)+j)->side)+k)->rot)+l,1,Rottype,buffer_rot,buffer_rot_size,&position,MPI_COMM_WORLD); // MPI_Send(buffer_rot,position,MPI_PACKED,i+1, 2000000+1000*i, MPI_COMM_WORLD); MPI_Send(((((((polymer+ipolymer)->back)+j)->side)+k)->rot)+l, 1, Rottype, i+1, 2000000+1000*i+100*j+10*k+l, MPI_COMM_WORLD); } if(iproc==i+1) { // MPI_Recv(buffer_rot,buffer_rot_size,MPI_PACKED,i,2000000+1000*i, MPI_COMM_WORLD, &astatus); // position=0; for(j=0; j<nback;j++) for(k=0; k<side_dims[j];k++) for(l=0; l<rot_dims[j]; l++) // MPI_Unpack(buffer_rot,buffer_rot_size,&position,(((((replica->back)+j)->side)+k)->rot)+l,1,Rottype,MPI_COMM_WORLD); MPI_Recv(((((((replica+ipolymer)->back)+j)->side)+k)->rot)+l, 1, Rottype, i, 2000000+1000*i+100*j+10*k+l , MPI_COMM_WORLD, &astatus); } //} //sidechains i+i -> i // if(!nosidechains) // { if(iproc==i+1) { position=0; for(j=0; j<nback;j++) for(k=0; k<side_dims[j];k++) MPI_Pack(((((polymer+ipolymer)->back)+j)->side)+k,1,Sidetype,buffer_side,buffer_side_size,&position,MPI_COMM_WORLD); MPI_Send(buffer_side,position,MPI_PACKED,i, 3000000+100*i, MPI_COMM_WORLD); // for(j=0; j<nback;j++) for(k=0; k<((polymer->back)+j)->nside;k++) // MPI_Send((((polymer->back)+j)->side)+k, 1, Sidetype, i, 3000000+100*i+10*j+k, MPI_COMM_WORLD); } if(iproc==i) { MPI_Recv(buffer_side,buffer_side_size,MPI_PACKED,i+1,3000000+100*i, MPI_COMM_WORLD, &astatus); position=0; for(j=0; j<nback;j++) for(k=0; k<side_dims[j];k++) MPI_Unpack(buffer_side,buffer_side_size,&position,((((replica+ipolymer)->back)+j)->side)+k,1,Sidetype,MPI_COMM_WORLD); // for(j=0; j<nback;j++) for(k=0; k<((replica->back)+j)->nside;k++) // MPI_Recv((((replica->back)+j)->side)+k, 1, Sidetype, i+1, 3000000+100*i+10*j+k, MPI_COMM_WORLD, &astatus); } //rotamers i+1 -> i if(iproc==i+1) { /* position=0; for(j=0; j<nback;j++) for(k=0; k<((polymer->back)+j)->nside;k++) for(l=0; l<rot_dims[j]; l++) MPI_Pack((((((polymer->back)+j)->side)+k)->rot)+l,1,Rottype,buffer_rot,buffer_rot_size,&position,MPI_COMM_WORLD); MPI_Send(buffer_rot,position,MPI_PACKED,i, 4000000+1000*i, MPI_COMM_WORLD); */ for(j=0; j<nback;j++) for(k=0; k<(((polymer+ipolymer)->back)+j)->nside;k++) for(l=0; l<(((polymer+ipolymer)->back)+j)->nrot; l++) MPI_Send(((((((polymer+ipolymer)->back)+j)->side)+k)->rot)+l, 1, Rottype, i, 4000000+1000*i+100*j+10*k+l, MPI_COMM_WORLD); } if(iproc==i) { /* MPI_Recv(buffer_rot,buffer_rot_size,MPI_PACKED,i+1,4000000+1000*i, MPI_COMM_WORLD, &astatus); position=0; for(j=0; j<nback;j++) for(k=0; k<((replica->back)+j)->nside;k++) for(l=0; l<rot_dims[j]; l++) MPI_Unpack(buffer_rot,buffer_rot_size,&position,(((((replica->back)+j)->side)+k)->rot)+l,1,Rottype,MPI_COMM_WORLD); */ for(j=0; j<nback;j++) for(k=0; k<(((replica+ipolymer)->back)+j)->nside;k++) for(l=0; l<(((replica+ipolymer)->back)+j)->nrot; l++) MPI_Recv(((((((replica+ipolymer)->back)+j)->side)+k)->rot)+l, 1, Rottype, i+1, 4000000+1000*i+100*j+10*k+l , MPI_COMM_WORLD, &astatus); } free(buffer_side); } free(buffer_back); }//end of ipolymer loop ex_acc[i]++; //accepted exchange counter x[i]=1; x[i+1]=1; }//end of accepted exchange // if not accepted else { x[i]=0; x[i+1]=0; } ex_count[i]++; //tried exchange counter a=0; } if(x[iproc]==1) { CopyAllPolymers(replica,polymer,parms->npol,parms->nosidechains,parms->nosidechains); CopyAllPolymers(replica,oldp,parms->npol,parms->nosidechains,parms->nosidechains); //etot=Totalenergy : polymer and oldp contacts must be recomputed polymer->etot = TotalEnergy(polymer,u,parms,parms->npol,1,parms->nosidechains,parms->debug,iproc); oldp->etot=TotalEnergy(oldp,u,parms,parms->npol,1,parms->nosidechains,parms->debug,iproc); if (parms->shell==1) { UpdateShell(polymer,parms); CopyShell(polymer,oldp,parms); parms->ishell=0; } } // free(buffer_back); return a; }
int LocalMove(struct s_polymer *p, struct s_polymer *oldp,struct s_polymer *fragment,struct s_potential *pot,int nmul,struct s_mc_parms *parms, double t) { int ok=0,nang=0; int iw,ip,iapdbtocheck,i,m; double deltaE; double detL1,detL2,detA1,detA2,W1,W2,psisquared,e; ip=irand(parms->npol); iw=(nmul-1)+irand( (p+ip)->nback-nmul+1 ); //iw=20; for(i=0; i<nmul; i++) { nang+=((((p+ip)->back)+iw-nmul+i)+1)->move; } deltaE = -GetEnergyMonomerRange(p,iw-nmul+1,iw+1,ip); if(iw==((p+ip)->nback-1)) //pivot forward OK { for(i=0; i<nang; i++) (fragment+ip)->d_ang[i]=parms->dw_mpivot*(0.05-frand()); if (!parms->nodihpot) for(i=0; i<nmul+3; i++) { deltaE-=(((p+ip)->back)+iw-nmul+i+1)->e_dih; } m=0; for(i=0; i<nmul; i++) { if( (((p+ip)->back)+iw+i-nmul+2)->move==1) { ok*=PivotForward((p+ip),iw-nmul+i+1,(fragment+ip)->d_ang[m],nmul-i-2,parms); m++; if(m==nang) break; } } if(!parms->nosidechains) { ok*=AddSidechain(p,iw-nmul+1,iw+1,ip); } deltaE += EnergyMonomerRange(p,pot,iw-nmul+1,iw+1,ip,parms->npol,parms->shell,1,parms->nosidechains,parms->disentangle,parms->hb); if (!parms->nodihpot) for(i=0; i<nmul+3; i++) { deltaE+=EnergyDihedrals(p,pot,iw-nmul+i+1,ip,1); } ok*=Metropolis(deltaE,t,p->tables); if(ok==0) { UpdateMonomerRange(oldp,p,iw-nmul+1,iw+1,ip,parms->shell); } else { //move accepted UpdateMonomerRange(p,oldp,iw-nmul+1,iw+1,ip,parms->shell); p->etot+=deltaE; parms->acc++; } } //end of forward else if(iw==nmul-1) //pivot backward OK { for(i=0; i<nang; i++) (fragment+ip)->d_ang[i]=parms->dw_mpivot*(0.05-frand()); if (!parms->nodihpot) for(i=0; i<nmul+3; i++) { deltaE-=(((p+ip)->back)+i)->e_dih; } m=0; for(i=0; i<nmul; i++) { if( (((p+ip)->back)+iw-i)->move==1) { ok*=PivotBackward((p+ip),iw-i,(fragment+ip)->d_ang[m],nmul-i-2,parms); m++; if(m==nang) break; } } if(!parms->nosidechains) ok*=AddSidechain(p,0,iw+1,ip); deltaE += EnergyMonomerRange(p,pot,0,iw+1,ip,parms->npol,parms->shell,1,parms->nosidechains,parms->disentangle,parms->hb); if (!parms->nodihpot) for(i=0; i<nmul+3; i++) { deltaE+=EnergyDihedrals(p,pot,i,ip,1); } ok*=Metropolis(deltaE,t,p->tables); if(ok==0) { UpdateMonomerRange(oldp,p,0,iw+1,ip,parms->shell); } else { UpdateMonomerRange(p,oldp,0,iw+1,ip,parms->shell); p->etot+=deltaE; parms->acc++; } } //end of backward else if(iw!=((p+ip)->nback-2))//pivot local { if((((p+ip)->back)+iw+1)->iapdb==0) iapdbtocheck=1; if((((p+ip)->back)+iw+1)->iapdb==1) iapdbtocheck=2; if((((p+ip)->back)+iw+1)->iapdb==2) iapdbtocheck=0; int out; Gaussian_Angles((fragment+ip)->g_ang,nang); Compute_G(fragment,p,ip,iw-nmul+1,nmul,nang,parms); MatA((fragment+ip)->A,(fragment+ip)->G,nang,parms->bgs_a,parms->bgs_b); Cholesky_2((fragment+ip)->L,(fragment+ip)->A,nang); psisquared=Squared_n_Norma((fragment+ip)->g_ang,nang); e=exp(-psisquared); detL1=DetTriang((fragment+ip)->L,nang); detA1=detL1*detL1; W1=e * sqrt(detA1); InvertTriang((fragment+ip)->Y,(fragment+ip)->L,nang); TransposedMatOnVect((fragment+ip)->Y,(fragment+ip)->g_ang,(fragment+ip)->d_ang,nang); if(!parms->nodihpot) for(i=0; i<nmul+3; i++) { deltaE -= (((p+ip)->back)+iw-nmul+i+1)->e_dih; } if(!parms->noangpot) { deltaE-=(((p+ip)->back)+iw)->e_ang; deltaE-=(((p+ip)->back)+iw+1)->e_ang; } m=0; for(i=0; i<nmul; i++) { if( (((p+ip)->back)+iw+i-nmul+2)->move==1) { ok*=PivotForward((p+ip),iw-nmul+i+1,(fragment+ip)->d_ang[m],nmul-i-2,parms); m++; if(m==nang) break; } } double rc2=parms->r_cloose*parms->r_cloose; double dihedral=Dihedral( (((p+ip)->back)+iw-iapdbtocheck)->pos, (((p+ip)->back)+iw+1-iapdbtocheck)->pos, (((p+ip)->back)+iw+2-iapdbtocheck)->pos, (((p+ip)->back)+iw+3-iapdbtocheck)->pos, p->tables, &out ); // fprintf(stderr,"Checking Dihedral: backbone atoms %d,%d,%d,%d\n",+iw-iapdbtocheck,+iw+1-iapdbtocheck,+iw+2-iapdbtocheck,+iw+3-iapdbtocheck); if( DAbs (Dist2( (((p+ip)->back)+iw)->pos,(((p+ip)->back)+iw+1)->pos ) -(((p+ip)->back)+iw)->d2_next < rc2 ) && DAbs( Angle( (((p+ip)->back)+iw-1)->pos, (((p+ip)->back)+iw)->pos, (((p+ip)->back)+iw+1)->pos, (p+ip)->tables, &out) - (((p+ip)->back)+iw-1)->a_next) < 0.05 && DAbs(180-DAbs(dihedral)) < DELTAOMEGA) { if(!parms->nosidechains) { ok *= AddSidechain(p,iw-nmul+1,iw+1,ip); } deltaE += EnergyMonomerRange(p,pot,iw-nmul+1,iw+1,ip,parms->npol,parms->shell,1,parms->nosidechains,parms->disentangle,parms->hb); if (!parms->nodihpot) for(i=0; i<nmul+3; i++) { deltaE+=EnergyDihedrals(p,pot,iw-nmul+i+1,ip,1); } if(!parms->noangpot) { // fprintf(stderr,"\nCOMPUTING ANGLE ENERGY deltaE=%lf\t",deltaE); deltaE+=EnergyAngles(p,pot,iw,ip,1); deltaE+=EnergyAngles(p,pot,iw+1,ip,1); // fprintf(stderr,"-> %lf\n",deltaE); } Compute_G(fragment,p,ip,iw-nmul+1,nmul,nang,parms); MatA((fragment+ip)->A,(fragment+ip)->G,nang,parms->bgs_a,parms->bgs_b); Cholesky_2((fragment+ip)->L,(fragment+ip)->A,nang); detL2=DetTriang((fragment+ip)->L,nang); detA2=detL2*detL2; TransposedMatOnVect((fragment+ip)->L,(fragment+ip)->d_ang,(fragment+ip)->g_ang,nang); psisquared=Squared_n_Norma((fragment+ip)->g_ang,nang); e=exp(-psisquared); W2=e*sqrt(detA2); ok*=B_Metropolis(deltaE,t,W2,W1,p->tables); if(ok==0) //move rejected { UpdateMonomerRange(oldp,p,iw-nmul+1,iw+1,ip,parms->shell); } else //move accepted { UpdateMonomerRange(p,oldp,iw-nmul+1,iw+1,ip,parms->shell); p->etot+=deltaE; parms->acc++; } }//end of loose condition else //if not loose pivot { ok=0; UpdateMonomerRange(oldp,p,iw-nmul+1,iw+1,ip,parms->shell); } }//end of local pivot parms->mov++; return ok; }
/*PARALELO*/ int main( int argc, char *argv[] ) { int round, ir, ir_min, count, ran_num, N, N_total, N_input; double x[NMAX], y[NMAX], x_local[NMAX], y_local[NMAX], delta; double maxx, maxy, minx, miny, tempm; int plot_control; double f, sumf, sumf2, local_sumf, local_sumf2, total_sumf, total_sumf2, integral, sigma; unsigned int semilla; int node, myid, numprocs; int number, nmax; MPI_Status recv_status; /* join the MPI virtual machine */ MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &myid); MPI_Comm_size(MPI_COMM_WORLD, &numprocs); nmax = NMAX - ( NMAX % ( numprocs-1) ); /* adjust NMAX for # nodes */ delta = 0.2; /* Metropolis delta - size of jump */ x[0] = 0.5; /* initial position in plane */ y[0] = 0.6; maxx=x[0]; minx=x[0]; maxy=y[0]; miny=y[0]; local_sumf=0.0; total_sumf=0.0; local_sumf2=0.0; total_sumf2=0.0; if ( myid == 0 ) { /* plot control */ /* plot_control = 0; if ( argc == 2 ) if ( strcmp( argv[1], "-p") == 0 )*/ plot_control = 0; N_total = 0; /* total # of random numbers */ ran_num = 0; /* current number of random numbers */ count = 1; /* counter for selected numbers */ f = func(x[0],y[0]); /* Monte-Carlo sums */ sumf = f; sumf2 = f*f ; semilla=(unsigned int)time((time_t *)NULL); srand((unsigned int)(semilla)+131*myid); /* accuracy improvement */ fprintf( stderr, "\n Enter # of random number to use ( 0 to quit ): " ); while ( scanf( "%d", &N_input ) != EOF && N_input > 0 ) { /* commensurate with proc # ? */ if ( N_input % (numprocs-1) != 0 ) N_input = N_input - ( N_input % (numprocs-1) ); printf( " # of random numbers used = %d \n", N_input ); /* add to total */ N_total = N_total + N_input; while ( ran_num < N_total ) { /* # of random numbers to generate */ N = N_total - ran_num; if ( N > nmax ) N = nmax; /* send N to nodes */ number = N / (numprocs-1) + 1; /* generate & send random */ /* numbers to each node */ for ( node=1 ; node<numprocs ; node++ ) { MPI_Ssend(&number, 1, MPI_INT, node, 121, MPI_COMM_WORLD); if ( N != 0 ) { /* Metropolis Algorithm */ Metropolis ( x, y, weight, delta, number , &count ); /* number control */ ran_num = ran_num + number - 1; /* send x & y to nodes */ /* send x & y to nodes */ MPI_Ssend( &x[1], number-1, MPI_DOUBLE, node, 123, MPI_COMM_WORLD ); MPI_Ssend( &y[1], number-1, MPI_DOUBLE, node, 123, MPI_COMM_WORLD ); /* plot info */ if ( plot_control == 1 ) { for ( ir=1 ; ir<number ; ir++ ) printf( " %f %f\n", x[ir], y[ir] ); } /* ready for next bunch of */ /* random numbers */ x[0] = x[number-1]; y[0] = y[number-1]; } /* if */ } /* for */ /* get sums from nodes */ MPI_Reduce ( &local_sumf, &total_sumf, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD ); MPI_Reduce ( &local_sumf2, &total_sumf2, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD ); tempm=minx; MPI_Allreduce(&tempm,&minx,1,MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD); tempm=miny; MPI_Allreduce(&tempm,&miny,1,MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD); tempm=maxx; MPI_Allreduce(&tempm,&maxx,1,MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); tempm=maxy; MPI_Allreduce(&tempm,&maxy,1,MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); /* add to global totals */ /* add to global totals */ sumf = sumf + total_sumf; sumf2 = sumf2 + total_sumf2; } /* while ran_num */ /* finalize Monte-Carlo calc */ integral = sumf/(double)N_total; sigma = sqrt( ( sumf2/(double)N_total - integral*integral ) / (double)N_total ); fprintf( stderr, " Max x = %f Min x = %f Max y = %f Min y = %f\n", maxx,minx,maxy,miny); fprintf( stderr, " Integral = %f +/- sigma = %f \n", integral, sigma ); fprintf( stderr, "\n Enter # of random number to use ( 0 to quit ): " ); } /* while scanf */ /* siganl -> nodes to suicide */ number = -1; for ( node=1 ; node<numprocs ; node++ ) MPI_Ssend(&number, 1, MPI_INT, node, 121, MPI_COMM_WORLD); /* Acceptance ratio - should be > ~0.5 */ fprintf( stderr, "\n Acceptance ratio: %d %d %f\n\n", N_total, count, (double)N_total/(double)count ); /* end main code */ MPI_Finalize(); exit(1); } /* if my_node */ else { /* loop over all bunches of */ /* random numbers */ for ( ; ; ) { /* receive signal or # of numbers */ MPI_Recv( &number, 1, MPI_INT, 0, 121, MPI_COMM_WORLD, &recv_status); /* end code - suicide */ if ( number <0 ) { MPI_Finalize(); exit(0); } else if ( number > 0 ) /* perform MC integral */ { MPI_Recv( &x_local, number-1, MPI_DOUBLE, 0, 123, MPI_COMM_WORLD, &recv_status); MPI_Recv( &y_local, number-1, MPI_DOUBLE, 0, 123, MPI_COMM_WORLD, &recv_status); /* Monte-Carlo integral */ local_sumf = 0.0; local_sumf2 = 0.0; for ( ir=0 ; ir<number-1 ; ir++ ) { f = func( x_local[ir], y_local[ir] ); local_sumf = local_sumf + f; local_sumf2 = local_sumf2 + f*f; if (x_local[ir]<minx) minx=x_local[ir]; if (x_local[ir]>maxx) maxx=x_local[ir]; if (y_local[ir]<miny) miny=y_local[ir]; if (y_local[ir]>maxy) maxy=y_local[ir]; } /* send partial sums to node 0 */ MPI_Reduce ( &local_sumf, &total_sumf, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD ); MPI_Reduce ( &local_sumf2, &total_sumf2, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD ); tempm=minx; MPI_Allreduce(&tempm,&minx,1,MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD); tempm=miny; MPI_Allreduce(&tempm,&miny,1,MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD); tempm=maxx; MPI_Allreduce(&tempm,&maxx,1,MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); tempm=maxy; MPI_Allreduce(&tempm,&maxy,1,MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD); } } } /* Acceptance ratio - should be > ~0.5 */ if ( myid == 0 ) fprintf( stderr, "\n Acceptance ratio: %f\n\n", (double)N_total/(double)count ); /* end of code */ MPI_Finalize(); return 0; }