Spectral Integral Suite in C++
sis.hpp
Go to the documentation of this file.
1 #define lapack_complex_double std::complex<double>
171 #define lapack_complex_float std::complex<float>
172 #ifndef SIS_HPP
173 #define SIS_HPP
174 #endif
175 #ifndef _STL_VECTOR_H
176 #include <vector>
177 #endif
178 #ifndef _GLIBCXX_VALARRAY
179 #include <valarray>
180 #endif
181 #ifndef _GLIBCXX_IOSTREAM
182 #include <iostream>
183 #endif
184 #if !defined _GLIBCXX_CMATH || !defined _GLIBCXX_MATH_H
185 #include <cmath>
186 #endif
187 #ifndef _GLIBCXX_COMPLEX
188 #include <complex>
189 #endif
190 #ifndef _GLIBCXX_NUMERIC_LIMITS
191 #include <limits>
192 #endif
193 #ifndef _GLIBCXX_ALGORITHM
194 #include <algorithm>
195 #endif
196 #ifndef _MKL_DFTI_H_
197 #include <mkl_dfti.h>
198 #endif
199 #ifndef EIGEN_CORE_H
200 #include <eigen3/Eigen/Eigen>
201 #endif
202 #ifndef _TIME_H
203 #include <time.h>
204 #endif
205 #ifdef SIS_USE_FEAST
206 extern "C" {
207 void feastinit_(int *feastparam);
208 }
209 extern "C" {
210 void zfeast_gegv_(int *N, std::complex<double> *A, int *LDA,
211  std::complex<double> *B, int *LDB, int *feastparam,
212  double *epsout, int *loop, double *Emid, double *r, int *M0,
213  std::complex<double> *lambda, std::complex<double> *q,
214  int *mode, double *res, int *info);
215 }
216 #ifndef _STDIO_H_
217 #include <stdio.h>
218 #endif
219 #ifndef _STDLIB_H
220 #include <stdlib.h>
221 #endif
222 #endif
223 #ifdef SIS_USE_LAPACK
224 extern "C" {
225 void dgeev_(char *jobvl, char *jobvr, int *n, double *a, int *lda, double *wr,
226  double *wi, double *vl, int *ldvl, double *vr, int *ldvr,
227  double *work, int *lwork, double *rwork, int *info);
228 }
229 extern "C" {
230 void dggev_(char *jobvl, char *jobvr, int *n, double *a, int *lda, double *b,
231  int *ldb, double *alphar, double *alphai, double *beta, double *vl,
232  int *ldvl, double *vr, int *ldvr, double *wkopt, int *lwork,
233  double *rwork, int *info);
234 }
235 extern "C" {
236 void zgeev_(char *jobvl, char *jobvr, int *n, std::complex<double> *a, int *lda,
237  std::complex<double> *w, std::complex<double> *vl, int *ldvl,
238  std::complex<double> *vr, int *ldvr, std::complex<double> *work,
239  int *lwork, double *rwork, int *info);
240 }
241 extern "C" {
242 void zggev_(char *jobvl, char *jobvr, int *n, std::complex<double> *a, int *lda,
243  std::complex<double> *b, int *ldb, std::complex<double> *alpha,
244  std::complex<double> *beta, std::complex<double> *vl, int *ldvl,
245  std::complex<double> *vr, int *ldvr, std::complex<double> *wkopt,
246  int *lwork, double *rwork, int *info);
247 }
248 #ifndef _STDIO_H_
249 #include <stdio.h>
250 #endif
251 #ifndef _STDLIB_H
252 #include <stdlib.h>
253 #endif
254 #endif
255 
256 int ind = 0;
257 // I define a few useful operator overloads to std::valarray that aren't
258 // inherently defined, like multiplying a complex number with a real valarray.
259 // I place these functions within the same namespace: std.
260 namespace std {
261 
263 template <class T>
264 std::valarray<std::complex<T> > dou2com(const std::valarray<T> &a,
265  const std::valarray<T> &b) {
266  std::valarray<std::complex<T> > temp;
267 int bre;
268  temp.resize(a.size());
269  for (int i = 0; i < a.size(); i++) {
270  temp[i] = std::complex<T>(a[i], b[i]);
271  }
272 
273  // std::cin >> bre;
274  // std::cout << "showing in dou2com " << imag(temp).max() << endl;
275  return temp;
276 
277 };
278 
280 template <class T> valarray<T> real(const valarray<complex<T> > &in) {
281  valarray<T> temp;
282 
283  temp.resize(in.size());
284  for (int i = 0; i < temp.size(); i++) {
285  temp[i] = real(in[i]);
286  }
287  return temp;
288 };
289 
291 template <class T> valarray<T> imag(const valarray<complex<T> > &in) {
292  valarray<T> temp;
293  temp.resize(in.size());
294  for (int i = 0; i < temp.size(); i++) {
295  temp[i] = imag(in[i]);
296  }
297  return temp;
298 };
299 
301 template <class T>
302 std::valarray<std::complex<T> > operator*(std::complex<T> left,
303  std::valarray<T> right) {
304  std::valarray<T> re(right.size()), im(right.size());
305  re = real(left) * right;
306  im = imag(left) * right;
307  return std::dou2com(re, im);
308 }
309 
311 template <class T>
312 std::valarray<std::complex<T> > operator*(const std::valarray<T> &left,
313  const std::complex<T> &right) {
314  std::valarray<T> re(left.size()), im(left.size());
315  re = left * real(right);
316  im = left * imag(right);
317  return std::dou2com(re, im);
318 }
319 
321 template <class T>
322 std::valarray<std::complex<T> > operator+(std::complex<T> left,
323  std::valarray<T> right) {
324  std::valarray<T> re(right.size()), im(right.size());
325  re = real(left) + right;
326  im = imag(left);
327 
328  return std::dou2com(re, im);
329 }
330 
332 template <class T>
333 std::valarray<std::complex<T> > operator+(const std::valarray<T> &left,
334  std::complex<T> right) {
335  std::valarray<T> re(left.size()), im(left.size());
336  re.resize(left.size());
337  im.resize(left.size());
338  re = left + real(right);
339  im = imag(right);
340  return std::dou2com(re, im);
341 }
343 template <class T>
344 std::valarray<std::complex<T> > operator-(std::complex<T> left,
345  std::valarray<T> right) {
346  std::valarray<T> re(right.size()), im(right.size());
347  re.resize(right.size());
348  im.resize(right.size());
349  re = real(left) - right;
350  im = imag(left);
351  return std::dou2com(re, im);
352 }
353 
355 template <class T>
356 std::valarray<std::complex<T> > operator-(const std::valarray<T> &left,
357  const std::complex<T> &right) {
358  std::valarray<T> re(left.size()), im(left.size());
359  re = left - real(right);
360  im = imag(right);
361  return std::dou2com(re, im);
362 }
363 
364 // \brief Multiplying a complex valarray with a real number
365 template <class T>
366 std::valarray<std::complex<T> >
367 operator*(T left, std::valarray<std::complex<T> > right) {
368  std::valarray<T> re(right.size()), im(right.size());
369  im = left * imag(right);
370  re = left * real(right);
371  return std::dou2com(re, im);
372 }
373 
375 template <class T>
376 std::valarray<std::complex<T> >
377 operator*(const std::valarray<std::complex<T> > &left, const T &right) {
378  std::valarray<T> re(left.size()), im(left.size());
379  re = real(left) * right;
380  im = imag(left) * right;
381  return std::dou2com(re, im);
382 }
383 
385 template <class T>
386 std::valarray<std::complex<T> >
387 operator+(T left, std::valarray<std::complex<T> > right) {
388  std::valarray<T> re(right.size()), im(right.size());
389  re = left + real(right);
390  im = imag(right);
391  return std::dou2com(re, im);
392 }
393 
395 template <class T>
396 std::valarray<std::complex<T> >
397 operator+(const std::valarray<std::complex<T> > &left, const T &right) {
398  std::valarray<T> re(left.size()), im(left.size());
399  re = real(left) + right;
400  im = imag(left);
401  return std::dou2com(re, im);
402 }
404 template <class T>
405 std::valarray<std::complex<T> >
406 operator-(T left, std::valarray<std::complex<T> > right) {
407  std::valarray<T> re(right.size()), im(right.size());
408  re = left - real(right);
409  im = -imag(right);
410  return std::dou2com(re, im);
411 }
412 
414 template <class T>
415 std::valarray<std::complex<T> >
416 operator-(const std::valarray<std::complex<T> > &left, const T &right) {
417  std::valarray<T> re(left.size()), im(left.size());
418  re = real(left) - right;
419  im = imag(left);
420  return std::dou2com(re, im);
421 }
422 
424 template <class T>
425 std::valarray<std::complex<T> >
426 operator*(const std::valarray<std::complex<T> > &left,
427  const std::valarray<T> &right) {
428  std::valarray<T> re(right.size()), im(right.size());
429  re = real(left) * right;
430  im = imag(left) * right;
431  return std::dou2com(re, im);
432 }
433 
435 template <class T>
436 std::valarray<std::complex<T> >
437 operator*(const std::valarray<T> &left,
438  const std::valarray<std::complex<T> > &right) {
439  std::valarray<T> re(left.size()), im(left.size());
440  re = left * real(right);
441  im = left * real(right);
442  return std::dou2com(re, im);
443 }
444 
445 string int2str(int i) {
446  string out;
447  stringstream temp;
448  temp << i;
449  return temp.str();
450 };
451 
452 template <class T>
453 valarray<complex<T> > pow(valarray<complex<T> > base, T power) {
454  complex<T> power_ = complex<T>(power, 0.0);
455  valarray<complex<T> > out = pow(base, power_);
456  return out;
457 }
458 
459 }; // namespace std
460 
461 namespace sis {
462 
463 #ifndef PI
464 #define PI 3.141592653589793
465 #endif
466 #define SIS_SINGULAR 1
467 #define SIS_SVD 0
468 #define SIS_SVD_LEFT 1
469 #define SIS_SVD_RIGHT 2
470 #define SIS_PHYS_SPACE 1
471 #define SIS_CHEB_SPACE 0
472 int N = 31;
473 
474 #ifdef SIS_USE_FEAST
475 namespace feast {
477 int M0 = 10;
478 int info = 0;
479 std::complex<double> center(0.0, 0.0);
480 double radius = 10.0;
481 int feastparam[64];
482 void feast_init() { feastinit_(feastparam); }
483 void display() {
484  if (info == 202) {
485  std::cout << "Error: Problem with size of system N" << '\n';
486  } else if (info == 201) {
487  std::cout << "Error: Problem with subspace M0" << '\n';
488  } else if (info == 200) {
489  std::cout << "Error: Problem with Emin, Emax, Emid, r" << '\n';
490  } else if (info == 6) {
491  std::cout << "Warning: FEAST converges but subspace is not bi-orthogonal"
492  << '\n';
493  } else if (info == 5) {
494  std::cout << "Warning: Only stochastic estimation of #eigenvalues returned "
495  "fpm(14)=2"
496  << '\n';
497  } else if (info == 4) {
498  std::cout << "Warning: Only the subspace has been returned using fpm(14)=1"
499  << '\n';
500  } else if (info == 3) {
501  std::cout << "Warning: Size of the subspace M0 is too small (M0<=M)"
502  << '\n';
503  } else if (info == 2) {
504  std::cout << "Warning: No Convergence (#iteration loops>fpm(4))" << '\n';
505  } else if (info == 1) {
506  std::cout << "Warning: No Eigenvalue found in the search interval" << '\n';
507  } else if (info == 0) {
508  std::cout << "Error: Successful exit" << '\n';
509  } else if (info == -1) {
510  std::cout << "Error: Internal error for allocation memory" << '\n';
511  } else if (info == -2) {
512  std::cout << "Error: Internal error of the inner system solver in FEAST "
513  "predefined interfaces"
514  << '\n';
515  } else if (info == -3) {
516  std::cout << "Error: Internal error of the reduced eigenvalue solver. "
517  << "Possible cause for Hermitian problem: matrix B may not be "
518  "positive definite"
519  << '\n';
520  } else {
521  std::cout << "Error: Problem with " << info - 100
522  << "th parameter of feast parameter" << '\n';
523  }
524 }
525 } // namespace feast
526 #endif
527 
528 template <class T> class LinopMat;
529 template <class T> class BcMat;
530 template <class T> class MatGen;
531 template <class T> class SingularValueDecomposition;
532 template <class T> class Discretize;
533 
534 #ifndef SIS_TYPE
535 #define SIS_TYPE double
536 #endif
537 
538 std::valarray<std::complex<SIS_TYPE> > half_shift(N + 1), rev_half_shift(N + 1),
539  yc(N + 1);
540 std::valarray<SIS_TYPE> y(N + 1);
541 Eigen::Matrix<std::complex<SIS_TYPE>, Eigen::Dynamic, Eigen::Dynamic> ycEigen;
542 Eigen::Matrix<SIS_TYPE, Eigen::Dynamic, Eigen::Dynamic> yEigen;
543 
544 template <class T> std::valarray<std::complex<T> > fft(std::valarray<T> in1) {
545  int bre;
546  int n = in1.size();
547  std::valarray<std::complex<T> > out(n);
548  std::valarray<T> zvec(n);
549  zvec = 0.0;
550  out[0] = std::complex<T>(in1[0], 0.0);
551  DFTI_DESCRIPTOR_HANDLE descriptor;
552  MKL_LONG status;
553 
554  status = DftiCreateDescriptor(&descriptor, DFTI_DOUBLE, DFTI_REAL, 1,
555  n); // Specify size and precision
556  // cout<<status<<endl;
557  status = DftiSetValue(descriptor, DFTI_PLACEMENT,
558  DFTI_NOT_INPLACE); // Out of place FFT
559  status = DftiSetValue(descriptor, DFTI_CONJUGATE_EVEN_STORAGE,
560  DFTI_COMPLEX_COMPLEX);
561 
562  // cout<<status<<endl;
563  status = DftiCommitDescriptor(descriptor); // Finalize the descriptor
564  // cout<<status<<endl;
565  status = DftiComputeForward(descriptor, &in1[0],
566  &out[0]); // Compute the Forward FFT
567  // cout<<status<<endl;
568  status = DftiFreeDescriptor(&descriptor); // Free the descriptor
569  // cout<<status<<endl;
570  for (int j = 0; j < n / 2; j++)
571  out[n / 2 + j] = std::conj(out[n / 2 - j]);
572 
573  return out;
574 };
575 
576 template <class T>
577 std::valarray<std::complex<T> > fft(std::slice_array<T> in1) {
578  return fft(std::valarray<T>(in1));
579 }
580 
581 template <class T>
582 std::valarray<T> ifft_cs(std::valarray<std::complex<T> > in)
583 // For conjugate symmetric
584 {
585  int bre;
586  int n = in.size();
587  std::valarray<T> out(2 * n);
588  out[0] = real(in[0]);
589  std::valarray<std::complex<T> > in1(std::complex<T>(0.0, 0.0), n + 1);
590  in1[std::slice(0, n, 1)] = in;
591  DFTI_DESCRIPTOR_HANDLE descriptor;
592  MKL_LONG status;
593 
594  status = DftiCreateDescriptor(&descriptor, DFTI_DOUBLE, DFTI_REAL, 1,
595  2 * n); // Specify size and precision
596  // std::cout<<status<<endl;
597  status = DftiSetValue(descriptor, DFTI_PLACEMENT,
598  DFTI_NOT_INPLACE); // Out of place FFT
599  status = DftiSetValue(descriptor, DFTI_CONJUGATE_EVEN_STORAGE,
600  DFTI_COMPLEX_COMPLEX);
601  // cout<<status<<endl;
602  status = DftiCommitDescriptor(descriptor); // Finalize the descriptor
603  // cout<<status<<endl;
604  status = DftiComputeBackward(descriptor, &in1[0],
605  &out[0]); // Compute the Backward FFT
606  // cout<<status<<endl;
607  status = DftiFreeDescriptor(&descriptor); // Free the descriptor
608  // std::cout<<status<<endl;
609  out = out / T(2 * n); // need to manually scale
610  return out;
611 };
612 
613 template <class T>
614 std::valarray<T> ifft_cs(std::slice_array<std::complex<T> > in) {
615  return ifft_cs(std::valarray<std::complex<T> >(in));
616 }
617 template <class T> std::valarray<T> dct(const std::valarray<T> &x) {
618  int n = x.size();
619  int bre;
620  std::valarray<T> y(2 * n), v(n);
621  std::valarray<std::complex<T> > V(n);
622  for (int i = 0; i < n; i++)
623  y[i] = x[i];
624 
625  for (int i = n; i < 2 * n; i++)
626  y[i] = x[2 * n - i - 1];
627 
628  for (int i = 0; i < n; i++)
629  v[i] = y[2 * i];
630  V = fft(v);
631  return 2.0 * real(std::valarray<std::complex<T> >(half_shift * V)) / T(n);
632 };
633 
634 template <class T> std::valarray<T> dct(const std::slice_array<T> &x) {
635  return dct(std::valarray<T>(x));
636 };
637 
638 template <class T> std::valarray<T> idct(const std::valarray<T> &u) {
639  int n = u.size();
640  int bre;
641  std::valarray<T> temp_u(n + 1);
642  std::valarray<T> x(n), v(n);
643  temp_u = 0.0;
644  temp_u[std::slice(0, n, 1)] = u;
645  std::valarray<std::complex<T> > V(n);
646  for (int i = 0; i < n; i++) {
647  V[i] =
648  std::complex<T>(temp_u[i], 0.0) - std::complex<T>(0.0, temp_u[n - i]);
649  }
650  V = std::complex<T>(0.5, 0.0) * rev_half_shift * V;
651 
652  v = ifft_cs(std::valarray<std::complex<T> >(V[std::slice(0, n / 2, 1)]));
653 
654  for (int i = 0; i < (n + 1) / 2; i++)
655  x[2 * i] = v[i];
656  for (int i = (n + 1) / 2; i < n; i++)
657  x[2 * n - 2 * i - 1] = v[i];
658  return x * T(n);
659 };
660 
661 template <class T> std::valarray<T> idct(const std::slice_array<T> &u) {
662  return idct(std::valarray<T>(u));
663 };
664 
665 template <class T>
666 std::valarray<std::complex<T> > dct(const std::valarray<std::complex<T> > &in) {
667  int n = in.size() - 1;
668  std::valarray<T> inr(n + 1), ini(n + 1);
669  inr = real(in);
670  ini = imag(in);
671  inr = dct(inr);
672  ini = dct(ini);
673  return dou2com(inr, ini);
674 };
675 
676 template <class T>
677 std::valarray<std::complex<T> >
678 dct(const std::slice_array<std::complex<T> > &in) {
679  return dct(std::valarray<std::complex<T> >(in));
680 };
681 
682 template <class T>
683 std::valarray<std::complex<T> >
684 idct(const std::valarray<std::complex<T> > &in) {
685  int n = in.size() - 1;
686 
687  std::valarray<T> inr(in.size()), ini(in.size());
688  inr = std::real(in);
689  ini = std::imag(in);
690  inr = idct(inr);
691  ini = idct(ini);
692  return dou2com(inr, ini);
693 };
694 
695 template <class T>
696 std::valarray<std::complex<T> >
697 idct(const std::slice_array<std::complex<T> > &in) {
698  return idct(std::valarray<std::complex<T> >(in));
699 };
700 
701 
702 
707 template <class T>
708 std::valarray<std::complex<T> > fft2(std::valarray<T> in1, int Nx, int Nz) {
709  int bre;
710  std::valarray<std::complex<T> > result(Nx * (Nz / 2 + 1)), out(Nx * Nz / 2);
711  result[0] = std::complex<T>(in1[0], 0.0);
712  DFTI_DESCRIPTOR_HANDLE descriptor;
713 
714  MKL_LONG status = 0;
715  DFTI_DESCRIPTOR_HANDLE hand = 0;
716  MKL_LONG n[2];
717  n[0] = Nx;
718  n[1] = Nz;
719  status = DftiCreateDescriptor(&hand, DFTI_DOUBLE, DFTI_REAL, 2, n);
720  status = DftiSetValue(hand, DFTI_PLACEMENT, DFTI_NOT_INPLACE);
721  status =
722  DftiSetValue(hand, DFTI_CONJUGATE_EVEN_STORAGE, DFTI_COMPLEX_COMPLEX);
723  MKL_LONG rs[3];
724  rs[0] = 0;
725  rs[1] = Nz;
726  rs[2] = 1;
727  status = DftiSetValue(hand, DFTI_INPUT_STRIDES, rs);
728  MKL_LONG cs[3];
729  cs[0] = 0;
730  cs[1] = Nz / 2 + 1;
731  cs[2] = 1;
732  status = DftiSetValue(hand, DFTI_OUTPUT_STRIDES, cs);
733  status = DftiCommitDescriptor(hand);
734  status = DftiComputeForward(hand, &in1[0], &result[0]);
735  DftiFreeDescriptor(&hand);
736  for (int j = 0; j < Nx; j++) {
737  for (int k = 0; k < Nz / 2; k++) {
738  out[j * (Nz / 2) + k] = result[j * (Nz / 2 + 1) + k];
739  }
740  }
741  // Set values at Nyquist to zero:
742  {
743  int j = Nx / 2;
744  for (int k = 0; k < Nz / 2; k++) {
745  out[j * (Nz / 2) + k] = 0.0;
746  }
747  }
748  // for (int j = 0; j < Nx; j ++){
749  // for (int k = 0; k < Nz /2; k ++){
750  // std::cout << out[j*(Nz /2) + k] << " ";
751  // }
752  // std::cout << '\n';
753  // }
754  return out;
755 };
756 
764 template <class T>
765 std::valarray<T> ifft2_cs(std::valarray<std::complex<T> > in1, int Nx, int Nz) {
766  int bre;
767  std::valarray<std::complex<T> > in(Nx * (Nz / 2 + 1));
768  std::valarray<T> out(Nx * Nz);
769  in = std::complex<T>(0.0, 0.0);
770  for (int j = 0; j < Nx; j++) {
771  for (int k = 0; k < Nz / 2; k++) {
772  in[j * (Nz / 2 + 1) + k] = in1[j * (Nz / 2) + k];
773  }
774  }
775 
776  // std::cout << "showing the before ifft" << '\n';
777  // for (int j = 0; j < Nx; j ++){
778  // for (int k = 0; k < Nz /2 + 1; k ++){
779  // std::cout << in[j * (Nz/2 + 1) + k] << " " ;
780  // }
781  // std::cout << "\n" << '\n';
782  // }
783  // std::cin >> bre;
784 
785  MKL_LONG status = 0;
786  DFTI_DESCRIPTOR_HANDLE hand = 0;
787  MKL_LONG n[2];
788  n[0] = Nx;
789  n[1] = Nz;
790  status = DftiCreateDescriptor(&hand, DFTI_DOUBLE, DFTI_REAL, 2, n);
791  status = DftiSetValue(hand, DFTI_PLACEMENT, DFTI_NOT_INPLACE);
792  status =
793  DftiSetValue(hand, DFTI_CONJUGATE_EVEN_STORAGE, DFTI_COMPLEX_COMPLEX);
794  MKL_LONG cs[3];
795  cs[0] = 0;
796  cs[1] = Nz / 2 + 1;
797  cs[2] = 1;
798  status = DftiSetValue(hand, DFTI_INPUT_STRIDES, cs);
799  MKL_LONG rs[3];
800  rs[0] = 0;
801  rs[1] = Nz;
802  rs[2] = 1;
803  status = DftiSetValue(hand, DFTI_OUTPUT_STRIDES, rs);
804  status = DftiCommitDescriptor(hand);
805  status = DftiComputeBackward(hand, &in[0], &out[0]);
806  DftiFreeDescriptor(&hand);
807  out = out / double(Nx * Nz);
808  // for (int j = 0; j < Nx; j ++){
809  // for (int k = 0; k < Nz; k ++){
810  // std::cout << out[j*(Nz) + k] << " ";
811  // }
812  // std::cout << '\n';
813  // }
814  return out;
815 };
816 
817 template <class T>
818 std::valarray<std::complex<T> > fft2(std::slice_array<T> in1, int Nx, int Nz) {
819  return fft2(std::valarray<T>(in1), Nx, Nz);
820 }
821 
822 template <class T>
823 std::valarray<T> ifft2_cs(std::slice_array<std::complex<T> > in, int Nx,
824  int Nz) {
825  return ifft2_cs(std::valarray<std::complex<T> >(in), Nx, Nz);
826 }
827 
828 
859 // an 8 x 8 matrix is thus converted to a 12 x 12 matrix according to the 3/2 rule
860 template <class T>
861 std::valarray<std::complex<T> > dealias_prod_2D(std::valarray<std::complex<T> > a, std::valarray<std::complex<T> > b, int Nx, int Nz){
862  std::valarray<std::complex<T> > tempa(0.0,(3*Nx/2) * (3*(Nz/2)/2)), tempb(0.0,(3*Nx/2) * (3*(Nz/2)/2));
863 
864  // Now assign values to the new matrices:
865  for (int i = 0; i< Nx/2; i++) {
866  tempa[std::slice(i*3*Nz/4,Nz/2,1)] = a[std::slice(i*Nz/2,Nz/2,1)];
867  tempa[std::slice(i*3*Nz/4 + Nx*3*Nz/4 ,Nz/2,1)] = a[std::slice(i*Nz/2+Nx*Nz/4,Nz/2,1)];
868  tempb[std::slice(i*3*Nz/4,Nz/2,1)] = b[std::slice(i*Nz/2,Nz/2,1)];
869  tempb[std::slice(i*3*Nz/4 + Nx*3*Nz/4 ,Nz/2,1)] = b[std::slice(i*Nz/2+Nx*Nz/4,Nz/2,1)];
870 }
871 
872 // take to real space:
873 std::valarray<T> tempar((3*(Nx)/2) * (3*(Nz)/2));
874 std::valarray<T> tempbr((3*(Nx)/2) * (3*(Nz)/2));
875 
876 tempar = sis::ifft2_cs(tempa,3*Nx/2,3*Nz/2);
877 tempbr = sis::ifft2_cs(tempb,3*Nx/2,3*Nz/2);
878 
879 // Multiply them:
880 tempar = tempar * tempbr;
881 
882 // Go back to Fourier space:
883 tempa = sis::fft2(tempar,3*Nx/2,3*Nz/2);
884 
885 // Remove zero padding:
886 for (int i = 0; i< Nx/2; i++){
887  a[std::slice(i*Nz/2,Nz/2,1)] = tempa[std::slice(i*3*Nz/4,Nz/2,1)];
888  a[std::slice(i*Nz/2+Nx*Nz/4,Nz/2,1)] = tempa[std::slice(i*3*Nz/4 + Nx*3*Nz/4 ,Nz/2,1)];
889 }
890 // Rescaling needed due to zero padding:
891 a = a*std::complex<T>(9.0/4.0,0.0);
892 return a;
893 }
894 
898 
899 template <class T>
900 std::complex<T>
901 size(const Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> &in) {
902  return std::complex<T>(in.rows(), in.cols());
903 }
904 
905 template <class T>
906 std::complex<T>
907 size(const Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> &in) {
908  return std::complex<T>(in.rows(), in.cols());
909 }
910 
912 template <class T> void disp(std::valarray<T> in) {
913  for (int i = 0; i < in.size(); i++) {
914  std::cout << in[i] << "\n";
915  }
916 };
917 
920 template <class T> void setChebPts(std::valarray<T> &in) {
921  in.resize(N + 1);
922  for (int i = 0; i < N + 1; i++)
923  in[i] = cos(M_PI * (i + 0.5) / (N + 1.0));
924 };
925 
929 template <class T> void setChebPts(std::valarray<std::complex<T> > &in) {
930  in.resize(N + 1);
931  for (int i = 0; i < N + 1; i++)
932  in[i] = std::complex<T>(cos(PI * (i + 0.5) / (N + 1.0)), 0.0);
933 };
934 
938 template <class T> void setChebPts(Eigen::Array<T, Eigen::Dynamic, 1> &in) {
939  in.resize(N + 1);
940  for (int i = 0; i < N + 1; i++)
941  in[i] = cos(PI * (i + 0.5) / (N + 1.0));
942 };
943 
947 template <class T>
948 void setChebPts(Eigen::Array<std::complex<T>, Eigen::Dynamic, 1> &in) {
949  in.resize(N + 1);
950  for (int i = 0; i < N + 1; i++)
951  in[i] = std::complex<T>(cos(PI * (i + 0.5) / (N + 1.0)), 0.0);
952 };
953 
954 void sis_setup() {
955  std::complex<SIS_TYPE> ii;
956  ii = std::complex<SIS_TYPE>(0.0, 1.0);
957  half_shift.resize(N + 1);
958  rev_half_shift.resize(N + 1);
959  yEigen.resize(N + 1, 1);
960  ycEigen.resize(N + 1, 1);
961  y.resize(N + 1);
962  yc.resize(N + 1);
963  setChebPts(y);
964  setChebPts(yc);
965  for (int i = 0; i < N + 1; i++) {
966  half_shift[i] =
967  exp(-ii * std::complex<SIS_TYPE>(M_PI * i / (2.0 * (N + 1)), 0.0));
968  rev_half_shift[i] =
969  exp(ii * std::complex<SIS_TYPE>(M_PI * i / (2.0 * (N + 1)), 0.0));
970  }
971 
972  for (int i = 0; i < N + 1; i++) {
973  yEigen(i, 0) = y[i];
974  ycEigen(i, 0) = yc[i];
975  }
976 
977  // IMPORTANT: The values assigned to half_shift and rev_half_shift, must
978  // never be changed in any header/ the main program. These are global
979  // variables ONLY for reading, not for writing into.
980  // Rewriting on these can cause data races with unknown behavior.
981 }
982 
985 template <class T>
986 Eigen::Matrix<T, Eigen::Dynamic, 1>
987 diff(const Eigen::Matrix<T, Eigen::Dynamic, 1> &u) {
988  int n = u.size() - 1;
989  Eigen::Matrix<T, Eigen::Dynamic, 1> du(n + 1);
990  du[n - 1] = 2.0 * n * u[n];
991  // cout<<n-1<<"\t"<<du[n-1]<<endl;
992 // std::cout << "here" << '\n' << std::flush;
993  for (int i = 1; i < (n + 1) / 2; i++) {
994  du[n - (2 * i + 1)] =
995  du[n - (2 * i - 1)] + 2.0 * (n - 2 * i) * u[n - 2 * i];
996  }
997  du[n] = 0.0;
998  for (int i = 1; i < (n + 1) / 2; i++) {
999  du[n - 2 * i] =
1000  du[n - 2 * (i - 1)] + 2.0 * (n - (2 * i - 1)) * u[n + 1 - 2 * i];
1001  }
1002  return du;
1003 };
1004 
1007 template <class T> std::valarray<T> diff(const std::valarray<T> &u) {
1008  int n = u.size() - 1;
1009  std::valarray<T> du(n + 1);
1010  du[n - 1] = 2.0 * n * u[n];
1011  // cout<<n-1<<"\t"<<du[n-1]<<endl;
1012 
1013  for (int i = 1; i < (n + 1) / 2; i++) {
1014  du[n - (2 * i + 1)] =
1015  du[n - (2 * i - 1)] + 2.0 * (n - 2 * i) * u[n - 2 * i];
1016  }
1017  du[n] = 0.0;
1018  for (int i = 1; i < (n + 1) / 2; i++) {
1019  du[n - 2 * i] =
1020  du[n - 2 * (i - 1)] + 2.0 * (n - (2 * i - 1)) * u[n + 1 - 2 * i];
1021  }
1022  return du;
1023 };
1024 
1029 template <class T>
1030 Eigen::Matrix<T, Eigen::Dynamic, 1>
1031 integ(const Eigen::Matrix<T, Eigen::Dynamic, 1> &u) {
1032  int n = u.size() - 1;
1033  int i, neve, nodd;
1034  Eigen::Matrix<T, Eigen::Dynamic, 1> I1v(u.size());
1035  I1v.setConstant(0.0);
1036  neve = (n + 1) / 2;
1037  nodd = neve;
1038 
1039  // split into eve and odd parts
1040  Eigen::Matrix<T, Eigen::Dynamic, 1> uodd(nodd), ueve(neve);
1041  uodd.setConstant(0.0);
1042  ueve.setConstant(0.0);
1043  for (i = 0; i < neve; i++)
1044  ueve[i] = u[2 * i];
1045 
1046  for (i = 0; i < nodd; i++)
1047  uodd[i] = u[2 * i + 1];
1048 
1049  I1v[0] = uodd[0] / 4.0;
1050 
1051  for (i = 1; i < neve; i++)
1052  I1v[2 * i] = (uodd[i - 1] - uodd[i]) / (4.0 * i);
1053 
1054  for (i = 0; i < nodd - 1; i++)
1055  I1v[2 * i + 1] = (ueve[i] - ueve[i + 1]) / (4 * i + 2.0);
1056 
1057  I1v[2 * i + 1] = ueve[i] / (4.0 * i + 2.0);
1058 
1059  return I1v;
1060 };
1061 
1066 template <class T> std::valarray<T> integ(const std::valarray<T> &u) {
1067  int n = u.size() - 1;
1068  int i, neve, nodd;
1069  std::valarray<T> I1v(u.size());
1070  I1v = 0.0;
1071  neve = (n + 1) / 2;
1072  nodd = neve;
1073 
1074  // split into eve and odd parts
1075  std::valarray<T> uodd(nodd), ueve(neve);
1076  uodd = 0.0;
1077  ueve = 0.0;
1078  for (i = 0; i < neve; i++)
1079  ueve[i] = u[2 * i];
1080 
1081  for (i = 0; i < nodd; i++)
1082  uodd[i] = u[2 * i + 1];
1083 
1084  I1v[0] = uodd[0] / 4.0;
1085 
1086  for (i = 1; i < neve; i++)
1087  I1v[2 * i] = (uodd[i - 1] - uodd[i]) / (4.0 * i);
1088 
1089  for (i = 0; i < nodd - 1; i++)
1090  I1v[2 * i + 1] = (ueve[i] - ueve[i + 1]) / (4 * i + 2.0);
1091 
1092  I1v[2 * i + 1] = ueve[i] / (4.0 * i + 2.0);
1093 
1094  return I1v;
1095 };
1096 
1097 template <class T>
1098 Eigen::Array<T, Eigen::Dynamic, 1>
1099 integ(const Eigen::Array<T, Eigen::Dynamic, 1> &u) {
1100  int n = u.size() - 1;
1101  int i, neve, nodd;
1102  Eigen::Matrix<T, Eigen::Dynamic, 1> I1v(u.size());
1103  I1v.setConstant(0.0);
1104  neve = (n + 1) / 2;
1105  nodd = neve;
1106 
1107  // split into eve and odd parts
1108  Eigen::Matrix<T, Eigen::Dynamic, 1> uodd(nodd), ueve(neve);
1109  uodd.setConstant(0.0);
1110  ueve.setConstant(0.0);
1111  for (i = 0; i < neve; i++)
1112  ueve[i] = u[2 * i];
1113 
1114  for (i = 0; i < nodd; i++)
1115  uodd[i] = u[2 * i + 1];
1116 
1117  I1v[0] = uodd[0] / 4.0;
1118 
1119  for (i = 1; i < neve; i++)
1120  I1v[2 * i] = (uodd[i - 1] - uodd[i]) / (4.0 * i);
1121 
1122  for (i = 0; i < nodd - 1; i++)
1123  I1v[2 * i + 1] = (ueve[i] - ueve[i + 1]) / (4 * i + 2.0);
1124 
1125  I1v[2 * i + 1] = ueve[i] / (4.0 * i + 2.0);
1126 
1127  return I1v;
1128 };
1129 
1131 template <class T>
1132 Eigen::Array<std::complex<T>, Eigen::Dynamic, 1>
1133 dou2com(const Eigen::Array<T, Eigen::Dynamic, 1> &a,
1134  const Eigen::Array<T, Eigen::Dynamic, 1> &b) {
1135  Eigen::Array<std::complex<T>, Eigen::Dynamic, 1> temp;
1136  temp.resize(a.size());
1137  for (int i = 0; i < a.size(); i++) {
1138  temp[i] = std::complex<T>(a[i], b[i]);
1139  }
1140  return temp;
1141 };
1142 
1143 
1149 
1150 template <class T> class Chebfun {
1151 private:
1152 public:
1156  std::valarray<T> v;
1162  v.resize(N + 1);
1163  for (int i = 0; i < N + 1; i++)
1164  v[i] = cos(PI * (i + 0.5) / (N + 1.0));
1165  };
1167  Chebfun(const std::valarray<T> &in) {
1168  if (in.size() != N + 1) {
1169  std::cout << "Input size for Chebfun has to be sis::N +1. If you set "
1170  "sis::N = 11, then value input valarray size must be N+1.\n "
1171  "Exiting ...\n ";
1172  exit(1);
1173  }
1174  v = in;
1176  };
1178  Chebfun(const Eigen::Array<T, Eigen::Dynamic, Eigen::Dynamic> &in) {
1179  int bre;
1180 
1181  v.resize(in.size());
1182  if (in.size() != N + 1) {
1183  std::cout << "Input size for Chebfun has to be sis::N +1. If you set "
1184  "sis::N = 11, then value input valarray size must be N+1.\n "
1185  "Exiting ...\n ";
1186  exit(1);
1187  }
1188  for (int i = 0; i < in.size(); i++) {
1189  v[i] = in(i, 0);
1190  }
1192  };
1193 
1194  /* /// \brief constructor by an input Eigen::Matrix<T,Eigen::Dynamic,1>
1195  Chebfun(const Eigen::Matrix<T, Eigen::Dynamic, 1> &in) {
1196  int bre;
1197  if (in.size() != N + 1) {
1198  std::cout << "Input size for Chebfun has to be sis::N +1. If you set "
1199  "sis::N = 11, then value input valarray size must be N+1.\n
1200  " "Exiting ...\n "; exit(1);
1201  }
1202  for (int i = 0; i < in.size(); i++) {
1203  v[i] = in[i];
1204  }
1205  dct_flag = SIS_PHYS_SPACE;
1206  pf = fftw_plan_r2r_1d(N + 1, &v[0], &v[0], FFTW_REDFT10, FFTW_ESTIMATE);
1207  pb = fftw_plan_r2r_1d(N + 1, &v[0], &v[0], FFTW_REDFT01, FFTW_ESTIMATE);
1208  };*/
1210  Chebfun(const Chebfun &in) {
1211  v = in.v;
1212  dct_flag = in.dct_flag;
1213  }
1214 
1217  void p2c() {
1218 
1219  if (dct_flag == SIS_PHYS_SPACE) {
1220  int n = v.size();
1221  std::valarray<T> y(2 * n), vd(n);
1222  std::valarray<std::complex<T> > V(n);
1223  for (int i = 0; i < n; i++)
1224  y[i] = v[i];
1225  for (int i = n; i < 2 * n; i++)
1226  y[i] = v[2 * n - i - 1];
1227 
1228  for (int i = 0; i < n; i++)
1229  vd[i] = y[2 * i];
1230  V = fft(vd);
1231  DFTI_DESCRIPTOR_HANDLE descriptor;
1232  MKL_LONG status;
1233 
1234  status = DftiCreateDescriptor(&descriptor, DFTI_DOUBLE, DFTI_REAL, 1, n);
1235 
1236  status = DftiSetValue(descriptor, DFTI_PLACEMENT,
1237  DFTI_NOT_INPLACE);
1238  status = DftiSetValue(descriptor, DFTI_CONJUGATE_EVEN_STORAGE, DFTI_COMPLEX_COMPLEX);
1239 
1240  status = DftiCommitDescriptor(descriptor);
1241  status = DftiComputeForward(descriptor, &vd[0], &V[0]);
1242  status = DftiFreeDescriptor(&descriptor);
1243  for (int j = 0; j < n / 2; j++)
1244  V[n / 2 + j] = std::conj(V[n / 2 - j]);
1245  v = 2.0 * std::real(std::valarray<std::complex<T> >(half_shift * V)) / T(n);
1246  }
1247  else
1248  {
1249  std::cout << "In Cheb-space. Can't move to Cheb-space\n";
1250  exit(1);
1251  }
1253  };
1254 
1257  void c2p() {
1258  if (dct_flag == SIS_CHEB_SPACE) {
1259  int n = v.size();
1260  std::valarray<T> temp_u(n + 1);
1261  std::valarray<T> x(n), vd(n);
1262  vd[0] = 0.0;
1263  temp_u = 0.0;
1264  temp_u[std::slice(0, n, 1)] = v;
1265  std::valarray<std::complex<T> > V(n);
1266  for (int i = 0; i < n; i++)
1267  {
1268  V[i] =
1269  std::complex<T>(temp_u[i], 0.0) - std::complex<T>(0.0, temp_u[n - i]);
1270  }
1271  V = std::complex<T>(0.5, 0.0) * rev_half_shift * V;
1272 
1273  std::valarray<std::complex<T> > in1(std::complex<T>(0.0, 0.0), n / 2 + 1);
1274  in1[std::slice(0, n / 2, 1)] = V[std::slice(0, n / 2, 1)];
1275 
1276  DFTI_DESCRIPTOR_HANDLE descriptor;
1277  MKL_LONG status;
1278 
1279  status = DftiCreateDescriptor(&descriptor, DFTI_DOUBLE, DFTI_REAL, 1, n);
1280  status = DftiSetValue(descriptor, DFTI_PLACEMENT, DFTI_NOT_INPLACE);
1281  status = DftiSetValue(descriptor, DFTI_CONJUGATE_EVEN_STORAGE, DFTI_COMPLEX_COMPLEX);
1282  status = DftiCommitDescriptor(descriptor);
1283  status = DftiComputeBackward(descriptor, &in1[0], &vd[0]);
1284  status = DftiFreeDescriptor(&descriptor);
1285  for (int i = 0; i < (n + 1) / 2; i++)
1286  v[2 * i] = vd[i];
1287  for (int i = (n + 1) / 2; i < n; i++)
1288  v[2 * n - 2 * i - 1] = vd[i];
1289  } else {
1290  std::cout << "In Physical-space. Can't move to Physical-space\n";
1291  exit(1);
1292  }
1294  };
1295 
1297  Eigen::Array<T, Eigen::Dynamic, 1> ev() {
1298  Eigen::Array<T, Eigen::Dynamic, 1> temp;
1299  temp.resize(v.size());
1300  for (int i = 0; i < v.size(); i++) {
1301  temp[i] = v[i];
1302  }
1303  return temp;
1304  }
1305 
1309  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> MultMat() {
1310  int bre;
1311  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> toep(N + 1, N + 1),
1312  hank(N + 1, N + 1);
1313  toep.setConstant(0.0);
1314  hank.setConstant(0.0);
1315  if (dct_flag == SIS_PHYS_SPACE) {
1316  p2c();
1317  }
1318  Eigen::Array<T, Eigen::Dynamic, 1> v_arr;
1319  v_arr.resize(v.size());
1320  for (int i = 0; i < v.size(); i++) {
1321  v_arr[i] = v[i];
1322  }
1323  Eigen::Matrix<T, Eigen::Dynamic, 1> vec(N + 1);
1324  vec.setConstant(0.0);
1325  vec.block(0, 0, N + 1, 1) = v_arr.matrix();
1326  for (int i = 0; i < N + 1; i++) {
1327  toep.block(i, i, 1, N + 1 - i) =
1328  vec.block(0, 0, N + 1 - i, 1).transpose();
1329  }
1330 
1331  toep = toep.eval() + toep.transpose().eval();
1332  toep.diagonal() = (toep.diagonal() / 2.0).eval();
1333 
1334  hank.setConstant(0.0);
1335  for (int i = 1; i < N + 1; i++) {
1336  hank.block(i, 0, 1, N - i) = vec.block(i, 0, N - i, 1).transpose();
1337  }
1338 
1339  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> out;
1340  out = 0.5 * (toep + hank);
1341  return out.transpose();
1342  }
1343 
1345  void operator=(T right) {
1346  if (dct_flag == SIS_CHEB_SPACE) {
1347  v = 0.0;
1348  v[0] = 2.0 * right;
1349  } else {
1350  v = right;
1351  }
1352  }
1353 
1355  void operator=(const Chebfun &right) {
1356  v = right.v;
1357  dct_flag = right.dct_flag;
1358  }
1359 
1361  void operator=(const Eigen::Matrix<T, Eigen::Dynamic, 1> &right) {
1362  for (int i = 0; i < N + 1; i++) {
1363  v[i] = right[i];
1364  }
1365  }
1366 
1368  void operator=(const std::valarray<T> &right) { v = right; }
1369 
1372  void operator+=(const T &right) {
1373  if (this->dct_flag == SIS_CHEB_SPACE) {
1374  v[0] += 2.0 * right;
1375  } else {
1376  v += right;
1377  }
1378  }
1379 
1382  void operator+=(Chebfun right) {
1383  if (dct_flag == right.dct_flag) {
1384  v += right.v;
1385  } else {
1386  if (dct_flag == SIS_PHYS_SPACE) {
1387  right.c2p();
1388  v += right.v;
1389  right.p2c();
1390  } else {
1391  right.p2c();
1392  v += right.v;
1393  right.c2p();
1394  }
1395  }
1396  }
1398  // void operator=(const Eigen::Array<T, Eigen::Dynamic, 1> &right) {
1399  // this->v = right;
1400  //}
1402  T operator()(const T &a) {
1403  if (a > 1 || a < -1) {
1404  std::cout << "Error: Cannot evaluate a Chebfun outside the domain"
1405  << '\n';
1406  exit(1);
1407  }
1408  std::valarray<T> k(N + 1);
1409  for (int i = 0; i < N + 1; i++) {
1410  k[i] = double(i);
1411  }
1412  k = cos(k * acos(a));
1413  k[0] = 0.5 * k[0];
1414  if (dct_flag == SIS_PHYS_SPACE) {
1415  p2c();
1416  k = k * v;
1417  c2p();
1418  return (k.sum());
1419  } else {
1420  k = k * v;
1421  return k.sum();
1422  }
1423  }
1424 
1428  Chebfun<T> temp;
1429 
1430  if (dct_flag == SIS_PHYS_SPACE) {
1431  p2c();
1432  temp.dct_flag = SIS_CHEB_SPACE;
1433  temp.v = integ(v);
1434  c2p();
1435  temp.c2p();
1436  return temp;
1437  } else {
1438  v = integ(v);
1439  temp.dct_flag = SIS_CHEB_SPACE;
1440  return temp;
1441  }
1442  }
1444  T L2norm() {
1445  Chebfun<T> temp;
1446  temp.dct_flag = SIS_PHYS_SPACE;
1447  if (dct_flag == SIS_PHYS_SPACE) {
1448  temp.v = v * v;
1449  } else {
1450  c2p();
1451  temp.v = v * v;
1452  p2c();
1453  }
1454  temp.p2c();
1455  temp.v = integ(temp.v);
1456 
1457  T ans = (temp.operator()(1) - temp.operator()(-1)) / 2.0;
1458  return ans;
1459  };
1460 
1462  if (abs(v[N - 1] + v[N]) / 2 < abs(std::numeric_limits<T>::epsilon())) {
1463  return true;
1464  } else {
1465  return false;
1466  }
1467  }
1469  if (abs(v[N / 2] + v[N / 2 + 1]) / 2 <
1470  abs(std::numeric_limits<T>::epsilon())) {
1471  return true;
1472  } else {
1473  return false;
1474  }
1475  }
1478  T trunc() { return abs(v[N] + v[N - 1]) / 2.0; }
1479 
1480  //~Chebfun(){
1481  // v.~valarray();
1482  //}
1483 };
1484 
1486 template <class T> Chebfun<T> conj(Chebfun<T> in) { return in; };
1487 
1489 template <class T> class Chebfun<std::complex<T> > {
1490 private:
1491 public:
1495  std::valarray<std::complex<T> > v;
1501  v.resize(N + 1);
1502  for (int i = 0; i < N + 1; i++) {
1503  v[i] = cos(PI * (i + 0.5) / (N + 1.0));
1504  }
1505  };
1507  Chebfun(const std::valarray<std::complex<T> > &in) {
1508  if (in.size() != N + 1) {
1509  std::cout << "Input size for Chebfun has to be sis::N +1. If you set "
1510  "sis::N = 11, then value input valarray size must be N+1.\n "
1511  "Exiting ...\n ";
1512  exit(1);
1513  }
1514  v = in;
1516  };
1518  Chebfun(const Eigen::Array<std::complex<T>, Eigen::Dynamic, 1> &in) {
1519  v.resize(in.size());
1520  if (in.size() != N + 1) {
1521  std::cout << "Input size for Chebfun has to be sis::N +1. If you set "
1522  "sis::N = 11, then value input valarray size must be N+1.\n "
1523  "Exiting ...\n ";
1524  exit(1);
1525  }
1526  for (int i = 0; i < in.size(); i++) {
1527  v[i] = in[i];
1528  }
1530  };
1531 
1533  Chebfun(const Eigen::Matrix<std::complex<T>, Eigen::Dynamic, 1> &in) {
1534  v.resize(N + 1);
1535  if (in.size() != N + 1) {
1536  std::cout << "Input size for Chebfun has to be sis::N +1. If you set "
1537  "sis::N = 11, then value input valarray size must be N+1.\n "
1538  "Exiting ...\n ";
1539  exit(1);
1540  }
1541  for (int i = 0; i < in.size(); i++) {
1542  v[i] = in[i];
1543  }
1545  };
1546 
1548  Chebfun(const Chebfun<std::complex<T> > &in) {
1549  v = in.v;
1550  dct_flag = in.dct_flag;
1551  }
1552 
1555  void p2c()
1556  {
1557  if (dct_flag == SIS_PHYS_SPACE)
1558  {
1559  std::valarray<T> vr(v.size()), vi(v.size());
1560  int n = v.size();
1561  vr = std::real(v);
1562  vi = std::imag(v);
1563  std::valarray<T> y(2 * n), vd(n);
1564  std::valarray<std::complex<T> > V(n);
1565  for (int i = 0; i < n; i++)
1566  y[i] = vr[i];
1567  for (int i = n; i < 2 * n; i++)
1568  y[i] = vr[2 * n - i - 1];
1569 
1570  for (int i = 0; i < n; i++)
1571  vd[i] = y[2 * i];
1572  V = fft(vd);
1573  DFTI_DESCRIPTOR_HANDLE descriptor;
1574  MKL_LONG status;
1575 
1576  status = DftiCreateDescriptor(&descriptor, DFTI_DOUBLE, DFTI_REAL, 1, n);
1577 
1578  status = DftiSetValue(descriptor, DFTI_PLACEMENT,
1579  DFTI_NOT_INPLACE);
1580  status = DftiSetValue(descriptor, DFTI_CONJUGATE_EVEN_STORAGE, DFTI_COMPLEX_COMPLEX);
1581 
1582  status = DftiCommitDescriptor(descriptor);
1583  status = DftiComputeForward(descriptor, &vd[0], &V[0]);
1584  //status = DftiFreeDescriptor(&descriptor);
1585  for (int j = 0; j < n / 2; j++)
1586  V[n / 2 + j] = std::conj(V[n / 2 - j]);
1587  vr = 2.0 * std::real(std::valarray<std::complex<T> >(half_shift * V)) / T(n);
1588 
1589  for (int i = 0; i < n; i++)
1590  y[i] = vi[i];
1591  for (int i = n; i < 2 * n; i++)
1592  y[i] = vi[2 * n - i - 1];
1593 
1594  for (int i = 0; i < n; i++)
1595  vd[i] = y[2 * i];
1596  //V = fft(vd);
1597 
1598  status = DftiComputeForward(descriptor, &vd[0], &V[0]);
1599  status = DftiFreeDescriptor(&descriptor);
1600  for (int j = 0; j < n / 2; j++)
1601  V[n / 2 + j] = std::conj(V[n / 2 - j]);
1602  vi = 2.0 * std::real(std::valarray<std::complex<T> >(half_shift * V)) / T(n);
1603  v = dou2com(vr, vi);
1604  }
1605  else
1606  {
1607  std::cout << "In Cheb-space. Can't move to Cheb-space\n";
1608  exit(1);
1609  }
1611  };
1612 
1615  void c2p()
1616  {
1617  if (dct_flag == SIS_CHEB_SPACE)
1618  {
1619  std::valarray<T> vr(v.size()), vi(v.size());
1620  int n = v.size();
1621  vr = std::real(v);
1622  vi = std::imag(v);
1623  std::valarray<T> temp_u(n + 1);
1624  std::valarray<T> x(n), vd(n);
1625  vd[0] = 0.0;
1626  temp_u = 0.0;
1627  temp_u[std::slice(0, n, 1)] = vr;
1628  std::valarray<std::complex<T> > V(n);
1629  for (int i = 0; i < n; i++)
1630  {
1631  V[i] =
1632  std::complex<T>(temp_u[i], 0.0) - std::complex<T>(0.0, temp_u[n - i]);
1633  }
1634  V = std::complex<T>(0.5, 0.0) * rev_half_shift * V;
1635 
1636  //vd = ifft_cs(std::valarray<std::complex<T> >(V[std::slice(0, n / 2, 1)]));
1637  std::valarray<std::complex<T> > in1(std::complex<T>(0.0, 0.0), n / 2 + 1);
1638  in1[std::slice(0, n / 2, 1)] = V[std::slice(0, n / 2, 1)];
1639 
1640  DFTI_DESCRIPTOR_HANDLE descriptor;
1641  MKL_LONG status;
1642 
1643  status = DftiCreateDescriptor(&descriptor, DFTI_DOUBLE, DFTI_REAL, 1,
1644  n); // Specify size and precision
1645  // std::cout<<status<<endl;
1646  status = DftiSetValue(descriptor, DFTI_PLACEMENT,
1647  DFTI_NOT_INPLACE); // Out of place FFT
1648  status = DftiSetValue(descriptor, DFTI_CONJUGATE_EVEN_STORAGE,
1649  DFTI_COMPLEX_COMPLEX);
1650  // cout<<status<<endl;
1651  status = DftiCommitDescriptor(descriptor); // Finalize the descriptor
1652  // cout<<status<<endl;
1653  status = DftiComputeBackward(descriptor, &in1[0],
1654  &vd[0]); // Compute the Backward FFT
1655  // cout<<status<<endl;
1656  //status = DftiFreeDescriptor(&descriptor); // Free the descriptor
1657  // std::cout<<status<<endl;
1658 
1659  for (int i = 0; i < (n + 1) / 2; i++)
1660  vr[2 * i] = vd[i];
1661  for (int i = (n + 1) / 2; i < n; i++)
1662  vr[2 * n - 2 * i - 1] = vd[i];
1663 
1665  vd[0] = 0.0;
1666  temp_u = 0.0;
1667  temp_u[std::slice(0, n, 1)] = vi;
1668  for (int i = 0; i < n; i++)
1669  {
1670  V[i] =
1671  std::complex<T>(temp_u[i], 0.0) - std::complex<T>(0.0, temp_u[n - i]);
1672  }
1673  V = std::complex<T>(0.5, 0.0) * rev_half_shift * V;
1674 
1675  //vd = ifft_cs(std::valarray<std::complex<T> >(V[std::slice(0, n / 2, 1)]));
1676  in1 = std::complex<T>(0.0, 0.0);
1677  in1[std::slice(0, n / 2, 1)] = V[std::slice(0, n / 2, 1)];
1678 
1679  //status = DftiCreateDescriptor(&descriptor, //DFTI_DOUBLE, DFTI_REAL, 1,
1680  // n); // Specify size and precision
1681  // std::cout<<status<<endl;
1682  //status = DftiSetValue(descriptor, //DFTI_PLACEMENT,
1683  // DFTI_NOT_INPLACE); // Out of place FFT
1684  //status = DftiSetValue(descriptor, DFTI_CONJUGATE_EVEN_STORAGE,
1685  // DFTI_COMPLEX_COMPLEX);
1686  // cout<<status<<endl;
1687  //status = DftiCommitDescriptor(descriptor); // Finalize the descriptor
1688  // cout<<status<<endl;
1689  status = DftiComputeBackward(descriptor, &in1[0],
1690  &vd[0]); // Compute the Backward FFT
1691  // cout<<status<<endl;
1692  status = DftiFreeDescriptor(&descriptor); // Free the descriptor
1693  // std::cout<<status<<endl;
1694 
1695  for (int i = 0; i < (n + 1) / 2; i++)
1696  vi[2 * i] = vd[i];
1697  for (int i = (n + 1) / 2; i < n; i++)
1698  vi[2 * n - 2 * i - 1] = vd[i];
1699 
1700  v = dou2com(vr, vi);
1701  }
1702  else
1703  {
1704  std::cout << "In Physical-space. Can't move to Physical-space\n";
1705  exit(1);
1706  }
1708  };
1709 
1711  Eigen::Array<T, Eigen::Dynamic, 1> evr() {
1712  Eigen::Array<T, Eigen::Dynamic, 1> temp;
1713  temp.resize(v.size());
1714  for (int i = 0; i < v.size(); i++) {
1715  temp[i] = std::real(v[i]);
1716  }
1717  return temp;
1718  }
1719 
1721  Eigen::Array<T, Eigen::Dynamic, 1> evi() {
1722  Eigen::Array<T, Eigen::Dynamic, 1> temp;
1723  temp.resize(v.size());
1724  for (int i = 0; i < v.size(); i++) {
1725  temp[i] = std::imag(v[i]);
1726  }
1727  return temp;
1728  }
1729 
1731  Eigen::Array<std::complex<T>, Eigen::Dynamic, 1> evc() {
1732  Eigen::Array<std::complex<T>, Eigen::Dynamic, 1> temp;
1733  temp.resize(v.size());
1734  for (int i = 0; i < v.size(); i++) {
1735  temp[i] = v[i];
1736  }
1737  return temp;
1738  }
1742  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> MultMat() {
1743  int bre;
1744  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> toep(N + 1,
1745  N + 1),
1746  hank(N + 1, N + 1);
1747  toep.setConstant(0.0);
1748  hank.setConstant(0.0);
1749  if (dct_flag == SIS_PHYS_SPACE) {
1750  p2c();
1751  }
1752  Eigen::Array<T, Eigen::Dynamic, 1> vr_arr, vi_arr;
1753  vr_arr.resize(v.size());
1754  vi_arr.resize(v.size());
1755  for (int i = 0; i < v.size(); i++) {
1756  vr_arr[i] = std::real(v[i]);
1757  vi_arr[i] = std::imag(v[i]);
1758  }
1759  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, 1> vec(N + 1);
1760  vec.setConstant(0.0);
1761  vec.block(0, 0, N + 1, 1) = dou2com(vr_arr, vi_arr).matrix();
1762 
1763  for (int i = 0; i < N + 1; i++) {
1764  toep.block(i, i, 1, N + 1 - i) =
1765  vec.block(0, 0, N + 1 - i, 1).transpose();
1766  }
1767 
1768  toep = toep.eval() + toep.transpose().eval();
1769  toep.diagonal() = (toep.diagonal() / 2.0).eval();
1770 
1771  hank.setConstant(0.0);
1772  for (int i = 1; i < N + 1; i++) {
1773  hank.block(i, 0, 1, N - i) = vec.block(i, 0, N - i, 1).transpose();
1774  }
1775 //std::cout << "in " << __LINE__ << "\n";
1776 // std::cout << hank << "\n";
1777 // std::cin >> bre;
1778  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> out;
1779  out = std::complex<double>(0.5, 0.0) * (toep + hank);
1780 
1781  //std::cout << "in " << "\n";
1782  //std::cout << out << "\n";
1783  return out.transpose();
1784 
1785  }
1786 
1788  void operator=(const Chebfun<std::complex<T> > &in) {
1789  v = in.v;
1790  dct_flag = in.dct_flag;
1791  }
1793  void operator=(const Chebfun<T> &in) {
1794  v.resize(in.v.size());
1795  for (int i = 0; i < v.size(); i++)
1796  v[i] = in.v[i];
1797 
1798  dct_flag = in.dct_flag;
1799  }
1800 
1802  void operator=(const std::complex<T> &right) {
1803  if (dct_flag == SIS_CHEB_SPACE) {
1804  v = std::complex<T>(0.0, 0.0);
1805  v[0] = 2.0 * right;
1806  } else {
1807  v = right;
1808  }
1809  }
1810 
1812  void
1813  operator=(const Eigen::Matrix<std::complex<T>, Eigen::Dynamic, 1> &right) {
1814  v.resize(right.size());
1815  for (int i = 0; i < right.size(); i++) {
1816  v[i] = right[i];
1817  }
1818  }
1819 
1821  void operator=(const std::valarray<std::complex<T> > &right) { v = right; }
1822  void operator=(const std::valarray<T> &right) {
1823  v = std::complex<T>(right, 0.0);
1824  }
1825 
1828  void operator+=(Chebfun<std::complex<T> > b) {
1829  if (dct_flag == b.dct_flag) {
1830  v += b.v;
1831  } else {
1832  if (dct_flag == SIS_PHYS_SPACE) {
1833  b.c2p();
1834  v += b.v;
1835  b.p2c();
1836  } else {
1837  b.p2c();
1838  v += b.v;
1839  b.c2p();
1840  }
1841  }
1842  }
1845  if (dct_flag == b.dct_flag) {
1846  for (int i = 0; i < v.size(); i++)
1847  v[i] += b.v[i];
1848  } else {
1849  if (dct_flag == SIS_PHYS_SPACE) {
1850  b.c2p();
1851  for (int i = 0; i < v.size(); i++)
1852  v[i] += b.v[i];
1853  b.p2c();
1854  } else {
1855  b.p2c();
1856  for (int i = 0; i < v.size(); i++)
1857  v[i] += b.v[i];
1858  b.c2p();
1859  }
1860  }
1861  }
1862 
1864  void operator+=(std::complex<T> right) {
1865  if (dct_flag == SIS_CHEB_SPACE) {
1866  v[0] += 2.0 * right;
1867  } else {
1868  v += right;
1869  }
1870  }
1871 
1873  // void
1874  // operator=(const Eigen::Array<std::complex<T>, Eigen::Dynamic, 1> &right) {
1875  // this->vr = right.real();
1876  // this->vi = right.imag();
1877  // }
1879  std::complex<T> operator()(const double &a) {
1880  if (a > 1.0 || a < -1.0) {
1881  std::cout << "Error: Cannot evaluate a Chebfun outside the domain"
1882  << '\n';
1883  exit(1);
1884  }
1885  std::valarray<std::complex<T> > k(N + 1);
1886  for (int i = 0; i < N + 1; i++) {
1887  k[i] = std::complex<T>(i, 0.0);
1888  }
1889  k = cos(k * acos(std::complex<T>(a, 0.0)));
1890  k[0] = std::complex<T>(0.5, 0.0) * k[0];
1891  if (dct_flag == SIS_PHYS_SPACE) {
1892  p2c();
1893  k = k * v;
1894  this->c2p();
1895  return (k.sum());
1896  } else {
1897  k = k * v;
1898  return k.sum();
1899  }
1900  }
1902  Chebfun<T> fun;
1903  fun.v = real(v);
1904  fun.dct_flag = dct_flag;
1905  return fun;
1906  }
1908  Chebfun<T> fun;
1909  fun.v = imag(v);
1910  fun.dct_flag = dct_flag;
1911  return fun;
1912  };
1913 
1915  Chebfun<std::complex<T> > temp;
1916  if (dct_flag == SIS_PHYS_SPACE) {
1917  p2c();
1918  temp.v = integ(v);
1919  temp.dct_flag = SIS_CHEB_SPACE;
1920  c2p();
1921  temp.c2p();
1922  return temp;
1923  } else {
1924  temp.v = integ(v);
1925  temp.dct_flag = SIS_CHEB_SPACE;
1926  return temp;
1927  }
1928  }
1929 
1930  T L2norm() {
1931  Chebfun<T> temp;
1932  temp.dct_flag = SIS_PHYS_SPACE;
1933  if (dct_flag == SIS_PHYS_SPACE) {
1934  temp.v =
1935  std::real(std::valarray<std::complex<T> >(v * v.apply(std::conj)));
1936  } else {
1937  c2p();
1938  temp.v =
1939  std::real(std::valarray<std::complex<T> >(v * v.apply(std::conj)));
1940  p2c();
1941  }
1942 
1943  temp.p2c();
1944  temp.v = integ(temp.v);
1945 
1946  T ans = (temp.operator()(1) - temp.operator()(-1)) / 2.0;
1947  return ans;
1948  };
1949  T trunc() { return std::abs(v[N] + v[N - 1]) / 2.0; }
1950  //~Chebfun(){
1951  // v.~valarray();
1952  //}
1954 };
1956 template <class T>
1957 Chebfun<std::complex<T> > conj(Chebfun<std::complex<T> > in) {
1958  in.v = in.v.apply(std::conj);
1959  return in;
1960 };
1961 
1963 template <class T> Chebfun<T> diff(Chebfun<T> in, int n) {
1964  if (n == 0) {
1965  return in;
1966  } else {
1967  if (in.dct_flag == SIS_PHYS_SPACE) {
1968  in.p2c();
1969  in.v = diff(in.v);
1970  in.c2p();
1971  return diff(in, n - 1);
1972  } else {
1973  in.v = diff(in.v);
1974  return diff(in, n - 1);
1975  }
1976  }
1977 };
1978 
1980 template <class T>
1981 std::ostream &operator<<(std::ostream &stream, Chebfun<T> a) {
1982  std::valarray<T> y(N + 1);
1983  for (int i = 0; i < N + 1; i++) {
1984  y[i] = std::cos(PI * (i + 0.5) / (N + 1.0));
1985  }
1986  stream << "A Chebfun in ";
1987  if (a.dct_flag == SIS_CHEB_SPACE) {
1988  stream << "Chebyshev-space. Values of coefficients are: \n";
1989  for (int i = 0; i < a.v.size(); i++) {
1990  stream << a.v[i] << "\n";
1991  }
1992  } else {
1993  stream << "physical-space. Values at set points are: \n";
1994  stream << "y\t\t f(y)\n";
1995  for (int i = 0; i < N + 1; i++) {
1996  stream << y[i] << "\t\t" << a.v[i] << "\n";
1997  }
1998  }
1999  return stream;
2000 };
2001 
2002 // template <class T> class ChebfunMat<std::complex<T> >;
2004 template <class T> class ChebfunMat {
2005  friend class ChebfunMat<std::complex<T> >;
2006  friend class LinopMat<T>;
2007 
2008 private:
2009  int count;
2010 
2011 public:
2013  int r;
2015  int c;
2018  std::valarray<Chebfun<T> > ChebfunVec;
2020  ChebfunMat() : ChebfunVec(), r(0), c(0), count(0) {}
2021 
2023  ChebfunMat(int r_, int c_) {
2024  r = r_;
2025  c = c_;
2026  count = 0;
2027  ChebfunVec.resize(r * c);
2028  };
2029 
2032  r = in.r;
2033  c = in.c;
2034  resize(r, c);
2035  count = in.count;
2036  for (int i = 0; i < r * c; i++) {
2037  ChebfunVec[i] = in.ChebfunVec[i];
2038  }
2039  }
2041  void operator=(const ChebfunMat &in) {
2042  r = in.r;
2043  c = in.c;
2044  resize(r, c);
2045  count = in.count;
2046  for (int i = 0; i < r * c; i++) {
2047  ChebfunVec[i].v = in.ChebfunVec[i].v;
2048  ChebfunVec[i].dct_flag = in.ChebfunVec[i].dct_flag;
2049  }
2050  }
2051 
2055  void operator=(const Eigen::Matrix<T, Eigen::Dynamic,
2056  Eigen::Dynamic> &in) {
2057 
2058  if (in.rows() != r * (N + 1) || in.cols() != c) {
2059  std::cout
2060  << "Error in assigning a ChebfunMat through an Eigen Matrix. In line "
2061  << __LINE__ << ". Exiting ..." << '\n';
2062  exit(1);
2063  }
2064  for (int i = 0; i < r; i++) {
2065  for (int j = 0; j < c; j++) {
2066  operator()(i, j) = in.block(i * (N + 1), j, N + 1, 1);
2067  }
2068  }
2069  }
2070 
2074  int bre;
2075  ChebfunVec[count].v = b;
2076  count++;
2077  return *this;
2078  };
2079 
2083  Chebfun<T> &temp = ChebfunVec[i];
2084  return temp;
2085  };
2086 
2090  Chebfun<T> &operator()(int i, int j) { return ChebfunVec[j + c * i]; };
2091 
2093  void p2c(){
2094  for (int i = 0; i < r; i++){
2095  for (int j = 0; j < c; j++){
2096  if (operator()(i,j).dct_flag == SIS_PHYS_SPACE){
2097  operator()(i,j).p2c();
2098  }
2099  }
2100  }
2101  }
2102 
2104  void c2p(){
2105  for (int i = 0; i < r; i++){
2106  for (int j = 0; j < c; j++){
2107  if (operator()(i,j).dct_flag == SIS_CHEB_SPACE){
2108  operator()(i,j).c2p();
2109  }
2110  }
2111  }
2112  }
2113 
2114 
2117  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic >
2118  operator()(T p) {
2119  if (p <=1 && p >= -1 ){
2120  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic > temp(r,c);
2121  for (int i = 0 ; i < r; i ++){
2122  for (int j = 0; j < c; j++){
2123  temp(i,j) = operator()(i,j)(p);
2124  }
2125  }
2126  return temp;
2127  } else {
2128  std::cout << "Point of evaluation not in [-1,1]. In " << __LINE__
2129  << '\n';
2130  exit(1);
2131  }
2132  };
2133 
2136  ChebfunMat<T> &operator<<(Eigen::Array<T, Eigen::Dynamic, 1> b) {
2137  int bre;
2138  for (int i = 0; i < N + 1; i++) {
2139  ChebfunVec[count].v[i] = b[i];
2140  }
2141  count++;
2142  return *this;
2144  };
2145 
2148  ChebfunMat<T> &operator<<(std::valarray<T> b) {
2149  int bre;
2150  ChebfunVec[count].v = b;
2151  count++;
2152  return *this;
2154  };
2155 
2157  ChebfunMat<T> &operator<<(Chebfun<T> b) {
2158  int bre;
2159  ChebfunVec[count] = b;
2160  count++;
2161  return *this;
2162  };
2163 
2166  void resize(int r_, int c_) {
2167  r = r_;
2168  c = c_;
2169  ChebfunVec.resize(r * c);
2170  count = 0;
2171  }
2172 
2176  ChebfunVec[count].v = b;
2177  count++;
2178  return *this;
2179  }
2182  ChebfunMat<T> &operator,(Eigen::Array<T, Eigen::Dynamic, 1> b) {
2183  for (int i = 0; i < N + 1; i++) {
2184  ChebfunVec[count].v[i] = b[i];
2185  }
2186  count++;
2187  return *this;
2188  }
2189 
2192  ChebfunMat<T> &operator,(std::valarray<T> b) {
2193  ChebfunVec[count].v = b;
2194  count++;
2195  return *this;
2196  }
2200  ChebfunVec[count] = b;
2201  count++;
2202  return *this;
2203  }
2204 
2206  void setConstant(double in) {
2207  for (int i = 0; i < r; i++) {
2208  for (int j = 0; j < c; j++) {
2209  operator()(i, j) = in;
2210  }
2211  }
2212  }
2213 
2215  sis::ChebfunMat<T> out;
2216  out.resize(c, r);
2217  for (int i = 0; i < r; i++) {
2218  for (int j = 0; j < c; j++) {
2219  out(j, i) = conj(operator()(i, j));
2220  }
2221  }
2222  return out;
2223  };
2224 
2226  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>
2228  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> out(
2229  r * (N + 1), c);
2230  int bre;
2231  // std::cout << "r,c = " << std::complex<int>(r, c) << '\n';
2232  for (int i = 0; i < r; i++) {
2233  for (int j = 0; j < c; j++) {
2234  // std::cout << "in " << __LINE__ << '\n';
2235  if (operator()(i, j).dct_flag == SIS_CHEB_SPACE) {
2236  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> temp;
2237  out.block(i * (N + 1), j, N + 1, 1) =
2238  // temp =
2239  operator()(i, j).ev();
2240  // std::cout << "in " << __LINE__ << '\n';
2241  } else {
2242  operator()(i, j).p2c();
2243  out.block(i * (N + 1), j, N + 1, 1) = operator()(i, j).ev();
2244  operator()(i, j).c2p();
2245  }
2246  }
2247  }
2248  }
2249  // ~ChebfunMat(){
2250  // ChebfunVec.~valarray();
2251  // }
2252 };
2253 
2255 template <class T> class ChebfunMat<std::complex<T> > {
2256 private:
2257  int count;
2258 
2259 public:
2261  int r;
2263  int c;
2266  std::valarray<Chebfun<std::complex<T> > > ChebfunVec;
2268  ChebfunMat() : ChebfunVec(), r(0), c(0), count(0) {}
2269 
2271  ChebfunMat(int r_, int c_) {
2272  r = r_;
2273  c = c_;
2274  count = 0;
2275  ChebfunVec.resize(r * c);
2276  };
2277 
2279  ChebfunMat(const ChebfunMat<std::complex<T> > &in) {
2280  r = in.r;
2281  c = in.c;
2282  resize(r, c);
2283  count = in.count;
2284  for (int i = 0; i < r * c; i++) {
2285  ChebfunVec[i] = in.ChebfunVec[i];
2286  }
2287  }
2289  void operator=(const ChebfunMat<std::complex<T> > &in) {
2290  resize(in.r, in.c);
2291  count = in.count;
2292  for (int i = 0; i < r * c; i++) {
2293  ChebfunVec[i].v = in.ChebfunVec[i].v;
2294  ChebfunVec[i].dct_flag = in.ChebfunVec[i].dct_flag;
2295  }
2296  }
2297 
2299  void operator=(const ChebfunMat<T> &in) {
2300  r = in.r;
2301  c = in.c;
2302  resize(r, c);
2303  count = in.count;
2304  for (int i = 0; i < r * c; i++) {
2305  ChebfunVec[i] = in.ChebfunVec[i];
2306  }
2307  }
2308 
2311  ChebfunMat<std::complex<T> > &operator<<(std::complex<T> b) {
2312  int bre;
2313  // std::cout << "I am here " << __LINE__ << std::endl;
2314  // std::cout << "Value : " << b << std::endl;
2315  // std::cout << "Count : " << count << std::endl;
2316  ChebfunVec[count].v = b;
2317 
2318  count++;
2319  return *this;
2320  };
2321 
2325  Chebfun<std::complex<T> > &temp = ChebfunVec[i];
2326  return temp;
2327  };
2328 
2330  void p2c(){
2331  for (int i = 0; i < r; i++){
2332  for (int j = 0; j < c; j++){
2333  if (operator()(i,j).dct_flag == SIS_PHYS_SPACE){
2334  operator()(i,j).p2c();
2335  }
2336  }
2337  }
2338  }
2339 
2341  void c2p(){
2342  for (int i = 0; i < r; i++){
2343  for (int j = 0; j < c; j++){
2344  if (operator()(i,j).dct_flag == SIS_CHEB_SPACE){
2345  operator()(i,j).c2p();
2346  }
2347  }
2348  }
2349  }
2354 
2355  return ChebfunVec[j + c * i];
2356  };
2357 
2360  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic >
2361  operator()(T p) {
2362  if (p <=1 && p >= -1 ){
2363  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic > temp(r,c);
2364  for (int i = 0 ; i < r; i ++){
2365  for (int j = 0; j < c; j++){
2366  temp(i,j) = operator()(i,j)(p);
2367  }
2368  }
2369  return temp;
2370  } else {
2371  std::cout << "Point of evaluation not in [-1,1]. In " << __LINE__
2372  << '\n';
2373  exit(1);
2374  }
2375  };
2376 
2380  operator<<(Eigen::Array<std::complex<T>, Eigen::Dynamic, 1> b) {
2381  for (int i = 0; i < N + 1; i++) {
2382  ChebfunVec[count].v[i] = b[i];
2383  }
2384  count++;
2385  return *this;
2386  };
2387 
2388  // \brief Use this to input multiple Chebfuns to the ChebfunMat using comma
2390  ChebfunMat<std::complex<T> > &operator<<(std::valarray<std::complex<T> > b) {
2391  ChebfunVec[count].v = b;
2392  count++;
2393  return *this;
2394  };
2395 
2396  // \brief Use this to input multiple Chebfuns to the ChebfunMat using comma
2398  ChebfunMat<std::complex<T> > &operator<<(std::valarray<T> b) {
2399  int bre;
2400  for (int i = 0; i < N + 1; i++)
2401  ChebfunVec[count].v[i] = b[i];
2402  count++;
2403  return *this;
2404  };
2405 
2408  ChebfunMat<std::complex<T> > &operator<<(Chebfun<std::complex<T> > b) {
2409  int bre;
2410  ChebfunVec[count] = b;
2411  count++;
2412  return *this;
2413  };
2414 
2417  void resize(int r_, int c_) {
2418  r = r_;
2419  c = c_;
2420  ChebfunVec.resize(r * c);
2421  count = 0;
2422  }
2423 
2426  ChebfunMat<std::complex<T> > &operator,(std::complex<T> b) {
2427  ChebfunVec[count].v = b;
2428  count++;
2429  return *this;
2430  }
2431 
2435  Eigen::Array<std::complex<T>, Eigen::Dynamic, 1> b) {
2436  for (int i = 0; i < N + 1; i++) {
2437  ChebfunVec[count].v[i] = b[i];
2438  }
2439  count++;
2440  return *this;
2441  }
2444  ChebfunMat<std::complex<T> > &operator,(std::valarray<std::complex<T> > b) {
2445  ChebfunVec[count].v = b;
2446  count++;
2447  return *this;
2448  }
2449 
2451  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic>
2453  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> out(
2454  r * (N + 1), c);
2455  int bre;
2456  // std::cout << "r,c = " << std::complex<int>(r, c) << '\n';
2457  for (int i = 0; i < r; i++) {
2458  for (int j = 0; j < c; j++) {
2459  // std::cout << "in " << __LINE__ << '\n';
2460  if (operator()(i, j).dct_flag == SIS_CHEB_SPACE) {
2461  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> temp;
2462  out.block(i * (N + 1), j, N + 1, 1) =
2463  // temp =
2464  operator()(i, j).evc();
2465  // std::cout << "in " << __LINE__ << '\n';
2466  } else {
2467  operator()(i, j).p2c();
2468  out.block(i * (N + 1), j, N + 1, 1) = operator()(i, j).evc();
2469  operator()(i, j).c2p();
2470  }
2471  }
2472  }
2473  // std::cout << "out is " << out << '\n';
2474  // std::cin >> bre;
2475  return out;
2476  }
2477 
2481  void operator=(const Eigen::Matrix<std::complex<T>, Eigen::Dynamic,
2482  Eigen::Dynamic> &in) {
2483 
2484  if (in.rows() != r * (N + 1) || in.cols() != c) {
2485  std::cout
2486  << "Error in assigning a ChebfunMat through an Eigen Matrix. In line "
2487  << __LINE__ << ". Exiting ..." << '\n';
2488  exit(1);
2489  }
2490  for (int i = 0; i < r; i++) {
2491  for (int j = 0; j < c; j++) {
2492  operator()(i, j) = in.block(i * (N + 1), j, N + 1, 1);
2493  }
2494  }
2495  }
2496 
2498  void setConstant(T in) {
2499  for (int i = 0; i < r; i++) {
2500  for (int j = 0; j < c; j++) {
2501  operator()(i, j) = in;
2502  }
2503  }
2504  }
2505 
2507  void setConstant(std::complex<T> in) {
2508  for (int i = 0; i < r; i++) {
2509  for (int j = 0; j < c; j++) {
2510  operator()(i, j) = in;
2511  }
2512  }
2513  }
2514 
2517  out.resize(c, r);
2518  for (int i = 0; i < r; i++) {
2519  for (int j = 0; j < c; j++) {
2520  out(j, i) = conj(operator()(i, j));
2521  }
2522  }
2523  return out;
2524  };
2525  // ~ChebfunMat(){
2526  // ChebfunVec.~valarray();
2527  // }
2528 };
2529 
2533  sis::ChebfunMat<T> out;
2534  out.resize(in.r, in.c);
2535  for (int i = 0; i < in.r; i++) {
2536  for (int j = 0; j < in.c; j++) {
2537  out(i, j) = conj(in(i, j));
2538  }
2539  }
2540  return out;
2541 };
2542 
2545 template <class T> ChebfunMat<T> diff(ChebfunMat<T> in, int n) {
2546  ChebfunMat<T> out;
2547  int bre;
2548  out.resize(in.r, in.c);
2549  for (int i = 0; i < in.r; i++) {
2550  for (int j = 0; j < in.c; j++) {
2551  out(i, j) = diff(in(i, j), n);
2552  }
2553  }
2554  return out;
2555 };
2556 
2560 template <class T> class Linop {
2561 private:
2562  int i, j;
2563 
2564 public:
2565  int NCC;
2566  int n;
2567 
2568  Eigen::Matrix<T, Eigen::Dynamic, 1>
2629  Eigen::Matrix<T, Eigen::Dynamic, 1> solution;
2630 
2632  Linop() { NCC = 0; };
2633 
2636  Linop(const int &n_) {
2637  n = n_;
2638  coef.resize(n + 1);
2639  NCC = 0;
2640  };
2641 
2643  Linop(const Linop<T> &in) {
2644  n = in.n;
2645  NCC = in.NCC;
2646  coef = in.coef;
2647  if (NCC == 1) {
2648  coefFun = in.coefFun;
2649  }
2650  solution = in.solution;
2651  }
2652 
2654  void operator=(const Linop<T> &in) {
2655  n = in.n;
2656  NCC = in.NCC;
2657  coef = in.coef;
2658  coefFun = in.coefFun;
2659  solution = in.solution;
2660  }
2661 
2664  Chebfun<T> out;
2665  out.v = 0.0;
2666  // if non constant coefficients:
2667  if (NCC==1){
2668  for (int i = 0; i < n + 1; i ++){
2669  out = out + (coefFun[n-i]*diff(in,i));
2670  }
2671  } else {
2672  for (int i = 0; i < n + 1; i ++){
2673  out = out + (coef[n-i]*diff(in,i));
2674  }
2675  }
2676  return out;
2677  }
2678 
2680  void operator+=(const Linop<T> &in) {
2681  Linop<T> temp;
2682  temp = *this + in;
2683  operator=(temp);
2684  }
2685 
2687  void operator=(const T &in) {
2688  n = 0;
2689  NCC = 0;
2690  set();
2691  coef[0] = in;
2692  }
2693 
2695  void operator=(const Eigen::Array<T, Eigen::Dynamic, 1> &in) {
2696  n = 0;
2697  ncc();
2698  coefFun << in;
2699  }
2700 
2702  void operator=(const std::valarray<T> &in) {
2703  n = 0;
2704  ncc();
2705  coefFun << in;
2706  }
2709  if (in.dct_flag == SIS_PHYS_SPACE) {
2710  operator=(in.v);
2711  } else {
2712  in.c2p();
2713  operator=(in.v);
2714  in.p2c();
2715  }
2716  };
2719  Linop<T> out = *this;
2720  if (out.NCC == 0) {
2721  out.coef = out.coef / in;
2722  } else {
2723  for (int i = 0; i < out.n + 1; i++) {
2724  out.coefFun[i].v = out.coefFun[i].v / in;
2725  }
2726  }
2727  return out;
2728  }
2729 
2733  void set() {
2734  coef.resize(n + 1);
2735  NCC = 0;
2736  };
2737 
2741  void set(int n_) {
2742  n = n_;
2743  coef.resize(n_ + 1);
2744  NCC = 0;
2745  };
2746 
2751  void ncc() {
2752  NCC = 1;
2753  coefFun.resize(1, n + 1);
2754  }
2755 
2760  void ncc(int n_) {
2761  NCC = 1;
2762  n = n_;
2763  coefFun.resize(1, n + 1);
2764  }
2765 };
2766 
2768 template <class T> class Linop<std::complex<T> > {
2769 private:
2770  int i, j;
2771 
2772 public:
2773  int NCC;
2774  int n;
2775  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, 1>
2784 
2792 
2817 
2819  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, 1>
2821 
2823  Linop() { NCC = 0; };
2824 
2826  Linop(const int &n_) {
2827  n = n_;
2828  coef.resize(n + 1);
2829  NCC = 0;
2830  };
2831 
2833  Linop(const Linop<std::complex<T> > &in) {
2834  n = in.n;
2835  NCC = in.NCC;
2836  coef = in.coef;
2837  if (NCC == 1) {
2838  coefFun = in.coefFun;
2839  }
2840  solution = in.solution;
2841  }
2842  void operator=(const Linop<std::complex<T> > &in) {
2843  n = in.n;
2844  NCC = in.NCC;
2845  coef = in.coef;
2846  if (NCC == 1) {
2847  coefFun = in.coefFun;
2848  }
2849  solution = in.solution;
2850  }
2851 
2852  void operator=(const Linop<T> &in) {
2853  n = in.n;
2854  NCC = in.NCC;
2855  coef = in.coef;
2856  coefFun = in.coefFun;
2857  solution = in.solution;
2858  }
2859 
2860  void operator+=(const Linop<T> &in) {
2861  Linop<std::complex<T> > temp;
2862  temp = *this + in;
2863  operator=(temp);
2864  }
2865 
2867  Chebfun<std::complex<T> > operator()(Chebfun<std::complex<T> > in){
2869  out.v = std::complex<T>(0.0, 0.0);
2870  // if non constant coefficients:
2871  if (NCC==1){
2872  for (int i = 0; i < n + 1; i ++){
2873  out = out + (coefFun[n-i]*diff(in,i));
2874  }
2875  } else {
2876  for (int i = 0; i < n + 1; i ++){
2877  out = out + (coef[n-i]*diff(in,i));
2878  }
2879  }
2880  return out;
2881  }
2882 
2883 
2884  void operator+=(const Linop<std::complex<T> > &in) {
2885  Linop<std::complex<T> > temp;
2886  temp = *this + in;
2887  operator=(temp);
2888  }
2889 
2891  void operator=(const std::complex<T> &in) {
2892  n = 0;
2893  NCC = 0;
2894  set();
2895  coef[0] = in;
2896  }
2897 
2899  void operator=(T in) {
2900  n = 0;
2901  NCC = 0;
2902  set();
2903  coef[0] = in;
2904  }
2905 
2907  void operator=(const Eigen::Array<std::complex<T>, Eigen::Dynamic, 1> &in) {
2908  n = 0;
2909  ncc();
2910  coefFun << in;
2911  }
2912 
2914  void operator=(const std::valarray<T> &in) {
2915  n = 0;
2916  ncc();
2917  coefFun << in;
2918  }
2919 
2920  void operator=(const std::valarray<std::complex<T> > &in) {
2921  n = 0;
2922  ncc();
2923  coefFun << in;
2924  }
2925 
2927  if (in.dct_flag == SIS_PHYS_SPACE) {
2928  operator=(in.v);
2929  } else {
2930  in.c2p();
2931  operator=(in.v);
2932  in.p2c();
2933  }
2934  };
2935 
2936  void operator=(Chebfun<std::complex<T> > in) {
2937  if (in.dct_flag == SIS_PHYS_SPACE) {
2938  operator=(in.v);
2939  } else {
2940  in.c2p();
2941  operator=(in.v);
2942  in.p2c();
2943  }
2944  };
2945 
2948  Linop<std::complex<T> > out = *this;
2949  if (out.NCC == 0) {
2950  out.coef = out.coef / in;
2951  } else {
2952  for (int i = 0; i < out.n + 1; i++) {
2953  out.coefFun[i].v = out.coefFun[i].v / std::complex<T>(in, 0.0);
2954  }
2955  }
2956  return out;
2957  }
2958 
2960  Linop<std::complex<T> > operator/(std::complex<T> in) {
2961  Linop<std::complex<T> > out = *this;
2962  if (out.NCC == 0) {
2963  out.coef = out.coef / in;
2964  } else {
2965  for (int i = 0; i < out.n + 1; i++) {
2966  out.coefFun[i].v = out.coefFun[i].v / in;
2967  }
2968  }
2969  return out;
2970  }
2971 
2974  Linop<std::complex<T> > out = *this;
2975  if (out.NCC == 0) {
2976  out.coef = out.coef * in;
2977  } else {
2978  for (int i = 0; i < out.n + 1; i++) {
2979  out.coefFun[i].v = out.coefFun[i].v * std::complex<T>(in, 0.0);
2980  }
2981  }
2982  return out;
2983  }
2984  /* /// \brief Multiplying Linop by ArrayXd.
2985  Linop<std::complex<T> > operator*(Eigen::Array<T, Eigen::Dynamic, 1> in) {
2986  Linop<std::complex<T> > out = *this;
2987  if (out.NCC == 0) {
2988  ncc();
2989  for (int i = 0; i < n + 1; i++) {
2990  out.coefFun[i].v = out.coef[i] * in;
2991  }
2992  } else {
2993  for (int i = 0; i < out.n + 1; i++) {
2994  out.coefFun[i].vr = out.coefFun[i].vr * in;
2995  out.coefFun[i].vi = out.coefFun[i].vi * in;
2996  }
2997  }
2998  return out;
2999  }
3000 
3002  Linop<std::complex<T> >
3003  operator*(Eigen::Array<std::complex<T>, Eigen::Dynamic, 1> in) {
3004  Linop<std::complex<T> > out = *this;
3005  if (out.NCC == 0) {
3006  ncc();
3007  for (int i = 0; i < n + 1; i++) {
3008  out.coefFun[i].vr = (out.coef[i] * in).real();
3009  out.coefFun[i].vi = (out.coef[i] * in).imag();
3010  }
3011  } else {
3012  for (int i = 0; i < out.n + 1; i++) {
3013  out.coefFun[i].vr =
3014  out.coefFun[i].vr * in.real() - out.coefFun[i].vi * in.imag();
3015  out.coefFun[i].vi =
3016  out.coefFun[i].vi * in.real() + out.coefFun[i].vr * in.imag();
3017  }
3018  }
3019  return out;
3020  }
3021  */
3023  Linop<std::complex<T> > operator*(std::complex<T> in) {
3024  Linop<std::complex<T> > out = *this;
3025  if (out.NCC == 0) {
3026  out.coef = out.coef * in;
3027  } else {
3028  for (int i = 0; i < out.n + 1; i++) {
3029  out.coefFun[i].v = out.coefFun[i].v * in;
3030  }
3031  }
3032  return out;
3033  }
3037  void set() {
3038  coef.resize(n + 1);
3039  NCC = 0;
3040  };
3041 
3045  void set(int n_) {
3046  n = n_;
3047  coef.resize(n_ + 1);
3048  NCC = 0;
3049  };
3054  void ncc() {
3055  NCC = 1;
3056  coefFun.resize(1, n + 1);
3057  }
3058 
3063  void ncc(int n_) {
3064  NCC = 1;
3065  n = n_;
3066  coefFun.resize(1, n + 1);
3067  }
3069  sis::Linop<T> L;
3070  L.n = this->n;
3071  if (NCC == 0) {
3072  L.set();
3073  L.coef = coef.real();
3074  } else {
3075  L.ncc();
3076  for (int i = 0; i < n + 1; i++)
3077  L.coefFun[i].v = std::real(coefFun[i].v);
3078  }
3079 
3080  return L;
3081  };
3082 
3084  sis::Linop<T> L;
3085  L.n = this->n;
3086  if (NCC == 0) {
3087  L.set();
3088  L.coef = coef.imag();
3089  } else {
3090  L.ncc();
3091  for (int i = 0; i < n + 1; i++)
3092  L.coefFun[i].v = std::imag(coefFun[i].v);
3093  }
3094 
3095  return L;
3096  };
3099  Chebfun<std::complex<T> > solve(Chebfun<std::complex<T> > in){};
3100 };
3101 
3103 template <class T> Linop<T> diff(Linop<T> in, int n) {
3104  int bre;
3105  if (n == 0) {
3106  return in;
3107  } else {
3108  if (in.NCC == 0) { // if constant coefficients
3109  Linop<T> out(in.n + 1);
3110  out.coef << in.coef, 0.0;
3111  return diff(out, n - 1);
3112  } else {
3113  Linop<T> out;
3114  out.ncc(in.n + 1);
3115  out.coefFun[0] = in.coefFun[0];
3116  out.coefFun[out.n] = diff(in.coefFun[in.n], 1);
3117  for (int i = 1; i < out.n; i++) {
3118  out.coefFun[i] = diff(in.coefFun[i - 1], 1) + in.coefFun[i];
3119  }
3120  return diff(out, n - 1);
3121  }
3122  }
3123 };
3124 
3126 template <class T> class EigenSorter {
3127 private:
3128 public:
3130  bool Mp;
3132  int numMp;
3133  T minVal;
3135  bool isInf;
3138 
3141  numMp = 0;
3142  minVal = 0;
3143  epsilon = 1e-11;
3144  epsilon = abs(epsilon);
3145  }
3146 
3148  void compute(Eigen::Matrix<std::complex<T>, Eigen::Dynamic, 1> in) {
3149  std::vector<T> temp;
3150  temp.reserve(in.rows());
3151  for (int i = 0; i < in.rows(); i++) {
3152  temp.push_back(std::abs(in[i]));
3153  }
3154  if (floor(N / 2) < N / 2) {
3155  numMp = 0;
3156  while (numMp < N && ((temp[numMp] + temp[numMp + 1]) / 2.0) > epsilon) {
3157  numMp = numMp + 2;
3158  }
3159  } else {
3160  numMp = 1;
3161  while (numMp < N && ((temp[numMp] + temp[numMp + 1]) / 2.0) > epsilon) {
3162  numMp = numMp + 2;
3163  }
3164  }
3165  Chebfun<std::complex<T> > tempfun(in);
3166  tempfun.dct_flag = SIS_CHEB_SPACE;
3167  // Eigenfunction has to be nonzero. If zero, set the numMp to N+1
3168  if (tempfun.L2norm() < 1e-11) {
3169  numMp = N + 1;
3170  }
3171  if (std::isnan(tempfun.L2norm())) {
3172  numMp = N + 1;
3173  }
3174  if (numMp >= N) {
3175  minVal = (temp[N] + temp[N - 1]) / 2.0;
3176  Mp = false;
3177  } else {
3178  Mp = true;
3179  }
3180  }
3181 
3183  void compute(Eigen::Matrix<std::complex<T>, Eigen::Dynamic, 1> in, int c) {
3184  int bre;
3185  std::vector<T> temp;
3186  temp.reserve(N + 1);
3187  ChebfunMat<std::complex<T> > tempfuns;
3188  tempfuns.resize(c, 1);
3189  std::vector<std::vector<double> > L2norms;
3190  double ave_L2norm = 0.0;
3191  L2norms.resize(c);
3192  for (int i = 0; i < c; i++) {
3193  Eigen::Matrix<T, Eigen::Dynamic, 1> tempMatr, tempMati;
3194  tempMatr = in.block(i * (N + 1), 0, N + 1, 1).real();
3195  tempMati = in.block(i * (N + 1), 0, N + 1, 1).imag();
3196  for (int j = 0; j < N + 1; j++) {
3197  tempfuns(i, 0).v[j] = std::complex<T>(tempMatr[j], tempMati[j]);
3198  }
3199  tempfuns(i, 0).dct_flag = SIS_CHEB_SPACE;
3200  L2norms[i].resize(2);
3201  L2norms[i][0] = (tempfuns(i, 0).L2norm());
3202  L2norms[i][1] = i;
3203  ave_L2norm += L2norms[i][0];
3204  }
3205 
3206  // Use the Chebfun with the largest L2norm as the one that ascertains
3207  // sorting criteria
3208  std::sort(L2norms.begin(), L2norms.end());
3209  ave_L2norm = ave_L2norm / double(c);
3210 
3211  if (ave_L2norm > 1e-11) {
3212  for (int i = int(L2norms[c - 1][1]) * (N + 1);
3213  i < int(L2norms[c - 1][1] + 1) * (N + 1); i++) {
3214  temp.push_back(std::abs(in[i]));
3215  }
3216  // This checks if N is odd or even:
3217  if (floor(N / 2) < N / 2) {
3218  numMp = 0;
3219  while (numMp < N && ((temp[numMp] + temp[numMp + 1]) / 2.0) > epsilon) {
3220  numMp = numMp + 2;
3221  }
3222  } else {
3223  numMp = 1;
3224  while (numMp < N && ((temp[numMp] + temp[numMp + 1]) / 2.0) > epsilon) {
3225  numMp = numMp + 2;
3226  }
3227  }
3228  } // Eigenfunction-vector has to be nonzero. If zero, set the numMp to N+1
3229  else {
3230  numMp = N + 1;
3231  }
3232 
3233  if (std::isnan(ave_L2norm)) {
3234  numMp = N + 1;
3235  }
3236 
3237  if (numMp >= N) {
3238  minVal = (temp[N] + temp[N - 1]) / 2.0;
3239  Mp = false;
3240  } else {
3241  Mp = true;
3242  }
3243  }
3244 };
3245 
3252 
3253 template <class T> class GeneralizedEigenSolver {
3254 private:
3255 public:
3256  std::vector<ChebfunMat<std::complex<T> > > eigenvectorsMat;
3257  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, 1> eigenvalues;
3263 #ifdef SIS_USE_LAPACK
3264  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, 1> alpha, beta;
3265  int info; // gives info on lapack solver.
3266 #endif
3267  void compute(Linop<T> L, Linop<T> M, int num_vals){};
3268 
3276  void compute(const LinopMat<T> &Lmat_, const LinopMat<T> &Mmat_, int num_vals,
3277  const BcMat<T> &Lbc_) {
3278  LinopMat<T> Lmat = Lmat_;
3279  LinopMat<T> Mmat = Mmat_;
3280  BcMat<T> Lbc = Lbc_;
3281  int bre;
3282  int total_of_all_orders = 0;
3283  int total_boundary_conditions = 0;
3284  if (Lmat.r != Lmat.c) {
3285  std::cout << "Solution only possible with square LinopMats. Exiting ..."
3286  << '\n';
3287  exit(1);
3288  }
3289  if (Mmat.r != Mmat.c) {
3290  std::cout << "Solution only possible with square LinopMats. Exiting ..."
3291  << '\n';
3292  exit(1);
3293  }
3294  if (Mmat.c != Lmat.c) {
3295  std::cout << "Both matrices have to be of same size. Exiting ..." << '\n';
3296  exit(1);
3297  }
3298  int r = Lmat.r, c = Lmat.c;
3299  // Find the highest derivative in each column. To do this create a vector
3300  // highest_each_column, and a temp_int_vec that will hold all values of a
3301  // given column to and the maximum will be stored in highest_each_column
3302  std::vector<int> highest_each_columnL, highest_each_columnM,
3303  highest_each_column;
3304  highest_each_columnL.resize(c);
3305  highest_each_columnM.resize(c);
3306  highest_each_column.resize(c);
3307 
3308  std::vector<int> temp_vec_int;
3309  temp_vec_int.resize(r);
3310  for (int j = 0; j < c; j++) {
3311  for (int i = 0; i < r; i++) {
3312  temp_vec_int[i] = Lmat(i, j).n;
3313  }
3314  highest_each_columnL[j] =
3315  *std::max_element(temp_vec_int.begin(), temp_vec_int.end());
3316  }
3317  for (int j = 0; j < c; j++) {
3318  for (int i = 0; i < r; i++) {
3319  temp_vec_int[i] = Mmat(i, j).n;
3320  }
3321  highest_each_columnM[j] =
3322  *std::max_element(temp_vec_int.begin(), temp_vec_int.end());
3323  }
3324  for (int i = 0; i < c; i++) {
3325  total_of_all_orders += (highest_each_columnL[i] > highest_each_columnM[i])
3326  ? highest_each_columnL[i]
3327  : highest_each_columnM[i];
3328  highest_each_column[i] =
3329  (highest_each_columnL[i] > highest_each_columnM[i])
3330  ? highest_each_columnL[i]
3331  : highest_each_columnM[i];
3332  }
3333  total_boundary_conditions = Lbc.m;
3334 
3335  // total_of_all_orders has to be equal to total number of boundary
3336  // conditions, else the problem is ill-posed, if ill-posed, cout the same
3337  // and exit.
3338  if (total_of_all_orders != total_boundary_conditions) {
3339  std::cout << "The problem is ill-posed, the total of the highest "
3340  "orders of all "
3341  "dependent variables has to be equal to the total number of "
3342  "boundary conditions specified."
3343  "\n "
3344  "Total no. of boundary conditions: "
3345  << total_boundary_conditions
3346  << "\n"
3347  "Total of all orders: "
3348  << total_of_all_orders << "\n Exiting ...\n";
3349  exit(1);
3350  }
3351  // Declare the master matrix L:
3352  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> masterL(
3353  r * (N + 1), c * (N + 1) + total_boundary_conditions);
3354  // Declare the master matrix M:
3355  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> masterM(
3356  r * (N + 1), c * (N + 1) + total_boundary_conditions);
3357 
3358  masterL.setConstant(0.0);
3359  masterM.setConstant(0.0);
3360  MatGen<T> Mat;
3361  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> subs_mat;
3362  subs_mat.resize(total_boundary_conditions, (N + 1) * c);
3363  subs_mat.setConstant(0.0);
3364  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> mat_temp(
3365  total_boundary_conditions, total_boundary_conditions),
3366  constraints(total_boundary_conditions,
3367  c * (N + 1) + total_of_all_orders);
3368 
3369  mat_temp.setConstant(0.0);
3370  int row_counter = 0, col_counter = 0;
3371 
3372  for (int i = 0; i < Lbc.m; i++) {
3373  for (int j = 0; j < Lbc.n; j++) {
3374  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> temp =
3375  Lbc(i, j, highest_each_column[j]);
3376  constraints.block(i, col_counter, 1, temp.cols()) = temp;
3377  col_counter += temp.cols();
3378  }
3379  col_counter = 0;
3380  }
3381 
3382  Eigen::ColPivHouseholderQR<
3383  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> >
3384  qr;
3385  qr.compute(constraints);
3386  if (qr.rank() != constraints.rows()) {
3387  std::cout << "The boundary conditions supplied are not "
3388  << " linearly independent." << '\n';
3389  std::cout << "qr.rank = " << qr.rank()
3390  << ", no. bcs: " << total_boundary_conditions << ". Exiting ..."
3391  << '\n';
3392  exit(1);
3393  }
3394 
3395  // Permutation matrix
3396  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> P;
3397  P = qr.colsPermutation();
3398  // Permute constraints
3399  constraints = constraints * P;
3400  mat_temp = constraints.block(0, 0, constraints.rows(), constraints.rows());
3401 
3402  Eigen::ColPivHouseholderQR<
3403  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> >
3404  consSolver(mat_temp);
3405  subs_mat = -consSolver.inverse() *
3406  constraints.block(0, constraints.rows(), constraints.rows(),
3407  constraints.cols() - constraints.rows());
3408 
3409  row_counter = 0;
3410  col_counter = 0;
3411  int master_row_counter = 0;
3412  int master_col_counter = 0;
3413  for (int j = 0; j < c; j++) {
3414  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
3415  ? highest_each_columnL[j]
3416  : highest_each_columnM[j];
3417  Mat.compute(n);
3418  for (int i = 0; i < r; i++) {
3419  int diffn = n - Lmat(i, j).n;
3420  if (Lmat(i, j).NCC == 0) {
3421  for (int k = 0; k < Lmat(i, j).n + 1; k++) {
3422  masterL.block(master_row_counter, master_col_counter, N + 1,
3423  N + 1 + n) +=
3424  Lmat(i, j).coef[k] *
3425  (Mat.mats2[k + diffn].block(0, 0, N + 1, N + 1 + n));
3426  }
3427  } else {
3428  for (int k = 0; k < Lmat(i, j).n + 1; k++) {
3429  masterL.block(master_row_counter, master_col_counter, N + 1,
3430  N + 1 + n) +=
3431  Lmat(i, j).coefFun[k].MultMat().block(0, 0, N + 1, N + 1) *
3432  (Mat.mats2[k + diffn].block(0, 0, N + 1, N + 1 + n));
3433  }
3434  }
3435  diffn = n - Mmat(i, j).n;
3436  if (Mmat(i, j).NCC == 0) {
3437  for (int k = 0; k < Mmat(i, j).n + 1; k++) {
3438  masterM.block(master_row_counter, master_col_counter, N + 1,
3439  N + 1 + n) +=
3440  Mmat(i, j).coef[k] *
3441  (Mat.mats2[k + diffn].block(0, 0, N + 1, N + 1 + n));
3442  }
3443  } else {
3444  for (int k = 0; k < Mmat(i, j).n + 1; k++) {
3445  masterM.block(master_row_counter, master_col_counter, N + 1,
3446  N + 1 + n) +=
3447  Mmat(i, j).coefFun[k].MultMat().block(0, 0, N + 1, N + 1) *
3448  (Mat.mats2[k + diffn].block(0, 0, N + 1, N + 1 + n));
3449  }
3450  }
3451  master_row_counter += N + 1;
3452  }
3453  master_row_counter = 0;
3454  master_col_counter += N + 1 + n;
3455  }
3456  // Permute columns of M and L:
3457  masterL = masterL * P;
3458  masterM = masterM * P;
3459 
3460  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> masterL2, masterM2;
3461 
3462  masterL2 =
3463  masterL.block(0, constraints.rows(), c * (N + 1), c * (N + 1)) +
3464  (masterL.block(0, 0, c * (N + 1), constraints.rows()) * subs_mat);
3465  masterM2 =
3466  masterM.block(0, constraints.rows(), c * (N + 1), c * (N + 1)) +
3467  (masterM.block(0, 0, c * (N + 1), constraints.rows()) * subs_mat);
3468 #ifndef SIS_USE_LAPACK
3469  Eigen::ColPivHouseholderQR<
3470  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> >
3471  solver(masterM2);
3472  Eigen::EigenSolver<Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> > eigs;
3473  bool Is_M_Invertible;
3474  if (solver.isInvertible()) {
3475  // std::cout << "M is invertible" << '\n';
3476  // std::cin >> bre;
3477  Is_M_Invertible = true;
3478  eigs.compute(solver.inverse() * masterL2);
3479  // std::cout << "Eigenvalues :\n" << eigs.eigenvalues() << '\n';
3480  } else {
3481  // std::cout << "M is not invertible." << '\n';
3482  // std::cin >> bre;
3483  Is_M_Invertible = false;
3484  solver.compute(masterL2);
3485  eigs.compute(solver.inverse() * masterM2);
3486  // std::cout << "Eigenvalues :\n" << 1 / eigs.eigenvalues().array() <<
3487  // '\n';
3488  }
3489  // std::cin >> bre;
3490  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic>
3491  evecMat_master(c * (N + 1), c * (N + 1));
3492  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, 1> temp_vec;
3493  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> fir_n_mat =
3494  subs_mat * eigs.eigenvectors();
3495  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> evecMat(
3496  c * (N + 1) + total_boundary_conditions, c * (N + 1));
3497  evecMat << fir_n_mat, eigs.eigenvectors();
3498 
3499  // Unpermute eveMat:
3500  evecMat = P * evecMat;
3501  row_counter = 0;
3502  col_counter = 0;
3503  for (int i = 0; i < c; i++) {
3504  int n = (highest_each_columnL[i] > highest_each_columnM[i])
3505  ? highest_each_columnL[i]
3506  : highest_each_columnM[i];
3507  Mat.compute(n);
3508  evecMat_master.block(i * (N + 1), 0, N + 1, c * (N + 1)) =
3509  Mat.mats2[n] * evecMat.block(row_counter, 0, N + 1 + n, c * (N + 1));
3510  row_counter += N + 1 + n;
3511  }
3512  std::vector<std::vector<T> > eigenval_trunc_sorter;
3513 
3514  eigenval_trunc_sorter.resize(c * (N + 1));
3515  for (int i = 0; i < c * (N + 1); i++) {
3516  eigenval_trunc_sorter[i].resize(2);
3517  }
3518 
3519  Eigen::Matrix<int, Eigen::Dynamic, 1> MPcount(c * (N + 1));
3520  MPcount.setConstant(0);
3521  std::vector<EigenSorter<T> > sorter;
3522  sorter.resize(c * (N + 1));
3523  for (int i = 0; i < c * (N + 1); i++) {
3524  sorter[i].compute(evecMat_master.block(0, i, c * (N + 1), 1), c);
3525  if (!Is_M_Invertible) {
3526  // If M is not invertible, there will be zero eigenvalues, so that 1/0 =
3527  // inf eigenvalue, remove them.
3528  if (abs(eigs.eigenvalues()[i]) < 1e-11) {
3529  sorter[i].numMp = N + 1;
3530  sorter[i].Mp = false;
3531  sorter[i].minVal = 1e11;
3532  }
3533  }
3534  // sorter[i].compute(evecMat_master.block(0, i, (N + 1), 1));
3535  if (sorter[i].Mp == true) {
3536  MPcount[i] = 1;
3537  }
3538  }
3539  int MPcount_sum = MPcount.sum();
3540  eigenvectorsMat.resize(num_vals);
3541  for (int i = 0; i < num_vals; i++) {
3542  eigenvectorsMat[i].resize(c, 1);
3543  }
3544  eigenvalues.resize(num_vals);
3545  if (MPcount_sum >= num_vals) {
3546  for (int i = 0; i < c * (N + 1); i++) {
3547  eigenval_trunc_sorter[i][0] = T(sorter[i].numMp);
3548  eigenval_trunc_sorter[i][1] = i;
3549  // std::cout << eigs.eigenvalues()[i] << " " << sorter[i].numMp <<
3550  // "\n"; std::cin > > bre;
3551  }
3552  std::sort(eigenval_trunc_sorter.begin(), eigenval_trunc_sorter.end());
3553  for (int i = 0; i < num_vals; i++) {
3554  if (Is_M_Invertible) {
3555  eigenvalues[i] = eigs.eigenvalues()[int(eigenval_trunc_sorter[i][1])];
3556  } else {
3557  eigenvalues[i] =
3558  1.0 / eigs.eigenvalues()[int(eigenval_trunc_sorter[i][1])];
3559  }
3560  }
3561  for (int j = 0; j < c; j++) {
3562  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
3563  ? highest_each_columnL[j]
3564  : highest_each_columnM[j];
3565 
3566  temp_vec.resize(N + 1 + n, 1);
3567  for (int i = 0; i < num_vals; i++) {
3568  eigenvectorsMat[i][j] = evecMat_master.block(
3569  j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
3570  }
3571  }
3572  } else {
3573  std::cout << "Last " << num_vals - MPcount_sum
3574  << " eigenvectors are not resolved to machine precision."
3575  << '\n';
3576  for (int i = 0; i < c * (N + 1); i++) {
3577  eigenval_trunc_sorter[i][0] = T(sorter[i].numMp);
3578  eigenval_trunc_sorter[i][1] = i;
3579  }
3580  std::sort(eigenval_trunc_sorter.begin(), eigenval_trunc_sorter.end());
3581  for (int i = 0; i < MPcount_sum; i++) {
3582  if (Is_M_Invertible) {
3583  eigenvalues[i] = eigs.eigenvalues()[int(eigenval_trunc_sorter[i][1])];
3584  } else {
3585  eigenvalues[i] =
3586  1.0 / eigs.eigenvalues()[int(eigenval_trunc_sorter[i][1])];
3587  }
3588  }
3589  for (int j = 0; j < c; j++) {
3590  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
3591  ? highest_each_columnL[j]
3592  : highest_each_columnM[j];
3593  temp_vec.resize(N + 1 + n, 1);
3594  for (int i = 0; i < MPcount_sum; i++) {
3595  eigenvectorsMat[i][j] = evecMat_master.block(
3596  j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
3597  }
3598  }
3599 
3600  std::vector<std::vector<T> > eigenval_trunc_sorter2;
3601  eigenval_trunc_sorter2.resize(c * (N + 1) - MPcount_sum);
3602  for (int i = MPcount_sum; i < c * (N + 1); i++) {
3603  eigenval_trunc_sorter2[i - MPcount_sum].resize(2);
3604  eigenval_trunc_sorter2[i - MPcount_sum][0] =
3605  sorter[int(eigenval_trunc_sorter[i][1])].minVal;
3606  eigenval_trunc_sorter2[i - MPcount_sum][1] =
3607  eigenval_trunc_sorter[i][1];
3608  }
3609  std::sort(eigenval_trunc_sorter2.begin(), eigenval_trunc_sorter2.end());
3610  for (int i = MPcount_sum; i < num_vals; i++) {
3611  if (Is_M_Invertible) {
3612  eigenvalues[i] = eigs.eigenvalues()[int(
3613  eigenval_trunc_sorter2[i - MPcount_sum][1])];
3614  } else {
3615  eigenvalues[i] =
3616  1.0 / eigs.eigenvalues()[int(
3617  eigenval_trunc_sorter2[i - MPcount_sum][1])];
3618  }
3619  }
3620  for (int j = 0; j < c; j++) {
3621  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
3622  ? highest_each_columnL[j]
3623  : highest_each_columnM[j];
3624  Mat.compute(n);
3625  temp_vec.resize(N + 1 + n, 1);
3626  for (int i = MPcount_sum; i < num_vals; i++) {
3627  eigenvectorsMat[i][j] = evecMat_master.block(
3628  j * (N + 1), int(eigenval_trunc_sorter2[i - MPcount_sum][1]),
3629  N + 1, 1);
3630  }
3631  }
3632  }
3633 #else
3634  std::cout << "Using lapack routine..." << '\n';
3635  char jobvl = 'N'; // Don't compute left evecs
3636  char jobvr = 'V'; // Compute right evecs
3637  std::complex<double> wkopt; // Eistimate optimum workspace
3638  std::complex<double> *work; // allocate optimum workspace
3639  alpha.resize(masterL2.rows(), 1); // alpha for gen. eig. prob.
3640  beta.resize(masterL2.rows(), 1); // beta for gen. eig. prob.
3641 
3642  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> masterL2_,
3643  masterM2_, vl(masterL2.rows(), masterL2.rows()),
3644  vr(masterL2.rows(), masterL2.rows()),
3645  eigenvalues_temp(masterL2.rows(), 1), alpha_temp(masterL2.rows(), 1),
3646  beta_temp(masterL2.rows(), 1);
3647 
3648  masterL2_ = masterL2;
3649  masterM2_ = masterM2;
3650  // vl : left evecs, vr: right evecs.
3651  int ldL = masterL2.outerStride(); // ld for leading dimension
3652  int ldM = masterM2.outerStride();
3653  int ldvl = vl.outerStride();
3654  int ldvr = vr.outerStride();
3655  int sizeL = masterL2.rows();
3656  int lwork = -1; // set lwork to -1 to estimate workspace.
3657  double rwork[8 * sizeL];
3658 
3659  // call this to estimate workspace
3660  zggev_(&jobvl, &jobvr, &sizeL, masterL2_.data(), &ldL, masterM2_.data(),
3661  &ldM, alpha_temp.data(), beta_temp.data(), vl.data(), &ldvl,
3662  vr.data(), &ldvr, &wkopt, &lwork, rwork, &info);
3663 
3664  // Now allocate workspace:
3665  lwork = (int)real(wkopt);
3666  work = (std::complex<double> *)malloc(lwork * sizeof(std::complex<double>));
3667 
3668  // Solve eigenvalue problem:
3669  zggev_(&jobvl, &jobvr, &sizeL, masterL2_.data(), &ldL, masterM2_.data(),
3670  &ldM, alpha_temp.data(), beta_temp.data(), vl.data(), &ldvl,
3671  vr.data(), &ldvr, work, &lwork, rwork, &info);
3672 
3673  // Free workspace.
3674  free((void *)work);
3675 
3676  eigenvalues_temp = alpha_temp.array() / beta_temp.array();
3677 
3678  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic>
3679  evecMat_master(c * (N + 1), c * (N + 1));
3680  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, 1> temp_vec;
3681  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> fir_n_mat =
3682  subs_mat * vr;
3683  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> evecMat(
3684  c * (N + 1) + total_boundary_conditions, c * (N + 1));
3685  evecMat << fir_n_mat, vr;
3686  // Unpermute eveMat:
3687  evecMat = P * evecMat;
3688  row_counter = 0;
3689  col_counter = 0;
3690  for (int i = 0; i < c; i++) {
3691  int n = (highest_each_columnL[i] > highest_each_columnM[i])
3692  ? highest_each_columnL[i]
3693  : highest_each_columnM[i];
3694  Mat.compute(n);
3695  evecMat_master.block(i * (N + 1), 0, N + 1, c * (N + 1)) =
3696  Mat.mats2[n] * evecMat.block(row_counter, 0, N + 1 + n, c * (N + 1));
3697  row_counter += N + 1 + n;
3698  }
3699  std::vector<std::vector<T> > eigenval_trunc_sorter;
3700 
3701  eigenval_trunc_sorter.resize(c * (N + 1));
3702  for (int i = 0; i < c * (N + 1); i++) {
3703  eigenval_trunc_sorter[i].resize(2);
3704  }
3705 
3706  Eigen::Matrix<int, Eigen::Dynamic, 1> MPcount(c * (N + 1));
3707  MPcount.setConstant(0);
3708  std::vector<EigenSorter<T> > sorter;
3709  sorter.resize(c * (N + 1));
3710  for (int i = 0; i < c * (N + 1); i++) {
3711  sorter[i].compute(evecMat_master.block(0, i, c * (N + 1), 1), c);
3712  // sorter[i].compute(evecMat_master.block(0, i, (N + 1), 1));
3713  if (sorter[i].Mp == true) {
3714  MPcount[i] = 1;
3715  }
3716  }
3717  if (num_vals > masterL2.rows()) {
3718  std::cout << "Only " << masterL.rows()
3719  << " eigenvalues can be calculated."
3720  << "Storing only that many." << '\n';
3721  num_vals = masterL2.rows();
3722  }
3723 
3724  int MPcount_sum = MPcount.sum();
3725  eigenvectorsMat.resize(num_vals);
3726  for (int i = 0; i < num_vals; i++) {
3727  eigenvectorsMat[i].resize(c, 1);
3728  }
3729  eigenvalues.resize(num_vals);
3730  beta.resize(num_vals);
3731  alpha.resize(num_vals);
3732  if (MPcount_sum >= num_vals) {
3733  for (int i = 0; i < c * (N + 1); i++) {
3734  eigenval_trunc_sorter[i][0] = T(sorter[i].numMp);
3735  eigenval_trunc_sorter[i][1] = i;
3736  // std::cout << eigs.eigenvalues()[i] << " " << sorter[i].numMp <<
3737  // "\n"; std::cin > > bre;
3738  }
3739  std::sort(eigenval_trunc_sorter.begin(), eigenval_trunc_sorter.end());
3740  for (int i = 0; i < num_vals; i++) {
3741  eigenvalues[i] = eigenvalues_temp(int(eigenval_trunc_sorter[i][1]), 0);
3742  alpha[i] = alpha_temp(int(eigenval_trunc_sorter[i][1]), 0);
3743  beta[i] = beta_temp(int(eigenval_trunc_sorter[i][1]), 0);
3744  }
3745  for (int j = 0; j < c; j++) {
3746  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
3747  ? highest_each_columnL[j]
3748  : highest_each_columnM[j];
3749 
3750  temp_vec.resize(N + 1 + n, 1);
3751  for (int i = 0; i < num_vals; i++) {
3752  eigenvectorsMat[i][j] = evecMat_master.block(
3753  j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
3754  eigenvectorsMat[i][j].dct_flag = SIS_CHEB_SPACE;
3755  }
3756  }
3757  } else {
3758  std::cout << "Last " << num_vals - MPcount_sum
3759  << " eigenvectors are not resolved to machine precision."
3760  << '\n';
3761  for (int i = 0; i < c * (N + 1); i++) {
3762  eigenval_trunc_sorter[i][0] = T(sorter[i].numMp);
3763  eigenval_trunc_sorter[i][1] = i;
3764  }
3765  std::sort(eigenval_trunc_sorter.begin(), eigenval_trunc_sorter.end());
3766  for (int i = 0; i < MPcount_sum; i++) {
3767  eigenvalues[i] = eigenvalues_temp(int(eigenval_trunc_sorter[i][1]), 0);
3768  alpha[i] = alpha_temp(int(eigenval_trunc_sorter[i][1]), 0);
3769  beta[i] = beta_temp(int(eigenval_trunc_sorter[i][1]), 0);
3770  }
3771  for (int j = 0; j < c; j++) {
3772  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
3773  ? highest_each_columnL[j]
3774  : highest_each_columnM[j];
3775  temp_vec.resize(N + 1 + n, 1);
3776  for (int i = 0; i < MPcount_sum; i++) {
3777  eigenvectorsMat[i][j] = evecMat_master.block(
3778  j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
3779  eigenvectorsMat[i][j].dct_flag = SIS_CHEB_SPACE;
3780  }
3781  }
3782 
3783  std::vector<std::vector<T> > eigenval_trunc_sorter2;
3784  eigenval_trunc_sorter2.resize(c * (N + 1) - MPcount_sum);
3785  for (int i = MPcount_sum; i < c * (N + 1); i++) {
3786  eigenval_trunc_sorter2[i - MPcount_sum].resize(2);
3787  eigenval_trunc_sorter2[i - MPcount_sum][0] =
3788  sorter[int(eigenval_trunc_sorter[i][1])].minVal;
3789  eigenval_trunc_sorter2[i - MPcount_sum][1] =
3790  eigenval_trunc_sorter[i][1];
3791  }
3792  std::sort(eigenval_trunc_sorter2.begin(), eigenval_trunc_sorter2.end());
3793  for (int i = MPcount_sum; i < num_vals; i++) {
3794  eigenvalues[i] = eigenvalues_temp(
3795  int(eigenval_trunc_sorter2[i - MPcount_sum][1]), 0);
3796  alpha[i] =
3797  alpha_temp(int(eigenval_trunc_sorter2[i - MPcount_sum][1]), 0);
3798  beta[i] = beta_temp(int(eigenval_trunc_sorter2[i - MPcount_sum][1]), 0);
3799  }
3800  for (int j = 0; j < c; j++) {
3801  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
3802  ? highest_each_columnL[j]
3803  : highest_each_columnM[j];
3804  Mat.compute(n);
3805  temp_vec.resize(N + 1 + n, 1);
3806  for (int i = MPcount_sum; i < num_vals; i++) {
3807  eigenvectorsMat[i][j] = evecMat_master.block(
3808  j * (N + 1), int(eigenval_trunc_sorter2[i - MPcount_sum][1]),
3809  N + 1, 1);
3810  eigenvectorsMat[i][j].dct_flag = SIS_CHEB_SPACE;
3811  }
3812  }
3813  }
3814 
3815 #endif
3816  }
3817 
3818 
3828  const LinopMat<T> &Mmat_, int num_vals,
3829  const BcMat<T> &Lbc_, const BcMat<T> &Mbc_) {
3830 
3831  LinopMat<T> Lmat = Lmat_;
3832  LinopMat<T> Mmat = Mmat_;
3833  BcMat<T> Lbc = Lbc_;
3834  BcMat<T> Mbc = Mbc_;
3835  int bre;
3836  int total_of_all_orders = 0;
3837  int total_boundary_conditions = 0;
3838  if (Lmat.r != Lmat.c) {
3839  std::cout << "Solution only possible with square LinopMats. Exiting ..."
3840  << '\n';
3841  exit(1);
3842  }
3843  if (Mmat.r != Mmat.c) {
3844  std::cout << "Solution only possible with square LinopMats. Exiting ..."
3845  << '\n';
3846  exit(1);
3847  }
3848  if (Mmat.c != Lmat.c) {
3849  std::cout << "Both matrices have to be of same size. Exiting ..." << '\n';
3850  exit(1);
3851  }
3852  int r = Lmat.r, c = Lmat.c;
3853  // Find the highest derivative in each column. To do this create a vector
3854  // highest_each_column, and a temp_int_vec that will hold all values of a
3855  // given column to and the maximum will be stored in highest_each_column
3856  std::vector<int> highest_each_columnL, highest_each_columnM,
3857  highest_each_column, num_bc_each_var;
3858  highest_each_columnL.resize(c);
3859  highest_each_columnM.resize(c);
3860  highest_each_column.resize(c);
3861  num_bc_each_var.resize(c);
3862  std::vector<int> temp_vec_int;
3863  temp_vec_int.resize(r);
3864  for (int j = 0; j < c; j++) {
3865  for (int i = 0; i < r; i++) {
3866  temp_vec_int[i] = Lmat(i, j).n;
3867  }
3868  highest_each_columnL[j] =
3869  *std::max_element(temp_vec_int.begin(), temp_vec_int.end());
3870  }
3871  for (int j = 0; j < c; j++) {
3872  for (int i = 0; i < r; i++) {
3873  temp_vec_int[i] = Mmat(i, j).n;
3874  }
3875  highest_each_columnM[j] =
3876  *std::max_element(temp_vec_int.begin(), temp_vec_int.end());
3877  }
3878  for (int i = 0; i < c; i++) {
3879  total_of_all_orders += (highest_each_columnL[i] > highest_each_columnM[i])
3880  ? highest_each_columnL[i]
3881  : highest_each_columnM[i];
3882  highest_each_column[i] =
3883  (highest_each_columnL[i] > highest_each_columnM[i])
3884  ? highest_each_columnL[i]
3885  : highest_each_columnM[i];
3886  }
3887  for (int i = 0; i < c; i++) {
3888  total_boundary_conditions += Lmat.BcVec[i].nbc();
3889  num_bc_each_var[i] = Lmat.BcVec[i].nbc();
3890  }
3891 
3892  if (Lbc.m != Mbc.m) {
3893  std::cout << "The Lbc and Mbc have to be of same dimensions" << '\n'
3894  << "Exiting in " << __LINE__ << "...\n";
3895 
3896  exit(1);
3897  }
3898  // total_of_all_orders has to be equal to total number of boundary
3899  // conditions, else the problem is ill-posed, if ill-posed, cout the same
3900  // and exit.
3901  if (total_of_all_orders != (total_boundary_conditions + Lbc.m)) {
3902  std::cout << "The problem is ill-posed, the total of the highest "
3903  "orders of all "
3904  "dependent variables has to be equal to the total number of "
3905  "boundary conditions plus number of constraints specified."
3906  "\n "
3907  "Total no. of boundary conditions: "
3908  << total_boundary_conditions
3909  << "\n"
3910  "Total of all orders: "
3911  << total_of_all_orders << "\n Number of Constraints : " << Lbc.m
3912  << "\n Exiting in " << __LINE__ << " ...\n ";
3913  exit(1);
3914  }
3915  // Declare the master matrix L:
3916  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> masterL(
3917  r * (N + 1) + Lbc.m, c * (N + 1) + Lbc.m);
3918  // Declare the master matrix M:
3919  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> masterM(
3920  r * (N + 1) + Lbc.m, c * (N + 1) + Lbc.m);
3921 
3922  masterL.setConstant(0.0);
3923  masterM.setConstant(0.0);
3924  MatGen<T> Mat;
3925  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> subs_mat;
3926 
3927  subs_mat.resize(total_boundary_conditions, (N + 1) * c + Lbc.m);
3928 
3929  subs_mat.setConstant(0.0);
3930  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> mat_temp(
3931  total_boundary_conditions, total_boundary_conditions);
3932  mat_temp.setConstant(0.0);
3933  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> subs_mat_col_mul(
3934  c * (N + 1), total_boundary_conditions);
3935  subs_mat_col_mul.setConstant(0.0);
3936  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> subs_mat_col_mul2(
3937  c * (N + 1), total_boundary_conditions);
3938  subs_mat_col_mul2.setConstant(0.0);
3939  int subs_mat_row_counter = 0;
3940  int subs_mat_col_counter = 0;
3941  int row_counter = 0, col_counter = 0;
3942  for (int j = 0; j < c; j++) {
3943  // overall order is the one which is greater in each column:
3944  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
3945  ? highest_each_columnL[j]
3946  : highest_each_columnM[j];
3947  // Store the LinopMat with the larger degree to setup boundary conditions
3948  // LinopMat<T > Tmat =
3949  // (highest_each_columnL[j] > highest_each_columnM[j]) ? Lmat : Mmat;
3950 
3951  Mat.compute(n);
3952  std::vector<Eigen::Matrix<T, 1, Eigen::Dynamic> > lbc_vecs(
3953  Lmat.BcVec[j].nl, Eigen::Matrix<T, 1, Eigen::Dynamic>(N + 1 + 2 * n));
3954  std::vector<Eigen::Matrix<T, 1, Eigen::Dynamic> > rbc_vecs(
3955  Lmat.BcVec[j].nr, Eigen::Matrix<T, 1, Eigen::Dynamic>(N + 1 + 2 * n));
3956  std::vector<Eigen::Matrix<T, 1, Eigen::Dynamic> > lbc_con_vecs(
3957  Lmat.BcVec[j].nl, Eigen::Matrix<T, 1, Eigen::Dynamic>(n));
3958  std::vector<Eigen::Matrix<T, 1, Eigen::Dynamic> > rbc_con_vecs(
3959  Lmat.BcVec[j].nr, Eigen::Matrix<T, 1, Eigen::Dynamic>(n));
3960  Eigen::Matrix<T, 1, Eigen::Dynamic> ones(N + 1 + 2 * n);
3961  Eigen::Matrix<T, 1, Eigen::Dynamic> onem(N + 1 + 2 * n);
3962  Eigen::Matrix<T, 1, Eigen::Dynamic> onesn(n);
3963  Eigen::Matrix<T, 1, Eigen::Dynamic> onemn(n);
3964  // This follows as T_n(1) = 1.0.
3965  ones.setConstant(1.0);
3966  onesn.setConstant(1.0);
3967  onem.setConstant(1.0);
3968  onemn.setConstant(1.0);
3969  // This follows as T_n(-1) = (-1)^n.
3970  for (int k = 1; k < N + 1 + 2 * n; k = k + 2) {
3971  onem[k] = -1.0;
3972  }
3973  for (int k = 1; k < n; k = k + 2) {
3974  onemn[k] = -1.0;
3975  }
3976  if (n > 0) {
3977  ones[0] = 0.5;
3978  onesn[0] = 0.5;
3979  onem[0] = 0.5;
3980  onemn[0] = 0.5;
3981  }
3982  // Next just multiply matrices based on the order.
3983  for (int k = 0; k < Lmat.BcVec[j].nl; k++) {
3984  lbc_vecs[k].resize(N + 1 + 2 * n);
3985  lbc_vecs[k].setConstant(0.0);
3986  for (int l = 0; l < Lmat.BcVec[j].ord + 1; l++) {
3987  lbc_vecs[k] += Lmat.BcVec[j].coefl(k, l) *
3988  (onem * Mat.mats[l + (n - Lmat.BcVec[j].ord)]);
3989  }
3990  }
3991 
3992  for (int k = 0; k < Lmat.BcVec[j].nr; k++) {
3993  rbc_vecs[k].resize(N + 1 + 2 * n);
3994  rbc_vecs[k].setConstant(0.0);
3995  for (int l = 0; l < Lmat.BcVec[j].ord + 1; l++) {
3996  rbc_vecs[k] += Lmat.BcVec[j].coefr(k, l) *
3997  (ones * Mat.mats[l + (n - Lmat.BcVec[j].ord)]);
3998  }
3999  }
4000  for (int k = 0; k < Lmat.BcVec[j].nl; k++) {
4001  lbc_con_vecs[k].setConstant(0.0);
4002  for (int l = 0; l < Lmat.BcVec[j].ord + 1; l++) {
4003  if (l + n - Lmat.BcVec[j].ord - 1 > -1) {
4004  lbc_con_vecs[k] +=
4005  Lmat.BcVec[j].coefl(k, l) *
4006  (onemn * Mat.con_mats[l + n - Lmat.BcVec[j].ord - 1]);
4007  }
4008  }
4009  }
4010  for (int k = 0; k < Lmat.BcVec[j].nr; k++) {
4011  rbc_con_vecs[k].setConstant(0.0);
4012  for (int l = 0; l < Lmat.BcVec[j].ord + 1; l++) {
4013  if (l + n - Lmat.BcVec[j].ord - 1 > -1) {
4014  rbc_con_vecs[k] +=
4015  Lmat.BcVec[j].coefr(k, l) *
4016  (onesn * Mat.con_mats[l + n - Lmat.BcVec[j].ord - 1]);
4017  }
4018  }
4019  }
4020 
4021  for (int k = 0; k < Lmat.BcVec[j].nl; k++) {
4022  mat_temp.block(row_counter, col_counter, 1,
4023  Lmat.BcVec[j].nl + Lmat.BcVec[j].nr) =
4024  lbc_vecs[k].head(Lmat.BcVec[j].nl + Lmat.BcVec[j].nr);
4025  row_counter++;
4026  }
4027  for (int k = Lmat.BcVec[j].nl; k < Lmat.BcVec[j].nl + Lmat.BcVec[j].nr;
4028  k++) {
4029  mat_temp.block(row_counter, col_counter, 1,
4030  Lmat.BcVec[j].nl + Lmat.BcVec[j].nr) =
4031  rbc_vecs[k - Lmat.BcVec[j].nl].head(Lmat.BcVec[j].nl +
4032  Lmat.BcVec[j].nr);
4033  row_counter++;
4034  }
4035  col_counter = col_counter + Lmat.BcVec[j].nbc();
4036  for (int k = 0; k < Lmat.BcVec[j].nl; k++) {
4037  subs_mat.block(subs_mat_row_counter, subs_mat_col_counter, 1,
4038  (N + 1 - Lmat.BcVec[j].nbc())) =
4039  lbc_vecs[k].block(0, Lmat.BcVec[j].nbc(), 1,
4040  N + 1 - Lmat.BcVec[j].nbc());
4041  subs_mat.block(subs_mat_row_counter,
4042  subs_mat_col_counter + (N + 1 - Lmat.BcVec[j].nbc()), 1,
4043  n) = lbc_con_vecs[k];
4044  subs_mat_row_counter++;
4045  }
4046 
4047  for (int k = Lmat.BcVec[j].nl; k < Lmat.BcVec[j].nbc(); k++) {
4048  subs_mat.block(subs_mat_row_counter, subs_mat_col_counter, 1,
4049  (N + 1 - Lmat.BcVec[j].nbc())) =
4050  rbc_vecs[k - Lmat.BcVec[j].nl].block(0, Lmat.BcVec[j].nbc(), 1,
4051  N + 1 - Lmat.BcVec[j].nbc());
4052  subs_mat.block(subs_mat_row_counter,
4053  subs_mat_col_counter + (N + 1 - Lmat.BcVec[j].nbc()), 1,
4054  n) = rbc_con_vecs[k - Lmat.BcVec[j].nl];
4055  subs_mat_row_counter++;
4056  }
4057  subs_mat_col_counter += (N + 1 + n - Lmat.BcVec[j].nbc());
4058  }
4059  if (mat_temp.rows() != 0 || mat_temp.cols() != 0) {
4060  Eigen::ColPivHouseholderQR<
4061  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> >
4062  consSolver(mat_temp);
4063  if (!consSolver.isInvertible()) {
4064  std::cout << "the matrix is not invertible." << '\n';
4065  exit(1);
4066  }
4067  subs_mat = -consSolver.inverse() * subs_mat.eval();
4068  }
4069  row_counter = 0;
4070  col_counter = 0;
4071  int master_row_counter = 0;
4072  int master_col_counter = 0;
4073  subs_mat_row_counter = 0;
4074  subs_mat_col_counter = 0;
4075  for (int j = 0; j < c; j++) {
4076  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
4077  ? highest_each_columnL[j]
4078  : highest_each_columnM[j];
4079  Mat.compute(n);
4080  for (int i = 0; i < r; i++) {
4081 
4082  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> solver_matL(
4083  N + 1, N + 1 + n - Lmat.BcVec[j].nbc());
4084  solver_matL.setConstant(0.0);
4085  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> solver_matM(
4086  N + 1, N + 1 + n - Lmat.BcVec[j].nbc());
4087  solver_matM.setConstant(0.0);
4088  int diffn = n - Lmat(i, j).n;
4089  if (Lmat(i, j).NCC == 0) {
4090  for (int k = 0; k < Lmat(i, j).n + 1; k++) {
4091  solver_matL.block(0, 0, N + 1, N + 1 + n - Lmat.BcVec[j].nbc()) +=
4092  Lmat(i, j).coef[k] *
4093  (Mat.mats2[k + diffn].block(0, Lmat.BcVec[j].nbc(), N + 1,
4094  N + 1 + n - Lmat.BcVec[j].nbc()));
4095  subs_mat_col_mul.block(i * (N + 1), subs_mat_col_counter, N + 1,
4096  Lmat.BcVec[j].nbc()) +=
4097  Lmat(i, j).coef[k] *
4098  (Mat.mats2[k + diffn].block(0, 0, N + 1, Lmat.BcVec[j].nbc()));
4099  }
4100  } else {
4101  for (int k = 0; k < Lmat(i, j).n + 1; k++) {
4102  solver_matL.block(0, 0, N + 1, N + 1 + n - Lmat.BcVec[j].nbc()) +=
4103  Lmat(i, j).coefFun[k].MultMat().block(0, 0, N + 1, N + 1) *
4104  (Mat.mats2[k + diffn].block(0, Lmat.BcVec[j].nbc(), N + 1,
4105  N + 1 + n - Lmat.BcVec[j].nbc()));
4106  subs_mat_col_mul.block(i * (N + 1), subs_mat_col_counter, N + 1,
4107  Lmat.BcVec[j].nbc()) +=
4108  Lmat(i, j).coefFun[k].MultMat().block(0, 0, N + 1, N + 1) *
4109  (Mat.mats2[k + diffn].block(0, 0, N + 1, Lmat.BcVec[j].nbc()));
4110  }
4111  }
4112  diffn = n - Mmat(i, j).n;
4113  if (Mmat(i, j).NCC == 0) {
4114  for (int k = 0; k < Mmat(i, j).n + 1; k++) {
4115  solver_matM.block(0, 0, N + 1, N + 1 + n - Lmat.BcVec[j].nbc()) +=
4116  Mmat(i, j).coef[k] *
4117  (Mat.mats2[k + diffn].block(0, Lmat.BcVec[j].nbc(), N + 1,
4118  N + 1 + n - Lmat.BcVec[j].nbc()));
4119  subs_mat_col_mul2.block(i * (N + 1), subs_mat_col_counter, N + 1,
4120  Lmat.BcVec[j].nbc()) +=
4121  Mmat(i, j).coef[k] *
4122  (Mat.mats2[k + diffn].block(0, 0, N + 1, Lmat.BcVec[j].nbc()));
4123  }
4124  } else {
4125  for (int k = 0; k < Mmat(i, j).n + 1; k++) {
4126  solver_matM.block(0, 0, N + 1, N + 1 + n - Lmat.BcVec[j].nbc()) +=
4127  Mmat(i, j).coefFun[k].MultMat().block(0, 0, N + 1, N + 1) *
4128  (Mat.mats2[k + diffn].block(0, Lmat.BcVec[j].nbc(), N + 1,
4129  N + 1 + n - Lmat.BcVec[j].nbc()));
4130  subs_mat_col_mul2.block(i * (N + 1), subs_mat_col_counter, N + 1,
4131  Lmat.BcVec[j].nbc()) +=
4132  Mmat(i, j).coefFun[k].MultMat().block(0, 0, N + 1, N + 1) *
4133  (Mat.mats2[k + diffn].block(0, 0, N + 1, Lmat.BcVec[j].nbc()));
4134  }
4135  }
4136  subs_mat_row_counter += N + 1 + n - Lmat.BcVec[j].nbc();
4137  masterL.block(i * (N + 1), master_col_counter, N + 1,
4138  N + 1 + n - Lmat.BcVec[j].nbc()) = solver_matL;
4139  masterM.block(i * (N + 1), master_col_counter, N + 1,
4140  N + 1 + n - Lmat.BcVec[j].nbc()) = solver_matM;
4141  }
4142  subs_mat_col_counter += Lmat.BcVec[j].nbc();
4143  subs_mat_row_counter = 0;
4144  master_row_counter = 0;
4145  master_col_counter += N + 1 + n - Lmat.BcVec[j].nbc();
4146  }
4147  if (mat_temp.rows() != 0 || mat_temp.cols() != 0) {
4148  masterL.block(0, 0, c * (N + 1), c * (N + 1) + Lbc.m) +=
4149  masterL.block(0, 0, c * (N + 1), c * (N + 1) + Lbc.m).eval() +
4150  (subs_mat_col_mul * subs_mat);
4151  masterM.block(0, 0, c * (N + 1), c * (N + 1) + Lbc.m) +=
4152  masterM.block(0, 0, c * (N + 1), c * (N + 1) + Lbc.m).eval() +
4153  (subs_mat_col_mul2 * subs_mat);
4154  }
4155  // Now append the constraints:
4156 
4157  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> constraints_bigL(
4158  Lbc.m, c * (N + 1) + Lbc.m),
4159  constraints_smallL(Lbc.m, total_boundary_conditions),
4160  constraints_bigM(Lbc.m, c * (N + 1) + Lbc.m),
4161  constraints_smallM(Lbc.m, total_boundary_conditions);
4162  constraints_bigL.setConstant(0.0);
4163  constraints_smallL.setConstant(0.0);
4164  constraints_bigM.setConstant(0.0);
4165  constraints_smallM.setConstant(0.0);
4166  col_counter = 0;
4167  row_counter = 0;
4168  int col_counter2 = 0;
4169  int row_counter2 = 0;
4170  for (int i = 0; i < Lbc.m; i++) {
4171  for (int j = 0; j < Lbc.n; j++) {
4172  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> temp =
4173  Lbc(i, j, highest_each_column[j]);
4174 
4175  constraints_bigL.block(i, col_counter, 1,
4176  N + 1 + highest_each_column[j] -
4177  num_bc_each_var[j]) =
4178  temp.block(0, num_bc_each_var[j], 1,
4179  N + 1 + highest_each_column[j] - num_bc_each_var[j]);
4180 
4181  constraints_smallL.block(i, col_counter2, 1, num_bc_each_var[j]) =
4182  temp.block(0, 0, 1, num_bc_each_var[j]);
4183  // std::cout << "i = " << i << ", j = " << j << ",
4184  // highest_each_column["
4185  // << j << "]= " << highest_each_column[j] << '\n';
4186  temp = Mbc(i, j, highest_each_column[j]);
4187 
4188  constraints_bigM.block(i, col_counter, 1,
4189  N + 1 + highest_each_column[j] -
4190  num_bc_each_var[j]) =
4191  temp.block(0, num_bc_each_var[j], 1,
4192  N + 1 + highest_each_column[j] - num_bc_each_var[j]);
4193 
4194  constraints_smallM.block(i, col_counter2, 1, num_bc_each_var[j]) =
4195  temp.block(0, 0, 1, num_bc_each_var[j]);
4196  col_counter += N + 1 + highest_each_column[j] - num_bc_each_var[j];
4197  col_counter2 += num_bc_each_var[j];
4198  }
4199  col_counter = 0;
4200  col_counter2 = 0;
4201  }
4202  if (mat_temp.rows() != 0 || mat_temp.cols() != 0) {
4203  masterL.block(c * (N + 1), 0, Lbc.m, c * (N + 1) + Lbc.m) =
4204  constraints_bigL + constraints_smallL * subs_mat;
4205  masterM.block(c * (N + 1), 0, Lbc.m, c * (N + 1) + Lbc.m) =
4206  constraints_bigM + constraints_smallM * subs_mat;
4207  } else {
4208  masterL.block(c * (N + 1), 0, Lbc.m, c * (N + 1) + Lbc.m) =
4209  constraints_bigL;
4210  masterM.block(c * (N + 1), 0, Lbc.m, c * (N + 1) + Lbc.m) =
4211  constraints_bigM;
4212  }
4213 
4214 #ifndef SIS_USE_LAPACK
4215  Eigen::ColPivHouseholderQR<
4216  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> >
4217  solver(masterM);
4218  Eigen::ComplexEigenSolver<Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> >
4219  eigs;
4220  bool Is_M_Invertible;
4221  if (solver.isInvertible()) {
4222  Is_M_Invertible = true;
4223  eigs.compute(solver.inverse() * masterL);
4224  // std::cout << "Eigenvalues :\n" << eigs.eigenvalues() << '\n';
4225  } else {
4226  Is_M_Invertible = false;
4227  solver.compute(masterL);
4228  eigs.compute(solver.inverse() * masterM);
4229  // std::cout << "Eigenvalues :\n" << 1 / eigs.eigenvalues().array() <<
4230  // '\n';
4231  }
4232  // std::cin >> bre;
4233  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic>
4234  evecMat_master(c * (N + 1) + Lbc.m, c * (N + 1) + Lbc.m);
4235  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, 1> temp_vec;
4236  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> fir_n_mat,
4237  full_mat;
4238  if (subs_mat.size() > 0) {
4239  fir_n_mat = subs_mat * eigs.eigenvectors();
4240  }
4241  full_mat.resize(c * (N + 1) + Lbc.m + fir_n_mat.rows(),
4242  c * (N + 1) + Lbc.m);
4243 
4244  row_counter = 0;
4245  row_counter2 = 0;
4246  col_counter = 0;
4247  // Repack eigenvectors using fir_n_mat:
4248  for (int i = 0; i < c; i++) {
4249  int n = (highest_each_columnL[i] > highest_each_columnM[i])
4250  ? highest_each_columnL[i]
4251  : highest_each_columnM[i];
4252  if (subs_mat.size() > 0) {
4253  full_mat.block(row_counter, 0, num_bc_each_var[i],
4254  c * (N + 1) + Lbc.m) =
4255  fir_n_mat.block(col_counter, 0, num_bc_each_var[i],
4256  c * (N + 1) + Lbc.m);
4257  }
4258  row_counter += num_bc_each_var[i];
4259  col_counter += num_bc_each_var[i];
4260 
4261  full_mat.block(row_counter, 0, N + 1 + n - num_bc_each_var[i],
4262  c * (N + 1) + Lbc.m) =
4263  eigs.eigenvectors().block(row_counter2, 0,
4264  N + 1 + n - num_bc_each_var[i],
4265  c * (N + 1) + Lbc.m);
4266  row_counter += N + 1 + n - num_bc_each_var[i];
4267  row_counter2 += N + 1 + n - num_bc_each_var[i];
4268  }
4269 
4270  row_counter = 0;
4271  for (int i = 0; i < c; i++) {
4272  int n = (highest_each_columnL[i] > highest_each_columnM[i])
4273  ? highest_each_columnL[i]
4274  : highest_each_columnM[i];
4275  Mat.compute(n);
4276  evecMat_master.block(i * (N + 1), 0, N + 1, c * (N + 1) + Lbc.m) =
4277  Mat.mats2[n] *
4278  full_mat.block(row_counter, 0, N + 1 + n, c * (N + 1) + Lbc.m);
4279  row_counter += N + 1 + n;
4280  }
4281 
4282  std::vector<std::vector<T> > eigenval_trunc_sorter;
4283 
4284  eigenval_trunc_sorter.resize(c * (N + 1) + Lbc.m);
4285  for (int i = 0; i < c * (N + 1) + Lbc.m; i++) {
4286  eigenval_trunc_sorter[i].resize(2);
4287  }
4288 
4289  Eigen::Matrix<int, Eigen::Dynamic, 1> MPcount(c * (N + 1) + Lbc.m);
4290  MPcount.setConstant(0);
4291  std::vector<EigenSorter<T> > sorter;
4292  sorter.resize(c * (N + 1) + Lbc.m);
4293  for (int i = 0; i < c * (N + 1) + Lbc.m; i++) {
4294  sorter[i].compute(evecMat_master.block(0, i, c * (N + 1), 1), c);
4295  if (!Is_M_Invertible) {
4296  // If M is not invertible, there will be zero eigenvalues, so that 1/0 =
4297  // inf eigenvalue, remove them.
4298  if (abs(eigs.eigenvalues()[i]) < 1e-11) {
4299  sorter[i].numMp = N + 1;
4300  sorter[i].Mp = false;
4301  sorter[i].minVal = 1e11;
4302  }
4303  }
4304  // sorter[i].compute(evecMat_master.block(0, i, (N + 1), 1));
4305  if (sorter[i].Mp == true) {
4306  MPcount[i] = 1;
4307  }
4308  }
4309  int MPcount_sum = MPcount.sum();
4310  eigenvectorsMat.resize(num_vals);
4311  for (int i = 0; i < num_vals; i++) {
4312  eigenvectorsMat[i].resize(c, 1);
4313  }
4314  eigenvalues.resize(num_vals);
4315  if (MPcount_sum >= num_vals) {
4316  for (int i = 0; i < c * (N + 1) + Lbc.m; i++) {
4317  eigenval_trunc_sorter[i][0] = T(sorter[i].numMp);
4318  eigenval_trunc_sorter[i][1] = i;
4319  // std::cout << eigs.eigenvalues()[i] << " " << sorter[i].numMp <<
4320  // "\n"; std::cin > > bre;
4321  }
4322  std::sort(eigenval_trunc_sorter.begin(), eigenval_trunc_sorter.end());
4323  for (int i = 0; i < num_vals; i++) {
4324  if (Is_M_Invertible) {
4325  eigenvalues[i] = eigs.eigenvalues()[int(eigenval_trunc_sorter[i][1])];
4326  } else {
4327  eigenvalues[i] =
4328  1.0 / eigs.eigenvalues()[int(eigenval_trunc_sorter[i][1])];
4329  }
4330  }
4331  for (int j = 0; j < c; j++) {
4332  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
4333  ? highest_each_columnL[j]
4334  : highest_each_columnM[j];
4335 
4336  temp_vec.resize(N + 1 + n, 1);
4337  for (int i = 0; i < num_vals; i++) {
4338  eigenvectorsMat[i][j] = evecMat_master.block(
4339  j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
4340  eigenvectorsMat[i][j].dct_flag = SIS_CHEB_SPACE;
4341  }
4342  }
4343  } else {
4344  std::cout << "Last " << num_vals - MPcount_sum
4345  << " eigenvectors are not resolved to machine precision."
4346  << '\n';
4347  for (int i = 0; i < c * (N + 1) + Lbc.m; i++) {
4348  eigenval_trunc_sorter[i][0] = T(sorter[i].numMp);
4349  eigenval_trunc_sorter[i][1] = i;
4350  }
4351  std::sort(eigenval_trunc_sorter.begin(), eigenval_trunc_sorter.end());
4352  for (int i = 0; i < MPcount_sum; i++) {
4353  if (Is_M_Invertible) {
4354  eigenvalues[i] = eigs.eigenvalues()[int(eigenval_trunc_sorter[i][1])];
4355  } else {
4356  eigenvalues[i] =
4357  1.0 / eigs.eigenvalues()[int(eigenval_trunc_sorter[i][1])];
4358  }
4359  }
4360  for (int j = 0; j < c; j++) {
4361  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
4362  ? highest_each_columnL[j]
4363  : highest_each_columnM[j];
4364  temp_vec.resize(N + 1 + n, 1);
4365  for (int i = 0; i < MPcount_sum; i++) {
4366  eigenvectorsMat[i][j] = evecMat_master.block(
4367  j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
4368  eigenvectorsMat[i][j].dct_flag = SIS_CHEB_SPACE;
4369  }
4370  }
4371 
4372  std::vector<std::vector<T> > eigenval_trunc_sorter2;
4373  eigenval_trunc_sorter2.resize(c * (N + 1) + Lbc.m - MPcount_sum);
4374  for (int i = MPcount_sum; i < c * (N + 1) + Lbc.m; i++) {
4375  eigenval_trunc_sorter2[i - MPcount_sum].resize(2);
4376  eigenval_trunc_sorter2[i - MPcount_sum][0] =
4377  sorter[int(eigenval_trunc_sorter[i][1])].minVal;
4378  eigenval_trunc_sorter2[i - MPcount_sum][1] =
4379  eigenval_trunc_sorter[i][1];
4380  }
4381  std::sort(eigenval_trunc_sorter2.begin(), eigenval_trunc_sorter2.end());
4382  for (int i = MPcount_sum; i < num_vals; i++) {
4383  if (Is_M_Invertible) {
4384  eigenvalues[i] = eigs.eigenvalues()[int(
4385  eigenval_trunc_sorter2[i - MPcount_sum][1])];
4386  } else {
4387  eigenvalues[i] =
4388  1.0 / eigs.eigenvalues()[int(
4389  eigenval_trunc_sorter2[i - MPcount_sum][1])];
4390  }
4391  }
4392  for (int j = 0; j < c; j++) {
4393  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
4394  ? highest_each_columnL[j]
4395  : highest_each_columnM[j];
4396  Mat.compute(n);
4397  temp_vec.resize(N + 1 + n, 1);
4398  for (int i = MPcount_sum; i < num_vals; i++) {
4399  eigenvectorsMat[i][j] = evecMat_master.block(
4400  j * (N + 1), int(eigenval_trunc_sorter2[i - MPcount_sum][1]),
4401  N + 1, 1);
4402  eigenvectorsMat[i][j].dct_flag = SIS_CHEB_SPACE;
4403  }
4404  }
4405  }
4406 
4407 #else
4408  char jobvl = 'N'; // Don't compute left evecs
4409  char jobvr = 'V'; // Compute right evecs
4410  std::complex<double> wkopt; // Eistimate optimum workspace
4411  std::complex<double> *work; // allocate optimum workspace
4412  alpha.resize(masterL.rows(), 1); // alpha for gen. eig. prob.
4413  beta.resize(masterL.rows(), 1); // beta for gen. eig. prob.
4414 
4415  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> masterL_,
4416  masterM_, vl(masterL.rows(), masterL.rows()),
4417  vr(masterL.rows(), masterL.rows()), eigenvalues_temp(masterL.rows(), 1),
4418  alpha_temp(masterL.rows(), 1), beta_temp(masterL.rows(), 1);
4419  masterL_ = masterL;
4420  masterM_ = masterM;
4421  // vl : left evecs, vr: right evecs.
4422  int ldL = masterL.outerStride(); // ld for leading dimension
4423  int ldM = masterM.outerStride();
4424  int ldvl = vl.outerStride();
4425  int ldvr = vr.outerStride();
4426  int sizeL = masterL.rows();
4427  int lwork = -1; // set lwork to -1 to estimate workspace.
4428  double rwork[8 * sizeL];
4429 
4430  // call this to estimate workspace
4431  zggev_(&jobvl, &jobvr, &sizeL, masterL_.data(), &ldL, masterM_.data(), &ldM,
4432  alpha_temp.data(), beta_temp.data(), vl.data(), &ldvl, vr.data(),
4433  &ldvr, &wkopt, &lwork, rwork, &info);
4434 
4435  // Now allocate workspace:
4436  lwork = (int)real(wkopt);
4437  work = (std::complex<double> *)malloc(lwork * sizeof(std::complex<double>));
4438 
4439  // Solve eigenvalue problem:
4440  zggev_(&jobvl, &jobvr, &sizeL, masterL_.data(), &ldL, masterM_.data(), &ldM,
4441  alpha_temp.data(), beta_temp.data(), vl.data(), &ldvl, vr.data(),
4442  &ldvr, work, &lwork, rwork, &info);
4443 
4444  // Free workspace.
4445  free((void *)work);
4446 
4447  eigenvalues_temp = alpha_temp.array() / beta_temp.array();
4448 
4449  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic>
4450  evecMat_master(c * (N + 1), c * (N + 1) + Lbc.m);
4451  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, 1> temp_vec;
4452  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> fir_n_mat =
4453  subs_mat * vr;
4454  row_counter = 0;
4455  col_counter = 0;
4456  for (int i = 0; i < c; i++) {
4457  int n = (highest_each_columnL[i] > highest_each_columnM[i])
4458  ? highest_each_columnL[i]
4459  : highest_each_columnM[i];
4460  Mat.compute(n);
4461  // std::cout << "n = " << n << '\n';
4462  // std::cin > > bre;
4463 
4464  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> evecMat(
4465  N + 1 + n, c * (N + 1) + Lbc.m);
4466  evecMat.setConstant(0.0);
4467  evecMat.block(num_bc_each_var[i], 0, N + 1 + n - num_bc_each_var[i],
4468  c * (N + 1) + Lbc.m) =
4469  vr.block(row_counter, 0, N + 1 + n - num_bc_each_var[i],
4470  c * (N + 1) + Lbc.m);
4471  row_counter += N + 1 + n - num_bc_each_var[i];
4472  evecMat.block(0, 0, num_bc_each_var[i], c * (N + 1) + Lbc.m) =
4473  fir_n_mat.block(col_counter, 0, num_bc_each_var[i],
4474  c * (N + 1) + Lbc.m);
4475  col_counter += num_bc_each_var[i];
4476  evecMat_master.block(i * (N + 1), 0, N + 1, c * (N + 1) + Lbc.m) =
4477  Mat.mats2[n] * evecMat;
4478  }
4479  std::vector<std::vector<T> > eigenval_trunc_sorter;
4480 
4481  eigenval_trunc_sorter.resize(c * (N + 1) + Lbc.m);
4482  for (int i = 0; i < c * (N + 1) + Lbc.m; i++) {
4483  eigenval_trunc_sorter[i].resize(2);
4484  }
4485 
4486  Eigen::Matrix<int, Eigen::Dynamic, 1> MPcount(c * (N + 1) + Lbc.m);
4487  MPcount.setConstant(0);
4488  std::vector<EigenSorter<T> > sorter;
4489  sorter.resize(c * (N + 1) + Lbc.m);
4490  for (int i = 0; i < c * (N + 1) + Lbc.m; i++) {
4491  sorter[i].compute(evecMat_master.block(0, i, c * (N + 1), 1), c);
4492  // sorter[i].compute(evecMat_master.block(0, i, (N + 1), 1));
4493  if (sorter[i].Mp == true) {
4494  MPcount[i] = 1;
4495  }
4496  }
4497  int MPcount_sum = MPcount.sum();
4498 
4499  if (num_vals > masterL.rows()) {
4500  std::cout << "Only " << masterL.rows()
4501  << " eigenvalues can be calculated."
4502  << "Storing only that many." << '\n';
4503  num_vals = masterL.rows();
4504  }
4505  eigenvectorsMat.resize(num_vals);
4506  for (int i = 0; i < num_vals; i++) {
4507  eigenvectorsMat[i].resize(c, 1);
4508  }
4509  eigenvalues.resize(num_vals);
4510  if (MPcount_sum >= num_vals) {
4511  for (int i = 0; i < c * (N + 1); i++) {
4512  eigenval_trunc_sorter[i][0] = T(sorter[i].numMp);
4513  eigenval_trunc_sorter[i][1] = i;
4514  // std::cout << eigs.eigenvalues()[i] << " " << sorter[i].numMp <<
4515  // "\n"; std::cin > > bre;
4516  }
4517  std::sort(eigenval_trunc_sorter.begin(), eigenval_trunc_sorter.end());
4518  for (int i = 0; i < num_vals; i++) {
4519  eigenvalues[i] = eigenvalues_temp(int(eigenval_trunc_sorter[i][1]), 0);
4520  alpha[i] = alpha_temp(int(eigenval_trunc_sorter[i][1]), 0);
4521  beta[i] = beta_temp(int(eigenval_trunc_sorter[i][1]), 0);
4522  }
4523  for (int j = 0; j < c; j++) {
4524  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
4525  ? highest_each_columnL[j]
4526  : highest_each_columnM[j];
4527 
4528  temp_vec.resize(N + 1 + n, 1);
4529  for (int i = 0; i < num_vals; i++) {
4530  eigenvectorsMat[i][j] = evecMat_master.block(
4531  j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
4532  eigenvectorsMat[i][j].dct_flag = SIS_CHEB_SPACE;
4533  }
4534  }
4535  } else {
4536  std::cout << "Last " << num_vals - MPcount_sum
4537  << " eigenvectors are not resolved to machine precision."
4538  << '\n';
4539  for (int i = 0; i < c * (N + 1); i++) {
4540  eigenval_trunc_sorter[i][0] = T(sorter[i].numMp);
4541  eigenval_trunc_sorter[i][1] = i;
4542  }
4543  std::sort(eigenval_trunc_sorter.begin(), eigenval_trunc_sorter.end());
4544  for (int i = 0; i < MPcount_sum; i++) {
4545  eigenvalues[i] = eigenvalues_temp(int(eigenval_trunc_sorter[i][1]), 0);
4546  alpha[i] = alpha_temp(int(eigenval_trunc_sorter[i][1]), 0);
4547  beta[i] = beta_temp(int(eigenval_trunc_sorter[i][1]), 0);
4548  }
4549  for (int j = 0; j < c; j++) {
4550  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
4551  ? highest_each_columnL[j]
4552  : highest_each_columnM[j];
4553  temp_vec.resize(N + 1 + n, 1);
4554  for (int i = 0; i < MPcount_sum; i++) {
4555  eigenvectorsMat[i][j] = evecMat_master.block(
4556  j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
4557  eigenvectorsMat[i][j].dct_flag = SIS_CHEB_SPACE;
4558  }
4559  }
4560 
4561  std::vector<std::vector<T> > eigenval_trunc_sorter2;
4562  eigenval_trunc_sorter2.resize(c * (N + 1) + Lbc.m - MPcount_sum);
4563  for (int i = MPcount_sum; i < c * (N + 1) + Lbc.m; i++) {
4564  eigenval_trunc_sorter2[i - MPcount_sum].resize(2);
4565  eigenval_trunc_sorter2[i - MPcount_sum][0] =
4566  sorter[int(eigenval_trunc_sorter[i][1])].minVal;
4567  eigenval_trunc_sorter2[i - MPcount_sum][1] =
4568  eigenval_trunc_sorter[i][1];
4569  }
4570  std::sort(eigenval_trunc_sorter2.begin(), eigenval_trunc_sorter2.end());
4571  for (int i = MPcount_sum; i < num_vals; i++) {
4572  eigenvalues[i] = eigenvalues_temp(
4573  int(eigenval_trunc_sorter2[i - MPcount_sum][1]), 0);
4574  alpha[i] =
4575  alpha_temp(int(eigenval_trunc_sorter2[i - MPcount_sum][1]), 0);
4576  beta[i] = beta_temp(int(eigenval_trunc_sorter2[i - MPcount_sum][1]), 0);
4577  }
4578  for (int j = 0; j < c; j++) {
4579  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
4580  ? highest_each_columnL[j]
4581  : highest_each_columnM[j];
4582  Mat.compute(n);
4583  temp_vec.resize(N + 1 + n, 1);
4584  for (int i = MPcount_sum; i < num_vals; i++) {
4585  eigenvectorsMat[i][j] = evecMat_master.block(
4586  j * (N + 1), int(eigenval_trunc_sorter2[i - MPcount_sum][1]),
4587  N + 1, 1);
4588  eigenvectorsMat[i][j].dct_flag = SIS_CHEB_SPACE;
4589  }
4590  }
4591  }
4592 
4593 #endif
4594  }
4595 
4604  const LinopMat<T> &Mmat_, int num_vals,
4605  const BcMat<T> &Lbc_embed_,
4606  const BcMat<T> &Lbc_append_,
4607  const BcMat<T> &Mbc_append_) {
4608  LinopMat<T> Lmat = Lmat_;
4609  LinopMat<T> Mmat = Mmat_;
4610  BcMat<T> Lbc_embed = Lbc_embed_;
4611  BcMat<T> Lbc_append = Lbc_append_;
4612  BcMat<T> Mbc_append = Mbc_append_;
4613  int bre;
4614  int total_of_all_orders = 0;
4615  int total_boundary_conditions = 0;
4616  int total_constraints = 0;
4617  if (Lmat.r != Lmat.c) {
4618  std::cout << "Solution only possible with square LinopMats. Exiting ..."
4619  << '\n';
4620  exit(1);
4621  }
4622  if (Mmat.r != Mmat.c) {
4623  std::cout << "Solution only possible with square LinopMats. Exiting ..."
4624  << '\n';
4625  exit(1);
4626  }
4627  if (Mmat.c != Lmat.c) {
4628  std::cout << "Both matrices have to be of same size. Exiting ..." << '\n';
4629  exit(1);
4630  }
4631 
4632  if (Lmat.c != Lbc_embed.n) {
4633  std::cout
4634  << "Number of columns in Lbc_embed have to be equal to number of "
4635  << "columns in Lmat . Exiting .... In line " << __LINE__ << '\n';
4636  exit(1);
4637  }
4638  if (Lmat.c != Lbc_append.n) {
4639  std::cout
4640  << "Number of columns in Lbc_append have to be equal to number of "
4641  << "columns in Lmat . Exiting .... In line " << __LINE__ << '\n';
4642  exit(1);
4643  }
4644  if (Lmat.c != Mbc_append.n) {
4645  std::cout
4646  << "Number of columns in Mbc_append have to be equal to number of "
4647  << "columns in Lmat . Exiting .... In line " << __LINE__ << '\n';
4648  exit(1);
4649  }
4650  if (Lbc_append.m != Mbc_append.m) {
4651  std::cout << "Number of rows in Mbc_append have to be equal to number of "
4652  << "rows in Lbc_append. Exiting .... In line " << __LINE__
4653  << '\n';
4654  exit(1);
4655  }
4656 
4657  int r = Lmat.r, c = Lmat.c;
4658  // Find the highest derivative in each column. To do this create a vector
4659  // highest_each_column, and a temp_int_vec that will hold all values of a
4660  // given column to and the maximum will be stored in highest_each_column
4661  std::vector<int> highest_each_columnL, highest_each_columnM,
4662  highest_each_column;
4663  highest_each_columnL.resize(c);
4664  highest_each_columnM.resize(c);
4665  highest_each_column.resize(c);
4666 
4667  std::vector<int> temp_vec_int;
4668  temp_vec_int.resize(r);
4669  for (int j = 0; j < c; j++) {
4670  for (int i = 0; i < r; i++) {
4671  temp_vec_int[i] = Lmat(i, j).n;
4672  }
4673  highest_each_columnL[j] =
4674  *std::max_element(temp_vec_int.begin(), temp_vec_int.end());
4675  }
4676  for (int j = 0; j < c; j++) {
4677  for (int i = 0; i < r; i++) {
4678  temp_vec_int[i] = Mmat(i, j).n;
4679  }
4680  highest_each_columnM[j] =
4681  *std::max_element(temp_vec_int.begin(), temp_vec_int.end());
4682  }
4683  for (int i = 0; i < c; i++) {
4684  total_of_all_orders += (highest_each_columnL[i] > highest_each_columnM[i])
4685  ? highest_each_columnL[i]
4686  : highest_each_columnM[i];
4687  highest_each_column[i] =
4688  (highest_each_columnL[i] > highest_each_columnM[i])
4689  ? highest_each_columnL[i]
4690  : highest_each_columnM[i];
4691  }
4692  total_boundary_conditions = Lbc_embed.m + Lbc_append.m;
4693 
4694  // total_of_all_orders has to be equal to total number of boundary
4695  // conditions, else the problem is ill-posed, if ill-posed, cout the same
4696  // and exit.
4697  if (total_of_all_orders != total_boundary_conditions) {
4698  std::cout << "The problem is ill-posed, the total of the highest "
4699  "orders of all "
4700  "dependent variables has to be equal to the total number of "
4701  "boundary conditions specified."
4702  "\n "
4703  "Total no. of boundary conditions: "
4704  << total_boundary_conditions
4705  << "\n"
4706  "Total of all orders: "
4707  << total_of_all_orders << "\n Exiting ...\n";
4708  exit(1);
4709  }
4710  // Declare the master matrix L:
4711  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> masterL(
4712  r * (N + 1), c * (N + 1) + total_boundary_conditions);
4713  // Declare the master matrix M:
4714  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> masterM(
4715  r * (N + 1), c * (N + 1) + total_boundary_conditions);
4716 
4717  masterL.setConstant(0.0);
4718  masterM.setConstant(0.0);
4719  MatGen<T> Mat;
4720  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> subs_mat;
4721  subs_mat.resize(total_boundary_conditions, (N + 1) * c);
4722  subs_mat.setConstant(0.0);
4723  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> mat_temp(
4724  total_boundary_conditions, total_boundary_conditions),
4725  constraints_embed(Lbc_embed.m, c * (N + 1) + total_of_all_orders);
4726 
4727  mat_temp.setConstant(0.0);
4728  int row_counter = 0, col_counter = 0;
4729 
4730  for (int i = 0; i < Lbc_embed.m; i++) {
4731  for (int j = 0; j < Lbc_embed.n; j++) {
4732  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> temp =
4733  Lbc_embed(i, j, highest_each_column[j]);
4734  constraints_embed.block(i, col_counter, 1, temp.cols()) = temp;
4735  col_counter += temp.cols();
4736  }
4737  col_counter = 0;
4738  }
4739 
4740  Eigen::ColPivHouseholderQR<
4741  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> >
4742  qr;
4743  qr.compute(constraints_embed);
4744  if (qr.rank() != constraints_embed.rows()) {
4745  std::cout << "The boundary conditions supplied are not "
4746  << " linearly independent." << '\n';
4747  std::cout << "qr.rank = " << qr.rank()
4748  << ", no. bcs: " << total_boundary_conditions << ". Exiting ..."
4749  << '\n';
4750  exit(1);
4751  }
4752 
4753  // Permutation matrix
4754  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> P;
4755  P = qr.colsPermutation();
4756  // Permute constraints
4757  constraints_embed = constraints_embed * P;
4758  mat_temp = constraints_embed.block(0, 0, constraints_embed.rows(),
4759  constraints_embed.rows());
4760 
4761  Eigen::ColPivHouseholderQR<
4762  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> >
4763  consSolver(mat_temp);
4764  subs_mat = -consSolver.inverse() *
4765  constraints_embed.block(
4766  0, constraints_embed.rows(), constraints_embed.rows(),
4767  constraints_embed.cols() - constraints_embed.rows());
4768 
4769  row_counter = 0;
4770  col_counter = 0;
4771  int master_row_counter = 0;
4772  int master_col_counter = 0;
4773  for (int j = 0; j < c; j++) {
4774  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
4775  ? highest_each_columnL[j]
4776  : highest_each_columnM[j];
4777  Mat.compute(n);
4778  for (int i = 0; i < r; i++) {
4779  int diffn = n - Lmat(i, j).n;
4780  if (Lmat(i, j).NCC == 0) {
4781  for (int k = 0; k < Lmat(i, j).n + 1; k++) {
4782  masterL.block(master_row_counter, master_col_counter, N + 1,
4783  N + 1 + n) +=
4784  Lmat(i, j).coef[k] *
4785  (Mat.mats2[k + diffn].block(0, 0, N + 1, N + 1 + n));
4786  }
4787  } else {
4788  for (int k = 0; k < Lmat(i, j).n + 1; k++) {
4789  masterL.block(master_row_counter, master_col_counter, N + 1,
4790  N + 1 + n) +=
4791  Lmat(i, j).coefFun[k].MultMat().block(0, 0, N + 1, N + 1) *
4792  (Mat.mats2[k + diffn].block(0, 0, N + 1, N + 1 + n));
4793  }
4794  }
4795  diffn = n - Mmat(i, j).n;
4796  if (Mmat(i, j).NCC == 0) {
4797  for (int k = 0; k < Mmat(i, j).n + 1; k++) {
4798  masterM.block(master_row_counter, master_col_counter, N + 1,
4799  N + 1 + n) +=
4800  Mmat(i, j).coef[k] *
4801  (Mat.mats2[k + diffn].block(0, 0, N + 1, N + 1 + n));
4802  }
4803  } else {
4804  for (int k = 0; k < Mmat(i, j).n + 1; k++) {
4805  masterM.block(master_row_counter, master_col_counter, N + 1,
4806  N + 1 + n) +=
4807  Mmat(i, j).coefFun[k].MultMat().block(0, 0, N + 1, N + 1) *
4808  (Mat.mats2[k + diffn].block(0, 0, N + 1, N + 1 + n));
4809  }
4810  }
4811  master_row_counter += N + 1;
4812  }
4813  master_row_counter = 0;
4814  master_col_counter += N + 1 + n;
4815  }
4816  // Permute columns of M and L:
4817  masterL = masterL * P;
4818  masterM = masterM * P;
4819 
4820  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> masterL2(
4821  r * (N + 1) + Lbc_append.m, c * (N + 1) + Lbc_append.m),
4822  masterM2(r * (N + 1) + Lbc_append.m, c * (N + 1) + Lbc_append.m);
4823 
4824  masterL2.block(0, 0, r * (N + 1), r * (N + 1) + Lbc_append.m) =
4825  masterL.block(0, constraints_embed.rows(), c * (N + 1),
4826  c * (N + 1) + Lbc_append.m) +
4827  (masterL.block(0, 0, c * (N + 1), constraints_embed.rows()) * subs_mat);
4828  masterM2.block(0, 0, r * (N + 1), r * (N + 1) + Lbc_append.m) =
4829  masterM.block(0, constraints_embed.rows(), c * (N + 1),
4830  c * (N + 1) + Lbc_append.m) +
4831  (masterM.block(0, 0, c * (N + 1), constraints_embed.rows()) * subs_mat);
4832 
4833  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> constraints_appendL(
4834  Lbc_append.m, c * (N + 1) + total_of_all_orders),
4835  constraints_appendM(Lbc_append.m, c * (N + 1) + total_of_all_orders);
4836  col_counter = 0;
4837  for (int i = 0; i < Lbc_append.m; i++) {
4838  for (int j = 0; j < Lbc_append.n; j++) {
4839  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> temp =
4840  Lbc_append(i, j, highest_each_column[j]);
4841  constraints_appendL.block(i, col_counter, 1, temp.cols()) = temp;
4842  col_counter += temp.cols();
4843  }
4844  col_counter = 0;
4845  }
4846  col_counter = 0;
4847  for (int i = 0; i < Lbc_append.m; i++) {
4848  for (int j = 0; j < Lbc_append.n; j++) {
4849  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> temp =
4850  Mbc_append(i, j, highest_each_column[j]);
4851  constraints_appendM.block(i, col_counter, 1, temp.cols()) = temp;
4852  col_counter += temp.cols();
4853  }
4854  col_counter = 0;
4855  }
4856  constraints_appendM = constraints_appendM * P;
4857  constraints_appendL = constraints_appendL * P;
4858 
4859  masterL2.block(r * (N + 1), 0, Lbc_append.m, r * (N + 1) + Lbc_append.m) =
4860  constraints_appendL.block(0, Lbc_embed.m, Lbc_append.m,
4861  r * (N + 1) + Lbc_append.m) +
4862  (constraints_appendL.block(0, 0, Lbc_append.m, Lbc_embed.m) * subs_mat);
4863 
4864  masterM2.block(r * (N + 1), 0, Lbc_append.m, r * (N + 1) + Lbc_append.m) =
4865  constraints_appendM.block(0, Lbc_embed.m, Lbc_append.m,
4866  r * (N + 1) + Lbc_append.m) +
4867  (constraints_appendM.block(0, 0, Lbc_append.m, Lbc_embed.m) * subs_mat);
4868 
4869 #ifndef SIS_USE_LAPACK
4870  Eigen::ColPivHouseholderQR<
4871  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> >
4872  solver(masterM2);
4873  Eigen::ComplexEigenSolver<Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> >
4874  eigs;
4875  bool Is_M_Invertible;
4876  if (solver.isInvertible()) {
4877  // std::cout << "M is invertible" << '\n';
4878  // std::cin >> bre;
4879  Is_M_Invertible = true;
4880  eigs.compute(solver.inverse() * masterL2);
4881  // std::cout << "Eigenvalues :\n" << eigs.eigenvalues() << '\n';
4882  } else {
4883  // std::cout << "M is not invertible." << '\n';
4884  // std::cin >> bre;
4885  Is_M_Invertible = false;
4886  solver.compute(masterL2);
4887  eigs.compute(solver.inverse() * masterM2);
4888  // std::cout << "Eigenvalues :\n" << 1 / eigs.eigenvalues().array() <<
4889  // '\n';
4890  }
4891  // std::cin >> bre;
4892  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> evecMat_master(
4893  c * (N + 1), c * (N + 1) + Lbc_append.m);
4894  Eigen::Matrix<T, Eigen::Dynamic, 1> temp_vec;
4895  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> fir_n_mat =
4896  subs_mat * eigs.eigenvectors();
4897  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> evecMat(
4898  c * (N + 1) + total_boundary_conditions, c * (N + 1) + Lbc_append.m);
4899  evecMat << fir_n_mat, eigs.eigenvectors();
4900 
4901  // Unpermute eveMat:
4902  evecMat = P * evecMat;
4903  row_counter = 0;
4904  col_counter = 0;
4905  for (int i = 0; i < c; i++) {
4906  int n = (highest_each_columnL[i] > highest_each_columnM[i])
4907  ? highest_each_columnL[i]
4908  : highest_each_columnM[i];
4909  Mat.compute(n);
4910  evecMat_master.block(i * (N + 1), 0, N + 1, c * (N + 1) + Lbc_append.m) =
4911  Mat.mats2[n] *
4912  evecMat.block(row_counter, 0, N + 1 + n, c * (N + 1) + Lbc_append.m);
4913  row_counter += N + 1 + n;
4914  }
4915  std::vector<std::vector<T> > eigenval_trunc_sorter;
4916 
4917  eigenval_trunc_sorter.resize(c * (N + 1) + Lbc_append.m);
4918  for (int i = 0; i < c * (N + 1) + Lbc_append.m; i++) {
4919  eigenval_trunc_sorter[i].resize(2);
4920  }
4921 
4922  Eigen::Matrix<int, Eigen::Dynamic, 1> MPcount(c * (N + 1) + Lbc_append.m);
4923  MPcount.setConstant(0);
4924  std::vector<EigenSorter<T> > sorter;
4925  sorter.resize(c * (N + 1) + Lbc_append.m);
4926  for (int i = 0; i < c * (N + 1) + Lbc_append.m; i++) {
4927  sorter[i].compute(evecMat_master.block(0, i, c * (N + 1), 1), c);
4928  if (!Is_M_Invertible) {
4929  // If M is not invertible, there will be zero eigenvalues, so that 1/0 =
4930  // inf eigenvalue, remove them.
4931  if (abs(eigs.eigenvalues()[i]) < 1e-11) {
4932  sorter[i].numMp = N + 1;
4933  sorter[i].Mp = false;
4934  sorter[i].minVal = 1e11;
4935  }
4936  }
4937  // sorter[i].compute(evecMat_master.block(0, i, (N + 1), 1));
4938  if (sorter[i].Mp == true) {
4939  MPcount[i] = 1;
4940  }
4941  }
4942  if (num_vals > masterL.rows()) {
4943  std::cout << "Only " << masterL.rows()
4944  << " eigenvalues can be calculated."
4945  << "Storing only that many." << '\n';
4946  num_vals = masterL.rows();
4947  }
4948  int MPcount_sum = MPcount.sum();
4949  eigenvectorsMat.resize(num_vals);
4950  for (int i = 0; i < num_vals; i++) {
4951  eigenvectorsMat[i].resize(c, 1);
4952  }
4953  eigenvalues.resize(num_vals);
4954  if (MPcount_sum >= num_vals) {
4955  for (int i = 0; i < c * (N + 1) + Lbc_append.m; i++) {
4956  eigenval_trunc_sorter[i][0] = T(sorter[i].numMp);
4957  eigenval_trunc_sorter[i][1] = i;
4958  // std::cout << eigs.eigenvalues()[i] << " " << sorter[i].numMp <<
4959  // "\n"; std::cin > > bre;
4960  }
4961  std::sort(eigenval_trunc_sorter.begin(), eigenval_trunc_sorter.end());
4962  for (int i = 0; i < num_vals; i++) {
4963  if (Is_M_Invertible) {
4964  eigenvalues[i] = eigs.eigenvalues()[int(eigenval_trunc_sorter[i][1])];
4965  } else {
4966  eigenvalues[i] =
4967  1.0 / eigs.eigenvalues()[int(eigenval_trunc_sorter[i][1])];
4968  }
4969  }
4970  for (int j = 0; j < c; j++) {
4971  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
4972  ? highest_each_columnL[j]
4973  : highest_each_columnM[j];
4974 
4975  temp_vec.resize(N + 1 + n, 1);
4976  for (int i = 0; i < num_vals; i++) {
4977  eigenvectorsMat[i][j] = evecMat_master.block(
4978  j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
4979  }
4980  }
4981  } else {
4982  std::cout << "Last " << num_vals - MPcount_sum
4983  << " eigenvectors are not resolved to machine precision."
4984  << '\n';
4985  for (int i = 0; i < c * (N + 1) + Lbc_append.m; i++) {
4986  eigenval_trunc_sorter[i][0] = T(sorter[i].numMp);
4987  eigenval_trunc_sorter[i][1] = i;
4988  }
4989  std::sort(eigenval_trunc_sorter.begin(), eigenval_trunc_sorter.end());
4990  for (int i = 0; i < MPcount_sum; i++) {
4991  if (Is_M_Invertible) {
4992  eigenvalues[i] = eigs.eigenvalues()[int(eigenval_trunc_sorter[i][1])];
4993  } else {
4994  eigenvalues[i] =
4995  1.0 / eigs.eigenvalues()[int(eigenval_trunc_sorter[i][1])];
4996  }
4997  }
4998  for (int j = 0; j < c; j++) {
4999  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
5000  ? highest_each_columnL[j]
5001  : highest_each_columnM[j];
5002  temp_vec.resize(N + 1 + n, 1);
5003  for (int i = 0; i < MPcount_sum; i++) {
5004  eigenvectorsMat[i][j] = evecMat_master.block(
5005  j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
5006  }
5007  }
5008 
5009  std::vector<std::vector<T> > eigenval_trunc_sorter2;
5010  eigenval_trunc_sorter2.resize(c * (N + 1) + Lbc_append.m - MPcount_sum);
5011  for (int i = MPcount_sum; i < c * (N + 1) + Lbc_append.m; i++) {
5012  eigenval_trunc_sorter2[i - MPcount_sum].resize(2);
5013  eigenval_trunc_sorter2[i - MPcount_sum][0] =
5014  sorter[int(eigenval_trunc_sorter[i][1])].minVal;
5015  eigenval_trunc_sorter2[i - MPcount_sum][1] =
5016  eigenval_trunc_sorter[i][1];
5017  }
5018  std::sort(eigenval_trunc_sorter2.begin(), eigenval_trunc_sorter2.end());
5019  for (int i = MPcount_sum; i < num_vals; i++) {
5020  if (Is_M_Invertible) {
5021  eigenvalues[i] = eigs.eigenvalues()[int(
5022  eigenval_trunc_sorter2[i - MPcount_sum][1])];
5023  } else {
5024  eigenvalues[i] =
5025  1.0 / eigs.eigenvalues()[int(
5026  eigenval_trunc_sorter2[i - MPcount_sum][1])];
5027  }
5028  }
5029  for (int j = 0; j < c; j++) {
5030  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
5031  ? highest_each_columnL[j]
5032  : highest_each_columnM[j];
5033  Mat.compute(n);
5034  temp_vec.resize(N + 1 + n, 1);
5035  for (int i = MPcount_sum; i < num_vals; i++) {
5036  eigenvectorsMat[i][j] = evecMat_master.block(
5037  j * (N + 1), int(eigenval_trunc_sorter2[i - MPcount_sum][1]),
5038  N + 1, 1);
5039  }
5040  }
5041  }
5042 #else
5043  std::cout << "Using lapack routine..." << '\n';
5044  char jobvl = 'N'; // Don't compute left evecs
5045  char jobvr = 'V'; // Compute right evecs
5046  std::complex<double> wkopt; // Eistimate optimum workspace
5047  std::complex<double> *work; // allocate optimum workspace
5048  alpha.resize(masterL2.rows(), 1); // alpha for gen. eig. prob.
5049  beta.resize(masterL2.rows(), 1); // beta for gen. eig. prob.
5050 
5051  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> masterL2_,
5052  masterM2_, vl(masterL2.rows(), masterL2.rows()),
5053  vr(masterL2.rows(), masterL2.rows()),
5054  eigenvalues_temp(masterL2.rows(), 1), alpha_temp(masterL2.rows(), 1),
5055  beta_temp(masterL2.rows(), 1);
5056  masterL2_ = masterL2;
5057  masterM2_ = masterM2;
5058  // vl : left evecs, vr: right evecs.
5059  int ldL = masterL2.outerStride(); // ld for leading dimension
5060  int ldM = masterM2.outerStride();
5061  int ldvl = vl.outerStride();
5062  int ldvr = vr.outerStride();
5063  int sizeL = masterL2.rows();
5064  int lwork = -1; // set lwork to -1 to estimate workspace.
5065  double rwork[8 * sizeL];
5066 
5067  // call this to estimate workspace
5068  zggev_(&jobvl, &jobvr, &sizeL, masterL2_.data(), &ldL, masterM2_.data(),
5069  &ldM, alpha_temp.data(), beta_temp.data(), vl.data(), &ldvl,
5070  vr.data(), &ldvr, &wkopt, &lwork, rwork, &info);
5071 
5072  // Now allocate workspace:
5073  lwork = (int)real(wkopt);
5074  work = (std::complex<double> *)malloc(lwork * sizeof(std::complex<double>));
5075 
5076  // Solve eigenvalue problem:
5077  zggev_(&jobvl, &jobvr, &sizeL, masterL2_.data(), &ldL, masterM2_.data(),
5078  &ldM, alpha_temp.data(), beta_temp.data(), vl.data(), &ldvl,
5079  vr.data(), &ldvr, work, &lwork, rwork, &info);
5080 
5081  // Free workspace.
5082  free((void *)work);
5083 
5084  eigenvalues_temp = alpha_temp.array() / beta_temp.array();
5085 
5086  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic>
5087  evecMat_master(c * (N + 1), c * (N + 1) + Lbc_append.m);
5088  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, 1> temp_vec;
5089  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> fir_n_mat =
5090  subs_mat * vr;
5091  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> evecMat(
5092  c * (N + 1) + total_boundary_conditions, c * (N + 1) + Lbc_append.m);
5093  evecMat << fir_n_mat, vr;
5094  // Unpermute eveMat:
5095  evecMat = P * evecMat;
5096  row_counter = 0;
5097  col_counter = 0;
5098  for (int i = 0; i < c; i++) {
5099  int n = (highest_each_columnL[i] > highest_each_columnM[i])
5100  ? highest_each_columnL[i]
5101  : highest_each_columnM[i];
5102  Mat.compute(n);
5103  evecMat_master.block(i * (N + 1), 0, N + 1, c * (N + 1) + Lbc_append.m) =
5104  Mat.mats2[n] *
5105  evecMat.block(row_counter, 0, N + 1 + n, c * (N + 1) + Lbc_append.m);
5106  row_counter += N + 1 + n;
5107  }
5108  std::vector<std::vector<T> > eigenval_trunc_sorter;
5109 
5110  eigenval_trunc_sorter.resize(c * (N + 1) + Lbc_append.m);
5111  for (int i = 0; i < c * (N + 1) + Lbc_append.m; i++) {
5112  eigenval_trunc_sorter[i].resize(2);
5113  }
5114 
5115  Eigen::Matrix<int, Eigen::Dynamic, 1> MPcount(c * (N + 1) + Lbc_append.m);
5116  MPcount.setConstant(0);
5117  std::vector<EigenSorter<T> > sorter;
5118  sorter.resize(c * (N + 1) + Lbc_append.m);
5119  for (int i = 0; i < c * (N + 1) + Lbc_append.m; i++) {
5120  sorter[i].compute(evecMat_master.block(0, i, c * (N + 1), 1), c);
5121  // sorter[i].compute(evecMat_master.block(0, i, (N + 1), 1));
5122  if (sorter[i].Mp == true) {
5123  MPcount[i] = 1;
5124  }
5125  }
5126  if (num_vals > masterL2.rows()) {
5127  std::cout << "Only " << masterL2.rows()
5128  << " eigenvalues can be calculated."
5129  << "Storing only that many." << '\n';
5130  num_vals = masterL2.rows();
5131  }
5132 
5133  int MPcount_sum = MPcount.sum();
5134  eigenvectorsMat.resize(num_vals);
5135  for (int i = 0; i < num_vals; i++) {
5136  eigenvectorsMat[i].resize(c, 1);
5137  }
5138  eigenvalues.resize(num_vals);
5139  beta.resize(num_vals);
5140  alpha.resize(num_vals);
5141  if (MPcount_sum >= num_vals) {
5142  for (int i = 0; i < c * (N + 1) + Lbc_append.m; i++) {
5143  eigenval_trunc_sorter[i][0] = T(sorter[i].numMp);
5144  eigenval_trunc_sorter[i][1] = i;
5145  // std::cout << eigs.eigenvalues()[i] << " " << sorter[i].numMp <<
5146  // "\n"; std::cin > > bre;
5147  }
5148  std::sort(eigenval_trunc_sorter.begin(), eigenval_trunc_sorter.end());
5149  for (int i = 0; i < num_vals; i++) {
5150  eigenvalues[i] = eigenvalues_temp(int(eigenval_trunc_sorter[i][1]), 0);
5151  alpha[i] = alpha_temp(int(eigenval_trunc_sorter[i][1]), 0);
5152  beta[i] = beta_temp(int(eigenval_trunc_sorter[i][1]), 0);
5153  }
5154  for (int j = 0; j < c; j++) {
5155  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
5156  ? highest_each_columnL[j]
5157  : highest_each_columnM[j];
5158 
5159  temp_vec.resize(N + 1 + n, 1);
5160  for (int i = 0; i < num_vals; i++) {
5161  eigenvectorsMat[i][j] = evecMat_master.block(
5162  j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
5163  eigenvectorsMat[i][j].dct_flag = SIS_CHEB_SPACE;
5164  }
5165  }
5166  } else {
5167  std::cout << "Last " << num_vals - MPcount_sum
5168  << " eigenvectors are not resolved to machine precision."
5169  << '\n';
5170  for (int i = 0; i < c * (N + 1) + Lbc_append.m; i++) {
5171  eigenval_trunc_sorter[i][0] = T(sorter[i].numMp);
5172  eigenval_trunc_sorter[i][1] = i;
5173  }
5174  std::sort(eigenval_trunc_sorter.begin(), eigenval_trunc_sorter.end());
5175  for (int i = 0; i < MPcount_sum; i++) {
5176  eigenvalues[i] = eigenvalues_temp(int(eigenval_trunc_sorter[i][1]), 0);
5177  alpha[i] = alpha_temp(int(eigenval_trunc_sorter[i][1]), 0);
5178  beta[i] = beta_temp(int(eigenval_trunc_sorter[i][1]), 0);
5179  }
5180  for (int j = 0; j < c; j++) {
5181  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
5182  ? highest_each_columnL[j]
5183  : highest_each_columnM[j];
5184  temp_vec.resize(N + 1 + n, 1);
5185  for (int i = 0; i < MPcount_sum; i++) {
5186  eigenvectorsMat[i][j] = evecMat_master.block(
5187  j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
5188  eigenvectorsMat[i][j].dct_flag = SIS_CHEB_SPACE;
5189  }
5190  }
5191 
5192  std::vector<std::vector<T> > eigenval_trunc_sorter2;
5193  eigenval_trunc_sorter2.resize(c * (N + 1) + Lbc_append.m - MPcount_sum);
5194  for (int i = MPcount_sum; i < c * (N + 1) + Lbc_append.m; i++) {
5195  eigenval_trunc_sorter2[i - MPcount_sum].resize(2);
5196  eigenval_trunc_sorter2[i - MPcount_sum][0] =
5197  sorter[int(eigenval_trunc_sorter[i][1])].minVal;
5198  eigenval_trunc_sorter2[i - MPcount_sum][1] =
5199  eigenval_trunc_sorter[i][1];
5200  }
5201  std::sort(eigenval_trunc_sorter2.begin(), eigenval_trunc_sorter2.end());
5202  for (int i = MPcount_sum; i < num_vals; i++) {
5203  eigenvalues[i] = eigenvalues_temp(
5204  int(eigenval_trunc_sorter2[i - MPcount_sum][1]), 0);
5205  alpha[i] =
5206  alpha_temp(int(eigenval_trunc_sorter2[i - MPcount_sum][1]), 0);
5207  beta[i] = beta_temp(int(eigenval_trunc_sorter2[i - MPcount_sum][1]), 0);
5208  }
5209  for (int j = 0; j < c; j++) {
5210  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
5211  ? highest_each_columnL[j]
5212  : highest_each_columnM[j];
5213  Mat.compute(n);
5214  temp_vec.resize(N + 1 + n, 1);
5215  for (int i = MPcount_sum; i < num_vals; i++) {
5216  eigenvectorsMat[i][j] = evecMat_master.block(
5217  j * (N + 1), int(eigenval_trunc_sorter2[i - MPcount_sum][1]),
5218  N + 1, 1);
5219  eigenvectorsMat[i][j].dct_flag = SIS_CHEB_SPACE;
5220  }
5221  }
5222  }
5223 
5224 #endif
5225  }
5226 };
5227 
5228 template <class T> class GeneralizedEigenSolver<std::complex<T> > {
5229 private:
5230 public:
5231  //std::valarray<ChebfunMat<std::complex<T> > > eigenvectorsMat;
5233  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, 1> eigenvalues;
5234  Eigen::Matrix<int, Eigen::Dynamic, 1> MPorNot;
5238  GeneralizedEigenSolver() : converged(0){};
5239 
5240 #ifdef SIS_USE_LAPACK
5241  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, 1> alpha, beta;
5242  int info; // gives info on lapack solver.
5243 #endif
5244 
5248  void compute(const LinopMat<std::complex<T> > &Lmat_,
5249  int num_vals, const BcMat<std::complex<T> > &bc_) {
5250  LinopMat<std::complex<T> > Mmat(Lmat_.r, Lmat_.c);
5251  Mmat.setIdentity();
5252  compute(Lmat_, Mmat, num_vals, bc_);
5253  }
5254 
5257  void compute(const LinopMat<std::complex<T> > &Lmat_,
5258  const BcMat<std::complex<T> > &bc_) {
5259  LinopMat<std::complex<T> > Mmat(Lmat_.r, Lmat_.c);
5260  int num_vals = Lmat_.r * (N + 1);
5261  Mmat.setIdentity();
5262  compute(Lmat_, Mmat, num_vals, bc_);
5263  }
5270  void compute(const LinopMat<std::complex<T> > &Lmat_,
5271  const LinopMat<std::complex<T> > &Mmat_, int num_vals,
5272  const BcMat<std::complex<T> > &Lbc_) {
5273  LinopMat<std::complex<T> > Lmat = Lmat_;
5274 
5275  LinopMat<std::complex<T> > Mmat = Mmat_;
5276  int bre;
5277  BcMat<std::complex<T> > Lbc = Lbc_;
5278  int total_of_all_orders = 0;
5279  int total_boundary_conditions = 0;
5280 
5281  if (Lmat.r != Lmat.c) {
5282  std::cout << "Solution only possible with square LinopMats. Exiting ..."
5283  << '\n';
5284  exit(1);
5285  }
5286  if (Mmat.r != Mmat.c) {
5287  std::cout << "Solution only possible with square LinopMats. Exiting ..."
5288  << '\n';
5289  exit(1);
5290  }
5291  if (Mmat.c != Lmat.c) {
5292  std::cout << "Both matrices have to be of same size. Exiting ..." << '\n';
5293  exit(1);
5294  }
5295  int r = Lmat.r, c = Lmat.c;
5296  // Find the highest derivative in each column. To do this create a vector
5297  // highest_each_column, and a temp_int_vec that will hold all values of a
5298  // given column to and the maximum will be stored in highest_each_column
5299  std::vector<int> highest_each_columnL, highest_each_columnM,
5300  highest_each_column;
5301  highest_each_columnL.resize(c);
5302  highest_each_columnM.resize(c);
5303  highest_each_column.resize(c);
5304 
5305  std::vector<int> temp_vec_int;
5306  temp_vec_int.resize(r);
5307  for (int j = 0; j < c; j++) {
5308  for (int i = 0; i < r; i++) {
5309  temp_vec_int[i] = Lmat(i, j).n;
5310  }
5311  highest_each_columnL[j] =
5312  *std::max_element(temp_vec_int.begin(), temp_vec_int.end());
5313  }
5314  for (int j = 0; j < c; j++) {
5315  for (int i = 0; i < r; i++) {
5316  temp_vec_int[i] = Mmat(i, j).n;
5317  }
5318  highest_each_columnM[j] =
5319  *std::max_element(temp_vec_int.begin(), temp_vec_int.end());
5320  }
5321  for (int i = 0; i < c; i++) {
5322  total_of_all_orders += (highest_each_columnL[i] > highest_each_columnM[i])
5323  ? highest_each_columnL[i]
5324  : highest_each_columnM[i];
5325  highest_each_column[i] =
5326  (highest_each_columnL[i] > highest_each_columnM[i])
5327  ? highest_each_columnL[i]
5328  : highest_each_columnM[i];
5329  // std::cout << "highest_each_column["<< i << "]: " <<
5330  // highest_each_column[i] << '\n';
5331  }
5332  total_boundary_conditions = Lbc.m;
5333 
5334  // total_of_all_orders has to be equal to total number of boundary
5335  // conditions, else the problem is ill-posed, if ill-posed, cout the same
5336  // and exit.
5337  if (total_of_all_orders != total_boundary_conditions) {
5338  std::cout << "The problem is ill-posed, the total of the highest "
5339  "orders of all "
5340  "dependent variables has to be equal to the total number of "
5341  "boundary conditions specified."
5342  "\n "
5343  "Total no. of boundary conditions: "
5344  << total_boundary_conditions
5345  << "\n"
5346  "Total of all orders: "
5347  << total_of_all_orders << "\n Exiting ...\n";
5348  // exit(1);
5349  }
5350  // Declare the master matrix L:
5351  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> masterL(
5352  r * (N + 1), c * (N + 1) + total_boundary_conditions);
5353  // Declare the master matrix M:
5354  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> masterM(
5355  r * (N + 1), c * (N + 1) + total_boundary_conditions);
5356 
5357  masterL.setConstant(0.0);
5358  masterM.setConstant(0.0);
5359  MatGen<T> Mat;
5360  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> subs_mat;
5361  subs_mat.resize(total_boundary_conditions, (N + 1) * c);
5362  subs_mat.setConstant(0.0);
5363  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> mat_temp(
5364  total_boundary_conditions, total_boundary_conditions),
5365  constraints(total_boundary_conditions,
5366  c * (N + 1) + total_of_all_orders);
5367 
5368  mat_temp.setConstant(0.0);
5369  int row_counter = 0, col_counter = 0;
5370  for (int i = 0; i < Lbc.m; i++) {
5371  for (int j = 0; j < Lbc.n; j++) {
5372  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> temp=
5373  Lbc(i, j, highest_each_column[j]);
5374  // std::cout << temp << std::endl;
5375  // std::cin >> bre;
5376  constraints.block(i, col_counter, 1, temp.cols()) = temp;
5377  col_counter += temp.cols();
5378  }
5379  col_counter = 0;
5380  }
5381 
5382  Eigen::ColPivHouseholderQR<
5383  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> >
5384  qr;
5385  qr.compute(constraints);
5386  if (qr.rank() != constraints.rows()) {
5387  std::cout << "The boundary conditions supplied are not "
5388  << " linearly independent." << '\n';
5389  std::cout << "qr.rank = " << qr.rank()
5390  << ", no. bcs: " << total_boundary_conditions << ". Exiting ..."
5391  << '\n';
5392  exit(1);
5393  }
5394 
5395  // Permutation matrix
5396  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> P;
5397  P = qr.colsPermutation();
5398  // Permute constraints
5399  constraints = constraints * P;
5400  mat_temp = constraints.block(0, 0, constraints.rows(), constraints.rows());
5401 
5402  Eigen::ColPivHouseholderQR<
5403  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> >
5404  consSolver(mat_temp);
5405  subs_mat = -consSolver.inverse() *
5406  constraints.block(0, constraints.rows(), constraints.rows(),
5407  constraints.cols() - constraints.rows());
5408 
5409  row_counter = 0;
5410  col_counter = 0;
5411  int master_row_counter = 0;
5412  int master_col_counter = 0;
5413  for (int j = 0; j < c; j++) {
5414  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
5415  ? highest_each_columnL[j]
5416  : highest_each_columnM[j];
5417  Mat.compute(n);
5418  for (int i = 0; i < r; i++) {
5419  int diffn = n - Lmat(i, j).n;
5420  if (Lmat(i, j).NCC == 0) {
5421  for (int k = 0; k < Lmat(i, j).n + 1; k++) {
5422  masterL.block(master_row_counter, master_col_counter, N + 1,
5423  N + 1 + n) +=
5424  Lmat(i, j).coef[k] *
5425  (Mat.mats2[k + diffn].block(0, 0, N + 1, N + 1 + n));
5426  // std::cout << "In, "
5427  // << "Lmat("<< i << "," << j << ").coef[" << k << "]" << Lmat(i, j).coef[k]
5428  //.. << __LINE__ << "\n";
5429  // std::cout << masterL.block(master_row_counter, master_col_counter, N + 1,
5430  // N + 1 + n) << "\n";
5431  // std::cout << Lmat(i, j).coefFun[k].MultMat() << "\n";
5432  //std::cin >> bre;
5433  }
5434  } else {
5435  for (int k = 0; k < Lmat(i, j).n + 1; k++) {
5436  masterL.block(master_row_counter, master_col_counter, N + 1,
5437  N + 1 + n) +=
5438  Lmat(i, j).coefFun[k].MultMat().block(0, 0, N + 1, N + 1) *
5439  (Mat.mats2[k + diffn].block(0, 0, N + 1, N + 1 + n));
5440  // std::cout << "In, "
5441  // << "Lmat(" << i << "," << j << ").coef[" << k << "]"
5442  // << __LINE__ << "\n";
5443  // std::cout << masterL.block(master_row_counter, master_col_counter,// N + 1,
5444  // N + 1 + n) << "\n";//*
5445  // (Mat.mats2[k + diffn].block(0, 0, N + 1, N + 1 + n))
5446  // << "\n";
5447  // std::cout << Lmat(i, j).coefFun[k].MultMat() << "\n";
5448  // std::cin >> bre;
5449  }
5450  }
5451  diffn = n - Mmat(i, j).n;
5452  if (Mmat(i, j).NCC == 0) {
5453  for (int k = 0; k < Mmat(i, j).n + 1; k++) {
5454  masterM.block(master_row_counter, master_col_counter, N + 1,
5455  N + 1 + n) +=
5456  Mmat(i, j).coef[k] *
5457  (Mat.mats2[k + diffn].block(0, 0, N + 1, N + 1 + n));
5458  }
5459  } else {
5460  for (int k = 0; k < Mmat(i, j).n + 1; k++) {
5461  masterM.block(master_row_counter, master_col_counter, N + 1,
5462  N + 1 + n) +=
5463  Mmat(i, j).coefFun[k].MultMat().block(0, 0, N + 1, N + 1) *
5464  (Mat.mats2[k + diffn].block(0, 0, N + 1, N + 1 + n));
5465  }
5466  }
5467  master_row_counter += N + 1;
5468  }
5469  master_row_counter = 0;
5470  master_col_counter += N + 1 + n;
5471  }
5472  // Permute columns of M and L:
5473  masterL = masterL * P;
5474  masterM = masterM * P;
5475 
5476  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> masterL2,
5477  masterM2;
5478 
5479  masterL2 =
5480  masterL.block(0, constraints.rows(), c * (N + 1), c * (N + 1)) +
5481  (masterL.block(0, 0, c * (N + 1), constraints.rows()) * subs_mat);
5482 
5483  masterM2 =
5484  masterM.block(0, constraints.rows(), c * (N + 1), c * (N + 1)) +
5485  (masterM.block(0, 0, c * (N + 1), constraints.rows()) * subs_mat);
5486 
5487 #if defined SIS_USE_LAPACK
5488  char jobvl = 'N'; // Don't compute left evecs
5489  char jobvr = 'V'; // Compute right evecs
5490  std::complex<double> wkopt; // Eistimate optimum workspace
5491  std::complex<double> *work; // allocate optimum workspace
5492  alpha.resize(masterL2.rows(), 1); // alpha for gen. eig. prob.
5493  beta.resize(masterL2.rows(), 1); // beta for gen. eig. prob.
5494 
5495  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> vl(
5496  masterL2.rows(), masterL2.rows()),
5497  vr(masterL2.rows(), masterL2.rows()),
5498  eigenvalues_temp(masterL2.rows(), 1), alpha_temp(masterL2.rows(), 1),
5499  beta_temp(masterL2.rows(), 1);
5500  // vl : left evecs, vr: right evecs.
5501  int ldL = masterL2.outerStride(); // ld for leading dimension
5502  int ldM = masterM2.outerStride();
5503  int ldvl = vl.outerStride();
5504  int ldvr = vr.outerStride();
5505  int sizeL = masterL2.rows();
5506  int lwork = -1; // set lwork to -1 to estimate workspace.
5507  double rwork[8 * sizeL];
5508 
5509  // call this to estimate workspace
5510  zggev_(&jobvl, &jobvr, &sizeL, masterL2.data(), &ldL, masterM2.data(), &ldM,
5511  alpha_temp.data(), beta_temp.data(), vl.data(), &ldvl, vr.data(),
5512  &ldvr, &wkopt, &lwork, rwork, &info);
5513 
5514  // Now allocate workspace:
5515  lwork = (int)real(wkopt);
5516  work = (std::complex<double> *)malloc(lwork * sizeof(std::complex<double>));
5517 
5518  // Solve eigenvalue problem:
5519  zggev_(&jobvl, &jobvr, &sizeL, masterL2.data(), &ldL, masterM2.data(), &ldM,
5520  alpha_temp.data(), beta_temp.data(), vl.data(), &ldvl, vr.data(),
5521  &ldvr, work, &lwork, rwork, &info);
5522 
5523  // Free workspace.
5524  free((void *)work);
5525 
5526  eigenvalues_temp = alpha_temp.array() / beta_temp.array();
5527 
5528  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic>
5529  evecMat_master(c * (N + 1), c * (N + 1));
5530  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, 1> temp_vec;
5531  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> fir_n_mat =
5532  subs_mat * vr;
5533  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> evecMat(
5534  c * (N + 1) + total_boundary_conditions, c * (N + 1));
5535  evecMat << fir_n_mat, vr;
5536  // Unpermute eveMat:
5537  evecMat = P * evecMat;
5538  row_counter = 0;
5539  col_counter = 0;
5540  for (int i = 0; i < c; i++) {
5541  int n = (highest_each_columnL[i] > highest_each_columnM[i])
5542  ? highest_each_columnL[i]
5543  : highest_each_columnM[i];
5544  Mat.compute(n);
5545  evecMat_master.block(i * (N + 1), 0, N + 1, c * (N + 1)) =
5546  Mat.mats2[n] * evecMat.block(row_counter, 0, N + 1 + n, c * (N + 1));
5547  row_counter += N + 1 + n;
5548  }
5549 #ifndef SIS_DONT_SORT
5550  std::vector<std::vector<T> > eigenval_trunc_sorter;
5551 
5552  eigenval_trunc_sorter.resize(c * (N + 1));
5553  for (int i = 0; i < c * (N + 1); i++) {
5554  eigenval_trunc_sorter[i].resize(2);
5555  }
5556 
5557  Eigen::Matrix<int, Eigen::Dynamic, 1> MPcount(c * (N + 1));
5558  MPcount.setConstant(0);
5559  std::vector<EigenSorter<T> > sorter;
5560  sorter.resize(c * (N + 1));
5561  for (int i = 0; i < c * (N + 1); i++) {
5562  sorter[i].compute(evecMat_master.block(0, i, c * (N + 1), 1), c);
5563  // sorter[i].compute(evecMat_master.block(0, i, (N + 1), 1));
5564  if (std::abs(beta_temp(i, 0)) < 1e-11) {
5565  sorter[i].numMp = N + 1;
5566  sorter[i].Mp = false;
5567  sorter[i].minVal = 1e11;
5568  }
5569  if (sorter[i].Mp == true) {
5570  MPcount[i] = 1;
5571  }
5572  }
5573  if (num_vals > masterL2.rows()) {
5574  std::cout << "Only " << masterL2.rows()
5575  << " eigenvalues can be calculated."
5576  << "Storing only that many." << '\n';
5577  num_vals = masterL2.rows();
5578  }
5579 
5580  int MPcount_sum = MPcount.sum();
5581  converged = MPcount_sum;
5582 
5583  eigenvectors.resize(c, num_vals);
5584  //eigenvectorsMat.resize(num_vals);
5585  //for (int i = 0; i < num_vals; i++) {
5586  // eigenvectorsMat[i].resize(c, 1);
5587  //}
5588  eigenvalues.resize(num_vals);
5589  MPorNot.resize(num_vals);
5590  beta.resize(num_vals);
5591  alpha.resize(num_vals);
5592  converged = MPcount_sum;
5593  if (MPcount_sum >= num_vals) {
5594  for (int i = 0; i < c * (N + 1); i++) {
5595  eigenval_trunc_sorter[i][0] = T(sorter[i].numMp);
5596  eigenval_trunc_sorter[i][1] = i;
5597  // std::cout << eigs.eigenvalues()[i] << " " << sorter[i].numMp <<
5598  // "\n"; std::cin > > bre;
5599  }
5600  std::sort(eigenval_trunc_sorter.begin(), eigenval_trunc_sorter.end());
5601  for (int i = 0; i < num_vals; i++) {
5602  eigenvalues[i] = eigenvalues_temp(int(eigenval_trunc_sorter[i][1]), 0);
5603  alpha[i] = alpha_temp(int(eigenval_trunc_sorter[i][1]), 0);
5604  beta[i] = beta_temp(int(eigenval_trunc_sorter[i][1]), 0);
5605  MPorNot[i] = 1;
5606  }
5607  for (int j = 0; j < c; j++) {
5608  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
5609  ? highest_each_columnL[j]
5610  : highest_each_columnM[j];
5611 
5612  temp_vec.resize(N + 1 + n, 1);
5613  for (int i = 0; i < num_vals; i++) {
5614  eigenvectors(j,i) = evecMat_master.block(
5615  j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
5616  eigenvectors(j,i).dct_flag = SIS_CHEB_SPACE;
5617  //eigenvectorsMat[i][j] = evecMat_master.block(
5618  // j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
5619  //eigenvectorsMat[i][j].dct_flag = SIS_CHEB_SPACE;
5620  }
5621  }
5622  } else {
5623  std::cout << "Last " << num_vals - MPcount_sum
5624  << " eigenvectors are not resolved to machine precision."
5625  << '\n';
5626  for (int i = 0; i < c * (N + 1); i++) {
5627  eigenval_trunc_sorter[i][0] = T(sorter[i].numMp);
5628  eigenval_trunc_sorter[i][1] = i;
5629  }
5630  std::sort(eigenval_trunc_sorter.begin(), eigenval_trunc_sorter.end());
5631  for (int i = 0; i < MPcount_sum; i++) {
5632  eigenvalues[i] = eigenvalues_temp(int(eigenval_trunc_sorter[i][1]), 0);
5633  alpha[i] = alpha_temp(int(eigenval_trunc_sorter[i][1]), 0);
5634  beta[i] = beta_temp(int(eigenval_trunc_sorter[i][1]), 0);
5635  MPorNot[i] = 1;
5636  }
5637  for (int j = 0; j < c; j++) {
5638  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
5639  ? highest_each_columnL[j]
5640  : highest_each_columnM[j];
5641  temp_vec.resize(N + 1 + n, 1);
5642  for (int i = 0; i < MPcount_sum; i++) {
5643  eigenvectors(j,i) = evecMat_master.block(
5644  j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
5645  eigenvectors(j,i).dct_flag = SIS_CHEB_SPACE;
5646  // eigenvectorsMat[i][j] = evecMat_master.block(
5647  // j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
5648  // eigenvectorsMat[i][j].dct_flag = SIS_CHEB_SPACE;
5649  }
5650  }
5651 
5652  std::vector<std::vector<T> > eigenval_trunc_sorter2;
5653  eigenval_trunc_sorter2.resize(c * (N + 1) - MPcount_sum);
5654  for (int i = MPcount_sum; i < c * (N + 1); i++) {
5655  eigenval_trunc_sorter2[i - MPcount_sum].resize(2);
5656  eigenval_trunc_sorter2[i - MPcount_sum][0] =
5657  sorter[int(eigenval_trunc_sorter[i][1])].minVal;
5658  eigenval_trunc_sorter2[i - MPcount_sum][1] =
5659  eigenval_trunc_sorter[i][1];
5660  }
5661  std::sort(eigenval_trunc_sorter2.begin(), eigenval_trunc_sorter2.end());
5662  for (int i = MPcount_sum; i < num_vals; i++) {
5663  eigenvalues[i] = eigenvalues_temp(
5664  int(eigenval_trunc_sorter2[i - MPcount_sum][1]), 0);
5665  alpha[i] =
5666  alpha_temp(int(eigenval_trunc_sorter2[i - MPcount_sum][1]), 0);
5667  beta[i] = beta_temp(int(eigenval_trunc_sorter2[i - MPcount_sum][1]), 0);
5668  MPorNot[i] = 0;
5669  }
5670  for (int j = 0; j < c; j++) {
5671  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
5672  ? highest_each_columnL[j]
5673  : highest_each_columnM[j];
5674  Mat.compute(n);
5675  temp_vec.resize(N + 1 + n, 1);
5676  for (int i = MPcount_sum; i < num_vals; i++) {
5677  eigenvectors(j,i) = evecMat_master.block(
5678  j * (N + 1), int(eigenval_trunc_sorter2[i - MPcount_sum][1]),
5679  N + 1, 1);
5680  eigenvectors(j,i).dct_flag = SIS_CHEB_SPACE;
5681  // eigenvectorsMat[i][j] = evecMat_master.block(
5682  // j * (N + 1), int(eigenval_trunc_sorter2[i - MPcount_sum][1]),
5683  // N + 1, 1);
5684  // eigenvectorsMat[i][j].dct_flag = SIS_CHEB_SPACE;
5685  }
5686  }
5687  }
5688 #else
5689  eigenvectors.resize(c, c * (N + 1));
5690  //eigenvectorsMat.resize(c * (N + 1));
5691  //for (int i = 0; i < c * (N + 1); i++) {
5692  // eigenvectorsMat[i].resize(c, 1);
5693  //}
5694  eigenvalues.resize(c * (N + 1));
5695  MPorNot.resize(c * (N + 1));
5696  beta.resize(c * (N + 1));
5697  alpha.resize(c * (N + 1));
5698  converged = -2;
5699  for (int i = 0; i < c * (N + 1); i++) {
5700  eigenvalues[i] = eigenvalues_temp(i, 0);
5701  alpha[i] = alpha_temp(i, 0);
5702  beta[i] = beta_temp(i, 0);
5703  MPorNot[i] = -2;
5704  }
5705  for (int j = 0; j < c; j++) {
5706  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
5707  ? highest_each_columnL[j]
5708  : highest_each_columnM[j];
5709 
5710  temp_vec.resize(N + 1 + n, 1);
5711  for (int i = 0; i < c * (N + 1); i++) {
5712  eigenvectors(j,i) = evecMat_master.block(j * (N + 1), i, N + 1, 1);
5713  eigenvectors(j,i).dct_flag = SIS_CHEB_SPACE;
5714  // eigenvectorsMat[i][j] = evecMat_master.block(j * (N + 1), i, N + 1, 1);
5715  // eigenvectorsMat[i][j].dct_flag = SIS_CHEB_SPACE;
5716  }
5717  }
5718 #endif
5719 #else
5720 
5721  Eigen::ColPivHouseholderQR<
5722  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> >
5723  solver(masterM2);
5724  Eigen::ComplexEigenSolver<
5725  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> >
5726  eigs;
5727  bool Is_M_Invertible;
5728  if (solver.isInvertible()) {
5729  // std::cout << "M is invertible" << '\n';
5730  // std::cin >> bre;
5731  Is_M_Invertible = true;
5732  eigs.compute(solver.inverse() * masterL2);
5733  // std::cout << "Eigenvalues :\n" << eigs.eigenvalues() << '\n';
5734  } else {
5735  // std::cout << "M is not invertible." << '\n';
5736  // std::cin >> bre;
5737  Is_M_Invertible = false;
5738  solver.compute(masterL2);
5739  eigs.compute(solver.inverse() * masterM2);
5740  // std::cout << "Eigenvalues :\n" << 1 / eigs.eigenvalues().array() <<
5741  // '\n';
5742  }
5743  // std::cin >> bre;
5744  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic>
5745  evecMat_master(c * (N + 1), c * (N + 1));
5746  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, 1> temp_vec;
5747  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> fir_n_mat =
5748  subs_mat * eigs.eigenvectors();
5749  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> evecMat(
5750  c * (N + 1) + total_boundary_conditions, c * (N + 1));
5751  evecMat << fir_n_mat, eigs.eigenvectors();
5752 
5753  // Unpermute eveMat:
5754  evecMat = P * evecMat;
5755  row_counter = 0;
5756  col_counter = 0;
5757  for (int i = 0; i < c; i++) {
5758  int n = (highest_each_columnL[i] > highest_each_columnM[i])
5759  ? highest_each_columnL[i]
5760  : highest_each_columnM[i];
5761  Mat.compute(n);
5762  evecMat_master.block(i * (N + 1), 0, N + 1, c * (N + 1)) =
5763  Mat.mats2[n] * evecMat.block(row_counter, 0, N + 1 + n, c * (N + 1));
5764  row_counter += N + 1 + n;
5765  }
5766 
5767 #ifndef SIS_DONT_SORT
5768  std::vector<std::vector<T> > eigenval_trunc_sorter;
5769 
5770  eigenval_trunc_sorter.resize(c * (N + 1));
5771  for (int i = 0; i < c * (N + 1); i++) {
5772  eigenval_trunc_sorter[i].resize(2);
5773  }
5774 
5775  Eigen::Matrix<int, Eigen::Dynamic, 1> MPcount(c * (N + 1));
5776  MPcount.setConstant(0);
5777  std::vector<EigenSorter<T> > sorter;
5778  sorter.resize(c * (N + 1));
5779  for (int i = 0; i < c * (N + 1); i++) {
5780  sorter[i].compute(evecMat_master.block(0, i, c * (N + 1), 1), c);
5781  if (!Is_M_Invertible) {
5782  // If M is not invertible, there will be zero eigenvalues, so that 1/0 =
5783  // inf eigenvalue, remove them.
5784  if (abs(eigs.eigenvalues()[i]) < 1e-11) {
5785  sorter[i].numMp = N + 1;
5786  sorter[i].Mp = false;
5787  sorter[i].minVal = 1e11;
5788  }
5789  }
5790  // sorter[i].compute(evecMat_master.block(0, i, (N + 1), 1));
5791  if (sorter[i].Mp == true) {
5792  MPcount[i] = 1;
5793  }
5794  }
5795  if (num_vals > masterL2.rows()) {
5796  std::cout << "Only " << masterL2.rows()
5797  << " eigenvalues can be calculated."
5798  << "Storing only that many." << '\n';
5799  num_vals = masterL2.rows();
5800  }
5801 
5802  int MPcount_sum = MPcount.sum();
5803  converged = MPcount_sum;
5804  eigenvectors.resize(c,num_vals);
5805  //eigenvectorsMat.resize(num_vals);
5806  //for (int i = 0; i < num_vals; i++) {
5807  // eigenvectorsMat[i].resize(c, 1);
5808  //}
5809  eigenvalues.resize(num_vals);
5810  MPorNot.resize(num_vals);
5811  if (MPcount_sum >= num_vals) {
5812  for (int i = 0; i < c * (N + 1); i++) {
5813  eigenval_trunc_sorter[i][0] = T(sorter[i].numMp);
5814  eigenval_trunc_sorter[i][1] = i;
5815  // std::cout << eigs.eigenvalues()[i] << " " << sorter[i].numMp <<
5816  // "\n"; std::cin > > bre;
5817  }
5818  std::sort(eigenval_trunc_sorter.begin(), eigenval_trunc_sorter.end());
5819  for (int i = 0; i < num_vals; i++) {
5820  if (Is_M_Invertible) {
5821  eigenvalues[i] = eigs.eigenvalues()[int(eigenval_trunc_sorter[i][1])];
5822  MPorNot[i] = 1;
5823  } else {
5824  eigenvalues[i] =
5825  1.0 / eigs.eigenvalues()[int(eigenval_trunc_sorter[i][1])];
5826  MPorNot[i] = 1;
5827  }
5828  }
5829  for (int j = 0; j < c; j++) {
5830  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
5831  ? highest_each_columnL[j]
5832  : highest_each_columnM[j];
5833 
5834  temp_vec.resize(N + 1 + n, 1);
5835  for (int i = 0; i < num_vals; i++) {
5836  eigenvectors(j,i) = evecMat_master.block(
5837  j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
5838  eigenvectors(j,i).dct_flag = SIS_CHEB_SPACE;
5839  //eigenvectorsMat[i][j] = evecMat_master.block(
5840  // j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
5841  //eigenvectorsMat[i][j].dct_flag = SIS_CHEB_SPACE;
5842  }
5843  }
5844  } else {
5845  std::cout << "Last " << num_vals - MPcount_sum
5846  << " eigenvectors are not resolved to machine precision."
5847  << '\n';
5848  for (int i = 0; i < c * (N + 1); i++) {
5849  eigenval_trunc_sorter[i][0] = T(sorter[i].numMp);
5850  eigenval_trunc_sorter[i][1] = i;
5851  }
5852  std::sort(eigenval_trunc_sorter.begin(), eigenval_trunc_sorter.end());
5853  for (int i = 0; i < MPcount_sum; i++) {
5854  if (Is_M_Invertible) {
5855  eigenvalues[i] = eigs.eigenvalues()[int(eigenval_trunc_sorter[i][1])];
5856  MPorNot[i] = 1;
5857 
5858  } else {
5859  eigenvalues[i] =
5860  1.0 / eigs.eigenvalues()[int(eigenval_trunc_sorter[i][1])];
5861  MPorNot[i] = 1;
5862  }
5863  }
5864  for (int j = 0; j < c; j++) {
5865  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
5866  ? highest_each_columnL[j]
5867  : highest_each_columnM[j];
5868  temp_vec.resize(N + 1 + n, 1);
5869  for (int i = 0; i < MPcount_sum; i++) {
5870  eigenvectors(j,i) = evecMat_master.block(
5871  j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
5872  eigenvectors(j,i).dct_flag = SIS_CHEB_SPACE;
5873  //eigenvectorsMat[i][j] = evecMat_master.block(
5874  // j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
5875  //eigenvectorsMat[i][j].dct_flag = SIS_CHEB_SPACE;
5876  }
5877  }
5878 
5879  std::vector<std::vector<T> > eigenval_trunc_sorter2;
5880  eigenval_trunc_sorter2.resize(c * (N + 1) - MPcount_sum);
5881  for (int i = MPcount_sum; i < c * (N + 1); i++) {
5882  eigenval_trunc_sorter2[i - MPcount_sum].resize(2);
5883  eigenval_trunc_sorter2[i - MPcount_sum][0] =
5884  sorter[int(eigenval_trunc_sorter[i][1])].minVal;
5885  eigenval_trunc_sorter2[i - MPcount_sum][1] =
5886  eigenval_trunc_sorter[i][1];
5887  }
5888  std::sort(eigenval_trunc_sorter2.begin(), eigenval_trunc_sorter2.end());
5889  for (int i = MPcount_sum; i < num_vals; i++) {
5890  if (Is_M_Invertible) {
5891  eigenvalues[i] = eigs.eigenvalues()[int(
5892  eigenval_trunc_sorter2[i - MPcount_sum][1])];
5893  MPorNot[i] = 0;
5894 
5895  } else {
5896  eigenvalues[i] =
5897  1.0 / eigs.eigenvalues()[int(
5898  eigenval_trunc_sorter2[i - MPcount_sum][1])];
5899  MPorNot[i] = 0;
5900  }
5901  }
5902  for (int j = 0; j < c; j++) {
5903  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
5904  ? highest_each_columnL[j]
5905  : highest_each_columnM[j];
5906  Mat.compute(n);
5907  temp_vec.resize(N + 1 + n, 1);
5908  for (int i = MPcount_sum; i < num_vals; i++) {
5909  eigenvectors(j,i) = evecMat_master.block(
5910  j * (N + 1), int(eigenval_trunc_sorter2[i - MPcount_sum][1]),
5911  N + 1, 1);
5912  eigenvectors(j,i).dct_flag = SIS_CHEB_SPACE;
5913  //eigenvectorsMat[i][j] = evecMat_master.block(
5914  // j * (N + 1), int(eigenval_trunc_sorter2[i - MPcount_sum][1]),
5915  // N + 1, 1);
5916  //eigenvectorsMat[i][j].dct_flag = SIS_CHEB_SPACE;
5917  }
5918  }
5919  }
5920 
5921 #else
5922  eigenvectors.resize(c, c * (N + 1))
5923  //eigenvectorsMat.resize(c * (N + 1));
5924  //for (int i = 0; i < c * (N + 1); i++) {
5925  // eigenvectorsMat[i].resize(c, 1);
5926  //}
5927  eigenvalues.resize(c * (N + 1));
5928  MPorNot.resize(c * (N + 1));
5929  converged = -2;
5930  for (int i = 0; i < c * (N + 1); i++) {
5931  if (Is_M_Invertible) {
5932  eigenvalues[i] = eigs.eigenvalues()[i];
5933  MPorNot[i] = -2;
5934  } else {
5935  eigenvalues[i] = 1.0 / eigs.eigenvalues()[i];
5936  MPorNot[i] = -2;
5937  }
5938  }
5939  for (int j = 0; j < c; j++) {
5940  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
5941  ? highest_each_columnL[j]
5942  : highest_each_columnM[j];
5943 
5944  temp_vec.resize(N + 1 + n, 1);
5945  for (int i = 0; i < c * (N + 1); i++) {
5946  eigenvectors(j,i) = evecMat_master.block(j * (N + 1), i, N + 1, 1);
5947  eigenvectors(j,i).dct_flag = SIS_CHEB_SPACE;
5948  // eigenvectorsMat[i][j] = evecMat_master.block(j * (N + 1), i, N + 1, 1);
5949  // eigenvectorsMat[i][j].dct_flag = SIS_CHEB_SPACE;
5950  }
5951  }
5952 #endif
5953 #endif
5954  // Change everything to physical space:
5955  eigenvectors.c2p();
5956  }
5957 
5958 
5970  void computeAppend(const LinopMat<std::complex<T> > &Lmat_,
5971  const LinopMat<std::complex<T> > &Mmat_, int num_vals,
5972  const BcMat<std::complex<T> > &Lbc_) {
5973  LinopMat<std::complex<T> > Lmat = Lmat_;
5974 
5975  LinopMat<std::complex<T> > Mmat = Mmat_;
5976  int bre;
5977  BcMat<std::complex<T> > Lbc = Lbc_;
5978  int total_of_all_orders = 0;
5979  int total_boundary_conditions = 0;
5980  if (Lmat.r != Lmat.c) {
5981  std::cout << "Solution only possible with square LinopMats. Exiting ..."
5982  << '\n';
5983  exit(1);
5984  }
5985  if (Mmat.r != Mmat.c) {
5986  std::cout << "Solution only possible with square LinopMats. Exiting ..."
5987  << '\n';
5988  exit(1);
5989  }
5990  if (Mmat.c != Lmat.c) {
5991  std::cout << "Both matrices have to be of same size. Exiting ..." << '\n';
5992  exit(1);
5993  }
5994  int r = Lmat.r, c = Lmat.c;
5995  // Find the highest derivative in each column. To do this create a vector
5996  // highest_each_column, and a temp_int_vec that will hold all values of a
5997  // given column to and the maximum will be stored in highest_each_column
5998  std::vector<int> highest_each_columnL, highest_each_columnM,
5999  highest_each_column;
6000  highest_each_columnL.resize(c);
6001  highest_each_columnM.resize(c);
6002  highest_each_column.resize(c);
6003 
6004  std::vector<int> temp_vec_int;
6005  temp_vec_int.resize(r);
6006  for (int j = 0; j < c; j++) {
6007  for (int i = 0; i < r; i++) {
6008  temp_vec_int[i] = Lmat(i, j).n;
6009  }
6010  highest_each_columnL[j] =
6011  *std::max_element(temp_vec_int.begin(), temp_vec_int.end());
6012  }
6013  for (int j = 0; j < c; j++) {
6014  for (int i = 0; i < r; i++) {
6015  temp_vec_int[i] = Mmat(i, j).n;
6016  }
6017  highest_each_columnM[j] =
6018  *std::max_element(temp_vec_int.begin(), temp_vec_int.end());
6019  }
6020  for (int i = 0; i < c; i++) {
6021  total_of_all_orders += (highest_each_columnL[i] > highest_each_columnM[i])
6022  ? highest_each_columnL[i]
6023  : highest_each_columnM[i];
6024  highest_each_column[i] =
6025  (highest_each_columnL[i] > highest_each_columnM[i])
6026  ? highest_each_columnL[i]
6027  : highest_each_columnM[i];
6028  // std::cout << "highest_each_column["<< i << "]: " <<
6029  // highest_each_column[i] << '\n';
6030  }
6031  total_boundary_conditions = Lbc.m;
6032 
6033  // total_of_all_orders has to be equal to total number of boundary
6034  // conditions, else the problem is ill-posed, if ill-posed, cout the same
6035  // and exit.
6036  if (total_of_all_orders != total_boundary_conditions) {
6037  std::cout << "The problem is ill-posed, the total of the highest "
6038  "orders of all "
6039  "dependent variables has to be equal to the total number of "
6040  "boundary conditions specified."
6041  "\n "
6042  "Total no. of boundary conditions: "
6043  << total_boundary_conditions
6044  << "\n"
6045  "Total of all orders: "
6046  << total_of_all_orders << "\n Exiting ...\n";
6047  // exit(1);
6048  }
6049  // Declare the master matrix L:
6050  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> masterL(
6051  r * (N + 1), c * (N + 1) + total_boundary_conditions);
6052  // Declare the master matrix M:
6053  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> masterM(
6054  r * (N + 1), c * (N + 1) + total_boundary_conditions);
6055 
6056  masterL.setConstant(0.0);
6057  masterM.setConstant(0.0);
6058  MatGen<T> Mat;
6059  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic>
6060  constraints(total_boundary_conditions,
6061  c * (N + 1) + total_of_all_orders),
6062  Zeros(total_boundary_conditions,
6063  c * (N + 1) + total_of_all_orders);
6064 
6065  Zeros.setConstant(0.0);
6066  int row_counter = 0, col_counter = 0;
6067  for (int i = 0; i < Lbc.m; i++) {
6068  for (int j = 0; j < Lbc.n; j++) {
6069  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> temp=
6070  Lbc(i, j, highest_each_column[j]);
6071  constraints.block(i, col_counter, 1, temp.cols()) = temp;
6072  col_counter += temp.cols();
6073  }
6074  col_counter = 0;
6075  }
6076 
6077  row_counter = 0;
6078  col_counter = 0;
6079  int master_row_counter = 0;
6080  int master_col_counter = 0;
6081  for (int j = 0; j < c; j++) {
6082  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
6083  ? highest_each_columnL[j]
6084  : highest_each_columnM[j];
6085  Mat.compute(n);
6086  for (int i = 0; i < r; i++) {
6087  int diffn = n - Lmat(i, j).n;
6088  if (Lmat(i, j).NCC == 0) {
6089  for (int k = 0; k < Lmat(i, j).n + 1; k++) {
6090  masterL.block(master_row_counter, master_col_counter, N + 1,
6091  N + 1 + n) +=
6092  Lmat(i, j).coef[k] *
6093  (Mat.mats2[k + diffn].block(0, 0, N + 1, N + 1 + n));
6094  }
6095  } else {
6096  for (int k = 0; k < Lmat(i, j).n + 1; k++) {
6097  masterL.block(master_row_counter, master_col_counter, N + 1,
6098  N + 1 + n) +=
6099  Lmat(i, j).coefFun[k].MultMat().block(0, 0, N + 1, N + 1) *
6100  (Mat.mats2[k + diffn].block(0, 0, N + 1, N + 1 + n));
6101  }
6102  }
6103  diffn = n - Mmat(i, j).n;
6104  if (Mmat(i, j).NCC == 0) {
6105  for (int k = 0; k < Mmat(i, j).n + 1; k++) {
6106  masterM.block(master_row_counter, master_col_counter, N + 1,
6107  N + 1 + n) +=
6108  Mmat(i, j).coef[k] *
6109  (Mat.mats2[k + diffn].block(0, 0, N + 1, N + 1 + n));
6110  }
6111  } else {
6112  for (int k = 0; k < Mmat(i, j).n + 1; k++) {
6113  masterM.block(master_row_counter, master_col_counter, N + 1,
6114  N + 1 + n) +=
6115  Mmat(i, j).coefFun[k].MultMat().block(0, 0, N + 1, N + 1) *
6116  (Mat.mats2[k + diffn].block(0, 0, N + 1, N + 1 + n));
6117  }
6118  }
6119  master_row_counter += N + 1;
6120  }
6121  master_row_counter = 0;
6122  master_col_counter += N + 1 + n;
6123  }
6124  // Permute columns of M and L:
6125  // masterL = masterL * P;
6126  // masterM = masterM * P;
6127 
6128  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> masterL2(
6129  r * (N + 1) + total_boundary_conditions,
6130  c * (N + 1) + total_boundary_conditions),
6131  masterM2(
6132  r * (N + 1) + total_boundary_conditions,
6133  c * (N + 1) + total_boundary_conditions);
6134 
6135  masterL2 << masterL,constraints;
6136 
6137 
6138  masterM2 << masterM, Zeros;
6139 
6140 #if defined SIS_USE_LAPACK
6141  char jobvl = 'N'; // Don't compute left evecs
6142  char jobvr = 'V'; // Compute right evecs
6143  std::complex<double> wkopt; // Eistimate optimum workspace
6144  std::complex<double> *work; // allocate optimum workspace
6145  alpha.resize(masterL2.rows(), 1); // alpha for gen. eig. prob.
6146  beta.resize(masterL2.rows(), 1); // beta for gen. eig. prob.
6147 
6148  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> vl(
6149  masterL2.rows(), masterL2.rows()),
6150  vr(masterL2.rows(), masterL2.rows()),
6151  eigenvalues_temp(masterL2.rows(), 1), alpha_temp(masterL2.rows(), 1),
6152  beta_temp(masterL2.rows(), 1);
6153  // vl : left evecs, vr: right evecs.
6154  int ldL = masterL2.outerStride(); // ld for leading dimension
6155  int ldM = masterM2.outerStride();
6156  int ldvl = vl.outerStride();
6157  int ldvr = vr.outerStride();
6158  int sizeL = masterL2.rows();
6159  int lwork = -1; // set lwork to -1 to estimate workspace.
6160  double rwork[8 * sizeL];
6161 
6162  // call this to estimate workspace
6163  zggev_(&jobvl, &jobvr, &sizeL, masterL2.data(), &ldL, masterM2.data(), &ldM,
6164  alpha_temp.data(), beta_temp.data(), vl.data(), &ldvl, vr.data(),
6165  &ldvr, &wkopt, &lwork, rwork, &info);
6166 
6167  // Now allocate workspace:
6168  lwork = (int)real(wkopt);
6169  work = (std::complex<double> *)malloc(lwork * sizeof(std::complex<double>));
6170 
6171  // Solve eigenvalue problem:
6172  zggev_(&jobvl, &jobvr, &sizeL, masterL2.data(), &ldL, masterM2.data(), &ldM,
6173  alpha_temp.data(), beta_temp.data(), vl.data(), &ldvl, vr.data(),
6174  &ldvr, work, &lwork, rwork, &info);
6175 
6176  // Free workspace.
6177  free((void *)work);
6178 
6179  eigenvalues_temp = alpha_temp.array() / beta_temp.array();
6180 
6181 eigenvalues.resize(eigenvalues_temp.rows(),1);
6182 alpha.resize(alpha_temp.rows(),1);
6183 beta.resize(beta_temp.rows(),1);
6184 eigenvalues = eigenvalues_temp;
6185 alpha = alpha_temp;
6186 beta = beta_temp;
6187 #else
6188 std::cout << "This function needs SIS_USE_LAPACK to be defined, and LAPACK"
6189  << " linking is essential. Exiting ..." << '\n';
6190  exit(1);
6191 #endif
6192  }
6193 
6194 #ifdef SIS_USE_FEAST
6195  void feast_compute(const LinopMat<std::complex<T> > &Lmat_,
6196  const LinopMat<std::complex<T> > &Mmat_, int num_vals,
6197  const BcMat<std::complex<T> > &Lbc_) {
6198  LinopMat<std::complex<T> > Lmat = Lmat_;
6199  LinopMat<std::complex<T> > Mmat = Mmat_;
6200  BcMat<std::complex<T> > Lbc = Lbc_;
6201  int bre;
6202  int total_of_all_orders = 0;
6203  int total_boundary_conditions = 0;
6204  if (Lmat.r != Lmat.c) {
6205  std::cout << "Solution only possible with square LinopMats. Exiting ..."
6206  << '\n';
6207  exit(1);
6208  }
6209  if (Mmat.r != Mmat.c) {
6210  std::cout << "Solution only possible with square LinopMats. Exiting ..."
6211  << '\n';
6212  exit(1);
6213  }
6214  if (Mmat.c != Lmat.c) {
6215  std::cout << "Both matrices have to be of same size. Exiting ..." << '\n';
6216  exit(1);
6217  }
6218  int r = Lmat.r, c = Lmat.c;
6219  // Find the highest derivative in each column. To do this create a vector
6220  // highest_each_column, and a temp_int_vec that will hold all values of a
6221  // given column to and the maximum will be stored in highest_each_column
6222  std::vector<int> highest_each_columnL, highest_each_columnM,
6223  highest_each_column;
6224  highest_each_columnL.resize(c);
6225  highest_each_columnM.resize(c);
6226  highest_each_column.resize(c);
6227 
6228  std::vector<int> temp_vec_int;
6229  temp_vec_int.resize(r);
6230  for (int j = 0; j < c; j++) {
6231  for (int i = 0; i < r; i++) {
6232  temp_vec_int[i] = Lmat(i, j).n;
6233  }
6234  highest_each_columnL[j] =
6235  *std::max_element(temp_vec_int.begin(), temp_vec_int.end());
6236  }
6237  for (int j = 0; j < c; j++) {
6238  for (int i = 0; i < r; i++) {
6239  temp_vec_int[i] = Mmat(i, j).n;
6240  }
6241  highest_each_columnM[j] =
6242  *std::max_element(temp_vec_int.begin(), temp_vec_int.end());
6243  }
6244  for (int i = 0; i < c; i++) {
6245  total_of_all_orders += (highest_each_columnL[i] > highest_each_columnM[i])
6246  ? highest_each_columnL[i]
6247  : highest_each_columnM[i];
6248  highest_each_column[i] =
6249  (highest_each_columnL[i] > highest_each_columnM[i])
6250  ? highest_each_columnL[i]
6251  : highest_each_columnM[i];
6252  // std::cout << "highest_each_column["<< i << "]: " <<
6253  // highest_each_column[i] << '\n';
6254  }
6255  total_boundary_conditions = Lbc.m;
6256 
6257  // total_of_all_orders has to be equal to total number of boundary
6258  // conditions, else the problem is ill-posed, if ill-posed, cout the same
6259  // and exit.
6260  if (total_of_all_orders != total_boundary_conditions) {
6261  std::cout << "The problem is ill-posed, the total of the highest "
6262  "orders of all "
6263  "dependent variables has to be equal to the total number of "
6264  "boundary conditions specified."
6265  "\n "
6266  "Total no. of boundary conditions: "
6267  << total_boundary_conditions
6268  << "\n"
6269  "Total of all orders: "
6270  << total_of_all_orders << "\n Exiting ...\n";
6271  exit(1);
6272  }
6273  // Declare the master matrix L:
6274  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> masterL(
6275  r * (N + 1), c * (N + 1) + total_boundary_conditions);
6276  // Declare the master matrix M:
6277  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> masterM(
6278  r * (N + 1), c * (N + 1) + total_boundary_conditions);
6279 
6280  masterL.setConstant(0.0);
6281  masterM.setConstant(0.0);
6282  MatGen<T> Mat;
6283  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> subs_mat;
6284  subs_mat.resize(total_boundary_conditions, (N + 1) * c);
6285  subs_mat.setConstant(0.0);
6286  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> mat_temp(
6287  total_boundary_conditions, total_boundary_conditions),
6288  constraints(total_boundary_conditions,
6289  c * (N + 1) + total_of_all_orders);
6290 
6291  mat_temp.setConstant(0.0);
6292  int row_counter = 0, col_counter = 0;
6293 
6294  for (int i = 0; i < Lbc.m; i++) {
6295  for (int j = 0; j < Lbc.n; j++) {
6296  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> temp =
6297  Lbc(i, j, highest_each_column[j]);
6298  constraints.block(i, col_counter, 1, temp.cols()) = temp;
6299  col_counter += temp.cols();
6300  }
6301  col_counter = 0;
6302  }
6303 
6304  Eigen::ColPivHouseholderQR<
6305  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> >
6306  qr;
6307  qr.compute(constraints);
6308  if (qr.rank() != constraints.rows()) {
6309  std::cout << "The boundary conditions supplied are not "
6310  << " linearly independent." << '\n';
6311  std::cout << "qr.rank = " << qr.rank()
6312  << ", no. bcs: " << total_boundary_conditions << ". Exiting ..."
6313  << '\n';
6314  exit(1);
6315  }
6316 
6317  // Permutation matrix
6318  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> P;
6319  P = qr.colsPermutation();
6320  // Permute constraints
6321  constraints = constraints * P;
6322  mat_temp = constraints.block(0, 0, constraints.rows(), constraints.rows());
6323 
6324  Eigen::ColPivHouseholderQR<
6325  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> >
6326  consSolver(mat_temp);
6327  subs_mat = -consSolver.inverse() *
6328  constraints.block(0, constraints.rows(), constraints.rows(),
6329  constraints.cols() - constraints.rows());
6330 
6331  row_counter = 0;
6332  col_counter = 0;
6333  int master_row_counter = 0;
6334  int master_col_counter = 0;
6335  for (int j = 0; j < c; j++) {
6336  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
6337  ? highest_each_columnL[j]
6338  : highest_each_columnM[j];
6339  Mat.compute(n);
6340  for (int i = 0; i < r; i++) {
6341  int diffn = n - Lmat(i, j).n;
6342  if (Lmat(i, j).NCC == 0) {
6343  for (int k = 0; k < Lmat(i, j).n + 1; k++) {
6344  masterL.block(master_row_counter, master_col_counter, N + 1,
6345  N + 1 + n) +=
6346  Lmat(i, j).coef[k] *
6347  (Mat.mats2[k + diffn].block(0, 0, N + 1, N + 1 + n));
6348  }
6349  } else {
6350  for (int k = 0; k < Lmat(i, j).n + 1; k++) {
6351  masterL.block(master_row_counter, master_col_counter, N + 1,
6352  N + 1 + n) +=
6353  Lmat(i, j).coefFun[k].MultMat().block(0, 0, N + 1, N + 1) *
6354  (Mat.mats2[k + diffn].block(0, 0, N + 1, N + 1 + n));
6355  }
6356  }
6357  diffn = n - Mmat(i, j).n;
6358  if (Mmat(i, j).NCC == 0) {
6359  for (int k = 0; k < Mmat(i, j).n + 1; k++) {
6360  masterM.block(master_row_counter, master_col_counter, N + 1,
6361  N + 1 + n) +=
6362  Mmat(i, j).coef[k] *
6363  (Mat.mats2[k + diffn].block(0, 0, N + 1, N + 1 + n));
6364  }
6365  } else {
6366  for (int k = 0; k < Mmat(i, j).n + 1; k++) {
6367  masterM.block(master_row_counter, master_col_counter, N + 1,
6368  N + 1 + n) +=
6369  Mmat(i, j).coefFun[k].MultMat().block(0, 0, N + 1, N + 1) *
6370  (Mat.mats2[k + diffn].block(0, 0, N + 1, N + 1 + n));
6371  }
6372  }
6373  master_row_counter += N + 1;
6374  }
6375  master_row_counter = 0;
6376  master_col_counter += N + 1 + n;
6377  }
6378  // Permute columns of M and L:
6379  masterL = masterL * P;
6380  masterM = masterM * P;
6381 
6382  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> masterL2,
6383  masterM2;
6384 
6385  masterL2 =
6386  masterL.block(0, constraints.rows(), c * (N + 1), c * (N + 1)) +
6387  (masterL.block(0, 0, c * (N + 1), constraints.rows()) * subs_mat);
6388 
6389  masterM2 =
6390  masterM.block(0, constraints.rows(), c * (N + 1), c * (N + 1)) +
6391  (masterM.block(0, 0, c * (N + 1), constraints.rows()) * subs_mat);
6392 
6393  int ldL = masterL2.outerStride(); // ld for leading dimension
6394  int ldM = masterM2.outerStride();
6395  double epsout;
6396  double Emid[2];
6397  int loop;
6398  int M;
6399  // feast::M0 = 2;
6400  double res[2 * feast::M0];
6401  feast::feast_init();
6402  // feast::feastparam[6] = 8;
6403  feast::feastparam[0] = 1;
6404  feast::feastparam[7] = 56;
6405  // feast::feastparam[13] = 2;
6406  // Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> lambda(
6407  // masterL2.rows(), 1), vecs(masterL2.rows(), 2 * masterL2.rows()),
6408  // vr;
6409 
6410  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> lambda(
6411  feast::M0, 1),
6412  vecs(masterM2.rows(), 2 * feast::M0), vr;
6413  lambda.setConstant(0.0);
6414  vecs.setConstant(0.0);
6415  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic>
6416  eigenvalues_temp;
6417  Emid[0] = std::real(feast::center);
6418  Emid[1] = std::imag(feast::center);
6419 
6420  std::cout << "in " << __LINE__ << '\n' << std::flush;
6421  zfeast_gegv_(&N, masterL2.data(), &ldL, masterM2.data(), &ldM,
6422  feast::feastparam, &epsout, &loop, Emid, &feast::radius,
6423  &feast::M0, lambda.data(), vecs.data(), &M, res, &feast::info);
6424  feast::display();
6425  // feast::M0 = M + 10;
6426  // lambda.resize(feast::M0, 1);
6427  // vecs.resize(feast::M0, 2 * feast::M0);
6428  // feast::feast_init();
6429  // zfeast_gegv_(&N, masterL2.data(), &ldL, masterM2.data(), &ldM,
6430  // feast::feastparam, &epsout, &loop, Emid, &feast::radius, &feast::M0,
6431  //lambda.data(), vecs.data(), &M, res, &feast::info);
6432  std::cout << "M = " << M << '\n';
6433  // std::cout << "lambda = " << lambda.block(0,0,M,1) << '\n';
6434  eigenvalues_temp = lambda.block(0, 0, M, 1);
6435  vr.resize(masterL2.rows(), M);
6436  vr = vecs.block(0, 0, vecs.rows(), M);
6437  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic>
6438  evecMat_master(c * (N + 1), M);
6439  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, 1> temp_vec;
6440  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> fir_n_mat =
6441  subs_mat * vr;
6442  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> evecMat(
6443  c * (N + 1) + total_boundary_conditions, M);
6444  evecMat << fir_n_mat, vr;
6445  // Unpermute eveMat:
6446  evecMat = P * evecMat;
6447  row_counter = 0;
6448  col_counter = 0;
6449  for (int i = 0; i < c; i++) {
6450  int n = (highest_each_columnL[i] > highest_each_columnM[i])
6451  ? highest_each_columnL[i]
6452  : highest_each_columnM[i];
6453  Mat.compute(n);
6454  evecMat_master.block(i * (N + 1), 0, N + 1, M) =
6455  Mat.mats2[n] * evecMat.block(row_counter, 0, N + 1 + n, M);
6456  row_counter += N + 1 + n;
6457  }
6458  std::vector<std::vector<T> > eigenval_trunc_sorter;
6459 
6460  eigenval_trunc_sorter.resize(M);
6461  for (int i = 0; i < M; i++) {
6462  eigenval_trunc_sorter[i].resize(2);
6463  }
6464 
6465  Eigen::Matrix<int, Eigen::Dynamic, 1> MPcount(M);
6466  MPcount.setConstant(0);
6467  std::vector<EigenSorter<T> > sorter;
6468  sorter.resize(M);
6469  for (int i = 0; i < M; i++) {
6470  sorter[i].compute(evecMat_master.block(0, i, c * (N + 1), 1), c);
6471  // sorter[i].compute(evecMat_master.block(0, i, (N + 1), 1));
6472  if (sorter[i].Mp == true) {
6473  MPcount[i] = 1;
6474  }
6475  }
6476  if (num_vals > M) {
6477  std::cout << "Only " << M << " eigenvalues can be calculated."
6478  << "Storing only that many." << '\n';
6479  num_vals = M;
6480  }
6481 
6482  int MPcount_sum = MPcount.sum();
6483  converged = MPcount_sum;
6484 
6485  eigenvectorsMat.resize(num_vals);
6486  for (int i = 0; i < num_vals; i++) {
6487  eigenvectorsMat[i].resize(c, 1);
6488  }
6489  eigenvalues.resize(num_vals);
6490  converged = MPcount_sum;
6491  if (MPcount_sum >= num_vals) {
6492  for (int i = 0; i < M; i++) {
6493  eigenval_trunc_sorter[i][0] = T(sorter[i].numMp);
6494  eigenval_trunc_sorter[i][1] = i;
6495  // std::cout << eigs.eigenvalues()[i] << " " << sorter[i].numMp <<
6496  // "\n"; std::cin > > bre;
6497  }
6498  std::sort(eigenval_trunc_sorter.begin(), eigenval_trunc_sorter.end());
6499  for (int i = 0; i < num_vals; i++) {
6500  eigenvalues[i] = eigenvalues_temp(int(eigenval_trunc_sorter[i][1]), 0);
6501  }
6502  for (int j = 0; j < c; j++) {
6503  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
6504  ? highest_each_columnL[j]
6505  : highest_each_columnM[j];
6506 
6507  temp_vec.resize(N + 1 + n, 1);
6508  for (int i = 0; i < num_vals; i++) {
6509  eigenvectorsMat[i][j] = evecMat_master.block(
6510  j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
6511  eigenvectorsMat[i][j].dct_flag = SIS_CHEB_SPACE;
6512  }
6513  }
6514  } else {
6515  std::cout << "Last " << num_vals - MPcount_sum
6516  << " eigenvectors are not resolved to machine precision."
6517  << '\n';
6518  for (int i = 0; i < M; i++) {
6519  eigenval_trunc_sorter[i][0] = T(sorter[i].numMp);
6520  eigenval_trunc_sorter[i][1] = i;
6521  }
6522  std::sort(eigenval_trunc_sorter.begin(), eigenval_trunc_sorter.end());
6523  for (int i = 0; i < MPcount_sum; i++) {
6524  eigenvalues[i] = eigenvalues_temp(int(eigenval_trunc_sorter[i][1]), 0);
6525  }
6526  for (int j = 0; j < c; j++) {
6527  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
6528  ? highest_each_columnL[j]
6529  : highest_each_columnM[j];
6530  temp_vec.resize(N + 1 + n, 1);
6531  for (int i = 0; i < MPcount_sum; i++) {
6532  eigenvectorsMat[i][j] = evecMat_master.block(
6533  j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
6534  eigenvectorsMat[i][j].dct_flag = SIS_CHEB_SPACE;
6535  }
6536  }
6537 
6538  std::vector<std::vector<T> > eigenval_trunc_sorter2;
6539  eigenval_trunc_sorter2.resize(M - MPcount_sum);
6540  for (int i = MPcount_sum; i < M; i++) {
6541  eigenval_trunc_sorter2[i - MPcount_sum].resize(2);
6542  eigenval_trunc_sorter2[i - MPcount_sum][0] =
6543  sorter[int(eigenval_trunc_sorter[i][1])].minVal;
6544  eigenval_trunc_sorter2[i - MPcount_sum][1] =
6545  eigenval_trunc_sorter[i][1];
6546  }
6547  std::sort(eigenval_trunc_sorter2.begin(), eigenval_trunc_sorter2.end());
6548  for (int i = MPcount_sum; i < num_vals; i++) {
6549  eigenvalues[i] = eigenvalues_temp(
6550  int(eigenval_trunc_sorter2[i - MPcount_sum][1]), 0);
6551  }
6552  for (int j = 0; j < c; j++) {
6553  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
6554  ? highest_each_columnL[j]
6555  : highest_each_columnM[j];
6556  Mat.compute(n);
6557  temp_vec.resize(N + 1 + n, 1);
6558  for (int i = MPcount_sum; i < num_vals; i++) {
6559  eigenvectorsMat[i][j] = evecMat_master.block(
6560  j * (N + 1), int(eigenval_trunc_sorter2[i - MPcount_sum][1]),
6561  N + 1, 1);
6562  eigenvectorsMat[i][j].dct_flag = SIS_CHEB_SPACE;
6563  }
6564  }
6565  }
6566  }
6567 #endif
6568  void compute_with_constraints(const LinopMat<std::complex<T> > &Lmat_,
6577  const LinopMat<std::complex<T> > &Mmat_,
6578  int num_vals,
6579  const BcMat<std::complex<T> > &Lbc_,
6580  const BcMat<std::complex<T> > &Mbc_) {
6581 
6582  LinopMat<std::complex<T> > Lmat = Lmat_;
6583  LinopMat<std::complex<T> > Mmat = Mmat_;
6584  BcMat<std::complex<T> > Lbc = Lbc_;
6585  BcMat<std::complex<T> > Mbc = Mbc_;
6586  int bre;
6587  int total_of_all_orders = 0;
6588  int total_boundary_conditions = 0;
6589  if (Lmat.r != Lmat.c) {
6590  std::cout << "Solution only possible with square LinopMats. Exiting ..."
6591  << '\n';
6592  exit(1);
6593  }
6594  if (Mmat.r != Mmat.c) {
6595  std::cout << "Solution only possible with square LinopMats. Exiting ..."
6596  << '\n';
6597  exit(1);
6598  }
6599  if (Mmat.c != Lmat.c) {
6600  std::cout << "Both matrices have to be of same size. Exiting ..." << '\n';
6601  exit(1);
6602  }
6603  int r = Lmat.r, c = Lmat.c;
6604  // Find the highest derivative in each column. To do this create a vector
6605  // highest_each_column, and a temp_int_vec that will hold all values of a
6606  // given column to and the maximum will be stored in highest_each_column
6607  std::vector<int> highest_each_columnL, highest_each_columnM,
6608  highest_each_column, num_bc_each_var;
6609  highest_each_columnL.resize(c);
6610  highest_each_columnM.resize(c);
6611  highest_each_column.resize(c);
6612  num_bc_each_var.resize(c);
6613  std::vector<int> temp_vec_int;
6614  temp_vec_int.resize(r);
6615  for (int j = 0; j < c; j++) {
6616  for (int i = 0; i < r; i++) {
6617  temp_vec_int[i] = Lmat(i, j).n;
6618  }
6619  highest_each_columnL[j] =
6620  *std::max_element(temp_vec_int.begin(), temp_vec_int.end());
6621  }
6622  for (int j = 0; j < c; j++) {
6623  for (int i = 0; i < r; i++) {
6624  temp_vec_int[i] = Mmat(i, j).n;
6625  }
6626  highest_each_columnM[j] =
6627  *std::max_element(temp_vec_int.begin(), temp_vec_int.end());
6628  }
6629  for (int i = 0; i < c; i++) {
6630  total_of_all_orders += (highest_each_columnL[i] > highest_each_columnM[i])
6631  ? highest_each_columnL[i]
6632  : highest_each_columnM[i];
6633  highest_each_column[i] =
6634  (highest_each_columnL[i] > highest_each_columnM[i])
6635  ? highest_each_columnL[i]
6636  : highest_each_columnM[i];
6637  }
6638  for (int i = 0; i < c; i++) {
6639  total_boundary_conditions += Lmat.BcVec[i].nbc();
6640  num_bc_each_var[i] = Lmat.BcVec[i].nbc();
6641  }
6642 
6643  if (Lbc.m != Mbc.m) {
6644  std::cout << "The Lbc and Mbc have to be of same dimensions" << '\n'
6645  << "Exiting in " << __LINE__ << "...\n";
6646 
6647  exit(1);
6648  }
6649  // total_of_all_orders has to be equal to total number of boundary
6650  // conditions, else the problem is ill-posed, if ill-posed, cout the same
6651  // and exit.
6652  if (total_of_all_orders != (total_boundary_conditions + Lbc.m)) {
6653  std::cout << "The problem is ill-posed, the total of the highest "
6654  "orders of all "
6655  "dependent variables has to be equal to the total number of "
6656  "boundary conditions plus number of constraints specified."
6657  "\n "
6658  "Total no. of boundary conditions: "
6659  << total_boundary_conditions
6660  << "\n"
6661  "Total of all orders: "
6662  << total_of_all_orders << "\n Number of Constraints : " << Lbc.m
6663  << "\n Exiting in " << __LINE__ << " ...\n ";
6664  exit(1);
6665  }
6666  // Declare the master matrix L:
6667  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> masterL(
6668  r * (N + 1) + Lbc.m, c * (N + 1) + Lbc.m);
6669  // Declare the master matrix M:
6670  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> masterM(
6671  r * (N + 1) + Lbc.m, c * (N + 1) + Lbc.m);
6672 
6673  masterL.setConstant(0.0);
6674  masterM.setConstant(0.0);
6675  MatGen<T> Mat;
6676  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> subs_mat;
6677 
6678  subs_mat.resize(total_boundary_conditions, (N + 1) * c + Lbc.m);
6679 
6680  subs_mat.setConstant(0.0);
6681  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> mat_temp(
6682  total_boundary_conditions, total_boundary_conditions);
6683  mat_temp.setConstant(0.0);
6684  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic>
6685  subs_mat_col_mul(c * (N + 1), total_boundary_conditions);
6686  subs_mat_col_mul.setConstant(0.0);
6687  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic>
6688  subs_mat_col_mul2(c * (N + 1), total_boundary_conditions);
6689  subs_mat_col_mul2.setConstant(0.0);
6690  int subs_mat_row_counter = 0;
6691  int subs_mat_col_counter = 0;
6692  int row_counter = 0, col_counter = 0;
6693  for (int j = 0; j < c; j++) {
6694  // overall order is the one which is greater in each column:
6695  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
6696  ? highest_each_columnL[j]
6697  : highest_each_columnM[j];
6698  // Store the LinopMat with the larger degree to setup boundary conditions
6699  // LinopMat<std::complex<T> > Tmat =
6700  // (highest_each_columnL[j] > highest_each_columnM[j]) ? Lmat : Mmat;
6701 
6702  Mat.compute(n);
6703  std::vector<Eigen::Matrix<std::complex<T>, 1, Eigen::Dynamic> > lbc_vecs(
6704  Lmat.BcVec[j].nl,
6705  Eigen::Matrix<std::complex<T>, 1, Eigen::Dynamic>(N + 1 + 2 * n));
6706  std::vector<Eigen::Matrix<std::complex<T>, 1, Eigen::Dynamic> > rbc_vecs(
6707  Lmat.BcVec[j].nr,
6708  Eigen::Matrix<std::complex<T>, 1, Eigen::Dynamic>(N + 1 + 2 * n));
6709  std::vector<Eigen::Matrix<std::complex<T>, 1, Eigen::Dynamic> >
6710  lbc_con_vecs(Lmat.BcVec[j].nl,
6711  Eigen::Matrix<std::complex<T>, 1, Eigen::Dynamic>(n));
6712  std::vector<Eigen::Matrix<std::complex<T>, 1, Eigen::Dynamic> >
6713  rbc_con_vecs(Lmat.BcVec[j].nr,
6714  Eigen::Matrix<std::complex<T>, 1, Eigen::Dynamic>(n));
6715  Eigen::Matrix<T, 1, Eigen::Dynamic> ones(N + 1 + 2 * n);
6716  Eigen::Matrix<T, 1, Eigen::Dynamic> onem(N + 1 + 2 * n);
6717  Eigen::Matrix<T, 1, Eigen::Dynamic> onesn(n);
6718  Eigen::Matrix<T, 1, Eigen::Dynamic> onemn(n);
6719  // This follows as T_n(1) = 1.0.
6720  ones.setConstant(1.0);
6721  onesn.setConstant(1.0);
6722  onem.setConstant(1.0);
6723  onemn.setConstant(1.0);
6724  // This follows as T_n(-1) = (-1)^n.
6725  for (int k = 1; k < N + 1 + 2 * n; k = k + 2) {
6726  onem[k] = -1.0;
6727  }
6728  for (int k = 1; k < n; k = k + 2) {
6729  onemn[k] = -1.0;
6730  }
6731  if (n > 0) {
6732  ones[0] = 0.5;
6733  onesn[0] = 0.5;
6734  onem[0] = 0.5;
6735  onemn[0] = 0.5;
6736  }
6737  // Next just multiply matrices based on the order.
6738  for (int k = 0; k < Lmat.BcVec[j].nl; k++) {
6739  lbc_vecs[k].resize(N + 1 + 2 * n);
6740  lbc_vecs[k].setConstant(std::complex<T>(0.0, 0.0));
6741  for (int l = 0; l < Lmat.BcVec[j].ord + 1; l++) {
6742  lbc_vecs[k] += Lmat.BcVec[j].coefl(k, l) *
6743  (onem * Mat.mats[l + (n - Lmat.BcVec[j].ord)]);
6744  }
6745  }
6746 
6747  for (int k = 0; k < Lmat.BcVec[j].nr; k++) {
6748  rbc_vecs[k].resize(N + 1 + 2 * n);
6749  rbc_vecs[k].setConstant(std::complex<T>(0.0, 0.0));
6750  for (int l = 0; l < Lmat.BcVec[j].ord + 1; l++) {
6751  rbc_vecs[k] += Lmat.BcVec[j].coefr(k, l) *
6752  (ones * Mat.mats[l + (n - Lmat.BcVec[j].ord)]);
6753  }
6754  }
6755  for (int k = 0; k < Lmat.BcVec[j].nl; k++) {
6756  lbc_con_vecs[k].setConstant(0.0);
6757  for (int l = 0; l < Lmat.BcVec[j].ord + 1; l++) {
6758  if (l + n - Lmat.BcVec[j].ord - 1 > -1) {
6759  lbc_con_vecs[k] +=
6760  Lmat.BcVec[j].coefl(k, l) *
6761  (onemn * Mat.con_mats[l + n - Lmat.BcVec[j].ord - 1]);
6762  }
6763  }
6764  }
6765  for (int k = 0; k < Lmat.BcVec[j].nr; k++) {
6766  rbc_con_vecs[k].setConstant(0.0);
6767  for (int l = 0; l < Lmat.BcVec[j].ord + 1; l++) {
6768  if (l + n - Lmat.BcVec[j].ord - 1 > -1) {
6769  rbc_con_vecs[k] +=
6770  Lmat.BcVec[j].coefr(k, l) *
6771  (onesn * Mat.con_mats[l + n - Lmat.BcVec[j].ord - 1]);
6772  }
6773  }
6774  }
6775 
6776  for (int k = 0; k < Lmat.BcVec[j].nl; k++) {
6777  mat_temp.block(row_counter, col_counter, 1,
6778  Lmat.BcVec[j].nl + Lmat.BcVec[j].nr) =
6779  lbc_vecs[k].head(Lmat.BcVec[j].nl + Lmat.BcVec[j].nr);
6780  row_counter++;
6781  }
6782  for (int k = Lmat.BcVec[j].nl; k < Lmat.BcVec[j].nl + Lmat.BcVec[j].nr;
6783  k++) {
6784  mat_temp.block(row_counter, col_counter, 1,
6785  Lmat.BcVec[j].nl + Lmat.BcVec[j].nr) =
6786  rbc_vecs[k - Lmat.BcVec[j].nl].head(Lmat.BcVec[j].nl +
6787  Lmat.BcVec[j].nr);
6788  row_counter++;
6789  }
6790  col_counter = col_counter + Lmat.BcVec[j].nbc();
6791  for (int k = 0; k < Lmat.BcVec[j].nl; k++) {
6792  subs_mat.block(subs_mat_row_counter, subs_mat_col_counter, 1,
6793  (N + 1 - Lmat.BcVec[j].nbc())) =
6794  lbc_vecs[k].block(0, Lmat.BcVec[j].nbc(), 1,
6795  N + 1 - Lmat.BcVec[j].nbc());
6796  subs_mat.block(subs_mat_row_counter,
6797  subs_mat_col_counter + (N + 1 - Lmat.BcVec[j].nbc()), 1,
6798  n) = lbc_con_vecs[k];
6799  subs_mat_row_counter++;
6800  }
6801 
6802  for (int k = Lmat.BcVec[j].nl; k < Lmat.BcVec[j].nbc(); k++) {
6803  subs_mat.block(subs_mat_row_counter, subs_mat_col_counter, 1,
6804  (N + 1 - Lmat.BcVec[j].nbc())) =
6805  rbc_vecs[k - Lmat.BcVec[j].nl].block(0, Lmat.BcVec[j].nbc(), 1,
6806  N + 1 - Lmat.BcVec[j].nbc());
6807  subs_mat.block(subs_mat_row_counter,
6808  subs_mat_col_counter + (N + 1 - Lmat.BcVec[j].nbc()), 1,
6809  n) = rbc_con_vecs[k - Lmat.BcVec[j].nl];
6810  subs_mat_row_counter++;
6811  }
6812  subs_mat_col_counter += (N + 1 + n - Lmat.BcVec[j].nbc());
6813  }
6814  if (mat_temp.rows() != 0 || mat_temp.cols() != 0) {
6815  Eigen::ColPivHouseholderQR<
6816  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> >
6817  consSolver(mat_temp);
6818  if (!consSolver.isInvertible()) {
6819  std::cout << "the matrix is not invertible." << '\n';
6820  exit(1);
6821  }
6822  subs_mat = -consSolver.inverse() * subs_mat.eval();
6823  }
6824  row_counter = 0;
6825  col_counter = 0;
6826  int master_row_counter = 0;
6827  int master_col_counter = 0;
6828  subs_mat_row_counter = 0;
6829  subs_mat_col_counter = 0;
6830  for (int j = 0; j < c; j++) {
6831  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
6832  ? highest_each_columnL[j]
6833  : highest_each_columnM[j];
6834  Mat.compute(n);
6835  for (int i = 0; i < r; i++) {
6836 
6837  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic>
6838  solver_matL(N + 1, N + 1 + n - Lmat.BcVec[j].nbc());
6839  solver_matL.setConstant(0.0);
6840  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic>
6841  solver_matM(N + 1, N + 1 + n - Lmat.BcVec[j].nbc());
6842  solver_matM.setConstant(0.0);
6843  int diffn = n - Lmat(i, j).n;
6844  if (Lmat(i, j).NCC == 0) {
6845  for (int k = 0; k < Lmat(i, j).n + 1; k++) {
6846  solver_matL.block(0, 0, N + 1, N + 1 + n - Lmat.BcVec[j].nbc()) +=
6847  Lmat(i, j).coef[k] *
6848  (Mat.mats2[k + diffn].block(0, Lmat.BcVec[j].nbc(), N + 1,
6849  N + 1 + n - Lmat.BcVec[j].nbc()));
6850  subs_mat_col_mul.block(i * (N + 1), subs_mat_col_counter, N + 1,
6851  Lmat.BcVec[j].nbc()) +=
6852  Lmat(i, j).coef[k] *
6853  (Mat.mats2[k + diffn].block(0, 0, N + 1, Lmat.BcVec[j].nbc()));
6854  }
6855  } else {
6856  for (int k = 0; k < Lmat(i, j).n + 1; k++) {
6857  solver_matL.block(0, 0, N + 1, N + 1 + n - Lmat.BcVec[j].nbc()) +=
6858  Lmat(i, j).coefFun[k].MultMat().block(0, 0, N + 1, N + 1) *
6859  (Mat.mats2[k + diffn].block(0, Lmat.BcVec[j].nbc(), N + 1,
6860  N + 1 + n - Lmat.BcVec[j].nbc()));
6861  subs_mat_col_mul.block(i * (N + 1), subs_mat_col_counter, N + 1,
6862  Lmat.BcVec[j].nbc()) +=
6863  Lmat(i, j).coefFun[k].MultMat().block(0, 0, N + 1, N + 1) *
6864  (Mat.mats2[k + diffn].block(0, 0, N + 1, Lmat.BcVec[j].nbc()));
6865  }
6866  }
6867  diffn = n - Mmat(i, j).n;
6868  if (Mmat(i, j).NCC == 0) {
6869  for (int k = 0; k < Mmat(i, j).n + 1; k++) {
6870  solver_matM.block(0, 0, N + 1, N + 1 + n - Lmat.BcVec[j].nbc()) +=
6871  Mmat(i, j).coef[k] *
6872  (Mat.mats2[k + diffn].block(0, Lmat.BcVec[j].nbc(), N + 1,
6873  N + 1 + n - Lmat.BcVec[j].nbc()));
6874  subs_mat_col_mul2.block(i * (N + 1), subs_mat_col_counter, N + 1,
6875  Lmat.BcVec[j].nbc()) +=
6876  Mmat(i, j).coef[k] *
6877  (Mat.mats2[k + diffn].block(0, 0, N + 1, Lmat.BcVec[j].nbc()));
6878  }
6879  } else {
6880  for (int k = 0; k < Mmat(i, j).n + 1; k++) {
6881  solver_matM.block(0, 0, N + 1, N + 1 + n - Lmat.BcVec[j].nbc()) +=
6882  Mmat(i, j).coefFun[k].MultMat().block(0, 0, N + 1, N + 1) *
6883  (Mat.mats2[k + diffn].block(0, Lmat.BcVec[j].nbc(), N + 1,
6884  N + 1 + n - Lmat.BcVec[j].nbc()));
6885  subs_mat_col_mul2.block(i * (N + 1), subs_mat_col_counter, N + 1,
6886  Lmat.BcVec[j].nbc()) +=
6887  Mmat(i, j).coefFun[k].MultMat().block(0, 0, N + 1, N + 1) *
6888  (Mat.mats2[k + diffn].block(0, 0, N + 1, Lmat.BcVec[j].nbc()));
6889  }
6890  }
6891  subs_mat_row_counter += N + 1 + n - Lmat.BcVec[j].nbc();
6892  masterL.block(i * (N + 1), master_col_counter, N + 1,
6893  N + 1 + n - Lmat.BcVec[j].nbc()) = solver_matL;
6894  masterM.block(i * (N + 1), master_col_counter, N + 1,
6895  N + 1 + n - Lmat.BcVec[j].nbc()) = solver_matM;
6896  }
6897  subs_mat_col_counter += Lmat.BcVec[j].nbc();
6898  subs_mat_row_counter = 0;
6899  master_row_counter = 0;
6900  master_col_counter += N + 1 + n - Lmat.BcVec[j].nbc();
6901  }
6902  if (mat_temp.rows() != 0 || mat_temp.cols() != 0) {
6903  masterL.block(0, 0, c * (N + 1), c * (N + 1) + Lbc.m) +=
6904  masterL.block(0, 0, c * (N + 1), c * (N + 1) + Lbc.m).eval() +
6905  (subs_mat_col_mul * subs_mat);
6906  masterM.block(0, 0, c * (N + 1), c * (N + 1) + Lbc.m) +=
6907  masterM.block(0, 0, c * (N + 1), c * (N + 1) + Lbc.m).eval() +
6908  (subs_mat_col_mul2 * subs_mat);
6909  }
6910  // Now append the constraints:
6911 
6912  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic>
6913  constraints_bigL(Lbc.m, c * (N + 1) + Lbc.m),
6914  constraints_smallL(Lbc.m, total_boundary_conditions),
6915  constraints_bigM(Lbc.m, c * (N + 1) + Lbc.m),
6916  constraints_smallM(Lbc.m, total_boundary_conditions);
6917  constraints_bigL.setConstant(0.0);
6918  constraints_smallL.setConstant(0.0);
6919  constraints_bigM.setConstant(0.0);
6920  constraints_smallM.setConstant(0.0);
6921  col_counter = 0;
6922  row_counter = 0;
6923  int col_counter2 = 0;
6924  int row_counter2 = 0;
6925  for (int i = 0; i < Lbc.m; i++) {
6926  for (int j = 0; j < Lbc.n; j++) {
6927  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> temp =
6928  Lbc(i, j, highest_each_column[j]);
6929 
6930  constraints_bigL.block(i, col_counter, 1,
6931  N + 1 + highest_each_column[j] -
6932  num_bc_each_var[j]) =
6933  temp.block(0, num_bc_each_var[j], 1,
6934  N + 1 + highest_each_column[j] - num_bc_each_var[j]);
6935 
6936  constraints_smallL.block(i, col_counter2, 1, num_bc_each_var[j]) =
6937  temp.block(0, 0, 1, num_bc_each_var[j]);
6938  // std::cout << "i = " << i << ", j = " << j << ",
6939  // highest_each_column["
6940  // << j << "]= " << highest_each_column[j] << '\n';
6941  temp = Mbc(i, j, highest_each_column[j]);
6942 
6943  constraints_bigM.block(i, col_counter, 1,
6944  N + 1 + highest_each_column[j] -
6945  num_bc_each_var[j]) =
6946  temp.block(0, num_bc_each_var[j], 1,
6947  N + 1 + highest_each_column[j] - num_bc_each_var[j]);
6948 
6949  constraints_smallM.block(i, col_counter2, 1, num_bc_each_var[j]) =
6950  temp.block(0, 0, 1, num_bc_each_var[j]);
6951  col_counter += N + 1 + highest_each_column[j] - num_bc_each_var[j];
6952  col_counter2 += num_bc_each_var[j];
6953  }
6954  col_counter = 0;
6955  col_counter2 = 0;
6956  }
6957  if (mat_temp.rows() != 0 || mat_temp.cols() != 0) {
6958  masterL.block(c * (N + 1), 0, Lbc.m, c * (N + 1) + Lbc.m) =
6959  constraints_bigL + constraints_smallL * subs_mat;
6960  masterM.block(c * (N + 1), 0, Lbc.m, c * (N + 1) + Lbc.m) =
6961  constraints_bigM + constraints_smallM * subs_mat;
6962  } else {
6963  masterL.block(c * (N + 1), 0, Lbc.m, c * (N + 1) + Lbc.m) =
6964  constraints_bigL;
6965  masterM.block(c * (N + 1), 0, Lbc.m, c * (N + 1) + Lbc.m) =
6966  constraints_bigM;
6967  }
6968 
6969 #ifndef SIS_USE_LAPACK
6970  Eigen::ColPivHouseholderQR<
6971  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> >
6972  solver(masterM);
6973  Eigen::ComplexEigenSolver<
6974  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> >
6975  eigs;
6976  bool Is_M_Invertible;
6977  if (solver.isInvertible()) {
6978  Is_M_Invertible = true;
6979  eigs.compute(solver.inverse() * masterL);
6980  // std::cout << "Eigenvalues :\n" << eigs.eigenvalues() << '\n';
6981  } else {
6982  Is_M_Invertible = false;
6983  solver.compute(masterL);
6984  eigs.compute(solver.inverse() * masterM);
6985  // std::cout << "Eigenvalues :\n" << 1 / eigs.eigenvalues().array() <<
6986  // '\n';
6987  }
6988  // std::cin >> bre;
6989  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic>
6990  evecMat_master(c * (N + 1) + Lbc.m, c * (N + 1) + Lbc.m);
6991  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, 1> temp_vec;
6992  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> fir_n_mat,
6993  full_mat;
6994  if (subs_mat.size() > 0) {
6995  fir_n_mat = subs_mat * eigs.eigenvectors();
6996  }
6997  full_mat.resize(c * (N + 1) + Lbc.m + fir_n_mat.rows(),
6998  c * (N + 1) + Lbc.m);
6999 
7000  row_counter = 0;
7001  row_counter2 = 0;
7002  col_counter = 0;
7003  // Repack eigenvectors using fir_n_mat:
7004  for (int i = 0; i < c; i++) {
7005  int n = (highest_each_columnL[i] > highest_each_columnM[i])
7006  ? highest_each_columnL[i]
7007  : highest_each_columnM[i];
7008  if (subs_mat.size() > 0) {
7009  full_mat.block(row_counter, 0, num_bc_each_var[i],
7010  c * (N + 1) + Lbc.m) =
7011  fir_n_mat.block(col_counter, 0, num_bc_each_var[i],
7012  c * (N + 1) + Lbc.m);
7013  }
7014  row_counter += num_bc_each_var[i];
7015  col_counter += num_bc_each_var[i];
7016 
7017  full_mat.block(row_counter, 0, N + 1 + n - num_bc_each_var[i],
7018  c * (N + 1) + Lbc.m) =
7019  eigs.eigenvectors().block(row_counter2, 0,
7020  N + 1 + n - num_bc_each_var[i],
7021  c * (N + 1) + Lbc.m);
7022  row_counter += N + 1 + n - num_bc_each_var[i];
7023  row_counter2 += N + 1 + n - num_bc_each_var[i];
7024  }
7025 
7026  row_counter = 0;
7027  for (int i = 0; i < c; i++) {
7028  int n = (highest_each_columnL[i] > highest_each_columnM[i])
7029  ? highest_each_columnL[i]
7030  : highest_each_columnM[i];
7031  Mat.compute(n);
7032  evecMat_master.block(i * (N + 1), 0, N + 1, c * (N + 1) + Lbc.m) =
7033  Mat.mats2[n] *
7034  full_mat.block(row_counter, 0, N + 1 + n, c * (N + 1) + Lbc.m);
7035  row_counter += N + 1 + n;
7036  }
7037 
7038  std::vector<std::vector<T> > eigenval_trunc_sorter;
7039 
7040  eigenval_trunc_sorter.resize(c * (N + 1) + Lbc.m);
7041  for (int i = 0; i < c * (N + 1) + Lbc.m; i++) {
7042  eigenval_trunc_sorter[i].resize(2);
7043  }
7044 
7045  Eigen::Matrix<int, Eigen::Dynamic, 1> MPcount(c * (N + 1) + Lbc.m);
7046  MPcount.setConstant(0);
7047  std::vector<EigenSorter<T> > sorter;
7048  sorter.resize(c * (N + 1) + Lbc.m);
7049  for (int i = 0; i < c * (N + 1) + Lbc.m; i++) {
7050  sorter[i].compute(evecMat_master.block(0, i, c * (N + 1), 1), c);
7051  if (!Is_M_Invertible) {
7052  // If M is not invertible, there will be zero eigenvalues, so that 1/0 =
7053  // inf eigenvalue, remove them.
7054  if (abs(eigs.eigenvalues()[i]) < 1e-11) {
7055  sorter[i].numMp = N + 1;
7056  sorter[i].Mp = false;
7057  sorter[i].minVal = 1e11;
7058  }
7059  }
7060  // sorter[i].compute(evecMat_master.block(0, i, (N + 1), 1));
7061  if (sorter[i].Mp == true) {
7062  MPcount[i] = 1;
7063  }
7064  }
7065  if (num_vals > masterL.rows()) {
7066  std::cout << "Only " << masterL.rows()
7067  << " eigenvalues can be calculated."
7068  << "Storing only that many." << '\n';
7069  num_vals = masterL.rows();
7070  }
7071  int MPcount_sum = MPcount.sum();
7072  converged = MPcount_sum;
7073 
7074  eigenvectors.resize(c, num_vals);
7075  //eigenvectorsMat.resize(num_vals);
7076  //for (int i = 0; i < num_vals; i++) {
7077  // eigenvectorsMat[i].resize(c, 1);
7078  //}
7079  eigenvalues.resize(num_vals);
7080  if (MPcount_sum >= num_vals) {
7081  for (int i = 0; i < c * (N + 1) + Lbc.m; i++) {
7082  eigenval_trunc_sorter[i][0] = T(sorter[i].numMp);
7083  eigenval_trunc_sorter[i][1] = i;
7084  // std::cout << eigs.eigenvalues()[i] << " " << sorter[i].numMp <<
7085  // "\n"; std::cin > > bre;
7086  }
7087  std::sort(eigenval_trunc_sorter.begin(), eigenval_trunc_sorter.end());
7088  for (int i = 0; i < num_vals; i++) {
7089  if (Is_M_Invertible) {
7090  eigenvalues[i] = eigs.eigenvalues()[int(eigenval_trunc_sorter[i][1])];
7091  } else {
7092  eigenvalues[i] =
7093  1.0 / eigs.eigenvalues()[int(eigenval_trunc_sorter[i][1])];
7094  }
7095  }
7096  for (int j = 0; j < c; j++) {
7097  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
7098  ? highest_each_columnL[j]
7099  : highest_each_columnM[j];
7100 
7101  temp_vec.resize(N + 1 + n, 1);
7102  for (int i = 0; i < num_vals; i++) {
7103  eigenvectors(j,i) = evecMat_master.block(
7104  j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
7105  eigenvectors(j,i).dct_flag = SIS_CHEB_SPACE;
7106  //eigenvectorsMat[i][j] = evecMat_master.block(
7107  // j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
7108  //eigenvectorsMat[i][j].dct_flag = SIS_CHEB_SPACE;
7109  }
7110  }
7111  } else {
7112  std::cout << "Last " << num_vals - MPcount_sum
7113  << " eigenvectors are not resolved to machine precision."
7114  << '\n';
7115  for (int i = 0; i < c * (N + 1) + Lbc.m; i++) {
7116  eigenval_trunc_sorter[i][0] = T(sorter[i].numMp);
7117  eigenval_trunc_sorter[i][1] = i;
7118  }
7119  std::sort(eigenval_trunc_sorter.begin(), eigenval_trunc_sorter.end());
7120  for (int i = 0; i < MPcount_sum; i++) {
7121  if (Is_M_Invertible) {
7122  eigenvalues[i] = eigs.eigenvalues()[int(eigenval_trunc_sorter[i][1])];
7123  } else {
7124  eigenvalues[i] =
7125  1.0 / eigs.eigenvalues()[int(eigenval_trunc_sorter[i][1])];
7126  }
7127  }
7128  for (int j = 0; j < c; j++) {
7129  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
7130  ? highest_each_columnL[j]
7131  : highest_each_columnM[j];
7132  temp_vec.resize(N + 1 + n, 1);
7133  for (int i = 0; i < MPcount_sum; i++) {
7134  eigenvectors(j,i) = evecMat_master.block(
7135  j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
7136  eigenvectors(j,i).dct_flag = SIS_CHEB_SPACE;
7137  //eigenvectorsMat[i][j] = evecMat_master.block(
7138  // j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
7139  //eigenvectorsMat[i][j].dct_flag = SIS_CHEB_SPACE;
7140  }
7141  }
7142 
7143  std::vector<std::vector<T> > eigenval_trunc_sorter2;
7144  eigenval_trunc_sorter2.resize(c * (N + 1) + Lbc.m - MPcount_sum);
7145  for (int i = MPcount_sum; i < c * (N + 1) + Lbc.m; i++) {
7146  eigenval_trunc_sorter2[i - MPcount_sum].resize(2);
7147  eigenval_trunc_sorter2[i - MPcount_sum][0] =
7148  sorter[int(eigenval_trunc_sorter[i][1])].minVal;
7149  eigenval_trunc_sorter2[i - MPcount_sum][1] =
7150  eigenval_trunc_sorter[i][1];
7151  }
7152  std::sort(eigenval_trunc_sorter2.begin(), eigenval_trunc_sorter2.end());
7153  for (int i = MPcount_sum; i < num_vals; i++) {
7154  if (Is_M_Invertible) {
7155  eigenvalues[i] = eigs.eigenvalues()[int(
7156  eigenval_trunc_sorter2[i - MPcount_sum][1])];
7157  } else {
7158  eigenvalues[i] =
7159  1.0 / eigs.eigenvalues()[int(
7160  eigenval_trunc_sorter2[i - MPcount_sum][1])];
7161  }
7162  }
7163  for (int j = 0; j < c; j++) {
7164  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
7165  ? highest_each_columnL[j]
7166  : highest_each_columnM[j];
7167  Mat.compute(n);
7168  temp_vec.resize(N + 1 + n, 1);
7169  for (int i = MPcount_sum; i < num_vals; i++) {
7170  eigenvectors(j,i) = evecMat_master.block(
7171  j * (N + 1), int(eigenval_trunc_sorter2[i - MPcount_sum][1]),
7172  N + 1, 1);
7173  eigenvectors(j,i).dct_flag = SIS_CHEB_SPACE;
7174  //eigenvectorsMat[i][j] = evecMat_master.block(
7175  // j * (N + 1), int(eigenval_trunc_sorter2[i - MPcount_sum][1]),
7176  // N + 1, 1);
7177  //eigenvectorsMat[i][j].dct_flag = SIS_CHEB_SPACE;
7178  }
7179  }
7180  }
7181 
7182 #else
7183  char jobvl = 'N'; // Don't compute left evecs
7184  char jobvr = 'V'; // Compute right evecs
7185  std::complex<double> wkopt; // Eistimate optimum workspace
7186  std::complex<double> *work; // allocate optimum workspace
7187  alpha.resize(masterL.rows(), 1); // alpha for gen. eig. prob.
7188  beta.resize(masterL.rows(), 1); // beta for gen. eig. prob.
7189 
7190  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> vl(
7191  masterL.rows(), masterL.rows()),
7192  vr(masterL.rows(), masterL.rows()), eigenvalues_temp(masterL.rows(), 1),
7193  alpha_temp(masterL.rows(), 1), beta_temp(masterL.rows(), 1);
7194  // vl : left evecs, vr: right evecs.
7195  int ldL = masterL.outerStride(); // ld for leading dimension
7196  int ldM = masterM.outerStride();
7197  int ldvl = vl.outerStride();
7198  int ldvr = vr.outerStride();
7199  int sizeL = masterL.rows();
7200  int lwork = -1; // set lwork to -1 to estimate workspace.
7201  double rwork[8 * sizeL];
7202 
7203  // call this to estimate workspace
7204  zggev_(&jobvl, &jobvr, &sizeL, masterL.data(), &ldL, masterM.data(), &ldM,
7205  alpha_temp.data(), beta_temp.data(), vl.data(), &ldvl, vr.data(),
7206  &ldvr, &wkopt, &lwork, rwork, &info);
7207 
7208  // Now allocate workspace:
7209  lwork = (int)real(wkopt);
7210  work = (std::complex<double> *)malloc(lwork * sizeof(std::complex<double>));
7211 
7212  // Solve eigenvalue problem:
7213  zggev_(&jobvl, &jobvr, &sizeL, masterL.data(), &ldL, masterM.data(), &ldM,
7214  alpha_temp.data(), beta_temp.data(), vl.data(), &ldvl, vr.data(),
7215  &ldvr, work, &lwork, rwork, &info);
7216 
7217  // Free workspace.
7218  free((void *)work);
7219 
7220  eigenvalues_temp = alpha_temp.array() / beta_temp.array();
7221 
7222  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic>
7223  evecMat_master(c * (N + 1), c * (N + 1) + Lbc.m);
7224  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, 1> temp_vec;
7225  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> fir_n_mat =
7226  subs_mat * vr;
7227  row_counter = 0;
7228  col_counter = 0;
7229  for (int i = 0; i < c; i++) {
7230  int n = (highest_each_columnL[i] > highest_each_columnM[i])
7231  ? highest_each_columnL[i]
7232  : highest_each_columnM[i];
7233  Mat.compute(n);
7234  // std::cout << "n = " << n << '\n';
7235  // std::cin > > bre;
7236 
7237  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> evecMat(
7238  N + 1 + n, c * (N + 1) + Lbc.m);
7239  evecMat.setConstant(0.0);
7240  evecMat.block(num_bc_each_var[i], 0, N + 1 + n - num_bc_each_var[i],
7241  c * (N + 1) + Lbc.m) =
7242  vr.block(row_counter, 0, N + 1 + n - num_bc_each_var[i],
7243  c * (N + 1) + Lbc.m);
7244  row_counter += N + 1 + n - num_bc_each_var[i];
7245  evecMat.block(0, 0, num_bc_each_var[i], c * (N + 1) + Lbc.m) =
7246  fir_n_mat.block(col_counter, 0, num_bc_each_var[i],
7247  c * (N + 1) + Lbc.m);
7248  col_counter += num_bc_each_var[i];
7249  evecMat_master.block(i * (N + 1), 0, N + 1, c * (N + 1) + Lbc.m) =
7250  Mat.mats2[n] * evecMat;
7251  }
7252  std::vector<std::vector<T> > eigenval_trunc_sorter;
7253 
7254  eigenval_trunc_sorter.resize(c * (N + 1) + Lbc.m);
7255  for (int i = 0; i < c * (N + 1) + Lbc.m; i++) {
7256  eigenval_trunc_sorter[i].resize(2);
7257  }
7258 
7259  Eigen::Matrix<int, Eigen::Dynamic, 1> MPcount(c * (N + 1) + Lbc.m);
7260  MPcount.setConstant(0);
7261  std::vector<EigenSorter<T> > sorter;
7262  sorter.resize(c * (N + 1) + Lbc.m);
7263  for (int i = 0; i < c * (N + 1) + Lbc.m; i++) {
7264  sorter[i].compute(evecMat_master.block(0, i, c * (N + 1), 1), c);
7265  // sorter[i].compute(evecMat_master.block(0, i, (N + 1), 1));
7266  if (sorter[i].Mp == true) {
7267  MPcount[i] = 1;
7268  }
7269  }
7270  int MPcount_sum = MPcount.sum();
7271  converged = MPcount_sum;
7272 
7273  if (num_vals > masterL.rows()) {
7274  std::cout << "Only " << masterL.rows()
7275  << " eigenvalues can be calculated."
7276  << "Storing only that many." << '\n';
7277  num_vals = masterL.rows();
7278  }
7279 
7280  eigenvectors.resize(c,num_vals);
7281  //eigenvectorsMat.resize(num_vals);
7282  //for (int i = 0; i < num_vals; i++) {
7283  // eigenvectorsMat[i].resize(c, 1);
7284  // }
7285  eigenvalues.resize(num_vals);
7286  if (MPcount_sum >= num_vals) {
7287  for (int i = 0; i < c * (N + 1); i++) {
7288  eigenval_trunc_sorter[i][0] = T(sorter[i].numMp);
7289  eigenval_trunc_sorter[i][1] = i;
7290  // std::cout << eigs.eigenvalues()[i] << " " << sorter[i].numMp <<
7291  // "\n"; std::cin > > bre;
7292  }
7293  std::sort(eigenval_trunc_sorter.begin(), eigenval_trunc_sorter.end());
7294  for (int i = 0; i < num_vals; i++) {
7295  eigenvalues[i] = eigenvalues_temp(int(eigenval_trunc_sorter[i][1]), 0);
7296  alpha[i] = alpha_temp(int(eigenval_trunc_sorter[i][1]), 0);
7297  beta[i] = beta_temp(int(eigenval_trunc_sorter[i][1]), 0);
7298  }
7299  for (int j = 0; j < c; j++) {
7300  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
7301  ? highest_each_columnL[j]
7302  : highest_each_columnM[j];
7303 
7304  temp_vec.resize(N + 1 + n, 1);
7305  for (int i = 0; i < num_vals; i++) {
7306  eigenvectors(j,i) = evecMat_master.block(
7307  j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
7308  eigenvectors(j,i).dct_flag = SIS_CHEB_SPACE;
7309  //eigenvectorsMat[i][j] = evecMat_master.block(
7310  // j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
7311  //eigenvectorsMat[i][j].dct_flag = SIS_CHEB_SPACE;
7312  }
7313  }
7314  } else {
7315  std::cout << "Last " << num_vals - MPcount_sum
7316  << " eigenvectors are not resolved to machine precision."
7317  << '\n';
7318  for (int i = 0; i < c * (N + 1); i++) {
7319  eigenval_trunc_sorter[i][0] = T(sorter[i].numMp);
7320  eigenval_trunc_sorter[i][1] = i;
7321  }
7322  std::sort(eigenval_trunc_sorter.begin(), eigenval_trunc_sorter.end());
7323  for (int i = 0; i < MPcount_sum; i++) {
7324  eigenvalues[i] = eigenvalues_temp(int(eigenval_trunc_sorter[i][1]), 0);
7325  alpha[i] = alpha_temp(int(eigenval_trunc_sorter[i][1]), 0);
7326  beta[i] = beta_temp(int(eigenval_trunc_sorter[i][1]), 0);
7327  }
7328  for (int j = 0; j < c; j++) {
7329  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
7330  ? highest_each_columnL[j]
7331  : highest_each_columnM[j];
7332  temp_vec.resize(N + 1 + n, 1);
7333  for (int i = 0; i < MPcount_sum; i++) {
7334  eigenvectors(j,i) = evecMat_master.block(
7335  j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
7336  eigenvectors(j,i).dct_flag = SIS_CHEB_SPACE;
7337  //eigenvectorsMat[i][j] = evecMat_master.block(
7338  // j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
7339  //eigenvectorsMat[i][j].dct_flag = SIS_CHEB_SPACE;
7340  }
7341  }
7342 
7343  std::vector<std::vector<T> > eigenval_trunc_sorter2;
7344  eigenval_trunc_sorter2.resize(c * (N + 1) + Lbc.m - MPcount_sum);
7345  for (int i = MPcount_sum; i < c * (N + 1) + Lbc.m; i++) {
7346  eigenval_trunc_sorter2[i - MPcount_sum].resize(2);
7347  eigenval_trunc_sorter2[i - MPcount_sum][0] =
7348  sorter[int(eigenval_trunc_sorter[i][1])].minVal;
7349  eigenval_trunc_sorter2[i - MPcount_sum][1] =
7350  eigenval_trunc_sorter[i][1];
7351  }
7352  std::sort(eigenval_trunc_sorter2.begin(), eigenval_trunc_sorter2.end());
7353  for (int i = MPcount_sum; i < num_vals; i++) {
7354  eigenvalues[i] = eigenvalues_temp(
7355  int(eigenval_trunc_sorter2[i - MPcount_sum][1]), 0);
7356  alpha[i] =
7357  alpha_temp(int(eigenval_trunc_sorter2[i - MPcount_sum][1]), 0);
7358  beta[i] = beta_temp(int(eigenval_trunc_sorter2[i - MPcount_sum][1]), 0);
7359  }
7360  for (int j = 0; j < c; j++) {
7361  int n = (highest_each_columnL[j] >= highest_each_columnM[j])
7362  ? highest_each_columnL[j]
7363  : highest_each_columnM[j];
7364  Mat.compute(n);
7365  temp_vec.resize(N + 1 + n, 1);
7366  for (int i = MPcount_sum; i < num_vals; i++) {
7367  eigenvectors(j,i) = evecMat_master.block(
7368  j * (N + 1), int(eigenval_trunc_sorter2[i - MPcount_sum][1]),
7369  N + 1, 1);
7370  eigenvectors(j,i).dct_flag = SIS_CHEB_SPACE;
7371  //eigenvectorsMat[i][j] = evecMat_master.block(
7372  // j * (N + 1), int(eigenval_trunc_sorter2[i - MPcount_sum][1]),
7373  // N + 1, 1);
7374  //eigenvectorsMat[i][j].dct_flag = SIS_CHEB_SPACE;
7375  }
7376  }
7377  }
7378 
7379 #endif
7380  // Convert everything to physical space
7381  eigenvalues.c2p();
7382  }
7383 
7384 
7388 
7389  int n = eigenvalues.size();
7390  std::vector<std::vector<T> > sorter;
7391  sorter.resize(n);
7392  for (int i = 0; i < n; i++) {
7393  sorter[i].resize(2);
7394  }
7395 
7396  for (int i = 0; i < n; i++) {
7397  sorter[i][0] = eigenvalues[i].real();
7398  sorter[i][1] = i;
7399  }
7400 
7401  // Sort in ascending order
7402  std::sort(sorter.begin(), sorter.end());
7403  // Then reverse it.
7404  std::reverse(sorter.begin(), sorter.end());
7405 
7406  ChebfunMat<std::complex<T> > tempMat(eigenvectors.r, eigenvectors.c);
7407  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, 1> tempvals;
7408  Eigen::Matrix<int, Eigen::Dynamic, 1> tempMP;
7409  tempvals = eigenvalues;
7410  tempMat = eigenvectors;
7411  tempMP = MPorNot;
7412 #ifdef SIS_USE_LAPACK
7413  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, 1> tempAlpha, tempBeta;
7414  tempAlpha = alpha;
7415  tempBeta = beta;
7416 #endif
7417  for (int i = 0; i < n; i++) {
7418  eigenvalues[i] = tempvals[sorter[i][1]];
7419  for (int j = 0; j < tempMat.r; j++)
7420  eigenvectors(j,i) = tempMat(j,sorter[i][1]);
7421  MPorNot[i] = tempMP[sorter[i][1]];
7422 
7423 #ifdef SIS_USE_LAPACK
7424  alpha[i] = tempAlpha[sorter[i][1]];
7425  beta[i] = tempBeta[sorter[i][1]];
7426 #endif
7427  }
7428  }
7429 
7431  void keepConverged() {
7432  if (converged < eigenvalues.size()) {
7433  int c = eigenvectors.c;
7434  int r = eigenvectors.r;
7435  ChebfunMat<std::complex<T> > eigenvectors_temp;
7436  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, 1> eigenvalues_temp;
7437 #ifdef SIS_USE_LAPACK
7438  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, 1> alpha_temp = alpha;
7439  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, 1> beta_temp = beta;
7440  alpha.resize(converged);
7441  beta.resize(converged);
7442 #endif
7443  eigenvectors_temp = eigenvectors;
7444  eigenvalues_temp = eigenvalues;
7445  eigenvectors.resize(eigenvectors_temp.r,converged);
7446 
7447  eigenvalues.resize(converged);
7448  int count = 0;
7449  for (int i = 0; i < eigenvalues_temp.size(); i++) {
7450  if (MPorNot[i] == 1) {
7451  for (int j = 0; j < eigenvectors_temp.r; j++)
7452  eigenvectors(j,count) = eigenvectors_temp(j,i);
7453  eigenvalues[count] = eigenvalues_temp[i];
7454 #ifdef SIS_USE_LAPACK
7455  alpha[count] = alpha_temp[i];
7456  beta[count] = beta_temp[i];
7457 #endif
7458  count++;
7459  }
7460  }
7461  MPorNot.resize(converged);
7462  MPorNot.setConstant(1);
7463  }
7464  }
7465 
7468  void keep(int n) {
7469  if (n < eigenvalues.size()) {
7470  int c = eigenvectors.c;
7471  int r = eigenvectors.r;
7472  ChebfunMat<std::complex<T> > eigenvectors_temp;
7473  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, 1> eigenvalues_temp;
7474  eigenvectors_temp = eigenvectors;
7475  eigenvalues_temp = eigenvalues;
7476 #ifdef SIS_USE_LAPACK
7477  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, 1> alpha_temp = alpha;
7478  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, 1> beta_temp = beta;
7479 #endif
7480  eigenvectors.resize(eigenvectors_temp.r,n);
7481  //eigenvectorsMat.resize(n);
7482  //for (int i = 0; i < n; i++) {
7483  // eigenvectorsMat[i].resize(c, 1);
7484  //}
7485 
7486  eigenvalues.resize(n);
7487  for (int i = 0; i < n; i++) {
7488  for (int j = 0; j < eigenvectors_temp.r; j++)
7489  eigenvectors(j,i) = eigenvectors_temp(j,i);
7490  eigenvalues[i] = eigenvalues_temp[i];
7491 #ifdef SIS_USE_LAPACK
7492  alpha[i] = alpha_temp[i];
7493  beta[i] = beta_temp[i];
7494 #endif
7495  }
7496  }
7497  }
7498 
7501  void removeInf() {
7502  std::vector<T> noninf_indices;
7503  for (int i = 0; i < eigenvalues.size(); i++) {
7504 #ifndef SIS_USE_LAPACK
7505  if (std::abs(eigenvalues[i]) > 1.0e8 ||
7506  std::isnan(eigenvalues[i].real()) ||
7507  std::isnan(eigenvalues[i].imag())) {
7508  } else {
7509  noninf_indices.push_back(i);
7510  }
7511 #else
7512  if (std::abs(beta[i]) < 1.0e-8) {
7513  } else {
7514  noninf_indices.push_back(i);
7515  }
7516 #endif
7517  }
7518 
7519  int n = noninf_indices.size();
7520  int c = eigenvectors.c;
7521  int r = eigenvectors.r;
7522  ChebfunMat<std::complex<T> > eigenvectors_temp;
7523  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, 1> eigenvalues_temp;
7524  Eigen::Matrix<int, Eigen::Dynamic, 1> MPorNot_temp;
7525 #ifdef SIS_USE_LAPACK
7526  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, 1> alpha_temp = alpha;
7527  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, 1> beta_temp = beta;
7528 #endif
7529  eigenvectors_temp = eigenvectors;
7530  eigenvalues_temp = eigenvalues;
7531  MPorNot_temp = MPorNot;
7532  eigenvectors.resize(eigenvectors_temp.r,n);
7533  //for (int i = 0; i < n; i++) {
7534  // eigenvectors[i].resize(c, 1);
7535  //}
7536 
7537  eigenvalues.resize(n);
7538  MPorNot.resize(n);
7539 #ifdef SIS_USE_LAPACK
7540  alpha.resize(n);
7541  beta.resize(n);
7542 #endif
7543  int counter = 0;
7544  for (int i = 0; i < n; i++) {
7545  for (int j = 0; j < eigenvectors_temp.r; j++)
7546  eigenvectors(j,i) = eigenvectors_temp(j,noninf_indices[i]);
7547  eigenvalues[i] = eigenvalues_temp[noninf_indices[i]];
7548  MPorNot[i] = MPorNot_temp[noninf_indices[i]];
7549 #ifdef SIS_USE_LAPACK
7550  alpha[i] = alpha_temp[noninf_indices[i]];
7551  beta[i] = beta_temp[noninf_indices[i]];
7552 #endif
7553  }
7554  }
7556  void compute(
7557  const Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> &L_,
7558  const Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> &M_,
7559  Discretize<std::complex<T> > Dis) {
7560  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> masterM2 =
7561  M_,
7562  masterL2 =
7563  L_;
7564  int num_vals = masterM2.rows();
7565  int c = masterM2.rows() / (N + 1);
7566  int total_boundary_conditions = Dis.subs_mat.rows();
7567  MatGen<std::complex<T> > Mat;
7568  int row_counter = 0;
7569  int col_counter = 0;
7570 #ifndef SIS_USE_LAPACK
7571  Eigen::ColPivHouseholderQR<
7572  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> >
7573  solver(masterM2);
7574  Eigen::ComplexEigenSolver<
7575  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> >
7576  eigs;
7577  bool Is_M_Invertible;
7578  if (solver.isInvertible()) {
7579  // std::cout << "M is invertible" << '\n';
7580  // std::cin >> bre;
7581  Is_M_Invertible = true;
7582  eigs.compute(solver.inverse() * masterL2);
7583  // std::cout << "Eigenvalues :\n" << eigs.eigenvalues() << '\n';
7584  } else {
7585  // std::cout << "M is not invertible." << '\n';
7586  // std::cin >> bre;
7587  Is_M_Invertible = false;
7588  solver.compute(masterL2);
7589  eigs.compute(solver.inverse() * masterM2);
7590  // std::cout << "Eigenvalues :\n" << 1 / eigs.eigenvalues().array() <<
7591  // '\n';
7592  }
7593  // std::cin >> bre;
7594  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic>
7595  evecMat_master(c * (N + 1), c * (N + 1));
7596  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, 1> temp_vec;
7597  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> fir_n_mat =
7598  Dis.subs_mat * eigs.eigenvectors();
7599  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> evecMat(
7600  c * (N + 1) + total_boundary_conditions, c * (N + 1));
7601  evecMat << fir_n_mat, eigs.eigenvectors();
7602 
7603  // Unpermute eveMat:
7604 
7605  evecMat = Dis.P * evecMat;
7606 
7607  for (int i = 0; i < c; i++) {
7608  int n = Dis.highest_each_column[i];
7609  Mat.compute(n);
7610  evecMat_master.block(i * (N + 1), 0, N + 1, c * (N + 1)) =
7611  Mat.mats2[n] * evecMat.block(row_counter, 0, N + 1 + n, c * (N + 1));
7612  row_counter += N + 1 + n;
7613  }
7614  std::vector<std::vector<T> > eigenval_trunc_sorter;
7615 
7616  eigenval_trunc_sorter.resize(c * (N + 1));
7617  for (int i = 0; i < c * (N + 1); i++) {
7618  eigenval_trunc_sorter[i].resize(2);
7619  }
7620 
7621  Eigen::Matrix<int, Eigen::Dynamic, 1> MPcount(c * (N + 1));
7622  MPcount.setConstant(0);
7623  std::vector<EigenSorter<T> > sorter;
7624  sorter.resize(c * (N + 1));
7625  for (int i = 0; i < c * (N + 1); i++) {
7626  sorter[i].compute(evecMat_master.block(0, i, c * (N + 1), 1), c);
7627  if (!Is_M_Invertible) {
7628  // If M is not invertible, there will be zero eigenvalues, so that 1/0 =
7629  // inf eigenvalue, remove them.
7630  if (abs(eigs.eigenvalues()[i]) < 1e-11) {
7631  sorter[i].numMp = N + 1;
7632  sorter[i].Mp = false;
7633  sorter[i].minVal = 1e11;
7634  }
7635  }
7636  // sorter[i].compute(evecMat_master.block(0, i, (N + 1), 1));
7637  if (sorter[i].Mp == true) {
7638  MPcount[i] = 1;
7639  }
7640  }
7641  if (num_vals > masterL2.rows()) {
7642  std::cout << "Only " << masterL2.rows()
7643  << " eigenvalues can be calculated."
7644  << "Storing only that many." << '\n';
7645  num_vals = masterL2.rows();
7646  }
7647 
7648  int MPcount_sum = MPcount.sum();
7649  converged = MPcount_sum;
7650  eigenvectors.resize(c,num_vals);
7651  //eigenvectorsMat.resize(num_vals);
7652  //for (int i = 0; i < num_vals; i++) {
7653  // eigenvectorsMat[i].resize(c, 1);
7654  //}
7655  eigenvalues.resize(num_vals);
7656  if (MPcount_sum >= num_vals) {
7657  for (int i = 0; i < c * (N + 1); i++) {
7658  eigenval_trunc_sorter[i][0] = T(sorter[i].numMp);
7659  eigenval_trunc_sorter[i][1] = i;
7660  // std::cout << eigs.eigenvalues()[i] << " " << sorter[i].numMp <<
7661  // "\n"; std::cin > > bre;
7662  }
7663  std::sort(eigenval_trunc_sorter.begin(), eigenval_trunc_sorter.end());
7664  for (int i = 0; i < num_vals; i++) {
7665  if (Is_M_Invertible) {
7666  eigenvalues[i] = eigs.eigenvalues()[int(eigenval_trunc_sorter[i][1])];
7667  } else {
7668  eigenvalues[i] =
7669  1.0 / eigs.eigenvalues()[int(eigenval_trunc_sorter[i][1])];
7670  }
7671  }
7672  for (int j = 0; j < c; j++) {
7673  int n = Dis.highest_each_column[j];
7674 
7675  temp_vec.resize(N + 1 + n, 1);
7676  for (int i = 0; i < num_vals; i++) {
7677  eigenvectors(j,i) = evecMat_master.block(
7678  j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
7679  eigenvectors(j,i).dct_flag = SIS_CHEB_SPACE;
7680  //eigenvectorsMat[i][j] = evecMat_master.block(
7681  // j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
7682  //eigenvectorsMat[i][j].dct_flag = SIS_CHEB_SPACE;
7683  }
7684  }
7685  } else {
7686  std::cout << "Last " << num_vals - MPcount_sum
7687  << " eigenvectors are not resolved to machine precision."
7688  << '\n';
7689  for (int i = 0; i < c * (N + 1); i++) {
7690  eigenval_trunc_sorter[i][0] = T(sorter[i].numMp);
7691  eigenval_trunc_sorter[i][1] = i;
7692  }
7693  std::sort(eigenval_trunc_sorter.begin(), eigenval_trunc_sorter.end());
7694  for (int i = 0; i < MPcount_sum; i++) {
7695  if (Is_M_Invertible) {
7696  eigenvalues[i] = eigs.eigenvalues()[int(eigenval_trunc_sorter[i][1])];
7697  } else {
7698  eigenvalues[i] =
7699  1.0 / eigs.eigenvalues()[int(eigenval_trunc_sorter[i][1])];
7700  }
7701  }
7702  for (int j = 0; j < c; j++) {
7703  int n = Dis.highest_each_column[j];
7704  temp_vec.resize(N + 1 + n, 1);
7705  for (int i = 0; i < MPcount_sum; i++) {
7706  eigenvectors(j,i) = evecMat_master.block(
7707  j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
7708  eigenvectors(j,i).dct_flag = SIS_CHEB_SPACE;
7709  //eigenvectorsMat[i][j] = evecMat_master.block(
7710  // j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
7711  //eigenvectorsMat[i][j].dct_flag = SIS_CHEB_SPACE;
7712  }
7713  }
7714 
7715  std::vector<std::vector<T> > eigenval_trunc_sorter2;
7716  eigenval_trunc_sorter2.resize(c * (N + 1) - MPcount_sum);
7717  for (int i = MPcount_sum; i < c * (N + 1); i++) {
7718  eigenval_trunc_sorter2[i - MPcount_sum].resize(2);
7719  eigenval_trunc_sorter2[i - MPcount_sum][0] =
7720  sorter[int(eigenval_trunc_sorter[i][1])].minVal;
7721  eigenval_trunc_sorter2[i - MPcount_sum][1] =
7722  eigenval_trunc_sorter[i][1];
7723  }
7724  std::sort(eigenval_trunc_sorter2.begin(), eigenval_trunc_sorter2.end());
7725  for (int i = MPcount_sum; i < num_vals; i++) {
7726  if (Is_M_Invertible) {
7727  eigenvalues[i] = eigs.eigenvalues()[int(
7728  eigenval_trunc_sorter2[i - MPcount_sum][1])];
7729  } else {
7730  eigenvalues[i] =
7731  1.0 / eigs.eigenvalues()[int(
7732  eigenval_trunc_sorter2[i - MPcount_sum][1])];
7733  }
7734  }
7735  for (int j = 0; j < c; j++) {
7736  int n = Dis.highest_each_column[j];
7737  Mat.compute(n);
7738  temp_vec.resize(N + 1 + n, 1);
7739  for (int i = MPcount_sum; i < num_vals; i++) {
7740  eigenvectors(j,i) = evecMat_master.block(
7741  j * (N + 1), int(eigenval_trunc_sorter2[i - MPcount_sum][1]),
7742  N + 1, 1);
7743  eigenvectors(j,i).dct_flag = SIS_CHEB_SPACE;
7744  // eigenvectorsMat[i][j] = evecMat_master.block(
7745  // j * (N + 1), int(eigenval_trunc_sorter2[i - MPcount_sum][1]),
7746  // N + 1, 1);
7747  // eigenvectorsMat[i][j].dct_flag = SIS_CHEB_SPACE;
7748  }
7749  }
7750  }
7751 #else
7752  char jobvl = 'N'; // Don't compute left evecs
7753  char jobvr = 'V'; // Compute right evecs
7754  std::complex<double> wkopt; // Eistimate optimum workspace
7755  std::complex<double> *work; // allocate optimum workspace
7756  alpha.resize(masterL2.rows(), 1); // alpha for gen. eig. prob.
7757  beta.resize(masterL2.rows(), 1); // beta for gen. eig. prob.
7758 
7759  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> vl(
7760  masterL2.rows(), masterL2.rows()),
7761  vr(masterL2.rows(), masterL2.rows()),
7762  eigenvalues_temp(masterL2.rows(), 1), alpha_temp(masterL2.rows(), 1),
7763  beta_temp(masterL2.rows(), 1);
7764  // vl : left evecs, vr: right evecs.
7765  int ldL = masterL2.outerStride(); // ld for leading dimension
7766  int ldM = masterM2.outerStride();
7767  int ldvl = vl.outerStride();
7768  int ldvr = vr.outerStride();
7769  int sizeL = masterL2.rows();
7770  int lwork = -1; // set lwork to -1 to estimate workspace.
7771  double rwork[8 * sizeL];
7772 
7773  // call this to estimate workspace
7774  zggev_(&jobvl, &jobvr, &sizeL, masterL2.data(), &ldL, masterM2.data(), &ldM,
7775  alpha_temp.data(), beta_temp.data(), vl.data(), &ldvl, vr.data(),
7776  &ldvr, &wkopt, &lwork, rwork, &info);
7777 
7778  // Now allocate workspace:
7779  lwork = (int)real(wkopt);
7780  work = (std::complex<double> *)malloc(lwork * sizeof(std::complex<double>));
7781 
7782  // Solve eigenvalue problem:
7783  zggev_(&jobvl, &jobvr, &sizeL, masterL2.data(), &ldL, masterM2.data(), &ldM,
7784  alpha_temp.data(), beta_temp.data(), vl.data(), &ldvl, vr.data(),
7785  &ldvr, work, &lwork, rwork, &info);
7786 
7787  // Free workspace.
7788  free((void *)work);
7789 
7790  eigenvalues_temp = alpha_temp.array() / beta_temp.array();
7791 
7792  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic>
7793  evecMat_master(c * (N + 1), c * (N + 1));
7794  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, 1> temp_vec;
7795  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> fir_n_mat =
7796  Dis.subs_mat * vr;
7797  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> evecMat(
7798  c * (N + 1) + total_boundary_conditions, c * (N + 1));
7799  evecMat << fir_n_mat, vr;
7800  // Unpermute eveMat:
7801  evecMat = Dis.P * evecMat;
7802  for (int i = 0; i < c; i++) {
7803  int n = Dis.highest_each_column[i];
7804  Mat.compute(n);
7805  evecMat_master.block(i * (N + 1), 0, N + 1, c * (N + 1)) =
7806  Mat.mats2[n] * evecMat.block(row_counter, 0, N + 1 + n, c * (N + 1));
7807  row_counter += N + 1 + n;
7808  }
7809  std::vector<std::vector<T> > eigenval_trunc_sorter;
7810 
7811  eigenval_trunc_sorter.resize(c * (N + 1));
7812  for (int i = 0; i < c * (N + 1); i++) {
7813  eigenval_trunc_sorter[i].resize(2);
7814  }
7815 
7816  Eigen::Matrix<int, Eigen::Dynamic, 1> MPcount(c * (N + 1));
7817  MPcount.setConstant(0);
7818  std::vector<EigenSorter<T> > sorter;
7819  sorter.resize(c * (N + 1));
7820  for (int i = 0; i < c * (N + 1); i++) {
7821  sorter[i].compute(evecMat_master.block(0, i, c * (N + 1), 1), c);
7822  // sorter[i].compute(evecMat_master.block(0, i, (N + 1), 1));
7823  if (sorter[i].Mp == true) {
7824  MPcount[i] = 1;
7825  }
7826  }
7827  if (num_vals > masterL2.rows()) {
7828  std::cout << "Only " << masterL2.rows()
7829  << " eigenvalues can be calculated."
7830  << "Storing only that many." << '\n';
7831  num_vals = masterL2.rows();
7832  }
7833 
7834  int MPcount_sum = MPcount.sum();
7835  converged = MPcount_sum;
7836 
7837  eigenvectors.resize(c,num_vals);
7838  //eigenvectorsMat.resize(num_vals);
7839  //for (int i = 0; i < num_vals; i++) {
7840  // eigenvectorsMat[i].resize(c, 1);
7841  //}
7842  eigenvalues.resize(num_vals);
7843  beta.resize(num_vals);
7844  alpha.resize(num_vals);
7845  converged = MPcount_sum;
7846  if (MPcount_sum >= num_vals) {
7847  for (int i = 0; i < c * (N + 1); i++) {
7848  eigenval_trunc_sorter[i][0] = T(sorter[i].numMp);
7849  eigenval_trunc_sorter[i][1] = i;
7850  // std::cout << eigs.eigenvalues()[i] << " " << sorter[i].numMp <<
7851  // "\n"; std::cin > > bre;
7852  }
7853  std::sort(eigenval_trunc_sorter.begin(), eigenval_trunc_sorter.end());
7854  for (int i = 0; i < num_vals; i++) {
7855  eigenvalues[i] = eigenvalues_temp(int(eigenval_trunc_sorter[i][1]), 0);
7856  alpha[i] = alpha_temp(int(eigenval_trunc_sorter[i][1]), 0);
7857  beta[i] = beta_temp(int(eigenval_trunc_sorter[i][1]), 0);
7858  }
7859  for (int j = 0; j < c; j++) {
7860  int n = Dis.highest_each_column[j];
7861 
7862  temp_vec.resize(N + 1 + n, 1);
7863  for (int i = 0; i < num_vals; i++) {
7864  eigenvectors(j,i) = evecMat_master.block(
7865  j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
7866  eigenvectors(j,i).dct_flag = SIS_CHEB_SPACE;
7867  //eigenvectorsMat[i][j] = evecMat_master.block(
7868  // j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
7869  //eigenvectorsMat[i][j].dct_flag = SIS_CHEB_SPACE;
7870  }
7871  }
7872  } else {
7873  std::cout << "Last " << num_vals - MPcount_sum
7874  << " eigenvectors are not resolved to machine precision."
7875  << '\n';
7876  for (int i = 0; i < c * (N + 1); i++) {
7877  eigenval_trunc_sorter[i][0] = T(sorter[i].numMp);
7878  eigenval_trunc_sorter[i][1] = i;
7879  }
7880  std::sort(eigenval_trunc_sorter.begin(), eigenval_trunc_sorter.end());
7881  for (int i = 0; i < MPcount_sum; i++) {
7882  eigenvalues[i] = eigenvalues_temp(int(eigenval_trunc_sorter[i][1]), 0);
7883  alpha[i] = alpha_temp(int(eigenval_trunc_sorter[i][1]), 0);
7884  beta[i] = beta_temp(int(eigenval_trunc_sorter[i][1]), 0);
7885  }
7886  for (int j = 0; j < c; j++) {
7887  int n = Dis.highest_each_column[j];
7888  temp_vec.resize(N + 1 + n, 1);
7889  for (int i = 0; i < MPcount_sum; i++) {
7890  eigenvectors(j,i) = evecMat_master.block(
7891  j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
7892  eigenvectors(j,i).dct_flag = SIS_CHEB_SPACE;
7893  //eigenvectorsMat[i][j] = evecMat_master.block(
7894  // j * (N + 1), int(eigenval_trunc_sorter[i][1]), N + 1, 1);
7895  //eigenvectorsMat[i][j].dct_flag = SIS_CHEB_SPACE;
7896  }
7897  }
7898 
7899  std::vector<std::vector<T> > eigenval_trunc_sorter2;
7900  eigenval_trunc_sorter2.resize(c * (N + 1) - MPcount_sum);
7901  for (int i = MPcount_sum; i < c * (N + 1); i++) {
7902  eigenval_trunc_sorter2[i - MPcount_sum].resize(2);
7903  eigenval_trunc_sorter2[i - MPcount_sum][0] =
7904  sorter[int(eigenval_trunc_sorter[i][1])].minVal;
7905  eigenval_trunc_sorter2[i - MPcount_sum][1] =
7906  eigenval_trunc_sorter[i][1];
7907  }
7908  std::sort(eigenval_trunc_sorter2.begin(), eigenval_trunc_sorter2.end());
7909  for (int i = MPcount_sum; i < num_vals; i++) {
7910  eigenvalues[i] = eigenvalues_temp(
7911  int(eigenval_trunc_sorter2[i - MPcount_sum][1]), 0);
7912  alpha[i] =
7913  alpha_temp(int(eigenval_trunc_sorter2[i - MPcount_sum][1]), 0);
7914  beta[i] = beta_temp(int(eigenval_trunc_sorter2[i - MPcount_sum][1]), 0);
7915  }
7916  for (int j = 0; j < c; j++) {
7917  int n = Dis.highest_each_column[j];
7918  Mat.compute(n);
7919  temp_vec.resize(N + 1 + n, 1);
7920  for (int i = MPcount_sum; i < num_vals; i++) {
7921  eigenvectors(j,i) = evecMat_master.block(
7922  j * (N + 1), int(eigenval_trunc_sorter2[i - MPcount_sum][1]),
7923  N + 1, 1);
7924  eigenvectors(j,i).dct_flag = SIS_CHEB_SPACE;
7925  //eigenvectorsMat[i][j] = evecMat_master.block(
7926  // j * (N + 1), int(eigenval_trunc_sorter2[i - MPcount_sum][1]),
7927  // N + 1, 1);
7928  //eigenvectorsMat[i][j].dct_flag = SIS_CHEB_SPACE;
7929  }
7930  }
7931  }
7932 
7933 #endif
7934  //Convert everything to physical space
7935  eigenvectors.c2p();
7936  }
7937 };
7938 
7942 template <class T> class EigenSolver : public GeneralizedEigenSolver<T> {};
7943 
7946 template <class T>
7947 class EigenSolver<std::complex<T> >
7948  : public GeneralizedEigenSolver<std::complex<T> > {};
7949 
7953 template <class T> class MatGen {
7954 private:
7955  int n;
7956 
7957 public:
7958  std::vector<Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> >
7960  std::vector<Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> >
7962  std::vector<Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> >
7964 
7966  MatGen() {}
7968  MatGen(int n_) { compute(n_); }
7969 
7971  void compute(int n_) {
7972  clear();
7973  n = n_;
7974  int bre;
7975  mats.resize(n + 1);
7976  for (int i = 0; i < n + 1; i++) {
7977  mats[i].resize(N + 1 + 2 * n, N + 1 + 2 * n);
7978  mats[i].setConstant( 0.0);
7979  }
7980  mats[0].block(0, 0, N + 1, N + 1) =
7981  Eigen::Matrix<T, Eigen::Dynamic,
7982  Eigen::Dynamic>::Identity(N + 1, N + 1);
7983  for (int i = 1; i < n + 1; i++) {
7984  mats[i].row(0) = 0.5 * mats[i - 1].row(1);
7985  for (int j = 1; j < N + 2 * n; j++) {
7986  mats[i].row(j) =
7987  (mats[i - 1].row(j - 1) - mats[i - 1].row(j + 1)) / (2.0 * j);
7988  }
7989  }
7990  if (n > 0) {
7991  con_mats.resize(n);
7992  for (int i = 0; i < n; i++) {
7993  con_mats[i].resize(n, n);
7994  con_mats[i].setConstant(0.0);
7995  }
7996  // Next we set the matrices for the constants
7997  con_mats[n - 1].setIdentity(n, n);
7998  for (int i = n - 2; i > -1; i--) {
7999  for (int j = 0; j < n; j++) {
8000  con_mats[i].col(j) = diff<T>(con_mats[i + 1].col(j));
8001  }
8002  }
8003  }
8004  mats2.resize(n + 1);
8005  for (int i = 0; i < n + 1; i++) {
8006  mats2[i].resize(N + 1, N + 1 + n);
8007  mats2[i].setConstant( 0.0);
8008  }
8009  for (int i = 0; i < n + 1; i++) {
8010  mats2[i].block(0, 0, N + 1, N + 1) = mats[i].block(0, 0, N + 1, N + 1);
8011  }
8012  for (int i = 0; i < n; i++) {
8013  mats2[i + 1].block(0, N + 1, n, n) = con_mats[i];
8014  }
8015  // std::cout << "In " << __LINE__ << std::endl;
8016  // std::cout << mats[1] << std::endl;
8017  // std::cin >> bre;
8018  }
8019  void clear() {
8020  mats.clear();
8021  mats2.clear();
8022  con_mats.clear();
8023  }
8024 };
8025 
8029 template <class T> class MatGen<std::complex<T> > {
8030 private:
8031  int n;
8032 
8033 public:
8034  std::vector<Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> >
8036  std::vector<Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> >
8038  std::vector<Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> >
8040 
8042  MatGen() {}
8044  MatGen(int n_) { compute(n_); }
8045 
8047  void compute(int n_) {
8048  clear();
8049  n = n_;
8050  int bre;
8051  mats.resize(n + 1);
8052  for (int i = 0; i < n + 1; i++) {
8053  mats[i].resize(N + 1 + 2 * n, N + 1 + 2 * n);
8054  mats[i].setConstant(std::complex<T>(0.0, 0.0));
8055  }
8056  mats[0].block(0, 0, N + 1, N + 1) =
8057  Eigen::Matrix<std::complex<T>, Eigen::Dynamic,
8058  Eigen::Dynamic>::Identity(N + 1, N + 1);
8059  for (int i = 1; i < n + 1; i++) {
8060  mats[i].row(0) = 0.5 * mats[i - 1].row(1);
8061  for (int j = 1; j < N + 2 * n; j++) {
8062  mats[i].row(j) =
8063  (mats[i - 1].row(j - 1) - mats[i - 1].row(j + 1)) / (2.0 * j);
8064  }
8065  }
8066 
8067  if (n > 0) {
8068  con_mats.resize(n);
8069  for (int i = 0; i < n; i++) {
8070  con_mats[i].resize(n, n);
8071  con_mats[i].setConstant(std::complex<T>(0.0, 0.0));
8072  }
8073  // Next we set the matrices for the constants
8074  con_mats[n - 1].setIdentity(n, n);
8075  for (int i = n - 2; i > -1; i--) {
8076  for (int j = 0; j < n; j++) {
8077  con_mats[i].col(j) = diff<std::complex<T> >(con_mats[i + 1].col(j));
8078  }
8079  }
8080  }
8081  mats2.resize(n + 1);
8082  for (int i = 0; i < n + 1; i++) {
8083  mats2[i].resize(N + 1, N + 1 + n);
8084  mats2[i].setConstant(std::complex<T>(0.0, 0.0));
8085  }
8086  for (int i = 0; i < n + 1; i++) {
8087  mats2[i].block(0, 0, N + 1, N + 1) = mats[i].block(0, 0, N + 1, N + 1);
8088  }
8089  for (int i = 0; i < n; i++) {
8090  mats2[i + 1].block(0, N + 1, n, n) = con_mats[i];
8091  }
8092  //std::cout << "In " << __LINE__ << std::endl;
8093  //std::cout << mats[0] << std::endl;
8094  //std::cin >> bre;
8095  }
8096  void clear() {
8097  mats.clear();
8098  mats2.clear();
8099  con_mats.clear();
8100  }
8101 };
8102 
8105 template <class T> class LinopMat {
8106  friend class EigenSolver<T>;
8107  friend class GeneralizedEigenSolver<T>;
8108  friend class GeneralizedEigenSolver<std::complex<T> >;
8109  friend class LinopMat<std::complex<T> >;
8110 
8111 private:
8112  int count;
8113 
8114 public:
8116  int r;
8118  int c;
8121  std::valarray<Linop<T> > LinopVec;
8122  int countc;
8123  int countr;
8141 
8143  LinopMat() : LinopVec(), r(0), c(0), count(0) {}
8144 
8146  LinopMat(int r_, int c_) {
8147  r = r_;
8148  c = c_;
8149  count = 0;
8150  LinopVec.resize(r * c);
8151  };
8152 
8154  LinopMat(const LinopMat<T> &in) {
8155  r = in.r;
8156  c = in.c;
8157  resize(r, c);
8158  count = in.count;
8159  for (int i = 0; i < r * c; i++) {
8160  LinopVec[i] = in.LinopVec[i];
8161  }
8162  }
8164  void operator=(const LinopMat &in) {
8165  // std::cout << "in copier" << '\n' << std::flush;
8166  r = in.r;
8167  c = in.c;
8168  resize(r, c);
8169  count = in.count;
8170  for (int i = 0; i < r * c; i++) {
8171  LinopVec[i] = in.LinopVec[i];
8172  }
8173  }
8177  int bre;
8178  LinopVec[count] = b;
8179  count++;
8180  return *this;
8181  };
8182 
8186  Linop<T> &temp = LinopVec[i];
8187  return temp;
8188  };
8189 
8193  Linop<T> &operator()(int i, int j) { return LinopVec[j + c * i]; };
8194 
8197  LinopMat<T> &operator<<(Eigen::Array<T, Eigen::Dynamic, 1> b) {
8198  int bre;
8199  LinopVec[count] = b;
8200  count++;
8201  return *this;
8202  };
8203 
8205  LinopMat<T> &operator<<(Linop<T> b) {
8206  int bre;
8207  LinopVec[count] = b;
8208  count++;
8209  return *this;
8210  };
8211 
8214  void resize(int r_, int c_) {
8215  r = r_;
8216  c = c_;
8217  LinopVec.resize(r * c);
8218  count = 0;
8219  }
8220 
8224  LinopVec[count] = b;
8225  count++;
8226  return *this;
8227  }
8230  LinopMat<T> &operator,(Eigen::Array<T, Eigen::Dynamic, 1> b) {
8231  LinopVec[count] = b;
8232  count++;
8233  return *this;
8234  }
8238  LinopVec[count] = b;
8239  count++;
8240  return *this;
8241  }
8242 
8246 
8251  LinopMat<T> &operator<<(LinopMat<T> b) {
8252  setConstant(0.0);
8253  go_to_next_row = false;
8254  int bre;
8255  if (b.c > c || b.r > r) {
8256  std::cout << "Incompatible shape to input LinopMat."
8257  << " In" << __LINE__ << '\n';
8258  exit(1);
8259  }
8260  for (int i = 0; i < b.r; i++) {
8261  for (int j = 0; j < b.c; j++) {
8262  operator()(i, j) = b(i, j);
8263  }
8264  }
8265  countr = 0;
8266  countc = b.c;
8267  if (countc == c) {
8268  go_to_next_row = true;
8269  countr += b.r;
8270  }
8271  // if (ind == 2) {
8272  // std::cout << "countc: " << countc << '\n';
8273  // std::cout << "countr: " << countr << '\n';
8274  // std::cout << "count: " << count << '\n';
8275  // std::cout << "go_to_next_row: " << go_to_next_row << '\n';
8276  // std::cin >> bre;
8277  //}
8278  count++;
8279  return *this;
8280  };
8281 
8283  int bre;
8284  if (!go_to_next_row) {
8285  // std::cout << "in if" << '\n';
8286  for (int i = 0; i < b.r; i++) {
8287  for (int j = 0; j < b.c; j++) {
8288  operator()(countr + i, countc + j) = b(i, j);
8289  // std::cout << "(" << countr + i<< "," << countc + j << ")" << '\n';
8290  }
8291  }
8292  countc += b.c;
8293  if (countc == c) {
8294  go_to_next_row = true;
8295  countr += b.r;
8296  countc = 0;
8297  }
8298  } else {
8299  // std::cout << "in else" << '\n';
8300  go_to_next_row = false;
8301  for (int i = 0; i < b.r; i++) {
8302  for (int j = 0; j < b.c; j++) {
8303  operator()(countr + i, countc + j) = b(i, j);
8304  // std::cout << "(" << countr + i<< "," << countc + j << ")" << '\n';
8305  }
8306  }
8307  countc += b.c;
8308  if (countc == c) {
8309  go_to_next_row = true;
8310  countr += b.r;
8311  countc = 0;
8312  }
8313  }
8314  // if (ind == 2) {
8315  // std::cout << "countc: " << countc << '\n';
8316  // std::cout << "countr: " << countr << '\n';
8317  // std::cout << "count: " << count << '\n';
8318  // std::cout << "go_to_next_row: " << go_to_next_row << '\n';
8319  // std::cin >> bre;
8320  // }
8321  count++;
8322  return *this;
8323  };
8324 
8326  LinopMat<T> temp;
8327  temp.resize(r, c);
8328  for (int i = 0; i < r; i++) {
8329  for (int j = 0; j < c; j++) {
8330  temp(i, j) = conj(operator()(j, i));
8331  }
8332  }
8333  return temp;
8334  }
8335 
8337  void setConstant(T in) {
8338  for (int i = 0; i < r; i++) {
8339  for (int j = 0; j < c; j++) {
8340  operator()(i, j) = in;
8341  }
8342  }
8343  };
8344 
8346  void setIdentity() {
8347  if (r != c) {
8348  std::cout << "setIdentity() is only for square LinopMats" << '\n';
8349  exit(1);
8350  }
8351  setConstant(0.0);
8352  for (int i = 0; i < r; i++) {
8353  operator()(i, i) = 1.0;
8354  }
8355  };
8356 
8357  // LinopMat<T> operator-(LinopMat<T> in) {
8358  // LinopMat<T> temp(in.r, in.c);
8359  // for (int i = 0; i < in.r; i++) {
8360  // for (int j = 0; j < in.c; j++) {
8361  // temp(i, j) = -in(i, j);
8362  // }
8363  // }
8364  // return temp;//
8365  // }
8366  //~LinopMat(){
8367  // LinopVec.~valarray();
8368  //}
8369 };
8370 
8373 template <class T> class LinopMat<std::complex<T> > {
8374  friend class EigenSolver<std::complex<T> >;
8375  friend class GeneralizedEigenSolver<std::complex<T> >;
8376  friend class BcMat<std::complex<T> >;
8377 
8378 private:
8379  int count;
8380 
8381 public:
8383  int r;
8385  int c;
8388  std::valarray<Linop<std::complex<T> > > LinopVec;
8389 
8390  int countc;
8391  int countr;
8393 
8395  LinopMat() : LinopVec(), r(0), c(0), count(0) {}
8396 
8398  LinopMat(int r_, int c_) {
8399  r = r_;
8400  c = c_;
8401  count = 0;
8402  LinopVec.resize(r * c);
8403  };
8404 
8406  LinopMat(const LinopMat<std::complex<T> > &in) {
8407  r = in.r;
8408  c = in.c;
8409  resize(r, c);
8410  count = in.count;
8411  for (int i = 0; i < r * c; i++) {
8412  LinopVec[i] = in.LinopVec[i];
8413  }
8414  }
8415 
8417  LinopMat(const LinopMat<T> &in) {
8418  r = in.r;
8419  c = in.c;
8420  resize(r, c);
8421  count = in.count;
8422  for (int i = 0; i < r * c; i++) {
8423  LinopVec[i] = in.LinopVec[i];
8424  }
8425  }
8427  void operator=(const LinopMat<std::complex<T> > &in) {
8428  r = in.r;
8429  c = in.c;
8430  resize(r, c);
8431  count = in.count;
8432  for (int i = 0; i < r * c; i++) {
8433  LinopVec[i] = in.LinopVec[i];
8434  }
8435  }
8436 
8438  void operator=(const LinopMat<T> &in) {
8439  r = in.r;
8440  c = in.c;
8441  resize(r, c);
8442  count = in.count;
8443  for (int i = 0; i < r * c; i++) {
8444  LinopVec[i] = in.LinopVec[i];
8445  }
8446  }
8449  LinopMat<std::complex<T> > &operator<<(std::complex<T> b) {
8450  int bre;
8451  LinopVec[count] = b;
8452  count++;
8453  return *this;
8454  };
8458  int bre;
8459  LinopVec[count] = b;
8460  count++;
8461  return *this;
8462  };
8463 
8466  Linop<std::complex<T> > &operator[](int i) { return LinopVec[i]; };
8467 
8472  // std::cout << ind++ << '\n';
8473  return LinopVec[j + c * i];
8474  };
8475 
8478  ChebfunMat<std::complex<T> > out(r, in.c);
8479  if (c != in.r){
8480  std::cout << "Incompatible shapes in applying LinopMat to ChebfunMat."
8481  << "In line "<< __LINE__ <<". Exiting "<< '\n';
8482  exit(1);
8483  }
8484  for (int i = 0 ; i < out.r; i++){
8485  for (int j = 0; j < out.c; j++){
8486  out(i,j).v = std::complex<T>(0.0,0.0);
8487  }
8488  }
8489  for (int i = 0; i < r; i++) {
8490  for (int j = 0; j < in.c; j++) {
8491  for (int k = 0; k < c; k++) {
8492  out(i, j) = out(i, j) + (operator()(i, k) (in(k, j)));
8493  }
8494  }
8495  }
8496  return out;
8497  };
8498 
8502  operator<<(Eigen::Array<std::complex<T>, Eigen::Dynamic, 1> b) {
8503  int bre;
8504  LinopVec[count] = b;
8505  count++;
8506  return *this;
8507  };
8508 
8511  LinopMat<std::complex<T> > &operator<<(std::valarray<std::complex<T> > b) {
8512  int bre;
8513  LinopVec[count] = b;
8514  count++;
8515  return *this;
8516  };
8519  LinopMat<std::complex<T> > &operator<<(std::valarray<T> b) {
8520  int bre;
8521  LinopVec[count] = b;
8522  count++;
8523  return *this;
8524  };
8525 
8527  LinopMat<std::complex<T> > &operator<<(Linop<std::complex<T> > b) {
8528  int bre;
8529  LinopVec[count] = b;
8530  count++;
8531  return *this;
8532  };
8533 
8535  LinopMat<std::complex<T> > &operator<<(Linop<T> b) {
8536  int bre;
8537  LinopVec[count] = b;
8538  count++;
8539  return *this;
8540  };
8541 
8544  void resize(int r_, int c_) {
8545  r = r_;
8546  c = c_;
8547  LinopVec.resize(r * c);
8548  count = 0;
8549  }
8550 
8553  LinopMat<std::complex<T> > &operator,(std::complex<T> b) {
8554  LinopVec[count] = b;
8555  count++;
8556  return *this;
8557  }
8558 
8562  LinopVec[count] = b;
8563  count++;
8564  return *this;
8565  }
8566 
8570  Eigen::Array<std::complex<T>, Eigen::Dynamic, 1> b) {
8571  LinopVec[count] = b;
8572  count++;
8573  return *this;
8574  }
8575 
8578  LinopMat<std::complex<T> > &operator,(std::valarray<std::complex<T> > b) {
8579  LinopVec[count] = b;
8580  count++;
8581  return *this;
8582  }
8585  LinopMat<std::complex<T> > &operator,(std::valarray<T> b) {
8586  LinopVec[count] = b;
8587  count++;
8588  return *this;
8589  }
8590 
8593  LinopMat<std::complex<T> > &operator,(Linop<std::complex<T> > b) {
8594  LinopVec[count] = b;
8595  count++;
8596  return *this;
8597  }
8598 
8602  LinopVec[count] = b;
8603  count++;
8604  return *this;
8605  }
8606 
8608  void setConstant(T in) {
8609  for (int i = 0; i < r; i++) {
8610  for (int j = 0; j < c; j++) {
8611  operator()(i, j) = in;
8612  }
8613  }
8614  };
8615 
8617  void setConstant(std::complex<T> in) {
8618  for (int i = 0; i < r; i++) {
8619  for (int j = 0; j < c; j++) {
8620  operator()(i, j) = in;
8621  }
8622  }
8623  };
8624 
8626  void setIdentity() {
8627  if (r != c) {
8628  std::cout << "setIdentity() is only for square LinopMats" << '\n';
8629  exit(1);
8630  }
8631  setConstant(0.0);
8632  for (int i = 0; i < r; i++) {
8633  operator()(i, i) = 1.0;
8634  }
8635  };
8640  LinopMat<std::complex<T> > &operator<<(LinopMat<std::complex<T> > b) {
8641  setConstant(0.0);
8642  go_to_next_row = false;
8643  int bre;
8644  if (b.c > c || b.r > r) {
8645  std::cout << "Incompatible shape to input LinopMat."
8646  << " In" << __LINE__ << '\n';
8647  exit(1);
8648  }
8649  for (int i = 0; i < b.r; i++) {
8650  for (int j = 0; j < b.c; j++) {
8651  operator()(i, j) = b(i, j);
8652  }
8653  }
8654  countr = 0;
8655  countc = b.c;
8656  if (countc == c) {
8657  go_to_next_row = true;
8658  countr += b.r;
8659  countc = 0;
8660  }
8661  // if (ind == 2) {
8662  // std::cout << "countc: " << countc << '\n';
8663  // std::cout << "countr: " << countr << '\n';
8664  // std::cout << "count: " << count << '\n';
8665  // std::cout << "go_to_next_row: " << go_to_next_row << '\n';
8666  // std::cin >> bre;
8667  //}
8668  count++;
8669  return *this;
8670  };
8671 
8672  LinopMat<std::complex<T> > &operator,(LinopMat<std::complex<T> > b) {
8673  int bre;
8674  if (!go_to_next_row) {
8675  // std::cout << "in if" << '\n';
8676  for (int i = 0; i < b.r; i++) {
8677  for (int j = 0; j < b.c; j++) {
8678  operator()(countr + i, countc + j) = b(i, j);
8679  // std::cout << "(" << countr + i<< "," << countc + j << ")" << '\n';
8680  }
8681  }
8682  countc += b.c;
8683  if (countc == c) {
8684  go_to_next_row = true;
8685  countr += b.r;
8686  countc = 0;
8687  }
8688  } else {
8689  // std::cout << "in else" << '\n';
8690  go_to_next_row = false;
8691  for (int i = 0; i < b.r; i++) {
8692  for (int j = 0; j < b.c; j++) {
8693  operator()(countr + i, countc + j) = b(i, j);
8694  // std::cout << "(" << countr + i<< "," << countc + j << ")" <<
8695  // '\n';
8696  }
8697  }
8698  countc += b.c;
8699  if (countc == c) {
8700  go_to_next_row = true;
8701  countr += b.r;
8702  countc = 0;
8703  }
8704  }
8705  // if (ind == 2) {
8706  // std::cout << "countc: " << countc << '\n';
8707  // std::cout << "countr: " << countr << '\n';
8708  // std::cout << "count: " << count << '\n';
8709  // std::cout << "go_to_next_row: " << go_to_next_row << '\n';
8710  // std::cin >> bre;
8711  //}
8712  count++;
8713  return *this;
8714  };
8715 
8716  LinopMat<std::complex<T> > &operator<<(LinopMat<T> b) {
8717  setConstant(0.0);
8718  go_to_next_row = false;
8719  int bre;
8720  if (b.c > c || b.r > r) {
8721  std::cout << "Incompatible shape to input LinopMat."
8722  << " In" << __LINE__ << '\n';
8723  exit(1);
8724  }
8725  for (int i = 0; i < b.r; i++) {
8726  for (int j = 0; j < b.c; j++) {
8727  operator()(i, j) = b(i, j);
8728  }
8729  }
8730  countr = 0;
8731  countc = b.c;
8732  if (countc == c) {
8733  go_to_next_row = true;
8734  countr += b.r;
8735  }
8736  // if (ind == 2) {
8737  // std::cout << "countc: " << countc << '\n';
8738  // std::cout << "countr: " << countr << '\n';
8739  // std::cout << "count: " << count << '\n';
8740  // std::cout << "go_to_next_row: " << go_to_next_row << '\n';
8741  // std::cin >> bre;
8742  //}
8743  count++;
8744  return *this;
8745  };
8746 
8748  int bre;
8749  if (!go_to_next_row) {
8750  // std::cout << "in if" << '\n';
8751  for (int i = 0; i < b.r; i++) {
8752  for (int j = 0; j < b.c; j++) {
8753  operator()(countr + i, countc + j) = b(i, j);
8754  // std::cout << "(" << countr + i<< "," << countc + j << ")" << '\n';
8755  }
8756  }
8757  countc += b.c;
8758  if (countc == c) {
8759  go_to_next_row = true;
8760  countr += b.r;
8761  countc = 0;
8762  }
8763  } else {
8764  // std::cout << "in else" << '\n';
8765  go_to_next_row = false;
8766  for (int i = 0; i < b.r; i++) {
8767  for (int j = 0; j < b.c; j++) {
8768  operator()(countr + i, countc + j) = b(i, j);
8769  // std::cout << "(" << countr + i<< "," << countc + j << ")" << '\n';
8770  }
8771  }
8772  countc += b.c;
8773  if (countc == c) {
8774  go_to_next_row = true;
8775  countr += b.r;
8776  countc = 0;
8777  }
8778  }
8779  // if (ind == 2) {
8780  // std::cout << "countc: " << countc << '\n';
8781  // std::cout << "countr: " << countr << '\n';
8782  // std::cout << "count: " << count << '\n';
8783  // std::cout << "go_to_next_row: " << go_to_next_row << '\n';
8784  // std::cin >> bre;
8785  // }
8786  count++;
8787  return *this;
8788  };
8789 
8791  LinopMat<std::complex<T> > temp;
8792  temp.resize(r, c);
8793  for (int i = 0; i < r; i++) {
8794  for (int j = 0; j < c; j++) {
8795  temp(i, j) = conj(operator()(j, i));
8796  }
8797  }
8798  return temp;
8799  }
8800 
8801  // LinopMat<std::complex<T> > operator-(LinopMat<std::complex<T> > in) {
8802  // LinopMat<std::complex<T> > temp(in.r, in.c);
8803  // for (int i = 0; i < in.r; i++) {
8804  // for (int j = 0; j < in.c; j++) {
8805  // temp(i, j) = -in(i, j);
8806  // }
8807  // }
8808  // return temp;
8809  // }
8810  //~LinopMat(){
8811  // LinopVec.~valarray();
8812  //}
8813 };
8814 
8817 template <class T> class BcMat {
8818  friend class EigenSolver<T>;
8819  friend class GeneralizedEigenSolver<T>;
8820  friend class GeneralizedEigenSolver<std::complex<T> >;
8821  friend class LinopMat<std::complex<T> >;
8823  friend class SingularValueDecomposition<std::complex<T> >;
8824  friend class Discretize<T>;
8825  friend class Discretize<std::complex<T> >;
8826 
8827 private:
8828  int m, n;
8829 
8830 public:
8832  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> eval;
8833  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> vals;
8834 
8835  BcMat() {
8836  m = 0;
8837  n = 0;
8838  }
8839  BcMat(int m_, int n_) {
8840  m = m_;
8841  n = n_;
8842  eval.resize(m_, n_);
8843  vals.resize(m_, 1);
8844  L.resize(m, n);
8845  eval.setConstant(0.0);
8846  vals.setConstant(0.0);
8847  }
8848  void resize(int m_, int n_) {
8849  m = m_;
8850  n = n_;
8851  eval.resize(m_, n_);
8852  vals.resize(m_, 1);
8853  eval.setConstant(0.0);
8854  vals.setConstant(0.0);
8855  L.resize(m, n);
8856  }
8857  void operator=(const BcMat<T> &in) {
8858  m = in.m;
8859  n = in.n;
8860  L = in.L;
8861  eval = in.eval;
8862  vals = in.vals;
8863  }
8864 
8865  int rows() {
8866  return m;
8867  }
8868 
8869  int cols() {
8870  return n;
8871  }
8872 
8878  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> operator()(int i, int j,
8879  int ord) {
8880  int n = ord;
8881  Eigen::Matrix<T, 1, Eigen::Dynamic> vals(1, N + 1 + 2 * n), valcons(n);
8882  for (int k = 0; k < N + 1 + 2 * n; k++) {
8883  vals[k] = cos(k * acos(eval(i, j)));
8884  }
8885  for (int k = 0; k < n; k++) {
8886  valcons[k] = cos(k * acos(eval(i, j)));
8887  }
8888  vals[0] *= 0.5;
8889  valcons[0] *= 0.5;
8890  MatGen<T> Mat;
8891  Mat.compute(n);
8892  Eigen::Matrix<T, 1, Eigen::Dynamic> out(1, N + 1 + n);
8893  out.setConstant(0.0);
8894  int diffn = n - L(i, j).n;
8895  for (int k = 0; k < L(i, j).n + 1; k++) {
8896  if (L(i, j).NCC == 0) {
8897 
8898  out.block(0, 0, 1, N + 1) +=
8899  (L(i, j).coef[k] * vals * Mat.mats[k + diffn]).head(N + 1);
8900  if (k + diffn - 1 > -1) {
8901  out.block(0, N + 1, 1, n) +=
8902  (L(i, j).coef[k] * valcons * Mat.con_mats[k + diffn - 1]);
8903  }
8904  } else {
8905  out.block(0, 0, 1, N + 1) +=
8906  (L(i, j).coefFun[k](eval(i, j)) * vals * Mat.mats[k + diffn])
8907  .head(N + 1);
8908  if (k + diffn - 1 > -1) {
8909  out.block(0, N + 1, 1, n) += (L(i, j).coefFun[k](eval(i, j)) *
8910  valcons * Mat.con_mats[k + diffn - 1]);
8911  }
8912  }
8913  }
8914  return out;
8915  }
8916 };
8917 
8918 template <class T> class BcMat<std::complex<T> > {
8919  friend class EigenSolver<T>;
8920  friend class GeneralizedEigenSolver<T>;
8921  friend class GeneralizedEigenSolver<std::complex<T> >;
8922  friend class LinopMat<std::complex<T> >;
8924  friend class SingularValueDecomposition<std::complex<T> >;
8925  friend class Discretize<T>;
8926  friend class Discretize<std::complex<T> >;
8927 
8928 private:
8929  int m, n;
8930 
8931 public:
8932  LinopMat<std::complex<T> > L;
8933  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> eval;
8934  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> vals;
8935  BcMat() {
8936  m = 0;
8937  n = 0;
8938  }
8939  BcMat(int m_, int n_) {
8940  m = m_;
8941  n = n_;
8942  eval.resize(m_, n_);
8943  vals.resize(m_, 1);
8944  L.resize(m, n);
8945  // eval.setConstant(0.0);
8946  // vals.setConstant(0.0);
8947  }
8948  void resize(int m_, int n_) {
8949  m = m_;
8950  n = n_;
8951  eval.resize(m_, n_);
8952  vals.resize(m_, 1);
8953 // eval.setConstant(0.0);
8954 // vals.setConstant(0.0);
8955  L.resize(m, n);
8956  }
8957  void operator=(const BcMat<std::complex<T> > &in) {
8958  m = in.m;
8959  n = in.n;
8960  L = in.L;
8961  eval = in.eval;
8962  vals = in.vals;
8963  }
8964 
8965  int rows() {
8966  return m;
8967  }
8968 
8969  int cols() {
8970  return n;
8971  }
8972 
8978  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic>
8979  operator()(int i, int j, int ord) {
8980  int n = ord;
8981  int bre;
8982  Eigen::Matrix<T, 1, Eigen::Dynamic> vals(1, N + 1 + 2 * n), valcons(n);
8983  for (int k = 0; k < N + 1 + 2 * n; k++) {
8984  vals[k] = cos(T(k) * acos(eval(i, j)));
8985  }
8986  for (int k = 0; k < n; k++) {
8987  valcons[k] = cos(T(k) * acos(eval(i, j)));
8988  }
8989 
8990  vals[0] *= 0.5;
8991  if (n > 0) {
8992  valcons[0] *= 0.5;
8993  }
8994 
8995  //std::cout << "in " << __LINE__ << std::endl << vals;
8996  //std::cout << "in " << __LINE__ << std::endl << valcons;
8997  //exit(1);
8998  MatGen<T> Mat;
8999  Mat.compute(n);
9000  Eigen::Matrix<std::complex<T>, 1, Eigen::Dynamic> out(1, N + 1 + n);
9001  out.setConstant(0.0);
9002  int diffn = n - L(i, j).n;
9003  for (int k = 0; k < L(i, j).n + 1; k++) {
9004  if (L(i, j).NCC == 0) {
9005  // std::cout << "Im here;;;" << '\n';
9006  // if (ind == 2){
9007  // std::cout << "L("<<i<<", "<<j<<").coef["<<k<<"]:"<<L(i, j).coef[k] <<
9008  // '\n'; std::cout << "size of vals: " << vals.size() << '\n'; std::cout
9009  // << "Mat.mats["<< k + diffn << "]: "<< size(Mat.mats[k + diffn]) <<
9010  // '\n';
9011  //}
9012  out.block(0, 0, 1, N + 1) +=
9013  (L(i, j).coef[k] * vals * Mat.mats[k + diffn]).head(N + 1);
9014  //std::cout << Mat.mats[k + diffn] << std::endl;
9015  //std::cin >> bre;
9016 
9017  if (k + diffn - 1 > -1) {
9018  out.block(0, N + 1, 1, n) +=
9019  (L(i, j).coef[k] * valcons * Mat.con_mats[k + diffn - 1]);
9020  }
9021  } else {
9022  out.block(0, 0, 1, N + 1) +=
9023  (L(i, j).coefFun[k](eval(i, j)) * vals * Mat.mats[k + diffn])
9024  .head(N + 1);
9025  if (k + diffn - 1 > -1) {
9026  out.block(0, N + 1, 1, n) += (L(i, j).coefFun[k](eval(i, j)) *
9027  valcons * Mat.con_mats[k + diffn - 1]);
9028  }
9029  }
9030  }
9031  return out;
9032  }
9033 };
9034 
9037 template <class T> class nChoosek {
9038 public:
9040 
9041  T operator()(int n, int k) { return T(nCk_(n, k)); }
9042 
9043  int nCk_(int n, int k) {
9044  if (k == 0 || k == n) {
9045  return 1;
9046  } else if (n < k) {
9047  return 0;
9048  }
9049  return nCk_(n - 1, k - 1) + nCk_(n - 1, k);
9050  }
9051 };
9052 
9055 template <class T> class nChoosek<std::complex<T> > {
9056 public:
9058 
9059  T operator()(int n, int k) { return T(nCk_(n, k)); }
9060 
9061  int nCk_(int n, int k) {
9062  if (k == 0 || k == n) {
9063  return 1;
9064  } else if (n < k) {
9065  return 0;
9066  }
9067  return nCk_(n - 1, k - 1) + nCk_(n - 1, k);
9068  }
9069 };
9070 
9074 template <class T>
9075 Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>
9076 feval2D(std::valarray<ChebfunMat<T> > Amat, int r, int c, T a) {
9077 
9078  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> outmat(r * Amat[0].r,
9079  r * Amat[0].r);
9080  outmat.setConstant(0.0);
9081  int bre;
9082  for (int i = 0; i < r; i++) {
9083  for (int j = 0; j < c; j++) {
9084  for (int l = 0; l < Amat[i * c + j].r; l++) {
9085  for (int m = 0; m < Amat[i * c + j].c; m++) {
9086  outmat(i * Amat[i * c + j].r + l, j * Amat[i * c + j].c + m) =
9087  Amat[i * c + j](l, m)(a);
9088  // std::cout << "(" << i << "," << j << "," << l << "," << m << ")"
9089  // << '\n';
9090  // std::cout << "outmat: \n" << outmat << '\n';
9091  // std::cin >> bre;
9092  }
9093  }
9094  }
9095  }
9096 
9097  return outmat;
9098 };
9099 
9103 template <class T>
9104 Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic>
9105 feval2D(std::valarray<ChebfunMat<std::complex<T> > > Amat, int r, int c, T a) {
9106 
9107  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> outmat(
9108  r * Amat[0].r, r * Amat[0].r);
9109  outmat.setConstant(0.0);
9110  int bre;
9111  for (int i = 0; i < r; i++) {
9112  for (int j = 0; j < c; j++) {
9113  for (int l = 0; l < Amat[i * c + j].r; l++) {
9114  for (int m = 0; m < Amat[i * c + j].c; m++) {
9115  outmat(i * Amat[i * c + j].r + l, j * Amat[i * c + j].c + m) =
9116  Amat[i * c + j](l, m)(a);
9117  // std::cout << "(" << i << "," << j << "," << l << "," << m << ")"
9118  // << '\n';
9119  // std::cout << "outmat: \n" << outmat << '\n';
9120  // std::cin >> bre;
9121  }
9122  }
9123  }
9124  }
9125  return outmat;
9126 };
9133 template <class T>
9134 class SingularValueDecomposition : public GeneralizedEigenSolver<T> {
9135 private:
9136 public:
9139  void compute(const LinopMat<T> &A_, const BcMat<T> &Lbc_,
9140  const BcMat<T> &Rbc_, int num_vals) {
9141  int bre;
9142  LinopMat<T> A = A_;
9143  BcMat<T> Lbc = Lbc_;
9144  BcMat<T> Rbc = Rbc_;
9145  LinopMat<T> Astar = Adjoint(A);
9146  BcMat<T> Bc_adjoint = AdjointBc_analytical(A, Lbc_, Rbc_);
9147 
9148  // Define the composite operator:
9149  LinopMat<T> Acomp(2 * A.r, 2 * A.r);
9150  LinopMat<T> Z(A.r, A.r);
9151  Z.setConstant(0.0);
9152  Acomp << A, Z, //
9153  Z, Astar;
9154  // for (int i = 0; i < Acomp.r; i ++){
9155  // for (int j = 0; j < Acomp.c;j ++){
9156  // if(Acomp(i,j).NCC == 0){
9157  // std::cout << "("<< i <<"," << j << "):" << '\n';
9158  // std::cout << Acomp(i,j).coef << '\n';
9159  // std::cin >> bre;
9160  // } else {
9161  // for (int k = 0; k < Acomp(i,j).n + 1; k ++){
9162  // std::cout << "("<< i <<"," << j << "," << k << "):" << '\n';
9163  // std::cout << Acomp(i,j).coefFun[k] << '\n';
9164  // std::cin >> bre;
9165  // }
9166  // }
9167  // }
9168  // }
9169 
9170  // std::cout << "Bc_adjoint: \n" << '\n';
9171  // for (int i = 0; i < Bc_adjoint.m; i++) {
9172  // for (int j = 0; j < Bc_adjoint.n; j++) {
9173  // std::cout << "(" << i << "," << j << ")" << '\n';
9174  // std::cout << Bc_adjoint.L(i, j).coef << '\n';
9175  // }
9176  //}
9177  // std::cout << "Bc_adjoint.eval: \n" << Bc_adjoint.eval << '\n';
9178  // std::cin >> bre;
9179  // Form composite boundary conditions:
9180  BcMat<T> BcComp(Lbc.m + Rbc.m + Bc_adjoint.m, 2 * A.r);
9181  LinopMat<T> Z1(Lbc.m, Astar.c), Z2(Rbc.m, Astar.c), Z3(Bc_adjoint.m, A.c);
9182  Z1.setConstant(0.0);
9183  Z2.setConstant(0.0);
9184  Z3.setConstant(0.0);
9185  ind = 2;
9186 
9187  for (int i = 0; i < Lbc.m; i++) {
9188  for (int j = 0; j < Lbc.n; j++) {
9189  Lbc.eval(i, j) = -1.0;
9190  }
9191  }
9192  for (int i = 0; i < Rbc.m; i++) {
9193  for (int j = 0; j < Rbc.n; j++) {
9194  Rbc.eval(i, j) = 1.0;
9195  }
9196  }
9197  // std::cout << "("<< Lbc.L.r << "," ")"<< << '\n';
9198  // std::cout << "Entering ::::::::::::::" << '\n';
9199  // std::cout << "BcComp: " << "(" << BcComp.m <<","<< BcComp.n<< ")" <<
9200  // '\n'; std::cout << "Lbc: " << "(" << Lbc.m <<","<< Lbc.n<< ")" << '\n';
9201  // std::cout << "Z1: " << "(" << Z1.r <<","<< Z1.c<< ")" << '\n';
9202  // std::cout << "Rbc: " << "(" << Rbc.m <<","<< Rbc.n<< ")" << '\n';
9203  // std::cout << "Z2: " << "(" << Z2.r <<","<< Z2.c<< ")" << '\n';
9204  // std::cout << "Z3: " << "(" << Z3.r <<","<< Z3.c<< ")" << '\n';
9205  // std::cout << "Bc_adjoint: " << "(" << Bc_adjoint.m <<","<< Bc_adjoint.n<<
9206  // ")" << '\n';
9207  BcComp.L << Lbc.L, Z1, //
9208  Rbc.L, Z2, //
9209  Z3, Bc_adjoint.L;
9210 
9211  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> z1(Lbc.m, Astar.c),
9212  z2(Rbc.m, Astar.c), z3(Bc_adjoint.m, A.c);
9213  z1.setConstant(0.0);
9214  z2.setConstant(0.0);
9215  z3.setConstant(0.0);
9216  BcComp.eval << Lbc.eval, z1, //
9217  Rbc.eval, z2, //
9218  z3, Bc_adjoint.eval;
9219  // std::cout << "done >>>" << std::flush << '\n';
9220  LinopMat<T> Mmat(Acomp.r, Acomp.c), I(A.r, A.r);
9221  I.setIdentity();
9222  Mmat << Z, I, //
9223  I, Z;
9224  // std::cout << "BcComp: \n" << '\n';
9225  // for (int i = 0; i < BcComp.m; i++) {
9226  // for (int j = 0; j < BcComp.n; j++) {
9227  // std::cout << "(" << i << "," << j << ")" << '\n';
9228  // std::cout << BcComp.L(i, j).coef << '\n';
9229  // }
9230  // }
9231  // std::cin >> bre;
9232  // std::cout << "Bccomp.eval: " << BcComp.eval << std::endl;
9233  // std::cin >> bre;
9234  GeneralizedEigenSolver<T>::compute(Acomp, Mmat, num_vals, BcComp);
9235  };
9236 
9245  void compute(const LinopMat<T> &A_, const LinopMat<T> &B_,
9246  const LinopMat<T> &C_, const BcMat<T> &Lbc_,
9247  const BcMat<T> &Rbc_, int num_vals){
9248 
9249  };
9250 
9258  void compute(const LinopMat<T> &A_, const ChebfunMat<T> &B_,
9259  const LinopMat<T> &C_, const BcMat<T> &Lbc_,
9260  const BcMat<T> &Rbc_, int num_vals){
9261 
9262  };
9263 
9270  int bre;
9271  LinopMat<T> Lmat = Lmat_;
9272  int r = Lmat.r;
9273  int c = Lmat.c;
9274  // std::cin >> bre;
9275  LinopMat<T> outLmat;
9276  std::vector<int> highest_each_columnL;
9277  highest_each_columnL.resize(c);
9278  std::vector<int> temp_vec_int;
9279  temp_vec_int.resize(r);
9280  std::vector<int> alphaSize;
9281  int total_of_all_orders = 0;
9282 
9283  int counter = 0;
9284  for (int j = 0; j < c; j++) {
9285  for (int i = 0; i < r; i++) {
9286  temp_vec_int[i] = Lmat(i, j).n;
9287  }
9288  highest_each_columnL[j] =
9289  *std::max_element(temp_vec_int.begin(), temp_vec_int.end());
9290  }
9291 
9292  for (int i = 0; i < c; i++) {
9293  total_of_all_orders += highest_each_columnL[i];
9294  }
9295  int n = *std::max_element(highest_each_columnL.begin(),
9296  highest_each_columnL.end());
9297  // n is the overall order.
9298  // std::cout << "Total of all orders = " << total_of_all_orders << '\n';
9299  // std::cin >> bre;
9300  std::valarray<ChebfunMat<T> > alphais;
9301  std::valarray<ChebfunMat<T> > betais;
9302  outLmat.resize(Lmat.c, Lmat.r);
9303  alphais.resize(n + 1);
9304  betais.resize(n + 1);
9305  int outer_counter = 0;
9306  // Assign alphais
9307  for (int k = 0; k < n + 1; k++) {
9308  alphais[k].resize(Lmat.r, Lmat.c);
9309  alphais[k].setConstant(0.0);
9310  for (int i = 0; i < Lmat.r; i++) {
9311  for (int j = 0; j < Lmat.c; j++) {
9312  if (Lmat(i, j).n - k >= 0) {
9313  if (Lmat(i, j).NCC == 0) {
9314  alphais[k](i, j) = Lmat(i, j).coef[Lmat(i, j).n - k];
9315 
9316  } else {
9317  alphais[k](i, j) = Lmat(i, j).coefFun[Lmat(i, j).n - k];
9318  }
9319  }
9320  }
9321  }
9322  }
9323  /*std::cout << "alphais[0](0,0).coef" << '\n';
9324  std::cout << alphais[0](0, 0) << '\n';
9325  std::cout << alphais[1](0, 0) << '\n';
9326  std::cout << alphais[2](0, 0) << '\n';
9327  */
9328  if (ind == 2) {
9329  std::cout << "in " << __LINE__ << '\n';
9330  for (int k = 0; k < alphais.size(); k++) {
9331  for (int i = 0; i < 2; i++) {
9332  for (int j = 0; j < 2; j++) {
9333  std::cout << alphais[k](i, j) << '\n';
9334  std::cout << "(" << i << "," << j << ")" << '\n';
9335  std::cout << "k: " << k << '\n';
9336  // std::cin >> bre;
9337  }
9338  }
9339  }
9340  }
9341  // std::cout << "DONE alphai ,..." << '\n';
9342  // std::cin >> bre;
9343  nChoosek<T> nck;
9344  // Then Multiply binomial coefficients and assign to betais.
9345  for (int i = 0; i < n + 1; i++) {
9346  betais[i].resize(Lmat.r, Lmat.c);
9347  betais[i].setConstant(0.0);
9348  for (int j = i; j < n + 1; j++) {
9349  betais[i] =
9350  betais[i] + (pow(-1, j) * nck(j, i) * diff(alphais[i], j - i));
9351  }
9352  }
9353 
9354  /*std::cout << "Im in " << __LINE__ << '\n';
9355  std::cout << "betais[0](0,0).coef" << '\n';
9356  std::cout << betais[0](0, 0) << '\n';
9357  std::cout << betais[1](0, 0) << '\n';
9358  std::cout << betais[2](0, 0) << '\n';
9359  */
9360  // take the cTranspose, we will represent betais same as betais_star.
9361  for (int i = 0; i < n + 1; i++) {
9362  betais[i] = betais[i].cTranspose();
9363  }
9364 
9365  if (ind == 2) {
9366  std::cout << "in " << __LINE__ << '\n';
9367  for (int k = 0; k < betais.size(); k++) {
9368  for (int i = 0; i < 2; i++) {
9369  for (int j = 0; j < 2; j++) {
9370  std::cout << betais[k](i, j) << '\n';
9371  std::cout << "(" << i << "," << j << ")" << '\n';
9372  std::cout << "k: " << k << '\n';
9373  // std::cin >> bre;
9374  }
9375  }
9376  }
9377  }
9378  // Now, assemble the adjoint operator from betais_star
9379  // Assign alphais.
9380  // std::cout << "Lmatr,c : " << r << "," << c << '\n';
9381  for (int i = 0; i < Lmat.c; i++) {
9382  for (int j = 0; j < Lmat.r; j++) {
9383  outLmat(i, j).ncc(n);
9384  for (int k = 0; k < n + 1; k++) {
9385  outLmat(i, j).coefFun[n - k] = betais[k](i, j);
9386  }
9387  }
9388  }
9389 
9390  // std::cout << "DONE!!" << std::flush << '\n';
9391 
9392  return outLmat;
9393  };
9394 
9405 
9406  // \todo It is possible to have incosistent equations and yet find an Adjoint
9407  // bc that compensates for the rank deficiency.
9409  const BcMat<T> &Rbc_) {
9410  int bre;
9411  LinopMat<T> Lmat = Lmat_;
9412  BcMat<T> Lbc = Lbc_;
9413  BcMat<T> Rbc = Rbc_;
9414  int r = Lmat.r;
9415  int c = Lmat.c;
9416  std::vector<int> highest_each_columnL;
9417  highest_each_columnL.resize(c);
9418  std::vector<int> temp_vec_int;
9419  temp_vec_int.resize(r);
9420  std::vector<int> alphaSize;
9421  int total_of_all_orders = 0;
9422  // std::cout << "Entered ABCAN" << '\n';
9423 
9424  int counter = 0;
9425  for (int j = 0; j < c; j++) {
9426  for (int i = 0; i < r; i++) {
9427  temp_vec_int[i] = Lmat(i, j).n;
9428  }
9429  highest_each_columnL[j] =
9430  *std::max_element(temp_vec_int.begin(), temp_vec_int.end());
9431  }
9432 
9433  for (int i = 0; i < c; i++) {
9434  total_of_all_orders += highest_each_columnL[i];
9435  }
9436  int n = *std::max_element(highest_each_columnL.begin(),
9437  highest_each_columnL.end());
9438  // n is the overall order.
9439  // std::cin >> bre;
9440  std::valarray<ChebfunMat<T> > alphais;
9441  std::valarray<ChebfunMat<T> > betais;
9442  alphais.resize(n + 1);
9443  betais.resize(n + 1);
9444  int outer_counter = 0;
9445  // Assign alphais
9446  for (int k = 0; k < n + 1; k++) {
9447  alphais[k].resize(Lmat.r, Lmat.c);
9448  alphais[k].setConstant(0.0);
9449  for (int i = 0; i < Lmat.r; i++) {
9450  for (int j = 0; j < Lmat.c; j++) {
9451  if (Lmat(i, j).n - k >= 0) {
9452  if (Lmat(i, j).NCC == 0) {
9453  alphais[k](i, j) = Lmat(i, j).coef[Lmat(i, j).n - k];
9454  } else {
9455  alphais[k](i, j) = Lmat(i, j).coefFun[Lmat(i, j).n - k];
9456  }
9457  }
9458  }
9459  }
9460  }
9461  // std::cout << "in " << __LINE__ << '\n' << std::flush;
9462  // std::cin >> bre;
9463  // Need a 2D vector of ChebfunMats, storing in row major format.
9464  //
9465  std::valarray<ChebfunMat<T> > Amat;
9466  Amat.resize(n * n);
9467  for (int i = 0; i < n * n; i++) {
9468  Amat[i].resize(Lmat.r, Lmat.c);
9469  Amat[i].setConstant(0.0);
9470  }
9471  // std::cout << "in " << __LINE__ << '\n' << std::flush;
9472  nChoosek<T> nck;
9473  for (int i = 0; i < n; i++) {
9474  for (int j = 0; j < n - i; j++) {
9475  for (int k = i; k < n - j; k++) {
9476  Amat[i * n + j] = Amat[i * n + j] + (pow(-1, k) * nck(k, i) *
9477  diff(alphais[k + j + 1], k - i));
9478  }
9479  }
9480  }
9481  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> Aplus(n * r, n * r),
9482  Aminus(n * r, n * r);
9483 
9484  Aplus = feval2D(Amat, n, n, 1.0);
9485  Aminus = feval2D(Amat, n, n, -1.0);
9486  // std::cout << "Aplus : \n" << Aplus << '\n';
9487  // std::cout << "Aminus : \n" << Aminus << '\n';
9488  // std::cin >> bre;
9489  Amat.resize(0);
9490  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> Blbc(Lbc.m, n * Lbc.n),
9491  Brbc(Rbc.m, n * Rbc.n);
9492  Blbc.setConstant(0.0);
9493  Brbc.setConstant(0.0);
9494  // std::cout << "Blbc: " << size(Blbc) << '\n';
9495  for (int k = 0; k < n + 1; k++) {
9496  for (int i = 0; i < Lbc.m; i++) {
9497  for (int j = 0; j < Lbc.n; j++) {
9498  if (Lbc.L(i, j).n - k >= 0) {
9499  if (Lbc.L(i, j).NCC == 0) {
9500  // std::cout << "(" << i << "," << j << "," << k << ")" <<
9501  // '\n';
9502  Blbc(i, Lbc.n * k + j) = Lbc.L(i, j).coef[Lbc.L(i, j).n - k];
9503  // std::cout << "Blbc: \n" << Blbc << '\n';
9504  // std::cin >> bre;
9505  } else {
9506  std::cout << "boundary conditions cannot have non-constant"
9507  << "coefficients" << '\n';
9508  exit(1);
9509  }
9510  }
9511  }
9512  }
9513  }
9514  for (int k = 0; k < n + 1; k++) {
9515  for (int i = 0; i < Rbc.m; i++) {
9516  for (int j = 0; j < Rbc.n; j++) {
9517  if (Rbc.L(i, j).n - k >= 0) {
9518  if (Rbc.L(i, j).NCC == 0) {
9519  Brbc(i, Rbc.n * k + j) = Rbc.L(i, j).coef[Rbc.L(i, j).n - k];
9520  // std::cout << "(" << i << "," << j << "," << k << ")" <<
9521  // '\n'; std::cout << "Brbc: \n" << Brbc << '\n'; std::cin >>
9522  // bre;
9523  } else {
9524  std::cout << "boundary conditions cannot have non-constant"
9525  << "coefficients" << '\n';
9526  exit(1);
9527  }
9528  }
9529  }
9530  }
9531  }
9532 
9533  Eigen::CompleteOrthogonalDecomposition<
9534  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> >
9535  cod;
9536  cod.compute(Blbc);
9537  if (cod.rank() != Blbc.rows()) {
9538  std::cout << "the bounndary conditions are not linearly independent."
9539  << "Exiting ..." << '\n';
9540  exit(1);
9541  }
9542  // Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> forcL(lbc_val.size(),
9543  // 1),
9544  // forcR(rbc_val.size(), 1);
9545  // for (int i = 0; i < lbc_val.size(); i++) {
9546  // forcL(i, 0) = lbc_val[i];
9547  // }
9548  // for (int i = 0; i < rbc_val.size(); i++) {
9549  // forcR(i, 0) = rbc_val[i];
9550  // }
9551 
9552  // Find the particular solutions:
9553  // Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> minNormSol_lbc =
9554  // cod.solve(forcL);
9555  // std::cout << "minNormSol_lbc: " << minNormSol_lbc << std::flush << '\n';
9556  // Find the null-space:
9557  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> V =
9558  cod.matrixZ().adjoint();
9559  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> Null_space =
9560  V.block(0, cod.rank(), V.rows(), V.cols() - cod.rank());
9561  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> P = cod.colsPermutation();
9562  Null_space = P * Null_space;
9563 
9564  // Determine as many LI solutions using the Null-space.
9565  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> solutionL(
9566  Null_space.rows(), Null_space.cols());
9567  // for (int i = 0; i < Null_space.cols(); i++) {
9568  // solutionL.col(i) = Null_space.col(i) + minNormSol_lbc;
9569  // }
9570  solutionL = Null_space;
9571  // Do the same for RBC:
9572  cod.compute(Brbc);
9573  // std::cout << "in " << __LINE__ << '\n';
9574  if (cod.rank() != Brbc.rows()) {
9575  std::cout << "the bounndary conditions are not linearly independent."
9576  << "Exiting ..." << '\n';
9577  exit(1);
9578  }
9579  // Find the particular solutions:
9580  // Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> minNormSol_rbc =
9581  // cod.solve(forcR);
9582 
9583  // Find the null-space:
9584  V = cod.matrixZ().adjoint();
9585 
9586  Null_space = V.block(0, cod.rank(), V.rows(), V.cols() - cod.rank());
9587 
9588  P = cod.colsPermutation();
9589 
9590  Null_space = P * Null_space;
9591 
9592  // Determine as many LI solutions using the Null-space.
9593  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> solutionR(
9594  Null_space.rows(), Null_space.cols());
9595  // for (int i = 0; i < Null_space.cols(); i++) {
9596  // solutionR.col(i) = Null_space.col(i) + minNormSol_rbc;
9597  //}
9598  solutionR = Null_space;
9599  // Now determine the boundary conditions in lbc:
9600  solutionL.adjointInPlace();
9601  Aminus.adjointInPlace();
9602  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> lbc = solutionL * Aminus;
9603 
9604  solutionR.adjointInPlace();
9605  Aplus.adjointInPlace();
9606  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> rbc = solutionR * Aplus;
9607 
9608  // The lbc and rbc are now in the basis u1, u2, express in the normal basis:
9609  BcMat<T> out;
9610  out.resize(lbc.rows() + rbc.rows(), Lmat.r);
9611  // std::cout << "lbc: \n " << lbc << '\n';
9612  // std::cout << "rbc: \n " << rbc << '\n';
9613  // std::cin >> bre;
9614  for (int i = 0; i < lbc.rows(); i++) {
9615  for (int j = 0; j < Lmat.c; j++) {
9616  out.L(i, j).set(n - 1);
9617  out.eval(i, j) = -1.0;
9618  for (int k = 0; k < n; k++) {
9619  out.L(i, j).coef[n - k - 1] = lbc(i, Lmat.c * k + j);
9620  }
9621  }
9622  }
9623 
9624  for (int i = 0; i < rbc.rows(); i++) {
9625  for (int j = 0; j < Lmat.c; j++) {
9626  out.L(i + lbc.rows(), j).set(n - 1);
9627  out.eval(i + lbc.rows(), j) = 1.0;
9628  for (int k = 0; k < n; k++) {
9629  // std::cout << "(" << i << "," << j << "," << k << ")" <<
9630  // '\n';
9631  out.L(i + lbc.rows(), j).coef[n - k - 1] = rbc(i, Lmat.c * k + j);
9632  }
9633  }
9634  }
9635  // std::cout << "out: \n" << '\n';
9636  // for (int i = 0; i < out.m; i++) {
9637  // for (int j = 0; j < out.n; j++) {
9638  // std::cout << "(" << i << "," << j << ")" << '\n';
9639  // std::cout << out.L(i, j).coef << '\n';
9640  // }
9641  // }
9642  // std::cout << "out.eval: \n" << out.eval << '\n';
9643  // std::cout << "in " << __LINE__ << '\n';
9644 
9645  // return the expression for boundary conditions:
9646  return out;
9647  };
9648 };
9649 
9654 template <class T> class Discretize : public MatGen<T> {
9655 public:
9656  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> P;
9657  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> subs_mat;
9658  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> mat_temp;
9659  std::vector<int> highest_each_column;
9660  int num_bc;
9664  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>
9665  operator()(const LinopMat<T> &Lmat_, const BcMat<T> &bc_) {
9666 
9667  LinopMat<T> Lmat = Lmat_;
9668  BcMat<T> bc = bc_;
9669  int r = Lmat.r, c = Lmat.c;
9670  if (Lmat_.c != bc_.n) {
9671  std::cout << "The number of comlumns have to be the same in " << __LINE__
9672  << '\n';
9673  std::cout << ". Exiting..." << '\n';
9674  exit(1);
9675  }
9676  num_bc = bc.m;
9677  highest_each_column.resize(c);
9678  int bre;
9679  int total_of_all_orders = 0;
9680  int total_boundary_conditions = 0;
9681  std::vector<int> temp_vec_int;
9682  temp_vec_int.resize(r);
9683  for (int j = 0; j < c; j++) {
9684  for (int i = 0; i < r; i++) {
9685  temp_vec_int[i] = Lmat(i, j).n;
9686  }
9687  highest_each_column[j] =
9688  *std::max_element(temp_vec_int.begin(), temp_vec_int.end());
9689  total_of_all_orders += highest_each_column[j];
9690  }
9691 
9692  total_boundary_conditions = bc.m;
9693 
9694  // total_of_all_orders has to be equal to total number of boundary
9695  // conditions, else the problem is ill-posed, if ill-posed, cout the same
9696  // and exit.
9697  if (total_of_all_orders != total_boundary_conditions) {
9698  std::cout << "The problem is ill-posed, the total of the highest "
9699  "orders of all "
9700  "dependent variables has to be equal to the total number of "
9701  "boundary conditions specified."
9702  "\n "
9703  "Total no. of boundary conditions: "
9704  << total_boundary_conditions
9705  << "\n"
9706  "Total of all orders: "
9707  << total_of_all_orders << "\n Exiting ...\n";
9708  exit(1);
9709  }
9710 
9711  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> masterL(
9712  r * (N + 1), c * (N + 1) + total_boundary_conditions);
9713 
9714  masterL.setConstant(0.0);
9715 
9716  subs_mat.resize(total_boundary_conditions, (N + 1) * c);
9717  subs_mat.setConstant(0.0);
9718 
9719  mat_temp.resize(total_boundary_conditions, total_boundary_conditions);
9720  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> constraints(
9721  total_boundary_conditions, c * (N + 1) + total_of_all_orders);
9722  mat_temp.setConstant(0.0);
9723  int row_counter = 0, col_counter = 0;
9724  for (int i = 0; i < bc.m; i++) {
9725  for (int j = 0; j < bc.n; j++) {
9726  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> temp =
9727  bc(i, j, highest_each_column[j]);
9728  constraints.block(i, col_counter, 1, temp.cols()) = temp;
9729  col_counter += temp.cols();
9730  }
9731  col_counter = 0;
9732  }
9733 
9734  Eigen::ColPivHouseholderQR<
9735  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> >
9736  qr;
9737  qr.compute(constraints);
9738  if (qr.rank() != constraints.rows()) {
9739  std::cout << "The boundary conditions supplied are not "
9740  << " linearly independent." << '\n';
9741  std::cout << "qr.rank = " << qr.rank()
9742  << ", no. bcs: " << total_boundary_conditions << ". Exiting ..."
9743  << '\n';
9744  exit(1);
9745  }
9746 
9747  P = qr.colsPermutation();
9748  // Permute constraints
9749  constraints = constraints * P;
9750  mat_temp = constraints.block(0, 0, constraints.rows(), constraints.rows());
9751 
9752  Eigen::ColPivHouseholderQR<
9753  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> >
9754  consSolver(mat_temp);
9755  subs_mat = -consSolver.inverse() *
9756  constraints.block(0, constraints.rows(), constraints.rows(),
9757  constraints.cols() - constraints.rows());
9758 
9759  row_counter = 0;
9760  col_counter = 0;
9761  int master_row_counter = 0;
9762  int master_col_counter = 0;
9763  for (int j = 0; j < c; j++) {
9764  int n = highest_each_column[j];
9765  MatGen<T>::compute(n);
9766  for (int i = 0; i < r; i++) {
9767  int diffn = n - Lmat(i, j).n;
9768  if (Lmat(i, j).NCC == 0) {
9769  for (int k = 0; k < Lmat(i, j).n + 1; k++) {
9770  masterL.block(master_row_counter, master_col_counter, N + 1,
9771  N + 1 + n) +=
9772  Lmat(i, j).coef[k] *
9773  (MatGen<T>::mats2[k + diffn].block(0, 0, N + 1, N + 1 + n));
9774  }
9775  } else {
9776  for (int k = 0; k < Lmat(i, j).n + 1; k++) {
9777  masterL.block(master_row_counter, master_col_counter, N + 1,
9778  N + 1 + n) +=
9779  Lmat(i, j).coefFun[k].MultMat().block(0, 0, N + 1, N + 1) *
9780  (MatGen<T>::mats2[k + diffn].block(0, 0, N + 1, N + 1 + n));
9781  }
9782  }
9783  master_row_counter += N + 1;
9784  }
9785  master_row_counter = 0;
9786  master_col_counter += N + 1 + n;
9787  }
9788 
9789  // Permute columns of M and L:
9790  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> masterL2;
9791  masterL = masterL * P;
9792  masterL2 =
9793  masterL.block(0, constraints.rows(), c * (N + 1), c * (N + 1)) +
9794  (masterL.block(0, 0, c * (N + 1), constraints.rows()) * subs_mat);
9795  return masterL2;
9796  }
9797 
9801  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>
9802  operator()(const LinopMat<T> &Lmat) {
9803  int r = Lmat.r, c = Lmat.c;
9804  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> masterL(
9805  r * (N + 1), c * (N + 1) + num_bc);
9806 
9807  masterL.setConstant(0.0);
9808 
9809  int row_counter = 0;
9810  int col_counter = 0;
9811  int master_row_counter = 0;
9812  int master_col_counter = 0;
9813 
9814  for (int j = 0; j < c; j++) {
9815  int n = highest_each_column[j];
9817  for (int i = 0; i < r; i++) {
9818  int diffn = n - Lmat(i, j).n;
9819  if (Lmat(i, j).NCC == 0) {
9820  for (int k = 0; k < Lmat(i, j).n + 1; k++) {
9821  masterL.block(master_row_counter, master_col_counter, N + 1,
9822  N + 1 + n) +=
9823  Lmat(i, j).coef[k] *
9824  (MatGen<T>::mats2[k + diffn].block(0, 0, N + 1, N + 1 + n));
9825  }
9826  } else {
9827  for (int k = 0; k < Lmat(i, j).n + 1; k++) {
9828  masterL.block(master_row_counter, master_col_counter, N + 1,
9829  N + 1 + n) +=
9830  Lmat(i, j).coefFun[k].MultMat().block(0, 0, N + 1, N + 1) *
9831  (MatGen<T>::mats2[k + diffn].block(0, 0, N + 1, N + 1 + n));
9832  }
9833  }
9834  master_row_counter += N + 1;
9835  }
9836  master_row_counter = 0;
9837  master_col_counter += N + 1 + n;
9838  }
9839 
9840  // Permute columns of M and L:
9841  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> masterL2;
9842  masterL = masterL * P;
9843  masterL2 = masterL.block(0, num_bc, c * (N + 1), c * (N + 1)) +
9844  (masterL.block(0, 0, c * (N + 1), num_bc) * subs_mat);
9845 
9846  return masterL2;
9847  }
9848 };
9849 
9854 template <class T>
9855 class Discretize<std::complex<T> > : public MatGen<std::complex<T> > {
9856 public:
9857  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> P;
9858  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> subs_mat;
9859  // Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> mat_temp;
9860  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> A1;
9861  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> invmat_temp;
9862  std::vector<int> highest_each_column;
9863 
9864  int num_bc;
9865 
9867  Discretize() : num_bc(0) {}
9871  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic>
9872  operator()(const LinopMat<std::complex<T> > &Lmat_,
9873  const BcMat<std::complex<T> > &bc_) {
9874  int bre;
9875  LinopMat<std::complex<T> > Lmat = Lmat_;
9876  BcMat<std::complex<T> > bc = bc_;
9877  int r = Lmat.r, c = Lmat.c;
9878  if (Lmat_.c != bc_.n) {
9879  std::cout << "The number of comlumns have to be the same in " << __LINE__
9880  << '\n';
9881  std::cout << ". Exiting..." << '\n';
9882  exit(1);
9883  }
9884  num_bc = bc.m;
9885  highest_each_column.resize(c);
9886  int total_of_all_orders = 0;
9887  int total_boundary_conditions = 0;
9888  std::vector<int> temp_vec_int;
9889  temp_vec_int.resize(r);
9890  for (int j = 0; j < c; j++) {
9891  for (int i = 0; i < r; i++) {
9892  temp_vec_int[i] = Lmat(i, j).n;
9893  }
9894  highest_each_column[j] =
9895  *std::max_element(temp_vec_int.begin(), temp_vec_int.end());
9896  // std::cout << "highest_each_column[" << j << "]" <<
9897  // highest_each_column[j]
9898  // << '\n';
9899  total_of_all_orders += highest_each_column[j];
9900  }
9901  // std::cin >> bre;
9902  total_boundary_conditions = bc.m;
9903 
9904  // total_of_all_orders has to be equal to total number of boundary
9905  // conditions, else the problem is ill-posed, if ill-posed, cout the same
9906  // and exit.
9907  if (total_of_all_orders != total_boundary_conditions) {
9908  std::cout << "The problem is ill-posed, the total of the highest "
9909  "orders of all "
9910  "dependent variables has to be equal to the total number of "
9911  "boundary conditions specified."
9912  "\n "
9913  "Total no. of boundary conditions: "
9914  << total_boundary_conditions
9915  << "\n"
9916  "Total of all orders: "
9917  << total_of_all_orders << "\n Exiting ...\n";
9918  exit(1);
9919  }
9920 
9921  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> masterL(
9922  r * (N + 1), c * (N + 1) + total_boundary_conditions);
9923 
9924  masterL.setConstant(0.0);
9925 
9926  subs_mat.resize(total_boundary_conditions, (N + 1) * c);
9927  subs_mat.setConstant(0.0);
9928  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> mat_temp;
9929  mat_temp.resize(total_boundary_conditions, total_boundary_conditions);
9930  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> constraints(
9931  total_boundary_conditions, c * (N + 1) + total_of_all_orders);
9932  mat_temp.setConstant(0.0);
9933  int row_counter = 0, col_counter = 0;
9934  for (int i = 0; i < bc.m; i++) {
9935  for (int j = 0; j < bc.n; j++) {
9936  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> temp =
9937  bc(i, j, highest_each_column[j]);
9938  constraints.block(i, col_counter, 1, temp.cols()) = temp;
9939  col_counter += temp.cols();
9940  }
9941  col_counter = 0;
9942  }
9943 
9944  Eigen::ColPivHouseholderQR<
9945  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> >
9946  qr;
9947  qr.compute(constraints);
9948  if (qr.rank() != constraints.rows()) {
9949  std::cout << "The boundary conditions supplied are not "
9950  << " linearly independent." << '\n';
9951  std::cout << "qr.rank = " << qr.rank()
9952  << ", no. bcs: " << total_boundary_conditions << ". Exiting ..."
9953  << '\n';
9954  // exit(1);
9955  }
9956  P = qr.colsPermutation();
9957 
9958  // Permute constraints
9959  constraints = constraints * P;
9960  mat_temp = constraints.block(0, 0, constraints.rows(), constraints.rows());
9961 
9962  Eigen::ColPivHouseholderQR<
9963  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> >
9964  consSolver(mat_temp);
9965  subs_mat = -consSolver.inverse() *
9966  constraints.block(0, constraints.rows(), constraints.rows(),
9967  constraints.cols() - constraints.rows());
9968  invmat_temp = consSolver.inverse();
9969  row_counter = 0;
9970  col_counter = 0;
9971  int master_row_counter = 0;
9972  int master_col_counter = 0;
9973  for (int j = 0; j < c; j++) {
9974  int n = highest_each_column[j];
9976  for (int i = 0; i < r; i++) {
9977  int diffn = n - Lmat(i, j).n;
9978  if (Lmat(i, j).NCC == 0) {
9979  for (int k = 0; k < Lmat(i, j).n + 1; k++) {
9980  masterL.block(master_row_counter, master_col_counter, N + 1,
9981  N + 1 + n) +=
9982  Lmat(i, j).coef[k] *
9983  (MatGen<std::complex<T> >::mats2[k + diffn].block(0, 0, N + 1,
9984  N + 1 + n));
9985  }
9986  } else {
9987  for (int k = 0; k < Lmat(i, j).n + 1; k++) {
9988  masterL.block(master_row_counter, master_col_counter, N + 1,
9989  N + 1 + n) +=
9990  Lmat(i, j).coefFun[k].MultMat().block(0, 0, N + 1, N + 1) *
9991  (MatGen<std::complex<T> >::mats2[k + diffn].block(0, 0, N + 1,
9992  N + 1 + n));
9993  }
9994  }
9995  master_row_counter += N + 1;
9996  }
9997  master_row_counter = 0;
9998  master_col_counter += N + 1 + n;
9999  }
10000 
10001  // Permute columns of M and L:
10002  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> masterL2;
10003  masterL = masterL * P;
10004  masterL2 =
10005  masterL.block(0, constraints.rows(), c * (N + 1), c * (N + 1)) +
10006  (masterL.block(0, 0, c * (N + 1), constraints.rows()) * subs_mat);
10007  // std::cout << "masterL2: \n" << masterL2 << '\n';
10008  // std::cin >> bre;
10009  A1 = masterL.block(0, 0, c * (N + 1), constraints.rows());
10010  return masterL2;
10011  }
10012 
10016  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic>
10017  operator()(const LinopMat<std::complex<T> > &Lmat_) {
10018  LinopMat<std::complex<T> > Lmat = Lmat_;
10019  int r = Lmat.r, c = Lmat.c;
10020 
10021  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> masterL(
10022  r * (N + 1), c * (N + 1) + num_bc);
10023  masterL.setConstant(0.0);
10024  int row_counter = 0;
10025  int col_counter = 0;
10026  int master_row_counter = 0;
10027  int master_col_counter = 0;
10028  for (int j = 0; j < c; j++) {
10029  int n = highest_each_column[j];
10031  for (int i = 0; i < r; i++) {
10032  int diffn = n - Lmat(i, j).n;
10033  if (Lmat(i, j).NCC == 0) {
10034  for (int k = 0; k < Lmat(i, j).n + 1; k++) {
10035  masterL.block(master_row_counter, master_col_counter, N + 1,
10036  N + 1 + n) +=
10037  Lmat(i, j).coef[k] *
10038  (MatGen<std::complex<T> >::mats2[k + diffn].block(0, 0, N + 1,
10039  N + 1 + n));
10040  }
10041  } else {
10042  for (int k = 0; k < Lmat(i, j).n + 1; k++) {
10043  masterL.block(master_row_counter, master_col_counter, N + 1,
10044  N + 1 + n) +=
10045  Lmat(i, j).coefFun[k].MultMat().block(0, 0, N + 1, N + 1) *
10046  (MatGen<std::complex<T> >::mats2[k + diffn].block(0, 0, N + 1,
10047  N + 1 + n));
10048  }
10049  }
10050  master_row_counter += N + 1;
10051  }
10052  master_row_counter = 0;
10053  master_col_counter += N + 1 + n;
10054  }
10055 
10056  // Permute columns of M and L:
10057  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> masterL2;
10058  masterL = masterL * P;
10059  masterL2 = masterL.block(0, num_bc, r * (N + 1), c * (N + 1)) +
10060  (masterL.block(0, 0, r * (N + 1), num_bc) * subs_mat);
10061  return masterL2;
10062  }
10063 
10065  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic>
10066 
10067  ChebDiff(const LinopMat<std::complex<T> > &Lmat_) {
10068  LinopMat<std::complex<T> > Lmat = Lmat_;
10069  int r = Lmat.r, c = Lmat.c;
10070  highest_each_column.resize(c);
10071  int bre;
10072  int total_of_all_orders = 0;
10073  int total_boundary_conditions = 0;
10074  std::vector<int> temp_vec_int;
10075  temp_vec_int.resize(r);
10076  for (int j = 0; j < c; j++) {
10077  for (int i = 0; i < r; i++) {
10078  temp_vec_int[i] = Lmat(i, j).n;
10079  }
10080  highest_each_column[j] =
10081  *std::max_element(temp_vec_int.begin(), temp_vec_int.end());
10082  std::cout << "highest_each_column[" << j << "]" << highest_each_column[j]
10083  << '\n';
10084  total_of_all_orders += highest_each_column[j];
10085  }
10086  int n = *std::max_element(highest_each_column.begin(),
10087  highest_each_column.end());
10088  std::vector<Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> >
10089  diffMats;
10090  diffMats.resize(n + 1);
10091 
10092  for (int i = 0; i < n + 1; i++) {
10093  diffMats[i].resize(N + 1, N + 1);
10094  }
10095 
10096  diffMats[0] = Eigen::Matrix<std::complex<T>, Eigen::Dynamic,
10097  Eigen::Dynamic>::Identity(N + 1, N + 1);
10098  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> Dmat(N + 1,
10099  N + 1),
10100  masterL(r * (N + 1), c * (N + 1)), temp;
10101 
10102  Dmat.setConstant(0.0);
10103  masterL.setConstant(0.0);
10104  for (int k = 0; k < N + 1; k++) {
10105  for (int p = k + 1; p < N + 1; p++) {
10106  if ((p + k) % 2) {
10107  Dmat(k, p) = p;
10108  }
10109  }
10110  }
10111  std::valarray<T> y(N + 1), y1(N + 1);
10112  setChebPts(y);
10114  fun.vr = y * y;
10115  fun.vi = 0.0;
10116  fun.p2c();
10117  temp = fun.evc();
10118 
10119  for (int i = 1; i < n + 1; i++) {
10120  diffMats[i] = 2.0 * Dmat * diffMats[i - 1];
10121  }
10122  // temp = diffMats[1] * temp;
10123  // std::cout << "temp = \n" << temp << '\n';
10124  // std::cin >> bre;
10125 
10126  int master_row_counter = 0;
10127  int master_col_counter = 0;
10128  for (int j = 0; j < c; j++) {
10129  int n = highest_each_column[j];
10130  for (int i = 0; i < r; i++) {
10131  int diffn = n - Lmat(i, j).n;
10132  if (Lmat(i, j).NCC == 0) {
10133  for (int k = 0; k < Lmat(i, j).n + 1; k++) {
10134  masterL.block(master_row_counter, master_col_counter, N + 1,
10135  N + 1) +=
10136  Lmat(i, j).coef[Lmat(i, j).n - k] * (diffMats[k]);
10137  }
10138  } else {
10139  for (int k = 0; k < Lmat(i, j).n + 1; k++) {
10140  masterL.block(master_row_counter, master_col_counter, N + 1,
10141  N + 1) +=
10142  Lmat(i, j).coefFun[Lmat(i, j).n - k].MultMat().block(
10143  0, 0, N + 1, N + 1) *
10144  (diffMats[k]);
10145  }
10146  }
10147  master_row_counter += N + 1;
10148  }
10149  master_row_counter = 0;
10150  master_col_counter += N + 1;
10151  }
10152 
10153  return masterL;
10154  }
10155 
10159  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic>
10160  MatAppend(const LinopMat<std::complex<T> > &Lmat_,
10161  const BcMat<std::complex<T> > &bc_) {
10162  int bre;
10163  LinopMat<std::complex<T> > Lmat = Lmat_;
10164  BcMat<std::complex<T> > bc = bc_;
10165  int r = Lmat.r, c = Lmat.c;
10166  if (Lmat_.c != bc_.n) {
10167  std::cout << "The number of comlumns have to be the same in " << __LINE__
10168  << '\n';
10169  std::cout << ". Exiting..." << '\n';
10170  exit(1);
10171  }
10172  num_bc = bc.m;
10173  highest_each_column.resize(c);
10174  int total_of_all_orders = 0;
10175  int total_boundary_conditions = 0;
10176  std::vector<int> temp_vec_int;
10177  temp_vec_int.resize(r);
10178  for (int j = 0; j < c; j++) {
10179  for (int i = 0; i < r; i++) {
10180  temp_vec_int[i] = Lmat(i, j).n;
10181  }
10182  highest_each_column[j] =
10183  *std::max_element(temp_vec_int.begin(), temp_vec_int.end());
10184  // std::cout << "highest_each_column[" << j << "]" <<
10185  // highest_each_column[j]
10186  // << '\n';
10187  total_of_all_orders += highest_each_column[j];
10188  }
10189  // std::cin >> bre;
10190  total_boundary_conditions = bc.m;
10191 
10192  // total_of_all_orders has to be equal to total number of boundary
10193  // conditions, else the problem is ill-posed, if ill-posed, cout the same
10194  // and exit.
10195  if (total_of_all_orders != total_boundary_conditions) {
10196  std::cout << "The problem is ill-posed, the total of the highest "
10197  "orders of all "
10198  "dependent variables has to be equal to the total number of "
10199  "boundary conditions specified."
10200  "\n "
10201  "Total no. of boundary conditions: "
10202  << total_boundary_conditions
10203  << "\n"
10204  "Total of all orders: "
10205  << total_of_all_orders << "\n Exiting ...\n";
10206  exit(1);
10207  }
10208 
10209  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> masterL(
10210  r * (N + 1), c * (N + 1) + total_boundary_conditions);
10211 
10212  masterL.setConstant(0.0);
10213 
10214  subs_mat.resize(total_boundary_conditions, (N + 1) * c);
10215  subs_mat.setConstant(0.0);
10216  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> mat_temp;
10217  mat_temp.resize(total_boundary_conditions, total_boundary_conditions);
10218  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> constraints(
10219  total_boundary_conditions, c * (N + 1) + total_of_all_orders);
10220  mat_temp.setConstant(0.0);
10221  int row_counter = 0, col_counter = 0;
10222  for (int i = 0; i < bc.m; i++) {
10223  for (int j = 0; j < bc.n; j++) {
10224  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> temp =
10225  bc(i, j, highest_each_column[j]);
10226  constraints.block(i, col_counter, 1, temp.cols()) = temp;
10227  col_counter += temp.cols();
10228  }
10229  col_counter = 0;
10230  }
10231 
10232  row_counter = 0;
10233  col_counter = 0;
10234  int master_row_counter = 0;
10235  int master_col_counter = 0;
10236  for (int j = 0; j < c; j++) {
10237  int n = highest_each_column[j];
10239  for (int i = 0; i < r; i++) {
10240  int diffn = n - Lmat(i, j).n;
10241  if (Lmat(i, j).NCC == 0) {
10242  for (int k = 0; k < Lmat(i, j).n + 1; k++) {
10243  masterL.block(master_row_counter, master_col_counter, N + 1,
10244  N + 1 + n) +=
10245  Lmat(i, j).coef[k] *
10246  (MatGen<std::complex<T> >::mats2[k + diffn].block(0, 0, N + 1, N + 1 + n));
10247  }
10248  } else {
10249  for (int k = 0; k < Lmat(i, j).n + 1; k++) {
10250  masterL.block(master_row_counter, master_col_counter, N + 1, N + 1 + n) +=
10251  Lmat(i, j).coefFun[k].MultMat().block(0, 0, N + 1, N + 1) *
10252  (MatGen<std::complex<T> >::mats2[k + diffn].block(0, 0, N + 1, N + 1 + n));
10253  }
10254  }
10255  master_row_counter += N + 1;
10256  }
10257  master_row_counter = 0;
10258  master_col_counter += N + 1 + n;
10259  }
10260 
10261  // Permute columns of M and L:
10262  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> masterL2(
10263  r * (N + 1) + total_boundary_conditions,
10264  c * (N + 1) + total_boundary_conditions);
10265 
10266  masterL2 << masterL, constraints;
10267  return masterL2;
10268  }
10269 };
10270 
10277 template <class T>
10278 class SingularValueDecomposition<std::complex<T> >
10279  : public GeneralizedEigenSolver<std::complex<T> > {
10280 private:
10281 public:
10282  // Options: SIS_SVD_RIGHT: compute only right singular eigenvectors
10283  // SIS_SVD_LEFT: compute only left singular eigenvectors.
10284  // SIS_SVD: compute both. The former two are twice as fast.
10287 
10289  double gamma_opt;
10291  double omega_opt;
10292  SingularValueDecomposition() : svd_flag(SIS_SVD), isSingular(0) {}
10295  void compute(const LinopMat<std::complex<T> > &A_,
10296  const BcMat<std::complex<T> > &Lbc_,
10297  const BcMat<std::complex<T> > &Rbc_, int num_vals) {
10298  int bre;
10299  LinopMat<std::complex<T> > A = A_;
10300  BcMat<std::complex<T> > Lbc = Lbc_;
10301  BcMat<std::complex<T> > Rbc = Rbc_;
10302  LinopMat<std::complex<T> > Astar = Adjoint(A);
10303  BcMat<std::complex<T> > Bc_adjoint = AdjointBc_analytical(A, Lbc_, Rbc_);
10304 
10305  // Define the composite operator:
10306  LinopMat<std::complex<T> > Acomp(2 * A.r, 2 * A.r);
10307  LinopMat<std::complex<T> > Z(A.r, A.r);
10308  Z.setConstant(0.0);
10309  Acomp << A, Z, //
10310  Z, Astar;
10311  // for (int i = 0; i < Astar.r; i ++){
10312  // for (int j = 0; j < Astar.c;j ++){
10313  // if(Astar(i,j).NCC == 0){
10314  // std::cout << "ij = ("<< i <<"," << j << "):" << '\n';
10315  // std::cout << Astar(i,j).coef << '\n';
10316  // std::cin >> bre;
10317  // } else {
10318  // for (int k = 0; k < Astar(i,j).n + 1; k ++){
10319  // std::cout << "("<< i <<"," << j << "," << k << "):" << '\n';
10320  // std::cout << Astar(i,j).coefFun[k] << '\n';
10321  // std::cin >> bre;
10322  // }
10323  // }
10324  // }
10325  // }
10326 
10327  // std::cout << "Bc_adjoint: \n" << '\n';
10328  // for (int i = 0; i < Bc_adjoint.m; i++) {
10329  // for (int j = 0; j < Bc_adjoint.n; j++) {
10330  // std::cout << "(" << i << "," << j << ")" << '\n';
10331  // std::cout << Bc_adjoint.L(i, j).coef << '\n';
10332  // }
10333  //}
10334  // std::cout << "Bc_adjoint.eval: \n" << Bc_adjoint.eval << '\n';
10335  // std::cin >> bre;
10336  // Form composite boundary conditions:
10337  BcMat<std::complex<T> > BcComp(Lbc.m + Rbc.m + Bc_adjoint.m, 2 * A.r);
10338  LinopMat<std::complex<T> > Z1(Lbc.m, Astar.c), Z2(Rbc.m, Astar.c),
10339  Z3(Bc_adjoint.m, A.c);
10340  Z1.setConstant(0.0);
10341  Z2.setConstant(0.0);
10342  Z3.setConstant(0.0);
10343 
10344  for (int i = 0; i < Lbc.m; i++) {
10345  for (int j = 0; j < Lbc.n; j++) {
10346  Lbc.eval(i, j) = -1.0;
10347  }
10348  }
10349  for (int i = 0; i < Rbc.m; i++) {
10350  for (int j = 0; j < Rbc.n; j++) {
10351  Rbc.eval(i, j) = 1.0;
10352  }
10353  }
10354  // std::cout << "("<< Lbc.L.r << "," ")"<< << '\n';
10355  // std::cout << "Entering ::::::::::::::" << '\n';
10356  // std::cout << "BcComp: " << "(" << BcComp.m <<","<< BcComp.n<< ")" <<
10357  // '\n'; std::cout << "Lbc: " << "(" << Lbc.m <<","<< Lbc.n<< ")" << '\n';
10358  // std::cout << "Z1: " << "(" << Z1.r <<","<< Z1.c<< ")" << '\n';
10359  // std::cout << "Rbc: " << "(" << Rbc.m <<","<< Rbc.n<< ")" << '\n';
10360  // std::cout << "Z2: " << "(" << Z2.r <<","<< Z2.c<< ")" << '\n';
10361  // std::cout << "Z3: " << "(" << Z3.r <<","<< Z3.c<< ")" << '\n';
10362  // std::cout << "Bc_adjoint: " << "(" << Bc_adjoint.m <<","<< Bc_adjoint.n<<
10363  // ")" << '\n';
10364  BcComp.L << Lbc.L, Z1, //
10365  Rbc.L, Z2, //
10366  Z3, Bc_adjoint.L;
10367 
10368  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> z1(Lbc.m, Astar.c),
10369  z2(Rbc.m, Astar.c), z3(Bc_adjoint.m, A.c);
10370  z1.setConstant(0.0);
10371  z2.setConstant(0.0);
10372  z3.setConstant(0.0);
10373 
10374  BcComp.eval << Lbc.eval, z1, //
10375  Rbc.eval, z2, //
10376  z3, Bc_adjoint.eval;
10377  // std::cout << "done >>>" << std::flush << '\n';
10378 
10379  LinopMat<std::complex<T> > Mmat(Acomp.r, Acomp.c), I(A.r, A.r);
10380  I.setIdentity();
10381  Mmat << Z, I, //
10382  I, Z;
10383  // std::cout << "BcComp: \n" << '\n';
10384  // for (int i = 0; i < BcComp.m; i++) {
10385  // for (int j = 0; j < BcComp.n; j++) {
10386  // std::cout << "(" << i << "," << j << ")" << '\n';
10387  // std::cout << BcComp.L(i, j).coef << '\n';
10388  // }
10389  // }
10390  // std::cin >> bre;
10391  // std::cout << "Bccomp.eval: " << BcComp.eval << std::endl;
10392  // std::cin >> bre;
10393  GeneralizedEigenSolver<std::complex<T> >::compute(Acomp, Mmat, num_vals,
10394  BcComp);
10395  };
10396 
10404  void compute(const LinopMat<std::complex<T> > &A_,
10405  const LinopMat<std::complex<T> > &B_,
10406  const LinopMat<std::complex<T> > &C_,
10407  const BcMat<std::complex<T> > &Lbc_,
10408  const BcMat<std::complex<T> > &Rbc_, int num_vals) {
10409  int bre;
10410  LinopMat<std::complex<T> > A = A_;
10411  LinopMat<std::complex<T> > B = B_;
10412  LinopMat<std::complex<T> > C = C_;
10413  BcMat<std::complex<T> > Lbc = Lbc_;
10414  BcMat<std::complex<T> > Rbc = Rbc_;
10415  LinopMat<std::complex<T> > Astar = Adjoint(A);
10416  LinopMat<std::complex<T> > Bstar = Adjoint(B);
10417  LinopMat<std::complex<T> > Cstar = Adjoint(C);
10418  BcMat<std::complex<T> > Astar_bc = AdjointBc_analytical(A, Lbc, Rbc);
10419 
10420  // std::cout << "Astar_bc: \n" << '\n';
10421  // for (int i = 0; i < Astar_bc.m; i++) {
10422  // for (int j = 0; j < Astar_bc.n; j++) {
10423  // std::cout << "ij = (" << i << "," << j << ")" << '\n';
10424  // std::cout << Astar_bc.L(i, j).coef << '\n';
10425  // }
10426  // }
10427  // std::cin >> bre;
10428  // std::cout << "Astar_bc.eval: " << Astar_bc.eval << std::endl;
10429  // std::cin >> bre;
10430  // std::valarray<std::complex<T> > rr(N + 1);
10431  // setChebPts(rr);
10432  // for (int i = 0; i < Astar.r; i ++){
10433  // for (int j = 0; j < Astar.c;j ++){
10434  // if(Astar(i,j).NCC == 0){
10435  // std::cout << "ij = ("<< i <<"," << j << "):" << '\n';
10436  // std::cout << Astar(i,j).coef << '\n';
10437  // std::cin >> bre;
10438  // } else {
10439  // for (int k = 0; k < Astar(i,j).n + 1; k ++){
10440  // if (Astar(i,j).coefFun[k].dct_flag == SIS_PHYS_SPACE){
10441  // Astar(i,j).coefFun[k].v = Astar(i,j).coefFun[k].v / (rr);
10442  // } else {
10443  // Astar(i,j).coefFun[k].c2p();
10444  // Astar(i,j).coefFun[k].v = Astar(i,j).coefFun[k].v / (rr);
10445  // Astar(i,j).coefFun[k].p2c();
10446  // }
10447  // std::cout << "("<< i <<"," << j << "," << k << "):" << '\n';
10448  // std::cout << Astar(i,j).coefFun[k](-1) << '\n';
10449  // std::cin >> bre;
10450  // }
10451  // }
10452  // }
10453  //}
10454 
10455  BcMat<std::complex<T> > A_bc(Lbc.m + Rbc.m, Lbc.n);
10456  Lbc.eval.setConstant(-1.0);
10457  Rbc.eval.setConstant(1.0);
10458 
10459  A_bc.L << Lbc.L, //
10460  Rbc.L;
10461 
10462  A_bc.eval << Lbc.eval, //
10463  Rbc.eval; //
10464 
10465  LinopMat<std::complex<T> > BBstar, CstarC;
10466  BBstar = B * Bstar;
10467  CstarC = Cstar * C;
10468 
10469  if (svd_flag == SIS_SVD) {
10470  LinopMat<std::complex<T> > Lmat(A.r + Astar.r, A.c + Astar.c),
10471  Mmat(A.r + Astar.r, A.c + Astar.c);
10472  LinopMat<std::complex<T> > Z1(A.r, A.c), Z2(A_bc.m, Astar_bc.n),
10473  Z3(Astar_bc.m, A_bc.n);
10474  Z1.setConstant(0.0);
10475  Z2.setConstant(0.0);
10476  Z3.setConstant(0.0);
10477  Lmat << A, Z1, //
10478  Z1, Astar;
10479  Mmat << Z1, BBstar, //
10480  CstarC, Z1;
10481 
10482  BcMat<std::complex<T> > bcf(A_bc.m + Astar_bc.m, A_bc.n + A_bc.n);
10483  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> z2(A_bc.eval.rows(),
10484  Astar_bc.eval.cols()),
10485  z3(Astar_bc.eval.rows(), A_bc.eval.cols());
10486  z2.setConstant(0.0);
10487  z3.setConstant(0.0);
10488  bcf.L << A_bc.L, Z2, //
10489  Z3, Astar_bc.L;
10490  bcf.eval << A_bc.eval, z2, //
10491  z3, Astar_bc.eval;
10493  Lmat.r * (N + 1), bcf);
10495  GeneralizedEigenSolver<std::complex<T> >::sortByLargestReal();
10496  GeneralizedEigenSolver<std::complex<T> >::keep(num_vals);
10497  // GeneralizedEigenSolver<std::complex<T> >::keepConverged();
10498  // GeneralizedEigenSolver<std::complex<T> >::sortByLargestReal();
10499  } else if (svd_flag == SIS_SVD_RIGHT) {
10500  Discretize<std::complex<T> > ADis, AstarDis;
10501  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> A0, A0star,
10502  B0B0star, C0starC0, L, M, invA0, invA0star;
10503  A0 = ADis(A, A_bc);
10504  A0star = AstarDis(Astar, Astar_bc);
10505  B0B0star = AstarDis((BBstar));
10506  C0starC0 = ADis((CstarC));
10507  Eigen::ColPivHouseholderQR<
10508  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> >
10509  qr(A0star);
10510  if (!qr.isInvertible()) {
10511  std::cout << "Cannot compute the right singular vectors alone."
10512  << "Change svd_flag to SIS_SVD. Exiting ... " << '\n';
10513  exit(1);
10514  }
10515  invA0star = qr.inverse();
10516  qr.compute(A0);
10517  if (!qr.isInvertible()) {
10518  std::cout << "Cannot compute the right singular vectors alone."
10519  << "Change svd_flag to SIS_SVD. Exiting ... " << '\n';
10520  exit(1);
10521  }
10522  invA0 = qr.inverse();
10523  L = B0B0star * invA0star * C0starC0;
10524  M = A0;
10525  Eigen::ComplexEigenSolver<
10526  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> >
10527  eigs;
10528 
10530 
10532  GeneralizedEigenSolver<std::complex<T> >::sortByLargestReal();
10533  GeneralizedEigenSolver<std::complex<T> >::keep(num_vals);
10534  } else if (svd_flag == SIS_SVD_LEFT) {
10535  Discretize<std::complex<T> > ADis, AstarDis;
10536  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> A0, A0star,
10537  B0B0star, C0starC0, L, M, invA0, invA0star;
10538  A0 = ADis(A, A_bc);
10539  A0star = AstarDis(Astar, Astar_bc);
10540  B0B0star = AstarDis((BBstar));
10541  C0starC0 = ADis((CstarC));
10542  Eigen::ColPivHouseholderQR<
10543  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> >
10544  qr(A0star);
10545  if (!qr.isInvertible()) {
10546  std::cout << "Cannot compute the right singular vectors alone."
10547  << "Change svd_flag to SIS_SVD. Exiting ... " << '\n';
10548  exit(1);
10549  }
10550  invA0star = qr.inverse();
10551  qr.compute(A0);
10552  if (!qr.isInvertible()) {
10553  std::cout << "Cannot compute the right singular vectors alone."
10554  << "Change svd_flag to SIS_SVD. Exiting ... " << '\n';
10555  exit(1);
10556  }
10557  invA0 = qr.inverse();
10558  L = C0starC0 * invA0 * B0B0star;
10559 
10560  Eigen::ComplexEigenSolver<
10561  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> >
10562  eigs;
10563 
10564  GeneralizedEigenSolver<std::complex<T> >::compute(L, A0star, AstarDis);
10565 
10567  GeneralizedEigenSolver<std::complex<T> >::sortByLargestReal();
10568  GeneralizedEigenSolver<std::complex<T> >::keep(num_vals);
10569  }
10570  };
10571 
10580  std::complex<T> PowerSpectralDensity(const LinopMat<std::complex<T> > &A_,
10581  const LinopMat<std::complex<T> > &B_,
10582  const LinopMat<std::complex<T> > &C_,
10583  const BcMat<std::complex<T> > &Lbc_,
10584  const BcMat<std::complex<T> > &Rbc_) {
10585  int bre;
10586  LinopMat<std::complex<T> > A = A_;
10587  LinopMat<std::complex<T> > B = B_;
10588  LinopMat<std::complex<T> > C = C_;
10589  BcMat<std::complex<T> > Lbc = Lbc_;
10590  BcMat<std::complex<T> > Rbc = Rbc_;
10591  LinopMat<std::complex<T> > Astar = Adjoint(A);
10592  LinopMat<std::complex<T> > Bstar = Adjoint(B);
10593  LinopMat<std::complex<T> > Cstar = Adjoint(C);
10594  BcMat<std::complex<T> > Astar_bc = AdjointBc_analytical(A, Lbc, Rbc);
10595 
10596  // std::cout << "Astar_bc: \n" << '\n';
10597  // for (int i = 0; i < Astar_bc.m; i++) {
10598  // for (int j = 0; j < Astar_bc.n; j++) {
10599  // std::cout << "ij = (" << i << "," << j << ")" << '\n';
10600  // std::cout << Astar_bc.L(i, j).coef << '\n';
10601  // }
10602  // }
10603  // std::cin >> bre;
10604  // std::cout << "Astar_bc.eval: " << Astar_bc.eval << std::endl;
10605  // std::cin >> bre;
10606  // std::valarray<std::complex<T> > rr(N + 1);
10607  // setChebPts(rr);
10608  // for (int i = 0; i < Astar.r; i ++){
10609  // for (int j = 0; j < Astar.c;j ++){
10610  // if(Astar(i,j).NCC == 0){
10611  // std::cout << "ij = ("<< i <<"," << j << "):" << '\n';
10612  // std::cout << Astar(i,j).coef << '\n';
10613  // std::cin >> bre;
10614  // } else {
10615  // for (int k = 0; k < Astar(i,j).n + 1; k ++){
10616  // if (Astar(i,j).coefFun[k].dct_flag == SIS_PHYS_SPACE){
10617  // Astar(i,j).coefFun[k].v = Astar(i,j).coefFun[k].v / (rr);
10618  // } else {
10619  // Astar(i,j).coefFun[k].c2p();
10620  // Astar(i,j).coefFun[k].v = Astar(i,j).coefFun[k].v / (rr);
10621  // Astar(i,j).coefFun[k].p2c();
10622  // }
10623  // std::cout << "("<< i <<"," << j << "," << k << "):" << '\n';
10624  // std::cout << Astar(i,j).coefFun[k](-1) << '\n';
10625  // std::cin >> bre;
10626  // }
10627  // }
10628  // }
10629  //}
10630 
10631  BcMat<std::complex<T> > A_bc(Lbc.m + Rbc.m, Lbc.n);
10632  Lbc.eval.setConstant(-1.0);
10633  Rbc.eval.setConstant(1.0);
10634 
10635  A_bc.L << Lbc.L, //
10636  Rbc.L;
10637 
10638  A_bc.eval << Lbc.eval, //
10639  Rbc.eval; //
10640 
10641  LinopMat<std::complex<T> > BBstar, CstarC;
10642  BBstar = B * Bstar;
10643  CstarC = Cstar * C;
10644 
10645 
10646  Discretize<std::complex<T> > ADis, AstarDis;
10647  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> A0, A0star,
10648  B0B0star, C0starC0, L, M, invA0, invA0star;
10649  A0 = ADis(A, A_bc);
10650  A0star = AstarDis(Astar, Astar_bc);
10651  B0B0star = AstarDis((BBstar));
10652  C0starC0 = ADis((CstarC));
10653  Eigen::ColPivHouseholderQR<
10654  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> >
10655  qr(A0);
10656  if (!qr.isInvertible()) {
10657  std::cout << "Cannot compute the right singular vectors alone."
10658  << "Change svd_flag to SIS_SVD. Exiting ... "<< __LINE__ << '\n';
10659  exit(1);
10660  }
10661  invA0 = qr.inverse();
10662  qr.compute(A0star);
10663  if (!qr.isInvertible()) {
10664  std::cout << "Cannot compute the right singular vectors alone."
10665  << "Change svd_flag to SIS_SVD. Exiting ... " << __LINE__<< '\n';
10666  exit(1);
10667  }
10668 
10669  invA0star = qr.inverse();
10670  L = invA0 * B0B0star * invA0star * C0starC0;
10671  std::complex<T> tempc = L.trace();
10672  return tempc;
10673  };
10674 
10675 
10676  std::complex<T> PowerSpectralDensity(const LinopMat<std::complex<T> > &A_,
10677  const LinopMat<std::complex<T> > &B_,
10678  const LinopMat<std::complex<T> > &C_,
10679  const BcMat<std::complex<T> > &Lbc_,
10680  const BcMat<std::complex<T> > &Rbc_,
10681  const BcMat<std::complex<T> > &Lbc_adjoint_,
10682  const BcMat<std::complex<T> > &Rbc_adjoint_) {
10683  int bre;
10684  LinopMat<std::complex<T> > A = A_;
10685  LinopMat<std::complex<T> > B = B_;
10686  LinopMat<std::complex<T> > C = C_;
10687  BcMat<std::complex<T> > Lbc = Lbc_;
10688  BcMat<std::complex<T> > Rbc = Rbc_;
10689  BcMat<std::complex<T> > Lbc_adjoint = Lbc_adjoint_;
10690  BcMat<std::complex<T> > Rbc_adjoint = Rbc_adjoint_;
10691  LinopMat<std::complex<T> > Astar = Adjoint(A);
10692  LinopMat<std::complex<T> > Bstar = Adjoint(B);
10693  LinopMat<std::complex<T> > Cstar = Adjoint(C);
10694  // BcMat<std::complex<T> > Astar_bc = AdjointBc_analytical(A, Lbc, Rbc);
10695 
10696  // std::cout << "Astar_bc: \n" << '\n';
10697  // for (int i = 0; i < Astar_bc.m; i++) {
10698  // for (int j = 0; j < Astar_bc.n; j++) {
10699  // std::cout << "ij = (" << i << "," << j << ")" << '\n';
10700  // std::cout << Astar_bc.L(i, j).coef << '\n';
10701  // }
10702  // }
10703  // std::cin >> bre;
10704  // std::cout << "Astar_bc.eval: " << Astar_bc.eval << std::endl;
10705  // std::cin >> bre;
10706  // std::valarray<std::complex<T> > rr(N + 1);
10707  // setChebPts(rr);
10708  // for (int i = 0; i < Astar.r; i ++){
10709  // for (int j = 0; j < Astar.c;j ++){
10710  // if(Astar(i,j).NCC == 0){
10711  // std::cout << "ij = ("<< i <<"," << j << "):" << '\n';
10712  // std::cout << Astar(i,j).coef << '\n';
10713  // std::cin >> bre;
10714  // } else {
10715  // for (int k = 0; k < Astar(i,j).n + 1; k ++){
10716  // if (Astar(i,j).coefFun[k].dct_flag == SIS_PHYS_SPACE){
10717  // Astar(i,j).coefFun[k].v = Astar(i,j).coefFun[k].v / (rr);
10718  // } else {
10719  // Astar(i,j).coefFun[k].c2p();
10720  // Astar(i,j).coefFun[k].v = Astar(i,j).coefFun[k].v / (rr);
10721  // Astar(i,j).coefFun[k].p2c();
10722  // }
10723  // std::cout << "("<< i <<"," << j << "," << k << "):" << '\n';
10724  // std::cout << Astar(i,j).coefFun[k](-1) << '\n';
10725  // std::cin >> bre;
10726  // }
10727  // }
10728  // }
10729  //}
10730 
10731  BcMat<std::complex<T> > A_bc(Lbc.m + Rbc.m, Lbc.n), Astar_bc(Lbc_adjoint.m + Rbc_adjoint.m, Lbc_adjoint.n);
10732  Lbc.eval.setConstant(-1.0);
10733  Rbc.eval.setConstant(1.0);
10734 
10735  A_bc.L << Lbc.L, //
10736  Rbc.L;
10737 
10738  A_bc.eval << Lbc.eval, //
10739  Rbc.eval; //
10740 
10741  Astar_bc.L << Lbc_adjoint.L,//
10742  Rbc_adjoint.L;
10743  Astar_bc.eval << Lbc_adjoint.eval,//
10744  Rbc_adjoint.eval;
10745 
10746  LinopMat<std::complex<T> > BBstar, CstarC;
10747  BBstar = B * Bstar;
10748  CstarC = Cstar * C;
10749 
10750 
10751  Discretize<std::complex<T> > ADis, AstarDis;
10752  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> A0, A0star,
10753  B0B0star, C0starC0, L, M, invA0, invA0star;
10754  A0 = ADis(A, A_bc);
10755  A0star = AstarDis(Astar, Astar_bc);
10756  B0B0star = AstarDis((BBstar));
10757  C0starC0 = ADis((CstarC));
10758  Eigen::ColPivHouseholderQR<
10759  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> >
10760  qr(A0);
10761  if (!qr.isInvertible()) {
10762  std::cout << "Cannot compute the right singular vectors alone."
10763  << "Change svd_flag to SIS_SVD. Exiting ... "<< __LINE__ << '\n';
10764  exit(1);
10765  }
10766  invA0 = qr.inverse();
10767  qr.compute(A0star);
10768  if (!qr.isInvertible()) {
10769  std::cout << "Cannot compute the right singular vectors alone."
10770  << "Change svd_flag to SIS_SVD. Exiting ... " << __LINE__<< '\n';
10771  exit(1);
10772  }
10773 
10774  invA0star = qr.inverse();
10775  L = invA0 * B0B0star * invA0star * C0starC0;
10776  std::complex<T> tempc = L.trace();
10777  return tempc;
10778  };
10779 
10780 
10781  std::valarray<std::complex<T> > PowerSpectralDensityIndividual(const LinopMat<std::complex<T> > &A_,
10782  const LinopMat<std::complex<T> > &B_,
10783  const LinopMat<std::complex<T> > &C1_,
10784  const LinopMat<std::complex<T> > &C2_,
10785  const LinopMat<std::complex<T> > &C3_,
10786  const BcMat<std::complex<T> > &Lbc_,
10787  const BcMat<std::complex<T> > &Rbc_) {
10788  int bre;
10789  LinopMat<std::complex<T> > A = A_;
10790  LinopMat<std::complex<T> > B = B_;
10791  LinopMat<std::complex<T> > C1 = C1_;
10792  LinopMat<std::complex<T> > C2 = C2_;
10793  LinopMat<std::complex<T> > C3 = C3_;
10794  BcMat<std::complex<T> > Lbc = Lbc_;
10795  BcMat<std::complex<T> > Rbc = Rbc_;
10796  LinopMat<std::complex<T> > Astar = Adjoint(A);
10797  LinopMat<std::complex<T> > Bstar = Adjoint(B);
10798  LinopMat<std::complex<T> > Cstar1 = Adjoint(C1);
10799  LinopMat<std::complex<T> > Cstar2 = Adjoint(C2);
10800  LinopMat<std::complex<T> > Cstar3 = Adjoint(C3);
10801 
10802  BcMat<std::complex<T> > Astar_bc = AdjointBc_analytical(A, Lbc, Rbc);
10803 
10804  // std::cout << "Astar_bc: \n" << '\n';
10805  // for (int i = 0; i < Astar_bc.m; i++) {
10806  // for (int j = 0; j < Astar_bc.n; j++) {
10807  // std::cout << "ij = (" << i << "," << j << ")" << '\n';
10808  // std::cout << Astar_bc.L(i, j).coef << '\n';
10809  // }
10810  // }
10811  // std::cin >> bre;
10812  // std::cout << "Astar_bc.eval: " << Astar_bc.eval << std::endl;
10813  // std::cin >> bre;
10814  // std::valarray<std::complex<T> > rr(N + 1);
10815  // setChebPts(rr);
10816  // for (int i = 0; i < Astar.r; i ++){
10817  // for (int j = 0; j < Astar.c;j ++){
10818  // if(Astar(i,j).NCC == 0){
10819  // std::cout << "ij = ("<< i <<"," << j << "):" << '\n';
10820  // std::cout << Astar(i,j).coef << '\n';
10821  // std::cin >> bre;
10822  // } else {
10823  // for (int k = 0; k < Astar(i,j).n + 1; k ++){
10824  // if (Astar(i,j).coefFun[k].dct_flag == SIS_PHYS_SPACE){
10825  // Astar(i,j).coefFun[k].v = Astar(i,j).coefFun[k].v / (rr);
10826  // } else {
10827  // Astar(i,j).coefFun[k].c2p();
10828  // Astar(i,j).coefFun[k].v = Astar(i,j).coefFun[k].v / (rr);
10829  // Astar(i,j).coefFun[k].p2c();
10830  // }
10831  // std::cout << "("<< i <<"," << j << "," << k << "):" << '\n';
10832  // std::cout << Astar(i,j).coefFun[k](-1) << '\n';
10833  // std::cin >> bre;
10834  // }
10835  // }
10836  // }
10837  //}
10838 
10839  BcMat<std::complex<T> > A_bc(Lbc.m + Rbc.m, Lbc.n);
10840  Lbc.eval.setConstant(-1.0);
10841  Rbc.eval.setConstant(1.0);
10842 
10843  A_bc.L << Lbc.L, //
10844  Rbc.L;
10845 
10846  A_bc.eval << Lbc.eval, //
10847  Rbc.eval; //
10848 
10849  LinopMat<std::complex<T> > BBstar, CstarC, CstarC1, CstarC2, CstarC3;
10850  BBstar = B * Bstar;
10851  //CstarC = Cstar * C;
10852  CstarC1 = Cstar1 * C1;
10853  CstarC2 = Cstar2 * C2;
10854  CstarC3 = Cstar3 * C3;
10855 
10856 
10857  Discretize<std::complex<T> > ADis, AstarDis;
10858  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> A0, A0star,
10859  B0B0star, C0starC0,C0starC01,C0starC02,C0starC03, L, M, invA0, invA0star;
10860  A0 = ADis(A, A_bc);
10861  A0star = AstarDis(Astar, Astar_bc);
10862  B0B0star = AstarDis((BBstar));
10863  //C0starC0 = ADis((CstarC));
10864  C0starC01 = ADis((CstarC1));
10865  C0starC02 = ADis((CstarC2));
10866  C0starC03 = ADis((CstarC3));
10867 
10868  Eigen::ColPivHouseholderQR<
10869  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> >
10870  qr(A0star);
10871  if (!qr.isInvertible()) {
10872  std::cout << "Cannot compute the right singular vectors alone."
10873  << "Change svd_flag to SIS_SVD. Exiting ... " << '\n';
10874  exit(1);
10875  }
10876  invA0star = qr.inverse();
10877  qr.compute(A0);
10878  if (!qr.isInvertible()) {
10879  std::cout << "Cannot compute the right singular vectors alone."
10880  << "Change svd_flag to SIS_SVD. Exiting ... " << '\n';
10881  exit(1);
10882  }
10883 
10884  invA0 = qr.inverse();
10885  L = invA0 * B0B0star * invA0star;// * C0starC0;
10886  std::valarray<std::complex<T> > tempc(3);
10887  tempc[0] = (L*C0starC01).trace();
10888  tempc[1] = (L*C0starC02).trace();
10889  tempc[2] = (L*C0starC03).trace();
10890  return tempc;
10891  };
10901  void compute(const LinopMat<std::complex<T> > &A_,
10902  const LinopMat<std::complex<T> > &B_,
10903  const LinopMat<std::complex<T> > &C_,
10904  const BcMat<std::complex<T> > &Lbc_,
10905  const BcMat<std::complex<T> > &Rbc_,
10906  const BcMat<std::complex<T> > &Lbc_adjoint_,
10907  const BcMat<std::complex<T> > &Rbc_adjoint_, int num_vals) {
10908  int bre;
10909  LinopMat<std::complex<T> > A = A_;
10910  LinopMat<std::complex<T> > B = B_;
10911  LinopMat<std::complex<T> > C = C_;
10912  BcMat<std::complex<T> > Lbc = Lbc_;
10913  BcMat<std::complex<T> > Rbc = Rbc_;
10914  BcMat<std::complex<T> > Lbc_adjoint = Lbc_adjoint_;
10915  BcMat<std::complex<T> > Rbc_adjoint = Rbc_adjoint_;
10916  LinopMat<std::complex<T> > Astar = Adjoint(A);
10917  LinopMat<std::complex<T> > Bstar = Adjoint(B);
10918  LinopMat<std::complex<T> > Cstar = Adjoint(C);
10919 
10920  // std::cout << "Astar_bc: \n" << '\n';
10921  // for (int i = 0; i < Astar_bc.m; i++) {
10922  // for (int j = 0; j < Astar_bc.n; j++) {
10923  // std::cout << "ij = (" << i << "," << j << ")" << '\n';
10924  // std::cout << Astar_bc.L(i, j).coef << '\n';
10925  // }
10926  // }
10927  // std::cin >> bre;
10928  // std::cout << "Astar_bc.eval: " << Astar_bc.eval << std::endl;
10929  // std::cin >> bre;
10930  // std::valarray<std::complex<T> > rr(N + 1);
10931  // setChebPts(rr);
10932  // for (int i = 0; i < Astar.r; i ++){
10933  // for (int j = 0; j < Astar.c;j ++){
10934  // if(Astar(i,j).NCC == 0){
10935  // std::cout << "ij = ("<< i <<"," << j << "):" << '\n';
10936  // std::cout << Astar(i,j).coef << '\n';
10937  // std::cin >> bre;
10938  // } else {
10939  // for (int k = 0; k < Astar(i,j).n + 1; k ++){
10940  // if (Astar(i,j).coefFun[k].dct_flag == SIS_PHYS_SPACE){
10941  // Astar(i,j).coefFun[k].v = Astar(i,j).coefFun[k].v;
10942  // } else {
10943  // Astar(i,j).coefFun[k].c2p();
10944  // Astar(i,j).coefFun[k].v = Astar(i,j).coefFun[k].v;
10945  // Astar(i,j).coefFun[k].p2c();
10946  // }
10947  // std::cout << "("<< i <<"," << j << "," << k << "):" << '\n';
10948  // std::cout << Astar(i,j).coefFun[k] << '\n';
10949  // std::cin >> bre;
10950  // }
10951  // }
10952  // }
10953  // }
10954 
10955  BcMat<std::complex<T> > A_bc(Lbc.m + Rbc.m, Lbc.n);
10956  BcMat<std::complex<T> > Astar_bc(Lbc_adjoint.m + Rbc_adjoint.m,
10957  Lbc_adjoint.n);
10958  Lbc.eval.setConstant(-1.0);
10959  Rbc.eval.setConstant(1.0);
10960 
10961  Lbc_adjoint.eval.setConstant(-1.0);
10962  Rbc_adjoint.eval.setConstant(1.0);
10963 
10964  A_bc.L << Lbc.L, //
10965  Rbc.L;
10966  Astar_bc.L << Lbc_adjoint.L, //
10967  Rbc_adjoint.L;
10968 
10969  A_bc.eval << Lbc.eval, //
10970  Rbc.eval; //
10971  Astar_bc.eval << Lbc_adjoint.eval, //
10972  Rbc_adjoint.eval;
10973 
10974  LinopMat<std::complex<T> > BBstar, CstarC;
10975  BBstar = B * Bstar;
10976  CstarC = Cstar * C;
10977 
10978  if (svd_flag == SIS_SVD) {
10979  LinopMat<std::complex<T> > Lmat(A.r + Astar.r, A.c + Astar.c),
10980  Mmat(A.r + Astar.r, A.c + Astar.c);
10981  LinopMat<std::complex<T> > Z1(A.r, A.c), Z2(A_bc.m, Astar_bc.n),
10982  Z3(Astar_bc.m, A_bc.n);
10983  Z1.setConstant(0.0);
10984  Z2.setConstant(0.0);
10985  Z3.setConstant(0.0);
10986  Lmat << A, Z1, //
10987  Z1, Astar;
10988  Mmat << Z1, BBstar, //
10989  CstarC, Z1;
10990 
10991  BcMat<std::complex<T> > bcf(A_bc.m + Astar_bc.m, A_bc.n + A_bc.n);
10992  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> z2(A_bc.eval.rows(),
10993  Astar_bc.eval.cols()),
10994  z3(Astar_bc.eval.rows(), A_bc.eval.cols());
10995  z2.setConstant(0.0);
10996  z3.setConstant(0.0);
10997  bcf.L << A_bc.L, Z2, //
10998  Z3, Astar_bc.L;
10999  bcf.eval << A_bc.eval, z2, //
11000  z3, Astar_bc.eval;
11002  Lmat.r * (N + 1), bcf);
11003  // std::cout << "evals:\n"
11004  //<< GeneralizedEigenSolver<std::complex<T> >::eigenvalues << '\n';
11005  // std::cin >> bre;
11006  // std::cout << "evals:\n"
11007  //<< GeneralizedEigenSolver<std::complex<T> >::eigenvectorsMat[2][0] <<
11008  //'\n'; std::cin >> bre; std::cout << "evals:\n"
11009  //<< GeneralizedEigenSolver<std::complex<T> >::eigenvectorsMat[2][1] <<
11010  //'\n'; std::cin >> bre; std::cout << "evals:\n"
11011  //<< GeneralizedEigenSolver<std::complex<T> >::eigenvectorsMat[2][2] <<
11012  //'\n'; std::cin >> bre; std::cout << "evals:\n"
11013  //<< GeneralizedEigenSolver<std::complex<T> >::eigenvectorsMat[2][3] <<
11014  //'\n'; std::cin >> bre;
11015 
11017  // GeneralizedEigenSolver<std::complex<T> >::keepConverged();
11018  GeneralizedEigenSolver<std::complex<T> >::sortByLargestReal();
11019  GeneralizedEigenSolver<std::complex<T> >::keep(num_vals);
11020  } else if (svd_flag == SIS_SVD_RIGHT) {
11021  std::cout << "computing only right singular vectors" << '\n';
11022  Discretize<std::complex<T> > ADis, AstarDis;
11023  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> A0, A0star,
11024  B0B0star, C0starC0, L, M, invA0, invA0star;
11025  A0 = ADis(A, A_bc);
11026  A0star = AstarDis(Astar, Astar_bc);
11027  B0B0star = AstarDis((BBstar));
11028  C0starC0 = ADis((CstarC));
11029  Eigen::ColPivHouseholderQR<
11030  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> >
11031  qr(A0star);
11032  if (!qr.isInvertible()) {
11033  std::cout << "Cannot compute the right singular vectors alone."
11034  << "Change svd_flag to SIS_SVD. Exiting ... " << '\n';
11035  exit(1);
11036  }
11037  invA0star = qr.inverse();
11038 
11039  L = B0B0star * invA0star * C0starC0;
11040 
11042 
11044  GeneralizedEigenSolver<std::complex<T> >::sortByLargestReal();
11045  GeneralizedEigenSolver<std::complex<T> >::keep(num_vals);
11046  } else if (svd_flag == SIS_SVD_LEFT) {
11047  Discretize<std::complex<T> > ADis, AstarDis;
11048  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> A0, A0star,
11049  B0B0star, C0starC0, L, M, invA0, invA0star;
11050  A0 = ADis(A, A_bc);
11051  A0star = AstarDis(Astar, Astar_bc);
11052  B0B0star = AstarDis((BBstar));
11053  C0starC0 = ADis((CstarC));
11054  Eigen::ColPivHouseholderQR<
11055  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> >
11056  qr;
11057  qr.compute(A0);
11058  if (!qr.isInvertible()) {
11059  std::cout << "Cannot compute the right singular vectors alone."
11060  << "Change svd_flag to SIS_SVD. Exiting ... " << '\n';
11061  exit(1);
11062  }
11063  invA0 = qr.inverse();
11064  L = C0starC0 * invA0 * B0B0star;
11065 
11066  GeneralizedEigenSolver<std::complex<T> >::compute(L, A0star, AstarDis);
11067 
11069  GeneralizedEigenSolver<std::complex<T> >::sortByLargestReal();
11070  GeneralizedEigenSolver<std::complex<T> >::keep(num_vals);
11071  }
11072  };
11073 
11074 #ifdef SIS_USE_FEAST
11075  void feast_compute(const LinopMat<std::complex<T> > &A_,
11077  const LinopMat<std::complex<T> > &B_,
11078  const LinopMat<std::complex<T> > &C_,
11079  const BcMat<std::complex<T> > &Lbc_,
11080  const BcMat<std::complex<T> > &Rbc_,
11081  const BcMat<std::complex<T> > &Lbc_adjoint_,
11082  const BcMat<std::complex<T> > &Rbc_adjoint_) {
11083  int bre;
11084  LinopMat<std::complex<T> > A = A_;
11085  LinopMat<std::complex<T> > B = B_;
11086  LinopMat<std::complex<T> > C = C_;
11087  BcMat<std::complex<T> > Lbc = Lbc_;
11088  BcMat<std::complex<T> > Rbc = Rbc_;
11089  BcMat<std::complex<T> > Lbc_adjoint = Lbc_adjoint_;
11090  BcMat<std::complex<T> > Rbc_adjoint = Rbc_adjoint_;
11091  LinopMat<std::complex<T> > Astar = Adjoint(A);
11092  LinopMat<std::complex<T> > Bstar = Adjoint(B);
11093  LinopMat<std::complex<T> > Cstar = Adjoint(C);
11094 
11095  BcMat<std::complex<T> > A_bc(Lbc.m + Rbc.m, Lbc.n);
11096  BcMat<std::complex<T> > Astar_bc(Lbc_adjoint.m + Rbc_adjoint.m,
11097  Lbc_adjoint.n);
11098  Lbc.eval.setConstant(-1.0);
11099  Rbc.eval.setConstant(1.0);
11100 
11101  Lbc_adjoint.eval.setConstant(-1.0);
11102  Rbc_adjoint.eval.setConstant(1.0);
11103 
11104  A_bc.L << Lbc.L, //
11105  Rbc.L;
11106  Astar_bc.L << Lbc_adjoint.L, //
11107  Rbc_adjoint.L;
11108 
11109  A_bc.eval << Lbc.eval, //
11110  Rbc.eval; //
11111  Astar_bc.eval << Lbc_adjoint.eval, //
11112  Rbc_adjoint.eval;
11113 
11114  LinopMat<std::complex<T> > BBstar, CstarC;
11115  BBstar = B * Bstar;
11116  CstarC = Cstar * C;
11117 
11118  LinopMat<std::complex<T> > Lmat(A.r + Astar.r, A.c + Astar.c),
11119  Mmat(A.r + Astar.r, A.c + Astar.c);
11120  LinopMat<std::complex<T> > Z1(A.r, A.c), Z2(A_bc.m, Astar_bc.n),
11121  Z3(Astar_bc.m, A_bc.n);
11122  Z1.setConstant(0.0);
11123  Z2.setConstant(0.0);
11124  Z3.setConstant(0.0);
11125  Lmat << A, Z1, //
11126  Z1, Astar;
11127  Mmat << Z1, BBstar, //
11128  CstarC, Z1;
11129 
11130  BcMat<std::complex<T> > bcf(A_bc.m + Astar_bc.m, A_bc.n + A_bc.n);
11131  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> z2(A_bc.eval.rows(),
11132  Astar_bc.eval.cols()),
11133  z3(Astar_bc.eval.rows(), A_bc.eval.cols());
11134  z2.setConstant(0.0);
11135  z3.setConstant(0.0);
11136  bcf.L << A_bc.L, Z2, //
11137  Z3, Astar_bc.L;
11138  bcf.eval << A_bc.eval, z2, //
11139  z3, Astar_bc.eval;
11140 
11141  GeneralizedEigenSolver<std::complex<T> >::feast_compute(Mmat, Lmat, 10,
11142  bcf);
11143  // GeneralizedEigenSolver<std::complex<T> >::removeInf();
11144  GeneralizedEigenSolver<std::complex<T> >::sortByLargestReal();
11145 
11146  // std::cout << "evals:\n"
11147  //<< GeneralizedEigenSolver<std::complex<T> >::eigenvalues << '\n';
11148  // std::cin >> bre;
11149  // std::cout << "evals:\n"
11150  //<< GeneralizedEigenSolver<std::complex<T> >::eigenvectorsMat[2][0] <<
11151  //'\n'; std::cin >> bre; std::cout << "evals:\n"
11152  //<< GeneralizedEigenSolver<std::complex<T> >::eigenvectorsMat[2][1] <<
11153  //'\n'; std::cin >> bre; std::cout << "evals:\n"
11154  //<< GeneralizedEigenSolver<std::complex<T> >::eigenvectorsMat[2][2] <<
11155  //'\n'; std::cin >> bre; std::cout << "evals:\n"
11156  //<< GeneralizedEigenSolver<std::complex<T> >::eigenvectorsMat[2][3] <<
11157  //'\n'; std::cin >> bre;
11158  };
11159 #endif
11160  void HinfNorm(const LinopMat<std::complex<T> > &E_,
11168  const LinopMat<std::complex<T> > &A_,
11169  const LinopMat<std::complex<T> > &B_,
11170  const LinopMat<std::complex<T> > &C_,
11171  const BcMat<std::complex<T> > &Lbc_,
11172  const BcMat<std::complex<T> > &Rbc_,
11173  const BcMat<std::complex<T> > &Lbc_adjoint_,
11174  const BcMat<std::complex<T> > &Rbc_adjoint_) {
11175  // An initial guess to omega.
11176  double seed = 10.0;
11177  omega_opt = seed;
11178  int bre;
11179 
11180  std::complex<T> ii(0.0, 1.0);
11181  LinopMat<std::complex<T> > E = E_;
11182  LinopMat<std::complex<T> > A = A_;
11183  LinopMat<std::complex<T> > B = B_;
11184  LinopMat<std::complex<T> > C = C_;
11185  BcMat<std::complex<T> > Lbc = Lbc_;
11186  BcMat<std::complex<T> > Rbc = Rbc_;
11187  BcMat<std::complex<T> > Lbc_adjoint = Lbc_adjoint_;
11188  BcMat<std::complex<T> > Rbc_adjoint = Rbc_adjoint_;
11189  LinopMat<std::complex<T> > Estar = Adjoint(E);
11190  LinopMat<std::complex<T> > Astar = Adjoint(A);
11191  LinopMat<std::complex<T> > Bstar = Adjoint(B);
11192  LinopMat<std::complex<T> > Cstar = Adjoint(C);
11193  LinopMat<std::complex<T> > BBstar = B * Bstar;
11194  LinopMat<std::complex<T> > CstarC = Cstar * C;
11195  LinopMat<std::complex<T> > A2, A2star, HamiltonL, HamiltonM;
11196  BcMat<std::complex<T> > A_bc(Lbc.m + Rbc.m, Lbc.n);
11197  BcMat<std::complex<T> > Astar_bc(Lbc_adjoint.m + Rbc_adjoint.m,
11198  Lbc_adjoint.n);
11199 
11200  A_bc.L << Lbc.L, //
11201  Rbc.L;
11202  Astar_bc.L << Lbc_adjoint.L, //
11203  Rbc_adjoint.L;
11204 
11205  A_bc.eval << Lbc.eval, //
11206  Rbc.eval; //
11207  Astar_bc.eval << Lbc_adjoint.eval, //
11208  Rbc_adjoint.eval;
11209 
11210  BcMat<std::complex<T> > bcf(A_bc.m + Astar_bc.m, A_bc.n + A_bc.n);
11211  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> z2(A_bc.eval.rows(),
11212  Astar_bc.eval.cols()),
11213  z3(Astar_bc.eval.rows(), A_bc.eval.cols());
11214  z2.setConstant(0.0);
11215  z3.setConstant(0.0);
11216  LinopMat<std::complex<T> > Z1(A.r, A.c), Z2(A_bc.m, Astar_bc.n),
11217  Z3(Astar_bc.m, A_bc.n);
11218  Z1.setConstant(0.0);
11219  Z2.setConstant(0.0);
11220  Z3.setConstant(0.0);
11221 
11222  bcf.L << A_bc.L, Z2, //
11223  Z3, Astar_bc.L;
11224  bcf.eval << A_bc.eval, z2, //
11225  z3, Astar_bc.eval;
11226 
11227  double gamma_lb, gamma_ub, gamma;
11228  double Hinf_eps = 1e-4;
11229 
11230  A2 = (ii * omega_opt * E) - A;
11231  compute(A2, B, C, Lbc, Rbc, Lbc_adjoint, Rbc_adjoint, A2.r * (N + 1));
11232  gamma_lb = GeneralizedEigenSolver<std::complex<T> >::eigenvalues[0].real();
11233  // gamma_lb= std::sqrt(gamma_lb);
11234  while (true) {
11235  gamma = (1.0 + 2.0 * Hinf_eps) * gamma_lb;
11236  std::cout << "gamma : " << gamma << '\n';
11237  // std::cin >> bre;
11238  // std::cout << "A: ("<< A.r <<"," << A.c << ")" << '\n';
11239  // std::cout << "BBstar: ("<< BBstar.r <<"," << BBstar.c << ")" << '\n';
11240  // std::cout << "CstarC: ("<< CstarC.r <<"," << CstarC.c << ")" << '\n';
11241  // std::cout << "Astar: ("<< Astar.r <<"," << Astar.c << ")" << '\n';
11242  // std::cin >> bre;
11243 
11244  HamiltonL.resize(2 * A2.r, 2 * A2.c);
11245  HamiltonM.resize(2 * A2.r, 2 * A2.c);
11246  HamiltonL << A, (BBstar / (-gamma * gamma)), //
11247  CstarC, Astar;
11248  HamiltonM << E, Z1, //
11249  Z1, Estar;
11250  GeneralizedEigenSolver<std::complex<T> >::compute(HamiltonL, HamiltonM,
11251  4 * A.r * (N + 1), bcf);
11252  // GeneralizedEigenSolver<std::complex<T> >::keepConverged();
11253  GeneralizedEigenSolver<std::complex<T> >::sortByLargestReal();
11254  std::ofstream outf("eval_saver.txt");
11255 
11256  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> mattemp(
11257  GeneralizedEigenSolver<std::complex<T> >::eigenvalues.rows(), 2);
11258  mattemp << GeneralizedEigenSolver<std::complex<T> >::alpha,
11259  GeneralizedEigenSolver<std::complex<T> >::beta;
11260 
11261  std::cout << "eigenvalues from Hamiltonian: \n"
11262  << GeneralizedEigenSolver<std::complex<T> >::eigenvalues
11263  << '\n';
11264  outf << "eigenvalues from Hamiltonian: \n" << mattemp << '\n';
11265 
11266  outf.close();
11267  std::cin >> bre;
11268  std::vector<T> omegas;
11269  for (int i = 0;
11270  i < GeneralizedEigenSolver<std::complex<T> >::eigenvalues.size();
11271  i = i + 1) {
11272  if (std::abs(GeneralizedEigenSolver<std::complex<T> >::eigenvalues[i]
11273  .imag()) < 1e-9) {
11274  omegas.push_back(std::abs(
11275  GeneralizedEigenSolver<std::complex<T> >::eigenvalues[i].real()));
11276  }
11277  }
11278  if (omegas.size() == 0) {
11279  A2 = (ii * omega_opt * E) - A;
11280  int num_vals = A2.r * 2 * (N + 1);
11281  compute(A2, B, C, Lbc, Rbc, Lbc_adjoint, Rbc_adjoint, num_vals);
11282  gamma_ub = gamma;
11283  break;
11284  }
11285 
11286  std::sort(omegas.begin(), omegas.end());
11287  std::valarray<T> ms;
11288  ms.resize(omegas.size() - 1);
11289  for (int i = 0; i < omegas.size() - 1; i++) {
11290  ms[i] = (omegas[i] + omegas[i + 1]) / 2.0;
11291  std::cout << "ms[" << i << "] : " << ms[i] << '\n';
11292  }
11293  omegas.clear();
11294  std::vector<std::vector<T> > gammas;
11295  gammas.resize(ms.size());
11296  for (int i = 0; i < ms.size(); i++) {
11297  // std::cout << "ms["<< i << "] : " << ms[i] << '\n';
11298  A2 = (ii * ms[i] * E) - A;
11299  int num_vals = A2.r * 2 * (N + 1);
11300  compute(A2, B, C, Lbc, Rbc, Lbc_adjoint, Rbc_adjoint, num_vals);
11301  // std::cout << "in " << __LINE__ << '\n';
11302  gammas[i].resize(2);
11303  // std::cout << "size: " << GeneralizedEigenSolver<std::complex<T>
11304  // >::eigenvalues.size() << '\n';
11305  gammas[i][0] =
11306  GeneralizedEigenSolver<std::complex<T> >::eigenvalues[0].real();
11307  gammas[i][1] = i;
11308  }
11309 
11310  std::sort(gammas.begin(), gammas.end());
11311  std::cout << "gamma end: " << gammas[gammas.size() - 1][0] << '\n';
11312  std::cout << "gamma 0: " << gammas[0][0] << '\n';
11313  std::cin >> bre;
11314  gamma_lb = gammas[gammas.size() - 1][0];
11315  omega_opt = ms[gammas[gammas.size() - 1][1]];
11316  std::cout << "omega_opt = " << omega_opt << '\n';
11317  }
11318  gamma_opt = (gamma_lb + gamma_ub) / 2.0;
11319  }
11320 
11327  LinopMat<std::complex<T> > Adjoint(const LinopMat<std::complex<T> > &Lmat_) {
11328  int bre;
11329  LinopMat<std::complex<T> > Lmat = Lmat_;
11330  int r = Lmat.r;
11331  int c = Lmat.c;
11332  // std::cin >> bre;
11333  LinopMat<std::complex<T> > outLmat;
11334  std::vector<int> highest_each_columnL;
11335  highest_each_columnL.resize(c);
11336  std::vector<int> temp_vec_int;
11337  temp_vec_int.resize(r);
11338  std::vector<int> alphaSize;
11339  int total_of_all_orders = 0;
11340 
11341  int counter = 0;
11342  for (int j = 0; j < c; j++) {
11343  for (int i = 0; i < r; i++) {
11344  temp_vec_int[i] = Lmat(i, j).n;
11345  }
11346  highest_each_columnL[j] =
11347  *std::max_element(temp_vec_int.begin(), temp_vec_int.end());
11348  }
11349 
11350  for (int i = 0; i < c; i++) {
11351  total_of_all_orders += highest_each_columnL[i];
11352  }
11353  int n = *std::max_element(highest_each_columnL.begin(),
11354  highest_each_columnL.end());
11355  // n is the overall order.
11356  // std::cout << "Total of all orders = " << total_of_all_orders << '\n';
11357  // std::cin >> bre;
11358  std::valarray<ChebfunMat<std::complex<T> > > alphais;
11359  std::valarray<ChebfunMat<std::complex<T> > > betais;
11360  outLmat.resize(Lmat.c, Lmat.r);
11361  alphais.resize(n + 1);
11362  betais.resize(n + 1);
11363  int outer_counter = 0;
11364  // Assign alphais
11365  for (int k = 0; k < n + 1; k++) {
11366  alphais[k].resize(Lmat.r, Lmat.c);
11367  alphais[k].setConstant(0.0);
11368  for (int i = 0; i < Lmat.r; i++) {
11369  for (int j = 0; j < Lmat.c; j++) {
11370  if (Lmat(i, j).n - k >= 0) {
11371  if (Lmat(i, j).NCC == 0) {
11372  alphais[k](i, j) = Lmat(i, j).coef[Lmat(i, j).n - k];
11373 
11374  } else {
11375  alphais[k](i, j) = Lmat(i, j).coefFun[Lmat(i, j).n - k];
11376  }
11377  }
11378  }
11379  }
11380  }
11381  /*std::cout << "alphais[0](0,0).coef" << '\n';
11382  std::cout << alphais[0](0, 0) << '\n';
11383  std::cout << alphais[1](0, 0) << '\n';
11384  std::cout << alphais[2](0, 0) << '\n';
11385  */
11386  // if (ind == 2) {
11387  // std::cout << "in " << __LINE__ << '\n';
11388  // for (int k = 0; k < alphais.size(); k++) {
11389  // for (int i = 0; i < 2; i++) {
11390  // for (int j = 0; j < 2; j++) {
11391  // std::cout << alphais[k](i, j) << '\n';
11392  // std::cout << "(" << i << "," << j << ")" << '\n';
11393  // std::cout << "k: " << k << '\n';
11394  // // std::cin >> bre;
11395  // }
11396  // }
11397  // }
11398  // }
11400  // std::cin >> bre;
11402  // Then Multiply binomial coefficients and assign to betais.
11403  for (int i = 0; i < n + 1; i++) {
11404  betais[i].resize(Lmat.r, Lmat.c);
11405  betais[i].setConstant(0.0);
11406  for (int j = i; j < n + 1; j++) {
11407  betais[i] =
11408  betais[i] + (pow(-1, j) * nck(j, i) * diff(alphais[j], j - i));
11409  }
11410  }
11411 
11412  /*std::cout << "Im in " << __LINE__ << '\n';
11413  std::cout << "betais[0](0,0).coef" << '\n';
11414  std::cout << betais[0](0, 0) << '\n';
11415  std::cout << betais[1](0, 0) << '\n';
11416  std::cout << betais[2](0, 0) << '\n';
11417  */
11418  // take the cTranspose, we will represent betais same as betais_star.
11419  for (int i = 0; i < n + 1; i++) {
11420  betais[i] = betais[i].cTranspose();
11421  }
11422 
11423  // if (ind == 2) {
11424  // std::cout << "in " << __LINE__ << '\n';
11425  // for (int k = 0; k < betais.size(); k++) {
11426  // for (int i = 0; i < 2; i++) {
11427  // for (int j = 0; j < 2; j++) {
11428  // std::cout << betais[k](i, j) << '\n';
11429  // std::cout << "(" << i << "," << j << ")" << '\n';
11430  // std::cout << "k: " << k << '\n';
11431  // // std::cin >> bre;
11432  // }
11433  // }
11434  // }
11435  // }
11436  // Now, assemble the adjoint operator from betais_star
11437  // Assign alphais.
11439  for (int i = 0; i < Lmat.c; i++) {
11440  for (int j = 0; j < Lmat.r; j++) {
11441  outLmat(i, j).ncc(n);
11442  for (int k = 0; k < n + 1; k++) {
11443  outLmat(i, j).coefFun[n - k] = betais[k](i, j);
11444  }
11445  }
11446  }
11447  // std::cout << "in Adjoint::::::" << '\n';
11448  // for (int i = 0; i < outLmat.r; i ++){
11449  // for (int j = 0; j < outLmat.c; j ++){
11450  // for (int k = 0; k < outLmat(i,j).n + 1; k ++){
11451  // std::cout << "ijk: ("<< i <<","<<j<<","<<k<< ")" << '\n';
11452  // std::cout << outLmat(i,j).coefFun[k] << '\n';
11453  // std::cin >> bre;
11454  // }
11455  // }
11456  // }
11457  // // Reduce the orders so that orders of Linops are reduced according to
11458  // a
11459  // transpose of orders.
11460  LinopMat<std::complex<T> > tempMat(outLmat.r, outLmat.c);
11461  for (int i = 0; i < outLmat.r; i++) {
11462  for (int j = 0; j < outLmat.c; j++) {
11463  tempMat(i, j).ncc(Lmat(j, i).n);
11464  for (int k = 0; k < Lmat(j, i).n + 1; k++) {
11465  tempMat(i, j).coefFun[Lmat(j, i).n - k] =
11466  outLmat(i, j).coefFun[outLmat(i, j).n - k];
11467  }
11468  }
11469  }
11470  // total_of_all_orders = 0;
11471 
11472  // counter = 0;
11473  // for (int j = 0; j < c; j++) {
11474  // for (int i = 0; i < r; i++) {
11475  // temp_vec_int[i] = Lmat(i, j).n;
11476  // }
11477  // highest_each_columnL[j] =
11478  // *std::max_element(temp_vec_int.begin(), temp_vec_int.end());
11479  // std::cout << "hecl["<< j << "]: " << highest_each_columnL[j] << '\n';
11480  // }
11481 
11482  // for (int i = 0; i < c; i++) {
11483  // total_of_all_orders += highest_each_columnL[i];
11484  // }
11485  // n = *std::max_element(highest_each_columnL.begin(),
11486  // highest_each_columnL.end());
11487 
11488  return tempMat;
11489  };
11490 
11501 
11502  // \todo It is possible to have incosistent equations and yet find an Adjoint
11503  // bc that compensates for the rank deficiency.
11505  AdjointBc_analytical(const LinopMat<std::complex<T> > &Lmat_,
11506  const BcMat<std::complex<T> > &Lbc_,
11507  const BcMat<std::complex<T> > &Rbc_) {
11508  int bre;
11509  LinopMat<std::complex<T> > Lmat = Lmat_;
11510  BcMat<std::complex<T> > Lbc = Lbc_;
11511  BcMat<std::complex<T> > Rbc = Rbc_;
11512  int r = Lmat.r;
11513  int c = Lmat.c;
11514  std::vector<int> highest_each_columnL;
11515  highest_each_columnL.resize(c);
11516  std::vector<int> temp_vec_int;
11517  temp_vec_int.resize(r);
11518  std::vector<int> alphaSize;
11519  int total_of_all_orders = 0;
11520 
11521  int counter = 0;
11522  for (int j = 0; j < c; j++) {
11523  for (int i = 0; i < r; i++) {
11524  temp_vec_int[i] = Lmat(i, j).n;
11525  }
11526  highest_each_columnL[j] =
11527  *std::max_element(temp_vec_int.begin(), temp_vec_int.end());
11528  }
11529 
11530  for (int i = 0; i < c; i++) {
11531  total_of_all_orders += highest_each_columnL[i];
11532  }
11533  int n = *std::max_element(highest_each_columnL.begin(),
11534  highest_each_columnL.end());
11535  // n is the overall order.
11536  // std::cin >> bre;
11537  std::valarray<ChebfunMat<std::complex<T> > > alphais;
11538  std::valarray<ChebfunMat<std::complex<T> > > betais;
11539  alphais.resize(n + 1);
11540  betais.resize(n + 1);
11541  int outer_counter = 0;
11542  // Assign alphais
11543  for (int k = 0; k < n + 1; k++) {
11544  alphais[k].resize(Lmat.r, Lmat.c);
11545  alphais[k].setConstant(0.0);
11546  for (int i = 0; i < Lmat.r; i++) {
11547  for (int j = 0; j < Lmat.c; j++) {
11548  if (Lmat(i, j).n - k >= 0) {
11549  if (Lmat(i, j).NCC == 0) {
11550  alphais[k](i, j) = Lmat(i, j).coef[Lmat(i, j).n - k];
11551  } else {
11552  alphais[k](i, j) = Lmat(i, j).coefFun[Lmat(i, j).n - k];
11553  }
11554  }
11555  }
11556  }
11557  }
11558  // Need a 2D vector of ChebfunMats, storing in row major format.
11559  //
11560  std::valarray<ChebfunMat<std::complex<T> > > Amat;
11561  Amat.resize(n * n);
11562  for (int i = 0; i < n * n; i++) {
11563  Amat[i].resize(Lmat.r, Lmat.c);
11564  Amat[i].setConstant(0.0);
11565  }
11567  for (int i = 0; i < n; i++) {
11568  for (int j = 0; j < n - i; j++) {
11569  for (int k = i; k < n - j; k++) {
11570  Amat[i * n + j] = Amat[i * n + j] + (pow(-1, k) * nck(k, i) *
11571  diff(alphais[k + j + 1], k - i));
11572  }
11573  }
11574  }
11575 
11576  if (isSingular) {
11577  std::valarray<std::complex<double> > rr(N + 1);
11578  setChebPts(rr);
11579  r = 0.5 * r + 0.5;
11580  for (int i = 0; i < n * n; i++) {
11581  for (int l = 0; l < Amat[i].r; l++) {
11582  for (int m = 0; m < Amat[i].c; m++) {
11583  if (Amat[i](l, m).dct_flag == SIS_PHYS_SPACE) {
11584  Amat[i](l, m).v = Amat[i](l, m).v / (rr * rr);
11585  } else {
11586  Amat[i](l, m).c2p();
11587  Amat[i](l, m).v = Amat[i](l, m).v / (rr * rr);
11588  Amat[i](l, m).p2c();
11589  }
11590  }
11591  }
11592  }
11593  }
11594  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> Aplus(n * r,
11595  n * r),
11596  Aminus(n * r, n * r);
11597 
11598  Aplus = feval2D(Amat, n, n, 1.0);
11599  Aminus = feval2D(Amat, n, n, -1.0);
11600  // std::cout << "Aplus : \n" << Aplus << '\n';
11601  // std::cout << "Aminus : \n" << Aminus << '\n';
11602  // std::cin >> bre;
11603  Amat.resize(0);
11604  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> Blbc(
11605  Lbc.m, n * Lbc.n),
11606  Brbc(Rbc.m, n * Rbc.n);
11607  Blbc.setConstant(0.0);
11608  Brbc.setConstant(0.0);
11610  for (int k = 0; k < n + 1; k++) {
11611  for (int i = 0; i < Lbc.m; i++) {
11612  for (int j = 0; j < Lbc.n; j++) {
11613  if (Lbc.L(i, j).n - k >= 0) {
11614  if (Lbc.L(i, j).NCC == 0) {
11615  // std::cout << "(" << i << "," << j << "," << k << ")"
11616  // << '\n';
11617  Blbc(i, Lbc.n * k + j) = Lbc.L(i, j).coef[Lbc.L(i, j).n - k];
11618  // std::cout << "Blbc: \n" << Blbc << '\n';
11619  // std::cin >> bre;
11620  } else {
11621  std::cout << "boundary conditions cannot have non-constant"
11622  << "coefficients" << '\n';
11623  exit(1);
11624  }
11625  }
11626  }
11627  }
11628  }
11629  for (int k = 0; k < n + 1; k++) {
11630  for (int i = 0; i < Rbc.m; i++) {
11631  for (int j = 0; j < Rbc.n; j++) {
11632  if (Rbc.L(i, j).n - k >= 0) {
11633  if (Rbc.L(i, j).NCC == 0) {
11634  Brbc(i, Rbc.n * k + j) = Rbc.L(i, j).coef[Rbc.L(i, j).n - k];
11638  } else {
11639  std::cout << "boundary conditions cannot have non-constant"
11640  << "coefficients" << '\n';
11641  exit(1);
11642  }
11643  }
11644  }
11645  }
11646  }
11647  // std::cout << "blbc:" << size(Blbc) << '\n';
11648  // std::cout << "blbc: \n" << Blbc << '\n';
11649  Eigen::CompleteOrthogonalDecomposition<
11650  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> >
11651  cod;
11652  cod.compute(Blbc);
11653  if (cod.rank() != Blbc.rows()) {
11654  std::cout << "the bounndary conditions are not linearly independent."
11655  << "Exiting ..." << '\n';
11656  exit(1);
11657  }
11658  // Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> forcL(
11659  // lbc_val.size(), 1),
11660  // forcR(rbc_val.size(), 1);
11661  // for (int i = 0; i < lbc_val.size(); i++) {
11662  // forcL(i, 0) = lbc_val[i];
11663  // }
11664  // for (int i = 0; i < rbc_val.size(); i++) {
11665  // forcR(i, 0) = rbc_val[i];
11666  // }
11667 
11668  // Find the particular solutions:
11669  // Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic>
11670  // minNormSol_lbc = cod.solve(forcL);
11672  // Find the null-space:
11673  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> V =
11674  cod.matrixZ().adjoint();
11675  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> Null_space =
11676  V.block(0, cod.rank(), V.rows(), V.cols() - cod.rank());
11677  Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic> P = cod.colsPermutation();
11678  Null_space = P * Null_space;
11679  // std::cout << "Null_space:" << size(Null_space) << '\n';
11680  cod.compute(Null_space);
11681  // std::cout << "rank of Null: " << cod.rank() << '\n';
11682 
11683  // Determine as many LI solutions using the Null-space.
11684  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> solutionL(
11685  Null_space.rows(), Null_space.cols());
11686  // for (int i = 0; i < Null_space.cols(); i++) {
11687  // solutionL.col(i) = Null_space.col(i) + minNormSol_lbc;
11688  //}
11689  solutionL = Null_space;
11690  // Do the same for RBC:
11691  cod.compute(Brbc);
11692  if (cod.rank() != Brbc.rows()) {
11693  std::cout << "the bounndary conditions are not linearly independent."
11694  << "Exiting ..." << '\n';
11695  exit(1);
11696  }
11697  // Find the particular solutions:
11698  // Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic>
11699  // minNormSol_rbc = cod.solve(forcR);
11700 
11701  // Find the null-space:
11702  V = cod.matrixZ().adjoint();
11703 
11704  Null_space = V.block(0, cod.rank(), V.rows(), V.cols() - cod.rank());
11705 
11706  P = cod.colsPermutation();
11707 
11708  Null_space = P * Null_space;
11709 
11710  // Determine as many LI solutions using the Null-space.
11711  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> solutionR(
11712  Null_space.rows(), Null_space.cols());
11713  // for (int i = 0; i < Null_space.cols(); i++) {
11714  // solutionR.col(i) = Null_space.col(i) + minNormSol_rbc;
11715  //}
11716  solutionR = Null_space;
11717 
11718  // Now determine the boundary conditions in lbc:
11719  solutionL.adjointInPlace();
11720  Aminus.adjointInPlace();
11721  cod.compute(Aminus);
11722 
11723  // std::cout << " size of Aminus:" << size(Aminus) << " rank of Aminus: "
11724  // << cod.rank() << '\n'; std::cin >> bre;
11725  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic>
11726  lbc1 = solutionL * Aminus,
11727  Ptemp, lbc;
11728  // std::cout << "lbc1: \n" << lbc1 << '\n';
11729  // std::cout << "in :::::; :::::" << '\n';
11730  // std::cin >> bre;
11731  cod.compute(lbc1.transpose());
11732  Ptemp = cod.colsPermutation();
11733  lbc1 = Ptemp * lbc1;
11734  lbc = lbc1.block(0, 0, cod.rank(), lbc1.cols());
11735 
11736  solutionR.adjointInPlace();
11737  Aplus.adjointInPlace();
11738  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic>
11739  rbc1 = solutionR * Aplus,
11740  Ptemp2, rbc;
11741  cod.compute(rbc1.transpose());
11742  Ptemp2 = cod.colsPermutation();
11743  rbc1 = Ptemp2 * rbc1;
11744  rbc = rbc1.block(0, 0, cod.rank(), rbc1.cols());
11745 
11746  // The lbc and rbc are now in the basis u1, u2, express in the normal basis:
11747  BcMat<std::complex<T> > out;
11748  out.resize(lbc.rows() + rbc.rows(), Lmat.r);
11752  for (int i = 0; i < lbc.rows(); i++) {
11753  for (int j = 0; j < Lmat.c; j++) {
11754  out.L(i, j).set(n - 1);
11755  out.eval(i, j) = -1.0;
11756  for (int k = 0; k < n; k++) {
11757  out.L(i, j).coef[n - k - 1] = lbc(i, Lmat.c * k + j);
11758  }
11759  }
11760  }
11761 
11762  for (int i = 0; i < rbc.rows(); i++) {
11763  for (int j = 0; j < Lmat.c; j++) {
11764  out.L(i + lbc.rows(), j).set(n - 1);
11765  out.eval(i + lbc.rows(), j) = 1.0;
11766  for (int k = 0; k < n; k++) {
11768  out.L(i + lbc.rows(), j).coef[n - k - 1] = rbc(i, Lmat.c * k + j);
11769  }
11770  }
11771  }
11772 
11773  // This is to filter out higher derivatives in the boundary conditions,
11774  BcMat<std::complex<T> > tempMat(out.m, out.n);
11775  for (int i = 0; i < out.m; i++) {
11776  for (int j = 0; j < out.n; j++) {
11777  tempMat.L(i, j).set(highest_each_columnL[j] - 1);
11778  for (int k = 0; k < highest_each_columnL[j]; k++) {
11779  tempMat.L(i, j).coef[highest_each_columnL[j] - k - 1] =
11780  out.L(i, j).coef[out.L(i, j).n - k];
11781  }
11782  }
11783  }
11784  tempMat.eval = out.eval;
11785 
11786  // std::cout << "out: \n" << '\n';
11787  // for (int i = 0; i < out.m; i++) {
11788  // for (int j = 0; j < out.n; j++) {
11789  // std::cout << "(" << i << "," << j << ")" << '\n';
11790  // std::cout << out.L(i, j).coef << '\n';
11791  // }
11792  // }
11793  // std::cout << "out.eval: \n" << out.eval << '\n';
11794  // std::cout << "in " << __LINE__ << '\n';
11795 
11796  // return the expression for boundary conditions:
11797  return tempMat;
11798  };
11799 };
11800 
11806 void vtkExportCartesian2D3C(const std::string &flnm,
11807  const std::valarray<double> &y,
11808  const std::valarray<double> &z,
11809  const std::valarray<double> &u,
11810  const std::valarray<double> &v,
11811  const std::valarray<double> &w,
11812  const std::valarray<double> &p) {
11813  std::string filename;
11814  filename = flnm + ".vtk";
11815  std::ofstream outf(filename);
11816  int Nz = z.size();
11817  int Ny = y.size();
11818  outf << "# vtk DataFile Version 2.0\n"
11819  << "2D3C velocity vector data \n"
11820  << "ASCII" << '\n'
11821  << "DATASET RECTILINEAR_GRID\n"
11822  << "DIMENSIONS " << 1 << " " << Ny << " " << Nz << "\n"
11823  << "X_COORDINATES " << 1 << " double\n";
11824  outf << 0.0 << " "
11825  << "\n"
11826  << "Y_COORDINATES " << Ny << " double\n";
11827  for (int i = 0; i < Ny; i++) {
11828  outf << y[i] << " ";
11829  }
11830  outf << "\n"
11831  << "Z_COORDINATES " << Nz << " double\n";
11832  for (int i = 0; i < Nz; i++) {
11833  outf << z[i] << " ";
11834  }
11835  outf << "\n\n"
11836  << "POINT_DATA " << Nz * (Ny) << "\n"
11837  << "SCALARS pressure double 1\n"
11838  << "LOOKUP_TABLE default\n";
11839  for (int j = 0; j < Nz; j++) {
11840  for (int i = 0; i < Ny; i++) {
11841  outf << p[(Ny)*i + j] << "\t";
11842  }
11843  outf << "\n";
11844  }
11845  outf << "\n\n"
11846  << "VECTORS Velocity double\n";
11847  for (int j = 0; j < Nz; j++) {
11848  for (int i = 0; i < Ny; i++) {
11849  outf << u[Nz * i + j] << " " << v[Nz * i + j] << " " << w[Nz * i + j]
11850  << "\n";
11851  }
11852  outf << "\n";
11853  }
11854 
11855  outf.close();
11856 }
11857 
11863  const std::string &flnm, const std::valarray<double> &x,
11864  const std::valarray<double> &y, const std::valarray<double> &z,
11865  const std::valarray<double> &u, const std::valarray<double> &v,
11866  const std::valarray<double> &w, const std::valarray<double> &p) {
11867  std::string filename;
11868  filename = flnm + ".vtk";
11869  std::ofstream outf(filename);
11870  int Nz = z.size();
11871  int Nx = x.size();
11872  int Ny = y.size();
11873  outf << "# vtk DataFile Version 2.0\n"
11874  << "3D velocity vector data \n"
11875  << "ASCII" << '\n'
11876  << "DATASET RECTILINEAR_GRID\n"
11877  << "DIMENSIONS " << Nx << " " << Ny << " " << Nz << "\n"
11878  << "X_COORDINATES " << Nx << " double\n";
11879  for (int i = 0; i < Nx; i++) {
11880  outf << x[i] << " ";
11881  }
11882  outf << "\n"
11883  << "Y_COORDINATES " << Ny << " double\n";
11884  for (int i = 0; i < Ny; i++) {
11885  outf << y[i] << " ";
11886  }
11887  outf << "\n"
11888  << "Z_COORDINATES " << Nz << " double\n";
11889  for (int i = 0; i < Nz; i++) {
11890  outf << z[i] << " ";
11891  }
11892  outf << "\n\n"
11893  << "POINT_DATA " << Nx * Nz * (Ny) << "\n"
11894  << "SCALARS pressure double 1\n"
11895  << "LOOKUP_TABLE default\n";
11896  for (int k = 0; k < Nz; k++) {
11897  for (int i = 0; i < Ny; i++) {
11898  for (int j = 0; j < Nx; j++) {
11899  outf << p[i * Nx * Nz + j * Nz + k] << "\t";
11900  }
11901  }
11902  outf << "\n";
11903  }
11904  outf << "\n\n"
11905  << "VECTORS Velocity double\n";
11906  for (int k = 0; k < Nz; k++) {
11907  for (int i = 0; i < Ny; i++) {
11908  for (int j = 0; j < Nx; j++) {
11909  outf << u[i * Nx * Nz + j * Nz + k] << " "
11910  << v[i * Nx * Nz + j * Nz + k] << " "
11911  << w[i * Nx * Nz + j * Nz + k] << "\n";
11912  }
11913  }
11914  outf << "\n";
11915  }
11916 
11917  outf.close();
11918 }
11919 
11924  const std::string &flnm, const std::valarray<double> &x,
11925  const std::valarray<double> &y, const std::valarray<double> &z,
11926  const std::valarray<double> &t11, const std::valarray<double> &t12,
11927  const std::valarray<double> &t13, const std::valarray<double> &t22,
11928  const std::valarray<double> &t23, const std::valarray<double> &t33) {
11929  std::string filename;
11930  filename = flnm + ".vtk";
11931  std::ofstream outf(filename);
11932  int Nz = z.size();
11933  int Nx = x.size();
11934  int Ny = y.size();
11935  outf << "# vtk DataFile Version 2.0\n"
11936  << "3D velocity vector data \n"
11937  << "ASCII" << '\n'
11938  << "DATASET RECTILINEAR_GRID\n"
11939  << "DIMENSIONS " << Nx << " " << Ny << " " << Nz << "\n"
11940  << "X_COORDINATES " << Nx << " double\n";
11941  for (int i = 0; i < Nx; i++) {
11942  outf << x[i] << " ";
11943  }
11944  outf << "\n"
11945  << "Y_COORDINATES " << Ny << " double\n";
11946  for (int i = 0; i < Ny; i++) {
11947  outf << y[i] << " ";
11948  }
11949  outf << "\n"
11950  << "Z_COORDINATES " << Nz << " double\n";
11951  for (int i = 0; i < Nz; i++) {
11952  outf << z[i] << " ";
11953  }
11954  outf << "\n\n"
11955  << "POINT_DATA " << Nx * Nz * (Ny) << "\n"
11956  << "TENSORS Stress double\n";
11957  for (int k = 0; k < Nz; k++) {
11958  for (int i = 0; i < Ny; i++) {
11959  for (int j = 0; j < Nx; j++) {
11960  outf << t11[i * Nx * Nz + j * Nz + k] << " "
11961  << t12[i * Nx * Nz + j * Nz + k] << " "
11962  << t13[i * Nx * Nz + j * Nz + k] << "\n"
11963  << t12[i * Nx * Nz + j * Nz + k] << " "
11964  << t22[i * Nx * Nz + j * Nz + k] << " "
11965  << t23[i * Nx * Nz + j * Nz + k] << "\n"
11966  << t13[i * Nx * Nz + j * Nz + k] << " "
11967  << t23[i * Nx * Nz + j * Nz + k] << " "
11968  << t33[i * Nx * Nz + j * Nz + k] << "\n\n";
11969  }
11970  }
11971  }
11972 
11973  outf.close();
11974 }
11975 
11976 template <class T> Linop<T> conj(Linop<T> in) {
11977  if (in.NCC == 0) {
11978  in.coef = in.coef.conjugate().eval();
11979  } else {
11980  for (int i = 0; i < in.n + 1; i++) {
11981  in.coefFun[i] = conj(in.coefFun[i]);
11982  }
11983  }
11984  return in;
11985 };
11988  ChebfunMat<T> out;
11989  int bre;
11991  if (a.r != b.r || a.c != b.c) {
11992  std::cout << "addition of vector of ChebfunMats not possible"
11993  << ". In " << __LINE__ << '\n';
11994  exit(1);
11995  } else {
11996  out.resize(a.r, a.c);
11997  for (int i = 0; i < out.r; i++) {
11998  for (int j = 0; j < out.c; j++) {
11999  // std::cout << "a("<< i << ","<<j << ")" << '\n';
12000  // std::cout << a(i,j) << '\n';
12001  // std::cout << "b("<< i << ","<<j << ")" << '\n';
12002  // std::cout << b(i,j) << '\n';
12003  // std::cin >> bre;
12004  out(i, j) = a(i, j) + b(i, j);
12005  }
12006  }
12007  }
12008  return out;
12009 };
12010 
12013 template <class T>
12014 std::vector<ChebfunMat<T> > operator+(std::vector<sis::ChebfunMat<T> > a,
12015  std::vector<sis::ChebfunMat<T> > b) {
12016  if (a.size() != b.size()) {
12017  std::cout << "addition of vector of ChebfunMats not possible"
12018  << ". In " << __LINE__ << '\n';
12019  exit(1);
12020  }
12021  std::vector<sis::ChebfunMat<T> > out;
12022  out.resize(a.size());
12023  for (int i = 0; i < a.size(); i++) {
12024  if (a[i].r != b[i].r || a[i].c != b[i].c) {
12025  std::cout << "addition of vector of ChebfunMats not possible"
12026  << ". In " << __LINE__ << '\n';
12027  exit(1);
12028  } else {
12029  out[i] = a[i] + b[i];
12030  }
12031  }
12032  return out;
12033 };
12034 
12036 template <class T>
12037 std::ostream &operator<<(std::ostream &stream, std::valarray<T> a) {
12038  stream << "\n";
12039  for (int i = 0; i < a.size(); i++) {
12040  stream << a[i] << "\n";
12041  };
12042  return stream;
12043 };
12044 
12045 template <class T>
12046 std::ostream &operator<<(std::ostream &stream, std::vector<T> a) {
12047  stream << "\n";
12048  for (int i = 0; i < a.size(); i++) {
12049  stream << a[i] << "\n";
12050  };
12051  return stream;
12052 };
12053 
12054 // Minus of a Linop:
12055 template <class T> Linop<T> operator-(const Linop<T> &in) {
12056  Linop<T> out;
12057  out = in;
12058  if (out.NCC == 0) {
12059  out.coef = -out.coef;
12060  } else {
12061  for (int i = 0; i < out.n + 1; i++) {
12062  out.coefFun[i].v = -out.coefFun[i].v;
12063  }
12064  }
12065  return out;
12066 };
12067 
12068 // Minus of a Chebfun:
12069 template <class T> Chebfun<T> operator-(const Chebfun<T> &in) {
12070  Chebfun<T> out;
12071  out = in;
12072  out.v = -out.v;
12073  return out;
12074 };
12075 
12076 // Addition of two Linop:
12077 template <class T> Linop<T> operator+(Linop<T> l_, Linop<T> r_) {
12078  Linop<T> out;
12079  if (l_.NCC == 0) {
12080  if (r_.NCC == 0) {
12081  if (l_.n > r_.n) {
12082  int diffn = l_.n - r_.n;
12083  out.set(l_.n);
12084  for (int i = r_.n; i > -1; i--) {
12085  out.coef[i + diffn] = l_.coef[i + diffn] + r_.coef[i];
12086  }
12087  for (int i = 0; i < diffn; i++) {
12088  out.coef[i] = l_.coef[i];
12089  }
12090  } else {
12091  int diffn = r_.n - l_.n;
12092  out.set(r_.n);
12093  for (int i = l_.n; i > -1; i--) {
12094  out.coef[i + diffn] = r_.coef[i + diffn] + l_.coef[i];
12095  }
12096  for (int i = 0; i < diffn; i++) {
12097  out.coef[i] = r_.coef[i];
12098  }
12099  }
12100  } else {
12101  if (l_.n > r_.n) {
12102  // std::cout << "l.n ,r.n" << l_.n << "," << r_.n << '\n';
12103  int diffn = l_.n - r_.n;
12104  out.ncc(l_.n);
12105  for (int i = r_.n; i > -1; i--) {
12106  out.coefFun[i + diffn].v = l_.coef[i + diffn] + r_.coefFun[i].v;
12107  }
12108  for (int i = 0; i < diffn; i++) {
12109  out.coefFun[i].v = l_.coef[i];
12110  }
12111  } else {
12112  int diffn = r_.n - l_.n;
12113  out.ncc(r_.n);
12114  for (int i = l_.n; i > -1; i--) {
12115  out.coefFun[i + diffn].v = r_.coefFun[i + diffn].v + l_.coef[i];
12116  }
12117  for (int i = 0; i < diffn; i++) {
12118  out.coefFun[i].v = r_.coefFun[i].v;
12119  }
12120  }
12121  }
12122  } else {
12123  if (r_.NCC == 0) {
12124  if (l_.n > r_.n) {
12125  int diffn = l_.n - r_.n;
12126  out.ncc(l_.n);
12127  for (int i = r_.n; i > -1; i--) {
12128  out.coefFun[i + diffn].v = l_.coefFun[i + diffn].v + r_.coef[i];
12129  }
12130  for (int i = 0; i < diffn; i++) {
12131  out.coefFun[i].v = l_.coefFun[i].v;
12132  }
12133  } else {
12134  int diffn = r_.n - l_.n;
12135  out.ncc(r_.n);
12136  for (int i = l_.n; i > -1; i--) {
12137  out.coefFun[i + diffn].v = r_.coef[i + diffn] + l_.coefFun[i].v;
12138  }
12139  for (int i = 0; i < diffn; i++) {
12140  out.coefFun[i].v = r_.coef[i];
12141  }
12142  }
12143  } else {
12144  if (l_.n > r_.n) {
12145  int diffn = l_.n - r_.n;
12146  out.ncc(l_.n);
12147  for (int i = r_.n; i > -1; i--) {
12148  out.coefFun[i + diffn].v = l_.coefFun[i + diffn].v + r_.coefFun[i].v;
12149  }
12150  for (int i = 0; i < diffn; i++) {
12151  out.coefFun[i].v = l_.coefFun[i].v;
12152  }
12153  } else {
12154  int diffn = r_.n - l_.n;
12155  out.ncc(r_.n);
12156  for (int i = l_.n; i > -1; i--) {
12157  out.coefFun[i + diffn].v = r_.coefFun[i + diffn].v + l_.coefFun[i].v;
12158  }
12159  for (int i = 0; i < diffn; i++) {
12160  out.coefFun[i].v = r_.coefFun[i].v;
12161  }
12162  }
12163  }
12164  }
12165  return out;
12166 };
12167 
12169 template <class T>
12171  Linop<std::complex<T> > out;
12172  if (real.NCC == 0) {
12173  if (imag.NCC == 0) {
12174  if (real.n > imag.n) {
12175  int diffn = real.n - imag.n;
12176  out.set(real.n);
12177  for (int i = imag.n; i > -1; i--) {
12178  out.coef[i + diffn] =
12179  std::complex<T>(real.coef[i + diffn], imag.coef[i]);
12180  }
12181  for (int i = 0; i < diffn; i++) {
12182  out.coef[i] = real.coef[i];
12183  }
12184  } else {
12185  int diffn = imag.n - real.n;
12186  out.set(imag.n);
12187  for (int i = real.n; i > -1; i--) {
12188  out.coef[i + diffn] =
12189  std::complex<T>(real.coef[i], imag.coef[i + diffn]);
12190  }
12191  for (int i = 0; i < diffn; i++) {
12192  out.coef[i] = std::complex<T>(0.0, imag.coef[i]);
12193  }
12194  }
12195  } else {
12196  if (real.n > imag.n) {
12197  int diffn = real.n - imag.n;
12198  out.ncc(real.n);
12199  for (int i = imag.n; i > -1; i--) {
12200  std::valarray<T> temp(N + 1);
12201  temp = real.coef[i + diffn];
12202  out.coefFun[i + diffn].v = dou2com(temp, imag.coefFun[i].v);
12203  }
12204  for (int i = 0; i < diffn; i++) {
12205  out.coefFun[i].v = std::complex<T>(real.coef[i], 0.0);
12206  }
12207  } else {
12208  int diffn = imag.n - real.n;
12209  out.ncc(imag.n);
12210  for (int i = real.n; i > -1; i--) {
12211  std::valarray<T> temp(N + 1);
12212  temp = real.coef[i];
12213  out.coefFun[i + diffn].v = dou2com(temp, imag.coefFun[i + diffn].v);
12214  }
12215  for (int i = 0; i < diffn; i++) {
12216  std::valarray<T> temp(N + 1);
12217  temp = 0.0;
12218  out.coefFun[i].v = dou2com(temp, imag.coefFun[i].v);
12219  }
12220  }
12221  }
12222  } else {
12223  if (imag.NCC == 0) {
12224  if (real.n > imag.n) {
12225  int diffn = real.n - imag.n;
12226  out.ncc(real.n);
12227  for (int i = imag.n; i > -1; i--) {
12228  std::valarray<T> temp(N + 1);
12229  temp = imag.coef[i];
12230  out.coefFun[i + diffn].v = dou2com(real.coefFun[i + diffn].v, temp);
12231  }
12232  for (int i = 0; i < diffn; i++) {
12233  std::valarray<T> temp(N + 1);
12234  temp = 0.0;
12235  out.coefFun[i].v = dou2com(real.coefFun[i].v, temp);
12236  }
12237  } else {
12238  int diffn = imag.n - real.n;
12239  out.ncc(imag.n);
12240  for (int i = real.n; i > -1; i--) {
12241  std::valarray<T> temp(N + 1);
12242  temp = imag.coef[i + diffn];
12243  out.coefFun[i + diffn].v = dou2com(real.coefFun[i].v, temp);
12244  }
12245  for (int i = 0; i < diffn; i++) {
12246  out.coefFun[i].v = std::complex<T>(0.0, imag.coef[i]);
12247  }
12248  }
12249  } else {
12250  if (real.n > imag.n) {
12251  int diffn = real.n - imag.n;
12252  out.ncc(real.n);
12253  for (int i = imag.n; i > -1; i--) {
12254  out.coefFun[i + diffn].v =
12255  dou2com(real.coefFun[i + diffn].v, imag.coefFun[i].v);
12256  }
12257  for (int i = 0; i < diffn; i++) {
12258  std::valarray<T> temp(N + 1);
12259  temp = 0.0;
12260  out.coefFun[i].v = dou2com(real.coefFun[i].v, temp);
12261  }
12262  } else {
12263  int diffn = imag.n - real.n;
12264  out.ncc(imag.n);
12265  for (int i = real.n; i > -1; i--) {
12266  out.coefFun[i + diffn].v =
12267  dou2com(real.coefFun[i].v, imag.coefFun[i + diffn].v);
12268  }
12269  for (int i = 0; i < diffn; i++) {
12270  std::valarray<T> temp(N + 1);
12271  temp = 0.0;
12272  out.coefFun[i].v = dou2com(temp, imag.coefFun[i].v);
12273  }
12274  }
12275  }
12276  }
12277  return out;
12278 };
12279 
12281 template <class T>
12282 Linop<std::complex<T> > operator+(Linop<std::complex<T> > l_, Linop<T> r_) {
12283  Linop<T> outr, outi;
12284  Linop<std::complex<T> > out;
12285  outr = l_.real() + r_;
12286  outi = l_.imag();
12287  out = dou2com(outr, outi);
12288  return out;
12289 };
12290 
12292 template <class T>
12293 Linop<std::complex<T> > operator+(Linop<T> l_, Linop<std::complex<T> > r_) {
12294  Linop<T> outr, outi;
12295  Linop<std::complex<T> > out;
12296  outr = l_ + r_.real();
12297  outi = r_.imag();
12298  out = dou2com(outr, outi);
12299  return out;
12300 };
12301 
12303 template <class T> Linop<T> operator+(Linop<T> l_, Chebfun<T> r_) {
12304  Linop<T> temp;
12305  temp = r_;
12306  return l_ + temp;
12307 };
12308 
12310 template <class T>
12311 Linop<std::complex<T> > operator+(Linop<std::complex<T> > l_,
12312  Chebfun<std::complex<T> > r_) {
12313  Linop<std::complex<T> > temp;
12314  temp = r_;
12315  return l_ + temp;
12316 };
12317 
12319 template <class T>
12320 Linop<std::complex<T> > operator+(Linop<T> l_, Chebfun<std::complex<T> > r_) {
12321 
12322  Linop<T> outr, outi;
12323  outr = l_ + r_.real();
12324  outi = r_.imag();
12325  return dou2com(outr, outi);
12326 };
12327 
12329 template <class T>
12330 Linop<std::complex<T> > operator+(Linop<std::complex<T> > l_, Chebfun<T> r_) {
12331  Linop<T> outr, outi;
12332  outr = l_.real() + r_;
12333  outi = l_.imag();
12334  return dou2com(l_, r_);
12335 };
12336 
12338 template <class T> Linop<T> operator+(Chebfun<T> l_, Linop<T> r_) {
12339  Linop<T> temp;
12340  temp = l_;
12341  return r_ + temp;
12342 };
12343 
12345 template <class T>
12346 Linop<std::complex<T> > operator+(Chebfun<std::complex<T> > l_,
12347  Linop<std::complex<T> > r_) {
12348  Linop<std::complex<T> > temp;
12349  temp = l_;
12350  return temp + r_;
12351 };
12352 
12354 template <class T>
12355 Linop<std::complex<T> > operator+(Chebfun<T> l_, Linop<std::complex<T> > r_) {
12356  Linop<T> outr, outi;
12357  outr = l_ + r_.real();
12358  outi = r_.imag();
12359  return dou2com(outr, outi);
12360 };
12362 template <class T>
12363 Linop<std::complex<T> > operator+(Chebfun<std::complex<T> > l_, Linop<T> r_) {
12364  Linop<T> outr, outi;
12365  outr = l_.real() + r_;
12366  outi = l_.imag();
12367  return dou2com(outr, outi);
12368 };
12369 
12371 template <class T> Linop<T> operator+(Linop<T> l_, std::valarray<T> r_) {
12372  Linop<T> temp;
12373  temp = r_;
12374  return l_ + temp;
12375 };
12376 
12378 template <class T>
12379 Linop<std::complex<T> > operator+(Linop<std::complex<T> > l_,
12380  std::valarray<std::complex<T> > r_) {
12381  Linop<std::complex<T> > temp;
12382  temp = r_;
12383  return l_ + temp;
12384 };
12385 
12387 template <class T>
12389  std::valarray<std::complex<T> > r_) {
12390 
12391  Linop<std::complex<T> > temp1;
12392  Linop<std::complex<T> > temp2;
12393  temp1 = l_;
12394  temp2 = r_;
12395  return temp1 + temp2;
12396 };
12397 
12399 template <class T>
12400 Linop<std::complex<T> > operator+(Linop<std::complex<T> > l_,
12401  std::valarray<T> r_) {
12402  Linop<T> outr, outi;
12403  outr = l_.real() + r_;
12404  outi = l_.imag();
12405  return dou2com(outr, outi);
12406 };
12407 
12409 template <class T> Linop<T> operator+(std::valarray<T> l_, const Linop<T> &r_) {
12410  Linop<T> temp;
12411  temp = l_;
12412  return r_ + temp;
12413 };
12414 
12416 template <class T>
12417 Linop<std::complex<T> > operator+(const std::valarray<std::complex<T> > &l_,
12418  const Linop<std::complex<T> > &r_) {
12419  Linop<std::complex<T> > temp;
12420  temp = l_;
12421  return temp + r_;
12422 };
12423 
12425 template <class T>
12426 Linop<std::complex<T> > operator+(std::valarray<T> l_,
12427  Linop<std::complex<T> > r_) {
12428  return dou2com(l_, r_);
12429 };
12431 template <class T>
12432 Linop<std::complex<T> > operator+(std::valarray<std::complex<T> > l_,
12433  Linop<T> r_) {
12434  Linop<T> outr, outi;
12435  outr = real(l_) + r_;
12436  outi = imag(l_);
12437  return dou2com(outr, outi);
12438 };
12439 
12441 template <class T> Linop<T> operator-(Linop<T> l_, Linop<T> r_) {
12442  return l_ + (-r_);
12443 };
12444 
12446 template <class T>
12447 Linop<std::complex<T> > operator-(Linop<std::complex<T> > l_, Linop<T> r_) {
12448  return l_ + (-r_);
12449 };
12450 
12452 template <class T>
12453 Linop<std::complex<T> > operator-(Linop<T> l_, Linop<std::complex<T> > r_) {
12454  return l_ + (-r_);
12455 };
12456 
12458 template <class T> Linop<T> operator-(Linop<T> l_, Chebfun<T> r_) {
12459  return l_ + (-r_);
12460 };
12461 
12463 template <class T>
12464 Linop<std::complex<T> > operator-(Linop<std::complex<T> > l_,
12465  Chebfun<std::complex<T> > r_) {
12466  return l_ + (-r_);
12467 };
12468 
12470 template <class T>
12471 Linop<std::complex<T> > operator-(Linop<T> l_, Chebfun<std::complex<T> > r_) {
12472  return l_ + (-r_);
12473 };
12474 
12476 template <class T>
12477 Linop<std::complex<T> > operator-(Linop<std::complex<T> > l_, Chebfun<T> r_) {
12478  return l_ + (-r_);
12479 };
12480 
12482 template <class T> Linop<T> operator-(Chebfun<T> l_, Linop<T> r_) {
12483  return l_ + (-r_);
12484 };
12485 
12487 template <class T>
12488 Linop<std::complex<T> > operator-(Chebfun<std::complex<T> > l_,
12489  Linop<std::complex<T> > r_) {
12490  return l_ + (-r_);
12491 };
12492 
12494 template <class T>
12495 Linop<std::complex<T> > operator-(Chebfun<T> l_, Linop<std::complex<T> > r_) {
12496  return l_ + (-r_);
12497 };
12499 template <class T>
12500 Linop<std::complex<T> > operator-(Chebfun<std::complex<T> > l_, Linop<T> r_) {
12501  return l_ + (-r_);
12502 };
12503 
12505 template <class T> Linop<T> operator-(Linop<T> l_, std::valarray<T> r_) {
12506  return l_ + std::valarray<T>(-r_);
12507 };
12508 
12510 template <class T>
12512  std::valarray<std::complex<T> > r_) {
12513  return l_ + std::valarray<std::complex<T> >(-r_);
12514 };
12515 
12517 template <class T>
12518 Linop<std::complex<T> > operator-(Linop<std::complex<T> > l_,
12519  std::valarray<T> r_) {
12520  return l_ + std::valarray<T>(-r_);
12521 };
12522 
12524 template <class T>
12525 Linop<T> operator-(const std::valarray<T> &l_, const Linop<T> &r_) {
12526  return l_ + (-r_);
12527 };
12528 
12530 template <class T>
12531 Linop<std::complex<T> > operator-(std::valarray<T> l_,
12532  Linop<std::complex<T> > r_) {
12533  return l_ + (-r_);
12534 };
12536 template <class T>
12537 Linop<std::complex<T> > operator-(std::valarray<std::complex<T> > l_,
12538  Linop<T> r_) {
12539  return l_ + (-r_);
12540 };
12541 
12542 template <class T>
12543 Eigen::Array<T, Eigen::Dynamic, 1>
12544 operator*(std::valarray<T> left,
12545  const Eigen::Array<T, Eigen::Dynamic, 1> &right) {
12546  Eigen::Array<T, Eigen::Dynamic, 1> out;
12547  out.resize(left.size());
12548  for (int i = 0; i < left.size(); i++) {
12549  out[i] = left[i] * right[i];
12550  }
12551  return out;
12552 };
12553 
12554 template <class T> Linop<T> operator*(std::valarray<T> left, Linop<T> right) {
12555  Linop<T> temp;
12556  temp = right;
12557  if (right.NCC == 0) {
12558  temp.ncc();
12559  for (int i = 0; i < right.n + 1; i++) {
12560  temp.coefFun[i].v = left * right.coef[i];
12561  }
12562  } else {
12563  temp.ncc();
12564  for (int i = 0; i < right.n + 1; i++) {
12565  temp.coefFun[i].v = left * right.coefFun[i].v;
12566  }
12567  }
12568  return temp;
12569 };
12570 
12571 template <class T>
12572 Linop<std::complex<T> > operator*(std::valarray<std::complex<T> > left,
12573  Linop<T> right) {
12574  Linop<std::complex<T> > temp;
12575  temp = right;
12576  return left * temp;
12577 };
12578 
12579 template <class T>
12580 Linop<std::complex<T> > operator*(std::valarray<T> left,
12581  Linop<std::complex<T> > right) {
12582  std::valarray<std::complex<T> > temp;
12583  std::valarray<T> zvec;
12584  zvec = 0.0;
12585  temp = dou2com(temp, zvec);
12586  return temp * right;
12587 };
12588 
12590 template <class T> Linop<T> operator*(Chebfun<T> left, Linop<T> right) {
12591  Linop<T> temp;
12592  temp = right;
12593  if (right.NCC == 0) {
12594  temp.ncc();
12595  for (int i = 0; i < right.n + 1; i++) {
12596  temp.coefFun[i] = left * right.coef[i];
12597  }
12598  } else {
12599  temp.ncc();
12600  for (int i = 0; i < right.n + 1; i++) {
12601  temp.coefFun[i] = left * right.coefFun[i];
12602  }
12603  }
12604  return temp;
12605 };
12606 
12607 template <class T>
12608 Linop<std::complex<T> > operator*(Chebfun<std::complex<T> > left,
12609  Linop<T> right) {
12610  Linop<std::complex<T> > temp;
12611  temp = right;
12612  return left * temp;
12613 };
12614 
12615 template <class T>
12617  Linop<std::complex<T> > right) {
12618  Chebfun<std::complex<T> > temp;
12619  temp = left;
12620  return temp * right;
12621 };
12622 
12624 template <class T> Linop<T> operator*(T left, Linop<T> right) {
12625  Linop<T> temp;
12626  temp = right;
12627  if (right.NCC == 0) {
12628  for (int i = 0; i < right.n + 1; i++) {
12629  temp.coef[i] = left * right.coef[i];
12630  }
12631  } else {
12632  temp.ncc();
12633  for (int i = 0; i < right.n + 1; i++) {
12634  temp.coefFun[i].v = left * right.coefFun[i].v;
12635  }
12636  }
12637  return temp;
12638 };
12639 
12640 template <class T>
12641 Linop<std::complex<T> > operator*(std::complex<T> left, Linop<T> right) {
12642  Linop<std::complex<T> > temp;
12643  temp = right;
12644  return left * temp;
12645 };
12646 
12647 template <class T>
12648 Linop<std::complex<T> > operator*(T left, Linop<std::complex<T> > right) {
12649  std::complex<T> temp(left, 0.0);
12650  return temp * right;
12651 };
12652 
12654 template <class T> Linop<T> operator+(const Linop<T> &left, T right) {
12655  Linop<T> _right;
12656  _right = right;
12657  return _right + left;
12658 };
12659 
12661 template <class T> Linop<T> operator+(T left, const Linop<T> &right) {
12662  Linop<T> _left;
12663  _left = left;
12664  return _left + right;
12665 };
12666 
12668 template <class T>
12669 Linop<std::complex<T> > operator+(const Linop<std::complex<T> > &left,
12670  T right) {
12671  Linop<std::complex<T> > _right;
12672  _right = right;
12673  return _right + left;
12674 };
12675 
12677 template <class T>
12678 Linop<std::complex<T> > operator+(std::complex<T> left, const Linop<T> &right) {
12679  Linop<std::complex<T> > _left;
12680  _left = left;
12681  return _left + right;
12682 };
12683 
12685 template <class T>
12686 Linop<std::complex<T> > operator+(const Linop<T> &left, std::complex<T> right) {
12687  Linop<std::complex<T> > _right;
12688  _right = right;
12689  return _right + left;
12690 };
12691 
12693 template <class T>
12695  const Linop<std::complex<T> > &right) {
12696  Linop<std::complex<T> > _left;
12697  _left = left;
12698  return _left + right;
12699 };
12701 template <class T> Linop<T> operator-(const Linop<T> &left, T right) {
12702  Linop<T> _right;
12703  _right = right;
12704  return left - _right;
12705 };
12706 
12708 template <class T> Linop<T> operator-(T left, const Linop<T> &right) {
12709  Linop<T> _left;
12710  ;
12711  _left = left;
12712  return _left - right;
12713 };
12714 
12716 template <class T>
12718  const Linop<std::complex<T> > &right) {
12719  Linop<std::complex<T> > _left;
12720  _left = left;
12721  return _left - right;
12722 };
12723 
12724 template <class T>
12725 Linop<std::complex<T> > operator-(std::complex<T> left, const Linop<T> &right) {
12726  Linop<std::complex<T> > _left;
12727  _left = left;
12728  return _left - right;
12729 };
12730 
12731 template <class T>
12732 Linop<std::complex<T> > operator-(const Linop<std::complex<T> > &left,
12733  T right) {
12734  Linop<std::complex<T> > _right;
12735  _right = right;
12736  return left - _right;
12737 };
12738 
12739 template <class T>
12740 Linop<std::complex<T> > operator-(const Linop<T> &left, std::complex<T> right) {
12741  Linop<std::complex<T> > _right;
12742  _right = right;
12743  return left - _right;
12744 };
12745 
12747 template <class T> Chebfun<T> operator*(T a, Chebfun<T> b) {
12748  Chebfun<T> out;
12749  out.v = a * b.v;
12750  out.dct_flag = b.dct_flag;
12751  return out;
12752 };
12753 
12755 template <class T> Chebfun<T> operator*(Chebfun<T> b, T a) {
12756  Chebfun<T> out;
12757  out.v = a * b.v;
12758  out.dct_flag = b.dct_flag;
12759  return out;
12760 };
12761 
12763 template <class T>
12764 Chebfun<std::complex<T> > operator*(Chebfun<std::complex<T> > b, T a) {
12766  out.fftw_init();
12767  out.v = a * b.v;
12768  out.dct_flag = b.dct_flag;
12769  return out;
12770 };
12771 
12773 template <class T>
12774 Chebfun<std::complex<T> > operator*(T a, Chebfun<std::complex<T> > b) {
12776  out.v = a * b.v;
12777  out.dct_flag = b.dct_flag;
12778  return out;
12779 };
12780 
12783 template <class T> ChebfunMat<T> operator*(T a, ChebfunMat<T> in) {
12784  ChebfunMat<T> out;
12785  out.resize(in.r, in.c);
12786  int bre;
12787 
12788  for (int i = 0; i < in.r; i++) {
12789  for (int j = 0; j < in.c; j++) {
12790  out(i, j) = a * in(i, j);
12791  }
12792  }
12793 
12794  return out;
12795 };
12796 
12799 template <class T>
12800 ChebfunMat<std::complex<T> > operator*(T a, ChebfunMat<std::complex<T> > in) {
12802  out.resize(in.r, in.c);
12803  for (int i = 0; i < in.r; i++) {
12804  for (int j = 0; j < in.c; j++) {
12805  out(i, j) = a * in(i, j);
12806  }
12807  }
12808  return out;
12809 };
12810 
12813 template <class T>
12816  out.resize(in.r, in.c);
12817  for (int i = 0; i < in.r; i++) {
12818  for (int j = 0; j < in.c; j++) {
12819  out(i, j) = a * in(i, j);
12820  }
12821  }
12822 };
12823 
12828 template <class T>
12829 std::valarray<ChebfunMat<T> > operator*(T a, std::valarray<ChebfunMat<T> > in) {
12830  std::valarray<ChebfunMat<T> > out;
12831  out.resize(in.size());
12832  for (int i = 0; i < in.size(); i++) {
12833  out[i] = a * in[i];
12834  }
12835 };
12836 
12840 template <class T>
12841 std::valarray<ChebfunMat<std::complex<T> > >
12842 operator*(std::complex<T> a, std::valarray<ChebfunMat<T> > in) {
12843  std::valarray<ChebfunMat<std::complex<T> > > out;
12844  out.resize(in.size());
12845  for (int i = 0; i < in.size(); i++) {
12846  out[i] = a * in[i];
12847  }
12848 };
12849 
12853 template <class T>
12854 std::valarray<ChebfunMat<T> >
12855 operator*(T a, std::valarray<ChebfunMat<std::complex<T> > > in) {
12856  std::valarray<ChebfunMat<std::complex<T> > > out;
12857  out.resize(in.size());
12858  for (int i = 0; i < in.size(); i++) {
12859  out[i] = a * in[i];
12860  }
12861 };
12862 
12864 
12867 template <class T> Chebfun<T> operator*(Chebfun<T> a, Chebfun<T> b) {
12868  Chebfun<T> out;
12869  if (a.dct_flag == b.dct_flag) {
12870  if (a.dct_flag == SIS_PHYS_SPACE) {
12871  out.v = a.v * b.v;
12872  out.dct_flag = SIS_PHYS_SPACE;
12873  return out;
12874  } else {
12875  a.c2p();
12876  b.c2p();
12877  out.v = a.v + b.v;
12878  out.dct_flag = a.dct_flag;
12879  a.p2c();
12880  b.p2c();
12881  out.p2c();
12882  return out;
12883  }
12884  } else {
12885  if (a.dct_flag == SIS_PHYS_SPACE) {
12886  b.c2p();
12887  out.v = a.v + b.v;
12888  out.dct_flag = SIS_PHYS_SPACE;
12889  b.p2c();
12890  return out;
12891  } else {
12892  a.c2p();
12893  out.v = a.v + b.v;
12894  out.dct_flag = SIS_PHYS_SPACE;
12895  a.p2c();
12896  return out;
12897  }
12898  }
12899 };
12900 
12901 template <class T>
12903 
12904  Chebfun<std::complex<T> > out, a_;
12905  a_ = a;
12906  return (a_ * b);
12907 };
12908 
12909 template <class T>
12911  Chebfun<std::complex<T> > out, a_;
12912  a_ = a;
12913  return (b * a_);
12914 };
12915 
12928 template <class T> Linop<T> operator*(Linop<T> L1, Linop<T> L2) {
12929  Linop<T> out;
12930  out.set(L1.n + L2.n);
12931  if (L1.NCC == 0 && L1.NCC == 0) {
12932  for (int i = 0; i < L1.n + L2.n + 1; i++) {
12933  out.coef[i] = 0.0;
12934  }
12935  for (int i = 0; i < L1.n + 1; i++) {
12936  out += L1.coef[i] * diff(L2, L1.n - i);
12937  }
12938  } else {
12939  out.ncc(L1.n + L2.n);
12940  for (int i = 0; i < L1.n + L2.n + 1; i++) {
12941  out.coefFun[i] = 0.0;
12942  }
12943  if (L1.NCC == 0) {
12944  for (int i = 0; i < L1.n + 1; i++) {
12945  out += L1.coef[i] * diff(L2, L1.n - i);
12946  }
12947  } else {
12948  for (int i = 0; i < L1.n + 1; i++) {
12949  out += L1.coefFun[i] * diff(L2, L1.n - i);
12950  }
12951  }
12952  }
12953  return out;
12954 };
12955 
12956 template <class T>
12957 Linop<std::complex<T> > operator*(Linop<std::complex<T> > L1, Linop<T> L2) {
12958  Linop<std::complex<T> > out;
12959  out.set(L1.n + L2.n);
12960  if (L1.NCC == 0 && L1.NCC == 0) {
12961  for (int i = 0; i < L1.n + L2.n + 1; i++) {
12962  out.coef[i] = 0.0;
12963  }
12964  for (int i = 0; i < L1.n + 1; i++) {
12965  out += L1.coef[i] * diff(L2, L1.n - i);
12966  }
12967  } else {
12968  out.ncc(L1.n + L2.n);
12969  for (int i = 0; i < L1.n + L2.n + 1; i++) {
12970  out.coefFun[i] = 0.0;
12971  }
12972  if (L1.NCC == 0) {
12973  for (int i = 0; i < L1.n + 1; i++) {
12974  out += L1.coef[i] * diff(L2, L1.n - i);
12975  }
12976  } else {
12977  for (int i = 0; i < L1.n + 1; i++) {
12978  out += L1.coefFun[i] * diff(L2, L1.n - i);
12979  }
12980  }
12981  }
12982  return out;
12983 };
12984 
12985 template <class T> Linop<T> operator*(Linop<T> L1, Linop<std::complex<T> > L2) {
12986  Linop<std::complex<T> > out;
12987  out.set(L1.n + L2.n);
12988  if (L1.NCC == 0 && L1.NCC == 0) {
12989  for (int i = 0; i < L1.n + L2.n + 1; i++) {
12990  out.coef[i] = 0.0;
12991  }
12992  for (int i = 0; i < L1.n + 1; i++) {
12993  out += L1.coef[i] * diff(L2, L1.n - i);
12994  }
12995  } else {
12996  out.ncc(L1.n + L2.n);
12997  for (int i = 0; i < L1.n + L2.n + 1; i++) {
12998  out.coefFun[i] = 0.0;
12999  }
13000  if (L1.NCC == 0) {
13001  for (int i = 0; i < L1.n + 1; i++) {
13002  out += L1.coef[i] * diff(L2, L1.n - i);
13003  }
13004  } else {
13005  for (int i = 0; i < L1.n + 1; i++) {
13006  out += L1.coefFun[i] * diff(L2, L1.n - i);
13007  }
13008  }
13009  }
13010  return out;
13011 };
13012 
13015 template <class T> Chebfun<T> operator+(Chebfun<T> a, Chebfun<T> b) {
13016  Chebfun<T> out;
13017  if (a.dct_flag == b.dct_flag) {
13018  out.v = a.v + b.v;
13019  out.dct_flag = a.dct_flag;
13020  return out;
13021  } else {
13022  if (a.dct_flag == SIS_PHYS_SPACE) {
13023  b.c2p();
13024  out.v = a.v + b.v;
13025  out.dct_flag = SIS_PHYS_SPACE;
13026  b.p2c();
13027  return out;
13028  } else {
13029  a.c2p();
13030  out.v = a.v + b.v;
13031  out.dct_flag = SIS_PHYS_SPACE;
13032  a.p2c();
13033  return out;
13034  }
13035  }
13036 };
13037 
13038 template <class T>
13040  Chebfun<std::complex<T> > out, a_;
13041  a_ = a;
13042  return (a_ + b);
13043 };
13044 
13045 template <class T>
13047  Chebfun<std::complex<T> > out, b_;
13048  b_ = b;
13049  return (a + b_);
13050 };
13051 
13052 template <class T> Linop<T> pow(Linop<T> in, int a) {
13053  if (a < 0) {
13054  std::cout << "Cannot have a negative power for linop ..." << '\n';
13055  std::cout << "in " << __LINE__ << '\n';
13056  exit(1);
13057  } else if (a == 1) {
13058  return in;
13059  } else {
13060  return pow(in, a - 1) * in;
13061  }
13062 };
13063 
13064 template <class T> LinopMat<T> operator+(LinopMat<T> left, LinopMat<T> right) {
13065  LinopMat<T> temp;
13066  if (left.r != right.r || left.c != right.c) {
13067  std::cout << "Incompatible shapes of LinopMats for addition." << '\n';
13068  exit(1);
13069  }
13070  temp.resize(left.r, left.c);
13071  for (int i = 0; i < left.r; i++) {
13072  for (int j = 0; j < left.c; j++) {
13073  temp(i, j) = left(i, j) + right(i, j);
13074  }
13075  }
13076  return temp;
13077 };
13078 
13079 template <class T>
13081  LinopMat<T> right) {
13082  LinopMat<std::complex<T> > temp;
13083  if (left.r != right.r || left.c != right.c) {
13084  std::cout << "Incompatible shapes of LinopMats for addition." << '\n';
13085  exit(1);
13086  }
13087  temp.resize(left.r, left.c);
13088  for (int i = 0; i < left.r; i++) {
13089  for (int j = 0; j < left.c; j++) {
13090  temp(i, j) = left(i, j) + right(i, j);
13091  }
13092  }
13093  return temp;
13094 };
13095 
13096 template <class T>
13098  LinopMat<std::complex<T> > right) {
13099  LinopMat<std::complex<T> > temp;
13100  if (left.r != right.r || left.c != right.c) {
13101  std::cout << "Incompatible shapes of LinopMats for addition." << '\n';
13102  exit(1);
13103  }
13104  temp.resize(left.r, left.c);
13105  for (int i = 0; i < left.r; i++) {
13106  for (int j = 0; j < left.c; j++) {
13107  temp(i, j) = left(i, j) + right(i, j);
13108  }
13109  }
13110  return temp;
13111 };
13112 
13114 template <class T> LinopMat<T> operator*(T a, LinopMat<T> right) {
13115  for (int i = 0; i < right.r; i++) {
13116  for (int j = 0; j < right.c; j++) {
13117  right(i, j) = a * right(i, j);
13118  }
13119  }
13120  return right;
13121 };
13122 
13124 template <class T>
13125 LinopMat<std::complex<T> > operator*(T a, LinopMat<std::complex<T> > right) {
13126  for (int i = 0; i < right.r; i++) {
13127  for (int j = 0; j < right.c; j++) {
13128  right(i, j) = a * right(i, j);
13129  }
13130  }
13131  return right;
13132 };
13133 
13135 template <class T>
13136 LinopMat<std::complex<T> > operator*(std::complex<T> a, LinopMat<T> right) {
13137  LinopMat<std::complex<T> > out(right.r, right.c);
13138  for (int i = 0; i < right.r; i++) {
13139  for (int j = 0; j < right.c; j++) {
13140  out(i, j) = a * right(i, j);
13141  }
13142  }
13143  return out;
13144 };
13145 
13147 template <class T> LinopMat<T> operator*(LinopMat<T> left, LinopMat<T> right) {
13148  if (left.c != right.r) {
13149  std::cout << "Incompatible shapes of LinopMats for multiplication." << '\n';
13150  exit(1);
13151  }
13152 
13153  LinopMat<T> out(left.r, right.c);
13154  out.setConstant(0.0);
13155  for (int i = 0; i < left.r; i++) {
13156  for (int j = 0; j < right.c; j++) {
13157  for (int k = 0; k < left.c; k++) {
13158  out(i, j) = out(i, j) + (left(i, k) * right(k, j));
13159  }
13160  }
13161  }
13162  return out;
13163 };
13165 template <class T>
13167  LinopMat<T> right) {
13168  if (left.c != right.r) {
13169  std::cout << "Incompatible shapes of LinopMats for multiplication." << '\n';
13170  exit(1);
13171  }
13172 
13173  LinopMat<std::complex<T> > out(left.r, right.c);
13174  out.setConstant(0.0);
13175  for (int i = 0; i < left.r; i++) {
13176  for (int j = 0; j < right.c; j++) {
13177  for (int k = 0; k < left.c; k++) {
13178  out(i, j) = out(i, j) + (left(i, k) * right(k, j));
13179  }
13180  }
13181  }
13182  return out;
13183 };
13185 template <class T>
13187  LinopMat<std::complex<T> > right) {
13188  if (left.c != right.r) {
13189  std::cout << "Incompatible shapes of LinopMats for multiplication." << '\n';
13190  exit(1);
13191  }
13192 
13193  LinopMat<std::complex<T> > out(left.r, right.c);
13194  out.setConstant(0.0);
13195  for (int i = 0; i < left.r; i++) {
13196  for (int j = 0; j < right.c; j++) {
13197  for (int k = 0; k < left.c; k++) {
13198  out(i, j) = out(i, j) + (left(i, k) * right(k, j));
13199  }
13200  }
13201  }
13202  return out;
13203 };
13204 
13206 template <class T> LinopMat<T> operator-(LinopMat<T> left, LinopMat<T> right) {
13207  LinopMat<T> temp;
13208  if (left.r != right.r || left.c != right.c) {
13209  std::cout << "Incompatible shapes of LinopMats for subtraction." << '\n';
13210  exit(1);
13211  }
13212  temp.resize(left.r, left.c);
13213  for (int i = 0; i < left.r; i++) {
13214  for (int j = 0; j < left.c; j++) {
13215  temp(i, j) = left(i, j) - right(i, j);
13216  }
13217  }
13218  return temp;
13219 };
13220 
13221 template <class T>
13223  LinopMat<T> right) {
13224  LinopMat<std::complex<T> > temp;
13225  if (left.r != right.r || left.c != right.c) {
13226  std::cout << "Incompatible shapes of LinopMats for addition." << '\n';
13227  exit(1);
13228  }
13229  temp.resize(left.r, left.c);
13230  for (int i = 0; i < left.r; i++) {
13231  for (int j = 0; j < left.c; j++) {
13232  temp(i, j) = left(i, j) - right(i, j);
13233  }
13234  }
13235  return temp;
13236 };
13237 
13238 template <class T>
13240  LinopMat<std::complex<T> > right) {
13241  LinopMat<std::complex<T> > temp;
13242  if (left.r != right.r || left.c != right.c) {
13243  std::cout << "Incompatible shapes of LinopMats for addition." << '\n';
13244  exit(1);
13245  }
13246  temp.resize(left.r, left.c);
13247  for (int i = 0; i < left.r; i++) {
13248  for (int j = 0; j < left.c; j++) {
13249  temp(i, j) = left(i, j) - right(i, j);
13250  }
13251  }
13252  return temp;
13253 };
13254 
13255 template <class T> LinopMat<T> operator/(LinopMat<T> left_, T right) {
13256  LinopMat<T> outMat;
13257  outMat.resize(left_.r, left_.c);
13258  for (int i = 0; i < left_.r; i++) {
13259  for (int j = 0; j < left_.c; j++) {
13260  outMat(i, j) = left_(i, j) / right;
13261  }
13262  }
13263  return outMat;
13264 };
13265 
13266 template <class T>
13267 LinopMat<std::complex<T> > operator/(LinopMat<std::complex<T> > left_,
13268  T right) {
13269  LinopMat<std::complex<T> > outMat;
13270  outMat.resize(left_.r, left_.c);
13271  for (int i = 0; i < left_.r; i++) {
13272  for (int j = 0; j < left_.c; j++) {
13273  outMat(i, j) = left_(i, j) / right;
13274  }
13275  }
13276  return outMat;
13277 };
13278 
13280 template <class T>
13281 ChebfunMat<std::complex<T> >
13282 linSolve(const LinopMat<std::complex<T> > &Lmat_,
13283  const BcMat<std::complex<T> > &bcmat_,
13284  const ChebfunMat<std::complex<T> > &forc_) {
13285  LinopMat<std::complex<T> > Lmat = Lmat_;
13286  ChebfunMat<std::complex<T> > forc = forc_;
13287  BcMat<std::complex<T> > bcmat = bcmat_;
13288 
13290  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> A0 =
13291  Dis.MatAppend(Lmat, bcmat);
13292  Eigen::ColPivHouseholderQR<
13293  Eigen::Matrix<std::complex<T>, Eigen::Dynamic, Eigen::Dynamic> >
13294  qr;
13295  qr.compute(A0);
13296  if (!qr.isInvertible()) {
13297  std::cout << "Solution not possible. This system is singular." << '\n';
13298  exit(1);
13299  }
13300  Eigen::Matrix<std::complex<double>, Eigen::Dynamic, Eigen::Dynamic> force =
13301  forc.ChebfunMat2EigenMat();
13302 
13303  //int bre;
13304 //std::cout << "In " << __LINE__ << std::endl;
13305  // std::cout << force << std::endl;
13306  //std::cin >> bre;
13307  Eigen::Matrix<std::complex<double>, Eigen::Dynamic, Eigen::Dynamic> force2(
13308  A0.rows(), force.cols());
13309  // std::cout << "force: " << size(force2) << '\n' << std::flush;
13310  for (int i = 0; i < force2.cols(); i++) {
13311  force2.block(0, i, force.rows(), 1) = force.col(i);
13312  force2.block(force.rows(), i, bcmat.vals.rows(), 1) = bcmat.vals;
13313  }
13314 
13315 
13316 
13317  // std::cout << "A0: " << size(A0) << '\n' << std::flush;
13318 
13319  // Solve:
13320  force2 = qr.inverse() * force2;
13321 
13322  // Parse it from form (a0 ... an C0 C1) to (a0 ... an), append constants to
13323  // to the series
13324  MatGen<std::complex<T> > Mat;
13325  int row_counter = 0;
13326  for (int i = 0; i < forc.c; i++) {
13327  int n = Dis.highest_each_column[i];
13328  Mat.compute(n);
13329  force.block(i * (N + 1), 0, N + 1, forc.c) =
13330  Mat.mats2[n] *
13331  force2.block(row_counter, 0, N + 1 + n, forc.c);
13332  row_counter += N + 1 + n;
13333  }
13334 
13335 
13336  //std::cout << "force.size: " << size(force) << '\n';
13337  ChebfunMat<std::complex<T> > out(forc.r, forc.c);
13338  // Assignment automatically assings Eigen matrix to a ChebfunMat.
13339  out = force;
13340  // This is raw assingn in the previous line. Specify that everything is in
13341  // Cheb space. Then convert to physical space for convinience:
13342  for (int i = 0; i < out.r; i++) {
13343  for (int j = 0; j < out.c; j++) {
13344  out(i, j).dct_flag = SIS_CHEB_SPACE;
13345  out(i, j).c2p();
13346  }
13347  }
13348  return out;
13349 }
13350 
13351 } // namespace sis
13352 /*/// \brief Defining addition of ChebfunMats.
13353 template <class T>
13354  ChebfunMat<T> operator+( ChebfunMat<T> a, ChebfunMat<T> b){
13355  ChebfunMat<T> out;
13356  if (a.r != b.r || a.c != b.c){
13357  std::cout << "addition of vector of ChebfunMats not possible"
13358  << ". In " << __LINE__ << '\n';
13359  exit(1);
13360  out.resize(a.r,a.c);
13361  for (int i = 0; i < out.r; i++){
13362  for (int j = 0; j < out.c; j++){
13363  out(i,j) = a(i,j) + b(i,j);
13364  }
13365  }
13366  }
13367 };
13368 
13371 template <class T>
13372 std::vector< ChebfunMat<T> > operator+(std::vector< ChebfunMat<T> > a,
13373  std::vector< ChebfunMat<T> > b){
13374  if (a.size() != b.size()){
13375  std::cout << "addition of vector of ChebfunMats not possible"
13376  << ". In " << __LINE__ << '\n';
13377  exit(1);
13378  }
13379  std::vector<sis::ChebfunMat<T> > out;
13380  out.resize(a.size());
13381  for (int i = 0; i < a.size(); i++ ){
13382  if (a[i].r != b[i].r || a[i].c != b[i].c){
13383  std::cout << "addition of vector of ChebfunMats not possible"
13384  << ". In " << __LINE__ << '\n';
13385  exit(1);
13386  } else {
13387  out[i] = a[i] + b[i];
13388  }
13389  }
13390  return out;
13391 };*/
13392 
13396 // template <class T>
13397 // std::complex<T> operator*(T a, std::complex<T> b) {
13398 // return std::complex<T>(a, 0.0) * b;
13399 //}
void operator=(const ChebfunMat &in)
Assignment operator.
Definition: sis.hpp:2041
void operator+=(const Linop< std::complex< T > > &in)
Definition: sis.hpp:2884
void sis_setup()
Definition: sis.hpp:954
void c2p()
Converts every element to phys-space, if not already in phys-space.
Definition: sis.hpp:2341
void operator=(const LinopMat< std::complex< T > > &in)
Assignment operator.
Definition: sis.hpp:8427
Chebfun()
Null constructor.
Definition: sis.hpp:1160
void compute(const LinopMat< std::complex< T > > &Lmat_, int num_vals, const BcMat< std::complex< T > > &bc_)
Call this with an input Linear operator to solve for eigenvalues and vectors. The number of Eigen val...
Definition: sis.hpp:5248
LinopMat(int r_, int c_)
Initializes a Linop Matrix of r_ rows and c_ columns.
Definition: sis.hpp:8398
void operator=(const T &in)
Assignment operator for constant input.
Definition: sis.hpp:2687
void compute(const LinopMat< T > &A_, const LinopMat< T > &B_, const LinopMat< T > &C_, const BcMat< T > &Lbc_, const BcMat< T > &Rbc_, int num_vals)
Computes the Singular value(s) of a system in the input-output form, This is used to the find the fr...
Definition: sis.hpp:9245
Chebfun< T > operator()(Chebfun< T > in)
Apply the operator on a Chebfun.
Definition: sis.hpp:2663
Linop()
A null-constructor for Linop.
Definition: sis.hpp:2632
BcMat< std::complex< T > > AdjointBc_analytical(const LinopMat< std::complex< T > > &Lmat_, const BcMat< std::complex< T > > &Lbc_, const BcMat< std::complex< T > > &Rbc_)
Computes adjoint boundary conditions analytically, needs boundary conditions all right boundary condi...
Definition: sis.hpp:11505
Linop()
A null-constructor for Linop.
Definition: sis.hpp:2823
Eigen::Array< std::complex< T >, Eigen::Dynamic, 1 > evc()
Returns property complex array vr + i vi in terms of Eigen::Array.
Definition: sis.hpp:1731
void ncc(int n_)
Sets the the size of non-constant coefficient array based on the order of differential equation...
Definition: sis.hpp:2760
void removeInf()
This will remove all infinite eigenvalues. Useful when solving generalized eigenvalue problems...
Definition: sis.hpp:7501
void resize(int r_, int c_)
This clears all contents in the LinopMat, and then creates a fresh LinopMat of size r_ x c_...
Definition: sis.hpp:8544
BcMat will hold general Boundary conditions as LinopMats at evealuation points, as given by operator ...
Definition: sis.hpp:529
ChebfunMat< T > coefFun
Definition: sis.hpp:2621
std::valarray< std::complex< T > > operator*(std::complex< T > left, std::valarray< T > right)
Multiplying a complex number with a real valarray.
Definition: sis.hpp:302
void compute(const LinopMat< std::complex< T > > &A_, const BcMat< std::complex< T > > &Lbc_, const BcMat< std::complex< T > > &Rbc_, int num_vals)
Computes the singular values/functions of a Linear block matrix operator.
Definition: sis.hpp:10295
LinopMat< T > & operator,(Eigen::Array< T, Eigen::Dynamic, 1 > b)
Overloads comma separator to input Chebfuns into a ChebfunMat. Input type Eigen array.
Definition: sis.hpp:8230
ChebfunMat< std::complex< T > > linSolve(const LinopMat< std::complex< T > > &Lmat_, const BcMat< std::complex< T > > &bcmat_, const ChebfunMat< std::complex< T > > &forc_)
Linear equation solver.
Definition: sis.hpp:13282
#define SIS_PHYS_SPACE
Definition: sis.hpp:470
Linop(const Linop< std::complex< T > > &in)
Copy constructor.
Definition: sis.hpp:2833
void operator=(const Eigen::Matrix< T, Eigen::Dynamic, 1 > &right)
To assign a Chebfun through a vector.
Definition: sis.hpp:1361
int countr
Definition: sis.hpp:8123
This class sets up integration Matrices. This class must be intiated by the highest order of based on...
Definition: sis.hpp:530
MatGen()
Null Constructor.
Definition: sis.hpp:7966
void operator=(Chebfun< T > in)
Assignment through a Chebfun:
Definition: sis.hpp:2708
void operator+=(std::complex< T > right)
add a constant to self
Definition: sis.hpp:1864
Chebfun< T > & operator[](int i)
Use this to to refer to Chebfuns. For 1D Matrices, we use the Row major format when refering to [i]...
Definition: sis.hpp:2082
ChebfunMat< std::complex< T > > & operator,(std::complex< T > b)
Overloads comma separator to input Chebfuns into a ChebfunMat. Input type complex constant...
Definition: sis.hpp:2426
void operator=(const Linop< std::complex< T > > &in)
Definition: sis.hpp:2842
void disp(std::valarray< T > in)
Prints a valarray to terminal.
Definition: sis.hpp:912
void operator+=(const T &right)
Adding constant to itself.
Definition: sis.hpp:1372
LinopMat< std::complex< T > > & operator,(Linop< T > b)
Overloads comma separator to input Chebfuns into a ChebfunMat. Input type Chebfun.
Definition: sis.hpp:8601
Chebfun< std::complex< T > > cumsum()
Definition: sis.hpp:1914
void compute(const LinopMat< std::complex< T > > &A_, const LinopMat< std::complex< T > > &B_, const LinopMat< std::complex< T > > &C_, const BcMat< std::complex< T > > &Lbc_, const BcMat< std::complex< T > > &Rbc_, int num_vals)
Computes singular values of the frequency response operator of a system in the input-output form...
Definition: sis.hpp:10404
MatGen(int n_)
Constructor.
Definition: sis.hpp:7968
std::valarray< T > ifft2_cs(std::valarray< std::complex< T > > in1, int Nx, int Nz)
ifft2 for a 2D matrix stored in the row-major format, Nx and Nz denote dimensions in x and z...
Definition: sis.hpp:765
void resize(int m_, int n_)
Definition: sis.hpp:8948
std::vector< Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > > mats2
Definition: sis.hpp:7961
int converged
Number of eigenvalues that have converged to machine precision.
Definition: sis.hpp:5236
LinopMat< T > operator/(LinopMat< T > left_, T right)
Definition: sis.hpp:13255
ChebfunMat< T > cTranspose()
Definition: sis.hpp:2214
LinopMat< std::complex< T > > & operator,(T b)
Overloads comma separator to input Chebfuns into a ChebfunMat. Input type constant.
Definition: sis.hpp:8561
Linop< T > pow(Linop< T > in, int a)
Definition: sis.hpp:13052
Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > eval
Definition: sis.hpp:8832
std::valarray< std::complex< T > > PowerSpectralDensityIndividual(const LinopMat< std::complex< T > > &A_, const LinopMat< std::complex< T > > &B_, const LinopMat< std::complex< T > > &C1_, const LinopMat< std::complex< T > > &C2_, const LinopMat< std::complex< T > > &C3_, const BcMat< std::complex< T > > &Lbc_, const BcMat< std::complex< T > > &Rbc_)
Definition: sis.hpp:10781
LinopMat< std::complex< T > > & operator,(std::complex< T > b)
Overloads comma separator to input Chebfuns into a ChebfunMat. Input type constant.
Definition: sis.hpp:8553
int r
Number of rows.
Definition: sis.hpp:2013
This is a chebfun analogue. Chebfun will represent both values in physical space or an array of Cheby...
Definition: sis.hpp:1150
void operator=(const LinopMat< T > &in)
Assignment operator.
Definition: sis.hpp:8438
Class to compute binomial coefficients returns a double output.
Definition: sis.hpp:9037
std::valarray< T > v
Stores a flag to denote if function is in Cheb-space or physical space.
Definition: sis.hpp:1156
Chebfun(const Eigen::Array< T, Eigen::Dynamic, Eigen::Dynamic > &in)
constructor by an input Eigen::Array<T,Eigen::Dynamic,1>
Definition: sis.hpp:1178
Linop This class creates a Linear operator to solve TPBVPs.
Definition: sis.hpp:2560
Eigen::Matrix< std::complex< T >, Eigen::Dynamic, Eigen::Dynamic > MatAppend(const LinopMat< std::complex< T > > &Lmat_, const BcMat< std::complex< T > > &bc_)
Definition: sis.hpp:10160
valarray< T > imag(const valarray< complex< T > > &in)
imaginary part of a complex valarray
Definition: sis.hpp:291
void compute(const LinopMat< std::complex< T > > &Lmat_, const LinopMat< std::complex< T > > &Mmat_, int num_vals, const BcMat< std::complex< T > > &Lbc_)
The main solver for LinopMat. Read about class BcMat to see how this works, also see examples example...
Definition: sis.hpp:5270
#define SIS_SVD_RIGHT
Definition: sis.hpp:469
bool Mp
Stores true if machine precision is reached, else false.
Definition: sis.hpp:3131
void operator=(const BcMat< std::complex< T > > &in)
Definition: sis.hpp:8957
LinopMat< T > & operator,(Linop< T > b)
Overloads comma separator to input Chebfuns into a ChebfunMat. Input type Chebfun.
Definition: sis.hpp:8237
ChebfunMat(const ChebfunMat< T > &in)
Copy constructor.
Definition: sis.hpp:2031
Eigen::Array< T, Eigen::Dynamic, 1 > ev()
Returns property v in terms of Eigen::Array.
Definition: sis.hpp:1297
void compute(const LinopMat< T > &A_, const ChebfunMat< T > &B_, const LinopMat< T > &C_, const BcMat< T > &Lbc_, const BcMat< T > &Rbc_, int num_vals)
Computes the Singular value(s) of a system in the input-output form, here, B(y) is a function and no...
Definition: sis.hpp:9258
std::vector< Eigen::Matrix< std::complex< T >, Eigen::Dynamic, Eigen::Dynamic > > mats2
Definition: sis.hpp:8037
int countc
Definition: sis.hpp:8122
Chebfun< T > & operator()(int i, int j)
Use this to to refer to Chebfuns. For 2D Matrices, refer to matrix element Chebfun by (i...
Definition: sis.hpp:2090
LinopMat(const LinopMat< std::complex< T > > &in)
Copy constructor.
Definition: sis.hpp:8406
Linop(const int &n_)
Makes a Linop by specifying the order n_ of the differential equation.
Definition: sis.hpp:2636
void operator=(const std::complex< T > &right)
To assign a Chebfun to a constant.
Definition: sis.hpp:1802
Chebfun(const Chebfun &in)
Copy conststructor.
Definition: sis.hpp:1210
std::valarray< std::complex< T > > fft(std::valarray< T > in1)
Definition: sis.hpp:544
Linop< T > operator/(T in)
Dividing Linop by scalar.
Definition: sis.hpp:2718
int r
Number of rows.
Definition: sis.hpp:8116
void operator=(const std::valarray< T > &right)
Definition: sis.hpp:1822
LinopMat< std::complex< T > > & operator,(LinopMat< std::complex< T > > b)
Definition: sis.hpp:8672
void compute_with_constraints(const LinopMat< T > &Lmat_, const LinopMat< T > &Mmat_, int num_vals, const BcMat< T > &Lbc_, const BcMat< T > &Mbc_)
Definition: sis.hpp:3827
Chebfun(const Eigen::Array< std::complex< T >, Eigen::Dynamic, 1 > &in)
constructor by an input Eigen::Array<T,Eigen::Eigen::Dynamic,1>
Definition: sis.hpp:1518
Definition: sis.hpp:260
void compute_with_constraints(const LinopMat< T > &Lmat_, const LinopMat< T > &Mmat_, int num_vals, const BcMat< T > &Lbc_embed_, const BcMat< T > &Lbc_append_, const BcMat< T > &Mbc_append_)
Definition: sis.hpp:4603
void setIdentity()
Sets LinopMat to identity.
Definition: sis.hpp:8346
Linop< T > operator-(const Linop< T > &in)
Definition: sis.hpp:12055
Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > P
Definition: sis.hpp:9656
std::valarray< Chebfun< std::complex< T > > > ChebfunVec
This 1D vector of Chebfuns holds all Chebfuns of the ChebfunMat in the row-major format.
Definition: sis.hpp:2266
Chebfun< std::complex< T > > operator()(Chebfun< std::complex< T > > in)
Apply the operator on a Chebfun.
Definition: sis.hpp:2867
ChebfunMat< std::complex< T > > eigenvectors
Definition: sis.hpp:5232
EigenSorter()
Null constructor.
Definition: sis.hpp:3140
Eigen::Matrix< std::complex< T >, Eigen::Dynamic, 1 > coef
Stores the coefficients in the differential equation.
Definition: sis.hpp:2783
std::valarray< std::complex< T > > dealias_prod_2D(std::valarray< std::complex< T > > a, std::valarray< std::complex< T > > b, int Nx, int Nz)
dealias_prod_2D for a 2D matrix stored in the row-major format, Nx and Nz denote dimensions in x and ...
Definition: sis.hpp:861
double omega_opt
This is the value of at which H-infinity norm occurs.
Definition: sis.hpp:10291
void p2c()
Converts a Chebfun from values in physical-space to coefficients of Chebyshev polynomials.
Definition: sis.hpp:1217
Linop< std::complex< T > > & operator[](int i)
Use this to to refer to Linops. For 1D Matrices, we use the Row major format when refering to [i]...
Definition: sis.hpp:8466
LinopMat< T > Adjoint(const LinopMat< T > &Lmat_)
Computes the adjoint of a linear operator. This is a differential adjoint, and not the conjugate tran...
Definition: sis.hpp:9269
void operator=(Chebfun< T > in)
Definition: sis.hpp:2926
void setConstant(T in)
Sets every member in LinopMat to constant.
Definition: sis.hpp:8608
std::vector< ChebfunMat< std::complex< T > > > eigenvectorsMat
Definition: sis.hpp:3256
std::valarray< T > ifft_cs(std::valarray< std::complex< T > > in)
Definition: sis.hpp:582
Linop(const int &n_)
Makes a Linop by specifying the order n_ of the differential equation.
Definition: sis.hpp:2826
complex< double > ii(0.0, 1.0)
Eigen::Matrix< std::complex< T >, Eigen::Dynamic, Eigen::Dynamic > operator()(const LinopMat< std::complex< T > > &Lmat_, const BcMat< std::complex< T > > &bc_)
Definition: sis.hpp:9872
std::valarray< std::complex< SIS_TYPE > > rev_half_shift(N+1)
void ncc(int n_)
Sets the the size of non-constant coefficient array based on the order of differential equation...
Definition: sis.hpp:3063
void operator=(const Chebfun< T > &in)
assignment operator of Chebfun
Definition: sis.hpp:1793
std::valarray< std::complex< T > > v
Stores a flag to denote if function is in Cheb-space or physical space.
Definition: sis.hpp:1495
LinopMat(int r_, int c_)
Initializes a Linop Matrix of r_ rows and c_ columns.
Definition: sis.hpp:8146
void sortByLargestReal()
This function will sort the eigenvalues and vectors by the largest real part.
Definition: sis.hpp:7387
Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > subs_mat
Definition: sis.hpp:9657
void keepConverged()
This will remove all unconverged and infinite eigenvalues from the list.
Definition: sis.hpp:7431
void operator=(const Linop< T > &in)
Definition: sis.hpp:2852
sis::Linop< T > imag()
Definition: sis.hpp:3083
Eigen::Matrix< SIS_TYPE, Eigen::Dynamic, Eigen::Dynamic > yEigen
Definition: sis.hpp:542
std::complex< T > PowerSpectralDensity(const LinopMat< std::complex< T > > &A_, const LinopMat< std::complex< T > > &B_, const LinopMat< std::complex< T > > &C_, const BcMat< std::complex< T > > &Lbc_, const BcMat< std::complex< T > > &Rbc_, const BcMat< std::complex< T > > &Lbc_adjoint_, const BcMat< std::complex< T > > &Rbc_adjoint_)
Definition: sis.hpp:10676
#define PI
Definition: sis.hpp:464
std::vector< Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > > mats
Definition: sis.hpp:7959
LinopMat< std::complex< T > > & operator,(std::valarray< std::complex< T > > b)
Overloads comma separator to input Chebfuns into a ChebfunMat. Input type valarray.
Definition: sis.hpp:8578
void operator=(const BcMat< T > &in)
Definition: sis.hpp:8857
LinopMat< T > & operator<<(T b)
Use this to input multiple Linops to the LinopMat using comma separators. Input type of constant...
Definition: sis.hpp:8176
ChebfunMat< std::complex< T > > operator()(ChebfunMat< std::complex< T > > in)
Use this to apply a LinopMat on a ChebfunMat.
Definition: sis.hpp:8477
Chebfun< std::complex< T > > & operator[](int i)
Use this to to refer to Chebfuns. For 1D Matrices, we use the Row major format when refering to [i]...
Definition: sis.hpp:2324
Eigen::Matrix< std::complex< T >, Eigen::Dynamic, 1 > solution
Stores the solution.
Definition: sis.hpp:2820
std::complex< T > size(const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &in)
This function is useful to see size of Eigen matrices. Returns a complex number, where the real part ...
Definition: sis.hpp:901
Eigen::Matrix< std::complex< T >, Eigen::Dynamic, Eigen::Dynamic > P
Definition: sis.hpp:9857
ChebfunMat(int r_, int c_)
Initializes a Chebfun Matrix of r_ rows and c_ columns.
Definition: sis.hpp:2271
int rows()
Definition: sis.hpp:8865
void operator=(Chebfun< std::complex< T > > in)
Definition: sis.hpp:2936
Linop< std::complex< T > > operator/(std::complex< T > in)
Dividing Linop by scalar.
Definition: sis.hpp:2960
Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > operator()(const LinopMat< T > &Lmat)
Discretization based on a previous call with Boundary conditions. Then other LinopMats can be discret...
Definition: sis.hpp:9802
Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > operator()(const LinopMat< T > &Lmat_, const BcMat< T > &bc_)
Definition: sis.hpp:9665
void operator=(const ChebfunMat< std::complex< T > > &in)
Assignment operator.
Definition: sis.hpp:2289
void operator+=(Chebfun< std::complex< T > > b)
Add complex chebfun to self.
Definition: sis.hpp:1828
std::vector< int > highest_each_column
Definition: sis.hpp:9659
void compute(int n_)
Call this to generate integration matrices for highest order n.
Definition: sis.hpp:7971
std::valarray< T > idct(const std::valarray< T > &u)
Definition: sis.hpp:638
void vtkExportCartesian2D3C(const std::string &flnm, const std::valarray< double > &y, const std::valarray< double > &z, const std::valarray< double > &u, const std::valarray< double > &v, const std::valarray< double > &w, const std::valarray< double > &p)
Exports all data of 2D3C to a file. There are two dimensions, the wall-normal and the spanwise...
Definition: sis.hpp:11806
void operator+=(Chebfun right)
Add a Chebfun to itself. If both are in same space, return will be in same space, else the lhs will r...
Definition: sis.hpp:1382
Discretize()
Null Constructor.
Definition: sis.hpp:9867
void vtkExportCartesian3D(const std::string &flnm, const std::valarray< double > &x, const std::valarray< double > &y, const std::valarray< double > &z, const std::valarray< double > &u, const std::valarray< double > &v, const std::valarray< double > &w, const std::valarray< double > &p)
Exports all data of 3D velocity to a file. VTK file can be directly exported into paraview...
Definition: sis.hpp:11862
string int2str(int i)
Definition: sis.hpp:445
bool isMachinePrecision()
Definition: sis.hpp:1461
void setIdentity()
Sets LinopMat to identity.
Definition: sis.hpp:8626
void operator+=(const Linop< T > &in)
Add to self:
Definition: sis.hpp:2680
void c2p()
Converts a Chebfun from Chebyshev coefficients to values in physical space.
Definition: sis.hpp:1615
int c
Number of columns.
Definition: sis.hpp:2015
int nCk_(int n, int k)
Definition: sis.hpp:9043
Eigen::Matrix< std::complex< T >, Eigen::Dynamic, 1 > eigenvalues
Definition: sis.hpp:3257
void operator=(T right)
Equating the Chebfun to a constant.
Definition: sis.hpp:1345
LinopMat< T > & operator,(T b)
Overloads comma separator to input Chebfuns into a ChebfunMat. Input type constant.
Definition: sis.hpp:8223
Eigen::Matrix< std::complex< T >, Eigen::Dynamic, Eigen::Dynamic > operator()(T p)
Use this to evaluate the whole ChebfunMat at a given point. Point must lie in the domain...
Definition: sis.hpp:2361
Eigen::Matrix< std::complex< T >, Eigen::Dynamic, Eigen::Dynamic > ChebDiff(const LinopMat< std::complex< T > > &Lmat_)
Chebyshev differentiation operator for LinopMat.
Definition: sis.hpp:10067
int c
Number of columns.
Definition: sis.hpp:8118
This class represents a block matrix operator. It is a matrix of operators.
Definition: sis.hpp:528
bool isMachinePrecisionHalf()
Definition: sis.hpp:1468
void p2c()
Converts every element to Cheb-space, if not already in Cheb-space.
Definition: sis.hpp:2330
T minVal
Stores the smallest value in the Chebyshev series.
Definition: sis.hpp:3134
Given a linear block matrix operator and appropriate boundary conditions, this class will produce an ...
Definition: sis.hpp:532
sis::Linop< T > real()
Definition: sis.hpp:3068
std::valarray< std::complex< SIS_TYPE > > yc(N+1)
T operator()(int n, int k)
Definition: sis.hpp:9041
std::valarray< std::complex< T > > operator-(std::complex< T > left, std::valarray< T > right)
Subtracting a real valarray from a complex number.
Definition: sis.hpp:344
void operator=(const Eigen::Array< std::complex< T >, Eigen::Dynamic, 1 > &in)
Assignment operator for function input, through Eigen array.
Definition: sis.hpp:2907
std::complex< T > operator()(const double &a)
To assign a Chebfun through a array.
Definition: sis.hpp:1879
void setConstant(T in)
sets the all the Chebfuns in the ChebfunMat to constant
Definition: sis.hpp:2498
Eigen::Matrix< std::complex< T >, Eigen::Dynamic, Eigen::Dynamic > operator()(int i, int j, int ord)
Calling BcMat(i,j, ord) will produce row vector representing [---—][a0 a1 ... an C0 C1]^T...
Definition: sis.hpp:8979
Definition: sis.hpp:461
Linop< T > operator*(Linop< T > L1, Linop< T > L2)
These are used to define operator compositions, L1(L2). It is defined as operator multiplication...
Definition: sis.hpp:12928
void operator=(const std::valarray< std::complex< T > > &right)
To assign a Chebfun through a valarray.
Definition: sis.hpp:1821
std::valarray< Linop< T > > LinopVec
This 1D vector of Linops holds all Linops of the LinopMat in the row-major format.
Definition: sis.hpp:8121
Chebfun()
Null constructor.
Definition: sis.hpp:1499
#define SIS_SVD_LEFT
Definition: sis.hpp:468
int n
The order of the Linear differential operator.
Definition: sis.hpp:2566
void set()
Sets the the size of coefficient array based on the order of differential equation. Suppose order is 3, then the size of array needed is 4.
Definition: sis.hpp:2733
Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > operator()(T p)
Use this to evaluate the whole ChebfunMat at a given point. Point must lie in the domain...
Definition: sis.hpp:2118
std::valarray< std::complex< T > > dou2com(const std::valarray< T > &a, const std::valarray< T > &b)
Use this to make a complex valarray out of two real valarrays.
Definition: sis.hpp:264
void compute(int n_)
Call this to generate integration matrices for highest order n.
Definition: sis.hpp:8047
void operator=(const Chebfun &right)
To assign a Chebfun through another Chebfun.
Definition: sis.hpp:1355
Linop(const Linop< T > &in)
Copy constructor.
Definition: sis.hpp:2643
int cols()
Definition: sis.hpp:8869
void operator=(const Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > &in)
Assigning a ChebfunMat using a Eigen-matrix. Eigen-Matrix should be of size (r*(N+1), c), else an error is thrown. This implies that one must have called the resize(r,c) function before using this.
Definition: sis.hpp:2055
Eigen::Matrix< std::complex< T >, Eigen::Dynamic, Eigen::Dynamic > invmat_temp
Definition: sis.hpp:9861
Eigen::Matrix< T, Eigen::Dynamic, 1 > solution
Stores the solution.
Definition: sis.hpp:2629
int NCC
Flag to set (value 1) for enabling nonconstant coefficients.
Definition: sis.hpp:2565
Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > ChebfunMat2EigenMat()
Returns an Eigen matrix representing the ChebfunMat.
Definition: sis.hpp:2227
std::valarray< T > dct(const std::valarray< T > &x)
Definition: sis.hpp:617
ChebfunMat(const ChebfunMat< std::complex< T > > &in)
Copy constructor.
Definition: sis.hpp:2279
ChebfunMat< T > & operator,(std::valarray< T > b)
Overloads comma separator to input Chebfuns into a ChebfunMat. Input type valarray.
Definition: sis.hpp:2192
Eigen::Array< T, Eigen::Dynamic, 1 > operator*(std::valarray< T > left, const Eigen::Array< T, Eigen::Dynamic, 1 > &right)
Definition: sis.hpp:12544
Chebfun< std::complex< T > > solve(Chebfun< std::complex< T > > in)
This function solves the differential equation. See solve for details.
Definition: sis.hpp:3099
LinopMat< std::complex< T > > cTranspose()
Definition: sis.hpp:8790
LinopMat< T > & operator,(LinopMat< T > b)
Definition: sis.hpp:8282
void operator=(const Eigen::Matrix< std::complex< T >, Eigen::Dynamic, 1 > &right)
To assign a Chebfun through a vector.
Definition: sis.hpp:1813
Linop< std::complex< T > > operator/(T in)
Dividing Linop by scalar.
Definition: sis.hpp:2947
void operator+=(const Linop< T > &in)
Definition: sis.hpp:2860
std::valarray< std::complex< T > > operator+(std::complex< T > left, std::valarray< T > right)
Adding a complex number to a real valarray.
Definition: sis.hpp:322
Eigen::Matrix< std::complex< T >, Eigen::Dynamic, Eigen::Dynamic > operator()(const LinopMat< std::complex< T > > &Lmat_)
Discretization based on a previous call with Boundary conditions. Then other LinopMats can be discret...
Definition: sis.hpp:10017
LinopMat< std::complex< T > > & operator,(LinopMat< T > b)
Definition: sis.hpp:8747
void clear()
Definition: sis.hpp:8019
int NCC
Flag to set (value 1) for enabling nonconstant coefficients.
Definition: sis.hpp:2773
T operator()(const T &a)
To assign a Chebfun through a Array.
Definition: sis.hpp:1402
std::valarray< std::complex< T > > fft2(std::valarray< T > in1, int Nx, int Nz)
fft2 for a 2D matrix stored in the row-major format, Nx and Nz denote dimensions in x and z...
Definition: sis.hpp:708
Eigen::Matrix< std::complex< T >, Eigen::Dynamic, Eigen::Dynamic > MultMat()
This function returns the Toeplitz + almost Hankel matrix needed to express multiplication of two Che...
Definition: sis.hpp:1742
void operator=(const Eigen::Matrix< std::complex< T >, Eigen::Dynamic, Eigen::Dynamic > &in)
Assigning a ChebfunMat using a Eigen-matrix. Eigen-Matrix should be of size (r*(N+1), c), else an error is thrown. This implies that one must have called the resize(r,c) function before using this.
Definition: sis.hpp:2481
void compute(const LinopMat< T > &A_, const BcMat< T > &Lbc_, const BcMat< T > &Rbc_, int num_vals)
Computes the singular values/functions of a Linear block matrix operator.
Definition: sis.hpp:9139
int numMp
Stores number of Chebyshev coefficients in which MP is reached, if not reached, it is set to N+1...
Definition: sis.hpp:3132
ChebfunMat< T > & operator,(T b)
Overloads comma separator to input Chebfuns into a ChebfunMat. Input type constant.
Definition: sis.hpp:2175
Eigen::Matrix< T, Eigen::Dynamic, 1 > coef
Stores the coefficients in the differential equation.
Definition: sis.hpp:2569
void setChebPts(std::valarray< T > &in)
This function sets points to evaluate a function so that a DCT will give represent the same function ...
Definition: sis.hpp:920
Chebfun(const Eigen::Matrix< std::complex< T >, Eigen::Dynamic, 1 > &in)
constructor by an input Eigen::Matrix<T,Eigen::Eigen::Dynamic,1>
Definition: sis.hpp:1533
Eigen::Matrix< T, Eigen::Dynamic, 1 > diff(const Eigen::Matrix< T, Eigen::Dynamic, 1 > &u)
Chebyshev differentiation operator for a vector of Chebyshev coefficients.
Definition: sis.hpp:987
ChebfunMat()
Null constructor.
Definition: sis.hpp:2268
valarray< complex< T > > pow(valarray< complex< T > > base, T power)
Definition: sis.hpp:453
ChebfunMat< std::complex< T > > cTranspose()
Definition: sis.hpp:2515
double gamma_opt
This is the H-infinity norm.
Definition: sis.hpp:10289
void operator=(const std::valarray< T > &in)
Assignment operator for function input, through valarray.
Definition: sis.hpp:2914
Eigen::Matrix< std::complex< SIS_TYPE >, Eigen::Dynamic, Eigen::Dynamic > ycEigen
Definition: sis.hpp:541
ChebfunMat< std::complex< T > > coefFun
Use this to input all non-constant coefficients. See coefFun for details.
Definition: sis.hpp:2818
Eigen::Array< T, Eigen::Dynamic, 1 > evi()
Returns property v in terms of Eigen::Array.
Definition: sis.hpp:1721
std::vector< int > highest_each_column
Definition: sis.hpp:9862
LinopMat(const LinopMat< T > &in)
Copy constructor.
Definition: sis.hpp:8154
ChebfunMat< std::complex< T > > & operator,(Eigen::Array< std::complex< T >, Eigen::Dynamic, 1 > b)
Overloads comma separator to input Chebfuns into a ChebfunMat. Input type complex Eigen array...
Definition: sis.hpp:2434
void compute(const LinopMat< std::complex< T > > &Lmat_, const BcMat< std::complex< T > > &bc_)
Call this with an input Linear operator to solve for eigenvalues and vectors.
Definition: sis.hpp:5257
LinopMat< T > L
Definition: sis.hpp:8831
ChebfunMat< T > operator+(ChebfunMat< T > a, ChebfunMat< T > b)
Defining addition of ChebfunMats.
Definition: sis.hpp:11987
std::vector< Eigen::Matrix< std::complex< T >, Eigen::Dynamic, Eigen::Dynamic > > mats
Definition: sis.hpp:8035
void keep(int n)
This will keep only n and remove the rest. Use this carefully. Only first n will be kept...
Definition: sis.hpp:7468
Linop< std::complex< T > > operator*(std::complex< T > in)
Multiplying Linop by scalar.
Definition: sis.hpp:3023
MatGen(int n_)
Constructor.
Definition: sis.hpp:8044
ChebfunMat< T > & operator<<(T b)
Use this to input multiple Chebfuns to the ChebfunMat using comma separators. Input type of constant...
Definition: sis.hpp:2073
Chebfun(const std::valarray< T > &in)
constructor by an input valarray
Definition: sis.hpp:1167
void compute(Linop< T > L, Linop< T > M, int num_vals)
Call this with an input Linear operator to solve for eigenvalues and vectors. The number of Eigen val...
Definition: sis.hpp:3267
void vtkExportCartesianStress3D(const std::string &flnm, const std::valarray< double > &x, const std::valarray< double > &y, const std::valarray< double > &z, const std::valarray< double > &t11, const std::valarray< double > &t12, const std::valarray< double > &t13, const std::valarray< double > &t22, const std::valarray< double > &t23, const std::valarray< double > &t33)
Exports stress data to a file. VTK file can be directly exported into paraview, or into Python using ...
Definition: sis.hpp:11923
LinopMat< std::complex< T > > & operator,(std::valarray< T > b)
Overloads comma separator to input Chebfuns into a ChebfunMat. Input type valarray.
Definition: sis.hpp:8585
void setConstant(std::complex< T > in)
sets the all the Chebfuns in the ChebfunMat to constant
Definition: sis.hpp:2507
Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > feval2D(std::valarray< ChebfunMat< T > > Amat, int r, int c, T a)
Definition: sis.hpp:9076
BcMat(int m_, int n_)
Definition: sis.hpp:8839
void p2c()
Converts a Chebfun from values in physical-space to coefficients of Chebyshev polynomials.
Definition: sis.hpp:1555
Eigen::Array< std::complex< T >, Eigen::Dynamic, 1 > dou2com(const Eigen::Array< T, Eigen::Dynamic, 1 > &a, const Eigen::Array< T, Eigen::Dynamic, 1 > &b)
Use this to make a complex array out of two Eigen real valarrays.
Definition: sis.hpp:1133
void compute(const LinopMat< std::complex< T > > &A_, const LinopMat< std::complex< T > > &B_, const LinopMat< std::complex< T > > &C_, const BcMat< std::complex< T > > &Lbc_, const BcMat< std::complex< T > > &Rbc_, const BcMat< std::complex< T > > &Lbc_adjoint_, const BcMat< std::complex< T > > &Rbc_adjoint_, int num_vals)
Computes singular values of the frequency response operator of a system in the input-output form...
Definition: sis.hpp:10901
Linop< std::complex< T > > operator*(T in)
Multiplying Linop by scalar.
Definition: sis.hpp:2973
void operator=(T in)
Assignment operator for constant input.
Definition: sis.hpp:2899
This class computes various SingularValues of a differential block matrix operator using using it&#39;s a...
Definition: sis.hpp:531
void ncc()
Sets the the size of non-constant coefficient array based on the order of differential equation...
Definition: sis.hpp:2751
T L2norm()
Returns the L2norm of the function.
Definition: sis.hpp:1444
BcMat< T > AdjointBc_analytical(const LinopMat< T > &Lmat_, const BcMat< T > &Lbc_, const BcMat< T > &Rbc_)
Computes adjoint boundary conditions analytically, needs boundary conditions all right boundary condi...
Definition: sis.hpp:9408
std::valarray< Chebfun< T > > ChebfunVec
This 1D vector of Chebfuns holds all Chebfuns of the ChebfunMat in the row-major format.
Definition: sis.hpp:2018
ChebfunMat< std::complex< T > > & operator,(std::valarray< std::complex< T > > b)
Overloads comma separator to input Chebfuns into a ChebfunMat. Input type complex valarray...
Definition: sis.hpp:2444
Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > operator()(int i, int j, int ord)
Calling BcMat(i,j, ord) will produce row vector representing [---—][a0 a1 ... an C0 C1]^T...
Definition: sis.hpp:8878
ChebfunMat< T > solve(const ChebfunMat< T > &in)
Solves an input ChebfunMat, Dimensions of ChebfunMat have to be (c,1)
Definition: sis.hpp:8245
void operator+=(Chebfun< T > b)
Add real Chebfun to self.
Definition: sis.hpp:1844
LinopMat(const LinopMat< T > &in)
Copy constructor.
Definition: sis.hpp:8417
int N
Specifies number of Chebyshev polynomials, default N = 31.
Definition: sis.hpp:472
Eigen::Matrix< std::complex< T >, Eigen::Dynamic, Eigen::Dynamic > ChebfunMat2EigenMat()
Returns an Eigen matrix representing the ChebfunMat.
Definition: sis.hpp:2452
void setConstant(T in)
Sets every member in LinopMat to constant.
Definition: sis.hpp:8337
std::complex< T > PowerSpectralDensity(const LinopMat< std::complex< T > > &A_, const LinopMat< std::complex< T > > &B_, const LinopMat< std::complex< T > > &C_, const BcMat< std::complex< T > > &Lbc_, const BcMat< std::complex< T > > &Rbc_)
Computes power spectral density from the frequency response operator of a system in the input-output ...
Definition: sis.hpp:10580
int dct_flag
Definition: sis.hpp:1153
LinopMat< T > cTranspose()
Definition: sis.hpp:8325
#define SIS_CHEB_SPACE
Definition: sis.hpp:471
Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > MultMat()
This function returns the Toeplitz + almost Hankel matrix needed to express multiplication of two Che...
Definition: sis.hpp:1309
void compute(Eigen::Matrix< std::complex< T >, Eigen::Dynamic, 1 > in)
Computes Mp and numMp for Linops.
Definition: sis.hpp:3148
void ncc()
Sets the the size of non-constant coefficient array based on the order of differential equation...
Definition: sis.hpp:3054
Chebfun< T > cumsum()
Returns a Chebfun that represents the indefinite integral of the Chebfun.
Definition: sis.hpp:1427
Chebfun(const std::valarray< std::complex< T > > &in)
constructor by an input valarray
Definition: sis.hpp:1507
void operator=(const Chebfun< std::complex< T > > &in)
assignment operator of Chebfun
Definition: sis.hpp:1788
void p2c()
Converts every element to Cheb-space, if not already in Cheb-space.
Definition: sis.hpp:2093
void computeAppend(const LinopMat< std::complex< T > > &Lmat_, const LinopMat< std::complex< T > > &Mmat_, int num_vals, const BcMat< std::complex< T > > &Lbc_)
Another main solver for LinopMat, a minimal solver for eigenvalues only. LAPACK needs to be linked to...
Definition: sis.hpp:5970
void resize(int m_, int n_)
Definition: sis.hpp:8848
MatGen()
Null Constructor.
Definition: sis.hpp:8042
GeneralizedEigenSolver()
Null constructor.
Definition: sis.hpp:3259
void operator=(const ChebfunMat< T > &in)
Assignment operator.
Definition: sis.hpp:2299
int ind
Definition: sis.hpp:256
void compute(const Eigen::Matrix< std::complex< T >, Eigen::Dynamic, Eigen::Dynamic > &L_, const Eigen::Matrix< std::complex< T >, Eigen::Dynamic, Eigen::Dynamic > &M_, Discretize< std::complex< T > > Dis)
This is used to use a discretization to compute eigenvalues.
Definition: sis.hpp:7556
Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > mat_temp
Definition: sis.hpp:9658
Linop< std::complex< T > > & operator()(int i, int j)
Use this to to refer to Linop. For 2D Matrices, refer to matrix element Linop by (i,j) with the row and column index. Indices start from 0.
Definition: sis.hpp:8471
void c2p()
Converts every element to phys-space, if not already in phys-space.
Definition: sis.hpp:2104
Chebfun< T > conj(Chebfun< T > in)
Complex conjugate of a Chebfun.
Definition: sis.hpp:1486
valarray< T > real(const valarray< complex< T > > &in)
real part of a complex valarray
Definition: sis.hpp:280
void resize(int r_, int c_)
This clears all contents in the ChebfunMat, and then creates a fresh ChebfunMat of size r_ x c_...
Definition: sis.hpp:2166
Linop< T > & operator[](int i)
Use this to to refer to Linops. For 1D Matrices, we use the Row major format when refering to [i]...
Definition: sis.hpp:8185
Eigen::Matrix< int, Eigen::Dynamic, 1 > MPorNot
Definition: sis.hpp:5234
This class computes the eigenvalues and eigenvectors (functions) of a Linear operator Linop...
Definition: sis.hpp:7942
bool go_to_next_row
Definition: sis.hpp:8124
void compute(const LinopMat< T > &Lmat_, const LinopMat< T > &Mmat_, int num_vals, const BcMat< T > &Lbc_)
This will use do the same work as compute(), but will overide all boundary conditions specified throu...
Definition: sis.hpp:3276
void compute(Eigen::Matrix< std::complex< T >, Eigen::Dynamic, 1 > in, int c)
Computes Mp and numMp for LinopMats.
Definition: sis.hpp:3183
Eigen::Matrix< std::complex< T >, Eigen::Dynamic, Eigen::Dynamic > subs_mat
Definition: sis.hpp:9858
void c2p()
Converts a Chebfun from Chebyshev coefficients to values in physical space.
Definition: sis.hpp:1257
This class will solve the generalized eigenvalue problem for two linear operators. One of them can be singular.
Definition: sis.hpp:3253
T trunc()
Provides the truncation defined in terms of the abs(last + last_but_one)/2.0.
Definition: sis.hpp:1478
Chebfun(const Chebfun< std::complex< T > > &in)
Copy constructor.
Definition: sis.hpp:1548
void operator=(const LinopMat &in)
Assignment operator.
Definition: sis.hpp:8164
This class stores functions and values needed to sort Eigenvalues.
Definition: sis.hpp:3126
void operator=(const std::complex< T > &in)
Assignment operator for constant input.
Definition: sis.hpp:2891
void operator=(const std::valarray< std::complex< T > > &in)
Definition: sis.hpp:2920
std::vector< Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > > con_mats
Definition: sis.hpp:7963
ChebfunMat< T > & operator,(Eigen::Array< T, Eigen::Dynamic, 1 > b)
Overloads comma separator to input Chebfuns into a ChebfunMat. Input type Eigen array.
Definition: sis.hpp:2182
LinopMat< std::complex< T > > & operator,(Eigen::Array< std::complex< T >, Eigen::Dynamic, 1 > b)
Overloads comma separator to input Chebfuns into a ChebfunMat. Input type Eigen array.
Definition: sis.hpp:8569
std::valarray< SIS_TYPE > y(N+1)
Eigen::Array< T, Eigen::Dynamic, 1 > evr()
Returns property vr in terms of Eigen::Array.
Definition: sis.hpp:1711
#define SIS_SVD
Definition: sis.hpp:467
This class holds a matrix of Chebfuns.
Definition: sis.hpp:2004
void setConstant(double in)
sets the all the Chebfuns in the ChebfunMat to constant
Definition: sis.hpp:2206
void resize(int r_, int c_)
This clears all contents in the LinopMat, and then creates a fresh LinopMat of size r_ x c_...
Definition: sis.hpp:8214
Chebfun< std::complex< T > > & operator()(int i, int j)
Use this to to refer to Chebfuns. For 2D Matrices, refer to matrix element Chebfun by (i...
Definition: sis.hpp:2353
ChebfunMat< T > & operator,(Chebfun< T > b)
Overloads comma separator to input Chebfuns into a ChebfunMat. Input type Chebfun.
Definition: sis.hpp:2199
int c
Number of columns.
Definition: sis.hpp:2263
Eigen::Matrix< std::complex< T >, Eigen::Dynamic, 1 > eigenvalues
Definition: sis.hpp:5233
Eigen::Matrix< T, Eigen::Dynamic, Eigen::Dynamic > vals
Definition: sis.hpp:8833
Eigen::Matrix< T, Eigen::Dynamic, 1 > integ(const Eigen::Matrix< T, Eigen::Dynamic, 1 > &u)
Chebyshev integration operator for a vector of Chebyshev coefficients.
Definition: sis.hpp:1031
std::valarray< std::complex< SIS_TYPE > > half_shift(N+1)
void setConstant(std::complex< T > in)
Sets every member in LinopMat to complex constant.
Definition: sis.hpp:8617
void resize(int r_, int c_)
This clears all contents in the ChebfunMat, and then creates a fresh ChebfunMat of size r_ x c_...
Definition: sis.hpp:2417
LinopMat< std::complex< T > > & operator,(Linop< std::complex< T > > b)
Overloads comma separator to input Chebfuns into a ChebfunMat. Input type Chebfun.
Definition: sis.hpp:8593
Eigen::Matrix< std::complex< T >, Eigen::Dynamic, Eigen::Dynamic > A1
Definition: sis.hpp:9860
void operator=(const std::valarray< T > &in)
Assignment operator for function input, through valarray.
Definition: sis.hpp:2702
void operator=(const std::valarray< T > &right)
To assign a Chebfun through a valarray.
Definition: sis.hpp:1368
Linop< T > conj(Linop< T > in)
Definition: sis.hpp:11976
void operator=(const Linop< T > &in)
Assignment operator.
Definition: sis.hpp:2654
Linop< T > & operator()(int i, int j)
Use this to to refer to Linop. For 2D Matrices, refer to matrix element Linop by (i,j) with the row and column index. Indices start from 0.
Definition: sis.hpp:8193
ChebfunMat(int r_, int c_)
Initializes a Chebfun Matrix of r_ rows and c_ columns.
Definition: sis.hpp:2023
std::vector< Eigen::Matrix< std::complex< T >, Eigen::Dynamic, Eigen::Dynamic > > con_mats
Definition: sis.hpp:8039
LinopMat< std::complex< T > > Adjoint(const LinopMat< std::complex< T > > &Lmat_)
Computes the formal adjoint of a Linear operator. This is a differential adjoint, and not the conjuga...
Definition: sis.hpp:11327
void operator=(const Eigen::Array< T, Eigen::Dynamic, 1 > &in)
Assignment operator for function input, through Eigen array.
Definition: sis.hpp:2695