moab
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 { 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   
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines