Line data Source code
1 : // The libMesh Finite Element Library.
2 : // Copyright (C) 2002-2025 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 : #ifndef LIBMESH_ABAQUS_IO_H
20 : #define LIBMESH_ABAQUS_IO_H
21 :
22 : // Local includes
23 : #include "libmesh/libmesh_common.h"
24 : #include "libmesh/mesh_input.h"
25 :
26 : // C++ includes
27 : #include <fstream>
28 : #include <memory>
29 : #include <set>
30 :
31 : namespace libMesh
32 : {
33 :
34 : /**
35 : * The AbaqusIO class is a preliminary implementation for reading
36 : * Abaqus mesh files in ASCII format.
37 : *
38 : * \author John W. Peterson
39 : * \date 2011
40 : */
41 8 : class AbaqusIO : public MeshInput<MeshBase>
42 : {
43 : public:
44 : /**
45 : * Constructor. Takes a writable reference to a mesh object.
46 : */
47 : explicit
48 : AbaqusIO (MeshBase & mesh);
49 :
50 : /**
51 : * Destructor.
52 : */
53 : virtual ~AbaqusIO ();
54 :
55 : /**
56 : * This method implements reading a mesh from a specified file.
57 : */
58 : virtual void read (const std::string & name) override;
59 :
60 : /**
61 : * Default false. Set this flag to true if you want libmesh to
62 : * automatically generate sidesets from Abaqus' nodesets. If the
63 : * Abaqus file already contains some sidesets, we ignore this flag
64 : * and don't generate sidesets, because the algorithm to do so
65 : * currently does not take into account existing sidesets.
66 : */
67 : bool build_sidesets_from_nodesets;
68 :
69 : protected:
70 : /**
71 : * The type of data structure used to store Node and Elemset IDs.
72 : */
73 : typedef std::map<std::string, std::vector<dof_id_type>> container_t;
74 :
75 : /**
76 : * Type of the data structure for storing the (elem ID, side) pairs
77 : * defining sidesets. These come from the *Surface sections of the
78 : * input file.
79 : */
80 : typedef std::map<std::string, std::vector<std::pair<dof_id_type, unsigned>>> sideset_container_t;
81 :
82 : /**
83 : * This function parses a block of nodes in the Abaqus file once
84 : * such a block has been found. If the *NODE section specifies an
85 : * NSET name, also pass that to this function.
86 : */
87 : void read_nodes(std::string nset_name);
88 :
89 : /**
90 : * This function parses a block of elements in the Abaqus file.
91 : * You must pass it an upper-cased version of the string declaring
92 : * this section, which is typically something like:
93 : * *ELEMENT, TYPE=CPS3
94 : * so that it can determine the type of elements to read.
95 : */
96 : void read_elements(std::string upper, std::string elset_name);
97 :
98 : /**
99 : * This function parses a label of the form foo=bar from a
100 : * comma-delimited line of the form
101 : * ..., foo=bar, ...
102 : * The input to the function in this case would be foo, the
103 : * output would be bar
104 : */
105 : std::string parse_label(std::string line, std::string label_name) const;
106 :
107 : /**
108 : * \returns \p true if the input string is a generated elset or nset,
109 : * false otherwise.
110 : *
111 : * The input string is assumed to already be in all upper
112 : * case. Generated nsets are assumed to have the following format:
113 : * *Nset, nset=Set-1, generate
114 : */
115 : bool detect_generated_set(std::string upper) const;
116 :
117 : /**
118 : * This function reads all the IDs for the current node or element
119 : * set of the given name, storing them in the passed map using the
120 : * name as key.
121 : */
122 : void read_ids(std::string set_name, container_t & container);
123 :
124 : /**
125 : * This function handles "generated" nset and elset sections. These
126 : * are denoted by having the comma-separated "GENERATE" keyword in
127 : * their definition, e.g.
128 : * *Nset, nset=Set-1, generate
129 : */
130 : void generate_ids(std::string set_name, container_t & container);
131 :
132 : /**
133 : * This function is called after all the elements have been
134 : * read and assigns element subdomain IDs.
135 : *
136 : * The IDs are simply chosen in the order in which the elset
137 : * labels are stored in the map (roughly alphabetically). To make
138 : * this easy on people who are planning to use Exodus output,
139 : * we'll assign different geometric elements to different (but
140 : * related) subdomains, i.e. assuming there are E elemsets:
141 : *
142 : * Elemset 0, Geometric Type 0: ID 0
143 : * Elemset 0, Geometric Type 1: ID 0+E
144 : * ...
145 : * Elemset 0, Geometric Type N: ID 0+N*E
146 : * --------------------------------------
147 : * Elemset 1, Geometric Type 0: ID 1
148 : * Elemset 1, Geometric Type 1: ID 1+E
149 : * ...
150 : * Elemset 1, Geometric Type N: ID 1+N*E
151 : * etc.
152 : */
153 : void assign_subdomain_ids();
154 :
155 : /**
156 : * This function reads a sideset from the input file. This is defined
157 : * by a "*Surface" section in the file, and then a list of element ID
158 : * and side IDs for the set.
159 : */
160 : void read_sideset(const std::string & sideset_name,
161 : const std::string & sideset_type,
162 : sideset_container_t & container);
163 :
164 : /**
165 : * This function assigns boundary IDs to node sets based on the
166 : * alphabetical order in which the sets are labeled in the Abaqus
167 : * file. We choose the alphabetical ordering simply because
168 : * Abaqus does not provide a numerical one within the file.
169 : */
170 : void assign_boundary_node_ids();
171 :
172 : /**
173 : * Called at the end of the read() function, assigns any sideset IDs
174 : * found when reading the file to the BoundaryInfo object.
175 : */
176 : void assign_sideset_ids();
177 :
178 : /**
179 : * Any of the various sections can start with some number of lines
180 : * of comments, which start with "**". This function discards
181 : * any lines of comments that it finds from the stream, leaving
182 : * trailing data intact.
183 : */
184 : void process_and_discard_comments();
185 :
186 : /**
187 : * \returns The maximum geometric element dimension encountered while
188 : * reading the Mesh.
189 : *
190 : * Only valid after the elements have been read in and the
191 : * elems_of_dimension array has been populated.
192 : */
193 : unsigned char max_elem_dimension_seen();
194 :
195 : /**
196 : * Abaqus writes nodesets and elemsets with labels. As we read
197 : * them in, we'll use these maps to provide a natural ordering for
198 : * them.
199 : */
200 : container_t _nodeset_ids;
201 : container_t _elemset_ids;
202 : sideset_container_t _sideset_ids;
203 :
204 : /**
205 : * Stream object used to interact with the file
206 : */
207 : std::unique_ptr<std::istream> _in;
208 :
209 : /**
210 : * A set of the different geometric element types detected when reading the
211 : * mesh.
212 : */
213 : std::set<ElemType> _elem_types;
214 :
215 : /**
216 : * This flag gets set to true after the first "*PART" section
217 : * we see. If it is still true when we see a second PART
218 : * section, we will print an error message... we don't currently
219 : * handle input files with multiple parts.
220 : */
221 : bool _already_seen_part;
222 :
223 : /**
224 : * Attempts to convert the input string to a numerical value using
225 : * strtol. If the conversion fails, 0 will be stored in the output,
226 : * so you must check the return value, which will be true if the
227 : * conversion succeeded, and false if it failed for any reason.
228 : */
229 : bool string_to_num(const std::string &input, dof_id_type &output) const;
230 :
231 : /**
232 : * Removes all whitespace characters from "line". Simpler than trying
233 : * to remember the erase-remove-if idiom.
234 : */
235 : void strip_ws(std::string &line) const;
236 :
237 : /**
238 : * Override this callback to implement support for more sections in
239 : * derived classes.
240 : */
241 1284 : virtual void extended_parsing(const std::string & /*header*/) {}
242 : };
243 :
244 : } // namespace
245 :
246 : #endif // LIBMESH_ABAQUS_IO_H
|