/* This file is part of the OpenLB library * * Copyright (C) 2016 Fabian Klemens * E-mail contact: info@openlb.net * The most recent release of OpenLB can be downloaded at * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef GNUPLOT_WRITER_HH #define GNUPLOT_WRITER_HH #include #include #include #include "core/singleton.h" #include "io/fileName.h" #include "gnuplotWriter.h" #include "utilities/vectorHelpers.h" namespace olb { /// Constructor with name of outputFiles /// boolean true for real-time plotting //WARNING: experimental! template< typename T > Gnuplot::Gnuplot(std::string name, bool liveplot) : _name(name), _dataFile(singleton::directories().getGnuplotOutDir()+"data/"+_name+".dat"), _dir(singleton::directories().getGnuplotOutDir()) { _liveplot = liveplot; if (singleton::mpi().getRank() == _rank) { std::ofstream fout; ///add (new) data file fout.open(_dataFile.c_str(), std::ios::trunc); fout.close(); } } /// writes the data and plot file for two doubles (x and y) /// plotType indicates whether you want a linegraph 'l' (default) or a scatterplot 'p' (default: 'l') template< typename T > void Gnuplot::setData(T xValue, T yValue, std::string name, std::string key, char plotType) { if (_init) { _dataSize = 1; _key = key; _names = {name}; _plotTypes = {plotType}; if (_liveplot) { writePlotFile("plot"); } } writeDataFile(xValue, yValue); if (_liveplot && _init) { startGnuplot("plot"); } _init = false; return; } /// writes the data and plot file for two doubles (x and y), where x is increasing integer template< typename T > void Gnuplot::setData(bool noXvalue, T yValue, std::string name, std::string key, char plotType) { T xValue = _time; setData(xValue, yValue, name, key, {plotType}); _time++; } /// writes the data and plot file for a double and a vector of doubles (x and y1,y2,...) /// plotType indicates whether you want a linegraph 'l' (default) or a scatterplot 'p': (default: {'l','l'}) /// The position in the vector 'plotType'{'l', 'p'} is linked to the rank of the y-axis (y1, y2) : /// y1 is plotted in form of a line plot & y2 is plotted in form of a scatterplot template< typename T > void Gnuplot::setData(T xValue, std::vector yValues, std::vector names, std::string key, std::vector plotType) { if (_init) { _dataSize = yValues.size(); _key = key; _names = names; _plotTypes = plotType; if (_names.size() < _dataSize) { for (unsigned int i = _names.size(); i < _dataSize; i++) { _names.push_back(""); } } if (_plotTypes.size() < _dataSize) { for (unsigned int i = _plotTypes.size(); i < _dataSize; i++) { _plotTypes.push_back('l'); } } if (_liveplot) { writePlotFile("plot"); } } writeDataFile(xValue,yValues); if (_liveplot && _init) { startGnuplot("plot"); } _init = false; return; } /// writes the data and plot file for a double and a vector of doubles (x and y1,y2,...), where x is increasing integer template< typename T > void Gnuplot::setData(bool noXvalue, std::vector yValues, std::vector names, std::string key, std::vector plotType) { T xValue = _time; setData(xValue, yValues, names, key, plotType); _time++; } /// writes an PDF template< typename T > void Gnuplot::writePDF() { if (!_init) { writePlotFile("pdf"); startGnuplot("plotPDF"); } return; } /// writes PNGs /// usage: first argument: numbering of png file /// second argument: range for the x axis /// thrid argument: specifies the name of the plot in case the user wants to /// create more than one plot with the simulation results (default: plotName = "") /// no arguments: writes consecutive numbers with adaptive xrange template< typename T > void Gnuplot::writePNG(int iT, double xRange, std::string plotName) { if (!_init) { _iT = iT; _xRange = xRange; /// initialize the writePlotFile for Gnuplot with the type and the name of the output data writePlotFile("png", plotName); startGnuplot("plotPNG", plotName); } return; } /// plotName specifies the name of the plot in case the user wants to create more than /// one plot with the simulation results (default: plotName = "") template< typename T > void Gnuplot::writePlotFile(std::string type, std::string plotName) { if (singleton::mpi().getRank() == _rank ) { std::ofstream fout; std::string plotFile; if (_liveplot && type == "plot") { plotFile = singleton::directories().getGnuplotOutDir()+"data/plot.p"; } else if (type == "pdf") { plotFile = singleton::directories().getGnuplotOutDir()+"data/plotPDF.p"; } else if (type == "png") { plotFile = singleton::directories().getGnuplotOutDir()+"data/plotPNG"+plotName+".p"; } else { std::cout << "WARNING: invalid Gnuplot type={'', 'plot'; 'pdf', 'png'}" << std::endl; exit(-1); } fout.open(plotFile.c_str(), std::ios::trunc); fout << "set key " << _key << "\n"; if (type=="pdf") { fout << "set terminal pdf enhanced" << "\n" << "set output '"<<_dir<<_name<<".pdf'" << "\n"; } if (type=="png") { if ( !util::nearZero(_xRange+1) ) { fout << "set xr[0:"<< _xRange <<"]" << "\n"; } fout << "set terminal png" << "\n" << "set output '"<<_dir<<_name; if (_iT != -1) { fout <<"_"<<_iT; } fout <<".png'" << "\n"; } /// set the x and y label of the Plot fout << "set xlabel '" << _xLabel << "'" << "\n"; fout << "set ylabel '" << _yLabel << "'" << "\n"; /// vector which holds the information about the plotType /// (e.g. scatterplot 'p' or lineplot 'l': default {'l','l'}) fout << "plot '"<<_dataFile<<"' u 1:2 w " << _plotTypes[0] << " t '"<< _names[0] << "'"; for (unsigned int i = 0; i < _dataSize-1; ++i) { fout << ", '"<<_dataFile<<"' u 1:" << i+3 << " w " << _plotTypes[i+1] << " t '" << _names[i+1] << "'"; } fout << "\n"; if (_liveplot && type=="plot") { fout << "pause -1" << "\n" << "reread" << "\n"; } fout.close(); } return; } /// writes the data file for two doubles (x and y) template< typename T > void Gnuplot::writeDataFile(T xValue, T yValue) { if (singleton::mpi().getRank() == _rank) { std::ofstream fout; fout.precision(6); fout.open(_dataFile.c_str(), std::ios::app); fout << xValue << " " << yValue << std::endl; fout.close(); } return; } /// set Label of the gnuplotPlot; xLabel and yLabel template< typename T > void Gnuplot::setLabel(std::string xLabel, std::string yLabel) { _xLabel = xLabel; _yLabel = yLabel; } /// writes the data file for one double and a vector of doubles (x and y1,y2,...) template< typename T > void Gnuplot::writeDataFile(T xValue, std::vector yValues) { if (singleton::mpi().getRank() == _rank) { std::ofstream fout; fout.precision(6); fout.open(_dataFile.c_str(), std::ios::app); fout << xValue; for (unsigned int i = 0; i < yValues.size(); i++) { fout << " " << yValues[i]; } fout << "\n"; fout.close(); } return; } /// system command to start gnuplot (LINUX ONLY!) /// plotName indicates the name of the plot in case the user wants to create /// more than one plot with the simulation results (default: plotName = "") template< typename T > void Gnuplot::startGnuplot(std::string plotFile, std::string plotName) { #ifdef WIN32 std::cout << "GNUPLOT WORKS ONLT WITH LINUX" << std::endl; // exit (EXIT_FAILURE); return; #endif #ifndef WIN32 if (singleton::mpi().getRank() == _rank) { if (!system(nullptr)) { exit (EXIT_FAILURE); } const std::string command = "gnuplot -persistent "+_dir+"data/"+plotFile+plotName+".p > /dev/null &"; if ( system(command.c_str()) ) { std::cout << "Error at GnuplotWriter" << std::endl; } } return; #endif } } // namespace olb #endif