Nektar++
Loading...
Searching...
No Matches
UnsteadyAdvection.cpp
Go to the documentation of this file.
1/////////////////////////////////////////////////////////////////////////////
2//
3// File: UnsteadyAdvection.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: Unsteady linear advection solve routines
32//
33///////////////////////////////////////////////////////////////////////////////
34
39#include <iostream>
40
41namespace Nektar
42{
43
46 "UnsteadyAdvection", UnsteadyAdvection::create,
47 "Unsteady Advection equation.");
48
52 : UnsteadySystem(pSession, pGraph), AdvectionSystem(pSession, pGraph)
53{
54}
55
56/**
57 * @brief Initialisation object for the unsteady linear advection equation.
58 */
59void UnsteadyAdvection::v_InitObject(bool DeclareFields)
60{
61 // Call to the initialisation object of UnsteadySystem
62 AdvectionSystem::v_InitObject(DeclareFields);
63
64 // Read the advection velocities from session file
65 m_session->LoadParameter("wavefreq", m_waveFreq, 0.0);
66
67 // check to see if it is explicity turned off
68 m_session->MatchSolverInfo("GJPStabilisation", "False",
70
71 // if GJPStabilisation set to False bool will be true and
72 // if not false so negate/revese bool
74
75 m_session->LoadParameter("GJPJumpScale", m_GJPJumpScale, 1.0);
76
77 // Define Velocity fields
78 std::vector<std::string> vel;
79 vel.push_back("Vx");
80 vel.push_back("Vy");
81 vel.push_back("Vz");
82
83 // Resize the advection velocities vector to dimension of the problem
84 vel.resize(m_spacedim);
85
86 // Store in the global variable m_velocity the advection velocities
88 GetFunction("AdvectionVelocity")->Evaluate(vel, m_velocity);
89
90 // Set advection velocities
94 for (int i = 0; i < m_spacedim; i++)
95 {
96 m_varcoeffs[varcoefftypes[i]] = m_velocity[i];
97 }
98
99 // Type of advection class to be used
100 switch (m_projectionType)
101 {
102 // Discontinuous field
104 {
105 // Do not forwards transform initial condition
106 m_homoInitialFwd = false;
107
108 // Define the normal velocity fields
109 if (m_fields[0]->GetTrace())
110 {
112 }
113
114 std::string advName;
115 std::string riemName;
116 m_session->LoadSolverInfo("AdvectionType", advName, "WeakDG");
118 advName, advName);
120 {
121 m_advObject->SetFluxVector(
123 }
124 else
125 {
127 this);
128 }
129 m_session->LoadSolverInfo("UpwindType", riemName, "Upwind");
132 riemName, m_session);
133 m_riemannSolver->SetScalar(
135 m_advObject->SetRiemannSolver(m_riemannSolver);
136 m_advObject->InitObject(m_session, m_fields);
137 break;
138 }
139 // Continuous field
142 {
143 std::string advName;
144 m_session->LoadSolverInfo("AdvectionType", advName,
145 "NonConservative");
147 advName, advName);
149 {
150 m_advObject->SetFluxVector(
152 }
153 else
154 {
156 this);
157 }
158 break;
159 }
160 default:
161 {
162 ASSERTL0(false, "Unsupported projection type.");
163 break;
164 }
165 }
166
167 // Forcing terms
168 m_forcing = SolverUtils::Forcing::Load(m_session, shared_from_this(),
169 m_fields, m_fields.size());
170
171 // If explicit it computes RHS and PROJECTION for the time integration
173 {
176 }
177 // Otherwise it gives an error (no implicit integration)
178 else
179 {
182 "Implicit UnsteadyAdvection is not implemented for a "
183 "Discontinuous Galerkin discretisation.")
184 }
185}
186
187/**
188 * @brief Compute the right-hand side for the linear advection equation.
189 *
190 * @param inarray Given fields.
191 * @param outarray Calculated solution.
192 * @param time Time.
193 */
195 const Array<OneD, const Array<OneD, NekDouble>> &inarray,
196 Array<OneD, Array<OneD, NekDouble>> &outarray, const NekDouble time)
197{
198 // Number of fields (variables of the problem)
199 int nVariables = inarray.size();
200
202 if (m_meshDistorted)
203 {
204 timer.Start();
205 Array<OneD, Array<OneD, NekDouble>> tmpIn(nVariables);
206 // If ALE we must take Mu coefficient space to u physical space
208 auto advWeakDGObject =
209 std::dynamic_pointer_cast<SolverUtils::AdvectionWeakDG>(
211 advWeakDGObject->AdvectCoeffs(nVariables, m_fields, m_velocity, tmpIn,
212 outarray, time);
213 timer.Stop();
214 }
215 else
216 {
217 timer.Start();
218 m_advObject->Advect(nVariables, m_fields, m_velocity, inarray, outarray,
219 time);
220 timer.Stop();
221 }
222
223 // Elapsed time
224 timer.AccumulateRegion("Advect");
225
226 // Negate the RHS
227 for (int i = 0; i < nVariables; ++i)
228 {
229 Vmath::Neg(outarray[i].size(), outarray[i], 1);
230 }
231
232 // Add forcing terms
233 for (auto &x : m_forcing)
234 {
235 // set up non-linear terms
236 x->Apply(m_fields, inarray, outarray, time);
237 }
238}
239
240/**
241 * @brief Compute the projection for the linear advection equation.
242 *
243 * @param inarray Given fields.
244 * @param outarray Calculated solution.
245 * @param time Time.
246 */
248 const Array<OneD, const Array<OneD, NekDouble>> &inarray,
249 Array<OneD, Array<OneD, NekDouble>> &outarray, const NekDouble time)
250{
251 // Number of fields (variables of the problem)
252 int nVariables = inarray.size();
253
254 // Perform ALE movement
255 if (m_ALESolver)
256 {
258 }
259
260 // Set the boundary conditions
262
263 // Switch on the projection type (Discontinuous or Continuous)
264 switch (m_projectionType)
265 {
266 // Discontinuous projection
268 {
269 // Just copy over array
270 if (inarray != outarray)
271 {
272 int npoints = GetNpoints();
273
274 for (int i = 0; i < nVariables; ++i)
275 {
276 Vmath::Vcopy(npoints, inarray[i], 1, outarray[i], 1);
277 }
278 }
279 break;
280 }
281 // Continuous projection
284 {
285 int ncoeffs = m_fields[0]->GetNcoeffs();
286 Array<OneD, NekDouble> coeffs(ncoeffs, 0.0);
288 {
291
292 Array<OneD, NekDouble> wsp(ncoeffs);
293
294 for (int i = 0; i < nVariables; ++i)
295 {
297 std::dynamic_pointer_cast<MultiRegions::ContField>(
298 m_fields[i]);
299
300 m_fields[i]->IProductWRTBase(inarray[i], wsp);
301
303 cfield->GetGJPForcing();
304
305 factors[StdRegions::eFactorGJP] =
307
308 if (GJPData->IsSemiImplicit())
309 {
310 mtype = StdRegions::eMassGJP;
311 }
312
313 // to set up forcing need initial guess in
314 // physical space
315 NekDouble scale = -factors[StdRegions::eFactorGJP];
316
317 GJPData->Apply(inarray[i], wsp, NullNekDouble1DArray,
318 scale);
319
320 // Solve the system
322 mtype, cfield->GetLocalToGlobalMap(), factors);
323
324 cfield->GlobalSolve(key, wsp, coeffs, NullNekDouble1DArray);
325
326 m_fields[i]->BwdTrans(coeffs, outarray[i]);
327 }
328 }
329 else
330 {
331 for (int i = 0; i < nVariables; ++i)
332 {
333 m_fields[i]->FwdTrans(inarray[i], coeffs);
334 m_fields[i]->BwdTrans(coeffs, outarray[i]);
335 }
336 }
337 break;
338 }
339 default:
340 ASSERTL0(false, "Unknown projection scheme");
341 break;
342 }
343}
344
345/**
346 * @brief Implicit solution of the unsteady advection problem.
347 */
349 const Array<OneD, const Array<OneD, NekDouble>> &inarray,
351 [[maybe_unused]] const NekDouble time, const NekDouble lambda)
352{
354
355 int nvariables = inarray.size();
356 int npoints = m_fields[0]->GetNpoints();
357 factors[StdRegions::eFactorLambda] = -1.0 / lambda;
358
359 for (int i = 0; i < nvariables; ++i)
360 {
361 // Multiply 1.0/timestep/lambda
362 Vmath::Smul(npoints, factors[StdRegions::eFactorLambda], inarray[i], 1,
363 outarray[i], 1);
364
365 // Solve a system of equations
366 m_fields[i]->LinearAdvectionReactionSolve(
367 outarray[i], m_fields[i]->UpdateCoeffs(), factors, m_varcoeffs);
368
369 m_fields[i]->BwdTrans(m_fields[i]->GetCoeffs(), outarray[i]);
370
371 m_fields[i]->SetPhysState(false);
372 }
373}
374
375/**
376 * @brief Get the normal velocity for the linear advection equation.
377 */
383
385 const Array<OneD, const Array<OneD, NekDouble>> &velfield)
386{
387 // Number of trace (interface) points
388 int nTracePts = GetTraceNpoints();
389 int nPts = m_velocity[0].size();
390
391 // Auxiliary variable to compute the normal velocity
392 Array<OneD, NekDouble> tmp(nPts), tmp2(nTracePts);
393
394 // Reset the normal velocity
395 Vmath::Zero(nTracePts, m_traceVn, 1);
396
397 for (int i = 0; i < velfield.size(); ++i)
398 {
399 // velocity - grid velocity for ALE before getting trace velocity
400 Vmath::Vsub(nPts, velfield[i], 1, m_gridVelocity[i], 1, tmp, 1);
401
402 m_fields[0]->ExtractTracePhys(tmp, tmp2);
403
404 Vmath::Vvtvp(nTracePts, m_traceNormals[i], 1, tmp2, 1, m_traceVn, 1,
405 m_traceVn, 1);
406 }
407
408 return m_traceVn;
409}
410
411/**
412 * @brief Return the flux vector for the linear advection equation.
413 *
414 * @param physfield Fields.
415 * @param flux Resulting flux.
416 */
418 const Array<OneD, Array<OneD, NekDouble>> &physfield,
420{
421 ASSERTL1(flux[0].size() == m_velocity.size(),
422 "Dimension of flux array and velocity array do not match");
423
424 const int nq = m_fields[0]->GetNpoints();
425
426 for (int i = 0; i < flux.size(); ++i)
427 {
428 for (int j = 0; j < flux[0].size(); ++j)
429 {
430 for (int k = 0; k < nq; ++k)
431 {
432 // If ALE we need to take off the grid velocity
433 flux[i][j][k] =
434 physfield[i][k] * (m_velocity[j][k] - m_gridVelocity[j][k]);
435 }
436 }
437 }
438}
439
440/**
441 * @brief Return the flux vector for the linear advection equation using
442 * the dealiasing technique.
443 *
444 * @param physfield Fields.
445 * @param flux Resulting flux.
446 */
448 const Array<OneD, Array<OneD, NekDouble>> &physfield,
450{
451 ASSERTL1(flux[0].size() == m_velocity.size(),
452 "Dimension of flux array and velocity array do not match");
453
454 int nq = physfield[0].size();
455 int nVariables = physfield.size();
456
457 // Factor to rescale 1d points in dealiasing
458 NekDouble OneDptscale = 2;
459
461
462 // Get number of points to dealias a cubic non-linearity
463 nq = m_fields[0]->Get1DScaledTotPoints(OneDptscale);
464
465 // Initialisation of higher-space variables
466 Array<OneD, Array<OneD, NekDouble>> physfieldInterp(nVariables);
468 Array<OneD, Array<OneD, Array<OneD, NekDouble>>> fluxInterp(nVariables);
469
470 // Interpolation to higher space of physfield
471 for (int i = 0; i < nVariables; ++i)
472 {
473 physfieldInterp[i] = Array<OneD, NekDouble>(nq);
475 for (int j = 0; j < m_expdim; ++j)
476 {
477 fluxInterp[i][j] = Array<OneD, NekDouble>(nq);
478 }
479
480 m_fields[0]->PhysInterp1DScaled(OneDptscale, physfield[i],
481 physfieldInterp[i]);
482 }
483
484 // Interpolation to higher space of velocity
485 for (int j = 0; j < m_expdim; ++j)
486 {
487 velocityInterp[j] = Array<OneD, NekDouble>(nq);
488
489 m_fields[0]->PhysInterp1DScaled(OneDptscale, m_velocity[j],
490 velocityInterp[j]);
491 }
492
493 // Evaluation of flux vector in the higher space
494 for (int i = 0; i < flux.size(); ++i)
495 {
496 for (int j = 0; j < flux[0].size(); ++j)
497 {
498 Vmath::Vmul(nq, physfieldInterp[i], 1, velocityInterp[j], 1,
499 fluxInterp[i][j], 1);
500 }
501 }
502
503 // Galerkin project solution back to original space
504 for (int i = 0; i < nVariables; ++i)
505 {
506 for (int j = 0; j < m_spacedim; ++j)
507 {
508 m_fields[0]->PhysGalerkinProjection1DScaled(
509 OneDptscale, fluxInterp[i][j], flux[i][j]);
510 }
511 }
512}
513
515{
516 AdvectionSystem::v_GenerateSummary(s);
518 {
520 s, "GJP Stab. Impl. ",
521 m_session->GetSolverInfo("GJPStabilisation"));
522 SolverUtils::AddSummaryItem(s, "GJP Stab. JumpScale", m_GJPJumpScale);
523 }
524}
525
526bool UnsteadyAdvection::v_PreIntegrate([[maybe_unused]] int step)
527{
528 return false;
529}
530
532 std::vector<Array<OneD, NekDouble>> &fieldcoeffs,
533 std::vector<std::string> &variables)
534{
535 bool extraFields;
536 m_session->MatchSolverInfo("OutputExtraFields", "True", extraFields, true);
537
538 if (extraFields && m_ALESolver)
539 {
540 ExtraFldOutputGridVelocity(fieldcoeffs, variables);
541 }
542}
543
546{
548 {
549 m_spaceDim = spaceDim;
550 m_fieldsALE = fields;
551
552 // Initialise grid velocities as 0s
555 for (int i = 0; i < spaceDim; ++i)
556 {
557 m_gridVelocity[i] =
558 Array<OneD, NekDouble>(fields[0]->GetTotPoints(), 0.0);
560 fields[0]->GetTrace()->GetTotPoints(), 0.0);
561 }
562 }
563 ALEHelper::InitObject(spaceDim, fields);
564}
565
566} // namespace Nektar
#define ASSERTL0(condition, msg)
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode....
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
void DefineProjection(FuncPointerT func, ObjectPointerT obj)
void DefineImplicitSolve(FuncPointerT func, ObjectPointerT obj)
void AccumulateRegion(std::string, int iolevel=0)
Accumulate elapsed time for a region.
Definition Timer.cpp:70
Array< OneD, MultiRegions::ExpListSharedPtr > m_fieldsALE
Definition ALEHelper.h:140
SOLVER_UTILS_EXPORT void InitObject(int spaceDim, Array< OneD, MultiRegions::ExpListSharedPtr > &fields)
Definition ALEHelper.cpp:48
Array< OneD, Array< OneD, NekDouble > > m_gridVelocityTrace
Definition ALEHelper.h:142
SOLVER_UTILS_EXPORT void ALEDoElmtInvMassBwdTrans(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray)
SOLVER_UTILS_EXPORT void ExtraFldOutputGridVelocity(std::vector< Array< OneD, NekDouble > > &fieldcoeffs, std::vector< std::string > &variables)
SOLVER_UTILS_EXPORT void MoveMesh(const NekDouble &time, Array< OneD, Array< OneD, NekDouble > > &traceNormals)
Array< OneD, Array< OneD, NekDouble > > m_gridVelocity
Definition ALEHelper.h:141
A base class for PDEs which include an advection component.
SolverUtils::AdvectionSharedPtr m_advObject
Advection term.
SOLVER_UTILS_EXPORT void v_InitObject(bool DeclareField=true) override
Initialisation object for EquationSystem.
int m_spacedim
Spatial dimension (>= expansion dim).
NekDouble m_timestep
Time step size.
SOLVER_UTILS_EXPORT int GetTraceNpoints()
Array< OneD, MultiRegions::ExpListSharedPtr > m_fields
Array holding all dependent variables.
SOLVER_UTILS_EXPORT int GetNpoints()
bool m_specHP_dealiasing
Flag to determine if dealisising is usde for the Spectral/hp element discretisation.
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 GetTotPoints()
enum MultiRegions::ProjectionType m_projectionType
Type of projection; e.g continuous or discontinuous.
SOLVER_UTILS_EXPORT void SetBoundaryConditions(NekDouble time)
Evaluates the boundary conditions at the given time.
SOLVER_UTILS_EXPORT SessionFunctionSharedPtr GetFunction(std::string name, const MultiRegions::ExpListSharedPtr &field=MultiRegions::NullExpListSharedPtr, bool cache=false)
Get a SessionFunction by name.
static SOLVER_UTILS_EXPORT std::vector< ForcingSharedPtr > Load(const LibUtilities::SessionReaderSharedPtr &pSession, const std::weak_ptr< EquationSystem > &pEquation, const Array< OneD, MultiRegions::ExpListSharedPtr > &pFields, const unsigned int &pNumForcingFields=0)
Definition Forcing.cpp:76
Base class for unsteady solvers.
LibUtilities::TimeIntegrationSchemeOperators m_ode
The time integration scheme operators to use.
bool m_explicitAdvection
Indicates if explicit or implicit treatment of advection is used.
bool m_homoInitialFwd
Flag to determine if simulation should start in homogeneous forward transformed state.
void v_ALEInitObject(int spaceDim, Array< OneD, MultiRegions::ExpListSharedPtr > &fields) override
std::vector< SolverUtils::ForcingSharedPtr > m_forcing
Forcing terms.
void v_ExtraFldOutput(std::vector< Array< OneD, NekDouble > > &fieldcoeffs, std::vector< std::string > &variables) override
Array< OneD, NekDouble > m_traceVn
Array< OneD, NekDouble > & GetNormalVel(const Array< OneD, const Array< OneD, NekDouble > > &velfield)
Get the normal velocity based on input velfield.
void DoImplicitSolve(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray, const NekDouble time, const NekDouble lambda)
Implicit solution of the unsteady advection problem.
StdRegions::VarCoeffMap m_varcoeffs
static std::string className
Name of class.
Array< OneD, NekDouble > & GetNormalVelocity()
Get the normal velocity.
void v_GenerateSummary(SolverUtils::SummaryList &s) override
Print Summary.
Array< OneD, Array< OneD, NekDouble > > m_velocity
Advection velocity.
static SolverUtils::EquationSystemSharedPtr create(const LibUtilities::SessionReaderSharedPtr &pSession, const SpatialDomains::MeshGraphSharedPtr &pGraph)
Creates an instance of this class.
void DoOdeRhs(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray, const NekDouble time)
Compute the RHS.
void DoOdeProjection(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray, const NekDouble time)
Compute the projection.
void GetFluxVectorDeAlias(const Array< OneD, Array< OneD, NekDouble > > &physfield, Array< OneD, Array< OneD, Array< OneD, NekDouble > > > &flux)
Evaluate the flux at each solution point using dealiasing.
UnsteadyAdvection(const LibUtilities::SessionReaderSharedPtr &pSession, const SpatialDomains::MeshGraphSharedPtr &pGraph)
void v_InitObject(bool DeclareFields=true) override
Initialise the object.
void GetFluxVector(const Array< OneD, Array< OneD, NekDouble > > &physfield, Array< OneD, Array< OneD, Array< OneD, NekDouble > > > &flux)
Evaluate the flux at each solution point.
SolverUtils::RiemannSolverSharedPtr m_riemannSolver
bool v_PreIntegrate(int step) override
std::shared_ptr< SessionReader > SessionReaderSharedPtr
std::shared_ptr< GJPStabilisation > GJPStabilisationSharedPtr
std::shared_ptr< ContField > ContFieldSharedPtr
Definition ContField.h:278
AdvectionFactory & GetAdvectionFactory()
Gets the factory for initialising advection objects.
Definition Advection.cpp:43
std::vector< std::pair< std::string, std::string > > SummaryList
Definition Misc.h:46
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:47
RiemannSolverFactory & GetRiemannSolverFactory()
std::shared_ptr< MeshGraph > MeshGraphSharedPtr
Definition MeshGraph.h:217
std::map< ConstFactorType, NekDouble > ConstFactorMap
static Array< OneD, NekDouble > NullNekDouble1DArray
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.hpp:72
void Neg(int n, T *x, const int incx)
Negate x = -x.
Definition Vmath.hpp:292
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.hpp:366
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.hpp:100
void Zero(int n, T *x, const int incx)
Zero vector.
Definition Vmath.hpp:273
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition Vmath.hpp:825
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.hpp:220