コード例 #1
0
ファイル: veldisp.c プロジェクト: surftour/astrotools
/* This function computes the local velocity dispersion
 * of each particle (among particles of the same type)
 */
void veldisp(void)
{
  double vsum[3], v2sum[3];
  double h, hinv, hinv3;
  double rho, wk;
  double dx, dy, dz, r, r2, u;
  int    i,j,k,ii,n,count;
  float  *r2list;
  int    *ngblist;
 

  /* only active particles */


  for(i=IndFirstUpdate,count=0; count<NumForceUpdate; i=P[i].ForceFlag, count++)   
    {
      if(P[i].Type>0)
	{
	  rho= vsum[0] = vsum[1] = vsum[2] = v2sum[0] = v2sum[1] = v2sum[2] = 0;
  
	  P[i].HsmlVelDisp= sqrt(ngb_treefind(P[i].PosPred, All.DesNumNgb, 
					      1.1*P[i].HsmlVelDisp, 
					      P[i].Type, &ngblist, &r2list));   
	  
	  h = P[i].HsmlVelDisp;
	  hinv  = 1.0/h;
	  hinv3 = hinv*hinv*hinv;
	  
	  for(n=0; n<All.DesNumNgb; n++)
	    {
	      j  = ngblist[n]+1; 
	  
	      dx = P[i].PosPred[0] - P[j].PosPred[0];
	      dy = P[i].PosPred[1] - P[j].PosPred[1];
	      dz = P[i].PosPred[2] - P[j].PosPred[2];
#ifdef PERIODIC
	      dx= periodic(dx);
	      dy= periodic(dy);
	      dz= periodic(dz);
#endif
	      r2 = dx*dx + dy*dy + dz*dz;
	      
	      r = sqrt(r2);
	      
	      if(r<h)
		{
		  u = r*hinv;
		  
		  ii = (int)(u*KERNEL_TABLE);
		  
		  wk =hinv3*( Kernel[ii]  + (Kernel[ii+1]-Kernel[ii])*(u-KernelRad[ii])*KERNEL_TABLE);
		  
		  rho += P[j].Mass * wk;
		}
	      
	      for(k=0; k<3; k++)
		{
		  vsum[k] +=  P[j].VelPred[k];
		  v2sum[k] += P[j].VelPred[k]*P[j].VelPred[k];
		}
	    }
	  
	  P[i].DensVelDisp = rho;
	  P[i].VelDisp = 0;
	  
	  for(k=0; k<3; k++)
	    {
	      vsum[k] /= All.DesNumNgb;
	      v2sum[k]/= All.DesNumNgb;
	      
	      P[i].VelDisp += v2sum[k] - vsum[k]*vsum[k];
	    }
	  
	  if(P[i].VelDisp > 0)
	    P[i].VelDisp= sqrt(P[i].VelDisp);
	  else
	    P[i].VelDisp= 0;
	}
    }
}
コード例 #2
0
ファイル: sidm.c プロジェクト: junkoda/sidm-nbody
/* the function below detects particles that have a number of neighbours 
 * outside the allowed tolerance range. For these, particles the smoothing
 * length is adjusted accordingly. Note that the smoothing length is
 */
