MOAB: Mesh Oriented datABase  (version 5.2.1)
propagate_tags.cpp
Go to the documentation of this file.
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 ) { write_tag = data_tag.handle; }
00284     // If write tag was specified, if it exists its type
00285     // msut match that of the data tag.  If it doesn't exist,
00286     // create it.
00287     else
00288     {
00289         DataType data_type;
00290         CALL( tag_get_data_type, ( data_tag.handle, data_type ) );
00291 
00292         CALL( tag_get_handle,
00293               ( write_tag_name, data_size, data_type, write_tag, MB_TAG_SPARSE | MB_TAG_BYTES | MB_TAG_CREAT ) );
00294     }
00295 
00296     /**************** Done processing input -- do actual work ****************/
00297 
00298     // Get list of sets with identifying tags
00299     Range sets, temp;
00300     for( TagVect::iterator i = ident_tags.begin(); i != ident_tags.end(); ++i )
00301     {
00302         const void* value[] = { i->value };
00303         CALL( get_entities_by_type_and_tag, ( 0, MBENTITYSET, &i->handle, i->value ? value : 0, 1, temp ) );
00304         sets.merge( temp );
00305     }
00306 
00307     // For each set, set tag on contained entities
00308     std::vector< unsigned char > tag_data( data_size );
00309     for( Range::iterator i = sets.begin(); i != sets.end(); ++i )
00310     {
00311         // Get tag value
00312         ErrorCode rval = iface->tag_get_data( data_tag.handle, &*i, 1, &tag_data[0] );
00313         if( MB_TAG_NOT_FOUND == rval )
00314         {
00315             if( !data_tag.value )
00316             {
00317                 std::cerr << "Data tag not set for entityset " << iface->id_from_handle( *i ) << std::endl;
00318                 continue;
00319             }
00320             memcpy( &tag_data[0], data_tag.value, data_size );
00321         }
00322         else if( MB_SUCCESS != rval )
00323         {
00324             CALL( tag_get_data, ( data_tag.handle, &*i, 1, &tag_data[0] ) );
00325         }
00326 
00327         // Get entities
00328         Range entities;
00329         CALL( get_entities_by_handle, ( *i, entities, true ) );
00330         int junk;
00331         Range::iterator eb = entities.lower_bound( entities.begin(), entities.end(), CREATE_HANDLE( MBEDGE, 0, junk ) );
00332         if( elems_spec )
00333             for( Range::iterator j = eb; j != entities.end(); ++j )
00334                 CALL( tag_set_data, ( write_tag, &*j, 1, &tag_data[0] ) );
00335         if( nodes_spec )
00336             for( Range::iterator j = entities.begin(); j != eb; ++j )
00337                 CALL( tag_set_data, ( write_tag, &*j, 1, &tag_data[0] ) );
00338         if( node_from_elem_spec )
00339         {
00340             Range elems;
00341             elems.merge( eb, entities.end() );
00342             entities.clear();
00343             CALL( get_adjacencies, ( elems, 0, false, entities, Interface::UNION ) );
00344             for( Range::iterator j = entities.begin(); j != entities.end(); ++j )
00345                 CALL( tag_set_data, ( write_tag, &*j, 1, &tag_data[0] ) );
00346         }
00347     }
00348 
00349     // Write the output file
00350     if( MB_SUCCESS != iface->write_mesh( output_name ) )
00351     {
00352         std::cerr << "Failed to write file: " << output_name << std::endl;
00353         std::string message;
00354         if( MB_SUCCESS == iface->get_last_error( message ) ) std::cerr << message << std::endl;
00355         return 2;
00356     }
00357 
00358     return 0;
00359 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines