$extrastylesheet
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 00019 00020 // C++ includes 00021 #include <fstream> 00022 #include <iomanip> 00023 #include <iostream> 00024 #include <deque> 00025 #include <map> 00026 00027 // Local includes 00028 #include "libmesh/libmesh_config.h" 00029 #include "libmesh/fro_io.h" 00030 #include "libmesh/mesh_base.h" 00031 #include "libmesh/boundary_info.h" 00032 #include "libmesh/elem.h" 00033 00034 namespace libMesh 00035 { 00036 00037 00038 00039 // ------------------------------------------------------------ 00040 // FroIO members 00041 void FroIO::write (const std::string& fname) 00042 { 00043 // We may need to gather a ParallelMesh to output it, making that 00044 // const qualifier in our constructor a dirty lie 00045 MeshSerializer serialize(const_cast<MeshBase&>(this->mesh()), !_is_parallel_format); 00046 00047 if (this->mesh().processor_id() == 0) 00048 { 00049 // Open the output file stream 00050 std::ofstream out_stream (fname.c_str()); 00051 libmesh_assert (out_stream.good()); 00052 00053 // Make sure it opened correctly 00054 if (!out_stream.good()) 00055 libmesh_file_error(fname.c_str()); 00056 00057 // Get a reference to the mesh 00058 const MeshBase& the_mesh = MeshOutput<MeshBase>::mesh(); 00059 00060 // Write the header 00061 out_stream << the_mesh.n_elem() << " " 00062 << the_mesh.n_nodes() << " " 00063 << "0 0 " 00064 << the_mesh.get_boundary_info().n_boundary_ids() << " 1\n"; 00065 00066 // Write the nodes -- 1-based! 00067 for (unsigned int n=0; n<the_mesh.n_nodes(); n++) 00068 out_stream << n+1 << " \t" 00069 << std::scientific 00070 << std::setprecision(12) 00071 << the_mesh.point(n)(0) << " \t" 00072 << the_mesh.point(n)(1) << " \t" 00073 << 0. << '\n'; 00074 00075 // Write the elements -- 1-based! 00076 MeshBase::const_element_iterator it = the_mesh.active_elements_begin(); 00077 const MeshBase::const_element_iterator end = the_mesh.active_elements_end(); 00078 00079 for (unsigned int e=0 ; it != end; ++it) 00080 { 00081 // .fro likes TRI3's 00082 if ((*it)->type() != TRI3) 00083 libmesh_error_msg("ERROR: .fro format only valid for triangles!\n" \ 00084 << " writing of " << fname << " aborted."); 00085 00086 out_stream << ++e << " \t"; 00087 00088 for (unsigned int n=0; n<(*it)->n_nodes(); n++) 00089 out_stream << (*it)->node(n)+1 << " \t"; 00090 00091 // // LHS -> RHS Mapping, for inverted triangles 00092 // out_stream << (*it)->node(0)+1 << " \t"; 00093 // out_stream << (*it)->node(2)+1 << " \t"; 00094 // out_stream << (*it)->node(1)+1 << " \t"; 00095 00096 out_stream << "1\n"; 00097 } 00098 00099 // Write BCs. 00100 { 00101 const std::set<boundary_id_type>& bc_ids = 00102 the_mesh.get_boundary_info().get_boundary_ids(); 00103 00104 std::vector<dof_id_type> el; 00105 std::vector<unsigned short int> sl; 00106 std::vector<boundary_id_type> il; 00107 00108 the_mesh.get_boundary_info().build_side_list (el, sl, il); 00109 00110 00111 // Map the boundary ids into [1,n_bc_ids], 00112 // treat them one at a time. 00113 boundary_id_type bc_id=0; 00114 for (std::set<boundary_id_type>::const_iterator id = bc_ids.begin(); 00115 id != bc_ids.end(); ++id) 00116 { 00117 std::deque<dof_id_type> node_list; 00118 00119 std::map<dof_id_type, dof_id_type> 00120 forward_edges, backward_edges; 00121 00122 // Get all sides on this element with the relevant BC id. 00123 for (std::size_t e=0; e<el.size(); e++) 00124 if (il[e] == *id) 00125 { 00126 // need to build up node_list as a sorted array of edge nodes... 00127 // for the following: 00128 // a---b---c---d---e 00129 // node_list [ a b c d e]; 00130 // 00131 // the issue is just how to get this out of the elem/side based data structure. 00132 // the approach is to build up 'chain links' like this: 00133 // a---b b---c c---d d---e 00134 // and piece them together. 00135 // 00136 // so, for an arbitray edge n0---n1, we build the 00137 // "forward_edges" map n0-->n1 00138 // "backward_edges" map n1-->n0 00139 // and then start with one chain link, and add on... 00140 // 00141 UniquePtr<Elem> side = the_mesh.elem(el[e])->build_side(sl[e]); 00142 00143 const dof_id_type 00144 n0 = side->node(0), 00145 n1 = side->node(1); 00146 00147 // insert into forward-edge set 00148 forward_edges.insert (std::make_pair(n0, n1)); 00149 00150 // insert into backward-edge set 00151 backward_edges.insert (std::make_pair(n1, n0)); 00152 00153 // go ahead and add one edge to the list -- this will give us the beginning of a 00154 // chain to work from! 00155 if (node_list.empty()) 00156 { 00157 node_list.push_front(n0); 00158 node_list.push_back (n1); 00159 } 00160 } 00161 00162 // we now have the node_list with one edge, the forward_edges, and the backward_edges 00163 // the node_list will be filled when (node_list.size() == (n_edges+1)) 00164 // until that is the case simply add on to the beginning and end of the node_list, 00165 // building up a chain of ordered nodes... 00166 const std::size_t n_edges = forward_edges.size(); 00167 00168 while (node_list.size() != (n_edges+1)) 00169 { 00170 const dof_id_type 00171 front_node = node_list.front(), 00172 back_node = node_list.back(); 00173 00174 // look for front_pair in the backward_edges list 00175 { 00176 std::map<dof_id_type, dof_id_type>::iterator 00177 pos = backward_edges.find(front_node); 00178 00179 if (pos != backward_edges.end()) 00180 { 00181 node_list.push_front(pos->second); 00182 00183 backward_edges.erase(pos); 00184 } 00185 } 00186 00187 // look for back_pair in the forward_edges list 00188 { 00189 std::map<dof_id_type, dof_id_type>::iterator 00190 pos = forward_edges.find(back_node); 00191 00192 if (pos != forward_edges.end()) 00193 { 00194 node_list.push_back(pos->second); 00195 00196 forward_edges.erase(pos); 00197 } 00198 } 00199 00200 // libMesh::out << "node_list.size()=" << node_list.size() 00201 // << ", n_edges+1=" << n_edges+1 << std::endl; 00202 } 00203 00204 00205 out_stream << ++bc_id << " " << node_list.size() << '\n'; 00206 00207 std::deque<dof_id_type>::iterator pos = node_list.begin(); 00208 for ( ; pos != node_list.end(); ++pos) 00209 out_stream << *pos+1 << " \t0\n"; 00210 } 00211 } 00212 } 00213 } 00214 00215 } // namespace libMesh