MOAB: Mesh Oriented datABase
(version 5.4.1)
|
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 \ 00043 { \ 00044 ErrorCode _r = iface->A B; \ 00045 if( MB_SUCCESS != _r ) \ 00046 { \ 00047 std::cerr << #A << #B << " failed at " << __FILE__ << ":" << __LINE__ << std::endl; \ 00048 exit( 5 ); \ 00049 } \ 00050 } while( false ) 00051 00052 Interface* iface = 0; 00053 const char* exe_name = 0; 00054 00055 static void usage( bool error = true ) 00056 { 00057 std::ostream& s = error ? std::cerr : std::cout; 00058 00059 s << "Usage: " << exe_name << " <options> <input_file> <output_file>" << std::endl 00060 << " " << exe_name << " -h" << std::endl 00061 << "Options: " << std::endl 00062 << " -t <ident_tag>[=<value>] " << std::endl 00063 << " -d <data_tag>[=<default>] " << std::endl 00064 << " -c <data_tag=type:size>[=defult] " << std::endl 00065 << " -w <write_tag> " << std::endl 00066 << " -n|-e|-E " << std::endl 00067 << std::endl; 00068 if( error ) 00069 { 00070 s << "Try '-h' for verbose help." << std::endl; 00071 exit( 1 ); 00072 } 00073 00074 s << "This utility will write tag data to a subset of the mesh entities " << std::endl 00075 << "contained in a file. The behavior is controlled by three main " << std::endl 00076 << "properties:" << std::endl 00077 << " 1) The ident_tag is used to identify sets of entities for which " << std::endl 00078 << " data will be stored on each contained element or node. The -n " << std::endl 00079 << " or -e flags can be used to restrict operation to only nodes or " << std::endl 00080 << " elements, respectively." << std::endl 00081 << " 2) The data_tag is used to identify which value to write on to " << std::endl 00082 << " each entity. This is a tag on the set containing the entities." << std::endl 00083 << " 3) The write_tag is the name of the tag that the data is stored in " << std::endl 00084 << " on each mesh entity." << std::endl 00085 << std::endl 00086 << " -t : Specify an ident_tag. If a value is specified, only those " << std::endl 00087 << " sets with the specified value are processed. At least one " << std::endl 00088 << " ident_tag must be specified. Multiple ident_tags may be " << std::endl 00089 << " specified, in which case any set that matches any of the " << std::endl 00090 << " specified ident_tags will be processed (logical OR)." << std::endl 00091 << std::endl 00092 << " -d : Specify the data_tag. If multiple ident_tags are specified " << std::endl 00093 << " then the data_tag must be specified. If only one ident_tag " << std::endl 00094 << " is specified then the data_tag specification is optional." << std::endl 00095 << " If no data_tag is specified, the value of the ident_tag " << std::endl 00096 << " will be used. If a value is specified for the data_tag, " << std::endl 00097 << " then the specified value will be used for any set that " << std::endl 00098 << " doesn't have a value for the data_tag." << std::endl 00099 << std::endl 00100 << " -c : Similar to -d, except that the tag is created if it doesn't" << std::endl 00101 << " already exist. If the tag is created, then all entities" << std::endl 00102 << " receive the specified default value for the tag. In this " << std::endl 00103 << " case it is an error if no default value is specified." << std::endl 00104 << std::endl 00105 << " -w : Specify the tag to create and store values in on mesh " << std::endl 00106 << " entities. If no write_tag is specified, the data_tag " << std::endl 00107 << " will be used." << std::endl 00108 << std::endl 00109 << " -n : Write tag data only on nodes (vertices)." << std::endl 00110 << " -e : Write tag data only on elements." << std::endl 00111 << " -E : Tag value on each node is that of one of its adjacent elements." << std::endl 00112 << std::endl 00113 << "The syntax for specifying tag values is as follows: " << std::endl 00114 << std::endl; 00115 tag_syntax( s ); 00116 s << std::endl; 00117 exit( 0 ); 00118 } 00119 00120 static void about( bool error = true ) 00121 { 00122 std::ostream& s = error ? std::cerr : std::cout; 00123 s << "A utility to propogate tag values from the entity sets " 00124 "containing mesh entities to the entities contained in " 00125 "those sets." 00126 << std::endl 00127 << std::endl; 00128 usage( error ); 00129 } 00130 00131 static void parse_error( const char* msg, const char* val = 0 ) 00132 { 00133 std::cerr << msg; 00134 if( val ) std::cerr << ": " << val; 00135 std::cerr << std::endl; 00136 std::cerr << "Try '" << exe_name << " -h' for help" << std::endl; 00137 exit( 1 ); 00138 } 00139 00140 int main( int argc, char* argv[] ) 00141 { 00142 Core mb_core; 00143 exe_name = argv[0]; 00144 iface = &mb_core; 00145 00146 if( argc == 1 ) about(); 00147 00148 // find file names 00149 // load input file before processing other options so 00150 // tags are defined 00151 const char* input_name = 0; 00152 const char* output_name = 0; 00153 for( int i = 1; i < argc; ++i ) 00154 { 00155 if( argv[i][0] == '-' ) 00156 { 00157 switch( argv[i][1] ) 00158 { 00159 case 't': 00160 case 'c': 00161 case 'd': 00162 case 'w': 00163 ++i; 00164 case 'n': 00165 case 'e': 00166 case 'E': 00167 break; 00168 case 'h': 00169 usage( false ); 00170 break; 00171 default: 00172 parse_error( "Invalid option", argv[i] ); 00173 break; 00174 } 00175 } 00176 else if( !input_name ) 00177 input_name = argv[i]; 00178 else if( !output_name ) 00179 output_name = argv[i]; 00180 else 00181 parse_error( "Unexpected argument", argv[i] ); 00182 } 00183 00184 if( !input_name ) parse_error( "No input file specified." ); 00185 if( !output_name ) parse_error( "No output file specified." ); 00186 00187 // Read the input file 00188 if( MB_SUCCESS != iface->load_mesh( input_name ) ) 00189 { 00190 std::cerr << "Failed to read file: " << input_name << std::endl; 00191 std::string message; 00192 if( MB_SUCCESS == iface->get_last_error( message ) ) std::cerr << message << std::endl; 00193 return 2; 00194 } 00195 00196 bool nodes_spec = false; 00197 bool elems_spec = false; 00198 bool node_from_elem_spec = false; 00199 bool have_data_tag = false; 00200 const char* write_tag_name = 0; 00201 Tag write_tag = 0; 00202 TagSpec data_tag = { 0, 0 }; 00203 typedef std::vector< TagSpec > TagVect; 00204 TagVect ident_tags; 00205 int data_size = 0; 00206 00207 for( int i = 1; i < argc; ++i ) 00208 { 00209 if( argv[i] == input_name || argv[i] == output_name ) 00210 continue; 00211 else if( !strcmp( argv[i], "-n" ) ) 00212 nodes_spec = true; 00213 else if( !strcmp( argv[i], "-e" ) ) 00214 elems_spec = true; 00215 else if( !strcmp( argv[i], "-E" ) ) 00216 { 00217 node_from_elem_spec = true; 00218 elems_spec = true; 00219 nodes_spec = false; 00220 } 00221 else if( !argv[i][0] ) 00222 usage(); 00223 else 00224 { 00225 char flag = argv[i][1]; 00226 if( ( flag != 't' && flag != 'd' && flag != 'w' && flag != 'c' ) || argv[i][2] ) 00227 parse_error( "Invalid argument", argv[i] ); 00228 00229 ++i; 00230 if( i == argc ) parse_error( "Expected tag spec following option", argv[i - 1] ); 00231 00232 if( flag == 'w' ) 00233 { 00234 if( write_tag_name ) parse_error( "Invalid argument", argv[i] ); 00235 write_tag_name = argv[i]; 00236 } 00237 else if( flag == 'c' ) 00238 { 00239 TagSpec spec; 00240 if( parse_tag_create( argv[i], spec, iface ) ) parse_error( "Failed to parse tag spec", argv[i] ); 00241 00242 if( have_data_tag ) parse_error( "Invalid argument", argv[i] ); 00243 00244 data_tag = spec; 00245 have_data_tag = true; 00246 } 00247 else 00248 { 00249 TagSpec spec; 00250 if( parse_tag_spec( argv[i], spec, iface ) ) parse_error( "Failed to parse tag spec", argv[i] ); 00251 00252 if( flag == 'd' ) 00253 { 00254 if( have_data_tag ) parse_error( "Invalid argument", argv[i] ); 00255 00256 data_tag = spec; 00257 have_data_tag = true; 00258 } 00259 else 00260 { 00261 ident_tags.push_back( spec ); 00262 } 00263 } 00264 } 00265 } // for(args) 00266 00267 // if neither, default to both 00268 if( !nodes_spec && !elems_spec ) nodes_spec = elems_spec = true; 00269 00270 // must have at least one identifying tag 00271 if( ident_tags.empty() ) parse_error( "At least one identifying tag must be specified." ); 00272 00273 // If data tag wasn't specified, use identifying tag for data 00274 if( !have_data_tag ) 00275 { 00276 if( ident_tags.size() > 1 ) parse_error( "No data tag specified." ); 00277 data_tag.value = 0; 00278 data_tag.handle = ident_tags[0].handle; 00279 } 00280 CALL( tag_get_bytes, ( data_tag.handle, data_size ) ); 00281 00282 // If write dat wasn't specified, use data tag 00283 if( !write_tag_name ) 00284 { 00285 write_tag = data_tag.handle; 00286 } 00287 // If write tag was specified, if it exists its type 00288 // msut match that of the data tag. If it doesn't exist, 00289 // create it. 00290 else 00291 { 00292 DataType data_type; 00293 CALL( tag_get_data_type, ( data_tag.handle, data_type ) ); 00294 00295 CALL( tag_get_handle, 00296 ( write_tag_name, data_size, data_type, write_tag, MB_TAG_SPARSE | MB_TAG_BYTES | MB_TAG_CREAT ) ); 00297 } 00298 00299 /**************** Done processing input -- do actual work ****************/ 00300 00301 // Get list of sets with identifying tags 00302 Range sets, temp; 00303 for( TagVect::iterator i = ident_tags.begin(); i != ident_tags.end(); ++i ) 00304 { 00305 const void* value[] = { i->value }; 00306 CALL( get_entities_by_type_and_tag, ( 0, MBENTITYSET, &i->handle, i->value ? value : 0, 1, temp ) ); 00307 sets.merge( temp ); 00308 } 00309 00310 // For each set, set tag on contained entities 00311 std::vector< unsigned char > tag_data( data_size ); 00312 for( Range::iterator i = sets.begin(); i != sets.end(); ++i ) 00313 { 00314 // Get tag value 00315 ErrorCode rval = iface->tag_get_data( data_tag.handle, &*i, 1, &tag_data[0] ); 00316 if( MB_TAG_NOT_FOUND == rval ) 00317 { 00318 if( !data_tag.value ) 00319 { 00320 std::cerr << "Data tag not set for entityset " << iface->id_from_handle( *i ) << std::endl; 00321 continue; 00322 } 00323 memcpy( &tag_data[0], data_tag.value, data_size ); 00324 } 00325 else if( MB_SUCCESS != rval ) 00326 { 00327 CALL( tag_get_data, ( data_tag.handle, &*i, 1, &tag_data[0] ) ); 00328 } 00329 00330 // Get entities 00331 Range entities; 00332 CALL( get_entities_by_handle, ( *i, entities, true ) ); 00333 int junk; 00334 Range::iterator eb = entities.lower_bound( entities.begin(), entities.end(), CREATE_HANDLE( MBEDGE, 0, junk ) ); 00335 if( elems_spec ) 00336 for( Range::iterator j = eb; j != entities.end(); ++j ) 00337 CALL( tag_set_data, ( write_tag, &*j, 1, &tag_data[0] ) ); 00338 if( nodes_spec ) 00339 for( Range::iterator j = entities.begin(); j != eb; ++j ) 00340 CALL( tag_set_data, ( write_tag, &*j, 1, &tag_data[0] ) ); 00341 if( node_from_elem_spec ) 00342 { 00343 Range elems; 00344 elems.merge( eb, entities.end() ); 00345 entities.clear(); 00346 CALL( get_adjacencies, ( elems, 0, false, entities, Interface::UNION ) ); 00347 for( Range::iterator j = entities.begin(); j != entities.end(); ++j ) 00348 CALL( tag_set_data, ( write_tag, &*j, 1, &tag_data[0] ) ); 00349 } 00350 } 00351 00352 // Write the output file 00353 if( MB_SUCCESS != iface->write_mesh( output_name ) ) 00354 { 00355 std::cerr << "Failed to write file: " << output_name << std::endl; 00356 std::string message; 00357 if( MB_SUCCESS == iface->get_last_error( message ) ) std::cerr << message << std::endl; 00358 return 2; 00359 } 00360 00361 return 0; 00362 }