Arh2Reader.cc 19.5 KB
Newer Older
1
2
3
4
5
6
7
8
9
#include "Arh2Reader.h"
#include "Mesh.h"
#include "MeshStructure.h"
#include "Traverse.h"
#include "DOFVector.h"
#include "SystemVector.h"
#include "Debug.h"
#include "../Arh2Reader.h"

10
#include <boost/filesystem.hpp>
11
12
13
14
15
16
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/copy.hpp>
#ifdef HAVE_COMPRESSION
#include <boost/iostreams/filter/zlib.hpp>
#endif

17
18
19
20
21
22
23
24
25
namespace AMDiS { namespace io {

  using namespace std;

  namespace Arh2Reader
  {
    namespace detail
    {
      
Siqi Ling's avatar
Siqi Ling committed
26
      uint8_t firstRead(ifstream& file)
27
28
29
30
      {
	FUNCNAME("Arh2Reader::detail::firstRead");
	
	string typeId(4, ' ');
Siqi Ling's avatar
Siqi Ling committed
31
	uint8_t major = 0, minor = 0;
32
33
    
	file.read(const_cast<char*>(typeId.data()), 4);
Siqi Ling's avatar
Siqi Ling committed
34
	TEST_EXIT(typeId == "arh2")
35
36
	  ("Cannot read Arh2 format: this file is not \"arh2\" format.\n");

Siqi Ling's avatar
Siqi Ling committed
37
38
	file.read(reinterpret_cast<char*>(&major), 1);
	TEST_EXIT(major == AMDiS::io::Arh2Reader::MAJOR)
39
	  ("Cannot read Arh2 format: Arh2Reader major version is %i, the file major version is %i. \n",
Siqi Ling's avatar
Siqi Ling committed
40
	  AMDiS::io::Arh2Reader::MAJOR, major);
41

Siqi Ling's avatar
Siqi Ling committed
42
43
	file.read(reinterpret_cast<char*>(&minor), 1);
	TEST_EXIT(minor <= AMDiS::io::Arh2Reader::MINOR)
44
	  ("Cannot read Arh2 format: Arh2Reader minor version is %i is smaller than the file minor version %i.\n", 
Siqi Ling's avatar
Siqi Ling committed
45
46
	  AMDiS::io::Arh2Reader::MINOR, minor);
	return minor;
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
143
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
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
      }
      
