cgma
mcnp2cad.cpp
Go to the documentation of this file.
00001 #include <iostream>
00002 #include <fstream>
00003 #include <string>
00004 #include <stdexcept>
00005 #include <cctype>
00006 #include <vector>
00007 #include <set>
00008 #include <map>
00009 #include <sstream>
00010 #include <algorithm>
00011 
00012 #include <cassert>
00013 
00014 #include "iGeom.h"
00015 #include "geometry.hpp"
00016 #include "MCNPInput.hpp"
00017 #include "options.hpp"
00018 #include "volumes.hpp"
00019 #include "ProgOptions.hpp"
00020 #include "version.hpp"
00021 
00022 
00023 /* mcnp2cad should be compatible with any implementation of the iGeom library.
00024  * But when we know that CGM is the implementation of iGeom that we're using,
00025  * we can do a few other useful things.  Those extra things are confined to this
00026  * file and guarded by this macro.
00027  */
00028 //#ifdef USING_CGMA
00029 
00030 #include <RefEntityFactory.hpp>
00031 #include <Body.hpp>
00032 #include <GeometryQueryTool.hpp>
00033 #include <CubitMessage.hpp>
00034 
00035 
00036 static bool CGMA_opt_inhibit_intersect_errs = false;
00037 
00038 /*  CubitMessage doesn't provide a way to shut up error messages.
00039  *  For those rare cases when we really want that behavior, we set up 
00040  *  a message handler that just drops messages.
00041  */
00042 class SilentCubitMessageHandler : public CubitMessageHandler
00043 {
00044 
00045 public:
00046   static int num_dropped_errors;
00047 
00048   SilentCubitMessageHandler() {}
00049 
00050   virtual void print_message_prefix(const char *){}
00051   virtual void print_message(const char *){}
00052   virtual void print_error_prefix(const char *){}
00053   virtual void print_error(const char *){num_dropped_errors++;}
00054 };
00055 
00056 int SilentCubitMessageHandler::num_dropped_errors = 0;
00057 
00058 /* RAII class to set up and shut down a SilentCubitMessageHandler */
00059 class CubitSilence
00060 {
00061 protected:
00062   CubitMessageHandler* old_handler;
00063   SilentCubitMessageHandler silencer;
00064 public:
00065   CubitSilence() :
00066     old_handler( CubitMessage::instance()->get_message_handler() )
00067   {
00068     CubitMessage::instance()->set_message_handler( &silencer );
00069   }
00070 
00071   ~CubitSilence(){
00072     CubitMessage::instance()->set_message_handler( old_handler );
00073   }
00074 };
00075 
00076 //#endif /* USING_CGMA */
00077 
00078 typedef std::vector<iBase_EntityHandle> entity_collection_t;
00079 
00080 // intersect two volumes that may or may not overlap; return true on success.
00081 static bool intersectIfPossible( iGeom_Instance igm, 
00082                                  iBase_EntityHandle h1, iBase_EntityHandle h2, iBase_EntityHandle* result, 
00083                                  bool delete_on_failure = true)
00084 {
00085   int igm_result;
00086 
00087 //#ifdef USING_CGMA
00088   if( CGMA_opt_inhibit_intersect_errs ){
00089     CubitSilence s;
00090     iGeom_intersectEnts( igm, h1, h2, result, &igm_result); 
00091   }  else
00092 //#endif
00093   {
00094     iGeom_intersectEnts( igm, h1, h2, result, &igm_result);
00095   }
00096   
00097   if( igm_result == iBase_SUCCESS ){
00098     return true;
00099   }
00100   else{
00101     if( delete_on_failure ){
00102       iGeom_deleteEnt( igm, h1, &igm_result);
00103       CHECK_IGEOM(igm_result, "deleting an intersection candidate");
00104       iGeom_deleteEnt( igm, h2, &igm_result);
00105       CHECK_IGEOM(igm_result, "deleting an intersection candidate");
00106     }
00107     return false;
00108   }
00109 }
00110 
00111 // determine whether the bounding boxes of two volumes overlap.
00112 // this can save an expensive call to intersectIfPossible()
00113 static bool boundBoxesIntersect( iGeom_Instance igm, iBase_EntityHandle h1, iBase_EntityHandle h2 ){
00114 
00115   Vector3d h1_min, h1_max, h2_min, h2_max;
00116   int igm_result;
00117   
00118   iGeom_getEntBoundBox( igm, h1, h1_min.v, h1_min.v+1, h1_min.v+2, h1_max.v, h1_max.v+1, h1_max.v+2, &igm_result );
00119   CHECK_IGEOM( igm_result, "Getting bounding box h1" );
00120   iGeom_getEntBoundBox( igm, h2, h2_min.v, h2_min.v+1, h2_min.v+2, h2_max.v, h2_max.v+1, h2_max.v+2, &igm_result );
00121   CHECK_IGEOM( igm_result, "Getting bounding box h2" );
00122 
00123   bool ret = false;
00124 
00125   for( int i = 0; i < 3 && ret == false; ++i ){
00126     ret = ret || ( h1_min.v[i] > h2_max.v[i] );
00127     ret = ret || ( h2_min.v[i] > h1_max.v[i] );
00128   }
00129 
00130   return !ret;
00131 
00132 }
00133 
00137 class GeometryContext {
00138 
00148 protected:
00149 
00150   // note: this appears slow, since it's called for all cells and constructs a string
00151   // for each.  A lookup table would probably be faster, but there are never more than
00152   // a few thousand cells.
00153   std::string materialName( int mat, double rho ){
00154     std::string ret;
00155     std::stringstream formatter;
00156     if(Gopt.uwuw_names){
00157       bool mass_density = false;
00158       if (rho <= 0){
00159         mass_density = true;
00160         rho = -rho;
00161       }
00162       char rho_formatted [50];
00163       sprintf(rho_formatted, "%E", rho);
00164       formatter << "mat:m" << mat;
00165       if(mass_density)
00166           formatter << "/rho:" <<rho_formatted;
00167       else
00168           formatter << "/atom:" << rho_formatted;
00169     }
00170     else
00171       formatter << "mat_" << mat << "_rho_" << rho;
00172     formatter >> ret;
00173     return ret;
00174   }
00175 
00176   std::string importanceName( char impchar, double imp ){
00177     std::string ret; 
00178     std::stringstream formatter;
00179     formatter << "imp." << impchar << "_" << imp;
00180     formatter >> ret;
00181     return ret;
00182   }
00183 
00184   class NamedGroup {
00185   protected:
00186     std::string name;
00187     entity_collection_t entities;
00188   public:
00189     NamedGroup( ) : name("") {}
00190     NamedGroup( std::string name_p ):
00191       name(name_p)
00192     {}
00193 
00194     const std::string& getName() const { return name; }
00195     const entity_collection_t& getEntities() const { return entities; }
00196 
00197     void add( iBase_EntityHandle new_handle ){
00198       entities.push_back(new_handle);
00199     }
00200 
00201     void update( iBase_EntityHandle old_h, iBase_EntityHandle new_h ){
00202       entity_collection_t::iterator i = std::find( entities.begin(), entities.end(), old_h );
00203       if( i != entities.end() ){
00204         if( new_h ){
00205           *i = new_h;
00206         }
00207         else {
00208           entities.erase( i );
00209         }
00210       }
00211     }
00212 
00213     bool contains( iBase_EntityHandle handle ) const {
00214       return std::find( entities.begin(), entities.end(), handle ) != entities.end(); 
00215     }
00216 
00217   };
00218 
00219   class NamedEntity { 
00220   protected:
00221     iBase_EntityHandle handle;
00222     std::string name;
00223   public:
00224     NamedEntity( iBase_EntityHandle handle_p, std::string name_p = "" ):
00225       handle(handle_p), name(name_p)
00226     {}
00227     virtual ~NamedEntity(){}
00228 
00229     const std::string& getName() const { return name; }
00230     iBase_EntityHandle getHandle() const{ return handle; }
00231 
00232     void setHandle( iBase_EntityHandle new_h ) {
00233       handle = new_h;
00234     }
00235 
00236     static NamedEntity* makeCellIDName( iBase_EntityHandle h, int ident ){
00237       NamedEntity* e = new NamedEntity(h);
00238       std::stringstream formatter;
00239       formatter << "MCNP_ID_" << ident;
00240       formatter >> e->name;
00241       return e;
00242     }
00243 
00244   };
00245 
00246 protected:
00247   iGeom_Instance& igm;
00248   InputDeck& deck;
00249   double world_size;
00250   int universe_depth;
00251 
00252   std::map< std::string, NamedGroup* > named_groups;
00253   std::vector< NamedEntity* > named_cells;
00254 
00255   NamedGroup* getNamedGroup( const std::string& name ){
00256     if( named_groups.find( name ) == named_groups.end() ){
00257       named_groups[ name ] = new NamedGroup( name );
00258       if( OPT_DEBUG ) std::cout << "New named group: " << name 
00259                                 << "num groups now " << named_groups.size() << std::endl;
00260     }
00261     return named_groups[ name ];
00262   }
00263 
00264 public:
00265   GeometryContext( iGeom_Instance& igm_p, InputDeck& deck_p ) :
00266     igm(igm_p), deck(deck_p), world_size(0.0), universe_depth(0)
00267   {}
00268 
00269   bool defineLatticeNode( CellCard& cell, iBase_EntityHandle cell_shell, iBase_EntityHandle lattice_shell,
00270                           int x, int y, int z, entity_collection_t& accum );
00271   
00272 
00273   entity_collection_t defineCell( CellCard& cell, bool defineEmbedded, iBase_EntityHandle lattice_shell );
00274   entity_collection_t populateCell( CellCard& cell, iBase_EntityHandle cell_shell, iBase_EntityHandle lattice_shell );
00275  
00276 
00277   entity_collection_t defineUniverse( int universe, iBase_EntityHandle container, const Transform* transform );
00278   
00279 
00280   void addToVolumeGroup( iBase_EntityHandle cell, const std::string& groupname );
00281   void setVolumeCellID( iBase_EntityHandle cell, int ident);
00282   void setMaterial( iBase_EntityHandle cell, int material, double density ){
00283     if( Gopt.tag_materials ){
00284         addToVolumeGroup( cell, materialName(material,density) );
00285     }
00286   }
00287 
00288   void setImportances( iBase_EntityHandle cell, const std::map<char, double>& imps ){
00289     if( Gopt.tag_importances ){
00290       for( std::map<char, double>::const_iterator i = imps.begin();
00291            i != imps.end(); ++i )
00292       {
00293           char impchar = (*i).first;
00294           double imp = (*i).second;
00295           addToVolumeGroup( cell, importanceName( impchar, imp ) );
00296       }
00297     }
00298   }
00299 
00300 
00301   void updateMaps ( iBase_EntityHandle old_cell, iBase_EntityHandle new_cell );
00302 
00303   bool mapSanityCheck( iBase_EntityHandle* cells, size_t count );
00304 
00305   void tagGroups( );
00306   void tagCellIDsAsEntNames();
00307 
00308   std::string uprefix() { 
00309     return std::string( universe_depth, ' ' );
00310   }
00311 
00312   iBase_EntityHandle createGraveyard( iBase_EntityHandle& boundary );
00313   void createGeometry( );
00314 
00315 };
00316 
00317 void GeometryContext::addToVolumeGroup( iBase_EntityHandle cell, const std::string& name ){
00318 
00319   NamedGroup* group = getNamedGroup( name );
00320   group->add( cell );
00321 
00322   if( OPT_DEBUG ){ std::cout << uprefix() 
00323                              << "Added cell to volgroup " << group->getName() << std::endl; }
00324 }
00325 
00326 
00327 void GeometryContext::setVolumeCellID( iBase_EntityHandle cell, int ident ){
00328 
00329   named_cells.push_back( NamedEntity::makeCellIDName(cell, ident) );
00330 
00331 }
00332 
00334 void GeometryContext::updateMaps( iBase_EntityHandle old_cell, iBase_EntityHandle new_cell ){
00335 
00336   /* update named_groups.  handling of new_cell == NULL case is performed within NamedGroup class */
00337   for( std::map<std::string,NamedGroup*>::iterator i = named_groups.begin();
00338        i != named_groups.end(); ++i )
00339   {
00340     NamedGroup* group = (*i).second;
00341     group->update( old_cell, new_cell );
00342   }
00343 
00344   /* update named entities.*/
00345   if( new_cell != NULL ){
00346     for( std::vector< NamedEntity* >::iterator i = named_cells.begin(); 
00347          i != named_cells.end(); ++i )
00348       {
00349         NamedEntity* ne = *i;
00350         if( ne->getHandle() == old_cell ){
00351           ne->setHandle( new_cell );
00352         }
00353       }
00354   }
00355   else{ /* new_cell == NULL (i.e. cell has disappeared) */
00356 
00357     // this case is expected to be uncommon in most geometries, so the fact that erasing
00358     // from a std::vector is slow should not be a problem.
00359     std::vector< NamedEntity* >::iterator i = named_cells.begin();
00360     while( i != named_cells.end() ){
00361       if( (*i)->getHandle() == old_cell ){
00362         delete (*i);
00363         named_cells.erase(i);
00364       }
00365       else{
00366         ++i;
00367       }
00368     }
00369   }
00370 
00371 }
00372 
00374 void GeometryContext::tagGroups( ){
00375 
00376   // the NamedGroup system used to be used solely to create groups for material specification,
00377   // but it has since been expanded for importance groups.  Some of the old messages that
00378   // talk about material groups could be confusing.
00379   int igm_result;
00380   
00381   std::string name_tag_id = "NAME";
00382   int name_tag_maxlength = 64;
00383   iBase_TagHandle name_tag;
00384 
00385   iGeom_getTagHandle( igm, name_tag_id.c_str(), &name_tag, &igm_result, name_tag_id.length() );
00386   CHECK_IGEOM( igm_result, "Looking up NAME tag" );
00387   
00388   iGeom_getTagSizeBytes( igm, name_tag, &name_tag_maxlength, &igm_result );
00389   CHECK_IGEOM( igm_result, "Querying NAME tag length" );
00390   if( OPT_DEBUG ) std::cout << "Name tag length: " << name_tag_maxlength << " actual id " << name_tag << std::endl;
00391 
00392   for( std::map<std::string,NamedGroup*>::iterator i = named_groups.begin(); i != named_groups.end(); ++i ){
00393 
00394     NamedGroup* group = (*i).second;
00395     if(OPT_VERBOSE){ 
00396       std::cout << "Creating volume group " << group->getName() << " of size " << group->getEntities().size() << std::endl;
00397     }
00398 
00399     iBase_EntitySetHandle set;
00400     iGeom_createEntSet( igm, 0, &set, &igm_result );
00401     CHECK_IGEOM( igm_result, "Creating a new entity set " );
00402     
00403     const entity_collection_t& group_list = group->getEntities();
00404     for( entity_collection_t::const_iterator j = group_list.begin(); j != group_list.end(); ++j ){
00405       iGeom_addEntToSet( igm, *j, set, &igm_result );
00406       CHECK_IGEOM( igm_result, "Adding entity to material set" );
00407     }
00408 
00409     std::string name = group->getName();
00410     if( name.length() > (unsigned)name_tag_maxlength ){
00411       name.resize( name_tag_maxlength - 1);
00412       std::cerr << "Warning: trimmed material name " << group->getName() 
00413                 << " to length " << name_tag_maxlength << std::endl;
00414     }
00415 
00416     iGeom_setEntSetData( igm, set, name_tag, name.c_str(), name.length(), &igm_result );
00417     CHECK_IGEOM( igm_result, "Naming a material group's EntitySet" );
00418     
00419   }
00420 
00421 }
00422 
00424 void GeometryContext::tagCellIDsAsEntNames(){
00425   
00426   int igm_result;
00427 
00428   std::string name_tag_id = "NAME";
00429   int name_tag_maxlength = 64;
00430   iBase_TagHandle name_tag;
00431 
00432   iGeom_getTagHandle( igm, name_tag_id.c_str(), &name_tag, &igm_result, name_tag_id.length() );
00433   CHECK_IGEOM( igm_result, "Looking up NAME tag" );
00434   
00435   iGeom_getTagSizeBytes( igm, name_tag, &name_tag_maxlength, &igm_result );
00436   CHECK_IGEOM( igm_result, "Querying NAME tag length" );
00437   if( OPT_DEBUG ) std::cout << "Name tag length: " << name_tag_maxlength << " actual id " << name_tag << std::endl;
00438 
00439 
00440   if( OPT_VERBOSE ){ std::cout << "Naming " << named_cells.size() << " volumes." <<  std::endl; }
00441 
00442   for( std::vector< NamedEntity* >::iterator i = named_cells.begin(); i!=named_cells.end(); ++i){
00443     std::string name = (*i)->getName();
00444     iBase_EntityHandle entity = (*i)->getHandle();
00445 
00446     if( name.length() > (unsigned)name_tag_maxlength ){
00447       name.resize( name_tag_maxlength - 1);
00448       std::cerr << "Warning: trimmed entity name " << (*i)->getName() 
00449                 << " to length " << name_tag_maxlength << std::endl;
00450     }
00451 
00452     if( entity == NULL ){ std::cerr << "Error: NULL in named_cells" << std::endl; continue; }
00453     
00454     iGeom_setData( igm, entity, name_tag, name.c_str(), name.length(), &igm_result );
00455     CHECK_IGEOM( igm_result, "Naming an NamedEntity" );
00456   }
00457 
00458 }
00459 
00461 bool GeometryContext::mapSanityCheck( iBase_EntityHandle* cells, size_t count){ 
00462   bool good = true;
00463   int igm_result;
00464 
00465   iBase_EntitySetHandle rootset;
00466   iGeom_getRootSet( igm, &rootset, &igm_result );
00467   CHECK_IGEOM( igm_result, "Getting root set for sanity check" );
00468 
00469   int num_regions;
00470   iGeom_getNumOfType( igm, rootset, iBase_REGION, &num_regions, &igm_result );
00471   CHECK_IGEOM( igm_result, "Getting num regions for sanity check" );
00472 
00473   iBase_EntityHandle * handle_vector = new iBase_EntityHandle[ num_regions ];
00474   int size = 0;
00475 
00476   std::cout << "Map sanity check: num_regions = " << num_regions << std::endl;
00477   iGeom_getEntities( igm, rootset, iBase_REGION, &handle_vector, &num_regions, &size, &igm_result );
00478   CHECK_IGEOM( igm_result, "Getting entities for sanity check" );
00479 
00480   std::cout << "Map sanity check: root set size = " << size << " (" << num_regions << ")" << std::endl;
00481   std::cout << "Cell count: " << count << std::endl;
00482   
00483   // sanity conditions: all the entityhandles in the naming lists are part of the cells list
00484   std::set< iBase_EntityHandle > allRegions;
00485   for( size_t i = 0; i < count; ++i ){
00486     allRegions.insert( cells[i] );
00487   }
00488   
00489   int named_group_volume_count = 0;
00490   for( std::map<std::string, NamedGroup*>::iterator i = named_groups.begin(); i!=named_groups.end(); ++i){
00491     NamedGroup* group = (*i).second;
00492     named_group_volume_count += group->getEntities().size();
00493 
00494     // graveyard cells are not present in allRegions
00495     if( group->getName() == "graveyard" )
00496       continue;
00497 
00498     entity_collection_t group_cells = group->getEntities();
00499     
00500     for( entity_collection_t::iterator j = group_cells.begin(); j != group_cells.end(); ++j ){
00501       bool check = allRegions.find( *j ) != allRegions.end();
00502       if( ! check ){
00503         std::cout << "Entity handle " << *j << " is not in allRegions!" << std::endl;
00504       }
00505       good = good && check;
00506     }
00507   }
00508 
00509   std::cout << "Num EntityHandles in NamedGroups: " << named_group_volume_count << std::endl;
00510 
00511   if( good ){ std::cout << "Map sanity check: pass!"  << std::endl; }
00512   else{ std::cout << "WARNING: Failed map sanity check!" << std::endl; }
00513 
00514   return good;
00515 }
00516 
00522 bool GeometryContext::defineLatticeNode(  CellCard& cell, iBase_EntityHandle cell_shell, iBase_EntityHandle lattice_shell,
00523                                           int x, int y, int z, entity_collection_t& accum )
00524 {
00525   const Lattice& lattice = cell.getLattice();
00526   int lattice_universe =   cell.getUniverse();
00527 
00528   const FillNode* fn = &(lattice.getFillForNode( x, y, z ));                            
00529   Transform t = lattice.getTxForNode( x, y, z );        
00530   int igm_result;
00531   
00532   iBase_EntityHandle cell_copy;
00533   iGeom_copyEnt( igm, cell_shell, &cell_copy, &igm_result );
00534   CHECK_IGEOM( igm_result, "Copying a lattice cell shell" );
00535   cell_copy = applyTransform( t, igm, cell_copy );
00536   
00537   if( !boundBoxesIntersect( igm, cell_copy, lattice_shell ) ){
00538     iGeom_deleteEnt( igm, cell_copy, &igm_result);
00539     CHECK_IGEOM( igm_result, "Deleting a lattice cell shell" );
00540     if( OPT_DEBUG ) std::cout << uprefix() << " node failed bbox check" << std::endl;
00541     return false;
00542   }
00543 
00544   entity_collection_t node_subcells;
00545   if( fn->getFillingUniverse() == 0 ){
00546     // this node of the lattice was assigned universe zero, meaning it's
00547     // defined to be emtpy. Delete the shell and return true.
00548     iGeom_deleteEnt( igm, cell_copy, &igm_result );
00549     CHECK_IGEOM( igm_result, "Deleting a universe-0 lattice cell" );
00550     return true;
00551   }
00552   else if( fn->getFillingUniverse() == lattice_universe ){
00553     // this node is just a translated copy of the origin element in the lattice
00554     setVolumeCellID(cell_copy, cell.getIdent());
00555     if( cell.getMat() != 0 ){ setMaterial( cell_copy, cell.getMat(), cell.getRho() ); }
00556     if( cell.getImportances().size() ){ setImportances( cell_copy, cell.getImportances()); }
00557     node_subcells.push_back( cell_copy );
00558   }
00559   else{
00560     // this node has an embedded universe
00561 
00562     iBase_EntityHandle cell_copy_unmoved;
00563     iGeom_copyEnt( igm, cell_shell, &cell_copy_unmoved, &igm_result );
00564     CHECK_IGEOM( igm_result, "Re-copying a lattice cell shell" );
00565     node_subcells = defineUniverse(  fn->getFillingUniverse(), cell_copy_unmoved, (fn->hasTransform() ? &(fn->getTransform()) : NULL ) );
00566     for( size_t i = 0; i < node_subcells.size(); ++i ){
00567       node_subcells[i] = applyTransform( t, igm, node_subcells[i] );
00568     }
00569 
00570     iGeom_deleteEnt( igm, cell_copy, &igm_result );
00571     CHECK_IGEOM( igm_result, "Deleting lattice cell copy" );
00572 
00573   }
00574 
00575   // bound the node with the enclosing lattice shell
00576   bool success = false;
00577   for( size_t i = 0; i < node_subcells.size(); ++i ){
00578     iBase_EntityHandle lattice_shell_copy;
00579     iGeom_copyEnt( igm, lattice_shell, &lattice_shell_copy, &igm_result );
00580 
00581     iBase_EntityHandle result;
00582     if( intersectIfPossible( igm, lattice_shell_copy, node_subcells[i], &result, true ) ){
00583       updateMaps( node_subcells[i], result );
00584       if( OPT_DEBUG ) std::cout << " node defined successfully" << std::endl;
00585       accum.push_back( result );
00586       success = true;
00587     }
00588     else{ 
00589       // lattice_shell_copy and node_subcells[i] were deleted by intersectIfPossible(),
00590       // so there's no need to delete them explicitly
00591       updateMaps( node_subcells[i], NULL );
00592       if( OPT_DEBUG ) std::cout << " node failed intersection" << std::endl;
00593     }
00594   }
00595 
00596   return success;
00597 }
00598 
00599 typedef struct{ int v[3]; } int_triple;
00600 
00601 static std::vector<int_triple> makeGridShellOfRadius( int r, int dimensions ){
00602   if( r == 0 ){ 
00603     int_triple v; v.v[0] = v.v[1] = v.v[2] = 0;
00604     return std::vector<int_triple>(1,v);
00605   }
00606   else{
00607     std::vector<int_triple> ret;
00608     
00609     int jmin = dimensions > 1 ? -r : 0;
00610     int jmax = dimensions > 1 ?  r : 0;
00611     int kmin = dimensions > 2 ? -r : 0;
00612     int kmax = dimensions > 2 ?  r : 0;
00613     for( int i = -r; i <= r; ++i ){
00614       for( int j = jmin;j <= jmax; ++j ){
00615         for( int k = kmin; k <= kmax; ++k ){
00616           if( i == -r || i == r ||
00617               j == -r || j == r ||
00618               k == -r || k == r ){
00619             int_triple v;
00620             v.v[0] = i; 
00621             v.v[1] = j;
00622             v.v[2] = k;
00623             ret.push_back(v);
00624           }
00625         }
00626       }
00627     }
00628     return ret;
00629   }
00630 }
00631 
00633 entity_collection_t GeometryContext::populateCell( CellCard& cell,  iBase_EntityHandle cell_shell, 
00634                                                    iBase_EntityHandle lattice_shell = NULL )
00635 {
00636   
00637   if( OPT_DEBUG ) std::cout << uprefix() << "Populating cell " << cell.getIdent() << std::endl;
00638 
00639 
00640   if( !cell.hasFill() && !cell.isLattice() ){
00641     // no further geometry inside this cell; set its material
00642     setVolumeCellID(cell_shell, cell.getIdent());
00643     if( cell.getMat() != 0 ){ setMaterial( cell_shell, cell.getMat(), cell.getRho() ); }
00644     if( cell.getImportances().size() ){ setImportances( cell_shell, cell.getImportances()); }
00645     return entity_collection_t(1, cell_shell );
00646   }
00647   else if(cell.hasFill() && !cell.isLattice()){
00648     // define a simple (non-lattice) fill
00649     
00650     const FillNode& n = cell.getFill().getOriginNode();
00651     int filling_universe = n.getFillingUniverse();
00652     
00653     if( OPT_DEBUG ){
00654       std::cout << uprefix() << "Creating cell " << cell.getIdent() 
00655                 << ", which is filled with universe " << filling_universe << std::endl;
00656     }
00657     
00658     // the contained universe is transformed by the FillNode's transform, if any, or
00659     // else by the cell's TRCL value, if any.
00660     const Transform* t;
00661     if( n.hasTransform() ){
00662       t = &(n.getTransform());
00663     } else if( cell.getTrcl().hasData() ){
00664       t = &(cell.getTrcl().getData() );
00665     } else { 
00666       t = NULL; 
00667     }
00668 
00669     if( OPT_DEBUG && t ) std::cout << uprefix() << " ... and has transform: " << *t << std::endl;
00670 
00671     entity_collection_t subcells = defineUniverse(  filling_universe, cell_shell, t );
00672  
00673     return subcells;
00674      
00675   }
00676   else {
00677     // cell is a lattice, bounded by lattice_shell.  cell_shell is the origin element of the lattice and
00678     // cell->getLattice() has the lattice parameters.
00679 
00680     assert(lattice_shell);
00681     
00682     if( OPT_VERBOSE ) std::cout << uprefix() << "Creating cell " << cell.getIdent() << "'s lattice" << std::endl;
00683 
00684     entity_collection_t subcells;
00685         
00686     const Lattice& lattice = cell.getLattice();
00687     int num_dims = lattice.numFiniteDirections();
00688     
00689     if( OPT_DEBUG ) std::cout << uprefix() << "  lattice num dims: " << num_dims << std::endl;
00690 
00691     if( lattice.isFixedSize() ){
00692 
00693       if( OPT_DEBUG ) std::cout << uprefix() << "Defining fixed lattice" << std::endl;
00694 
00695       irange xrange = lattice.getXRange(), yrange = lattice.getYRange(), zrange = lattice.getZRange();
00696 
00697       for( int i = xrange.first; i <= xrange.second; ++i){
00698         for( int j = yrange.first; j <= yrange.second; ++j ){
00699           for( int k = zrange.first; k <= zrange.second; ++k ){
00700 
00701             if( OPT_DEBUG ) std::cout << uprefix() << "Defining lattice node " << i << ", " << j << ", " << k << std::endl;
00702 
00703             /* bool success = */ defineLatticeNode( cell, cell_shell, lattice_shell, i, j, k, subcells );
00704 
00705             if( num_dims < 3 ) break; // from z loop
00706           }
00707           if( num_dims < 2 ) break; // from y loop
00708         }
00709       }
00710 
00711     }
00712     else{
00713 
00714       if( OPT_DEBUG ) std::cout << uprefix() << "Defining infinite lattice" << std::endl;
00715       if( OPT_VERBOSE && Gopt.infinite_lattice_extra_effort ) 
00716         std::cout << uprefix() << "Infinite lattice extra effort enabled." << std::endl;
00717 
00718       // when extra effort is enabled, initialize done_one to false;
00719       // the code will keep trying to create lattice elements until at least one 
00720       // element has been successfully created.
00721       bool done = false, done_one = !Gopt.infinite_lattice_extra_effort;
00722       int radius = 0;
00723 
00724       while( !done ){
00725         
00726         done = done_one;
00727         std::vector<int_triple> shell = makeGridShellOfRadius(radius++, num_dims);
00728 
00729         for( std::vector<int_triple>::iterator i = shell.begin(); i!=shell.end(); ++i){
00730           int x = (*i).v[0];
00731           int y = (*i).v[1];
00732           int z = (*i).v[2];
00733           
00734           if( OPT_DEBUG ) std::cout << uprefix() << "Defining lattice node " << x << ", " << y << ", " << z << std::endl;
00735 
00736           bool success = defineLatticeNode( cell, cell_shell, lattice_shell, x, y, z, subcells );
00737           if( success ){
00738             done = false;
00739             done_one = true;
00740           }
00741 
00742         }       
00743       }
00744     }
00745 
00746     int igm_result;
00747     iGeom_deleteEnt( igm, cell_shell, &igm_result );
00748     CHECK_IGEOM( igm_result, "Deleting cell shell after building lattice" );
00749     iGeom_deleteEnt( igm, lattice_shell, &igm_result );
00750     CHECK_IGEOM( igm_result, "Deleting lattice shell after building lattice" );
00751 
00752     return subcells;
00753   }
00754 }
00755 
00761 entity_collection_t GeometryContext::defineCell(  CellCard& cell,  bool defineEmbedded = true, 
00762                                                   iBase_EntityHandle lattice_shell = NULL )
00763 {
00764   int ident = cell.getIdent();
00765   const CellCard::geom_list_t& geom = cell.getGeom();
00766  
00767   if( OPT_VERBOSE ) std::cout << uprefix() << "Defining cell " << ident << std::endl;
00768 
00769   int igm_result;
00770 
00771   entity_collection_t tmp;
00772 
00773   std::vector<iBase_EntityHandle> stack;
00774   for(CellCard::geom_list_t::const_iterator i = geom.begin(); i!=geom.end(); ++i){
00775     
00776     const CellCard::geom_list_entry_t& token = (*i);
00777     switch(token.first){
00778     case CellCard::CELLNUM:
00779       // a cell number appears in a geometry list only because it is being complemented with the # operator
00780       // thus, when defineCell is called on it, set defineEmbedded to false
00781       tmp = defineCell( *(deck.lookup_cell_card(token.second)), false);
00782       assert(tmp.size() == 1);
00783       stack.push_back( tmp.at(0) );
00784       break;
00785     case CellCard::SURFNUM:
00786       {      
00787         int surface = token.second;
00788         bool pos = true;
00789         if( surface < 0){
00790           pos = false; surface = -surface;
00791         }
00792         try{
00793           SurfaceVolume& surf = makeSurface( deck.lookup_surface_card( surface ) );
00794           iBase_EntityHandle surf_handle = surf.define( pos, igm, world_size );
00795           stack.push_back(surf_handle);
00796         }
00797         catch(std::runtime_error& e) { std::cerr << e.what() << std::endl; }
00798       }
00799       break;
00800     case CellCard::MBODYFACET:
00801       {
00802         int cellnum = std::abs(token.second) / 10;
00803         int facet = std::abs(token.second) - (cellnum*10);
00804         std::cerr << "Attempting to define facet " << facet << " of cell " << cellnum << std::endl;
00805         throw std::runtime_error( "Macrobody facets are not yet supported by mcnp2cad." );
00806       }
00807       break;
00808     case CellCard::INTERSECT:
00809       {
00810         assert( stack.size() >= 2 );
00811         iBase_EntityHandle s1 = stack.back(); stack.pop_back();
00812         iBase_EntityHandle s2 = stack.back(); stack.pop_back();
00813         iBase_EntityHandle result;
00814         if( intersectIfPossible( igm, s1, s2, &result ) ){
00815           stack.push_back(result);
00816         }
00817         else{
00818           std::cout << "FAILED INTERSECTION CELL #" << cell.getIdent() << std::endl;
00819           throw std::runtime_error("Intersection failed");
00820         }
00821       }
00822       break;
00823     case CellCard::UNION:
00824       { 
00825         assert( stack.size() >= 2 );
00826         iBase_EntityHandle s[2];
00827         s[0] = stack.back(); stack.pop_back();
00828         s[1] = stack.back(); stack.pop_back();
00829         iBase_EntityHandle result;
00830         iGeom_uniteEnts( igm, s, 2, &result, &igm_result);
00831         CHECK_IGEOM( igm_result, "Uniting two entities" );
00832         stack.push_back(result);
00833       }
00834       break;
00835     case CellCard::COMPLEMENT:
00836       {
00837         assert (stack.size() >= 1 );
00838         iBase_EntityHandle world_sphere = makeWorldSphere(igm, world_size);
00839         iBase_EntityHandle s = stack.back(); stack.pop_back();
00840         iBase_EntityHandle result;
00841 
00842         iGeom_subtractEnts( igm, world_sphere, s, &result, &igm_result);
00843         CHECK_IGEOM( igm_result, "Complementing an entity" );
00844         stack.push_back(result);
00845       }
00846       break;
00847     default:
00848       throw std::runtime_error( "Unexpected token while evaluating cell geometry");
00849       break;
00850     }
00851   }
00852 
00853   assert( stack.size() == 1);
00854 
00855   iBase_EntityHandle cellHandle = stack[0];
00856 
00857   if( cell.getTrcl().hasData() ){
00858     cellHandle = applyTransform( cell.getTrcl().getData(), igm, cellHandle );
00859   }
00860 
00861   if( defineEmbedded ){
00862     return populateCell( cell, cellHandle, lattice_shell );
00863   }
00864   else{
00865     return entity_collection_t( 1, cellHandle );
00866   }
00867   
00868 }
00869 
00875 entity_collection_t GeometryContext::defineUniverse( int universe, iBase_EntityHandle container = NULL, 
00876                                                      const Transform* transform = NULL )
00877 {
00878 
00879   if( OPT_VERBOSE ) std::cout << uprefix() << "Defining universe " << universe << std::endl;
00880   universe_depth++;
00881 
00882   InputDeck::cell_card_list u_cells = deck.getCellsOfUniverse( universe );
00883   entity_collection_t subcells;
00884 
00885   iBase_EntityHandle lattice_shell = NULL;
00886   if( u_cells.size() == 1 && u_cells[0]->isLattice() ){
00887     lattice_shell = container;
00888     // reverse-transform the containing volume before using it as a lattice boundary
00889     if(transform){
00890       lattice_shell = applyReverseTransform( *transform, igm, lattice_shell );
00891     }
00892   }
00893 
00894   // define all the cells of this universe
00895   for( InputDeck::cell_card_list::iterator i = u_cells.begin(); i!=u_cells.end(); ++i){
00896     entity_collection_t tmp = defineCell( *(*i), true, lattice_shell );
00897     for( size_t i = 0; i < tmp.size(); ++i){
00898       subcells.push_back( tmp[i] );
00899     }
00900   }
00901   
00902   if( transform ){
00903     for( size_t i = 0; i < subcells.size(); ++i){
00904       subcells[i] = applyTransform( *transform, igm, subcells[i] );      
00905     }
00906   }
00907 
00908   if( container && !lattice_shell ){
00909     
00910     int igm_result;
00911     
00912     for( size_t i = 0; i < subcells.size(); ++i ){
00913       
00914       if( OPT_DEBUG ) std::cout << uprefix() << "Bounding a universe cell..." << std::flush;    
00915       bool subcell_removed = false;
00916 
00917       if( boundBoxesIntersect( igm, subcells[i], container )){
00918         iBase_EntityHandle container_copy;
00919         iGeom_copyEnt( igm, container, &container_copy, &igm_result);
00920         CHECK_IGEOM( igm_result, "Copying a universe-bounding cell" );
00921         
00922         iBase_EntityHandle subcell_bounded;
00923         bool valid_result = intersectIfPossible( igm, container_copy, subcells[i], &subcell_bounded );
00924         if( valid_result ){
00925           updateMaps( subcells[i], subcell_bounded );
00926           subcells[i] = subcell_bounded;
00927           if( OPT_DEBUG ) std::cout << " ok." <<  std::endl;
00928         }
00929         else{
00930           subcell_removed = true;
00931         }
00932 
00933       }
00934       else{
00935         // bounding boxes didn't intersect, delete subcells[i].
00936         // this suggests invalid geometry, but we can continue anyway.
00937         iGeom_deleteEnt( igm, subcells[i], &igm_result );
00938         CHECK_IGEOM( igm_result, "Deleting a subcell that didn't intersect a parent's bounding box (strange!)" );
00939         subcell_removed = true;
00940       }
00941       
00942       if( subcell_removed ){
00943         updateMaps( subcells[i], NULL );
00944         subcells.erase( subcells.begin()+i );
00945         i--;
00946         if( OPT_DEBUG ) std::cout << " removed." << std::endl;
00947       }
00948       
00949     }
00950         
00951     iGeom_deleteEnt( igm, container, &igm_result );
00952     CHECK_IGEOM( igm_result, "Deleting a bounding cell" );
00953   }
00954 
00955   universe_depth--;
00956   if( OPT_VERBOSE ) std::cout << uprefix() << "Done defining universe " << universe << std::endl;
00957 
00958   return subcells;
00959  
00960 }
00961 
00967 iBase_EntityHandle GeometryContext::createGraveyard( iBase_EntityHandle& inner_copy ) {
00968   iBase_EntityHandle inner, outer, graveyard;
00969   int igm_result;
00970 
00971 #ifdef CGM_HAVE_FACET_ENGINE_ONLY
00972   FacetModifyEngine::set_modify_enabled(CUBIT_TRUE);
00973 #endif
00974 
00975   double inner_size = 2.0 * world_size;
00976   iGeom_createBrick( igm, inner_size, inner_size, inner_size, &inner, &igm_result );
00977   CHECK_IGEOM( igm_result, "Making graveyard" );
00978   
00979   iGeom_copyEnt( igm, inner, &inner_copy, &igm_result );
00980   CHECK_IGEOM( igm_result, "Copying graveyard" );
00981   
00982   double outer_size = 2.0 * ( world_size + (world_size / 50.0) );
00983   iGeom_createBrick( igm, outer_size, outer_size, outer_size, &outer, &igm_result );
00984   CHECK_IGEOM( igm_result, "Making outer graveyard" );
00985 
00986   iGeom_subtractEnts( igm, outer, inner, &graveyard, &igm_result );
00987   CHECK_IGEOM( igm_result, "subtracting graveyard" );
00988   
00989   addToVolumeGroup( graveyard, "graveyard" );
00990   
00991   // reset world size to a sphere that bounds the inner shell of this graveyard
00992   world_size *= sqrt(3.0);
00993   if( OPT_DEBUG ) std::cout << "Spherical world size for graveyard: " << world_size << std::endl;
00994   
00995   return graveyard;
00996 
00997 }
00998 
00999 void GeometryContext::createGeometry( ){
01000 
01001   int igm_result;
01002  
01003   InputDeck::cell_card_list    cells     = deck.getCells();
01004   InputDeck::surface_card_list surfaces  = deck.getSurfaces();
01005   InputDeck::data_card_list    datacards = deck.getDataCards();
01006 
01007   // estimate how large the geometry will need to be to accomodate all the surfaces
01008   for( InputDeck::surface_card_list::iterator i = surfaces.begin(); i!=surfaces.end(); ++i){
01009     // catch all exceptions from makeSurface at this time; if they exist, they will
01010     // more properly be displayed to the user at a later time.  Right now we just want
01011     // to estimate a size and failures can be ignored.
01012     try{
01013       world_size = std::max( world_size, makeSurface( *i ).getFarthestExtentFromOrigin() );
01014     } catch(std::runtime_error& e){}
01015   }
01016 
01017   // translations can extend the size of the world
01018   double translation_addition = 0;
01019   for( InputDeck::data_card_list::iterator i = datacards.begin(); i!=datacards.end(); ++i){
01020     DataCard* c = *i;
01021     if( c->getKind() == DataCard::TR ){
01022       double tform_len = dynamic_cast<DataRef<Transform>*>(c)->getData().getTranslation().length();
01023       translation_addition = std::max (translation_addition, tform_len );
01024     }
01025   }
01026 
01027   for( InputDeck::cell_card_list::iterator i = cells.begin(); i!=cells.end(); ++i){
01028     CellCard* c = *i;
01029       // translations can come from TRCL data
01030     if( c->getTrcl().hasData() ){
01031       double tform_len = c->getTrcl().getData().getTranslation().length();
01032       translation_addition = std::max( translation_addition, tform_len );
01033     }
01034     // translations can also come from fill nodes.  This implementation does *not* take
01035     // lattices into account, as they are assumed to be contained within other volumes.
01036     if( c->hasFill() && c->getFill().getOriginNode().hasTransform() ){
01037       double tform_len = c->getFill().getOriginNode().getTransform().getTranslation().length();
01038       translation_addition = std::max( translation_addition, tform_len );
01039     }
01040   }
01041 
01042   world_size += translation_addition;
01043   world_size *= 1.2;
01044 
01045   std::cout << "World size: " << world_size << " (trs added " << translation_addition << ")" << std::endl;
01046 
01047   iBase_EntityHandle graveyard = NULL, graveyard_boundary = NULL;
01048   if( Gopt.make_graveyard ){
01049     graveyard = createGraveyard ( graveyard_boundary ); 
01050   }
01051 
01052   std::cout << "Defining geometry..." << std::endl;
01053 
01054   entity_collection_t defined_cells = defineUniverse( 0, graveyard_boundary );
01055   if( graveyard ){ defined_cells.push_back(graveyard); }
01056 
01057   size_t count = defined_cells.size();
01058   iBase_EntityHandle *cell_array = new iBase_EntityHandle[ count ];
01059   for( unsigned int i = 0; i < count; ++i ){
01060     cell_array[i] = defined_cells[i];
01061   }
01062 
01063 //#ifdef USING_CGMA
01064   {
01065     // in CGM's default implementation, each new volume and surface created
01066     // through CSG operations gets a new unique ID number, so those IDs can
01067     // be large and widely-spaced.  We want them to start from 1.
01068     RefEntityFactory::instance()->compress_ref_ids("surface", false );
01069     RefEntityFactory::instance()->compress_ref_ids("volume", false );
01070   }
01071 //#endif
01072 
01073 
01074   if( OPT_DEBUG ){ mapSanityCheck(cell_array, count); }
01075   tagGroups();
01076 
01077   if( Gopt.tag_cell_IDs ){
01078     tagCellIDsAsEntNames();
01079   }
01080   
01081 
01082   if ( Gopt.imprint_geom ) {
01083     std::cout << "Imprinting all...\t\t\t" << std::flush;
01084     iGeom_imprintEnts( igm, cell_array, count, &igm_result );
01085     CHECK_IGEOM( igm_result, "Imprinting all cells" );
01086     std::cout << " done." << std::endl;
01087     
01088     double tolerance = world_size / 1.0e7;
01089     if( Gopt.override_tolerance ){
01090       tolerance = Gopt.specific_tolerance;
01091     }
01092 
01093     if ( Gopt.merge_geom ) {
01094       std::cout << "Merging, tolerance=" << tolerance << "...\t\t" << std::flush;
01095       iGeom_mergeEnts( igm, cell_array, count,  tolerance, &igm_result );
01096       CHECK_IGEOM( igm_result, "Merging all cells" );
01097       std::cout << " done." << std::endl;
01098     }
01099   }
01100 
01101 
01102   std::string outName = Gopt.output_file;
01103   std::cout << "Saving file \"" << outName << "\"...\t\t\t" << std::flush;
01104   iGeom_save( igm, outName.c_str(), "", &igm_result, outName.length(), 0 );
01105   CHECK_IGEOM( igm_result, "saving the output file "+outName );
01106   std::cout << " done." << std::endl;
01107 
01108 }
01109 
01110 void debugSurfaceDistances( InputDeck& deck, std::ostream& out = std::cout ){
01111 
01112   InputDeck::surface_card_list& surfaces = deck.getSurfaces();
01113   for( InputDeck::surface_card_list::iterator i = surfaces.begin(); i!=surfaces.end(); ++i){
01114     try{
01115       const SurfaceVolume& s = makeSurface(*i);
01116       out << "S" << (*i)->getIdent() << " distance from origin: " << s.getFarthestExtentFromOrigin() << std::endl;
01117     }
01118     catch(std::runtime_error& e){
01119       std::cerr << "Error debugging surface distances: " << e.what() << std::endl;
01120       throw;
01121     }
01122   }
01123   
01124 }
01125 
01126 std::string mcnp2cad_version(bool full = true);
01127 
01128 
01129 struct program_option_struct Gopt;
01130 
01131 int main(int argc, char* argv[]){
01132 
01133   // set default options
01134   Gopt.verbose = Gopt.debug = false;
01135   Gopt.infinite_lattice_extra_effort = false;
01136   Gopt.tag_materials = true;
01137   Gopt.tag_importances = true;
01138   Gopt.tag_cell_IDs = true;
01139   Gopt.make_graveyard = true;
01140   Gopt.imprint_geom = true;
01141   Gopt.merge_geom = true;
01142   Gopt.input_file = "";
01143   Gopt.output_file = OPT_DEFAULT_OUTPUT_FILENAME;
01144   Gopt.igeom_init_options = "";
01145   Gopt.override_tolerance = false;
01146   Gopt.uwuw_names = false;
01147 
01148   bool DiFlag = false, DoFlag = false;
01149 
01150   ProgOptions po("mcnp2cad " + mcnp2cad_version(false) +  ": An MCNP geometry to CAD file converter");
01151   po.setVersion( mcnp2cad_version() );
01152 
01153   po.addOpt<void>("extra-effort,e","Use extra effort to get infinite lattices right (may be slow)", 
01154                   &Gopt.infinite_lattice_extra_effort );
01155   po.addOpt<void>("verbose,v", "Verbose output", &Gopt.verbose );
01156   po.addOpt<void>("debug,D", "Debugging (very verbose) output", &Gopt.debug );
01157   po.addOpt<void>("Di", "Debug output for MCNP parsing phase only", &DiFlag);
01158   po.addOpt<void>("Do","Debug output for iGeom output phase only", &DoFlag);
01159 
01160   po.addOptionHelpHeading( "Options controlling CAD output:" );
01161   po.addOpt<std::string>(",o", "Give name of output file. Default: " + Gopt.output_file, &Gopt.output_file );
01162   po.addOpt<double>("tol,t", "Specify a tolerance for merging surfaces", &Gopt.specific_tolerance );
01163   po.addOpt<void>("skip-mats,M", "Do not tag materials using group names", 
01164                   &Gopt.tag_materials, po.store_false );
01165   po.addOpt<void>("skip-imps,P", "Do not tag cell importances using group names",
01166                   &Gopt.tag_importances, po.store_false );
01167   po.addOpt<void>("skip-nums,N", "Do not tag cell numbers using body names",
01168                   &Gopt.tag_cell_IDs, po.store_false );
01169   po.addOpt<void>("skip-merge,E", "Do not merge the geometry",
01170                   &Gopt.merge_geom, po.store_false );
01171   po.addOpt<void>("skip-imprint,I", "Do not imprint the geometry; implies skip-merge",
01172                   &Gopt.imprint_geom, po.store_false );
01173   po.addOpt<void>("skip-graveyard,G", "Do not bound the geometry with a `graveyard' bounding box",
01174                   &Gopt.make_graveyard, po.store_false );
01175   po.addOpt<void>("uwuw-names,U", "Use a UWUW compatible name scheme for material groups,"
01176                                    "i.e. 'mat:mX/rho:Y' where X is material number is Y is density",
01177                   &Gopt.uwuw_names, po.store_true );
01178 
01179 //#ifdef USING_CGMA
01180   po.addOptionHelpHeading ("Options controlling CGM library:");
01181   po.addOpt<int>("geomver","Override geometry export engine version");
01182   po.addOptionHelpHeading ("    (use --geomver 1600 for backward compatibility w/ Cubit 10.2)");
01183   po.addOpt<void>("Cv", "Verbose messages from CGM" );
01184   po.addOpt<void>("Cq", "Silence warning messages from CGM" );
01185   po.addOpt<void>("CIq","Silence ERROR messages from CGM when doing intersect tests.");
01186   po.addOptionHelpHeading( "         (May be useful for infinite lattices, but use cautiously)" );
01187 //#endif
01188 
01189   po.addRequiredArg( "input_file", "Path to MCNP geometry input file", &Gopt.input_file );
01190 
01191   po.parseCommandLine( argc, argv );
01192 
01193   if( po.numOptSet( "tol,t" ) ){
01194     Gopt.override_tolerance = true;
01195     if( Gopt.specific_tolerance <= 0.0 || Gopt.specific_tolerance > .1 ){
01196       std::cerr << "Warning: you seem to have specified an unusual tolerance (" 
01197                 << Gopt.specific_tolerance << ")." << std::endl;
01198     }
01199   }
01200 
01201 //#ifdef USING_CGMA
01202 
01203   // Enable the info_flag only if --Cv is requested
01204   if(po.numOptSet( "Cv" )){
01205     CubitMessage::instance()->set_info_flag( true );
01206   }
01207   else{
01208     CubitMessage::instance()->set_info_flag( false );
01209   }
01210 
01211   // Silence warnings if --Cq is set
01212   if(po.numOptSet( "Cq" )){    
01213     CubitMessage::instance()->set_warning_flag( false );
01214   }
01215 
01216   // Enable silent intersection errors if --CIq is set
01217   if(po.numOptSet( "CIq" )){
01218     CGMA_opt_inhibit_intersect_errs = true;
01219   }
01220 
01221 //#endif
01222 
01223   if( Gopt.merge_geom && !Gopt.imprint_geom ) {
01224     std::cerr << "Warning: cannot merge geometry without imprinting, will skip merge too." << std::endl;
01225   }
01226 
01227   std::ifstream input(Gopt.input_file.c_str(), std::ios::in );
01228   if( !input.is_open() ){
01229     std::cerr << "Error: couldn't open file \"" << Gopt.input_file << "\"" << std::endl;
01230     return 1;
01231   }
01232   
01233   std::cout << "Reading input file..." << std::endl;
01234 
01235   // if --Di and not -D, set debugging to be true for InputDeck::build() call only
01236   if( DiFlag && !OPT_DEBUG){
01237     Gopt.debug = true;
01238   }
01239   else{ DiFlag = false; }
01240 
01241   InputDeck& deck = InputDeck::build(input);
01242   std::cout << "Done reading input." << std::endl;
01243 
01244   // turn off debug if it was set by --Di only
01245   if( DiFlag ){ Gopt.debug = false; }
01246   
01247   if( DoFlag && !OPT_DEBUG ){ Gopt.debug = true; }
01248 
01249   if( OPT_DEBUG ){ 
01250     debugSurfaceDistances( deck );
01251   }
01252 
01253 #ifdef CGM_HAVE_FACET_ENGINE_ONLY
01254   FacetModifyEngine::set_modify_enabled(CUBIT_TRUE);
01255 #endif
01256 
01257   iGeom_Instance igm;
01258   int igm_result; 
01259 
01260   iGeom_newGeom( Gopt.igeom_init_options.c_str(), &igm, &igm_result, Gopt.igeom_init_options.length() );
01261   CHECK_IGEOM( igm_result, "Initializing iGeom");
01262 
01263 //#ifdef USING_CGMA
01264   int export_vers;
01265   if( po.getOpt( "geomver", &export_vers) ){
01266     if( CUBIT_SUCCESS == GeometryQueryTool::instance()->set_export_allint_version( export_vers ) ){
01267       std::cout << "Set export engine version to " << export_vers << std::endl; 
01268     }
01269     // on failure, an error message will be printed by CGM
01270   }
01271 
01272 //#endif
01273 
01274   GeometryContext context( igm, deck );
01275   context.createGeometry();
01276   
01277 //#ifdef USING_CGMA
01278   if( CGMA_opt_inhibit_intersect_errs && SilentCubitMessageHandler::num_dropped_errors > 0){
01279     std::cout << "--CIq: supressed " << SilentCubitMessageHandler::num_dropped_errors << " intersection errors." << std::endl;
01280   }
01281 //#endif 
01282 
01283   return 0;
01284 }
01285 
01290 std::string mcnp2cad_version( bool full ){
01291   std::stringstream str;
01292   str << (full ? "mcnp2cad version " : "")
01293       << MCNP2CAD_VERSION_MAJOR << "." 
01294       << MCNP2CAD_VERSION_MINOR << "." 
01295       << MCNP2CAD_VERSION_REV;
01296   if(full)
01297       str << "\nCompiled on " << __DATE__ << " at " << __TIME__ ;
01298   return str.str();
01299 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines