MFEM v4.10.0
Finite element discretization library
Loading...
Searching...
No Matches
ex22p.cpp
Go to the documentation of this file.
1// MFEM Example 22 - Parallel Version
2//
3// Compile with: make ex22p
4//
5// Sample runs: mpirun -np 4 ex22p -m ../data/inline-segment.mesh -o 3
6// mpirun -np 4 ex22p -m ../data/inline-tri.mesh -o 3
7// mpirun -np 4 ex22p -m ../data/inline-quad.mesh -o 3
8// mpirun -np 4 ex22p -m ../data/inline-quad.mesh -o 3 -p 1
9// mpirun -np 4 ex22p -m ../data/inline-quad.mesh -o 3 -p 2
10// mpirun -np 4 ex22p -m ../data/inline-quad.mesh -o 1 -p 1 -pa
11// mpirun -np 4 ex22p -m ../data/inline-tet.mesh -o 2
12// mpirun -np 4 ex22p -m ../data/inline-hex.mesh -o 2
13// mpirun -np 4 ex22p -m ../data/inline-hex.mesh -o 2 -p 1
14// mpirun -np 4 ex22p -m ../data/inline-hex.mesh -o 2 -p 2
15// mpirun -np 4 ex22p -m ../data/inline-hex.mesh -o 1 -p 2 -pa
16// mpirun -np 4 ex22p -m ../data/inline-wedge.mesh -o 1
17// mpirun -np 4 ex22p -m ../data/inline-pyramid.mesh -o 1
18// mpirun -np 4 ex22p -m ../data/star.mesh -o 2 -sigma 10.0
19//
20// Device sample runs:
21// mpirun -np 4 ex22p -m ../data/inline-quad.mesh -o 1 -p 1 -pa -d cuda
22// mpirun -np 4 ex22p -m ../data/inline-hex.mesh -o 1 -p 2 -pa -d cuda
23// mpirun -np 4 ex22p -m ../data/star.mesh -o 2 -sigma 10.0 -pa -d cuda
24//
25// Description: This example code demonstrates the use of MFEM to define and
26// solve simple complex-valued linear systems. It implements three
27// variants of a damped harmonic oscillator:
28//
29// 1) A scalar H1 field
30// -Div(a Grad u) - omega^2 b u + i omega c u = 0
31//
32// 2) A vector H(Curl) field
33// Curl(a Curl u) - omega^2 b u + i omega c u = 0
34//
35// 3) A vector H(Div) field
36// -Grad(a Div u) - omega^2 b u + i omega c u = 0
37//
38// In each case the field is driven by a forced oscillation, with
39// angular frequency omega, imposed at the boundary or a portion
40// of the boundary.
41//
42// In electromagnetics the coefficients are typically named the
43// permeability, mu = 1/a, permittivity, epsilon = b, and
44// conductivity, sigma = c. The user can specify these constants
45// using either set of names.
46//
47// The example also demonstrates how to display a time-varying
48// solution as a sequence of fields sent to a single GLVis socket.
49//
50// We recommend viewing examples 1, 3 and 4 before viewing this
51// example.
52
53#include "mfem.hpp"
54#include <fstream>
55#include <iostream>
56
57using namespace std;
58using namespace mfem;
59
60static real_t mu_ = 1.0;
61static real_t epsilon_ = 1.0;
62static real_t sigma_ = 20.0;
63static real_t omega_ = 10.0;
64
67
68void u1_real_exact(const Vector &, Vector &);
69void u1_imag_exact(const Vector &, Vector &);
70
71void u2_real_exact(const Vector &, Vector &);
72void u2_imag_exact(const Vector &, Vector &);
73
74bool check_for_inline_mesh(const char * mesh_file);
75
76int main(int argc, char *argv[])
77{
78 // 1. Initialize MPI and HYPRE.
79 Mpi::Init(argc, argv);
80 int num_procs = Mpi::WorldSize();
81 int myid = Mpi::WorldRank();
83
84 // 2. Parse command-line options.
85 const char *mesh_file = "../data/inline-quad.mesh";
86 int ser_ref_levels = 1;
87 int par_ref_levels = 1;
88 int order = 1;
89 int prob = 0;
90 real_t freq = -1.0;
91 real_t a_coef = 0.0;
92 bool visualization = 1;
93 bool herm_conv = true;
94 bool exact_sol = true;
95 bool pa = false;
96 const char *device_config = "cpu";
97
98 OptionsParser args(argc, argv);
99 args.AddOption(&mesh_file, "-m", "--mesh",
100 "Mesh file to use.");
101 args.AddOption(&ser_ref_levels, "-rs", "--refine-serial",
102 "Number of times to refine the mesh uniformly in serial.");
103 args.AddOption(&par_ref_levels, "-rp", "--refine-parallel",
104 "Number of times to refine the mesh uniformly in parallel.");
105 args.AddOption(&order, "-o", "--order",
106 "Finite element order (polynomial degree).");
107 args.AddOption(&prob, "-p", "--problem-type",
108 "Choose between 0: H_1, 1: H(Curl), or 2: H(Div) "
109 "damped harmonic oscillator.");
110 args.AddOption(&a_coef, "-a", "--stiffness-coef",
111 "Stiffness coefficient (spring constant or 1/mu).");
112 args.AddOption(&epsilon_, "-b", "--mass-coef",
113 "Mass coefficient (or epsilon).");
114 args.AddOption(&sigma_, "-c", "--damping-coef",
115 "Damping coefficient (or sigma).");
116 args.AddOption(&mu_, "-mu", "--permeability",
117 "Permeability of free space (or 1/(spring constant)).");
118 args.AddOption(&epsilon_, "-eps", "--permittivity",
119 "Permittivity of free space (or mass constant).");
120 args.AddOption(&sigma_, "-sigma", "--conductivity",
121 "Conductivity (or damping constant).");
122 args.AddOption(&freq, "-f", "--frequency",
123 "Frequency (in Hz).");
124 args.AddOption(&herm_conv, "-herm", "--hermitian", "-no-herm",
125 "--no-hermitian", "Use convention for Hermitian operators.");
126 args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
127 "--no-visualization",
128 "Enable or disable GLVis visualization.");
129 args.AddOption(&pa, "-pa", "--partial-assembly", "-no-pa",
130 "--no-partial-assembly", "Enable Partial Assembly.");
131 args.AddOption(&device_config, "-d", "--device",
132 "Device configuration string, see Device::Configure().");
133 args.Parse();
134 if (!args.Good())
135 {
136 if (myid == 0)
137 {
138 args.PrintUsage(cout);
139 }
140 return 1;
141 }
142 if (myid == 0)
143 {
144 args.PrintOptions(cout);
145 }
146
147 MFEM_VERIFY(prob >= 0 && prob <=2,
148 "Unrecognized problem type: " << prob);
149
150 if ( a_coef != 0.0 )
151 {
152 mu_ = 1.0 / a_coef;
153 }
154 if ( freq > 0.0 )
155 {
156 omega_ = 2.0 * M_PI * freq;
157 }
158
159 exact_sol = check_for_inline_mesh(mesh_file);
160 if (myid == 0 && exact_sol)
161 {
162 cout << "Identified a mesh with known exact solution" << endl;
163 }
164
167
168 // 3. Enable hardware devices such as GPUs, and programming models such as
169 // CUDA, OCCA, RAJA and OpenMP based on command line options.
170 Device device(device_config);
171 if (myid == 0) { device.Print(); }
172
173 // 4. Read the (serial) mesh from the given mesh file on all processors. We
174 // can handle triangular, quadrilateral, tetrahedral, hexahedral, surface
175 // and volume meshes with the same code.
176 Mesh *mesh = new Mesh(mesh_file, 1, 1);
177 int dim = mesh->Dimension();
178
179 // 5. Refine the serial mesh on all processors to increase the resolution.
180 for (int l = 0; l < ser_ref_levels; l++)
181 {
182 mesh->UniformRefinement();
183 }
184
185 // 6. Define a parallel mesh by a partitioning of the serial mesh. Refine
186 // this mesh further in parallel to increase the resolution. Once the
187 // parallel mesh is defined, the serial mesh can be deleted.
188 ParMesh *pmesh = new ParMesh(MPI_COMM_WORLD, *mesh);
189 delete mesh;
190 for (int l = 0; l < par_ref_levels; l++)
191 {
192 pmesh->UniformRefinement();
193 }
194
195 // 7. Define a parallel finite element space on the parallel mesh. Here we
196 // use continuous Lagrange, Nedelec, or Raviart-Thomas finite elements of
197 // the specified order.
198 if (dim == 1 && prob != 0 )
199 {
200 if (myid == 0)
201 {
202 cout << "Switching to problem type 0, H1 basis functions, "
203 << "for 1 dimensional mesh." << endl;
204 }
205 prob = 0;
206 }
207
208 FiniteElementCollection *fec = NULL;
209 switch (prob)
210 {
211 case 0: fec = new H1_FECollection(order, dim); break;
212 case 1: fec = new ND_FECollection(order, dim); break;
213 case 2: fec = new RT_FECollection(order - 1, dim); break;
214 default: break; // This should be unreachable
215 }
216 ParFiniteElementSpace *fespace = new ParFiniteElementSpace(pmesh, fec);
217 HYPRE_BigInt size = fespace->GlobalTrueVSize();
218 if (myid == 0)
219 {
220 cout << "Number of finite element unknowns: " << size << endl;
221 }
222
223 // 8. Determine the list of true (i.e. parallel conforming) essential
224 // boundary dofs. In this example, the boundary conditions are defined
225 // based on the type of mesh and the problem type.
227 Array<int> ess_bdr;
228 if (pmesh->bdr_attributes.Size())
229 {
230 ess_bdr.SetSize(pmesh->bdr_attributes.Max());
231 ess_bdr = 1;
232 fespace->GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
233 }
234
235 // 9. Set up the parallel linear form b(.) which corresponds to the
236 // right-hand side of the FEM linear system.
237 ParComplexLinearForm b(fespace, conv);
238 b = 0.0;
239
240 // 10. Define the solution vector u as a parallel complex finite element grid
241 // function corresponding to fespace. Initialize u with initial guess of
242 // 1+0i or the exact solution if it is known.
243 ParComplexGridFunction u(fespace);
245 if (exact_sol) { u_exact = new ParComplexGridFunction(fespace); }
246
253
254 ConstantCoefficient zeroCoef(0.0);
255 ConstantCoefficient oneCoef(1.0);
256
257 Vector zeroVec(dim); zeroVec = 0.0;
258 Vector oneVec(dim); oneVec = 0.0; oneVec[(prob==2)?(dim-1):0] = 1.0;
259 VectorConstantCoefficient zeroVecCoef(zeroVec);
260 VectorConstantCoefficient oneVecCoef(oneVec);
261
262 switch (prob)
263 {
264 case 0:
265 if (exact_sol)
266 {
267 u.ProjectBdrCoefficient(u0_r, u0_i, ess_bdr);
268 u_exact->ProjectCoefficient(u0_r, u0_i);
269 }
270 else
271 {
272 u.ProjectBdrCoefficient(oneCoef, zeroCoef, ess_bdr);
273 }
274 break;
275 case 1:
276 if (exact_sol)
277 {
278 u.ProjectBdrCoefficientTangent(u1_r, u1_i, ess_bdr);
279 u_exact->ProjectCoefficient(u1_r, u1_i);
280 }
281 else
282 {
283 u.ProjectBdrCoefficientTangent(oneVecCoef, zeroVecCoef, ess_bdr);
284 }
285 break;
286 case 2:
287 if (exact_sol)
288 {
289 u.ProjectBdrCoefficientNormal(u2_r, u2_i, ess_bdr);
290 u_exact->ProjectCoefficient(u2_r, u2_i);
291 }
292 else
293 {
294 u.ProjectBdrCoefficientNormal(oneVecCoef, zeroVecCoef, ess_bdr);
295 }
296 break;
297 default: break; // This should be unreachable
298 }
299
300 if (visualization && exact_sol)
301 {
302 char vishost[] = "localhost";
303 int visport = 19916;
304 socketstream sol_sock_r(vishost, visport);
305 sol_sock_r << "parallel " << num_procs << " " << myid << "\n";
306 sol_sock_r.precision(8);
307 sol_sock_r << "solution\n" << *pmesh << u_exact->real()
308 << "window_title 'Exact: Real Part'" << flush;
309 // Make sure all ranks have sent their real solution before initiating
310 // another set of GLVis connections (one from each rank):
311 MPI_Barrier(pmesh->GetComm());
312 socketstream sol_sock_i(vishost, visport);
313 sol_sock_i << "parallel " << num_procs << " " << myid << "\n";
314 sol_sock_i.precision(8);
315 sol_sock_i << "solution\n" << *pmesh << u_exact->imag()
316 << "window_title 'Exact: Imaginary Part'" << flush;
317 // Make sure all ranks have sent their imaginary solution before initiating
318 // another set of GLVis connections (one from each rank):
319 MPI_Barrier(pmesh->GetComm());
320 }
321
322 // 11. Set up the parallel sesquilinear form a(.,.) on the finite element
323 // space corresponding to the damped harmonic oscillator operator of the
324 // appropriate type:
325 //
326 // 0) A scalar H1 field
327 // -Div(a Grad) - omega^2 b + i omega c
328 //
329 // 1) A vector H(Curl) field
330 // Curl(a Curl) - omega^2 b + i omega c
331 //
332 // 2) A vector H(Div) field
333 // -Grad(a Div) - omega^2 b + i omega c
334 //
335 ConstantCoefficient stiffnessCoef(1.0/mu_);
336 ConstantCoefficient massCoef(-omega_ * omega_ * epsilon_);
337 ConstantCoefficient lossCoef(omega_ * sigma_);
338 ConstantCoefficient negMassCoef(omega_ * omega_ * epsilon_);
339
340 ParSesquilinearForm *a = new ParSesquilinearForm(fespace, conv);
341 if (pa) { a->SetAssemblyLevel(AssemblyLevel::PARTIAL); }
342 switch (prob)
343 {
344 case 0:
345 a->AddDomainIntegrator(new DiffusionIntegrator(stiffnessCoef),
346 NULL);
347 a->AddDomainIntegrator(new MassIntegrator(massCoef),
348 new MassIntegrator(lossCoef));
349 break;
350 case 1:
351 a->AddDomainIntegrator(new CurlCurlIntegrator(stiffnessCoef),
352 NULL);
353 a->AddDomainIntegrator(new VectorFEMassIntegrator(massCoef),
354 new VectorFEMassIntegrator(lossCoef));
355 break;
356 case 2:
357 a->AddDomainIntegrator(new DivDivIntegrator(stiffnessCoef),
358 NULL);
359 a->AddDomainIntegrator(new VectorFEMassIntegrator(massCoef),
360 new VectorFEMassIntegrator(lossCoef));
361 break;
362 default: break; // This should be unreachable
363 }
364
365 // 11a. Set up the parallel bilinear form for the preconditioner
366 // corresponding to the appropriate operator
367 //
368 // 0) A scalar H1 field
369 // -Div(a Grad) - omega^2 b + omega c
370 //
371 // 1) A vector H(Curl) field
372 // Curl(a Curl) + omega^2 b + omega c
373 //
374 // 2) A vector H(Div) field
375 // -Grad(a Div) - omega^2 b + omega c
376 //
377 ParBilinearForm *pcOp = new ParBilinearForm(fespace);
378 if (pa) { pcOp->SetAssemblyLevel(AssemblyLevel::PARTIAL); }
379 switch (prob)
380 {
381 case 0:
382 pcOp->AddDomainIntegrator(new DiffusionIntegrator(stiffnessCoef));
383 pcOp->AddDomainIntegrator(new MassIntegrator(massCoef));
384 pcOp->AddDomainIntegrator(new MassIntegrator(lossCoef));
385 break;
386 case 1:
387 pcOp->AddDomainIntegrator(new CurlCurlIntegrator(stiffnessCoef));
388 pcOp->AddDomainIntegrator(new VectorFEMassIntegrator(negMassCoef));
389 pcOp->AddDomainIntegrator(new VectorFEMassIntegrator(lossCoef));
390 break;
391 case 2:
392 pcOp->AddDomainIntegrator(new DivDivIntegrator(stiffnessCoef));
393 pcOp->AddDomainIntegrator(new VectorFEMassIntegrator(massCoef));
394 pcOp->AddDomainIntegrator(new VectorFEMassIntegrator(lossCoef));
395 break;
396 default: break; // This should be unreachable
397 }
398
399 // 12. Assemble the parallel bilinear form and the corresponding linear
400 // system, applying any necessary transformations such as: parallel
401 // assembly, eliminating boundary conditions, applying conforming
402 // constraints for non-conforming AMR, etc.
403 a->Assemble();
404 pcOp->Assemble();
405
407 Vector B, U;
408
409 a->FormLinearSystem(ess_tdof_list, u, b, A, U, B);
410
411 if (myid == 0)
412 {
413 cout << "Size of linear system: "
414 << 2 * fespace->GlobalTrueVSize() << endl << endl;
415 }
416
417 // 13. Define and apply a parallel FGMRES solver for AU=B with a block
418 // diagonal preconditioner based on the appropriate multigrid
419 // preconditioner from hypre.
420 {
421 Array<int> blockTrueOffsets;
422 blockTrueOffsets.SetSize(3);
423 blockTrueOffsets[0] = 0;
424 blockTrueOffsets[1] = A->Height() / 2;
425 blockTrueOffsets[2] = A->Height() / 2;
426 blockTrueOffsets.PartialSum();
427
428 BlockDiagonalPreconditioner BDP(blockTrueOffsets);
429
430 Operator * pc_r = NULL;
431 Operator * pc_i = NULL;
432
433 if (pa)
434 {
435 pc_r = new OperatorJacobiSmoother(*pcOp, ess_tdof_list);
436 }
437 else
438 {
439 OperatorHandle PCOp;
440 pcOp->FormSystemMatrix(ess_tdof_list, PCOp);
441 switch (prob)
442 {
443 case 0:
444 pc_r = new HypreBoomerAMG(*PCOp.As<HypreParMatrix>());
445 break;
446 case 1:
447 pc_r = new HypreAMS(*PCOp.As<HypreParMatrix>(), fespace);
448 break;
449 case 2:
450 if (dim == 2 )
451 {
452 pc_r = new HypreAMS(*PCOp.As<HypreParMatrix>(), fespace);
453 }
454 else
455 {
456 pc_r = new HypreADS(*PCOp.As<HypreParMatrix>(), fespace);
457 }
458 break;
459 default: break; // This should be unreachable
460 }
461 }
462 pc_i = new ScaledOperator(pc_r,
464 -1.0:1.0);
465
466 BDP.SetDiagonalBlock(0, pc_r);
467 BDP.SetDiagonalBlock(1, pc_i);
468 BDP.owns_blocks = 1;
469
470 FGMRESSolver fgmres(MPI_COMM_WORLD);
471 fgmres.SetPreconditioner(BDP);
472 fgmres.SetOperator(*A.Ptr());
473 fgmres.SetRelTol(1e-12);
474 fgmres.SetMaxIter(1000);
475 fgmres.SetPrintLevel(1);
476 fgmres.Mult(B, U);
477 }
478 // 14. Recover the parallel grid function corresponding to U. This is the
479 // local finite element solution on each processor.
480 a->RecoverFEMSolution(U, b, u);
481
482 if (exact_sol)
483 {
484 real_t err_r = -1.0;
485 real_t err_i = -1.0;
486
487 switch (prob)
488 {
489 case 0:
490 err_r = u.real().ComputeL2Error(u0_r);
491 err_i = u.imag().ComputeL2Error(u0_i);
492 break;
493 case 1:
494 err_r = u.real().ComputeL2Error(u1_r);
495 err_i = u.imag().ComputeL2Error(u1_i);
496 break;
497 case 2:
498 err_r = u.real().ComputeL2Error(u2_r);
499 err_i = u.imag().ComputeL2Error(u2_i);
500 break;
501 default: break; // This should be unreachable
502 }
503
504 if ( myid == 0 )
505 {
506 cout << endl;
507 cout << "|| Re (u_h - u) ||_{L^2} = " << err_r << endl;
508 cout << "|| Im (u_h - u) ||_{L^2} = " << err_i << endl;
509 cout << endl;
510 }
511 }
512
513 // 15. Save the refined mesh and the solution in parallel. This output can be
514 // viewed later using GLVis: "glvis -np <np> -m mesh -g sol".
515 {
516 ostringstream mesh_name, sol_r_name, sol_i_name, sol_z_name;
517 mesh_name << "mesh." << setfill('0') << setw(6) << myid;
518 sol_r_name << "sol_r." << setfill('0') << setw(6) << myid;
519 sol_i_name << "sol_i." << setfill('0') << setw(6) << myid;
520 sol_z_name << "sol_z." << setfill('0') << setw(6) << myid;
521
522 ofstream mesh_ofs(mesh_name.str().c_str());
523 mesh_ofs.precision(8);
524 pmesh->Print(mesh_ofs);
525
526 ofstream sol_r_ofs(sol_r_name.str().c_str());
527 ofstream sol_i_ofs(sol_i_name.str().c_str());
528 ofstream sol_z_ofs(sol_z_name.str().c_str());
529 sol_r_ofs.precision(8);
530 sol_i_ofs.precision(8);
531 sol_z_ofs.precision(8);
532 u.real().Save(sol_r_ofs);
533 u.imag().Save(sol_i_ofs);
534 u.Save(sol_z_ofs);
535 }
536
537 // 16. Send the solution by socket to a GLVis server.
538 if (visualization)
539 {
540 char vishost[] = "localhost";
541 int visport = 19916;
542 socketstream sol_sock_r(vishost, visport);
543 sol_sock_r << "parallel " << num_procs << " " << myid << "\n";
544 sol_sock_r.precision(8);
545 sol_sock_r << "solution\n" << *pmesh << u.real()
546 << "window_title 'Solution: Real Part'" << flush;
547 // Make sure all ranks have sent their real solution before initiating
548 // another set of GLVis connections (one from each rank):
549 MPI_Barrier(pmesh->GetComm());
550 socketstream sol_sock_i(vishost, visport);
551 sol_sock_i << "parallel " << num_procs << " " << myid << "\n";
552 sol_sock_i.precision(8);
553 sol_sock_i << "solution\n" << *pmesh << u.imag()
554 << "window_title 'Solution: Imaginary Part'" << flush;
555 // Make sure all ranks have sent their imaginary solution before initiating
556 // another set of GLVis connections (one from each rank):
557 MPI_Barrier(pmesh->GetComm());
558 }
559 if (visualization && exact_sol)
560 {
561 *u_exact -= u;
562
563 char vishost[] = "localhost";
564 int visport = 19916;
565 socketstream sol_sock_r(vishost, visport);
566 sol_sock_r << "parallel " << num_procs << " " << myid << "\n";
567 sol_sock_r.precision(8);
568 sol_sock_r << "solution\n" << *pmesh << u_exact->real()
569 << "window_title 'Error: Real Part'" << flush;
570 // Make sure all ranks have sent their real solution before initiating
571 // another set of GLVis connections (one from each rank):
572 MPI_Barrier(pmesh->GetComm());
573 socketstream sol_sock_i(vishost, visport);
574 sol_sock_i << "parallel " << num_procs << " " << myid << "\n";
575 sol_sock_i.precision(8);
576 sol_sock_i << "solution\n" << *pmesh << u_exact->imag()
577 << "window_title 'Error: Imaginary Part'" << flush;
578 // Make sure all ranks have sent their imaginary solution before initiating
579 // another set of GLVis connections (one from each rank):
580 MPI_Barrier(pmesh->GetComm());
581 }
582 if (visualization)
583 {
584 ParGridFunction u_t(fespace);
585 u_t = u.real();
586 char vishost[] = "localhost";
587 int visport = 19916;
588 socketstream sol_sock(vishost, visport);
589 sol_sock << "parallel " << num_procs << " " << myid << "\n";
590 sol_sock.precision(8);
591 sol_sock << "solution\n" << *pmesh << u_t
592 << "window_title 'Harmonic Solution (t = 0.0 T)'"
593 << "pause\n" << flush;
594 if (myid == 0)
595 cout << "GLVis visualization paused."
596 << " Press space (in the GLVis window) to resume it.\n";
597 int num_frames = 32;
598 int i = 0;
599 while (sol_sock)
600 {
601 real_t t = (real_t)(i % num_frames) / num_frames;
602 ostringstream oss;
603 oss << "Harmonic Solution (t = " << t << " T)";
604
605 add(cos( 2.0 * M_PI * t), u.real(),
606 sin(-2.0 * M_PI * t), u.imag(), u_t);
607 sol_sock << "parallel " << num_procs << " " << myid << "\n";
608 sol_sock << "solution\n" << *pmesh << u_t
609 << "window_title '" << oss.str() << "'" << flush;
610 i++;
611 }
612 }
613
614 // 17. Free the used memory.
615 delete a;
616 delete u_exact;
617 delete pcOp;
618 delete fespace;
619 delete fec;
620 delete pmesh;
621
622 return 0;
623}
624
625bool check_for_inline_mesh(const char * mesh_file)
626{
627 string file(mesh_file);
628 size_t p0 = file.find_last_of("/");
629 string s0 = file.substr((p0==string::npos)?0:(p0+1),7);
630 return s0 == "inline-";
631}
632
633complex<real_t> u0_exact(const Vector &x)
634{
635 int dim = x.Size();
636 complex<real_t> i(0.0, 1.0);
637 complex<real_t> alpha = (epsilon_ * omega_ - i * sigma_);
638 complex<real_t> kappa = std::sqrt(mu_ * omega_* alpha);
639 return std::exp(-i * kappa * x[dim - 1]);
640}
641
643{
644 return u0_exact(x).real();
645}
646
648{
649 return u0_exact(x).imag();
650}
651
652void u1_real_exact(const Vector &x, Vector &v)
653{
654 int dim = x.Size();
655 v.SetSize(dim); v = 0.0; v[0] = u0_real_exact(x);
656}
657
658void u1_imag_exact(const Vector &x, Vector &v)
659{
660 int dim = x.Size();
661 v.SetSize(dim); v = 0.0; v[0] = u0_imag_exact(x);
662}
663
664void u2_real_exact(const Vector &x, Vector &v)
665{
666 int dim = x.Size();
667 v.SetSize(dim); v = 0.0; v[dim-1] = u0_real_exact(x);
668}
669
670void u2_imag_exact(const Vector &x, Vector &v)
671{
672 int dim = x.Size();
673 v.SetSize(dim); v = 0.0; v[dim-1] = u0_imag_exact(x);
674}
void u_exact(const Vector &x, Vector &u)
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
void PartialSum()
Fill the entries of the array with the cumulative sum of the entries.
Definition array.cpp:104
void SetAssemblyLevel(AssemblyLevel assembly_level)
Set the desired assembly level.
void AddDomainIntegrator(BilinearFormIntegrator *bfi)
Adds new Domain Integrator. Assumes ownership of bfi.
A class to handle Block diagonal preconditioners in a matrix-free implementation.
void SetDiagonalBlock(int iblock, Operator *op)
Add a square block op in the block-entry (iblock, iblock).
@ HERMITIAN
Native convention for Hermitian operators.
@ BLOCK_SYMMETRIC
Alternate convention for damping operators.
A coefficient that is constant across space and time.
Integrator for for Nedelec elements.
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
FGMRES method.
Definition solvers.hpp:681
void Mult(const Vector &b, Vector &x) const override
Iterative solution of the linear system using the FGMRES method.
Definition solvers.cpp:1343
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
Definition fe_coll.hpp:27
A general function coefficient.
Arbitrary order H1-conforming (continuous) finite elements.
Definition fe_coll.hpp:291
The Auxiliary-space Divergence Solver in hypre.
Definition hypre.hpp:2066
The Auxiliary-space Maxwell Solver in hypre.
Definition hypre.hpp:1989
The BoomerAMG solver in hypre.
Definition hypre.hpp:1829
Wrapper for hypre's ParCSR matrix class.
Definition hypre.hpp:419
static void Init()
Initialize hypre by calling HYPRE_Init() and set default options. After calling Hypre::Init(),...
Definition hypre.cpp:33
void SetOperator(const Operator &op) override
Also calls SetOperator for the preconditioner if there is one.
Definition solvers.cpp:184
void SetRelTol(real_t rtol)
Definition solvers.hpp:238
virtual void SetPreconditioner(Solver &pr)
This should be called before SetOperator.
Definition solvers.cpp:178
virtual void SetPrintLevel(int print_lvl)
Legacy method to set the level of verbosity of the solver output.
Definition solvers.cpp:76
void SetMaxIter(int max_it)
Definition solvers.hpp:240
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
int Dimension() const
Dimension of the reference space used within the elements.
Definition mesh.hpp:1314
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
Definition mesh.cpp:12125
static int WorldRank()
Return the MPI rank in MPI_COMM_WORLD.
static int WorldSize()
Return the size of MPI_COMM_WORLD.
static void Init(int &argc, char **&argv, int required=default_thread_required, int *provided=nullptr)
Singleton creation with Mpi::Init(argc, argv).
Arbitrary order H(curl)-conforming Nedelec finite elements.
Definition fe_coll.hpp:526
Pointer to an Operator of a specified type.
Definition handle.hpp:34
OpType * As() const
Return the Operator pointer statically cast to a specified OpType. Similar to the method Get().
Definition handle.hpp:104
Operator * Ptr() const
Access the underlying Operator pointer.
Definition handle.hpp:87
Jacobi smoothing for a given bilinear form (no matrix necessary).
Definition solvers.hpp:422
Abstract operator.
Definition operator.hpp:27
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
Definition operator.hpp:68
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.
Class for parallel bilinear form.
void Assemble(int skip_zeros=1)
Assemble the local matrix.
void FormSystemMatrix(const Array< int > &ess_tdof_list, OperatorHandle &A) override
Form the linear system matrix A, see FormLinearSystem() for details.
Abstract parallel finite element space.
Definition pfespace.hpp:31
void GetEssentialTrueDofs(const Array< int > &bdr_attr_is_ess, Array< int > &ess_tdof_list, int component=-1) const override
HYPRE_BigInt GlobalTrueVSize() const
Definition pfespace.hpp:361
Class for parallel grid function.
Definition pgridfunc.hpp:50
Class for parallel meshes.
Definition pmesh.hpp:35
MPI_Comm GetComm() const
Definition pmesh.hpp:403
void Print(std::ostream &out=mfem::out, const std::string &comments="") const override
Definition pmesh.cpp:4856
Arbitrary order H(div)-conforming Raviart-Thomas finite elements.
Definition fe_coll.hpp:430
Scaled Operator B: x -> a A(x).
Definition operator.hpp:899
Vector coefficient that is constant in space and time.
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
void SetSize(int s)
Resize the vector to size s.
Definition vector.hpp:633
const int * ess_tdof_list
const real_t alpha
Definition ex15.cpp:369
void u2_real_exact(const Vector &, Vector &)
Definition ex22p.cpp:664
bool check_for_inline_mesh(const char *mesh_file)
Definition ex22p.cpp:625
void u1_imag_exact(const Vector &, Vector &)
Definition ex22p.cpp:658
real_t u0_real_exact(const Vector &)
Definition ex22p.cpp:642
void u1_real_exact(const Vector &, Vector &)
Definition ex22p.cpp:652
real_t u0_imag_exact(const Vector &)
Definition ex22p.cpp:647
void u2_imag_exact(const Vector &, Vector &)
Definition ex22p.cpp:670
complex< real_t > u0_exact(const Vector &x)
Definition ex22p.cpp:633
real_t kappa
Definition ex24.cpp:54
int dim
Definition ex24.cpp:53
real_t freq
Definition ex24.cpp:54
prob_type prob
Definition ex25.cpp:156
int main()
HYPRE_Int HYPRE_BigInt
real_t b
Definition lissajous.cpp:42
real_t a
Definition lissajous.cpp:41
real_t u(const Vector &xvec)
Definition lor_mms.hpp:22
void add(const Vector &v1, const Vector &v2, Vector &v)
Definition vector.cpp:414
float real_t
Definition config.hpp:46
const char vishost[]
STL namespace.