MFEM v4.8.0
Finite element discretization library
Loading...
Searching...
No Matches
field-interp.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// Field Interp Miniapp: Transfer a grid function between meshes
14// -------------------------------------------------------------
15//
16// This miniapp provides the capability to transfer a grid function (H1, L2,
17// H(div), and H(curl)) from one mesh onto another using GSLIB-FindPoints. Using
18// FindPoints, we identify the nodal positions of the target mesh with respect
19// to the source mesh and then interpolate the source grid function. The
20// interpolated values are then projected onto the desired finite element space
21// on the target mesh. Finally, the transferred solution is visualized using
22// GLVis. Note that the source grid function can be a user-defined vector
23// function or a grid function file that is compatible with the source mesh.
24//
25// Compile with: make field-interp
26//
27// Sample runs:
28// field-interp
29// field-interp -o 1
30// field-interp -fts 3 -ft 0
31// field-interp -m1 triple-pt-1.mesh -s1 triple-pt-1.gf -m2 triple-pt-2.mesh -ft 1
32// field-interp -m1 triple-pt-1.mesh -m2 triple-pt-2.mesh -ft 1
33// field-interp -m2 ../meshing/amr-quad-q2.mesh -ft 0 -r 1 -fts 0
34
35#include "mfem.hpp"
36#include <fstream>
37
38using namespace mfem;
39using namespace std;
40
41// Scalar function to project
42double scalar_func(const Vector &x)
43{
44 const int dim = x.Size();
45 double res = 0.0;
46 for (int d = 0; d < dim; d++) { res += x(d) * x(d); }
47 return res;
48}
49
50void vector_func(const Vector &p, Vector &F)
51{
52 F(0) = scalar_func(p);
53 for (int i = 1; i < F.Size(); i++) { F(i) = (i+1)*pow(-1, i)*F(0); }
54}
55
56int main (int argc, char *argv[])
57{
58 // Set the method's default parameters.
59 const char *src_mesh_file = "../meshing/square01.mesh";
60 const char *tar_mesh_file = "../../data/inline-tri.mesh";
61 const char *src_sltn_file = "must_be_provided_by_the_user.gf";
62 int src_fieldtype = 0;
63 int src_ncomp = 1;
64 int src_gf_ordering = 0;
65 int ref_levels = 0;
66 int fieldtype = -1;
67 int order = 3;
68 bool visualization = true;
69 int visport = 19916;
70
71 // Parse command-line options.
72 OptionsParser args(argc, argv);
73 args.AddOption(&src_mesh_file, "-m1", "--mesh1",
74 "Mesh file for the starting solution.");
75 args.AddOption(&tar_mesh_file, "-m2", "--mesh2",
76 "Mesh file for interpolation.");
77 args.AddOption(&src_sltn_file, "-s1", "--solution1",
78 "(optional) GridFunction file compatible with src_mesh_file."
79 "Set src_fieldtype to -1 if this option is used.");
80 args.AddOption(&src_fieldtype, "-fts", "--field-type-src",
81 "Source GridFunction type:"
82 "0 - H1 (default), 1 - L2, 2 - H(div), 3 - H(curl).");
83 args.AddOption(&src_ncomp, "-nc", "--ncomp",
84 "Number of components for H1 or L2 GridFunctions.");
85 args.AddOption(&src_gf_ordering, "-gfo", "--gfo",
86 "Node ordering: 0 (byNodes) or 1 (byVDim)");
87 args.AddOption(&ref_levels, "-r", "--refine",
88 "Number of refinements of the interpolation mesh.");
89 args.AddOption(&fieldtype, "-ft", "--field-type",
90 "Target GridFunction type: -1 - source GridFunction type (default),"
91 "0 - H1, 1 - L2, 2 - H(div), 3 - H(curl).");
92 args.AddOption(&order, "-o", "--order",
93 "Order of the interpolated solution.");
94 args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
95 "--no-visualization",
96 "Enable or disable GLVis visualization.");
97 args.AddOption(&visport, "-p", "--send-port", "Socket for GLVis.");
98 args.Parse();
99 if (!args.Good())
100 {
101 args.PrintUsage(cout);
102 return 1;
103 }
104 args.PrintOptions(cout);
105
106 // If a grid function is specified, set src_fieldtype to -1
107 if (strcmp(src_sltn_file, "must_be_provided_by_the_user.gf") != 0)
108 {
109 src_fieldtype = -1;
110 }
111
112 // Input meshes.
113 Mesh mesh_1(src_mesh_file, 1, 1, false);
114 Mesh mesh_2(tar_mesh_file, 1, 1, false);
115 const int dim = mesh_1.Dimension();
116 MFEM_ASSERT(dim == mesh_2.Dimension(), "Source and target meshes "
117 "must be in the same dimension.");
118 MFEM_VERIFY(dim > 1, "GSLIB requires a 2D or a 3D mesh" );
119
120 for (int lev = 0; lev < ref_levels; lev++)
121 {
122 mesh_2.UniformRefinement();
123 }
124
125 if (mesh_1.GetNodes() == NULL) { mesh_1.SetCurvature(1); }
126 if (mesh_2.GetNodes() == NULL) { mesh_2.SetCurvature(1); }
127 const int mesh_poly_deg =
128 mesh_2.GetNodes()->FESpace()->GetElementOrder(0);
129 cout << "Source mesh curvature: "
130 << mesh_1.GetNodes()->OwnFEC()->Name() << endl
131 << "Target mesh curvature: "
132 << mesh_2.GetNodes()->OwnFEC()->Name() << endl;
133
134 int src_vdim = src_ncomp;
135 FiniteElementCollection *src_fec = NULL;
136 FiniteElementSpace *src_fes = NULL;
137 GridFunction *func_source = NULL;
138 if (src_fieldtype < 0) // use src_sltn_file
139 {
140 ifstream mat_stream_1(src_sltn_file);
141 func_source = new GridFunction(&mesh_1, mat_stream_1);
142 src_vdim = func_source->FESpace()->GetVDim();
143 src_fes = func_source->FESpace();
144 }
145 else if (src_fieldtype == 0)
146 {
147 src_fec = new H1_FECollection(order, dim);
148 }
149 else if (src_fieldtype == 1)
150 {
151 src_fec = new L2_FECollection(order, dim);
152 }
153 else if (src_fieldtype == 2)
154 {
155 src_fec = new RT_FECollection(order, dim);
156 src_ncomp = 1;
157 src_vdim = dim;
158 }
159 else if (src_fieldtype == 3)
160 {
161 src_fec = new ND_FECollection(order, dim);
162 src_ncomp = 1;
163 src_vdim = dim;
164 }
165 else
166 {
167 MFEM_ABORT("Invalid FECollection type.");
168 }
169
170 if (src_fieldtype > -1)
171 {
172 MFEM_VERIFY(src_gf_ordering >= 0 && src_gf_ordering <= 1,
173 " Source grid function ordering must be 0 (byNodes)"
174 " or 1 (byVDIM.");
175 src_fes = new FiniteElementSpace(&mesh_1, src_fec, src_ncomp, src_gf_ordering);
176 func_source = new GridFunction(src_fes);
177 // Project the grid function using VectorFunctionCoefficient.
179 func_source->ProjectCoefficient(F);
180 }
181
182 // Display the starting mesh and the field.
183 if (visualization)
184 {
185 char vishost[] = "localhost";
186 socketstream sout1;
187 sout1.open(vishost, visport);
188 if (!sout1)
189 {
190 cout << "Unable to connect to GLVis server at "
191 << vishost << ':' << visport << endl;
192 }
193 else
194 {
195 sout1.precision(8);
196 sout1 << "solution\n" << mesh_1 << *func_source
197 << "window_title 'Source mesh and solution'"
198 << "window_geometry 0 0 600 600";
199 if (dim == 2) { sout1 << "keys RmjAc"; }
200 if (dim == 3) { sout1 << "keys mA\n"; }
201 sout1 << flush;
202 }
203 }
204
205 const Geometry::Type gt = mesh_2.GetTypicalElementGeometry();
206 MFEM_VERIFY(gt != Geometry::PRISM, "Wedge elements are not currently "
207 "supported.");
208 MFEM_VERIFY(mesh_2.GetNumGeometries(mesh_2.Dimension()) == 1, "Mixed meshes"
209 "are not currently supported.");
210
211 // Ensure the source grid function can be transferred using GSLIB-FindPoints.
212 const FiniteElementCollection *fec_in = func_source->FESpace()->FEColl();
213 std::cout << "Source FE collection: " << fec_in->Name() << std::endl;
214
215 if (src_fieldtype < 0)
216 {
217 const H1_FECollection *fec_h1 = dynamic_cast<const H1_FECollection *>(fec_in);
218 const L2_FECollection *fec_l2 = dynamic_cast<const L2_FECollection *>(fec_in);
219 const RT_FECollection *fec_rt = dynamic_cast<const RT_FECollection *>(fec_in);
220 const ND_FECollection *fec_nd = dynamic_cast<const ND_FECollection *>(fec_in);
221 if (fec_h1) { src_fieldtype = 0; }
222 else if (fec_l2) { src_fieldtype = 1; }
223 else if (fec_rt) { src_fieldtype = 2; }
224 else if (fec_nd) { src_fieldtype = 3; }
225 else { MFEM_ABORT("GridFunction type not supported yet."); }
226 }
227 if (fieldtype < 0) { fieldtype = src_fieldtype; }
228
229 // Setup the FiniteElementSpace and GridFunction on the target mesh.
230 FiniteElementCollection *tar_fec = NULL;
231 FiniteElementSpace *tar_fes = NULL;
232
233 int tar_vdim = src_vdim;
234 if (fieldtype == 0)
235 {
236 tar_fec = new H1_FECollection(order, dim);
237 tar_vdim = (src_fieldtype > 1) ? dim : src_vdim;
238 }
239 else if (fieldtype == 1)
240 {
241 tar_fec = new L2_FECollection(order, dim);
242 tar_vdim = (src_fieldtype > 1) ? dim : src_vdim;
243 }
244 else if (fieldtype == 2)
245 {
246 tar_fec = new RT_FECollection(order, dim);
247 tar_vdim = 1;
248 MFEM_VERIFY(src_fieldtype > 1, "Cannot interpolate a scalar "
249 "grid function to a vector");
250
251 }
252 else if (fieldtype == 3)
253 {
254 tar_fec = new ND_FECollection(order, dim);
255 tar_vdim = 1;
256 MFEM_VERIFY(src_fieldtype > 1, "Cannot interpolate a scalar "
257 "grid function to a vector");
258 }
259 else
260 {
261 MFEM_ABORT("GridFunction type not supported.");
262 }
263 std::cout << "Target FE collection: " << tar_fec->Name() << std::endl;
264 tar_fes = new FiniteElementSpace(&mesh_2, tar_fec, tar_vdim,
265 src_fes->GetOrdering());
266 GridFunction func_target(tar_fes);
267
268 const int NE = mesh_2.GetNE(),
269 nsp = tar_fes->GetTypicalFE()->GetNodes().GetNPoints(),
270 tar_ncomp = func_target.VectorDim();
271
272 // Generate list of points where the grid function will be evaluated.
273 Vector vxyz;
274 int point_ordering;
275 if (fieldtype == 0 && order == mesh_poly_deg)
276 {
277 vxyz = *mesh_2.GetNodes();
278 point_ordering = mesh_2.GetNodes()->FESpace()->GetOrdering();
279 }
280 else
281 {
282 vxyz.SetSize(nsp*NE*dim);
283 for (int i = 0; i < NE; i++)
284 {
285 const FiniteElement *fe = tar_fes->GetFE(i);
286 const IntegrationRule ir = fe->GetNodes();
288
289 DenseMatrix pos;
290 et->Transform(ir, pos);
291 Vector rowx(vxyz.GetData() + i*nsp, nsp),
292 rowy(vxyz.GetData() + i*nsp + NE*nsp, nsp),
293 rowz;
294 if (dim == 3)
295 {
296 rowz.SetDataAndSize(vxyz.GetData() + i*nsp + 2*NE*nsp, nsp);
297 }
298 pos.GetRow(0, rowx);
299 pos.GetRow(1, rowy);
300 if (dim == 3) { pos.GetRow(2, rowz); }
301 }
302 point_ordering = Ordering::byNODES;
303 }
304 const int nodes_cnt = vxyz.Size() / dim;
305
306 // Evaluate source grid function.
307 Vector interp_vals(nodes_cnt*tar_ncomp);
308 FindPointsGSLIB finder;
309 finder.Setup(mesh_1);
310 finder.Interpolate(vxyz, *func_source, interp_vals, point_ordering);
311
312 // Project the interpolated values to the target FiniteElementSpace.
313 if (fieldtype <= 1) // H1 or L2
314 {
315 if ((fieldtype == 0 && order == mesh_poly_deg) || fieldtype == 1)
316 {
317 func_target = interp_vals;
318 }
319 else // H1 - but mesh order != GridFunction order
320 {
321 Array<int> vdofs;
322 Vector vals;
323 Vector elem_dof_vals(nsp*tar_ncomp);
324
325 for (int i = 0; i < mesh_2.GetNE(); i++)
326 {
327 tar_fes->GetElementVDofs(i, vdofs);
328 vals.SetSize(vdofs.Size());
329 for (int j = 0; j < nsp; j++)
330 {
331 for (int d = 0; d < tar_ncomp; d++)
332 {
333 // Arrange values byNodes
334 int idx = src_fes->GetOrdering() == Ordering::byNODES ?
335 d*nsp*NE + i*nsp + j : i*nsp*dim + d + j*dim;
336 elem_dof_vals(j + d*nsp) = interp_vals(idx);
337 }
338 }
339 func_target.SetSubVector(vdofs, elem_dof_vals);
340 }
341 }
342 }
343 else // H(div) or H(curl)
344 {
345 Array<int> vdofs;
346 Vector vals;
347 Vector elem_dof_vals(nsp*tar_ncomp);
348
349 for (int i = 0; i < mesh_2.GetNE(); i++)
350 {
351 tar_fes->GetElementVDofs(i, vdofs);
352 vals.SetSize(vdofs.Size());
353 for (int j = 0; j < nsp; j++)
354 {
355 for (int d = 0; d < tar_ncomp; d++)
356 {
357 // Arrange values byVDim
358 int idx = src_fes->GetOrdering() == Ordering::byNODES ?
359 d*nsp*NE + i*nsp + j : i*nsp*dim + d + j*dim;
360 elem_dof_vals(j*tar_ncomp+d) = interp_vals(idx);
361 }
362 }
363 tar_fes->GetFE(i)->ProjectFromNodes(elem_dof_vals,
364 *tar_fes->GetElementTransformation(i),
365 vals);
366 func_target.SetSubVector(vdofs, vals);
367 }
368 }
369
370 // Visualize the transferred solution.
371 if (visualization)
372 {
373 char vishost[] = "localhost";
374 socketstream sout1;
375 sout1.open(vishost, visport);
376 if (!sout1)
377 {
378 cout << "Unable to connect to GLVis server at "
379 << vishost << ':' << visport << endl;
380 }
381 else
382 {
383 sout1.precision(8);
384 sout1 << "solution\n" << mesh_2 << func_target
385 << "window_title 'Target mesh and solution'"
386 << "window_geometry 600 0 600 600";
387 if (dim == 2) { sout1 << "keys RmjAc"; }
388 if (dim == 3) { sout1 << "keys mA\n"; }
389 sout1 << flush;
390 }
391 }
392
393 // Output the target mesh with the interpolated solution.
394 ostringstream rho_name;
395 rho_name << "interpolated.gf";
396 ofstream rho_ofs(rho_name.str().c_str());
397 rho_ofs.precision(8);
398 func_target.Save(rho_ofs);
399 rho_ofs.close();
400
401 // Free the internal gslib data.
402 finder.FreeData();
403
404 // Delete remaining memory.
405 if (func_source->OwnFEC())
406 {
407 delete func_source;
408 }
409 else
410 {
411 delete func_source;
412 delete src_fes;
413 delete src_fec;
414 }
415 delete tar_fes;
416 delete tar_fec;
417
418 return 0;
419}
int Size() const
Return the logical size of the array.
Definition array.hpp:147
Data type dense matrix using column-major storage.
Definition densemat.hpp:24
void GetRow(int r, Vector &row) const
virtual void Transform(const IntegrationPoint &, Vector &)=0
Transform integration point from reference coordinates to physical coordinates and store them in the ...
FindPointsGSLIB can robustly evaluate a GridFunction on an arbitrary collection of points.
Definition gslib.hpp:67
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 void FreeData()
Definition gslib.cpp:1128
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
Definition fe_coll.hpp:27
virtual const char * Name() const
Definition fe_coll.hpp:79
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition fespace.hpp:244
ElementTransformation * GetElementTransformation(int i) const
Returns ElementTransformation for the i-th element.
Definition fespace.hpp:924
DofTransformation * GetElementVDofs(int i, Array< int > &vdofs) const
Returns indices of degrees of freedom for the i'th element. The returned indices are offsets into an ...
Definition fespace.cpp:332
virtual const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th element in t...
Definition fespace.cpp:3835
Ordering::Type GetOrdering() const
Return the ordering method.
Definition fespace.hpp:876
const FiniteElementCollection * FEColl() const
Definition fespace.hpp:878
int GetVDim() const
Returns the vector dimension of the finite element space.
Definition fespace.hpp:841
const FiniteElement * GetTypicalFE() const
Return GetFE(0) if the local mesh is not empty; otherwise return a typical FE based on the Geometry t...
Definition fespace.cpp:3871
Abstract class for all finite elements.
Definition fe_base.hpp:244
virtual void ProjectFromNodes(Vector &vc, ElementTransformation &Trans, Vector &dofs) const
Given a vector of values at the finite element nodes and a transformation, compute its projection (ap...
Definition fe_base.cpp:138
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
FiniteElementCollection * OwnFEC()
Definition gridfunc.hpp:124
virtual void Save(std::ostream &out) const
Save the GridFunction to an output stream.
FiniteElementSpace * FESpace()
virtual void ProjectCoefficient(Coefficient &coeff)
Project coeff Coefficient to this GridFunction. The projection computation depends on the choice of t...
int VectorDim() const
Shortcut for calling FiniteElementSpace::GetVectorDim() on the underlying fes.
Definition gridfunc.cpp:353
Arbitrary order H1-conforming (continuous) finite elements.
Definition fe_coll.hpp:275
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
Arbitrary order "L2-conforming" discontinuous finite elements.
Definition fe_coll.hpp:346
Mesh data type.
Definition mesh.hpp:64
Geometry::Type GetTypicalElementGeometry() const
If the local mesh is not empty, return GetElementGeometry(0); otherwise, return a typical Geometry pr...
Definition mesh.cpp:1528
int GetNE() const
Returns number of elements.
Definition mesh.hpp:1282
int Dimension() const
Dimension of the reference space used within the elements.
Definition mesh.hpp:1216
void GetNodes(Vector &node_coord) const
Definition mesh.cpp:9294
int GetNumGeometries(int dim) const
Return the number of geometries of the given dimension present in the mesh.
Definition mesh.cpp:7243
virtual void SetCurvature(int order, bool discont=false, int space_dim=-1, int ordering=1)
Set the curvature of the mesh nodes using the given polynomial degree.
Definition mesh.cpp:6484
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
void SetDataAndSize(real_t *d, int s)
Set the Vector data and size.
Definition vector.hpp:183
void SetSubVector(const Array< int > &dofs, const real_t value)
Set the entries listed in dofs to the given value.
Definition vector.cpp:679
int Size() const
Returns the size of the vector.
Definition vector.hpp:226
void SetSize(int s)
Resize the vector to size s.
Definition vector.hpp:558
real_t * GetData() const
Return a pointer to the beginning of the Vector data.
Definition vector.hpp:235
int open(const char hostname[], int port)
Open the socket stream on 'port' at 'hostname'.
int dim
Definition ex24.cpp:53
double scalar_func(const Vector &x)
void vector_func(const Vector &p, Vector &F)
int main()
const char vishost[]
real_t p(const Vector &x, real_t t)