Commit 2cd3ef3d authored by Giacomo Mulas's avatar Giacomo Mulas
Browse files

Merge branch 'virtualize_output' into 'master'

Draft: move binary file output to virtual file passed via MPI to process 0, thread 0...

See merge request giacomo.mulas/np_tmcode!35
parents 60678631 1c2d1352
Loading
Loading
Loading
Loading
+637 −352

File changed.

Preview size limit exceeded, changes collapsed.

+249 −0
Original line number Diff line number Diff line
@@ -5,6 +5,10 @@
#ifndef INCLUDE_FILE_IO_H_
#define INCLUDE_FILE_IO_H_

#include <vector>

class mixMPI;

/*! \class FileSchema
 *
 * \brief File content descriptor.
@@ -156,4 +160,249 @@ class HDFFile {
	       hid_t dapl_id=H5P_DEFAULT, hid_t dxpl_id=H5P_DEFAULT
  );
};

/*! \class VirtualAsciiFile
 *
 * \brief Virtual representation of an ASCII file.
 */
class VirtualAsciiFile {
protected:
  //! \brief The number of lines.
  // int32_t _num_lines;
  //! \brief A vector of strings representing the file lines.
  std::vector<std::string> *_file_lines;

public:
  // const int32_t &num_lines = _num_lines;
  /*! \brief VirtualAsciiFile instance constructor.
   *
   * \param lines: `int32_t` Number of lines, if known in advance (optional, default is 0).
   */
  VirtualAsciiFile(int32_t lines = 0);

  /*! \brief VirtualAsciiFile copy constructor.
   *
   * \param rhs: `const VirtualAsciiFile&` Reference to a VirtualAsciiFile instance.
   */
  VirtualAsciiFile(const VirtualAsciiFile& rhs);

  /*! \brief VirtualAsciiFile instance constructor copying all contents off MPISend() calls from MPI process rr.
   *
   * \param mpidata: `mixMPI *` pointer to MPI data structure.
   * \param rr: `int` rank of the MPI process sending the data.
   */
  VirtualAsciiFile(const mixMPI *mpidata, int rr);

  /*! \brief VirtualAsciiFile instance destroyer.
   */
  ~VirtualAsciiFile();

  /*! \brief Append another VirtualAsciiFile at the end of the current instance.
   *
   * \param rhs: `const VirtualAsciiFile&` Reference to the VirtualAsciiFile to be appended.
   */
  void append(VirtualAsciiFile& rhs);

  /*! \brief Append a line at the end of the file.
   *
   * \param line: `const string&` Reference to a string representing the line.
   */
  void append_line(const std::string& line);

  /*! \brief Append the contents of the VirtualAsciiFile to a physical file on disk.
   *
   * \param file_name: `const string&` Name of the file to append contents to.
   * \return result: `int` A result code (0 if successful).
   */
  int append_to_disk(const std::string& file_name);

  /*! \brief Insert another VirtualAsciiFile at a given position.
   *
   * This function inserts a target VirtualAsciiFile in the current one at the given
   * position. Optionally, a range of lines to be inserted can be specified, otherwise
   * the full content of the target file is inserted. This function DOES NOT increase
   * the size of the inner storage and it can only be used if the inner storage has
   * already been adjusted to contain the insertion target.
   *
   * \param position: `int32_t` The position at which the other file is inserted in this one.
   * \param rhs: `const VirtualAsciiFile&` The refence to the VirtualAsciiFile to be inserted.
   * \param start: `int32_t` The first line to be inserted (optional, default is 0).
   * \param end: `int32_t` The last line to be inserted (optional, default is 0 to read all).
   * \param line: `const string&` Reference to a string representing the line.
   * \return result: `int` A result code (0 if successful).
   */
  int insert(int32_t position, VirtualAsciiFile& rhs, int32_t start = 0, int32_t end = 0);
  
  /*! \brief Get the number of lines in the current instance.
   *
   * \return size: `int32_t` The number of lines in the VirtualAsciiFile instance.
   */
  int32_t number_of_lines() { return _file_lines->size(); }
    
