MFEM v4.10.0
Finite element discretization library
Loading...
Searching...
No Matches
pacoustics.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2026, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11//
12// MFEM Ultraweak DPG acoustics example
13//
14// Compile with: make pacoustics
15//
16// sample runs
17
18// mpirun -np 4 pacoustics -o 3 -m ../../data/star.mesh -sref 1 -pref 2 -rnum 1.9 -sc -prob 0
19// mpirun -np 4 pacoustics -o 3 -m ../../data/star.mesh -sref 1 -pref 2 -rnum 1.9 -sc -prob 0 -pmg
20// mpirun -np 4 pacoustics -o 3 -m ../../data/inline-quad.mesh -sref 1 -pref 2 -rnum 5.2 -sc -prob 1
21// mpirun -np 4 pacoustics -o 4 -m ../../data/inline-tri.mesh -sref 1 -pref 2 -rnum 7.1 -sc -prob 1
22// mpirun -np 4 pacoustics -o 2 -m ../../data/inline-hex.mesh -sref 0 -pref 1 -rnum 1.9 -sc -prob 0
23// mpirun -np 4 pacoustics -o 2 -m ../../data/inline-hex.mesh -sref 0 -pref 1 -rnum 1.9 -sc -prob 0 -pmg
24// mpirun -np 4 pacoustics -o 3 -m ../../data/inline-quad.mesh -sref 2 -pref 1 -rnum 7.1 -sc -prob 2
25// mpirun -np 4 pacoustics -o 3 -m ../../data/inline-quad.mesh -sref 2 -pref 1 -rnum 7.1 -sc -prob 2 -pmg
26// mpirun -np 4 pacoustics -o 2 -m ../../data/inline-hex.mesh -sref 0 -pref 1 -rnum 4.1 -sc -prob 2
27// mpirun -np 4 pacoustics -o 3 -m meshes/scatter.mesh -sref 1 -pref 1 -rnum 7.1 -sc -prob 3
28// mpirun -np 4 pacoustics -o 4 -m meshes/scatter.mesh -sref 1 -pref 1 -rnum 10.1 -sc -prob 4
29// mpirun -np 4 pacoustics -o 4 -m meshes/scatter.mesh -sref 1 -pref 1 -rnum 12.1 -sc -prob 5
30
31// AMR runs
32// mpirun -np 4 pacoustics -o 3 -m meshes/scatter.mesh -sref 0 -pref 7 -theta 0.75 -rnum 10.1 -sc -prob 3
33// mpirun -np 4 pacoustics -o 3 -m meshes/scatter.mesh -sref 0 -pref 12 -theta 0.75 -rnum 20.1 -sc -prob 3
34
35// Description:
36// This example code demonstrates the use of MFEM to define and solve
37// the "ultraweak" (UW) DPG formulation for the Helmholtz problem
38
39// - Δ p - ω² p = f̃ , in Ω
40// p = p₀, on ∂Ω
41
42// It solves the following kinds of problems
43// 1) Known exact solutions with error convergence rates
44// a) f̃ = 0 and p₀ is a plane wave
45// b) A manufactured solution problem where p_exact is a Gaussian beam
46// 2) PML problems
47// a) Gaussian beam scattering from a square
48// b) Plane wave scattering from a square
49// c) Point Source
50
51// The DPG UW deals with the First Order System
52// ∇ p + i ω u = 0, in Ω
53// ∇⋅u + i ω p = f, in Ω (1)
54// p = p₀, in ∂Ω
55// where f:=f̃/(i ω)
56
57// The ultraweak-DPG formulation is obtained by integration by parts of both
58// equations and the introduction of trace unknowns on the mesh skeleton
59
60// p ∈ L²(Ω), u ∈ (L²(Ω))ᵈⁱᵐ
61// p̂ ∈ H^1/2(Ω), û ∈ H^-1/2(Ω)
62// -(p,∇⋅v) + i ω (u,v) + <p̂,v⋅n> = 0, ∀ v ∈ H(div,Ω)
63// -(u,∇ q) + i ω (p,q) + <û,q > = (f,q) ∀ q ∈ H^1(Ω)
64// p̂ = p₀ on ∂Ω
65
66// Note:
67// p̂ := p, û := u on the mesh skeleton
68
69// -------------------------------------------------------------
70// | | p | u | p̂ | û | RHS |
71// -------------------------------------------------------------
72// | v | -(p, ∇⋅v) | i ω (u,v) | < p̂, v⋅n> | | |
73// | | | | | | |
74// | q | i ω (p,q) |-(u , ∇ q) | | < û,q > | (f,q) |
75
76// where (q,v) ∈ H¹(Ω) × H(div,Ω)
77
78// Here we use the "Adjoint Graph" norm on the test space i.e.,
79// ||(q,v)||²ᵥ = ||A^*(q,v)||² + ||(q,v)||² where A is the
80// acoustics operator defined by (1)
81
82// The PML formulation is
83
84// - ∇⋅(|J| J⁻¹ J⁻ᵀ ∇ p) - ω² |J| p = f
85
86// where J is the Jacobian of the stretching map and |J| its determinant.
87
88// The first order system reads
89
90// ∇ p + i ω α u = 0, in Ω
91// ∇⋅u + i ω β p = f, in Ω (2)
92// p = p₀, in ∂Ω
93// where f:=f̃/(i ω), α:= Jᵀ J / |J|, β:= |J|
94
95// and the ultraweak DPG formulation
96//
97// p ∈ L²(Ω), u ∈ (L²(Ω))ᵈⁱᵐ
98// p̂ ∈ H^1/2(Ω), û ∈ H^-1/2(Ω)
99// -(p, ∇⋅v) + i ω (α u , v) + < p̂, v⋅n> = 0, ∀ v ∈ H(div,Ω)
100// -(u , ∇ q) + i ω (β p , q) + < û, q > = (f,q) ∀ q ∈ H¹(Ω)
101// p̂ = p₀ on ∂Ω
102
103// Note:
104// p̂ := p on Γₕ (skeleton)
105// û := u on Γₕ
106
107// ----------------------------------------------------------------
108// | | p | u | p̂ | û | RHS |
109// ----------------------------------------------------------------
110// | v | -(p, ∇⋅v) | i ω (α u,v) | < p̂, v⋅n> | | |
111// | | | | | | |
112// | q | i ω (β p,q) |-(u , ∇ q) | | < û,q > | (f,q) |
113
114// where (q,v) ∈ H¹(Ω) × H(div,Ω)
115
116// Finally the test norm is defined by the adjoint operator of (2) i.e.,
117
118// ||(q,v)||²ᵥ = ||A^*(q,v)||² + ||(q,v)||²
119
120// where A is the operator defined by (2)
121
122// For more information see https://doi.org/10.1016/j.camwa.2017.06.044
123
124#include "mfem.hpp"
126#include "util/pml.hpp"
129#include <fstream>
130#include <iostream>
131
132using namespace std;
133using namespace mfem;
134using namespace mfem::common;
135
136complex<real_t> acoustics_solution(const Vector & X);
137void acoustics_solution_grad(const Vector & X,vector<complex<real_t>> &dp);
138complex<real_t> acoustics_solution_laplacian(const Vector & X);
139
140real_t p_exact_r(const Vector &x);
141real_t p_exact_i(const Vector &x);
142void u_exact_r(const Vector &x, Vector & u);
143void u_exact_i(const Vector &x, Vector & u);
144real_t rhs_func_r(const Vector &x);
145real_t rhs_func_i(const Vector &x);
146void gradp_exact_r(const Vector &x, Vector &gradu);
147void gradp_exact_i(const Vector &x, Vector &gradu);
148real_t divu_exact_r(const Vector &x);
149real_t divu_exact_i(const Vector &x);
150real_t d2_exact_r(const Vector &x);
151real_t d2_exact_i(const Vector &x);
152real_t hatp_exact_r(const Vector & X);
153real_t hatp_exact_i(const Vector & X);
154void hatu_exact_r(const Vector & X, Vector & hatu);
155void hatu_exact_i(const Vector & X, Vector & hatu);
157
158int dim;
160
170
171static const char *enum_str[] =
172{
173 "plane_wave",
174 "gaussian_beam",
175 "pml_general",
176 "pml_beam_scatter",
177 "pml_plane_wave_scatter",
178 "pml_pointsource"
179};
180
182
183int main(int argc, char *argv[])
184{
185 Mpi::Init();
186 int myid = Mpi::WorldRank();
187 Hypre::Init();
188
189 const char *mesh_file = "../../data/inline-quad.mesh";
190 int order = 1;
191 int delta_order = 1;
192 bool visualization = true;
193 real_t rnum=1.0;
194 real_t theta = 0.0;
195 bool static_cond = false;
196 int iprob = 0;
197 int sr = 0;
198 int pr = 0;
199 bool pmg = false;
200 int pmg_levels = -1;
201 real_t relax_factor = 2.0/3;
202 int visport = 19916;
203 bool exact_known = false;
204 bool with_pml = false;
205 bool paraview = false;
206
207 OptionsParser args(argc, argv);
208 args.AddOption(&mesh_file, "-m", "--mesh",
209 "Mesh file to use.");
210 args.AddOption(&order, "-o", "--order",
211 "Finite element order (polynomial degree)");
212 args.AddOption(&rnum, "-rnum", "--number-of-wavelengths",
213 "Number of wavelengths");
214 args.AddOption(&iprob, "-prob", "--problem", "Problem case"
215 " 0: plane wave, 1: Gaussian beam, 2: Generic PML,"
216 " 3: Scattering of a Gaussian beam"
217 " 4: Scattering of a plane wave, 5: Point source");
218 args.AddOption(&delta_order, "-do", "--delta-order",
219 "Order enrichment for DPG test space.");
220 args.AddOption(&theta, "-theta", "--theta",
221 "Theta parameter for AMR");
222 args.AddOption(&sr, "-sref", "--serial-ref",
223 "Number of parallel refinements.");
224 args.AddOption(&pr, "-pref", "--parallel-ref",
225 "Number of parallel refinements.");
226 args.AddOption(&pmg, "-pmg", "--p-refinement-multigrid", "-no-pmg",
227 "--no-p-refinement-multigrid", "Enable P-Refinement Multigrid.");
228 args.AddOption(&pmg_levels, "-pmgl","--p-refinement-multigrid-levels",
229 "Number of levels for P-Refinement Multigrid.");
230 args.AddOption(&relax_factor, "-rf", "--relaxation-factor",
231 "Relaxation factor for the p-multigrid smoother.");
232 args.AddOption(&static_cond, "-sc", "--static-condensation", "-no-sc",
233 "--no-static-condensation", "Enable static condensation.");
234 args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
235 "--no-visualization",
236 "Enable or disable GLVis visualization.");
237 args.AddOption(&paraview, "-paraview", "--paraview", "-no-paraview",
238 "--no-paraview",
239 "Enable or disable ParaView visualization.");
240 args.AddOption(&visport, "-p", "--send-port", "Socket for GLVis.");
241 args.Parse();
242 if (!args.Good())
243 {
244 if (myid == 0)
245 {
246 args.PrintUsage(cout);
247 }
248 return 1;
249 }
250
251 if (iprob > 5) { iprob = 0; }
252 prob = (prob_type)iprob;
253 omega = 2.*M_PI*rnum;
254
255 if (prob > 1)
256 {
257 with_pml = true;
258 if (prob > 2) { mesh_file = "meshes/scatter.mesh"; }
259 }
260 else
261 {
262 exact_known = true;
263 }
264
265 if (myid == 0)
266 {
267 args.PrintOptions(cout);
268 }
269
270 Mesh mesh(mesh_file, 1, 1);
271
272 for (int i = 0; i<sr; i++)
273 {
274 mesh.UniformRefinement();
275 }
276 dim = mesh.Dimension();
277 MFEM_VERIFY(dim > 1, "Dimension = 1 is not supported in this example");
278
279 CartesianPML * pml = nullptr;
280 if (with_pml)
281 {
282 Array2D<real_t> length(dim, 2); length = 0.125;
283 pml = new CartesianPML(&mesh,length);
284 pml->SetOmega(omega);
285 }
286
287 mesh.EnsureNCMesh(true);
288 ParMesh pmesh(MPI_COMM_WORLD, mesh);
289 mesh.Clear();
290
291 Array<int> attr;
292 Array<int> attrPML;
293 // PML element attribute marker
294 if (pml) { pml->SetAttributes(&pmesh, &attr, &attrPML); }
295
296 // Define spaces
297 enum TrialSpace
298 {
299 p_space = 0,
300 u_space = 1,
301 hatp_space = 2,
302 hatu_space = 3
303 };
304 enum TestSpace
305 {
306 q_space = 0,
307 v_space = 1
308 };
309
310 // L2 space for p
311 FiniteElementCollection *p_fec = new L2_FECollection(order-1,dim);
312 ParFiniteElementSpace *p_fes = new ParFiniteElementSpace(&pmesh,p_fec);
313
314 // Vector L2 space for u
315 FiniteElementCollection *u_fec = new L2_FECollection(order-1,dim);
316 ParFiniteElementSpace *u_fes = new ParFiniteElementSpace(&pmesh,u_fec, dim);
317
318 // H^1/2 space for p̂
319 FiniteElementCollection * hatp_fec = new H1_Trace_FECollection(order,dim);
320 ParFiniteElementSpace *hatp_fes = new ParFiniteElementSpace(&pmesh,hatp_fec);
321
322 // H^-1/2 space for û
323 FiniteElementCollection * hatu_fec = new RT_Trace_FECollection(order-1,dim);
324 ParFiniteElementSpace *hatu_fes = new ParFiniteElementSpace(&pmesh,hatu_fec);
325
326 // testspace fe collections
327 int test_order = order+delta_order;
328 FiniteElementCollection * q_fec = new H1_FECollection(test_order, dim);
329 FiniteElementCollection * v_fec = new RT_FECollection(test_order-1, dim);
330
333 trial_fes.Append(p_fes);
334 trial_fes.Append(u_fes);
335 trial_fes.Append(hatp_fes);
336 trial_fes.Append(hatu_fes);
337 test_fec.Append(q_fec);
338 test_fec.Append(v_fec);
339
340 // Bilinear form Coefficients
341 Coefficient * omeg_cf = nullptr;
342 Coefficient * negomeg_cf = nullptr;
343 Coefficient * omeg2_cf = nullptr;
344
345 ConstantCoefficient one(1.0);
346 ConstantCoefficient negone(-1.0);
349 ConstantCoefficient negomeg(-omega);
350
351 if (pml)
352 {
353 omeg_cf = new RestrictedCoefficient(omeg,attr);
354 negomeg_cf = new RestrictedCoefficient(negomeg,attr);
355 omeg2_cf = new RestrictedCoefficient(omeg2,attr);
356 }
357 else
358 {
359 omeg_cf = &omeg;
360 negomeg_cf = &negomeg;
361 omeg2_cf = &omeg2;
362 }
363
364 // PML coefficients
367 PmlCoefficient abs_detJ_2(abs_detJ_2_function,pml);
368 ProductCoefficient omeg_detJ_r(omeg,detJ_r);
369 ProductCoefficient omeg_detJ_i(omeg,detJ_i);
370 ProductCoefficient negomeg_detJ_r(negomeg,detJ_r);
371 ProductCoefficient negomeg_detJ_i(negomeg,detJ_i);
372 ProductCoefficient omeg2_abs_detJ_2(omeg2,abs_detJ_2);
373 RestrictedCoefficient omeg_detJ_r_restr(omeg_detJ_r,attrPML);
374 RestrictedCoefficient omeg_detJ_i_restr(omeg_detJ_i,attrPML);
375 RestrictedCoefficient negomeg_detJ_r_restr(negomeg_detJ_r,attrPML);
376 RestrictedCoefficient negomeg_detJ_i_restr(negomeg_detJ_i,attrPML);
377 RestrictedCoefficient omeg2_abs_detJ_2_restr(omeg2_abs_detJ_2,attrPML);
381 ScalarMatrixProductCoefficient omeg_Jt_J_detJinv_r(omeg,Jt_J_detJinv_r);
382 ScalarMatrixProductCoefficient omeg_Jt_J_detJinv_i(omeg,Jt_J_detJinv_i);
383 ScalarMatrixProductCoefficient negomeg_Jt_J_detJinv_r(negomeg,Jt_J_detJinv_r);
384 ScalarMatrixProductCoefficient negomeg_Jt_J_detJinv_i(negomeg,Jt_J_detJinv_i);
385 ScalarMatrixProductCoefficient omeg2_abs_Jt_J_detJinv_2(omeg2,
386 abs_Jt_J_detJinv_2);
387 MatrixRestrictedCoefficient omeg_Jt_J_detJinv_r_restr(omeg_Jt_J_detJinv_r,
388 attrPML);
389 MatrixRestrictedCoefficient omeg_Jt_J_detJinv_i_restr(omeg_Jt_J_detJinv_i,
390 attrPML);
391 MatrixRestrictedCoefficient negomeg_Jt_J_detJinv_r_restr(negomeg_Jt_J_detJinv_r,
392 attrPML);
393 MatrixRestrictedCoefficient negomeg_Jt_J_detJinv_i_restr(negomeg_Jt_J_detJinv_i,
394 attrPML);
395 MatrixRestrictedCoefficient omeg2_abs_Jt_J_detJinv_2_restr(
396 omeg2_abs_Jt_J_detJinv_2,attrPML);
397
398 ParComplexDPGWeakForm * a = new ParComplexDPGWeakForm(trial_fes,test_fec);
399 a->StoreMatrices(); // needed for AMR
400
401 // Trial integrators
402 // Integrators not in PML
403 // i ω (p,q)
404 a->AddTrialIntegrator(nullptr,new MixedScalarMassIntegrator(*omeg_cf),
405 TrialSpace::p_space,TestSpace::q_space);
406 // -(u , ∇ q)
407 a->AddTrialIntegrator(new TransposeIntegrator(new GradientIntegrator(negone)),
408 nullptr,TrialSpace::u_space,TestSpace::q_space);
409 // -(p, ∇⋅v)
410 a->AddTrialIntegrator(new MixedScalarWeakGradientIntegrator(one),nullptr,
411 TrialSpace::p_space,TestSpace::v_space);
412 // i ω (u,v)
413 a->AddTrialIntegrator(nullptr,
415 TrialSpace::u_space,TestSpace::v_space);
416 // < p̂, v⋅n>
417 a->AddTrialIntegrator(new NormalTraceIntegrator,nullptr,
418 TrialSpace::hatp_space,TestSpace::v_space);
419 // < û,q >
420 a->AddTrialIntegrator(new TraceIntegrator,nullptr,
421 TrialSpace::hatu_space,TestSpace::q_space);
422
423 // test integrators
424 // (∇q,∇δq)
425 a->AddTestIntegrator(new DiffusionIntegrator(one),nullptr,
426 TestSpace::q_space, TestSpace::q_space);
427 // (q,δq)
428 a->AddTestIntegrator(new MassIntegrator(one),nullptr,
429 TestSpace::q_space, TestSpace::q_space);
430 // (∇⋅v,∇⋅δv)
431 a->AddTestIntegrator(new DivDivIntegrator(one),nullptr,
432 TestSpace::v_space, TestSpace::v_space);
433 // (v,δv)
434 a->AddTestIntegrator(new VectorFEMassIntegrator(one),nullptr,
435 TestSpace::v_space, TestSpace::v_space);
436 // -i ω (∇q,δv)
437 a->AddTestIntegrator(nullptr,new MixedVectorGradientIntegrator(*negomeg_cf),
438 TestSpace::q_space, TestSpace::v_space);
439 // i ω (v,∇ δq)
440 a->AddTestIntegrator(nullptr,
442 TestSpace::v_space, TestSpace::q_space);
443 // ω^2 (v,δv)
444 a->AddTestIntegrator(new VectorFEMassIntegrator(*omeg2_cf),nullptr,
445 TestSpace::v_space, TestSpace::v_space);
446 // - i ω (∇⋅v,δq)
447 a->AddTestIntegrator(nullptr,new VectorFEDivergenceIntegrator(*negomeg_cf),
448 TestSpace::v_space, TestSpace::q_space);
449 // i ω (q,∇⋅v)
450 a->AddTestIntegrator(nullptr,new MixedScalarWeakGradientIntegrator(*negomeg_cf),
451 TestSpace::q_space, TestSpace::v_space);
452 // ω^2 (q,δq)
453 a->AddTestIntegrator(new MassIntegrator(*omeg2_cf),nullptr,
454 TestSpace::q_space, TestSpace::q_space);
455
456 // integrators in the PML region
457 // Custom integration rule for the test space in the PML region
459 2*test_order + 1);
460 if (pml)
461 {
462 // Trial integrators
463 // i ω (p,q) = i ω ( (β_r p,q) + i (β_i p,q) )
464 // = (- ω b_i p ) + i (ω β_r p,q)
465 a->AddTrialIntegrator(new MixedScalarMassIntegrator(negomeg_detJ_i_restr),
466 new MixedScalarMassIntegrator(omeg_detJ_r_restr),
467 TrialSpace::p_space,TestSpace::q_space);
468
469 // i ω (α u,v) = i ω ( (α_re u,v) + i (α_im u,v) )
470 // = (-ω a_im u,v) + i (ω a_re u, v)
471 a->AddTrialIntegrator(new TransposeIntegrator(
472 new VectorFEMassIntegrator(negomeg_Jt_J_detJinv_i_restr)),
474 new VectorFEMassIntegrator(omeg_Jt_J_detJinv_r_restr)),
475 TrialSpace::u_space,TestSpace::v_space);
476 // Test integrators
477 // -i ω (α ∇q,δv) = -i ω ( (α_r ∇q,δv) + i (α_i ∇q,δv) )
478 // = (ω α_i ∇q,δv) + i (-ω α_r ∇q,δv)
480 omeg_Jt_J_detJinv_i_restr);
481 integ0_r->SetIntegrationRule(ir);
483 negomeg_Jt_J_detJinv_r_restr);
484 integ0_i->SetIntegrationRule(ir);
485 a->AddTestIntegrator(integ0_r, integ0_i,
486 TestSpace::q_space,TestSpace::v_space);
487
488 // i ω (α^* v,∇ δq) = i ω (ᾱ v,∇ δq) (since α is diagonal)
489 // = i ω ( (α_r v,∇ δq) - i (α_i v,∇ δq)
490 // = (ω α_i v, ∇ δq) + i (ω α_r v,∇ δq )
491 a->AddTestIntegrator(new MixedVectorWeakDivergenceIntegrator(
492 negomeg_Jt_J_detJinv_i_restr),
493 new MixedVectorWeakDivergenceIntegrator(negomeg_Jt_J_detJinv_r_restr),
494 TestSpace::v_space,TestSpace::q_space);
495
496 // ω^2 (|α|^2 v,δv) α α^* = |α|^2 since α is diagonal
498 omeg2_abs_Jt_J_detJinv_2_restr);
499 integ1->SetIntegrationRule(ir);
500 a->AddTestIntegrator(integ1, nullptr,TestSpace::v_space,TestSpace::v_space);
501
502 // - i ω (β ∇⋅v,δq) = - i ω ( (β_re ∇⋅v,δq) + i (β_im ∇⋅v,δq) )
503 // = (ω β_im ∇⋅v,δq) + i (-ω β_re ∇⋅v,δq )
504 a->AddTestIntegrator(new VectorFEDivergenceIntegrator(omeg_detJ_i_restr),
505 new VectorFEDivergenceIntegrator(negomeg_detJ_r_restr),
506 TestSpace::v_space,TestSpace::q_space);
507
508 // i ω (β̄ q,∇⋅v) = i ω ( (β_re ∇⋅v,δq) - i (β_im ∇⋅v,δq) )
509 // = (ω β_im ∇⋅v,δq) + i (ω β_re ∇⋅v,δq )
510 a->AddTestIntegrator(new MixedScalarWeakGradientIntegrator(
511 negomeg_detJ_i_restr),
512 new MixedScalarWeakGradientIntegrator(negomeg_detJ_r_restr),
513 TestSpace::q_space,TestSpace::v_space);
514
515 // ω^2 (β̄ β q,δq) = (ω^2 |β|^2 )
516 MassIntegrator * integ = new MassIntegrator(omeg2_abs_detJ_2_restr);
517 integ->SetIntegrationRule(ir);
518 a->AddTestIntegrator(integ,nullptr,
519 TestSpace::q_space,TestSpace::q_space);
520 }
521
522 // RHS
526 if (prob == prob_type::gaussian_beam)
527 {
528 a->AddDomainLFIntegrator(new DomainLFIntegrator(f_rhs_r),
529 new DomainLFIntegrator(f_rhs_i),
530 TestSpace::q_space);
531 }
532 if (prob == prob_type::pml_general)
533 {
534 a->AddDomainLFIntegrator(new DomainLFIntegrator(f_source),nullptr,
535 TestSpace::q_space);
536 }
537
540
541 Array<int> elements_to_refine;
542
543 socketstream p_out_r;
544 socketstream p_out_i;
545 if (myid == 0)
546 {
547 std::cout << "\n Ref |"
548 << " Dofs |"
549 << " ω |" ;
550 if (exact_known)
551 {
552 std::cout << " L2 Error |"
553 << " Rate |" ;
554 }
555 std::cout << " Residual |"
556 << " Rate |"
557 << " PCG it |" << endl;
558 std::cout << std::string((exact_known) ? 82 : 60,'-')
559 << endl;
560 }
561
562 real_t res0 = 0.;
563 real_t err0 = 0.;
564 int dof0 = 0;
565
566 ParGridFunction p_r, p_i, u_r, u_i;
567
568 ParaViewDataCollection * paraview_dc = nullptr;
569
570 if (paraview)
571 {
572 paraview_dc = new ParaViewDataCollection(enum_str[prob], &pmesh);
573 paraview_dc->SetPrefixPath("ParaView/Acoustics");
574 paraview_dc->SetLevelsOfDetail(order);
575 paraview_dc->SetCycle(0);
576 paraview_dc->SetDataFormat(VTKFormat::BINARY);
577 paraview_dc->SetHighOrderOutput(true);
578 paraview_dc->SetTime(0.0); // set the time
579 paraview_dc->RegisterField("p_r",&p_r);
580 paraview_dc->RegisterField("p_i",&p_i);
581 paraview_dc->RegisterField("u_r",&u_r);
582 paraview_dc->RegisterField("u_i",&u_i);
583 }
584
585 if (static_cond) { a->EnableStaticCondensation(); }
586 for (int it = 0; it<=pr; it++)
587 {
588 a->Assemble();
589
591 Array<int> ess_bdr;
592 if (pmesh.bdr_attributes.Size())
593 {
594 ess_bdr.SetSize(pmesh.bdr_attributes.Max());
595 ess_bdr = 1;
596 hatp_fes->GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
597 if (pml && prob>2)
598 {
599 ess_bdr = 0;
600 ess_bdr[1] = 1;
601 }
602 }
603
604 // shift the ess_tdofs
605 for (int j = 0; j < ess_tdof_list.Size(); j++)
606 {
607 ess_tdof_list[j] += p_fes->GetTrueVSize() + u_fes->GetTrueVSize();
608 }
609
610 Array<int> offsets(5);
611 offsets[0] = 0;
612 offsets[1] = p_fes->GetVSize();
613 offsets[2] = u_fes->GetVSize();
614 offsets[3] = hatp_fes->GetVSize();
615 offsets[4] = hatu_fes->GetVSize();
616 offsets.PartialSum();
617
618 Vector x(2*offsets.Last());
619 x = 0.;
620
621 if (prob!=2)
622 {
623 ParGridFunction hatp_gf_r(hatp_fes, x, offsets[2]);
624 ParGridFunction hatp_gf_i(hatp_fes, x, offsets.Last()+ offsets[2]);
625 hatp_gf_r.ProjectBdrCoefficient(hatpex_r, ess_bdr);
626 hatp_gf_i.ProjectBdrCoefficient(hatpex_i, ess_bdr);
627 }
628
629 OperatorPtr Ah;
630 Vector X,B;
631 a->FormLinearSystem(ess_tdof_list,x,Ah, X,B);
632
633 ComplexOperator * Ahc = Ah.As<ComplexOperator>();
634
635 BlockOperator * BlockA_r = dynamic_cast<BlockOperator *>(&Ahc->real());
636
638 if (static_cond)
639 {
640 a->GetTraceFESpaces(prec_fes);
641 }
642 else
643 {
644 prec_fes = trial_fes;
645 }
646 Solver * cprec = nullptr;
647 if (pmg)
648 {
649#ifdef MFEM_USE_MUMPS
650 bool mumps_coarse_solver = true;
651#else
652 bool mumps_coarse_solver = false;
653#endif
654 std::vector<Array<int>> ess_bdr_marker(prec_fes.Size());
655 for (int b = 0; b<prec_fes.Size(); b++)
656 {
657 if (pmesh.bdr_attributes.Size())
658 {
659 ess_bdr_marker[b].SetSize(pmesh.bdr_attributes.Max());
660 int ess_block = (static_cond) ? 0 : 2;
661 if (b == ess_block) // hatp
662 {
663 ess_bdr_marker[b] = ess_bdr;
664 }
665 else
666 {
667 ess_bdr_marker[b] = 0;
668 }
669 }
670 }
671 cprec = new ComplexPRefinementMultigrid(prec_fes, ess_bdr_marker, *Ahc,
672 pmg_levels, relax_factor, mumps_coarse_solver );
673 }
674 else
675 {
677 BlockA_r->RowOffsets());
678 real_prec->owns_blocks = 1;
679 for (int i = 0; i<BlockA_r->NumRowBlocks(); i++)
680 {
681 auto prec = MakeFESpaceDefaultSolver(prec_fes[i],0);
682 prec->SetOperator(BlockA_r->GetBlock(i,i));
683 real_prec->SetDiagonalBlock(i,prec);
684 }
685 cprec = new ComplexPreconditioner(real_prec, true);
686 }
687
688 CGSolver cg(MPI_COMM_WORLD);
689 cg.SetRelTol(1e-6);
690 cg.SetMaxIter(10000);
691 cg.SetPrintLevel(0);
692 cg.SetOperator(*Ahc);
693 cg.SetPreconditioner(*cprec);
694 cg.Mult(B, X);
695
696 delete cprec;
697
698 int num_iter = cg.GetNumIterations();
699
700 a->RecoverFEMSolution(X,x);
701
702 Vector & residuals = a->ComputeResidual(x);
703
704 real_t residual = residuals.Norml2();
705 real_t maxresidual = residuals.Max();
706 real_t globalresidual = residual * residual;
707 MPI_Allreduce(MPI_IN_PLACE, &maxresidual, 1, MPITypeMap<real_t>::mpi_type,
708 MPI_MAX,MPI_COMM_WORLD);
709 MPI_Allreduce(MPI_IN_PLACE, &globalresidual, 1,
710 MPITypeMap<real_t>::mpi_type, MPI_SUM, MPI_COMM_WORLD);
711
712 globalresidual = sqrt(globalresidual);
713
714 p_r.MakeRef(p_fes, x, 0);
715 p_i.MakeRef(p_fes, x, offsets.Last());
716
717 u_r.MakeRef(u_fes,x, offsets[1]);
718 u_i.MakeRef(u_fes,x, offsets.Last()+offsets[1]);
719
720 int dofs = 0;
721 for (int i = 0; i<trial_fes.Size(); i++)
722 {
723 dofs += trial_fes[i]->GlobalTrueVSize();
724 }
725
726 real_t L2Error = 0.0;
727 real_t rate_err = 0.0;
728 if (exact_known)
729 {
732 real_t p_err_r = p_r.ComputeL2Error(p_ex_r);
733 real_t p_err_i = p_i.ComputeL2Error(p_ex_i);
734
735 // Error in velocity
738
739 real_t u_err_r = u_r.ComputeL2Error(u_ex_r);
740 real_t u_err_i = u_i.ComputeL2Error(u_ex_i);
741
742 L2Error = sqrt(p_err_r*p_err_r + p_err_i*p_err_i
743 +u_err_r*u_err_r + u_err_i*u_err_i);
744
745 rate_err = (it) ? dim*log(err0/L2Error)/log((real_t)dof0/dofs) : 0.0;
746 err0 = L2Error;
747 }
748
749 real_t rate_res = (it) ? dim*log(res0/globalresidual)/log((
750 real_t)dof0/dofs) : 0.0;
751
752 res0 = globalresidual;
753 dof0 = dofs;
754
755 if (myid == 0)
756 {
757 std::ios oldState(nullptr);
758 oldState.copyfmt(std::cout);
759 std::cout << std::right << std::setw(5) << it << " | "
760 << std::setw(10) << dof0 << " | "
761 << std::setprecision(1) << std::fixed
762 << std::setw(4) << 2*rnum << " π | ";
763 if (exact_known)
764 {
765 std::cout << std::setprecision(3) << std::setw(10)
766 << std::scientific << err0 << " | "
767 << std::setprecision(2)
768 << std::setw(6) << std::fixed << rate_err << " | " ;
769 }
770 std::cout << std::setprecision(3)
771 << std::setw(10) << std::scientific << res0 << " | "
772 << std::setprecision(2)
773 << std::setw(6) << std::fixed << rate_res << " | "
774 << std::setw(6) << std::fixed << num_iter << " | "
775 << std::endl;
776 std::cout.copyfmt(oldState);
777 }
778
779 if (visualization)
780 {
781 const char * keys = (it == 0 && dim == 2) ? "jRcml\n" : nullptr;
782 char vishost[] = "localhost";
783 VisualizeField(p_out_r,vishost, visport, p_r,
784 "Numerical pressure (real part)", 0, 0, 500, 500, keys);
785 VisualizeField(p_out_i,vishost, visport, p_i,
786 "Numerical pressure (imaginary part)", 501, 0, 500, 500, keys);
787 }
788
789 if (paraview)
790 {
791 paraview_dc->SetCycle(it);
792 paraview_dc->SetTime((real_t)it);
793 paraview_dc->Save();
794 }
795
796 if (it == pr)
797 {
798 break;
799 }
800
801 if (theta > 0.0)
802 {
803 elements_to_refine.SetSize(0);
804 for (int iel = 0; iel<pmesh.GetNE(); iel++)
805 {
806 if (residuals[iel] > theta * maxresidual)
807 {
808 elements_to_refine.Append(iel);
809 }
810 }
811 pmesh.GeneralRefinement(elements_to_refine,1,1);
812 }
813 else
814 {
815 pmesh.UniformRefinement();
816 }
817 if (pml) { pml->SetAttributes(&pmesh); }
818 for (int i =0; i<trial_fes.Size(); i++)
819 {
820 trial_fes[i]->Update(false);
821 }
822 a->Update();
823 }
824
825 if (paraview)
826 {
827 delete paraview_dc;
828 }
829
830 if (pml)
831 {
832 delete omeg_cf;
833 delete omeg2_cf;
834 delete negomeg_cf;
835 delete pml;
836 }
837 delete a;
838 delete q_fec;
839 delete v_fec;
840 delete hatp_fes;
841 delete hatp_fec;
842 delete hatu_fes;
843 delete hatu_fec;
844 delete u_fec;
845 delete p_fec;
846 delete u_fes;
847 delete p_fes;
848
849 return 0;
850}
851
853{
854 return acoustics_solution(x).real();
855}
856
858{
859 return acoustics_solution(x).imag();
860}
861
863{
864 return p_exact_r(X);
865}
866
868{
869 return p_exact_i(X);
870}
871
872void gradp_exact_r(const Vector &x, Vector &grad_r)
873{
874 grad_r.SetSize(x.Size());
875 vector<complex<real_t>> grad;
877 for (unsigned i = 0; i < grad.size(); i++)
878 {
879 grad_r[i] = grad[i].real();
880 }
881}
882
883void gradp_exact_i(const Vector &x, Vector &grad_i)
884{
885 grad_i.SetSize(x.Size());
886 vector<complex<real_t>> grad;
888 for (unsigned i = 0; i < grad.size(); i++)
889 {
890 grad_i[i] = grad[i].imag();
891 }
892}
893
895{
896 return acoustics_solution_laplacian(x).real();
897}
898
900{
901 return acoustics_solution_laplacian(x).imag();
902}
903
904// u = - ∇ p / (i ω )
905// = i (∇ p_r + i * ∇ p_i) / ω
906// = - ∇ p_i / ω + i ∇ p_r / ω
907void u_exact_r(const Vector &x, Vector & u)
908{
909 gradp_exact_i(x,u);
910 u *= -1./omega;
911}
912
913void u_exact_i(const Vector &x, Vector & u)
914{
915 gradp_exact_r(x,u);
916 u *= 1./omega;
917}
918
919void hatu_exact_r(const Vector & X, Vector & hatu)
920{
921 u_exact_r(X,hatu);
922}
923void hatu_exact_i(const Vector & X, Vector & hatu)
924{
925 u_exact_i(X,hatu);
926}
927
928// ∇⋅u = i Δ p / ω
929// = i (Δ p_r + i * Δ p_i) / ω
930// = - Δ p_i / ω + i Δ p_r / ω
931
933{
934 return -d2_exact_i(x)/omega;
935}
936
938{
939 return d2_exact_r(x)/omega;
940}
941
942// f = ∇⋅u + i ω p
943// f_r = ∇⋅u_r - ω p_i
945{
946 real_t p = p_exact_i(x);
947 real_t divu = divu_exact_r(x);
948 return divu - omega * p;
949}
950
951// f_i = ∇⋅u_i + ω p_r
953{
954 real_t p = p_exact_r(x);
955 real_t divu = divu_exact_i(x);
956 return divu + omega * p;
957}
958
959complex<real_t> acoustics_solution(const Vector & X)
960{
961 complex<real_t> zi = complex<real_t>(0., 1.);
962 switch (prob)
963 {
965 case plane_wave:
966 {
967 real_t beta = omega/std::sqrt((real_t)X.Size());
968 complex<real_t> alpha = beta * zi * X.Sum();
969 return exp(alpha);
970 }
971 break;
972 case gaussian_beam:
973 case pml_beam_scatter:
974 {
975 real_t rk = omega;
976 real_t degrees = 45;
977 real_t alpha = (180+degrees) * M_PI/180.;
978 real_t sina = sin(alpha);
979 real_t cosa = cos(alpha);
980 // shift the origin
981 real_t shift = 0.1;
982 real_t xprim=X(0) + shift;
983 real_t yprim=X(1) + shift;
984
985 real_t x = xprim*sina - yprim*cosa;
986 real_t y = xprim*cosa + yprim*sina;
987 //wavelength
988 real_t rl = 2.*M_PI/rk;
989
990 // beam waist radius
991 real_t w0 = 0.05;
992
993 // function w
994 real_t fact = rl/M_PI/(w0*w0);
995 real_t aux = 1. + (fact*y)*(fact*y);
996
997 real_t w = w0*sqrt(aux);
998
999 real_t phi0 = atan(fact*y);
1000
1001 real_t r = y + 1./y/(fact*fact);
1002
1003 // pressure
1004 complex<real_t> ze = - x*x/(w*w) - zi*rk*y - zi * real_t(M_PI) * x * x/rl/r +
1005 zi*phi0/2_r;
1006 real_t pf = pow(2.0/M_PI/(w*w),0.25);
1007
1008 return pf*exp(ze);
1009 }
1010 break;
1011 case pml_pointsource:
1012 {
1013 real_t x = X(0)-0.5;
1014 real_t y = X(1)-0.5;
1015 real_t r = sqrt(x*x + y*y);
1016 real_t beta = omega * r;
1017 complex<real_t> Ho = real_t(jn(0, beta)) + zi * real_t(yn(0, beta));
1018 return 0.25_r*zi*Ho;
1019 }
1020 break;
1021 default:
1022 MFEM_ABORT("Should be unreachable");
1023 return 1;
1024 break;
1025 }
1026}
1027
1028void acoustics_solution_grad(const Vector & X, vector<complex<real_t>> & dp)
1029{
1030 dp.resize(X.Size());
1031 complex<real_t> zi = complex<real_t>(0., 1.);
1032 // initialize
1033 for (int i = 0; i<X.Size(); i++) { dp[i] = 0.0; }
1034 switch (prob)
1035 {
1037 case plane_wave:
1038 {
1039 real_t beta = omega/std::sqrt((real_t)X.Size());
1040 complex<real_t> alpha = beta * zi * X.Sum();
1041 complex<real_t> p = exp(alpha);
1042 for (int i = 0; i<X.Size(); i++)
1043 {
1044 dp[i] = zi * beta * p;
1045 }
1046 }
1047 break;
1048 case gaussian_beam:
1049 case pml_beam_scatter:
1050 {
1051 real_t rk = omega;
1052 real_t degrees = 45;
1053 real_t alpha = (180+degrees) * M_PI/180.;
1054 real_t sina = sin(alpha);
1055 real_t cosa = cos(alpha);
1056 // shift the origin
1057 real_t shift = 0.1;
1058 real_t xprim=X(0) + shift;
1059 real_t yprim=X(1) + shift;
1060
1061 real_t x = xprim*sina - yprim*cosa;
1062 real_t y = xprim*cosa + yprim*sina;
1063 real_t dxdxprim = sina, dxdyprim = -cosa;
1064 real_t dydxprim = cosa, dydyprim = sina;
1065 //wavelength
1066 real_t rl = 2.*M_PI/rk;
1067
1068 // beam waist radius
1069 real_t w0 = 0.05;
1070
1071 // function w
1072 real_t fact = rl/M_PI/(w0*w0);
1073 real_t aux = 1. + (fact*y)*(fact*y);
1074
1075 real_t w = w0*sqrt(aux);
1076 real_t dwdy = w0*fact*fact*y/sqrt(aux);
1077
1078 real_t phi0 = atan(fact*y);
1079 real_t dphi0dy = cos(phi0)*cos(phi0)*fact;
1080
1081 real_t r = y + 1./y/(fact*fact);
1082 real_t drdy = 1. - 1./(y*y)/(fact*fact);
1083
1084 constexpr real_t r2 = 2.0;
1085 const real_t rPI = M_PI;
1086
1087 // pressure
1088 complex<real_t> ze = - x*x/(w*w) - zi*rk*y - zi * rPI * x * x/rl/r +
1089 zi*phi0/r2;
1090
1091 complex<real_t> zdedx = -r2*x/(w*w) - r2*zi*rPI*x/rl/r;
1092 complex<real_t> zdedy = r2*x*x/(w*w*w)*dwdy - zi*rk + zi*rPI*x*x/rl/
1093 (r*r)*drdy + zi*dphi0dy/r2;
1094
1095 real_t pf = pow(2.0/M_PI/(w*w),0.25);
1096 real_t dpfdy = -pow(2./M_PI/(w*w),-0.75)/M_PI/(w*w*w)*dwdy;
1097
1098 complex<real_t> zp = pf*exp(ze);
1099 complex<real_t> zdpdx = zp*zdedx;
1100 complex<real_t> zdpdy = dpfdy*exp(ze)+zp*zdedy;
1101
1102 dp[0] = (zdpdx*dxdxprim + zdpdy*dydxprim);
1103 dp[1] = (zdpdx*dxdyprim + zdpdy*dydyprim);
1104 }
1105 break;
1106 default:
1107 MFEM_ABORT("Should be unreachable");
1108 break;
1109 }
1110}
1111
1112complex<real_t> acoustics_solution_laplacian(const Vector & X)
1113{
1114 complex<real_t> zi = complex<real_t>(0., 1.);
1115 switch (prob)
1116 {
1118 case plane_wave:
1119 {
1120 real_t beta = omega/std::sqrt((real_t)X.Size());
1121 complex<real_t> alpha = beta * zi * X.Sum();
1122 return dim * beta * beta * exp(alpha);
1123 }
1124 break;
1125 case gaussian_beam:
1126 case pml_beam_scatter:
1127 {
1128 real_t rk = omega;
1129 real_t degrees = 45;
1130 real_t alpha = (180+degrees) * M_PI/180.;
1131 real_t sina = sin(alpha);
1132 real_t cosa = cos(alpha);
1133 // shift the origin
1134 real_t shift = 0.1;
1135 real_t xprim=X(0) + shift;
1136 real_t yprim=X(1) + shift;
1137
1138 real_t x = xprim*sina - yprim*cosa;
1139 real_t y = xprim*cosa + yprim*sina;
1140 real_t dxdxprim = sina, dxdyprim = -cosa;
1141 real_t dydxprim = cosa, dydyprim = sina;
1142 //wavelength
1143 real_t rl = 2.*M_PI/rk;
1144
1145 // beam waist radius
1146 real_t w0 = 0.05;
1147
1148 // function w
1149 real_t fact = rl/M_PI/(w0*w0);
1150 real_t aux = 1. + (fact*y)*(fact*y);
1151
1152 real_t w = w0*sqrt(aux);
1153 real_t dwdy = w0*fact*fact*y/sqrt(aux);
1154 real_t d2wdydy = w0*fact*fact*(1. - (fact*y)*(fact*y)/aux)/sqrt(aux);
1155
1156 real_t phi0 = atan(fact*y);
1157 real_t dphi0dy = cos(phi0)*cos(phi0)*fact;
1158 real_t d2phi0dydy = -2.*cos(phi0)*sin(phi0)*fact*dphi0dy;
1159
1160 real_t r = y + 1./y/(fact*fact);
1161 real_t drdy = 1. - 1./(y*y)/(fact*fact);
1162 real_t d2rdydy = 2./(y*y*y)/(fact*fact);
1163
1164 constexpr real_t r2 = 2.0;
1165 const real_t rPI = M_PI;
1166
1167 // pressure
1168 complex<real_t> ze = - x*x/(w*w) - zi*rk*y - zi * rPI * x * x/rl/r +
1169 zi*phi0/r2;
1170
1171 complex<real_t> zdedx = -r2*x/(w*w) - r2*zi*rPI*x/rl/r;
1172 complex<real_t> zdedy = r2*x*x/(w*w*w)*dwdy - zi*rk + zi*rPI*x*x/rl/
1173 (r*r)*drdy + zi*dphi0dy/r2;
1174 complex<real_t> zd2edxdx = -r2/(w*w) - r2*zi*rPI/rl/r;
1175 complex<real_t> zd2edxdy = 4_r*x/(w*w*w)*dwdy + zi*r2*rPI*x/rl/(r*r)*drdy;
1176 complex<real_t> zd2edydx = zd2edxdy;
1177 complex<real_t> zd2edydy = -6_r*x*x/(w*w*w*w)*dwdy*dwdy
1178 //+ complex<real_t>(2.*x*x/(w*w*w)*d2wdydy)
1179 + real_t(2.*x*x/(w*w*w)*d2wdydy)
1180 - zi * real_t(2.*M_PI*x*x/rl/(r*r*r)*drdy*drdy)
1181 + zi * real_t(M_PI*x*x/rl/(r*r)*d2rdydy) + zi/real_t(2.*d2phi0dydy);
1182
1183 real_t pf = pow(2.0/M_PI/(w*w),0.25);
1184 real_t dpfdy = -pow(2./M_PI/(w*w),-0.75)/M_PI/(w*w*w)*dwdy;
1185 real_t d2pfdydy = -1./M_PI*pow(2./M_PI,-0.75)*(-1.5*pow(w,-2.5)
1186 *dwdy*dwdy + pow(w,-1.5)*d2wdydy);
1187
1188
1189 complex<real_t> zp = pf*exp(ze);
1190 complex<real_t> zdpdx = zp*zdedx;
1191 complex<real_t> zdpdy = dpfdy*exp(ze)+zp*zdedy;
1192 complex<real_t> zd2pdxdx = zdpdx*zdedx + zp*zd2edxdx;
1193 complex<real_t> zd2pdxdy = zdpdy*zdedx + zp*zd2edxdy;
1194 complex<real_t> zd2pdydx = dpfdy*exp(ze)*zdedx + zdpdx*zdedy + zp*zd2edydx;
1195 complex<real_t> zd2pdydy = d2pfdydy*exp(ze) + dpfdy*exp(
1196 ze)*zdedy + zdpdy*zdedy + zp*zd2edydy;
1197
1198
1199 return (zd2pdxdx*dxdxprim + zd2pdydx*dydxprim)*dxdxprim
1200 + (zd2pdxdy*dxdxprim + zd2pdydy*dydxprim)*dydxprim
1201 + (zd2pdxdx*dxdyprim + zd2pdydx*dydyprim)*dxdyprim
1202 + (zd2pdxdy*dxdyprim + zd2pdydy*dydyprim)*dydyprim;
1203 }
1204 break;
1205 default:
1206 MFEM_ABORT("Should be unreachable");
1207 return 1;
1208 break;
1209 }
1210}
1211
1213{
1214 Vector center(dim);
1215 center = 0.5;
1216 real_t r = 0.0;
1217 for (int i = 0; i < dim; ++i)
1218 {
1219 r += pow(x[i] - center[i], 2.);
1220 }
1221 real_t n = 5.0 * omega / M_PI;
1222 real_t coeff = pow(n, 2) / M_PI;
1223 real_t alpha = -pow(n, 2) * r;
1224 return -omega * coeff * exp(alpha)/omega;
1225}
Dynamic 2D array using row-major layout.
Definition array.hpp:459
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
int Append(const T &el)
Append element 'el' to array, resize if necessary.
Definition array.hpp:941
T & Last()
Return the last element in the array.
Definition array.hpp:974
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).
A class to handle Block systems in a matrix-free implementation.
Conjugate gradient method.
Definition solvers.hpp:627
Class for setting up a simple Cartesian PML region.
Definition pml.hpp:19
void SetAttributes(Mesh *mesh_, Array< int > *attrNonPML=nullptr, Array< int > *attrPML=nullptr)
Mark element in the PML region.
Definition pml.cpp:73
void SetOmega(real_t omega_)
Definition pml.hpp:64
Base class Coefficients that optionally depend on space and time. These are used by the BilinearFormI...
Mimic the action of a complex operator using two real operators.
virtual Operator & real()
Real or imaginary part accessor methods.
Creates a p-refinement multigrid preconditioner for a given set of parallel finite element spaces and...
A coefficient that is constant across space and time.
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.
for Raviart-Thomas elements
Class for domain integration .
Definition lininteg.hpp:108
Collection of finite elements from the same family in multiple dimensions. This class is used to matc...
Definition fe_coll.hpp:27
int GetVSize() const
Return the number of vector dofs, i.e. GetNDofs() x GetVDim().
Definition fespace.hpp:824
A general function coefficient.
Arbitrary order H1-conforming (continuous) finite elements.
Definition fe_coll.hpp:291
Arbitrary order "H^{1/2}-conforming" trace finite elements defined on the interface between mesh elem...
Definition fe_coll.hpp:357
static void Init()
Initialize hypre by calling HYPRE_Init() and set default options. After calling Hypre::Init(),...
Definition hypre.cpp:33
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.
void SetIntegrationRule(const IntegrationRule &ir)
Prescribe a fixed IntegrationRule to use. Sets the NURBS patch integration rule to null.
Arbitrary order "L2-conforming" discontinuous finite elements.
Definition fe_coll.hpp:369
Derived matrix coefficient that has the value of the parent matrix coefficient where it is active and...
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
void GeneralRefinement(const Array< Refinement > &refinements, int nonconforming=-1, int nc_limit=0)
Definition mesh.cpp:11713
Geometry::Type GetTypicalElementGeometry() const
If the local mesh is not empty, return GetElementGeometry(0); otherwise, return a typical Geometry pr...
Definition mesh.cpp:1705
void Clear()
Clear the contents of the Mesh.
Definition mesh.hpp:835
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
void EnsureNCMesh(bool simplices_nonconforming=false)
Definition mesh.cpp:11781
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 void Init(int &argc, char **&argv, int required=default_thread_required, int *provided=nullptr)
Singleton creation with Mpi::Init(argc, argv).
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 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 representing the parallel weak formulation. (Convenient for DPG Equations)
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
int GetTrueVSize() const override
Return the number of local vector true dofs.
Definition pfespace.hpp:365
Class for parallel grid function.
Definition pgridfunc.hpp:50
real_t ComputeL2Error(Coefficient *exsol[], const IntegrationRule *irs[]=NULL, const Array< int > *elems=NULL) const override
Returns ||u_ex - u_h||_L2 in parallel for H1 or L2 elements.
void ProjectBdrCoefficient(Coefficient *coeff[], VectorCoefficient *vcoeff, const Array< int > &attr)
void MakeRef(FiniteElementSpace *f, real_t *v) override
Make the ParGridFunction reference external data on a new FiniteElementSpace.
Class for parallel meshes.
Definition pmesh.hpp:35
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)
Scalar coefficient defined as the product of two scalar coefficients or a scalar and a scalar coeffic...
Arbitrary order H(div)-conforming Raviart-Thomas finite elements.
Definition fe_coll.hpp:430
Arbitrary order "H^{-1/2}-conforming" face finite elements defined on the interface between mesh elem...
Definition fe_coll.hpp:492
Derived coefficient that takes the value of the parent coefficient for the active attributes and is z...
Matrix coefficient defined as a product of a scalar coefficient and a matrix coefficient.
Base class for solvers.
Definition operator.hpp:855
A general vector function coefficient.
Vector data type.
Definition vector.hpp:82
real_t Norml2() const
Returns the l2 norm of the vector.
Definition vector.cpp:968
real_t Max() const
Returns the maximal element of the vector.
Definition vector.cpp:1200
int Size() const
Returns the size of the vector.
Definition vector.hpp:234
real_t Sum() const
Return the sum of the vector entries.
Definition vector.cpp:1246
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
bool exact_known
Definition ex25.cpp:144
prob_type
Definition ex25.cpp:149
int main()
real_t b
Definition lissajous.cpp:42
real_t a
Definition lissajous.cpp:41
void VisualizeField(socketstream &sock, const char *vishost, int visport, GridFunction &gf, const char *title, int x, int y, int w, int h, const char *keys, bool vec)
real_t detJ_r_function(const Vector &x, CartesianPML *pml)
PML stretching functions: See https://doi.org/10.1006/jcph.1994.1159.
Definition pml.cpp:163
real_t u(const Vector &xvec)
Definition lor_mms.hpp:22
Solver * MakeFESpaceDefaultSolver(const ParFiniteElementSpace *pfespace, int print_level)
Creates a default solver for a given parallel FE space. The default solvers are the following:
void Jt_J_detJinv_r_function(const Vector &x, CartesianPML *pml, DenseMatrix &M)
Definition pml.cpp:194
void abs_Jt_J_detJinv_2_function(const Vector &x, CartesianPML *pml, DenseMatrix &M)
Definition pml.cpp:226
void Jt_J_detJinv_i_function(const Vector &x, CartesianPML *pml, DenseMatrix &M)
Definition pml.cpp:210
float real_t
Definition config.hpp:46
real_t abs_detJ_2_function(const Vector &x, CartesianPML *pml)
Definition pml.cpp:183
real_t detJ_i_function(const Vector &x, CartesianPML *pml)
Definition pml.cpp:173
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.
real_t p(const Vector &x, real_t t)
real_t hatp_exact_r(const Vector &X)
void hatu_exact_i(const Vector &X, Vector &hatu)
real_t omega
real_t p_exact_r(const Vector &x)
complex< real_t > acoustics_solution(const Vector &X)
void gradp_exact_i(const Vector &x, Vector &gradu)
void gradp_exact_r(const Vector &x, Vector &gradu)
real_t rhs_func_r(const Vector &x)
complex< real_t > acoustics_solution_laplacian(const Vector &X)
real_t divu_exact_i(const Vector &x)
int dim
void u_exact_r(const Vector &x, Vector &u)
real_t divu_exact_r(const Vector &x)
real_t d2_exact_r(const Vector &x)
real_t source_function(const Vector &x)
real_t hatp_exact_i(const Vector &X)
real_t d2_exact_i(const Vector &x)
real_t rhs_func_i(const Vector &x)
void acoustics_solution_grad(const Vector &X, vector< complex< real_t > > &dp)
prob_type prob
prob_type
@ pml_beam_scatter
@ gaussian_beam
@ plane_wave
@ pml_plane_wave_scatter
@ pml_pointsource
@ pml_general
real_t p_exact_i(const Vector &x)
void hatu_exact_r(const Vector &X, Vector &hatu)
void u_exact_i(const Vector &x, Vector &u)
MFEM_HOST_DEVICE Complex exp(const Complex &q)
Helper struct to convert a C++ type to an MPI type.