$extrastylesheet
gnuplot_io.C
Go to the documentation of this file.
00001 // The libMesh Finite Element Library.
00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
00003 
00004 // This library is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public
00006 // License as published by the Free Software Foundation; either
00007 // version 2.1 of the License, or (at your option) any later version.
00008 
00009 // This library is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // Lesser General Public License for more details.
00013 
00014 // You should have received a copy of the GNU Lesser General Public
00015 // License along with this library; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018 // C++ includes
00019 #include <fstream>
00020 #include <sstream>
00021 #include <map>
00022 
00023 // Local includes
00024 #include "libmesh/elem.h"
00025 #include "libmesh/libmesh_logging.h"
00026 #include "libmesh/mesh_base.h"
00027 #include "libmesh/gnuplot_io.h"
00028 
00029 namespace libMesh
00030 {
00031 
00032 GnuPlotIO::GnuPlotIO(const MeshBase& mesh_in,
00033                      const std::string& title,
00034                      int mesh_properties)
00035   :
00036   MeshOutput<MeshBase> (mesh_in),
00037   _title(title)
00038 {
00039   _grid       = (mesh_properties & GRID_ON);
00040   _png_output = (mesh_properties & PNG_OUTPUT);
00041 }
00042 
00043 void GnuPlotIO::write(const std::string& fname)
00044 {
00045   this->write_solution(fname);
00046 }
00047 
00048 void GnuPlotIO::write_nodal_data (const std::string& fname,
00049                                   const std::vector<Number>& soln,
00050                                   const std::vector<std::string>& names)
00051 {
00052   START_LOG("write_nodal_data()", "GnuPlotIO");
00053 
00054   this->write_solution(fname, &soln, &names);
00055 
00056   STOP_LOG("write_nodal_data()", "GnuPlotIO");
00057 }
00058 
00059 
00060 
00061 
00062 void GnuPlotIO::write_solution(const std::string& fname,
00063                                const std::vector<Number>* soln,
00064                                const std::vector<std::string>* names)
00065 {
00066   // Even when writing on a serialized ParallelMesh, we expect
00067   // non-proc-0 help with calls like n_active_elem
00068   // libmesh_assert_equal_to (this->mesh().processor_id(), 0);
00069 
00070   const MeshBase& the_mesh = MeshOutput<MeshBase>::mesh();
00071 
00072   dof_id_type n_active_elem = the_mesh.n_active_elem();
00073 
00074   if (this->mesh().processor_id() == 0)
00075     {
00076       std::stringstream data_stream_name;
00077       data_stream_name << fname << "_data";
00078       const std::string data_file_name = data_stream_name.str();
00079 
00080       // This class is designed only for use with 1D meshes
00081       libmesh_assert_equal_to (the_mesh.mesh_dimension(), 1);
00082 
00083       // Make sure we have a solution to plot
00084       libmesh_assert ((names != NULL) && (soln != NULL));
00085 
00086       // Create an output stream for script file
00087       std::ofstream out_stream(fname.c_str());
00088 
00089       // Make sure it opened correctly
00090       if (!out_stream.good())
00091         libmesh_file_error(fname.c_str());
00092 
00093       // The number of variables in the equation system
00094       const unsigned int n_vars =
00095         cast_int<unsigned int>(names->size());
00096 
00097       // Write header to stream
00098       out_stream << "# This file was generated by gnuplot_io.C\n"
00099                  << "# Stores 1D solution data in GNUplot format\n"
00100                  << "# Execute this by loading gnuplot and typing "
00101                  << "\"call '" << fname << "'\"\n"
00102                  << "reset\n"
00103                  << "set title \"" << _title << "\"\n"
00104                  << "set xlabel \"x\"\n"
00105                  << "set xtics nomirror\n";
00106 
00107       // Loop over the elements to find the minimum and maximum x values,
00108       // and also to find the element boundaries to write out as xtics
00109       // if requested.
00110       Real x_min=0., x_max=0.;
00111 
00112       // construct string for xtic positions at element edges
00113       std::stringstream xtics_stream;
00114 
00115       MeshBase::const_element_iterator it = the_mesh.active_elements_begin();
00116       const MeshBase::const_element_iterator end_it =
00117         the_mesh.active_elements_end();
00118 
00119       unsigned int count = 0;
00120 
00121       for( ; it != end_it; ++it)
00122         {
00123           const Elem* el = *it;
00124 
00125           // if el is the left edge of the mesh, print its left node position
00126           if(el->neighbor(0) == NULL)
00127             {
00128               x_min = (*(el->get_node(0)))(0);
00129               xtics_stream << "\"\" " << x_min << ", \\\n";
00130             }
00131           if(el->neighbor(1) == NULL)
00132             {
00133               x_max = (*(el->get_node(1)))(0);
00134             }
00135           xtics_stream << "\"\" " << (*(el->get_node(1)))(0);
00136 
00137           if(count+1 != n_active_elem)
00138             {
00139               xtics_stream << ", \\\n";
00140             }
00141           count++;
00142         }
00143 
00144       out_stream << "set xrange [" << x_min << ":" << x_max << "]\n";
00145 
00146       if(_grid)
00147         out_stream << "set x2tics (" << xtics_stream.str() << ")\nset grid noxtics noytics x2tics\n";
00148 
00149       if(_png_output)
00150         {
00151           out_stream << "set terminal png\n";
00152           out_stream << "set output \"" << fname << ".png\"\n";
00153         }
00154 
00155       out_stream << "plot "
00156                  << axes_limits
00157                  << " \"" << data_file_name << "\" using 1:2 title \"" << (*names)[0]
00158                  << "\" with lines";
00159       if(n_vars > 1)
00160         {
00161           for(unsigned int i=1; i<n_vars; i++)
00162             {
00163               out_stream << ", \\\n\"" << data_file_name << "\" using 1:" << i+2
00164                          << " title \"" << (*names)[i] << "\" with lines";
00165             }
00166         }
00167 
00168       out_stream.close();
00169 
00170 
00171       // Create an output stream for data file
00172       std::ofstream data(data_file_name.c_str());
00173 
00174       if (!data.good())
00175         libmesh_error_msg("ERROR: opening output data file " << data_file_name);
00176 
00177       // get ordered nodal data using a map
00178       typedef std::pair<Real, std::vector<Number> > key_value_pair;
00179       typedef std::map<Real, std::vector<Number> > map_type;
00180       typedef map_type::iterator map_iterator;
00181 
00182       map_type node_map;
00183 
00184 
00185       it  = the_mesh.active_elements_begin();
00186 
00187       for ( ; it != end_it; ++it)
00188         {
00189           const Elem* elem = *it;
00190 
00191           for(unsigned int i=0; i<elem->n_nodes(); i++)
00192             {
00193               std::vector<Number> values;
00194 
00195               // Get the global id of the node
00196               dof_id_type global_id = elem->node(i);
00197 
00198               for(unsigned int c=0; c<n_vars; c++)
00199                 {
00200                   values.push_back( (*soln)[global_id*n_vars + c] );
00201                 }
00202 
00203               node_map[ the_mesh.point(global_id)(0) ] = values;
00204             }
00205         }
00206 
00207 
00208       map_iterator map_it = node_map.begin();
00209       const map_iterator end_map_it = node_map.end();
00210 
00211       for( ; map_it != end_map_it; ++map_it)
00212         {
00213           key_value_pair kvp = *map_it;
00214           std::vector<Number> values = kvp.second;
00215 
00216           data << kvp.first << "\t";
00217 
00218           for(unsigned int i=0; i<values.size(); i++)
00219             {
00220               data << values[i] << "\t";
00221             }
00222 
00223           data << "\n";
00224         }
00225 
00226       data.close();
00227     }
00228 }
00229 
00230 } // namespace libMesh