Exemple #1
0
//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;
    };	
	
}
Exemple #2
0
/*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];
		};
    };
}
Exemple #3
0
/*
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];
		};
	};
}
Exemple #4
0
//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];
		};
	};
}
Exemple #5
0
/*****************************************************************************
 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;
}