Nektar++
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 // 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: Generic timestepping for Unsteady solvers
32 //
33 ///////////////////////////////////////////////////////////////////////////////
34 
35 #include <iostream>
36 #include <iomanip>
37 using namespace std;
38 
39 #include <boost/core/ignore_unused.hpp>
40 #include <boost/format.hpp>
41 
46 
47 namespace Nektar
48 {
49  namespace SolverUtils
50  {
51  /**
52  * @class UnsteadySystem
53  *
54  * Provides the underlying timestepping framework for unsteady solvers
55  * including the general timestepping routines. This class is not
56  * intended to be directly instantiated, but rather is a base class
57  * on which to define unsteady solvers.
58  *
59  * For details on implementing unsteady solvers see
60  * \ref sectionADRSolverModuleImplementation here
61  */
62 
63  /**
64  * Processes SolverInfo parameters from the session file and sets up
65  * timestepping-specific code.
66  * @param pSession Session object to read parameters from.
67  */
68  UnsteadySystem::UnsteadySystem(
71  : EquationSystem(pSession, pGraph),
72  m_infosteps(10)
73 
74  {
75  }
76 
77  /**
78  * Initialization object for UnsteadySystem class.
79  */
81  {
83 
84  m_initialStep = 0;
85 
86  // Load SolverInfo parameters
87  m_session->MatchSolverInfo("DIFFUSIONADVANCEMENT","Explicit",
88  m_explicitDiffusion,true);
89  m_session->MatchSolverInfo("ADVECTIONADVANCEMENT","Explicit",
90  m_explicitAdvection,true);
91  m_session->MatchSolverInfo("REACTIONADVANCEMENT", "Explicit",
92  m_explicitReaction, true);
93 
94  m_session->LoadParameter("CheckAbortSteps", m_abortSteps, 1);
95  // Steady state tolerance
96  m_session->LoadParameter("SteadyStateTol", m_steadyStateTol, 0.0);
97  // Frequency for checking steady state
98  m_session->LoadParameter("SteadyStateSteps",
100 
101  // For steady problems, we do not initialise the time integration
102  if (m_session->DefinesSolverInfo("TIMEINTEGRATIONMETHOD"))
103  {
105  CreateInstance(m_session->GetSolverInfo(
106  "TIMEINTEGRATIONMETHOD"));
107 
108  // Load generic input parameters
109  m_session->LoadParameter("IO_InfoSteps", m_infosteps, 0);
110  m_session->LoadParameter("IO_FiltersInfoSteps",
112  m_session->LoadParameter("CFL", m_cflSafetyFactor, 0.0);
113 
114  // Time tolerance between filter update time and time integration
115  m_session->LoadParameter("FilterTimeWarning", m_filterTimeWarning, 1);
116 
117  // Ensure that there is no conflict of parameters
118  if(m_cflSafetyFactor > 0.0)
119  {
120  // Check final condition
121  ASSERTL0(m_fintime == 0.0 || m_steps == 0,
122  "Final condition not unique: "
123  "fintime > 0.0 and Nsteps > 0");
124  // Check timestep condition
125  ASSERTL0(m_timestep == 0.0,
126  "Timestep not unique: timestep > 0.0 & CFL > 0.0");
127  }
128  else
129  {
130  ASSERTL0(m_timestep != 0.0,
131  "Need to set either TimeStep or CFL");
132  }
133 
134  // Set up time to be dumped in field information
135  m_fieldMetaDataMap["Time"] =
136  boost::lexical_cast<std::string>(m_time);
137  }
138 
139  // By default attempt to forward transform initial condition.
140  m_homoInitialFwd = true;
141 
142  // Set up filters
143  for (auto &x : m_session->GetFilters())
144  {
145  m_filters.push_back(make_pair(x.first, GetFilterFactory().CreateInstance(
146  x.first, m_session, shared_from_this(), x.second)));
147  }
148  }
149 
150  /**
151  * Destructor for the class UnsteadyAdvection.
152  */
154  {
155  }
156 
157  /**
158  * @brief Returns the maximum time estimator for CFL control.
159  */
161  {
162  NekDouble TimeStability = 0.0;
163  switch(m_intScheme->GetIntegrationMethod())
164  {
168  {
169  TimeStability = 2.784;
170  break;
171  }
178  {
179  TimeStability = 2.0;
180  break;
181  }
183  {
184  TimeStability = 1.0;
185  break;
186  }
187  default:
188  {
189  ASSERTL0(
190  false,
191  "No CFL control implementation for this time"
192  "integration scheme");
193  }
194  }
195  return TimeStability;
196  }
197 
198  /**
199  * @brief Initialises the time integration scheme (as specified in the
200  * session file), and perform the time integration.
201  */
203  {
204  ASSERTL0(m_intScheme != 0, "No time integration scheme.");
205 
206  int i = 1;
207  int nvariables = 0;
208  int nfields = m_fields.num_elements();
209 
210  if (m_intVariables.empty())
211  {
212  for (i = 0; i < nfields; ++i)
213  {
214  m_intVariables.push_back(i);
215  }
216  nvariables = nfields;
217  }
218  else
219  {
220  nvariables = m_intVariables.size();
221  }
222 
223  // Integrate in wave-space if using homogeneous1D
225  {
226  for(i = 0; i < nfields; ++i)
227  {
228  m_fields[i]->HomogeneousFwdTrans(m_fields[i]->GetPhys(),
229  m_fields[i]->UpdatePhys());
230  m_fields[i]->SetWaveSpace(true);
231  m_fields[i]->SetPhysState(false);
232  }
233  }
234 
235  // Set up wrapper to fields data storage.
236  Array<OneD, Array<OneD, NekDouble> > fields(nvariables);
237 
238  // Order storage to list time-integrated fields first.
239  for(i = 0; i < nvariables; ++i)
240  {
241  fields[i] = m_fields[m_intVariables[i]]->GetPhys();
242  m_fields[m_intVariables[i]]->SetPhysState(false);
243  }
244 
245  // Initialise time integration scheme
246  m_intSoln = m_intScheme->InitializeScheme(
247  m_timestep, fields, m_time, m_ode);
248 
249  // Initialise filters
250  for (auto &x : m_filters)
251  {
252  x.second->Initialise(m_fields, m_time);
253  }
254 
255  LibUtilities::Timer timer;
256  bool doCheckTime = false;
257  int step = m_initialStep;
258  int stepCounter = 0;
259  NekDouble intTime = 0.0;
260  NekDouble lastCheckTime = 0.0;
261  NekDouble cpuTime = 0.0;
262  NekDouble cpuPrevious = 0.0;
263  NekDouble elapsed = 0.0;
264  NekDouble totFilterTime = 0.0;
265 
266  Array<OneD, int> abortFlags(2, 0);
267  string abortFile = "abort";
268  if (m_session->DefinesSolverInfo("CheckAbortFile"))
269  {
270  abortFile = m_session->GetSolverInfo("CheckAbortFile");
271  }
272 
273  while ((step < m_steps ||
275  abortFlags[1] == 0)
276  {
277  if (m_cflSafetyFactor)
278  {
279  m_timestep = GetTimeStep(fields);
280 
281  // Ensure that the final timestep finishes at the final
282  // time, or at a prescribed IO_CheckTime.
283  if (m_time + m_timestep > m_fintime && m_fintime > 0.0)
284  {
286  }
287  else if (m_checktime &&
288  m_time + m_timestep - lastCheckTime >= m_checktime)
289  {
290  lastCheckTime += m_checktime;
291  m_timestep = lastCheckTime - m_time;
292  doCheckTime = true;
293  }
294  }
295 
296  // Perform any solver-specific pre-integration steps
297  timer.Start();
298  if (v_PreIntegrate(step))
299  {
300  break;
301  }
302 
303  fields = m_intScheme->TimeIntegrate(
304  stepCounter, m_timestep, m_intSoln, m_ode);
305  timer.Stop();
306 
307  m_time += m_timestep;
308  elapsed = timer.TimePerTest(1);
309  intTime += elapsed;
310  cpuTime += elapsed;
311 
312  // Write out status information
313  if (m_session->GetComm()->GetRank() == 0 &&
314  !((step+1) % m_infosteps))
315  {
316  cout << "Steps: " << setw(8) << left << step+1 << " "
317  << "Time: " << setw(12) << left << m_time;
318 
319  if (m_cflSafetyFactor)
320  {
321  cout << " Time-step: " << setw(12)
322  << left << m_timestep;
323  }
324 
325  stringstream ss;
326  ss << cpuTime << "s";
327  cout << " CPU Time: " << setw(8) << left
328  << ss.str() << endl;
329  cpuPrevious = cpuTime;
330  cpuTime = 0.0;
331  }
332 
333  // Transform data into coefficient space
334  for (i = 0; i < nvariables; ++i)
335  {
336  // copy fields into ExpList::m_phys and assign the new
337  // array to fields
338  m_fields[m_intVariables[i]]->SetPhys(fields[i]);
339  fields[i] = m_fields[m_intVariables[i]]->UpdatePhys();
340  if( v_RequireFwdTrans() )
341  {
342  m_fields[m_intVariables[i]]->FwdTrans_IterPerExp(
343  fields[i],
344  m_fields[m_intVariables[i]]->UpdateCoeffs());
345  }
346  m_fields[m_intVariables[i]]->SetPhysState(false);
347  }
348 
349  // Perform any solver-specific post-integration steps
350  if (v_PostIntegrate(step))
351  {
352  break;
353  }
354 
355  // Check for steady-state
356  if (m_steadyStateTol > 0.0 && (!((step+1)%m_steadyStateSteps)) )
357  {
358  if (CheckSteadyState(step))
359  {
360  if (m_comm->GetRank() == 0)
361  {
362  cout << "Reached Steady State to tolerance "
363  << m_steadyStateTol << endl;
364  }
365  break;
366  }
367  }
368 
369  // test for abort conditions (nan, or abort file)
370  if (m_abortSteps && !((step+1) % m_abortSteps) )
371  {
372  abortFlags[0] = 0;
373  for (i = 0; i < nvariables; ++i)
374  {
375  if (Vmath::Nnan(fields[i].num_elements(),
376  fields[i], 1) > 0)
377  {
378  abortFlags[0] = 1;
379  }
380  }
381 
382  //rank zero looks for abort file and deltes it
383  //if it exists. The communicates the abort
384  if(m_session->GetComm()->GetRank() == 0)
385  {
386  if(boost::filesystem::exists(abortFile))
387  {
388  boost::filesystem::remove(abortFile);
389  abortFlags[1] = 1;
390  }
391  }
392 
393  m_session->GetComm()->AllReduce(abortFlags,
395 
396  ASSERTL0 (!abortFlags[0],
397  "NaN found during time integration.");
398  }
399 
400  // Update filters
401  for (auto &x : m_filters)
402  {
403  timer.Start();
404  x.second->Update(m_fields, m_time);
405  timer.Stop();
406  elapsed = timer.TimePerTest(1);
407  totFilterTime += elapsed;
408 
409  // Write out individual filter status information
410  if(m_session->GetComm()->GetRank() == 0 &&
411  !((step+1) % m_filtersInfosteps) && !m_filters.empty() &&
412  m_session->DefinesCmdLineArgument("verbose"))
413  {
414  stringstream s0;
415  s0 << x.first << ":";
416  stringstream s1;
417  s1 << elapsed << "s";
418  stringstream s2;
419  s2 << elapsed / cpuPrevious * 100 << "%";
420  cout << "CPU time for filter " << setw(25) << left
421  << s0.str() << setw(12) << left << s1.str() <<
422  endl << "\t Percentage of time integration: "
423  << setw(10) << left << s2.str() << endl;
424  }
425  }
426 
427  // Write out overall filter status information
428  if (m_session->GetComm()->GetRank() == 0 &&
429  !((step+1) % m_filtersInfosteps) && !m_filters.empty())
430  {
431  stringstream ss;
432  ss << totFilterTime << "s";
433  cout << "Total filters CPU Time:\t\t\t " << setw(10)
434  << left << ss.str() << endl;
435  }
436  totFilterTime = 0.0;
437 
438  // Write out checkpoint files
439  if ((m_checksteps && !((step + 1) % m_checksteps)) ||
440  doCheckTime)
441  {
443  {
444  vector<bool> transformed(nfields, false);
445  for(i = 0; i < nfields; i++)
446  {
447  if (m_fields[i]->GetWaveSpace())
448  {
449  m_fields[i]->SetWaveSpace(false);
450  m_fields[i]->BwdTrans(m_fields[i]->GetCoeffs(),
451  m_fields[i]->UpdatePhys());
452  m_fields[i]->SetPhysState(true);
453  transformed[i] = true;
454  }
455  }
457  m_nchk++;
458  for(i = 0; i < nfields; i++)
459  {
460  if (transformed[i])
461  {
462  m_fields[i]->SetWaveSpace(true);
463  m_fields[i]->HomogeneousFwdTrans(
464  m_fields[i]->GetPhys(),
465  m_fields[i]->UpdatePhys());
466  m_fields[i]->SetPhysState(false);
467  }
468  }
469  }
470  else
471  {
473  m_nchk++;
474  }
475  doCheckTime = false;
476  }
477 
478  // Step advance
479  ++step;
480  ++stepCounter;
481  }
482 
483  // Print out summary statistics
484  if (m_session->GetComm()->GetRank() == 0)
485  {
486  if (m_cflSafetyFactor > 0.0)
487  {
488  cout << "CFL safety factor : " << m_cflSafetyFactor << endl
489  << "CFL time-step : " << m_timestep << endl;
490  }
491 
492  if (m_session->GetSolverInfo("Driver") != "SteadyState")
493  {
494  cout << "Time-integration : " << intTime << "s" << endl;
495  }
496  }
497 
498  // If homogeneous, transform back into physical space if necessary.
500  {
501  for(i = 0; i < nfields; i++)
502  {
503  if (m_fields[i]->GetWaveSpace())
504  {
505  m_fields[i]->SetWaveSpace(false);
506  m_fields[i]->BwdTrans(m_fields[i]->GetCoeffs(),
507  m_fields[i]->UpdatePhys());
508  m_fields[i]->SetPhysState(true);
509  }
510  }
511  }
512  else
513  {
514  for(i = 0; i < nvariables; ++i)
515  {
516  m_fields[m_intVariables[i]]->SetPhys(fields[i]);
517  m_fields[m_intVariables[i]]->SetPhysState(true);
518  }
519  }
520 
521  // Finalise filters
522  for (auto &x : m_filters)
523  {
524  x.second->Finalise(m_fields, m_time);
525  }
526 
527  // Print for 1D problems
528  if(m_spacedim == 1)
529  {
530  v_AppendOutput1D(fields);
531  }
532  }
533 
534  /**
535  * @brief Sets the initial conditions.
536  */
538  {
543  }
544 
545  /**
546  * @brief Prints a summary with some information regards the
547  * time-stepping.
548  */
550  {
552  AddSummaryItem(s, "Advection",
553  m_explicitAdvection ? "explicit" : "implicit");
554 
555  if(m_session->DefinesSolverInfo("AdvectionType"))
556  {
557  AddSummaryItem(s, "AdvectionType",
558  m_session->GetSolverInfo("AdvectionType"));
559  }
560 
561  AddSummaryItem(s, "Diffusion",
562  m_explicitDiffusion ? "explicit" : "implicit");
563 
564  if (m_session->GetSolverInfo("EQTYPE")
565  == "SteadyAdvectionDiffusionReaction")
566  {
567  AddSummaryItem(s, "Reaction",
568  m_explicitReaction ? "explicit" : "implicit");
569  }
570 
571  AddSummaryItem(s, "Time Step", m_timestep);
572  AddSummaryItem(s, "No. of Steps", m_steps);
573  AddSummaryItem(s, "Checkpoints (steps)", m_checksteps);
574  AddSummaryItem(s, "Integration Type",
576  m_intScheme->GetIntegrationMethod()]);
577  }
578 
579  /**
580  * Stores the solution in a file for 1D problems only. This method has
581  * been implemented to facilitate the post-processing for 1D problems.
582  */
584  Array<OneD, Array<OneD, NekDouble> > &solution1D)
585  {
586  // Coordinates of the quadrature points in the real physical space
590  m_fields[0]->GetCoords(x, y, z);
591 
592  // Print out the solution in a txt file
593  ofstream outfile;
594  outfile.open("solution1D.txt");
595  for(int i = 0; i < GetNpoints(); i++)
596  {
597  outfile << scientific << setw (17) << setprecision(16) << x[i]
598  << " " << solution1D[0][i] << endl;
599  }
600  outfile << endl << endl;
601  outfile.close();
602  }
603 
605  {
606  if (m_session->DefinesFunction("InitialConditions"))
607  {
608  for (int i = 0; i < m_fields.num_elements(); ++i)
609  {
611 
612  vType = m_session->GetFunctionType(
613  "InitialConditions", m_session->GetVariable(i));
614 
615  if (vType == LibUtilities::eFunctionTypeFile)
616  {
617  std::string filename
618  = m_session->GetFunctionFilename(
619  "InitialConditions", m_session->GetVariable(i));
620 
621  fs::path pfilename(filename);
622 
623  // redefine path for parallel file which is in directory
624  if(fs::is_directory(pfilename))
625  {
626  fs::path metafile("Info.xml");
627  fs::path fullpath = pfilename / metafile;
628  filename = LibUtilities::PortablePath(fullpath);
629  }
632  m_session, filename);
633  fld->ImportFieldMetaData(filename, m_fieldMetaDataMap);
634 
635  // check to see if time defined
636  if (m_fieldMetaDataMap !=
638  {
639  auto iter = m_fieldMetaDataMap.find("Time");
640  if (iter != m_fieldMetaDataMap.end())
641  {
642  time = boost::lexical_cast<NekDouble>(
643  iter->second);
644  }
645 
646  iter = m_fieldMetaDataMap.find("ChkFileNum");
647  if (iter != m_fieldMetaDataMap.end())
648  {
649  nchk = boost::lexical_cast<NekDouble>(
650  iter->second);
651  }
652  }
653 
654  break;
655  }
656  }
657  }
658  }
659 
660  /**
661  * @brief Return the timestep to be used for the next step in the
662  * time-marching loop.
663  *
664  * This function can be overloaded to facilitate solver which utilise a
665  * CFL (or other) parameter to determine a maximum timestep under which
666  * the problem remains stable.
667  */
669  const Array<OneD, const Array<OneD, NekDouble> > &inarray)
670  {
671  return v_GetTimeStep(inarray);
672  }
673 
674  /**
675  * @brief Return the timestep to be used for the next step in the
676  * time-marching loop.
677  *
678  * @see UnsteadySystem::GetTimeStep
679  */
681  const Array<OneD, const Array<OneD, NekDouble> > &inarray)
682  {
683  boost::ignore_unused(inarray);
684  NEKERROR(ErrorUtil::efatal, "Not defined for this class");
685  return 0.0;
686  }
687 
689  {
690  boost::ignore_unused(step);
691  return false;
692  }
693 
695  {
696  boost::ignore_unused(step);
697  return false;
698  }
699 
701  const Array<OneD, Array<OneD, NekDouble> > vel,
702  StdRegions::VarCoeffMap &varCoeffMap)
703  {
704  int phystot = m_fields[0]->GetTotPoints();
705  int nvel = vel.num_elements();
706 
707  Array<OneD, NekDouble> varcoeff(phystot),tmp;
708 
709  // calculate magnitude of v
710  Vmath::Vmul(phystot,vel[0],1,vel[0],1,varcoeff,1);
711  for(int n = 1; n < nvel; ++n)
712  {
713  Vmath::Vvtvp(phystot,vel[n],1,vel[n],1,varcoeff,1,varcoeff,1);
714  }
715  Vmath::Vsqrt(phystot,varcoeff,1,varcoeff,1);
716 
717  for(int i = 0; i < m_fields[0]->GetNumElmts(); ++i)
718  {
719  int offset = m_fields[0]->GetPhys_Offset(i);
720  int nq = m_fields[0]->GetExp(i)->GetTotPoints();
721  Array<OneD, NekDouble> unit(nq,1.0);
722 
723  int nmodes = 0;
724 
725  for(int n = 0; n < m_fields[0]->GetExp(i)->GetNumBases(); ++n)
726  {
727  nmodes = max(nmodes,
728  m_fields[0]->GetExp(i)->GetBasisNumModes(n));
729  }
730 
731  NekDouble h = m_fields[0]->GetExp(i)->Integral(unit);
732  h = pow(h,(NekDouble) (1.0/nvel))/((NekDouble) nmodes);
733 
734  Vmath::Smul(nq,h,varcoeff+offset,1,tmp = varcoeff+offset,1);
735  }
736 
737  // set up map with eVarCoffLaplacian key
738  varCoeffMap[StdRegions::eVarCoeffLaplacian] = varcoeff;
739  }
740 
742  {
743  if (m_steadyStateTol > 0.0)
744  {
745  const int nPoints = m_fields[0]->GetTotPoints();
747  m_fields.num_elements());
748 
749  for (int i = 0; i < m_fields.num_elements(); ++i)
750  {
752  Vmath::Vcopy(nPoints, m_fields[i]->GetPhys(), 1,
753  m_previousSolution[i], 1);
754  }
755 
756  if (m_comm->GetRank() == 0)
757  {
758  std::string fName = m_session->GetSessionName() +
759  std::string(".res");
760  m_errFile.open(fName.c_str());
761  m_errFile << setw(26) << left << "# Time";
762 
763  for (int i = 0; i < m_fields.num_elements(); ++i)
764  {
765  m_errFile << setw(26) << m_session->GetVariables()[i];
766  }
767 
768  m_errFile << endl;
769  }
770  }
771  }
772 
773  /**
774  * @brief Calculate whether the system has reached a steady state by
775  * observing residuals to a user-defined tolerance.
776  */
778  {
779  const int nPoints = GetTotPoints();
780  const int nFields = m_fields.num_elements();
781 
782  // Holds L2 errors.
783  Array<OneD, NekDouble> L2 (nFields);
784  Array<OneD, NekDouble> residual (nFields);
785  Array<OneD, NekDouble> reference(nFields);
786 
787  for (int i = 0; i < nFields; ++i)
788  {
789  Array<OneD, NekDouble> tmp(nPoints);
790 
791  Vmath::Vsub(nPoints, m_fields[i]->GetPhys(), 1,
792  m_previousSolution[i], 1, tmp, 1);
793  Vmath::Vmul(nPoints, tmp, 1, tmp, 1, tmp, 1);
794  residual[i] = Vmath::Vsum(nPoints, tmp, 1);
795 
796  Vmath::Vmul(nPoints, m_previousSolution[i], 1,
797  m_previousSolution[i], 1, tmp, 1);
798  reference[i] = Vmath::Vsum(nPoints, tmp, 1);
799  }
800 
801  m_comm->AllReduce(residual , LibUtilities::ReduceSum);
802  m_comm->AllReduce(reference, LibUtilities::ReduceSum);
803 
804  // L2 error
805  for (int i = 0; i < nFields; ++i)
806  {
807  reference[i] = (reference[i] == 0) ? 1 : reference[i];
808  L2[i] = sqrt(residual[i] / reference[i]);
809  }
810 
811  if (m_comm->GetRank() == 0 && ((step+1) % m_infosteps == 0))
812  {
813  // Output time
814  m_errFile << boost::format("%25.19e") % m_time;
815 
816  // Output residuals
817  for (int i = 0; i < nFields; ++i)
818  {
819  m_errFile << " " << boost::format("%25.19e") % L2[i];
820  }
821 
822  m_errFile << endl;
823  }
824 
825  // Calculate maximum L2 error
826  NekDouble maxL2 = Vmath::Vmax(nFields, L2, 1);
827 
828  if (m_session->DefinesCmdLineArgument("verbose") &&
829  m_comm->GetRank() == 0 && ((step+1) % m_infosteps == 0))
830  {
831  cout << "-- Maximum L^2 residual: " << maxL2 << endl;
832  }
833 
834  if (maxL2 <= m_steadyStateTol)
835  {
836  return true;
837  }
838 
839  for (int i = 0; i < m_fields.num_elements(); ++i)
840  {
841  Vmath::Vcopy(nPoints, m_fields[i]->GetPhys(), 1,
842  m_previousSolution[i], 1);
843  }
844 
845  return false;
846  }
847  }
848 }
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.
NekDouble m_filterTimeWarning
Number of time steps between outputting status information.
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
bool m_explicitReaction
Indicates if explicit or implicit treatment of reaction is used.
std::shared_ptr< MeshGraph > MeshGraphSharedPtr
Definition: MeshGraph.h:163
virtual SOLVER_UTILS_EXPORT bool v_PreIntegrate(int step)
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mod...
Definition: ErrorUtil.hpp:209
Array< OneD, Array< OneD, NekDouble > > m_previousSolution
Storage for previous solution for steady-state check.
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.
int m_abortSteps
Number of steps between checks for abort conditions.
void Vsqrt(int n, const T *x, const int incx, T *y, const int incy)
sqrt y = sqrt(x)
Definition: Vmath.cpp:411
Runge-Kutta multi-stage scheme 4th order explicit (old name)
T Vmax(int n, const T *x, const int incx)
Return the maximum element in x – called vmax to avoid conflict with max.
Definition: Vmath.cpp:782
LibUtilities::TimeIntegrationSchemeOperators m_ode
The time integration scheme operators to use.
NekDouble m_timestep
Time step size.
NekDouble TimePerTest(unsigned int n)
Returns amount of seconds per iteration in a test with n iterations.
Definition: Timer.cpp:57
std::vector< std::pair< std::string, std::string > > SummaryList
Definition: Misc.h:46
Classical RungeKutta4 method (new name for eClassicalRungeKutta4)
std::vector< std::pair< std::string, FilterSharedPtr > > m_filters
SOLVER_UTILS_EXPORT void Checkpoint_Output(const int n)
Write checkpoint file of m_fields.
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 SOLVER_UTILS_EXPORT void v_AppendOutput1D(Array< OneD, Array< OneD, NekDouble >> &solution1D)
Print the solution at each solution point in a txt file.
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.
int m_checksteps
Number of steps between checkpoints.
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.
NekDouble m_steadyStateTol
Tolerance to which steady state should be evaluated at.
LibUtilities::CommSharedPtr m_comm
Communicator.
SOLVER_UTILS_EXPORT int GetTotPoints()
NekDouble m_fintime
Finish time of the simulation.
virtual SOLVER_UTILS_EXPORT void v_InitObject()
Initialisation object for EquationSystem.
int m_steps
Number of steps to take.
virtual SOLVER_UTILS_EXPORT void v_GenerateSummary(SummaryList &s)
Print a summary of time stepping parameters.
Classical RungeKutta2 method (new name for eMidpoint)
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:216
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:264
void AddSummaryItem(SummaryList &l, const std::string &name, const std::string &value)
Adds a summary item to the summary info list.
Definition: Misc.cpp:49
int Nnan(int n, const T *x, const int incx)
Return number of NaN elements of x.
Definition: Vmath.cpp:895
Nonlinear SSP RungeKutta2 explicit (surrogate for eRungeKutta2_ImprovedEuler)
Improved RungeKutta2 explicit (old name meaning Heun&#39;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
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).
int m_filtersInfosteps
Number of time steps between outputting filters information.
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:346
int m_steadyStateSteps
Check for steady state at step interval.
static std::shared_ptr< FieldIO > CreateForFile(const LibUtilities::SessionReaderSharedPtr session, const std::string &filename)
Construct a FieldIO object for a given input filename.
Definition: FieldIO.cpp:226
SOLVER_UTILS_EXPORT int GetNpoints()
Array< OneD, MultiRegions::ExpListSharedPtr > m_fields
Array holding all dependent variables.
LibUtilities::SessionReaderSharedPtr m_session
The session reader.
LibUtilities::TimeIntegrationWrapperSharedPtr m_intScheme
Wrapper to the time integration scheme.
int m_initialStep
Number of the step where the simulation should begin.
bool CheckSteadyState(int step)
Calculate whether the system has reached a steady state by observing residuals to a user-defined tole...
FilterFactory & GetFilterFactory()
Definition: Filter.cpp:41
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.
SOLVER_UTILS_EXPORT void SVVVarDiffCoeff(const Array< OneD, Array< OneD, NekDouble >> vel, StdRegions::VarCoeffMap &varCoeffMap)
Evaluate the SVV diffusion coefficient according to Moura&#39;s paper where it should proportional to h t...
midpoint method (old name)
T Vsum(int n, const T *x, const int incx)
Subtract return sum(x)
Definition: Vmath.cpp:740
std::shared_ptr< FieldIO > FieldIOSharedPtr
Definition: FieldIO.h:306
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1064
static FieldMetaDataMap NullFieldMetaDataMap
Definition: FieldIO.h:53
LibUtilities::TimeIntegrationSolutionSharedPtr m_intSoln
std::shared_ptr< SessionReader > SessionReaderSharedPtr
virtual SOLVER_UTILS_EXPORT void v_DoInitialise()
Sets up initial conditions.
enum HomogeneousType m_HomogeneousType
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