BackupRestore.hpp 4.94 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#pragma once

#include <cstdint>
#include <fstream>
#include <memory>
#include <vector>

#include <dune/grid/common/backuprestore.hh>
#include <dune/grid/common/gridfactory.hh>

namespace AMDiS
{
  // Fallback Implementation for Grids not supporting direct BackupRestore
  template <class Grid>
  class BackupRestoreByGridFactory
  {
    template <class GridView>
    class Writer
    {
      enum { dim = GridView::dimension };
      enum { dow = GridView::dimensionworld };

      using ct = typename GridView::ctype;

    public:
      Writer(GridView const& gv)
        : gridView_(gv)
      {
        std::int64_t num = 0;
        indexMap_.resize(gridView_.size(dim));
        auto const& indexSet = gridView_.indexSet();
        for (auto const& vertex : vertices(gridView_))
          indexMap_[indexSet.index(vertex)] = std::int64_t(num++);
      }

      void writeVertices(std::ostream& out) const
      {
        for (auto const& vertex : vertices(gridView_)) {
          auto v = vertex.geometry().center();
          out.write((char*)&v, dow*sizeof(ct));
        }
      }

      void writeElements(std::ostream& out) const
      {
        auto const& indexSet = gridView_.indexSet();

        std::vector<std::int64_t> connectivity;
        connectivity.reserve(8);
        for (auto const& e : elements(gridView_)) {
          unsigned int id = e.type().id();
          out.write((char*)&id, sizeof(unsigned int));

          connectivity.clear();
          for (unsigned int j = 0; j < e.subEntities(dim); ++j)
            connectivity.emplace_back(indexMap_[indexSet.subIndex(e,j,dim)]);

          out.write((char*)connectivity.data(), connectivity.size()*sizeof(std::int64_t));
        }
      }

    private:
      GridView gridView_;
      std::vector<std::int64_t> indexMap_;
    };

    class Reader
    {
      enum { dim = Grid::dimension };
      enum { dow = Grid::dimensionworld };

      using ct = typename Grid::ctype;
      using Factory = Dune::GridFactory<Grid>;
      using GlobalCoordinates = Dune::FieldVector<ct,dow>;

    public:
      Reader(Factory& factory, std::istream& in)
        : factory_(factory)
      {
        in.read((char*)&numElements_, sizeof(std::int64_t));
        in.read((char*)&numVertices_, sizeof(std::int64_t));
      }

      void readVertices(std::istream& in) const
      {
        GlobalCoordinates p;
        for (std::int64_t i = 0; i < numVertices_; ++i) {
          in.read((char*)&p[0], dow*sizeof(ct));
          factory_.insertVertex(p);
        }
      }

      void readElements(std::istream& in) const
      {
        std::vector<std::int64_t> connectivity(8);
        std::vector<unsigned int> vertices;
        vertices.reserve(8);

        for (std::int64_t i = 0; i < numElements_; ++i) {
          unsigned int id = 0;
          in.read((char*)&id, sizeof(unsigned int));

          Dune::GeometryType type(id,dim);
          auto refElem = Dune::referenceElement<ct,dim>(type);

          in.read((char*)connectivity.data(), refElem.size(dim)*sizeof(std::int64_t));
          vertices.clear();
          std::copy_n(connectivity.begin(),refElem.size(dim),std::back_inserter(vertices));

          factory_.insertElement(type, vertices);
        }
      }

    private:
      Factory& factory_;
      std::int64_t numElements_ = 0;
      std::int64_t numVertices_ = 0;
    };

  public:
    /// \brief Write a hierarchic grid to disk
    template <class GridView>
    static void backup(GridView const& gv, std::string const& filename)
    {
      std::ofstream out(filename, std::ios::binary);
      backup(gv,out);
    }

    /// \brief write a hierarchic grid into a stream
    template <class GridView>
    static void backup(GridView const& gv, std::ostream& out)
    {
      std::int32_t dim = GridView::dimension;
      std::int32_t dow = GridView::dimensionworld;
      std::int64_t num_elements = gv.size(0);
      std::int64_t num_vertices = gv.size(dim);

      out.write((char*)&dim, sizeof(std::int32_t));
      out.write((char*)&dow, sizeof(std::int32_t));
      out.write((char*)&num_elements, sizeof(std::int64_t));
      out.write((char*)&num_vertices, sizeof(std::int64_t));

143
      Writer<GridView> writer(gv);
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
      writer.writeVertices(out);
      writer.writeElements(out);
    }

    /// \brief read a hierarchic grid from disk
    static Grid* restore(std::string const& filename)
    {
      std::ifstream in(filename, std::ios::binary);
      return restore(in);
    }

    /// \brief read a hierarchic grid from a stream
    static Grid* restore(std::istream& in)
    {
      Dune::GridFactory<Grid> factory;

      std::int32_t dim = 0, dow = 0;

      in.read((char*)&dim, sizeof(std::int32_t));
      in.read((char*)&dow, sizeof(std::int32_t));

      assert(Grid::dimension == dim);
      assert(Grid::dimensionworld == dow);

      Reader reader(factory, in);
      reader.readVertices(in);
      reader.readElements(in);

      std::unique_ptr<Grid> ptr(factory.createGrid());
      return ptr.release();
    }
  };

} // end namespace AMDiS