Nektar++
UnsteadyViscousBurgers.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File: UnsteadyViscousBurgers.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 advection-diffusion solve routines
32 //
33 ///////////////////////////////////////////////////////////////////////////////
34 
35 #include <iostream>
36 
37 #include <boost/core/ignore_unused.hpp>
38 
40 #include <StdRegions/StdQuadExp.h>
41 
42 using namespace std;
43 
44 namespace Nektar
45 {
46 string UnsteadyViscousBurgers::className =
48  "UnsteadyViscousBurgers", UnsteadyViscousBurgers::create);
49 
50 UnsteadyViscousBurgers::UnsteadyViscousBurgers(
53  : UnsteadySystem(pSession, pGraph), AdvectionSystem(pSession, pGraph),
54  m_varCoeffLap(StdRegions::NullVarCoeffMap)
55 {
56  m_planeNumber = 0;
57 }
58 
59 /**
60  * @brief Initialisation object for the unsteady linear advection
61  * diffusion equation.
62  */
63 void UnsteadyViscousBurgers::v_InitObject(bool DeclareFields)
64 {
65  AdvectionSystem::v_InitObject(DeclareFields);
66 
67  m_session->LoadParameter("wavefreq", m_waveFreq, 0.0);
68  m_session->LoadParameter("epsilon", m_epsilon, 0.0);
69 
70  m_session->MatchSolverInfo("SpectralVanishingViscosity", "True",
71  m_useSpecVanVisc, false);
72  m_session->MatchSolverInfo("SpectralVanishingViscosity", "VarDiff",
75  {
76  m_useSpecVanVisc = true;
77  }
78 
79  if (m_useSpecVanVisc)
80  {
81  m_session->LoadParameter("SVVCutoffRatio", m_sVVCutoffRatio, 0.75);
82  m_session->LoadParameter("SVVDiffCoeff", m_sVVDiffCoeff, 0.1);
83  }
84 
85  // Type of advection and diffusion classes to be used
86  switch (m_projectionType)
87  {
88  // Discontinuous field
90  {
91  ASSERTL0(false, "Need to implement for DG");
92  // Do not forwards transform initial condition
93  m_homoInitialFwd = false;
94 
95  // Advection term
96  string advName;
97  string riemName;
98  m_session->LoadSolverInfo("AdvectionType", advName, "WeakDG");
100  advName, advName);
101  m_advObject->SetFluxVector(
103  m_session->LoadSolverInfo("UpwindType", riemName, "Upwind");
106  riemName, m_session);
107  m_advObject->SetRiemannSolver(m_riemannSolver);
108  m_advObject->InitObject(m_session, m_fields);
109 
110  // Diffusion term
111  std::string diffName;
112  m_session->LoadSolverInfo("DiffusionType", diffName, "LDG");
114  diffName, diffName);
115  m_diffusion->SetFluxVector(
117  m_diffusion->InitObject(m_session, m_fields);
118  break;
119  }
120  // Continuous field
123  {
124  // Advection term
125  std::string advName;
126  m_session->LoadSolverInfo("AdvectionType", advName,
127  "NonConservative");
129  advName, advName);
130  m_advObject->SetFluxVector(
132 
134  {
136  for (int i = 0; i < m_fields.size(); ++i)
137  {
138  vel[i] = m_fields[i]->UpdatePhys();
139  }
141  }
142 
143  // In case of Galerkin explicit diffusion gives an error
145  {
146  ASSERTL0(false, "Explicit Galerkin diffusion not set up.");
147  }
148  // In case of Galerkin implicit diffusion: do nothing
149  break;
150  }
151  default:
152  {
153  ASSERTL0(false, "Unsupported projection type.");
154  break;
155  }
156  }
157 
158  // Forcing terms
159  m_forcing = SolverUtils::Forcing::Load(m_session, shared_from_this(),
160  m_fields, m_fields.size());
161 
164 
166  m_explicitDiffusion == 1)
167  {
169  }
170 }
171 
172 /**
173  * @brief Unsteady linear advection diffusion equation destructor.
174  */
176 {
177 }
178 
179 /**
180  * @brief Get the normal velocity for the unsteady linear advection
181  * diffusion equation.
182  */
184  Array<OneD, Array<OneD, NekDouble>> &inarray)
185 {
186  // Number of trace (interface) points
187  int i;
188  int nTracePts = GetTraceNpoints();
189 
190  // Auxiliary variable to compute the normal velocity
191  Array<OneD, NekDouble> tmp(nTracePts);
192  m_traceVn = Array<OneD, NekDouble>(nTracePts, 0.0);
193 
194  // Reset the normal velocity
195  Vmath::Zero(nTracePts, m_traceVn, 1);
196 
197  for (i = 0; i < inarray.size(); ++i)
198  {
199  m_fields[0]->ExtractTracePhys(inarray[i], tmp);
200 
201  Vmath::Vvtvp(nTracePts, m_traceNormals[i], 1, tmp, 1, m_traceVn, 1,
202  m_traceVn, 1);
203  }
204 
205  return m_traceVn;
206 }
207 
208 /**
209  * @brief Compute the right-hand side for the unsteady linear advection
210  * diffusion problem.
211  *
212  * @param inarray Given fields.
213  * @param outarray Calculated solution.
214  * @param time Time.
215  */
217  const Array<OneD, const Array<OneD, NekDouble>> &inarray,
218  Array<OneD, Array<OneD, NekDouble>> &outarray, const NekDouble time)
219 {
220  // Number of fields (variables of the problem)
221  int nVariables = inarray.size();
222 
223  // Number of solution points
224  int nSolutionPts = GetNpoints();
225 
226  Array<OneD, Array<OneD, NekDouble>> outarrayDiff(nVariables);
227 
228  for (int i = 0; i < nVariables; ++i)
229  {
230  outarrayDiff[i] = Array<OneD, NekDouble>(nSolutionPts, 0.0);
231  }
232 
233  // RHS computation using the new advection base class
234  m_advObject->Advect(nVariables, m_fields, inarray, inarray, outarray, time);
235 
236  // Negate the RHS
237  for (int i = 0; i < nVariables; ++i)
238  {
239  Vmath::Neg(nSolutionPts, outarray[i], 1);
240  }
241 
242  // No explicit diffusion for CG
244  {
245  m_diffusion->Diffuse(nVariables, m_fields, inarray, outarrayDiff);
246 
247  for (int i = 0; i < nVariables; ++i)
248  {
249  Vmath::Vadd(nSolutionPts, &outarray[i][0], 1, &outarrayDiff[i][0],
250  1, &outarray[i][0], 1);
251  }
252  }
253 
254  // Add forcing terms
255  for (auto &x : m_forcing)
256  {
257  // set up non-linear terms
258  x->Apply(m_fields, inarray, outarray, time);
259  }
260 }
261 
262 /**
263  * @brief Compute the projection for the unsteady advection
264  * diffusion problem.
265  *
266  * @param inarray Given fields.
267  * @param outarray Calculated solution.
268  * @param time Time.
269  */
271  const Array<OneD, const Array<OneD, NekDouble>> &inarray,
272  Array<OneD, Array<OneD, NekDouble>> &outarray, const NekDouble time)
273 {
274  int i;
275  int nvariables = inarray.size();
276  SetBoundaryConditions(time);
277  switch (m_projectionType)
278  {
280  {
281  // Just copy over array
282  int npoints = GetNpoints();
283 
284  for (i = 0; i < nvariables; ++i)
285  {
286  Vmath::Vcopy(npoints, inarray[i], 1, outarray[i], 1);
287  }
288  break;
289  }
292  {
293  // Do nothing for the moment.
294  }
295  default:
296  {
297  ASSERTL0(false, "Unknown projection scheme");
298  break;
299  }
300  }
301 }
302 
303 /* @brief Compute the diffusion term implicitly.
304  *
305  * @param inarray Given fields.
306  * @param outarray Calculated solution.
307  * @param time Time.
308  * @param lambda Diffusion coefficient.
309  */
311  const Array<OneD, const Array<OneD, NekDouble>> &inarray,
312  Array<OneD, Array<OneD, NekDouble>> &outarray, const NekDouble time,
313  const NekDouble lambda)
314 {
315  int nvariables = inarray.size();
316  int nq = m_fields[0]->GetNpoints();
317 
319  factors[StdRegions::eFactorLambda] = 1.0 / lambda / m_epsilon;
320 
321  if (m_useSpecVanVisc)
322  {
325  }
326 
327  Array<OneD, Array<OneD, NekDouble>> F(nvariables);
328  F[0] = Array<OneD, NekDouble>(nq * nvariables);
329 
330  for (int n = 1; n < nvariables; ++n)
331  {
332  F[n] = F[n - 1] + nq;
333  }
334 
335  // We solve ( \nabla^2 - HHlambda ) Y[i] = rhs [i]
336  // inarray = input: \hat{rhs} -> output: \hat{Y}
337  // outarray = output: nabla^2 \hat{Y}
338  // where \hat = modal coeffs
339  for (int i = 0; i < nvariables; ++i)
340  {
341  // Multiply 1.0/timestep/lambda
342  Vmath::Smul(nq, -factors[StdRegions::eFactorLambda], inarray[i], 1,
343  F[i], 1);
344  }
345 
346  // Setting boundary conditions
347  SetBoundaryConditions(time);
348 
350  {
351  static int cnt = 0;
352 
353  if (cnt % 10 == 0)
354  {
356  for (int i = 0; i < m_fields.size(); ++i)
357  {
358  m_fields[i]->ClearGlobalLinSysManager();
359  vel[i] = m_fields[i]->UpdatePhys();
360  }
362  }
363  ++cnt;
364  }
365  for (int i = 0; i < nvariables; ++i)
366  {
367  // Solve a system of equations with Helmholtz solver
368  m_fields[i]->HelmSolve(F[i], m_fields[i]->UpdateCoeffs(), factors,
369  m_varCoeffLap);
370 
371  m_fields[i]->BwdTrans(m_fields[i]->GetCoeffs(), outarray[i]);
372  }
373 }
374 
375 /**
376  * @brief Return the flux vector for the advection part.
377  *
378  * @param physfield Fields.
379  * @param flux Resulting flux.
380  */
382  const Array<OneD, Array<OneD, NekDouble>> &physfield,
384 {
385 
386  const int nq = m_fields[0]->GetNpoints();
387 
388  for (int i = 0; i < flux.size(); ++i)
389  {
390  for (int j = 0; j < flux[0].size(); ++j)
391  {
392  Vmath::Vmul(nq, physfield[i], 1, physfield[j], 1, flux[i][j], 1);
393  }
394  }
395 }
396 
397 /**
398  * @brief Return the flux vector for the diffusion part.
399  *
400  * @param i Equation number.
401  * @param j Spatial direction.
402  * @param physfield Fields.
403  * @param derivatives First order derivatives.
404  * @param flux Resulting flux.
405  */
407  const Array<OneD, Array<OneD, NekDouble>> &inarray,
408  const Array<OneD, Array<OneD, Array<OneD, NekDouble>>> &qfield,
409  Array<OneD, Array<OneD, Array<OneD, NekDouble>>> &viscousTensor)
410 {
411  boost::ignore_unused(inarray);
412 
413  unsigned int nDim = qfield.size();
414  unsigned int nConvectiveFields = qfield[0].size();
415  unsigned int nPts = qfield[0][0].size();
416 
417  for (unsigned int j = 0; j < nDim; ++j)
418  {
419  for (unsigned int i = 0; i < nConvectiveFields; ++i)
420  {
421  Vmath::Smul(nPts, m_epsilon, qfield[j][i], 1, viscousTensor[j][i],
422  1);
423  }
424  }
425 }
426 
428 {
430  if (m_useSpecVanVisc)
431  {
432  stringstream ss;
433  ss << "SVV (cut off = " << m_sVVCutoffRatio
434  << ", coeff = " << m_sVVDiffCoeff << ")";
435  AddSummaryItem(s, "Smoothing", ss.str());
436  }
437 }
438 } // namespace Nektar
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215
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)
void DefineImplicitSolve(FuncPointerT func, ObjectPointerT obj)
A base class for PDEs which include an advection component.
SolverUtils::AdvectionSharedPtr m_advObject
Advection term.
virtual SOLVER_UTILS_EXPORT void v_InitObject(bool DeclareField=true) override
Init object for UnsteadySystem class.
SOLVER_UTILS_EXPORT int GetTraceNpoints()
Array< OneD, MultiRegions::ExpListSharedPtr > m_fields
Array holding all dependent variables.
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()
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.
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:120
Base class for unsteady solvers.
LibUtilities::TimeIntegrationSchemeOperators m_ode
The time integration scheme operators to use.
bool m_explicitDiffusion
Indicates if explicit or implicit treatment of diffusion is used.
SOLVER_UTILS_EXPORT void SVVVarDiffCoeff(const Array< OneD, Array< OneD, NekDouble >> vel, StdRegions::VarCoeffMap &varCoeffMap)
Evaluate the SVV diffusion coefficient according to Moura's paper where it should proportional to h t...
virtual SOLVER_UTILS_EXPORT void v_GenerateSummary(SummaryList &s) override
Print a summary of time stepping parameters.
bool m_homoInitialFwd
Flag to determine if simulation should start in homogeneous forward transformed state.
Array< OneD, NekDouble > m_traceVn
virtual void v_GenerateSummary(SolverUtils::SummaryList &s) override
Print Summary.
void DoImplicitSolve(const Array< OneD, const Array< OneD, NekDouble >> &inarray, Array< OneD, Array< OneD, NekDouble >> &outarray, NekDouble time, NekDouble lambda)
Solve implicitly the diffusion term.
void DoOdeRhs(const Array< OneD, const Array< OneD, NekDouble >> &inarray, Array< OneD, Array< OneD, NekDouble >> &outarray, const NekDouble time)
Compute the RHS.
SolverUtils::DiffusionSharedPtr m_diffusion
std::vector< SolverUtils::ForcingSharedPtr > m_forcing
Forcing terms.
void DoOdeProjection(const Array< OneD, const Array< OneD, NekDouble >> &inarray, Array< OneD, Array< OneD, NekDouble >> &outarray, const NekDouble time)
Perform the projection.
void GetFluxVectorAdv(const Array< OneD, Array< OneD, NekDouble >> &physfield, Array< OneD, Array< OneD, Array< OneD, NekDouble >>> &flux)
Evaluate the flux at each solution point for the advection part.
virtual void v_InitObject(bool DeclareFields=true) override
Initialise the object.
Array< OneD, NekDouble > & GetNormalVelocity(Array< OneD, Array< OneD, NekDouble >> &inarray)
Get the normal velocity.
SolverUtils::RiemannSolverSharedPtr m_riemannSolver
void GetFluxVectorDiff(const Array< OneD, Array< OneD, NekDouble >> &inarray, const Array< OneD, Array< OneD, Array< OneD, NekDouble >>> &qfield, Array< OneD, Array< OneD, Array< OneD, NekDouble >>> &viscousTensor)
Evaluate the flux at each solution point for the diffusion part.
StdRegions::VarCoeffMap m_varCoeffLap
Variable Coefficient map for the Laplacian which can be activated as part of SVV or otherwise.
std::shared_ptr< SessionReader > SessionReaderSharedPtr
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
DiffusionFactory & GetDiffusionFactory()
Definition: Diffusion.cpp:41
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:172
std::map< ConstFactorType, NekDouble > ConstFactorMap
Definition: StdRegions.hpp:399
static VarCoeffMap NullVarCoeffMap
Definition: StdRegions.hpp:344
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
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:209
void Neg(int n, T *x, const int incx)
Negate x = -x.
Definition: Vmath.cpp:518
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:574
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:359
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:248
void Zero(int n, T *x, const int incx)
Zero vector.
Definition: Vmath.cpp:492
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1255