SolutionDataStorage.h 10.4 KB
Newer Older
1
2
3
4
#ifndef AMDIS_SOLUTION_DATA_STORAGE_H
#define AMDIS_SOLUTION_DATA_STORAGE_H

#include <iostream>
Thomas Witkowski's avatar
Thomas Witkowski committed
5
#include <fstream>
6
#include <vector>
Thomas Witkowski's avatar
Thomas Witkowski committed
7
#include <map>
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include "DOFVector.h"
#include "SystemVector.h"
#include "Parameters.h"

namespace AMDiS {

  template<typename T>
  struct SolutionHelper
  {
    typedef FiniteElemSpace* type;
  };

  template <>
  struct SolutionHelper<SystemVector>
  {
    typedef std::vector<FiniteElemSpace*> type;
  };
  
Thomas Witkowski's avatar
Thomas Witkowski committed
26
27


Thomas Witkowski's avatar
Thomas Witkowski committed
28
29
30
31
32
33
34
35
36
37
38
  /** \brief
   * Class to store solution data for one timestep.
   *
   * Within this class, the solution data for one timestep is stored. The 
   * type of the solution data is the typename of the class, i.e., either
   * DOFVector or SystemVector. The class is resonsible for serialization
   * and deserialization of the solution.
   *
   * The class is used only from class \ref SolutionDataStorage, and must
   * not be used by the user in other context.
   */
39
  template<typename T>
Thomas Witkowski's avatar
Thomas Witkowski committed
40
  class SolutionData 
41
42
  {
  public:
Thomas Witkowski's avatar
Thomas Witkowski committed
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

    /** \brief 
     * The constructor requires already the data. So no empty data class
     * can be created.
     */
    SolutionData(T* sol, 
		 typename SolutionHelper<T>::type fes,
		 double ts,
		 int i) 
      : solution(sol),
	feSpace(fes),
	timestamp(ts),
	id(i),
	serialized(false),
	filename("")
    {}

60
    /** \brief
Thomas Witkowski's avatar
Thomas Witkowski committed
61
62
     * The destructor either deletes the data files or deletes the pointers
     * to the data.
63
     */
Thomas Witkowski's avatar
Thomas Witkowski committed
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
    ~SolutionData() 
    {
      if (!serialized) {
	DELETE solution;
	deleteFeSpace(feSpace);
      }
    }

    /// Serialize the data to a file.
    void serialize(std::string fn) 
    {
      std::ofstream out(fn.c_str());
      serializeFeSpace(out, feSpace);
      solution->serialize(out);
      out.close();

      serialized = true;
      filename = fn;   

      DELETE solution;
      deleteFeSpace(feSpace);
    }

    /// Deserialize the data from file.
    void deserialize()
    {
      std::string feName = "";
      int dim = 0;
      int degree = 0;

      std::ifstream in(filename.c_str());
      deserializeFeSpace(in, feSpace);
      solution = new T("", feSpace, 0);
      solution->deserialize(in);
      in.close();

      serialized = false;
      filename = "";
    }
103

104
    /** \brief
Thomas Witkowski's avatar
Thomas Witkowski committed
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
143
144
     * Returns the data. In the case the data was serialized to the disk,
     * it will be first deserialized from the corresponding file.
     */
    void getData(T** ptrSolution, double *ptrTimestamp)
    {
      if (serialized) {
 	deserialize();
      } 

      *ptrSolution = solution;
      *ptrTimestamp = timestamp;      
    }

    /// Returns \ref serialized.
    bool isSerialized() {
      return serialized;
    }

  protected:
    /// Serialize a fe space to a file.
    void serializeFeSpace(std::ofstream &out, FiniteElemSpace* fe) 
    {     
      // Write the mesh to file.
      out << fe->getMesh()->getName() << "\n";

      int dim = fe->getMesh()->getDim();
      out.write(reinterpret_cast<const char*>(&dim), sizeof(int));

      fe->getMesh()->serialize(out);

      // Then, write all other fe space data to file.
      dim = fe->getBasisFcts()->getDim();
      int degree = fe->getBasisFcts()->getDegree();
      out << ((fe->getName() != "") ? fe->getName() : "noname") << "\n";
      out.write(reinterpret_cast<const char*>(&dim), sizeof(int));
      out.write(reinterpret_cast<const char*>(&degree), sizeof(int));
    }

    /** \brief 
     * Serialize a vector of fe spaces to a file. 
145
     *
Thomas Witkowski's avatar
Thomas Witkowski committed
146
147
148
     * Takes special care about multiple fe space pointers, pointing to the
     * same fe space. In this case, only the first fe space is serialized
     * completely.
149
     */
Thomas Witkowski's avatar
Thomas Witkowski committed
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
    void serializeFeSpace(std::ofstream &out, std::vector<FiniteElemSpace*>& fe)
    {
      int size = fe.size();     
      out.write(reinterpret_cast<const char*>(&size), sizeof(int));

      for (int i = 0; i < size; i++) {
	// Check, if the pointer points to an fe space serialized before.
	int found = -1;
	for (int j = 0; j < i; j++) {
	  if (fe[j] == fe[i]) {
	    found = j;
	    break;
	  }
	}

        out.write(reinterpret_cast<const char*>(&found), sizeof(int));
	// Only in case this fe space was not serialized before, write it to the file.
	if (found == -1) {
	  serializeFeSpace(out, fe[i]);
	}
      }
    }
172

Thomas Witkowski's avatar
Thomas Witkowski committed
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
    void deserializeFeSpace(std::ifstream &in, FiniteElemSpace** fe) 
    {
      std::string name = "";
      int dim = 0;
      int degree = 0;

      in >> name;
      in.get();
      in.read(reinterpret_cast<char*>(&dim), sizeof(int));
      Mesh *mesh = new Mesh(name, dim);
      mesh->deserialize(in);

      in >> name;
      in.get();
      in.read(reinterpret_cast<char*>(&dim), sizeof(int));
      in.read(reinterpret_cast<char*>(&degree), sizeof(int));

      *fe = FiniteElemSpace::provideFESpace(NULL,
					    Lagrange::getLagrange(dim, degree),
					    mesh,
					    name);
      (*fe)->setAdmin(const_cast<DOFAdmin*>(&(mesh->getDOFAdmin(0))));
    }

    void deserializeFeSpace(std::ifstream &in, std::vector<FiniteElemSpace*>& fe)
    {
      int size;
      in.read(reinterpret_cast<char*>(&size), sizeof(int));

      fe.resize(size);
      for (int i = 0; i < size; i++) {
	int found;
	in.read(reinterpret_cast<char*>(&found), sizeof(int));
	if (found == -1) {
	  deserializeFeSpace(in, &(fe[i]));
	} else {
	  fe[i] = fe[found];
	}
      }
    }

    /// Remove one fe space from memory.
    void deleteFeSpace(FiniteElemSpace* fe)
    {
      if (fe) {
	DELETE fe->getMesh();
	DELETE fe;
	fe = NULL;
      }
    }

    /// Remove a vector of fe spaces from memory. 
    void deleteFeSpace(std::vector<FiniteElemSpace*>& fe)
    {
      // Stores all pointers to fe spaces, that were deleted. This should
      // avoid double deletion of pointer.
      std::map<FiniteElemSpace*, bool> deletedFeSpaces;

      for (int i = 0; i < static_cast<int>(fe.size()); i++) {
	if (deletedFeSpaces.find(fe[i]) == deletedFeSpaces.end()) {
	  deleteFeSpace(fe[i]);
	  deletedFeSpaces[fe[i]] = true;
	}
      }

      fe.clear();
    }

    public:
242
    /** \brief
Thomas Witkowski's avatar
Thomas Witkowski committed
243
244
     * Here, all the solutions (i.e. either DOFVectors or SystemVectors)
     * are stored.
245
     */
Thomas Witkowski's avatar
Thomas Witkowski committed
246
    T* solution;
247

248
    /** \brief
Thomas Witkowski's avatar
Thomas Witkowski committed
249
250
251
     * Stores to every solution its FE Space. If \ref fixedFESpace is set
     * to true, only one entry exists. This is than the FE Space for all
     * solutions.
252
     */
Thomas Witkowski's avatar
Thomas Witkowski committed
253
    typename SolutionHelper<T>::type feSpace;
254
255

    /** \brief
Thomas Witkowski's avatar
Thomas Witkowski committed
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
     * Stores to every solutions the timestamp at which the solution was
     * created in the adaption loop.
     */
    double timestamp;

    /** \brief
     * If true, the solution data is serialied to disk and the pointers
     * are not valid.
     */
    bool serialized;

    /// If solution data is serialied, here the corresponding filename is stored.
    std::string filename;

    int id;
  };



