diff options
Initialize at openlb-1-3
Diffstat (limited to 'src/io/superVtmWriter2D.hh')
| -rw-r--r-- | src/io/superVtmWriter2D.hh | 448 | 
1 files changed, 448 insertions, 0 deletions
diff --git a/src/io/superVtmWriter2D.hh b/src/io/superVtmWriter2D.hh new file mode 100644 index 0000000..da828a3 --- /dev/null +++ b/src/io/superVtmWriter2D.hh @@ -0,0 +1,448 @@ +/*  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 + *  <http://www.openlb.net/> + * + *  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 <fstream> +#include <iostream> +#include <iomanip> +#include <string> +#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<typename T, typename W> +SuperVTMwriter2D<T,W>::SuperVTMwriter2D( std::string name, bool binary ) +  : clout( std::cout,"SuperVTMwriter2D" ), _createFile(false), _name(name), _binary(binary) +{} + +template<typename T, typename W> +void SuperVTMwriter2D<T,W>::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<T> const& cGeometry = (**it_begin).getSuperStructure().getCuboidGeometry(); +    // no gaps between vti files (cuboids) +    (**it_begin).getSuperStructure().communicate(); +    LoadBalancer<T>& 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<typename T, typename W> +void SuperVTMwriter2D<T,W>::write(SuperF2D<T,W>& f, int iT) +{ +  CuboidGeometry2D<T> const& cGeometry = f.getSuperStructure().getCuboidGeometry(); +  LoadBalancer<T>& 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<typename T, typename W> +void SuperVTMwriter2D<T,W>::write(std::shared_ptr<SuperF2D<T,W>> ptr_f, int iT) +{ +  write(*ptr_f, iT); +} + +template<typename T, typename W> +void SuperVTMwriter2D<T,W>::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<typename T, typename W> +void SuperVTMwriter2D<T,W>::addFunctor(SuperF2D<T,W>& f) +{ +  _pointerVec.push_back(&f); +} + +template<typename T, typename W> +void SuperVTMwriter2D<T,W>::clearAddedFunctors() +{ +  _pointerVec.clear(); +} + +template<typename T, typename W> +std::string SuperVTMwriter2D<T,W>::getName() const +{ +  return _name; +} + + + + +////////////////////private member functions/////////////////////////////////// +template<typename T, typename W> +void SuperVTMwriter2D<T,W>::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 << "<?xml version=\"1.0\"?>\n"; +  fout << "<VTKFile type=\"ImageData\" version=\"0.1\" " +       << "byte_order=\"LittleEndian\">\n"; +  fout << "<ImageData WholeExtent=\"" +       << x0 <<" "<< x1 <<" " +       << y0 <<" "<< y1 <<" " +       << 0 <<" "<< 0 +       << "\" Origin=\"" << originX << " " << originY << " " << "0" +       << "\" Spacing=\"" << delta << " " << delta << " " << delta << "\">\n"; +  fout << "<Piece Extent=\"" +       << x0 <<" "<< x1 <<" " +       << y0 <<" "<< y1 <<" " +       << 0  <<" "<< 0 <<"\">\n"; +  fout << "<PointData>\n"; +  fout.close(); +} + +template<typename T, typename W> +void SuperVTMwriter2D<T,W>::closeVTI(const std::string& fullNamePiece) +{ +  std::ofstream fout(fullNamePiece, std::ios::app ); +  if (!fout) { +    clout << "Error: could not open " << fullNamePiece << std::endl; +  } +  fout << "</ImageData>\n"; +  fout << "</VTKFile>\n"; +  fout.close(); +} + +template<typename T, typename W> +void SuperVTMwriter2D<T,W>::preamblePVD(const std::string& fullNamePVD) +{ +  std::ofstream fout(fullNamePVD, std::ios::trunc); +  if (!fout) { +    clout << "Error: could not open " << fullNamePVD << std::endl; +  } +  fout << "<?xml version=\"1.0\"?>\n"; +  fout << "<VTKFile type=\"Collection\" version=\"0.1\" " +       << "byte_order=\"LittleEndian\">\n" +       << "<Collection>\n"; +  fout.close(); +} + +template<typename T, typename W> +void SuperVTMwriter2D<T,W>::closePVD(const std::string& fullNamePVD) +{ +  std::ofstream fout(fullNamePVD, std::ios::app ); +  if (!fout) { +    clout << "Error: could not open " << fullNamePVD << std::endl; +  } +  fout << "</Collection>\n"; +  fout << "</VTKFile>\n"; +  fout.close(); +} + +template<typename T, typename W> +void SuperVTMwriter2D<T,W>::preambleVTM(const std::string& fullNamePVD) +{ +  std::ofstream fout(fullNamePVD, std::ios::trunc); +  if (!fout) { +    clout << "Error: could not open " << fullNamePVD << std::endl; +  } +  fout << "<?xml version=\"1.0\"?>\n"; +  fout << "<VTKFile type=\"vtkMultiBlockDataSet\" version=\"1.0\" " +       << "byte_order=\"LittleEndian\">\n" +       << "<vtkMultiBlockDataSet>\n" ; +  fout.close(); +} + +template<typename T, typename W> +void SuperVTMwriter2D<T,W>::closeVTM(const std::string& fullNamePVD) +{ +  std::ofstream fout(fullNamePVD, std::ios::app ); +  if (!fout) { +    clout << "Error: could not open " << fullNamePVD << std::endl; +  } +  fout << "</vtkMultiBlockDataSet>\n"; +  fout << "</VTKFile>\n"; +  fout.close(); +} + +template<typename T, typename W> +void SuperVTMwriter2D<T,W>::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 << "<Block index=\"" << iC << "\" >\n"; +  fout << "<DataSet index= \"0\" " << "file=\"" << namePiece << "\">\n" +       << "</DataSet>\n"; +  fout << "</Block>\n"; +  fout.close(); +} + +template<typename T, typename W> +void SuperVTMwriter2D<T,W>::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 << "<DataSet timestep=\"" << iT << "\" " +         << "group=\"\" part=\"\" " +         << "file=\"" << namePiece << "\"/>\n"; +    fout.close(); +    closePVD(fullNamePVDMaster); +  } else { +    clout << "Error: could not open " << fullNamePVDMaster << std::endl; +  } +} + +template<typename T, typename W> +void SuperVTMwriter2D<T,W>::dataArray(const std::string& fullName, +                                      SuperF2D<T,W>& 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 << "<DataArray " ; +  fout << "type=\"Float32\" Name=\"" << f.getName() << "\" " +       << "NumberOfComponents=\"" << f.getTargetDim() <<"\">\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<int> 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 << "</DataArray>\n"; +  fout.close(); +} + +template<typename T, typename W> +void SuperVTMwriter2D<T,W>::dataArrayBinary(const std::string& fullName, +                                            SuperF2D<T,W>& 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 << "<DataArray "; +  fout << "type=\"Float32\" Name=\"" << f.getName() << "\" " +       << "format=\"binary\" encoding=\"base64\" " +       << "NumberOfComponents=\"" << f.getTargetDim() <<"\">\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<unsigned int> sizeEncoder(ofstr, 1); +  unsigned int uintBinarySize = (unsigned int)binarySize; +  sizeEncoder.encode(&uintBinarySize, 1); +  //  write numbers from functor +  Base64Encoder<float>* dataEncoder = new Base64Encoder<float>( 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<float[]> 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</DataArray>\n"; +  ffout.close(); +  delete dataEncoder; +} + +template<typename T, typename W> +void SuperVTMwriter2D<T,W>::closePiece(const std::string& fullNamePiece) +{ +  std::ofstream fout(fullNamePiece, std::ios::app ); +  if (!fout) { +    clout << "Error: could not open " << fullNamePiece << std::endl; +  } +  fout << "</PointData>\n"; +  fout << "</Piece>\n"; +  fout.close(); +} + + +}  // namespace olb + +#endif  | 
