VtkWriter.cc 9.5 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
/******************************************************************************
 *
 * AMDiS - Adaptive multidimensional simulations
 *
 * Copyright (C) 2013 Dresden University of Technology. All Rights Reserved.
 * Web: https://fusionforge.zih.tu-dresden.de/projects/amdis
 *
 * Authors: 
 * Simon Vey, Thomas Witkowski, Andreas Naumann, Simon Praetorius, et al.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 *
 * This file is part of AMDiS
 *
 * See also license.opensource.txt in the distribution.
 * 
 ******************************************************************************/


#include <stdio.h>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
#include <cmath>

#include "boost/filesystem/operations.hpp"
#include "boost/filesystem/convenience.hpp"

32
33
34
35
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/copy.hpp>
36
#ifdef HAVE_COMPRESSION
37
#include <boost/iostreams/filter/zlib.hpp>
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#endif
#include "AdaptInfo.h"
#include "VtkWriter.h"

namespace AMDiS  { namespace io {
  
    namespace VtkWriter
    {
      
      using namespace std;

      int Aux::writeFile(string name)
      {
	FUNCNAME("VtkWriter::writeFile()");
	
	boost::iostreams::filtering_ostream file;
54

55
56
57
58
59
60
61
62
	{
	  ofstream swapfile(name.c_str(), ios::out | ios::trunc);
	  TEST_EXIT(swapfile.is_open())
	    ("Cannot open file %s for writing!\n", name.c_str());
	  swapfile.close();
	}

	file.push(boost::iostreams::file_descriptor_sink(name, ios::trunc));
63
64
65
66
67
68
69
	
 	if(format == APPENDED || format == APPENDED_COMPRESSED)
	  writeFileToStreamAppended(file);
	else {
	  TEST_EXIT(format == ASCII)("Unknown ParaView mode.\n");
	  writeFileToStream(file);
	}
70
71
72
	return 0;
      }
      
73
74
75
76
77
78
79
80
81
82
83
      std::string Aux::getStreamData()
      {
	using namespace std;

	string result(""), header(""), body("");
	switch(format) {
	  case APPENDED: {
	    BinaryStream hstream;
	    hstream << bstream.getSize();
	    body = bstream.str();
	    header = hstream.str();
84
85
// 	    result = detail::base64Encode(header + body);
	    result = header + body;
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
	    break;
	  }
	  case APPENDED_COMPRESSED: {
#ifdef HAVE_COMPRESSION
	    BinaryStream hstream;
	    int nBlocks = bstream.getSize() / AMDIS_ZLIB_BLOCK_SIZE + 1;
	    int finalsize = bstream.getSize() % AMDIS_ZLIB_BLOCK_SIZE;
	    hstream << nBlocks << AMDIS_ZLIB_BLOCK_SIZE << finalsize;
	      
	    string data = bstream.str();
	      
	    for(int i = 0; i < nBlocks; i++) {
	      string subData = (nBlocks - 1 == i) ? data.substr(i * AMDIS_ZLIB_BLOCK_SIZE, finalsize) : data.substr(i * AMDIS_ZLIB_BLOCK_SIZE, AMDIS_ZLIB_BLOCK_SIZE);
	      stringstream tmp1, tmp2;
	      tmp1 << subData;
	      boost::iostreams::filtering_streambuf<boost::iostreams::input> in;
	      in.push(boost::iostreams::zlib_compressor());
	      in.push(tmp1);
		
	      boost::iostreams::copy(in, tmp2);
	      subData = tmp2.str();
	      int size = subData.length();
	      hstream << size;
	      body += subData;
	    }
	    header = hstream.str();
112
113
// 	    result = detail::base64Encode(header) + detail::base64Encode(body);
	    result = header + body;
114
115
116
117
118
119
120
121
122
123
#endif
	    break;
	  }
	  case ASCII:
	  default:break;
	}
	bstream.str("");
	return result;
      }
      
124
125
126
127
// __________________________________________________________________________ //
      
      namespace detail 
      {
128
129
130
131
132
133
134
// 	std::string base64Encode(std::string text)
// 	{
// 	  unsigned int writePaddChars = (3-text.length()%3)%3;
// 	  std::string base64(binary_base64(text.begin()),binary_base64(text.end()));
// 	  base64.append(writePaddChars,'=');
// 	  return base64;
// 	}
135
136
137
138
139
140
141
142
	
