Page MenuHomec4science

dumpers.cc
No OneTemporary

File Metadata

Created
Wed, May 22, 07:38

dumpers.cc

/* -------------------------------------------------------------------------- */
#include "dumpers.hh"
#include "grid.hh"
/* -------------------------------------------------------------------------- */
#include <array>
#include <fstream>
#include <iomanip>
#include <sstream>
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
void Dumper::set_min(float min) { m_min = min; }
void Dumper::set_max(float max) { m_max = max; }
float Dumper::min() const { return m_min; }
float Dumper::max() const { return m_max; }
/* -------------------------------------------------------------------------- */
void DumperASCII::dump(const Grid & grid, int step) {
std::ofstream fout;
std::stringstream sfilename;
sfilename << "out_" << std::setfill('0') << std::setw(5) << step << ".pgm";
fout.open(sfilename.str());
int m = grid.m();
int n = grid.n();
fout << "P2" << std::endl << "# CREATOR: Poisson program" << std::endl;
fout << m << " " << n << std::endl;
fout << 255 << std::endl;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
int v = 255. * (grid(i, j) - m_min) / (m_max - m_min);
v = std::min(v, 255);
fout << v << std::endl;
}
}
}
/* -------------------------------------------------------------------------- */
void DumperBinary::dump(const Grid & grid, int step) {
std::stringstream sfilename;
std::array<int, 2> coords{0, 0}, dims{0, 0};
#if defined(_MPI)
int prank{0}, psize{1};
MPI_Comm_rank(m_communicator, &prank);
MPI_Comm_size(m_communicator, &psize);
std::array<int, 2> periods{0, 0};
MPI_Cart_get(m_communicator, dims.size(), dims.data(), periods.data(), coords.data());
#else
dims = {1, 1};
#endif
sfilename << "out_" << std::setfill('0') << std::setw(5) << step << ".bmp";
int h = grid.m();
int w = grid.n();
int global_w = w;
std::array<int, 2> starts = {0, 0};
std::array<int, 2> local_sizes = {h, w};
std::array<int, 2> global_sizes = local_sizes;
#if defined(_MPI)
// removing the ghosts
if(prank == 0) std::cout << dims[0] << " " << dims[1] << "\n";
for (std::size_t i = 0; i < local_sizes.size(); ++i) {
if (dims[i] > 1) {
local_sizes[i] -= (coords[i] == 0 || coords[i] == dims[i] - 1 ? 1 : 2);
starts[i] += (coords[i] == 0 ? 0 : 1);
}
}
std::array<MPI_Comm, 2> comms;
// determining the local offset
std::array<int, 2> offset = {0, 0};
std::vector<std::vector<int>> line_col_size(2);
for (size_t i = 0; i < line_col_size.size(); ++i) {
std::array<int, 2> remain_dims = {false, false};
remain_dims[i] = true;
MPI_Cart_sub(m_communicator, remain_dims.data(), &(comms[i]));
line_col_size[i].resize(dims[i]);
MPI_Allgather(&local_sizes[i], 1, MPI_INT, line_col_size[i].data(), 1,
MPI_INT, comms[i]);
global_sizes[i] = 0;
for (int j = 0; j < dims[i]; ++j) {
global_sizes[i] += line_col_size[i][j];
}
}
//for (int i = dims[0] - 1; i > coords[0]; --i) {
for (int i = 0; i < coords[0]; ++i) {
offset[0] += line_col_size[0][i];
}
for (int i = 0; i < coords[1]; ++i) {
offset[1] += line_col_size[1][i];
}
#endif
global_w = 4 * ((24 * global_sizes[1] + 31) / 32);
// if the file width (3*w) is not a multiple of 4 adds enough bytes to make it
// a multiple of 4
int padding = global_w - 3 * global_sizes[1];
w = 3 * local_sizes[1];
if (coords[1] == dims[1] - 1) {
w += padding;
} else {
padding = 0;
}
int filesize = 54 + global_sizes[0] * global_w;
std::vector<char> img(local_sizes[0] * w);
std::fill(img.begin(), img.end(), 0);
for (int i = 0; i < local_sizes[0]; i++) {
for (int j = 0; j < local_sizes[1]; j++) {
float v =
((grid(i + starts[0], j + starts[1]) - m_min) / (m_max - m_min));
float r = v * 255; // Red channel
float g = v * 255; // Green channel
float b = 0.f; //prank * 255 / psize; // Red channel
r = std::min(r, 255.f);
g = std::min(g, 255.f);
b = std::min(b, 255.f);
img[w * i + 3 * j + 0] = r;
img[w * i + 3 * j + 1] = g;
img[w * i + 3 * j + 2] = b;
}
}
auto write_bytes = [](auto && array, auto && value) {
array[0] = value;
array[1] = value >> 8;
array[2] = value >> 16;
array[3] = value >> 24;
};
std::array<char, 14> bmpfileheader = {'B', 'M', 0, 0, 0, 0, 0,
0, 0, 0, 54, 0, 0, 0};
std::array<char, 40> bmpinfoheader = {40, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 24, 0};
write_bytes(&bmpfileheader[2], filesize);
write_bytes(&bmpinfoheader[4], global_sizes[1]);
write_bytes(&bmpinfoheader[8], global_sizes[0]);
write_bytes(&bmpinfoheader[20], filesize - 54);
#if defined(_MPI)
MPI_File fh;
MPI_Status status;
MPI_Datatype subarray_t;
#if defined(_DEBUG_MPI)
for (int i = 0; i < psize; ++i) {
if (prank == i)
std::cerr << prank << " (" << coords[0] << ", " << coords[1] << ")"
<< " - " << local_sizes[0] << "x" << local_sizes[1] << "(" << w
<< ") + " << offset[0] << "x" << offset[1] << "("<< 3*offset[1]<<") ++ ["
<< global_sizes[0] << "x" << global_sizes[1] << "(" << global_w
<< ")] " << padding << "\n";
MPI_Barrier(m_communicator);
}
#endif
global_sizes[1] = global_w;
local_sizes[1] = w;
offset[1] *= 3;
MPI_Type_create_subarray(global_sizes.size(), global_sizes.data(),
local_sizes.data(), offset.data(), MPI_ORDER_C,
MPI_CHAR, &subarray_t);
MPI_Type_commit(&subarray_t);
// opening a file in write and create mode
MPI_File_open(MPI_COMM_WORLD, sfilename.str().c_str(),
MPI_MODE_WRONLY | MPI_MODE_CREATE, MPI_INFO_NULL, &fh);
// defining the size of the file
MPI_File_set_size(fh, filesize);
// rank 0 writes the header
if (prank == 0) {
MPI_File_write_at(fh, 0, bmpfileheader.data(), 14, MPI_CHAR, &status);
MPI_File_write_at(fh, 14, bmpinfoheader.data(), 40, MPI_CHAR, &status);
}
if(prank == 0) {
std::cout << filesize << std::endl;
}
MPI_File_set_view(fh, 54, MPI_CHAR, subarray_t, "native", MPI_INFO_NULL);
MPI_File_write(fh, img.data(), img.size(), MPI_CHAR, &status);
MPI_File_close(&fh);
#endif
}

Event Timeline