Go back to Richel Bilderbeek's homepage.

Go back to Richel Bilderbeek's C++ page.

 

 

 

 

 

(C++) OpenFoam

 

Technical facts

 

 

 

 

 

 

./CppOpenFoam/CppOpenFoam.pri

 

INCLUDEPATH += \
    ../../Classes/CppOpenFoam

SOURCES += \
    ../../Classes/CppOpenFoam/openfoamfiles.cpp \
    ../../Classes/CppOpenFoam/openfoampointsfileitem.cpp \
    ../../Classes/CppOpenFoam/openfoampointsfile.cpp \
    ../../Classes/CppOpenFoam/openfoampointindex.cpp \
    ../../Classes/CppOpenFoam/openfoampoint.cpp \
    ../../Classes/CppOpenFoam/openfoamparseerror.cpp \
    ../../Classes/CppOpenFoam/openfoamhelper.cpp \
    ../../Classes/CppOpenFoam/openfoamownerfileitem.cpp \
    ../../Classes/CppOpenFoam/openfoamownerfile.cpp \
    ../../Classes/CppOpenFoam/openfoamneighbourfileitem.cpp \
    ../../Classes/CppOpenFoam/openfoamneighbourfile.cpp \
    ../../Classes/CppOpenFoam/openfoammesh.cpp \
    ../../Classes/CppOpenFoam/openfoamheader.cpp \
    ../../Classes/CppOpenFoam/openfoamfilenames.cpp \
    ../../Classes/CppOpenFoam/openfoamfacesfileitem.cpp \
    ../../Classes/CppOpenFoam/openfoamfacesfile.cpp \
    ../../Classes/CppOpenFoam/openfoamfaceindex.cpp \
    ../../Classes/CppOpenFoam/openfoamface.cpp \
    ../../Classes/CppOpenFoam/openfoamcellindex.cpp \
    ../../Classes/CppOpenFoam/openfoamcell.cpp \
    ../../Classes/CppOpenFoam/openfoamboundaryindex.cpp \
    ../../Classes/CppOpenFoam/openfoamboundaryfileitem.cpp \
    ../../Classes/CppOpenFoam/openfoamboundaryfile.cpp \
    ../../Classes/CppOpenFoam/openfoamboundary.cpp \
    ../../Classes/CppOpenFoam/openfoampatchfieldtypes.cpp \
    ../../Classes/CppOpenFoam/openfoampatchfieldtype.cpp \
    ../../Classes/CppOpenFoam/openfoamthermophysicalpropertiesfile.cpp \
    ../../Classes/CppOpenFoam/openfoampressurefile.cpp \
    ../../Classes/CppOpenFoam/openfoamalphatfile.cpp \
    ../../Classes/CppOpenFoam/openfoamcontroldictfile.cpp \
    ../../Classes/CppOpenFoam/openfoamturbulencepropertiesfile.cpp \
    ../../Classes/CppOpenFoam/openfoamdecomposepardictfile.cpp \
    ../../Classes/CppOpenFoam/openfoamepsilonfile.cpp \
    ../../Classes/CppOpenFoam/openfoamfvschemesfile.cpp \
    ../../Classes/CppOpenFoam/openfoamfvsolutionfile.cpp \
    ../../Classes/CppOpenFoam/openfoamkfile.cpp \
    ../../Classes/CppOpenFoam/openfoamvelocityfieldfile.cpp \
    ../../Classes/CppOpenFoam/openfoamraspropertiesfile.cpp \
    ../../Classes/CppOpenFoam/openfoamtemperaturefile.cpp

HEADERS  += \
    ../../Classes/CppOpenFoam/openfoamfiles.h \
    ../../Classes/CppOpenFoam/openfoampointsfileitem.h \
    ../../Classes/CppOpenFoam/openfoampointsfile.h \
    ../../Classes/CppOpenFoam/openfoampointindex.h \
    ../../Classes/CppOpenFoam/openfoampoint.h \
    ../../Classes/CppOpenFoam/openfoamparseerror.h \
    ../../Classes/CppOpenFoam/openfoamownerfileitem.h \
    ../../Classes/CppOpenFoam/openfoamownerfile.h \
    ../../Classes/CppOpenFoam/openfoamhelper.h \
    ../../Classes/CppOpenFoam/openfoamneighbourfileitem.h \
    ../../Classes/CppOpenFoam/openfoamneighbourfile.h \
    ../../Classes/CppOpenFoam/openfoammesh.h \
    ../../Classes/CppOpenFoam/openfoamheader.h \
    ../../Classes/CppOpenFoam/openfoamfwd.h \
    ../../Classes/CppOpenFoam/openfoamfilenames.h \
    ../../Classes/CppOpenFoam/openfoamfacesfileitem.h \
    ../../Classes/CppOpenFoam/openfoamfacesfile.h \
    ../../Classes/CppOpenFoam/openfoamfaceindex.h \
    ../../Classes/CppOpenFoam/openfoamface.h \
    ../../Classes/CppOpenFoam/openfoamcellindex.h \
    ../../Classes/CppOpenFoam/openfoamcell.h \
    ../../Classes/CppOpenFoam/openfoamboundaryindex.h \
    ../../Classes/CppOpenFoam/openfoamboundaryfileitem.h \
    ../../Classes/CppOpenFoam/openfoamboundaryfile.h \
    ../../Classes/CppOpenFoam/openfoamboundary.h \
    ../../Classes/CppOpenFoam/openfoampatchfieldtypes.h \
    ../../Classes/CppOpenFoam/openfoampatchfieldtype.h \
    ../../Classes/CppOpenFoam/openfoamthermophysicalpropertiesfile.h \
    ../../Classes/CppOpenFoam/openfoampressurefile.h \
    ../../Classes/CppOpenFoam/openfoamalphatfile.h \
    ../../Classes/CppOpenFoam/openfoamcontroldictfile.h \
    ../../Classes/CppOpenFoam/openfoamturbulencepropertiesfile.h \
    ../../Classes/CppOpenFoam/openfoamdecomposepardictfile.h \
    ../../Classes/CppOpenFoam/openfoamepsilonfile.h \
    ../../Classes/CppOpenFoam/openfoamfvschemesfile.h \
    ../../Classes/CppOpenFoam/openfoamfvsolutionfile.h \
    ../../Classes/CppOpenFoam/openfoamkfile.h \
    ../../Classes/CppOpenFoam/openfoamvelocityfieldfile.h \
    ../../Classes/CppOpenFoam/openfoamraspropertiesfile.h \
    ../../Classes/CppOpenFoam/openfoamtemperaturefile.h

OTHER_FILES += \
    ../../Classes/CppOpenFoam/Licence.txt

RESOURCES += \
    ../../Classes/CppOpenFoam/CppOpenFoam.qrc

 

 

 

 

 

./CppOpenFoam/openfoamalphatfile.h

 

#ifndef RIBI_OPENFOAMALPHATFILE_H
#define RIBI_OPENFOAMALPHATFILE_H

#include <array>
#include <iosfwd>
#include <vector>
#include "openfoamfwd.h"
#include "openfoamheader.h"

namespace ribi {
namespace foam {

///Reads and writes an OpenFOAM alphat file
struct AlphatFile
{
  explicit AlphatFile(
    const Header header = GetDefaultHeader()
  ) noexcept;

  static Header GetDefaultHeader() noexcept;
  const Header& GetHeader() const noexcept { return m_header; }

  void SetBoundaryField(const std::string& boundary_field) noexcept { m_boundary_field = boundary_field; }
  void SetDimensions(const std::array<int,7>& dimensions) noexcept { m_dimensions = dimensions; }
  void SetInternalField(const std::string& internal_field) noexcept { m_internal_field = internal_field; }

  private:

  std::string m_boundary_field;
  std::array<int,7> m_dimensions;

  ///The OpenFOAM header
  Header m_header;
  std::string m_internal_field;

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif

  friend std::ostream& operator<<(std::ostream& os, const AlphatFile& f) noexcept;
};

std::ostream& operator<<(std::ostream& os, const AlphatFile& f) noexcept;

} //~namespace foam
} //~namespace ribi

#endif // RIBI_OPENFOAMALPHATFILE_H

 

 

 

 

 

./CppOpenFoam/openfoamalphatfile.cpp

 

#include "openfoamalphatfile.h"

#include <cassert>
#include <fstream>
#include <iostream>
#include <stdexcept>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"

#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/lexical_cast.hpp>

#include <QFile>

#include "fileio.h"

#include "openfoamheader.h"
#include "testtimer.h"
#include "trace.h"
#pragma GCC diagnostic pop


ribi::foam::AlphatFile::AlphatFile(
  const Header header
) noexcept
  : m_boundary_field{},
    m_dimensions{ {} },
    m_header{header},
    m_internal_field{}
{
  #ifndef NDEBUG
  Test();
  #endif
}

ribi::foam::Header ribi::foam::AlphatFile::GetDefaultHeader() noexcept
{
  return Header("volScalarField","0","","alphat");
}

#ifndef NDEBUG
void ribi::foam::AlphatFile::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
}
#endif

std::ostream& ribi::foam::operator<<(std::ostream& os, const AlphatFile& f) noexcept
{
  os
    << f.GetHeader() << '\n'
    << "" << '\n'
    << "" << '\n'
    << "dimensions ["
      << f.m_dimensions[0] << " "
      << f.m_dimensions[1] << " "
      << f.m_dimensions[2] << " "
      << f.m_dimensions[3] << " "
      << f.m_dimensions[4] << " "
      << f.m_dimensions[5] << " "
      << f.m_dimensions[6]
      << "];" << '\n'
    << "" << '\n'
    << "internalField " << f.m_internal_field << ";\n"
    << "" << '\n'
    << "boundaryField" << '\n'
    << "{" << '\n'
    << f.m_boundary_field << '\n'
    << "}" << '\n'
  ;
  return os;
}

 

 

 

 

 

./CppOpenFoam/openfoamboundary.h

 

#ifndef RIBI_OPENFOAMBOUNDARY_H
#define RIBI_OPENFOAMBOUNDARY_H

#include <vector>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#include <boost/shared_ptr.hpp>
#include "openfoamfwd.h"
#include "openfoampatchfieldtype.h"
#pragma GCC diagnostic pop

namespace ribi {
namespace foam {

///A Boundary contains Faces that form a surface boundary
struct Boundary
{
  explicit Boundary(
    const std::vector<boost::shared_ptr<Face>>& faces,
    const std::string& name,
    const PatchFieldType type
  ) noexcept;

  const std::vector<boost::shared_ptr<      Face>>& GetFaces() noexcept { return m_faces; }
        std::vector<boost::shared_ptr<const Face>>  GetFaces() const noexcept;
  const std::string& GetName() const noexcept { return m_name; }
  PatchFieldType GetType() const noexcept { return m_type; }


  private:
  const std::vector<boost::shared_ptr<Face>> m_faces;
  const std::string m_name;
  const PatchFieldType m_type;

  friend std::ostream& operator<<(std::ostream& os, const Boundary& boundary) noexcept;
};

std::ostream& operator<<(std::ostream& os, const Boundary& boundary) noexcept;

} //namespace foam
} //namespace ribi

#endif // RIBI_OPENFOAMBOUNDARY_H

 

 

 

 

 

./CppOpenFoam/openfoamboundary.cpp

 

#include "openfoamboundary.h"

#include <cassert>
#include <ostream>

#include "trace.h"
#include "openfoamface.h"
#include "openfoampatchfieldtypes.h"

ribi::foam::Boundary::Boundary(
  const std::vector<boost::shared_ptr<Face>>& faces,
  const std::string& name,
  const PatchFieldType type
  ) noexcept
  : m_faces(faces),
    m_name(name),
    m_type(type)
{

}

std::vector<boost::shared_ptr<const ribi::foam::Face>> ribi::foam::Boundary::GetFaces() const noexcept
{
  std::vector<boost::shared_ptr<const ribi::foam::Face>> v;
  std::transform(
    m_faces.begin(),
    m_faces.end(),
    std::back_inserter(v),
    [](const boost::shared_ptr<Face> face)
    {
      assert(face);
      const boost::shared_ptr<const ribi::foam::Face> const_face {
        face
      };
      assert(face == const_face);
      return const_face;
    }
  );
  assert(v.size() == m_faces.size());
  //Only check first and last
  assert(v.empty() || v[0] == m_faces[0]);
  assert(v.empty() || v[ v.size() - 1 ] == m_faces[ v.size() - 1 ]);
  return v;
}

std::ostream& ribi::foam::operator<<(std::ostream& os, const ribi::foam::Boundary& boundary) noexcept
{
  os
    << boundary.m_name << '\n'
    << boundary.m_type << '\n';
  for (const boost::shared_ptr<Face> face: boundary.m_faces)
  {
    os << *face << '\n';
  }
  return os;
}

 

 

 

 

 

./CppOpenFoam/openfoamboundaryfile.h

 

#ifndef RIBI_OPENFOAMBOUNDARYFILE_H
#define RIBI_OPENFOAMBOUNDARYFILE_H

#include <iosfwd>
#include <string>
#include <vector>
#include "fileiofwd.h"
#include "openfoamfwd.h"
#include "openfoamheader.h"
#include "openfoamboundaryfileitem.h"

namespace ribi {
namespace foam {

///Reads and writes an OpenFOAM boundary file
struct BoundaryFile
{
  ///Read an OpenFOAM 'boundary' file.
  ///Throws std::runtime_error if file is incorrectly formed
  explicit BoundaryFile(const std::string& filename) : BoundaryFile(Parse(filename)) {}
  explicit BoundaryFile(
    const Header header = GetDefaultHeader(),
    const std::vector<BoundaryFileItem>& items = {});


  static Header GetDefaultHeader() noexcept;
  const Header& GetHeader() const noexcept { return m_header; }

  std::vector<BoundaryFileItem> GetItems() const noexcept { return m_items; }

  BoundaryFileItem GetItem(const BoundaryIndex& boundary_index) const noexcept;

  ///Obtain the number of boundaries, the size of m_items, or the first boundary index not available
  BoundaryIndex GetMaxBoundaryIndex() const noexcept;

  ///Is the Face belonging to a Boundary?
  ///(if not, it belongs to a Cell)
  bool IsBoundary(const FaceIndex& face_index) const noexcept { return CanGet(face_index); }

  ///Swap the face indices between
  //void Swap(const FaceIndex& lhs, const FaceIndex& rhs);

  private:
  ///Read an OpenFOAM 'boundary' file.
  ///Throws std::runtime_error if file is incorrectly formed
  explicit BoundaryFile(std::istream& is) : BoundaryFile(Parse(is)) {}

  ///The OpenFOAM header
  Header m_header;
  ///The items boundary contains
  std::vector<BoundaryFileItem> m_items;

  ///Is the FaceIndex present among the current items?
  bool CanGet(const FaceIndex& face_index) const noexcept;

  ///Find out which BoundaryFileItem the face belongs to
  ///Assumes CanGet(face_index) == true
  BoundaryFileItem& Find(const FaceIndex& face_index) noexcept;


  ///Read an OpenFOAM 'boundary' file.
  ///Throws std::runtime_error if file is incorrectly formed
  static BoundaryFile Parse(std::istream& is);

  static BoundaryFile Parse(const std::string& filename);

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif

  friend std::ostream& operator<<(std::ostream& os, const BoundaryFile& f) noexcept;
  friend std::istream& operator>>(std::istream& is, BoundaryFile& f);
};

bool operator==(const BoundaryFile& lhs,const BoundaryFile& rhs) noexcept;
bool operator!=(const BoundaryFile& lhs,const BoundaryFile& rhs) noexcept;
std::ostream& operator<<(std::ostream& os, const BoundaryFile& f) noexcept;

///Read an OpenFOAM 'boundary' file.
///Throws std::runtime_error if file is incorrectly formed
std::istream& operator>>(std::istream& is, BoundaryFile& f);

} //~namespace foam
} //~namespace ribi

#endif // RIBI_OPENFOAMBOUNDARYFILE_H

 

 

 

 

 

./CppOpenFoam/openfoamboundaryfile.cpp

 

#include "openfoamboundaryfile.h"

#include <cassert>
#include <fstream>
#include <iostream>
#include <stdexcept>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"

#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/lexical_cast.hpp>

#include <QFile>


#include "fileio.h"
#include "openfoamheader.h"
#include "openfoamboundaryindex.h"
#include "openfoamboundaryfileitem.h"
#include "testtimer.h"
#include "trace.h"
#pragma GCC diagnostic pop


ribi::foam::BoundaryFile::BoundaryFile(
  const Header header,
  const std::vector<BoundaryFileItem>& items)
  : m_header{header},
    m_items(items)
{
  #ifndef NDEBUG
  Test();
  #endif
}

bool ribi::foam::BoundaryFile::CanGet(const FaceIndex& face_index) const noexcept
{
  for (const BoundaryFileItem& item: m_items)
  {
    const int i = face_index.Get();
    const int min = item.GetStartFace().Get();
    const int max = min + item.GetNfaces();
    if (i >= min && i < max) return true;
  }
  return false;
}

ribi::foam::BoundaryFileItem& ribi::foam::BoundaryFile::Find(const FaceIndex& face_index) noexcept
{
  assert(CanGet(face_index));
  const int sz = static_cast<int>(m_items.size());
  for (int i=0; i!=sz; ++i)
  {
    const int j = face_index.Get();
    const int min = m_items[i].GetStartFace().Get();
    const int max = min + m_items[i].GetNfaces();
    if (j >= min && j < max) return m_items[i];
  }
  assert(!"Should not get here");
  throw std::logic_error("ribi::foam::BoundaryFile::Find");
}

ribi::foam::Header ribi::foam::BoundaryFile::GetDefaultHeader() noexcept
{
  const std::string class_name = "polyBoundaryMesh";
  const std::string location   = "constant" + fileio::FileIo().GetPathSeperator() + "polyMesh";
  const std::string note       = "";
  const std::string object     = "boundary";

  return Header(class_name,location,note,object);
}

ribi::foam::BoundaryFileItem ribi::foam::BoundaryFile::GetItem(const ribi::foam::BoundaryIndex& boundary_index) const noexcept
{
  assert(boundary_index.Get() >= 0);
  assert(boundary_index < GetMaxBoundaryIndex());
  return m_items[ boundary_index.Get() ];
}

ribi::foam::BoundaryIndex ribi::foam::BoundaryFile::GetMaxBoundaryIndex() const noexcept
{
  return BoundaryIndex(static_cast<int>(m_items.size()));
}

ribi::foam::BoundaryFile ribi::foam::BoundaryFile::Parse(std::istream& is)
{
  BoundaryFile b;
  is >> b;
  assert(is);
  return b;
}

ribi::foam::BoundaryFile ribi::foam::BoundaryFile::Parse(const std::string& filename)
{
  const std::string tmp_filename { fileio::FileIo().GetTempFileName() };
  fileio::FileIo().CopyFile(filename,tmp_filename);
  Header::CleanFile(tmp_filename);
  std::ifstream f(tmp_filename.c_str());
  const ribi::foam::BoundaryFile file { Parse(f) };
  f.close();
  fileio::FileIo().DeleteFile(tmp_filename);
  return file;
}

#ifndef NDEBUG
void ribi::foam::BoundaryFile::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  {
    BoundaryFileItem();
    FaceIndex(0);
    BoundaryIndex(0);
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);

  //Some initial data
  const Header header("some_name","some_location","some_object");
  std::vector<BoundaryFileItem> items;
  for (int i=1; i!=4; ++i)
  {
    const std::string name = "some_name" + boost::lexical_cast<std::string>(i);
    const PatchFieldType type = PatchFieldType::codedFixedValue;
    const int n_faces = i;
    const FaceIndex start_face(i * i);
    BoundaryFileItem item(name,type,n_faces,start_face);
    items.push_back(item);
  }
  //operator==
  {
    const BoundaryFile b(header,items);
    const BoundaryFile c(header,items);
    assert(header == header);
    assert(b == c);
  }
  //operator!=
  {
    const BoundaryFile b(header,items);
    const Header other_header("some_other_name","some_other_location","some_other_object");
    assert(header != other_header);
    const BoundaryFile c(other_header,items);
    assert(b != c);
  }
  //operator!=
  {
    const BoundaryFile b(header,items);
    std::vector<BoundaryFileItem> other_items;
    for (int i=1; i!=3; ++i)
    {
      const std::string name = "some_other_name" + boost::lexical_cast<std::string>(i);
      const PatchFieldType type = PatchFieldType::compressible_turbulentTemperatureCoupledBaffleMixed;
      const int n_faces = i + 123;
      const FaceIndex start_face((i * i) + 456);
      BoundaryFileItem item(name,type,n_faces,start_face);
      other_items.push_back(item);
    }
    const BoundaryFile c(header,other_items);
    assert(b != c);
  }
  //Stream conversion
  {
    const BoundaryFile b(header,items);
    std::stringstream s;
    s << b;
    BoundaryFile c;
    s >> c;
    if (b != c)
    {
      TRACE(b);
      TRACE(c);
    }
    assert(b == c);
  }
  //Read from testing file
  for (int test_index = 0; test_index!=5; ++test_index)
  {
    std::string filename_appendix;
    switch (test_index)
    {
      case 0: filename_appendix = "_1x1x1"; break;
      case 1: filename_appendix = "_1x1x2"; break;
      case 2: filename_appendix = "_1x2x2"; break;
      case 3: filename_appendix = "_2x2x2"; break;
      case 4: filename_appendix = "_3x4x5"; break;
      default: assert(!"Should never get here");
        throw std::logic_error("foam::Files::CreateTestFiles: unknown test index");
    }
    assert(!filename_appendix.empty());
    const std::string filename_base { GetDefaultHeader().GetObject() };
    const std::string filename = filename_base + filename_appendix;
    const std::string resources_path { ":/CppOpenFoam/files/" + filename };

    {
      QFile f( resources_path.c_str() );
      f.copy(filename.c_str());
    }
    {
      if (!fileio::FileIo().IsRegularFile(filename))
      {
        TRACE("ERROR");
        TRACE(filename);
      }
      assert(fileio::FileIo().IsRegularFile(filename));
      BoundaryFile b(filename);
      if (b.GetItems().empty())
      {
        TRACE("ERROR");
      }
      assert( (!b.GetItems().empty() || b.GetItems().empty())
        && "If a mesh has no non-boundary cells, neighbour can be empty");
    }
  }
}
#endif

bool ribi::foam::operator==(const BoundaryFile& lhs,const BoundaryFile& rhs) noexcept
{
  const bool verbose{false};
  if (lhs.GetHeader() != rhs.GetHeader())
  {
    if (verbose)
    {
      TRACE("Headers differ:");
      TRACE(lhs.GetHeader());
      TRACE(rhs.GetHeader());
    }
    return false;
  }
  const std::vector<BoundaryFileItem>& lhs_items = lhs.GetItems();
  const std::vector<BoundaryFileItem>& rhs_items = rhs.GetItems();
  if (lhs_items.size() != rhs_items.size())
  {
    if (verbose)
    {
      TRACE("Number of items differ:");
      TRACE(lhs_items.size());
      TRACE(rhs_items.size());
    }
    return false;
  }
  const bool all_items_equal {
    std::equal(lhs_items.begin(),lhs_items.end(),rhs_items.begin())
  };
  if (verbose && !all_items_equal)
  {
    TRACE("Items differ:");
    TRACE(all_items_equal);
  }
  return all_items_equal;
}

bool ribi::foam::operator!=(const BoundaryFile& lhs,const BoundaryFile& rhs) noexcept
{
  return !(lhs == rhs);
}

std::istream& ribi::foam::operator>>(std::istream& is, BoundaryFile& f)
{
  assert(f.m_items.empty()); //Make empty otherwise

  //Read header
  is >> f.m_header;
  assert(is);

  //Read items
  int n_items = 0;
  char opening_bracket = '\0';
  {
    //Eat comment
    char c = '\0';
    is >> c;
    assert(is);
    if (c >= '0' && c <= '9')
    {
      while (c != '(' && c != '{')
      {
        //Start eating n_items
        n_items *= 10;
        const int n = c - '0';
        assert(n >= 0 && n <= 9);
        n_items += n;
        is >> c;
        assert(is);
      }
    }
    opening_bracket = c;
    #ifndef NDEBUG
    if (!(opening_bracket == '(' || opening_bracket == '{'))
    {
      TRACE(opening_bracket);
      TRACE("ERROR");
    }
    #endif
    assert(opening_bracket == '(' || opening_bracket == '{');
  }
  assert(opening_bracket == '(' || opening_bracket == '{');
  if (opening_bracket == '(')
  {
    for (int i=0; i!=n_items; ++i)
    {
      BoundaryFileItem item;
      is >> item;
      assert(is);
      f.m_items.push_back(item);
    }
  }
  else
  {
    assert(opening_bracket == '{');
    //Read once, push n_items times
    BoundaryFileItem item;
    is >> item;
    assert(is);
    for (int i=0; i!=n_items; ++i)
    {
      f.m_items.push_back(item);
    }
  }
  //Eat comments until bracket close
  {
    char bracket_close = '\0';
    while (bracket_close != ')' && bracket_close != '}')
    {
      is >> bracket_close;
      assert(is);
    }
    assert(bracket_close == ')' || bracket_close == '}');
    assert(
         (opening_bracket == '(' && bracket_close == ')')
      || (opening_bracket == '{' && bracket_close == '}')
    );
  }
  return is;
}

std::ostream& ribi::foam::operator<<(std::ostream& os, const BoundaryFile& f) noexcept
{
  os
    << f.GetHeader() << '\n'
    << "" << '\n'
    << std::count_if(
      f.m_items.begin(),f.m_items.end(),
      [](const BoundaryFileItem& item)
      {
        return item.GetType() != PatchFieldType::no_patch_field;
      }
    ) << '\n'
    << "(" << '\n'
  ;

  for(const BoundaryFileItem item: f.m_items)
  {
    if (item.GetType() == PatchFieldType::no_patch_field) continue;
    os << item << '\n';
  }

  os
    << ")" << '\n'
  ;
  return os;
}

 

 

 

 

 

./CppOpenFoam/openfoamboundaryfileitem.h

 

#ifndef RIBI_OPENFOAMBOUNDARYFILEITEM_H
#define RIBI_OPENFOAMBOUNDARYFILEITEM_H

#include <string>
#include <iosfwd>

#include "openfoamfaceindex.h"
#include "openfoampatchfieldtype.h"

namespace ribi {
namespace foam {

///An item in an OpenFOAM boundary file
struct BoundaryFileItem
{
  explicit BoundaryFileItem(
    const std::string& name = "",
    const PatchFieldType patch_field_type = PatchFieldType::empty,
    const int n_faces = 0,
    const FaceIndex n_start_face = FaceIndex(0)
  );

  const std::string& GetName() const noexcept { return m_name; }
  int GetNfaces() const noexcept { return m_n_faces; }

  ///Obtain the first Face its index
  FaceIndex GetStartFace() const noexcept { return m_start_face; }

  ///Obtain the last+1 Face index
  FaceIndex GetEndFace() const noexcept;

  PatchFieldType GetType() const noexcept { return m_type; }

  private:

  int m_n_faces;
  std::string m_name;
  FaceIndex m_start_face;
  PatchFieldType m_type;

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif

  friend class OpenFoamBoundaryFile;
  friend std::istream& operator>>(std::istream& is, BoundaryFileItem& f);
};

bool operator==(const BoundaryFileItem& lhs, const BoundaryFileItem& rhs) noexcept;
bool operator!=(const BoundaryFileItem& lhs, const BoundaryFileItem& rhs) noexcept;
std::ostream& operator<<(std::ostream& os, const BoundaryFileItem& f) noexcept;
std::istream& operator>>(std::istream& is, BoundaryFileItem& f);

} //~namespace foam
} //~namespace ribi


#endif // RIBI_OPENFOAMBOUNDARYFILEITEM_H

 

 

 

 

 

./CppOpenFoam/openfoamboundaryfileitem.cpp

 

#include "openfoamboundaryfileitem.h"

#include <cassert>
#include <iostream>

#include "openfoampatchfieldtypes.h"
#include "testtimer.h"
#include "trace.h"

ribi::foam::BoundaryFileItem::BoundaryFileItem(
  const std::string& name,
  const PatchFieldType patch_field_type,
  const int n_faces,
  const FaceIndex n_start_face
  )
  :
    m_n_faces{n_faces},
    m_name{name},
    m_start_face{n_start_face},
    m_type{patch_field_type}
{
  #ifndef NDEBUG
  Test();
  #endif
  assert(m_n_faces >= 0);
  assert(m_start_face.Get() >= 0);
}

ribi::foam::FaceIndex ribi::foam::BoundaryFileItem::GetEndFace() const noexcept
{
  return m_start_face + FaceIndex(m_n_faces);
}

#ifndef NDEBUG
void ribi::foam::BoundaryFileItem::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
  const BoundaryFileItem i("some_name",PatchFieldType::empty,123,FaceIndex(456));
  std::stringstream s;
  s << i;
  BoundaryFileItem j;
  s >> j;
  if (i != j)
  {
    TRACE(i);
    TRACE(j);
  }
  assert(i == j);
}
#endif

bool ribi::foam::operator==(const BoundaryFileItem& lhs, const BoundaryFileItem& rhs) noexcept
{
  return
       lhs.GetName() == rhs.GetName()
    && lhs.GetNfaces() == rhs.GetNfaces()
    && lhs.GetStartFace() == rhs.GetStartFace()
    && lhs.GetType() == rhs.GetType()
  ;
}

bool ribi::foam::operator!=(const BoundaryFileItem& lhs, const BoundaryFileItem& rhs) noexcept
{
  return !(lhs == rhs);
}

std::ostream& ribi::foam::operator<<(std::ostream& os, const BoundaryFileItem& item) noexcept
{
  os
    << "    " << item.GetName() << '\n'
    << "    {" << '\n'
    << "        type " << item.GetType() << ";\n"
    << "        nFaces " << item.GetNfaces() << ";\n"
    << "        startFace " << item.GetStartFace() << ";\n"
    << "    }" << '\n';
  return os;
}

std::istream& ribi::foam::operator>>(std::istream& is, BoundaryFileItem& f)
{
  {
    is >> f.m_name;
    assert(is);
  }
  {
    std::string bracket_open;
    is >> bracket_open;
    assert(is);
    assert(bracket_open == "{");
  }
  {
    std::string type_text;
    is >> type_text;
    assert(is);
    assert(type_text == "type");
  }
  {
    std::string type_str;
    is >> type_str;
    assert(is);
    assert(type_str.back() == ';');
    type_str.pop_back();
    assert(type_str.back() != ';');
    f.m_type = PatchFieldTypes::ToType(type_str);
  }
  {
    std::string n_faces_text;
    is >> n_faces_text;
    assert(is);
    assert(n_faces_text == "nFaces");
  }
  {
    is >> f.m_n_faces;
  }
  {
    std::string semicolon;
    is >> semicolon;
    assert(is);
    #ifndef NDEBUG
    if (semicolon != ";")
    {
      TRACE(semicolon);
    }
    #endif
    assert(semicolon == ";");
  }
  {
    std::string start_face_text;
    is >> start_face_text;
    assert(is);
    #ifndef NDEBUG
    if (start_face_text != "startFace")
    {
      TRACE(start_face_text);
    }
    #endif
    assert(start_face_text == "startFace");
  }
  {
    is >> f.m_start_face;
    assert(is);
  }
  {
    std::string semicolon;
    is >> semicolon;
    assert(is);
    assert(semicolon == ";");
  }
  {
    std::string bracket_close;
    is >> bracket_close;
    assert(is);
    assert(bracket_close == "}");
  }
  return is;
}

 

 

 

 

 

./CppOpenFoam/openfoamboundaryindex.h

 

#ifndef RIBI_OPENFOAMBOUNDARYINDEX_H
#define RIBI_OPENFOAMBOUNDARYINDEX_H

#include <iosfwd>

namespace ribi {
namespace foam {

struct BoundaryIndex
{
  ///Throws std::invalid_argument if the index is invalid
  explicit BoundaryIndex(const int index);
  int Get() const noexcept { return m_index; }

  ///Throws std::invalid_argument if the new index is invalid
  BoundaryIndex& operator-=(const BoundaryIndex& rhs);
  BoundaryIndex& operator++() noexcept;   //Prefix
  BoundaryIndex operator++(int) noexcept; //Postfix
  private:
  int m_index;
  friend std::istream& operator>>(std::istream& is, BoundaryIndex& face_index) noexcept;
};

std::ostream& operator<<(std::ostream& os, const BoundaryIndex& face_index) noexcept;
std::istream& operator>>(std::istream& is, BoundaryIndex& face_index) noexcept;

const BoundaryIndex operator+(const BoundaryIndex& lhs, const BoundaryIndex& rhs) noexcept;
const BoundaryIndex operator-(const BoundaryIndex& lhs, const BoundaryIndex& rhs);

bool operator==(const BoundaryIndex& lhs, const BoundaryIndex& rhs) noexcept;
bool operator!=(const BoundaryIndex& lhs, const BoundaryIndex& rhs) noexcept;
bool operator<(const BoundaryIndex& lhs, const BoundaryIndex& rhs) noexcept;
bool operator>(const BoundaryIndex& lhs, const BoundaryIndex& rhs) noexcept;
bool operator>=(const BoundaryIndex& lhs, const BoundaryIndex& rhs) noexcept;
bool operator<=(const BoundaryIndex& lhs, const BoundaryIndex& rhs) noexcept;

} //~namespace foam
} //~namespace ribi

#endif // RIBI_OPENFOAMBOUNDARYINDEX_H

 

 

 

 

 

./CppOpenFoam/openfoamboundaryindex.cpp

 

#include "openfoamboundaryindex.h"

