MFEM v4.8.0
Finite element discretization library
Loading...
Searching...
No Matches
maxwell.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 example for Maxwell
13//
14// Compile with: make maxwell
15//
16// Sample runs
17// maxwell -m ../../data/inline-tri.mesh -ref 4 -o 1 -rnum 1.0
18// maxwell -m ../../data/amr-quad.mesh -ref 3 -o 2 -rnum 1.6 -sc
19// maxwell -m ../../data/inline-quad.mesh -ref 2 -o 3 -rnum 4.2 -sc
20// maxwell -m ../../data/inline-hex.mesh -ref 1 -o 2 -sc -rnum 1.0
21
22// Description:
23// This example code demonstrates the use of MFEM to define and solve
24// the "ultraweak" (UW) DPG formulation for the (indefinite) Maxwell problem
25
26// ∇×(1/μ ∇×E) - ω² ϵ E = Ĵ , in Ω
27// E×n = E₀, on ∂Ω
28
29// It solves a problem with a manufactured solution E_exact being a plane wave
30// in the x-component and zero in y (and z) component.
31// This example computes and prints out convergence rates for the L² error.
32
33// The DPG UW deals with the First Order System
34// i ω μ H + ∇ × E = 0, in Ω
35// -i ω ϵ E + ∇ × H = J, in Ω (1)
36// E × n = E₀, on ∂Ω
37
38// Note: Ĵ = -iωJ
39// in 2D
40// E is vector valued and H is scalar.
41// (∇ × E, F) = (E, ∇ × F) + < n × E , F>
42// or (∇ ⋅ AE , F) = (AE, ∇ F) + < AE ⋅ n, F>
43// where A = [0 1; -1 0];
44
45// E ∈ (L²(Ω))² , H ∈ L²(Ω)
46// Ê ∈ H^-1/2(Ω)(Γₕ), Ĥ ∈ H^1/2(Γₕ)
47// i ω μ (H,F) + (E, ∇ × F) + < AÊ, F > = 0, ∀ F ∈ H¹
48// -i ω ϵ (E,G) + (H,∇ × G) + < Ĥ, G × n > = (J,G) ∀ G ∈ H(curl,Ω)
49// Ê = E₀ on ∂Ω
50// -------------------------------------------------------------------------
51// | | E | H | Ê | Ĥ | RHS |
52// -------------------------------------------------------------------------
53// | F | (E,∇ × F) | i ω μ (H,F) | < Ê, F > | | |
54// | | | | | | |
55// | G | -i ω ϵ (E,G) | (H,∇ × G) | | < Ĥ, G × n > | (J,G) |
56// where (F,G) ∈ H¹ × H(curl,Ω)
57
58// in 3D
59// E,H ∈ ((L²(Ω)))³
60// Ê ∈ H_0^1/2(Ω)(curl, Γₕ), Ĥ ∈ H^-1/2(curl, Γₕ)
61// i ω μ (H,F) + (E,∇ × F) + < Ê, F × n > = 0, ∀ F ∈ H(curl,Ω)
62// -i ω ϵ (E,G) + (H,∇ × G) + < Ĥ, G × n > = (J,G) ∀ G ∈ H(curl,Ω)
63// Ê × n = E_0 on ∂Ω
64// -------------------------------------------------------------------------
65// | | E | H | Ê | Ĥ | RHS |
66// -------------------------------------------------------------------------
67// | F | (E,∇ × F) | i ω μ (H,F) | < n × Ê, F > | | |
68// | | | | | | |
69// | G | -i ω ϵ (E,G) | (H,∇ × G) | | < n × Ĥ, G > | (J,G) |
70// where (F,G) ∈ H(curl,Ω) × H(curl,Ω)
71
72// Here we use the "Adjoint Graph" norm on the test space i.e.,
73// ||(F,G)||²ᵥ = ||A^*(F,G)||² + ||(F,G)||² where A is the
74// Maxwell operator defined by (1)
75
76// For more information see https://doi.org/10.1016/j.camwa.2021.01.017
77
78#include "mfem.hpp"
81#include <fstream>
82#include <iostream>
83
84using namespace std;
85using namespace mfem;
86using namespace mfem::common;
87
88void maxwell_solution(const Vector & X, std::vector<complex<real_t>> &E);
89
90void maxwell_solution_curl(const Vector & X,
91 std::vector<complex<real_t>> &curlE);
92
94 std::vector<complex<real_t>> &curlcurlE);
95
96void E_exact_r(const Vector &x, Vector & E_r);
97void E_exact_i(const Vector &x, Vector & E_i);
98
99void H_exact_r(const Vector &x, Vector & H_r);
100void H_exact_i(const Vector &x, Vector & H_i);
101
102void curlE_exact_r(const Vector &x, Vector &curlE_r);
103void curlE_exact_i(const Vector &x, Vector &curlE_i);
104void curlH_exact_r(const Vector &x,Vector &curlH_r);
105void curlH_exact_i(const Vector &x,Vector &curlH_i);
106
107void curlcurlE_exact_r(const Vector &x, Vector & curlcurlE_r);
108void curlcurlE_exact_i(const Vector &x, Vector & curlcurlE_i);
109
110void hatE_exact_r(const Vector & X, Vector & hatE_r);
111void hatE_exact_i(const Vector & X, Vector & hatE_i);
112
113void hatH_exact_r(const Vector & X, Vector & hatH_r);
114void hatH_exact_i(const Vector & X, Vector & hatH_i);
115
118
119void rhs_func_r(const Vector &x, Vector & J_r);
120void rhs_func_i(const Vector &x, Vector & J_i);
121
122int dim;
125real_t mu = 1.0;
127
128int main(int argc, char *argv[])
129{
130 const char *mesh_file = "../../data/inline-quad.mesh";
131 int order = 1;
132 int delta_order = 1;
133 bool visualization = true;
134 real_t rnum=1.0;
135 int ref = 0;
136 int visport = 19916;
137 bool static_cond = false;
138
139 OptionsParser args(argc, argv);
140 args.AddOption(&mesh_file, "-m", "--mesh",
141 "Mesh file to use.");
142 args.AddOption(&order, "-o", "--order",
143 "Finite element order (polynomial degree)");
144 args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
145 "--no-visualization",
146 "Enable or disable GLVis visualization.");
147 args.AddOption(&rnum, "-rnum", "--number-of-wavelengths",
148 "Number of wavelengths");
149 args.AddOption(&mu, "-mu", "--permeability",
150 "Permeability of free space (or 1/(spring constant)).");
151 args.AddOption(&epsilon, "-eps", "--permittivity",
152 "Permittivity of free space (or mass constant).");
153 args.AddOption(&delta_order, "-do", "--delta-order",
154 "Order enrichment for DPG test space.");
155 args.AddOption(&ref, "-ref", "--serial-ref",
156 "Number of serial refinements.");
157 args.AddOption(&static_cond, "-sc", "--static-condensation", "-no-sc",
158 "--no-static-condensation", "Enable static condensation.");
159 args.AddOption(&visport, "-p", "--send-port", "Socket for GLVis.");
160 args.Parse();
161 if (!args.Good())
162 {
163 args.PrintUsage(cout);
164 return 1;
165 }
166 args.PrintOptions(cout);
167
168 omega = 2.*M_PI*rnum;
169
170 Mesh mesh(mesh_file, 1, 1);
171 dim = mesh.Dimension();
172 MFEM_VERIFY(dim > 1, "Dimension = 1 is not supported in this example");
173
174 dimc = (dim == 3) ? 3 : 1;
175 int test_order = order+delta_order;
176
177 // Define spaces
178 enum TrialSpace
179 {
180 E_space = 0,
181 H_space = 1,
182 hatE_space = 2,
183 hatH_space = 3
184 };
185 enum TestSpace
186 {
187 F_space = 0,
188 G_space = 1
189 };
190 // L2 space for E
191 FiniteElementCollection *E_fec = new L2_FECollection(order-1,dim);
192 FiniteElementSpace *E_fes = new FiniteElementSpace(&mesh,E_fec,dim);
193
194 // Vector L2 space for H
195 FiniteElementCollection *H_fec = new L2_FECollection(order-1,dim);
196 FiniteElementSpace *H_fes = new FiniteElementSpace(&mesh,H_fec, dimc);
197
198 // H^-1/2 (curl) space for Ê
199 FiniteElementCollection * hatE_fec = nullptr;
200 FiniteElementCollection * hatH_fec = nullptr;
201 FiniteElementCollection * F_fec = nullptr;
202 if (dim == 3)
203 {
204 hatE_fec = new ND_Trace_FECollection(order,dim);
205 hatH_fec = new ND_Trace_FECollection(order,dim);
206 F_fec = new ND_FECollection(test_order, dim);
207 }
208 else
209 {
210 hatE_fec = new RT_Trace_FECollection(order-1,dim);
211 hatH_fec = new H1_Trace_FECollection(order,dim);
212 F_fec = new H1_FECollection(test_order, dim);
213 }
214 FiniteElementSpace *hatE_fes = new FiniteElementSpace(&mesh,hatE_fec);
215 FiniteElementSpace *hatH_fes = new FiniteElementSpace(&mesh,hatH_fec);
216 FiniteElementCollection * G_fec = new ND_FECollection(test_order, dim);
217
218 // Coefficients
219 ConstantCoefficient one(1.0);
223 ConstantCoefficient negepsomeg(-epsilon*omega);
225 ConstantCoefficient negmuomeg(-mu*omega);
226
227 DenseMatrix rot_mat(2);
228 rot_mat(0,0) = 0.; rot_mat(0,1) = 1.;
229 rot_mat(1,0) = -1.; rot_mat(1,1) = 0.;
230 MatrixConstantCoefficient rot(rot_mat);
231 ScalarMatrixProductCoefficient epsrot(epsomeg,rot);
232 ScalarMatrixProductCoefficient negepsrot(negepsomeg,rot);
233
236
237 trial_fes.Append(E_fes);
238 trial_fes.Append(H_fes);
239 trial_fes.Append(hatE_fes);
240 trial_fes.Append(hatH_fes);
241
242 test_fec.Append(F_fec);
243 test_fec.Append(G_fec);
244
245 ComplexDPGWeakForm * a = new ComplexDPGWeakForm(trial_fes,test_fec);
246 a->StoreMatrices();
247
248 // (E,∇ × F)
249 a->AddTrialIntegrator(new TransposeIntegrator(new MixedCurlIntegrator(one)),
250 nullptr,TrialSpace::E_space,TestSpace::F_space);
251 // -i ω ϵ (E , G)
252 a->AddTrialIntegrator(nullptr,
253 new TransposeIntegrator(new VectorFEMassIntegrator(negepsomeg)),
254 TrialSpace::E_space,TestSpace::G_space);
255 // (H,∇ × G)
256 a->AddTrialIntegrator(new TransposeIntegrator(new MixedCurlIntegrator(one)),
257 nullptr, TrialSpace::H_space,TestSpace::G_space);
258
259 if (dim == 3)
260 {
261 // i ω μ (H, F)
262 a->AddTrialIntegrator(nullptr,
264 TrialSpace::H_space,TestSpace::F_space);
265 // < n×Ê,F>
266 a->AddTrialIntegrator(new TangentTraceIntegrator,nullptr,
267 TrialSpace::hatE_space,TestSpace::F_space);
268 }
269 else
270 {
271 // i ω μ (H, F)
272 a->AddTrialIntegrator(nullptr,new MixedScalarMassIntegrator(muomeg),
273 TrialSpace::H_space,TestSpace::F_space);
274 // <Ê,F>
275 a->AddTrialIntegrator(new TraceIntegrator,nullptr,
276 TrialSpace::hatE_space, TestSpace::F_space);
277 }
278 // < n×Ĥ ,G>
279 a->AddTrialIntegrator(new TangentTraceIntegrator,nullptr,
280 TrialSpace::hatH_space, TestSpace::G_space);
281
282 // test integrators for the adjoint graph norm on the test space
283 // (∇×G ,∇× δG)
284 a->AddTestIntegrator(new CurlCurlIntegrator(one),nullptr,
285 TestSpace::G_space,TestSpace::G_space);
286 // (G,δG)
287 a->AddTestIntegrator(new VectorFEMassIntegrator(one),nullptr,
288 TestSpace::G_space, TestSpace::G_space);
289
290 if (dim == 3)
291 {
292 // (∇×F,∇×δF)
293 a->AddTestIntegrator(new CurlCurlIntegrator(one),nullptr,
294 TestSpace::F_space, TestSpace::F_space);
295 // (F,δF)
296 a->AddTestIntegrator(new VectorFEMassIntegrator(one),nullptr,
297 TestSpace::F_space,TestSpace::F_space);
298 // μ^2 ω^2 (F,δF)
299 a->AddTestIntegrator(new VectorFEMassIntegrator(mu2omeg2),nullptr,
300 TestSpace::F_space, TestSpace::F_space);
301 // -i ω μ (F,∇ × δG) = (F, ω μ ∇ × δ G)
302 a->AddTestIntegrator(nullptr,new MixedVectorWeakCurlIntegrator(negmuomeg),
303 TestSpace::F_space, TestSpace::G_space);
304 // -i ω ϵ (∇ × F, δG)
305 a->AddTestIntegrator(nullptr,new MixedVectorCurlIntegrator(negepsomeg),
306 TestSpace::F_space, TestSpace::G_space);
307 // i ω μ (∇ × G,δF)
308 a->AddTestIntegrator(nullptr,new MixedVectorCurlIntegrator(epsomeg),
309 TestSpace::G_space, TestSpace::F_space);
310 // i ω ϵ (G, ∇ × δF )
311 a->AddTestIntegrator(nullptr,new MixedVectorWeakCurlIntegrator(muomeg),
312 TestSpace::G_space, TestSpace::F_space);
313 // ϵ^2 ω^2 (G,δG)
314 a->AddTestIntegrator(new VectorFEMassIntegrator(eps2omeg2),nullptr,
315 TestSpace::G_space, TestSpace::G_space);
316 }
317 else
318 {
319 // (∇F,∇δF)
320 a->AddTestIntegrator(new DiffusionIntegrator(one),nullptr,
321 TestSpace::F_space, TestSpace::F_space);
322 // (F,δF)
323 a->AddTestIntegrator(new MassIntegrator(one),nullptr,
324 TestSpace::F_space, TestSpace::F_space);
325 // μ^2 ω^2 (F,δF)
326 a->AddTestIntegrator(new MassIntegrator(mu2omeg2),nullptr,
327 TestSpace::F_space, TestSpace::F_space);
328 // -i ω μ (F,∇ × δG) = i (F, -ω μ ∇ × δ G)
329 a->AddTestIntegrator(nullptr,
330 new TransposeIntegrator(new MixedCurlIntegrator(negmuomeg)),
331 TestSpace::F_space, TestSpace::G_space);
332 // -i ω ϵ (∇ × F, δG) = i (- ω ϵ A ∇ F,δG), A = [0 1; -1; 0]
333 a->AddTestIntegrator(nullptr,new MixedVectorGradientIntegrator(negepsrot),
334 TestSpace::F_space, TestSpace::G_space);
335 // i ω μ (∇ × G,δF) = i (ω μ ∇ × G, δF )
336 a->AddTestIntegrator(nullptr,new MixedCurlIntegrator(muomeg),
337 TestSpace::G_space, TestSpace::F_space);
338 // i ω ϵ (G, ∇ × δF ) = i (ω ϵ G, A ∇ δF) = i ( G , ω ϵ A ∇ δF)
339 a->AddTestIntegrator(nullptr,
341 TestSpace::G_space, TestSpace::F_space);
342 // ϵ^2 ω^2 (G,δG)
343 a->AddTestIntegrator(new VectorFEMassIntegrator(eps2omeg2),nullptr,
344 TestSpace::G_space, TestSpace::G_space);
345 }
346
347 // RHS
350 a->AddDomainLFIntegrator(new VectorFEDomainLFIntegrator(f_rhs_r),
351 new VectorFEDomainLFIntegrator(f_rhs_i),
352 TestSpace::G_space);
353
356
357 socketstream E_out_r;
358 socketstream E_out_i;
359
360 real_t err0 = 0.;
361 int dof0 = 0; // init to suppress gcc warning
362
363 std::cout << "\n Ref |"
364 << " Dofs |"
365 << " ω |"
366 << " L2 Error |"
367 << " Rate |"
368 << " PCG it |" << endl;
369 std::cout << std::string(60,'-')
370 << endl;
371
372 for (int it = 0; it<=ref; it++)
373 {
374 if (static_cond) { a->EnableStaticCondensation(); }
375 a->Assemble();
376
377 Array<int> ess_tdof_list;
378 Array<int> ess_bdr;
379 if (mesh.bdr_attributes.Size())
380 {
381 ess_bdr.SetSize(mesh.bdr_attributes.Max());
382 ess_bdr = 1;
383 hatE_fes->GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
384 }
385
386 // shift the ess_tdofs
387 for (int j = 0; j < ess_tdof_list.Size(); j++)
388 {
389 ess_tdof_list[j] += E_fes->GetTrueVSize() + H_fes->GetTrueVSize();
390 }
391
392 Array<int> offsets(5);
393 offsets[0] = 0;
394 offsets[1] = E_fes->GetVSize();
395 offsets[2] = H_fes->GetVSize();
396 offsets[3] = hatE_fes->GetVSize();
397 offsets[4] = hatH_fes->GetVSize();
398 offsets.PartialSum();
399
400 Vector x(2*offsets.Last());
401 x = 0.;
402
403 GridFunction hatE_gf_r(hatE_fes, x, offsets[2]);
404 GridFunction hatE_gf_i(hatE_fes, x, offsets.Last() + offsets[2]);
405 if (dim == 3)
406 {
407 hatE_gf_r.ProjectBdrCoefficientTangent(hatEex_r, ess_bdr);
408 hatE_gf_i.ProjectBdrCoefficientTangent(hatEex_i, ess_bdr);
409 }
410 else
411 {
412 hatE_gf_r.ProjectBdrCoefficientNormal(hatEex_r, ess_bdr);
413 hatE_gf_i.ProjectBdrCoefficientNormal(hatEex_i, ess_bdr);
414 }
415 OperatorPtr Ah;
416 Vector X,B;
417 a->FormLinearSystem(ess_tdof_list,x,Ah, X,B);
418
419 ComplexOperator * Ahc = Ah.As<ComplexOperator>();
420
421 BlockMatrix * A_r = dynamic_cast<BlockMatrix *>(&Ahc->real());
422 BlockMatrix * A_i = dynamic_cast<BlockMatrix *>(&Ahc->imag());
423
424 int num_blocks = A_r->NumRowBlocks();
425 Array<int> tdof_offsets(2*num_blocks+1);
426 tdof_offsets[0] = 0;
427 int k = (static_cond) ? 2 : 0;
428 for (int i=0; i<num_blocks; i++)
429 {
430 tdof_offsets[i+1] = trial_fes[i+k]->GetTrueVSize();
431 tdof_offsets[num_blocks+i+1] = trial_fes[i+k]->GetTrueVSize();
432 }
433 tdof_offsets.PartialSum();
434
435 BlockOperator A(tdof_offsets);
436 for (int i = 0; i<num_blocks; i++)
437 {
438 for (int j = 0; j<num_blocks; j++)
439 {
440 A.SetBlock(i,j,&A_r->GetBlock(i,j));
441 A.SetBlock(i,j+num_blocks,&A_i->GetBlock(i,j), -1.0);
442 A.SetBlock(i+num_blocks,j+num_blocks,&A_r->GetBlock(i,j));
443 A.SetBlock(i+num_blocks,j,&A_i->GetBlock(i,j));
444 }
445 }
446
447 BlockDiagonalPreconditioner M(tdof_offsets);
448 M.owns_blocks = 1;
449 for (int i = 0; i<num_blocks; i++)
450 {
451 M.SetDiagonalBlock(i, new GSSmoother((SparseMatrix&)A_r->GetBlock(i,i)));
452 M.SetDiagonalBlock(num_blocks+i, new GSSmoother((SparseMatrix&)A_r->GetBlock(i,
453 i)));
454 }
455
456 CGSolver cg;
457 cg.SetRelTol(1e-10);
458 cg.SetMaxIter(2000);
459 cg.SetPrintLevel(0);
460 cg.SetPreconditioner(M);
461 cg.SetOperator(A);
462 cg.Mult(B, X);
463
464 a->RecoverFEMSolution(X,x);
465
466 GridFunction E_r(E_fes, x, 0);
467 GridFunction E_i(E_fes, x, offsets.Last());
468
471
472 GridFunction H_r(H_fes, x, offsets[1]);
473 GridFunction H_i(H_fes, x, offsets.Last() + offsets[1]);
474
477
478 int dofs = 0;
479 for (int i = 0; i<trial_fes.Size(); i++)
480 {
481 dofs += trial_fes[i]->GetTrueVSize();
482 }
483
484 real_t E_err_r = E_r.ComputeL2Error(E_ex_r);
485 real_t E_err_i = E_i.ComputeL2Error(E_ex_i);
486 real_t H_err_r = H_r.ComputeL2Error(H_ex_r);
487 real_t H_err_i = H_i.ComputeL2Error(H_ex_i);
488
489 real_t L2Error = sqrt(E_err_r*E_err_r + E_err_i*E_err_i
490 + H_err_r*H_err_r + H_err_i*H_err_i);
491
492 real_t rate_err = (it) ? dim*log(err0/L2Error)/log((real_t)dof0/dofs) : 0.0;
493
494 err0 = L2Error;
495 dof0 = dofs;
496
497 std::ios oldState(nullptr);
498 oldState.copyfmt(std::cout);
499 std::cout << std::right << std::setw(5) << it << " | "
500 << std::setw(10) << dof0 << " | "
501 << std::setprecision(1) << std::fixed
502 << std::setw(4) << 2*rnum << " π | "
503 << std::setprecision(3)
504 << std::setw(10) << std::scientific << err0 << " | "
505 << std::setprecision(2)
506 << std::setw(6) << std::fixed << rate_err << " | "
507 << std::setw(6) << std::fixed << cg.GetNumIterations() << " | "
508 << std::endl;
509 std::cout.copyfmt(oldState);
510
511 if (visualization)
512 {
513 const char * keys = (it == 0 && dim == 2) ? "jRcml\n" : nullptr;
514 char vishost[] = "localhost";
515 VisualizeField(E_out_r,vishost, visport, E_r,
516 "Numerical Electric field (real part)", 0, 0, 500, 500, keys);
517 VisualizeField(E_out_i,vishost, visport, E_i,
518 "Numerical Electric field (imaginary part)", 501, 0, 500, 500, keys);
519 }
520
521 if (it == ref)
522 {
523 break;
524 }
525
526 mesh.UniformRefinement();
527 for (int i =0; i<trial_fes.Size(); i++)
528 {
529 trial_fes[i]->Update(false);
530 }
531 a->Update();
532 }
533
534 delete a;
535 delete F_fec;
536 delete G_fec;
537 delete hatH_fes;
538 delete hatH_fec;
539 delete hatE_fes;
540 delete hatE_fec;
541 delete H_fec;
542 delete E_fec;
543 delete H_fes;
544 delete E_fes;
545
546 return 0;
547}
548
549void E_exact_r(const Vector &x, Vector & E_r)
550{
551 std::vector<std::complex<real_t>> E;
552 maxwell_solution(x, E);
553 E_r.SetSize(E.size());
554 for (unsigned i = 0; i < E.size(); i++)
555 {
556 E_r[i]= E[i].real();
557 }
558}
559
560void E_exact_i(const Vector &x, Vector & E_i)
561{
562 std::vector<std::complex<real_t>> E;
563 maxwell_solution(x, E);
564 E_i.SetSize(E.size());
565 for (unsigned i = 0; i < E.size(); i++)
566 {
567 E_i[i]= E[i].imag();
568 }
569}
570
571void curlE_exact_r(const Vector &x, Vector &curlE_r)
572{
573 std::vector<std::complex<real_t>> curlE;
574 maxwell_solution_curl(x, curlE);
575 curlE_r.SetSize(curlE.size());
576 for (unsigned i = 0; i < curlE.size(); i++)
577 {
578 curlE_r[i]= curlE[i].real();
579 }
580}
581
582void curlE_exact_i(const Vector &x, Vector &curlE_i)
583{
584 std::vector<std::complex<real_t>> curlE;
585 maxwell_solution_curl(x, curlE);
586 curlE_i.SetSize(curlE.size());
587 for (unsigned i = 0; i < curlE.size(); i++)
588 {
589 curlE_i[i]= curlE[i].imag();
590 }
591}
592
593void curlcurlE_exact_r(const Vector &x, Vector & curlcurlE_r)
594{
595 std::vector<std::complex<real_t>> curlcurlE;
596 maxwell_solution_curlcurl(x, curlcurlE);
597 curlcurlE_r.SetSize(curlcurlE.size());
598 for (unsigned i = 0; i < curlcurlE.size(); i++)
599 {
600 curlcurlE_r[i]= curlcurlE[i].real();
601 }
602}
603
604void curlcurlE_exact_i(const Vector &x, Vector & curlcurlE_i)
605{
606 std::vector<std::complex<real_t>> curlcurlE;
607 maxwell_solution_curlcurl(x, curlcurlE);
608 curlcurlE_i.SetSize(curlcurlE.size());
609 for (unsigned i = 0; i < curlcurlE.size(); i++)
610 {
611 curlcurlE_i[i]= curlcurlE[i].imag();
612 }
613}
614
615void H_exact_r(const Vector &x, Vector & H_r)
616{
617 // H = i ∇ × E / ω μ
618 // H_r = - ∇ × E_i / ω μ
619 Vector curlE_i;
620 curlE_exact_i(x,curlE_i);
621 H_r.SetSize(dimc);
622 for (int i = 0; i<dimc; i++)
623 {
624 H_r(i) = - curlE_i(i) / (omega * mu);
625 }
626}
627
628void H_exact_i(const Vector &x, Vector & H_i)
629{
630 // H = i ∇ × E / ω μ
631 // H_i = ∇ × E_r / ω μ
632 Vector curlE_r;
633 curlE_exact_r(x,curlE_r);
634 H_i.SetSize(dimc);
635 for (int i = 0; i<dimc; i++)
636 {
637 H_i(i) = curlE_r(i) / (omega * mu);
638 }
639}
640
641void curlH_exact_r(const Vector &x,Vector &curlH_r)
642{
643 // ∇ × H_r = - ∇ × ∇ × E_i / ω μ
644 Vector curlcurlE_i;
645 curlcurlE_exact_i(x,curlcurlE_i);
646 curlH_r.SetSize(dim);
647 for (int i = 0; i<dim; i++)
648 {
649 curlH_r(i) = -curlcurlE_i(i) / (omega * mu);
650 }
651}
652
653void curlH_exact_i(const Vector &x,Vector &curlH_i)
654{
655 // ∇ × H_i = ∇ × ∇ × E_r / ω μ
656 Vector curlcurlE_r;
657 curlcurlE_exact_r(x,curlcurlE_r);
658 curlH_i.SetSize(dim);
659 for (int i = 0; i<dim; i++)
660 {
661 curlH_i(i) = curlcurlE_r(i) / (omega * mu);
662 }
663}
664
665void hatE_exact_r(const Vector & x, Vector & hatE_r)
666{
667 if (dim == 3)
668 {
669 E_exact_r(x,hatE_r);
670 }
671 else
672 {
673 Vector E_r;
674 E_exact_r(x,E_r);
675 hatE_r.SetSize(hatE_r.Size());
676 // rotate E_hat
677 hatE_r[0] = E_r[1];
678 hatE_r[1] = -E_r[0];
679 }
680}
681
682void hatE_exact_i(const Vector & x, Vector & hatE_i)
683{
684 if (dim == 3)
685 {
686 E_exact_i(x,hatE_i);
687 }
688 else
689 {
690 Vector E_i;
691 E_exact_i(x,E_i);
692 hatE_i.SetSize(hatE_i.Size());
693 // rotate E_hat
694 hatE_i[0] = E_i[1];
695 hatE_i[1] = -E_i[0];
696 }
697}
698
699void hatH_exact_r(const Vector & x, Vector & hatH_r)
700{
701 H_exact_r(x,hatH_r);
702}
703
704void hatH_exact_i(const Vector & x, Vector & hatH_i)
705{
706 H_exact_i(x,hatH_i);
707}
708
710{
711 Vector hatH_r;
712 H_exact_r(x,hatH_r);
713 return hatH_r[0];
714}
715
717{
718 Vector hatH_i;
719 H_exact_i(x,hatH_i);
720 return hatH_i[0];
721}
722
723// J = -i ω ϵ E + ∇ × H
724// J_r + iJ_i = -i ω ϵ (E_r + i E_i) + ∇ × (H_r + i H_i)
725void rhs_func_r(const Vector &x, Vector & J_r)
726{
727 // J_r = ω ϵ E_i + ∇ × H_r
728 Vector E_i, curlH_r;
729 E_exact_i(x,E_i);
730 curlH_exact_r(x,curlH_r);
731 J_r.SetSize(dim);
732 for (int i = 0; i<dim; i++)
733 {
734 J_r(i) = omega * epsilon * E_i(i) + curlH_r(i);
735 }
736}
737
738void rhs_func_i(const Vector &x, Vector & J_i)
739{
740 // J_i = - ω ϵ E_r + ∇ × H_i
741 Vector E_r, curlH_i;
742 E_exact_r(x,E_r);
743 curlH_exact_i(x,curlH_i);
744 J_i.SetSize(dim);
745 for (int i = 0; i<dim; i++)
746 {
747 J_i(i) = -omega * epsilon * E_r(i) + curlH_i(i);
748 }
749}
750
751void maxwell_solution(const Vector & X, std::vector<complex<real_t>> &E)
752{
753 E.resize(dim);
754 std::complex<real_t> zi(0,1);
755 std::complex<real_t> pw = exp(-zi * omega * (X.Sum()));
756 E[0] = pw;
757 E[1] = 0.0;
758 if (dim == 3) { E[2] = 0.0; }
759}
760
762 std::vector<complex<real_t>> &curlE)
763{
764 curlE.resize(dimc);
765 std::complex<real_t> zi(0,1);
766 std::complex<real_t> pw = exp(-zi * omega * (X.Sum()));
767 if (dim == 3)
768 {
769 curlE[0] = 0.0;
770 curlE[1] = -zi * omega * pw;
771 curlE[2] = zi * omega * pw;
772 }
773 else
774 {
775 curlE[0] = zi * omega * pw;
776 }
777}
778
780 std::vector<complex<real_t>> &curlcurlE)
781{
782 curlcurlE.resize(dim);
783 std::complex<real_t> zi(0,1);
784 std::complex<real_t> pw = exp(-zi * omega * (X.Sum()));
785 if (dim == 3)
786 {
787 curlcurlE[0] = 2_r * omega * omega * pw;
788 curlcurlE[1] = - omega * omega * pw;
789 curlcurlE[2] = - omega * omega * pw;
790 }
791 else
792 {
793 curlcurlE[0] = omega * omega * pw;
794 curlcurlE[1] = - omega * omega * pw ;
795 }
796}
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.
void SetDiagonalBlock(int iblock, Operator *op)
Add a square block op in the block-entry (iblock, iblock).
SparseMatrix & GetBlock(int i, int j)
Return a reference to block (i,j). Reference may be invalid if Aij(i,j) == NULL.
int NumRowBlocks() const
Return the number of row blocks.
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).
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 representing the DPG weak formulation for complex valued systems (see the class DPGWeakForm).
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.
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
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition fespace.hpp:244
virtual int GetTrueVSize() const
Return the number of vector true (conforming) dofs.
Definition fespace.hpp:851
virtual void GetEssentialTrueDofs(const Array< int > &bdr_attr_is_ess, Array< int > &ess_tdof_list, int component=-1) const
Get a list of essential true dofs, ess_tdof_list, corresponding to the boundary attributes marked in ...
Definition fespace.cpp:658
int GetVSize() const
Return the number of vector dofs, i.e. GetNDofs() x GetVDim().
Definition fespace.hpp:848
Data type for Gauss-Seidel smoother of sparse matrix.
Class for grid function - Vector with associated FE space.
Definition gridfunc.hpp:31
virtual real_t ComputeL2Error(Coefficient *exsol[], const IntegrationRule *irs[]=NULL, const Array< int > *elems=NULL) const
Returns ||exsol - u_h||_L2 for scalar or vector H1 or L2 elements.
virtual void ProjectBdrCoefficientTangent(VectorCoefficient &vcoeff, const Array< int > &bdr_attr)
Project the tangential components of the given VectorCoefficient on the boundary. Only boundary attri...
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
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
A matrix coefficient that is constant in space and time.
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
int Dimension() const
Dimension of the reference space used within the elements.
Definition mesh.hpp:1216
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
Definition mesh.cpp:11295
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.
Arbitrary order "H^{-1/2}-conforming" face finite elements defined on the interface between mesh elem...
Definition fe_coll.hpp:462
Matrix coefficient defined as a product of a scalar coefficient and a matrix coefficient.
Data type sparse matrix.
Definition sparsemat.hpp:51
for VectorFiniteElements (Nedelec, Raviart-Thomas)
Definition lininteg.hpp:344
A general vector function coefficient.
Vector data type.
Definition vector.hpp:82
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
void curlE_exact_i(const Vector &x, Vector &curlE_i)
Definition maxwell.cpp:582
void H_exact_i(const Vector &x, Vector &H_i)
Definition maxwell.cpp:628
real_t omega
Definition maxwell.cpp:124
void curlcurlE_exact_r(const Vector &x, Vector &curlcurlE_r)
Definition maxwell.cpp:593
int dimc
Definition maxwell.cpp:123
void hatH_exact_r(const Vector &X, Vector &hatH_r)
Definition maxwell.cpp:699
void hatE_exact_r(const Vector &X, Vector &hatE_r)
Definition maxwell.cpp:665
void H_exact_r(const Vector &x, Vector &H_r)
Definition maxwell.cpp:615
real_t hatH_exact_scalar_i(const Vector &X)
Definition maxwell.cpp:716
void curlH_exact_r(const Vector &x, Vector &curlH_r)
Definition maxwell.cpp:641
real_t hatH_exact_scalar_r(const Vector &X)
Definition maxwell.cpp:709
int dim
Definition maxwell.cpp:122
real_t mu
Definition maxwell.cpp:125
void rhs_func_r(const Vector &x, Vector &J_r)
Definition maxwell.cpp:725
void hatH_exact_i(const Vector &X, Vector &hatH_i)
Definition maxwell.cpp:704
void rhs_func_i(const Vector &x, Vector &J_i)
Definition maxwell.cpp:738
real_t epsilon
Definition maxwell.cpp:126
void curlcurlE_exact_i(const Vector &x, Vector &curlcurlE_i)
Definition maxwell.cpp:604
void E_exact_r(const Vector &x, Vector &E_r)
Definition maxwell.cpp:549
void maxwell_solution_curlcurl(const Vector &X, std::vector< complex< real_t > > &curlcurlE)
Definition maxwell.cpp:779
void E_exact_i(const Vector &x, Vector &E_i)
Definition maxwell.cpp:560
void hatE_exact_i(const Vector &X, Vector &hatE_i)
Definition maxwell.cpp:682
void maxwell_solution_curl(const Vector &X, std::vector< complex< real_t > > &curlE)
Definition maxwell.cpp:761
void maxwell_solution(const Vector &X, std::vector< complex< real_t > > &E)
Definition maxwell.cpp:751
void curlE_exact_r(const Vector &x, Vector &curlE_r)
Definition maxwell.cpp:571
void curlH_exact_i(const Vector &x, Vector &curlH_i)
Definition maxwell.cpp:653
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)
float real_t
Definition config.hpp:43
const char vishost[]