      void setDofValues(int macroElIndex, Mesh *mesh,
			     vector<vector<double> >& values, 
                             vector<DOFVector<double>*>& vecs,
                             vector<vector<int> >& feSpaces)
      {
	if(vecs.size() == 0)
	  return;

	std::set<int> unique;
	std::pair<std::set<int>::iterator,bool> ret;
	std::vector<std::set<int> > visited;
	std::vector<int> dofIndex;
	int globalDof = 0; 

	for(size_t i = 0; i < feSpaces.size(); i++)
	{
	  visited.push_back(unique);
	  dofIndex.push_back(0);
	}

	TraverseStack stack;
	ElInfo *elInfo = stack.traverseFirstOneMacro(mesh, macroElIndex, -1, 
						    Mesh::CALL_EVERY_EL_PREORDER);
	while (elInfo) {
	  Element *el = elInfo->getElement();
	  if (el->isLeaf())
	  {
	    int valuePos = 0;
	    for(size_t i = 0; i < feSpaces.size(); i++)
	    {
	      int num = -1;
	      for(size_t j = 0; j < feSpaces[i].size(); j++)
	      {
		if((vecs.size() > (unsigned)feSpaces[i][j]) && vecs[feSpaces[i][j]])
		{
		  num = feSpaces[i][j];
		  break;
		}
	      }
	      if(num == -1)
	      {
		valuePos += feSpaces[i].size();
		continue;
	      }
	      DOFAdmin* admin = vecs[num]->getFeSpace()->getAdmin(); 
	      TEST_EXIT(admin)("the DOFAdmin of DOFVector is null, this should not happen.");

	      int n0, nd, nd0;

	      if ((nd = admin->getNumberOfDofs(VERTEX)))  {
		int vertices = mesh->getGeo(VERTEX);
		nd0 = admin->getNumberOfPreDofs(VERTEX);
		n0 = mesh->getNode(VERTEX);
		for (int n = 0; n < vertices; n++)
		  for(int d = 0; d < nd; d++)
		  {
		    globalDof = elInfo->getElement()->getDof(n0 + n, nd0 + d);
		    ret = visited[i].insert(globalDof);
		    if(ret.second)
		    {
		      for(size_t j = 0 ; j < feSpaces[i].size(); j++)
		      {
			if((vecs.size() > (unsigned)feSpaces[i][j]) && vecs[feSpaces[i][j]])
			{
			  (*vecs[feSpaces[i][j]])[globalDof] = values[valuePos + j][dofIndex[i]];
			}
		      }
		      dofIndex[i]++;
		    }
		  }
	      }
	      if (mesh->getDim() > 1) {
		if ((nd = admin->getNumberOfDofs(EDGE)))  {
		  int edges = mesh->getGeo(EDGE);
		  nd0 = admin->getNumberOfPreDofs(EDGE);
		  n0 = mesh->getNode(EDGE);
		  for (int n = 0; n < edges; n++)
		  for(int d = 0; d < nd; d++)
		  {
		    globalDof = elInfo->getElement()->getDof(n0 + n, nd0 + d);
		    ret = visited[i].insert(globalDof);
		    if(ret.second)
		    {
		      for(size_t j = 0 ; j < feSpaces[i].size(); j++)
		      {
			if((vecs.size() > (unsigned)feSpaces[i][j]) && vecs[feSpaces[i][j]])
			  (*vecs[feSpaces[i][j]])[globalDof] = values[valuePos + j][dofIndex[i]];
		      }
		      dofIndex[i]++;
		    }
		  }
		}
	      }
	      if (mesh->getDim() == 3) {
		if ((nd = admin->getNumberOfDofs(FACE)))  {
		  int faces = mesh->getGeo(FACE);
		  nd0 = admin->getNumberOfPreDofs(FACE);
		  n0 = mesh->getNode(FACE);
		  for (int n = 0; n < faces; n++)
		  for(int d = 0; d < nd; d++)
		  {
		    globalDof = elInfo->getElement()->getDof(n0 + n, nd0 + d);
		    ret = visited[i].insert(globalDof);
		    if(ret.second)
		    {
		      for(size_t j = 0 ; j < feSpaces[i].size(); j++)
		      {
			if((vecs.size() > (unsigned)feSpaces[i][j]) && vecs[feSpaces[i][j]])
			  (*vecs[feSpaces[i][j]])[globalDof] = values[valuePos + j][dofIndex[i]];
		      }
		      dofIndex[i]++;
		    }
		  }
		}
	      }
	      if ((nd = admin->getNumberOfDofs(CENTER)))  {
		nd0 = admin->getNumberOfPreDofs(CENTER);
		n0 = mesh->getNode(CENTER);
		for(int d = 0; d < nd; d++)
		{
		  globalDof = elInfo->getElement()->getDof(n0, nd0 + d);
		  ret = visited[i].insert(globalDof);
		  if(ret.second)
		  {
		    for(size_t j = 0 ; j < feSpaces[i].size(); j++)
		    {
		      if((vecs.size() > (unsigned)feSpaces[i][j]) && vecs[feSpaces[i][j]])
			(*vecs[feSpaces[i][j]])[globalDof] = values[valuePos + j][dofIndex[i]];
		    }
		    dofIndex[i]++;    
		  }
		}
	      }
	      valuePos += feSpaces[i].size();
	    }
	  }                                                                                         
	  elInfo = stack.traverseNext(elInfo);
	} 
      }
      
