15#if defined(MFEM_USE_MPI) && defined(MFEM_USE_GSLIB)
18#ifdef MFEM_HAVE_GCC_PRAGMA_DIAGNOSTIC
19#pragma GCC diagnostic push
20#pragma GCC diagnostic ignored "-Wunused-function"
31#ifdef MFEM_HAVE_GCC_PRAGMA_DIAGNOSTIC
32#pragma GCC diagnostic pop
42 : coords(
dim), fields(), tags()
47 for (
int f = 0;
f < field_vdims.
Size();
f++)
49 fields.emplace_back(field_vdims[
f]);
53 tags.reserve(num_tags);
54 for (
int t = 0; t < num_tags; t++)
64 static_cast<size_t>(t) <
tags.size(),
"Invalid tag index");
65 tags[t].MakeRef(tag_data, 1);
71 static_cast<size_t>(
f) <
fields.size(),
"Invalid field "
96 for (
size_t f = 0;
f <
fields.size();
f++)
102 for (
int c = 0; c <
fields[
f].Size(); c++)
115 for (
size_t t = 0; t <
tags.size(); t++)
133 for (
size_t f = 0;
f <
fields.size();
f++)
135 os <<
"Field " <<
f <<
": (";
136 for (
int c = 0; c <
fields[
f].Size(); c++)
141 for (
size_t t = 0; t <
tags.size(); t++)
143 os <<
"Tag " << t <<
": " <<
tags[t][0] <<
"\n";
153std::string ParticleSet::GetDefaultFieldName(
int i)
155 return "Field_" + std::to_string(i);
158std::string ParticleSet::GetDefaultTagName(
int i)
160 return "Tag_" + std::to_string(i);
163Array<const char*> ParticleSet::GetEmptyNameArray(
int N)
165 Array<const char*> names(N);
171int ParticleSet::GetRank(MPI_Comm comm_)
173 int r; MPI_Comm_rank(comm_, &r);
176int ParticleSet::GetSize(MPI_Comm comm_)
178 int s; MPI_Comm_size(comm_, &s);
195 for (
int t = 0; t <
GetNTags(); t++)
197 tags[t]->Reserve(res);
215 int num_add = new_ids.
Size();
217 int new_np = old_np + num_add;
223 for (
int i = 0; i < num_add; i++)
225 (*new_indices)[i] =
ids.
Size() + i;
240 for (
int t = 0; t <
GetNTags(); t++)
242 tags[t]->SetSize(new_np);
246#if defined(MFEM_USE_MPI) && defined(MFEM_USE_GSLIB)
264 const int *d_send_idxs = send_idxs.
GetMemory().Read(device_mc, nsend);
268 const int p = d_send_idxs[i];
272 for (
int c = 0; c < vdim; c++)
274 d_send_data[i*vdim + c] = d_src[offset + c*stride];
281static void GatherParticleTagsDevice(
const Array<int> &tag,
282 const Array<int> &send_idxs,
283 Array<int> &send_tag,
287 send_tag.SetSize(nsend);
288 int *d_send_tag = send_tag.GetMemory().Write(device_mc, nsend);
289 const int *d_tag = tag.GetMemory().Read(device_mc, tag.Size());
290 const int *d_send_idxs = send_idxs.GetMemory().Read(device_mc, nsend);
294 d_send_tag[i] = d_tag[d_send_idxs[i]];
300static void ScatterParticleVectorDevice(ParticleVector &pv,
301 const Vector &recv_data,
302 const Array<int> &recv_locs,
305 const int vdim = pv.GetVDim();
306 const int ordering = pv.GetOrdering();
307 const int num_particles = pv.GetNumParticles();
309 const real_t *d_recv_data =
310 recv_data.GetMemory().Read(device_mc, recv_data.Size());
311 const int *d_recv_locs = recv_locs.GetMemory().Read(device_mc, nrecv);
312 real_t *d_dst = pv.GetMemory().ReadWrite(device_mc, pv.Size());
316 const int p = d_recv_locs[i];
320 for (
int c = 0; c < vdim; c++)
322 d_dst[offset + c*stride] = d_recv_data[i*vdim + c];
329static void ScatterParticleTagsDevice(Array<int> &tag,
330 const Array<int> &recv_tag,
331 const Array<int> &recv_locs,
335 const int *d_recv_tag = recv_tag.GetMemory().Read(device_mc, nrecv);
336 const int *d_recv_locs = recv_locs.GetMemory().Read(device_mc, nrecv);
337 int *d_tag = tag.GetMemory().ReadWrite(device_mc, tag.Size());
341 d_tag[d_recv_locs[i]] = d_recv_tag[i];
345template<
size_t NBytes>
346void ParticleSet::TransferParticlesImpl(ParticleSet &pset,
347 const Array<int> &send_idxs,
348 const Array<unsigned int> &send_ranks)
352 alignas(
real_t) std::array<std::byte, NBytes> data;
356 int nreals = pset.GetFieldVDims().Sum() + pset.Coords().GetVDim();
357 int ntags = pset.GetNTags();
358 size_t nbytes = nreals*
sizeof(
real_t) + ntags*
sizeof(
int);
359 MFEM_VERIFY(nbytes <= NBytes,
"More data than can be packed.");
361 using parr_t = pdata_t;
362 gslib::array gsl_arr;
364 array_init(parr_t, &gsl_arr, send_idxs.Size());
365 pdata_arr = (parr_t*) gsl_arr.ptr;
367 int nparticles = pset.GetNParticles();
368 int nsend = send_idxs.Size();
369 gsl_arr.n = send_idxs.Size();
371 const int *h_send_idxs_initial = send_idxs.HostRead();
372 const IDType *h_ids = pset.GetIDs().HostRead();
373 for (
int i = 0; i < send_idxs.Size(); i++)
375 parr_t &pdata = pdata_arr[i];
376 pdata.id = h_ids[h_send_idxs_initial[i]];
382 int max_vdim = pset.Coords().GetVDim();
383 for (
int f = 0;
f < pset.GetNFields();
f++)
385 int f_vdim = pset.Field(
f).GetVDim();
386 if (f_vdim > max_vdim) { max_vdim = f_vdim; }
392 send_data.
SetSize(nsend * max_vdim);
393 send_tag.SetSize(nsend);
397 for (
int f = -1;
f < pset.GetNFields();
f++)
399 const ParticleVector &pv =
f == -1 ? pset.Coords() : pset.Field(
f);
400 const int vdim = pv.GetVDim();
401 const int ordering = pv.GetOrdering();
402 const int num_particles = pv.GetNumParticles();
407 GatherParticleVectorDevice(pv, send_idxs, send_data, nsend);
409 const real_t *h_send_data = send_data.HostRead();
410 for (
int i = 0; i < nsend; i++)
412 std::memcpy(pdata_arr[i].data.data() + counter,
413 h_send_data + i*vdim, vdim *
sizeof(
real_t));
418 const real_t *h_src = pv.HostRead();
419 const int *h_send_idxs = send_idxs.HostRead();
420 for (
int i = 0; i < nsend; i++)
422 parr_t &pdata = pdata_arr[i];
423 const int p = h_send_idxs[i];
428 for (
int c = 0; c < vdim; c++)
430 std::memcpy(pdata.data.data() + counter + c*
sizeof(
real_t),
431 h_src + offset + c*stride,
sizeof(
real_t));
436 counter += vdim*
sizeof(
real_t);
441 for (
int t = 0; t < pset.GetNTags(); t++)
443 const Array<int> &tag = pset.Tag(t);
444 const size_t tag_counter = counter + t*
sizeof(int);
449 GatherParticleTagsDevice(tag, send_idxs, send_tag, nsend);
451 const int *h_send_tag = send_tag.HostRead();
452 for (
int i = 0; i < nsend; i++)
454 std::memcpy(pdata_arr[i].data.data() + tag_counter,
455 h_send_tag + i,
sizeof(
int));
460 const int *h_tag = tag.HostRead();
461 const int *h_send_idxs = send_idxs.HostRead();
462 for (
int i = 0; i < nsend; i++)
464 std::memcpy(pdata_arr[i].data.data() + tag_counter,
465 h_tag + h_send_idxs[i],
sizeof(
int));
471 sarray_transfer_ext(parr_t, &gsl_arr, send_ranks.GetData(),
472 sizeof(
unsigned int), pset.cr);
475 int nrecv = (int) gsl_arr.n;
481 recv_data.SetSize(nrecv * max_vdim);
482 recv_tag.SetSize(nrecv);
485 int ndelete = nsend - nrecv;
489 auto datap =
const_cast<int*
>(send_idxs.HostRead());
490 Array<int> delete_idxs(datap + nrecv, ndelete);
491 pset.RemoveParticles(delete_idxs);
495 pset.Reserve(nparticles-ndelete);
498 pdata_arr = (parr_t*) gsl_arr.ptr;
501 int num_new = nrecv > nsend ? nrecv - nsend : 0;
502 Array<IDType> new_ids(num_new);
503 for (
int i = 0; i < num_new; i++)
505 new_ids[i] = pdata_arr[nsend + i].id;
509 Array<int> new_indices;
512 pset.AddParticles(new_ids, &new_indices);
516 Array<int> recv_locs(nrecv);
517 int *h_recv_locs = recv_locs.HostWrite();
518 const int *h_send_idxs_recv = send_idxs.HostRead();
519 for (
int i = 0; i < nrecv; i++)
521 parr_t &pdata = pdata_arr[i];
524 h_recv_locs[i] = h_send_idxs_recv[i];
525 pset.UpdateID(h_recv_locs[i], pdata.id);
529 h_recv_locs[i] = new_indices[i - nsend];
535 size_t recv_counter = 0;
536 for (
int f = -1;
f < pset.GetNFields();
f++)
538 ParticleVector &pv = (
f == -1 ? pset.Coords() : pset.Field(
f));
539 const int vdim = pv.GetVDim();
540 const int ordering = pv.GetOrdering();
541 const int num_particles = pv.GetNumParticles();
546 recv_data.SetSize(nrecv*vdim);
547 real_t *h_recv_data = recv_data.HostWrite();
549 for (
int i = 0; i < nrecv; i++)
551 std::memcpy(h_recv_data + i*vdim,
552 pdata_arr[i].data.data() + recv_counter,
556 ScatterParticleVectorDevice(pv, recv_data, recv_locs, nrecv);
560 real_t *h_dst = pv.HostReadWrite();
561 const int *h_recv_locs_read = recv_locs.HostRead();
562 for (
int i = 0; i < nrecv; i++)
564 parr_t &pdata = pdata_arr[i];
565 const int p = h_recv_locs_read[i];
570 for (
int c = 0; c < vdim; c++)
572 std::memcpy(h_dst + offset + c*stride,
573 pdata.data.data() + recv_counter + c*
sizeof(
real_t),
579 recv_counter += vdim*
sizeof(
real_t);
584 for (
int t = 0; t < pset.GetNTags(); t++)
586 Array<int> &tag = pset.Tag(t);
587 const size_t tag_counter = recv_counter + t*
sizeof(int);
592 recv_tag.SetSize(nrecv);
593 int *h_recv_tag = recv_tag.HostWrite();
595 for (
int i = 0; i < nrecv; i++)
597 std::memcpy(h_recv_tag + i,
598 pdata_arr[i].data.data() + tag_counter,
sizeof(
int));
601 ScatterParticleTagsDevice(tag, recv_tag, recv_locs, nrecv);
605 int *h_tag = tag.HostReadWrite();
606 const int *h_recv_locs_read = recv_locs.HostRead();
607 for (
int i = 0; i < nrecv; i++)
609 std::memcpy(h_tag + h_recv_locs_read[i],
610 pdata_arr[i].data.data() + tag_counter,
sizeof(
int));
614 array_free(&gsl_arr);
617 for (
int f = -1;
f < pset.GetNFields();
f++)
619 ParticleVector &pv = (
f == -1 ? pset.Coords() : pset.Field(
f));
620 pv.ReadWrite(pv.UseDevice());
622 for (
int t = 0; t < pset.GetNTags(); t++)
624 Array<int> &tag_arr = pset.Tag(t);
625 if (tag_arr.UseDevice()) { tag_arr.ReadWrite(
true); }
629template<
size_t NBytes>
630ParticleSet::TransferParticlesType ParticleSet::TransferParticles::Kernel()
632 return &ParticleSet::TransferParticlesImpl<NBytes>;
635ParticleSet::Kernels::Kernels()
637 constexpr size_t sizd =
sizeof(
real_t);
638 TransferParticles::Specialization<2*sizd>::Add();
639 TransferParticles::Specialization<3*sizd>::Add();
640 TransferParticles::Specialization<4*sizd>::Add();
641 TransferParticles::Specialization<8*sizd>::Add();
642 TransferParticles::Specialization<12*sizd>::Add();
643 TransferParticles::Specialization<16*sizd>::Add();
644 TransferParticles::Specialization<20*sizd>::Add();
645 TransferParticles::Specialization<24*sizd>::Add();
646 TransferParticles::Specialization<28*sizd>::Add();
647 TransferParticles::Specialization<32*sizd>::Add();
648 TransferParticles::Specialization<36*sizd>::Add();
649 TransferParticles::Specialization<40*sizd>::Add();
652auto ParticleSet::TransferParticles::Fallback(
size_t bufsize)
653-> ParticleSet::TransferParticlesType
655 constexpr size_t sizd =
sizeof(
real_t);
656 if (bufsize < 4*sizd)
658 return &ParticleSet::TransferParticlesImpl<4*sizd>;
660 else if (bufsize < 8*sizd)
662 return &ParticleSet::TransferParticlesImpl<8*sizd>;
664 else if (bufsize < 12*sizd)
666 return &ParticleSet::TransferParticlesImpl<12*sizd>;
668 else if (bufsize < 16*sizd)
670 return &ParticleSet::TransferParticlesImpl<16*sizd>;
672 else if (bufsize < 20*sizd)
674 return &ParticleSet::TransferParticlesImpl<20*sizd>;
676 else if (bufsize < 24*sizd)
678 return &ParticleSet::TransferParticlesImpl<24*sizd>;
680 else if (bufsize < 28*sizd)
682 return &ParticleSet::TransferParticlesImpl<28*sizd>;
684 else if (bufsize < 32*sizd)
686 return &ParticleSet::TransferParticlesImpl<32*sizd>;
688 else if (bufsize < 36*sizd)
690 return &ParticleSet::TransferParticlesImpl<36*sizd>;
692 else if (bufsize < 40*sizd)
694 return &ParticleSet::TransferParticlesImpl<40*sizd>;
696 return &ParticleSet::TransferParticlesImpl<60*sizd>;
703 "rank_list must be of size GetNParticles().");
705 int rank = GetRank(
comm);
713 for (
int i = 0; i < rank_list.
Size(); i++)
715 if (rank !=
static_cast<int>(rank_list[i]))
718 send_ranks.
Append(rank_list[i]);
725 size_t nbytes = nreals*
sizeof(
real_t) + ntags*
sizeof(
int);
728 TransferParticles::Run(nbytes, *
this, send_idxs, send_ranks);
739 const std::stringstream &ss_header,
const std::stringstream &ss_data)
744 int rank = GetRank(
comm);
746 MPI_File_delete(fname, MPI_INFO_NULL);
748 int mpi_err = MPI_File_open(
comm, fname, MPI_MODE_CREATE | MPI_MODE_WRONLY,
749 MPI_INFO_NULL, &file);
750 MFEM_VERIFY(mpi_err == MPI_SUCCESS,
"MPI_File_open failed.");
755 MPI_File_write_at(file, 0, ss_header.str().data(), ss_header.str().size(),
756 MPI_CHAR, MPI_STATUS_IGNORE);
760 MPI_Offset data_size = ss_data.str().size();
764 MPI_Exscan(&data_size, &offset, 1, MPI_OFFSET, MPI_SUM,
comm);
771 offset += ss_header.str().size();
774 MPI_File_write_at_all(file, offset, ss_data.str().data(),
775 data_size, MPI_BYTE, MPI_STATUS_IGNORE);
778 MPI_File_close(&file);
781 std::ofstream ofs(fname);
782 MFEM_VERIFY(ofs.is_open() && !ofs.fail(),
783 "Error: Could not open file " << fname <<
" for writing.");
784 ofs << ss_header.str() << ss_data.str();
795 : id_stride(id_stride_),
796 id_counter(id_counter_),
797 coords(
dim, coords_ordering)
802 for (
int f = 0;
f < field_vdims.
Size();
f++)
804 AddField(field_vdims[
f], field_orderings[
f], field_names_[
f]);
808 for (
int t = 0; t < num_tags; t++)
815 for (
int i = 0; i < num_particles; i++)
854 Array<const char*>(), use_device)
862 :
ParticleSet(1, 0, num_particles,
dim, all_ordering, field_vdims,
863 GetOrderingArray(all_ordering, field_vdims.Size()),
864 GetEmptyNameArray(field_vdims.Size()), num_tags,
865 GetEmptyNameArray(num_tags), use_device)
871 char*> &field_names_,
int num_tags,
874 :
ParticleSet(1, 0, num_particles,
dim, all_ordering, field_vdims,
875 GetOrderingArray(all_ordering, field_vdims.Size()),
876 field_names_, num_tags,
877 tag_names_, use_device)
888 :
ParticleSet(1, 0, num_particles,
dim, coords_ordering, field_vdims,
889 field_orderings, field_names_, num_tags, tag_names_, use_device)
901 Array<const char*>(), use_device)
909 :
ParticleSet(comm_, rank_num_particles,
dim, all_ordering, field_vdims,
910 GetOrderingArray(all_ordering, field_vdims.Size()),
911 GetEmptyNameArray(field_vdims.Size()), num_tags,
912 GetEmptyNameArray(num_tags), use_device)
919 char*> &field_names_,
922 :
ParticleSet(comm_, rank_num_particles,
dim, all_ordering, field_vdims,
923 GetOrderingArray(all_ordering, field_vdims.Size()),
924 field_names_, num_tags,
925 tag_names_, use_device)
944 tag_names_, use_device)
949 cr =
new gslib::crystal;
960 MPI_Allreduce(MPI_IN_PLACE, &total, 1, MPI_UNSIGNED_LONG_LONG,
967 const char* field_name)
969 std::string field_name_str(field_name ? field_name :
"");
972 field_name_str = GetDefaultFieldName(
field_names.size());
974 fields.emplace_back(std::make_unique<ParticleVector>(vdim, field_ordering,
984 std::string tag_name_str(tag_name ? tag_name :
"");
987 tag_name_str = GetDefaultTagName(
tag_names.size());
999 "Particle is incompatible with ParticleSet.");
1014 for (
int i = 0; i < num_particles; i++)
1036 for (
int t = 0; t <
GetNTags(); t++)
1038 tags[t]->DeleteAt(list);
1053 for (
int t = 0; t <
GetNTags(); t++)
1075 for (
int t = 0; t <
GetNTags(); t++)
1077 if (
tags[t]->UseDevice())
1088 "GetParticleRef is only valid when coordinates and fields are "
1089 "ordered byVDIM and particle data is host-resident.");
1098 "GetParticleRef only valid when all fields ordered byVDIM.");
1102 for (
int t = 0; t <
GetNTags(); t++)
1104 p.SetTagRef(t, &(*
tags[t])[i]);
1113 "Particle is incompatible with ParticleSet.");
1122 for (
int t = 0; t <
GetNTags(); t++)
1134 all_field_idxs[
f] =
f;
1137 for (
int t = 0; t <
GetNTags(); t++)
1139 all_tag_idxs[t] = t;
1142 PrintCSV(fname, all_field_idxs, all_tag_idxs, precision);
1148 std::stringstream ss_header;
1154 ss_header <<
",rank";
1157 std::array<char, 3> ax = {
'X',
'Y',
'Z'};
1160 ss_header <<
"," << ax[c];
1163 for (
int f = 0;
f < field_idxs.
Size();
f++)
1166 for (
int c = 0; c < pv.
GetVDim(); c++)
1169 (pv.
GetVDim() > 1 ?
"_" + std::to_string(c) :
"");
1173 for (
int t = 0; t < tag_idxs.
Size(); t++)
1175 ss_header <<
"," <<
tag_names[tag_idxs[t]];
1180 std::stringstream ss_data;
1181 ss_data.precision(precision);
1183 int rank = GetRank(
comm);
1187 for (
int i = 0; i <
GetNTags(); i++)
1189 tags[i]->HostRead();
1198 ss_data <<
"," << rank;
1203 ss_data <<
"," <<
coords(i, c);
1205 for (
int f = 0;
f < field_idxs.
Size();
f++)
1208 for (
int c = 0; c < pv.
GetVDim(); c++)
1210 ss_data <<
"," << pv(i, c);
1213 for (
int t = 0; t < tag_idxs.
Size(); t++)
1215 ss_data <<
"," << (*
tags[tag_idxs[t]])[i];
1226#if defined(MFEM_USE_MPI) && defined(MFEM_USE_GSLIB)
Memory< T > & GetMemory()
Return a reference to the Memory object used by the Array.
const T * HostRead() const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), false).
void Reserve(int capacity)
Ensures that the allocated size is at least the given size.
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
int Size() const
Return the logical size of the array.
int Append(const T &el)
Append element 'el' to array, resize if necessary.
T * HostReadWrite()
Shortcut for mfem::ReadWrite(a.GetMemory(), a.Size(), false).
void DeleteAt(const Array< int > &indices)
Delete entries at indices, and resize.
T Sum() const
Return the sum of all the array entries using the '+'' operator for class 'T'.
static MemoryClass GetDeviceMemoryClass()
Get the current Device MemoryClass. This is the MemoryClass used by most MFEM device kernels to acces...
static bool IsEnabled()
Return true if any backend other than Backend::CPU is enabled.
T * Write(MemoryClass mc, int size)
Get write-only access to the memory with the given MemoryClass.
const T * Read(MemoryClass mc, int size) const
Get read-only access to the memory with the given MemoryClass.
static bool IsFinalized()
Return true if MPI has been finalized.
The ordering method used when the number of unknowns per mesh node (vector dimension) is bigger than ...
ParticleSet initializes and manages data associated with particles.
Array< IDType > ids
Global unique IDs of particles owned by this rank.
ParticleVector coords
Spatial coordinates of particles owned by this rank.
~ParticleSet()
Destructor.
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.
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_, bool use_device)
Hidden main constructor of ParticleSet.
Particle GetParticle(int i) const
Get new Particle object with copy of data associated with particle i .
ParticleVector & Coords()
Get a reference to the coordinates ParticleVector.
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).
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.
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
IDType GetGlobalNParticles() const
Get the global number of active particles across all ranks.
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.
Array< int > GetFieldVDims() const
Get an Array<int> of the field vector-dimensions registered to 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.
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.
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.
ParticleVector carries vector data (of a given vector dimension) for an arbitrary number of particles...
void SetValues(int i, const Vector &nvals)
Set particle i 's data to nvals .
void GetValues(int i, Vector &nvals) const
Get a copy of particle i 's data.
int GetNumParticles() const
Get the number of particle data in the ParticleVector.
void DeleteParticles(const Array< int > &indices)
Remove particle data at indices.
void SetNumParticles(int num_vectors, bool keep_data=true)
Set the number of particle Vector data to be held by the ParticleVector, keeping existing data.
int GetVDim() const
Get the Vector dimension of the ParticleVector.
void GetValuesRef(int i, Vector &nref)
For GetOrdering == Ordering::byVDIM, set nref to refer to particle i 's data.
Ordering::Type GetOrdering() const
Get the ordering of data in 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.
bool operator==(const Particle &rhs) const
Particle equality operator.
std::vector< Vector > fields
A std::vector of Vector where each Vector holds data for a given field (e.g., mass,...
Vector coords
Spatial coordinates.
Particle(int dim, const Array< int > &field_vdims, int num_tags)
Construct a Particle instance.
void Print(std::ostream &os=mfem::out) const
Print all particle data to os.
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.
Memory< real_t > & GetMemory()
Return a reference to the Memory object used by the Vector.
int Size() const
Returns the size of the vector.
virtual void UseDevice(bool use_dev) const
Enable execution of Vector operations using the mfem::Device.
void SetSize(int s)
Resize the vector to size s.
void Reserve(int res)
Update Capacity() to res (if less than current), keeping existing entries.
MemoryClass
Memory classes identify sets of memory types.
std::function< real_t(const Vector &)> f(real_t mass_coeff)
void forall(int N, lambda &&body)
real_t p(const Vector &x, real_t t)