16 #include "linalg/Matrix.h"
17 #include "linalg/Vector.h"
18 #include "linalg/scalapack_wrapper.h"
19 #include "utils/Utilities.h"
20 #include "utils/CSVDatabase.h"
21 #include "utils/HDFDatabase.h"
27 #if __cplusplus >= 201103L
30 #include <boost/shared_ptr.hpp>
34 #define zgetrf CAROM_FC_GLOBAL(zgetrf, ZGETRF)
35 #define zgetri CAROM_FC_GLOBAL(zgetri, ZGETRI)
39 void zgetrf(
int*,
int*,
double*,
int*,
int*,
int*);
42 void zgetri(
int*,
double*,
int*,
int*,
double*,
int*,
int*);
47 DMDc::DMDc(
int dim,
int dim_c, std::shared_ptr<Vector> state_offset)
49 CAROM_VERIFY(dim > 0);
50 CAROM_VERIFY(dim_c > 0);
54 MPI_Initialized(&mpi_init);
56 MPI_Init(
nullptr,
nullptr);
59 MPI_Comm_rank(MPI_COMM_WORLD, &
d_rank);
68 DMDc::DMDc(
int dim,
int dim_c,
double dt, std::shared_ptr<Vector> state_offset)
70 CAROM_VERIFY(dim > 0);
71 CAROM_VERIFY(dim_c > 0);
72 CAROM_VERIFY(dt > 0.0);
76 MPI_Initialized(&mpi_init);
78 MPI_Init(
nullptr,
nullptr);
81 MPI_Comm_rank(MPI_COMM_WORLD, &
d_rank);
95 MPI_Initialized(&mpi_init);
97 MPI_Init(
nullptr,
nullptr);
100 MPI_Comm_rank(MPI_COMM_WORLD, &
d_rank);
105 load(base_file_name);
109 std::shared_ptr<Matrix> & phi_real,
110 std::shared_ptr<Matrix> & phi_imaginary,
111 std::shared_ptr<Matrix> & B_tilde,
int k,
double dt,
double t_offset,
112 std::shared_ptr<Vector> & state_offset, std::shared_ptr<Matrix> & basis)
116 MPI_Initialized(&mpi_init);
118 MPI_Init(
nullptr,
nullptr);
121 MPI_Comm_rank(MPI_COMM_WORLD, &
d_rank);
144 CAROM_VERIFY(u_in != 0);
145 CAROM_VERIFY(t >= 0.0);
162 if (
d_rank == 0) std::cout <<
"Removing existing snapshot at time: " <<
178 d_snapshots.push_back(std::shared_ptr<Vector>(sample));
183 d_controls.push_back(std::shared_ptr<Vector>(control));
193 CAROM_VERIFY(f_snapshots->numColumns() > 1);
194 CAROM_VERIFY(f_controls->numColumns() == f_snapshots->numColumns() - 1);
195 CAROM_VERIFY(energy_fraction > 0 && energy_fraction <= 1);
204 CAROM_VERIFY(f_snapshots->numColumns() > 1);
205 CAROM_VERIFY(f_controls->numColumns() == f_snapshots->numColumns() - 1);
206 CAROM_VERIFY(k > 0 && k <= f_snapshots->numColumns() - 1);
212 std::pair<Matrix*, Matrix*>
222 int input_control_dim = (B == NULL) ? controls.
numRows() : 0;
231 for (
int i = 0; i < snapshots.
numRows(); i++)
233 for (
int j = 0; j < snapshots.
numColumns() - 1; j++)
235 f_snapshots_in->
item(i, j) = snapshots(i, j);
236 f_snapshots_out->
item(i, j) = snapshots(i, j + 1);
245 for (
int i = 0; i < controls.
numRows(); i++)
249 for (
int j = 0; j < snapshots.
numColumns() - 1; j++)
251 f_snapshots_in->
item(snapshots.
numRows() + i, j) = controls.
item(i, j);
256 std::unique_ptr<Matrix> Bf = B->
mult(controls);
257 *f_snapshots_out -= *Bf;
261 return std::pair<Matrix*,Matrix*>(f_snapshots_in, f_snapshots_out);
266 const Matrix & f_controls,
272 f_snapshots, f_controls, B);
273 Matrix* f_snapshots_in = f_snapshot_pair.first;
274 Matrix* f_snapshots_out = f_snapshot_pair.second;
280 CAROM_VERIFY(MPI_Allgather(MPI_IN_PLACE,
286 MPI_COMM_WORLD) == MPI_SUCCESS);
288 row_offset[i] = row_offset[i + 1] - row_offset[i];
291 CAROM_VERIFY(row_offset[0] == 0);
296 SLPK_Matrix svd_input;
299 initialize_matrix(&svd_input, f_snapshots_in->
numColumns(),
305 scatter_block(&svd_input, 1, row_offset[rank] + 1,
308 row_offset[rank + 1] - row_offset[rank], rank);
311 std::unique_ptr<SVDManager> d_factorizer_in(
new SVDManager);
314 svd_init(d_factorizer_in.get(), &svd_input);
315 d_factorizer_in->dov = 1;
316 factorize(d_factorizer_in.get());
317 free_matrix_data(&svd_input);
324 d_sv.push_back(d_factorizer_in->S[i]);
333 double total_energy = 0.0;
336 total_energy += d_factorizer_in->S[i];
338 double current_energy = 0.0;
341 current_energy += d_factorizer_in->S[i];
351 if (
d_rank == 0) std::cout <<
"Using " << d_k_in <<
" basis vectors out of " <<
355 std::unique_ptr<Matrix> d_basis_in(
new Matrix(f_snapshots_in->
numRows(), d_k_in,
362 gather_block(&d_basis_in->item(0, 0), d_factorizer_in->V,
363 1, row_offset[
static_cast<unsigned>(
d_rank)]+1,
364 d_k_in, row_offset[
static_cast<unsigned>(
d_rank) + 1] -
365 row_offset[
static_cast<unsigned>(
d_rank)],
370 gather_transposed_block(&d_basis_right->
item(0, 0), d_factorizer_in->U, 1, 1,
375 for (
int i = 0; i < d_k_in; ++i)
377 d_S_inv->
item(i, i) = 1 / d_factorizer_in->S[
static_cast<unsigned>(i)];
386 CAROM_VERIFY(MPI_Allgather(MPI_IN_PLACE,
392 MPI_COMM_WORLD) == MPI_SUCCESS);
394 row_offset[i] = row_offset[i + 1] - row_offset[i];
397 CAROM_VERIFY(row_offset[0] == 0);
402 SLPK_Matrix svd_output;
405 initialize_matrix(&svd_output, f_snapshots_out->
numColumns(),
411 scatter_block(&svd_output, 1, row_offset[rank] + 1,
414 row_offset[rank + 1] - row_offset[rank], rank);
417 std::unique_ptr<SVDManager> d_factorizer_out(
new SVDManager);
420 svd_init(d_factorizer_out.get(), &svd_output);
421 d_factorizer_out->dov = 1;
422 factorize(d_factorizer_out.get());
423 free_matrix_data(&svd_output);
430 d_sv.push_back(d_factorizer_out->S[i]);
438 double total_energy = 0.0;
441 total_energy += d_factorizer_out->S[i];
443 double current_energy = 0.0;
446 current_energy += d_factorizer_out->S[i];
456 if (
d_rank == 0) std::cout <<
"Using " <<
d_k <<
" basis vectors out of " <<
464 gather_block(&
d_basis->item(0, 0), d_factorizer_out->V,
465 1, row_offset[
static_cast<unsigned>(
d_rank)]+1,
466 d_k, row_offset[
static_cast<unsigned>(
d_rank) + 1] -
467 row_offset[
static_cast<unsigned>(
d_rank)],
471 free_matrix_data(d_factorizer_out->U);
472 free_matrix_data(d_factorizer_out->V);
473 free(d_factorizer_out->U);
474 free(d_factorizer_out->V);
475 free(d_factorizer_out->S);
477 release_context(&svd_output);
481 d_basis.reset(d_basis_in.release());
488 std::unique_ptr<Matrix> d_basis_mult_f_snapshots_out =
d_basis->transposeMult(
490 std::unique_ptr<Matrix> d_basis_mult_f_snapshots_out_mult_d_basis_right =
491 d_basis_mult_f_snapshots_out->mult(*d_basis_right);
492 std::shared_ptr<Matrix> d_A_tilde_orig =
493 d_basis_mult_f_snapshots_out_mult_d_basis_right->mult(
502 for (
int j = 0; j < d_k_in; j++)
504 for (
int i = 0; i < f_snapshots.
numRows(); i++)
506 d_basis_in_state->
item(i, j) = d_basis_in->item(i, j);
508 for (
int i = 0; i < f_controls.
numRows(); i++)
510 d_basis_in_control_transpose->
item(j, i) =
511 d_basis_in->item(f_snapshots.
numRows() + i, j);
514 std::unique_ptr<Matrix> d_basis_state_rot = d_basis_in_state->
transposeMult(
516 d_A_tilde = d_A_tilde_orig->mult(*d_basis_state_rot);
517 d_B_tilde = d_A_tilde_orig->mult(*d_basis_in_control_transpose);
518 delete d_basis_in_state;
519 delete d_basis_in_control_transpose;
535 for (
int i = 0; i < init.
dim(); i++)
537 init(i) = f_snapshots_in->
item(i, 0);
545 delete d_basis_right;
547 delete f_snapshots_in;
548 delete f_snapshots_out;
552 free_matrix_data(d_factorizer_in->U);
553 free_matrix_data(d_factorizer_in->V);
554 free(d_factorizer_in->U);
555 free(d_factorizer_in->V);
556 free(d_factorizer_in->S);
558 release_context(&svd_input);
564 std::shared_ptr<Matrix> d_phi_real_squared =
d_phi_real->transposeMult(
566 std::unique_ptr<Matrix> d_phi_real_squared_2 =
d_phi_imaginary->transposeMult(
568 *d_phi_real_squared += *d_phi_real_squared_2;
570 std::shared_ptr<Matrix> d_phi_imaginary_squared =
d_phi_real->transposeMult(
572 std::unique_ptr<Matrix> d_phi_imaginary_squared_2 =
574 *d_phi_imaginary_squared -= *d_phi_imaginary_squared_2;
576 const int dprs_row = d_phi_real_squared->numRows();
577 const int dprs_col = d_phi_real_squared->numColumns();
578 double* inverse_input =
new double[dprs_row * dprs_col * 2];
579 for (
int i = 0; i < d_phi_real_squared->numRows(); i++)
582 for (
int j = 0; j < d_phi_real_squared->numColumns() * 2; j++)
586 inverse_input[d_phi_real_squared->numColumns() * 2 * i + j] =
587 d_phi_real_squared->item(i, k);
591 inverse_input[d_phi_imaginary_squared->numColumns() * 2 * i + j] =
592 d_phi_imaginary_squared->item(i, k);
601 int mtx_size = d_phi_real_squared->numColumns();
602 int lwork = mtx_size*mtx_size*std::max(10,
d_num_procs);
603 int* ipiv =
new int [mtx_size];
604 double* work =
new double [lwork];
607 zgetrf(&mtx_size, &mtx_size, inverse_input, &mtx_size, ipiv, &info);
608 zgetri(&mtx_size, inverse_input, &mtx_size, ipiv, work, &lwork, &info);
633 std::unique_ptr<Vector> init_real =
d_phi_real->transposeMult(init);
634 std::unique_ptr<Vector> init_imaginary =
d_phi_imaginary->transposeMult(init);
636 std::unique_ptr<Vector> d_projected_init_real_1 =
638 std::unique_ptr<Vector> d_projected_init_real_2 =
642 std::unique_ptr<Vector> d_projected_init_imaginary_1 =
644 std::unique_ptr<Vector> d_projected_init_imaginary_2 =
647 *d_projected_init_imaginary_1);
650 std::unique_ptr<Matrix> B_tilde_f =
d_B_tilde->mult(controls);
651 std::unique_ptr<Matrix> UBf =
d_basis->mult(*B_tilde_f);
652 std::unique_ptr<Matrix> controls_real =
d_phi_real->transposeMult(*UBf);
653 std::unique_ptr<Matrix> controls_imaginary =
d_phi_imaginary->transposeMult(
657 std::unique_ptr<Matrix> d_projected_controls_real_2 =
663 std::unique_ptr<Matrix> d_projected_controls_imaginary_2 =
667 delete [] inverse_input;
673 std::cout <<
"t_offset is updated from " <<
d_t_offset
674 <<
" to " << t_offset << std::endl;
680 std::unique_ptr<Vector>
685 CAROM_VERIFY(t >= 0.0);
689 int n = round(t /
d_dt);
692 std::pair<std::shared_ptr<Matrix>,std::shared_ptr<Matrix>> d_phi_pair =
694 std::shared_ptr<Matrix> d_phi_mult_eigs_real = d_phi_pair.first;
695 std::shared_ptr<Matrix> d_phi_mult_eigs_imaginary = d_phi_pair.second;
697 std::unique_ptr<Vector> d_predicted_state_real_1 = d_phi_mult_eigs_real->mult(
699 std::unique_ptr<Vector> d_predicted_state_real_2 =
701 std::unique_ptr<Vector> d_predicted_state_real =
702 d_predicted_state_real_1->minus(*d_predicted_state_real_2);
707 for (
int k = 0; k < n; k++)
710 std::pair<std::shared_ptr<Matrix>, std::shared_ptr<Matrix>> d_phi_pair =
712 d_phi_mult_eigs_real = d_phi_pair.first;
713 d_phi_mult_eigs_imaginary = d_phi_pair.second;
717 d_predicted_state_real_1 = d_phi_mult_eigs_real->mult(
719 d_predicted_state_real_2 = d_phi_mult_eigs_imaginary->mult(
720 *f_control_imaginary);
721 *d_predicted_state_real += *d_predicted_state_real_1;
722 *d_predicted_state_real -= *d_predicted_state_real_2;
725 delete f_control_real;
726 delete f_control_imaginary;
728 return d_predicted_state_real;
743 return std::pow(eig, t /
d_dt);
746 std::pair<std::shared_ptr<Matrix>,std::shared_ptr<Matrix>>
752 for (
int i = 0; i <
d_k; i++)
755 d_eigs_exp_real->
item(i, i) = std::real(eig_exp);
756 d_eigs_exp_imaginary->
item(i, i) = std::imag(eig_exp);
759 std::shared_ptr<Matrix> d_phi_mult_eigs_real =
d_phi_real->mult(
761 std::unique_ptr<Matrix> d_phi_mult_eigs_real_2 =
d_phi_imaginary->mult(
762 *d_eigs_exp_imaginary);
763 *d_phi_mult_eigs_real -= *d_phi_mult_eigs_real_2;
764 std::shared_ptr<Matrix> d_phi_mult_eigs_imaginary =
d_phi_real->mult(
765 *d_eigs_exp_imaginary);
766 std::unique_ptr<Matrix> d_phi_mult_eigs_imaginary_2 =
d_phi_imaginary->mult(
768 *d_phi_mult_eigs_imaginary += *d_phi_mult_eigs_imaginary_2;
770 delete d_eigs_exp_real;
771 delete d_eigs_exp_imaginary;
773 return std::pair<std::shared_ptr<Matrix>,std::shared_ptr<Matrix>>
774 (d_phi_mult_eigs_real,
775 d_phi_mult_eigs_imaginary);
784 std::unique_ptr<const Matrix>
790 std::unique_ptr<const Matrix>
794 CAROM_VERIFY(snapshots.size() > 0);
795 CAROM_VERIFY(snapshots[0]->dim() > 0);
796 for (
int i = 0 ; i < snapshots.size() - 1; i++)
798 CAROM_VERIFY(snapshots[i]->dim() == snapshots[i + 1]->dim());
799 CAROM_VERIFY(snapshots[i]->distributed() == snapshots[i + 1]->distributed());
802 Matrix* snapshot_mat =
new Matrix(snapshots[0]->dim(), snapshots.size(),
803 snapshots[0]->distributed());
805 for (
int i = 0; i < snapshots[0]->dim(); i++)
807 for (
int j = 0; j < snapshots.size(); j++)
809 snapshot_mat->
item(i, j) = snapshots[j]->item(i);
813 return std::unique_ptr<const Matrix>(snapshot_mat);
819 CAROM_ASSERT(!base_file_name.empty());
822 std::string full_file_name = base_file_name;
824 database.
open(full_file_name,
"r");
829 sprintf(tmp,
"t_offset");
835 sprintf(tmp,
"num_eigs");
839 std::vector<double> eigs_real;
840 std::vector<double> eigs_imag;
842 sprintf(tmp,
"eigs_real");
843 eigs_real.resize(num_eigs);
846 sprintf(tmp,
"eigs_imag");
847 eigs_imag.resize(num_eigs);
850 for (
int i = 0; i < num_eigs; i++)
852 d_eigs.push_back(std::complex<double>(eigs_real[i], eigs_imag[i]));
856 full_file_name = base_file_name +
"_basis";
860 full_file_name = base_file_name +
"_A_tilde";
864 full_file_name = base_file_name +
"_B_tilde";
868 full_file_name = base_file_name +
"_phi_real";
872 full_file_name = base_file_name +
"_phi_imaginary";
876 full_file_name = base_file_name +
"_phi_real_squared_inverse";
880 full_file_name = base_file_name +
"_phi_imaginary_squared_inverse";
884 full_file_name = base_file_name +
"_projected_init_real";
888 full_file_name = base_file_name +
"_projected_init_imaginary";
892 full_file_name = base_file_name +
"_state_offset";
902 MPI_Barrier(MPI_COMM_WORLD);
908 load(std::string(base_file_name));
914 CAROM_ASSERT(!base_file_name.empty());
920 std::string full_file_name = base_file_name;
922 database.
create(full_file_name);
927 sprintf(tmp,
"t_offset");
933 sprintf(tmp,
"num_eigs");
936 std::vector<double> eigs_real;
937 std::vector<double> eigs_imag;
939 for (
int i = 0; i <
d_eigs.size(); i++)
941 eigs_real.push_back(
d_eigs[i].real());
942 eigs_imag.push_back(
d_eigs[i].imag());
945 sprintf(tmp,
"eigs_real");
948 sprintf(tmp,
"eigs_imag");
953 std::string full_file_name;
957 full_file_name = base_file_name +
"_basis";
958 d_basis->write(full_file_name);
963 full_file_name = base_file_name +
"_A_tilde";
969 full_file_name = base_file_name +
"_B_tilde";
973 full_file_name = base_file_name +
"_phi_real";
976 full_file_name = base_file_name +
"_phi_imaginary";
979 full_file_name = base_file_name +
"_phi_real_squared_inverse";
982 full_file_name = base_file_name +
"_phi_imaginary_squared_inverse";
985 full_file_name = base_file_name +
"_projected_init_real";
988 full_file_name = base_file_name +
"_projected_init_imaginary";
993 full_file_name = base_file_name +
"_state_offset";
997 MPI_Barrier(MPI_COMM_WORLD);
1003 save(std::string(base_file_name));
void putDoubleVector(const std::string &file_name, const std::vector< double > &data, int nelements, const bool distributed=false) override
Writes a vector of doubles associated with the supplied filename to the currently open CSV database f...
void putComplexVector(const std::string &file_name, const std::vector< std::complex< double >> &data, int nelements)
Writes a vector of complex doubles associated with the supplied filename.
std::vector< double > d_sv
std::vector holding the signular values.
std::vector< std::shared_ptr< Vector > > d_controls
std::vector holding the controls.
std::shared_ptr< Vector > d_projected_init_real
The real part of the projected initial condition.
double d_dt
The time step size between samples.
std::shared_ptr< Matrix > d_phi_real_squared_inverse
The real part of d_phi_squared_inverse.
virtual void setOffset(std::shared_ptr< Vector > &offset_vector)
Set the state offset.
int d_num_procs
The number of processors being run on.
std::unique_ptr< Matrix > d_projected_controls_real
The real part of the projected controls.
virtual void addOffset(Vector &result)
Add the state offset when predicting the solution.
std::unique_ptr< Matrix > d_projected_controls_imaginary
The imaginary part of the projected controls.
int d_num_singular_vectors
The maximum number of singular vectors.
void project(const Vector &init, const Matrix &controls, double t_offset=-1.0)
Project U using d_phi, where U is the initial condition and the controls. Calculate pinv(phi) x U,...
std::shared_ptr< Matrix > d_A_tilde
A_tilde.
bool d_trained
Whether the DMDc has been trained or not.
std::shared_ptr< Vector > d_projected_init_imaginary
The imaginary part of the projected initial condition.
std::vector< std::shared_ptr< Vector > > d_snapshots
std::vector holding the snapshots.
std::vector< std::complex< double > > d_eigs
A vector holding the complex eigenvalues of the eigenmodes.
std::unique_ptr< Vector > predict(double t)
Predict state given a time. Uses the projected initial condition of the training dataset (the first c...
double d_t_offset
The time offset of the first sample.
virtual std::pair< Matrix *, Matrix * > computeDMDcSnapshotPair(const Matrix &snapshots, const Matrix &controls, const Matrix *B)
Returns a pair of pointers to the minus and plus snapshot matrices.
void constructDMDc(const Matrix &f_snapshots, const Matrix &f_controls, int rank, int num_procs, const Matrix *B)
Construct the DMDc object.
std::unique_ptr< const Matrix > getSnapshotMatrix()
Get the snapshot matrix contained within d_snapshots.
virtual void save(std::string base_file_name)
Save the object state to a file.
virtual std::complex< double > computeEigExp(std::complex< double > eig, double t)
Compute the appropriate exponential function when predicting the solution.
int d_k
The number of columns used after obtaining the SVD decomposition.
bool d_init_projected
Whether the initial condition has been projected.
void summary(std::string base_file_name)
Output the DMDc record in CSV files.
std::unique_ptr< const Matrix > createSnapshotMatrix(const std::vector< std::shared_ptr< Vector >> &snapshots)
Get the snapshot matrix contained within d_snapshots.
std::vector< double > d_sampled_times
The stored times of each sample.
std::shared_ptr< Matrix > d_phi_real
The real part of d_phi.
std::shared_ptr< Matrix > d_basis
The left singular vector basis.
int d_dim_c
The total dimension of the control vector.
std::shared_ptr< Vector > d_state_offset
State offset in snapshot.
DMDc()
Unimplemented default constructor.
int d_rank
The rank of the process this object belongs to.
double d_energy_fraction
The energy fraction used to obtain the DMDc modes.
double getTimeOffset() const
Get the time offset contained within d_t_offset.
std::pair< std::shared_ptr< Matrix >, std::shared_ptr< Matrix > > phiMultEigs(double t)
Internal function to multiply d_phi with the eigenvalues.
int d_dim
The total dimension of the sample vector.
std::shared_ptr< Matrix > d_B_tilde
B_tilde.
std::shared_ptr< Matrix > d_phi_imaginary
The imaginary part of d_phi.
std::shared_ptr< Matrix > d_phi_imaginary_squared_inverse
The imaginary part of d_phi_squared_inverse.
virtual void takeSample(double *u_in, double t, double *f_in, bool last_step=false)
Sample the new state, u_in. Any samples in d_snapshots taken at the same or later time will be erased...
virtual void load(std::string base_file_name)
Load the object state from a file.
virtual void train(double energy_fraction, const Matrix *B=NULL)
Train the DMDc model with energy fraction criterion. The control matrix B may be available and used i...
void getInteger(const std::string &key, int &data)
Reads an integer associated with the supplied key from the currently open database file.
void putDouble(const std::string &key, double data)
Writes a double associated with the supplied key to currently open database file.
void putInteger(const std::string &key, int data)
Writes an integer associated with the supplied key to currently open database file.
void getDouble(const std::string &key, double &data)
Reads a double associated with the supplied key from the currently open database file.
virtual void getDoubleArray(const std::string &key, double *data, int nelements, const bool distributed=false) override
Reads an array of doubles associated with the supplied key from the currently open HDF5 database file...
virtual bool create(const std::string &file_name, const MPI_Comm comm=MPI_COMM_NULL) override
Creates a new HDF5 database file with the supplied name.
virtual bool open(const std::string &file_name, const std::string &type, const MPI_Comm comm=MPI_COMM_NULL) override
Opens an existing HDF5 database file with the supplied name.
virtual void putDoubleArray(const std::string &key, const double *const data, int nelements, const bool distributed=false) override
Writes an array of doubles associated with the supplied key to the currently open HDF5 database file.
virtual bool close() override
Closes the currently open HDF5 database file.
double * getData() const
Get the matrix data as a pointer.
bool distributed() const
Returns true if the Matrix is distributed.
int numColumns() const
Returns the number of columns in the Matrix. This method will return the same value from each process...
int numDistributedRows() const
Returns the number of rows of the Matrix across all processors.
const double & item(int row, int col) const
Const Matrix member access. Matrix data is stored in row-major format.
int numRows() const
Returns the number of rows of the Matrix on this processor.
std::unique_ptr< Matrix > mult(const Matrix &other) const
Multiplies this Matrix with other and returns the product.
std::unique_ptr< Matrix > transposeMult(const Matrix &other) const
Multiplies the transpose of this Matrix with other and returns the product.
int dim() const
Returns the dimension of the Vector on this processor.
ComplexEigenPair NonSymmetricRightEigenSolve(const Matrix &A)
Computes the eigenvectors/eigenvalues of an NxN real nonsymmetric matrix.
Matrix * ev_real
The real component of the eigenvectors in matrix form.
std::vector< std::complex< double > > eigs
The corresponding complex eigenvalues.
Matrix * ev_imaginary
The imaginary component of the eigenvectors in matrix form.
static bool file_exist(const std::string &filename)
Verifies if a file exists.