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