Nektar++
DriverSteadyState.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File: DriverSteadyState.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: Driver class for the steady-state solver
32 //
33 ///////////////////////////////////////////////////////////////////////////////
34 
37 
38 #include <boost/algorithm/string/classification.hpp>
39 #include <boost/algorithm/string/predicate.hpp>
40 #include <boost/algorithm/string/split.hpp>
41 
42 using namespace std;
43 
44 namespace Nektar
45 {
46 namespace SolverUtils
47 {
48 
49 string DriverSteadyState::className =
51  DriverSteadyState::create);
52 string DriverSteadyState::driverLookupId =
53  LibUtilities::SessionReader::RegisterEnumValue("Driver", "SteadyState", 0);
54 
55 /**
56  *
57  */
58 DriverSteadyState::DriverSteadyState(
61  : DriverModifiedArnoldi(pSession, pGraph)
62 {
63 }
64 
65 /**
66  *
67  */
69 {
70 }
71 
72 /**
73  *
74  */
76 {
78 }
79 
80 void DriverSteadyState::v_Execute(ostream &out)
81 
82 {
83  // With a loop over "DoSolve", this Driver implements the
84  // "encapsulated" Selective Frequency Damping method(SFD)
85  // to find the steady state of a flow above the critical Reynolds
86  // number.
87  m_equ[m_nequ - 1]->PrintSummary(out);
88 
89  m_session->LoadParameter("IO_InfoSteps", m_infosteps, 1000);
90  m_session->LoadParameter("IO_CheckSteps", m_checksteps, 100000);
91  m_session->LoadParameter("ControlCoeff", m_X, 1);
92  m_session->LoadParameter("FilterWidth", m_Delta, 2);
93 
94  // To evaluate optimum SFD parameters if growth rate provided in the
95  // xml file
96  m_session->LoadParameter("GrowthRateEV", GrowthRateEV, 0.0);
97 
98  // To evaluate optimum SFD parameters if frequency provided in the xml
99  // file
100  m_session->LoadParameter("FrequencyEV", FrequencyEV, 0.0);
101 
102  // Determine when SFD method is converged
103  m_session->LoadParameter("TOL", TOL, 1.0e-08);
104 
105  // Used only for the Adaptive SFD method
106  m_session->LoadParameter("AdaptiveTOL", AdaptiveTOL, 1.0e-02);
107 
108  // Used only for the Adaptive SFD method
109  m_session->LoadParameter("AdaptiveTime", AdaptiveTime, 50.0 * m_Delta);
110 
111  if (m_comm->GetRank() == 0)
112  {
113  PrintSummarySFD();
114  }
115 
116  timer.Start();
117 
118  // Definition of shared pointer (used only for the Adaptive SFD method)
120 
121  NumVar_SFD = m_equ[m_nequ - 1]->UpdateFields()[0]->GetCoordim(0);
122  // SFD to run for incompressible case with scalar field
123  if (m_session->GetSolverInfo("EqType") == "UnsteadyNavierStokes" ||
124  m_session->GetSolverInfo("EqType") == "SteadyNavierStokes")
125  {
126  int nConvectiveFields = m_session->GetVariables().size();
127  if (boost::iequals(m_session->GetVariable(nConvectiveFields - 1), "p"))
128  {
129  nConvectiveFields -= 1;
130  }
131  NumVar_SFD = nConvectiveFields;
132  }
133  // Condition necessary to run SFD for the compressible case
134  if (m_session->GetSolverInfo("EqType") == "EulerCFE" ||
135  m_session->GetSolverInfo("EqType") == "NavierStokesCFE" ||
136  m_session->GetSolverInfo("EqType") == "NavierStokesImplicitCFE")
137  {
138  // Number of variables for the compressible equations
139  NumVar_SFD += 2;
140  }
141  if (m_session->DefinesSolverInfo("HOMOGENEOUS"))
142  {
143  if (m_session->GetSolverInfo("HOMOGENEOUS") == "1D")
144  {
145  NumVar_SFD += 1;
146  }
147  }
148 
149  // We store the time step
150  m_dt = m_equ[m_nequ - 1]->GetTimeStep();
151 
152  // Evaluate optimum SFD parameters if dominent EV given by xml file
153  if (GrowthRateEV != 0.0 && FrequencyEV != 0.0)
154  {
155  cout << "Besed on the dominant EV given in the xml file,"
156  << "a 1D model is used to evaluate the optumum parameters"
157  << "of the SFD method:" << endl;
158  complex<NekDouble> EV = polar(exp(GrowthRateEV), FrequencyEV);
160  }
161 
162  // We set up the elements of the operator of the encapsulated
163  // formulation of the selective frequencive damping method
165 
166  // m_steps is set to 1. Then "m_equ[m_nequ - 1]->DoSolve()" will run
167  // for only one time step
168  m_equ[m_nequ - 1]->SetSteps(1);
169  ofstream m_file("ConvergenceHistory.txt", ios::out | ios::trunc);
170 
175 
176  for (int i = 0; i < NumVar_SFD; ++i)
177  {
178  q0[i] = Array<OneD, NekDouble>(m_equ[m_nequ - 1]->GetTotPoints(),
179  0.0); // q0 is initialised
180  qBar0[i] =
181  Array<OneD, NekDouble>(m_equ[m_nequ - 1]->GetTotPoints(), 0.0);
182  m_equ[m_nequ - 1]->CopyFromPhysField(i, qBar0[i]);
183  }
184 
185  /// Definition of variables used in this algorithm
186  m_stepCounter = 0;
187  m_Check = 0;
188  m_Check_BaseFlow = 1;
190  Diff_q_qBar = 1.0;
191  Diff_q1_q0 = 1.0;
192  cpuTime = 0.0;
193  elapsed = 0.0;
194  totalTime = 0.0;
195  FlowPartiallyConverged = false;
196 
197  while (max(Diff_q_qBar, Diff_q1_q0) > TOL)
198  {
199  /// Call the Navier-Stokes solver for one time step
200  m_equ[m_nequ - 1]->DoSolve();
201 
202  for (int i = 0; i < NumVar_SFD; ++i)
203  {
204  /// Copy the current flow field into q0
205  m_equ[m_nequ - 1]->CopyFromPhysField(i, q0[i]);
206 
207  /// Apply the linear operator to the outcome of the solver
208  ComputeSFD(i, q0, qBar0, q1, qBar1);
209 
210  /// Update qBar
211  qBar0[i] = qBar1[i];
212 
213  /// Copy the output of the SFD method into the current flow field
214  m_equ[m_nequ - 1]->CopyToPhysField(i, q1[i]);
215  }
216 
217  if (m_infosteps && !((m_stepCounter + 1) % m_infosteps))
218  {
220 
221  /// Loop for the adaptive SFD method
223  FlowPartiallyConverged == false)
224  {
225 
227 
228  if (Diff_q_qBar < AdaptiveTOL)
229  {
230  if (m_comm->GetRank() == 0)
231  {
232  cout << "\n\t The SFD method is converging: we compute "
233  << "stability analysis using the 'partially "
234  << "converged' steady state as base flow:\n"
235  << endl;
236  }
237 
238  m_equ[m_nequ - 1]->Checkpoint_BaseFlow(m_Check_BaseFlow);
240 
241  A->GetAdvObject()->SetBaseFlow(q0,
242  m_equ[0]->UpdateFields());
244 
245  if (m_comm->GetRank() == 0)
246  {
247  // Compute the update of the SFD parameters only on
248  // one processor
250  }
251  else
252  {
253  // On all the other processors, the parameters are set
254  // to 0
255  m_X = 0;
256  m_Delta = 0;
257  }
258  // The we give to all the processors the value of X and
259  // Delta of the first processor
262 
263  FlowPartiallyConverged = true;
264  }
266  AdaptiveTime)
267  {
268  if (m_comm->GetRank() == 0)
269  {
270  cout << "\n\t We compute stability analysis using"
271  << " the current flow field as base flow:\n"
272  << endl;
273  }
274 
275  m_equ[m_nequ - 1]->Checkpoint_BaseFlow(m_Check_BaseFlow);
277 
278  A->GetAdvObject()->SetBaseFlow(q0,
279  m_equ[0]->UpdateFields());
281 
282  if (m_comm->GetRank() == 0)
283  {
284  // Compute the update of the SFD parameters only on
285  // one processor
287  }
288  else
289  {
290  // On all the other processors, the parameters are set
291  // to 0
292  m_X = 0;
293  m_Delta = 0;
294  }
295  // The we give to all the processors the value of X and
296  // Delta of the first processor
299 
301  }
302  }
303  }
304 
305  if (m_checksteps && m_stepCounter &&
306  (!((m_stepCounter + 1) % m_checksteps)))
307  {
308  m_Check++;
309  m_equ[m_nequ - 1]->Checkpoint_Output(m_Check);
310  }
311  m_stepCounter++;
312  }
313 
314  m_file.close();
315 
316  /// We save the final solution into a .fld file
317  m_equ[m_nequ - 1]->Output();
318 
319  for (int j = 0; j < m_equ[m_nequ - 1]->GetNvariables(); ++j)
320  {
321  NekDouble vL2Error = m_equ[m_nequ - 1]->L2Error(j, false);
322  NekDouble vLinfError = m_equ[m_nequ - 1]->LinfError(j);
323  if (m_comm->GetRank() == 0)
324  {
325  out << "L 2 error (variable " << m_equ[m_nequ - 1]->GetVariable(j)
326  << ") : " << vL2Error << endl;
327  out << "L inf error (variable " << m_equ[m_nequ - 1]->GetVariable(j)
328  << ") : " << vLinfError << endl;
329  }
330  }
331 }
332 
333 /**
334  * This routine defines the encapsulated SFD operator with first-order
335  * splitting and exact resolution of the second subproblem.
336  *(See http://scitation.aip.org/content/aip/journal/pof2/26/3/10.1063/1.4867482
337  *for details)
338  */
340  const NekDouble Delta_input)
341 {
342  NekDouble X = X_input * m_dt;
343  NekDouble Delta = Delta_input / m_dt;
344  NekDouble coeff = 1.0 / (1.0 + X * Delta);
345  M11 = coeff * (1.0 + X * Delta * exp(-(X + 1.0 / Delta)));
346  M12 = coeff * (X * Delta * (1.0 - exp(-(X + 1.0 / Delta))));
347  M21 = coeff * (1.0 - exp(-(X + 1.0 / Delta)));
348  M22 = coeff * (X * Delta + exp(-(X + 1.0 / Delta)));
349 }
350 
352  const int i, const Array<OneD, const Array<OneD, NekDouble>> &q0,
353  const Array<OneD, const Array<OneD, NekDouble>> &qBar0,
356 {
357  q1[i] = Array<OneD, NekDouble>(m_equ[m_nequ - 1]->GetTotPoints(), 0.0);
358  qBar1[i] = Array<OneD, NekDouble>(m_equ[m_nequ - 1]->GetTotPoints(), 0.0);
359 
360  /// Encapsulated SFD method
361  Vmath::Svtvp(q1[i].size(), M11, q0[i], 1, q1[i], 1, q1[i], 1);
362  Vmath::Svtvp(q1[i].size(), M12, qBar0[i], 1, q1[i], 1, q1[i], 1);
363 
364  Vmath::Svtvp(qBar1[i].size(), M21, q0[i], 1, qBar1[i], 1, qBar1[i], 1);
365  Vmath::Svtvp(qBar1[i].size(), M22, qBar0[i], 1, qBar1[i], 1, qBar1[i], 1);
366 }
367 
369 {
370  NekDouble growthEV(0.0);
371  NekDouble frequencyEV(0.0);
372 
373  // m_kdim is the dimension of Krylov subspace (defined in the xml file and
374  // used in DriverArnoldi.cpp)
375  ReadEVfile(m_kdim, growthEV, frequencyEV);
376 
377  cout << "\n\tgrowthEV = " << growthEV << endl;
378  cout << "\tfrequencyEV = " << frequencyEV << endl;
379 
380  complex<NekDouble> ApproxEV = polar(exp(growthEV), frequencyEV);
381 
382  NekDouble X_new = m_X;
383  NekDouble Delta_new = m_Delta;
384 
385  GradientDescentMethod(ApproxEV, X_new, Delta_new);
386 
387  m_X = X_new;
388  m_Delta = Delta_new;
389 
391 }
392 
393 /**
394  * This routine implements a gradient descent method to find the parameters X
395  * end Delta which give the minimum eigenlavue of the SFD problem applied to
396  * the scalar case u(n+1) = \alpha*u(n).
397  */
398 void DriverSteadyState::GradientDescentMethod(const complex<NekDouble> &alpha,
399  NekDouble &X_output,
400  NekDouble &Delta_output)
401 {
402  cout << "\n\tWe enter the Gradient Descent Method [...]" << endl;
403  bool OptParmFound = false;
404  bool Descending = true;
405  NekDouble X_input = X_output;
406  NekDouble Delta_input = Delta_output;
407 
408  NekDouble X_init = X_output;
409  NekDouble Delta_init = Delta_output;
410  int stepCounter(0);
411 
412  NekDouble F0(0.0);
413  NekDouble F0x(0.0);
414  NekDouble F0y(0.0);
415  NekDouble F1(0.0);
416  NekDouble dx = 0.00000001;
417  NekDouble dirx(0.0);
418  NekDouble diry(0.0);
419  NekDouble s(0.0);
420  NekDouble CurrentMin = 1.0;
421 
422  while (OptParmFound == false)
423  {
424  Descending = true;
425  EvalEV_ScalarSFD(X_input, Delta_input, alpha, F0);
426  EvalEV_ScalarSFD(X_input + dx, Delta_input, alpha, F0x);
427  EvalEV_ScalarSFD(X_input, Delta_input + dx, alpha, F0y);
428  dirx = (F0 - F0x);
429  diry = (F0 - F0y);
430  s = abs(0.000001 / dirx);
431  X_output = X_input + s * dirx;
432  Delta_output = Delta_input + s * diry;
433  F1 = F0;
434 
435  while (Descending == true)
436  {
437  CurrentMin = F1;
438  X_input = X_output;
439  Delta_input = Delta_output;
440  EvalEV_ScalarSFD(X_output, Delta_output, alpha, F1);
441 
442  if (F1 > CurrentMin)
443  {
444  Descending = false;
445  }
446  else
447  {
448  s = s + s * 0.01;
449  X_output = X_input + s * dirx;
450  Delta_output = Delta_input + s * diry;
451  }
452 
453  if (stepCounter > 9999999)
454  {
455  // We are stuck in this loop..
456  // Then we restart it with different initail conditions
457  Descending = false;
458  X_input = X_init;
459  Delta_init = Delta_init + Delta_init * 0.1;
460  Delta_input = Delta_init;
461  stepCounter = 0;
462  }
463  stepCounter++;
464  }
465 
466  if (abs(F0 - F1) < dx)
467  {
468  cout << "\tThe Gradient Descent Method has converged!" << endl;
469  EvalEV_ScalarSFD(X_output, Delta_output, alpha, F1);
470  cout << "\n\tThe updated parameters are: X_tilde = " << X_output
471  << " and Delta_tilde = " << Delta_output << endl;
472  OptParmFound = true;
473  }
474  }
475 }
476 
477 /**
478  * This routine evaluates the maximum eigenvalue of the SFD system when applied
479  * to the 1D model u(n+1) = alpha*u(n)
480  */
482  const NekDouble &Delta_input,
483  const complex<NekDouble> &alpha,
484  NekDouble &MaxEV)
485 {
486  NekDouble A11 =
487  (1.0 + X_input * Delta_input * exp(-(X_input + 1.0 / Delta_input))) /
488  (1.0 + X_input * Delta_input);
489  NekDouble A12 =
490  (X_input * Delta_input -
491  X_input * Delta_input * exp(-(X_input + 1.0 / Delta_input))) /
492  (1.0 + X_input * Delta_input);
493  NekDouble A21 = (1.0 - 1.0 * exp(-(X_input + 1.0 / Delta_input))) /
494  (1 + X_input * Delta_input);
495  NekDouble A22 =
496  (X_input * Delta_input + 1.0 * exp(-(X_input + 1.0 / Delta_input))) /
497  (1.0 + X_input * Delta_input);
498 
499  complex<NekDouble> B11 = alpha;
500  NekDouble B12 = 0.0;
501  NekDouble B21 = 0.0;
502  NekDouble B22 = 1.0;
503 
504  complex<NekDouble> a = A11 * B11 + A12 * B21;
505  NekDouble b = A11 * B12 + A12 * B22;
506  complex<NekDouble> c = A21 * B11 + A22 * B21;
507  NekDouble d = A21 * B12 + A22 * B22;
508 
509  complex<NekDouble> delt = sqrt((a - d) * (a - d) + 4.0 * b * c);
510  complex<NekDouble> lambda_1 = 0.5 * (a + d + delt);
511  complex<NekDouble> lambda_2 = 0.5 * (a + d - delt);
512 
513  NekDouble NORM_1 = abs(lambda_1);
514  NekDouble NORM_2 = abs(lambda_2);
515 
516  MaxEV = max(NORM_1, NORM_2);
517 }
518 
519 void DriverSteadyState::ReadEVfile(int &KrylovSubspaceDim, NekDouble &growthEV,
520  NekDouble &frequencyEV)
521 {
522  // This routine reads the .evl file written by the Arnoldi algorithm
523  // (written in September 2014)
524  std::string line;
525  int NumLinesInFile = 0;
526  std::string EVfileName = m_session->GetSessionName() + ".evl";
527  std::ifstream EVfile(EVfileName.c_str());
528  ASSERTL0(EVfile.good(), "Cannot open .evl file.");
529 
530  if (EVfile)
531  {
532  // This block counts the total number of lines of the .evl file
533  // We keep going util we reach the end of the file
534  while (getline(EVfile, line))
535  {
536  ++NumLinesInFile;
537  }
538 
539  // It may happen that the Stability method that have produced the .elv
540  // file converges in less than m_kdim iterations. In this case,
541  // KrylovSubspaceDim has to be changed here
542  if (NumLinesInFile <
543  KrylovSubspaceDim * 2.0 +
544  KrylovSubspaceDim * (KrylovSubspaceDim + 1.0) / 2.0)
545  {
546  for (int i = 1; i <= KrylovSubspaceDim; ++i)
547  {
548  if (NumLinesInFile == i * 2.0 + i * (i + 1.0) / 2.0)
549  {
550  KrylovSubspaceDim = i;
551  }
552  }
553  }
554 
555  // go back to the beginning of the file
556  EVfile.clear();
557  EVfile.seekg(0, ios::beg);
558 
559  // We now want to go to the line where the most unstable eigenlavue was
560  // written
561  for (int i = 0; i < (NumLinesInFile - KrylovSubspaceDim); ++i)
562  {
563  std::getline(EVfile, line);
564  cout << "Discard line: " << line << endl;
565  }
566 
567  std::vector<std::string> tokens;
568  std::getline(EVfile, line);
569  boost::algorithm::split(tokens, line, boost::is_any_of("\t "),
570  boost::token_compress_on);
571 
572  ASSERTL0(tokens.size() >= 5,
573  "Unexpected formatting of .evl file while reading line:\n" +
574  line);
575  growthEV = boost::lexical_cast<NekDouble>(tokens[4]);
576  frequencyEV = boost::lexical_cast<NekDouble>(tokens[5]);
577  }
578  else
579  {
580  cout << "An error occurred when opening the .evl file" << endl;
581  }
582  EVfile.close();
583 }
584 
585 /**
586  * This routine evaluates |q-qBar|_inf (and |q1-q0|_inf) and writes the values
587  * in "ConvergenceHistory.txt"
588  */
590  const Array<OneD, const Array<OneD, NekDouble>> &qBar1,
591  const Array<OneD, const Array<OneD, NekDouble>> &q0,
592  NekDouble &MaxNormDiff_q_qBar, NekDouble &MaxNormDiff_q1_q0)
593 {
594  Array<OneD, NekDouble> NormDiff_q_qBar(NumVar_SFD, 1.0);
595  Array<OneD, NekDouble> NormDiff_q1_q0(NumVar_SFD, 1.0);
596  MaxNormDiff_q_qBar = 0.0;
597  MaxNormDiff_q1_q0 = 0.0;
598 
599  for (int i = 0; i < NumVar_SFD; ++i)
600  {
601  NormDiff_q_qBar[i] = m_equ[m_nequ - 1]->LinfError(i, qBar1[i]);
602  NormDiff_q1_q0[i] = m_equ[m_nequ - 1]->LinfError(i, q0[i]);
603 
604  if (MaxNormDiff_q_qBar < NormDiff_q_qBar[i])
605  {
606  MaxNormDiff_q_qBar = NormDiff_q_qBar[i];
607  }
608  if (MaxNormDiff_q1_q0 < NormDiff_q1_q0[i])
609  {
610  MaxNormDiff_q1_q0 = NormDiff_q1_q0[i];
611  }
612  }
613 
614  timer.Stop();
616  cpuTime += elapsed;
617  totalTime += elapsed;
618 
619  if (m_comm->GetRank() == 0)
620  {
621  cout << "SFD - Step: " << left << m_stepCounter + 1
622  << ";\tTime: " << left << m_equ[m_nequ - 1]->GetFinalTime()
623  << ";\tCPU time = " << left << cpuTime << " s"
624  << ";\tTot time = " << left << totalTime << " s"
625  << ";\tX = " << left << m_X << ";\tDelta = " << left << m_Delta
626  << ";\t|q-qBar|inf = " << left << MaxNormDiff_q_qBar << endl;
627  std::ofstream m_file("ConvergenceHistory.txt", std::ios_base::app);
628  m_file << m_stepCounter + 1 << "\t" << m_equ[m_nequ - 1]->GetFinalTime()
629  << "\t" << totalTime << "\t" << MaxNormDiff_q_qBar << "\t"
630  << MaxNormDiff_q1_q0 << endl;
631  m_file.close();
632  }
633 
634  cpuTime = 0.0;
635  timer.Start();
636 }
637 
639 {
640  cout << "\n====================================="
641  "=================================="
642  << endl;
643  cout << "Parameters for the SFD method:" << endl;
644  cout << "\tControl Coefficient: X = " << m_X << endl;
645  cout << "\tFilter Width: Delta = " << m_Delta << endl;
646  cout << "The simulation is stopped when |q-qBar|inf < " << TOL << endl;
648  {
649  cout << "\nWe use the adaptive SFD method:" << endl;
650  cout << " The parameters are updated every " << AdaptiveTime
651  << " time units;" << endl;
652  cout << " until |q-qBar|inf becomes smaller than " << AdaptiveTOL
653  << endl;
654  }
655  cout << "====================================="
656  "==================================\n"
657  << endl;
658 }
659 
660 } // namespace SolverUtils
661 } // namespace Nektar
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:198
NekDouble TimePerTest(unsigned int n)
Returns amount of seconds per iteration in a test with n iterations.
Definition: Timer.cpp:68
A base class for PDEs which include an advection component.
LibUtilities::SessionReaderSharedPtr m_session
Session reader object.
Definition: Driver.h:88
LibUtilities::CommSharedPtr m_comm
Communication object.
Definition: Driver.h:85
enum EvolutionOperatorType m_EvolutionOperator
Evolution Operator.
Definition: Driver.h:103
Array< OneD, EquationSystemSharedPtr > m_equ
Equation system to solve.
Definition: Driver.h:97
int m_nequ
number of equations
Definition: Driver.h:100
virtual void v_InitObject(std::ostream &out=std::cout) override
Virtual function for initialisation implementation.
virtual void v_Execute(std::ostream &out=std::cout) override
Virtual function for solve implementation.
virtual SOLVER_UTILS_EXPORT void v_InitObject(std::ostream &out=std::cout) override
Second-stage initialisation.
void ComputeSFD(const int i, const Array< OneD, const Array< OneD, NekDouble >> &q0, const Array< OneD, const Array< OneD, NekDouble >> &qBar0, Array< OneD, Array< OneD, NekDouble >> &q1, Array< OneD, Array< OneD, NekDouble >> &qBar1)
NekDouble m_Delta
Definition of the SFD parameters:
virtual SOLVER_UTILS_EXPORT ~DriverSteadyState()
Destructor.
void SetSFDOperator(const NekDouble X_input, const NekDouble Delta_input)
NekDouble M11
Definition of the SFD operator.
virtual SOLVER_UTILS_EXPORT void v_Execute(std::ostream &out=std::cout) override
Virtual function for solve implementation.
void GradientDescentMethod(const std::complex< NekDouble > &alpha, NekDouble &X_output, NekDouble &Delta_output)
void EvalEV_ScalarSFD(const NekDouble &X_input, const NekDouble &Delta_input, const std::complex< NekDouble > &alpha, NekDouble &MaxEV)
void ConvergenceHistory(const Array< OneD, const Array< OneD, NekDouble >> &qBar1, const Array< OneD, const Array< OneD, NekDouble >> &q0, NekDouble &MaxNormDiff_q_qBar, NekDouble &MaxNormDiff_q1_q0)
bool FlowPartiallyConverged
For adaptive SFD method.
void ReadEVfile(int &KrylovSubspaceDim, NekDouble &growthEV, NekDouble &frequencyEV)
std::shared_ptr< SessionReader > SessionReaderSharedPtr
DriverFactory & GetDriverFactory()
Definition: Driver.cpp:64
std::shared_ptr< AdvectionSystem > AdvectionSystemSharedPtr
Shared pointer to an AdvectionSystem class.
std::shared_ptr< MeshGraph > MeshGraphSharedPtr
Definition: MeshGraph.h:172
The above copyright notice and this permission notice shall be included.
Definition: CoupledSolver.h:2
double NekDouble
void Svtvp(int n, const T alpha, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
svtvp (scalar times vector plus vector): z = alpha*x + y
Definition: Vmath.cpp:622
scalarT< T > abs(scalarT< T > in)
Definition: scalar.hpp:298
scalarT< T > sqrt(scalarT< T > in)
Definition: scalar.hpp:294