CFD Online Logo CFD Online URL
www.cfd-online.com
[Sponsors]
Home > Forums > General Forums > Main CFD Forum

Paraview .vtr files in binary

Register Blogs Community New Posts Updated Threads Search

Reply
 
LinkBack Thread Tools Search this Thread Display Modes
Old   April 3, 2024, 11:10
Post Paraview .vtr files in binary
  #1
New Member
 
djr4cfd
Join Date: Jan 2018
Posts: 13
Rep Power: 8
djr4cfd is on a distinguished road
Dear all,
I am trying to write my output files in vtr format and the following gives me a correct output file in ASCII.

Code:
#include <iostream>
#include <fstream>
#include <cmath>

// Function to calculate phi = sin(x) * cos(y)
double phi(double x, double y) {
    return sin(x) * cos(y);
}

int main() {
    int n = 10; // Size of the mesh (10x10)
    double step = 1.0 / (n - 1); // Step size
    
    std::ofstream outfile("output.vtr");
    
    // Writing the header
    outfile << "<?xml version=\"1.0\"?>\n";
    outfile << "<VTKFile type=\"RectilinearGrid\" version=\"0.1\" byte_order=\"LittleEndian\">\n";
    outfile << "<RectilinearGrid WholeExtent=\"0 " << n-1 << " 0 " << n-1 << " 0 0\">\n";
    outfile << "<Piece Extent=\"0 " << n-1 << " 0 " << n-1 << " 0 0\">\n";
    // Writing the scalar data (phi)
    outfile << "<PointData>\n";
    outfile << "<DataArray type=\"Float64\" Name=\"phi\" NumberOfComponents=\"1\" format=\"ascii\">\n";
    for (int j = 0; j < n; ++j) {
        for (int i = 0; i < n; ++i) {
            double x = i * step;
            double y = j * step;
            outfile << phi(x, y) << " ";
        }
    }
    outfile << "\n</DataArray>\n";
    outfile << "</PointData>\n";
    // Writing the coordinates
    outfile << "<Coordinates>\n";
    outfile << "<DataArray type=\"Float64\" Name=\"X_COORDINATES\" NumberOfComponents=\"1\" format=\"ascii\">\n";
    for (int i = 0; i < n; ++i) {
        outfile << i * step << " ";
    }
    outfile << "\n</DataArray>\n";
    outfile << "<DataArray type=\"Float64\" Name=\"Y_COORDINATES\" NumberOfComponents=\"1\" format=\"ascii\">\n";
    for (int j = 0; j < n; ++j) {
        outfile << j * step << " ";
    }
    outfile << "\n</DataArray>\n";  
    outfile << "<DataArray type=\"Float64\" Name=\"Z_COORDINATES\" NumberOfComponents=\"1\" format=\"ascii\">\n";
    outfile << "0.0 \n";
    outfile << "</DataArray>\n";
    outfile << "</Coordinates>\n";
    
    // Closing tags
    outfile << "</Piece>\n";
    outfile << "</RectilinearGrid>\n";
    outfile << "</VTKFile>\n";
    
    outfile.close();
    
    std::cout << "Output file generated: output.vtr\n";
    
    return 0;
}

To get output file in BINARY, I tried the following:
Code:
#include <iostream>
#include <fstream>
#include <cmath>

// Function to calculate phi = sin(x) * cos(y)
double phi(double x, double y) {
    return sin(x) * cos(y);
}

