Example #1
0
void
replace_coordinates(struct atomgrp* ag, const char* pdb_path)
{
    struct atomgrp* ag_new = read_pdb_nopar(pdb_path);

    if (ag_new->natoms != ag->natoms) {
        _mol_error("new atomgroup has %d atoms, old has %d atoms", ag_new->natoms, ag->natoms);
        exit(EXIT_FAILURE);
    }

    int list[ag->natoms];
    for (int i=0; i<ag->natoms; i++) {
        list[i] = i;
    }

    setup_subag(ag, ag_new, ag->natoms, list);

    free_atomgrp(ag_new);
}
void accs2(struct atomgrp* ag, float r_solv, short cont_acc, float* as)
{
	const int NAC=5000;  /* max number of atoms in a cube */

/* integration increment */
	const float P=0.01;

	int i, sint=sizeof(int), sflo=sizeof(float);
	int n_at1=ag->natoms;
	float  xmin, xmax, ymin, ymax, zmin, zmax;
	float rmax=0;

	float pi=acos(-1.0);
	float pix2=2.0*pi;
	float ri, xi, yi, zi;

	float *x;
	float *y;
	float *z;
	float *r;
	float *r2;

	float *dx;
	float *dy;
	float *d;
	float *dsq;
	float *arcif;
	int *inov;


	float dmax;
	int idim;
	int jidim;
	int kjidim;
	int *itab;
	int *natm;
	int* cube;

	int j, k, l, m, n, kji;

	int ir, io, in, mkji, nm, nzp, karc;
	float area, xr, yr, zr, rr, rrx2, rr2, b, zres, zgrid;
	float rsec2r, rsecr, rsec2n, rsecn;
	float calpha, alpha, beta, ti, tf, arcsum, parea, t, tt;

/* eliminate atoms with zero radii */
	int n_at=0;
	int *restat;
	i=n_at1*sint;
	restat=_mol_malloc(i);
	for(i=0; i<n_at1; i++)
	{
		as[i]=0.0;
		ri=ag->atoms[i].rminh;
		if(ri>0.0)restat[n_at++]=i;
	}

/* initialize boundary constants */
	xmin=ag->atoms[restat[0]].X;
	xmax=xmin;
	ymin=ag->atoms[restat[0]].Y;
	ymax=ymin;
	zmin=ag->atoms[restat[0]].Z;
	zmax=zmin;

/* allocate general atom related arrays */
	i=n_at*sflo;
	x=_mol_malloc(i);
	y=_mol_malloc(i);
	z=_mol_malloc(i);
	r=_mol_malloc(i);
	r2=_mol_malloc(i);

/* allocate arrays for neighbouring atoms */
	dx=_mol_malloc(i);
	dy=_mol_malloc(i);
	d=_mol_malloc(i);
	dsq=_mol_malloc(i);
	arcif=_mol_malloc(2*2*i);
	i=n_at*sint;
	inov=_mol_malloc(i);

/* calculate sizes and dimensions*/
	for(i=0; i<n_at; i++)
	{
		ri=ag->atoms[restat[i]].rminh;
		ri=ri+r_solv;
		r[i]=ri;
		r2[i]=ri*ri;
		if(ri>rmax)rmax=ri;
		x[i]=ag->atoms[restat[i]].X;
		if(xmin>x[i])xmin=x[i];
		if(xmax<x[i])xmax=x[i];
		y[i]=ag->atoms[restat[i]].Y;
		if(ymin>y[i])ymin=y[i];
		if(ymax<y[i])ymax=y[i];
		z[i]=ag->atoms[restat[i]].Z;
		if(zmin>z[i])zmin=z[i];
		if(zmax<z[i])zmax=z[i];
	}
	dmax=rmax*2.0;

	i=(xmax-xmin)/dmax+1;
	idim=i<3?3:i;

	i=(ymax-ymin)/dmax+1;
	jidim=i<3?3:i;
	jidim*=idim;

	i=(zmax-zmin)/dmax+1;
	kjidim=i<3?3:i;
	kjidim*=jidim;				/* total number of cubes */


/* map atoms to adjacent cubes */
/* allocate cubical arrays */

	i=kjidim*sint;
	itab=_mol_malloc(i);		/* number of atoms in each cube */
	for(i=0; i<kjidim; i++)itab[i]=0;

	i=NAC*kjidim*sint;
	natm=_mol_malloc(i);		/* atom index in each cube */

	i=n_at*sint;
	cube=_mol_malloc(i);		/* cube number for each atom */

	for(l=0; l<n_at; l++)
	{
		i=(x[l]-xmin)/dmax;
		j=(y[l]-ymin)/dmax;
		k=(z[l]-zmin)/dmax;
		kji=k*jidim+j*idim+i;	/* cube number */
		n=itab[kji]+1;
		if(n>NAC)
		{
			_mol_error("number of atoms in a cube %d is above the maximum  NAC= %d\n", n, NAC);
			exit(EXIT_FAILURE);
		}
		itab[kji]=n;
		natm[kji*NAC+n-1]=l;
		cube[l]=kji;
	}

/* main loop over atoms */
	zi=1.0/P+0.5;
	nzp=zi;		 /* number of z planes */

	for (ir=0; ir<n_at; ir++)
	{
		kji=cube[ir];
		io=0;					/* number of neighbouring atoms */
		area=0.0;
		xr=x[ir];
		yr=y[ir];
		zr=z[ir];
		rr=r[ir];
		rrx2=rr*2;
		rr2=r2[ir];
/* loops over neighbouring cubes */
		for (k=-1; k<2; k++)
		{
			for(j=-1; j<2; j++)
			{
				for(i=-1; i<2; i++)
				{
					mkji=kji+k*jidim+j*idim+i;
					if(mkji<0)continue;
					if(mkji>=kjidim)goto esc_cubes;
					nm=itab[mkji];
					if(nm<1)continue;
					for(m=0; m<nm; m++)
					{
						in=natm[mkji*NAC+m];
						if(in!=ir)
						{
							xi=xr-x[in];
							yi=yr-y[in];
							dx[io]=xi;
							dy[io]=yi;
							ri=xi*xi+yi*yi;
							dsq[io]=ri;
							d[io]=sqrtf(ri);
							inov[io]=in;
							io++;
						}
					}
				}
			}
		}

		esc_cubes:
		if(io!=0)
		{
			zres=rrx2/nzp;	/* separation between planes */
			zgrid=z[ir]-rr-zres/2.0;	/* z level */

			for(i=0; i<nzp; i++)
			{
				zgrid+=zres;
/* radius of the circle intersection with a z-plane */
				zi=zgrid-zr;
				rsec2r=rr2-zi*zi;
				rsecr=sqrtf(rsec2r);

				karc=0;
				for(j=0; j<io; j++)
				{
					in=inov[j];
/* radius of the circle for a neighbour */
					zi=zgrid-z[in];
					rsec2n=r2[in]-zi*zi;
					if(rsec2n<=0.0)continue;
					rsecn=sqrtf(rsec2n);
/* are they close? */
					if(d[j]>=rsecr+rsecn)continue;
/* do they intersect? */
					b=rsecr-rsecn;
					if(b<=0.0)
					{
						if(d[j]<=-b)goto next_plane;
					}
					else
					{
						if(d[j]<=b)continue;
					}
					calpha=(dsq[j]+rsec2r-rsec2n)/(2.0*d[j]*rsecr);
					if(calpha>=1.0)continue;
/* yes, they do */
					alpha=acosf(calpha);
					beta=atan2f(dy[j],dx[j])+pi;
					ti=beta-alpha;
					tf=beta+alpha;
					if(ti<0.0)ti+=pix2;
					if(tf>pix2)tf-=pix2;
					arcif[karc]=ti;
					if(tf<ti)
					{
						arcif[karc+1]=pix2;
						karc+=2;
						arcif[karc]=0.0;
					}
					arcif[karc+1]=tf;
					karc+=2;
				}
/* find the atom accessible surface increment in z-plane */

				karc/=2;
				if(karc==0)
					arcsum=pix2;
				else
				{
					qsort(arcif, karc, 2*sizeof(arcif[0]), accs_comp);
					arcsum=arcif[0];
					t=arcif[1];
					if(karc>1)
					{
						for(k=2; k<karc*2; k+=2)
						{
							if(t<arcif[k])arcsum+=(arcif[k]-t);
							tt=arcif[k+1];
							if(tt>t)t=tt;
						}
					}
					arcsum+=(pix2-t);
				}
				parea=arcsum*zres;
				area+=parea;
				next_plane:;
			}
		}
		else
		{
			area=pix2*rrx2;
		}

		ri=rr-r_solv;
		if(cont_acc)
			b=area*ri*ri/rr;
		else
			b=area*rr;
		as[restat[ir]]=b;
	}
/* free all */
	free(x);
	free(y);
	free(z);
	free(r);
	free(r2);
	free(dx);
	free(dy);
	free(d);
	free(dsq);
	free(arcif);
	free(inov);
	free(itab);
	free(natm);
	free(cube);
	free(restat);
}