#include <cassert>
#include <iostream>
#include <stdexcept>

#include "trace.h"

ribi::foam::BoundaryIndex::BoundaryIndex(const int index)
  : m_index(index)
{
  #ifndef NDEBUG
  if (m_index < 0)
  {
    TRACE("ERROR");
    TRACE(m_index);
  }
  #endif
  assert(m_index >= 0
    && "A BoundaryIndex must be zero or a positive value");
  if (m_index < 0)
  {
    throw std::invalid_argument("A BoundaryIndex must be zero or a positive value");
  }
}

ribi::foam::BoundaryIndex& ribi::foam::BoundaryIndex::operator-=(const BoundaryIndex& rhs)
{
  m_index -= rhs.Get();

  assert(m_index >= 0
    && "A BoundaryIndex must be zero or a positive value");
  if (m_index < 0)
  {
    throw std::invalid_argument(
      "BoundaryIndex::operator-=: BoundaryIndex cannot be negative");
  }
  return *this;
}

ribi::foam::BoundaryIndex& ribi::foam::BoundaryIndex::operator++() noexcept
{
  ++m_index;
  return *this;
}

ribi::foam::BoundaryIndex ribi::foam::BoundaryIndex::operator++(int) noexcept
{
  BoundaryIndex old(*this);
  ++(*this);
  return old;
}

std::ostream& ribi::foam::operator<<(std::ostream& os, const BoundaryIndex& face_index) noexcept
{
  os << face_index.Get();
  return os;
}

std::istream& ribi::foam::operator>>(std::istream& is, BoundaryIndex& face_index) noexcept
{
  is >> face_index.m_index;
  assert(is);
  return is;
}

const ribi::foam::BoundaryIndex ribi::foam::operator+(const BoundaryIndex& lhs, const BoundaryIndex& rhs) noexcept
{
  return BoundaryIndex(lhs.Get() + rhs.Get());
}

const ribi::foam::BoundaryIndex ribi::foam::operator-(const BoundaryIndex& lhs, const BoundaryIndex& rhs)
{
  return BoundaryIndex(lhs.Get() - rhs.Get());
}

bool ribi::foam::operator==(const BoundaryIndex& lhs, const BoundaryIndex& rhs) noexcept
{
  return lhs.Get() == rhs.Get();
}

bool ribi::foam::operator!=(const BoundaryIndex& lhs, const BoundaryIndex& rhs) noexcept
{
  return !(lhs == rhs);
}

bool ribi::foam::operator<(const BoundaryIndex& lhs, const BoundaryIndex& rhs) noexcept
{
  return lhs.Get() < rhs.Get();
}

bool ribi::foam::operator>(const BoundaryIndex& lhs, const BoundaryIndex& rhs) noexcept
{
  return lhs.Get() > rhs.Get();
}

bool ribi::foam::operator>=(const BoundaryIndex& lhs, const BoundaryIndex& rhs) noexcept
{
  return !(lhs < rhs);
}

bool ribi::foam::operator<=(const BoundaryIndex& lhs, const BoundaryIndex& rhs) noexcept
{
  return !(lhs > rhs);
}

 

 

 

 

 

./CppOpenFoam/openfoamcell.h

 

#ifndef RIBI_OPENFOAMCELL_H
#define RIBI_OPENFOAMCELL_H

#include <vector>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#include <boost/shared_ptr.hpp>
#include "openfoamfwd.h"
#pragma GCC diagnostic pop

namespace ribi {
namespace foam {

///A Cell contains Faces that enclose a volume
///These Faces are
///- owned/managed by this Cell: m_owned_faces
///- owned/managed by a neighbouring Cell: m_faces
///Faces know
///- the Cell that owns them
///- optionally, the Cell they are also a member of, called 'neighbour'.
///  If this is nullptr, the Face is a boundary face
///If a Cell contains a boundary Face, it is a boundary cell
struct Cell
{
  ///owned_faces is a subset of all_faces
  explicit Cell(
    const std::vector<boost::shared_ptr<Face>> owned_faces = {},
    const std::vector<boost::shared_ptr<Face>> all_faces = {}
  );

  ///Can only assign once
  void AssignOwnedFaces(const std::vector<boost::shared_ptr<Face>>& owned_faces);

  //const boost::shared_ptr<const Cell> GetNeighbour() const noexcept;
        std::vector<boost::shared_ptr<const Face>>  GetOwnedFaces() const noexcept;
  const std::vector<boost::shared_ptr<      Face>>& GetOwnedFaces()       noexcept { return m_owned_faces; }

  bool HasFace(const boost::shared_ptr<const Face> face) const noexcept;
  bool OwnsFace(const boost::shared_ptr<const Face> face) const noexcept;

  private:

  ///m_owned_faces is a subset of m_all_faces
  std::vector<boost::shared_ptr<Face>> m_all_faces;

  ///m_owned_faces is a subset of m_all_faces
  std::vector<boost::shared_ptr<Face>> m_owned_faces;

  friend std::ostream& operator<<(std::ostream& os, const Cell& cell) noexcept;
};

std::ostream& operator<<(std::ostream& os, const Cell& cell) noexcept;

//bool operator<(const boost::shared_ptr<const Cell>& lhs, const boost::shared_ptr<      Cell>& rhs) = delete;
//bool operator<(const boost::shared_ptr<const Cell>& lhs, const boost::shared_ptr<const Cell>& rhs) = delete;
//bool operator<(const boost::shared_ptr<      Cell>& lhs, const boost::shared_ptr<      Cell>& rhs) = delete;
//bool operator<(const boost::shared_ptr<      Cell>& lhs, const boost::shared_ptr<const Cell>& rhs) = delete;

} //namespace foam
} //namespace ribi

#endif // RIBI_OPENFOAMCELL_H

 

 

 

 

 

./CppOpenFoam/openfoamcell.cpp

 

#include "openfoamcell.h"

#include <cassert>
#include <ostream>

#include "openfoamface.h"
#include "trace.h"

ribi::foam::Cell::Cell(
  const std::vector<boost::shared_ptr<Face>> owned_faces,
  const std::vector<boost::shared_ptr<Face>> all_faces
  )
  : m_all_faces{all_faces},
    m_owned_faces{owned_faces}
{
  #ifndef NDEBUG
  for (const boost::shared_ptr<Face> face: m_owned_faces)
  {
    assert(face);
    assert(std::count(m_all_faces.begin(),m_all_faces.end(),face) == 1
      && "m_owned_faces must be a subset of m_all_faces");
  }
  #endif
}

void ribi::foam::Cell::AssignOwnedFaces(const std::vector<boost::shared_ptr<Face>>& owned_faces)
{
  assert(m_owned_faces.empty() && "owned faces can only be assigned once");
  assert(!owned_faces.empty());
  m_owned_faces = owned_faces;
}

std::vector<boost::shared_ptr<const ribi::foam::Face>> ribi::foam::Cell::GetOwnedFaces() const noexcept
{
  std::vector<boost::shared_ptr<const ribi::foam::Face>> v;
  std::transform(
    m_owned_faces.begin(),
    m_owned_faces.end(),
    std::back_inserter(v),
    [](const boost::shared_ptr<Face> face)
    {
      assert(face);
      const boost::shared_ptr<const ribi::foam::Face> const_face {
        face
      };
      assert(face == const_face);
      return const_face;
    }
  );
  assert(v.size() == m_owned_faces.size());
  //Only check first and last
  assert(v.empty() || v[0] == m_owned_faces[0]);
  assert(v.empty() || v[ v.size() - 1 ] == m_owned_faces[ v.size() - 1 ]);
  return v;
}

bool ribi::foam::Cell::HasFace(const boost::shared_ptr<const ribi::foam::Face> face) const noexcept
{
  #ifndef NDEBUG
  assert(m_all_faces.size() >= m_owned_faces.size()
    && "m_owned_faces must be a subset of m_all_faces: there should be more m_all_faces"
  );
  for (const boost::shared_ptr<Face> face: m_owned_faces)
  {
    assert(face);
    assert(std::count(m_all_faces.begin(),m_all_faces.end(),face) == 1
      && "m_owned_faces must be a subset of m_all_faces: every owned Face must be in m_all_faces"
    );
  }
  #endif

  return std::count(m_all_faces.begin(),m_all_faces.end(),face);
}

bool ribi::foam::Cell::OwnsFace(const boost::shared_ptr<const ribi::foam::Face> face) const noexcept
{
  return std::count(m_owned_faces.begin(),m_owned_faces.end(),face);

}

std::ostream& ribi::foam::operator<<(std::ostream& os, const ribi::foam::Cell& cell) noexcept
{
  for (boost::shared_ptr<Face> face: cell.m_owned_faces)
  {
    assert(face);
    os << *face << '\n';
  }
  return os;
}

 

 

 

 

 

./CppOpenFoam/openfoamcellindex.h

 

#ifndef RIBI_OPENFOAMCELLINDEX_H
#define RIBI_OPENFOAMCELLINDEX_H

#include <iosfwd>

namespace ribi {
namespace foam {

struct CellIndex
{
  explicit CellIndex(const int index = -1);
  int Get() const noexcept { return m_index; }

  CellIndex& operator++() noexcept;   //Prefix
  CellIndex operator++(int) noexcept; //Postfix

  private:
  int m_index;
  friend std::istream& operator>>(std::istream& is, CellIndex& cell_index);

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif
};

std::ostream& operator<<(std::ostream& os, const CellIndex& cell_index) noexcept;
std::istream& operator>>(std::istream& is, CellIndex& cell_index);

bool operator==(const CellIndex& lhs, const CellIndex& rhs) noexcept;
bool operator!=(const CellIndex& lhs, const CellIndex& rhs) noexcept;
bool operator<(const CellIndex& lhs, const CellIndex& rhs) noexcept;
bool operator>(const CellIndex& lhs, const CellIndex& rhs) noexcept;
bool operator>=(const CellIndex& lhs, const CellIndex& rhs) noexcept;
bool operator<=(const CellIndex& lhs, const CellIndex& rhs) noexcept;

} //~namespace foam
} //~namespace ribi

#endif // RIBI_OPENFOAMCELLINDEX_H

 

 

 

 

 

./CppOpenFoam/openfoamcellindex.cpp

 

#include "openfoamcellindex.h"

#include <cassert>
#include <iostream>

#include "testtimer.h"
#include "trace.h"

ribi::foam::CellIndex::CellIndex(const int index)
  : m_index(index)
{
  #ifndef NDEBUG
  Test();
  #endif

  assert(m_index >= -1
    && "A CellIndex must be minus one or higher");
}

ribi::foam::CellIndex& ribi::foam::CellIndex::operator++() noexcept
{
  ++m_index;
  return *this;
}

ribi::foam::CellIndex ribi::foam::CellIndex::operator++(int) noexcept
{
  CellIndex old(*this);
  ++(*this);
  return old;
}


#ifndef NDEBUG
void ribi::foam::CellIndex::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
  CellIndex a(2);
  CellIndex b(2);
  CellIndex c(3);
  assert(a == a);
  assert(a == b);
  assert(b == a);
  assert(b == b);
  assert(b != c);
  assert(c != b);
  assert(c == c);
}
#endif

std::ostream& ribi::foam::operator<<(std::ostream& os, const CellIndex& cell_index) noexcept
{
  os << cell_index.Get();
  return os;
}

std::istream& ribi::foam::operator>>(std::istream& is, CellIndex& cell_index)
{
  is >> cell_index.m_index;
  #ifndef NDEBUG
  if (!is)
  {
    TRACE("ERROR");
  }
  #endif
  assert(is);
  return is;
}

bool ribi::foam::operator==(const CellIndex& lhs, const CellIndex& rhs) noexcept
{
  return lhs.Get() == rhs.Get();
}

bool ribi::foam::operator!=(const CellIndex& lhs, const CellIndex& rhs) noexcept
{
  return !(lhs == rhs);
}

bool ribi::foam::operator<(const CellIndex& lhs, const CellIndex& rhs) noexcept
{
  return lhs.Get() < rhs.Get();
}

bool ribi::foam::operator>(const CellIndex& lhs, const CellIndex& rhs) noexcept
{
  return lhs.Get() > rhs.Get();
}

bool ribi::foam::operator>=(const CellIndex& lhs, const CellIndex& rhs) noexcept
{
  return !(lhs < rhs);
}

bool ribi::foam::operator<=(const CellIndex& lhs, const CellIndex& rhs) noexcept
{
  return !(lhs > rhs);
}

 

 

 

 

 

./CppOpenFoam/openfoamcontroldictfile.h

 

#ifndef RIBI_OPENFOAMCONTROLDICTFILE_H
#define RIBI_OPENFOAMCONTROLDICTFILE_H

#include <iosfwd>
#include <vector>
#include "openfoamfwd.h"
#include "openfoamheader.h"

namespace ribi {
namespace foam {

///Reads and writes an OpenFOAM thermophysicalProperties file
struct ControlDictFile
{
  explicit ControlDictFile(
    const Header header = GetDefaultHeader()
  );

  static Header GetDefaultHeader() noexcept;
  const Header& GetHeader() const noexcept { return m_header; }

  void SetAdjustTimeStep(const bool adjust_time_step) noexcept { m_adjust_time_step = adjust_time_step; }
  void SetApplication(const std::string& application) noexcept { m_application = application; }
  void SetDeltaT(const double delta_t) noexcept { m_delta_t = delta_t; }
  void SetEndTime(const double end_time) noexcept { m_end_time = end_time; }
  void SetPurgeWrite(const int purge_write) noexcept { m_purge_write = purge_write; }
  void SetRunTimeModifiable(const bool run_time_modifiable) { m_run_time_modifiable = run_time_modifiable; }
  void SetStartFrom(const std::string& start_from) noexcept { m_start_from = start_from; }
  void SetStartTime(const double start_time) noexcept { m_start_time = start_time; }
  void SetStopAt(const std::string& stop_at) noexcept { m_stop_at = stop_at; }
  void SetTimeFormat(const std::string& time_format) noexcept { m_time_format = time_format; }
  void SetTimePrecision(const int time_precision) noexcept { m_time_precision = time_precision; }
  void SetWriteCompression(const std::string& write_compression) noexcept { m_write_compression = write_compression; }
  void SetWriteControl(const std::string& write_control) noexcept { m_write_control = write_control; }
  void SetWriteFormat(const std::string& write_format) noexcept { m_write_format = write_format; }
  void SetWriteInterval(const double write_interval) noexcept { m_write_interval = write_interval; }
  void SetWritePrecision(const int write_precision) noexcept { m_write_precision = write_precision; }
  private:

  bool m_adjust_time_step;
  std::string m_application;
  double m_delta_t;
  double m_end_time;

  ///The OpenFOAM header
  Header m_header;

  int m_purge_write;
  std::string m_start_from;
  double m_start_time;
  std::string m_stop_at;
  std::string m_time_format;
  int m_time_precision;
  bool m_run_time_modifiable;
  std::string m_write_compression;
  std::string m_write_control;
  std::string m_write_format;
  double m_write_interval;
  int m_write_precision;

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif

  friend std::ostream& operator<<(std::ostream& os, const ControlDictFile& f) noexcept;
};

std::ostream& operator<<(std::ostream& os, const ControlDictFile& f) noexcept;

} //~namespace foam
} //~namespace ribi

#endif // RIBI_OPENFOAMCONTROLDICTFILE_H

 

 

 

 

 

./CppOpenFoam/openfoamcontroldictfile.cpp

 

#include "openfoamcontroldictfile.h"

#include <cassert>
#include <fstream>
#include <iostream>
#include <stdexcept>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"

#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/lexical_cast.hpp>

#include <QFile>

#include "fileio.h"

#include "openfoamheader.h"
#include "testtimer.h"
#include "trace.h"
#pragma GCC diagnostic pop


ribi::foam::ControlDictFile::ControlDictFile(
  const Header header
)
  : m_adjust_time_step{},
    m_application{},
    m_delta_t{},
    m_end_time{},
    m_header{header},
    m_purge_write{},
    m_start_from{},
    m_start_time{},
    m_stop_at{},
    m_time_format{},
    m_time_precision{},
    m_run_time_modifiable{},
    m_write_compression{},
    m_write_control{},
    m_write_format{},
    m_write_interval{},
    m_write_precision{}
{
  #ifndef NDEBUG
  Test();
  #endif
}

ribi::foam::Header ribi::foam::ControlDictFile::GetDefaultHeader() noexcept
{
  return Header("dictionary","system","","controlDict");
}

#ifndef NDEBUG
void ribi::foam::ControlDictFile::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
}
#endif

std::ostream& ribi::foam::operator<<(std::ostream& os, const ControlDictFile& f) noexcept
{
  os
    << f.GetHeader() << '\n'
    << "" << '\n'
    << "application " << f.m_application << ";\n"
    << "startFrom " << f.m_start_from <<";\n"
    << "startTime " << f.m_start_time << ";\n"
    << "stopAt " << f.m_stop_at << ";\n"
    << "endTime " << f.m_end_time << ";\n"
    << "deltaT " << f.m_delta_t << ";\n"
    << "writeControl " << f.m_write_control << ";\n"
    << "writeInterval " << f.m_write_interval << ";\n"
    << "purgeWrite " << f.m_purge_write << ";\n"
    << "writeFormat " << f.m_write_format << ";\n"
    << "writePrecision " << f.m_write_precision << ";\n"
    << "writeCompression " << f.m_write_compression << ";\n"
    << "timeFormat " << f.m_time_format << ";\n"
    << "timePrecision " << f.m_time_precision << ";\n"
    << "runTimeModifiable " << (f.m_run_time_modifiable ? "yes" : "no") << ";\n"
    << "adjustTimeStep " << (f.m_adjust_time_step ? "yes" : "no") << ";\n"
  ;
  return os;
}

 

 

 

 

 

./CppOpenFoam/openfoamdecomposepardictfile.h

 

#ifndef RIBI_OPENFOAMDECOMPOSEPARDICTFILE_H
#define RIBI_OPENFOAMDECOMPOSEPARDICTFILE_H

#include <iosfwd>
#include <vector>
#include "openfoamfwd.h"
#include "openfoamheader.h"

namespace ribi {
namespace foam {

///Reads and writes an OpenFOAM thermophysicalProperties file
struct DecomposeParDictFile
{
  explicit DecomposeParDictFile(
    const Header header = GetDefaultHeader()
  );

  static Header GetDefaultHeader() noexcept;
  const Header& GetHeader() const noexcept { return m_header; }

  private:

  ///The OpenFOAM header
  Header m_header;

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif

  friend std::ostream& operator<<(std::ostream& os, const DecomposeParDictFile& f) noexcept;
};

std::ostream& operator<<(std::ostream& os, const DecomposeParDictFile& f) noexcept;

} //~namespace foam
} //~namespace ribi

#endif // RIBI_OPENFOAMDECOMPOSEPARDICTFILE_H

 

 

 

 

 

./CppOpenFoam/openfoamdecomposepardictfile.cpp

 

#include "openfoamdecomposepardictfile.h"

#include <cassert>
#include <fstream>
#include <iostream>
#include <stdexcept>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"

#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/lexical_cast.hpp>

#include <QFile>

#include "fileio.h"

#include "openfoamheader.h"
#include "testtimer.h"
#include "trace.h"
#pragma GCC diagnostic pop


ribi::foam::DecomposeParDictFile::DecomposeParDictFile(
  const Header header
)
  : m_header{header}
{
  #ifndef NDEBUG
  Test();
  #endif
}

ribi::foam::Header ribi::foam::DecomposeParDictFile::GetDefaultHeader() noexcept
{
  return Header("dictionary","system","","decomposeParDict");
}

#ifndef NDEBUG
void ribi::foam::DecomposeParDictFile::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
}
#endif

std::ostream& ribi::foam::operator<<(std::ostream& os, const DecomposeParDictFile& f) noexcept
{
  os
    << f.GetHeader() << '\n'
    << "\n"
    << "numberOfSubdomains 4;\n"
    << "\n"
    << "member function           scotch;\n"
    << "\n"
    << "simpleCoeffs\n"
    << "{\n"
    << "    n ( 4 1 1 );\n"
    << "    delta 0.001;\n"
    << "}\n"
    << "\n"
    << "hierarchicalCoeffs\n"
    << "{\n"
    << "    n ( 1 1 1 );\n"
    << "    delta 0.001;\n"
    << "    order xyz;\n"
    << "}\n"
    << "\n"
    << "metisCoeffs\n"
    << "{\n"
    << "    processorWeights ( 1 1 1 1 );\n"
    << "}\n"
    << "\n"
    << "manualCoeffs\n"
    << "{\n"
    << "    dataFile "";\n"
    << "}\n"
    << "\n"
    << "distributed no;\n"
    << "\n"
    << "roots ( );\n"
  ;
  return os;
}

 

 

 

 

 

./CppOpenFoam/openfoamepsilonfile.h

 

#ifndef OPENFOAMEPSILONFILE_H
#define OPENFOAMEPSILONFILE_H

#include <iosfwd>
#include <vector>
#include "openfoamfwd.h"
#include "openfoamheader.h"

namespace ribi {
namespace foam {

///Reads and writes an OpenFOAM epsilon file
struct EpsilonFile
{
  explicit EpsilonFile(
    const Header header = GetDefaultHeader()
  );

  static Header GetDefaultHeader() noexcept;
  const Header& GetHeader() const noexcept { return m_header; }

  private:

  ///The OpenFOAM header
  Header m_header;

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif

  friend std::ostream& operator<<(std::ostream& os, const EpsilonFile& f) noexcept;
};

std::ostream& operator<<(std::ostream& os, const EpsilonFile& f) noexcept;

} //~namespace foam
} //~namespace ribi

#endif // OPENFOAMEPSILONFILE_H

 

 

 

 

 

./CppOpenFoam/openfoamepsilonfile.cpp

 

#include "openfoamepsilonfile.h"

#include "openfoamdecomposepardictfile.h"

#include <cassert>
#include <fstream>
#include <iostream>
#include <stdexcept>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"

#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/lexical_cast.hpp>

#include <QFile>

#include "fileio.h"

#include "openfoamheader.h"
#include "testtimer.h"
#include "trace.h"
#pragma GCC diagnostic pop


ribi::foam::EpsilonFile::EpsilonFile(
  const Header header
)
  : m_header{header}
{
  #ifndef NDEBUG
  Test();
  #endif
}

ribi::foam::Header ribi::foam::EpsilonFile::GetDefaultHeader() noexcept
{
  return Header("volScalarField","0","","epsilon");
}

#ifndef NDEBUG
void ribi::foam::EpsilonFile::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
}
#endif

std::ostream& ribi::foam::operator<<(std::ostream& os, const EpsilonFile& f) noexcept
{
  os
    << f.GetHeader() << '\n'
    << "\n"
    << "dimensions      [ 0 2 -3 0 0 0 0 ];\n"
    << "\n"
    << "internalField   uniform 500000;\n"
    << "\n"
    << "boundaryField\n"
    << "{\n"
    << "\n"
    << "     inlet\n"
    << "     {\n"
    << " type zeroGradient;\n"
    << "     }\n"
    << "\n"
    << "     outlet\n"
    << " {\n"
    << "         type zeroGradient;\n"
    << "   }\n"
    << "\n"
    << "     side_CW\n"
    << "     {\n"
    << "         type zeroGradient;\n"
    << "     }\n"
    << "\n"
    << "     side_CCW\n"
    << "     {\n"
    << "         type zeroGradient;\n"
    << "     }\n"
    << " \n"
    << "     defaultFaces\n"
    << "     {\n"
    << "         type compressible::epsilonWallFunction;\n"
    << "         value uniform 500000;\n"
    << "     }\n"
    << "}\n"
  ;
  return os;
}

 

 

 

 

 

./CppOpenFoam/openfoamface.h

 

#ifndef RIBI_OPENFOAMFACE_H
#define RIBI_OPENFOAMFACE_H

#include <vector>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/shared_ptr.hpp>
#ifndef _WIN32
#include <boost/geometry/geometries/polygon.hpp>
#endif
#include "openfoamfwd.h"
#pragma GCC diagnostic pop

namespace ribi {

namespace foam {

///An OpenFOAM face:
///- has a collection of points/vertices/coordinats
///- has a/no neighbouring cell
///- has a/no cell owning this face
struct Face
{
  typedef boost::geometry::model::point<double,3,boost::geometry::cs::cartesian> Coordinat3D;

  explicit Face(
    const boost::shared_ptr<Cell>& neighbour,
    const boost::shared_ptr<Cell>& owner,
    const std::vector<boost::shared_ptr<Coordinat3D>>& points
  ) noexcept;

  Face(const Face&) = delete;
  Face& operator=(const Face&) = delete;

  ///Can only assign once
  void AssignNeighbour(const boost::shared_ptr<Cell> neighbour) noexcept;

  ///Can only assign once
  void AssignOwner(const boost::shared_ptr<Cell> owner) noexcept;

  boost::shared_ptr<const Cell> GetNeighbour() const noexcept { return m_neighbour; }

  boost::shared_ptr<const Cell> GetOwner() const noexcept { return m_owner; }
  boost::shared_ptr<      Cell> GetOwner()       noexcept;

        std::vector<boost::shared_ptr<const Coordinat3D>> GetPoints() const noexcept;
  const std::vector<boost::shared_ptr<      Coordinat3D>>&GetPoints()       noexcept { return m_points; }
  private:
  ///If this Face has no Neighbour, this is nullptr
  boost::shared_ptr<Cell> m_neighbour;

  ///If this Face has no Owner, this is nullptr
  boost::shared_ptr<Cell> m_owner;

  ///The points/vertices/coordinats this face consists of
  const std::vector<boost::shared_ptr<Coordinat3D>> m_points;

  friend std::ostream& operator<<(std::ostream& os, const Face& face) noexcept;
};

///Calculate the center of the Face
boost::geometry::model::point<double,3,boost::geometry::cs::cartesian> CalcCenter(const Face& face) noexcept;

std::ostream& operator<<(std::ostream& os, const Face& face) noexcept;

//bool operator<(const boost::shared_ptr<const Face>& lhs, const boost::shared_ptr<      Face>& rhs) = delete;
//bool operator<(const boost::shared_ptr<const Face>& lhs, const boost::shared_ptr<const Face>& rhs) = delete;
//bool operator<(const boost::shared_ptr<      Face>& lhs, const boost::shared_ptr<      Face>& rhs) = delete;
//bool operator<(const boost::shared_ptr<      Face>& lhs, const boost::shared_ptr<const Face>& rhs) = delete;

} //~namespace foam
} //~namespace ribi

#endif // RIBI_OPENFOAMFACE_H

 

 

 

 

 

./CppOpenFoam/openfoamface.cpp

 

#include "openfoamface.h"

#include <cassert>
#include <ostream>

#include "openfoamcell.h"
#include "openfoamhelper.h"
#include "trace.h"

ribi::foam::Face::Face(
  const boost::shared_ptr<Cell>& neighbour,
  const boost::shared_ptr<Cell>& owner,
  const std::vector<boost::shared_ptr<Coordinat3D>>& points
) noexcept
  : m_neighbour(neighbour),
    m_owner(owner),
    m_points(points)
{
  #ifndef NDEBUG
  assert(!m_neighbour);
  assert(!m_owner);
  for (const auto& p: m_points) { assert(p); }
  #endif
}

void ribi::foam::Face::AssignNeighbour(const boost::shared_ptr<ribi::foam::Cell> neighbour) noexcept
{
  assert(!m_neighbour && "neighbour can only be assigned once");
  assert(neighbour);
  m_neighbour = neighbour;
}

void ribi::foam::Face::AssignOwner(const boost::shared_ptr<ribi::foam::Cell> owner) noexcept
{
  assert(!m_owner && "Can only assign owner once");
  assert(owner);

  m_owner = owner;
}

boost::shared_ptr<ribi::foam::Cell> ribi::foam::Face::GetOwner() noexcept
{
  assert( (m_owner || !m_owner) && "Allow Face to have no owner");
  return m_owner;
}

std::vector<boost::shared_ptr<const boost::geometry::model::point<double,3,boost::geometry::cs::cartesian>>>
  ribi::foam::Face::GetPoints() const noexcept
{
  std::vector<boost::shared_ptr<const Coordinat3D>> v;
  std::transform(
    m_points.begin(),
    m_points.end(),
    std::back_inserter(v),
    [](const boost::shared_ptr<Coordinat3D> point)
    {
      assert(point);
      const boost::shared_ptr<const Coordinat3D> const_point {
        point
      };
      assert(point == const_point);
      return const_point;
    }
  );
  assert(v.size() == m_points.size());
  //Only check first and last
  assert(v.empty() || v[0] == m_points[0]);
  assert(v.empty() || v[ v.size() - 1 ] == m_points[ v.size() - 1 ]);
  return v;
}

boost::geometry::model::point<double,3,boost::geometry::cs::cartesian> ribi::foam::CalcCenter(const Face& face) noexcept
{
  typedef boost::geometry::model::point<double,3,boost::geometry::cs::cartesian> Coordinat3D;

  Coordinat3D d(0.0,0.0,0.0);
  for (boost::shared_ptr<const Coordinat3D> c: face.GetPoints())
  {
    assert(c);
    d.set<0>(d.get<0>() + c->get<0>());
    d.set<1>(d.get<1>() + c->get<1>());
    d.set<2>(d.get<2>() + c->get<2>());
    //d += (*c);
  }
  //d /= static_cast<double>(face.GetPoints().size());
  d.set<0>(d.get<0>() / static_cast<double>(face.GetPoints().size()));
  d.set<1>(d.get<1>() / static_cast<double>(face.GetPoints().size()));
  d.set<2>(d.get<2>() / static_cast<double>(face.GetPoints().size()));
  return d;
}

std::ostream& ribi::foam::operator<<(std::ostream& os, const ribi::foam::Face& face) noexcept
{
  typedef boost::geometry::model::point<double,3,boost::geometry::cs::cartesian> Coordinat3D;

  if (face.m_neighbour)
  {
    //Only display the address of a neighbour to prevent recursion
    assert(face.m_neighbour);
    os << face.m_neighbour;
  }
  os << '\n';
  assert(face.m_owner && "Every Face has an owner");
  //if (face.m_owner)
  {
    //Only display the address of a owner to prevent recursion
    assert(face.m_owner);
    os << face.m_owner;
  }
  os << '\n';
  for (const boost::shared_ptr<Coordinat3D> coordinat: face.m_points)
  {
    assert(coordinat);
    os << ToStr(*coordinat) << '\n';
  }
  return os;

}

 

 

 

 

 

./CppOpenFoam/openfoamfaceindex.h

 

#ifndef RIBI_OPENFOAMFACEINDEX_H
#define RIBI_OPENFOAMFACEINDEX_H

#include <iosfwd>

namespace ribi {
namespace foam {

struct FaceIndex
{
  ///Throws std::invalid_argument if the index is invalid
  explicit FaceIndex(const int index);
  int Get() const noexcept { return m_index; }

  ///Throws std::invalid_argument if the new index is invalid
  FaceIndex& operator+=(const FaceIndex& rhs);
  FaceIndex& operator-=(const FaceIndex& rhs);
  FaceIndex& operator++() noexcept;   //Prefix
  FaceIndex operator++(int) noexcept; //Postfix
  FaceIndex& operator--() noexcept;   //Prefix
  FaceIndex operator--(int) noexcept; //Postfix
  private:
  int m_index;
  friend std::istream& operator>>(std::istream& is, FaceIndex& face_index) noexcept;
};

std::ostream& operator<<(std::ostream& os, const FaceIndex& face_index) noexcept;
std::istream& operator>>(std::istream& is, FaceIndex& face_index) noexcept;

const FaceIndex operator+(const FaceIndex& lhs, const FaceIndex& rhs) noexcept;
const FaceIndex operator-(const FaceIndex& lhs, const FaceIndex& rhs);

bool operator==(const FaceIndex& lhs, const FaceIndex& rhs) noexcept;
bool operator!=(const FaceIndex& lhs, const FaceIndex& rhs) noexcept;
bool operator<(const FaceIndex& lhs, const FaceIndex& rhs) noexcept;
bool operator>(const FaceIndex& lhs, const FaceIndex& rhs) noexcept;
bool operator>=(const FaceIndex& lhs, const FaceIndex& rhs) noexcept;
bool operator<=(const FaceIndex& lhs, const FaceIndex& rhs) noexcept;

} //~namespace foam
} //~namespace ribi

#endif // RIBI_OPENFOAMFACEINDEX_H

 

 

 

 

 

./CppOpenFoam/openfoamfaceindex.cpp

 

#include "openfoamfaceindex.h"

#include <cassert>
#include <iostream>
#include <stdexcept>

#include "trace.h"

ribi::foam::FaceIndex::FaceIndex(const int index)
  : m_index(index)
{
  #ifndef NDEBUG
  if (m_index < 0)
  {
    TRACE("ERROR");
    TRACE(m_index);
  }
  #endif
  assert(m_index >= 0
    && "A FaceIndex must be zero or a positive value");
  if (m_index < 0)
  {
    throw std::invalid_argument("A FaceIndex must be zero or a positive value");
  }
}

ribi::foam::FaceIndex& ribi::foam::FaceIndex::operator+=(const FaceIndex& rhs)
{
  m_index += rhs.Get();

  assert(m_index >= 0
    && "A FaceIndex must be zero or a positive value, must have overflowed");
  if (m_index < 0)
  {
    throw std::invalid_argument(
      "FaceIndex::operator+=: FaceIndex cannot be negative, must have overflowed");
  }
  return *this;
}

ribi::foam::FaceIndex& ribi::foam::FaceIndex::operator-=(const FaceIndex& rhs)
{
  m_index -= rhs.Get();

  assert(m_index >= 0
    && "A FaceIndex must be zero or a positive value");
  if (m_index < 0)
  {
    throw std::invalid_argument(
      "FaceIndex::operator-=: FaceIndex cannot be negative");
  }
  return *this;
}

