예제 #1
0
double OctTree_t::EvaluatePotential(const HBTReal targetPos[3], const HBTReal targetMass)
/*return specific physical potential, GM/Rphysical. 
 * targetPos[] is comoving.
 * if targetMass!=0, then the self-potential from targetMass is excluded. 
 * do not set targetMass (i.e., keep to 0.) if target is outside the particlelist of tree*/
{
  OctTreeCell_t *nop = 0;
  HBTInt no;
  double r2, dx, dy, dz, mass, r, u, h, h_inv, wp;
  double pot, pos_x, pos_y, pos_z;

  pos_x = targetPos[0];
  pos_y = targetPos[1];
  pos_z = targetPos[2];

  h = 2.8 * HBTConfig.SofteningHalo;
  h_inv = 1.0 / h;

  pot=targetMass/HBTConfig.SofteningHalo; //to cancle out the self-potential added during tree walk.

  no = NumberOfParticles;//start from root node

  while(no >= 0)
    {
      if(no < NumberOfParticles)		/* single particle */
	{
	  dx = Snapshot->GetComovingPosition(no)[0] - pos_x;
	  dy = Snapshot->GetComovingPosition(no)[1] - pos_y;
	  dz = Snapshot->GetComovingPosition(no)[2] - pos_z;
	  if(HBTConfig.PeriodicBoundaryOn)
	  {
	  dx=NEAREST(dx);
	  dy=NEAREST(dy);
	  dz=NEAREST(dz);
	  }
	  mass = Snapshot->GetMass(no);
	  no = NextnodeFromParticle[no];
	      r2 = dx * dx + dy * dy + dz * dz;	
	}
      else
	{
	  nop = &Nodes[no];
	  dx = nop->way.s[0] - pos_x;
	  dy = nop->way.s[1] - pos_y;
	  dz = nop->way.s[2] - pos_z;
	  if(HBTConfig.PeriodicBoundaryOn)
	  {
	  dx=NEAREST(dx);
	  dy=NEAREST(dy);
	  dz=NEAREST(dz);
	  }
	  mass = nop->way.mass;
	  r2 = dx * dx + dy * dy + dz * dz;
		/* we have an internal node. Need to check opening criterion */
	  if((nop->way.len * nop->way.len )>( r2 * HBTConfig.TreeNodeOpenAngleSquare))
	    {
	      /* open cell */
	      no = nop->way.nextnode;
	      continue;
	    }
	  no = nop->way.sibling;	/* node can be used */
	}
 
      r = sqrt(r2);

      if(r >= h)
	pot -= mass / r;
      else
	{
	  u = r * h_inv;

	  if(u < 0.5)
	    wp = -2.8 + u * u * (5.333333333333 + u * u * (6.4 * u - 9.6));
	  else
	    wp =
	      -3.2 + 0.066666666667 / u + u * u * (10.666666666667 +
						   u * (-16.0 + u * (9.6 - 2.133333333333 * u)));

	  pot += mass * h_inv * wp;
	}
    }
    
  return pot*PhysicalConst::G/Snapshot->ScaleFactor;
}
예제 #2
0
파일: treesearch.c 프로젝트: Kambrian/HBT
HBTInt treesearch_infect_particles(HBTInt seed, HBTInt grpid,
		struct ParticleGroup *GrpTags, HBTReal PPos[][3])
{
/*tag all the particles that are linked to seed with grpid
 * Note if system stack size is too small, this recursive routine may crash
 * in that case you should set:  ulimit -s unlimited  (bash) before running.
**/
 HBTInt numngb, totnumngb, no, p;
  double dx, dy, dz, r2, h2;
  union NODE *this;
  HBTReal *searchcenter;

  searchcenter=PPos[GrpTags[seed].PIndex];
  //~ h2 = radius * radius;

  numngb = 0; 
  no = NumPart;

