MFEM v4.8.0
Finite element discretization library
Loading...
Searching...
No Matches
pmaxwell.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 Maxwell parallel example
13//
14// Compile with: make pmaxwell
15//
16// sample run
17// mpirun -np 4 pmaxwell -m ../../data/star.mesh -o 2 -sref 0 -pref 3 -rnum 0.5 -prob 0
18// mpirun -np 4 pmaxwell -m ../../data/inline-quad.mesh -o 3 -sref 0 -pref 3 -rnum 4.8 -sc -prob 0
19// mpirun -np 4 pmaxwell -m ../../data/inline-hex.mesh -o 2 -sref 0 -pref 1 -rnum 0.8 -sc -prob 0
20// mpirun -np 4 pmaxwell -m ../../data/inline-quad.mesh -o 3 -sref 1 -pref 3 -rnum 4.8 -sc -prob 2
21// mpirun -np 4 pmaxwell -o 3 -sref 1 -pref 2 -rnum 11.8 -sc -prob 3
22// mpirun -np 4 pmaxwell -o 3 -sref 1 -pref 2 -rnum 9.8 -sc -prob 4
23
24// AMR run. Note that this is a computationally intensive sample run.
25// We recommend trying it on a large machine with more mpi ranks
26// mpirun -np 4 pmaxwell -o 3 -sref 0 -pref 15 -prob 1 -theta 0.7 -sc
27
28// Description:
29// This example code demonstrates the use of MFEM to define and solve
30// the "ultraweak" (UW) DPG formulation for the Maxwell problem
31
32// ∇×(1/μ ∇×E) - ω² ϵ E = Ĵ , in Ω
33// E×n = E₀ , on ∂Ω
34
35// It solves the following kinds of problems
36// 1) Known exact solutions with error convergence rates
37// a) A manufactured solution problem where E is a plane beam
38// 2) Fichera "microwave" problem
39// 3) PML problems
40// a) Generic PML problem with point source given by the load
41// b) Plane wave scattering from a square
42// c) PML problem with a point source prescribed on the boundary
43
44// The DPG UW deals with the First Order System
45// i ω μ H + ∇ × E = 0, in Ω
46// -i ω ϵ E + ∇ × H = J, in Ω
47// E × n = E_0, on ∂Ω
48// Note: Ĵ = -iωJ
49
50// The ultraweak-DPG formulation is obtained by integration by parts of both
51// equations and the introduction of trace unknowns on the mesh skeleton
52
53// in 2D
54// E is vector valued and H is scalar.
55// (∇ × E, F) = (E, ∇ × F) + < n × E , F>
56// or (∇ ⋅ AE , F) = (AE, ∇ F) + < AE ⋅ n, F>
57// where A = [0 1; -1 0];
58
59// E ∈ (L²(Ω))² , H ∈ L²(Ω)
60// Ê ∈ H^-1/2(Ω)(Γₕ), Ĥ ∈ H^1/2(Γₕ)
61// i ω μ (H,F) + (E, ∇ × F) + < AÊ, F > = 0, ∀ F ∈ H¹
62// -i ω ϵ (E,G) + (H,∇ × G) + < Ĥ, G × n > = (J,G) ∀ G ∈ H(curl,Ω)
63// Ê = E₀ on ∂Ω
64// -------------------------------------------------------------------------
65// | | E | H | Ê | Ĥ | RHS |
66// -------------------------------------------------------------------------
67// | F | (E,∇ × F) | i ω μ (H,F) | < Ê, F > | | |
68// | | | | | | |
69// | G | -i ω ϵ (E,G) | (H,∇ × G) | | < Ĥ, G × n > | (J,G) |
70// where (F,G) ∈ H¹ × H(curl,Ω)
71
72// in 3D
73// E,H ∈ (L^2(Ω))³
74// Ê ∈ H_0^1/2(Ω)(curl, Γₕ), Ĥ ∈ H^-1/2(curl, Γₕ)
75// i ω μ (H,F) + (E,∇ × F) + < Ê, F × n > = 0, ∀ F ∈ H(curl,Ω)
76// -i ω ϵ (E,G) + (H,∇ × G) + < Ĥ, G × n > = (J,G) ∀ G ∈ H(curl,Ω)
77// Ê × n = E₀ on ∂Ω
78// -------------------------------------------------------------------------
79// | | E | H | Ê | Ĥ | RHS |
80// -------------------------------------------------------------------------
81// | F | (E,∇ × F) | i ω μ (H,F) | < n × Ê, F > | | |
82// | | | | | | |
83// | G | -i ω ϵ (E,G) | (H,∇ × G) | | < n × Ĥ, G > | (J,G) |
84// where (F,G) ∈ H(curl,Ω) × H(curl,Ω)
85
86// Here we use the "Adjoint Graph" norm on the test space i.e.,
87// ||(F,G)||²ᵥ = ||A^*(F,G)||² + ||(F,G)||² where A is the
88// maxwell operator defined by (1)
89
90// The PML formulation is
91
92// ∇×(1/μ α ∇×E) - ω² ϵ β E = Ĵ , in Ω
93// E×n = E₀ , on ∂Ω
94
95// where α = |J|⁻¹ Jᵀ J (in 2D it's the scalar |J|⁻¹),
96// β = |J| J⁻¹ J⁻ᵀ, J is the Jacobian of the stretching map
97// and |J| its determinant.
98
99// The first order system reads
100// i ω μ α⁻¹ H + ∇ × E = 0, in Ω
101// -i ω ϵ β E + ∇ × H = J, in Ω
102// E × n = E₀, on ∂Ω
103
104// and the ultraweak formulation is
105
106// in 2D
107// E ∈ (L²(Ω))² , H ∈ L²(Ω)
108// Ê ∈ H^-1/2(Ω)(Γₕ), Ĥ ∈ H^1/2(Γₕ)
109// i ω μ (α⁻¹ H,F) + (E, ∇ × F) + < AÊ, F > = 0, ∀ F ∈ H¹
110// -i ω ϵ (β E,G) + (H,∇ × G) + < Ĥ, G × n > = (J,G) ∀ G ∈ H(curl,Ω)
111// Ê = E₀ on ∂Ω
112// ---------------------------------------------------------------------------------
113// | | E | H | Ê | Ĥ | RHS |
114// ---------------------------------------------------------------------------------
115// | F | (E,∇ × F) | i ω μ (α⁻¹ H,F) | < Ê, F > | | |
116// | | | | | | |
117// | G | -i ω ϵ (β E,G) | (H,∇ × G) | | < Ĥ, G × n > | (J,G) |
118
119// where (F,G) ∈ H¹ × H(curl,Ω)
120
121//
122// in 3D
123// E,H ∈ (L^2(Ω))³
124// Ê ∈ H_0^1/2(Ω)(curl, Γ_h), Ĥ ∈ H^-1/2(curl, Γₕ)
125// i ω μ (α⁻¹ H,F) + (E,∇ × F) + < Ê, F × n > = 0, ∀ F ∈ H(curl,Ω)
126// -i ω ϵ (β E,G) + (H,∇ × G) + < Ĥ, G × n > = (J,G) ∀ G ∈ H(curl,Ω)
127// Ê × n = E_0 on ∂Ω
128// -------------------------------------------------------------------------------
129// | | E | H | Ê | Ĥ | RHS |
130// -------------------------------------------------------------------------------
131// | F | ( E,∇ × F) | i ω μ (α⁻¹ H,F) | < n × Ê, F > | | |
132// | | | | | | |
133// | G | -iωϵ (β E,G) | (H,∇ × G) | | < n × Ĥ, G > | (J,G) |
134// where (F,G) ∈ H(curl,Ω) × H(curl,Ω)
135
136// For more information see https://doi.org/10.1016/j.camwa.2021.01.017
137
138#include "mfem.hpp"
140#include "util/pml.hpp"
142#include <fstream>
143#include <iostream>
144
145using namespace std;
146using namespace mfem;
147using namespace mfem::common;
148
149void E_exact_r(const Vector &x, Vector & E_r);
150void E_exact_i(const Vector &x, Vector & E_i);
151
152void H_exact_r(const Vector &x, Vector & H_r);
153void H_exact_i(const Vector &x, Vector & H_i);
154
155
156void rhs_func_r(const Vector &x, Vector & J_r);
157void rhs_func_i(const Vector &x, Vector & J_i);
158
159void curlE_exact_r(const Vector &x, Vector &curlE_r);
160void curlE_exact_i(const Vector &x, Vector &curlE_i);
161void curlH_exact_r(const Vector &x,Vector &curlH_r);
162void curlH_exact_i(const Vector &x,Vector &curlH_i);
163
164void curlcurlE_exact_r(const Vector &x, Vector & curlcurlE_r);
165void curlcurlE_exact_i(const Vector &x, Vector & curlcurlE_i);
166
167void hatE_exact_r(const Vector & X, Vector & hatE_r);
168void hatE_exact_i(const Vector & X, Vector & hatE_i);
169
170void hatH_exact_r(const Vector & X, Vector & hatH_r);
171void hatH_exact_i(const Vector & X, Vector & hatH_i);
172
175
176void maxwell_solution(const Vector & X,
177 std::vector<complex<real_t>> &E);
178
179void maxwell_solution_curl(const Vector & X,
180 std::vector<complex<real_t>> &curlE);
181
182void maxwell_solution_curlcurl(const Vector & X,
183 std::vector<complex<real_t>> &curlcurlE);
184
185void source_function(const Vector &x, Vector & f);
186
187int dim;
190real_t mu = 1.0;
192
201
202static const char *enum_str[] =
203{
204 "plane_wave",
205 "fichera_oven",
206 "pml_general",
207 "pml_plane_wave_scatter",
208 "pml_pointsource"
209};
210
212
213int main(int argc, char *argv[])
214{
215 Mpi::Init();
216 int myid = Mpi::WorldRank();
217 Hypre::Init();
218
219 const char *mesh_file = "../../data/inline-quad.mesh";
220 int order = 1;
221 int delta_order = 1;
222 real_t rnum=1.0;
223 real_t theta = 0.0;
224 bool static_cond = false;
225 int iprob = 0;
226 int sr = 0;
227 int pr = 1;
228 bool exact_known = false;
229 bool with_pml = false;
230 bool visualization = true;
231 int visport = 19916;
232 bool paraview = false;
233
234 OptionsParser args(argc, argv);
235 args.AddOption(&mesh_file, "-m", "--mesh",
236 "Mesh file to use.");
237 args.AddOption(&order, "-o", "--order",
238 "Finite element order (polynomial degree)");
239 args.AddOption(&rnum, "-rnum", "--number-of-wavelengths",
240 "Number of wavelengths");
241 args.AddOption(&mu, "-mu", "--permeability",
242 "Permeability of free space (or 1/(spring constant)).");
243 args.AddOption(&epsilon, "-eps", "--permittivity",
244 "Permittivity of free space (or mass constant).");
245 args.AddOption(&iprob, "-prob", "--problem", "Problem case"
246 " 0: plane wave, 1: Fichera 'oven', "
247 " 2: Generic PML problem with point source given as a load "
248 " 3: Scattering of a plane wave, "
249 " 4: Point source given on the boundary");
250 args.AddOption(&delta_order, "-do", "--delta-order",
251 "Order enrichment for DPG test space.");
252 args.AddOption(&theta, "-theta", "--theta",
253 "Theta parameter for AMR");
254 args.AddOption(&sr, "-sref", "--serial-ref",
255 "Number of parallel refinements.");
256 args.AddOption(&pr, "-pref", "--parallel-ref",
257 "Number of parallel refinements.");
258 args.AddOption(&static_cond, "-sc", "--static-condensation", "-no-sc",
259 "--no-static-condensation", "Enable static condensation.");
260 args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
261 "--no-visualization",
262 "Enable or disable GLVis visualization.");
263 args.AddOption(&paraview, "-paraview", "--paraview", "-no-paraview",
264 "--no-paraview",
265 "Enable or disable ParaView visualization.");
266 args.AddOption(&visport, "-p", "--send-port", "Socket for GLVis.");
267 args.Parse();
268 if (!args.Good())
269 {
270 if (myid == 0)
271 {
272 args.PrintUsage(cout);
273 }
274 return 1;
275 }
276
277 if (iprob > 4) { iprob = 0; }
278 prob = (prob_type)iprob;
279 omega = 2.*M_PI*rnum;
280
281 if (prob == 0)
282 {
283 exact_known = true;
284 }
285 else if (prob == 1)
286 {
287 mesh_file = "meshes/fichera-waveguide.mesh";
288 omega = 5.0;
289 rnum = omega/(2.*M_PI);
290 }
291 else if (prob == 2)
292 {
293 with_pml = true;
294 }
295 else
296 {
297 with_pml = true;
298 mesh_file = "meshes/scatter.mesh";
299 }
300
301 if (myid == 0)
302 {
303 args.PrintOptions(cout);
304 }
305
306 Mesh mesh(mesh_file, 1, 1);
307 dim = mesh.Dimension();
308 MFEM_VERIFY(dim > 1, "Dimension = 1 is not supported in this example");
309
310 dimc = (dim == 3) ? 3 : 1;
311
312 for (int i = 0; i<sr; i++)
313 {
314 mesh.UniformRefinement();
315 }
316 mesh.EnsureNCMesh(false);
317
318 CartesianPML * pml = nullptr;
319 if (with_pml)
320 {
321 Array2D<real_t> length(dim, 2); length = 0.25;
322 pml = new CartesianPML(&mesh,length);
323 pml->SetOmega(omega);
325 }
326
327 ParMesh pmesh(MPI_COMM_WORLD, mesh);
328 mesh.Clear();
329
330 // PML element attribute marker
331 Array<int> attr;
332 Array<int> attrPML;
333 if (pml) { pml->SetAttributes(&pmesh, &attr, &attrPML); }
334
335 // Define spaces
336 enum TrialSpace
337 {
338 E_space = 0,
339 H_space = 1,
340 hatE_space = 2,
341 hatH_space = 3
342 };
343 enum TestSpace
344 {
345 F_space = 0,
346 G_space = 1
347 };
348 // L2 space for E
349 FiniteElementCollection *E_fec = new L2_FECollection(order-1,dim);
350 ParFiniteElementSpace *E_fes = new ParFiniteElementSpace(&pmesh,E_fec,dim);
351
352 // Vector L2 space for H
353 FiniteElementCollection *H_fec = new L2_FECollection(order-1,dim);
354 ParFiniteElementSpace *H_fes = new ParFiniteElementSpace(&pmesh,H_fec, dimc);
355
356 // H^-1/2 (curl) space for Ê
357 FiniteElementCollection * hatE_fec = nullptr;
358 FiniteElementCollection * hatH_fec = nullptr;
359 FiniteElementCollection * F_fec = nullptr;
360 int test_order = order+delta_order;
361 if (dim == 3)
362 {
363 hatE_fec = new ND_Trace_FECollection(order,dim);
364 hatH_fec = new ND_Trace_FECollection(order,dim);
365 F_fec = new ND_FECollection(test_order, dim);
366 }
367 else
368 {
369 hatE_fec = new RT_Trace_FECollection(order-1,dim);
370 hatH_fec = new H1_Trace_FECollection(order,dim);
371 F_fec = new H1_FECollection(test_order, dim);
372 }
373 ParFiniteElementSpace *hatE_fes = new ParFiniteElementSpace(&pmesh,hatE_fec);
374 ParFiniteElementSpace *hatH_fes = new ParFiniteElementSpace(&pmesh,hatH_fec);
375 FiniteElementCollection * G_fec = new ND_FECollection(test_order, dim);
376
379 trial_fes.Append(E_fes);
380 trial_fes.Append(H_fes);
381 trial_fes.Append(hatE_fes);
382 trial_fes.Append(hatH_fes);
383 test_fec.Append(F_fec);
384 test_fec.Append(G_fec);
385
386 // Bilinear form coefficients
387 ConstantCoefficient one(1.0);
391 ConstantCoefficient negepsomeg(-epsilon*omega);
393 ConstantCoefficient negmuomeg(-mu*omega);
394 // for the 2D case
395 DenseMatrix rot_mat(2);
396 rot_mat(0,0) = 0.; rot_mat(0,1) = 1.;
397 rot_mat(1,0) = -1.; rot_mat(1,1) = 0.;
398 MatrixConstantCoefficient rot(rot_mat);
399 ScalarMatrixProductCoefficient epsrot(epsomeg,rot);
400 ScalarMatrixProductCoefficient negepsrot(negepsomeg,rot);
401
402 Coefficient * epsomeg_cf = nullptr;
403 Coefficient * negepsomeg_cf = nullptr;
404 Coefficient * eps2omeg2_cf = nullptr;
405 Coefficient * muomeg_cf = nullptr;
406 Coefficient * negmuomeg_cf = nullptr;
407 Coefficient * mu2omeg2_cf = nullptr;
408 MatrixCoefficient *epsrot_cf = nullptr;
409 MatrixCoefficient *negepsrot_cf = nullptr;
410
411 if (pml)
412 {
413 epsomeg_cf = new RestrictedCoefficient(epsomeg,attr);
414 negepsomeg_cf = new RestrictedCoefficient(negepsomeg,attr);
415 eps2omeg2_cf = new RestrictedCoefficient(eps2omeg2,attr);
416 muomeg_cf = new RestrictedCoefficient(muomeg,attr);
417 negmuomeg_cf = new RestrictedCoefficient(negmuomeg,attr);
418 mu2omeg2_cf = new RestrictedCoefficient(mu2omeg2,attr);
419 epsrot_cf = new MatrixRestrictedCoefficient(epsrot,attr);
420 negepsrot_cf = new MatrixRestrictedCoefficient(negepsrot,attr);
421 }
422 else
423 {
424 epsomeg_cf = &epsomeg;
425 negepsomeg_cf = &negepsomeg;
426 eps2omeg2_cf = &eps2omeg2;
427 muomeg_cf = &muomeg;
428 negmuomeg_cf = &negmuomeg;
429 mu2omeg2_cf = &mu2omeg2;
430 epsrot_cf = &epsrot;
431 negepsrot_cf = &negepsrot;
432 }
433
434 // PML coefficients;
437 PmlCoefficient abs_detJ_2(abs_detJ_2_function,pml);
441
442 ProductCoefficient negmuomeg_detJ_r(negmuomeg,detJ_r);
443 ProductCoefficient negmuomeg_detJ_i(negmuomeg,detJ_i);
444 ProductCoefficient muomeg_detJ_r(muomeg,detJ_r);
445 ProductCoefficient mu2omeg2_detJ_2(mu2omeg2,abs_detJ_2);
446 ScalarMatrixProductCoefficient epsomeg_detJ_Jt_J_inv_i(epsomeg,
447 detJ_Jt_J_inv_i);
448 ScalarMatrixProductCoefficient epsomeg_detJ_Jt_J_inv_r(epsomeg,
449 detJ_Jt_J_inv_r);
450 ScalarMatrixProductCoefficient negepsomeg_detJ_Jt_J_inv_r(negepsomeg,
451 detJ_Jt_J_inv_r);
452 ScalarMatrixProductCoefficient muomeg_detJ_Jt_J_inv_r(muomeg,detJ_Jt_J_inv_r);
453 ScalarMatrixProductCoefficient negmuomeg_detJ_Jt_J_inv_i(negmuomeg,
454 detJ_Jt_J_inv_i);
455 ScalarMatrixProductCoefficient negmuomeg_detJ_Jt_J_inv_r(negmuomeg,
456 detJ_Jt_J_inv_r);
457 ScalarMatrixProductCoefficient mu2omeg2_detJ_Jt_J_inv_2(mu2omeg2,
458 abs_detJ_Jt_J_inv_2);
459 ScalarMatrixProductCoefficient eps2omeg2_detJ_Jt_J_inv_2(eps2omeg2,
460 abs_detJ_Jt_J_inv_2);
461
462 RestrictedCoefficient negmuomeg_detJ_r_restr(negmuomeg_detJ_r,attrPML);
463 RestrictedCoefficient negmuomeg_detJ_i_restr(negmuomeg_detJ_i,attrPML);
464 RestrictedCoefficient muomeg_detJ_r_restr(muomeg_detJ_r,attrPML);
465 RestrictedCoefficient mu2omeg2_detJ_2_restr(mu2omeg2_detJ_2,attrPML);
466 MatrixRestrictedCoefficient epsomeg_detJ_Jt_J_inv_i_restr(
467 epsomeg_detJ_Jt_J_inv_i,attrPML);
468 MatrixRestrictedCoefficient epsomeg_detJ_Jt_J_inv_r_restr(
469 epsomeg_detJ_Jt_J_inv_r,attrPML);
470 MatrixRestrictedCoefficient negepsomeg_detJ_Jt_J_inv_r_restr(
471 negepsomeg_detJ_Jt_J_inv_r,attrPML);
472 MatrixRestrictedCoefficient muomeg_detJ_Jt_J_inv_r_restr(muomeg_detJ_Jt_J_inv_r,
473 attrPML);
474 MatrixRestrictedCoefficient negmuomeg_detJ_Jt_J_inv_i_restr(
475 negmuomeg_detJ_Jt_J_inv_i,attrPML);
476 MatrixRestrictedCoefficient negmuomeg_detJ_Jt_J_inv_r_restr(
477 negmuomeg_detJ_Jt_J_inv_r,attrPML);
478 MatrixRestrictedCoefficient mu2omeg2_detJ_Jt_J_inv_2_restr(
479 mu2omeg2_detJ_Jt_J_inv_2,attrPML);
480 MatrixRestrictedCoefficient eps2omeg2_detJ_Jt_J_inv_2_restr(
481 eps2omeg2_detJ_Jt_J_inv_2,attrPML);
482
483 MatrixProductCoefficient * epsomeg_detJ_Jt_J_inv_i_rot = nullptr;
484 MatrixProductCoefficient * epsomeg_detJ_Jt_J_inv_r_rot = nullptr;
485 MatrixProductCoefficient * negepsomeg_detJ_Jt_J_inv_r_rot = nullptr;
486 MatrixRestrictedCoefficient * epsomeg_detJ_Jt_J_inv_i_rot_restr = nullptr;
487 MatrixRestrictedCoefficient * epsomeg_detJ_Jt_J_inv_r_rot_restr = nullptr;
488 MatrixRestrictedCoefficient * negepsomeg_detJ_Jt_J_inv_r_rot_restr = nullptr;
489
490 if (pml && dim == 2)
491 {
492 epsomeg_detJ_Jt_J_inv_i_rot = new MatrixProductCoefficient(
493 epsomeg_detJ_Jt_J_inv_i, rot);
494 epsomeg_detJ_Jt_J_inv_r_rot = new MatrixProductCoefficient(
495 epsomeg_detJ_Jt_J_inv_r, rot);
496 negepsomeg_detJ_Jt_J_inv_r_rot = new MatrixProductCoefficient(
497 negepsomeg_detJ_Jt_J_inv_r, rot);
498 epsomeg_detJ_Jt_J_inv_i_rot_restr = new MatrixRestrictedCoefficient(
499 *epsomeg_detJ_Jt_J_inv_i_rot, attrPML);
500 epsomeg_detJ_Jt_J_inv_r_rot_restr = new MatrixRestrictedCoefficient(
501 *epsomeg_detJ_Jt_J_inv_r_rot, attrPML);
502 negepsomeg_detJ_Jt_J_inv_r_rot_restr = new MatrixRestrictedCoefficient(
503 *negepsomeg_detJ_Jt_J_inv_r_rot, attrPML);
504 }
505
506 ParComplexDPGWeakForm * a = new ParComplexDPGWeakForm(trial_fes,test_fec);
507 a->StoreMatrices(); // needed for AMR
508
509 // (E,∇ × F)
510 a->AddTrialIntegrator(new TransposeIntegrator(new MixedCurlIntegrator(one)),
511 nullptr,TrialSpace::E_space, TestSpace::F_space);
512 // -i ω ϵ (E , G) = i (- ω ϵ E, G)
513 a->AddTrialIntegrator(nullptr,
514 new TransposeIntegrator(new VectorFEMassIntegrator(*negepsomeg_cf)),
515 TrialSpace::E_space,TestSpace::G_space);
516 // (H,∇ × G)
517 a->AddTrialIntegrator(new TransposeIntegrator(new MixedCurlIntegrator(one)),
518 nullptr,TrialSpace::H_space, TestSpace::G_space);
519 // < n×Ĥ ,G>
520 a->AddTrialIntegrator(new TangentTraceIntegrator,nullptr,
521 TrialSpace::hatH_space, TestSpace::G_space);
522 // test integrators
523 // (∇×G ,∇× δG)
524 a->AddTestIntegrator(new CurlCurlIntegrator(one),nullptr,
525 TestSpace::G_space,TestSpace::G_space);
526 // (G,δG)
527 a->AddTestIntegrator(new VectorFEMassIntegrator(one),nullptr,
528 TestSpace::G_space,TestSpace::G_space);
529
530 if (dim == 3)
531 {
532 // i ω μ (H, F)
533 a->AddTrialIntegrator(nullptr, new TransposeIntegrator(
534 new VectorFEMassIntegrator(*muomeg_cf)),
535 TrialSpace::H_space,TestSpace::F_space);
536 // < n×Ê,F>
537 a->AddTrialIntegrator(new TangentTraceIntegrator,nullptr,
538 TrialSpace::hatE_space, TestSpace::F_space);
539
540 // test integrators
541 // (∇×F,∇×δF)
542 a->AddTestIntegrator(new CurlCurlIntegrator(one),nullptr,
543 TestSpace::F_space, TestSpace::F_space);
544 // (F,δF)
545 a->AddTestIntegrator(new VectorFEMassIntegrator(one),nullptr,
546 TestSpace::F_space,TestSpace::F_space);
547 // μ^2 ω^2 (F,δF)
548 a->AddTestIntegrator(new VectorFEMassIntegrator(*mu2omeg2_cf),nullptr,
549 TestSpace::F_space, TestSpace::F_space);
550 // -i ω μ (F,∇ × δG) = i (F, -ω μ ∇ × δ G)
551 a->AddTestIntegrator(nullptr,new MixedVectorWeakCurlIntegrator(*negmuomeg_cf),
552 TestSpace::F_space, TestSpace::G_space);
553 // -i ω ϵ (∇ × F, δG)
554 a->AddTestIntegrator(nullptr,new MixedVectorCurlIntegrator(*negepsomeg_cf),
555 TestSpace::F_space, TestSpace::G_space);
556 // i ω μ (∇ × G,δF)
557 a->AddTestIntegrator(nullptr,new MixedVectorCurlIntegrator(*muomeg_cf),
558 TestSpace::G_space, TestSpace::F_space);
559 // i ω ϵ (G, ∇ × δF )
560 a->AddTestIntegrator(nullptr,new MixedVectorWeakCurlIntegrator(*epsomeg_cf),
561 TestSpace::G_space, TestSpace::F_space);
562 // ϵ^2 ω^2 (G,δG)
563 a->AddTestIntegrator(new VectorFEMassIntegrator(*eps2omeg2_cf),nullptr,
564 TestSpace::G_space, TestSpace::G_space);
565 }
566 else
567 {
568 // i ω μ (H, F)
569 a->AddTrialIntegrator(nullptr,new MixedScalarMassIntegrator(*muomeg_cf),
570 TrialSpace::H_space, TestSpace::F_space);
571 // < n×Ê,F>
572 a->AddTrialIntegrator(new TraceIntegrator,nullptr,
573 TrialSpace::hatE_space, TestSpace::F_space);
574 // test integrators
575 // (∇F,∇δF)
576 a->AddTestIntegrator(new DiffusionIntegrator(one),nullptr,
577 TestSpace::F_space, TestSpace::F_space);
578 // (F,δF)
579 a->AddTestIntegrator(new MassIntegrator(one),nullptr,
580 TestSpace::F_space, TestSpace::F_space);
581 // μ^2 ω^2 (F,δF)
582 a->AddTestIntegrator(new MassIntegrator(*mu2omeg2_cf),nullptr,
583 TestSpace::F_space, TestSpace::F_space);
584 // -i ω μ (F,∇ × δG) = i (F, -ω μ ∇ × δ G)
585 a->AddTestIntegrator(nullptr,
586 new TransposeIntegrator(new MixedCurlIntegrator(*negmuomeg_cf)),
587 TestSpace::F_space, TestSpace::G_space);
588 // -i ω ϵ (∇ × F, δG) = i (- ω ϵ A ∇ F,δG), A = [0 1; -1; 0]
589 a->AddTestIntegrator(nullptr,new MixedVectorGradientIntegrator(*negepsrot_cf),
590 TestSpace::F_space, TestSpace::G_space);
591 // i ω μ (∇ × G,δF) = i (ω μ ∇ × G, δF )
592 a->AddTestIntegrator(nullptr,new MixedCurlIntegrator(*muomeg_cf),
593 TestSpace::G_space, TestSpace::F_space);
594 // i ω ϵ (G, ∇ × δF ) = i (ω ϵ G, A ∇ δF) = i ( G , ω ϵ A ∇ δF)
595 a->AddTestIntegrator(nullptr,
597 new MixedVectorGradientIntegrator(*epsrot_cf)),
598 TestSpace::G_space, TestSpace::F_space);
599 // ϵ^2 ω^2 (G, δG)
600 a->AddTestIntegrator(new VectorFEMassIntegrator(*eps2omeg2_cf),nullptr,
601 TestSpace::G_space, TestSpace::G_space);
602 }
603 if (pml)
604 {
605 //trial integrators
606 // -i ω ϵ (β E , G) = -i ω ϵ ((β_re + i β_im) E, G)
607 // = (ω ϵ β_im E, G) + i (- ω ϵ β_re E, G)
608 a->AddTrialIntegrator(
610 epsomeg_detJ_Jt_J_inv_i_restr)),
612 negepsomeg_detJ_Jt_J_inv_r_restr)),
613 TrialSpace::E_space,TestSpace::G_space);
614 if (dim == 3)
615 {
616 //trial integrators
617 // i ω μ (α^-1 H, F) = i ω μ ( (α^-1_re + i α^-1_im) H, F)
618 // = (- ω μ α^-1_im, H,F) + i *(ω μ α^-1_re H, F)
619 a->AddTrialIntegrator(
621 negmuomeg_detJ_Jt_J_inv_i_restr)),
623 muomeg_detJ_Jt_J_inv_r_restr)),
624 TrialSpace::H_space, TestSpace::F_space);
625 // test integrators
626 // μ^2 ω^2 (|α|^-2 F,δF)
627 a->AddTestIntegrator(
628 new VectorFEMassIntegrator(mu2omeg2_detJ_Jt_J_inv_2_restr),nullptr,
629 TestSpace::F_space, TestSpace::F_space);
630 // -i ω μ (α^-* F,∇ × δG) = i (F, - ω μ α^-1 ∇ × δ G)
631 // = i (F, - ω μ (α^-1_re + i α^-1_im) ∇ × δ G)
632 // = (F, - ω μ α^-1_im ∇ × δ G) + i (F, - ω μ α^-1_re ∇×δG)
633 a->AddTestIntegrator(new MixedVectorWeakCurlIntegrator(
634 negmuomeg_detJ_Jt_J_inv_i_restr),
635 new MixedVectorWeakCurlIntegrator(negmuomeg_detJ_Jt_J_inv_r_restr),
636 TestSpace::F_space,TestSpace::G_space);
637 // -i ω ϵ (β ∇ × F, δG) = -i ω ϵ ((β_re + i β_im) ∇ × F, δG)
638 // = (ω ϵ β_im ∇ × F, δG) + i (- ω ϵ β_re ∇ × F, δG)
639 a->AddTestIntegrator(new MixedVectorCurlIntegrator(
640 epsomeg_detJ_Jt_J_inv_i_restr),
641 new MixedVectorCurlIntegrator(negepsomeg_detJ_Jt_J_inv_r_restr),
642 TestSpace::F_space,TestSpace::G_space);
643 // i ω μ (α^-1 ∇ × G,δF) = i ω μ ((α^-1_re + i α^-1_im) ∇ × G,δF)
644 // = (- ω μ α^-1_im ∇ × G,δF) + i (ω μ α^-1_re ∇ × G,δF)
645 a->AddTestIntegrator(new MixedVectorCurlIntegrator(
646 negmuomeg_detJ_Jt_J_inv_i_restr),
647 new MixedVectorCurlIntegrator(muomeg_detJ_Jt_J_inv_r_restr),
648 TestSpace::G_space, TestSpace::F_space);
649 // i ω ϵ (β^* G, ∇×δF) = i ω ϵ ( (β_re - i β_im) G, ∇×δF)
650 // = (ω ϵ β_im G, ∇×δF) + i ( ω ϵ β_re G, ∇×δF)
651 a->AddTestIntegrator(new MixedVectorWeakCurlIntegrator(
652 epsomeg_detJ_Jt_J_inv_i_restr),
653 new MixedVectorWeakCurlIntegrator(epsomeg_detJ_Jt_J_inv_r_restr),
654 TestSpace::G_space, TestSpace::F_space);
655 // ϵ^2 ω^2 (|β|^2 G,δG)
656 a->AddTestIntegrator(new VectorFEMassIntegrator(
657 eps2omeg2_detJ_Jt_J_inv_2_restr),nullptr,
658 TestSpace::G_space, TestSpace::G_space);
659 }
660 else
661 {
662 //trial integrators
663 // i ω μ (α^-1 H, F) = i ω μ ( (α^-1_re + i α^-1_im) H, F)
664 // = (- ω μ α^-1_im, H,F) + i *(ω μ α^-1_re H, F)
665 a->AddTrialIntegrator(
666 new MixedScalarMassIntegrator(negmuomeg_detJ_i_restr),
667 new MixedScalarMassIntegrator(muomeg_detJ_r_restr),
668 TrialSpace::H_space, TestSpace::F_space);
669 // test integrators
670 // μ^2 ω^2 (|α|^-2 F,δF)
671 a->AddTestIntegrator(new MassIntegrator(mu2omeg2_detJ_2_restr),nullptr,
672 TestSpace::F_space, TestSpace::F_space);
673 // -i ω μ (α^-* F,∇ × δG) = (F, ω μ α^-1 ∇ × δ G)
674 // =(F, - ω μ α^-1_im ∇ × δ G) + i (F, - ω μ α^-1_re ∇×δG)
675 a->AddTestIntegrator(
676 new TransposeIntegrator(new MixedCurlIntegrator(negmuomeg_detJ_i_restr)),
677 new TransposeIntegrator(new MixedCurlIntegrator(negmuomeg_detJ_r_restr)),
678 TestSpace::F_space, TestSpace::G_space);
679 // -i ω ϵ (β ∇ × F, δG) = i (- ω ϵ β A ∇ F,δG), A = [0 1; -1; 0]
680 // = (ω ϵ β_im A ∇ F, δG) + i (- ω ϵ β_re A ∇ F, δG)
681 a->AddTestIntegrator(new MixedVectorGradientIntegrator(
682 *epsomeg_detJ_Jt_J_inv_i_rot_restr),
683 new MixedVectorGradientIntegrator(*negepsomeg_detJ_Jt_J_inv_r_rot_restr),
684 TestSpace::F_space, TestSpace::G_space);
685 // i ω μ (α^-1 ∇ × G,δF) = i (ω μ α^-1 ∇ × G, δF )
686 // = (- ω μ α^-1_im ∇ × G,δF) + i (ω μ α^-1_re ∇ × G,δF)
687 a->AddTestIntegrator(new MixedCurlIntegrator(negmuomeg_detJ_i_restr),
688 new MixedCurlIntegrator(muomeg_detJ_r_restr),
689 TestSpace::G_space, TestSpace::F_space);
690 // i ω ϵ (β^* G, ∇ × δF ) = i ( G , ω ϵ β A ∇ δF)
691 // = ( G , ω ϵ β_im A ∇ δF) + i ( G , ω ϵ β_re A ∇ δF)
692 a->AddTestIntegrator(
694 *epsomeg_detJ_Jt_J_inv_i_rot_restr)),
696 *epsomeg_detJ_Jt_J_inv_r_rot_restr)),
697 TestSpace::G_space, TestSpace::F_space);
698 // ϵ^2 ω^2 (|β|^2 G,δG)
699 a->AddTestIntegrator(new VectorFEMassIntegrator(
700 eps2omeg2_detJ_Jt_J_inv_2_restr),nullptr,
701 TestSpace::G_space, TestSpace::G_space);
702 }
703 }
704 // RHS
708 if (prob == 0)
709 {
710 a->AddDomainLFIntegrator(new VectorFEDomainLFIntegrator(f_rhs_r),
711 new VectorFEDomainLFIntegrator(f_rhs_i),
712 TestSpace::G_space);
713 }
714 else if (prob == 2)
715 {
716 a->AddDomainLFIntegrator(new VectorFEDomainLFIntegrator(f_source),nullptr,
717 TestSpace::G_space);
718 }
719
722
723 socketstream E_out_r;
724 socketstream H_out_r;
725 if (myid == 0)
726 {
727 std::cout << "\n Ref |"
728 << " Dofs |"
729 << " ω |" ;
730 if (exact_known)
731 {
732 std::cout << " L2 Error |"
733 << " Rate |" ;
734 }
735 std::cout << " Residual |"
736 << " Rate |"
737 << " PCG it |" << endl;
738 std::cout << std::string((exact_known) ? 82 : 60,'-')
739 << endl;
740 }
741
742 real_t res0 = 0.;
743 real_t err0 = 0.;
744 int dof0 = 0; // init to suppress gcc warning
745
746 Array<int> elements_to_refine;
747
748 ParGridFunction E_r, E_i, H_r, H_i;
749
750 ParaViewDataCollection * paraview_dc = nullptr;
751
752 if (paraview)
753 {
754 paraview_dc = new ParaViewDataCollection(enum_str[prob], &pmesh);
755 paraview_dc->SetPrefixPath("ParaView/Maxwell");
756 paraview_dc->SetLevelsOfDetail(order);
757 paraview_dc->SetCycle(0);
758 paraview_dc->SetDataFormat(VTKFormat::BINARY);
759 paraview_dc->SetHighOrderOutput(true);
760 paraview_dc->SetTime(0.0); // set the time
761 paraview_dc->RegisterField("E_r",&E_r);
762 paraview_dc->RegisterField("E_i",&E_i);
763 paraview_dc->RegisterField("H_r",&H_r);
764 paraview_dc->RegisterField("H_i",&H_i);
765 }
766
767 if (static_cond) { a->EnableStaticCondensation(); }
768 for (int it = 0; it<=pr; it++)
769 {
770 a->Assemble();
771
772 Array<int> ess_tdof_list;
773 Array<int> ess_bdr;
774 if (pmesh.bdr_attributes.Size())
775 {
776 ess_bdr.SetSize(pmesh.bdr_attributes.Max());
777 ess_bdr = 1;
778 hatE_fes->GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
779 if (pml)
780 {
781 ess_bdr = 0;
782 ess_bdr[1] = 1;
783 }
784 }
785
786 // shift the ess_tdofs
787 for (int j = 0; j < ess_tdof_list.Size(); j++)
788 {
789 ess_tdof_list[j] += E_fes->GetTrueVSize() + H_fes->GetTrueVSize();
790 }
791
792 Array<int> offsets(5);
793 offsets[0] = 0;
794 offsets[1] = E_fes->GetVSize();
795 offsets[2] = H_fes->GetVSize();
796 offsets[3] = hatE_fes->GetVSize();
797 offsets[4] = hatH_fes->GetVSize();
798 offsets.PartialSum();
799
800 Vector x(2*offsets.Last());
801 x = 0.;
802
803 if (prob != 2)
804 {
805 ParGridFunction hatE_gf_r(hatE_fes, x, offsets[2]);
806 ParGridFunction hatE_gf_i(hatE_fes, x, offsets.Last() + offsets[2]);
807 if (dim == 3)
808 {
809 hatE_gf_r.ProjectBdrCoefficientTangent(hatEex_r, ess_bdr);
810 hatE_gf_i.ProjectBdrCoefficientTangent(hatEex_i, ess_bdr);
811 }
812 else
813 {
814 hatE_gf_r.ProjectBdrCoefficientNormal(hatEex_r, ess_bdr);
815 hatE_gf_i.ProjectBdrCoefficientNormal(hatEex_i, ess_bdr);
816 }
817 }
818
819 OperatorPtr Ah;
820 Vector X,B;
821 a->FormLinearSystem(ess_tdof_list,x,Ah, X,B);
822
823 ComplexOperator * Ahc = Ah.As<ComplexOperator>();
824
825 BlockOperator * BlockA_r = dynamic_cast<BlockOperator *>(&Ahc->real());
826 BlockOperator * BlockA_i = dynamic_cast<BlockOperator *>(&Ahc->imag());
827
828 int num_blocks = BlockA_r->NumRowBlocks();
829 Array<int> tdof_offsets(2*num_blocks+1);
830
831 tdof_offsets[0] = 0;
832 int skip = (static_cond) ? 0 : 2;
833 int k = (static_cond) ? 2 : 0;
834 for (int i=0; i<num_blocks; i++)
835 {
836 tdof_offsets[i+1] = trial_fes[i+k]->GetTrueVSize();
837 tdof_offsets[num_blocks+i+1] = trial_fes[i+k]->GetTrueVSize();
838 }
839 tdof_offsets.PartialSum();
840
841 BlockOperator blockA(tdof_offsets);
842 for (int i = 0; i<num_blocks; i++)
843 {
844 for (int j = 0; j<num_blocks; j++)
845 {
846 blockA.SetBlock(i,j,&BlockA_r->GetBlock(i,j));
847 blockA.SetBlock(i,j+num_blocks,&BlockA_i->GetBlock(i,j), -1.0);
848 blockA.SetBlock(i+num_blocks,j+num_blocks,&BlockA_r->GetBlock(i,j));
849 blockA.SetBlock(i+num_blocks,j,&BlockA_i->GetBlock(i,j));
850 }
851 }
852
853 X = 0.;
854 BlockDiagonalPreconditioner M(tdof_offsets);
855
856 if (!static_cond)
857 {
858 HypreBoomerAMG * solver_E = new HypreBoomerAMG((HypreParMatrix &)
859 BlockA_r->GetBlock(0,0));
860 solver_E->SetPrintLevel(0);
861 solver_E->SetSystemsOptions(dim);
862 HypreBoomerAMG * solver_H = new HypreBoomerAMG((HypreParMatrix &)
863 BlockA_r->GetBlock(1,1));
864 solver_H->SetPrintLevel(0);
865 solver_H->SetSystemsOptions(dim);
866 M.SetDiagonalBlock(0,solver_E);
867 M.SetDiagonalBlock(1,solver_H);
868 M.SetDiagonalBlock(num_blocks,solver_E);
869 M.SetDiagonalBlock(num_blocks+1,solver_H);
870 }
871
872 HypreSolver * solver_hatH = nullptr;
873 HypreAMS * solver_hatE = new HypreAMS((HypreParMatrix &)BlockA_r->GetBlock(skip,
874 skip),
875 hatE_fes);
876 solver_hatE->SetPrintLevel(0);
877 if (dim == 2)
878 {
879 solver_hatH = new HypreBoomerAMG((HypreParMatrix &)BlockA_r->GetBlock(skip+1,
880 skip+1));
881 dynamic_cast<HypreBoomerAMG*>(solver_hatH)->SetPrintLevel(0);
882 }
883 else
884 {
885 solver_hatH = new HypreAMS((HypreParMatrix &)BlockA_r->GetBlock(skip+1,skip+1),
886 hatH_fes);
887 dynamic_cast<HypreAMS*>(solver_hatH)->SetPrintLevel(0);
888 }
889
890 M.SetDiagonalBlock(skip,solver_hatE);
891 M.SetDiagonalBlock(skip+1,solver_hatH);
892 M.SetDiagonalBlock(skip+num_blocks,solver_hatE);
893 M.SetDiagonalBlock(skip+num_blocks+1,solver_hatH);
894
895 CGSolver cg(MPI_COMM_WORLD);
896 cg.SetRelTol(1e-6);
897 cg.SetMaxIter(10000);
898 cg.SetPrintLevel(0);
899 cg.SetPreconditioner(M);
900 cg.SetOperator(blockA);
901 cg.Mult(B, X);
902
903 for (int i = 0; i<num_blocks; i++)
904 {
905 delete &M.GetDiagonalBlock(i);
906 }
907
908 int num_iter = cg.GetNumIterations();
909
910 a->RecoverFEMSolution(X,x);
911
912 Vector & residuals = a->ComputeResidual(x);
913
914 real_t residual = residuals.Norml2();
915 real_t maxresidual = residuals.Max();
916 real_t globalresidual = residual * residual;
917 MPI_Allreduce(MPI_IN_PLACE, &maxresidual, 1, MPITypeMap<real_t>::mpi_type,
918 MPI_MAX, MPI_COMM_WORLD);
919 MPI_Allreduce(MPI_IN_PLACE, &globalresidual, 1,
920 MPITypeMap<real_t>::mpi_type, MPI_SUM, MPI_COMM_WORLD);
921
922 globalresidual = sqrt(globalresidual);
923
924 E_r.MakeRef(E_fes,x, 0);
925 E_i.MakeRef(E_fes,x, offsets.Last());
926
927 H_r.MakeRef(H_fes,x, offsets[1]);
928 H_i.MakeRef(H_fes,x, offsets.Last()+offsets[1]);
929
930 int dofs = 0;
931 for (int i = 0; i<trial_fes.Size(); i++)
932 {
933 dofs += trial_fes[i]->GlobalTrueVSize();
934 }
935
936 real_t L2Error = 0.0;
937 real_t rate_err = 0.0;
938
939 if (exact_known)
940 {
945 real_t E_err_r = E_r.ComputeL2Error(E_ex_r);
946 real_t E_err_i = E_i.ComputeL2Error(E_ex_i);
947 real_t H_err_r = H_r.ComputeL2Error(H_ex_r);
948 real_t H_err_i = H_i.ComputeL2Error(H_ex_i);
949 L2Error = sqrt( E_err_r*E_err_r + E_err_i*E_err_i
950 + H_err_r*H_err_r + H_err_i*H_err_i );
951 rate_err = (it) ? dim*log(err0/L2Error)/log((real_t)dof0/dofs) : 0.0;
952 err0 = L2Error;
953 }
954
955 real_t rate_res = (it) ? dim*log(res0/globalresidual)/log((
956 real_t)dof0/dofs) : 0.0;
957
958 res0 = globalresidual;
959 dof0 = dofs;
960
961 if (myid == 0)
962 {
963 std::ios oldState(nullptr);
964 oldState.copyfmt(std::cout);
965 std::cout << std::right << std::setw(5) << it << " | "
966 << std::setw(10) << dof0 << " | "
967 << std::setprecision(1) << std::fixed
968 << std::setw(4) << 2.0*rnum << " π | "
969 << std::setprecision(3);
970 if (exact_known)
971 {
972 std::cout << std::setw(10) << std::scientific << err0 << " | "
973 << std::setprecision(2)
974 << std::setw(6) << std::fixed << rate_err << " | " ;
975 }
976 std::cout << std::setprecision(3)
977 << std::setw(10) << std::scientific << res0 << " | "
978 << std::setprecision(2)
979 << std::setw(6) << std::fixed << rate_res << " | "
980 << std::setw(6) << std::fixed << num_iter << " | "
981 << std::endl;
982 std::cout.copyfmt(oldState);
983 }
984
985 if (visualization)
986 {
987 const char * keys = (it == 0 && dim == 2) ? "jRcml\n" : nullptr;
988 char vishost[] = "localhost";
989 VisualizeField(E_out_r,vishost, visport, E_r,
990 "Numerical Electric field (real part)", 0, 0, 500, 500, keys);
991 VisualizeField(H_out_r,vishost, visport, H_r,
992 "Numerical Magnetic field (real part)", 501, 0, 500, 500, keys);
993 }
994
995 if (paraview)
996 {
997 paraview_dc->SetCycle(it);
998 paraview_dc->SetTime((real_t)it);
999 paraview_dc->Save();
1000 }
1001
1002 if (it == pr)
1003 {
1004 break;
1005 }
1006
1007 if (theta > 0.0)
1008 {
1009 elements_to_refine.SetSize(0);
1010 for (int iel = 0; iel<pmesh.GetNE(); iel++)
1011 {
1012 if (residuals[iel] > theta * maxresidual)
1013 {
1014 elements_to_refine.Append(iel);
1015 }
1016 }
1017 pmesh.GeneralRefinement(elements_to_refine,1,1);
1018 }
1019 else
1020 {
1021 pmesh.UniformRefinement();
1022 }
1023 if (pml) { pml->SetAttributes(&pmesh); }
1024 for (int i =0; i<trial_fes.Size(); i++)
1025 {
1026 trial_fes[i]->Update(false);
1027 }
1028 a->Update();
1029 }
1030
1031 if (pml && dim == 2)
1032 {
1033 delete epsomeg_detJ_Jt_J_inv_i_rot;
1034 delete epsomeg_detJ_Jt_J_inv_r_rot;
1035 delete negepsomeg_detJ_Jt_J_inv_r_rot;
1036 delete epsomeg_detJ_Jt_J_inv_i_rot_restr;
1037 delete epsomeg_detJ_Jt_J_inv_r_rot_restr;
1038 delete negepsomeg_detJ_Jt_J_inv_r_rot_restr;
1039 }
1040
1041 if (paraview)
1042 {
1043 delete paraview_dc;
1044 }
1045
1046 delete a;
1047 delete F_fec;
1048 delete G_fec;
1049 delete hatH_fes;
1050 delete hatH_fec;
1051 delete hatE_fes;
1052 delete hatE_fec;
1053 delete H_fec;
1054 delete E_fec;
1055 delete H_fes;
1056 delete E_fes;
1057
1058 return 0;
1059}
1060
1061void E_exact_r(const Vector &x, Vector & E_r)
1062{
1063 std::vector<std::complex<real_t>> E;
1064 maxwell_solution(x,E);
1065 E_r.SetSize(E.size());
1066 for (unsigned i = 0; i < E.size(); i++)
1067 {
1068 E_r[i]= E[i].real();
1069 }
1070}
1071
1072void E_exact_i(const Vector &x, Vector & E_i)
1073{
1074 std::vector<std::complex<real_t>> E;
1075 maxwell_solution(x, E);
1076 E_i.SetSize(E.size());
1077 for (unsigned i = 0; i < E.size(); i++)
1078 {
1079 E_i[i]= E[i].imag();
1080 }
1081}
1082
1083void curlE_exact_r(const Vector &x, Vector &curlE_r)
1084{
1085 std::vector<std::complex<real_t>> curlE;
1086 maxwell_solution_curl(x, curlE);
1087 curlE_r.SetSize(curlE.size());
1088 for (unsigned i = 0; i < curlE.size(); i++)
1089 {
1090 curlE_r[i]= curlE[i].real();
1091 }
1092}
1093
1094void curlE_exact_i(const Vector &x, Vector &curlE_i)
1095{
1096 std::vector<std::complex<real_t>> curlE;
1097 maxwell_solution_curl(x, curlE);
1098 curlE_i.SetSize(curlE.size());
1099 for (unsigned i = 0; i < curlE.size(); i++)
1100 {
1101 curlE_i[i]= curlE[i].imag();
1102 }
1103}
1104
1105void curlcurlE_exact_r(const Vector &x, Vector & curlcurlE_r)
1106{
1107 std::vector<std::complex<real_t>> curlcurlE;
1108 maxwell_solution_curlcurl(x, curlcurlE);
1109 curlcurlE_r.SetSize(curlcurlE.size());
1110 for (unsigned i = 0; i < curlcurlE.size(); i++)
1111 {
1112 curlcurlE_r[i]= curlcurlE[i].real();
1113 }
1114}
1115
1116void curlcurlE_exact_i(const Vector &x, Vector & curlcurlE_i)
1117{
1118 std::vector<std::complex<real_t>> curlcurlE;
1119 maxwell_solution_curlcurl(x, curlcurlE);
1120 curlcurlE_i.SetSize(curlcurlE.size());
1121 for (unsigned i = 0; i < curlcurlE.size(); i++)
1122 {
1123 curlcurlE_i[i]= curlcurlE[i].imag();
1124 }
1125}
1126
1127
1128void H_exact_r(const Vector &x, Vector & H_r)
1129{
1130 // H = i ∇ × E / ω μ
1131 // H_r = - ∇ × E_i / ω μ
1132 Vector curlE_i;
1133 curlE_exact_i(x,curlE_i);
1134 H_r.SetSize(dimc);
1135 for (int i = 0; i<dimc; i++)
1136 {
1137 H_r(i) = - curlE_i(i) / (omega * mu);
1138 }
1139}
1140
1141void H_exact_i(const Vector &x, Vector & H_i)
1142{
1143 // H = i ∇ × E / ω μ
1144 // H_i = ∇ × E_r / ω μ
1145 Vector curlE_r;
1146 curlE_exact_r(x,curlE_r);
1147 H_i.SetSize(dimc);
1148 for (int i = 0; i<dimc; i++)
1149 {
1150 H_i(i) = curlE_r(i) / (omega * mu);
1151 }
1152}
1153
1154void curlH_exact_r(const Vector &x,Vector &curlH_r)
1155{
1156 // ∇ × H_r = - ∇ × ∇ × E_i / ω μ
1157 Vector curlcurlE_i;
1158 curlcurlE_exact_i(x,curlcurlE_i);
1159 curlH_r.SetSize(dim);
1160 for (int i = 0; i<dim; i++)
1161 {
1162 curlH_r(i) = -curlcurlE_i(i) / (omega * mu);
1163 }
1164}
1165
1166void curlH_exact_i(const Vector &x,Vector &curlH_i)
1167{
1168 // ∇ × H_i = ∇ × ∇ × E_r / ω μ
1169 Vector curlcurlE_r;
1170 curlcurlE_exact_r(x,curlcurlE_r);
1171 curlH_i.SetSize(dim);
1172 for (int i = 0; i<dim; i++)
1173 {
1174 curlH_i(i) = curlcurlE_r(i) / (omega * mu);
1175 }
1176}
1177
1178void hatE_exact_r(const Vector & x, Vector & hatE_r)
1179{
1180 if (dim == 3)
1181 {
1182 E_exact_r(x,hatE_r);
1183 }
1184 else
1185 {
1186 Vector E_r;
1187 E_exact_r(x,E_r);
1188 hatE_r.SetSize(hatE_r.Size());
1189 // rotate E_hat
1190 hatE_r[0] = E_r[1];
1191 hatE_r[1] = -E_r[0];
1192 }
1193}
1194
1195void hatE_exact_i(const Vector & x, Vector & hatE_i)
1196{
1197 if (dim == 3)
1198 {
1199 E_exact_i(x,hatE_i);
1200 }
1201 else
1202 {
1203 Vector E_i;
1204 E_exact_i(x,E_i);
1205 hatE_i.SetSize(hatE_i.Size());
1206 // rotate E_hat
1207 hatE_i[0] = E_i[1];
1208 hatE_i[1] = -E_i[0];
1209 }
1210}
1211
1212void hatH_exact_r(const Vector & x, Vector & hatH_r)
1213{
1214 H_exact_r(x,hatH_r);
1215}
1216
1217void hatH_exact_i(const Vector & x, Vector & hatH_i)
1218{
1219 H_exact_i(x,hatH_i);
1220}
1221
1223{
1224 Vector hatH_r;
1225 H_exact_r(x,hatH_r);
1226 return hatH_r[0];
1227}
1228
1230{
1231 Vector hatH_i;
1232 H_exact_i(x,hatH_i);
1233 return hatH_i[0];
1234}
1235
1236// J = -i ω ϵ E + ∇ × H
1237// J_r + iJ_i = -i ω ϵ (E_r + i E_i) + ∇ × (H_r + i H_i)
1238void rhs_func_r(const Vector &x, Vector & J_r)
1239{
1240 // J_r = ω ϵ E_i + ∇ × H_r
1241 Vector E_i, curlH_r;
1242 E_exact_i(x,E_i);
1243 curlH_exact_r(x,curlH_r);
1244 J_r.SetSize(dim);
1245 for (int i = 0; i<dim; i++)
1246 {
1247 J_r(i) = omega * epsilon * E_i(i) + curlH_r(i);
1248 }
1249}
1250
1251void rhs_func_i(const Vector &x, Vector & J_i)
1252{
1253 // J_i = - ω ϵ E_r + ∇ × H_i
1254 Vector E_r, curlH_i;
1255 E_exact_r(x,E_r);
1256 curlH_exact_i(x,curlH_i);
1257 J_i.SetSize(dim);
1258 for (int i = 0; i<dim; i++)
1259 {
1260 J_i(i) = -omega * epsilon * E_r(i) + curlH_i(i);
1261 }
1262}
1263
1264void maxwell_solution(const Vector & X, std::vector<complex<real_t>> &E)
1265{
1266 complex<real_t> zi = complex<real_t>(0., 1.);
1267 E.resize(dim);
1268 for (int i = 0; i < dim; ++i)
1269 {
1270 E[i] = 0.0;
1271 }
1272 switch (prob)
1273 {
1274 case plane_wave:
1275 {
1276 E[0] = exp(zi * omega * (X.Sum()));
1277 }
1278 break;
1280 {
1281 E[1] = exp(zi * omega * (X(0)));
1282 }
1283 break;
1284 case fichera_oven:
1285 {
1286 if (abs(X(2) - 3.0) < 1e-10)
1287 {
1288 E[0] = sin(M_PI*X(1));
1289 }
1290 }
1291 break;
1292 case pml_pointsource:
1293 {
1294 Vector shift(dim);
1295 real_t k = omega * sqrt(epsilon * mu);
1296 shift = -0.5;
1297
1298 if (dim == 2)
1299 {
1300 real_t x0 = X(0) + shift(0);
1301 real_t x1 = X(1) + shift(1);
1302 real_t r = sqrt(x0 * x0 + x1 * x1);
1303 real_t beta = k * r;
1304
1305 // Bessel functions
1306 complex<real_t> Ho, Ho_r, Ho_rr;
1307 Ho = real_t(jn(0, beta)) + zi * real_t(yn(0, beta));
1308 Ho_r = -k * real_t(jn(1, beta)) + zi * real_t(yn(1, beta));
1309 Ho_rr = -k * k * (1_r / beta *
1310 (real_t(jn(1, beta)) + zi * real_t(yn(1, beta))) -
1311 (real_t(jn(2, beta)) + zi * real_t(yn(2, beta))));
1312
1313 // First derivatives
1314 real_t r_x = x0 / r;
1315 real_t r_y = x1 / r;
1316 real_t r_xy = -(r_x / r) * r_y;
1317 real_t r_xx = (1.0 / r) * (1.0 - r_x * r_x);
1318
1319 complex<real_t> val, val_xx, val_xy;
1320 val = 0.25_r * zi * Ho;
1321 val_xx = 0.25_r * zi * (r_xx * Ho_r + r_x * r_x * Ho_rr);
1322 val_xy = 0.25_r * zi * (r_xy * Ho_r + r_x * r_y * Ho_rr);
1323 E[0] = zi / k * (k * k * val + val_xx);
1324 E[1] = zi / k * val_xy;
1325 }
1326 else
1327 {
1328 real_t x0 = X(0) + shift(0);
1329 real_t x1 = X(1) + shift(1);
1330 real_t x2 = X(2) + shift(2);
1331 real_t r = sqrt(x0 * x0 + x1 * x1 + x2 * x2);
1332
1333 real_t r_x = x0 / r;
1334 real_t r_y = x1 / r;
1335 real_t r_z = x2 / r;
1336 real_t r_xx = (1.0 / r) * (1.0 - r_x * r_x);
1337 real_t r_yx = -(r_y / r) * r_x;
1338 real_t r_zx = -(r_z / r) * r_x;
1339
1340 complex<real_t> val, val_r, val_rr;
1341 val = exp(zi * k * r) / r;
1342 val_r = val / r * (zi * k * r - 1_r);
1343 val_rr = val / (r * r) * (-k * k * r * r
1344 - 2_r * zi * k * r + 2_r);
1345
1346 complex<real_t> val_xx, val_yx, val_zx;
1347 val_xx = val_rr * r_x * r_x + val_r * r_xx;
1348 val_yx = val_rr * r_x * r_y + val_r * r_yx;
1349 val_zx = val_rr * r_x * r_z + val_r * r_zx;
1350 complex<real_t> alpha = zi * k / 4_r / real_t(M_PI) / k / k;
1351 E[0] = alpha * (k * k * val + val_xx);
1352 E[1] = alpha * val_yx;
1353 E[2] = alpha * val_zx;
1354 }
1355 }
1356 break;
1357
1358 default:
1359 MFEM_ABORT("Should be unreachable");
1360 break;
1361 }
1362}
1363
1365 std::vector<complex<real_t>> &curlE)
1366{
1367 complex<real_t> zi = complex<real_t>(0., 1.);
1368 curlE.resize(dimc);
1369 for (int i = 0; i < dimc; ++i)
1370 {
1371 curlE[i] = 0.0;
1372 }
1373 switch (prob)
1374 {
1375 case plane_wave:
1376 {
1377 std::complex<real_t> pw = exp(zi * omega * (X.Sum()));
1378 if (dim == 3)
1379 {
1380 curlE[0] = 0.0;
1381 curlE[1] = zi * omega * pw;
1382 curlE[2] = -zi * omega * pw;
1383 }
1384 else
1385 {
1386 curlE[0] = -zi * omega * pw;
1387 }
1388 }
1389 break;
1391 {
1392 std::complex<real_t> pw = exp(zi * omega * (X(0)));
1393 curlE[0] = zi * omega * pw;
1394 }
1395 break;
1396 default:
1397 MFEM_ABORT("Should be unreachable");
1398 break;
1399 }
1400}
1401
1403 std::vector<complex<real_t>> &curlcurlE)
1404{
1405 complex<real_t> zi = complex<real_t>(0., 1.);
1406 curlcurlE.resize(dim);
1407 for (int i = 0; i < dim; ++i)
1408 {
1409 curlcurlE[i] = 0.0;
1410 }
1411 switch (prob)
1412 {
1413 case plane_wave:
1414 {
1415 std::complex<real_t> pw = exp(zi * omega * (X.Sum()));
1416 if (dim == 3)
1417 {
1418 curlcurlE[0] = 2_r * omega * omega * pw;
1419 curlcurlE[1] = - omega * omega * pw;
1420 curlcurlE[2] = - omega * omega * pw;
1421 }
1422 else
1423 {
1424 curlcurlE[0] = omega * omega * pw;
1425 curlcurlE[1] = -omega * omega * pw;
1426 }
1427 }
1428 break;
1430 {
1431 std::complex<real_t> pw = exp(zi * omega * (X(0)));
1432 curlcurlE[1] = omega * omega * pw;
1433 }
1434 break;
1435 default:
1436 MFEM_ABORT("Should be unreachable");
1437 break;
1438 }
1439}
1440
1442{
1443 Vector center(dim);
1444 center = 0.5;
1445 real_t r = 0.0;
1446 for (int i = 0; i < dim; ++i)
1447 {
1448 r += pow(x[i] - center[i], 2.);
1449 }
1450 real_t n = 5.0 * omega * sqrt(epsilon * mu) / M_PI;
1451 real_t coeff = pow(n, 2) / M_PI;
1452 real_t alpha = -pow(n, 2) * r;
1453 f = 0.0;
1454 f[0] = -omega * coeff * exp(alpha)/omega;
1455}
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 SetEpsilonAndMu(real_t epsilon_, real_t mu_)
Definition pml.hpp:65
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.
Integrator for for Nedelec elements.
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.
Data type dense matrix using column-major storage.
Definition densemat.hpp:24
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
void ProjectBdrCoefficientNormal(VectorCoefficient &vcoeff, const Array< int > &bdr_attr)
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 Maxwell Solver in hypre.
Definition hypre.hpp:1871
void SetPrintLevel(int print_lvl)
Definition hypre.cpp:5863
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
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
Base class for Matrix Coefficients that optionally depend on time and space.
A matrix coefficient that is constant in space and time.
Matrix coefficient defined as the product of two matrices.
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
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).
Arbitrary order H(curl)-conforming Nedelec finite elements.
Definition fe_coll.hpp:482
Arbitrary order H(curl)-trace finite elements defined on the interface between mesh elements (faces,...
Definition fe_coll.hpp:528
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 MakeRef(FiniteElementSpace *f, real_t *v) override
Make the ParGridFunction reference external data on a new FiniteElementSpace.
void ProjectBdrCoefficientTangent(VectorCoefficient &vcoeff, const Array< int > &bdr_attr) override
Project the tangential components of the given VectorCoefficient on the boundary. Only boundary attri...
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^{-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.
for VectorFiniteElements (Nedelec, Raviart-Thomas)
Definition lininteg.hpp:344
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
void detJ_Jt_J_inv_r_function(const Vector &x, CartesianPML *pml, DenseMatrix &M)
Definition pml.cpp:242
float real_t
Definition config.hpp:43
real_t abs_detJ_2_function(const Vector &x, CartesianPML *pml)
Definition pml.cpp:180
std::function< real_t(const Vector &)> f(real_t mass_coeff)
Definition lor_mms.hpp:30
real_t detJ_i_function(const Vector &x, CartesianPML *pml)
Definition pml.cpp:170
void abs_detJ_Jt_J_inv_2_function(const Vector &x, CartesianPML *pml, DenseMatrix &M)
Definition pml.cpp:276
void detJ_Jt_J_inv_i_function(const Vector &x, CartesianPML *pml, DenseMatrix &M)
Definition pml.cpp:259
const char vishost[]
void curlE_exact_i(const Vector &x, Vector &curlE_i)
void H_exact_i(const Vector &x, Vector &H_i)
real_t omega
Definition pmaxwell.cpp:189
void curlcurlE_exact_r(const Vector &x, Vector &curlcurlE_r)
int dimc
Definition pmaxwell.cpp:188
void source_function(const Vector &x, Vector &f)
void hatH_exact_r(const Vector &X, Vector &hatH_r)
void hatE_exact_r(const Vector &X, Vector &hatE_r)
void H_exact_r(const Vector &x, Vector &H_r)
real_t hatH_exact_scalar_i(const Vector &X)
void curlH_exact_r(const Vector &x, Vector &curlH_r)
real_t hatH_exact_scalar_r(const Vector &X)
int dim
Definition pmaxwell.cpp:187
real_t mu
Definition pmaxwell.cpp:190
void rhs_func_r(const Vector &x, Vector &J_r)
void hatH_exact_i(const Vector &X, Vector &hatH_i)
void rhs_func_i(const Vector &x, Vector &J_i)
real_t epsilon
Definition pmaxwell.cpp:191
void curlcurlE_exact_i(const Vector &x, Vector &curlcurlE_i)
void E_exact_r(const Vector &x, Vector &E_r)
void maxwell_solution_curlcurl(const Vector &X, std::vector< complex< real_t > > &curlcurlE)
void E_exact_i(const Vector &x, Vector &E_i)
void hatE_exact_i(const Vector &X, Vector &hatE_i)
prob_type prob
Definition pmaxwell.cpp:211
void maxwell_solution_curl(const Vector &X, std::vector< complex< real_t > > &curlE)
prob_type
Definition pmaxwell.cpp:194
@ fichera_oven
Definition pmaxwell.cpp:196
@ plane_wave
Definition pmaxwell.cpp:195
@ pml_plane_wave_scatter
Definition pmaxwell.cpp:198
@ pml_pointsource
Definition pmaxwell.cpp:199
@ pml_general
Definition pmaxwell.cpp:197
void maxwell_solution(const Vector &X, std::vector< complex< real_t > > &E)
void curlE_exact_r(const Vector &x, Vector &curlE_r)
void curlH_exact_i(const Vector &x, Vector &curlH_i)
Helper struct to convert a C++ type to an MPI type.