bool MeshTransformationFunction::mapRefCellPointsUsingExactGeometry(FieldContainer<double> &cellPoints, const FieldContainer<double> &refCellPoints, GlobalIndexType cellID)
{
  // returns true if the MeshTransformationFunction handles this cell, false otherwise
  // if true, then populates cellPoints
  if (_cellTransforms.find(cellID) == _cellTransforms.end())
  {
    return false;
  }
//  cout << "refCellPoints in mapRefCellPointsUsingExactGeometry():\n" << refCellPoints;
//
//  cout << "cellPoints prior to mapRefCellPointsUsingExactGeometry():\n" << cellPoints;

  int numPoints = refCellPoints.dimension(0);
  int spaceDim = refCellPoints.dimension(1);

  CellTopoPtr cellTopo = _mesh->getElementType(cellID)->cellTopoPtr;
  bool spaceTime = false;
  CellTopoPtr spaceTimeTopo;
  FieldContainer<double> refCellPointsSpaceTime, refCellPointsSpace;
  double time0, time1;
  if (cellTopo->getTensorialDegree() > 0)
  {
    spaceDim = spaceDim - 1;
    spaceTime = true;
    spaceTimeTopo = cellTopo;
    cellTopo = CellTopology::cellTopology(cellTopo->getShardsTopology(), cellTopo->getTensorialDegree() - 1);
    refCellPointsSpaceTime = refCellPoints;
    // copy out the spatial points:
    refCellPointsSpace.resize(numPoints, spaceDim);
    for (int ptOrdinal=0; ptOrdinal<numPoints; ptOrdinal++)
    {
      for (int d=0; d<spaceDim; d++)
      {
        refCellPointsSpace(ptOrdinal,d) = refCellPointsSpaceTime(ptOrdinal,d);
      }
    }
    // determine the temporal bounds:
    unsigned sideOrdinal_t0 = spaceTimeTopo->getTemporalSideOrdinal(0);
    unsigned sideOrdinal_t1 = spaceTimeTopo->getTemporalSideOrdinal(1);
    unsigned sampleVertexOrdinal_t0 = spaceTimeTopo->getNodeMap(spaceDim, sideOrdinal_t0, 0);
    unsigned sampleVertexOrdinal_t1 = spaceTimeTopo->getNodeMap(spaceDim, sideOrdinal_t1, 0);
    CellPtr cell = _mesh->getTopology()->getCell(cellID);
    IndexType sampleVertexIndex_t0 = cell->vertices()[sampleVertexOrdinal_t0];
    IndexType sampleVertexIndex_t1 = cell->vertices()[sampleVertexOrdinal_t1];
    time0 = _mesh->getTopology()->getVertex(sampleVertexIndex_t0)[spaceDim];
    time1 = _mesh->getTopology()->getVertex(sampleVertexIndex_t1)[spaceDim];
  }
  else
  {
    refCellPointsSpace = refCellPoints;  // would be possible to avoid this copy by e.g. using a pointer in the call to mapToPhysicalFrame() below
  }
  if (cellTopo->getKey().first == shards::Quadrilateral<4>::key)
  {
    TEUCHOS_TEST_FOR_EXCEPTION(spaceDim != 2, std::invalid_argument, "points must be in 2D for the quad!");
    FieldContainer<double> parametricPoints(numPoints,spaceDim); // map to (t1,t2) space
    int whichCell = 0;
    CamelliaCellTools::mapToPhysicalFrame(parametricPoints,refCellPointsSpace,
                                          ParametricSurface::parametricQuadNodes(),
                                          cellTopo,whichCell);

//    cout << "parametricPoints in mapRefCellPointsUsingExactGeometry():\n" << parametricPoints;

    // for space-time, this is a bit fragile.  Would be better to do something manually in terms of the first temporal side...
    // (one could do this in Mesh or MeshTopology, and that would be OK)
    vector< ParametricCurvePtr > edgeFunctions = _mesh->parametricEdgesForCell(cellID);

    ParametricSurfacePtr interpolant = ParametricSurface::transfiniteInterpolant(edgeFunctions);

    for (int ptIndex=0; ptIndex<numPoints; ptIndex++)
    {
      double t1 = parametricPoints(ptIndex,0);
      double t2 = parametricPoints(ptIndex,1);

      double x,y;
      // transfinite interpolation:
      interpolant->value(t1, t2, x, y);

      cellPoints(ptIndex,0) = x;
      cellPoints(ptIndex,1) = y;
      if (spaceTime)
      {
        // per our assumptions on mesh transformations, we do a linear transform in time dimension
        double t_reference = refCellPoints(ptIndex,2); // goes from -1 to 1
        double t_physical = time0 + (t_reference + 1.0) * (time1-time0) / 2.0;
        cellPoints(ptIndex,2) = t_physical;
      }
    }
  }
  else
  {
    // TODO: work out what to do for triangles (or perhaps even a general polygon)
    TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "Unhandled cell type");
  }

//  cout << "cellPoints after to mapRefCellPointsUsingExactGeometry():\n" << cellPoints;

  return true;
}