const std::vector<boost::shared_ptr<ribi::foam::Boundary> > ribi::foam::Mesh::CreateBoundaries(
  const Files& files,
  const std::vector<boost::shared_ptr<Face>>& all_faces
  )
{
  assert(files.GetFaces()->GetMaxFaceIndex().Get() == static_cast<int>(all_faces.size()));

  std::vector<boost::shared_ptr<ribi::foam::Boundary>> boundaries;

  const BoundaryIndex n_boundaries = files.GetBoundary()->GetMaxBoundaryIndex();
  for (BoundaryIndex i = BoundaryIndex(0); i!=n_boundaries; ++i)
  {
    const BoundaryFileItem& item { files.GetBoundary()->GetItem(i) };
    const std::string name = item.GetName();
    const auto type = item.GetType();

    std::vector<boost::shared_ptr<Face> > faces;
    const FaceIndex end_face { item.GetEndFace() } ;
    for (FaceIndex face_index = item.GetStartFace(); face_index!=end_face; ++face_index)
    {
      const int fi = face_index.Get();
      assert(fi >= 0);
      assert(fi < static_cast<int>(all_faces.size()));
      faces.push_back(all_faces[fi]);
    }

    //Face belongs to Boundary
    const boost::shared_ptr<Boundary> boundary {
      new Boundary(
        faces,
        name,
        type
      )
    };
    boundaries.push_back(boundary);
  }
  return boundaries;
}
ribi::foam::Mesh::Mesh(
  const std::vector<boost::shared_ptr<Boundary>>& boundaries,
  const std::vector<boost::shared_ptr<Cell>>& cells,
  const std::vector<boost::shared_ptr<Face>>& faces,
  const std::vector<boost::shared_ptr<ribi::Coordinat3D>>& points
  )
  : m_boundaries(boundaries),
    m_cells(cells),
    m_faces(faces),
    m_points(points)
{
  #ifndef NDEBUG
  Test();
  for (const boost::shared_ptr<Face> face: m_faces)
  {
    assert(face);
    assert(face->GetOwner());
    assert( (face->GetNeighbour() || !face->GetNeighbour() )
      && "internalMesh faces have a neighbour, defaultWall faces don't"
    );
  }
  #endif

  if (!AreFacesOrdered())
  {
    std::cout << "Reordering faces" << std::endl;
    ReorderFaces();
  }

  #ifndef NDEBUG
  assert(AreFacesOrdered());
  const Files f(this->CreateFiles());
  assert(f.GetFaces()->GetItems().size() == faces.size());
  assert(f.GetBoundary()->GetItems().size() == boundaries.size());
  assert(f.GetPoints()->GetItems().size() == points.size());
  #endif

}
ribi::foam::Mesh::Mesh(
  const Files& files,
  const std::vector<boost::shared_ptr<ribi::Coordinat3D>>& points
  )
  : m_boundaries{},
    m_cells{CreateEmptyCells(files)},
    m_faces{CreateFacesWithPoints(files,points)},
    m_points(points)
{
  #ifndef NDEBUG
  Test();
  #endif
  //Add Cell owner to Faces
  {
    assert(!m_cells.empty());
    const FaceIndex n_faces = files.GetFaces()->GetMaxFaceIndex();
    for (FaceIndex i = FaceIndex(0); i!=n_faces; ++i)
    {
      const CellIndex owner_cell_index { files.GetOwner()->GetItem(i).GetCellIndex() };
      #ifndef NDEBUG
      if (owner_cell_index.Get() >= static_cast<int>(m_cells.size()))
      {
        TRACE("ERROR");
        TRACE(owner_cell_index);
        TRACE(m_cells.size());
      }
      #endif
      assert(owner_cell_index.Get() >= 0);
      assert(owner_cell_index.Get() < static_cast<int>(m_cells.size()));
      assert(m_cells[ owner_cell_index.Get() ]);
      const boost::shared_ptr<Cell> owner { m_cells[ owner_cell_index.Get() ] };
      assert(owner);
      assert(!m_faces[i.Get()]->GetOwner() );
      m_faces[i.Get()]->AssignOwner(owner);
      assert( m_faces[i.Get()]->GetOwner() );
    }
  }
  #ifndef NDEBUG
  for (const boost::shared_ptr<Face> face: m_faces) { assert(face); assert(face->GetOwner()); }
  #endif

  //Add owned Faces to Cells
  {
    std::map<boost::shared_ptr<Cell>,std::vector<boost::shared_ptr<Face>>> m;
    for (const boost::shared_ptr<Face> face: m_faces)
    {
      assert(face);
      const boost::shared_ptr<Cell> owner { face->GetOwner() };
      assert(owner);
      //if (!owner) continue;
      if (m.find(owner) == m.end()) { m.insert(std::make_pair(owner, std::vector<boost::shared_ptr<Face>>() ) ); }
      assert(m.find(owner) != m.end());
      (*m.find(owner)).second.push_back(face);
    }
    for (auto p: m)
    {
      p.first->AssignOwnedFaces(p.second);
    }
  }
  //Add neighbours to Faces
  {
    const int n_faces = static_cast<int>(m_faces.size());
    for (int i=0; i!=n_faces; ++i)
    {
      const FaceIndex index(i);
      assert(files.GetNeighbour());
      //Not all Faces have a neighbour
      if (!files.GetNeighbour()->CanGetItem(index)) continue;
      assert(files.GetNeighbour()->CanGetItem(index));
      const CellIndex neighbour_index {
        files.GetNeighbour()->GetItem(index).GetCellIndex()
      };
      assert(i >= 0);
      assert(i < static_cast<int>(m_faces.size()));
      assert(neighbour_index.Get() < static_cast<int>(m_cells.size()));
      assert(!m_faces[i]->GetNeighbour());
      m_faces[i]->AssignNeighbour( m_cells[ neighbour_index.Get() ] );
      assert(m_faces[i]->GetNeighbour());
    }
  }

  //Assign boundaries
  m_boundaries = CreateBoundaries(files,m_faces);

  //Check
  #ifndef NDEBUG
  for (boost::shared_ptr<Cell> cell: m_cells)
  {
    assert(cell);
    //assert( (cell->GetNeighbour() || !cell->GetNeighbour())
    //  && "Not all cells have a neighbour, for example in a 1x1x1 mesh");
  }

  if (GetNumberOfBoundaries() != files.GetBoundary()->GetMaxBoundaryIndex().Get())
  {
    TRACE("ERROR");
    TRACE(GetNumberOfBoundaries());
    TRACE(files.GetBoundary()->GetMaxBoundaryIndex());
  }
  #endif
  assert(GetNumberOfBoundaries() == files.GetBoundary()->GetMaxBoundaryIndex().Get());

  assert(GetNumberOfFaces() == files.GetFaces()->GetMaxFaceIndex().Get());
}