libMesh
Loading...
Searching...
No Matches
fro_io.C
Go to the documentation of this file.
1// The libMesh Finite Element Library.
2// Copyright (C) 2002-2026 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3
4// This library is free software; you can redistribute it and/or
5// modify it under the terms of the GNU Lesser General Public
6// License as published by the Free Software Foundation; either
7// version 2.1 of the License, or (at your option) any later version.
8
9// This library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12// Lesser General Public License for more details.
13
14// You should have received a copy of the GNU Lesser General Public
15// License along with this library; if not, write to the Free Software
16// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
18
19
20// C++ includes
21#include <fstream>
22#include <iomanip>
23#include <iostream>
24#include <deque>
25#include <map>
26
27// Local includes
28#include "libmesh/libmesh_config.h"
29#include "libmesh/fro_io.h"
30#include "libmesh/mesh_base.h"
31#include "libmesh/boundary_info.h"
32#include "libmesh/elem.h"
33
34namespace libMesh
35{
36
37
38
39// ------------------------------------------------------------
40// FroIO members
41void FroIO::write (const std::string & fname)
42{
43 // We may need to gather a DistributedMesh to output it, making that
44 // const qualifier in our constructor a dirty lie
45 MeshSerializer serialize(const_cast<MeshBase &>(this->mesh()), !_is_parallel_format);
46
47 if (this->mesh().processor_id() == 0)
48 {
49 // Open the output file stream
50 std::ofstream out_stream (fname.c_str());
51 libmesh_assert (out_stream.good());
52
53 // Make sure it opened correctly
54 if (!out_stream.good())
55 libmesh_file_error(fname.c_str());
56
57 // Get a reference to the mesh
58 const MeshBase & the_mesh = MeshOutput<MeshBase>::mesh();
59
60 // Write the header
61 out_stream << the_mesh.n_elem() << " "
62 << the_mesh.n_nodes() << " "
63 << "0 0 "
64 << the_mesh.get_boundary_info().n_boundary_ids() << " 1\n";
65
66 // Write the nodes -- 1-based!
67 for (auto n : make_range(the_mesh.n_nodes()))
68 out_stream << n+1 << " \t"
69 << std::scientific
70 << std::setprecision(this->ascii_precision())
71 << the_mesh.point(n)(0) << " \t"
72 << the_mesh.point(n)(1) << " \t"
73 << 0. << '\n';
74
75 // Write the elements -- 1-based!
76 unsigned int e = 0;
77 for (const auto & elem : the_mesh.active_element_ptr_range())
78 {
79 // .fro likes TRI3's
80 libmesh_error_msg_if(elem->type() != TRI3,
81 "ERROR: .fro format only valid for triangles!\n"
82 << " writing of " << fname << " aborted.");
83
84 out_stream << ++e << " \t";
85
86 for (const Node & node : elem->node_ref_range())
87 out_stream << node.id()+1 << " \t";
88
89 // // LHS -> RHS Mapping, for inverted triangles
90 // out_stream << elem->node_id(0)+1 << " \t";
91 // out_stream << elem->node_id(2)+1 << " \t";
92 // out_stream << elem->node_id(1)+1 << " \t";
93
94 out_stream << "1\n";
95 }
96
97 // Write BCs.
98 {
99 const std::set<boundary_id_type> & bc_ids =
101
102 // Build a list of (elem, side, bc) tuples.
103 auto bc_triples = the_mesh.get_boundary_info().build_side_list();
104
105 // Map the boundary ids into [1,n_bc_ids],
106 // treat them one at a time.
107 boundary_id_type bc_id=0;
108 for (const auto & id : bc_ids)
109 {
110 std::deque<dof_id_type> node_list;
111
112 std::map<dof_id_type, dof_id_type>
113 forward_edges, backward_edges;
114
115 // Get all sides on this element with the relevant BC id.
116 for (const auto & t : bc_triples)
117 if (std::get<2>(t) == id)
118 {
119 // need to build up node_list as a sorted array of edge nodes...
120 // for the following:
121 // a---b---c---d---e
122 // node_list [ a b c d e];
123 //
124 // the issue is just how to get this out of the elem/side based data structure.
125 // the approach is to build up 'chain links' like this:
126 // a---b b---c c---d d---e
127 // and piece them together.
128 //
129 // so, for an arbitrary edge n0---n1, we build the
130 // "forward_edges" map n0-->n1
131 // "backward_edges" map n1-->n0
132 // and then start with one chain link, and add on...
133 //
134 std::unique_ptr<const Elem> side =
135 the_mesh.elem_ref(std::get<0>(t)).build_side_ptr(std::get<1>(t));
136
137 const dof_id_type
138 n0 = side->node_id(0),
139 n1 = side->node_id(1);
140
141 // insert into forward-edge set
142 forward_edges.emplace(n0, n1);
143
144 // insert into backward-edge set
145 backward_edges.emplace(n1, n0);
146
147 // go ahead and add one edge to the list -- this will give us the beginning of a
148 // chain to work from!
149 if (node_list.empty())
150 {
151 node_list.push_front(n0);
152 node_list.push_back (n1);
153 }
154 }
155
156 // we now have the node_list with one edge, the forward_edges, and the backward_edges
157 // the node_list will be filled when (node_list.size() == (n_edges+1))
158 // until that is the case simply add on to the beginning and end of the node_list,
159 // building up a chain of ordered nodes...
160 const std::size_t n_edges = forward_edges.size();
161
162 while (node_list.size() != (n_edges+1))
163 {
164 const dof_id_type
165 front_node = node_list.front(),
166 back_node = node_list.back();
167
168 // look for front_pair in the backward_edges list
169 if (const auto pos = backward_edges.find(front_node);
170 pos != backward_edges.end())
171 {
172 node_list.push_front(pos->second);
173 backward_edges.erase(pos);
174 }
175
176 // look for back_pair in the forward_edges list
177 if (const auto pos = forward_edges.find(back_node);
178 pos != forward_edges.end())
179 {
180 node_list.push_back(pos->second);
181 forward_edges.erase(pos);
182 }
183 }
184
185 out_stream << ++bc_id << " " << node_list.size() << '\n';
186
187 for (const auto & node_id : node_list)
188 out_stream << node_id + 1 << " \t0\n";
189 }
190 }
191 }
192}
193
194} // namespace libMesh
std::size_t n_boundary_ids() const
std::vector< BCTuple > build_side_list(BCTupleSortBy sort_by=BCTupleSortBy::ELEM_ID) const
const std::set< boundary_id_type > & get_boundary_ids() const
dof_id_type node_id(const unsigned int i) const
Definition elem.h:2484
virtual void write(const std::string &) override
This method implements writing a mesh to a specified file.
Definition fro_io.C:41
This is the MeshBase class.
Definition mesh_base.h:81
virtual const Point & point(const dof_id_type i) const =0
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
Definition mesh_base.h:170
virtual dof_id_type n_elem() const =0
virtual dof_id_type n_nodes() const =0
virtual const Elem & elem_ref(const dof_id_type i) const
Definition mesh_base.h:788
const bool _is_parallel_format
Flag specifying whether this format is parallel-capable.
unsigned int & ascii_precision()
Return/set the precision to use when writing ASCII files.
const MeshBase & mesh() const
Temporarily serialize a DistributedMesh for non-distributed-mesh capable code paths.
A Node is like a Point, but with more information.
Definition node.h:55
The libMesh namespace provides an interface to certain functionality in the library.
int8_t boundary_id_type
Definition id_types.h:51
libmesh_assert(ctx)
uint8_t dof_id_type
Definition id_types.h:67
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
Definition int_range.h:176