diff --git a/dumux/io/gnuplotinterface.hh b/dumux/io/gnuplotinterface.hh index ef936f1b92e5c407c8a82b77e4e15cc69022d38d..208b2b6e219305642653bf797413ea1f243e574d 100644 --- a/dumux/io/gnuplotinterface.hh +++ b/dumux/io/gnuplotinterface.hh @@ -24,6 +24,9 @@ * * The data sets for a specific window have to be passed by the addDataSet function * and then plotted by using the plot function. + * + * \todo the use of the plottingWindowNumber in each function could be replaced, but + * a new GnuplotInterface object has to be created for each plot */ #ifndef HAVE_GNUPLOT @@ -67,6 +70,8 @@ public: xRangeMin_(0), xRangeMax_(0), yRangeMin_(0), yRangeMax_(0), xLabel_(0), yLabel_(0), + options_(0), + datafileSeparator_(0), gnuplotPath_(GNUPLOT_EXECUTABLE), terminalType_("wxt"), numberOfGnuplotWindows_(8+1) @@ -83,6 +88,8 @@ public: yRangeMax_.resize(numberOfGnuplotWindows_, -1e100); xLabel_.resize(numberOfGnuplotWindows_, ""); yLabel_.resize(numberOfGnuplotWindows_, ""); + options_.resize(numberOfGnuplotWindows_, ""); + datafileSeparator_.resize(numberOfGnuplotWindows_, ' '); } //! \brief The destructor @@ -102,22 +109,26 @@ public: const unsigned int plottingWindowNumber, bool interaction) { - // setting correct terminal - std::string plot = "set term "; - - if (interaction) - plot += "wxt " + numberToString(plottingWindowNumber) + "\n"; - else - plot += " pngcairo size 800,600\nset output \"" + title + ".png\"\n"; - - plot += "set yrange [" + numberToString(yRangeMin_[plottingWindowNumber]) - + ":" + numberToString(yRangeMax_[plottingWindowNumber]) + "]" + "\n"; - plot += "set xrange [" + numberToString(xRangeMin_[plottingWindowNumber]) - + ":" + numberToString(xRangeMax_[plottingWindowNumber]) + "]" + "\n"; - + // set correct terminal and general options + std::string plot = "reset\n"; + plot += "set datafile separator \'" + convertToString(datafileSeparator_[plottingWindowNumber]) + "\'\n"; + plot += "set term wxt " + convertToString(plottingWindowNumber) + "\n"; + if (xRangeMin_[plottingWindowNumber] < 1e100 || xRangeMax_[plottingWindowNumber] > -1e100) + { + plot += "set xrange [" + convertToString(xRangeMin_[plottingWindowNumber]) + + ":" + convertToString(xRangeMax_[plottingWindowNumber]) + "]" + "\n"; + } + if (yRangeMin_[plottingWindowNumber] < 1e100 || yRangeMax_[plottingWindowNumber] > -1e100) + { + plot += "set yrange [" + convertToString(yRangeMin_[plottingWindowNumber]) + + ":" + convertToString(yRangeMax_[plottingWindowNumber]) + "]" + "\n"; + } plot += "set xlabel \"" + xLabel_[plottingWindowNumber] + "\"\n"; plot += "set ylabel \"" + yLabel_[plottingWindowNumber] + "\"\n"; + // set user defined options + plot += options_[plottingWindowNumber] + "\n"; + // plot curves plot += "plot"; for (unsigned int i = 0; i < fileName_[plottingWindowNumber].size(); ++i) @@ -130,22 +141,28 @@ public: plot += "\n"; } - if (!interaction) + // live plot of the results if gnuplot is installed + if (interaction) { - std::string fileName = title + ".gp"; - std::ofstream file; - file.open(fileName); - file << plot; - file.close(); - } - #ifdef HAVE_GNUPLOT - executeGnuplot(plot.c_str()); + executeGnuplot(plot.c_str()); #endif + } + + // create a gnuplot file for output a png + plot += "\n"; + plot += "set term pngcairo size 800,600\n"; + plot += "set output \"" + title + ".png\"\n"; + plot += "replot\n"; + std::string fileName = title + ".gp"; + std::ofstream file; + file.open(fileName); + file << plot; + file.close(); } /*! - * \brief Deletes all plots from a plotting window + * \brief Deletes all plots from a plotting window and resets user-defined options * * \param plottingWindowNumber The ID of the specific plot */ @@ -154,6 +171,7 @@ public: fileName_[plottingWindowNumber].resize(0); plotOptions_[plottingWindowNumber].resize(0); plotName_[plottingWindowNumber].resize(0); + options_[plottingWindowNumber].resize(0); } /*! @@ -210,14 +228,14 @@ public: assert(x.size() == y.size()); //write data to file - std::string fileName = numberToString(plottingWindowNumber) + "_" + plotName + ".dat"; + std::string fileName = convertToString(plottingWindowNumber) + "_" + plotName + ".dat"; std::ofstream file; file.open(fileName); for (unsigned int i = 0; i < x.size(); i++) { - checkNumber(x[i], "x[i] i=" + numberToString(i) + " in " + fileName); - checkNumber(y[i], "y[i] i=" + numberToString(i) + " in " + fileName); - file << x[i] << " " << y[i] << std::endl; + checkNumber(x[i], "x[i] i=" + convertToString(i) + " in " + fileName); + checkNumber(y[i], "y[i] i=" + convertToString(i) + " in " + fileName); + file << x[i] << datafileSeparator_[plottingWindowNumber] << y[i] << std::endl; } file.close(); @@ -281,6 +299,30 @@ public: yRangeMax_[plottingWindowNumber] = std::max(yRangeMax_[plottingWindowNumber], upperEnd); } + /*! + * \brief Sets additional user-defined options + * + * \param option Additional line of option in gnuplot language + * \param plottingWindowNumber The ID of the specific plot + */ + void setOption(std::string option, + const unsigned int plottingWindowNumber) + { + options_[plottingWindowNumber] += option + "\n"; + } + + /*! + * \brief Sets the datafile separator + * + * \param separator The separator sign between two data columns + * \param plottingWindowNumber The ID of the specific plot + */ + void setDatafileSeparator(char separator, + const unsigned int plottingWindowNumber) + { + datafileSeparator_[plottingWindowNumber] = separator; + } + /*! * \brief Sets the plotting style for the data sets * @@ -328,11 +370,12 @@ private: Dune::dwarn << "warning: " << text << " is infinity, adjust your data range" << std::endl; } - // Convert number to string - template<class T> std::string numberToString(const T number) const + // Convert number or character to string + template<class T> + std::string convertToString(const T input) const { std::ostringstream stream; - stream << number; + stream << input; return stream.str(); } @@ -347,6 +390,8 @@ private: std::vector<Scalar> yRangeMax_; StringVector xLabel_; StringVector yLabel_; + StringVector options_; + std::vector<char> datafileSeparator_; std::string gnuplotPath_; std::string terminalType_; const unsigned int numberOfGnuplotWindows_; diff --git a/dumux/io/plotoverline2d.hh b/dumux/io/plotoverline2d.hh index 2f7dbcc428638f33306fb51308cadd9d2ae85cb0..afef3aa1c67a36ae50ff3bd3f0d4afbabfd700d9 100644 --- a/dumux/io/plotoverline2d.hh +++ b/dumux/io/plotoverline2d.hh @@ -99,10 +99,30 @@ public: * so they can be read in by another program like matlab. * The file can be found by the extension: dat */ + DUNE_DEPRECATED_MSG("write() method has changed signature") void write(const Problem & problem, const GlobalPosition & pointOne, const GlobalPosition & pointTwo, const std::string appendOutputName = "") + { + write(problem, pointOne, pointTwo, true, appendOutputName); + } + + /*! + * \brief A function that writes results over a line (like paraview's plotOverline into a text file.) + * + * The writer needs to be called in postTimeStep(). + * + * This function puts output variables (TemperaturePhase, Saturation, t, tIndex, ...) + * over space (1D, over a line) into a text file, + * so they can be read in by another program like matlab. + * The file can be found by the extension: dat + */ + void write(const Problem & problem, + const GlobalPosition & pointOne, + const GlobalPosition & pointTwo, + const bool appendData, + const std::string appendOutputName = "") { static_assert(dim==2, "this implements plot over Line: so far this works only for 2D"); @@ -116,6 +136,28 @@ public: std::vector<bool> isVisited(numGlobalVerts); std::fill(isVisited.begin(), isVisited.end(), false); + + // filename of the output file + std::string fileName = problem.name(); + fileName += appendOutputName; + fileName += ".dat"; + std::ofstream dataFile; + const unsigned int timeStepIndex = problem.timeManager().timeStepIndex(); + + // Writing a header into the output + if (timeStepIndex == 0 || !appendData) + { + dataFile.open(fileName.c_str()); + dataFile << "# This is a DuMuX output file for further processing with the preferred graphics program of your choice. \n"; + + dataFile << "# This output file was written from "<< __FILE__ << ", line " <<__LINE__ << "\n"; + dataFile << "# This output file was generated from code compiled at " << __TIME__ <<", "<< __DATE__<< "\n"; + dataFile << "\n"; + dataFile << "# Header\n"; + dataFile << "#timestep time x y Sw Tw Tn Ts xH2On xH2OnEquil xN2w xN2wEquil\n"; + dataFile.close(); + } + // Looping over all elements of the domain ElementIterator eEndIt = problem.gridView().template end<0>(); for (ElementIterator eIt = problem.gridView().template begin<0>() ; eIt != eEndIt; ++eIt) @@ -145,31 +187,6 @@ public: const GlobalPosition & globalPosCurrent = fvGeometry.subContVol[scvIdx].global; - std::ofstream dataFile; - const unsigned int timeStepIndex = problem.timeManager().timeStepIndex() ; - - // filename of the output file - std::string fileName = problem.name(); - - // filename consists of problem name + some function argument + .dat - // this way several plot overlines can be written from one simulation - fileName += appendOutputName; - fileName +=".dat"; - - // Writing a header into the output - if (timeStepIndex == 0) - { - dataFile.open(fileName.c_str()); - dataFile << "# This is a DuMuX output file for further processing with the preferred graphics program of your choice. \n"; - - dataFile << "# This output file was written from "<< __FILE__ << ", line " <<__LINE__ << "\n"; - dataFile << "# This output file was generated from code compiled at " << __TIME__ <<", "<< __DATE__<< "\n"; - dataFile << "\n"; - dataFile << "# Header\n"; - dataFile << "#timestep\t time\t\t \t\t x \t\t y \t\tSw \t\t\t Tw\t\t Tn\t Ts \t xH2On \t xH2OnEquil \t xN2w \txN2wEquil\n"; - dataFile.close(); - } - // write output if the current location is between two specified points if (isBetween(globalPosCurrent, pointOne, pointTwo)) { @@ -186,24 +203,24 @@ public: // actual output into the text file // This could be done much more efficiently // if writing to the text file would be done all at once. - dataFile.open(fileName.c_str() , std::ios::app); + dataFile.open(fileName.c_str(), std::ios::app); dataFile << timeStepIndex - <<"\t\t\t" + <<" " << time - << "\t\t\t" + << " " << globalPosCurrent[0] - << "\t\t\t" + << " " << globalPosCurrent[1]; - dataFile <<"\t\t\t" + dataFile <<" " << saturationW - <<"\t\t" << Tw - <<"\t\t" << Tn - <<"\t\t" << Ts - <<"\t\t" << xH2On - <<"\t\t" << xH2OnEquil - <<"\t\t" << xN2w - <<"\t\t" << xN2wEquil + <<" " << Tw + <<" " << Tn + <<" " << Ts + <<" " << xH2On + <<" " << xH2OnEquil + <<" " << xN2w + <<" " << xN2wEquil ; dataFile <<"\n"; dataFile.close(); diff --git a/test/implicit/mpnc/evaporationatmosphereproblem.hh b/test/implicit/mpnc/evaporationatmosphereproblem.hh index e520f1a898e20a5cd59f1b7f6156cb7eb2da3f86..5b4338d40645d22ef4650ca337d967abc7253d22 100644 --- a/test/implicit/mpnc/evaporationatmosphereproblem.hh +++ b/test/implicit/mpnc/evaporationatmosphereproblem.hh @@ -61,6 +61,7 @@ #include <dumux/implicit/mpnc/velomodelnewtoncontroller.hh> #include <dumux/material/fluidsystems/h2on2fluidsystemkinetic.hh> +#include <dumux/io/gnuplotinterface.hh> #include <dumux/io/plotoverline2d.hh> #include <dumux/material/fluidstates/nonequilibriumfluidstate.hh> @@ -327,6 +328,7 @@ public: writerDepth.write(*this, pointDepthOne, pointDepthTwo, + false, /* do not append data*/ "plotOverLineIntoDepth"); // Calculate storage terms of the individual phases @@ -358,6 +360,20 @@ public: <<"Storage total: [" << storage << "]" << "\n"; } + + // use gnuplot for plotting the line data + unsigned int windowNumber = 0; + gnuplot_.reset(windowNumber); + gnuplot_.setXlabel("xN2w [-]", windowNumber); + gnuplot_.setYlabel("y [m]", windowNumber); + std::ostringstream stream; + stream << this->timeManager().time(); + gnuplot_.setOption("set label 'at time " + stream.str() + "' at screen 0.15,0.90 left", windowNumber); + gnuplot_.setDatafileSeparator(' ', windowNumber); + std::string fileName = outputName_ + "plotOverLineIntoDepth.dat"; + gnuplot_.addFileToPlot(fileName, fileName, + windowNumber, " u 11:4 w l"); + gnuplot_.plot("plot", windowNumber, true); } /*! @@ -765,6 +781,7 @@ private: Scalar pnInjection_; Dune::ParameterTree inputParameters_; Scalar x_[numPhases][numComponents] ; + Dumux::GnuplotInterface<Scalar> gnuplot_; Scalar TInject_; diff --git a/test/io/gnuplotinterface/test_gnuplotinterface.cc b/test/io/gnuplotinterface/test_gnuplotinterface.cc index 9a9279c1d58f74f95ba22ddf028e999134703bff..ca3793e3f18c22cc46da6ce783e1e0b1dbe661f0 100644 --- a/test/io/gnuplotinterface/test_gnuplotinterface.cc +++ b/test/io/gnuplotinterface/test_gnuplotinterface.cc @@ -55,6 +55,9 @@ int main() gnuplot.setYRange(yMin, yMax, windowNumber); gnuplot.setXlabel("x [-]", windowNumber); gnuplot.setYlabel("f(x) [-]", windowNumber); + gnuplot.setDatafileSeparator(',', windowNumber); + gnuplot.setOption("set arrow from 0,0 to 2,20 head filled lc rgb 'dark-gray'", windowNumber); + gnuplot.setOption("set label 'arrow' at 1,15 center tc rgb 'dark-gray'", windowNumber); gnuplot.addDataSetToPlot(x, y, "dataSet_f(x)=x^2", windowNumber, "every 5 w lp ps 2"); gnuplot.addFunctionToPlot("x**3", "function_f(x)=x^3", windowNumber); gnuplot.addFileToPlot("0_dataSet_f(x)=x^2.dat", "file_f(x)=x^2.dat", windowNumber);