Skip to content

Commit 7cda79e

Browse files
authored
Merge pull request #1068 from su2code/feature_CGeneralSquareMatrixCM
Added CSquareMatrixCM to the toolboxes
2 parents 6691b70 + dd7ebda commit 7cda79e

8 files changed

Lines changed: 337 additions & 82 deletions

File tree

Common/include/blas_structure.hpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,55 @@ class CBlasStructure {
9494
void axpy(const int n, const su2double a, const su2double *x,
9595
const int incx, su2double *y, const int incy);
9696

97+
/*!
98+
* \brief Invert a square matrix.
99+
* \param[in] M - Size.
100+
* \param[in,out] mat - Matrix, and inverse on exit.
101+
*/
102+
template<class Mat>
103+
static void inverse(const int M, Mat& mat) {
104+
using Scalar = typename Mat::Scalar;
105+
106+
/*--- Copy the data from A into the augmented matrix and initialize mat with the identity. ---*/
107+
Mat aug = mat;
108+
mat = Scalar(0);
109+
for(int j=0; j<M; ++j) mat(j,j) = 1;
110+
111+
/*--- Outer loop of the Gauss-Jordan elimination. ---*/
112+
for(int j=0; j<M; ++j) {
113+
114+
/*--- Find the pivot in the current column. ---*/
115+
int jj = j;
116+
Scalar valMax = fabs(aug(j,j));
117+
for(int i=j+1; i<M; ++i) {
118+
Scalar val = fabs(aug(i,j));
119+
if(val > valMax){
120+
jj = i;
121+
valMax = val;
122+
}
123+
}
124+
125+
/*--- Swap the rows j and jj, if needed. ---*/
126+
if(jj > j) {
127+
for(int k=j; k<M; ++k) std::swap(aug(j,k), aug(jj,k));
128+
for(int k=0; k<M; ++k) std::swap(mat(j,k), mat(jj,k));
129+
}
130+
131+
/*--- Performing row operations to form required identity
132+
matrix out of the input matrix. ---*/
133+
for(int i=0; i<M; ++i) {
134+
if(i == j) continue;
135+
valMax = aug(i,j)/aug(j,j);
136+
for(int k=j; k<M; ++k) aug(i,k) -= valMax*aug(j,k);
137+
for(int k=0; k<M; ++k) mat(i,k) -= valMax*mat(j,k);
138+
}
139+
140+
valMax = 1.0/aug(j,j);
141+
for(int k=j; k<M; ++k) aug(j,k) *= valMax;
142+
for(int k=0; k<M; ++k) mat(j,k) *= valMax;
143+
}
144+
}
145+
97146
private:
98147

99148
#if !(defined(HAVE_LIBXSMM) || defined(HAVE_BLAS) || defined(HAVE_MKL)) || (defined(CODI_REVERSE_TYPE) || defined(CODI_FORWARD_TYPE))

Common/include/containers/C2DContainer.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -613,7 +613,8 @@ class C2DContainer :
613613
* \brief Useful typedefs with default template parameters
614614
*/
615615
template<class T> using su2vector = C2DContainer<unsigned long, T, StorageType::ColumnMajor, 64, DynamicSize, 1>;
616-
template<class T> using su2matrix = C2DContainer<unsigned long, T, StorageType::RowMajor, 64, DynamicSize, DynamicSize>;
616+
template<class T> using su2matrix = C2DContainer<unsigned long, T, StorageType::RowMajor, 64, DynamicSize, DynamicSize>;
617+
template<class T> using ColMajorMatrix = C2DContainer<unsigned long, T, StorageType::ColumnMajor, 64, DynamicSize, DynamicSize>;
617618

618619
using su2activevector = su2vector<su2double>;
619620
using su2activematrix = su2matrix<su2double>;
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/*!
2+
* \file CSquareMatrixCM.hpp
3+
* \brief Dense general square matrix, used for example in DG standard elements
4+
* in Column Major order storage.
5+
* \author Edwin van der Weide, Pedro Gomes.
6+
* \version 7.0.8 "Blackbird"
7+
*
8+
* SU2 Project Website: https://su2code.github.io
9+
*
10+
* The SU2 Project is maintained by the SU2 Foundation
11+
* (http://su2foundation.org)
12+
*
13+
* Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
14+
*
15+
* SU2 is free software; you can redistribute it and/or
16+
* modify it under the terms of the GNU Lesser General Public
17+
* License as published by the Free Software Foundation; either
18+
* version 2.1 of the License, or (at your option) any later version.
19+
*
20+
* SU2 is distributed in the hope that it will be useful,
21+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
22+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23+
* Lesser General Public License for more details.
24+
*
25+
* You should have received a copy of the GNU Lesser General Public
26+
* License along with SU2. If not, see <http://www.gnu.org/licenses/>.
27+
*/
28+
#pragma once
29+
30+
#include <vector>
31+
#include "../containers/C2DContainer.hpp"
32+
33+
/*!
34+
* \brief Class to store a dense general square matrix that uses the Column
35+
* Major order storage format. The code should be compiled with
36+
* LAPACK to use optimized matrix inversion and multiplication routines.
37+
*/
38+
class CSquareMatrixCM {
39+
static_assert(ColMajorMatrix<passivedouble>::Storage == StorageType::ColumnMajor,
40+
"Column major storage is assumed for LAPACK.");
41+
private:
42+
ColMajorMatrix<passivedouble> mat; /*!< \brief Storage of the actual matrix. */
43+
44+
public:
45+
46+
/*!
47+
* \brief Default constructor. Nothing to be done.
48+
*/
49+
CSquareMatrixCM() = default;
50+
51+
/*!
52+
* \overload
53+
* \brief Overloaded constructor, which allocates the memory to store
54+
* the matrix.
55+
* \param[in] N - Number of rows and colums of the matrix.
56+
*/
57+
CSquareMatrixCM(int N) {Initialize(N);}
58+
59+
/*!
60+
* \brief Operator, which makes available the given matrix element as a reference.
61+
* \param[in] i - Row index of the matrix element.
62+
* \param[in] j - Column index of the matrix element.
63+
* \return Reference to element (i,j).
64+
*/
65+
inline passivedouble& operator() (int i, int j) {return mat(i,j);}
66+
67+
/*!
68+
* \brief Operator, which makes available the given matrix element as a const reference.
69+
* \param[in] i - Row index of the matrix element.
70+
* \param[in] j - Column index of the matrix element.
71+
* \return Constant reference to element (i,j).
72+
*/
73+
inline const passivedouble& operator() (int i, int j) const {return mat(i,j);}
74+
75+
/*!
76+
* \brief Function, which makes available a reference to the actual matrix.
77+
* \return A reference to mat.
78+
*/
79+
inline ColMajorMatrix<passivedouble>& GetMat() {return mat;}
80+
81+
/*!
82+
* \brief Function, which makes available a const reference to the actual matrix.
83+
* \return A const reference to mat.
84+
*/
85+
inline const ColMajorMatrix<passivedouble>& GetMat() const {return mat;}
86+
87+
/*!
88+
* \brief Function, which allocates the memory for the matrix.
89+
* \param[in] N - Number of rows and colums of the matrix.
90+
*/
91+
inline void Initialize(int N) {mat.resize(N,N);}
92+
93+
/*!
94+
* \brief Function, which makes available the size of the matrix.
95+
* \return The number of rows, columns of the matrix.
96+
*/
97+
inline int Size() const {return mat.rows();}
98+
99+
/*!
100+
* \brief Function, which carries out the matrix produc of the current matrix
101+
* with mat_in and stores the result in mat_out.
102+
* \param[in] side - left: mat_out = this * mat_in, right: mat_out = mat_in * this
103+
* \param[in] mat_in - Matrix to be multiplied by the current matrix.
104+
* \param[out] mat_out - Matrix to store the result of the multiplication.
105+
*/
106+
void MatMatMult(const char side,
107+
const ColMajorMatrix<passivedouble> &mat_in,
108+
ColMajorMatrix<passivedouble> &mat_out) const;
109+
110+
/*!
111+
* \brief Naive matrix-vector multiplication with general type.
112+
*/
113+
template<class ForwardIt>
114+
void MatVecMult(ForwardIt vec_in, ForwardIt vec_out) const
115+
{
116+
for (int i = 0; i < Size(); ++i) {
117+
*vec_out = 0.0;
118+
auto vec = vec_in;
119+
for (int k = 0; k < Size(); ++k)
120+
*vec_out += *(vec++) * mat(i,k);
121+
++vec_out;
122+
}
123+
}
124+
125+
/*!
126+
* \brief Function, which inverts the matrix in-place.
127+
*/
128+
void Invert();
129+
130+
/*!
131+
* \brief Function, which transposes the matrix in-place.
132+
*/
133+
void Transpose();
134+
135+
};

Common/include/toolboxes/CSymmetricMatrix.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ class CSymmetricMatrix {
4242
// Not optimized dense matrix factorization and inversion for portability.
4343
void CalcInv(bool is_spd);
4444
void CholeskyDecompose();
45-
void LUDecompose(su2passivematrix& decomp, std::vector<int>& perm) const;
4645
// Matrix inversion using LAPACK routines (LDLT and LLT factorization).
4746
void CalcInv_sytri();
4847
void CalcInv_potri();

Common/lib/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ lib_sources = \
113113
../src/toolboxes/CLinearPartitioner.cpp \
114114
../src/toolboxes/C1DInterpolation.cpp \
115115
../src/toolboxes/CSymmetricMatrix.cpp \
116+
../src/toolboxes/CSquareMatrixCM.cpp \
116117
../src/toolboxes/MMS/CVerificationSolution.cpp \
117118
../src/toolboxes/MMS/CIncTGVSolution.cpp \
118119
../src/toolboxes/MMS/CInviscidVortexSolution.cpp \
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
/*!
2+
* \file CSquareMatrixCM.cpp
3+
* \brief Implementation of dense matrix helper class in Column Major order (see hpp).
4+
* \author Edwin van der Weide, Pedro Gomes.
5+
* \version 7.0.8 "Blackbird"
6+
*
7+
* SU2 Project Website: https://su2code.github.io
8+
*
9+
* The SU2 Project is maintained by the SU2 Foundation
10+
* (http://su2foundation.org)
11+
*
12+
* Copyright 2012-2020, SU2 Contributors (cf. AUTHORS.md)
13+
*
14+
* SU2 is free software; you can redistribute it and/or
15+
* modify it under the terms of the GNU Lesser General Public
16+
* License as published by the Free Software Foundation; either
17+
* version 2.1 of the License, or (at your option) any later version.
18+
*
19+
* SU2 is distributed in the hope that it will be useful,
20+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
21+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22+
* Lesser General Public License for more details.
23+
*
24+
* You should have received a copy of the GNU Lesser General Public
25+
* License along with SU2. If not, see <http://www.gnu.org/licenses/>.
26+
*/
27+
28+
#include "../../include/toolboxes/CSquareMatrixCM.hpp"
29+
#include "../../include/mpi_structure.hpp"
30+
#include "../../include/blas_structure.hpp"
31+
32+
using namespace std;
33+
34+
#if defined(HAVE_MKL)
35+
#include "mkl.h"
36+
#ifndef HAVE_LAPACK
37+
#define HAVE_LAPACK
38+
#endif
39+
#elif defined(HAVE_LAPACK)
40+
/*--- Lapack / Blas routines used in CSquareMatrixCM. ---*/
41+
extern "C" void dgetrf_(const int*, const int*, passivedouble*, const int*,
42+
int*, int*);
43+
extern "C" void dgetri_(const int*, passivedouble*, const int*, int*,
44+
passivedouble*, const int*, int*);
45+
extern "C" void dgemm_(char*, char*, const int*, const int*, const int*,
46+
const passivedouble*, const passivedouble*,
47+
const int *, const passivedouble*, const int*,
48+
const passivedouble*, passivedouble*, const int*);
49+
#define DGEMM dgemm_
50+
#endif
51+
52+
void CSquareMatrixCM::Transpose() {
53+
54+
for(int j=1; j<Size(); ++j)
55+
for(int i=0; i<j; ++i)
56+
swap(mat(i,j), mat(j,i));
57+
}
58+
59+
void CSquareMatrixCM::Invert() {
60+
61+
#ifdef HAVE_LAPACK
62+
63+
/*--- Computation of the inverse using the Lapack routines. ---*/
64+
int sz = Size();
65+
int info;
66+
vector<int> ipiv(sz);
67+
vector<passivedouble> work(sz);
68+
69+
dgetrf_(&sz, &sz, mat.data(), &sz, ipiv.data(), &info);
70+
if(info != 0) SU2_MPI::Error(string("Matrix is singular"), CURRENT_FUNCTION);
71+
72+
dgetri_(&sz, mat.data(), &sz, ipiv.data(), work.data(), &sz, &info);
73+
if(info != 0) SU2_MPI::Error(string("Matrix inversion failed"), CURRENT_FUNCTION);
74+
75+
#else
76+
CBlasStructure::inverse(Size(), mat);
77+
#endif
78+
}
79+
80+
void CSquareMatrixCM::MatMatMult(const char side,
81+
const ColMajorMatrix<passivedouble> &mat_in,
82+
ColMajorMatrix<passivedouble> &mat_out) const {
83+
84+
/*--- Check the type of multiplication to be carried out. ---*/
85+
if (side == 'L' || side == 'l') {
86+
87+
/*--- Left side: mat_out = this * mat_in. Set some sizes
88+
and allocate the memory for mat_out. ---*/
89+
const int M = Size(), N = mat_in.cols();
90+
assert(M == mat_in.rows());
91+
92+
mat_out.resize(M,N);
93+
94+
#ifdef HAVE_LAPACK
95+
96+
/*--- The Lapack/blas function dgemm is used to carry out
97+
the matrix matrix multiplication. ---*/
98+
passivedouble alpha = 1.0, beta = 0.0;
99+
char trans = 'N';
100+
101+
DGEMM(&trans, &trans, &M, &N, &M, &alpha, mat.data(), &M,
102+
mat_in.data(), &M, &beta, mat_out.data(), &M);
103+
#else
104+
/*--- Naive product. ---*/
105+
for (int i = 0; i < M; ++i) {
106+
for (int j = 0; j < N; ++j) {
107+
mat_out(i,j) = 0.0;
108+
for (int k = 0; k < M; ++k)
109+
mat_out(i,j) += mat(i,k) * mat_in(k,j);
110+
}
111+
}
112+
#endif
113+
114+
}
115+
else {
116+
117+
/*--- Right_side: mat_out = mat_in * this. Set some sizes
118+
and allocate the memory for mat_out. ---*/
119+
const int M = mat_in.rows(), N = Size();
120+
assert(N == mat_in.cols());
121+
122+
mat_out.resize(M,N);
123+
124+
#ifdef HAVE_LAPACK
125+
126+
/*--- The Lapack/blas function dgemm is used to carry out
127+
the matrix matrix multiplication. ---*/
128+
passivedouble alpha = 1.0, beta = 0.0;
129+
char trans = 'N';
130+
131+
DGEMM(&trans, &trans, &M, &N, &N, &alpha, mat_in.data(), &M,
132+
mat.data(), &N, &beta, mat_out.data(), &M);
133+
#else
134+
/*--- Naive product. ---*/
135+
for (int i = 0; i < M; ++i) {
136+
for (int j = 0; j < N; ++j) {
137+
mat_out(i,j) = 0.0;
138+
for (int k = 0; k < N; ++k)
139+
mat_out(i,j) += mat_in(i,k) * mat(k,j);
140+
}
141+
}
142+
#endif
143+
}
144+
}

0 commit comments

Comments
 (0)