Hi, everyone

I’m not familiar to ASPECT, could someone tell me how to get the data of 
ghost cells?
In the ASPECT, I find that it is implemented through the following 
functions to obtain ghost particles
in ~/aspect/source/particle/world.cc

template <int dim>

std::map<types::subdomain_id,unsigned int>

World<dim>::get_subdomain_id_to_neighbor_map() const

{

}

template <int dim>

   void

   World<dim>::exchange_ghost_particles()
     {

    }

template <int dim>

void

World<dim>::send_recv_particles
(const std::vector<std::vector<std::pair<types::LevelInd,Particle <dim> > > 
> &send_particles,

     std::vector<std::pair<types::LevelInd,
 Particle<dim> > >   &received_particles)

   {

   }

*Presently, I just have a simple data(for example, an object of 
vector<valuetype> on each cell), which is not so complex like the particle, 
how can I realize this this easily?*

 

Thanks very much!


May modify directly in the following codes


   template <int dim>
    std::map<types::subdomain_id, unsigned int>
    World<dim>::get_subdomain_id_to_neighbor_map() const
    {
      std::map<types::subdomain_id, unsigned int> 
subdomain_id_to_neighbor_map;
      const std::set<types::subdomain_id> ghost_owners = 
this->get_triangulation().ghost_owners();
      std::set<types::subdomain_id>::const_iterator ghost_owner = 
ghost_owners.begin();

      for (unsigned int neighbor_id=0; neighbor_id<ghost_owners.size(); 
++neighbor_id,++ghost_owner)
        {
          
subdomain_id_to_neighbor_map.insert(std::make_pair(*ghost_owner,neighbor_id));
        }
      return subdomain_id_to_neighbor_map;
    }




 
    template <int dim>
    void
    World<dim>::exchange_ghost_particles()
    {
      TimerOutput::Scope timer_section(this->get_computing_timer(), 
"Particles: Exchange ghosts");

      // First clear the current ghost_particle information
      ghost_particles.clear();

      const std::map<types::subdomain_id, unsigned int> 
subdomain_to_neighbor_map(get_subdomain_id_to_neighbor_map());

      std::vector<std::vector<std::pair<types::LevelInd, Particle<dim> > > 
> ghost_particles_by_domain(subdomain_to_neighbor_map.size());
      std::vector<std::set<unsigned int> > 
vertex_to_neighbor_subdomain(this->get_triangulation().n_vertices());

      typename DoFHandler<dim>::active_cell_iterator
      cell = this->get_dof_handler().begin_active(),
      endc = this->get_dof_handler().end();
      for (; cell != endc; ++cell)
        {
          if (cell->is_ghost())
            for (unsigned int v=0; v<GeometryInfo<dim>::vertices_per_cell; 
++v)
              
vertex_to_neighbor_subdomain[cell->vertex_index(v)].insert(cell->subdomain_id());
        }

      cell = this->get_triangulation().begin_active();
      for (; cell != endc; ++cell)
        {
          if (!cell->is_ghost())
            {
              std::set<unsigned int> cell_to_neighbor_subdomain;
              for (unsigned int v=0; 
v<GeometryInfo<dim>::vertices_per_cell; ++v)
                {
                  
cell_to_neighbor_subdomain.insert(vertex_to_neighbor_subdomain[cell->vertex_index(v)].begin(),
                                                    
vertex_to_neighbor_subdomain[cell->vertex_index(v)].end());
                }

              if (cell_to_neighbor_subdomain.size() > 0)
                {
                  const std::pair< const typename 
std::multimap<types::LevelInd,Particle <dim> >::iterator,
                        const typename 
std::multimap<types::LevelInd,Particle <dim> >::iterator>
                        particle_range_in_cell = 
particles.equal_range(std::make_pair(cell->level(),cell->index()));
                  for (std::set<types::subdomain_id>::const_iterator 
domain=cell_to_neighbor_subdomain.begin();
                       domain != cell_to_neighbor_subdomain.end(); ++domain)
                    {
                      const unsigned int neighbor_id = 
subdomain_to_neighbor_map.find(*domain)->second;
                      ghost_particles_by_domain[neighbor_id].insert(
                        ghost_particles_by_domain[neighbor_id].end(),
                        particle_range_in_cell.first,
                        particle_range_in_cell.second);
                    }
                }
            }
        }

      std::vector<std::pair<types::LevelInd, Particle<dim> > > 
received_ghost_particles;
      send_recv_particles(ghost_particles_by_domain,
                          received_ghost_particles);

      ghost_particles.insert(received_ghost_particles.begin(),
                             received_ghost_particles.end());
    }