void sidm_ensure_neighbours(int mode)
{
#define MAXITER 30

  int    i, ntot, last=0;
  float  *r2list;
  int    *ngblist, count, candidates;
  int    iter=0;
  double save;
  
  /*
  int    IndFirstUpdateBackup, NumForceUpdateBackup;
  
  IndFirstUpdateBackup= IndFirstUpdate;
  NumForceUpdateBackup= NumForceUpdate;
  for(i=IndFirstUpdate, count=0; count<NumForceUpdate; 
      i=P[i].ForceFlag, count++){
    P[i].ForceFlagBackup= P[i].ForceFlag;
  }
  */

  for(i=IndFirstUpdate, count=0, candidates=0; count<NumForceUpdate; 
      i=P[i].ForceFlag, count++) {
    if(P[i].Type>0) {
      if(P[i].NgbVelDisp < (All.DesNumNgb-All.MaxNumNgbDeviation) || 
	 (P[i].NgbVelDisp > (All.DesNumNgb+All.MaxNumNgbDeviation)))
        candidates++;
    }
  }

  MPI_Reduce(&candidates, &ntot, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
  MPI_Bcast(&ntot, 1, MPI_INT, 0, MPI_COMM_WORLD);
  
  if(ntot > 0) {
    //#ifdef FINDNBRLOG
      //      if(ThisTask==0)
      //{
      //printf("\n%d particles have too few/too many neighbours in sidm calculation!\n", ntot);
      // printf("Now fixing that...\n"); 
      // }
    //#endif
      
    for(i=IndFirstUpdate, count=0; count<NumForceUpdate; 
	i=P[i].ForceFlag, count++)   
      P[i].Left= P[i].Right= 0;
      
    do {
      for(i=1+N_gas, NumForceUpdate= 0, NumSphUpdate=0; i<=NumPart; i++) { 
	if( P[i].NgbVelDisp < (All.DesNumNgb-All.MaxNumNgbDeviation) || 
	    P[i].NgbVelDisp > (All.DesNumNgb+All.MaxNumNgbDeviation)) {
          if(P[i].Left>0 && P[i].Right>0)
            if((P[i].Right-P[i].Left) < 1.0e-3 * P[i].Left)
              continue;
	  
          if(NumForceUpdate==0)
            IndFirstUpdate= i;
          else
            P[last].ForceFlag= i;

          NumForceUpdate++;
          last=i;
          
          if(P[i].NgbVelDisp < (All.DesNumNgb-All.MaxNumNgbDeviation))
            P[i].Left= dmax(P[i].HsmlVelDisp, P[i].Left);
          else
            if(P[i].Right!=0)
              {
            if(P[i].HsmlVelDisp<P[i].Right)
              P[i].Right= P[i].HsmlVelDisp;
              }
            else
              P[i].Right= P[i].HsmlVelDisp;
        }
      }
      
      MPI_Allreduce(&NumForceUpdate, &ntot, 1, MPI_INT, MPI_SUM, 
		    MPI_COMM_WORLD);
      
      if(ntot > 0) {
	//#ifdef FINDNBRLOG
	//  if(ThisTask==0)
	//printf("ngb iteration %d.  still %d particles\n", iter, ntot);
	//#endif
	for(i=IndFirstUpdate, count=0; count<NumForceUpdate; 
	    i=P[i].ForceFlag, count++) {
          if(iter >= 20) {
	    printf("i=%d ID=%d Hsml=%g Left=%g Right=%g Ngbs=%d Right-Left=%g\n   pos=(%g|%g|%g)\n",
		   i, P[i].ID, P[i].HsmlVelDisp, P[i].Left, P[i].Right, 
		   P[i].NgbVelDisp, P[i].Right-P[i].Left,
		   P[i].PosPred[0], P[i].PosPred[1], P[i].PosPred[2]);
	  }
          
          if(iter == MAXITER) {
	    printf("ThisTask=%d Mi=(%g|%g|%g) Ma=(%g|%g|%g)\n", ThisTask,
		   DomainMin[P[i].Type][0], DomainMin[P[i].Type][1], 
		   DomainMin[P[i].Type][2], DomainMax[P[i].Type][0], 
		   DomainMax[P[i].Type][1], DomainMax[P[i].Type][2]);
	    printf("i=%d ID=%d coord=(%g|%g|%g)\n", i, P[i].ID, 
		   P[i].PosPred[0], P[i].PosPred[1], P[i].PosPred[2]);
	    printf("ngb_treefind= %g\n", sqrt(ngb_treefind(P[i].PosPred , 
			  All.DesNumNgb, 0, P[i].Type, &ngblist, &r2list)));
	  }
          
          if(P[i].Left==0 || P[i].Right==0) {
	    if(P[i].Right==0 && P[i].NgbVelDisp<15 && 
	       NtypeLocal[P[i].Type]>All.DesNumNgb) {
              P[i].HsmlVelDisp= sqrt(ngb_treefind(P[i].PosPred, All.DesNumNgb, 
					    0, P[i].Type, &ngblist, &r2list));  
            }
	    else {
              P[i].HsmlVelDisp=  P[i].HsmlVelDisp*( 0.5 + 0.5*pow(P[i].NgbVelDisp/((double)All.DesNumNgb), -1.0/3));
            }
	  }
          else {
	    P[i].HsmlVelDisp=  0.5*(P[i].Left + P[i].Right);
	  }
        }
          
	sidm();

	iter++;

	if(iter > MAXITER) {
          fprintf(stdout, "failed to converge in function ensure_neighbours()\n");
          endrun(1155);
        }
      }
    } while(ntot > 0);
      
    if(mode == 0) {   /* restore timeline to active particles */
      /*
      IndFirstUpdate= IndFirstUpdateBackup;
      NumForceUpdate= NumForceUpdateBackup;
      for(i=IndFirstUpdateBackup, count=0; count<NumForceUpdateBackup; 
	  i=P[i].ForceFlagBackup, count++){
	P[i].ForceFlag= P[i].ForceFlagBackup;
      }
      */
      
      save= All.TimeStep;
      find_next_time();
      All.TimeStep= save;
    }
    else { /* make all particles active again */
      for(i=1; i<=NumPart; i++) 
        P[i].ForceFlag=i+1;
      
      P[NumPart].ForceFlag=1; 
      IndFirstUpdate=1; 
      NumForceUpdate=NumPart; 
      NumSphUpdate=N_gas;
    }
  }
#undef MAXITER
}