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