1 #include <iostream>
2 #include <cstdlib>
3 #include "moab/Range.hpp"
4 #include "moab/Core.hpp"
5 #include "MBTagConventions.hpp"
6 #include "moab/GeomTopoTool.hpp"
7
8 using namespace moab;
9
10 Tag geomTag = 0;
11 Tag blockTag = 0;
12 Tag sideTag = 0;
13 Tag nodeTag = 0;
14 Tag nameTag = 0;
15 Tag idTag = 0;
16 bool printAnonSets = false;
17 bool printSVSense = false;
18
19 Core mb;
20 GeomTopoTool geomTool( &mb );
21
22 static void usage( const char* name, bool brief = true )
23 {
24 std::ostream& str = brief ? std::cerr : std::cout;
25 if( !brief )
26 str << name << ": A tool to export entity set parent/child relations" << std::endl
27 << " for use as input to graphviz" << std::endl;
28 str << "Usage: " << name << " [-a | [-g] [-m] [-n] ] <input_file>" << std::endl
29 << " " << name << " -h" << std::endl;
30 if( brief ) exit( 1 );
31 str << " The default behavior is equivalent to \"-gmn\"." << std::endl
32 << " If any of the following options are used to specify which " << std::endl
33 << " sets to output, then there are no defaults. Only the " << std::endl
34 << " indicated sets will be output." << std::endl
35 << " -a : write all sets (default is only geom, mesh, and named)" << std::endl
36 << " -g : write geometric topology sets" << std::endl
37 << " -m : write material sets and boundary condition sets" << std::endl
38 << " -n : write named sets" << std::endl
39 << " -s : label surface-volume links with sense" << std::endl
40 << " The default link behavior is to both child links" << std::endl
41 << " and containment with solid lines." << std::endl
42 << " -P : do not write child links" << std::endl
43 << " -p : write child links with dashed lines" << std::endl
44 << " -C : do not write containment links" << std::endl
45 << " -c : write containment links with dashed lines" << std::endl;
46 exit( 0 );
47 }
48
49 enum Link
50 {
51 NONE = 0,
52 SOLID,
53 DASHED
54 };
55 static void write_dot( Link contained, Link children );
56 static void dot_nodes( std::ostream& s, Range& sets_out );
57 static void dot_children( std::ostream& s, const Range& sets, bool dashed );
58 static void dot_contained( std::ostream& s, const Range& sets, bool dashed );
59
60 int main( int argc, char* argv[] )
61 {
62 Link children = SOLID, contained = SOLID;
63 bool printGeomSets = true;
64 bool printMeshSets = true;
65 bool printNamedSets = true;
66 const char* input_file = 0;
67 bool geom_flag = false, mesh_flag = false, name_flag = false, all_flag = false;
68 bool no_more_flags = false;
69 for( int i = 1; i < argc; ++i )
70 {
71 if( no_more_flags || argv[i][0] != '-' )
72 {
73 if( input_file ) usage( argv[0] );
74 input_file = argv[i];
75 continue;
76 }
77 for( int j = 1; argv[i][j]; ++j )
78 {
79 switch( argv[i][j] )
80 {
81 case 'a':
82 all_flag = true;
83 break;
84 case 'g':
85 geom_flag = true;
86 break;
87 case 'm':
88 mesh_flag = true;
89 break;
90 case 'n':
91 name_flag = true;
92 break;
93 case 's':
94 printSVSense = true;
95 break;
96 case 'P':
97 children = NONE;
98 break;
99 case 'p':
100 children = DASHED;
101 break;
102 case 'C':
103 contained = NONE;
104 break;
105 case 'c':
106 contained = DASHED;
107 break;
108 case '-':
109 no_more_flags = true;
110 break;
111 case 'h':
112 usage( argv[0], false );
113 break;
114 default:
115 std::cerr << "Unknown flag: '" << argv[i][j] << "'" << std::endl;
116 usage( argv[0] );
117 }
118 }
119 }
120
121 if( !input_file )
122 {
123 std::cerr << "No input file specified." << std::endl;
124 usage( argv[0] );
125 }
126
127 if( all_flag )
128 {
129 printGeomSets = printMeshSets = printNamedSets = printAnonSets = true;
130 }
131 else if( geom_flag || mesh_flag || name_flag )
132 {
133 printGeomSets = geom_flag;
134 printMeshSets = mesh_flag;
135 printNamedSets = name_flag;
136 }
137
138 if( MB_SUCCESS != mb.load_mesh( input_file ) )
139 {
140 std::cerr << input_file << ": file read failed." << std::endl;
141 return 1;
142 }
143
144 Tag t;
145 if( printGeomSets )
146 {
147 if( MB_SUCCESS == mb.tag_get_handle( GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, t ) )
148 {
149 geomTag = t;
150 }
151 }
152 if( printMeshSets )
153 {
154 if( MB_SUCCESS == mb.tag_get_handle( MATERIAL_SET_TAG_NAME, 1, MB_TYPE_INTEGER, t ) )
155 {
156 blockTag = t;
157 }
158 if( MB_SUCCESS == mb.tag_get_handle( DIRICHLET_SET_TAG_NAME, 1, MB_TYPE_INTEGER, t ) )
159 {
160 nodeTag = t;
161 }
162 if( MB_SUCCESS == mb.tag_get_handle( NEUMANN_SET_TAG_NAME, 1, MB_TYPE_INTEGER, t ) )
163 {
164 sideTag = t;
165 }
166 }
167 if( printNamedSets )
168 {
169 if( MB_SUCCESS == mb.tag_get_handle( NAME_TAG_NAME, NAME_TAG_SIZE, MB_TYPE_OPAQUE, t ) )
170 {
171 nameTag = t;
172 }
173 }
174 idTag = mb.globalId_tag();
175
176 write_dot( contained, children );
177 return 0;
178 }
179
180 void write_dot( Link contained, Link children )
181 {
182 Range sets;
183 std::cout << "digraph {" << std::endl;
184 dot_nodes( std::cout, sets );
185 std::cout << std::endl;
186 if( contained ) dot_contained( std::cout, sets, contained == DASHED );
187 if( children ) dot_children( std::cout, sets, children == DASHED );
188 std::cout << "}" << std::endl;
189 }
190
191 static void dot_get_sets( Range& curr_sets, Range& result_sets, Tag tag, void* tag_val = 0 )
192 {
193 if( !tag ) return;
194
195 result_sets.clear();
196 mb.get_entities_by_type_and_tag( 0, MBENTITYSET, &tag, &tag_val, 1, result_sets );
197 result_sets = subtract( result_sets, curr_sets );
198 curr_sets.merge( result_sets );
199 }
200
201 static void dot_write_node( std::ostream& s, EntityHandle h, const char* label, int* id = 0 )
202 {
203 s << 's' << mb.id_from_handle( h ) << " [label = \"" << label;
204 if( id ) s << ' ' << *id;
205 s << "\"];" << std::endl;
206 }
207
208 static void dot_write_id_nodes( std::ostream& s, const Range& entites, Tag id_tag, const char* type_name )
209 {
210 int id;
211 for( Range::iterator i = entites.begin(); i != entites.end(); ++i )
212 if( MB_SUCCESS == mb.tag_get_data( id_tag, &*i, 1, &id ) ) dot_write_node( s, *i, type_name, &id );
213 }
214
215 void dot_nodes( std::ostream& s, Range& sets )
216 {
217 Range vol_sets, surf_sets, curv_sets, vert_sets;
218 Range block_sets, side_sets, node_sets;
219 Range named_sets, other_sets;
220
221 dot_get_sets( sets, named_sets, nameTag );
222
223 int dim = 3;
224 dot_get_sets( sets, vol_sets, geomTag, &dim );
225 dim = 2;
226 dot_get_sets( sets, surf_sets, geomTag, &dim );
227 dim = 1;
228 dot_get_sets( sets, curv_sets, geomTag, &dim );
229 dim = 0;
230 dot_get_sets( sets, vert_sets, geomTag, &dim );
231
232 dot_get_sets( sets, block_sets, blockTag );
233 dot_get_sets( sets, side_sets, sideTag );
234 dot_get_sets( sets, node_sets, nodeTag );
235
236 if( printAnonSets )
237 {
238 mb.get_entities_by_type( 0, MBENTITYSET, other_sets );
239 Range xsect = subtract( other_sets, sets );
240 sets.swap( other_sets );
241 other_sets.swap( xsect );
242 }
243
244 dot_write_id_nodes( s, vol_sets, idTag, "Volume" );
245 dot_write_id_nodes( s, surf_sets, idTag, "Surface" );
246 dot_write_id_nodes( s, curv_sets, idTag, "Curve" );
247 dot_write_id_nodes( s, vert_sets, idTag, "Vertex" );
248 dot_write_id_nodes( s, block_sets, blockTag, "Block" );
249 dot_write_id_nodes( s, side_sets, sideTag, "Neumann Set" );
250 dot_write_id_nodes( s, node_sets, nodeTag, "Dirichlet Set" );
251
252 Range::iterator i;
253 char name[NAME_TAG_SIZE + 1];
254 for( i = named_sets.begin(); i != named_sets.end(); ++i )
255 {
256 if( MB_SUCCESS == mb.tag_get_data( nameTag, &*i, 1, name ) )
257 {
258 name[NAME_TAG_SIZE] = '\0';
259 dot_write_node( s, *i, name );
260 }
261 }
262 for( i = other_sets.begin(); i != other_sets.end(); ++i )
263 {
264 int id = mb.id_from_handle( *i );
265 dot_write_node( s, *i, "EntitySet ", &id );
266 }
267 }
268
269 static void dot_down_link( std::ostream& s,
270 EntityHandle parent,
271 EntityHandle child,
272 bool dashed,
273 const char* label = 0 )
274 {
275 s << 's' << mb.id_from_handle( parent ) << " -> " << 's' << mb.id_from_handle( child );
276 if( dashed && label )
277 s << " [style = dashed label = \"" << label << "\"]";
278 else if( dashed )
279 s << " [style = dashed]";
280 else if( label )
281 s << " [label = \"" << label << "\"]";
282 s << ';' << std::endl;
283 }
284
285 void dot_children( std::ostream& s, const Range& sets, bool dashed )
286 {
287 int sense;
288 const char *fstr = "forward", *rstr = "reverse";
289 for( Range::iterator i = sets.begin(); i != sets.end(); ++i )
290 {
291 Range parents;
292 mb.get_parent_meshsets( *i, parents );
293 parents = intersect( parents, sets );
294
295 for( Range::iterator j = parents.begin(); j != parents.end(); ++j )
296 {
297 const char* linklabel = 0;
298 if( printSVSense && MB_SUCCESS == geomTool.get_sense( *i, *j, sense ) )
299
300
301 linklabel = ( sense == (int)SENSE_FORWARD ) ? fstr : rstr;
302
303 dot_down_link( s, *j, *i, dashed, linklabel );
304 }
305 }
306 }
307
308 void dot_contained( std::ostream& s, const Range& sets, bool dashed )
309 {
310 for( Range::iterator i = sets.begin(); i != sets.end(); ++i )
311 {
312 Range contained;
313 mb.get_entities_by_type( *i, MBENTITYSET, contained );
314 contained = intersect( contained, sets );
315
316 for( Range::iterator j = contained.begin(); j != contained.end(); ++j )
317 dot_down_link( s, *i, *j, dashed );
318 }
319 }