MFEM v4.8.0
Finite element discretization library
Loading...
Searching...
No Matches
findpts.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// -------------------------------------------------------------
13// Find Points Miniapp: Evaluate grid function in physical space
14// -------------------------------------------------------------
15//
16// This miniapp demonstrates the interpolation of a high-order grid function on
17// a set of points in physical-space. The miniapp is based on GSLIB-FindPoints,
18// which provides two key functionalities. First, for a given set of points in
19// the physical-space, it determines the computational coordinates (element
20// number, reference-space coordinates inside the element, and processor number
21// [in parallel]) for each point. Second, based on computational coordinates, it
22// interpolates a grid function in the given points. Inside GSLIB, computation
23// of the coordinates requires use of a Hash Table to identify the candidate
24// processor and element for each point, followed by the Newton's method to
25// determine the reference-space coordinates inside the candidate element.
26//
27// Compile with: make findpts
28//
29// Sample runs:
30// findpts -m ../../data/rt-2d-p4-tri.mesh -o 8 -mo 4
31// findpts -m ../../data/inline-tri.mesh -o 3
32// findpts -m ../../data/inline-quad.mesh -o 3
33// findpts -m ../../data/inline-quad.mesh -o 3 -po 1
34// findpts -m ../../data/inline-quad.mesh -o 3 -po 1 -fo 1 -nc 2
35// findpts -m ../../data/inline-quad.mesh -o 3 -hr -pr -mpr -mo 2
36// findpts -m ../../data/inline-quad.mesh -o 3 -hr -pr -mpr -mo 3
37// findpts -m ../../data/inline-tet.mesh -o 3
38// findpts -m ../../data/inline-hex.mesh -o 3
39// findpts -m ../../data/inline-wedge.mesh -o 3
40// findpts -m ../../data/amr-quad.mesh -o 2
41// findpts -m ../../data/rt-2d-q3.mesh -o 8 -mo 4 -ft 2
42// findpts -m ../../data/square-mixed.mesh -o 2 -mo 2
43// findpts -m ../../data/square-mixed.mesh -o 2 -mo 2 -hr -pr -mpr
44// findpts -m ../../data/square-mixed.mesh -o 2 -mo 3 -ft 2
45// findpts -m ../../data/fichera-mixed.mesh -o 3 -mo 2
46// findpts -m ../../data/inline-pyramid.mesh -o 1 -mo 1
47// findpts -m ../../data/tinyzoo-3d.mesh -o 1 -mo 1
48
49#include "mfem.hpp"
51
52using namespace mfem;
53using namespace std;
54
56 const char *title, int locx)
57{
58 Mesh *mesh = fespace.GetMesh();
59 L2_FECollection order_coll = L2_FECollection(0, mesh->Dimension());
60 FiniteElementSpace order_space = FiniteElementSpace(mesh, &order_coll);
61 GridFunction order_gf = GridFunction(&order_space);
62
63 for (int e = 0; e < mesh->GetNE(); e++)
64 {
65 order_gf(e) = fespace.GetElementOrder(e);
66 }
67
68 socketstream vis1;
69 common::VisualizeField(vis1, "localhost", 19916, order_gf, title,
70 locx, 0, 400, 400, "RjmAcp");
71}
72
74
75// Scalar function to project
76double field_func(const Vector &x)
77{
78 const int dim = x.Size();
79 double res = 0.0;
80 for (int d = 0; d < dim; d++) { res += std::pow(x(d), func_order); }
81 return res;
82}
83
84void F_exact(const Vector &p, Vector &F)
85{
86 F(0) = field_func(p);
87 for (int i = 1; i < F.Size(); i++) { F(i) = (i+1)*F(0); }
88}
89
90int main (int argc, char *argv[])
91{
92 // Set the method's default parameters.
93 const char *mesh_file = "../../data/rt-2d-q3.mesh";
94 int order = 3;
95 int mesh_poly_deg = 3;
96 int rs_levels = 0;
97 bool visualization = true;
98 int fieldtype = 0;
99 int ncomp = 1;
100 bool hrefinement = false;
101 bool prefinement = false;
102 int point_ordering = 0;
103 int gf_ordering = 0;
104 bool mesh_prefinement = false;
105
106 // Parse command-line options.
107 OptionsParser args(argc, argv);
108 args.AddOption(&mesh_file, "-m", "--mesh",
109 "Mesh file to use.");
110 args.AddOption(&order, "-o", "--order",
111 "Finite element order (polynomial degree).");
112 args.AddOption(&mesh_poly_deg, "-mo", "--mesh-order",
113 "Polynomial degree of mesh finite element space.");
114 args.AddOption(&rs_levels, "-rs", "--refine-serial",
115 "Number of times to refine the mesh uniformly in serial.");
116 args.AddOption(&fieldtype, "-ft", "--field-type",
117 "Field type: 0 - H1, 1 - L2, 2 - H(div), 3 - H(curl).");
118 args.AddOption(&ncomp, "-nc", "--ncomp",
119 "Number of components for H1 or L2 GridFunctions");
120 args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
121 "--no-visualization",
122 "Enable or disable GLVis visualization.");
123 args.AddOption(&hrefinement, "-hr", "--h-refinement", "-no-hr",
124 "--no-h-refinement",
125 "Do random h refinements to mesh (does not work for pyramids).");
126 args.AddOption(&prefinement, "-pr", "--p-refinement", "-no-pr",
127 "--no-p-refinement",
128 "Do random p refinements to solution field (does not work for pyramids).");
129 args.AddOption(&point_ordering, "-po", "--point-ordering",
130 "Ordering of points to be found."
131 "0 (default): byNodes, 1: byVDIM");
132 args.AddOption(&gf_ordering, "-fo", "--fespace-ordering",
133 "Ordering of fespace that will be used for grid function to be interpolated."
134 "0 (default): byNodes, 1: byVDIM");
135 args.AddOption(&mesh_prefinement, "-mpr", "--mesh-p-refinement", "-no-mpr",
136 "--no-mesh-p-refinement",
137 "Do random p refinements to mesh Nodes.");
138
139 args.Parse();
140 if (!args.Good())
141 {
142 args.PrintUsage(cout);
143 return 1;
144 }
145 args.PrintOptions(cout);
146
147 func_order = std::min(order, 2);
148
149 // Initialize and refine the starting mesh.
150 Mesh mesh(mesh_file, 1, 1, false);
151 for (int lev = 0; lev < rs_levels; lev++) { mesh.UniformRefinement(); }
152 const int dim = mesh.Dimension();
153 cout << "Mesh curvature of the original mesh: ";
154 if (mesh.GetNodes()) { cout << mesh.GetNodes()->OwnFEC()->Name(); }
155 else { cout << "(NONE)"; }
156 cout << endl;
157
158 // Mesh bounding box.
159 Vector pos_min, pos_max;
160 MFEM_VERIFY(mesh_poly_deg > 0, "The order of the mesh must be positive.");
161 mesh.GetBoundingBox(pos_min, pos_max, mesh_poly_deg);
162 if (hrefinement || prefinement || mesh_prefinement) { mesh.EnsureNCMesh(true); }
163 cout << "--- Generating equidistant point for:\n"
164 << "x in [" << pos_min(0) << ", " << pos_max(0) << "]\n"
165 << "y in [" << pos_min(1) << ", " << pos_max(1) << "]\n";
166 if (dim == 3)
167 {
168 cout << "z in [" << pos_min(2) << ", " << pos_max(2) << "]\n";
169 }
170
171 // Random h-refinements to mesh
172 if (hrefinement) { mesh.RandomRefinement(0.5); }
173
174 // Curve the mesh based on the chosen polynomial degree.
175 H1_FECollection fecm(mesh_poly_deg, dim);
176 FiniteElementSpace fespace(&mesh, &fecm, dim);
177 mesh.SetNodalFESpace(&fespace);
178 GridFunction Nodes(&fespace);
179 mesh.SetNodalGridFunction(&Nodes);
180 cout << "Mesh curvature of the curved mesh: " << fecm.Name() << endl;
181
182 if (mesh_prefinement)
183 {
185 for (int e = 0; e < mesh.GetNE(); e++)
186 {
187 if ((double) rand() / RAND_MAX < 0.2)
188 {
189 refs.Append(pRefinement(e,1));
190 }
191 }
192 fespace.PRefineAndUpdate(refs);
193 Nodes.Update();
194 }
195
196 MFEM_VERIFY(ncomp > 0, "Invalid number of components.");
197 int vec_dim = ncomp;
198 FiniteElementCollection *fec = NULL;
199 if (fieldtype == 0)
200 {
201 fec = new H1_FECollection(order, dim);
202 cout << "H1-GridFunction\n";
203 }
204 else if (fieldtype == 1)
205 {
206 fec = new L2_FECollection(order, dim);
207 cout << "L2-GridFunction\n";
208 }
209 else if (fieldtype == 2)
210 {
211 fec = new RT_FECollection(order, dim);
212 ncomp = 1;
213 vec_dim = dim;
214 cout << "H(div)-GridFunction\n";
215 }
216 else if (fieldtype == 3)
217 {
218 fec = new ND_FECollection(order, dim);
219 ncomp = 1;
220 vec_dim = dim;
221 cout << "H(curl)-GridFunction\n";
222 }
223 else
224 {
225 MFEM_ABORT("Invalid field type.");
226 }
227 FiniteElementSpace sc_fes(&mesh, fec, ncomp, gf_ordering);
228 GridFunction field_vals(&sc_fes);
229
230 // Random p-refinements to the solution field
231 if (prefinement)
232 {
234 for (int e = 0; e < mesh.GetNE(); e++)
235 {
236 if ((double) rand() / RAND_MAX < 0.5)
237 {
238 refs.Append(pRefinement(e,1));
239 }
240 }
241 sc_fes.PRefineAndUpdate(refs);
242 field_vals.Update();
243 }
244
245 std::unique_ptr<GridFunction> mesh_nodes_max;
246 if (mesh_prefinement) { mesh_nodes_max = Nodes.ProlongateToMaxOrder(); }
247 GridFunction *mesh_nodes_pref = mesh_prefinement ?
248 mesh_nodes_max.get() : &Nodes;
249
250 if (mesh_prefinement && visualization)
251 {
252 mesh.SetNodalGridFunction(mesh_nodes_pref);
253 VisualizeFESpacePolynomialOrder(fespace, "Mesh Polynomial Order", 400);
254 mesh.SetNodalGridFunction(&Nodes);
255 }
256
257 if (prefinement && visualization)
258 {
259 mesh.SetNodalGridFunction(mesh_nodes_pref);
260 VisualizeFESpacePolynomialOrder(sc_fes, "Solution Polynomial Order", 800);
261 mesh.SetNodalGridFunction(&Nodes);
262 }
263
264 // Project the GridFunction using VectorFunctionCoefficient.
266 field_vals.ProjectCoefficient(F);
267
268 std::unique_ptr<GridFunction> field_vals_max;
269 if (prefinement) { field_vals_max = field_vals.ProlongateToMaxOrder(); }
270 GridFunction *field_vals_pref = prefinement ?
271 field_vals_max.get() : &field_vals;
272
273 // Display the mesh and the field through glvis.
274 if (visualization)
275 {
276 if (mesh_prefinement) { mesh.SetNodalGridFunction(mesh_nodes_pref); }
277 socketstream vis1;
278 common::VisualizeField(vis1, "localhost", 19916, *field_vals_pref,
279 "Solution",
280 0, 0, 400, 400, "RmjA*****");
281 if (mesh_prefinement) { mesh.SetNodalGridFunction(&Nodes); }
282 }
283
284 // Generate equidistant points in physical coordinates over the whole mesh.
285 // Note that some points might be outside, if the mesh is not a box. Note
286 // also that all tasks search the same points (not mandatory).
287 const int pts_cnt_1D = 25;
288 int pts_cnt = pow(pts_cnt_1D, dim);
289 Vector vxyz(pts_cnt * dim);
290 if (dim == 2)
291 {
293 const IntegrationRule &ir = el.GetNodes();
294 for (int i = 0; i < ir.GetNPoints(); i++)
295 {
296 const IntegrationPoint &ip = ir.IntPoint(i);
297 if (point_ordering == Ordering::byNODES)
298 {
299 vxyz(i) = pos_min(0) + ip.x * (pos_max(0)-pos_min(0));
300 vxyz(pts_cnt + i) = pos_min(1) + ip.y * (pos_max(1)-pos_min(1));
301 }
302 else
303 {
304 vxyz(i*dim + 0) = pos_min(0) + ip.x * (pos_max(0)-pos_min(0));
305 vxyz(i*dim + 1) = pos_min(1) + ip.y * (pos_max(1)-pos_min(1));
306 }
307 }
308 }
309 else
310 {
312 const IntegrationRule &ir = el.GetNodes();
313 for (int i = 0; i < ir.GetNPoints(); i++)
314 {
315 const IntegrationPoint &ip = ir.IntPoint(i);
316 if (point_ordering == Ordering::byNODES)
317 {
318 vxyz(i) = pos_min(0) + ip.x * (pos_max(0)-pos_min(0));
319 vxyz(pts_cnt + i) = pos_min(1) + ip.y * (pos_max(1)-pos_min(1));
320 vxyz(2*pts_cnt + i) = pos_min(2) + ip.z * (pos_max(2)-pos_min(2));
321 }
322 else
323 {
324 vxyz(i*dim + 0) = pos_min(0) + ip.x * (pos_max(0)-pos_min(0));
325 vxyz(i*dim + 1) = pos_min(1) + ip.y * (pos_max(1)-pos_min(1));
326 vxyz(i*dim + 2) = pos_min(2) + ip.z * (pos_max(2)-pos_min(2));
327 }
328 }
329 }
330
331 // Find and Interpolate FE function values on the desired points.
332 Vector interp_vals(pts_cnt*vec_dim);
333 FindPointsGSLIB finder;
334 finder.Setup(mesh);
336 finder.Interpolate(vxyz, field_vals, interp_vals, point_ordering);
337 Array<unsigned int> code_out = finder.GetCode();
338 Vector dist_p_out = finder.GetDist();
339
340 int face_pts = 0, not_found = 0, found = 0;
341 double error = 0.0, max_err = 0.0, max_dist = 0.0;
342 Vector pos(dim);
343 for (int j = 0; j < vec_dim; j++)
344 {
345 for (int i = 0; i < pts_cnt; i++)
346 {
347 if (code_out[i] < 2)
348 {
349 if (j == 0) { found++; }
350 for (int d = 0; d < dim; d++)
351 {
352 pos(d) = point_ordering == Ordering::byNODES ?
353 vxyz(d*pts_cnt + i) :
354 vxyz(i*dim + d);
355 }
356 Vector exact_val(vec_dim);
357 F_exact(pos, exact_val);
358 error = gf_ordering == Ordering::byNODES ?
359 fabs(exact_val(j) - interp_vals[i + j*pts_cnt]) :
360 fabs(exact_val(j) - interp_vals[i*vec_dim + j]);
361 max_err = std::max(max_err, error);
362 max_dist = std::max(max_dist, dist_p_out(i));
363 if (code_out[i] == 1 && j == 0) { face_pts++; }
364 }
365 else { if (j == 0) { not_found++; } }
366 }
367 }
368
369 cout << setprecision(16)
370 << "Searched points: " << pts_cnt
371 << "\nFound points: " << found
372 << "\nMax interp error: " << max_err
373 << "\nMax dist (of found): " << max_dist
374 << "\nPoints not found: " << not_found
375 << "\nPoints on faces: " << face_pts << endl;
376
377 // Free the internal gslib data.
378 finder.FreeData();
379
380 delete fec;
381
382 return 0;
383}
int Append(const T &el)
Append element 'el' to array, resize if necessary.
Definition array.hpp:830
@ ClosedUniform
Nodes: x_i = i/(n-1), i=0,...,n-1.
Definition fe_base.hpp:39
FindPointsGSLIB can robustly evaluate a GridFunction on an arbitrary collection of points.
Definition gslib.hpp:67
virtual const Vector & GetDist() const
Definition gslib.hpp:304
void Setup(Mesh &m, const double bb_t=0.1, const double newt_tol=1.0e-12, const int npt_max=256)
Definition gslib.cpp:163
virtual void Interpolate(const GridFunction &field_in, Vector &field_out)
Definition gslib.cpp:1721
virtual const Array< unsigned int > & GetCode() const
Definition gslib.hpp:295
virtual void FreeData()
Definition gslib.cpp:1128
virtual void SetL2AvgType(AvgType avgtype_)
Definition gslib.hpp:267
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
Definition fe_coll.hpp:27
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition fespace.hpp:244
int GetElementOrder(int i) const
Returns the order of the i'th finite element.
Definition fespace.cpp:221
Mesh * GetMesh() const
Returns the mesh.
Definition fespace.hpp:679
virtual void PRefineAndUpdate(const Array< pRefinement > &refs, bool want_transfer=true)
Definition fespace.cpp:4276
const IntegrationRule & GetNodes() const
Get a const reference to the nodes of the element.
Definition fe_base.hpp:400
Class for grid function - Vector with associated FE space.
Definition gridfunc.hpp:31
virtual void Update()
Transform by the Space UpdateMatrix (e.g., on Mesh change).
Definition gridfunc.cpp:167
virtual void ProjectCoefficient(Coefficient &coeff)
Project coeff Coefficient to this GridFunction. The projection computation depends on the choice of t...
std::unique_ptr< GridFunction > ProlongateToMaxOrder() const
Return a GridFunction with the values of this, prolongated to the maximum order of all elements in th...
Arbitrary order H1-conforming (continuous) finite elements.
Definition fe_coll.hpp:275
const char * Name() const override
Definition fe_coll.hpp:297
Class for integration point with weight.
Definition intrules.hpp:35
Class for an integration rule - an Array of IntegrationPoint.
Definition intrules.hpp:100
int GetNPoints() const
Returns the number of the points in the integration rule.
Definition intrules.hpp:256
IntegrationPoint & IntPoint(int i)
Returns a reference to the i-th integration point.
Definition intrules.hpp:259
Arbitrary order "L2-conforming" discontinuous finite elements.
Definition fe_coll.hpp:346
Arbitrary order L2 elements in 3D on a cube.
Definition fe_l2.hpp:80
Arbitrary order L2 elements in 2D on a square.
Definition fe_l2.hpp:46
Mesh data type.
Definition mesh.hpp:64
int GetNE() const
Returns number of elements.
Definition mesh.hpp:1282
void GetBoundingBox(Vector &min, Vector &max, int ref=2)
Returns the minimum and maximum corners of the mesh bounding box.
Definition mesh.cpp:138
int Dimension() const
Dimension of the reference space used within the elements.
Definition mesh.hpp:1216
void RandomRefinement(real_t prob, bool aniso=false, int nonconforming=-1, int nc_limit=0)
Refine each element with given probability. Uses GeneralRefinement.
Definition mesh.cpp:10975
void SetNodalGridFunction(GridFunction *nodes, bool make_owner=false)
Definition mesh.cpp:6473
void GetNodes(Vector &node_coord) const
Definition mesh.cpp:9294
virtual void SetNodalFESpace(FiniteElementSpace *nfes)
Definition mesh.cpp:6426
void EnsureNCMesh(bool simplices_nonconforming=false)
Definition mesh.cpp:10951
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
Definition mesh.cpp:11295
Arbitrary order H(curl)-conforming Nedelec finite elements.
Definition fe_coll.hpp:482
void Parse()
Parse the command-line options. Note that this function expects all the options provided through the ...
void PrintUsage(std::ostream &out) const
Print the usage message.
void PrintOptions(std::ostream &out) const
Print the options.
void AddOption(bool *var, const char *enable_short_name, const char *enable_long_name, const char *disable_short_name, const char *disable_long_name, const char *description, bool required=false)
Add a boolean option and set 'var' to receive the value. Enable/disable tags are used to set the bool...
Definition optparser.hpp:82
bool Good() const
Return true if the command line options were parsed successfully.
Arbitrary order H(div)-conforming Raviart-Thomas finite elements.
Definition fe_coll.hpp:403
A general vector function coefficient.
Vector data type.
Definition vector.hpp:82
int Size() const
Returns the size of the vector.
Definition vector.hpp:226
int dim
Definition ex24.cpp:53
double field_func(const Vector &x)
Definition findpts.cpp:76
double func_order
Definition findpts.cpp:73
void F_exact(const Vector &p, Vector &F)
Definition findpts.cpp:84
void VisualizeFESpacePolynomialOrder(FiniteElementSpace &fespace, const char *title, int locx)
Definition findpts.cpp:55
int main()
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)
real_t p(const Vector &x, real_t t)