14 #include "linalg/Matrix.h"
15 #include "Utilities.h"
30 int num_f_basis_vectors_used,
31 std::vector<int>& f_sampled_row,
32 std::vector<int>& f_sampled_rows_per_proc,
33 Matrix& f_basis_sampled_inv,
37 CAROM_VERIFY(num_procs == f_sampled_rows_per_proc.size());
43 MPI_Datatype MaxRowType, oldtypes[2];
45 MPI_Aint offsets[2], extent, lower_bound;
48 oldtypes[0] = MPI_DOUBLE;
55 #if (MPI_VERSION == 1)
56 MPI_Type_extent(MPI_DOUBLE, &extent);
58 MPI_Type_get_extent(MPI_DOUBLE, &lower_bound, &extent);
62 oldtypes[1] = MPI_INT;
69 #if (MPI_VERSION == 1)
70 MPI_Type_struct(2, blockcounts, offsets, oldtypes, &MaxRowType);
72 MPI_Type_create_struct(2, blockcounts, offsets, oldtypes, &MaxRowType);
74 MPI_Type_commit(&MaxRowType);
78 MPI_Op_create((MPI_User_function*)RowInfoMax,
true, &RowInfoOp);
81 CAROM_VERIFY(0 < num_f_basis_vectors_used
82 && num_f_basis_vectors_used <= f_basis->numColumns());
83 int num_basis_vectors =
84 std::min(num_f_basis_vectors_used, f_basis->
numColumns());
85 CAROM_VERIFY(num_basis_vectors == f_sampled_row.size());
86 CAROM_VERIFY(num_basis_vectors == f_basis_sampled_inv.
numRows()
87 && num_basis_vectors == f_basis_sampled_inv.
numColumns());
89 int basis_size = f_basis->
numRows();
93 Matrix M(num_basis_vectors, num_basis_vectors,
false);
96 double* c =
new double [num_basis_vectors];
98 vector<set<int> > proc_sampled_f_row(num_procs);
99 vector<map<int, int> > proc_f_row_to_tmp_fs_row(num_procs);
100 int num_f_basis_cols = f_basis_sampled_inv.
numColumns();
106 RowInfo f_bv_max_local, f_bv_max_global;
107 f_bv_max_local.row_val = -1.0;
108 f_bv_max_local.proc = myid;
109 for (
int i = 0; i < basis_size; ++i) {
110 double f_bv_val = fabs(f_basis->
item(i, 0));
111 if (f_bv_val > f_bv_max_local.row_val) {
112 f_bv_max_local.row_val = f_bv_val;
113 f_bv_max_local.row = i;
116 MPI_Allreduce(&f_bv_max_local, &f_bv_max_global, 1,
117 MaxRowType, RowInfoOp, MPI_COMM_WORLD);
120 if (f_bv_max_global.proc == myid) {
121 for (
int j = 0; j < num_basis_vectors; ++j) {
122 c[j] = f_basis->
item(f_bv_max_global.row, j);
125 MPI_Bcast(c, num_basis_vectors, MPI_DOUBLE,
126 f_bv_max_global.proc, MPI_COMM_WORLD);
128 for (
int j = 0; j < num_basis_vectors; ++j) {
129 tmp_fs.
item(0, j) = c[j];
131 proc_sampled_f_row[f_bv_max_global.proc].insert(f_bv_max_global.row);
132 proc_f_row_to_tmp_fs_row[f_bv_max_global.proc][f_bv_max_global.row] = 0;
136 for (
int i = 1; i < num_basis_vectors; ++i) {
140 for (
int row = 0; row < i; ++row) {
141 for (
int col = 0; col < i; ++col) {
142 M.
item(row, col) = tmp_fs.
item(row, col);
151 for (
int minv_row = 0; minv_row < i; ++minv_row) {
153 for (
int minv_col = 0; minv_col < i; ++minv_col) {
154 tmp += M.
item(minv_row, minv_col)*tmp_fs.
item(minv_col, i);
163 f_bv_max_local.row_val = -1.0;
164 f_bv_max_local.proc = myid;
165 for (
int F_row = 0; F_row < basis_size; ++F_row) {
167 for (
int F_col = 0; F_col < i; ++F_col) {
168 tmp += f_basis->
item(F_row, F_col)*c[F_col];
170 double r_val = fabs(f_basis->
item(F_row, i) - tmp);
171 if (r_val > f_bv_max_local.row_val) {
172 f_bv_max_local.row_val = r_val;
173 f_bv_max_local.row = F_row;
176 MPI_Allreduce(&f_bv_max_local, &f_bv_max_global, 1,
177 MaxRowType, RowInfoOp, MPI_COMM_WORLD);
180 if (f_bv_max_global.proc == myid) {
181 for (
int j = 0; j < num_basis_vectors; ++j) {
182 c[j] = f_basis->
item(f_bv_max_global.row, j);
185 MPI_Bcast(c, num_basis_vectors, MPI_DOUBLE,
186 f_bv_max_global.proc, MPI_COMM_WORLD);
188 for (
int j = 0; j < num_basis_vectors; ++j) {
189 tmp_fs.
item(i, j) = c[j];
191 proc_sampled_f_row[f_bv_max_global.proc].insert(f_bv_max_global.row);
192 proc_f_row_to_tmp_fs_row[f_bv_max_global.proc][f_bv_max_global.row] = i;
198 for (
int i = 0; i < num_procs; ++i) {
199 set<int>& this_proc_sampled_f_row = proc_sampled_f_row[i];
200 map<int, int>& this_proc_f_row_to_tmp_fs_row =
201 proc_f_row_to_tmp_fs_row[i];
202 f_sampled_rows_per_proc[i] = this_proc_sampled_f_row.size();
203 for (set<int>::iterator j = this_proc_sampled_f_row.begin();
204 j != this_proc_sampled_f_row.end(); ++j) {
206 f_sampled_row[idx] = this_f_row;
207 int tmp_fs_row = this_proc_f_row_to_tmp_fs_row[this_f_row];
208 for (
int col = 0; col < num_f_basis_cols; ++col) {
209 f_basis_sampled_inv.
item(idx, col) = tmp_fs.
item(tmp_fs_row, col);
219 MPI_Type_free(&MaxRowType);
220 MPI_Op_free(&RowInfoOp);
void setSize(int num_rows, int num_cols)
Sets the number of rows and columns of the matrix and reallocates storage if needed....
Matrix * inverse() const
Computes and returns the inverse of this.
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...
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.
void DEIM(const Matrix *f_basis, int num_f_basis_vectors_used, std::vector< int > &f_sampled_row, std::vector< int > &f_sampled_rows_per_proc, Matrix &f_basis_sampled_inv, int myid, int num_procs)
Computes the DEIM algorithm on the given basis.