Пример #1
0
static void insert_level(int levToInsert) {
	int n;
    for (n = 2; n < bddnodesize; n++) {
        int lev, lo, hi, newLev, hash, r, r2, NEXT_r;
        if (LOW(n) == INVALID_BDD) continue;
        lev = LEVEL(n);
        if (lev <= levToInsert || lev == bddvarnum-1) {
            continue;
        }
        lo = LOW(n);
        hi = HIGH(n);
        newLev = lev+1;
        hash = NODEHASH(lev, lo, hi);
        r = HASH(hash);
        r2 = 0;
        while (r != n && r != 0) {
            r2 = r;
            r = NEXT(r);
        }
        NEXT_r = NEXT(r);
        if (r2 == 0) {
            SETHASH(hash, NEXT_r);
        } else {
            SETNEXT(r2, NEXT_r);
        }
        SETLEVEL(n, newLev);
        lo = LOW(n); hi = HIGH(n);
        hash = NODEHASH(newLev, lo, hi);
        r = HASH(hash);
        SETHASH(hash, n);
        SETNEXT(n, r);
    }
}
Пример #2
0
int kdBuildTree(KD kd)
{
	int l,n,i,d,m,j,ct;
	KDN *c;

	n = kd->nActive;
	kd->nLevels = 1;
	l = 1;
	while (n > kd->nBucket) {
		n = n>>1;
		l = l<<1;
		++kd->nLevels;
		}
	kd->nSplit = l;
	kd->nNodes = l<<1;
	kd->kdNodes = (KDN *)malloc(kd->nNodes*sizeof(KDN));
	assert(kd->kdNodes != NULL);
	/*
	 ** Set up ROOT node
	 */
	c = kd->kdNodes;
	c[ROOT].pLower = 0;
	c[ROOT].pUpper = kd->nActive-1;
	c[ROOT].bnd = kd->bnd;
	i = ROOT;
	ct = ROOT;
	SETNEXT(ct);
	while (1) {
		if (i < kd->nSplit) {
			d = 0;
			for (j=1;j<3;++j) {
				if (c[i].bnd.fMax[j]-c[i].bnd.fMin[j] > 
					c[i].bnd.fMax[d]-c[i].bnd.fMin[d]) d = j;
				}
			c[i].iDim = d;
			m = kdMedianJst(kd,d,c[i].pLower,c[i].pUpper);
			c[i].fSplit = kd->p[m].r[d];
			c[LOWER(i)].bnd = c[i].bnd;
			c[LOWER(i)].bnd.fMax[d] = c[i].fSplit;
			c[LOWER(i)].pLower = c[i].pLower;
			c[LOWER(i)].pUpper = m-1;
			c[UPPER(i)].bnd = c[i].bnd;
			c[UPPER(i)].bnd.fMin[d] = c[i].fSplit;
			c[UPPER(i)].pLower = m;
			c[UPPER(i)].pUpper = c[i].pUpper;
			i = LOWER(i);
			}
		else {
			c[i].iDim = -1;
			SETNEXT(i);
			if (i == ct) break;
			}
		}
	kdUpPass(kd,ROOT);
	return(1);
	}
Пример #3
0
/*
 * Requires:
 *   "bp" is the address of block to be added to beginning of free list
 *
 * Effects:
 *    1) Sets pointer for prev free block to be null (since it's at the head of free list)
 *    2) Sets pointer for next free block to be at beginning of free list
 *    3) Sets pointer for prev free block of the old block to be the new block
 *
 *    adds a block to the beginning of the free list
 */
