void PiecewiseLinearDiscontinuousScalarSpaceBarycentric<BasisFunctionType>::dumpClusterIdsEx(
        const char* fileName,
        const std::vector<unsigned int>& clusterIdsOfDofs,
        DofType dofType) const
{
    // Note: this will probably only work for spaces on full grids
    // (not on segments)

    if (dofType != GLOBAL_DOFS && dofType != FLAT_LOCAL_DOFS)
        throw std::invalid_argument("PiecewiseLinearDiscontinuousScalarSpaceBarycentricScalarSpace::"
                                    "dumpClusterIds(): invalid DOF type");
    const size_t idCount = clusterIdsOfDofs.size();
    if ((dofType == GLOBAL_DOFS && idCount != globalDofCount()) ||
            (dofType == FLAT_LOCAL_DOFS && idCount != flatLocalDofCount()))
        throw std::invalid_argument("PiecewiseLinearDiscontinuousScalarSpaceBarycentricScalarSpace::"
                                    "dumpClusterIds(): incorrect dimension");

    std::auto_ptr<VtkWriter> vtkWriter = this->gridView().vtkWriter();
    if (dofType == GLOBAL_DOFS) {
        arma::Row<double> data(idCount);
        for (size_t i = 0; i < idCount; ++i)
            data(i) = clusterIdsOfDofs[i];
        vtkWriter->addVertexData(data, "ids");
        vtkWriter->write(fileName);
    } else {
        arma::Mat<double> data(idCount, globalDofCount());
        data.fill(0.);
        size_t row = 0;
        for (size_t id = 0; id < idCount; ++id) {
            bool exists = false;
            for (size_t fldof = 0; fldof < idCount; ++fldof) {
                if (clusterIdsOfDofs[fldof] == id) {
                    LocalDof ldof = m_flatLocal2localDofs[fldof];
                    GlobalDofIndex gdof = m_local2globalDofs[ldof.entityIndex][ldof.dofIndex];
                    data(row, gdof) = 1;
                    exists = true;
                }
            }
            if (!exists)
                data.shed_row(row); // very inefficient, of course
            else
                ++row;
        }
        std::cout << "about to write" <<std::endl;
        vtkWriter->addVertexData(data, "ids");
        vtkWriter->write(fileName);
    }
}
void PiecewiseLinearDiscontinuousScalarSpace<BasisFunctionType>::
dumpClusterIdsEx(const char *fileName,
                 const std::vector<unsigned int> &clusterIdsOfDofs,
                 DofType dofType) const {
    if (dofType != GLOBAL_DOFS && dofType != FLAT_LOCAL_DOFS)
        throw std::invalid_argument("PiecewiseLinearDiscontinuousScalarSpace::"
                                    "dumpClusterIds(): invalid DOF type");
    const size_t idCount = clusterIdsOfDofs.size();
    if ((dofType == GLOBAL_DOFS && idCount != globalDofCount()) ||
            (dofType == FLAT_LOCAL_DOFS && idCount != flatLocalDofCount()))
        throw std::invalid_argument("PiecewiseLinearDiscontinuousScalarSpace::"
                                    "dumpClusterIds(): incorrect dimension");

    std::unique_ptr<GridView> view = this->grid()->leafView();
    std::unique_ptr<VtkWriter> vtkWriter = view->vtkWriter();

    Matrix<double> data(idCount, globalDofCount());
    data.setZero();
    size_t row = 0;
    for (size_t id = 0; id < idCount; ++id) {
        bool exists = false;
        for (size_t fldof = 0; fldof < idCount; ++fldof) {
            if (clusterIdsOfDofs[fldof] == id) {
                LocalDof ldof = m_flatLocal2localDofs[fldof];
                GlobalDofIndex gdof =
                    m_local2globalDofs[ldof.entityIndex][ldof.dofIndex];
                data(row, gdof) = 1;
                exists = true;
            }
        }
        if (!exists)
            eigenRemoveRowFromMatrix(data, row); // very inefficient, of course
        else
            ++row;
    }
    std::cout << "about to write" << std::endl;
    vtkWriter->addVertexData(data, "ids");
    vtkWriter->write(fileName);
}
void PiecewiseLinearDiscontinuousScalarSpaceBarycentric<BasisFunctionType>::getGlobalDofNormals(
        std::vector<Point3D<CoordinateType> >& normals) const
{
    const int gridDim = this->domainDimension();
    const int globalDofCount_ = globalDofCount();
    const int worldDim = this->grid()->dimWorld();
    normals.resize(globalDofCount_);

    const IndexSet& indexSet = this->gridView().indexSet();
    int elementCount = this->gridView().entityCount(0);

    arma::Mat<CoordinateType> elementNormals(worldDim, elementCount);
    std::auto_ptr<EntityIterator<0> > it = this->gridView().template entityIterator<0>();
    arma::Col<CoordinateType> center(gridDim);
    center.fill(0.5);
    arma::Col<CoordinateType> normal;
    while (!it->finished()) {
        const Entity<0>& e = it->entity();
        int index = indexSet.entityIndex(e);
        e.geometry().getNormals(center, normal);

        for (int dim = 0; dim < worldDim; ++dim)
            elementNormals(dim, index) = normal(dim);
        it->next();
    }

    if (gridDim == 1)
        for (size_t g = 0; g < globalDofCount_; ++g) {
            normals[g].x = 0.;
            normals[g].y = 0.;
            for (size_t l = 0; l < m_global2localDofs[g].size(); ++l) {
                normals[g].x += elementNormals(0, m_global2localDofs[g][l].entityIndex);
                normals[g].y += elementNormals(1, m_global2localDofs[g][l].entityIndex);
            }
            normals[g].x /= m_global2localDofs[g].size();
            normals[g].y /= m_global2localDofs[g].size();
        }
    else // gridDim == 2
        for (size_t g = 0; g < globalDofCount_; ++g) {
            normals[g].x = 0.;
            normals[g].y = 0.;
            for (size_t l = 0; l < m_global2localDofs[g].size(); ++l) {
                normals[g].x += elementNormals(0, m_global2localDofs[g][l].entityIndex);
                normals[g].y += elementNormals(1, m_global2localDofs[g][l].entityIndex);
                normals[g].z += elementNormals(2, m_global2localDofs[g][l].entityIndex);
            }
            normals[g].x /= m_global2localDofs[g].size();
            normals[g].y /= m_global2localDofs[g].size();
            normals[g].z /= m_global2localDofs[g].size();
        }
}
void PiecewiseLinearDiscontinuousScalarSpaceBarycentric<BasisFunctionType>::
getFlatLocalDofBoundingBoxes(
       std::vector<BoundingBox<CoordinateType> >& bboxes) const
{
    // TODO: extract this loop into a private function
    const IndexSet& indexSet = this->gridView().indexSet();
    const int elementCount = this->gridView().entityCount(0);

    std::vector<arma::Mat<CoordinateType> > elementCorners(elementCount);
    std::auto_ptr<EntityIterator<0> > it = this->gridView().template entityIterator<0>();
    while (!it->finished()) {
        const Entity<0>& e = it->entity();
        int index = indexSet.entityIndex(e);
        const Geometry& geo = e.geometry();
        geo.getCorners(acc(elementCorners, index));
        it->next();
    }

    BoundingBox<CoordinateType> model;
    const CoordinateType maxCoord = std::numeric_limits<CoordinateType>::max();
    model.lbound.x = model.lbound.y = model.lbound.z = maxCoord;
    model.ubound.x = model.ubound.y = model.ubound.z = -maxCoord;

    const int flatLocalDofCount_ = m_flatLocal2localDofs.size();
    bboxes.resize(flatLocalDofCount_, model);
    for (int i = 0; i < flatLocalDofCount_; ++i) {
        const LocalDof& localDof = acc(m_flatLocal2localDofs, i);
        BoundingBox<CoordinateType>& bbox = acc(bboxes, i);
        extendBoundingBox(bbox, acc(elementCorners, localDof.entityIndex));
        setBoundingBoxReference<CoordinateType>(
                    bbox,
                    acc(elementCorners, localDof.entityIndex).col(
                        localDof.dofIndex));
    }

#ifndef NDEBUG
    const int globalDofCount_ = globalDofCount();
    for (size_t i = 0; i < globalDofCount_; ++i) {
        assert(bboxes[i].reference.x >= bboxes[i].lbound.x);
        assert(bboxes[i].reference.y >= bboxes[i].lbound.y);
        assert(bboxes[i].reference.z >= bboxes[i].lbound.z);
        assert(bboxes[i].reference.x <= bboxes[i].ubound.x);
        assert(bboxes[i].reference.y <= bboxes[i].ubound.y);
        assert(bboxes[i].reference.z <= bboxes[i].ubound.z);
    }
#endif // NDEBUG
}
void PiecewiseConstantDiscontinuousScalarSpaceBarycentric<
    BasisFunctionType>::dumpClusterIdsEx(const char *fileName,
                                         const std::vector<unsigned int> &
                                             clusterIdsOfGlobalDofs,
                                         DofType dofType) const {
  if (dofType != GLOBAL_DOFS && dofType != FLAT_LOCAL_DOFS)
    throw std::invalid_argument(
        "PiecewiseConstantDiscontinuousScalarSpaceBarycentric::"
        "dumpClusterIds(): invalid DOF type");
  const size_t idCount = clusterIdsOfGlobalDofs.size();
  if ((dofType == GLOBAL_DOFS && idCount != globalDofCount()) ||
      (dofType == FLAT_LOCAL_DOFS && idCount != flatLocalDofCount()))
    throw std::invalid_argument("PiecewiseConstantDiscontinuousScalarSpaceBaryc"
                                "entric::dumpClusterIds(): "
                                "clusterIds has incorrect length");

  std::unique_ptr<GridView> view = this->grid()->leafView();
  std::unique_ptr<VtkWriter> vtkWriter = view->vtkWriter();
  arma::Row<double> data(idCount);
  for (size_t i = 0; i < idCount; ++i)
    data(i) = clusterIdsOfGlobalDofs[i];
  vtkWriter->addCellData(data, "ids");
  vtkWriter->write(fileName);
}
size_t
PiecewiseLinearDiscontinuousScalarSpace<BasisFunctionType>::flatLocalDofCount()
const {
    return globalDofCount();
}