Nektar++
MMFMaxwell.cpp
Go to the documentation of this file.
1 /////////////////////////////////////////////////////////////////////////////
2 //
3 // File MMFMaxwell.cpp
4 //
5 // For more information, please see: http://www.nektar.info
6 //
7 // The MIT License
8 //
9 // Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10 // Department of Aeronautics, Imperial College London (UK), and Scientific
11 // Computing and Imaging Institute, University of Utah (USA).
12 //
13 // Permission is hereby granted, free of charge, to any person obtaining a
14 // copy of this software and associated documentation files (the "Software"),
15 // to deal in the Software without restriction, including without limitation
16 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 // and/or sell copies of the Software, and to permit persons to whom the
18 // Software is furnished to do so, subject to the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be included
21 // in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 // DEALINGS IN THE SOFTWARE.
30 //
31 // Description: MMF Maxwell solve routines
32 //
33 ///////////////////////////////////////////////////////////////////////////////
34 
36 
37 #include <boost/core/ignore_unused.hpp>
38 #include <boost/algorithm/string/predicate.hpp>
39 #include <boost/algorithm/string.hpp>
40 #include <iomanip>
41 #include <iostream>
42 
46 #include <SolverUtils/MMFSystem.h>
47 
48 #include <typeinfo>
49 
50 namespace Nektar
51 {
52 std::string MMFMaxwell::className =
54  "MMFMaxwell", MMFMaxwell::create, "MMFMaxwell equation.");
55 
58  : UnsteadySystem(pSession, pGraph), MMFSystem(pSession, pGraph)
59 {
60 }
61 
62 /**
63  * @brief Initialisation object for the unsteady linear advection equation.
64  */
66 {
67  // Call to the initialisation object
69 
70  int nq = m_fields[0]->GetNpoints();
71  int shapedim = m_fields[0]->GetShapeDimension();
72 
73  m_session->LoadParameter("ElemtGroup0", m_ElemtGroup0, 0);
74  m_session->LoadParameter("ElemtGroup1", m_ElemtGroup1, 0);
75  m_session->LoadParameter("boundaryforSF", m_boundaryforSF, 0);
76  m_session->LoadParameter("PrintoutSurfaceCurrent", m_PrintoutSurfaceCurrent,
77  0);
78 
79  m_session->LoadParameter("AddRotation", m_AddRotation, 0);
80 
81  m_session->LoadParameter("NoInc", m_NoInc, 0);
82 
83  // PML parameters
84  m_session->LoadParameter("TestPML", m_TestPML, 0);
85  m_session->LoadParameter("PMLelement", m_PMLelement, 0);
86  m_session->LoadParameter("RecPML", m_RecPML, 0);
87 
88  m_session->LoadParameter("AddPML", m_AddPML, 0);
89  if (m_AddPML == 1)
90  {
92  }
93  m_session->LoadParameter("PMLorder", m_PMLorder, 3);
94 
95  m_session->LoadParameter("PMLthickness", m_PMLthickness, 0.0);
96  m_session->LoadParameter("PMLstart", m_PMLstart, 0.0);
97  m_session->LoadParameter("PMLmaxsigma", m_PMLmaxsigma, 100.0);
98 
99  // Point Source parmaters
100  m_session->LoadParameter("Psx", m_Psx, 0.0);
101  m_session->LoadParameter("Psy", m_Psy, 0.0);
102  m_session->LoadParameter("Psz", m_Psz, 0.0);
103  m_session->LoadParameter("PSduration", m_PSduration, 1.0);
104  m_session->LoadParameter("Gaussianradius", m_Gaussianradius, 1.0);
105 
106  // Cloaking parameter
107  m_session->LoadParameter("CloakNlayer", m_CloakNlayer, 5);
108  m_session->LoadParameter("Cloakraddelta", m_Cloakraddelta, 0.0);
109 
111  m_session->LoadParameter("varepsilon1", m_varepsilon[0], 1.0);
112  m_session->LoadParameter("varepsilon2", m_varepsilon[1], 1.0);
113  m_session->LoadParameter("varepsilon3", m_varepsilon[2], 1.0);
114  m_n1 = sqrt(m_varepsilon[0]);
115  m_n2 = sqrt(m_varepsilon[1]);
116  m_n3 = sqrt(m_varepsilon[2]);
117 
119  m_session->LoadParameter("mu1", m_mu[0], 1.0);
120  m_session->LoadParameter("mu2", m_mu[1], 1.0);
121  m_session->LoadParameter("mu3", m_mu[2], 1.0);
122 
123  Array<OneD, Array<OneD, NekDouble>> Anisotropy(shapedim);
124  for (int j = 0; j < shapedim; ++j)
125  {
126  Anisotropy[j] = Array<OneD, NekDouble>(nq, 1.0);
127  }
128 
129  // Add Rectangular PML
130  MMFSystem::MMFInitObject(Anisotropy, m_RecPML);
131 
132  // Compute the cross producted MF
134 
135  m_session->LoadParameter("Frequency", m_freq, 1.0);
136 
137  // Define TestMaxwellType
138  if (m_session->DefinesSolverInfo("TESTMAXWELLTYPE"))
139  {
140  std::string TestMaxwellTypeStr =
141  m_session->GetSolverInfo("TESTMAXWELLTYPE");
142  for (int i = 0; i < (int)SolverUtils::SIZE_TestMaxwellType; ++i)
143  {
144  if (boost::iequals(SolverUtils::TestMaxwellTypeMap[i],
145  TestMaxwellTypeStr))
146  {
148  break;
149  }
150  }
151  }
152 
153  else
154  {
156  }
157 
158  // Define Polarization
159  if (m_session->DefinesSolverInfo("POLTYPE"))
160  {
161  std::string PolTypeStr = m_session->GetSolverInfo("POLTYPE");
162  for (int i = 0; i < (int)SolverUtils::SIZE_PolType; ++i)
163  {
164  if (boost::iequals(SolverUtils::PolTypeMap[i], PolTypeStr))
165  {
167  break;
168  }
169  }
170  }
171  else
172  {
174  }
175 
176  // Define Incident wave Type
177  if (m_session->DefinesSolverInfo("INCTYPE"))
178  {
179  std::string IncTypeStr = m_session->GetSolverInfo("INCTYPE");
180  for (int i = 0; i < (int)SolverUtils::SIZE_IncType; ++i)
181  {
182  if (boost::iequals(SolverUtils::IncTypeMap[i], IncTypeStr))
183  {
185  break;
186  }
187  }
188  }
189  else
190  {
192  }
193 
194  // Define Cloak Type
195  if (m_session->DefinesSolverInfo("CLOAKTYPE"))
196  {
197  std::string CloakTypeStr = m_session->GetSolverInfo("CLOAKTYPE");
198  for (int i = 0; i < (int)SIZE_CloakType; ++i)
199  {
200  if (boost::iequals(CloakTypeMap[i], CloakTypeStr))
201  {
202  m_CloakType = (CloakType)i;
203  break;
204  }
205  }
206  }
207  else
208  {
209  m_CloakType = (CloakType)0;
210  }
211 
212  // Define Source Type
213  if (m_session->DefinesSolverInfo("SOURCETYPE"))
214  {
215  std::string SourceTypeStr = m_session->GetSolverInfo("SOURCETYPE");
216  for (int i = 0; i < (int)SIZE_SourceType; ++i)
217  {
218  if (boost::iequals(SourceTypeMap[i], SourceTypeStr))
219  {
221  break;
222  }
223  }
224  }
225  else
226  {
228  }
229 
230  // Compute n_timesMFFwd and m_times_timesMFFwd
231  ComputeNtimesMF();
232 
233  // Compute vaepsilon and mu vector (m_epsveci, m_muvec0);
236  for (int k = 0; k < m_spacedim; ++k)
237  {
238  m_epsvec[k] = Array<OneD, NekDouble>(nq, 1.0);
239  m_muvec[k] = Array<OneD, NekDouble>(nq, 1.0);
240  }
241 
242  Array<OneD, NekDouble> radvec(nq);
243  m_DispersiveCloak = false;
244  switch (m_CloakType)
245  {
246  case eOpticalCloak:
247  {
248  radvec = ComputeRadCloak();
250  }
251  break;
252 
253  case eOpticalConstCloak:
254  {
255  radvec = ComputeRadCloak(m_CloakNlayer);
257 
258  std::cout << "*** rad = [ " << Vmath::Vmax(nq, radvec, 1) << " , "
259  << Vmath::Vmin(nq, radvec, 1) << " ) " << std::endl;
260  }
261  break;
262 
264  {
265  m_DispersiveCloak = true;
266  m_wp2Tol = 0.01;
267  radvec = ComputeRadCloak();
269 
270  std::cout << "*** rad = [ " << Vmath::Vmax(nq, radvec, 1) << " , "
271  << Vmath::Vmin(nq, radvec, 1) << " ) " << std::endl;
272  std::cout << "*** wp2 = [ " << Vmath::Vmax(nq, m_wp2, 1) << " , "
273  << Vmath::Vmin(nq, m_wp2, 1) << " ) " << std::endl;
274  }
275  break;
276 
277  case eMicroWaveCloak:
278  {
279  radvec = ComputeRadCloak();
281  }
282  break;
283 
284  default:
285  {
287  }
288  break;
289  }
290 
291  NekDouble eps1min, eps1max, eps2min, eps2max, eps3min, eps3max;
292  NekDouble mu1min, mu1max, mu2min, mu2max, mu3min, mu3max;
293 
294  eps1min = Vmath::Vmin(nq, m_epsvec[0], 1);
295  eps3min = Vmath::Vmin(nq, m_epsvec[2], 1);
296  eps1max = Vmath::Vmax(nq, m_epsvec[0], 1);
297  eps3max = Vmath::Vmax(nq, m_epsvec[2], 1);
298 
299  if (m_DispersiveCloak)
300  {
301  Array<OneD, NekDouble> realepsr(nq);
302  Vmath::Sadd(nq, -m_wp2Tol, m_wp2, 1, realepsr, 1);
303  Vmath::Smul(nq, 1.0 / (m_Incfreq * m_Incfreq), realepsr, 1, realepsr,
304  1);
305  Vmath::Neg(nq, realepsr, 1);
306  Vmath::Sadd(nq, 1.0, realepsr, 1, realepsr, 1);
307 
308  eps2min = Vmath::Vmin(nq, realepsr, 1);
309  eps2max = Vmath::Vmax(nq, realepsr, 1);
310  }
311 
312  else
313  {
314  eps2min = Vmath::Vmin(nq, m_epsvec[1], 1);
315  eps2max = Vmath::Vmax(nq, m_epsvec[1], 1);
316  }
317 
318  mu1min = Vmath::Vmin(nq, m_muvec[0], 1);
319  mu2min = Vmath::Vmin(nq, m_muvec[1], 1);
320  mu3min = Vmath::Vmin(nq, m_muvec[2], 1);
321  mu1max = Vmath::Vmax(nq, m_muvec[0], 1);
322  mu2max = Vmath::Vmax(nq, m_muvec[1], 1);
323  mu3max = Vmath::Vmax(nq, m_muvec[2], 1);
324 
325  std::cout << "muvec0 = " << RootMeanSquare(m_muvec[0])
326  << ", muvec1 = " << RootMeanSquare(m_muvec[1]) << std::endl;
327 
328  std::cout << "*** epsvec1 = [ " << eps1min << " , " << eps1max
329  << " ], epsvec2 = [ " << eps2min << " , " << eps2max
330  << " ], epsvec3 = [ " << eps3min << " , " << eps3max << " ] "
331  << std::endl;
332  std::cout << "*** muvec1 = [ " << mu1min << " , " << mu1max
333  << " ], muvec2 = [ " << mu2min << " , " << mu2max
334  << " ], muvec3 = [ " << mu3min << " , " << mu3max << " ] "
335  << std::endl;
336 
337  NekDouble dtFactor;
338  switch (m_PolType)
339  {
340  // eTransMagnetic
342  {
343  dtFactor = mu1min * eps3min;
344  if (mu1min > mu2min)
345  {
346  dtFactor = mu2min * eps3min;
347  }
348  }
349  break;
350 
352  {
353  dtFactor = eps1min * mu3min;
354  if (eps1min > eps2min)
355  {
356  dtFactor = eps2min * mu3min;
357  }
358  }
359  break;
360 
361  default:
362  {
363  dtFactor = 1.0;
364  }
365  break;
366  }
367  std::cout << "*** dt factor proportional to varepsilon * mu is " << dtFactor
368  << std::endl;
369 
370  // Compute m_Zim and m_Yim
372 
373  // Compute m_epsvecminus1 and m_muminus1
376  for (int k = 0; k < m_spacedim; ++k)
377  {
380 
381  if (!m_NoInc)
382  {
383  Vmath::Sadd(nq, -1.0, m_muvec[k], 1, m_negmuvecminus1[k], 1);
384  Vmath::Sadd(nq, -1.0, m_epsvec[k], 1, m_negepsvecminus1[k], 1);
385 
386  Vmath::Neg(nq, m_negmuvecminus1[k], 1);
387  Vmath::Neg(nq, m_negepsvecminus1[k], 1);
388  }
389  }
390 
391  eps1min = Vmath::Vmin(nq, m_negepsvecminus1[0], 1);
392  eps2min = Vmath::Vmin(nq, m_negepsvecminus1[1], 1);
393  eps3min = Vmath::Vmin(nq, m_negepsvecminus1[2], 1);
394  eps1max = Vmath::Vmax(nq, m_negepsvecminus1[0], 1);
395  eps2max = Vmath::Vmax(nq, m_negepsvecminus1[1], 1);
396  eps3max = Vmath::Vmax(nq, m_negepsvecminus1[2], 1);
397 
398  mu1min = Vmath::Vmin(nq, m_negmuvecminus1[0], 1);
399  mu2min = Vmath::Vmin(nq, m_negmuvecminus1[1], 1);
400  mu3min = Vmath::Vmin(nq, m_negmuvecminus1[2], 1);
401  mu1max = Vmath::Vmax(nq, m_negmuvecminus1[0], 1);
402  mu2max = Vmath::Vmax(nq, m_negmuvecminus1[1], 1);
403  mu3max = Vmath::Vmax(nq, m_negmuvecminus1[2], 1);
404 
405  std::cout << "*** negepsvecminus1 = [ " << eps1min << " , " << eps1max
406  << " ], negepsvecminus1 = [ " << eps2min << " , " << eps2max
407  << " ], negepsvecminus1 = [ " << eps3min << " , " << eps3max
408  << " ] " << std::endl;
409  std::cout << "*** negmuvecminus1 = [ " << mu1min << " , " << mu1max
410  << " ], negmuvecminus1 = [ " << mu2min << " , " << mu2max
411  << " ], negmuvecminus1 = [ " << mu3min << " , " << mu3max << " ] "
412  << std::endl;
413 
414  // Compute de^m/dt \cdot e^k
415  if (m_AddRotation)
416  {
419 
421  }
422 
423  // Generate Sigma Block with thicknes of m_PMLthickness and m_PMLmax
424  if (m_AddPML > 0)
425  {
427  }
428 
429  // If explicit it computes RHS and PROJECTION for the time integration
431  {
434  }
435  // Otherwise it gives an error (no implicit integration)
436  else
437  {
438  ASSERTL0(false, "Implicit unsteady Advection not set up.");
439  }
440 }
441 
442 /**
443  * @brief Unsteady linear advection equation destructor.
444  */
446 {
447 }
448 
450 {
451  ASSERTL0(m_intScheme != 0, "No time integration scheme.");
452 
453  int i, nchk = 1;
454  int nq = GetTotPoints();
455  int nvariables = 0;
456  int nfields = m_fields.size();
457 
458  if (m_intVariables.empty())
459  {
460  for (i = 0; i < nfields; ++i)
461  {
462  m_intVariables.push_back(i);
463  }
464  nvariables = nfields;
465  }
466  else
467  {
468  nvariables = m_intVariables.size();
469  }
470 
471  // Set up wrapper to fields data storage.
472  Array<OneD, Array<OneD, NekDouble>> fields(nvariables);
473  Array<OneD, Array<OneD, NekDouble>> tmp(nvariables);
474 
475  // Order storage to list time-integrated fields first.
476  for (i = 0; i < nvariables; ++i)
477  {
478  fields[i] = m_fields[m_intVariables[i]]->GetPhys();
479  m_fields[m_intVariables[i]]->SetPhysState(false);
480  }
481 
482  // Initialise time integration scheme
483  m_intScheme->InitializeScheme(m_timestep, fields, m_time, m_ode);
484 
485  // Check uniqueness of checkpoint output
486  ASSERTL0((m_checktime == 0.0 && m_checksteps == 0) ||
487  (m_checktime > 0.0 && m_checksteps == 0) ||
488  (m_checktime == 0.0 && m_checksteps > 0),
489  "Only one of IO_CheckTime and IO_CheckSteps "
490  "should be set!");
491 
492  int Ntot = m_steps / m_checksteps + 1;
493 
494  Array<OneD, NekDouble> TimeSeries(Ntot);
495  Array<OneD, NekDouble> Energy(Ntot);
496 
497  LibUtilities::Timer timer;
498  bool doCheckTime = false;
499  int step = 0;
500  NekDouble intTime = 0.0;
501  NekDouble cpuTime = 0.0;
502  NekDouble elapsed = 0.0;
503 
504  int cntap = 0;
505  Array<OneD, NekDouble> Ezantipod;
506  int indxantipod = 0;
507 
508  switch (m_SourceType)
509  {
510  case ePointSource:
511  {
513 
517 
518  m_fields[0]->GetCoords(x, y, z);
519 
520  NekDouble Tol = 0.000001;
521  NekDouble rad;
522  for (i = 0; i < nq; ++i)
523  {
524  rad = sqrt((x[i] + m_Psx) * (x[i] + m_Psx) +
525  (y[i] + m_Psy) * (y[i] + m_Psy) +
526  (z[i] + m_Psz) * (z[i] + m_Psz));
527  std::cout << "rad" << rad << std::endl;
528  if (rad < Tol)
529  {
530  indxantipod = i;
531  break;
532  }
533  }
534  }
535  break;
536 
537  case ePlanarSource:
538  {
540 
544 
545  m_fields[0]->GetCoords(x, y, z);
546 
547  NekDouble Tol = 0.000001;
548  NekDouble rad;
549  for (i = 0; i < nq; ++i)
550  {
551  rad = sqrt((x[i] - m_Psx) * (x[i] - m_Psx));
552  if (rad < Tol)
553  {
554  m_SourceVector[i] = 1.0;
555  }
556  }
557 
558  std::cout << "*** Area of Planar Source = "
559  << m_fields[0]->Integral(m_SourceVector) << std::endl;
560  }
561  break;
562 
563  default:
564  break;
565  }
566 
567  int cntpml = 0;
568  int P1indx = 0, P2indx = 0, P3indx = 0;
572  if (m_TestPML)
573  {
577 
581 
582  m_fields[0]->GetCoords(x, y, z);
583 
584  NekDouble Tol = 0.000001;
585  NekDouble rad;
586  for (int i = 0; i < nq; ++i)
587  {
588  rad = sqrt((x[i] + 3.0) * (x[i] + 3.0) + (y[i]) * (y[i]));
589 
590  if (rad < Tol)
591  {
592  P1indx = i;
593  break;
594  }
595  }
596 
597  for (int i = 0; i < nq; ++i)
598  {
599  rad =
600  sqrt((x[i] + 3.0) * (x[i] + 3.0) + (y[i] - 1.5) * (y[i] - 1.5));
601  if (rad < Tol)
602  {
603  P2indx = i;
604  break;
605  }
606  }
607 
608  for (int i = 0; i < nq; ++i)
609  {
610  rad =
611  sqrt((x[i] + 3.0) * (x[i] + 3.0) + (y[i] - 3.0) * (y[i] - 3.0));
612  if (rad < Tol)
613  {
614  P3indx = i;
615  break;
616  }
617  }
618  }
619 
620  int indx;
621  while (step < m_steps || m_time < m_fintime - NekConstants::kNekZeroTol)
622  {
623 
624  timer.Start();
625  fields = m_intScheme->TimeIntegrate(step, m_timestep, m_ode);
626  timer.Stop();
627 
628  m_time += m_timestep;
629  elapsed = timer.TimePerTest(1);
630  intTime += elapsed;
631  cpuTime += elapsed;
632 
633  // Write out status information
634  if (m_session->GetComm()->GetRank() == 0 && !((step + 1) % m_infosteps))
635  {
636  std::cout << "Steps: " << std::setw(8) << std::left << step + 1 << " "
637  << "Time: " << std::setw(12) << std::left << m_time;
638 
639  std::stringstream ss;
640  ss << cpuTime / 60.0 << " min.";
641  std::cout << " CPU Time: " << std::setw(8) << std::left << ss.str()
642  << std::endl;
643 
644  cpuTime = 0.0;
645  }
646 
647  switch (m_SourceType)
648  {
649  case ePointSource:
650  {
651  if (m_time <= m_PSduration)
652  {
653  Array<OneD, NekDouble> Impulse(nq);
654  Impulse = GaussianPulse(m_time, m_Psx, m_Psy, m_Psz,
656  Vmath::Vadd(nq, &Impulse[0], 1,
657  &fields[m_intVariables[2]][0], 1,
658  &fields[m_intVariables[2]][0], 1);
659  }
660  }
661  break;
662 
663  case ePlanarSource:
664  {
665  Array<OneD, NekDouble> Impulse(nq);
666  for (int i = 0; i < 3; ++i)
667  {
668  Impulse = GetIncidentField(i, m_time);
669  Vmath::Vmul(nq, m_SourceVector, 1, Impulse, 1, Impulse, 1);
670  Vmath::Vadd(nq, &Impulse[0], 1,
671  &fields[m_intVariables[i]][0], 1,
672  &fields[m_intVariables[i]][0], 1);
673  }
674  }
675  break;
676 
677  default:
678  break;
679  }
680 
681  // Transform data into coefficient space
682  for (i = 0; i < nvariables; ++i)
683  {
684  m_fields[m_intVariables[i]]->SetPhys(fields[i]);
685  m_fields[m_intVariables[i]]->FwdTrans_IterPerExp(
686  fields[i], m_fields[m_intVariables[i]]->UpdateCoeffs());
687  m_fields[m_intVariables[i]]->SetPhysState(false);
688  }
689  // for (i = 0; i < nq; ++i)
690  // std::cout << m_fields[0][0][i] <<std::endl;
691 
692  // Write out checkpoint files
693  if ((m_checksteps && step && !((step + 1) % m_checksteps)) ||
694  doCheckTime)
695  {
696  indx = (step + 1) / m_checksteps;
697  TimeSeries[indx] = m_time;
698 
700  {
701  Checkpoint_TotalFieldOutput(nchk, m_time, fields);
702  Checkpoint_TotPlotOutput(nchk, m_time, fields);
703  }
704  Checkpoint_PlotOutput(nchk, fields);
705  Checkpoint_EDFluxOutput(nchk, m_time, fields);
706  Checkpoint_EnergyOutput(nchk, m_time, fields);
707  Checkpoint_Output(nchk++);
708 
709  Energy[indx] = ComputeEnergyDensity(fields);
710 
711  std::cout << "|EHr|: F1 = " << RootMeanSquare(fields[0])
712  << ", F2 = " << RootMeanSquare(fields[1])
713  << ", F3 = " << RootMeanSquare(fields[2])
714  << ", Energy = " << Energy[indx] << std::endl;
715  if (nfields > 3)
716  {
717  std::cout << "|DBr|: D1 = " << RootMeanSquare(fields[3])
718  << ", D2 = " << RootMeanSquare(fields[4])
719  << ", D3 = " << RootMeanSquare(fields[5]) << std::endl;
720 
721  int nTraceNumPoints = GetTraceNpoints();
722  int totbdryexp =
723  m_fields[0]->GetBndCondExpansions()[0]->GetExpSize();
724  int npts = m_fields[0]
725  ->GetBndCondExpansions()[0]
726  ->GetExp(0)
727  ->GetNumPoints(0);
728 
729  Array<OneD, NekDouble> x0(nq);
730  Array<OneD, NekDouble> x1(nq);
731  Array<OneD, NekDouble> x2(nq);
732 
733  m_fields[0]->GetCoords(x0, x1, x2);
734 
735  Array<OneD, NekDouble> E1Fwd(nTraceNumPoints);
736  Array<OneD, NekDouble> E2Fwd(nTraceNumPoints);
737  Array<OneD, NekDouble> H3Fwd(nTraceNumPoints);
738 
739  m_fields[0]->ExtractTracePhys(fields[0], E1Fwd);
740  m_fields[0]->ExtractTracePhys(fields[1], E2Fwd);
741  m_fields[0]->ExtractTracePhys(fields[2], H3Fwd);
742 
743  int id2, cnt = 0;
744  NekDouble E1atPECloc, E1atPEC = 0.0;
745  NekDouble E2atPECloc, E2atPEC = 0.0;
746  NekDouble H3atPECloc, H3atPEC = 0.0;
747 
748  Array<OneD, NekDouble> E1Fwdloc(npts);
749  Array<OneD, NekDouble> E2Fwdloc(npts);
750  Array<OneD, NekDouble> H3Fwdloc(npts);
751 
752  for (int e = 0; e < totbdryexp; ++e)
753  {
754  id2 = m_fields[0]->GetTrace()->GetPhys_Offset(
755  m_fields[0]
756  ->GetTraceMap()
757  ->GetBndCondIDToGlobalTraceID(cnt + e));
758 
759  Vmath::Vcopy(npts, &E1Fwd[id2], 1, &E1Fwdloc[0], 1);
760  Vmath::Vcopy(npts, &E2Fwd[id2], 1, &E2Fwdloc[0], 1);
761  Vmath::Vcopy(npts, &H3Fwd[id2], 1, &H3Fwdloc[0], 1);
762 
763  E1atPECloc = Vmath::Vamax(npts, E1Fwdloc, 1);
764  E2atPECloc = Vmath::Vamax(npts, E2Fwdloc, 1);
765  H3atPECloc = Vmath::Vamax(npts, H3Fwdloc, 1);
766 
767  if (E1atPEC < E1atPECloc)
768  {
769  E1atPEC = E1atPECloc;
770  }
771 
772  if (E2atPEC < E2atPECloc)
773  {
774  E2atPEC = E2atPECloc;
775  }
776 
777  if (H3atPEC < H3atPECloc)
778  {
779  H3atPEC = H3atPECloc;
780  }
781  }
782 
783  std::cout << "At PEC, Max. E1 = " << E1atPEC
784  << ", E2 = " << E2atPEC << ", H3 = " << H3atPEC
785  << std::endl;
786  }
787 
788  if (m_SourceType == ePointSource)
789  {
790  Ezantipod[cntap++] = fields[2][indxantipod];
791  }
792 
793  if (m_TestPML)
794  {
795  P1[cntpml] = fields[2][P1indx];
796  P2[cntpml] = fields[2][P2indx];
797  P3[cntpml] = fields[2][P3indx];
798  cntpml++;
799  }
800  doCheckTime = false;
801  }
802 
803  // Step advance
804  ++step;
805  }
806 
807  // Print out summary statistics
808  if (m_session->GetComm()->GetRank() == 0)
809  {
810  std::cout << "Time-integration : " << intTime << "s" << std::endl;
811 
812  std::cout << "TimeSeries = " << std::endl;
813  for (int i = 0; i < m_steps / m_checksteps; ++i)
814  {
815  std::cout << TimeSeries[i] << ", ";
816  }
817  std::cout << std::endl << std::endl;
818 
819  std::cout << "Energy Density = " << std::endl;
820  for (int i = 0; i < m_steps / m_checksteps; ++i)
821  {
822  std::cout << Energy[i] << ", ";
823  }
824  std::cout << std::endl << std::endl;
825 
827  {
829  }
830 
831  if (m_SourceType == ePointSource)
832  {
833  std::cout << "Ez at antipod = " << std::endl;
834  for (int i = 0; i < m_steps / m_checksteps; ++i)
835  {
836  std::cout << Ezantipod[i] << ", ";
837  }
838  std::cout << std::endl << std::endl;
839  }
840 
841  if (m_TestPML)
842  {
843  std::cout << "P1 = " << std::endl;
844  for (int i = 0; i < m_steps / m_checksteps; ++i)
845  {
846  std::cout << P1[i] << ", ";
847  }
848  std::cout << std::endl << std::endl;
849 
850  std::cout << "P2 = " << std::endl;
851  for (int i = 0; i < m_steps / m_checksteps; ++i)
852  {
853  std::cout << P2[i] << ", ";
854  }
855  std::cout << std::endl << std::endl;
856 
857  std::cout << "P3 = " << std::endl;
858  for (int i = 0; i < m_steps / m_checksteps; ++i)
859  {
860  std::cout << P3[i] << ", ";
861  }
862  std::cout << std::endl << std::endl;
863  }
864  }
865 
866  for (i = 0; i < nvariables; ++i)
867  {
868  m_fields[m_intVariables[i]]->SetPhys(fields[i]);
869  m_fields[m_intVariables[i]]->SetPhysState(true);
870  }
871 
872  for (i = 0; i < nvariables; ++i)
873  {
874  m_fields[i]->FwdTrans(m_fields[i]->GetPhys(),
875  m_fields[i]->UpdateCoeffs());
876  }
877 }
878 
879 /**
880  * @brief Compute the right-hand side for the linear advection equation.
881  *
882  * @param inarray Given fields.
883  * @param outarray Calculated solution.
884  * @param time Time.
885  */
887  const Array<OneD, const Array<OneD, NekDouble>> &inarray,
888  Array<OneD, Array<OneD, NekDouble>> &outarray, const NekDouble time)
889 {
890  int i;
891  int nvar = inarray.size();
892  int ncoeffs = GetNcoeffs();
893  int nq = GetTotPoints();
894 
895  Array<OneD, Array<OneD, NekDouble>> physarray(nvar);
896  Array<OneD, Array<OneD, NekDouble>> modarray(nvar);
897  for (i = 0; i < nvar; ++i)
898  {
899  physarray[i] = Array<OneD, NekDouble>(nq);
900  modarray[i] = Array<OneD, NekDouble>(ncoeffs, 0.0);
901 
902  Vmath::Vcopy(nq, &inarray[i][0], 1, &physarray[i][0], 1);
903  }
904 
905  for (i = 0; i < nvar; i++)
906  {
907  m_fields[i]->SetPhysState(true);
908  }
909 
910  // Compute Curl
911  switch (m_TestMaxwellType)
912  {
915 
916  {
917 
918  // Imaginary part is computed the same as Real part
921 
922  for (int i = 0; i < 3; ++i)
923  {
924  tmpin[i] = Array<OneD, NekDouble>(nq);
925  tmpout[i] = Array<OneD, NekDouble>(ncoeffs, 0.0);
926 
927  Vmath::Vcopy(nq, &physarray[i][0], 1, &tmpin[i][0], 1);
928  }
929 
930  WeakDGMaxwellDirDeriv(tmpin, tmpout, time);
931  AddGreenDerivCompensate(tmpin, tmpout);
932 
933  for (int i = 0; i < 3; ++i)
934  {
935  // For E and H
936  Vmath::Vcopy(ncoeffs, &tmpout[i][0], 1, &modarray[i][0], 1);
937  }
938  }
939  break;
940 
941  default:
942  {
943 
944  WeakDGMaxwellDirDeriv(physarray, modarray, time);
945  AddGreenDerivCompensate(physarray, modarray);
946  }
947  break;
948  }
949 
950  for (i = 0; i < nvar; ++i)
951  {
952  m_fields[i]->MultiplyByElmtInvMass(modarray[i], modarray[i]);
953  m_fields[i]->BwdTrans(modarray[i], outarray[i]);
954  }
955 
957  {
959  for (int j = 0; j < 2; ++j)
960  {
961  F = TestMaxwellSphere(time, m_freq, 3 + j);
962  Vmath::Vadd(nq, &F[0], 1, &outarray[j][0], 1, &outarray[j][0], 1);
963  }
964  }
965 
966  // Add Absorbing Boundary Conditions
967  if (m_AddPML > 0)
968  {
969  AddPML(physarray, outarray);
970  }
971 
972  // Add dedt component
973  if (m_AddRotation)
974  {
975  AddCoriolis(physarray, outarray);
976  AdddedtMaxwell(physarray, outarray);
977  }
978 
979  // Divide it by varepsilon or mu
980  Array<OneD, NekDouble> dFdt(nq, 0.0);
981  switch (m_TestMaxwellType)
982  {
984  {
985  Vmath::Vdiv(nq, outarray[0], 1, m_epsvec[0], 1, outarray[0], 1);
986  Vmath::Vdiv(nq, outarray[1], 1, m_muvec[0], 1, outarray[1], 1);
987  }
988  break;
989 
990  // TO BE CHANGED
992  {
993  Array<OneD, NekDouble> Hxdt(nq, 0.0);
994  Array<OneD, NekDouble> Hydt(nq, 0.0);
995 
996  Hxdt = TestMaxwell2DPEC(time, 10, m_PolType);
997  Hydt = TestMaxwell2DPEC(time, 11, m_PolType);
998 
999  Array<OneD, NekDouble> x0(nq);
1000  Array<OneD, NekDouble> x1(nq);
1001  Array<OneD, NekDouble> x2(nq);
1002 
1003  m_fields[0]->GetCoords(x0, x1, x2);
1004 
1005  NekDouble theta, tmpx, tmpy;
1006  NekDouble uxx, uxy, uyy, detu, uti, uri;
1007  Array<OneD, NekDouble> utvec(nq, 1.0);
1008  Array<OneD, NekDouble> urvec(nq, 1.0);
1009  Array<OneD, NekDouble> tmpIN(nq);
1010 
1011  // Case I: ut = 4.0, ur = 0.5
1012  // NekDouble ut=4.0;
1013  // NekDouble ur=0.5;
1014 
1015  // m_fields[0]->GenerateElementVector(m_ElemtGroup1, ut, 1.0,
1016  // utvec);
1017  // m_fields[0]->GenerateElementVector(m_ElemtGroup1, ur, 1.0,
1018  // urvec);
1019 
1020  // Case II: ut = 0.5, ur = 1 - 2x^2
1021  NekDouble ut = 0.5;
1022  m_fields[0]->GenerateElementVector(m_ElemtGroup1, ut, 1.0, utvec);
1023 
1024  m_fields[0]->GenerateElementVector(m_ElemtGroup1, 1.0, 0.0, tmpIN);
1025 
1026  for (int i = 0; i < nq; i++)
1027  {
1028  urvec[i] =
1029  tmpIN[i] * (1.0 - 2 * x0[i] * x0[i]) + (1.0 - tmpIN[i]);
1030  }
1031 
1032  for (int i = 0; i < nq; ++i)
1033  {
1034  theta = atan2((x1[i] + 2.0), (x0[i] + 2.0));
1035 
1036  uti = utvec[i];
1037  uri = urvec[i];
1038 
1039  uxx = uti * cos(theta) * cos(theta) +
1040  uri * sin(theta) * sin(theta);
1041  uyy = uti * sin(theta) * sin(theta) +
1042  uri * cos(theta) * cos(theta);
1043  uxy = (uti - uri) * cos(theta) * sin(theta);
1044 
1045  detu = uxx * uyy - uxy * uxy;
1046 
1047  tmpx = outarray[0][i] + (1.0 - uxx) * Hxdt[i] - uxy * Hydt[i];
1048  tmpy = outarray[1][i] - uxy * Hxdt[i] + (1.0 - uyy) * Hydt[i];
1049 
1050  outarray[0][i] = (1 / detu) * (uyy * tmpx - uxy * tmpy);
1051  outarray[1][i] = (1 / detu) * (-uxy * tmpx + uxx * tmpy);
1052  }
1053  }
1054  break;
1055 
1059  {
1060  switch (m_PolType)
1061  {
1063  {
1065  {
1066  dFdt = TestMaxwell2DPEC(time, 10, m_PolType);
1067  Vmath::Vvtvp(nq, m_negmuvecminus1[0], 1, dFdt, 1,
1068  outarray[0], 1, outarray[0], 1);
1069 
1070  dFdt = TestMaxwell2DPEC(time, 11, m_PolType);
1071  Vmath::Vvtvp(nq, m_negmuvecminus1[1], 1, dFdt, 1,
1072  outarray[1], 1, outarray[1], 1);
1073 
1074  dFdt = TestMaxwell2DPEC(time, 12, m_PolType);
1075  Vmath::Vvtvp(nq, m_negepsvecminus1[2], 1, dFdt, 1,
1076  outarray[2], 1, outarray[2], 1);
1077  }
1078 
1080  {
1081  dFdt = GetIncidentField(10, time);
1082  Vmath::Vvtvp(nq, m_negmuvecminus1[0], 1, dFdt, 1,
1083  outarray[0], 1, outarray[0], 1);
1084 
1085  dFdt = GetIncidentField(11, time);
1086  Vmath::Vvtvp(nq, m_negmuvecminus1[1], 1, dFdt, 1,
1087  outarray[1], 1, outarray[1], 1);
1088 
1089  dFdt = GetIncidentField(12, time);
1090  Vmath::Vvtvp(nq, m_negepsvecminus1[2], 1, dFdt, 1,
1091  outarray[2], 1, outarray[2], 1);
1092  }
1093 
1094  Vmath::Vdiv(nq, outarray[0], 1, m_muvec[0], 1, outarray[0],
1095  1);
1096  Vmath::Vdiv(nq, outarray[1], 1, m_muvec[1], 1, outarray[1],
1097  1);
1098  Vmath::Vdiv(nq, outarray[2], 1, m_epsvec[2], 1, outarray[2],
1099  1);
1100  }
1101  break;
1102 
1104  {
1106  {
1107  // (I - \mu^i) d F^{inc} / dt
1108  dFdt = TestMaxwell2DPEC(time, 10, m_PolType);
1109  Vmath::Vvtvp(nq, m_negepsvecminus1[0], 1, dFdt, 1,
1110  outarray[0], 1, outarray[0], 1);
1111 
1112  dFdt = TestMaxwell2DPEC(time, 11, m_PolType);
1113  Vmath::Vvtvp(nq, m_negepsvecminus1[1], 1, dFdt, 1,
1114  outarray[1], 1, outarray[1], 1);
1115 
1116  dFdt = TestMaxwell2DPEC(time, 12, m_PolType);
1117  Vmath::Vvtvp(nq, m_negmuvecminus1[2], 1, dFdt, 1,
1118  outarray[2], 1, outarray[2], 1);
1119  }
1120 
1122  {
1123  dFdt = GetIncidentField(10, time);
1124  Vmath::Vvtvp(nq, m_negepsvecminus1[0], 1, dFdt, 1,
1125  outarray[0], 1, outarray[0], 1);
1126 
1127  // Add - wp^2 \int E_2^{inc}
1128  dFdt = GetIncidentField(21, time);
1129  if (m_DispersiveCloak)
1130  {
1131  Vmath::Vmul(nq, m_wp2, 1, dFdt, 1, dFdt, 1);
1132  Vmath::Vsub(nq, outarray[1], 1, dFdt, 1,
1133  outarray[1], 1);
1134  }
1135 
1136  else
1137  {
1138  Vmath::Vvtvp(nq, m_negepsvecminus1[1], 1, dFdt, 1,
1139  outarray[1], 1, outarray[1], 1);
1140  }
1141 
1142  dFdt = GetIncidentField(12, time);
1143  Vmath::Vvtvp(nq, m_negmuvecminus1[2], 1, dFdt, 1,
1144  outarray[2], 1, outarray[2], 1);
1145  }
1146 
1147  Vmath::Vdiv(nq, outarray[0], 1, m_epsvec[0], 1, outarray[0],
1148  1);
1149  Vmath::Vdiv(nq, outarray[1], 1, m_epsvec[1], 1, outarray[1],
1150  1);
1151  Vmath::Vdiv(nq, outarray[2], 1, m_muvec[2], 1, outarray[2],
1152  1);
1153  }
1154  break;
1155 
1156  default:
1157  break;
1158  }
1159  }
1160  break; // case SolverUtils::eTestMaxwell2DPEC:
1161 
1162  default:
1163  break;
1164 
1165  } // switch(m_TestMaxwellType)
1166 }
1167 
1169  const Array<OneD, const Array<OneD, NekDouble>> &physarray,
1170  Array<OneD, Array<OneD, NekDouble>> &outarray)
1171 {
1172  // routine works for both primitive and conservative formulations
1173  int ncoeffs = outarray[0].size();
1174  int nq = physarray[0].size();
1175 
1176  Array<OneD, NekDouble> tmp(nq);
1177  Array<OneD, NekDouble> tmpc(ncoeffs);
1178 
1180  for (int j = 0; j < m_shapedim; ++j)
1181  {
1182  fluxvector[j] = Array<OneD, NekDouble>(nq);
1183  }
1184 
1185  // m_CurlMF[0][0] = e^3 \cdot (\nabla \times e^1) [ NEW m_CurlMF[0][2] ]
1186  // m_CurlMF[0][1] = 0.0
1187  // m_CurlMF[1][0] = 0.0,
1188  // m_CurlMF[1][1] = e^3 \cdot (\nabla \times e^2) [ NEW m_CurlMF[1][2] ]
1189  // m_CurlMF[2][0] = e^1 \cdot (\nabla \times e^3) [ NEW m_CurlMF[2][0] ]
1190  // m_CurlMF[2][1] = e^2 \cdot (\nabla \times e^3) [ NEW m_CurlMF[2][1] ]
1191 
1192  int var;
1193 
1194  switch (m_TestMaxwellType)
1195  {
1203  {
1204  var = 0;
1205  GetMaxwellFluxVector(var, physarray, fluxvector);
1206  Vmath::Vmul(nq, &fluxvector[0][0], 1, &m_CurlMF[0][2][0], 1,
1207  &tmp[0], 1);
1208  m_fields[var]->IProductWRTBase(tmp, tmpc);
1209  Vmath::Vadd(ncoeffs, tmpc, 1, outarray[var], 1, outarray[var], 1);
1210 
1211  var = 1;
1212  GetMaxwellFluxVector(var, physarray, fluxvector);
1213  Vmath::Vmul(nq, &fluxvector[1][0], 1, &m_CurlMF[1][2][0], 1,
1214  &tmp[0], 1);
1215  Vmath::Neg(nq, tmp, 1);
1216  m_fields[var]->IProductWRTBase(tmp, tmpc);
1217  Vmath::Vadd(ncoeffs, tmpc, 1, outarray[var], 1, outarray[var], 1);
1218 
1219  var = 2;
1220  GetMaxwellFluxVector(var, physarray, fluxvector);
1221  Vmath::Vmul(nq, &fluxvector[0][0], 1, &m_CurlMF[2][0][0], 1,
1222  &tmp[0], 1);
1223  Vmath::Vvtvm(nq, &fluxvector[1][0], 1, &m_CurlMF[2][1][0], 1,
1224  &tmp[0], 1, &tmp[0], 1);
1225  m_fields[var]->IProductWRTBase(tmp, tmpc);
1226  Vmath::Vadd(ncoeffs, tmpc, 1, outarray[var], 1, outarray[var], 1);
1227  }
1228  break;
1229 
1230  default:
1231  break;
1232  }
1233 }
1234 
1235 /**
1236  * @brief Calculate weak DG advection in the form \f$ \langle\phi,
1237  * \hat{F}\cdot n\rangle - (\nabla \phi \cdot F) \f$
1238  *
1239  * @param InField Fields.
1240  * @param OutField Storage for result.
1241  * @param NumericalFluxIncludesNormal Default: true.
1242  * @param InFieldIsPhysSpace Default: false.
1243  * @param nvariables Number of fields.
1244  */
1246  const Array<OneD, const Array<OneD, NekDouble>> &InField,
1247  Array<OneD, Array<OneD, NekDouble>> &OutField, const NekDouble time)
1248 {
1249  int i;
1250  int nq = GetNpoints();
1251  int ncoeffs = GetNcoeffs();
1252  int nTracePointsTot = GetTraceNpoints();
1253  int nvar = 3;
1254 
1256  for (i = 0; i < m_shapedim; ++i)
1257  {
1258  fluxvector[i] = Array<OneD, NekDouble>(nq);
1259  }
1260 
1261  Array<OneD, Array<OneD, NekDouble>> physfield(nvar);
1262  for (i = 0; i < nvar; ++i)
1263  {
1264  physfield[i] = InField[i];
1265  }
1266 
1267  Array<OneD, NekDouble> tmpc(ncoeffs);
1268  for (i = 0; i < nvar; ++i)
1269  {
1270  GetMaxwellFluxVector(i, physfield, fluxvector);
1271 
1272  OutField[i] = Array<OneD, NekDouble>(ncoeffs, 0.0);
1273  for (int j = 0; j < m_shapedim; ++j)
1274  {
1275  // Directional derivation with respect to the j'th moving frame
1276  // tmp_j = ( \nabla \phi, fluxvector[j] \mathbf{e}^j )
1277  m_fields[i]->IProductWRTDirectionalDerivBase(m_CrossProductMF[j],
1278  fluxvector[j], tmpc);
1279  Vmath::Vadd(ncoeffs, &tmpc[0], 1, &OutField[i][0], 1,
1280  &OutField[i][0], 1);
1281  }
1282  }
1283 
1284  // V the numerical flux and add to the modal coeffs
1285  // if the NumericalFlux function does not include the
1286  // normal in the output
1287  Array<OneD, Array<OneD, NekDouble>> numfluxFwd(nvar);
1288  Array<OneD, Array<OneD, NekDouble>> numfluxBwd(nvar);
1289 
1290  for (i = 0; i < nvar; ++i)
1291  {
1292  numfluxFwd[i] = Array<OneD, NekDouble>(nTracePointsTot, 0.0);
1293  numfluxBwd[i] = Array<OneD, NekDouble>(nTracePointsTot, 0.0);
1294  }
1295 
1296  // Evaluate numerical flux in physical space which may in
1297  // general couple all component of vectors
1298  NumericalMaxwellFlux(physfield, numfluxFwd, numfluxBwd, time);
1299 
1300  // Evaulate <\phi, \hat{F}\cdot n> - OutField[i]
1301  for (i = 0; i < nvar; ++i)
1302  {
1303  Vmath::Neg(ncoeffs, OutField[i], 1);
1304  m_fields[i]->AddFwdBwdTraceIntegral(numfluxFwd[i], numfluxBwd[i],
1305  OutField[i]);
1306  m_fields[i]->SetPhysState(false);
1307  }
1308 }
1309 
1310 /**
1311  * @brief Compute the projection for the linear advection equation.
1312  *
1313  * @param inarray Given fields.
1314  * @param outarray Calculated solution.
1315  * @param time Time.
1316  */
1318  const Array<OneD, const Array<OneD, NekDouble>> &inarray,
1319  Array<OneD, Array<OneD, NekDouble>> &outarray, const NekDouble time)
1320 {
1321  boost::ignore_unused(time);
1322 
1323  int var = inarray.size();
1324 
1325  // SetBoundaryConditions(time);
1326 
1327  int nq = GetNpoints();
1328  for (int i = 0; i < var; ++i)
1329  {
1330  Vmath::Vcopy(nq, inarray[i], 1, outarray[i], 1);
1331  }
1332 }
1333 
1335  bool dumpInitialConditions,
1336  const int domain)
1337 {
1338  boost::ignore_unused(domain);
1339 
1340  int nq = GetTotPoints();
1341  int nvar = m_fields.size();
1342 
1343  switch (m_TestMaxwellType)
1344  {
1346  {
1347  m_fields[0]->SetPhys(TestMaxwell1D(initialtime, 0));
1348  m_fields[1]->SetPhys(TestMaxwell1D(initialtime, 1));
1349  }
1350  break;
1351 
1354  {
1355  m_fields[0]->SetPhys(TestMaxwell2DPEC(initialtime, 0, m_PolType));
1356  m_fields[1]->SetPhys(TestMaxwell2DPEC(initialtime, 1, m_PolType));
1357  m_fields[2]->SetPhys(TestMaxwell2DPEC(initialtime, 2, m_PolType));
1358  }
1359  break;
1360 
1362  {
1363  m_fields[0]->SetPhys(TestMaxwell2DPMC(initialtime, 0, m_PolType));
1364  m_fields[1]->SetPhys(TestMaxwell2DPMC(initialtime, 1, m_PolType));
1365  m_fields[2]->SetPhys(TestMaxwell2DPMC(initialtime, 2, m_PolType));
1366  }
1367  break;
1368 
1371  {
1372  Array<OneD, NekDouble> Zeros(nq, 0.0);
1373 
1374  for (int i = 0; i < nvar; i++)
1375  {
1376  m_fields[i]->SetPhys(Zeros);
1377  }
1378  }
1379  break;
1380 
1382  {
1383  m_fields[0]->SetPhys(TestMaxwellSphere(initialtime, m_freq, 0));
1384  m_fields[1]->SetPhys(TestMaxwellSphere(initialtime, m_freq, 1));
1385  m_fields[2]->SetPhys(TestMaxwellSphere(initialtime, m_freq, 2));
1386  }
1387  break;
1388 
1390  {
1391  m_fields[2]->SetPhys(GaussianPulse(initialtime, m_Psx, m_Psy, m_Psz,
1392  m_Gaussianradius));
1393  }
1394  break;
1395 
1396  default:
1397  break;
1398  }
1399 
1400  // forward transform to fill the modal coeffs
1401  for (int i = 0; i < nvar; ++i)
1402  {
1403  m_fields[i]->SetPhysState(true);
1404  m_fields[i]->FwdTrans(m_fields[i]->GetPhys(),
1405  m_fields[i]->UpdateCoeffs());
1406  }
1407 
1408  if (dumpInitialConditions)
1409  {
1410  std::string outname = m_sessionName + "_initial.chk";
1411  WriteFld(outname);
1412 
1413  Array<OneD, Array<OneD, NekDouble>> fields(nvar);
1414  for (int i = 0; i < nvar; ++i)
1415  {
1416  fields[i] = m_fields[i]->GetPhys();
1417  }
1418 
1419  Checkpoint_PlotOutput(0, fields);
1420  }
1421 }
1422 
1423 void MMFMaxwell::v_EvaluateExactSolution(unsigned int field,
1424  Array<OneD, NekDouble> &outfield,
1425  const NekDouble time)
1426 {
1427  int nq = m_fields[0]->GetNpoints();
1428  outfield = Array<OneD, NekDouble>(nq);
1429 
1430  switch (m_TestMaxwellType)
1431  {
1433  {
1434  outfield = TestMaxwell1D(time, field);
1435  }
1436  break;
1437 
1440  {
1441  outfield = TestMaxwell2DPEC(time, field, m_PolType);
1442  }
1443  break;
1444 
1446  {
1447  outfield = TestMaxwell2DPMC(time, field, m_PolType);
1448  }
1449  break;
1450 
1452  {
1453  outfield = TestMaxwellSphere(time, m_freq, field);
1454  }
1455  break;
1456 
1457  default:
1458  {
1459  outfield = Array<OneD, NekDouble>(nq, 0.0);
1460  }
1461  break;
1462  }
1463 }
1464 
1466  unsigned int field)
1467 {
1468  int nq = m_fields[0]->GetNpoints();
1469 
1470  Array<OneD, NekDouble> x0(nq);
1471  Array<OneD, NekDouble> x1(nq);
1472  Array<OneD, NekDouble> x2(nq);
1473 
1474  m_fields[0]->GetCoords(x0, x1, x2);
1475 
1476  Array<OneD, NekDouble> E(nq);
1477  Array<OneD, NekDouble> H(nq);
1478 
1479  // Derive the frequency \omega
1480  NekDouble omega;
1481  NekDouble Tol = 0.000000001;
1482  if (fabs(m_n1 - m_n2) < Tol)
1483  {
1484  omega = m_pi / m_n1;
1485  }
1486 
1487  else
1488  {
1489  omega = 2.0 * m_pi / m_n2;
1490 
1491  NekDouble newomega, F, Fprime;
1492  for (int i = 0; i < 10000; ++i)
1493  {
1494  F = m_n1 * tan(m_n2 * omega) + m_n2 * tan(m_n1 * omega);
1495  Fprime =
1496  m_n1 * m_n2 * (1.0 / cos(m_n2 * omega) / cos(m_n2 * omega) +
1497  1.0 / cos(m_n1 * omega) / cos(m_n1 * omega));
1498 
1499  newomega = omega - F / Fprime;
1500 
1501  if (fabs(newomega - omega) > Tol)
1502  {
1503  omega = newomega;
1504  }
1505 
1506  else
1507  {
1508  break;
1509  }
1510  }
1511  }
1512 
1513  // Generate A^k and B^k
1514  std::complex<double> im = sqrt(std::complex<double>(-1));
1515  std::complex<double> A1, A2, B1, B2;
1516  std::complex<double> Ak, Bk, nk;
1517  std::complex<double> Ec, Hc;
1518 
1519  A1 = m_n2 * cos(m_n2 * omega) / (m_n1 * cos(m_n1 * omega));
1520  A2 = exp(-1.0 * im * omega * (m_n1 + m_n2));
1521  B1 = A1 * exp(-2.0 * im * m_n1 * omega);
1522  B2 = A2 * exp(2.0 * im * m_n2 * omega);
1523 
1524  for (int i = 0; i < nq; ++i)
1525  {
1526  if (x0[i] > 0)
1527  {
1528  Ak = A2;
1529  Bk = B2;
1530  nk = m_n2;
1531  }
1532 
1533  else
1534  {
1535  Ak = A1;
1536  Bk = B1;
1537  nk = m_n1;
1538  }
1539 
1540  Ec = (Ak * exp(im * nk * omega * x0[i]) -
1541  Bk * exp(-im * nk * omega * x0[i])) *
1542  exp(im * omega * time);
1543  Hc = nk * (Ak * exp(im * nk * omega * x0[i]) +
1544  Bk * exp(-im * nk * omega * x0[i])) *
1545  exp(im * omega * time);
1546 
1547  E[i] = Ec.real();
1548  H[i] = Hc.real();
1549  }
1550 
1551  Array<OneD, NekDouble> outfield;
1552  switch (field)
1553  {
1554  case (0):
1555  {
1556  outfield = E;
1557  }
1558  break;
1559 
1560  case (1):
1561  {
1562  outfield = H;
1563  }
1564  break;
1565  }
1566 
1567  return outfield;
1568 }
1569 
1571  const NekDouble time, unsigned int field,
1572  const SolverUtils::PolType Polarization)
1573 {
1574  int nq = m_fields[0]->GetNpoints();
1575 
1576  Array<OneD, NekDouble> x0(nq);
1577  Array<OneD, NekDouble> x1(nq);
1578  Array<OneD, NekDouble> x2(nq);
1579 
1580  m_fields[0]->GetCoords(x0, x1, x2);
1581 
1582  NekDouble freqm = 1.0, freqn = 1.0;
1583  NekDouble omega = m_pi * sqrt(freqm * freqm + freqn * freqn);
1584  NekDouble mpi = freqm * m_pi;
1585  NekDouble npi = freqn * m_pi;
1586 
1587  Array<OneD, NekDouble> F1(nq);
1588  Array<OneD, NekDouble> F2(nq);
1589  Array<OneD, NekDouble> Fz(nq);
1590  Array<OneD, NekDouble> dF1dt(nq);
1591  Array<OneD, NekDouble> dF2dt(nq);
1592  Array<OneD, NekDouble> dFzdt(nq);
1593  NekDouble Fx, Fy, dFxdt, dFydt;
1594 
1595  for (int i = 0; i < nq; ++i)
1596  {
1597  switch (Polarization)
1598  {
1600  {
1601  Fx = -1.0 * (npi / omega) * sin(mpi * x0[i]) *
1602  cos(npi * x1[i]) * sin(omega * time);
1603  Fy = (mpi / omega) * cos(mpi * x0[i]) * sin(npi * x1[i]) *
1604  sin(omega * time);
1605 
1606  F1[i] =
1607  Fx * m_movingframes[0][i] + Fy * m_movingframes[0][i + nq];
1608  F2[i] =
1609  Fx * m_movingframes[1][i] + Fy * m_movingframes[1][i + nq];
1610  Fz[i] = sin(mpi * x0[i]) * sin(npi * x1[i]) * cos(omega * time);
1611 
1612  dFxdt = (npi)*sin(mpi * x0[i]) * cos(npi * x1[i]) *
1613  cos(omega * time);
1614  dFydt = -1.0 * (mpi)*cos(mpi * x0[i]) * sin(npi * x1[i]) *
1615  cos(omega * time);
1616 
1617  dF1dt[i] = dFxdt * m_movingframes[0][i] +
1618  dFydt * m_movingframes[0][i + nq];
1619  dF2dt[i] = dFxdt * m_movingframes[1][i] +
1620  dFydt * m_movingframes[1][i + nq];
1621  dFzdt[i] = omega * sin(mpi * x0[i]) * sin(npi * x1[i]) *
1622  sin(omega * time);
1623  }
1624  break;
1625 
1627  {
1628  Fx = -1.0 * (npi / omega) * cos(mpi * x0[i]) *
1629  sin(npi * x1[i]) * sin(omega * time);
1630  Fy = (mpi / omega) * sin(mpi * x0[i]) * cos(npi * x1[i]) *
1631  sin(omega * time);
1632 
1633  F1[i] =
1634  Fx * m_movingframes[0][i] + Fy * m_movingframes[0][i + nq];
1635  F2[i] =
1636  Fx * m_movingframes[1][i] + Fy * m_movingframes[1][i + nq];
1637  Fz[i] = cos(mpi * x0[i]) * cos(npi * x1[i]) * cos(omega * time);
1638 
1639  dFxdt = (npi)*cos(mpi * x0[i]) * sin(npi * x1[i]) *
1640  cos(omega * time);
1641  dFydt = -1.0 * (mpi)*sin(mpi * x0[i]) * cos(npi * x1[i]) *
1642  cos(omega * time);
1643 
1644  dF1dt[i] = dFxdt * m_movingframes[0][i] +
1645  dFydt * m_movingframes[0][i + nq];
1646  dF2dt[i] = dFxdt * m_movingframes[1][i] +
1647  dFydt * m_movingframes[1][i + nq];
1648  dFzdt[i] = omega * cos(mpi * x0[i]) * cos(npi * x1[i]) *
1649  sin(omega * time);
1650  }
1651  break;
1652 
1653  default:
1654  break;
1655  }
1656  }
1657 
1658  Array<OneD, NekDouble> outfield;
1659  switch (field)
1660  {
1661  case (0):
1662  {
1663  outfield = F1;
1664  }
1665  break;
1666 
1667  case (1):
1668  {
1669  outfield = F2;
1670  }
1671  break;
1672 
1673  case (2):
1674  {
1675  outfield = Fz;
1676  }
1677  break;
1678 
1679  case (10):
1680  {
1681  outfield = dF1dt;
1682  }
1683  break;
1684 
1685  case (11):
1686  {
1687  outfield = dF2dt;
1688  }
1689  break;
1690 
1691  case (12):
1692  {
1693  outfield = dFzdt;
1694  }
1695  break;
1696  }
1697 
1698  return outfield;
1699 }
1700 
1702  const NekDouble time, unsigned int field,
1703  const SolverUtils::PolType Polarization)
1704 {
1705  int nq = m_fields[0]->GetNpoints();
1706 
1707  Array<OneD, NekDouble> x0(nq);
1708  Array<OneD, NekDouble> x1(nq);
1709  Array<OneD, NekDouble> x2(nq);
1710 
1711  m_fields[0]->GetCoords(x0, x1, x2);
1712 
1713  NekDouble freqm = 1.0, freqn = 1.0;
1714  NekDouble omega = m_pi * sqrt(freqm * freqm + freqn * freqn);
1715  NekDouble mpi = freqm * m_pi;
1716  NekDouble npi = freqn * m_pi;
1717 
1718  Array<OneD, NekDouble> F1(nq);
1719  Array<OneD, NekDouble> F2(nq);
1720  Array<OneD, NekDouble> Fz(nq);
1721  NekDouble Fx, Fy;
1722 
1723  for (int i = 0; i < nq; ++i)
1724  {
1725  switch (Polarization)
1726  {
1728  {
1729  Fx = (npi / omega) * cos(mpi * x0[i]) * sin(npi * x1[i]) *
1730  sin(omega * time);
1731  Fy = -(mpi / omega) * sin(mpi * x0[i]) * cos(npi * x1[i]) *
1732  sin(omega * time);
1733 
1734  F1[i] =
1735  Fx * m_movingframes[0][i] + Fy * m_movingframes[0][i + nq];
1736  F2[i] =
1737  Fx * m_movingframes[1][i] + Fy * m_movingframes[1][i + nq];
1738  Fz[i] = cos(mpi * x0[i]) * cos(npi * x1[i]) * cos(omega * time);
1739  }
1740  break;
1741 
1743  {
1744  Fx = (npi / omega) * sin(mpi * x0[i]) * cos(npi * x1[i]) *
1745  sin(omega * time);
1746  Fy = -(mpi / omega) * cos(mpi * x0[i]) * sin(npi * x1[i]) *
1747  sin(omega * time);
1748 
1749  F1[i] =
1750  Fx * m_movingframes[0][i] + Fy * m_movingframes[0][i + nq];
1751  F2[i] =
1752  Fx * m_movingframes[1][i] + Fy * m_movingframes[1][i + nq];
1753  Fz[i] = sin(mpi * x0[i]) * sin(npi * x1[i]) * cos(omega * time);
1754  }
1755  break;
1756 
1757  default:
1758  break;
1759  }
1760  }
1761 
1762  Array<OneD, NekDouble> outfield;
1763  switch (field)
1764  {
1765  case (0):
1766  {
1767  outfield = F1;
1768  }
1769  break;
1770 
1771  case (1):
1772  {
1773  outfield = F2;
1774  }
1775  break;
1776 
1777  case (2):
1778  {
1779  outfield = Fz;
1780  }
1781  break;
1782  }
1783 
1784  return outfield;
1785 }
1786 
1788  const NekDouble omega,
1789  unsigned int field)
1790 {
1791  int nq = m_fields[0]->GetTotPoints();
1792 
1793  Array<OneD, NekDouble> outfield(nq);
1794 
1795  Array<OneD, NekDouble> x(nq);
1796  Array<OneD, NekDouble> y(nq);
1797  Array<OneD, NekDouble> z(nq);
1798 
1799  m_fields[0]->GetCoords(x, y, z);
1800 
1801  Array<OneD, NekDouble> H1(nq);
1802  Array<OneD, NekDouble> H2(nq);
1803  Array<OneD, NekDouble> E3(nq);
1804  Array<OneD, NekDouble> F1(nq);
1805  Array<OneD, NekDouble> F2(nq);
1806 
1807  Array<OneD, NekDouble> curlv(nq);
1810  for (int i = 0; i < m_spacedim; ++i)
1811  {
1812  velvec[i] = Array<OneD, NekDouble>(nq, 0.0);
1813  Fvec[i] = Array<OneD, NekDouble>(nq, 0.0);
1814  }
1815 
1816  NekDouble xj, yj, zj, sin_varphi, cos_varphi, sin_theta, cos_theta;
1817  NekDouble vth, vphi, Fth, Fphi;
1818  for (int i = 0; i < nq; i++)
1819  {
1820  xj = x[i];
1821  yj = y[i];
1822  zj = z[i];
1823 
1824  CartesianToSpherical(xj, yj, zj, sin_varphi, cos_varphi, sin_theta,
1825  cos_theta);
1826 
1827  vth = -4.0 * sin_varphi * cos_varphi * cos_theta * cos_theta *
1828  cos_theta * sin_theta;
1829  vphi =
1830  -1.0 * sin_varphi * sin_varphi * cos_theta * cos_theta * cos_theta;
1831  velvec[0][i] = -vth * sin_theta * cos_varphi - vphi * sin_varphi;
1832  velvec[1][i] = -vth * sin_theta * sin_varphi + vphi * cos_varphi;
1833  velvec[2][i] = vth * cos_theta;
1834 
1835  E3[i] = (-4.0 * cos_theta * cos_theta * sin_theta * cos_varphi *
1836  cos_varphi) *
1837  (1.0 / omega * sin(omega * time));
1838 
1839  Fth = -omega * vth -
1840  (8.0 / omega) * cos_theta * sin_theta * cos_varphi * sin_varphi;
1841  Fphi = -omega * vphi +
1842  (4.0 / omega) * cos_varphi * cos_varphi * cos_theta *
1843  (2.0 * sin_theta * sin_theta - cos_theta * cos_theta);
1844  Fvec[0][i] = -Fth * sin_theta * cos_varphi - Fphi * sin_varphi;
1845  Fvec[1][i] = -Fth * sin_theta * sin_varphi + Fphi * cos_varphi;
1846  Fvec[2][i] = Fth * cos_theta;
1847  }
1848 
1849  H1 = CartesianToMovingframes(velvec, 0);
1850  H2 = CartesianToMovingframes(velvec, 1);
1851 
1852  Vmath::Smul(nq, cos(omega * time), H1, 1, H1, 1);
1853  Vmath::Smul(nq, cos(omega * time), H2, 1, H2, 1);
1854 
1855  F1 = CartesianToMovingframes(Fvec, 0);
1856  F2 = CartesianToMovingframes(Fvec, 1);
1857 
1858  Vmath::Smul(nq, sin(omega * time), F1, 1, F1, 1);
1859  Vmath::Smul(nq, sin(omega * time), F2, 1, F2, 1);
1860 
1861  switch (field)
1862  {
1863  // return H1
1864  case 0:
1865  {
1866  outfield = H1;
1867  }
1868  break;
1869 
1870  case 1:
1871  {
1872  outfield = H2;
1873  }
1874  break;
1875 
1876  case 2:
1877  {
1878  outfield = E3;
1879  }
1880  break;
1881 
1882  case 3:
1883  {
1884  outfield = F1;
1885  }
1886  break;
1887 
1888  case 4:
1889  {
1890  outfield = F2;
1891  }
1892  break;
1893 
1894  default:
1895  break;
1896  }
1897 
1898  return outfield;
1899 }
1900 
1902  Array<OneD, Array<OneD, NekDouble>> &fields, const int time)
1903 {
1904  int nq = m_fields[0]->GetTotPoints();
1905  int nTraceNumPoints = GetTraceTotPoints();
1906 
1907  int totbdryexp =
1908  m_fields[0]->GetBndCondExpansions()[m_boundaryforSF]->GetExpSize();
1909  int npts = m_fields[0]
1910  ->GetBndCondExpansions()[m_boundaryforSF]
1911  ->GetExp(0)
1912  ->GetNumPoints(0);
1913  int totnpts = totbdryexp * npts;
1914 
1915  Array<OneD, NekDouble> Jphi(totnpts);
1916  Array<OneD, NekDouble> Jrad(totnpts);
1917  Array<OneD, NekDouble> Jcurrent(totnpts);
1918 
1919  Array<OneD, NekDouble> phiFwd(nTraceNumPoints);
1920  Array<OneD, NekDouble> radFwd(nTraceNumPoints);
1921 
1922  // Compute phiFwd = acos(-x/r) along the trace
1923  Array<OneD, NekDouble> x(nq);
1924  Array<OneD, NekDouble> y(nq);
1925  Array<OneD, NekDouble> z(nq);
1926 
1927  m_fields[0]->GetCoords(x, y, z);
1928 
1929  Array<OneD, NekDouble> xFwd(nTraceNumPoints);
1930  Array<OneD, NekDouble> yFwd(nTraceNumPoints);
1931 
1932  m_fields[0]->ExtractTracePhys(x, xFwd);
1933  m_fields[0]->ExtractTracePhys(y, yFwd);
1934 
1935  for (int i = 0; i < nTraceNumPoints; ++i)
1936  {
1937  radFwd[i] = sqrt(xFwd[i] * xFwd[i] / m_MMFfactors[0] / m_MMFfactors[0] +
1938  yFwd[i] * yFwd[i] / m_MMFfactors[1] / m_MMFfactors[1]);
1939  phiFwd[i] = atan2(yFwd[i] / radFwd[i], -1.0 * xFwd[i] / radFwd[i]);
1940  }
1941 
1942  Array<OneD, NekDouble> ntimesHFwd(nTraceNumPoints);
1943  ntimesHFwd = ComputeSurfaceCurrent(time, fields);
1944 
1945  // The surface for current should be the first boundary
1946  int id2, cnt = 0;
1947  for (int e = 0; e < totbdryexp; ++e)
1948  {
1949  id2 = m_fields[0]->GetTrace()->GetPhys_Offset(
1950  m_fields[0]->GetTraceMap()->GetBndCondIDToGlobalTraceID(cnt + e));
1951 
1952  Vmath::Vcopy(npts, &phiFwd[id2], 1, &Jphi[e * npts], 1);
1953  Vmath::Vcopy(npts, &radFwd[id2], 1, &Jrad[e * npts], 1);
1954  Vmath::Vcopy(npts, &ntimesHFwd[id2], 1, &Jcurrent[e * npts], 1);
1955  }
1956 
1957  // Vmath::Vmul(totnpts, tmpr, 1, tmpr, 1, Jcurrent, 1);
1958  // Vmath::Vvtvp(totnpts, tmpi, 1, tmpi, 1, Jcurrent, 1, Jcurrent, 1);
1959  // Vmath::Vsqrt(totnpts, Jcurrent, 1, Jcurrent, 1);
1960 
1961  std::cout << "========================================================"
1962  << std::endl;
1963 
1964  std::cout << "phi = " << std::endl;
1965  for (int i = 0; i < totnpts; ++i)
1966  {
1967  std::cout << Jphi[i] << ", ";
1968  }
1969  std::cout << std::endl << std::endl;
1970 
1971  std::cout << "J = " << std::endl;
1972  for (int i = 0; i < totnpts; ++i)
1973  {
1974  std::cout << Jcurrent[i] << ", ";
1975  }
1976  std::cout << std::endl << std::endl;
1977 }
1978 
1980  const int time, const Array<OneD, const Array<OneD, NekDouble>> &fields)
1981 {
1982  int nq = m_fields[0]->GetTotPoints();
1983  int nTraceNumPoints = GetTraceTotPoints();
1984 
1985  Array<OneD, NekDouble> outfield(nTraceNumPoints, 0.0);
1986 
1987  switch (m_PolType)
1988  {
1989  // (n \times H^r)_z = H1r (n \times e^1)_z + H2r (n \times e^2)_z,
1991  {
1992  Array<OneD, NekDouble> tmp(nq);
1993  Array<OneD, NekDouble> tmpFwd(nTraceNumPoints);
1994 
1995  for (int i = 0; i < 2; i++)
1996  {
1997  tmp = GetIncidentField(i, time);
1998  Vmath::Vadd(nq, fields[i], 1, tmp, 1, tmp, 1);
1999 
2000  m_fields[0]->ExtractTracePhys(tmp, tmpFwd);
2001  Vmath::Vvtvp(nTraceNumPoints, &m_ntimesMFFwd[i][2][0], 1,
2002  &tmpFwd[0], 1, &outfield[0], 1, &outfield[0], 1);
2003  }
2004  }
2005  break;
2006 
2008  {
2009  Array<OneD, NekDouble> tmp(nq);
2010 
2011  tmp = GetIncidentField(2, time);
2012  Vmath::Vadd(nq, fields[2], 1, tmp, 1, tmp, 1);
2013  m_fields[0]->ExtractTracePhys(tmp, outfield);
2014  }
2015  break;
2016 
2017  default:
2018  break;
2019  }
2020 
2021  return outfield;
2022 }
2023 
2024 void MMFMaxwell::GenerateSigmaPML(const NekDouble PMLthickness,
2025  const NekDouble PMLstart,
2026  const NekDouble PMLmaxsigma,
2027  Array<OneD, Array<OneD, NekDouble>> &SigmaPML)
2028 {
2029  int nq = m_fields[0]->GetNpoints();
2030 
2031  // Construct sigmaX and sigmaY for UPML
2032  Array<OneD, NekDouble> x(nq);
2033  Array<OneD, NekDouble> y(nq);
2034  Array<OneD, NekDouble> z(nq);
2035 
2036  m_fields[0]->GetCoords(x, y, z);
2037 
2038  // Construction of SigmaPML
2040  for (int j = 0; j < m_shapedim; j++)
2041  {
2042  SigmaPML[j] = Array<OneD, NekDouble>(nq, 0.0);
2043  }
2044 
2045  // PML region indicator: [ 0 : curvedPML : RecPML]
2046  // RecPML = [0 : 0 : 1]
2047  // PMLRegion = [0 : 1 : 1], CurvedPML = PMLRegion - RecPML = [0: 1: 0]
2048  Array<OneD, NekDouble> RecPML(nq);
2049  Array<OneD, NekDouble> CurvedPML(nq);
2050  Array<OneD, NekDouble> PMLRegion(nq);
2051  m_fields[0]->GenerateElementVector(m_RecPML, 0.0, 1.0, RecPML);
2052  m_fields[0]->GenerateElementVector(m_PMLelement, 0.0, 1.0, PMLRegion);
2053  Vmath::Vsub(nq, PMLRegion, 1, RecPML, 1, CurvedPML, 1);
2054 
2055  switch (m_AddPML)
2056  {
2057  // RecPML only
2058  case 1:
2059  {
2060  // Rectangular PML
2061  NekDouble xRlayer, xLlayer, yRlayer, yLlayer;
2062 
2063  xRlayer = Vmath::Vmax(nq, x, 1) - PMLthickness;
2064  xLlayer = Vmath::Vmin(nq, x, 1) + PMLthickness;
2065  yRlayer = Vmath::Vmax(nq, y, 1) - PMLthickness;
2066  yLlayer = Vmath::Vmin(nq, y, 1) + PMLthickness;
2067 
2068  NekDouble xd, yd;
2069  for (int i = 0; i < nq; i++)
2070  {
2071  // SimgaPML along e^1
2072  if (x[i] >= xRlayer)
2073  {
2074  xd = (x[i] - xRlayer) / PMLthickness;
2075  }
2076 
2077  else if (x[i] <= xLlayer)
2078  {
2079  xd = (xLlayer - x[i]) / PMLthickness;
2080  }
2081 
2082  else
2083  {
2084  xd = 0.0;
2085  }
2086 
2087  SigmaPML[0][i] = RecPML[i] * PMLmaxsigma * (xd * xd * xd);
2088 
2089  // SigmaPML along e^2
2090  if (y[i] >= yRlayer)
2091  {
2092  yd = (y[i] - yRlayer) / PMLthickness;
2093  }
2094 
2095  else if (y[i] <= yLlayer)
2096  {
2097  yd = (yLlayer - y[i]) / PMLthickness;
2098  }
2099 
2100  else
2101  {
2102  yd = 0.0;
2103  }
2104 
2105  SigmaPML[1][i] = PMLRegion[i] * PMLmaxsigma * (yd * yd * yd);
2106  }
2107  }
2108  break;
2109 
2110  // CurvedPML only
2111  case 2:
2112  {
2113  // Curved PML
2114  NekDouble relrad, rad;
2115  for (int i = 0; i < nq; i++)
2116  {
2117  rad = sqrt(x[i] * x[i] / m_MMFfactors[0] / m_MMFfactors[0] +
2118  y[i] * y[i] / m_MMFfactors[1] / m_MMFfactors[1]);
2119 
2120  if (rad >= PMLstart)
2121  {
2122  relrad = (rad - PMLstart) / PMLthickness;
2123  SigmaPML[1][i] =
2124  PMLRegion[i] * PMLmaxsigma * pow(relrad, m_PMLorder);
2125  }
2126  }
2127  }
2128  break;
2129 
2130  // Slanted PML
2131  case 3:
2132  {
2133  NekDouble relrad, radon, radtw, radth, radfo;
2134  for (int i = 0; i < nq; i++)
2135  {
2136  radon = -1.0 * x[i] + y[i] - 7;
2137  radtw = x[i] + y[i] - 7;
2138  radth = -x[i] - y[i] - 7;
2139  radfo = x[i] - y[i] - 7;
2140 
2141  if (radon >= 0.0)
2142  {
2143  relrad = radon / PMLthickness;
2144  SigmaPML[1][i] =
2145  PMLRegion[i] * PMLmaxsigma * pow(relrad, m_PMLorder);
2146  }
2147 
2148  if (radtw >= 0.0)
2149  {
2150  relrad = radtw / PMLthickness;
2151  SigmaPML[0][i] =
2152  PMLRegion[i] * PMLmaxsigma * pow(relrad, m_PMLorder);
2153  }
2154 
2155  if (radth >= 0.0)
2156  {
2157  relrad = radth / PMLthickness;
2158  SigmaPML[0][i] =
2159  PMLRegion[i] * PMLmaxsigma * pow(relrad, m_PMLorder);
2160  }
2161 
2162  if (radfo >= 0.0)
2163  {
2164  relrad = radfo / PMLthickness;
2165  SigmaPML[1][i] =
2166  PMLRegion[i] * PMLmaxsigma * pow(relrad, m_PMLorder);
2167  }
2168  }
2169  }
2170  break;
2171  }
2172 
2173  std::cout << "*** sigma1 = [ " << Vmath::Vmin(nq, &SigmaPML[0][0], 1)
2174  << " , " << Vmath::Vmax(nq, &SigmaPML[0][0], 1)
2175  << " ] , sigma2 = [ " << Vmath::Vmin(nq, &SigmaPML[1][0], 1)
2176  << " , " << Vmath::Vmax(nq, &SigmaPML[1][0], 1) << " ] "
2177  << std::endl;
2178 }
2179 
2181  Array<OneD, Array<OneD, NekDouble>> &fields)
2182 {
2183  int nq = GetTotPoints();
2184  NekDouble energy;
2185 
2186  Array<OneD, NekDouble> tmp(nq, 0.0);
2187 
2188  for (int i = 0; i < 3; ++i)
2189  {
2190  Vmath::Vvtvp(nq, &fields[i][0], 1, &fields[i][0], 1, &tmp[0], 1,
2191  &tmp[0], 1);
2192  }
2193 
2194  energy = 0.5 * (m_fields[0]->Integral(tmp));
2195  return energy;
2196 }
2197 
2199  Array<OneD, Array<OneD, NekDouble>> &epsvec,
2201 {
2202  switch (m_TestMaxwellType)
2203  {
2205  {
2206  m_fields[0]->GenerateElementVector(m_ElemtGroup1, m_varepsilon[0],
2207  m_varepsilon[1], epsvec[0]);
2208  m_fields[0]->GenerateElementVector(m_ElemtGroup1, 1.0, 1.0,
2209  muvec[0]);
2210  }
2211  break;
2212 
2218  {
2219  switch (m_PolType)
2220  {
2222  {
2223  m_fields[0]->GenerateElementVector(m_ElemtGroup1, m_mu[0],
2224  1.0, muvec[0]);
2225  m_fields[0]->GenerateElementVector(m_ElemtGroup1, m_mu[1],
2226  1.0, muvec[1]);
2227  m_fields[0]->GenerateElementVector(
2228  m_ElemtGroup1, m_varepsilon[2], 1.0, epsvec[2]);
2229 
2230  // // ONLY FOR VARIABLE ANISOTROPY TEST
2231  // int nq = GetTotPoints();
2232 
2233  // Array<OneD, NekDouble> tmpIN(nq);
2234 
2235  // m_fields[0]->GenerateElementVector(m_ElemtGroup1, 1.0,
2236  // 0.0, tmpIN);
2237 
2238  // Array<OneD, NekDouble> x0(nq);
2239  // Array<OneD, NekDouble> x1(nq);
2240  // Array<OneD, NekDouble> x2(nq);
2241 
2242  // m_fields[0]->GetCoords(x0,x1,x2);
2243 
2244  // for (int i=0; i<nq; i++)
2245  // {
2246  // muvec[1][i] = tmpIN[i]*(1.0 - 2*x0[i]*x0[i]) +
2247  // (1.0-tmpIN[i]);
2248  // }
2249  }
2250  break;
2251 
2253  {
2254  m_fields[0]->GenerateElementVector(
2255  m_ElemtGroup1, m_varepsilon[0], 1.0, epsvec[0]);
2256  m_fields[0]->GenerateElementVector(
2257  m_ElemtGroup1, m_varepsilon[1], 1.0, epsvec[1]);
2258  m_fields[0]->GenerateElementVector(m_ElemtGroup1, m_mu[2],
2259  1.0, muvec[2]);
2260 
2261  // // ONLY FOR VARIABLE ANISOTROPY TEST
2262  // int nq = GetTotPoints();
2263 
2264  // Array<OneD, NekDouble> tmpIN(nq);
2265 
2266  // m_fields[0]->GenerateElementVector(m_ElemtGroup1, 1.0,
2267  // 0.0, tmpIN);
2268 
2269  // Array<OneD, NekDouble> x0(nq);
2270  // Array<OneD, NekDouble> x1(nq);
2271  // Array<OneD, NekDouble> x2(nq);
2272 
2273  // m_fields[0]->GetCoords(x0,x1,x2);
2274 
2275  // for (int i=0; i<nq; i++)
2276  // {
2277  // epsvec[1][i] = tmpIN[i]*(1.0 - 2*x0[i]*x0[i]) +
2278  // (1.0-tmpIN[i]);
2279  // }
2280  }
2281  break;
2282 
2283  default:
2284  break; // Pol
2285  }
2286  }
2287 
2288  default:
2289  break; // TestType
2290  }
2291 }
2292 
2294  const Array<OneD, const NekDouble> &radvec,
2295  Array<OneD, Array<OneD, NekDouble>> &epsvec,
2296  Array<OneD, Array<OneD, NekDouble>> &muvec, const bool Dispersion)
2297 {
2298  boost::ignore_unused(muvec, Dispersion);
2299 
2300  int nq = GetNpoints();
2301 
2302  // Cloaking metamaterial
2303  // \varepsilon_\theta = (b/(b-a))^2
2304  // \varepsilon_r = (b/(b-a))^2 ((r-a)/r)^2
2305  // \mu_z = 1.0m_CloakingOn
2306 
2307  NekDouble m_b = 1.0 / 0.314;
2308  NekDouble m_a = 1.0;
2309 
2310  NekDouble m_adel = m_a - m_Cloakraddelta;
2311 
2312  NekDouble boveradel = m_b / (m_b - m_adel);
2313 
2314  Array<OneD, NekDouble> Cloakregion(nq, 0.0);
2315 
2316  NekDouble la = m_MMFfactors[0];
2317  NekDouble lb = m_MMFfactors[1];
2318 
2319  NekDouble ExactCloakArea;
2320  if (fabs(la * lb - 1.0) < 0.00001)
2321  {
2322  ExactCloakArea = m_pi * (m_b * m_b - m_a * m_a);
2323  }
2324 
2325  else
2326  {
2327  ExactCloakArea = m_pi * (3.0 * lb * 3.0 * la - lb * la);
2328  }
2329 
2330  m_fields[0]->GenerateElementVector(m_ElemtGroup1, 1.0, 0.0, Cloakregion);
2331 
2332  ExactCloakArea = ExactCloakArea - (m_fields[0]->Integral(Cloakregion));
2333  std::cout << "*** Error of Cloakregion area = " << ExactCloakArea
2334  << std::endl;
2335 
2336  NekDouble ratio;
2337 
2338  epsvec[0] = Array<OneD, NekDouble>(nq, 1.0);
2339  epsvec[1] = Array<OneD, NekDouble>(nq, 1.0);
2340  m_wp2 = Array<OneD, NekDouble>(nq, 0.0);
2341  for (int i = 0; i < nq; ++i)
2342  {
2343  if (Cloakregion[i] > 0)
2344  {
2345  // relrad = m_a +
2346  // (m_b-m_adel)*(radvec[i]-m_adel)/(Cloakradmax-m_adel);
2347  ratio = (radvec[i] - m_adel) / radvec[i];
2348 
2349  epsvec[0][i] = boveradel * boveradel;
2350  if (m_DispersiveCloak)
2351  {
2352  epsvec[1][i] = 1.0;
2353  m_wp2[i] = m_Incfreq * m_Incfreq *
2354  (1.0 - boveradel * boveradel * ratio * ratio) +
2355  m_wp2Tol;
2356  }
2357 
2358  else
2359  {
2360  epsvec[1][i] = boveradel * boveradel * (ratio * ratio);
2361  }
2362  }
2363  }
2364 }
2365 
2367  const Array<OneD, const NekDouble> &radvec,
2368  Array<OneD, Array<OneD, NekDouble>> &epsvec,
2370 {
2371  int nq = GetNpoints();
2372 
2373  NekDouble m_b = 2.67;
2374  NekDouble m_a = 1.33;
2375  NekDouble m_adel;
2376 
2377  m_adel = m_a - m_Cloakraddelta;
2378 
2379  Array<OneD, NekDouble> Cloakregion(nq, 0.0);
2380  NekDouble ExactCloakArea = m_pi * (m_b * m_b - m_a * m_a);
2381  m_fields[0]->GenerateElementVector(m_ElemtGroup1, 1.0, 0.0, Cloakregion);
2382 
2383  if (m_ElemtGroup0 > 0)
2384  {
2385  Array<OneD, NekDouble> Vacregion(nq, 0.0);
2386  m_fields[0]->GenerateElementVector(m_ElemtGroup0, 1.0, 0.0, Vacregion);
2387 
2388  Vmath::Vsub(nq, Cloakregion, 1, Vacregion, 1, Cloakregion, 1);
2389  }
2390 
2391  ExactCloakArea = ExactCloakArea - (m_fields[0]->Integral(Cloakregion));
2392  std::cout << "*** Error of Cloakregion area = " << ExactCloakArea
2393  << std::endl;
2394 
2395  epsvec[0] = Array<OneD, NekDouble>(nq, 1.0);
2396  epsvec[1] = Array<OneD, NekDouble>(nq, 1.0);
2397 
2398  muvec[0] = Array<OneD, NekDouble>(nq, 1.0);
2399  muvec[1] = Array<OneD, NekDouble>(nq, 1.0);
2400  for (int i = 0; i < nq; ++i)
2401  {
2402  if (Cloakregion[i] > 0)
2403  {
2404  // relrad = m_a +
2405  // (m_b-m_a)*(radvec[i]-Cloakradmin)/(Cloakradmax-Cloakradmin);
2406  // ratio = (relrad - m_a + m_Cloakraddelta)/relrad;
2407 
2408  epsvec[0][i] = radvec[i] / (radvec[i] - m_adel);
2409  epsvec[1][i] = (radvec[i] - m_adel) / radvec[i];
2410  muvec[2][i] = (m_b / (m_b - m_adel)) * (m_b / (m_b - m_adel)) *
2411  (radvec[i] - m_adel) / radvec[i];
2412 
2413  muvec[0][i] = epsvec[0][i];
2414  muvec[1][i] = epsvec[1][i];
2415  epsvec[2][i] = muvec[2][i];
2416  }
2417  }
2418 }
2419 
2421  const Array<OneD, const Array<OneD, NekDouble>> &physarray,
2422  Array<OneD, Array<OneD, NekDouble>> &outarray)
2423 {
2424  int nq = m_fields[0]->GetTotPoints();
2425  Array<OneD, NekDouble> tmp(nq);
2426 
2427  Array<OneD, NekDouble> Sigma0plus1Neg(nq);
2428  Array<OneD, NekDouble> Sigma0minus1(nq);
2429  Array<OneD, NekDouble> Sigma1minus0(nq);
2430 
2431  Vmath::Vsub(nq, &m_SigmaPML[1][0], 1, &m_SigmaPML[0][0], 1,
2432  &Sigma1minus0[0], 1);
2433  Vmath::Vsub(nq, &m_SigmaPML[0][0], 1, &m_SigmaPML[1][0], 1,
2434  &Sigma0minus1[0], 1);
2435  Vmath::Vadd(nq, &m_SigmaPML[0][0], 1, &m_SigmaPML[1][0], 1,
2436  &Sigma0plus1Neg[0], 1);
2437  Vmath::Neg(nq, Sigma0plus1Neg, 1);
2438 
2439  switch (m_PolType)
2440  {
2442  {
2443  int indxH0 = 0;
2444  int indxH1 = 1;
2445  int indxE2 = 2;
2446  int indxQ0 = 3;
2447  int indxQ1 = 4;
2448  int indxP2 = 5;
2449 
2450  // dH0/dt: Add (sigma_0 - \sigma_1) H0 + Q0
2451  Vmath::Vvtvp(nq, &Sigma0minus1[0], 1, &physarray[indxH0][0], 1,
2452  &outarray[indxH0][0], 1, &outarray[indxH0][0], 1);
2453  Vmath::Vadd(nq, &physarray[indxQ0][0], 1, &outarray[indxH0][0], 1,
2454  &outarray[indxH0][0], 1);
2455 
2456  // dH1/dt: Add (sigma_1 - \sigma_0) H1 + Q1
2457  Vmath::Vvtvp(nq, &Sigma1minus0[0], 1, &physarray[indxH1][0], 1,
2458  &outarray[indxH1][0], 1, &outarray[indxH1][0], 1);
2459  Vmath::Vadd(nq, &physarray[indxQ1][0], 1, &outarray[indxH1][0], 1,
2460  &outarray[indxH1][0], 1);
2461 
2462  // dHz/dt: Add -(\sigma_0 + \sigma_1) Ez + Pz
2463  Vmath::Vvtvp(nq, &Sigma0plus1Neg[0], 1, &physarray[indxE2][0], 1,
2464  &outarray[indxE2][0], 1, &outarray[indxE2][0], 1);
2465  Vmath::Vadd(nq, &physarray[indxP2][0], 1, &outarray[indxE2][0], 1,
2466  &outarray[indxE2][0], 1);
2467 
2468  // dQ0/dt: Assign -\sigma_0 * ( Q0 + (\sigma_0 - \sigma_1) * H0 )
2469  Vmath::Vvtvp(nq, &Sigma0minus1[0], 1, &physarray[indxH0][0], 1,
2470  &physarray[indxQ0][0], 1, &outarray[indxQ0][0], 1);
2471  Vmath::Vmul(nq, &m_SigmaPML[0][0], 1, &outarray[indxQ0][0], 1,
2472  &outarray[indxQ0][0], 1);
2473  Vmath::Neg(nq, &outarray[indxQ0][0], 1);
2474 
2475  // dQ1/dt: Assign -\sigma_1 * ( Q1 + (\sigma_1 - \sigma_0) * H1 )
2476  Vmath::Vvtvp(nq, &Sigma1minus0[0], 1, &physarray[indxH1][0], 1,
2477  &physarray[indxQ1][0], 1, &outarray[indxQ1][0], 1);
2478  Vmath::Vmul(nq, &m_SigmaPML[1][0], 1, &outarray[indxQ1][0], 1,
2479  &outarray[indxQ1][0], 1);
2480  Vmath::Neg(nq, &outarray[indxQ1][0], 1);
2481 
2482  if (m_DispersiveCloak)
2483  {
2484  Vmath::Vvtvp(nq, &m_wp2[0], 1, &physarray[indxH1][0], 1,
2485  &outarray[indxQ1][0], 1, &outarray[indxQ1][0], 1);
2486  }
2487 
2488  // dP3/dt: Assign - \sigma_1 * \sigma_2 * E_z
2489  Vmath::Vmul(nq, &m_SigmaPML[0][0], 1, &m_SigmaPML[1][0], 1,
2490  &outarray[indxP2][0], 1);
2491  Vmath::Vmul(nq, &physarray[indxE2][0], 1, &outarray[indxP2][0], 1,
2492  &outarray[indxP2][0], 1);
2493  Vmath::Neg(nq, &outarray[indxP2][0], 1);
2494  }
2495  break;
2496 
2498  {
2499  int indxE0 = 0;
2500  int indxE1 = 1;
2501  int indxH2 = 2;
2502  int indxQ0 = 3;
2503  int indxQ1 = 4;
2504  int indxP2 = 5;
2505 
2506  // dE0/dt: Add (sigma_0 - \sigma_1) E0 - Q0
2507  Vmath::Vvtvp(nq, &Sigma0minus1[0], 1, &physarray[indxE0][0], 1,
2508  &outarray[indxE0][0], 1, &outarray[indxE0][0], 1);
2509  Vmath::Vsub(nq, &outarray[indxE0][0], 1, &physarray[indxQ0][0], 1,
2510  &outarray[indxE0][0], 1);
2511 
2512  // dE1/dt: Add (sigma_1 - \sigma_0) E1 - Q1
2513  Vmath::Vvtvp(nq, &Sigma1minus0[0], 1, &physarray[indxE1][0], 1,
2514  &outarray[indxE1][0], 1, &outarray[indxE1][0], 1);
2515  Vmath::Vsub(nq, &outarray[indxE1][0], 1, &physarray[indxQ1][0], 1,
2516  &outarray[indxE1][0], 1);
2517 
2518  // dHz/dt: Add -(\sigma_0 + \sigma_1) Hz - Pz
2519  Vmath::Vvtvp(nq, &Sigma0plus1Neg[0], 1, &physarray[indxH2][0], 1,
2520  &outarray[indxH2][0], 1, &outarray[indxH2][0], 1);
2521  Vmath::Vsub(nq, &outarray[indxH2][0], 1, &physarray[indxP2][0], 1,
2522  &outarray[indxH2][0], 1);
2523 
2524  // dQ0/dt: Assign -\sigma_0 * ( Q0 + (\sigma_1 - \sigma_0) * E0 )
2525  Vmath::Vvtvp(nq, &Sigma1minus0[0], 1, &physarray[indxE0][0], 1,
2526  &physarray[indxQ0][0], 1, &outarray[indxQ0][0], 1);
2527  Vmath::Vmul(nq, &m_SigmaPML[0][0], 1, &outarray[indxQ0][0], 1,
2528  &outarray[indxQ0][0], 1);
2529  Vmath::Neg(nq, &outarray[indxQ0][0], 1);
2530 
2531  // dQ1/dt: Assign -\sigma_1 * ( Q1 + (\sigma_0 - \sigma_1) * E1 )
2532  Vmath::Vvtvp(nq, &Sigma0minus1[0], 1, &physarray[indxE1][0], 1,
2533  &physarray[indxQ1][0], 1, &outarray[indxQ1][0], 1);
2534  Vmath::Vmul(nq, &m_SigmaPML[1][0], 1, &outarray[indxQ1][0], 1,
2535  &outarray[indxQ1][0], 1);
2536  Vmath::Neg(nq, &outarray[indxQ1][0], 1);
2537 
2538  if (m_DispersiveCloak)
2539  {
2540  Vmath::Vvtvp(nq, &m_wp2[0], 1, &physarray[indxE1][0], 1,
2541  &outarray[indxQ1][0], 1, &outarray[indxQ1][0], 1);
2542  }
2543 
2544  // dP3/dt: Assign \sigma_1 * \sigma_2 * H_z
2545  Vmath::Vmul(nq, &m_SigmaPML[0][0], 1, &m_SigmaPML[1][0], 1,
2546  &outarray[indxP2][0], 1);
2547  Vmath::Vmul(nq, &physarray[indxH2][0], 1, &outarray[indxP2][0], 1,
2548  &outarray[indxP2][0], 1);
2549  }
2550  break;
2551 
2552  default:
2553  break;
2554  }
2555 }
2556 
2558  const int n, const NekDouble time,
2559  const Array<OneD, const Array<OneD, NekDouble>> &fieldphys)
2560 {
2561  int nvar = m_fields.size();
2562  int nq = m_fields[0]->GetTotPoints();
2563  int ncoeffs = m_fields[0]->GetNcoeffs();
2564 
2565  std::string outname =
2566  m_sessionName + "Tot_" + boost::lexical_cast<std::string>(n) + ".chk";
2567 
2568  std::vector<std::string> variables(nvar);
2569  std::vector<Array<OneD, NekDouble>> fieldcoeffs(nvar);
2570 
2571  for (int i = 0; i < nvar; ++i)
2572  {
2573  fieldcoeffs[i] = Array<OneD, NekDouble>(ncoeffs);
2574  }
2575 
2576  Array<OneD, NekDouble> totfield(nq);
2577  for (int i = 0; i < nvar; ++i)
2578  {
2579  totfield = GetIncidentField(i, time);
2580  Vmath::Vadd(nq, fieldphys[i], 1, totfield, 1, totfield, 1);
2581 
2582  m_fields[i]->FwdTrans(totfield, fieldcoeffs[i]);
2583  variables[i] = m_boundaryConditions->GetVariable(i);
2584  }
2585 
2586  WriteFld(outname, m_fields[0], fieldcoeffs, variables);
2587 }
2588 
2589 // Only for nvar = 3
2591  const int n, const Array<OneD, const Array<OneD, NekDouble>> &fieldphys)
2592 {
2593  int nvar = m_fields.size();
2594  int nq = m_fields[0]->GetTotPoints();
2595  int ncoeffs = m_fields[0]->GetNcoeffs();
2596 
2597  std::string outname =
2598  m_sessionName + "Plot_" + boost::lexical_cast<std::string>(n) + ".chk";
2599 
2600  std::vector<std::string> variables(nvar);
2601  variables[0] = "Fx";
2602  variables[1] = "Fy";
2603  variables[2] = "Fz";
2604 
2605  std::vector<Array<OneD, NekDouble>> fieldcoeffs(nvar);
2606  for (int i = 0; i < nvar; ++i)
2607  {
2608  fieldcoeffs[i] = Array<OneD, NekDouble>(ncoeffs);
2609  }
2610 
2611  Array<OneD, NekDouble> tmp(nq);
2612  for (int k = 0; k < m_spacedim; ++k)
2613  {
2614  Vmath::Vmul(nq, &fieldphys[0][0], 1, &m_movingframes[0][k * nq], 1,
2615  &tmp[0], 1);
2616  Vmath::Vvtvp(nq, &fieldphys[1][0], 1, &m_movingframes[1][k * nq], 1,
2617  &tmp[0], 1, &tmp[0], 1);
2618 
2619  m_fields[k]->FwdTrans(tmp, fieldcoeffs[k]);
2620  }
2621 
2622  WriteFld(outname, m_fields[0], fieldcoeffs, variables);
2623 }
2624 
2626  const int n, const NekDouble time,
2627  const Array<OneD, const Array<OneD, NekDouble>> &fieldphys)
2628 {
2629  int nvar = m_fields.size();
2630  int nq = m_fields[0]->GetTotPoints();
2631  int ncoeffs = m_fields[0]->GetNcoeffs();
2632 
2633  std::string outname = m_sessionName + "TotPlot_" +
2634  boost::lexical_cast<std::string>(n) + ".chk";
2635 
2636  std::vector<std::string> variables(nvar);
2637  variables[0] = "Frx";
2638  variables[1] = "Fry";
2639  variables[2] = "Frz";
2640  for (int i = 3; i < nvar; ++i)
2641  {
2642  variables[i] = m_boundaryConditions->GetVariable(i);
2643  }
2644 
2645  std::vector<Array<OneD, NekDouble>> fieldcoeffs(nvar);
2646  for (int i = 0; i < nvar; ++i)
2647  {
2648  fieldcoeffs[i] = Array<OneD, NekDouble>(ncoeffs);
2649  }
2650 
2651  Array<OneD, NekDouble> tmp(nq);
2652  Array<OneD, NekDouble> totfield0(nq);
2653  Array<OneD, NekDouble> totfield1(nq);
2654 
2655  totfield0 = GetIncidentField(0, time);
2656  Vmath::Vadd(nq, fieldphys[0], 1, totfield0, 1, totfield0, 1);
2657 
2658  totfield1 = GetIncidentField(1, time);
2659  Vmath::Vadd(nq, fieldphys[1], 1, totfield1, 1, totfield1, 1);
2660 
2661  for (int k = 0; k < m_spacedim; ++k)
2662  {
2663  Vmath::Vmul(nq, &totfield0[0], 1, &m_movingframes[0][k * nq], 1,
2664  &tmp[0], 1);
2665  Vmath::Vvtvp(nq, &totfield1[0], 1, &m_movingframes[1][k * nq], 1,
2666  &tmp[0], 1, &tmp[0], 1);
2667 
2668  m_fields[k]->FwdTrans(tmp, fieldcoeffs[k]);
2669  }
2670 
2671  for (int j = 3; j < nvar; ++j)
2672  {
2673  m_fields[j]->FwdTrans(fieldphys[j], fieldcoeffs[j]);
2674  }
2675 
2676  WriteFld(outname, m_fields[0], fieldcoeffs, variables);
2677 }
2678 
2680  const int n, const NekDouble time,
2681  const Array<OneD, const Array<OneD, NekDouble>> &fieldphys)
2682 {
2683  boost::ignore_unused(time);
2684 
2685  int nvar = m_fields.size();
2686  int nq = m_fields[0]->GetTotPoints();
2687  int ncoeffs = m_fields[0]->GetNcoeffs();
2688 
2689  std::string outname = m_sessionName + "EDFlux_" +
2690  boost::lexical_cast<std::string>(n) + ".chk";
2691 
2692  std::vector<std::string> variables(nvar);
2693  variables[0] = "EDFx";
2694  variables[1] = "EDFy";
2695  variables[2] = "EDFz";
2696  for (int i = 3; i < nvar; ++i)
2697  {
2698  variables[i] = m_boundaryConditions->GetVariable(i);
2699  }
2700 
2701  std::vector<Array<OneD, NekDouble>> fieldcoeffs(nvar);
2702  for (int i = 0; i < nvar; ++i)
2703  {
2704  fieldcoeffs[i] = Array<OneD, NekDouble>(ncoeffs);
2705  }
2706 
2707  Array<OneD, NekDouble> tmp(nq);
2708 
2709  // TE: H^3 (E^2 e^1 - E^1 e^2 )
2710  // TM: -E^3 (H^2 e^1 - H^1 e^2 )
2711  for (int k = 0; k < m_spacedim; ++k)
2712  {
2713  Vmath::Vmul(nq, &fieldphys[0][0], 1, &m_movingframes[1][k * nq], 1,
2714  &tmp[0], 1);
2715  Vmath::Vvtvm(nq, &fieldphys[1][0], 1, &m_movingframes[0][k * nq], 1,
2716  &tmp[0], 1, &tmp[0], 1);
2717 
2718  Vmath::Vmul(nq, &fieldphys[2][0], 1, &tmp[0], 1, &tmp[0], 1);
2719 
2721  {
2722  Vmath::Neg(nq, tmp, 1);
2723  }
2724 
2725  m_fields[k]->FwdTrans(tmp, fieldcoeffs[k]);
2726  }
2727 
2728  WriteFld(outname, m_fields[0], fieldcoeffs, variables);
2729 }
2730 
2732  const int n, const NekDouble time,
2733  const Array<OneD, const Array<OneD, NekDouble>> &fieldphys)
2734 {
2735  boost::ignore_unused(time);
2736 
2737  int nvar = m_fields.size();
2738  int nq = m_fields[0]->GetTotPoints();
2739  int ncoeffs = m_fields[0]->GetNcoeffs();
2740 
2741  std::string outname = m_sessionName + "Energy_" +
2742  boost::lexical_cast<std::string>(n) + ".chk";
2743 
2744  std::vector<std::string> variables(nvar);
2745  variables[0] = "Energy";
2746  variables[1] = "EnergyFlux";
2747  variables[2] = "Zero";
2748  for (int i = 3; i < nvar; ++i)
2749  {
2750  variables[i] = m_boundaryConditions->GetVariable(i);
2751  }
2752 
2753  std::vector<Array<OneD, NekDouble>> fieldcoeffs(nvar);
2754  for (int i = 0; i < nvar; ++i)
2755  {
2756  fieldcoeffs[i] = Array<OneD, NekDouble>(ncoeffs);
2757  }
2758 
2759  // Energy = 0.5 * ( E^2 + H^2 )
2760  Array<OneD, NekDouble> energy(nq, 0.0);
2761  Array<OneD, NekDouble> totfield(nq);
2762  for (int k = 0; k < m_spacedim; ++k)
2763  {
2764  // totfield = GetIncidentField(k,time);
2765  // Vmath::Vadd(nq, &fieldphys[k][0], 1, &totfield[0], 1, &totfield[0],
2766  // 1);
2767 
2768  Vmath::Vvtvp(nq, &fieldphys[k][0], 1, &fieldphys[k][0], 1, &energy[0],
2769  1, &energy[0], 1);
2770  }
2771  Vmath::Smul(nq, 0.5, energy, 1, energy, 1);
2772  m_fields[0]->FwdTrans(energy, fieldcoeffs[0]);
2773 
2774  // EnergyFlux = F3* sqrt( F1^2 + F2^2 )
2775  Array<OneD, NekDouble> energyflux(nq, 0.0);
2776  Array<OneD, NekDouble> Zero(nq, 0.0);
2777  for (int k = 0; k < 2; ++k)
2778  {
2779  // totfield = GetIncidentField(k,time);
2780  // Vmath::Vadd(nq, &fieldphys[k][0], 1, &totfield[0], 1, &totfield[0],
2781  // 1);
2782 
2783  Vmath::Vvtvp(nq, &fieldphys[k][0], 1, &fieldphys[k][0], 1,
2784  &energyflux[0], 1, &energyflux[0], 1);
2785  }
2786 
2787  Vmath::Vsqrt(nq, energyflux, 1, energyflux, 1);
2788  Vmath::Vmul(nq, &fieldphys[2][0], 1, &energyflux[0], 1, &energyflux[0], 1);
2789 
2790  m_fields[1]->FwdTrans(energyflux, fieldcoeffs[1]);
2791  m_fields[2]->FwdTrans(Zero, fieldcoeffs[2]);
2792 
2793  WriteFld(outname, m_fields[0], fieldcoeffs, variables);
2794 }
2795 
2797  const NekDouble Psx,
2798  const NekDouble Psy,
2799  const NekDouble Psz,
2800  const NekDouble Gaussianradius)
2801 {
2802  int nq = m_fields[0]->GetTotPoints();
2803  int ncoeffs = m_fields[0]->GetNcoeffs();
2804 
2805  Array<OneD, NekDouble> x(nq);
2806  Array<OneD, NekDouble> y(nq);
2807  Array<OneD, NekDouble> z(nq);
2808 
2809  m_fields[0]->GetCoords(x, y, z);
2810 
2811  Array<OneD, NekDouble> outarray(nq, 0.0);
2812  Array<OneD, NekDouble> tmpc(ncoeffs);
2813  NekDouble rad;
2814 
2815  NekDouble SFradius = m_PSduration * 0.1;
2816  NekDouble SmoothFactor =
2817  1.0 / (1.0 + exp(-0.5 * (time - m_PSduration) / SFradius));
2818 
2819  for (int j = 0; j < nq; ++j)
2820  {
2821  rad = sqrt((x[j] - Psx) * (x[j] - Psx) + (y[j] - Psy) * (y[j] - Psy) +
2822  (z[j] - Psz) * (z[j] - Psz));
2823  outarray[j] = SmoothFactor * exp(-1.0 * (rad / Gaussianradius) *
2824  (rad / Gaussianradius));
2825  }
2826 
2827  m_fields[0]->FwdTrans_IterPerExp(outarray, tmpc);
2828  m_fields[0]->BwdTrans(tmpc, outarray);
2829 
2830  return outarray;
2831 }
2832 
2834 {
2835  int nq = GetTotPoints();
2836 
2837  NekDouble m_Omega = 1.5486 * 0.000001;
2838 
2839  NekDouble x0j, x1j, x2j;
2840  NekDouble sin_theta, cos_theta, sin_varphi, cos_varphi;
2841 
2842  Array<OneD, NekDouble> x(nq);
2843  Array<OneD, NekDouble> y(nq);
2844  Array<OneD, NekDouble> z(nq);
2845 
2846  m_fields[0]->GetCoords(x, y, z);
2847 
2848  Array<OneD, NekDouble> outarray(nq, 0.0);
2849  for (int j = 0; j < nq; ++j)
2850  {
2851  x0j = x[j];
2852  x1j = y[j];
2853  x2j = z[j];
2854 
2855  CartesianToSpherical(x0j, x1j, x2j, sin_varphi, cos_varphi, sin_theta,
2856  cos_theta);
2857 
2858  outarray[j] = 2.0 * m_Omega * sin_theta;
2859  }
2860 
2861  return outarray;
2862 }
2863 
2865  Array<OneD, Array<OneD, NekDouble>> &outarray)
2866 {
2867  int nq = physarray[0].size();
2868 
2869  Array<OneD, NekDouble> tmp(nq);
2870 
2871  int indx;
2872  for (int j = 0; j < m_shapedim; ++j)
2873  {
2874  if (j == 0)
2875  {
2876  indx = 2;
2877  }
2878 
2879  else if (j == 1)
2880  {
2881  indx = 1;
2882  }
2883 
2884  Vmath::Vmul(nq, m_coriolis, 1, physarray[indx], 1, tmp, 1);
2885 
2886  switch (m_PolType)
2887  {
2889  {
2890  Vmath::Vmul(nq, m_muvec[indx], 1, tmp, 1, tmp, 1);
2891  }
2892  break;
2893 
2895  {
2896  Vmath::Vmul(nq, m_epsvec[indx], 1, tmp, 1, tmp, 1);
2897  }
2898  break;
2899 
2900  default:
2901  break;
2902  }
2903 
2904  if (j == 1)
2905  {
2906  Vmath::Neg(nq, tmp, 1);
2907  }
2908 
2909  Vmath::Vadd(nq, tmp, 1, outarray[j], 1, outarray[j], 1);
2910  }
2911 }
2912 
2914 {
2915  int nq = GetNpoints();
2916 
2917  NekDouble m_b = 1.0 / 0.314;
2918  NekDouble m_a = 1.0;
2919 
2920  Array<OneD, int> Layer(CloakNlayer);
2921 
2922  NekDouble la = m_MMFfactors[0];
2923  NekDouble lb = m_MMFfactors[1];
2924  if (CloakNlayer == 8)
2925  {
2926  // Circular 8 layer
2927  if (fabs(la * lb - 1.0) < 0.0001)
2928  {
2929  Layer[0] = 119;
2930  Layer[1] = 239;
2931  Layer[2] = 323;
2932  Layer[3] = 459;
2933  Layer[4] = 575;
2934  Layer[5] = 727;
2935  Layer[6] = 891;
2936  Layer[7] = 1059;
2937  }
2938 
2939  // Ellipsoid 8 layer
2940  else
2941  {
2942  Layer[0] = 115;
2943  Layer[1] = 219;
2944  Layer[2] = 335;
2945  Layer[3] = 459;
2946  Layer[4] = 607;
2947  Layer[5] = 767;
2948  Layer[6] = 951;
2949  Layer[7] = 1155;
2950  }
2951  }
2952 
2953  if (CloakNlayer == 16)
2954  {
2955  // Circular 16 layer
2956  if (fabs(la * lb - 1.0) < 0.0001)
2957  {
2958  Layer[0] = 43;
2959  Layer[1] = 87;
2960  Layer[2] = 135;
2961  Layer[3] = 187;
2962  Layer[4] = 239;
2963  Layer[5] = 295;
2964  Layer[6] = 355;
2965  Layer[7] = 415;
2966  Layer[8] = 479;
2967  Layer[9] = 555;
2968  Layer[10] = 639;
2969  Layer[11] = 727;
2970  Layer[12] = 823;
2971  Layer[13] = 927;
2972  Layer[14] = 1039;
2973  Layer[15] = 1159;
2974  }
2975 
2976  // Ellipsoid 8 layer
2977  else
2978  {
2979  Layer[0] = 135;
2980  Layer[1] = 259;
2981  Layer[2] = 387;
2982  Layer[3] = 523;
2983  Layer[4] = 667;
2984  Layer[5] = 803;
2985  Layer[6] = 939;
2986  Layer[7] = 1083;
2987  Layer[8] = 1235;
2988  Layer[9] = 1387;
2989  Layer[10] = 1539;
2990  Layer[11] = 1699;
2991  Layer[12] = 1867;
2992  Layer[13] = 2035;
2993  Layer[14] = 2203;
2994  Layer[15] = 2379;
2995  }
2996  }
2997 
2998  Array<OneD, NekDouble> x0(nq);
2999  Array<OneD, NekDouble> x1(nq);
3000  Array<OneD, NekDouble> x2(nq);
3001 
3002  m_fields[0]->GetCoords(x0, x1, x2);
3003 
3004  Array<OneD, NekDouble> Formertmp(nq, 0.0);
3005  Array<OneD, NekDouble> Currenttmp(nq, 0.0);
3006  Array<OneD, NekDouble> Cloakregion(nq, 0.0);
3007 
3008  m_fields[0]->GenerateElementVector(Layer[0], 1.0, 0.0, Currenttmp);
3009  Vmath::Vcopy(nq, Currenttmp, 1, Cloakregion, 1);
3010  for (int i = 1; i < CloakNlayer; ++i)
3011  {
3012  m_fields[0]->GenerateElementVector(Layer[i], 1.0, 0.0, Currenttmp);
3013  m_fields[0]->GenerateElementVector(Layer[i - 1], 1.0, 0.0, Formertmp);
3014 
3015  Vmath::Vsub(nq, Currenttmp, 1, Formertmp, 1, Currenttmp, 1);
3016 
3017  Vmath::Svtvp(nq, 1.0 * (i + 1), Currenttmp, 1, Cloakregion, 1,
3018  Cloakregion, 1);
3019  }
3020 
3021  Array<OneD, NekDouble> radvec(nq);
3022 
3023  for (int i = 0; i < nq; ++i)
3024  {
3025  switch (m_MMFdir)
3026  {
3028  {
3029  if ((Cloakregion[i] > 0) && (CloakNlayer > 0))
3030  {
3031  radvec[i] =
3032  1.0 +
3033  (m_b - m_a) / CloakNlayer * (Cloakregion[i] - 0.5);
3034  }
3035 
3036  else
3037  {
3038  radvec[i] =
3039  sqrt(x0[i] * x0[i] / la / la + x1[i] * x1[i] / lb / lb);
3040  }
3041  }
3042  break;
3043 
3045  {
3046  radvec[i] = sqrt(2.0 * x0[i] * x0[i] +
3047  x1[i] * x1[i] * x1[i] * x1[i] + x1[i] * x1[i]);
3048  }
3049  break;
3050 
3052  {
3053  radvec[i] = sqrt(3.0 * x0[i] * x0[i] +
3054  x1[i] * x1[i] * x1[i] * x1[i] - x1[i] * x1[i]);
3055  }
3056  break;
3057 
3058  default:
3059  break;
3060  }
3061  }
3062 
3063  return radvec;
3064 }
3065 
3067 {
3070  s, "TestMaxwellType",
3072  SolverUtils::AddSummaryItem(s, "PolType",
3074  SolverUtils::AddSummaryItem(s, "IncType",
3076 
3077  if (m_varepsilon[0] * m_varepsilon[1] * m_varepsilon[2] > 1.0)
3078  {
3079  SolverUtils::AddSummaryItem(s, "varepsilon1", m_varepsilon[0]);
3080  SolverUtils::AddSummaryItem(s, "varepsilon2", m_varepsilon[1]);
3081  SolverUtils::AddSummaryItem(s, "varepsilon3", m_varepsilon[2]);
3082  }
3083 
3084  if (m_mu[0] * m_mu[1] * m_mu[2] > 1.0)
3085  {
3086  SolverUtils::AddSummaryItem(s, "mu1", m_mu[0]);
3087  SolverUtils::AddSummaryItem(s, "mu2", m_mu[1]);
3088  SolverUtils::AddSummaryItem(s, "mu3", m_mu[2]);
3089  }
3090 
3091  if (m_boundaryforSF > 0)
3092  {
3093  SolverUtils::AddSummaryItem(s, "boundarySF", m_boundaryforSF);
3094  }
3095 
3096  if (m_ElemtGroup1 > 0)
3097  {
3098  SolverUtils::AddSummaryItem(s, "CloakNlayer", m_CloakNlayer);
3099  SolverUtils::AddSummaryItem(s, "ElemtGroup1", m_ElemtGroup1);
3100  }
3101 
3102  SolverUtils::AddSummaryItem(s, "AddRotation", m_AddRotation);
3103 
3104  if (m_AddPML > 0)
3105  {
3106  SolverUtils::AddSummaryItem(s, "AddPML", m_AddPML);
3107  SolverUtils::AddSummaryItem(s, "PMLelement", m_PMLelement);
3108  SolverUtils::AddSummaryItem(s, "RecPML", m_RecPML);
3109  SolverUtils::AddSummaryItem(s, "PMLorder", m_PMLorder);
3110  SolverUtils::AddSummaryItem(s, "PMLthickness", m_PMLthickness);
3111  SolverUtils::AddSummaryItem(s, "PMLstart", m_PMLstart);
3112  SolverUtils::AddSummaryItem(s, "PMLmaxsigma", m_PMLmaxsigma);
3113  }
3114 
3115  if (m_SourceType)
3116  {
3117  SolverUtils::AddSummaryItem(s, "SourceType",
3122  SolverUtils::AddSummaryItem(s, "PSduration", m_PSduration);
3123  SolverUtils::AddSummaryItem(s, "Gaussianradius", m_Gaussianradius);
3124  }
3125 
3126  if (m_CloakType)
3127  {
3129  SolverUtils::AddSummaryItem(s, "DispersiveCloak", m_DispersiveCloak);
3130  SolverUtils::AddSummaryItem(s, "CloakNlayer", m_CloakNlayer);
3131  SolverUtils::AddSummaryItem(s, "Cloakraddelta", m_Cloakraddelta);
3132  }
3133 }
3135 {
3136  int Ntot = inarray.size();
3137 
3138  NekDouble reval = 0.0;
3139  for (int i = 0; i < Ntot; ++i)
3140  {
3141  std::cout << "[" << i << "] = " << inarray[2][i] << std::endl;
3142  // reval = reval + inarray[i]*inarray[i];
3143  }
3144  reval = sqrt(reval / Ntot);
3145 }
3146 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
const char *const CloakTypeMap[]
Definition: MMFMaxwell.h:51
SourceType
Definition: MMFMaxwell.h:58
@ ePointSource
Definition: MMFMaxwell.h:60
@ ePlanarSource
Definition: MMFMaxwell.h:61
@ SIZE_SourceType
Definition: MMFMaxwell.h:62
const char *const SourceTypeMap[]
Definition: MMFMaxwell.h:65
CloakType
Definition: MMFMaxwell.h:42
@ eOpticalCloak
Definition: MMFMaxwell.h:44
@ eMicroWaveCloak
Definition: MMFMaxwell.h:47
@ eOpticalDispersiveCloak
Definition: MMFMaxwell.h:46
@ eOpticalConstCloak
Definition: MMFMaxwell.h:45
@ SIZE_CloakType
Definition: MMFMaxwell.h:48
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:200
void DefineProjection(FuncPointerT func, ObjectPointerT obj)
void DefineOdeRhs(FuncPointerT func, ObjectPointerT obj)
NekDouble TimePerTest(unsigned int n)
Returns amount of seconds per iteration in a test with n iterations.
Definition: Timer.cpp:62
NekDouble m_CloakNlayer
Definition: MMFMaxwell.h:113
NekDouble m_PSduration
Definition: MMFMaxwell.h:121
CloakType m_CloakType
Definition: MMFMaxwell.h:76
Array< OneD, NekDouble > m_mu
Definition: MMFMaxwell.h:133
void ComputeMaterialVector(Array< OneD, Array< OneD, NekDouble >> &epsvec, Array< OneD, Array< OneD, NekDouble >> &muvec)
NekDouble m_PMLmaxsigma
Definition: MMFMaxwell.h:137
Array< OneD, NekDouble > TestMaxwellSphere(const NekDouble time, const NekDouble omega, unsigned int field)
Array< OneD, NekDouble > m_coriolis
Definition: MMFMaxwell.h:142
Array< OneD, Array< OneD, NekDouble > > m_CrossProductMF
Definition: MMFMaxwell.h:123
NekDouble m_Gaussianradius
Definition: MMFMaxwell.h:121
NekDouble m_PMLstart
Definition: MMFMaxwell.h:137
void Checkpoint_TotalFieldOutput(const int n, const NekDouble time, const Array< OneD, const Array< OneD, NekDouble >> &fieldphys)
void Checkpoint_EnergyOutput(const int n, const NekDouble time, const Array< OneD, const Array< OneD, NekDouble >> &fieldphys)
void Checkpoint_TotPlotOutput(const int n, const NekDouble time, const Array< OneD, const Array< OneD, NekDouble >> &fieldphys)
void GenerateSigmaPML(const NekDouble PMLthickness, const NekDouble PMLstart, const NekDouble PMLmaxsigma, Array< OneD, Array< OneD, NekDouble >> &SigmaPML)
void Checkpoint_PlotOutput(const int n, const Array< OneD, const Array< OneD, NekDouble >> &fieldphys)
Array< OneD, NekDouble > ComputeRadCloak(const int Nlayer=5)
Array< OneD, NekDouble > TestMaxwell2DPEC(const NekDouble time, unsigned int field, const SolverUtils::PolType Polarization)
void DoOdeProjection(const Array< OneD, const Array< OneD, NekDouble >> &inarray, Array< OneD, Array< OneD, NekDouble >> &outarray, const NekDouble time)
Compute the projection.
Array< OneD, NekDouble > m_SourceVector
Definition: MMFMaxwell.h:119
virtual ~MMFMaxwell()
Destructor.
Definition: MMFMaxwell.cpp:445
void AddPML(const Array< OneD, const Array< OneD, NekDouble >> &physarray, Array< OneD, Array< OneD, NekDouble >> &outarray)
NekDouble m_Cloakraddelta
Definition: MMFMaxwell.h:114
void DoOdeRhs(const Array< OneD, const Array< OneD, NekDouble >> &inarray, Array< OneD, Array< OneD, NekDouble >> &outarray, const NekDouble time)
Compute the RHS.
Definition: MMFMaxwell.cpp:886
static std::string className
Name of class.
Definition: MMFMaxwell.h:91
virtual void v_SetInitialConditions(const NekDouble initialtime, bool dumpInitialConditions, const int domain)
void WeakDGMaxwellDirDeriv(const Array< OneD, const Array< OneD, NekDouble >> &InField, Array< OneD, Array< OneD, NekDouble >> &OutField, const NekDouble time=0.0)
Calculate weak DG advection in the form .
void ComputeMaterialMicroWaveCloak(const Array< OneD, const NekDouble > &radvec, Array< OneD, Array< OneD, NekDouble >> &epsvec, Array< OneD, Array< OneD, NekDouble >> &muvec)
Array< OneD, Array< OneD, NekDouble > > m_SigmaPML
Definition: MMFMaxwell.h:138
Array< OneD, NekDouble > m_varepsilon
Definition: MMFMaxwell.h:132
void AddGreenDerivCompensate(const Array< OneD, const Array< OneD, NekDouble >> &physarray, Array< OneD, Array< OneD, NekDouble >> &outarray)
virtual void v_InitObject()
Initialise the object.
Definition: MMFMaxwell.cpp:65
MMFMaxwell(const LibUtilities::SessionReaderSharedPtr &pSession, const SpatialDomains::MeshGraphSharedPtr &pGraph)
Session reader.
Definition: MMFMaxwell.cpp:56
void Printout_SurfaceCurrent(Array< OneD, Array< OneD, NekDouble >> &fields, const int time)
SourceType m_SourceType
Definition: MMFMaxwell.h:77
static SolverUtils::EquationSystemSharedPtr create(const LibUtilities::SessionReaderSharedPtr &pSession, const SpatialDomains::MeshGraphSharedPtr &pGraph)
Creates an instance of this class.
Definition: MMFMaxwell.h:81
NekDouble m_freq
Definition: MMFMaxwell.h:129
int m_PrintoutSurfaceCurrent
Definition: MMFMaxwell.h:105
NekDouble m_PMLthickness
Definition: MMFMaxwell.h:137
Array< OneD, NekDouble > GaussianPulse(const NekDouble time, const NekDouble Psx, const NekDouble Psy, const NekDouble Psz, const NekDouble Gaussianradius)
NekDouble m_wp2Tol
Definition: MMFMaxwell.h:116
void AddCoriolis(Array< OneD, Array< OneD, NekDouble >> &physarray, Array< OneD, Array< OneD, NekDouble >> &outarray)
virtual void v_DoSolve()
Solves an unsteady problem.
Definition: MMFMaxwell.cpp:449
void print_MMF(Array< OneD, Array< OneD, NekDouble >> &inarray)
virtual void v_GenerateSummary(SolverUtils::SummaryList &s)
Print Summary.
Array< OneD, NekDouble > m_wp2
Definition: MMFMaxwell.h:117
void Checkpoint_EDFluxOutput(const int n, const NekDouble time, const Array< OneD, const Array< OneD, NekDouble >> &fieldphys)
virtual void v_EvaluateExactSolution(unsigned int field, Array< OneD, NekDouble > &outfield, const NekDouble time)
void ComputeMaterialOpticalCloak(const Array< OneD, const NekDouble > &radvec, Array< OneD, Array< OneD, NekDouble >> &epsvec, Array< OneD, Array< OneD, NekDouble >> &muvec, const bool Dispersion=false)
Array< OneD, NekDouble > TestMaxwell2DPMC(const NekDouble time, unsigned int field, const SolverUtils::PolType Polarization)
Array< OneD, NekDouble > EvaluateCoriolis()
Array< OneD, NekDouble > TestMaxwell1D(const NekDouble time, unsigned int field)
NekDouble ComputeEnergyDensity(Array< OneD, Array< OneD, NekDouble >> &fields)
Array< OneD, NekDouble > ComputeSurfaceCurrent(const int time, const Array< OneD, const Array< OneD, NekDouble >> &fields)
int m_spacedim
Spatial dimension (>= expansion dim).
SOLVER_UTILS_EXPORT int GetTraceNpoints()
NekDouble m_timestep
Time step size.
NekDouble m_time
Current time of simulation.
SOLVER_UTILS_EXPORT int GetTraceTotPoints()
Array< OneD, MultiRegions::ExpListSharedPtr > m_fields
Array holding all dependent variables.
NekDouble m_fintime
Finish time of the simulation.
SOLVER_UTILS_EXPORT void Checkpoint_Output(const int n)
Write checkpoint file of m_fields.
NekDouble m_checktime
Time between checkpoints.
SOLVER_UTILS_EXPORT void WriteFld(const std::string &outname)
Write field data to the given filename.
std::string m_sessionName
Name of the session.
LibUtilities::SessionReaderSharedPtr m_session
The session reader.
SOLVER_UTILS_EXPORT int GetNpoints()
SOLVER_UTILS_EXPORT int GetNcoeffs()
int m_steps
Number of steps to take.
SpatialDomains::BoundaryConditionsSharedPtr m_boundaryConditions
Pointer to boundary conditions object.
int m_checksteps
Number of steps between checkpoints.
SOLVER_UTILS_EXPORT int GetTotPoints()
A base class for PDEs which include an advection component.
Definition: MMFSystem.h:141
SOLVER_UTILS_EXPORT Array< OneD, NekDouble > CartesianToMovingframes(const Array< OneD, const Array< OneD, NekDouble >> &uvec, unsigned int field)
Definition: MMFSystem.cpp:774
SOLVER_UTILS_EXPORT void NumericalMaxwellFlux(Array< OneD, Array< OneD, NekDouble >> &physfield, Array< OneD, Array< OneD, NekDouble >> &numfluxFwd, Array< OneD, Array< OneD, NekDouble >> &numfluxBwd, const NekDouble time=0.0)
Definition: MMFSystem.cpp:1735
SOLVER_UTILS_EXPORT void ComputeZimYim(Array< OneD, Array< OneD, NekDouble >> &epsvec, Array< OneD, Array< OneD, NekDouble >> &muvec)
Definition: MMFSystem.cpp:1107
SOLVER_UTILS_EXPORT void GetMaxwellFluxVector(const int var, const Array< OneD, const Array< OneD, NekDouble >> &physfield, Array< OneD, Array< OneD, NekDouble >> &flux)
Definition: MMFSystem.cpp:1614
SOLVER_UTILS_EXPORT void DeriveCrossProductMF(Array< OneD, Array< OneD, NekDouble >> &CrossProductMF)
Definition: MMFSystem.cpp:571
Array< OneD, Array< OneD, NekDouble > > m_muvec
Definition: MMFSystem.h:207
SpatialDomains::GeomMMF m_MMFdir
Definition: MMFSystem.h:216
Array< OneD, Array< OneD, NekDouble > > m_movingframes
Definition: MMFSystem.h:180
Array< OneD, NekDouble > m_MMFfactors
Definition: MMFSystem.h:154
SOLVER_UTILS_EXPORT Array< OneD, NekDouble > GetIncidentField(const int var, const NekDouble time)
Definition: MMFSystem.cpp:2034
Array< OneD, Array< OneD, Array< OneD, NekDouble > > > m_ntimesMFFwd
Definition: MMFSystem.h:196
SOLVER_UTILS_EXPORT void MMFInitObject(const Array< OneD, const Array< OneD, NekDouble >> &Anisotropy, const int TangentXelem=-1)
Definition: MMFSystem.cpp:53
Array< OneD, Array< OneD, NekDouble > > m_negepsvecminus1
Definition: MMFSystem.h:209
SOLVER_UTILS_EXPORT void AdddedtMaxwell(const Array< OneD, const Array< OneD, NekDouble >> &physarray, Array< OneD, Array< OneD, NekDouble >> &outarray)
Definition: MMFSystem.cpp:1369
Array< OneD, Array< OneD, NekDouble > > m_epsvec
Definition: MMFSystem.h:206
SOLVER_UTILS_EXPORT void CartesianToSpherical(const NekDouble x0j, const NekDouble x1j, const NekDouble x2j, NekDouble &sin_varphi, NekDouble &cos_varphi, NekDouble &sin_theta, NekDouble &cos_theta)
Definition: MMFSystem.cpp:795
Array< OneD, Array< OneD, NekDouble > > m_negmuvecminus1
Definition: MMFSystem.h:210
SOLVER_UTILS_EXPORT void ComputeNtimesMF()
Definition: MMFSystem.cpp:618
SOLVER_UTILS_EXPORT NekDouble RootMeanSquare(const Array< OneD, const NekDouble > &inarray)
Definition: MMFSystem.cpp:2367
TestMaxwellType m_TestMaxwellType
Definition: MMFSystem.h:150
Array< OneD, Array< OneD, Array< OneD, NekDouble > > > m_CurlMF
Definition: MMFSystem.h:190
SOLVER_UTILS_EXPORT void Computedemdxicdote()
Definition: MMFSystem.cpp:1279
virtual SOLVER_UTILS_EXPORT void v_GenerateSummary(SummaryList &s)
Print a summary of time stepping parameters.
Definition: MMFSystem.cpp:2492
Base class for unsteady solvers.
LibUtilities::TimeIntegrationSchemeOperators m_ode
The time integration scheme operators to use.
LibUtilities::TimeIntegrationSchemeSharedPtr m_intScheme
Wrapper to the time integration scheme.
bool m_explicitAdvection
Indicates if explicit or implicit treatment of advection is used.
virtual SOLVER_UTILS_EXPORT void v_InitObject()
Init object for UnsteadySystem class.
int m_infosteps
Number of time steps between outputting status information.
static NekDouble rad(NekDouble x, NekDouble y)
Definition: Interpreter.cpp:86
std::shared_ptr< SessionReader > SessionReaderSharedPtr
static const NekDouble kNekZeroTol
const char *const IncTypeMap[]
Definition: MMFSystem.h:135
std::vector< std::pair< std::string, std::string > > SummaryList
Definition: Misc.h:46
@ SIZE_TestMaxwellType
Length of enum list.
Definition: MMFSystem.h:105
EquationSystemFactory & GetEquationSystemFactory()
const char *const TestMaxwellTypeMap[]
Definition: MMFSystem.h:108
void AddSummaryItem(SummaryList &l, const std::string &name, const std::string &value)
Adds a summary item to the summary info list.
Definition: Misc.cpp:47
const char *const PolTypeMap[]
Definition: MMFSystem.h:123
@ eTangentIrregular
Circular around the centre of domain.
@ eTangentCircular
Circular around the centre of domain.
@ eTangentNonconvex
Circular around the centre of domain.
std::shared_ptr< MeshGraph > MeshGraphSharedPtr
Definition: MeshGraph.h:174
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:1
double NekDouble
void Vsqrt(int n, const T *x, const int incx, T *y, const int incy)
sqrt y = sqrt(x)
Definition: Vmath.cpp:475
void Vmul(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Multiply vector z = x*y.
Definition: Vmath.cpp:192
void Svtvp(int n, const T alpha, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
svtvp (scalar times vector plus vector): z = alpha*x + y
Definition: Vmath.cpp:565
void Neg(int n, T *x, const int incx)
Negate x = -x.
Definition: Vmath.cpp:461
T Vmin(int n, const T *x, const int incx)
Return the minimum element in x - called vmin to avoid conflict with min.
Definition: Vmath.cpp:992
void Vvtvp(int n, const T *w, const int incw, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
vvtvp (vector times vector plus vector): z = w*x + y
Definition: Vmath.cpp:513
void Vadd(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Add vector z = x+y.
Definition: Vmath.cpp:322
void Vvtvm(int n, const T *w, const int incw, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
vvtvm (vector times vector plus vector): z = w*x - y
Definition: Vmath.cpp:541
void Smul(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Scalar multiply y = alpha*x.
Definition: Vmath.cpp:225
void Vdiv(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Multiply vector z = x/y.
Definition: Vmath.cpp:257
void Zero(int n, T *x, const int incx)
Zero vector.
Definition: Vmath.cpp:436
T Vamax(int n, const T *x, const int incx)
Return the maximum absolute element in x called vamax to avoid conflict with max.
Definition: Vmath.cpp:942
void Sadd(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Add vector y = alpha - x.
Definition: Vmath.cpp:341
T Vmax(int n, const T *x, const int incx)
Return the maximum element in x – called vmax to avoid conflict with max.
Definition: Vmath.cpp:892
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1199
void Vsub(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Subtract vector z = x-y.
Definition: Vmath.cpp:372
scalarT< T > sqrt(scalarT< T > in)
Definition: scalar.hpp:267