33 template <
int dim,
int spacedim>
35 pack_particles(std::vector<ParticleIterator<dim, spacedim>> &particles)
37 std::vector<char> buffer;
39 if (particles.empty())
42 buffer.resize(particles.size() *
43 particles.front()->serialized_size_in_bytes());
44 void *current_data = buffer.data();
46 for (
const auto &particle : particles)
48 current_data = particle->write_particle_data_to_memory(current_data);
57 template <
int dim,
int spacedim>
62 , global_number_of_particles(0)
63 , number_of_locally_owned_particles(0)
64 , global_max_particles_per_cell(0)
65 , next_free_particle_index(0)
69 , tria_attached_data_index(
numbers::invalid_unsigned_int)
77 template <
int dim,
int spacedim>
81 const unsigned int n_properties)
82 : triangulation(&triangulation, typeid(*this).name())
83 , mapping(&mapping, typeid(*this).name())
84 , property_pool(
std::make_unique<
PropertyPool<dim, spacedim>>(n_properties))
85 , cells_to_particle_cache(triangulation.n_active_cells(), particles.
end())
86 , global_number_of_particles(0)
87 , number_of_locally_owned_particles(0)
88 , global_max_particles_per_cell(0)
89 , next_free_particle_index(0)
93 , tria_attached_data_index(
numbers::invalid_unsigned_int)
94 , triangulation_cache(
95 std::make_unique<
GridTools::Cache<dim, spacedim>>(triangulation,
105 template <
int dim,
int spacedim>
110 for (
const auto &connection : tria_listeners)
111 connection.disconnect();
116 template <
int dim,
int spacedim>
121 const unsigned int n_properties)
125 triangulation = &new_triangulation;
126 mapping = &new_mapping;
128 reset_particle_container(particles);
131 property_pool = std::make_unique<PropertyPool<dim, spacedim>>(n_properties);
135 triangulation_cache =
136 std::make_unique<GridTools::Cache<dim, spacedim>>(new_triangulation,
139 cells_to_particle_cache.resize(triangulation->n_active_cells(),
142 connect_to_triangulation_signals();
147 template <
int dim,
int spacedim>
152 const unsigned int n_properties =
158 property_pool = std::make_unique<PropertyPool<dim, spacedim>>(
163 number_of_locally_owned_particles =
166 global_max_particles_per_cell =
172 particles.insert(particle_container_owned_end(),
175 particles.insert(particle_container_ghost_end(),
179 for (
auto it = particles.begin(); it != particles.end(); ++it)
180 if (!it->particles.empty())
181 cells_to_particle_cache[it->cell->active_cell_index()] = it;
183 ghost_particles_cache.ghost_particles_by_domain =
190 template <
int dim,
int spacedim>
195 global_number_of_particles = 0;
196 number_of_locally_owned_particles = 0;
197 next_free_particle_index = 0;
198 global_max_particles_per_cell = 0;
203 template <
int dim,
int spacedim>
207 for (
auto &particles_in_cell : particles)
208 for (
auto &particle : particles_in_cell.particles)
210 property_pool->deregister_particle(particle);
212 cells_to_particle_cache.clear();
213 reset_particle_container(particles);
214 if (triangulation !=
nullptr)
215 cells_to_particle_cache.resize(triangulation->n_active_cells(),
220 property_pool->clear();
225 template <
int dim,
int spacedim>
229 property_pool->reserve(n_particles);
234 template <
int dim,
int spacedim>
242 past_the_end_iterator =
243 triangulation !=
nullptr ?
244 triangulation->end() :
247 given_particles.clear();
248 for (
unsigned int i = 0; i < 3; ++i)
249 given_particles.emplace_back(
251 past_the_end_iterator);
254 const_cast<typename particle_container::iterator &
>(owned_particles_end) =
255 ++given_particles.begin();
260 template <
int dim,
int spacedim>
265 bool sort_is_necessary =
false;
267 auto previous = particle_container_owned_begin();
268 for (
auto next = previous; next != particle_container_owned_end(); ++next)
272 previous->cell > next->cell)
274 sort_is_necessary =
true;
280 if (sort_is_necessary)
295 reset_particle_container(sorted_particles);
298 for (
const auto &cell : triangulation->active_cell_iterators())
299 if (!cell->is_artificial())
300 if (cells_to_particle_cache[cell->active_cell_index()] !=
307 typename particle_container::iterator insert_position =
308 cell->is_locally_owned() ? particle_container_owned_end() :
309 --sorted_particles.end();
310 typename particle_container::iterator new_entry =
311 sorted_particles.insert(
312 insert_position,
typename particle_container::value_type());
313 new_entry->cell = cell;
314 new_entry->particles =
315 std::move(cells_to_particle_cache[cell->active_cell_index()]
318 particles = std::move(sorted_particles);
321 cells_to_particle_cache.clear();
322 cells_to_particle_cache.resize(triangulation->n_active_cells(),
324 for (
auto it = particles.begin(); it != particles.end(); ++it)
325 if (!it->particles.empty())
326 cells_to_particle_cache[it->cell->active_cell_index()] = it;
332 particles.front().particles.empty() &&
334 particles.back().particles.empty() &&
336 owned_particles_end->particles.empty(),
343 for (
const auto &it : cells_to_particle_cache)
344 Assert(it != particles.begin() && it != owned_particles_end &&
345 it != --(particles.end()),
350 for (
auto it = particle_container_owned_begin();
351 it != particle_container_owned_end();
356 std::vector<typename particle_container::iterator> verify_cache(
357 triangulation->n_active_cells(), particles.end());
358 for (
auto it = particles.begin(); it != particles.end(); ++it)
359 if (!it->particles.empty())
360 verify_cache[it->cell->active_cell_index()] = it;
362 for (
unsigned int i = 0; i < verify_cache.size(); ++i)
363 Assert(verify_cache[i] == cells_to_particle_cache[i],
369 number_of_locally_owned_particles = 0;
372 for (
const auto &particles_in_cell : particles)
375 particles_in_cell.particles.size();
378 result[0] =
std::max(result[0], n_particles_in_cell);
381 if (n_particles_in_cell > 0 &&
382 particles_in_cell.cell->is_locally_owned())
383 number_of_locally_owned_particles += n_particles_in_cell;
386 for (
const auto &particle : particles_in_cell.particles)
387 result[1] =
std::max(result[1], property_pool->get_id(particle));
390 global_number_of_particles =
392 triangulation->get_mpi_communicator());
394 if (global_number_of_particles == 0)
396 next_free_particle_index = 0;
397 global_max_particles_per_cell = 0;
402 triangulation->get_mpi_communicator(),
405 next_free_particle_index = result[1] + 1;
406 global_max_particles_per_cell = result[0];
412 template <
int dim,
int spacedim>
418 if (cells_to_particle_cache.empty())
421 if (cell->is_artificial() ==
false)
423 return cells_to_particle_cache[cell->active_cell_index()] !=
425 cells_to_particle_cache[cell->active_cell_index()]
431 ExcMessage(
"You can't ask for the particles on an artificial "
432 "cell since we don't know what exists on these "
440 template <
int dim,
int spacedim>
447 ->particles_in_cell(cell);
452 template <
int dim,
int spacedim>
457 const unsigned int active_cell_index = cell->active_cell_index();
459 if (cell->is_artificial() ==
false)
461 if (cells_to_particle_cache[active_cell_index] == particles.end())
463 return boost::make_iterator_range(
469 const typename particle_container::iterator
470 particles_in_current_cell =
471 cells_to_particle_cache[active_cell_index];
472 typename particle_container::iterator particles_in_next_cell =
473 particles_in_current_cell;
474 ++particles_in_next_cell;
475 return boost::make_iterator_range(
482 ExcMessage(
"You can't ask for the particles on an artificial "
483 "cell since we don't know what exists on these "
491 template <
int dim,
int spacedim>
496 auto &particles_on_cell = particle->particles_in_cell->particles;
501 auto handle = particle->get_handle();
503 property_pool->deregister_particle(handle);
508 const auto cell = particle->get_surrounding_cell();
509 const bool owned_cell = cell->is_locally_owned();
511 --number_of_locally_owned_particles;
513 if (particles_on_cell.size() > 1)
515 particles_on_cell[particle->particle_index_within_cell] =
516 std::move(particles_on_cell.back());
517 particles_on_cell.resize(particles_on_cell.size() - 1);
521 particles.erase(particle->particles_in_cell);
522 cells_to_particle_cache[cell->active_cell_index()] = particles.end();
528 template <
int dim,
int spacedim>
532 &particles_to_remove)
540 return a->particles_in_cell->cell > b->particles_in_cell->cell ||
541 (a->particles_in_cell->cell == b->particles_in_cell->cell &&
542 a->particle_index_within_cell > b->particle_index_within_cell);
545 bool particles_are_sorted =
true;
546 auto previous = particles_to_remove.begin();
547 for (
auto next = previous; next != particles_to_remove.end(); ++next)
549 if (check_greater(*previous, *next))
551 particles_are_sorted =
false;
556 if (particles_are_sorted)
559 for (
auto it = particles_to_remove.rbegin();
560 it != particles_to_remove.rend();
562 remove_particle(*it);
566 std::vector<ParticleHandler<dim, spacedim>::particle_iterator>
567 sorted_particles(particles_to_remove);
568 std::sort(sorted_particles.begin(),
569 sorted_particles.end(),
572 for (
const auto &particle : sorted_particles)
573 remove_particle(particle);
576 update_cached_numbers();
581 template <
int dim,
int spacedim>
596 template <
int dim,
int spacedim>
602 const unsigned int active_cell_index = cell->active_cell_index();
603 typename particle_container::iterator &cache =
604 cells_to_particle_cache[active_cell_index];
605 if (cache == particles.end())
607 const typename particle_container::iterator insert_position =
608 cell->is_locally_owned() ? particle_container_owned_end() :
609 particle_container_ghost_end();
610 cache = particles.emplace(
617 cache->particles.push_back(handle);
622 cache->particles.size() - 1);
627 template <
int dim,
int spacedim>
634 Assert(cells_to_particle_cache.size() == triangulation->n_active_cells(),
636 Assert(cell->is_locally_owned(),
637 ExcMessage(
"You tried to insert particles into a cell that is not "
638 "locally owned. This is not supported."));
641 insert_particle(property_pool->register_particle(), cell);
643 data = particle_it->read_particle_data_from_memory(
data);
645 ++number_of_locally_owned_particles;
652 template <
int dim,
int spacedim>
662 Assert(cells_to_particle_cache.size() == triangulation->n_active_cells(),
665 Assert(cell->is_locally_owned(),
666 ExcMessage(
"You tried to insert particles into a cell that is not "
667 "locally owned. This is not supported."));
670 insert_particle(property_pool->register_particle(), cell);
672 particle_it->set_location(position);
673 particle_it->set_reference_location(reference_position);
674 particle_it->set_id(particle_index);
676 if (properties.
size() != 0)
677 particle_it->set_properties(properties);
679 ++number_of_locally_owned_particles;
686 template <
int dim,
int spacedim>
693 reserve(n_locally_owned_particles() + new_particles.size());
694 for (
const auto &cell_and_particle : new_particles)
695 insert_particle(cell_and_particle.second, cell_and_particle.first);
697 update_cached_numbers();
702 template <
int dim,
int spacedim>
709 update_cached_numbers();
710 reserve(n_locally_owned_particles() + positions.size());
717 get_next_free_particle_index();
720#ifdef DEAL_II_WITH_MPI
721 if (
const auto parallel_triangulation =
727 MPI_Scan(&particles_to_add_locally,
730 Utilities::MPI::mpi_type_id_for_type<types::particle_index>,
732 parallel_triangulation->get_mpi_communicator());
734 local_start_index -= particles_to_add_locally;
738 local_start_index += local_next_particle_index;
740 auto point_locations =
744 auto &cells = std::get<0>(point_locations);
745 auto &local_positions = std::get<1>(point_locations);
746 auto &index_map = std::get<2>(point_locations);
747 auto &missing_points = std::get<3>(point_locations);
753 (void)missing_points;
755 for (
unsigned int i = 0; i < cells.size(); ++i)
756 for (
unsigned int p = 0; p < local_positions[i].size(); ++p)
757 insert_particle(positions[index_map[i][p]],
758 local_positions[i][p],
759 local_start_index + index_map[i][p],
762 update_cached_numbers();
767 template <
int dim,
int spacedim>
768 std::map<unsigned int, IndexSet>
772 &global_bounding_boxes,
773 const std::vector<std::vector<double>> &properties,
774 const std::vector<types::particle_index> &ids)
776 if (!properties.empty())
781 for (
const auto &p : properties)
789 const auto comm = triangulation->get_mpi_communicator();
794 const auto n_global_properties =
798 const auto n_particles_per_proc =
802 std::vector<unsigned int> particle_start_indices(n_mpi_processes);
804 unsigned int particle_start_index = get_next_free_particle_index();
805 for (
unsigned int process = 0; process < particle_start_indices.size();
808 particle_start_indices[process] = particle_start_index;
809 particle_start_index += n_particles_per_proc[process];
813 const auto cells_positions_and_index_maps =
816 global_bounding_boxes);
820 const auto &local_cells_containing_particles =
821 std::get<0>(cells_positions_and_index_maps);
825 const auto &local_reference_positions =
826 std::get<1>(cells_positions_and_index_maps);
829 const auto &original_indices_of_local_particles =
830 std::get<2>(cells_positions_and_index_maps);
833 const auto &local_positions = std::get<3>(cells_positions_and_index_maps);
835 const auto &calling_process_indices =
836 std::get<4>(cells_positions_and_index_maps);
839 std::map<unsigned int, std::vector<unsigned int>>
840 original_process_to_local_particle_indices_tmp;
841 for (
unsigned int i_cell = 0;
842 i_cell < local_cells_containing_particles.size();
845 for (
unsigned int i_particle = 0;
846 i_particle < local_positions[i_cell].size();
849 const unsigned int local_id_on_calling_process =
850 original_indices_of_local_particles[i_cell][i_particle];
851 const unsigned int calling_process =
852 calling_process_indices[i_cell][i_particle];
854 original_process_to_local_particle_indices_tmp[calling_process]
855 .push_back(local_id_on_calling_process);
858 std::map<unsigned int, IndexSet> original_process_to_local_particle_indices;
859 for (
auto &process_and_particle_indices :
860 original_process_to_local_particle_indices_tmp)
862 const unsigned int calling_process = process_and_particle_indices.first;
863 original_process_to_local_particle_indices.insert(
864 {calling_process,
IndexSet(n_particles_per_proc[calling_process])});
865 std::sort(process_and_particle_indices.second.begin(),
866 process_and_particle_indices.second.end());
867 original_process_to_local_particle_indices[calling_process].add_indices(
868 process_and_particle_indices.second.begin(),
869 process_and_particle_indices.second.end());
870 original_process_to_local_particle_indices[calling_process].compress();
878 std::map<unsigned int, std::vector<std::vector<double>>>
879 locally_owned_properties_from_other_processes;
886 std::map<unsigned int, std::vector<types::particle_index>>
887 locally_owned_ids_from_other_processes;
889 if (n_global_properties > 0 || !ids.empty())
894 comm, original_process_to_local_particle_indices);
897 if (n_global_properties > 0)
899 std::map<unsigned int, std::vector<std::vector<double>>>
900 non_locally_owned_properties;
902 for (
const auto &it : send_to_cpu)
904 std::vector<std::vector<double>> properties_to_send(
905 it.second.n_elements(),
906 std::vector<double>(n_properties_per_particle()));
907 unsigned int index = 0;
908 for (
const auto el : it.second)
909 properties_to_send[index++] = properties[el];
910 non_locally_owned_properties.insert(
911 {it.first, properties_to_send});
916 locally_owned_properties_from_other_processes =
920 locally_owned_properties_from_other_processes.size(),
921 original_process_to_local_particle_indices.size());
926 std::map<unsigned int, std::vector<types::particle_index>>
927 non_locally_owned_ids;
928 for (
const auto &it : send_to_cpu)
930 std::vector<types::particle_index> ids_to_send(
931 it.second.n_elements());
932 unsigned int index = 0;
933 for (
const auto el : it.second)
934 ids_to_send[index++] = ids[el];
935 non_locally_owned_ids.insert({it.first, ids_to_send});
940 locally_owned_ids_from_other_processes =
944 original_process_to_local_particle_indices.size());
949 for (
unsigned int i_cell = 0;
950 i_cell < local_cells_containing_particles.size();
953 for (
unsigned int i_particle = 0;
954 i_particle < local_positions[i_cell].size();
957 const unsigned int local_id_on_calling_process =
958 original_indices_of_local_particles[i_cell][i_particle];
960 const unsigned int calling_process =
961 calling_process_indices[i_cell][i_particle];
963 const unsigned int index_within_set =
964 original_process_to_local_particle_indices[calling_process]
965 .index_within_set(local_id_on_calling_process);
967 const unsigned int particle_id =
969 local_id_on_calling_process +
970 particle_start_indices[calling_process] :
971 locally_owned_ids_from_other_processes[calling_process]
975 insert_particle(local_positions[i_cell][i_particle],
976 local_reference_positions[i_cell][i_particle],
978 local_cells_containing_particles[i_cell]);
980 if (n_global_properties > 0)
982 particle_it->set_properties(
983 locally_owned_properties_from_other_processes
984 [calling_process][index_within_set]);
989 update_cached_numbers();
991 return original_process_to_local_particle_indices;
996 template <
int dim,
int spacedim>
997 std::map<unsigned int, IndexSet>
1001 &global_bounding_boxes)
1005 std::vector<Point<spacedim>> positions;
1006 std::vector<std::vector<double>> properties;
1007 std::vector<types::particle_index> ids;
1008 positions.resize(particles.size());
1009 ids.resize(particles.size());
1010 if (n_properties_per_particle() > 0)
1011 properties.resize(particles.size(),
1012 std::vector<double>(n_properties_per_particle()));
1015 for (
const auto &p : particles)
1017 positions[i] = p.get_location();
1018 ids[i] = p.get_id();
1019 if (p.has_properties())
1020 properties[i] = {p.get_properties().begin(),
1021 p.get_properties().end()};
1025 return insert_global_particles(positions,
1026 global_bounding_boxes,
1033 template <
int dim,
int spacedim>
1037 return global_number_of_particles;
1042 template <
int dim,
int spacedim>
1046 return global_max_particles_per_cell;
1051 template <
int dim,
int spacedim>
1055 return number_of_locally_owned_particles;
1060 template <
int dim,
int spacedim>
1064 return property_pool->n_properties_per_slot();
1069 template <
int dim,
int spacedim>
1073 return next_free_particle_index;
1078 template <
int dim,
int spacedim>
1083 std::vector<types::particle_index> indices;
1084 indices.reserve(n_locally_owned_particles());
1085 for (
const auto &p : *
this)
1086 indices.push_back(p.get_id());
1087 set.add_indices(indices.begin(), indices.end());
1094 template <
int dim,
int spacedim>
1098 return property_pool->n_slots();
1103 template <
int dim,
int spacedim>
1107 const bool add_to_output_vector)
const
1113 for (
auto it =
begin(); it !=
end(); ++it, ++i)
1115 if (add_to_output_vector)
1116 positions[i] = positions[i] + it->get_location();
1118 positions[i] = it->get_location();
1124 template <
int dim,
int spacedim>
1128 const bool displace_particles)
1134 for (
auto it =
begin(); it !=
end(); ++it, ++i)
1137 if (displace_particles)
1138 location += new_positions[i];
1140 location = new_positions[i];
1142 sort_particles_into_subdomains_and_cells();
1147 template <
int dim,
int spacedim>
1151 const bool displace_particles)
1158 for (
auto &particle : *
this)
1161 function.
vector_value(particle_location, new_position);
1162 if (displace_particles)
1163 for (
unsigned int d = 0; d < spacedim; ++d)
1164 particle_location[d] += new_position[d];
1166 for (
unsigned int d = 0; d < spacedim; ++d)
1167 particle_location[d] = new_position[d];
1169 sort_particles_into_subdomains_and_cells();
1174 template <
int dim,
int spacedim>
1178 return *property_pool;
1196 compare_particle_association(
1197 const unsigned int a,
1198 const unsigned int b,
1202 const double scalar_product_a = center_directions[a] * particle_direction;
1203 const double scalar_product_b = center_directions[b] * particle_direction;
1208 return (scalar_product_a > scalar_product_b);
1214 template <
int dim,
int spacedim>
1219 Assert(cells_to_particle_cache.size() == triangulation->n_active_cells(),
1230 std::vector<particle_iterator> particles_out_of_cell;
1235 particles_out_of_cell.reserve(n_locally_owned_particles() / 4);
1242 struct StageOne_CopyData
1244 std::vector<particle_iterator> local_particles_out_of_cell;
1246 StageOne_CopyData(
const unsigned int size)
1248 local_particles_out_of_cell.reserve(
size);
1255 struct StageOne_ScratchData
1257 std::vector<Point<spacedim>> real_locations;
1258 std::vector<Point<dim>> reference_locations;
1259 StageOne_ScratchData(
const unsigned int size)
1261 real_locations.reserve(
size);
1262 reference_locations.reserve(
size);
1266 const auto stage_one_worker =
1269 StageOne_ScratchData &scratch,
1270 StageOne_CopyData ©) {
1276 copy.local_particles_out_of_cell.clear();
1278 if (cell->is_locally_owned() ==
false)
1283 scratch.real_locations.
clear();
1285 const unsigned int n_pic = n_particles_in_cell(cell);
1286 auto pic = particles_in_cell(cell);
1288 for (
const auto &particle : pic)
1289 scratch.real_locations.push_back(particle.get_location());
1291 scratch.reference_locations.resize(n_pic);
1292 mapping->transform_points_real_to_unit_cell(
1293 cell, scratch.real_locations, scratch.reference_locations);
1295 auto particle = pic.
begin();
1296 for (
const auto &p_unit : scratch.reference_locations)
1299 cell->reference_cell().contains_point(p_unit,
1300 tolerance_inside_cell))
1301 particle->set_reference_location(p_unit);
1303 copy.local_particles_out_of_cell.push_back(particle);
1309 const auto stage_one_copier = [&](
const StageOne_CopyData ©) {
1310 particles_out_of_cell.insert(particles_out_of_cell.end(),
1311 copy.local_particles_out_of_cell.begin(),
1312 copy.local_particles_out_of_cell.end());
1315 triangulation->end(),
1318 StageOne_ScratchData(global_max_particles_per_cell),
1319 StageOne_CopyData(global_max_particles_per_cell));
1327 std::map<types::subdomain_id, std::vector<particle_iterator>>
1331 std::vector<typename Triangulation<dim, spacedim>::active_cell_iterator>>
1339 std::set<types::subdomain_id> ghost_owners;
1340 if (
const auto parallel_triangulation =
1343 ghost_owners = parallel_triangulation->ghost_owners();
1348 for (
const auto &ghost_owner : ghost_owners)
1349 moved_particles[ghost_owner].reserve(particles_out_of_cell.size() / 4);
1350 for (
const auto &ghost_owner : ghost_owners)
1351 moved_cells[ghost_owner].reserve(particles_out_of_cell.size() / 4);
1356 std::set<typename Triangulation<dim, spacedim>::active_cell_iterator>>
1357 &vertex_to_cells = triangulation_cache->get_vertex_to_cell_map();
1361 const std::vector<std::vector<Tensor<1, spacedim>>>
1362 &vertex_to_cell_centers =
1363 triangulation_cache->get_vertex_to_cell_centers_directions();
1372 struct StageTwo_CopyData
1380 struct StageTwo_ScratchData
1382 std::vector<Point<spacedim>> real_locations;
1383 std::vector<Point<dim>> reference_locations;
1384 std::vector<unsigned int> search_order;
1386 StageTwo_ScratchData()
1393 struct StageTwo_QueuedData
1399 std::vector<StageTwo_QueuedData> data_queue;
1401 data_queue.reserve(n_locally_owned_particles() / 4);
1403 const auto stage_two_worker =
1405 const typename std::vector<particle_iterator>::iterator out_particle,
1406 StageTwo_ScratchData &scratch,
1407 StageTwo_CopyData ©) {
1411 copy.current_cell = (*out_particle)->get_surrounding_cell();
1412 copy.found_cell =
false;
1414 scratch.real_locations[0] = (*out_particle)->get_location();
1418 const unsigned int closest_vertex =
1419 GridTools::find_closest_vertex_of_cell<dim, spacedim>(
1420 copy.current_cell, (*out_particle)->get_location(), *mapping);
1421 const unsigned int closest_vertex_index =
1422 copy.current_cell->vertex_index(closest_vertex);
1424 const auto &candidate_cells = vertex_to_cells[closest_vertex_index];
1425 const unsigned int n_candidate_cells = candidate_cells.size();
1429 scratch.search_order.resize(n_candidate_cells);
1430 for (
unsigned int i = 0; i < n_candidate_cells; ++i)
1431 scratch.search_order[i] = i;
1437 (*out_particle)->get_location() -
1438 copy.current_cell->vertex(closest_vertex);
1443 1e4 * std::numeric_limits<double>::epsilon() *
1444 std::numeric_limits<double>::epsilon() *
1445 vertex_to_cell_centers[closest_vertex_index][0].norm_square())
1447 vertex_to_particle /= vertex_to_particle.
norm();
1448 const auto &vertex_to_cells_center =
1449 vertex_to_cell_centers[closest_vertex_index];
1451 std::sort(scratch.search_order.begin(),
1452 scratch.search_order.end(),
1453 [&vertex_to_particle,
1454 &vertex_to_cells_center](
const unsigned int a,
1455 const unsigned int b) {
1456 return compare_particle_association<spacedim>(
1457 a, b, vertex_to_particle, vertex_to_cells_center);
1463 for (
unsigned int i = 0; i < n_candidate_cells; ++i)
1467 const_iterator candidate_cell = candidate_cells.begin();
1469 std::advance(candidate_cell, scratch.search_order[i]);
1475 if ((*candidate_cell)->is_artificial())
1478 mapping->transform_points_real_to_unit_cell(
1480 scratch.real_locations,
1481 scratch.reference_locations);
1484 scratch.reference_locations[0], tolerance_inside_cell))
1486 copy.current_cell = *candidate_cell;
1487 copy.found_cell =
true;
1495 if (!copy.found_cell)
1502#if defined(DEAL_II_WITH_BOOST_BUNDLED) || \
1503 !(defined(__clang_major__) && __clang_major__ >= 16) || \
1504 BOOST_VERSION >= 108100
1505 std::vector<std::pair<Point<spacedim>,
unsigned int>>
1506 closest_vertex_in_domain;
1507 triangulation_cache->get_used_vertices_rtree().query(
1508 boost::geometry::index::nearest((*out_particle)->get_location(),
1510 std::back_inserter(closest_vertex_in_domain));
1514 const unsigned int closest_vertex_index_in_domain =
1515 closest_vertex_in_domain[0].second;
1517 const unsigned int closest_vertex_index_in_domain =
1520 (*out_particle)->get_location());
1525 for (
const auto &cell :
1526 vertex_to_cells[closest_vertex_index_in_domain])
1530 if (cell->is_artificial())
1533 mapping->transform_points_real_to_unit_cell(
1534 cell, scratch.real_locations, scratch.reference_locations);
1537 scratch.reference_locations[0], tolerance_inside_cell))
1539 copy.current_cell = cell;
1540 copy.found_cell =
true;
1545 copy.out_particle = (*out_particle);
1546 copy.reference_location = scratch.reference_locations[0];
1549 const auto stage_two_copier = [&](
const StageTwo_CopyData ©) {
1550 auto local_out_particle = copy.out_particle;
1552 if (!copy.found_cell)
1557 signals.particle_lost(copy.out_particle,
1558 copy.out_particle->get_surrounding_cell());
1563 local_out_particle->set_reference_location(copy.reference_location);
1567 StageTwo_QueuedData data_entry;
1568 data_entry.current_cell = copy.current_cell;
1569 data_entry.out_particle = copy.out_particle;
1570 data_queue.push_back(data_entry);
1574 particles_out_of_cell.end(),
1577 StageTwo_ScratchData(),
1578 StageTwo_CopyData(),
1583 for (
const auto &data_entry : data_queue)
1587 if (data_entry.current_cell->is_locally_owned())
1590 data_entry.out_particle->particles_in_cell->particles
1591 [data_entry.out_particle->particle_index_within_cell];
1594 const auto old_value = old;
1598 insert_particle(old_value, data_entry.current_cell);
1602 moved_particles[data_entry.current_cell->subdomain_id()]
1603 .push_back(data_entry.out_particle);
1604 moved_cells[data_entry.current_cell->subdomain_id()].push_back(
1605 data_entry.current_cell);
1611#ifdef DEAL_II_WITH_MPI
1612 if (
const auto parallel_triangulation =
1617 parallel_triangulation->get_mpi_communicator()) > 1)
1618 send_recv_particles(moved_particles, moved_cells);
1623 remove_particles(particles_out_of_cell);
1626 std::vector<typename PropertyPool<dim, spacedim>::Handle> unsorted_handles;
1627 unsorted_handles.reserve(property_pool->n_registered_slots());
1630 for (
auto &particles_in_cell : particles)
1631 for (
auto &particle : particles_in_cell.particles)
1633 unsorted_handles.push_back(particle);
1634 particle = sorted_handle++;
1637 property_pool->sort_memory_slots(unsorted_handles);
1643 template <
int dim,
int spacedim>
1646 const bool enable_cache)
1649 const auto parallel_triangulation =
1652 if (parallel_triangulation !=
nullptr)
1655 parallel_triangulation->get_mpi_communicator()) == 1)
1661#ifndef DEAL_II_WITH_MPI
1665 for (
const auto &cell : triangulation->active_cell_iterators())
1666 if (cell->is_ghost() &&
1667 cells_to_particle_cache[cell->active_cell_index()] != particles.end())
1669 Assert(cells_to_particle_cache[cell->active_cell_index()]->cell ==
1673 for (
auto &ghost_particle :
1674 cells_to_particle_cache[cell->active_cell_index()]->particles)
1675 property_pool->deregister_particle(ghost_particle);
1678 particles.erase(cells_to_particle_cache[cell->active_cell_index()]);
1679 cells_to_particle_cache[cell->active_cell_index()] = particles.end();
1683 ghost_particles_cache.ghost_particles_by_domain.clear();
1684 ghost_particles_cache.valid =
false;
1691 const std::map<unsigned int, std::set<types::subdomain_id>>
1692 &vertices_with_ghost_neighbors =
1693 triangulation_cache->get_vertices_with_ghost_neighbors();
1695 const std::set<types::subdomain_id> ghost_owners =
1696 parallel_triangulation->ghost_owners();
1697 for (
const auto ghost_owner : ghost_owners)
1698 ghost_particles_cache.ghost_particles_by_domain[ghost_owner].reserve(
1699 n_locally_owned_particles() / 4);
1701 const std::vector<std::set<unsigned int>> vertex_to_neighbor_subdomain =
1702 triangulation_cache->get_vertex_to_neighbor_subdomain();
1704 for (
const auto &cell : triangulation->active_cell_iterators())
1706 if (cell->is_locally_owned())
1708 std::set<unsigned int> cell_to_neighbor_subdomain;
1709 for (
const unsigned int v : cell->vertex_indices())
1711 const auto vertex_ghost_neighbors =
1712 vertices_with_ghost_neighbors.find(cell->vertex_index(v));
1713 if (vertex_ghost_neighbors !=
1714 vertices_with_ghost_neighbors.end())
1716 cell_to_neighbor_subdomain.insert(
1717 vertex_ghost_neighbors->second.begin(),
1718 vertex_ghost_neighbors->second.end());
1722 if (cell_to_neighbor_subdomain.size() > 0)
1725 particles_in_cell(cell);
1727 for (
const auto domain : cell_to_neighbor_subdomain)
1729 for (
typename particle_iterator_range::iterator particle =
1730 particle_range.begin();
1731 particle != particle_range.end();
1733 ghost_particles_cache.ghost_particles_by_domain[domain]
1734 .push_back(particle);
1740 send_recv_particles(
1741 ghost_particles_cache.ghost_particles_by_domain,
1752 template <
int dim,
int spacedim>
1757 const auto parallel_triangulation =
1760 if (parallel_triangulation ==
nullptr ||
1762 parallel_triangulation->get_mpi_communicator()) == 1)
1768#ifdef DEAL_II_WITH_MPI
1771 Assert(ghost_particles_cache.valid,
1773 "Ghost particles cannot be updated if they first have not been "
1774 "exchanged at least once with the cache enabled"));
1777 send_recv_particles_properties_and_location(
1778 ghost_particles_cache.ghost_particles_by_domain);
1784#ifdef DEAL_II_WITH_MPI
1785 template <
int dim,
int spacedim>
1794 const bool build_cache)
1797 Assert(cells_to_particle_cache.size() == triangulation->n_active_cells(),
1800 ghost_particles_cache.valid = build_cache;
1802 const auto parallel_triangulation =
1805 Assert(parallel_triangulation,
1806 ExcMessage(
"This function is only implemented for "
1807 "parallel::TriangulationBase objects."));
1810 const std::set<types::subdomain_id> ghost_owners =
1811 parallel_triangulation->ghost_owners();
1812 const std::vector<types::subdomain_id> neighbors(ghost_owners.begin(),
1813 ghost_owners.end());
1814 const unsigned int n_neighbors = neighbors.size();
1816 if (send_cells.size() != 0)
1822 particles_to_send.end(),
1827 for (
auto send_particles = particles_to_send.begin();
1828 send_particles != particles_to_send.end();
1830 Assert(ghost_owners.find(send_particles->first) != ghost_owners.end(),
1833 std::size_t n_send_particles = 0;
1834 for (
auto send_particles = particles_to_send.begin();
1835 send_particles != particles_to_send.end();
1837 n_send_particles += send_particles->second.size();
1843 std::vector<unsigned int> n_send_data(n_neighbors, 0);
1844 std::vector<unsigned int> send_offsets(n_neighbors, 0);
1845 std::vector<char> send_data;
1850 const unsigned int individual_particle_data_size =
1852 (size_callback ? size_callback() : 0);
1854 const unsigned int individual_total_particle_data_size =
1855 individual_particle_data_size + cellid_size;
1860 if (n_send_particles > 0)
1863 send_data.resize(n_send_particles *
1864 individual_total_particle_data_size);
1866 void *
data =
static_cast<void *
>(&send_data.front());
1869 for (
unsigned int i = 0; i < n_neighbors; ++i)
1871 send_offsets[i] =
reinterpret_cast<std::size_t
>(
data) -
1872 reinterpret_cast<std::size_t
>(&send_data.front());
1874 const unsigned int n_particles_to_send =
1875 particles_to_send.at(neighbors[i]).size();
1877 Assert(
static_cast<std::size_t
>(n_particles_to_send) *
1878 individual_total_particle_data_size ==
1879 static_cast<std::size_t
>(
1880 n_particles_to_send *
1881 individual_total_particle_data_size),
1882 ExcMessage(
"Overflow when trying to send particle "
1885 for (
unsigned int j = 0; j < n_particles_to_send; ++j)
1891 if (send_cells.empty())
1892 cell = particles_to_send.at(neighbors[i])[j]
1893 ->get_surrounding_cell();
1895 cell = send_cells.at(neighbors[i])[j];
1898 cell->id().template to_binary<dim>();
1899 memcpy(
data, &cellid, cellid_size);
1900 data =
static_cast<char *
>(
data) + cellid_size;
1902 data = particles_to_send.at(neighbors[i])[j]
1903 ->write_particle_data_to_memory(
data);
1906 store_callback(particles_to_send.at(neighbors[i])[j],
data);
1908 n_send_data[i] = n_particles_to_send;
1913 std::vector<unsigned int> n_recv_data(n_neighbors);
1914 std::vector<unsigned int> recv_offsets(n_neighbors);
1920 std::vector<MPI_Request> n_requests(2 * n_neighbors);
1921 for (
unsigned int i = 0; i < n_neighbors; ++i)
1924 MPI_Irecv(&(n_recv_data[i]),
1929 parallel_triangulation->get_mpi_communicator(),
1930 &(n_requests[2 * i]));
1933 for (
unsigned int i = 0; i < n_neighbors; ++i)
1936 MPI_Isend(&(n_send_data[i]),
1941 parallel_triangulation->get_mpi_communicator(),
1942 &(n_requests[2 * i + 1]));
1946 MPI_Waitall(2 * n_neighbors, n_requests.data(), MPI_STATUSES_IGNORE);
1951 unsigned int total_recv_data = 0;
1952 for (
unsigned int neighbor_id = 0; neighbor_id < n_neighbors; ++neighbor_id)
1954 recv_offsets[neighbor_id] = total_recv_data;
1956 n_recv_data[neighbor_id] * individual_total_particle_data_size;
1960 std::vector<char> recv_data(total_recv_data);
1964 std::vector<MPI_Request> requests(2 * n_neighbors);
1965 unsigned int send_ops = 0;
1966 unsigned int recv_ops = 0;
1971 for (
unsigned int i = 0; i < n_neighbors; ++i)
1972 if (n_recv_data[i] > 0)
1975 MPI_Irecv(&(recv_data[recv_offsets[i]]),
1976 n_recv_data[i] * individual_total_particle_data_size,
1980 parallel_triangulation->get_mpi_communicator(),
1981 &(requests[send_ops]));
1986 for (
unsigned int i = 0; i < n_neighbors; ++i)
1987 if (n_send_data[i] > 0)
1990 MPI_Isend(&(send_data[send_offsets[i]]),
1991 n_send_data[i] * individual_total_particle_data_size,
1995 parallel_triangulation->get_mpi_communicator(),
1996 &(requests[send_ops + recv_ops]));
2001 MPI_Waitall(send_ops + recv_ops, requests.data(), MPI_STATUSES_IGNORE);
2007 const void *recv_data_it =
static_cast<const void *
>(recv_data.data());
2010 auto &ghost_particles_iterators =
2011 ghost_particles_cache.ghost_particles_iterators;
2015 ghost_particles_iterators.clear();
2017 auto &send_pointers_particles = ghost_particles_cache.send_pointers;
2018 send_pointers_particles.assign(n_neighbors + 1, 0);
2020 for (
unsigned int i = 0; i < n_neighbors; ++i)
2021 send_pointers_particles[i + 1] =
2022 send_pointers_particles[i] +
2023 n_send_data[i] * individual_particle_data_size;
2025 auto &recv_pointers_particles = ghost_particles_cache.recv_pointers;
2026 recv_pointers_particles.assign(n_neighbors + 1, 0);
2028 for (
unsigned int i = 0; i < n_neighbors; ++i)
2029 recv_pointers_particles[i + 1] =
2030 recv_pointers_particles[i] +
2031 n_recv_data[i] * individual_particle_data_size;
2033 ghost_particles_cache.neighbors = neighbors;
2035 ghost_particles_cache.send_data.resize(
2036 ghost_particles_cache.send_pointers.back());
2037 ghost_particles_cache.recv_data.resize(
2038 ghost_particles_cache.recv_pointers.back());
2041 while (
reinterpret_cast<std::size_t
>(recv_data_it) -
2042 reinterpret_cast<std::size_t
>(recv_data.data()) <
2046 memcpy(&binary_cellid, recv_data_it, cellid_size);
2047 const CellId id(binary_cellid);
2048 recv_data_it =
static_cast<const char *
>(recv_data_it) + cellid_size;
2051 triangulation->create_cell_iterator(
id);
2053 insert_particle(property_pool->register_particle(), cell);
2054 const typename particle_container::iterator &cache =
2055 cells_to_particle_cache[cell->active_cell_index()];
2060 cache->particles.size() - 1);
2063 particle_it->read_particle_data_from_memory(recv_data_it);
2066 recv_data_it = load_callback(particle_it, recv_data_it);
2069 ghost_particles_iterators.push_back(particle_it);
2072 AssertThrow(recv_data_it == recv_data.data() + recv_data.size(),
2074 "The amount of data that was read into new particles "
2075 "does not match the amount of data sent around."));
2081#ifdef DEAL_II_WITH_MPI
2082 template <
int dim,
int spacedim>
2088 const auto parallel_triangulation =
2092 parallel_triangulation,
2094 "This function is only implemented for parallel::TriangulationBase "
2097 const auto &neighbors = ghost_particles_cache.neighbors;
2098 const auto &send_pointers = ghost_particles_cache.send_pointers;
2099 const auto &recv_pointers = ghost_particles_cache.recv_pointers;
2101 std::vector<char> &send_data = ghost_particles_cache.send_data;
2104 if (send_pointers.back() > 0)
2106 void *
data =
static_cast<void *
>(&send_data.front());
2109 for (
const auto i : neighbors)
2110 for (
const auto &p : particles_to_send.at(i))
2112 data = p->write_particle_data_to_memory(
data);
2118 std::vector<char> &recv_data = ghost_particles_cache.recv_data;
2122 std::vector<MPI_Request> requests(2 * neighbors.size());
2123 unsigned int send_ops = 0;
2124 unsigned int recv_ops = 0;
2129 for (
unsigned int i = 0; i < neighbors.size(); ++i)
2130 if ((recv_pointers[i + 1] - recv_pointers[i]) > 0)
2133 MPI_Irecv(recv_data.data() + recv_pointers[i],
2134 recv_pointers[i + 1] - recv_pointers[i],
2138 parallel_triangulation->get_mpi_communicator(),
2139 &(requests[send_ops]));
2144 for (
unsigned int i = 0; i < neighbors.size(); ++i)
2145 if ((send_pointers[i + 1] - send_pointers[i]) > 0)
2148 MPI_Isend(send_data.data() + send_pointers[i],
2149 send_pointers[i + 1] - send_pointers[i],
2153 parallel_triangulation->get_mpi_communicator(),
2154 &(requests[send_ops + recv_ops]));
2159 MPI_Waitall(send_ops + recv_ops, requests.data(), MPI_STATUSES_IGNORE);
2165 const void *recv_data_it =
static_cast<const void *
>(recv_data.data());
2168 auto &ghost_particles_iterators =
2169 ghost_particles_cache.ghost_particles_iterators;
2171 for (
auto &recv_particle : ghost_particles_iterators)
2176 recv_particle->read_particle_data_from_memory(recv_data_it);
2178 Assert(recv_particle->particles_in_cell->cell->is_ghost(),
2182 recv_data_it = load_callback(
2185 recv_particle->particle_index_within_cell),
2189 AssertThrow(recv_data_it == recv_data.data() + recv_data.size(),
2191 "The amount of data that was read into new particles "
2192 "does not match the amount of data sent around."));
2196 template <
int dim,
int spacedim>
2199 const std::function<std::size_t()> &size_callb,
2204 size_callback = size_callb;
2205 store_callback = store_callb;
2206 load_callback = load_callb;
2210 template <
int dim,
int spacedim>
2215 for (
const auto &connection : tria_listeners)
2216 connection.disconnect();
2218 tria_listeners.clear();
2220 tria_listeners.push_back(triangulation->signals.create.connect([&]() {
2221 this->initialize(*(this->triangulation),
2223 this->property_pool->n_properties_per_slot());
2226 this->tria_listeners.push_back(
2227 this->triangulation->signals.clear.connect([&]() { this->clear(); }));
2231 *
>(&(*triangulation)) !=
nullptr)
2233 tria_listeners.push_back(
2234 triangulation->signals.post_distributed_refinement.connect(
2235 [&]() { this->post_mesh_change_action(); }));
2236 tria_listeners.push_back(
2237 triangulation->signals.post_distributed_repartition.connect(
2238 [&]() { this->post_mesh_change_action(); }));
2239 tria_listeners.push_back(
2240 triangulation->signals.post_distributed_load.connect(
2241 [&]() { this->post_mesh_change_action(); }));
2245 tria_listeners.push_back(triangulation->signals.post_refinement.connect(
2246 [&]() { this->post_mesh_change_action(); }));
2252 template <
int dim,
int spacedim>
2258 const bool distributed_triangulation =
2261 &(*triangulation)) !=
nullptr;
2262 (void)distributed_triangulation;
2265 distributed_triangulation || number_of_locally_owned_particles == 0,
2267 "Mesh refinement in a non-distributed triangulation is not supported "
2268 "by the ParticleHandler class. Either insert particles after mesh "
2269 "creation, or use a distributed triangulation."));
2273 if (number_of_locally_owned_particles == 0)
2274 cells_to_particle_cache.resize(triangulation->n_active_cells(),
2280 template <
int dim,
int spacedim>
2284 register_data_attach();
2289 template <
int dim,
int spacedim>
2293 register_data_attach();
2298 template <
int dim,
int spacedim>
2302 const auto callback_function =
2306 return this->pack_callback(cell_iterator, cell_status);
2309 tria_attached_data_index =
2311 ->register_data_attach(callback_function,
2317 template <
int dim,
int spacedim>
2321 const bool serialization =
false;
2322 notify_ready_to_unpack(serialization);
2327 template <
int dim,
int spacedim>
2331 const bool serialization =
true;
2332 notify_ready_to_unpack(serialization);
2336 template <
int dim,
int spacedim>
2339 const bool serialization)
2349 register_data_attach();
2354 const auto callback_function =
2358 const boost::iterator_range<std::vector<char>::const_iterator>
2360 this->unpack_callback(cell_iterator, cell_status, range_iterator);
2364 ->notify_ready_to_unpack(tria_attached_data_index, callback_function);
2368 update_cached_numbers();
2374 template <
int dim,
int spacedim>
2380 std::vector<particle_iterator> stored_particles_on_cell;
2389 const unsigned int n_particles = n_particles_in_cell(cell);
2390 stored_particles_on_cell.reserve(n_particles);
2392 for (
unsigned int i = 0; i < n_particles; ++i)
2394 cells_to_particle_cache[cell->active_cell_index()],
2404 for (
const auto &child : cell->child_iterators())
2406 const unsigned int n_particles = n_particles_in_cell(child);
2408 stored_particles_on_cell.reserve(
2409 stored_particles_on_cell.size() + n_particles);
2411 const typename particle_container::iterator &cache =
2412 cells_to_particle_cache[child->active_cell_index()];
2413 for (
unsigned int i = 0; i < n_particles; ++i)
2414 stored_particles_on_cell.push_back(
2425 return pack_particles(stored_particles_on_cell);
2430 template <
int dim,
int spacedim>
2435 const boost::iterator_range<std::vector<char>::const_iterator> &data_range)
2437 if (data_range.begin() == data_range.end())
2440 const auto cell_to_store_particles =
2444 if (data_range.begin() != data_range.end())
2446 const void *
data =
static_cast<const void *
>(&(*data_range.begin()));
2447 const void *
end =
static_cast<const void *
>(
2448 &(*data_range.begin()) + (data_range.end() - data_range.begin()));
2452 const void *old_data =
data;
2453 const auto x = insert_particle(
data, cell_to_store_particles);
2457 const void *new_data =
data;
2462 x->serialized_size_in_bytes());
2467 "The particle data could not be deserialized successfully. "
2468 "Check that when deserializing the particles you expect "
2469 "the same number of properties that were serialized."));
2472 auto loaded_particles_on_cell = particles_in_cell(cell_to_store_particles);
2487 for (
auto &particle : loaded_particles_on_cell)
2490 mapping->transform_real_to_unit_cell(cell_to_store_particles,
2491 particle.get_location());
2492 particle.set_reference_location(p_unit);
2501 typename particle_container::iterator &cache =
2502 cells_to_particle_cache[cell_to_store_particles
2503 ->active_cell_index()];
2510 auto particle = loaded_particles_on_cell.begin();
2511 for (
unsigned int i = 0; i < cache->particles.size();)
2513 bool found_new_cell =
false;
2515 for (
const auto &child : cell->child_iterators())
2522 mapping->transform_real_to_unit_cell(
2523 child, particle->get_location());
2524 if (cell->reference_cell().contains_point(
2525 p_unit, tolerance_inside_cell))
2527 found_new_cell =
true;
2528 particle->set_reference_location(p_unit);
2532 if (child != cell_to_store_particles)
2535 insert_particle(cache->particles[i], child);
2537 cache->particles[i] = cache->particles.back();
2538 cache->particles.pop_back();
2555 if (found_new_cell ==
false)
2564 signals.particle_lost(particle,
2565 particle->get_surrounding_cell());
2566 if (cache->particles[i] !=
2568 property_pool->deregister_particle(cache->particles[i]);
2569 cache->particles[i] = cache->particles.back();
2570 cache->particles.pop_back();
2574 if (cache->particles.empty())
2576 particles.erase(cache);
2577 cache = particles.end();
2589#include "particles/particle_handler.inst"
* x_component_mask set(0, true)
@ children_will_be_coarsened
std::array< std::uint64_t, 3 > binary_type
const unsigned int n_components
virtual void vector_value(const Point< dim > &p, Vector< RangeNumberType > &values) const
Abstract base class for mapping classes.
static unsigned int n_threads()
void register_additional_store_load_functions(const std::function< std::size_t()> &size_callback, const std::function< void *(const particle_iterator &, void *)> &store_callback, const std::function< const void *(const particle_iterator &, const void *)> &load_callback)
void exchange_ghost_particles(const bool enable_ghost_cache=false)
unsigned int tria_attached_data_index
types::particle_index n_global_particles() const
unsigned int global_max_particles_per_cell
void unpack_after_coarsening_and_refinement()
void register_data_attach()
internal::GhostParticlePartitioner< dim, spacedim > ghost_particles_cache
particle_container::iterator particle_container_ghost_begin() const
void prepare_for_serialization()
unsigned int n_properties_per_particle() const
types::particle_index global_number_of_particles
particle_container::iterator particle_container_owned_end() const
void update_cached_numbers()
void prepare_for_coarsening_and_refinement()
particle_container::iterator particle_container_ghost_end() const
boost::iterator_range< particle_iterator > particle_iterator_range
void post_mesh_change_action()
void send_recv_particles(const std::map< types::subdomain_id, std::vector< particle_iterator > > &particles_to_send, const std::map< types::subdomain_id, std::vector< typename Triangulation< dim, spacedim >::active_cell_iterator > > &new_cells_for_particles=std::map< types::subdomain_id, std::vector< typename Triangulation< dim, spacedim >::active_cell_iterator > >(), const bool enable_cache=false)
ObserverPointer< const Mapping< dim, spacedim >, ParticleHandler< dim, spacedim > > mapping
void send_recv_particles_properties_and_location(const std::map< types::subdomain_id, std::vector< particle_iterator > > &particles_to_send)
void get_particle_positions(VectorType &output_vector, const bool add_to_output_vector=false) const
types::particle_index number_of_locally_owned_particles
PropertyPool< dim, spacedim > & get_property_pool() const
void initialize(const Triangulation< dim, spacedim > &tria, const Mapping< dim, spacedim > &mapping, const unsigned int n_properties=0)
std::unique_ptr< PropertyPool< dim, spacedim > > property_pool
types::particle_index get_max_local_particle_index() const
void reserve(const std::size_t n_particles)
std::map< unsigned int, IndexSet > insert_global_particles(const std::vector< Point< spacedim > > &positions, const std::vector< std::vector< BoundingBox< spacedim > > > &global_bounding_boxes, const std::vector< std::vector< double > > &properties={}, const std::vector< types::particle_index > &ids={})
void notify_ready_to_unpack(const bool serialization)
void connect_to_triangulation_signals()
std::enable_if_t< std::is_convertible_v< VectorType *, Function< spacedim > * >==false > set_particle_positions(const VectorType &input_vector, const bool displace_particles=true)
std::vector< char > pack_callback(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const CellStatus status) const
void insert_particles(const std::multimap< typename Triangulation< dim, spacedim >::active_cell_iterator, Particle< dim, spacedim > > &particles)
types::particle_index next_free_particle_index
void remove_particle(const particle_iterator &particle)
types::particle_index n_locally_owned_particles() const
void reset_particle_container(particle_container &particles)
types::particle_index n_particles_in_cell(const typename Triangulation< dim, spacedim >::active_cell_iterator &cell) const
void update_ghost_particles()
typename ParticleAccessor< dim, spacedim >::particle_container particle_container
ObserverPointer< const Triangulation< dim, spacedim >, ParticleHandler< dim, spacedim > > triangulation
particle_iterator_range particles_in_cell(const typename Triangulation< dim, spacedim >::active_cell_iterator &cell)
particle_iterator insert_particle(const Particle< dim, spacedim > &particle, const typename Triangulation< dim, spacedim >::active_cell_iterator &cell)
void sort_particles_into_subdomains_and_cells()
void remove_particles(const std::vector< particle_iterator > &particles)
types::particle_index n_global_max_particles_per_cell() const
particle_container::iterator particle_container_owned_begin() const
void unpack_callback(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const CellStatus status, const boost::iterator_range< std::vector< char >::const_iterator > &data_range)
virtual ~ParticleHandler()
void copy_from(const ParticleHandler< dim, spacedim > &particle_handler)
types::particle_index get_next_free_particle_index() const
particle_container particles
IndexSet locally_owned_particle_ids() const
void set_property_pool(PropertyPool< dim, spacedim > &property_pool)
const Point< dim > & get_reference_location() const
const Point< spacedim > & get_location() const
std::size_t serialized_size_in_bytes() const
types::particle_index get_id() const
ArrayView< double > get_properties()
numbers::NumberTraits< Number >::real_type norm() const
constexpr numbers::NumberTraits< Number >::real_type norm_square() const
IteratorState::IteratorStates state() const
cell_iterator begin(const unsigned int level=0) const
#define DEAL_II_NAMESPACE_OPEN
constexpr bool running_in_debug_mode()
#define DEAL_II_NAMESPACE_CLOSE
#define DEAL_II_ASSERT_UNREACHABLE()
static ::ExceptionBase & ExcNotImplemented()
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
#define AssertThrowMPI(error_code)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcPointNotAvailableHere()
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
TriaIterator< CellAccessor< dim, spacedim > > cell_iterator
std::vector< index_type > data
@ past_the_end
Iterator reached end of container.
@ valid
Iterator points to a valid object.
T sum(const T &t, const MPI_Comm mpi_communicator)
std::map< unsigned int, T > some_to_some(const MPI_Comm comm, const std::map< unsigned int, T > &objects_to_send)
unsigned int n_mpi_processes(const MPI_Comm mpi_communicator)
T max(const T &t, const MPI_Comm mpi_communicator)
std::vector< T > all_gather(const MPI_Comm comm, const T &object_to_send)
void run(const std::vector< std::vector< Iterator > > &colored_iterators, Worker worker, Copier copier, const ScratchData &sample_scratch_data, const CopyData &sample_copy_data, const unsigned int queue_length=2 *MultithreadInfo::n_threads(), const unsigned int chunk_size=8)
constexpr unsigned int invalid_unsigned_int
constexpr types::subdomain_id artificial_subdomain_id
bool is_finite(const double x)
::VectorizedArray< Number, width > max(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
unsigned int subdomain_id