ribi::foam::FaceIndex& ribi::foam::FaceIndex::operator++() noexcept
{
  ++m_index;
  assert(m_index >= 0);
  return *this;
}

ribi::foam::FaceIndex ribi::foam::FaceIndex::operator++(int) noexcept
{
  FaceIndex old(*this);
  ++(*this);
  assert(m_index >= 0);
  return old;
}

ribi::foam::FaceIndex& ribi::foam::FaceIndex::operator--() noexcept
{
  --m_index;
  assert(m_index >= 0);
  return *this;
}

ribi::foam::FaceIndex ribi::foam::FaceIndex::operator--(int) noexcept
{
  FaceIndex old(*this);
  --(*this);
  assert(m_index >= 0);
  return old;
}

std::ostream& ribi::foam::operator<<(std::ostream& os, const FaceIndex& face_index) noexcept
{
  os << face_index.Get();
  return os;
}

std::istream& ribi::foam::operator>>(std::istream& is, FaceIndex& face_index) noexcept
{
  is >> face_index.m_index;
  assert(is);
  return is;
}

const ribi::foam::FaceIndex ribi::foam::operator+(const FaceIndex& lhs, const FaceIndex& rhs) noexcept
{
  return FaceIndex(lhs.Get() + rhs.Get());
}

const ribi::foam::FaceIndex ribi::foam::operator-(const FaceIndex& lhs, const FaceIndex& rhs)
{
  return FaceIndex(lhs.Get() - rhs.Get());
}

bool ribi::foam::operator==(const FaceIndex& lhs, const FaceIndex& rhs) noexcept
{
  return lhs.Get() == rhs.Get();
}

bool ribi::foam::operator!=(const FaceIndex& lhs, const FaceIndex& rhs) noexcept
{
  return !(lhs == rhs);
}

bool ribi::foam::operator<(const FaceIndex& lhs, const FaceIndex& rhs) noexcept
{
  return lhs.Get() < rhs.Get();
}

bool ribi::foam::operator>(const FaceIndex& lhs, const FaceIndex& rhs) noexcept
{
  return lhs.Get() > rhs.Get();
}

bool ribi::foam::operator>=(const FaceIndex& lhs, const FaceIndex& rhs) noexcept
{
  return !(lhs < rhs);
}

bool ribi::foam::operator<=(const FaceIndex& lhs, const FaceIndex& rhs) noexcept
{
  return !(lhs > rhs);
}

 

 

 

 

 

./CppOpenFoam/openfoamfacesfile.h

 

#ifndef RIBI_OPENFOAMFACESFILE_H
#define RIBI_OPENFOAMFACESFILE_H

#include <iosfwd>
#include <string>
#include <vector>
#include "fileiofwd.h"
#include "openfoamfwd.h"
#include "openfoamheader.h"
#include "openfoamfacesfileitem.h"

namespace ribi {
namespace foam {

///Reads and writes an OpenFOAM boundary file
struct FacesFile
{
  explicit FacesFile(const std::string& filename) : FacesFile(Parse(filename)) {}
  explicit FacesFile(
    const Header header = GetDefaultHeader(),
    const std::vector<FacesFileItem>& items = {});

  bool CanGetItem(const FaceIndex& face_index) const noexcept;

  static Header GetDefaultHeader() noexcept;
  const Header& GetHeader() const noexcept { return m_header; }
  std::vector<FacesFileItem> GetItems() const noexcept { return m_items; }

  ///Assumes CanGetItem is true
  const FacesFileItem& GetItem(const FaceIndex& face_index) const noexcept;

  ///Obtain the number of faces, the size of m_items, or the first face index not available
  FaceIndex GetMaxFaceIndex() const noexcept;

  private:
  explicit FacesFile(std::istream& is) : FacesFile(Parse(is)) {}

  ///The OpenFOAM header
  Header m_header;
  ///The items faces contains
  std::vector<FacesFileItem> m_items;

  static FacesFile Parse(std::istream& is);
  static FacesFile Parse(const std::string& filename);

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif

  friend std::ostream& operator<<(std::ostream& os, const FacesFile& f) noexcept;
  friend std::istream& operator>>(std::istream& is, FacesFile& f);
};

bool operator==(const FacesFile& lhs,const FacesFile& rhs) noexcept;
bool operator!=(const FacesFile& lhs,const FacesFile& rhs) noexcept;
std::ostream& operator<<(std::ostream& os, const FacesFile& f) noexcept;
std::istream& operator>>(std::istream& is, FacesFile& f);

} //~namespace foam
} //~namespace ribi

#endif // RIBI_OPENFOAMFACESFILE_H

 

 

 

 

 

./CppOpenFoam/openfoamfacesfile.cpp

 

#include "openfoamfacesfile.h"

#include <cassert>
#include <fstream>
#include <iostream>
#include <stdexcept>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/lexical_cast.hpp>

#include <QFile>


#include "fileio.h"
#include "openfoamheader.h"
#include "openfoamfacesfileitem.h"
#include "openfoamfaceindex.h"
#include "openfoamparseerror.h"
#include "testtimer.h"
#include "trace.h"
#pragma GCC diagnostic pop


ribi::foam::FacesFile::FacesFile(
  const Header header,
  const std::vector<FacesFileItem>& items)
  : m_header{header},
    m_items(items)
{
  #ifndef NDEBUG
  Test();
  #endif
}

bool ribi::foam::FacesFile::CanGetItem(const ribi::foam::FaceIndex& face_index) const noexcept
{
  assert(face_index.Get() >= 0);
  return face_index.Get() < static_cast<int>(m_items.size());
}

ribi::foam::Header ribi::foam::FacesFile::GetDefaultHeader() noexcept
{
  return Header("faceList","constant/polyMesh","","faces");
}

const ribi::foam::FacesFileItem& ribi::foam::FacesFile::GetItem(const ribi::foam::FaceIndex& face_index) const noexcept
{
  assert(CanGetItem(face_index));
  return m_items[ face_index.Get() ];
}


ribi::foam::FaceIndex ribi::foam::FacesFile::GetMaxFaceIndex() const noexcept
{
  return FaceIndex(static_cast<int>(m_items.size()));
}

ribi::foam::FacesFile ribi::foam::FacesFile::Parse(std::istream& is)
{
  FacesFile b;
  is >> b;
  assert(is);
  return b;
}

ribi::foam::FacesFile ribi::foam::FacesFile::Parse(const std::string& filename)
{
  const std::string tmp_filename { fileio::FileIo().GetTempFileName() };
  fileio::FileIo().CopyFile(filename,tmp_filename);
  Header::CleanFile(tmp_filename);
  std::ifstream f(tmp_filename.c_str());
  const FacesFile file { Parse(f) };
  f.close();
  fileio::FileIo().DeleteFile(tmp_filename);
  return file;
}

#ifndef NDEBUG
void ribi::foam::FacesFile::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
  //Some initial data
  const Header header("some_name","some_location","some_object");
  std::vector<FacesFileItem> items;
  for (int i=1; i!=4; ++i)
  {
    FacesFileItem item( std::vector<PointIndex>(i,PointIndex(i)));
    items.push_back(item);
  }
  //operator==
  {
    const FacesFile b(header,items);
    const FacesFile c(header,items);
    assert(header == header);
    assert(b == c);
  }
  //operator!=
  {
    const FacesFile b(header,items);
    const Header other_header("some_other_name","some_other_location","some_other_object");
    assert(header != other_header);
    const FacesFile c(other_header,items);
    assert(b != c);
  }
  //operator!=
  {
    const FacesFile b(header,items);
    std::vector<FacesFileItem> other_items;
    for (int i=1; i!=3; ++i)
    {
      FacesFileItem item( std::vector<PointIndex>(i+1,PointIndex(i*i)) );
      other_items.push_back(item);
    }
    const FacesFile c(header,other_items);
    assert(b != c);
  }
  //Stream conversion
  {
    const FacesFile b(header,items);
    std::stringstream s;
    s << b;
    FacesFile c;
    s >> c;
    if (b != c)
    {
      TRACE(b);
      TRACE(c);
    }
    assert(b == c);
  }
  //Read from testing file
  for (int test_index = 0; test_index!=5; ++test_index)
  {
    std::string filename_appendix;
    switch (test_index)
    {
      case 0: filename_appendix = "_1x1x1"; break;
      case 1: filename_appendix = "_1x1x2"; break;
      case 2: filename_appendix = "_1x2x2"; break;
      case 3: filename_appendix = "_2x2x2"; break;
      case 4: filename_appendix = "_3x4x5"; break;
      default: assert(!"Should never get here");
        throw std::logic_error("foam::Files::CreateTestFiles: unknown test index");
    }
    assert(!filename_appendix.empty());
    const std::string filename_base { GetDefaultHeader().GetObject() };
    const std::string filename = filename_base + filename_appendix;
    const std::string resources_path { ":/CppOpenFoam/files/" + filename };

    {
      QFile f( resources_path.c_str() );
      f.copy(filename.c_str());
    }
    {
      if (!fileio::FileIo().IsRegularFile(filename))
      {
        TRACE("ERROR");
        TRACE(filename);
      }
      assert(fileio::FileIo().IsRegularFile(filename));
      FacesFile b(filename);
      if (b.GetItems().empty())
      {
        TRACE("ERROR");
      }
      assert( (!b.GetItems().empty() || b.GetItems().empty())
        && "If a mesh has no non-bhoundary cells, neighbour can be empty");
    }
  }
}
#endif

bool ribi::foam::operator==(const FacesFile& lhs,const FacesFile& rhs) noexcept
{
  if (lhs.GetHeader() != rhs.GetHeader())
  {
    return false;
  }
  const std::vector<FacesFileItem>& lhs_items = lhs.GetItems();
  const std::vector<FacesFileItem>& rhs_items = rhs.GetItems();
  if (lhs_items.size() != rhs_items.size())
  {
    return false;
  }
  return std::equal(lhs_items.begin(),lhs_items.end(),rhs_items.begin());
}

bool ribi::foam::operator!=(const FacesFile& lhs,const FacesFile& rhs) noexcept
{
  return !(lhs == rhs);
}

std::istream& ribi::foam::operator>>(std::istream& is, FacesFile& f)
{
  assert(f.m_items.empty()); //Make empty otherwise

  //Read header
  is >> f.m_header;
  assert(is);

  //Read items
  int n_items = 0;
  char opening_bracket = '\0';
  {
    //Eat comment
    char c = '\0';
    is >> c;
    assert(is);
    if (c >= '0' && c <= '9')
    {
      while (c != '(' && c != '{')
      {
        //Start eating n_items
        n_items *= 10;
        const int n = c - '0';
        assert(n >= 0 && n <= 9);
        n_items += n;
        is >> c;
        assert(is);
      }
    }
    opening_bracket = c;
    #ifndef NDEBUG
    if (!(opening_bracket == '(' || opening_bracket == '{'))
    {
      TRACE(opening_bracket);
      TRACE("ERROR");
    }
    #endif
    assert(opening_bracket == '(' || opening_bracket == '{');
  }
  assert(opening_bracket == '(' || opening_bracket == '{');
  if (opening_bracket == '(')
  {
    for (int i=0; i!=n_items; ++i)
    {
      FacesFileItem item;
      is >> item;
      assert(is);
      f.m_items.push_back(item);
    }
  }
  else
  {
    assert(opening_bracket == '{');
    //Read once, push n_items times
    FacesFileItem item;
    is >> item;
    assert(is);
    for (int i=0; i!=n_items; ++i)
    {
      f.m_items.push_back(item);
    }
  }
  //Eat comments until bracket close
  {
    char bracket_close = '\0';
    while (bracket_close != ')' && bracket_close != '}')
    {
      is >> bracket_close;
      assert(is);
    }
    assert(bracket_close == ')' || bracket_close == '}');
    assert(
         (opening_bracket == '(' && bracket_close == ')')
      || (opening_bracket == '{' && bracket_close == '}')
    );
  }
  return is;
}

std::ostream& ribi::foam::operator<<(std::ostream& os, const FacesFile& f) noexcept
{
  os
    << f.GetHeader() << '\n'
    << "" << '\n'
    << f.m_items.size() << '\n'
    << "(" << '\n'
  ;

  for(const FacesFileItem item: f.m_items)
  {
    os << item << '\n';
  }

  os
    << ")" << '\n'
  ;
  return os;
}

 

 

 

 

 

./CppOpenFoam/openfoamfacesfileitem.h

 

#ifndef RIBI_OPENFOAMFACESFILEITEM_H
#define RIBI_OPENFOAMFACESFILEITEM_H

#include <vector>
#include <iosfwd>
#include "openfoampointindex.h"

namespace ribi {
namespace foam {

///An item in an OpenFOAM 'faces' file
struct FacesFileItem
{
  explicit FacesFileItem(
    const std::vector<PointIndex>& point_indices = {}
  );

  const std::vector<PointIndex>& GetPointIndices() const noexcept { return m_point_indices; }

  private:

  std::vector<PointIndex> m_point_indices;

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif

  friend class OpenFoamFacesFile;
  friend std::istream& operator>>(std::istream& is, FacesFileItem& f);
};

bool operator==(const FacesFileItem& lhs, const FacesFileItem& rhs) noexcept;
bool operator!=(const FacesFileItem& lhs, const FacesFileItem& rhs) noexcept;
std::ostream& operator<<(std::ostream& os, const FacesFileItem& f) noexcept;
std::istream& operator>>(std::istream& is, FacesFileItem& f);

} //~namespace foam
} //~namespace ribi


#endif // RIBI_OPENFOAMFACESFILEITEM_H

 

 

 

 

 

./CppOpenFoam/openfoamfacesfileitem.cpp

 

#include "openfoamfacesfileitem.h"

#include <cassert>
#include <iostream>
#include <sstream>

#include "openfoamparseerror.h"
#include "testtimer.h"
#include "trace.h"

ribi::foam::FacesFileItem::FacesFileItem(
  const std::vector<PointIndex>& point_indices
  )
  : m_point_indices{point_indices}
{
  #ifndef NDEBUG
  Test();
  for (PointIndex index: m_point_indices)
  {
    assert(index.Get() >= 0 && "Sure, there is a point with index 0");
  }
  #endif
}

#ifndef NDEBUG
void ribi::foam::FacesFileItem::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
  const FacesFileItem i( { PointIndex(1),PointIndex(2),PointIndex(3),PointIndex(4) } );
  std::stringstream s;
  s << i;
  FacesFileItem j;
  s >> j;
  if (i != j)
  {
    TRACE(i);
    TRACE(j);
  }
  assert(i == j);
}
#endif

bool ribi::foam::operator==(const FacesFileItem& lhs, const FacesFileItem& rhs) noexcept
{
  return
       lhs.GetPointIndices() == rhs.GetPointIndices()
  ;
}

bool ribi::foam::operator!=(const FacesFileItem& lhs, const FacesFileItem& rhs) noexcept
{
  return !(lhs == rhs);
}

std::ostream& ribi::foam::operator<<(std::ostream& os, const FacesFileItem& item) noexcept
{
  os
    << item.GetPointIndices().size()
    << "("
  ;

  std::stringstream s;
  for (const PointIndex i: item.GetPointIndices()) { s << i << " "; }
  std::string t { s.str() };
  assert(t.back() == ' ');
  t.pop_back();
  assert(t.back() != ' ');
  os
    << t
    << ")"
  ;

  return os;
}

std::istream& ribi::foam::operator>>(std::istream& is, FacesFileItem& f)
{
  assert(f.GetPointIndices().empty()); //Or empty it
  int n_nodes = 0;
  {
    is >> n_nodes;
    assert(is);
    if (n_nodes <= 0)
    {
      throw ParseError();
    }
    assert(n_nodes > 0);
  }
  {
    char bracket_open;
    is >> bracket_open;
    assert(is);
    assert(bracket_open == '(');
  }
  for (int i=0; i!=n_nodes; ++i)
  {
    PointIndex node;
    is >> node;
    assert(is);
    f.m_point_indices.push_back(node);
  }
  {
    char bracket_close;
    is >> bracket_close;
    assert(is);
    assert(bracket_close == ')');
  }
  return is;
}

 

 

 

 

 

./CppOpenFoam/openfoamfilenames.h

 

#ifndef RIBI_OPENFOAMFILENAMES_H
#define RIBI_OPENFOAMFILENAMES_H

#include <string>
#include <vector>

#include "fileio.h"
//

namespace ribi {
namespace foam {

///Filenames used for OpenFOAM
struct Filenames
{
  std::vector<std::string> GetAll() const noexcept;

  ///The filename for the OpenFOAM its case its velocity field
  std::string GetAlphat() const noexcept;

  ///The filename the resulting boundary (needed by OpenFoam) will be written to
  ///Must use Win32 backslashes
  std::string GetBoundary() const noexcept;

  ///The filename that indicates that this is an OpenFOAM case
  std::string GetCase() const noexcept;

  ///The filename for the OpenFOAM its controlDict
  std::string GetControlDict() const noexcept;

  ///The filename the resulting faces will be written to
  ///Must use Win32 backslashes
  std::string GetFaces() const noexcept;

  ///The filename of the OpenFOAM solver schemes
  ///Must use Win32 backslashes
  std::string GetFvSchemes() const noexcept;

  ///The filename of the OpenFOAM solver solution
  ///Must use Win32 backslashes
  std::string GetFvSolution() const noexcept;

  ///The filename the resulting neighbour (needed by OpenFOAM) will be written to
  ///Must use Win32 backslashes
  std::string GetNeighbour() const noexcept;

  ///The filename that indicates that this is an OpenFOAM case
  std::string GetOpenFoamCase() const noexcept { return GetCase(); }

  ///The filename for the OpenFOAM its controlDict
  std::string GetOpenFoamControlDict() const noexcept { return GetControlDict(); }

  ///The filename of the OpenFOAM solver schemes
  std::string GetOpenFoamFvSchemes() const noexcept { return GetFvSchemes(); }

  ///The filename of the OpenFOAM solver solution
  std::string GetOpenFoamFvSolution() const noexcept { return GetFvSolution(); }

  ///The filename for the OpenFOAM its case its pressure field
  std::string GetOpenFoamPressureField() const noexcept { return GetPressureField(); }

  ///The filename for the OpenFOAM its case its TransportProperties
  std::string GetOpenFoamTransportProperties() const noexcept { return GetTransportProperties(); }

  ///The filename for the OpenFOAM its case its velocity field
  std::string GetOpenFoamVelocityField() const noexcept { return GetVelocityField(); }

  ///The filename the resulting owner (needed by OpenFOAM) will be written to
  ///Must use Win32 backslashes
  std::string GetOwner() const noexcept;

  ///The filename the resulting nodes will be written to
  ///Must use Win32 backslashes
  std::string GetPoints() const noexcept;

  ///The filename for the OpenFOAM its case its pressure field
  std::string GetPressureField() const noexcept;

  ///The filename for the OpenFOAM its case its pressure field
  std::string GetTemperatureField() const noexcept;

  ///The filename for the OpenFOAM its case its thermophysicalProperties
  std::string GetThermophysicalProperties() const noexcept;

  ///The filename for the OpenFOAM its case its TransportProperties
  std::string GetTransportProperties() const noexcept;

  ///The filename for the OpenFOAM its case its TransportProperties
  std::string GetTurbulenceProperties() const noexcept;

  ///The filename for the OpenFOAM its case its velocity field
  std::string GetVelocityField() const noexcept;

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif
};

std::ostream& operator<<(std::ostream& os, const Filenames& filenames) noexcept;

} //~namespace foam
} //~namespace ribi

#endif // RIBI_OPENFOAMFILENAMES_H

 

 

 

 

 

./CppOpenFoam/openfoamfilenames.cpp

 

#include "openfoamfilenames.h"

//#include "parameterfilenamesopenfoam.h"

#include <cassert>
#include <sstream>

#include "fileio.h"
#include "xml.h"

std::vector<std::string> ribi::foam::Filenames::GetAll() const noexcept
{
  return {
    this->GetBoundary(),
    this->GetFaces(),
    this->GetNeighbour(),
    this->GetCase(),
    this->GetOwner(),
    this->GetPoints()
  };
}

std::string ribi::foam::Filenames::GetAlphat() const noexcept
{
  return std::string(
      "0"
    + fileio::FileIo().GetPathSeperator()
    + "alphat"
  );
}

std::string ribi::foam::Filenames::GetBoundary() const noexcept
{
  return std::string(
      "constant"
    + fileio::FileIo().GetPathSeperator()
    + "polyMesh"
    + fileio::FileIo().GetPathSeperator()
    + "boundary"
  );
}

std::string ribi::foam::Filenames::GetFaces() const noexcept
{
  return std::string(
      "constant"
    + fileio::FileIo().GetPathSeperator()
    + "polyMesh"
    + fileio::FileIo().GetPathSeperator()
    + "faces"
  );
}

std::string ribi::foam::Filenames::GetNeighbour() const noexcept
{
  return std::string(
      "constant"
    + fileio::FileIo().GetPathSeperator()
    + "polyMesh"
    + fileio::FileIo().GetPathSeperator()
    + "neighbour"
  );
}

std::string ribi::foam::Filenames::GetCase() const noexcept
{
  return std::string("case.foam");
}

std::string ribi::foam::Filenames::GetControlDict() const noexcept
{
  return std::string(
      "system"
    + fileio::FileIo().GetPathSeperator()
    + "controlDict"
  );
}

std::string ribi::foam::Filenames::GetFvSchemes() const noexcept
{
  return std::string(
      "system"
    + fileio::FileIo().GetPathSeperator()
    + "fvSchemes"
  );
}

std::string ribi::foam::Filenames::GetFvSolution() const noexcept
{
  return std::string(
      "system"
    + fileio::FileIo().GetPathSeperator()
    + "fvSolution"
  );
}

std::string ribi::foam::Filenames::GetOwner() const noexcept
{
  return std::string(
      "constant"
    + fileio::FileIo().GetPathSeperator()
    + "polyMesh"
    + fileio::FileIo().GetPathSeperator()
    + "owner"
  );
}

std::string ribi::foam::Filenames::GetPoints() const noexcept
{
  return std::string(
      "constant"
    + fileio::FileIo().GetPathSeperator()
    + "polyMesh"
    + fileio::FileIo().GetPathSeperator()
    + "points"
  );
}

std::string ribi::foam::Filenames::GetPressureField() const noexcept
{
  return std::string(
      "0"
    + fileio::FileIo().GetPathSeperator()
    + "p"
  );
}

std::string ribi::foam::Filenames::GetTemperatureField() const noexcept
{
  return std::string(
      "0"
    + fileio::FileIo().GetPathSeperator()
    + "T"
  );
}

std::string ribi::foam::Filenames::GetThermophysicalProperties() const noexcept
{
  return std::string(
      "constant"
    + fileio::FileIo().GetPathSeperator()
    + "thermophysicalProperties"
  );
}

std::string ribi::foam::Filenames::GetTransportProperties() const noexcept
{
  return std::string(
      "constant"
    + fileio::FileIo().GetPathSeperator()
    + "transportProperties"
  );
}

std::string ribi::foam::Filenames::GetTurbulenceProperties() const noexcept
{
  return std::string(
      "constant"
    + fileio::FileIo().GetPathSeperator()
    + "turbulenceProperties"
  );
}

std::string ribi::foam::Filenames::GetVelocityField() const noexcept
{
  return std::string(
      "0"
    + fileio::FileIo().GetPathSeperator()
    + "U"
  );
}


std::ostream& ribi::foam::operator<<(std::ostream& os, const ribi::foam::Filenames& filenames) noexcept
{
  std::stringstream s;
  s
    << ribi::xml::ToXml("filename_boundary",filenames.GetBoundary())
    << ribi::xml::ToXml("filename_faces",filenames.GetFaces())
    << ribi::xml::ToXml("filename_neightbour",filenames.GetNeighbour())
    << ribi::xml::ToXml("filename_openfoam",filenames.GetCase())
    << ribi::xml::ToXml("filename_owner",filenames.GetOwner())
    << ribi::xml::ToXml("filename_points",filenames.GetPoints())
  ;

  os << ribi::xml::ToXml("parameter_filenames_openfoam",s.str());
  return os;
}

 

 

 

 

 

./CppOpenFoam/openfoamfiles.h

 

#ifndef RIBI_OPENFOAMFILES_H
#define RIBI_OPENFOAMFILES_H

#include <vector>
#include <iosfwd>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#include <boost/shared_ptr.hpp>
#include "openfoamfwd.h"
#pragma GCC diagnostic pop

namespace ribi {
namespace foam {

///Files contains the info of all files in an OpenFOAM folder
///This info can be used to create a Mesh
///After creating a Files, these files can be deleted
///Use CreateCopy to let these files be recreated again
struct Files
{
  ///Builds up Files from the current or any folder
  ///Use an empty string to build up from current folder
  explicit Files(const std::string& folder_name)
    : Files(
        CreateBoundary(folder_name),
        CreateFaces(folder_name),
        CreateNeighbour(folder_name),
        CreateOwner(folder_name),
        CreatePoints(folder_name)
      ) { }

  ///Builds up a Files from its information or from nothing
  explicit Files(
    const boost::shared_ptr<BoundaryFile> boundary = CreateDefaultBoundary(),
    const boost::shared_ptr<FacesFile> faces = CreateDefaultFaces(),
    const boost::shared_ptr<NeighbourFile> neighbour = CreateDefaultNeighbour(),
    const boost::shared_ptr<OwnerFile> owner = CreateDefaultOwner(),
    const boost::shared_ptr<PointsFile> points = CreateDefaultPoints()
  );
  Files(const Files& other);
  Files& operator=(const Files& rhs) = delete;

  ///Create a copy of the complete file structure of Files in the copy folder name
  static void CreateCopy(const Files& files, const std::string copy_folder_name) noexcept;

  ///Create test files in the correct OpenFOAM folder structure
  ///These files are obtained from the /Classes/CppOpenFoam/CppOpenFoam.qrc resources file
  static void CreateTestFiles(const std::string& folder_name, const int test_index);

  ///Create valid test Files
  ///0: empty Files
  ///1: Cube
  ///2: 1x2 cubes
  ///3: 2x2 cubes
  static std::vector<boost::shared_ptr<Files>> CreateTestFiles() noexcept;

  boost::shared_ptr<const BoundaryFile> GetBoundary() const noexcept { return m_boundary; }
  boost::shared_ptr<const FacesFile> GetFaces() const noexcept { return m_faces; }
  boost::shared_ptr<const NeighbourFile> GetNeighbour() const noexcept { return m_neighbour; }
  boost::shared_ptr<const OwnerFile> GetOwner() const noexcept { return m_owner; }
  boost::shared_ptr<const PointsFile> GetPoints() const noexcept { return m_points; }

  void Swap(const FaceIndex& lhs, const FaceIndex& rhs);

  private:
  const boost::shared_ptr<BoundaryFile> m_boundary;
  const boost::shared_ptr<FacesFile> m_faces;
  const boost::shared_ptr<NeighbourFile> m_neighbour;
  const boost::shared_ptr<OwnerFile> m_owner;
  const boost::shared_ptr<PointsFile> m_points;

  ///Checks this class for correctless
  ///Throws std::logic_error if there are incorrectnesses
  void CheckMe() const;

  static boost::shared_ptr<BoundaryFile> CreateBoundary(const std::string& folder_name);
  static boost::shared_ptr<BoundaryFile> CreateDefaultBoundary() noexcept;
  static boost::shared_ptr<FacesFile> CreateDefaultFaces() noexcept;
  static boost::shared_ptr<NeighbourFile> CreateDefaultNeighbour() noexcept;
  static boost::shared_ptr<OwnerFile> CreateDefaultOwner() noexcept;
  static boost::shared_ptr<PointsFile> CreateDefaultPoints() noexcept;
  static boost::shared_ptr<FacesFile> CreateFaces(const std::string& folder_name);

  ///Creates the folder structure needed by OpenFOAM
  static void CreateFolders(const std::string& folder_name);

  static boost::shared_ptr<Filenames> CreateFilenames() noexcept;
  static boost::shared_ptr<NeighbourFile> CreateNeighbour(const std::string& folder_name);
  static boost::shared_ptr<OwnerFile> CreateOwner(const std::string& folder_name);
  static boost::shared_ptr<PointsFile> CreatePoints(const std::string& folder_name);


  #ifndef NDEBUG
  static void Test() noexcept;
  #endif
};

///Write all info to a single stream. Use CreateCopy to write all info
///to an OpenFOAM folder structure with multiple files
std::ostream& operator<<(std::ostream& os, const Files& files) noexcept;

bool operator==(const Files& lhs, const Files& rhs) noexcept;
bool operator!=(const Files& lhs, const Files& rhs) noexcept;

} //~namespace foam
} //~namespace ribi

#endif // RIBI_OPENFOAMFILES_H

 

 

 

 

 

./CppOpenFoam/openfoamfiles.cpp

 

#include "openfoamfiles.h"

#include <cassert>
#include <fstream>
#include <iostream>
#include <map>
#include <set>
#include <sstream>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#include <boost/make_shared.hpp>

#include <QFile>

#include "fileio.h"

#include "openfoamboundaryfile.h"
#include "openfoamfacesfile.h"
#include "openfoamneighbourfile.h"
#include "openfoamownerfile.h"
#include "openfoamfilenames.h"
#include "openfoampointsfile.h"
#include "testtimer.h"
#include "trace.h"
#pragma GCC diagnostic pop

/*
ribi::foam::Files::Files(const std::string& folder_name)
  : m_boundary(CreateBoundary(folder_name)),
    m_faces(CreateFaces(folder_name)),
    m_neighbour(CreateNeighbour(folder_name)),
    m_owner(CreateOwner(folder_name)),
    m_points(CreatePoints(folder_name))
{
  #ifndef NDEBUG
  Test();
  #endif
  assert(ribi::fileio::FileIo().IsFolder(folder_name));
  assert(m_boundary);
  assert(m_faces);
  assert(m_neighbour);
  assert(m_owner);
  assert(m_points);
}
*/

ribi::foam::Files::Files(
  const boost::shared_ptr<BoundaryFile> boundary,
  const boost::shared_ptr<FacesFile> faces,
  const boost::shared_ptr<NeighbourFile> neighbour,
  const boost::shared_ptr<OwnerFile> owner,
  const boost::shared_ptr<PointsFile> points
) : m_boundary(boundary),
    m_faces(faces),
    m_neighbour(neighbour),
    m_owner(owner),
    m_points(points)
{
  #ifndef NDEBUG
  Test();
  #endif
  assert(m_boundary);
  assert(m_faces);
  assert(m_neighbour);
  assert(m_owner);
  assert(m_points);

  #ifndef NDEBUG
  CheckMe();
  #endif

}

ribi::foam::Files::Files(const Files& other)
  : m_boundary(boost::make_shared<BoundaryFile>(*other.m_boundary)),
    m_faces(boost::make_shared<FacesFile>(*other.m_faces)),
    m_neighbour(boost::make_shared<NeighbourFile>(*other.m_neighbour)),
    m_owner(boost::make_shared<OwnerFile>(*other.m_owner)),
    m_points(boost::make_shared<PointsFile>(*other.m_points))
{

  #ifndef NDEBUG
  Test();
  #endif
  assert(m_boundary);
  assert(m_faces);
  assert(m_neighbour);
  assert(m_owner);
  assert(m_points);

  assert(*m_boundary == *other.m_boundary && "Must be a copy");
  assert( m_boundary !=  other.m_boundary && "Must be a deep copy");
  assert(*m_faces == *other.m_faces && "Must be a copy");
  assert( m_faces !=  other.m_faces && "Must be a deep copy");

  assert(*m_neighbour == *other.m_neighbour && "Must be a copy");
  assert( m_neighbour !=  other.m_neighbour && "Must be a deep copy");

  assert(*m_owner == *other.m_owner && "Must be a copy");
  assert( m_owner !=  other.m_owner && "Must be a deep copy");

  assert(*m_points == *other.m_points && "Must be a copy");
  assert( m_points !=  other.m_points && "Must be a deep copy");

  #ifndef NDEBUG
  CheckMe();
  #endif
}

