/*! \file KDFOF.cxx * \brief This file contains subroutines involving FOF routines \todo must make periodic */ #include namespace NBody { Int_t* KDTree::FOF(Double_t fdist, Int_t &numgroup, Int_t minnum, int order, Int_tree_t *pHead, Int_tree_t *pNext, Int_tree_t *pTail, Int_tree_t *pLen, int ipcheckflag, FOFcheckfunc check, Double_t *params) { Double_t fdist2=fdist*fdist, off[6]; //array containing particles group id Int_t *pGroup=new Int_t[numparts]; //array containing head particle of Group Int_tree_t *pGroupHead=new Int_tree_t[numparts]; //First-in First-out pointer, used to point to the next particle of //interest in the group to be examined. Int_tree_t *Fifo=new Int_tree_t[numparts]; //array used to flag if bucket already searched. short *pBucketFlag=new short[numnodes]; //flags for memory management bool iph,ipt,ipn,ipl; //arrays used in determining group id. //pHead contains the index of the particle at head of the particles group //pTail contains tail of the particles group and Next the next in the list //and pLen is indexed by group and is length of group. //flags to see if mem allocated iph=ipt=ipn=ipl=false; if (pHead==NULL) {pHead=new Int_tree_t[numparts];iph=true;} if (pNext==NULL) {pNext=new Int_tree_t[numparts];ipn=true;} if (pLen==NULL) {pLen=new Int_tree_t[numparts];ipl=true;} if (pTail==NULL) {pTail=new Int_tree_t[numparts];ipt=true;} Int_t iGroup=0,iHead=0,iTail=0,id,iid; Int_t maxlen=0; //initial arrays //initial arrays for (Int_t i=0;iFOFSearchBall(0.0,fdist2,iGroup,numparts,bucket,pGroup,pLen,pHead,pTail,pNext,pBucketFlag, Fifo,iTail,off,iid); else root->FOFSearchBallPeriodic(0.0,fdist2,iGroup,numparts,bucket,pGroup,pLen,pHead,pTail,pNext,pBucketFlag, Fifo,iTail,off,period,iid); } if(pLen[iGroup]0){ if (order) { //generate pList array to store go through particle list and generate linked list Int_t **pList, *pCount; pList=new Int_t*[iGroup+1]; pCount=new Int_t[iGroup+1]; for (Int_t i=1;i<=iGroup;i++) {pList[i]=new Int_t[pLen[i]];pCount[i]=0;} for (Int_t i=0;i0) { pList[gid][pCount[gid]++]=i; } } //now order group indices PriorityQueue *pq=new PriorityQueue(iGroup); for (Int_t i = 1; i <=iGroup; i++) pq->Push(i, pLen[i]); maxlen=pq->TopPriority(); for (Int_t i = 1; i<=iGroup; i++) { Int_t groupid=pq->TopQueue(); pq->Pop(); for (Int_t j=0;jFOFSearchCriterion(0.0,cmp,params,iGroup,numparts,bucket,pGroup,pLen,pHead,pTail,pNext,pBucketFlag, Fifo,iTail,off,iid); else root->FOFSearchCriterionPeriodic(0.0,cmp,params,iGroup,numparts,bucket,pGroup,pLen,pHead,pTail,pNext,pBucketFlag, Fifo,iTail,off,period,iid); } //make sure group big enough if(pLen[iGroup]0){ if (order) { //generate pList array to store go through particle list and generate linked list Int_t **pList, *pCount; pList=new Int_t*[iGroup+1]; pCount=new Int_t[iGroup+1]; for (Int_t i=1;i<=iGroup;i++) {pList[i]=new Int_t[pLen[i]];pCount[i]=0;} for (Int_t i=0;i0) pList[gid][pCount[gid]++]=i; } //now order group indices PriorityQueue *pq=new PriorityQueue(iGroup); for (Int_t i = 1; i <=iGroup; i++) pq->Push(i, pLen[i]); maxlen=pq->TopPriority(); for (Int_t i = 1;i<=iGroup; i++) { Int_t groupid=pq->TopQueue(); pq->Pop(); for (Int_t j=0;jFOFSearchCriterionSetBasisForLinks(0.0,cmp,check,params,iGroup,numparts,bucket,pGroup,pLen,pHead,pTail,pNext,pBucketFlag, Fifo,iTail,off,iid); else root->FOFSearchCriterionSetBasisForLinksPeriodic(0.0,cmp,check,params,iGroup,numparts,bucket,pGroup,pLen,pHead,pTail,pNext,pBucketFlag, Fifo,iTail,off,period,iid); } } //make sure group big enough if(pLen[iGroup]0){ if (order) { //generate pList array to store go through particle list and generate linked list Int_t **pList, *pCount; pList=new Int_t*[iGroup+1]; pCount=new Int_t[iGroup+1]; for (Int_t i=1;i<=iGroup;i++) {pList[i]=new Int_t[pLen[i]];pCount[i]=0;} for (Int_t i=0;i0) pList[gid][pCount[gid]++]=i; } //now order group indices PriorityQueue *pq=new PriorityQueue(iGroup); for (Int_t i = 1; i <=iGroup; i++) pq->Push(i, pLen[i]); maxlen=pq->TopPriority(); for (Int_t i = 1;i<=iGroup; i++) { Int_t groupid=pq->TopQueue(); pq->Pop(); for (Int_t j=0;j0) { Int_t oldGroup=pGroup[iid],oldHead=pGroupHead[oldGroup],oldTail=pTail[oldHead],currentTail=pTail[pGroupHead[iGroup]],ii; //adjust ids ii=oldHead; do { pGroup[bucket[ii].GetID()]=iGroup; pHead[ii]=pGroupHead[iGroup]; } while ((ii=pNext[ii])!=-1); ii=currentTail; do { pTail[ii]=oldTail; } while ((ii=pNext[ii])!=-1); pLen[iGroup]+=pLen[oldGroup]; pLen[oldGroup]=-1;//indicates mergered with another group //now link groups by setting next to current particle and adjust tail and Head pNext[currentTail]=oldHead; pTail[pGroupHead[iGroup]]=oldTail; pHead[oldHead]=pGroupHead[iGroup];//pHead[target]; } //othersise adjust group id and head, tail pointer appropriately else { pGroup[iid]=iGroup; Fifo[iTail++]=nnID[target][j]; pLen[iGroup]++; pNext[pTail[pGroupHead[iGroup]]]=nnID[target][j]; pTail[pGroupHead[iGroup]]=nnID[target][j]; pHead[nnID[target][j]]=pGroupHead[iGroup]; //pNext[pTail[pHead[target]]]=pHead[nnID[target][j]]; //pTail[pHead[target]]=pTail[pHead[nnID[target][j]]]; //pHead[nnID[target][j]]=pHead[target]; if(iTail==numparts)iTail=0; } } } } } //free memory delete[] Fifo; delete[] pHead; delete[] pTail; delete[] pNext; //generate pList array to store go through particle list and generate linked list pList=new Int_t*[iGroup+1]; pCount=new Int_t[iGroup+1]; for (Int_t i=1;i<=iGroup;i++) if (pLen[i]>0) {pList[i]=new Int_t[pLen[i]];pCount[i]=0;} for (Int_t i=0;i0) if(pLen[gid]>0) pList[gid][pCount[gid]++]=i; } //now determine largest group, number of groups that are above minimum number numgroup=iGroup; for (Int_t i=1;i<=numgroup;i++){ if(pLen[i]0) for (Int_t j=0;j0) pq->Push(i, pLen[i]); //printf("Found %d groups. Largest is %d with %d particles.\n",iGroup,1,(Int_t)pq->TopPriority()); for (Int_t i = 1; i<=iGroup; i++) { Int_t groupid=pq->TopQueue(),size=pq->TopPriority();pq->Pop(); for (Int_t j=0;j0) { Int_t oldGroup=pGroup[iid],oldHead=pGroupHead[oldGroup],oldTail=pTail[oldHead],currentTail=pTail[pGroupHead[iGroup]],ii; //adjust ids ii=oldHead; do { pGroup[bucket[ii].GetID()]=iGroup; pHead[ii]=pGroupHead[iGroup]; } while ((ii=pNext[ii])!=-1); ii=currentTail; do { pTail[ii]=oldTail; } while ((ii=pNext[ii])!=-1); pLen[iGroup]+=pLen[oldGroup]; pLen[oldGroup]=-1; //now link groups by setting next to current particle and adjust tail and Head pNext[currentTail]=oldHead; pTail[pGroupHead[iGroup]]=oldTail; pHead[oldHead]=pGroupHead[iGroup]; } //othersise adjust group id and head, tail pointer appropriately else { pGroup[iid]=iGroup; Fifo[iTail++]=nnID[target][j]; pLen[iGroup]++; pNext[pTail[pGroupHead[iGroup]]]=nnID[target][j]; pTail[pGroupHead[iGroup]]=nnID[target][j]; pHead[nnID[target][j]]=pGroupHead[iGroup]; if(iTail==numparts)iTail=0; } } } } } //free memory delete[] Fifo; delete[] pHead; delete[] pTail; delete[] pNext; //generate pList array to store go through particle list and generate linked list pList=new Int_t*[iGroup+1]; pCount=new Int_t[iGroup+1]; for (Int_t i=1;i<=iGroup;i++) if (pLen[i]>0) {pList[i]=new Int_t[pLen[i]];pCount[i]=0;} for (Int_t i=0;i0) if(pLen[gid]>0) pList[gid][pCount[gid]++]=i; } //now determine largest group, number of groups that are above minimum number numgroup=iGroup; for (Int_t i=1;i<=numgroup;i++){ if(pLen[i]0) for (Int_t j=0;j0) pq->Push(i, pLen[i]); //printf("Found %d groups. Largest is %d with %d particles.\n",iGroup,1,(Int_t)pq->TopPriority()); for (Int_t i = 1; i<=iGroup; i++) { Int_t groupid=pq->TopQueue(),size=pq->TopPriority();pq->Pop(); for (Int_t j=0;j=0;i--) if (pGroup[i]==iGroup) {oldtail=i;break;} for (Int_t i=0;iFOFSearchCriterion(0.0,cmp,params,iGroup,numparts,bucket,pGroup,pLen,pHead,pTail,pNext,pBucketFlag, Fifo,iTail,off,iid); } nsize=pLen[iGroup]; delete[] pBucketFlag; return nsize; } }