MFEM v4.9.0
Finite element discretization library
Loading...
Searching...
No Matches
particleset.hpp
Go to the documentation of this file.
1// Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11
12#ifndef MFEM_PARTICLESET
13#define MFEM_PARTICLESET
14
15#include "../config/config.hpp"
16#include "../linalg/linalg.hpp"
17#include "gslib.hpp"
18#include "kernel_dispatch.hpp"
19
20namespace mfem
21{
22
23/** @brief Container for data associated with a single particle.
24 *
25 * @note This class mainly serves as a convenience interface to individual
26 * particle data from ParticleSet. We recommend seeing ParticleSet first.
27 *
28 * @details As described in ParticleSet documentation, each particle has a
29 * position (\ref coords), arbitrary number of scalar or vector \ref real_t
30 * data (\ref fields), and arbitrary number of integers (\ref tags)
31 * associated with it.
32 *
33 * \ref fields can thus hold data such as mass, momentum, and velocity, while
34 * \ref tags can hold integer data such as particle type, color, etc.
35 *
36 * Each particle also has a unique global ID, but that is managed by the
37 * ParticleSet class and not stored in this Particle class. Simiarly, the names
38 * of the fields and tags, typically useful for output purposes, are managed by
39 * the ParticleSet class.
40 *
41 *
42 * For clarity, we will use the particles below to illustrate the data layout
43 * for \ref coords, \ref fields, and \ref tags
44 *
45 * @anchor sample_particle_data
46 * @code
47 * Particle_0: coords = (x0, y0),
48 * fields = {'mass'=m0, 'vel' = (vx0, vy0)},
49 * tags = {'type'=t0, 'color'=color0}
50 * Particle_1: coords = (x1, y1),
51 * fields = {'mass'=m1, 'vel' = (vx1, vy1)},
52 * tags = {'type'=t1, 'color'=color1}
53 * Particle_2: coords = (x2, y2),
54 * fields = {'mass'=m2, 'vel' = (vx2, vy2)},
55 * tags = {'type'=t2, 'color'=color2}
56 * @endcode
57 *
58 */
60{
61protected:
62 /** @brief Spatial coordinates
63 *
64 * @details For the \ref sample_particle_data, \ref coords would hold
65 * (x_i, y_i) for each particle i.
66 */
68
69 /** @brief A std::vector of Vector where each Vector holds data for a given
70 * field (e.g., mass, momentum or velocity) associated with the particle.
71 *
72 * @details For the \ref sample_particle_data, \ref fields would be
73 * fields[0]=(m_i), fields[1]=(vx_i,vy_i) for each particle i.
74 */
75 std::vector<Vector> fields;
76
77 /** @brief A std::vector of Array<int> where each Array<int> holds data
78 * for a given tag.
79 *
80 * @details For the \ref sample_particle_data, \ref tags would be
81 * tags[0]=(type_i), tags[1]=(color_i) for each particle i. \n
82 *
83 * @note An Array of length 1 is used for EACH tag, strictly for
84 * its owning/non-owning semantics (see Array<T>::MakeRef).
85 */
86 std::vector<Array<int>> tags;
87public:
88 /** @brief Construct a Particle instance.
89 * @param[in] dim Spatial dimension (size of #coords).
90 * @param[in] field_vdims Vector dimensions of particle fields.
91 * @param[in] num_tags Number of integer tags.
92 */
93 Particle(int dim, const Array<int> &field_vdims, int num_tags);
94
95 // Force default constructors and destructor
96 Particle(const Particle&) = default;
97 Particle& operator=(const Particle&) = default;
98 Particle(Particle&&) = default;
100 ~Particle() = default;
101
102 /// Get the spatial dimension of this particle.
103 int GetDim() const { return coords.Size(); }
104
105 /// Get the number of fields associated with this particle.
106 int GetNFields() const { return fields.size(); }
107
108 /// Get the vector dimension of field \p f .
109 int GetFieldVDim(int f) const { return fields[f].Size(); }
110
111 /// Get the number of tags associated with this particle.
112 int GetNTags() const { return tags.size(); }
113
114 /// Get reference to particle coordinates Vector.
115 Vector& Coords() { return coords; }
116
117 /// Get const reference to particle coordinates Vector.
118 const Vector& Coords() const { return coords; }
119
120 /// Get reference to field \p f , component \p c value.
121 real_t& FieldValue(int f, int c=0)
122 {
123 MFEM_ASSERT(f >= 0 && static_cast<std::size_t>(f) < fields.size(),
124 "Invalid field index");
125 MFEM_ASSERT(c >= 0 && c < fields[f].Size(),
126 "Invalid component index");
127 return fields[f][c];
128 }
129
130 /// Get const reference to field \p f , component \p c value.
131 const real_t& FieldValue(int f, int c=0) const
132 {
133 MFEM_ASSERT(f >= 0 && static_cast<std::size_t>(f) < fields.size(),
134 "invalid field index");
135 MFEM_ASSERT(c >= 0 && c < fields[f].Size(),
136 "invalid component index");
137 return fields[f][c];
138 }
139
140 /// Get reference to field \p f Vector.
142 {
143 MFEM_ASSERT(f >= 0 && static_cast<std::size_t>(f) < fields.size(),
144 "invalid field index");
145 return fields[f];
146 }
147
148 /// Get const reference to field \p f Vector.
149 const Vector& Field(int f) const
150 {
151 MFEM_ASSERT(f >= 0 && static_cast<std::size_t>(f) < fields.size(),
152 "invalid field index");
153 return fields[f];
154 }
155
156 /// Get reference to tag \p t .
157 int& Tag(int t)
158 {
159 MFEM_ASSERT(t >= 0 && static_cast<std::size_t>(t) < tags.size(),
160 "invalid tag index");
161 return tags[t][0];
162 }
163
164 /// Get const reference to tag \p t .
165 const int& Tag(int t) const
166 {
167 MFEM_ASSERT(t >= 0 && static_cast<std::size_t>(t) < tags.size(),
168 "invalid tag index");
169 return tags[t][0];
170 }
171
172 /// Set tag \p t to reference external data.
173 void SetTagRef(int t, int *tag_data);
174
175 /// Set field \p f to reference external data.
176 void SetFieldRef(int f, real_t *field_data);
177
178 /// Particle equality operator.
179 bool operator==(const Particle &rhs) const;
180
181 /// Particle inequality operator.
182 bool operator!=(const Particle &rhs) const { return !operator==(rhs); }
183
184 /// Print all particle data to \p os.
185 void Print(std::ostream &os=mfem::out) const;
186};
187
188/** @brief ParticleSet initializes and manages data associated with particles.
189 *
190 * @details Particles are inherently initialized to have a position and an ID,
191 * and optionally can have any number of Vector (of arbitrary vdim) and scalar
192 * integer data in the form of @b fields and @b tags respectively. All particle
193 * data are internally stored in a Struct-of-Arrays fashion, as elaborated on
194 * below.
195 *
196 * @par Coordinates:
197 * All particle coordinates are stored in a ParticleVector with vector
198 * dimension equal to the spatial dimension, ordered either byNODES or byVDIM.
199 * The ParticleVector \ref coords contains the coordinates of all particles.
200 *
201 * @par IDs:
202 * Each particle is assigned a unique global ID of type IDType. In parallel,
203 * IDs are initialized starting with @b rank and striding by @b size. The IDs
204 * of all particles owned by this rank are stored in \ref ids.
205 *
206 * @par Fields:
207 * Fields represent scalar or vector \ref real_t data to be associated with
208 * each particles, such as mass, momentum, or moment. For a given field, all
209 * particle data is stored in a single ParticleVector with a given
210 * vector dimension (1 for scalar data) and Ordering::Type (byNODES or
211 * byVDIM). The unique_ptrs to all the ParticleVectors are stored in the
212 * std::vector \ref fields.
213 *
214 * @par Tags:
215 * Tags represent integers associated with each particle. For a given tag,
216 * all particle data are stored in a single Array<int>. The unique_ptrs to all
217 * the Array<int> is stored in the std::vector \ref tags.
218 *
219 * @par Names:
220 * Each field and tag can optionally be given a name (string) to be used when
221 * printing particle data in CSV format using PrintCSV(). The names of all
222 * fields and tags are stored in the std::vectors \ref field_names and
223 * \ref tag_names, respectively.
224 *
225 * @note We assume that all particles in a ParticleSet have the same number
226 * of fields and tags.
227 *
228 * Following the example in the Particle class, we will use the
229 * particles below to illustrate the data layout for \ref coords, \ref ids,
230 * \ref fields, \ref tags, \ref field_names, and \ref tag_names.
231 * In each case, the name of the field and tag is enclosed in '...' for
232 * clarity. Additionally, we assume for this example that the particle
233 * coordinates and the 'vel' field are ordered byVDIM in their respective
234 * ParticleVector.
235 * @anchor sample_particleset_data
236 * @code
237 * Particle_0: id = id0, coords = (x0, y0),
238 * fields = {'mass'=m0, 'vel' = (vx0, vy0)},
239 * tags = {'type'=t0, 'color'=c0}
240 * Particle_1: id = id1, coords = (x1, y1),
241 * fields = {'mass'=m1, 'vel' = (vx1, vy1)},
242 * tags = {'type'=t1, 'color'=c1}
243 * Particle_2: id = id2, coords = (x2, y2),
244 * fields = {'mass'=m2, 'vel' = (vx2, vy2)},
245 * tags = {'type'=t2, 'color'=c2}
246 * @endcode
247 */
249{
250public:
251 using IDType = unsigned long long;
252private:
253 /// Constructs an Array of size N filled with Ordering::Type o.
254 static Array<Ordering::Type> GetOrderingArray(Ordering::Type o, int N);
255
256 /// Returns default field name for field index i. "Field_{i}"
257 static std::string GetDefaultFieldName(int i);
258
259 /// Returns default tag name for tag index i. "Tag_{i}"
260 static std::string GetDefaultTagName(int i);
261
262 /// Constructs an Array of size N filled with nullptr.
263 static Array<const char*> GetEmptyNameArray(int N);
264
265#ifdef MFEM_USE_MPI
266 static int GetRank(MPI_Comm comm_);
267 static int GetSize(MPI_Comm comm_);
268#endif // MFEM_USE_MPI
269
270protected:
271 /// Stride for IDs (used internally when new particles are added).
272 /** In parallel, this defaults to the number of MPI ranks. */
273 const int id_stride;
274
275 /// Current globally unique ID to be assigned to the next particle added.
276 /** In parallel, this starts locally as the rank and increments with
277 * id_stride, ensuring a global unique identifier whenever a particle is
278 * added.
279 */
281
282 /** @brief Global unique IDs of particles owned by this rank.
283 *
284 * @details For the \ref sample_particleset_data, \ref ids would be
285 * ids[0]=id0, ids[1]=id1, ids[2]=id2.
286 */
288
289 /** @brief Spatial coordinates of particles owned by this rank.
290 *
291 * @details For the \ref sample_particleset_data, \ref coords would be
292 * coords=(x0,y0,x1,y1,x2,y2) assuming coords ordering is byVDIM.
293 */
295
296 /** @brief All particle fields for particles owned by this rank.
297 *
298 * @details For the \ref sample_particleset_data, \ref fields would be
299 * *fields[0]=(m0,m1,m2), *fields[1]=(vx0,vy0,vx1,vy1,vx2,vy2)
300 * assuming fields[1] ordering is byVDIM.
301 */
302 std::vector<std::unique_ptr<ParticleVector>> fields;
303
304 /** @brief All particle tags for particles owned by this rank.
305 *
306 * @details For the \ref sample_particleset_data, \ref tags would be
307 * *tags[0]=(t0,t1,t2), *tags[1]=(c0,c1,c2).
308 */
309 std::vector<std::unique_ptr<Array<int>>> tags;
310
311 /** @brief Field names, to be written when PrintCSV() is called.
312 *
313 * @details For the \ref sample_particleset_data, \ref field_names would be
314 * field_names[0]='mass', field_names[1]='vel'.
315 */
316 std::vector<std::string> field_names;
317
318 /** @brief Tag names, to be written when PrintCSV() is called.
319 *
320 * @details For the \ref sample_particleset_data, \ref tag_names would be
321 * tag_names[0]='type', tag_names[1]='color'.
322 */
323 std::vector<std::string> tag_names;
324
325 /** @brief Add particles with global identifiers \p new_ids and
326 * optionally get the local indices of new particles in \p new_indices .
327 *
328 * @details Note the data of new particles is uninitialized and must be
329 * set.
330 */
331 void AddParticles(const Array<IDType> &new_ids,
332 Array<int> *new_indices=nullptr);
333
334#ifdef MFEM_USE_MPI
335 MPI_Comm comm;
336#endif // MFEM_USE_MPI
337
338#if defined(MFEM_USE_MPI) && defined(MFEM_USE_GSLIB)
339 struct gslib::crystal *cr = nullptr; // gslib's internal data
340 struct gslib::comm *gsl_comm = nullptr; // gslib's internal data
341
342 /// \cond DO_NOT_DOCUMENT
343 template<std::size_t NBytes>
344 static void TransferParticlesImpl(ParticleSet &pset,
345 const Array<int> &send_idxs,
346 const Array<unsigned int> &send_ranks);
347
348 using TransferParticlesType = void (*)(ParticleSet &pset,
349 const Array<int> &send_idxs,
350 const Array<unsigned int> &send_ranks);
351
352 // Specialization parameter: NBytes
353 MFEM_REGISTER_KERNELS(TransferParticles, TransferParticlesType, (size_t));
354 friend TransferParticles;
355 struct Kernels
356 {
357 Kernels();
358 };
359 /// \endcond
360
361#endif // MFEM_USE_MPI && MFEM_USE_GSLIB
362
363 /** @brief Update global ID of a particle.
364 *
365 * @details This method updates the global ID of the particle at given
366 * local index after Redistribute().
367 *
368 * @note This method must be used very carefully as it updates global
369 * ID of a particle.
370 */
371 void UpdateID(int local_idx, IDType new_global_id)
372 { ids[local_idx] = new_global_id; }
373
374 /** @brief Create a Particle object with the same spatial dimension,
375 * number of fields and field vdims, and number of tags as this ParticleSet.
376 */
377 Particle CreateParticle() const;
378
379 /** @brief Write string in \p ss_header , followed by \p ss_data , to a
380 * single file; compatible in parallel.
381 */
382 void WriteToFile(const char *fname, const std::stringstream &ss_header,
383 const std::stringstream &ss_data);
384
385 /** @brief Check if a particle could belong in this ParticleSet by
386 * comparing field and tag dimension.
387 */
388 bool IsValidParticle(const Particle &p) const;
389
390 /** @brief Hidden main constructor of ParticleSet
391 *
392 * @param[in] id_stride_ ID stride.
393 * @param[in] id_counter_ Starting ID counter.
394 * @param[in] num_particles Number of particles to initialize.
395 * @param[in] dim Particle spatial dimension.
396 * @param[in] coords_ordering Ordering of coordinates
397 * @param[in] field_vdims Array of field vector dimensions
398 * @param[in] field_orderings Array of field ordering types.
399 * @param[in] field_names_ Array of field names.
400 * @param[in] num_tags Number of tags to register.
401 * @param[in] tag_names_ Array of tag names.
402 */
403 ParticleSet(int id_stride_, IDType id_counter_, int num_particles, int dim,
404 Ordering::Type coords_ordering, const Array<int> &field_vdims,
405 const Array<Ordering::Type> &field_orderings,
406 const Array<const char*> &field_names_, int num_tags,
407 const Array<const char*> &tag_names_);
408
409public:
410
411 /** @brief Construct a serial ParticleSet.
412 *
413 * @param[in] num_particles Number of particles to initialize.
414 * @param[in] dim Particle spatial dimension.
415 * @param[in] coords_ordering Ordering of coordinates.
416 */
417 ParticleSet(int num_particles, int dim,
418 Ordering::Type coords_ordering=Ordering::byVDIM);
419
420 /** @brief Construct a serial ParticleSet with specified fields and tags at
421 * construction.
422 *
423 * @param[in] num_particles Number of particles to initialize.
424 * @param[in] dim Particle spatial dimension.
425 * @param[in] field_vdims Array of field vector dimensions.
426 * @param[in] num_tags Number of tags to register.
427 * @param[in] all_ordering (Optional) Ordering of coordinates and
428 * field ParticleVector.
429 */
430 ParticleSet(int num_particles, int dim, const Array<int> &field_vdims,
431 int num_tags, Ordering::Type all_ordering=Ordering::byVDIM);
432
433 /** @brief Construct a serial ParticleSet with specified fields and tags at
434 * construction, with names.
435 *
436 * @param[in] num_particles Number of particles to initialize.
437 * @param[in] dim Particle spatial dimension.
438 * @param[in] field_vdims Array of field vector dimensions.
439 * @param[in] field_names_ Array of field names.
440 * @param[in] num_tags Number of tags to register.
441 * @param[in] tag_names_ Array of tag names.
442 * @param[in] all_ordering (Optional) Ordering of coordinates and
443 * field ParticleVector.
444 */
445 ParticleSet(int num_particles, int dim, const Array<int> &field_vdims,
446 const Array<const char*> &field_names_, int num_tags,
447 const Array<const char*> &tag_names_,
448 Ordering::Type all_ordering=Ordering::byVDIM);
449
450 /** @brief Comprehensive serial constructor of ParticleSet.
451 *
452 * @param[in] num_particles Number of particles to initialize.
453 * @param[in] dim Particle spatial dimension.
454 * @param[in] coords_ordering Ordering of coordinates.
455 * @param[in] field_vdims Array of field vector dimensions.
456 * @param[in] field_orderings Array of field ordering types.
457 * @param[in] field_names_ Array of field names.
458 * @param[in] num_tags Number of tags to register.
459 * @param[in] tag_names_ Array of tag names.
460 */
461 ParticleSet(int num_particles, int dim, Ordering::Type coords_ordering,
462 const Array<int> &field_vdims,
463 const Array<Ordering::Type> &field_orderings,
464 const Array<const char*> &field_names_, int num_tags,
465 const Array<const char*> &tag_names_);
466
467#ifdef MFEM_USE_MPI
468 /** @brief Construct a parallel ParticleSet.
469 *
470 * @param[in] comm_ MPI communicator.
471 * @param[in] rank_num_particles Number of particles to initialize.
472 * @param[in] dim Particle spatial dimension.
473 * @param[in] coords_ordering (Optional) Ordering of coordinates.
474 */
475 ParticleSet(MPI_Comm comm_, int rank_num_particles, int dim,
476 Ordering::Type coords_ordering=Ordering::byVDIM);
477
478 /** @brief Construct a parallel ParticleSet with specified fields and tags
479 * at construction.
480 *
481 * @param[in] comm_ MPI communicator.
482 * @param[in] rank_num_particles # of particles to initialize on this rank.
483 * @param[in] dim Particle spatial dimension.
484 * @param[in] field_vdims Array of field vector dimensions.
485 * @param[in] num_tags Number of tags to register.
486 * @param[in] all_ordering (Optional) Ordering of coordinates and
487 * field ParticleVector.
488 */
489 ParticleSet(MPI_Comm comm_, int rank_num_particles, int dim,
490 const Array<int> &field_vdims, int num_tags,
491 Ordering::Type all_ordering=Ordering::byVDIM);
492
493 /** @brief Construct a parallel ParticleSet with specified fields and tags
494 * at construction, with names (for PrintCSV()).
495 *
496 * @param[in] comm_ MPI communicator.
497 * @param[in] rank_num_particles # of particles to initialize on this rank.
498 * @param[in] dim Particle spatial dimension.
499 * @param[in] field_vdims Array of field vector dimension.
500 * @param[in] field_names_ Array of field names.
501 * @param[in] num_tags Number of tags to register.
502 * @param[in] tag_names_ Array of tag names.
503 * @param[in] all_ordering (Optional) Ordering of coordinates and
504 * field ParticleVector.
505 */
506 ParticleSet(MPI_Comm comm_, int rank_num_particles, int dim,
507 const Array<int> &field_vdims,
508 const Array<const char*> &field_names_,
509 int num_tags, const Array<const char*> &tag_names_,
510 Ordering::Type all_ordering=Ordering::byVDIM);
511
512 /** @brief Comprehensive parallel constructor of ParticleSet.
513 *
514 * @param[in] comm_ MPI communicator.
515 * @param[in] rank_num_particles # of particles to initialize on this rank.
516 * @param[in] dim Particle spatial dimension.
517 * @param[in] coords_ordering Ordering of coordinates.
518 * @param[in] field_vdims Array of field vector dimensions.
519 * @param[in] field_orderings Array of field ordering types.
520 * @param[in] field_names_ Array of field names.
521 * @param[in] num_tags Number of tags to register.
522 * @param[in] tag_names_ Array of tag names.
523 */
524 ParticleSet(MPI_Comm comm_, int rank_num_particles, int dim,
525 Ordering::Type coords_ordering, const Array<int> &field_vdims,
526 const Array<Ordering::Type> &field_orderings,
527 const Array<const char*> &field_names_, int num_tags,
528 const Array<const char*> &tag_names_);
529
530 /// Get the MPI communicator for this ParticleSet.
531 MPI_Comm GetComm() const { return comm; };
532#endif // MFEM_USE_MPI
533 /// Get the global number of active particles across all ranks.
534 IDType GetGlobalNParticles() const;
535
536 /// Get the spatial dimension.
537 int GetDim() const { return coords.GetVDim(); }
538
539 /// Get the global IDs of the active particles owned by this ParticleSet.
540 const Array<IDType>& GetIDs() const { return ids; }
541
542 /** @brief Add a field to the ParticleSet.
543 *
544 * @param[in] vdim Vector dimension of the field.
545 * @param[in] field_ordering (Optional) Ordering::Type of the field.
546 * @param[in] field_name (Optional) Name of the field.
547 *
548 * @return Index of the newly-added field.
549 */
550 int AddField(int vdim, Ordering::Type field_ordering=Ordering::byVDIM,
551 const char* field_name=nullptr);
552
553 /** @brief Add a field to the ParticleSet.
554 *
555 * @details Same as AddField() but with different parameter order
556 * for convenience
557 */
558 int AddNamedField(int vdim, const char* field_name,
559 Ordering::Type field_ordering=Ordering::byVDIM)
560 {
561 return AddField(vdim, field_ordering, field_name);
562 }
563
564 /** @brief Add a tag to the ParticleSet.
565 *
566 * @param[in] tag_name (Optional) Name of the tag.
567 *
568 * @return Index of the newly-added tag.
569 */
570 int AddTag(const char* tag_name=nullptr);
571
572 /// Reserve memory for \p res particles.
573 /** Can help to avoid re-allocation for adding + removing particles. */
574 void Reserve(int res);
575
576 /// Get the number of active particles currently held by this ParticleSet.
577 int GetNParticles() const { return ids.Size(); }
578
579 /// Get the number of fields registered to particles.
580 int GetNFields() const { return fields.size(); }
581
582 /// Get an Array<int> of the field vector-dimensions registered to particles.
583 const Array<int> GetFieldVDims() const;
584
585 /// Get Field vector-dimension
586 int FieldVDim(int f) const { return fields[f]->GetVDim(); }
587
588 /// Get the number of tags registered to particles.
589 int GetNTags() const { return tags.size(); }
590
591 /// Add a particle using Particle .
592 void AddParticle(const Particle &p);
593
594 /** @brief Add \p num_particles particles, and optionally get the local
595 * indices of new particles in \p new_indices .
596 *
597 * @details The data of new particles is uninitialized and must be
598 * set.
599 */
600 void AddParticles(int num_particles, Array<int> *new_indices=nullptr);
601
602 /// Remove particle data specified by \p list of particle indices.
603 void RemoveParticles(const Array<int> &list);
604
605 /// Get a reference to the coordinates ParticleVector.
607
608 /// Get a const reference to the coordinates ParticleVector.
609 const ParticleVector& Coords() const { return coords; }
610
611 /// Get a reference to field \p f 's ParticleVector.
612 ParticleVector& Field(int f) { return *fields[f]; }
613
614 /// Get a const reference to field \p f 's ParticleVector.
615 const ParticleVector& Field(int f) const { return *fields[f]; }
616
617 /// Get a reference to tag \p t 's Array<int>.
618 Array<int>& Tag(int t) { return *tags[t]; }
619
620 /// Get a const reference to tag \p t 's Array<int>.
621 const Array<int>& Tag(int t) const { return *tags[t]; }
622
623 /** @brief Get new Particle object with copy of data associated with
624 particle \p i . */
625 Particle GetParticle(int i) const;
626
627 /** @brief Get Particle object whose members reference the actual data
628 * associated with particle \p i in this ParticleSet.
629 *
630 * @see IsParticleRefValid for when this method can be used.
631 *
632 * @warning If particles are added, removed, or redistributed after
633 * invoking this, the returned Particle member references may be
634 * invalidated.
635 */
637
638 /** @brief Determine if GetParticleRef is valid.
639 *
640 * If coordinates and all fields are ordered byVDIM, then returns true.
641 * Otherwise, false.
642 */
643 bool IsParticleRefValid() const;
644
645 /// Set data for particle at index \p i with data from provided particle \p p
646 void SetParticle(int i, const Particle &p);
647
648 /** @brief Print all particle data to a comma-delimited CSV file.
649 *
650 * The first row contains the header. We include the particle ID,
651 * owning rank (in parallel), coordinates, followed by all fields and
652 * tags.
653 *
654 * The output can be visualized in Paraview by loading the csv files, and
655 * applying the "Table To Points" filter.
656 */
657 void PrintCSV(const char *fname, int precision=16);
658
659 /** @brief Print only particle field and tags given by \p field_idxs and
660 \p tag_idxs respectively to a CSV file. */
661 void PrintCSV(const char *fname, const Array<int> &field_idxs,
662 const Array<int> &tag_idxs, int precision=16);
663
664#if defined(MFEM_USE_MPI) && defined(MFEM_USE_GSLIB)
665
666 /** @brief Redistribute particle data to \p rank_list
667
668 @param[in] rank_list Array of size GetNParticles() denoting ultimate
669 destination of particle data. Index = this rank
670 means no data is moved.
671 */
672 void Redistribute(const Array<unsigned int> &rank_list);
673
674#endif // MFEM_USE_MPI && MFEM_USE_GSLIB
675
676 /// Destructor
677 ~ParticleSet();
678 ParticleSet(const ParticleSet&) = delete;
680};
681
682} // namespace mfem
683
684
685#endif // MFEM_PARTICLESET
int Size() const
Return the logical size of the array.
Definition array.hpp:166
Type
Ordering methods:
Definition ordering.hpp:17
ParticleSet initializes and manages data associated with particles.
MPI_Comm GetComm() const
Get the MPI communicator for this ParticleSet.
const ParticleVector & Coords() const
Get a const reference to the coordinates ParticleVector.
Array< IDType > ids
Global unique IDs of particles owned by this rank.
ParticleVector coords
Spatial coordinates of particles owned by this rank.
~ParticleSet()
Destructor.
ParticleSet & operator=(const ParticleSet &)=delete
unsigned long long IDType
void Redistribute(const Array< unsigned int > &rank_list)
Redistribute particle data to rank_list.
int GetNTags() const
Get the number of tags registered to particles.
void AddParticle(const Particle &p)
Add a particle using Particle .
bool IsValidParticle(const Particle &p) const
Check if a particle could belong in this ParticleSet by comparing field and tag dimension.
Particle GetParticleRef(int i)
Get Particle object whose members reference the actual data associated with particle i in this Partic...
std::vector< std::string > tag_names
Tag names, to be written when PrintCSV() is called.
std::vector< std::unique_ptr< ParticleVector > > fields
All particle fields for particles owned by this rank.
Particle GetParticle(int i) const
Get new Particle object with copy of data associated with particle i .
const Array< int > GetFieldVDims() const
Get an Array<int> of the field vector-dimensions registered to particles.
ParticleVector & Coords()
Get a reference to the coordinates ParticleVector.
const Array< IDType > & GetIDs() const
Get the global IDs of the active particles owned by this ParticleSet.
int GetNFields() const
Get the number of fields registered to particles.
int AddTag(const char *tag_name=nullptr)
Add a tag to the ParticleSet.
const int id_stride
Stride for IDs (used internally when new particles are added).
void UpdateID(int local_idx, IDType new_global_id)
Update global ID of a particle.
bool IsParticleRefValid() const
Determine if GetParticleRef is valid.
ParticleVector & Field(int f)
Get a reference to field f 's ParticleVector.
int GetDim() const
Get the spatial dimension.
int GetNParticles() const
Get the number of active particles currently held by this ParticleSet.
void WriteToFile(const char *fname, const std::stringstream &ss_header, const std::stringstream &ss_data)
Write string in ss_header , followed by ss_data , to a single file; compatible in parallel.
ParticleSet(int id_stride_, IDType id_counter_, int num_particles, int dim, Ordering::Type coords_ordering, const Array< int > &field_vdims, const Array< Ordering::Type > &field_orderings, const Array< const char * > &field_names_, int num_tags, const Array< const char * > &tag_names_)
Hidden main constructor of ParticleSet.
Array< int > & Tag(int t)
Get a reference to tag t 's Array<int>.
int AddField(int vdim, Ordering::Type field_ordering=Ordering::byVDIM, const char *field_name=nullptr)
Add a field to the ParticleSet.
struct gslib::crystal * cr
void PrintCSV(const char *fname, int precision=16)
Print all particle data to a comma-delimited CSV file.
void Reserve(int res)
Reserve memory for res particles.
std::vector< std::unique_ptr< Array< int > > > tags
All particle tags for particles owned by this rank.
IDType id_counter
Current globally unique ID to be assigned to the next particle added.
const ParticleVector & Field(int f) const
Get a const reference to field f 's ParticleVector.
void RemoveParticles(const Array< int > &list)
Remove particle data specified by list of particle indices.
struct gslib::comm * gsl_comm
void AddParticles(const Array< IDType > &new_ids, Array< int > *new_indices=nullptr)
Add particles with global identifiers new_ids and optionally get the local indices of new particles i...
std::vector< std::string > field_names
Field names, to be written when PrintCSV() is called.
int AddNamedField(int vdim, const char *field_name, Ordering::Type field_ordering=Ordering::byVDIM)
Add a field to the ParticleSet.
int FieldVDim(int f) const
Get Field vector-dimension.
const Array< int > & Tag(int t) const
Get a const reference to tag t 's Array<int>.
Particle CreateParticle() const
Create a Particle object with the same spatial dimension, number of fields and field vdims,...
void SetParticle(int i, const Particle &p)
Set data for particle at index i with data from provided particle p.
ParticleSet(const ParticleSet &)=delete
ParticleVector carries vector data (of a given vector dimension) for an arbitrary number of particles...
int GetVDim() const
Get the Vector dimension of the ParticleVector.
Container for data associated with a single particle.
std::vector< Array< int > > tags
A std::vector of Array<int> where each Array<int> holds data for a given tag.
int GetFieldVDim(int f) const
Get the vector dimension of field f .
int GetDim() const
Get the spatial dimension of this particle.
~Particle()=default
Particle(const Particle &)=default
Particle & operator=(Particle &&)=default
bool operator==(const Particle &rhs) const
Particle equality operator.
int & Tag(int t)
Get reference to tag t .
int GetNTags() const
Get the number of tags associated with this particle.
Particle(Particle &&)=default
Vector & Field(int f)
Get reference to field f Vector.
std::vector< Vector > fields
A std::vector of Vector where each Vector holds data for a given field (e.g., mass,...
const real_t & FieldValue(int f, int c=0) const
Get const reference to field f , component c value.
const Vector & Coords() const
Get const reference to particle coordinates Vector.
const Vector & Field(int f) const
Get const reference to field f Vector.
Vector coords
Spatial coordinates.
real_t & FieldValue(int f, int c=0)
Get reference to field f , component c value.
Particle(int dim, const Array< int > &field_vdims, int num_tags)
Construct a Particle instance.
Particle & operator=(const Particle &)=default
bool operator!=(const Particle &rhs) const
Particle inequality operator.
Vector & Coords()
Get reference to particle coordinates Vector.
void Print(std::ostream &os=mfem::out) const
Print all particle data to os.
const int & Tag(int t) const
Get const reference to tag t .
int GetNFields() const
Get the number of fields associated with this particle.
void SetTagRef(int t, int *tag_data)
Set tag t to reference external data.
void SetFieldRef(int f, real_t *field_data)
Set field f to reference external data.
Vector data type.
Definition vector.hpp:82
int Size() const
Returns the size of the vector.
Definition vector.hpp:234
int dim
Definition ex24.cpp:53
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
Definition globals.hpp:66
float real_t
Definition config.hpp:46
std::function< real_t(const Vector &)> f(real_t mass_coeff)
Definition lor_mms.hpp:30
real_t p(const Vector &x, real_t t)
Base class for Schrodinger solver kernels.