Nektar++
Static Public Member Functions | Static Public Attributes | Protected Member Functions | Private Member Functions | Static Private Attributes | Friends | List of all members
Nektar::SolverUtils::DriverModifiedArnoldi Class Reference

#include <DriverModifiedArnoldi.h>

Inheritance diagram for Nektar::SolverUtils::DriverModifiedArnoldi:
[legend]

Static Public Member Functions

static DriverSharedPtr create (const LibUtilities::SessionReaderSharedPtr &pSession, const SpatialDomains::MeshGraphSharedPtr &pGraph)
 Creates an instance of this class. More...
 

Static Public Attributes

static std::string className
 Name of the class. More...
 

Protected Member Functions

 DriverModifiedArnoldi (const LibUtilities::SessionReaderSharedPtr pSession, const SpatialDomains::MeshGraphSharedPtr pGraph)
 Constructor. More...
 
virtual ~DriverModifiedArnoldi ()
 Destructor. More...
 
virtual void v_InitObject (std::ostream &out=std::cout)
 Virtual function for initialisation implementation. More...
 
virtual void v_Execute (std::ostream &out=std::cout)
 Virtual function for solve implementation. More...
 
- Protected Member Functions inherited from Nektar::SolverUtils::DriverArnoldi
 DriverArnoldi (const LibUtilities::SessionReaderSharedPtr pSession, const SpatialDomains::MeshGraphSharedPtr pGraph)
 Constructor. More...
 
virtual ~DriverArnoldi ()
 Destructor. More...
 
void CopyArnoldiArrayToField (Array< OneD, NekDouble > &array)
 Copy Arnoldi storage to fields. More...
 
void CopyFieldToArnoldiArray (Array< OneD, NekDouble > &array)
 Copy fields to Arnoldi storage. More...
 
void CopyFwdToAdj ()
 Copy the forward field to the adjoint system in transient growth calculations. More...
 
void WriteFld (std::string file, std::vector< Array< OneD, NekDouble > > coeffs)
 Write coefficients to file. More...
 
void WriteFld (std::string file, Array< OneD, NekDouble > coeffs)
 
void WriteEvs (std::ostream &evlout, const int k, const NekDouble real, const NekDouble imag, NekDouble resid=NekConstants::kNekUnsetDouble, bool DumpInverse=true)
 
void MaskInit ()
 init mask More...
 
void GetUnmaskFunction (std::vector< std::vector< LibUtilities::EquationSharedPtr > > &unmaskfun)
 
virtual Array< OneD, NekDoublev_GetRealEvl (void)
 
virtual Array< OneD, NekDoublev_GetImagEvl (void)
 
- Protected Member Functions inherited from Nektar::SolverUtils::Driver
 Driver (const LibUtilities::SessionReaderSharedPtr pSession, const SpatialDomains::MeshGraphSharedPtr pGraph)
 Initialises EquationSystem class members. More...
 

Private Member Functions

void EV_update (Array< OneD, NekDouble > &src, Array< OneD, NekDouble > &tgt)
 Generates a new vector in the sequence by applying the linear operator. More...
 
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. More...
 
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. More...
 
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. More...
 
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)
 

Static Private Attributes

static std::string driverLookupId
 

Friends

class MemoryManager< DriverModifiedArnoldi >
 

Additional Inherited Members

- Public Member Functions inherited from Nektar::SolverUtils::DriverArnoldi
SOLVER_UTILS_EXPORT void ArnoldiSummary (std::ostream &out)
 
SOLVER_UTILS_EXPORT const Array< OneD, const NekDouble > & GetMaskCoeff () const
 
SOLVER_UTILS_EXPORT const Array< OneD, const NekDouble > & GetMaskPhys () const
 
- Public Member Functions inherited from Nektar::SolverUtils::Driver
virtual ~Driver ()
 Destructor. More...
 
SOLVER_UTILS_EXPORT void InitObject (std::ostream &out=std::cout)
 Initialise Object. More...
 
SOLVER_UTILS_EXPORT void Execute (std::ostream &out=std::cout)
 Execute driver. More...
 
SOLVER_UTILS_EXPORT Array< OneD, EquationSystemSharedPtrGetEqu ()
 
SOLVER_UTILS_EXPORT Array< OneD, NekDoubleGetRealEvl (void)
 
SOLVER_UTILS_EXPORT Array< OneD, NekDoubleGetImagEvl (void)
 
- Protected Attributes inherited from Nektar::SolverUtils::DriverArnoldi
int m_kdim
 
int m_nvec
 Dimension of Krylov subspace. More...
 
int m_nits
 Number of vectors to test. More...
 
NekDouble m_evtol
 Maxmum number of iterations. More...
 
NekDouble m_period
 Tolerance of iteratiosn. More...
 
bool m_timeSteppingAlgorithm
 Period of time stepping algorithm. More...
 
int m_infosteps
 underlying operator is time stepping More...
 
int m_nfields
 interval to dump information if required. More...
 
NekDouble m_realShift
 
NekDouble m_imagShift
 
int m_negatedOp
 
Array< OneD, NekDoublem_real_evl
 Operator in solve call is negated. More...
 
Array< OneD, NekDoublem_imag_evl
 
bool m_useMask
 
Array< OneD, NekDoublem_maskCoeffs
 
Array< OneD, NekDoublem_maskPhys
 
- Protected Attributes inherited from Nektar::SolverUtils::Driver
LibUtilities::CommSharedPtr m_comm
 Communication object. More...
 
LibUtilities::SessionReaderSharedPtr m_session
 Session reader object. More...
 
LibUtilities::SessionReaderSharedPtr session_LinNS
 I the Coupling between SFD and arnoldi. More...
 
SpatialDomains::MeshGraphSharedPtr m_graph
 MeshGraph object. More...
 
Array< OneD, EquationSystemSharedPtrm_equ
 Equation system to solve. More...
 
int m_nequ
 number of equations More...
 
enum EvolutionOperatorType m_EvolutionOperator
 Evolution Operator. More...
 
- Static Protected Attributes inherited from Nektar::SolverUtils::Driver
static std::string evolutionOperatorLookupIds []
 
static std::string evolutionOperatorDef
 
static std::string driverDefault
 

Detailed Description

Definition at line 46 of file DriverModifiedArnoldi.h.

Constructor & Destructor Documentation

◆ DriverModifiedArnoldi()

Nektar::SolverUtils::DriverModifiedArnoldi::DriverModifiedArnoldi ( const LibUtilities::SessionReaderSharedPtr  pSession,
const SpatialDomains::MeshGraphSharedPtr  pGraph 
)
protected

Constructor.

Definition at line 59 of file DriverModifiedArnoldi.cpp.

62  : DriverArnoldi(pSession, pGraph)
63 {
64 }
DriverArnoldi(const LibUtilities::SessionReaderSharedPtr pSession, const SpatialDomains::MeshGraphSharedPtr pGraph)
Constructor.

◆ ~DriverModifiedArnoldi()

Nektar::SolverUtils::DriverModifiedArnoldi::~DriverModifiedArnoldi ( )
protectedvirtual

Destructor.

Definition at line 70 of file DriverModifiedArnoldi.cpp.

71 {
72 }

Member Function Documentation

◆ create()

static DriverSharedPtr Nektar::SolverUtils::DriverModifiedArnoldi::create ( const LibUtilities::SessionReaderSharedPtr pSession,
const SpatialDomains::MeshGraphSharedPtr pGraph 
)
inlinestatic

Creates an instance of this class.

Definition at line 52 of file DriverModifiedArnoldi.h.

55  {
57  ::AllocateSharedPtr(pSession, pGraph);
58  p->InitObject();
59  return p;
60  }
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
std::shared_ptr< Driver > DriverSharedPtr
A shared pointer to a Driver object.
Definition: Driver.h:51

References Nektar::MemoryManager< DataType >::AllocateSharedPtr(), and CellMLToNektar.cellml_metadata::p.

◆ EV_big()

void Nektar::SolverUtils::DriverModifiedArnoldi::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 
)
private

Compute estimates of the eigenvalues/eigenvectors of the original system.

Definition at line 617 of file DriverModifiedArnoldi.cpp.

626 {
627  boost::ignore_unused(wr);
628 
629  NekDouble wgt, norm;
630  Array<OneD, Array<OneD, NekDouble> > btmp(nvec);
631  Array<OneD, Array<OneD, NekDouble> > etmp(nvec);
632  for(int i=0; i<nvec; ++i)
633  {
634  if (m_useMask)
635  {
636  btmp[i] = Array<OneD, NekDouble>(ntot, 0.);
637  etmp[i] = Array<OneD, NekDouble>(ntot, 0.);
638  }
639  else
640  {
641  btmp[i] = evecs[i];
642  }
643  }
644 
645  // Generate big eigenvectors
646  for (int j = 0; j < nvec; ++j)
647  {
648  Vmath::Zero(ntot, btmp[j], 1);
649  if (m_useMask)
650  {
651  Vmath::Zero(ntot, etmp[j], 1);
652  }
653  for (int i = 0; i < kdim; ++i)
654  {
655  wgt = zvec[i + j*kdim];
656  Vmath::Svtvp(ntot, wgt, bvecs[i], 1, btmp[j], 1, btmp[j], 1);
657  if (m_useMask)
658  {
659  Vmath::Svtvp(ntot, wgt, evecs[i], 1, etmp[j], 1, etmp[j], 1);
660  }
661  }
662  }
663 
664  // Normalise the big eigenvectors
665  for (int i = 0; i < nvec; ++i)
666  {
667  if (wi[i] == 0.0) // Real mode
668  {
669  if (m_session->GetComm()->GetRank() == 0)
670  {
671  cout << "eigenvalue " << i << ": real mode" << endl;
672  }
673  norm = Blas::Ddot(ntot, &btmp[i][0], 1, &btmp[i][0], 1);
674  m_comm->AllReduce(norm, Nektar::LibUtilities::ReduceSum);
675  norm = std::sqrt(norm);
676  if (m_useMask)
677  {
678  Vmath::Smul(ntot, 1.0/norm, btmp[i], 1, bvecs[i], 1);
679  Vmath::Smul(ntot, 1.0/norm, etmp[i], 1, evecs[i], 1);
680  }
681  else
682  {
683  Vmath::Smul(ntot, 1.0/norm, btmp[i], 1, evecs[i], 1);
684  }
685  }
686  else
687  {
688  if (m_session->GetComm()->GetRank() == 0)
689  {
690  cout << "eigenvalues " << i << ", " << i+1
691  << ": complex modes" << endl;
692  }
693  norm = Blas::Ddot(ntot, &btmp[i][0], 1, &btmp[i][0], 1);
694  norm += Blas::Ddot(ntot, &btmp[i+1][0], 1, &btmp[i+1][0], 1);
695  m_comm->AllReduce(norm, Nektar::LibUtilities::ReduceSum);
696  norm = std::sqrt(norm);
697 
698  if (m_useMask)
699  {
700  Vmath::Smul(ntot, 1.0/norm, btmp[i], 1, bvecs[i], 1);
701  Vmath::Smul(ntot, 1.0/norm, btmp[i+1], 1, bvecs[i+1], 1);
702  Vmath::Smul(ntot, 1.0/norm, etmp[i], 1, evecs[i], 1);
703  Vmath::Smul(ntot, 1.0/norm, etmp[i+1], 1, evecs[i+1], 1);
704  }
705  else
706  {
707  Vmath::Smul(ntot, 1.0/norm, btmp[i], 1, evecs[i], 1);
708  Vmath::Smul(ntot, 1.0/norm, btmp[i+1], 1, evecs[i+1], 1);
709  }
710 
711  i++;
712  }
713  }
714 }
LibUtilities::SessionReaderSharedPtr m_session
Session reader object.
Definition: Driver.h:89
LibUtilities::CommSharedPtr m_comm
Communication object.
Definition: Driver.h:86
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:197
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
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:225
void Zero(int n, T *x, const int incx)
Zero vector.
Definition: Vmath.cpp:436
scalarT< T > sqrt(scalarT< T > in)
Definition: scalar.hpp:267

References Blas::Ddot(), Nektar::SolverUtils::Driver::m_comm, Nektar::SolverUtils::Driver::m_session, Nektar::SolverUtils::DriverArnoldi::m_useMask, Nektar::LibUtilities::ReduceSum, Vmath::Smul(), tinysimd::sqrt(), Vmath::Svtvp(), and Vmath::Zero().

Referenced by EV_post().

◆ EV_post()

void Nektar::SolverUtils::DriverModifiedArnoldi::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 
)
private

Post-process the Ritz eigenvalues/eigenvectors of the matrix H, to compute estimations of the leading eigenvalues and eigenvectors of the original matrix.

Definition at line 557 of file DriverModifiedArnoldi.cpp.

567 {
568  if (icon == 0)
569  {
570  // Not converged, write final Krylov vector
571  ASSERTL0(false, "Convergence was not achieved within the "
572  "prescribed number of iterations.");
573  }
574  else if (icon < 0)
575  {
576  // Minimum residual reached
577  ASSERTL0(false, "Minimum residual reached.");
578  }
579  else if (icon == nvec)
580  {
581  // Converged, write out eigenvectors
582  EV_big(Tseq, Kseq, ntot, kdim, icon, zvec, wr, wi);
583  Array<OneD, MultiRegions::ExpListSharedPtr> fields
584  = m_equ[0]->UpdateFields();
585 
586  for (int j = 0; j < icon; ++j)
587  {
588  std::string file = m_session->GetSessionName() + "_eig_"
589  + boost::lexical_cast<std::string>(j)
590  + ".fld";
591 
592  if (m_comm->GetRank() == 0)
593  {
594  WriteEvs(cout, j, wr[j], wi[j]);
595  }
596  WriteFld(file,Kseq[j]);
597  if (m_useMask)
598  {
599  std::string fileunmask = m_session->GetSessionName() + "_eig_masked_"
600  + boost::lexical_cast<std::string>(j)
601  + ".fld";
602  WriteFld(fileunmask,Tseq[j]);
603  }
604  }
605  }
606  else
607  {
608  // Not recognised
609  ASSERTL0(false, "Unrecognised value.");
610  }
611 }
#define ASSERTL0(condition, msg)
Definition: ErrorUtil.hpp:216
void WriteFld(std::string file, std::vector< Array< OneD, NekDouble > > coeffs)
Write coefficients to file.
void WriteEvs(std::ostream &evlout, const int k, const NekDouble real, const NekDouble imag, NekDouble resid=NekConstants::kNekUnsetDouble, bool DumpInverse=true)
Array< OneD, EquationSystemSharedPtr > m_equ
Equation system to solve.
Definition: Driver.h:98
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)

References ASSERTL0, EV_big(), Nektar::SolverUtils::Driver::m_comm, Nektar::SolverUtils::Driver::m_equ, Nektar::SolverUtils::Driver::m_session, Nektar::SolverUtils::DriverArnoldi::m_useMask, Nektar::SolverUtils::DriverArnoldi::WriteEvs(), and Nektar::SolverUtils::DriverArnoldi::WriteFld().

Referenced by v_Execute().

◆ EV_small()

void Nektar::SolverUtils::DriverModifiedArnoldi::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 
)
private

Generates the upper Hessenberg matrix H and computes its eigenvalues.

Computes the Ritz eigenvalues and eigenvectors of the Hessenberg matrix constructed from the Krylov sequence.

Definition at line 382 of file DriverModifiedArnoldi.cpp.

392 {
393  int kdimp = kdim + 1;
394  int lwork = 10*kdim;
395  int ier;
396  Array<OneD, NekDouble> R(kdimp * kdimp, 0.0);
397  Array<OneD, NekDouble> H(kdimp * kdim, 0.0);
398  Array<OneD, NekDouble> rwork(lwork, 0.0);
399 
400  // Modified G-S orthonormalisation
401  for (int i = 0; i < kdimp; ++i)
402  {
403  NekDouble gsc = Blas::Ddot(ntot, &Kseq[i][0], 1, &Kseq[i][0], 1);
404  m_comm->AllReduce(gsc, Nektar::LibUtilities::ReduceSum);
405  gsc = std::sqrt(gsc);
406  ASSERTL0(gsc != 0.0, "Vectors are linearly independent.");
407 
408  R[i*kdimp+i] = gsc;
409  Vmath::Smul(ntot, 1.0/gsc, Kseq[i], 1, Kseq[i], 1);
410  if (m_useMask)
411  {
412  Vmath::Smul(ntot, 1.0/gsc, Kseqcopy[i], 1, Kseqcopy[i], 1);
413  }
414 
415  for (int j = i + 1; j < kdimp; ++j)
416  {
417  gsc = Blas::Ddot(ntot, &Kseq[i][0], 1, &Kseq[j][0], 1);
418  m_comm->AllReduce(gsc, Nektar::LibUtilities::ReduceSum);
419  Vmath::Svtvp(ntot, -gsc, Kseq[i], 1, Kseq[j], 1, Kseq[j], 1);
420  if (m_useMask)
421  {
422  Vmath::Svtvp(ntot, -gsc, Kseqcopy[i], 1, Kseqcopy[j], 1, Kseqcopy[j], 1);
423  }
424  R[j*kdimp+i] = gsc;
425  }
426  }
427 
428  // Compute H matrix
429  for (int i = 0; i < kdim; ++i)
430  {
431  for (int j = 0; j < kdim; ++j)
432  {
433  H[j*kdim+i] = alpha[j+1] * R[(j+1)*kdimp+i]
434  - Vmath::Dot(j, &H[0] + i, kdim, &R[0] + j*kdimp, 1);
435  H[j*kdim+i] /= R[j*kdimp+j];
436  }
437  }
438 
439  H[(kdim-1)*kdim+kdim] = alpha[kdim]
440  * std::fabs(R[kdim*kdimp+kdim] / R[(kdim-1)*kdimp + kdim-1]);
441 
442  Lapack::dgeev_('N', 'V', kdim, &H[0], kdim, &wr[0], &wi[0], 0, 1,
443  &zvec[0], kdim, &rwork[0], lwork, ier);
444 
445  ASSERTL0(!ier, "Error with dgeev");
446 
447  resnorm = H[(kdim-1)*kdim + kdim];
448 }
T Dot(int n, const T *w, const T *x)
vvtvp (vector times vector times vector): z = w*x*y
Definition: Vmath.cpp:1038

References ASSERTL0, Blas::Ddot(), Vmath::Dot(), Nektar::SolverUtils::Driver::m_comm, Nektar::SolverUtils::DriverArnoldi::m_useMask, Nektar::LibUtilities::ReduceSum, Vmath::Smul(), tinysimd::sqrt(), and Vmath::Svtvp().

Referenced by v_Execute().

◆ EV_sort()

void Nektar::SolverUtils::DriverModifiedArnoldi::EV_sort ( Array< OneD, NekDouble > &  evec,
Array< OneD, NekDouble > &  wr,
Array< OneD, NekDouble > &  wi,
Array< OneD, NekDouble > &  test,
const int  dim 
)
private

Sorts a sequence of eigenvectors/eigenvalues by magnitude.

