MFEM v4.9.0
Finite element discretization library
Loading...
Searching...
No Matches
particles_extras.cpp
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#include "particles_extras.hpp"
13
14
15namespace mfem
16{
17namespace common
18{
19
20void Add3DPoint(const Vector &center, Mesh &m, real_t scale)
21{
22 real_t s = 0.5*scale;
23 Vector v[8];
24
25 for (int i = 0; i < 8; i++)
26 {
27 v[i].SetSize(3);
28 v[i] = 0.0;
29 }
30
31 for (int i = 0; i < center.Size(); i++)
32 {
33 v[0][i] = center[i];
34 }
35
36 Vector v_s(3); v_s = s;
37 v[0] -= v_s;
38
39 v[1] = v[0];
40 v[1][0] += 2*s;
41
42 v[2] = v[1];
43 v[2][1] += 2*s;
44
45 v[3] = v[2];
46 v[3][0] -= 2*s;
47
48 Vector v_s_z(3);
49 v_s_z = 0.0;
50 v_s_z[2] = s;
51 for (int i = 4; i < 8; i++)
52 {
53 add(1.0, v[i-4], 2.0, v_s_z, v[i]);
54 }
55
56 for (int i = 0; i < 8; i++)
57 {
58 m.AddVertex(v[i]);
59 }
60
61 int vi[8];
62 for (int i = 0; i < 8; i++)
63 {
64 vi[i] = i + (m.GetNE())*8;
65 }
66 m.AddHex(vi);
67}
68
69void Add2DPoint(const Vector &center, Mesh &m, real_t scale)
70{
71 real_t s = 0.5*scale;
72 Vector v[4];
73
74 for (int i = 0; i < 4; i++)
75 {
76 v[i].SetSize(2);
77 v[i] = 0.0;
78 }
79
80 for (int i = 0; i < center.Size(); i++)
81 {
82 v[0][i] = center[i];
83 }
84
85 Vector v_s(2); v_s = s;
86 v[0] -= v_s;
87
88 v[1] = v[0];
89 v[1][0] += 2*s;
90
91 v[2] = v[1];
92 v[2][1] += 2*s;
93
94 v[3] = v[2];
95 v[3][0] -= 2*s;
96
97 for (int i = 0; i < 4; i++)
98 {
99 m.AddVertex(v[i]);
100 }
101
102 int vi[4];
103 for (int i = 0; i < 4; i++)
104 {
105 vi[i] = i + (m.GetNE())*4;
106 }
107 m.AddQuad(vi);
108}
109
110
111void VisualizeParticles(socketstream &sock, const char* vishost, int visport,
112 const ParticleSet &pset, const Vector &scalar_field,
113 real_t psize,
114 const char* title, int x, int y, int w, int h, const char* keys)
115{
116 const int dim = pset.GetDim();
117 MFEM_VERIFY(dim == 2 || dim == 3,
118 "ParticleSet dimension must be 2 or 3 for visualization.");
119 const int nv = dim == 2 ? 4 : 8;
120
121 L2_FECollection l2fec(1,dim);
122 Mesh particles_mesh(dim, pset.GetNParticles()*nv, pset.GetNParticles(),
123 0, dim);
124
125 for (int i = 0; i < pset.GetNParticles(); i++)
126 {
127 Vector pcoords;
128 pset.Coords().GetValues(i, pcoords);
129 if (dim == 2)
130 {
131 Add2DPoint(pcoords, particles_mesh, psize);
132 }
133 else
134 {
135 Add3DPoint(pcoords, particles_mesh, psize);
136 }
137 }
138 particles_mesh.FinalizeMesh();
139
140 FiniteElementSpace fes(&particles_mesh, &l2fec, 1);
141 GridFunction gf(&fes);
142
143 for (int i = 0; i < pset.GetNParticles(); i++)
144 {
145 for (int j = 0; j < nv; j++)
146 {
147 gf[j+i*nv] = scalar_field[i];
148 }
149 }
150
151#ifdef MFEM_USE_MPI
152 VisualizeField(sock, vishost, visport, gf, pset.GetComm(), title,
153 x, y, w, h, keys, false);
154#else
155 VisualizeField(sock, vishost, visport, gf, title, x, y, w, h, keys, false);
156#endif // MFEM_USE_MPI
157}
158
159
161 int tail_size_, const char *vishost_,
162 int visport_, const char *title_,
163 int x_, int y_, int w_, int h_,
164 const char *keys_)
165 : pset(particles), tail_size(tail_size_),
166 x(x_), y(y_), w(w_), h(h_), title(title_), keys(keys_),
167 vishost(vishost_), visport(visport_)
168#ifdef MFEM_USE_MPI
169 ,comm(particles.GetComm())
170#endif // MFEM_USE_MPI
171{
173}
174
176{
177 if (!pset.GetNParticles()) { return; }
178 // Create a new mesh for all particle segments for this timestep
179 segment_meshes.emplace_front(1, pset.GetNParticles()*2,
181 0, pset.GetDim());
182
183 // Add segment start particle IDs
184 segment_ids.emplace_front(pset.GetIDs());
185
186 if (tail_size > 0 && static_cast<int>(segment_meshes.size()) > tail_size)
187 {
188 segment_meshes.pop_back();
189 segment_ids.pop_back();
190 }
191
192 // Add all particle starting vertices
193 for (int i = 0; i < pset.GetNParticles(); i++)
194 {
195 Vector pcoords;
196 pset.Coords().GetValues(i, pcoords);
197 segment_meshes.front().AddVertex(pcoords);
198 }
199}
200
202{
203 if (segment_meshes.empty()) { return; } // no segments to end
204
205 const Array<ParticleSet::IDType> &end_ids = pset.GetIDs();
206
207 // Add all endpoint vertices + segments for all particles
208 int num_start = segment_ids.front().Size();
209 for (int i = 0; i < num_start; i++)
210 {
211 // If this particle's initial position was set in AddSegmentStart,
212 // set the vertex to its now current location
213 int pidx = end_ids.Find(segment_ids.front()[i]);
214 if (pidx != -1)
215 {
216 Vector pcoords;
217 pset.Coords().GetValues(pidx, pcoords);
218 segment_meshes.front().AddVertex(pcoords);
219 }
220 else // Otherwise set its end vertex == start vertex
221 {
222 segment_meshes.front().AddVertex(segment_meshes.front().GetVertex(i));
223 }
224 segment_meshes.front().AddSegment(i, i+num_start);
225 }
226 segment_meshes.front().FinalizeMesh();
227}
228
229
231{
233 if (segment_meshes.empty() && !mesh)
234 {
236 return;
237 }
238
239 // Create a mesh of all the trajectory segments
240 std::vector<Mesh*> all_meshes;
241 for (Mesh &m : segment_meshes)
242 {
243 all_meshes.push_back(&m);
244 }
245 if (mesh)
246 {
247 all_meshes.push_back(mesh);
248 }
249
250 Mesh trajectories(all_meshes.data(), all_meshes.size());
251
252#ifdef MFEM_USE_MPI
253 VisualizeMesh(sock, vishost, visport, trajectories, comm,
254 title, x, y, w, h, keys);
255#else
256 VisualizeMesh(sock, vishost, visport, trajectories,
257 title, x, y, w, h, keys);
258#endif
259
261}
262
263} // namespace common
264} // namespace mfem
int Size() const
Return the logical size of the array.
Definition array.hpp:166
int Find(const T &el) const
Return the first index where 'el' is found; return -1 if not found.
Definition array.hpp:971
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition fespace.hpp:208
Class for grid function - Vector with associated FE space.
Definition gridfunc.hpp:32
Arbitrary order "L2-conforming" discontinuous finite elements.
Definition fe_coll.hpp:350
Mesh data type.
Definition mesh.hpp:65
void FinalizeMesh(int refine=0, bool fix_orientation=true)
Finalize the construction of any type of Mesh.
Definition mesh.cpp:3496
int AddQuad(int v1, int v2, int v3, int v4, int attr=1)
Adds a quadrilateral to the mesh given by 4 vertices v1 through v4.
Definition mesh.cpp:2085
int AddVertex(real_t x, real_t y=0.0, real_t z=0.0)
Definition mesh.cpp:2000
int GetNE() const
Returns number of elements.
Definition mesh.hpp:1377
int AddHex(int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8, int attr=1)
Adds a hexahedron to the mesh given by 8 vertices v1 through v8.
Definition mesh.cpp:2148
ParticleSet initializes and manages data associated with particles.
MPI_Comm GetComm() const
Get the MPI communicator for this ParticleSet.
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 GetDim() const
Get the spatial dimension.
int GetNParticles() const
Get the number of active particles currently held by this ParticleSet.
void GetValues(int i, Vector &nvals) const
Get a copy of particle i 's data.
Vector data type.
Definition vector.hpp:82
int Size() const
Returns the size of the vector.
Definition vector.hpp:234
void SetSize(int s)
Resize the vector to size s.
Definition vector.hpp:584
void Visualize()
Visualize the particle trajectories (and mesh if provided).
std::list< Array< ParticleSet::IDType > > segment_ids
Track particle IDs that exist at the segment start.
ParticleTrajectories(const ParticleSet &particles, int tail_size_, const char *vishost_, int visport_, const char *title_, int x_=0, int y_=0, int w_=400, int h_=400, const char *keys_=nullptr)
Setup up the particle trajectory for visualization.
std::list< Mesh > segment_meshes
Each segment is stored as a Mesh snapshot.
int dim
Definition ex24.cpp:53
void Add2DPoint(const Vector &center, Mesh &m, real_t scale)
Add a point to a given Mesh, represented as a quad sized scale.
void VisualizeMesh(socketstream &sock, const char *vishost, int visport, Mesh &mesh, const char *title, int x, int y, int w, int h, const char *keys)
void Add3DPoint(const Vector &center, Mesh &m, real_t scale)
Add a point to a given Mesh, represented as a hex sized scale.
void VisualizeParticles(socketstream &sock, const char *vishost, int visport, const ParticleSet &pset, const Vector &scalar_field, real_t psize, const char *title, int x, int y, int w, int h, const char *keys)
Plot particles in ParticleSet pset, represented as quads/hexes of size psize and colored by scalar_fi...
void VisualizeField(socketstream &sock, const char *vishost, int visport, GridFunction &gf, const char *title, int x, int y, int w, int h, const char *keys, bool vec)
void add(const Vector &v1, const Vector &v2, Vector &v)
Definition vector.cpp:414
float real_t
Definition config.hpp:46
const char vishost[]