Nektar++
MMFSWE.cpp
Go to the documentation of this file.
1 /////////////////////////////////////////////////////////////////////////////
2 //
3 // File MMFSWE.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 solve routines
32 //
33 ///////////////////////////////////////////////////////////////////////////////
34 
35 #include <iomanip>
36 #include <iostream>
37 
38 #include <boost/core/ignore_unused.hpp>
39 #include <boost/algorithm/string/predicate.hpp>
40 
45 
46 namespace Nektar
47 {
48 std::string MMFSWE::className =
50  "MMFSWE", MMFSWE::create, "MMFSWE equation.");
51 
54  : UnsteadySystem(pSession, pGraph), MMFSystem(pSession, pGraph)
55 {
56  m_planeNumber = 0;
57 }
58 
59 /**
60  * @brief Initialisation object for the unsteady linear advection equation.
61  */
63 {
64  // Call to the initialisation object
66 
67  int nq = m_fields[0]->GetNpoints();
68  int shapedim = m_fields[0]->GetShapeDimension();
69  Array<OneD, Array<OneD, NekDouble>> Anisotropy(shapedim);
70  for (int j = 0; j < shapedim; ++j)
71  {
72  Anisotropy[j] = Array<OneD, NekDouble>(nq, 1.0);
73  }
74 
75  MMFSystem::MMFInitObject(Anisotropy);
76 
77  // Load acceleration of gravity
78  m_session->LoadParameter("Gravity", m_g, 9.81);
79 
80  // Add Coriolois effects
81  m_session->LoadParameter("AddCoriolis", m_AddCoriolis, 1);
82 
83  // Add Rotation of the sphere along the pole
84  m_session->LoadParameter("AddRotation", m_AddRotation, 1);
85 
86  m_session->LoadParameter("AddRossbyDisturbance", m_RossbyDisturbance, 0);
87  m_session->LoadParameter("PurturbedJet", m_PurturbedJet, 0);
88 
89  // Define TestType
90  ASSERTL0(m_session->DefinesSolverInfo("TESTTYPE"),
91  "No TESTTYPE defined in session.");
92  std::string TestTypeStr = m_session->GetSolverInfo("TESTTYPE");
93  for (int i = 0; i < (int)SIZE_TestType; ++i)
94  {
95  if (boost::iequals(TestTypeMap[i], TestTypeStr))
96  {
97  m_TestType = (TestType)i;
98  break;
99  }
100  }
101 
102  // Variable Setting for each test problem
103  NekDouble gms = 9.80616;
104 
105  switch (m_TestType)
106  {
107  case eTestSteadyZonal:
108  {
109  NekDouble SecondToDay = 60.0 * 60.0 * 24.0;
110  NekDouble rad_earth = 6.37122 * 1000000;
111  NekDouble Omegams;
112 
113  // Nondimensionalized coeffs.
114  m_g = (gms * SecondToDay * SecondToDay) / rad_earth;
115 
116  m_session->LoadParameter("RotationAngle", m_alpha, 0.0);
117  m_session->LoadParameter("u0", m_u0, 2.0 * m_pi / 12.0);
118  m_session->LoadParameter("Omega", Omegams, 7.292 * 0.00001);
119  m_Omega = Omegams * SecondToDay;
120 
121  m_session->LoadParameter("H0", m_H0, 2.94 * 10000);
122  m_H0 = m_H0 / (rad_earth * gms);
123 
124  m_Hvar = (1.0 / m_g) * (m_Omega * m_u0 + 0.5 * m_u0 * m_u0);
125  }
126  break;
127 
128  case eTestUnsteadyZonal:
129  {
130  NekDouble SecondToDay = 60.0 * 60.0 * 24.0;
131  NekDouble rad_earth = 6.37122 * 1000000;
132  NekDouble Omegams;
133 
134  // Nondimensionalized coeffs.
135  m_g = (gms * SecondToDay * SecondToDay) / rad_earth;
136 
137  m_session->LoadParameter("RotationAngle", m_alpha, 0.0);
138  m_session->LoadParameter("u0", m_u0, 2.0 * m_pi / 12.0);
139  m_session->LoadParameter("Omega", Omegams, 7.292 * 0.00001);
140  m_Omega = Omegams * SecondToDay;
141 
142  m_H0 = 133681.0 / (rad_earth * gms); // m^2 / s^2
143  m_k2 = 10.0 / (rad_earth * gms); // m^2 / s^2
144  }
145  break;
146 
148  {
149  NekDouble SecondToDay = 60.0 * 60.0 * 24.0;
150  NekDouble rad_earth = 6.37122 * 1000000;
151  NekDouble Omegams;
152 
153  // Nondimensionalized coeffs.
154  m_g = (gms * SecondToDay * SecondToDay) / rad_earth;
155 
156  m_session->LoadParameter("RotationAngle", m_alpha, 0.0);
157 
158  m_session->LoadParameter("u0", m_u0, 20.0);
159  m_u0 = m_u0 * SecondToDay / rad_earth;
160 
161  m_session->LoadParameter("Omega", Omegams, 7.292 * 0.00001);
162  m_Omega = Omegams * SecondToDay;
163 
164  m_H0 = 5960.0 / rad_earth;
165  m_hs0 = 2000.0 / rad_earth;
166  }
167  break;
168 
169  case eTestUnstableJet:
170  {
171  NekDouble SecondToDay = 60.0 * 60.0 * 24.0;
172  NekDouble rad_earth = 6.37122 * 1000000;
173  NekDouble Omegams;
174 
175  // Nondimensionalized coeffs.
176  m_g = (gms * SecondToDay * SecondToDay) / rad_earth;
177 
178  m_session->LoadParameter("u0", m_u0, 80.0);
179  m_u0 = m_u0 * SecondToDay / rad_earth;
180 
181  m_session->LoadParameter("Omega", Omegams, 7.292 * 0.00001);
182  m_Omega = Omegams * SecondToDay;
183 
184  m_session->LoadParameter("H0", m_H0, 10000.0);
185  m_H0 = m_H0 / rad_earth;
186 
187  m_uthetamax = 80 * SecondToDay / rad_earth;
188  m_theta0 = m_pi / 7.0;
189  m_theta1 = m_pi / 2.0 - m_theta0;
190  m_en = exp(-4.0 / (m_theta1 - m_theta0) / (m_theta1 - m_theta0));
191  m_hbar = 120.0 / rad_earth;
192 
193  std::cout << "m_theta0 = " << m_theta0 << ", m_theta1 = " << m_theta1
194  << ", m_en = " << m_en << ", m_hbar = " << m_hbar
195  << std::endl;
196  }
197  break;
198 
199  case eTestRossbyWave:
200  {
201  NekDouble SecondToDay = 60.0 * 60.0 * 24.0;
202  NekDouble rad_earth = 6.37122 * 1000000;
203  NekDouble Omegams;
204 
205  // Nondimensionalized coeffs.
206  m_g = (gms * SecondToDay * SecondToDay) / rad_earth;
207 
208  m_session->LoadParameter("Omega", Omegams, 7.292 * 0.00001);
209  m_Omega = Omegams * SecondToDay;
210 
211  m_session->LoadParameter("H0", m_H0, 8000.0);
212  m_H0 = m_H0 / rad_earth;
213 
214  m_angfreq = 7.848 * 0.000001 * SecondToDay;
215  m_K = 7.848 * 0.000001 * SecondToDay;
216  }
217  break;
218 
219  default:
220  break;
221  }
222 
223  // TestVorticityComputation
225  {
227  }
228 
229  // If explicit it computes RHS and PROJECTION for the time integration
231  {
234  }
235  // Otherwise it gives an error (no implicit integration)
236  else
237  {
238  ASSERTL0(false, "Implicit unsteady Advection not set up.");
239  }
240 }
241 
242 /**
243  * @brief Unsteady linear advection equation destructor.
244  */
246 {
247 }
248 
250 {
251  ASSERTL0(m_intScheme != 0, "No time integration scheme.");
252 
253  int i, nchk = 1;
254  int nvariables = 0;
255  int nfields = m_fields.size();
256  int nq = m_fields[0]->GetNpoints();
257 
258  if (m_intVariables.empty())
259  {
260  for (i = 0; i < nfields; ++i)
261  {
262  m_intVariables.push_back(i);
263  }
264  nvariables = nfields;
265  }
266  else
267  {
268  nvariables = m_intVariables.size();
269  }
270 
271  // Set up wrapper to fields data storage.
272  Array<OneD, Array<OneD, NekDouble>> fields(nvariables);
273  Array<OneD, Array<OneD, NekDouble>> tmp(nvariables);
274 
275  // Order storage to list time-integrated fields first.
276  for (i = 0; i < nvariables; ++i)
277  {
278  fields[i] = m_fields[m_intVariables[i]]->GetPhys();
279  m_fields[m_intVariables[i]]->SetPhysState(false);
280  }
281 
282  // Initialise time integration scheme
283  m_intScheme->InitializeScheme(m_timestep, fields, m_time, m_ode);
284 
285  // Check uniqueness of checkpoint output
286  ASSERTL0((m_checktime == 0.0 && m_checksteps == 0) ||
287  (m_checktime > 0.0 && m_checksteps == 0) ||
288  (m_checktime == 0.0 && m_checksteps > 0),
289  "Only one of IO_CheckTime and IO_CheckSteps "
290  "should be set!");
291 
292  LibUtilities::Timer timer;
293  bool doCheckTime = false;
294  int step = 0;
295  NekDouble intTime = 0.0;
296  NekDouble cpuTime = 0.0;
297  NekDouble elapsed = 0.0;
298 
299  NekDouble Mass = 0.0, Energy = 0.0, Enstrophy = 0.0, Vorticity = 0.0;
300  Array<OneD, NekDouble> zeta(nq);
301  Array<OneD, Array<OneD, NekDouble>> fieldsprimitive(nvariables);
302  for (int i = 0; i < nvariables; ++i)
303  {
304  fieldsprimitive[i] = Array<OneD, NekDouble>(nq);
305  }
306 
307  while (step < m_steps || m_time < m_fintime - NekConstants::kNekZeroTol)
308  {
309  timer.Start();
310  fields = m_intScheme->TimeIntegrate(step, m_timestep, m_ode);
311  timer.Stop();
312 
313  m_time += m_timestep;
314  elapsed = timer.TimePerTest(1);
315  intTime += elapsed;
316  cpuTime += elapsed;
317 
318  // Write out status information
319  if (m_session->GetComm()->GetRank() == 0 && !((step + 1) % m_infosteps))
320  {
321  std::cout << "Steps: " << std::setw(8) << std::left << step + 1 << " "
322  << "Time: " << std::setw(12) << std::left << m_time;
323 
324  std::stringstream ss;
325  ss << cpuTime << "s";
326  std::cout << " CPU Time: " << std::setw(8) << std::left << ss.str()
327  << std::endl;
328 
329  // Printout Mass, Energy, Enstrophy
330  ConservativeToPrimitive(fields, fieldsprimitive);
331 
332  // Vorticity zeta
333  ComputeVorticity(fieldsprimitive[1], fieldsprimitive[2], zeta);
334  Vorticity =
335  std::abs(m_fields[0]->Integral(zeta) - m_Vorticity0);
336 
337  // Masss = h^*
338  Mass = (ComputeMass(fieldsprimitive[0]) - m_Mass0) / m_Mass0;
339 
340  // Energy = 0.5*( h^*(u^2 + v^2) + g ( h^2 - h_s^s ) )
341  Energy = (ComputeEnergy(fieldsprimitive[0], fieldsprimitive[1],
342  fieldsprimitive[2]) -
343  m_Energy0) /
344  m_Energy0;
345 
346  // Enstrophy = 0.5/h^* ( \mathbf{k} \cdot (\nabla \times \mathbf{v}
347  // ) + f )^2
348  Enstrophy =
349  (ComputeEnstrophy(fieldsprimitive[0], fieldsprimitive[1],
350  fieldsprimitive[2]) -
351  m_Enstrophy0) /
352  m_Enstrophy0;
353 
354  std::cout << "dMass = " << std::setw(8) << std::left << Mass << " "
355  << ", dEnergy = " << std::setw(8) << std::left << Energy
356  << " "
357  << ", dEnstrophy = " << std::setw(8) << std::left
358  << Enstrophy << " "
359  << ", dVorticity = " << std::setw(8) << std::left
360  << Vorticity << std::endl
361  << std::endl;
362 
363  cpuTime = 0.0;
364  }
365 
366  // (h, hu, hv) -> (\eta, u, v)
368 
369  // Transform data into coefficient space
370  for (i = 0; i < nvariables; ++i)
371  {
372  m_fields[m_intVariables[i]]->SetPhys(fields[i]);
373  m_fields[m_intVariables[i]]->FwdTrans_IterPerExp(
374  fields[i], m_fields[m_intVariables[i]]->UpdateCoeffs());
375  m_fields[m_intVariables[i]]->SetPhysState(false);
376  }
377 
378  // Write out checkpoint files
379  if ((m_checksteps && step && !((step + 1) % m_checksteps)) ||
380  doCheckTime)
381  {
382  Checkpoint_Output(nchk++);
383  doCheckTime = false;
384 
385  // (\eta, u, v) -> (h, hu, hv)
387  }
388 
389  // Step advance
390  ++step;
391  }
392 
393  // Print out summary statistics
394  if (m_session->GetComm()->GetRank() == 0)
395  {
396  if (m_cflSafetyFactor > 0.0)
397  {
398  std::cout << "CFL safety factor : " << m_cflSafetyFactor << std::endl
399  << "CFL time-step : " << m_timestep << std::endl;
400  }
401 
402  if (m_session->GetSolverInfo("Driver") != "SteadyState")
403  {
404  std::cout << "Time-integration : " << intTime << "s" << std::endl;
405  }
406  }
407 
408  for (i = 0; i < nvariables; ++i)
409  {
410  m_fields[m_intVariables[i]]->SetPhys(fields[i]);
411  m_fields[m_intVariables[i]]->SetPhysState(true);
412  }
413 
414  // (h, hu, hv) -> (\eta, u, v)
416 
417  for (i = 0; i < nvariables; ++i)
418  {
419  m_fields[i]->FwdTrans(m_fields[i]->GetPhys(),
420  m_fields[i]->UpdateCoeffs());
421  }
422 }
423 
424 void MMFSWE::DoOdeRhs(const Array<OneD, const Array<OneD, NekDouble>> &inarray,
425  Array<OneD, Array<OneD, NekDouble>> &outarray,
426  const NekDouble time)
427 {
428  boost::ignore_unused(time);
429 
430  int i;
431  int nvariables = inarray.size();
432  int ncoeffs = GetNcoeffs();
433  int nq = GetTotPoints();
434 
435  // inarray in physical space
436  Array<OneD, Array<OneD, NekDouble>> physarray(nvariables);
437  Array<OneD, Array<OneD, NekDouble>> modarray(nvariables);
438 
439  for (i = 0; i < nvariables; ++i)
440  {
441  physarray[i] = Array<OneD, NekDouble>(nq);
442  modarray[i] = Array<OneD, NekDouble>(ncoeffs);
443  }
444 
445  // (h, hu, hv) -> (\eta, u, v)
446  ConservativeToPrimitive(inarray, physarray);
447 
448  // Weak Directional Derivative
449  WeakDGSWEDirDeriv(physarray, modarray);
450  AddDivForGradient(physarray, modarray);
451 
452  for (i = 0; i < nvariables; ++i)
453  {
454  Vmath::Neg(ncoeffs, modarray[i], 1);
455  }
456 
457  // coriolis forcing
458  if (m_AddCoriolis)
459  {
460  AddCoriolis(physarray, modarray);
461  }
462 
463  // Bottom Elevation Effect
464  // Add g H \nabla m_depth
465  AddElevationEffect(physarray, modarray);
466 
467  // Add terms concerning the rotation of the moving frame
468  if (m_AddRotation)
469  {
470  AddRotation(physarray, modarray);
471  }
472 
473  for (i = 0; i < nvariables; ++i)
474  {
475  m_fields[i]->MultiplyByElmtInvMass(modarray[i], modarray[i]);
476  m_fields[i]->BwdTrans(modarray[i], outarray[i]);
477  }
478 }
479 
481  const Array<OneD, Array<OneD, NekDouble>> &InField,
482  Array<OneD, Array<OneD, NekDouble>> &OutField)
483 {
484  int i;
485  int nq = GetNpoints();
486  int ncoeffs = GetNcoeffs();
487  int nTracePointsTot = GetTraceNpoints();
488  int nvariables = m_fields.size();
489 
491  Array<OneD, Array<OneD, NekDouble>> physfield(nvariables);
492 
493  for (i = 0; i < m_shapedim; ++i)
494  {
495  fluxvector[i] = Array<OneD, NekDouble>(nq);
496  }
497 
498  // InField is Primitive
499  for (i = 0; i < nvariables; ++i)
500  {
501  physfield[i] = InField[i];
502  }
503 
504  // Get the ith component of the flux vector in (physical space)
505  // fluxvector[0] = component for e^1 cdot \nabla \varphi
506  // fluxvector[1] = component for e^2 cdot \nabla \varphi
507  Array<OneD, NekDouble> fluxtmp(nq);
508  Array<OneD, NekDouble> tmp(ncoeffs);
509 
510  // Compute Divergence Components
511  for (i = 0; i < nvariables; ++i)
512  {
513  GetSWEFluxVector(i, physfield, fluxvector);
514 
515  OutField[i] = Array<OneD, NekDouble>(ncoeffs, 0.0);
516  for (int j = 0; j < m_shapedim; ++j)
517  {
518  // Directional derivation with respect to the j'th moving frame
519  // tmp_j = ( \nabla \phi, fluxvector[j] \mathbf{e}^j )
520  m_fields[i]->IProductWRTDirectionalDerivBase(m_movingframes[j],
521  fluxvector[j], tmp);
522  Vmath::Vadd(ncoeffs, &tmp[0], 1, &OutField[i][0], 1,
523  &OutField[i][0], 1);
524  }
525  }
526 
527  // Numerical Flux
528  Array<OneD, Array<OneD, NekDouble>> numfluxFwd(nvariables);
529  Array<OneD, Array<OneD, NekDouble>> numfluxBwd(nvariables);
530 
531  for (i = 0; i < nvariables; ++i)
532  {
533  numfluxFwd[i] = Array<OneD, NekDouble>(nTracePointsTot);
534  numfluxBwd[i] = Array<OneD, NekDouble>(nTracePointsTot);
535  }
536 
537  NumericalSWEFlux(physfield, numfluxFwd, numfluxBwd);
538 
539  // Evaulate <\phi, \hat{F}\cdot n> - OutField[i]
540  for (i = 0; i < nvariables; ++i)
541  {
542  Vmath::Neg(ncoeffs, OutField[i], 1);
543  m_fields[i]->AddFwdBwdTraceIntegral(numfluxFwd[i], numfluxBwd[i],
544  OutField[i]);
545  m_fields[i]->SetPhysState(false);
546  }
547 }
548 
549 // Substract 0.5 * g * H * H / || e^m ||^2 \nalba \cdot e^m
551  Array<OneD, Array<OneD, NekDouble>> &outarray)
552 {
553  // routine works for both primitive and conservative formulations
554  int ncoeffs = outarray[0].size();
555  int nq = physarray[0].size();
556 
558  Array<OneD, NekDouble> tmp(nq);
560  for (int i = 0; i < m_shapedim; ++i)
561  {
562  fluxvector[i] = Array<OneD, NekDouble>(nq);
563  }
564 
565  // Get 0.5 g H*H / || e^m ||^2
566  GetSWEFluxVector(3, physarray, fluxvector);
567 
568  Array<OneD, NekDouble> tmpc(ncoeffs);
569  for (int j = 0; j < m_shapedim; ++j)
570  {
571  Vmath::Vmul(nq, &fluxvector[0][0], 1, &m_DivMF[j][0], 1, &tmp[0], 1);
572 
573  Vmath::Neg(nq, &tmp[0], 1);
574  m_fields[0]->IProductWRTBase(tmp, tmpc);
575 
576  Vmath::Vadd(ncoeffs, outarray[j + 1], 1, tmpc, 1, outarray[j + 1], 1);
577  }
578 }
579 
581  const int i, const Array<OneD, const Array<OneD, NekDouble>> &physfield,
583 {
584  int nq = m_fields[0]->GetTotPoints();
585 
586  switch (i)
587  {
588  // flux function for the h equation = [(\eta + d ) u, (\eta + d) v ]
589  case 0:
590  {
591  // h in flux 1
592  Vmath::Vadd(nq, physfield[0], 1, m_depth, 1, flux[1], 1);
593 
594  // hu in flux 0
595  Vmath::Vmul(nq, flux[1], 1, physfield[1], 1, flux[0], 1);
596 
597  // hv in flux 1
598  Vmath::Vmul(nq, flux[1], 1, physfield[2], 1, flux[1], 1);
599  }
600  break;
601 
602  // flux function for the hu equation = [Hu^2 + 0.5 g H^2, Huv]
603  case 1:
604  {
605  Array<OneD, NekDouble> tmp(nq);
606 
607  // h in tmp
608  Vmath::Vadd(nq, physfield[0], 1, m_depth, 1, tmp, 1);
609 
610  // hu in flux 1
611  Vmath::Vmul(nq, tmp, 1, physfield[1], 1, flux[1], 1);
612 
613  // huu in flux 0
614  Vmath::Vmul(nq, flux[1], 1, physfield[1], 1, flux[0], 1);
615 
616  // hh in tmp
617  Vmath::Vmul(nq, tmp, 1, tmp, 1, tmp, 1);
618 
619  // huu + 0.5 g hh in flux 0
620  // Daxpy overwrites flux[0] on exit
621  Blas::Daxpy(nq, 0.5 * m_g, tmp, 1, flux[0], 1);
622 
623  // huv in flux 1
624  Vmath::Vmul(nq, flux[1], 1, physfield[2], 1, flux[1], 1);
625  }
626  break;
627 
628  // flux function for the hv equation = [Huv, Hv^2]
629  case 2:
630  {
631  Array<OneD, NekDouble> tmp(nq);
632 
633  // h in tmp
634  Vmath::Vadd(nq, physfield[0], 1, m_depth, 1, tmp, 1);
635 
636  // hv in flux 0
637  Vmath::Vmul(nq, tmp, 1, physfield[2], 1, flux[0], 1);
638 
639  // hvv in flux 1
640  Vmath::Vmul(nq, flux[0], 1, physfield[2], 1, flux[1], 1);
641 
642  // huv in flux 0
643  Vmath::Vmul(nq, flux[0], 1, physfield[1], 1, flux[0], 1);
644 
645  // hh in tmp
646  Vmath::Vmul(nq, tmp, 1, tmp, 1, tmp, 1);
647 
648  // hvv + 0.5 g hh in flux 1
649  Blas::Daxpy(nq, 0.5 * m_g, tmp, 1, flux[1], 1);
650  }
651  break;
652 
653  // flux function 0.5 g h * h
654  case 3:
655  {
657  flux[0] = Array<OneD, NekDouble>(nq, 0.0);
658 
659  // h in tmp
660  Vmath::Vadd(nq, physfield[0], 1, m_depth, 1, h, 1);
661 
662  // hh in tmp
663  Vmath::Vmul(nq, h, 1, h, 1, h, 1);
664 
665  // 0.5 g hh in flux 0
666  Blas::Daxpy(nq, 0.5 * m_g, h, 1, flux[0], 1);
667  }
668  break;
669 
670  default:
671  break;
672  }
673 }
674 
676  Array<OneD, Array<OneD, NekDouble>> &numfluxFwd,
677  Array<OneD, Array<OneD, NekDouble>> &numfluxBwd)
678 {
679 
680  int i, k;
681  int nTraceNumPoints = GetTraceTotPoints();
682  int nvariables = 3; // only the dependent variables
683 
684  // get temporary arrays
685  Array<OneD, Array<OneD, NekDouble>> Fwd(nvariables);
686  Array<OneD, Array<OneD, NekDouble>> Bwd(nvariables);
687  Array<OneD, NekDouble> DepthFwd(nTraceNumPoints);
688  Array<OneD, NekDouble> DepthBwd(nTraceNumPoints);
689 
690  for (i = 0; i < nvariables; ++i)
691  {
692  Fwd[i] = Array<OneD, NekDouble>(nTraceNumPoints);
693  Bwd[i] = Array<OneD, NekDouble>(nTraceNumPoints);
694  }
695 
696  // get the physical values at the trace
697  for (i = 0; i < nvariables; ++i)
698  {
699  m_fields[i]->GetFwdBwdTracePhys(physfield[i], Fwd[i], Bwd[i]);
700 
701  // Copy Fwd to Bwd at boundaries
702  CopyBoundaryTrace(Fwd[i], Bwd[i], SolverUtils::eFwdEQBwd);
703  }
704  m_fields[0]->GetFwdBwdTracePhys(m_depth, DepthFwd, DepthBwd);
705  CopyBoundaryTrace(DepthFwd, DepthBwd, SolverUtils::eFwdEQBwd);
706 
707  // note that we are using the same depth - i.e. the depth is assumed
708  // continuous...
709  switch (m_upwindType)
710  {
711  case SolverUtils::eHLLC:
712  {
713  // rotate the values to the normal direction
714  NekDouble tmpX, tmpY;
715 
716  // Fwd[1] = hu^+ = ( h^1^+ (e^1 \cdot n) + h^2^+ ( e^2 \cdot n) )
717  // Fwd[2] = hv^+ = ( h^1^+ (e^1 \cdot n^{\perp}) + h^2^+ ( e^2 \cdot
718  // n^{\perp}) )
719  // Bwd[1] = hu^- = ( h^1^- (e^1 \cdot n) + h^2^- ( e^2 \cdot n) )
720  // Bwd[2] = hv^- = ( h^1^- (e^1 \cdot n^{\perp}) + h^2^- ( e^2 \cdot
721  // n^{\perp}) )
722 
723  for (k = 0; k < nTraceNumPoints; ++k)
724  {
725  tmpX = Fwd[1][k] * m_ncdotMFFwd[0][k] +
726  Fwd[2][k] * m_ncdotMFFwd[1][k];
727  tmpY = Fwd[1][k] * m_nperpcdotMFFwd[0][k] +
728  Fwd[2][k] * m_nperpcdotMFFwd[1][k];
729  Fwd[1][k] = tmpX;
730  Fwd[2][k] = tmpY;
731 
732  tmpX = Bwd[1][k] * m_ncdotMFBwd[0][k] +
733  Bwd[2][k] * m_ncdotMFBwd[1][k];
734  tmpY = Bwd[1][k] * m_nperpcdotMFBwd[0][k] +
735  Bwd[2][k] * m_nperpcdotMFBwd[1][k];
736  Bwd[1][k] = tmpX;
737  Bwd[2][k] = tmpY;
738  }
739 
740  // Solve the Riemann problem
741  NekDouble denomFwd, denomBwd;
742  Array<OneD, NekDouble> numfluxF(nvariables);
743  Array<OneD, NekDouble> numfluxB(nvariables);
744 
745  NekDouble eF1n, eF2n, eB1n, eB2n;
746  NekDouble eF1t, eF2t, eB1t, eB2t;
747  for (k = 0; k < nTraceNumPoints; ++k)
748  {
749  RiemannSolverHLLC(k, Fwd[0][k] + DepthFwd[k], Fwd[1][k],
750  Fwd[2][k], Bwd[0][k] + DepthFwd[k], Bwd[1][k],
751  Bwd[2][k], numfluxF, numfluxB);
752 
753  // uflux = 1/[ ( e^1 \cdot n) ( e^2 \cdot n^{\perp} ) - (e^2
754  // \cdot n)(e^1 \cdot n^{\perp} ) ] ( e^2 \cdot n^{\perp} huflux
755  // - e^2 \cdot n hvflux
756  // vflux = -1/[ ( e^1 \cdot n) ( e^2 \cdot n^{\perp} ) - (e^2
757  // \cdot n)(e^1 \cdot n^{\perp} ) ] ( -e^1 \cdot n^{\perp}
758  // huflux + e^1 \cdot n hvflux
759  eF1n = m_ncdotMFFwd[0][k];
760  eF2n = m_ncdotMFFwd[1][k];
761  eB1n = m_ncdotMFBwd[0][k];
762  eB2n = m_ncdotMFBwd[1][k];
763 
764  eF1t = m_nperpcdotMFFwd[0][k];
765  eF2t = m_nperpcdotMFFwd[1][k];
766  eB1t = m_nperpcdotMFBwd[0][k];
767  eB2t = m_nperpcdotMFBwd[1][k];
768 
769  denomFwd = eF1n * eF2t - eF2n * eF1t;
770  denomBwd = eB1n * eB2t - eB2n * eB1t;
771 
772  numfluxFwd[0][k] = numfluxF[0];
773  numfluxFwd[1][k] = (1.0 / denomFwd) *
774  (eF2t * numfluxF[1] - eF2n * numfluxF[2]);
775  numfluxFwd[2][k] =
776  (1.0 / denomFwd) *
777  (-1.0 * eF1t * numfluxF[1] + eF1n * numfluxF[2]);
778 
779  numfluxBwd[0][k] = 1.0 * numfluxB[0];
780  numfluxBwd[1][k] = (1.0 / denomBwd) *
781  (eB2t * numfluxB[1] - eB2n * numfluxB[2]);
782  numfluxBwd[2][k] =
783  (1.0 / denomBwd) *
784  (-1.0 * eB1t * numfluxB[1] + eB1n * numfluxB[2]);
785  }
786  }
787  break;
788 
792  {
793  Array<OneD, NekDouble> numfluxF(nvariables * (m_shapedim + 1));
794  Array<OneD, NekDouble> numfluxB(nvariables * (m_shapedim + 1));
795 
796  for (k = 0; k < nTraceNumPoints; ++k)
797  {
799  {
800  AverageFlux(k, Fwd[0][k] + DepthFwd[k], Fwd[1][k],
801  Fwd[2][k], Bwd[0][k] + DepthFwd[k], Bwd[1][k],
802  Bwd[2][k], numfluxF, numfluxB);
803  }
804 
806  {
807  LaxFriedrichFlux(k, Fwd[0][k] + DepthFwd[k], Fwd[1][k],
808  Fwd[2][k], Bwd[0][k] + DepthFwd[k],
809  Bwd[1][k], Bwd[2][k], numfluxF, numfluxB);
810  }
811 
813  {
814  RusanovFlux(k, Fwd[0][k] + DepthFwd[k], Fwd[1][k],
815  Fwd[2][k], Bwd[0][k] + DepthFwd[k], Bwd[1][k],
816  Bwd[2][k], numfluxF, numfluxB);
817  }
818 
819  int indx;
820  NekDouble tmpF0, tmpF1, tmpB0, tmpB1;
821  for (i = 0; i < nvariables; ++i)
822  {
823  indx = i * (m_shapedim + 1);
824 
825  tmpF0 = numfluxF[indx] * m_ncdotMFFwd[0][k];
826  tmpF1 = numfluxF[indx + 1] * m_ncdotMFFwd[1][k];
827 
828  tmpB0 = numfluxB[indx] * m_ncdotMFBwd[0][k];
829  tmpB1 = numfluxB[indx + 1] * m_ncdotMFBwd[1][k];
830 
831  numfluxFwd[i][k] = tmpF0 + tmpF1 + numfluxF[indx + 2];
832  numfluxBwd[i][k] = tmpB0 + tmpB1 + numfluxB[indx + 2];
833  }
834  }
835  }
836  break;
837 
838  default:
839  {
840  ASSERTL0(false, "populate switch statement for upwind flux");
841  }
842  break;
843  }
844 }
845 
846 void MMFSWE::RiemannSolverHLLC(const int index, NekDouble hL, NekDouble uL,
847  NekDouble vL, NekDouble hR, NekDouble uR,
848  NekDouble vR, Array<OneD, NekDouble> &numfluxF,
849  Array<OneD, NekDouble> &numfluxB)
850 {
851  boost::ignore_unused(index);
852 
853  NekDouble g = m_g;
854 
855  NekDouble cL = sqrt(g * hL);
856  NekDouble cR = sqrt(g * hR);
857 
858  NekDouble uRF, vRF, uLB, vLB;
859  NekDouble hstarF, hstarB;
860 
861  // Temporary assignments
862  uRF = uR;
863  vRF = vR;
864  uLB = uL;
865  vLB = vL;
866 
867  // the two-rarefaction wave assumption
868  hstarF = 0.5 * (cL + cR) + 0.25 * (uL - uRF);
869  hstarF *= hstarF;
870  hstarF *= (1.0 / g);
871 
872  hstarB = 0.5 * (cL + cR) + 0.25 * (uLB - uR);
873  hstarB *= hstarB;
874  hstarB *= (1.0 / g);
875 
876  NekDouble hfluxF, hufluxF, hvfluxF;
877  NekDouble hfluxB, hufluxB, hvfluxB;
878  Computehhuhvflux(hL, uL, vL, hR, uRF, vRF, hstarF, hfluxF, hufluxF,
879  hvfluxF);
880  Computehhuhvflux(hL, uLB, vLB, hR, uR, vR, hstarB, hfluxB, hufluxB,
881  hvfluxB);
882 
883  numfluxF[0] = hfluxF;
884  numfluxF[1] = hufluxF;
885  numfluxF[2] = hvfluxF;
886 
887  numfluxB[0] = hfluxB;
888  numfluxB[1] = hufluxB;
889  numfluxB[2] = hvfluxB;
890 }
891 
893  NekDouble hR, NekDouble uR, NekDouble vR,
894  NekDouble hstar, NekDouble &hflux,
895  NekDouble &huflux, NekDouble &hvflux)
896 {
897  NekDouble g = m_g;
898 
899  NekDouble hC, huC, hvC, SL, SR, Sstar;
900  NekDouble cL = sqrt(g * hL);
901  NekDouble cR = sqrt(g * hR);
902 
903  // Compute SL
904  if (hstar > hL)
905  SL = uL - cL * sqrt(0.5 * ((hstar * hstar + hstar * hL) / (hL * hL)));
906  else
907  SL = uL - cL;
908 
909  // Compute SR
910  if (hstar > hR)
911  SR = uR + cR * sqrt(0.5 * ((hstar * hstar + hstar * hR) / (hR * hR)));
912  else
913  SR = uR + cR;
914 
915  if (fabs(hR * (uR - SR) - hL * (uL - SL)) <= 1.0e-15)
916  Sstar = 0.0;
917  else
918  Sstar = (SL * hR * (uR - SR) - SR * hL * (uL - SL)) /
919  (hR * (uR - SR) - hL * (uL - SL));
920 
921  if (SL >= 0)
922  {
923  hflux = hL * uL;
924  huflux = uL * uL * hL + 0.5 * g * hL * hL;
925  hvflux = hL * uL * vL;
926  }
927  else if (SR <= 0)
928  {
929  hflux = hR * uR;
930  huflux = uR * uR * hR + 0.5 * g * hR * hR;
931  hvflux = hR * uR * vR;
932  }
933  else
934  {
935  if ((SL < 0) && (Sstar >= 0))
936  {
937  hC = hL * ((SL - uL) / (SL - Sstar));
938  huC = hC * Sstar;
939  hvC = hC * vL;
940 
941  hflux = hL * uL + SL * (hC - hL);
942  huflux = (uL * uL * hL + 0.5 * g * hL * hL) + SL * (huC - hL * uL);
943  hvflux = (uL * vL * hL) + SL * (hvC - hL * vL);
944  }
945  else
946  {
947  hC = hR * ((SR - uR) / (SR - Sstar));
948  huC = hC * Sstar;
949  hvC = hC * vR;
950 
951  hflux = hR * uR + SR * (hC - hR);
952  huflux = (uR * uR * hR + 0.5 * g * hR * hR) + SR * (huC - hR * uR);
953  hvflux = (uR * vR * hR) + SR * (hvC - hR * vR);
954  }
955  }
956 }
957 
958 void MMFSWE::AverageFlux(const int index, NekDouble hL, NekDouble uL,
959  NekDouble vL, NekDouble hR, NekDouble uR, NekDouble vR,
960  Array<OneD, NekDouble> &numfluxF,
961  Array<OneD, NekDouble> &numfluxB)
962 {
963  NekDouble MageF1, MageF2, MageB1, MageB2;
964  NekDouble eF1_cdot_eB1, eF1_cdot_eB2;
965  NekDouble eF2_cdot_eB1, eF2_cdot_eB2;
966 
967  NekDouble g = m_g;
968  NekDouble uRF, vRF, uLB, vLB;
969 
970  ComputeMagAndDot(index, MageF1, MageF2, MageB1, MageB2, eF1_cdot_eB1,
971  eF1_cdot_eB2, eF2_cdot_eB1, eF2_cdot_eB2);
972 
973  // uRF = uR component in moving frames e^{Fwd}
974  // vRF = vR component in moving frames e^{Fwd}
975  uRF = (uR * eF1_cdot_eB1 + vR * eF1_cdot_eB2) / MageF1;
976  vRF = (uR * eF2_cdot_eB1 + vR * eF2_cdot_eB2) / MageF2;
977 
978  numfluxF[0] = 0.5 * (hL * uL + hR * uRF);
979  numfluxF[1] = 0.5 * (hL * vL + hR * vRF);
980  numfluxF[2] = 0.0;
981 
982  numfluxF[3] =
983  0.5 * (hL * uL * uL + hR * uRF * uRF + 0.5 * g * (hL * hL + hR * hR));
984  numfluxF[4] = 0.5 * (hL * uL * vL + hR * uRF * vRF);
985  numfluxF[5] = 0.0;
986 
987  numfluxF[6] = 0.5 * (hL * uL * vL + hR * uRF * vRF);
988  numfluxF[7] =
989  0.5 * (hL * vL * vL + hR * vRF * vRF + 0.5 * g * (hL * hL + hR * hR));
990  numfluxF[8] = 0.0;
991 
992  // uLB = uL component in moving frames e^{Bwd}
993  // vLB = vL component in moving frames e^{Bwd}
994  uLB = (uL * eF1_cdot_eB1 + vL * eF2_cdot_eB1) / MageB1;
995  vLB = (uL * eF1_cdot_eB2 + vL * eF2_cdot_eB2) / MageB2;
996 
997  numfluxB[0] = 0.5 * (hR * uR + hR * uLB);
998  numfluxB[1] = 0.5 * (hR * vR + hR * vLB);
999  numfluxB[2] = 0.0;
1000 
1001  numfluxB[3] =
1002  0.5 * (hR * uR * uR + hR * uLB * uLB + 0.5 * g * (hR * hR + hL * hL));
1003  numfluxB[4] = 0.5 * (hR * uR * vR + hR * uLB * vLB);
1004  numfluxB[5] = 0.0;
1005 
1006  numfluxB[6] = 0.5 * (hR * uR * vR + hR * uLB * vLB);
1007  numfluxB[7] =
1008  0.5 * (hR * vR * vR + hR * vLB * vLB + 0.5 * g * (hR * hR + hL * hL));
1009  numfluxB[8] = 0.0;
1010 }
1011 
1012 void MMFSWE::LaxFriedrichFlux(const int index, NekDouble hL, NekDouble uL,
1013  NekDouble vL, NekDouble hR, NekDouble uR,
1014  NekDouble vR, Array<OneD, NekDouble> &numfluxF,
1015  Array<OneD, NekDouble> &numfluxB)
1016 {
1017  int nvariables = 3;
1018  NekDouble MageF1, MageF2, MageB1, MageB2;
1019  NekDouble eF1_cdot_eB1, eF1_cdot_eB2;
1020  NekDouble eF2_cdot_eB1, eF2_cdot_eB2;
1021 
1022  NekDouble g = m_g;
1023  NekDouble uRF, vRF, uLB, vLB;
1024  NekDouble velL, velR, lambdaF, lambdaB;
1025 
1026  Array<OneD, NekDouble> EigF(nvariables);
1027  Array<OneD, NekDouble> EigB(nvariables);
1028 
1029  // Compute Magnitude and Dot product of moving frames for the index
1030  ComputeMagAndDot(index, MageF1, MageF2, MageB1, MageB2, eF1_cdot_eB1,
1031  eF1_cdot_eB2, eF2_cdot_eB1, eF2_cdot_eB2);
1032 
1033  // Get the velocity in the normal to the edge
1034  velL = uL * m_ncdotMFFwd[0][index] + vL * m_ncdotMFFwd[1][index];
1035  velR = -1.0 * (uR * m_ncdotMFBwd[0][index] + vR * m_ncdotMFBwd[1][index]);
1036 
1037  EigF[0] = velL - sqrt(g * hL);
1038  EigF[1] = velL;
1039  EigF[2] = velL + sqrt(g * hL);
1040 
1041  EigB[0] = velR - sqrt(g * hR);
1042  EigB[1] = velR;
1043  EigB[2] = velR + sqrt(g * hR);
1044 
1045  lambdaF = Vmath::Vamax(nvariables, EigF, 1);
1046  lambdaB = Vmath::Vamax(nvariables, EigB, 1);
1047 
1048  // uRF = uR component in moving frames e^{Fwd}
1049  // vRF = vR component in moving frames e^{Fwd}
1050  uRF = (uR * eF1_cdot_eB1 + vR * eF1_cdot_eB2) / MageF1;
1051  vRF = (uR * eF2_cdot_eB1 + vR * eF2_cdot_eB2) / MageF2;
1052 
1053  numfluxF[0] = 0.5 * (hL * uL + hR * uRF);
1054  numfluxF[1] = 0.5 * (hL * vL + hR * vRF);
1055  numfluxF[2] = 0.5 * lambdaF * (hL - hR);
1056 
1057  numfluxF[3] = 0.5 * (hL * uL * uL * MageF1 + hR * uRF * uRF * MageB1 +
1058  0.5 * g * (hL * hL + hR * hR));
1059  numfluxF[4] = 0.5 * (hL * uL * vL * MageF1 + hR * uRF * vRF * MageB1);
1060  numfluxF[5] = 0.5 * lambdaF * (uL * hL - uRF * hR);
1061 
1062  numfluxF[6] = 0.5 * (hL * uL * vL * MageF2 + hR * uRF * vRF * MageB2);
1063  numfluxF[7] = 0.5 * (hL * vL * vL * MageF2 + hR * vRF * vRF * MageB2 +
1064  0.5 * g * (hL * hL + hR * hR));
1065  numfluxF[8] = 0.5 * lambdaF * (vL * hL - vRF * hR);
1066 
1067  // uLB = uL component in moving frames e^{Bwd}
1068  // vLB = vL component in moving frames e^{Bwd}
1069  uLB = (uL * eF1_cdot_eB1 + vL * eF2_cdot_eB1) / MageB1;
1070  vLB = (uL * eF1_cdot_eB2 + vL * eF2_cdot_eB2) / MageB2;
1071 
1072  numfluxB[0] = 0.5 * (hR * uR + hR * uLB);
1073  numfluxB[1] = 0.5 * (hR * vR + hR * vLB);
1074  numfluxB[2] = 0.5 * lambdaB * (hL - hR);
1075 
1076  numfluxB[3] = 0.5 * (hR * uR * uR * MageB1 + hR * uLB * uLB * MageF1 +
1077  0.5 * g * (hR * hR + hL * hL));
1078  numfluxB[4] = 0.5 * (hR * uR * vR * MageB1 + hR * uLB * vLB * MageF1);
1079  numfluxB[5] = 0.5 * lambdaB * (uLB * hL - uR * hR);
1080 
1081  numfluxB[6] = 0.5 * (hR * uR * vR * MageB2 + hR * uLB * vLB * MageF2);
1082  numfluxB[7] = 0.5 * (hR * vR * vR * MageB2 + hR * vLB * vLB * MageF2 +
1083  0.5 * g * (hR * hR + hL * hL));
1084  numfluxB[8] = 0.5 * lambdaB * (vLB * hL - vR * hR);
1085 }
1086 
1087 void MMFSWE::RusanovFlux(const int index, NekDouble hL, NekDouble uL,
1088  NekDouble vL, NekDouble hR, NekDouble uR, NekDouble vR,
1089  Array<OneD, NekDouble> &numfluxF,
1090  Array<OneD, NekDouble> &numfluxB)
1091 {
1092  int nvariables = 3;
1093  NekDouble MageF1, MageF2, MageB1, MageB2;
1094  NekDouble eF1_cdot_eB1, eF1_cdot_eB2;
1095  NekDouble eF2_cdot_eB1, eF2_cdot_eB2;
1096 
1097  NekDouble g = m_g;
1098  NekDouble uRF, vRF, uLB, vLB;
1099  NekDouble velL, velR;
1100 
1101  Array<OneD, NekDouble> EigF(nvariables);
1102  Array<OneD, NekDouble> EigB(nvariables);
1103 
1104  // Compute Magnitude and Dot product of moving frames for the index
1105  ComputeMagAndDot(index, MageF1, MageF2, MageB1, MageB2, eF1_cdot_eB1,
1106  eF1_cdot_eB2, eF2_cdot_eB1, eF2_cdot_eB2);
1107 
1108  // Get the velocity in the normal to the edge
1109  velL = uL * m_ncdotMFFwd[0][index] + vL * m_ncdotMFFwd[1][index];
1110  velR = -1.0 * (uR * m_ncdotMFBwd[0][index] + vR * m_ncdotMFBwd[1][index]);
1111 
1112  NekDouble SL, SR;
1113  SL = fabs(velL) + sqrt(g * hL);
1114  SR = fabs(velR) + sqrt(g * hR);
1115 
1116  NekDouble S;
1117  if (SL > SR)
1118  S = SL;
1119  else
1120  S = SR;
1121 
1122  // uRF = uR component in moving frames e^{Fwd}
1123  // vRF = vR component in moving frames e^{Fwd}
1124  uRF = (uR * eF1_cdot_eB1 + vR * eF1_cdot_eB2) / MageF1;
1125  vRF = (uR * eF2_cdot_eB1 + vR * eF2_cdot_eB2) / MageF2;
1126 
1127  numfluxF[0] = 0.5 * (hL * uL + hR * uRF);
1128  numfluxF[1] = 0.5 * (hL * vL + hR * vRF);
1129  numfluxF[2] = 0.5 * S * (hL - hR);
1130 
1131  numfluxF[3] =
1132  0.5 * (hL * uL * uL + hR * uRF * uRF + 0.5 * g * (hL * hL + hR * hR));
1133  numfluxF[4] = 0.5 * (hL * uL * vL + hR * uRF * vRF);
1134  numfluxF[5] = 0.5 * S * (uL * hL - uRF * hR);
1135 
1136  numfluxF[6] = 0.5 * (hL * uL * vL + hR * uRF * vRF);
1137  numfluxF[7] =
1138  0.5 * (hL * vL * vL + hR * vRF * vRF + 0.5 * g * (hL * hL + hR * hR));
1139  numfluxF[8] = 0.5 * S * (vL * hL - vRF * hR);
1140 
1141  // uLB = uL component in moving frames e^{Bwd}
1142  // vLB = vL component in moving frames e^{Bwd}
1143  uLB = (uL * eF1_cdot_eB1 + vL * eF2_cdot_eB1) / MageB1;
1144  vLB = (uL * eF1_cdot_eB2 + vL * eF2_cdot_eB2) / MageB2;
1145 
1146  numfluxB[0] = 0.5 * (hR * uR + hR * uLB);
1147  numfluxB[1] = 0.5 * (hR * vR + hR * vLB);
1148  numfluxB[2] = 0.5 * S * (hL - hR);
1149 
1150  numfluxB[3] =
1151  0.5 * (hR * uR * uR + hR * uLB * uLB + 0.5 * g * (hR * hR + hL * hL));
1152  numfluxB[4] = 0.5 * (hR * uR * vR + hR * uLB * vLB);
1153  numfluxB[5] = 0.5 * S * (uLB * hL - uR * hR);
1154 
1155  numfluxB[6] = 0.5 * (hR * uR * vR + hR * uLB * vLB);
1156  numfluxB[7] =
1157  0.5 * (hR * vR * vR + hR * vLB * vLB + 0.5 * g * (hR * hR + hL * hL));
1158  numfluxB[8] = 0.5 * S * (vLB * hL - vR * hR);
1159 }
1160 
1161 void MMFSWE::ComputeMagAndDot(const int index, NekDouble &MageF1,
1162  NekDouble &MageF2, NekDouble &MageB1,
1163  NekDouble &MageB2, NekDouble &eF1_cdot_eB1,
1164  NekDouble &eF1_cdot_eB2, NekDouble &eF2_cdot_eB1,
1165  NekDouble &eF2_cdot_eB2)
1166 {
1167  NekDouble MF1x, MF1y, MF1z, MF2x, MF2y, MF2z;
1168  NekDouble MB1x, MB1y, MB1z, MB2x, MB2y, MB2z;
1169 
1170  MF1x = m_MFtraceFwd[0][0][index];
1171  MF1y = m_MFtraceFwd[0][1][index];
1172  MF1z = m_MFtraceFwd[0][2][index];
1173 
1174  MF2x = m_MFtraceFwd[1][0][index];
1175  MF2y = m_MFtraceFwd[1][1][index];
1176  MF2z = m_MFtraceFwd[1][2][index];
1177 
1178  MB1x = m_MFtraceBwd[0][0][index];
1179  MB1y = m_MFtraceBwd[0][1][index];
1180  MB1z = m_MFtraceBwd[0][2][index];
1181 
1182  MB2x = m_MFtraceBwd[1][0][index];
1183  MB2y = m_MFtraceBwd[1][1][index];
1184  MB2z = m_MFtraceBwd[1][2][index];
1185 
1186  // MFtrace = MFtrace [ j*spacedim + k ], j = shape, k = sapce
1187  MageF1 = MF1x * MF1x + MF1y * MF1y + MF1z * MF1z;
1188  MageF2 = MF2x * MF2x + MF2y * MF2y + MF2z * MF2z;
1189  MageB1 = MB1x * MB1x + MB1y * MB1y + MB1z * MB1z;
1190  MageB2 = MB2x * MB2x + MB2y * MB2y + MB2z * MB2z;
1191 
1192  eF1_cdot_eB1 = MF1x * MB1x + MF1y * MB1y + MF1z * MB1z;
1193  eF1_cdot_eB2 = MF1x * MB2x + MF1y * MB2y + MF1z * MB2z;
1194  eF2_cdot_eB1 = MF2x * MB1x + MF2y * MB1y + MF2z * MB1z;
1195  eF2_cdot_eB2 = MF2x * MB2x + MF2y * MB2y + MF2z * MB2z;
1196 }
1197 
1198 // Add Coriolis factors
1200  Array<OneD, Array<OneD, NekDouble>> &outarray)
1201 {
1202  int ncoeffs = outarray[0].size();
1203  int nq = physarray[0].size();
1204 
1205  Array<OneD, NekDouble> h(nq);
1206  Array<OneD, NekDouble> tmp(nq);
1207  Array<OneD, NekDouble> tmpc(ncoeffs);
1208 
1209  // physarray is primitive
1210  // conservative formulation compute h
1211  // h = \eta + d
1212  Vmath::Vadd(nq, physarray[0], 1, m_depth, 1, h, 1);
1213 
1214  int indx = 0;
1215  for (int j = 0; j < m_shapedim; ++j)
1216  {
1217  if (j == 0)
1218  {
1219  indx = 2;
1220  }
1221 
1222  else if (j == 1)
1223  {
1224  indx = 1;
1225  }
1226 
1227  // add to hu equation
1228  Vmath::Vmul(nq, m_coriolis, 1, physarray[indx], 1, tmp, 1);
1229  Vmath::Vmul(nq, h, 1, tmp, 1, tmp, 1);
1230 
1231  if (j == 1)
1232  {
1233  Vmath::Neg(nq, tmp, 1);
1234  }
1235 
1236  // N \cdot (e^1 \times e^2 )
1237  // Vmath::Vmul(nq, &m_MF1crossMF2dotSN[0], 1, &tmp[0], 1, &tmp[0], 1);
1238  m_fields[0]->IProductWRTBase(tmp, tmpc);
1239  Vmath::Vadd(ncoeffs, tmpc, 1, outarray[j + 1], 1, outarray[j + 1], 1);
1240  }
1241 }
1242 
1243 // Compuate g H \nabla m_depth
1245  Array<OneD, Array<OneD, NekDouble>> &outarray)
1246 {
1247  int ncoeffs = outarray[0].size();
1248  int nq = physarray[0].size();
1249 
1250  Array<OneD, NekDouble> h(nq);
1251  Array<OneD, NekDouble> tmp(nq);
1252  Array<OneD, NekDouble> tmpc(ncoeffs);
1253 
1254  // physarray is primitive
1255  // conservative formulation compute h
1256  // h = \eta + d
1257  Vmath::Vadd(nq, physarray[0], 1, m_depth, 1, h, 1);
1258 
1259  for (int j = 0; j < m_shapedim; ++j)
1260  {
1261  Vmath::Vmul(nq, &h[0], 1, &m_Derivdepth[j][0], 1, &tmp[0], 1);
1262  Vmath::Smul(nq, m_g, tmp, 1, tmp, 1);
1263 
1264  m_fields[0]->IProductWRTBase(tmp, tmpc);
1265 
1266  Vmath::Vadd(ncoeffs, tmpc, 1, outarray[j + 1], 1, outarray[j + 1], 1);
1267  }
1268 }
1269 
1270 // =================================================
1271 // Add rotational factors
1272 // =================================================
1274  Array<OneD, Array<OneD, NekDouble>> &outarray)
1275 {
1276  // routine works for both primitive and conservative formulations
1277  int ncoeffs = outarray[0].size();
1278  int nq = physarray[0].size();
1279 
1280  // Compute h
1281  Array<OneD, NekDouble> h(nq);
1282  Vmath::Vadd(nq, &physarray[0][0], 1, &m_depth[0], 1, &h[0], 1);
1283 
1284  Array<OneD, NekDouble> de0dt_cdot_e0;
1285  Array<OneD, NekDouble> de0dt_cdot_e1;
1286  Array<OneD, NekDouble> de1dt_cdot_e0;
1287  Array<OneD, NekDouble> de1dt_cdot_e1;
1288  Compute_demdt_cdot_ek(0, 0, physarray, de0dt_cdot_e0);
1289  Compute_demdt_cdot_ek(1, 0, physarray, de1dt_cdot_e0);
1290  Compute_demdt_cdot_ek(0, 1, physarray, de0dt_cdot_e1);
1291  Compute_demdt_cdot_ek(1, 1, physarray, de1dt_cdot_e1);
1292 
1293  Array<OneD, NekDouble> Rott1(nq);
1294  Array<OneD, NekDouble> Rott2(nq);
1295  Vmath::Vmul(nq, physarray[1], 1, de0dt_cdot_e0, 1, Rott1, 1);
1296  Vmath::Vmul(nq, physarray[1], 1, de0dt_cdot_e1, 1, Rott2, 1);
1297  Vmath::Vvtvp(nq, physarray[2], 1, de1dt_cdot_e0, 1, Rott1, 1, Rott1, 1);
1298  Vmath::Vvtvp(nq, physarray[2], 1, de1dt_cdot_e1, 1, Rott2, 1, Rott2, 1);
1299 
1300  // Multiply H and \partial \phi / \partial t which is assumed to be u_{\phi}
1301  Vmath::Vmul(nq, &h[0], 1, &Rott1[0], 1, &Rott1[0], 1);
1302  Vmath::Vmul(nq, &h[0], 1, &Rott2[0], 1, &Rott2[0], 1);
1303 
1304  Vmath::Neg(nq, Rott1, 1);
1305  Vmath::Neg(nq, Rott2, 1);
1306 
1307  Array<OneD, NekDouble> tmpc1(ncoeffs);
1308  Array<OneD, NekDouble> tmpc2(ncoeffs);
1309  m_fields[0]->IProductWRTBase(Rott1, tmpc1);
1310  m_fields[0]->IProductWRTBase(Rott2, tmpc2);
1311 
1312  Vmath::Vadd(ncoeffs, tmpc1, 1, outarray[1], 1, outarray[1], 1);
1313  Vmath::Vadd(ncoeffs, tmpc2, 1, outarray[2], 1, outarray[2], 1);
1314 }
1315 
1316 // =====================================================================
1317 // Compute \frac{d e^{indm}}{dt} \cdot e^{indk} / \| e^{indk} \|
1318 // Equivalently, [ \frac{d e^{indm}}{d \xi_1} \frac{ d \xi_1}{d \phi} + \frac{d
1319 // e^{indm}}{d \xi_2} \frac{ d \xi_2}{d \phi} ] \frac{d \phi}{dt}
1321  const int indm, const int indk,
1322  const Array<OneD, const Array<OneD, NekDouble>> &physarray,
1323  Array<OneD, NekDouble> &outarray)
1324 {
1325  int j, k;
1326  int nq = m_fields[0]->GetNpoints();
1327 
1328  Array<OneD, NekDouble> tmp(nq, 0.0);
1329  Array<OneD, NekDouble> tmpderiv(nq);
1330 
1331  outarray = Array<OneD, NekDouble>(nq, 0.0);
1332  for (j = 0; j < m_shapedim; ++j)
1333  {
1334  for (k = 0; k < m_spacedim; ++k)
1335  {
1336  // Compute d e^m / d \xi_1 and d e^m / d \xi_2
1337  Vmath::Vcopy(nq, &m_movingframes[indm][k * nq], 1, &tmp[0], 1);
1338  m_fields[0]->PhysDirectionalDeriv(m_movingframes[j], tmp, tmpderiv);
1339 
1340  Vmath::Vmul(nq, &physarray[j + 1][0], 1, &tmpderiv[0], 1,
1341  &tmpderiv[0], 1);
1342 
1343  Vmath::Vvtvp(nq, &tmpderiv[0], 1, &m_movingframes[indk][k * nq], 1,
1344  &outarray[0], 1, &outarray[0], 1);
1345  }
1346  }
1347 }
1348 
1349 /**
1350  * @brief Compute the projection for the linear advection equation.
1351  *
1352  * @param inarray Given fields.
1353  * @param outarray Calculated solution.
1354  * @param time Time.
1355  */
1357  const Array<OneD, const Array<OneD, NekDouble>> &inarray,
1358  Array<OneD, Array<OneD, NekDouble>> &outarray, const NekDouble time)
1359 {
1360  switch (m_projectionType)
1361  {
1363  {
1364  ConservativeToPrimitive(inarray, outarray);
1365  SetBoundaryConditions(outarray, time);
1366  PrimitiveToConservative(outarray, outarray);
1367  }
1368  break;
1369  default:
1370  ASSERTL0(false, "Unknown projection scheme");
1371  break;
1372  }
1373 }
1374 
1376  NekDouble time)
1377 {
1378 
1379  int nvariables = m_fields.size();
1380  int cnt = 0;
1381 
1382  // loop over Boundary Regions
1383  for (int n = 0; n < m_fields[0]->GetBndConditions().size(); ++n)
1384  {
1385 
1386  // Zonal Boundary Condition
1387  if (m_fields[0]->GetBndConditions()[n]->GetUserDefined() == "eMG")
1388  {
1389  if (m_expdim == 1)
1390  {
1391  ASSERTL0(false, "Illegal dimension");
1392  }
1393  else if (m_expdim == 2)
1394  {
1395  // ZonalBoundary2D(n,cnt,inarray);
1396  }
1397  }
1398 
1399  // Wall Boundary Condition
1400  if (m_fields[0]->GetBndConditions()[n]->GetUserDefined() == "eWall")
1401  {
1402  if (m_expdim == 1)
1403  {
1404  ASSERTL0(false, "Illegal dimension");
1405  }
1406  else if (m_expdim == 2)
1407  {
1408  WallBoundary2D(n, cnt, inarray);
1409  }
1410  }
1411 
1412  // Time Dependent Boundary Condition (specified in meshfile)
1413  if (m_fields[0]->GetBndConditions()[n]->GetUserDefined() ==
1414  "eTimeDependent")
1415  {
1416  for (int i = 0; i < nvariables; ++i)
1417  {
1418  m_fields[i]->EvaluateBoundaryConditions(time);
1419  }
1420  }
1421  cnt += m_fields[0]->GetBndCondExpansions()[n]->GetExpSize();
1422  }
1423 }
1424 
1425 void MMFSWE::WallBoundary2D(int bcRegion, int cnt,
1426  Array<OneD, Array<OneD, NekDouble>> &physarray)
1427 {
1428 
1429  int i;
1430  int nTraceNumPoints = GetTraceTotPoints();
1431  int nvariables = physarray.size();
1432 
1433  // get physical values of the forward trace
1434  Array<OneD, Array<OneD, NekDouble>> Fwd0(nvariables);
1435  for (i = 0; i < nvariables; ++i)
1436  {
1437  Fwd0[i] = Array<OneD, NekDouble>(nTraceNumPoints);
1438  m_fields[i]->ExtractTracePhys(physarray[i], Fwd0[i]);
1439  }
1440 
1441  Array<OneD, Array<OneD, NekDouble>> Fwd(nvariables);
1442  for (i = 0; i < nvariables; ++i)
1443  {
1444  Fwd[i] = Array<OneD, NekDouble>(nTraceNumPoints);
1445  m_fields[i]->ExtractTracePhys(physarray[i], Fwd[i]);
1446  }
1447 
1448  // Adjust the physical values of the trace to take
1449  // user defined boundaries into account
1450  int e, id1, id2, npts;
1451 
1452  for (e = 0; e < m_fields[0]->GetBndCondExpansions()[bcRegion]->GetExpSize();
1453  ++e)
1454  {
1455  npts = m_fields[0]
1456  ->GetBndCondExpansions()[bcRegion]
1457  ->GetExp(e)
1458  ->GetTotPoints();
1459  id1 = m_fields[0]->GetBndCondExpansions()[bcRegion]->GetPhys_Offset(e);
1460  id2 = m_fields[0]->GetTrace()->GetPhys_Offset(
1461  m_fields[0]->GetTraceMap()->GetBndCondIDToGlobalTraceID(cnt + e));
1462 
1463  switch (m_expdim)
1464  {
1465  case 1:
1466  {
1467  // negate the forward flux
1468  Vmath::Neg(npts, &Fwd[1][id2], 1);
1469  }
1470  break;
1471  case 2:
1472  {
1473  Array<OneD, NekDouble> tmp_n(npts);
1474  Array<OneD, NekDouble> tmp_t(npts);
1475 
1476  Vmath::Vmul(npts, &Fwd[1][id2], 1, &m_ncdotMFFwd[0][id2], 1,
1477  &tmp_n[0], 1);
1478  Vmath::Vvtvp(npts, &Fwd[2][id2], 1, &m_ncdotMFFwd[1][id2], 1,
1479  &tmp_n[0], 1, &tmp_n[0], 1);
1480 
1481  Vmath::Vmul(npts, &Fwd[1][id2], 1, &m_nperpcdotMFFwd[0][id2], 1,
1482  &tmp_t[0], 1);
1483  Vmath::Vvtvp(npts, &Fwd[2][id2], 1, &m_nperpcdotMFFwd[1][id2],
1484  1, &tmp_t[0], 1, &tmp_t[0], 1);
1485 
1486  // negate the normal flux
1487  Vmath::Neg(npts, tmp_n, 1);
1488 
1489  Array<OneD, NekDouble> denom(npts);
1490  Array<OneD, NekDouble> tmp_u(npts);
1491  Array<OneD, NekDouble> tmp_v(npts);
1492 
1493  // denom = (e^1 \cdot n ) (e^2 \cdot t) - (e^2 \cdot n ) (e^1
1494  // \cdot t)
1495  Vmath::Vmul(npts, &m_ncdotMFFwd[1][id2], 1,
1496  &m_nperpcdotMFFwd[0][id2], 1, &denom[0], 1);
1497  Vmath::Vvtvm(npts, &m_ncdotMFFwd[0][id2], 1,
1498  &m_nperpcdotMFFwd[1][id2], 1, &denom[0], 1,
1499  &denom[0], 1);
1500 
1501  Vmath::Vmul(npts, &m_ncdotMFFwd[1][id2], 1, &tmp_t[0], 1,
1502  &tmp_u[0], 1);
1503  Vmath::Vvtvm(npts, &m_nperpcdotMFFwd[1][id2], 1, &tmp_n[0], 1,
1504  &tmp_u[0], 1, &tmp_u[0], 1);
1505  Vmath::Vdiv(npts, &tmp_u[0], 1, &denom[0], 1, &tmp_u[0], 1);
1506 
1507  Vmath::Vcopy(npts, &tmp_u[0], 1, &Fwd[1][id2], 1);
1508 
1509  Vmath::Vmul(npts, &m_nperpcdotMFFwd[0][id2], 1, &tmp_n[0], 1,
1510  &tmp_v[0], 1);
1511  Vmath::Vvtvm(npts, &m_ncdotMFFwd[0][id2], 1, &tmp_t[0], 1,
1512  &tmp_v[0], 1, &tmp_v[0], 1);
1513  Vmath::Vdiv(npts, &tmp_v[0], 1, &denom[0], 1, &tmp_v[0], 1);
1514 
1515  Vmath::Vcopy(npts, &tmp_v[0], 1, &Fwd[2][id2], 1);
1516  }
1517  break;
1518 
1519  default:
1520  ASSERTL0(false, "Illegal expansion dimension");
1521  }
1522 
1523  // copy boundary adjusted values into the boundary expansion
1524  for (i = 0; i < nvariables; ++i)
1525  {
1526  Vmath::Vcopy(npts, &Fwd[i][id2], 1,
1527  &(m_fields[i]
1528  ->GetBndCondExpansions()[bcRegion]
1529  ->UpdatePhys())[id1],
1530  1);
1531  }
1532  }
1533 }
1534 
1535 /**
1536  *
1537  */
1539 {
1540  // Compute m_depth and m_Derivdepth
1542  EvaluateCoriolis();
1545 
1546  // transfer the initial conditions to modal values
1547  for(int i = 0; i < m_fields.size(); ++i)
1548  {
1549  m_fields[i]->SetPhysState(true);
1550  m_fields[i]->FwdTrans(m_fields[i]->GetPhys(),m_fields[i]->UpdateCoeffs());
1551  }
1552 
1553 }
1554 
1556 {
1557  int nq = GetTotPoints();
1558 
1559  m_depth = Array<OneD, NekDouble>(nq, 0.0);
1560 
1561  switch (m_TestType)
1562  {
1563  case eTestPlane:
1564  {
1565  Vmath::Fill(nq, 1.0, m_depth, 1);
1566  }
1567  break;
1568 
1569  case eTestUnsteadyZonal:
1570  {
1571  // H_0 = k_1 - k_2 - (1/2/g) (Omega sin \phi)
1572  Array<OneD, NekDouble> x(nq);
1573  Array<OneD, NekDouble> y(nq);
1574  Array<OneD, NekDouble> z(nq);
1575 
1576  m_fields[0]->GetCoords(x, y, z);
1577 
1578  NekDouble x0j, x1j, x2j;
1579  NekDouble sin_varphi, cos_varphi, sin_theta, cos_theta;
1580 
1581  for (int j = 0; j < nq; ++j)
1582  {
1583  x0j = x[j];
1584  x1j = y[j];
1585  x2j = z[j];
1586 
1587  CartesianToSpherical(x0j, x1j, x2j, sin_varphi, cos_varphi,
1588  sin_theta, cos_theta);
1589  m_depth[j] =
1590  m_H0 - m_k2 -
1591  (0.5 / m_g) * (m_Omega * sin_theta) * (m_Omega * sin_theta);
1592  }
1593  }
1594  break;
1595 
1596  case eTestIsolatedMountain:
1597  {
1598  // H_0 = k_1 - k_2 - (1/2/g) (Omega sin \phi)
1599  Array<OneD, NekDouble> x(nq);
1600  Array<OneD, NekDouble> y(nq);
1601  Array<OneD, NekDouble> z(nq);
1602 
1603  m_fields[0]->GetCoords(x, y, z);
1604 
1605  int indx = 0;
1606  NekDouble x0j, x1j, x2j, dist2;
1607  NekDouble phi, theta, sin_varphi, cos_varphi, sin_theta, cos_theta;
1608  NekDouble hRad, phic, thetac;
1609  NekDouble Tol = 0.000001;
1610 
1611  hRad = m_pi / 9.0;
1612  phic = -m_pi / 2.0;
1613  thetac = m_pi / 6.0;
1614 
1615  for (int j = 0; j < nq; ++j)
1616  {
1617  x0j = x[j];
1618  x1j = y[j];
1619  x2j = z[j];
1620 
1621  CartesianToSpherical(x0j, x1j, x2j, sin_varphi, cos_varphi,
1622  sin_theta, cos_theta);
1623 
1624  if ((std::abs(sin(phic) - sin_varphi) +
1625  std::abs(sin(thetac) - sin_theta)) < Tol)
1626  {
1627  std::cout << "A point " << j
1628  << " is coincient with the singularity "
1629  << std::endl;
1630  indx = 1;
1631  }
1632 
1633  phi = atan2(sin_varphi, cos_varphi);
1634  theta = atan2(sin_theta, cos_theta);
1635 
1636  // Compute r
1637  dist2 = (phi - phic) * (phi - phic) +
1638  (theta - thetac) * (theta - thetac);
1639 
1640  if (dist2 > hRad * hRad)
1641  {
1642  dist2 = hRad * hRad;
1643  }
1644 
1645  m_depth[j] = m_H0 - m_hs0 * (1.0 - sqrt(dist2) / hRad);
1646  }
1647 
1648  if (!indx)
1649  {
1650  std::cout << "No point is coincident with the singularity point"
1651  << std::endl;
1652  }
1653  }
1654  break;
1655 
1656  case eTestUnstableJet:
1657  {
1658  for (int j = 0; j < nq; ++j)
1659  {
1660  m_depth[j] = m_H0;
1661  }
1662  }
1663  break;
1664 
1665  case eTestSteadyZonal:
1666  case eTestRossbyWave:
1667  {
1668  Vmath::Zero(nq, m_depth, 1);
1669  }
1670  break;
1671 
1672  default:
1673  {
1674  Vmath::Zero(nq, m_depth, 1);
1675  }
1676  break;
1677  }
1678 
1679  // Comptue \nabla m_depth \cdot e^i
1681 
1682  for (int j = 0; j < m_shapedim; j++)
1683  {
1685  m_fields[0]->PhysDirectionalDeriv(m_movingframes[j], m_depth,
1686  m_Derivdepth[j]);
1687  }
1688 
1689  std::cout << "Water Depth (m_depth) was generated with mag = "
1690  << AvgAbsInt(m_depth) << " with max. deriv = ( "
1691  << Vmath::Vamax(nq, m_Derivdepth[0], 1) << " , "
1692  << Vmath::Vamax(nq, m_Derivdepth[1], 1) << " ) " << std::endl;
1693 }
1694 
1696 {
1697  switch (m_TestType)
1698  {
1699  case eTestPlane:
1700  {
1701  GetFunction("Coriolis")->Evaluate("f", m_coriolis);
1702  }
1703  break;
1704 
1705  case eTestSteadyZonal:
1706  {
1708  }
1709  break;
1710 
1711  case eTestUnsteadyZonal:
1712  case eTestIsolatedMountain:
1713  case eTestUnstableJet:
1714  case eTestRossbyWave:
1715  {
1717  }
1718  break;
1719 
1720  default:
1721  break;
1722  }
1723 }
1724 
1726 {
1727  int nq = GetTotPoints();
1728  NekDouble sin_theta, cos_theta, sin_varphi, cos_varphi;
1729 
1730  Array<OneD, NekDouble> x(nq);
1731  Array<OneD, NekDouble> y(nq);
1732  Array<OneD, NekDouble> z(nq);
1733 
1734  m_fields[0]->GetCoords(x, y, z);
1735 
1736  NekDouble x0j, x1j, x2j;
1737  NekDouble tmp;
1738 
1739  outarray = Array<OneD, NekDouble>(nq, 0.0);
1740  for (int j = 0; j < nq; ++j)
1741  {
1742  x0j = x[j];
1743  x1j = y[j];
1744  x2j = z[j];
1745 
1746  CartesianToSpherical(x0j, x1j, x2j, sin_varphi, cos_varphi, sin_theta,
1747  cos_theta);
1748 
1749  // H = 2 \Omega *(- \cos \phi \cos \theta \sin \alpha + \sin \theta \cos
1750  // \alpha )
1751  tmp = -1.0 * cos_varphi * cos_theta * sin(m_alpha) +
1752  sin_theta * cos(m_alpha);
1753  outarray[j] = 2.0 * m_Omega * tmp;
1754  }
1755 }
1756 
1758 {
1759  int nq = GetTotPoints();
1760 
1761  NekDouble x0j, x1j, x2j;
1762  NekDouble sin_theta, cos_theta, sin_varphi, cos_varphi;
1763 
1764  Array<OneD, NekDouble> x(nq);
1765  Array<OneD, NekDouble> y(nq);
1766  Array<OneD, NekDouble> z(nq);
1767 
1768  m_fields[0]->GetCoords(x, y, z);
1769 
1770  outarray = Array<OneD, NekDouble>(nq, 0.0);
1771  for (int j = 0; j < nq; ++j)
1772  {
1773  x0j = x[j];
1774  x1j = y[j];
1775  x2j = z[j];
1776 
1777  CartesianToSpherical(x0j, x1j, x2j, sin_varphi, cos_varphi, sin_theta,
1778  cos_theta);
1779 
1780  outarray[j] = 2.0 * m_Omega * sin_theta;
1781  }
1782 }
1783 
1785  bool dumpInitialConditions,
1786  const int domain)
1787 {
1788  boost::ignore_unused(domain);
1789 
1790  int nq = GetTotPoints();
1791 
1792  switch (m_TestType)
1793  {
1794  case eTestPlane:
1795  {
1796  Array<OneD, NekDouble> eta0(nq);
1797  Array<OneD, NekDouble> u0(nq);
1798  Array<OneD, NekDouble> v0(nq);
1799 
1800  TestSWE2Dproblem(initialtime, 0, eta0);
1801  m_fields[0]->SetPhys(eta0);
1802 
1803  TestSWE2Dproblem(initialtime, 1, u0);
1804  m_fields[1]->SetPhys(u0);
1805 
1806  TestSWE2Dproblem(initialtime, 2, v0);
1807  m_fields[2]->SetPhys(v0);
1808 
1809  // forward transform to fill the modal coeffs
1810  for (int i = 0; i < m_fields.size(); ++i)
1811  {
1812  m_fields[i]->SetPhysState(true);
1813  m_fields[i]->FwdTrans(m_fields[i]->GetPhys(),
1814  m_fields[i]->UpdateCoeffs());
1815  }
1816  }
1817  break;
1818 
1819  case eTestSteadyZonal:
1820  {
1821  Array<OneD, NekDouble> eta0(nq);
1822  Array<OneD, NekDouble> u0(nq);
1823  Array<OneD, NekDouble> v0(nq);
1824  Array<OneD, NekDouble> zeta0(nq);
1825 
1826  SteadyZonalFlow(0, eta0);
1827  m_fields[0]->SetPhys(eta0);
1828 
1829  SteadyZonalFlow(1, u0);
1830  m_fields[1]->SetPhys(u0);
1831 
1832  SteadyZonalFlow(2, v0);
1833  m_fields[2]->SetPhys(v0);
1834 
1835  // ComputeVorticity(u0, v0, zeta0);
1836  m_Vorticity0 = m_fields[0]->Integral(zeta0);
1837 
1838  m_Mass0 = ComputeMass(eta0);
1839  m_Energy0 = ComputeEnergy(eta0, u0, v0);
1840  m_Enstrophy0 = ComputeEnstrophy(eta0, u0, v0);
1841 
1842  // forward transform to fill the modal coeffs
1843  for (int i = 0; i < m_fields.size(); ++i)
1844  {
1845  m_fields[i]->SetPhysState(true);
1846  m_fields[i]->FwdTrans(m_fields[i]->GetPhys(),
1847  m_fields[i]->UpdateCoeffs());
1848  }
1849  }
1850  break;
1851 
1852  case eTestUnsteadyZonal:
1853  {
1854  Array<OneD, NekDouble> eta0(nq);
1855  Array<OneD, NekDouble> u0(nq);
1856  Array<OneD, NekDouble> v0(nq);
1857 
1858  UnsteadyZonalFlow(0, initialtime, eta0);
1859  m_fields[0]->SetPhys(eta0);
1860 
1861  UnsteadyZonalFlow(1, initialtime, u0);
1862  m_fields[1]->SetPhys(u0);
1863 
1864  UnsteadyZonalFlow(2, initialtime, v0);
1865  m_fields[2]->SetPhys(v0);
1866 
1867  m_Mass0 = ComputeMass(eta0);
1868  m_Energy0 = ComputeEnergy(eta0, u0, v0);
1869  m_Enstrophy0 = ComputeEnstrophy(eta0, u0, v0);
1870 
1871  // forward transform to fill the modal coeffs
1872  for (int i = 0; i < m_fields.size(); ++i)
1873  {
1874  m_fields[i]->SetPhysState(true);
1875  m_fields[i]->FwdTrans(m_fields[i]->GetPhys(),
1876  m_fields[i]->UpdateCoeffs());
1877  }
1878  }
1879  break;
1880 
1881  case eTestIsolatedMountain:
1882  {
1883  Array<OneD, NekDouble> eta0(nq);
1884  Array<OneD, NekDouble> u0(nq);
1885  Array<OneD, NekDouble> v0(nq);
1886 
1887  IsolatedMountainFlow(0, initialtime, eta0);
1888  m_fields[0]->SetPhys(eta0);
1889 
1890  IsolatedMountainFlow(1, initialtime, u0);
1891  m_fields[1]->SetPhys(u0);
1892 
1893  IsolatedMountainFlow(2, initialtime, v0);
1894  m_fields[2]->SetPhys(v0);
1895 
1896  m_Mass0 = ComputeMass(eta0);
1897  m_Energy0 = ComputeEnergy(eta0, u0, v0);
1898  m_Enstrophy0 = ComputeEnstrophy(eta0, u0, v0);
1899 
1900  // forward transform to fill the modal coeffs
1901  for (int i = 0; i < m_fields.size(); ++i)
1902  {
1903  m_fields[i]->SetPhysState(true);
1904  m_fields[i]->FwdTrans(m_fields[i]->GetPhys(),
1905  m_fields[i]->UpdateCoeffs());
1906  }
1907  }
1908  break;
1909 
1910  case eTestUnstableJet:
1911  {
1912  Array<OneD, NekDouble> eta0(nq);
1913  Array<OneD, NekDouble> u0(nq);
1914  Array<OneD, NekDouble> v0(nq);
1915 
1916  UnstableJetFlow(0, initialtime, eta0);
1917  m_fields[0]->SetPhys(eta0);
1918 
1919  UnstableJetFlow(1, initialtime, u0);
1920  m_fields[1]->SetPhys(u0);
1921 
1922  UnstableJetFlow(2, initialtime, v0);
1923  m_fields[2]->SetPhys(v0);
1924 
1925  m_Mass0 = ComputeMass(eta0);
1926  m_Energy0 = ComputeEnergy(eta0, u0, v0);
1927  m_Enstrophy0 = ComputeEnstrophy(eta0, u0, v0);
1928 
1929  // forward transform to fill the modal coeffs
1930  for (int i = 0; i < m_fields.size(); ++i)
1931  {
1932  m_fields[i]->SetPhysState(true);
1933  m_fields[i]->FwdTrans(m_fields[i]->GetPhys(),
1934  m_fields[i]->UpdateCoeffs());
1935  }
1936  }
1937  break;
1938 
1939  case eTestRossbyWave:
1940  {
1941  Array<OneD, NekDouble> eta0(nq);
1942  Array<OneD, NekDouble> u0(nq);
1943  Array<OneD, NekDouble> v0(nq);
1944 
1945  RossbyWave(0, eta0);
1946  m_fields[0]->SetPhys(eta0);
1947 
1948  RossbyWave(1, u0);
1949  m_fields[1]->SetPhys(u0);
1950 
1951  RossbyWave(2, v0);
1952  m_fields[2]->SetPhys(v0);
1953 
1954  m_Mass0 = ComputeMass(eta0);
1955  m_Energy0 = ComputeEnergy(eta0, u0, v0);
1956  m_Enstrophy0 = ComputeEnstrophy(eta0, u0, v0);
1957 
1958  // forward transform to fill the modal coeffs
1959  for (int i = 0; i < m_fields.size(); ++i)
1960  {
1961  m_fields[i]->SetPhysState(true);
1962  m_fields[i]->FwdTrans(m_fields[i]->GetPhys(),
1963  m_fields[i]->UpdateCoeffs());
1964  }
1965  }
1966  break;
1967 
1968  default:
1969  break;
1970  }
1971 
1972  if (dumpInitialConditions)
1973  {
1974  // dump initial conditions to file
1975  std::string outname = m_sessionName + "_initial.chk";
1976  WriteFld(outname);
1977 
1978  outname = m_sessionName + "_initialCART.chk";
1979  Checkpoint_Output_Cartesian(outname);
1980  }
1981 }
1982 
1983 void MMFSWE::TestSWE2Dproblem(const NekDouble time, unsigned int field,
1984  Array<OneD, NekDouble> &outfield)
1985 {
1986  boost::ignore_unused(time);
1987 
1988  int nq = m_fields[0]->GetNpoints();
1989 
1990  Array<OneD, NekDouble> x0(nq);
1991  Array<OneD, NekDouble> x1(nq);
1992  Array<OneD, NekDouble> x2(nq);
1993 
1994  m_fields[0]->GetCoords(x0, x1, x2);
1995 
1996  Array<OneD, NekDouble> eta0(nq);
1997  Array<OneD, NekDouble> u0(nq);
1998  Array<OneD, NekDouble> v0(nq);
1999 
2001 
2002  for (int i = 0; i < m_spacedim; ++i)
2003  {
2004  uvec[i] = Array<OneD, NekDouble>(nq, 0.0);
2005  }
2006 
2007  for (int i = 0; i < nq; ++i)
2008  {
2009  eta0[i] = (0.771 * 0.395 * 0.395 * (1.0 / cosh(0.395 * x0[i])) *
2010  (1.0 / cosh(0.395 * x0[i]))) *
2011  (3.0 + 6.0 * x1[i] * x1[i]) / (4.0) *
2012  exp(-0.5 * x1[i] * x1[i]);
2013  uvec[0][i] = (0.771 * 0.395 * 0.395 * (1.0 / cosh(0.395 * x0[i])) *
2014  (1.0 / cosh(0.395 * x0[i]))) *
2015  (-9.0 + 6.0 * x1[i] * x1[i]) / (4.0) *
2016  exp(-0.5 * x1[i] * x1[i]);
2017  uvec[1][i] = (-2.0 * 0.395 * tanh(0.395 * x0[i])) *
2018  (0.771 * 0.395 * 0.395 * (1.0 / cosh(0.395 * x0[i])) *
2019  (1.0 / cosh(0.395 * x0[i]))) *
2020  (2.0 * x1[i]) * exp(-0.5 * x1[i] * x1[i]);
2021  }
2022 
2023  u0 = CartesianToMovingframes(uvec, 0);
2024  v0 = CartesianToMovingframes(uvec, 1);
2025 
2026  switch (field)
2027  {
2028  case (0):
2029  {
2030  outfield = eta0;
2031  }
2032  break;
2033 
2034  case (1):
2035  {
2036  outfield = u0;
2037  }
2038  break;
2039 
2040  case (2):
2041  {
2042  outfield = v0;
2043  }
2044  break;
2045  }
2046 }
2047 
2048 void MMFSWE::SteadyZonalFlow(unsigned int field,
2049  Array<OneD, NekDouble> &outfield)
2050 {
2051  int nq = GetTotPoints();
2052  NekDouble uhat, vhat;
2053  NekDouble sin_theta, cos_theta, sin_varphi, cos_varphi;
2054  NekDouble x0j, x1j, x2j, tmp;
2055 
2056  Array<OneD, NekDouble> eta(nq, 0.0);
2057  Array<OneD, NekDouble> u(nq, 0.0);
2058  Array<OneD, NekDouble> v(nq, 0.0);
2059 
2061  for (int i = 0; i < m_spacedim; ++i)
2062  {
2063  uvec[i] = Array<OneD, NekDouble>(nq, 0.0);
2064  }
2065 
2066  Array<OneD, NekDouble> x(nq);
2067  Array<OneD, NekDouble> y(nq);
2068  Array<OneD, NekDouble> z(nq);
2069 
2070  m_fields[0]->GetCoords(x, y, z);
2071 
2072  for (int j = 0; j < nq; ++j)
2073  {
2074  x0j = x[j];
2075  x1j = y[j];
2076  x2j = z[j];
2077 
2078  CartesianToSpherical(x0j, x1j, x2j, sin_varphi, cos_varphi, sin_theta,
2079  cos_theta);
2080 
2081  // H = H_0 - (1/g)*(a \Omega u_0 + 0.5*u_0^2 )*(- \cos \phi \cos \theta
2082  // \sin \alpha + \sin \theta \cos \alpha )^2
2083  tmp = -1.0 * cos_varphi * cos_theta * sin(m_alpha) +
2084  sin_theta * cos(m_alpha);
2085  eta[j] = m_H0 - m_Hvar * tmp * tmp;
2086 
2087  // u = (\vec{u} \cdot e^1 )/ || e^1 ||^2 , v = (\vec{u} \cdot e^2 )/
2088  // || e^2 ||^2
2089  uhat = m_u0 * (cos_theta * cos(m_alpha) +
2090  sin_theta * cos_varphi * sin(m_alpha));
2091  vhat = -1.0 * m_u0 * sin_varphi * sin(m_alpha);
2092 
2093  uvec[0][j] = -1.0 * uhat * sin_varphi - vhat * sin_theta * cos_varphi;
2094  uvec[1][j] = uhat * cos_varphi - vhat * sin_theta * sin_varphi;
2095  uvec[2][j] = vhat * cos_theta;
2096  }
2097 
2098  // Projection of u onto the tangent plane with conserving the mag. of the
2099  // velocity.
2101 
2102  for (int i = 0; i < m_spacedim; ++i)
2103  {
2104  uvecproj[i] = Array<OneD, NekDouble>(nq, 0.0);
2105  }
2106 
2107  // u is projected on the tangent plane with preserving its length
2108  // GramSchumitz(m_surfaceNormal, uvec, uvecproj, true);
2109 
2110  // Change it to the coordinate of moving frames
2111  // CartesianToMovingframes(0,uvecproj,u);
2112  // CartesianToMovingframes(1,uvecproj,v);
2113 
2114  u = CartesianToMovingframes(uvec, 0);
2115  v = CartesianToMovingframes(uvec, 1);
2116 
2117  switch (field)
2118  {
2119  case (0):
2120  {
2121  outfield = eta;
2122  }
2123  break;
2124 
2125  case (1):
2126  {
2127  outfield = u;
2128  }
2129  break;
2130 
2131  case (2):
2132  {
2133  outfield = v;
2134  }
2135  break;
2136  }
2137 }
2138 
2140 {
2141  int nq = m_fields[0]->GetTotPoints();
2142 
2143  Array<OneD, NekDouble> tmp(nq);
2144  Vmath::Vadd(nq, eta, 1, m_depth, 1, tmp, 1);
2145 
2146  return m_fields[0]->Integral(tmp);
2147 }
2148 
2152 {
2153  int nq = m_fields[0]->GetTotPoints();
2154 
2155  Array<OneD, NekDouble> tmp(nq);
2156  Array<OneD, NekDouble> htmp(nq);
2157  Array<OneD, NekDouble> hstmp(nq);
2158 
2159  Vmath::Vmul(nq, u, 1, u, 1, tmp, 1);
2160  Vmath::Vvtvp(nq, v, 1, v, 1, tmp, 1, tmp, 1);
2161  Vmath::Vmul(nq, eta, 1, tmp, 1, tmp, 1);
2162 
2163  Vmath::Sadd(nq, m_H0, eta, 1, htmp, 1);
2164  Vmath::Vmul(nq, htmp, 1, htmp, 1, htmp, 1);
2165 
2166  Vmath::Sadd(nq, -1.0 * m_H0, m_depth, 1, hstmp, 1);
2167  Vmath::Vmul(nq, hstmp, 1, hstmp, 1, hstmp, 1);
2168 
2169  Vmath::Vsub(nq, htmp, 1, hstmp, 1, htmp, 1);
2170  Vmath::Smul(nq, m_g, htmp, 1, htmp, 1);
2171 
2172  Vmath::Vadd(nq, htmp, 1, tmp, 1, tmp, 1);
2173  Vmath::Smul(nq, 0.5, tmp, 1, tmp, 1);
2174 
2175  return m_fields[0]->Integral(tmp);
2176 }
2177 
2181 {
2182  int nq = m_fields[0]->GetTotPoints();
2183 
2184  Array<OneD, NekDouble> hstartmp(nq);
2185  Array<OneD, NekDouble> tmp(nq);
2186 
2187  Vmath::Vadd(nq, eta, 1, m_depth, 1, hstartmp, 1);
2188 
2191  for (int i = 0; i < m_spacedim; ++i)
2192  {
2193  uvec[i] = Array<OneD, NekDouble>(nq);
2194  Curlu[i] = Array<OneD, NekDouble>(nq);
2195  }
2196 
2197  ComputeVorticity(u, v, tmp);
2198 
2199  Vmath::Vadd(nq, m_coriolis, 1, tmp, 1, tmp, 1);
2200  Vmath::Vmul(nq, tmp, 1, tmp, 1, tmp, 1);
2201  Vmath::Vdiv(nq, tmp, 1, hstartmp, 1, tmp, 1);
2202  Vmath::Smul(nq, 0.5, tmp, 1, tmp, 1);
2203 
2204  return m_fields[0]->Integral(tmp);
2205 }
2206 
2207 // Vorticity = \nabla v \cdot e^1 + v \nabla \cdot e^1 - ( \nabla u \cdot e^2 +
2208 // u \nabla \cdot e^2 )
2211  Array<OneD, NekDouble> &Vorticity)
2212 {
2213  int nq = m_fields[0]->GetTotPoints();
2214 
2215  Array<OneD, NekDouble> tmp(nq);
2216 
2217  Vorticity = Array<OneD, NekDouble>(nq, 0.0);
2218 
2219  m_fields[0]->PhysDirectionalDeriv(m_movingframes[0], v, Vorticity);
2220  Vmath::Vvtvp(nq, &v[0], 1, &m_CurlMF[1][2][0], 1, &Vorticity[0], 1,
2221  &Vorticity[0], 1);
2222 
2223  m_fields[0]->PhysDirectionalDeriv(m_movingframes[1], u, tmp);
2224  Vmath::Neg(nq, tmp, 1);
2225  Vmath::Vvtvp(nq, &u[0], 1, &m_CurlMF[0][2][0], 1, &tmp[0], 1, &tmp[0], 1);
2226 
2227  Vmath::Vadd(nq, tmp, 1, Vorticity, 1, Vorticity, 1);
2228 }
2229 
2231 {
2232  int nq = m_fields[0]->GetNpoints();
2233 
2234  Array<OneD, NekDouble> velcoeff(nq, 0.0);
2235 
2236  Array<OneD, NekDouble> Dtmp0(nq);
2237  Array<OneD, NekDouble> Dtmp1(nq);
2238  Array<OneD, NekDouble> Dtmp2(nq);
2239  Array<OneD, NekDouble> Drv(nq);
2240 
2241  vellc = Array<OneD, NekDouble>(nq, 0.0);
2242 
2243  // m_vellc = \nabla m_vel \cdot tan_i
2244  Array<OneD, NekDouble> tmp(nq);
2245  Array<OneD, NekDouble> vessel(nq);
2246 
2247  for (int j = 0; j < m_shapedim; ++j)
2248  {
2249  Vmath::Zero(nq, velcoeff, 1);
2250  for (int k = 0; k < m_spacedim; ++k)
2251  {
2252  // a_j = tan_j cdot m_vel
2253  Vmath::Vvtvp(nq, &m_movingframes[j][k * nq], 1, &m_velocity[k][0],
2254  1, &velcoeff[0], 1, &velcoeff[0], 1);
2255  }
2256 
2257  // d a_j / d x^k
2258  m_fields[0]->PhysDeriv(velcoeff, Dtmp0, Dtmp1, Dtmp2);
2259 
2260  for (int k = 0; k < m_spacedim; ++k)
2261  {
2262  // tan_j^k ( d a_j / d x^k )
2263  switch (k)
2264  {
2265  case (0):
2266  {
2267  Vmath::Vvtvp(nq, &Dtmp0[0], 1, &m_movingframes[j][k * nq],
2268  1, &vellc[0], 1, &vellc[0], 1);
2269  }
2270  break;
2271 
2272  case (1):
2273  {
2274  Vmath::Vvtvp(nq, &Dtmp1[0], 1, &m_movingframes[j][k * nq],
2275  1, &vellc[0], 1, &vellc[0], 1);
2276  }
2277  break;
2278 
2279  case (2):
2280  {
2281  Vmath::Vvtvp(nq, &Dtmp2[0], 1, &m_movingframes[j][k * nq],
2282  1, &vellc[0], 1, &vellc[0], 1);
2283  }
2284  break;
2285  }
2286  }
2287  }
2288 }
2289 
2290 void MMFSWE::UnsteadyZonalFlow(unsigned int field, const NekDouble time,
2291  Array<OneD, NekDouble> &outfield)
2292 {
2293  int nq = GetTotPoints();
2294  NekDouble uhat, vhat;
2295  NekDouble sin_theta, cos_theta, sin_varphi, cos_varphi;
2296  NekDouble x0j, x1j, x2j, tmp;
2297 
2298  NekDouble TR, Ttheta;
2299 
2300  Array<OneD, NekDouble> eta(nq, 0.0);
2301  Array<OneD, NekDouble> u(nq, 0.0);
2302  Array<OneD, NekDouble> v(nq, 0.0);
2303 
2305  for (int i = 0; i < m_spacedim; ++i)
2306  {
2307  uvec[i] = Array<OneD, NekDouble>(nq, 0.0);
2308  }
2309 
2310  Array<OneD, NekDouble> x(nq);
2311  Array<OneD, NekDouble> y(nq);
2312  Array<OneD, NekDouble> z(nq);
2313 
2314  m_fields[0]->GetCoords(x, y, z);
2315 
2316  for (int j = 0; j < nq; ++j)
2317  {
2318  x0j = x[j];
2319  x1j = y[j];
2320  x2j = z[j];
2321 
2322  CartesianToSpherical(x0j, x1j, x2j, sin_varphi, cos_varphi, sin_theta,
2323  cos_theta);
2324 
2325  // \eta = ( - ( u_0 ( - T_R sin \alpha \cos \theta + \cos \alpha \sin
2326  // \theta ) + \Omega \sin \theta )^2 + \Omega \sin \theta )^2 + (\Omega
2327  // \sin \theta )^2
2328  TR =
2329  cos_varphi * cos(m_Omega * time) - sin_varphi * sin(m_Omega * time);
2330  Ttheta =
2331  sin_varphi * cos(m_Omega * time) + cos_varphi * sin(m_Omega * time);
2332  tmp = -1.0 * TR * sin(m_alpha) * cos_theta + cos(m_alpha) * sin_theta;
2333 
2334  eta[j] = -1.0 * (m_u0 * tmp + m_Omega * sin_theta) *
2335  (m_u0 * tmp + m_Omega * sin_theta) +
2336  m_Omega * m_Omega * sin_theta * sin_theta;
2337  eta[j] = 0.5 * eta[j] / m_g;
2338 
2339  // u = u_0*(TR*\sin \alpha * \sin \theta + \cos \alpha * \cos \theta
2340  // v = - u_0 Ttheta * \sin \alpha
2341  uhat =
2342  m_u0 * (TR * sin(m_alpha) * sin_theta + cos(m_alpha) * cos_theta);
2343  vhat = -1.0 * m_u0 * Ttheta * sin(m_alpha);
2344 
2345  uvec[0][j] = -1.0 * uhat * sin_varphi - vhat * sin_theta * cos_varphi;
2346  uvec[1][j] = uhat * cos_varphi - vhat * sin_theta * sin_varphi;
2347  uvec[2][j] = vhat * cos_theta;
2348  }
2349 
2350  // Projection of u onto the tangent plane with conserving the mag. of the
2351  // velocity.
2353 
2354  for (int i = 0; i < m_spacedim; ++i)
2355  {
2356  uvecproj[i] = Array<OneD, NekDouble>(nq, 0.0);
2357  }
2358 
2359  // u is projected on the tangent plane with preserving its length
2360  // GramSchumitz(m_surfaceNormal, uvec, uvecproj, true);
2361 
2362  // Change it to the coordinate of moving frames
2363  // CartesianToMovingframes(0,uvecproj,u);
2364  // CartesianToMovingframes(1,uvecproj,v);
2365 
2366  u = CartesianToMovingframes(uvec, 0);
2367  v = CartesianToMovingframes(uvec, 1);
2368 
2369  switch (field)
2370  {
2371  case (0):
2372  {
2373  outfield = eta;
2374  }
2375  break;
2376 
2377  case (1):
2378  {
2379  outfield = u;
2380  }
2381  break;
2382 
2383  case (2):
2384  {
2385  outfield = v;
2386  }
2387  break;
2388  }
2389 }
2390 
2391 void MMFSWE::IsolatedMountainFlow(unsigned int field, const NekDouble time,
2392  Array<OneD, NekDouble> &outfield)
2393 {
2394  boost::ignore_unused(time);
2395 
2396  int nq = GetTotPoints();
2397 
2398  NekDouble uhat, vhat;
2399  NekDouble sin_theta, cos_theta, sin_varphi, cos_varphi;
2400  NekDouble x0j, x1j, x2j;
2401 
2402  Array<OneD, NekDouble> eta(nq, 0.0);
2403  Array<OneD, NekDouble> u(nq, 0.0);
2404  Array<OneD, NekDouble> v(nq, 0.0);
2405 
2407  for (int i = 0; i < m_spacedim; ++i)
2408  {
2409  uvec[i] = Array<OneD, NekDouble>(nq, 0.0);
2410  }
2411 
2412  Array<OneD, NekDouble> x(nq);
2413  Array<OneD, NekDouble> y(nq);
2414  Array<OneD, NekDouble> z(nq);
2415 
2416  m_fields[0]->GetCoords(x, y, z);
2417 
2418  for (int j = 0; j < nq; ++j)
2419  {
2420  x0j = x[j];
2421  x1j = y[j];
2422  x2j = z[j];
2423 
2424  CartesianToSpherical(x0j, x1j, x2j, sin_varphi, cos_varphi, sin_theta,
2425  cos_theta);
2426 
2427  // eta = - (1/g) (\Omega u_0 + 0.4 u^2 ) \sin^2 \theta
2428  eta[j] = (-1.0 / m_g) * (m_Omega * m_u0 + 0.5 * m_u0 * m_u0) *
2429  sin_theta * sin_theta;
2430 
2431  uhat = m_u0 * cos_theta;
2432  vhat = 0.0;
2433 
2434  uvec[0][j] = -1.0 * uhat * sin_varphi - vhat * sin_theta * cos_varphi;
2435  uvec[1][j] = uhat * cos_varphi - vhat * sin_theta * sin_varphi;
2436  uvec[2][j] = vhat * cos_theta;
2437  }
2438 
2439  // Projection of u onto the tangent plane with conserving the mag. of the
2440  // velocity.
2442 
2443  for (int i = 0; i < m_spacedim; ++i)
2444  {
2445  uvecproj[i] = Array<OneD, NekDouble>(nq, 0.0);
2446  }
2447 
2448  // u is projected on the tangent plane with preserving its length
2449  // GramSchumitz(m_surfaceNormal, uvec, uvecproj, true);
2450 
2451  // Change it to the coordinate of moving frames
2452  // CartesianToMovingframes(0,uvecproj,u);
2453  // CartesianToMovingframes(1,uvecproj,v);
2454 
2455  u = CartesianToMovingframes(uvec, 0);
2456  v = CartesianToMovingframes(uvec, 1);
2457 
2458  switch (field)
2459  {
2460  case (0):
2461  {
2462  outfield = eta;
2463  }
2464  break;
2465 
2466  case (1):
2467  {
2468  outfield = u;
2469  }
2470  break;
2471 
2472  case (2):
2473  {
2474  outfield = v;
2475  }
2476  break;
2477  }
2478 }
2479 
2480 void MMFSWE::UnstableJetFlow(unsigned int field, const NekDouble time,
2481  Array<OneD, NekDouble> &outfield)
2482 {
2483  boost::ignore_unused(time);
2484 
2485  int nq = GetTotPoints();
2486 
2487  NekDouble uhat, vhat;
2488  NekDouble sin_theta, cos_theta, sin_varphi, cos_varphi;
2489  NekDouble x0j, x1j, x2j;
2490  NekDouble Ttheta, Tphi;
2491 
2492  Array<OneD, NekDouble> eta(nq, 0.0);
2493  Array<OneD, NekDouble> u(nq, 0.0);
2494  Array<OneD, NekDouble> v(nq, 0.0);
2495 
2497  for (int i = 0; i < m_spacedim; ++i)
2498  {
2499  uvec[i] = Array<OneD, NekDouble>(nq, 0.0);
2500  }
2501 
2502  Array<OneD, NekDouble> x(nq);
2503  Array<OneD, NekDouble> y(nq);
2504  Array<OneD, NekDouble> z(nq);
2505 
2506  m_fields[0]->GetCoords(x, y, z);
2507 
2508  int Nint = 1000;
2509  NekDouble dth, intj;
2510  for (int j = 0; j < nq; ++j)
2511  {
2512  x0j = x[j];
2513  x1j = y[j];
2514  x2j = z[j];
2515 
2516  CartesianToSpherical(x0j, x1j, x2j, sin_varphi, cos_varphi, sin_theta,
2517  cos_theta);
2518 
2519  Ttheta = atan2(sin_theta, cos_theta);
2520  Tphi = atan2(sin_varphi, cos_varphi);
2521 
2522  uhat = ComputeUnstableJetuphi(Ttheta);
2523  vhat = 0.0;
2524 
2525  // eta = - (1/g) (\Omega u_0 + 0.4 u^2 ) \sin^2 \theta
2526  dth = Ttheta / Nint;
2527  eta[j] = dth * 0.5 *
2529  for (int i = 1; i < Nint - 1; i++)
2530  {
2531  intj = i * dth;
2532  eta[j] = eta[j] + dth * ComputeUnstableJetEta(intj);
2533  }
2534  eta[j] = (-1.0 / m_g) * eta[j];
2535 
2536  // Add perturbation
2537  if (m_PurturbedJet)
2538  {
2539  eta[j] =
2540  eta[j] +
2541  m_hbar * cos_theta * exp(-9.0 * Tphi * Tphi) *
2542  exp(-225.0 * (m_pi / 4.0 - Ttheta) * (m_pi / 4.0 - Ttheta));
2543  }
2544 
2545  uvec[0][j] = -1.0 * uhat * sin_varphi - vhat * sin_theta * cos_varphi;
2546  uvec[1][j] = uhat * cos_varphi - vhat * sin_theta * sin_varphi;
2547  uvec[2][j] = vhat * cos_theta;
2548  }
2549 
2550  // Projection of u onto the tangent plane with conserving the mag. of the
2551  // velocity.
2553 
2554  for (int i = 0; i < m_spacedim; ++i)
2555  {
2556  uvecproj[i] = Array<OneD, NekDouble>(nq, 0.0);
2557  }
2558 
2559  // u is projected on the tangent plane with preserving its length
2560  // GramSchumitz(m_surfaceNormal, uvec, uvecproj, true);
2561 
2562  // Change it to the coordinate of moving frames
2563  // CartesianToMovingframes(0,uvecproj,u);
2564  // CartesianToMovingframes(1,uvecproj,v);
2565 
2566  u = CartesianToMovingframes(uvec, 0);
2567  v = CartesianToMovingframes(uvec, 1);
2568 
2569  switch (field)
2570  {
2571  case (0):
2572  {
2573  outfield = eta;
2574  }
2575  break;
2576 
2577  case (1):
2578  {
2579  outfield = u;
2580  }
2581  break;
2582 
2583  case (2):
2584  {
2585  outfield = v;
2586  }
2587  break;
2588  }
2589 }
2590 
2591 void MMFSWE::RossbyWave(unsigned int field, Array<OneD, NekDouble> &outfield)
2592 {
2593  int nq = GetTotPoints();
2594  NekDouble uhat, vhat;
2595  NekDouble sin_theta, cos_theta, sin_varphi, cos_varphi;
2596  NekDouble x0j, x1j, x2j;
2597  NekDouble Ath, Bth, Cth, tmp;
2598 
2599  Array<OneD, NekDouble> eta(nq, 0.0);
2600  Array<OneD, NekDouble> u(nq, 0.0);
2601  Array<OneD, NekDouble> v(nq, 0.0);
2602 
2604  for (int i = 0; i < m_spacedim; ++i)
2605  {
2606  uvec[i] = Array<OneD, NekDouble>(nq, 0.0);
2607  }
2608 
2609  Array<OneD, NekDouble> x(nq);
2610  Array<OneD, NekDouble> y(nq);
2611  Array<OneD, NekDouble> z(nq);
2612 
2613  m_fields[0]->GetCoords(x, y, z);
2614 
2615  NekDouble R = 4.0;
2616  NekDouble cos2theta, cosRtheta, cos6theta, cos2Rtheta, cosRm1theta;
2617  NekDouble cos2phi, cos4phi, sin4phi, cos8phi;
2618 
2619  // disturbancees of Rossby-Haurwitz Wave
2620  NekDouble x0d, y0d, z0d, phi0, theta0;
2621  //NekDouble rad_earth = 6.37122 * 1000000;
2622 
2623  phi0 = 40.0 * m_pi / 180.0;
2624  theta0 = 50.0 * m_pi / 180.0;
2625 
2626  x0d = cos(phi0) * cos(theta0);
2627  y0d = sin(phi0) * cos(theta0);
2628  z0d = sin(theta0);
2629 
2630  for (int j = 0; j < nq; ++j)
2631  {
2632  x0j = x[j];
2633  x1j = y[j];
2634  x2j = z[j];
2635 
2636  CartesianToSpherical(x0j, x1j, x2j, sin_varphi, cos_varphi, sin_theta,
2637  cos_theta);
2638 
2639  // H = H_0 - (1/g)*(a \Omega u_0 + 0.5*u_0^2 )*(- \cos \phi \cos \theta
2640  // \sin \alpha + \sin \theta \cos \alpha )^2
2641 
2642  // tmp = cos^{2R} \theta, R = 4;
2643  cos2theta = cos_theta * cos_theta;
2644  cosRm1theta = cos_theta * cos2theta;
2645  cosRtheta = cos2theta * cos2theta;
2646  cos6theta = cos2theta * cosRtheta;
2647  cos2Rtheta = cosRtheta * cosRtheta;
2648 
2649  tmp = (0.5 * m_angfreq) * (2.0 * m_Omega + m_angfreq);
2650  Ath = tmp * cos2theta +
2651  0.25 * m_K * m_K * cos6theta *
2652  ((R + 1.0) * cosRtheta + (2 * R * R - R - 2.0) * cos2theta -
2653  2 * R * R);
2654 
2655  tmp = (2.0 * m_K) * (m_Omega + m_angfreq) / ((R + 1.0) * (R + 2.0));
2656  Bth = tmp * cosRtheta *
2657  ((R * R + 2 * R + 2) - (R + 1.0) * (R + 1.0) * cos2theta);
2658 
2659  Cth =
2660  0.25 * m_K * m_K * cos2Rtheta * ((R + 1.0) * cos2theta - (R + 2.0));
2661 
2662  // cos (2 \phi) = 2 * cos \phi * cos \phi - 1.0
2663  cos2phi = 2.0 * cos_varphi * cos_varphi - 1.0;
2664  cos4phi = 2.0 * cos2phi * cos2phi - 1.0;
2665  cos8phi = 2.0 * cos4phi * cos4phi - 1.0;
2666 
2667  // sin (2 \phi) = 2 * cos \phi * sin \phi
2668  sin4phi = 4.0 * sin_varphi * cos_varphi * cos2phi;
2669 
2670  eta[j] = m_H0 + (1.0 / m_g) * (Ath + Bth * cos4phi + Cth * cos8phi);
2671 
2672  // disturbances is added
2673  if (m_RossbyDisturbance)
2674  {
2675  eta[j] = eta[j] *
2676  (1.0 + (1.0 / 40.0) * (x0j * x0d + x1j * y0d + x2j * z0d));
2677  }
2678 
2679  // u = (\vec{u} \cdot e^1 )/ || e^1 ||^2 , v = (\vec{u} \cdot e^2 )/
2680  // || e^2 ||^2
2681  uhat = m_angfreq * cos_theta +
2682  m_K * cosRm1theta * (R * sin_theta * sin_theta - cos2theta) *
2683  cos4phi;
2684  vhat = -1.0 * m_K * R * cosRm1theta * sin_theta * sin4phi;
2685 
2686  uvec[0][j] = -1.0 * uhat * sin_varphi - vhat * sin_theta * cos_varphi;
2687  uvec[1][j] = uhat * cos_varphi - vhat * sin_theta * sin_varphi;
2688  uvec[2][j] = vhat * cos_theta;
2689  }
2690 
2691  // NekDouble etamin, etaaver;
2692  // etamin = Vmath::Vmin(nq, eta, 1)*rad_earth;
2693  // etaaver = Vmath::Vsum(nq, eta, 1)/nq*rad_earth;
2694 
2695  // Projection of u onto the tangent plane with conserving the mag. of the
2696  // velocity.
2698 
2699  for (int i = 0; i < m_spacedim; ++i)
2700  {
2701  uvecproj[i] = Array<OneD, NekDouble>(nq, 0.0);
2702  }
2703 
2704  // u is projected on the tangent plane with preserving its length
2705  // GramSchumitz(m_surfaceNormal, uvec, uvecproj, true);
2706 
2707  // Change it to the coordinate of moving frames
2708  // CartesianToMovingframes(0,uvecproj,u);
2709  // CartesianToMovingframes(1,uvecproj,v);
2710 
2711  u = CartesianToMovingframes(uvec, 0);
2712  v = CartesianToMovingframes(uvec, 1);
2713 
2714  switch (field)
2715  {
2716  case (0):
2717  {
2718  outfield = eta;
2719  }
2720  break;
2721 
2722  case (1):
2723  {
2724  outfield = u;
2725  }
2726  break;
2727 
2728  case (2):
2729  {
2730  outfield = v;
2731  }
2732  break;
2733  }
2734 }
2735 
2737 {
2738  NekDouble uphi, f, dh;
2739 
2740  uphi = ComputeUnstableJetuphi(theta);
2741  f = 2.0 * m_Omega * sin(theta);
2742 
2743  dh = f * uphi + tan(theta) * uphi * uphi;
2744 
2745  return dh;
2746 }
2747 
2749 {
2750  NekDouble uphi;
2751 
2752  if ((theta > m_theta0) && (theta < m_theta1))
2753  {
2754  uphi = (m_uthetamax / m_en) *
2755  exp(1.0 / (theta - m_theta0) / (theta - m_theta1));
2756  }
2757 
2758  else
2759  {
2760  uphi = 0.0;
2761  }
2762 
2763  return uphi;
2764 }
2765 
2766 void MMFSWE::Checkpoint_Output_Cartesian(std::string outname)
2767 {
2768  int nq = m_fields[0]->GetTotPoints();
2769  int ncoeffs = m_fields[0]->GetNcoeffs();
2770 
2771  NekDouble rad_earth = 6.37122 * 1000000;
2772 
2773  int nvariables = 7;
2774 
2775  // vector u in Cartesian coordinates
2776  std::vector<std::string> variables(nvariables);
2777 
2778  variables[0] = "eta";
2779  variables[1] = "hstar";
2780  variables[2] = "vorticity";
2781  variables[3] = "ux";
2782  variables[4] = "uy";
2783  variables[5] = "uz";
2784  variables[6] = "null";
2785 
2786  // Obtain \vec{u} in cartesian coordinate
2787  Array<OneD, Array<OneD, NekDouble>> fieldphys(nvariables);
2788  std::vector<Array<OneD, NekDouble>> fieldcoeffs(nvariables);
2789  for (int i = 0; i < nvariables; ++i)
2790  {
2791  fieldphys[i] = Array<OneD, NekDouble>(nq, 0.0);
2792  fieldcoeffs[i] = Array<OneD, NekDouble>(ncoeffs);
2793  }
2794 
2795  Vmath::Smul(nq, rad_earth, &(m_fields[0]->GetPhys())[0], 1,
2796  &fieldphys[0][0], 1);
2797  // Vmath::Vadd(nq, &(m_fields[0]->GetPhys())[0], 1, &m_depth[0], 1,
2798  // &fieldphys[1][0], 1);
2799 
2800  Vmath::Vcopy(nq, &m_depth[0], 1, &fieldphys[1][0], 1);
2801  Vmath::Neg(nq, &fieldphys[1][0], 1);
2802  Vmath::Sadd(nq, m_H0, &fieldphys[1][0], 1, &fieldphys[1][0], 1);
2803  Vmath::Smul(nq, rad_earth, &fieldphys[1][0], 1, &fieldphys[1][0], 1);
2804 
2805  Array<OneD, NekDouble> utmp(nq);
2806  Array<OneD, NekDouble> vtmp(nq);
2807 
2808  Vmath::Vcopy(nq, &(m_fields[1]->GetPhys())[0], 1, &utmp[0], 1);
2809  Vmath::Vcopy(nq, &(m_fields[2]->GetPhys())[0], 1, &vtmp[0], 1);
2810 
2811  ComputeVorticity(utmp, vtmp, fieldphys[2]);
2812  // u_x = u e^1_x + v e^2_x
2813  int indx = 3;
2814  for (int k = 0; k < m_spacedim; ++k)
2815  {
2816  Vmath::Vmul(nq, &utmp[0], 1, &m_movingframes[0][k * nq], 1,
2817  &fieldphys[k + indx][0], 1);
2818  Vmath::Vvtvp(nq, &vtmp[0], 1, &m_movingframes[1][k * nq], 1,
2819  &fieldphys[k + indx][0], 1, &fieldphys[k + indx][0], 1);
2820  }
2821 
2822  for (int i = 0; i < nvariables; ++i)
2823  {
2824  m_fields[0]->FwdTrans(fieldphys[i], fieldcoeffs[i]);
2825  }
2826 
2827  WriteFld(outname, m_fields[0], fieldcoeffs, variables);
2828 }
2829 
2830 // (h, hu, hv) -> (\eta, u, v)
2832  const Array<OneD, const Array<OneD, NekDouble>> &physin,
2833  Array<OneD, Array<OneD, NekDouble>> &physout)
2834 {
2835  int nq = GetTotPoints();
2836 
2837  if (physin[0].get() == physout[0].get())
2838  {
2839  // copy indata and work with tmp array
2841  for (int i = 0; i < 3; ++i)
2842  {
2843  // deep copy
2844  tmp[i] = Array<OneD, NekDouble>(nq);
2845  Vmath::Vcopy(nq, physin[i], 1, tmp[i], 1);
2846  }
2847 
2848  // \eta = h - d
2849  Vmath::Vsub(nq, tmp[0], 1, m_depth, 1, physout[0], 1);
2850 
2851  // u = hu/h
2852  Vmath::Vdiv(nq, tmp[1], 1, tmp[0], 1, physout[1], 1);
2853 
2854  // v = hv/h
2855  Vmath::Vdiv(nq, tmp[2], 1, tmp[0], 1, physout[2], 1);
2856  }
2857  else
2858  {
2859  // \eta = h - d
2860  Vmath::Vsub(nq, physin[0], 1, m_depth, 1, physout[0], 1);
2861 
2862  // u = hu/h
2863  Vmath::Vdiv(nq, physin[1], 1, physin[0], 1, physout[1], 1);
2864 
2865  // v = hv/h
2866  Vmath::Vdiv(nq, physin[2], 1, physin[0], 1, physout[2], 1);
2867  }
2868 }
2869 
2871  const Array<OneD, const Array<OneD, NekDouble>> &physin,
2872  Array<OneD, Array<OneD, NekDouble>> &physout)
2873 {
2874 
2875  int nq = GetTotPoints();
2876 
2877  if (physin[0].get() == physout[0].get())
2878  {
2879  // copy indata and work with tmp array
2881  for (int i = 0; i < 3; ++i)
2882  {
2883  // deep copy
2884  tmp[i] = Array<OneD, NekDouble>(nq);
2885  Vmath::Vcopy(nq, physin[i], 1, tmp[i], 1);
2886  }
2887 
2888  // h = \eta + d
2889  Vmath::Vadd(nq, tmp[0], 1, m_depth, 1, physout[0], 1);
2890 
2891  // hu = h * u
2892  Vmath::Vmul(nq, physout[0], 1, tmp[1], 1, physout[1], 1);
2893 
2894  // hv = h * v
2895  Vmath::Vmul(nq, physout[0], 1, tmp[2], 1, physout[2], 1);
2896  }
2897  else
2898  {
2899  // h = \eta + d
2900  Vmath::Vadd(nq, physin[0], 1, m_depth, 1, physout[0], 1);
2901 
2902  // hu = h * u
2903  Vmath::Vmul(nq, physout[0], 1, physin[1], 1, physout[1], 1);
2904 
2905  // hv = h * v
2906  Vmath::Vmul(nq, physout[0], 1, physin[2], 1, physout[2], 1);
2907  }
2908 }
2909 
2910 // To obtain [eta, u, v ] from [H, Hu, Hv]
2912 {
2913  int nq = GetTotPoints();
2914 
2915  // u = hu/h
2916  Vmath::Vdiv(nq, m_fields[1]->GetPhys(), 1, m_fields[0]->GetPhys(), 1,
2917  m_fields[1]->UpdatePhys(), 1);
2918 
2919  // v = hv/ v
2920  Vmath::Vdiv(nq, m_fields[2]->GetPhys(), 1, m_fields[0]->GetPhys(), 1,
2921  m_fields[2]->UpdatePhys(), 1);
2922 
2923  // \eta = h - d
2924  Vmath::Vsub(nq, m_fields[0]->GetPhys(), 1, m_depth, 1,
2925  m_fields[0]->UpdatePhys(), 1);
2926 }
2927 
2929 {
2930  int nq = GetTotPoints();
2931 
2932  // h = \eta + d
2933  Vmath::Vadd(nq, m_fields[0]->GetPhys(), 1, m_depth, 1,
2934  m_fields[0]->UpdatePhys(), 1);
2935 
2936  // hu = h * u
2937  Vmath::Vmul(nq, m_fields[0]->GetPhys(), 1, m_fields[1]->GetPhys(), 1,
2938  m_fields[1]->UpdatePhys(), 1);
2939 
2940  // hv = h * v
2941  Vmath::Vmul(nq, m_fields[0]->GetPhys(), 1, m_fields[2]->GetPhys(), 1,
2942  m_fields[2]->UpdatePhys(), 1);
2943 }
2944 
2946 {
2947  // Construct beta
2948  int i, k;
2949  int n = 1, m = 1;
2950  int nq = m_fields[0]->GetTotPoints();
2951 
2952  NekDouble alpha, beta_theta, beta_phi;
2953 
2954  NekDouble xp, yp, zp, Re;
2955  NekDouble theta, phi, sin_theta, cos_theta, sin_varphi, cos_varphi;
2956  NekDouble cosntheta3;
2957 
2958  NekDouble thetax, thetay, thetaz;
2959  NekDouble phix, phiy, phiz;
2960 
2961  Array<OneD, NekDouble> x(nq);
2962  Array<OneD, NekDouble> y(nq);
2963  Array<OneD, NekDouble> z(nq);
2964 
2965  Array<OneD, NekDouble> u(nq);
2966  Array<OneD, NekDouble> v(nq);
2967 
2968  Array<OneD, NekDouble> vorticitycompt(nq);
2969  Array<OneD, NekDouble> vorticityexact(nq);
2970 
2971  m_fields[0]->GetCoords(x, y, z);
2972 
2974  for (i = 0; i < m_spacedim; ++i)
2975  {
2976  uvec[i] = Array<OneD, NekDouble>(nq, 0.0);
2977  }
2978 
2979  // Generate SphericalCoords
2980  for (k = 0; k < nq; ++k)
2981  {
2982  xp = x[k];
2983  yp = y[k];
2984  zp = z[k];
2985 
2986  Re = sqrt(xp * xp + yp * yp + zp * zp);
2987 
2988  CartesianToSpherical(xp, yp, zp, sin_varphi, cos_varphi, sin_theta,
2989  cos_theta);
2990 
2991  alpha = sin_varphi;
2992 
2993  theta = atan2(sin_theta, cos_theta);
2994  phi = atan2(sin_varphi, cos_varphi);
2995 
2996  cosntheta3 = cos(n * theta) * cos(n * theta) * cos(n * theta);
2997 
2998  beta_theta = -4.0 * n * cosntheta3 * cos(m * phi) * sin(n * theta) / Re;
2999  beta_phi = -m * cosntheta3 * sin(m * phi) / Re;
3000 
3001  thetax = -1.0 * cos_varphi * sin_theta;
3002  thetay = -1.0 * sin_varphi * sin_theta;
3003  thetaz = cos_theta;
3004 
3005  phix = -1.0 * sin_varphi;
3006  phiy = cos_varphi;
3007  phiz = 0.0;
3008 
3009  uvec[0][k] = alpha * (beta_theta * thetax + beta_phi * phix);
3010  uvec[1][k] = alpha * (beta_theta * thetay + beta_phi * phiy);
3011  uvec[2][k] = alpha * (beta_theta * thetaz + beta_phi * phiz);
3012 
3013  vorticityexact[k] = -4.0 * n / Re / Re * cos_theta * cos_theta *
3014  cos_varphi * cos(m * phi) * sin(n * theta);
3015  }
3016 
3017  u = CartesianToMovingframes(uvec, 0);
3018  v = CartesianToMovingframes(uvec, 1);
3019 
3020  std::cout << "chi migi1" << std::endl;
3021 
3022  ComputeVorticity(u, v, vorticitycompt);
3023  /*for (int k=0; k < nq; k++)
3024  {
3025 
3026  std::cout << "vorticitycompt[ " << k << "]"<< "\t"<<vorticitycompt[k]<<
3027  std::endl;
3028 
3029  }*/
3030 
3031  Vmath::Vsub(nq, vorticityexact, 1, vorticitycompt, 1, vorticitycompt, 1);
3032 
3033  std::cout << "Vorticity: L2 error = " << AvgAbsInt(vorticitycompt)
3034  << ", Linf error = " << Vmath::Vamax(nq, vorticitycompt, 1)
3035  << std::endl;
3036 }
3037 
3038 NekDouble MMFSWE::v_L2Error(unsigned int field,
3039  const Array<OneD, NekDouble> &exactsoln,
3040  bool Normalised)
3041 {
3042  boost::ignore_unused(exactsoln);
3043 
3044  int nq = m_fields[field]->GetNpoints();
3045  NekDouble L2error = -1.0;
3046 
3047  if (m_NumQuadPointsError == 0)
3048  {
3049  if (m_fields[field]->GetPhysState() == false)
3050  {
3051  m_fields[field]->BwdTrans(m_fields[field]->GetCoeffs(),
3052  m_fields[field]->UpdatePhys());
3053  }
3054 
3055  switch (field)
3056  {
3057  case (0):
3058  {
3059  // I(h) = I (h - h_exact ) / I (h_exact)
3060  Array<OneD, NekDouble> exactsolution(nq);
3061  v_EvaluateExactSolution(0, exactsolution, m_time);
3062 
3063  // exactsoln = u - u_T so that L2 compute u_T
3064  NekDouble L2exact = m_fields[0]->Integral(exactsolution);
3065 
3066  Vmath::Vsub(nq, &(m_fields[0]->GetPhys())[0], 1,
3067  &exactsolution[0], 1, &exactsolution[0], 1);
3068  Vmath::Vabs(nq, exactsolution, 1, exactsolution, 1);
3069 
3070  L2error = (m_fields[0]->Integral(exactsolution)) / L2exact;
3071  }
3072  break;
3073 
3074  case (1):
3075  {
3076  // I2 (u) = I( (u - u_ext)^2 + (v - v_ext)^2 )^{1/2} / I(
3077  // u_ext^2 + v_ext^2 )^{1/2}
3078  Array<OneD, NekDouble> exactu(nq);
3079  Array<OneD, NekDouble> exactv(nq);
3080  Array<OneD, NekDouble> tmp(nq);
3081 
3082  // L2exact = \int (\sqrt{exactu*exactu+exactv*exactv})
3083  NekDouble L2exact;
3084  v_EvaluateExactSolution(1, exactu, m_time);
3085  v_EvaluateExactSolution(2, exactv, m_time);
3086  Vmath::Vmul(nq, exactu, 1, exactu, 1, tmp, 1);
3087  Vmath::Vvtvp(nq, exactv, 1, exactv, 1, tmp, 1, tmp, 1);
3088  Vmath::Vsqrt(nq, tmp, 1, tmp, 1);
3089 
3090  L2exact = m_fields[1]->Integral(tmp);
3091 
3092  // L2exact = \int
3093  // (\sqrt{(u-exactu)*(u-exactu)+(v-exactv)*(v-exactv)})
3094  Vmath::Vsub(nq, &(m_fields[1]->GetPhys())[0], 1, &exactu[0], 1,
3095  &exactu[0], 1);
3096  Vmath::Vsub(nq, &(m_fields[2]->GetPhys())[0], 1, &exactv[0], 1,
3097  &exactv[0], 1);
3098  Vmath::Vmul(nq, exactu, 1, exactu, 1, tmp, 1);
3099  Vmath::Vvtvp(nq, exactv, 1, exactv, 1, tmp, 1, tmp, 1);
3100  Vmath::Vsqrt(nq, tmp, 1, tmp, 1);
3101 
3102  L2error = (m_fields[1]->Integral(tmp)) / L2exact;
3103  }
3104  break;
3105 
3106  case (2):
3107  {
3108  L2error = 0.0;
3109  }
3110  break;
3111 
3112  default:
3113  break;
3114  }
3115 
3116  if (Normalised == true)
3117  {
3118  Array<OneD, NekDouble> one(m_fields[field]->GetNpoints(), 1.0);
3119 
3120  NekDouble Vol = m_fields[field]->Integral(one);
3121  m_comm->AllReduce(Vol, LibUtilities::ReduceSum);
3122 
3123  L2error = sqrt(L2error * L2error / Vol);
3124  }
3125  }
3126  else
3127  {
3128  Array<OneD, NekDouble> L2INF(2);
3129  L2INF = ErrorExtraPoints(field);
3130  L2error = L2INF[0];
3131  }
3132 
3133  return L2error;
3134 }
3135 
3136 NekDouble MMFSWE::v_LinfError(unsigned int field,
3137  const Array<OneD, NekDouble> &exactsoln)
3138 {
3139  boost::ignore_unused(exactsoln);
3140 
3141  NekDouble LinfError = -1.0;
3142 
3143  if (m_fields[field]->GetPhysState() == false)
3144  {
3145  m_fields[field]->BwdTrans(m_fields[field]->GetCoeffs(),
3146  m_fields[field]->UpdatePhys());
3147  }
3148 
3149  int nq = m_fields[field]->GetNpoints();
3150 
3151  // Obtain \vec{u} in cartesian coordinate
3152  Array<OneD, NekDouble> x(nq);
3153  Array<OneD, NekDouble> y(nq);
3154  Array<OneD, NekDouble> z(nq);
3155 
3156  m_fields[0]->GetCoords(x, y, z);
3157 
3158  switch (field)
3159  {
3160  case (0):
3161  {
3162  NekDouble Letaint;
3163 
3164  Array<OneD, NekDouble> exactsolution(nq);
3165 
3166  EvaluateExactSolution(field, exactsolution, m_time);
3167  LinfError = m_fields[field]->Linf(m_fields[field]->GetPhys(),
3168  exactsolution);
3169 
3170  Letaint = Vmath::Vamax(nq, exactsolution, 1);
3171 
3172  Vmath::Vsub(nq, &(m_fields[0]->GetPhys())[0], 1, &exactsolution[0],
3173  1, &exactsolution[0], 1);
3174 
3175  LinfError = fabs(LinfError / Letaint);
3176  }
3177  break;
3178 
3179  case (1):
3180  {
3181  Array<OneD, NekDouble> exactu(nq);
3182  Array<OneD, NekDouble> exactv(nq);
3183  Array<OneD, NekDouble> tmpu(nq);
3184  Array<OneD, NekDouble> tmpv(nq);
3185  Array<OneD, NekDouble> Lerr(nq);
3186  Array<OneD, NekDouble> uT(nq);
3187 
3188  EvaluateExactSolution(1, exactu, m_time);
3189  EvaluateExactSolution(2, exactv, m_time);
3190 
3191  // Compute max[sqrt{(u-uex)^2 + (v-vex)^2}]
3192  Vmath::Vcopy(nq, &(m_fields[1]->UpdatePhys())[0], 1, &tmpu[0], 1);
3193  Vmath::Vcopy(nq, &(m_fields[2]->UpdatePhys())[0], 1, &tmpv[0], 1);
3194 
3195  Vmath::Vsub(nq, &exactu[0], 1, &tmpu[0], 1, &tmpu[0], 1);
3196  Vmath::Vsub(nq, &exactv[0], 1, &tmpv[0], 1, &tmpv[0], 1);
3197 
3198  Vmath::Vmul(nq, &tmpu[0], 1, &tmpu[0], 1, &tmpu[0], 1);
3199  Vmath::Vmul(nq, &tmpv[0], 1, &tmpv[0], 1, &tmpv[0], 1);
3200 
3201  Vmath::Vadd(nq, &tmpu[0], 1, &tmpv[0], 1, &Lerr[0], 1);
3202  Vmath::Vsqrt(nq, &Lerr[0], 1, &Lerr[0], 1);
3203 
3204  // uT = max[sqrt( u_T^2 + v_T^2 ) ]
3205  Vmath::Vmul(nq, &exactu[0], 1, &exactu[0], 1, &tmpu[0], 1);
3206  Vmath::Vmul(nq, &exactv[0], 1, &exactv[0], 1, &tmpv[0], 1);
3207  Vmath::Vadd(nq, &tmpu[0], 1, &tmpv[0], 1, &uT[0], 1);
3208  Vmath::Vsqrt(nq, &uT[0], 1, &uT[0], 1);
3209 
3210  LinfError = Vmath::Vamax(nq, Lerr, 1) / Vmath::Vamax(nq, uT, 1);
3211  }
3212  break;
3213 
3214  case (2):
3215  {
3216  LinfError = 0.0;
3217  }
3218  break;
3219 
3220  default:
3221  break;
3222  }
3223 
3224  return LinfError;
3225 }
3226 
3227 void MMFSWE::v_EvaluateExactSolution(unsigned int field,
3228  Array<OneD, NekDouble> &outfield,
3229  const NekDouble time)
3230 {
3231  switch (m_TestType)
3232  {
3233  case eTestSteadyZonal:
3234  {
3235  SteadyZonalFlow(field, outfield);
3236  }
3237  break;
3238 
3239  case eTestUnsteadyZonal:
3240  {
3241  UnsteadyZonalFlow(field, time, outfield);
3242  }
3243  break;
3244 
3245  case eTestIsolatedMountain:
3246  {
3247  IsolatedMountainFlow(field, time, outfield);
3248  }
3249  break;
3250 
3251  case eTestUnstableJet:
3252  {
3253  UnstableJetFlow(field, time, outfield);
3254  }
3255  break;
3256 
3257  case eTestRossbyWave:
3258  {
3259  RossbyWave(field, outfield);
3260  }
3261  break;
3262 
3263  case eTestPlane:
3264  {
3265  TestSWE2Dproblem(time, field, outfield);
3266  }
3267  break;
3268 
3269  default:
3270  break;
3271  }
3272 }
3273 
3275 {
3278 
3279  switch (m_TestType)
3280  {
3281  case eTestSteadyZonal:
3282  {
3283  SolverUtils::AddSummaryItem(s, "Rotation Angle", m_alpha);
3284  }
3285  break;
3286 
3287  case eTestRossbyWave:
3288  {
3289  SolverUtils::AddSummaryItem(s, "RossbyDistrubance",
3291  }
3292  break;
3293 
3294  case eTestUnstableJet:
3295  {
3296  SolverUtils::AddSummaryItem(s, "PurturbedJet", m_PurturbedJet);
3297  }
3298  break;
3299 
3300  default:
3301  break;
3302  }
3303 }
3304 
3305 } // end namespace Nektar
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
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
void ComputeVorticity(const Array< OneD, const NekDouble > &u, const Array< OneD, const NekDouble > &v, Array< OneD, NekDouble > &Vorticity)
Definition: MMFSWE.cpp:2209
void AddCoriolis(Array< OneD, Array< OneD, NekDouble >> &physarray, Array< OneD, Array< OneD, NekDouble >> &outarray)
Definition: MMFSWE.cpp:1199
void UnstableJetFlow(unsigned int field, const NekDouble time, Array< OneD, NekDouble > &outfield)
Definition: MMFSWE.cpp:2480
virtual void v_EvaluateExactSolution(unsigned int field, Array< OneD, NekDouble > &outfield, const NekDouble time)
Definition: MMFSWE.cpp:3227
int m_PurturbedJet
Definition: MMFSWE.h:276
NekDouble m_k2
Definition: MMFSWE.h:96
NekDouble ComputeUnstableJetuphi(const NekDouble theta)
Definition: MMFSWE.cpp:2748
MMFSWE(const LibUtilities::SessionReaderSharedPtr &pSession, const SpatialDomains::MeshGraphSharedPtr &pGraph)
Session reader.
Definition: MMFSWE.cpp:52
NekDouble m_alpha
Definition: MMFSWE.h:95
void AddElevationEffect(Array< OneD, Array< OneD, NekDouble >> &physarray, Array< OneD, Array< OneD, NekDouble >> &outarray)
Definition: MMFSWE.cpp:1244
static SolverUtils::EquationSystemSharedPtr create(const LibUtilities::SessionReaderSharedPtr &pSession, const SpatialDomains::MeshGraphSharedPtr &pGraph)
Creates an instance of this class.
Definition: MMFSWE.h:67
virtual ~MMFSWE()
Destructor.
Definition: MMFSWE.cpp:245
NekDouble m_en
Definition: MMFSWE.h:98
void RossbyWave(unsigned int field, Array< OneD, NekDouble > &outfield)
Definition: MMFSWE.cpp:2591
void ComputeNablaCdotVelocity(Array< OneD, NekDouble > &vellc)
Definition: MMFSWE.cpp:2230
NekDouble m_Energy0
Definition: MMFSWE.h:101
void GetSWEFluxVector(const int i, const Array< OneD, const Array< OneD, NekDouble >> &physfield, Array< OneD, Array< OneD, NekDouble >> &flux)
Definition: MMFSWE.cpp:580
void AddDivForGradient(Array< OneD, Array< OneD, NekDouble >> &physarray, Array< OneD, Array< OneD, NekDouble >> &outarray)
Definition: MMFSWE.cpp:550
void WeakDGSWEDirDeriv(const Array< OneD, Array< OneD, NekDouble >> &InField, Array< OneD, Array< OneD, NekDouble >> &OutField)
Definition: MMFSWE.cpp:480
void EvaluateStandardCoriolis(Array< OneD, NekDouble > &outarray)
Definition: MMFSWE.cpp:1757
static std::string className
Name of class.
Definition: MMFSWE.h:77
virtual void v_GenerateSummary(SolverUtils::SummaryList &s)
Print Summary.
Definition: MMFSWE.cpp:3274
NekDouble m_theta0
Definition: MMFSWE.h:98
void PrimitiveToConservative()
Definition: MMFSWE.cpp:2928
void IsolatedMountainFlow(unsigned int field, const NekDouble time, Array< OneD, NekDouble > &outfield)
Definition: MMFSWE.cpp:2391
NekDouble m_hbar
Definition: MMFSWE.h:98
NekDouble m_K
Definition: MMFSWE.h:99
Array< OneD, NekDouble > m_coriolis
Coriolis force.
Definition: MMFSWE.h:90
void ComputeMagAndDot(const int index, NekDouble &MageF1, NekDouble &MageF2, NekDouble &MageB1, NekDouble &MageB2, NekDouble &eF1_cdot_eB1, NekDouble &eF1_cdot_eB2, NekDouble &eF2_cdot_eB1, NekDouble &eF2_cdot_eB2)
Definition: MMFSWE.cpp:1161
void DoOdeRhs(const Array< OneD, const Array< OneD, NekDouble >> &inarray, Array< OneD, Array< OneD, NekDouble >> &outarray, const NekDouble time)
Compute the RHS.
Definition: MMFSWE.cpp:424
NekDouble m_Hvar
Definition: MMFSWE.h:95
void Compute_demdt_cdot_ek(const int indm, const int indk, const Array< OneD, const Array< OneD, NekDouble >> &physarray, Array< OneD, NekDouble > &outarray)
Definition: MMFSWE.cpp:1320
TestType m_TestType
Definition: MMFSWE.h:79
void AverageFlux(const int index, NekDouble hL, NekDouble uL, NekDouble vL, NekDouble hR, NekDouble uR, NekDouble vR, Array< OneD, NekDouble > &numfluxF, Array< OneD, NekDouble > &numfluxB)
Definition: MMFSWE.cpp:958
NekDouble m_Vorticity0
Definition: MMFSWE.h:101
void Checkpoint_Output_Cartesian(std::string outname)
Definition: MMFSWE.cpp:2766
void Computehhuhvflux(NekDouble hL, NekDouble uL, NekDouble vL, NekDouble hR, NekDouble uR, NekDouble vR, NekDouble hstar, NekDouble &hflux, NekDouble &huflux, NekDouble &hvflux)
Definition: MMFSWE.cpp:892
void TestVorticityComputation()
Definition: MMFSWE.cpp:2945
void RiemannSolverHLLC(const int index, NekDouble hL, NekDouble uL, NekDouble vL, NekDouble hR, NekDouble uR, NekDouble vR, Array< OneD, NekDouble > &numfluxF, Array< OneD, NekDouble > &numfluxB)
Definition: MMFSWE.cpp:846
NekDouble ComputeEnstrophy(const Array< OneD, const NekDouble > &eta, const Array< OneD, const NekDouble > &u, const Array< OneD, const NekDouble > &v)
Definition: MMFSWE.cpp:2178
void NumericalSWEFlux(Array< OneD, Array< OneD, NekDouble >> &physfield, Array< OneD, Array< OneD, NekDouble >> &numfluxFwd, Array< OneD, Array< OneD, NekDouble >> &numfluxBwd)
Definition: MMFSWE.cpp:675
NekDouble m_uthetamax
Definition: MMFSWE.h:98
NekDouble ComputeMass(const Array< OneD, const NekDouble > &eta)
Definition: MMFSWE.cpp:2139
void EvaluateWaterDepth(void)
Definition: MMFSWE.cpp:1555
void UnsteadyZonalFlow(unsigned int field, const NekDouble time, Array< OneD, NekDouble > &outfield)
Definition: MMFSWE.cpp:2290
virtual NekDouble v_LinfError(unsigned int field, const Array< OneD, NekDouble > &exactsoln)
Virtual function for the L_inf error computation between fields and a given exact solution.
Definition: MMFSWE.cpp:3136
virtual void v_DoInitialise()
Sets up initial conditions.
Definition: MMFSWE.cpp:1538
NekDouble ComputeEnergy(const Array< OneD, const NekDouble > &eta, const Array< OneD, const NekDouble > &u, const Array< OneD, const NekDouble > &v)
Definition: MMFSWE.cpp:2149
void LaxFriedrichFlux(const int index, NekDouble hL, NekDouble uL, NekDouble vL, NekDouble hR, NekDouble uR, NekDouble vR, Array< OneD, NekDouble > &numfluxF, Array< OneD, NekDouble > &numfluxB)
Definition: MMFSWE.cpp:1012
NekDouble ComputeUnstableJetEta(const NekDouble theta)
Definition: MMFSWE.cpp:2736
virtual void v_DoSolve()
Solves an unsteady problem.
Definition: MMFSWE.cpp:249
NekDouble m_Mass0
Definition: MMFSWE.h:101
void EvaluateCoriolis(void)
Definition: MMFSWE.cpp:1695
void EvaluateCoriolisForZonalFlow(Array< OneD, NekDouble > &outarray)
Definition: MMFSWE.cpp:1725
virtual NekDouble v_L2Error(unsigned int field, const Array< OneD, NekDouble > &exactsoln, bool Normalised)
Virtual function for the L_2 error computation between fields and a given exact solution.
Definition: MMFSWE.cpp:3038
NekDouble m_theta1
Definition: MMFSWE.h:98
int m_AddRotation
Definition: MMFSWE.h:92
Array< OneD, Array< OneD, NekDouble > > m_velocity
Advection velocity.
Definition: MMFSWE.h:107
int m_planeNumber
Definition: MMFSWE.h:115
virtual void v_SetInitialConditions(const NekDouble initialtime, bool dumpInitialConditions, const int domain)
Definition: MMFSWE.cpp:1784
void WallBoundary2D(int bcRegion, int cnt, Array< OneD, Array< OneD, NekDouble >> &physarray)
Definition: MMFSWE.cpp:1425
void SetBoundaryConditions(Array< OneD, Array< OneD, NekDouble >> &inarray, NekDouble time)
Definition: MMFSWE.cpp:1375
NekDouble m_angfreq
Definition: MMFSWE.h:99
void TestSWE2Dproblem(const NekDouble time, unsigned int field, Array< OneD, NekDouble > &outfield)
Definition: MMFSWE.cpp:1983
NekDouble m_Omega
Definition: MMFSWE.h:95
int m_RossbyDisturbance
Definition: MMFSWE.h:275
NekDouble m_H0
Definition: MMFSWE.h:95
int m_AddCoriolis
Definition: MMFSWE.h:92
void AddRotation(Array< OneD, Array< OneD, NekDouble >> &physarray, Array< OneD, Array< OneD, NekDouble >> &outarray)
Definition: MMFSWE.cpp:1273
Array< OneD, Array< OneD, NekDouble > > m_Derivdepth
Definition: MMFSWE.h:87
NekDouble m_u0
Definition: MMFSWE.h:95
void ConservativeToPrimitive()
Definition: MMFSWE.cpp:2911
NekDouble m_Enstrophy0
Definition: MMFSWE.h:101
void SteadyZonalFlow(unsigned int field, Array< OneD, NekDouble > &outfield)
Definition: MMFSWE.cpp:2048
virtual void v_InitObject()
Initialise the object.
Definition: MMFSWE.cpp:62
void RusanovFlux(const int index, NekDouble hL, NekDouble uL, NekDouble vL, NekDouble hR, NekDouble uR, NekDouble vR, Array< OneD, NekDouble > &numfluxF, Array< OneD, NekDouble > &numfluxB)
Definition: MMFSWE.cpp:1087
Array< OneD, NekDouble > m_depth
Still water depth.
Definition: MMFSWE.h:86
NekDouble m_g
Definition: MMFSWE.h:94
NekDouble m_hs0
Definition: MMFSWE.h:97
void DoOdeProjection(const Array< OneD, const Array< OneD, NekDouble >> &inarray, Array< OneD, Array< OneD, NekDouble >> &outarray, const NekDouble time)
Compute the projection.
Definition: MMFSWE.cpp:1356
int m_spacedim
Spatial dimension (>= expansion dim).
SOLVER_UTILS_EXPORT int GetTraceNpoints()
int m_expdim
Expansion dimension.
LibUtilities::CommSharedPtr m_comm
Communicator.
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.
SOLVER_UTILS_EXPORT NekDouble LinfError(unsigned int field, const Array< OneD, NekDouble > &exactsoln=NullNekDouble1DArray)
Linf error computation.
SOLVER_UTILS_EXPORT void EvaluateExactSolution(int field, Array< OneD, NekDouble > &outfield, const NekDouble time)
Evaluates an exact solution.
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.
SOLVER_UTILS_EXPORT int GetExpSize()
std::string m_sessionName
Name of the session.
LibUtilities::SessionReaderSharedPtr m_session
The session reader.
SOLVER_UTILS_EXPORT Array< OneD, NekDouble > ErrorExtraPoints(unsigned int field)
Compute error (L2 and L_inf) over an larger set of quadrature points return [L2 Linf].
SOLVER_UTILS_EXPORT int GetNpoints()
SOLVER_UTILS_EXPORT int GetNcoeffs()
enum MultiRegions::ProjectionType m_projectionType
Type of projection; e.g continuous or discontinuous.
int m_steps
Number of steps to take.
int m_NumQuadPointsError
Number of Quadrature points used to work out the error.
int m_checksteps
Number of steps between checkpoints.
SOLVER_UTILS_EXPORT void SetInitialConditions(NekDouble initialtime=0.0, bool dumpInitialConditions=true, const int domain=0)
Initialise the data in the dependent fields.
SOLVER_UTILS_EXPORT SessionFunctionSharedPtr GetFunction(std::string name, const MultiRegions::ExpListSharedPtr &field=MultiRegions::NullExpListSharedPtr, bool cache=false)
Get a SessionFunction by name.
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
Array< OneD, Array< OneD, NekDouble > > m_DivMF
Definition: MMFSystem.h:189
Array< OneD, Array< OneD, NekDouble > > m_nperpcdotMFFwd
Definition: MMFSystem.h:186
Array< OneD, Array< OneD, NekDouble > > m_nperpcdotMFBwd
Definition: MMFSystem.h:187
SOLVER_UTILS_EXPORT NekDouble AvgAbsInt(const Array< OneD, const NekDouble > &inarray)
Definition: MMFSystem.cpp:2336
Array< OneD, Array< OneD, NekDouble > > m_movingframes
Definition: MMFSystem.h:180
Array< OneD, Array< OneD, Array< OneD, NekDouble > > > m_MFtraceFwd
Definition: MMFSystem.h:193
Array< OneD, Array< OneD, Array< OneD, NekDouble > > > m_MFtraceBwd
Definition: MMFSystem.h:194
SOLVER_UTILS_EXPORT void MMFInitObject(const Array< OneD, const Array< OneD, NekDouble >> &Anisotropy, const int TangentXelem=-1)
Definition: MMFSystem.cpp:53
SOLVER_UTILS_EXPORT void CopyBoundaryTrace(const Array< OneD, const NekDouble > &Fwd, Array< OneD, NekDouble > &Bwd, const BoundaryCopyType BDCopyType, const int var=0, const std::string btype="NoUserDefined")
Definition: MMFSystem.cpp:838
Array< OneD, Array< OneD, NekDouble > > m_ncdotMFBwd
Definition: MMFSystem.h:184
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_ncdotMFFwd
Definition: MMFSystem.h:183
Array< OneD, Array< OneD, Array< OneD, NekDouble > > > m_CurlMF
Definition: MMFSystem.h:190
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.
NekDouble m_cflSafetyFactor
CFL safety factor (comprise between 0 to 1).
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 void Daxpy(const int &n, const double &alpha, const double *x, const int &incx, const double *y, const int &incy)
BLAS level 1: y = alpha x plus y.
Definition: Blas.hpp:167
std::shared_ptr< SessionReader > SessionReaderSharedPtr
static const NekDouble kNekZeroTol
std::vector< std::pair< std::string, std::string > > SummaryList
Definition: Misc.h:46
EquationSystemFactory & GetEquationSystemFactory()
@ eAverage
averaged (or centred) flux
Definition: MMFSystem.h:77
@ eLaxFriedrich
Lax-Friedrich flux.
Definition: MMFSystem.h:78
@ eHLLC
Harten-Lax-Leer Contact wave flux.
Definition: MMFSystem.h:82
@ eRusanov
Upwind.
Definition: MMFSystem.h:80
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
std::shared_ptr< MeshGraph > MeshGraphSharedPtr
Definition: MeshGraph.h:174
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:1
@ eTestUnstableJet
Definition: MMFSWE.h:50
@ eTestSteadyZonal
Definition: MMFSWE.h:47
@ eTestPlane
Definition: MMFDiffusion.h:48
@ eTestUnsteadyZonal
Definition: MMFSWE.h:48
@ SIZE_TestType
Length of enum list.
Definition: MMFDiffusion.h:55
@ eTestIsolatedMountain
Definition: MMFSWE.h:49
@ eTestRossbyWave
Definition: MMFSWE.h:51
const char *const TestTypeMap[]
Definition: MMFDiffusion.h:58
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 Vabs(int n, const T *x, const int incx, T *y, const int incy)
vabs: y = |x|
Definition: Vmath.cpp:493
void Neg(int n, T *x, const int incx)
Negate x = -x.
Definition: Vmath.cpp:461
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
void Fill(int n, const T alpha, T *x, const int incx)
Fill a vector with a constant value.
Definition: Vmath.cpp:45
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
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 > abs(scalarT< T > in)
Definition: scalar.hpp:272
scalarT< T > sqrt(scalarT< T > in)
Definition: scalar.hpp:267