Nektar++
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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 // 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: Incompressible Navier Stokes solver
33 //
34 ///////////////////////////////////////////////////////////////////////////////
35 
37 
38 
39 namespace Nektar
40 {
41  namespace SolverUtils
42  {
45 
46  /**
47  *
48  */
50  : Driver(pSession)
51  {
52  }
53 
54 
55  /**
56  *
57  */
59  {
60  }
61 
62 
63  /**
64  *
65  */
67  {
69  }
70 
71 
72  void DriverSteadyState::v_Execute(ostream &out)
73 
74  {
75  //With a loop over "DoSolve", this Driver implements the "encaplulated" Selective Frequency Damping method
76  //to find the steady state of a flow above the critical Reynolds number.
77 
78  m_equ[0]->PrintSummary(out);
79  m_equ[0]->DoInitialise();
80 
81  // - SFD Routine -
82  // Compressible case
83  NumVar_SFD = m_equ[0]->UpdateFields()[0]->GetCoordim(0);
84  if (m_session->GetSolverInfo("EqType") == "EulerCFE" ||
85  m_session->GetSolverInfo("EqType") == "NavierStokesCFE")
86  {
87  NumVar_SFD += 2; //Number of variables for the compressible equations
88  }
89 
90  Array<OneD, Array<OneD, NekDouble> > q0(NumVar_SFD);
91  Array<OneD, Array<OneD, NekDouble> > q1(NumVar_SFD);
92  Array<OneD, Array<OneD, NekDouble> > qBar0(NumVar_SFD);
93  Array<OneD, Array<OneD, NekDouble> > qBar1(NumVar_SFD);
94 
95  NekDouble TOL(0);
96  m_n=0;
97  m_Check=0;
98 
99  m_session->LoadParameter("FilterWidth", m_Delta0, 1);
100  m_session->LoadParameter("ControlCoeff",m_X0, 1);
101  m_session->LoadParameter("TOL", TOL, 1.0e-08);
102  m_session->LoadParameter("IO_InfoSteps", m_infosteps, 1000);
103  m_session->LoadParameter("IO_CheckSteps", m_checksteps, 100000);
104 
105  m_dt = m_equ[0]->GetTimeStep();
106 
107  //The time-step is applied here to clarify the matrix F expression
108  m_X = m_X0*m_dt;
110 
111  //Exact solution of the Filters equation (ici on a X_tilde et Delta_tile!!!)
112  c1 = 1.0/(1.0 + m_X*m_Delta);
113  F11 = c1*(1.0 + m_X*m_Delta*exp(-(m_X + 1.0/m_Delta)));
114  F12 = c1*(m_X*m_Delta*(1.0 - exp(-(m_X + 1.0/m_Delta))));
115  F21 = c1*(1.0 - exp(-(m_X + 1.0/m_Delta)));
116  F22 = c1*(m_X*m_Delta + exp(-(m_X + 1.0/m_Delta)));
117 
118  cout << "------------------ SFD Parameters ------------------" << endl;
119  cout << "\tX = " << m_X0 << endl;
120  cout << "\tDelta = " << m_Delta0 << endl;
121  cout << "----------------------------------------------------" << endl;
122 
123  m_equ[0]->SetStepsToOne(); //m_steps is set to 1. Then "m_equ[0]->DoSolve()" will run for only one time step
124  ofstream m_file("ConvergenceHistory.txt", ios::out | ios::trunc);
125 
126  for(int i = 0; i < NumVar_SFD; ++i)
127  {
128  q0[i] = Array<OneD, NekDouble> (m_equ[0]->GetTotPoints(), 0.0); //q0 is initialised
129  qBar0[i] = Array<OneD, NekDouble> (m_equ[0]->GetTotPoints(), 0.0);
130  m_equ[0]->CopyFromPhysField(i, qBar0[i]); //qBar0 is initially set at beiing equal to the initial conditions provided in the input file
131  }
132 
133  MaxNormDiff_q_qBar = 1.0;
134  MaxNormDiff_q1_q0 = 1.0;
136 
137 
138  while (max(MaxNormDiff_q_qBar, MaxNormDiff_q1_q0) > TOL)
139  {
140  //First order Splitting with exact resolution of the filters equation
141  m_equ[0]->DoSolve();
142 
143  for(int i = 0; i < NumVar_SFD; ++i)
144  {
145  m_equ[0]->CopyFromPhysField(i, q0[i]);
146 
147  //Apply the linear operator F to the outcome of the solver
148  ExactFilters(i, q0, qBar0, q1, qBar1);
149 
150  qBar0[i] = qBar1[i];
151  m_equ[0]->CopyToPhysField(i, q1[i]);
152  }
153 
154 
155  if(m_infosteps && !((m_n+1)%m_infosteps))
156  {
158  }
159 
160  if(m_checksteps && m_n&&(!((m_n+1)%m_checksteps)))
161  {
162  m_Check++;
163  m_equ[0]->Checkpoint_Output(m_Check);
164  }
165 
166  m_n++;
167  }
168 
169  cout << "\nFINAL Filter Width: Delta = " << m_Delta << "; FINAL Control Coeff: X = " << m_X << "\n" << endl;
170  m_Check++;
171  m_equ[0]->Checkpoint_Output(m_Check);
172 
173  m_file.close();
174  // - End SFD Routine -
175 
176  m_equ[0]->Output();
177 
178  // Evaluate and output computation time and solution accuracy.
179  // The specific format of the error output is essential for the
180  // regression tests to work.
181  // Evaluate L2 Error
182  for(int i = 0; i < m_equ[0]->GetNvariables(); ++i)
183  {
184  NekDouble vL2Error = m_equ[0]->L2Error(i,false);
185  NekDouble vLinfError = m_equ[0]->LinfError(i);
186  if (m_comm->GetRank() == 0)
187  {
188  out << "L 2 error (variable " << m_equ[0]->GetVariable(i) << ") : " << vL2Error << endl;
189  out << "L inf error (variable " << m_equ[0]->GetVariable(i) << ") : " << vLinfError << endl;
190  }
191  }
192  }
193 
194 
196  const Array<OneD, const Array<OneD, NekDouble> > &q0,
197  const Array<OneD, const Array<OneD, NekDouble> > &qBar0,
198  Array<OneD, Array<OneD, NekDouble> > &q1,
199  Array<OneD, Array<OneD, NekDouble> > &qBar1)
200  {
201  q1[i] = Array<OneD, NekDouble> (m_equ[0]->GetTotPoints(),0.0);
202  qBar1[i] = Array<OneD, NekDouble> (m_equ[0]->GetTotPoints(),0.0);
203 
204  //Exact solution of the Filters equation
205  Vmath::Svtvp(q1[i].num_elements(), F11, q0[i], 1, q1[i], 1, q1[i], 1 );
206  Vmath::Svtvp(q1[i].num_elements(), F12, qBar0[i], 1, q1[i], 1, q1[i], 1 );
207 
208  Vmath::Svtvp(qBar1[i].num_elements(), F21, q0[i], 1, qBar1[i], 1, qBar1[i], 1 );
209  Vmath::Svtvp(qBar1[i].num_elements(), F22, qBar0[i], 1, qBar1[i], 1, qBar1[i], 1 );
210  }
211 
212 
213  void DriverSteadyState::ConvergenceHistory(const Array<OneD, const Array<OneD, NekDouble> > &qBar1,
214  const Array<OneD, const Array<OneD, NekDouble> > &q0,
215  NekDouble &MaxNormDiff_q_qBar,
216  NekDouble &MaxNormDiff_q1_q0)
217  {
218  //This routine evaluates |q-qBar|_L2 and save the value in "ConvergenceHistory.txt"
219 
220  Array<OneD, NekDouble > NormDiff_q_qBar(NumVar_SFD, 1.0);
221  Array<OneD, NekDouble > NormDiff_q1_q0(NumVar_SFD, 1.0);
222 
223  MaxNormDiff_q_qBar=0.0;
224  MaxNormDiff_q1_q0=0.0;
225 
226  //Norm Calculation
227  for(int i = 0; i < NumVar_SFD; ++i)
228  {
229  //To check convergence of SFD
230  //NormDiff_q_qBar[i] = m_equ[0]->L2Error(i, qBar1[i], false);
231  NormDiff_q_qBar[i] = m_equ[0]->LinfError(i, qBar1[i]);
232 
233  //To check convergence of Navier-Stokes
234  NormDiff_q1_q0[i] = m_equ[0]->LinfError(i, q0[i]);
235 
236  if (MaxNormDiff_q_qBar < NormDiff_q_qBar[i])
237  {
238  MaxNormDiff_q_qBar = NormDiff_q_qBar[i];
239  }
240 
241  if (MaxNormDiff_q1_q0 < NormDiff_q1_q0[i])
242  {
243  MaxNormDiff_q1_q0 = NormDiff_q1_q0[i];
244  }
245  }
246 
247  #if NEKTAR_USE_MPI
248  MPI_Comm_rank(MPI_COMM_WORLD,&MPIrank);
249  if (MPIrank==0)
250  {
251  cout << "SFD (MPI) - Step: " << m_n+1 << "; Time: " << m_equ[0]->GetFinalTime() << "; |q-qBar|inf = " << MaxNormDiff_q_qBar << "; |q1-q0|inf = " << MaxNormDiff_q1_q0 << ";\t for X = " << m_X0 <<" and Delta = " << m_Delta0 <<endl;
252  std::ofstream m_file( "ConvergenceHistory.txt", std::ios_base::app);
253  m_file << m_n+1 << "\t" << m_equ[0]->GetFinalTime() << "\t" << MaxNormDiff_q_qBar << "\t" << MaxNormDiff_q1_q0 << endl;
254  m_file.close();
255  }
256  #else
257  cout << "SFD - Step: " << m_n+1 << "; Time: " << m_equ[0]->GetFinalTime() << "; |q-qBar|inf = " << MaxNormDiff_q_qBar << "; |q1-q0|inf = " << MaxNormDiff_q1_q0 << ";\t for X = " << m_X0 <<" and Delta = " << m_Delta0 <<endl;
258  std::ofstream m_file( "ConvergenceHistory.txt", std::ios_base::app);
259  m_file << m_n+1 << "\t" << m_equ[0]->GetFinalTime() << "\t" << MaxNormDiff_q_qBar << "\t" << MaxNormDiff_q1_q0 << endl;
260  m_file.close();
261  #endif
262 
263  }
264  }
265 }
266