fro_io.C
Go to the documentation of this file.00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2012 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 (libMesh::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.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 { 00084 libMesh::err << "ERROR: .fro format only valid for triangles!\n" 00085 << " writing of " << fname << " aborted.\n" 00086 << std::endl; 00087 libmesh_error(); 00088 } 00089 00090 out_stream << ++e << " \t"; 00091 00092 for (unsigned int n=0; n<(*it)->n_nodes(); n++) 00093 out_stream << (*it)->node(n)+1 << " \t"; 00094 00095 // // LHS -> RHS Mapping, for inverted triangles 00096 // out_stream << (*it)->node(0)+1 << " \t"; 00097 // out_stream << (*it)->node(2)+1 << " \t"; 00098 // out_stream << (*it)->node(1)+1 << " \t"; 00099 00100 out_stream << "1\n"; 00101 } 00102 00103 // Write BCs. 00104 { 00105 const std::set<boundary_id_type>& bc_ids = 00106 the_mesh.boundary_info->get_boundary_ids(); 00107 00108 std::vector<dof_id_type> el; 00109 std::vector<unsigned short int> sl; 00110 std::vector<boundary_id_type> il; 00111 00112 the_mesh.boundary_info->build_side_list (el, sl, il); 00113 00114 00115 // Map the boundary ids into [1,n_bc_ids], 00116 // treat them one at a time. 00117 boundary_id_type bc_id=0; 00118 for (std::set<boundary_id_type>::const_iterator id = bc_ids.begin(); 00119 id != bc_ids.end(); ++id) 00120 { 00121 std::deque<dof_id_type> node_list; 00122 00123 std::map<dof_id_type, dof_id_type> 00124 forward_edges, backward_edges; 00125 00126 // Get all sides on this element with the relevant BC id. 00127 for (std::size_t e=0; e<el.size(); e++) 00128 if (il[e] == *id) 00129 { 00130 // need to build up node_list as a sorted array of edge nodes... 00131 // for the following: 00132 // a---b---c---d---e 00133 // node_list [ a b c d e]; 00134 // 00135 // the issue is just how to get this out of the elem/side based data structure. 00136 // the approach is to build up 'chain links' like this: 00137 // a---b b---c c---d d---e 00138 // and piece them together. 00139 // 00140 // so, for an arbitray edge n0---n1, we build the 00141 // "forward_edges" map n0-->n1 00142 // "backward_edges" map n1-->n0 00143 // and then start with one chain link, and add on... 00144 // 00145 AutoPtr<Elem> side = the_mesh.elem(el[e])->build_side(sl[e]); 00146 00147 const dof_id_type 00148 n0 = side->node(0), 00149 n1 = side->node(1); 00150 00151 // insert into forward-edge set 00152 forward_edges.insert (std::make_pair(n0, n1)); 00153 00154 // insert into backward-edge set 00155 backward_edges.insert (std::make_pair(n1, n0)); 00156 00157 // go ahead and add one edge to the list -- this will give us the beginning of a 00158 // chain to work from! 00159 if (node_list.empty()) 00160 { 00161 node_list.push_front(n0); 00162 node_list.push_back (n1); 00163 } 00164 } 00165 00166 // we now have the node_list with one edge, the forward_edges, and the backward_edges 00167 // the node_list will be filled when (node_list.size() == (n_edges+1)) 00168 // until that is the case simply add on to the beginning and end of the node_list, 00169 // building up a chain of ordered nodes... 00170 const std::size_t n_edges = forward_edges.size(); 00171 00172 while (node_list.size() != (n_edges+1)) 00173 { 00174 const dof_id_type 00175 front_node = node_list.front(), 00176 back_node = node_list.back(); 00177 00178 // look for front_pair in the backward_edges list 00179 { 00180 std::map<dof_id_type, dof_id_type>::iterator 00181 pos = backward_edges.find(front_node); 00182 00183 if (pos != backward_edges.end()) 00184 { 00185 node_list.push_front(pos->second); 00186 00187 backward_edges.erase(pos); 00188 } 00189 } 00190 00191 // look for back_pair in the forward_edges list 00192 { 00193 std::map<dof_id_type, dof_id_type>::iterator 00194 pos = forward_edges.find(back_node); 00195 00196 if (pos != forward_edges.end()) 00197 { 00198 node_list.push_back(pos->second); 00199 00200 forward_edges.erase(pos); 00201 } 00202 } 00203 00204 // libMesh::out << "node_list.size()=" << node_list.size() 00205 // << ", n_edges+1=" << n_edges+1 << std::endl; 00206 } 00207 00208 00209 out_stream << ++bc_id << " " << node_list.size() << '\n'; 00210 00211 std::deque<dof_id_type>::iterator pos = node_list.begin(); 00212 for ( ; pos != node_list.end(); ++pos) 00213 out_stream << *pos+1 << " \t0\n"; 00214 } 00215 } 00216 } 00217 } 00218 00219 } // namespace libMesh
Site Created By: libMesh Developers
Last modified: February 05 2013 19:54:47 UTC
Hosted By: