src/matrix_matrix.cpp

Go to the documentation of this file.
00001 //
00002 // C++ Implementation: matrix_matrix
00003 //
00004 // Description: 
00005 //
00006 //
00007 // Author: Roman Geus <geus@maxwell>, (C) 2004
00008 //
00009 // Copyright: See COPYING file that comes with this distribution
00010 //
00011 //
00012 
00013 #include <algorithm>
00014 #include <vector>
00015 #include <set>
00016 #include "rlog/rlog.h"
00017 #include "Epetra_Comm.h"
00018 #include "Epetra_CrsMatrix.h"
00019 #include "Epetra_FECrsMatrix.h"
00020 #include "Epetra_Export.h"
00021 #include "Epetra_Import.h"
00022 #include "Epetra_Map.h"
00023 #include "matrix_matrix.h"
00024 
00025 #define USE_MM_COLMAP 1
00026 
00027 using namespace std;
00028 
00031 static void bext_map_1(const Epetra_CrsMatrix& A, std::vector<int>& col_indices) {
00032     for (int i_local = 0; i_local < A.NumMyRows(); ++ i_local) {
00033         int info;
00034         int num_entries_A;
00035         double *values_A;
00036         int *indices_A;
00037 
00038         // extract non-zeros of row i
00039         info = A.ExtractMyRowView(i_local, num_entries_A, values_A, indices_A);
00040         rAssert(info == 0);
00041 
00042         // loop over non-zero entries of row i of A
00043         for (int k = 0; k < num_entries_A; ++ k) {
00044             int j_global = A.GCID(indices_A[k]);
00045 
00046             // add j_global to list of indices
00047             std::vector<int>::iterator found_it;
00048             found_it = std::find(col_indices.begin(),
00049                                  col_indices.end(),
00050                                  j_global);
00051             if (found_it == col_indices.end()) {
00052                 col_indices.push_back(j_global);
00053             }
00054         }
00055 
00056     } // for i_local
00057 }
00058 
00061 static void bext_map_2(const Epetra_CrsMatrix& A, std::vector<int>& col_indices) {
00062     for (int i_local = 0; i_local < A.NumMyRows(); ++ i_local) {
00063         int info;
00064         int num_entries_A;
00065         double *values_A;
00066         int *indices_A;
00067 
00068         // extract non-zeros of row i
00069         info = A.ExtractMyRowView(i_local, num_entries_A, values_A, indices_A);
00070         rAssert(info == 0);
00071 
00072         // loop over non-zero entries of row i of A
00073         for (int k = 0; k < num_entries_A; ++ k) {
00074             int j_global = A.GCID(indices_A[k]);
00075             col_indices.push_back(j_global);
00076         }
00077 
00078     } // for i_local
00079     std::sort(col_indices.begin(), col_indices.end());
00080     std::vector<int>::iterator erase_it = std::unique(col_indices.begin(), col_indices.end());
00081     col_indices.erase(erase_it, col_indices.end());
00082 }
00083 
00086 static void bext_map_3(const Epetra_CrsMatrix& A, std::vector<int>& col_indices) {
00087     std::set<int> set_B;
00088     for (int i_local = 0; i_local < A.NumMyRows(); ++ i_local) {
00089         int info;
00090         int num_entries_A;
00091         double *values_A;
00092         int *indices_A;
00093 
00094         // extract non-zeros of row i
00095         info = A.ExtractMyRowView(i_local, num_entries_A, values_A, indices_A);
00096         rAssert(info == 0);
00097 
00098         // loop over non-zero entries of row i of A
00099         for (int k = 0; k < num_entries_A; ++ k) {
00100             int j_global = A.GCID(indices_A[k]);
00101             set_B.insert(j_global);
00102         }
00103 
00104     } // for i_local
00105 
00106     col_indices.reserve(set_B.size());
00107     for (std::set<int>::iterator it = set_B.begin();
00108         it != set_B.end();
00109         ++ it)
00110     {
00111         col_indices.push_back(*it);
00112     }
00113 }
00114 
00116 int poor_man_matrix_matrix(const Epetra_CrsMatrix& A, const Epetra_CrsMatrix& B, Epetra_CrsMatrix& C) {
00117     int info;
00118 
00119     if (A.Comm().NumProc() == 1) {
00120         // call optimised code for np == 1
00121         return poor_man_matrix_matrix_local(A, B, C);
00122     }
00123 
00124     // Calculate new map for B
00125     // Note: the indices need not to be sorted
00126 #ifdef USE_MM_COLMAP
00127     Epetra_Map map_B(A.ColMap());
00128 #else
00129     // Compute indices of rows of B needed
00130     std::vector<int> indices_B;
00131     bext_map_3(A, indices_B);
00132     rDebug("%d: poor_man_matrix_matrix: local rows: %d -> %d",
00133            A.Comm().MyPID(), B.NumMyRows(), indices_B.size());
00134     rDebug("%d: poor_man_matrix_matrix: column map size: %d",
00135            A.Comm().MyPID(), A.ColMap().NumMyElements());
00136     Epetra_Map map_B(-1, indices_B.size(), &indices_B[0], 0, A.Comm());
00137 #endif
00138 
00139     // Redistribute B using new map
00140     Epetra_Import plan_B(map_B, B.RowMap());
00141     Epetra_CrsMatrix Bext(Copy, map_B, 0);
00142     info = Bext.Import(B, plan_B, Insert);
00143     rAssert(info == 0);
00144     info = Bext.FillComplete(B.DomainMap(), B.RangeMap());
00145     rAssert(info == 0);
00146 
00147     // loop over rows of A
00148     for (int i_local = 0; i_local < A.NumMyRows(); ++ i_local) {
00149         // extract non-zeros of row i
00150         int num_entries_A, num_entries_B;
00151         double *values_A, *values_B;
00152         int *indices_A, *indices_B;
00153         info = A.ExtractMyRowView(i_local, num_entries_A, values_A, indices_A);
00154         rAssert(info == 0);
00155 
00156         // do local computation
00157         for (int k = 0; k < num_entries_A; ++ k) {
00158             int j_global = A.GCID(indices_A[k]);
00159             rAssert(Bext.MyGRID(j_global));
00160             info = Bext.ExtractMyRowView(Bext.LRID(j_global), num_entries_B, values_B, indices_B);
00161             rAssert(info == 0);
00162             for (int l = 0; l < num_entries_B; ++ l) {
00163                 double value = values_A[k] * values_B[l];
00164                 int index = Bext.GCID(indices_B[l]);
00165                 info = C.SumIntoGlobalValues(A.GRID(i_local), 1, &value, &index);
00166                 if (info > 0)
00167                     info = C.InsertGlobalValues(A.GRID(i_local), 1, &value, &index);
00168                 rAssert(info >= 0);
00169             } // for l
00170         } // for k
00171 
00172     } // for i_local
00173     info = C.FillComplete(B.OperatorDomainMap(), A.OperatorRangeMap());
00174     rAssert(info >= 0);
00175     return 0;
00176 }
00177 
00180 int poor_man_matrix_matrix_local(const Epetra_CrsMatrix& A, const Epetra_CrsMatrix& B, Epetra_CrsMatrix& C) {
00181     int info;
00182 
00183     // loop over rows of A
00184     for (int i_local = 0; i_local < A.NumMyRows(); ++ i_local) {
00185         // extract non-zeros of row i
00186         int num_entries_A, num_entries_B;
00187         double *values_A, *values_B;
00188         int *indices_A, *indices_B;
00189         info = A.ExtractMyRowView(i_local, num_entries_A, values_A, indices_A);
00190         rAssert(info == 0);
00191 
00192         // do local computation
00193         for (int k = 0; k < num_entries_A; ++ k) {
00194             int j_global = A.GCID(indices_A[k]);
00195             if (B.MyGRID(j_global)) {
00196                 // row j_global of M is local
00197                 info = B.ExtractMyRowView(B.LRID(j_global), num_entries_B, values_B, indices_B);
00198                 rAssert(info == 0);
00199                 for (int l = 0; l < num_entries_B; ++ l) {
00200                     double value = values_A[k] * values_B[l];
00201                     int index = B.GCID(indices_B[l]);
00202                     info = C.SumIntoGlobalValues(A.GRID(i_local), 1, &value, &index);
00203                     if (info > 0)
00204                         info = C.InsertGlobalValues(A.GRID(i_local), 1, &value, &index);
00205                     rAssert(info >= 0);
00206                 } // for l
00207             }
00208         } // for k
00209 
00210     } // for i_local
00211     info = C.FillComplete(B.OperatorDomainMap(), A.OperatorRangeMap());
00212     rAssert(info >= 0);
00213     return 0;
00214 }
00215 
00217 int poor_man_matrix_matrix_graph(const Epetra_CrsGraph& A, const Epetra_CrsGraph& B, Epetra_CrsGraph& C) {
00218     int max_nnz_B = B.MaxNumIndices();
00219     vector<int> ind_B(max_nnz_B);
00220     int *indices_B = &ind_B[0];
00221 
00222     // loop over rows of A
00223     for (int i_local = 0; i_local < A.NumMyRows(); ++ i_local) {
00224         // extract non-zeros of row i
00225         int num_entries_A, num_entries_B;
00226         int *indices_A;
00227         int info;
00228         info = A.ExtractMyRowView(i_local, num_entries_A, indices_A);
00229         rAssert(info == 0);
00230 
00231         // do local computation
00232         for (int k = 0; k < num_entries_A; ++ k) {
00233             int j_global = A.GCID(indices_A[k]);
00234             if (B.MyGRID(j_global)) {
00235                 // row j_global of M is local
00236                 info = B.ExtractMyRowCopy(B.LRID(j_global), max_nnz_B, num_entries_B, indices_B);
00237                 rAssert(info == 0);
00238                 // transform to global column indices
00239                 for (int l = 0; l < num_entries_B; ++ l)
00240                     indices_B[l] = B.GCID(indices_B[l]);
00241                 // insert into C
00242                 info = C.InsertGlobalIndices(A.GRID(i_local), num_entries_B, indices_B);
00243                 rAssert(info >= 0);
00244             }
00245         } // for k
00246     } // for i_local
00247     return 0;
00248 }
00249 
00253 int poor_man_matrix_matrix_local2(const Epetra_CrsMatrix& A, const Epetra_CrsMatrix& B, Epetra_CrsMatrix& C) {
00254     int info;
00255 
00256     int max_nnz_B = B.MaxNumEntries();
00257     vector<int> ind_B(max_nnz_B);
00258     vector<double> val_B(max_nnz_B);
00259     double *values_B = &val_B[0];
00260     int *indices_B = &ind_B[0];
00261 
00262     // FIXME: A and C must have the same RowMap() or this routine fails!
00263     // FIXME: B and C must have the same ColMap() or this routine fails!
00264 
00265     // loop over rows of A
00266     for (int i_local = 0; i_local < A.NumMyRows(); ++ i_local) {
00267         // extract non-zeros of row i
00268         int num_entries_A, num_entries_B;
00269         double *values_A;
00270         int *indices_A;
00271         info = A.ExtractMyRowView(i_local, num_entries_A, values_A, indices_A);
00272         rAssert(info == 0);
00273 
00274         // do local computation
00275         for (int k = 0; k < num_entries_A; ++ k) {
00276             int j_global = A.GCID(indices_A[k]);
00277             if (B.MyGRID(j_global)) {
00278                 // extract row j of B (having local indices)
00279                 info = B.ExtractMyRowCopy(B.LRID(j_global), max_nnz_B, num_entries_B, values_B, indices_B);
00280                 rAssert(info == 0);
00281                 // scale extracted row by A[i,j]
00282                 for (int l = 0; l < num_entries_B; ++ l)
00283                     values_B[l] *= values_A[k];
00284                 // add scaled row into row i of C
00285                 info = C.SumIntoMyValues(i_local, num_entries_B, values_B, indices_B);
00286                 if (info != 0)
00287                     rDebug("info=%d", info);
00288                 rAssert(info == 0);
00289             }
00290         } // for k
00291 
00292     } // for i_local
00293     info = C.FillComplete(B.OperatorDomainMap(), A.OperatorRangeMap());
00294     rAssert(info >= 0);
00295     return 0;
00296 }
00297 
00298 int transpose_matrix(const Epetra_CrsMatrix& A, Epetra_FECrsMatrix& T) {
00299     int info;
00300     
00301     for (int lrow = 0; lrow < A.NumMyRows(); lrow ++) {
00302         int grow = A.RowMap().GID(lrow);
00303         int nof_entries;
00304         int* col;
00305         double* val;
00306         info = A.ExtractMyRowView(lrow, nof_entries, val, col);
00307         rAssert(info == 0);
00308     
00309         for (int k = 0; k < nof_entries; k ++) {
00310             int gcol = A.ColMap().GID(col[k]);
00311             info = T.InsertGlobalValues(1, &gcol, 1, &grow, val+k);
00312             rAssert(info >= 0);
00313         }
00314     }
00315     
00316     info = T.GlobalAssemble(false);
00317     rAssert(info == 0);
00318     info = T.FillComplete(A.OperatorRangeMap(), A.OperatorDomainMap());
00319     rAssert(info == 0);
00320     return 0;   
00321 }

Generated on Fri Oct 26 13:35:12 2007 for FEMAXX (Finite Element Maxwell Eigensolver) by  doxygen 1.4.7