/*!
 * \brief Map a point to the reference space of an entity. Return the
 */
bool BoxImpl::mapToReferenceFrame( 
    const Teuchos::ArrayView<const double>& point,
    const Teuchos::ArrayView<double>& reference_point ) const
{
    reference_point.assign( point );
    return true;
}
//---------------------------------------------------------------------------//
// Return the centroid of the entity.
void STKMeshEntityLocalMap::centroid( 
    const Entity& entity, const Teuchos::ArrayView<double>& centroid ) const
{ 
    // Get the STK entity.
    const stk::mesh::Entity& stk_entity = STKMeshHelpers::extractEntity(entity);
    stk::mesh::EntityRank rank = d_bulk_data->entity_rank(stk_entity);

    // Extract the centroid of the element.
    if ( rank == stk::topology::ELEM_RANK )
    {
	shards::CellTopology entity_topo = 
	    stk::mesh::get_cell_topology(
		d_bulk_data->bucket(stk_entity).topology() );
	Intrepid::FieldContainer<double> entity_coords = 
	    STKMeshHelpers::getEntityNodeCoordinates(
		Teuchos::Array<stk::mesh::Entity>(1,stk_entity), *d_bulk_data );
	IntrepidCellLocalMap::centroid( 
	    entity_topo, entity_coords, centroid );
    }

    // Extract the centroid of the face.
    else if ( rank == stk::topology::FACE_RANK )
    {
	bool not_implemented = true;
	DTK_INSIST( !not_implemented );
    }

    // The centroid of a node is the node coordinates.
    else if ( rank == stk::topology::NODE_RANK )
    {
	Intrepid::FieldContainer<double> entity_coords = 
	    STKMeshHelpers::getEntityNodeCoordinates(
		Teuchos::Array<stk::mesh::Entity>(1,stk_entity), *d_bulk_data );
	centroid.assign( entity_coords.getData()() );
    }

    // Check for unsupported ranks.
    else
    {
	bool bad_rank = true;
	DTK_INSIST( !bad_rank );
    }
}
/*!
 * \brief Map a reference point to the physical space of an entity.
 */
void BoxImpl::mapToPhysicalFrame( 
    const Teuchos::ArrayView<const double>& reference_point,
    const Teuchos::ArrayView<double>& point ) const
{
    point.assign( reference_point );
}
/*
 * TODO: The following definition assumes that the matrix being adapted lends
 * itself to easier access in the row direction.  If this is not the case, and
 * mat_ is more easily access in column-major fashion, then it may make sense
 * to "swap" this definition to getCrs(), and define getCcs() (using getCrs)
 * instead.
 *
 * This definitions uses getCrs() to first get a CRS representation, then uses
 * an adaption of one of Knuth's algorithms to change it into a CCS format.
 */
void
MatrixAdapter<NewMatrix>::getCcs(
  const Teuchos::ArrayView<Scalar> nzval,
  const Teuchos::ArrayView<GlobalOrdinal> rowind,
  const Teuchos::ArrayView<global_size_type> colptr,
  size_t& nnz,
  bool local,
  int root)
{
  using Teuchos::Array;
  using Teuchos::ArrayView;

  Teuchos::RCP<const Teuchos::Comm<int> > comm = getComm();
  const int rank = comm->getRank();

  global_size_type numCols = 0;
  global_size_type numRows = 0;
  
  if ( local ){
    numCols = getLocalNumCols();
    numRows = getLocalNumRows();
  } else {
    numCols = getGlobalNumCols();
    numRows = getGlobalNumRows();
  }
  
  Array<scalar_type> nzval_tmp(nzval.size());
  Array<GlobalOrdinal> colind(nzval.size());
  Array<global_size_type> rowptr(numRows + 1);

  this->getCrs(nzval_tmp, colind, rowptr, nnz, local, root);
  /* We now have a compressed-row storage format of this matrix.  We transform
   * this into a compressed-column format using a distribution-counting sort
   * algorithm, which is described by D.E. Knuth in TAOCP Vol 3, 2nd ed pg 78.
   
   * Check the conditional execution here.  Also, we were having trouble with
   * Tpetra::CrsMatrix not reporting the correct global number of columns.
   */
  if( local || rank == root ){
    // Count the number of entries in each column
    Array<global_size_type> count(numCols + 1, 0);
    typename Array<GlobalOrdinal>::iterator ind_it;
    for( ind_it = colind.begin(); ind_it != colind.end(); ++ind_it ){
      ++(count[(*ind_it) + 1]);
    }

    // Accumulate
    typename Array<global_size_type>::iterator cnt_it;
    for( cnt_it = count.begin() + 1; cnt_it != count.end(); ++cnt_it ){
      *cnt_it = *cnt_it + *(cnt_it - 1);
    }
    // This becomes the array of column pointers
    colptr.assign(count);

    /* Move the nonzero values into their final place in nzval, based on the
     * counts found previously.
     *
     * This sequence deviates from Knuth's algorithm a bit, following more
     * closely the description presented in Gustavson, Fred G. "Two Fast
     * Algorithms for Sparse Matrices: Multiplication and Permuted
     * Transposition" ACM Trans. Math. Softw. volume 4, number 3, 1978, pages
     * 250--269, http://doi.acm.org/10.1145/355791.355796.
     *
     * The row indices end up in sorted order
     */

    for( global_size_type row = 0; row < numRows; ++row ){
      GlobalOrdinal u = rowptr[row];
      GlobalOrdinal v = rowptr[row + 1];
      for( GlobalOrdinal j = u; j < v; ++j ){
        GlobalOrdinal i = count[colind[j]];
        nzval[i] = nzval_tmp[j];
        rowind[i] = row;
        ++(count[colind[j]]);
      }
    }
  }
}
//---------------------------------------------------------------------------//
// Get the coordinates of the point.
void PointImpl::getCoordinates( 
    const Teuchos::ArrayView<double>& coordinates ) const
{ 
    coordinates.assign( d_coordinates );
}