r3108 - in cgm/trunk: . cgm_apps/cgm_cubit_acis geom geom/OCC geom/facet geom/parallel geom/virtual itaps
Author: hongjun Date: 2009-08-19 15:05:46 -0500 (Wed, 19 Aug 2009) New Revision: 3108 Added: cgm/trunk/geom/parallel/AcisMemFile.hpp cgm/trunk/geom/parallel/CGMParallelComm.cpp cgm/trunk/geom/parallel/CGMParallelComm.hpp cgm/trunk/geom/parallel/CGMProcConfig.cpp cgm/trunk/geom/parallel/CGMProcConfig.hpp cgm/trunk/geom/parallel/FileOptions.cpp cgm/trunk/geom/parallel/FileOptions.hpp cgm/trunk/itaps/partest.cpp Removed: cgm/trunk/geom/parallel/AcisMemFile.hpp Modified: cgm/trunk/cgm_apps/cgm_cubit_acis/Makefile cgm/trunk/configure.ac cgm/trunk/geom/GeometryQueryEngine.hpp cgm/trunk/geom/GeometryQueryTool.cpp cgm/trunk/geom/GeometryQueryTool.hpp cgm/trunk/geom/OCC/OCCQueryEngine.cpp cgm/trunk/geom/OCC/OCCQueryEngine.hpp cgm/trunk/geom/facet/FacetQueryEngine.cpp cgm/trunk/geom/facet/FacetQueryEngine.hpp cgm/trunk/geom/parallel/Makefile.am cgm/trunk/geom/parallel/ParallelGeomTool.cpp cgm/trunk/geom/parallel/ParallelGeomTool.hpp cgm/trunk/geom/virtual/VirtualQueryEngine.cpp cgm/trunk/geom/virtual/VirtualQueryEngine.hpp cgm/trunk/itaps/CATag.hpp cgm/trunk/itaps/Makefile.am cgm/trunk/itaps/iGeom_CGMA.cc Log: o Parallel iGeom codes are added and modified. o CGMParallelComm.*pp, FileOptions.*pp, ParallelGeomTool.*pp, CGMProcConfig.*pp are added in geom/parallel directory. o Binary read and write functions are added in OCCQueryEngine. o GeometryQueryTool, GeometryQueryEngine are modified by changing of OCCQueryEngine. o partest is test file of parallel iGeom Modified: cgm/trunk/cgm_apps/cgm_cubit_acis/Makefile =================================================================== --- cgm/trunk/cgm_apps/cgm_cubit_acis/Makefile 2009-08-19 18:39:01 UTC (rev 3107) +++ cgm/trunk/cgm_apps/cgm_cubit_acis/Makefile 2009-08-19 20:05:46 UTC (rev 3108) @@ -1,22 +1,21 @@ # # CGM_BASE_DIR: base directory below which are geom/ and util/, the cgm source # -CGM_BASE_DIR = ${HOME}/cubit/CGM-10.1 +CGM_BASE_DIR = ${HOME}/lib/CGM # # CUBIT_INSTALL_DIR: the installation directory of your cubit executable, below -# which should be bin/ and libs/ containing libcubiti19.so (in bin/) and the acis +# which should be bin/ containing libcubiti19.so (in bin/) and other # shared libs (in libs/). # -CUBIT_INSTALL_DIR = /cubit +CUBIT_INSTALL_DIR = ${HOME}/cubit-10.2-amd64 -LFLAGS = -Wl,--unresolved-symbols=ignore-all -Wl,--allow-shlib-undefined -Wl,-rpath,${CUBIT_INSTALL_DIR}/bin -Wl,-rpath,${CUBIT_INSTALL_DIR}/libs +LFLAGS = -Wl,--unresolved-symbols=ignore-all -Wl,--allow-shlib-undefined -Wl,-rpath,${CUBIT_INSTALL_DIR}/bin -Wl,-rpath,${HOME}/lib/OpenCASCADE6.3.0/lib +include ${CGM_BASE_DIR}/lib/cgm.make + cgm_cubit_acis_app: main_cubit_acis.o Makefile snippet.o - ${CXX} -o cgm_cubit_acis ${LFLAGS} main_cubit_acis.o snippet.o -L${CUBIT_INSTALL_DIR}/bin -L${CUBIT_INSTALL_DIR}/libs \ - -lcubiti19 -lacisstep -lxstep -lacisiges -lxiges -lSPAXAssemblyRep -lSPAXInterop -lSPAXAcisBase -lSPAXDefaultGeometryRep -lSPAXBase -lxacis2k -lxcore2k -lSpaAVis -lSpaAWarp -lSpaASurf -lSpaALops -lSpaABlend -lSpaACIS -lSpaBase -lcubiti19 -lacisstep -lxstep -lacisiges -lxiges -lSPAXAssemblyRep -lSPAXInterop -lSPAXAcisBase -lSPAXDefaultGeometryRep -lSPAXBase -lxacis2k -lxcore2k -lSpaAVis -lSpaAWarp -lSpaASurf -lSpaALops -lSpaABlend -lSpaACIS -lSpaBase + ${CXX} ${CGM_INCLUDES} -o cgm_cubit_acis ${LFLAGS} main_cubit_acis.o snippet.o ${CGM_LIBS_LINK} -include ${CGM_BASE_DIR}/include/config.make - main_cubit_acis.o : Makefile NoAcisQueryEngine.hpp NoAcisModifyEngine.hpp mcnp_converter.o : mcnp_converter.cpp Makefile NoAcisQueryEngine.hpp NoAcisModifyEngine.hpp @@ -25,8 +24,8 @@ $(CXX) ${CGM_CXXFLAGS} -g -I. ${CGM_INCLUDES} -o $@ -c $< test: - ./cgm_cubit_acis geom.sat + ./cgm_cubit_acis ${HOME}/source/CGM/itaps/testgeom.sat .cpp.o: - $(CXX) ${CGM_CXXFLAGS} -g -I. -I${CGM_BASE_DIR}/include -o $@ -c $< + $(CXX) ${CGM_CXXFLAGS} -g -I. ${CGM_INCLUDES} -o $@ -c $< Modified: cgm/trunk/configure.ac =================================================================== --- cgm/trunk/configure.ac 2009-08-19 18:39:01 UTC (rev 3107) +++ cgm/trunk/configure.ac 2009-08-19 20:05:46 UTC (rev 3108) @@ -281,7 +281,7 @@ CUBIT_OCC_LIB= HAVE_OCC_DEF= if test "x$occ_DIR" != "xno"; then - OCC_LIBS="-lTKMath -lTKXSBase -lTKernel -lTKShHealing -lTKBRep -lTKG3d -lTKBO -lTKFeat -lTKFillet -lTKG2d -lTKOffset -lTKBool -lTKGeomAlgo -lTKGeomBase -lTKPrim -lTKTopAlgo -lTKHLR -lTKIGES -lTKMesh -lTKPrim -lTKSTEP209 -lTKSTEPAttr -lTKSTEPBase -lTKSTEP -lTKSTL -lTKTopAlgo -lTKXSBase -lTKLCAF" + OCC_LIBS="-lTKMath -lTKXSBase -lTKernel -lTKShHealing -lTKBRep -lTKG3d -lTKBO -lTKFeat -lTKFillet -lTKG2d -lTKOffset -lTKBool -lTKGeomAlgo -lTKGeomBase -lTKPrim -lTKTopAlgo -lTKHLR -lTKIGES -lTKMesh -lTKPrim -lTKSTEP209 -lTKSTEPAttr -lTKSTEPBase -lTKSTEP -lTKSTL -lTKTopAlgo -lTKXSBase -lTKLCAF -lTKBin" CUBIT_OCC_LIB="-lcubit_OCC" # Set OCC_INC_FLAG and OCC_LIB_FLAG based on --with-occ option Modified: cgm/trunk/geom/GeometryQueryEngine.hpp =================================================================== --- cgm/trunk/geom/GeometryQueryEngine.hpp 2009-08-19 18:39:01 UTC (rev 3107) +++ cgm/trunk/geom/GeometryQueryEngine.hpp 2009-08-19 20:05:46 UTC (rev 3108) @@ -49,6 +49,13 @@ const char* file_type, const CubitString &cubit_version, const char* logfile_name = NULL ) = 0; + + virtual CubitStatus export_solid_model( + DLIList<TopologyBridge*>& bridge_list, + char*& p_buffer, + int& n_buffer_size, + bool b_export_buffer) = 0; + //R CubitStatus //R- CUBIT_SUCCESS/CUBIT_FAILURE //I ref_entity_list @@ -101,6 +108,11 @@ bool import_vertices = true, bool free_surfaces = true ) = 0; + + virtual CubitStatus import_solid_model(DLIList<TopologyBridge*> &imported_entities, + const char* pBuffer, + const int n_buffer_size) = 0; + //R CubitStatus //R- CUBIT_SUCCESS/CUBIT_FAILURE //I file_ptr Modified: cgm/trunk/geom/GeometryQueryTool.cpp =================================================================== --- cgm/trunk/geom/GeometryQueryTool.cpp 2009-08-19 18:39:01 UTC (rev 3107) +++ cgm/trunk/geom/GeometryQueryTool.cpp 2009-08-19 20:05:46 UTC (rev 3108) @@ -507,6 +507,32 @@ return result; } +CubitStatus GeometryQueryTool::export_solid_model(DLIList<RefEntity*>& ref_entity_list, + char*& p_buffer, + int& n_buffer_size, + bool b_export_buffer) +{ + // Get TopologyBridges from RefEntities. + DLIList<TopologyBridge*> bridge_list(ref_entity_list.size()), ref_ent_bridges; + ref_entity_list.reset(); + for( int i = ref_entity_list.size(); i--; ) + { + ref_ent_bridges.clean_out(); + TopologyEntity* topo_ptr = dynamic_cast<TopologyEntity*>(ref_entity_list.get_and_step()); + if( topo_ptr ) + topo_ptr->bridge_manager()->get_bridge_list( ref_ent_bridges ); + bridge_list += ref_ent_bridges; + } + + bridge_list.reset(); + GeometryQueryEngine *gqe = bridge_list.get()->get_geometry_query_engine(); + + CubitStatus result = gqe->export_solid_model(bridge_list, p_buffer, + n_buffer_size, b_export_buffer); + + return result; +} + //------------------------------------------------------------------------- // Purpose : Fire a ray and see which entities it hits // @@ -642,6 +668,35 @@ return status; } +CubitStatus GeometryQueryTool::import_solid_model(DLIList<RefEntity*> *imported_entities, + const char* pBuffer, + const int n_buffer_size) +{ + if (0 == gqeList.size()) { + PRINT_WARNING("No active geometry engine.\n"); + return CUBIT_FAILURE; + } + + // Use the default MQE to import a list of ToplogyBridges from the file. + gqeList.reset(); + DLIList<TopologyBridge*> bridge_list; + + CubitStatus status; + for (int i = 0; i < gqeList.size(); i++) + { + status = gqeList.get_and_step()->import_solid_model( bridge_list, pBuffer, n_buffer_size ); + + if (bridge_list.size() > 0) break; + } + if (bridge_list.size() == 0) return status; + + bridge_list.reset(); + status = construct_refentities(bridge_list, imported_entities); + + // now return + return status; +} + CubitStatus GeometryQueryTool::construct_refentities(DLIList<TopologyBridge*> &bridge_list, DLIList<RefEntity*> *imported_entities) { Modified: cgm/trunk/geom/GeometryQueryTool.hpp =================================================================== --- cgm/trunk/geom/GeometryQueryTool.hpp 2009-08-19 18:39:01 UTC (rev 3107) +++ cgm/trunk/geom/GeometryQueryTool.hpp 2009-08-19 20:05:46 UTC (rev 3108) @@ -254,6 +254,11 @@ * */ + CubitStatus export_solid_model(DLIList<RefEntity*>& ref_entity_list, + char*& p_buffer, + int& n_buffer_size, + bool b_export_buffer); + CubitStatus import_solid_model(const char* file_name, const char* file_type, const char* logfile_name = NULL, @@ -264,6 +269,7 @@ CubitBoolean import_vertices = CUBIT_TRUE, CubitBoolean free_surfaces = CUBIT_TRUE, DLIList<RefEntity*> *imported_entities = NULL); + /**< * Import all or specified entities in a solid model file. * \arg file_ptr @@ -294,6 +300,11 @@ * CUBIT_SUCCESS if everything goes well. */ + // import entities in a solid model buffer + CubitStatus import_solid_model(DLIList<RefEntity*> *imported_entities, + const char* pBuffer, + const int n_buffer_size); + CubitStatus construct_refentities(DLIList<TopologyBridge*> &topology_bridges, DLIList<RefEntity*> *imported_entities = NULL); //- given a list of TB's, construct ref entities for them; if the 2nd list pointer is Modified: cgm/trunk/geom/OCC/OCCQueryEngine.cpp =================================================================== --- cgm/trunk/geom/OCC/OCCQueryEngine.cpp 2009-08-19 18:39:01 UTC (rev 3107) +++ cgm/trunk/geom/OCC/OCCQueryEngine.cpp 2009-08-19 20:05:46 UTC (rev 3108) @@ -14,6 +14,9 @@ // //------------------------------------------------------------------------- #include <Standard_Stream.hxx> +//#include <Standard_SStream.hxx> +//#include <Standard_String.hxx> +//#include <stringbuf> #include "BRep_Tool.hxx" #include "gp_Pnt.hxx" #include "gp_Ax1.hxx" @@ -24,6 +27,7 @@ #include "BRepBuilderAPI_Transform.hxx" #include "BRepBuilderAPI_MakeSolid.hxx" #include "OCCShapeAttributeSet.hpp" +//#include "OCCBinToolsShapeSet.hpp" #include "BRepBuilderAPI_MakeShell.hxx" #include "GProp_GProps.hxx" #include "BRepGProp.hxx" @@ -110,6 +114,7 @@ #include <BRepAdaptor_Surface.hxx> #include <TDataStd_Shape.hxx> #include <TDF_ChildIterator.hxx> +#include <BinTools_ShapeSet.hxx> #include "Standard_Boolean.hxx" #include "TDF_Label.hxx" @@ -975,6 +980,123 @@ return CUBIT_SUCCESS; } +CubitStatus OCCQueryEngine::export_solid_model( DLIList<TopologyBridge*>& ref_entity_list, + char*& p_buffer, + int& n_buffer_size, + bool b_export_buffer) +{ + DLIList<OCCBody*> OCC_bodies; + DLIList<OCCSurface*> OCC_surfaces; + DLIList<OCCCurve*> OCC_curves; + DLIList<OCCPoint*> OCC_points; + + DLIList<TopologyBridge*> ref_entities_handled; + + int i; + //Collect all free entities (bodies, curves, vertices ) + ref_entity_list.reset(); + for(i=ref_entity_list.size(); i>0; i--) + { + TopologyBridge* ref_entity_ptr = ref_entity_list.get(); + CubitBoolean handled = CUBIT_TRUE; + + //if it is a Vertex + if( OCCPoint* pt = CAST_TO( ref_entity_ptr, OCCPoint) ) + OCC_points.append( pt ); + + //if it is a Curve + else if( OCCCurve* curve = CAST_TO( ref_entity_ptr, OCCCurve) ) + OCC_curves.append( curve ); + + //if it is a surface + else if( OCCSurface* surf = CAST_TO( ref_entity_ptr, OCCSurface) ) + OCC_surfaces.append( surf ); + + //if it is a Body + else if( OCCBody* body = CAST_TO( ref_entity_ptr, OCCBody ) ) + OCC_bodies.append( body ); + + else + handled = CUBIT_FALSE; + + if( handled == CUBIT_TRUE ) + { + ref_entities_handled.append( ref_entity_ptr ); + ref_entity_list.change_to(NULL); + } + + ref_entity_list.step(); + } + + ref_entity_list.remove_all_with_value(NULL); + + int free_body_count = OCC_bodies.size(); + int free_curve_count = OCC_curves.size(); + int free_point_count = OCC_points.size(); + int free_surface_count = OCC_surfaces.size(); + + //if nothing to write out...return + if( free_body_count == 0 && free_surface_count == 0 && + free_curve_count == 0 && free_point_count == 0) + return CUBIT_SUCCESS; + + //save the facets (geometry info ) + CubitStatus status; + + //write out topology and attributes + status = write_topology( p_buffer, n_buffer_size, + b_export_buffer, + OCC_bodies, OCC_surfaces, + OCC_curves, OCC_points); + if( status == CUBIT_FAILURE ) return CUBIT_FAILURE; + + if( free_body_count || free_surface_count || + free_curve_count || free_point_count ) + if (b_export_buffer) PRINT_INFO( "\nExported:" ); + else PRINT_INFO( "\nSize checked:" ); + + int flg = 0; + + if( free_body_count ) + { + if( flg )PRINT_INFO( " " );else flg=1; + if( free_body_count == 1 ) + PRINT_INFO( "%4d OCC Body to buffer\n", free_body_count ); + else + PRINT_INFO( "%4d OCC Bodies to buffer\n", free_body_count ); + } + + if( free_surface_count ) + { + if( flg )PRINT_INFO( " " );else flg=1; + if( free_surface_count == 1 ) + PRINT_INFO( "%4d OCC Surface to buffer\n", free_surface_count ); + else + PRINT_INFO( "%4d OCC Surface to buffer\n", free_surface_count ); + } + + if( free_curve_count ) + { + if( flg )PRINT_INFO( " " );else flg=1; + if( free_curve_count == 1 ) + PRINT_INFO( "%4d OCC Curve to buffer\n", free_curve_count ); + else + PRINT_INFO( "%4d OCC Curves to buffer\n", free_curve_count ); + } + + if( free_point_count ) + { + if( flg )PRINT_INFO( " " );else flg=1; + if( free_point_count == 1 ) + PRINT_INFO( "%4d OCC Point to buffer\n", free_point_count ); + else + PRINT_INFO( "%4d OCC Points to buffer\n", free_point_count ); + } + PRINT_INFO( "\n" ); + + return CUBIT_SUCCESS; +} + //=========================================================================== //Function Name:export_solid_model //Member Type: PUBLIC @@ -1101,7 +1223,288 @@ return CUBIT_SUCCESS; } +/* +CubitStatus +OCCQueryEngine::write_topology( //const unsigned char* p_buffer, + //char* p_buffer, + ofstream& os, + DLIList<OCCBody*> &OCC_bodies, + DLIList<OCCSurface*> &OCC_surfaces, + DLIList<OCCCurve*> &OCC_curves, + DLIList<OCCPoint*> &OCC_points) +{ + int i; + //Create a compound shape to export + BRep_Builder B; + TopoDS_Compound Co; + B.MakeCompound(Co); + + //Add every shape to the compound + for (i = 0; i < OCC_bodies.size(); i++) + { + OCCBody* body = OCC_bodies.get_and_step(); + TopoDS_CompSolid *shape = body->get_TopoDS_Shape(); + + if (shape == NULL) //sheet body or shell body + { + OCCSurface* surface = body->my_sheet_surface(); + OCCShell* shell = body->shell(); + if (surface == NULL && shell == NULL) + { + + PRINT_ERROR( "Wrong body structure. Internal ERROR\n" ); + continue; + } + if(surface) + B.Add(Co,*(surface->get_TopoDS_Face())); + else + B.Add(Co,*(shell->get_TopoDS_Shell())); + continue; + } + + //check if this body is build backwards from lump. if so, + //the body and its CompSolid doesn't have bounded relationship + //established. In this case, each individual lump of the body + // will be exported as TopoDS_Solid without a CompSolid + if(OCCMap->IsBound(*shape)) + B.Add(Co, *shape); + else + { + DLIList<Lump*> lumps = body->lumps(); + for(int i = 0; i < lumps.size(); i++) + { + OCCLump *occ_lump = (OCCLump *) lumps.get_and_step(); + TopoDS_Solid solid = *(occ_lump->get_TopoDS_Solid()); + B.Add(Co, solid); + } + } + } + + for (i = 0; i < OCC_surfaces.size(); i++) + { + TopoDS_Face *face = OCC_surfaces.get_and_step()->get_TopoDS_Face(); + B.Add(Co, *face); + } + + //Add standalone wires to the export BRep file + for (i = 0; i < WireList->size(); i++) + { + TopoDS_Wire *wire = WireList->get_and_step()->get_TopoDS_Wire(); + B.Add(Co, *wire); + } + + for (i = 0; i < OCC_curves.size(); i++) + { + TopoDS_Edge *edge = OCC_curves.get_and_step()->get_TopoDS_Edge(); + B.Add(Co, *edge); + } + + for (i = 0; i < OCC_points.size(); i++) + { + TopoDS_Vertex *vertex = OCC_points.get_and_step()->get_TopoDS_Vertex(); + B.Add(Co, *vertex); + } + + //if(strcmp(file_type, "OCC") == 0) + //{ + TDF_Label label; + if(EXPORT_ATTRIB) + label = mainLabel; + + if(!Write(Co, os)) + return CUBIT_FAILURE; + + return CUBIT_SUCCESS; +} + +CubitStatus +OCCQueryEngine::write_topology( + std::ostringstream& os, + DLIList<OCCBody*> &OCC_bodies, + DLIList<OCCSurface*> &OCC_surfaces, + DLIList<OCCCurve*> &OCC_curves, + DLIList<OCCPoint*> &OCC_points) +{ + + int i; + //Create a compound shape to export + BRep_Builder B; + TopoDS_Compound Co; + B.MakeCompound(Co); + + //Add every shape to the compound + for (i = 0; i < OCC_bodies.size(); i++) + { + OCCBody* body = OCC_bodies.get_and_step(); + TopoDS_CompSolid *shape = body->get_TopoDS_Shape(); + + if (shape == NULL) //sheet body or shell body + { + OCCSurface* surface = body->my_sheet_surface(); + OCCShell* shell = body->shell(); + if (surface == NULL && shell == NULL) + { + + PRINT_ERROR( "Wrong body structure. Internal ERROR\n" ); + continue; + } + if(surface) + B.Add(Co,*(surface->get_TopoDS_Face())); + else + B.Add(Co,*(shell->get_TopoDS_Shell())); + continue; + } + + //check if this body is build backwards from lump. if so, + //the body and its CompSolid doesn't have bounded relationship + //established. In this case, each individual lump of the body + // will be exported as TopoDS_Solid without a CompSolid + if(OCCMap->IsBound(*shape)) + B.Add(Co, *shape); + else + { + DLIList<Lump*> lumps = body->lumps(); + for(int i = 0; i < lumps.size(); i++) + { + OCCLump *occ_lump = (OCCLump *) lumps.get_and_step(); + TopoDS_Solid solid = *(occ_lump->get_TopoDS_Solid()); + B.Add(Co, solid); + } + } + } + + for (i = 0; i < OCC_surfaces.size(); i++) + { + TopoDS_Face *face = OCC_surfaces.get_and_step()->get_TopoDS_Face(); + B.Add(Co, *face); + } + + //Add standalone wires to the export BRep file + for (i = 0; i < WireList->size(); i++) + { + TopoDS_Wire *wire = WireList->get_and_step()->get_TopoDS_Wire(); + B.Add(Co, *wire); + } + + for (i = 0; i < OCC_curves.size(); i++) + { + TopoDS_Edge *edge = OCC_curves.get_and_step()->get_TopoDS_Edge(); + B.Add(Co, *edge); + } + + for (i = 0; i < OCC_points.size(); i++) + { + TopoDS_Vertex *vertex = OCC_points.get_and_step()->get_TopoDS_Vertex(); + B.Add(Co, *vertex); + } + + //if(strcmp(file_type, "OCC") == 0) + //{ + TDF_Label label; + if(EXPORT_ATTRIB) + label = mainLabel; + + if(!Write(Co, os)) + return CUBIT_FAILURE; + + return CUBIT_SUCCESS; +} +*/ +CubitStatus +OCCQueryEngine::write_topology( char*& p_buffer, + int& n_buffer_size, + bool b_export_buffer, + DLIList<OCCBody*> &OCC_bodies, + DLIList<OCCSurface*> &OCC_surfaces, + DLIList<OCCCurve*> &OCC_curves, + DLIList<OCCPoint*> &OCC_points) +{ + + int i; + //Create a compound shape to export + BRep_Builder B; + TopoDS_Compound Co; + B.MakeCompound(Co); + + //Add every shape to the compound + for (i = 0; i < OCC_bodies.size(); i++) + { + OCCBody* body = OCC_bodies.get_and_step(); + TopoDS_CompSolid *shape = body->get_TopoDS_Shape(); + + if (shape == NULL) //sheet body or shell body + { + OCCSurface* surface = body->my_sheet_surface(); + OCCShell* shell = body->shell(); + if (surface == NULL && shell == NULL) + { + + PRINT_ERROR( "Wrong body structure. Internal ERROR\n" ); + continue; + } + if(surface) + B.Add(Co,*(surface->get_TopoDS_Face())); + else + B.Add(Co,*(shell->get_TopoDS_Shell())); + continue; + } + + //check if this body is build backwards from lump. if so, + //the body and its CompSolid doesn't have bounded relationship + //established. In this case, each individual lump of the body + // will be exported as TopoDS_Solid without a CompSolid + if(OCCMap->IsBound(*shape)) + B.Add(Co, *shape); + else + { + DLIList<Lump*> lumps = body->lumps(); + for(int i = 0; i < lumps.size(); i++) + { + OCCLump *occ_lump = (OCCLump *) lumps.get_and_step(); + TopoDS_Solid solid = *(occ_lump->get_TopoDS_Solid()); + B.Add(Co, solid); + } + } + } + + for (i = 0; i < OCC_surfaces.size(); i++) + { + TopoDS_Face *face = OCC_surfaces.get_and_step()->get_TopoDS_Face(); + B.Add(Co, *face); + } + + //Add standalone wires to the export BRep file + for (i = 0; i < WireList->size(); i++) + { + TopoDS_Wire *wire = WireList->get_and_step()->get_TopoDS_Wire(); + B.Add(Co, *wire); + } + + for (i = 0; i < OCC_curves.size(); i++) + { + TopoDS_Edge *edge = OCC_curves.get_and_step()->get_TopoDS_Edge(); + B.Add(Co, *edge); + } + + for (i = 0; i < OCC_points.size(); i++) + { + TopoDS_Vertex *vertex = OCC_points.get_and_step()->get_TopoDS_Vertex(); + B.Add(Co, *vertex); + } + + //if(strcmp(file_type, "OCC") == 0) + //{ + TDF_Label label; + if(EXPORT_ATTRIB) + label = mainLabel; + + if(!Write(Co, p_buffer, n_buffer_size, b_export_buffer)) + return CUBIT_FAILURE; + + return CUBIT_SUCCESS; +} + CubitBoolean OCCQueryEngine::Write(const TopoDS_Shape& Sh, const Standard_CString File, TDF_Label label) @@ -1129,7 +1532,200 @@ return isGood; } +/* +CubitBoolean OCCQueryEngine::Write(const TopoDS_Shape& Sh, + //const unsigned char* pbuffer, + //streambuf* rpsbuf) + //char* pbuffer, + //TDF_Label label) + std::ofstream& os) +{ + os.open("test.txt", std::ios::out); + std::filebuf* pbuf_os = os.rdbuf(); + if (!pbuf_os->is_open()) return Standard_False; + + CubitBoolean isGood = (os.good() && !os.eof()); + if (!isGood) return isGood; + long os_size1 = pbuf_os->pubseekoff(0, std::ios_base::end, std::ios::out); + std::cout << "size os1 = " << os_size1 << std::endl; + + BinTools_ShapeSet SS; + SS.Add(Sh); + isGood = os.good(); + SS.Write(os); + isGood = os.good(); + + //std::streamsize size = pbuf->in_avail(); + long os_size = pbuf_os->pubseekoff(0, std::ios_base::end, std::ios::out); + std::cout << "size os2 = " << os_size << std::endl; + + char* buffer = new char[os_size]; + //os.write(buffer, os_size); + //pbuf_os->sputn(buffer, os_size); + + //memcpy(buffer, pbuf_os, os_size); + + return CUBIT_TRUE; +} + +CubitBoolean OCCQueryEngine::Write(const TopoDS_Shape& Sh, + std::ostringstream& os) +{ + + CubitBoolean isGood = (os.good() && !os.eof()); + if (!isGood) return isGood; + + std::stringbuf* pbuf = os.rdbuf(); + std::streamsize ssize = pbuf->in_avail(); + long size = pbuf->pubseekoff(0, std::ios_base::end, std::ios::out); + std::cout << "size os1 = " << size << " " << ssize << std::endl; + + BinTools_ShapeSet SS; + SS.Add(Sh); + isGood = os.good(); + SS.Write(os); + isGood = os.good(); + + ssize = pbuf->in_avail(); + size = pbuf->pubseekoff(0, std::ios_base::end, std::ios::out); + std::cout << "size os2 = " << size << " " << ssize << std::endl; + + char* buffer = new char[size]; + //os.write(buffer, os_size); + pbuf->sputn(buffer, size); + + std::istringstream is; + pbuf = is.rdbuf(); + + ssize = pbuf->in_avail(); + size = pbuf->pubseekoff(0, std::ios_base::end, std::ios::in); + std::cout << "size io1 = " << size << " " << ssize << std::endl; + + //is.tie(&os); + //is.read(buffer, size1); + pbuf->pubseekpos(0, std::ios::in); + pbuf->sgetn(buffer, size); + + ssize = pbuf->in_avail(); + size = is.rdbuf()->pubseekoff(0, std::ios_base::end, std::ios::in); + std::cout << "size io2 = " << size << " " << ssize << std::endl; + + pbuf->pubsetbuf(buffer, size); + + ssize = pbuf->in_avail(); + size = is.rdbuf()->pubseekoff(0, std::ios_base::end, std::ios::in); + std::cout << "size io3 = " << size << " " << ssize << std::endl; + + BinTools_ShapeSet SS2; + SS2.Read(is); + int nShape = SS2.NbShapes(); + std::cout << "nShpae = %d" << nShape << std::endl; + + + // test + std::ostringstream oss("test"); + pbuf = oss.rdbuf(); + ssize = pbuf->in_avail(); + size = pbuf->pubseekoff(0, std::ios_base::end, std::ios::out); + std::cout << "test size os1 = " << size << " " << ssize << std::endl; + + char* tbuffer = new char[size]; + //pbuf->sputn(tbuffer, size); + ssize = pbuf->sgetn(tbuffer, size); + + std::istringstream iss; + pbuf = iss.rdbuf(); + + //ssize = pbuf->in_avail(); + size = pbuf->pubseekoff(0, std::ios_base::end, std::ios::in); + std::cout << "test size io1 = " << size << " " << ssize << std::endl; + + //is.tie(&os); + //is.read(buffer, size1); + pbuf->pubseekpos(0, std::ios::in); + //pbuf->sgetn(tbuffer, size); + //ssize = pbuf->sputn(tbuffer, size); + pbuf->pubsetbuf(tbuffer, size); + + //ssize = pbuf->in_avail(); + size = iss.rdbuf()->pubseekoff(0, std::ios_base::end, std::ios::in); + std::cout << "test size io2 = " << size << " " << ssize << std::endl; + + pbuf->pubsetbuf(tbuffer, size); + + ssize = pbuf->in_avail(); + size = iss.rdbuf()->pubseekoff(0, std::ios_base::end, std::ios::in); + std::cout << "test size io3 = " << size << " " << ssize << std::endl; + + // + std::stringstream ssos("test2"); + ssize = ssos.rdbuf()->in_avail(); + size = ssos.rdbuf()->pubseekoff(0, std::ios_base::end, std::ios::in); + std::cout << "test size os4 = " << size << " " << ssize << std::endl; + std::string mystr = ssos.rdbuf()->str(); + std::stringstream ssis(mystr); + ssize = ssis.rdbuf()->in_avail(); + size = ssis.rdbuf()->pubseekoff(0, std::ios_base::end, std::ios::in); + std::cout << "test size is4 = " << size << " " << ssize << std::endl; + + std::stringbuf sbos; + std::stringbuf sbis; + std::iostream tos(&sbos); + std::iostream tis(&sbis); + BinTools_ShapeSet tSS1; + tSS1.Add(Sh); + isGood = tos.good(); + std::cout << "isGood=" << isGood << std::endl; + tSS1.Write(tos); + isGood = tos.good(); + std::cout << "isGood=" << isGood << std::endl; + size = tos.rdbuf()->pubseekoff(0, std::ios_base::end, std::ios::out); + std::cout << "test fos size = " << size << std::endl; + char* tbuffer1 = new char[size]; + tos.read(tbuffer1, size); + + tis.write(tbuffer1, size); + BinTools_ShapeSet tSS2; + tSS2.Read(tis); + isGood = tis.good(); + std::cout << "isGood=" << isGood << std::endl; + nShape = tSS2.NbShapes(); + std::cout << "test nShpae = " << nShape << std::endl; + + return CUBIT_TRUE; +} +*/ +CubitBoolean OCCQueryEngine::Write(const TopoDS_Shape& Sh, + char*& pBuffer, + int& n_buffer_size, + bool b_write_buffer) +{ + std::stringbuf sb; + std::iostream os(&sb); + BinTools_ShapeSet SS; + + SS.Add(Sh); + CubitBoolean isGood = os.good(); + //std::cout << "isGood=" << isGood << std::endl; + if (!isGood) return isGood; + SS.Write(os); + isGood = os.good(); + //std::cout << "isGood=" << isGood << std::endl; + if (!isGood) return isGood; + + n_buffer_size = os.rdbuf()->pubseekoff(0, std::ios_base::end, std::ios::out); + //std::cout << "test fos size = " << n_buffer_size + // << " nShape= " << SS.NbShapes() << std::endl; + + if (b_write_buffer) { + //delete pBuffer; + //pBuffer = new char[n_buffer_size]; + os.read(pBuffer, n_buffer_size); + } + + return CUBIT_TRUE; +} CubitBoolean OCCQueryEngine::Read(TopoDS_Shape& Sh, const Standard_CString File, @@ -1150,7 +1746,65 @@ SS.Read(Sh,in,nbshapes, &label); return CUBIT_TRUE; } + +CubitBoolean OCCQueryEngine::Read(TopoDS_Shape& Sh, + const char* pBuffer, + const int n_buffer_size) +{ + std::stringbuf sb; + std::iostream is(&sb); + is.write(pBuffer, n_buffer_size); + /* + BinTools_ShapeSet SS; + SS.Read(is); + CubitBoolean isGood = is.good(); + std::cout << "isGood=" << isGood << std::endl; + int nShape = SS.NbShapes(); + std::cout << "test nShpae = " << nShape << std::endl; + if (!nShape) return CUBIT_FALSE; + //Sh = SS.TopoDS_Shape(); + //SS.Read(Sh, is, nShape); + */ + //TDF_Label label; + //CubitBoolean print_results = false; + //OCCBinToolsShapeSet SS; + BinTools_ShapeSet SS; + SS.Read(is); + int nbshapes = SS.NbShapes(); + if (!nbshapes) return CUBIT_FALSE; + + //TopoDS_Shape fs = SS.Shape(1); + //TopoDS_Shape ls = SS.Shape(nbshapes); + /* for (int i = 1; i <= nbshapes; i++) { + TopoDS_Shape s = SS.Shape(i); + std::cout << "shape type" << i << "=" << s.ShapeType() << std::endl; + }*/ + + //SS.Read(Sh, is, nbshapes); + Sh = SS.Shape(nbshapes); + + //is.seekg (0, std::ios::beg); + //do { + //SS.Read(Sh, is, nbshapes); + //if (!Sh.IsNull()) { + //AddShapes(S,SS); + //break; + //} + //} while(!Sh.IsNull()); + + /* + BRep_Builder B; + TopoDS_Compound Co; + B.MakeCompound(Co); + for (int i = 1; i <= nShape; i++) { + B.Add(Co, SS.Shape(i)); + } + Sh = Co; + */ + return CUBIT_TRUE; +} + CubitStatus OCCQueryEngine::import_temp_geom_file(FILE* file_ptr, const char* file_name, @@ -1224,6 +1878,18 @@ return CUBIT_SUCCESS; } +CubitStatus OCCQueryEngine::import_solid_model(DLIList<TopologyBridge*> &imported_entities, + const char* pBuffer, + const int n_buffer_size) +{ + TopoDS_Shape *aShape = new TopoDS_Shape; + Standard_Boolean result = Read(*aShape, pBuffer, n_buffer_size); + if (result==0) return CUBIT_FAILURE; + + imported_entities = populate_topology_bridge(*aShape); + return CUBIT_SUCCESS; +} + //=========================================================================== //Function Name:populate_topology_bridge //Member Type: PUBLIC Modified: cgm/trunk/geom/OCC/OCCQueryEngine.hpp =================================================================== --- cgm/trunk/geom/OCC/OCCQueryEngine.hpp 2009-08-19 18:39:01 UTC (rev 3107) +++ cgm/trunk/geom/OCC/OCCQueryEngine.hpp 2009-08-19 20:05:46 UTC (rev 3108) @@ -231,6 +231,12 @@ const CubitString &cubit_version, const char* logfile_name = NULL ); + // write shapes to buffer as binary format + virtual CubitStatus export_solid_model( DLIList<TopologyBridge*>& ref_entity_list, + char*& p_buffer, + int& n_buffer_size, + bool b_export_buffer); + virtual CubitStatus save_temp_geom_file( DLIList<TopologyBridge*>& ref_entity_list, const char *file_name, const CubitString &cubit_version, @@ -254,6 +260,10 @@ CubitBoolean import_vertices = CUBIT_TRUE, CubitBoolean free_surfaces = CUBIT_TRUE ); + virtual CubitStatus import_solid_model(DLIList<TopologyBridge*> &imported_entities, + const char* pBuffer, + const int n_buffer_size); + CubitStatus unhook_BodySM_from_OCC( BodySM* bodysm)const; CubitStatus unhook_Surface_from_OCC( Surface* surface) const; CubitStatus unhook_Curve_from_OCC( Curve* curve) const; @@ -387,15 +397,32 @@ DLIList<OCCCurve*> &facet_curves, DLIList<OCCPoint*> &facet_points ); + CubitStatus write_topology( char*& p_buffer, + int& n_buffer_size, + bool b_export_buffer, + DLIList<OCCBody*> &OCC_bodies, + DLIList<OCCSurface*> &OCC_surfaces, + DLIList<OCCCurve*> &OCC_curves, + DLIList<OCCPoint*> &OCC_points); + CubitBoolean Write(const TopoDS_Shape& Sh, const Standard_CString File, TDF_Label label); + CubitBoolean Write(const TopoDS_Shape& Sh, + char*& p_buffer, + int& n_buffer_size, + bool b_export_buffer); + CubitBoolean Read(TopoDS_Shape& Sh, const Standard_CString File, TDF_Label label, bool print_results); + CubitBoolean Read(TopoDS_Shape& Sh, + const char* pBuffer, + const int n_buffer_size); + static OCCQueryEngine* instance_; //- static pointer to unique instance of this class Modified: cgm/trunk/geom/facet/FacetQueryEngine.cpp =================================================================== --- cgm/trunk/geom/facet/FacetQueryEngine.cpp 2009-08-19 18:39:01 UTC (rev 3107) +++ cgm/trunk/geom/facet/FacetQueryEngine.cpp 2009-08-19 20:05:46 UTC (rev 3108) @@ -849,6 +849,14 @@ return CUBIT_SUCCESS; } +CubitStatus FacetQueryEngine::export_solid_model( DLIList<TopologyBridge*>& bridge_list, + char*& p_buffer, + int& n_buffer_size, + bool b_export_buffer) +{ + return CUBIT_FAILURE; +} + CubitStatus FacetQueryEngine::gather_all_facet_entities( DLIList<FacetBody*> &facet_bodies, DLIList<FacetLump*> &facet_lumps, @@ -1790,13 +1798,13 @@ PRINT_ERROR("Trouble reading in file type for MBG\n"); return CUBIT_FAILURE; } - + if( strncmp( fileType, "MESH_BASED_GEOMETRY", 19 ) ) { PRINT_ERROR("Not MESH_BASED_GEOMETRY file type\n"); return CUBIT_FAILURE; } - + // read in the endian value NCubitFile::CIOWrapper file_reader(file_ptr, 19, 0); @@ -1838,6 +1846,12 @@ return CUBIT_SUCCESS; } +CubitStatus FacetQueryEngine::import_solid_model(DLIList<TopologyBridge*> &imported_entities, + const char* pBuffer, + const int n_buffer_size) +{ + return CUBIT_FAILURE; +} //=============================================================================== // Function : restore_facets Modified: cgm/trunk/geom/facet/FacetQueryEngine.hpp =================================================================== --- cgm/trunk/geom/facet/FacetQueryEngine.hpp 2009-08-19 18:39:01 UTC (rev 3107) +++ cgm/trunk/geom/facet/FacetQueryEngine.hpp 2009-08-19 20:05:46 UTC (rev 3108) @@ -270,6 +270,11 @@ const CubitString &cubit_version, const char* logfile_name = NULL ); + virtual CubitStatus export_solid_model( DLIList<TopologyBridge*>& bridge_list, + char*& p_buffer, + int& n_buffer_size, + bool b_export_buffer); + virtual CubitStatus save_temp_geom_file( DLIList<TopologyBridge*>& ref_entity_list, const char *file_name, const CubitString &cubit_version, @@ -292,7 +297,11 @@ CubitBoolean import_curves = CUBIT_TRUE, CubitBoolean import_vertices = CUBIT_TRUE, CubitBoolean free_surfaces = CUBIT_TRUE ); -private: + + virtual CubitStatus import_solid_model(DLIList<TopologyBridge*> &imported_entities, + const char* pBuffer, + const int n_buffer_size); + private: CubitStatus import_solid_model(FILE *file_ptr, const char* /*file_type*/, DLIList<TopologyBridge*> &imported_entities, Deleted: cgm/trunk/geom/parallel/AcisMemFile.hpp =================================================================== --- cgm/trunk/geom/parallel/AcisMemFile.hpp 2009-08-19 18:39:01 UTC (rev 3107) +++ cgm/trunk/geom/parallel/AcisMemFile.hpp 2009-08-19 20:05:46 UTC (rev 3108) @@ -1,144 +0,0 @@ -#ifndef ACISMEMFILE -#define ACISMEMFILE - -//--------------------------------------------------------------------- -// Define the AcisMemFile class for doing ACIS save and restore to a memory -// buffer. This file is intended as an example of how to create a new -// ACIS FileInterface object. -// -// This class is used to store ACIS-specific geometry in a memory file; -// generic memory file functions are implemented in CGMMemFile; ACIS-specific -// functions for gathering ACIS geometry and putting it in a memory buffer -// is implemented in AcisMemFile and in the ACIS BinaryFile class. -// -// There is also a FileSizeComputer class. This can be used to determine -// how many bytes a list of entities will use when saved. -//--------------------------------------------------------------------- - -#if CUBIT_ACIS_VERSION < 1100 -#include "kernel/kernutil/fileio/binfile.hxx" -#else -#include "binfile.hxx" -#endif -#include "CGMMemFile.hpp" -#include "DLIList.hpp" - -class AcisQueryEngine; -class RefEntity; -class ENTITY_LIST; -//--------------------------------------------------------------------- - -class AcisMemFile : public BinaryFile, - public CGMMemFile -{ - -public: - - AcisMemFile(AcisQueryEngine *aqe) {acisQueryEngine = aqe;}; - //- (empty) constructor - - virtual ~AcisMemFile() {}; - //- (empty) destructor - - virtual FilePosition set_mark(); - //- The methods for positioning the file pointer must also be - //- implemented for each derived class. These are not normally - //- used. - - virtual FilePosition goto_mark(FilePosition); - //- The methods for positioning the file pointer must also be - //- implemented for each derived class. These are not normally - //- used. - - size_t BytesWritten() { return (size_t)m_currentPosition; } - //- Get the number of bytes written - -protected: - - CubitStatus read_refentity_list(DLIList<RefEntity*> &ref_entity_list); - //- read a RefEntity list from the buffer into ref_entity_list; relies on engine- - //- specific implementation - - CubitStatus write_refentity_list(DLIList<RefEntity*> &ref_entity_list); - //- write a RefEntity list to the buffer from ref_entity_list; relies on engine- - //- specific implementation - CubitStatus append_refentity_list(DLIList<RefEntity*> &ref_entity_list, - int &buffer_size); - - CubitStatus get_refentity_list(DLIList<RefEntity*> &ref_entity_list); - - virtual int get_refentity_list_size(DLIList<RefEntity*> ref_entity_list); - //- get a the size of entities - - virtual size_t read(void* buf, size_t length, logical swap); - //- ACIS-dependent function to read data from a buffer - - virtual void write(const void* data, size_t len, logical swap); - //- ACIS-dependent function to write data to a buffer - -private: - size_t write_memory_buffer(ENTITY_LIST &entity_list); - //- write ACIS entity list to memory buffer - - size_t append_memory_buffer(ENTITY_LIST &entity_list, - int &buffer_size); - - //unsigned char* get_memory_buffer(ENTITY_LIST &entity_list); - - int get_memory_buffer_size(ENTITY_LIST entity_list); - //- get a the size of entities in memory buffer - - size_t read_memory_buffer(ENTITY_LIST &entity_list); - // read ACIS entity list from memory buffer - size_t scatter_memory_buffer(ENTITY_LIST &entity_list, - int *buffer_sizes); - AcisQueryEngine *acisQueryEngine; - //- for convenience - -}; - -//--------------------------------------------------------------------- -// This class can be used to compute how many bytes will be required -// to save a list of entities in binary format. The following example -// shows how it can be used: -// -// ENTITY_LIST elist; -// ... add entities you want saved to the list -// FileSizeComputer fsc; -// outcome result = api_save_entity_list_file(&fsc, elist); -// if(result.ok()) { -// unsigned long bytesNeeded = sc.GetSize(); -// } - -class FileSizeComputer : public BinaryFile { - -private: - size_t m_bytesNeeded; - int num_writes; // number of calls to write function - -protected: - - // These are the virtual methods which actually do the reading - // and writing of the data. - - // Read doesn't really do anything. - virtual size_t read(void* buf, size_t length, logical swap); - virtual void write(const void* data, size_t len, logical swap); - -public: - - // The methods for positioning the file pointer must also be - // implemented for each derived class. These do not do - // anything in this class - virtual FilePosition set_mark(); - virtual FilePosition goto_mark(FilePosition); - -public: - FileSizeComputer(); - virtual ~FileSizeComputer(); - size_t GetSize(); - int GetWrites(); -}; - -//--------------------------------------------------------------------- -#endif Added: cgm/trunk/geom/parallel/AcisMemFile.hpp =================================================================== --- cgm/trunk/geom/parallel/AcisMemFile.hpp (rev 0) +++ cgm/trunk/geom/parallel/AcisMemFile.hpp 2009-08-19 20:05:46 UTC (rev 3108) @@ -0,0 +1,144 @@ +#ifndef ACISMEMFILE +#define ACISMEMFILE + +//--------------------------------------------------------------------- +// Define the AcisMemFile class for doing ACIS save and restore to a memory +// buffer. This file is intended as an example of how to create a new +// ACIS FileInterface object. +// +// This class is used to store ACIS-specific geometry in a memory file; +// generic memory file functions are implemented in CGMMemFile; ACIS-specific +// functions for gathering ACIS geometry and putting it in a memory buffer +// is implemented in AcisMemFile and in the ACIS BinaryFile class. +// +// There is also a FileSizeComputer class. This can be used to determine +// how many bytes a list of entities will use when saved. +//--------------------------------------------------------------------- + +#if CUBIT_ACIS_VERSION < 1100 +#include "kernel/kernutil/fileio/binfile.hxx" +#else +#include "binfile.hxx" +#endif +#include "CGMMemFile.hpp" +#include "DLIList.hpp" + +class AcisQueryEngine; +class RefEntity; +class ENTITY_LIST; +//--------------------------------------------------------------------- + +class AcisMemFile : public BinaryFile, + public CGMMemFile +{ + +public: + + AcisMemFile(AcisQueryEngine *aqe) {acisQueryEngine = aqe;}; + //- (empty) constructor + + virtual ~AcisMemFile() {}; + //- (empty) destructor + + virtual FilePosition set_mark(); + //- The methods for positioning the file pointer must also be + //- implemented for each derived class. These are not normally + //- used. + + virtual FilePosition goto_mark(FilePosition); + //- The methods for positioning the file pointer must also be + //- implemented for each derived class. These are not normally + //- used. + + size_t BytesWritten() { return (size_t)m_currentPosition; } + //- Get the number of bytes written + +protected: + + CubitStatus read_refentity_list(DLIList<RefEntity*> &ref_entity_list); + //- read a RefEntity list from the buffer into ref_entity_list; relies on engine- + //- specific implementation + + CubitStatus write_refentity_list(DLIList<RefEntity*> &ref_entity_list); + //- write a RefEntity list to the buffer from ref_entity_list; relies on engine- + //- specific implementation + CubitStatus append_refentity_list(DLIList<RefEntity*> &ref_entity_list, + int &buffer_size); + + CubitStatus get_refentity_list(DLIList<RefEntity*> &ref_entity_list); + + virtual int get_refentity_list_size(DLIList<RefEntity*> ref_entity_list); + //- get a the size of entities + + virtual size_t read(void* buf, size_t length, logical swap); + //- ACIS-dependent function to read data from a buffer + + virtual void write(const void* data, size_t len, logical swap); + //- ACIS-dependent function to write data to a buffer + +private: + size_t write_memory_buffer(ENTITY_LIST &entity_list); + //- write ACIS entity list to memory buffer + + size_t append_memory_buffer(ENTITY_LIST &entity_list, + int &buffer_size); + + //unsigned char* get_memory_buffer(ENTITY_LIST &entity_list); + + int get_memory_buffer_size(ENTITY_LIST entity_list); + //- get a the size of entities in memory buffer + + size_t read_memory_buffer(ENTITY_LIST &entity_list); + // read ACIS entity list from memory buffer + size_t scatter_memory_buffer(ENTITY_LIST &entity_list, + int *buffer_sizes); + AcisQueryEngine *acisQueryEngine; + //- for convenience + +}; + +//--------------------------------------------------------------------- +// This class can be used to compute how many bytes will be required +// to save a list of entities in binary format. The following example +// shows how it can be used: +// +// ENTITY_LIST elist; +// ... add entities you want saved to the list +// FileSizeComputer fsc; +// outcome result = api_save_entity_list_file(&fsc, elist); +// if(result.ok()) { +// unsigned long bytesNeeded = sc.GetSize(); +// } + +class FileSizeComputer : public BinaryFile { + +private: + size_t m_bytesNeeded; + int num_writes; // number of calls to write function + +protected: + + // These are the virtual methods which actually do the reading + // and writing of the data. + + // Read doesn't really do anything. + virtual size_t read(void* buf, size_t length, logical swap); + virtual void write(const void* data, size_t len, logical swap); + +public: + + // The methods for positioning the file pointer must also be + // implemented for each derived class. These do not do + // anything in this class + virtual FilePosition set_mark(); + virtual FilePosition goto_mark(FilePosition); + +public: + FileSizeComputer(); + virtual ~FileSizeComputer(); + size_t GetSize(); + int GetWrites(); +}; + +//--------------------------------------------------------------------- +#endif Property changes on: cgm/trunk/geom/parallel/AcisMemFile.hpp ___________________________________________________________________ Added: svn:executable + * Added: cgm/trunk/geom/parallel/CGMParallelComm.cpp =================================================================== --- cgm/trunk/geom/parallel/CGMParallelComm.cpp (rev 0) +++ cgm/trunk/geom/parallel/CGMParallelComm.cpp 2009-08-19 20:05:46 UTC (rev 3108) @@ -0,0 +1,421 @@ +#include "CGMParallelComm.hpp" +//#include "CubitAttrib.hpp" +//#include "OCCQueryEngine.hpp" +#include "TopologyEntity.hpp" +#include "GeometryQueryEngine.hpp" +#include "RefEntity.hpp" + +//#include <iostream> +#include <sstream> + +#ifdef USE_MPI +#include "mpi.h" +#endif + +#define INITIAL_BUFF_SIZE 1024 +#define RRA(a) if (CUBIT_SUCCESS != result) { \ + std::string tmp_str; \ + tmp_str.append("\n"); tmp_str.append(a); \ + PRINT_ERROR(tmp_str.c_str()); \ + return result;} + +CGMParallelComm::CGMParallelComm(CGMTagManager *impl, + MPI_Comm comm, int* id ) + : cgmImpl(impl), procConfig(comm) +{ + myBuffer.resize(INITIAL_BUFF_SIZE); + + int flag = 1; + int retval = MPI_Initialized(&flag); + if (MPI_SUCCESS != retval || !flag) { + int argc = 0; + char **argv = NULL; + + // mpi not initialized yet - initialize here + retval = MPI_Init(&argc, &argv); + } + + pcommID = add_pcomm(this); + if (id) + *id = pcommID; + + m_pBuffer = NULL; + m_nBufferSize = 0; + m_currentPosition = 0; +} + +CGMParallelComm::CGMParallelComm(CGMTagManager *impl, + std::vector<unsigned char> &tmp_buff, + MPI_Comm comm, + int* id) + : cgmImpl(impl), procConfig(comm) +{ + myBuffer.swap(tmp_buff); + int flag = 1; + int retval = MPI_Initialized(&flag); + if (MPI_SUCCESS != retval || !flag) { + int argc = 0; + char **argv = NULL; + + // mpi not initialized yet - initialize here + retval = MPI_Init(&argc, &argv); + } + + pcommID = add_pcomm(this); + if (id) + *id = pcommID; + + m_pBuffer = NULL; + m_nBufferSize = 0; + m_currentPosition = 0; +} + +CGMParallelComm::~CGMParallelComm() +{ + remove_pcomm(this); + delete m_pBuffer; +} + +int CGMParallelComm::add_pcomm(CGMParallelComm *pc) +{ + // add this pcomm to instance tag + std::vector<CGMParallelComm *> pc_array; + pc_array = cgmImpl->get_pc_array(); + pc_array.push_back(pc); + + return pc_array.size() - 1; +} + +void CGMParallelComm::remove_pcomm(CGMParallelComm *pc) +{ + // remove this pcomm from instance tag + std::vector<CGMParallelComm *> pc_array; + pc_array = cgmImpl->get_pc_array(); + + std::vector<CGMParallelComm*>::iterator pc_it = + std::find(pc_array.begin(), pc_array.end(), pc); + assert(pc_it != pc_array.end()); + pc_array.erase(pc_it); +} + +//! get the indexed pcomm object from the interface +CGMParallelComm *CGMParallelComm::get_pcomm(CGMTagManager *impl, + const int index) +{ + std::vector<CGMParallelComm *> pc_array; + pc_array = impl->get_pc_array(); + + if (pc_array.size() < (unsigned int) (index + 1)) return NULL; + else return pc_array[index]; +} + +CubitStatus CGMParallelComm::get_all_pcomm(CGMTagManager *impl, + std::vector<CGMParallelComm*>& list ) +{ + list = impl->get_pc_array(); + return CUBIT_SUCCESS; +} + + +//! get the indexed pcomm object from the interface +CGMParallelComm *CGMParallelComm::get_pcomm(CGMTagManager *impl, + //MBEntityHandle prtn, + const MPI_Comm* comm ) +{ + //MBErrorCode rval; + CGMParallelComm* result = 0; + + //MBTag prtn_tag; + //rval = impl->tag_create( PARTITIONING_PCOMM_TAG_NAME, + // sizeof(int), + // MB_TAG_SPARSE, + // MB_TYPE_INTEGER, + // prtn_tag, + // 0, true ); + //if (MB_SUCCESS != rval) + //return 0; + + int pcomm_id; + //rval = impl->tag_get_data( prtn_tag, &prtn, 1, &pcomm_id ); + //if (MB_SUCCESS == rval) { + result= get_pcomm(impl, + pcomm_id ); + //} + /* + else if (MB_TAG_NOT_FOUND == rval && comm) { + result = new MBParallelComm( impl, *comm, &pcomm_id ); + if (!result) + return 0; + result->set_partitioning( prtn ); + + rval = impl->tag_set_data( prtn_tag, &prtn, 1, &pcomm_id ); + if (MB_SUCCESS != rval) { + delete result; + result = 0; + } + }*/ + + return result; +} + +CubitStatus CGMParallelComm::bcast_buffer(const unsigned int from_proc) +{ + //- broadcasts the buffer contained in this object + + if ((int)procConfig.proc_rank() == from_proc) { + PRINT_DEBUG_100("Broadcasting buffer size from %d.\n", from_proc); + MPI_Bcast(&m_nBufferSize, 1, MPI_INT, from_proc, MPI_COMM_WORLD); + PRINT_DEBUG_100("Broadcasting buffer from %d, %d bytes.\n", from_proc, + m_nBufferSize); + MPI_Bcast(m_pBuffer, m_nBufferSize, MPI_BYTE, from_proc, + MPI_COMM_WORLD); + } + else { + int this_size; + PRINT_DEBUG_100("Broadcasting buffer size from proc %d.\n", + procConfig.proc_rank()); + MPI_Bcast(&this_size, 1, MPI_INT, from_proc, + MPI_COMM_WORLD); + PRINT_DEBUG_100("Processor %d: received size of %d.\n", procConfig.proc_rank(), this_size); + check_size(this_size); + PRINT_DEBUG_100("Broadcasting buffer from proc %d, %d bytes.\n", + procConfig.proc_rank(), this_size); + MPI_Bcast(m_pBuffer, this_size, MPI_BYTE, from_proc, + MPI_COMM_WORLD); + } + + return CUBIT_SUCCESS; +} + +CubitStatus CGMParallelComm::broadcast_entities(const unsigned int from_proc, + DLIList<RefEntity*> &ref_entity_list) +{ +#ifndef USE_MPI + return CUBIT_FAILURE; +#else + CubitStatus result = CUBIT_SUCCESS; + + if ((int)procConfig.proc_rank() == from_proc) { + int nBufferSize = 0; + result = write_buffer(ref_entity_list, m_pBuffer, nBufferSize, false); + RRA("Failed to write ref entity list to buffer."); + + result = check_size(nBufferSize); + RRA("Failed to write ref entity list to buffer."); + + result = write_buffer(ref_entity_list, m_pBuffer, nBufferSize, true); + //m_currentPosition = m_nBufferSize; + RRA("Failed to write ref entity list to buffer."); + } + + result = bcast_buffer(from_proc); + RRA("Failed to broadcast buffer to processors."); + + if ((int)procConfig.proc_rank() != from_proc) { + result = read_buffer(ref_entity_list, m_pBuffer, m_nBufferSize); + RRA("Failed to read ref entity list from buffer."); + } + + return CUBIT_SUCCESS; +#endif +} + +// scatter exact amount of geometry information to each processors +CubitStatus CGMParallelComm::scatter_entities(const unsigned int from_proc, + DLIList<RefEntity*> &ref_entity_list) +{ +#ifndef USE_MPI + return CUBIT_FAILURE; +#else + CubitStatus result = CUBIT_SUCCESS; + CubitStatus status; + double tScatter; + int mySendCount; + int nEntity; + DLIList<RefEntity*> temp_list, temp_ref_list; + + int nProcs = procConfig.proc_size(); + int *sendCounts = new int[nProcs]; + int *displacements = new int[nProcs]; + int nBarEntity; + int restEntity; + int nEndEntity; + displacements[0] = 0; + + if (procConfig.proc_rank() == from_proc) { + int curPosition = 0; + nEntity = ref_entity_list.size(); + nBarEntity = nEntity/nProcs; + restEntity = nEntity%nProcs; + nEndEntity = nBarEntity + restEntity; + + ref_entity_list.reset(); + int sum = 0; + + // make temporary lists to contain geometry information for each processors + for (int i = 0; i < nProcs; i++) { + if (i == from_proc) { + ref_entity_list.step(nBarEntity); + if (i < restEntity) ref_entity_list.step(); + sendCounts[i] = 0; + } + else { + for ( int j = 0; j < nBarEntity; j++) { + RefEntity* body_ptr = ref_entity_list.get_and_step(); + temp_list.append(body_ptr); + } + + if (i < restEntity) { + RefEntity* body_ptr = ref_entity_list.get_and_step(); + temp_list.append(body_ptr); + } + + //sendCounts[i] = get_ref_list_buffer_size(temp_list); + result = write_buffer(temp_list, m_pBuffer, sendCounts[i], false); + RRA("Failed to write ref entity list to buffer."); + + sum += sendCounts[i]; + temp_list.clean_out(); + } + } + + // check the size of the buffer and resize if necessary + check_size(sum); + + // now append the real information + ref_entity_list.reset(); + for (int i = 0; i < nProcs; i++) { + if (i == from_proc) { + ref_entity_list.step(nBarEntity); + if (i < restEntity) ref_entity_list.step(); + } + else { + for ( int j = 0; j < nBarEntity; j++) { + temp_list.append(ref_entity_list.get_and_step()); + } + + if (i < restEntity) { + temp_list.append(ref_entity_list.get_and_step()); + } + + append_to_buffer(temp_list, sendCounts[i]); + temp_list.clean_out(); + } + } + } + + // broadcast buffer size array + PRINT_DEBUG_100("Broadcasting buffer size array from master.\n"); + MPI_Bcast(sendCounts, nProcs, MPI_INT, from_proc, MPI_COMM_WORLD); + + for (int i = 1; i < nProcs; i++) { + displacements[i] = displacements[i-1] + sendCounts[i-1]; + } + + mySendCount = sendCounts[procConfig.proc_rank()]; + + if (procConfig.proc_rank() != from_proc) check_size(mySendCount); + + PRINT_DEBUG_100("Scattering buffer from master.\n"); + + // scatter geometry + MPI_Scatterv(m_pBuffer, sendCounts, displacements, MPI_BYTE, m_pBuffer, + mySendCount, MPI_BYTE, from_proc, MPI_COMM_WORLD); + + if (procConfig.proc_rank() != from_proc) { + result = read_buffer(ref_entity_list, m_pBuffer, mySendCount); + RRA("Failed to read ref entity list from buffer."); + } + + return CUBIT_SUCCESS; +#endif +} +/* +CubitStatus CGMParallelComm::write_buffer(DLIList<RefEntity*> &ref_entity_list, + std::ofstream& os) +{ +#ifndef USE_MPI + return CUBIT_FAILURE; +#else + //ofstream os; + //CubitStatus result = GeometryQueryTool::instance()->export_solid_model(ref_entity_list, p_buffer); + CubitStatus result = GeometryQueryTool::instance()->export_solid_model(ref_entity_list, os); + RRA("Failed to compute buffer size in broadcast_entities."); + + return CUBIT_SUCCESS; +#endif +} + +CubitStatus CGMParallelComm::write_buffer(DLIList<RefEntity*> &ref_entity_list, + std::ostringstream& os) +{ +#ifndef USE_MPI + return CUBIT_FAILURE; +#else + CubitStatus result = GeometryQueryTool::instance()->export_solid_model(ref_entity_list, os); + RRA("Failed to compute buffer size in broadcast_entities."); + + return CUBIT_SUCCESS; +#endif +} +*/ +CubitStatus CGMParallelComm::write_buffer(DLIList<RefEntity*> &ref_entity_list, + char* pBuffer, + int& n_buffer_size, + bool b_write_buffer) +{ +#ifndef USE_MPI + return CUBIT_FAILURE; +#else + CubitStatus result = GeometryQueryTool::instance()->export_solid_model(ref_entity_list, pBuffer, + n_buffer_size, b_write_buffer); + RRA("Failed to write ref entities to buffer."); + + if (b_write_buffer) m_currentPosition += n_buffer_size; + return CUBIT_SUCCESS; +#endif +} + +CubitStatus CGMParallelComm::read_buffer(DLIList<RefEntity*> &ref_entity_list, + const char* pBuffer, + const int n_buffer_size) +{ +#ifndef USE_MPI + return CUBIT_FAILURE; +#else + CubitStatus result = GeometryQueryTool::instance()->import_solid_model(&ref_entity_list, pBuffer, + n_buffer_size); + RRA("Failed to read ref entities from buffer."); + + return CUBIT_SUCCESS; +#endif +} + +CubitStatus CGMParallelComm::check_size(int& target_size, const CubitBoolean keep) +{ + PRINT_DEBUG_100("Checking buffer size on proc %d, target size %d.\n", + procConfig.proc_rank(), target_size); + + if (m_nBufferSize < target_size) { + PRINT_DEBUG_100("Increasing buffer size on proc %d.\n", procConfig.proc_rank()); + void *temp_buffer = malloc(target_size); + if (keep && 0 != m_currentPosition) memcpy(temp_buffer, m_pBuffer, m_currentPosition); + delete m_pBuffer; + m_pBuffer = (char *) temp_buffer; + m_nBufferSize = target_size; + } + + return CUBIT_SUCCESS; +} + +CubitStatus CGMParallelComm::append_to_buffer(DLIList<RefEntity*> &ref_entity_list, + int add_size) +{ + if (m_currentPosition + add_size > m_nBufferSize) return CUBIT_FAILURE; + CubitStatus result = write_buffer(ref_entity_list, m_pBuffer + m_currentPosition, add_size, true); + RRA("Failed to append ref entity list to buffer."); + + //m_currentPosition += add_size; + + return CUBIT_SUCCESS; +} Added: cgm/trunk/geom/parallel/CGMParallelComm.hpp =================================================================== --- cgm/trunk/geom/parallel/CGMParallelComm.hpp (rev 0) +++ cgm/trunk/geom/parallel/CGMParallelComm.hpp 2009-08-19 20:05:46 UTC (rev 3108) @@ -0,0 +1,225 @@ +/** + * \class CGMParallelComm + * \brief Parallel communications in CGM + * \author Hong-Jun Kim, copied from MBParallelComm.hpp + * + * This class implements methods to communicate geometry between processors + * + */ + +#ifndef CGM_PARALLEL_COMM_HPP +#define CGM_PARALLEL_COMM_HPP + +//#include "CGMForward.hpp" +#include "GeometryQueryTool.hpp" +//#include "CGMRange.hpp" +#include "CGMProcConfig.hpp" +#include "CATag.hpp" +#include <map> +#include <set> +#include <vector> +#include "math.h" + +#ifdef SEEK_SET +# define SEEK_SET_OLD SEEK_SET +# undef SEEK_SET +#endif +#ifdef SEEK_CUR +# define SEEK_CUR_OLD SEEK_CUR +# undef SEEK_CUR +#endif +#ifdef SEEK_END +# define SEEK_END_OLD SEEK_END +# undef SEEK_END +#endif +#include "mpi.h" +#ifdef SEEK_SET_OLD +# undef SEEK_SET +# define SEEK_SET SEEK_SET_OLD +# undef SEEK_SET_OLD +#endif +#ifdef SEEK_CUR_OLD +# undef SEEK_CUR +# define SEEK_CUR SEEK_CUR_OLD +# undef SEEK_CUR_OLD +#endif +#ifdef SEEK_END_OLD +# undef SEEK_END +# define SEEK_END SEEK_END_OLD +# undef SEEK_END_OLD +#endif + + +extern "C" { + struct tuple_list; +} + +//class TagServer; +//class SequenceManager; +//template <typename KeyType, typename ValType, ValType NullVal> class RangeMap; +//typedef RangeMap<CGMEntityHandle, CGMEntityHandle, 0> HandleMap; + +#define MAX_SHARING_PROCS 64 + +class CGMParallelComm +{ +public: + + //! constructor + CGMParallelComm(CGMTagManager *impl, + MPI_Comm comm = MPI_COMM_WORLD, + int* pcomm_id_out = 0); + + //! constructor taking buffer, for testing + CGMParallelComm(CGMTagManager *impl, + std::vector<unsigned char> &tmp_buff, + MPI_Comm comm = MPI_COMM_WORLD, + int* pcomm_id_out = 0); + + //! Get ID used to reference this PCOMM instance + int get_id() const { return pcommID; } + + //! get the indexed pcomm object from the interface + static CGMParallelComm *get_pcomm(CGMTagManager *impl, + const int index); + + //! Get CGMParallelComm instance associated with partition handle + //! Will create CGMParallelComm instance if a) one does not already + //! exist and b) a valid value for MPI_Comm is passed. + static CGMParallelComm *get_pcomm(CGMTagManager *impl, + //CGMEntityHandle partitioning, + const MPI_Comm* comm = 0 ); + + static CubitStatus get_all_pcomm(CGMTagManager *impl, + std::vector<CGMParallelComm*>& list ); + + //! destructor + ~CGMParallelComm(); + + //static unsigned char PROC_SHARED, PROC_OWNER; + /* + //! assign a global id space, for largest-dimension or all entities (and + //! in either case for vertices too) + CGMErrorCode assign_global_ids(CGMEntityHandle this_set, + const int dimension, + const int start_id = 1, + const bool largest_dim_only = true, + const bool parallel = true); + + //! check for global ids; based only on tag handle being there or not; + //! if it's not there, create them for the specified dimensions + CGMErrorCode check_global_ids(CGMEntityHandle this_set, + const int dimension, + const int start_id = 1, + const bool largest_dim_only = true, + const bool parallel = true); + */ + + //! return partition ref entity list + DLIList<RefEntity*> &partition_surf_list() {return partitioningSurfList;} + const DLIList<RefEntity*> &partition_surf_list() const {return partitioningSurfList;} + DLIList<RefEntity*> &partition_body_list() {return partitioningBodyList;} + const DLIList<RefEntity*> &partition_body_list() const {return partitioningBodyList;} + + //! Get proc config for this communication object + const CGMProcConfig &proc_config() const {return procConfig;} + + //! Get proc config for this communication object + CGMProcConfig &proc_config() {return procConfig;} + + CubitStatus broadcast_entities(const unsigned int from_proc, + DLIList<RefEntity*> &ref_entity_list); + + CubitStatus scatter_entities(const unsigned int from_proc, + DLIList<RefEntity*> &ref_entity_list); + /* + CubitStatus write_buffer(DLIList<RefEntity*> &ref_entity_list, + //const unsigned char* p_buffer); + //char* p_buffer); + std::ofstream& os); + + CubitStatus write_buffer(DLIList<RefEntity*> &ref_entity_list, + std::ostringstream& os); + */ + CubitStatus write_buffer(DLIList<RefEntity*> &ref_entity_list, + char* pBuffer, + int& n_buffer_size, + bool b_export_buffer); + + CubitStatus read_buffer(DLIList<RefEntity*> &ref_entity_list, + const char* pBuffer, + const int n_buffer_size); + + CubitStatus bcast_buffer(const unsigned int from_proc); + + CubitStatus append_to_buffer(DLIList<RefEntity*> &ref_entity_list, + int add_size); + +private: + + //! add a pc to the iface instance tag PARALLEL_COMM + int add_pcomm(CGMParallelComm *pc); + + //! remove a pc from the iface instance tag PARALLEL_COMM + void remove_pcomm(CGMParallelComm *pc); + + CubitStatus check_size(int& target_size, const CubitBoolean keep = CUBIT_FALSE); + + //! CGM query tool interface associated with this writer + GeometryQueryTool *gqt; + + //! CGM tag manager interface associated with this writer + CGMTagManager *cgmImpl; + + //! Proc config object, keeps info on parallel stuff + CGMProcConfig procConfig; + + //! Tag server, so we can get more info about tags + //TagServer *tagServer; + + //! Sequence manager, to get more efficient access to entities + //SequenceManager *sequenceManager; + + + //! data buffer used to communicate + std::vector<unsigned char> myBuffer; + + char* m_pBuffer; + + int m_nBufferSize; + + int m_currentPosition; + + //std::ofstream mOfstream; + + //! more data buffers, proc-specific + //std::vector<unsigned char> ownerRBuffs[MAX_SHARING_PROCS], + //ownerSBuffs[MAX_SHARING_PROCS], ghostRBuffs[MAX_SHARING_PROCS], + // ghostSBuffs[MAX_SHARING_PROCS]; + + //! request objects, may be used if store_remote_handles is used + //MPI_Request sendReqs[2*MAX_SHARING_PROCS]; + + //! processor rank for each buffer index + //std::vector<int> buffProcs; + + //! the partition, interface sets for this comm'n instance + //CGMRange partitionSets, interfaceSets; + + //! local entities ghosted to other procs + //std::map<unsigned int, CGMRange> ghostedEnts; + + //! tags used to save sharing procs and handles + //CGMTag sharedpTag, sharedpsTag, sharedhTag, sharedhsTag, pstatusTag, + //ifaceSetsTag, partitionTag; + + //int globalPartCount; //!< Cache of global part count + + //CGMEntityHandle partitioningSet; //!< entity set containing all parts + DLIList<RefEntity*> partitioningSurfList; // ref entity list containing all parts + DLIList<RefEntity*> partitioningBodyList; // ref entity list containing all parts + + int pcommID; +}; + +#endif Added: cgm/trunk/geom/parallel/CGMProcConfig.cpp =================================================================== --- cgm/trunk/geom/parallel/CGMProcConfig.cpp (rev 0) +++ cgm/trunk/geom/parallel/CGMProcConfig.cpp 2009-08-19 20:05:46 UTC (rev 3108) @@ -0,0 +1,23 @@ +#include "CGMProcConfig.hpp" + +//! Constructor +CGMProcConfig::CGMProcConfig(MPI_Comm proc_comm) + : procComm(proc_comm), + crystalInit(false) +{ +#ifdef USE_MPI + int rank, size; + MPI_Comm_rank(procComm, &rank); + procRank = (unsigned int) rank; + MPI_Comm_size(procComm, &size); + procSize = (unsigned int) size; +#else + procRank = 0; + procSize = 1; +#endif +} + +CGMProcConfig::~CGMProcConfig() +{ +} + Added: cgm/trunk/geom/parallel/CGMProcConfig.hpp =================================================================== --- cgm/trunk/geom/parallel/CGMProcConfig.hpp (rev 0) +++ cgm/trunk/geom/parallel/CGMProcConfig.hpp 2009-08-19 20:05:46 UTC (rev 3108) @@ -0,0 +1,89 @@ +#ifndef CGM_PROC_CONFIG_HPP +#define CGM_PROC_CONFIG_HPP + +//#include "MBTypes.h" +//#include "MBRange.hpp" + +//class MBInterface; + + +#ifdef USE_MPI +/* MPICH2 will fail if SEEK_* macros are defined + * because they are also C++ enums. Undefine them + * when including mpi.h and then redefine them + * for sanity. + */ + +# ifdef SEEK_SET +# define CGM_SEEK_SET SEEK_SET +# define CGM_SEEK_CUR SEEK_CUR +# define CGM_SEEK_END SEEK_END +# undef SEEK_SET +# undef SEEK_CUR +# undef SEEK_END +# endif +#include "mpi.h" + +# ifdef CGM_SEEK_SET +# define SEEK_SET CGM_SEEK_SET +# define SEEK_CUR CGM_SEEK_CUR +# define SEEK_END CGM_SEEK_END +# undef CGM_SEEK_SET +# undef CGM_SEEK_CUR +# undef CGM_SEEK_END +# endif +//extern "C" +//{ + //#include "types.h" + //#include "errmem.h" +//#include "crystal.h" +//} +#else +typedef int MPI_Comm; +#define MPI_COMM_WORLD 0 +//typedef void* crystal_data; +#endif + +/**\brief Multi-CPU information for parallel CGM */ +class CGMProcConfig { +public: + + CGMProcConfig(MPI_Comm proc_comm = MPI_COMM_WORLD); + + ~CGMProcConfig(); + + //! Get the current processor number + unsigned proc_rank() const + { return procRank; } + + //! Get the number of processors + unsigned proc_size() const + { return procSize; } + + //! get a crystal router for this parallel job + //crystal_data *crystal_router(bool construct_if_missing = true); + + //! get/set the communicator for this proc config + const MPI_Comm proc_comm() const {return procComm;} + void proc_comm(MPI_Comm this_comm) {procComm = this_comm;} + +private: + + //! MPI communicator set for this instance + MPI_Comm procComm; + + //! rank of this processor + unsigned procRank; + + //! number of processors + unsigned procSize; + + //! whether the crystal router's been initialized or not + bool crystalInit; + + //! crystal router for this parallel job + //crystal_data crystalData; + +}; + +#endif Added: cgm/trunk/geom/parallel/FileOptions.cpp =================================================================== --- cgm/trunk/geom/parallel/FileOptions.cpp (rev 0) +++ cgm/trunk/geom/parallel/FileOptions.cpp 2009-08-19 20:05:46 UTC (rev 3108) @@ -0,0 +1,463 @@ +/**\file FileOptions.cpp + *\ copied from MOAB + *\date 2009-06-11 + */ + +#include "FileOptions.hpp" + +#include <ctype.h> +#include <stdlib.h> +#include <string.h> + +const char DEFAULT_SEPARATOR = ';'; + +static inline bool strempty( const char* s ) { return !*s; } + +FileOptions::FileOptions( const char* str ) + : mData(0) +{ + // if option string is null, just return + if (!str) + return; + + // check if alternate separator is specified + char separator[2] = { DEFAULT_SEPARATOR, '\0' }; + if (*str == DEFAULT_SEPARATOR) { + ++str; + if (strempty(str)) + return; + separator[0] = *str; + ++str; + } + + // don't bother allocating copy of input string if + // input string is empty. + if (!strempty(str)) + { + // tokenize at separator character + mData = strdup( str ); + for (char* i = strtok( mData, separator ); i; i = strtok( 0, separator )) + if (!strempty(i)) // skip empty strings + mOptions.push_back( i ); + } +} + +FileOptions::FileOptions( const FileOptions& copy ) : + mData(0), mOptions( copy.mOptions.size() ) +{ + if (!copy.mOptions.empty()) { + const char* last = copy.mOptions.back(); + const char* endptr = last + strlen(last) + 1; + size_t len = endptr - copy.mData; + mData = (char*)malloc( len ); + memcpy( mData, copy.mData, len ); + for (size_t i = 0; i < mOptions.size(); ++i) + mOptions[i] = mData + (copy.mOptions[i] - copy.mData); + } +} + +FileOptions& FileOptions::operator=( const FileOptions& copy ) +{ + free( mData ); + mData = 0; + mOptions.resize( copy.mOptions.size() ); + + if (!copy.mOptions.empty()) { + const char* last = copy.mOptions.back(); + const char* endptr = last + strlen(last) + 1; + size_t len = endptr - copy.mData; + mData = (char*)malloc( len ); + memcpy( mData, copy.mData, len ); + for (size_t i = 0; i < mOptions.size(); ++i) + mOptions[i] = mData + (copy.mOptions[i] - copy.mData); + } + + return *this; +} + +FileOptions::~FileOptions() +{ + free( mData ); +} + +FOErrorCode FileOptions::get_null_option( const char* name ) const +{ + const char* s; + FOErrorCode rval = get_option( name, s ); + if (FO_SUCCESS != rval) + return rval; + return strempty(s) ? FO_SUCCESS : FO_TYPE_OUT_OF_RANGE; +} + +FOErrorCode FileOptions::get_int_option( const char* name, int& value ) const +{ + const char* s; + FOErrorCode rval = get_option( name, s ); + if (FO_SUCCESS != rval) + return rval; + + // empty string + if (strempty(s)) + return FO_TYPE_OUT_OF_RANGE; + + // parse value + char* endptr; + long int pval = strtol( s, &endptr, 0 ); + if (!strempty(endptr)) // syntax error + return FO_TYPE_OUT_OF_RANGE; + + // check for overflow (parsing long int, returning int) + value = pval; + if (pval != (long int)value) + return FO_TYPE_OUT_OF_RANGE; + + return FO_SUCCESS; +} + +FOErrorCode FileOptions::get_ints_option( const char* name, + std::vector<int>& values) const +{ + const char* s; + FOErrorCode rval = get_option( name, s ); + if (FO_SUCCESS != rval) + return rval; + + // empty string + if (strempty(s)) + return FO_TYPE_OUT_OF_RANGE; + + // parse values + while (!strempty(s)) { + char* endptr; + long int sval = strtol( s, &endptr, 0 ); + +#define EATSPACE(a) while ((!strncmp(a, " ", 1) || \ + !strncmp(a, ",", 1)) && !strempty(a)) a++; + //EATSPACE(endptr); + + while ((!strncmp(endptr, " ", 1) || + !strncmp(endptr, ",", 1)) && !strempty(endptr)) { + endptr++; + } + + long int eval = sval; + if (!strcmp(endptr, "-")) { + endptr++; + s = endptr; + eval = strtol(s, &endptr, 0); + EATSPACE(endptr); + } + + // check for overflow (parsing long int, returning int) + int value = sval; + if (sval != (long int)value) + return FO_TYPE_OUT_OF_RANGE; + value = eval; + if (eval != (long int)value) + return FO_TYPE_OUT_OF_RANGE; + + for (int i = sval; i <= eval; i++) + values.push_back(i); + + s = endptr; + } + + return FO_SUCCESS; +} + +FOErrorCode FileOptions::get_real_option ( const char* name, double& value ) const +{ + const char* s; + FOErrorCode rval = get_option( name, s ); + if (FO_SUCCESS != rval) + return rval; + + // empty string + if (strempty(s)) + return FO_TYPE_OUT_OF_RANGE; + + // parse value + char* endptr; + value = strtod( s, &endptr ); + if (!strempty(endptr)) // syntax error + return FO_TYPE_OUT_OF_RANGE; + + return FO_SUCCESS; +} + +FOErrorCode FileOptions::get_str_option( const char* name, std::string& value ) const +{ + const char* s; + FOErrorCode rval = get_option( name, s ); + if (FO_SUCCESS != rval) + return rval; + if (strempty(s)) + return FO_TYPE_OUT_OF_RANGE; + value = s; + return FO_SUCCESS; +} + +FOErrorCode FileOptions::get_option( const char* name, std::string& value ) const +{ + const char* s; + FOErrorCode rval = get_option( name, s ); + if (FO_SUCCESS != rval) + return rval; + + value = s; + return FO_SUCCESS; +} + +FOErrorCode FileOptions::get_option( const char* name, const char*& value ) const +{ + std::vector<const char*>::const_iterator i; + for (i = mOptions.begin(); i != mOptions.end(); ++i) { + const char* opt = *i; + if (compare( name, opt )) { + value = opt + strlen(name); + // if compare returned true, next char after option + // name must be either the null char or an equals symbol. + if (*value == '=') + ++value; + + return FO_SUCCESS; + } + } + + return FO_ENTITY_NOT_FOUND; +} + +FOErrorCode FileOptions::match_option( const char* name, + const char* value ) const +{ + int idx; + const char* array[] = { value, NULL }; + return match_option( name, array, idx ); +} + +FOErrorCode FileOptions::match_option( const char* name, + const char* const* values, + int& index ) const +{ + const char* optval; + FOErrorCode rval = get_option( name, optval ); + if (FO_SUCCESS != rval) + return rval; + + for (index = 0; values[index]; ++index) + if (compare( optval, values[index] )) + return FO_SUCCESS; + + index = -1; + return FO_FAILURE; +} + + +bool FileOptions::compare( const char* name, const char* option ) +{ + while (!strempty(name) && toupper(*name) == toupper(*option)) { + ++name; + ++option; + } + // match if name matched option for length of name, + // and option either matched entirely or matches up to + // and equals sign. + return strempty(name) && (strempty(option) || *option == '='); +} + +void FileOptions::get_options( std::vector<std::string>& list ) const +{ + list.clear(); + list.resize( mOptions.size() ); + std::copy( mOptions.begin(), mOptions.end(), list.begin() ); +} + +#ifdef TEST + +#include <iostream> + +#define CHECK(A) \ + if (FO_SUCCESS != (A)) { \ + std::cerr << "Failure at line " << __LINE__ << ": error code " << (A) << std::endl; \ + return 1; \ + } + +#define EQUAL(A,B) \ + if (A != B) { \ + std::cerr << "Failure at line " << __LINE__ << ": expected " << (B) << " but got " << (A) << std::endl; \ + return 2; \ + } + +int main() +{ + FileOptions tool( "INT1=1;NUL1;STR1=ABC;DBL1=1.0;dbl2=2.0;DBL3=3.0;INT2=2;nul2;NUL3;INT3=3;str2=once upon a time;str3==fubar=;;" ); + + std::string s; + int i; + double d; + FOErrorCodeyy rval; + + // test basic get_option method without deleting entry + rval = tool.get_option( "STR1", s ); + CHECK(rval); + EQUAL( s, "ABC" ); + + // test basic get_option method again, this time deleting the entry + rval = tool.get_option( "STR1", s ); + CHECK(rval); + EQUAL( s, "ABC" ); + + // test basig get_option method with a null option + rval = tool.get_option( "NUL2", s ); + CHECK( rval ); + EQUAL( s.empty(), true ); + + + // test null option + rval = tool.get_null_option( "nul1" ); + CHECK( rval ); + + // try null option method on non-null value + rval = tool.get_null_option( "INT1" ) ; + EQUAL( rval, FO_TYPE_OUT_OF_RANGE) ; + + + // test integer option + rval = tool.get_int_option( "int1", i ); + CHECK( rval ); + EQUAL( i, 1 ); + + rval = tool.get_int_option( "int2", i ); + CHECK( rval ); + EQUAL( i, 2 ); + + // test integer option on non-integer value + rval = tool.get_int_option( "dbl2", i ); + EQUAL( rval, FO_TYPE_OUT_OF_RANGE ); + + // test integer option on null value + rval = tool.get_int_option( "NUL3", i); + EQUAL( rval, FO_TYPE_OUT_OF_RANGE ); + + // test double option + rval = tool.get_real_option( "dbl1", d ); + CHECK( rval ); + EQUAL( d, 1.0 ); + + rval = tool.get_real_option( "dbl2", d ); + CHECK( rval ); + EQUAL( d, 2.0 ); + + rval = tool.get_real_option( "int3", d ); + CHECK( rval ); + EQUAL( d, 3.0 ); + + // test real option on non-real value + rval = tool.get_real_option( "str2", d ); + EQUAL( rval, FO_TYPE_OUT_OF_RANGE ); + + + // test real option on null value + rval = tool.get_real_option( "NUL3", d ); + EQUAL( rval, FO_TYPE_OUT_OF_RANGE ); + + // test get a simple string option + rval = tool.get_str_option( "DBL3", s ); + CHECK( rval ); + EQUAL( s, "3.0" ); + + // test get a string with spaces + rval = tool.get_str_option("STR2", s ); + CHECK( rval ); + EQUAL( s, "once upon a time" ); + + // try to get a string value for a null option + rval = tool.get_str_option( "nul3", s ); + EQUAL( rval, FO_TYPE_OUT_OF_RANGE ); + + // test options using generic get_option method + + rval = tool.get_option( "NUL3", s ); + CHECK( rval ); + EQUAL( s.empty(), true ); + + rval = tool.get_option( "STR3", s ); + CHECK( rval ); + EQUAL( s, "=fubar=" ); + + // test size of options string + unsigned l = tool.size(); + EQUAL( l, 12u ); + + + // test alternate separator + + FileOptions tool2( ";+OPT1=ABC+OPT2=" ); + l = tool2.size(); + EQUAL( l, 2 ); + + rval = tool2.get_option( "opt1", s ); + CHECK( rval ); + EQUAL( s, "ABC" ); + + rval = tool2.get_option( "opt2", s ); + CHECK( rval ); + bool e = s.empty(); + EQUAL( e, true ); + + l = tool2.size(); + EQUAL( l, 2 ); + + + // test empty options string + + FileOptions tool3( ";;;;" ); + e = tool3.empty(); + EQUAL( e, true ); + l = tool3.size(); + EQUAL( l, 0 ); + + FileOptions tool4(NULL); + e = tool4.empty(); + EQUAL( e, true ); + l = tool4.size(); + EQUAL( l, 0 ); + + FileOptions tool5(";+"); + e = tool5.empty(); + EQUAL( e, true ); + l = tool5.size(); + EQUAL( l, 0 ); + + // test copy constructor + + FileOptions tool6( tool2 ); + + rval = tool6.get_option( "opt1", s ); + CHECK( rval ); + EQUAL( s, "ABC" ); + + rval = tool6.get_option( "opt2", s ); + CHECK( rval ); + e = s.empty(); + EQUAL( e, true ); + + l = tool6.size(); + EQUAL( l, 2 ); + + FileOptions tool7( tool5 ); + e = tool7.empty(); + EQUAL( e, true ); + l = tool7.size(); + EQUAL( l, 0 ); + + // test assignment operator + + FileOptions tool8( tool2 ); + tool8 = tool; + EQUAL( tool8.size(), tool.size() ); + + return 0; +} + +#endif Added: cgm/trunk/geom/parallel/FileOptions.hpp =================================================================== --- cgm/trunk/geom/parallel/FileOptions.hpp (rev 0) +++ cgm/trunk/geom/parallel/FileOptions.hpp 2009-08-19 20:05:46 UTC (rev 3108) @@ -0,0 +1,165 @@ +/**\file FileOptions.hpp + *\copied from MOAB + *\date 2009-06-11 + */ + +#ifndef FILE_OPTIONS_HPP +#define FILE_OPTIONS_HPP + +#include <string> +#include <vector> +#include "CubitDefines.h" + +/* file option type */ +enum FOErrorCode +{ + FO_SUCCESS = 0, + FO_TYPE_OUT_OF_RANGE, + FO_ENTITY_NOT_FOUND, + FO_FAILURE +}; + +/**\brief Parse options string passed to file IO routines + * + * This is a utility class used by file-IO-related code to + * parse the options string passed to ParallelMeshTool::load_file + */ +class FileOptions { +public: + + /*\param options_string The concatenation of a list of + * options, separated either by the default separator + * (semicolon) with a custom separator specified at + * the beginning of the string (semicolon followed by + * destired separator character.) + */ + FileOptions( const char* option_string ); + + FileOptions( const FileOptions& copy ); + FileOptions& operator=( const FileOptions& copy ); + + ~FileOptions(); + + /**\brief Check for option with no value + * + * Check for an option w/out a value. + *\param name The option name + *\return - CUBIT_SUCCESS if option is found + * - CUBIT_TYPE_OUT_OF_RANGE if options is found, but has value + * - CUBIT_ENTITY_NOT_FOUND if option is not found. + */ + FOErrorCode get_null_option( const char* name ) const; + + /**\brief Check for option with an integer value. + * + * Check for an option with an integer value + *\param name The option name + *\param value Output. The value. + *\return - CUBIT_SUCCESS if option is found + * - CUBIT_TYPE_OUT_OF_RANGE if options is found, but does not have an integer value + * - CUBIT_ENTITY_NOT_FOUND if option is not found. + */ + FOErrorCode get_int_option( const char* name, int& value ) const; + + /**\brief Check for option with a double value. + * + * Check for an option with a double value + *\param name The option name + *\param value Output. The value. + *\return - CUBIT_SUCCESS if option is found + * - CUBIT_TYPE_OUT_OF_RANGE if options is found, but does not have a double value + * - CUBIT_ENTITY_NOT_FOUND if option is not found. + */ + FOErrorCode get_real_option( const char* name, double& value ) const; + + /**\brief Check for option with any value. + * + * Check for an option with any value. + *\param name The option name + *\param value Output. The value. + *\return - CUBIT_SUCCESS if option is found + * - CUBIT_TYPE_OUT_OF_RANGE if options is found, but does not have a value + * - CUBIT_ENTITY_NOT_FOUND if option is not found. + */ + FOErrorCode get_str_option( const char* name, std::string& value ) const; + + /**\brief Check for option + * + * Check for an option + *\param name The option name + *\param value The option value, or an empty string if no value. + *\return CUBIT_SUCCESS or CUBIT_ENTITY_NOT_FOUND + */ + FOErrorCode get_option( const char* name, std::string& value ) const; + + /**\brief Check the string value of an option + * + * Check which of a list of possible values a string option contains. + *\param name The option name + *\param values A NULL-terminated array of C-style strings enumerating + * the possible option values. + *\param index Output: The index into <code>values</code> for the + * option value. + *\return CUBIT_SUCCESS if matched name and value. + * CUBIT_ENTITY_NOT_FOUND if the option was not specified + * CUBIT_FAILURE if the option value is not in the input <code>values</code> array. + */ + FOErrorCode match_option( const char* name, const char* const* values, int& index ) const; + + /**\brief Check if an option matches a string value + * + * Check if the value for an option is the passed string. + *\param name The option name + *\param value The expected value. + *\return CUBIT_SUCCESS if matched name and value. + * CUBIT_ENTITY_NOT_FOUND if the option was not specified + * CUBIT_FAILURE if the option value doesn't match the passed string/ + */ + FOErrorCode match_option( const char* name, const char* value ) const; + + /**\brief Check for option for which the value is a list of ints + * + * Check for an option which is an int list. The value is expected to + * be a comma-separated list of int ranges, where an int range can be + * either a single integer value or a range of integer values separated + * by a dash ('-'). + * + *\param name The option name + *\param values Output. The list of integer values. + *\return - CUBIT_SUCCESS if option is found + * - CUBIT_TYPE_OUT_OF_RANGE if options is found, but does not contain an ID list + * - CUBIT_ENTITY_NOT_FOUND if option is not found. + */ + FOErrorCode get_ints_option( const char* name, std::vector<int>& values) const; + + /** number of options */ + inline unsigned size() const + { return mOptions.size(); } + + /** true if no options */ + inline bool empty() const + { return mOptions.empty(); } + + /** Get list of options */ + void get_options( std::vector<std::string>& list ) const; + +private: + + /**\brief Check for option + * + * Check for an option + *\param name The option name + *\param value The option value, or an empty string if no value. + *\return CUBIT_SUCCESS or CUBIT_ENTITY_NOT_FOUND + */ + FOErrorCode get_option( const char* name, const char*& value) const; + + char* mData; + std::vector<const char*> mOptions; + + /** Case-insensitive compare of name with option value. */ + static bool compare( const char* name, const char* option ); +}; + +#endif + Modified: cgm/trunk/geom/parallel/Makefile.am =================================================================== --- cgm/trunk/geom/parallel/Makefile.am 2009-08-19 18:39:01 UTC (rev 3107) +++ cgm/trunk/geom/parallel/Makefile.am 2009-08-19 20:05:46 UTC (rev 3108) @@ -1,17 +1,28 @@ # Don't require GNU-standard files (Changelog, README, etc.) AUTOMAKE_OPTIONS = foreign + # Override default defines with the ones we want from the configure script -# Override default defines with the ones we want from the configure script -DEFS = $(TEMPLATE_DEFS_INCLUDED) \ - $(LITTLE_ENDIAN) $(ACIS_STEP_TRANSLATOR) $(ACIS_IGES_TRANSLATOR) \ - -DCUBIT_ACIS_VERSION=$(ACIS_VERSION) -DACIS_VERSION=$(ACIS_VERSION) \ - -D$(ACIS_PLATFORM) +if build_OCC +# DEFS = $(TEMPLATE_DEFS_INCLUDED) $(HAVE_OCC_DEF) + DEFS += $(HAVE_OCC_DEF) +else + DEFS = $(TEMPLATE_DEFS_INCLUDED) \ + $(LITTLE_ENDIAN) $(ACIS_STEP_TRANSLATOR) $(ACIS_IGES_TRANSLATOR) \ + -DCUBIT_ACIS_VERSION=$(ACIS_VERSION) -DACIS_VERSION=$(ACIS_VERSION) \ + -D$(ACIS_PLATFORM) +# DEFS += $(ACIS_STEP_TRANSLATOR) $(ACIS_IGES_TRANSLATOR) \ + -DCUBIT_ACIS_VERSION=$(ACIS_VERSION) -DACIS_VERSION=$(ACIS_VERSION) \ + -D$(ACIS_PLATFORM) +endif +# because "ISO C++ does not support ‘long long" +CXXFLAGS += -Wno-long-long + INCLUDES = -I$(top_srcdir)/util \ -I$(top_srcdir)/geom \ -I$(top_srcdir)/geom/ACIS \ - -I$(ACIS_DIR)/include \ + -I$(ACIS_DIR)/include \ $(MPI_INCLUDE) # The name of the library to build @@ -25,21 +36,17 @@ # The non-template sources libcubit_parallel_la_SOURCES = \ - AcisMemFile.cpp \ - CABodies.cpp \ - CGMMemFile.cpp \ - ParallelGeomTool.cpp \ - ProcData.cpp \ - TDParallel.cpp + CGMProcConfig.cpp \ + CGMParallelComm.cpp \ + FileOptions.cpp \ + ParallelGeomTool.cpp # The non-template headers # If any of these do not need to be installed, move them # to the _SOURCES list above. libcubit_parallel_la_include_HEADERS = \ - AcisMemFile.hpp \ - CABodies.cpp \ - CGMMemFile.hpp \ - ParallelGeomTool.hpp \ - ProcData.hpp \ - TDParallel.hpp + CGMProcConfig.hpp \ + CGMParallelComm.hpp \ + FileOptions.hpp \ + ParallelGeomTool.hpp Modified: cgm/trunk/geom/parallel/ParallelGeomTool.cpp =================================================================== --- cgm/trunk/geom/parallel/ParallelGeomTool.cpp 2009-08-19 18:39:01 UTC (rev 3107) +++ cgm/trunk/geom/parallel/ParallelGeomTool.cpp 2009-08-19 20:05:46 UTC (rev 3108) @@ -1,51 +1,539 @@ +#include <cstdio> + +#include "CubitString.hpp" +#include "CubitMessage.hpp" +#include "DLList.hpp" +#include "RefEntity.hpp" +#include "CubitEntity.hpp" +#include "CastTo.hpp" +#include "CubitUtil.hpp" + +#include "TopologyBridge.hpp" +#include "GeometryQueryTool.hpp" #include "ParallelGeomTool.hpp" -#include "AcisMemFile.hpp" -#include "AcisQueryEngine.hpp" -#include "TSTTG_CGM.h" -#include "ProcData.hpp" +#include "CGMParallelConventions.h" +#include "CATag.hpp" +#include "CGMParallelComm.hpp" -ParallelGeomTool *ParallelGeomTool::instance_ = NULL; +const bool debug = true; -int ParallelGeomTool::load_parallel(TSTTG_Instance geom, - const char *name, - int par_load_option) +enum CGMParallelActions {PA_READ=0, PA_BROADCAST, PA_DELETE_NONLOCAL, + PA_SCATTER, + PA_CHECK_GIDS_SERIAL, PA_GET_ENTS, + PA_RESOLVE_SHARED_ENTS, + PA_EXCHANGE_GHOSTS}; + +enum CGMPartitionActions {PT_GEOM_DIM=0, PT_PAR_PART}; + +const char *CGMParallelActionsNames[] = { + "PARALLEL READ", + "PARALLEL BROADCAST", + "PARALLEL DELETE NONLOCAL", + "PARALLEL SCATTER", + "PARALLEL CHECK_GIDS_SERIAL", + "PARALLEL GET_FILESET_ENTS", + "PARALLEL RESOLVE_SHARED_ENTS", + "PARALLEL EXCHANGE_GHOSTS" +}; + +const char* ParallelGeomTool::CGMparallelOptsNames[] = { "NONE", "READ", "READ_DELETE", "BCAST", + "BCAST_DELETE", "SCATTER", "SCATTER_DELETE", + "READ_PARALLEL", "FORMAT", "", 0 }; + +const char* ParallelGeomTool::CGMpartitionOptsNames[] = { "NONE", "GEOM_DIMENSION", + "PARARELL_PARTITION", "", 0 }; + +//ParallelGeomTool *ParallelGeomTool::instance_ = NULL; + +ParallelGeomTool::ParallelGeomTool(CGMTagManager* impl, CGMParallelComm *pc) + : cgmImpl(impl), myPcomm(pc) { - // declare an acismemfile object - AcisMemFile amf(AcisQueryEngine::instance()); + if (!myPcomm) { + myPcomm = CGMParallelComm::get_pcomm(impl, 0); + if (NULL == myPcomm) myPcomm = new CGMParallelComm(cgmImpl); + } + //gqt = GeometryQueryTool::instfance(); +} - DLIList<RefEntity*> ref_ents, ref_ents_master; +CubitStatus ParallelGeomTool::load_file(const char *file_name, + const char *options, + const char* set_tag_name, + const int* set_tag_values, + int num_set_tag_values) +{ + FileOptions opts(options); - // if I'm the master, load the file and get the entities - int result; - if (ProcData::instance()->is_master()) { - result = TSTTG_load(geom, name, NULL, 0); - if (TSTTB_SUCCESS != result) return result; + // Get parallel settings + int parallel_mode; + FOErrorCode result = opts.match_option("PARALLEL", CGMparallelOptsNames, + parallel_mode); + if (FO_FAILURE == result) { + PRINT_ERROR( "Unexpected value for 'PARALLEL' option\n" ); + return CUBIT_FAILURE; + } + else if (FO_ENTITY_NOT_FOUND == result) { + parallel_mode = 0; + } - // get all the volumes - TSTTG_EntityHandle *ents = NULL; - int ents_alloc = 0, ents_size; - result = TSTTG_getEntities(geom, 0, TSTTG_REGION, - &ents, &ents_alloc, &ents_size); - if (TSTTB_SUCCESS != result) return result; + bool distrib = false; + bool surf_partition = false; + bool body_partition = false; + std::string partition_tag_name; + std::vector<int> partition_tag_vals; - // make this the storage for the ent list - ref_ents.copy_from((RefEntity**)ents, ents_size); + // Get partition tag value(s), if any, and whether they're to be + result = opts.get_ints_option("PARTITION_VAL", partition_tag_vals); + + // Get partition setting + result = opts.get_option("PARTITION", partition_tag_name); + + if (FO_ENTITY_NOT_FOUND == result || partition_tag_name.empty()) { + partition_tag_name = PARALLEL_PARTITION_TAG_NAME; + distrib = true; } + else { + if (partition_tag_name == "GEOM_DIMENSION") { + int geom_dim = 0; + for (std::vector<int>::iterator pit = partition_tag_vals.begin(); + pit != partition_tag_vals.end(); pit++) { + geom_dim = *pit; + if (geom_dim == 2) surf_partition = true; // body & surface distribution + else if (geom_dim == 3) body_partition = true; // body only distribution + } + if (!surf_partition && !body_partition) { + PRINT_ERROR("Geometry dimension %d is not supported.\n", geom_dim); + return CUBIT_FAILURE; + } + } + else if (partition_tag_name == "PARALLEL_PARTITION") { + } - // now communicate the entities - if (BCAST == par_load_option) { - // broadcast - result = amf.bcast_entity_list(ref_ents); + // distributed or assigned + result = opts.get_null_option("PARTITION_DISTRIBUTE"); + if (FO_SUCCESS == result) { + distrib = true; + body_partition = true; + } } - else if (BCAST_AND_DELETE == par_load_option) { - // bcast and delete - result = amf.bcast_and_delete_entity_list(ref_ents, ref_ents_master); + + // get MPI IO processor rank + int reader_rank; + result = opts.get_int_option("MPI_IO_RANK", reader_rank); + if (FO_ENTITY_NOT_FOUND == result) + reader_rank = 0; + else if (FO_SUCCESS != result) { + PRINT_ERROR( "Unexpected value for 'MPI_IO_RANK' option\n" ); + return CUBIT_FAILURE; } - else if (SCATTER == par_load_option) { - // scatter - result = amf.scatter_entity_list(ref_ents); + + // now that we've parsed all the parallel options, make an instruction + // queue + std::vector<int> pa_vec; + bool is_reader = (reader_rank == (int) myPcomm->proc_config().proc_rank()); + + switch (parallel_mode) { + + case POPT_READ: + pa_vec.push_back(PA_READ); + //pa_vec.push_back(PA_CHECK_GIDS_SERIAL); + pa_vec.push_back(PA_GET_ENTS); + break; + + case POPT_DEFAULT: + case POPT_READ_DELETE: + pa_vec.push_back(PA_READ); + //pa_vec.push_back(PA_CHECK_GIDS_SERIAL); + pa_vec.push_back(PA_GET_ENTS); + pa_vec.push_back(PA_DELETE_NONLOCAL); + break; + + case POPT_BCAST: + if (is_reader) { + pa_vec.push_back(PA_READ); + //pa_vec.push_back(PA_CHECK_GIDS_SERIAL); + pa_vec.push_back(PA_GET_ENTS); + } + pa_vec.push_back(PA_BROADCAST); + if (!is_reader) pa_vec.push_back(PA_GET_ENTS); + break; + + case POPT_BCAST_DELETE: + if (is_reader) { + pa_vec.push_back(PA_READ); + //pa_vec.push_back(PA_CHECK_GIDS_SERIAL); + pa_vec.push_back(PA_GET_ENTS); + } + pa_vec.push_back(PA_BROADCAST); + //if (!is_reader) pa_vec.push_back(PA_GET_FILESET_ENTS); + pa_vec.push_back(PA_DELETE_NONLOCAL); + break; + + case PORT_SCATTER: + if (is_reader) { + pa_vec.push_back(PA_READ); + //pa_vec.push_back(PA_CHECK_GIDS_SERIAL); + pa_vec.push_back(PA_GET_ENTS); + } + pa_vec.push_back(PA_SCATTER); + if (!is_reader) pa_vec.push_back(PA_GET_ENTS); + break; + + case PORT_SCATTER_DELETE: + if (is_reader) { + pa_vec.push_back(PA_READ); + //pa_vec.push_back(PA_CHECK_GIDS_SERIAL); + pa_vec.push_back(PA_GET_ENTS); + } + pa_vec.push_back(PA_SCATTER); + if (is_reader) pa_vec.push_back(PA_DELETE_NONLOCAL); + else pa_vec.push_back(PA_GET_ENTS); + break; + + case POPT_FORMAT: + PRINT_ERROR( "Access to format-specific parallel read not implemented.\n"); + return CUBIT_FAILURE; + + case POPT_READ_PARALLEL: + PRINT_ERROR( "Partitioning for PARALLEL=READ_PARALLEL not supported yet.\n"); + return CUBIT_FAILURE; + + default: + return CUBIT_FAILURE; } + + return load_file(file_name, parallel_mode, + partition_tag_name, + partition_tag_vals, distrib, pa_vec, opts, + set_tag_name, set_tag_values, + num_set_tag_values, + reader_rank, surf_partition, body_partition + ); +} + +CubitStatus ParallelGeomTool::load_file(const char *file_name, + int parallel_mode, + std::string &partition_tag_name, + std::vector<int> &partition_tag_vals, + bool distrib, + std::vector<int> &pa_vec, + const FileOptions &opts, + const char* set_tag_name, + const int* set_tag_values, + const int num_set_tag_values, + const int reader_rank, + const bool surf_partition, + const bool body_partition + ) +{ + // check file type + CubitString file_type; + //if (strstr(file_name, ".sab")) file_type = "ACIS_SAB"; + //else if (strstr(file_name, ".sat")) file_type = "ACIS_SAT"; + if (strstr(file_name, ".stp")) file_type = "STEP"; + else if (strstr(file_name, ".igs")) file_type = "IGES"; + else if (strstr(file_name, ".occ") || strstr(file_name, ".brep")) file_type = "OCC"; + else { + PRINT_ERROR("File type not known for file %s; skipping.\n", file_name); + return CUBIT_FAILURE; + } - return result; + // do the work by options + bool i_read = false; + std::vector<int>::iterator vit; + int i; + DLIList<RefEntity*> surf_entity_list, body_entity_list; + for (i = 1, vit = pa_vec.begin(); vit != pa_vec.end(); vit++, i++) { + CubitStatus tmp_result = CUBIT_SUCCESS; + switch (*vit) { +//================== + case PA_READ: + i_read = true; + double tStart, tEnd; + + if (debug) { + std::cout << "Reading file " << file_name << std::endl; + tStart = MPI_Wtime(); + } + tmp_result = GeometryQueryTool::instance()->import_solid_model(file_name, file_type.c_str()); + + if (CUBIT_SUCCESS != tmp_result) { + PRINT_ERROR("Reading file %s failed.\n", file_name); + return CUBIT_FAILURE; + } + else if (debug) { + tEnd = MPI_Wtime(); + PRINT_INFO("Read time in proc %d is %f.\n", myPcomm->proc_config().proc_size(), + tEnd - tStart); + PRINT_INFO("Read done.\n"); + } + + break; + +//================== + case PA_GET_ENTS: + if (debug) std::cout << "Getting entities." << std::endl; + + // get entities + if (body_partition) { + tmp_result = GeometryQueryTool::instance()->ref_entity_list("body", body_entity_list, CUBIT_FALSE); + + if (CUBIT_SUCCESS != tmp_result) { + PRINT_ERROR("Getting body entities failed.\n"); + return CUBIT_FAILURE; + } + } + if (surf_partition) { + tmp_result = GeometryQueryTool::instance()->ref_entity_list("surface", surf_entity_list, CUBIT_FALSE); + + if (CUBIT_SUCCESS != tmp_result) { + PRINT_ERROR("Getting surf entities failed.\n"); + return CUBIT_FAILURE; + } + } + if (debug) PRINT_INFO("Getting entities done.\n"); + + break; + +//================== + case PA_DELETE_NONLOCAL: + if (debug) { + PRINT_INFO("Deleting nonlocal entities.\n"); + tStart = MPI_Wtime(); + } + + tmp_result = delete_nonlocal_entities(partition_tag_name, + partition_tag_vals, + surf_entity_list, + body_entity_list, + distrib); + + if (CUBIT_SUCCESS != tmp_result) { + PRINT_ERROR("Delete failed.\n"); + return CUBIT_FAILURE; + } + else if (debug) { + tEnd = MPI_Wtime(); + PRINT_INFO("Delete done.\n"); + PRINT_INFO("Delete time in proc %d is %f.\n", myPcomm->proc_config().proc_size(), + tEnd - tStart); + } + break; + +//================== + case PA_BROADCAST: + // do the actual broadcast; if single-processor, ignore error + if (myPcomm->proc_config().proc_size() > 1) { + if (body_partition) { + if (debug) { + PRINT_INFO("Broadcasting body entities.\n"); + tStart = MPI_Wtime(); + } + + tmp_result = myPcomm->broadcast_entities(reader_rank, body_entity_list); + + if (CUBIT_SUCCESS != tmp_result) { + PRINT_ERROR("Broadcasting body entities failed.\n"); + return CUBIT_FAILURE; + } + else if (debug) { + tEnd = MPI_Wtime(); + PRINT_INFO("Bcast bodies done.\n"); + PRINT_INFO("Broadcast bodies time in proc %d is %f.\n", myPcomm->proc_config().proc_size(), + tEnd - tStart); + } + } + if (surf_partition) { + if (debug) { + PRINT_INFO("Broadcasting surface entities.\n"); + tStart = MPI_Wtime(); + } + tmp_result = myPcomm->broadcast_entities(reader_rank, surf_entity_list); + + if (CUBIT_SUCCESS != tmp_result) { + PRINT_ERROR("Broadcasting surface entities failed.\n"); + return CUBIT_FAILURE; + } + else if (debug) { + tEnd = MPI_Wtime(); + PRINT_INFO("Bcast surface done.\n"); + PRINT_INFO("Broadcast surfaces time in proc %d is %f.\n", myPcomm->proc_config().proc_size(), + tEnd - tStart); + } + } + } + + break; + +//================== + case PA_SCATTER: + // do the actual scatter + if (myPcomm->proc_config().proc_size() > 1) { + if (body_partition) { + if (debug) { + PRINT_INFO("Scattering body entities.\n"); + tStart = MPI_Wtime(); + } + tmp_result = myPcomm->scatter_entities(reader_rank, body_entity_list); + + if (CUBIT_SUCCESS != tmp_result) { + PRINT_ERROR("Scattering body entities failed.\n"); + return CUBIT_FAILURE; + } + else if (debug) { + tEnd = MPI_Wtime(); + PRINT_INFO("Scatter bodies done.\n"); + PRINT_INFO("Scatter bodies time in proc %d is %f.\n", myPcomm->proc_config().proc_size(), + tEnd - tStart); + } + } + if (surf_partition) { + if (debug) { + PRINT_INFO("Scattering surface entities.\n"); + tStart = MPI_Wtime(); + } + tmp_result = myPcomm->scatter_entities(reader_rank, surf_entity_list); + + if (CUBIT_SUCCESS != tmp_result) { + PRINT_ERROR("Scattering surf entities failed.\n"); + return CUBIT_FAILURE; + } + else if (debug) { + tEnd = MPI_Wtime(); + PRINT_INFO("Scatter surfaces done;\n"); + PRINT_INFO("Scatter surfaces time in proc %d is %f.\n", myPcomm->proc_config().proc_size(), + tEnd - tStart); + } + } + } + if (debug) PRINT_INFO("Scatter done.\n"); + + break; + +//================== + default: + return CUBIT_FAILURE; + } + } + + return CUBIT_SUCCESS; } +CubitStatus ParallelGeomTool::delete_nonlocal_entities(std::string &ptag_name, + std::vector<int> &ptag_vals, + DLIList<RefEntity*> surf_entity_list, + DLIList<RefEntity*> body_entity_list, + const bool distribute) +{ + unsigned int i; + CubitStatus result; + int proc_sz = myPcomm->proc_config().proc_size(); + int proc_rk = myPcomm->proc_config().proc_rank(); + + if (distribute) { // Round-Robin + // for now, require that number of partition sets be greater + // than number of procs + if (body_entity_list.size() < proc_sz && + surf_entity_list.size() < proc_sz) { + result = CUBIT_FAILURE; + PRINT_ERROR("Number of procs greater than number of partitions."); + return CUBIT_FAILURE; + } + + // delete unneeded surf entities + unsigned int tot_entity = surf_entity_list.size(); + unsigned int n_entity = tot_entity / proc_sz; + unsigned int n_entity_leftover = tot_entity % proc_sz; + unsigned int begin_entity = 0; + + if (proc_rk < (int) n_entity_leftover) { + n_entity++; + begin_entity = n_entity * proc_rk; + } + else + begin_entity = proc_rk * n_entity + n_entity_leftover; + + DLIList<RefEntity*> tmp_entity_list, delete_surf_list, delete_body_list; + unsigned int end_entity = begin_entity + n_entity; + for (i = 0; i < tot_entity; i++) { + if (i >= begin_entity && i < end_entity) tmp_entity_list.append(surf_entity_list[i]); + else { + delete_surf_list.append(surf_entity_list[i]); + //GeometryQueryTool::instance()->delete_RefEntity(surf_entity_list[i]); + } + } + + // change partition surf ref entity list + myPcomm->partition_surf_list().clean_out(); + myPcomm->partition_surf_list() += tmp_entity_list; + + // delete unneeded body entities + tot_entity = body_entity_list.size(); + n_entity = tot_entity / proc_sz; + n_entity_leftover = tot_entity % proc_sz; + + if (proc_rk < (int) n_entity_leftover) { + n_entity++; + begin_entity = n_entity * proc_rk; + } + else + begin_entity = proc_rk * n_entity + n_entity_leftover; + + end_entity = begin_entity + n_entity; + for (i = 0; i < tot_entity; i++) { + if (i >= begin_entity && i < end_entity) tmp_entity_list.append(body_entity_list[i]); + else { + delete_body_list.append(body_entity_list[i]); + //GeometryQueryTool::instance()->delete_RefEntity(body_entity_list[i]); + } + } + + char pre_surf[100], pre_body[100]; + DLIList<CubitEntity*> tmp_surf_list, tmp_body_list; + if (debug) { + CAST_LIST_TO_PARENT(delete_surf_list, tmp_surf_list); + sprintf( pre_surf, "Deleted %d Surfaces: ", tmp_surf_list.size() ); + CAST_LIST_TO_PARENT(delete_body_list, tmp_body_list); + sprintf( pre_body, "Deleted %d Bodies: ", tmp_body_list.size() ); + CubitUtil::list_entity_ids( pre_surf, tmp_surf_list ); + } + + unsigned int nDelete = delete_surf_list.size(); + for (i = 0; i < nDelete; i++) { + GeometryQueryTool::instance()->delete_RefEntity(surf_entity_list[i]); + } + + if (debug) CubitUtil::list_entity_ids( pre_body, tmp_body_list ); + + nDelete = delete_body_list.size(); + for (i = 0; i < nDelete; i++) { + GeometryQueryTool::instance()->delete_RefEntity(body_entity_list[i]); + } + + // change partition surf ref entity list + myPcomm->partition_body_list().clean_out(); + myPcomm->partition_body_list() += tmp_entity_list; + } + else { + myPcomm->partition_surf_list().clean_out(); + myPcomm->partition_surf_list() += surf_entity_list; + myPcomm->partition_body_list().clean_out(); + myPcomm->partition_body_list() += body_entity_list; + } + + if (debug) { + /* + surf_entity_list.clean_out(); + GeometryQueryTool::instance()->ref_entity_list("surface", surf_entity_list, CUBIT_FALSE); + body_entity_list.clean_out(); + GeometryQueryTool::instance()->ref_entity_list("body", body_entity_list, CUBIT_FALSE); + std::cerr << "My partition surf/body ref entity list size1: " + << surf_entity_list.size() << " " + << body_entity_list.size() << std::endl;*/ + + std::cerr << "My partition surf/body ref entity list size: " + << myPcomm->partition_surf_list().size() << " " + << myPcomm->partition_body_list().size() << std::endl; + } + + return CUBIT_SUCCESS; +} Modified: cgm/trunk/geom/parallel/ParallelGeomTool.hpp =================================================================== --- cgm/trunk/geom/parallel/ParallelGeomTool.hpp 2009-08-19 18:39:01 UTC (rev 3107) +++ cgm/trunk/geom/parallel/ParallelGeomTool.hpp 2009-08-19 20:05:46 UTC (rev 3108) @@ -1,32 +1,88 @@ #ifndef PARALLELGEOMTOOL_HPP #define PARALLELGEOMTOOL_HPP -#include "TSTTG_CGM.h" +#include <vector> +#include "CubitDefines.h" +#include "CGMParallelComm.hpp" +//#include "ProcData.hpp" +#include "FileOptions.hpp" +//#include "CATag.hpp" +//#include "CGMParallelComm.hpp" +//class CGMTagManager; +//class CGMParallelComm; + class ParallelGeomTool { public: - static ParallelGeomTool *instance(); + ParallelGeomTool(CGMTagManager* impl = NULL, CGMParallelComm *pc = NULL); + + //static ParallelGeomTool *instance(); + enum ParallelLoadOption {BCAST, BCAST_AND_DELETE, SCATTER}; - // load geometry to parallel processors, using ParallelLoadOption - // to determine how - int load_parallel(TSTTG_Instance geom, - const char *name, - int par_load_option); + // load a file + CubitStatus load_file(const char *file_names, const char *options, + const char* set_tag_name = 0, + const int* set_tag_values = 0, + int num_set_tag_values = 0); + CubitStatus load_file(const char *file_name, + int parallel_mode, + std::string &partition_tag_name, + std::vector<int> &partition_tag_vals, + bool distrib, + std::vector<int> &pa_vec, + const FileOptions &opts, + const char* set_tag_name, + const int* set_tag_values, + const int num_set_tag_values, + const int reader_rank, + const bool surf_partition, + const bool body_partition); + + static const char *CGMparallelOptsNames[]; + + static const char *CGMpartitionOptsNames[]; + + enum CGMParallelOpts {POPT_NONE=0, POPT_READ, POPT_READ_DELETE, POPT_BCAST, + POPT_BCAST_DELETE, PORT_SCATTER, + PORT_SCATTER_DELETE, POPT_READ_PARALLEL, + POPT_FORMAT, POPT_DEFAULT}; + private: - ParallelGeomTool() {} - static ParallelGeomTool *instance_; + // surf ref entity list to be partitioned + DLIList<RefEntity*> msurf_entity_list; + + // body ref entity list to be partitioned + DLIList<RefEntity*> mbody_entity_list; + + CubitStatus delete_nonlocal_entities(std::string &ptag_name, + std::vector<int> &ptag_vals, + DLIList<RefEntity*> surf_entity_list, + DLIList<RefEntity*> body_entity_list, + bool distribute); + + //CubitStatus delete_nonlocal_entities(MBEntityHandle file_set); + + + //static ParallelGeomTool *instance_; + + CGMTagManager *cgmImpl; + + // each reader can keep track of its own pcomm + CGMParallelComm *myPcomm; + + //GeometryQueryTool *gqt; }; - +/* inline ParallelGeomTool *ParallelGeomTool::instance() { if (!instance_) instance_ = new ParallelGeomTool(); return instance_; -} + }*/ #endif Modified: cgm/trunk/geom/virtual/VirtualQueryEngine.cpp =================================================================== --- cgm/trunk/geom/virtual/VirtualQueryEngine.cpp 2009-08-19 18:39:01 UTC (rev 3107) +++ cgm/trunk/geom/virtual/VirtualQueryEngine.cpp 2009-08-19 20:05:46 UTC (rev 3108) @@ -1526,6 +1526,14 @@ return CUBIT_FAILURE; } +CubitStatus VirtualQueryEngine::export_solid_model( DLIList<TopologyBridge*>& bridge_list, + char*& p_Buffer, + int& n_buffer_size, + bool b_export_buffer) +{ + return CUBIT_FAILURE; +} + CubitStatus VirtualQueryEngine::save_temp_geom_file( DLIList<TopologyBridge*>& , const char* , const CubitString &, @@ -1560,6 +1568,16 @@ return CUBIT_FAILURE; } +CubitStatus VirtualQueryEngine::import_solid_model(DLIList<TopologyBridge*> &imported_entities, + const char* pBuffer, + const int n_buffer_size) +{ + PRINT_INFO("VirtualQueryEngine::import_solid_model\n"); + + default_error_message( "import_solid_model()"); + return CUBIT_FAILURE; +} + void VirtualQueryEngine::delete_solid_model_entities(DLIList<BodySM*>& list) const { for ( int i = list.size(); i--; ) Modified: cgm/trunk/geom/virtual/VirtualQueryEngine.hpp =================================================================== --- cgm/trunk/geom/virtual/VirtualQueryEngine.hpp 2009-08-19 18:39:01 UTC (rev 3107) +++ cgm/trunk/geom/virtual/VirtualQueryEngine.hpp 2009-08-19 20:05:46 UTC (rev 3108) @@ -357,6 +357,11 @@ const CubitString &cubit_version, const char* logfile_name = NULL ); + virtual CubitStatus export_solid_model( DLIList<TopologyBridge*>& bridge_list, + char*& p_buffer, + int& n_buffer_size, + bool b_export_buffer); + virtual CubitStatus save_temp_geom_file(DLIList<TopologyBridge*>& bridge_list, const char *file_name, const CubitString &cubit_version, @@ -381,6 +386,10 @@ CubitBoolean import_vertices = CUBIT_TRUE, CubitBoolean free_surfaces = CUBIT_TRUE ); + virtual CubitStatus import_solid_model(DLIList<TopologyBridge*> &imported_entities, + const char* pBuffer, + const int n_buffer_size); + virtual void delete_solid_model_entities(DLIList<BodySM*>&) const; virtual CubitStatus delete_solid_model_entities( BodySM* body_ptr ) const; virtual CubitStatus delete_solid_model_entities(Surface* surf_ptr ) const; Modified: cgm/trunk/itaps/CATag.hpp =================================================================== --- cgm/trunk/itaps/CATag.hpp 2009-08-19 18:39:01 UTC (rev 3107) +++ cgm/trunk/itaps/CATag.hpp 2009-08-19 20:05:46 UTC (rev 3108) @@ -42,6 +42,7 @@ class RefEntity; class RefGroup; class CATag; +class CGMParallelComm; class CGMTagManager { @@ -116,6 +117,8 @@ return static_instance; } + inline std::vector<CGMParallelComm*>& get_pc_array() { return pc_array; } + private: CGMTagManager(); @@ -129,6 +132,9 @@ static const char *CATag_NAME_INTERNAL; RefGroup *interfaceGroup; + // list of parallel comm + std::vector<CGMParallelComm*> pc_array; + bool getPresetTagData(const RefEntity *entity, const long tag_num, char *tag_value, int &tag_size); Modified: cgm/trunk/itaps/Makefile.am =================================================================== --- cgm/trunk/itaps/Makefile.am 2009-08-19 18:39:01 UTC (rev 3107) +++ cgm/trunk/itaps/Makefile.am 2009-08-19 20:05:46 UTC (rev 3108) @@ -3,6 +3,10 @@ DEFS = $(TEMPLATE_DEFS_INCLUDED) $(HAVE_ACIS_DEF) $(HAVE_OCC_DEF) +# because "ISO C++ does not support ‘long long" +CXXFLAGS += -Wno-long-long +#CXXFLAGS = -Wall -pipe -pedantic -g -DDEBUG -Wno-long-long -DUSE_MPI + if USE_BABEL SIDL_DIR = SIDL else @@ -20,6 +24,9 @@ if build_OCC TESTS += testgeom_occ endif +if build_parallel + TESTS += partest testgeomParallel +endif SUBDIRS = . $(SIDL_DIR) @@ -67,6 +74,19 @@ chaman_CPPFLAGS = $(CPPFLAGS) -DSRCDIR=$(srcdir) chaman_LDFLAGS = $(CGM_EXT_LTFLAGS) $(CGM_EXT_LDFLAGS) +if build_parallel + partest_SOURCES = partest.cpp + partest_LDADD = $(testgeom_LDADD) + partest_CPPFLAGS = $(testgeom_CPPFLAGS) -DFORCE_OCC + partest_LDFLAGS = $(testgeom_LDFLAGS) + testgeomParallel_SOURCES = testgeomParallel.cpp + testgeomParallel_LDADD = $(testgeom_LDADD) + testgeomParallel_CPPFLAGS = $(testgeom_CPPFLAGS) -DFORCE_OCC + testgeomParallel_LDFLAGS = $(testgeom_LDFLAGS) + INCLUDES += -I$(top_srcdir)/geom/parallel +endif + + # Automake doesn't seem to have a directory defined for # platform-dependent data (or include) files. So put # in $(libdir). Define a $(cfgdir) to get around automake's Modified: cgm/trunk/itaps/iGeom_CGMA.cc =================================================================== --- cgm/trunk/itaps/iGeom_CGMA.cc 2009-08-19 18:39:01 UTC (rev 3107) +++ cgm/trunk/itaps/iGeom_CGMA.cc 2009-08-19 20:05:46 UTC (rev 3108) @@ -314,32 +314,19 @@ std::string file_name( name, name_len ); name = file_name.c_str(); - // process options + // check if work in parallel bool parallel = false; - int par_load_option = -1; - std::vector<std::string> opts; - tokenize( std::string(options, options_size), opts ); - for (size_t i = 0; i < opts.size(); ++i) { - if (opts[i] == "PARALLEL" - || opts[i] == "parallel") - parallel = true; - - if (opts[i] == "GEOM_BCAST" - || opts[i] == "geom_bcast"); - par_load_option = 0; - - if (opts[i] == "GEOM_BCAST_AND_DELETE" - || opts[i] == "geom_bcast_and_delete") - par_load_option = 1; - - if (opts[i] == "GEOM_SCATTER" - || opts[i] == "geom_scatter") - par_load_option = 2; - } + FileOptions opts(options); + std::string parallel_opt; + FOErrorCode rval = opts.get_option("PARALLEL", parallel_opt); + if (FO_SUCCESS == rval) parallel = true; + // parallel if (parallel) { #ifdef USE_MPI - CubitStatus status = ParallelGeomTool::instance()->load_parallel(name, par_load_option); + //CubitStatus status = ParallelGeomTool::instance()->load_file(name, options); + ParallelGeomTool pgt(reinterpret_cast<CGMTagManager*> (instance), NULL); + CubitStatus status = pgt.load_file(name, options); if (CUBIT_SUCCESS != status) { ERROR(iBase_FAILURE, "Trouble loading geometry file in parallel."); } @@ -347,27 +334,28 @@ ERROR(iBase_NOT_SUPPORTED, "Parallel not enabled in this version."); #endif } - - iBase_ErrorType result; - CubitStatus status = CUBIT_SUCCESS; - - if (strstr(name, ".cub") != NULL) { - iGeom_load_cub_geometry(name, err); - if (iBase_SUCCESS != *err) { - return; - } - } else { - if (strstr(name, ".brep") != NULL || strstr(name, ".occ") != NULL) - status = gqt->read_geometry_file(name, NULL, "OCC"); - else - status = gqt->read_geometry_file(name); - if (CUBIT_SUCCESS != status) { - ERROR(iBase_FILE_NOT_FOUND, "Trouble loading geometry file."); + CubitStatus status = CUBIT_SUCCESS; + + if (strstr(name, ".cub") != NULL) { + iGeom_load_cub_geometry(name, err); + if (iBase_SUCCESS != *err) { + return; + } } + else { + if (strstr(name, ".brep") != NULL || strstr(name, ".occ") != NULL) + status = gqt->read_geometry_file(name, NULL, "OCC"); + else + status = gqt->read_geometry_file(name); + if (CUBIT_SUCCESS != status) { + ERROR(iBase_FILE_NOT_FOUND, "Trouble loading geometry file."); + } + } } - + // now process uncaught/unregistered attributes + iBase_ErrorType result; result = process_attribs(instance); RETURN(result); @@ -5882,7 +5870,8 @@ if (NULL == cubfile) RETURN(iBase_FILE_NOT_FOUND); // first get the length - int result = fseek(cubfile, 0, SEEK_END); + //int result = fseek(cubfile, 0, SEEK_END); + int result = fseek(cubfile, 0, 2); if (result) { ERROR(iBase_FAILURE, "Couldn't seek to end of .cub file."); } @@ -5896,7 +5885,8 @@ } // get the model header - result = fseek(cubfile, 4, SEEK_SET); + //result = fseek(cubfile, 4, SEEK_SET); + result = fseek(cubfile, 4, 0); if (result) { ERROR(iBase_FAILURE, "Seek failed reading cub file header."); } @@ -5916,7 +5906,8 @@ ERROR(iBase_FAILURE, "Reading model table will go past end of file."); } - result = fseek(cubfile, model_table_offset, SEEK_SET); + //result = fseek(cubfile, model_table_offset, SEEK_SET); + result = fseek(cubfile, model_table_offset, 0); if (result) { ERROR(iBase_FAILURE, "Seek failed seeking to model table."); } Added: cgm/trunk/itaps/partest.cpp =================================================================== --- cgm/trunk/itaps/partest.cpp (rev 0) +++ cgm/trunk/itaps/partest.cpp 2009-08-19 20:05:46 UTC (rev 3108) @@ -0,0 +1,88 @@ +// Test parallel iGeom + +#include <iostream> +#include <stdio.h> +#include <string.h> + +# ifdef SEEK_SET +# define PTEST_SEEK_SET SEEK_SET +# define PTEST_SEEK_CUR SEEK_CUR +# define PTEST_SEEK_END SEEK_END +# undef SEEK_SET +# undef SEEK_CUR +# undef SEEK_END +# endif +#include "mpi.h" +# ifdef PTEST_SEEK_SET +# define SEEK_SET PTEST_SEEK_SET +# define SEEK_CUR PTEST_SEEK_CUR +# define SEEK_END PTEST_SEEK_END +# undef PTEST_SEEK_SET +# undef PTEST_SEEK_CUR +# undef PTEST_SEEK_END +# endif + +#include "iGeom.h" + +#define IGEOM_ASSERT(ierr) if (ierr!=0) printf("igeom assert\n"); +#define IGEOM_NULL 0 + +int main(int argc, char* argv[]){ + int rank, size; + MPI_Init(&argc, &argv); + MPI_Comm_rank( MPI_COMM_WORLD, &rank ); + MPI_Comm_size( MPI_COMM_WORLD, &size ); + printf("Hello\n"); + + iGeom_Instance igeom; + int ierr; + igeom = IGEOM_NULL; + iGeom_newGeom("PARALLEL", &igeom, &ierr, 8); + IGEOM_ASSERT(ierr); + + // check command line arg + const char* filename = 0; + int nMethod = 1; + std::string options; + + if (argc == 3) { + filename = argv[1]; + nMethod = atoi(argv[2]); + } + else { + if (rank == 0) printf("Usage: %s [<filename>] [<send_methond>]\n", argv[0]); + if (argc != 1 || argc != 2) return 1; + if (rank == 0) { + printf(" No file specified. Defaulting to: %s\n", "Moto.brep"); + printf(" No send method specified. Defaulting to: read_delete\n"); + } + filename = "../../../test_files/Moto.brep"; + } + + // set geometry send method + if (nMethod == 0) options += "PARALLEL=READ;"; + else if (nMethod == 1) options += "PARALLEL=READ_DELETE;"; + else if (nMethod == 2) options += "PARALLEL=BCAST;"; + else if (nMethod == 3) options += "PARALLEL=BCAST_DELETE;"; + else if (nMethod == 4) options += "PARALLEL=SCATTER;"; + else if (nMethod == 5) options += "PARALLEL=SCATTER_DELETE;"; + else if (nMethod == 6) options += "PARALLEL=READ_PARALLEL;"; + else { + printf("Send method %d is not supported. Defaulting to: read_delete\n", nMethod); + options = "READ_DELETE;"; + } + + // do body partitioning with round robin distribution + options += "PARTITION=GEOM_DIMENSION;PARTITION_VAL=3;PARTITION_DISTRIBUTE;"; + + double tStart = MPI_Wtime(); + iGeom_load(igeom, filename, options.c_str(), &ierr, strlen(filename), options.length()); + + MPI_Barrier(MPI_COMM_WORLD); + double tEnd = MPI_Wtime(); + + IGEOM_ASSERT(ierr); + + printf("Done. Geometry load time is %f\n", tEnd - tStart); + MPI_Finalize(); +}
participants (1)
-
hongjun@mcs.anl.gov