MFEM v4.10.0
Finite element discretization library
Loading...
Searching...
No Matches
ex4.cpp
Go to the documentation of this file.
1// MFEM Example 4
2//
3// Compile with: make ex4
4//
5// Sample runs: ex4 -m ../data/square-disc.mesh
6// ex4 -m ../data/star.mesh
7// ex4 -m ../data/beam-tet.mesh
8// ex4 -m ../data/beam-hex.mesh
9// ex4 -m ../data/beam-hex.mesh -o 2 -pa
10// ex4 -m ../data/escher.mesh
11// ex4 -m ../data/fichera.mesh -o 2 -hb
12// ex4 -m ../data/fichera.mesh -o 2 -hb -ea
13// ex4 -m ../data/fichera-q2.vtk
14// ex4 -m ../data/fichera-q3.mesh -o 2 -sc
15// ex4 -m ../data/square-disc-nurbs.mesh
16// ex4 -m ../data/beam-hex-nurbs.mesh
17// ex4 -m ../data/periodic-square.mesh -no-bc
18// ex4 -m ../data/periodic-cube.mesh -no-bc
19// ex4 -m ../data/amr-quad.mesh
20// ex4 -m ../data/amr-hex.mesh
21// ex4 -m ../data/amr-hex.mesh -o 2 -hb
22// ex4 -m ../data/amr-hex.mesh -o 2 -hb -ea
23// ex4 -m ../data/fichera-amr.mesh -o 2 -sc
24// ex4 -m ../data/ref-prism.mesh -o 1
25// ex4 -m ../data/octahedron.mesh -o 1
26// ex4 -m ../data/star-surf.mesh -o 1
27//
28// Device sample runs:
29// ex4 -m ../data/star.mesh -pa -d cuda
30// ex4 -m ../data/star.mesh -hb -ea -d cuda
31// ex4 -m ../data/amr-quad.mesh -hb -ea -d cuda
32// ex4 -m ../data/star.mesh -pa -d raja-cuda
33// ex4 -m ../data/star.mesh -pa -d raja-omp
34// ex4 -m ../data/beam-hex.mesh -pa -d cuda
35//
36// Description: This example code solves a simple 2D/3D H(div) diffusion
37// problem corresponding to the second order definite equation
38// -grad(alpha div F) + beta F = f with boundary condition F dot n
39// = <given normal field>. Here, we use a given exact solution F
40// and compute the corresponding r.h.s. f. We discretize with
41// Raviart-Thomas finite elements.
42//
43// The example demonstrates the use of H(div) finite element
44// spaces with the grad-div and H(div) vector finite element mass
45// bilinear form, as well as the computation of discretization
46// error when the exact solution is known. Bilinear form
47// hybridization and static condensation are also illustrated.
48//
49// We recommend viewing examples 1-3 before viewing this example.
50
51#include "mfem.hpp"
52#include <fstream>
53#include <iostream>
54
55using namespace std;
56using namespace mfem;
57
58// Exact solution, F, and r.h.s., f. See below for implementation.
59void F_exact(const Vector &, Vector &);
60void f_exact(const Vector &, Vector &);
62
63int main(int argc, char *argv[])
64{
65 // 1. Parse command-line options.
66 const char *mesh_file = "../data/star.mesh";
67 int order = 1;
68 bool set_bc = true;
69 bool static_cond = false;
70 bool hybridization = false;
71 bool pa = false;
72 bool ea = false;
73 const char *device_config = "cpu";
74 bool visualization = 1;
75
76 OptionsParser args(argc, argv);
77 args.AddOption(&mesh_file, "-m", "--mesh",
78 "Mesh file to use.");
79 args.AddOption(&order, "-o", "--order",
80 "Finite element order (polynomial degree).");
81 args.AddOption(&set_bc, "-bc", "--impose-bc", "-no-bc", "--dont-impose-bc",
82 "Impose or not essential boundary conditions.");
83 args.AddOption(&freq, "-f", "--frequency", "Set the frequency for the exact"
84 " solution.");
85 args.AddOption(&static_cond, "-sc", "--static-condensation", "-no-sc",
86 "--no-static-condensation", "Enable static condensation.");
87 args.AddOption(&hybridization, "-hb", "--hybridization", "-no-hb",
88 "--no-hybridization", "Enable hybridization.");
89 args.AddOption(&pa, "-pa", "--partial-assembly", "-no-pa",
90 "--no-partial-assembly", "Enable Partial Assembly.");
91 args.AddOption(&ea, "-ea", "--element-assembly", "-no-ea",
92 "--no-element-assembly", "Enable Element Assembly.");
93 args.AddOption(&device_config, "-d", "--device",
94 "Device configuration string, see Device::Configure().");
95 args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
96 "--no-visualization",
97 "Enable or disable GLVis visualization.");
98 args.ParseCheck();
99 kappa = freq * M_PI;
100
101 // 2. Enable hardware devices such as GPUs, and programming models such as
102 // CUDA, OCCA, RAJA and OpenMP based on command line options.
103 Device device(device_config);
104 device.Print();
105
106 // 3. Read the mesh from the given mesh file. We can handle triangular,
107 // quadrilateral, tetrahedral, hexahedral, surface and volume, as well as
108 // periodic meshes with the same code.
109 Mesh *mesh = new Mesh(mesh_file, 1, 1);
110 int dim = mesh->Dimension();
111 int sdim = mesh->SpaceDimension();
112
113 // 4. Refine the mesh to increase the resolution. In this example we do
114 // 'ref_levels' of uniform refinement. We choose 'ref_levels' to be the
115 // largest number that gives a final mesh with no more than 25,000
116 // elements.
117 {
118 int ref_levels =
119 (int)floor(log(25000./mesh->GetNE())/log(2.)/dim);
120 for (int l = 0; l < ref_levels; l++)
121 {
122 mesh->UniformRefinement();
123 }
124 }
125
126 // 5. Define a finite element space on the mesh. Here we use the
127 // Raviart-Thomas finite elements of the specified order.
128 FiniteElementCollection *fec = new RT_FECollection(order-1, dim);
129 FiniteElementSpace *fespace = new FiniteElementSpace(mesh, fec);
130 cout << "Number of finite element unknowns: "
131 << fespace->GetTrueVSize() << endl;
132
133 // 6. Determine the list of true (i.e. conforming) essential boundary dofs.
134 // In this example, the boundary conditions are defined by marking all
135 // the boundary attributes from the mesh as essential (Dirichlet) and
136 // converting them to a list of true dofs.
138 if (mesh->bdr_attributes.Size())
139 {
140 Array<int> ess_bdr(mesh->bdr_attributes.Max());
141 ess_bdr = set_bc ? 1 : 0;
142 fespace->GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
143 }
144
145 // 7. Set up the linear form b(.) which corresponds to the right-hand side
146 // of the FEM linear system, which in this case is (f,phi_i) where f is
147 // given by the function f_exact and phi_i are the basis functions in the
148 // finite element fespace.
150 LinearForm *b = new LinearForm(fespace);
151 b->AddDomainIntegrator(new VectorFEDomainLFIntegrator(f));
152 b->Assemble();
153
154 // 8. Define the solution vector x as a finite element grid function
155 // corresponding to fespace. Initialize x by projecting the exact
156 // solution. Note that only values from the boundary faces will be used
157 // when eliminating the non-homogeneous boundary condition to modify the
158 // r.h.s. vector b.
159 GridFunction x(fespace);
162
163 // 9. Set up the bilinear form corresponding to the H(div) diffusion operator
164 // grad alpha div + beta I, by adding the div-div and the mass domain
165 // integrators.
167 Coefficient *beta = new ConstantCoefficient(1.0);
168 BilinearForm *a = new BilinearForm(fespace);
169 if (pa) { a->SetAssemblyLevel(AssemblyLevel::PARTIAL); }
170 if (ea) { a->SetAssemblyLevel(AssemblyLevel::ELEMENT); }
171 a->AddDomainIntegrator(new DivDivIntegrator(*alpha));
172 a->AddDomainIntegrator(new VectorFEMassIntegrator(*beta));
173
174 // 10. Assemble the bilinear form and the corresponding linear system,
175 // applying any necessary transformations such as: eliminating boundary
176 // conditions, applying conforming constraints for non-conforming AMR,
177 // static condensation, hybridization, etc.
178 FiniteElementCollection *hfec = NULL;
179 FiniteElementSpace *hfes = NULL;
180 if (static_cond)
181 {
182 a->EnableStaticCondensation();
183 }
184 else if (hybridization)
185 {
186 hfec = new DG_Interface_FECollection(order-1, dim);
187 hfes = new FiniteElementSpace(mesh, hfec);
188 a->EnableHybridization(hfes, new NormalTraceJumpIntegrator(),
190 }
191 a->Assemble();
192
193 OperatorPtr A;
194 Vector B, X;
195 a->FormLinearSystem(ess_tdof_list, x, *b, A, X, B);
196
197 cout << "Size of linear system: " << A->Height() << endl;
198
199 // 11. Solve the linear system A X = B.
200 if (!pa && (!ea || hybridization))
201 {
202#ifndef MFEM_USE_SUITESPARSE
203 // Use a simple symmetric Gauss-Seidel preconditioner with PCG.
204 GSSmoother M((SparseMatrix&)(*A));
205 PCG(*A, M, B, X, 1, 10000, 1e-20, 0.0);
206#else
207 // If MFEM was compiled with SuiteSparse, use UMFPACK to solve the system.
208 UMFPackSolver umf_solver;
209 umf_solver.Control[UMFPACK_ORDERING] = UMFPACK_ORDERING_METIS;
210 umf_solver.SetOperator(*A);
211 umf_solver.Mult(B, X);
212#endif
213 }
214 else // Jacobi preconditioning in partial assembly mode
215 {
216 if (UsesTensorBasis(*fespace))
217 {
219 PCG(*A, M, B, X, 1, 10000, 1e-20, 0.0);
220 }
221 else
222 {
223 CG(*A, B, X, 1, 10000, 1e-20, 0.0);
224 }
225 }
226
227 // 12. Recover the solution as a finite element grid function.
228 a->RecoverFEMSolution(X, *b, x);
229
230 // 13. Compute and print the L^2 norm of the error.
231 cout << "\n|| F_h - F ||_{L^2} = " << x.ComputeL2Error(F) << '\n' << endl;
232
233 // 14. Save the refined mesh and the solution. This output can be viewed
234 // later using GLVis: "glvis -m refined.mesh -g sol.gf".
235 {
236 ofstream mesh_ofs("refined.mesh");
237 mesh_ofs.precision(8);
238 mesh->Print(mesh_ofs);
239 ofstream sol_ofs("sol.gf");
240 sol_ofs.precision(8);
241 x.Save(sol_ofs);
242 }
243
244 // 15. Send the solution by socket to a GLVis server.
245 if (visualization)
246 {
247 char vishost[] = "localhost";
248 int visport = 19916;
249 socketstream sol_sock(vishost, visport);
250 sol_sock.precision(8);
251 sol_sock << "solution\n" << *mesh << x << flush;
252 }
253
254 // 16. Free the used memory.
255 delete hfes;
256 delete hfec;
257 delete a;
258 delete alpha;
259 delete beta;
260 delete b;
261 delete fespace;
262 delete fec;
263 delete mesh;
264
265 return 0;
266}
267
268
269// The exact solution (for non-surface meshes)
270void F_exact(const Vector &p, Vector &F)
271{
272 int dim = p.Size();
273
274 real_t x = p(0);
275 real_t y = p(1);
276 // real_t z = (dim == 3) ? p(2) : 0.0; // Uncomment if F is changed to depend on z
277
278 F(0) = cos(kappa*x)*sin(kappa*y);
279 F(1) = cos(kappa*y)*sin(kappa*x);
280 if (dim == 3)
281 {
282 F(2) = 0.0;
283 }
284}
285
286// The right hand side
287void f_exact(const Vector &p, Vector &f)
288{
289 int dim = p.Size();
290
291 real_t x = p(0);
292 real_t y = p(1);
293 // real_t z = (dim == 3) ? p(2) : 0.0; // Uncomment if f is changed to depend on z
294
295 real_t temp = 1 + 2*kappa*kappa;
296
297 f(0) = temp*cos(kappa*x)*sin(kappa*y);
298 f(1) = temp*cos(kappa*y)*sin(kappa*x);
299 if (dim == 3)
300 {
301 f(2) = 0;
302 }
303}
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
Definition array.cpp:69
int Size() const
Return the logical size of the array.
Definition array.hpp:192
A "square matrix" operator for the associated FE space and BLFIntegrators The sum of all the BLFInteg...
Base class Coefficients that optionally depend on space and time. These are used by the BilinearFormI...
A coefficient that is constant across space and time.
The MFEM Device class abstracts hardware devices such as GPUs, as well as programming models such as ...
Definition device.hpp:129
void Print(std::ostream &os=mfem::out)
Print the configuration of the MFEM virtual device object.
Definition device.cpp:319
for Raviart-Thomas elements
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:210
virtual int GetTrueVSize() const
Return the number of vector true (conforming) dofs.
Definition fespace.hpp:827
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
Gauss-Seidel smoother of a sparse matrix.
Class for grid function - Vector with associated FE space.
Definition gridfunc.hpp:53
virtual void Save(std::ostream &out) const
Save the GridFunction to an output stream.
virtual real_t ComputeL2Error(Coefficient *exsol[], const IntegrationRule *irs[]=NULL, const Array< int > *elems=NULL) const
Returns ||exsol - u_h||_L2 for scalar or vector H1 or L2 elements.
virtual void ProjectCoefficient(Coefficient &coeff, ProjectType type=ProjectType::DEFAULT)
Project coeff Coefficient to this GridFunction. The projection computation depends on the choice of t...
Vector with associated FE space and LinearFormIntegrators.
Mesh data type.
Definition mesh.hpp:67
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
Definition mesh.hpp:309
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
int SpaceDimension() const
Dimension of the physical space containing the mesh.
Definition mesh.hpp:1317
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
Definition mesh.cpp:12125
Pointer to an Operator of a specified type.
Definition handle.hpp:34
Jacobi smoothing for a given bilinear form (no matrix necessary).
Definition solvers.hpp:422
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
Definition operator.hpp:68
void ParseCheck(std::ostream &out=mfem::out)
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
Arbitrary order H(div)-conforming Raviart-Thomas finite elements.
Definition fe_coll.hpp:430
Data type sparse matrix.
Definition sparsemat.hpp:51
Direct sparse solver using UMFPACK.
Definition solvers.hpp:1210
real_t Control[UMFPACK_CONTROL]
Definition solvers.hpp:1220
void SetOperator(const Operator &op) override
Factorize the given Operator op which must be a SparseMatrix.
Definition solvers.cpp:3368
void Mult(const Vector &b, Vector &x) const override
Direct solution of the linear system using UMFPACK.
Definition solvers.cpp:3463
for VectorFiniteElements (Nedelec, Raviart-Thomas)
Definition lininteg.hpp:365
A general vector function coefficient.
Vector data type.
Definition vector.hpp:82
int Size() const
Returns the size of the vector.
Definition vector.hpp:234
const int * ess_tdof_list
const real_t alpha
Definition ex15.cpp:369
int dim
Definition ex24.cpp:53
real_t kappa
Definition ex4.cpp:61
void f_exact(const Vector &, Vector &)
Definition ex4.cpp:287
real_t freq
Definition ex4.cpp:61
void F_exact(const Vector &, Vector &)
Definition ex4.cpp:270
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
void CG(const Operator &A, const Vector &b, Vector &x, int print_iter, int max_num_iter, real_t RTOLERANCE, real_t ATOLERANCE)
Conjugate gradient method. (tolerances are squared)
Definition solvers.cpp:1052
bool UsesTensorBasis(const FiniteElementSpace &fes)
Return true if the mesh contains only one topology and the elements are tensor elements.
Definition fespace.hpp:1644
float real_t
Definition config.hpp:46
std::function< real_t(const Vector &)> f(real_t mass_coeff)
Definition lor_mms.hpp:30
const char vishost[]
STL namespace.
real_t p(const Vector &x, real_t t)