  /** \brief
   * Storage for solution datas with optimization process.
   *
   * This class may be used to store solutions within an optimization process. 
   * Within the forward step, solutions are stored within this data storage, and
   * are then used within the backward step. The storage supports serialization
   * and deserialization of solutions (and the corresponding fe spaces) to save
   * memory.
   *
   * The template typename must be the type of the solution data to be stored, i.e,
   * either DOFVector<double> or SystemVector.
   */
  template<typename T>
  class SolutionDataStorage 
  {
  public:
    /** \brief
     * Constructor. The parameter is a string that will be used to search for 
     * parameters of the storage within the init file.
294
     */
Thomas Witkowski's avatar
Thomas Witkowski committed
295
    SolutionDataStorage(std::string name);
296

297
    /** \brief
Thomas Witkowski's avatar
Thomas Witkowski committed
298
     * Destructor. Deletes all stored solutions and deletes all serialized files.
299
     */
Thomas Witkowski's avatar
Thomas Witkowski committed
300
301
302
303
304
305
306
307
308
    ~SolutionDataStorage();

    /// Add a solution and its timestamp to the storage.
    void push(T *solution, double timestamp);

    /// Get solution data from storage. Returns true, if solution data is valid.
    bool pop(T **solution, double *timestep);

    /// Delete all pointers and empties all internal vectors.
309
    void clear();
310
	     
311
    /** \brief
Thomas Witkowski's avatar
Thomas Witkowski committed
312
     * Return for a given solution number the corresponding fe Space. If the
313
314
315
316
     * the fe Space is fixed, the fe Space for all solutions is stored at
     * position 0.
     */
    typename SolutionHelper<T>::type getFeSpace(int i = 0) {
Thomas Witkowski's avatar
Thomas Witkowski committed
317
      return solutions[i]->feSpace;
318
    }
319

Thomas Witkowski's avatar
Thomas Witkowski committed
320
    /// Returns \ref poped.
321
322
323
324
    bool isPoped() {
      return poped;
    }

Thomas Witkowski's avatar
Thomas Witkowski committed
325
    /// Add a new container to the storage.
Thomas Witkowski's avatar
Thomas Witkowski committed
326
327
    void addContainer(std::string name);

Thomas Witkowski's avatar
Thomas Witkowski committed
328
    /// Add value to a container.
Thomas Witkowski's avatar
Thomas Witkowski committed
329
330
    void push(std::string name, WorldVector<double> value);

Thomas Witkowski's avatar
Thomas Witkowski committed
331
    /// Get value from a container.
Thomas Witkowski's avatar
Thomas Witkowski committed
332
333
    void pop(std::string name, WorldVector<double> &value);

Thomas Witkowski's avatar
Thomas Witkowski committed
334
    /// Reset, , a container/
Thomas Witkowski's avatar
Thomas Witkowski committed
335
336
    void reset(std::string name);

Thomas Witkowski's avatar
Thomas Witkowski committed
337
    /// Clear, i.e. delete all values, a container.
Thomas Witkowski's avatar
Thomas Witkowski committed
338
339
    void clear(std::string name);

340
  protected:
341
342
343
    /** \brief
     *
     */
Thomas Witkowski's avatar
Thomas Witkowski committed
344
345
346
347
    int addMemoryUsage(FiniteElemSpace* feSpace) {
      memoryUsage += feSpace->getMesh()->calcMemoryUsage();
    }

348
349
350
    /** \brief
     *
     */
Thomas Witkowski's avatar
Thomas Witkowski committed
351
352
353
354
355
356
357
358
359
360
361
362
    int addMemoryUsage(std::vector<FiniteElemSpace*> feSpaces) {
      // Is used to determine equal meshes for different components.
      std::vector<Mesh*> meshes;

      for (int i = 0; i < static_cast<int>(feSpaces.size()); i++) {
	if (find(meshes.begin(), meshes.end(), feSpaces[i]->getMesh()) != meshes.end()) {
	  memoryUsage += feSpaces[i]->getMesh()->calcMemoryUsage();
	  meshes.push_back(feSpaces[i]->getMesh());
	}
      }
    }

363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
    /** \brief
     * Number of MBytes of memory that can be used for solution storage.
     */
    int maxMemoryUsage;

