Line data Source code
1 : /*
2 : * Copyright (c) 2009-2015: G-CSC, Goethe University Frankfurt
3 : * Author: Sebastian Reiter
4 : *
5 : * This file is part of UG4.
6 : *
7 : * UG4 is free software: you can redistribute it and/or modify it under the
8 : * terms of the GNU Lesser General Public License version 3 (as published by the
9 : * Free Software Foundation) with the following additional attribution
10 : * requirements (according to LGPL/GPL v3 §7):
11 : *
12 : * (1) The following notice must be displayed in the Appropriate Legal Notices
13 : * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14 : *
15 : * (2) The following notice must be displayed at a prominent place in the
16 : * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17 : *
18 : * (3) The following bibliography is recommended for citation and must be
19 : * preserved in all covered files:
20 : * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21 : * parallel geometric multigrid solver on hierarchically distributed grids.
22 : * Computing and visualization in science 16, 4 (2013), 151-164"
23 : * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24 : * flexible software system for simulating pde based models on high performance
25 : * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26 : *
27 : * This program is distributed in the hope that it will be useful,
28 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 : * GNU Lesser General Public License for more details.
31 : */
32 :
33 : #include <fstream>
34 : #include "lib_grid/lg_base.h"
35 : #include "lib_grid/algorithms/serialization.h"
36 : #include "file_io_lgb.h"
37 :
38 : #include <sstream>
39 : #include <boost/archive/text_oarchive.hpp>
40 : #include <boost/archive/text_iarchive.hpp>
41 : #include "common/boost_serialization_routines.h"
42 : #include "common/util/archivar.h"
43 : #include "common/util/factory.h"
44 : #include "lib_grid/refinement/projectors/projection_handler.h"
45 : #include "lib_grid/refinement/projectors/projectors.h"
46 :
47 : using namespace std;
48 :
49 : namespace ug
50 : {
51 :
52 : enum LGBConstants
53 : {
54 : LGBC_NONE = 0,
55 : LGBC_POS2D = 1,
56 : LGBC_POS3D = 1 << 1,
57 : LGBC_SUBSET_HANDLER = 1 << 2,
58 : LGBC_SELECTOR = 1 << 3,
59 : LGBC_PROJECTION_HANDLER = 1 << 4
60 : };
61 :
62 0 : void SerializeProjector(BinaryBuffer& out, RefinementProjector& proj)
63 : {
64 0 : static Factory<RefinementProjector, ProjectorTypes> projFac;
65 0 : static Archivar<boost::archive::text_oarchive, RefinementProjector, ProjectorTypes> archivar;
66 :
67 0 : const string& projName = projFac.class_name(proj);
68 :
69 0 : Serialize(out, projName);
70 :
71 0 : stringstream ss;
72 : boost::archive::text_oarchive ar(ss, boost::archive::no_header);
73 : archivar.archive(ar, proj);
74 :
75 0 : Serialize(out, ss.str());
76 0 : }
77 :
78 :
79 0 : void SerializeProjectionHandler(BinaryBuffer& out, ProjectionHandler& ph)
80 : {
81 0 : const int magicNumber = 978523;
82 0 : out.write((char*)&magicNumber, sizeof(int));
83 :
84 0 : if(ph.default_projector().valid()){
85 0 : byte b = 1;
86 0 : out.write((char*)&b, sizeof(b));
87 0 : SerializeProjector(out, *ph.default_projector());
88 : }
89 : else{
90 0 : byte b = 0;
91 0 : out.write((char*)&b, sizeof(b));
92 : }
93 :
94 0 : int numProjectors = (int)ph.num_projectors();
95 0 : out.write((char*)&numProjectors, sizeof(int));
96 :
97 0 : for(int i = -1; i < numProjectors; ++i){
98 0 : if(!ph.projector(i).valid()){
99 0 : const int invInd = -2;
100 0 : out.write((char*)& invInd, sizeof(int));
101 : continue;
102 0 : }
103 :
104 0 : RefinementProjector& proj= *ph.projector(i);
105 :
106 0 : out.write((char*)& i, sizeof(int));
107 0 : SerializeProjector(out, proj);
108 : }
109 0 : out.write((char*)&magicNumber, sizeof(int));
110 0 : }
111 :
112 :
113 0 : SPRefinementProjector DeserializeProjector(BinaryBuffer& in)
114 : {
115 : static Archivar<boost::archive::text_iarchive,
116 : RefinementProjector,
117 : ProjectorTypes>
118 0 : archivar;
119 :
120 0 : static Factory<RefinementProjector, ProjectorTypes> projFac;
121 :
122 : std::string name;
123 0 : Deserialize(in, name);
124 :
125 0 : if(name.empty())
126 : return SPRefinementProjector();
127 :
128 : SPRefinementProjector proj = projFac.create(name);
129 :
130 : std::string data;
131 0 : Deserialize(in, data);
132 0 : std::stringstream ss(data, std::ios_base::in);
133 : boost::archive::text_iarchive ar(ss, boost::archive::no_header);
134 : archivar.archive(ar, *proj);
135 : return proj;
136 0 : }
137 :
138 :
139 0 : void DeserializeProjectionHandler(BinaryBuffer& in, ProjectionHandler& ph)
140 : {
141 : const int magicNumber = 978523;
142 : int tmpMagicNumber;
143 0 : in.read((char*)&tmpMagicNumber, sizeof(int));
144 0 : UG_COND_THROW(tmpMagicNumber != magicNumber,
145 : "Magic number mismatch in DeserializeProjectionHandler (1)!");
146 :
147 0 : ph.clear();
148 :
149 : byte b;
150 0 : in.read((char*)&b, sizeof(b));
151 0 : if(b){
152 0 : ph.set_default_projector(DeserializeProjector(in));
153 : }
154 : else
155 0 : ph.set_default_projector(SPRefinementProjector());
156 :
157 : int numProjectors;
158 0 : in.read((char*)&numProjectors, sizeof(int));
159 :
160 0 : for(int i = -1; i < numProjectors; ++i){
161 : int index;
162 0 : in.read((char*)& index, sizeof(int));
163 0 : if(index == -2){
164 0 : continue;
165 : }
166 :
167 0 : ph.set_projector(index, DeserializeProjector(in));
168 : }
169 :
170 0 : in.read((char*)&tmpMagicNumber, sizeof(int));
171 0 : UG_COND_THROW(tmpMagicNumber != magicNumber,
172 : "Magic number mismatch in DeserializeProjectionHandler (2)!");
173 0 : }
174 :
175 :
176 :
177 :
178 0 : bool SaveGridToLGB(Grid& grid, const char* filename,
179 : ISubsetHandler** ppSH, int numSHs,
180 : ProjectionHandler* pPH,
181 : APosition aPos)
182 : {
183 0 : return SaveGridToLGB (grid, filename,ppSH, numSHs, NULL, 0, pPH, aPos);
184 : }
185 :
186 :
187 0 : bool SaveGridToLGB(Grid& grid, const char* filename,
188 : ISubsetHandler** ppSH, int numSHs,
189 : ISelector** ppSel, int numSels,
190 : ProjectionHandler* pPH,
191 : APosition aPos)
192 : {
193 : // make sure that aPos is attached to the grid
194 0 : if(!grid.has_vertex_attachment(aPos))
195 : return false;
196 :
197 0 : BinaryBuffer tbuf;
198 :
199 : // write the header
200 0 : byte endianess = 1;
201 0 : byte intSize = (byte)sizeof(int);
202 0 : byte numberSize = (byte)sizeof(number);
203 0 : int versionNumber = 4;
204 :
205 0 : tbuf.write((char*)&endianess, sizeof(byte));
206 0 : tbuf.write((char*)&intSize, sizeof(byte));
207 0 : tbuf.write((char*)&numberSize, sizeof(byte));
208 0 : tbuf.write((char*)&versionNumber, sizeof(int));
209 :
210 : // the options
211 0 : uint opts = LGBC_POS3D;
212 0 : if(numSHs > 0)
213 0 : opts |= LGBC_SUBSET_HANDLER;
214 0 : if(numSels > 0)
215 0 : opts |= LGBC_SELECTOR;
216 0 : if(pPH)
217 0 : opts |= LGBC_PROJECTION_HANDLER;
218 :
219 : // write the options
220 0 : tbuf.write((char*)&opts, sizeof(uint));
221 :
222 : // serialize the grid
223 0 : SerializeGridElements(grid, tbuf);
224 :
225 : // serialize the position-attachment
226 0 : SerializeAttachment<Vertex>(grid, aPos, tbuf);
227 :
228 : // Serialize the subset-handler
229 0 : if(numSHs > 0){
230 : // write the number of subset handlers which shall be serialized
231 0 : tbuf.write((char*)&numSHs, sizeof(int));
232 0 : for(int i = 0; i< numSHs; ++i)
233 0 : SerializeSubsetHandler(grid, *ppSH[i], tbuf);
234 : }
235 :
236 : // Serialize the selectors
237 0 : if(numSels > 0){
238 0 : tbuf.write((char*)&numSels, sizeof(int));
239 0 : for(int i = 0; i< numSels; ++i)
240 0 : SerializeSelector(grid, *ppSel[i], tbuf);
241 : }
242 :
243 : // Serializie the projection handler
244 0 : if(pPH){
245 : ProjectionHandler& ph = *pPH;
246 :
247 : // find corresponding subset handler
248 : {
249 0 : UG_COND_THROW(numSHs < 1, "If a ProjectionHandler is specified, the corresponding SubsetHandler also has to be specified!");
250 :
251 0 : int i = 0;
252 0 : for (; i < numSHs; ++i)
253 0 : if (ppSH[i] == ph.subset_handler())
254 : break;
255 :
256 0 : UG_COND_THROW(i == numSHs, "ERROR in 'SaveGridToLGB': "
257 : "No matching SubsetHandler could be found.\n"
258 : "Please make sure to add the associated SubsetHandler before adding a ProjectionHandler");
259 :
260 : // write index of corresponding subset handler
261 0 : tbuf.write((char*)&i, sizeof(int));
262 : }
263 :
264 0 : SerializeProjectionHandler(tbuf, ph);
265 : }
266 :
267 : // write a magic-number that allows us to check during read
268 : // whether everything went ok.
269 0 : int magicNumber = 3478384;
270 0 : tbuf.write((char*)&magicNumber, sizeof(int));
271 :
272 : // open the outstream
273 0 : ofstream out(filename, ios::binary);
274 0 : if(!out) return false;
275 :
276 0 : out.write(tbuf.buffer(), tbuf.write_pos());
277 :
278 : // done
279 0 : out.close();
280 : return true;
281 0 : }
282 :
283 :
284 :
285 0 : bool LoadGridFromLGB(Grid& grid, const char* filename,
286 : ISubsetHandler** ppSH, int numSHs,
287 : ProjectionHandler* pPH,
288 : APosition aPos)
289 : {
290 0 : return LoadGridFromLGB (grid, filename, ppSH, numSHs, NULL, 0, pPH, aPos);
291 : }
292 :
293 :
294 0 : bool LoadGridFromLGB(Grid& grid, const char* filename,
295 : ISubsetHandler** ppSH, int numSHs,
296 : ISelector** ppSel, int numSels,
297 : ProjectionHandler* pPH,
298 : APosition aPos)
299 : {
300 0 : grid.clear_geometry();
301 :
302 : // if aPos is not yet attached to the grid, we'll do it now.
303 0 : if(!grid.has_vertex_attachment(aPos))
304 0 : grid.attach_to_vertices(aPos);
305 :
306 : // open the outstream
307 0 : ifstream in(filename, ios::binary);
308 0 : if(!in){
309 0 : UG_LOG("ERROR in LoadGridFromLGB: couldn't open file: " << filename << endl);
310 : return false;
311 : }
312 :
313 : // read the whole file into a binary buffer
314 0 : BinaryBuffer tbuf;
315 0 : in.seekg(0, ios::end);
316 0 : streampos fileLen = in.tellg();
317 0 : in.seekg(0, ios::beg);
318 :
319 0 : tbuf.reserve(fileLen);
320 0 : in.read(tbuf.buffer(), fileLen);
321 0 : tbuf.set_write_pos(fileLen);
322 :
323 0 : in.close();
324 :
325 : // read the header
326 : byte endianess;
327 : byte intSize;
328 : byte numberSize;
329 : int versionNumber;
330 :
331 0 : tbuf.read((char*)&endianess, sizeof(byte));
332 0 : tbuf.read((char*)&intSize, sizeof(byte));
333 0 : tbuf.read((char*)&numberSize, sizeof(byte));
334 0 : tbuf.read((char*)&versionNumber, sizeof(int));
335 :
336 : // check whether the values are ok
337 0 : if(endianess != 1)
338 : {
339 : LOG("ERROR in LoadGridFromLGB: wrong endianess\n");
340 : return false;
341 : }
342 0 : if(intSize != sizeof(int))
343 : {
344 : LOG("ERROR in LoadGridFromLGB: bad integer-size\n");
345 : return false;
346 : }
347 0 : if(numberSize != sizeof(number))
348 : {
349 : LOG("ERROR in LoadGridFromLGB: bad number-size\n");
350 : return false;
351 : }
352 0 : if((versionNumber < 2) || (versionNumber > 4))
353 : {
354 0 : LOG("ERROR in LoadGridFromLGB: bad file-version: " << versionNumber << ". Expected 2 or 3.\n");
355 : return false;
356 : }
357 :
358 : // from version 3 on grids write a small header
359 0 : bool readGridHeader = (versionNumber >= 3);
360 :
361 : // read the options
362 : uint opts;
363 0 : tbuf.read((char*)&opts, sizeof(uint));
364 :
365 : // to avoid problems with autgenerated elements we'll deactivate
366 : // all options and reactivate them later on
367 0 : uint gridOptions = grid.get_options();
368 0 : grid.set_options(GRIDOPT_NONE);
369 :
370 : // deserialize the grid
371 0 : DeserializeGridElements(grid, tbuf, readGridHeader);
372 :
373 : // deserialize the position-attachment
374 0 : DeserializeAttachment<Vertex>(grid, aPos, tbuf);
375 :
376 : // Serialize the subset-handler
377 0 : if((opts & LGBC_SUBSET_HANDLER) == LGBC_SUBSET_HANDLER)
378 : {
379 : // read number of subset handlers
380 : int numSrcSHs;
381 0 : tbuf.read((char*)&numSrcSHs, sizeof(int));
382 :
383 : // starting from version 4, subset-infos contain a property-map
384 0 : bool readPropertyMap = (versionNumber >= 4);
385 :
386 : int i;
387 0 : for(i = 0; i < min(numSrcSHs, numSHs); ++i){
388 0 : DeserializeSubsetHandler(grid, *ppSH[i], tbuf, readPropertyMap);
389 : }
390 :
391 : // read the rest
392 0 : for(; i < numSrcSHs; ++i)
393 : {
394 0 : SubsetHandler sh(grid);
395 0 : DeserializeSubsetHandler(grid, sh, tbuf, readPropertyMap);
396 0 : }
397 : }
398 :
399 0 : if((opts & LGBC_SELECTOR) == LGBC_SELECTOR)
400 : {
401 : // read number of subset handlers
402 : int numSrcSels;
403 0 : tbuf.read((char*)&numSrcSels, sizeof(int));
404 :
405 : int i;
406 0 : for(i = 0; i < min(numSrcSels, numSels); ++i){
407 0 : DeserializeSelector(grid, *ppSel[i], tbuf);
408 : }
409 :
410 : // read the rest
411 0 : for(; i < numSrcSels; ++i)
412 : {
413 0 : Selector sel(grid);
414 0 : DeserializeSelector(grid, sel, tbuf);
415 0 : }
416 : }
417 :
418 :
419 0 : if((opts & LGBC_PROJECTION_HANDLER) == LGBC_PROJECTION_HANDLER)
420 : {
421 : // read number of subset handlers
422 : int shIndex;
423 0 : tbuf.read((char*)&shIndex, sizeof(int));
424 :
425 0 : if(pPH)
426 0 : DeserializeProjectionHandler(tbuf, *pPH);
427 : else{
428 0 : ProjectionHandler ph;
429 0 : DeserializeProjectionHandler(tbuf, ph);
430 0 : }
431 : }
432 :
433 : // reactivate the grid-options
434 0 : grid.set_options(gridOptions);
435 :
436 : // check the magic-number
437 : int magicNumber;
438 0 : tbuf.read((char*)&magicNumber, sizeof(int));
439 :
440 0 : if(magicNumber != 3478384){
441 0 : LOG("ERROR in LoadGridFromLGB: Bad magic number at end of file: " << magicNumber << endl);
442 : return false;
443 : }
444 : // done
445 : return true;
446 0 : }
447 :
448 : }// end of namespace
|