int main() {
    int n = 10; // Size of the mesh (10x10)
    double step = 1.0 / (n - 1); // Step size
    
    std::ofstream outfile("output.vtr");
    
    double A[n][n];
    double xx[n];
    double yy[n];
    
    for (int j = 0; j < n; ++j) {
        for (int i = 0; i < n; ++i) {
            double x = i * step;
            double y = j * step;
            //outfile << phi(x, y) << " ";
            A[i][j]= phi(x, y);
        }
    }
    
    for (int i = 0; i < n; ++i) {
        xx[i] =i * step;
    }
    
    for (int j = 0; j < n; ++j) {
        yy[j] =j * step;
    }
    
    // Writing the header
    outfile << "<?xml version=\"1.0\"?>\n";
    outfile << "<VTKFile type=\"RectilinearGrid\" version=\"0.1\" byte_order=\"LittleEndian\">\n";
    outfile << "<RectilinearGrid WholeExtent=\"0 " << n-1 << " 0 " << n-1 << " 0 0\">\n";
    outfile << "<Piece Extent=\"0 " << n-1 << " 0 " << n-1 << " 0 0\">\n";
    // Writing the scalar data (phi)
    outfile << "<PointData>\n";
    outfile << "<DataArray type=\"Int64\" Name=\"phi\" NumberOfComponents=\"1\" format=\"binary\">\n";
    for (int j = 0; j < n; ++j) {
        for (int i = 0; i < n; ++i) {
            outfile.write(reinterpret_cast<const char*>(&A[i][j]), sizeof(double));
        }
    }
    outfile << "\n</DataArray>\n";
    outfile << "</PointData>\n";
    // Writing the coordinates
    outfile << "<Coordinates>\n";
    outfile << "<DataArray type=\"Int64\" Name=\"X_COORDINATES\" NumberOfComponents=\"1\" format=\"binary\">\n";
    for (int i = 0; i < n; ++i) {
        outfile.write(reinterpret_cast<const char*>(&xx[i]), sizeof(double));
    }
    outfile << "\n</DataArray>\n";
    outfile << "<DataArray type=\"Int64\" Name=\"Y_COORDINATES\" NumberOfComponents=\"1\" format=\"binary\">\n";
    for (int j = 0; j < n; ++j) {
        outfile.write(reinterpret_cast<const char*>(&yy[j]), sizeof(double));
    }
    outfile << "\n</DataArray>\n";  
    outfile << "<DataArray type=\"Int64\" Name=\"Z_COORDINATES\" NumberOfComponents=\"1\" format=\"binary\">\n";
    double z =0.0;
    outfile.write(reinterpret_cast<const char*>(&z), sizeof(double));
    //outfile << "0.0 \n";
    outfile << "\n</DataArray>\n";
    outfile << "</Coordinates>\n";
    
    // Closing tags
    outfile << "</Piece>\n";
    outfile << "</RectilinearGrid>\n";
    outfile << "</VTKFile>\n";
    
    outfile.close();
    
    std::cout << "Output file generated: output.vtr\n";
    
    return 0;
}
The generated output is not correctly read by Paraview. It gives me the following error.

ERROR: In /builds/gitlab-kitware-sciviz-ci/build/superbuild/paraview/src/VTK/IO/XMLParser/vtkXMLParser.cxx, line 379
vtkXMLDataParser (0x1659c570): Error parsing XML in stream at line 7, column 0, byte index 255: not well-formed (invalid token)

ERROR: In /builds/gitlab-kitware-sciviz-ci/build/superbuild/paraview/src/VTK/IO/XML/vtkXMLReader.cxx, line 521
vtkXMLRectilinearGridReader (0x17dda5a0): Error parsing input file. ReadXMLInformation aborting.

I am using a Ubuntu system; byte_order is LittleEndian and using g++ compiler. Paraview version is 5.10.1.

Can anyone help me fix this. A similar example for writing binary vtr files using c++ will also help.
djr4cfd is offline   Reply With Quote

Old   April 7, 2024, 02:12
Default Successfully ported to legacy VTK. But xml vtk binary is still unaccomplished
  #2
New Member
 
djr4cfd
Join Date: Jan 2018
Posts: 13
Rep Power: 8
djr4cfd is on a distinguished road
Hi all,
I have successfully implemented the output file writing in binary using the legacy vtk format. For this, I had to use byte swap to BigEndian. The code is as follows.

Code:
#include <iostream>
#include <fstream>
#include <cmath>

template <typename T>
void SwapEnd(T& var)
{
  char* varArray = reinterpret_cast<char*>(&var);
  for(long i = 0; i < static_cast<long>(sizeof(var)/2); i++)
    std::swap(varArray[sizeof(var) - 1 - i],varArray[i]);
}