Sorts the computed eigenvalues by smallest residual first.

Definition at line 520 of file DriverModifiedArnoldi.cpp.

526 {
527  Array<OneD, NekDouble> z_tmp(dim,0.0);
528  NekDouble wr_tmp, wi_tmp, te_tmp;
529  for (int j = 1; j < dim; ++j)
530  {
531  wr_tmp = wr[j];
532  wi_tmp = wi[j];
533  te_tmp = test[j];
534  Vmath::Vcopy(dim, &evec[0] + j*dim, 1, &z_tmp[0], 1);
535  int i = j - 1;
536  while (i >= 0 && test[i] > te_tmp)
537  {
538  wr[i+1] = wr[i];
539  wi[i+1] = wi[i];
540  test[i+1] = test[i];
541  Vmath::Vcopy(dim, &evec[0] + i*dim, 1, &evec[0] + (i+1)*dim, 1);
542  i--;
543  }
544  wr[i+1] = wr_tmp;
545  wi[i+1] = wi_tmp;
546  test[i+1] = te_tmp;
547  Vmath::Vcopy(dim, &z_tmp[0], 1, &evec[0] + (i+1)*dim, 1);
548  }
549 }
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition: Vmath.cpp:1199

References Vmath::Vcopy().

Referenced by EV_test().

◆ EV_test()

int Nektar::SolverUtils::DriverModifiedArnoldi::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 
)
private

Tests for convergence of eigenvalues of H.

Check for convergence of the residuals of the eigenvalues of H.

Definition at line 454 of file DriverModifiedArnoldi.cpp.

464 {
465  int idone = 0;
466  // NekDouble period = 0.1;
467 
468  Array<OneD, NekDouble> resid(kdim);
469  for (int i = 0; i < kdim; ++i)
470  {
471  NekDouble tmp = std::sqrt(Vmath::Dot(kdim, &zvec[0] + i*kdim, 1,
472  &zvec[0] + i*kdim, 1));
473  resid[i] = resnorm * std::fabs(zvec[kdim - 1 + i*kdim]) / tmp;
474  if (wi[i] < 0.0)
475  {
476  resid[i-1] = resid[i] = hypot(resid[i-1], resid[i]);
477  }
478  }
479 
480  EV_sort(zvec, wr, wi, resid, kdim);
481 
482  while (nvec <= kdim && resid[nvec-1] < m_evtol)
483  {
484  idone = nvec;
485  ++nvec;
486  }
487  nvec -= (idone > 0);
488 
489  if (m_comm->GetRank() == 0)
490  {
491  evlout << "-- Iteration = " << itrn << ", H(k+1, k) = "
492  << resnorm << endl;
493  evlout.precision(4);
494  evlout.setf(ios::scientific, ios::floatfield);
496  {
497  evlout << " Magnitude Angle Growth "
498  << "Frequency Residual" << endl;
499  }
500  else
501  {
502  evlout << " Real Imaginary inverse real "
503  << "inverse imag Residual" << endl;
504  }
505 
506  for (int i = 0; i < kdim; i++)
507  {
508  WriteEvs(evlout,i,wr[i],wi[i],resid[i]);
509  }
510  }
511 
512  resid0 = resid[nvec-1];
513  return idone;
514 }
bool m_timeSteppingAlgorithm
Period of time stepping algorithm.
Definition: DriverArnoldi.h:63
NekDouble m_evtol
Maxmum number of iterations.
Definition: DriverArnoldi.h:61
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.

References Vmath::Dot(), EV_sort(), Nektar::SolverUtils::Driver::m_comm, Nektar::SolverUtils::DriverArnoldi::m_evtol, Nektar::SolverUtils::DriverArnoldi::m_timeSteppingAlgorithm, tinysimd::sqrt(), and Nektar::SolverUtils::DriverArnoldi::WriteEvs().

Referenced by v_Execute().

◆ EV_update()

void Nektar::SolverUtils::DriverModifiedArnoldi::EV_update ( Array< OneD, NekDouble > &  src,
Array< OneD, NekDouble > &  tgt 
)
private

Generates a new vector in the sequence by applying the linear operator.

Definition at line 349 of file DriverModifiedArnoldi.cpp.

352 {
353  // Copy starting vector into first sequence element.
355  m_equ[0]->TransCoeffToPhys();
356 
357  m_equ[0]->SetTime(0.);
358  m_equ[0]->DoSolve();
359 
361  {
362  Array<OneD, MultiRegions::ExpListSharedPtr> fields;
363  fields = m_equ[0]->UpdateFields();
364 
365  //start Adjoint with latest fields of direct
366  CopyFwdToAdj();
367  m_equ[1]->TransCoeffToPhys();
368 
369  m_equ[1]->SetTime(0.);
370  m_equ[1]->DoSolve();
371  }
372 
373  // Copy starting vector into first sequence element.
375 }
void CopyFwdToAdj()
Copy the forward field to the adjoint system in transient growth calculations.
void CopyFieldToArnoldiArray(Array< OneD, NekDouble > &array)
Copy fields to Arnoldi storage.
void CopyArnoldiArrayToField(Array< OneD, NekDouble > &array)
Copy Arnoldi storage to fields.
enum EvolutionOperatorType m_EvolutionOperator
Evolution Operator.
Definition: Driver.h:104