*I'm not clear about the particles.equal_range().*
*The following send_receive particles is mots difficult for me to 
understand*

  template <int dim>
    void
    World<dim>::send_recv_particles(const 
std::vector<std::vector<std::pair<types::LevelInd,Particle <dim> > > > 
&send_particles,
                                    std::vector<std::pair<types::LevelInd, 
Particle<dim> > >                     &received_particles)
    {
      // Determine the communication pattern
      const std::vector<types::subdomain_id> neighbors 
(this->get_triangulation().ghost_owners().begin(),
                                                        
this->get_triangulation().ghost_owners().end());
      const unsigned int n_neighbors = neighbors.size();

      Assert(n_neighbors == send_particles.size(),
             ExcMessage("The particles to send to other processes should be 
sorted into a vector "
                        "containing as many vectors of particles as there 
are neighbor processes. This "
                        "is not the case for an unknown reason. Contact the 
developers if you encounter "
                        "this error."));

      unsigned int n_send_particles = 0;
      for (unsigned int i=0; i<n_neighbors; ++i)
        n_send_particles += send_particles[i].size();

#if DEAL_II_VERSION_GTE(8,5,0)
      const unsigned int cellid_size = sizeof(CellId::binary_type);
      const unsigned int particle_size = 
property_manager->get_particle_size() + integrator->get_data_size() + 
cellid_size;
#else
      const unsigned int particle_size = 
property_manager->get_particle_size() + integrator->get_data_size();
#endif

      // Determine the amount of data we will send to other processors
      std::vector<unsigned int> n_send_data(n_neighbors);
      std::vector<unsigned int> n_recv_data(n_neighbors);

      std::vector<unsigned int> send_offsets(n_neighbors);
      std::vector<unsigned int> recv_offsets(n_neighbors);

      // Allocate space for sending and receiving particle data
      std::vector<char> send_data(n_send_particles * particle_size);
      void *data = static_cast<void *> (&send_data.front());

      for (types::subdomain_id neighbor_id = 0; neighbor_id < n_neighbors; 
++neighbor_id)
        {
          send_offsets[neighbor_id] = reinterpret_cast<std::size_t> (data) 
- reinterpret_cast<std::size_t> (&send_data.front());

          // Copy the particle data into the send array
          typename std::vector<std::pair<types::LevelInd,Particle <dim> > 
>::const_iterator
          cell_particle = send_particles[neighbor_id].begin(),
          end_particle = send_particles[neighbor_id].end();
          for (; cell_particle != end_particle; ++cell_particle)
            {
#if DEAL_II_VERSION_GTE(8,5,0)
              const typename 
parallel::distributed::Triangulation<dim>::cell_iterator cell 
(&this->get_triangulation(),
                                                                            
                cell_particle->first.first,
                                                                            
                cell_particle->first.second);
              const CellId::binary_type cellid = cell->id().template 
to_binary<dim>();
              memcpy(data, &cellid, cellid_size);
              data = static_cast<char *>(data) + cellid_size;
#endif
              cell_particle->second.write_data(data);
              data = integrator->write_data(data, 
cell_particle->second.get_id());
            }
          n_send_data[neighbor_id] = reinterpret_cast<std::size_t> (data) - 
send_offsets[neighbor_id] - reinterpret_cast<std::size_t> 
(&send_data.front());
        }

      // Notify other processors how many particles we will send
      std::vector<MPI_Request> n_requests(2*n_neighbors);
      for (unsigned int i=0; i<n_neighbors; ++i)
        MPI_Irecv(&(n_recv_data[i]), 1, MPI_INT, neighbors[i], 0, 
this->get_mpi_communicator(), &(n_requests[2*i]));
      for (unsigned int i=0; i<n_neighbors; ++i)
        MPI_Isend(&(n_send_data[i]), 1, MPI_INT, neighbors[i], 0, 
this->get_mpi_communicator(), &(n_requests[2*i+1]));
      MPI_Waitall(2*n_neighbors,&n_requests[0],MPI_STATUSES_IGNORE);

      // Determine how many particles and data we will receive
      unsigned int total_recv_data = 0;
      for (unsigned int neighbor_id=0; neighbor_id<n_neighbors; 
++neighbor_id)
        {
          recv_offsets[neighbor_id] = total_recv_data;
          total_recv_data += n_recv_data[neighbor_id];
        }

      // Set up the space for the received particle data
      std::vector<char> recv_data(total_recv_data);

      // Exchange the particle data between domains
      std::vector<MPI_Request> requests(2*n_neighbors);
      unsigned int send_ops = 0;
      unsigned int recv_ops = 0;

      for (unsigned int i=0; i<n_neighbors; ++i)
        if (n_recv_data[i] > 0)
          {
            MPI_Irecv(&(recv_data[recv_offsets[i]]), n_recv_data[i], 
MPI_CHAR, neighbors[i], 1, 
this->get_mpi_communicator(),&(requests[send_ops]));
            send_ops++;
          }

      for (unsigned int i=0; i<n_neighbors; ++i)
        if (n_send_data[i] > 0)
          {
            MPI_Isend(&(send_data[send_offsets[i]]), n_send_data[i], 
MPI_CHAR, neighbors[i], 1, 
this->get_mpi_communicator(),&(requests[send_ops+recv_ops]));
            recv_ops++;
          }
      MPI_Waitall(send_ops+recv_ops,&requests[0],MPI_STATUSES_IGNORE);

      // Put the received particles into the domain if they are in the 
triangulation
      const void *recv_data_it = static_cast<const void *> 
(&recv_data.front());

#if !DEAL_II_VERSION_GTE(8,5,0)
      const std::vector<std::set<typename 
Triangulation<dim>::active_cell_iterator> >
      
vertex_to_cells(GridTools::vertex_to_cell_map(this->get_triangulation()));
      const std::vector<std::vector<Tensor<1,dim> > > 
vertex_to_cell_centers(vertex_to_cell_centers_directions(vertex_to_cells));

      std::vector<unsigned int> neighbor_permutation;
#endif

      while (reinterpret_cast<std::size_t> (recv_data_it) - 
reinterpret_cast<std::size_t> (&recv_data.front()) < total_recv_data)
        {
#if DEAL_II_VERSION_GTE(8,5,0)
          CellId::binary_type binary_cellid;
          memcpy(&binary_cellid, recv_data_it, cellid_size);
          const CellId id(binary_cellid);
          recv_data_it = static_cast<const char *> (recv_data_it) + 
cellid_size;

          const typename 
parallel::distributed::Triangulation<dim>::active_cell_iterator cell = 
id.to_cell(this->get_triangulation());
          const Particle<dim> 
recv_particle(recv_data_it,property_manager->get_particle_size());
          recv_data_it = integrator->read_data(recv_data_it, 
recv_particle.get_id());
#else
          Particle<dim> 
recv_particle(recv_data_it,property_manager->get_particle_size());
          recv_data_it = integrator->read_data(recv_data_it, 
recv_particle.get_id());
          const std::pair<const typename 
parallel::distributed::Triangulation<dim>::active_cell_iterator,
                Point<dim> > current_cell_and_position =
                  GridTools::find_active_cell_around_point<> 
(this->get_mapping(),
                                                              
this->get_triangulation(),
                                                              
recv_particle.get_location());
          typename 
parallel::distributed::Triangulation<dim>::active_cell_iterator cell = 
current_cell_and_position.first;
          
recv_particle.set_reference_location(current_cell_and_position.second);

          // GridTools::find_active_cell_around_point can find a different 
cell than
          // particle_is_in_cell if the particle is very close to the 
boundary
          // therefore, we might get a cell here that does not belong to us.
          // But then at least one of its neighbors belongs to us, and the 
particle
          // is extremely close to the boundary of these two cells. Look in 
the
          // neighbor cells for the particle.
          if (!cell->is_locally_owned())
            {
              const unsigned int closest_vertex = 
get_closest_vertex_of_cell(cell,recv_particle.get_location());
              const unsigned int closest_vertex_index = 
cell->vertex_index(closest_vertex);
              Tensor<1,dim> vertex_to_particle = 
recv_particle.get_location() - cell->vertex(closest_vertex);
              vertex_to_particle /= vertex_to_particle.norm();

              const unsigned int n_neighbor_cells = 
vertex_to_cells[closest_vertex_index].size();

              neighbor_permutation.resize(n_neighbor_cells);
              for (unsigned int i=0; i<n_neighbor_cells; ++i)
                neighbor_permutation[i] = i;

              std::sort(neighbor_permutation.begin(),
                        neighbor_permutation.end(),
                        std_cxx11::bind(&compare_particle_association<dim>,
                                        std_cxx11::_1,
                                        std_cxx11::_2,
                                        std_cxx11::cref(vertex_to_particle),
                                        
std_cxx11::cref(vertex_to_cell_centers[closest_vertex_index])));

              // Search all of the cells adjacent to the closest vertex of 
the previous cell
              // Most likely we will find the particle in them.
              for (unsigned int i=0; i<n_neighbor_cells; ++i)
                {
                  try
                    {
                      typename std::set<typename 
Triangulation<dim>::active_cell_iterator>::const_iterator neighbor_cell = 
vertex_to_cells[closest_vertex_index].begin();
                      std::advance(neighbor_cell,neighbor_permutation[i]);
                      const Point<dim> p_unit = 
this->get_mapping().transform_real_to_unit_cell(*neighbor_cell,
                                                                            
                    recv_particle.get_location());
                      if (GeometryInfo<dim>::is_inside_unit_cell(p_unit))
                        {
                          cell = *neighbor_cell;
                          recv_particle.set_reference_location(p_unit);
                          break;
                        }
                    }
                  catch (typename Mapping<dim>::ExcTransformationFailed &)
                    {}
                }
            }
#endif

          const types::LevelInd found_cell = 
std::make_pair(cell->level(),cell->index());

          received_particles.push_back(std::make_pair(found_cell, 
recv_particle));
        }

      AssertThrow(recv_data_it == &recv_data.back()+1,
                  ExcMessage("The amount of data that was read into new 
particles "
                             "does not match the amount of data sent 
around."));
    }

Thanks so much!

Best 

Jack




>
> Just for reference, Rene Gassmoeller implemented something similar for 
> particles recently: There, we store particles on every locally owned cell, 
> but 
> there are times when one also wants to access particles on ghost cells. 
> This 
> is implemented here: 
>    https://github.com/geodynamics/aspect/pull/1216 
>    https://github.com/geodynamics/aspect/pull/1253 
>
> It's not terribly complicated because one just has to gather the 
> information 
> on cells that are ghosts on some other processor, and then send this 
> information to all relevant processors. 
>
> Best 
>   W. 
>
> -- 
> ------------------------------------------------------------------------ 
> Wolfgang Bangerth          email:                 bang...@colostate.edu 
> <javascript:> 
>                             www: http://www.math.colostate.edu/~bangerth/ 
>
>

-- 
The deal.II project is located at http://www.dealii.org/
For mailing list/forum options, see 
https://groups.google.com/d/forum/dealii?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"deal.II User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to dealii+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to