I switched from matlab to C++ to write a CFD solver. I am using Eigen linear algebra library. It has many function for the Matrix and Vector manipulations but it's lacking in functions to convert Matrix to Array.
MatrixXf m(2,2);
m<<1,2,3,4;
ArrayXf a(4);
a=m.array();
This is the solution I have for this
m.resize(4,1);
a=m;
I don' like this because the m is changed, which I don't want because m is a very big matrix.
If you don't want to copy the values you can use an Eigen::Map like so:
MatrixXf m(2,2);
m<<1,2,3,4;
Eigen::Map<ArrayXf> mp(m.data(), m.size());
You can then use mp as an ArrayXf. Note that this points to the original m matrix, i.e. changes to mp will be present in m. If you want a copy, you can use:
ArrayXf a = mp;
You could write your own function and copy value by value.
MatrixXf matrix(2,2);
int cols=matrix.cols();
int rows=matrix.rows;
ArrayXf array(cols*rows);
for(int c=0;c<cols;c++)
for(int r=0;r<rows;r++)
array(c*rows+r)=matrix(c,r);
Related
How do I perform a matrix vector product using the Eigen library in C++ with a "for loop", when the date type of my variables are in the form Eigen::MatrixXd and Eigen::VectorXd?
NOTE: I don't want to use the in-built * operator of directly multiplying a matrix with vector, I want to use a for loop and perform the element wise operation myself
When I try to do the element wise multiplication on Eigen::MatrixXd and Eigen::VectorXd, I get an error.
I have no idea what problem you have encountered. Here is an example that may help.
// mat: 3x4 vec_h: 4x1
Eigen::MatrixXd mat = Eigen::MatrixXd::Ones(3,4);
Eigen::VectorXd vec_h = Eigen::VectorXd::Random(4);
// mat.row(i): 1x4
// mat.row(i).transpose(): 4x1
// cwiseProduct() element-wise multiplication
// add .eval() because we are changing the element value in place.
for (int i = 0; i < mat.rows(); ++i) {
mat.row(i)=mat.row(i).transpose().cwiseProduct(vec_h).eval();
}
In case you are looking for more information, here's the link Eigen: The Array class and coefficient-wise operations
I have MatrixXf A & MatrixXf B and I want to create a new matrix MatrixXf C with max values for each index i.e.
C(i,j) = max(A(i,j), B(i,J);
Does Eigen have a function to do this?
A.cwiseMax(B) can also be used.
Check http://eigen.tuxfamily.org/dox/group__QuickRefPage.html#title6 for reference
I'm creating a circuit analysis library in C++ (also to learn C++, so I'm very new to it).
After getting familiar with Eigen, I'd like to have a matrix where each cell hosts a 3x3 complex matrix.
So far I've tried this very simple prove of principle:
typedef Eigen::MatrixXcd cx_mat;
typedef Eigen::SparseMatrix<cx_mat> sp_mat_mat;
void test(cx_mat Z1){
sp_mat_mat Y(2, 2);
Y(0, 0) = Z1;
Y(2, 2) = Z1;
cout << "\n\nY:\n" << Y << endl;
}
Testing this simple example fails as a probable consequence of Eigen expecting a number instead of a structure.
As a matter of fact the matrix of matrices is prompt to be sparse, hence the sparse matrix structure.
Is there any way to make this work?
Any help is appreciated.
I don't believe Eigen will give you a way to make this work. I you think about the other functions which are connected to Matrix or Sparse matrix, like:
inverse()
norm()
m.row()*m.col()
what should Eigen do when a matrix element number is replaced by a matrix?
What I can understand is that you want to have a data structure that stores your Eigen::MatrixXcd in an memory efficient way.
You could also realize this using the map container:
#include <map>
typedef Eigen::MatrixXcd cx_mat;
cx_mat Z1;
std::map<int,Eigen::MatrixXcd> sp_mat_mat;
int cols = 2;
sp_mat_mat[0*cols+0]=Z1;
sp_mat_mat[2*cols+2]=Z1;
Less memory efficient, but perhaps easier to access would be using the vector container:
#include <vector>
std::vector<std::vector<Eigen::MatrixXcd>> mat_mat;
Have you found a way to create a matrix of matrices?
I see that we can use a 2-D array to create a matrix of matrices.
For example,
#include <Eigen/Dense>
MatrixXd A;
MatrixXd B;
A = MatrixXd::Random(3, 3);
B = MatrixXd::Random(3, 4);
C = MatrixXd::Random(4, 4);
MatrixXd D[2][2];
D[0][0] = A;
D[0][1] = B; D[1][0] = B.transpose();
D[1][1] = C;
I don't know if this way is memory-efficient or not. Let's check it out.
You asked "sparse matrix structure. Is there any way to make this work?" I would say no, because it is not easy to translate a circuit design into a "matrix of matrices" in the first place.. if you want to simulate something, you choose a representation close to it,. In case of an electronic circuit diagram, the schema in memory should IMHO be a directed graph, with linked-list items. At each node/junction, there is a matrix representing the behaviour of a particular component input to output transfer (eg resistor, capacitor, transistor) and you propagate the signal through the matrices assigned to each component. The transformed signal eventually arrives at an output, through the connections in your connected graph. In software, it should work similarly.. Suggested further reading: https://core.ac.uk/download/pdf/53745212.pdf
I have an array of doubles, and I want to create a 4-by-4 matrix using the Eigen library. I also want to specify that the data is stored in row-major order. How can I do this?
I have tried the following, but it does not compile:
double data[16];
Eigen::Matrix4d M = Eigen::Map<Eigen::Matrix4d>(data, 4, 4, Eigen::RowMajor);
You need to pass a row-major matrix type to Map, e.g.:
Map<Matrix<double,4,4,RowMajor> > M(data);
then you can use M as an Eigen matrix, and the values of data will be modified, e.g.:
M = M.inverse();
If you want to copy the data to a true column-major Eigen matrix, then do:
Matrix4d M = Map<Matrix<double,4,4,RowMajor> >(data);
Of course, you can also copy to a row-major matrix by using the right type for M.
RowMajor forms actually come in handy when using arrays to store data sometimes. Hence you can also prefer using a typedef to RowMajor type.
namespace Eigen{
typedef Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> MatrixXfRowMajor;
}
You can replace by float by any datatype of choice. For a 4x4 matrix then, we can simply do
Eigen::MatrixXfRowMajor mat;
mat.resize(4,4);
I need to convert a MATLAB code into C++, and I'm stuck with this instruction:
a = K\F
, where K is a sparse matrix of size n x n, and F is a column vector of size n.
I know it's easy to solve that using the Eigen library - I have tried the fullPivLu() method, and I've been able to built a working snippet, using a Matrix and a Vector.
However, my K is a SparseMatrix<double> (while F is a VectorXd). My declarations:
SparseMatrix<double> K(nec, nec);
VectorXd F(nec);
and it seems that SparseMatrix doesn't have the fullPivLu() method, nor the lu() one.
I've tried, in fact, these two different approaches, taken from the documentation:
//1.
MatrixXd x = K.fullPivLu().solve(F);
//2.
VectorXf x;
K.lu().solve(F, &x);
They don't work, because fullPivLu() and lu() are not members of 'Eigen::SparseMatrix<_Scalar>'
So, I am asking: is there a way to solve a system of linear equations (the MATLAB's mldivide, or '\'), using Eigen for C++, with K being a sparse matrix?
Thank you for any help.
Would Eigen::SparseLU work for you?