diff --git a/src/output/vtk.cpp b/src/output/vtk.cpp index 559f00c8..13b47d30 100644 --- a/src/output/vtk.cpp +++ b/src/output/vtk.cpp @@ -124,21 +124,21 @@ Vtk::Vtk(Input &input, DataBlock *datain, std::string filebase) { for (int32_t i = 0; i < nx1 + ioffset; i++) { if(grid.np_tot[IDIR] == 1) // only one dimension in this direction - xnode[i] = BigEndian(static_cast(grid.x[IDIR](i))); + xnode[i] = bigEndian(static_cast(grid.x[IDIR](i))); else - xnode[i] = BigEndian(static_cast(grid.xl[IDIR](i + grid.nghost[IDIR]))); + xnode[i] = bigEndian(static_cast(grid.xl[IDIR](i + grid.nghost[IDIR]))); } for (int32_t j = 0; j < nx2 + joffset; j++) { if(grid.np_tot[JDIR] == 1) // only one dimension in this direction - ynode[j] = BigEndian(static_cast(grid.x[JDIR](j))); + ynode[j] = bigEndian(static_cast(grid.x[JDIR](j))); else - ynode[j] = BigEndian(static_cast(grid.xl[JDIR](j + grid.nghost[JDIR]))); + ynode[j] = bigEndian(static_cast(grid.xl[JDIR](j + grid.nghost[JDIR]))); } for (int32_t k = 0; k < nx3 + koffset; k++) { if(grid.np_tot[KDIR] == 1) - znode[k] = BigEndian(static_cast(grid.x[KDIR](k))); + znode[k] = bigEndian(static_cast(grid.x[KDIR](k))); else - znode[k] = BigEndian(static_cast(grid.xl[KDIR](k + grid.nghost[KDIR]))); + znode[k] = bigEndian(static_cast(grid.xl[KDIR](k + grid.nghost[KDIR]))); } #if VTK_FORMAT == VTK_STRUCTURED_GRID // VTK_FORMAT /* -- Allocate memory for node_coord which is later used -- */ @@ -191,35 +191,35 @@ Vtk::Vtk(Input &input, DataBlock *datain, std::string filebase) { for (int32_t k = 0; k < nodesubsize[0]; k++) { for (int32_t j = 0; j < nodesubsize[1]; j++) { for (int32_t i = 0; i < nodesubsize[2]; i++) { - // BigEndian allows us to get back to little endian when needed + // bigEndian allows us to get back to little endian when needed x1 = grid.xl[IDIR](i + data->gbeg[IDIR]); x2 = grid.xl[JDIR](j + data->gbeg[JDIR]); x3 = grid.xl[KDIR](k + data->gbeg[KDIR]); #if (GEOMETRY == CARTESIAN) || (GEOMETRY == CYLINDRICAL) - node_coord(k,j,i,0) = BigEndian(x1); - node_coord(k,j,i,1) = BigEndian(x2); - node_coord(k,j,i,2) = BigEndian(x3); + node_coord(k,j,i,0) = bigEndian(x1); + node_coord(k,j,i,1) = bigEndian(x2); + node_coord(k,j,i,2) = bigEndian(x3); #elif GEOMETRY == POLAR - node_coord(k,j,i,0) = BigEndian(x1 * cos(x2)); - node_coord(k,j,i,1) = BigEndian(x1 * sin(x2)); - node_coord(k,j,i,2) = BigEndian(x3); + node_coord(k,j,i,0) = bigEndian(x1 * std::cos(x2)); + node_coord(k,j,i,1) = bigEndian(x1 * std::sin(x2)); + node_coord(k,j,i,2) = bigEndian(x3); #elif GEOMETRY == SPHERICAL #if DIMENSIONS == 1 - node_coord(k,j,i,0) = BigEndian(x1); - node_coord(k,j,i,1) = BigEndian(0.0); - node_coord(k,j,i,2) = BigEndian(0.0); + node_coord(k,j,i,0) = bigEndian(x1); + node_coord(k,j,i,1) = bigEndian(0.0f); + node_coord(k,j,i,2) = bigEndian(0.0f); #elif DIMENSIONS == 2 - node_coord(k,j,i,0) = BigEndian(x1 * sin(x2)); - node_coord(k,j,i,1) = BigEndian(x1 * cos(x2)); - node_coord(k,j,i,2) = BigEndian(0.0); + node_coord(k,j,i,0) = bigEndian(x1 * std::sin(x2)); + node_coord(k,j,i,1) = bigEndian(x1 * std::cos(x2)); + node_coord(k,j,i,2) = bigEndian(0.0f); #elif DIMENSIONS == 3 - node_coord(k,j,i,0) = BigEndian(x1 * sin(x2) * cos(x3)); - node_coord(k,j,i,1) = BigEndian(x1 * sin(x2) * sin(x3)); - node_coord(k,j,i,2) = BigEndian(x1 * cos(x2)); + node_coord(k,j,i,0) = bigEndian(x1 * std::sin(x2) * std::cos(x3)); + node_coord(k,j,i,1) = bigEndian(x1 * std::sin(x2) * std::sin(x3)); + node_coord(k,j,i,2) = bigEndian(x1 * std::cos(x2)); #endif // DIMENSIONS #endif // GEOMETRY } @@ -301,7 +301,7 @@ int Vtk::Write() { for(int j = data->beg[JDIR]; j < data->end[JDIR] ; j++ ) { for(int i = data->beg[IDIR]; i < data->end[IDIR] ; i++ ) { vect3D[i-data->beg[IDIR] + (j-data->beg[JDIR])*nx1loc + (k-data->beg[KDIR])*nx1loc*nx2loc] - = BigEndian(static_cast(Vcin(k,j,i))); + = bigEndian(static_cast(Vcin(k,j,i))); } } } @@ -379,7 +379,7 @@ void Vtk::WriteHeader(IdfxFileHandler fvtk, real time) { ssheader.str(std::string()); // convert time to single precision big endian - int32_t geoBig = BigEndian(this->geometry); + int32_t geoBig = bigEndian(this->geometry); WriteHeaderBinary(&geoBig, 1, fvtk); // Done, add cariage return for next ascii write @@ -396,7 +396,7 @@ void Vtk::WriteHeader(IdfxFileHandler fvtk, real time) { int32_t perBig{-1}; for (int dir=0; dir<3; dir++) { - perBig = BigEndian(this->periodicity[dir]); + perBig = bigEndian(this->periodicity[dir]); WriteHeaderBinary(&perBig, 1, fvtk); } // Done, add cariage return for next ascii write @@ -410,7 +410,7 @@ void Vtk::WriteHeader(IdfxFileHandler fvtk, real time) { ssheader.str(std::string()); // convert time to single precision big endian - float timeBE = BigEndian(static_cast(time)); + float timeBE = bigEndian(static_cast(time)); WriteHeaderBinary(&timeBE, 1, fvtk); // Done, add cariage return for next ascii write diff --git a/src/output/vtk.hpp b/src/output/vtk.hpp index 4857f19d..c33e0d05 100644 --- a/src/output/vtk.hpp +++ b/src/output/vtk.hpp @@ -21,25 +21,18 @@ #include "idefix.hpp" #include "input.hpp" #include "dataBlock.hpp" +#include "bigEndian.hpp" #include "scalarField.hpp" + // Forward class declaration class Output; class DataBlock; class BaseVtk { - private: - // Endianness swaping function and variable - bool shouldSwapEndian {true}; - protected: BaseVtk() { - // Test endianness - int tmp1 = 1; - unsigned char *tmp2 = (unsigned char *) &tmp1; - if (*tmp2 == 0) - this->shouldSwapEndian = false; // Initialise the root tag (used for MPI non-collective I/Os) this->isRoot = idfx::prank == 0; } @@ -68,25 +61,9 @@ class BaseVtk { // DataBlock parent DataBlock *data; - /* ****************************************************************************/ - /** Determines if the machine is little-endian. If so, - it will force the data to be big-endian. - @param in_number floating point number to be converted in big endian */ - /* *************************************************************************** */ + // BigEndian conversion + BigEndian bigEndian; - template - T BigEndian(T in_number) { - if (shouldSwapEndian) { - unsigned char *bytes = (unsigned char*) &in_number; - unsigned char tmp = bytes[0]; - bytes[0] = bytes[3]; - bytes[3] = tmp; - tmp = bytes[1]; - bytes[1] = bytes[2]; - bytes[2] = tmp; - } - return(in_number); - } void WriteHeaderString(const char* header, IdfxFileHandler fvtk) { #ifdef WITH_MPI diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt index ff971569..b36f8a08 100644 --- a/src/utils/CMakeLists.txt +++ b/src/utils/CMakeLists.txt @@ -1,6 +1,7 @@ add_subdirectory(iterativesolver) target_sources(idefix + PUBLIC ${CMAKE_CURRENT_LIST_DIR}/bigEndian.hpp PUBLIC ${CMAKE_CURRENT_LIST_DIR}/dumpImage.cpp PUBLIC ${CMAKE_CURRENT_LIST_DIR}/dumpImage.hpp PUBLIC ${CMAKE_CURRENT_LIST_DIR}/lookupTable.hpp diff --git a/src/utils/bigEndian.hpp b/src/utils/bigEndian.hpp new file mode 100644 index 00000000..08bd73c0 --- /dev/null +++ b/src/utils/bigEndian.hpp @@ -0,0 +1,63 @@ +// *********************************************************************************** +// Idefix MHD astrophysical code +// Copyright(C) Geoffroy R. J. Lesur +// and other code contributors +// Licensed under CeCILL 2.1 License, see COPYING for more information +// *********************************************************************************** + +#ifndef UTILS_BIGENDIAN_HPP_ +#define UTILS_BIGENDIAN_HPP_ + +#include +#include +#include "idefix.hpp" + +/* ****************************************************************************/ +/** Determines if the machine is little-endian. If so, + it will force the data to be big-endian. +@param in_number floating point number to be converted in big endian */ +/* *************************************************************************** */ + +class BigEndian { + public: + BigEndian() { + // Test endianness + union { + uint32_t i; + char c[4]; + } bint = {0x01020304}; + + if(bint.c[0] == 1) + this->shouldSwapEndian = false; + else + this->shouldSwapEndian = true; + } + + // Swap when needed + template + T operator() (T in_number) { + static_assert(std::is_arithmetic_v == true); + T out_number; + if (this->shouldSwapEndian) { + constexpr int size = sizeof(T); + union { + T u; + unsigned char byte[size]; + } in, out; + in.u = in_number; + for(int n = 0 ; n < size ; n++) { + out.byte[size-n-1] = in.byte[n]; + } + out_number = out.u; + } else { + out_number = in_number; + } + return(out_number); + } + + private: + // Endianness swaping flag + bool shouldSwapEndian; +}; + +#endif // UTILS_BIGENDIAN_HPP_