Nektar++
DriverModifiedArnoldi.cpp
Go to the documentation of this file.
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 // File: DriverModifiedArnoldi.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 for eigenvalue analysis using the modified Arnoldi
32 // method.
33 //
34 ///////////////////////////////////////////////////////////////////////////////
35 
36 #include <iomanip>
37 
38 #include <boost/core/ignore_unused.hpp>
39 
41 
42 using namespace std;
43 
44 namespace Nektar
45 {
46 namespace SolverUtils
47 {
48 
49 string DriverModifiedArnoldi::className =
50  GetDriverFactory().RegisterCreatorFunction("ModifiedArnoldi",
51  DriverModifiedArnoldi::create);
52 string DriverModifiedArnoldi::driverLookupId =
53  LibUtilities::SessionReader::RegisterEnumValue("Driver", "ModifiedArnoldi",
54  0);
55 
56 /**
57  *
58  */
59 DriverModifiedArnoldi::DriverModifiedArnoldi(
62  : DriverArnoldi(pSession, pGraph)
63 {
64 }
65 
66 /**
67  *
68  */
70 {
71 }
72 
73 /**
74  *
75  */
77 {
79 
80  m_equ[0]->PrintSummary(out);
81 
82  // Print session parameters
83  if (m_comm->GetRank() == 0)
84  {
85  out << "\tArnoldi solver type : Modified Arnoldi" << endl;
86  }
87 
89 
90  for (int i = 0; i < m_nequ; ++i)
91  {
92  m_equ[i]->DoInitialise();
93  }
94 
95  // FwdTrans Initial conditions to be in Coefficient Space
96  m_equ[m_nequ - 1]->TransPhysToCoeff();
97 }
98 
99 /**
100  *
101  */
103 {
104  int i = 0;
105  int j = 0;
106  int nq = m_equ[0]->UpdateFields()[0]->GetNcoeffs();
107  int ntot = m_nfields * nq;
108  int converged = 0;
109  NekDouble resnorm = 0.0;
110  ofstream evlout;
111  std::string evlFile = m_session->GetSessionName() + ".evl";
112 
113  if (m_comm->GetRank() == 0)
114  {
115  evlout.open(evlFile.c_str());
116  }
117 
118  // Allocate memory
123 
130  for (i = 0; i < m_kdim + 1; ++i)
131  {
132  Kseq[i] = Array<OneD, NekDouble>(ntot, 0.0);
133  if (m_useMask)
134  {
135  Kseqcopy[i] = Array<OneD, NekDouble>(ntot, 0.0);
136  }
137  else
138  {
139  Kseqcopy[i] = Kseq[i];
140  }
141  Tseq[i] = Array<OneD, NekDouble>(ntot, 0.0);
142  }
143 
144  // Copy starting vector into second sequence element (temporary).
145  if (m_session->DefinesFunction("InitialConditions"))
146  {
147  if (m_comm->GetRank() == 0)
148  {
149  out << "\tInital vector : specified in input file " << endl;
150  }
151  m_equ[0]->SetInitialConditions(0.0, false);
152 
153  CopyFieldToArnoldiArray(Kseq[1]);
154  }
155  else
156  {
157  if (m_comm->GetRank() == 0)
158  {
159  out << "\tInital vector : random " << endl;
160  }
161 
162  NekDouble eps = 0.0001;
163  Vmath::FillWhiteNoise(ntot, eps, &Kseq[1][0], 1);
164  if (m_useMask)
165  {
166  Vmath::Vmul(ntot, Kseq[1], 1, GetMaskCoeff(), 1, Kseq[1], 1);
167  }
168  }
169 
170  // Perform one iteration to enforce boundary conditions.
171  // Set this as the initial value in the sequence.
172  EV_update(Kseq[1], Kseq[0]);
173  if (m_comm->GetRank() == 0)
174  {
175  out << "Iteration: " << 0 << endl;
176  }
177 
178  // Normalise first vector in sequence
179  if (m_useMask)
180  {
181  Vmath::Vmul(ntot, Kseq[0], 1, GetMaskCoeff(), 1, Kseqcopy[0], 1);
182  }
183  alpha[0] = Blas::Ddot(ntot, &Kseqcopy[0][0], 1, &Kseqcopy[0][0], 1);
184  m_comm->AllReduce(alpha[0], Nektar::LibUtilities::ReduceSum);
185  alpha[0] = std::sqrt(alpha[0]);
186  Vmath::Smul(ntot, 1.0 / alpha[0], Kseq[0], 1, Kseq[0], 1);
187 
188  // Fill initial krylov sequence
189  NekDouble resid0;
190  for (i = 1; !converged && i <= m_kdim; ++i)
191  {
192  // Compute next vector
193  EV_update(Kseq[i - 1], Kseq[i]);
194 
195  // Normalise
196  if (m_useMask)
197  {
198  Vmath::Vmul(ntot, Kseq[i], 1, GetMaskCoeff(), 1, Kseqcopy[i], 1);
199  }
200  alpha[i] = Blas::Ddot(ntot, &Kseqcopy[i][0], 1, &Kseqcopy[i][0], 1);
201  m_comm->AllReduce(alpha[i], Nektar::LibUtilities::ReduceSum);
202  alpha[i] = std::sqrt(alpha[i]);
203 
204  // alpha[i] = std::sqrt(alpha[i]);
205  Vmath::Smul(ntot, 1.0 / alpha[i], Kseq[i], 1, Kseq[i], 1);
206 
207  // Copy Krylov sequence into temporary storage
208  for (int k = 0; k < i + 1; ++k)
209  {
210  if (m_useMask)
211  {
212  Vmath::Vmul(ntot, Kseq[k], 1, GetMaskCoeff(), 1, Tseq[k], 1);
213  Vmath::Vcopy(ntot, Kseq[k], 1, Kseqcopy[k], 1);
214  }
215  else
216  {
217  Vmath::Vcopy(ntot, Kseq[k], 1, Tseq[k], 1);
218  ;
219  }
220  }
221 
222  // Generate Hessenberg matrix and compute eigenvalues of it.
223  EV_small(Tseq, Kseqcopy, ntot, alpha, i, zvec, wr, wi, resnorm);
224 
225  // Test for convergence.
226  converged = EV_test(i, i, zvec, wr, wi, resnorm, std::min(i, m_nvec),
227  evlout, resid0);
228  if (i >= m_nvec)
229  {
230  converged = max(converged, 0);
231  }
232  else
233  {
234  converged = 0;
235  }
236 
237  if (m_comm->GetRank() == 0)
238  {
239  out << "Iteration: " << i << " (residual : " << resid0 << ")"
240  << endl;
241  }
242  }
243 
244  // Continue with full sequence
245  if (!converged)
246  {
247  for (i = m_kdim + 1; !converged && i <= m_nits; ++i)
248  {
249  // Shift all the vectors in the sequence.
250  // First vector is removed.
251  for (int j = 1; j <= m_kdim; ++j)
252  {
253  alpha[j - 1] = alpha[j];
254  Vmath::Vcopy(ntot, Kseq[j], 1, Kseq[j - 1], 1);
255  }
256 
257  // Compute next vector
258  EV_update(Kseq[m_kdim - 1], Kseq[m_kdim]);
259 
260  // Compute new scale factor
261  if (m_useMask)
262  {
263  Vmath::Vmul(ntot, Kseq[m_kdim], 1, GetMaskCoeff(), 1,
264  Kseqcopy[m_kdim], 1);
265  }
266  alpha[m_kdim] = Blas::Ddot(ntot, &Kseqcopy[m_kdim][0], 1,
267  &Kseqcopy[m_kdim][0], 1);
268  m_comm->AllReduce(alpha[m_kdim], Nektar::LibUtilities::ReduceSum);
269  alpha[m_kdim] = std::sqrt(alpha[m_kdim]);
270  Vmath::Smul(ntot, 1.0 / alpha[m_kdim], Kseq[m_kdim], 1,
271  Kseq[m_kdim], 1);
272 
273  // Copy Krylov sequence into temporary storage
274  for (int k = 0; k < m_kdim + 1; ++k)
275  {
276  if (m_useMask)
277  {
278  Vmath::Vmul(ntot, Kseq[k], 1, GetMaskCoeff(), 1, Tseq[k],
279  1);
280  Vmath::Vcopy(ntot, Kseq[k], 1, Kseqcopy[k], 1);
281  }
282  else
283  {
284  Vmath::Vcopy(ntot, Kseq[k], 1, Tseq[k], 1);
285  ;
286  }
287  }
288 
289  // Generate Hessenberg matrix and compute eigenvalues of it
290  EV_small(Tseq, Kseqcopy, ntot, alpha, m_kdim, zvec, wr, wi,
291  resnorm);
292 
293  // Test for convergence.
294  converged = EV_test(i, m_kdim, zvec, wr, wi, resnorm, m_nvec,
295  evlout, resid0);
296 
297  if (m_comm->GetRank() == 0)
298  {
299  out << "Iteration: " << i << " (residual : " << resid0 << ")"
300  << endl;
301  }
302  }
303  }
304 
305  m_equ[0]->Output();
306 
307  // Evaluate and output computation time and solution accuracy.
308  // The specific format of the error output is essential for the
309  // regression tests to work.
310  // Evaluate L2 Error
311  for (j = 0; j < m_equ[0]->GetNvariables(); ++j)
312  {
313  NekDouble vL2Error = m_equ[0]->L2Error(j, false);
314  NekDouble vLinfError = m_equ[0]->LinfError(j);
315  if (m_comm->GetRank() == 0)
316  {
317  out << "L 2 error (variable " << m_equ[0]->GetVariable(j)
318  << ") : " << vL2Error << endl;
319  out << "L inf error (variable " << m_equ[0]->GetVariable(j)
320  << ") : " << vLinfError << endl;
321  }
322  }
323 
324  // Process eigenvectors and write out.
325  m_nvec = converged;
326  EV_post(Tseq, Kseqcopy, ntot, min(--i, m_kdim), m_nvec, zvec, wr, wi,
327  converged);
328 
329  WARNINGL0(m_imagShift == 0, "Complex Shift applied. "
330  "Need to implement Ritz re-evaluation of"
331  "eigenvalue. Only one half of complex "
332  "value will be correct");
333 
334  // store eigenvalues so they can be accessed from driver class
335  m_real_evl = wr;
336  m_imag_evl = wi;
337 
338  // Close the runtime info file.
339  if (m_comm->GetRank() == 0)
340  {
341  evlout.close();
342  }
343 }
344 
345 /**
346  *
347  */
350 {
351  // Copy starting vector into first sequence element.
353  m_equ[0]->TransCoeffToPhys();
354 
355  m_equ[0]->SetTime(0.);
356  m_equ[0]->DoSolve();
357 
359  {
361  fields = m_equ[0]->UpdateFields();
362 
363  // start Adjoint with latest fields of direct
364  CopyFwdToAdj();
365  m_equ[1]->TransCoeffToPhys();
366 
367  m_equ[1]->SetTime(0.);
368  m_equ[1]->DoSolve();
369  }
370 
371  // Copy starting vector into first sequence element.
373 }
374 
375 /**
376  * Computes the Ritz eigenvalues and eigenvectors of the Hessenberg matrix
377  * constructed from the Krylov sequence.
378  */
381  Array<OneD, Array<OneD, NekDouble>> &Kseqcopy, const int ntot,
382  const Array<OneD, NekDouble> &alpha, const int kdim,
384  Array<OneD, NekDouble> &wi, NekDouble &resnorm)
385 {
386  int kdimp = kdim + 1;
387  int lwork = 10 * kdim;
388  int ier;
389  Array<OneD, NekDouble> R(kdimp * kdimp, 0.0);
390  Array<OneD, NekDouble> H(kdimp * kdim, 0.0);
391  Array<OneD, NekDouble> rwork(lwork, 0.0);
392 
393  // Modified G-S orthonormalisation
394  for (int i = 0; i < kdimp; ++i)
395  {
396  NekDouble gsc = Blas::Ddot(ntot, &Kseq[i][0], 1, &Kseq[i][0], 1);
397  m_comm->AllReduce(gsc, Nektar::LibUtilities::ReduceSum);
398  gsc = std::sqrt(gsc);
399  ASSERTL0(gsc != 0.0, "Vectors are linearly independent.");
400 
401  R[i * kdimp + i] = gsc;
402  Vmath::Smul(ntot, 1.0 / gsc, Kseq[i], 1, Kseq[i], 1);
403  if (m_useMask)
404  {
405  Vmath::Smul(ntot, 1.0 / gsc, Kseqcopy[i], 1, Kseqcopy[i], 1);
406  }
407 
408  for (int j = i + 1; j < kdimp; ++j)
409  {
410  gsc = Blas::Ddot(ntot, &Kseq[i][0], 1, &Kseq[j][0], 1);
411  m_comm->AllReduce(gsc, Nektar::LibUtilities::ReduceSum);
412  Vmath::Svtvp(ntot, -gsc, Kseq[i], 1, Kseq[j], 1, Kseq[j], 1);
413  if (m_useMask)
414  {
415  Vmath::Svtvp(ntot, -gsc, Kseqcopy[i], 1, Kseqcopy[j], 1,
416  Kseqcopy[j], 1);
417  }
418  R[j * kdimp + i] = gsc;
419  }
420  }
421 
422  // Compute H matrix
423  for (int i = 0; i < kdim; ++i)
424  {
425  for (int j = 0; j < kdim; ++j)
426  {
427  H[j * kdim + i] =
428  alpha[j + 1] * R[(j + 1) * kdimp + i] -
429  Vmath::Dot(j, &H[0] + i, kdim, &R[0] + j * kdimp, 1);
430  H[j * kdim + i] /= R[j * kdimp + j];
431  }
432  }
433 
434  H[(kdim - 1) * kdim + kdim] =
435  alpha[kdim] *
436  std::fabs(R[kdim * kdimp + kdim] / R[(kdim - 1) * kdimp + kdim - 1]);
437 
438  Lapack::dgeev_('N', 'V', kdim, &H[0], kdim, &wr[0], &wi[0], 0, 1, &zvec[0],
439  kdim, &rwork[0], lwork, ier);
440 
441  ASSERTL0(!ier, "Error with dgeev");
442 
443  resnorm = H[(kdim - 1) * kdim + kdim];
444 }
445 
446 /**
447  * Check for convergence of the residuals of the eigenvalues of H.
448  */
449 int DriverModifiedArnoldi::EV_test(const int itrn, const int kdim,
453  const NekDouble resnorm, int nvec,
454  ofstream &evlout, NekDouble &resid0)
455 {
456  int idone = 0;
457  // NekDouble period = 0.1;
458 
459  Array<OneD, NekDouble> resid(kdim);
460  for (int i = 0; i < kdim; ++i)
461  {
462  NekDouble tmp = std::sqrt(
463  Vmath::Dot(kdim, &zvec[0] + i * kdim, 1, &zvec[0] + i * kdim, 1));
464  resid[i] = resnorm * std::fabs(zvec[kdim - 1 + i * kdim]) / tmp;
465  if (wi[i] < 0.0)
466  {
467  resid[i - 1] = resid[i] = hypot(resid[i - 1], resid[i]);
468  }
469  }
470 
471  EV_sort(zvec, wr, wi, resid, kdim);
472 
473  while (nvec <= kdim && resid[nvec - 1] < m_evtol)
474  {
475  idone = nvec;
476  ++nvec;
477  }
478  nvec -= (idone > 0);
479 
480  if (m_comm->GetRank() == 0)
481  {
482  evlout << "-- Iteration = " << itrn << ", H(k+1, k) = " << resnorm
483  << endl;
484  evlout.precision(4);
485  evlout.setf(ios::scientific, ios::floatfield);
487  {
488  evlout << " Magnitude Angle Growth "
489  << "Frequency Residual" << endl;
490  }
491  else
492  {
493  evlout << " Real Imaginary inverse real "
494  << "inverse imag Residual" << endl;
495  }
496 
497  for (int i = 0; i < kdim; i++)
498  {
499  WriteEvs(evlout, i, wr[i], wi[i], resid[i]);
500  }
501  }
502 
503  resid0 = resid[nvec - 1];
504  return idone;
505 }
506 
507 /**
508  * Sorts the computed eigenvalues by smallest residual first.
509  */
513  Array<OneD, NekDouble> &test, const int dim)
514 {
515  Array<OneD, NekDouble> z_tmp(dim, 0.0);
516  NekDouble wr_tmp, wi_tmp, te_tmp;
517  for (int j = 1; j < dim; ++j)
518  {
519  wr_tmp = wr[j];
520  wi_tmp = wi[j];
521  te_tmp = test[j];
522  Vmath::Vcopy(dim, &evec[0] + j * dim, 1, &z_tmp[0], 1);
523  int i = j - 1;
524  while (i >= 0 && test[i] > te_tmp)
525  {
526  wr[i + 1] = wr[i];
527  wi[i + 1] = wi[i];
528  test[i + 1] = test[i];
529  Vmath::Vcopy(dim, &evec[0] + i * dim, 1, &evec[0] + (i + 1) * dim,
530  1);
531  i--;
532  }
533  wr[i + 1] = wr_tmp;
534  wi[i + 1] = wi_tmp;
535  test[i + 1] = te_tmp;
536  Vmath::Vcopy(dim, &z_tmp[0], 1, &evec[0] + (i + 1) * dim, 1);
537  }
538 }
539 
540 /**
541  * Post-process the Ritz eigenvalues/eigenvectors of the matrix H, to compute
542  * estimations of the leading eigenvalues and eigenvectors of the original
543  * matrix.
544  */
547  const int ntot, const int kdim,
548  const int nvec,
551  Array<OneD, NekDouble> &wi, const int icon)
552 {
553  if (icon == 0)
554  {
555  // Not converged, write final Krylov vector
556  ASSERTL0(false, "Convergence was not achieved within the "
557  "prescribed number of iterations.");
558  }
559  else if (icon < 0)
560  {
561  // Minimum residual reached
562  ASSERTL0(false, "Minimum residual reached.");
563  }
564  else if (icon == nvec)
565  {
566  // Converged, write out eigenvectors
567  EV_big(Tseq, Kseq, ntot, kdim, icon, zvec, wr, wi);
569  m_equ[0]->UpdateFields();
570 
571  for (int j = 0; j < icon; ++j)
572  {
573  std::string file = m_session->GetSessionName() + "_eig_" +
574  boost::lexical_cast<std::string>(j) + ".fld";
575 
576  if (m_comm->GetRank() == 0)
577  {
578  WriteEvs(cout, j, wr[j], wi[j]);
579  }
580  WriteFld(file, Kseq[j]);
581  if (m_useMask)
582  {
583  std::string fileunmask =
584  m_session->GetSessionName() + "_eig_masked_" +
585  boost::lexical_cast<std::string>(j) + ".fld";
586  WriteFld(fileunmask, Tseq[j]);
587  }
588  }
589  }
590  else
591  {
592  // Not recognised
593  ASSERTL0(false, "Unrecognised value.");
594  }
595 }
596 
597 /**
598  * Compute estimates of the eigenvalues/eigenvectors of the original system.
599  */
602  const int ntot, const int kdim,
603  const int nvec, Array<OneD, NekDouble> &zvec,
606 {
607  boost::ignore_unused(wr);
608 
609  NekDouble wgt, norm;
612  for (int i = 0; i < nvec; ++i)
613  {
614  if (m_useMask)
615  {
616  btmp[i] = Array<OneD, NekDouble>(ntot, 0.);
617  etmp[i] = Array<OneD, NekDouble>(ntot, 0.);
618  }
619  else
620  {
621  btmp[i] = evecs[i];
622  }
623  }
624 
625  // Generate big eigenvectors
626  for (int j = 0; j < nvec; ++j)
627  {
628  Vmath::Zero(ntot, btmp[j], 1);
629  if (m_useMask)
630  {
631  Vmath::Zero(ntot, etmp[j], 1);
632  }
633  for (int i = 0; i < kdim; ++i)
634  {
635  wgt = zvec[i + j * kdim];
636  Vmath::Svtvp(ntot, wgt, bvecs[i], 1, btmp[j], 1, btmp[j], 1);
637  if (m_useMask)
638  {
639  Vmath::Svtvp(ntot, wgt, evecs[i], 1, etmp[j], 1, etmp[j], 1);
640  }
641  }
642  }
643 
644  // Normalise the big eigenvectors
645  for (int i = 0; i < nvec; ++i)
646  {
647  if (wi[i] == 0.0) // Real mode
648  {
649  if (m_session->GetComm()->GetRank() == 0)
650  {
651  cout << "eigenvalue " << i << ": real mode" << endl;
652  }
653  norm = Blas::Ddot(ntot, &btmp[i][0], 1, &btmp[i][0], 1);
654  m_comm->AllReduce(norm, Nektar::LibUtilities::ReduceSum);
655  norm = std::sqrt(norm);
656  if (m_useMask)
657  {
658  Vmath::Smul(ntot, 1.0 / norm, btmp[i], 1, bvecs[i], 1);
659  Vmath::Smul(ntot, 1.0 / norm, etmp[i], 1, evecs[i], 1);
660  }
661  else
662  {
663  Vmath::Smul(ntot, 1.0 / norm, btmp[i], 1, evecs[i], 1);
664  }
665  }
666  else
667  {
668  if (m_session->GetComm()->GetRank() == 0)
669  {
670  cout << "eigenvalues " << i << ", " << i + 1
671  << ": complex modes" << endl;
672  }
673  norm = Blas::Ddot(ntot, &btmp[i][0], 1, &btmp[i][0], 1);
674  norm += Blas::Ddot(ntot, &btmp[i + 1][0], 1, &btmp[i + 1][0], 1);
675  m_comm->AllReduce(norm, Nektar::LibUtilities::ReduceSum);
676  norm = std::sqrt(norm);
677 
678  if (m_useMask)
679  {
680  Vmath::Smul(ntot, 1.0 / norm, btmp[i], 1, bvecs[i], 1);
681  Vmath::Smul(ntot, 1.0 / norm, btmp[i + 1], 1, bvecs[i + 1], 1);
682  Vmath::Smul(ntot, 1.0 / norm, etmp[i], 1, evecs[i], 1);
683  Vmath::Smul(ntot, 1.0 / norm, etmp[i + 1], 1, evecs[i + 1], 1);
684  }
685  else
686  {
687  Vmath::Smul(ntot, 1.0 / norm, btmp[i], 1, evecs[i], 1);
688  Vmath::Smul(ntot, 1.0 / norm, btmp[i + 1], 1, evecs[i + 1], 1);
689  }
690 
691  i++;
692  }
693  }
694 }
695 
696 } // namespace SolverUtils
697 } // namespace Nektar
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:215
#define WARNINGL0(condition, msg)
Definition: ErrorUtil.hpp:222
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:198
Base class for the development of solvers.
Definition: DriverArnoldi.h:47
void CopyFwdToAdj()
Copy the forward field to the adjoint system in transient growth calculations.
virtual void v_InitObject(std::ostream &out=std::cout) override
void WriteFld(std::string file, std::vector< Array< OneD, NekDouble >> coeffs)
Write coefficients to file.
SOLVER_UTILS_EXPORT const Array< OneD, const NekDouble > & GetMaskCoeff() const
void CopyFieldToArnoldiArray(Array< OneD, NekDouble > &array)
Copy fields to Arnoldi storage.
int m_nvec
Dimension of Krylov subspace.
Definition: DriverArnoldi.h:61
bool m_timeSteppingAlgorithm
Period of time stepping algorithm.
Definition: DriverArnoldi.h:65
int m_nits
Number of vectors to test.
Definition: DriverArnoldi.h:62
Array< OneD, NekDouble > m_imag_evl
Definition: DriverArnoldi.h:75
void CopyArnoldiArrayToField(Array< OneD, NekDouble > &array)
Copy Arnoldi storage to fields.
NekDouble m_evtol
Maxmum number of iterations.
Definition: DriverArnoldi.h:63
int m_nfields
interval to dump information if required.
Definition: DriverArnoldi.h:69
SOLVER_UTILS_EXPORT void ArnoldiSummary(std::ostream &out)
Array< OneD, NekDouble > m_real_evl
Operator in solve call is negated.
Definition: DriverArnoldi.h:74
void WriteEvs(std::ostream &evlout, const int k, const NekDouble real, const NekDouble imag, NekDouble resid=NekConstants::kNekUnsetDouble, bool DumpInverse=true)
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
void EV_update(Array< OneD, NekDouble > &src, Array< OneD, NekDouble > &tgt)
Generates a new vector in the sequence by applying the linear operator.
int EV_test(const int itrn, const int kdim, Array< OneD, NekDouble > &zvec, Array< OneD, NekDouble > &wr, Array< OneD, NekDouble > &wi, const NekDouble resnorm, int nvec, std::ofstream &evlout, NekDouble &resid0)
Tests for convergence of eigenvalues of H.
void EV_sort(Array< OneD, NekDouble > &evec, Array< OneD, NekDouble > &wr, Array< OneD, NekDouble > &wi, Array< OneD, NekDouble > &test, const int dim)
Sorts a sequence of eigenvectors/eigenvalues by magnitude.
void EV_small(Array< OneD, Array< OneD, NekDouble >> &Kseq, Array< OneD, Array< OneD, NekDouble >> &Kseqcopy, const int ntot, const Array< OneD, NekDouble > &alpha, const int kdim, Array< OneD, NekDouble > &zvec, Array< OneD, NekDouble > &wr, Array< OneD, NekDouble > &wi, NekDouble &resnorm)
Generates the upper Hessenberg matrix H and computes its eigenvalues.
void EV_post(Array< OneD, Array< OneD, NekDouble >> &Tseq, Array< OneD, Array< OneD, NekDouble >> &Kseq, const int ntot, const int kdim, const int nvec, Array< OneD, NekDouble > &zvec, Array< OneD, NekDouble > &wr, Array< OneD, NekDouble > &wi, const int icon)
void EV_big(Array< OneD, Array< OneD, NekDouble >> &bvecs, Array< OneD, Array< OneD, NekDouble >> &evecs, const int ntot, const int kdim, const int nvec, Array< OneD, NekDouble > &zvec, Array< OneD, NekDouble > &wr, Array< OneD, NekDouble > &wi)
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.
static double Ddot(const int &n, const double *x, const int &incx, const double *y, const int &incy)
BLAS level 1: output = .
Definition: Blas.hpp:182
std::shared_ptr< SessionReader > SessionReaderSharedPtr
DriverFactory & GetDriverFactory()
Definition: Driver.cpp:64
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 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:209
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
T Dot(int n, const T *w, const T *x)
dot (vector times vector): z = w*x
Definition: Vmath.cpp:1100
void Smul(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Scalar multiply y = alpha*x.
Definition: Vmath.cpp:248
void Zero(int n, T *x, const int incx)
Zero vector.
Definition: Vmath.cpp:492
void FillWhiteNoise(int n, const T eps, T *x, const int incx, int outseed)
Fills a vector with white noise.
Definition: Vmath.cpp:155
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1255
scalarT< T > sqrt(scalarT< T > in)
Definition: scalar.hpp:294