コード例 #1
0
void subfind_find_linkngb(void)
{
  long long ntot;
  int i, j, ndone, ndone_flag, npleft, dummy, iter = 0, save_DesNumNgb;
  MyFloat *Left, *Right;
  char *Todo;
  int ngrp, recvTask, place, nexport, nimport;
  double t0, t1;


  if(ThisTask == 0)
    printf("Start find_linkngb (%d particles on task=%d)\n", NumPartGroup, ThisTask);

  save_DesNumNgb = All.DesNumNgb;
  All.DesNumNgb = All.DesLinkNgb;	/* for simplicity, reset this value */


  /* allocate buffers to arrange communication */

  Ngblist = (int *) mymalloc("Ngblist", NumPartGroup * sizeof(int));
  Dist2list = (double *) mymalloc("Dist2list", NumPartGroup * sizeof(double));

  All.BunchSize =
    (int) ((All.BufferSize * 1024 * 1024) / (sizeof(struct data_index) + sizeof(struct data_nodelist) +
					     sizeof(struct linkngbdata_in) + sizeof(struct linkngbdata_out) +
					     sizemax(sizeof(struct linkngbdata_in),
						     sizeof(struct linkngbdata_out))));
  DataIndexTable =
    (struct data_index *) mymalloc("DataIndexTable", All.BunchSize * sizeof(struct data_index));
  DataNodeList =
    (struct data_nodelist *) mymalloc("DataNodeList", All.BunchSize * sizeof(struct data_nodelist));

  Left = mymalloc("Left", sizeof(MyFloat) * NumPartGroup);
  Right = mymalloc("Right", sizeof(MyFloat) * NumPartGroup);
  Todo = mymalloc("Todo", sizeof(char) * NumPartGroup);

  for(i = 0; i < NumPartGroup; i++)
    {
      Left[i] = Right[i] = 0;
      Todo[i] = 1;
    }

  /* we will repeat the whole thing for those particles where we didn't find enough neighbours */
  do
    {
      t0 = second();

      i = 0;			/* begin with this index */

      do
	{
	  for(j = 0; j < NTask; j++)
	    {
	      Send_count[j] = 0;
	      Exportflag[j] = -1;
	    }

	  /* do local particles and prepare export list */

	  for(nexport = 0; i < NumPartGroup; i++)
	    {
	      if(Todo[i])
		{
		  if(subfind_linkngb_evaluate(i, 0, &nexport, Send_count) < 0)
		    break;
		}
	    }

#ifdef OMP_SORT
	  omp_qsort(DataIndexTable, nexport, sizeof(struct data_index), data_index_compare);
#else
	  qsort(DataIndexTable, nexport, sizeof(struct data_index), data_index_compare);
#endif

	  MPI_Alltoall(Send_count, 1, MPI_INT, Recv_count, 1, MPI_INT, MPI_COMM_WORLD);

	  for(j = 0, nimport = 0, Recv_offset[0] = 0, Send_offset[0] = 0; j < NTask; j++)
	    {
	      nimport += Recv_count[j];

	      if(j > 0)
		{
		  Send_offset[j] = Send_offset[j - 1] + Send_count[j - 1];
		  Recv_offset[j] = Recv_offset[j - 1] + Recv_count[j - 1];
		}
	    }

	  LinkngbDataGet =
	    (struct linkngbdata_in *) mymalloc("	  LinkngbDataGet",
					       nimport * sizeof(struct linkngbdata_in));
	  LinkngbDataIn =
	    (struct linkngbdata_in *) mymalloc("	  LinkngbDataIn",
					       nexport * sizeof(struct linkngbdata_in));

	  /* prepare particle data for export */
	  for(j = 0; j < nexport; j++)
	    {
	      place = DataIndexTable[j].Index;

	      LinkngbDataIn[j].Pos[0] = P[place].Pos[0];
	      LinkngbDataIn[j].Pos[1] = P[place].Pos[1];
	      LinkngbDataIn[j].Pos[2] = P[place].Pos[2];
	      LinkngbDataIn[j].DM_Hsml = P[place].DM_Hsml;

	      memcpy(LinkngbDataIn[j].NodeList,
		     DataNodeList[DataIndexTable[j].IndexGet].NodeList, NODELISTLENGTH * sizeof(int));
	    }

	  /* exchange particle data */
	  for(ngrp = 1; ngrp < (1 << PTask); ngrp++)
	    {
	      recvTask = ThisTask ^ ngrp;

	      if(recvTask < NTask)
		{
		  if(Send_count[recvTask] > 0 || Recv_count[recvTask] > 0)
		    {
		      /* get the particles */
		      MPI_Sendrecv(&LinkngbDataIn[Send_offset[recvTask]],
				   Send_count[recvTask] * sizeof(struct linkngbdata_in), MPI_BYTE,
				   recvTask, TAG_DENS_A,
				   &LinkngbDataGet[Recv_offset[recvTask]],
				   Recv_count[recvTask] * sizeof(struct linkngbdata_in), MPI_BYTE,
				   recvTask, TAG_DENS_A, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
		    }
		}
	    }

	  myfree(LinkngbDataIn);
	  LinkngbDataResult =
	    (struct linkngbdata_out *) mymalloc("	  LinkngbDataResult",
						nimport * sizeof(struct linkngbdata_out));
	  LinkngbDataOut =
	    (struct linkngbdata_out *) mymalloc("	  LinkngbDataOut",
						nexport * sizeof(struct linkngbdata_out));


	  /* now do the particles that were sent to us */
	  for(j = 0; j < nimport; j++)
	    subfind_linkngb_evaluate(j, 1, &dummy, &dummy);

	  if(i >= NumPartGroup)
	    ndone_flag = 1;
	  else
	    ndone_flag = 0;

	  MPI_Allreduce(&ndone_flag, &ndone, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);

	  /* get the result */
	  for(ngrp = 1; ngrp < (1 << PTask); ngrp++)
	    {
	      recvTask = ThisTask ^ ngrp;
	      if(recvTask < NTask)
		{
		  if(Send_count[recvTask] > 0 || Recv_count[recvTask] > 0)
		    {
		      /* send the results */
		      MPI_Sendrecv(&LinkngbDataResult[Recv_offset[recvTask]],
				   Recv_count[recvTask] * sizeof(struct linkngbdata_out),
				   MPI_BYTE, recvTask, TAG_DENS_B,
				   &LinkngbDataOut[Send_offset[recvTask]],
				   Send_count[recvTask] * sizeof(struct linkngbdata_out),
				   MPI_BYTE, recvTask, TAG_DENS_B, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
		    }
		}
	    }

	  /* add the result to the local particles */
	  for(j = 0; j < nexport; j++)
	    {
	      place = DataIndexTable[j].Index;

	      P[place].DM_NumNgb += LinkngbDataOut[j].Ngb;
	    }


	  myfree(LinkngbDataOut);
	  myfree(LinkngbDataResult);
	  myfree(LinkngbDataGet);
	}
      while(ndone < NTask);

      /* do final operations on results */
      for(i = 0, npleft = 0; i < NumPartGroup; i++)
	{
	  /* now check whether we had enough neighbours */
	  if(Todo[i])
	    {
	      if(P[i].DM_NumNgb != All.DesLinkNgb &&
		 ((Right[i] - Left[i]) > 1.0e-3 * Left[i] || Left[i] == 0 || Right[i] == 0))
		{
		  /* need to redo this particle */
		  npleft++;

		  if(P[i].DM_NumNgb < All.DesLinkNgb)
		    Left[i] = DMAX(P[i].DM_Hsml, Left[i]);
		  else
		    {
		      if(Right[i] != 0)
			{
			  if(P[i].DM_Hsml < Right[i])
			    Right[i] = P[i].DM_Hsml;
			}
		      else
			Right[i] = P[i].DM_Hsml;
		    }

		  if(iter >= MAXITER - 10)
		    {
		      printf
			("i=%d task=%d ID=%d DM_Hsml=%g Left=%g Right=%g Ngbs=%g Right-Left=%g\n   pos=(%g|%g|%g)\n",
			 i, ThisTask, (int) P[i].ID, P[i].DM_Hsml, Left[i], Right[i],
			 (double) P[i].DM_NumNgb, Right[i] - Left[i], P[i].Pos[0], P[i].Pos[1], P[i].Pos[2]);
		      fflush(stdout);
		    }

		  if(Right[i] > 0 && Left[i] > 0)
		    P[i].DM_Hsml = pow(0.5 * (pow(Left[i], 3) + pow(Right[i], 3)), 1.0 / 3);
		  else
		    {
		      if(Right[i] == 0 && Left[i] == 0)
			endrun(8189);	/* can't occur */

		      if(Right[i] == 0 && Left[i] > 0)
			P[i].DM_Hsml *= 1.26;

		      if(Right[i] > 0 && Left[i] == 0)
			P[i].DM_Hsml /= 1.26;
		    }
		}
	      else
		Todo[i] = 0;
	    }
	}


      sumup_large_ints(1, &npleft, &ntot);

      t1 = second();

      if(ntot > 0)
	{
	  iter++;

	  if(iter > 0 && ThisTask == 0)
	    {
	      printf("find linkngb iteration %d: need to repeat for %d%09d particles. (took %g sec)\n", iter,
		     (int) (ntot / 1000000000), (int) (ntot % 1000000000), timediff(t0, t1));
	      fflush(stdout);
	    }

	  if(iter > MAXITER)
	    {
	      printf("failed to converge in neighbour iteration in density()\n");
	      fflush(stdout);
	      endrun(1155);
	    }
	}
    }
  while(ntot > 0);

  myfree(Todo);
  myfree(Right);
  myfree(Left);

  myfree(DataNodeList);
  myfree(DataIndexTable);

  myfree(Dist2list);
  myfree(Ngblist);

  All.DesNumNgb = save_DesNumNgb;	/* restore it */
}
コード例 #2
0
/* This function updates the weights for SN before exploding. This is
 * necessary due to the fact that gas particles neighbours of a given star
 * could have been transformed into stars and they need to be taken off the
 * neighbour list for the exploding star.
 */
void cs_update_weights(void)
{
  MyFloat *Left, *Right;
  int i, j, ndone, ndone_flag, npleft, dummy, iter = 0;
  int ngrp, sendTask, recvTask, place, nexport, nimport;
  long long ntot;
  double dmax1, dmax2;
  double desnumngb;

  if(ThisTask == 0)
    {
      printf("... start update weights phase = %d ...\n", Flag_phase);
      fflush(stdout);
    }

  Left = (MyFloat *) mymalloc(NumPart * sizeof(MyFloat));
  Right = (MyFloat *) mymalloc(NumPart * sizeof(MyFloat));

  for(i = FirstActiveParticle; i >= 0; i = NextActiveParticle[i])
    {
      if(P[i].Type == 6 || P[i].Type == 7)
	{
	  Left[i] = Right[i] = 0;
	}
    }

  /* allocate buffers to arrange communication */
  Ngblist = (int *) mymalloc(NumPart * sizeof(int));
  R2ngblist = (double *) mymalloc(NumPart * sizeof(double));


  All.BunchSize =
    (int) ((All.BufferSize * 1024 * 1024) / (sizeof(struct data_index) + sizeof(struct data_nodelist) +
					     sizeof(struct updateweight_in) +
					     sizeof(struct updateweight_out) +
					     sizemax(sizeof(struct updateweight_in),
						     sizeof(struct updateweight_out))));
  DataIndexTable = (struct data_index *) mymalloc(All.BunchSize * sizeof(struct data_index));
  DataNodeList = (struct data_nodelist *) mymalloc(All.BunchSize * sizeof(struct data_nodelist));


  desnumngb = All.DesNumNgb;

  /* we will repeat the whole thing for those particles where we didn't find enough neighbours */
  do
    {
      i = FirstActiveParticle;	/* begin with this index */

      do
	{
	  for(j = 0; j < NTask; j++)
	    {
	      Send_count[j] = 0;
	      Exportflag[j] = -1;
	    }

	  /* do local particles and prepare export list */
	  for(nexport = 0; i >= 0; i = NextActiveParticle[i])
	    {
	      if((P[i].Type == 6 || P[i].Type == 7) && P[i].TimeBin >= 0)
		{
		  if(cs_update_weight_evaluate(i, 0, &nexport, Send_count) < 0)
		    break;
		}
	    }

#ifdef MYSORT
	  mysort_dataindex(DataIndexTable, nexport, sizeof(struct data_index), data_index_compare);
#else
	  qsort(DataIndexTable, nexport, sizeof(struct data_index), data_index_compare);
#endif

	  MPI_Allgather(Send_count, NTask, MPI_INT, Sendcount_matrix, NTask, MPI_INT, MPI_COMM_WORLD);

	  for(j = 0, nimport = 0, Recv_offset[0] = 0, Send_offset[0] = 0; j < NTask; j++)
	    {
	      Recv_count[j] = Sendcount_matrix[j * NTask + ThisTask];
	      nimport += Recv_count[j];

	      if(j > 0)
		{
		  Send_offset[j] = Send_offset[j - 1] + Send_count[j - 1];
		  Recv_offset[j] = Recv_offset[j - 1] + Recv_count[j - 1];
		}
	    }

	  UpdateweightGet = (struct updateweight_in *) mymalloc(nimport * sizeof(struct updateweight_in));
	  UpdateweightIn = (struct updateweight_in *) mymalloc(nexport * sizeof(struct updateweight_in));

	  /* prepare particle data for export */
	  for(j = 0; j < nexport; j++)
	    {
	      place = DataIndexTable[j].Index;

	      UpdateweightIn[j].Pos[0] = P[place].Pos[0];
	      UpdateweightIn[j].Pos[1] = P[place].Pos[1];
	      UpdateweightIn[j].Pos[2] = P[place].Pos[2];
	      UpdateweightIn[j].Hsml = PPP[place].Hsml;

	      memcpy(UpdateweightIn[j].NodeList,
		     DataNodeList[DataIndexTable[j].IndexGet].NodeList, NODELISTLENGTH * sizeof(int));
	    }

	  /* exchange particle data */
	  for(ngrp = 1; ngrp < (1 << PTask); ngrp++)
	    {
	      sendTask = ThisTask;
	      recvTask = ThisTask ^ ngrp;

	      if(recvTask < NTask)
		{
		  if(Send_count[recvTask] > 0 || Recv_count[recvTask] > 0)
		    {
		      /* get the particles */
		      MPI_Sendrecv(&UpdateweightIn[Send_offset[recvTask]],
				   Send_count[recvTask] * sizeof(struct updateweight_in), MPI_BYTE,
				   recvTask, TAG_DENS_A,
				   &UpdateweightGet[Recv_offset[recvTask]],
				   Recv_count[recvTask] * sizeof(struct updateweight_in), MPI_BYTE,
				   recvTask, TAG_DENS_A, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
		    }
		}
	    }


	  myfree(UpdateweightIn);
	  UpdateweightResult =
	    (struct updateweight_out *) mymalloc(nimport * sizeof(struct updateweight_out));
	  UpdateweightOut = (struct updateweight_out *) mymalloc(nexport * sizeof(struct updateweight_out));


	  /* now do the particles that were sent to us */

	  for(j = 0; j < nimport; j++)
	    cs_update_weight_evaluate(j, 1, &dummy, &dummy);

	  if(i < 0)
	    ndone_flag = 1;
	  else
	    ndone_flag = 0;

	  MPI_Allreduce(&ndone_flag, &ndone, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);

	  /* get the result */
	  for(ngrp = 1; ngrp < (1 << PTask); ngrp++)
	    {
	      sendTask = ThisTask;
	      recvTask = ThisTask ^ ngrp;
	      if(recvTask < NTask)
		{
		  if(Send_count[recvTask] > 0 || Recv_count[recvTask] > 0)
		    {
		      /* send the results */
		      MPI_Sendrecv(&UpdateweightResult[Recv_offset[recvTask]],
				   Recv_count[recvTask] * sizeof(struct updateweight_out),
				   MPI_BYTE, recvTask, TAG_DENS_B,
				   &UpdateweightOut[Send_offset[recvTask]],
				   Send_count[recvTask] * sizeof(struct updateweight_out),
				   MPI_BYTE, recvTask, TAG_DENS_B, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
		    }
		}

	    }


	  /* add the result to the local particles */
	  for(j = 0; j < nexport; j++)
	    {
	      place = DataIndexTable[j].Index;

	      PPP[place].n.dNumNgb += UpdateweightOut[j].Ngb;
	    }

	  myfree(UpdateweightOut);
	  myfree(UpdateweightResult);
	  myfree(UpdateweightGet);
	}
      while(ndone < NTask);


      /* do final operations on results */
      for(i = FirstActiveParticle, npleft = 0; i >= 0; i = NextActiveParticle[i])
	{
	  if(P[i].Type == 6 || P[i].Type == 7)
	    {
#ifdef FLTROUNDOFFREDUCTION
	      PPP[i].n.NumNgb = FLT(PPP[i].n.dNumNgb);
#endif

	      /* now check whether we had enough neighbours */

	      if(PPP[i].n.NumNgb < (desnumngb - All.MaxNumNgbDeviation) ||
		 (PPP[i].n.NumNgb > (desnumngb + All.MaxNumNgbDeviation)
		  && PPP[i].Hsml > (1.01 * All.MinGasHsml)))
		{
		  /* need to redo this particle */
		  npleft++;

		  if(Left[i] > 0 && Right[i] > 0)
		    if((Right[i] - Left[i]) < 1.0e-3 * Left[i])
		      {
			/* this one should be ok */
			npleft--;
			P[i].TimeBin = -P[i].TimeBin - 1;	/* Mark as inactive */
			continue;
		      }

		  if(PPP[i].n.NumNgb < (desnumngb - All.MaxNumNgbDeviation))
		    Left[i] = DMAX(PPP[i].Hsml, Left[i]);
		  else
		    {
		      if(Right[i] != 0)
			{
			  if(PPP[i].Hsml < Right[i])
			    Right[i] = PPP[i].Hsml;
			}
		      else
			Right[i] = PPP[i].Hsml;
		    }

		  if(iter >= MAXITER - 10)
		    {
		      printf
			("i=%d task=%d ID=%d Hsml=%g Left=%g Right=%g Ngbs=%g Right-Left=%g\n   pos=(%g|%g|%g)\n",
			 i, ThisTask, (int) P[i].ID, PPP[i].Hsml, Left[i], Right[i],
			 (float) PPP[i].n.NumNgb, Right[i] - Left[i], P[i].Pos[0], P[i].Pos[1], P[i].Pos[2]);
		      fflush(stdout);
		    }

		  if(Right[i] > 0 && Left[i] > 0)
		    PPP[i].Hsml = pow(0.5 * (pow(Left[i], 3) + pow(Right[i], 3)), 1.0 / 3);
		  else
		    {
		      if(Right[i] == 0 && Left[i] == 0)
			endrun(8188);	/* can't occur */

		      if(Right[i] == 0 && Left[i] > 0)
			{
			  PPP[i].Hsml *= 1.26;
			}

		      if(Right[i] > 0 && Left[i] == 0)
			{
			  PPP[i].Hsml /= 1.26;
			}
		    }

		  if(PPP[i].Hsml < All.MinGasHsml)
		    PPP[i].Hsml = All.MinGasHsml;
		}
	      else
		P[i].TimeBin = -P[i].TimeBin - 1;	/* Mark as inactive */


	      /* CECILIA */
	      if(iter == MAXITER)
		{
		  int old_type;

		  old_type = P[i].Type;
		  P[i].Type = 4;	/* no SN mark any more */
		  PPP[i].n.NumNgb = 0;
		  printf("part=%d of type=%d was assigned NumNgb=%g and type=%d\n", i, old_type,
			 PPP[i].n.NumNgb, P[i].Type);
		}

	    }
	}

      sumup_large_ints(1, &npleft, &ntot);

      if(ntot > 0)
	{
	  iter++;

	  if(iter > 0 && ThisTask == 0)
	    {
	      printf("ngb iteration %d: need to repeat for %d%09d particles.\n", iter,
		     (int) (ntot / 1000000000), (int) (ntot % 1000000000));
	      fflush(stdout);
	    }

	  if(iter > MAXITER)
	    {
#ifndef CS_FEEDBACK
	      printf("failed to converge in neighbour iteration in update_weights \n");
	      fflush(stdout);
	      endrun(1155);
#else
	      /* CECILIA */
	      if(Flag_phase == 2)	/* HOT */
		{
		  printf("Not enough hot neighbours for energy/metal distribution part=%d Type=%d\n", i,
			 P[i].Type);
		  fflush(stdout);
		  break;
		  /* endrun(1156); */
		}
	      else
		{
		  printf("Not enough cold neighbours for energy/metal distribution part=%d Type=%d\n", i,
			 P[i].Type);
		  fflush(stdout);
		  break;
		}
#endif
	    }
	}
    }
  while(ntot > 0);


  myfree(DataNodeList);
  myfree(DataIndexTable);
  myfree(R2ngblist);
  myfree(Ngblist);
  myfree(Right);
  myfree(Left);

  /* mark as active again */
  for(i = FirstActiveParticle; i >= 0; i = NextActiveParticle[i])
    if(P[i].TimeBin < 0)
      P[i].TimeBin = -P[i].TimeBin - 1;

  /* collect some timing information */

  if(ThisTask == 0)
    {
      printf("... update weights phase = %d done...\n", Flag_phase);
      fflush(stdout);
    }

}
コード例 #3
0
ファイル: scf.c プロジェクト: boywert/SussexBigRun2013
/* reshift positions to center of mass */
void SCF_do_center_of_mass_correction(double fac_rad, double start_rad, double fac_part, int max_iter)
{
 int i, k, n;
 MyDouble pos[3], pos_all[3];
 int num, num_all;
 int iter=0;
 double rad, max_rad=start_rad;


 if (ThisTask==0)
  printf("SCF center of mass correction...\n");

 
 for(n = 0; n < 6; n++)
   SCF_n_type[n] = 0;

 for(n = 0; n < NumPart; n++)
   SCF_n_type[P[n].Type]++;

 sumup_large_ints(6, SCF_n_type, SCF_ntot_type_all);
 
 if (ThisTask==0)
  printf("total number of DM particles=%lld\n", SCF_ntot_type_all[1]);
 
 
 
 while(iter < max_iter)
  {
   num=0;
   for(k = 0; k < 3; k++)
    {
     pos[k]=0.0;
     pos_all[k]=0.0;
    }
 
   for(i = 0; i < NumPart; i++)
    { 
     rad = sqrt(P[i].Pos[0]*P[i].Pos[0] + P[i].Pos[1]*P[i].Pos[1] + P[i].Pos[2]*P[i].Pos[2]);
     
     /* consider only DM particles of SCF coefficients */
     if (P[i].Type != 1 || rad > max_rad)
      continue;
   
     for(k = 0; k < 3; k++)
      pos[k]+=P[i].Pos[k];
     
     num++;
    }  
   
   MPI_Allreduce(&pos[0], &pos_all[0], 3, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); 
   MPI_Allreduce(&num, &num_all, 3, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
   
#ifdef DEBUG
  if (ThisTask==0)
   {
    printf("temp. center of mass = (%g|%g|%g)     iter=%d  num_all=%d\n", pos_all[0]/num_all, pos_all[1]/num_all, pos_all[2]/num_all, iter, num_all);
    printf("done.\n");
   }

#endif  
 
   for(i = 0; i < NumPart; i++)
   {    
    for(k = 0; k < 3; k++)
     P[i].Pos[k]-=pos_all[k]/num_all;
   }  
 
   if (num_all < fac_part*SCF_ntot_type_all[1])
    break;
    
   max_rad*=fac_rad;
   iter++;
  }


  if (ThisTask==0)
   {
    printf("SCF center of mass = (%g|%g|%g)   iter=%d\n", pos_all[0]/num_all, pos_all[1]/num_all, pos_all[2]/num_all, iter);
    printf("done.\n");
   }
}