      void read(string filename,
                         Mesh *mesh,
                         vector<DOFVector<double>*> vecs,
                         bool byName)
       {
	FUNCNAME("Arh2Reader::detail::read()");

	// Get set of all macro elements in mesh.
	std::set<int> macroInMesh;
	for (std::deque<MacroElement*>::iterator it = mesh->getMacroElements().begin();
	    it != mesh->getMacroElements().end(); ++it)
	  macroInMesh.insert((*it)->getIndex());

202
	RefinementManager *refManager = NULL;
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
	switch (mesh->getDim()) {
	case 1:
	  refManager = new RefinementManager1d();
	  break;
	case 2:
	  refManager = new RefinementManager2d();
	  break;
	case 3:
	  refManager = new RefinementManager3d();
	  break;
	default:
	  ERROR_EXIT("Should not happen!\n");
	}
	ifstream file;
	file.open(filename.c_str(), ios::in | ios::binary);
	TEST_EXIT(file.is_open())
	  ("Cannot open file %s\n", filename.c_str());
Siqi Ling's avatar
Siqi Ling committed
220
221
222
223
	  
	file.seekg (0, file.end);
        int fileSize = file.tellg();
        file.seekg (0, file.beg);
224
      
Siqi Ling's avatar
Siqi Ling committed
225
	string cps = "null";
226
227
228
229
230
231
232
	uint32_t headerLen = 0;
	uint32_t nMacroElements = 0;
	uint32_t nValueVectors = 0;
	uint32_t nFeSpaces = 0;
	uint32_t dim = 0, dow = 0;

	// Read fixed header
Siqi Ling's avatar
Siqi Ling committed
233
	uint8_t minor = firstRead(file);
234
235
236
237
238
239
240
      
	file.read(reinterpret_cast<char*>(&headerLen), 4);
	file.read(reinterpret_cast<char*>(&dow), 4);
	file.read(reinterpret_cast<char*>(&dim), 4);
	file.read(reinterpret_cast<char*>(&nFeSpaces), 4);
	file.read(reinterpret_cast<char*>(&nValueVectors), 4);
	file.read(reinterpret_cast<char*>(&nMacroElements), 4);
Siqi Ling's avatar
Siqi Ling committed
241
242
243
	
	if(minor >= 1)
	  file.read(const_cast<char*>(cps.data()), 4);
244
245
	
#ifdef HAVE_COMPRESSION
Siqi Ling's avatar
Siqi Ling committed
246
247
	TEST_EXIT(cps == "null" || cps == "zlib")
	  ("Cannot read Arh2 file. Currently only support zlib compression.\n");
248
#else
Siqi Ling's avatar
Siqi Ling committed
249
	TEST_EXIT(cps == "null")
250
251
252
	  ("HAVE_COMPRESSION OFF. Cannot read compressed Arh2 file.\n");	
#endif
	  
253
254
255
256
257
258
259
260
	TEST_EXIT(dow == (unsigned)mesh->getGeo(WORLD))
	  ("Dow is not match!\n");
	TEST_EXIT(dim == (unsigned)mesh->getDim())
	  ("Dim is not match!\n");
	TEST_EXIT(nValueVectors >= vecs.size())
	  ("File %s has %d vector(s), which is less than the number of DOFVectors %i in vecs!\n",
	   filename.c_str(), nValueVectors, vecs.size());

Siqi Ling's avatar
Siqi Ling committed
261
262
263
	vector<int> vecsNameLen(0);
	vector<string> vecsName(0);
	vector<int> vecsFeSpaceNum(0);
264
	vector<int> macroElIndex(nMacroElements);
Siqi Ling's avatar
Siqi Ling committed
265
	vector<int> macroElSize(nMacroElements);
266
	
Siqi Ling's avatar
Siqi Ling committed
267
	vector<vector<int> > feSpaceDOFs(0);
268
269
270
271
	vector<int> perDOFs(4, 0);
	vector<vector<int> > sortedFeSpaces(nFeSpaces);
	
	// Read macro table
Siqi Ling's avatar
Siqi Ling committed
272
	for(unsigned int i = 0; i < nMacroElements; i++)
273
274
	{
	  file.read(reinterpret_cast<char*>(&macroElIndex[i]), 4);
Siqi Ling's avatar
Siqi Ling committed
275
	  file.read(reinterpret_cast<char*>(&macroElSize[i]), 4);
276
277
	}
	// Read feSpace table
Siqi Ling's avatar
Siqi Ling committed
278
	for(unsigned int i = 0; i < nFeSpaces; i++)
279
280
281
282
283
284
285
286
	{
	  for(int j = 0; j < 4; j++)
	  {
	    file.read(reinterpret_cast<char*>(&perDOFs[j]), 4);
	  }
	  feSpaceDOFs.push_back(perDOFs);
	}
	// Read value table
Siqi Ling's avatar
Siqi Ling committed
287
	for(unsigned int i = 0; i < nValueVectors; i++)
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
	{
	  string tmpString("");
	  uint32_t tmpInt = 0;
	  file.read(reinterpret_cast<char*>(&tmpInt), 4);
	  vecsNameLen.push_back(tmpInt);
	  tmpString.resize(tmpInt, ' ');
	  file.read(const_cast<char*>(tmpString.data()), tmpInt); //
	  vecsName.push_back(tmpString);
	  file.read(reinterpret_cast<char*>(&tmpInt), 4);
	  sortedFeSpaces[tmpInt].push_back(i);
	  vecsFeSpaceNum.push_back(tmpInt);
	} 
	// Adjust and check vecs
	if(byName)
	{
	  if(!vecs.empty())
	  {
	    vector<DOFVector<double>*> tmpVecs = vecs;
	    vecs.clear();
307
	    vecs.resize(nValueVectors, NULL);
308
309
310
311
312
313
	    
	    for(size_t k = 0; k < tmpVecs.size(); k++)
	    {
	      if(!tmpVecs[k])
		break;
	      
Siqi Ling's avatar
Siqi Ling committed
314
	      unsigned int i;
315
316
317
318
	      TEST_EXIT(tmpVecs[k]->getFeSpace()->getAdmin())
		("Vecs number %i has no DOFAdmin. Should not happen.\n", k);
	      DimVec<int>* nDOF = tmpVecs[k]->getFeSpace()->getBasisFcts()->getNumberOfDofs();
	      
Siqi Ling's avatar
Siqi Ling committed
319
320
321
322
	      for(i = 0; i < nValueVectors; i++)
	      {
		if(tmpVecs[k]->getName() != vecsName[i])
		{  
323
		  continue;
Siqi Ling's avatar
Siqi Ling committed
324
325
326
327
328
329
330
		}
		int j;
		for(j = 0; j < nDOF->getSize(); j++)
		{
		  if((*nDOF)[j] != feSpaceDOFs[vecsFeSpaceNum[i]][j])
		  {
		    break;
331
332
		  }
		}
Siqi Ling's avatar
Siqi Ling committed
333
334
		if(j == nDOF->getSize())
		{
335
336
337
338
339
340
341
342
343
344
345
		  vecs[i] = tmpVecs[k];
		  break;
		}
	      }
	      TEST_EXIT(i < nValueVectors)
		("NO DOFVector with the same name and feSpace is found in the file.\n");
	    }
	  }
	}
	else
	{
Siqi Ling's avatar
Siqi Ling committed
346
347
348
349
	  for(size_t i = 0; i < vecs.size(); i++)
	  {
	    if(vecs[i])
	    {
350
351
352
353
	      TEST_EXIT(vecs[i]->getFeSpace()->getAdmin())
	      ("Vecs number %i has no DOFAdmin. Should not happen.\n", i);
    
	      DimVec<int>* nDOF = vecs[i]->getFeSpace()->getBasisFcts()->getNumberOfDofs();
Siqi Ling's avatar
Siqi Ling committed
354
355
356
	      for(int j = 0; j < nDOF->getSize(); j++)
	      {
		TEST_EXIT((*nDOF)[j] == feSpaceDOFs[vecsFeSpaceNum[i]][j])
357
		  ("The fespace of vec number %i is not equal to the correspond fespace.\n", i+1);
Siqi Ling's avatar
Siqi Ling committed
358
	      }
359
360
361
362
	    }
	  }
	}
	// Read data: meshstructure and dof values
Siqi Ling's avatar
Siqi Ling committed
363
	for (unsigned int i = 0; i < nMacroElements; i++) {
364
	  stringstream dataStream(ios::out | ios::in | ios::binary);
Siqi Ling's avatar
Siqi Ling committed
365
366
367
368
369
	  int size = 0;
	  if(minor >= 1)
	    size = macroElSize[i];
	  else
	    size = (i != nMacroElements - 1) ? macroElSize[i + 1] - macroElSize[i] : fileSize - macroElSize[i];
370
371
372
373
374
	  char* buffer = new char[size];
	  file.read(buffer, size);
	  dataStream.write(buffer, size);
	  delete[] buffer;
#ifdef HAVE_COMPRESSION
Siqi Ling's avatar
Siqi Ling committed
375
376
377
378
379
380
381
	  if(cps == "zlib") {
	    stringstream tmp(ios::out | ios::in);
	    boost::iostreams::filtering_streambuf<boost::iostreams::input> in;
	    in.push(boost::iostreams::zlib_decompressor());
	    in.push(dataStream);
	    boost::iostreams::copy(in, tmp);
	    dataStream.str(tmp.str());
382
383
384
	  }
#endif  
          uint32_t nStructureCodes = 0;
385
386
	  uint32_t codeSize = 0;

387
388
389
	  dataStream.read(reinterpret_cast<char*>(&nStructureCodes), 4);
	  dataStream.read(reinterpret_cast<char*>(&codeSize), 4);
	  
390
	  vector<uint64_t> structureCode(nStructureCodes);
391
	  dataStream.read(reinterpret_cast<char*>(&(structureCode[0])), 8 * nStructureCodes);
392
393
394
395
396
397
398
399
400
401
402
403

	  MeshStructure elementStructure;
	  elementStructure.init(structureCode, codeSize);
	  if (macroInMesh.count(macroElIndex[i]))
	    elementStructure.fitMeshToStructure(mesh, refManager, false, macroElIndex[i]);

	  if (nValueVectors > 0) {
	    vector<vector<double> > values(nValueVectors);
	    int valuePos = 0;
	    for(unsigned int j = 0; j < nFeSpaces; j++)
	    {
	      uint32_t nValuesPerVector = 0;
404
	      dataStream.read(reinterpret_cast<char*>(&nValuesPerVector), 4);
405
	      
406
407
408
	      for(size_t k = 0; k < sortedFeSpaces[j].size(); k++)
	      {
		values[valuePos + k].resize(nValuesPerVector); 
Siqi Ling's avatar
Siqi Ling committed
409
		dataStream.read(reinterpret_cast<char*>(&(values[valuePos + k][0])), 8 * nValuesPerVector);
410
411
412
413
414
415
416
417
418
419
420
421
	      } 
	      valuePos += sortedFeSpaces[j].size();
	    }
	    if(!vecs.empty())
	    {
	      if(macroInMesh.count(macroElIndex[i]))
	      {
		setDofValues(macroElIndex[i], mesh, values, vecs, sortedFeSpaces);
	      }
	    }
	  }
	}
Siqi Ling's avatar
Siqi Ling committed
422
	file.close();
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
	delete refManager;
      }
    
      void readFile(string filename, Mesh *mesh,
			  vector<DOFVector<double>*> vecs,
			  bool writeParallel,
			  int nProcs,
			  bool byName)
      {
	FUNCNAME("Arh2Reader::detail::readFile()");
	//The last element in vecs must NOT be NULL
	std::set<string> nameSet;
	pair<std::set<string>::iterator,bool> ret;
	  
	while(!vecs.empty())
	{
439
	  if(vecs.back() == NULL)
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
	    vecs.pop_back();
	  else
	    break;
	}
	// This is the precondition
	for(size_t i = 0; i < vecs.size(); i++)
	{
	  if(vecs[i])
	  {
	    if(!mesh)
	      mesh = vecs[i]->getFeSpace()->getMesh();
	    else
	      TEST_EXIT(mesh == vecs[i]->getFeSpace()->getMesh())
		("The mesh of the DOFVectors should be the same for Reader because in one file there is only one mesh.\n");
	    ret = nameSet.insert(vecs[i]->getName());
	    TEST_EXIT(ret.second)("DOFVectors in vecs cannot have idential name. Please check.\n");
	  }
	}
	if(!mesh)
	{
	  WARNING("You haven't specified the target, no mesh or DOFVectors is given.\n");
	  return;
	}
	if (writeParallel) {
	  using boost::lexical_cast;
	  int sPos = filename.find(".arh");
466
	  TEST_EXIT(sPos >= 0)("Failed to find file postfix: \"arh \"!\n");
467
468
469
	  string name = filename.substr(0, sPos);

	  if (nProcs == -1) {
470
#ifdef HAVE_PARALLEL_DOMAIN_AMDIS
471
472
	    string procFilename = name + "-p" + lexical_cast<string>(MPI::COMM_WORLD.Get_rank()) + "-.arh";
	    read(procFilename, mesh, vecs, byName);
473
	    MSG("ARH file read from: %s\n", procFilename.c_str());
474
#else
475
	    ERROR_EXIT("Reading parallel ARH files in sequential computations requires to specify the number of nodes on which the ARH file was created!\n");
476
#endif
477
	  } else {
478
	    
Siqi Ling's avatar
Siqi Ling committed
479
480
481
482
483
	    // check if there are no more or less files as nProcs
	    int n = 0;
	    for (; n < nProcs + 1; n++) {
	      string fn = name + "-p" + boost::lexical_cast<string>(n) + "-.arh";
	      if(!boost::filesystem::exists(fn)) break;
484
	    }
Siqi Ling's avatar
Siqi Ling committed
485
486
	    TEST_EXIT(n == nProcs)
	      ("Number of arh files doesn't match number of processors \n");
487
	      
Siqi Ling's avatar
Siqi Ling committed
488
489
490
491
492
493
494
495
496
497
498
	    //
	    // Some test should be checked. This is because of the variation of the
	    // number of macro elements per processor:
	    // 
	    //    There should be at least 10 macro Elements per processor, therefore:
	    //        nMacroElements * 2^gr >= nProcs * 10
	    //          =>  gr = log_2(nProcs * 10 / nMacroElements)  

	    int allMacros = mesh->getNumberOfMacros();
	    int allMacrosFromProcFiles = 0;
	    
499
#ifdef HAVE_PARALLEL_DOMAIN_AMDIS
Siqi Ling's avatar
Siqi Ling committed
500
501
502
503
	    int sendValue = static_cast<int>(mesh->getNumberOfMacros());
            MPI::COMM_WORLD.Allreduce(&sendValue, &allMacros, 1, MPI_INT, MPI_SUM);
	    
	    if(MPI::COMM_WORLD.Get_rank() == 0) { 
504
#endif	      
Siqi Ling's avatar
Siqi Ling committed
505
506
	      for(int i = 0; i < nProcs; i++) {
		allMacrosFromProcFiles += readNumOfMacrosFromSgArh(filename, i);
507
508
	      }
	      
Siqi Ling's avatar
Siqi Ling committed
509
510
511
512
513
514
515
516
517
	      TEST_EXIT(allMacros == allMacrosFromProcFiles)
	      ("Number of macro elements in parallel ARH files doesn't match to the current runtime.\n"); 
#ifdef HAVE_PARALLEL_DOMAIN_AMDIS
	    }
#endif    
	    for (int i = 0; i < nProcs; i++) {
	      string procFilename = name + "-p" + lexical_cast<string>(i) + "-.arh";
	      read(procFilename, mesh, vecs, byName);
	      MSG("ARH file read from: %s\n", procFilename.c_str());
518
519
520
521
522
523
524
	    }
	  }
	} else {
	  read(filename, mesh, vecs, byName);
	}
	MSG("ARH file read from: %s\n", filename.c_str());
      }
525
526
527
528
529
530
531
532
      