void ribi::foam::Files::CheckMe() const
{
  assert(m_faces);
  assert(m_points);
  const FaceIndex n_faces { FaceIndex(static_cast<int>(this->m_faces->GetItems().size())) };
  const PointIndex n_points { PointIndex(static_cast<int>(this->m_points->GetItems().size())) };

  TRACE("CheckMe: 'boundary' file individuals items");
  for (const BoundaryFileItem& item: m_boundary->GetItems())
  {
    std::stringstream s;
    s << "Error in 'boundary' file in this item:\n"
      << '\n'
      << item << '\n'
      << '\n';
    if (item.GetNfaces() <= 0)
    {
      s << "nFaces (" << item.GetNfaces() << ") must be a positive non-zero value";
      throw std::logic_error(s.str());
    }
    if (item.GetStartFace() > n_faces)
    {
      s << "startFace (" << item.GetStartFace() << ") beyond number of faces (" << n_faces << ")";
      throw std::logic_error(s.str());
    }
    if (item.GetStartFace() + FaceIndex(item.GetNfaces()) > n_faces)
    {
      s << "startFace (" << item.GetStartFace() << ")"
        << " + nFaces (" << n_faces << ")"
        << " = " << (item.GetStartFace() + FaceIndex(item.GetNfaces()))
        << " is beyond number of faces (" << n_faces << ")"
        ;
      throw std::logic_error(s.str());
    }
  }
  TRACE("CheckMe: 'boundary' file: no ranges should overlap");
  const int n_boundary_items { static_cast<int>(m_boundary->GetItems().size()) };
  for (int i=0; i!=n_boundary_items; ++i)
  {
    const BoundaryFileItem item_i = m_boundary->GetItems()[i];
    const FaceIndex first_i = item_i.GetStartFace();
    assert(first_i.Get() >= 0);
    assert(item_i.GetNfaces() >= 0);
    const FaceIndex last_i = first_i + FaceIndex(item_i.GetNfaces());
    for (int j=0; j!=n_boundary_items; ++j)
    {
      if (i == j) continue;
      const BoundaryFileItem item_j = m_boundary->GetItems()[j];
      const FaceIndex first_j = item_j.GetStartFace();
      assert(item_j.GetNfaces() >= 0);
      const FaceIndex last_j = first_j + FaceIndex(item_j.GetNfaces());
      if ( (first_i >= first_j && first_i < last_j)
        || (last_i  >  first_j && last_i  < last_j)
        || (first_j >= first_i && first_j < last_i)
        || (last_j  >  first_i && last_j  < last_i)
      )
      {
        TRACE(*m_boundary);
        std::stringstream s;
        s << "Error in 'boundary' file in these items:\n"
          << '\n'
          << item_i << '\n'
          << '\n'
          << item_j << '\n'
          << '\n'
          << "Face index ranges overlap: "
          << "[" << first_i << "," << last_i << "> and "
          << "[" << first_j << "," << last_j << ">";
        throw std::logic_error(s.str());
      }
    }
  }
  //
  TRACE("CheckMe: 'faces' files: point indices must be valid");
  for (const FacesFileItem& item: m_faces->GetItems())
  {
    for (const PointIndex& index: item.GetPointIndices())
    {
      assert(index.Get() >= 0);
      if (index >= n_points)
      {
        std::stringstream s;
        s << "Error in 'faces' file in this item:\n"
          << '\n'
          << item << '\n'
          << '\n'
          << "point index (" << index << ") beyond number of points (" << n_points << ")"
        ;
        throw std::logic_error(s.str());

      }
    }
  }
  const bool do_check_doubles = false;
  if (do_check_doubles)
  {
    TRACE("CheckMe: 'faces' files: detect doublures: START");
    {
      for (FaceIndex i = FaceIndex(0); i!=n_faces; ++i)
      {
        std::vector<PointIndex> v_i { m_faces->GetItem(i).GetPointIndices() };
        std::sort(v_i.begin(),v_i.end());
        for (FaceIndex j = FaceIndex(0); j!=n_faces; ++j)
        {
          if (i == j) continue;
          std::vector<PointIndex> v_j { m_faces->GetItem(j).GetPointIndices() };
          std::sort(v_j.begin(),v_j.end());
          if (v_i == v_j)
          {
            std::stringstream s;
            s << "Error in 'faces' file in these items:\n"
              << "\n"
              << "Item " << i << ": " << m_faces->GetItem(i) << '\n'
              << "Item " << j << ": " << m_faces->GetItem(j) << '\n'
              << "\n"
              << "Faces at index " << i << " and " << j << " consist of the same Point indices";
            ;
            throw std::logic_error(s.str());

          }
        }

      }
    }
  }
  else
  {
    TRACE("CheckMe: 'faces' files: detect doublures: SKIP");
  }

  TRACE("CheckMe: 'owner' files");
  if (m_owner->GetItems().size() != m_faces->GetItems().size())
  {
    std::stringstream s;
    s << "The file 'owner' has a different amount of faces than 'faces':\n"
      << "'faces' has " << m_faces->GetItems().size()
      << ", where 'owner' has " << m_owner->GetItems().size()
      << '\n'
    ;
    throw std::logic_error(s.str());
  }

  #ifdef SURE_THIS_CODE_CANNOT_BE_REUSED_20131212
  //Faces that have the same owner (which is a cell index) are member of the same cell
  //Each point index of all faces must be present at least one times: at least three faces are
  //needed at each vertex to form an enclosing/non-leaking cell surface, yet not all faces
  //are owned by each cell
  //Because each point index must be present once, it has no use collecting these
  {
    std::map<CellIndex,std::multiset<PointIndex>> m;
    for (FaceIndex face_index = FaceIndex(0); face_index!=n_faces; ++face_index)
    {
      //Find the point indices of this face
      const std::vector<PointIndex> p { m_faces->GetItem(face_index).GetPointIndices() };

      //Find the owner of this face
      const CellIndex c { m_owner->GetItem(face_index).GetCellIndex() };

      //Add the combination to m
      if (m.find(c) == m.end()) { m.insert(std::make_pair(c,std::multiset<PointIndex>())); }
      assert(m.find(c) != m.end());
      std::copy(p.begin(),p.end(),std::inserter(m.find(c)->second,m.find(c)->second.begin()));
    }
    //Check that each point index is present at least twice
    for (const std::pair<CellIndex,std::multiset<PointIndex>>& s: m)
    {
      for (const PointIndex& i: s.second)
      {
        const int count = s.second.count(i);
        if (count < 2)
        {
          TRACE(*m_owner);
          TRACE(*m_faces);
          std::stringstream str;
          str
            << "Error in 'owner' and 'faces' file combination:\n"
            << "The file 'owner' has faces owned by the same cell,"
            << "of which these faces do not cover each vertex with at least two times\n"
            << '\n'
            << "In this case, cell index " << s.first
            << " its faces have a point index " << i << " that is only a member of "
            << count << " faces"
          ;
          throw std::logic_error(str.str());

        }
      }
    }
  }
  #endif
  TRACE("CheckMe finished successfully");
}

boost::shared_ptr<ribi::foam::BoundaryFile> ribi::foam::Files::CreateBoundary(
  const std::string& folder_name)
{
  std::cout << (__func__) << std::endl;

  assert(ribi::fileio::FileIo().IsFolder(folder_name));

  const std::string filename(
    (folder_name.empty() ? folder_name : folder_name + fileio::FileIo().GetPathSeperator())
    + CreateFilenames()->GetBoundary()
  );
  #ifndef NDEBUG
  if (!fileio::FileIo().IsRegularFile(filename))
  {
    TRACE(filename);
    TRACE("BREAK");
  }
  #endif

  assert(fileio::FileIo().IsRegularFile(filename));

  std::ifstream is(filename.c_str());

  try
  {

    const boost::shared_ptr<ribi::foam::BoundaryFile> p {
      new ribi::foam::BoundaryFile(filename)
    };

    assert(p);
    return p;
  }
  catch(std::runtime_error& e)
  {

    std::stringstream s;
    s << "File '" << filename << "' is not an OpenFOAM 'boundary' file: "
      << e.what();
    TRACE(s.str());
    throw std::runtime_error(s.str());
  }
}

void ribi::foam::Files::CreateCopy(
  const ribi::foam::Files& files,
  const std::string copy_folder_name) noexcept
{
  #ifndef NDEBUG
  if (fileio::FileIo().IsFolder(copy_folder_name))
  {
    TRACE(copy_folder_name);
  }
  #endif
  assert(!fileio::FileIo().IsFolder(copy_folder_name)
    && "Cannot make a copy in an existing folder");

  CreateFolders(copy_folder_name);
  //boundary
  {
    const std::string destination_path {
        copy_folder_name
      + fileio::FileIo().GetPathSeperator()
      + BoundaryFile::GetDefaultHeader().GetLocation()
      + fileio::FileIo().GetPathSeperator()
      + BoundaryFile::GetDefaultHeader().GetObject()
    };
    std::ofstream f(destination_path.c_str());
    f << *files.GetBoundary();
  }
  //faces
  {
    const std::string destination_path {
        copy_folder_name
      + fileio::FileIo().GetPathSeperator()
      + FacesFile::GetDefaultHeader().GetLocation()
      + fileio::FileIo().GetPathSeperator()
      + FacesFile::GetDefaultHeader().GetObject()
    };
    std::ofstream f(destination_path.c_str());
    f << *files.GetFaces();
  }
  //neighbour
  {
    const std::string destination_path {
        copy_folder_name
      + fileio::FileIo().GetPathSeperator()
      + NeighbourFile::GetDefaultHeader().GetLocation()
      + fileio::FileIo().GetPathSeperator()
      + NeighbourFile::GetDefaultHeader().GetObject()
    };
    std::ofstream f(destination_path.c_str());
    f << *files.GetNeighbour();
  }
  //owner
  {
    const std::string destination_path {
        copy_folder_name
      + fileio::FileIo().GetPathSeperator()
      + OwnerFile::GetDefaultHeader().GetLocation()
      + fileio::FileIo().GetPathSeperator()
      + OwnerFile::GetDefaultHeader().GetObject()
    };
    std::ofstream f(destination_path.c_str());
    f << *files.GetOwner();
  }
  //points
  {
    const std::string destination_path {
        copy_folder_name
      + fileio::FileIo().GetPathSeperator()
      + PointsFile::GetDefaultHeader().GetLocation()
      + fileio::FileIo().GetPathSeperator()
      + PointsFile::GetDefaultHeader().GetObject()
    };
    std::ofstream f(destination_path.c_str());
    f << *files.GetPoints();
  }


  try
  {
    assert(Files(copy_folder_name) == files
      && "Resulting Files must be same");
  }
  catch (std::runtime_error& e)
  {
    TRACE(e.what());
    assert(!"Resulting Files must be same");
  }
}

boost::shared_ptr<ribi::foam::BoundaryFile> ribi::foam::Files::CreateDefaultBoundary() noexcept
{
  const boost::shared_ptr<BoundaryFile> p {
    new BoundaryFile
  };
  assert(p);
  return p;
}

boost::shared_ptr<ribi::foam::FacesFile> ribi::foam::Files::CreateDefaultFaces() noexcept
{
  const boost::shared_ptr<FacesFile> p {
    new FacesFile
  };
  assert(p);
  return p;
}

boost::shared_ptr<ribi::foam::NeighbourFile> ribi::foam::Files::CreateDefaultNeighbour() noexcept
{
  const boost::shared_ptr<NeighbourFile> p {
    new NeighbourFile
  };
  assert(p);
  return p;
}

boost::shared_ptr<ribi::foam::OwnerFile> ribi::foam::Files::CreateDefaultOwner() noexcept
{
  const boost::shared_ptr<OwnerFile> p {
    new OwnerFile
  };
  assert(p);
  return p;
}

boost::shared_ptr<ribi::foam::PointsFile> ribi::foam::Files::CreateDefaultPoints() noexcept
{
  const boost::shared_ptr<PointsFile> p {
    new PointsFile
  };
  assert(p);
  return p;
}

boost::shared_ptr<ribi::foam::FacesFile> ribi::foam::Files::CreateFaces(
  const std::string& folder_name)
{
  std::cout << (__func__) << std::endl;
  assert(ribi::fileio::FileIo().IsFolder(folder_name));
  const std::string filename(
    (folder_name.empty() ? folder_name : folder_name + fileio::FileIo().GetPathSeperator())
    + CreateFilenames()->GetFaces()
  );
  //std::ifstream is(filename.c_str());
  boost::shared_ptr<ribi::foam::FacesFile> p {
    new ribi::foam::FacesFile(filename)
  };
  assert(p);
  return p;
}

boost::shared_ptr<ribi::foam::Filenames> ribi::foam::Files::CreateFilenames() noexcept
{
  const boost::shared_ptr<ribi::foam::Filenames> p {
    new Filenames
  };
  assert(p);
  return p;
}

void ribi::foam::Files::CreateFolders(const std::string& folder_name)
{
  {
    const std::string s { fileio::FileIo().GetPathSeperator() };
    const std::string f { folder_name + s + "constant" };
    if (!fileio::FileIo().IsFolder(f)) { fileio::FileIo().CreateFolder(f); }
    assert(fileio::FileIo().IsFolder(f));
  }
  {
    const std::string s { fileio::FileIo().GetPathSeperator() };
    const std::string f { folder_name + s + "constant" + s + "polyMesh" };
    if (!fileio::FileIo().IsFolder(f)) { fileio::FileIo().CreateFolder(f); }
    assert(fileio::FileIo().IsFolder(f));
  }
}

boost::shared_ptr<ribi::foam::NeighbourFile> ribi::foam::Files::CreateNeighbour(
  const std::string& folder_name)
{
  std::cout << (__func__) << std::endl;
  assert(ribi::fileio::FileIo().IsFolder(folder_name));
  const std::string filename(
    (folder_name.empty() ? folder_name : folder_name + fileio::FileIo().GetPathSeperator())
    + CreateFilenames()->GetNeighbour()
  );
  //std::ifstream is(filename.c_str());
  boost::shared_ptr<ribi::foam::NeighbourFile> p {
    new ribi::foam::NeighbourFile(filename)
  };
  assert(p);
  return p;
}

boost::shared_ptr<ribi::foam::OwnerFile> ribi::foam::Files::CreateOwner(
  const std::string& folder_name)
{
  std::cout << (__func__) << std::endl;
  assert(ribi::fileio::FileIo().IsFolder(folder_name));
  const std::string filename(
    (folder_name.empty() ? folder_name : folder_name + fileio::FileIo().GetPathSeperator())
    + CreateFilenames()->GetOwner()
  );

  const boost::shared_ptr<ribi::foam::OwnerFile> p {
    new ribi::foam::OwnerFile(filename)
  };
  //std::ifstream is(filename.c_str());
  //const boost::shared_ptr<ribi::foam::OwnerFile> p {
  //  new ribi::foam::OwnerFile(is)
  //};
  assert(p);
  return p;
}

boost::shared_ptr<ribi::foam::PointsFile> ribi::foam::Files::CreatePoints(
  const std::string& folder_name)
{
  std::cout << (__func__) << std::endl;
  assert(ribi::fileio::FileIo().IsFolder(folder_name));
  const std::string filename(
    (folder_name.empty() ? folder_name : folder_name + fileio::FileIo().GetPathSeperator())
    + CreateFilenames()->GetPoints()
  );
  //std::ifstream is(filename.c_str());
  boost::shared_ptr<ribi::foam::PointsFile> p {
    new ribi::foam::PointsFile(filename)
  };
  assert(p);
  return p;
}

std::vector<boost::shared_ptr<ribi::foam::Files>> ribi::foam::Files::CreateTestFiles() noexcept
{
  std::vector<boost::shared_ptr<ribi::foam::Files>> v;
  //Empty
  {
    const boost::shared_ptr<Files> files {
      new Files
    };
    assert(files);
    v.push_back(files);
  }
  //Complex from resources
  for (int i=0; i!=5; ++i)
  {
    const std::string folder_name = ribi::fileio::FileIo().GetTempFolderName();
    CreateTestFiles(folder_name,i);
    const boost::shared_ptr<Files> files {
      new Files(folder_name)
    };
    assert(files);
    v.push_back(files);
    ribi::fileio::FileIo().DeleteFolder(folder_name);
  }
  return v;
}

void ribi::foam::Files::CreateTestFiles(const std::string& folder_name, const int test_index)
{
  assert(test_index >= 0 && test_index < 5);

  CreateFolders(folder_name);

  //Read from testing file
  for (const std::string filename_base:
    {
      BoundaryFile::GetDefaultHeader().GetObject(),
      FacesFile::GetDefaultHeader().GetObject(),
      NeighbourFile::GetDefaultHeader().GetObject(),
      OwnerFile::GetDefaultHeader().GetObject(),
      PointsFile::GetDefaultHeader().GetObject()
    }
  )
  {
    std::string filename_appendix;
    switch (test_index)
    {
      case 0: filename_appendix = "_1x1x1"; break;
      case 1: filename_appendix = "_1x1x2"; break;
      case 2: filename_appendix = "_1x2x2"; break;
      case 3: filename_appendix = "_2x2x2"; break;
      case 4: filename_appendix = "_3x4x5"; break;
      default: assert(!"Should never get here");
        throw std::logic_error("foam::Files::CreateTestFiles: unknown test index");
    }
    assert(!filename_appendix.empty());
    const std::string filename = filename_base + filename_appendix;
    const std::string resources_path { ":/CppOpenFoam/files/" + filename };
    const std::string destination_path {
      folder_name
      + fileio::FileIo().GetPathSeperator()
      + "constant"
      + fileio::FileIo().GetPathSeperator()
      + "polyMesh"
      + fileio::FileIo().GetPathSeperator()
      + filename_base
    };
    QFile f(resources_path.c_str());
    f.copy(destination_path.c_str());
    assert(fileio::FileIo().IsRegularFile(destination_path));
  }
}

void ribi::foam::Files::Swap(const ribi::foam::FaceIndex& lhs, const ribi::foam::FaceIndex& rhs)
{
  assert(lhs != rhs);
  //Boundary
  {
    //Cleanest interface I could think of
    //m_boundary->Swap(lhs,rhs);
    /*

    boost::shared_ptr<int> lhs_n_faces;
    if (m_boundary->CanGetItem(lhs))
    {
      lhs_n_faces.reset(new int(m_boundary->Find(lhs).GetNfaces()));
    }
    boost::shared_ptr<int> rhs_n_faces;
    {

    }
    const BoundaryIndex lhs_boundary_index = m_boundary->GetItem(lhs).GetCellIndex();
    const BoundaryIndex rhs_boundary_index = m_owner->GetItem(rhs).GetCellIndex();

    //Set swapped
    m_owner->SetItem(lhs,OwnerFileItem(rhs_cell_index));
    m_owner->SetItem(rhs,OwnerFileItem(lhs_cell_index));
   */
  }
  //Neighbour
  {
    //Can only swap two cellIndices when either both of them are absent
    //(both cells are boundary cells)
    //or both of them are present
    //(both cells are non-boundary cells)
    /*
    const bool lhs_is_boundary = m_neighbour->CanGetItem(lhs);
    const bool rhs_is_boundary = m_neighbour->CanGetItem(rhs);
    assert(lhs_is_boundary == rhs_is_boundary
      && "Can only swap two boundary or two non-boundary faces");

    if (lhs_is_boundary != rhs_is_boundary)
    {
      throw std::logic_error("Can only swap two boundary or two non-boundary faces");
    }

    if (lhs_is_boundary)
    {
      assert(rhs_is_boundary);
      //Done! Boundary cells have no neighbours
    }
    else
    {
      const CellIndex lhs_cell_index = m_neighbour->GetItem(lhs).GetCellIndex();
      const CellIndex rhs_cell_index = m_neighbour->GetItem(rhs).GetCellIndex();

      //Set swapped
      m_neighbour->SetItem(lhs,NeighbourFileItem(rhs_cell_index));
      m_neighbour->SetItem(rhs,NeighbourFileItem(lhs_cell_index));
    }
    */
  }
  //Owner
  {
    const CellIndex lhs_cell_index = m_owner->GetItem(lhs).GetCellIndex();
    const CellIndex rhs_cell_index = m_owner->GetItem(rhs).GetCellIndex();

    //Set swapped
    m_owner->SetItem(lhs,OwnerFileItem(rhs_cell_index));
    m_owner->SetItem(rhs,OwnerFileItem(lhs_cell_index));
  }
}

#ifndef NDEBUG
void ribi::foam::Files::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
  //operator==
  {
    const Files f;
    assert(f == f);
    const Files g;
    assert(f == g);
    assert(g == f);
    assert(g == g);
  }
  //operator==
  {
    const Files f;
    assert(f == f);
    const Files g;
    assert(f == g);
    assert(g == f);
    assert(g == g);
  }
  //operator!=
  {
    const std::vector<boost::shared_ptr<ribi::foam::Files>> v { Files::CreateTestFiles() };
    const std::size_t sz = v.size();
    for (std::size_t i=0; i!=sz; ++i)
    {
      for (std::size_t j=0; j!=sz; ++j)
      {
        if (i == j) { assert(v[i] == v[j]); }
        if (i != j) { assert(v[i] != v[j]); }
      }
    }
  }
  //CreateCopy
  for (int test_index=0; test_index!=5; ++test_index)
  {
    const std::string temp_folder_source = ribi::fileio::FileIo().GetTempFolderName();
    {
      assert(!ribi::fileio::FileIo().IsFolder(temp_folder_source));
      CreateTestFiles(temp_folder_source,test_index);
    }
    const Files source(temp_folder_source);
    const std::string temp_folder_target = ribi::fileio::FileIo().GetTempFolderName();
    Files::CreateCopy(source,temp_folder_target);
    const Files target(temp_folder_target);
    assert(source == target);
    ribi::fileio::FileIo().DeleteFolder(temp_folder_source);
    ribi::fileio::FileIo().DeleteFolder(temp_folder_target);
  }
  //Swap faces
  {
    const std::string temp_folder = ribi::fileio::FileIo().GetTempFolderName();
    assert(!ribi::fileio::FileIo().IsFolder(temp_folder));
    CreateTestFiles(temp_folder,3); //3 = 2x2x2 cubes
    const Files f(temp_folder);
    assert(f == f);
    Files g(temp_folder);
    assert(f == g);
    assert(g == f);
    assert(g == g);
    const FaceIndex i(1);
    const FaceIndex j(11);
    g.Swap(i,j);
    assert(g != f);
    assert(f != g);
    g.Swap(i,j);
    assert(f == g);
    ribi::fileio::FileIo().DeleteFolder(temp_folder);
    assert(!ribi::fileio::FileIo().IsFolder(temp_folder));

  }
}
#endif

bool ribi::foam::operator==(const ribi::foam::Files& lhs, const ribi::foam::Files& rhs) noexcept
{
  //Split function for ease in debugging
  const bool verbose{false};
  if (*lhs.GetBoundary()!= *rhs.GetBoundary())
  {
    if (verbose)
    {
      TRACE("Boundaries differ:");
      TRACE(*lhs.GetBoundary());
      TRACE(*rhs.GetBoundary());
    }
    return false;
  }
  if (*lhs.GetFaces() != *rhs.GetFaces())
  {
    if (verbose)
    {
      TRACE("Faces differ:");
      TRACE(*lhs.GetFaces());
      TRACE(*rhs.GetFaces());
    }
    return false;
  }
  if (*lhs.GetNeighbour() != *rhs.GetNeighbour())
  {
    if (verbose)
    {
      TRACE("Neighbours differ:");
      TRACE(*lhs.GetNeighbour());
      TRACE(*rhs.GetNeighbour());
    }
    return false;
  }
  if (*lhs.GetOwner() != *rhs.GetOwner())
  {
    if (verbose)
    {
      TRACE("Owners differ:");
      TRACE(*lhs.GetOwner());
      TRACE(*rhs.GetOwner());
    }
    return false;
  }
  if (*lhs.GetPoints() != *rhs.GetPoints())
  {
    if (verbose)
    {
      TRACE("Points differ:");
      TRACE(*lhs.GetPoints());
      TRACE(*rhs.GetPoints());
    }
    return false;
  }
  return true;
}

bool ribi::foam::operator!=(const ribi::foam::Files& lhs, const ribi::foam::Files& rhs) noexcept
{
  return !(lhs == rhs);
}

std::ostream& ribi::foam::operator<<(std::ostream& os, const Files& files) noexcept
{
  os
    << (*files.GetBoundary()) << '\n'
    << (*files.GetFaces())    << '\n'
    << (*files.GetNeighbour()) << '\n'
    << (*files.GetOwner())     << '\n'
    << (*files.GetPoints())
  ;
  return os;
}

 

 

 

 

 

./CppOpenFoam/openfoamfvschemesfile.h

 

#ifndef RIBI_OPENFOAMFVSCHEMESFILE_H
#define RIBI_OPENFOAMFVSCHEMESFILE_H

#include <iosfwd>
#include <vector>
#include "openfoamfwd.h"
#include "openfoamheader.h"

namespace ribi {
namespace foam {

///Reads and writes an OpenFOAM thermophysicalProperties file
struct FvSchemesFile
{
  explicit FvSchemesFile(
    const Header header = GetDefaultHeader()
  );

  static Header GetDefaultHeader() noexcept;
  const Header& GetHeader() const noexcept { return m_header; }

  private:

  ///The OpenFOAM header
  Header m_header;

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif

  friend std::ostream& operator<<(std::ostream& os, const FvSchemesFile& f) noexcept;
};

std::ostream& operator<<(std::ostream& os, const FvSchemesFile& f) noexcept;

} //~namespace foam
} //~namespace ribi

#endif // RIBI_OPENFOAMFVSCHEMESFILE_H

 

 

 

 

 

./CppOpenFoam/openfoamfvschemesfile.cpp

 

#include "openfoamfvschemesfile.h"

#include <cassert>
#include <fstream>
#include <iostream>
#include <stdexcept>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"

#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/lexical_cast.hpp>

#include <QFile>

#include "fileio.h"

#include "openfoamheader.h"
#include "testtimer.h"
#include "trace.h"
#pragma GCC diagnostic pop


ribi::foam::FvSchemesFile::FvSchemesFile(
  const Header header
) : m_header(header)
{
  #ifndef NDEBUG
  Test();
  #endif
}

ribi::foam::Header ribi::foam::FvSchemesFile::GetDefaultHeader() noexcept
{
  return Header("dictionary","system","","fvSchemes");
}

#ifndef NDEBUG
void ribi::foam::FvSchemesFile::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
}
#endif

std::ostream& ribi::foam::operator<<(std::ostream& os, const FvSchemesFile& f) noexcept
{
  os
    << f.GetHeader() << '\n'
    << "" << '\n'
    << "ddtSchemes\n"
    << "{\n"
    << "  default Euler;\n"
    << "}\n"
    << "\n"
    << "gradSchemes\n"
    << "{\n"
    << "  default Gauss linear;\n"
    << "}\n"
    << "\n"
    << "divSchemes\n"
    << "{\n"
    << "  default none;\n"
    << "  div(phi,U) Gauss limitedLinearV 1;\n"
    << "  div(phi,e) Gauss limitedLinear 1;\n"
    << "  div(phid,p) Gauss limitedLinear 1;\n"
    << "  div(phi,K) Gauss limitedLinear 1;\n"
    << "  div(phiv,p) Gauss limitedLinear 1;\n"
    << "  div(phi,k) Gauss upwind;\n"
    << "  div(phi,epsilon) Gauss upwind;\n"
    << "  div((muEff*dev2(T(grad(U))))) Gauss linear;\n"
    << "}\n"
    << "\n"
    << "laplacianSchemes\n"
    << "{\n"
    << "  default Gauss linear corrected;\n"
    << "}\n"
    << "\n"
    << "interpolationSchemes\n"
    << "{\n"
    << "  default linear;\n"
    << "}\n"
    << "\n"
    << "snGradSchemes\n"
    << "{\n"
    << "  default corrected;\n"
    << "}\n"
    << "\n"
    << "fluxRequired\n"
    << "{\n"
    << "  default no;\n"
    << "  p;\n"
    << "}\n";
  return os;
}

 

 

 

 

 

./CppOpenFoam/openfoamfvsolutionfile.h

 

#ifndef RIBI_OPENFOAMFVSOLUTIONFILE_H
#define RIBI_OPENFOAMFVSOLUTIONFILE_H

#include <iosfwd>
#include <vector>
#include "openfoamfwd.h"
#include "openfoamheader.h"

namespace ribi {
namespace foam {

///Reads and writes an OpenFOAM thermophysicalProperties file
struct FvSolutionFile
{
  explicit FvSolutionFile(
    const Header header = GetDefaultHeader()
  );

  static Header GetDefaultHeader() noexcept;
  const Header& GetHeader() const noexcept { return m_header; }

  private:

  ///The OpenFOAM header
  Header m_header;

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif

  friend std::ostream& operator<<(std::ostream& os, const FvSolutionFile& f) noexcept;
};

std::ostream& operator<<(std::ostream& os, const FvSolutionFile& f) noexcept;

} //~namespace foam
} //~namespace ribi

#endif // RIBI_OPENFOAMFVSOLUTIONFILE_H

 

 

 

 

 

./CppOpenFoam/openfoamfvsolutionfile.cpp

 

#include "openfoamfvsolutionfile.h"

#include <cassert>
#include <fstream>
#include <iostream>
#include <stdexcept>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"

#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/lexical_cast.hpp>

#include <QFile>

#include "fileio.h"

#include "openfoamheader.h"
#include "testtimer.h"
#include "trace.h"
#pragma GCC diagnostic pop


ribi::foam::FvSolutionFile::FvSolutionFile(
  const Header header
) : m_header(header)
{
  #ifndef NDEBUG
  Test();
  #endif
}

ribi::foam::Header ribi::foam::FvSolutionFile::GetDefaultHeader() noexcept
{
  return Header("dictionary","system","","fvSolution");
}

#ifndef NDEBUG
void ribi::foam::FvSolutionFile::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
}
#endif

std::ostream& ribi::foam::operator<<(std::ostream& os, const FvSolutionFile& f) noexcept
{
  os
    << f.GetHeader() << '\n';
  return os;
}



/*

#include "trianglemeshbuilder.h"

#include <sstream>

const std::string ribi::trim::TriangleMeshBuilder::CreateOpenFoamFvSolution() const noexcept
{
  std::stringstream s;
  s
    << "FoamFile\n"
    << "{\n"
    << "    version     2.0;\n"
    << "    format      ascii;\n"
    << "    class       dictionary;\n"
    << "    location    \"system\";\n"
    << "    object      fvSolution;\n"
    << "}\n"
    << "\n"
    << "solvers\n"
    << "{\n"
    << "    \"rho.*\"\n"
    << "    {\n"
    << "        solver          diagonal;\n"
    << "    }\n"
    << "\n"
    << "    \"p.*\"\n"
    << "    {\n"
    << "        solver          PBiCG;\n"
    << "        preconditioner  DILU;\n"
    << "        tolerance       1e-08;\n"
    << "        relTol          0;\n"
    << "    }\n"
    << "\n"
    << "    \"(U|e|R).*\"\n"
    << "    {\n"
    << "        $p;\n"
    << "        tolerance       1e-05;\n"
    << "    }\n"
    << "\n"
    << "    \"(k|epsilon).*\"\n"
    << "    {\n"
    << "        $p;\n"
    << "        tolerance       1e-08;\n"
    << "    }\n"
    << "}\n"
    << "\n"
    << "PIMPLE\n"
    << "{\n"
    << "    nOuterCorrectors 2;\n"
    << "    nCorrectors      1;\n"
    << "    nNonOrthogonalCorrectors 0;\n"
    << "}\n";
  return s.str();
}


*/

 

 

 

 

 

./CppOpenFoam/openfoamfwd.h

 

#ifndef RIBI_OPENFOAMFWD_H
#define RIBI_OPENFOAMFWD_H

namespace ribi {

//struct Coordinat3D;

namespace foam {

struct Boundary;
struct BoundaryFile;
struct BoundaryFileItem;
struct BoundaryIndex;
struct Cell;
struct CellIndex;
struct Face;
struct FaceIndex;
struct FacesFile;
struct FacesFileItem;
struct Filenames;
struct Files;
struct Header;
struct Mesh;
struct NeighbourFile;
struct NeighbourFileItem;
struct OwnerFile;
struct OwnerFileItem;
struct PointIndex;
struct PointsFile;
struct PointsFileItem;

} //~namespace foam
} //~namespace ribi

#endif // RIBI_OPENFOAMFWD_H

 

 

 

 

 

./CppOpenFoam/openfoamheader.h

 

#ifndef RIBI_OPENFOAMHEADER_H
#define RIBI_OPENFOAMHEADER_H

#include <iosfwd>
#include <string>

namespace ribi {
namespace foam {

///The header that is above all OpenFoam files
struct Header
{
  ///In order of appearance in the text
  explicit Header(
    const std::string& class_name = "",
    const std::string& location   = "",
    const std::string& note       = "",
    const std::string& object     = "",
    const std::string& version    = "2.0"
  );

  ///Remove comments from a file
  static void CleanFile(const std::string& filename) noexcept;

  const std::string& GetClass() const noexcept { return m_class_name; }
  const std::string& GetLocation() const noexcept { return m_location; }
  const std::string& GetNote() const noexcept { return m_note; }
  const std::string& GetObject() const noexcept { return m_object; }
  const std::string& GetVersion() const noexcept { return m_version; }

  ///A header consists out of multiple lines
  ///(1) header name
  ///(2) bracket open
  ///(3) version
  ///(4) format
  ///(5) class
  ///(6) location
  ///(7) object
  ///(8) bracket close
  static constexpr int GetNumberOfLines() { return 8; }

  void SetVersion(const std::string& version) noexcept { m_version = version; }


  private:

  std::string m_class_name;
  std::string m_location;
  std::string m_note;
  std::string m_object;
  std::string m_version;

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif

  friend std::istream& operator>>(std::istream& is, Header& h);
};

bool operator==(const Header& lhs, const Header& rhs) noexcept;
bool operator!=(const Header& lhs, const Header& rhs) noexcept;
std::ostream& operator<<(std::ostream& os, const Header& f) noexcept;

///Read the header of an OpenFOAM file.
///Throws std::runtime_error if file is incorrectly formed
std::istream& operator>>(std::istream& is, Header& h);

} //~namespace foam
} //~namespace ribi

#endif // RIBI_OPENFOAMHEADER_H

 

 

 

 

 

./CppOpenFoam/openfoamheader.cpp

 

#include "openfoamheader.h"

#include <cassert>
#include <ostream>
#include <sstream>
#include <stdexcept>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#include <boost/algorithm/string/trim.hpp>

#include "fileio.h"
#include "testtimer.h"
#include "trace.h"
#pragma GCC diagnostic pop

ribi::foam::Header::Header(
    const std::string& class_name,
    const std::string& location,
    const std::string& note,
    const std::string& object,
    const std::string& version
  )
  : m_class_name(class_name),
    m_location(location),
    m_note(note),
    m_object(object),
    m_version(version)
{
  #ifndef NDEBUG
  Test();
  assert( (location.empty() || location[0] != '\"' )
    && "A location may not start with a quotation mark"
  );
  assert( (location.empty() || location[ location.size() - 1 ] != '\"' )
    && "A location may not end with a quotation mark"
  );
  #endif
}

void ribi::foam::Header::CleanFile(
  const std::string& filename) noexcept
{
  #ifndef NDEBUG
  if(!fileio::FileIo().IsRegularFile(filename))
  {
    TRACE("ERROR");
  }
  #endif

  assert(fileio::FileIo().IsRegularFile(filename));
  //v is dirty
  const std::vector<std::string> v { fileio::FileIo().FileToVector(filename) };
  //w will be clean
  std::vector<std::string> w;
  std::transform(v.begin(),v.end(),std::back_inserter(w),
    [](std::string s)
    {
      std::replace(s.begin(),s.end(),'\t',' ');
      boost::algorithm::trim(s);
      if (s.size() >= 2 && s.substr(0,2) == "//") s = std::string();
      return s;
    }
  );
  //w is clean
  assert(fileio::FileIo().IsRegularFile(filename));
  fileio::FileIo().VectorToFile(w,filename,fileio::CopyMode::allow_overwrite);
}


#ifndef NDEBUG
void ribi::foam::Header::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
  const Header h("some_name","some_location","some_note","some_object");
  std::stringstream s;
  s << h;
  Header i;
  s >> i;
  if (h != i)
  {
    TRACE(h);
    TRACE(i);
  }
  assert(h == i);
}
#endif

bool ribi::foam::operator==(const ribi::foam::Header& lhs, const ribi::foam::Header& rhs) noexcept
{
  const bool verbose{false};
  if (lhs.GetClass() != rhs.GetClass())
  {
    if (verbose)
    {
      TRACE("Classes differ:");
      TRACE(lhs.GetClass());
      TRACE(rhs.GetClass());
    }
    return false;
  }
  //Compare location independent of OS path seperator
  {
    std::string lhs_location = lhs.GetLocation();
    std::string rhs_location = rhs.GetLocation();
    std::replace(lhs_location.begin(),lhs_location.end(),'\\','/');
    std::replace(rhs_location.begin(),rhs_location.end(),'\\','/');
    if (lhs_location != rhs_location)
    {
      if (verbose)
      {
        TRACE("Locations differ:");
        TRACE(lhs.GetLocation());
        TRACE(rhs.GetLocation());
      }
      return false;
    }
  }
  if (lhs.GetObject() != rhs.GetObject())
  {
    if (verbose)
    {
      TRACE("Object differ:");
      TRACE(lhs.GetObject());
      TRACE(rhs.GetObject());
    }
    return false;
  }
  return true;
}

bool ribi::foam::operator!=(const ribi::foam::Header& lhs, const ribi::foam::Header& rhs) noexcept
{
  return !(lhs == rhs);
}

std::ostream& ribi::foam::operator<<(std::ostream& os, const Header& f) noexcept
{
  os
    << "FoamFile" << '\n'
    << "{" << '\n'
    << "  version  " << f.GetVersion()  << ";\n"
    << "  format   " << "ascii"         << ";\n"
    << "  class    " << f.GetClass()    << ";\n"
    << "  location \"" << f.GetLocation() << "\";\n"
    << "  object   " << f.GetObject()   << ";\n"
    << "}" << '\n'
  ;
  return os;
}

std::istream& ribi::foam::operator>>(std::istream& is, Header& h)
{
  {
    std::string title;
    is >> title;
    assert(is);
    while (title != "FoamFile")
    {
      assert(title.size() >= 2);

      //Eat comment
      if (title.substr(0,2) == "/*")
      {
        std::string s;
        while (s.size() < 2 || s.substr(s.size()-2,2) != "*/")
        {
          is >> s;
          assert(is);
        }
      }
      //Try reading title after comment again
      is >> title;
      assert(is);
    }
    if (title != "FoamFile")
    {
      std::stringstream s;
      s << "Stream incorrectly assumed to be an OpenFOAM header. "
        << "OpenFOAM header start with 'FoamFile'. "
        << "This file starts with  '"
        << title << "' instead";
      TRACE(s.str());
      throw std::runtime_error(s.str());
    }
  }
  {
    std::string bracket_open;
    is >> bracket_open;
    assert(is);
    assert(bracket_open == "{");
  }
  while (1)
  {
    std::string s;
    is >> s;
    assert(is);
    if (s == "version")
    {
      std::string t;
      is >> t;
      assert(is);
      //assert(t == "2.0;");
      h.m_version = t.substr(0,t.size() - 1);
      assert(h.m_version == "2.0");
    }
    else if (s == "format" )
    {
      std::string t;
      is >> t;
      assert(is);
      assert(t == "ascii;");
    }
    else if (s == "class"  )
    {
      std::string class_name;
      is >> class_name;
      assert(is);
      assert(class_name.back() == ';');
      class_name.pop_back();
      assert(class_name.back() != ';');
      h.m_class_name = class_name;
    }
    else if (s == "location")
    {
      std::string location;
      is >> location;
      assert(is);
      assert(location.size() > 3);
      assert(location[0] == '\"');
      assert(location[ location.size() - 2] == '\"');
      assert(location[ location.size() - 1] == ';');
      location = location.substr(1,location.size() - 3);

      assert( (location.empty() || location[0] != '\"' )
        && "A location may not start with a quotation mark"
      );
      assert( (location.empty() || location[ location.size() - 1 ] != '\"' )
        && "A location may not end with a quotation mark"
      );
      assert( (location.empty() || location[ location.size() - 1 ] != ';' )
        && "A location may not end with a semicolon"
      );

      h.m_location = location;
    }
    else if (s == "note")
    {
      //Read until ;
      std::string s;
      is >> s;
      assert(is);
      assert(!s.empty());
      while (s.back() != ';')
      {
        std::string t;
        is >> t;
        assert(is);
        s += t;
      }
      assert(s.back() == ';');
      s.pop_back();
      assert(s.back() != ';');
      h.m_note = s;
    }
    else if (s == "object")
    {
      std::string object;
      is >> object;
      assert(is);
      assert(object.back() == ';');
      object.pop_back();
      assert(object.back() != ';');
      h.m_object = object;
    }
    else if (s == "}")
    {
      break;
    }
  }
  return is;
}

 

 

 

 

 

./CppOpenFoam/openfoamhelper.h

 

#ifndef RIBI_OPENFOAMHELPER_H
#define RIBI_OPENFOAMHELPER_H

//#include <iosfwd>
//#include <string>
#include <vector>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/shared_ptr.hpp>
#ifndef _WIN32
#include <boost/geometry/geometries/polygon.hpp>
#endif
#include "openfoamfwd.h"
#pragma GCC diagnostic pop


namespace ribi {
namespace foam {



///Help adding constness a bit
template <class T>
std::vector<boost::shared_ptr<const T>> AddConst(
  const std::vector<boost::shared_ptr<T>> v)
{
  return std::vector<boost::shared_ptr<const T>>(std::begin(v),std::end(v));
}

std::string ToStr(const boost::geometry::model::point<double,3,boost::geometry::cs::cartesian>& p) noexcept;
std::string ToXml(const boost::geometry::model::point<double,3,boost::geometry::cs::cartesian>& p) noexcept;

bool operator==(
  const boost::geometry::model::point<double,3,boost::geometry::cs::cartesian>& lhs,
  const boost::geometry::model::point<double,3,boost::geometry::cs::cartesian>& rhs
) noexcept;

boost::geometry::model::point<double,3,boost::geometry::cs::cartesian> operator+(
  const boost::geometry::model::point<double,3,boost::geometry::cs::cartesian>& lhs,
  const boost::geometry::model::point<double,3,boost::geometry::cs::cartesian>& rhs
) noexcept;

boost::geometry::model::point<double,3,boost::geometry::cs::cartesian> operator/(
  const boost::geometry::model::point<double,3,boost::geometry::cs::cartesian>& lhs,
  const double factor
) noexcept;

boost::geometry::model::point<double,3,boost::geometry::cs::cartesian>& operator+=(
  boost::geometry::model::point<double,3,boost::geometry::cs::cartesian>& lhs,
  const boost::geometry::model::point<double,3,boost::geometry::cs::cartesian>& rhs
) noexcept;

boost::geometry::model::point<double,3,boost::geometry::cs::cartesian>& operator/=(
  boost::geometry::model::point<double,3,boost::geometry::cs::cartesian>& p,
  const double factor
) noexcept;

//Name of operator+
boost::geometry::model::point<double,3,boost::geometry::cs::cartesian> Add(
  const boost::geometry::model::point<double,3,boost::geometry::cs::cartesian>& lhs,
  const boost::geometry::model::point<double,3,boost::geometry::cs::cartesian>& rhs
) noexcept;

} //~namespace foam
} //~namespace ribi

#endif // RIBI_OPENFOAMHELPER_H

 

 

 

 

 

./CppOpenFoam/openfoamhelper.cpp

 

#include "openfoamhelper.h"

#include <sstream>
#include "xml.h"

boost::geometry::model::point<double,3,boost::geometry::cs::cartesian> ribi::foam::Add(
  const boost::geometry::model::point<double,3,boost::geometry::cs::cartesian>& lhs,
  const boost::geometry::model::point<double,3,boost::geometry::cs::cartesian>& rhs
) noexcept
{
  return lhs + rhs;
}

std::string ribi::foam::ToStr(const boost::geometry::model::point<double,3,boost::geometry::cs::cartesian>& p) noexcept
{
  std::stringstream s;
  s
    << "(" << boost::geometry::get<0>(p)
    << "," << boost::geometry::get<1>(p)
    << "," << boost::geometry::get<2>(p)
    << ")"
  ;

  return s.str();
}

std::string ribi::foam::ToXml(const boost::geometry::model::point<double,3,boost::geometry::cs::cartesian>& p) noexcept
{
  std::stringstream s;
  s
    << ribi::xml::ToXml("x",boost::geometry::get<0>(p))
    << ribi::xml::ToXml("y",boost::geometry::get<1>(p))
    << ribi::xml::ToXml("z",boost::geometry::get<2>(p));

  std::stringstream t;
  t << ribi::xml::ToXml("coordinat3d",s.str());
  return t.str();
}

bool ribi::foam::operator==(
  const boost::geometry::model::point<double,3,boost::geometry::cs::cartesian>& lhs,
  const boost::geometry::model::point<double,3,boost::geometry::cs::cartesian>& rhs
) noexcept
{
  return
       boost::geometry::get<0>(lhs) == boost::geometry::get<0>(rhs)
    && boost::geometry::get<1>(lhs) == boost::geometry::get<1>(rhs)
    && boost::geometry::get<2>(lhs) == boost::geometry::get<2>(rhs)
  ;
}

boost::geometry::model::point<double,3,boost::geometry::cs::cartesian> ribi::foam::operator+(
  const boost::geometry::model::point<double,3,boost::geometry::cs::cartesian>& lhs,
  const boost::geometry::model::point<double,3,boost::geometry::cs::cartesian>& rhs
) noexcept
{
  typedef std::remove_const<std::remove_reference<decltype(lhs)>::type>::type ReturnType;
  return ReturnType(
    boost::geometry::get<0>(lhs) + boost::geometry::get<0>(rhs),
    boost::geometry::get<1>(lhs) + boost::geometry::get<1>(rhs),
    boost::geometry::get<2>(lhs) + boost::geometry::get<2>(rhs)
  );
}

boost::geometry::model::point<double,3,boost::geometry::cs::cartesian>& ribi::foam::operator+=(
  boost::geometry::model::point<double,3,boost::geometry::cs::cartesian>& lhs,
  const boost::geometry::model::point<double,3,boost::geometry::cs::cartesian>& rhs
) noexcept
{
  lhs = lhs + rhs;
  return lhs;
}

boost::geometry::model::point<double,3,boost::geometry::cs::cartesian> ribi::foam::operator/(
  const boost::geometry::model::point<double,3,boost::geometry::cs::cartesian>& p,
  const double factor
) noexcept
{
  typedef std::remove_const<std::remove_reference<decltype(p)>::type>::type ReturnType;
  return ReturnType(
    boost::geometry::get<0>(p) / factor,
    boost::geometry::get<1>(p) / factor,
    boost::geometry::get<2>(p) / factor
  );
}

boost::geometry::model::point<double,3,boost::geometry::cs::cartesian>& ribi::foam::operator/=(
  boost::geometry::model::point<double,3,boost::geometry::cs::cartesian>& p,
  const double factor
) noexcept
{
  p = p / factor;
  return p;
}

 

 

 

 

 

./CppOpenFoam/openfoamkfile.h

 

#ifndef OPENFOAMKFILE_H
#define OPENFOAMKFILE_H

#include <iosfwd>
#include <vector>
#include "openfoamfwd.h"
#include "openfoamheader.h"

namespace ribi {
namespace foam {

///Reads and writes an OpenFOAM thermophysicalProperties file
struct KFile
{
  explicit KFile(
    const Header header = GetDefaultHeader()
  );

  static Header GetDefaultHeader() noexcept;
  const Header& GetHeader() const noexcept { return m_header; }

  private:
  Header m_header;

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif

  friend std::ostream& operator<<(std::ostream& os, const KFile& f) noexcept;
};

std::ostream& operator<<(std::ostream& os, const KFile& f) noexcept;

} //~namespace foam
} //~namespace ribi

#endif // OPENFOAMKFILE_H

 

 

 

 

 

./CppOpenFoam/openfoamkfile.cpp

 

#include "openfoamkfile.h"

#include <cassert>
#include <fstream>
#include <iostream>
#include <stdexcept>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"

#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/lexical_cast.hpp>

#include <QFile>

#include "fileio.h"

#include "openfoamheader.h"
#include "testtimer.h"
#include "trace.h"
#pragma GCC diagnostic pop


ribi::foam::KFile::KFile(
  const Header header
) : m_header(header)
{
  #ifndef NDEBUG
  Test();
  #endif
}

ribi::foam::Header ribi::foam::KFile::GetDefaultHeader() noexcept
{
  return Header("dictionary","system","","K");
}

#ifndef NDEBUG
void ribi::foam::KFile::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
}
#endif

std::ostream& ribi::foam::operator<<(std::ostream& os, const KFile& f) noexcept
{
  //No idea
  os
    << f.GetHeader() << '\n'
    << "" << '\n'
  ;
  return os;
}

 

 

 

 

 

./CppOpenFoam/openfoammesh.h

 

#ifndef RIBI_OPENFOAMMESH_H
#define RIBI_OPENFOAMMESH_H

#include <iosfwd>
#include <string>
#include <vector>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wunused-variable"
#include <boost/shared_ptr.hpp>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#ifndef _WIN32
#include <boost/geometry/geometries/polygon.hpp>
#endif
#include "openfoamfwd.h"
#pragma GCC diagnostic pop



namespace ribi {
namespace foam {

///Mesh contains the mesh of an OpenFOAM mesh in an indexless way
///A Mesh can be converted to a Files and vice versa
struct Mesh
{
  typedef boost::geometry::model::point<double,3,boost::geometry::cs::cartesian> Coordinat3D;

  ///Step #0
  ///Create Points so these can be shared over the Faces
  ///Create Cells so these can be shared over the Faces
  explicit Mesh(const Files& files) : Mesh(files,CreatePoints(files)) {}

  explicit 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<Coordinat3D>>& points
  );

  ///Write the Mesh to a Files
  Files CreateFiles() const noexcept;

  boost::shared_ptr<const Face> FindMostSimilarFace(
    const std::vector<Coordinat3D>& coordinats
  ) const;


  const std::vector<boost::shared_ptr<Boundary>>& GetBoundaries() noexcept { return m_boundaries; }
  const std::vector<boost::shared_ptr<Cell>>& GetCells() noexcept { return  m_cells; }
  const std::vector<boost::shared_ptr<      Face>>& GetFaces()       noexcept { return m_faces; }
  const std::vector<boost::shared_ptr<const Face>>  GetFaces() const noexcept;
  int GetNumberOfBoundaries() const noexcept;
  int GetNumberOfCells() const noexcept;
  int GetNumberOfFaces() const noexcept;
  int GetNumberOfPoints() const noexcept;
  const std::vector<boost::shared_ptr<Coordinat3D>>& GetPoints() noexcept { return m_points; }
  static std::string GetVersion() noexcept;
  std::vector<std::string> GetVersionHistory() const noexcept;

  private:

  ///Order is not important
  std::vector<boost::shared_ptr<Boundary>> m_boundaries;

  ///Order is not important
  std::vector<boost::shared_ptr<Cell>> m_cells;

  ///Order is important for ReorderFaces only
  std::vector<boost::shared_ptr<Face>> m_faces;

  ///Order is not important
  std::vector<boost::shared_ptr<Coordinat3D>> m_points;

  ///Step #1
  ///Create Faces so these can be shared over Boundary and Cell
  Mesh(const Files& files,
    const std::vector<boost::shared_ptr<Coordinat3D>>& points);

  ///Checks if the Faces their indices are adjacent
  ///when they belong to the
  ///same Boundary
  bool AreFacesOrdered() const noexcept;

  //static double CalcSimilaritySlow(
  //  const std::vector<Coordinat3D>& v,
  //  const std::vector<Coordinat3D>& w) noexcept;

  static double CalcSimilarityFaster(
    const std::vector<boost::shared_ptr<const Coordinat3D>>& v,
    const std::vector<Coordinat3D>& w) noexcept;

  //static double CalcSimilaritySlow(
  //  const std::vector<boost::shared_ptr<const Coordinat3D>>& v,
  //  const std::vector<Coordinat3D>& w) noexcept;

  static std::vector<boost::shared_ptr<Boundary>> CreateBoundaries(
    const Files& files, const std::vector<boost::shared_ptr<Face>>& faces);

  boost::shared_ptr<BoundaryFile> CreateBoundary() const noexcept;

  ///Create empty Cells, as much as needed
  static std::vector<boost::shared_ptr<Cell>> CreateEmptyCells(
    const Files& files);

  boost::shared_ptr<FacesFile> CreateFaces() const noexcept;

  ///Create the Faces from the points, but cannot initialize Owner and Neighbour
  static std::vector<boost::shared_ptr<Face>> CreateFacesWithPoints(
    const Files& files,
    const std::vector<boost::shared_ptr<Coordinat3D>>& points);

  boost::shared_ptr<NeighbourFile> CreateNeighbour() const noexcept;
  boost::shared_ptr<OwnerFile> CreateOwner() const noexcept;
  boost::shared_ptr<PointsFile> CreatePoints() const noexcept;

  static std::vector<boost::shared_ptr<Coordinat3D>> CreatePoints(const Files& files);

  ///This member function is called to reorder the faces in such a way
  ///that indices in m_faces are adjacent when they belong to the
  ///same Boundary
  ///
  ///For example, consider the following boundary file:
  ///
  ///2
  ///(
  ///  boundary_left
  ///  {
  ///    type            patch;
  ///    nFaces          2;
  ///    startFace       0;
  ///  }
  ///  boundary_right
  ///  {
  ///    type            patch;
  ///    nFaces          2;
  ///    startFace       2;
  ///  }
  ///)
  ///
  ///ReorderFaces will put the faces belonging to 'boundary_left'
  ///at indices 0 and 1, and the faces belonging to 'boundary_right'
  ///at indices 2 and 3.
  ///
  ///Because this is an indexless structure, the ordering of Faces in
  ///m_faces is unimportant, except for this: when writing to file
  void ReorderFaces();

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif

  friend std::ostream& operator<<(std::ostream& os, const Mesh& mesh) noexcept;
};

std::ostream& operator<<(std::ostream& os, const Mesh& mesh) noexcept;

} //~namespace foam
} //~namespace ribi

#endif // RIBI_OPENFOAMMESH_H

 

 

 

 

 

./CppOpenFoam/openfoammesh.cpp

 

#include "openfoammesh.h"

#include <cassert>
#include <iostream>
#include <ostream>
#include <map>

#include "openfoamboundary.h"
#include "openfoamboundaryfile.h"
#include "openfoamboundaryfileitem.h"
#include "openfoamboundaryindex.h"
#include "openfoamcell.h"
#include "openfoamface.h"
#include "openfoamfacesfile.h"
#include "openfoamfiles.h"
#include "openfoamhelper.h"
#include "openfoamneighbourfile.h"
#include "openfoamownerfile.h"
#include "openfoampatchfieldtypes.h"
#include "openfoampoint.h"
#include "openfoampointsfile.h"
#include "testtimer.h"
#include "trace.h"

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<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<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 (const 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());
}

bool ribi::foam::Mesh::AreFacesOrdered() const noexcept
{
  for (const boost::shared_ptr<Boundary> boundary: m_boundaries)
  {
    assert(!boundary->GetFaces().empty());
    #ifndef NDEBUG
    const int n_faces {
      static_cast<int>(boundary->GetFaces().size())
    };
    assert(n_faces > 0);
    #endif
    //Determine the start face: at which indices are the Faces in m_faces?
    std::vector<int> indices;
    std::transform(boundary->GetFaces().begin(),boundary->GetFaces().end(),std::back_inserter(indices),
      [this](const boost::shared_ptr<Face> face)
      {
        const std::vector<boost::shared_ptr<Face>>::const_iterator iter {
          std::find(m_faces.begin(),m_faces.end(),face)
        };
        assert(iter != m_faces.end());
        const int index = std::distance(m_faces.begin(),iter);
        assert(index >= 0);
        assert(index < static_cast<int>(m_faces.size()));
        return index;
      }
    );
    assert(!indices.empty());
    assert(indices.size() == boundary->GetFaces().size());
    std::sort(indices.begin(),indices.end());
    const std::size_t n_indices = indices.size();
    if (n_indices > 1)
    {
      for (std::size_t i=1; i!=n_indices; ++i)
      {
        assert(indices[i-1] != indices[i]  && "All face indices must be unique");
        if (indices[i-1] + 1 != indices[i])
        {
          return false;
        }
      }
    }
  }
  return true;
}

double ribi::foam::Mesh::CalcSimilarityFaster(
  const std::vector<boost::shared_ptr<const Coordinat3D>>& v,
  const std::vector<Coordinat3D>& w) noexcept
{
  if (v.size() != w.size()) return std::numeric_limits<double>::max();
  //Sum all coordinats, distance equals the distance between the center points

  #ifdef USE_CUSTOM_RIBI_COORDINAT3D
  const Coordinat3D a = std::accumulate(v.begin(),v.end(),Coordinat3D(),
    [](const Coordinat3D& init, const boost::shared_ptr<const Coordinat3D> c)
    {
      return init + (*c);
    }
  );
  //for (const boost::shared_ptr<const Coordinat3D> c: v) { a += (*c); }
  const Coordinat3D b = std::accumulate(w.begin(),w.end(),Coordinat3D());
  return Distance(a,b);
  #else
  typedef boost::geometry::model::point<double,3,boost::geometry::cs::cartesian> Coordinat3D;
  const auto a(
    std::accumulate(v.begin(),v.end(),Coordinat3D(0.0,0.0,0.0),
      [](const Coordinat3D& init, const boost::shared_ptr<const Coordinat3D> c)
      {
        return Coordinat3D(
          boost::geometry::get<0>(init) + boost::geometry::get<0>(*c),
          boost::geometry::get<1>(init) + boost::geometry::get<1>(*c),
          boost::geometry::get<2>(init) + boost::geometry::get<2>(*c)
        );
      }
    )
  );
  const auto b(
    std::accumulate(w.begin(),w.end(),Coordinat3D(),&ribi::foam::Add
      /*
      ,[](const Coordinat3D& init, const Coordinat3D& c)
      {
        return Coordinat3D(
          boost::geometry::get<0>(init) + boost::geometry::get<0>(c),
          boost::geometry::get<1>(init) + boost::geometry::get<1>(c),
          boost::geometry::get<2>(init) + boost::geometry::get<2>(c)
        );
      }
      */
    )
  );
  return boost::geometry::distance(a,b);
  #endif
}

/*
double ribi::foam::Mesh::CalcSimilaritySlow(
  const std::vector<Coordinat3D>& v,
  const std::vector<Coordinat3D>& w) noexcept
{
  if (v.size() != w.size()) return std::numeric_limits<double>::max();
  const double distance {
    std::accumulate(v.begin(),v.end(),0.0,
      [w](const double init,const Coordinat3D& c)
      {
        //Find the closest coordinat in w to c
        const std::vector<Coordinat3D>::const_iterator closest {
          std::min_element(w.begin(),w.end(),
            [c](const Coordinat3D& lhs, const Coordinat3D& rhs)
            {
              return Distance(lhs,c) < Distance(rhs,c);
            }
          )
        };
        return init + Distance(c,*closest);
      }
    )
  };
  return distance;
}
*/

/*
double ribi::foam::Mesh::CalcSimilaritySlow(
  const std::vector<boost::shared_ptr<const Coordinat3D>>& v,
  const std::vector<Coordinat3D>& w) noexcept
{
  if (v.size() != w.size()) return std::numeric_limits<double>::max();
  const double distance {
    std::accumulate(v.begin(),v.end(),0.0,
      [w](const double init,const boost::shared_ptr<const Coordinat3D>& c)
      {

        //Find the closest coordinat in w to c
        const std::vector<Coordinat3D>::const_iterator closest {
          std::min_element(w.begin(),w.end(),
            [c](const Coordinat3D& lhs, const Coordinat3D& rhs)
            {
              return Distance(lhs,*c) < Distance(rhs,*c);
            }
          )
        };
        return init + Distance(*c,*closest);
      }
    )
  };
  return distance;
}
*/

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;
}

boost::shared_ptr<ribi::foam::BoundaryFile> ribi::foam::Mesh::CreateBoundary() const noexcept
{
  std::vector<BoundaryFileItem> items;


  for (const boost::shared_ptr<Boundary> boundary: m_boundaries)
  {
    assert(!boundary->GetFaces().empty());
    const int n_faces {
      static_cast<int>(boundary->GetFaces().size())
    };
    assert(n_faces > 0);
    //Determine the start face: at which indices are the Faces in m_faces?
    std::vector<int> indices;
    std::transform(boundary->GetFaces().begin(),boundary->GetFaces().end(),std::back_inserter(indices),
      [this](const boost::shared_ptr<Face> face)
      {
        const std::vector<boost::shared_ptr<Face>>::const_iterator iter {
          std::find(m_faces.begin(),m_faces.end(),face)
        };
        assert(iter != m_faces.end());
        const int index = std::distance(m_faces.begin(),iter);
        assert(index >= 0);
        assert(index < static_cast<int>(m_faces.size()));
        return index;
      }
    );
    assert(!indices.empty());
    assert(indices.size() == boundary->GetFaces().size());
    std::sort(indices.begin(),indices.end());
    #ifndef NDEBUG
    const std::size_t n_indices = indices.size();
    if (n_indices > 1)
    {
      for (std::size_t i=1; i!=n_indices; ++i)
      {
        assert(indices[i-1] != indices[i]
          && "All face indices must be unique");
        if (indices[i-1] + 1 != indices[i])
        {
          TRACE("ERROR");
        }
        assert(indices[i-1] + 1 == indices[i]
          && "All face indices must be adjacent");
      }
    }
    #endif

    const FaceIndex n_start_face = FaceIndex(indices[0]);
    const BoundaryFileItem item(
      boundary->GetName(),
      boundary->GetType(),
      n_faces,
      n_start_face
    );
    items.push_back(item);
  }

  boost::shared_ptr<BoundaryFile> f {
    new BoundaryFile(
      BoundaryFile::GetDefaultHeader(),
      items
    )
  };
  assert(f);
  return f;
}

std::vector<boost::shared_ptr<ribi::foam::Cell>> ribi::foam::Mesh::CreateEmptyCells(
  const Files& files)
{
  std::vector<boost::shared_ptr<ribi::foam::Cell>> cells;
  const CellIndex n_cells = files.GetOwner()->CountNumberOfCells();
  assert(n_cells == files.GetOwner()->CountNumberOfCells());
  assert(n_cells > CellIndex(0));
  for (CellIndex i=CellIndex(0); i!=n_cells; ++i)
  {
    const boost::shared_ptr<Cell> cell(
      new Cell
    );
    cells.push_back(cell);
  }
  assert(!cells.empty());
  return cells;
}

boost::shared_ptr<ribi::foam::FacesFile> ribi::foam::Mesh::CreateFaces() const noexcept
{
  std::vector<FacesFileItem> items;

  //std::vector<boost::shared_ptr<const ribi::foam::Face>> faces;
  std::transform(
    m_faces.begin(),
    m_faces.end(),
    std::back_inserter(items),
    [this](const boost::shared_ptr<const Face> face)
    {
      assert(face);
      const std::vector<boost::shared_ptr<const Coordinat3D>> points {
        face->GetPoints()
      };
      std::vector<PointIndex> point_indices;
      std::transform(points.begin(),points.end(),
        std::back_inserter(point_indices),
        [this](boost::shared_ptr<const Coordinat3D> coordinat)
        {
          const std::vector<boost::shared_ptr<Coordinat3D>>::const_iterator iter {
            std::find(m_points.begin(),m_points.end(),coordinat)
          };
          assert(iter != m_points.end());
          const int index {
            std::distance(m_points.begin(),iter)
          };
          assert(index >= 0);
          assert(index < static_cast<int>(m_points.size()));
          return PointIndex(index);
        }
      );
      return FacesFileItem(point_indices);
    }
  );

  const boost::shared_ptr<FacesFile> f {
    new FacesFile(
      FacesFile::GetDefaultHeader(),
      items
    )
  };
  assert(f);
  return f;
}

std::vector<boost::shared_ptr<ribi::foam::Face>> ribi::foam::Mesh::CreateFacesWithPoints(
  const Files& files,
  const std::vector<boost::shared_ptr<Coordinat3D>>& all_points)
{
  const FaceIndex n_faces { files.GetFaces()->GetMaxFaceIndex() };

  std::vector<boost::shared_ptr<Face>> faces;
  for (FaceIndex i = FaceIndex(0); i!=n_faces; ++i)
  {
    const std::vector<PointIndex> point_indices {
      files.GetFaces()->GetItem(i).GetPointIndices()
    };

    std::vector<boost::shared_ptr<Coordinat3D>> points;
    for (const PointIndex& point_index: point_indices)
    {
      assert(point_index.Get() >= 0);
      assert(point_index.Get() < static_cast<int>(all_points.size()));
      points.push_back(all_points[point_index.Get() ]);
    }
    const boost::shared_ptr<Face> face(
      new Face(
        nullptr,
        nullptr,
        points
      )
    );
    assert(face);
    faces.push_back(face);
  }
  assert(faces.size() == files.GetFaces()->GetItems().size());
  return faces;
}

ribi::foam::Files ribi::foam::Mesh::CreateFiles() const noexcept
{
  boost::shared_ptr<BoundaryFile> boundary {
    CreateBoundary()
  };
  assert(boundary);
  boost::shared_ptr<FacesFile> faces {
    CreateFaces()
  };
  assert(faces);
  boost::shared_ptr<NeighbourFile> neighbour {
    CreateNeighbour()
  };
  assert(neighbour);
  boost::shared_ptr<OwnerFile> owner {
    CreateOwner()
  };
  assert(owner);
  boost::shared_ptr<PointsFile> points {
    CreatePoints()
  };
  assert(points);
  const Files f(
    boundary,
    faces,
    neighbour,
    owner,
    points
  );
  return f;
}

boost::shared_ptr<ribi::foam::NeighbourFile> ribi::foam::Mesh::CreateNeighbour() const noexcept
{
  std::vector<NeighbourFileItem> v;
  for (boost::shared_ptr<Face> face: m_faces)
  {
    assert(face);
    const boost::shared_ptr<const ribi::foam::Cell> neighbour { face->GetNeighbour() };

    assert( (neighbour || !neighbour)
      && "Not all cells have a neighbour, for example in a 1x1x1 mesh");
    if (!neighbour) continue;

    assert(std::find(m_cells.begin(),m_cells.end(),neighbour) != m_cells.end());

    const int index
      = std::distance(
        m_cells.begin(),
        std::find(m_cells.begin(),m_cells.end(),neighbour)
      );

    assert(index >= 0);
    assert(index < static_cast<int>(m_cells.size()));
    const CellIndex cell_index(index);
    const NeighbourFileItem item(cell_index);
    v.push_back(item);
  }

  const boost::shared_ptr<ribi::foam::NeighbourFile> p {
    new NeighbourFile(
      NeighbourFile::GetDefaultHeader(),
      v
    )
  };
  assert(p);
  return p;
}

boost::shared_ptr<ribi::foam::OwnerFile> ribi::foam::Mesh::CreateOwner() const noexcept
{
  std::vector<OwnerFileItem> items;

  std::transform(
    m_faces.begin(),
    m_faces.end(),
    std::back_inserter(items),
    [this](const boost::shared_ptr<Face> face)
    {
      assert(face);
      const boost::shared_ptr<Cell> owner = face->GetOwner();
      assert(owner);
      const auto iter = std::find(m_cells.begin(),m_cells.end(),owner);
      assert(iter != m_cells.end());
      const int index = static_cast<int>(std::distance(m_cells.begin(),iter));
      assert(index >= 0);
      assert(index < static_cast<int>(m_cells.size()));
      const CellIndex cell_index(index);
      return OwnerFileItem(cell_index);
    }
  );

  const boost::shared_ptr<OwnerFile> p {
    new OwnerFile(
      OwnerFile::GetDefaultHeader(),
      items
    )
  };
  assert(p);
  return p;
}

