49 #include <Epetra_Export.h> 
   50 #include <Epetra_Import.h> 
   51 #include <Epetra_Util.h> 
   52 #include <Epetra_Map.h> 
   53 #include <Epetra_Comm.h> 
   54 #include <Epetra_CrsMatrix.h> 
   55 #include <Epetra_Vector.h> 
   56 #include <Epetra_Directory.h> 
   57 #include <Epetra_HashTable.h> 
   58 #include <Epetra_Distributor.h> 
   60 #include <Teuchos_TimeMonitor.hpp> 
   74            CrsMatrixStruct& Mview,
 
   79            CrsMatrixStruct& Mview,
 
   89 template<
typename int_type>
 
   90 double sparsedot(
double* u, int_type* u_ind, 
int u_len,
 
   91                  double* v, int_type* v_ind, 
int v_len)
 
   98   while(v_idx < v_len && u_idx < u_len) {
 
   99     int_type ui = u_ind[u_idx];
 
  100     int_type vi = v_ind[v_idx];
 
  109       result += u[u_idx++]*v[v_idx++];
 
  118 template<
typename int_type>
 
  122       bool keep_all_hard_zeros)
 
  128   for(i=0; i<Aview.
numRows; ++i) {
 
  131   for(i=0; i<Bview.
numRows; ++i) {
 
  144   int iworklen = maxlen*2 + numBcols;
 
  145   int_type* iwork = 
new int_type[iworklen];
 
  147   int_type * bcols = iwork+maxlen*2;
 
  149   Bview.
colMap->MyGlobalElementsPtr(bgids);
 
  150   double* bvals = 
new double[maxlen*2];
 
  151   double* avals = bvals+maxlen;
 
  153   int_type max_all_b = (int_type) Bview.
colMap->MaxAllGID64();
 
  154   int_type min_all_b = (int_type) Bview.
colMap->MinAllGID64();
 
  158   for(i=0; i<numBcols; ++i) {
 
  160     bcols[blid] = bgids[i];
 
  167   int_type* b_firstcol = 
new int_type[2*numBrows];
 
  168   int_type* b_lastcol = b_firstcol+numBrows;
 
  170   for(i=0; i<numBrows; ++i) {
 
  171     b_firstcol[i] = max_all_b;
 
  172     b_lastcol[i] = min_all_b;
 
  175     if (Blen_i < 1) 
continue;
 
  176     int* Bindices_i = Bview.
indices[i];
 
  179       for(k=0; k<Blen_i; ++k) {
 
  180         temp = (int_type) Bview.
importColMap->GID64(Bindices_i[k]);
 
  181         if (temp < b_firstcol[i]) b_firstcol[i] = temp;
 
  182         if (temp > b_lastcol[i]) b_lastcol[i] = temp;
 
  186       for(k=0; k<Blen_i; ++k) {
 
  187         temp = bcols[Bindices_i[k]];
 
  188         if (temp < b_firstcol[i]) b_firstcol[i] = temp;
 
  189         if (temp > b_lastcol[i]) b_lastcol[i] = temp;
 
  196   int_type* Aind = iwork;
 
  197   int_type* Bind = iwork+maxlen;
 
  199   bool C_filled = C.
Filled();
 
  210   for(i=0; i<Aview.
numRows; ++i) {
 
  215     int* Aindices_i = Aview.
indices[i];
 
  216     double* Aval_i  = Aview.
values[i];
 
  222     for(k=0; k<A_len_i; ++k) {
 
  223       Aind[k] = (int_type) Aview.
colMap->GID64(Aindices_i[k]);
 
  224       avals[k] = Aval_i[k];
 
  227     util.
Sort<int_type>(
true, A_len_i, Aind, 1, &avals, 0, NULL, 0, 0);
 
  229     int_type mina = Aind[0];
 
  230     int_type maxa = Aind[A_len_i-1];
 
  232     if (mina > max_all_b || maxa < min_all_b) {
 
  236     int_type global_row = (int_type) Aview.
rowMap->GID64(i);
 
  239     for(j=0; j<Bview.
numRows; ++j) {
 
  240       if (b_firstcol[j] > maxa || b_lastcol[j] < mina) {
 
  244       int* Bindices_j = Bview.
indices[j];
 
  254         for(k=0; k<B_len_j; ++k) {
 
  255           tmp = (int_type) Bview.
importColMap->GID64(Bindices_j[k]);
 
  256           if (tmp < mina || tmp > maxa) {
 
  260           bvals[Blen] = Bview.
values[j][k];
 
  265         for(k=0; k<B_len_j; ++k) {
 
  266           tmp = bcols[Bindices_j[k]];
 
  267           if (tmp < mina || tmp > maxa) {
 
  271           bvals[Blen] = Bview.
values[j][k];
 
  280       util.
Sort<int_type>(
true, Blen, Bind, 1, &bvals, 0, NULL, 0, 0);
 
  282       double C_ij = 
sparsedot(avals, Aind, A_len_i,
 
  285       if (!keep_all_hard_zeros && C_ij == 0.0) 
 
  288       int_type global_col = (int_type) Bview.
rowMap->GID64(j);
 
  303           std::cerr << 
"EpetraExt::MatrixMatrix::Multiply Warning: failed " 
  304               << 
"to insert value in result matrix at position "<<global_row
 
  305              <<
"," <<global_col<<
", possibly because result matrix has a " 
  306              << 
"column-map that doesn't include column "<<global_col
 
  307              <<
" on this proc." <<std::endl;
 
  316   delete [] b_firstcol;
 
  322       CrsMatrixStruct& Bview,
 
  324       bool keep_all_hard_zeros)
 
  326 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES 
  327   if(Aview.rowMap->GlobalIndicesInt() &&
 
  328      Aview.colMap->GlobalIndicesInt() &&
 
  329      Aview.rowMap->GlobalIndicesInt() &&
 
  330      Aview.colMap->GlobalIndicesInt()) {
 
  331     return mult_A_Btrans<int>(Aview, Bview, C, keep_all_hard_zeros);
 
  335 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES 
  336   if(Aview.rowMap->GlobalIndicesLongLong() &&
 
  337      Aview.colMap->GlobalIndicesLongLong() &&
 
  338      Aview.rowMap->GlobalIndicesLongLong() &&
 
  339      Aview.colMap->GlobalIndicesLongLong()) {
 
  340     return mult_A_Btrans<long long>(Aview, Bview, C, keep_all_hard_zeros);
 
  344     throw std::runtime_error(
"EpetraExt::mult_A_Btrans: GlobalIndices type unknown");
 
  349 template<
typename int_type>
 
  358   int C_firstCol_import = 0;
 
  359   int C_lastCol_import = -1;
 
  366   int C_numCols = C_lastCol - C_firstCol + 1;
 
  367   int C_numCols_import = C_lastCol_import - C_firstCol_import + 1;
 
  369   if (C_numCols_import > C_numCols) C_numCols = C_numCols_import;
 
  371   double* C_row_i = 
new double[C_numCols];
 
  372   int_type* C_colInds = 
new int_type[C_numCols];
 
  376   for(j=0; j<C_numCols; ++j) {
 
  395   Aview.
rowMap->MyGlobalElementsPtr(Arows);
 
  397   bool C_filled = C.
Filled();
 
  400   for(i=0; i<Aview.
numRows; ++i) {
 
  402     int* Aindices_i = Aview.
indices[i];
 
  403     double* Aval_i  = Aview.
values[i];
 
  409       std::cout << 
"mult_Atrans_B ERROR, proc "<<localProc<<
" needs row " 
  410            <<Arows[i]<<
" of matrix B, but doesn't have it."<<std::endl;
 
  414     int* Bcol_inds = Bview.
indices[Bi];
 
  415     double* Bvals_i = Bview.
values[Bi];
 
  427       for(j=0; j<Blen; ++j) {
 
  428         C_colInds[j] = (int_type) Bview.
importColMap->GID64(Bcol_inds[j]);
 
  432       for(j=0; j<Blen; ++j) {
 
  433         C_colInds[j] = (int_type) Bview.
colMap->GID64(Bcol_inds[j]);
 
  440       int Aj = Aindices_i[j];
 
  441       double Aval = Aval_i[j];
 
  448         global_row = (int_type) Aview.
colMap->GID64(Aj);
 
  455       for(k=0; k<Blen; ++k) {
 
  456         C_row_i[k] = Aval*Bvals_i[k];
 
  487              CrsMatrixStruct& Bview,
 
  490 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES 
  491   if(Aview.rowMap->GlobalIndicesInt() &&
 
  492      Aview.colMap->GlobalIndicesInt() &&
 
  493      Aview.rowMap->GlobalIndicesInt() &&
 
  494      Aview.colMap->GlobalIndicesInt()) {
 
  495     return mult_Atrans_B<int>(Aview, Bview, C);
 
  499 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES 
  500   if(Aview.rowMap->GlobalIndicesLongLong() &&
 
  501      Aview.colMap->GlobalIndicesLongLong() &&
 
  502      Aview.rowMap->GlobalIndicesLongLong() &&
 
  503      Aview.colMap->GlobalIndicesLongLong()) {
 
  504     return mult_Atrans_B<long long>(Aview, Bview, C);
 
  508     throw std::runtime_error(
"EpetraExt::mult_Atrans_B: GlobalIndices type unknown");
 
  512 template<
typename int_type>
 
  516            bool keep_all_hard_zeros)
 
  521   int C_firstCol_import = 0;
 
  522   int C_lastCol_import = -1;
 
  529   int C_numCols = C_lastCol - C_firstCol + 1;
 
  530   int C_numCols_import = C_lastCol_import - C_firstCol_import + 1;
 
  532   if (C_numCols_import > C_numCols) C_numCols = C_numCols_import;
 
  534   double* dwork = 
new double[C_numCols];
 
  535   int_type* iwork = 
new int_type[C_numCols];
 
  537   double* C_col_j = dwork;
 
  538   int_type* C_inds = iwork;
 
  542   for(j=0; j<C_numCols; ++j) {
 
  547   int_type* A_col_inds = 0;
 
  548   Aview.
colMap->MyGlobalElementsPtr(A_col_inds);
 
  549   int_type* A_col_inds_import = 0;
 
  551     Aview.
importColMap->MyGlobalElementsPtr(A_col_inds_import);
 
  564   Bview.
rowMap->MyGlobalElementsPtr(Brows);
 
  567   for(j=0; j<Bview.
numRows; ++j) {
 
  568     int* Bindices_j = Bview.
indices[j];
 
  569     double* Bvals_j = Bview.
values[j];
 
  571     int_type global_col = Brows[j];
 
  581       int bk = Bindices_j[k];
 
  582       double Bval = Bvals_j[k];
 
  589         global_k = (int_type) Bview.
colMap->GID64(bk);
 
  598       int* Aindices_k = Aview.
indices[ak];
 
  599       double* Avals_k = Aview.
values[ak];
 
  605           C_col_j[C_len] = Avals_k[i]*Bval;
 
  606           C_inds[C_len++] = A_col_inds_import[Aindices_k[i]];
 
  611           C_col_j[C_len] = Avals_k[i]*Bval;
 
  612           C_inds[C_len++] = A_col_inds[Aindices_k[i]];
 
  618       for(i=0; i < C_len ; ++i) {
 
  619         if (!keep_all_hard_zeros && C_col_j[i] == 0.0) 
continue;
 
  621         int_type global_row = C_inds[i];
 
  622         if (!Crowmap->
MyGID(global_row)) {
 
  651            CrsMatrixStruct& Bview,
 
  653            bool keep_all_hard_zeros)
 
  655 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES 
  656   if(Aview.rowMap->GlobalIndicesInt() &&
 
  657      Aview.colMap->GlobalIndicesInt() &&
 
  658      Aview.rowMap->GlobalIndicesInt() &&
 
  659      Aview.colMap->GlobalIndicesInt()) {
 
  660     return mult_Atrans_Btrans<int>(Aview, Bview, C, keep_all_hard_zeros);
 
  664 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES 
  665   if(Aview.rowMap->GlobalIndicesLongLong() &&
 
  666      Aview.colMap->GlobalIndicesLongLong() &&
 
  667      Aview.rowMap->GlobalIndicesLongLong() &&
 
  668      Aview.colMap->GlobalIndicesLongLong()) {
 
  669     return mult_Atrans_Btrans<long long>(Aview, Bview, C, keep_all_hard_zeros);
 
  673     throw std::runtime_error(
"EpetraExt::mult_Atrans_Btrans: GlobalIndices type unknown");
 
  677 template<
typename int_type>
 
  694 #ifdef ENABLE_MMM_TIMINGS 
  695   using Teuchos::TimeMonitor;
 
  696   Teuchos::RCP<Teuchos::TimeMonitor> MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(
"EpetraExt: MMM I&X Alloc")));
 
  705   targetMap.MyGlobalElementsPtr(Mrows);
 
  715   Mview.
rowMap       = &targetMap;
 
  722 #ifdef ENABLE_MMM_TIMINGS 
  723   MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(
"EpetraExt: MMM I&X Extract")));
 
  726   int *rowptr=0, *colind=0;
 
  731   if(Mrowmap.
SameAs(targetMap)) {
 
  733     for(
int i=0; i<Mview.
numRows; ++i) {
 
  735       Mview.
indices[i]          = colind + rowptr[i];
 
  736       Mview.
values[i]           = vals + rowptr[i];
 
  741   else if(prototypeImporter && prototypeImporter->SourceMap().SameAs(M.
RowMap()) && prototypeImporter->TargetMap().SameAs(targetMap)){
 
  743     int * PermuteToLIDs   = prototypeImporter->PermuteToLIDs();
 
  744     int * PermuteFromLIDs = prototypeImporter->PermuteFromLIDs();
 
  745     int * RemoteLIDs      = prototypeImporter->RemoteLIDs();
 
  746     for(
int i=0; i<prototypeImporter->NumSameIDs();i++){
 
  748       Mview.
indices[i]          = colind + rowptr[i];
 
  749       Mview.
values[i]           = vals + rowptr[i];
 
  752     for(
int i=0; i<prototypeImporter->NumPermuteIDs();i++){
 
  753       int to                     = PermuteToLIDs[i];
 
  754       int from                   = PermuteFromLIDs[i];
 
  756       Mview.
indices[to]          = colind + rowptr[from];
 
  757       Mview.
values[to]           = vals + rowptr[from];
 
  760     for(
int i=0; i<prototypeImporter->NumRemoteIDs();i++){
 
  761       Mview.
remote[RemoteLIDs[i]] = 
true;
 
  767     for(
int i=0; i<Mview.
numRows; ++i) {
 
  768       int mlid = Mrowmap.
LID(Mrows[i]);
 
  775         Mview.
indices[i]          = colind + rowptr[mlid];
 
  776         Mview.
values[i]           = vals + rowptr[mlid];
 
  782 #ifdef ENABLE_MMM_TIMINGS 
  783   MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(
"EpetraExt: MMM I&X Collective-0")));
 
  788       std::cerr << 
"EpetraExt::MatrixMatrix::Multiply ERROR, numProcs < 2 but " 
  789            << 
"attempting to import remote matrix rows."<<std::endl;
 
  802   int globalMaxNumRemote = 0;
 
  805   if (globalMaxNumRemote > 0) {
 
  806 #ifdef ENABLE_MMM_TIMINGS 
  807     MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(
"EpetraExt: MMM I&X Import-1")));
 
  813     for(
int i=0; i<Mview.
numRows; ++i) {
 
  815         MremoteRows[offset++] = Mrows[i];
 
  821 #ifdef ENABLE_MMM_TIMINGS 
  822     MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(
"EpetraExt: MMM I&X Import-2")));
 
  828     if(prototypeImporter && prototypeImporter->SourceMap().SameAs(M.
RowMap()) && prototypeImporter->TargetMap().SameAs(targetMap)) {
 
  831     else if(!prototypeImporter) {
 
  832       Epetra_Map MremoteRowMap2((int_type) -1, Mview.
numRemote, MremoteRows, (int_type) Mrowmap.IndexBase64(), Mrowmap.
Comm());
 
  836       throw std::runtime_error(
"prototypeImporter->SourceMap() does not match M.RowMap()!");
 
  839 #ifdef ENABLE_MMM_TIMINGS 
  840     MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(
"EpetraExt: MMM I&X Import-3")));
 
  847 #ifdef ENABLE_MMM_TIMINGS 
  848     MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(
"EpetraExt: MMM I&X Import-4")));
 
  866     for(
int i=0; i<Mview.
numRows; ++i) {
 
  868         int importLID = MremoteRowMap.LID(Mrows[i]);
 
  870         Mview.
indices[i]          = colind + rowptr[importLID];
 
  871         Mview.
values[i]           = vals + rowptr[importLID];
 
  876     int_type * MyColGIDs = 0;
 
  886     delete [] MremoteRows;
 
  887 #ifdef ENABLE_MMM_TIMINGS 
  904 template<
typename int_type>
 
  922   int_type* map1_elements = 0;
 
  923   map1->MyGlobalElementsPtr(map1_elements);
 
  925   int_type* map2_elements = 0;
 
  926   map2->MyGlobalElementsPtr(map2_elements);
 
  928   int_type* union_elements = 
new int_type[map1_len+map2_len];
 
  930   int map1_offset = 0, map2_offset = 0, union_offset = 0;
 
  932   while(map1_offset < map1_len && map2_offset < map2_len) {
 
  933     int_type map1_elem = map1_elements[map1_offset];
 
  934     int_type map2_elem = map2_elements[map2_offset];
 
  936     if (map1_elem < map2_elem) {
 
  937       union_elements[union_offset++] = map1_elem;
 
  940     else if (map1_elem > map2_elem) {
 
  941       union_elements[union_offset++] = map2_elem;
 
  945       union_elements[union_offset++] = map1_elem;
 
  952   for(i=map1_offset; i<map1_len; ++i) {
 
  953     union_elements[union_offset++] = map1_elements[i];
 
  956   for(i=map2_offset; i<map2_len; ++i) {
 
  957     union_elements[union_offset++] = map2_elements[i];
 
  960   mapunion = 
new Epetra_Map((int_type) -1, union_offset, union_elements,
 
  961                             (int_type) map1->IndexBase64(), map1->
Comm());
 
  963   delete [] union_elements;
 
  969 template<
typename int_type>
 
  978   std::pair<int_type,int_type> my_col_range = get_col_range<int_type>(column_map);
 
  981   int num_procs = Comm.
NumProc();
 
  982   int my_proc = Comm.MyPID();
 
  983   std::vector<int> send_procs;
 
  984   send_procs.reserve(num_procs-1);
 
  985   std::vector<int_type> col_ranges;
 
  986   col_ranges.reserve(2*(num_procs-1));
 
  987   for(
int p=0; p<num_procs; ++p) {
 
  988     if (p == my_proc) 
continue;
 
  989     send_procs.push_back(p);
 
  990     col_ranges.push_back(my_col_range.first);
 
  991     col_ranges.push_back(my_col_range.second);
 
  996   int num_recv_procs = 0;
 
  997   int num_send_procs = send_procs.size();
 
  998   bool deterministic = 
true;
 
  999   int* send_procs_ptr = send_procs.size()>0 ? &send_procs[0] : NULL;
 
 1000   distor->
CreateFromSends(num_send_procs, send_procs_ptr, deterministic, num_recv_procs);
 
 1002   int len_import_chars = 0;
 
 1003   char* import_chars = NULL;
 
 1005   char* export_chars = col_ranges.size()>0 ? 
reinterpret_cast<char*
>(&col_ranges[0]) : NULL;
 
 1006   int err = distor->
Do(export_chars, 2*
sizeof(int_type), len_import_chars, import_chars);
 
 1008     std::cout << 
"ERROR returned from Distributor::Do."<<std::endl;
 
 1011   int_type* IntImports = 
reinterpret_cast<int_type*
>(import_chars);
 
 1012   int num_import_pairs = len_import_chars/(2*
sizeof(int_type));
 
 1014   std::vector<int> send_procs2;
 
 1015   send_procs2.reserve(num_procs);
 
 1016   std::vector<int_type> proc_col_ranges;
 
 1017   std::pair<int_type,int_type> M_col_range = get_col_range<int_type>(M);
 
 1018   for(
int i=0; i<num_import_pairs; ++i) {
 
 1019     int_type first_col = IntImports[offset++];
 
 1020     int_type last_col =  IntImports[offset++];
 
 1021     if (first_col <= M_col_range.second && last_col >= M_col_range.first) {
 
 1022       send_procs2.push_back(send_procs[i]);
 
 1023       proc_col_ranges.push_back(first_col);
 
 1024       proc_col_ranges.push_back(last_col);
 
 1028   std::vector<int_type> send_rows;
 
 1029   std::vector<int> rows_per_send_proc;
 
 1034   int* send_procs2_ptr = send_procs2.size()>0 ? &send_procs2[0] : NULL;
 
 1036   err = distor2->
CreateFromSends(send_procs2.size(), send_procs2_ptr, deterministic, num_recv_procs);
 
 1038   export_chars = send_rows.size()>0 ? 
reinterpret_cast<char*
>(&send_rows[0]) : NULL;
 
 1039   int* rows_per_send_proc_ptr = rows_per_send_proc.size()>0 ? &rows_per_send_proc[0] : NULL;
 
 1040   len_import_chars = 0;
 
 1041   err = distor2->
Do(export_chars, (
int)
sizeof(int_type), rows_per_send_proc_ptr, len_import_chars, import_chars);
 
 1043   int_type* recvd_row_ints = 
reinterpret_cast<int_type*
>(import_chars);
 
 1044   int num_recvd_rows = len_import_chars/
sizeof(int_type);
 
 1046   Epetra_Map recvd_rows((int_type) -1, num_recvd_rows, recvd_row_ints, (int_type) column_map.IndexBase64(), Comm);
 
 1050   delete [] import_chars;
 
 1054   err = form_map_union<int_type>(&(M.
RowMap()), &recvd_rows, (
const Epetra_Map*&)result_map);
 
 1065 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES 
 1067     return Tfind_rows_containing_cols<int>(M, column_map);
 
 1071 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES 
 1073     return Tfind_rows_containing_cols<long long>(M, column_map);
 
 1077     throw std::runtime_error(
"EpetraExt::find_rows_containing_cols: GlobalIndices type unknown");
 
 1081 template<
typename int_type>
 
 1087          bool call_FillComplete_on_result,
 
 1088          bool keep_all_hard_zeros)
 
 1092 #ifdef ENABLE_MMM_TIMINGS 
 1093   using Teuchos::TimeMonitor;
 
 1094   Teuchos::RCP<TimeMonitor> MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(
"EpetraExt: MMM All Setup")));
 
 1119   if (transposeB && !transposeA) scenario = 2;
 
 1120   if (transposeA && !transposeB) scenario = 3;
 
 1121   if (transposeA && transposeB)  scenario = 4;
 
 1122   if(NewFlag && call_FillComplete_on_result && transposeA && !transposeB) scenario = 5; 
 
 1125   long long Aouter = transposeA ? A.NumGlobalCols64() : A.NumGlobalRows64();
 
 1126   long long Bouter = transposeB ? B.NumGlobalRows64() : B.NumGlobalCols64();
 
 1127   long long Ainner = transposeA ? A.NumGlobalRows64() : A.NumGlobalCols64();
 
 1128   long long Binner = transposeB ? B.NumGlobalCols64() : B.NumGlobalRows64();
 
 1129   if (Ainner != Binner) {
 
 1130     std::cerr << 
"MatrixMatrix::Multiply: ERROR, inner dimensions of op(A) and op(B) " 
 1131          << 
"must match for matrix-matrix product. op(A) is " 
 1132          <<Aouter<<
"x"<<Ainner << 
", op(B) is "<<Binner<<
"x"<<Bouter<<std::endl;
 
 1140   if (Aouter > C.NumGlobalRows64()) {
 
 1141     std::cerr << 
"MatrixMatrix::Multiply: ERROR, dimensions of result C must " 
 1142          << 
"match dimensions of op(A) * op(B). C has "<<C.NumGlobalRows64()
 
 1143          << 
" rows, should have at least "<<Aouter << std::endl;
 
 1173   CrsMatrixStruct Aview;
 
 1174   CrsMatrixStruct Atransview;
 
 1175   CrsMatrixStruct Bview;
 
 1176   Teuchos::RCP<Epetra_CrsMatrix> Atrans;
 
 1181 #ifdef ENABLE_MMM_TIMINGS 
 1182   MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(
"EpetraExt: MMM All I&X")));
 
 1188     if (scenario == 3 || scenario == 4) {
 
 1189       workmap1 = Tfind_rows_containing_cols<int_type>(A, *domainMap_A);
 
 1190       targetMap_A = workmap1;
 
 1193   if (scenario == 5) {
 
 1194     targetMap_A = &(A.
ColMap());
 
 1198   if(scenario==1 && call_FillComplete_on_result) {
 
 1199     EPETRA_CHK_ERR(import_only<int_type>(A,*targetMap_A,Aview));
 
 1201   else if (scenario == 5){
 
 1205     Atrans = Teuchos::rcp(at.CreateTransposeLocal(*Anonconst));
 
 1206     import_only<int_type>(*Atrans,*targetMap_A,Atransview);
 
 1209     EPETRA_CHK_ERR( import_and_extract_views<int_type>(A, *targetMap_A, Aview));
 
 1219   if(scenario==1 || numProcs > 1){
 
 1220     if (transposeA && scenario == 3) {
 
 1221       colmap_op_A = targetMap_A;
 
 1224       colmap_op_A = &(A.
ColMap());
 
 1226     targetMap_B = colmap_op_A;
 
 1228   if(scenario==5) targetMap_B = &(B.
RowMap());
 
 1237       EPETRA_CHK_ERR( form_map_union<int_type>(colmap_op_A, domainMap_B, mapunion1) );
 
 1238       workmap2 = Tfind_rows_containing_cols<int_type>(B, *mapunion1);
 
 1239       targetMap_B = workmap2;
 
 1244   if((scenario==1 && call_FillComplete_on_result) || scenario==5) {
 
 1245     EPETRA_CHK_ERR(import_only<int_type>(B,*targetMap_B,Bview,A.
Importer()));
 
 1248     EPETRA_CHK_ERR( import_and_extract_views<int_type>(B, *targetMap_B, Bview) );
 
 1251 #ifdef ENABLE_MMM_TIMINGS 
 1252   MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(
"EpetraExt: MMM All Multiply")));
 
 1259   CrsWrapper_Epetra_CrsMatrix ecrsmat(C);
 
 1262   case 1:    EPETRA_CHK_ERR( mult_A_B(A,Aview,B,Bview,C,call_FillComplete_on_result, keep_all_hard_zeros) );
 
 1264   case 2:    EPETRA_CHK_ERR( 
mult_A_Btrans(Aview, Bview, ecrsmat, keep_all_hard_zeros) );
 
 1266   case 3:    EPETRA_CHK_ERR( 
mult_Atrans_B(Aview, Bview, ecrsmat) );
 
 1268   case 4:    EPETRA_CHK_ERR( 
mult_Atrans_Btrans(Aview, Bview, ecrsmat, keep_all_hard_zeros) );
 
 1270   case 5:    EPETRA_CHK_ERR( mult_AT_B_newmatrix(Atransview, Bview, C, keep_all_hard_zeros) );
 
 1275   if (scenario != 1 && call_FillComplete_on_result && scenario != 5) {
 
 1290       EPETRA_CHK_ERR( C.
FillComplete(*domainmap, *rangemap) );
 
 1297   delete mapunion1; mapunion1 = NULL;
 
 1298   delete workmap1; workmap1 = NULL;
 
 1299   delete workmap2; workmap2 = NULL;
 
 1309                            bool call_FillComplete_on_result,
 
 1310          bool keep_all_hard_zeros)
 
 1312 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES 
 1314     return TMultiply<int>(A, transposeA, B, transposeB, C, call_FillComplete_on_result,  keep_all_hard_zeros);
 
 1318 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES 
 1320     return TMultiply<long long>(A, transposeA, B, transposeB, C, call_FillComplete_on_result,  keep_all_hard_zeros);
 
 1324     throw std::runtime_error(
"EpetraExt::MatrixMatrix::Add: GlobalIndices type unknown");
 
 1328 template<
typename int_type>
 
 1344     std::cerr << 
"EpetraExt::MatrixMatrix::Add ERROR, input matrix A.Filled() is false, it is required to be true. (Result matrix B is not required to be Filled())."<<std::endl;
 
 1360   int A_NumEntries, B_NumEntries;
 
 1361   int_type * A_Indices = 
new int_type[MaxNumEntries];
 
 1362   double * A_Values = 
new double[MaxNumEntries];
 
 1363   int* B_Indices_local;
 
 1364   int_type* B_Indices_global;
 
 1375     for( 
int i = 0; i < NumMyRows; ++i )
 
 1377       Row = (int_type) B.GRID64(i);
 
 1378       EPETRA_CHK_ERR( Aprime->
ExtractGlobalRowCopy( Row, MaxNumEntries, A_NumEntries, A_Values, A_Indices ) );
 
 1380       if (scalarB != 1.0) {
 
 1383                                                   B_Values, B_Indices_global));
 
 1387                                               B_Values, B_Indices_local));
 
 1390         for(
int jj=0; jj<B_NumEntries; ++jj) {
 
 1391           B_Values[jj] = scalarB*B_Values[jj];
 
 1395       if( scalarA != 1.0 ) {
 
 1396         for( 
int j = 0; j < A_NumEntries; ++j ) A_Values[j] *= scalarA;
 
 1402         if (err < 0) ierr = err;
 
 1406         assert( err == 0 || err == 1 || err == 3 );
 
 1407         if (err < 0) ierr = err;
 
 1412     EPETRA_CHK_ERR( B.
Scale(scalarB) );
 
 1415   delete [] A_Indices;
 
 1418   if( Atrans ) 
delete Atrans;
 
 1429 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES 
 1431         return TAdd<int>(A, transposeA, scalarA, B, scalarB);
 
 1435 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES 
 1437         return TAdd<long long>(A, transposeA, scalarA, B, scalarB);
 
 1441     throw std::runtime_error(
"EpetraExt::MatrixMatrix::Add: GlobalIndices type unknown");
 
 1444 template<
typename int_type>
 
 1459      std::cerr << 
"EpetraExt::MatrixMatrix::Add ERROR, input matrix A.Filled() or B.Filled() is false," 
 1460                << 
"they are required to be true. (Result matrix C should be an empty pointer)" << std::endl;
 
 1492   double scalar[] = { scalarA, scalarB};
 
 1495   for(
int k=0;k<2;k++) {
 
 1498      int_type * Indices = 
new int_type[MaxNumEntries];
 
 1499      double * Values = 
new double[MaxNumEntries];
 
 1506      for( 
int i = 0; i < NumMyRows; ++i ) {
 
 1507         Row = (int_type) Mat[k]->GRID64(i);
 
 1508         EPETRA_CHK_ERR( Mat[k]->ExtractGlobalRowCopy( Row, MaxNumEntries, NumEntries, Values, Indices));
 
 1510         if( scalar[k] != 1.0 )
 
 1511            for( 
int j = 0; j < NumEntries; ++j ) Values[j] *= scalar[k];
 
 1515            if (err < 0) ierr = err;
 
 1518            if (err < 0) ierr = err;
 
 1526   if( Atrans ) 
delete Atrans;
 
 1527   if( Btrans ) 
delete Btrans;
 
 1540 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES 
 1542         return TAdd<int>(A, transposeA, scalarA, B, transposeB, scalarB, C);
 
 1546 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES 
 1548         return TAdd<long long>(A, transposeA, scalarA, B, transposeB, scalarB, C);
 
 1552     throw std::runtime_error(
"EpetraExt::MatrixMatrix::Add: GlobalIndices type unknown");
 
 1558 template<
typename int_type>
 
 1559 int MatrixMatrix::TJacobi(
double omega,
 
 1564                           bool call_FillComplete_on_result)
 
 1566 #ifdef ENABLE_MMM_TIMINGS 
 1567   using Teuchos::TimeMonitor;
 
 1568   Teuchos::RCP<TimeMonitor> MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(
"EpetraExt: Jacobi All Setup")));
 
 1577   long long Aouter = A.NumGlobalRows64();
 
 1578   long long Bouter = B.NumGlobalCols64();
 
 1579   long long Ainner = A.NumGlobalCols64();
 
 1580   long long Binner = B.NumGlobalRows64();
 
 1581   long long Dlen   = Dinv.GlobalLength64();
 
 1582   if (Ainner != Binner) {
 
 1583     std::cerr << 
"MatrixMatrix::Jacobi: ERROR, inner dimensions of A and B " 
 1584          << 
"must match for matrix-matrix product. A is " 
 1585          <<Aouter<<
"x"<<Ainner << 
", B is "<<Binner<<
"x"<<Bouter<<std::endl;
 
 1593   if (Aouter > C.NumGlobalRows64()) {
 
 1594     std::cerr << 
"MatrixMatrix::Jacobi: ERROR, dimensions of result C must " 
 1595          << 
"match dimensions of A * B. C has "<<C.NumGlobalRows64()
 
 1596          << 
" rows, should have at least "<<Aouter << std::endl;
 
 1601   if(Dlen != Aouter) {
 
 1602     std::cerr << 
"MatrixMatrix::Jacboi: ERROR, dimensions of result D must " 
 1603               << 
"match dimensions of A's rows. D has "<< Dlen
 
 1604               << 
" rows, should have " << Aouter << std::endl;
 
 1609     std::cerr << 
"MatrixMatrix::Jacboi: ERROR, RowMap of A must match RowMap of B " 
 1610               << 
"and Map of D."<<std::endl;
 
 1637   CrsMatrixStruct Aview;
 
 1638   CrsMatrixStruct Bview;
 
 1643 #ifdef ENABLE_MMM_TIMINGS 
 1644   MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(
"EpetraExt: Jacobi All I&X")));
 
 1648   if(call_FillComplete_on_result) {
 
 1649     EPETRA_CHK_ERR(import_only<int_type>(A,*targetMap_A,Aview));
 
 1652     EPETRA_CHK_ERR( import_and_extract_views<int_type>(A, *targetMap_A, Aview));
 
 1661     colmap_op_A = &(A.
ColMap());
 
 1662     targetMap_B = colmap_op_A;
 
 1666   if(call_FillComplete_on_result) {
 
 1667     EPETRA_CHK_ERR(import_only<int_type>(B,*targetMap_B,Bview,A.
Importer()));
 
 1670     EPETRA_CHK_ERR( import_and_extract_views<int_type>(B, *targetMap_B, Bview) );
 
 1673 #ifdef ENABLE_MMM_TIMINGS 
 1674   MM = Teuchos::rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(
"EpetraExt: Jacobi All Multiply")));
 
 1681   CrsWrapper_Epetra_CrsMatrix ecrsmat(C);
 
 1682   EPETRA_CHK_ERR( jacobi_A_B(omega,Dinv,A,Aview,B,Bview,C,call_FillComplete_on_result) );
 
 1686   delete mapunion1; mapunion1 = NULL;
 
 1687   delete workmap1; workmap1 = NULL;
 
 1688   delete workmap2; workmap2 = NULL;
 
 1700                          bool call_FillComplete_on_result)
 
 1702 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES 
 1704     return TJacobi<int>(omega, Dinv, A, B, C, call_FillComplete_on_result);
 
 1708 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES 
 1710     return TJacobi<long long>(omega, Dinv, A, B, C, call_FillComplete_on_result);
 
 1714     throw std::runtime_error(
"EpetraExt::MatrixMatrix::Jacobi: GlobalIndices type unknown");
 
LightweightCrsMatrix * importMatrix
 
const Epetra_Map & RangeMap() const 
 
Epetra_BlockMap * RowMapEP_
 
virtual int SumIntoGlobalValues(int GlobalRow, int NumEntries, double *Values, int *Indices)=0
 
virtual int SumIntoGlobalValues(int GlobalRow, int NumEntries, const double *Values, const int *Indices)
 
bool GlobalIndicesLongLong() const 
 
void MyGlobalElementsPtr(int *&MyGlobalElementList) const 
 
bool SameAs(const Epetra_BlockMap &Map) const 
 
LightweightMap * RowMapLW_
 
void pack_outgoing_rows(const Epetra_CrsMatrix &mtx, const std::vector< int > &proc_col_ranges, std::vector< int > &send_rows, std::vector< int > &rows_per_send_proc)
 
const Epetra_Map * rowMap
 
virtual int CreateFromSends(const int &NumExportIDs, const int *ExportPIDs, bool Deterministic, int &NumRemoteIDs)=0
 
const Epetra_Map & RowMatrixRowMap() const 
 
static int Multiply(const Epetra_CrsMatrix &A, bool transposeA, const Epetra_CrsMatrix &B, bool transposeB, Epetra_CrsMatrix &C, bool call_FillComplete_on_result=true, bool keep_all_hard_zeros=false)
Given Epetra_CrsMatrix objects A, B and C, form the product C = A*B. 
 
virtual int InsertGlobalValues(int GlobalRow, int NumEntries, double *Values, int *Indices)=0
 
std::vector< int > colind_
 
bool GlobalIndicesInt() const 
 
const Epetra_Map & ColMap() const 
 
bool IndicesAreLocal() const 
 
const Epetra_CrsMatrix * origMatrix
 
Transform to form the explicit transpose of a Epetra_RowMatrix. 
 
virtual int MyPID() const =0
 
int FillComplete(bool OptimizeDataStorage=true)
 
virtual int MaxAll(double *PartialMaxs, double *GlobalMaxs, int Count) const =0
 
int ExtractMyRowView(int MyRow, int &NumEntries, double *&Values, int *&Indices) const 
 
int PutScalar(double ScalarConstant)
 
Epetra_Map * find_rows_containing_cols(const Epetra_CrsMatrix &M, const Epetra_Map &column_map)
 
int mult_Atrans_Btrans(CrsMatrixStruct &Aview, CrsMatrixStruct &Bview, CrsWrapper &C, bool keep_all_hard_zeros)
 
const Epetra_Map & RowMap() const 
 
int NumMyElements() const 
 
int form_map_union(const Epetra_Map *map1, const Epetra_Map *map2, const Epetra_Map *&mapunion)
 
const Epetra_Map * origRowMap
 
int import_and_extract_views(const Epetra_CrsMatrix &M, const Epetra_Map &targetMap, CrsMatrixStruct &Mview, const Epetra_Import *prototypeImporter=0)
 
virtual const Epetra_Map & RowMap() const =0
 
const Epetra_Import * Importer() const 
 
int ExtractGlobalRowView(int GlobalRow, int &NumEntries, double *&Values, int *&Indices) const 
 
int NumMyElements() const 
 
int MaxNumEntries() const 
 
int ExtractGlobalRowCopy(int GlobalRow, int Length, int &NumEntries, double *Values, int *Indices) const 
 
int mult_Atrans_B(CrsMatrixStruct &Aview, CrsMatrixStruct &Bview, CrsWrapper &C)
 
static void Sort(bool SortAscending, int NumKeys, T *Keys, int NumDoubleCompanions, double **DoubleCompanions, int NumIntCompanions, int **IntCompanions, int NumLongLongCompanions, long long **LongLongCompanions)
 
const Epetra_Map * domainMap
 
bool MyGID(int GID_in) const 
 
std::vector< double > vals_
 
static int Add(const Epetra_CrsMatrix &A, bool transposeA, double scalarA, Epetra_CrsMatrix &B, double scalarB)
Given Epetra_CrsMatrix objects A and B, form the sum B = a*A + b*B. 
 
const Epetra_Comm & Comm() const 
 
virtual int Do(char *export_objs, int obj_size, int &len_import_objs, char *&import_objs)=0
 
bool IndicesAreGlobal() const 
 
long long IndexBase64() const 
 
virtual int InsertGlobalValues(int GlobalRow, int NumEntries, const double *Values, const int *Indices)
 
double sparsedot(double *u, int_type *u_ind, int u_len, double *v, int_type *v_ind, int v_len)
Method for internal use... 
 
virtual int NumProc() const =0
 
static int Jacobi(double omega, const Epetra_Vector &Dinv, const Epetra_CrsMatrix &A, const Epetra_CrsMatrix &B, Epetra_CrsMatrix &C, bool call_FillComplete_on_result=true)
Given Epetra_CrsMatrix objects A, B and C, and Epetra_Vector Dinv, form the product C = (I-omega * Di...
 
const Epetra_Map & DomainMap() const 
 
Epetra_Map * Tfind_rows_containing_cols(const Epetra_CrsMatrix &M, const Epetra_Map &column_map)
 
int Scale(double ScalarConstant)
 
std::vector< int > rowptr_
 
int mult_A_Btrans(CrsMatrixStruct &Aview, CrsMatrixStruct &Bview, CrsWrapper &C, bool keep_all_hard_zeros)
 
const Epetra_Map * colMap
 
const Epetra_BlockMap * importColMap
 
const Epetra_Comm & Comm() const 
 
int import_only(const Epetra_CrsMatrix &M, const Epetra_Map &targetMap, CrsMatrixStruct &Mview, const Epetra_Import *prototypeImporter)
 
int ExtractCrsDataPointers(int *&IndexOffset, int *&Indices, double *&Values_in) const