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