static void 
addToBeginningOfFreeList(void *bp)
{
	SETNEXT(bp) = free_listp; //Sets next ptr to start of free list
	SETPREV(free_listp) = bp; //Sets current's prev to new block
	SETPREV(bp) = NULL; // Sets prev pointer to NULL
}
Пример #4
0
static void dup_level(int levToInsert, int val) {
	int n;
    for (n = 2; n < bddnodesize; n++) {
    	int lev, lo, hi, newLev;
        int n_low, n_high;
        int hash, r, r2, NEXT_r;
        if (LOW(n) == INVALID_BDD) continue;
        lev = LEVEL(n);
        if (lev != levToInsert || lev == bddvarnum-1) {
            continue;
        }
        lo = LOW(n);
        hi = HIGH(n);
        bdd_addref(n);
        n_low = bdd_makenode(levToInsert+1, val<=0 ? lo : 0, val<=0 ? 0 : lo);
        n_high = bdd_makenode(levToInsert+1, val==0 ? hi : 0, val==0 ? 0 : hi);
        bdd_delref(n);
        newLev = lev;
        SETLOW(n, n_low);
        SETHIGH(n, n_high);
        hash = NODEHASH(lev, lo, hi);
        r = HASH(hash);
        r2 = 0;
        while (r != n && r != 0) {
            r2 = r;
            r = NEXT(r);
        }
        NEXT_r = NEXT(r);
        if (r2 == 0) {
            SETHASH(hash, NEXT_r);
        } else {
            SETNEXT(r2, NEXT_r);
        }
        SETLEVEL(n, newLev);
        lo = LOW(n); hi = HIGH(n);
        hash = NODEHASH(newLev, lo, hi);
        r = HASH(hash);
        SETHASH(hash, n);
        SETNEXT(n, r);
    }
}
Пример #5
0
int smBallGather(SMX smx,float fBall2,float *ri)
{
	KDN *c;
	PARTICLE *p;
	int pj,nCnt,cp,nSplit;
	float dx,dy,dz,x,y,z,lx,ly,lz,sx,sy,sz,fDist2;

	c = smx->kd->kdNodes;
	p = smx->kd->p;
	nSplit = smx->kd->nSplit;
	lx = smx->fPeriod[0];
	ly = smx->fPeriod[1];
	lz = smx->fPeriod[2];
	x = ri[0];
	y = ri[1];
	z = ri[2];
	nCnt = 0;
	cp = ROOT;
	while (1) {
		INTERSECT(c,cp,fBall2,lx,ly,lz,x,y,z,sx,sy,sz);
		/*
		 ** We have an intersection to test.
		 */
		if (cp < nSplit) {
			cp = LOWER(cp);
			continue;
			}
		else {
			for (pj=c[cp].pLower;pj<=c[cp].pUpper;++pj) {
				dx = sx - p[pj].r[0];
				dy = sy - p[pj].r[1];
				dz = sz - p[pj].r[2];
				fDist2 = dx*dx + dy*dy + dz*dz;
				if (fDist2 < fBall2) {
					smx->fList[nCnt] = fDist2;
					smx->pList[nCnt++] = pj;
					}
				}
			}
	GetNextCell:
		SETNEXT(cp);
		if (cp == ROOT) break;
		}
	assert(nCnt <= smx->nListSize);
	return(nCnt);
	}
Пример #6
0
/* Requires:
 * "bp" is the address of block to be removed from free list
 * has_prev, 0 for no prev block, 1 for has prev block
 *
 * Effects:
 *    Removes block from free list by resetting pointers and unallocating block
 */