      void readMetaFromSgArh(std::string filename, int nProc, 
			   std::vector< std::set<std::pair<int, int> > >& data)
      {
	ifstream file;
	file.open(filename.c_str(), ios::in | ios::binary);
	TEST_EXIT(file.is_open())
	  ("Cannot open file %s\n", filename.c_str());
Siqi Ling's avatar
Siqi Ling committed
533
534
535
536
	    
	file.seekg (0, file.end);
	int fileSize = file.tellg();
	file.seekg (0, file.beg);
537
538
539
540
541
542
	  
	uint32_t dow = 0, dim = 0;
	uint32_t headerLen = 0;
	uint32_t nMacroElements = 0;
	uint32_t nValueVectors = 0;
	uint32_t nFeSpaces = 0;
Siqi Ling's avatar
Siqi Ling committed
543
	string cps = "null";    
544
	
Siqi Ling's avatar
Siqi Ling committed
545
	uint8_t minor = firstRead(file);
546
547
548
549
550
551
552

	file.read(reinterpret_cast<char*>(&headerLen), 4);
	file.read(reinterpret_cast<char*>(&dow), 4);
	file.read(reinterpret_cast<char*>(&dim), 4);
	file.read(reinterpret_cast<char*>(&nFeSpaces), 4);
	file.read(reinterpret_cast<char*>(&nValueVectors), 4);
	file.read(reinterpret_cast<char*>(&nMacroElements), 4);
Siqi Ling's avatar
Siqi Ling committed
553
554
555

	if(minor > 0)
	  file.read(const_cast<char*>(cps.data()), 4);
556
557
	
#ifdef HAVE_COMPRESSION
Siqi Ling's avatar
Siqi Ling committed
558
559
	TEST_EXIT(cps == "null" || cps == "zlib")
	  ("Cannot read Arh2 file. Currently only support zlib compression.\n");
560
#else
Siqi Ling's avatar
Siqi Ling committed
561
	TEST_EXIT(cps == "null")
562
563
564
565
	  ("HAVE_COMPRESSION OFF. Cannot read compressed Arh2 file.\n");	
#endif
      
	vector<int> macroElIndex(nMacroElements);
Siqi Ling's avatar
Siqi Ling committed
566
	vector<int> macroElSize(nMacroElements);
567
568
569
	vector<vector<int> > sortedFeSpaces(nFeSpaces);
	  
	// Read macro table
570
	for(uint32_t i = 0; i < nMacroElements; i++) {
571
	  file.read(reinterpret_cast<char*>(&macroElIndex[i]), 4);
Siqi Ling's avatar
Siqi Ling committed
572
	  file.read(reinterpret_cast<char*>(&macroElSize[i]), 4);
573
574
575
	}
	
	// Read feSpace table
Siqi Ling's avatar
Siqi Ling committed
576
	file.seekg(nFeSpaces * 4 * 4, ios_base::cur);
577
578
	
	// Read value table
579
	for(uint32_t i = 0; i < nValueVectors; i++) {
580
581
582
583
584
585
586
587
588
	  string tmpString("");
	  uint32_t tmpInt = 0;
	  file.read(reinterpret_cast<char*>(&tmpInt), 4);
	  tmpString.resize(tmpInt, ' ');
	  file.read(const_cast<char*>(tmpString.data()), tmpInt); //
	  file.read(reinterpret_cast<char*>(&tmpInt), 4);
	  sortedFeSpaces[tmpInt].push_back(i);
	} 
    
589
	for (uint32_t i = 0; i < nMacroElements; i++) {
590
	  stringstream dataStream(ios::out | ios::in | ios::binary);
Siqi Ling's avatar
Siqi Ling committed
591
592
593
594
595
596
	  int size = 0;
	  
	  if(minor > 0)
	    size = macroElSize[i];
	  else
	    size = (i != nMacroElements - 1) ? macroElSize[i + 1] - macroElSize[i] : fileSize - macroElSize[i];
597
598
599
600
601
602
603
	    
	  char* buffer = new char[size];
	  file.read(buffer, size);
	  dataStream.write(buffer, size);
	  delete[] buffer;
	  
#ifdef HAVE_COMPRESSION      
Siqi Ling's avatar
Siqi Ling committed
604
605
606
607
608
609
610
	  if(cps == "zlib") {
	    stringstream tmp(ios::out | ios::in);
	    boost::iostreams::filtering_streambuf<boost::iostreams::input> in;
	    in.push(boost::iostreams::zlib_decompressor());
	    in.push(dataStream);
	    boost::iostreams::copy(in, tmp);
	    dataStream.str(tmp.str());
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
	  }
#endif	    
	  uint32_t nStructureCodes = 0;
	  uint32_t codeSize = 0;

	  dataStream.read(reinterpret_cast<char*>(&nStructureCodes), 4);
	  dataStream.read(reinterpret_cast<char*>(&codeSize), 4);

	  data[nProc].insert(make_pair(macroElIndex[i], codeSize));
	  
	  // We only need codeSize for each macro element data block, so skip all of the unnecessary.
          dataStream.seekg(8 * nStructureCodes, ios_base::cur); 

	  if (nValueVectors > 0) {
	    
626
	    for(uint32_t j = 0; j < nFeSpaces; j++) {
627
628
	      uint32_t nValuesPerVector = 0;
	      dataStream.read(reinterpret_cast<char*>(&nValuesPerVector), 4);
Siqi Ling's avatar
Siqi Ling committed
629
	      dataStream.seekg(sortedFeSpaces[j].size() * 8 * nValuesPerVector, ios_base::cur);
630
631
632
633
	    }
	  }
	}
      } // end readMetaFromSgArh
634
635
636
637
638
639
640
641
    
  
      int readNumOfMacrosFromSgArh(std::string filename, int nProc)
      {
	FUNCNAME("Arh2Reader::readHeaderSize");
	using boost::lexical_cast;
	
	int sPos = filename.find(".arh");
642
	TEST_EXIT(sPos >= 0)("Failed to find file postfix: \"arh \"!\n");
643
644
645
646
647
648
649
650
651
652
653
654
655
	
	if (nProc >= 0) {
	  string name = filename.substr(0, sPos);
	  filename = name + "-p" + lexical_cast<string>(nProc) + "-.arh";
	}
	
	ifstream file;
	  
	file.open(filename.c_str(), ios::in | ios::binary);
	TEST_EXIT(file.is_open())
	  ("Cannot open file %s\n", filename.c_str());
	  
	int nMacroElements = 0;
Siqi Ling's avatar
Siqi Ling committed
656
	detail::firstRead(file);  
657
658
659
660
661
662
	file.seekg(20, ios_base::cur); 
	file.read(reinterpret_cast<char*>(&nMacroElements), 4);
	file.close();
	
	return nMacroElements;
      }
Siqi Ling's avatar
Siqi Ling committed
663

664

665
    } // end namespace detail
666
  } // end namespace Arh2Reader
Siqi Ling's avatar
Siqi Ling committed
667
} } // end namespace io, AMDiS