boost::shared_ptr<ribi::foam::PointsFile> ribi::foam::Mesh::CreatePoints() const noexcept
{
  std::vector<PointsFileItem> items;
  std::transform(
    m_points.begin(),
    m_points.end(),
    std::back_inserter(items),
    [](const boost::shared_ptr<Coordinat3D> point)
    {
      assert(point);
      return PointsFileItem(*point);
    }
  );

  const boost::shared_ptr<PointsFile> p {
    new PointsFile(
      PointsFile::GetDefaultHeader(),
      items
    )
  };
  assert(p);
  return p;
}

std::vector<boost::shared_ptr<boost::geometry::model::point<double,3,boost::geometry::cs::cartesian>>>
  ribi::foam::Mesh::CreatePoints(const Files& files)
{
  std::vector<boost::shared_ptr<Coordinat3D>> v;
  assert(files.GetPoints());
  for (const PointsFileItem& item: files.GetPoints()->GetItems())
  {
    static_assert(std::is_same<PointsFileItem,Point>(),
      "Point is a typedef for PointsFileItem"
    );
    const boost::shared_ptr<Coordinat3D> p {
      new Coordinat3D(item.GetCoordinat())

    };
    assert(p);
    v.push_back(p);
  }
  return v;
}

boost::shared_ptr<const ribi::foam::Face> ribi::foam::Mesh::FindMostSimilarFace(
  const std::vector<Coordinat3D>& coordinats
  ) const
{
  ///Obtain the distance from focal coordinats to each face its coordinat
  std::vector<double> distances;
  const std::size_t sz = m_faces.size();
  for (std::size_t i=0; i!=sz; ++i)
  {
    assert(i < m_faces.size());
    assert(m_faces[i]);
    const double distance = CalcSimilarityFaster(
      AddConst(m_faces[i]->GetPoints()),
      coordinats
    );
    TRACE(distance);
    distances.push_back(distance);
  }

  //Find the most similar
  const int index {
    std::distance(
      distances.begin(),
      std::min_element(distances.begin(),distances.end())
    )
  };

  //Return the face
  const boost::shared_ptr<const ribi::foam::Face> p {
    m_faces[index]
  };
  assert(p);
  return p;
}

const std::vector<boost::shared_ptr<const ribi::foam::Face>> ribi::foam::Mesh::GetFaces() const noexcept
{
  std::vector<boost::shared_ptr<const ribi::foam::Face>> v;
  std::transform(
    m_faces.begin(),m_faces.end(),
    std::back_inserter(v),
    [](boost::shared_ptr<ribi::foam::Face> old_face)
    {
      const boost::shared_ptr<const ribi::foam::Face> new_face(old_face);
      assert(old_face == new_face);
      return new_face;
    }
  );
  return v;
}

int ribi::foam::Mesh::GetNumberOfBoundaries() const noexcept
{
  return static_cast<int>(this->m_boundaries.size());
}

int ribi::foam::Mesh::GetNumberOfCells() const noexcept
{
  return static_cast<int>(m_cells.size());
}

int ribi::foam::Mesh::GetNumberOfFaces() const noexcept
{
  return static_cast<int>(m_faces.size());
}

int ribi::foam::Mesh::GetNumberOfPoints() const noexcept
{
  return static_cast<int>(m_points.size());
}

std::string ribi::foam::Mesh::GetVersion() noexcept
{
  return "1.1";
}

std::vector<std::string> ribi::foam::Mesh::GetVersionHistory() const noexcept
{
  return {
    "2014-xx-xx: version 1.0: initial version",
    "2014-05-08: version 1.1: initial versioning"
  };
}

void ribi::foam::Mesh::ReorderFaces()
{
  assert(!this->AreFacesOrdered());

  const std::size_t n_boundaries = m_boundaries.size();
  std::size_t new_face_index = 0; //The index to put the next Face at
  for (std::size_t i=0; i!=n_boundaries; ++i)
  {
    const boost::shared_ptr<Boundary> boundary = m_boundaries[i];
    const std::size_t n_faces = boundary->GetFaces().size();
    for (std::size_t j=0; j!=n_faces; ++j)
    {
      assert(j < boundary->GetFaces().size());
      const std::vector<boost::shared_ptr<Face>>::iterator here {
        std::find(m_faces.begin(),m_faces.end(),boundary->GetFaces()[j])
      };
      assert(here != m_faces.end());
      const std::size_t old_face_index = std::distance(m_faces.begin(),here);
      assert(old_face_index >= new_face_index);
      std::swap(m_faces[old_face_index],m_faces[new_face_index]);
      ++new_face_index;
    }
  }


  assert(this->AreFacesOrdered());
}


#ifndef NDEBUG
void ribi::foam::Mesh::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
  //Check if the number of boundary faces is correct
  {
    const std::vector<boost::shared_ptr<ribi::foam::Files>> v { Files::CreateTestFiles() };
    assert(v.size() == 6);
    const std::vector<int> n_internal_mesh_faces_expected { 0,0,1,4,12,133 };
    assert(v.size() == n_internal_mesh_faces_expected.size());
    const int n_meshes = static_cast<int>(v.size());
    for (int mesh_index = 0; mesh_index != n_meshes; ++mesh_index)
    {
      const Mesh mesh(*v[mesh_index]);
      const std::vector<boost::shared_ptr<const Face>> mesh_faces {
        mesh.GetFaces()
      };
      const int n_internal {
        std::count_if(mesh_faces.begin(),mesh_faces.end(),
          [](const boost::shared_ptr<const Face> face)
          {
            assert(face);
            assert(face->GetOwner());
            return face->GetNeighbour(); //internal faces have a neighbour
          }
        )
      };
      assert(n_internal == n_internal_mesh_faces_expected[mesh_index]
        && "Must have as much internal faces as expected"
      );
    }
  }
  //CalcSimilarity: empty
  {
    std::vector<boost::shared_ptr<const Coordinat3D>> v;
    std::vector<Coordinat3D> w;
    assert(CalcSimilarityFaster(v,w) < 0.001);
  }
  //CalcSimilarity: one point
  {
    std::vector<boost::shared_ptr<const Coordinat3D>> v;
    std::vector<Coordinat3D> w;
    {
      const Coordinat3D c(1.1,2.2,3.3);
      boost::shared_ptr<const Coordinat3D> d {
        new Coordinat3D(c)
      };
      assert(c == *d); //Exact comparison
      assert(boost::geometry::distance(c,*d) < 0.0000001); //Fuzzier comparison
      w.push_back(c);
      v.push_back(d);
    }
    assert(CalcSimilarityFaster(v,w) < 0.001);
  }
  //CalcSimilarity: two points
  {
    std::vector<boost::shared_ptr<const Coordinat3D>> v;
    std::vector<Coordinat3D> w;
    {
      const Coordinat3D c(1.1,2.2,3.3);
      boost::shared_ptr<const Coordinat3D> d {
        new Coordinat3D(c)
      };
      assert(c == *d); //Exact comparison
      assert(boost::geometry::distance(c,*d) < 0.0000001); //Fuzzier comparison
      w.push_back(c);
      v.push_back(d);
    }
    {
      const Coordinat3D c(2.2,3.3,4.4);
      boost::shared_ptr<const Coordinat3D> d {
        new Coordinat3D(c)
      };
      assert(c == *d); //Exact comparison
      assert(boost::geometry::distance(c,*d) < 0.0000001); //Fuzzier comparison
      w.push_back(c);
      v.push_back(d);
    }
    assert(CalcSimilarityFaster(v,w) < 0.001);
  }
  //CalcSimilarity: one versus two points
  {
    std::vector<boost::shared_ptr<const Coordinat3D>> v;
    std::vector<Coordinat3D> w;
    {
      const Coordinat3D c(1.1,2.2,3.3);
      boost::shared_ptr<const Coordinat3D> d {
        new Coordinat3D(c)
      };
      assert(c == *d); //Exact comparison
      assert(boost::geometry::distance(c,*d) < 0.0000001); //Fuzzier comparison
      w.push_back(c);
      v.push_back(d);
    }
    {
      const Coordinat3D c(2.2,3.3,4.4);
      w.push_back(c);
    }
    assert(CalcSimilarityFaster(v,w) > 1000000000.0);
  }
  //Find most similar Faces
  {
    //Handcraft Faces, put these in mesh

    //For the Points, I used the same setup as in Classes/CppOpenFoam/points_1x1x1:
    //
    // 8((0 0 0) (1 0 0) (0 1 0) (1 1 0) (0 0 1) (1 0 1) (0 1 1) (1 1 1))
    //
    // The order of points is determined by blockMesh
    const boost::shared_ptr<Coordinat3D> p0 { new Coordinat3D(0.0,0.0,0.0) };
    const boost::shared_ptr<Coordinat3D> p1 { new Coordinat3D(1.0,0.0,0.0) };
    const boost::shared_ptr<Coordinat3D> p2 { new Coordinat3D(0.0,1.0,0.0) };
    const boost::shared_ptr<Coordinat3D> p3 { new Coordinat3D(1.0,1.0,0.0) };
    const boost::shared_ptr<Coordinat3D> p4 { new Coordinat3D(0.0,0.0,1.0) };
    const boost::shared_ptr<Coordinat3D> p5 { new Coordinat3D(1.0,0.0,1.0) };
    const boost::shared_ptr<Coordinat3D> p6 { new Coordinat3D(0.0,1.0,1.0) };
    const boost::shared_ptr<Coordinat3D> p7 { new Coordinat3D(1.0,1.0,1.0) };
    assert(p0); assert(p1); assert(p2); assert(p3);
    assert(p4); assert(p5); assert(p6); assert(p7);
    const boost::shared_ptr<Cell> cell { new Cell };
    const std::vector<boost::shared_ptr<Cell>> cells { cell };

    const boost::shared_ptr<Cell> n0; //No neighbours in a 1x1 mesh
    const boost::shared_ptr<Cell> n1; //No neighbours in a 1x1 mesh
    const boost::shared_ptr<Cell> n2; //No neighbours in a 1x1 mesh
    const boost::shared_ptr<Cell> n3; //No neighbours in a 1x1 mesh
    const boost::shared_ptr<Cell> n4; //No neighbours in a 1x1 mesh
    const boost::shared_ptr<Cell> n5; //No neighbours in a 1x1 mesh
    const boost::shared_ptr<Cell> own0 { cell }; //The only Cell owns all Faces
    const boost::shared_ptr<Cell> own1 { cell }; //The only Cell owns all Faces
    const boost::shared_ptr<Cell> own2 { cell }; //The only Cell owns all Faces
    const boost::shared_ptr<Cell> own3 { cell }; //The only Cell owns all Faces
    const boost::shared_ptr<Cell> own4 { cell }; //The only Cell owns all Faces
    const boost::shared_ptr<Cell> own5 { cell }; //The only Cell owns all Faces

    const std::vector<boost::shared_ptr<Coordinat3D>> points { p0,p1,p2,p3,p4,p5,p6,p7 };
    //For the Faces, I used the same setup as in Classes/CppOpenFoam/faces_1x1x1:
    //
    //
    //  6
    //  (
    //  4(0 2 3 1)
    //  4(0 4 6 2)
    //  4(0 1 5 4)
    //  4(1 3 7 5)
    //  4(2 6 7 3)
    //  4(4 5 7 6)
    //  )
    //
    // The order of faces is determined by blockMesh
    const boost::shared_ptr<Face> f0 { new Face(n0,own0, { p0, p2, p3, p1 } ) };
    const boost::shared_ptr<Face> f1 { new Face(n1,own1, { p0, p4, p6, p2 } ) };
    const boost::shared_ptr<Face> f2 { new Face(n2,own2, { p0, p1, p5, p4 } ) };
    const boost::shared_ptr<Face> f3 { new Face(n3,own3, { p1, p3, p7, p5 } ) };
    const boost::shared_ptr<Face> f4 { new Face(n4,own4, { p2, p6, p7, p3 } ) };
    const boost::shared_ptr<Face> f5 { new Face(n5,own5, { p4, p5, p7, p6 } ) };

    const std::vector<boost::shared_ptr<Face>> faces { f0,f1,f2,f3,f4,f5 };
    cell->AssignOwnedFaces( { f0,f1,f2,f3,f4,f5 } );

    boost::shared_ptr<Boundary> boundary { new Boundary(  {f0,f1,f2,f3,f4,f5 },"defaultFaces",PatchFieldType::wall) };
    const std::vector<boost::shared_ptr<Boundary>> boundaries { boundary };

    const Mesh m(
      boundaries,
      cells,
      faces,
      points
    );
    for (const boost::shared_ptr<Face> face: faces)
    {
      assert(face);
      const std::vector<boost::shared_ptr<const Coordinat3D>> points { AddConst(face->GetPoints()) };
      std::vector<Coordinat3D> coordinats;
      std::transform(points.begin(),points.end(),
        std::back_inserter(coordinats),
        [](const boost::shared_ptr<const Coordinat3D> shared_coordinat)
        {
          return Coordinat3D(*shared_coordinat);
        }
      );
      //For every Face, extract the coordinats
      //FindMostSimilar should find back the original Face
      const boost::shared_ptr<const ribi::foam::Face> result {
        m.FindMostSimilarFace(coordinats)
      };
      assert(result);
      if (face != result)
      {
        TRACE("ERROR");
        TRACE(*face);
        TRACE(*result);
      }
      assert(result == face);
    }
  }
}
#endif


std::ostream& ribi::foam::operator<<(std::ostream& os, const ribi::foam::Mesh& mesh) noexcept
{
  typedef boost::geometry::model::point<double,3,boost::geometry::cs::cartesian> Coordinat3D;

  TRACE("Smallest: points");
  os << "Points: ";
  for (boost::shared_ptr<Coordinat3D> point: mesh.m_points)
  {
    assert(point);
    os << "* " << ToStr(*point) << '\n';
  }
  TRACE("Small: faces");
  os << "Faces:\n";
  for (boost::shared_ptr<Face> face: mesh.m_faces)
  {
    os
      << "* Neighbour: " << face->GetNeighbour() << '\n'
      << "* Owner: " << face->GetOwner() << '\n'
      << "* Coordinats: ";
    for(boost::shared_ptr<const Coordinat3D> coordinat: face->GetPoints())
    {
      os << coordinat << ' ';
    }
    os << '\n';
  }
  TRACE("Bigger: boundaries");
  os << "Boundary:\n";
  for (boost::shared_ptr<Boundary> boundary: mesh.m_boundaries)
  {
    os
      << "* Name: " << boundary->GetName() << '\n'
      << "* Type: " << boundary->GetType() << '\n'
      << "* Faces: ";
    for (const boost::shared_ptr<const Face> face: boundary->GetFaces())
    {
      os << face << ' ';
    }
    os << '\n';
  }

  TRACE("Biggest: cells");
  os << "Cells:\n";
  for (const boost::shared_ptr<Cell> cell: mesh.m_cells)
  {
    os
       //<< "* Neighbour: " << cell->GetNeighbour() << '\n'
       << "* Faces: ";
    for (boost::shared_ptr<const ribi::foam::Face> face: cell->GetOwnedFaces())
    {
      os << face << ' ';
    }
    os << '\n';
  }

  return os;
}

 

 

 

 

 

./CppOpenFoam/openfoamneighbourfile.h

 

#ifndef RIBI_OPENFOAMNEIGHBOURFILE_H
#define RIBI_OPENFOAMNEIGHBOURFILE_H

#include <iosfwd>
#include <string>
#include <vector>
#include "fileiofwd.h"
#include "openfoamfwd.h"
#include "openfoamheader.h"
#include "openfoamneighbourfileitem.h"

namespace ribi {
namespace foam {

///Reads and writes an OpenFOAM boundary file
struct NeighbourFile
{
  explicit NeighbourFile(const std::string& filename) : NeighbourFile(Parse(filename)) {}
  explicit NeighbourFile(
    const Header header = GetDefaultHeader(),
    const std::vector<NeighbourFileItem>& items = {});

  ///If the FaceIndex is present
  bool CanGetItem(const FaceIndex& face_index) const noexcept;

  //DON'T: Use OwnerFile::CountNumberOfCells instead
  //WHY: because all cell indices are detected in owner
  ///Find the first CellIndex beyond the cell indices present
  ///Or: find the first CellIndex that does not exist anymore
  //const CellIndex CountNumberOfCells() const noexcept;

  static Header GetDefaultHeader() noexcept;
  const Header& GetHeader() const noexcept { return m_header; }
  const std::vector<NeighbourFileItem>& GetItems() const noexcept { return m_items; }

  ///Assumes CanGetItem == true
  const NeighbourFileItem& GetItem(const FaceIndex& face_index) const noexcept;

  int GetNumberOfItems() const noexcept { return static_cast<int>(m_items.size()); }

  void SetItem(const FaceIndex& face_index, const NeighbourFileItem& item) noexcept;

  private:
  explicit NeighbourFile(std::istream& is) : NeighbourFile(Parse(is)) {}

  ///The OpenFOAM header
  Header m_header;
  ///The items 'neighbour' contains
  std::vector<NeighbourFileItem> m_items;

  static NeighbourFile Parse(std::istream& is);
  static NeighbourFile Parse(const std::string& filename);

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif

  friend std::ostream& operator<<(std::ostream& os, const NeighbourFile& f) noexcept;
  friend std::istream& operator>>(std::istream& is, NeighbourFile& f);
};

bool operator==(const NeighbourFile& lhs,const NeighbourFile& rhs) noexcept;
bool operator!=(const NeighbourFile& lhs,const NeighbourFile& rhs) noexcept;
std::ostream& operator<<(std::ostream& os, const NeighbourFile& f) noexcept;
std::istream& operator>>(std::istream& is, NeighbourFile& f);

} //~namespace foam
} //~namespace ribi

#endif // RIBI_OPENFOAMNEIGHBOURFILE_H

 

 

 

 

 

./CppOpenFoam/openfoamneighbourfile.cpp

 

#include "openfoamneighbourfile.h"

#include <cassert>
#include <fstream>
#include <iostream>
#include <stdexcept>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"

#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/lexical_cast.hpp>

#include <QFile>


#include "fileio.h"
#include "openfoamheader.h"
#include "openfoamneighbourfileitem.h"
#include "openfoamfaceindex.h"
#include "testtimer.h"
#include "trace.h"
#pragma GCC diagnostic pop


ribi::foam::NeighbourFile::NeighbourFile(
  const Header header,
  const std::vector<NeighbourFileItem>& items)
  : m_header{header},
    m_items(items)
{
  #ifndef NDEBUG
  Test();
  #endif
}

bool ribi::foam::NeighbourFile::CanGetItem(
  const FaceIndex& face_index) const noexcept
{
  assert(face_index.Get() >= 0);
  return face_index.Get() < static_cast<int>(m_items.size());
}

ribi::foam::Header ribi::foam::NeighbourFile::GetDefaultHeader() noexcept
{
  return Header("labelList","constant/polyMesh","","neighbour");
}

const ribi::foam::NeighbourFileItem& ribi::foam::NeighbourFile::GetItem(
  const FaceIndex& face_index) const noexcept
{
  #ifndef NDEBUG
  if(!CanGetItem(face_index))
  {
    TRACE("BREAK");
  }
  #endif
  assert(CanGetItem(face_index));
  return m_items[ static_cast<int>(face_index.Get()) ];
}

ribi::foam::NeighbourFile ribi::foam::NeighbourFile::Parse(std::istream& is)
{
  NeighbourFile b;
  is >> b;
  assert(is);
  return b;
}

ribi::foam::NeighbourFile ribi::foam::NeighbourFile::Parse(const std::string& filename)
{
  const std::string tmp_filename { fileio::FileIo().GetTempFileName() };
  fileio::FileIo().CopyFile(filename,tmp_filename);
  Header::CleanFile(tmp_filename);
  std::ifstream f(tmp_filename.c_str());
  const NeighbourFile file { Parse(f) };
  f.close();
  fileio::FileIo().DeleteFile(tmp_filename);
  return file;
}

void ribi::foam::NeighbourFile::SetItem(const FaceIndex& face_index, const NeighbourFileItem& item) noexcept
{
  assert(face_index.Get() >= 0);
  assert(face_index.Get() < static_cast<int>(m_items.size()));
  m_items[ face_index.Get() ] = item;
  assert(GetItem(face_index) == item);
}

#ifndef NDEBUG
void ribi::foam::NeighbourFile::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
  //Some initial data
  const Header header("some_name","some_location","some_object");
  std::vector<NeighbourFileItem> items;
  for (int i=1; i!=4; ++i)
  {
    NeighbourFileItem item(CellIndex(i * i));
    items.push_back(item);
  }
  //operator==
  {
    const NeighbourFile b(header,items);
    const NeighbourFile c(header,items);
    assert(header == header);
    assert(b == c);
  }
  //operator!=
  {
    const NeighbourFile b(header,items);
    const Header other_header("some_other_name","some_other_location","some_other_object");
    assert(header != other_header);
    const NeighbourFile c(other_header,items);
    assert(b != c);
  }
  //operator!=
  {
    const NeighbourFile b(header,items);
    std::vector<NeighbourFileItem> other_items;
    for (int i=1; i!=3; ++i)
    {
      NeighbourFileItem item(CellIndex(2 * i * i));
      other_items.push_back(item);
    }
    const NeighbourFile c(header,other_items);
    assert(b != c);
  }
  //Stream conversion
  {
    const NeighbourFile b(header,items);
    std::stringstream s;
    s << b;
    NeighbourFile c;
    s >> c;
    if (b != c)
    {
      TRACE(b);
      TRACE(c);
    }
    assert(b == c);
  }
  //Read from testing file
  for (int test_index = 0; test_index!=5; ++test_index)
  {
    std::string filename_appendix;
    switch (test_index)
    {
      case 0: filename_appendix = "_1x1x1"; break;
      case 1: filename_appendix = "_1x1x2"; break;
      case 2: filename_appendix = "_1x2x2"; break;
      case 3: filename_appendix = "_2x2x2"; break;
      case 4: filename_appendix = "_3x4x5"; break;
      default: assert(!"Should never get here");
        throw std::logic_error("foam::Files::CreateTestFiles: unknown test index");
    }
    assert(!filename_appendix.empty());
    const std::string filename_base { GetDefaultHeader().GetObject() };
    const std::string filename = filename_base + filename_appendix;
    const std::string resources_path { ":/CppOpenFoam/files/" + filename };

    {
      QFile f( resources_path.c_str() );
      f.copy(filename.c_str());
    }
    {
      if (!fileio::FileIo().IsRegularFile(filename))
      {
        TRACE("ERROR");
        TRACE(filename);
      }
      assert(fileio::FileIo().IsRegularFile(filename));
      NeighbourFile b(filename);
      assert( (!b.GetItems().empty() || b.GetItems().empty())
        && "If a mesh has no non-bhoundary cells, neighbour can be empty");
    }
  }
}
#endif

bool ribi::foam::operator==(const NeighbourFile& lhs,const NeighbourFile& rhs) noexcept
{
  if (lhs.GetHeader() != rhs.GetHeader())
  {
    return false;
  }
  const std::vector<NeighbourFileItem>& lhs_items = lhs.GetItems();
  const std::vector<NeighbourFileItem>& rhs_items = rhs.GetItems();
  if (lhs_items.size() != rhs_items.size())
  {
    return false;
  }
  return std::equal(lhs_items.begin(),lhs_items.end(),rhs_items.begin());
}

bool ribi::foam::operator!=(const NeighbourFile& lhs,const NeighbourFile& rhs) noexcept
{
  return !(lhs == rhs);
}

std::istream& ribi::foam::operator>>(std::istream& is, NeighbourFile& f)
{
  assert(f.m_items.empty()); //Make empty otherwise

  //Read header
  is >> f.m_header;
  assert(is);

  //Read items
  int n_items = 0;
  char opening_bracket = '\0';
  {
    //Eat comment
    char c = '\0';
    is >> c;
    assert(is);
    if (c >= '0' && c <= '9')
    {
      while (c != '(' && c != '{')
      {
        //Start eating n_items
        n_items *= 10;
        const int n = c - '0';
        assert(n >= 0 && n <= 9);
        n_items += n;
        is >> c;
        assert(is);
      }
    }
    opening_bracket = c;
    #ifndef NDEBUG
    if (!(opening_bracket == '(' || opening_bracket == '{'))
    {
      TRACE(opening_bracket);
      TRACE("ERROR");
    }
    #endif
    assert(opening_bracket == '(' || opening_bracket == '{');
  }
  assert(opening_bracket == '(' || opening_bracket == '{');
  if (opening_bracket == '(')
  {
    for (int i=0; i!=n_items; ++i)
    {
      NeighbourFileItem item;
      is >> item;
      assert(is);
      f.m_items.push_back(item);
    }
  }
  else
  {
    assert(opening_bracket == '{');
    //Read once, push n_items times
    NeighbourFileItem item;
    is >> item;
    assert(is);
    for (int i=0; i!=n_items; ++i)
    {
      f.m_items.push_back(item);
    }
  }
  //Eat comments until bracket close
  {
    char bracket_close = '\0';
    while (bracket_close != ')' && bracket_close != '}')
    {
      is >> bracket_close;
      assert(is);
    }
    assert(bracket_close == ')' || bracket_close == '}');
    assert(
         (opening_bracket == '(' && bracket_close == ')')
      || (opening_bracket == '{' && bracket_close == '}')
    );
  }
  return is;
}

std::ostream& ribi::foam::operator<<(std::ostream& os, const NeighbourFile& f) noexcept
{
  os
    << f.GetHeader() << '\n'
    << "" << '\n'
    << f.m_items.size() << '\n'
    << "(" << '\n'
  ;

  for(const NeighbourFileItem item: f.m_items)
  {
    os << item << '\n';
  }

  os
    << ")" << '\n'
  ;
  return os;
}

 

 

 

 

 

./CppOpenFoam/openfoamneighbourfileitem.h

 

#ifndef RIBI_OPENFOAMNEIGHBOURFILEITEM_H
#define RIBI_OPENFOAMNEIGHBOURFILEITEM_H

#include <vector>
#include <iosfwd>
#include "openfoamcellindex.h"

namespace ribi {
namespace foam {

///An item in an OpenFOAM 'neighbour' file
///A neighbour files contains, for every face, the cell index of which the face is a neighbour of
///
///For example, from /Classes/CppOpenFoam/neighbour_1x2x2:
///
///4(1 2 3 3)
///
///Equivalent to, as faces_1x2x2 contains twenty faces:
///
///20(1 2 3 3 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1)
///
///This means that:
/// - Face 0 has Cell 1 as its neighbour, and is thus an internal face
/// - Face 1 has Cell 2 as its neighbour, and is thus an internal face
/// - Face 2 has Cell 3 as its neighbour, and is thus an internal face
/// - Face 3 has Cell 3 as its neighbour, and is thus an internal face
/// - All other Faces have no neighbours, and are thus boundary faces
///
///The file 'neighbour' has path '[case_folder]/constant/polyMesh/neighbour'
struct NeighbourFileItem
{
  ///A CellIndex of -1 denotes that a Face has no Neighbour
  explicit NeighbourFileItem(const CellIndex cell_index = CellIndex(-1));

  ///A CellIndex of -1 denotes that a Face has no Neighbour
  const CellIndex& GetCellIndex() const noexcept { return m_cell_index; }

  private:

  CellIndex m_cell_index;

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif

  friend class OpenFoamNeighbourFile;
  friend std::istream& operator>>(std::istream& is, NeighbourFileItem& f);
};

bool operator==(const NeighbourFileItem& lhs, const NeighbourFileItem& rhs) noexcept;
bool operator!=(const NeighbourFileItem& lhs, const NeighbourFileItem& rhs) noexcept;
std::ostream& operator<<(std::ostream& os, const NeighbourFileItem& f) noexcept;
std::istream& operator>>(std::istream& is, NeighbourFileItem& f);

} //~namespace foam
} //~namespace ribi

#endif // RIBI_OPENFOAMNEIGHBOURFILEITEM_H

 

 

 

 

 

./CppOpenFoam/openfoamneighbourfileitem.cpp

 

#include "openfoamneighbourfileitem.h"

#include <cassert>
#include <iostream>

#include "testtimer.h"
#include "trace.h"

ribi::foam::NeighbourFileItem::NeighbourFileItem(
  const CellIndex cell_index
  )
  : m_cell_index{cell_index}
{
  #ifndef NDEBUG
  Test();
  assert(m_cell_index.Get() >= -1 && "Also allow -1"); //?NONSENSE or not?
  #endif
}

#ifndef NDEBUG
void ribi::foam::NeighbourFileItem::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
  const NeighbourFileItem i(CellIndex(123));
  std::stringstream s;
  s << i;
  NeighbourFileItem j;
  s >> j;
  if (i != j)
  {
    TRACE(i);
    TRACE(j);
  }
  assert(i == j);
}
#endif

bool ribi::foam::operator==(const NeighbourFileItem& lhs, const NeighbourFileItem& rhs) noexcept
{
  return
       lhs.GetCellIndex() == rhs.GetCellIndex()
  ;
}

bool ribi::foam::operator!=(const NeighbourFileItem& lhs, const NeighbourFileItem& rhs) noexcept
{
  return !(lhs == rhs);
}

std::ostream& ribi::foam::operator<<(std::ostream& os, const NeighbourFileItem& item) noexcept
{
  os << item.GetCellIndex();
  return os;
}

std::istream& ribi::foam::operator>>(std::istream& is, NeighbourFileItem& f)
{
  is >> f.m_cell_index;
  assert(is);
  assert(f.GetCellIndex().Get() >= -1);
  return is;
}

 

 

 

 

 

./CppOpenFoam/openfoamownerfile.h

 

#ifndef RIBI_OPENFOAMOWNERFILE_H
#define RIBI_OPENFOAMOWNERFILE_H

#include <iosfwd>
#include <string>
#include <vector>
#include "fileiofwd.h"
#include "openfoamfwd.h"
#include "openfoamheader.h"
#include "openfoamownerfileitem.h"

namespace ribi {
namespace foam {

///Reads and writes an OpenFOAM boundary file
struct OwnerFile
{
  explicit OwnerFile(const std::string& filename) : OwnerFile(Parse(filename)) {}
  explicit OwnerFile(
    const Header header = GetDefaultHeader(),
    const std::vector<OwnerFileItem>& items = {});

  ///Find the first CellIndex beyond the cell indices present
  ///Or: find the first CellIndex that does not exist anymore
  CellIndex CountNumberOfCells() const noexcept;

  static Header GetDefaultHeader() noexcept;
  const Header& GetHeader() const noexcept { return m_header; }
  std::vector<OwnerFileItem> GetItems() const noexcept { return m_items; }
  const OwnerFileItem& GetItem(const FaceIndex& face_index) const noexcept;


  void SetItem(const FaceIndex& face_index, const OwnerFileItem& item) noexcept;

  private:

  ///The OpenFOAM header
  Header m_header;
  ///The items 'neighbour' contains
  std::vector<OwnerFileItem> m_items;

  explicit OwnerFile(std::istream& is) : OwnerFile(Parse(is)) {}
  static OwnerFile Parse(std::istream& is);
  static OwnerFile Parse(const std::string& filename);

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif

  friend std::ostream& operator<<(std::ostream& os, const OwnerFile& f) noexcept;
  friend std::istream& operator>>(std::istream& is, OwnerFile& f);
};

bool operator==(const OwnerFile& lhs,const OwnerFile& rhs) noexcept;
bool operator!=(const OwnerFile& lhs,const OwnerFile& rhs) noexcept;
std::ostream& operator<<(std::ostream& os, const OwnerFile& f) noexcept;
std::istream& operator>>(std::istream& is, OwnerFile& f);

} //~namespace foam
} //~namespace ribi

#endif // RIBI_OPENFOAMOWNERFILE_H

 

 

 

 

 

./CppOpenFoam/openfoamownerfile.cpp

 

#include "openfoamownerfile.h"

#include <cassert>
#include <fstream>
#include <iostream>
#include <stdexcept>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"

#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/lexical_cast.hpp>

#include <QFile>


#include "fileio.h"
#include "openfoamheader.h"
#include "openfoamfaceindex.h"
#include "openfoamownerfileitem.h"
#include "testtimer.h"
#include "trace.h"
#pragma GCC diagnostic pop


ribi::foam::OwnerFile::OwnerFile(
  const Header header,
  const std::vector<OwnerFileItem>& items)
  : m_header{header},
    m_items(items)
{
  #ifndef NDEBUG
  Test();
  #endif
}

ribi::foam::CellIndex ribi::foam::OwnerFile::CountNumberOfCells() const noexcept
{
  assert( (!m_items.empty() || m_items.empty())
    && "If an OwnerFile is empty, there is 1 cell, otherwise 1+max_value_found");
  if (m_items.empty()) return CellIndex(1);

  CellIndex i = (*std::max_element(
    m_items.begin(),
    m_items.end(),
    [](const OwnerFileItem& lhs, const OwnerFileItem& rhs)
    {
      return lhs.GetCellIndex() < rhs.GetCellIndex();
    }
  )).GetCellIndex();

  // +1, because if the highest cell index found is x, there are x+1 cells
  return ++i;
}

ribi::foam::Header ribi::foam::OwnerFile::GetDefaultHeader() noexcept
{
  return Header("labelList","constant/polyMesh","","owner");
}

const ribi::foam::OwnerFileItem& ribi::foam::OwnerFile::GetItem(
  const ribi::foam::FaceIndex& face_index) const noexcept
{
  const int i = face_index.Get();
  assert(i < static_cast<int>(m_items.size()));
  return m_items[i];
}

ribi::foam::OwnerFile ribi::foam::OwnerFile::Parse(std::istream& is)
{
  OwnerFile b;
  is >> b;
  assert(is);
  return b;
}

ribi::foam::OwnerFile ribi::foam::OwnerFile::Parse(const std::string& filename)
{
  const std::string tmp_filename { fileio::FileIo().GetTempFileName() };
  fileio::FileIo().CopyFile(filename,tmp_filename);
  Header::CleanFile(tmp_filename);
  std::ifstream f(tmp_filename.c_str());
  const OwnerFile file { Parse(f) };
  f.close();
  fileio::FileIo().DeleteFile(tmp_filename);
  return file;
}