  while(no >= 0)//infect neighbours
    {
		
      if(no < NumPart)		/* single particle */
	  {
		  *pInfected = no;
		  no = Nextnode[*pInfected];
		  if(GrpTags[*pInfected].GrpID>=0) //already tagged
			continue;  
		  
		  p = GrpTags[*pInfected].PIndex;

		  dx = PPos[p][0] - searchcenter[0];
		  #ifdef PERIODIC_BDR
		  dx=NEAREST(dx);
		  #endif
		  if(dx < -LinkLength)
			continue;
		  if(dx > LinkLength)
			continue;

		  dy =PPos[p][1] - searchcenter[1];
		  #ifdef PERIODIC_BDR
		  dy=NEAREST(dy);
		  #endif
		  if(dy < -LinkLength)
			continue;
		  if(dy > LinkLength)
			continue;

		  dz = PPos[p][2] - searchcenter[2];
		  #ifdef PERIODIC_BDR
		  dz=NEAREST(dz);
		  #endif
		  if(dz < -LinkLength)
			continue;
		  if(dz > LinkLength)
			continue;

		  r2 = dx * dx + dy * dy + dz * dz;

		  if(r2 < LinkLength2) //confirm the infection (fill the stack)
			{
			  GrpTags[*pInfected].GrpID=grpid;
			  numngb++;
			  pInfected++;
			}
	  }
      else
	  {
	  this = &Nodes[no];

	  no = Nodes[no].way.sibling;	/* in case the node can be discarded */
	//since way.s[3] is CoM rather than center of cube,compare with Len rather than Lenhalf to allow for misaligned CoM
	  if((NEAREST(this->way.s[0] - searchcenter[0]) + this->way.len) < -LinkLength)
	    continue;
	  if((NEAREST(this->way.s[0] - searchcenter[0]) - this->way.len) > LinkLength)
	    continue;
	  if((NEAREST(this->way.s[1] - searchcenter[1]) + this->way.len) < -LinkLength)
	    continue;
	  if((NEAREST(this->way.s[1] - searchcenter[1]) - this->way.len) > LinkLength)
	    continue;
	  if((NEAREST(this->way.s[2] - searchcenter[2]) + this->way.len) < -LinkLength)
	    continue;
	  if((NEAREST(this->way.s[2] - searchcenter[2]) - this->way.len) > LinkLength)
	    continue;

	  no = this->way.nextnode;	/* ok, we need to open the node */
	  }
    }
	
