Gmm++ の最初のステップ

どのように逆行列を計算しますか?

Gmm++ では全ての種類の行列の逆行列を計算することはできません.今のところ,逆行列を計算する唯一の方法は,密なLU分解(つまり,密行列の場合のみ)を使用することです.例えば

gmm::dense_matrix<double> M(3, 3), M2(3,3), M3(3,3);
gmm::copy(gmm::identity_matrix(), M);  // M = Id.
gmm::scale(M, 2.0);                    // M = 2 * Id.
M(1,2) = 1.0;

gmm::copy(M, M2);

gmm::lu_inverse(M);

gmm::mult(M, M2, M3);

std::cout << M << " times " << M2 << " is equal to " << M3 << endl;

詳細については,密なLU分解に対応するセクションを参照してください.型 gmm::dense_matrix<double> は, gmm::row_matrix< std::vector<double> > または gmm::col_matrix< std::vector<double> > で置き換えることができます.

線形システムをどのように解きますか?

線形システムを解く方法は複数あります.密行列の場合は,LU分解を使用するのが最善です.例えば

gmm::dense_matrix<double> M(3, 3);
gmm::clear(M);                  // M = 0.
M(0,0) = M(1,1) = M(2,2) = 2.0; // M = 2 * Id.
M(1,2) = 1.0;

std::vector<double> X(3), B(3), Bagain(3);
B[0] = 1.0; B[1] = 2.0; B[2] = 3.0;  // B = [1 2 3]

gmm::lu_solve(M, X, B);

gmm::mult(M, X, Bagain);

std::cout << M << " times " << gmm::vref(X) << " is equal to " << gmm::vref(Bagain) << endl;

今,偏微分方程式の離散化から来る疎なシステムを持っているなら,前処理行列の有無にかかわらず,さまざまな反復ソルバーがあります.これは,前処理GMRESによる例です.

int nbdof = 1000; // number of degrees of freedom.
gmm::row_matrix< gmm::rsvector<double> > M(nbdof, nbdof); // a sparse matrix
std::vector<double> X(nbdof), B(nbdof); // Unknown and left hand side.

... here the assembly of the pde discretization stiffness matrix ...
... and left hand side ...


// computation of a preconditioner (ILUT)
gmm::ilut_precond< gmm::row_matrix< gmm::rsvector<double> > > P(M, 10, 1e-4);

gmm::iteration iter(1E-8);  // defines an iteration object, with a max residu of 1E-8

gmm::gmres(M, X, B, P, 50, iter);  // execute the GMRES algorithm

std::cout << "The result " << gmm::vref(X) << endl;

どのようにベクトルを行列に変換し,それを変形することができますか?

Gmm++ では,ベクトルは行列とはみなされません.ベクトルを(1×n)行行列または(n×1)列行列として計算で使用する必要がある場合は,次を使用する必要があります.

gmm::row_vector(V) // gives a reference on V considered as
                   // a (1 by n) row matrix
gmm::col_vector(V) // gives a reference on V considered as
                   // a (n by 1) col matrix

たとえば,次のようにしてベクトルを密行列に変換できます.

std::vector<double> V(50);

// ... computation of V

gmm::dense_matrix<double> M(1, gmm::vect_size(V));
gmm::copy(gmm::row_vector(V), M);

次のようにして,行列 M の形状を変更することもできます.行列

gmm::reshape(M, 10, 5);

行列のサイズを変更するより良い方法は何ですか?

行列の大きさは,参照でない場合は次を使用して変更することができます.

gmm::resize(M, m, n);

この関数は元の行列とサイズ変更された行列の交点を尊重し,新しい要素はゼロに設定されます.重要なことは, std::vector のサイズ変更メソッドに基づいていることです.したがって,新しい行列のサイズが元のサイズよりも小さい場合,メモリフリーは行われません.

コンポーネントの古い値を保持する必要がない場合,または余分なメモリを解放したい場合は,次のように std::swap を使って行列のサイズを変更できます.

MATRIX_TYPE M(m1, n1);

... your code

{ MATRIX_TYPE(m2, n2) M2; std::swap(M, M2); } // resize matrix M.

もちろん,これはベクトルに対しても機能します.