Nektar++
MMFAdvection.cpp
Go to the documentation of this file.
1/////////////////////////////////////////////////////////////////////////////
2//
3// File: MMFAdvection.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/algorithm/string.hpp>
39#include <boost/core/ignore_unused.hpp>
40
44
45namespace Nektar
46{
47std::string MMFAdvection::className =
49 "MMFAdvection", MMFAdvection::create, "MMFAdvection equation.");
50
53 : UnsteadySystem(pSession, pGraph), MMFSystem(pSession, pGraph),
54 AdvectionSystem(pSession, pGraph)
55{
56 m_planeNumber = 0;
57}
58
59/**
60 * @brief Initialisation object for the unsteady linear advection equation.
61 */
62void MMFAdvection::v_InitObject(bool DeclareFields)
63{
64 // Call to the initialisation object
65 UnsteadySystem::v_InitObject(DeclareFields);
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 // Define TestType
78 ASSERTL0(m_session->DefinesSolverInfo("TESTTYPE"),
79 "No TESTTYPE defined in session.");
80 std::string TestTypeStr = m_session->GetSolverInfo("TESTTYPE");
81 for (int i = 0; i < (int)SIZE_TestType; ++i)
82 {
83 if (boost::iequals(TestTypeMap[i], TestTypeStr))
84 {
86 break;
87 }
88 }
89
90 m_session->LoadParameter("Angular Frequency", m_waveFreq, m_pi);
91 m_session->LoadParameter("Rotational Angle", m_RotAngle, 0.0);
92 m_session->LoadParameter("Velocity Projection", m_VelProjection, 0);
93
94 // Read the advection velocities from session file
95 m_session->LoadParameter("advx", m_advx, 1.0);
96 m_session->LoadParameter("advy", m_advy, 1.0);
97 m_session->LoadParameter("advz", m_advz, 1.0);
98
99 std::vector<std::string> vel;
100 vel.push_back("Vx");
101 vel.push_back("Vy");
102 vel.push_back("Vz");
103
104 // Resize the advection velocities vector to dimension of the problem
105 vel.resize(m_spacedim);
106
107 // Store in the global variable m_velocity the advection velocities
109 for (int k = 0; k < m_spacedim; ++k)
110 {
112 }
113
114 switch (m_surfaceType)
115 {
120 {
121 // true = project velocity onto the tangent plane
123 }
124 break;
125
128 {
129 GetFunction("AdvectionVelocity")->Evaluate(vel, m_velocity);
130 }
131 break;
132
133 default:
134 break;
135 }
136
137 std::cout << "|Velocity vector| = ( " << RootMeanSquare(m_velocity[0])
138 << " , " << RootMeanSquare(m_velocity[1]) << " , "
139 << RootMeanSquare(m_velocity[2]) << " ) " << std::endl;
140
141 // Define the normal velocity fields
142 if (m_fields[0]->GetTrace())
143 {
145 }
146
147 std::string advName;
148 std::string riemName;
149 m_session->LoadSolverInfo("AdvectionType", advName, "WeakDG");
152 m_advObject->SetFluxVector(&MMFAdvection::GetFluxVector, this);
153 m_session->LoadSolverInfo("UpwindType", riemName, "Upwind");
155 riemName, m_session);
156 m_riemannSolver->SetScalar("Vn", &MMFAdvection::GetNormalVelocity, this);
157
158 m_advObject->SetRiemannSolver(m_riemannSolver);
159 m_advObject->InitObject(m_session, m_fields);
160
161 // Compute m_traceVn = n \cdot v
163
164 // Compute m_vellc = nabal a^j \cdot m_vel
166 std::cout << "m_vellc is generated with mag = " << AvgInt(m_vellc)
167 << std::endl;
168
169 // Compute vel \cdot MF
171
172 // Modify e^i as v^i e^i
173 for (int j = 0; j < m_shapedim; j++)
174 {
175 for (int k = 0; k < m_spacedim; k++)
176 {
177 Vmath::Vmul(nq, &m_veldotMF[j][0], 1, &m_movingframes[j][k * nq], 1,
178 &m_movingframes[j][k * nq], 1);
179 }
180 }
181
182 // Reflect it into m_ncdotMFFwd and Bwd
184
185 // If explicit it computes RHS and PROJECTION for the time integration
187 {
190 }
191 // Otherwise it gives an error (no implicit integration)
192 else
193 {
194 ASSERTL0(false, "Implicit unsteady Advection not set up.");
195 }
196}
197
198/**
199 * @brief Unsteady linear advection equation destructor.
200 */
202{
203}
204
206{
207 ASSERTL0(m_intScheme != 0, "No time integration scheme.");
208
209 int i, nchk = 1;
210 int nvariables = 0;
211 int nfields = m_fields.size();
212 int nq = m_fields[0]->GetNpoints();
213
214 if (m_intVariables.empty())
215 {
216 for (i = 0; i < nfields; ++i)
217 {
218 m_intVariables.push_back(i);
219 }
220 nvariables = nfields;
221 }
222 else
223 {
224 nvariables = m_intVariables.size();
225 }
226
227 // Set up wrapper to fields data storage.
228 Array<OneD, Array<OneD, NekDouble>> fields(nvariables);
229 Array<OneD, Array<OneD, NekDouble>> tmp(nvariables);
230
231 // Order storage to list time-integrated fields first.
232 for (i = 0; i < nvariables; ++i)
233 {
234 fields[i] = m_fields[m_intVariables[i]]->GetPhys();
235 m_fields[m_intVariables[i]]->SetPhysState(false);
236 }
237
238 // Initialise time integration scheme
239 m_intScheme->InitializeScheme(m_timestep, fields, m_time, m_ode);
240
241 // Check uniqueness of checkpoint output
242 ASSERTL0((m_checktime == 0.0 && m_checksteps == 0) ||
243 (m_checktime > 0.0 && m_checksteps == 0) ||
244 (m_checktime == 0.0 && m_checksteps > 0),
245 "Only one of IO_CheckTime and IO_CheckSteps "
246 "should be set!");
247
249 bool doCheckTime = false;
250 int step = 0;
251 NekDouble intTime = 0.0;
252 NekDouble cpuTime = 0.0;
253 NekDouble elapsed = 0.0;
254
255 int Ntot, indx;
256 // Perform integration in time.
257 Ntot = m_checksteps ? m_steps / m_checksteps + 1 : 0;
258
259 Array<OneD, NekDouble> dMass(Ntot ? Ntot : 1);
260
261 Array<OneD, NekDouble> zeta(nq);
262 Array<OneD, Array<OneD, NekDouble>> fieldsprimitive(nvariables);
263 for (int i = 0; i < nvariables; ++i)
264 {
265 fieldsprimitive[i] = Array<OneD, NekDouble>(nq);
266 }
267
269 {
270 timer.Start();
271 fields = m_intScheme->TimeIntegrate(step, m_timestep);
272 timer.Stop();
273
275 elapsed = timer.TimePerTest(1);
276 intTime += elapsed;
277 cpuTime += elapsed;
278
279 // Write out status information
280 if (m_infosteps && !((step + 1) % m_infosteps) &&
281 m_session->GetComm()->GetRank() == 0)
282 {
283 std::cout << "Steps: " << std::setw(8) << std::left << step + 1
284 << " "
285 << "Time: " << std::setw(12) << std::left << m_time;
286
287 std::stringstream ss;
288 ss << cpuTime << "s";
289 std::cout << " CPU Time: " << std::setw(8) << std::left << ss.str()
290 << std::endl;
291
292 // Masss = h^*
293 indx = m_checksteps ? (step + 1) / m_checksteps : 0;
294 dMass[indx] =
295 (m_fields[0]->Integral(fields[0]) - m_Mass0) / m_Mass0;
296
297 std::cout << "dMass = " << std::setw(8) << std::left << dMass[indx]
298 << std::endl;
299
300 cpuTime = 0.0;
301 }
302
303 // Transform data into coefficient space
304 for (i = 0; i < nvariables; ++i)
305 {
306 m_fields[m_intVariables[i]]->SetPhys(fields[i]);
307 m_fields[m_intVariables[i]]->FwdTransLocalElmt(
308 fields[i], m_fields[m_intVariables[i]]->UpdateCoeffs());
309 m_fields[m_intVariables[i]]->SetPhysState(false);
310 }
311
312 // Write out checkpoint files
313 if ((m_checksteps && step && !((step + 1) % m_checksteps)) ||
314 doCheckTime)
315 {
316 Checkpoint_Output(nchk++);
317 doCheckTime = false;
318 }
319
320 // Step advance
321 ++step;
322 }
323
324 std::cout << "dMass = ";
325 for (i = 0; i < Ntot; ++i)
326 {
327 std::cout << dMass[i] << " , ";
328 }
329 std::cout << std::endl << std::endl;
330
331 // Print out summary statistics
332 if (m_session->GetComm()->GetRank() == 0)
333 {
334 if (m_cflSafetyFactor > 0.0)
335 {
336 std::cout << "CFL safety factor : " << m_cflSafetyFactor
337 << std::endl
338 << "CFL time-step : " << m_timestep << std::endl;
339 }
340
341 if (m_session->GetSolverInfo("Driver") != "SteadyState")
342 {
343 std::cout << "Time-integration : " << intTime << "s" << std::endl;
344 }
345 }
346
347 for (i = 0; i < nvariables; ++i)
348 {
349 m_fields[m_intVariables[i]]->SetPhys(fields[i]);
350 m_fields[m_intVariables[i]]->SetPhysState(true);
351 }
352
353 for (i = 0; i < nvariables; ++i)
354 {
355 m_fields[i]->FwdTrans(m_fields[i]->GetPhys(),
356 m_fields[i]->UpdateCoeffs());
357 }
358}
359
360/**
361 * @brief Get the normal velocity for the linear advection equation.
362 */
364{
365 // Number of trace (interface) points
366 int i;
367 int nTracePts = GetTraceNpoints();
368
369 // Auxiliary variable to compute the normal velocity
370 Array<OneD, NekDouble> tmp(nTracePts);
371
372 // Reset the normal velocity
373 Vmath::Zero(nTracePts, m_traceVn, 1);
374
375 for (i = 0; i < m_velocity.size(); ++i)
376 {
377 m_fields[0]->ExtractTracePhys(m_velocity[i], tmp);
378
379 Vmath::Vvtvp(nTracePts, m_traceNormals[i], 1, tmp, 1, m_traceVn, 1,
380 m_traceVn, 1);
381 }
382
383 return m_traceVn;
384}
385
386/**
387 * @brief Compute the right-hand side for the linear advection equation.
388 *
389 * @param inarray Given fields.
390 * @param outarray Calculated solution.
391 * @param time Time.
392 */
394 const Array<OneD, const Array<OneD, NekDouble>> &inarray,
395 Array<OneD, Array<OneD, NekDouble>> &outarray, const NekDouble time)
396{
397 boost::ignore_unused(time);
398
399 int i;
400 int nvariables = inarray.size();
401 int npoints = GetNpoints();
402
403 switch (m_projectionType)
404 {
406 {
407 int ncoeffs = inarray[0].size();
408
409 if (m_spacedim == 3)
410 {
411 Array<OneD, Array<OneD, NekDouble>> WeakAdv(nvariables);
412
413 WeakAdv[0] = Array<OneD, NekDouble>(ncoeffs * nvariables);
414 for (i = 1; i < nvariables; ++i)
415 {
416 WeakAdv[i] = WeakAdv[i - 1] + ncoeffs;
417 }
418
419 // Compute \nabla \cdot \vel u according to MMF scheme
420 WeakDGDirectionalAdvection(inarray, WeakAdv);
421
422 for (i = 0; i < nvariables; ++i)
423 {
424 m_fields[i]->MultiplyByElmtInvMass(WeakAdv[i], WeakAdv[i]);
425 m_fields[i]->BwdTrans(WeakAdv[i], outarray[i]);
426 Vmath::Neg(npoints, outarray[i], 1);
427 }
428 }
429 else
430 {
431 m_advObject->Advect(2, m_fields, m_velocity, inarray, outarray,
432 0.0);
433
434 for (i = 0; i < nvariables; ++i)
435 {
436 Vmath::Neg(npoints, outarray[i], 1);
437 }
438 }
439 }
440 break;
441
442 default:
443 {
444 ASSERTL0(false, "Unknown projection scheme");
445 }
446 break;
447 }
448}
449
450/**
451 * @brief Compute the projection for the linear advection equation.
452 *
453 * @param inarray Given fields.
454 * @param outarray Calculated solution.
455 * @param time Time.
456 */
458 const Array<OneD, const Array<OneD, NekDouble>> &inarray,
459 Array<OneD, Array<OneD, NekDouble>> &outarray, const NekDouble time)
460{
461 // Counter variable
462 int i;
463
464 // Number of fields (variables of the problem)
465 int nVariables = inarray.size();
466
467 // Set the boundary conditions
469
470 // Switch on the projection type (Discontinuous or Continuous)
471 switch (m_projectionType)
472 {
473 // Discontinuous projection
475 {
476 // Number of quadrature points
477 int nQuadraturePts = GetNpoints();
478
479 // Just copy over array
480 if (inarray != outarray)
481 {
482 for (i = 0; i < nVariables; ++i)
483 {
484 Vmath::Vcopy(nQuadraturePts, inarray[i], 1, outarray[i], 1);
485 }
486 }
487 break;
488 }
489
490 // Continuous projection
493 {
494 Array<OneD, NekDouble> coeffs(m_fields[0]->GetNcoeffs(), 0.0);
495 for (i = 0; i < nVariables; ++i)
496 {
497 m_fields[i]->FwdTrans(inarray[i], coeffs);
498 m_fields[i]->BwdTrans(coeffs, outarray[i]);
499 }
500 break;
501 }
502
503 default:
504 ASSERTL0(false, "Unknown projection scheme");
505 break;
506 }
507}
508
509/**
510 * @brief Return the flux vector for the linear advection equation.
511 *
512 * @param i Component of the flux vector to calculate.
513 * @param physfield Fields.
514 * @param flux Resulting flux.
515 */
517 const Array<OneD, Array<OneD, NekDouble>> &physfield,
519{
520 ASSERTL1(flux[0].size() == m_velocity.size(),
521 "Dimension of flux array and velocity array do not match");
522
523 int i, j;
524 int nq = physfield[0].size();
525
526 for (i = 0; i < flux.size(); ++i)
527 {
528 for (j = 0; j < flux[0].size(); ++j)
529 {
530 Vmath::Vmul(nq, physfield[i], 1, m_velocity[j], 1, flux[i][j], 1);
531 }
532 }
533}
534
536 const Array<OneD, Array<OneD, NekDouble>> &InField,
538{
539 int i, j;
540 int ncoeffs = GetNcoeffs();
541 int nTracePointsTot = GetTraceNpoints();
542 int nvariables = m_fields.size();
543
544 Array<OneD, Array<OneD, NekDouble>> physfield(nvariables);
545
546 // Get the variables in physical space
547 // already in physical space
548 for (i = 0; i < nvariables; ++i)
549 {
550 physfield[i] = InField[i];
551 }
552
554 for (i = 0; i < nvariables; ++i)
555 {
556 for (j = 0; j < m_shapedim; ++j)
557 {
558 WeakDeriv[j] = Array<OneD, NekDouble>(ncoeffs, 0.0);
559
560 // Directional derivation with respect to the j'th moving frame
561 // tmp[j] = \nabla \physfield[i] \cdot \mathbf{e}^j
562 // Implemented at TriExp::v_IProductWRTDirectionalDerivBase_SumFa
563 m_fields[0]->IProductWRTDirectionalDerivBase(
564 m_movingframes[j], physfield[i], WeakDeriv[j]);
565 }
566
567 // Get the numerical flux and add to the modal coeffs
568 // if the NumericalFluxs function already includes the
569 // normal in the output
570
571 Array<OneD, NekDouble> Fwd(nTracePointsTot);
572 Array<OneD, NekDouble> Bwd(nTracePointsTot);
573
574 Array<OneD, NekDouble> flux(nTracePointsTot, 0.0);
575 Array<OneD, NekDouble> fluxFwd(nTracePointsTot);
576 Array<OneD, NekDouble> fluxBwd(nTracePointsTot);
577
578 // Evaluate numerical flux in physical space which may in
579 // general couple all component of vectors
580 m_fields[i]->GetFwdBwdTracePhys(physfield[i], Fwd, Bwd);
581
582 // evaulate upwinded m_fields[i]
583 m_fields[i]->GetTrace()->Upwind(m_traceVn, Fwd, Bwd, flux);
584
585 OutField[i] = Array<OneD, NekDouble>(ncoeffs, 0.0);
586 for (j = 0; j < m_shapedim; ++j)
587 {
588 // calculate numflux = (n \cdot MF)*flux
589 Vmath::Vmul(nTracePointsTot, &flux[0], 1, &m_ncdotMFFwd[j][0], 1,
590 &fluxFwd[0], 1);
591 Vmath::Vmul(nTracePointsTot, &flux[0], 1, &m_ncdotMFBwd[j][0], 1,
592 &fluxBwd[0], 1);
593 Vmath::Neg(ncoeffs, WeakDeriv[j], 1);
594
595 // FwdBwdtegral because generallize (N \cdot MF)_{FWD} \neq -(N
596 // \cdot MF)_{BWD}
597 m_fields[i]->AddFwdBwdTraceIntegral(fluxFwd, fluxBwd, WeakDeriv[j]);
598 m_fields[i]->SetPhysState(false);
599
600 Vmath::Vadd(ncoeffs, &WeakDeriv[j][0], 1, &OutField[i][0], 1,
601 &OutField[i][0], 1);
602 }
603 }
604}
605
608{
609 int nq = m_fields[0]->GetNpoints();
610
611 NekDouble vel_phi, vel_theta, sin_varphi, cos_varphi, sin_theta, cos_theta;
612 NekDouble x0j, x1j, x2j;
613
617
618 m_fields[0]->GetCoords(x0, x1, x2);
619
620 // theta = a*sin(z/r), phi = a*tan(y/x);
621 for (int j = 0; j < nq; j++)
622 {
623 x0j = x0[j];
624 x1j = x1[j];
625 x2j = x2[j];
626
627 CartesianToSpherical(x0j, x1j, x2j, sin_varphi, cos_varphi, sin_theta,
628 cos_theta);
629
630 vel_phi = m_waveFreq * (cos_theta * cos(m_RotAngle) +
631 sin_theta * cos_varphi * sin(m_RotAngle));
632 vel_theta = -1.0 * m_waveFreq * sin_theta * sin(m_RotAngle);
633
634 velocity[0][j] =
635 -1.0 * vel_phi * sin_varphi - vel_theta * sin_theta * cos_varphi;
636 velocity[1][j] =
637 vel_phi * cos_varphi - vel_theta * sin_theta * sin_varphi;
638 velocity[2][j] = vel_theta * cos_theta;
639 }
640
641 // Project the veloicty on the tangent plane
642
643 if (m_VelProjection)
644 {
645 // Check MovingFrames \cdot SurfaceNormals = 0
647
651
652 for (int k = 0; k < m_spacedim; ++k)
653 {
654 newvelocity[k] = Array<OneD, NekDouble>(nq);
655 MF1[k] = Array<OneD, NekDouble>(nq);
656 MF2[k] = Array<OneD, NekDouble>(nq);
657 SN[k] = Array<OneD, NekDouble>(nq);
658
659 Vmath::Vcopy(nq, &m_movingframes[0][k * nq], 1, &MF1[k][0], 1);
660 Vmath::Vcopy(nq, &m_movingframes[1][k * nq], 1, &MF2[k][0], 1);
661 }
662
663 VectorCrossProd(MF1, MF2, SN);
664 GramSchumitz(SN, m_velocity, newvelocity, true);
665
666 Array<OneD, NekDouble> tmp(nq, 0.0);
668
669 for (int k = 0; k < m_spacedim; ++k)
670 {
671 Vmath::Vsub(nq, &m_velocity[0][0], 1, &newvelocity[0][0], 1,
672 &tmp[0], 1);
673 Vmath::Vmul(nq, &tmp[0], 1, &tmp[0], 1, &tmp[0], 1);
674 Vmath::Vadd(nq, tmp, 1, Projection, 1, Projection, 1);
675 }
676
677 std::cout
678 << "Velocity vector is projected onto the tangent plane: Diff = "
679 << RootMeanSquare(Projection) << std::endl;
680
681 for (int k = 0; k < m_spacedim; ++k)
682 {
683 Vmath::Vcopy(nq, &newvelocity[k][0], 1, &m_velocity[k][0], 1);
684 }
685 }
686}
687
689 const NekDouble Rhs)
690{
691
692 NekDouble Tol = 0.0001, Maxiter = 1000, N = 100;
693 NekDouble newy, F = 0.0, dF = 1.0, y0, tmp;
694
695 Array<OneD, NekDouble> xp(N + 1);
696 Array<OneD, NekDouble> yp(N + 1);
697
698 NekDouble intval = 0.0;
699 switch (m_surfaceType)
700 {
703 {
704 intval = sqrt(Rhs - zlevel * zlevel);
705 }
706 break;
707
709 {
710 intval = sqrt(0.5 * (Rhs - zlevel * zlevel * zlevel * zlevel -
711 zlevel * zlevel));
712 }
713 break;
714
716 {
717 tmp = 0.5 *
718 (Rhs - zlevel * zlevel * zlevel * zlevel - zlevel * zlevel);
719 intval = sqrt(0.5 * (1.0 + sqrt(1.0 + 4.0 * tmp)));
720 }
721 break;
722
723 default:
724 break;
725 }
726
727 switch (m_surfaceType)
728 {
729 // Find the half of all the xp and yp on zlevel ....
733 {
734 for (int j = 0; j < N + 1; ++j)
735 {
736 xp[j] = j * 2.0 * intval / N - intval;
737
738 y0 = 1.0;
739 for (int i = 0; i < Maxiter; ++i)
740 {
741 switch (m_surfaceType)
742 {
743 // Find the half of all the xp and yp on zlevel ....
746 {
747 F = xp[j] * xp[j] + y0 * y0 + zlevel * zlevel - Rhs;
748 dF = 2.0 * y0;
749 }
750 break;
751
753 {
754 F = 2.0 * xp[j] * xp[j] + y0 * y0 * y0 * y0 +
755 y0 * y0 + zlevel * zlevel * zlevel * zlevel +
756 zlevel * zlevel - Rhs;
757 dF = 4.0 * y0 * y0 * y0 + 2.0 * y0;
758 }
759 break;
760
761 default:
762 break;
763 }
764
765 newy = y0 - F / dF;
766
767 if (fabs(F / dF) < Tol)
768 {
769 yp[j] = newy;
770 break;
771 }
772
773 else
774 {
775 y0 = newy;
776 }
777
778 ASSERTL0(i < Maxiter,
779 "Advection Velocity convergence fails");
780
781 } // i-loop
782 }
783 }
784 break;
785
787 {
788 for (int j = 0; j < N + 1; ++j)
789 {
790 xp[j] = j * 2.0 * intval / N - intval;
791 tmp = 0.5 * Rhs -
792 0.5 * (zlevel * zlevel * zlevel * zlevel +
793 zlevel * zlevel) -
794 (xp[j] * xp[j] * xp[j] * xp[j] - xp[j] * xp[j]);
795 if (tmp < 0)
796 {
797 tmp = -1.0 * tmp;
798 }
799 yp[j] = sqrt(tmp);
800 } // j-loop
801 }
802 break;
803
804 default:
805 break;
806
807 } // switch-loop
808
809 NekDouble pi = 3.14159265358979323846;
810 NekDouble arclength = 0.0;
811 for (int j = 0; j < N; ++j)
812 {
813 arclength =
814 arclength + sqrt((yp[j + 1] - yp[j]) * (yp[j + 1] - yp[j]) +
815 (xp[j + 1] - xp[j]) * (xp[j + 1] - xp[j])) /
816 pi;
817 }
818
819 return arclength;
820}
821
823 bool dumpInitialConditions,
824 const int domain)
825{
826 boost::ignore_unused(domain);
827
828 int nq = m_fields[0]->GetNpoints();
829
831
832 switch (m_TestType)
833 {
834 case eAdvectionBell:
835 {
837 m_fields[0]->SetPhys(u);
838
839 m_Mass0 = m_fields[0]->Integral(u);
840
841 // forward transform to fill the modal coeffs
842 for (int i = 0; i < m_fields.size(); ++i)
843 {
844 m_fields[i]->SetPhysState(true);
845 m_fields[i]->FwdTrans(m_fields[i]->GetPhys(),
846 m_fields[i]->UpdateCoeffs());
847 }
848 }
849 break;
850
851 case eTestPlane:
852 {
853 Test2Dproblem(initialtime, u);
854 m_fields[0]->SetPhys(u);
855
856 m_Mass0 = m_fields[0]->Integral(u);
857
858 // forward transform to fill the modal coeffs
859 for (int i = 0; i < m_fields.size(); ++i)
860 {
861 m_fields[i]->SetPhysState(true);
862 m_fields[i]->FwdTrans(m_fields[i]->GetPhys(),
863 m_fields[i]->UpdateCoeffs());
864 }
865 }
866 break;
867
869 {
871 m_fields[0]->SetPhys(u);
872
873 m_Mass0 = m_fields[0]->Integral(u);
874 std::cout << "m_Mass0 = " << m_Mass0 << std::endl;
875
876 // forward transform to fill the modal coeffs
877 for (int i = 0; i < m_fields.size(); ++i)
878 {
879 m_fields[i]->SetPhysState(true);
880 m_fields[i]->FwdTrans(m_fields[i]->GetPhys(),
881 m_fields[i]->UpdateCoeffs());
882 }
883 }
884 break;
885
886 case eTestCube:
887 {
888 Test3Dproblem(initialtime, u);
889 m_fields[0]->SetPhys(u);
890
891 // forward transform to fill the modal coeffs
892 for (int i = 0; i < m_fields.size(); ++i)
893 {
894 m_fields[i]->SetPhysState(true);
895 m_fields[i]->FwdTrans(m_fields[i]->GetPhys(),
896 m_fields[i]->UpdateCoeffs());
897 }
898 }
899 break;
900
901 default:
902 break;
903 }
904
905 if (dumpInitialConditions)
906 {
907 // dump initial conditions to file
908 std::string outname = m_sessionName + "_initial.chk";
909 WriteFld(outname);
910 }
911}
912
914{
915 int nq = m_fields[0]->GetNpoints();
916
917 NekDouble dist, m_radius_limit;
918
922
923 m_fields[0]->GetCoords(x, y, z);
924
925 // Sets of parameters
926 m_radius_limit = 0.5;
927
928 NekDouble x0j, x1j;
929 outfield = Array<OneD, NekDouble>(nq, 0.0);
930 for (int j = 0; j < nq; ++j)
931 {
932 x0j = x[j];
933 x1j = y[j];
934
935 dist = sqrt(x0j * x0j + x1j * x1j);
936
937 if (dist < m_radius_limit)
938 {
939 outfield[j] = 0.5 * (1.0 + cos(m_pi * dist / m_radius_limit));
940 }
941 else
942 {
943 outfield[j] = 0.0;
944 }
945 }
946}
947
949{
950 int nq = m_fields[0]->GetNpoints();
951
952 NekDouble dist, radius, cosdiff, sin_theta, cos_theta, sin_varphi,
953 cos_varphi;
954 NekDouble m_theta_c, m_varphi_c, m_radius_limit, m_c0;
955
959
960 m_fields[0]->GetCoords(x, y, z);
961
962 // Sets of parameters
963 m_theta_c = 0.0;
964 m_varphi_c = 3.0 * m_pi / 2.0;
965 m_radius_limit = 7.0 * m_pi / 64.0;
966 m_c0 = 0.0;
967
968 NekDouble x0j, x1j, x2j;
969 outfield = Array<OneD, NekDouble>(nq, 0.0);
970 for (int j = 0; j < nq; ++j)
971 {
972 x0j = x[j];
973 x1j = y[j];
974 x2j = z[j];
975
976 radius = sqrt(x0j * x0j + x1j * x1j + x2j * x2j);
977
978 sin_varphi = x1j / sqrt(x0j * x0j + x1j * x1j);
979 cos_varphi = x0j / sqrt(x0j * x0j + x1j * x1j);
980
981 sin_theta = x2j / radius;
982 cos_theta = sqrt(x0j * x0j + x1j * x1j) / radius;
983
984 cosdiff = cos_varphi * cos(m_varphi_c) + sin_varphi * sin(m_varphi_c);
985 dist = radius * acos(sin(m_theta_c) * sin_theta +
986 cos(m_theta_c) * cos_theta * cosdiff);
987
988 if (dist < m_radius_limit)
989 {
990 outfield[j] =
991 0.5 * (1.0 + cos(m_pi * dist / m_radius_limit)) + m_c0;
992 }
993 else
994 {
995 outfield[j] = m_c0;
996 }
997 }
998}
999
1001 Array<OneD, NekDouble> &outfield)
1002{
1003 int nq = m_fields[0]->GetNpoints();
1004
1008
1009 m_fields[0]->GetCoords(x0, x1, x2);
1010
1012
1013 for (int i = 0; i < nq; ++i)
1014 {
1015 u[i] = cos(m_pi * (x0[i] - m_advx * time)) *
1016 cos(m_pi * (x1[i] - m_advy * time));
1017 }
1018
1019 outfield = u;
1020}
1021
1023 Array<OneD, NekDouble> &outfield)
1024{
1025 int nq = m_fields[0]->GetNpoints();
1026
1030
1031 m_fields[0]->GetCoords(x0, x1, x2);
1032
1034
1035 for (int i = 0; i < nq; ++i)
1036 {
1037 u[i] = cos(m_pi * (x0[i] - m_advx * time)) *
1038 cos(m_pi * (x1[i] - m_advy * time)) *
1039 cos(m_pi * (x2[i] - m_advz * time));
1040 }
1041
1042 outfield = u;
1043}
1044
1046{
1047 int nq = m_fields[0]->GetNpoints();
1048
1049 Array<OneD, NekDouble> velcoeff(nq, 0.0);
1050
1051 Array<OneD, NekDouble> Dtmp0(nq);
1052 Array<OneD, NekDouble> Dtmp1(nq);
1053 Array<OneD, NekDouble> Dtmp2(nq);
1054 Array<OneD, NekDouble> Drv(nq);
1055
1056 vellc = Array<OneD, NekDouble>(nq, 0.0);
1057
1058 // m_vellc = \nabla m_vel \cdot tan_i
1059 Array<OneD, NekDouble> tmp(nq);
1060 Array<OneD, NekDouble> vessel(nq);
1061
1062 for (int j = 0; j < m_shapedim; ++j)
1063 {
1064 Vmath::Zero(nq, velcoeff, 1);
1065 for (int k = 0; k < m_spacedim; ++k)
1066 {
1067 // a_j = tan_j cdot m_vel
1068 Vmath::Vvtvp(nq, &m_movingframes[j][k * nq], 1, &m_velocity[k][0],
1069 1, &velcoeff[0], 1, &velcoeff[0], 1);
1070 }
1071
1072 // d a_j / d x^k
1073 m_fields[0]->PhysDeriv(velcoeff, Dtmp0, Dtmp1, Dtmp2);
1074
1075 for (int k = 0; k < m_spacedim; ++k)
1076 {
1077 // tan_j^k ( d a_j / d x^k )
1078 switch (k)
1079 {
1080 case (0):
1081 {
1082 Vmath::Vvtvp(nq, &Dtmp0[0], 1, &m_movingframes[j][k * nq],
1083 1, &vellc[0], 1, &vellc[0], 1);
1084 }
1085 break;
1086
1087 case (1):
1088 {
1089 Vmath::Vvtvp(nq, &Dtmp1[0], 1, &m_movingframes[j][k * nq],
1090 1, &vellc[0], 1, &vellc[0], 1);
1091 }
1092 break;
1093
1094 case (2):
1095 {
1096 Vmath::Vvtvp(nq, &Dtmp2[0], 1, &m_movingframes[j][k * nq],
1097 1, &vellc[0], 1, &vellc[0], 1);
1098 }
1099 break;
1100 }
1101 }
1102 }
1103}
1104
1106 Array<OneD, Array<OneD, NekDouble>> &veldotMF)
1107{
1108 int nq = m_fields[0]->GetNpoints();
1109
1111
1112 Array<OneD, NekDouble> magMF(nq);
1113 for (int j = 0; j < m_shapedim; ++j)
1114 {
1115 veldotMF[j] = Array<OneD, NekDouble>(nq, 0.0);
1116
1117 for (int k = 0; k < m_spacedim; ++k)
1118 {
1119 Vmath::Vvtvp(nq, &m_movingframes[j][k * nq], 1, &m_velocity[k][0],
1120 1, &veldotMF[j][0], 1, &veldotMF[j][0], 1);
1121 }
1122 }
1123}
1124
1126 Array<OneD, NekDouble> &outfield,
1127 const NekDouble time)
1128{
1129 boost::ignore_unused(field);
1130
1131 switch (m_TestType)
1132 {
1133 case eAdvectionBell:
1134 {
1135 AdvectionBellSphere(outfield);
1136 }
1137 break;
1138
1139 case eTestPlane:
1140 {
1141 Test2Dproblem(time, outfield);
1142 }
1143 break;
1144
1146 {
1147 AdvectionBellPlane(outfield);
1148 }
1149 break;
1150
1151 case eTestCube:
1152 {
1153 Test3Dproblem(time, outfield);
1154 }
1155 break;
1156
1157 default:
1158 break;
1159 }
1160}
1161
1163{
1166 SolverUtils::AddSummaryItem(s, "Rotation Angle", m_RotAngle);
1167}
1168} // namespace Nektar
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
Definition: ErrorUtil.hpp:249
@ eTestPlaneMassConsv
Definition: MMFAdvection.h:46
@ eAdvectionBell
Definition: MMFAdvection.h:48
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:198
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:144
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:67
void Test2Dproblem(const NekDouble time, Array< OneD, NekDouble > &outfield)
void GetFluxVector(const Array< OneD, Array< OneD, NekDouble > > &physfield, Array< OneD, Array< OneD, Array< OneD, NekDouble > > > &flux)
Evaluate the flux at each solution point.
virtual ~MMFAdvection()
Destructor.
Array< OneD, Array< OneD, NekDouble > > m_veldotMF
Definition: MMFAdvection.h:98
void DoOdeProjection(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray, const NekDouble time)
Compute the projection.
void Test3Dproblem(const NekDouble time, Array< OneD, NekDouble > &outfield)
void AdvectionBellSphere(Array< OneD, NekDouble > &outfield)
NekDouble ComputeCirculatingArclength(const NekDouble zlevel, const NekDouble Rhs)
MMFAdvection(const LibUtilities::SessionReaderSharedPtr &pSession, const SpatialDomains::MeshGraphSharedPtr &pGraph)
Session reader.
void WeakDGDirectionalAdvection(const Array< OneD, Array< OneD, NekDouble > > &InField, Array< OneD, Array< OneD, NekDouble > > &OutField)
void DoOdeRhs(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray, const NekDouble time)
Compute the RHS.
void ComputeNablaCdotVelocity(Array< OneD, NekDouble > &vellc)
void ComputeveldotMF(Array< OneD, Array< OneD, NekDouble > > &veldotMF)
virtual void v_SetInitialConditions(const NekDouble initialtime, bool dumpInitialConditions, const int domain) override
void EvaluateAdvectionVelocity(Array< OneD, Array< OneD, NekDouble > > &velocity)
static SolverUtils::EquationSystemSharedPtr create(const LibUtilities::SessionReaderSharedPtr &pSession, const SpatialDomains::MeshGraphSharedPtr &pGraph)
Creates an instance of this class.
Definition: MMFAdvection.h:68
virtual void v_GenerateSummary(SolverUtils::SummaryList &s) override
Print Summary.
virtual void v_InitObject(bool DeclareFields=true) override
Initialise the object.
SolverUtils::RiemannSolverSharedPtr m_riemannSolver
Definition: MMFAdvection.h:86
virtual void v_EvaluateExactSolution(unsigned int field, Array< OneD, NekDouble > &outfield, const NekDouble time) override
Array< OneD, Array< OneD, NekDouble > > m_velocity
Advection velocity.
Definition: MMFAdvection.h:95
Array< OneD, NekDouble > & GetNormalVelocity()
Get the normal velocity.
virtual void v_DoSolve() override
Solves an unsteady problem.
static std::string className
Name of class.
Definition: MMFAdvection.h:78
Array< OneD, NekDouble > m_vellc
Definition: MMFAdvection.h:99
void AdvectionBellPlane(Array< OneD, NekDouble > &outfield)
Array< OneD, NekDouble > m_traceVn
Definition: MMFAdvection.h:96
A base class for PDEs which include an advection component.
SolverUtils::AdvectionSharedPtr m_advObject
Advection term.
int m_spacedim
Spatial dimension (>= expansion dim).
SOLVER_UTILS_EXPORT int GetTraceNpoints()
NekDouble m_timestep
Time step size.
int m_infosteps
Number of time steps between outputting status information.
NekDouble m_time
Current time of simulation.
Array< OneD, MultiRegions::ExpListSharedPtr > m_fields
Array holding all dependent variables.
NekDouble m_fintime
Finish time of the simulation.
SOLVER_UTILS_EXPORT void Checkpoint_Output(const int n)
Write checkpoint file of m_fields.
NekDouble m_checktime
Time between checkpoints.
SOLVER_UTILS_EXPORT void WriteFld(const std::string &outname)
Write field data to the given filename.
std::string m_sessionName
Name of the session.
LibUtilities::SessionReaderSharedPtr m_session
The session reader.
Array< OneD, Array< OneD, NekDouble > > m_traceNormals
Array holding trace normals for DG simulations in the forwards direction.
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.
SOLVER_UTILS_EXPORT void SetBoundaryConditions(NekDouble time)
Evaluates the boundary conditions at the given time.
int m_checksteps
Number of steps between checkpoints.
SOLVER_UTILS_EXPORT SessionFunctionSharedPtr GetFunction(std::string name, const MultiRegions::ExpListSharedPtr &field=MultiRegions::NullExpListSharedPtr, bool cache=false)
Get a SessionFunction by name.
A base class for PDEs which include an advection component.
Definition: MMFSystem.h:146
virtual SOLVER_UTILS_EXPORT void v_GenerateSummary(SummaryList &s) override
Print a summary of time stepping parameters.
Definition: MMFSystem.cpp:2452
SOLVER_UTILS_EXPORT void VectorCrossProd(const Array< OneD, const Array< OneD, NekDouble > > &v1, const Array< OneD, const Array< OneD, NekDouble > > &v2, Array< OneD, Array< OneD, NekDouble > > &v3)
Definition: MMFSystem.cpp:682
SOLVER_UTILS_EXPORT NekDouble AvgInt(const Array< OneD, const NekDouble > &inarray)
Definition: MMFSystem.cpp:2281
Array< OneD, Array< OneD, NekDouble > > m_movingframes
Definition: MMFSystem.h:185
SOLVER_UTILS_EXPORT void GramSchumitz(const Array< OneD, const Array< OneD, NekDouble > > &v1, const Array< OneD, const Array< OneD, NekDouble > > &v2, Array< OneD, Array< OneD, NekDouble > > &outarray, bool KeepTheMagnitude=true)
Definition: MMFSystem.cpp:2388
Array< OneD, Array< OneD, NekDouble > > m_ncdotMFBwd
Definition: MMFSystem.h:189
SOLVER_UTILS_EXPORT void ComputencdotMF()
Definition: MMFSystem.cpp:303
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:778
SOLVER_UTILS_EXPORT NekDouble RootMeanSquare(const Array< OneD, const NekDouble > &inarray)
Definition: MMFSystem.cpp:2327
Array< OneD, Array< OneD, NekDouble > > m_ncdotMFFwd
Definition: MMFSystem.h:188
SOLVER_UTILS_EXPORT void MMFInitObject(const Array< OneD, const Array< OneD, NekDouble > > &Anisotropy, const int TangentXelem=-1)
Definition: MMFSystem.cpp:53
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(bool DeclareField=true) override
Init object for UnsteadySystem class.
std::shared_ptr< SessionReader > SessionReaderSharedPtr
static const NekDouble kNekZeroTol
AdvectionFactory & GetAdvectionFactory()
Gets the factory for initialising advection objects.
Definition: Advection.cpp:47
std::vector< std::pair< std::string, std::string > > SummaryList
Definition: Misc.h:48
EquationSystemFactory & GetEquationSystemFactory()
void AddSummaryItem(SummaryList &l, const std::string &name, const std::string &value)
Adds a summary item to the summary info list.
Definition: Misc.cpp:49
RiemannSolverFactory & GetRiemannSolverFactory()
std::shared_ptr< MeshGraph > MeshGraphSharedPtr
Definition: MeshGraph.h:176
std::vector< double > z(NPUPPER)
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
@ eTestPlane
Definition: MMFDiffusion.h:48
@ eTestCube
Definition: MMFDiffusion.h:49
@ SIZE_TestType
Length of enum list.
Definition: MMFDiffusion.h:55
const char *const TestTypeMap[]
Definition: MMFDiffusion.h:58
double NekDouble
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:207
void Neg(int n, T *x, const int incx)
Negate x = -x.
Definition: Vmath.cpp:513
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:569
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:354
void Zero(int n, T *x, const int incx)
Zero vector.
Definition: Vmath.cpp:487
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1191
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:414
scalarT< T > sqrt(scalarT< T > in)
Definition: scalar.hpp:294