MFEM v4.10.0
Finite element discretization library
Loading...
Searching...
No Matches
ref321.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2026, 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// 3:1 Refinement Miniapp: Perform 3:1 anisotropic mesh refinements
14// -----------------------------------------------------------------
15//
16// This miniapp performs random 3:1 refinements of a quadrilateral or hexahedral
17// mesh. A diffusion equation is solved in an H1 finite element space defined on
18// the refined mesh, and its continuity is verified.
19//
20// Compile with: make ref321
21//
22// Sample runs: ref321 -mm -dim 2 -o 2 -r 100
23// ref321 -mm -dim 3 -o 2 -r 100
24// ref321 -m ../../data/star.mesh -o 2 -r 100
25
26#include "mfem.hpp"
27#include <fstream>
28#include <iostream>
29
30using namespace std;
31using namespace mfem;
32
34
35// Find the two children of parent element `elem` after its refinement in one
36// direction.
37void FindChildren(const Mesh & mesh, int elem, Array<int> & children)
38{
40 MFEM_ASSERT(mesh.GetNE() == cf.embeddings.Size(), "");
41
42 // Note that row `elem` of the table constructed by cf.MakeCoarseToFineTable
43 // is an alternative to this global loop, but constructing the table is also
44 // a global operation with global storage.
45 for (int i = 0; i < mesh.GetNE(); i++)
46 {
47 const int p = cf.embeddings[i].parent;
48 if (p == elem)
49 {
50 children.Append(i);
51 }
52 }
53}
54
55// Refine 3:1 via 2 refinements with scalings 2/3 and 1/2.
56void Refine31(Mesh & mesh, int elem, char type)
57{
58 Array<Refinement> refs; // Refinement is defined in ncmesh.hpp
59 refs.Append(Refinement(elem, type, 2.0 / 3.0));
60 mesh.GeneralRefinement(refs);
61
62 // Find the elements with parent `elem`
63 Array<int> children;
64 FindChildren(mesh, elem, children);
65 MFEM_ASSERT(children.Size() == 2, "");
66
67 const int elem1 = children[0];
68
69 refs.SetSize(0);
70 refs.Append(Refinement(elem1, type)); // Default scaling of 0.5
71 mesh.GeneralRefinement(refs);
72}
73
74// Randomly select elements for 3:1 refinements in random directions.
75void TestAnisoRefRandom(int num_refs, int dim, Mesh & mesh)
76{
77 std::mt19937 gen(1);
78 for (int i = 0; i < num_refs; i++)
79 {
80 const auto elem = gen() % mesh.GetNE();
81 const auto t = gen() % dim;
82 auto type = t == 0 ? Refinement::X :
83 (t == 1 ? Refinement::Y : Refinement::Z);
84 Refine31(mesh, elem, type);
85 }
86
87 mesh.EnsureNodes();
88 mesh.SetScaledNCMesh();
89}
90
91int main(int argc, char *argv[])
92{
93 // 1. Parse command-line options.
94 const char *mesh_file = "../../data/star.mesh";
95 int order = 1;
96 bool visualization = true;
97 bool makeMesh = false;
98 int num_refs = 1;
99 int tdim = 2; // Mesh dimension
100
101 OptionsParser args(argc, argv);
102 args.AddOption(&mesh_file, "-m", "--mesh",
103 "Mesh file to use.");
104 args.AddOption(&order, "-o", "--order",
105 "Finite element order (polynomial degree) or -1 for"
106 " isoparametric space.");
107 args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
108 "--no-visualization",
109 "Enable or disable GLVis visualization.");
110 args.AddOption(&makeMesh, "-mm", "--make-mesh", "-no-mm",
111 "--no-make-mesh", "Create Cartesian mesh");
112 args.AddOption(&tdim, "-dim", "--dimension", "Dimension for Cartesian mesh");
113 args.AddOption(&num_refs, "-r", "--refs", "Number of 3:1 refinements");
114 args.Parse();
115 if (!args.Good())
116 {
117 args.PrintUsage(cout);
118 return 1;
119 }
120 args.PrintOptions(cout);
121
122 // 2. Create or read the mesh from the given mesh file.
123 Mesh mesh;
124 if (makeMesh)
125 {
126 mesh = tdim == 3 ? Mesh::MakeCartesian3D(2, 2, 2, Element::HEXAHEDRON) :
128 }
129 else
130 {
131 mesh = Mesh::LoadFromFile(mesh_file, 1, 1);
132 }
133
134 const int dim = mesh.Dimension();
135
136 // 3. Randomly perform 3:1 refinements in the mesh.
137 TestAnisoRefRandom(num_refs, tdim, mesh);
138
139 // 4. Define a finite element space on the mesh. Here we use continuous
140 // Lagrange finite elements of the specified order.
141 H1_FECollection fec(order, dim);
142 FiniteElementSpace fespace(&mesh, &fec);
143 cout << "Number of finite element unknowns: "
144 << fespace.GetTrueVSize() << endl;
145
146 // 5. Define the solution vector x as a finite element grid function
147 // corresponding to fespace. Solve the Poisson problem, as in ex1.
148 GridFunction x(&fespace);
149
150 {
151 x = 0.0;
152 LinearForm b(&fespace);
153 ConstantCoefficient one(1.0);
154 b.AddDomainIntegrator(new DomainLFIntegrator(one));
155 b.Assemble();
156
157 BilinearForm a(&fespace);
158 a.AddDomainIntegrator(new DiffusionIntegrator());
159 a.Assemble();
160
161 OperatorPtr A;
162 Vector B, X;
164 if (mesh.bdr_attributes.Size())
165 {
166 Array<int> ess_bdr(mesh.bdr_attributes.Max());
167 ess_bdr = 1;
168 fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
169 }
170
171 a.FormLinearSystem(ess_tdof_list, x, b, A, X, B);
172
173 GSSmoother M((SparseMatrix&)(*A));
174 PCG(*A, M, B, X, 1, 2000, 1e-12, 0.0);
175 a.RecoverFEMSolution(X, b, x);
176 }
177
178 // 6. Verify the continuity of the projected function in H1.
179 const real_t h1err = CheckH1Continuity(x);
180 cout << "Error of H1 continuity: " << h1err << endl;
181 MFEM_VERIFY(h1err < 1.0e-7, "");
182
183 // 7. Save the refined mesh and the solution. This output can be viewed later
184 // using GLVis: "glvis -m ref321.mesh -g sol.gf".
185 ofstream mesh_ofs("ref321.mesh");
186 mesh_ofs.precision(8);
187 mesh.Print(mesh_ofs);
188 ofstream sol_ofs("sol.gf");
189 sol_ofs.precision(8);
190 x.Save(sol_ofs);
191
192 // 8. Send the solution by socket to a GLVis server.
193 if (visualization)
194 {
195 char vishost[] = "localhost";
196 int visport = 19916;
197 socketstream sol_sock(vishost, visport);
198 sol_sock.precision(8);
199 sol_sock << "solution\n" << mesh << x << flush;
200 }
201
202 return 0;
203}
204
206{
207 const FiniteElementSpace *fes = x.FESpace();
208 Mesh *mesh = fes->GetMesh();
209
210 const int dim = mesh->Dimension();
211
212 // Following the example of KellyErrorEstimator::ComputeEstimates(), we loop
213 // over interior faces and then shared faces.
214
215 // Compute error contribution from local interior faces
216 real_t errorMax = 0.0;
217 for (int f = 0; f < mesh->GetNumFaces(); f++)
218 {
219 if (mesh->FaceIsInterior(f))
220 {
221 int Inf1, Inf2, NCFace;
222 mesh->GetFaceInfos(f, &Inf1, &Inf2, &NCFace);
223
224 auto FT = mesh->GetFaceElementTransformations(f);
225
226 const int faceOrder = dim == 3 ? fes->GetFaceOrder(f) :
227 fes->GetEdgeOrder(f);
228 auto &int_rule = IntRules.Get(FT->FaceGeom, 2 * faceOrder);
229 const auto nip = int_rule.GetNPoints();
230
231 // Convention:
232 // * Conforming face: Face side with smaller element id handles the
233 // integration
234 // * Non-conforming face: The slave handles the integration.
235 // See FaceInfo documentation for details.
236 bool isNCSlave = FT->Elem2No >= 0 && NCFace >= 0;
237 bool isConforming = FT->Elem2No >= 0 && NCFace == -1;
238 if ((FT->Elem1No < FT->Elem2No && isConforming) || isNCSlave)
239 {
240 for (int i = 0; i < nip; i++)
241 {
242 const auto &fip = int_rule.IntPoint(i);
244
245 FT->Loc1.Transform(fip, ip);
246 const real_t v1 = x.GetValue(FT->Elem1No, ip);
247
248 FT->Loc2.Transform(fip, ip);
249 const real_t v2 = x.GetValue(FT->Elem2No, ip);
250
251 const real_t err_i = std::abs(v1 - v2);
252 errorMax = std::max(errorMax, err_i);
253 }
254 }
255 }
256 }
257
258 return errorMax;
259}
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
Definition array.cpp:69
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
Definition array.hpp:869
int Size() const
Return the logical size of the array.
Definition array.hpp:192
int Append(const T &el)
Append element 'el' to array, resize if necessary.
Definition array.hpp:941
A "square matrix" operator for the associated FE space and BLFIntegrators The sum of all the BLFInteg...
A coefficient that is constant across space and time.
Class for domain integration .
Definition lininteg.hpp:108
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition fespace.hpp:210
virtual int GetTrueVSize() const
Return the number of vector true (conforming) dofs.
Definition fespace.hpp:827
int GetEdgeOrder(int edge, int variant=0) const
Definition fespace.cpp:3379
int GetFaceOrder(int face, int variant=0) const
Returns the polynomial degree of the i'th face finite element.
Definition fespace.cpp:3395
virtual void GetEssentialTrueDofs(const Array< int > &bdr_attr_is_ess, Array< int > &ess_tdof_list, int component=-1) const
Get a list of essential true dofs, ess_tdof_list, corresponding to the boundary attributes marked in ...
Definition fespace.cpp:624
Mesh * GetMesh() const
Returns the mesh.
Definition fespace.hpp:639
Gauss-Seidel smoother of a sparse matrix.
Class for grid function - Vector with associated FE space.
Definition gridfunc.hpp:53
virtual real_t GetValue(int i, const IntegrationPoint &ip, int vdim=1) const
Definition gridfunc.cpp:429
virtual void Save(std::ostream &out) const
Save the GridFunction to an output stream.
FiniteElementSpace * FESpace()
Arbitrary order H1-conforming (continuous) finite elements.
Definition fe_coll.hpp:291
Class for integration point with weight.
Definition intrules.hpp:35
int GetNPoints() const
Returns the number of the points in the integration rule.
Definition intrules.hpp:255
const IntegrationRule & Get(int GeomType, int Order)
Returns an integration rule for given GeomType and Order.
Vector with associated FE space and LinearFormIntegrators.
Mesh data type.
Definition mesh.hpp:67
virtual FaceElementTransformations * GetFaceElementTransformations(int FaceNo, int mask=31)
Definition mesh.cpp:1179
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
Definition mesh.hpp:309
void GetFaceInfos(int Face, int *Inf1, int *Inf2) const
Definition mesh.cpp:1638
int GetNumFaces() const
Return the number of faces (3D), edges (2D) or vertices (1D).
Definition mesh.cpp:7302
void GeneralRefinement(const Array< Refinement > &refinements, int nonconforming=-1, int nc_limit=0)
Definition mesh.cpp:11713
void EnsureNodes()
Make sure that the mesh has valid nodes, i.e. its geometry is described by a vector finite element gr...
Definition mesh.cpp:7159
void SetScaledNCMesh()
Definition mesh.hpp:2543
virtual void Print(std::ostream &os=mfem::out, const std::string &comments="") const
Print the mesh to the given stream using the default MFEM mesh format.
Definition mesh.hpp:2610
int GetNE() const
Returns number of elements.
Definition mesh.hpp:1390
int Dimension() const
Dimension of the reference space used within the elements.
Definition mesh.hpp:1314
bool FaceIsInterior(int FaceNo) const
Return true if the given face is interior.
Definition mesh.hpp:1576
static Mesh MakeCartesian3D(int nx, int ny, int nz, Element::Type type, real_t sx=1.0, real_t sy=1.0, real_t sz=1.0, bool sfc_ordering=true)
Creates a mesh for the parallelepiped [0,sx]x[0,sy]x[0,sz], divided into nx*ny*nz hexahedra if type =...
Definition mesh.cpp:4786
static Mesh LoadFromFile(const std::string &filename, int generate_edges=0, int refine=1, bool fix_orientation=true)
Definition mesh.cpp:4758
NCMesh * ncmesh
Optional nonconforming mesh extension.
Definition mesh.hpp:318
static Mesh MakeCartesian2D(int nx, int ny, Element::Type type, bool generate_edges=false, real_t sx=1.0, real_t sy=1.0, bool sfc_ordering=true)
Creates mesh for the rectangle [0,sx]x[0,sy], divided into nx*ny quadrilaterals if type = QUADRILATER...
Definition mesh.cpp:4776
const CoarseFineTransformations & GetRefinementTransforms() const
Definition ncmesh.cpp:5204
Pointer to an Operator of a specified type.
Definition handle.hpp:34
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.
Data type sparse matrix.
Definition sparsemat.hpp:51
Vector data type.
Definition vector.hpp:82
const int * ess_tdof_list
int dim
Definition ex24.cpp:53
int main()
real_t b
Definition lissajous.cpp:42
real_t a
Definition lissajous.cpp:41
void PCG(const Operator &A, Solver &B, const Vector &b, Vector &x, int print_iter, int max_num_iter, real_t RTOLERANCE, real_t ATOLERANCE)
Preconditioned conjugate gradient method. (tolerances are squared)
Definition solvers.cpp:1067
float real_t
Definition config.hpp:46
std::function< real_t(const Vector &)> f(real_t mass_coeff)
Definition lor_mms.hpp:30
IntegrationRules IntRules(0, Quadrature1D::GaussLegendre)
A global object with all integration rules (defined in intrules.cpp)
Definition intrules.hpp:549
const char vishost[]
STL namespace.
real_t p(const Vector &x, real_t t)
void FindChildren(const Mesh &mesh, int elem, Array< int > &children)
Definition ref321.cpp:37
real_t CheckH1Continuity(GridFunction &x)
Definition ref321.cpp:205
void Refine31(Mesh &mesh, int elem, char type)
Definition ref321.cpp:56
void TestAnisoRefRandom(int num_refs, int dim, Mesh &mesh)
Definition ref321.cpp:75
Defines the coarse-fine transformations of all fine elements.
Definition ncmesh.hpp:90
Array< Embedding > embeddings
Fine element positions in their parents.
Definition ncmesh.hpp:92