diff --git a/Serie07/write_bmp/AUTHORS b/Serie07/write_bmp/AUTHORS new file mode 100644 index 0000000..9253635 --- /dev/null +++ b/Serie07/write_bmp/AUTHORS @@ -0,0 +1,4 @@ +Authors: + - Nicolas Richart + - Vincent Keller + . Vittoria Rezzonico diff --git a/Serie07/write_bmp/COPYING b/Serie07/write_bmp/COPYING new file mode 100644 index 0000000..e551330 --- /dev/null +++ b/Serie07/write_bmp/COPYING @@ -0,0 +1,24 @@ +Copyright (c) 2017, Ecole Polytechnique Federal de Lausanne - Scientific IT and +Application Support (SCITAS) All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Serie07/write_bmp/Makefile b/Serie07/write_bmp/Makefile new file mode 100644 index 0000000..6f64d80 --- /dev/null +++ b/Serie07/write_bmp/Makefile @@ -0,0 +1,14 @@ +CXX=mpic++ +LD=${CXX} +CXXFLAGS+=-Wall -Wextra -pedantic -std=c++11 -O3 +LDFLAGS+=-lm $(CXXFLAGS) + +OBJS=grid.o dumpers.o main.o + +all: write_bmp + +write_bmp: $(OBJS) + $(LD) -o $@ $(OBJS) $(LDFLAGS) + +clean: + rm -f write_bmp *.o *~ diff --git a/Serie07/write_bmp/dumpers.cc b/Serie07/write_bmp/dumpers.cc new file mode 100644 index 0000000..de7eb79 --- /dev/null +++ b/Serie07/write_bmp/dumpers.cc @@ -0,0 +1,120 @@ +/* -------------------------------------------------------------------------- */ +#include "dumpers.hh" +#include "grid.hh" +/* -------------------------------------------------------------------------- */ +#include +#include +#include +#include +/* -------------------------------------------------------------------------- */ + +/* -------------------------------------------------------------------------- */ +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(int step) { + std::ofstream fout; + std::stringstream sfilename; + + sfilename << "output/out_" << std::setfill('0') << std::setw(5) << step << ".pgm"; + fout.open(sfilename.str()); + + int m = m_grid.m(); + int n = m_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. * (m_grid(i, j) - m_min) / (m_max - m_min); + v = std::min(v, 255); + fout << v << std::endl; + } + } +} + +/* -------------------------------------------------------------------------- */ +void DumperBinary::dump(int step) { + std::ofstream fout; + std::stringstream sfilename; + + sfilename << "out_" << std::setfill('0') << std::setw(5) << step << ".bmp"; + fout.open(sfilename.str(), std::ios_base::binary); + + int h = m_grid.m(); + int w = m_grid.n(); + + int row_size = 3 * w; + // if the file width (3*w) is not a multiple of 4 adds enough bytes to make it + // a multiple of 4 + int padding = (4 - (row_size) % 4) % 4; + row_size += padding; + + int filesize = 54 + (row_size)*h; + + std::vector img(row_size*h); + std::fill(img.begin(), img.end(), 0); + + + for (int i = 0; i < h; i++) { + for (int j = 0; j < w; j++) { + float v = ((m_grid(h - 1 - i, j) - m_min) / (m_max - m_min)); + + float r = v * 255; // Red channel + float g = v * 255; // Green channel + float b = v * 255; // Red channel + + r = std::min(r, 255.f); + g = std::min(g, 255.f); + b = std::min(b, 255.f); + + img[row_size * i + 3 * j + 2] = r; + img[row_size * i + 3 * j + 1] = g; + img[row_size * i + 3 * j + 0] = b; + } + } + + std::array bmpfileheader = {'B', 'M', 0, 0, 0, 0, 0, + 0, 0, 0, 54, 0, 0, 0}; + std::array bmpinfoheader = {40, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 24, 0}; + + bmpfileheader[2] = filesize; + bmpfileheader[3] = filesize >> 8; + bmpfileheader[4] = filesize >> 16; + bmpfileheader[5] = filesize >> 24; + + bmpinfoheader[4] = w; + bmpinfoheader[5] = w >> 8; + bmpinfoheader[6] = w >> 16; + bmpinfoheader[7] = w >> 24; + bmpinfoheader[8] = h; + bmpinfoheader[9] = h >> 8; + bmpinfoheader[10] = h >> 16; + bmpinfoheader[11] = h >> 24; + bmpinfoheader[20] = (filesize - 54); + bmpinfoheader[21] = (filesize - 54) >> 8; + bmpinfoheader[22] = (filesize - 54) >> 16; + bmpinfoheader[23] = (filesize - 54) >> 24; + + fout.write(bmpfileheader.data(), 14); + fout.write(bmpinfoheader.data(), 40); + + fout.write(img.data(), h * row_size); +} diff --git a/Serie07/write_bmp/dumpers.hh b/Serie07/write_bmp/dumpers.hh new file mode 100644 index 0000000..27a5f12 --- /dev/null +++ b/Serie07/write_bmp/dumpers.hh @@ -0,0 +1,48 @@ +#include + +#ifndef DUMPERS_HH +#define DUMPERS_HH + +/* -------------------------------------------------------------------------- */ +class Grid; + +/* -------------------------------------------------------------------------- */ +class Dumper { +public: + explicit Dumper(const Grid & grid, MPI_Comm communicator) + : m_grid(grid), m_min(-1.), m_max(1.), m_communicator(communicator) {} + + virtual void dump(int step) = 0; + + void set_min(float min); + void set_max(float max); + + float min() const; + float max() const; + +protected: + const Grid & m_grid; + float m_min, m_max; + + MPI_Comm m_communicator; +}; + +/* -------------------------------------------------------------------------- */ +class DumperASCII : public Dumper { +public: + explicit DumperASCII(const Grid & grid, MPI_Comm communicator) + : Dumper(grid, communicator) {} + + virtual void dump(int step); +}; + +/* -------------------------------------------------------------------------- */ +class DumperBinary : public Dumper { +public: + explicit DumperBinary(const Grid & grid, MPI_Comm communicator) + : Dumper(grid, communicator) {} + + virtual void dump(int step); +}; + +#endif /* DUMPERS_HH */ diff --git a/Serie07/write_bmp/grid.cc b/Serie07/write_bmp/grid.cc new file mode 100644 index 0000000..bd635e9 --- /dev/null +++ b/Serie07/write_bmp/grid.cc @@ -0,0 +1,24 @@ +/* -------------------------------------------------------------------------- */ +#include "grid.hh" +/* -------------------------------------------------------------------------- */ +#include +/* -------------------------------------------------------------------------- */ + +/* -------------------------------------------------------------------------- */ +Grid::Grid(int m, int n) : m_m(m), m_n(n), m_storage(m * n) { clear(); } + +/* -------------------------------------------------------------------------- */ +void Grid::clear() { std::fill(m_storage.begin(), m_storage.end(), 0.); } + +/* -------------------------------------------------------------------------- */ +void Grid::resize(int m, int n) { + m_m = m; + m_n = n; + m_storage.resize(m*n); +} + +/* -------------------------------------------------------------------------- */ +int Grid::m() const { return m_m; } +int Grid::n() const { return m_n; } + +/* -------------------------------------------------------------------------- */ diff --git a/Serie07/write_bmp/grid.hh b/Serie07/write_bmp/grid.hh new file mode 100644 index 0000000..5f0c367 --- /dev/null +++ b/Serie07/write_bmp/grid.hh @@ -0,0 +1,31 @@ +#ifndef GRID_HH +#define GRID_HH + +/* -------------------------------------------------------------------------- */ +#include +/* -------------------------------------------------------------------------- */ + +class Grid { +public: + Grid(int m = 0, int n = 0); + + /// access the value [i][j] of the grid + inline float & operator()(int i, int j) { return m_storage[i * m_n + j]; } + inline const float & operator()(int i, int j) const { + return m_storage[i * m_n + j]; + } + + void resize(int m, int n); + + /// set the grid to 0 + void clear(); + + int m() const; + int n() const; + +private: + int m_m, m_n; + std::vector m_storage; +}; + +#endif /* GRID_HH */ diff --git a/Serie07/write_bmp/main.cc b/Serie07/write_bmp/main.cc new file mode 100644 index 0000000..b32b6a0 --- /dev/null +++ b/Serie07/write_bmp/main.cc @@ -0,0 +1,52 @@ +/* -------------------------------------------------------------------------- */ +#include +#include +/* -------------------------------------------------------------------------- */ +#include "grid.hh" +#include "dumpers.hh" +/* -------------------------------------------------------------------------- */ + +/* -------------------------------------------------------------------------- */ +static void usage(const std::string & prog_name) { + std::cerr << prog_name << " " << std::endl; + exit(0); +} + +/* -------------------------------------------------------------------------- */ +int main(int argc, char *argv[]) { + MPI_Init(&argc, &argv); + int prank, psize; + + MPI_Comm_rank(MPI_COMM_WORLD, &prank); + MPI_Comm_size(MPI_COMM_WORLD, &psize); + + if (argc != 2) usage(argv[0]); + + std::stringstream args(argv[1]); + int n; + args >> n; + + if(args.fail()) usage(argv[0]); + + int m_local = n / psize; + + Grid f(m_local, n); + + float h = 1./n; + int offset_m = m_local * prank; + int offset_n = 0; + + for (int i = 0; i < m_local; i++) { + for (int j = 0; j < n; j++) { + f(i, j) = std::sin(10. * M_PI * (offset_m + i) * h) * + std::cos(10. * M_PI * (offset_n + j) * h); + } + } + + DumperBinary dumper(f, MPI_COMM_WORLD); + dumper.dump(0); + + MPI_Finalize(); + +return 0; +}