cgma
|
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 }