static void 
removeBlockFromList(void *bp)
{
	int has_prev;

	if (GET(GETPREV(bp))) {
		has_prev = 1;
	}
	else {
		has_prev = 0;
	}
	
	if (has_prev)
		SETNEXT(*GETPREV(bp)) = *GETNEXT(bp);
	else
		free_listp = *GETNEXT(bp); 
	
	SETPREV(*GETNEXT(bp)) = *GETPREV(bp);
}
Пример #7
0
static int bdd_noderesize2(int doRehash, int oldsize, int newsize)
{
   int n;
   newsize = bdd_prime_lte(newsize);
   
   if (oldsize > newsize) {
     return 0;
   }
   bddnodesize = newsize;
   
   if (resize_handler != NULL)
      resize_handler(oldsize, bddnodesize);

   if (bddnodesize > MAX_ALLOC_NODES) {
     alloced = (BddNode*)realloc(alloced, sizeof(BddNode)*bddnodesize);
     if (alloced == NULL)
       return bdd_error(BDD_MEMORY);
     bddnodes = alloced;
     MAX_ALLOC_NODES = bddnodesize;
   } else {
     bddnodes = alloced;
   }

   if (doRehash)
      for (n=0 ; n<oldsize ; n++)
	 SETHASH(n, 0);
   
   for (n=oldsize ; n<bddnodesize ; n++)
   {
      INIT_NODE(n);
   }
   SETNEXT(bddnodesize-1, bddfreepos);
   bddfreepos = oldsize;
   bddfreenum += bddnodesize - oldsize;

   if (doRehash)
      bdd_gbc_rehash();

   bddresized = 1;
   
   return 0;
}
Пример #8
0
void kdBuildTree(KD kd)
{
	int l,n,i,d,m,j,diff;
	KDN *c;
	BND bnd;

	n = kd->nActive;
	kd->nLevels = 1;
	l = 1;
	while (n > kd->nBucket) {
		n = n>>1;
		l = l<<1;
		++kd->nLevels;
		}
	kd->nSplit = l;
	kd->nNodes = l<<1;
	if (kd->kdNodes != NULL) free(kd->kdNodes);
	kd->kdNodes = (KDN *)malloc(kd->nNodes*sizeof(KDN));
	assert(kd->kdNodes != NULL);
	/*
	 ** Calculate Bounds.
	 */
	for (j=0;j<3;++j) {
		bnd.fMin[j] = kd->p[0].r[j];
		bnd.fMax[j] = kd->p[0].r[j];
		}
	for (i=1;i<kd->nActive;++i) {
		for (j=0;j<3;++j) {
			if (bnd.fMin[j] > kd->p[i].r[j]) 
				bnd.fMin[j] = kd->p[i].r[j];
			else if (bnd.fMax[j] < kd->p[i].r[j])
				bnd.fMax[j] = kd->p[i].r[j];
			}
		}
	/*
	 ** Set up ROOT node
	 */
	c = kd->kdNodes;
	c[ROOT].pLower = 0;
	c[ROOT].pUpper = kd->nActive-1;
	c[ROOT].bnd = bnd;
	i = ROOT;
	while (1) {
		assert(c[i].pUpper - c[i].pLower + 1 > 0);
		if (i < kd->nSplit && (c[i].pUpper - c[i].pLower) > 0) {
			d = 0;
			for (j=1;j<3;++j) {
				if (c[i].bnd.fMax[j]-c[i].bnd.fMin[j] > 
					c[i].bnd.fMax[d]-c[i].bnd.fMin[d]) d = j;
				}
			c[i].iDim = d;

			m = (c[i].pLower + c[i].pUpper)/2;
			kdSelect(kd,d,m,c[i].pLower,c[i].pUpper);

			c[i].fSplit = kd->p[m].r[d];
			c[LOWER(i)].bnd = c[i].bnd;
			c[LOWER(i)].bnd.fMax[d] = c[i].fSplit;
			c[LOWER(i)].pLower = c[i].pLower;
			c[LOWER(i)].pUpper = m;
			c[UPPER(i)].bnd = c[i].bnd;
			c[UPPER(i)].bnd.fMin[d] = c[i].fSplit;
			c[UPPER(i)].pLower = m+1;
			c[UPPER(i)].pUpper = c[i].pUpper;
			diff = (m-c[i].pLower+1)-(c[i].pUpper-m);
			assert(diff == 0 || diff == 1);
			i = LOWER(i);
			}
		else {
			c[i].iDim = -1;
			SETNEXT(i);
			if (i == ROOT) break;
			}
		}
	kdUpPass(kd,ROOT);
	}
