Commit 50c5f296 authored by GILLES Sebastien's avatar GILLES Sebastien

#1422 Replace the boolean IsBinaryOutput by an enum class, and in some...

#1422 Replace the boolean IsBinaryOutput by an enum class, and in some functions or method provide the way to specify it by hand rather than using the global variable stored in the singleton. This possibility will be useful in the writing of new tests (and the API change is mostly transparent to end-user: it is an optional argument in the function).
parent ad600731
......@@ -430,10 +430,19 @@ namespace MoReFEM
{
oconv.str("");
if (!Utilities::OutputFormat::GetInstance(__FILE__, __LINE__).IsBinaryOutput())
oconv << common_part_for_same_time_iteration << mpi.template GetRank<int>() << ".hhdata";
else
oconv << common_part_for_same_time_iteration << mpi.template GetRank<int>() << ".binarydata";
switch(Utilities::OutputFormat::GetInstance(__FILE__, __LINE__).IsBinaryOutput())
{
case binary_or_ascii::ascii:
oconv << common_part_for_same_time_iteration << mpi.template GetRank<int>() << ".hhdata";
break;
case binary_or_ascii::binary:
oconv << common_part_for_same_time_iteration << mpi.template GetRank<int>() << ".binarydata";
break;
case binary_or_ascii::from_input_data:
assert(false && "Should not happen");
exit(EXIT_FAILURE);
} // switch
output_file = oconv.str();
}
......@@ -446,11 +455,20 @@ namespace MoReFEM
FilesystemNS::File::Append(inout, GetGodOfDof().GetTimeIterationFile(), __FILE__, __LINE__);
oconv.str("");
if (!Utilities::OutputFormat::GetInstance(__FILE__, __LINE__).IsBinaryOutput())
oconv << common_part_for_same_time_iteration << "*.hhdata";
else
oconv << common_part_for_same_time_iteration << "*.binarydata";
switch(Utilities::OutputFormat::GetInstance(__FILE__, __LINE__).IsBinaryOutput())
{
case binary_or_ascii::ascii:
oconv << common_part_for_same_time_iteration << "*.hhdata";
break;
case binary_or_ascii::binary:
oconv << common_part_for_same_time_iteration << "*.binarydata";
break;
case binary_or_ascii::from_input_data:
assert(false && "Should not happen");
exit(EXIT_FAILURE);
} // switch
inout << transient.NtimeModified() << ';' << transient.GetTime() << ';' << numbering_subset.GetUniqueId()
<< ';' << oconv.str() << std::endl;
}
......
......@@ -62,52 +62,66 @@ namespace MoReFEM
std::vector<double> LoadVector(const std::string& file)
{
std::vector<double> ret;
if (!Utilities::OutputFormat::GetInstance(__FILE__, __LINE__).IsBinaryOutput())
{
std::ifstream stream;
FilesystemNS::File::Read(stream, file, __FILE__, __LINE__);
const auto binary_or_ascii_choice =
Utilities::OutputFormat::GetInstance(__FILE__, __LINE__).IsBinaryOutput();
std::string line;
while(getline(stream, line))
ret.push_back(std::stod(line));
}
else
switch(binary_or_ascii_choice)
{
std::ifstream in (file, std::ifstream::binary);
if (in)
case binary_or_ascii::binary:
{
// Get length of file.
std::ifstream::pos_type block_size;
block_size = in.seekg(0, std::ifstream::end).tellg();
in.seekg(0, std::ifstream::beg);
std::ifstream in (file, std::ifstream::binary);
if (in)
{
// Get length of file.
std::ifstream::pos_type block_size;
block_size = in.seekg(0, std::ifstream::end).tellg();
in.seekg(0, std::ifstream::beg);
std::vector<char> buffer(static_cast<std::size_t>(block_size));
std::vector<char> buffer(static_cast<std::size_t>(block_size));
// Read data as a block.
in.read(buffer.data(), block_size);
// Read data as a block.
in.read(buffer.data(), block_size);
if (!in)
throw Exception("Unable to read file " + file, __FILE__, __LINE__);
if (!in)
throw Exception("Unable to read file " + file, __FILE__, __LINE__);
in.close();
in.close();
// Buffer contains the entire file. Convert bytes back into doubles.
const double * values = reinterpret_cast<double *> (buffer.data());
// Buffer contains the entire file. Convert bytes back into doubles.
const double * values = reinterpret_cast<double *> (buffer.data());
const unsigned long Nvalue_binary = static_cast<std::size_t>(block_size) / sizeof(double);
const unsigned long Nvalue_binary = static_cast<std::size_t>(block_size) / sizeof(double);
for (std::size_t i = 0u; i < Nvalue_binary; ++i)
{
if (std::fabs(values[i]) <= NumericNS::DefaultEpsilon<double>())
ret.push_back(0.);
else
ret.push_back(values[i]);
for (std::size_t i = 0u; i < Nvalue_binary; ++i)
{
if (std::fabs(values[i]) <= NumericNS::DefaultEpsilon<double>())
ret.push_back(0.);
else
ret.push_back(values[i]);
}
}
break;
}
case binary_or_ascii::ascii:
{
std::ifstream stream;
FilesystemNS::File::Read(stream, file, __FILE__, __LINE__);
std::string line;
while(getline(stream, line))
ret.push_back(std::stod(line));
break;
}
case binary_or_ascii::from_input_data:
{
assert(false && "Should not happen!");
exit(EXIT_FAILURE);
}
}
return ret;
}
......
//! \file
//
//
// BinaryOrAscii.hpp
// MoReFEM
//
// Created by sebastien on 16/07/2019.
//Copyright © 2019 Inria. All rights reserved.
//
#ifndef MOREFEM_x_THIRD_PARTY_x_WRAPPERS_x_PETSC_x_VECTOR_x_BINARY_OR_ASCII_HPP_
# define MOREFEM_x_THIRD_PARTY_x_WRAPPERS_x_PETSC_x_VECTOR_x_BINARY_OR_ASCII_HPP_
# include <memory>
# include <vector>
namespace MoReFEM
{
//! Enum class to specify whether the choice of output (ascii or binary)
enum class binary_or_ascii
{
from_input_data, // takes the value specified in the input data file.
ascii,
binary
};
} // namespace MoReFEM
#endif // MOREFEM_x_THIRD_PARTY_x_WRAPPERS_x_PETSC_x_VECTOR_x_BINARY_OR_ASCII_HPP_
......@@ -40,42 +40,55 @@ namespace MoReFEM
void PrintPerProcessor(const Vector& vector,
const std::string& output_file,
const char* invoking_file, int invoking_line)
const char* invoking_file, int invoking_line,
binary_or_ascii binary_or_ascii_choice)
{
::MoReFEM::Wrappers::Petsc
::AccessVectorContent<Utilities::Access::read_only> content(vector,
invoking_file, invoking_line);
const unsigned int Nvalue = content.GetSize(invoking_file, invoking_line);
if (!Utilities::OutputFormat::GetInstance(__FILE__, __LINE__).IsBinaryOutput())
switch(binary_or_ascii_choice)
{
std::ofstream out;
FilesystemNS::File::Create(out, output_file, invoking_file, invoking_line);
for (unsigned int i = 0u; i < Nvalue; ++i)
case binary_or_ascii::binary:
{
if (std::fabs(content.GetValue(i)) <= NumericNS::DefaultEpsilon<double>())
{
out << std::setw(12) << std::scientific << 0. << std::endl;
}
else
std::ofstream out_binary(output_file, std::ofstream::binary);
if (!out_binary)
throw Exception("Unable to create file " + output_file, invoking_file, invoking_line);
const auto array = content.GetArray();
out_binary.write(reinterpret_cast<const char *>(array), Nvalue * sizeof(double));
out_binary.close();
break;
}
case binary_or_ascii::ascii:
{
std::ofstream out;
FilesystemNS::File::Create(out, output_file, invoking_file, invoking_line);
for (unsigned int i = 0u; i < Nvalue; ++i)
{
out << std::setw(12) << std::scientific << std::setprecision(20) << content.GetValue(i) << std::endl;
if (std::fabs(content.GetValue(i)) <= NumericNS::DefaultEpsilon<double>())
out << std::setw(12) << std::scientific << 0. << std::endl;
else
out << std::setw(12) << std::scientific << std::setprecision(20)
<< content.GetValue(i) << std::endl;
}
break;
}
}
else
{
std::ofstream out_binary(output_file, std::ofstream::binary);
if (!out_binary)
throw Exception("Unable to create file " + output_file, invoking_file, invoking_line);
const auto array = content.GetArray();
out_binary.write(reinterpret_cast<const char *>(array), Nvalue * sizeof(double));
out_binary.close();
}
case binary_or_ascii::from_input_data:
{
assert( false && "This function should be called from Vector class, and this specific case "
"should have been addressed prior to this call (see Vector::Print() for instance "
"to see how).");
exit(EXIT_FAILURE);
}
} // switch
}
......
......@@ -17,6 +17,8 @@
# include <string>
# include "ThirdParty/Wrappers/Petsc/Vector/BinaryOrAscii.hpp"
namespace MoReFEM
{
......@@ -72,13 +74,16 @@ namespace MoReFEM
* \param[in] vector Vector which processor-wise content is to be written.
* \param[in] output_file Output file into which the values will be written. Beware: this file should
* be named differently for each rank!
* \param[in] choice Whether the vector should be printed as binary or ascii. Default value takes its
* cue from the choice written in the input data file.
* \param[in] invoking_file File that invoked the function or class; usually __FILE__.
* \param[in] invoking_line File that invoked the function or class; usually __LINE__.
*
*/
void PrintPerProcessor(const Vector& vector,
const std::string& output_file,
const char* invoking_file, int invoking_line);
const char* invoking_file, int invoking_line,
binary_or_ascii binary_or_ascii_choice);
} // namespace Petsc
......
......@@ -19,6 +19,7 @@ target_sources(${MOREFEM_UTILITIES}
"${CMAKE_CURRENT_LIST_DIR}/AccessGhostContent.hxx"
"${CMAKE_CURRENT_LIST_DIR}/AccessVectorContent.hpp"
"${CMAKE_CURRENT_LIST_DIR}/AccessVectorContent.hxx"
"${CMAKE_CURRENT_LIST_DIR}/BinaryOrAscii.hpp"
"${CMAKE_CURRENT_LIST_DIR}/Vector.hpp"
"${CMAKE_CURRENT_LIST_DIR}/Vector.hxx"
)
......
......@@ -586,7 +586,8 @@ namespace MoReFEM
}
void Vector::Load(const Mpi& mpi, const std::string& input_file, const char* invoking_file, int invoking_line,
void Vector::Load(const Mpi& mpi, const std::string& input_file,
const char* invoking_file, int invoking_line,
PetscViewerFormat format) const
{
Viewer viewer(mpi, input_file, format, invoking_file, invoking_line);
......
......@@ -26,9 +26,9 @@
# include "ThirdParty/Wrappers/Mpi/MpiScale.hpp"
# include "ThirdParty/IncludeWithoutWarning/Petsc/PetscVec.hpp"
# include "ThirdParty/Wrappers/Petsc/Vector/BinaryOrAscii.hpp"
# include "ThirdParty/Wrappers/Petsc/Vector/Internal/VectorHelper.hpp"
# include "ThirdParty/Wrappers/Mpi/Mpi.hpp"
# include "ThirdParty/Wrappers/Mpi/MpiScale.hpp"
namespace MoReFEM
......@@ -517,8 +517,6 @@ namespace MoReFEM
const char* invoking_file, int invoking_line) const;
/*!
* \brief Print the content of a vector in a file.
*
......@@ -530,11 +528,14 @@ namespace MoReFEM
* \copydetails doxygen_hide_mpi_param
* \copydoc doxygen_hide_invoking_file_and_line
* \param[in] output_file File into which the vector content will be written.
* \param[in] binary_or_ascii_choice Whether the vector should be printed as binary or ascii. Default
* value takes its cue from the choice written in the input data file.
*/
template<MpiScale MpiScaleT>
void Print(const Mpi& mpi,
const std::string& output_file,
const char* invoking_file, int invoking_line) const;
const char* invoking_file, int invoking_line,
binary_or_ascii binary_or_ascii_choice = binary_or_ascii::from_input_data) const;
/*!
......
......@@ -53,20 +53,37 @@ namespace MoReFEM
template<MpiScale MpiScaleT>
void Vector::Print(const Mpi& mpi,
const std::string& output_file,
const char* invoking_file, int invoking_line) const
const char* invoking_file, int invoking_line,
binary_or_ascii binary_or_ascii_choice) const
{
if (binary_or_ascii_choice == binary_or_ascii::from_input_data)
binary_or_ascii_choice = Utilities::OutputFormat::GetInstance(__FILE__, __LINE__).IsBinaryOutput();
switch(MpiScaleT)
{
case MpiScale::program_wise:
if (!Utilities::OutputFormat::GetInstance(__FILE__, __LINE__).IsBinaryOutput())
View(mpi, output_file, invoking_file, invoking_line, PETSC_VIEWER_ASCII_MATLAB);
else
ViewBinary(mpi, output_file, invoking_file, invoking_line);
{
switch(binary_or_ascii_choice)
{
case binary_or_ascii::ascii:
View(mpi, output_file, invoking_file, invoking_line, PETSC_VIEWER_ASCII_MATLAB);
break;
case binary_or_ascii::binary:
ViewBinary(mpi, output_file, invoking_file, invoking_line);
break;
case binary_or_ascii::from_input_data:
{
assert(false && "SHould have been handled at the beginning of current method.");
exit(EXIT_FAILURE);
}
}
break;
}
case MpiScale::processor_wise:
Internal::Wrappers::Petsc::PrintPerProcessor(*this, output_file, invoking_file, invoking_line);
Internal::Wrappers::Petsc::PrintPerProcessor(*this, output_file, invoking_file, invoking_line,
binary_or_ascii_choice);
break;
}
} // switch
}
......@@ -83,9 +100,7 @@ namespace MoReFEM
}
}
} // namespace Petsc
......
......@@ -32,9 +32,9 @@ namespace MoReFEM
OutputFormat::OutputFormat(bool binary_output)
: binary_output_(binary_output)
{
}
: binary_output_(binary_output ? binary_or_ascii::binary : binary_or_ascii::ascii)
{ }
const std::string& OutputFormat::ClassName()
{
......@@ -42,12 +42,7 @@ namespace MoReFEM
return ret;
}
bool OutputFormat::IsBinaryOutput()
{
return binary_output_;
}
} // namespace Utilities
......
......@@ -15,13 +15,15 @@
#ifndef MOREFEM_x_UTILITIES_x_OUTPUT_FORMAT_x_OUTPUT_FORMAT_HPP_
# define MOREFEM_x_UTILITIES_x_OUTPUT_FORMAT_x_OUTPUT_FORMAT_HPP_
#include <cstdlib>
#include <string>
# include <cstdlib>
# include <string>
#include "Utilities/String/String.hpp"
#include "Utilities/String/Traits.hpp"
#include "Utilities/Exceptions/Exception.hpp"
#include "Utilities/Singleton/Singleton.hpp"
# include "Utilities/String/String.hpp"
# include "Utilities/String/Traits.hpp"
# include "Utilities/Exceptions/Exception.hpp"
# include "Utilities/Singleton/Singleton.hpp"
# include "ThirdParty/Wrappers/Petsc/Vector/BinaryOrAscii.hpp"
namespace MoReFEM
......@@ -77,13 +79,13 @@ namespace MoReFEM
public:
//! Sets the output format of solution vectors to be binary if true, ascii if false.
bool IsBinaryOutput();
//! Output format for solution vectors.
binary_or_ascii IsBinaryOutput() const noexcept;
private:
//! Used to define whether the output is ascii or binary.
bool binary_output_ = false;
binary_or_ascii binary_output_ = binary_or_ascii::ascii;
};
......
......@@ -24,6 +24,12 @@ namespace MoReFEM
{
inline binary_or_ascii OutputFormat::IsBinaryOutput() const noexcept
{
return binary_output_;
}
} // namespace Utilities
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment