GlobalGridPartitioning::GlobalGridPartitioning(Index pos, Index procs, Index size, int points_min)
{
  Index i;
  Index index_beg, index_end;
  Index local_size;

  const Index active_procs = size / points_min;
  const Index size_per_proc = size / active_procs;
  const Index remainder = size % active_procs;

  for (i.X() = 0; i.X() < active_procs.X(); ++i.X())
    for (i.Y() = 0; i.Y() < active_procs.Y(); ++i.Y())
      for (i.Z() = 0; i.Z() < active_procs.Z(); ++i.Z()) {

	local_size = size_per_proc;

	for (int j=0; j<3; ++j)
	  if (pos[j] < remainder[j])
	    ++(local_size[j]);

	index_beg = i * local_size;

	for (int j=0; j<3; ++j)
	  if (i[j] >= remainder[j])
	    index_beg[j] += remainder[j];

	index_end = index_beg + local_size;

	begin.insert(std::make_pair(i, index_beg));
	end.insert(std::make_pair(i, index_end));

      }

}
Exemple #2
0
vmg_float Helper::InterpolateTrilinear(const Vector& point, const Grid& grid)
{
  vmg_float interpolate_vals[4], grid_vals[8];

  const Index index_global = (point - grid.Extent().Begin()) / grid.Extent().MeshWidth();
  const Index index_local = index_global - grid.Global().LocalBegin() + grid.Local().Begin();
  const Vector coord = (point - grid.Extent().Begin() - index_global * grid.Extent().MeshWidth()) / grid.Extent().MeshWidth();

  grid_vals[0] = grid.GetVal(index_local.X()  , index_local.Y()  , index_local.Z()  );
  grid_vals[1] = grid.GetVal(index_local.X()+1, index_local.Y()  , index_local.Z()  );
  grid_vals[2] = grid.GetVal(index_local.X()  , index_local.Y()+1, index_local.Z()  );
  grid_vals[3] = grid.GetVal(index_local.X()+1, index_local.Y()+1, index_local.Z()  );
  grid_vals[4] = grid.GetVal(index_local.X()  , index_local.Y()  , index_local.Z()+1);
  grid_vals[5] = grid.GetVal(index_local.X()+1, index_local.Y()  , index_local.Z()+1);
  grid_vals[6] = grid.GetVal(index_local.X()  , index_local.Y()+1, index_local.Z()+1);
  grid_vals[7] = grid.GetVal(index_local.X()+1, index_local.Y()+1, index_local.Z()+1);

  for (int i=0; i<4; ++i)
    interpolate_vals[i] = (1.0 - coord.X()) * grid_vals[2*i] + coord.X() * grid_vals[2*i+1];

  for (int i=0; i<2; ++i)
    interpolate_vals[i] = (1.0 - coord.Y()) * interpolate_vals[2*i] + coord.Y() * interpolate_vals[2*i+1];

  return (1.0 - coord.Z()) * interpolate_vals[0] + coord.Z() * interpolate_vals[1];
}
Exemple #3
0
static inline void ComputePartial(Grid& sol, Grid& rhs,
				  const Index& begin, const Index& end,
				  const vmg_float& prefactor, const int& off)
{
  const vmg_float fac = 1.0 / 6.0;

  for (int i=begin.X(); i<end.X(); ++i)
    for (int j=begin.Y(); j<end.Y(); ++j)
      for (int k=begin.Z() + (i + j + begin.Z() + off) % 2; k<end.Z(); k+=2)
	sol(i,j,k) = prefactor * rhs.GetVal(i,j,k) + fac * (sol.GetVal(i-1,j  ,k  ) +
							    sol.GetVal(i+1,j  ,k  ) +
							    sol.GetVal(i  ,j-1,k  ) +
							    sol.GetVal(i  ,j+1,k  ) +
							    sol.GetVal(i  ,j  ,k-1) +
							    sol.GetVal(i  ,j  ,k+1));
}
Exemple #4
0
void CommSerial::PrintGrid(Grid& grid, const char* information)
{
  Index i;
  std::stringstream out;
  std::ofstream out_file;

  OpenFileAndPrintHeader(out_file, grid, information);

  for (i.Z()=grid.Local().Begin().Z(); i.Z()<grid.Local().End().Z(); ++i.Z())
    for (i.Y()=grid.Local().Begin().Y(); i.Y()<grid.Local().End().Y(); ++i.Y())
      for (i.X()=grid.Local().Begin().X(); i.X()<grid.Local().End().X(); ++i.X())
	out << std::scientific << grid.GetVal(i) << std::endl;

  out_file << out.str();
  out_file.close();
}
Exemple #5
0
static inline void ComputePartial(Grid& sol, Grid& rhs, const Stencil& mat,
				  const Index& begin, const Index& end,
				  const vmg_float& prefactor, const vmg_float& diag_inv,
				  const int& off)
{
  int i,j,k;
  vmg_float temp;
  Stencil::iterator iter;

  for (i=begin.X(); i<end.X(); ++i)
    for (j=begin.Y(); j<end.Y(); ++j) {

      int z_begin = begin.Z() + (i + j + begin.Z() + off) % 2;

#ifdef DEBUG
      int off_sum = MG::GetComm()->LevelSum(rhs, z_begin - begin.Z());
      assert(z_begin - begin.Z() == 0 || z_begin - begin.Z() == 1);
      assert(off_sum == 0 || off_sum == MG::GetComm()->Size(rhs));
#endif /* DEBUG */

      for (k=z_begin; k<end.Z(); k+=2) {

	temp = prefactor * rhs.GetVal(i,j,k);

	for (iter=mat.begin(); iter!=mat.end(); ++iter)
	  temp -= iter->Val() * sol.GetVal(i+iter->Disp().X(),
					   j+iter->Disp().Y(),
					   k+iter->Disp().Z());

	sol(i,j,k) = temp * diag_inv;

      }
    }
}
void InterfaceParticles::ExportSolution(Grid& grid)
{
  Index i;

#ifdef OUTPUT_DEBUG
  vmg_float e = 0.0;
  vmg_float e_long = 0.0;
  vmg_float e_self = 0.0;
  vmg_float e_short_peak = 0.0;
  vmg_float e_short_spline = 0.0;
#endif

  Factory& factory = MG::GetFactory();
  Particle::CommMPI& comm = *dynamic_cast<Particle::CommMPI*>(MG::GetComm());

  /*
   * Get parameters and arrays
   */
  const vmg_int& near_field_cells = factory.GetObjectStorageVal<int>("PARTICLE_NEAR_FIELD_CELLS");
  const vmg_int& interpolation_degree = factory.GetObjectStorageVal<int>("PARTICLE_INTERPOLATION_DEGREE");

  Particle::Interpolation ip(interpolation_degree);

  const vmg_float r_cut = near_field_cells * grid.Extent().MeshWidth().Max();

  /*
   * Copy potential values to a grid with sufficiently large halo size.
   * This may be optimized in future.
   * The parameters of this grid have been set in the import step.
   */
  Grid& particle_grid = comm.GetParticleGrid();

  for (i.X()=0; i.X()<grid.Local().Size().X(); ++i.X())
    for (i.Y()=0; i.Y()<grid.Local().Size().Y(); ++i.Y())
      for (i.Z()=0; i.Z()<grid.Local().Size().Z(); ++i.Z())
        particle_grid(i + particle_grid.Local().Begin()) = grid.GetVal(i + grid.Local().Begin());

  comm.CommToGhosts(particle_grid);

  /*
   * Compute potentials
   */
  Particle::LinkedCellList lc(particles, near_field_cells, grid);
  Particle::LinkedCellList::iterator p1, p2;
  Grid::iterator iter;

  comm.CommLCListToGhosts(lc);

  for (int i=lc.Local().Begin().X(); i<lc.Local().End().X(); ++i)
    for (int j=lc.Local().Begin().Y(); j<lc.Local().End().Y(); ++j)
      for (int k=lc.Local().Begin().Z(); k<lc.Local().End().Z(); ++k) {

	if (lc(i,j,k).size() > 0)
	  ip.ComputeCoefficients(particle_grid, Index(i,j,k) - lc.Local().Begin() + particle_grid.Local().Begin());

	for (p1=lc(i,j,k).begin(); p1!=lc(i,j,k).end(); ++p1) {

	  // Interpolate long-range part of potential and electric field
	  ip.Evaluate(**p1);

	  // Subtract self-induced potential
	  (*p1)->Pot() -= (*p1)->Charge() * spl.GetAntiDerivativeAtZero();

#ifdef OUTPUT_DEBUG
	  e_long += 0.5 * (*p1)->Charge() * ip.EvaluatePotentialLR(**p1);
	  e_self += 0.5 * (*p1)->Charge() * (*p1)->Charge() * spl.GetAntiDerivativeAtZero();
#endif

	  for (int dx=-1*near_field_cells; dx<=near_field_cells; ++dx)
	    for (int dy=-1*near_field_cells; dy<=near_field_cells; ++dy)
	      for (int dz=-1*near_field_cells; dz<=near_field_cells; ++dz) {

		for (p2=lc(i+dx,j+dy,k+dz).begin(); p2!=lc(i+dx,j+dy,k+dz).end(); ++p2)

		  if (*p1 != *p2) {

		    const Vector dir = (*p1)->Pos() - (*p2)->Pos();
		    const vmg_float length = dir.Length();

		    if (length < r_cut) {

		      (*p1)->Pot() += (*p2)->Charge() / length * (1.0 + spl.EvaluatePotential(length));
		      (*p1)->Field() += (*p2)->Charge() * dir * spl.EvaluateField(length);

#ifdef OUTPUT_DEBUG
		      e_short_peak += 0.5 * (*p1)->Charge() * (*p2)->Charge() / length;
		      e_short_spline += 0.5 * (*p1)->Charge() * (*p2)->Charge() / length * spl.EvaluatePotential(length);
#endif
		    }
		  }
	      }
	}
      }

  /* Remove average force term */
  Vector average_force = 0.0;
  for (std::list<Particle::Particle>::const_iterator iter=particles.begin(); iter!=particles.end(); ++iter)
    average_force += iter->Charge() * iter->Field();
  const vmg_int& npl = MG::GetFactory().GetObjectStorageVal<vmg_int>("PARTICLE_NUM_LOCAL");
  const vmg_int num_particles_global = comm.GlobalSum(npl);
  average_force /= num_particles_global;
  comm.GlobalSumArray(average_force.vec(), 3);
  for (std::list<Particle::Particle>::iterator iter=particles.begin(); iter!=particles.end(); ++iter)
    iter->Field() -= average_force / iter->Charge();

  comm.CommParticlesBack(particles);

#ifdef OUTPUT_DEBUG
  vmg_float* q = factory.GetObjectStorageArray<vmg_float>("PARTICLE_CHARGE_ARRAY");
  const vmg_int& num_particles_local = factory.GetObjectStorageVal<vmg_int>("PARTICLE_NUM_LOCAL");
  const vmg_float* p = factory.GetObjectStorageArray<vmg_float>("PARTICLE_POTENTIAL_ARRAY");
  const vmg_float* f = factory.GetObjectStorageArray<vmg_float>("PARTICLE_FIELD_ARRAY");


  e_long = comm.GlobalSumRoot(e_long);
  e_short_peak = comm.GlobalSumRoot(e_short_peak);
  e_short_spline = comm.GlobalSumRoot(e_short_spline);
  e_self = comm.GlobalSumRoot(e_self);

  for (int j=0; j<num_particles_local; ++j)
    e += 0.5 * p[j] * q[j];
  e = comm.GlobalSumRoot(e);

  comm.PrintOnce(Debug, "E_long:         %e", e_long);
  comm.PrintOnce(Debug, "E_short_peak:   %e", e_short_peak);
  comm.PrintOnce(Debug, "E_short_spline: %e", e_short_spline);
  comm.PrintOnce(Debug, "E_self:         %e", e_self);
  comm.PrintOnce(Debug, "E_total:        %e", e);
  comm.PrintOnce(Debug, "E_total*:       %e", e_long + e_short_peak + e_short_spline - e_self);
#endif
}
Exemple #7
0
inline int Grid::GlobalLinearIndex(const Index& index) const
{
  return GlobalLinearIndex(index.X(), index.Y(), index.Z());
}
Exemple #8
0
inline int IsGrid<T>::GlobalLinearIndex(const Index& index) const
{
  return index.Z() + global.GlobalSize().Z() * (index.Y() + global.GlobalSize().Y() * index.X());
}
void Particle::CommMPI::CommLCListToGhosts(LinkedCellList& lc)
{
  VMG::MPI::DatatypesLocal types(lc, comm_global, false);
  std::vector<int> send_size(types.NB().size());
  vmg_int recv_size;
  std::list<Particle*>::iterator iter;
  Index ind;
  Vector offset;

  const Vector halo_length = lc.Local().HaloSize1() * lc.Extent().MeshWidth();

  lc.ClearHalo();

  for (unsigned int i=0; i<types.NB().size(); ++i)
    if (types.NB()[i].Feasible()) {

      for (int j=0; j<3; ++j)
        if ((types.Offset()[i][j] < 0 && lc.Global().LocalBegin()[j] == 0) ||
            (types.Offset()[i][j] > 0 && lc.Global().LocalEnd()[j] == lc.Global().GlobalSize()[j]))
          offset[j] = -1.0 * types.Offset()[i][j] * lc.Extent().Size()[j];
        else
          offset[j] = 0.0;

      for (ind.X() = types.NB()[i].Starts().X(); ind.X() < types.NB()[i].Starts().X()+types.NB()[i].Subsizes().X(); ++ind.X())
	for (ind.Y() = types.NB()[i].Starts().Y(); ind.Y() < types.NB()[i].Starts().Y()+types.NB()[i].Subsizes().Y(); ++ind.Y())
	  for (ind.Z() = types.NB()[i].Starts().Z(); ind.Z() < types.NB()[i].Starts().Z()+types.NB()[i].Subsizes().Z(); ++ind.Z())
	    for (iter=lc(ind).begin(); iter!=lc(ind).end(); ++iter) {

              for (int j=0; j<3; ++j)
                types.NB()[i].Buffer().push_back((*iter)->Pos()[j] + offset[j]);
              types.NB()[i].Buffer().push_back((*iter)->Charge());

              assert(lc.Extent().Begin().IsComponentwiseLessOrEqual((*iter)->Pos()));
              assert(lc.Extent().End().IsComponentwiseGreaterOrEqual((*iter)->Pos()));
              assert(lc.Extent().Begin().IsComponentwiseLessOrEqual((*iter)->Pos() + offset + halo_length));
              assert(lc.Extent().End().IsComponentwiseGreaterOrEqual((*iter)->Pos() + offset - halo_length));
	    }

      send_size[i] = types.NB()[i].Buffer().size();
      MPI_Isend(&send_size[i], 1, MPI_INT, types.NB()[i].Rank(), 2048+types.NB()[i].TagSend(), comm_global, &Request());

      if (send_size[i] > 0)
	MPI_Isend(&types.NB()[i].Buffer().front(), send_size[i], MPI_DOUBLE,
		  types.NB()[i].Rank(), 4096+types.NB()[i].TagSend(),
		  comm_global, &Request());
    }

  for (unsigned int i=0; i<types.Halo().size(); ++i)
    if (types.Halo()[i].Feasible()) {
      MPI_Recv(&recv_size, 1, MPI_INT, types.Halo()[i].Rank(), 2048+types.Halo()[i].TagReceive(), comm_global, MPI_STATUS_IGNORE);
      if (recv_size > 0) {
	types.Halo()[i].Buffer().resize(recv_size);
	MPI_Irecv(&types.Halo()[i].Buffer().front(), recv_size, MPI_DOUBLE,
		  types.Halo()[i].Rank(), 4096+types.Halo()[i].TagReceive(),
		  comm_global, &Request());
      }
    }

  WaitAll();

  for (unsigned int i=0; i<types.Halo().size(); ++i)
    for (unsigned int j=0; j<types.Halo()[i].Buffer().size(); j+=4)
      lc.AddParticleToHalo(&types.Halo()[i].Buffer()[j], types.Halo()[i].Buffer()[j+3]);
}