G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsEigenProblemBase.hpp
Go to the documentation of this file.
1 
14 #include <typeinfo>
15 #pragma once
16 
17 namespace gismo
18 {
19 
20 template <class T>
21 gsStatus gsEigenProblemBase<T>::compute()
22 {
23  if (m_status==gsStatus::AssemblyError)
24  return m_status;
25 
26  bool verbose = m_options.getSwitch("verbose");
27  if (verbose) { gsInfo<<"Solving eigenvalue problem" ; }
28  try
29  {
30  T shift = m_options.getReal("shift");
31  if (shift!=0.0)
32  m_eigSolver.compute(m_A-shift*m_B,m_B);
33  else
34  m_eigSolver.compute(m_A,m_B);
35 
36  if (verbose) { gsInfo<<"." ; }
37  m_values = m_eigSolver.eigenvalues();
38  m_values.array() += shift;
39  if (verbose) { gsInfo<<"." ; }
40  m_vectors = m_eigSolver.eigenvectors();
41  if (verbose) { gsInfo<<"." ; }
42  if (verbose) { gsInfo<<"Finished\n" ; }
43  m_status = gsStatus::Success;
44  }
45  catch (...)
46  {
47  m_status = gsStatus::SolverError;
48  }
49  return m_status;
50 };
51 
52 
53 template <class T>
54 gsStatus gsEigenProblemBase<T>::computeSparse(const index_t number)
55 {
56  if (m_status==gsStatus::AssemblyError)
57  return m_status;
58 
59  #ifdef gsSpectra_ENABLED
60  if (m_options.getInt("solver")==0)
61  return computeSparse_impl<Spectra::GEigsMode::Cholesky>(number);
62  else if (m_options.getInt("solver")==1)
63  return computeSparse_impl<Spectra::GEigsMode::RegularInverse>(number);
64  else if (m_options.getInt("solver")==2)
65  return computeSparse_impl<Spectra::GEigsMode::ShiftInvert>(number);
66  else if (m_options.getInt("solver")==3)
67  return computeSparse_impl<Spectra::GEigsMode::Buckling>(number);
68  else if (m_options.getInt("solver")==4)
69  return computeSparse_impl<Spectra::GEigsMode::Cayley>(number);
70  else
71  {
72  gsWarn<<"Solver index "<<m_options.getInt("solver")<<" unknown.\n";
73  m_status=gsStatus::NotStarted;
74  return m_status;
75  }
76  #else
77  gsWarn<<"Sparse solver is not implemented without gsSpectra. Please compile gismo with Spectra.\n";
78  m_status=gsStatus::NotStarted;
79  return gsStatus::NotStarted;
80  #endif
81 };
82 
83 #ifdef gsSpectra_ENABLED
84 template <class T>
85 template< Spectra::GEigsMode _GEigsMode>
86 typename std::enable_if<_GEigsMode==Spectra::GEigsMode::Cholesky ||
87  _GEigsMode==Spectra::GEigsMode::RegularInverse
88  ,
89  gsStatus>::type
90 gsEigenProblemBase<T>::computeSparse_impl(index_t number)
91 {
92  bool verbose = m_options.getSwitch("verbose");
93  T shift = m_options.getReal("shift");
94 
95  Spectra::SortRule selectionRule = static_cast<Spectra::SortRule>(m_options.getInt("selectionRule"));
96  Spectra::SortRule sortRule = static_cast<Spectra::SortRule>(m_options.getInt("sortRule"));
97 
98  index_t ncvFac = m_options.getInt("ncvFac");
99  T tol = m_options.getReal("tolerance");
100  if (verbose) { gsInfo<<"Solving eigenvalue problem" ; }
101 
102  gsSparseMatrix<T> Atmp;
103  if (shift!=0.0)
104  Atmp = m_A-shift*m_B;
105  else
106  Atmp = m_A;
107 
108  gsSpectraGenSymSolver<gsSparseMatrix<T>,_GEigsMode> solver(Atmp,m_B,number,ncvFac*number);
109 
110  if (verbose) { gsInfo<<"." ; }
111  solver.init();
112  if (verbose) { gsInfo<<"." ; }
113  solver.compute(selectionRule,1000,tol,sortRule);
114 
115  if (solver.info()==Spectra::CompInfo::Successful)
116  {
117  gsDebug<<"Spectra converged in "<<solver.num_iterations()<<" iterations and with "<<solver.num_operations()<<"operations. \n";
118  if (verbose) { gsInfo<<"." ; }
119  m_values = solver.eigenvalues();
120  m_values.array() += shift;
121  if (verbose) { gsInfo<<"." ; }
122  m_vectors = solver.eigenvectors();
123  if (verbose) { gsInfo<<"Finished\n" ; }
124 
125  m_status = gsStatus::Success;
126  }
127  else if (solver.info()==Spectra::CompInfo::NotConverging)
128  {
129  gsWarn<<"Spectra did not converge! Error code: NotConverging\n";
130  m_status = gsStatus::NotConverged;
131  }
132  else if (solver.info()==Spectra::CompInfo::NumericalIssue)
133  {
134  gsWarn<<"Spectra did not converge! Error code: NumericalIssue\n";
135  m_status = gsStatus::SolverError;
136  }
137  else if (solver.info()==Spectra::CompInfo::NotComputed)
138  {
139  gsWarn<<"Spectra did not converge! Error code: NotComputed\n";
140  m_status = gsStatus::SolverError;
141  }
142  else
143  {
144  gsWarn<<"No error code known\n";
145  m_status = gsStatus::OtherError;
146  }
147  return m_status;
148 }
149 #endif
150 
151 #ifdef gsSpectra_ENABLED
152 template <class T>
153 template< Spectra::GEigsMode _GEigsMode>
154 typename std::enable_if<_GEigsMode==Spectra::GEigsMode::ShiftInvert ||
155  _GEigsMode==Spectra::GEigsMode::Buckling ||
156  _GEigsMode==Spectra::GEigsMode::Cayley
157  ,
158  gsStatus>::type
159 gsEigenProblemBase<T>::computeSparse_impl(index_t number)
160 {
161  bool verbose = m_options.getSwitch("verbose");
162  T shift = m_options.getReal("shift");
163 
164  Spectra::SortRule selectionRule = static_cast<Spectra::SortRule>(m_options.getInt("selectionRule"));
165  Spectra::SortRule sortRule = static_cast<Spectra::SortRule>(m_options.getInt("sortRule"));
166 
167  if (selectionRule == Spectra::SortRule::SmallestMagn ) // =4
168  gsWarn<<"Selection Rule 'SmallestMagn' is selected, but for ShiftInvert, Buckling and Cayley it is advised to use 'LargestMagn'!\n";
169  if (selectionRule == Spectra::SortRule::SmallestAlge ) // =7
170  gsWarn<<"Selection Rule 'SmallestAlge' is selected, but for ShiftInvert, Buckling and Cayley it is advised to use 'LargestMagn'!\n";
171 
172  index_t ncvFac = m_options.getInt("ncvFac");
173  T tol = m_options.getReal("tolerance");
174  if (verbose) { gsInfo<<"Solving eigenvalue problem" ; }
175  gsSpectraGenSymShiftSolver<gsSparseMatrix<T>,_GEigsMode> solver(m_A,m_B,number,ncvFac*number,shift);
176  if (verbose) { gsInfo<<"." ; }
177  solver.init();
178  if (verbose) { gsInfo<<"." ; }
179  solver.compute(selectionRule,1000,tol,sortRule);
180 
181  if (solver.info()==Spectra::CompInfo::Successful)
182  {
183  gsDebug<<"Spectra converged in "<<solver.num_iterations()<<" iterations and with "<<solver.num_operations()<<"operations. \n";
184  if (verbose) { gsInfo<<"." ; }
185  m_values = solver.eigenvalues();
186  // m_values.array() += shift;
187  if (verbose) { gsInfo<<"." ; }
188  m_vectors = solver.eigenvectors();
189  if (verbose) { gsInfo<<"Finished\n" ; }
190 
191  m_status = gsStatus::Success;
192  }
193  else if (solver.info()==Spectra::CompInfo::NotConverging)
194  {
195  gsWarn<<"Spectra did not converge! Error code: NotConverging\n";
196  m_status = gsStatus::NotConverged;
197  }
198  else if (solver.info()==Spectra::CompInfo::NumericalIssue)
199  {
200  gsWarn<<"Spectra did not converge! Error code: NumericalIssue\n";
201  m_status = gsStatus::SolverError;
202  }
203  else if (solver.info()==Spectra::CompInfo::NotComputed)
204  {
205  gsWarn<<"Spectra did not converge! Error code: NotComputed\n";
206  m_status = gsStatus::SolverError;
207  }
208  else
209  {
210  gsWarn<<"No error code known\n";
211  m_status = gsStatus::OtherError;
212  }
213  return m_status;
214 };
215 #endif
216 
217 template <class T>
218 gsStatus gsEigenProblemBase<T>::computePower()
219 {
220  if (m_status==gsStatus::AssemblyError)
221  return m_status;
222 
223  bool verbose = m_options.getSwitch("verbose");
224  if (verbose) { gsInfo<<"Solving eigenvalue problem" ; }
225  gsMatrix<T> D = m_A.toDense().inverse() * (m_B);
226 
227  gsVector<T> v(D.cols());
228  v.setOnes();
229  gsVector<T> v_old(D.cols());
230  v_old.setZero();
231 
232  index_t kmax = 100;
233  real_t error,tol = m_options.getReal("tolerance");
234  for (index_t k=0; k!=kmax; k++)
235  {
236  v = D*v;
237  v.normalize();
238 
239  error = (v-v_old).norm();
240 
241  if ( error < tol )
242  {
243  m_status = gsStatus::Success;
244  break;
245  }
246  else if (k==kmax-1)
247  m_status = gsStatus::NotConverged;
248 
249  v_old = v;
250  }
251 
252  m_vectors = v;
253  m_values = (v.transpose() * v) / (v.transpose() * D * v);
254 
255  if (verbose) { gsInfo<<"Finished\n" ; }
256  return m_status;
257 };
258 
259 template <class T>
260 std::vector<std::pair<T,gsMatrix<T>> > gsEigenProblemBase<T>::makeMode(int k) const
261 {
262  std::vector<std::pair<T,gsMatrix<T>> > mode;
263  mode.push_back( std::make_pair( m_values.at(k), m_vectors.col(k) ) );
264  return mode;
265 };
266 
267 } // namespace gismo
Step did not converge.
#define gsDebug
Definition: gsDebug.h:61
Assembly problem in step.
Assembly failed due to an error in the expression (e.g. overflow)
#define index_t
Definition: gsConfig.h:32
gsStatus
Definition: gsStructuralAnalysisTypes.h:20
#define gsWarn
Definition: gsDebug.h:50
#define gsInfo
Definition: gsDebug.h:43
ALM has not started yet.