OpenLB 1.7
Loading...
Searching...
No Matches
superVtmWriter2D.hh
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2016 Albert Mink, Mathias J. Krause
4 * E-mail contact: info@openlb.net
5 * The most recent release of OpenLB can be downloaded at
6 * <http://www.openlb.net/>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this program; if not, write to the Free
20 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22*/
23
29#ifndef SUPER_VTM_WRITER_2D_HH
30#define SUPER_VTM_WRITER_2D_HH
31
32#include <fstream>
33#include <iostream>
34#include <iomanip>
35#include <string>
36#include "core/singleton.h"
40#include "io/base64.h"
41#include "io/fileName.h"
42#include "io/superVtmWriter2D.h"
43
44
45namespace olb {
46
47
48template<typename T, typename OUT_T, typename W>
49SuperVTMwriter2D<T,OUT_T,W>::SuperVTMwriter2D( std::string name, int overlap, bool binary )
50 : clout( std::cout,"SuperVTMwriter2D" ), _createFile(false), _name(name), _overlap(overlap), _binary(binary)
51{
52 static_assert(std::is_same_v<OUT_T, float> || std::is_same_v<OUT_T, double>,
53 "OUT_T must be either float or double");
54}
55
56template<typename T, typename OUT_T, typename W>
58{
59 int rank = 0;
60#ifdef PARALLEL_MODE_MPI
61 rank = singleton::mpi().getRank();
62#endif
63
64 // !!!!!!!!!!! check whether _pointerVec is empty
65 if ( _pointerVec.empty() ) {
66 clout << "Error: Did you add a Functor ?";
67 }
68 else {
69 // no gaps between vti files (cuboids)
70 for (SuperF2D<T,W>* f : _pointerVec) {
71 f->getSuperStructure().communicate();
72 }
73
74 // to get first element _pointerVec
75 // problem if functors with different SuperStructure are stored
76 // since till now, there is only one origin
77 auto it_begin = _pointerVec.cbegin();
78 if (it_begin == _pointerVec.end()) {
79 throw std::runtime_error("No functor to write");
80 }
81 CuboidGeometry2D<T> const& cGeometry = (**it_begin).getSuperStructure().getCuboidGeometry();
82 // no gaps between vti files (cuboids)
83 LoadBalancer<T>& load = (**it_begin).getSuperStructure().getLoadBalancer();
84
85 // PVD, owns all
86 if ( rank == 0 ) {
87 std::string pathPVD = singleton::directories().getVtkOutDir()
88 + createFileName( _name ) + ".pvd";
89 dataPVDmaster( iT, pathPVD, "data/" + createFileName( _name, iT ) + ".vtm" );
90
91 std::string pathVTM = singleton::directories().getVtkOutDir()
92 + "data/" + createFileName( _name, iT ) + ".vtm";
93 preambleVTM(pathVTM);
94 for (int iC = 0; iC < cGeometry.getNc(); iC++) {
95 dataVTM( iC, pathVTM, createFileName( _name, iT, iC) + ".vti" );
96 }
97 closeVTM(pathVTM);
98 }
99 // VTI, each process writes his cuboids
100 int originLatticeR[3] = {int()};
101 for (int iCloc = 0; iCloc < load.size(); iCloc++) {
102 int nx = cGeometry.get(load.glob(iCloc)).getNx();
103 int ny = cGeometry.get(load.glob(iCloc)).getNy();
104 // to be changed into the following line once local refinement has been implemented
105 // double deltaX = cGeometry.get(load.glob(iCloc)).getDeltaR();
106 T delta = cGeometry.getMotherCuboid().getDeltaR();
107
108 std::string fullNameVTI = singleton::directories().getVtkOutDir() + "data/"
109 + createFileName( _name, iT, load.glob(iCloc) ) + ".vti";
110
111 // get dimension/extent for each cuboid
112 originLatticeR[0] = load.glob(iCloc);
113 T originPhysR[2] = {T()};
114 cGeometry.getPhysR(originPhysR,originLatticeR);
115
116 preambleVTI(fullNameVTI, -_overlap,-_overlap, nx+_overlap-1, ny+_overlap-1, originPhysR[0],originPhysR[1], delta);
117 for (auto it : _pointerVec) {
118 if (_binary) {
119 dataArrayBinary(fullNameVTI, (*it), load.glob(iCloc), nx,ny);
120 }
121 else {
122 dataArray(fullNameVTI, (*it), load.glob(iCloc), nx,ny);
123 }
124 }
125 closePiece(fullNameVTI);
126 closeVTI(fullNameVTI);
127 }
128 }
129}
130
131template<typename T, typename OUT_T, typename W>
133{
136 // no gaps between vti files (cuboids)
138 T delta = cGeometry.getMotherCuboid().getDeltaR();
139
140 int rank = 0;
141#ifdef PARALLEL_MODE_MPI
142 rank = singleton::mpi().getRank();
143#endif
144
145 // write a pvd file, which links all vti files
146 // each vti file is written by one thread, which may own severals cuboids
147 if ( rank == 0 ) {
148 // master only
149 std::string pathVTM = singleton::directories().getVtkOutDir()
150 + createFileName( f.getName(), iT ) + ".vtm";
151
152 preambleVTM(pathVTM);
153 for (int iC = 0; iC < cGeometry.getNc(); iC++) {
154 std::string nameVTI = "data/" + createFileName( f.getName(), iT, iC) + ".vti";
155 // puts name of .vti piece to a .pvd file [fullNamePVD]
156 dataVTM( iC, pathVTM, nameVTI );
157 }
158 closeVTM(pathVTM);
159 } // master only
160
161 for (int iCloc = 0; iCloc < load.size(); iCloc++) {
162 // cuboid
163 int nx = cGeometry.get(load.glob(iCloc)).getNx();
164 int ny = cGeometry.get(load.glob(iCloc)).getNy();
165 // to be changed into the following line once local refinement has been implemented
166 // double deltaX = cGeometry.get(load.glob(iCloc)).getDeltaR();
167
168 std::string fullNameVTI = singleton::directories().getVtkOutDir() + "data/"
169 + createFileName( f.getName(), iT, load.glob(iCloc) ) + ".vti";
170
171 // get dimension/extent for each cuboid
172 int const originLatticeR[3] = {load.glob(iCloc),0,0};
173 T originPhysR[2] = {T()};
174 cGeometry.getPhysR(originPhysR,originLatticeR);
175
176 preambleVTI(fullNameVTI, -_overlap,-_overlap, nx+_overlap-1, ny+_overlap-1, originPhysR[0],originPhysR[1], delta);
177 if (_binary) {
178 dataArrayBinary(fullNameVTI, f, load.glob(iCloc), nx,ny);
179 }
180 else {
181 dataArray(fullNameVTI, f, load.glob(iCloc), nx,ny);
182 }
183 closePiece(fullNameVTI);
184 closeVTI(fullNameVTI);
185 } // cuboid
186}
187
188template<typename T, typename OUT_T, typename W>
189void SuperVTMwriter2D<T,OUT_T,W>::write(std::shared_ptr<SuperF2D<T,W>> ptr_f, int iT)
190{
191 write(*ptr_f, iT);
192}
193
194template<typename T, typename OUT_T, typename W>
196{
197 int rank = 0;
198#ifdef PARALLEL_MODE_MPI
199 rank = singleton::mpi().getRank();
200#endif
201 if ( rank == 0 ) {
202 std::string fullNamePVDmaster = singleton::directories().getVtkOutDir()
203 + createFileName( _name ) + ".pvd";
204 preamblePVD(fullNamePVDmaster);
205 closePVD(fullNamePVDmaster);
206 _createFile = true;
207 }
208}
209
210template<typename T, typename OUT_T, typename W>
212{
213 _pointerVec.push_back(&f);
214}
215
216template<typename T, typename OUT_T, typename W>
217void SuperVTMwriter2D<T,OUT_T,W>::addFunctor(SuperF2D<T,W>& f, const std::string& functorName)
218{
219 f.getName() = functorName;
220 _pointerVec.push_back(&f);
221}
222
223template<typename T, typename OUT_T, typename W>
225{
226 _pointerVec.clear();
227}
228
229template<typename T, typename OUT_T, typename W>
231{
232 return _name;
233}
234
235
236
237
239template<typename T, typename OUT_T, typename W>
240void SuperVTMwriter2D<T,OUT_T,W>::preambleVTI (const std::string& fullName,
241 int x0, int y0, int x1, int y1, T originX, T originY, T delta)
242{
243 const BaseType<T> d_delta = delta;
244 const BaseType<T> d_origin[2] = {originX, originY};
245 std::ofstream fout(fullName, std::ios::trunc);
246 if (!fout) {
247 clout << "Error: could not open " << fullName << std::endl;
248 }
249 fout << "<?xml version=\"1.0\"?>\n";
250 fout << "<VTKFile type=\"ImageData\" version=\"0.1\" "
251 << "byte_order=\"LittleEndian\">\n";
252 fout << "<ImageData WholeExtent=\""
253 << x0 <<" "<< x1 <<" "
254 << y0 <<" "<< y1 <<" "
255 << 0 <<" "<< 0
256 << "\" Origin=\"" << d_origin[0] << " " << d_origin[1] << " " << "0"
257 << "\" Spacing=\"" << d_delta << " " << d_delta << " " << d_delta << "\">\n";
258 fout << "<Piece Extent=\""
259 << x0 <<" "<< x1 <<" "
260 << y0 <<" "<< y1 <<" "
261 << 0 <<" "<< 0 <<"\">\n";
262 fout << "<PointData>\n";
263 fout.close();
264}
265
266template<typename T, typename OUT_T, typename W>
267void SuperVTMwriter2D<T,OUT_T,W>::closeVTI(const std::string& fullNamePiece)
268{
269 std::ofstream fout(fullNamePiece, std::ios::app );
270 if (!fout) {
271 clout << "Error: could not open " << fullNamePiece << std::endl;
272 }
273 fout << "</ImageData>\n";
274 fout << "</VTKFile>\n";
275 fout.close();
276}
277
278template<typename T, typename OUT_T, typename W>
279void SuperVTMwriter2D<T,OUT_T,W>::preamblePVD(const std::string& fullNamePVD)
280{
281 std::ofstream fout(fullNamePVD, std::ios::trunc);
282 if (!fout) {
283 clout << "Error: could not open " << fullNamePVD << std::endl;
284 }
285 fout << "<?xml version=\"1.0\"?>\n";
286 fout << "<VTKFile type=\"Collection\" version=\"0.1\" "
287 << "byte_order=\"LittleEndian\">\n"
288 << "<Collection>\n";
289 fout.close();
290}
291
292template<typename T, typename OUT_T, typename W>
293void SuperVTMwriter2D<T,OUT_T,W>::closePVD(const std::string& fullNamePVD)
294{
295 std::ofstream fout(fullNamePVD, std::ios::app );
296 if (!fout) {
297 clout << "Error: could not open " << fullNamePVD << std::endl;
298 }
299 fout << "</Collection>\n";
300 fout << "</VTKFile>\n";
301 fout.close();
302}
303
304template<typename T, typename OUT_T, typename W>
305void SuperVTMwriter2D<T,OUT_T,W>::preambleVTM(const std::string& fullNamePVD)
306{
307 std::ofstream fout(fullNamePVD, std::ios::trunc);
308 if (!fout) {
309 clout << "Error: could not open " << fullNamePVD << std::endl;
310 }
311 fout << "<?xml version=\"1.0\"?>\n";
312 fout << "<VTKFile type=\"vtkMultiBlockDataSet\" version=\"1.0\" "
313 << "byte_order=\"LittleEndian\">\n"
314 << "<vtkMultiBlockDataSet>\n" ;
315 fout.close();
316}
317
318template<typename T, typename OUT_T, typename W>
319void SuperVTMwriter2D<T,OUT_T,W>::closeVTM(const std::string& fullNamePVD)
320{
321 std::ofstream fout(fullNamePVD, std::ios::app );
322 if (!fout) {
323 clout << "Error: could not open " << fullNamePVD << std::endl;
324 }
325 fout << "</vtkMultiBlockDataSet>\n";
326 fout << "</VTKFile>\n";
327 fout.close();
328}
329
330template<typename T, typename OUT_T, typename W>
331void SuperVTMwriter2D<T,OUT_T,W>::dataVTM(int iC, const std::string& fullNamePVD,
332 const std::string& namePiece)
333{
334 std::ofstream fout(fullNamePVD, std::ios::app);
335 if (!fout) {
336 clout << "Error: could not open " << fullNamePVD << std::endl;
337 }
338 fout << "<Block index=\"" << iC << "\" >\n";
339 fout << "<DataSet index= \"0\" " << "file=\"" << namePiece << "\">\n"
340 << "</DataSet>\n";
341 fout << "</Block>\n";
342 fout.close();
343}
344
345template<typename T, typename OUT_T, typename W>
346void SuperVTMwriter2D<T,OUT_T,W>::dataPVDmaster(int iT,
347 const std::string& fullNamePVDMaster,
348 const std::string& namePiece)
349{
350 std::ofstream fout(fullNamePVDMaster, std::ios::in | std::ios::out | std::ios::ate);
351 if (fout) {
352 fout.seekp(-25,std::ios::end); // jump -25 form the end of file to overwrite closePVD
353
354 fout << "<DataSet timestep=\"" << iT << "\" "
355 << "group=\"\" part=\"\" "
356 << "file=\"" << namePiece << "\"/>\n";
357 fout.close();
358 closePVD(fullNamePVDMaster);
359 }
360 else {
361 clout << "Error: could not open " << fullNamePVDMaster << std::endl;
362 }
363}
364
365template<typename T, typename OUT_T, typename W>
366void SuperVTMwriter2D<T,OUT_T,W>::dataArray(const std::string& fullName,
367 SuperF2D<T,W>& f, int iC, int nx, int ny)
368{
369 std::cout << "DIOCANE" <<std::endl <<std::endl <<std::endl <<std::endl <<std::endl;
370 std::ofstream fout( fullName, std::ios::out | std::ios::app );
371 if (!fout) {
372 clout << "Error: could not open " << fullName << std::endl;
373 }
374
375 fout << "<DataArray " ;
376 if constexpr (std::is_same_v<OUT_T, float>) {
377 fout << "type=\"Float32\" Name=\"" << f.getName() << "\" "
378 << "NumberOfComponents=\"" << f.getTargetDim() <<"\">\n";
379 }
380 else if constexpr (std::is_same_v<OUT_T, double>) {
381 fout << "type=\"Float64\" Name=\"" << f.getName() << "\" "
382 << "NumberOfComponents=\"" << f.getTargetDim() <<"\">\n";
383 }
384
385 int i[3] = {iC, 0, 0};
386 W evaluated[f.getTargetDim()];
387 for (int iDim = 0; iDim < f.getTargetDim(); ++iDim) {
388 evaluated[iDim] = W();
389 }
390 // since cuboid has been blowed up by _overlap [every dimension]
391 // looping from -_overlap to ny (= ny+_overlap, as passed)
392 std::vector<int> tmpVec( 3,int(0) );
393 for (i[2]=-_overlap; i[2] < ny+_overlap; ++i[2]) {
394 for (i[1]=-_overlap; i[1] < nx+_overlap; ++i[1]) {
395 f(evaluated,i);
396 for (int iDim = 0; iDim < f.getTargetDim(); ++iDim) {
397 // tmpVec = {iC,iX,iY,iZ}; // std=c++11
398 fout << evaluated[iDim] << " ";
399 }
400 }
401 }
402 fout << "</DataArray>\n";
403 fout.close();
404}
405
406template<typename T, typename OUT_T, typename W>
407void SuperVTMwriter2D<T,OUT_T,W>::dataArrayBinary(const std::string& fullName,
408 SuperF2D<T,W>& f, int iC, int nx, int ny)
409{
410 std::ofstream fout( fullName, std::ios::out | std::ios::app );
411 if (!fout) {
412 clout << "Error: could not open " << fullName << std::endl;
413 }
414
415 fout << "<DataArray ";
416 if constexpr (std::is_same_v<OUT_T, float>) {
417 fout << "type=\"Float32\" Name=\"" << f.getName() << "\" "
418 << "format=\"binary\" encoding=\"base64\" "
419 << "NumberOfComponents=\"" << f.getTargetDim() <<"\">\n";
420 }
421 else if constexpr (std::is_same_v<OUT_T, double>) {
422 fout << "type=\"Float64\" Name=\"" << f.getName() << "\" "
423 << "format=\"binary\" encoding=\"base64\" "
424 << "NumberOfComponents=\"" << f.getTargetDim() <<"\">\n";
425 }
426 fout.close();
427
428 std::ofstream ofstr( fullName, std::ios::out | std::ios::app | std::ios::binary );
429 if (!ofstr) {
430 clout << "Error: could not open " << fullName << std::endl;
431 }
432
433 size_t fullSize = f.getTargetDim() * (nx+2*_overlap) * (ny+2*_overlap); // how many numbers to write
434 size_t binarySize = size_t( fullSize*sizeof(OUT_T) );
435 // writes first number, which have to be the size(byte) of the following data
436 Base64Encoder<unsigned int> sizeEncoder(ofstr, 1);
437 unsigned int uintBinarySize = (unsigned int)binarySize;
438 sizeEncoder.encode(&uintBinarySize, 1);
439 // write numbers from functor
440 Base64Encoder<OUT_T>* dataEncoder = new Base64Encoder<OUT_T>( ofstr, fullSize );
441
442 int i[3] = {iC, 0, 0};
443 W evaluated[f.getTargetDim()];
444 for (int iDim = 0; iDim < f.getTargetDim(); ++iDim) {
445 evaluated[iDim] = W();
446 }
447 int itter = 0;
448 std::unique_ptr<OUT_T[]> bufferFloat(new OUT_T[fullSize]);
449 for (i[2] = -_overlap; i[2] < ny+_overlap; ++i[2]) {
450 for (i[1] = -_overlap; i[1] < nx+_overlap; ++i[1]) {
451 f(evaluated,i);
452 for (int iDim = 0; iDim < f.getTargetDim(); ++iDim) {
453 bufferFloat[ itter ] = OUT_T( evaluated[iDim] );
454 itter++;
455 }
456 }
457 }
458 dataEncoder->encode( &bufferFloat[0], fullSize );
459 ofstr.close();
460
461 std::ofstream ffout( fullName, std::ios::out | std::ios::app );
462 if (!ffout) {
463 clout << "Error: could not open " << fullName << std::endl;
464 }
465 ffout << "\n</DataArray>\n";
466 ffout.close();
467 delete dataEncoder;
468}
469
470template<typename T, typename OUT_T, typename W>
471void SuperVTMwriter2D<T,OUT_T,W>::closePiece(const std::string& fullNamePiece)
472{
473 std::ofstream fout(fullNamePiece, std::ios::app );
474 if (!fout) {
475 clout << "Error: could not open " << fullNamePiece << std::endl;
476 }
477 fout << "</PointData>\n";
478 fout << "</Piece>\n";
479 fout.close();
480}
481
482
483} // namespace olb
484
485#endif
A cuboid structure represents the grid of a considered domain.
int getNc() const
Returns the number of cuboids in t < 2he structure.
Cuboid2D< T > getMotherCuboid() const
Returns the smallest cuboid that includes all cuboids of the structure.
Cuboid2D< T > & get(int i)
Read and write access to the cuboids.
std::vector< T > getPhysR(int iCglob, int iX, int iY) const
Returns the physical position to the given lattice position respecting periodicity for the overlap no...
std::string & getName()
read and write access to name
Definition genericF.hh:51
Base class for all LoadBalancer.
int glob(int loc) const
represents all functors that operate on a SuperStructure<T,2> in general
SuperStructure< T, 2 > & getSuperStructure()
CuboidGeometry< T, D > & getCuboidGeometry()
Read and write access to cuboid geometry.
virtual void communicate()
LoadBalancer< T > & getLoadBalancer()
Read and write access to the load balancer.
SuperVTMwriter2D writes any SuperF2D to vtk-based output files.
void createMasterFile()
have to be called before calling write(int iT=0), since it creates
void write(int iT=0)
writes functors stored in pointerVec every thread writes a vti file with data from his cuboids the vt...
SuperVTMwriter2D(std::string name, int overlap=1, bool binary=true)
void clearAddedFunctors()
to clear stored functors, not yet used due to lack of necessity
std::string getName() const
getter for _name
void addFunctor(SuperF2D< T, W > &f)
put functor to _pointerVec to simplify writing process of several functors
std::string getVtkOutDir() const
Definition singleton.h:97
int getRank() const
Returns the process ID.
The description of a vector of 2D cuboid – header file.
These functions help you to create file names.
Wrapper functions that simplify the use of MPI.
MpiManager & mpi()
Directories & directories()
Definition singleton.h:150
Top level namespace for all of OpenLB.
std::string createFileName(std::string name)
for .pvd masterFile
Definition fileName.hh:34
typename util::BaseTypeHelper< T >::type BaseType
Definition baseType.h:59
Definition of singletons: global, publicly available information.
A method to write vtk data for cuboid geometries (only for uniform grids) – header file.