	std::string extract_relative_path(std::string valueFilename, std::string animationFilename)
	{
	  using namespace boost::filesystem;
	  path vtu_path = valueFilename;
	  path pvd_path = animationFilename;
	    
	  path::iterator it_vtu, it_pvd;
Siqi Ling's avatar
Siqi Ling committed
143
144
145
146
#if (BOOST_VERSION < 104800)
	  path vtu_path0 = complete(vtu_path); vtu_path0.remove_filename();
	  path pvd_path0 = complete(pvd_path); pvd_path0.remove_filename();
#else
147
148
	  path vtu_path0 = absolute(vtu_path); vtu_path0.remove_filename();
	  path pvd_path0 = absolute(pvd_path); pvd_path0.remove_filename();
Siqi Ling's avatar
Siqi Ling committed
149
#endif
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
	  // find matching root directories
	  for (it_vtu = vtu_path0.begin(), it_pvd = pvd_path0.begin(); 
	      it_vtu != vtu_path0.end() && it_pvd != pvd_path0.end() && *it_vtu == *it_pvd;
	      it_vtu++, it_pvd++) {}
	  
	  // create relative path
	  path new_vtu_path;
	  for (; it_pvd != pvd_path0.end(); it_pvd++)
	    new_vtu_path /= "..";	  
	  for (; it_vtu != vtu_path0.end(); it_vtu++)
	    new_vtu_path /= *it_vtu;	  
	  new_vtu_path /= vtu_path.filename();
	  
	  return new_vtu_path.string();
	}
165
166
167
168
169
170
171
172

	int updateAnimationFile(AdaptInfo *adaptInfo,
				string valueFilename,
				vector< pair<double, string> > *paraViewAnimationFrames,
				string animationFilename)
	{
	  FUNCNAME("updateAnimationFile()");

173
174
	  paraViewAnimationFrames->push_back(
	    make_pair(adaptInfo->getTime(), extract_relative_path(valueFilename, animationFilename)));
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

	  boost::iostreams::filtering_ostream file;
	  {
	    ofstream swapfile(animationFilename.c_str(), 
				  ios::out | ios::trunc);
	    TEST_EXIT(swapfile.is_open())
	      ("Cannot open file %s for writing!\n", animationFilename.c_str());
	    swapfile.close();
	  }
	  file.push(boost::iostreams::file_descriptor_sink(animationFilename, 
							  ios::trunc)); 

	  file << "<?xml version=\"1.0\"?>\n";
	  file << "<VTKFile type=\"Collection\" version=\"0.1\" >"  << "\n";
	  file << "<Collection>\n";

	  for (vector<pair<double, string> >::iterator it = paraViewAnimationFrames->begin();
	      it < paraViewAnimationFrames->end(); ++it) {
	    file << "<DataSet timestep=\"" << it->first
		<< "\" part=\"0\" file=\"" << it->second << "\"/>\n";
	  }

	  file << "</Collection>\n";
	  file << "</VTKFile>\n";

	  return 0;
	}
	

204
205
        
        
206
207
	void writeParallelFile(string name, int nRanks,
			      string fnPrefix, string fnPostfix,
208
			      const vector<string> &componentNames,
209
			      ::AMDiS::io::VtkWriter::Vtuformat format,
Praetorius, Simon's avatar
Praetorius, Simon committed
210
			      bool highPrecision,
211
212
			      bool writeAsVector,
			      bool createSubDir
Praetorius, Simon's avatar
Praetorius, Simon committed
213
			      )
214
215
216
        {
	  using boost::lexical_cast;
          vector< string > fileNames(nRanks);
217
	  for (int i = 0; i < nRanks; i++)
218
	    fileNames[i] = fnPrefix + "-p" + lexical_cast<string>(i) + "-" + fnPostfix;
219
220
	  
          writeParallelFile(name, nRanks, fileNames, componentNames, format, highPrecision, writeAsVector, createSubDir);
221
222
223
224
225
226
227
        }