  /*! \brief Write virtual file contents to a real file on disk.
   *
   * \param file_name: `const string&` Name of the file to append contents to.
   * \return result: `int` A result code (0 if successful).
   */
  int write_to_disk(const std::string& file_name);

  /*! \brief Send VirtualAsciiFile instance to MPI process 0 via MPISend() calls.
   *
   * \param mpidata: `mixMPI *` pointer to MPI data structure.
   */
  void mpisend(const mixMPI *mpidata);
};


/*! \class VirtualBinaryLine
 *
 * \brief Virtual representation of a binary file line.
 */
class VirtualBinaryLine {
// protected:
//   //! \brief The pointer to the piece of data to be written, cast to char *
//   char *_data_pointer;
//   //! \brief the size of the data block.
//   size_t _data_size;

public:
  //! \brief The pointer to the piece of data to be written, cast to char *
  char *_data_pointer;
  //! \brief the size of the data block.
  size_t _data_size;
  //! \brief Read only view of `_data_pointer`.
  const char* data_pointer = _data_pointer;
  //! \brief Read only view of `_data_size`.
  const size_t & data_size = _data_size;

  /*! \brief VirtualBinaryLine instance constructor.
   *
   * \param mydata: `int, double, long, float, complex, or dcomplex`piece of data to put in the line.
   */
  VirtualBinaryLine(int mydata);
  VirtualBinaryLine(long mydata);
  VirtualBinaryLine(float mydata);
  VirtualBinaryLine(double mydata);
  // VirtualBinaryLine(complex mydata);
  VirtualBinaryLine(dcomplex mydata);

    /*! \brief VirtualBinaryLine copy constructor.
   *
   * \param rhs: `const VirtualBinaryLine&` Reference to a VirtualBinaryLine instance.
   */
  VirtualBinaryLine(const VirtualBinaryLine& rhs);

  /*! \brief VirtualBinaryLine instance constructor copying all contents off MPISend() calls from MPI process rr.
   *
   * \param mpidata: `mixMPI *` pointer to MPI data structure.
   * \param rr: `int` rank of the MPI process sending the data.
   */
  VirtualBinaryLine(const mixMPI *mpidata, int rr);

  /*! \brief VirtualBinaryLine instance destroyer.
   */
  ~VirtualBinaryLine();

  /*! \brief Send VirtualBinaryLine instance to MPI process 0 via MPISend() calls.
   *
   * \param mpidata: `mixMPI *` pointer to MPI data structure.
   */
  void mpisend(const mixMPI *mpidata);
};


/*! \class VirtualBinaryFile
 *
 * \brief Virtual representation of a binary file.
 */
class VirtualBinaryFile {
protected:
  //! \brief The number of lines.
  // int32_t _num_lines;
  // //! \brief A vector of strings representing the file lines.
  // std::vector<VirtualBinaryLine> *_file_lines;

public:
  //! \brief A vector of strings representing the file lines.
  std::vector<VirtualBinaryLine> *_file_lines;
  // const int32_t &num_lines = _num_lines;
  /*! \brief VirtualBinaryFile empty instance constructor.
   *
   */
  VirtualBinaryFile();

  /*! \brief VirtualBinaryFile copy constructor.
   *
   * \param rhs: `const VirtualBinaryFile&` Reference to a VirtualBinaryFile instance.
   */
  VirtualBinaryFile(const VirtualBinaryFile& rhs);

  /*! \brief VirtualBinaryFile instance constructor copying all contents off MPISend() calls from MPI process rr.
   *
   * \param mpidata: `mixMPI *` pointer to MPI data structure.
   * \param rr: `int` rank of the MPI process sending the data.
   */
  VirtualBinaryFile(const mixMPI *mpidata, int rr);

  /*! \brief VirtualBinaryFile instance destroyer.
   */
  ~VirtualBinaryFile();