	//~ printf("ngb=%d ",numngb);
	totnumngb=numngb;
	while(numngb>0)//pop the stack
	{
		pInfected--;
		totnumngb+=treesearch_infect_particles(*pInfected,grpid, GrpTags, PPos);
		numngb--;
	}
	return totnumngb; //total number of infected particles (excluding the seed particle)
}
예제 #3
0
int ngb_treefind_variable(float searchcenter[3], float hguess)
{
  int numngb, no, p;
  double dx, dy, dz, r2, h2;
  struct NODE *this;

  h2 = hguess * hguess;

  numngb = 0;
  no = NumPart;

  while(no >= 0)
    {
      if(no < NumPart)		/* single particle */
	{
	  p = no;
	  no = Nextnode[no];

	  dx = NEAREST(P[p].Pos[0] - searchcenter[0]);
	  if(dx < -hguess)
	    continue;
	  if(dx > hguess)
	    continue;

	  dy = NEAREST(P[p].Pos[1] - searchcenter[1]);
	  if(dy < -hguess)
	    continue;
	  if(dy > hguess)
	    continue;

	  dz = NEAREST(P[p].Pos[2] - searchcenter[2]);
	  if(dz < -hguess)
	    continue;
	  if(dz > hguess)
	    continue;

	  r2 = dx * dx + dy * dy + dz * dz;

	  if(r2 < h2)
	    {
	      R2list[numngb].r2 = r2;
	      R2list[numngb].index = p;
	      numngb++;
	    }
	}
      else
	{
	  this = &Nodes[no];

	  no = Nodes[no].u.d.sibling;	/* in case the node can be discarded */

	  if((NEAREST(this->center[0] - searchcenter[0]) + 0.5 * this->len) < -hguess)
	    continue;
	  if((NEAREST(this->center[0] - searchcenter[0]) - 0.5 * this->len) > hguess)
	    continue;
	  if((NEAREST(this->center[1] - searchcenter[1]) + 0.5 * this->len) < -hguess)
	    continue;
	  if((NEAREST(this->center[1] - searchcenter[1]) - 0.5 * this->len) > hguess)
	    continue;
	  if((NEAREST(this->center[2] - searchcenter[2]) + 0.5 * this->len) < -hguess)
	    continue;
	  if((NEAREST(this->center[2] - searchcenter[2]) - 0.5 * this->len) > hguess)
	    continue;

	  no = this->u.d.nextnode;	/* ok, we need to open the node */
	}
    }

  /*
     printf("numngb=%d\n", numngb);
   */
  return numngb;
}
예제 #4
0
파일: treesearch.c 프로젝트: Kambrian/HBT
HBTInt treesearch_sphere(HBTReal searchcenter[3], HBTReal radius,HBTInt *PIndex,HBTReal PPos[][3])
{/*find a list of particles from PIndex within radius around searchcenter
  * return the number of neighbors
  * also store distance^2 and ID in the global variables NgbR2 and NgbID */
  HBTInt numngb, no, p;
  double dx, dy, dz, r2, h2;
  union NODE *this;

  h2 = radius * radius;

  numngb = 0;
  no = NumPart;

  while(no >= 0)
    {
      if(no < NumPart)		/* single particle */
	{
	  p = PIndex[no];
	  no = Nextnode[no];

	  dx = PPos[p][0] - searchcenter[0];
	  #ifdef PERIODIC_BDR
	  dx=NEAREST(dx);
	  #endif
	  if(dx < -radius)
	    continue;
	  if(dx > radius)
	    continue;

	  dy =PPos[p][1] - searchcenter[1];
	  #ifdef PERIODIC_BDR
	  dy=NEAREST(dy);
	  #endif
	  if(dy < -radius)
	    continue;
	  if(dy > radius)
	    continue;

	  dz = PPos[p][2] - searchcenter[2];
	  #ifdef PERIODIC_BDR
	  dz=NEAREST(dz);
	  #endif
	  if(dz < -radius)
	    continue;
	  if(dz > radius)
	    continue;

	  r2 = dx * dx + dy * dy + dz * dz;

	  if(r2 < h2)
	    {
	      NgbR2[numngb]= r2;
	      NgbID[numngb]= p;
	      numngb++;
		  if(numngb==NgbNMax)
		  { 
			NgbNMax*=2;
		  	NgbR2=realloc(NgbR2,sizeof(HBTReal)*NgbNMax);
			NgbID=realloc(NgbID,sizeof(HBTInt)*NgbNMax);
		  }
	    }
	}
      else
	{
	  this = &Nodes[no];

	  no = Nodes[no].way.sibling;	/* in case the node can be discarded */
	//since way.s[3] is CoM rather than center of cube,compare with Len rather than Lenhalf to allow for misaligned CoM
	  if((NEAREST(this->way.s[0] - searchcenter[0]) + this->way.len) < -radius)
	    continue;
	  if((NEAREST(this->way.s[0] - searchcenter[0]) - this->way.len) > radius)
	    continue;
	  if((NEAREST(this->way.s[1] - searchcenter[1]) + this->way.len) < -radius)
	    continue;
	  if((NEAREST(this->way.s[1] - searchcenter[1]) - this->way.len) > radius)
	    continue;
	  if((NEAREST(this->way.s[2] - searchcenter[2]) + this->way.len) < -radius)
	    continue;
	  if((NEAREST(this->way.s[2] - searchcenter[2]) - this->way.len) > radius)
	    continue;

	  no = this->way.nextnode;	/* ok, we need to open the node */
	}
    }

  /*
     fprintf(Logfile,"numngb=%d\n", numngb);
   */
  return numngb;
}