moab
|
00001 /* 00002 * Copyright (c) 2005 Lawrence Livermore National Laboratory under 00003 * contract number B545069 with the University of Wisconsin - Madison. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 00014 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 00015 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00016 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 00017 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 00018 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 00019 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00020 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00021 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00022 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 00023 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00024 */ 00025 00026 #include <iostream> 00027 #include <vector> 00028 #include <cstdlib> 00029 00030 #include "parse.hpp" 00031 00032 #include "moab/Core.hpp" 00033 #include "moab/Range.hpp" 00034 #include "moab/Interface.hpp" 00035 #define IS_BUILDING_MB 00036 #include "Internals.hpp" 00037 #undef IS_BUILDING_MB 00038 00039 using namespace moab; 00040 00041 #define CALL(A,B) \ 00042 do { ErrorCode _r = iface->A B ; \ 00043 if (MB_SUCCESS != _r) { \ 00044 std::cerr << #A << #B << " failed at " << __FILE__ << ":" << __LINE__ << std::endl; \ 00045 exit( 5 ); }\ 00046 } \ 00047 while (false) 00048 00049 00050 Interface* iface = 0; 00051 const char* exe_name = 0; 00052 00053 static void usage( bool error = true ) 00054 { 00055 std::ostream& s = error ? std::cerr : std::cout; 00056 00057 s << "Usage: " << exe_name << " <options> <input_file> <output_file>" << std::endl 00058 << " " << exe_name << " -h" << std::endl 00059 << "Options: " << std::endl 00060 << " -t <ident_tag>[=<value>] " << std::endl 00061 << " -d <data_tag>[=<default>] " << std::endl 00062 << " -c <data_tag=type:size>[=defult] " << std::endl 00063 << " -w <write_tag> " << std::endl 00064 << " -n|-e|-E " << std::endl 00065 << std::endl; 00066 if (error) { 00067 s << "Try '-h' for verbose help." << std::endl; 00068 exit(1); 00069 } 00070 00071 s << "This utility will write tag data to a subset of the mesh entities " << std::endl 00072 << "contained in a file. The behavior is controlled by three main " << std::endl 00073 << "properties:" << std::endl 00074 << " 1) The ident_tag is used to identify sets of entities for which " << std::endl 00075 << " data will be stored on each contained element or node. The -n " << std::endl 00076 << " or -e flags can be used to restrict operation to only nodes or " << std::endl 00077 << " elements, respectively." << std::endl 00078 << " 2) The data_tag is used to identify which value to write on to " << std::endl 00079 << " each entity. This is a tag on the set containing the entities." << std::endl 00080 << " 3) The write_tag is the name of the tag that the data is stored in " << std::endl 00081 << " on each mesh entity." << std::endl 00082 << std::endl 00083 << " -t : Specify an ident_tag. If a value is specified, only those " << std::endl 00084 << " sets with the specified value are processed. At least one " << std::endl 00085 << " ident_tag must be specified. Multiple ident_tags may be " << std::endl 00086 << " specified, in which case any set that matches any of the " << std::endl 00087 << " specified ident_tags will be processed (logical OR)." << std::endl 00088 << std::endl 00089 << " -d : Specify the data_tag. If multiple ident_tags are specified " << std::endl 00090 << " then the data_tag must be specified. If only one ident_tag " << std::endl 00091 << " is specified then the data_tag specification is optional." << std::endl 00092 << " If no data_tag is specified, the value of the ident_tag " << std::endl 00093 << " will be used. If a value is specified for the data_tag, " << std::endl 00094 << " then the specified value will be used for any set that " << std::endl 00095 << " doesn't have a value for the data_tag." << std::endl 00096 << std::endl 00097 << " -c : Similar to -d, except that the tag is created if it doesn't" << std::endl 00098 << " already exist. If the tag is created, then all entities" << std::endl 00099 << " receive the specified default value for the tag. In this " << std::endl 00100 << " case it is an error if no default value is specified." << std::endl 00101 << std::endl 00102 << " -w : Specify the tag to create and store values in on mesh " << std::endl 00103 << " entities. If no write_tag is specified, the data_tag " << std::endl 00104 << " will be used." << std::endl 00105 << std::endl 00106 << " -n : Write tag data only on nodes (vertices)." << std::endl 00107 << " -e : Write tag data only on elements." << std::endl 00108 << " -E : Tag value on each node is that of one of its adjacent elements." << std::endl 00109 << std::endl 00110 << "The syntax for specifying tag values is as follows: " 00111 << std::endl << std::endl; 00112 tag_syntax(s); 00113 s << std::endl; 00114 exit(0); 00115 } 00116 00117 static void about( bool error = true ) 00118 { 00119 std::ostream& s = error ? std::cerr : std::cout; 00120 s << "A utility to propogate tag values from the entity sets " 00121 "containing mesh entities to the entities contained in " 00122 "those sets." << std::endl << std::endl; 00123 usage(error); 00124 } 00125 00126 static void parse_error( const char* msg, const char* val = 0 ) 00127 { 00128 std::cerr << msg; 00129 if (val) 00130 std::cerr << ": " << val; 00131 std::cerr << std::endl; 00132 std::cerr << "Try '" << exe_name << " -h' for help" << std::endl; 00133 exit(1); 00134 } 00135 00136 int main( int argc, char* argv[] ) 00137 { 00138 Core mb_core; 00139 exe_name = argv[0]; 00140 iface = &mb_core; 00141 00142 if (argc == 1) 00143 about(); 00144 00145 // find file names 00146 // load input file before processing other options so 00147 // tags are defined 00148 const char* input_name = 0; 00149 const char* output_name = 0; 00150 for (int i = 1; i < argc; ++i) 00151 { 00152 if (argv[i][0] == '-') 00153 { 00154 switch (argv[i][1]) { 00155 case 't': case 'c': case 'd': case 'w': 00156 ++i; 00157 case 'n': case 'e': case 'E': 00158 break; 00159 case 'h': 00160 usage(false); 00161 break; 00162 default: 00163 parse_error( "Invalid option", argv[i] ); 00164 break; 00165 } 00166 } 00167 else if (!input_name) 00168 input_name = argv[i]; 00169 else if (!output_name) 00170 output_name = argv[i]; 00171 else 00172 parse_error( "Unexpected argument", argv[i] ); 00173 } 00174 00175 if (!input_name) 00176 parse_error( "No input file specified." ); 00177 if (!output_name) 00178 parse_error( "No output file specified." ); 00179 00180 // Read the input file 00181 if (MB_SUCCESS != iface->load_mesh( input_name )) 00182 { 00183 std::cerr << "Failed to read file: " << input_name << std::endl; 00184 std::string message; 00185 if (MB_SUCCESS == iface->get_last_error(message)) 00186 std::cerr << message << std::endl; 00187 return 2; 00188 } 00189 00190 00191 00192 bool nodes_spec = false; 00193 bool elems_spec = false; 00194 bool node_from_elem_spec = false; 00195 bool have_data_tag = false; 00196 const char* write_tag_name = 0; 00197 Tag write_tag = 0; 00198 TagSpec data_tag = { 0, 0 }; 00199 typedef std::vector<TagSpec> TagVect; 00200 TagVect ident_tags; 00201 int data_size = 0; 00202 00203 for (int i = 1; i < argc; ++i) 00204 { 00205 if (argv[i] == input_name || argv[i] == output_name) 00206 continue; 00207 else if (!strcmp(argv[i],"-n")) 00208 nodes_spec = true; 00209 else if (!strcmp(argv[i], "-e")) 00210 elems_spec = true; 00211 else if (!strcmp(argv[i], "-E")) { 00212 node_from_elem_spec = true; 00213 elems_spec = true; 00214 nodes_spec = false; 00215 } 00216 else if (!argv[i][0]) 00217 usage(); 00218 else 00219 { 00220 char flag = argv[i][1]; 00221 if ((flag != 't' && flag != 'd' && flag != 'w' && flag != 'c') || argv[i][2]) 00222 parse_error( "Invalid argument", argv[i] ); 00223 00224 ++i; 00225 if (i == argc) 00226 parse_error( "Expected tag spec following option", argv[i-1] ); 00227 00228 if (flag == 'w') 00229 { 00230 if (write_tag_name) 00231 parse_error( "Invalid argument", argv[i] ); 00232 write_tag_name = argv[i]; 00233 } 00234 else if (flag == 'c') 00235 { 00236 TagSpec spec; 00237 if (parse_tag_create( argv[i], spec, iface )) 00238 parse_error( "Failed to parse tag spec", argv[i] ); 00239 00240 if (have_data_tag) 00241 parse_error( "Invalid argument", argv[i] ); 00242 00243 data_tag = spec; 00244 have_data_tag = true; 00245 } 00246 else 00247 { 00248 TagSpec spec; 00249 if (parse_tag_spec( argv[i], spec, iface)) 00250 parse_error("Failed to parse tag spec", argv[i] ); 00251 00252 if (flag == 'd') 00253 { 00254 if (have_data_tag) 00255 parse_error( "Invalid argument", argv[i] ); 00256 00257 data_tag = spec; 00258 have_data_tag = true; 00259 } 00260 else 00261 { 00262 ident_tags.push_back( spec ); 00263 } 00264 } 00265 } 00266 } // for(args) 00267 00268 // if neither, default to both 00269 if (!nodes_spec && !elems_spec) 00270 nodes_spec = elems_spec = true; 00271 00272 // must have at least one identifying tag 00273 if (ident_tags.empty()) 00274 parse_error ("At least one identifying tag must be specified."); 00275 00276 // If data tag wasn't specified, use identifying tag for data 00277 if (!have_data_tag) 00278 { 00279 if (ident_tags.size() > 1) 00280 parse_error ("No data tag specified."); 00281 data_tag.value = 0; 00282 data_tag.handle = ident_tags[0].handle; 00283 } 00284 CALL( tag_get_bytes, (data_tag.handle, data_size) ); 00285 00286 // If write dat wasn't specified, use data tag 00287 if (!write_tag_name) 00288 { 00289 write_tag = data_tag.handle; 00290 } 00291 // If write tag was specified, if it exists its type 00292 // msut match that of the data tag. If it doesn't exist, 00293 // create it. 00294 else 00295 { 00296 DataType data_type; 00297 CALL( tag_get_data_type, (data_tag.handle, data_type) ); 00298 00299 CALL( tag_get_handle, (write_tag_name, data_size, data_type, write_tag, MB_TAG_SPARSE|MB_TAG_BYTES|MB_TAG_CREAT) ); 00300 } 00301 00302 00303 /**************** Done processing input -- do actual work ****************/ 00304 00305 // Get list of sets with identifying tags 00306 Range sets, temp; 00307 for (TagVect::iterator i = ident_tags.begin(); i != ident_tags.end(); ++i) 00308 { 00309 const void* value[] = { i->value }; 00310 CALL( get_entities_by_type_and_tag, 00311 (0, MBENTITYSET, &i->handle, i->value ? value : 0, 1, temp) ); 00312 sets.merge( temp ); 00313 } 00314 00315 // For each set, set tag on contained entities 00316 std::vector<unsigned char> tag_data(data_size); 00317 for (Range::iterator i = sets.begin(); i != sets.end(); ++i) 00318 { 00319 // Get tag value 00320 ErrorCode rval = iface->tag_get_data( data_tag.handle, &*i, 1, &tag_data[0] ); 00321 if (MB_TAG_NOT_FOUND == rval) 00322 { 00323 if (!data_tag.value) 00324 { 00325 std::cerr << "Data tag not set for entityset " 00326 << iface->id_from_handle(*i) << std::endl; 00327 continue; 00328 } 00329 memcpy( &tag_data[0], data_tag.value, data_size ); 00330 } 00331 else if (MB_SUCCESS != rval) 00332 { 00333 CALL( tag_get_data, (data_tag.handle, &*i, 1, &tag_data[0]) ); 00334 } 00335 00336 // Get entities 00337 Range entities; 00338 CALL( get_entities_by_handle, (*i, entities, true) ); 00339 int junk; 00340 Range::iterator eb = entities.lower_bound( entities.begin(), 00341 entities.end(), 00342 CREATE_HANDLE(MBEDGE,0,junk) ); 00343 if (elems_spec) 00344 for (Range::iterator j = eb; j != entities.end(); ++j) 00345 CALL( tag_set_data, (write_tag, &*j, 1, &tag_data[0]) ); 00346 if (nodes_spec) 00347 for (Range::iterator j = entities.begin(); j != eb; ++j) 00348 CALL( tag_set_data, (write_tag, &*j, 1, &tag_data[0]) ); 00349 if (node_from_elem_spec) { 00350 Range elems; 00351 elems.merge( eb, entities.end() ); 00352 entities.clear(); 00353 CALL( get_adjacencies, (elems, 0, false, entities, Interface::UNION) ); 00354 for (Range::iterator j = entities.begin(); j != entities.end(); ++j) 00355 CALL( tag_set_data, (write_tag, &*j, 1, &tag_data[0]) ); 00356 } 00357 } 00358 00359 // Write the output file 00360 if (MB_SUCCESS != iface->write_mesh( output_name )) 00361 { 00362 std::cerr << "Failed to write file: " << output_name << std::endl; 00363 std::string message; 00364 if (MB_SUCCESS == iface->get_last_error(message)) 00365 std::cerr << message << std::endl; 00366 return 2; 00367 } 00368 00369 return 0; 00370 } 00371 00372 00373 00374 00375 00376 00377 00378 00379