  /*! \brief Append another VirtualBinaryFile at the end of the current instance.
   *
   * \param rhs: `const VirtualBinaryFile&` Reference to the VirtualBinaryFile to be appended.
   */
  void append(VirtualBinaryFile& rhs);

  /*! \brief Append a line at the end of the file.
   *
   * \param line: `const string&` Reference to a string representing the line.
   */
  void append_line(const VirtualBinaryLine& line);

  /*! \brief Append the contents of the VirtualBinaryFile to a physical file on disk.
   *
   * \param file_name: `const string&` Name of the file to append contents to.
   * \return result: `int` A result code (0 if successful).
   */
  int append_to_disk(const std::string& file_name);

  // /*! \brief Insert another VirtualBinaryFile at a given position.
  //  *
  //  * This function inserts a target VirtualBinaryFile in the current one at the given
  //  * position. Optionally, a range of lines to be inserted can be specified, otherwise
  //  * the full content of the target file is inserted. This function DOES NOT increase
  //  * the size of the inner storage and it can only be used if the inner storage has
  //  * already been adjusted to contain the insertion target.
  //  *
  //  * \param position: `int32_t` The position at which the other file is inserted in this one.
  //  * \param rhs: `const VirtualBinaryFile&` The refence to the VirtualBinaryFile to be inserted.
  //  * \param start: `int32_t` The first line to be inserted (optional, default is 0).
  //  * \param end: `int32_t` The last line to be inserted (optional, default is 0 to read all).
  //  * \param line: `const string&` Reference to a string representing the line.
  //  * \return result: `int` A result code (0 if successful).
  //  */
  // int insert(int32_t position, VirtualBinaryFile& rhs, int32_t start = 0, int32_t end = 0);
  
  /*! \brief Get the number of lines in the current instance.
   *
   * \return size: `int32_t` The number of lines in the VirtualBinaryFile instance.
   */
  int32_t number_of_lines() { return _file_lines->size(); }
    
  /*! \brief Write virtual file contents to a real file on disk.
   *
   * \param file_name: `const string&` Name of the file to append contents to.
   * \return result: `int` A result code (0 if successful).
   */
  int write_to_disk(const std::string& file_name);

  /*! \brief Send VirtualBinaryFile instance to MPI process 0 via MPISend() calls.
   *
   * \param mpidata: `mixMPI *` pointer to MPI data structure.
   */
  void mpisend(const mixMPI *mpidata);
};
#endif

+346 −0
Original line number Diff line number Diff line
@@ -3,7 +3,9 @@
 * \brief Implementation of file I/O operations.
 */
#include <exception>
#include <fstream>
#include <regex>
#include <cstring>
#include <string>
#include <hdf5.h>

@@ -15,12 +17,21 @@
#include "../include/List.h"
#endif

#ifndef INCLUDE_TYPES_H_
#include "../include/types.h"
#endif

#ifndef INCLUDE_FILE_IO_H_
#include "../include/file_io.h"
#endif

#ifdef USE_MPI
#include <mpi.h>
#endif

using namespace std;