    /** \brief
     * If true, it is allowed to write solutions also to disk.
     */
    bool useDisk;

    /** \brief
     * Directory, where solutions can be written temporarly.
     */
    std::string writeDirectory;

    /** \brief
     * Position of the latest valid solution.
     */
    int lastPos;

    /** \brief
     * If true, the last operation on the data storage was pop.
     */
    bool poped;
387
388
389
390
391

    /** \brief
     * Counts the memory usage of all solutions stored in memory.
     */
    int memoryUsage;
Thomas Witkowski's avatar
Thomas Witkowski committed
392

Thomas Witkowski's avatar
Thomas Witkowski committed
393
394
395
396
397
398
    /** \brief
     * Storage for the solutions, i.e., the DOFVector, the FESpace and the 
     * corresponding timestep.
     */
    std::vector<SolutionData<T>* > solutions;

399
400
401
    /** \brief
     *
     */
Thomas Witkowski's avatar
Thomas Witkowski committed
402
403
    std::map<std::string, std::vector<WorldVector<double > > > containers;

404
405
406
    /** \brief
     *
     */
Thomas Witkowski's avatar
Thomas Witkowski committed
407
    std::map<std::string, int> containersPos;
Thomas Witkowski's avatar
Thomas Witkowski committed
408
409

    int idcounter;
410
411
412
413
414
415
416
  };

}

#include "SolutionDataStorage.hh"

#endif // AMDIS_SOLUTION_DATA_STORAGE_H