/* This file is part of the OpenLB library * * Copyright (C) 2016 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 SUPER_VTM_WRITER_2D_HH #define SUPER_VTM_WRITER_2D_HH #include #include #include #include #include "core/singleton.h" #include "communication/loadBalancer.h" #include "geometry/cuboidGeometry2D.h" #include "communication/mpiManager.h" #include "io/base64.h" #include "io/fileName.h" #include "io/superVtmWriter2D.h" namespace olb { template SuperVTMwriter2D::SuperVTMwriter2D( std::string name, bool binary ) : clout( std::cout,"SuperVTMwriter2D" ), _createFile(false), _name(name), _binary(binary) {} template void SuperVTMwriter2D::write(int iT) { int rank = 0; #ifdef PARALLEL_MODE_MPI rank = singleton::mpi().getRank(); #endif // !!!!!!!!!!! check whether _pointerVec is empty if ( _pointerVec.empty() ) { clout << "Error: Did you add a Functor ?"; } else { // to get first element _pointerVec // problem if functors with different SuperStructure are stored // since till now, there is only one origin auto it_begin = _pointerVec.cbegin(); CuboidGeometry2D const& cGeometry = (**it_begin).getSuperStructure().getCuboidGeometry(); // no gaps between vti files (cuboids) (**it_begin).getSuperStructure().communicate(); LoadBalancer& load = (**it_begin).getSuperStructure().getLoadBalancer(); // PVD, owns all if ( rank == 0 ) { std::string pathPVD = singleton::directories().getVtkOutDir() + createFileName( _name ) + ".pvd"; dataPVDmaster( iT, pathPVD, "data/" + createFileName( _name, iT ) + ".vtm" ); std::string pathVTM = singleton::directories().getVtkOutDir() + "data/" + createFileName( _name, iT ) + ".vtm"; preambleVTM(pathVTM); for (int iC = 0; iC < cGeometry.getNc(); iC++) { dataVTM( iC, pathVTM, createFileName( _name, iT, iC) + ".vti" ); } closeVTM(pathVTM); } // VTI, each process writes his cuboids int originLatticeR[3] = {int()}; for (int iCloc = 0; iCloc < load.size(); iCloc++) { int nx = cGeometry.get(load.glob(iCloc)).getNx(); int ny = cGeometry.get(load.glob(iCloc)).getNy(); // to be changed into the following line once local refinement has been implemented // double deltaX = cGeometry.get(load.glob(iCloc)).getDeltaR(); T delta = cGeometry.getMotherCuboid().getDeltaR(); std::string fullNameVTI = singleton::directories().getVtkOutDir() + "data/" + createFileName( _name, iT, load.glob(iCloc) ) + ".vti"; // get dimension/extent for each cuboid originLatticeR[0] = load.glob(iCloc); T originPhysR[2] = {T()}; cGeometry.getPhysR(originPhysR,originLatticeR); preambleVTI(fullNameVTI, -1,-1,nx,ny, originPhysR[0],originPhysR[1], delta); for (auto it : _pointerVec) { if(_binary) { dataArrayBinary(fullNameVTI, (*it), load.glob(iCloc), nx,ny); } else { dataArray(fullNameVTI, (*it), load.glob(iCloc), nx,ny); } } closePiece(fullNameVTI); closeVTI(fullNameVTI); } } } template void SuperVTMwriter2D::write(SuperF2D& f, int iT) { CuboidGeometry2D const& cGeometry = f.getSuperStructure().getCuboidGeometry(); LoadBalancer& load = f.getSuperStructure().getLoadBalancer(); // no gaps between vti files (cuboids) f.getSuperStructure().communicate(); T delta = cGeometry.getMotherCuboid().getDeltaR(); int rank = 0; #ifdef PARALLEL_MODE_MPI rank = singleton::mpi().getRank(); #endif // write a pvd file, which links all vti files // each vti file is written by one thread, which may own severals cuboids if ( rank == 0 ) { // master only std::string pathVTM = singleton::directories().getVtkOutDir() + createFileName( f.getName(), iT ) + ".vtm"; preambleVTM(pathVTM); for (int iC = 0; iC < cGeometry.getNc(); iC++) { std::string nameVTI = "data/" + createFileName( f.getName(), iT, iC) + ".vti"; // puts name of .vti piece to a .pvd file [fullNamePVD] dataVTM( iC, pathVTM, nameVTI ); } closeVTM(pathVTM); } // master only for (int iCloc = 0; iCloc < load.size(); iCloc++) { // cuboid int nx = cGeometry.get(load.glob(iCloc)).getNx(); int ny = cGeometry.get(load.glob(iCloc)).getNy(); // to be changed into the following line once local refinement has been implemented // double deltaX = cGeometry.get(load.glob(iCloc)).getDeltaR(); std::string fullNameVTI = singleton::directories().getVtkOutDir() + "data/" + createFileName( f.getName(), iT, load.glob(iCloc) ) + ".vti"; // get dimension/extent for each cuboid int const originLatticeR[3] = {load.glob(iCloc),0,0}; T originPhysR[2] = {T()}; cGeometry.getPhysR(originPhysR,originLatticeR); preambleVTI(fullNameVTI, -1,-1, nx,ny, originPhysR[0],originPhysR[1], delta); if(_binary) { dataArrayBinary(fullNameVTI, f, load.glob(iCloc), nx,ny); } else { dataArray(fullNameVTI, f, load.glob(iCloc), nx,ny); } closePiece(fullNameVTI); closeVTI(fullNameVTI); } // cuboid } template void SuperVTMwriter2D::write(std::shared_ptr> ptr_f, int iT) { write(*ptr_f, iT); } template void SuperVTMwriter2D::createMasterFile() { int rank = 0; #ifdef PARALLEL_MODE_MPI rank = singleton::mpi().getRank(); #endif if ( rank == 0 ) { std::string fullNamePVDmaster = singleton::directories().getVtkOutDir() + createFileName( _name ) + ".pvd"; preamblePVD(fullNamePVDmaster); closePVD(fullNamePVDmaster); _createFile = true; } } template void SuperVTMwriter2D::addFunctor(SuperF2D& f) { _pointerVec.push_back(&f); } template void SuperVTMwriter2D::clearAddedFunctors() { _pointerVec.clear(); } template std::string SuperVTMwriter2D::getName() const { return _name; } ////////////////////private member functions/////////////////////////////////// template void SuperVTMwriter2D::preambleVTI (const std::string& fullName, int x0, int y0, int x1, int y1, T originX, T originY, T delta) { std::ofstream fout(fullName, std::ios::trunc); if (!fout) { clout << "Error: could not open " << fullName << std::endl; } fout << "\n"; fout << "\n"; fout << "\n"; fout << "\n"; fout << "\n"; fout.close(); } template void SuperVTMwriter2D::closeVTI(const std::string& fullNamePiece) { std::ofstream fout(fullNamePiece, std::ios::app ); if (!fout) { clout << "Error: could not open " << fullNamePiece << std::endl; } fout << "\n"; fout << "\n"; fout.close(); } template void SuperVTMwriter2D::preamblePVD(const std::string& fullNamePVD) { std::ofstream fout(fullNamePVD, std::ios::trunc); if (!fout) { clout << "Error: could not open " << fullNamePVD << std::endl; } fout << "\n"; fout << "\n" << "\n"; fout.close(); } template void SuperVTMwriter2D::closePVD(const std::string& fullNamePVD) { std::ofstream fout(fullNamePVD, std::ios::app ); if (!fout) { clout << "Error: could not open " << fullNamePVD << std::endl; } fout << "\n"; fout << "\n"; fout.close(); } template void SuperVTMwriter2D::preambleVTM(const std::string& fullNamePVD) { std::ofstream fout(fullNamePVD, std::ios::trunc); if (!fout) { clout << "Error: could not open " << fullNamePVD << std::endl; } fout << "\n"; fout << "\n" << "\n" ; fout.close(); } template void SuperVTMwriter2D::closeVTM(const std::string& fullNamePVD) { std::ofstream fout(fullNamePVD, std::ios::app ); if (!fout) { clout << "Error: could not open " << fullNamePVD << std::endl; } fout << "\n"; fout << "\n"; fout.close(); } template void SuperVTMwriter2D::dataVTM(int iC, const std::string& fullNamePVD, const std::string& namePiece) { std::ofstream fout(fullNamePVD, std::ios::app); if (!fout) { clout << "Error: could not open " << fullNamePVD << std::endl; } fout << "\n"; fout << "\n" << "\n"; fout << "\n"; fout.close(); } template void SuperVTMwriter2D::dataPVDmaster(int iT, const std::string& fullNamePVDMaster, const std::string& namePiece) { std::ofstream fout(fullNamePVDMaster, std::ios::in | std::ios::out | std::ios::ate); if (fout) { fout.seekp(-25,std::ios::end); // jump -25 form the end of file to overwrite closePVD fout << "\n"; fout.close(); closePVD(fullNamePVDMaster); } else { clout << "Error: could not open " << fullNamePVDMaster << std::endl; } } template void SuperVTMwriter2D::dataArray(const std::string& fullName, SuperF2D& f, int iC, int nx, int ny) { std::ofstream fout( fullName, std::ios::out | std::ios::app ); if (!fout) { clout << "Error: could not open " << fullName << std::endl; } fout << "\n"; int i[3] = {iC, 0, 0}; W evaluated[f.getTargetDim()]; for (int iDim = 0; iDim < f.getTargetDim(); ++iDim) { evaluated[iDim] = W(); } // since cuboid has been blowed up by 1 [every dimension] // looping from -1 to ny (= ny+1, as passed) std::vector tmpVec( 3,int(0) ); for (i[2]=-1; i[2] < ny+1; ++i[2]) { for (i[1]=-1; i[1] < nx+1; ++i[1]) { f(evaluated,i); for (int iDim = 0; iDim < f.getTargetDim(); ++iDim) { // tmpVec = {iC,iX,iY,iZ}; // std=c++11 fout << evaluated[iDim] << " "; } } } fout << "\n"; fout.close(); } template void SuperVTMwriter2D::dataArrayBinary(const std::string& fullName, SuperF2D& f, int iC, int nx, int ny) { std::ofstream fout( fullName, std::ios::out | std::ios::app ); if (!fout) { clout << "Error: could not open " << fullName << std::endl; } fout << "\n"; fout.close(); std::ofstream ofstr( fullName, std::ios::out | std::ios::app | std::ios::binary ); if (!ofstr) { clout << "Error: could not open " << fullName << std::endl; } size_t fullSize = f.getTargetDim() * (nx+2) * (ny+2); // how many numbers to write 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 = new Base64Encoder( ofstr, fullSize ); int i[3] = {iC, 0, 0}; W evaluated[f.getTargetDim()]; for (int iDim = 0; iDim < f.getTargetDim(); ++iDim) { evaluated[iDim] = W(); } int itter = 0; std::unique_ptr bufferFloat(new float[fullSize]); for (i[2] = -1; i[2] < ny+1; ++i[2]) { for (i[1] = -1; i[1] < nx+1; ++i[1]) { f(evaluated,i); for (int iDim = 0; iDim < f.getTargetDim(); ++iDim) { bufferFloat[ itter ] = float( evaluated[iDim] ); itter++; } } } dataEncoder->encode( &bufferFloat[0], fullSize ); ofstr.close(); std::ofstream ffout( fullName, std::ios::out | std::ios::app ); if (!ffout) { clout << "Error: could not open " << fullName << std::endl; } ffout << "\n\n"; ffout.close(); delete dataEncoder; } template void SuperVTMwriter2D::closePiece(const std::string& fullNamePiece) { std::ofstream fout(fullNamePiece, std::ios::app ); if (!fout) { clout << "Error: could not open " << fullNamePiece << std::endl; } fout << "\n"; fout << "\n"; fout.close(); } } // namespace olb #endif