MFEM v4.8.0
Finite element discretization library
Loading...
Searching...
No Matches
trimmer.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// Trimmer Miniapp: Trim away elements according to their attribute numbers
14// ------------------------------------------------------------------------
15//
16// This miniapp creates a new mesh consisting of all the elements not possessing
17// a given set of attribute numbers. The new boundary elements are created with
18// boundary attribute numbers related to the trimmed elements' attribute
19// numbers.
20//
21// By default the new boundary elements will have new attribute numbers so as
22// not to interfere with existing boundaries. For example, consider a mesh with
23// attributes given by:
24//
25// attributes = {a1, a2, a3, a4, a5, a6, ..., amax}
26// bdr_attributes = {b1, b2, ..., bmax}
27//
28// If we trim away elements with attributes a2 and a4 the new mesh will have
29// attributes:
30//
31// attributes: {a1, a3, a5, a6, ..., amax}
32// bdr_attributes = {b1, b2, ..., bmax, bmax + a2, bmax + a4}
33//
34// The user has the option of providing new attribute numbers for each group of
35// elements to be trimmed. In this case the new boundary elements may have the
36// same attribute numbers as existing boundary elements.
37//
38// The resulting mesh is displayed with GLVis (unless explicitly disabled) and
39// is also written to the file "trimmer.mesh"
40//
41// Compile with: make trimmer
42//
43// Sample runs: trimmer -a '2' -b '2'
44// trimmer -m ../../data/beam-hex.mesh -a '2'
45// trimmer -m ../../data/beam-hex.mesh -a '2' -b '2'
46
47#include "mfem.hpp"
48#include <fstream>
49#include <iostream>
50
51using namespace std;
52using namespace mfem;
53
54int main(int argc, char *argv[])
55{
56 // Parse command-line options.
57 const char *mesh_file = "../../data/beam-tet.vtk";
58 Array<int> attr;
59 Array<int> bdr_attr;
60 int visport = 19916;
61 bool visualization = 1;
62
63 OptionsParser args(argc, argv);
64 args.AddOption(&mesh_file, "-m", "--mesh",
65 "Mesh file to use.");
66 args.AddOption(&attr, "-a", "--attr",
67 "Set of attributes to remove from the mesh.");
68 args.AddOption(&bdr_attr, "-b", "--bdr-attr",
69 "Set of attributes to assign to the new boundary elements.");
70 args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
71 "--no-visualization",
72 "Enable or disable GLVis visualization.");
73 args.AddOption(&visport, "-p", "--send-port", "Socket for GLVis.");
74 args.Parse();
75 if (!args.Good())
76 {
77 args.PrintUsage(cout);
78 return 1;
79 }
80 args.PrintOptions(cout);
81
82 Mesh mesh(mesh_file, 0, 0);
83
84 int max_attr = mesh.attributes.Max();
85 int max_bdr_attr = mesh.bdr_attributes.Max();
86
87 if (bdr_attr.Size() == 0)
88 {
89 bdr_attr.SetSize(attr.Size());
90 for (int i=0; i<attr.Size(); i++)
91 {
92 bdr_attr[i] = max_bdr_attr + attr[i];
93 }
94 }
95 MFEM_VERIFY(attr.Size() == bdr_attr.Size(),
96 "Size mismatch in attribute arguments.");
97
98 Array<int> marker(max_attr);
99 Array<int> attr_inv(max_attr);
100 marker = 0;
101 attr_inv = 0;
102 for (int i=0; i<attr.Size(); i++)
103 {
104 marker[attr[i]-1] = 1;
105 attr_inv[attr[i]-1] = i;
106 }
107
108 // Count the number of elements in the final mesh
109 int num_elements = 0;
110 for (int e=0; e<mesh.GetNE(); e++)
111 {
112 int elem_attr = mesh.GetElement(e)->GetAttribute();
113 if (!marker[elem_attr-1]) { num_elements++; }
114 }
115
116 // Count the number of boundary elements in the final mesh
117 int num_bdr_elements = 0;
118 for (int f=0; f<mesh.GetNumFaces(); f++)
119 {
120 int e1 = -1, e2 = -1;
121 mesh.GetFaceElements(f, &e1, &e2);
122
123 int a1 = 0, a2 = 0;
124 if (e1 >= 0) { a1 = mesh.GetElement(e1)->GetAttribute(); }
125 if (e2 >= 0) { a2 = mesh.GetElement(e2)->GetAttribute(); }
126
127 if (a1 == 0 || a2 == 0)
128 {
129 if (a1 == 0 && !marker[a2-1]) { num_bdr_elements++; }
130 else if (a2 == 0 && !marker[a1-1]) { num_bdr_elements++; }
131 }
132 else
133 {
134 if (marker[a1-1] && !marker[a2-1]) { num_bdr_elements++; }
135 else if (!marker[a1-1] && marker[a2-1]) { num_bdr_elements++; }
136 }
137 }
138
139 cout << "Number of Elements: " << mesh.GetNE() << " -> "
140 << num_elements << endl;
141 cout << "Number of Boundary Elements: " << mesh.GetNBE() << " -> "
142 << num_bdr_elements << endl;
143
144 Mesh trimmed_mesh(mesh.Dimension(), mesh.GetNV(),
145 num_elements, num_bdr_elements, mesh.SpaceDimension());
146
147 // Copy vertices
148 for (int v=0; v<mesh.GetNV(); v++)
149 {
150 trimmed_mesh.AddVertex(mesh.GetVertex(v));
151 }
152
153 // Copy elements
154 for (int e=0; e<mesh.GetNE(); e++)
155 {
156 Element * el = mesh.GetElement(e);
157 int elem_attr = el->GetAttribute();
158 if (!marker[elem_attr-1])
159 {
160 Element * nel = mesh.NewElement(el->GetGeometryType());
161 nel->SetAttribute(elem_attr);
162 nel->SetVertices(el->GetVertices());
163 trimmed_mesh.AddElement(nel);
164 }
165 }
166
167 // Copy selected boundary elements
168 for (int be=0; be<mesh.GetNBE(); be++)
169 {
170 int e, info;
171 mesh.GetBdrElementAdjacentElement(be, e, info);
172
173 int elem_attr = mesh.GetElement(e)->GetAttribute();
174 if (!marker[elem_attr-1])
175 {
176 Element * nbel = mesh.GetBdrElement(be)->Duplicate(&trimmed_mesh);
177 trimmed_mesh.AddBdrElement(nbel);
178 }
179 }
180
181 // Create new boundary elements
182 for (int f=0; f<mesh.GetNumFaces(); f++)
183 {
184 int e1 = -1, e2 = -1;
185 mesh.GetFaceElements(f, &e1, &e2);
186
187 int i1 = -1, i2 = -1;
188 mesh.GetFaceInfos(f, &i1, &i2);
189
190 int a1 = 0, a2 = 0;
191 if (e1 >= 0) { a1 = mesh.GetElement(e1)->GetAttribute(); }
192 if (e2 >= 0) { a2 = mesh.GetElement(e2)->GetAttribute(); }
193
194 if (a1 != 0 && a2 != 0)
195 {
196 if (marker[a1-1] && !marker[a2-1])
197 {
198 Element * bel = (mesh.Dimension() == 1) ?
199 (Element*)new Point(&f) :
200 mesh.GetFace(f)->Duplicate(&trimmed_mesh);
201 bel->SetAttribute(bdr_attr[attr_inv[a1-1]]);
202 trimmed_mesh.AddBdrElement(bel);
203 }
204 else if (!marker[a1-1] && marker[a2-1])
205 {
206 Element * bel = (mesh.Dimension() == 1) ?
207 (Element*)new Point(&f) :
208 mesh.GetFace(f)->Duplicate(&trimmed_mesh);
209 bel->SetAttribute(bdr_attr[attr_inv[a2-1]]);
210 trimmed_mesh.AddBdrElement(bel);
211 }
212 }
213 }
214
215 trimmed_mesh.FinalizeTopology();
216 trimmed_mesh.Finalize();
217 trimmed_mesh.RemoveUnusedVertices();
218
219 // Check for curved or discontinuous mesh
220 if (mesh.GetNodes())
221 {
222 // Extract Nodes GridFunction and determine its type
223 const GridFunction * Nodes = mesh.GetNodes();
224 const FiniteElementSpace * fes = Nodes->FESpace();
225
226 Ordering::Type ordering = fes->GetOrdering();
227 int order = fes->FEColl()->GetOrder();
228 int sdim = mesh.SpaceDimension();
229 bool discont =
230 dynamic_cast<const L2_FECollection*>(fes->FEColl()) != NULL;
231
232 // Set curvature of the same type as original mesh
233 trimmed_mesh.SetCurvature(order, discont, sdim, ordering);
234
235 const FiniteElementSpace * trimmed_fes = trimmed_mesh.GetNodalFESpace();
236 GridFunction * trimmed_nodes = trimmed_mesh.GetNodes();
237
238 Array<int> vdofs;
239 Array<int> trimmed_vdofs;
240 Vector loc_vec;
241
242 // Copy nodes to trimmed mesh
243 int te = 0;
244 for (int e = 0; e < mesh.GetNE(); e++)
245 {
246 Element * el = mesh.GetElement(e);
247 int elem_attr = el->GetAttribute();
248 if (!marker[elem_attr-1])
249 {
250 fes->GetElementVDofs(e, vdofs);
251 Nodes->GetSubVector(vdofs, loc_vec);
252
253 trimmed_fes->GetElementVDofs(te, trimmed_vdofs);
254 trimmed_nodes->SetSubVector(trimmed_vdofs, loc_vec);
255 te++;
256 }
257 }
258 }
259
260 // Save the final mesh
261 ofstream mesh_ofs("trimmer.mesh");
262 mesh_ofs.precision(8);
263 trimmed_mesh.Print(mesh_ofs);
264
265 if (visualization)
266 {
267 // GLVis server to visualize to
268 char vishost[] = "localhost";
269 socketstream sol_sock(vishost, visport);
270 sol_sock.precision(8);
271 sol_sock << "mesh\n" << trimmed_mesh << flush;
272 }
273}
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
Definition array.cpp:68
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
Definition array.hpp:758
int Size() const
Return the logical size of the array.
Definition array.hpp:147
Abstract data type element.
Definition element.hpp:29
Geometry::Type GetGeometryType() const
Definition element.hpp:55
virtual Element * Duplicate(Mesh *m) const =0
virtual void GetVertices(Array< int > &v) const =0
Get the indices defining the vertices.
void SetAttribute(const int attr)
Set element's attribute.
Definition element.hpp:61
int GetAttribute() const
Return element's attribute.
Definition element.hpp:58
virtual void SetVertices(const Array< int > &v)=0
Set the indices defining the vertices.
int GetOrder() const
Return the order (polynomial degree) of the FE collection, corresponding to the order/degree returned...
Definition fe_coll.hpp:240
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition fespace.hpp:244
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
Ordering::Type GetOrdering() const
Return the ordering method.
Definition fespace.hpp:876
const FiniteElementCollection * FEColl() const
Definition fespace.hpp:878
Class for grid function - Vector with associated FE space.
Definition gridfunc.hpp:31
FiniteElementSpace * FESpace()
Arbitrary order "L2-conforming" discontinuous finite elements.
Definition fe_coll.hpp:346
Mesh data type.
Definition mesh.hpp:64
Element * NewElement(int geom)
Definition mesh.cpp:4672
int AddBdrElement(Element *elem)
Definition mesh.cpp:2243
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
Definition mesh.hpp:290
void GetFaceInfos(int Face, int *Inf1, int *Inf2) const
Definition mesh.cpp:1463
int GetNumFaces() const
Return the number of faces (3D), edges (2D) or vertices (1D).
Definition mesh.cpp:6531
const FiniteElementSpace * GetNodalFESpace() const
Definition mesh.cpp:6479
const Element * GetElement(int i) const
Return pointer to the i'th element object.
Definition mesh.hpp:1339
void FinalizeTopology(bool generate_bdr=true)
Finalize the construction of the secondary topology (connectivity) data of a Mesh.
Definition mesh.cpp:3362
virtual void Print(std::ostream &os=mfem::out, const std::string &comments="") const
Definition mesh.hpp:2433
int AddVertex(real_t x, real_t y=0.0, real_t z=0.0)
Definition mesh.cpp:1873
int GetNE() const
Returns number of elements.
Definition mesh.hpp:1282
const Element * GetFace(int i) const
Return pointer to the i'th face element object.
Definition mesh.hpp:1366
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
int AddElement(Element *elem)
Definition mesh.cpp:2236
void GetFaceElements(int Face, int *Elem1, int *Elem2) const
Definition mesh.cpp:1457
int SpaceDimension() const
Dimension of the physical space containing the mesh.
Definition mesh.hpp:1219
void GetNodes(Vector &node_coord) const
Definition mesh.cpp:9294
int GetNV() const
Returns number of vertices. Vertices are only at the corners of elements, where you would expect them...
Definition mesh.hpp:1279
void GetBdrElementAdjacentElement(int bdr_el, int &el, int &info) const
For the given boundary element, bdr_el, return its adjacent element and its info, i....
Definition mesh.cpp:7584
int GetNBE() const
Returns number of boundary elements.
Definition mesh.hpp:1285
virtual void Finalize(bool refine=false, bool fix_orientation=false)
Finalize the construction of a general Mesh.
Definition mesh.cpp:3468
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
Array< int > attributes
A list of all unique element attributes used by the Mesh.
Definition mesh.hpp:288
const real_t * GetVertex(int i) const
Return pointer to vertex i's coordinates.
Definition mesh.hpp:1321
void RemoveUnusedVertices()
Remove unused vertices and rebuild mesh connectivity.
Definition mesh.cpp:13197
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.
Type
Ordering methods:
Definition fespace.hpp:34
Data type point element.
Definition point.hpp:23
Vector data type.
Definition vector.hpp:82
void SetSubVector(const Array< int > &dofs, const real_t value)
Set the entries listed in dofs to the given value.
Definition vector.cpp:679
void GetSubVector(const Array< int > &dofs, Vector &elemvect) const
Extract entries listed in dofs to the output Vector elemvect.
Definition vector.cpp:653
int main()
std::function< real_t(const Vector &)> f(real_t mass_coeff)
Definition lor_mms.hpp:30
const char vishost[]