MFEM v4.8.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:392
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
Definition array.cpp:68
void SetSize(int nsize)
Change the logical size of the array, keep existing entries.
Definition array.hpp:758
int Size() const
Return the logical size of the array.
Definition array.hpp:147
void PartialSum()
Fill the entries of the array with the cumulative sum of the entries.
Definition array.cpp:103
int Append(const T &el)
Append element 'el' to array, resize if necessary.
Definition array.hpp:830
T & Last()
Return the last element in the array.
Definition array.hpp:863
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:538
void Mult(const Vector &b, Vector &x) const override
Iterative solution of the linear system using the Conjugate Gradient method.
Definition solvers.cpp:751
void SetOperator(const Operator &op) override
Set/update the solver for the given operator.
Definition solvers.hpp:551
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:106
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:848
A general function coefficient.
Arbitrary order H1-conforming (continuous) finite elements.
Definition fe_coll.hpp:275
Arbitrary order "H^{1/2}-conforming" trace finite elements defined on the interface between mesh elem...
Definition fe_coll.hpp:338
The Auxiliary-space Divergence Solver in hypre.
Definition hypre.hpp:1948
The Auxiliary-space Maxwell Solver in hypre.
Definition hypre.hpp:1871
The BoomerAMG solver in hypre.
Definition hypre.hpp:1717
void SetSystemsOptions(int dim, bool order_bynodes=false)
Definition hypre.cpp:5169
void SetPrintLevel(int print_level)
Definition hypre.hpp:1797
Wrapper for hypre's ParCSR matrix class.
Definition hypre.hpp:408
Abstract class for hypre's solvers and preconditioners.
Definition hypre.hpp:1188
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:229
virtual void SetPreconditioner(Solver &pr)
This should be called before SetOperator.
Definition solvers.cpp:174
int GetNumIterations() const
Returns the number of iterations taken during the last call to Mult()
Definition solvers.hpp:280
virtual void SetPrintLevel(int print_lvl)
Legacy method to set the level of verbosity of the solver output.
Definition solvers.cpp:72
void SetMaxIter(int max_it)
Definition solvers.hpp:231
Arbitrary order "L2-conforming" discontinuous finite elements.
Definition fe_coll.hpp:346
Derived matrix coefficient that has the value of the parent matrix coefficient where it is active and...
Mesh data type.
Definition mesh.hpp:64
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
Definition mesh.hpp:290
void GeneralRefinement(const Array< Refinement > &refinements, int nonconforming=-1, int nc_limit=0)
Definition mesh.cpp:10883
Geometry::Type GetTypicalElementGeometry() const
If the local mesh is not empty, return GetElementGeometry(0); otherwise, return a typical Geometry pr...
Definition mesh.cpp:1528
void Clear()
Clear the contents of the Mesh.
Definition mesh.hpp:761
int GetNE() const
Returns number of elements.
Definition mesh.hpp:1282
int Dimension() const
Dimension of the reference space used within the elements.
Definition mesh.hpp:1216
void EnsureNCMesh(bool simplices_nonconforming=false)
Definition mesh.cpp:10951
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
Definition mesh.cpp:11295
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:29
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:350
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
Helper class for ParaView visualization data.
void SetHighOrderOutput(bool high_order_output_)
void SetLevelsOfDetail(int levels_of_detail_)
void SetDataFormat(VTKFormat fmt)
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:403
Arbitrary order "H^{-1/2}-conforming" face finite elements defined on the interface between mesh elem...
Definition fe_coll.hpp:462
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:931
real_t Max() const
Returns the maximal element of the vector.
Definition vector.cpp:1164
int Size() const
Returns the size of the vector.
Definition vector.hpp:226
real_t Sum() const
Return the sum of the vector entries.
Definition vector.cpp:1204
void SetSize(int s)
Resize the vector to size s.
Definition vector.hpp:558
Vector beta
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:43
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)
Helper struct to convert a C++ type to an MPI type.