void ribi::foam::OwnerFile::SetItem(const FaceIndex& face_index, const OwnerFileItem& item) noexcept
{
  const int i = face_index.Get();
  assert(i < static_cast<int>(m_items.size()));
  m_items[i] = item;
  assert(m_items[i] == item);
}

#ifndef NDEBUG
void ribi::foam::OwnerFile::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
  //Some initial data
  const Header header("some_name","some_location","some_object");
  std::vector<OwnerFileItem> items;
  for (int i=1; i!=4; ++i)
  {
    OwnerFileItem item(CellIndex(i * i));
    items.push_back(item);
  }
  //operator==
  {
    const OwnerFile b(header,items);
    const OwnerFile c(header,items);
    assert(header == header);
    assert(b == c);
  }
  //operator!=
  {
    const OwnerFile b(header,items);
    const Header other_header("some_other_name","some_other_location","some_other_object");
    assert(header != other_header);
    const OwnerFile c(other_header,items);
    assert(b != c);
  }
  //operator!=
  {
    const OwnerFile b(header,items);
    std::vector<OwnerFileItem> other_items;
    for (int i=1; i!=3; ++i)
    {
      OwnerFileItem item(CellIndex(2 * i * i));
      other_items.push_back(item);
    }
    const OwnerFile c(header,other_items);
    assert(b != c);
  }
  //operator!=
  {
    const OwnerFile b(header,items);
    OwnerFile c(header,items);
    assert(b == c);
    const FaceIndex i(1);
    const CellIndex j { c.GetItem(i).GetCellIndex() };
    const OwnerFileItem new_item(CellIndex(j.Get() + 1));
    assert(c.GetItem(i) != new_item);
    c.SetItem(i,new_item);
    assert(c.GetItem(i) == new_item);
    assert(b != c);
  }
  //Stream conversion
  {
    const OwnerFile b(header,items);
    std::stringstream s;
    s << b;
    OwnerFile c;
    s >> c;
    if (b != c)
    {
      TRACE(b);
      TRACE(c);
    }
    assert(b == c);
  }
  //Read from testing file
  for (int test_index = 0; test_index!=5; ++test_index)
  {
    std::string filename_appendix;
    switch (test_index)
    {
      case 0: filename_appendix = "_1x1x1"; break;
      case 1: filename_appendix = "_1x1x2"; break;
      case 2: filename_appendix = "_1x2x2"; break;
      case 3: filename_appendix = "_2x2x2"; break;
      case 4: filename_appendix = "_3x4x5"; break;
      default: assert(!"Should never get here");
        throw std::logic_error("foam::Files::CreateTestFiles: unknown test index");
    }
    assert(!filename_appendix.empty());
    const std::string filename_base { GetDefaultHeader().GetObject() };
    const std::string filename = filename_base + filename_appendix;
    const std::string resources_path { ":/CppOpenFoam/files/" + filename };

    {
      QFile f( resources_path.c_str() );
      f.copy(filename.c_str());
    }
    {
      if (!fileio::FileIo().IsRegularFile(filename))
      {
        TRACE("ERROR");
        TRACE(filename);
      }
      assert(fileio::FileIo().IsRegularFile(filename));
      OwnerFile b(filename);
      if (b.GetItems().empty())
      {
        TRACE("ERROR");
      }
      assert(!b.GetItems().empty());
    }
  }
}
#endif

bool ribi::foam::operator==(const OwnerFile& lhs,const OwnerFile& rhs) noexcept
{
  if (lhs.GetHeader() != rhs.GetHeader())
  {
    return false;
  }
  const std::vector<OwnerFileItem>& lhs_items = lhs.GetItems();
  const std::vector<OwnerFileItem>& rhs_items = rhs.GetItems();
  if (lhs_items.size() != rhs_items.size())
  {
    return false;
  }
  return std::equal(lhs_items.begin(),lhs_items.end(),rhs_items.begin());
}

bool ribi::foam::operator!=(const OwnerFile& lhs,const OwnerFile& rhs) noexcept
{
  return !(lhs == rhs);
}

std::istream& ribi::foam::operator>>(std::istream& is, OwnerFile& f)
{
  assert(f.m_items.empty()); //Make empty otherwise

  //Read header
  is >> f.m_header;
  assert(is);

  //Read items
  int n_items = 0;
  char opening_bracket = '\0';
  {
    //Eat comment
    char c = '\0';
    is >> c;
    assert(is);
    if (c >= '0' && c <= '9')
    {
      while (c != '(' && c != '{')
      {
        //Start eating n_items
        n_items *= 10;
        const int n = c - '0';
        assert(n >= 0 && n <= 9);
        n_items += n;
        is >> c;
        assert(is);
      }
    }
    opening_bracket = c;
    #ifndef NDEBUG
    if (!(opening_bracket == '(' || opening_bracket == '{'))
    {
      TRACE(opening_bracket);
      TRACE("ERROR");
    }
    #endif
    assert(opening_bracket == '(' || opening_bracket == '{');
  }
  assert(opening_bracket == '(' || opening_bracket == '{');
  if (opening_bracket == '(')
  {
    for (int i=0; i!=n_items; ++i)
    {
      OwnerFileItem item;
      is >> item;
      assert(is);
      f.m_items.push_back(item);
    }
  }
  else
  {
    assert(opening_bracket == '{');
    //Read once, push n_items times
    OwnerFileItem item;
    is >> item;
    assert(is);
    for (int i=0; i!=n_items; ++i)
    {
      f.m_items.push_back(item);
    }
  }
  //Eat comments until bracket close
  {
    char bracket_close = '\0';
    while (bracket_close != ')' && bracket_close != '}')
    {
      is >> bracket_close;
      assert(is);
    }
    assert(bracket_close == ')' || bracket_close == '}');
    assert(
         (opening_bracket == '(' && bracket_close == ')')
      || (opening_bracket == '{' && bracket_close == '}')
    );
  }
  return is;
}

std::ostream& ribi::foam::operator<<(std::ostream& os, const OwnerFile& f) noexcept
{
  os
    << f.GetHeader() << '\n'
    << "" << '\n'
    << f.m_items.size() << '\n'
    << "(" << '\n'
  ;

  for(const OwnerFileItem item: f.m_items)
  {
    os << item << '\n';
  }

  os
    << ")" << '\n'
  ;
  return os;
}

 

 

 

 

 

./CppOpenFoam/openfoamownerfileitem.h

 

#ifndef OPENFOAMOWNERFILEITEM_H
#define OPENFOAMOWNERFILEITEM_H

#include <vector>
#include <iosfwd>
#include "openfoamcellindex.h"

namespace ribi {
namespace foam {

///An item in an OpenFOAM boundary file
struct OwnerFileItem
{
  explicit OwnerFileItem(const CellIndex& cell_index = CellIndex(0));

  CellIndex GetCellIndex() const noexcept { return m_cell_index; }

  private:

  CellIndex m_cell_index;

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif

  friend class OpenFoamOwnerFile;
  friend std::istream& operator>>(std::istream& is, OwnerFileItem& f);
};

bool operator==(const OwnerFileItem& lhs, const OwnerFileItem& rhs);
bool operator!=(const OwnerFileItem& lhs, const OwnerFileItem& rhs);
std::ostream& operator<<(std::ostream& os, const OwnerFileItem& f);
std::istream& operator>>(std::istream& is, OwnerFileItem& f);

} //~namespace foam
} //~namespace ribi

#endif // OPENFOAMOWNERFILEITEM_H

 

 

 

 

 

./CppOpenFoam/openfoamownerfileitem.cpp

 

#include "openfoamownerfileitem.h"

#include <cassert>
#include <iostream>

#include "testtimer.h"
#include "trace.h"

ribi::foam::OwnerFileItem::OwnerFileItem(
  const CellIndex& cell_index
  )
  : m_cell_index{cell_index}
{
  #ifndef NDEBUG
  Test();
  assert(m_cell_index.Get() >= 0);
  #endif
}

#ifndef NDEBUG
void ribi::foam::OwnerFileItem::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
  //operator==
  {
    const OwnerFileItem i(CellIndex(123));
    assert(i == i);
    const OwnerFileItem j(CellIndex(123));
    assert(i == j);
    assert(j == i);
    assert(j == j);
  }
  //operator!=
  {
    const OwnerFileItem i(CellIndex(123));
    const OwnerFileItem j(CellIndex(234));
    assert(i != j);
    assert(j != i);
  }
  //operator<< and operator>>
  {
    const OwnerFileItem i(CellIndex(123));
    std::stringstream s;
    s << i;
    OwnerFileItem j;
    s >> j;
    if (i != j)
    {
      TRACE(i);
      TRACE(j);
    }
    assert(i == j);
  }
}
#endif

bool ribi::foam::operator==(const OwnerFileItem& lhs, const OwnerFileItem& rhs)
{
  return
       lhs.GetCellIndex() == rhs.GetCellIndex()
  ;
}

bool ribi::foam::operator!=(const OwnerFileItem& lhs, const OwnerFileItem& rhs)
{
  return !(lhs == rhs);
}

std::ostream& ribi::foam::operator<<(std::ostream& os, const OwnerFileItem& item)
{
  os << item.GetCellIndex();
  return os;
}

std::istream& ribi::foam::operator>>(std::istream& is, OwnerFileItem& f)
{
  is >> f.m_cell_index;
  assert(is);
  if (f.GetCellIndex().Get() < 0) TRACE(f.GetCellIndex());
  assert(f.GetCellIndex().Get() >= 0);
  return is;
}

 

 

 

 

 

./CppOpenFoam/openfoamparseerror.h

 

#ifndef RIBI_OPENFOAMPARSEERROR_H
#define RIBI_OPENFOAMPARSEERROR_H

#include <stdexcept>

namespace ribi {
namespace foam {

struct ParseError : public std::runtime_error
{
  explicit ParseError(
    const std::string& filename = "",
    const int line = -1);

  const std::string m_filename;
  const int m_line;

  std::string CreateErrorMsg(
    const std::string& filename,
    const int line) noexcept;
};

} //~namespace foam
} //~namespace ribi

#endif // RIBI_OPENFOAMPARSEERROR_H

 

 

 

 

 

./CppOpenFoam/openfoamparseerror.cpp

 

#include "openfoamparseerror.h"

#include <sstream>

ribi::foam::ParseError::ParseError(
  const std::string& filename,
  const int line)
: std::runtime_error(CreateErrorMsg(filename,line).c_str()),
  m_filename(filename),
  m_line(line)
{

}

std::string ribi::foam::ParseError::CreateErrorMsg(
  const std::string& filename,
  const int line) noexcept
{
  std::stringstream s;
  s << "OpenFOAM file parsing error in ";
  if (filename.empty())
  {
    s << "unknown file";
  }
  else
  {
    s << "file '" << filename << "'";
  }
  s << " in ";
  if (line < 0)
  {
    s << "unknown line";
  }
  else
  {
    s << "line " << line;
  }
  return s.str();
}

 

 

 

 

 

./CppOpenFoam/openfoampatchfieldtype.h

 

#ifndef RIBI_OPENFOAMPATCHFIELDTYPE_H
#define RIBI_OPENFOAMPATCHFIELDTYPE_H

namespace ribi {
namespace foam {

/// From http://openfoam.org/docs/user/mesh-description.php, pragraph 5.1.1.4 Boundary:
///   A boundary is a list of patches, each of which is associated with a boundary condition.
///   A patch is a list of face labels which clearly must contain only boundary faces
///   and no internal faces. The boundary is required to be closed,
///   i.e. the sum all boundary face area vectors equates to zero to machine tolerance.
/// To indicate internal faces, use no_patch_field
enum class PatchFieldType {
  advective,
  alphaSgsJayatillekeWallFunction,
  alphaSgsWallFunction,
  alphatJayatillekeWallFunction,
  alphatWallFunction,
  buoyantPressure,
  calculated,
  codedFixedValue,
  codedMixed,
  compressible_epsilonWallFunction,
  compressible_kqRWallFunction,
  compressible_omegaWallFunction,
  compressible_temperatureThermoBaffle1D_constSolidThermoPhysics,
  compressible_temperatureThermoBaffle1D_expoSolidThermoPhysics,
  compressible_turbulentHeatFluxTemperature,
  compressible_turbulentMixingLengthDissipationRateInlet,
  compressible_turbulentMixingLengthFrequencyInlet,
  compressible_turbulentTemperatureCoupledBaffle,
  compressible_turbulentTemperatureCoupledBaffleMixed,
  compressible_turbulentTemperatureRadCoupledMixed,
  cyclic,
  cyclicAMI,
  cyclicSlip,
  directionMixed,
  empty,
  externalWallHeatFluxTemperature,
  fan,
  fanPressure,
  fixedEnthalpy,
  fixedFluxPressure,
  fixedGradient,
  fixedInternalEnergy,
  fixedInternalValue,
  fixedPressureCompressibleDensity,
  fixedValue,
  freestream,
  freestreamPressure,
  gradientEnthalpy,
  gradientInternalEnergy,
  htcConvection,
  inletOutlet,
  inletOutletTotalTemperature,
  mapped,
  mappedField,
  mappedFixedInternalValue,
  mappedFixedPushedInternalValue,
  mixed,
  mixedEnthalpy,
  mixedInternalEnergy,
  muSgsUSpaldingWallFunction,
  multiphaseFixedFluxPressure,
  mutLowReWallFunction,
  mutURoughWallFunction,
  mutUSpaldingWallFunction,
  mutUWallFunction,
  mutkRoughWallFunction,
  mutkWallFunction,
  no_patch_field, //To indicate that a 'no boundary'; that is, an internal face
  nonuniformTransformCyclic,
  oscillatingFixedValue,
  outletInlet,
  outletMappedUniformInlet,
  partialSlip,
  patch,
  phaseHydrostaticPressure,
  processor,
  processorCyclic,
  rotatingTotalPressure,
  sliced,
  slip,
  symmetryPlane,
  syringePressure,
  timeVaryingMappedFixedValue,
  totalFlowRateAdvectiveDiffusive,
  totalPressure,
  totalTemperature,
  turbulentInlet,
  turbulentIntensityKineticEnergyInlet,
  uniformDensityHydrostaticPressure,
  uniformFixedValue,
  uniformTotalPressure,
  wall, //Used for defaultFaces
  wallHeatTransfer,
  waveSurfacePressure,
  waveTransmissive,
  wedge,
  zeroGradient,
  n_types //Used for debugging only, keep at last position
};

} //~namespace foam
} //~namespace ribi

#endif // RIBI_OPENFOAMPATCHFIELDTYPE_H

 

 

 

 

 

./CppOpenFoam/openfoampatchfieldtype.cpp

 

#include "openfoampatchfieldtype.h"

 

 

 

 

 

./CppOpenFoam/openfoampatchfieldtypes.h

 

#ifndef RIBI_OPENFOAMPATCHFIELDTYPES_H
#define RIBI_OPENFOAMPATCHFIELDTYPES_H

#include <string>
#include <vector>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#include <boost/bimap.hpp>
#pragma GCC diagnostic pop

#include "openfoampatchfieldtype.h"

namespace ribi {
namespace foam {

struct PatchFieldTypes
{
  static std::vector<PatchFieldType> GetAllTypes();
  static std::string ToStr(const PatchFieldType type);
  static PatchFieldType ToType(const std::string& s);

  private:
  static boost::bimap<PatchFieldType,std::string> m_map;
  static boost::bimap<PatchFieldType,std::string> CreateMap();

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif
};

std::ostream& operator<<(std::ostream& os, const PatchFieldType patch_field) noexcept;
std::istream& operator>>(std::istream& is, PatchFieldType& patch_field);

} //~namespace foam
} //~namespace ribi

#endif // RIBI_OPENFOAMPATCHFIELDTYPES_H

 

 

 

 

 

./CppOpenFoam/openfoampatchfieldtypes.cpp

 

#include "openfoampatchfieldtypes.h"

#include <stdexcept>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"

#include <boost/bimap.hpp>

#include "trace.h"

#pragma GCC diagnostic pop

boost::bimap<ribi::foam::PatchFieldType,std::string> ribi::foam::PatchFieldTypes::m_map;

boost::bimap<ribi::foam::PatchFieldType,std::string> ribi::foam::PatchFieldTypes::CreateMap()
{
  #ifndef NDEBUG
  Test();
  #endif

  boost::bimap<PatchFieldType,std::string> m;
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::advective,"advective"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::alphaSgsJayatillekeWallFunction,"alphaSgsJayatillekeWallFunction"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::alphaSgsWallFunction,"alphaSgsWallFunction"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::alphatJayatillekeWallFunction,"alphatJayatillekeWallFunction"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::alphatWallFunction,"alphatWallFunction"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::buoyantPressure,"buoyantPressure"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::calculated,"calculated"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::codedFixedValue,"codedFixedValue"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::codedMixed,"codedMixed"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::compressible_epsilonWallFunction,"compressible_epsilonWallFunction"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::compressible_kqRWallFunction,"compressible_kqRWallFunction"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::compressible_omegaWallFunction,"compressible_omegaWallFunction"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::compressible_temperatureThermoBaffle1D_constSolidThermoPhysics,"compressible_temperatureThermoBaffle1D_constSolidThermoPhysics"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::compressible_temperatureThermoBaffle1D_expoSolidThermoPhysics,"compressible_temperatureThermoBaffle1D_expoSolidThermoPhysics"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::compressible_turbulentHeatFluxTemperature,"compressible_turbulentHeatFluxTemperature"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::compressible_turbulentMixingLengthDissipationRateInlet,"compressible_turbulentMixingLengthDissipationRateInlet"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::compressible_turbulentMixingLengthFrequencyInlet,"compressible_turbulentMixingLengthFrequencyInlet"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::compressible_turbulentTemperatureCoupledBaffle,"compressible_turbulentTemperatureCoupledBaffle"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::compressible_turbulentTemperatureCoupledBaffleMixed,"compressible_turbulentTemperatureCoupledBaffleMixed"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::compressible_turbulentTemperatureRadCoupledMixed,"compressible_turbulentTemperatureRadCoupledMixed"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::cyclic,"cyclic"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::cyclicAMI,"cyclicAMI"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::cyclicSlip,"cyclicSlip"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::directionMixed,"directionMixed"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::empty,"empty"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::externalWallHeatFluxTemperature,"externalWallHeatFluxTemperature"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::fan,"fan"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::fanPressure,"fanPressure"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::fixedEnthalpy,"fixedEnthalpy"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::fixedFluxPressure,"fixedFluxPressure"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::fixedGradient,"fixedGradient"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::fixedInternalEnergy,"fixedInternalEnergy"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::fixedInternalValue,"fixedInternalValue"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::fixedPressureCompressibleDensity,"fixedPressureCompressibleDensity"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::fixedValue,"fixedValue"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::freestream,"freestream"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::freestreamPressure,"freestreamPressure"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::gradientEnthalpy,"gradientEnthalpy"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::gradientInternalEnergy,"gradientInternalEnergy"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::htcConvection,"htcConvection"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::inletOutlet,"inletOutlet"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::inletOutletTotalTemperature,"inletOutletTotalTemperature"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::mapped,"mapped"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::mappedField,"mappedField"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::mappedFixedInternalValue,"mappedFixedInternalValue"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::mappedFixedPushedInternalValue,"mappedFixedPushedInternalValue"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::mixed,"mixed"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::mixedEnthalpy,"mixedEnthalpy"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::mixedInternalEnergy,"mixedInternalEnergy"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::muSgsUSpaldingWallFunction,"muSgsUSpaldingWallFunction"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::multiphaseFixedFluxPressure,"multiphaseFixedFluxPressure"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::mutLowReWallFunction,"mutLowReWallFunction"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::mutURoughWallFunction,"mutURoughWallFunction"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::mutUSpaldingWallFunction,"mutUSpaldingWallFunction"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::mutUWallFunction,"mutUWallFunction"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::mutkRoughWallFunction,"mutkRoughWallFunction"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::mutkWallFunction,"mutkWallFunction"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::no_patch_field,"no_patch_field"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::nonuniformTransformCyclic,"nonuniformTransformCyclic"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::oscillatingFixedValue,"oscillatingFixedValue"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::outletInlet,"outletInlet"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::outletMappedUniformInlet,"outletMappedUniformInlet"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::partialSlip,"partialSlip"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::patch,"patch"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::phaseHydrostaticPressure,"phaseHydrostaticPressure"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::processor,"processor"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::processorCyclic,"processorCyclic"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::rotatingTotalPressure,"rotatingTotalPressure"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::sliced,"sliced"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::slip,"slip"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::symmetryPlane,"symmetryPlane"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::syringePressure,"syringePressure"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::timeVaryingMappedFixedValue,"timeVaryingMappedFixedValue"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::totalFlowRateAdvectiveDiffusive,"totalFlowRateAdvectiveDiffusive"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::totalPressure,"totalPressure"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::totalTemperature,"totalTemperature"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::turbulentInlet,"turbulentInlet"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::turbulentIntensityKineticEnergyInlet,"turbulentIntensityKineticEnergyInlet"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::uniformDensityHydrostaticPressure,"uniformDensityHydrostaticPressure"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::uniformFixedValue,"uniformFixedValue"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::uniformTotalPressure,"uniformTotalPressure"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::wall,"wall"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::wallHeatTransfer,"wallHeatTransfer"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::waveSurfacePressure,"waveSurfacePressure"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::waveTransmissive,"waveTransmissive"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::wedge,"wedge"));
  m.insert(boost::bimap<PatchFieldType,std::string>::value_type(PatchFieldType::zeroGradient,"zeroGradient"));
  return m;
}

std::vector<ribi::foam::PatchFieldType> ribi::foam::PatchFieldTypes::GetAllTypes()
{
  const std::vector<PatchFieldType> v {
    PatchFieldType::advective,
    PatchFieldType::alphaSgsJayatillekeWallFunction,
    PatchFieldType::alphaSgsWallFunction,
    PatchFieldType::alphatJayatillekeWallFunction,
    PatchFieldType::alphatWallFunction,
    PatchFieldType::buoyantPressure,
    PatchFieldType::calculated,
    PatchFieldType::codedFixedValue,
    PatchFieldType::codedMixed,
    PatchFieldType::compressible_epsilonWallFunction,
    PatchFieldType::compressible_kqRWallFunction,
    PatchFieldType::compressible_omegaWallFunction,
    PatchFieldType::compressible_temperatureThermoBaffle1D_constSolidThermoPhysics,
    PatchFieldType::compressible_temperatureThermoBaffle1D_expoSolidThermoPhysics,
    PatchFieldType::compressible_turbulentHeatFluxTemperature,
    PatchFieldType::compressible_turbulentMixingLengthDissipationRateInlet,
    PatchFieldType::compressible_turbulentMixingLengthFrequencyInlet,
    PatchFieldType::compressible_turbulentTemperatureCoupledBaffle,
    PatchFieldType::compressible_turbulentTemperatureCoupledBaffleMixed,
    PatchFieldType::compressible_turbulentTemperatureRadCoupledMixed,
    PatchFieldType::cyclic,
    PatchFieldType::cyclicAMI,
    PatchFieldType::cyclicSlip,
    PatchFieldType::directionMixed,
    PatchFieldType::empty,
    PatchFieldType::externalWallHeatFluxTemperature,
    PatchFieldType::fan,
    PatchFieldType::fanPressure,
    PatchFieldType::fixedEnthalpy,
    PatchFieldType::fixedFluxPressure,
    PatchFieldType::fixedGradient,
    PatchFieldType::fixedInternalEnergy,
    PatchFieldType::fixedInternalValue,
    PatchFieldType::fixedPressureCompressibleDensity,
    PatchFieldType::fixedValue,
    PatchFieldType::freestream,
    PatchFieldType::freestreamPressure,
    PatchFieldType::gradientEnthalpy,
    PatchFieldType::gradientInternalEnergy,
    PatchFieldType::htcConvection,
    PatchFieldType::inletOutlet,
    PatchFieldType::inletOutletTotalTemperature,
    PatchFieldType::mapped,
    PatchFieldType::mappedField,
    PatchFieldType::mappedFixedInternalValue,
    PatchFieldType::mappedFixedPushedInternalValue,
    PatchFieldType::mixed,
    PatchFieldType::mixedEnthalpy,
    PatchFieldType::mixedInternalEnergy,
    PatchFieldType::muSgsUSpaldingWallFunction,
    PatchFieldType::multiphaseFixedFluxPressure,
    PatchFieldType::mutLowReWallFunction,
    PatchFieldType::mutURoughWallFunction,
    PatchFieldType::mutUSpaldingWallFunction,
    PatchFieldType::mutUWallFunction,
    PatchFieldType::mutkRoughWallFunction,
    PatchFieldType::mutkWallFunction,
    PatchFieldType::no_patch_field,
    PatchFieldType::nonuniformTransformCyclic,
    PatchFieldType::oscillatingFixedValue,
    PatchFieldType::outletInlet,
    PatchFieldType::outletMappedUniformInlet,
    PatchFieldType::partialSlip,
    PatchFieldType::patch,
    PatchFieldType::phaseHydrostaticPressure,
    PatchFieldType::processor,
    PatchFieldType::processorCyclic,
    PatchFieldType::rotatingTotalPressure,
    PatchFieldType::sliced,
    PatchFieldType::slip,
    PatchFieldType::symmetryPlane,
    PatchFieldType::syringePressure,
    PatchFieldType::timeVaryingMappedFixedValue,
    PatchFieldType::totalFlowRateAdvectiveDiffusive,
    PatchFieldType::totalPressure,
    PatchFieldType::totalTemperature,
    PatchFieldType::turbulentInlet,
    PatchFieldType::turbulentIntensityKineticEnergyInlet,
    PatchFieldType::uniformDensityHydrostaticPressure,
    PatchFieldType::uniformFixedValue,
    PatchFieldType::uniformTotalPressure,
    PatchFieldType::wall,
    PatchFieldType::wallHeatTransfer,
    PatchFieldType::waveSurfacePressure,
    PatchFieldType::waveTransmissive,
    PatchFieldType::wedge,
    PatchFieldType::zeroGradient
  };
  assert(static_cast<int>(v.size()) == static_cast<int>(PatchFieldType::n_types));
  return v;
}

#ifndef NDEBUG
void ribi::foam::PatchFieldTypes::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const std::vector<PatchFieldType> v = GetAllTypes();
  const std::size_t sz = v.size();
  for (std::size_t i=0; i!=sz; ++i)
  {
    assert(i < v.size());
    const PatchFieldType t = v[i];
    const std::string s = ToStr(t);
    assert(!s.empty());
    const PatchFieldType u = ToType(s);
    assert(u == t);
  }
}
#endif

std::string ribi::foam::PatchFieldTypes::ToStr(const PatchFieldType type)
{
  if (m_map.left.empty()) m_map = CreateMap();
  assert(!m_map.left.empty());
  assert(m_map.left.count(type) == 1);
  const std::string s = m_map.left.find(type)->second;
  return s;
}

ribi::foam::PatchFieldType ribi::foam::PatchFieldTypes::ToType(const std::string& s)
{
  if (m_map.right.empty()) m_map = CreateMap();
  assert(!m_map.right.empty());
  #ifndef NDEBUG
  if(m_map.right.count(s) != 1)
  {
    TRACE("ERROR");
    TRACE(s);
    TRACE(m_map.right.count(s));
  }

  #endif
  assert(m_map.right.count(s) == 1);
  const PatchFieldType t = m_map.right.find(s)->second;
  return t;
}

std::ostream& ribi::foam::operator<<(std::ostream& os, const PatchFieldType patch_field) noexcept
{
  os << PatchFieldTypes::ToStr(patch_field);
  return os;
}

std::istream& ribi::foam::operator>>(std::istream& is, PatchFieldType& patch_field)
{
  std::string s;
  is >> s;
  patch_field = PatchFieldTypes::ToType(s);
  return is;
}

 

 

 

 

 

./CppOpenFoam/openfoampoint.h

 

#ifndef RIBI_OPENFOAMPOINT_H
#define RIBI_OPENFOAMPOINT_H

#include "openfoampointsfileitem.h"

namespace ribi {
namespace foam {

typedef PointsFileItem Point;

} //~namespace foam
} //~namespace ribi


#endif // RIBI_OPENFOAMPOINT_H

 

 

 

 

 

./CppOpenFoam/openfoampoint.cpp

 

#include "openfoampoint.h"

 

 

 

 

 

./CppOpenFoam/openfoampointindex.h

 

#ifndef RIBI_OPENFOAMPOINTINDEX_H
#define RIBI_OPENFOAMPOINTINDEX_H

#include <iosfwd>

namespace ribi {
namespace foam {

///The index in the 'points' file
struct PointIndex
{
  explicit PointIndex(const int index = 0);
  int Get() const noexcept { return m_index; }
  PointIndex& operator++() noexcept;   //Prefix
  PointIndex operator++(int) noexcept; //Postfix
  PointIndex& operator--() noexcept;   //Prefix
  PointIndex operator--(int) noexcept; //Postfix

  PointIndex& operator+=(const PointIndex& rhs) noexcept;
  PointIndex& operator-=(const PointIndex& rhs) noexcept;

  private:
  int m_index;
  friend std::istream& operator>>(std::istream& is, PointIndex& face_index);
};

std::ostream& operator<<(std::ostream& os, const PointIndex& face_index) noexcept;
std::istream& operator>>(std::istream& is, PointIndex& face_index);

const PointIndex operator+(const PointIndex& lhs, const PointIndex& rhs) noexcept;
const PointIndex operator-(const PointIndex& lhs, const PointIndex& rhs) noexcept;

bool operator==(const PointIndex& lhs, const PointIndex& rhs) noexcept;
bool operator!=(const PointIndex& lhs, const PointIndex& rhs) noexcept;
bool operator<(const PointIndex& lhs, const PointIndex& rhs) noexcept;
bool operator>(const PointIndex& lhs, const PointIndex& rhs) noexcept;
bool operator<=(const PointIndex& lhs, const PointIndex& rhs) noexcept;
bool operator>=(const PointIndex& lhs, const PointIndex& rhs) noexcept;

} //~namespace foam
} //~namespace ribi

#endif // RIBI_OPENFOAMPOINTINDEX_H

 

 

 

 

 

./CppOpenFoam/openfoampointindex.cpp

 

#include "openfoampointindex.h"

#include <cassert>
#include <iostream>
#include <stdexcept>

ribi::foam::PointIndex::PointIndex(const int index)
  : m_index(index)
{
  assert(m_index >= 0
    && "A PointIndex must be zero or a positive value");
  if (index < 0)
  {
     throw std::logic_error("A PointIndex must be zero or a positive value");
  }
}

ribi::foam::PointIndex& ribi::foam::PointIndex::operator++() noexcept
{
  ++m_index;
  return *this;
}

ribi::foam::PointIndex ribi::foam::PointIndex::operator++(int) noexcept
{
  PointIndex old(*this);
  ++(*this);
  return old;
}

ribi::foam::PointIndex& ribi::foam::PointIndex::operator--() noexcept
{
  --m_index;
  return *this;
}

ribi::foam::PointIndex ribi::foam::PointIndex::operator--(int) noexcept
{
  PointIndex old(*this);
  --(*this);
  return old;
}

ribi::foam::PointIndex& ribi::foam::PointIndex::operator+=(const PointIndex& rhs) noexcept
{
  m_index += rhs.Get();
  assert(m_index >= 0
    && "A PointIndex must be zero or a positive value");
  return *this;
}

ribi::foam::PointIndex& ribi::foam::PointIndex::operator-=(const PointIndex& rhs) noexcept
{
  assert(rhs.Get() <= m_index);
  m_index -= rhs.Get();
  assert(m_index >= 0
    && "A PointIndex must be zero or a positive value");
  return *this;
}


std::ostream& ribi::foam::operator<<(std::ostream& os, const PointIndex& face_index) noexcept
{
  os << face_index.Get();
  return os;
}

std::istream& ribi::foam::operator>>(std::istream& is, PointIndex& face_index)
{
  is >> face_index.m_index;
  assert(is);
  return is;
}

bool ribi::foam::operator==(const PointIndex& lhs, const PointIndex& rhs) noexcept
{
  return lhs.Get() == rhs.Get();
}

bool ribi::foam::operator!=(const PointIndex& lhs, const PointIndex& rhs) noexcept
{
  return !(lhs == rhs);
}

bool ribi::foam::operator<(const PointIndex& lhs, const PointIndex& rhs) noexcept
{
  return lhs.Get() < rhs.Get();
}

bool ribi::foam::operator>(const PointIndex& lhs, const PointIndex& rhs) noexcept
{
  return lhs.Get() > rhs.Get();
}

bool ribi::foam::operator<=(const PointIndex& lhs, const PointIndex& rhs) noexcept
{
  return !(lhs > rhs);
}

bool ribi::foam::operator>=(const PointIndex& lhs, const PointIndex& rhs) noexcept
{
  return !(lhs < rhs);
}

const ribi::foam::PointIndex ribi::foam::operator+(const PointIndex& lhs, const PointIndex& rhs) noexcept
{
  return PointIndex(lhs.Get() + rhs.Get());
}

const ribi::foam::PointIndex ribi::foam::operator-(const PointIndex& lhs, const PointIndex& rhs) noexcept
{
  assert(lhs >= rhs);
  return PointIndex(lhs.Get() - rhs.Get());
}

 

 

 

 

 

./CppOpenFoam/openfoampointsfile.h

 

#ifndef RIBI_OPENFOAMPOINTSFILE_H
#define RIBI_OPENFOAMPOINTSFILE_H

