From 94d3e79a8617f88dc0219cfdeedfa3147833719d Mon Sep 17 00:00:00 2001 From: Adrian Kummerlaender Date: Mon, 24 Jun 2019 14:43:36 +0200 Subject: Initialize at openlb-1-3 --- src/io/superVtmWriter3D.hh | 439 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 439 insertions(+) create mode 100644 src/io/superVtmWriter3D.hh (limited to 'src/io/superVtmWriter3D.hh') diff --git a/src/io/superVtmWriter3D.hh b/src/io/superVtmWriter3D.hh new file mode 100644 index 0000000..b5ad6a2 --- /dev/null +++ b/src/io/superVtmWriter3D.hh @@ -0,0 +1,439 @@ +/* This file is part of the OpenLB library + * + * Copyright (C) 2016-2017 Albert Mink, Maximilian Gaedtke, Markus Morhard 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_3D_HH +#define SUPER_VTM_WRITER_3D_HH + +#include +#include +#include +#include +#include "core/singleton.h" +#include "communication/loadBalancer.h" +#include "geometry/cuboidGeometry3D.h" +#include "communication/mpiManager.h" +#include "io/fileName.h" +#include "io/superVtmWriter3D.h" +#include "io/base64.h" + +#include +#include +#include "zlib.h" + + + +namespace olb { + + +template +SuperVTMwriter3D::SuperVTMwriter3D( const std::string& name, bool binary, bool compress) + : clout( std::cout,"SuperVTMwriter3D" ), _createFile(false), _name(name), _binary(binary), _compress(compress) +{} + +template +void SuperVTMwriter3D::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 + const auto it_begin = _pointerVec.cbegin(); + CuboidGeometry3D const& cGeometry = (**it_begin).getSuperStructure().getCuboidGeometry(); + // no gaps between vti files (cuboids) + (**it_begin).getSuperStructure().communicate(); + LoadBalancer& load = (**it_begin).getSuperStructure().getLoadBalancer(); + const T delta = cGeometry.getMotherCuboid().getDeltaR(); + + // PVD, owns all + if ( rank == 0 ) { + const std::string pathPVD = singleton::directories().getVtkOutDir() + + createFileName( _name ) + ".pvd"; + dataPVDmaster( iT, pathPVD, "data/" + createFileName( _name, iT ) + ".vtm" ); + + const 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 its cuboids + for (int iCloc = 0; iCloc < load.size(); iCloc++) { + // get piece/whole extent + const Vector extent0(-1,-1,-1); + const Vector extent1( cGeometry.get(load.glob(iCloc)).getExtend() ); + + const std::string fullNameVTI = singleton::directories().getVtkOutDir() + "data/" + + createFileName( _name, iT, load.glob(iCloc) ) + ".vti"; + + // get dimension/extent for each cuboid + const int originLatticeR[4] = {load.glob(iCloc),0,0,0}; + T originPhysR[3] = {T()}; + cGeometry.getPhysR(originPhysR,originLatticeR); + + preambleVTI(fullNameVTI, extent0, extent1, originPhysR, delta); + for (auto it : _pointerVec) { + dataArray(fullNameVTI, *it, load.glob(iCloc), extent1); + } + closePiece(fullNameVTI); + closeVTI(fullNameVTI); + } + } +} + +template +void SuperVTMwriter3D::write(SuperF3D& f, int iT) +{ + CuboidGeometry3D const& cGeometry = f.getSuperStructure().getCuboidGeometry(); + LoadBalancer& load = f.getSuperStructure().getLoadBalancer(); + // no gaps between vti files (cuboids) + f.getSuperStructure().communicate(); + const 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 + const std::string pathVTM = singleton::directories().getVtkOutDir() + + createFileName( f.getName(), iT ) + ".vtm"; + + preambleVTM(pathVTM); + for (int iC = 0; iC < cGeometry.getNc(); iC++) { + const 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++) { + // get piece/whole extent + const Vector extent0(-1,-1,-1); + const Vector extent1( cGeometry.get(load.glob(iCloc)).getExtend() ); + + const std::string fullNameVTI = singleton::directories().getVtkOutDir() + "data/" + + createFileName( f.getName(), iT, load.glob(iCloc) ) + ".vti"; + + // get dimension/extent for each cuboid + const int originLatticeR[4] = {load.glob(iCloc),0,0,0}; + T originPhysR[3] = {T()}; + cGeometry.getPhysR(originPhysR,originLatticeR); + + preambleVTI(fullNameVTI, extent0, extent1, originPhysR, delta); + + dataArray(fullNameVTI, f, load.glob(iCloc), extent1); + closePiece(fullNameVTI); + closeVTI(fullNameVTI); + } // cuboid +} + + +template +void SuperVTMwriter3D::write(std::shared_ptr> ptr_f, int iT) +{ + write(*ptr_f, iT); +} + +template +void SuperVTMwriter3D::createMasterFile() +{ + int rank = 0; +#ifdef PARALLEL_MODE_MPI + rank = singleton::mpi().getRank(); +#endif + if ( rank == 0 ) { + const std::string fullNamePVDmaster = singleton::directories().getVtkOutDir() + + createFileName( _name ) + ".pvd"; + preamblePVD(fullNamePVDmaster); + closePVD(fullNamePVDmaster); + _createFile = true; + } +} + +template +void SuperVTMwriter3D::addFunctor(SuperF3D& f) +{ + _pointerVec.push_back(&f); +} + +template +void SuperVTMwriter3D::clearAddedFunctors() +{ + _pointerVec.clear(); +} + +template +std::string SuperVTMwriter3D::getName() const +{ + return _name; +} + + + + +////////////////////private member functions/////////////////////////////////// +template +void SuperVTMwriter3D::preambleVTI (const std::string& fullName, + const Vector extent0, const Vector extent1, T origin[], T delta) +{ + double d_delta = delta; + double d_origin[3] = {origin[0], origin[1], origin[2]}; + + std::ofstream fout(fullName, std::ios::trunc); + if (!fout) { + clout << "Error: could not open " << fullName << std::endl; + } + fout << "\n"; + fout << "\n"; + } else { + fout << "byte_order=\"LittleEndian\">\n"; + } + fout << "\n"; + fout << "\n"; + fout << "\n"; + fout.close(); +} + +template +void SuperVTMwriter3D::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 SuperVTMwriter3D::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 SuperVTMwriter3D::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 SuperVTMwriter3D::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 SuperVTMwriter3D::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 SuperVTMwriter3D::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 SuperVTMwriter3D::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 SuperVTMwriter3D::dataArray(const std::string& fullName, + SuperF3D& f, int iC, const Vector extent1) +{ + std::ofstream fout( fullName, std::ios::out | std::ios::app ); + if (!fout) { + clout << "Error: could not open " << fullName << std::endl; + } + + fout << "\n"; + } else { + fout << ">\n"; + } + + int i[4] = {iC, 0, 0, 0}; + W evaluated[f.getTargetDim()]; + for (int iDim = 0; iDim < f.getTargetDim(); ++iDim) { + evaluated[iDim] = W(); + } + + size_t numberOfFloats = f.getTargetDim() * (extent1[0]+2) * (extent1[1]+2) * (extent1[2]+2); + uint32_t binarySize = static_cast( numberOfFloats*sizeof(float) ); + + std::unique_ptr streamFloat(new float[numberOfFloats]); // stack may be too small + int itter = 0; + // fill buffer with functor data + for (i[3] = -1; i[3] < extent1[2]+1; ++i[3]) { + for (i[2] = -1; i[2] < extent1[1]+1; ++i[2]) { + for (i[1] = -1; i[1] < extent1[0]+1; ++i[1]) { + f(evaluated,i); + for (int iDim = 0; iDim < f.getTargetDim(); ++iDim) { + streamFloat[itter] = float( evaluated[iDim] ); + ++itter; + } + } + } + } + + if (_compress) { + // char buffer for functor data + const unsigned char* charData = reinterpret_cast(streamFloat.get()); + // buffer for compression + std::unique_ptr comprData(new unsigned char[ binarySize ]); // stack may be too small + + // compress data (not yet decoded as base64) by zlib + uLongf sizeCompr = compressBound(binarySize); + compress2( comprData.get(), &sizeCompr, charData, binarySize, -1); + + // encode prefix to base64 documented in http://www.earthmodels.org/software/vtk-and-paraview/vtk-file-formats + Base64Encoder prefixEncoder(fout, 4); + uint32_t prefix[4] = {1,binarySize,binarySize,static_cast(sizeCompr)}; + prefixEncoder.encode(prefix, 4); + + // encode compressed data to base64 + Base64Encoder dataEncoder( fout, sizeCompr ); + dataEncoder.encode(comprData.get(), sizeCompr); + } else if(_binary) { + // encode prefix to base64 documented in http://www.earthmodels.org/software/vtk-and-paraview/vtk-file-formats + Base64Encoder prefixEncoder(fout, 1); + prefixEncoder.encode(&binarySize, 1); + // write numbers from functor + Base64Encoder dataEncoder(fout, numberOfFloats); + dataEncoder.encode(streamFloat.get(),numberOfFloats); + } else { + for( size_t iOut = 0; iOut < numberOfFloats; ++iOut ) { + fout << streamFloat[iOut] << " "; + } + } + fout.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(); +} + +template +void SuperVTMwriter3D::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 -- cgit v1.2.3