The RigidCLL library


RigidCLL.cpp

Go to the documentation of this file.
00001 #include "RigidCLL.h"
00002 
00013 #include <iostream>
00014 #include <fstream>
00015 #include <stdlib.h>
00016 #include <math.h>
00017 #include <limits>
00018 
00039 #define BB_MARGIN 2
00040 
00046 #define MAX_UINT std::numeric_limits<unsigned int>::max()
00047 
00055 #define ERROR(s) {cerr<<s<<"\n";exit(0);}
00056 
00062 #define INF std::numeric_limits<double>::max()
00063 
00070 #define MANHATTAN_DISTANCE(dx,dy,dz,a1,a2)  dx=a1->cp[0]-a2->cp[0];dy=a1->cp[1]-a2->cp[1];dz=a1->cp[2]-a2->cp[2]
00071 
00072 /*************************************************************************/
00073 /*************************************************************************/
00074 /*                          AtomInfo methods                             */
00075 /*************************************************************************/
00076 /*************************************************************************/
00077 
00078 AtomInfo::AtomInfo(unsigned int identifier,unsigned int rigid,double x,double y,double z,double radius)
00079 {
00080   if (radius<=0)
00081     ERROR("The atom radius must be positive.");
00082   
00083   id=identifier;
00084   rID=rigid;
00085 
00086   /* The current and original positions of the atom */
00087   cp[0]=op[0]=x;
00088   cp[1]=op[1]=y;
00089   cp[2]=op[2]=z;
00090 
00091   r=radius;
00092 
00093   /* Indexes of the cell including this atom */
00094   c[0]=c[1]=c[2]=0; /* not used until the grid is defined. */
00095 }
00096 
00097 void AtomInfo::move(RigidTransform t)
00098 {
00099   cp[0]=t[0][0]*op[0]+t[0][1]*op[1]+t[0][2]*op[2]+t[0][3];
00100   cp[1]=t[1][0]*op[0]+t[1][1]*op[1]+t[1][2]*op[2]+t[1][3];
00101   cp[2]=t[2][0]*op[0]+t[2][1]*op[1]+t[2][2]*op[2]+t[2][3];
00102 }
00103 
00104 double AtomInfo::distance(AtomInfo *a)
00105 {
00106   double dx,dy,dz;
00107 
00108   MANHATTAN_DISTANCE(dx,dy,dz,this,a);
00109 
00110   return(sqrt(dx*dx+dy*dy+dz*dz));
00111 }
00112 
00113 ostream& operator<<(ostream& os,const AtomInfo &a)
00114 {
00115   os << "id:" << a.id ;
00116   os << " r:" << a.rID ;
00117   os << " op:(" << a.op[0] << "," << a.op[1] << "," << a.op[2] << ")";
00118   os << " cp:(" << a.cp[0] << "," << a.cp[1] << "," << a.cp[2] << ")";
00119 
00120   return(os);
00121 }
00122 
00123 /*************************************************************************/
00124 /*************************************************************************/
00125 /*                          AtomPair methods                             */
00126 /*************************************************************************/
00127 /*************************************************************************/
00128 
00129 AtomPair::AtomPair(AtomInfo *atom1,AtomInfo *atom2,double dst2)
00130 {
00131   a1=atom1->id;
00132   r1=atom1->rID;
00133   a2=atom2->id;
00134   r2=atom2->rID;
00135   d2=dst2;
00136 }
00137 
00138 bool AtomPair::operator<(const AtomPair a) const
00139 {
00140   unsigned int min1,min2,max1,max2;
00141 
00142   min1=(this->a1<this->a2?this->a1:this->a2); // minimum of the two atoms in p1
00143   max1=(this->a1<this->a2?this->a2:this->a1); // maximum of the two atoms in p1
00144 
00145   min2=(a.a1<a.a2?a.a1:a.a2); // minimum of the two atoms in p2
00146   max2=(a.a1<a.a2?a.a2:a.a1); // maximum of the two atoms in p2
00147 
00148   return((min1<min2)||((min1==min2)&&(max1<max2)));
00149 }
00150 
00151 ostream& operator<<(ostream& os,const AtomPair &a)
00152 {
00153   if (a.a1<a.a2)
00154     os << "  (" << a.a1 << "[" << a.r1  << "]," << a.a2 << "[" << a.r2  << "])";  
00155   else
00156     os << "  (" << a.a2 << "[" << a.r2  << "]," << a.a1 << "[" << a.r1  << "])";
00157 
00158   os << " d: " << sqrt(a.d2);  
00159   return(os);
00160 }
00161 
00162 bool AtomPair::operator==(AtomPair &a)
00163 {
00164   /* we only need to compare atom identifiers */
00165   return(((this->a1==a.a1)&&(this->a2==a.a2))||
00166          ((this->a1==a.a2)&&(this->a2==a.a1)));
00167 }
00168 
00169 /*************************************************************************/
00170 /*************************************************************************/
00171 /*                          CellInfo methods                             */
00172 /*************************************************************************/
00173 /*************************************************************************/
00174 
00175 CellInfo::CellInfo()
00176 {
00177   mobileID=MAX_UINT;
00178   fixedID=MAX_UINT;
00179 }
00180 
00181 void CellInfo::Reset()
00182 {
00183   mobileID=MAX_UINT;
00184 }
00185 
00186 void CellInfo::AddFixedAtom(unsigned int id,unsigned int *fixedLL)
00187 {
00188   fixedLL[id]=fixedID;
00189   fixedID=id;
00190 }
00191 
00192 void CellInfo::AddMobileAtom(unsigned int id,unsigned int *mobileLL)
00193 {
00194   mobileLL[id]=mobileID;
00195   mobileID=id;
00196 }
00197 
00198 /*************************************************************************/
00199 /*************************************************************************/
00200 /*                     RigidCLL private methods                          */
00201 /*************************************************************************/
00202 /*************************************************************************/
00203 
00204 void RigidCLL::InitRigidCLL()
00205 {
00206   o[0]=o[1]=o[2]=0.0;
00207   s[0]=s[1]=s[2]=0;
00208   grid=NULL;
00209   fixedLL=NULL;
00210   mobileLL=NULL;
00211   cutoff=0.0; /* default is steric clash */
00212   d=0.0; /* updated in warmup */
00213   cr.firstAtom=cr.lastAtom=MAX_UINT;
00214   nFixed=0;
00215   nMobile=0;
00216   rID=0;
00217   lastInGrid=MAX_UINT;
00218   checkInteraction=NULL;
00219 }
00220 
00221 void RigidCLL::UpdateCell(AtomInfo *a)
00222 {
00223   unsigned int i;
00224   
00225   for(i=0;i<3;i++)
00226     {
00227       a->c[i]=(unsigned int)floor((a->cp[i]-o[i])/d);
00228       #if (RIGIDCLL_DEBUG)
00229         /* atoms can not be in the limit of the grid, otherwise
00230            the search will fail */
00231         if ((a->c[i]<=0)||(a->c[i]>=s[i]-1))
00232           ERROR("Cell out of range in UpdateCell");
00233       #endif
00234     }
00235 }
00236 
00237 void RigidCLL::InsertFixedInGrid(unsigned int n)
00238 {
00239   AtomInfo *a;
00240   
00241   #if (RIGIDCLL_DEBUG)
00242     if (grid==NULL)
00243       ERROR("Inserting atom in an empty grid. Use the WarmUp method.");
00244   #endif
00245 
00246   a=&(fixedAtoms[n]);
00247 
00248   /* For fixed atoms we do not have the grid cell pre-computed */
00249   UpdateCell(a);
00250 
00251   grid[a->c[0]][a->c[1]][a->c[2]].AddFixedAtom(n,fixedLL);
00252 
00253   /* fixed atoms are never removed from the grid: there is no need
00254      to update the 'lastInGrid' */
00255 }
00256 
00257 void RigidCLL::InsertMobileInGrid(unsigned int n)
00258 {
00259   AtomInfo *a;
00260   
00261   #if (RIGIDCLL_DEBUG)
00262     if (grid==NULL)
00263       ERROR("Inserting atom in an empty grid. Use the WarmUp method.");
00264   #endif
00265 
00266   /* for mobile atoms the position in the grid is already pre-computed */
00267 
00268   a=&(mobileAtoms[n]);
00269 
00270   grid[a->c[0]][a->c[1]][a->c[2]].AddMobileAtom(n,mobileLL);
00271   
00272   /* For mobile atoms we have to keep track of the last
00273      atom added to the grid. We assume that 'n' is
00274      monotonically increasing. */
00275   lastInGrid=n;
00276 }
00277 
00278 void RigidCLL::DeleteGrid()
00279 {
00280   if (grid!=NULL)
00281     {
00282       /* It would be a good idea to use the atoms (fixed and mobile) to identify
00283          the possibly used cells in the grid. In any case, to deallocate we
00284          need the two loos 'i' and 'j'.... so adding a fast loop over 'k'
00285          is probably a reasonable solution. */
00286 
00287       unsigned int i,j;
00288 
00289       for(i=0;i<s[0];i++)
00290         {
00291           for(j=0;j<s[1];j++)
00292             {
00293               delete[] grid[i][j];
00294             }
00295           delete[] grid[i];
00296         }
00297       delete[] grid;
00298 
00299       delete[] fixedLL;
00300       delete[] mobileLL;
00301       
00302       grid=NULL;
00303       fixedLL=NULL;
00304       mobileLL=NULL;
00305     }
00306 }
00307 
00308 void RigidCLL::DeleteInteractions()
00309 {
00310   if (checkInteraction!=NULL)
00311     {
00312       unsigned int i,nr;
00313 
00314       nr=rID+1;
00315       for(i=0;i<nr;i++)
00316         {
00317           delete [] checkInteraction[i];
00318         }
00319       delete [] checkInteraction;
00320 
00321       checkInteraction=NULL;
00322     }
00323 }
00324 
00325 void RigidCLL::InitInteractions()
00326 {
00327   unsigned int i,j,nr;
00328 
00329   /* If defining a rigid, close it first */
00330   if (cr.firstAtom!=MAX_UINT)
00331     EndRigid();
00332 
00333   /* now define the interaction table */
00334   nr=rID+1;
00335   checkInteraction=new bool*[nr];
00336   for(i=0;i<nr;i++)
00337     {
00338       checkInteraction[i]=new bool[nr];
00339       for(j=0;j<nr;j++)
00340         checkInteraction[i][j]=(i!=j); /* self-interactions are not considered */
00341     }
00342 }
00343 
00344 
00345 void RigidCLL::ResetQuery()
00346 {
00347   unsigned int j;
00348   AtomInfo *a1;
00349 
00350   if (lastInGrid!=MAX_UINT)
00351     {
00352       for(j=0;j<=lastInGrid;j++)
00353         {
00354           a1=&(mobileAtoms[j]);
00355           grid[a1->c[0]][a1->c[1]][a1->c[2]].Reset();
00356         }    
00357       lastInGrid=MAX_UINT;
00358     }
00359 }
00360 
00361 void RigidCLL::Move(RigidTransform *t)
00362 {
00363   unsigned int j;
00364   AtomInfo *a1;
00365       
00366   /* Move the atoms */
00367   for(j=0;j<nMobile;j++)
00368     {
00369       a1=&(mobileAtoms[j]);
00370       a1->move(t[a1->rID]);
00371     }
00372 }
00373 
00374 bool RigidCLL::Check27(AtomInfo *a1)
00375 {
00376   AtomInfo *a2;
00377   unsigned int ix,iy,iz,aID;
00378   double dx,dy,dz,r;
00379   bool collision=false;
00380 
00381   /* for neighbours */
00382   ix=a1->c[0]-1;
00383   while((!collision)&&(ix<=a1->c[0]+1)) 
00384     {
00385       iy=a1->c[1]-1;
00386       while((!collision)&&(iy<=a1->c[1]+1))
00387         {              
00388           iz=a1->c[2]-1;
00389           while((!collision)&&(iz<=a1->c[2]+1))
00390             {
00391               /* first we check for possible interaction with
00392                  the fixed atoms in the cell, if any */
00393               if (checkInteraction[a1->rID][0])
00394                 {
00395                   /* loop over the list of fixed atoms */
00396                   aID=grid[ix][iy][iz].fixedID;
00397                   while((!collision)&&(aID!=MAX_UINT))
00398                     {
00399                       a2=&(fixedAtoms[aID]);
00400                                 
00401                       MANHATTAN_DISTANCE(dx,dy,dz,a1,a2);
00402                       r=a1->r+a2->r;
00403 
00404                       collision=(dx*dx+dy*dy+dz*dz<=r*r);
00405                               
00406                       aID=fixedLL[aID];
00407                     }
00408                 }
00409               /* and now loop over the mobile atoms, if any */
00410               aID=grid[ix][iy][iz].mobileID;
00411               while((!collision)&&(aID!=MAX_UINT))
00412                 {
00413                   a2=&(mobileAtoms[aID]);
00414                                               
00415                   if (checkInteraction[a1->rID][a2->rID]) 
00416                     {
00417                       MANHATTAN_DISTANCE(dx,dy,dz,a1,a2);
00418                       r=a1->r+a2->r;
00419 
00420                       collision=(dx*dx+dy*dy+dz*dz<=r*r);
00421                     }
00422                   aID=mobileLL[aID];
00423                 }
00424               iz++;
00425             }
00426           iy++;
00427         }
00428       ix++;
00429     }
00430   
00431   return(collision);
00432 }
00433 
00434 /*************************************************************************/
00435 /*************************************************************************/
00436 /*                      RigidCLL public methods                          */
00437 /*************************************************************************/
00438 /*************************************************************************/
00439 
00440 RigidCLL::RigidCLL():fixedAtoms(),mobileAtoms(),rigids()
00441 {
00442   InitRigidCLL();
00443 }
00444 
00445 RigidCLL::RigidCLL(char *name):fixedAtoms(),mobileAtoms(),rigids()
00446 {
00447   ifstream file;
00448   unsigned int nr,na,i,j,k;
00449   double x,y,z,r;
00450   bool f;
00451 
00452   /* First, the standard init */
00453   InitRigidCLL();
00454 
00455   /* Now, we fill in the structure using data from the file */
00456   file.open(name);
00457 
00458   file>>nr;
00459 
00460   k=0;
00461   for(i=0;i<nr;i++)
00462     {
00463       file >> na;
00464       file >> f;
00465 
00466       if (!f)
00467         NewRigid();
00468       
00469       for(j=0;j<na;j++)
00470         {
00471           file >> x;
00472           file >> y;
00473           file >> z;
00474           file >> r;
00475 
00476           if (f)
00477             AddFixedAtom(k,x,y,z,r);
00478           else
00479             AddAtom(k,x,y,z,r);
00480           k++;
00481         }
00482 
00483       if (!f)
00484         EndRigid();
00485     }
00486 
00487   file.close();
00488 
00489   /* allow the interaction between all the rigid groups */
00490   InitInteractions();
00491 }
00492 
00493 unsigned int RigidCLL::GetNumRigids()
00494 {
00495   /* The group of fixed atoms counts as one rigid */
00496   return(rID+1);
00497 }
00498 
00499 void RigidCLL::SetCutOff(double c)
00500 {
00501   if (c<0.0)
00502     ERROR("The cutoff must be possitive");
00503 
00504   cutoff=c;
00505 
00506   /* a new cutoff -> re-define the grid. We delete
00507      it and it will be re-defined when necessary. */
00508   DeleteGrid();
00509 }
00510 
00511 double RigidCLL::GetCutOff()
00512 {  
00513   return(cutoff);
00514 }
00515 
00516 double RigidCLL::GetBBSize(unsigned int axis)
00517 {
00518   if ((axis<0)||(axis>2))
00519     ERROR("Axis out of range in GetBBSize");
00520 
00521   if ((grid==NULL)||(s[axis]==0))
00522     ERROR("Calling GetBBSize on non-initialized RigidCLL object (call the WarmUp method first)");
00523 
00524   return(s[axis]*d);
00525 }
00526 
00527 RigidCLL::~RigidCLL()
00528 {
00529   Reset();
00530 }
00531 
00532 void RigidCLL::AddFixedAtom(unsigned int id,double x,double y,double z,double r)
00533 {
00534   if (checkInteraction!=NULL)
00535     ERROR("Adding atoms to a closed model. Use the Reset method first.");
00536 
00537   fixedAtoms.push_back(AtomInfo(id,0,x,y,z,r));
00538   nFixed++;
00539 }
00540 
00541 void RigidCLL::AddFixedAtom(unsigned int id,double *p,double r)
00542 {
00543   AddFixedAtom(id,p[0],p[1],p[2],r);
00544 }
00545 
00546 unsigned int RigidCLL::NewRigid()
00547 {
00548   if (checkInteraction!=NULL)
00549     ERROR("Adding atoms to a closed model. Use the Reset method first.");
00550 
00551   /* If already defining a rigid, close it first */
00552   if (cr.firstAtom!=MAX_UINT)
00553     EndRigid();
00554 
00555   /* initialize the current rigid structure */
00556   cr.firstAtom=nMobile;
00557   rID++; /* mobile rigids are numbered form 1 */
00558 
00559   return(rID);
00560 }
00561 
00562 void RigidCLL::AddAtom(unsigned int id,double x,double y,double z,double r)
00563 {
00564   if (cr.firstAtom==MAX_UINT)
00565     ERROR("Adding an atom out of a rigid group. Use NewRigid first.");
00566 
00567   mobileAtoms.push_back(AtomInfo(id,rID,x,y,z,r));
00568   nMobile++;
00569 }
00570 
00571 void RigidCLL::AddAtom(unsigned int id,double *p,double r)
00572 {
00573   AddAtom(id,p[0],p[1],p[2],r);
00574 }
00575 
00576 void RigidCLL::EndRigid()
00577 {
00578   /* if we are not defining a rigid, just ignore this call */
00579   if (cr.firstAtom!=MAX_UINT)
00580     {
00581       if (checkInteraction!=NULL)
00582         ERROR("Modifying a closed model. Use the Reset method first.");
00583       
00584       cr.lastAtom=nMobile; /* this is actually the first atom of the next rigid, if any */
00585       rigids.push_back(cr);
00586       cr.firstAtom=cr.lastAtom=MAX_UINT; /* flag to indicate the end of the rigid definition */
00587     }
00588 }
00589 
00590 void RigidCLL::ActivateInteraction(unsigned int r1,unsigned int r2)
00591 {
00592   if (checkInteraction==NULL)
00593     InitInteractions();
00594 
00595   /* rID is the identifier of the last rigid in the system */
00596   if ((r1>rID)||(r2>rID))
00597     ERROR("Rigid cluster identifier out of range in ActivateInteraction");
00598 
00599   if (r1==r2)
00600     ERROR("Can not activate the self-interaction of a rigid group.");
00601 
00602   checkInteraction[r1][r2]=checkInteraction[r2][r1]=true;
00603 }
00604 
00605 void RigidCLL::DeactivateInteraction(unsigned int r1,unsigned int r2)
00606 {
00607   if (checkInteraction==NULL)
00608     InitInteractions();
00609 
00610   if ((r1>rID)||(r2>rID))
00611     ERROR("Rigid cluster identifier out of range in DeactivateInteraction");
00612 
00613   checkInteraction[r1][r2]=checkInteraction[r2][r1]=false;
00614 }
00615 
00616 void RigidCLL::WarmUp(RigidTransform *t)
00617 {
00618   unsigned int i,j;
00619   double minC[3],maxC[3],maxR,range;
00620   vector<AtomInfo>::iterator it;
00621 
00622   if (t==NULL)
00623     ERROR("The Warmup methods need a valid conformation");
00624   
00625   /* if the interactions are not defined, assume all rigids interact between them */
00626   if (checkInteraction==NULL)
00627     InitInteractions();
00628 
00629   /* If we already have a grid, delete it before re-initializing */
00630   DeleteGrid();
00631   
00632   /* Compute the bounding box for all atoms */
00633   minC[0]=minC[1]=minC[2]=INF;
00634   maxC[0]=maxC[1]=maxC[2]=-INF;
00635   maxR=0;
00636 
00637   /* BB for the fixed atoms (for fixed atoms 'op' = 'cp' always) */
00638   for(it=fixedAtoms.begin();it!=fixedAtoms.end();++it)
00639     {
00640       for(j=0;j<3;j++)
00641         {
00642           if (it->cp[j]>maxC[j]) maxC[j]=it->cp[j];
00643           else { if (it->cp[j]<minC[j]) minC[j]=it->cp[j]; }
00644         }
00645 
00646       if (it->r>maxR) maxR=it->r;
00647     }
00648 
00649   /* include the mobile atoms in the BB. Use the current position 'cp'
00650      and not the origina one 'op' which is in local coordinates many times */
00651   for(it=mobileAtoms.begin();it!=mobileAtoms.end();++it)
00652     {
00653       /* update the 'cp' */
00654       it->move(t[it->rID]);
00655       for(j=0;j<3;j++)
00656         {
00657           if (it->cp[j]>maxC[j]) maxC[j]=it->cp[j];
00658           else { if (it->cp[j]<minC[j]) minC[j]=it->cp[j]; }
00659         }
00660       if (it->r>maxR) maxR=it->r;
00661     }
00662 
00663   /* compute the cutoff distance, if not given */
00664   if (cutoff==0)
00665     d=2.0*maxR;
00666   else
00667     d=cutoff;
00668   d2=d*d;
00669 
00670   /* Set up the origin of the grid and its size (in number of cells) 
00671      We define a grid that covers 27 times the bounding box previously
00672      computed (the bounding box is all surrounded by other boxes of
00673      the same size). In this way we hope that the motions of the molecule
00674      would neve scape the grid.
00675    */
00676   for(j=0;j<3;++j)
00677     {
00678       range=maxC[j]-minC[j];
00679       o[j]=minC[j]-(BB_MARGIN)*range;
00680       s[j]=(unsigned int)ceil((1+2*BB_MARGIN)*range/d);
00681     }
00682 
00683   /* Set up the grid */
00684   grid=new CellInfo **[s[0]];
00685   for(i=0;i<s[0];i++)
00686     {
00687       grid[i]=new CellInfo *[s[1]];
00688       for(j=0;j<s[1];j++)
00689         {
00690           grid[i][j]=new CellInfo [s[2]];
00691         }
00692     }
00693   fixedLL=new unsigned int[nFixed];
00694   mobileLL=new unsigned int[nMobile];
00695 
00696   /* Insert the fixed atoms in the grid */
00697   for(i=0;i<nFixed;i++)
00698     InsertFixedInGrid(i);
00699 
00700   /* we just created the grid: there is no mobile atom in it yet. */
00701   lastInGrid=MAX_UINT;
00702 }
00703               
00704 void RigidCLL::Reset()
00705 {
00706   DeleteGrid();
00707   DeleteInteractions();
00708 }
00709 
00710 bool RigidCLL::StericClash(RigidTransform *t)
00711 {
00712   unsigned int i,j;
00713   AtomInfo *a;
00714   bool collision=false;
00715 
00716     
00717   /* We could use the checkInteraction table to more accurately determine wether or not it 
00718      is worth proceed with the interaction detection. Here we use a conservative condition. */
00719   if ((rID>1)||((rID==1)&&(nFixed>0)))
00720     {  
00721       #if (RIGIDCLL_DEBUG)
00722         if (cutoff>0)
00723           ERROR("Using StericClash in a RigidCLL initialized to detect nearby-interactions");
00724       #endif 
00725 
00726       /* ensure we have a grid and that it is in it's iniital state */
00727       if (grid==NULL)
00728         WarmUp(t);
00729       else
00730         ResetQuery();
00731 
00732       /* Proceed with the query */
00733       for(i=0;((!collision)&&(i<rID));i++)
00734         {
00735           for(j=rigids[i].firstAtom;((!collision)&&(j<rigids[i].lastAtom));j++)
00736             {
00737               a=&(mobileAtoms[j]);
00738 
00739               /* Move the atom (we delay the movement as much as possible) */
00740               a->move(t[a->rID]); /* if we used the WarmUp this is redudant but... */
00741 
00742               /* This pre-computes the cell for this atom. This must be done even
00743                  if we skip the query phase (it is used in the insert). */
00744               UpdateCell(a);
00745 
00746               /* If we do not have fixed atoms, we can skip the query phase for 
00747                  the first rigid (the grid is empty!). */
00748               if ((nFixed>0)||(i>0))
00749                 collision=Check27(a);
00750             }
00751 
00752           /* Insert atoms in the grid (there is no need to add last rigid) */
00753           if ((!collision)&&(i<rID-1))
00754             {
00755               for(j=rigids[i].firstAtom;j<rigids[i].lastAtom;j++)
00756                 InsertMobileInGrid(j);   // this assumes UpdateCell already executed
00757             }
00758         }
00759     }
00760   return(collision);
00761 }
00762 
00763 bool RigidCLL::CLLStericClash(RigidTransform *t)
00764 {
00765   unsigned int i;
00766   bool collision=false;
00767 
00768   if ((rID>1)||((rID==1)&&(nFixed>0)))
00769     {
00770       #if (RIGIDCLL_DEBUG)
00771         if (cutoff>0)
00772           ERROR("Using CLLStericClash in a RigidCLL initialized to detect nearby-interactions");
00773       #endif
00774  
00775       /* ensure we have a grid and that it is in it's iniital state */
00776       if (grid==NULL)
00777         WarmUp(t); /* this already moves the atoms */
00778       else
00779         {
00780           ResetQuery();
00781           Move(t);
00782         }
00783 
00784       /* Proceed with the query */
00785 
00786       /* First insert all the mobile atoms in the grid */
00787       for(i=0;i<nMobile;i++)
00788         {
00789           UpdateCell(&(mobileAtoms[i]));
00790           InsertMobileInGrid(i);
00791         }
00792   
00793       /* Now check for collision */
00794       for(i=0;((!collision)&&(i<nMobile));i++)
00795         collision=Check27(&(mobileAtoms[i]));
00796     }
00797 
00798   return(collision);
00799 }
00800 
00801 bool RigidCLL::BruteForceStericClash(RigidTransform *t)
00802 {
00803   unsigned int i,j;
00804   AtomInfo *a1,*a2;
00805   double dx,dy,dz,r;
00806   bool collision=false;
00807 
00808   #if (RIGIDCLL_DEBUG)
00809     if (cutoff>0)
00810       ERROR("Using BruteForceStericClash in a RigidCLL initialized to detect nearby-interactions");
00811   #endif
00812 
00813   if ((rID>1)||((rID==1)&&(nFixed>0)))
00814     {
00815       /* ensure the interaction table is defined */
00816       if (checkInteraction==NULL)
00817         InitInteractions();
00818       
00819       /* Move all atoms */
00820       Move(t);
00821 
00822       for(i=0;((!collision)&&(i<nMobile));i++)
00823         {
00824           a1=&(mobileAtoms[i]);
00825 
00826           if (checkInteraction[a1->rID][0])
00827             {
00828               for(j=0;((!collision)&&(j<nFixed));j++)
00829                 {
00830                   a2=&(fixedAtoms[j]);
00831                      
00832                   MANHATTAN_DISTANCE(dx,dy,dz,a1,a2);
00833                   r=a1->r+a2->r;
00834                 
00835                   collision=(dx*dx+dy*dy+dz*dz<=r*r);
00836                 }
00837             }
00838         
00839           for(j=i+1;((!collision)&&(j<nMobile));j++)
00840             {
00841               a2=&(mobileAtoms[j]);
00842                      
00843               if (checkInteraction[a1->rID][a2->rID])
00844                 {
00845                   MANHATTAN_DISTANCE(dx,dy,dz,a1,a2);
00846                   r=a1->r+a2->r;
00847               
00848                   collision=(dx*dx+dy*dy+dz*dz<=r*r);
00849                 }
00850             }
00851         }
00852     }
00853 
00854   return(collision);
00855 }
00856 
00857 void RigidCLL::Interactions(RigidTransform *t,list<AtomPair> *c)
00858 {
00859   unsigned int i,j,aID,ix,iy,iz;
00860   double dx,dy,dz,d;
00861   AtomInfo *a1,*a2;
00862   RigidInfo *rigid;
00863     
00864   /* We could use the checkInteraction table to more accurately determine wether or not it 
00865      is worth proceed with the interaction detection. Here we use a conservative condition. */
00866   if ((rID>1)||((rID==1)&&(nFixed>0)))
00867     {
00868       #if (RIGIDCLL_DEBUG)
00869         if (cutoff==0)
00870           ERROR("Using Interactions in a RigidCLL initialized to detect steric clashes");
00871       #endif
00872 
00873       /* ensure we have a grid and that it is in it's iniital state */
00874       if (grid==NULL)
00875         WarmUp(t); /* this already moves the atoms */
00876       else
00877         {
00878           ResetQuery();
00879           Move(t);
00880         }
00881 
00882       /* Proceed with the query */
00883       for(i=0;i<rID;i++)
00884         {
00885           rigid=&(rigids[i]);
00886 
00887           for(j=rigid->firstAtom;j<rigid->lastAtom;j++) /* atom in rigid */
00888             {
00889               a1=&(mobileAtoms[j]);
00890 
00891               /* This pre-computes the cell for this atom and must be done even
00892                  if we skip the query phase. */
00893               UpdateCell(a1); 
00894 
00895               /* If we do not have fixed atoms, we can skip the query phase for 
00896                  the first rigid (the grid is empty!) */
00897               if ((nFixed>0)||(i>0))
00898                 {
00899                   /* for neighbours */
00900                   for(ix=a1->c[0]-1;ix<=a1->c[0]+1;ix++)
00901                     {
00902                       for(iy=a1->c[1]-1;iy<=a1->c[1]+1;iy++)
00903                         {              
00904                           for(iz=a1->c[2]-1;iz<=a1->c[2]+1;iz++)
00905                             {
00906                               if (checkInteraction[a1->rID][0])
00907                                 {
00908                                   /* first we check for possible interaction with
00909                                      the fixed atoms in the cell, if any */
00910                                   aID=grid[ix][iy][iz].fixedID;
00911                                   while(aID!=MAX_UINT)
00912                                     {
00913                                       a2=&(fixedAtoms[aID]);
00914 
00915                                       MANHATTAN_DISTANCE(dx,dy,dz,a1,a2);
00916                                       d=dx*dx+dy*dy+dz*dz;
00917                            
00918                                       if (d<=d2)
00919                                         c->push_back(AtomPair(a1,a2,d));
00920 
00921                                       aID=fixedLL[aID];
00922                                     }
00923                                 }
00924 
00925                               /* and now with the mobile atoms, if any */
00926                               aID=grid[ix][iy][iz].mobileID;
00927                               while(aID!=MAX_UINT)
00928                                 {
00929                                   a2=&(mobileAtoms[aID]);
00930                                
00931                                   if (checkInteraction[a1->rID][a2->rID])
00932                                     {
00933                                       MANHATTAN_DISTANCE(dx,dy,dz,a1,a2);
00934                                       d=dx*dx+dy*dy+dz*dz;
00935                                           
00936                                       if (d<=d2)
00937                                         c->push_back(AtomPair(a1,a2,d));
00938                                     }
00939                                   aID=mobileLL[aID];
00940                                 }
00941                             }
00942                         }
00943                     }
00944                 }
00945             }
00946       
00947           /* There is no need to add last rigid group to the grid (would no be used) */
00948           if (i<rID-1) 
00949             {
00950               /* Insert atoms in the grid */
00951               for(j=rigid->firstAtom;j<rigid->lastAtom;j++)
00952                 InsertMobileInGrid(j);
00953             }
00954         }
00955     }
00956 }
00957 
00958 void RigidCLL::CLLInteractions(RigidTransform *t,list<AtomPair> *c)
00959 {
00960   unsigned int i,aID,ix,iy,iz;
00961   double dx,dy,dz,d;
00962   AtomInfo *a1,*a2;
00963 
00964   /* If we have more than one atom -> we have to check for interaction. */
00965   if ((nMobile>1)||((nMobile==1)&&(nFixed>0)))
00966     {
00967       #if (RIGIDCLL_DEBUG)
00968         if (cutoff==0)
00969           ERROR("Using CLLInteractions in a RigidCLL initialized to detect steric clashes");
00970       #endif
00971 
00972       /* ensure we have a grid and that it is in it's iniital state */
00973       if (grid==NULL)
00974         WarmUp(t); /* this already moves the atoms */
00975       else
00976         {
00977           ResetQuery();
00978           Move(t);
00979         }
00980 
00981       /* Insert all atoms in the grid */
00982       for(i=0;i<nMobile;i++)
00983         {
00984           UpdateCell(&(mobileAtoms[i])); 
00985           InsertMobileInGrid(i);
00986         }
00987 
00988       /* Check for all possible interactions */
00989        for(i=0;i<nMobile;i++)
00990          {
00991            a1=&(mobileAtoms[i]);
00992 
00993            /* The loops below are the same as those in MoveAndDetect
00994                with a minor difference (see comments below).
00995                This minor difference avoids re-using the same code 
00996                (as we did in MoveAndCheck)*/
00997            for(ix=a1->c[0]-1;ix<=a1->c[0]+1;ix++)
00998              {
00999                for(iy=a1->c[1]-1;iy<=a1->c[1]+1;iy++)
01000                  {             
01001                    for(iz=a1->c[2]-1;iz<=a1->c[2]+1;iz++)
01002                      {
01003                        /* DIFFERENCE: do not rely on checkInteracion since CLL does not
01004                           have any notion of rigids */
01005                        aID=grid[ix][iy][iz].fixedID;
01006                        while(aID!=MAX_UINT)
01007                          {
01008                            a2=&(fixedAtoms[aID]);
01009                                
01010                            MANHATTAN_DISTANCE(dx,dy,dz,a1,a2);
01011                            d=dx*dx+dy*dy+dz*dz;
01012                                
01013                            if (d<=d2)
01014                              c->push_back(AtomPair(a1,a2,d));
01015 
01016                            aID=fixedLL[aID];
01017                          }
01018 
01019                        /* check interaction with mobile atoms in cell */
01020                        aID=grid[ix][iy][iz].mobileID;
01021                        while(aID!=MAX_UINT)
01022                          {
01023                            a2=&(mobileAtoms[aID]);
01024                                
01025                            if (a1->id<a2->id)  /* DIFFERENCE: Avoid detecting the same interaction twice !! */
01026                              {
01027                                MANHATTAN_DISTANCE(dx,dy,dz,a1,a2);
01028                                d=dx*dx+dy*dy+dz*dz;
01029                                           
01030                                if (d<=d2)
01031                                  c->push_back(AtomPair(a1,a2,d));
01032                              }
01033                            aID=mobileLL[aID];
01034                          }
01035                      }
01036                  }
01037              }
01038          }
01039     }
01040 }
01041 
01042 
01043 void RigidCLL::BruteForceInteractions(RigidTransform *t,list<AtomPair> *c)
01044 {
01045   unsigned int i,j;
01046   AtomInfo *a1,*a2;
01047   double dx,dy,dz,d;
01048   
01049   #if (RIGIDCLL_DEBUG)
01050     if (cutoff==0)
01051       ERROR("Using BruteForceInteractions in a RigidCLL initialized to detect steric clashes");
01052   #endif
01053 
01054   if ((rID>1)||((rID==1)&&(nFixed>0)))
01055     {
01056       /* ensure the interaction table is defined */
01057       if (checkInteraction==NULL)
01058         InitInteractions();
01059 
01060       /* Move the atoms */
01061       Move(t);
01062 
01063       /* perform the detection */
01064       for(i=0;i<nMobile;i++)
01065         {
01066           a1=&(mobileAtoms[i]);
01067 
01068           if (checkInteraction[a1->rID][0])
01069             {
01070               for(j=0;j<nFixed;j++)
01071                 {
01072                   a2=&(fixedAtoms[j]);
01073                      
01074                   MANHATTAN_DISTANCE(dx,dy,dz,a1,a2);
01075                   d=dx*dx+dy*dy+dz*dz;
01076                       
01077                   if (d<=d2)
01078                     c->push_back(AtomPair(a1,a2,d));
01079                 }
01080             }
01081         
01082           for(j=i+1;j<nMobile;j++)
01083             {
01084               a2=&(mobileAtoms[j]);
01085                      
01086               if (checkInteraction[a1->rID][a2->rID])
01087                 {            
01088                   MANHATTAN_DISTANCE(dx,dy,dz,a1,a2);
01089                   d=dx*dx+dy*dy+dz*dz;
01090                       
01091                   if (d<=d2)
01092                     c->push_back(AtomPair(a1,a2,d));
01093                 }
01094             }
01095         }
01096     }
01097 }