/* This file is part of the OpenLB library * * Copyright (C) 2014 Albert Mink, Mathias J. Krause * E-mail contact: info@openlb.net * The most recent release of OpenLB can be downloaded at * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ /** \file * A method to write vtk data for cuboid geometries * (only for uniform grids) -- generic implementation. */ #ifndef BLOCK_VTK_WRITER_3D_HH #define BLOCK_VTK_WRITER_3D_HH #include #include #include "communication/mpiManager.h" #include "core/singleton.h" #include "io/blockVtkWriter3D.h" #include "io/base64.h" #include "io/fileName.h" namespace olb { template BlockVTKwriter3D::BlockVTKwriter3D( std::string name, bool binary ) : clout( std::cout,"BlockVTKwriter3D" ), _name(name), _binary(binary) {} template BlockVTKwriter3D::~BlockVTKwriter3D () { clearAddedFunctors(); } template void BlockVTKwriter3D::write(int iT) { if ( _pointerVec.empty() ) { clout << "Error: Please add functor via addFunctor()"; } else { // get first functor auto it = _pointerVec.cbegin(); T originX = 0; T originY = 0; T originZ = 0; int nx = (**it).getBlockStructure().getNx() -1; int ny = (**it).getBlockStructure().getNy() -1; int nz = (**it).getBlockStructure().getNz() -1; std::string fullNameVti = singleton::directories().getVtkOutDir() + createFileName( _name, iT ) + ".vti"; preamble( fullNameVti, nx,ny,nz, originX,originY,originZ ); if ( _binary ) { // iterate on functors for ( auto functor = _pointerVec.cbegin(); functor != _pointerVec.cend(); ++functor) { writeRawDataBinary( fullNameVti, **functor, nx, ny, nz); } } else { for ( auto functor = _pointerVec.cbegin(); functor != _pointerVec.cend(); ++functor) { writeRawData( fullNameVti, **functor, nx, ny, nz); } } closePreamble( fullNameVti ); } } template void BlockVTKwriter3D::write(BlockF3D& f, int iT) { T originX = 0; T originY = 0; T originZ = 0; int nx = f.getBlockStructure().getNx() -1; int ny = f.getBlockStructure().getNy() -1; int nz = f.getBlockStructure().getNz() -1; std::string fullNameVti = singleton::directories().getVtkOutDir() + createFileName( f.getName(), iT ) + ".vti"; preamble( fullNameVti, nx,ny,nz, originX,originY,originZ ); if ( _binary ) { writeRawData( fullNameVti, f, nx,ny,nz ); } else { writeRawDataBinary( fullNameVti, f, nx,ny,nz ); } closePreamble( fullNameVti ); } template void BlockVTKwriter3D::addFunctor(BlockF3D& f) { _pointerVec.push_back(&f); } template void BlockVTKwriter3D::clearAddedFunctors() { _pointerVec.clear(); } template void BlockVTKwriter3D::preamble(const std::string& fullName, int nx, int ny, int nz, T originX, T originY, T originZ) { if (singleton::mpi().getRank()==0) { std::ofstream fout(fullName.c_str()); if (!fout) { clout << "Error: could not open " << fullName << std::endl; } // spacing is not known for BlockF3D classes // prone to error: spacing might correspond to extension in y or z direction // at the end of the day, is can be fixed by apply a scaling in paraview double spacing = 1/double(nx); fout << "\n"; fout << "\n"; fout << "\n"; fout << "\n"; fout << "\n"; fout.close(); } } template void BlockVTKwriter3D::closePreamble(const std::string& fullNamePiece) { if (singleton::mpi().getRank()==0) { std::ofstream fout(fullNamePiece.c_str(), std::ios::app ); if (!fout) { clout << "Error: could not open " << fullNamePiece << std::endl; } fout << "\n"; fout << "\n"; fout << "\n"; fout << "\n"; fout.close(); } } template void BlockVTKwriter3D::writeRawData(const std::string& fullNameVti, BlockF3D& f, int nx, int ny, int nz) { std::ofstream fout(fullNameVti.c_str(), std::ios::app); if (!fout) { clout << "Error: could not open " << fullNameVti << std::endl; } if (singleton::mpi().getRank()==0) { fout << "\n"; } int i[3] = {int()}; T evaluated[f.getTargetDim()]; for (int iDim = 0; iDim < f.getTargetDim(); ++iDim) { evaluated[iDim] = T(); } for (i[2] = 0; i[2] < nz+1; ++i[2]) { for (i[1] = 0; i[1] < ny+1; ++i[1]) { for (i[0] = 0; i[0] < nx+1; ++i[0]) { f(evaluated,i); for (int iDim = 0; iDim < f.getTargetDim(); ++iDim) { if (singleton::mpi().getRank()==0) { fout << evaluated[iDim] << " "; } } } } } if (singleton::mpi().getRank()==0) { fout << "\n\n"; } fout.close(); } // uses base64 encoder to write binary output // first number is written by a seperate sizeEncoder // this number indicates how many numbers will be stored. // then dataEncoder will be called to write output. // !!code is fixed to float functor values!! template void BlockVTKwriter3D::writeRawDataBinary(const std::string& fullNameVti, BlockF3D& f, int nx, int ny, int nz) { const char* fileName = fullNameVti.c_str(); std::ofstream fout(fileName, std::ios::app); if (!fout) { clout << "Error: could not open " << fileName << std::endl; } if (singleton::mpi().getRank()==0) { fout << "\n"; } else { fout << "type=\"Float32\" Name=\"" << f.getName() << "\" " << "format=\"binary\" encoding=\"base64\" " << "NumberOfComponents=\"" << f.getTargetDim() << "\">\n"; } } fout.close(); std::ofstream ofstr( fileName, std::ios::out | std::ios::app | std::ios::binary ); if (!ofstr) { clout << "Error: could not open " << fileName << std::endl; } size_t fullSize = f.getTargetDim() * (1 + nx) * (1 + ny) * (1 + nz); size_t binarySize = size_t( fullSize * sizeof(float) ); // writes first number, which have to be the size(byte) of the following data Base64Encoder sizeEncoder(ofstr, 1); unsigned int uintBinarySize = (unsigned int)binarySize; sizeEncoder.encode(&uintBinarySize, 1); // write numbers from functor Base64Encoder* dataEncoder = nullptr; dataEncoder = new Base64Encoder( ofstr, fullSize ); int i[3] = {int()}; T evaluated[f.getTargetDim()]; for (int iDim = 0; iDim < f.getTargetDim(); ++iDim) { evaluated[iDim] = T(); } for (i[2] = 0; i[2] < nz+1; ++i[2]) { for (i[1] = 0; i[1] < ny+1; ++i[1]) { for (i[0] = 0; i[0] < nx+1; ++i[0]) { f(evaluated,i); for (int iDim = 0; iDimencode( &evaluated2, 1 ); } } } } } ofstr.close(); if (singleton::mpi().getRank()==0) { std::ofstream foutt(fileName, std::ios::out | std::ios::app); if (!foutt) { clout << "Error: could not open " << fileName << std::endl; } foutt << "\n\n"; foutt.close(); } delete dataEncoder; } } // namespace olb #endif