Nektar++
VCSMapping.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File VCSMapping.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: Velocity Correction Scheme w/ coordinate transformation
32 // for the Incompressible Navier Stokes equations
33 ///////////////////////////////////////////////////////////////////////////////
34 
37 #include <SolverUtils/Core/Misc.h>
38 
39 #include <boost/algorithm/string.hpp>
40 
41 using namespace std;
42 
43 namespace Nektar
44 {
45  string VCSMapping::className =
47  "VCSMapping",
48  VCSMapping::create);
49 
50  /**
51  * Constructor. Creates ...
52  *
53  * \param
54  * \param
55  */
56  VCSMapping::VCSMapping(
59  : UnsteadySystem(pSession, pGraph),
60  VelocityCorrectionScheme(pSession, pGraph)
61  {
62 
63  }
64 
66  {
68 
71  "Could not create mapping in VCSMapping.");
72 
73  std::string vExtrapolation = "Mapping";
75  vExtrapolation,
76  m_session,
77  m_fields,
78  m_pressure,
79  m_velocity,
80  m_advObject);
81  m_extrapolation->SubSteppingTimeIntegration(m_intScheme);
82  m_extrapolation->GenerateHOPBCMap(m_session);
83 
84  // Storage to extrapolate pressure forcing
85  int physTot = m_fields[0]->GetTotPoints();
86  int intSteps = 1;
87 
88  if ( m_intScheme->GetName() == "IMEX" ||
89  m_intScheme->GetName() == "IMEXGear" )
90  {
91  m_intSteps = m_intScheme->GetOrder();
92  }
93  else
94  {
95  NEKERROR(ErrorUtil::efatal, "Integration method not suitable: "
96  "Options include IMEXGear or IMEXOrder{1,2,3,4}");
97  }
98 
100  for(int i = 0; i < m_presForcingCorrection.size(); i++)
101  {
103  }
104  m_verbose = (m_session->DefinesCmdLineArgument("verbose"))? true :false;
105 
106  // Load solve parameters related to the mapping
107  // Flags determining if pressure/viscous terms should be treated implicitly
108  m_session->MatchSolverInfo("MappingImplicitPressure","True",
109  m_implicitPressure,false);
110  m_session->MatchSolverInfo("MappingImplicitViscous","True",
111  m_implicitViscous,false);
112  m_session->MatchSolverInfo("MappingNeglectViscous","True",
113  m_neglectViscous,false);
114 
115  if (m_neglectViscous)
116  {
117  m_implicitViscous = false;
118  }
119 
120  // Tolerances and relaxation parameters for implicit terms
121  m_session->LoadParameter("MappingPressureTolerance",
122  m_pressureTolerance,1e-12);
123  m_session->LoadParameter("MappingViscousTolerance",
124  m_viscousTolerance,1e-12);
125  m_session->LoadParameter("MappingPressureRelaxation",
127  m_session->LoadParameter("MappingViscousRelaxation",
128  m_viscousRelaxation,1.0);
129 
130  }
131 
132  /**
133  * Destructor
134  */
136  {
137  }
138 
140  {
142 
143  // Set up Field Meta Data for output files
144  m_fieldMetaDataMap["Kinvis"] =
145  boost::lexical_cast<std::string>(m_kinvis);
146  m_fieldMetaDataMap["TimeStep"] =
147  boost::lexical_cast<std::string>(m_timestep);
148 
149  // Correct Dirichlet boundary conditions to account for mapping
150  m_mapping->UpdateBCs(0.0);
151  //
153  for(int i = 0; i < m_nConvectiveFields; ++i)
154  {
155  m_fields[i]->ImposeDirichletConditions(m_fields[i]->UpdateCoeffs());
156  m_fields[i]->BwdTrans(m_fields[i]->GetCoeffs(),
157  m_fields[i]->UpdatePhys());
159  }
160 
161  // Initialise m_gradP
162  int physTot = m_fields[0]->GetTotPoints();
164  for(int i = 0; i < m_nConvectiveFields; ++i)
165  {
166  m_gradP[i] = Array<OneD, NekDouble>(physTot,0.0);
168  m_pressure->GetPhys(),
169  m_gradP[i]);
170  if(m_pressure->GetWaveSpace())
171  {
172  m_pressure->HomogeneousBwdTrans(m_gradP[i],m_gradP[i]);
173  }
174  }
175  }
176 
177  /**
178  * Explicit part of the method - Advection, Forcing + HOPBCs
179  */
181  const Array<OneD, const Array<OneD, NekDouble> > &inarray,
182  Array<OneD, Array<OneD, NekDouble> > &outarray,
183  const NekDouble time)
184  {
185  EvaluateAdvectionTerms(inarray, outarray, time);
186 
187  // Smooth advection
189  {
190  for(int i = 0; i < m_nConvectiveFields; ++i)
191  {
192  m_pressure->SmoothField(outarray[i]);
193  }
194  }
195 
196  // Add forcing terms
197  for (auto &x : m_forcing)
198  {
199  x->Apply(m_fields, inarray, outarray, time);
200  }
201 
202  // Add mapping terms
203  ApplyIncNSMappingForcing( inarray, outarray);
204 
205  // Calculate High-Order pressure boundary conditions
206  m_extrapolation->EvaluatePressureBCs(inarray,outarray,m_kinvis);
207 
208  // Update mapping and deal with Dirichlet boundary conditions
209  if (m_mapping->IsTimeDependent())
210  {
211  if (m_mapping->IsFromFunction())
212  {
213  // If the transformation is explicitly defined, update it here
214  // Otherwise, it will be done somewhere else (ForcingMovingBody)
215  m_mapping->UpdateMapping(time+m_timestep);
216  }
217  m_mapping->UpdateBCs(time+m_timestep);
218  }
219  }
220 
221 
222  /**
223  * Forcing term for Poisson solver solver
224  */
226  const Array<OneD, const Array<OneD, NekDouble> > &fields,
228  const NekDouble aii_Dt)
229  {
230  if (m_mapping->HasConstantJacobian())
231  {
233  Forcing, aii_Dt);
234  }
235  else
236  {
237  int physTot = m_fields[0]->GetTotPoints();
238  int nvel = m_nConvectiveFields;
239  Array<OneD, NekDouble> wk(physTot, 0.0);
240 
241  Array<OneD, NekDouble> Jac(physTot,0.0);
242  m_mapping->GetJacobian(Jac);
243 
244  // Calculate div(J*u/Dt)
245  Vmath::Zero(physTot,Forcing[0],1);
246  for(int i = 0; i < nvel; ++i)
247  {
248  if (m_fields[i]->GetWaveSpace())
249  {
250  m_fields[i]->HomogeneousBwdTrans(fields[i],wk);
251  }
252  else
253  {
254  Vmath::Vcopy(physTot, fields[i], 1, wk, 1);
255  }
256  Vmath::Vmul(physTot,wk,1,Jac,1,wk,1);
257  if (m_fields[i]->GetWaveSpace())
258  {
259  m_fields[i]->HomogeneousFwdTrans(wk,wk);
260  }
261  m_fields[i]->PhysDeriv(MultiRegions::DirCartesianMap[i],wk, wk);
262  Vmath::Vadd(physTot,wk,1,Forcing[0],1,Forcing[0],1);
263  }
264  Vmath::Smul(physTot,1.0/aii_Dt,Forcing[0],1,Forcing[0],1);
265 
266  //
267  // If the mapping viscous terms are being treated explicitly
268  // we need to apply a correction to the forcing
269  if (!m_implicitViscous)
270  {
271  bool wavespace = m_fields[0]->GetWaveSpace();
272  m_fields[0]->SetWaveSpace(false);
273 
274  //
275  // Part 1: div(J*grad(U/J . grad(J)))
277  Array<OneD, Array<OneD, NekDouble> > velocity (nvel);
278  for(int i = 0; i < tmp.size(); i++)
279  {
280  tmp[i] = Array<OneD, NekDouble>(physTot,0.0);
281  velocity[i] = Array<OneD, NekDouble>(physTot,0.0);
282  if (wavespace)
283  {
284  m_fields[0]->HomogeneousBwdTrans(m_fields[i]->GetPhys(),
285  velocity[i]);
286  }
287  else
288  {
289  Vmath::Vcopy(physTot, m_fields[i]->GetPhys(), 1,
290  velocity[i], 1);
291  }
292  }
293  // Calculate wk = U.grad(J)
294  m_mapping->DotGradJacobian(velocity, wk);
295  // Calculate wk = (U.grad(J))/J
296  Vmath::Vdiv(physTot, wk, 1, Jac, 1, wk, 1);
297  // J*grad[(U.grad(J))/J]
298  for(int i = 0; i < nvel; ++i)
299  {
300  m_fields[0]->PhysDeriv(MultiRegions::DirCartesianMap[i],
301  wk, tmp[i]);
302  Vmath::Vmul(physTot, Jac, 1, tmp[i], 1, tmp[i], 1);
303  }
304  // div(J*grad[(U.grad(J))/J])
305  Vmath::Zero(physTot, wk, 1);
306  for(int i = 0; i < nvel; ++i)
307  {
308  m_fields[0]->PhysDeriv(MultiRegions::DirCartesianMap[i],
309  tmp[i], tmp[i]);
310  Vmath::Vadd(physTot, wk, 1, tmp[i], 1, wk, 1);
311  }
312 
313  // Part 2: grad(J) . curl(curl(U))
314  m_mapping->CurlCurlField(velocity, tmp, m_implicitViscous);
315  // dont need velocity any more, so reuse it
316  m_mapping->DotGradJacobian(tmp, velocity[0]);
317 
318  // Add two parts
319  Vmath::Vadd(physTot, velocity[0], 1, wk, 1, wk, 1);
320 
321  // Multiply by kinvis and prepare to extrapolate
322  int nlevels = m_presForcingCorrection.size();
323  Vmath::Smul(physTot, m_kinvis, wk, 1,
324  m_presForcingCorrection[nlevels-1], 1);
325 
326  // Extrapolate correction
327  m_extrapolation->ExtrapolateArray(m_presForcingCorrection);
328 
329  // Put in wavespace
330  if (wavespace)
331  {
332  m_fields[0]->HomogeneousFwdTrans(
333  m_presForcingCorrection[nlevels-1],wk);
334  }
335  else
336  {
337  Vmath::Vcopy(physTot, m_presForcingCorrection[nlevels-1], 1,
338  wk, 1);
339  }
340  // Apply correction: Forcing = Forcing - correction
341  Vmath::Vsub(physTot, Forcing[0], 1, wk, 1, Forcing[0], 1);
342 
343  m_fields[0]->SetWaveSpace(wavespace);
344  }
345  }
346  }
347 
348  /**
349  * Forcing term for Helmholtz solver
350  */
352  const Array<OneD, const Array<OneD, NekDouble> > &inarray,
354  const NekDouble aii_Dt)
355  {
356  NekDouble aii_dtinv = 1.0/aii_Dt;
357  int physTot = m_fields[0]->GetTotPoints();
358 
359  // Grad p
360  m_pressure->BwdTrans(m_pressure->GetCoeffs(),m_pressure->UpdatePhys());
361 
362  int nvel = m_velocity.size();
363  if(nvel == 2)
364  {
365  m_pressure->PhysDeriv(m_pressure->GetPhys(), Forcing[0], Forcing[1]);
366  }
367  else
368  {
369  m_pressure->PhysDeriv(m_pressure->GetPhys(), Forcing[0], Forcing[1],
370  Forcing[2]);
371  }
372 
373  // Copy grad p in physical space to m_gradP to reuse later
374  if (m_pressure->GetWaveSpace())
375  {
376  for (int i=0; i<nvel; i++)
377  {
378  m_pressure->HomogeneousBwdTrans(Forcing[i],m_gradP[i]);
379  }
380  }
381  else
382  {
383  for (int i=0; i<nvel; i++)
384  {
385  Vmath::Vcopy(physTot, Forcing[i], 1, m_gradP[i], 1);
386  }
387  }
388 
389  if ( (!m_mapping->HasConstantJacobian()) || m_implicitPressure)
390  {
391  // If pressure terms are treated explicitly, we need to divide by J
392  // if they are implicit, we need to calculate G(p)
393  if (m_implicitPressure)
394  {
395  m_mapping->RaiseIndex(m_gradP, Forcing);
396  }
397  else
398  {
399  Array<OneD, NekDouble> Jac(physTot,0.0);
400  m_mapping->GetJacobian(Jac);
401  for (int i=0; i<nvel; i++)
402  {
403  Vmath::Vdiv(physTot, m_gradP[i], 1, Jac, 1, Forcing[i], 1);
404  }
405  }
406  // Transform back to wavespace
407  if (m_pressure->GetWaveSpace())
408  {
409  for (int i=0; i<nvel; i++)
410  {
411  m_pressure->HomogeneousFwdTrans(Forcing[i],Forcing[i]);
412  }
413  }
414  }
415 
416  // Subtract inarray/(aii_dt) and divide by kinvis. Kinvis will
417  // need to be updated for the convected fields.
418  for(int i = 0; i < nvel; ++i)
419  {
420  Blas::Daxpy(physTot,-aii_dtinv,inarray[i],1,Forcing[i],1);
421  Blas::Dscal(physTot,1.0/m_kinvis,&(Forcing[i])[0],1);
422  }
423  }
424 
425  /**
426  * Solve pressure system
427  */
430  {
431  if (!m_implicitPressure)
432  {
434  }
435  else
436  {
437  int physTot = m_fields[0]->GetTotPoints();
438  int nvel = m_nConvectiveFields;
439  bool converged = false; // flag to mark if system converged
440  int s = 0; // iteration counter
441  NekDouble error; // L2 error at current iteration
442  NekDouble forcing_L2 = 0.0; // L2 norm of F
443 
444  int maxIter;
445  m_session->LoadParameter("MappingMaxIter",maxIter,5000);
446 
447  // rhs of the equation at current iteration
448  Array< OneD, NekDouble> F_corrected(physTot, 0.0);
449  // Pressure field at previous iteration
450  Array<OneD, NekDouble> previous_iter (physTot, 0.0);
451  // Temporary variables
455  for(int i = 0; i < nvel; ++i)
456  {
457  wk1[i] = Array<OneD, NekDouble> (physTot, 0.0);
458  wk2[i] = Array<OneD, NekDouble> (physTot, 0.0);
459  gradP[i] = Array<OneD, NekDouble> (physTot, 0.0);
460  }
461 
462  // Jacobian
463  Array<OneD, NekDouble> Jac(physTot, 0.0);
464  m_mapping->GetJacobian(Jac);
465 
466  // Factors for Laplacian system
468  factors[StdRegions::eFactorLambda] = 0.0;
469 
470  m_pressure->BwdTrans(m_pressure->GetCoeffs(),
471  m_pressure->UpdatePhys());
472  forcing_L2 = m_pressure->L2(Forcing, wk1[0]);
473  while (!converged)
474  {
475  // Update iteration counter and set previous iteration field
476  // (use previous timestep solution for first iteration)
477  s++;
478  ASSERTL0(s < maxIter,
479  "VCSMapping exceeded maximum number of iterations.");
480 
481  Vmath::Vcopy(physTot, m_pressure->GetPhys(), 1,
482  previous_iter, 1);
483 
484  // Correct pressure bc to account for iteration
485  m_extrapolation->CorrectPressureBCs(previous_iter);
486 
487  //
488  // Calculate forcing term for this iteration
489  //
490  for(int i = 0; i < nvel; ++i)
491  {
493  previous_iter, gradP[i]);
494  if(m_pressure->GetWaveSpace())
495  {
496  m_pressure->HomogeneousBwdTrans(gradP[i], wk1[i]);
497  }
498  else
499  {
500  Vmath::Vcopy(physTot, gradP[i], 1, wk1[i], 1);
501  }
502  }
503  m_mapping->RaiseIndex(wk1, wk2); // G(p)
504 
505  m_mapping->Divergence(wk2, F_corrected); // div(G(p))
506  if (!m_mapping->HasConstantJacobian())
507  {
508  Vmath::Vmul(physTot, F_corrected, 1,
509  Jac, 1,
510  F_corrected, 1);
511  }
512  // alpha*J*div(G(p))
513  Vmath::Smul(physTot, m_pressureRelaxation, F_corrected, 1,
514  F_corrected, 1);
515  if(m_pressure->GetWaveSpace())
516  {
517  m_pressure->HomogeneousFwdTrans(F_corrected, F_corrected);
518  }
519  // alpha*J*div(G(p)) - p_ii
520  for (int i = 0; i < m_nConvectiveFields; ++i)
521  {
523  gradP[i], wk1[0]);
524  Vmath::Vsub(physTot, F_corrected, 1, wk1[0], 1,
525  F_corrected, 1);
526  }
527  // p_i,i - J*div(G(p))
528  Vmath::Neg(physTot, F_corrected, 1);
529  // alpha*F - alpha*J*div(G(p)) + p_i,i
531  wk1[0], 1);
532  Vmath::Vadd(physTot, wk1[0], 1, F_corrected, 1, F_corrected, 1);
533 
534  //
535  // Solve system
536  //
537  m_pressure->HelmSolve(F_corrected, m_pressure->UpdateCoeffs(),
538  factors);
539  m_pressure->BwdTrans(m_pressure->GetCoeffs(),
540  m_pressure->UpdatePhys());
541 
542  //
543  // Test convergence
544  //
545  error = m_pressure->L2(m_pressure->GetPhys(), previous_iter);
546  if ( forcing_L2 != 0)
547  {
548  if ( (error/forcing_L2 < m_pressureTolerance))
549  {
550  converged = true;
551  }
552  }
553  else
554  {
555  if ( error < m_pressureTolerance)
556  {
557  converged = true;
558  }
559  }
560  }
561  if (m_verbose && m_session->GetComm()->GetRank()==0)
562  {
563  std::cout << " Pressure system (mapping) converged in " << s <<
564  " iterations with error = " << error << std::endl;
565  }
566  }
567  }
568 
569  /**
570  * Solve velocity system
571  */
573  const Array<OneD, const Array<OneD, NekDouble> > &Forcing,
574  Array<OneD, Array<OneD, NekDouble> > &outarray,
575  const NekDouble aii_Dt)
576  {
577  if(!m_implicitViscous)
578  {
580  }
581  else
582  {
583  int physTot = m_fields[0]->GetTotPoints();
584  int nvel = m_nConvectiveFields;
585  bool converged = false; // flag to mark if system converged
586  int s = 0; // iteration counter
587  NekDouble error, max_error; // L2 error at current iteration
588 
589  int maxIter;
590  m_session->LoadParameter("MappingMaxIter",maxIter,5000);
591 
592  //L2 norm of F
594 
595  // rhs of the equation at current iteration
596  Array<OneD, Array<OneD, NekDouble> > F_corrected(nvel);
597  // Solution at previous iteration
598  Array<OneD, Array<OneD, NekDouble> > previous_iter(nvel);
599  // Working space
601  for(int i = 0; i < nvel; ++i)
602  {
603  F_corrected[i] = Array<OneD, NekDouble> (physTot, 0.0);
604  previous_iter[i] = Array<OneD, NekDouble> (physTot, 0.0);
605  wk[i] = Array<OneD, NekDouble> (physTot, 0.0);
606  }
607 
608  // Factors for Helmholtz system
610  factors[StdRegions::eFactorLambda] =
611  1.0*m_viscousRelaxation/aii_Dt/m_kinvis;
612  if(m_useSpecVanVisc)
613  {
617  }
618 
619  // Calculate L2-norm of F and set initial solution for iteration
620  for(int i = 0; i < nvel; ++i)
621  {
622  forcing_L2[i] = m_fields[0]->L2(Forcing[i],wk[0]);
623  m_fields[i]->BwdTrans(m_fields[i]->GetCoeffs(),
624  previous_iter[i]);
625  }
626 
627  while (!converged)
628  {
629  converged = true;
630  // Iteration counter
631  s++;
632  ASSERTL0(s < maxIter,
633  "VCSMapping exceeded maximum number of iterations.");
634 
635  max_error = 0.0;
636 
637  //
638  // Calculate forcing term for next iteration
639  //
640 
641  // Calculate L(U)- in this parts all components might be coupled
642  if(m_fields[0]->GetWaveSpace())
643  {
644  for (int i = 0; i < nvel; ++i)
645  {
646  m_fields[0]->HomogeneousBwdTrans(previous_iter[i],
647  wk[i]);
648  }
649  }
650  else
651  {
652  for (int i = 0; i < nvel; ++i)
653  {
654  Vmath::Vcopy(physTot, previous_iter[i], 1, wk[i], 1);
655  }
656  }
657 
658  // (L(U^i) - 1/alpha*U^i_jj)
659  m_mapping->VelocityLaplacian(wk, F_corrected,
660  1.0/m_viscousRelaxation);
661 
662  if(m_fields[0]->GetWaveSpace())
663  {
664  for (int i = 0; i < nvel; ++i)
665  {
666  m_fields[0]->HomogeneousFwdTrans(F_corrected[i],
667  F_corrected[i]);
668  }
669  }
670  else
671  {
672  for (int i = 0; i < nvel; ++i)
673  {
674  Vmath::Vcopy(physTot, F_corrected[i], 1,
675  F_corrected[i], 1);
676  }
677  }
678 
679  // Loop velocity components
680  for (int i = 0; i < nvel; ++i)
681  {
682  // (-alpha*L(U^i) + U^i_jj)
683  Vmath::Smul(physTot, -1.0*m_viscousRelaxation,
684  F_corrected[i], 1,
685  F_corrected[i], 1);
686  // F_corrected = alpha*F + (-alpha*L(U^i) + U^i_jj)
687  Vmath::Smul(physTot, m_viscousRelaxation, Forcing[i], 1,
688  wk[0], 1);
689  Vmath::Vadd(physTot, wk[0], 1, F_corrected[i], 1,
690  F_corrected[i], 1);
691 
692  //
693  // Solve System
694  //
695  m_fields[i]->HelmSolve(F_corrected[i],
696  m_fields[i]->UpdateCoeffs(),factors);
697  m_fields[i]->BwdTrans(m_fields[i]->GetCoeffs(),outarray[i]);
698 
699  //
700  // Test convergence
701  //
702  error = m_fields[i]->L2(outarray[i], previous_iter[i]);
703 
704  if ( forcing_L2[i] != 0)
705  {
706  if ( (error/forcing_L2[i] >= m_viscousTolerance))
707  {
708  converged = false;
709  }
710  }
711  else
712  {
713  if ( error >= m_viscousTolerance)
714  {
715  converged = false;
716  }
717  }
718  if (error > max_error)
719  {
720  max_error = error;
721  }
722 
723  // Copy field to previous_iter
724  Vmath::Vcopy(physTot, outarray[i], 1, previous_iter[i], 1);
725  }
726  }
727  if (m_verbose && m_session->GetComm()->GetRank()==0)
728  {
729  std::cout << " Velocity system (mapping) converged in " << s <<
730  " iterations with error = " << max_error << std::endl;
731  }
732  }
733  }
734 
735  /**
736  * Explicit terms of the mapping
737  */
739  const Array<OneD, const Array<OneD, NekDouble> > &inarray,
740  Array<OneD, Array<OneD, NekDouble> > &outarray)
741  {
742  int physTot = m_fields[0]->GetTotPoints();
747  for (int i = 0; i < m_nConvectiveFields; ++i)
748  {
749  velPhys[i] = Array<OneD, NekDouble> (physTot, 0.0);
750  Forcing[i] = Array<OneD, NekDouble> (physTot, 0.0);
751  tmp[i] = Array<OneD, NekDouble> (physTot, 0.0);
752  }
753 
754  // Get fields and store velocity in wavespace and physical space
755  if(m_fields[0]->GetWaveSpace())
756  {
757  for (int i = 0; i < m_nConvectiveFields; ++i)
758  {
759  vel[i] = inarray[i];
760  m_fields[0]->HomogeneousBwdTrans(vel[i],velPhys[i]);
761  }
762  }
763  else
764  {
765  for (int i = 0; i < m_nConvectiveFields; ++i)
766  {
767  vel[i] = inarray[i];
768  Vmath::Vcopy(physTot, inarray[i], 1, velPhys[i], 1);
769  }
770  }
771 
772  //Advection contribution
774 
775  // Time-derivative contribution
776  if ( m_mapping->IsTimeDependent() )
777  {
778  MappingAccelerationCorrection(vel, velPhys, tmp);
779  for (int i = 0; i < m_nConvectiveFields; ++i)
780  {
781  Vmath::Vadd(physTot, tmp[i], 1, Forcing[i], 1, Forcing[i], 1);
782  }
783  }
784 
785  // Pressure contribution
786  if (!m_implicitPressure)
787  {
789  for (int i = 0; i < m_nConvectiveFields; ++i)
790  {
791  Vmath::Vadd(physTot, tmp[i], 1, Forcing[i], 1, Forcing[i], 1);
792  }
793  }
794  // Viscous contribution
795  if ( (!m_implicitViscous) && (!m_neglectViscous))
796  {
797  MappingViscousCorrection(velPhys, tmp);
798  for (int i = 0; i < m_nConvectiveFields; ++i)
799  {
800  Vmath::Smul(physTot, m_kinvis, tmp[i], 1, tmp[i], 1);
801  Vmath::Vadd(physTot, tmp[i], 1, Forcing[i], 1, Forcing[i], 1);
802  }
803  }
804 
805  // If necessary, transform to wavespace
806  if(m_fields[0]->GetWaveSpace())
807  {
808  for (int i = 0; i < m_nConvectiveFields; ++i)
809  {
810  m_fields[0]->HomogeneousFwdTrans(Forcing[i],Forcing[i]);
811  }
812  }
813 
814  // Add to outarray
815  for (int i = 0; i < m_nConvectiveFields; ++i)
816  {
817  Vmath::Vadd(physTot, outarray[i], 1, Forcing[i], 1, outarray[i], 1);
818  }
819  }
820 
822  const Array<OneD, const Array<OneD, NekDouble> > &velPhys,
823  Array<OneD, Array<OneD, NekDouble> > &outarray)
824  {
825  int physTot = m_fields[0]->GetTotPoints();
826  int nvel = m_nConvectiveFields;
827 
828  Array<OneD, Array<OneD, NekDouble> > wk(nvel*nvel);
829 
830  // Apply Christoffel symbols to obtain {i,kj}vel(k)
831  m_mapping->ApplyChristoffelContravar(velPhys, wk);
832 
833  // Calculate correction -U^j*{i,kj}vel(k)
834  for (int i = 0; i< nvel; i++)
835  {
836  Vmath::Zero(physTot,outarray[i],1);
837  for (int j = 0; j< nvel; j++)
838  {
839  Vmath::Vvtvp(physTot,wk[i*nvel+j],1,velPhys[j],1,
840  outarray[i],1,outarray[i],1);
841  }
842  Vmath::Neg(physTot, outarray[i], 1);
843  }
844  }
845 
847  const Array<OneD, const Array<OneD, NekDouble> > &vel,
848  const Array<OneD, const Array<OneD, NekDouble> > &velPhys,
849  Array<OneD, Array<OneD, NekDouble> > &outarray)
850  {
851  int physTot = m_fields[0]->GetTotPoints();
852  int nvel = m_nConvectiveFields;
853 
854  Array<OneD, Array<OneD, NekDouble> > wk(nvel*nvel);
856  Array<OneD, Array<OneD, NekDouble> > coordVel(nvel);
857  for (int i = 0; i< nvel; i++)
858  {
859  tmp[i] = Array<OneD, NekDouble> (physTot, 0.0);
860  coordVel[i] = Array<OneD, NekDouble> (physTot, 0.0);
861  }
862  // Get coordinates velocity in transformed system
863  m_mapping->GetCoordVelocity(tmp);
864  m_mapping->ContravarFromCartesian(tmp, coordVel);
865 
866  // Calculate first term: U^j u^i,j = U^j (du^i/dx^j + {i,kj}u^k)
867  m_mapping->ApplyChristoffelContravar(velPhys, wk);
868  for (int i=0; i< nvel; i++)
869  {
870  Vmath::Zero(physTot,outarray[i],1);
871 
872  m_fields[0]->PhysDeriv(velPhys[i], tmp[0], tmp[1]);
873  for (int j=0; j< nvel; j++)
874  {
875  if (j == 2)
876  {
877  m_fields[0]->PhysDeriv(MultiRegions::DirCartesianMap[j],
878  vel[i], tmp[2]);
879  if (m_fields[0]->GetWaveSpace())
880  {
881  m_fields[0]->HomogeneousBwdTrans(tmp[2],tmp[2]);
882  }
883  }
884 
885  Vmath::Vadd(physTot,wk[i*nvel+j],1,tmp[j],1,
886  wk[i*nvel+j], 1);
887 
888  Vmath::Vvtvp(physTot, coordVel[j], 1, wk[i*nvel+j], 1,
889  outarray[i], 1, outarray[i], 1);
890  }
891  }
892 
893  // Set wavespace to false and store current value
894  bool wavespace = m_fields[0]->GetWaveSpace();
895  m_fields[0]->SetWaveSpace(false);
896 
897  // Add -u^j U^i,j
898  m_mapping->ApplyChristoffelContravar(coordVel, wk);
899  for (int i=0; i< nvel; i++)
900  {
901  if(nvel == 2)
902  {
903  m_fields[0]->PhysDeriv(coordVel[i], tmp[0], tmp[1]);
904  }
905  else
906  {
907  m_fields[0]->PhysDeriv(coordVel[i], tmp[0], tmp[1], tmp[2]);
908  }
909 
910  for (int j=0; j< nvel; j++)
911  {
912  Vmath::Vadd(physTot,wk[i*nvel+j],1,tmp[j],1,
913  wk[i*nvel+j], 1);
914  Vmath::Neg(physTot, wk[i*nvel+j], 1);
915 
916  Vmath::Vvtvp(physTot, velPhys[j], 1, wk[i*nvel+j], 1,
917  outarray[i], 1, outarray[i], 1);
918  }
919  }
920 
921  // Restore value of wavespace
922  m_fields[0]->SetWaveSpace(wavespace);
923  }
924 
926  Array<OneD, Array<OneD, NekDouble> > &outarray)
927  {
928  int physTot = m_fields[0]->GetTotPoints();
929  int nvel = m_nConvectiveFields;
930 
931  // Calculate g^(ij)p_(,j)
932  m_mapping->RaiseIndex(m_gradP, outarray);
933 
934  // Calculate correction = (nabla p)/J - g^(ij)p_,j
935  // (Jac is not required if it is constant)
936  if ( !m_mapping->HasConstantJacobian())
937  {
938  Array<OneD, NekDouble> Jac(physTot, 0.0);
939  m_mapping->GetJacobian(Jac);
940  for(int i = 0; i < nvel; ++i)
941  {
942  Vmath::Vdiv(physTot, m_gradP[i], 1, Jac, 1, m_gradP[i], 1);
943  }
944  }
945  for(int i = 0; i < nvel; ++i)
946  {
947  Vmath::Vsub(physTot, m_gradP[i], 1,outarray[i], 1,
948  outarray[i],1);
949  }
950  }
951 
953  const Array<OneD, const Array<OneD, NekDouble> > &velPhys,
954  Array<OneD, Array<OneD, NekDouble> > &outarray)
955  {
956  // L(U) - 1.0*d^2(u^i)/dx^jdx^j
957  m_mapping->VelocityLaplacian(velPhys, outarray, 1.0);
958  }
959 
960 } //end of namespace
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
Definition: ErrorUtil.hpp:209
static GLOBAL_MAPPING_EXPORT MappingSharedPtr Load(const LibUtilities::SessionReaderSharedPtr &pSession, const Array< OneD, MultiRegions::ExpListSharedPtr > &pFields)
Return a pointer to the mapping, creating it on first call.
Definition: Mapping.cpp:268
MultiRegions::ExpListSharedPtr m_pressure
Pointer to field holding pressure field.
NekDouble m_kinvis
Kinematic viscosity.
bool m_SmoothAdvection
bool to identify if advection term smoothing is requested
ExtrapolateSharedPtr m_extrapolation
Array< OneD, int > m_velocity
int which identifies which components of m_fields contains the velocity (u,v,w);
int m_intSteps
Number of time integration steps AND Order of extrapolation for pressure boundary conditions.
int m_nConvectiveFields
Number of fields to be convected;.
std::vector< SolverUtils::ForcingSharedPtr > m_forcing
Forcing terms.
void EvaluateAdvectionTerms(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray, const NekDouble time)
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:200
tBaseSharedPtr CreateInstance(tKey idKey, tParam... args)
Create an instance of the class referred to by idKey.
Definition: NekFactory.hpp:145
SolverUtils::AdvectionSharedPtr m_advObject
Advection term.
NekDouble m_timestep
Time step size.
Array< OneD, MultiRegions::ExpListSharedPtr > m_fields
Array holding all dependent variables.
LibUtilities::SessionReaderSharedPtr m_session
The session reader.
LibUtilities::FieldMetaDataMap m_fieldMetaDataMap
Map to identify relevant solver info to dump in output fields.
SOLVER_UTILS_EXPORT int GetTotPoints()
Defines a forcing term to be explicitly applied.
Definition: Forcing.h:73
Base class for unsteady solvers.
virtual SOLVER_UTILS_EXPORT void v_DoInitialise()
Sets up initial conditions.
LibUtilities::TimeIntegrationSchemeSharedPtr m_intScheme
Wrapper to the time integration scheme.
void MappingViscousCorrection(const Array< OneD, const Array< OneD, NekDouble > > &velPhys, Array< OneD, Array< OneD, NekDouble > > &outarray)
Definition: VCSMapping.cpp:952
virtual ~VCSMapping()
Definition: VCSMapping.cpp:135
virtual void v_SolvePressure(const Array< OneD, NekDouble > &Forcing)
Definition: VCSMapping.cpp:428
NekDouble m_pressureTolerance
Definition: VCSMapping.h:88
NekDouble m_viscousRelaxation
Definition: VCSMapping.h:91
virtual void v_SetUpPressureForcing(const Array< OneD, const Array< OneD, NekDouble > > &fields, Array< OneD, Array< OneD, NekDouble > > &Forcing, const NekDouble aii_Dt)
Definition: VCSMapping.cpp:225
NekDouble m_pressureRelaxation
Definition: VCSMapping.h:90
virtual void v_EvaluateAdvection_SetPressureBCs(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray, const NekDouble time)
Definition: VCSMapping.cpp:180
NekDouble m_viscousTolerance
Definition: VCSMapping.h:89
virtual void v_SolveViscous(const Array< OneD, const Array< OneD, NekDouble > > &Forcing, Array< OneD, Array< OneD, NekDouble > > &outarray, const NekDouble aii_Dt)
Definition: VCSMapping.cpp:572
GlobalMapping::MappingSharedPtr m_mapping
Definition: VCSMapping.h:77
void MappingPressureCorrection(Array< OneD, Array< OneD, NekDouble > > &outarray)
Definition: VCSMapping.cpp:925
void ApplyIncNSMappingForcing(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray)
Definition: VCSMapping.cpp:738
virtual void v_InitObject()
Init object for UnsteadySystem class.
Definition: VCSMapping.cpp:65
Array< OneD, Array< OneD, NekDouble > > m_presForcingCorrection
Definition: VCSMapping.h:123
virtual void v_DoInitialise(void)
Sets up initial conditions.
Definition: VCSMapping.cpp:139
virtual void v_SetUpViscousForcing(const Array< OneD, const Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &Forcing, const NekDouble aii_Dt)
Definition: VCSMapping.cpp:351
void MappingAccelerationCorrection(const Array< OneD, const Array< OneD, NekDouble > > &vel, const Array< OneD, const Array< OneD, NekDouble > > &velPhys, Array< OneD, Array< OneD, NekDouble > > &outarray)
Definition: VCSMapping.cpp:846
Array< OneD, Array< OneD, NekDouble > > m_gradP
Definition: VCSMapping.h:94
void MappingAdvectionCorrection(const Array< OneD, const Array< OneD, NekDouble > > &velPhys, Array< OneD, Array< OneD, NekDouble > > &outarray)
Definition: VCSMapping.cpp:821
virtual void v_InitObject()
Init object for UnsteadySystem class.
virtual void v_SolveViscous(const Array< OneD, const Array< OneD, NekDouble > > &Forcing, Array< OneD, Array< OneD, NekDouble > > &outarray, const NekDouble aii_Dt)
NekDouble m_sVVCutoffRatio
cutt off ratio from which to start decayhing modes
NekDouble m_sVVDiffCoeff
Diffusion coefficient of SVV modes.
Array< OneD, Array< OneD, NekDouble > > m_F
virtual void v_SolvePressure(const Array< OneD, NekDouble > &Forcing)
virtual void v_SetUpPressureForcing(const Array< OneD, const Array< OneD, NekDouble > > &fields, Array< OneD, Array< OneD, NekDouble > > &Forcing, const NekDouble aii_Dt)
bool m_useSpecVanVisc
bool to identify if spectral vanishing viscosity is active.
static void Dscal(const int &n, const double &alpha, double *x, const int &incx)
BLAS level 1: x = alpha x.
Definition: Blas.hpp:182
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
MultiRegions::Direction const DirCartesianMap[]
Definition: ExpList.h:90
EquationSystemFactory & GetEquationSystemFactory()
std::shared_ptr< MeshGraph > MeshGraphSharedPtr
Definition: MeshGraph.h:174
std::map< ConstFactorType, NekDouble > ConstFactorMap
Definition: StdRegions.hpp:314
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:1
ExtrapolateFactory & GetExtrapolateFactory()
Definition: Extrapolate.cpp:49
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:192
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 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 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