Nektar++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
UnsteadySystem.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File UnsteadySystem.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 // License for the specific language governing rights and limitations under
14 // Permission is hereby granted, free of charge, to any person obtaining a
15 // copy of this software and associated documentation files (the "Software"),
16 // to deal in the Software without restriction, including without limitation
17 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 // and/or sell copies of the Software, and to permit persons to whom the
19 // Software is furnished to do so, subject to the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be included
22 // in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
25 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 // DEALINGS IN THE SOFTWARE.
31 //
32 // Description: Generic timestepping for Unsteady solvers
33 //
34 ///////////////////////////////////////////////////////////////////////////////
35 
36 #include <iostream>
37 #include <iomanip>
38 
43 
44 using namespace std;
45 
46 namespace Nektar
47 {
48  namespace SolverUtils
49  {
50  /**
51  * @class UnsteadySystem
52  *
53  * Provides the underlying timestepping framework for unsteady solvers
54  * including the general timestepping routines. This class is not
55  * intended to be directly instantiated, but rather is a base class
56  * on which to define unsteady solvers.
57  *
58  * For details on implementing unsteady solvers see
59  * \ref sectionADRSolverModuleImplementation here
60  */
61 
62  /**
63  * Processes SolverInfo parameters from the session file and sets up
64  * timestepping-specific code.
65  * @param pSession Session object to read parameters from.
66  */
67  UnsteadySystem::UnsteadySystem(
69  : EquationSystem(pSession),
70  m_infosteps(10)
71 
72  {
73  }
74 
75  /**
76  * Initialization object for UnsteadySystem class.
77  */
79  {
81 
82  m_initialStep = 0;
83 
84  // Load SolverInfo parameters
85  m_session->MatchSolverInfo("DIFFUSIONADVANCEMENT","Explicit",
86  m_explicitDiffusion,true);
87  m_session->MatchSolverInfo("ADVECTIONADVANCEMENT","Explicit",
88  m_explicitAdvection,true);
89  m_session->MatchSolverInfo("REACTIONADVANCEMENT", "Explicit",
90  m_explicitReaction, true);
91 
92  m_session->LoadParameter("CheckNanSteps", m_nanSteps, 1);
93 
94  // For steady problems, we do not initialise the time integration
95  if (m_session->DefinesSolverInfo("TIMEINTEGRATIONMETHOD"))
96  {
98  CreateInstance(m_session->GetSolverInfo(
99  "TIMEINTEGRATIONMETHOD"));
100 
101  // Load generic input parameters
102  m_session->LoadParameter("IO_InfoSteps", m_infosteps, 0);
103  m_session->LoadParameter("CFL", m_cflSafetyFactor, 0.0);
104 
105  // Set up time to be dumped in field information
106  m_fieldMetaDataMap["Time"] =
107  boost::lexical_cast<std::string>(m_time);
108  }
109 
110  // By default attempt to forward transform initial condition.
111  m_homoInitialFwd = true;
112 
113  // Set up filters
114  LibUtilities::FilterMap::const_iterator x;
115  LibUtilities::FilterMap f = m_session->GetFilters();
116  for (x = f.begin(); x != f.end(); ++x)
117  {
118  m_filters.push_back(GetFilterFactory().CreateInstance(
119  x->first,
120  m_session,
121  x->second));
122  }
123  }
124 
125  /**
126  * Destructor for the class UnsteadyAdvection.
127  */
129  {
130  }
131 
132  /**
133  * @brief Returns the maximum time estimator for CFL control.
134  */
136  {
137  NekDouble TimeStability = 0.0;
138  switch(m_intScheme->GetIntegrationMethod())
139  {
143  {
144  TimeStability = 2.784;
145  break;
146  }
153  {
154  TimeStability = 2.0;
155  break;
156  }
158  {
159  TimeStability = 1.0;
160  break;
161  }
162  default:
163  {
164  ASSERTL0(
165  false,
166  "No CFL control implementation for this time"
167  "integration scheme");
168  }
169  }
170  return TimeStability;
171  }
172 
173  /**
174  * @brief Initialises the time integration scheme (as specified in the
175  * session file), and perform the time integration.
176  */
178  {
179  ASSERTL0(m_intScheme != 0, "No time integration scheme.");
180 
181  int i = 1;
182  int nvariables = 0;
183  int nfields = m_fields.num_elements();
184 
185  if (m_intVariables.empty())
186  {
187  for (i = 0; i < nfields; ++i)
188  {
189  m_intVariables.push_back(i);
190  }
191  nvariables = nfields;
192  }
193  else
194  {
195  nvariables = m_intVariables.size();
196  }
197 
198  // Integrate in wave-space if using homogeneous1D
200  {
201  for(i = 0; i < nfields; ++i)
202  {
203  m_fields[i]->HomogeneousFwdTrans(m_fields[i]->GetPhys(),
204  m_fields[i]->UpdatePhys());
205  m_fields[i]->SetWaveSpace(true);
206  m_fields[i]->SetPhysState(false);
207  }
208  }
209 
210  // Set up wrapper to fields data storage.
211  Array<OneD, Array<OneD, NekDouble> > fields(nvariables);
212  Array<OneD, Array<OneD, NekDouble> > tmp (nvariables);
213 
214  // Order storage to list time-integrated fields first.
215  for(i = 0; i < nvariables; ++i)
216  {
217  fields[i] = m_fields[m_intVariables[i]]->GetPhys();
218  m_fields[m_intVariables[i]]->SetPhysState(false);
219  }
220 
221  // Initialise time integration scheme
222  m_intSoln = m_intScheme->InitializeScheme(
223  m_timestep, fields, m_time, m_ode);
224 
225  // Initialise filters
227  for (x = m_filters.begin(); x != m_filters.end(); ++x)
228  {
229  (*x)->Initialise(m_fields, m_time);
230  }
231 
232  // Ensure that there is no conflict of parameters
233  if(m_cflSafetyFactor > 0.0)
234  {
235  // Check final condition
236  ASSERTL0(m_fintime == 0.0 || m_steps == 0,
237  "Final condition not unique: "
238  "fintime > 0.0 and Nsteps > 0");
239 
240  // Check timestep condition
241  ASSERTL0(m_timestep == 0.0,
242  "Timestep not unique: timestep > 0.0 & CFL > 0.0");
243  }
244 
245  // Check uniqueness of checkpoint output
246  ASSERTL0((m_checktime == 0.0 && m_checksteps == 0) ||
247  (m_checktime > 0.0 && m_checksteps == 0) ||
248  (m_checktime == 0.0 && m_checksteps > 0),
249  "Only one of IO_CheckTime and IO_CheckSteps "
250  "should be set!");
251 
252  Timer timer;
253  bool doCheckTime = false;
254  int step = m_initialStep;
255  int stepCounter = 0;
256  NekDouble intTime = 0.0;
257  NekDouble lastCheckTime = 0.0;
258  NekDouble cpuTime = 0.0;
259  NekDouble elapsed = 0.0;
260 
261  while (step < m_steps ||
263  {
264  if (m_cflSafetyFactor)
265  {
266  m_timestep = GetTimeStep(fields);
267 
268  // Ensure that the final timestep finishes at the final
269  // time, or at a prescribed IO_CheckTime.
270  if (m_time + m_timestep > m_fintime && m_fintime > 0.0)
271  {
273  }
274  else if (m_checktime &&
275  m_time + m_timestep - lastCheckTime >= m_checktime)
276  {
277  lastCheckTime += m_checktime;
278  m_timestep = lastCheckTime - m_time;
279  doCheckTime = true;
280  }
281  }
282 
283  // Perform any solver-specific pre-integration steps
284  timer.Start();
285  if (v_PreIntegrate(step))
286  {
287  break;
288  }
289 
290  fields = m_intScheme->TimeIntegrate(
291  stepCounter, m_timestep, m_intSoln, m_ode);
292  timer.Stop();
293 
294  m_time += m_timestep;
295  elapsed = timer.TimePerTest(1);
296  intTime += elapsed;
297  cpuTime += elapsed;
298 
299  // Write out status information
300  if (m_session->GetComm()->GetRank() == 0 &&
301  !((step+1) % m_infosteps))
302  {
303  cout << "Steps: " << setw(8) << left << step+1 << " "
304  << "Time: " << setw(12) << left << m_time;
305 
306  if (m_cflSafetyFactor)
307  {
308  cout << " Time-step: " << setw(12)
309  << left << m_timestep;
310  }
311 
312  stringstream ss;
313  ss << cpuTime << "s";
314  cout << " CPU Time: " << setw(8) << left
315  << ss.str() << endl;
316  cpuTime = 0.0;
317  }
318 
319  // Transform data into coefficient space
320  for (i = 0; i < nvariables; ++i)
321  {
322  m_fields[m_intVariables[i]]->SetPhys(fields[i]);
323  if( v_RequireFwdTrans() )
324  {
325  m_fields[m_intVariables[i]]->FwdTrans_IterPerExp(
326  fields[i],
327  m_fields[m_intVariables[i]]->UpdateCoeffs());
328  }
329  m_fields[m_intVariables[i]]->SetPhysState(false);
330  }
331 
332  // Perform any solver-specific post-integration steps
333  if (v_PostIntegrate(step))
334  {
335  break;
336  }
337 
338  // search for NaN and quit if found
339  if (m_nanSteps && !((step+1) % m_nanSteps) )
340  {
341  int nanFound = 0;
342  for (i = 0; i < nvariables; ++i)
343  {
344  if (Vmath::Nnan(fields[i].num_elements(),
345  fields[i], 1) > 0)
346  {
347  nanFound = 1;
348  }
349  }
350  m_session->GetComm()->AllReduce(nanFound,
352  ASSERTL0 (!nanFound,
353  "NaN found during time integration.");
354  }
355  // Update filters
357  for (x = m_filters.begin(); x != m_filters.end(); ++x)
358  {
359  (*x)->Update(m_fields, m_time);
360  }
361 
362  // Write out checkpoint files
363  if ((m_checksteps && !((step + 1) % m_checksteps)) ||
364  doCheckTime)
365  {
367  {
368  vector<bool> transformed(nfields, false);
369  for(i = 0; i < nfields; i++)
370  {
371  if (m_fields[i]->GetWaveSpace())
372  {
373  m_fields[i]->SetWaveSpace(false);
374  m_fields[i]->BwdTrans(m_fields[i]->GetCoeffs(),
375  m_fields[i]->UpdatePhys());
376  m_fields[i]->SetPhysState(true);
377  transformed[i] = true;
378  }
379  }
381  m_nchk++;
382  for(i = 0; i < nfields; i++)
383  {
384  if (transformed[i])
385  {
386  m_fields[i]->SetWaveSpace(true);
387  m_fields[i]->HomogeneousFwdTrans(
388  m_fields[i]->GetPhys(),
389  m_fields[i]->UpdatePhys());
390  m_fields[i]->SetPhysState(false);
391  }
392  }
393  }
394  else
395  {
397  m_nchk++;
398  }
399  doCheckTime = false;
400  }
401 
402  // Step advance
403  ++step;
404  ++stepCounter;
405  }
406 
407  // Print out summary statistics
408  if (m_session->GetComm()->GetRank() == 0)
409  {
410  if (m_cflSafetyFactor > 0.0)
411  {
412  cout << "CFL safety factor : " << m_cflSafetyFactor << endl
413  << "CFL time-step : " << m_timestep << endl;
414  }
415 
416  if (m_session->GetSolverInfo("Driver") != "SteadyState")
417  {
418  cout << "Time-integration : " << intTime << "s" << endl;
419  }
420  }
421 
422  // If homogeneous, transform back into physical space if necessary.
424  {
425  for(i = 0; i < nfields; i++)
426  {
427  if (m_fields[i]->GetWaveSpace())
428  {
429  m_fields[i]->SetWaveSpace(false);
430  m_fields[i]->BwdTrans(m_fields[i]->GetCoeffs(),
431  m_fields[i]->UpdatePhys());
432  m_fields[i]->SetPhysState(true);
433  }
434  }
435  }
436  else
437  {
438  for(i = 0; i < nvariables; ++i)
439  {
440  m_fields[m_intVariables[i]]->SetPhys(fields[i]);
441  m_fields[m_intVariables[i]]->SetPhysState(true);
442  }
443  }
444 
445  // Finalise filters
446  for (x = m_filters.begin(); x != m_filters.end(); ++x)
447  {
448  (*x)->Finalise(m_fields, m_time);
449  }
450 
451  // Print for 1D problems
452  if(m_spacedim == 1)
453  {
454  v_AppendOutput1D(fields);
455  }
456  }
457 
458  /**
459  * @brief Sets the initial conditions.
460  */
462  {
466  }
467 
468  /**
469  * @brief Prints a summary with some information regards the
470  * time-stepping.
471  */
473  {
475  AddSummaryItem(s, "Advection",
476  m_explicitAdvection ? "explicit" : "implicit");
477 
478  if(m_session->DefinesSolverInfo("AdvectionType"))
479  {
480  AddSummaryItem(s, "AdvectionType",
481  m_session->GetSolverInfo("AdvectionType"));
482  }
483 
484  AddSummaryItem(s, "Diffusion",
485  m_explicitDiffusion ? "explicit" : "implicit");
486 
487  if (m_session->GetSolverInfo("EQTYPE")
488  == "SteadyAdvectionDiffusionReaction")
489  {
490  AddSummaryItem(s, "Reaction",
491  m_explicitReaction ? "explicit" : "implicit");
492  }
493 
494  AddSummaryItem(s, "Time Step", m_timestep);
495  AddSummaryItem(s, "No. of Steps", m_steps);
496  AddSummaryItem(s, "Checkpoints (steps)", m_checksteps);
497  AddSummaryItem(s, "Integration Type",
499  m_intScheme->GetIntegrationMethod()]);
500  }
501 
502  /**
503  * Stores the solution in a file for 1D problems only. This method has
504  * been implemented to facilitate the post-processing for 1D problems.
505  */
507  Array<OneD, Array<OneD, NekDouble> > &solution1D)
508  {
509  // Coordinates of the quadrature points in the real physical space
513  m_fields[0]->GetCoords(x, y, z);
514 
515  // Print out the solution in a txt file
516  ofstream outfile;
517  outfile.open("solution1D.txt");
518  for(int i = 0; i < GetNpoints(); i++)
519  {
520  outfile << scientific << setw (17) << setprecision(16) << x[i]
521  << " " << solution1D[0][i] << endl;
522  }
523  outfile << endl << endl;
524  outfile.close();
525  }
526 
528  Array<OneD, Array<OneD, NekDouble> > &physfield,
529  Array<OneD, Array<OneD, NekDouble> > &numflux)
530  {
531  ASSERTL0(false,
532  "This function is not implemented for this equation.");
533  }
534 
536  Array<OneD, Array<OneD, NekDouble> > &physfield,
537  Array<OneD, Array<OneD, NekDouble> > &numfluxX,
538  Array<OneD, Array<OneD, NekDouble> > &numfluxY )
539  {
540  ASSERTL0(false,
541  "This function is not implemented for this equation.");
542  }
543 
545  const Array<OneD, Array<OneD, NekDouble> > &ufield,
547  {
548  int i, j;
549  int nTraceNumPoints = GetTraceNpoints();
550  int nvariables = m_fields.num_elements();
551  int nqvar = uflux.num_elements();
552 
553  Array<OneD, NekDouble > Fwd (nTraceNumPoints);
554  Array<OneD, NekDouble > Bwd (nTraceNumPoints);
555  Array<OneD, NekDouble > Vn (nTraceNumPoints, 0.0);
556  Array<OneD, NekDouble > fluxtemp(nTraceNumPoints, 0.0);
557 
558  // Get the sign of (v \cdot n), v = an arbitrary vector
559 
560  // Evaulate upwind flux:
561  // uflux = \hat{u} \phi \cdot u = u^{(+,-)} n
562  for (j = 0; j < nqvar; ++j)
563  {
564  for (i = 0; i < nvariables ; ++i)
565  {
566  // Compute Fwd and Bwd value of ufield of i direction
567  m_fields[i]->GetFwdBwdTracePhys(ufield[i], Fwd, Bwd);
568 
569  // if Vn >= 0, flux = uFwd, i.e.,
570  // edge::eForward, if V*n>=0 <=> V*n_F>=0, pick uflux = uFwd
571  // edge::eBackward, if V*n>=0 <=> V*n_B<0, pick uflux = uFwd
572 
573  // else if Vn < 0, flux = uBwd, i.e.,
574  // edge::eForward, if V*n<0 <=> V*n_F<0, pick uflux = uBwd
575  // edge::eBackward, if V*n<0 <=> V*n_B>=0, pick uflux = uBwd
576 
577  m_fields[i]->GetTrace()->Upwind(m_traceNormals[j],
578  Fwd, Bwd, fluxtemp);
579 
580  // Imposing weak boundary condition with flux
581  // if Vn >= 0, uflux = uBwd at Neumann, i.e.,
582  // edge::eForward, if V*n>=0 <=> V*n_F>=0, pick uflux = uBwd
583  // edge::eBackward, if V*n>=0 <=> V*n_B<0, pick uflux = uBwd
584 
585  // if Vn >= 0, uflux = uFwd at Neumann, i.e.,
586  // edge::eForward, if V*n<0 <=> V*n_F<0, pick uflux = uFwd
587  // edge::eBackward, if V*n<0 <=> V*n_B>=0, pick uflux = uFwd
588 
589  if(m_fields[0]->GetBndCondExpansions().num_elements())
590  {
591  WeakPenaltyforScalar(i, ufield[i], fluxtemp);
592  }
593 
594  // if Vn >= 0, flux = uFwd*(tan_{\xi}^- \cdot \vec{n}),
595  // i.e,
596  // edge::eForward, uFwd \(\tan_{\xi}^Fwd \cdot \vec{n})
597  // edge::eBackward, uFwd \(\tan_{\xi}^Bwd \cdot \vec{n})
598 
599  // else if Vn < 0, flux = uBwd*(tan_{\xi}^- \cdot \vec{n}),
600  // i.e,
601  // edge::eForward, uBwd \(\tan_{\xi}^Fwd \cdot \vec{n})
602  // edge::eBackward, uBwd \(\tan_{\xi}^Bwd \cdot \vec{n})
603 
604  Vmath::Vmul(nTraceNumPoints,
605  m_traceNormals[j], 1,
606  fluxtemp, 1,
607  uflux[j][i], 1);
608  }
609  }
610  }
611 
612 
613 
615  const Array<OneD, Array<OneD, NekDouble> > &ufield,
618  {
619  int nTraceNumPoints = GetTraceNpoints();
620  int nvariables = m_fields.num_elements();
621  int nqvar = qfield.num_elements();
622 
623  NekDouble C11 = 1.0;
624  Array<OneD, NekDouble > Fwd(nTraceNumPoints);
625  Array<OneD, NekDouble > Bwd(nTraceNumPoints);
626  Array<OneD, NekDouble > Vn (nTraceNumPoints, 0.0);
627 
628  Array<OneD, NekDouble > qFwd (nTraceNumPoints);
629  Array<OneD, NekDouble > qBwd (nTraceNumPoints);
630  Array<OneD, NekDouble > qfluxtemp(nTraceNumPoints, 0.0);
631 
632  Array<OneD, NekDouble > uterm(nTraceNumPoints);
633 
634  // Evaulate upwind flux:
635  // qflux = \hat{q} \cdot u = q \cdot n - C_(11)*(u^+ - u^-)
636  for (int i = 0; i < nvariables; ++i)
637  {
638  qflux[i] = Array<OneD, NekDouble> (nTraceNumPoints, 0.0);
639  for (int j = 0; j < nqvar; ++j)
640  {
641  // Compute Fwd and Bwd value of ufield of jth direction
642  m_fields[i]->GetFwdBwdTracePhys(qfield[j][i],qFwd,qBwd);
643 
644  // if Vn >= 0, flux = uFwd, i.e.,
645  // edge::eForward, if V*n>=0 <=> V*n_F>=0, pick
646  // qflux = qBwd = q+
647  // edge::eBackward, if V*n>=0 <=> V*n_B<0, pick
648  // qflux = qBwd = q-
649 
650  // else if Vn < 0, flux = uBwd, i.e.,
651  // edge::eForward, if V*n<0 <=> V*n_F<0, pick
652  // qflux = qFwd = q-
653  // edge::eBackward, if V*n<0 <=> V*n_B>=0, pick
654  // qflux = qFwd = q+
655 
656  m_fields[i]->GetTrace()->Upwind(m_traceNormals[j],
657  qBwd, qFwd,
658  qfluxtemp);
659 
660  Vmath::Vmul(nTraceNumPoints,
661  m_traceNormals[j], 1,
662  qfluxtemp, 1,
663  qfluxtemp, 1);
664 
665  // Generate Stability term = - C11 ( u- - u+ )
666  m_fields[i]->GetFwdBwdTracePhys(ufield[i], Fwd, Bwd);
667 
668  Vmath::Vsub(nTraceNumPoints,
669  Fwd, 1, Bwd, 1,
670  uterm, 1);
671 
672  Vmath::Smul(nTraceNumPoints,
673  -1.0 * C11, uterm, 1,
674  uterm, 1);
675 
676  // Flux = {Fwd, Bwd} * (nx, ny, nz) + uterm * (nx, ny)
677  Vmath::Vadd(nTraceNumPoints,
678  uterm, 1,
679  qfluxtemp, 1,
680  qfluxtemp, 1);
681 
682  // Imposing weak boundary condition with flux
683  if (m_fields[0]->GetBndCondExpansions().num_elements())
684  {
685  WeakPenaltyforVector(i, j,
686  qfield[j][i],
687  qfluxtemp,
688  C11);
689  }
690 
691  // q_hat \cdot n = (q_xi \cdot n_xi) or (q_eta \cdot n_eta)
692  // n_xi = n_x * tan_xi_x + n_y * tan_xi_y + n_z * tan_xi_z
693  // n_xi = n_x * tan_eta_x + n_y * tan_eta_y + n_z*tan_eta_z
694  Vmath::Vadd(nTraceNumPoints,
695  qfluxtemp, 1,
696  qflux[i], 1,
697  qflux[i], 1);
698  }
699  }
700  }
701 
703  {
704  if (m_session->DefinesFunction("InitialConditions"))
705  {
706  for (int i = 0; i < m_fields.num_elements(); ++i)
707  {
709 
710  vType = m_session->GetFunctionType(
711  "InitialConditions", m_session->GetVariable(i));
712 
713  if (vType == LibUtilities::eFunctionTypeFile)
714  {
715  std::string filename
716  = m_session->GetFunctionFilename(
717  "InitialConditions", m_session->GetVariable(i));
718 
719  fs::path pfilename(filename);
720 
721  // redefine path for parallel file which is in directory
722  if(fs::is_directory(pfilename))
723  {
724  fs::path metafile("Info.xml");
725  fs::path fullpath = pfilename / metafile;
726  filename = LibUtilities::PortablePath(fullpath);
727  }
730  m_session, filename);
731  fld->ImportFieldMetaData(filename, m_fieldMetaDataMap);
732 
733  // check to see if time defined
734  if (m_fieldMetaDataMap !=
736  {
738 
739  iter = m_fieldMetaDataMap.find("Time");
740  if (iter != m_fieldMetaDataMap.end())
741  {
742  time = boost::lexical_cast<NekDouble>(
743  iter->second);
744  }
745 
746  iter = m_fieldMetaDataMap.find("ChkFileNum");
747  if (iter != m_fieldMetaDataMap.end())
748  {
749  nchk = boost::lexical_cast<NekDouble>(
750  iter->second);
751  }
752  }
753 
754  break;
755  }
756  }
757  }
758  }
759 
761  const int var,
762  const Array<OneD, const NekDouble> &physfield,
763  Array<OneD, NekDouble> &penaltyflux,
764  NekDouble time)
765  {
766  int i, e, npoints, id1, id2;
767 
768  // Number of boundary regions
769  int nbnd = m_fields[var]->GetBndCondExpansions().num_elements();
770  int Nfps, numBDEdge;
771  int nTraceNumPoints = GetTraceNpoints();
772  int cnt = 0;
773 
774  Array<OneD, NekDouble > uplus(nTraceNumPoints);
775 
776  m_fields[var]->ExtractTracePhys(physfield, uplus);
777  for (i = 0; i < nbnd; ++i)
778  {
779  // Number of boundary expansion related to that region
780  numBDEdge = m_fields[var]->
781  GetBndCondExpansions()[i]->GetExpSize();
782 
783  // Evaluate boundary values g_D or g_N from input files
785  m_session->GetFunction("InitialConditions", 0);
786 
787  npoints = m_fields[var]->
788  GetBndCondExpansions()[i]->GetNpoints();
789 
790  Array<OneD,NekDouble> BDphysics(npoints);
791  Array<OneD,NekDouble> x0(npoints,0.0);
792  Array<OneD,NekDouble> x1(npoints,0.0);
793  Array<OneD,NekDouble> x2(npoints,0.0);
794 
795  m_fields[var]->GetBndCondExpansions()[i]->GetCoords(x0,x1,x2);
796  ifunc->Evaluate(x0,x1,x2,time,BDphysics);
797 
798  // Weakly impose boundary conditions by modifying flux values
799  for (e = 0; e < numBDEdge ; ++e)
800  {
801  // Number of points on the expansion
802  Nfps = m_fields[var]->
803  GetBndCondExpansions()[i]->GetExp(e)->GetNumPoints(0);
804 
805  id1 = m_fields[var]->
806  GetBndCondExpansions()[i]->GetPhys_Offset(e);
807 
808  id2 = m_fields[0]->GetTrace()->
809  GetPhys_Offset(m_fields[0]->GetTraceMap()->
810  GetBndCondTraceToGlobalTraceMap(cnt++));
811 
812  // For Dirichlet boundary condition: uflux = g_D
813  if (m_fields[var]->GetBndConditions()[i]->
814  GetBoundaryConditionType() == SpatialDomains::eDirichlet)
815  {
816  Vmath::Vcopy(Nfps,
817  &BDphysics[id1], 1,
818  &penaltyflux[id2], 1);
819  }
820  // For Neumann boundary condition: uflux = u+
821  else if ((m_fields[var]->GetBndConditions()[i])->
822  GetBoundaryConditionType() == SpatialDomains::eNeumann)
823  {
824  Vmath::Vcopy(Nfps,
825  &uplus[id2], 1,
826  &penaltyflux[id2], 1);
827  }
828  }
829  }
830  }
831 
832  /**
833  * Diffusion: Imposing weak boundary condition for q with flux
834  * uflux = g_D on Dirichlet boundary condition
835  * uflux = u_Fwd on Neumann boundary condition
836  */
838  const int var,
839  const int dir,
840  const Array<OneD, const NekDouble> &physfield,
841  Array<OneD, NekDouble> &penaltyflux,
842  NekDouble C11,
843  NekDouble time)
844  {
845  int i, e, npoints, id1, id2;
846  int nbnd = m_fields[var]->GetBndCondExpansions().num_elements();
847  int numBDEdge, Nfps;
848  int nTraceNumPoints = GetTraceNpoints();
849  Array<OneD, NekDouble > uterm(nTraceNumPoints);
850  Array<OneD, NekDouble > qtemp(nTraceNumPoints);
851  int cnt = 0;
852 
853  m_fields[var]->ExtractTracePhys(physfield,qtemp);
854 
855  for (i = 0; i < nbnd; ++i)
856  {
857  numBDEdge = m_fields[var]->
858  GetBndCondExpansions()[i]->GetExpSize();
859 
860  // Evaluate boundary values g_D or g_N from input files
862  m_session->GetFunction("InitialConditions", 0);
863 
864  npoints = m_fields[var]->
865  GetBndCondExpansions()[i]->GetNpoints();
866 
867  Array<OneD,NekDouble> BDphysics(npoints);
868  Array<OneD,NekDouble> x0(npoints,0.0);
869  Array<OneD,NekDouble> x1(npoints,0.0);
870  Array<OneD,NekDouble> x2(npoints,0.0);
871 
872  m_fields[var]->GetBndCondExpansions()[i]->GetCoords(x0,x1,x2);
873  ifunc->Evaluate(x0,x1,x2,time,BDphysics);
874 
875  // Weakly impose boundary conditions by modifying flux values
876  for (e = 0; e < numBDEdge ; ++e)
877  {
878  Nfps = m_fields[var]->
879  GetBndCondExpansions()[i]->GetExp(e)->GetNumPoints(0);
880 
881  id1 = m_fields[var]->
882  GetBndCondExpansions()[i]->GetPhys_Offset(e);
883 
884  id2 = m_fields[0]->GetTrace()->
885  GetPhys_Offset(m_fields[0]->GetTraceMap()->
886  GetBndCondTraceToGlobalTraceMap(cnt++));
887 
888  // For Dirichlet boundary condition:
889  //qflux = q+ - C_11 (u+ - g_D) (nx, ny)
890  if(m_fields[var]->GetBndConditions()[i]->
891  GetBoundaryConditionType() == SpatialDomains::eDirichlet)
892  {
893  Vmath::Vmul(Nfps,
894  &m_traceNormals[dir][id2], 1,
895  &qtemp[id2], 1,
896  &penaltyflux[id2], 1);
897  }
898  // For Neumann boundary condition: qflux = g_N
899  else if((m_fields[var]->GetBndConditions()[i])->
900  GetBoundaryConditionType() == SpatialDomains::eNeumann)
901  {
902  Vmath::Vmul(Nfps,
903  &m_traceNormals[dir][id2], 1,
904  &BDphysics[id1], 1,
905  &penaltyflux[id2], 1);
906  }
907  }
908  }
909  }
910 
911  /**
912  * @brief Return the timestep to be used for the next step in the
913  * time-marching loop.
914  *
915  * This function can be overloaded to facilitate solver which utilise a
916  * CFL (or other) parameter to determine a maximum timestep under which
917  * the problem remains stable.
918  */
920  const Array<OneD, const Array<OneD, NekDouble> > &inarray)
921  {
922  return v_GetTimeStep(inarray);
923  }
924 
925  /**
926  * @brief Return the timestep to be used for the next step in the
927  * time-marching loop.
928  *
929  * @see UnsteadySystem::GetTimeStep
930  */
932  const Array<OneD, const Array<OneD, NekDouble> > &inarray)
933  {
934  ASSERTL0(false, "Not defined for this class");
935  return 0.0;
936  }
937 
939  {
940  return false;
941  }
942 
944  {
945  return false;
946  }
947 
949  {
950  return false;
951  }
952 
954  const Array<OneD, Array<OneD, NekDouble> > vel,
955  StdRegions::VarCoeffMap &varCoeffMap)
956  {
957  int phystot = m_fields[0]->GetTotPoints();
958  int nvel = vel.num_elements();
959 
960  Array<OneD, NekDouble> varcoeff(phystot),tmp;
961 
962  // calculate magnitude of v
963  Vmath::Vmul(phystot,vel[0],1,vel[0],1,varcoeff,1);
964  for(int n = 1; n < nvel; ++n)
965  {
966  Vmath::Vvtvp(phystot,vel[n],1,vel[n],1,varcoeff,1,varcoeff,1);
967  }
968  Vmath::Vsqrt(phystot,varcoeff,1,varcoeff,1);
969 
970  for(int i = 0; i < m_fields[0]->GetNumElmts(); ++i)
971  {
972  int offset = m_fields[0]->GetPhys_Offset(i);
973  int nq = m_fields[0]->GetExp(i)->GetTotPoints();
974  Array<OneD, NekDouble> unit(nq,1.0);
975 
976  int nmodes = 0;
977 
978  for(int n = 0; n < m_fields[0]->GetExp(i)->GetNumBases(); ++n)
979  {
980  nmodes = max(nmodes,
981  m_fields[0]->GetExp(i)->GetBasisNumModes(n));
982  }
983 
984  NekDouble h = m_fields[0]->GetExp(i)->Integral(unit);
985  h = pow(h,(NekDouble) (1.0/nvel))/((NekDouble) nmodes);
986 
987  Vmath::Smul(nq,h,varcoeff+offset,1,tmp = varcoeff+offset,1);
988  }
989 
990  // set up map with eVarCoffLaplacian key
991  varCoeffMap[StdRegions::eVarCoeffLaplacian] = varcoeff;
992  }
993  }
994 }
virtual SOLVER_UTILS_EXPORT bool v_SteadyStateCheck(int step)
virtual SOLVER_UTILS_EXPORT void v_DoSolve()
Solves an unsteady problem.
virtual SOLVER_UTILS_EXPORT void v_GenerateSummary(SummaryList &l)
Virtual function for generating summary information.
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:198
bool m_explicitReaction
Indicates if explicit or implicit treatment of reaction is used.
virtual SOLVER_UTILS_EXPORT void v_NumFluxforVector(const Array< OneD, Array< OneD, NekDouble > > &ufield, Array< OneD, Array< OneD, Array< OneD, NekDouble > > > &qfield, Array< OneD, Array< OneD, NekDouble > > &qflux)
virtual SOLVER_UTILS_EXPORT bool v_PreIntegrate(int step)
A base class for describing how to solve specific equations.
bool m_homoInitialFwd
Flag to determine if simulation should start in homogeneous forward transformed state.
Adams-Bashforth Forward multi-step scheme of order 2.
NekDouble m_time
Current time of simulation.
bool m_explicitDiffusion
Indicates if explicit or implicit treatment of diffusion is used.
void Vsqrt(int n, const T *x, const int incx, T *y, const int incy)
sqrt y = sqrt(x)
Definition: Vmath.cpp:408
Runge-Kutta multi-stage scheme 4th order explicit (old name)
LibUtilities::TimeIntegrationSchemeOperators m_ode
The time integration scheme operators to use.
NekDouble m_timestep
Time step size.
std::vector< std::pair< std::string, std::string > > SummaryList
Definition: Misc.h:47
void WeakPenaltyforVector(const int var, const int dir, const Array< OneD, const NekDouble > &physfield, Array< OneD, NekDouble > &penaltyflux, NekDouble C11, NekDouble time=0.0)
Classical RungeKutta4 method (new name for eClassicalRungeKutta4)
SOLVER_UTILS_EXPORT void Checkpoint_Output(const int n)
Write checkpoint file of m_fields.
virtual SOLVER_UTILS_EXPORT void v_AppendOutput1D(Array< OneD, Array< OneD, NekDouble > > &solution1D)
Print the solution at each solution point in a txt file.
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:442
virtual SOLVER_UTILS_EXPORT NekDouble v_GetTimeStep(const Array< OneD, const Array< OneD, NekDouble > > &inarray)
Return the timestep to be used for the next step in the time-marching loop.
virtual SOLVER_UTILS_EXPORT bool v_RequireFwdTrans()
STL namespace.
NekDouble m_checktime
Time between checkpoints.
SOLVER_UTILS_EXPORT void CheckForRestartTime(NekDouble &time, int &nchk)
const char *const TimeIntegrationMethodMap[]
SOLVER_UTILS_EXPORT NekDouble MaxTimeStepEstimator()
Get the maximum timestep estimator for cfl control.
Nonlinear SSP RungeKutta3 explicit.
int m_nchk
Number of checkpoints written so far.
boost::shared_ptr< SessionReader > SessionReaderSharedPtr
Definition: MeshPartition.h:51
int m_checksteps
Number of steps between checkpoints.
NekDouble m_fintime
Finish time of the simulation.
virtual SOLVER_UTILS_EXPORT void v_InitObject()
Initialisation object for EquationSystem.
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...
int m_steps
Number of steps to take.
Array< OneD, Array< OneD, NekDouble > > m_traceNormals
Array holding trace normals for DG simulations in the forwards direction.
virtual SOLVER_UTILS_EXPORT void v_GenerateSummary(SummaryList &s)
Print a summary of time stepping parameters.
Classical RungeKutta2 method (new name for eMidpoint)
void Stop()
Definition: Timer.cpp:62
static const NekDouble kNekZeroTol
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:213
bool m_explicitAdvection
Indicates if explicit or implicit treatment of advection is used.
virtual SOLVER_UTILS_EXPORT ~UnsteadySystem()
Destructor.
virtual SOLVER_UTILS_EXPORT bool v_PostIntegrate(int step)
Adams-Bashforth Forward multi-step scheme of order 1.
std::map< StdRegions::VarCoeffType, Array< OneD, NekDouble > > VarCoeffMap
Definition: StdRegions.hpp:227
void AddSummaryItem(SummaryList &l, const std::string &name, const std::string &value)
Adds a summary item to the summary info list.
Definition: Misc.cpp:50
int Nnan(int n, const T *x, const int incx)
Return number of NaN elements of x.
Definition: Vmath.cpp:892
std::vector< std::pair< std::string, FilterParams > > FilterMap
Definition: SessionReader.h:66
Nonlinear SSP RungeKutta2 explicit (surrogate for eRungeKutta2_ImprovedEuler)
Improved RungeKutta2 explicit (old name meaning Heun's method)
int m_spacedim
Spatial dimension (>= expansion dim).
LibUtilities::FieldMetaDataMap m_fieldMetaDataMap
Map to identify relevant solver info to dump in output fields.
std::string PortablePath(const boost::filesystem::path &path)
create portable path on different platforms for boost::filesystem path
Definition: FileSystem.cpp:41
boost::shared_ptr< FieldIO > FieldIOSharedPtr
Definition: FieldIO.h:309
double NekDouble
TimeIntegrationWrapperFactory & GetTimeIntegrationWrapperFactory()
virtual SOLVER_UTILS_EXPORT void v_InitObject()
Init object for UnsteadySystem class.
SOLVER_UTILS_EXPORT NekDouble GetTimeStep()
NekDouble m_cflSafetyFactor
CFL safety factor (comprise between 0 to 1).
virtual SOLVER_UTILS_EXPORT void v_NumFluxforScalar(const Array< OneD, Array< OneD, NekDouble > > &ufield, Array< OneD, Array< OneD, Array< OneD, NekDouble > > > &uflux)
boost::shared_ptr< Equation > EquationSharedPtr
SOLVER_UTILS_EXPORT void SetBoundaryConditions(NekDouble time)
Evaluates the boundary conditions at the given time.
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:343
virtual SOLVER_UTILS_EXPORT void v_NumericalFlux(Array< OneD, Array< OneD, NekDouble > > &physfield, Array< OneD, Array< OneD, NekDouble > > &numflux)
SOLVER_UTILS_EXPORT int GetPhys_Offset(int n)
StandardMatrixTag boost::call_traits< LhsDataType >::const_reference rhs typedef NekMatrix< LhsDataType, StandardMatrixTag >::iterator iterator
static boost::shared_ptr< FieldIO > CreateForFile(const LibUtilities::SessionReaderSharedPtr session, const std::string &filename)
Construct a FieldIO object for a given input filename.
Definition: FieldIO.cpp:212
SOLVER_UTILS_EXPORT int GetNpoints()
Array< OneD, MultiRegions::ExpListSharedPtr > m_fields
Array holding all dependent variables.
LibUtilities::SessionReaderSharedPtr m_session
The session reader.
SOLVER_UTILS_EXPORT int GetTraceNpoints()
LibUtilities::TimeIntegrationWrapperSharedPtr m_intScheme
Wrapper to the time integration scheme.
int m_initialStep
Number of the step where the simulation should begin.
FilterFactory & GetFilterFactory()
Definition: Filter.cpp:42
std::vector< FilterSharedPtr > m_filters
int m_infosteps
Number of time steps between outputting status information.
SOLVER_UTILS_EXPORT void SetInitialConditions(NekDouble initialtime=0.0, bool dumpInitialConditions=true, const int domain=0)
Initialise the data in the dependent fields.
void Start()
Definition: Timer.cpp:51
void WeakPenaltyforScalar(const int var, const Array< OneD, const NekDouble > &physfield, Array< OneD, NekDouble > &penaltyflux, NekDouble time=0.0)
midpoint method (old name)
NekDouble TimePerTest(unsigned int n)
Returns amount of seconds per iteration in a test with n iterations.
Definition: Timer.cpp:108
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1061
static FieldMetaDataMap NullFieldMetaDataMap
Definition: FieldIO.h:55
LibUtilities::TimeIntegrationSolutionSharedPtr m_intSoln
virtual SOLVER_UTILS_EXPORT void v_DoInitialise()
Sets up initial conditions.
enum HomogeneousType m_HomogeneousType
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:299
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:183