/* >>> FileSchema class implementation <<< */
FileSchema::FileSchema(int num_rec, const std::string *rec_types, const std::string *rec_names) {
  num_records = num_rec;
  record_types = new string[num_rec];
@@ -48,7 +59,9 @@ string* FileSchema::get_record_types() {
  for (int i = 0; i < num_records; i++) rec_types[i] = record_types[i];
  return rec_types;
}
/* >>> End of FileSchema class implementation <<< */

/* >>> HDFFile class implementation <<< */
HDFFile::HDFFile(const std::string& name, unsigned int flags, hid_t fcpl_id, hid_t fapl_id) {
  file_name = name;
  if (flags == H5F_ACC_EXCL || flags == H5F_ACC_TRUNC)
@@ -222,3 +235,336 @@ herr_t HDFFile::write(
  }
  return status;
}
/* >>> End of HDFFile class implementation <<< */

/* >>> VirtualAsciiFile class implementation <<< */
VirtualAsciiFile::VirtualAsciiFile(int32_t lines) {
  _file_lines = new vector<string>();
  for (int32_t li = 0; li < lines; li++) {
    _file_lines->push_back("");
  }
}

VirtualAsciiFile::VirtualAsciiFile(const VirtualAsciiFile& rhs) {
  // _num_lines = rhs._num_lines;
  _file_lines = new vector<string>();
  for (vector<string>::iterator it = rhs._file_lines->begin(); it != rhs._file_lines->end(); ++it) {
    _file_lines->push_back(*it);
  }
}

#ifdef MPI_VERSION
VirtualAsciiFile::VirtualAsciiFile(const mixMPI *mpidata, int rr) {
  // receive _num_lines from MPI process rr
  int32_t num_lines;
  MPI_Recv(&num_lines, 1, MPI_INT32_T, rr, 10, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
  int32_t mysize;
  _file_lines = new vector<string>();
  // loop over data to receive
  for (int32_t zi=0; zi<num_lines; zi++) {
    // receive the size of the string to receive
    MPI_Recv(&mysize, 1, MPI_INT32_T, rr, 10, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
    // allocate the buffer accordingly
    char buffer[mysize+1];
    // receive the char buffer
    MPI_Recv(buffer, mysize+1, MPI_CHAR, rr, 10, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
    // append to the vector
    _file_lines->push_back(buffer);
  }
}
#endif

VirtualAsciiFile::~VirtualAsciiFile() {
  // is it necessary to pop them out one by one? isn't there the dedicated method of std::vector to clean the vector?
  // besides, shouldn't this be done anyway by the destructor of std:vector?
  while (!_file_lines->size() > 0) {
    _file_lines->pop_back();
  }
  if (_file_lines != NULL) delete _file_lines;
}

void VirtualAsciiFile::append(VirtualAsciiFile& rhs) {
  // concatenate the virtualasciifile pointed by rhs to the current one
  // can't we use the dedicated method insert of std::vector to do the appending, instead of an explicit loop?
  for (vector<string>::iterator it = rhs._file_lines->begin(); it != rhs._file_lines->end(); ++it) {
    _file_lines->push_back(*it);
  }
}

void VirtualAsciiFile::append_line(const string& line) {
  // would it be worth reimplementing a sprintf-like method, so that we can give it all the arguments we would give to sprintf and get rid of the intermediate buffer completely?
  // append a line of output to the virtualasciifile
  _file_lines->push_back(line);
}

int VirtualAsciiFile::append_to_disk(const std::string& file_name) {
  // dump to disk the contents of the virtualasciifile, appending at the end of the given file_name
  int result = 0;
  fstream output_file;
  output_file.open(file_name, ios::app);
  if (output_file.is_open()) {
    for (vector<string>::iterator it = _file_lines->begin(); it != _file_lines->end(); ++it) {
      output_file << *it;
    }
    output_file.close();
  } else {
    result = 1;
  }
  return result;
}

int VirtualAsciiFile::insert(int32_t position, VirtualAsciiFile& rhs, int32_t start, int32_t end) {
  int result = 0;
  if (start == 0 && end == 0) {
    end = rhs.number_of_lines();
  }
  int32_t final_index = position + end - start;
  if (final_index <= number_of_lines()) {
    for (int32_t li = start; li < end; li++) {
      // since here we are replacing the previous placeholder empty strings, make sure they are properly released when they are replaced (i.e. try it with a simple hello world example and pass it through valgrind)
      _file_lines->at(position++) = rhs._file_lines->at(li);
    }
  } else {
    // ERROR: target file is too long;
    result = 1;
  }
  return result;
}

int VirtualAsciiFile::write_to_disk(const std::string& file_name) {
  // dump to disk the contents of the virtualasciifile, replacing the given file_name
  int result = 0;
  fstream output_file;
  output_file.open(file_name, ios::out);
  if (output_file.is_open()) {
    for (vector<string>::iterator it = _file_lines->begin(); it != _file_lines->end(); ++it) {
      output_file << *it;
    }
    output_file.close();
  } else {
    result = 1;
  }
  return result;
}

#ifdef MPI_VERSION
void VirtualAsciiFile::mpisend(const mixMPI *mpidata) {
  // Send VirtualAsciiFile instance to MPI process 0 via MPISend() calls
  // first send the size
  int32_t num_lines =  _file_lines->size();
  MPI_Send(&num_lines, 1, MPI_INT32_T, 0, 10, MPI_COMM_WORLD);
  // now loop over data to send
  int32_t mysize;
  for (vector<string>::iterator it = _file_lines->begin(); it != _file_lines->end(); ++it) {
    // send the length of each string
    mysize = (int32_t) it->size();
    MPI_Send(&mysize, 1, MPI_INT32_T, 0, 10, MPI_COMM_WORLD);
    // send the string itself
    MPI_Send(it->c_str(), mysize+1, MPI_CHAR, 0, 10, MPI_COMM_WORLD);
  }
}
#endif

/* >>> End of VirtualAsciiFile class implementation <<< */

// /* >>> VirtualBinaryLine class implementation <<< */
VirtualBinaryLine::VirtualBinaryLine(int mydata) {
  _data_size = sizeof(mydata);
  int *buffer = (int *) malloc(_data_size);
  *buffer = mydata;
  _data_pointer = reinterpret_cast<char *>(buffer);
}

VirtualBinaryLine::VirtualBinaryLine(double mydata) {
  _data_size = sizeof(mydata);
  double *buffer = (double *) malloc(_data_size);
  *buffer = mydata;
  _data_pointer = reinterpret_cast<char *>(buffer);
}

VirtualBinaryLine::VirtualBinaryLine(float mydata) {
  _data_size = sizeof(mydata);
  float *buffer = (float *) malloc(_data_size);
  *buffer = mydata;
  _data_pointer = reinterpret_cast<char *>(buffer);
}

VirtualBinaryLine::VirtualBinaryLine(long mydata) {
  _data_size = sizeof(mydata);
  long *buffer = (long *) malloc(_data_size);
  *buffer = mydata;
  _data_pointer = reinterpret_cast<char *>(buffer);
}

VirtualBinaryLine::VirtualBinaryLine(dcomplex mydata) {
  _data_size = sizeof(mydata);
  dcomplex *buffer = (dcomplex *) malloc(_data_size);
  *buffer = mydata;
  _data_pointer = reinterpret_cast<char *>(buffer);
}

// VirtualBinaryLine::VirtualBinaryLine(complex mydata) {
//   _data_size = sizeof(mydata);
//   complex *buffer = (complex *) malloc(_data_size);
//   *buffer = mydata;
//   _data_pointer = reinterpret_cast<char *>(buffer);
// }

VirtualBinaryLine::VirtualBinaryLine(const VirtualBinaryLine& rhs) {
  _data_size = rhs._data_size;
  _data_pointer = reinterpret_cast<char *>(malloc(rhs._data_size));
  memcpy(_data_pointer, rhs._data_pointer, _data_size);
}

#ifdef MPI_VERSION
VirtualBinaryLine::VirtualBinaryLine(const mixMPI *mpidata, int rr) {
  // receive mysize from MPI process rr
  int32_t mysize;
  MPI_Recv(&mysize, 1, MPI_INT32_T, rr, 10, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
  _data_size = mysize;
  // allocate the buffer accordingly
  _data_pointer = reinterpret_cast<char *>(malloc(mysize));
  // receive the char buffer
  MPI_Recv(_data_pointer, mysize, MPI_CHAR, rr, 10, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
}

#endif

VirtualBinaryLine::~VirtualBinaryLine() {
  if (_data_pointer != NULL) {
    free(_data_pointer);
    _data_pointer = NULL;
  }
}

#ifdef MPI_VERSION
void VirtualBinaryLine::mpisend(const mixMPI *mpidata) {
  // Send VirtualBinaryLine instance to MPI process 0 via MPISend() calls
  // first send the size
  int32_t mysize =  _data_size;
  MPI_Send(&mysize, 1, MPI_INT32_T, 0, 10, MPI_COMM_WORLD);
  // now send the data
  MPI_Send(_data_pointer, mysize, MPI_CHAR, 0, 10, MPI_COMM_WORLD);
}
#endif
/* >>> End of VirtualBinaryLine class implementation <<< */


/* >>> VirtualBinaryFile class implementation <<< */
VirtualBinaryFile::VirtualBinaryFile() {
  _file_lines = new vector<VirtualBinaryLine>();
}

VirtualBinaryFile::VirtualBinaryFile(const VirtualBinaryFile& rhs) {
  // _num_lines = rhs._num_lines;
  _file_lines = new vector<VirtualBinaryLine>();
  for (vector<VirtualBinaryLine>::iterator it = rhs._file_lines->begin(); it != rhs._file_lines->end(); ++it) {
    _file_lines->push_back(VirtualBinaryLine(*it));
  }
}

#ifdef MPI_VERSION
VirtualBinaryFile::VirtualBinaryFile(const mixMPI *mpidata, int rr) {
  // receive _num_lines from MPI process rr
  int32_t num_lines;
  MPI_Recv(&num_lines, 1, MPI_INT32_T, rr, 10, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
  _file_lines = new vector<VirtualBinaryLine>();
  // loop over data to receive
  for (int32_t zi=0; zi<num_lines; zi++) {
    // receive the line of data
    _file_lines->push_back(VirtualBinaryLine(mpidata, rr));
  }
}
#endif

VirtualBinaryFile::~VirtualBinaryFile() {
  // is it necessary to pop them out one by one? isn't there the dedicated method of std::vector to clean the vector?
  // besides, shouldn't this be done anyway by the destructor of std:vector?
  // for (vector<VirtualBinaryLine>::iterator it = _file_lines->begin(); it != _file_lines->end(); ++it) {
  //   delete it;
  // }
  while (!_file_lines->size() > 0) {
    _file_lines->pop_back();
  }
  if (_file_lines != NULL) delete _file_lines;
}

void VirtualBinaryFile::append(VirtualBinaryFile& rhs) {
  // concatenate the virtualasciifile pointed by rhs to the current one
  // can't we use the dedicated method insert of std::vector to do the appending, instead of an explicit loop?
  for (vector<VirtualBinaryLine>::iterator it = rhs._file_lines->begin(); it != rhs._file_lines->end(); ++it) {
    _file_lines->push_back(VirtualBinaryLine(*it));
  }
}

void VirtualBinaryFile::append_line(const VirtualBinaryLine& line) {
  // would it be worth reimplementing a sprintf-like method, so that we can give it all the arguments we would give to sprintf and get rid of the intermediate buffer completely?
  // append a line of output to the virtualasciifile
  _file_lines->push_back(VirtualBinaryLine(line));
}

int VirtualBinaryFile::append_to_disk(const std::string& file_name) {
  // dump to disk the contents of the virtualasciifile, appending at the end of the given file_name
  int result = 0;
  fstream output_file;
  output_file.open(file_name, ios::app | ios::binary);
  if (output_file.is_open()) {
    for (vector<VirtualBinaryLine>::iterator it = _file_lines->begin(); it != _file_lines->end(); ++it) {
      output_file.write(it->_data_pointer, it->_data_size);
    }
    output_file.close();
  } else {
    result = 1;
  }
  return result;
}

// int VirtualBinaryFile::insert(int32_t position, VirtualBinaryFile& rhs, int32_t start, int32_t end) {
//   int result = 0;
//   if (start == 0 && end == 0) {
//     end = rhs.number_of_lines();
//   }
//   int32_t final_index = position + end - start;
//   if (final_index <= number_of_lines()) {
//     for (int32_t li = start; li < end; li++) {
//       // since here we are replacing the previous placeholder empty strings, make sure they are properly released when they are replaced (i.e. try it with a simple hello world example and pass it through valgrind)
//       VirtualBinaryLine templine = VirtualBinaryLine(rhs._file_lines->at(li));
//       _file_lines->at(position++) = templine;
//     }
//   } else {
//     // ERROR: target file is too long;
//     result = 1;
//   }
//   return result;
// }

int VirtualBinaryFile::write_to_disk(const std::string& file_name) {
  // dump to disk the contents of the virtualasciifile, replacing the given file_name
  int result = 0;
  fstream output_file;
  output_file.open(file_name, ios::out | ios::binary);
  if (output_file.is_open()) {
    for (vector<VirtualBinaryLine>::iterator it = _file_lines->begin(); it != _file_lines->end(); ++it) {
      output_file.write(it->_data_pointer, it->_data_size);
    }
    output_file.close();
  } else {
    result = 1;
  }
  return result;
}

#ifdef MPI_VERSION
void VirtualBinaryFile::mpisend(const mixMPI *mpidata) {
  // Send VirtualBinaryFile instance to MPI process 0 via MPISend() calls
  // first send the size
  int32_t num_lines =  _file_lines->size();
  MPI_Send(&num_lines, 1, MPI_INT32_T, 0, 10, MPI_COMM_WORLD);
  // now loop over data to send
  for (vector<VirtualBinaryLine>::iterator it = _file_lines->begin(); it != _file_lines->end(); ++it) {
    it->mpisend(mpidata);
  }
}
#endif

/* >>> End of VirtualBinaryFile class implementation <<< */
+1 −1
Original line number Diff line number Diff line
@@ -124,7 +124,7 @@ endif

# CXXFLAGS defines the default compilation options for the C++ compiler
ifndef CXXFLAGS
  override CXXFLAGS=-O3 -ggdb -pg -coverage -I$(HDF5_INCLUDE) $(MPI_CXXFLAGS) $(NVTX_CXXFLAGS)
  override CXXFLAGS=-O3 -ggdb -pg -coverage -Wno-format-contains-nul -I$(HDF5_INCLUDE) $(MPI_CXXFLAGS) $(NVTX_CXXFLAGS)
  ifdef USE_OPENMP
    override CXXFLAGS+= -fopenmp
# closes USE_OPENMP
+6 −2
Original line number Diff line number Diff line
@@ -115,6 +115,8 @@ def compare_files(config):
        print("INFO: using line-wise mode")
        print("INFO: counting result lines...")
        while (f_lines[0] != ''):
            if (c_lines[0].startswith("INSERTION:")):
                c_lines = [c_file.readline()]
            if (c_lines[0] != ''):
                line_count += 1
            else:
@@ -166,6 +168,8 @@ def compare_files(config):
        else:
            f_lines = [fortran_file.readline()]
            c_lines = [c_file.readline()]
            if (c_lines[0].startswith("INSERTION:")):
                c_lines = [c_file.readline()]
            num_read_lines += 1
        # Start here the comparison loop
        if (len(f_lines) == len(c_lines)):
@@ -429,7 +433,7 @@ def parse_arguments():
        'fortran_file_name': '',
        'c_file_name': '',
        'full_log': False,
        'linewise': False,
        'linewise': True,
        'log_html': False,
        'html_output': 'pycompare.html',
        'warning_threshold': 0.005,
@@ -475,7 +479,7 @@ def print_help():
    print("--full                    Print all lines to log file (default prints only mismatches).")
    print("--help                    Print this help and exit.")
    print("--html[=OPT_OUTPUT_NAME]  Enable logging to HTML file (default logs to \"pycompare.html\").")
    print("--linewise                Load only one line at a time. Useful to compare big files (false by default).")
    print("--linewise                Load only one line at a time. Useful to compare big files (True by default).")
    print("--quick                   Stop on first mismatch (default is to perform a full check).")
    print("--warn                    Set a fractional threshold for numeric warning (default = 0.005).")
    print("                                            ")