int main()
{
    int n = 10; // Size of the mesh (10x10)
    double step = 1.0 / (n - 1); // Step size

    double A[n][n];
    double xx[n];
    double yy[n];
    
    for (int j = 0; j < n; j++) {
        for (int i = 0; i < n; i++) {
            double x = i * step;
            double y = j * step;
            A[i][j]= sin(x) * cos(y);
        }
    }
    
    for (int i = 0; i < n; i++) {
        xx[i] =i * step;
    }
    
    for (int j = 0; j < n; j++) {
        yy[j] =j * step;
    }

  std::ofstream vtkstream;
  vtkstream.open("outputBinary.vtk", std::ios::out | std::ios::binary);
  if (vtkstream) {
    vtkstream<<"# vtk DataFile Version 2.0"<<"\n";
    vtkstream<<"Phi=sin(x)"<<"\n";
    vtkstream<<"BINARY"<<"\n";
    vtkstream<<"DATASET RECTILINEAR_GRID"<<std::endl;
    vtkstream<<"DIMENSIONS " << n << " " << n << " 1"<<std::endl;
    vtkstream<<"X_COORDINATES " << n << " double"<<std::endl;
    //for (int i = 0; i < n; i++) {
    for (unsigned int i = 0; i < n; i++) {
        SwapEnd(xx[i]);
        vtkstream.write((char*)&xx[i], sizeof(double));
        //vtkstream<< xx[i] << " ";
    }
    vtkstream<<"\nY_COORDINATES " << n << " double"<<std::endl;
    //for (int j = 0; j < n; j++) {
    for (unsigned int j = 0; j < n; j++) {
        SwapEnd(yy[j]);
        vtkstream.write((char*)&yy[j], sizeof(double));
        //vtkstream<< yy[j] << " ";
    }
    vtkstream<<"\nZ_COORDINATES " << 1 << " double"<<std::endl;
    double zz = 0.0;
    SwapEnd(zz);
    vtkstream.write((char*)&zz, sizeof(double));
    //vtkstream<< "0.0" << "\n";
    vtkstream<<"POINT_DATA " << n*n << std::endl;
    vtkstream<<"SCALARS " << "Phi " << " double 1" <<std::endl;
    vtkstream<<"LOOKUP_TABLE default" <<std::endl;
    for (int j = 0; j < n; j++) {
        for (int i = 0; i < n; i++) {
            SwapEnd(A[i][j]);
            vtkstream.write((char*)&A[i][j], sizeof(double));
        }
    }
    vtkstream.close();
  } 
  
  else {
    std::cout<<"ERROR"<<std::endl;
  }
  return 0;
}


I desperately want to convert this to XML VTK in binary. Specifically, I wish to understand the following.

1. format ="binary"
This involves base64 encoding. But I am not able to understand how to do this in c++ for an array of double.

2. format="appended"
< AppendedData encoding="raw">
_NNNNData
</AppendedData>

Here I am not understanding how to specify NNNN.

Experts, please help me with this.
djr4cfd is offline   Reply With Quote

Old   April 8, 2024, 02:50
Default Working code in c++ to generate xml vtk files in appended raw binary
  #3
New Member
 
djr4cfd
Join Date: Jan 2018
Posts: 13
Rep Power: 8
djr4cfd is on a distinguished road
After lots and lots of effort, I found out how to write in binary.

Some reverse engineering helped me. We can load ascii files in paraview and use file>save data to generate binary files.

I am sharing the code below.

Code:
#include <iostream>
#include <fstream>
#include <cmath>

