MFEM v4.8.0
Finite element discretization library
Loading...
Searching...
No Matches
fit-node-position.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// Fitting of Selected Mesh Nodes to Specified Physical Positions
14// ------------------------------------------------------------------
15//
16// This example fits a selected set of the mesh nodes to given physical
17// positions while maintaining a valid mesh with good quality.
18//
19// Sample runs:
20// mpirun -np 4 fit-node-position
21// mpirun -np 4 fit-node-position -m square01-tri.mesh
22// mpirun -np 4 fit-node-position -m ./cube.mesh
23// mpirun -np 4 fit-node-position -m ./cube-tet.mesh -rs 0
24
25#include "mfem.hpp"
27
28using namespace mfem;
29using namespace std;
30
31char vishost[] = "localhost";
32int wsize = 350;
33
34int main (int argc, char *argv[])
35{
36 // Initialize MPI.
37 Mpi::Init();
38 int myid = Mpi::WorldRank();
39
40 const char *mesh_file = "square01.mesh";
41 int rs_levels = 2;
42 int mesh_poly_deg = 2;
43 int quad_order = 5;
44 bool glvis = true;
45 int visport = 19916;
46
47 // Parse command-line options.
48 OptionsParser args(argc, argv);
49 args.AddOption(&mesh_file, "-m", "--mesh",
50 "Mesh file to use.");
51 args.AddOption(&rs_levels, "-rs", "--refine-serial",
52 "Number of times to refine the mesh uniformly in serial.");
53 args.AddOption(&mesh_poly_deg, "-o", "--order",
54 "Polynomial degree of mesh finite element space.");
55 args.AddOption(&quad_order, "-qo", "--quad_order",
56 "Order of the quadrature rule.");
57 args.AddOption(&glvis, "-vis", "--visualization", "-no-vis",
58 "--no-visualization",
59 "Enable or disable GLVis visualization.");
60 args.AddOption(&visport, "-p", "--send-port", "Socket for GLVis.");
61 args.Parse();
62 if (!args.Good())
63 {
64 if (myid == 0) { args.PrintUsage(cout); }
65 return 1;
66 }
67 if (myid == 0) { args.PrintOptions(cout); }
68
69 // Read and refine the mesh.
70 Mesh *mesh = new Mesh(mesh_file, 1, 1, false);
71 for (int lev = 0; lev < rs_levels; lev++) { mesh->UniformRefinement(); }
72 ParMesh pmesh(MPI_COMM_WORLD, *mesh);
73 delete mesh;
74 const int dim = pmesh.Dimension();
75
76 // Setup mesh curvature and GridFunction that stores the coordinates.
78 if (mesh_poly_deg <= 0)
79 {
80 fec_mesh = new QuadraticPosFECollection;
81 mesh_poly_deg = 2;
82 }
83 else { fec_mesh = new H1_FECollection(mesh_poly_deg, dim); }
84 ParFiniteElementSpace pfes_mesh(&pmesh, fec_mesh, dim);
85 pmesh.SetNodalFESpace(&pfes_mesh);
86 ParGridFunction coord(&pfes_mesh);
87 pmesh.SetNodalGridFunction(&coord);
88 ParGridFunction x0(coord);
89
90 // Pick which nodes to fit and select the target positions.
91 // (attribute 2 would have a prescribed deformation in y-direction, same x).
92 Array<bool> fit_marker(pfes_mesh.GetNDofs());
93 ParGridFunction fit_marker_vis_gf(&pfes_mesh);
94 ParGridFunction coord_target(&pfes_mesh);
95 Array<int> vdofs;
96 fit_marker = false;
97 coord_target = coord;
98 fit_marker_vis_gf = 0.0;
99 for (int e = 0; e < pmesh.GetNBE(); e++)
100 {
101 const int nd = pfes_mesh.GetBE(e)->GetDof();
102 const int attr = pmesh.GetBdrElement(e)->GetAttribute();
103 if (attr != 2) { continue; }
104
105 pfes_mesh.GetBdrElementVDofs(e, vdofs);
106 for (int j = 0; j < nd; j++)
107 {
108 int j_x = vdofs[j], j_y = vdofs[nd+j];
109 const real_t x = coord(j_x),
110 z = (dim == 2) ? 0.0 : coord(vdofs[2*nd + j]);
111 fit_marker[pfes_mesh.VDofToDof(j_x)] = true;
112 fit_marker_vis_gf(j_x) = 1.0;
113 if (coord(j_y) < 0.5)
114 {
115 coord_target(j_y) = 0.1 * sin(4 * M_PI * x) * cos(M_PI * z);
116 }
117 else
118 {
119 if (coord(j_x) < 0.5)
120 {
121 coord_target(j_y) = 1.0 + 0.1 * sin(2 * M_PI * x);
122 }
123 else
124 {
125 coord_target(j_y) = 1.0 + 0.1 * sin(2 * M_PI * (x + 0.5));
126 }
127
128 }
129 }
130 }
131
132 // Visualize the selected nodes and their target positions.
133 if (glvis)
134 {
135 socketstream vis1;
136 coord = coord_target;
137 common::VisualizeField(vis1, "localhost", 19916, fit_marker_vis_gf,
138 "Target positions (DOFS with value 1)",
139 0, 0, 400, 400, (dim == 2) ? "Rjm" : "");
140 coord = x0;
141 }
142
143 // Allow slipping along the remaining boundaries.
144 // (attributes 1 and 3 would slip, while 4 is completely fixed).
145 int n = 0;
146 for (int i = 0; i < pmesh.GetNBE(); i++)
147 {
148 const int nd = pfes_mesh.GetBE(i)->GetDof();
149 const int attr = pmesh.GetBdrElement(i)->GetAttribute();
150 MFEM_VERIFY(!(dim == 2 && attr == 3),
151 "Boundary attribute 3 must be used only for 3D meshes. "
152 "Adjust the attributes (1/2/3/4 for fixed x/y/z/all "
153 "components, rest for free nodes), or use -fix-bnd.");
154 if (attr == 1 || attr == 3) { n += nd; }
155 if (attr == 4) { n += nd * dim; }
156 }
157 Array<int> ess_vdofs(n);
158 n = 0;
159 for (int i = 0; i < pmesh.GetNBE(); i++)
160 {
161 const int nd = pfes_mesh.GetBE(i)->GetDof();
162 const int attr = pmesh.GetBdrElement(i)->GetAttribute();
163 pfes_mesh.GetBdrElementVDofs(i, vdofs);
164 if (attr == 1) // Fix x components.
165 {
166 for (int j = 0; j < nd; j++)
167 { ess_vdofs[n++] = vdofs[j]; }
168 }
169 else if (attr == 3) // Fix z components.
170 {
171 for (int j = 0; j < nd; j++)
172 { ess_vdofs[n++] = vdofs[j+2*nd]; }
173 }
174 else if (attr == 4) // Fix all components.
175 {
176 for (int j = 0; j < vdofs.Size(); j++)
177 { ess_vdofs[n++] = vdofs[j]; }
178 }
179 }
180
181 // TMOP setup.
182 TMOP_QualityMetric *metric;
183 if (dim == 2) { metric = new TMOP_Metric_002; }
184 else { metric = new TMOP_Metric_302; }
186 pfes_mesh.GetComm());
187 ConstantCoefficient fit_weight(100.0);
188 auto integ = new TMOP_Integrator(metric, &target, nullptr);
189 integ->EnableSurfaceFitting(coord_target, fit_marker, fit_weight);
190
191 // Linear solver.
192 MINRESSolver minres(pfes_mesh.GetComm());
193 minres.SetMaxIter(100);
194 minres.SetRelTol(1e-12);
195 minres.SetAbsTol(0.0);
196
197 // Nonlinear solver.
198 ParNonlinearForm a(&pfes_mesh);
199 a.SetEssentialVDofs(ess_vdofs);
200 a.AddDomainIntegrator(integ);
201 const IntegrationRule &ir =
202 IntRules.Get(pmesh.GetTypicalElementGeometry(), quad_order);
203 TMOPNewtonSolver solver(pfes_mesh.GetComm(), ir, 0);
204 solver.SetOperator(a);
205 solver.SetPreconditioner(minres);
206 solver.SetPrintLevel(1);
207 solver.SetMaxIter(200);
208 solver.SetRelTol(1e-10);
209 solver.SetAbsTol(0.0);
212
213 // Solve.
214 Vector b(0);
215 coord.SetTrueVector();
216 solver.Mult(b, coord.GetTrueVector());
217 coord.SetFromTrueVector();
218
219 if (glvis)
220 {
221 socketstream vis2;
222 common::VisualizeMesh(vis2, "localhost", 19916, pmesh, "Final mesh",
223 400, 0, 400, 400);
224 }
225
226 delete metric;
227 return 0;
228}
int Size() const
Return the logical size of the array.
Definition array.hpp:147
A coefficient that is constant across space and time.
int GetAttribute() const
Return element's attribute.
Definition element.hpp:58
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
Definition fe_coll.hpp:27
const FiniteElement * GetBE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th boundary fac...
Definition fespace.cpp:3881
int GetNDofs() const
Returns number of degrees of freedom. This is the number of Local Degrees of Freedom.
Definition fespace.hpp:845
int VDofToDof(int vdof) const
Compute the inverse of the Dof to VDof mapping for a single index vdof.
Definition fespace.hpp:1146
DofTransformation * GetBdrElementVDofs(int i, Array< int > &vdofs) const
Returns indices of degrees of freedom for i'th boundary element. The returned indices are offsets int...
Definition fespace.cpp:348
int GetDof() const
Returns the number of degrees of freedom in the finite element.
Definition fe_base.hpp:334
void SetTrueVector()
Shortcut for calling GetTrueDofs() with GetTrueVector() as argument.
Definition gridfunc.hpp:147
void SetFromTrueVector()
Shortcut for calling SetFromTrueDofs() with GetTrueVector() as argument.
Definition gridfunc.hpp:153
const Vector & GetTrueVector() const
Read only access to the (optional) internal true-dof Vector.
Definition gridfunc.hpp:133
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
const IntegrationRule & Get(int GeomType, int Order)
Returns an integration rule for given GeomType and Order.
void SetRelTol(real_t rtol)
Definition solvers.hpp:229
virtual void SetPrintLevel(int print_lvl)
Legacy method to set the level of verbosity of the solver output.
Definition solvers.cpp:72
void SetMaxIter(int max_it)
Definition solvers.hpp:231
void SetAbsTol(real_t atol)
Definition solvers.hpp:230
void SetOperator(const Operator &op) override
Also calls SetOperator for the preconditioner if there is one.
Definition solvers.hpp:812
MINRES method.
Definition solvers.hpp:653
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 Dimension() const
Dimension of the reference space used within the elements.
Definition mesh.hpp:1216
const Element * GetBdrElement(int i) const
Return pointer to the i'th boundary element object.
Definition mesh.hpp:1354
void SetNodalGridFunction(GridFunction *nodes, bool make_owner=false)
Definition mesh.cpp:6473
int GetNBE() const
Returns number of boundary elements.
Definition mesh.hpp:1285
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
Definition mesh.cpp:11295
static int WorldRank()
Return the MPI rank in MPI_COMM_WORLD.
static void Init(int &argc, char **&argv, int required=default_thread_required, int *provided=nullptr)
Singleton creation with Mpi::Init(argc, argv).
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.
Abstract parallel finite element space.
Definition pfespace.hpp:29
MPI_Comm GetComm() const
Definition pfespace.hpp:334
Class for parallel grid function.
Definition pgridfunc.hpp:50
Class for parallel meshes.
Definition pmesh.hpp:34
void SetNodalFESpace(FiniteElementSpace *nfes) override
Definition pmesh.cpp:2027
Parallel non-linear operator on the true dofs.
Version of QuadraticFECollection with positive basis functions.
Definition fe_coll.hpp:918
void SetAdaptiveSurfaceFittingScalingFactor(real_t factor)
void Mult(const Vector &b, Vector &x) const override
Optimizes the mesh positions given by x.
void SetPreconditioner(Solver &pr) override
This should be called before SetOperator.
void SetTerminationWithMaxSurfaceFittingError(real_t max_error)
Used for error-based surface fitting termination.
A TMOP integrator class based on any given TMOP_QualityMetric and TargetConstructor.
Definition tmop.hpp:1885
3D barrier Shape (S) metric, well-posed (polyconvex & invex).
Definition tmop.hpp:720
Abstract class for local mesh quality metrics in the target-matrix optimization paradigm (TMOP) by P....
Definition tmop.hpp:24
Base class representing target-matrix construction algorithms for mesh optimization via the target-ma...
Definition tmop.hpp:1481
Vector data type.
Definition vector.hpp:82
int dim
Definition ex24.cpp:53
int wsize
char vishost[]
int main()
real_t b
Definition lissajous.cpp:42
real_t a
Definition lissajous.cpp:41
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 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)
float real_t
Definition config.hpp:43
IntegrationRules IntRules(0, Quadrature1D::GaussLegendre)
A global object with all integration rules (defined in intrules.cpp)
Definition intrules.hpp:492