deal.II version GIT relicensing-6816-g8d70a4508a 2026-09-28 16:30:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
particle_handler.h
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 2017 - 2025 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
13#ifndef dealii_particles_particle_handler_h
14#define dealii_particles_particle_handler_h
15
16#include <deal.II/base/config.h>
17
23
25
26#include <deal.II/fe/mapping.h>
27
29
34
35#include <boost/range/iterator_range.hpp>
36#include <boost/serialization/map.hpp>
37#include <boost/signals2.hpp>
38
39
41
42namespace Particles
43{
61 template <int dim, int spacedim = dim>
63 {
64 public:
69
73 using particle_iterator_range = boost::iterator_range<particle_iterator>;
74
80
85
96 const unsigned int n_properties = 0);
97
101 virtual ~ParticleHandler();
102
108 void
111 const unsigned int n_properties = 0);
112
133 void
134 copy_from(const ParticleHandler<dim, spacedim> &particle_handler);
135
139 void
140 clear();
141
147 void
149
164 void
165 reserve(const std::size_t n_particles);
166
175 void
177
182 begin() const;
183
188 begin();
189
194 end() const;
195
200 end();
201
206 begin_ghost() const;
207
212 begin_ghost();
213
218 end_ghost() const;
219
224 end_ghost();
225
232 const;
233
245
257 const;
258
264 void
265 remove_particle(const particle_iterator &particle);
266
272 void
273 remove_particles(const std::vector<particle_iterator> &particles);
274
283 const Particle<dim, spacedim> &particle,
285
303 const Point<spacedim> &position,
304 const Point<dim> &reference_position,
305 const types::particle_index particle_index,
307 const ArrayView<const double> &properties = {});
308
315 void
317 const std::multimap<
320
330 void
331 insert_particles(const std::vector<Point<spacedim>> &positions);
332
393 std::map<unsigned int, IndexSet>
395 const std::vector<Point<spacedim>> &positions,
396 const std::vector<std::vector<BoundingBox<spacedim>>>
397 &global_bounding_boxes,
398 const std::vector<std::vector<double>> &properties = {},
399 const std::vector<types::particle_index> &ids = {});
400
431 std::map<unsigned int, IndexSet>
433 const std::vector<Particle<dim, spacedim>> &particles,
434 const std::vector<std::vector<BoundingBox<spacedim>>>
435 &global_bounding_boxes);
436
480 template <typename VectorType>
481 std::enable_if_t<
482 std::is_convertible_v<VectorType *, Function<spacedim> *> == false>
483 set_particle_positions(const VectorType &input_vector,
484 const bool displace_particles = true);
485
506 void
507 set_particle_positions(const std::vector<Point<spacedim>> &new_positions,
508 const bool displace_particles = true);
509
510
529 void
531 const bool displace_particles = true);
532
560 template <typename VectorType>
561 void
562 get_particle_positions(VectorType &output_vector,
563 const bool add_to_output_vector = false) const;
564
579 void
580 get_particle_positions(std::vector<Point<spacedim>> &positions,
581 const bool add_to_output_vector = false) const;
582
609 void
611 const std::function<std::size_t()> &size_callback,
612 const std::function<void *(const particle_iterator &, void *)>
614 const std::function<const void *(const particle_iterator &, const void *)>
616
626 n_global_particles() const;
627
636
643
651
670
674 unsigned int
676
692
697 PropertyPool<dim, spacedim> &
698 get_property_pool() const;
699
704 get_triangulation() const;
705
710 get_mapping() const;
711
726 void
728
734 void
735 exchange_ghost_particles(const bool enable_ghost_cache = false);
736
744 void
746
756 void
758
777 void
779
791 void
793
802 void
803 deserialize();
804
811 template <class Archive>
812 void
813 serialize(Archive &ar, const unsigned int version);
814
827 struct Signals
828 {
842 boost::signals2::signal<void(
843 const typename Particles::ParticleIterator<dim, spacedim> &particle,
845 &cell)>
847 };
848
854
855 private:
864 const void *&data,
866
876
886 void
888
895
902
911 std::unique_ptr<PropertyPool<dim, spacedim>> property_pool;
912
917
923 const typename particle_container::iterator owned_particles_end;
924
930 std::vector<typename particle_container::iterator> cells_to_particle_cache;
931
937
943
953
959
971 std::function<std::size_t()> size_callback;
972
983 std::function<void *(const particle_iterator &, void *)> store_callback;
984
995 std::function<const void *(const particle_iterator &, const void *)>
997
1005
1009 const double tolerance_inside_cell = 1e-12;
1010
1020 std::unique_ptr<GridTools::Cache<dim, spacedim>> triangulation_cache;
1021
1022#ifdef DEAL_II_WITH_MPI
1046 void
1048 const std::map<types::subdomain_id, std::vector<particle_iterator>>
1049 &particles_to_send,
1050 const std::map<
1052 std::vector<
1054 &new_cells_for_particles = std::map<
1056 std::vector<
1058 const bool enable_cache = false);
1059
1071 void
1073 const std::map<types::subdomain_id, std::vector<particle_iterator>>
1074 &particles_to_send);
1075
1076#endif
1077
1085
1090 void
1092
1097 std::vector<boost::signals2::connection> tria_listeners;
1098
1107 void
1109
1115 void
1117
1125 void
1126 notify_ready_to_unpack(const bool serialization);
1127
1133 std::vector<char>
1136 const CellStatus status) const;
1137
1142 void
1145 const CellStatus status,
1146 const boost::iterator_range<std::vector<char>::const_iterator>
1147 &data_range);
1148
1153 typename particle_container::iterator
1155
1160 typename particle_container::iterator
1162
1167 typename particle_container::iterator
1169
1174 typename particle_container::iterator
1176 };
1177
1178
1179
1180 /* ---------------------- inline and template functions ------------------
1181 */
1182
1183 template <int dim, int spacedim>
1186 {
1187 return (const_cast<ParticleHandler<dim, spacedim> *>(this))->begin();
1188 }
1189
1190
1191
1192 template <int dim, int spacedim>
1195 {
1196 return particle_iterator(particle_container_owned_begin(),
1197 *property_pool,
1198 0);
1199 }
1200
1201
1202
1203 template <int dim, int spacedim>
1206 {
1207 return (const_cast<ParticleHandler<dim, spacedim> *>(this))->end();
1208 }
1209
1210
1211
1212 template <int dim, int spacedim>
1215 {
1216 return particle_iterator(particle_container_owned_end(), *property_pool, 0);
1217 }
1218
1219
1220
1221 template <int dim, int spacedim>
1224 {
1225 return (const_cast<ParticleHandler<dim, spacedim> *>(this))->begin_ghost();
1226 }
1227
1228
1229
1230 template <int dim, int spacedim>
1233 {
1234 return particle_iterator(particle_container_ghost_begin(),
1235 *property_pool,
1236 0);
1237 }
1238
1239
1240
1241 template <int dim, int spacedim>
1244 {
1245 return (const_cast<ParticleHandler<dim, spacedim> *>(this))->end_ghost();
1246 }
1247
1248
1249
1250 template <int dim, int spacedim>
1253 {
1254 return particle_iterator(particle_container_ghost_end(), *property_pool, 0);
1255 }
1256
1257
1258
1259 template <int dim, int spacedim>
1262 {
1263 // We should always have at least the three anchor entries in the list of
1264 // particles
1265 Assert(!particles.empty(), ExcInternalError());
1266 typename particle_container::iterator begin =
1267 const_cast<particle_container &>(particles).begin();
1268 return ++begin;
1269 }
1270
1271
1272
1273 template <int dim, int spacedim>
1276 {
1277 Assert(!particles.empty(), ExcInternalError());
1278 return owned_particles_end;
1279 }
1280
1281
1282
1283 template <int dim, int spacedim>
1286 {
1287 Assert(!particles.empty(), ExcInternalError());
1288 typename particle_container::iterator begin = owned_particles_end;
1289 return ++begin;
1290 }
1291
1292
1293
1294 template <int dim, int spacedim>
1297 {
1298 Assert(!particles.empty(), ExcInternalError());
1299 typename particle_container::iterator end =
1300 const_cast<particle_container &>(particles).end();
1301 return --end;
1302 }
1303
1304
1305
1306 template <int dim, int spacedim>
1307 template <class Archive>
1308 inline void
1309 ParticleHandler<dim, spacedim>::serialize(Archive &ar, const unsigned int)
1310 {
1311 // Note that we do not serialize the particle data itself (i.e., the
1312 // 'particles' member variable). Instead we
1313 // use the serialization functionality of the triangulation class, because
1314 // this guarantees that data is immediately shipped to new processes if
1315 // the domain is distributed differently after resuming from a checkpoint.
1316 //
1317 // See @ref step_83 "step-83" for how to serialize ParticleHandler objects.
1318 ar &global_number_of_particles &global_max_particles_per_cell
1319 &next_free_particle_index;
1320 }
1321
1322
1323
1324 template <int dim, int spacedim>
1325 template <typename VectorType>
1326 inline std::enable_if_t<
1327 std::is_convertible_v<VectorType *, Function<spacedim> *> == false>
1329 const VectorType &input_vector,
1330 const bool displace_particles)
1331 {
1332 AssertDimension(input_vector.size(),
1333 get_next_free_particle_index() * spacedim);
1334 for (auto &p : *this)
1335 {
1336 Point<spacedim> &position = p.get_location();
1337 const auto id = p.get_id();
1338
1339 if (displace_particles)
1340 for (unsigned int i = 0; i < spacedim; ++i)
1341 position[i] += input_vector[id * spacedim + i];
1342 else
1343 for (unsigned int i = 0; i < spacedim; ++i)
1344 position[i] = input_vector[id * spacedim + i];
1345 }
1346 sort_particles_into_subdomains_and_cells();
1347 }
1348
1349
1350
1351 template <int dim, int spacedim>
1352 template <typename VectorType>
1353 inline void
1355 VectorType &output_vector,
1356 const bool add_to_output_vector) const
1357 {
1358 AssertDimension(output_vector.size(),
1359 get_next_free_particle_index() * spacedim);
1360 for (const auto &p : *this)
1361 {
1362 auto point = p.get_location();
1363 const auto id = p.get_id();
1364 if (add_to_output_vector)
1365 for (unsigned int i = 0; i < spacedim; ++i)
1366 output_vector[id * spacedim + i] += point[i];
1367 else
1368 for (unsigned int i = 0; i < spacedim; ++i)
1369 output_vector[id * spacedim + i] = point[i];
1370 }
1371 if (add_to_output_vector)
1372 output_vector.compress(VectorOperation::add);
1373 else
1374 output_vector.compress(VectorOperation::insert);
1375 }
1376
1377
1378
1379 template <int dim, int spacedim>
1380 inline const Triangulation<dim, spacedim> &
1382 {
1383 Assert(triangulation != nullptr,
1384 ExcMessage("This ParticleHandler object has not been associated "
1385 "with a triangulation."));
1386
1387 return *triangulation;
1388 }
1389
1390
1391
1392 template <int dim, int spacedim>
1393 inline const Mapping<dim, spacedim> &
1395 {
1396 Assert(mapping != nullptr,
1397 ExcMessage("This ParticleHandler object has not been associated "
1398 "with a mapping."));
1399
1400 return *mapping;
1401 }
1402
1403} // namespace Particles
1404
1406
1407#endif
*  iterator end()
*  *  iterator begin()
CellStatus
Definition cell_status.h:29
Abstract base class for mapping classes.
Definition mapping.h:318
std::list< ParticlesInCell > particle_container
std::function< void *(const particle_iterator &, void *)> store_callback
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)
const Triangulation< dim, spacedim > & get_triangulation() const
void exchange_ghost_particles(const bool enable_ghost_cache=false)
types::particle_index n_global_particles() const
particle_iterator end_ghost() const
unsigned int global_max_particles_per_cell
internal::GhostParticlePartitioner< dim, spacedim > ghost_particles_cache
particle_container::iterator particle_container_ghost_begin() const
unsigned int n_properties_per_particle() const
types::particle_index global_number_of_particles
const Mapping< dim, spacedim > & get_mapping() const
particle_container::iterator particle_container_owned_end() const
particle_container::iterator particle_container_ghost_end() const
boost::iterator_range< particle_iterator > particle_iterator_range
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)
ParticleIterator< dim, spacedim > particle_iterator
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
particle_iterator begin_ghost() const
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)
void serialize(Archive &ar, const unsigned int version)
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)
particle_iterator begin() const
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)
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::function< std::size_t()> size_callback
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
const particle_container::iterator owned_particles_end
particle_iterator end() const
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
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 remove_particles(const std::vector< particle_iterator > &particles)
types::particle_index n_global_max_particles_per_cell() const
std::vector< boost::signals2::connection > tria_listeners
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)
std::vector< typename particle_container::iterator > cells_to_particle_cache
void copy_from(const ParticleHandler< dim, spacedim > &particle_handler)
std::function< const void *(const particle_iterator &, const void *)> load_callback
std::unique_ptr< GridTools::Cache< dim, spacedim > > triangulation_cache
types::particle_index get_next_free_particle_index() const
IndexSet locally_owned_particle_ids() const
Definition point.h:111
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define Assert(cond, exc)
#define AssertDimension(dim1, dim2)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcMessage(std::string arg1)
std::vector< index_type > data
Definition mpi.cc:734
boost::signals2::signal< void(const typename Particles::ParticleIterator< dim, spacedim > &particle, const typename Triangulation< dim, spacedim >::active_cell_iterator &cell)> particle_lost