#include <iosfwd>
#include <string>
#include <vector>
#include "fileiofwd.h"
#include "openfoamfwd.h"
#include "openfoamheader.h"
#include "openfoampointsfileitem.h"

namespace ribi {
namespace foam {

///Reads and writes an OpenFOAM boundary file
struct PointsFile
{
  explicit PointsFile(const std::string& filename) : PointsFile(Parse(filename)) {}
  explicit PointsFile(
    const Header header = GetDefaultHeader(),
    const std::vector<PointsFileItem>& items = {});

  static Header GetDefaultHeader() noexcept;
  const Header& GetHeader() const noexcept { return m_header; }
  const std::vector<PointsFileItem>& GetItems() const noexcept { return m_items; }

  private:
  explicit PointsFile(std::istream& is) : PointsFile(Parse(is)) {}

  ///The OpenFOAM header
  Header m_header;
  ///The items faces contains
  std::vector<PointsFileItem> m_items;

  static PointsFile Parse(std::istream& is);
  static PointsFile Parse(const std::string& filename);

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif

  friend std::ostream& operator<<(std::ostream& os, const PointsFile& f) noexcept;
  friend std::istream& operator>>(std::istream& is, PointsFile& f);
};

bool operator==(const PointsFile& lhs,const PointsFile& rhs) noexcept;
bool operator!=(const PointsFile& lhs,const PointsFile& rhs) noexcept;
std::ostream& operator<<(std::ostream& os, const PointsFile& f) noexcept;
std::istream& operator>>(std::istream& is, PointsFile& f);

} //~namespace foam
} //~namespace ribi

#endif // RIBI_OPENFOAMPOINTSFILE_H

 

 

 

 

 

./CppOpenFoam/openfoampointsfile.cpp

 

#include "openfoampointsfile.h"

#include <cassert>
#include <fstream>
#include <iostream>
#include <stdexcept>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"

#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/lexical_cast.hpp>

#include <QFile>

#include "fileio.h"

#include "openfoamheader.h"
#include "openfoampointsfileitem.h"
#include "testtimer.h"
#include "trace.h"
#pragma GCC diagnostic pop


ribi::foam::PointsFile::PointsFile(
  const Header header,
  const std::vector<PointsFileItem>& items)
  : m_header{header},
    m_items(items)
{
  #ifndef NDEBUG
  Test();
  #endif
}

ribi::foam::Header ribi::foam::PointsFile::GetDefaultHeader() noexcept
{
  return Header("vectorField","constant/polyMesh","","points");
}

ribi::foam::PointsFile ribi::foam::PointsFile::Parse(std::istream& is)
{
  PointsFile b;
  is >> b;
  assert(is);
  return b;
}

ribi::foam::PointsFile ribi::foam::PointsFile::Parse(const std::string& filename)
{
  const std::string tmp_filename { fileio::FileIo().GetTempFileName() };
  fileio::FileIo().CopyFile(filename,tmp_filename);
  Header::CleanFile(tmp_filename);
  std::ifstream f(tmp_filename.c_str());
  ribi::foam::PointsFile file { Parse(f) };
  f.close();
  fileio::FileIo().DeleteFile(tmp_filename);
  return file;
}

#ifndef NDEBUG
void ribi::foam::PointsFile::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
  typedef boost::geometry::model::point<double,3,boost::geometry::cs::cartesian> Coordinat3D;

  //Some initial data
  const Header header("some_name","some_location","some_object");
  std::vector<PointsFileItem> items;
  for (int i=1; i!=4; ++i)
  {
    PointsFileItem item(
      Coordinat3D(
        static_cast<double>(i) * 1.1,
        static_cast<double>(i) * 2.2,
        static_cast<double>(i) * 3.3
      )
    );
    items.push_back(item);
  }
  //operator==
  {
    const PointsFile b(header,items);
    const PointsFile c(header,items);
    assert(header == header);
    assert(b == c);
  }
  //operator!=
  {
    const PointsFile b(header,items);
    const Header other_header("some_other_name","some_other_location","some_other_object");
    assert(header != other_header);
    const PointsFile c(other_header,items);
    assert(b != c);
  }
  //operator!=
  {
    const PointsFile b(header,items);
    std::vector<PointsFileItem> other_items;
    for (int i=1; i!=3; ++i)
    {
      PointsFileItem item(
        Coordinat3D(
          static_cast<double>(i) * 4.4,
          static_cast<double>(i) * 5.5,
          static_cast<double>(i) * 6.6
        )
      );
      other_items.push_back(item);
    }
    const PointsFile c(header,other_items);
    assert(b != c);
  }
  //Stream conversion
  {
    const PointsFile b(header,items);
    std::stringstream s;
    s << b;
    PointsFile c;
    s >> c;
    if (b != c)
    {
      TRACE(b);
      TRACE(c);
    }
    assert(b == c);
  }
  //Read from testing file
  for (int test_index = 0; test_index!=5; ++test_index)
  {
    std::string filename_appendix;
    switch (test_index)
    {
      case 0: filename_appendix = "_1x1x1"; break;
      case 1: filename_appendix = "_1x1x2"; break;
      case 2: filename_appendix = "_1x2x2"; break;
      case 3: filename_appendix = "_2x2x2"; break;
      case 4: filename_appendix = "_3x4x5"; break;
      default: assert(!"Should never get here");
        throw std::logic_error("foam::Files::CreateTestFiles: unknown test index");
    }
    assert(!filename_appendix.empty());
    const std::string filename_base { GetDefaultHeader().GetObject() };
    const std::string filename = filename_base + filename_appendix;
    const std::string resources_path { ":/CppOpenFoam/files/" + filename };

    {
      QFile f( resources_path.c_str() );
      f.copy(filename.c_str());
    }
    {
      if (!fileio::FileIo().IsRegularFile(filename))
      {
        TRACE("ERROR");
        TRACE(filename);
      }
      assert(fileio::FileIo().IsRegularFile(filename));
      PointsFile b(filename);
      if (b.GetItems().empty())
      {
        TRACE("ERROR");
      }
      assert(!b.GetItems().empty());
    }
  }
}
#endif

bool ribi::foam::operator==(const PointsFile& lhs,const PointsFile& rhs) noexcept
{
  if (lhs.GetHeader() != rhs.GetHeader())
  {
    return false;
  }
  const std::vector<PointsFileItem>& lhs_items = lhs.GetItems();
  const std::vector<PointsFileItem>& rhs_items = rhs.GetItems();
  if (lhs_items.size() != rhs_items.size())
  {
    return false;
  }
  return std::equal(lhs_items.begin(),lhs_items.end(),rhs_items.begin());
}

bool ribi::foam::operator!=(const PointsFile& lhs,const PointsFile& rhs) noexcept
{
  return !(lhs == rhs);
}

std::istream& ribi::foam::operator>>(std::istream& is, PointsFile& f)
{
  assert(f.m_items.empty()); //Make empty otherwise

  //Read header
  is >> f.m_header;
  assert(is);

  //Read items
  int n_items = 0;
  char opening_bracket = '\0';
  {
    //Eat comment
    char c = '\0';
    is >> c;
    assert(is);
    if (c >= '0' && c <= '9')
    {
      while (c != '(' && c != '{')
      {
        //Start eating n_items
        n_items *= 10;
        const int n = c - '0';
        assert(n >= 0 && n <= 9);
        n_items += n;
        is >> c;
        assert(is);
      }
    }
    opening_bracket = c;
    #ifndef NDEBUG
    if (!(opening_bracket == '(' || opening_bracket == '{'))
    {
      TRACE(opening_bracket);
      TRACE("ERROR");
    }
    #endif
    assert(opening_bracket == '(' || opening_bracket == '{');
  }
  assert(opening_bracket == '(' || opening_bracket == '{');
  if (opening_bracket == '(')
  {
    for (int i=0; i!=n_items; ++i)
    {
      PointsFileItem item;
      is >> item;
      assert(is);
      f.m_items.push_back(item);
    }
  }
  else
  {
    assert(opening_bracket == '{');
    //Read once, push n_items times
    PointsFileItem item;
    is >> item;
    assert(is);
    for (int i=0; i!=n_items; ++i)
    {
      f.m_items.push_back(item);
    }
  }
  //Eat comments until bracket close
  {
    char bracket_close = '\0';
    while (bracket_close != ')' && bracket_close != '}')
    {
      is >> bracket_close;
      assert(is);
    }
    assert(bracket_close == ')' || bracket_close == '}');
    assert(
         (opening_bracket == '(' && bracket_close == ')')
      || (opening_bracket == '{' && bracket_close == '}')
    );
  }
  return is;
}

std::ostream& ribi::foam::operator<<(std::ostream& os, const PointsFile& f) noexcept
{
  os
    << f.GetHeader() << '\n'
    << "" << '\n'
    << f.m_items.size() << '\n'
    << "(" << '\n'
  ;

  for(const PointsFileItem item: f.m_items)
  {
    os << item << '\n';
  }

  os
    << ")" << '\n'
  ;
  return os;
}

 

 

 

 

 

./CppOpenFoam/openfoampointsfileitem.h

 

#ifndef RIBI_OPENFOAMPOINTSFILEITEM_H
#define RIBI_OPENFOAMPOINTSFILEITEM_H

#include <array>
#include <vector>
#include <iosfwd>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wunused-but-set-parameter"
#include <boost/geometry.hpp>
#pragma GCC diagnostic pop

namespace ribi {
namespace foam {

///An item in an OpenFOAM 'points' file
struct PointsFileItem
{
  typedef boost::geometry::model::point<double,3,boost::geometry::cs::cartesian> Coordinat3D;

  explicit PointsFileItem(
    const Coordinat3D& coordinat = Coordinat3D(0.0, 0.0, 0.0)
  );

  const Coordinat3D& GetCoordinat() const noexcept { return m_coordinat; }
        Coordinat3D& GetCoordinat()       noexcept { return m_coordinat; }

  private:

  Coordinat3D m_coordinat;

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif

  friend class OpenFoamPointsFile;
  friend std::istream& operator>>(std::istream& is, PointsFileItem& f);
};

bool operator==(const PointsFileItem& lhs, const PointsFileItem& rhs) noexcept;
bool operator!=(const PointsFileItem& lhs, const PointsFileItem& rhs) noexcept;
std::ostream& operator<<(std::ostream& os, const PointsFileItem& f) noexcept;
std::istream& operator>>(std::istream& is, PointsFileItem& f);

} //~namespace foam
} //~namespace ribi



#endif // RIBI_OPENFOAMPOINTSFILEITEM_H

 

 

 

 

 

./CppOpenFoam/openfoampointsfileitem.cpp

 

#include "openfoampointsfileitem.h"

#include <cassert>
#include <iostream>
#include <sstream>
#include "fuzzy_equal_to.h"
#include "testtimer.h"
#include "trace.h"

ribi::foam::PointsFileItem::PointsFileItem(
  const Coordinat3D& coordinat
  )
  : m_coordinat(coordinat)
{
  #ifndef NDEBUG
  Test();
  #endif
}

#ifndef NDEBUG
void ribi::foam::PointsFileItem::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
  //operator== and operator!=
  {
    const PointsFileItem i( Coordinat3D(1.1,2.2,3.3) );
    PointsFileItem j( Coordinat3D(2.2,3.3,4.4) );
    assert(i == i);
    assert(i != j);
    assert(j != i);
    assert(j == j);
  }
  //operator<< and operator>>
  {
    const PointsFileItem i( Coordinat3D(1.1,2.2,3.3) );
    std::stringstream s;
    s << i;
    PointsFileItem j;
    s >> j;
    if (i != j)
    {
      TRACE(i);
      TRACE(j);
    }
    assert(i == j);
  }
}
#endif

bool ribi::foam::operator==(const PointsFileItem& lhs, const PointsFileItem& rhs) noexcept
{
  const double abs_tolerance = 0.001;
  #ifdef USE_CUSTOM_RIBI_COORDINAT3D
  return
        fuzzy_equal_to_abs(abs_tolerance)(lhs.GetCoordinat().GetX(),rhs.GetCoordinat().GetX())
     && fuzzy_equal_to_abs(abs_tolerance)(lhs.GetCoordinat().GetY(),rhs.GetCoordinat().GetY())
     && fuzzy_equal_to_abs(abs_tolerance)(lhs.GetCoordinat().GetZ(),rhs.GetCoordinat().GetZ())
  ;
  #else
  using boost::geometry::get;
  return
        fuzzy_equal_to_abs(abs_tolerance)(get<0>(lhs.GetCoordinat()),get<0>(rhs.GetCoordinat()))
     && fuzzy_equal_to_abs(abs_tolerance)(get<1>(lhs.GetCoordinat()),get<1>(rhs.GetCoordinat()))
     && fuzzy_equal_to_abs(abs_tolerance)(get<2>(lhs.GetCoordinat()),get<2>(rhs.GetCoordinat()))
  ;
  #endif
}

bool ribi::foam::operator!=(const PointsFileItem& lhs, const PointsFileItem& rhs) noexcept
{
  return !(lhs == rhs);
}

std::ostream& ribi::foam::operator<<(std::ostream& os, const PointsFileItem& item) noexcept
{
  #ifdef USE_CUSTOM_RIBI_COORDINAT3D
  os
    << "("
    << item.GetCoordinat().GetX() << " "
    << item.GetCoordinat().GetY() << " "
    << item.GetCoordinat().GetZ()
    << ")"
  ;
  #else
  using boost::geometry::get;
  os
    << "("
    << get<0>(item.GetCoordinat()) << " "
    << get<1>(item.GetCoordinat()) << " "
    << get<2>(item.GetCoordinat())
    << ")"
  ;
  #endif
  return os;
}

std::istream& ribi::foam::operator>>(std::istream& is, PointsFileItem& f)
{

  {
    char bracket_open;
    is >> bracket_open;
    assert(bracket_open == '(');
  }
  {
    double x = 0.0;
    {
      is >> x;
      assert(is);
    }
    double y = 0.0;
    {
      is >> y;
      assert(is);
    }
    double z = 0.0;
    {
      is >> z;
      assert(is);
    }
    f.m_coordinat = decltype(f.m_coordinat)(x,y,z);
  }
  {
    char bracket_close;
    is >> bracket_close;
    assert(is);
    assert(bracket_close == ')');
  }
  return is;
}

 

 

 

 

 

./CppOpenFoam/openfoampressurefile.h

 

#ifndef RIBI_OPENFOAMPRESSUREFILE_H
#define RIBI_OPENFOAMPRESSUREFILE_H

#include <array>
#include <iosfwd>
#include <vector>
#include "openfoamfwd.h"
#include "openfoamheader.h"
#include "openfoampatchfieldtype.h"

namespace ribi {
namespace foam {

///Reads and writes an OpenFOAM pressure file, which has 'P' as its default name
struct PressureFile
{
  explicit PressureFile(
    const Header header = GetDefaultHeader()
  );

  static Header GetDefaultHeader() noexcept;
  const Header& GetHeader() const noexcept { return m_header; }
        Header& GetHeader()       noexcept { return m_header; }

  void SetBoundaryField(const std::string& boundary_field) noexcept { m_boundary_field = boundary_field; }

  //Cannot use this variant, as the boundary has very variable form
  //void SetBoundaryField(const std::vector<std::pair<std::string,PatchFieldType>>& boundary_field) noexcept { m_boundary_field = boundary_field; }
  void SetDimensions(const std::array<int,7>& dimensions) noexcept { m_dimensions = dimensions; }
  void SetInternalField(const std::string& internal_field) noexcept { m_internal_field = internal_field; }

  private:

  std::string m_boundary_field;
  //Cannot use this variant, as the boundary has very variable form
  //std::vector<std::pair<std::string,PatchFieldType>> m_boundary_field;
  std::array<int,7> m_dimensions;

  ///The OpenFOAM header
  Header m_header;
  std::string m_internal_field;

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif

  friend std::ostream& operator<<(std::ostream& os, const PressureFile& f) noexcept;
};

std::ostream& operator<<(std::ostream& os, const PressureFile& f) noexcept;

} //~namespace foam
} //~namespace ribi

#endif // RIBI_OPENFOAMPRESSUREFILE_H

 

 

 

 

 

./CppOpenFoam/openfoampressurefile.cpp

 

#include "openfoampressurefile.h"

#include <cassert>
#include <fstream>
#include <iostream>
#include <stdexcept>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"

#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/lexical_cast.hpp>

#include <QFile>

#include "fileio.h"

#include "openfoamheader.h"
#include "openfoampatchfieldtypes.h"
#include "testtimer.h"
#include "trace.h"
#pragma GCC diagnostic pop


ribi::foam::PressureFile::PressureFile(
  const Header header
) : m_boundary_field{},
    m_dimensions{ {} },
    m_header{header},
    m_internal_field{}
{
  #ifndef NDEBUG
  Test();
  #endif
}

ribi::foam::Header ribi::foam::PressureFile::GetDefaultHeader() noexcept
{
  return Header("volScalarField","0","","p");
}

#ifndef NDEBUG
void ribi::foam::PressureFile::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
}
#endif

std::ostream& ribi::foam::operator<<(std::ostream& os, const PressureFile& f) noexcept
{
  os
    << f.GetHeader() << '\n'
    << "" << '\n'
    << "dimensions ["
      << f.m_dimensions[0] << " "
      << f.m_dimensions[1] << " "
      << f.m_dimensions[2] << " "
      << f.m_dimensions[3] << " "
      << f.m_dimensions[4] << " "
      << f.m_dimensions[5] << " "
      << f.m_dimensions[6]
      << "];" << '\n'
    << "" << '\n'
    << "internalField " << f.m_internal_field << ";\n"
    << "" << '\n'
    << "boundaryField" << '\n'
    << "{" << '\n'
  ;
  os << f.m_boundary_field << '\n';
  /*
  for (const auto& p: f.m_boundary_field)
  {
    os
      << "  " << p.first << '\n'
      << "  {\n"
      << "    type " << PatchFieldTypes::ToStr(p.second) << ";\n"
      << "  }\n"
    ;
  }
  */
  os
    << "}" << '\n'
  ;
  return os;
}

 

 

 

 

 

./CppOpenFoam/openfoamraspropertiesfile.h

 

#ifndef OPENFOAMRASPROPERTIESFILE_H
#define OPENFOAMRASPROPERTIESFILE_H

#include <iosfwd>
#include <vector>
#include "openfoamfwd.h"
#include "openfoamheader.h"

namespace ribi {
namespace foam {

///Reads and writes an OpenFOAM thermophysicalProperties file
struct RasPropertiesFile
{
  explicit RasPropertiesFile(
    const Header& header = GetDefaultHeader()
  );

  static Header GetDefaultHeader() noexcept;
  const Header& GetHeader() const noexcept { return m_header; }

  private:

  ///The OpenFOAM header
  Header m_header;

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif

  friend std::ostream& operator<<(std::ostream& os, const RasPropertiesFile& f) noexcept;
};

std::ostream& operator<<(std::ostream& os, const RasPropertiesFile& f) noexcept;

} //~namespace foam
} //~namespace ribi

#endif // OPENFOAMRASPROPERTIESFILE_H

 

 

 

 

 

./CppOpenFoam/openfoamraspropertiesfile.cpp

 

#include "openfoamraspropertiesfile.h"

#include <cassert>
#include <fstream>
#include <iostream>
#include <stdexcept>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"

#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/lexical_cast.hpp>

#include <QFile>

#include "fileio.h"

#include "openfoamheader.h"
#include "testtimer.h"
#include "trace.h"
#pragma GCC diagnostic pop


ribi::foam::RasPropertiesFile::RasPropertiesFile(
  const Header& header
)
  : m_header{header}
{
  #ifndef NDEBUG
  Test();
  #endif
}

ribi::foam::Header ribi::foam::RasPropertiesFile::GetDefaultHeader() noexcept
{
  return Header("dictionary","constant","","RASProperties");
}

#ifndef NDEBUG
void ribi::foam::RasPropertiesFile::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
}
#endif

std::ostream& ribi::foam::operator<<(std::ostream& os, const RasPropertiesFile& f) noexcept
{
  os
    << f.GetHeader() << '\n'
    << "" << '\n'
    << "RASModel realizableKE;\n"
    << "\n"
    << "turbulence on;\n"
    << "\n"
    << "printCoeffs on;\n"
  ;
  return os;
}

 

 

 

 

 

./CppOpenFoam/openfoamtemperaturefile.h

 

#ifndef RIBI_OPENFOAMTEMPERATUREFILE_H
#define RIBI_OPENFOAMTEMPERATUREFILE_H

#include <array>
#include <iosfwd>
#include <vector>
#include "openfoamfwd.h"
#include "openfoamheader.h"
#include "openfoampatchfieldtype.h"

namespace ribi {
namespace foam {

///Reads and writes an OpenFOAM pressure file, which has 'P' as its default name
struct TemperatureFile
{
  explicit TemperatureFile(
    const Header header = GetDefaultHeader()
  );

  static Header GetDefaultHeader() noexcept;
  const Header& GetHeader() const noexcept { return m_header; }
        Header& GetHeader()       noexcept { return m_header; }

  void SetBoundaryField(const std::string& boundary_field) noexcept { m_boundary_field = boundary_field; }
  //Cannot use this variant, as the boundary has very variable form
  //void SetBoundaryField(const std::vector<std::pair<std::string,PatchFieldType>>& boundary_field) noexcept { m_boundary_field = boundary_field; }

  void SetDimensions(const std::array<int,7>& dimensions) noexcept { m_dimensions = dimensions; }
  void SetInternalField(const std::string& internal_field) noexcept { m_internal_field = internal_field; }

  private:

  std::string m_boundary_field;
  //Cannot use this variant, as the boundary has very variable form
  //std::vector<std::pair<std::string,PatchFieldType>> m_boundary_field;
  std::array<int,7> m_dimensions;

  ///The OpenFOAM header
  Header m_header;
  std::string m_internal_field;

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif

  friend std::ostream& operator<<(std::ostream& os, const TemperatureFile& f) noexcept;
};

std::ostream& operator<<(std::ostream& os, const TemperatureFile& f) noexcept;

} //~namespace foam
} //~namespace ribi

#endif // RIBI_OPENFOAMTEMPERATUREFILE_H

 

 

 

 

 

./CppOpenFoam/openfoamtemperaturefile.cpp

 

#include "openfoamtemperaturefile.h"

#include <cassert>
#include <fstream>
#include <iostream>
#include <stdexcept>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"

#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/lexical_cast.hpp>

#include <QFile>

#include "fileio.h"

#include "openfoamheader.h"
#include "openfoampatchfieldtypes.h"
#include "testtimer.h"
#include "trace.h"
#pragma GCC diagnostic pop


ribi::foam::TemperatureFile::TemperatureFile(
  const Header header
) : m_boundary_field{},
    m_dimensions{ {} },
    m_header{header},
    m_internal_field{}
{
  #ifndef NDEBUG
  Test();
  #endif
}

ribi::foam::Header ribi::foam::TemperatureFile::GetDefaultHeader() noexcept
{
  return Header("volScalarField","0","","T");
}

#ifndef NDEBUG
void ribi::foam::TemperatureFile::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
}
#endif

std::ostream& ribi::foam::operator<<(std::ostream& os, const TemperatureFile& f) noexcept
{
  os
    << f.GetHeader() << '\n'
    << "" << '\n'
    << "dimensions ["
      << f.m_dimensions[0] << " "
      << f.m_dimensions[1] << " "
      << f.m_dimensions[2] << " "
      << f.m_dimensions[3] << " "
      << f.m_dimensions[4] << " "
      << f.m_dimensions[5] << " "
      << f.m_dimensions[6]
      << "];" << '\n'
    << "" << '\n'
    << "internalField " << f.m_internal_field << ";\n"
    << "" << '\n'
    << "boundaryField" << '\n'
    << "{" << '\n'
  ;
  os << f.m_boundary_field << '\n';
  /*
  for (const auto& p: f.m_boundary_field)
  {
    os
      << "  " << p.first << '\n'
      << "  {\n"
      << "    type " << PatchFieldTypes::ToStr(p.second) << ";\n"
      << "  }\n"
    ;
  }
  */
  os
    << "}" << '\n'
  ;
  return os;
}

 

 

 

 

 

./CppOpenFoam/openfoamthermophysicalpropertiesfile.h

 

#ifndef RIBI_OPENFOAMTHERMOPHYSICALPROPERTIESFILE_H
#define RIBI_OPENFOAMTHERMOPHYSICALPROPERTIESFILE_H

#include <iosfwd>
#include <vector>
#include "openfoamfwd.h"
#include "openfoamheader.h"

namespace ribi {
namespace foam {

///Reads and writes an OpenFOAM thermophysicalProperties file
struct ThermophysicalPropertiesFile
{
  explicit ThermophysicalPropertiesFile(
    const Header header = GetDefaultHeader()
  );

  static Header GetDefaultHeader() noexcept;
  const Header& GetHeader() const noexcept { return m_header; }

  void SetMixture(const std::string& mixture) noexcept { m_mixture = mixture; }
  void SetThermoType(const std::string& thermo_type) noexcept { m_thermo_type = thermo_type; }

  private:

  ///The OpenFOAM header
  Header m_header;

  std::string m_mixture;
  std::string m_thermo_type;

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif

  friend std::ostream& operator<<(std::ostream& os, const ThermophysicalPropertiesFile& f) noexcept;
};

std::ostream& operator<<(std::ostream& os, const ThermophysicalPropertiesFile& f) noexcept;

} //~namespace foam
} //~namespace ribi




#endif // RIBI_OPENFOAMTHERMOPHYSICALPROPERTIESFILE_H

 

 

 

 

 

./CppOpenFoam/openfoamthermophysicalpropertiesfile.cpp

 

#include "openfoamthermophysicalpropertiesfile.h"

#include <cassert>
#include <fstream>
#include <iostream>
#include <stdexcept>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"

#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/lexical_cast.hpp>

#include <QFile>

#include "fileio.h"

#include "openfoamheader.h"
#include "testtimer.h"
#include "trace.h"
#pragma GCC diagnostic pop


ribi::foam::ThermophysicalPropertiesFile::ThermophysicalPropertiesFile(
  const Header header
)
  : m_header{header},
    m_mixture{},
    m_thermo_type{}
{
  #ifndef NDEBUG
  Test();
  #endif
}

ribi::foam::Header ribi::foam::ThermophysicalPropertiesFile::GetDefaultHeader() noexcept
{
  return Header("dictionary","constant","","thermophysicalProperties");
}

#ifndef NDEBUG
void ribi::foam::ThermophysicalPropertiesFile::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
}
#endif

std::ostream& ribi::foam::operator<<(std::ostream& os, const ThermophysicalPropertiesFile& f) noexcept
{
  os
    << f.GetHeader() << '\n'
    << "" << '\n'
    << "" << '\n'
    << "thermoType " << f.m_thermo_type << ";\n"
    << "mixture " << f.m_mixture << ";\n"
  ;
  return os;
}

 

 

 

 

 

./CppOpenFoam/openfoamturbulencepropertiesfile.h

 

#ifndef RIBI_OPENFOAMTURBULENCEPROPERTIESFILE_H
#define RIBI_OPENFOAMTURBULENCEPROPERTIESFILE_H

#include <iosfwd>
#include <vector>
#include "openfoamfwd.h"
#include "openfoamheader.h"

namespace ribi {
namespace foam {

///Reads and writes an OpenFOAM turbulenceProperties file
struct TurbulencePropertiesFile
{
  explicit TurbulencePropertiesFile(
    const Header header = GetDefaultHeader()
  );

  static Header GetDefaultHeader() noexcept;
  const Header& GetHeader() const noexcept { return m_header; }

  void SetSimulationType(const std::string& simulation_type) noexcept { m_simulation_type = simulation_type; }

  private:

  ///The OpenFOAM header
  Header m_header;

  std::string m_simulation_type;

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif

  friend std::ostream& operator<<(std::ostream& os, const TurbulencePropertiesFile& f) noexcept;
};

std::ostream& operator<<(std::ostream& os, const TurbulencePropertiesFile& f) noexcept;

} //~namespace foam
} //~namespace ribi

#endif // RIBI_OPENFOAMTURBULENCEPROPERTIESFILE_H

 

 

 

 

 

./CppOpenFoam/openfoamturbulencepropertiesfile.cpp

 

#include "openfoamturbulencepropertiesfile.h"

#include <cassert>
#include <fstream>
#include <iostream>
#include <stdexcept>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"

#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/lexical_cast.hpp>

#include <QFile>

#include "fileio.h"

#include "openfoamheader.h"
#include "testtimer.h"
#include "trace.h"
#pragma GCC diagnostic pop


ribi::foam::TurbulencePropertiesFile::TurbulencePropertiesFile(
  const Header header
)
  : m_header{header},
    m_simulation_type{}
{
  #ifndef NDEBUG
  Test();
  #endif
}

ribi::foam::Header ribi::foam::TurbulencePropertiesFile::GetDefaultHeader() noexcept
{
  return Header("dictionary","constant","","turbulenceProperties");
}

#ifndef NDEBUG
void ribi::foam::TurbulencePropertiesFile::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
}
#endif

std::ostream& ribi::foam::operator<<(std::ostream& os, const TurbulencePropertiesFile& f) noexcept
{
  os
    << f.GetHeader() << '\n'
    << "" << '\n'
    << "simulationType " << f.m_simulation_type << ";\n"
  ;
  return os;
}

 

 

 

 

 

./CppOpenFoam/openfoamvelocityfieldfile.h

 

#ifndef RIBI_OPENFOAMVELOCITYFIELDFILE_H
#define RIBI_OPENFOAMVELOCITYFIELDFILE_H

#include <array>
#include <iosfwd>
#include <vector>
#include "openfoamfwd.h"
#include "openfoamheader.h"
#include "openfoampatchfieldtype.h"

namespace ribi {
namespace foam {

///Reads and writes an OpenFOAM turbulenceProperties file
struct VelocityFieldFile
{
  explicit VelocityFieldFile(
    const Header header = GetDefaultHeader()
  ) noexcept;

  static Header GetDefaultHeader() noexcept;
  const Header& GetHeader() const noexcept { return m_header; }

  void SetBoundaryField(const std::string& boundary_field) noexcept { m_boundary_field = boundary_field; }
  //Cannot use this variant, as the boundary has very variable form
  //void SetBoundaryField(const std::vector<std::pair<std::string,PatchFieldType>>& boundary_field) noexcept { m_boundary_field = boundary_field; }

  void SetDimensions(const std::array<int,7>& dimensions) noexcept { m_dimensions = dimensions; }
  void SetInternalField(const std::string& internal_field) noexcept { m_internal_field = internal_field; }

  private:

  std::string m_boundary_field;
  //Cannot use this variant, as the boundary has very variable form
  //std::vector<std::pair<std::string,PatchFieldType>> m_boundary_field;

  std::array<int,7> m_dimensions;

  ///The OpenFOAM header
  Header m_header;

  std::string m_internal_field;

  #ifndef NDEBUG
  static void Test() noexcept;
  #endif

  friend std::ostream& operator<<(std::ostream& os, const VelocityFieldFile& f) noexcept;
};

std::ostream& operator<<(std::ostream& os, const VelocityFieldFile& f) noexcept;

} //~namespace foam
} //~namespace ribi

#endif // RIBI_OPENFOAMVELOCITYFIELDFILE_H

 

 

 

 

 

./CppOpenFoam/openfoamvelocityfieldfile.cpp

 

#include "openfoamvelocityfieldfile.h"

#include <cassert>
#include <fstream>
#include <iostream>
#include <stdexcept>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"

#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/lexical_cast.hpp>

#include <QFile>

#include "fileio.h"

#include "openfoamheader.h"
#include "openfoampatchfieldtypes.h"
#include "testtimer.h"
#include "trace.h"
#pragma GCC diagnostic pop


ribi::foam::VelocityFieldFile::VelocityFieldFile(
  const Header header
) noexcept
  : m_boundary_field{},
    m_dimensions{{}},
    m_header{header},
    m_internal_field{}
{
  #ifndef NDEBUG
  Test();
  #endif
}

ribi::foam::Header ribi::foam::VelocityFieldFile::GetDefaultHeader() noexcept
{
  return Header("volVectorField","0","","U");
}

#ifndef NDEBUG
void ribi::foam::VelocityFieldFile::Test() noexcept
{
  {
    static bool is_tested{false};
    if (is_tested) return;
    is_tested = true;
  }
  const TestTimer test_timer(__func__,__FILE__,1.0);
}
#endif

std::ostream& ribi::foam::operator<<(std::ostream& os, const VelocityFieldFile& f) noexcept
{
  os
    << f.GetHeader() << '\n'
    << "" << '\n'
    << "dimensions ["
      << f.m_dimensions[0] << " "
      << f.m_dimensions[1] << " "
      << f.m_dimensions[2] << " "
      << f.m_dimensions[3] << " "
      << f.m_dimensions[4] << " "
      << f.m_dimensions[5] << " "
      << f.m_dimensions[6]
      << "];" << '\n'
    << "\n"
    << "internalField " << f.m_internal_field << ";\n"
    << "\n"
    << "boundaryField\n"
    << "{\n" << '\n'
  ;
  os << f.m_boundary_field << '\n';
  /*
  for (const auto& p: f.m_boundary_field)
  {
    os
      << "  " << p.first << '\n'
      << "  {\n"
      << "    type " << PatchFieldTypes::ToStr(p.second) << ";\n"
      << "  }\n"
    ;
  }
  */
  os
    << "}\n";
    return os;
  ;
  return os;
}

 

 

 

 

 

Go back to Richel Bilderbeek's C++ page.

Go back to Richel Bilderbeek's homepage.

 

Valid XHTML 1.0 Strict

This page has been created by the tool CodeToHtml