Nektar++
DriverArnoldi.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File DriverArnoldi.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: Base Driver class for the stability solver
32 //
33 ///////////////////////////////////////////////////////////////////////////////
34 #include <iomanip>
35 
37 
38 using namespace std;
39 
40 namespace Nektar
41 {
42 namespace SolverUtils
43 {
44 
45 /**
46  * Constructor
47  */
48 DriverArnoldi::DriverArnoldi(
51  : Driver(pSession, pGraph)
52 {
53  m_session->LoadParameter("IO_InfoSteps", m_infosteps, 1);
54 }
55 
56 
57 /**
58  * Destructor
59  */
61 {
62 }
63 
64 
65 /**
66  * Arnoldi driver initialisation
67  */
68 void DriverArnoldi::v_InitObject(ostream &out)
69 {
71  m_session->MatchSolverInfo("SolverType",
72  "VelocityCorrectionScheme",
74 
76  {
77  m_period = m_session->GetParameter("TimeStep")
78  * m_session->GetParameter("NumSteps");
79  m_nfields = m_equ[0]->UpdateFields().num_elements() - 1;
80 
81  }
82  else
83  {
84  m_period = 1.0;
85  m_nfields = m_equ[0]->UpdateFields().num_elements();
86  }
87 
88  if(m_session->DefinesSolverInfo("ModeType") &&
89  (boost::iequals(m_session->GetSolverInfo("ModeType"),
90  "SingleMode")||
91  boost::iequals(m_session->GetSolverInfo("ModeType"),
92  "HalfMode")))
93  {
94  for(int i = 0; i < m_nfields; ++i)
95  {
96  m_equ[0]->UpdateFields()[i]->SetWaveSpace(true);
97  }
98  }
99  m_negatedOp = m_equ[0]->v_NegatedOp();
100 
101  m_session->LoadParameter("kdim", m_kdim, 16);
102  m_session->LoadParameter("nvec", m_nvec, 2);
103  m_session->LoadParameter("nits", m_nits, 500);
104  m_session->LoadParameter("evtol", m_evtol, 1e-06);
105 
106  ASSERTL0( m_kdim >= m_nvec, "nvec cannot be larger than kdim.");
107 
108  m_session->LoadParameter("realShift", m_realShift, 0.0);
109  m_equ[0]->SetLambda(m_realShift);
110 
111  m_session->LoadParameter("imagShift",m_imagShift,0.0);
112 
113  // The imaginary shift is applied at system assembly
114  // Only if using HOMOGENEOUS expansion and ModeType set to SingleMode
115  if(m_imagShift != 0.0)
116  {
117  if(!m_session->DefinesSolverInfo("HOMOGENEOUS")&&!m_session->DefinesSolverInfo("ModeType"))
118  {
119  NEKERROR(ErrorUtil::efatal, "Imaginary shift only supported with HOMOGENEOUS expansion and ModeType set to SingleMode");
120  }
121  else if(!boost::iequals(m_session->GetSolverInfo("ModeType"),"SingleMode"))
122  {
123  NEKERROR(ErrorUtil::efatal, "Imaginary shift only supported with HOMOGENEOUS expansion and ModeType set to SingleMode");
124  }
125  }
126 
127 }
128 
129 void DriverArnoldi::ArnoldiSummary(std::ostream &out)
130 {
131  if (m_comm->GetRank() == 0)
132  {
133  if(m_session->DefinesSolverInfo("ModeType") &&
134  boost::iequals(m_session->GetSolverInfo("ModeType"),
135  "SingleMode"))
136  {
137  out << "\tSingle Fourier mode : true " << endl;
138  ASSERTL0(m_session->DefinesSolverInfo("Homogeneous"),
139  "Expected a homogeneous expansion to be defined "
140  "with single mode");
141  }
142  else
143  {
144  out << "\tSingle Fourier mode : false " << endl;
145  }
146  if(m_session->DefinesSolverInfo("BetaZero"))
147  {
148  out << "\tBeta set to Zero : true (overrides LHom)"
149  << endl;
150  }
151  else
152  {
153  out << "\tBeta set to Zero : false " << endl;
154  }
155 
157  {
158  out << "\tEvolution operator : "
159  << m_session->GetSolverInfo("EvolutionOperator")
160  << endl;
161  }
162  else
163  {
164  out << "\tShift (Real,Imag) : " << m_realShift
165  << "," << m_imagShift << endl;
166  }
167  out << "\tKrylov-space dimension : " << m_kdim << endl;
168  out << "\tNumber of vectors : " << m_nvec << endl;
169  out << "\tMax iterations : " << m_nits << endl;
170  out << "\tEigenvalue tolerance : " << m_evtol << endl;
171  out << "======================================================"
172  << endl;
173  }
174 }
175 
176 /**
177  * Copy Arnoldi array to field variables which depend from
178  * either the m_fields or m_forces
179  */
181 {
182 
183  Array<OneD, MultiRegions::ExpListSharedPtr>& fields = m_equ[0]->UpdateFields();
184  int nq = fields[0]->GetNcoeffs();
185 
186  for (int k = 0; k < m_nfields; ++k)
187  {
188  Vmath::Vcopy(nq, &array[k*nq], 1, &fields[k]->UpdateCoeffs()[0], 1);
189  fields[k]->SetPhysState(false);
190  }
191 }
192 
193 /**
194  * Copy field variables which depend from either the m_fields
195  * or m_forces array the Arnoldi array
196  */
198 {
199 
201 
203  {
204  // This matters for the Adaptive SFD method because
205  // m_equ[1] is the nonlinear problem with non
206  // homogeneous BCs.
207  fields = m_equ[0]->UpdateFields();
208  }
209  else
210  {
211  fields = m_equ[m_nequ-1]->UpdateFields();
212  }
213 
214  for (int k = 0; k < m_nfields; ++k)
215  {
216  int nq = fields[0]->GetNcoeffs();
217  Vmath::Vcopy(nq, &fields[k]->GetCoeffs()[0], 1, &array[k*nq], 1);
218  fields[k]->SetPhysState(false);
219 
220  }
221 }
222 
223 
224 /**
225  * Initialisation for the transient growth
226  */
228 {
230 
232  "Transient Growth non available for Coupled Solver");
233 
234  fields = m_equ[0]->UpdateFields();
235  int nq = fields[0]->GetNcoeffs();
236 
237  for (int k=0 ; k < m_nfields; ++k)
238  {
239  Vmath::Vcopy(nq,
240  &fields[k]->GetCoeffs()[0], 1,
241  &m_equ[1]->UpdateFields()[k]->UpdateCoeffs()[0], 1);
242  }
243 }
244 
245 void DriverArnoldi::WriteFld(std::string file, std::vector<Array<OneD, NekDouble> > coeffs)
246 {
247 
248  std::vector<std::string> variables(m_nfields);
249 
250  ASSERTL1(coeffs.size() >= m_nfields, "coeffs is not of the correct length");
251  for(int i = 0; i < m_nfields; ++i)
252  {
253  variables[i] = m_equ[0]->GetVariable(i);
254  }
255 
256  m_equ[0]->WriteFld(file,m_equ[0]->UpdateFields()[0], coeffs, variables);
257 }
258 
259 
260 void DriverArnoldi::WriteFld(std::string file, Array<OneD, NekDouble> coeffs)
261 {
262 
263  std::vector<std::string> variables(m_nfields);
264  std::vector<Array<OneD, NekDouble> > fieldcoeffs(m_nfields);
265 
266  int ncoeffs = m_equ[0]->UpdateFields()[0]->GetNcoeffs();
267  ASSERTL1(coeffs.num_elements() >= ncoeffs*m_nfields,"coeffs is not of sufficient size");
268 
269  for(int i = 0; i < m_nfields; ++i)
270  {
271  variables[i] = m_equ[0]->GetVariable(i);
272  fieldcoeffs[i] = coeffs + i*ncoeffs;
273  }
274 
275  m_equ[0]->WriteFld(file,m_equ[0]->UpdateFields()[0], fieldcoeffs, variables);
276 }
277 
279  ostream &evlout,
280  const int i,
281  const NekDouble re_ev,
282  const NekDouble im_ev,
283  NekDouble resid,
284  bool DumpInverse)
285 {
287  {
288  NekDouble abs_ev = hypot (re_ev, im_ev);
289  NekDouble ang_ev = atan2 (im_ev, re_ev);
290 
291  evlout << "EV: " << setw(2) << i
292  << setw(12) << abs_ev
293  << setw(12) << ang_ev
294  << setw(12) << log (abs_ev) / m_period
295  << setw(12) << ang_ev / m_period;
296 
297  if(resid != NekConstants::kNekUnsetDouble)
298  {
299  evlout << setw(12) << resid;
300  }
301  evlout << endl;
302  }
303  else
304  {
305  NekDouble invmag = 1.0/(re_ev*re_ev + im_ev*im_ev);
306  NekDouble sign;
307  if(m_negatedOp)
308  {
309  sign = -1.0;
310  }
311  else
312  {
313  sign = 1.0;
314  }
315 
316  evlout << "EV: " << setw(2) << i
317  << setw(14) << sign*re_ev
318  << setw(14) << sign*im_ev;
319 
320  if(DumpInverse)
321  {
322  evlout << setw(14) << sign*re_ev*invmag + m_realShift
323  << setw(14) << sign*im_ev*invmag + m_imagShift;
324  }
325 
326  if(resid != NekConstants::kNekUnsetDouble)
327  {
328  evlout << setw(12) << resid;
329  }
330  evlout << endl;
331  }
332 }
333 
334 }
335 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
std::shared_ptr< MeshGraph > MeshGraphSharedPtr
Definition: MeshGraph.h:163
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mod...
Definition: ErrorUtil.hpp:209
void CopyFwdToAdj()
Copy the forward field to the adjoint system in transient growth calculations.
NekDouble m_evtol
Maxmum number of iterations.
Definition: DriverArnoldi.h:57
void CopyArnoldiArrayToField(Array< OneD, NekDouble > &array)
Copy Arnoldi storage to fields.
#define sign(a, b)
return the sign(b)*a
Definition: Polylib.cpp:16
SOLVER_UTILS_EXPORT void ArnoldiSummary(std::ostream &out)
STL namespace.
void CopyFieldToArnoldiArray(Array< OneD, NekDouble > &array)
Copy fields to Arnoldi storage.
void WriteFld(std::string file, std::vector< Array< OneD, NekDouble > > coeffs)
Write coefficients to file.
virtual SOLVER_UTILS_EXPORT void v_InitObject(std::ostream &out=std::cout)
Definition: Driver.cpp:90
virtual ~DriverArnoldi()
Destructor.
int m_nvec
Dimension of Krylov subspace.
Definition: DriverArnoldi.h:55
void WriteEvs(std::ostream &evlout, const int k, const NekDouble real, const NekDouble imag, NekDouble resid=NekConstants::kNekUnsetDouble, bool DumpInverse=true)
virtual void v_InitObject(std::ostream &out=std::cout)
enum EvolutionOperatorType m_EvolutionOperator
Evolution Operator.
Definition: Driver.h:104
double NekDouble
static const NekDouble kNekUnsetDouble
int m_nfields
interval to dump information if required.
Definition: DriverArnoldi.h:63
bool m_timeSteppingAlgorithm
Period of time stepping algorithm.
Definition: DriverArnoldi.h:59
Array< OneD, EquationSystemSharedPtr > m_equ
Equation system to solve.
Definition: Driver.h:98
NekDouble m_period
Tolerance of iteratiosn.
Definition: DriverArnoldi.h:58
int m_infosteps
underlying operator is time stepping
Definition: DriverArnoldi.h:61
LibUtilities::CommSharedPtr m_comm
Communication object.
Definition: Driver.h:86
Base class for the development of solvers.
Definition: Driver.h:66
#define ASSERTL1(condition, msg)
Assert Level 1 – Debugging which is used whether in FULLDEBUG or DEBUG compilation mode...
Definition: ErrorUtil.hpp:250
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1064
std::shared_ptr< SessionReader > SessionReaderSharedPtr
LibUtilities::SessionReaderSharedPtr m_session
Session reader object.
Definition: Driver.h:89
int m_nequ
number of equations
Definition: Driver.h:101
int m_nits
Number of vectors to test.
Definition: DriverArnoldi.h:56