MFEM v4.9.0
Finite element discretization library
Loading...
Searching...
No Matches
ex41p.cpp
Go to the documentation of this file.
1// MFEM Example 41 - Parallel Version
2//
3// Compile with: make ex41p
4//
5// Sample runs:
6// mpirun -np 4 ex41p
7// mpirun -np 4 ex41p -cg
8// mpirun -np 4 ex41p -m ../data/periodic-hexagon.mesh -p 0 -dt 0.005 -tf 10
9// mpirun -np 4 ex41p -m ../data/periodic-square.mesh -p 1 -dt 0.005 -tf 9
10// mpirun -np 4 ex41p -m ../data/periodic-hexagon.mesh -p 1 -dt 0.005 -tf 9
11// mpirun -np 4 ex41p -m ../data/star-q3.mesh -p 1 -rp 1 -dt 0.001 -tf 9
12// mpirun -np 4 ex41p -m ../data/disc-nurbs.mesh -p 1 -rp 1 -dt 0.005 -tf 9
13// mpirun -np 4 ex41p -m ../data/disc-nurbs.mesh -p 2 -rp 1 -dt 0.005 -tf 9
14// mpirun -np 4 ex41p -m ../data/periodic-square.mesh -rp 2 -dt 0.0025 -tf 9 -vs 20
15// mpirun -np 4 ex41p -m ../data/periodic-cube.mesh -p 0 -rs 2 -o 2 -dt 0.01 -tf 8
16//
17// Device sample runs:
18//
19// Description: This example code solves the time-dependent advection-diffusion
20// equation du/dt + v.grad(u) - a div(grad(u)) = 0, where v is a
21// given fluid velocity, a is the diffusion coefficient, and
22// u0(x)=u(0,x) is a given initial condition.
23//
24// The example demonstrates the use of Discontinuous Galerkin (DG)
25// bilinear forms in MFEM (face integrators), DG-LOR Preconditioning
26// and the use of IMEX ODE time integrators.
27//
28// The Option to use Continuous Finite Elements is available too.
29
30#include "mfem.hpp"
31
32using namespace std;
33using namespace mfem;
34
35// Mesh bounding box
37
38// Velocity coefficient
39template<int problem=0>
41{
42 int dim = x.Size();
43
44 // map to the reference [-1,1] domain
45 Vector X(dim);
46 for (int i = 0; i < dim; i++)
47 {
48 real_t center = (bb_min[i] + bb_max[i]) * 0.5;
49 X(i) = 2 * (x(i) - center) / (bb_max[i] - bb_min[i]);
50 }
51 switch (problem)
52 {
53 case 0:
54 {
55 // Translations in 1D, 2D, and 3D
56 switch (dim)
57 {
58 case 1: v(0) = 1.0; break;
59 case 2: v(0) = sqrt(2./3.); v(1) = sqrt(1./3.); break;
60 case 3: v(0) = sqrt(3./6.); v(1) = sqrt(2./6.); v(2) = sqrt(1./6.);
61 break;
62 }
63 break;
64 }
65 case 1:
66 case 2:
67 {
68 // Clockwise rotation in 2D around the origin
69 const real_t w = M_PI/2;
70 switch (dim)
71 {
72 case 1: v(0) = 1.0; break;
73 case 2: v(0) = w*X(1); v(1) = -w*X(0); break;
74 case 3: v(0) = w*X(1); v(1) = -w*X(0); v(2) = 0.0; break;
75 }
76 break;
77 }
78 case 3:
79 {
80 // Clockwise twisting rotation in 2D around the origin
81 const real_t w = M_PI/2;
82 real_t d = max((X(0)+1.)*(1.-X(0)),0.) * max((X(1)+1.)*(1.-X(1)),0.);
83 d = d*d;
84 switch (dim)
85 {
86 case 1: v(0) = 1.0; break;
87 case 2: v(0) = d*w*X(1); v(1) = -d*w*X(0); break;
88 case 3: v(0) = d*w*X(1); v(1) = -d*w*X(0); v(2) = 0.0; break;
89 }
90 break;
91 }
92 }
93}
94
95
96// Initial condition
97template<int problem=0>
99{
100 int dim = x.Size();
101
102 // map to the reference [-1,1] domain
103 Vector X(dim);
104 for (int i = 0; i < dim; i++)
105 {
106 real_t center = (bb_min[i] + bb_max[i]) * 0.5;
107 X(i) = 2 * (x(i) - center) / (bb_max[i] - bb_min[i]);
108 }
109
110 switch (problem)
111 {
112 case 0:
113 case 1:
114 {
115 switch (dim)
116 {
117 case 1:
118 return exp(-40.*pow(X(0)-0.5,2));
119 case 2:
120 case 3:
121 {
122 real_t rx = 0.45, ry = 0.25, cx = 0., cy = -0.2, w = 10.;
123 if (dim == 3)
124 {
125 const real_t s = (1. + 0.25*cos(2*M_PI*X(2)));
126 rx *= s;
127 ry *= s;
128 }
129 return ( std::erfc(w*(X(0)-cx-rx))*std::erfc(-w*(X(0)-cx+rx)) *
130 std::erfc(w*(X(1)-cy-ry))*std::erfc(-w*(X(1)-cy+ry)) )/16;
131 }
132 }
133 }
134 case 2:
135 {
136 real_t x_ = X(0), y_ = X(1), rho, phi;
137 rho = std::hypot(x_, y_);
138 phi = atan2(y_, x_);
139 return pow(sin(M_PI*rho),2)*sin(3*phi);
140 }
141 case 3:
142 {
143 const real_t f = M_PI;
144 return sin(f*X(0))*sin(f*X(1));
145 }
146 }
147 return 0.0;
148}
149
150
151class Implicit_Solver : public Solver
152{
153private:
154 HypreParMatrix &M, &S;
156 CGSolver linear_solver;
157 real_t dt;
158 SparseMatrix M_diag;
159public:
160 Implicit_Solver(HypreParMatrix &M_, HypreParMatrix &S_,
161 const FiniteElementSpace &fes)
162 : M(M_),
163 S(S_),
164 A(nullptr),
165 linear_solver(M.GetComm()),
166 dt(1.0)
167 {
168 linear_solver.iterative_mode = false;
169 linear_solver.SetRelTol(1e-9);
170 linear_solver.SetAbsTol(0.0);
171 linear_solver.SetMaxIter(100);
172 linear_solver.SetPrintLevel(0);
173
174 M.GetDiag(M_diag);
175 }
176
177 void SetTimeStep(real_t dt_)
178 {
179 real_t ddt = dt-dt_;
180
181 // syncronize ddt across all processes
182 MPI_Comm comm = M.GetComm();
183 int myrank;
184 MPI_Comm_rank(comm, &myrank);
185 MPI_Bcast(&ddt, 1, MPI_DOUBLE, 0, comm);
186
188 epsilon = std::numeric_limits<real_t>::epsilon();
189 // allow for some tolerance in the time stepping process
190 epsilon*=10;
191
192 if (fabs(ddt) > epsilon)
193 {
194 if (0==myrank)
195 {
196 cout << "Updating Implicit_Solver time step from " << dt
197 << " to " << dt_ << endl;
198 }
199
200 delete A;
201 dt = dt_;
202 // Form operator A = M + dt*S
203 A = Add(dt, S, 1.0, M);
204 linear_solver.SetOperator(*A);
205 }
206 }
207
208 void SetOperator(const Operator &op) override
209 {
210 linear_solver.SetOperator(op);
211 }
212
213 void Mult(const Vector &x, Vector &y) const override
214 {
215 linear_solver.Mult(x, y);
216 }
217
218 void SetPreconditioner(Solver &precond)
219 {
220 linear_solver.SetPreconditioner(precond);
221 }
222
223 ~Implicit_Solver() override
224 {
225 delete A;
226 }
227};
228
229/** A time-dependent operator for the right-hand side of the ODE. The DG weak
230 form of the advection-diffusion equation is (M + dt S) du/dt = Su - K u + b
231 , where M and K are the mass and advection matrices, and b describes the
232 flow on the boundary. In the case of IMEX evolution, the diffusion term is
233 treated implicitly, and the advection term is treated explicitly. */
234class IMEX_Evolution : public TimeDependentOperator
235{
236private:
237 OperatorHandle M, K, S, A;
238 const Vector &b;
239 Solver *M_prec;
240 CGSolver M_solver;
241 Implicit_Solver *implicit_solver;
242 LORSolver<HypreBoomerAMG>* lor_solver;
243
244 mutable Vector z;
245 mutable Vector w;
246
247public:
248 IMEX_Evolution(ParBilinearForm &M_, ParBilinearForm &K_, ParBilinearForm &S_,
249 const Vector &b_, ParBilinearForm &A_);
250
251 virtual
252 ~IMEX_Evolution()
253 {
254 delete implicit_solver;
255 delete lor_solver;
256 delete M_prec;
257 }
258
259 void Mult1(const Vector &x, Vector &y) const;
260
261 void ImplicitSolve2(const real_t dt, const Vector &x, Vector &k);
262
263 void Mult(const Vector &x, Vector &y) const override
264 {
265 if (TimeDependentOperator::EvalMode::ADDITIVE_TERM_1 == GetEvalMode())
266 {
267 Mult1(x,y);
268 }
269 else
270 {
271 mfem_error("TimeDependentOperator::Mult() is not overridden!");
272 }
273 }
274
275 void ImplicitSolve(const real_t dt, const Vector &x, Vector &k) override
276 {
277 if (TimeDependentOperator::EvalMode::ADDITIVE_TERM_2 == GetEvalMode())
278 {
279 ImplicitSolve2(dt,x,k);
280 }
281 else
282 {
283 mfem_error("TimeDependentOperator::ImplicitSolve() is not overridden!");
284 }
285 }
286};
287
288
289int main(int argc, char *argv[])
290{
291 // 1. Initialize MPI and HYPRE.
292 Mpi::Init();
293 int num_procs = Mpi::WorldSize();
294 int myid = Mpi::WorldRank();
295 Hypre::Init();
296
297 // 2. Parse command-line options.
298 int problem = 0;
299 const char *mesh_file = "../data/periodic-square.mesh";
300 int ser_ref_levels = 2;
301 int par_ref_levels = 0;
302 int order = 3;
303 int ode_solver_type = 64; // 61 - Forward Backward Euler
304 // 62 - IMEXRK2(2,2,2)
305 // 63 - IMEXRK2(2,3,2)
306 // 64 - IMEXRK3(3,4,3)
307 real_t t_final = 10.0;
308 real_t dt = 0.01;
309 bool paraview = false;
310 bool cg = false;
311 int vis_steps = 50;
312 bool adios2 = false;
313 bool binary = false;
314 real_t diffusion_term = 0.01;
315 real_t kappa = -1.0;
316 real_t sigma = -1.0;
317 bool visualization = true;
318 bool visit = false;
319 int precision = 16;
320 cout.precision(precision);
321
322 OptionsParser args(argc, argv);
323 args.AddOption(&mesh_file, "-m", "--mesh",
324 "Mesh file to use.");
325 args.AddOption(&problem, "-p", "--problem",
326 "Problem setup to use. See options in velocity_function().");
327 args.AddOption(&ser_ref_levels, "-rs", "--refine-serial",
328 "Number of times to refine the mesh uniformly in serial.");
329 args.AddOption(&par_ref_levels, "-rp", "--refine-parallel",
330 "Number of times to refine the mesh uniformly in parallel.");
331 args.AddOption(&order, "-o", "--order",
332 "Order (degree) of the finite elements.");
333 args.AddOption(&ode_solver_type, "-s", "--ode-solver",
334 ODESolver::IMEXTypes.c_str());
335 args.AddOption(&t_final, "-tf", "--t-final",
336 "Final time; start time is 0.");
337 args.AddOption(&dt, "-dt", "--time-step",
338 "Time step.");
339 args.AddOption(&diffusion_term, "-dc", "--diffusion-coeff",
340 "Diffusion coefficient in the PDE.");
341 args.AddOption(&paraview, "-paraview", "--paraview-datafiles", "-no-paraview",
342 "--no-paraview-datafiles",
343 "Save data files for ParaView (paraview.org) visualization.");
344 args.AddOption(&visit, "-visit", "--visit-datafiles", "-no-visit",
345 "--no-visit-datafiles",
346 "Save data files for VisIt (visit.llnl.gov) visualization.");
347 args.AddOption(&adios2, "-adios2", "--adios2-streams", "-no-adios2",
348 "--no-adios2-streams",
349 "Save data using adios2 streams.");
350 args.AddOption(&binary, "-binary", "--binary-datafiles", "-ascii",
351 "--ascii-datafiles",
352 "Use binary (Sidre) or ascii format for VisIt data files.");
353 args.AddOption(&vis_steps, "-vs", "--visualization-steps",
354 "Visualize every n-th timestep.");
355 args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
356 "--no-visualization",
357 "Enable or disable GLVis visualization.");
358 args.AddOption(&cg, "-cg", "--continuous-galerkin", "-dg",
359 "--discontinuous-galerkin",
360 "Use Continuous-Galerkin Finite elements (Default is DG)");
361 args.Parse();
362 if (!args.Good())
363 {
364 if (Mpi::Root())
365 {
366 args.PrintUsage(cout);
367 }
368 return 1;
369 }
370 if (Mpi::Root())
371 {
372 args.PrintOptions(cout);
373 }
374 if (kappa < 0)
375 {
376 kappa = (order+1)*(order+1);
377 }
378
379 // 3. Read the mesh from the given mesh file. We can handle geometrically
380 // periodic meshes in this code.
381 Mesh *mesh = new Mesh(mesh_file);
382 const int dim = mesh->Dimension();
383
384 // 4. Define the IMEX (Split) ODE solver used for time integration. The IMEX
385 // solvers currently available are: 55 - Forward Backward Euler,
386 // 56 - IMEXRK2(2,2,2), 57 - IMEXRK2(2,3,2), and
387 unique_ptr<ODESolver> ode_solver = ODESolver::SelectIMEX(ode_solver_type);
388
389 // 5. Refine the mesh to increase the resolution. In this example we do
390 // 'ref_levels' of uniform refinement, where 'ref_levels' is a
391 // command-line parameter.
392 for (int lev = 0; lev < ser_ref_levels; lev++) { mesh->UniformRefinement(); }
393 if (mesh->NURBSext)
394 {
395 mesh->SetCurvature(max(order, 1));
396 }
397 mesh->GetBoundingBox(bb_min, bb_max, max(order, 1));
398
399
400 // 6. Define the parallel mesh by a partitioning of the serial mesh. Refine
401 // this mesh further in parallel to increase the resolution. Once the
402 // parallel mesh is defined, the serial mesh can be deleted.
403 ParMesh *pmesh = new ParMesh(MPI_COMM_WORLD, *mesh);
404 delete mesh;
405 for (int lev = 0; lev < par_ref_levels; lev++)
406 {
407 pmesh->UniformRefinement();
408 }
409
410 // 7. Define the discontinuous DG finite element space of the given
411 // polynomial order on the refined mesh.
412 FiniteElementCollection *fec = NULL;
413 if (cg)
414 {
415 fec = new H1_FECollection(order, dim);
416 }
417 else
418 {
420 }
421 ParFiniteElementSpace *fes = new ParFiniteElementSpace(pmesh, fec);
422
423 HYPRE_BigInt global_vSize = fes->GlobalTrueVSize();
424 if (Mpi::Root())
425 {
426 cout << "Number of unknowns: " << global_vSize << endl;
427 }
428
429 // 8. Set up and assemble the bilinear and linear forms corresponding to the
430 // DG discretization. The DGTraceIntegrator involves integrals over mesh
431 // interior faces.
432 std::unique_ptr<VectorFunctionCoefficient> velocity;
433 if (0==problem)
434 {
436 }
437 else if (1==problem)
438 {
440 }
441 else if (2==problem)
442 {
444 }
445 else if (3==problem)
446 {
448 }
449 ConstantCoefficient diff_coeff(diffusion_term);
450 ConstantCoefficient dt_diff_coeff(dt*diffusion_term);
451
452 ParBilinearForm *m = new ParBilinearForm(fes);
453 ParBilinearForm *k = new ParBilinearForm(fes);
454 ParBilinearForm *s = new ParBilinearForm(fes);
455
457
458 constexpr real_t alpha = -1.0;
460
461 s->AddDomainIntegrator(new DiffusionIntegrator(diff_coeff));
462
463 // For the preconditioner - create billinear form corresponding to
464 // operator (M + dt S)
466 a->AddDomainIntegrator(new MassIntegrator);
467 a->AddDomainIntegrator(new DiffusionIntegrator(dt_diff_coeff));
468 if (!cg)
469 {
471 alpha));
474 kappa));
476 a->AddInteriorFaceIntegrator(new DGDiffusionIntegrator(dt_diff_coeff, sigma,
477 kappa));
478 a->AddBdrFaceIntegrator(new DGDiffusionIntegrator(dt_diff_coeff, sigma, kappa));
479 }
480
481 int skip_zeros = 0;
482 m->Assemble(skip_zeros);
483 k->Assemble(skip_zeros);
484 s->Assemble(skip_zeros);
485 a->Assemble();
486
487 m->Finalize(skip_zeros);
488 k->Finalize(skip_zeros);
489 s->Finalize(skip_zeros);
490 a->Finalize(skip_zeros);
491 HypreParVector b(fes);
492 b = 0.0;
493
494 // 9. Define the initial conditions. Set up visualization (if desired).
495 std::unique_ptr<FunctionCoefficient> u0;
496 if (0==problem)
497 {
498 u0.reset(new FunctionCoefficient(u0_function<0>));
499 }
500 else if (1==problem)
501 {
502 u0.reset(new FunctionCoefficient(u0_function<1>));
503 }
504 else if (2==problem)
505 {
506 u0.reset(new FunctionCoefficient(u0_function<2>));
507 }
508 else if (3==problem)
509 {
510 u0.reset(new FunctionCoefficient(u0_function<3>));
511 }
513 u->ProjectCoefficient(*u0);
514 HypreParVector *U = u->GetTrueDofs();
515
516 DataCollection *dc = NULL;
517 if (visit)
518 {
519 if (binary)
520 {
521#ifdef MFEM_USE_SIDRE
522 dc = new SidreDataCollection("Example41-Parallel", pmesh);
523#else
524 MFEM_ABORT("Must build with MFEM_USE_SIDRE=YES for binary output.");
525#endif
526 }
527 else
528 {
529 dc = new VisItDataCollection("Example41-Parallel", pmesh);
530 dc->SetPrecision(precision);
531 // To save the mesh using MFEM's parallel mesh format:
532 // dc->SetFormat(DataCollection::PARALLEL_FORMAT);
533 }
534 dc->RegisterField("solution", u);
535 dc->SetCycle(0);
536 dc->SetTime(0.0);
537 dc->Save();
538 }
539 ParaViewDataCollection *pd = NULL;
540 if (paraview)
541 {
542 pd = new ParaViewDataCollection("Example41P", pmesh);
543 pd->SetPrefixPath("ParaView");
544 pd->RegisterField("solution", u);
545 pd->SetLevelsOfDetail(order);
546 pd->SetDataFormat(VTKFormat::BINARY);
547 pd->SetHighOrderOutput(true);
548 pd->SetCycle(0);
549 pd->SetTime(0.0);
550 pd->Save();
551 }
552 socketstream sout;
553 if (visualization)
554 {
555 char vishost[] = "localhost";
556 int visport = 19916;
557 sout.open(vishost, visport);
558 if (!sout)
559 {
560 if (Mpi::Root())
561 {
562 cout << "Unable to connect to GLVis server at "
563 << vishost << ':' << visport << endl;
564 }
565 visualization = false;
566 if (Mpi::Root())
567 {
568 cout << "GLVis visualization disabled.\n";
569 }
570 }
571 else
572 {
573 sout << "parallel " << num_procs << " " << myid << "\n";
574 sout.precision(precision);
575 sout << "solution\n" << *pmesh << *u;
576 sout << "pause\n";
577 sout << flush;
578 if (Mpi::Root())
579 {
580 cout << "GLVis visualization paused."
581 << " Press space (in the GLVis window) to resume it.\n";
582 }
583 }
584 }
585#ifdef MFEM_USE_ADIOS2
586 ADIOS2DataCollection *adios2_dc = NULL;
587 if (adios2)
588 {
589 std::string postfix(mesh_file);
590 postfix.erase(0, std::string("../data/").size() );
591 postfix += "_o" + std::to_string(order);
592 const std::string collection_name = "ex41-p-" + postfix + ".bp";
593
594 adios2_dc = new ADIOS2DataCollection(MPI_COMM_WORLD, collection_name, pmesh);
595 // output data substreams are half the number of mpi processes
596 adios2_dc->SetParameter("SubStreams", std::to_string(num_procs/2) );
597 // adios2_dc->SetLevelsOfDetail(2);
598 adios2_dc->RegisterField("solution", u);
599 adios2_dc->SetCycle(0);
600 adios2_dc->SetTime(0.0);
601 adios2_dc->Save();
602 }
603#endif
604
605
606 // 10. Define the time-dependent evolution operator describing the
607 // ODE right-hand side, and perform time-integration (looping
608 // over the time iterations, ti, with a time-step dt).
609 IMEX_Evolution adv(*m, *k, *s, b, *a);
610
611 real_t t = 0.0;
612 adv.SetTime(t);
613 ode_solver->Init(adv);
614
615
616 bool done = false;
617 for (int ti = 0; !done; )
618 {
619 real_t dt_real = min(dt, t_final - t);
620 ode_solver->Step(*U, t, dt_real);
621 ti++;
622
623 done = (t >= t_final - 1e-8*dt);
624
625 if (done || ti % vis_steps == 0)
626 {
627 if (Mpi::Root())
628 {
629 cout << "time step: " << ti << ", time: " << t << endl;
630 }
631 *u = *U;
632 if (visualization)
633 {
634 sout << "parallel " << num_procs << " " << myid << "\n";
635 sout << "solution\n" << *pmesh << *u << flush;
636 }
637 if (paraview)
638 {
639 pd->SetCycle(ti);
640 pd->SetTime(t);
641 pd->Save();
642 }
643#ifdef MFEM_USE_ADIOS2
644 // transient solutions can be visualized with ParaView
645 if (adios2)
646 {
647 adios2_dc->SetCycle(ti);
648 adios2_dc->SetTime(t);
649 adios2_dc->Save();
650 }
651#endif
652 }
653 }
654
655 // 11. Free the used memory.
656 delete pd;
657 delete U;
658 delete u;
659 delete a;
660 delete s;
661 delete k;
662 delete m;
663 delete fes;
664 delete pmesh;
665 delete dc;
666 delete fec;
667
668 return 0;
669}
670
671// Implementation of class IMEX_Evolution
672IMEX_Evolution::IMEX_Evolution(ParBilinearForm &M_, ParBilinearForm &K_,
673 ParBilinearForm &S_, const Vector &b_, ParBilinearForm &A_)
674 : TimeDependentOperator(M_.ParFESpace()->GetTrueVSize()), b(b_),
675 M_solver(M_.ParFESpace()->GetComm()), z(height), w(height)
676{
677 if (M_.GetAssemblyLevel()==AssemblyLevel::LEGACY)
678 {
679 M.Reset(M_.ParallelAssemble(), true);
680 K.Reset(K_.ParallelAssemble(), true);
681 S.Reset(S_.ParallelAssemble(), true);
682 }
683 else
684 {
685 M.Reset(&M_, false);
686 K.Reset(&K_, false);
687 S.Reset(&S_, false);
688 }
689
690 M_solver.SetOperator(*M);
691
692 Array<int> ess_tdof_list;
693 if (M_.GetAssemblyLevel() == AssemblyLevel::LEGACY)
694 {
695 A.Reset(A_.ParallelAssemble(), true);
696 HypreParMatrix &M_mat = *M.As<HypreParMatrix>();
697 HypreParMatrix &S_mat = *S.As<HypreParMatrix>();
698 HypreSmoother *hypre_prec = new HypreSmoother(M_mat, HypreSmoother::Jacobi);
699 M_prec = hypre_prec;
700
701 implicit_solver = new Implicit_Solver(M_mat, S_mat, *M_.FESpace());
702 lor_solver = new LORSolver<HypreBoomerAMG>(A_, ess_tdof_list);
703 lor_solver->GetSolver().SetSystemsOptions(A_.ParFESpace()->GetVDim(), true);
704 implicit_solver -> SetPreconditioner(*lor_solver);
705 }
706 else
707 {
708 MFEM_ABORT("Implicit time integration is not supported with partial assembly");
709 }
710 M_solver.SetPreconditioner(*M_prec);
711 M_solver.iterative_mode = false;
712 M_solver.SetRelTol(1e-9);
713 M_solver.SetAbsTol(0.0);
714 M_solver.SetMaxIter(100);
715 M_solver.SetPrintLevel(0);
716}
717
718void IMEX_Evolution::Mult1(const Vector &x, Vector &y) const
719{
720 // Perform the explicit step
721 // y = M^{-1} (K x + b)
722 K->Mult(x, z);
723 z += b;
724 M_solver.Mult(z, y);
725}
726
727void IMEX_Evolution::ImplicitSolve2(const real_t dt, const Vector &x, Vector &k)
728{
729 // Perform the implicit step
730 // solve for k, k = -(M+dt S)^{-1} S x
731 MFEM_VERIFY(implicit_solver != NULL,
732 "Implicit time integration is not supported with partial assembly");
733 S->Mult(x, z);
734 z*= -1.0;
735 implicit_solver->SetTimeStep(dt);
736 implicit_solver->Mult(z, k);
737}
void SetParameter(const std::string key, const std::string value) noexcept
@ GaussLobatto
Closed type.
Definition fe_base.hpp:36
void AddDomainIntegrator(BilinearFormIntegrator *bfi)
Adds new Domain Integrator. Assumes ownership of bfi.
void Finalize(int skip_zeros=1) override
Finalizes the matrix initialization if the AssemblyLevel is AssemblyLevel::LEGACY....
FiniteElementSpace * FESpace()
Return the FE space associated with the BilinearForm.
AssemblyLevel GetAssemblyLevel() const
Returns the assembly level.
void AddBdrFaceIntegrator(BilinearFormIntegrator *bfi)
Adds new boundary Face Integrator. Assumes ownership of bfi.
void AddInteriorFaceIntegrator(BilinearFormIntegrator *bfi)
Adds new interior Face Integrator. Assumes ownership of bfi.
Conjugate gradient method.
Definition solvers.hpp:627
void Mult(const Vector &b, Vector &x) const override
Iterative solution of the linear system using the Conjugate Gradient method.
Definition solvers.cpp:869
void SetOperator(const Operator &op) override
Set/update the solver for the given operator.
Definition solvers.hpp:640
A coefficient that is constant across space and time.
void SetPrecision(int prec)
Set the precision (number of digits) used for the text output of doubles.
virtual void RegisterField(const std::string &field_name, GridFunction *gf)
Add a grid function to the collection.
void SetCycle(int c)
Set time cycle (for time-dependent simulations)
void SetTime(real_t t)
Set physical time (for time-dependent simulations)
void SetPrefixPath(const std::string &prefix)
Set the path where the DataCollection will be saved.
virtual void Save()
Save the collection to disk.
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:208
int GetVDim() const
Returns the vector dimension of the finite element space.
Definition fespace.hpp:819
A general function coefficient.
Arbitrary order H1-conforming (continuous) finite elements.
Definition fe_coll.hpp:279
Wrapper for hypre's ParCSR matrix class.
Definition hypre.hpp:419
void GetDiag(Vector &diag) const
Get the local diagonal of the matrix.
Definition hypre.cpp:1607
MPI_Comm GetComm() const
MPI communicator.
Definition hypre.hpp:609
Wrapper for hypre's parallel vector class.
Definition hypre.hpp:230
Parallel smoothers in hypre.
Definition hypre.hpp:1066
static void Init()
Initialize hypre by calling HYPRE_Init() and set default options. After calling Hypre::Init(),...
Definition hypre.cpp:33
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
void SetAbsTol(real_t atol)
Definition solvers.hpp:239
Represents a solver of type SolverType created using the low-order refined version of the given Bilin...
Definition lor.hpp:204
SolverType & GetSolver()
Access the underlying solver.
Definition lor.hpp:258
Mesh data type.
Definition mesh.hpp:65
NURBSExtension * NURBSext
Optional NURBS mesh extension.
Definition mesh.hpp:312
void GetBoundingBox(Vector &min, Vector &max, int ref=2)
Returns the minimum and maximum corners of the mesh bounding box.
Definition mesh.cpp:141
int Dimension() const
Dimension of the reference space used within the elements.
Definition mesh.hpp:1306
virtual void SetCurvature(int order, bool discont=false, int space_dim=-1, int ordering=1)
Set the curvature of the mesh nodes using the given polynomial degree.
Definition mesh.cpp:6799
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
Definition mesh.cpp:11637
static bool Root()
Return true if the rank in MPI_COMM_WORLD is zero.
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).
static MFEM_EXPORT std::unique_ptr< ODESolver > SelectIMEX(const int ode_solver_type)
Definition ode.cpp:115
static MFEM_EXPORT std::string IMEXTypes
Definition ode.hpp:198
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
void Reset(OpType *A, bool own_A=true)
Reset the OperatorHandle to the given OpType pointer, A.
Definition handle.hpp:145
Abstract operator.
Definition operator.hpp:25
virtual void Mult(const Vector &x, Vector &y) const =0
Operator application: y=A(x).
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.
HypreParMatrix * ParallelAssemble()
Returns the matrix assembled on the true dofs, i.e. P^t A P.
void Assemble(int skip_zeros=1)
Assemble the local matrix.
ParFiniteElementSpace * ParFESpace() const
Return the parallel FE space associated with the ParBilinearForm.
Abstract parallel finite element space.
Definition pfespace.hpp:31
HYPRE_BigInt GlobalTrueVSize() const
Definition pfespace.hpp:349
Class for parallel grid function.
Definition pgridfunc.hpp:50
Class for parallel meshes.
Definition pmesh.hpp:34
void SetLevelsOfDetail(int levels_of_detail_)
Set the refinement level.
void SetHighOrderOutput(bool high_order_output_)
Sets whether or not to output the data as high-order elements (false by default).
void SetDataFormat(VTKFormat fmt)
Set the data format for the ParaView output files.
Writer for ParaView visualization (PVD and VTU format)
Data collection with Sidre routines following the Conduit mesh blueprint specification.
Base class for solvers.
Definition operator.hpp:792
bool iterative_mode
If true, use the second argument of Mult() as an initial guess.
Definition operator.hpp:795
Data type sparse matrix.
Definition sparsemat.hpp:51
Base abstract class for first order time dependent operators.
Definition operator.hpp:344
virtual void SetTime(const real_t t_)
Set the current time.
Definition operator.hpp:406
EvalMode GetEvalMode() const
Return the current evaluation mode. See SetEvalMode() for details.
Definition operator.hpp:416
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
Data collection with VisIt I/O routines.
int open(const char hostname[], int port)
Open the socket stream on 'port' at 'hostname'.
real_t sigma(const Vector &x)
Definition maxwell.cpp:91
int problem
Definition ex15.cpp:62
const real_t alpha
Definition ex15.cpp:369
real_t kappa
Definition ex24.cpp:54
int dim
Definition ex24.cpp:53
real_t epsilon
Definition ex25.cpp:141
void velocity_function(const Vector &x, Vector &v)
Definition ex41p.cpp:40
real_t u0_function(const Vector &x)
Definition ex41p.cpp:98
Vector bb_min
Definition ex41p.cpp:36
Vector bb_max
Definition ex41p.cpp:36
int main()
HYPRE_Int HYPRE_BigInt
real_t b
Definition lissajous.cpp:42
real_t a
Definition lissajous.cpp:41
int GetTrueVSize(const FieldDescriptor &f)
Get the true dof size of a field descriptor.
Definition util.hpp:829
real_t u(const Vector &xvec)
Definition lor_mms.hpp:22
void mfem_error(const char *msg)
Definition error.cpp:154
L2_FECollection DG_FECollection
Declare an alternative name for L2_FECollection = DG_FECollection.
Definition fe_coll.hpp:403
float real_t
Definition config.hpp:46
std::function< real_t(const Vector &)> f(real_t mass_coeff)
Definition lor_mms.hpp:30
void Add(const DenseMatrix &A, const DenseMatrix &B, real_t alpha, DenseMatrix &C)
C = A + alpha*B.
const char vishost[]
MFEM_HOST_DEVICE Complex exp(const Complex &q)