MFEM v4.10.0
Finite element discretization library
Loading...
Searching...
No Matches
nurbs_ex24.cpp
Go to the documentation of this file.
1// MFEM Example 24 -- modified for NURBS FE
2//
3// Compile with: make nurbs_ex24
4//
5// Sample runs: nurbs_ex24 -m ../../data/pipe-nurbs-2d.mesh -o 2
6// nurbs_ex24 -m ../../data/pipe-nurbs-2d.mesh -p 2
7// nurbs_ex24 -m ../../data/cube-nurbs.mesh -o 2 -r 3
8// nurbs_ex24 -m ../../data/cube-nurbs.mesh -o 2 -p 1 -r 3
9// nurbs_ex24 -m ../../data/cube-nurbs.mesh -o 2 -p 2 -r 3
10// nurbs_ex24 -m ../../data/escher.mesh
11// nurbs_ex24 -m ../../data/escher.mesh -o 2
12// nurbs_ex24 -m ../../data/fichera.mesh
13// nurbs_ex24 -m ../../data/fichera-q2.vtk
14// nurbs_ex24 -m ../../data/fichera-q3.mesh
15// nurbs_ex24 -m ../../data/amr-quad.mesh -o 2
16// nurbs_ex24 -m ../../data/amr-hex.mesh
17//
18// Description: This example code illustrates usage of mixed finite element
19// spaces, with three variants:
20//
21// 0) (grad p, u) for p in H^1 tested against u in H(curl)
22// 1) (curl v, u) for v in H(curl) tested against u in H(div), 3D
23// 2) (div v, q) for v in H(div) tested against q in L_2
24//
25// Using different approaches, we project the gradient, curl, or
26// divergence to the appropriate space.
27//
28// NURBS-based H(curl) and H(div) spaces only implemented
29// for meshes consisting of a single patch.
30//
31// We recommend viewing examples 1, 3, and 5 before viewing this
32// example.
33
34#include "mfem.hpp"
35#include <fstream>
36#include <iostream>
37
38using namespace std;
39using namespace mfem;
40
41real_t p_exact(const Vector &x);
42void gradp_exact(const Vector &, Vector &);
44void v_exact(const Vector &x, Vector &v);
45void curlv_exact(const Vector &x, Vector &cv);
46template <typename CoefficientType>
47void Project(GridFunction &gf, CoefficientType &coef, int proj_type);
48
49int dim;
51
52int main(int argc, char *argv[])
53{
54 // 1. Parse command-line options.
55 const char *mesh_file = "../../data/cube-nurbs.mesh";
56 int ref_levels = -1;
57 int order = 1;
58 bool NURBS = true;
59 int prob = 0;
60 bool static_cond = false;
61 bool pa = false;
62 int proj_type_int = 0;
63 const char *device_config = "cpu";
64 int visport = 19916;
65 bool visualization = 1;
66
67 OptionsParser args(argc, argv);
68 args.AddOption(&mesh_file, "-m", "--mesh",
69 "Mesh file to use.");
70 args.AddOption(&ref_levels, "-r", "--refine",
71 "Number of times to refine the mesh uniformly, -1 for auto.");
72 args.AddOption(&order, "-o", "--order",
73 "Finite element order (polynomial degree).");
74 args.AddOption(&NURBS, "-n", "--nurbs", "-nn", "--no-nurbs",
75 "Use NURBS spaces if the mesh is a NURBS mesh.");
76 args.AddOption(&prob, "-p", "--problem-type",
77 "Choose between 0: grad, 1: curl, 2: div");
78 args.AddOption(&static_cond, "-sc", "--static-condensation", "-no-sc",
79 "--no-static-condensation", "Enable static condensation.");
80 args.AddOption(&pa, "-pa", "--partial-assembly", "-no-pa",
81 "--no-partial-assembly", "Enable Partial Assembly.");
82 args.AddOption(&proj_type_int, "-proj", "--projection",
83 "Projection type:\n."
84 " 0 = DEFAULT: ELEMENTL2 for NURBS elements, ELEMENT else.\n"
85 " 1 = ELEMENT: As defined in the respective element.\n"
86 " 2 = GLOBALL2: Global L2 projection.\n"
87 " 3 = ELEMENTL2: Element L2 projection.");
88 args.AddOption(&device_config, "-d", "--device",
89 "Device configuration string, see Device::Configure().");
90 args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
91 "--no-visualization",
92 "Enable or disable GLVis visualization.");
93
94 args.AddOption(&visport, "-p", "--send-port", "Socket for GLVis.");
95 args.Parse();
96 if (!args.Good())
97 {
99 return 1;
100 }
102 ProjectType proj_type = static_cast<ProjectType>(proj_type_int);
103 kappa = freq * M_PI;
104
105 // 2. Enable hardware devices such as GPUs, and programming models such as
106 // CUDA, OCCA, RAJA and OpenMP based on command line options.
107 Device device(device_config);
108 device.Print();
109
110 // 3. Read the mesh from the given mesh file. We can handle triangular,
111 // quadrilateral, tetrahedral, hexahedral, surface and volume meshes with
112 // the same code.
113 Mesh *mesh = new Mesh(mesh_file, 1, 1);
114 dim = mesh->Dimension();
115 if ((prob == 1) && (dim != 3))
116 {
117 MFEM_ABORT("The curl problem is only defined in 3D.");
118 }
119 int sdim = mesh->SpaceDimension();
120
121 // 4. Refine the mesh to increase the resolution. In this example we do
122 // 'ref_levels' of uniform refinement. We choose 'ref_levels' to be the
123 // largest number that gives a final mesh with no more than 50,000
124 // elements.
125 {
126 if (ref_levels < 0)
127 {
128 ref_levels = (int)floor(log(50000./mesh->GetNE())/log(2.)/dim);
129 }
130 for (int l = 0; l < ref_levels; l++)
131 {
132 mesh->UniformRefinement();
133 }
134 }
135
136 // 5. Define a finite element space on the mesh. Here we use H^1, H(Div) or
137 // H(Curl) finite elements of the specified order.
138 FiniteElementCollection *trial_fec = nullptr;
139 FiniteElementCollection *test_fec = nullptr;
140 NURBSExtension *NURBSext = nullptr;
141 if (mesh->NURBSext && NURBS)
142 {
143 NURBSext = new NURBSExtension(mesh->NURBSext, order);
144 if (prob == 0)
145 {
146 trial_fec = new NURBSFECollection(order);
147 test_fec = new NURBS_HCurlFECollection(order, dim);
148 }
149 else if (prob == 1)
150 {
151 trial_fec = new NURBS_HCurlFECollection(order, dim);
152 test_fec = new NURBS_HDivFECollection(order, dim);
153 }
154 else
155 {
156 trial_fec = new NURBS_HDivFECollection(order, dim);
157 test_fec = new NURBSFECollection(order);
158 }
159 mfem::out << "Create NURBS finite element" << endl;
160 }
161 else
162 {
163 if (prob == 0)
164 {
165 trial_fec = new H1_FECollection(order, dim);
166 test_fec = new ND_FECollection(order, dim);
167 }
168 else if (prob == 1)
169 {
170 trial_fec = new ND_FECollection(order, dim);
171 test_fec = new RT_FECollection(order-1, dim);
172 }
173 else
174 {
175 trial_fec = new RT_FECollection(order-1, dim);
176 test_fec = new L2_FECollection(order-1, dim);
177 }
178 mfem::out << "Create standard finite elements" << endl;
179 }
180
181 FiniteElementSpace trial_fes(mesh, NURBSext, trial_fec);
182 FiniteElementSpace test_fes(mesh,trial_fes.StealNURBSext(), test_fec);
183
184 int trial_size = trial_fes.GetTrueVSize();
185 int test_size = test_fes.GetTrueVSize();
186
187 if (prob == 0)
188 {
189 mfem::out << "Number of HCurl finite element unknowns: " << test_size << endl;
190 mfem::out << "Number of H1 finite element unknowns: " << trial_size << endl;
191 }
192 else if (prob == 1)
193 {
194 mfem::out << "Number of HCurl finite element unknowns: " << trial_size << endl;
195 mfem::out << "Number of HDiv finite element unknowns: " << test_size
196 << endl;
197 }
198 else
199 {
200 mfem::out << "Number of HDiv finite element unknowns: "
201 << trial_size << endl;
202 mfem::out << "Number of L2 finite element unknowns: " << test_size << endl;
203 }
204
205 // 6. Define the solution vector as a finite element grid function
206 // corresponding to the trial fespace.
207 GridFunction gftest(&test_fes);
208 GridFunction gftrial(&trial_fes);
209 GridFunction x(&test_fes);
211 VectorFunctionCoefficient gradp_coef(sdim, gradp_exact);
213 VectorFunctionCoefficient curlv_coef(sdim, curlv_exact);
215
216 if (prob == 0)
217 {
218 gftrial.ProjectCoefficient(p_coef, proj_type);
219 }
220 else if (prob == 1)
221 {
222 gftrial.ProjectCoefficient(v_coef, proj_type);
223 }
224 else
225 {
226 gftrial.ProjectCoefficient(gradp_coef, proj_type);
227 }
228 gftrial.SetTrueVector();
229 gftrial.SetFromTrueVector();
230
231 // 7. Set up the bilinear forms for L2 projection.
232 ConstantCoefficient one(1.0);
233 BilinearForm a(&test_fes);
234 MixedBilinearForm a_mixed(&trial_fes, &test_fes);
235 if (pa)
236 {
237 a.SetAssemblyLevel(AssemblyLevel::PARTIAL);
238 a_mixed.SetAssemblyLevel(AssemblyLevel::PARTIAL);
239 }
240
241 if (prob == 0)
242 {
243 a.AddDomainIntegrator(new VectorFEMassIntegrator(one));
245 }
246 else if (prob == 1)
247 {
248 a.AddDomainIntegrator(new VectorFEMassIntegrator(one));
250 }
251 else
252 {
253 a.AddDomainIntegrator(new MassIntegrator(one));
255 }
256
257 // 8. Assemble the bilinear form and the corresponding linear system,
258 // applying any necessary transformations such as: eliminating boundary
259 // conditions, applying conforming constraints for non-conforming AMR,
260 // static condensation, etc.
261 if (static_cond) { a.EnableStaticCondensation(); }
262
263 a.Assemble();
264 if (!pa) { a.Finalize(); }
265
266 a_mixed.Assemble();
267 if (!pa) { a_mixed.Finalize(); }
268
269 if (pa)
270 {
271 a_mixed.Mult(gftrial, x);
272 }
273 else
274 {
275 SparseMatrix& mixed = a_mixed.SpMat();
276 mixed.Mult(gftrial, x);
277 }
278
279 // 9. Define and apply a PCG solver for Ax = b with Jacobi preconditioner.
280 {
281 GridFunction rhs(&test_fes);
282 rhs = x;
283 x = 0.0;
284
285 CGSolver cg;
286 cg.SetRelTol(1e-12);
287 cg.SetMaxIter(1000);
288 cg.SetPrintLevel(1);
289 if (pa)
290 {
291 Array<int> ess_tdof_list; // empty
293
294 cg.SetOperator(a);
295 cg.SetPreconditioner(Jacobi);
296 cg.Mult(rhs, x);
297 }
298 else
299 {
300 SparseMatrix& Amat = a.SpMat();
301 DSmoother Jacobi(Amat);
302
303 cg.SetOperator(Amat);
304 cg.SetPreconditioner(Jacobi);
305 cg.Mult(rhs, x);
306
307 }
308 }
309
310 // 10. Compute the projection of the exact field.
311 GridFunction exact_proj(&test_fes);
312 if (prob == 0)
313 {
314 exact_proj.ProjectCoefficient(gradp_coef, proj_type);
315 }
316 else if (prob == 1)
317 {
318 exact_proj.ProjectCoefficient(curlv_coef, proj_type);
319 }
320 else
321 {
322 exact_proj.ProjectCoefficient(divgradp_coef, proj_type);
323 }
324 exact_proj.SetTrueVector();
325 exact_proj.SetFromTrueVector();
326
327 // 11. Compute and print the L_2 norm of the error.
328 if (prob == 0)
329 {
330 real_t errSol = x.ComputeL2Error(gradp_coef);
331 real_t errProj = exact_proj.ComputeL2Error(gradp_coef);
332
333 mfem::out << "\n Solution of (E_h,v) = (grad p_h,v) for E_h and v in H(curl): "
334 "|| E_h - grad p ||_{L_2} = " << errSol << '\n' << endl;
335 mfem::out << " Projection E_h of exact grad p in H(curl): || E_h - grad p "
336 "||_{L_2} = " << errProj << '\n' << endl;
337 }
338 else if (prob == 1)
339 {
340 real_t errSol = x.ComputeL2Error(curlv_coef);
341 real_t errProj = exact_proj.ComputeL2Error(curlv_coef);
342
343 mfem::out << "\n Solution of (E_h,w) = (curl v_h,w) for E_h and w in H(div): "
344 "|| E_h - curl v ||_{L_2} = " << errSol << '\n' << endl;
345 mfem::out << " Projection E_h of exact curl v in H(div): || E_h - curl v "
346 "||_{L_2} = " << errProj << '\n' << endl;
347 }
348 else
349 {
350 int order_quad = max(3, 2*order+1);
352 for (int i=0; i < Geometry::NumGeom; ++i)
353 {
354 irs[i] = &(IntRules.Get(i, order_quad));
355 }
356
357 real_t errSol = x.ComputeL2Error(divgradp_coef, irs);
358 real_t errProj = exact_proj.ComputeL2Error(divgradp_coef, irs);
359
360 mfem::out << "\n Solution of (f_h,q) = (div v_h,q) for f_h and q in L_2: "
361 "|| f_h - div v ||_{L_2} = " << errSol << '\n' << endl;
362
363 mfem::out << " Projection f_h of exact div v in L_2: || f_h - div v "
364 "||_{L_2} = " << errProj << '\n' << endl;
365 }
366
367 // 12. Save the refined mesh and the solution. This output can be viewed
368 // later using GLVis: "glvis -m refined.mesh -g sol.gf".
369 ofstream mesh_ofs("refined.mesh");
370 mesh_ofs.precision(8);
371 mesh->Print(mesh_ofs);
372 ofstream sol_ofs("sol.gf");
373 sol_ofs.precision(8);
374 x.Save(sol_ofs);
375
376 // 13. Send the solution by socket to a GLVis server.
377 if (visualization)
378 {
379 char vishost[] = "localhost";
380 socketstream sol_sock(vishost, visport);
381 sol_sock.precision(8);
382 sol_sock << "solution\n" << *mesh << x << flush;
383 }
384
385 // 14. Free the used memory.
386 delete trial_fec;
387 delete test_fec;
388 delete mesh;
389
390 return 0;
391}
392
394{
395 if (dim == 3)
396 {
397 return sin(x(0)) * sin(x(1)) * sin(x(2));
398 }
399 else if (dim == 2)
400 {
401 return sin(x(0)) * sin(x(1));
402 }
403
404 return 0.0;
405}
406
407void gradp_exact(const Vector &x, Vector &f)
408{
409 if (dim == 3)
410 {
411 f(0) = cos(x(0)) * sin(x(1)) * sin(x(2));
412 f(1) = sin(x(0)) * cos(x(1)) * sin(x(2));
413 f(2) = sin(x(0)) * sin(x(1)) * cos(x(2));
414 }
415 else
416 {
417 f(0) = cos(x(0)) * sin(x(1));
418 f(1) = sin(x(0)) * cos(x(1));
419 if (x.Size() == 3) { f(2) = 0.0; }
420 }
421}
422
424{
425 if (dim == 3)
426 {
427 return -3.0 * sin(x(0)) * sin(x(1)) * sin(x(2));
428 }
429 else if (dim == 2)
430 {
431 return -2.0 * sin(x(0)) * sin(x(1));
432 }
433
434 return 0.0;
435}
436
437void v_exact(const Vector &x, Vector &v)
438{
439 if (dim == 3)
440 {
441 v(0) = sin(kappa * x(1));
442 v(1) = sin(kappa * x(2));
443 v(2) = sin(kappa * x(0));
444 }
445 else
446 {
447 v(0) = sin(kappa * x(1));
448 v(1) = sin(kappa * x(0));
449 if (x.Size() == 3) { v(2) = 0.0; }
450 }
451}
452
453void curlv_exact(const Vector &x, Vector &cv)
454{
455 if (dim == 3)
456 {
457 cv(0) = -kappa * cos(kappa * x(2));
458 cv(1) = -kappa * cos(kappa * x(0));
459 cv(2) = -kappa * cos(kappa * x(1));
460 }
461 else
462 {
463 cv = 0.0;
464 }
465}
A "square matrix" operator for the associated FE space and BLFIntegrators The sum of all the BLFInteg...
Conjugate gradient method.
Definition solvers.hpp:627
A coefficient that is constant across space and time.
Jacobi-type diagonal smoother of a sparse matrix.
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
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
NURBSExtension * StealNURBSext()
Definition fespace.cpp:2634
A general function coefficient.
static const int NumGeom
Definition geom.hpp:46
Class for grid function - Vector with associated FE space.
Definition gridfunc.hpp:53
void SetTrueVector()
Shortcut for calling GetTrueDofs() with GetTrueVector() as argument.
Definition gridfunc.hpp:187
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.
void SetFromTrueVector()
Shortcut for calling SetFromTrueDofs() with GetTrueVector() as argument.
Definition gridfunc.hpp:193
virtual void ProjectCoefficient(Coefficient &coeff, ProjectType type=ProjectType::DEFAULT)
Project coeff Coefficient to this GridFunction. The projection computation depends on the choice of t...
Arbitrary order H1-conforming (continuous) finite elements.
Definition fe_coll.hpp:291
Class for an integration rule - an Array of IntegrationPoint.
Definition intrules.hpp:96
const IntegrationRule & Get(int GeomType, int Order)
Returns an integration rule for given GeomType and Order.
Arbitrary order "L2-conforming" discontinuous finite elements.
Definition fe_coll.hpp:369
Mesh data type.
Definition mesh.hpp:67
NURBSExtension * NURBSext
Optional NURBS mesh extension.
Definition mesh.hpp:317
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
void Assemble(int skip_zeros=1)
void Finalize(int skip_zeros=1) override
Finalizes the matrix initialization if the AssemblyLevel is AssemblyLevel::LEGACY.
void SetAssemblyLevel(AssemblyLevel assembly_level)
Set the desired assembly level. The default is AssemblyLevel::LEGACY.
const SparseMatrix & SpMat() const
Returns a const reference to the sparse matrix: .
void Mult(const Vector &x, Vector &y) const override
Matrix multiplication: .
void AddDomainIntegrator(BilinearFormIntegrator *bfi)
Adds a domain integrator. Assumes ownership of bfi.
Arbitrary order H(curl)-conforming Nedelec finite elements.
Definition fe_coll.hpp:526
NURBSExtension generally contains multiple NURBSPatch objects spanning an entire Mesh....
Definition nurbs.hpp:575
Arbitrary order non-uniform rational B-splines (NURBS) finite elements.
Definition fe_coll.hpp:749
Arbitrary order H(curl) NURBS finite elements.
Definition fe_coll.hpp:860
Arbitrary order H(div) NURBS finite elements.
Definition fe_coll.hpp:808
Jacobi smoothing for a given bilinear form (no matrix necessary).
Definition solvers.hpp:422
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.
Arbitrary order H(div)-conforming Raviart-Thomas finite elements.
Definition fe_coll.hpp:430
Data type sparse matrix.
Definition sparsemat.hpp:51
void Mult(const Vector &x, Vector &y) const override
Matrix vector multiplication.
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
prob_type prob
Definition ex25.cpp:156
int main()
real_t a
Definition lissajous.cpp:41
ProjectType
This enumerated type describes the main projection types used by GridFunction::ProjectCoefficient():
Definition gridfunc.hpp:49
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
Definition globals.hpp:66
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.
void Project(GridFunction &gf, CoefficientType &coef, int proj_type)
real_t p_exact(const Vector &x)
real_t kappa
void curlv_exact(const Vector &x, Vector &cv)
int dim
void v_exact(const Vector &x, Vector &v)
real_t freq
void gradp_exact(const Vector &, Vector &)
real_t div_gradp_exact(const Vector &x)