int main() {
    int n = 10; // Size of the mesh (10x10)
    double step = 1.0 / (n - 1); // Step size
    
    double A[n][n];
    double xx[n];
    double yy[n];
    
    for (int i = 0; i < n; i++) {
        xx[i] =i * step;
    }
    
    for (int j = 0; j < n; j++) {
        yy[j] =j * step;
    }
    
    double zz =0.0;

    for (int j = 0; j < n; j++) {
        for (int i = 0; i < n; i++) {
            A[i][j]= sin(xx[i]) * cos(yy[j]);
        }
    }

    // Size of each array
    int N1 = n*n*sizeof(double); // size of A in bytes
    int N2 = n*sizeof(double);   // size of xx in bytes
    int N3 = n*sizeof(double);   // size of yy in bytes
    int N4 = 1*sizeof(double);   // size of zz in bytes

    // Offsets
    int offset1 = 0;
    int offset2 = offset1 + sizeof(double) + N1;
    int offset3 = offset2 + sizeof(double) + N2;
    int offset4 = offset3 + sizeof(double) + N3;
    
    std::ofstream outfile("output_binaryAppended.vtr", std::ios::out | std::ios::binary);
     
    if (outfile) {
        // Writing the header
        outfile << "<?xml version=\"1.0\"?>\n";
        outfile << "<VTKFile type=\"RectilinearGrid\" version=\"1.0\" header_type=\"UInt64\" byte_order=\"LittleEndian\">\n";
        outfile << "<RectilinearGrid WholeExtent=\"0 " << n-1 << " 0 " << n-1 << " 0 0\">\n";
        outfile << "<Piece Extent=\"0 " << n-1 << " 0 " << n-1 << " 0 0\">\n";
        // Writing the scalar data (phi)
        outfile << "<PointData>\n";
        outfile << "<DataArray type=\"Float64\" Name=\"phi\" format=\"appended\" offset=\"" << offset1 <<"\">\n";
        outfile << "</DataArray>\n";
        outfile << "</PointData>\n";
        // Writing the coordinates
        outfile << "<Coordinates>\n";
        outfile << "<DataArray type=\"Float64\" Name=\"X_COORDINATES\" format=\"appended\" offset=\"" << offset2 <<"\">\n";
        outfile << "</DataArray>\n";
        outfile << "<DataArray type=\"Float64\" Name=\"Y_COORDINATES\" format=\"appended\" offset=\"" << offset3 <<"\">\n";
        outfile << "</DataArray>\n"; 
        outfile << "<DataArray type=\"Float64\" Name=\"Z_COORDINATES\" format=\"appended\" offset=\"" << offset4 <<"\">\n";
        outfile << "</DataArray>\n";
        outfile << "</Coordinates>\n";
        // Closing tags
        outfile << "</Piece>\n";
        outfile << "</RectilinearGrid>\n";
        // Appended Data
        outfile << "<AppendedData encoding=\"raw\">\n";
        outfile << "_";
        outfile.write((char*)&N1, sizeof(double));
        for (int j = 0; j < n; j++) {
            for (int i = 0; i < n; i++) {
                outfile.write((char*)&A[i][j], sizeof(double));
            }
        }
        outfile.write((char*)&N2, sizeof(double));
        for (int i = 0; i < n; i++) {
            outfile.write((char*)&xx[i], sizeof(double));
        }
        outfile.write((char*)&N3, sizeof(double));
        for (int j = 0; j < n; j++) {
            outfile.write((char*)&yy[j], sizeof(double));
        }
        outfile.write((char*)&N4, sizeof(double));
        outfile.write((char*)&zz, sizeof(double));
        
        outfile << "\n</AppendedData>\n";
        // Final closing tags
        outfile << "</VTKFile>\n";
        outfile.close();
    } 
  
    else {
        std::cout<<"ERROR"<<std::endl;
    }
    
    std::cout << "Output file generated: output_binaryAppended.vtr\n";

    return 0;
}
Hope this helps someone some day!!!
djr4cfd is offline   Reply With Quote

Reply

Tags
binary, littleendian, paraview, vtk file, xml vtk


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are On


Similar Threads
Thread Thread Starter Forum Replies Last Post
Converting vtk files in a single binary file raviramesh10 SU2 0 May 18, 2021 04:50
[General] Problem with reading in multiple grouped Ensight .case files into paraview scro1022 ParaView 0 November 27, 2020 08:00
Generating binary data files in fortran to read in paraview nadeem_malik Main CFD Forum 6 May 24, 2017 07:47
[OpenFOAM] ParaView 3.6.1 & 3.7.0: Can't view STL files johannes ParaView 2 December 3, 2009 14:07
Results saving in CFD hawk Main CFD Forum 16 July 21, 2005 20:51


All times are GMT -4. The time now is 10:38.