Пример #9
0
int kdFoF(KD kd,float fEps)
{
	PARTICLE *p;
	KDN *c;
	int pi,pj,pn,cp;

	int iGroup;

	int *Fifo,iHead,iTail,nFifo;
	float fEps2;
	float dx,dy,dz,x,y,z,lx,ly,lz,sx,sy,sz,fDist2;
#ifdef _OPENMP
    int idSelf;
    omp_lock_t *locks;

	for (pn=0;pn<kd->nActive;++pn) kd->p[pn].iTouched = -1;
    /* We really want to make an independent lock for each particle.  However, each lock
     * seems to use a buttload of memory (something like 312 bytes per lock).  Therefore,
     * to ensure that we don't use too much memory, only use 1 lock per 100 particles.
     * This should still provide very low lock contention while not using oodles of 
     * memory at the same time, since it is extremely rare that two threads will be looking
     * two particles that map to the same lock at the same time.*/
    kd->nHash = (int)(kd->nActive/100);
    locks = (omp_lock_t *)malloc(kd->nHash*sizeof(omp_lock_t));
    assert(locks != NULL);
    for (pn=0;pn<kd->nHash;++pn) omp_init_lock(&locks[pn]);
#endif

	p = kd->p;
	c = kd->kdNodes;
	lx = kd->fPeriod[0];
	ly = kd->fPeriod[1];
	lz = kd->fPeriod[2];
	fEps2 = fEps*fEps;
	for (pn=0;pn<kd->nActive;++pn) p[pn].iGroup = 0;
#pragma omp parallel default(none) shared(kd,locks,p,c,lx,ly,lz,fEps2) \
    private(pi,pj,pn,cp,iGroup,Fifo,iHead,iTail,dx,dy,dz,x,y,z,sx,sy,sz,fDist2,idSelf,nFifo)
  {
#ifdef _OPENMP
    nFifo = kd->nActive/omp_get_num_threads();
    idSelf = omp_get_thread_num();
#else
    nFifo = kd->nActive;
#endif
	Fifo = (int *)malloc(nFifo*sizeof(int));
	assert(Fifo != NULL);
	iHead = 0;
	iTail = 0;
	iGroup = 0;
#pragma omp for schedule(runtime)
	for (pn=0;pn<kd->nActive;++pn) {
		if (p[pn].iGroup) continue;
		/*
		 ** Mark it and add to the do-fifo.
		 */
#ifdef _OPENMP
        omp_set_lock(&locks[_hashLock(kd,pn)]);
        if (p[pn].iTouched >= 0 && p[pn].iTouched < idSelf ) {
            assert(p[pn].iGroup > 0);
            omp_unset_lock(&locks[_hashLock(kd,pn)]);
            continue;
        }
        p[pn].iTouched = idSelf;
        iGroup = pn+1;
		p[pn].iGroup = iGroup;
        omp_unset_lock(&locks[_hashLock(kd,pn)]);
#else
		++iGroup;
		p[pn].iGroup = iGroup;
#endif
		Fifo[iTail++] = pn;
		if (iTail == nFifo) iTail = 0;
		while (iHead != iTail) {
			pi = Fifo[iHead++];
			if (iHead == nFifo) iHead = 0;
			/*
			 ** Now do an fEps-Ball Gather!
			 */
			x = p[pi].r[0];
			y = p[pi].r[1];
			z = p[pi].r[2];
			cp = ROOT;
			while (1) {
				INTERSECT(c,cp,fEps2,lx,ly,lz,x,y,z,sx,sy,sz);
				/*
				 ** We have an intersection to test.
				 */
				if (c[cp].iDim >= 0) {
					cp = LOWER(cp);
					continue;
					}
				else {
					for (pj=c[cp].pLower;pj<=c[cp].pUpper;++pj) {
#ifdef _OPENMP
                        if (p[pj].iGroup == iGroup) {
                            /* We have already looked at this particle */
                            //assert(p[pj].iTouched == idSelf);  particle is not locked.
                            continue;
                        }
                        if (p[pj].iTouched >= 0 && p[pj].iTouched < idSelf) {
                            /* Somebody more important than us is already looking at this
                             * particle.  However, we do not yet know if this particle belongs
                             * in our group, so just skip it to save time but don't restart the
                             * entire group. */
                            // assert(p[pj].iGroup > 0); particle is not locked
                            continue;
                        }
#else
						if (p[pj].iGroup) continue;
#endif
						dx = sx - p[pj].r[0];
						dy = sy - p[pj].r[1];
						dz = sz - p[pj].r[2];
						fDist2 = dx*dx + dy*dy + dz*dz;
						if (fDist2 < fEps2) {
							/*
							 ** Mark it and add to the do-fifo.
							 */
#ifdef _OPENMP
                            omp_set_lock(&locks[_hashLock(kd,pj)]);
                            if (p[pj].iTouched >= 0 && p[pj].iTouched < idSelf) {
                                /* Now we know this particle should be in our group.  If somebody more
                                 * important than us touched it, about the entire group. */
                                assert(p[pj].iGroup > 0);
                                omp_unset_lock(&locks[_hashLock(kd,pj)]);
                                iHead = iTail;
                                /*printf("Thread %d: Aborting group %d. p[%d].iOrder  p.iGroup=%d  p.iTouched=%d (Per-Particle2)\n",
                                  idSelf, iGroup, pj, p[pj].iOrder, p[pj].iGroup, p[pj].iTouched);*/
                                goto RestartSnake;
                            }
                            p[pj].iTouched = idSelf;
							p[pj].iGroup = iGroup;
                            omp_unset_lock(&locks[_hashLock(kd,pj)]);
#else
							p[pj].iGroup = iGroup;
#endif
							Fifo[iTail++] = pj;
							if (iTail == nFifo) iTail = 0;
							}
						}
					SETNEXT(cp);
					if (cp == ROOT) break;
					continue;
					}
			ContainedCell:
				for (pj=c[cp].pLower;pj<=c[cp].pUpper;++pj) {
#ifdef _OPENMP
                    if (p[pj].iGroup == iGroup) continue;
                    if (p[pj].iTouched >= 0 && p[pj].iTouched < idSelf) {
                        /* Somebody more important that us is already looking at this
                         * group.  Abort this entire group! */
                        //assert(p[pj].iGroup > 0); particle is not locked
                        iHead = iTail;
                        /*printf("Thread %d: Aborting group %d. p[%d].iOrder=%d  p.iGroup=%d  p.iTouched=%d (Per-Cell1)\n",
                          idSelf, iGroup, pj, p[pj].iOrder, p[pj].iGroup, p[pj].iTouched);*/
                        goto RestartSnake;
                    }
#else
					if (p[pj].iGroup) continue;
#endif                    
					/*
					 ** Mark it and add to the do-fifo.
					 */
#ifdef _OPENMP
                    omp_set_lock(&locks[_hashLock(kd,pj)]);
                    if (p[pj].iTouched >= 0 && p[pj].iTouched < idSelf) {
                        /* Check again in case somebody touched it before the lock. */
                        assert(p[pj].iGroup > 0);
                        omp_unset_lock(&locks[_hashLock(kd,pj)]);
                        iHead = iTail;
                        /*printf("Thread %d: Aborting group %d.  p[%d].iGroup=%d  p[%d].iTouched=%d (Per-Cell2)\n",
                          idSelf, iGroup, pj, p[pj].iGroup, pj, p[pj].iTouched);*/
                        goto RestartSnake;
                    }
                    p[pj].iTouched = idSelf;
                    p[pj].iGroup = iGroup;
                    omp_unset_lock(&locks[_hashLock(kd,pj)]);
#else
					p[pj].iGroup = iGroup;
#endif
					Fifo[iTail++] = pj;
					if (iTail == nFifo) iTail = 0;
					}
			GetNextCell:
				SETNEXT(cp);
				if (cp == ROOT) break;
            }
        } /* End while(iHead != iTail) */
#ifdef _OPENMP
    RestartSnake:
#endif
        assert(iHead == iTail);
    }
	free(Fifo);
  }  /* End of the OpenMP PARALLEL section */

#ifdef _OPENMP
    /* Now we have count how many groups there are.  This is straightforward,
     * since the number of groups is the number of particles whose groupID equals
     * their particleID+1. */
    pj = 0;
	for (pn=0;pn<kd->nActive;++pn)
        if (p[pn].iGroup == pn+1) ++pj;
    kd->nGroup = (kd->nActive)+1;
    free(locks);
#else
	kd->nGroup = iGroup+1;
#endif
	return(kd->nGroup-1);
	}
