void
  MatrixAdapter<Matrix>::do_getCcs(const Teuchos::ArrayView<scalar_t> nzval,
				   const Teuchos::ArrayView<global_ordinal_t> rowind,
				   const Teuchos::ArrayView<typename MatrixAdapter<Matrix>::global_size_t> colptr,
				   typename MatrixAdapter<Matrix>::global_size_t& nnz,
				   const Teuchos::Ptr<const Tpetra::Map<local_ordinal_t,global_ordinal_t,node_t> > colmap,
		       EDistribution distribution,
				   EStorage_Ordering ordering,
				   col_access ca) const
  {
    using Teuchos::RCP;
    using Teuchos::ArrayView;
    using Teuchos::OrdinalTraits;
    
    RCP<const type> get_mat;
    if( *colmap == *this->col_map_ ){
      // No need to redistribute
      get_mat = rcp(this,false); // non-owning
    } else {
      get_mat = get(colmap, distribution);
    }

    // If all is well and good, then colmap == cmap
    RCP<const Tpetra::Map<scalar_t,local_ordinal_t,global_ordinal_t> > cmap = get_mat->getColMap();
    TEUCHOS_ASSERT( *colmap == *cmap );

    ArrayView<global_ordinal_t> node_elements = cmap->getNodeElementList();
    if( node_elements.size() == 0 ) return; // no more contribution
    
    typename ArrayView<global_ordinal_t>::iterator col_it, col_end;
    col_end = node_elements.end();

    size_t colptr_ind = OrdinalTraits<size_t>::zero();
    global_ordinal_t colInd = OrdinalTraits<global_ordinal_t>::zero();
    for( col_it = node_elements.begin(); col_it != col_end; ++col_it ){
      colptr[colptr_ind++] = colInd;
      size_t colNNZ = getGlobalColNNZ(*col_it);
      size_t nnzRet = 0;
      ArrayView<global_ordinal_t> rowind_view = rowind.view(colInd,colNNZ);
      ArrayView<scalar_t> nzval_view = nzval.view(colInd,colNNZ);
      getGlobalColCopy(*col_it, rowind_view, nzval_view, nnzRet);
      
      // It was suggested that instead of sorting each row's indices
      // individually, that we instead do a double-transpose at the
      // end, which would also lead to the indices being sorted.
      if( ordering == SORTED_INDICES ){
        Tpetra::sort2(rowind_view.begin(), rowind_view.end(), nzval_view.begin());
      }
      
      TEUCHOS_TEST_FOR_EXCEPTION( colNNZ != nnzRet,
			  std::runtime_error,
			  "Number of values returned different from "
                          "number of values reported");
      colInd += colNNZ;
    }
    colptr[colptr_ind] = nnz = colInd;
  }
  void
  MatrixAdapter<Matrix>::do_getCrs(const Teuchos::ArrayView<scalar_t> nzval,
				   const Teuchos::ArrayView<global_ordinal_t> colind,
				   const Teuchos::ArrayView<typename MatrixAdapter<Matrix>::global_size_t> rowptr,
				   typename MatrixAdapter<Matrix>::global_size_t& nnz,
				   const Teuchos::Ptr<const Tpetra::Map<local_ordinal_t,global_ordinal_t,node_t> > rowmap,
		       EDistribution distribution,
				   EStorage_Ordering ordering,
				   row_access ra) const
  {
    using Teuchos::rcp;
    using Teuchos::RCP;
    using Teuchos::ArrayView;
    using Teuchos::OrdinalTraits;
    
 
    ((void) ra);

    RCP<const type> get_mat;
    if( *rowmap == *this->row_map_ ){
      // No need to redistribute
      get_mat = rcp(this,false); // non-owning
    } else {
      get_mat = get(rowmap, distribution);
    }
    // RCP<const type> get_mat = get(rowmap);

    // rmap may not necessarily check same as rowmap because rmap may
    // have been constructued with Tpetra's "expert" constructor,
    // which assumes that the map points are non-contiguous.
    //
    // TODO: There may be some more checking between the row map
    // compatibility, but things are working fine now.

    RCP<const Tpetra::Map<local_ordinal_t,global_ordinal_t,node_t> > rmap = get_mat->getRowMap();
    ArrayView<const global_ordinal_t> node_elements = rmap->getNodeElementList();
    if( node_elements.size() == 0 ) return; // no more contribution

    typename ArrayView<const global_ordinal_t>::iterator row_it, row_end;
    row_end = node_elements.end();

    size_t rowptr_ind = OrdinalTraits<size_t>::zero();
    global_ordinal_t rowInd = OrdinalTraits<global_ordinal_t>::zero();
    for( row_it = node_elements.begin(); row_it != row_end; ++row_it ){
      rowptr[rowptr_ind++] = rowInd;
      size_t rowNNZ = get_mat->getGlobalRowNNZ(*row_it);
      size_t nnzRet = OrdinalTraits<size_t>::zero();
      ArrayView<global_ordinal_t> colind_view = colind.view(rowInd,rowNNZ); 
      ArrayView<scalar_t> nzval_view = nzval.view(rowInd,rowNNZ);

      get_mat->getGlobalRowCopy(*row_it, colind_view, nzval_view, nnzRet);
      for (size_t rr = 0; rr < nnzRet ; rr++)
      {
          colind_view[rr] = colind_view[rr] - rmap->getIndexBase();
      }

      // It was suggested that instead of sorting each row's indices
      // individually, that we instead do a double-transpose at the
      // end, which would also lead to the indices being sorted.
      if( ordering == SORTED_INDICES ){
        Tpetra::sort2(colind_view.begin(), colind_view.end(), nzval_view.begin());
      }
      
      TEUCHOS_TEST_FOR_EXCEPTION( rowNNZ != nnzRet,
			  std::runtime_error,
			  "Number of values returned different from "
                          "number of values reported");
      rowInd += rowNNZ;
    }
    rowptr[rowptr_ind] = nnz = rowInd;
  }