MFEM v4.7.0
Finite element discretization library
Loading...
Searching...
No Matches
maxwell.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2024, 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 bool static_cond = false;
137
138 OptionsParser args(argc, argv);
139 args.AddOption(&mesh_file, "-m", "--mesh",
140 "Mesh file to use.");
141 args.AddOption(&order, "-o", "--order",
142 "Finite element order (polynomial degree)");
143 args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
144 "--no-visualization",
145 "Enable or disable GLVis visualization.");
146 args.AddOption(&rnum, "-rnum", "--number-of-wavelengths",
147 "Number of wavelengths");
148 args.AddOption(&mu, "-mu", "--permeability",
149 "Permeability of free space (or 1/(spring constant)).");
150 args.AddOption(&epsilon, "-eps", "--permittivity",
151 "Permittivity of free space (or mass constant).");
152 args.AddOption(&delta_order, "-do", "--delta-order",
153 "Order enrichment for DPG test space.");
154 args.AddOption(&ref, "-ref", "--serial-ref",
155 "Number of serial refinements.");
156 args.AddOption(&static_cond, "-sc", "--static-condensation", "-no-sc",
157 "--no-static-condensation", "Enable static condensation.");
158 args.Parse();
159 if (!args.Good())
160 {
161 args.PrintUsage(cout);
162 return 1;
163 }
164 args.PrintOptions(cout);
165
166 omega = 2.*M_PI*rnum;
167
168 Mesh mesh(mesh_file, 1, 1);
169 dim = mesh.Dimension();
170 MFEM_VERIFY(dim > 1, "Dimension = 1 is not supported in this example");
171
172 dimc = (dim == 3) ? 3 : 1;
173 int test_order = order+delta_order;
174
175 // Define spaces
176 enum TrialSpace
177 {
178 E_space = 0,
179 H_space = 1,
180 hatE_space = 2,
181 hatH_space = 3
182 };
183 enum TestSpace
184 {
185 F_space = 0,
186 G_space = 1
187 };
188 // L2 space for E
189 FiniteElementCollection *E_fec = new L2_FECollection(order-1,dim);
190 FiniteElementSpace *E_fes = new FiniteElementSpace(&mesh,E_fec,dim);
191
192 // Vector L2 space for H
193 FiniteElementCollection *H_fec = new L2_FECollection(order-1,dim);
194 FiniteElementSpace *H_fes = new FiniteElementSpace(&mesh,H_fec, dimc);
195
196 // H^-1/2 (curl) space for Ê
197 FiniteElementCollection * hatE_fec = nullptr;
198 FiniteElementCollection * hatH_fec = nullptr;
199 FiniteElementCollection * F_fec = nullptr;
200 if (dim == 3)
201 {
202 hatE_fec = new ND_Trace_FECollection(order,dim);
203 hatH_fec = new ND_Trace_FECollection(order,dim);
204 F_fec = new ND_FECollection(test_order, dim);
205 }
206 else
207 {
208 hatE_fec = new RT_Trace_FECollection(order-1,dim);
209 hatH_fec = new H1_Trace_FECollection(order,dim);
210 F_fec = new H1_FECollection(test_order, dim);
211 }
212 FiniteElementSpace *hatE_fes = new FiniteElementSpace(&mesh,hatE_fec);
213 FiniteElementSpace *hatH_fes = new FiniteElementSpace(&mesh,hatH_fec);
214 FiniteElementCollection * G_fec = new ND_FECollection(test_order, dim);
215
216 // Coefficients
217 ConstantCoefficient one(1.0);
221 ConstantCoefficient negepsomeg(-epsilon*omega);
223 ConstantCoefficient negmuomeg(-mu*omega);
224
225 DenseMatrix rot_mat(2);
226 rot_mat(0,0) = 0.; rot_mat(0,1) = 1.;
227 rot_mat(1,0) = -1.; rot_mat(1,1) = 0.;
228 MatrixConstantCoefficient rot(rot_mat);
229 ScalarMatrixProductCoefficient epsrot(epsomeg,rot);
230 ScalarMatrixProductCoefficient negepsrot(negepsomeg,rot);
231
234
235 trial_fes.Append(E_fes);
236 trial_fes.Append(H_fes);
237 trial_fes.Append(hatE_fes);
238 trial_fes.Append(hatH_fes);
239
240 test_fec.Append(F_fec);
241 test_fec.Append(G_fec);
242
243 ComplexDPGWeakForm * a = new ComplexDPGWeakForm(trial_fes,test_fec);
244 a->StoreMatrices();
245
246 // (E,∇ × F)
247 a->AddTrialIntegrator(new TransposeIntegrator(new MixedCurlIntegrator(one)),
248 nullptr,TrialSpace::E_space,TestSpace::F_space);
249 // -i ω ϵ (E , G)
250 a->AddTrialIntegrator(nullptr,
251 new TransposeIntegrator(new VectorFEMassIntegrator(negepsomeg)),
252 TrialSpace::E_space,TestSpace::G_space);
253 // (H,∇ × G)
254 a->AddTrialIntegrator(new TransposeIntegrator(new MixedCurlIntegrator(one)),
255 nullptr, TrialSpace::H_space,TestSpace::G_space);
256
257 if (dim == 3)
258 {
259 // i ω μ (H, F)
260 a->AddTrialIntegrator(nullptr,
262 TrialSpace::H_space,TestSpace::F_space);
263 // < n×Ê,F>
264 a->AddTrialIntegrator(new TangentTraceIntegrator,nullptr,
265 TrialSpace::hatE_space,TestSpace::F_space);
266 }
267 else
268 {
269 // i ω μ (H, F)
270 a->AddTrialIntegrator(nullptr,new MixedScalarMassIntegrator(muomeg),
271 TrialSpace::H_space,TestSpace::F_space);
272 // <Ê,F>
273 a->AddTrialIntegrator(new TraceIntegrator,nullptr,
274 TrialSpace::hatE_space, TestSpace::F_space);
275 }
276 // < n×Ĥ ,G>
277 a->AddTrialIntegrator(new TangentTraceIntegrator,nullptr,
278 TrialSpace::hatH_space, TestSpace::G_space);
279
280 // test integrators for the adjoint graph norm on the test space
281 // (∇×G ,∇× δG)
282 a->AddTestIntegrator(new CurlCurlIntegrator(one),nullptr,
283 TestSpace::G_space,TestSpace::G_space);
284 // (G,δG)
285 a->AddTestIntegrator(new VectorFEMassIntegrator(one),nullptr,
286 TestSpace::G_space, TestSpace::G_space);
287
288 if (dim == 3)
289 {
290 // (∇×F,∇×δF)
291 a->AddTestIntegrator(new CurlCurlIntegrator(one),nullptr,
292 TestSpace::F_space, TestSpace::F_space);
293 // (F,δF)
294 a->AddTestIntegrator(new VectorFEMassIntegrator(one),nullptr,
295 TestSpace::F_space,TestSpace::F_space);
296 // μ^2 ω^2 (F,δF)
297 a->AddTestIntegrator(new VectorFEMassIntegrator(mu2omeg2),nullptr,
298 TestSpace::F_space, TestSpace::F_space);
299 // -i ω μ (F,∇ × δG) = (F, ω μ ∇ × δ G)
300 a->AddTestIntegrator(nullptr,new MixedVectorWeakCurlIntegrator(negmuomeg),
301 TestSpace::F_space, TestSpace::G_space);
302 // -i ω ϵ (∇ × F, δG)
303 a->AddTestIntegrator(nullptr,new MixedVectorCurlIntegrator(negepsomeg),
304 TestSpace::F_space, TestSpace::G_space);
305 // i ω μ (∇ × G,δF)
306 a->AddTestIntegrator(nullptr,new MixedVectorCurlIntegrator(epsomeg),
307 TestSpace::G_space, TestSpace::F_space);
308 // i ω ϵ (G, ∇ × δF )
309 a->AddTestIntegrator(nullptr,new MixedVectorWeakCurlIntegrator(muomeg),
310 TestSpace::G_space, TestSpace::F_space);
311 // ϵ^2 ω^2 (G,δG)
312 a->AddTestIntegrator(new VectorFEMassIntegrator(eps2omeg2),nullptr,
313 TestSpace::G_space, TestSpace::G_space);
314 }
315 else
316 {
317 // (∇F,∇δF)
318 a->AddTestIntegrator(new DiffusionIntegrator(one),nullptr,
319 TestSpace::F_space, TestSpace::F_space);
320 // (F,δF)
321 a->AddTestIntegrator(new MassIntegrator(one),nullptr,
322 TestSpace::F_space, TestSpace::F_space);
323 // μ^2 ω^2 (F,δF)
324 a->AddTestIntegrator(new MassIntegrator(mu2omeg2),nullptr,
325 TestSpace::F_space, TestSpace::F_space);
326 // -i ω μ (F,∇ × δG) = i (F, -ω μ ∇ × δ G)
327 a->AddTestIntegrator(nullptr,
328 new TransposeIntegrator(new MixedCurlIntegrator(negmuomeg)),
329 TestSpace::F_space, TestSpace::G_space);
330 // -i ω ϵ (∇ × F, δG) = i (- ω ϵ A ∇ F,δG), A = [0 1; -1; 0]
331 a->AddTestIntegrator(nullptr,new MixedVectorGradientIntegrator(negepsrot),
332 TestSpace::F_space, TestSpace::G_space);
333 // i ω μ (∇ × G,δF) = i (ω μ ∇ × G, δF )
334 a->AddTestIntegrator(nullptr,new MixedCurlIntegrator(muomeg),
335 TestSpace::G_space, TestSpace::F_space);
336 // i ω ϵ (G, ∇ × δF ) = i (ω ϵ G, A ∇ δF) = i ( G , ω ϵ A ∇ δF)
337 a->AddTestIntegrator(nullptr,
339 TestSpace::G_space, TestSpace::F_space);
340 // ϵ^2 ω^2 (G,δG)
341 a->AddTestIntegrator(new VectorFEMassIntegrator(eps2omeg2),nullptr,
342 TestSpace::G_space, TestSpace::G_space);
343 }
344
345 // RHS
348 a->AddDomainLFIntegrator(new VectorFEDomainLFIntegrator(f_rhs_r),
349 new VectorFEDomainLFIntegrator(f_rhs_i),
350 TestSpace::G_space);
351
354
355 socketstream E_out_r;
356 socketstream E_out_i;
357
358 real_t err0 = 0.;
359 int dof0 = 0; // init to suppress gcc warning
360
361 std::cout << "\n Ref |"
362 << " Dofs |"
363 << " ω |"
364 << " L2 Error |"
365 << " Rate |"
366 << " PCG it |" << endl;
367 std::cout << std::string(60,'-')
368 << endl;
369
370 for (int it = 0; it<=ref; it++)
371 {
372 if (static_cond) { a->EnableStaticCondensation(); }
373 a->Assemble();
374
375 Array<int> ess_tdof_list;
376 Array<int> ess_bdr;
377 if (mesh.bdr_attributes.Size())
378 {
379 ess_bdr.SetSize(mesh.bdr_attributes.Max());
380 ess_bdr = 1;
381 hatE_fes->GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
382 }
383
384 // shift the ess_tdofs
385 for (int j = 0; j < ess_tdof_list.Size(); j++)
386 {
387 ess_tdof_list[j] += E_fes->GetTrueVSize() + H_fes->GetTrueVSize();
388 }
389
390 Array<int> offsets(5);
391 offsets[0] = 0;
392 offsets[1] = E_fes->GetVSize();
393 offsets[2] = H_fes->GetVSize();
394 offsets[3] = hatE_fes->GetVSize();
395 offsets[4] = hatH_fes->GetVSize();
396 offsets.PartialSum();
397
398 Vector x(2*offsets.Last());
399 x = 0.;
400
401 GridFunction hatE_gf_r(hatE_fes, x, offsets[2]);
402 GridFunction hatE_gf_i(hatE_fes, x, offsets.Last() + offsets[2]);
403 if (dim == 3)
404 {
405 hatE_gf_r.ProjectBdrCoefficientTangent(hatEex_r, ess_bdr);
406 hatE_gf_i.ProjectBdrCoefficientTangent(hatEex_i, ess_bdr);
407 }
408 else
409 {
410 hatE_gf_r.ProjectBdrCoefficientNormal(hatEex_r, ess_bdr);
411 hatE_gf_i.ProjectBdrCoefficientNormal(hatEex_i, ess_bdr);
412 }
413 OperatorPtr Ah;
414 Vector X,B;
415 a->FormLinearSystem(ess_tdof_list,x,Ah, X,B);
416
417 ComplexOperator * Ahc = Ah.As<ComplexOperator>();
418
419 BlockMatrix * A_r = dynamic_cast<BlockMatrix *>(&Ahc->real());
420 BlockMatrix * A_i = dynamic_cast<BlockMatrix *>(&Ahc->imag());
421
422 int num_blocks = A_r->NumRowBlocks();
423 Array<int> tdof_offsets(2*num_blocks+1);
424 tdof_offsets[0] = 0;
425 int k = (static_cond) ? 2 : 0;
426 for (int i=0; i<num_blocks; i++)
427 {
428 tdof_offsets[i+1] = trial_fes[i+k]->GetTrueVSize();
429 tdof_offsets[num_blocks+i+1] = trial_fes[i+k]->GetTrueVSize();
430 }
431 tdof_offsets.PartialSum();
432
433 BlockOperator A(tdof_offsets);
434 for (int i = 0; i<num_blocks; i++)
435 {
436 for (int j = 0; j<num_blocks; j++)
437 {
438 A.SetBlock(i,j,&A_r->GetBlock(i,j));
439 A.SetBlock(i,j+num_blocks,&A_i->GetBlock(i,j), -1.0);
440 A.SetBlock(i+num_blocks,j+num_blocks,&A_r->GetBlock(i,j));
441 A.SetBlock(i+num_blocks,j,&A_i->GetBlock(i,j));
442 }
443 }
444
445 BlockDiagonalPreconditioner M(tdof_offsets);
446 M.owns_blocks = 1;
447 for (int i = 0; i<num_blocks; i++)
448 {
449 M.SetDiagonalBlock(i, new GSSmoother((SparseMatrix&)A_r->GetBlock(i,i)));
450 M.SetDiagonalBlock(num_blocks+i, new GSSmoother((SparseMatrix&)A_r->GetBlock(i,
451 i)));
452 }
453
454 CGSolver cg;
455 cg.SetRelTol(1e-10);
456 cg.SetMaxIter(2000);
457 cg.SetPrintLevel(0);
458 cg.SetPreconditioner(M);
459 cg.SetOperator(A);
460 cg.Mult(B, X);
461
462 a->RecoverFEMSolution(X,x);
463
464 GridFunction E_r(E_fes, x, 0);
465 GridFunction E_i(E_fes, x, offsets.Last());
466
469
470 GridFunction H_r(H_fes, x, offsets[1]);
471 GridFunction H_i(H_fes, x, offsets.Last() + offsets[1]);
472
475
476 int dofs = 0;
477 for (int i = 0; i<trial_fes.Size(); i++)
478 {
479 dofs += trial_fes[i]->GetTrueVSize();
480 }
481
482 real_t E_err_r = E_r.ComputeL2Error(E_ex_r);
483 real_t E_err_i = E_i.ComputeL2Error(E_ex_i);
484 real_t H_err_r = H_r.ComputeL2Error(H_ex_r);
485 real_t H_err_i = H_i.ComputeL2Error(H_ex_i);
486
487 real_t L2Error = sqrt(E_err_r*E_err_r + E_err_i*E_err_i
488 + H_err_r*H_err_r + H_err_i*H_err_i);
489
490 real_t rate_err = (it) ? dim*log(err0/L2Error)/log((real_t)dof0/dofs) : 0.0;
491
492 err0 = L2Error;
493 dof0 = dofs;
494
495 std::ios oldState(nullptr);
496 oldState.copyfmt(std::cout);
497 std::cout << std::right << std::setw(5) << it << " | "
498 << std::setw(10) << dof0 << " | "
499 << std::setprecision(1) << std::fixed
500 << std::setw(4) << 2*rnum << " π | "
501 << std::setprecision(3)
502 << std::setw(10) << std::scientific << err0 << " | "
503 << std::setprecision(2)
504 << std::setw(6) << std::fixed << rate_err << " | "
505 << std::setw(6) << std::fixed << cg.GetNumIterations() << " | "
506 << std::endl;
507 std::cout.copyfmt(oldState);
508
509 if (visualization)
510 {
511 const char * keys = (it == 0 && dim == 2) ? "jRcml\n" : nullptr;
512 char vishost[] = "localhost";
513 int visport = 19916;
514 VisualizeField(E_out_r,vishost, visport, E_r,
515 "Numerical Electric field (real part)", 0, 0, 500, 500, keys);
516 VisualizeField(E_out_i,vishost, visport, E_i,
517 "Numerical Electric field (imaginary part)", 501, 0, 500, 500, keys);
518 }
519
520 if (it == ref)
521 {
522 break;
523 }
524
525 mesh.UniformRefinement();
526 for (int i =0; i<trial_fes.Size(); i++)
527 {
528 trial_fes[i]->Update(false);
529 }
530 a->Update();
531 }
532
533 delete a;
534 delete F_fec;
535 delete G_fec;
536 delete hatH_fes;
537 delete hatH_fec;
538 delete hatE_fes;
539 delete hatE_fec;
540 delete H_fec;
541 delete E_fec;
542 delete H_fes;
543 delete E_fes;
544
545 return 0;
546}
547
548void E_exact_r(const Vector &x, Vector & E_r)
549{
550 std::vector<std::complex<real_t>> E;
551 maxwell_solution(x, E);
552 E_r.SetSize(E.size());
553 for (unsigned i = 0; i < E.size(); i++)
554 {
555 E_r[i]= E[i].real();
556 }
557}
558
559void E_exact_i(const Vector &x, Vector & E_i)
560{
561 std::vector<std::complex<real_t>> E;
562 maxwell_solution(x, E);
563 E_i.SetSize(E.size());
564 for (unsigned i = 0; i < E.size(); i++)
565 {
566 E_i[i]= E[i].imag();
567 }
568}
569
570void curlE_exact_r(const Vector &x, Vector &curlE_r)
571{
572 std::vector<std::complex<real_t>> curlE;
573 maxwell_solution_curl(x, curlE);
574 curlE_r.SetSize(curlE.size());
575 for (unsigned i = 0; i < curlE.size(); i++)
576 {
577 curlE_r[i]= curlE[i].real();
578 }
579}
580
581void curlE_exact_i(const Vector &x, Vector &curlE_i)
582{
583 std::vector<std::complex<real_t>> curlE;
584 maxwell_solution_curl(x, curlE);
585 curlE_i.SetSize(curlE.size());
586 for (unsigned i = 0; i < curlE.size(); i++)
587 {
588 curlE_i[i]= curlE[i].imag();
589 }
590}
591
592void curlcurlE_exact_r(const Vector &x, Vector & curlcurlE_r)
593{
594 std::vector<std::complex<real_t>> curlcurlE;
595 maxwell_solution_curlcurl(x, curlcurlE);
596 curlcurlE_r.SetSize(curlcurlE.size());
597 for (unsigned i = 0; i < curlcurlE.size(); i++)
598 {
599 curlcurlE_r[i]= curlcurlE[i].real();
600 }
601}
602
603void curlcurlE_exact_i(const Vector &x, Vector & curlcurlE_i)
604{
605 std::vector<std::complex<real_t>> curlcurlE;
606 maxwell_solution_curlcurl(x, curlcurlE);
607 curlcurlE_i.SetSize(curlcurlE.size());
608 for (unsigned i = 0; i < curlcurlE.size(); i++)
609 {
610 curlcurlE_i[i]= curlcurlE[i].imag();
611 }
612}
613
614void H_exact_r(const Vector &x, Vector & H_r)
615{
616 // H = i ∇ × E / ω μ
617 // H_r = - ∇ × E_i / ω μ
618 Vector curlE_i;
619 curlE_exact_i(x,curlE_i);
620 H_r.SetSize(dimc);
621 for (int i = 0; i<dimc; i++)
622 {
623 H_r(i) = - curlE_i(i) / (omega * mu);
624 }
625}
626
627void H_exact_i(const Vector &x, Vector & H_i)
628{
629 // H = i ∇ × E / ω μ
630 // H_i = ∇ × E_r / ω μ
631 Vector curlE_r;
632 curlE_exact_r(x,curlE_r);
633 H_i.SetSize(dimc);
634 for (int i = 0; i<dimc; i++)
635 {
636 H_i(i) = curlE_r(i) / (omega * mu);
637 }
638}
639
640void curlH_exact_r(const Vector &x,Vector &curlH_r)
641{
642 // ∇ × H_r = - ∇ × ∇ × E_i / ω μ
643 Vector curlcurlE_i;
644 curlcurlE_exact_i(x,curlcurlE_i);
645 curlH_r.SetSize(dim);
646 for (int i = 0; i<dim; i++)
647 {
648 curlH_r(i) = -curlcurlE_i(i) / (omega * mu);
649 }
650}
651
652void curlH_exact_i(const Vector &x,Vector &curlH_i)
653{
654 // ∇ × H_i = ∇ × ∇ × E_r / ω μ
655 Vector curlcurlE_r;
656 curlcurlE_exact_r(x,curlcurlE_r);
657 curlH_i.SetSize(dim);
658 for (int i = 0; i<dim; i++)
659 {
660 curlH_i(i) = curlcurlE_r(i) / (omega * mu);
661 }
662}
663
664void hatE_exact_r(const Vector & x, Vector & hatE_r)
665{
666 if (dim == 3)
667 {
668 E_exact_r(x,hatE_r);
669 }
670 else
671 {
672 Vector E_r;
673 E_exact_r(x,E_r);
674 hatE_r.SetSize(hatE_r.Size());
675 // rotate E_hat
676 hatE_r[0] = E_r[1];
677 hatE_r[1] = -E_r[0];
678 }
679}
680
681void hatE_exact_i(const Vector & x, Vector & hatE_i)
682{
683 if (dim == 3)
684 {
685 E_exact_i(x,hatE_i);
686 }
687 else
688 {
689 Vector E_i;
690 E_exact_i(x,E_i);
691 hatE_i.SetSize(hatE_i.Size());
692 // rotate E_hat
693 hatE_i[0] = E_i[1];
694 hatE_i[1] = -E_i[0];
695 }
696}
697
698void hatH_exact_r(const Vector & x, Vector & hatH_r)
699{
700 H_exact_r(x,hatH_r);
701}
702
703void hatH_exact_i(const Vector & x, Vector & hatH_i)
704{
705 H_exact_i(x,hatH_i);
706}
707
709{
710 Vector hatH_r;
711 H_exact_r(x,hatH_r);
712 return hatH_r[0];
713}
714
716{
717 Vector hatH_i;
718 H_exact_i(x,hatH_i);
719 return hatH_i[0];
720}
721
722// J = -i ω ϵ E + ∇ × H
723// J_r + iJ_i = -i ω ϵ (E_r + i E_i) + ∇ × (H_r + i H_i)
724void rhs_func_r(const Vector &x, Vector & J_r)
725{
726 // J_r = ω ϵ E_i + ∇ × H_r
727 Vector E_i, curlH_r;
728 E_exact_i(x,E_i);
729 curlH_exact_r(x,curlH_r);
730 J_r.SetSize(dim);
731 for (int i = 0; i<dim; i++)
732 {
733 J_r(i) = omega * epsilon * E_i(i) + curlH_r(i);
734 }
735}
736
737void rhs_func_i(const Vector &x, Vector & J_i)
738{
739 // J_i = - ω ϵ E_r + ∇ × H_i
740 Vector E_r, curlH_i;
741 E_exact_r(x,E_r);
742 curlH_exact_i(x,curlH_i);
743 J_i.SetSize(dim);
744 for (int i = 0; i<dim; i++)
745 {
746 J_i(i) = -omega * epsilon * E_r(i) + curlH_i(i);
747 }
748}
749
750void maxwell_solution(const Vector & X, std::vector<complex<real_t>> &E)
751{
752 E.resize(dim);
753 std::complex<real_t> zi(0,1);
754 std::complex<real_t> pw = exp(-zi * omega * (X.Sum()));
755 E[0] = pw;
756 E[1] = 0.0;
757 if (dim == 3) { E[2] = 0.0; }
758}
759
761 std::vector<complex<real_t>> &curlE)
762{
763 curlE.resize(dimc);
764 std::complex<real_t> zi(0,1);
765 std::complex<real_t> pw = exp(-zi * omega * (X.Sum()));
766 if (dim == 3)
767 {
768 curlE[0] = 0.0;
769 curlE[1] = -zi * omega * pw;
770 curlE[2] = zi * omega * pw;
771 }
772 else
773 {
774 curlE[0] = zi * omega * pw;
775 }
776}
777
779 std::vector<complex<real_t>> &curlcurlE)
780{
781 curlcurlE.resize(dim);
782 std::complex<real_t> zi(0,1);
783 std::complex<real_t> pw = exp(-zi * omega * (X.Sum()));
784 if (dim == 3)
785 {
786 curlcurlE[0] = 2_r * omega * omega * pw;
787 curlcurlE[1] = - omega * omega * pw;
788 curlcurlE[2] = - omega * omega * pw;
789 }
790 else
791 {
792 curlcurlE[0] = omega * omega * pw;
793 curlcurlE[1] = - omega * omega * pw ;
794 }
795}
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:697
int Size() const
Return the logical size of the array.
Definition array.hpp:144
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:769
T & Last()
Return the last element in the array.
Definition array.hpp:802
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:513
virtual void SetOperator(const Operator &op)
Also calls SetOperator for the preconditioner if there is one.
Definition solvers.hpp:526
virtual void Mult(const Vector &b, Vector &x) const
Iterative solution of the linear system using the Conjugate Gradient method.
Definition solvers.cpp:718
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:220
virtual int GetTrueVSize() const
Return the number of vector true (conforming) dofs.
Definition fespace.hpp:716
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:588
int GetVSize() const
Return the number of vector dofs, i.e. GetNDofs() x GetVDim().
Definition fespace.hpp:713
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
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:260
Arbitrary order "H^{1/2}-conforming" trace finite elements defined on the interface between mesh elem...
Definition fe_coll.hpp:322
void SetRelTol(real_t rtol)
Definition solvers.hpp:209
virtual void SetPreconditioner(Solver &pr)
This should be called before SetOperator.
Definition solvers.cpp:173
int GetNumIterations() const
Returns the number of iterations taken during the last call to Mult()
Definition solvers.hpp:260
virtual void SetPrintLevel(int print_lvl)
Legacy method to set the level of verbosity of the solver output.
Definition solvers.cpp:71
void SetMaxIter(int max_it)
Definition solvers.hpp:211
Arbitrary order "L2-conforming" discontinuous finite elements.
Definition fe_coll.hpp:330
A matrix coefficient that is constant in space and time.
Mesh data type.
Definition mesh.hpp:56
Array< int > bdr_attributes
A list of all unique boundary attributes used by the Mesh.
Definition mesh.hpp:282
int Dimension() const
Dimension of the reference space used within the elements.
Definition mesh.hpp:1160
void UniformRefinement(int i, const DSTable &, int *, int *, int *)
Definition mesh.cpp:10970
Arbitrary order H(curl)-conforming Nedelec finite elements.
Definition fe_coll.hpp:465
Arbitrary order H(curl)-trace finite elements defined on the interface between mesh elements (faces,...
Definition fe_coll.hpp:511
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:445
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:347
A general vector function coefficient.
Vector data type.
Definition vector.hpp:80
int Size() const
Returns the size of the vector.
Definition vector.hpp:218
real_t Sum() const
Return the sum of the vector entries.
Definition vector.cpp:1283
void SetSize(int s)
Resize the vector to size s.
Definition vector.hpp:538
void curlE_exact_i(const Vector &x, Vector &curlE_i)
Definition maxwell.cpp:581
void H_exact_i(const Vector &x, Vector &H_i)
Definition maxwell.cpp:627
real_t omega
Definition maxwell.cpp:124
void curlcurlE_exact_r(const Vector &x, Vector &curlcurlE_r)
Definition maxwell.cpp:592
int dimc
Definition maxwell.cpp:123
void hatH_exact_r(const Vector &X, Vector &hatH_r)
Definition maxwell.cpp:698
void hatE_exact_r(const Vector &X, Vector &hatE_r)
Definition maxwell.cpp:664
void H_exact_r(const Vector &x, Vector &H_r)
Definition maxwell.cpp:614
real_t hatH_exact_scalar_i(const Vector &X)
Definition maxwell.cpp:715
void curlH_exact_r(const Vector &x, Vector &curlH_r)
Definition maxwell.cpp:640
real_t hatH_exact_scalar_r(const Vector &X)
Definition maxwell.cpp:708
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:724
void hatH_exact_i(const Vector &X, Vector &hatH_i)
Definition maxwell.cpp:703
void rhs_func_i(const Vector &x, Vector &J_i)
Definition maxwell.cpp:737
real_t epsilon
Definition maxwell.cpp:126
void curlcurlE_exact_i(const Vector &x, Vector &curlcurlE_i)
Definition maxwell.cpp:603
void E_exact_r(const Vector &x, Vector &E_r)
Definition maxwell.cpp:548
void maxwell_solution_curlcurl(const Vector &X, std::vector< complex< real_t > > &curlcurlE)
Definition maxwell.cpp:778
void E_exact_i(const Vector &x, Vector &E_i)
Definition maxwell.cpp:559
void hatE_exact_i(const Vector &X, Vector &hatE_i)
Definition maxwell.cpp:681
void maxwell_solution_curl(const Vector &X, std::vector< complex< real_t > > &curlE)
Definition maxwell.cpp:760
void maxwell_solution(const Vector &X, std::vector< complex< real_t > > &E)
Definition maxwell.cpp:750
void curlE_exact_r(const Vector &x, Vector &curlE_r)
Definition maxwell.cpp:570
void curlH_exact_i(const Vector &x, Vector &curlH_i)
Definition maxwell.cpp:652
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)
const int visport
float real_t
Definition config.hpp:43
const char vishost[]