Пример #10
0
void smBallSearch(SMX smx,float fBall2,float *ri)
{
	KDN *c;
	PARTICLE *p;
	int cell,cp,ct,pj;
	float fDist2,dx,dy,dz,lx,ly,lz,sx,sy,sz,x,y,z;
	PQ *pq;

	c = smx->kd->kdNodes;
	p = smx->kd->p;
	pq = smx->pqHead;
	x = ri[0];
	y = ri[1];
	z = ri[2];
	lx = smx->fPeriod[0];
	ly = smx->fPeriod[1];
	lz = smx->fPeriod[2];
	cell = ROOT;
	/*
	 ** First find the "local" Bucket.
	 ** This could mearly be the closest bucket to ri[3].
	 */
	while (cell < smx->kd->nSplit) {
		if (ri[c[cell].iDim] < c[cell].fSplit) cell = LOWER(cell);
		else cell = UPPER(cell);
		}
	/*
	 ** Now start the search from the bucket given by cell!
	 */
	for (pj=c[cell].pLower;pj<=c[cell].pUpper;++pj) {
		dx = x - p[pj].r[0];
		dy = y - p[pj].r[1];
		dz = z - p[pj].r[2];
		fDist2 = dx*dx + dy*dy + dz*dz;
		if (fDist2 < fBall2) {
			if (smx->iMark[pj]) continue;
			smx->iMark[pq->p] = 0;
			smx->iMark[pj] = 1;
			pq->fKey = fDist2;
			pq->p = pj;
			pq->ax = 0.0;
			pq->ay = 0.0;
			pq->az = 0.0;
			PQ_REPLACE(pq);
			fBall2 = pq->fKey;
			}
		}
	while (cell != ROOT) {
		cp = SIBLING(cell);
		ct = cp;
		SETNEXT(ct);
		while (1) {
			INTERSECT(c,cp,fBall2,lx,ly,lz,x,y,z,sx,sy,sz);
			/*
			 ** We have an intersection to test.
			 */
			if (cp < smx->kd->nSplit) {
				cp = LOWER(cp);
				continue;
				}
			else {
				for (pj=c[cp].pLower;pj<=c[cp].pUpper;++pj) {
					dx = sx - p[pj].r[0];
					dy = sy - p[pj].r[1];
					dz = sz - p[pj].r[2];
					fDist2 = dx*dx + dy*dy + dz*dz;
					if (fDist2 < fBall2) {
						if (smx->iMark[pj]) continue;
						smx->iMark[pq->p] = 0;
						smx->iMark[pj] = 1;
						pq->fKey = fDist2;
						pq->p = pj;
						pq->ax = sx - x;
						pq->ay = sy - y;
						pq->az = sz - z;
						PQ_REPLACE(pq);
						fBall2 = pq->fKey;
						}
					}
				}
		GetNextCell:
			SETNEXT(cp);
			if (cp == ct) break;
			}
		cell = PARENT(cell);
		}
	smx->pqHead = pq;
	}
