$extrastylesheet
gmv_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 // Changes:
00019 // o no more subelements, all elements are written down to GMV directly
00020 // o Some nodes have to be left out, eg node 8 in QUAD9
00021 // o
00022 
00023 
00024 // C++ includes
00025 #include <iomanip>
00026 #include <fstream>
00027 #include <cstring> // for std::strcpy, std::memcpy
00028 #include <cstdio>  // for std::sprintf
00029 #include <vector>
00030 
00031 // Local includes
00032 #include "libmesh/libmesh_config.h"
00033 #include "libmesh/libmesh_logging.h"
00034 #include "libmesh/gmv_io.h"
00035 #include "libmesh/mesh_base.h"
00036 #include "libmesh/elem.h"
00037 #include "libmesh/equation_systems.h"
00038 #include "libmesh/numeric_vector.h"
00039 #include "libmesh/string_to_enum.h"
00040 
00041 // Wrap everything in a GMVLib namespace and
00042 // use extern "C" to avoid name mangling.
00043 #ifdef LIBMESH_HAVE_GMV
00044 namespace GMVLib
00045 {
00046 extern "C"
00047 {
00048 #include "gmvread.h"
00049 }
00050 }
00051 #endif
00052 
00053 // anonymous namespace to hold local data
00054 namespace
00055 {
00056 using namespace libMesh;
00057 
00066 struct ElementDefinition {
00067   // GMV element name
00068   std::string label;
00069 
00070   // Used to map libmesh nodes to GMV for writing
00071   std::vector<unsigned> node_map;
00072 };
00073 
00074 
00075 // maps from a libMesh element type to the proper GMV
00076 // ElementDefinition.  Placing the data structure here in this
00077 // anonymous namespace gives us the benefits of a global variable
00078 // without the nasty side-effects.
00079 std::map<ElemType, ElementDefinition> eletypes;
00080 
00081 // Helper function to fill up eletypes map
00082 void add_eletype_entry(ElemType libmesh_elem_type,
00083                        const unsigned* node_map,
00084                        const std::string& gmv_label,
00085                        unsigned nodes_size )
00086 {
00087   // If map entry does not exist, this will create it
00088   ElementDefinition& map_entry = eletypes[libmesh_elem_type];
00089 
00090   // Set the label
00091   map_entry.label = gmv_label;
00092 
00093   // Use the "swap trick" from Scott Meyer's "Effective STL" to swap
00094   // an unnamed temporary vector into the map_entry's vector.  Note:
00095   // the vector(iter, iter) constructor is used.
00096   std::vector<unsigned int>(node_map,
00097                             node_map+nodes_size).swap(map_entry.node_map);
00098 }
00099 
00100 
00101 // ------------------------------------------------------------
00102 // helper function to initialize the eletypes map
00103 void init_eletypes ()
00104 {
00105   if (eletypes.empty())
00106     {
00107       // This should happen only once.  The first time this method
00108       // is called the eletypes data struture will be empty, and
00109       // we will fill it.  Any subsequent calls will find an initialized
00110       // eletypes map and will do nothing.
00111 
00112       // EDGE2
00113       {
00114         const unsigned int node_map[] = {0,1};
00115         add_eletype_entry(EDGE2, node_map, "line 2", 2);
00116       }
00117 
00118       // LINE3
00119       {
00120         const unsigned int node_map[] = {0,1,2};
00121         add_eletype_entry(EDGE3, node_map, "3line 3", 3);
00122       }
00123 
00124       // TRI3
00125       {
00126         const unsigned int node_map[] = {0,1,2};
00127         add_eletype_entry(TRI3, node_map, "tri3 3", 3);
00128       }
00129 
00130       // TRI6
00131       {
00132         const unsigned int node_map[] = {0,1,2,3,4,5};
00133         add_eletype_entry(TRI6, node_map, "6tri 6", 6);
00134       }
00135 
00136       // QUAD4
00137       {
00138         const unsigned int node_map[] = {0,1,2,3};
00139         add_eletype_entry(QUAD4, node_map, "quad 4", 4);
00140       }
00141 
00142       // QUAD8, QUAD9
00143       {
00144         const unsigned int node_map[] = {0,1,2,3,4,5,6,7};
00145         add_eletype_entry(QUAD8, node_map, "8quad 8", 8);
00146 
00147         // QUAD9 was not supported by GMV but it gets the same entry, even the label (is that correct?)
00148         eletypes[QUAD9] = eletypes[QUAD8];
00149       }
00150 
00151       // HEX8
00152       {
00153         const unsigned int node_map[] = {0,1,2,3,4,5,6,7};
00154         add_eletype_entry(HEX8, node_map, "phex8 8", 8);
00155       }
00156 
00157       // HEX20, HEX27
00158       {
00159         // Note: This map is its own inverse
00160         const unsigned int node_map[] = {0,1,2,3,4,5,6,7,8,9,10,11,16,17,18,19,12,13,14,15};
00161         add_eletype_entry(HEX20, node_map, "phex20 20", 20);
00162 
00163         // HEX27 was not supported by GMV but it gets the same entry, even the label (is that correct?)
00164         eletypes[HEX27] = eletypes[HEX20];
00165       }
00166 
00167       // TET4
00168       {
00169         // This is correct, see write_ascii_old_impl() to confirm.
00170         // This map is also its own inverse.
00171         const unsigned node_map[] = {0,2,1,3};
00172         add_eletype_entry(TET4, node_map, "tet 4", 4);
00173       }
00174 
00175       // TET10
00176       {
00177         const unsigned int node_map[] = {0,1,2,3,4,5,6,7,8,9};
00178         add_eletype_entry(TET10, node_map, "ptet10 10", 10);
00179       }
00180 
00181       // PRISM6
00182       {
00183         const unsigned int node_map[] = {0,1,2,3,4,5};
00184         add_eletype_entry(PRISM6, node_map, "pprism6 6", 6);
00185       }
00186 
00187       // PRISM15, PRISM18
00188       {
00189         // Note: This map is its own inverse
00190         const unsigned int node_map[] = {0,1,2,3,4,5,6,7,8,12,13,14, 9,10,11};
00191         add_eletype_entry(PRISM15, node_map, "pprism15 15", 15);
00192 
00193         // PRISM18 was not supported by GMV but it gets the same entry, even the label (is that correct?)
00194         eletypes[PRISM18] = eletypes[PRISM15];
00195       }
00196       //==============================
00197     }
00198 }
00199 
00200 } // end anonymous namespace
00201 
00202 
00203 namespace libMesh
00204 {
00205 
00206 // ------------------------------------------------------------
00207 // GMVIO  members
00208 void GMVIO::write (const std::string& fname)
00209 {
00210   if (this->binary())
00211     this->write_binary (fname);
00212   else
00213     this->write_ascii_old_impl  (fname);
00214 }
00215 
00216 
00217 
00218 void GMVIO::write_nodal_data (const std::string& fname,
00219                               const std::vector<Number>& soln,
00220                               const std::vector<std::string>& names)
00221 {
00222   START_LOG("write_nodal_data()", "GMVIO");
00223 
00224   if (this->binary())
00225     this->write_binary (fname, &soln, &names);
00226   else
00227     this->write_ascii_old_impl  (fname, &soln, &names);
00228 
00229   STOP_LOG("write_nodal_data()", "GMVIO");
00230 }
00231 
00232 
00233 
00234 void GMVIO::write_ascii_new_impl (const std::string& fname,
00235                                   const std::vector<Number>* v,
00236                                   const std::vector<std::string>* solution_names)
00237 {
00238 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
00239 
00240   libMesh::err << "WARNING:  GMVIO::write_ascii_new_impl() not infinite-element aware!"
00241                << std::endl;
00242   libmesh_here();
00243 
00244   // Set it to our current precision
00245   this->write_ascii_old_impl (fname, v, solution_names);
00246 
00247 #else
00248 
00249   // Get a reference to the mesh
00250   const MeshBase& mesh = MeshOutput<MeshBase>::mesh();
00251 
00252   // This is a parallel_only function
00253   const unsigned int n_active_elem = mesh.n_active_elem();
00254 
00255   if (MeshOutput<MeshBase>::mesh().processor_id() != 0)
00256     return;
00257 
00258   // Open the output file stream
00259   std::ofstream out_stream (fname.c_str());
00260 
00261   out_stream << std::setprecision(this->ascii_precision());
00262 
00263   // Make sure it opened correctly
00264   if (!out_stream.good())
00265     libmesh_file_error(fname.c_str());
00266 
00267   unsigned int mesh_max_p_level = 0;
00268 
00269   // Begin interfacing with the GMV data file
00270   {
00271     out_stream << "gmvinput ascii\n\n";
00272 
00273     // write the nodes
00274     out_stream << "nodes " << mesh.n_nodes() << "\n";
00275     for (unsigned int n=0; n<mesh.n_nodes(); n++)
00276       out_stream << mesh.point(n)(0) << " ";
00277     out_stream << "\n";
00278 
00279     for (unsigned int n=0; n<mesh.n_nodes(); n++)
00280 #if LIBMESH_DIM > 1
00281       out_stream << mesh.point(n)(1) << " ";
00282 #else
00283     out_stream << 0. << " ";
00284 #endif
00285     out_stream << "\n";
00286 
00287     for (unsigned int n=0; n<mesh.n_nodes(); n++)
00288 #if LIBMESH_DIM > 2
00289       out_stream << mesh.point(n)(2) << " ";
00290 #else
00291     out_stream << 0. << " ";
00292 #endif
00293     out_stream << "\n\n";
00294   }
00295 
00296   {
00297     // write the connectivity
00298     out_stream << "cells " << n_active_elem << "\n";
00299 
00300     // initialize the eletypes map (eletypes is a file-global variable)
00301     init_eletypes();
00302 
00303     MeshBase::const_element_iterator       it  = mesh.active_elements_begin();
00304     const MeshBase::const_element_iterator end = mesh.active_elements_end();
00305 
00306     for ( ; it != end; ++it)
00307       {
00308         const Elem* elem = *it;
00309 
00310         mesh_max_p_level = std::max(mesh_max_p_level,
00311                                     elem->p_level());
00312 
00313         // Make sure we have a valid entry for
00314         // the current element type.
00315         libmesh_assert (eletypes.count(elem->type()));
00316 
00317         const ElementDefinition& ele = eletypes[elem->type()];
00318 
00319         // The element mapper better not require any more nodes
00320         // than are present in the current element!
00321         libmesh_assert_less_equal (ele.node_map.size(), elem->n_nodes());
00322 
00323         out_stream << ele.label << "\n";
00324         for (unsigned int i=0; i < ele.node_map.size(); i++)
00325           out_stream << elem->node(ele.node_map[i])+1 << " ";
00326         out_stream << "\n";
00327       }
00328     out_stream << "\n";
00329   }
00330 
00331   // optionally write the partition information
00332   if (this->partitioning())
00333     {
00334       if (this->write_subdomain_id_as_material())
00335         libmesh_error_msg("Not yet supported in GMVIO::write_ascii_new_impl");
00336 
00337       else // write processor IDs as materials.  This is the default
00338         {
00339           out_stream << "material "
00340                      << mesh.n_partitions()
00341             // Note: GMV may give you errors like
00342             // Error, material for cell 1 is greater than 1
00343             // Error, material for cell 2 is greater than 1
00344             // Error, material for cell 3 is greater than 1
00345             // ... because you put the wrong number of partitions here.
00346             // To ensure you write the correct number of materials, call
00347             // mesh.recalculate_n_partitions() before writing out the
00348             // mesh.
00349             // Note: we can't call it now because the Mesh is const here and
00350             // it is a non-const function.
00351                      << " 0\n";
00352 
00353           for (unsigned int proc=0; proc<mesh.n_partitions(); proc++)
00354             out_stream << "proc_" << proc << "\n";
00355 
00356           MeshBase::const_element_iterator       it  = mesh.active_elements_begin();
00357           const MeshBase::const_element_iterator end = mesh.active_elements_end();
00358 
00359           // FIXME - don't we need to use an ElementDefinition here? - RHS
00360           for ( ; it != end; ++it)
00361             out_stream << (*it)->processor_id()+1 << "\n";
00362           out_stream << "\n";
00363         }
00364     }
00365 
00366   // If there are *any* variables at all in the system (including
00367   // p level, or arbitrary cell-based data)
00368   // to write, the gmv file needs to contain the word "variable"
00369   // on a line by itself.
00370   bool write_variable = false;
00371 
00372   // 1.) p-levels
00373   if (this->p_levels() && mesh_max_p_level)
00374     write_variable = true;
00375 
00376   // 2.) solution data
00377   if ((solution_names != NULL) && (v != NULL))
00378     write_variable = true;
00379 
00380   // 3.) cell-centered data
00381   if ( !(this->_cell_centered_data.empty()) )
00382     write_variable = true;
00383 
00384   if (write_variable)
00385     out_stream << "variable\n";
00386 
00387   //   if ((this->p_levels() && mesh_max_p_level) ||
00388   //     ((solution_names != NULL) && (v != NULL)))
00389   //     out_stream << "variable\n";
00390 
00391   // optionally write the polynomial degree information
00392   if (this->p_levels() && mesh_max_p_level)
00393     {
00394       out_stream << "p_level 0\n";
00395 
00396       MeshBase::const_element_iterator       it  = mesh.active_elements_begin();
00397       const MeshBase::const_element_iterator end = mesh.active_elements_end();
00398 
00399       for ( ; it != end; ++it)
00400         {
00401           const Elem* elem = *it;
00402 
00403           const ElementDefinition& ele = eletypes[elem->type()];
00404 
00405           // The element mapper better not require any more nodes
00406           // than are present in the current element!
00407           libmesh_assert_less_equal (ele.node_map.size(), elem->n_nodes());
00408 
00409           for (unsigned int i=0; i < ele.node_map.size(); i++)
00410             out_stream << elem->p_level() << " ";
00411         }
00412       out_stream << "\n\n";
00413     }
00414 
00415 
00416   // optionally write cell-centered data
00417   if ( !(this->_cell_centered_data.empty()) )
00418     {
00419       std::map<std::string, const std::vector<Real>* >::iterator       it  = this->_cell_centered_data.begin();
00420       const std::map<std::string, const std::vector<Real>* >::iterator end = this->_cell_centered_data.end();
00421 
00422       for (; it != end; ++it)
00423         {
00424           // write out the variable name, followed by a zero.
00425           out_stream << (*it).first << " 0\n";
00426 
00427           const std::vector<Real>* the_array = (*it).second;
00428 
00429           // Loop over active elements, write out cell data.  If second-order cells
00430           // are split into sub-elements, the sub-elements inherit their parent's
00431           // cell-centered data.
00432           MeshBase::const_element_iterator       elem_it  = mesh.active_elements_begin();
00433           const MeshBase::const_element_iterator elem_end = mesh.active_elements_end();
00434 
00435           for (; elem_it != elem_end; ++elem_it)
00436             {
00437               const Elem* e = *elem_it;
00438 
00439               // Use the element's ID to find the value.
00440               libmesh_assert_less (e->id(), the_array->size());
00441               const Real the_value = the_array->operator[](e->id());
00442 
00443               if (this->subdivide_second_order())
00444                 for (unsigned int se=0; se < e->n_sub_elem(); se++)
00445                   out_stream << the_value << " ";
00446               else
00447                 out_stream << the_value << " ";
00448             }
00449 
00450           out_stream << "\n\n";
00451         }
00452     }
00453 
00454 
00455   // optionally write the data
00456   if ((solution_names != NULL) && (v != NULL))
00457     {
00458       const unsigned int n_vars = solution_names->size();
00459 
00460       if (!(v->size() == mesh.n_nodes()*n_vars))
00461         libMesh::err << "ERROR: v->size()=" << v->size()
00462                      << ", mesh.n_nodes()=" << mesh.n_nodes()
00463                      << ", n_vars=" << n_vars
00464                      << ", mesh.n_nodes()*n_vars=" << mesh.n_nodes()*n_vars
00465                      << "\n";
00466 
00467       libmesh_assert_equal_to (v->size(), mesh.n_nodes()*n_vars);
00468 
00469       for (unsigned int c=0; c<n_vars; c++)
00470         {
00471 
00472 #ifdef LIBMESH_USE_COMPLEX_NUMBERS
00473 
00474           // in case of complex data, write _three_ data sets
00475           // for each component
00476 
00477           // this is the real part
00478           out_stream << "r_" << (*solution_names)[c] << " 1\n";
00479 
00480           for (unsigned int n=0; n<mesh.n_nodes(); n++)
00481             out_stream << (*v)[n*n_vars + c].real() << " ";
00482 
00483           out_stream << "\n\n";
00484 
00485           // this is the imaginary part
00486           out_stream << "i_" << (*solution_names)[c] << " 1\n";
00487 
00488           for (unsigned int n=0; n<mesh.n_nodes(); n++)
00489             out_stream << (*v)[n*n_vars + c].imag() << " ";
00490 
00491           out_stream << "\n\n";
00492 
00493           // this is the magnitude
00494           out_stream << "a_" << (*solution_names)[c] << " 1\n";
00495           for (unsigned int n=0; n<mesh.n_nodes(); n++)
00496             out_stream << std::abs((*v)[n*n_vars + c]) << " ";
00497 
00498           out_stream << "\n\n";
00499 
00500 #else
00501 
00502           out_stream << (*solution_names)[c] << " 1\n";
00503 
00504           for (unsigned int n=0; n<mesh.n_nodes(); n++)
00505             out_stream << (*v)[n*n_vars + c] << " ";
00506 
00507           out_stream << "\n\n";
00508 
00509 #endif
00510         }
00511 
00512     }
00513 
00514   // If we wrote any variables, we have to close the variable section now
00515   if (write_variable)
00516     out_stream << "endvars\n";
00517 
00518 
00519   // end of the file
00520   out_stream << "\nendgmv\n";
00521 
00522 #endif
00523 }
00524 
00525 
00526 
00527 
00528 
00529 
00530 void GMVIO::write_ascii_old_impl (const std::string& fname,
00531                                   const std::vector<Number>* v,
00532                                   const std::vector<std::string>* solution_names)
00533 {
00534   // Get a reference to the mesh
00535   const MeshBase& mesh = MeshOutput<MeshBase>::mesh();
00536 
00537   // Use a MeshSerializer object to gather a parallel mesh before outputting it.
00538   // Note that we cast away constness here (which is bad), but the destructor of
00539   // the MeshSerializer object reparallelizes the Mesh, hopefully keeping it
00540   // "logically const" outside the context of this function...
00541   MeshSerializer serialize(const_cast<MeshBase&>(mesh),
00542                            !MeshOutput<MeshBase>::_is_parallel_format);
00543 
00544   // These are parallel_only functions
00545   const dof_id_type n_active_elem = mesh.n_active_elem(),
00546     n_active_sub_elem = mesh.n_active_sub_elem();
00547 
00548   if (MeshOutput<MeshBase>::mesh().processor_id() != 0)
00549     return;
00550 
00551   // Open the output file stream
00552   std::ofstream out_stream (fname.c_str());
00553 
00554   // Set it to our current precision
00555   out_stream << std::setprecision(this->ascii_precision());
00556 
00557   // Make sure it opened correctly
00558   if (!out_stream.good())
00559     libmesh_file_error(fname.c_str());
00560 
00561   // Make sure our nodes are contiguous and serialized
00562   libmesh_assert_equal_to (mesh.n_nodes(), mesh.max_node_id());
00563 
00564   // libmesh_assert (mesh.is_serial());
00565   // if (!mesh.is_serial())
00566   //   {
00567   //     if (MeshOutput<MeshBase>::mesh().processor_id() == 0)
00568   //       libMesh::err << "Error: GMVIO cannot yet write a ParallelMesh solution"
00569   //                     << std::endl;
00570   //     return;
00571   //   }
00572 
00573   unsigned int mesh_max_p_level = 0;
00574 
00575   // Begin interfacing with the GMV data file
00576 
00577   // FIXME - if subdivide_second_order() is off,
00578   // we probably should only be writing the
00579   // vertex nodes - RHS
00580   {
00581     // write the nodes
00582 
00583     out_stream << "gmvinput ascii\n\n";
00584     out_stream << "nodes " << mesh.n_nodes() << '\n';
00585     for (unsigned int n=0; n<mesh.n_nodes(); n++)
00586       out_stream << mesh.point(n)(0) << " ";
00587 
00588     out_stream << '\n';
00589 
00590     for (unsigned int n=0; n<mesh.n_nodes(); n++)
00591 #if LIBMESH_DIM > 1
00592       out_stream << mesh.point(n)(1) << " ";
00593 #else
00594     out_stream << 0. << " ";
00595 #endif
00596 
00597     out_stream << '\n';
00598 
00599     for (unsigned int n=0; n<mesh.n_nodes(); n++)
00600 #if LIBMESH_DIM > 2
00601       out_stream << mesh.point(n)(2) << " ";
00602 #else
00603     out_stream << 0. << " ";
00604 #endif
00605 
00606     out_stream << '\n' << '\n';
00607   }
00608 
00609 
00610 
00611   {
00612     // write the connectivity
00613 
00614     out_stream << "cells ";
00615     if (this->subdivide_second_order())
00616       out_stream << n_active_sub_elem;
00617     else
00618       out_stream << n_active_elem;
00619     out_stream << '\n';
00620 
00621     MeshBase::const_element_iterator       it  = mesh.active_elements_begin();
00622     const MeshBase::const_element_iterator end = mesh.active_elements_end();
00623 
00624     switch (mesh.mesh_dimension())
00625       {
00626       case 1:
00627         {
00628           // The same temporary storage will be used for each element
00629           std::vector<dof_id_type> conn;
00630 
00631           for ( ; it != end; ++it)
00632             {
00633               mesh_max_p_level = std::max(mesh_max_p_level,
00634                                           (*it)->p_level());
00635 
00636               if (this->subdivide_second_order())
00637                 for (unsigned int se=0; se<(*it)->n_sub_elem(); se++)
00638                   {
00639                     out_stream << "line 2\n";
00640                     (*it)->connectivity(se, TECPLOT, conn);
00641                     for (unsigned int i=0; i<conn.size(); i++)
00642                       out_stream << conn[i] << " ";
00643 
00644                     out_stream << '\n';
00645                   }
00646               else
00647                 {
00648                   out_stream << "line 2\n";
00649                   if ((*it)->default_order() == FIRST)
00650                     (*it)->connectivity(0, TECPLOT, conn);
00651                   else
00652                     {
00653                       UniquePtr<Elem> lo_elem = Elem::build(Elem::first_order_equivalent_type((*it)->type()));
00654                       for (unsigned int i = 0; i != lo_elem->n_nodes(); ++i)
00655                         lo_elem->set_node(i) = (*it)->get_node(i);
00656                       lo_elem->connectivity(0, TECPLOT, conn);
00657                     }
00658                   for (unsigned int i=0; i<conn.size(); i++)
00659                     out_stream << conn[i] << " ";
00660 
00661                   out_stream << '\n';
00662                 }
00663             }
00664           break;
00665         }
00666 
00667       case 2:
00668         {
00669           // The same temporary storage will be used for each element
00670           std::vector<dof_id_type> conn;
00671 
00672           for ( ; it != end; ++it)
00673             {
00674               mesh_max_p_level = std::max(mesh_max_p_level,
00675                                           (*it)->p_level());
00676 
00677               if (this->subdivide_second_order())
00678                 for (unsigned int se=0; se<(*it)->n_sub_elem(); se++)
00679                   {
00680                     // Quad elements
00681                     if (((*it)->type() == QUAD4) ||
00682                         ((*it)->type() == QUAD8) || // Note: QUAD8 will be output as one central quad and
00683                         // four surrounding triangles (though they will be written
00684                         // to GMV as QUAD4s).
00685                         ((*it)->type() == QUAD9)
00686 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
00687                         || ((*it)->type() == INFQUAD4)
00688                         || ((*it)->type() == INFQUAD6)
00689 #endif
00690                         )
00691                       {
00692                         out_stream << "quad 4\n";
00693                         (*it)->connectivity(se, TECPLOT, conn);
00694                         for (unsigned int i=0; i<conn.size(); i++)
00695                           out_stream << conn[i] << " ";
00696                       }
00697 
00698                     // Triangle elements
00699                     else if (((*it)->type() == TRI3) ||
00700                              ((*it)->type() == TRI6))
00701                       {
00702                         out_stream << "tri 3\n";
00703                         (*it)->connectivity(se, TECPLOT, conn);
00704                         for (unsigned int i=0; i<3; i++)
00705                           out_stream << conn[i] << " ";
00706                       }
00707                     else
00708                       libmesh_error_msg("Unsupported element type: " << Utility::enum_to_string((*it)->type()));
00709                   }
00710               else // !this->subdivide_second_order()
00711                 {
00712                   // Quad elements
00713                   if (((*it)->type() == QUAD4)
00714 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
00715                       || ((*it)->type() == INFQUAD4)
00716 #endif
00717                       )
00718                     {
00719                       (*it)->connectivity(0, TECPLOT, conn);
00720                       out_stream << "quad 4\n";
00721                       for (unsigned int i=0; i<conn.size(); i++)
00722                         out_stream << conn[i] << " ";
00723                     }
00724                   else if (((*it)->type() == QUAD8) ||
00725                            ((*it)->type() == QUAD9)
00726 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
00727                            || ((*it)->type() == INFQUAD6)
00728 #endif
00729                            )
00730                     {
00731                       UniquePtr<Elem> lo_elem = Elem::build(Elem::first_order_equivalent_type((*it)->type()));
00732                       for (unsigned int i = 0; i != lo_elem->n_nodes(); ++i)
00733                         lo_elem->set_node(i) = (*it)->get_node(i);
00734                       lo_elem->connectivity(0, TECPLOT, conn);
00735                       out_stream << "quad 4\n";
00736                       for (unsigned int i=0; i<conn.size(); i++)
00737                         out_stream << conn[i] << " ";
00738                     }
00739                   else if ((*it)->type() == TRI3)
00740                     {
00741                       (*it)->connectivity(0, TECPLOT, conn);
00742                       out_stream << "tri 3\n";
00743                       for (unsigned int i=0; i<3; i++)
00744                         out_stream << conn[i] << " ";
00745                     }
00746                   else if ((*it)->type() == TRI6)
00747                     {
00748                       UniquePtr<Elem> lo_elem = Elem::build(Elem::first_order_equivalent_type((*it)->type()));
00749                       for (unsigned int i = 0; i != lo_elem->n_nodes(); ++i)
00750                         lo_elem->set_node(i) = (*it)->get_node(i);
00751                       lo_elem->connectivity(0, TECPLOT, conn);
00752                       out_stream << "tri 3\n";
00753                       for (unsigned int i=0; i<3; i++)
00754                         out_stream << conn[i] << " ";
00755                     }
00756 
00757                   out_stream << '\n';
00758                 }
00759             }
00760 
00761           break;
00762         }
00763 
00764 
00765       case 3:
00766         {
00767           // The same temporary storage will be used for each element
00768           std::vector<dof_id_type> conn;
00769 
00770           for ( ; it != end; ++it)
00771             {
00772               mesh_max_p_level = std::max(mesh_max_p_level,
00773                                           (*it)->p_level());
00774 
00775               if (this->subdivide_second_order())
00776                 for (unsigned int se=0; se<(*it)->n_sub_elem(); se++)
00777                   {
00778 
00779 #ifndef  LIBMESH_ENABLE_INFINITE_ELEMENTS
00780                     if (((*it)->type() == HEX8)   ||
00781                         ((*it)->type() == HEX27))
00782                       {
00783                         out_stream << "phex8 8\n";
00784                         (*it)->connectivity(se, TECPLOT, conn);
00785                         for (unsigned int i=0; i<conn.size(); i++)
00786                           out_stream << conn[i] << " ";
00787                       }
00788 
00789                     else if ((*it)->type() == HEX20)
00790                       {
00791                         out_stream << "phex20 20\n";
00792                         out_stream << (*it)->node(0)+1  << " "
00793                                    << (*it)->node(1)+1  << " "
00794                                    << (*it)->node(2)+1  << " "
00795                                    << (*it)->node(3)+1  << " "
00796                                    << (*it)->node(4)+1  << " "
00797                                    << (*it)->node(5)+1  << " "
00798                                    << (*it)->node(6)+1  << " "
00799                                    << (*it)->node(7)+1  << " "
00800                                    << (*it)->node(8)+1  << " "
00801                                    << (*it)->node(9)+1  << " "
00802                                    << (*it)->node(10)+1 << " "
00803                                    << (*it)->node(11)+1 << " "
00804                                    << (*it)->node(16)+1 << " "
00805                                    << (*it)->node(17)+1 << " "
00806                                    << (*it)->node(18)+1 << " "
00807                                    << (*it)->node(19)+1 << " "
00808                                    << (*it)->node(12)+1 << " "
00809                                    << (*it)->node(13)+1 << " "
00810                                    << (*it)->node(14)+1 << " "
00811                                    << (*it)->node(15)+1 << " ";
00812                       }
00813 #else
00814                     /*
00815                      * In case of infinite elements, HEX20
00816                      * should be handled just like the
00817                      * INFHEX16, since these connect to each other
00818                      */
00819                     if (((*it)->type() == HEX8)     ||
00820                         ((*it)->type() == HEX27)    ||
00821                         ((*it)->type() == INFHEX8)  ||
00822                         ((*it)->type() == INFHEX16) ||
00823                         ((*it)->type() == INFHEX18) ||
00824                         ((*it)->type() == HEX20))
00825                       {
00826                         out_stream << "phex8 8\n";
00827                         (*it)->connectivity(se, TECPLOT, conn);
00828                         for (unsigned int i=0; i<conn.size(); i++)
00829                           out_stream << conn[i] << " ";
00830                       }
00831 #endif
00832 
00833                     else if (((*it)->type() == TET4)  ||
00834                              ((*it)->type() == TET10))
00835                       {
00836                         out_stream << "tet 4\n";
00837                         // Tecplot connectivity returns 8 entries for
00838                         // the Tet, enough to store it as a degenerate Hex.
00839                         // For GMV we only pick out the four relevant node
00840                         // indices.
00841                         (*it)->connectivity(se, TECPLOT, conn);
00842                         out_stream << conn[0] << " "  // libmesh tet node 0
00843                                    << conn[2] << " "  // libmesh tet node 2
00844                                    << conn[1] << " "  // libmesh tet node 1
00845                                    << conn[4] << " "; // libmesh tet node 3
00846                       }
00847 #ifndef  LIBMESH_ENABLE_INFINITE_ELEMENTS
00848                     else if (((*it)->type() == PRISM6)  ||
00849                              ((*it)->type() == PRISM15) ||
00850                              ((*it)->type() == PRISM18) ||
00851                              ((*it)->type() == PYRAMID5))
00852 #else
00853                     else if (((*it)->type() == PRISM6)     ||
00854                              ((*it)->type() == PRISM15)    ||
00855                              ((*it)->type() == PRISM18)    ||
00856                              ((*it)->type() == PYRAMID5)   ||
00857                              ((*it)->type() == INFPRISM6)  ||
00858                              ((*it)->type() == INFPRISM12))
00859 #endif
00860                       {
00865                         out_stream << "phex8 8\n";
00866                         (*it)->connectivity(se, TECPLOT, conn);
00867                         for (unsigned int i=0; i<conn.size(); i++)
00868                           out_stream << conn[i] << " ";
00869                       }
00870 
00871                     else
00872                       libmesh_error_msg("Encountered an unrecognized element " \
00873                                         << "type: " << (*it)->type()  \
00874                                         << "\nPossibly a dim-1 dimensional " \
00875                                         << "element?  Aborting...");
00876 
00877                     out_stream << '\n';
00878                   }
00879               else // !this->subdivide_second_order()
00880                 {
00881                   UniquePtr<Elem> lo_elem = Elem::build(Elem::first_order_equivalent_type((*it)->type()));
00882                   for (unsigned int i = 0; i != lo_elem->n_nodes(); ++i)
00883                     lo_elem->set_node(i) = (*it)->get_node(i);
00884                   if ((lo_elem->type() == HEX8)
00885 #ifdef  LIBMESH_ENABLE_INFINITE_ELEMENTS
00886                       || (lo_elem->type() == HEX27)
00887 #endif
00888                       )
00889                     {
00890                       out_stream << "phex8 8\n";
00891                       lo_elem->connectivity(0, TECPLOT, conn);
00892                       for (unsigned int i=0; i<conn.size(); i++)
00893                         out_stream << conn[i] << " ";
00894                     }
00895 
00896                   else if (lo_elem->type() == TET4)
00897                     {
00898                       out_stream << "tet 4\n";
00899                       lo_elem->connectivity(0, TECPLOT, conn);
00900                       out_stream << conn[0] << " "
00901                                  << conn[2] << " "
00902                                  << conn[1] << " "
00903                                  << conn[4] << " ";
00904                     }
00905                   else if ((lo_elem->type() == PRISM6)
00906 #ifdef  LIBMESH_ENABLE_INFINITE_ELEMENTS
00907                            || (lo_elem->type() == INFPRISM6)
00908 #endif
00909                            )
00910                     {
00915                       out_stream << "phex8 8\n";
00916                       lo_elem->connectivity(0, TECPLOT, conn);
00917                       for (unsigned int i=0; i<conn.size(); i++)
00918                         out_stream << conn[i] << " ";
00919                     }
00920 
00921                   else
00922                     libmesh_error_msg("Encountered an unrecognized element " \
00923                                       << "type.  Possibly a dim-1 dimensional " \
00924                                       << "element?  Aborting...");
00925 
00926                   out_stream << '\n';
00927                 }
00928             }
00929 
00930           break;
00931         }
00932 
00933       default:
00934         libmesh_error_msg("Unsupported mesh dimension: " << mesh.mesh_dimension());
00935       }
00936 
00937     out_stream << '\n';
00938   }
00939 
00940 
00941 
00942   // optionally write the partition information
00943   if (this->partitioning())
00944     {
00945       if (this->write_subdomain_id_as_material())
00946         {
00947           // Subdomain IDs can be non-contiguous and need not
00948           // necessarily start at 0.  Furthermore, since the user is
00949           // free to define subdomain_id_type to be a signed type, we
00950           // can't even assume max(subdomain_id) >= # unique subdomain ids.
00951 
00952           // We build a map<subdomain_id, unsigned> to associate to each
00953           // user-selected subdomain ID a unique, contiguous unsigned value
00954           // which we can write to file.
00955           std::map<subdomain_id_type, unsigned> sbdid_map;
00956           typedef std::map<subdomain_id_type, unsigned>::iterator sbdid_map_iter;
00957           {
00958             MeshBase::const_element_iterator       it  = mesh.active_elements_begin();
00959             const MeshBase::const_element_iterator end = mesh.active_elements_end();
00960 
00961             for ( ; it != end; ++it)
00962               {
00963                 // Try to insert with dummy value
00964                 sbdid_map.insert( std::make_pair((*it)->subdomain_id(), 0) );
00965               }
00966           }
00967 
00968           // Map is created, iterate through it to set indices.  They will be
00969           // used repeatedly below.
00970           {
00971             unsigned ctr=0;
00972             for (sbdid_map_iter it=sbdid_map.begin(); it != sbdid_map.end(); ++it)
00973               (*it).second = ctr++;
00974           }
00975 
00976           out_stream << "material "
00977                      << sbdid_map.size()
00978                      << " 0\n";
00979 
00980           for (unsigned int sbdid=0; sbdid<sbdid_map.size(); sbdid++)
00981             out_stream << "proc_" << sbdid << "\n";
00982 
00983           MeshBase::const_element_iterator       it  = mesh.active_elements_begin();
00984           const MeshBase::const_element_iterator end = mesh.active_elements_end();
00985 
00986           for ( ; it != end; ++it)
00987             {
00988               // Find the unique index for (*it)->subdomain_id(), print that to file
00989               sbdid_map_iter map_iter = sbdid_map.find( (*it)->subdomain_id() );
00990               unsigned gmv_mat_number = (*map_iter).second;
00991 
00992               if (this->subdivide_second_order())
00993                 for (unsigned int se=0; se<(*it)->n_sub_elem(); se++)
00994                   out_stream << gmv_mat_number+1 << '\n';
00995               else
00996                 out_stream << gmv_mat_number+1 << "\n";
00997             }
00998           out_stream << '\n';
00999 
01000         }
01001       else // write processor IDs as materials.  This is the default
01002         {
01003           out_stream << "material "
01004                      << mesh.n_partitions()
01005                      << " 0"<< '\n';
01006 
01007           for (unsigned int proc=0; proc<mesh.n_partitions(); proc++)
01008             out_stream << "proc_" << proc << '\n';
01009 
01010           MeshBase::const_element_iterator       it  = mesh.active_elements_begin();
01011           const MeshBase::const_element_iterator end = mesh.active_elements_end();
01012 
01013           for ( ; it != end; ++it)
01014             if (this->subdivide_second_order())
01015               for (unsigned int se=0; se<(*it)->n_sub_elem(); se++)
01016                 out_stream << (*it)->processor_id()+1 << '\n';
01017             else
01018               out_stream << (*it)->processor_id()+1 << '\n';
01019 
01020           out_stream << '\n';
01021         }
01022     }
01023 
01024 
01025   // If there are *any* variables at all in the system (including
01026   // p level, or arbitrary cell-based data)
01027   // to write, the gmv file needs to contain the word "variable"
01028   // on a line by itself.
01029   bool write_variable = false;
01030 
01031   // 1.) p-levels
01032   if (this->p_levels() && mesh_max_p_level)
01033     write_variable = true;
01034 
01035   // 2.) solution data
01036   if ((solution_names != NULL) && (v != NULL))
01037     write_variable = true;
01038 
01039   // 3.) cell-centered data
01040   if ( !(this->_cell_centered_data.empty()) )
01041     write_variable = true;
01042 
01043   if (write_variable)
01044     out_stream << "variable\n";
01045 
01046 
01047   // optionally write the p-level information
01048   if (this->p_levels() && mesh_max_p_level)
01049     {
01050       out_stream << "p_level 0\n";
01051 
01052       MeshBase::const_element_iterator       it  = mesh.active_elements_begin();
01053       const MeshBase::const_element_iterator end = mesh.active_elements_end();
01054 
01055       for ( ; it != end; ++it)
01056         if (this->subdivide_second_order())
01057           for (unsigned int se=0; se<(*it)->n_sub_elem(); se++)
01058             out_stream << (*it)->p_level() << " ";
01059         else
01060           out_stream << (*it)->p_level() << " ";
01061       out_stream << "\n\n";
01062     }
01063 
01064 
01065 
01066 
01067   // optionally write cell-centered data
01068   if ( !(this->_cell_centered_data.empty()) )
01069     {
01070       std::map<std::string, const std::vector<Real>* >::iterator       it  = this->_cell_centered_data.begin();
01071       const std::map<std::string, const std::vector<Real>* >::iterator end = this->_cell_centered_data.end();
01072 
01073       for (; it != end; ++it)
01074         {
01075           // write out the variable name, followed by a zero.
01076           out_stream << (*it).first << " 0\n";
01077 
01078           const std::vector<Real>* the_array = (*it).second;
01079 
01080           // Loop over active elements, write out cell data.  If second-order cells
01081           // are split into sub-elements, the sub-elements inherit their parent's
01082           // cell-centered data.
01083           MeshBase::const_element_iterator       elem_it  = mesh.active_elements_begin();
01084           const MeshBase::const_element_iterator elem_end = mesh.active_elements_end();
01085 
01086           for (; elem_it != elem_end; ++elem_it)
01087             {
01088               const Elem* e = *elem_it;
01089 
01090               // Use the element's ID to find the value...
01091               libmesh_assert_less (e->id(), the_array->size());
01092               const Real the_value = the_array->operator[](e->id());
01093 
01094               if (this->subdivide_second_order())
01095                 for (unsigned int se=0; se < e->n_sub_elem(); se++)
01096                   out_stream << the_value << " ";
01097               else
01098                 out_stream << the_value << " ";
01099             }
01100 
01101           out_stream << "\n\n";
01102         }
01103     }
01104 
01105 
01106 
01107 
01108   // optionally write the data
01109   if ((solution_names != NULL) &&
01110       (v != NULL))
01111     {
01112       const unsigned int n_vars =
01113         cast_int<unsigned int>(solution_names->size());
01114 
01115       if (!(v->size() == mesh.n_nodes()*n_vars))
01116         libMesh::err << "ERROR: v->size()=" << v->size()
01117                      << ", mesh.n_nodes()=" << mesh.n_nodes()
01118                      << ", n_vars=" << n_vars
01119                      << ", mesh.n_nodes()*n_vars=" << mesh.n_nodes()*n_vars
01120                      << std::endl;
01121 
01122       libmesh_assert_equal_to (v->size(), mesh.n_nodes()*n_vars);
01123 
01124       for (unsigned int c=0; c<n_vars; c++)
01125         {
01126 
01127 #ifdef LIBMESH_USE_COMPLEX_NUMBERS
01128 
01129           // in case of complex data, write _tree_ data sets
01130           // for each component
01131 
01132           // this is the real part
01133           out_stream << "r_" << (*solution_names)[c] << " 1\n";
01134 
01135           for (unsigned int n=0; n<mesh.n_nodes(); n++)
01136             out_stream << (*v)[n*n_vars + c].real() << " ";
01137 
01138           out_stream << '\n' << '\n';
01139 
01140 
01141           // this is the imaginary part
01142           out_stream << "i_" << (*solution_names)[c] << " 1\n";
01143 
01144           for (unsigned int n=0; n<mesh.n_nodes(); n++)
01145             out_stream << (*v)[n*n_vars + c].imag() << " ";
01146 
01147           out_stream << '\n' << '\n';
01148 
01149           // this is the magnitude
01150           out_stream << "a_" << (*solution_names)[c] << " 1\n";
01151           for (unsigned int n=0; n<mesh.n_nodes(); n++)
01152             out_stream << std::abs((*v)[n*n_vars + c]) << " ";
01153 
01154           out_stream << '\n' << '\n';
01155 
01156 #else
01157 
01158           out_stream << (*solution_names)[c] << " 1\n";
01159 
01160           for (unsigned int n=0; n<mesh.n_nodes(); n++)
01161             out_stream << (*v)[n*n_vars + c] << " ";
01162 
01163           out_stream << '\n' << '\n';
01164 
01165 #endif
01166         }
01167 
01168     }
01169 
01170   // If we wrote any variables, we have to close the variable section now
01171   if (write_variable)
01172     out_stream << "endvars\n";
01173 
01174 
01175   // end of the file
01176   out_stream << "\nendgmv\n";
01177 }
01178 
01179 
01180 
01181 
01182 
01183 
01184 
01185 void GMVIO::write_binary (const std::string& fname,
01186                           const std::vector<Number>* vec,
01187                           const std::vector<std::string>* solution_names)
01188 {
01189   // Get a reference to the mesh
01190   const MeshBase& mesh = MeshOutput<MeshBase>::mesh();
01191 
01192   // This is a parallel_only function
01193   const dof_id_type n_active_elem = mesh.n_active_elem();
01194 
01195   if (MeshOutput<MeshBase>::mesh().processor_id() != 0)
01196     return;
01197 
01198   std::ofstream out_stream (fname.c_str());
01199 
01200   libmesh_assert (out_stream.good());
01201 
01202   unsigned int mesh_max_p_level = 0;
01203 
01204   char buf[80];
01205 
01206   // Begin interfacing with the GMV data file
01207   {
01208     // write the nodes
01209     std::strcpy(buf, "gmvinput");
01210     out_stream.write(buf, std::strlen(buf));
01211 
01212     std::strcpy(buf, "ieeei4r4");
01213     out_stream.write(buf, std::strlen(buf));
01214   }
01215 
01216 
01217 
01218   // write the nodes
01219   {
01220     std::strcpy(buf, "nodes   ");
01221     out_stream.write(buf, std::strlen(buf));
01222 
01223     unsigned int tempint = mesh.n_nodes();
01224 
01225     std::memcpy(buf, &tempint, sizeof(unsigned int));
01226 
01227     out_stream.write(buf, sizeof(unsigned int));
01228 
01229     // write the x coordinate
01230     float *temp = new float[mesh.n_nodes()];
01231     for (unsigned int v=0; v<mesh.n_nodes(); v++)
01232       temp[v] = static_cast<float>(mesh.point(v)(0));
01233     out_stream.write(reinterpret_cast<char *>(temp), sizeof(float)*mesh.n_nodes());
01234 
01235     // write the y coordinate
01236     for (unsigned int v=0; v<mesh.n_nodes(); v++)
01237 #if LIBMESH_DIM > 1
01238       temp[v] = static_cast<float>(mesh.point(v)(1));
01239 #else
01240     temp[v] = 0.;
01241 #endif
01242     out_stream.write(reinterpret_cast<char *>(temp), sizeof(float)*mesh.n_nodes());
01243 
01244     // write the z coordinate
01245     for (unsigned int v=0; v<mesh.n_nodes(); v++)
01246 #if LIBMESH_DIM > 2
01247       temp[v] = static_cast<float>(mesh.point(v)(2));
01248 #else
01249     temp[v] = 0.;
01250 #endif
01251     out_stream.write(reinterpret_cast<char *>(temp), sizeof(float)*mesh.n_nodes());
01252 
01253     delete [] temp;
01254   }
01255 
01256 
01257   // write the connectivity
01258   {
01259     std::strcpy(buf, "cells   ");
01260     out_stream.write(buf, std::strlen(buf));
01261 
01262     unsigned int tempint = n_active_elem;
01263 
01264     std::memcpy(buf, &tempint, sizeof(unsigned int));
01265 
01266     out_stream.write(buf, sizeof(unsigned int));
01267 
01268     MeshBase::const_element_iterator       it  = mesh.active_elements_begin();
01269     const MeshBase::const_element_iterator end = mesh.active_elements_end();
01270 
01271     switch (mesh.mesh_dimension())
01272       {
01273 
01274       case 1:
01275         for ( ; it != end; ++it)
01276           {
01277             mesh_max_p_level = std::max(mesh_max_p_level,
01278                                         (*it)->p_level());
01279 
01280             for(unsigned se = 0; se < (*it)->n_sub_elem(); ++se)
01281               {
01282                 std::strcpy(buf, "line    ");
01283                 out_stream.write(buf, std::strlen(buf));
01284 
01285                 tempint = 2;
01286                 std::memcpy(buf, &tempint, sizeof(unsigned int));
01287                 out_stream.write(buf, sizeof(unsigned int));
01288 
01289                 std::vector<dof_id_type> conn;
01290                 (*it)->connectivity(se,TECPLOT,conn);
01291 
01292                 out_stream.write(reinterpret_cast<char*>(&conn[0]), sizeof(unsigned int)*tempint);
01293               }
01294           }
01295         break;
01296 
01297       case 2:
01298         for ( ; it != end; ++it)
01299           {
01300             mesh_max_p_level = std::max(mesh_max_p_level,
01301                                         (*it)->p_level());
01302 
01303             for(unsigned se = 0; se < (*it)->n_sub_elem(); ++se)
01304               {
01305                 std::strcpy(buf, "quad    ");
01306                 out_stream.write(buf, std::strlen(buf));
01307                 tempint = 4;
01308                 std::memcpy(buf, &tempint, sizeof(unsigned int));
01309                 out_stream.write(buf, sizeof(unsigned int));
01310                 std::vector<dof_id_type> conn;
01311                 (*it)->connectivity(se,TECPLOT,conn);
01312                 out_stream.write(reinterpret_cast<char*>(&conn[0]), sizeof(unsigned int)*tempint);
01313               }
01314           }
01315         break;
01316       case 3:
01317         for ( ; it != end; ++it)
01318           {
01319             mesh_max_p_level = std::max(mesh_max_p_level,
01320                                         (*it)->p_level());
01321 
01322             for(unsigned se = 0; se < (*it)->n_sub_elem(); ++se)
01323               {
01324                 std::strcpy(buf, "phex8   ");
01325                 out_stream.write(buf, std::strlen(buf));
01326                 tempint = 8;
01327                 std::memcpy(buf, &tempint, sizeof(unsigned int));
01328                 out_stream.write(buf, sizeof(unsigned int));
01329                 std::vector<dof_id_type> conn;
01330                 (*it)->connectivity(se,TECPLOT,conn);
01331                 out_stream.write(reinterpret_cast<char*>(&conn[0]), sizeof(unsigned int)*tempint);
01332               }
01333           }
01334         break;
01335       default:
01336         libmesh_error_msg("Unsupported mesh dimension: " << mesh.mesh_dimension());
01337 
01338       }
01339   }
01340 
01341 
01342 
01343   // optionally write the partition information
01344   if (this->partitioning())
01345     {
01346       if (this->write_subdomain_id_as_material())
01347         libmesh_error_msg("Not yet supported in GMVIO::write_binary");
01348 
01349       else
01350         {
01351           std::strcpy(buf, "material");
01352           out_stream.write(buf, std::strlen(buf));
01353 
01354           unsigned int tmpint = mesh.n_processors();
01355           std::memcpy(buf, &tmpint, sizeof(unsigned int));
01356           out_stream.write(buf, sizeof(unsigned int));
01357 
01358           tmpint = 0; // IDs are cell based
01359           std::memcpy(buf, &tmpint, sizeof(unsigned int));
01360           out_stream.write(buf, sizeof(unsigned int));
01361 
01362 
01363           for (unsigned int proc=0; proc<mesh.n_processors(); proc++)
01364             {
01365               std::sprintf(buf, "proc_%u", proc);
01366               out_stream.write(buf, 8);
01367             }
01368 
01369           std::vector<unsigned int> proc_id (n_active_elem);
01370 
01371           unsigned int n=0;
01372 
01373           MeshBase::const_element_iterator       it  = mesh.active_elements_begin();
01374           const MeshBase::const_element_iterator end = mesh.active_elements_end();
01375 
01376           for ( ; it != end; ++it)
01377             for (unsigned int se=0; se<(*it)->n_sub_elem(); se++)
01378               proc_id[n++] = (*it)->processor_id()+1;
01379 
01380 
01381           out_stream.write(reinterpret_cast<char *>(&proc_id[0]),
01382                            sizeof(unsigned int)*proc_id.size());
01383         }
01384     }
01385 
01386   // If there are *any* variables at all in the system (including
01387   // p level, or arbitrary cell-based data)
01388   // to write, the gmv file needs to contain the word "variable"
01389   // on a line by itself.
01390   bool write_variable = false;
01391 
01392   // 1.) p-levels
01393   if (this->p_levels() && mesh_max_p_level)
01394     write_variable = true;
01395 
01396   // 2.) solution data
01397   if ((solution_names != NULL) && (vec != NULL))
01398     write_variable = true;
01399 
01400   //   // 3.) cell-centered data - unsupported
01401   //   if ( !(this->_cell_centered_data.empty()) )
01402   //     write_variable = true;
01403 
01404   if (write_variable)
01405     {
01406       std::strcpy(buf, "variable");
01407       out_stream.write(buf, std::strlen(buf));
01408     }
01409 
01410   // optionally write the partition information
01411   if (this->p_levels() && mesh_max_p_level)
01412     {
01413       unsigned int n_floats = n_active_elem;
01414       for (unsigned int i=0; i != mesh.mesh_dimension(); ++i)
01415         n_floats *= 2;
01416 
01417       float *temp = new float[n_floats];
01418 
01419       std::strcpy(buf, "p_level");
01420       out_stream.write(buf, std::strlen(buf));
01421 
01422       unsigned int tempint = 0; // p levels are cell data
01423 
01424       std::memcpy(buf, &tempint, sizeof(unsigned int));
01425       out_stream.write(buf, sizeof(unsigned int));
01426 
01427       MeshBase::const_element_iterator       it  = mesh.active_elements_begin();
01428       const MeshBase::const_element_iterator end = mesh.active_elements_end();
01429       unsigned int n=0;
01430 
01431       for (; it != end; ++it)
01432         for (unsigned int se=0; se<(*it)->n_sub_elem(); se++)
01433           temp[n++] = static_cast<float>( (*it)->p_level() );
01434 
01435       out_stream.write(reinterpret_cast<char *>(temp),
01436                        sizeof(float)*n_floats);
01437 
01438       delete [] temp;
01439     }
01440 
01441 
01442   // optionally write cell-centered data
01443   if ( !(this->_cell_centered_data.empty()) )
01444     {
01445       libMesh::err << "Cell-centered data not (yet) supported in binary I/O mode!" << std::endl;
01446 
01447       //        std::map<std::string, const std::vector<Real>* >::iterator       it  = this->_cell_centered_data.begin();
01448       //        const std::map<std::string, const std::vector<Real>* >::iterator end = this->_cell_centered_data.end();
01449 
01450       //        for (; it != end; ++it)
01451       //  {
01452       //    // Write out the variable name ...
01453       //    std::strcpy(buf, (*it).first.c_str());
01454       //    out_stream.write(buf, std::strlen(buf));
01455 
01456       //    // ... followed by a zero.
01457       //    unsigned int tempint = 0; // 0 signifies cell data
01458       //    std::memcpy(buf, &tempint, sizeof(unsigned int));
01459       //    out_stream.write(buf, sizeof(unsigned int));
01460 
01461       //    // Get a pointer to the array of cell-centered data values
01462       //    const std::vector<Real>* the_array = (*it).second;
01463 
01464       //   // Since the_array might contain zeros (for inactive elements) we need to
01465       //   // make a copy of it containing just values for active elements.
01466       //   const unsigned int n_floats = n_active_elem * (1<<mesh.mesh_dimension());
01467       //   float *temp = new float[n_floats];
01468 
01469       //   MeshBase::const_element_iterator       elem_it  = mesh.active_elements_begin();
01470       //   const MeshBase::const_element_iterator elem_end = mesh.active_elements_end();
01471       //   unsigned int n=0;
01472 
01473       //   for (; elem_it != elem_end; ++elem_it)
01474       //     {
01475       //       // If there's a seg-fault, it will probably be here!
01476       //       const float the_value = static_cast<float>(the_array->operator[]((*elem_it)->id()));
01477 
01478       //       for (unsigned int se=0; se<(*elem_it)->n_sub_elem(); se++)
01479       // temp[n++] = the_value;
01480       //     }
01481 
01482 
01483       //    // Write "the_array" directly to the file
01484       //    out_stream.write(reinterpret_cast<char *>(temp),
01485       //      sizeof(float)*n_floats);
01486 
01487       //   delete [] temp;
01488       //  }
01489     }
01490 
01491 
01492 
01493 
01494   // optionally write the data
01495   if ((solution_names != NULL) &&
01496       (vec != NULL))
01497     {
01498       float *temp = new float[mesh.n_nodes()];
01499 
01500       const unsigned int n_vars =
01501         cast_int<unsigned int>(solution_names->size());
01502 
01503       for (unsigned int c=0; c<n_vars; c++)
01504         {
01505 
01506 #ifdef LIBMESH_USE_COMPLEX_NUMBERS
01507           // for complex data, write three datasets
01508 
01509 
01510           // Real part
01511           std::strcpy(buf, "r_");
01512           out_stream.write(buf, 2);
01513           std::strcpy(buf, (*solution_names)[c].c_str());
01514           out_stream.write(buf, 6);
01515 
01516           unsigned int tempint = 1; // always do nodal data
01517           std::memcpy(buf, &tempint, sizeof(unsigned int));
01518           out_stream.write(buf, sizeof(unsigned int));
01519 
01520           for (unsigned int n=0; n<mesh.n_nodes(); n++)
01521             temp[n] = static_cast<float>( (*vec)[n*n_vars + c].real() );
01522 
01523           out_stream.write(reinterpret_cast<char *>(temp), sizeof(float)*mesh.n_nodes());
01524 
01525 
01526           // imaginary part
01527           std::strcpy(buf, "i_");
01528           out_stream.write(buf, 2);
01529           std::strcpy(buf, (*solution_names)[c].c_str());
01530           out_stream.write(buf, 6);
01531 
01532           std::memcpy(buf, &tempint, sizeof(unsigned int));
01533           out_stream.write(buf, sizeof(unsigned int));
01534 
01535           for (unsigned int n=0; n<mesh.n_nodes(); n++)
01536             temp[n] = static_cast<float>( (*vec)[n*n_vars + c].imag() );
01537 
01538           out_stream.write(reinterpret_cast<char *>(temp), sizeof(float)*mesh.n_nodes());
01539 
01540           // magnitude
01541           std::strcpy(buf, "a_");
01542           out_stream.write(buf, 2);
01543           std::strcpy(buf, (*solution_names)[c].c_str());
01544           out_stream.write(buf, 6);
01545 
01546           std::memcpy(buf, &tempint, sizeof(unsigned int));
01547           out_stream.write(buf, sizeof(unsigned int));
01548 
01549           for (unsigned int n=0; n<mesh.n_nodes(); n++)
01550             temp[n] = static_cast<float>(std::abs((*vec)[n*n_vars + c]));
01551 
01552           out_stream.write(reinterpret_cast<char *>(temp), sizeof(float)*mesh.n_nodes());
01553 
01554 #else
01555 
01556 
01557           std::strcpy(buf, (*solution_names)[c].c_str());
01558           out_stream.write(buf, 8);
01559 
01560           unsigned int tempint = 1; // always do nodal data
01561           std::memcpy(buf, &tempint, sizeof(unsigned int));
01562           out_stream.write(buf, sizeof(unsigned int));
01563 
01564           for (unsigned int n=0; n<mesh.n_nodes(); n++)
01565             temp[n] = static_cast<float>((*vec)[n*n_vars + c]);
01566 
01567           out_stream.write(reinterpret_cast<char *>(temp), sizeof(float)*mesh.n_nodes());
01568 
01569 
01570 #endif
01571 
01572 
01573         }
01574 
01575       delete [] temp;
01576 
01577     }
01578 
01579   // If we wrote any variables, we have to close the variable section now
01580   if (write_variable)
01581     {
01582       std::strcpy(buf, "endvars ");
01583       out_stream.write(buf, std::strlen(buf));
01584     }
01585 
01586   // end the file
01587   std::strcpy(buf, "endgmv  ");
01588   out_stream.write(buf, std::strlen(buf));
01589 }
01590 
01591 
01592 
01593 
01594 
01595 
01596 
01597 
01598 
01599 void GMVIO::write_discontinuous_gmv (const std::string& name,
01600                                      const EquationSystems& es,
01601                                      const bool write_partitioning,
01602                                      const std::set<std::string>* system_names) const
01603 {
01604   std::vector<std::string> solution_names;
01605   std::vector<Number>      v;
01606 
01607   // Get a reference to the mesh
01608   const MeshBase& mesh = MeshOutput<MeshBase>::mesh();
01609 
01610   es.build_variable_names  (solution_names, NULL, system_names);
01611   es.build_discontinuous_solution_vector (v, system_names);
01612 
01613   // These are parallel_only functions
01614   const unsigned int n_active_elem = mesh.n_active_elem();
01615 
01616   if (mesh.processor_id() != 0)
01617     return;
01618 
01619   std::ofstream out_stream(name.c_str());
01620 
01621   libmesh_assert (out_stream.good());
01622 
01623   // Begin interfacing with the GMV data file
01624   {
01625 
01626     // write the nodes
01627     out_stream << "gmvinput ascii" << std::endl << std::endl;
01628 
01629     // Compute the total weight
01630     {
01631       MeshBase::const_element_iterator       it  = mesh.active_elements_begin();
01632       const MeshBase::const_element_iterator end = mesh.active_elements_end();
01633 
01634       unsigned int tw=0;
01635 
01636       for ( ; it != end; ++it)
01637         tw += (*it)->n_nodes();
01638 
01639       out_stream << "nodes " << tw << std::endl;
01640     }
01641 
01642 
01643 
01644     // Write all the x values
01645     {
01646       MeshBase::const_element_iterator       it  = mesh.active_elements_begin();
01647       const MeshBase::const_element_iterator end = mesh.active_elements_end();
01648 
01649       for ( ; it != end; ++it)
01650         for (unsigned int n=0; n<(*it)->n_nodes(); n++)
01651           out_stream << (*it)->point(n)(0) << " ";
01652 
01653       out_stream << std::endl;
01654     }
01655 
01656 
01657     // Write all the y values
01658     {
01659       MeshBase::const_element_iterator       it  = mesh.active_elements_begin();
01660       const MeshBase::const_element_iterator end = mesh.active_elements_end();
01661 
01662       for ( ; it != end; ++it)
01663         for (unsigned int n=0; n<(*it)->n_nodes(); n++)
01664 #if LIBMESH_DIM > 1
01665           out_stream << (*it)->point(n)(1) << " ";
01666 #else
01667       out_stream << 0. << " ";
01668 #endif
01669 
01670       out_stream << std::endl;
01671     }
01672 
01673 
01674     // Write all the z values
01675     {
01676       MeshBase::const_element_iterator       it  = mesh.active_elements_begin();
01677       const MeshBase::const_element_iterator end = mesh.active_elements_end();
01678 
01679       for ( ; it != end; ++it)
01680         for (unsigned int n=0; n<(*it)->n_nodes(); n++)
01681 #if LIBMESH_DIM > 2
01682           out_stream << (*it)->point(n)(2) << " ";
01683 #else
01684       out_stream << 0. << " ";
01685 #endif
01686 
01687       out_stream << std::endl << std::endl;
01688     }
01689   }
01690 
01691 
01692 
01693   {
01694     // write the connectivity
01695 
01696     out_stream << "cells " << n_active_elem << std::endl;
01697 
01698     MeshBase::const_element_iterator       it  = mesh.active_elements_begin();
01699     const MeshBase::const_element_iterator end = mesh.active_elements_end();
01700 
01701     unsigned int nn=1;
01702 
01703     switch (mesh.mesh_dimension())
01704       {
01705       case 1:
01706         {
01707           for ( ; it != end; ++it)
01708             for (unsigned int se=0; se<(*it)->n_sub_elem(); se++)
01709               {
01710                 if (((*it)->type() == EDGE2) ||
01711                     ((*it)->type() == EDGE3) ||
01712                     ((*it)->type() == EDGE4)
01713 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
01714                     || ((*it)->type() == INFEDGE2)
01715 #endif
01716                     )
01717                   {
01718                     out_stream << "line 2" << std::endl;
01719                     for (unsigned int i=0; i<(*it)->n_nodes(); i++)
01720                       out_stream << nn++ << " ";
01721 
01722                   }
01723                 else
01724                   libmesh_error_msg("Unsupported 1D element type: " << Utility::enum_to_string((*it)->type()));
01725 
01726                 out_stream << std::endl;
01727               }
01728 
01729           break;
01730         }
01731 
01732       case 2:
01733         {
01734           for ( ; it != end; ++it)
01735             for (unsigned int se=0; se<(*it)->n_sub_elem(); se++)
01736               {
01737                 if (((*it)->type() == QUAD4) ||
01738                     ((*it)->type() == QUAD8) || // Note: QUAD8 will be output as one central quad and
01739                     // four surrounding triangles (though they will be written
01740                     // to GMV as QUAD4s).
01741                     ((*it)->type() == QUAD9)
01742 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
01743                     || ((*it)->type() == INFQUAD4)
01744                     || ((*it)->type() == INFQUAD6)
01745 #endif
01746                     )
01747                   {
01748                     out_stream << "quad 4" << std::endl;
01749                     for (unsigned int i=0; i<(*it)->n_nodes(); i++)
01750                       out_stream << nn++ << " ";
01751 
01752                   }
01753                 else if (((*it)->type() == TRI3) ||
01754                          ((*it)->type() == TRI6))
01755                   {
01756                     out_stream << "tri 3" << std::endl;
01757                     for (unsigned int i=0; i<(*it)->n_nodes(); i++)
01758                       out_stream << nn++ << " ";
01759 
01760                   }
01761                 else
01762                   libmesh_error_msg("Unsupported 2D element type: " << Utility::enum_to_string((*it)->type()));
01763 
01764                 out_stream << std::endl;
01765               }
01766 
01767           break;
01768         }
01769 
01770 
01771       case 3:
01772         {
01773           for ( ; it != end; ++it)
01774             for (unsigned int se=0; se<(*it)->n_sub_elem(); se++)
01775               {
01776                 if (((*it)->type() == HEX8) ||
01777                     ((*it)->type() == HEX20) ||
01778                     ((*it)->type() == HEX27)
01779 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
01780                     || ((*it)->type() == INFHEX8)
01781                     || ((*it)->type() == INFHEX16)
01782                     || ((*it)->type() == INFHEX18)
01783 #endif
01784                     )
01785                   {
01786                     out_stream << "phex8 8" << std::endl;
01787                     for (unsigned int i=0; i<(*it)->n_nodes(); i++)
01788                       out_stream << nn++ << " ";
01789                   }
01790                 else if (((*it)->type() == PRISM6) ||
01791                          ((*it)->type() == PRISM15) ||
01792                          ((*it)->type() == PRISM18)
01793 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
01794                          || ((*it)->type() == INFPRISM6)
01795                          || ((*it)->type() == INFPRISM12)
01796 #endif
01797                          )
01798                   {
01799                     out_stream << "pprism6 6" << std::endl;
01800                     for (unsigned int i=0; i<(*it)->n_nodes(); i++)
01801                       out_stream << nn++ << " ";
01802                   }
01803                 else if (((*it)->type() == TET4) ||
01804                          ((*it)->type() == TET10))
01805                   {
01806                     out_stream << "tet 4" << std::endl;
01807                     for (unsigned int i=0; i<(*it)->n_nodes(); i++)
01808                       out_stream << nn++ << " ";
01809                   }
01810                 else
01811                   libmesh_error_msg("Unsupported 3D element type: " << Utility::enum_to_string((*it)->type()));
01812 
01813                 out_stream << std::endl;
01814               }
01815 
01816           break;
01817         }
01818 
01819       default:
01820         libmesh_error_msg("Unsupported mesh dimension: " << mesh.mesh_dimension());
01821       }
01822 
01823     out_stream << std::endl;
01824   }
01825 
01826 
01827 
01828   // optionally write the partition information
01829   if (write_partitioning)
01830     {
01831       if (_write_subdomain_id_as_material)
01832         libmesh_error_msg("Not yet supported in GMVIO::write_discontinuous_gmv");
01833 
01834       else
01835         {
01836           out_stream << "material "
01837                      << mesh.n_processors()
01838                      << " 0"<< std::endl;
01839 
01840           for (unsigned int proc=0; proc<mesh.n_processors(); proc++)
01841             out_stream << "proc_" << proc << std::endl;
01842 
01843           MeshBase::const_element_iterator       it  = mesh.active_elements_begin();
01844           const MeshBase::const_element_iterator end = mesh.active_elements_end();
01845 
01846           for ( ; it != end; ++it)
01847             out_stream << (*it)->processor_id()+1 << std::endl;
01848 
01849           out_stream << std::endl;
01850         }
01851     }
01852 
01853 
01854   // Writing cell-centered data is not yet supported in discontinuous GMV files.
01855   if ( !(this->_cell_centered_data.empty()) )
01856     {
01857       libMesh::err << "Cell-centered data not (yet) supported for discontinuous GMV files!" << std::endl;
01858     }
01859 
01860 
01861 
01862   // write the data
01863   {
01864     const unsigned int n_vars =
01865       cast_int<unsigned int>(solution_names.size());
01866 
01867     //    libmesh_assert_equal_to (v.size(), tw*n_vars);
01868 
01869     out_stream << "variable" << std::endl;
01870 
01871 
01872     for (unsigned int c=0; c<n_vars; c++)
01873       {
01874 
01875 #ifdef LIBMESH_USE_COMPLEX_NUMBERS
01876 
01877         // in case of complex data, write _tree_ data sets
01878         // for each component
01879 
01880         // this is the real part
01881         out_stream << "r_" << solution_names[c] << " 1" << std::endl;
01882         {
01883           MeshBase::const_element_iterator       it  = mesh.active_elements_begin();
01884           const MeshBase::const_element_iterator end = mesh.active_elements_end();
01885 
01886           for ( ; it != end; ++it)
01887             for (unsigned int n=0; n<(*it)->n_nodes(); n++)
01888               out_stream << v[(n++)*n_vars + c].real() << " ";
01889         }
01890         out_stream << std::endl << std::endl;
01891 
01892 
01893         // this is the imaginary part
01894         out_stream << "i_" << solution_names[c] << " 1" << std::endl;
01895         {
01896           MeshBase::const_element_iterator       it  = mesh.active_elements_begin();
01897           const MeshBase::const_element_iterator end = mesh.active_elements_end();
01898 
01899           for ( ; it != end; ++it)
01900             for (unsigned int n=0; n<(*it)->n_nodes(); n++)
01901               out_stream << v[(n++)*n_vars + c].imag() << " ";
01902         }
01903         out_stream << std::endl << std::endl;
01904 
01905         // this is the magnitude
01906         out_stream << "a_" << solution_names[c] << " 1" << std::endl;
01907         {
01908           MeshBase::const_element_iterator       it  = mesh.active_elements_begin();
01909           const MeshBase::const_element_iterator end = mesh.active_elements_end();
01910 
01911           for ( ; it != end; ++it)
01912             for (unsigned int n=0; n<(*it)->n_nodes(); n++)
01913               out_stream << std::abs(v[(n++)*n_vars + c]) << " ";
01914         }
01915         out_stream << std::endl << std::endl;
01916 
01917 #else
01918 
01919         out_stream << solution_names[c] << " 1" << std::endl;
01920         {
01921           MeshBase::const_element_iterator       it  = mesh.active_elements_begin();
01922           const MeshBase::const_element_iterator end = mesh.active_elements_end();
01923 
01924           unsigned int nn=0;
01925 
01926           for ( ; it != end; ++it)
01927             for (unsigned int n=0; n<(*it)->n_nodes(); n++)
01928               out_stream << v[(nn++)*n_vars + c] << " ";
01929         }
01930         out_stream << std::endl << std::endl;
01931 
01932 #endif
01933 
01934       }
01935 
01936     out_stream << "endvars" << std::endl;
01937   }
01938 
01939 
01940   // end of the file
01941   out_stream << std::endl << "endgmv" << std::endl;
01942 }
01943 
01944 
01945 
01946 
01947 
01948 void GMVIO::add_cell_centered_data (const std::string&       cell_centered_data_name,
01949                                     const std::vector<Real>* cell_centered_data_vals)
01950 {
01951   libmesh_assert(cell_centered_data_vals);
01952 
01953   // Make sure there are *at least* enough entries for all the active elements.
01954   // There can also be entries for inactive elements, they will be ignored.
01955   // libmesh_assert_greater_equal (cell_centered_data_vals->size(),
01956   //                           MeshOutput<MeshBase>::mesh().n_active_elem());
01957   this->_cell_centered_data[cell_centered_data_name] = cell_centered_data_vals;
01958 }
01959 
01960 
01961 
01962 
01963 
01964 
01965 void GMVIO::read (const std::string& name)
01966 {
01967   // This is a serial-only process for now;
01968   // the Mesh should be read on processor 0 and
01969   // broadcast later
01970   libmesh_assert_equal_to (MeshOutput<MeshBase>::mesh().processor_id(), 0);
01971 
01972   _next_elem_id = 0;
01973 
01974   libmesh_experimental();
01975 
01976 #ifndef LIBMESH_HAVE_GMV
01977 
01978   libmesh_error_msg("Cannot read GMV file " << name << " without the GMV API.");
01979 
01980 #else
01981   // We use the file-scope global variable eletypes for mapping nodes
01982   // from GMV to libmesh indices, so initialize that data now.
01983   init_eletypes();
01984 
01985   // Clear the mesh so we are sure to start from a pristeen state.
01986   MeshBase& mesh = MeshInput<MeshBase>::mesh();
01987   mesh.clear();
01988 
01989   // Keep track of what kinds of elements this file contains
01990   elems_of_dimension.clear();
01991   elems_of_dimension.resize(4, false);
01992 
01993   // It is apparently possible for gmv files to contain
01994   // a "fromfile" directive (?) But we currently don't make
01995   // any use of this feature in LibMesh.  Nonzero return val
01996   // from any function usually means an error has occurred.
01997   int ierr = GMVLib::gmvread_open_fromfileskip(const_cast<char*>(name.c_str()));
01998   if (ierr != 0)
01999     libmesh_error_msg("GMVLib::gmvread_open_fromfileskip failed!");
02000 
02001 
02002   // Loop through file until GMVEND.
02003   int iend = 0;
02004   while (iend == 0)
02005     {
02006       GMVLib::gmvread_data();
02007 
02008       /*  Check for GMVEND.  */
02009       if (GMVLib::gmv_data.keyword == GMVEND)
02010         {
02011           iend = 1;
02012           GMVLib::gmvread_close();
02013           break;
02014         }
02015 
02016       /*  Check for GMVERROR.  */
02017       if (GMVLib::gmv_data.keyword == GMVERROR)
02018         libmesh_error_msg("Encountered GMVERROR while reading!");
02019 
02020       /*  Process the data.  */
02021       switch (GMVLib::gmv_data.keyword)
02022         {
02023         case NODES:
02024           {
02025             //libMesh::out << "Reading nodes." << std::endl;
02026 
02027             if (GMVLib::gmv_data.num2 == NODES)
02028               this->_read_nodes();
02029 
02030             else if (GMVLib::gmv_data.num2 == NODE_V)
02031               libmesh_error_msg("Unsupported GMV data type NODE_V!");
02032 
02033             break;
02034           }
02035 
02036         case CELLS:
02037           {
02038             // Read 1 cell at a time
02039             // libMesh::out << "\nReading one cell." << std::endl;
02040             this->_read_one_cell();
02041             break;
02042           }
02043 
02044         case MATERIAL:
02045           {
02046             // keyword == 6
02047             // These are the materials, which we use to specify the mesh
02048             // partitioning.
02049             this->_read_materials();
02050             break;
02051           }
02052 
02053         case VARIABLE:
02054           {
02055             // keyword == 8
02056             // This is a field variable.
02057 
02058             // Check to see if we're done reading variables and break out.
02059             if (GMVLib::gmv_data.datatype == ENDKEYWORD)
02060               {
02061                 // libMesh::out << "Done reading GMV variables." << std::endl;
02062                 break;
02063               }
02064 
02065             if (GMVLib::gmv_data.datatype == NODE)
02066               {
02067                 // libMesh::out << "Reading node field data for variable "
02068                 //   << GMVLib::gmv_data.name1 << std::endl;
02069                 this->_read_var();
02070                 break;
02071               }
02072 
02073             else
02074               {
02075                 libMesh::err << "Warning: Skipping variable: "
02076                              << GMVLib::gmv_data.name1
02077                              << " which is of unsupported GMV datatype "
02078                              << GMVLib::gmv_data.datatype
02079                              << ".  Nodal field data is currently the only type currently supported."
02080                              << std::endl;
02081                 break;
02082               }
02083 
02084           }
02085 
02086         default:
02087           libmesh_error_msg("Encountered unknown GMV keyword " << GMVLib::gmv_data.keyword);
02088 
02089         } // end switch
02090     } // end while
02091 
02092   // Set the mesh dimension to the largest encountered for an element
02093   for (unsigned char i=0; i!=4; ++i)
02094     if (elems_of_dimension[i])
02095       mesh.set_mesh_dimension(i);
02096 
02097 #if LIBMESH_DIM < 3
02098   if (mesh.mesh_dimension() > LIBMESH_DIM)
02099     libmesh_error_msg("Cannot open dimension " \
02100                       << mesh.mesh_dimension()            \
02101                       << " mesh file when configured without "        \
02102                       << mesh.mesh_dimension()                        \
02103                       << "D support.");
02104 #endif
02105 
02106   // Done reading in the mesh, now call find_neighbors, etc.
02107   // mesh.find_neighbors();
02108 
02109   // Pass true flag to skip renumbering nodes and elements
02110   mesh.prepare_for_use(true);
02111 #endif
02112 }
02113 
02114 
02115 
02116 
02117 void GMVIO::_read_var()
02118 {
02119 #ifdef LIBMESH_HAVE_GMV
02120 
02121   // Copy all the variable's values into a local storage vector.
02122   _nodal_data.insert ( std::make_pair(std::string(GMVLib::gmv_data.name1),
02123                                       std::vector<Number>(GMVLib::gmv_data.doubledata1, GMVLib::gmv_data.doubledata1+GMVLib::gmv_data.num) ) );
02124 #endif
02125 }
02126 
02127 
02128 
02129 void GMVIO::_read_materials()
02130 {
02131 #ifdef LIBMESH_HAVE_GMV
02132 
02133   // LibMesh assigns materials on a per-cell basis
02134   libmesh_assert_equal_to (GMVLib::gmv_data.datatype, CELL);
02135 
02136   //   // Material names: LibMesh has no use for these currently...
02137   //   libMesh::out << "Number of material names="
02138   //     << GMVLib::gmv_data.num
02139   //     << std::endl;
02140 
02141   //   for (int i = 0; i < GMVLib::gmv_data.num; i++)
02142   //     {
02143   //       // Build a 32-char string from the appropriate entries
02144   //       std::string mat_string(&GMVLib::gmv_data.chardata1[i*33], 32);
02145 
02146   //       libMesh::out << "Material name " << i << ": " << mat_string << std::endl;
02147   //     }
02148 
02149   //   // Material labels: These correspond to (1-based) CPU IDs, and
02150   //   // there should be 1 of these for each element.
02151   //   libMesh::out << "Number of material labels = "
02152   //     << GMVLib::gmv_data.nlongdata1
02153   //     << std::endl;
02154 
02155   for (int i = 0; i < GMVLib::gmv_data.nlongdata1; i++)
02156     {
02157       // Debugging Info
02158       // libMesh::out << "Material ID " << i << ": "
02159       // << GMVLib::gmv_data.longdata1[i]
02160       // << std::endl;
02161 
02162       MeshInput<MeshBase>::mesh().elem(i)->processor_id() =
02163         cast_int<processor_id_type>(GMVLib::gmv_data.longdata1[i]-1);
02164     }
02165 
02166 #endif
02167 }
02168 
02169 
02170 
02171 
02172 void GMVIO::_read_nodes()
02173 {
02174 #ifdef LIBMESH_HAVE_GMV
02175   //   // Debug Info
02176   //   libMesh::out << "gmv_data.datatype="
02177   //     <<  GMVLib::gmv_data.datatype
02178   //     << std::endl;
02179 
02180   // LibMesh writes UNSTRUCT=100 node data
02181   libmesh_assert_equal_to (GMVLib::gmv_data.datatype, UNSTRUCT);
02182 
02183   // The nodal data is stored in gmv_data.doubledata{1,2,3}
02184   // and is nnodes long
02185   for (int i = 0; i < GMVLib::gmv_data.num; i++)
02186     {
02187       //       libMesh::out << "(x,y,z)="
02188       // << "("
02189       // << GMVLib::gmv_data.doubledata1[i]
02190       // << ","
02191       // << GMVLib::gmv_data.doubledata2[i]
02192       // << ","
02193       // << GMVLib::gmv_data.doubledata3[i]
02194       // << ")"
02195       // << std::endl;
02196 
02197       // Add the point to the Mesh
02198       MeshInput<MeshBase>::mesh().add_point
02199         ( Point(GMVLib::gmv_data.doubledata1[i],
02200                 GMVLib::gmv_data.doubledata2[i],
02201                 GMVLib::gmv_data.doubledata3[i]), i);
02202     }
02203 #endif
02204 }
02205 
02206 
02207 void GMVIO::_read_one_cell()
02208 {
02209 #ifdef LIBMESH_HAVE_GMV
02210   //   // Debug Info
02211   //   libMesh::out << "gmv_data.datatype="
02212   //     <<  GMVLib::gmv_data.datatype
02213   //     << std::endl;
02214 
02215   // This is either a REGULAR=111 cell or
02216   // the ENDKEYWORD=207 of the cells
02217 #ifndef NDEBUG
02218   bool recognized =
02219     (GMVLib::gmv_data.datatype==REGULAR) ||
02220     (GMVLib::gmv_data.datatype==ENDKEYWORD);
02221 #endif
02222   libmesh_assert (recognized);
02223 
02224   MeshBase& mesh = MeshInput<MeshBase>::mesh();
02225 
02226   if (GMVLib::gmv_data.datatype == REGULAR)
02227     {
02228       //       libMesh::out << "Name of the cell is: "
02229       // << GMVLib::gmv_data.name1
02230       // << std::endl;
02231 
02232       //       libMesh::out << "Cell has "
02233       // << GMVLib::gmv_data.num2
02234       // << " vertices."
02235       // << std::endl;
02236 
02237       // We need a mapping from GMV element types to LibMesh
02238       // ElemTypes.  Basically the reverse of the eletypes
02239       // std::map above.
02240       //
02241       // FIXME: Since Quad9's apparently don't exist for GMV, and since
02242       // In general we write linear sub-elements to GMV files, we need
02243       // to be careful to read back in exactly what we wrote out...
02244       ElemType type = this->_gmv_elem_to_libmesh_elem(GMVLib::gmv_data.name1);
02245 
02246       Elem* elem = Elem::build(type).release();
02247       elem->set_id(_next_elem_id++);
02248 
02249       // Get the ElementDefinition object for this element type
02250       const ElementDefinition& eledef = eletypes[type];
02251 
02252       // Print out the connectivity information for
02253       // this cell.
02254       for (int i=0; i<GMVLib::gmv_data.num2; i++)
02255         {
02256           //   // Debugging info
02257           //   libMesh::out << "Vertex " << i << " is node "
02258           //     << GMVLib::gmv_data.longdata1[i]
02259           //     << std::endl;
02260 
02261           // Map index i to GMV's numbering scheme
02262           unsigned mapped_i = eledef.node_map[i];
02263 
02264           // Note: Node numbers (as stored in libmesh) are 1-based
02265           elem->set_node(i) = mesh.node_ptr
02266             (cast_int<dof_id_type>(GMVLib::gmv_data.longdata1[mapped_i]-1));
02267         }
02268 
02269       elems_of_dimension[elem->dim()] = true;
02270 
02271       // Add the newly-created element to the mesh
02272       mesh.add_elem(elem);
02273     }
02274 
02275 
02276   if (GMVLib::gmv_data.datatype == ENDKEYWORD)
02277     {
02278       // There isn't a cell to read, so we just return
02279       return;
02280     }
02281 
02282 #endif
02283 }
02284 
02285 
02286 ElemType GMVIO::_gmv_elem_to_libmesh_elem(const char* elemname)
02287 {
02288   //
02289   // Linear Elements
02290   //
02291   if (!std::strncmp(elemname,"line",4))
02292     return EDGE2;
02293 
02294   if (!std::strncmp(elemname,"tri",3))
02295     return TRI3;
02296 
02297   if (!std::strncmp(elemname,"quad",4))
02298     return QUAD4;
02299 
02300   // FIXME: tet or ptet4?
02301   if ((!std::strncmp(elemname,"tet",3)) ||
02302       (!std::strncmp(elemname,"ptet4",5)))
02303     return TET4;
02304 
02305   // FIXME: hex or phex8?
02306   if ((!std::strncmp(elemname,"hex",3)) ||
02307       (!std::strncmp(elemname,"phex8",5)))
02308     return HEX8;
02309 
02310   // FIXME: prism or pprism6?
02311   if ((!std::strncmp(elemname,"prism",5)) ||
02312       (!std::strncmp(elemname,"pprism6",7)))
02313     return PRISM6;
02314 
02315   //
02316   // Quadratic Elements
02317   //
02318   if (!std::strncmp(elemname,"phex20",6))
02319     return HEX20;
02320 
02321   if (!std::strncmp(elemname,"phex27",6))
02322     return HEX27;
02323 
02324   if (!std::strncmp(elemname,"pprism15",8))
02325     return PRISM15;
02326 
02327   if (!std::strncmp(elemname,"ptet10",6))
02328     return TET10;
02329 
02330   if (!std::strncmp(elemname,"6tri",4))
02331     return TRI6;
02332 
02333   if (!std::strncmp(elemname,"8quad",5))
02334     return QUAD8;
02335 
02336   if (!std::strncmp(elemname,"3line",5))
02337     return EDGE3;
02338 
02339   // Unsupported/Unused types
02340   // if (!std::strncmp(elemname,"vface2d",7))
02341   // if (!std::strncmp(elemname,"vface3d",7))
02342   // if (!std::strncmp(elemname,"pyramid",7))
02343   // if (!std::strncmp(elemname,"ppyrmd5",7))
02344   // if (!std::strncmp(elemname,"ppyrmd13",8))
02345 
02346   // If we didn't return yet, then we didn't find the right cell!
02347   libmesh_error_msg("Uknown/unsupported element: " << elemname << " was read.");
02348 }
02349 
02350 
02351 
02352 
02353 void GMVIO::copy_nodal_solution(EquationSystems& es)
02354 {
02355   // Check for easy return if there isn't any nodal data
02356   if (_nodal_data.empty())
02357     {
02358       libMesh::err << "Unable to copy nodal solution: No nodal "
02359                    << "solution has been read in from file." << std::endl;
02360       return;
02361     }
02362 
02363   // Be sure there is at least one system
02364   libmesh_assert (es.n_systems());
02365 
02366   // Keep track of variable names which have been found and
02367   // copied already.  This could be used to prevent us from
02368   // e.g. copying the same var into 2 different systems ...
02369   // but this seems unlikely.  Also, it is used to tell if
02370   // any variables which were read in were not successfully
02371   // copied to the EquationSystems.
02372   std::set<std::string> vars_copied;
02373 
02374   // For each entry in the nodal data map, try to find a system
02375   // that has the same variable key name.
02376   for (unsigned int sys=0; sys<es.n_systems(); ++sys)
02377     {
02378       // Get a generic refernence to the current System
02379       System& system = es.get_system(sys);
02380 
02381       // And a reference to that system's dof_map
02382       // const DofMap & dof_map = system.get_dof_map();
02383 
02384       // For each var entry in the _nodal_data map, try to find
02385       // that var in the system
02386       std::map<std::string, std::vector<Number> >::iterator it = _nodal_data.begin();
02387       const std::map<std::string, std::vector<Number> >::iterator end = _nodal_data.end();
02388       for (; it != end; ++it)
02389         {
02390           std::string var_name = (*it).first;
02391           // libMesh::out << "Searching for var " << var_name << " in system " << sys << std::endl;
02392 
02393           if (system.has_variable(var_name))
02394             {
02395               // Check if there are as many nodes in the mesh as there are entries
02396               // in the stored nodal data vector
02397               libmesh_assert_equal_to ( (*it).second.size(), MeshInput<MeshBase>::mesh().n_nodes() );
02398 
02399               const unsigned int var_num = system.variable_number(var_name);
02400 
02401               // libMesh::out << "Variable "
02402               // << var_name
02403               // << " is variable "
02404               // << var_num
02405               // << " in system " << sys << std::endl;
02406 
02407               // The only type of nodal data we can read in from GMV is for
02408               // linear LAGRANGE type elements.
02409               const FEType& fe_type = system.variable_type(var_num);
02410               if ((fe_type.order != FIRST) || (fe_type.family != LAGRANGE))
02411                 {
02412                   libMesh::err << "Only FIRST-order LAGRANGE variables can be read from GMV files. "
02413                                << "Skipping variable " << var_name << std::endl;
02414                   break;
02415                 }
02416 
02417 
02418               // Loop over the stored vector's entries, inserting them into
02419               // the System's solution if appropriate.
02420               for (unsigned int i=0; i<(*it).second.size(); ++i)
02421                 {
02422                   // Since this var came from a GMV file, the index i corresponds to
02423                   // the (single) DOF value of the current variable for node i.
02424                   const unsigned int dof_index =
02425                     MeshInput<MeshBase>::mesh().node_ptr(i)->dof_number(sys,      /*system #*/
02426                                                                         var_num,  /*var # */
02427                                                                         0);       /*component #, always zero for LAGRANGE */
02428 
02429                   // libMesh::out << "Value " << i << ": "
02430                   //     << (*it).second [i]
02431                   //     << ", dof index="
02432                   //     << dof_index << std::endl;
02433 
02434                   // If the dof_index is local to this processor, set the value
02435                   if ((dof_index >= system.solution->first_local_index()) &&
02436                       (dof_index <  system.solution->last_local_index()))
02437                     system.solution->set (dof_index, (*it).second [i]);
02438                 } // end loop over my GMVIO's copy of the solution
02439 
02440               // Add the most recently copied var to the set of copied vars
02441               vars_copied.insert (var_name);
02442             } // end if (system.has_variable)
02443         } // end for loop over _nodal_data
02444 
02445       // Communicate parallel values before going to the next system.
02446       system.solution->close();
02447       system.update();
02448 
02449     } // end loop over all systems
02450 
02451 
02452 
02453   // Warn the user if any GMV variables were not successfully copied over to the EquationSystems object
02454   {
02455     std::map<std::string, std::vector<Number> >::iterator it = _nodal_data.begin();
02456     const std::map<std::string, std::vector<Number> >::iterator end = _nodal_data.end();
02457 
02458     for (; it != end; ++it)
02459       {
02460         if (vars_copied.find( (*it).first ) == vars_copied.end())
02461           {
02462             libMesh::err << "Warning: Variable "
02463                          << (*it).first
02464                          << " was not copied to the EquationSystems object."
02465                          << std::endl;
02466           }
02467       }
02468   }
02469 
02470 }
02471 
02472 } // namespace libMesh