	void writeParallelFile(string name, int nRanks,
			      vector<string>& subNames,
			      const vector<string> &componentNames,
			      ::AMDiS::io::VtkWriter::Vtuformat format,
			      bool highPrecision,
228
229
			      bool writeAsVector,
			      bool createSubDir
230
			      )
231
232
233
	{
	  FUNCNAME("writeParallelFile()");
	  using boost::lexical_cast;
234
235
236
237
238
	  
#ifndef HAVE_COMPRESSION
	  if(format == APPENDED_COMPRESSED) 
	    format = APPENDED;
#endif
239
240
241
242
243
244
245
246
247
248
249

	  boost::iostreams::filtering_ostream file;
	  {
	    ofstream swapfile(name.c_str(), ios::out | ios::trunc);
	    TEST_EXIT(swapfile.is_open())
	      ("Cannot open file %s for writing!\n", name.c_str());
	    swapfile.close();
	  }
	  file.push(boost::iostreams::file_descriptor_sink(name, ios::trunc)); 

	  file << "<?xml version=\"1.0\"?>\n";
250
251
252
253
254
255
	  
	  if(format == ::AMDiS::io::VtkWriter::APPENDED_COMPRESSED)
	    file << "<VTKFile type=\"PUnstructuredGrid\" compressor=\"vtkZLibDataCompressor\" >\n";
	  else
	    file << "<VTKFile type=\"PUnstructuredGrid\" >\n";
	  
256
	  file << "  <PUnstructuredGrid GhostLevel=\"0\">\n";
257
258
259
260
261
262
263
264
265
266
267
268
269
270
	  file << "    <PPoints>\n";
	  
	  if(highPrecision && format != ::AMDiS::io::VtkWriter::ASCII)
	    file << "      <PDataArray type=\"Float64\"";
	  else
	    file << "      <PDataArray type=\"Float32\"";
	  
	  if(format == ::AMDiS::io::VtkWriter::ASCII)
	    file << " NumberOfComponents=\"3\" format=\"ascii\"/>\n";
	  else
	    file << " NumberOfComponents=\"3\" format=\"appended\"/>\n";
	  
	  file << "    </PPoints>\n"
	      << "    <PCells>\n"
271
272
273
274
275
	      << "      <PDataArray type=\"Int32\" Name=\"offsets\"/>\n"
	      << "      <PDataArray type=\"UInt8\" Name=\"types\"/>\n"
	      << "      <PDataArray type=\"Int32\" Name=\"connectivity\"/>\n"
	      << "    </PCells>\n";
	  file << "    <PPointData>\n";
Praetorius, Simon's avatar
Praetorius, Simon committed
276
	  
277
278
	  int nValues = static_cast<int>(componentNames.size());
	  nValues = writeAsVector ? std::min(nValues,1) : nValues;	
279
	  for (int i = 0; i < nValues; i++) {
280
281
282
283
284
285
286
287
	    if(highPrecision && format != ::AMDiS::io::VtkWriter::ASCII)
	      file << "      <PDataArray type=\"Float64\" Name=\"";
	    else 
	      file << "      <PDataArray type=\"Float32\" Name=\"";
	    
	    file << componentNames[i];
	    
	    if(format == ::AMDiS::io::VtkWriter::ASCII)
Praetorius, Simon's avatar
Praetorius, Simon committed
288
	      file << "\" format=\"ascii\"";
289
	    else
Praetorius, Simon's avatar
Praetorius, Simon committed
290
291
292
293
	      file << "\" format=\"appended\"";
	    if (writeAsVector && componentNames.size() > 1)
	      file << " NumberOfComponents=\"" << std::max(3,static_cast<int>(componentNames.size())) << "\"";
	    file << "/>\n"; 
294
295
	  }
	  
Praetorius, Simon's avatar
Praetorius, Simon committed
296
	  
297
298
299
	  file << "    </PPointData>\n";

	  for (int i = 0; i < nRanks; i++) {
300
	    boost::filesystem::path filepath(subNames[i]);
301
302
303
304
305
	    file << "    <Piece Source=\"";
	    if (createSubDir)
	      file << "./data/";
	    file << boost::filesystem::basename(filepath)
	         << boost::filesystem::extension(filepath) << "\"/>\n";      
306
307
308
309
310
311
312
313
314
	  }

	  file << "  </PUnstructuredGrid>\n";
	  file << "</VTKFile>\n";
	}
	
      } // end namespace detail
    } // end namespace VtkWriter
} } // end namespace io, AMDiS