/* 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