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> 
   89template<
typename int_type>
 
   90double 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++];
 
 
  118template<
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;
 
 
  324      bool keep_all_hard_zeros)
 
  326#ifndef EPETRA_NO_32BIT_GLOBAL_INDICES 
  331    return mult_A_Btrans<int>(Aview, Bview, C, keep_all_hard_zeros);
 
  335#ifndef EPETRA_NO_64BIT_GLOBAL_INDICES 
  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");
 
 
  349template<
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];
 
 
  490#ifndef EPETRA_NO_32BIT_GLOBAL_INDICES 
  495    return mult_Atrans_B<int>(Aview, Bview, C);
 
  499#ifndef EPETRA_NO_64BIT_GLOBAL_INDICES 
  504    return mult_Atrans_B<long long>(Aview, Bview, C);
 
  508    throw std::runtime_error(
"EpetraExt::mult_Atrans_B: GlobalIndices type unknown");
 
 
  512template<
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)) {
 
 
  653           bool keep_all_hard_zeros)
 
  655#ifndef EPETRA_NO_32BIT_GLOBAL_INDICES 
  660    return mult_Atrans_Btrans<int>(Aview, Bview, C, keep_all_hard_zeros);
 
  664#ifndef EPETRA_NO_64BIT_GLOBAL_INDICES 
  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");
 
 
  677template<
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 
 
  904template<
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;
 
 
  969template<
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");
 
 
 1081template<
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) {
 
 1284      transposeB ? &(B.
RangeMap()) : &(B.DomainMap());
 
 1287      transposeA ? &(A.
DomainMap()) : &(A.RangeMap());
 
 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");
 
 
 1328template<
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");
 
 
 1444template<
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");
 
 
 1558template<
typename int_type>
 
 1559int 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();
 
 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");
 
 
const Epetra_CrsMatrix * origMatrix
 
const Epetra_Map * rowMap
 
const Epetra_Map * colMap
 
const Epetra_Map * domainMap
 
LightweightCrsMatrix * importMatrix
 
const Epetra_BlockMap * importColMap
 
const Epetra_Map * origRowMap
 
virtual const Epetra_Map & RowMap() const =0
 
virtual int InsertGlobalValues(int GlobalRow, int NumEntries, double *Values, int *Indices)=0
 
virtual int SumIntoGlobalValues(int GlobalRow, int NumEntries, double *Values, int *Indices)=0
 
Epetra_BlockMap * RowMapEP_
 
std::vector< double > vals_
 
LightweightMap * RowMapLW_
 
std::vector< int > colind_
 
std::vector< int > rowptr_
 
long long IndexBase64() const
 
void MyGlobalElementsPtr(int *&MyGlobalElementList) const
 
int NumMyElements() const
 
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...
 
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.
 
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.
 
Transform to form the explicit transpose of a Epetra_RowMatrix.
 
bool SameAs(const Epetra_BlockMap &Map) const
 
bool GlobalIndicesInt() const
 
const Epetra_Comm & Comm() const
 
int NumMyElements() const
 
bool MyGID(int GID_in) const
 
bool GlobalIndicesLongLong() const
 
virtual int MaxAll(double *PartialMaxs, double *GlobalMaxs, int Count) const=0
 
virtual int NumProc() const=0
 
virtual int MyPID() const=0
 
virtual Epetra_Distributor * CreateDistributor() const=0
 
int ExtractGlobalRowView(int GlobalRow, int &NumEntries, double *&Values, int *&Indices) const
 
virtual int SumIntoGlobalValues(int GlobalRow, int NumEntries, const double *Values, const int *Indices)
 
const Epetra_Map & RowMap() const
 
int ExtractMyRowView(int MyRow, int &NumEntries, double *&Values, int *&Indices) const
 
virtual int InsertGlobalValues(int GlobalRow, int NumEntries, const double *Values, const int *Indices)
 
int FillComplete(bool OptimizeDataStorage=true)
 
int PutScalar(double ScalarConstant)
 
int ExtractGlobalRowCopy(int GlobalRow, int Length, int &NumEntries, double *Values, int *Indices) const
 
int Scale(double ScalarConstant)
 
const Epetra_Comm & Comm() const
 
const Epetra_Map & RangeMap() const
 
int ExtractCrsDataPointers(int *&IndexOffset, int *&Indices, double *&Values_in) const
 
const Epetra_Map & ColMap() const
 
bool IndicesAreLocal() const
 
int MaxNumEntries() const
 
const Epetra_Map & DomainMap() const
 
const Epetra_Import * Importer() const
 
bool IndicesAreGlobal() const
 
const Epetra_Map & RowMatrixRowMap() const
 
const Epetra_BlockMap & Map() const
 
virtual int Do(char *export_objs, int obj_size, int &len_import_objs, char *&import_objs)=0
 
virtual int CreateFromSends(const int &NumExportIDs, const int *ExportPIDs, bool Deterministic, int &NumRemoteIDs)=0
 
long long GlobalLength64() const
 
static void EPETRA_LIB_DLL_EXPORT Sort(bool SortAscending, int NumKeys, T *Keys, int NumDoubleCompanions, double **DoubleCompanions, int NumIntCompanions, int **IntCompanions, int NumLongLongCompanions, long long **LongLongCompanions)
 
EpetraExt::BlockCrsMatrix: A class for constructing a distributed block matrix.
 
int mult_A_Btrans(CrsMatrixStruct &Aview, CrsMatrixStruct &Bview, CrsWrapper &C, bool keep_all_hard_zeros)
 
int import_and_extract_views(const Epetra_CrsMatrix &M, const Epetra_Map &targetMap, CrsMatrixStruct &Mview, const Epetra_Import *prototypeImporter=0)
 
double sparsedot(double *u, int_type *u_ind, int u_len, double *v, int_type *v_ind, int v_len)
Method for internal use... sparsedot forms a dot-product between two sparsely-populated 'vectors'.
 
int mult_Atrans_Btrans(CrsMatrixStruct &Aview, CrsMatrixStruct &Bview, CrsWrapper &C, bool keep_all_hard_zeros)
 
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)
 
int import_only(const Epetra_CrsMatrix &M, const Epetra_Map &targetMap, CrsMatrixStruct &Mview, const Epetra_Import *prototypeImporter)
 
Epetra_Map * find_rows_containing_cols(const Epetra_CrsMatrix &M, const Epetra_Map &column_map)
 
Epetra_Map * Tfind_rows_containing_cols(const Epetra_CrsMatrix &M, const Epetra_Map &column_map)
 
int mult_Atrans_B(CrsMatrixStruct &Aview, CrsMatrixStruct &Bview, CrsWrapper &C)
 
int form_map_union(const Epetra_Map *map1, const Epetra_Map *map2, const Epetra_Map *&mapunion)