References Nektar::SolverUtils::DriverArnoldi::CopyArnoldiArrayToField(), Nektar::SolverUtils::DriverArnoldi::CopyFieldToArnoldiArray(), Nektar::SolverUtils::DriverArnoldi::CopyFwdToAdj(), Nektar::SolverUtils::eTransientGrowth, Nektar::SolverUtils::Driver::m_equ, and Nektar::SolverUtils::Driver::m_EvolutionOperator.

Referenced by v_Execute().

◆ v_Execute()

void Nektar::SolverUtils::DriverModifiedArnoldi::v_Execute ( std::ostream &  out = std::cout)
protectedvirtual

Virtual function for solve implementation.

Implements Nektar::SolverUtils::Driver.

Reimplemented in Nektar::SolverUtils::DriverSteadyState.

Definition at line 106 of file DriverModifiedArnoldi.cpp.

107 {
108  int i = 0;
109  int j = 0;
110  int nq = m_equ[0]->UpdateFields()[0]->GetNcoeffs();
111  int ntot = m_nfields*nq;
112  int converged = 0;
113  NekDouble resnorm = 0.0;
114  ofstream evlout;
115  std::string evlFile = m_session->GetSessionName() + ".evl";
116 
117  if (m_comm->GetRank() == 0)
118  {
119  evlout.open(evlFile.c_str());
120  }
121 
122  // Allocate memory
123  Array<OneD, NekDouble> alpha = Array<OneD, NekDouble> (m_kdim+1, 0.0);
124  Array<OneD, NekDouble> wr = Array<OneD, NekDouble> (m_kdim, 0.0);
125  Array<OneD, NekDouble> wi = Array<OneD, NekDouble> (m_kdim, 0.0);
126  Array<OneD, NekDouble> zvec = Array<OneD, NekDouble> (m_kdim*m_kdim, 0.0);
127 
128  Array<OneD, Array<OneD, NekDouble> > Kseq
129  = Array<OneD, Array<OneD, NekDouble> > (m_kdim + 1);
130  Array<OneD, Array<OneD, NekDouble> > Kseqcopy
131  = Array<OneD, Array<OneD, NekDouble> > (m_kdim + 1);
132  Array<OneD, Array<OneD, NekDouble> > Tseq
133  = Array<OneD, Array<OneD, NekDouble> > (m_kdim + 1);
134  for (i = 0; i < m_kdim + 1; ++i)
135  {
136  Kseq[i] = Array<OneD, NekDouble>(ntot, 0.0);
137  if (m_useMask)
138  {
139  Kseqcopy[i] = Array<OneD, NekDouble>(ntot, 0.0);
140  }
141  else
142  {
143  Kseqcopy[i] = Kseq[i];
144  }
145  Tseq[i] = Array<OneD, NekDouble>(ntot, 0.0);
146  }
147 
148  // Copy starting vector into second sequence element (temporary).
149  if(m_session->DefinesFunction("InitialConditions"))
150  {
151  if (m_comm->GetRank() == 0)
152  {
153  out << "\tInital vector : specified in input file " << endl;
154  }
155  m_equ[0]->SetInitialConditions(0.0,false);
156 
157  CopyFieldToArnoldiArray(Kseq[1]);
158  }
159  else
160  {
161  if (m_comm->GetRank() == 0)
162  {
163  out << "\tInital vector : random " << endl;
164  }
165 
166  NekDouble eps=0.0001;
167  Vmath::FillWhiteNoise(ntot, eps , &Kseq[1][0], 1);
168  if (m_useMask)
169  {
170  Vmath::Vmul(ntot, Kseq[1], 1, GetMaskCoeff(), 1, Kseq[1], 1);
171  }
172  }
173 
174  // Perform one iteration to enforce boundary conditions.
175  // Set this as the initial value in the sequence.
176  EV_update(Kseq[1], Kseq[0]);
177  if (m_comm->GetRank() == 0)
178  {
179  out << "Iteration: " << 0 << endl;
180  }
181 
182  // Normalise first vector in sequence
183  if (m_useMask)
184  {
185  Vmath::Vmul(ntot, Kseq[0], 1, GetMaskCoeff(), 1, Kseqcopy[0], 1);
186  }
187  alpha[0] = Blas::Ddot(ntot, &Kseqcopy[0][0], 1, &Kseqcopy[0][0], 1);
188  m_comm->AllReduce(alpha[0], Nektar::LibUtilities::ReduceSum);
189  alpha[0] = std::sqrt(alpha[0]);
190  Vmath::Smul(ntot, 1.0/alpha[0], Kseq[0], 1, Kseq[0], 1);
191 
192  // Fill initial krylov sequence
193  NekDouble resid0;
194  for (i = 1; !converged && i <= m_kdim; ++i)
195  {
196  // Compute next vector
197  EV_update(Kseq[i-1], Kseq[i]);
198 
199  // Normalise
200  if (m_useMask)
201  {
202  Vmath::Vmul(ntot, Kseq[i], 1, GetMaskCoeff(), 1, Kseqcopy[i], 1);
203  }
204  alpha[i] = Blas::Ddot(ntot, &Kseqcopy[i][0], 1, &Kseqcopy[i][0], 1);
205  m_comm->AllReduce(alpha[i], Nektar::LibUtilities::ReduceSum);
206  alpha[i] = std::sqrt(alpha[i]);
207 
208  //alpha[i] = std::sqrt(alpha[i]);
209  Vmath::Smul(ntot, 1.0/alpha[i], Kseq[i], 1, Kseq[i], 1);
210 
211  // Copy Krylov sequence into temporary storage
212  for (int k = 0; k < i + 1; ++k)
213  {
214  if (m_useMask)
215  {
216  Vmath::Vmul(ntot, Kseq[k], 1, GetMaskCoeff(), 1, Tseq[k], 1);
217  Vmath::Vcopy(ntot, Kseq[k], 1, Kseqcopy[k], 1);
218  }
219  else
220  {
221  Vmath::Vcopy(ntot, Kseq[k], 1, Tseq[k], 1);;
222  }
223  }
224 
225  // Generate Hessenberg matrix and compute eigenvalues of it.
226  EV_small(Tseq, Kseqcopy, ntot, alpha, i, zvec, wr, wi, resnorm);
227 
228  // Test for convergence.
229  converged = EV_test(i, i, zvec, wr, wi, resnorm,
230  std::min(i, m_nvec), evlout, resid0);
231  if ( i >= m_nvec)
232  {
233  converged = max (converged, 0);
234  }
235  else
236  {
237  converged = 0;
238  }
239 
240  if (m_comm->GetRank() == 0)
241  {
242  out << "Iteration: " << i << " (residual : " << resid0
243  << ")" <<endl;
244  }
245  }
246 
247  // Continue with full sequence
248  if (!converged)
249  {
250  for (i = m_kdim + 1; !converged && i <= m_nits; ++i)
251  {
252  // Shift all the vectors in the sequence.
253  // First vector is removed.
254  for (int j = 1; j <= m_kdim; ++j)
255  {
256  alpha[j-1] = alpha[j];
257  Vmath::Vcopy(ntot, Kseq[j], 1, Kseq[j-1], 1);
258  }
259 
260  // Compute next vector
261  EV_update(Kseq[m_kdim - 1], Kseq[m_kdim]);
262 
263  // Compute new scale factor
264  if (m_useMask)
265  {
266  Vmath::Vmul(ntot, Kseq[m_kdim], 1, GetMaskCoeff(), 1,
267  Kseqcopy[m_kdim], 1);
268  }
269  alpha[m_kdim] = Blas::Ddot(ntot, &Kseqcopy[m_kdim][0], 1,
270  &Kseqcopy[m_kdim][0], 1);
271  m_comm->AllReduce(alpha[m_kdim], Nektar::LibUtilities::ReduceSum);
272  alpha[m_kdim] = std::sqrt(alpha[m_kdim]);
273  Vmath::Smul(ntot, 1.0/alpha[m_kdim], Kseq[m_kdim], 1,
274  Kseq[m_kdim], 1);
275 
276  // Copy Krylov sequence into temporary storage
277  for (int k = 0; k < m_kdim + 1; ++k)
278  {
279  if (m_useMask)
280  {
281  Vmath::Vmul(ntot, Kseq[k], 1, GetMaskCoeff(), 1, Tseq[k], 1);
282  Vmath::Vcopy(ntot, Kseq[k], 1, Kseqcopy[k], 1);
283  }
284  else
285  {
286  Vmath::Vcopy(ntot, Kseq[k], 1, Tseq[k], 1);;
287  }
288  }
289 
290  // Generate Hessenberg matrix and compute eigenvalues of it
291  EV_small(Tseq, Kseqcopy, ntot, alpha, m_kdim, zvec, wr, wi, resnorm);
292 
293  // Test for convergence.
294  converged = EV_test(i, m_kdim, zvec, wr, wi, resnorm,
295  m_nvec, evlout, resid0);
296 
297  if (m_comm->GetRank() == 0)
298  {
299  out << "Iteration: " << i << " (residual : "
300  << resid0 << ")" <<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 }
#define WARNINGL0(condition, msg)
Definition: ErrorUtil.hpp:223
SOLVER_UTILS_EXPORT const Array< OneD, const NekDouble > & GetMaskCoeff() const
int m_nvec
Dimension of Krylov subspace.
Definition: DriverArnoldi.h:59
int m_nits
Number of vectors to test.
Definition: DriverArnoldi.h:60
Array< OneD, NekDouble > m_imag_evl
Definition: DriverArnoldi.h:73
int m_nfields
interval to dump information if required.
Definition: DriverArnoldi.h:67
Array< OneD, NekDouble > m_real_evl
Operator in solve call is negated.
Definition: DriverArnoldi.h:72
void EV_update(Array< OneD, NekDouble > &src, Array< OneD, NekDouble > &tgt)
Generates a new vector in the sequence by applying the linear operator.
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)
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_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 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:192
void FillWhiteNoise(int n, const T eps, T *x, const int incx, int outseed)
Fills a vector with white noise.
Definition: Vmath.cpp:142

References Nektar::SolverUtils::DriverArnoldi::CopyFieldToArnoldiArray(), Blas::Ddot(), EV_post(), EV_small(), EV_test(), EV_update(), Vmath::FillWhiteNoise(), Nektar::SolverUtils::DriverArnoldi::GetMaskCoeff(), Nektar::SolverUtils::Driver::m_comm, Nektar::SolverUtils::Driver::m_equ, Nektar::SolverUtils::DriverArnoldi::m_imag_evl, Nektar::SolverUtils::DriverArnoldi::m_imagShift, Nektar::SolverUtils::DriverArnoldi::m_kdim, Nektar::SolverUtils::DriverArnoldi::m_nfields, Nektar::SolverUtils::DriverArnoldi::m_nits, Nektar::SolverUtils::DriverArnoldi::m_nvec, Nektar::SolverUtils::DriverArnoldi::m_real_evl, Nektar::SolverUtils::Driver::m_session, Nektar::SolverUtils::DriverArnoldi::m_useMask, Nektar::LibUtilities::ReduceSum, Vmath::Smul(), tinysimd::sqrt(), Vmath::Vcopy(), Vmath::Vmul(), and WARNINGL0.

Referenced by Nektar::SolverUtils::DriverSteadyState::v_Execute().

◆ v_InitObject()

void Nektar::SolverUtils::DriverModifiedArnoldi::v_InitObject ( std::ostream &  out = std::cout)
protectedvirtual

Virtual function for initialisation implementation.

Reimplemented from Nektar::SolverUtils::DriverArnoldi.

Reimplemented in Nektar::SolverUtils::DriverSteadyState.

Definition at line 78 of file DriverModifiedArnoldi.cpp.

79 {
81 
82  m_equ[0]->PrintSummary(out);
83 
84  // Print session parameters
85  if (m_comm->GetRank() == 0)
86  {
87  out << "\tArnoldi solver type : Modified Arnoldi" << endl;
88  }
89 
91 
92  for( int i = 0; i < m_nequ; ++i)
93  {
94  m_equ[i]->DoInitialise();
95  }
96 
97  //FwdTrans Initial conditions to be in Coefficient Space
98  m_equ[m_nequ-1] ->TransPhysToCoeff();
99 
100 }
virtual void v_InitObject(std::ostream &out=std::cout)
SOLVER_UTILS_EXPORT void ArnoldiSummary(std::ostream &out)
int m_nequ
number of equations
Definition: Driver.h:101

References Nektar::SolverUtils::DriverArnoldi::ArnoldiSummary(), Nektar::SolverUtils::Driver::m_comm, Nektar::SolverUtils::Driver::m_equ, Nektar::SolverUtils::Driver::m_nequ, and Nektar::SolverUtils::DriverArnoldi::v_InitObject().

Referenced by Nektar::SolverUtils::DriverSteadyState::v_InitObject().

Friends And Related Function Documentation

◆ MemoryManager< DriverModifiedArnoldi >

friend class MemoryManager< DriverModifiedArnoldi >
friend

Definition at line 1 of file DriverModifiedArnoldi.h.

Member Data Documentation

◆ className

string Nektar::SolverUtils::DriverModifiedArnoldi::className
static
Initial value:
=
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
Definition: NekFactory.hpp:200
static DriverSharedPtr create(const LibUtilities::SessionReaderSharedPtr &pSession, const SpatialDomains::MeshGraphSharedPtr &pGraph)
Creates an instance of this class.
DriverFactory & GetDriverFactory()
Definition: Driver.cpp:65

Name of the class.

Definition at line 63 of file DriverModifiedArnoldi.h.

◆ driverLookupId

string Nektar::SolverUtils::DriverModifiedArnoldi::driverLookupId
staticprivate
Initial value:
=
"ModifiedArnoldi",0)
static std::string RegisterEnumValue(std::string pEnum, std::string pString, int pEnumValue)
Registers an enumeration value.

Definition at line 135 of file DriverModifiedArnoldi.h.