Пример #11
0
/*
NAME   {* bdd\_init *}
SECTION {* kernel *}
SHORT  {* initializes the BDD package *}
PROTO  {* int bdd_init(int nodesize, int cachesize) *}
DESCR  {* This function initiates the bdd package and {\em must} be called
          before any bdd operations are done. The argument {\tt nodesize}
	  is the initial number of nodes in the nodetable and {\tt cachesize}
	  is the fixed size of the internal caches. Typical values for
	  {\tt nodesize} are 10000 nodes for small test examples and up to
	  1000000 nodes for large examples. A cache size of 10000 seems to
	  work good even for large examples, but lesser values should do it
	  for smaller examples.

	  The number of cache entries can also be set to depend on the size
	  of the nodetable using a call to {\tt bdd\_setcacheratio}.
	  
	  The initial number of nodes is not critical for any bdd operation
	  as the table will be resized whenever there are to few nodes left
	  after a garbage collection. But it does have some impact on the
	  efficency of the operations. *}
RETURN {* If no errors occur then 0 is returned, otherwise
          a negative error code. *}
ALSO   {* bdd\_done, bdd\_resize\_hook *}
*/
int bdd_init(int initnodesize, int cs)
{
   /* Check to see if tracing is enabled */
   char * str;
   if( (str = getenv("BUDDY_TRACE_FILE")) != NULL) {
     trace_enable = 1;
     trace_init(str);
   }

   {
     int n, err;
     BUDDY_PROLOGUE;
     ADD_ARG1(T_INT,initnodesize);
     ADD_ARG1(T_INT,cs);
     
     srand48( SRAND48SEED ) ;
     
     if (bddrunning)
       RETURN(bdd_error(BDD_RUNNING));
     
     bddnodesize = bdd_prime_gte(initnodesize);
     
     if ((MAX_ALLOC_NODES == 0) ||
	 (alloced=(BddNode*)malloc(sizeof(BddNode)*MAX_ALLOC_NODES)) == NULL) {
       if ((alloced=(BddNode*)malloc(sizeof(BddNode)*bddnodesize)) == NULL) {
	 RETURN(bdd_error(BDD_MEMORY));
       }
       MAX_ALLOC_NODES = bddnodesize;
     }
     bddnodes = alloced;
     
     bddresized = 0;
     
     for (n=0 ; n<bddnodesize ; n++) {
       INIT_NODE(n);
     }
     SETNEXT(bddnodesize-1, 0);
     
     SETMAXREF(0);
     SETMAXREF(1);
     SETLOW(0,0); SETHIGH(0,0);
     SETLOW(1,1); SETHIGH(1,1);
     
     if ((err=bdd_operator_init(cs)) < 0) {
       bdd_done();
       RETURN(err);
     }
     
     bddfreepos = 2;
     bddfreenum = bddnodesize-2;
     bddrunning = 1;
     bddvarnum = 0;
     gbcollectnum = 0;
     gbcclock = 0;
     cachesize = cs;
     usednodes_nextreorder = bddnodesize;
     bddmaxnodeincrease = DEFAULTMAXNODEINC;
     bddincreasefactor = 2;
     
     bdderrorcond = 0;
     
     bddcachestats.uniqueAccess = 0;
     bddcachestats.uniqueChain = 0;
     bddcachestats.uniqueHit = 0;
     bddcachestats.uniqueMiss = 0;
     bddcachestats.opHit = 0;
     bddcachestats.opMiss = 0;
     bddcachestats.swapCount = 0;
     
     bdd_gbc_hook(bdd_default_gbchandler);
     bdd_error_hook(bdd_default_errhandler);
     bdd_resize_hook(NULL);
     bdd_pairs_init();
     bdd_reorder_init();
     bdd_fdd_init();
     
     if (setjmp(bddexception) != 0)
       assert(0);
     
     RETURN(0);
   }
}
Пример #12
0
void pkdBucketWalk(PKD pkd,int iBucket,int nReps,int iOrder)
{
    KDN *pbuc,*pkdn;
    int iCell,id,ix,iy,iz,bRep,bIntersect,pj;
    FLOAT x,y,z,rOffset[3],fSoftMax,twoh2;

    pkd->nPart = 0;
    pkd->nCellSoft = 0;
    pkd->nCellNewt = 0;
    pbuc = &pkd->kdNodes[iBucket];
    /*
     ** Find the maximum softening for particles in the bucket.
     */
    fSoftMax = 0.0;
    for (pj=pbuc->pLower; pj<=pbuc->pUpper; ++pj) {
        if (pkd->pStore[pj].fSoft > fSoftMax) {
            fSoftMax = pkd->pStore[pj].fSoft;
        }
    }
    for (ix=-nReps; ix<=nReps; ++ix) {
        if (ix && pkd->fPeriod[0] == FLOAT_MAXVAL) continue;
        rOffset[0] = (ix == 0 ? 0.0 : ix*pkd->fPeriod[0]); /* to avoid multiplying machine infinity by zero */
        for (iy=-nReps; iy<=nReps; ++iy) {
            if (iy && pkd->fPeriod[1] == FLOAT_MAXVAL) continue;
            rOffset[1] = (iy == 0 ? 0.0 : iy*pkd->fPeriod[1]);
#ifdef SLIDING_PATCH
            if (pkd->PP->bPatch)
                rOffset[1] += SHEAR(ix,pkd->dTime,pkd->PP);
#endif
            for (iz=-nReps; iz<=nReps; ++iz) {
                if (iz && pkd->fPeriod[2] == FLOAT_MAXVAL) continue;
                rOffset[2] = (iz == 0 ? 0.0 : iz*pkd->fPeriod[2]);
                bRep = ix || iy || iz;
                /*
                 ** Walk the top tree first, finding local trees to
                 ** continue walking.
                 */
                iCell = ROOT;
                while (1) {
                    id = pkd->kdTop[iCell].pLower;
                    if (id == pkd->idSelf) {
                        pkdLocalWalk(pkd,iBucket,fSoftMax,bRep,rOffset,iOrder);
                        SETNEXT(iCell);
                        if (iCell == ROOT) break;
                    }
                    else if (id >= 0) {
                        pkdRemoteWalk(pkd,iBucket,fSoftMax,id,rOffset,iOrder);
                        SETNEXT(iCell);
                        if (iCell == ROOT) break;
                    }
                    else {
                        pkdn = &pkd->kdTop[iCell];
                        x = pkdn->r[0] + rOffset[0];
                        y = pkdn->r[1] + rOffset[1];
                        z = pkdn->r[2] + rOffset[2];
                        INTERSECTNP(pbuc,pkdn->fOpen2,x,y,z,bIntersect);
                        if (bIntersect) {
                            /*
                             ** Open top cell.
                             */
                            iCell = LOWER(iCell);
                        }
                        else {
                            /*
                             ** Cell-Bucket interaction accepted.
                             ** Decide whether it is safe to use
                             ** Newtonian form.
                             */
                            twoh2 = pkdn->fSoft + fSoftMax;
                            twoh2 *= twoh2;
                            if (twoh2 < pkdn->fOpen2) bIntersect = 0;
                            else {
                                INTERSECTNP(pbuc,twoh2,x,y,z,bIntersect);
                            }
                            if (bIntersect) {
                                /*
                                 ** May need to use softened Cell!
                                 */
                                if (pkd->nCellSoft == pkd->nMaxCellSoft) {
                                    pkd->nMaxCellSoft *= 2;
                                    pkd->ilcs = realloc(pkd->ilcs,
                                                        pkd->nMaxCellSoft*
                                                        sizeof(ILCS));
                                    assert(pkd->ilcs != NULL);
                                    if (pkd->nMaxCellSoft > pkd->nSqrtTmp) {
                                        pkd->nSqrtTmp = pkd->nMaxCellSoft;
                                        pkd->sqrttmp = realloc(pkd->sqrttmp,pkd->nSqrtTmp*sizeof(double));
                                        assert(pkd->sqrttmp != NULL);
                                        pkd->d2a = realloc(pkd->d2a,pkd->nSqrtTmp*sizeof(double));
                                        assert(pkd->d2a != NULL);
                                    }
                                }
                                pkd->ilcs[pkd->nCellSoft].m = pkdn->fMass;
                                pkd->ilcs[pkd->nCellSoft].h = pkdn->fSoft;
                                pkd->ilcs[pkd->nCellSoft].x = x;
                                pkd->ilcs[pkd->nCellSoft].y = y;
                                pkd->ilcs[pkd->nCellSoft].z = z;
                                pkd->ilcs[pkd->nCellSoft].xx = pkdn->mom.Qxx;
                                pkd->ilcs[pkd->nCellSoft].yy = pkdn->mom.Qyy;
                                pkd->ilcs[pkd->nCellSoft].zz = pkdn->mom.Qzz;
                                pkd->ilcs[pkd->nCellSoft].xy = pkdn->mom.Qxy;
                                pkd->ilcs[pkd->nCellSoft].xz = pkdn->mom.Qxz;
                                pkd->ilcs[pkd->nCellSoft].yz = pkdn->mom.Qyz;
                                ++pkd->nCellSoft;
                            }
                            else {
                                /*
                                 ** Can use Newtonian Cell interaction.
                                 */
                                if (pkd->nCellNewt == pkd->nMaxCellNewt) {
                                    pkd->nMaxCellNewt *= 2;
                                    pkd->ilcn = realloc(pkd->ilcn,
                                                        pkd->nMaxCellNewt*
                                                        sizeof(ILCN));
                                    assert(pkd->ilcn != NULL);
                                    if (pkd->nMaxCellNewt > pkd->nSqrtTmp) {
                                        pkd->nSqrtTmp = pkd->nMaxCellNewt;
                                        pkd->sqrttmp = realloc(pkd->sqrttmp,pkd->nSqrtTmp*sizeof(double));
                                        assert(pkd->sqrttmp != NULL);
                                        pkd->d2a = realloc(pkd->d2a,pkd->nSqrtTmp*sizeof(double));
                                        assert(pkd->d2a != NULL);
                                    }
                                }
                                SETILIST(iOrder,pkd->ilcn[pkd->nCellNewt],pkdn,x,y,z);
                                ++pkd->nCellNewt;
                            }
                            SETNEXT(iCell);
                            if (iCell == ROOT) break;
                        }
                    }
                } /* of Top tree walk */
            } /* of iz */
        } /* of iy */
    } /* of ix */
}