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