MOAB: Mesh Oriented datABase  (version 5.3.1)
WriteCCMIO.cpp
Go to the documentation of this file.
00001 /*
00002  * CCMIO file structure
00003  *
00004  * Root
00005  *   State(kCCMIOState)
00006  *     Processor*
00007  *       VerticesID
00008  *       TopologyID
00009  *       InitialID
00010  *       SolutionID
00011  *   Vertices*
00012  *     ->WriteVerticesx, WriteMap
00013  *   Topology*
00014  *     Boundary faces*(kCCMIOBoundaryFaces)
00015  *        ->WriteFaces, WriteFaceCells, WriteMap
00016  *     Internal faces(kCCMIOInternalFaces)
00017  *     Cells (kCCMIOCells)
00018  *        ->WriteCells (mapID), WriteMap, WriteCells
00019  *   Solution
00020  *     Phase
00021  *       Field
00022  *         FieldData
00023  *   Problem(kCCMIOProblemDescription)
00024  *     CellType* (kCCMIOCellType)
00025  *       Index (GetEntityIndex), MaterialId(WriteOpti), MaterialType(WriteOptstr),
00026  *         PorosityId(WriteOpti), SpinId(WriteOpti), GroupId(WriteOpti)
00027  *
00028  * MaterialType (CCMIOWriteOptstr in readexample)
00029  * constants (see readexample)
00030  * lagrangian data (CCMIOWriteLagrangianData)
00031  * vertices label (CCMIOEntityDescription)
00032  * restart info: char solver[], iterations, time, char timeUnits[], angle
00033  *      (CCMIOWriteRestartInfo, kCCMIORestartData), reference data?
00034  * phase:
00035  *   field: char name[], dims, CCMIODataType datatype, char units[]
00036  *       dims = kCCMIOScalar (CCMIOWriteFieldDataf),
00037  *              kCCMIOVector (CCMIOWriteMultiDimensionalFieldData),
00038  *              kCCMIOTensor
00039  * MonitoringSets: num, name (CellSet, VertexSet, BoundarySet, BlockSet, SplineSet, CoupleSet)
00040  *      CCMIOGetProstarSet, CCMIOWriteOpt1i,
00041  */
00042 
00043 #ifdef WIN32
00044 #ifdef _DEBUG
00045 // turn off warnings that say they debugging identifier has been truncated
00046 // this warning comes up when using some STL containers
00047 #pragma warning( disable : 4786 )
00048 #endif
00049 #endif
00050 
00051 #include "WriteCCMIO.hpp"
00052 #include "ccmio.h"
00053 #include "ccmioutility.h"
00054 #include "ccmiocore.h"
00055 #include <utility>
00056 #include <algorithm>
00057 #include <ctime>
00058 #include <string>
00059 #include <vector>
00060 #include <cstdio>
00061 #include <iostream>
00062 #include <algorithm>
00063 #include <sstream>
00064 
00065 #include "moab/Interface.hpp"
00066 #include "moab/Range.hpp"
00067 #include "moab/CN.hpp"
00068 #include "moab/Skinner.hpp"
00069 #include <cassert>
00070 #include "Internals.hpp"
00071 #include "ExoIIUtil.hpp"
00072 #include "MBTagConventions.hpp"
00073 #ifdef MOAB_HAVE_MPI
00074 #include "MBParallelConventions.h"
00075 #endif
00076 #include "moab/WriteUtilIface.hpp"
00077 
00078 namespace moab
00079 {
00080 
00081 static char const kStateName[] = "default";
00082 
00083 /*
00084   static const int ccm_types[] = {
00085     1,   // MBVERTEX
00086     2,   // MBEDGE
00087     -1,  // MBTRI
00088     -1,  // MBQUAD
00089     -1,  // MBPOLYGON
00090     13,  // MBTET
00091     14,  // MBPYRAMID
00092     12,  // MBPRISM
00093     -1,  // MBKNIFE
00094     11,  // MBHEX
00095     255  // MBPOLYHEDRON
00096   };
00097 */
00098 
00099 #define INS_ID( stringvar, prefix, id ) sprintf( stringvar, prefix, id )
00100 
00101 #define CHK_SET_CCMERR( ccm_err_code, ccm_err_msg )                                  \
00102     {                                                                                \
00103         if( kCCMIONoErr != ( ccm_err_code ) ) MB_SET_ERR( MB_FAILURE, ccm_err_msg ); \
00104     }
00105 
00106 WriterIface* WriteCCMIO::factory( Interface* iface )
00107 {
00108     return new WriteCCMIO( iface );
00109 }
00110 
00111 WriteCCMIO::WriteCCMIO( Interface* impl )
00112     : mbImpl( impl ), mCurrentMeshHandle( 0 ), mPartitionSetTag( 0 ), mNameTag( 0 ), mMaterialIdTag( 0 ),
00113       mMaterialTypeTag( 0 ), mRadiationTag( 0 ), mPorosityIdTag( 0 ), mSpinIdTag( 0 ), mGroupIdTag( 0 ),
00114       mColorIdxTag( 0 ), mProcessorIdTag( 0 ), mLightMaterialTag( 0 ), mFreeSurfaceMaterialTag( 0 ), mThicknessTag( 0 ),
00115       mProstarRegionNumberTag( 0 ), mBoundaryTypeTag( 0 ), mCreatingProgramTag( 0 ), mDimension( 0 ),
00116       mWholeMesh( false )
00117 {
00118     assert( impl != NULL );
00119 
00120     impl->query_interface( mWriteIface );
00121 
00122     // Initialize in case tag_get_handle fails below
00123     //! Get and cache predefined tag handles
00124     int negone = -1;
00125     impl->tag_get_handle( MATERIAL_SET_TAG_NAME, 1, MB_TYPE_INTEGER, mMaterialSetTag, MB_TAG_SPARSE | MB_TAG_CREAT,
00126                           &negone );
00127 
00128     impl->tag_get_handle( DIRICHLET_SET_TAG_NAME, 1, MB_TYPE_INTEGER, mDirichletSetTag, MB_TAG_SPARSE | MB_TAG_CREAT,
00129                           &negone );
00130 
00131     impl->tag_get_handle( NEUMANN_SET_TAG_NAME, 1, MB_TYPE_INTEGER, mNeumannSetTag, MB_TAG_SPARSE | MB_TAG_CREAT,
00132                           &negone );
00133 
00134     mGlobalIdTag = impl->globalId_tag();
00135 
00136 #ifdef MOAB_HAVE_MPI
00137     impl->tag_get_handle( PARALLEL_PARTITION_TAG_NAME, 1, MB_TYPE_INTEGER, mPartitionSetTag, MB_TAG_SPARSE );
00138     // No need to check result, if it's not there, we don't create one
00139 #endif
00140 
00141     int dum_val_array[] = { -1, -1, -1, -1 };
00142     impl->tag_get_handle( HAS_MID_NODES_TAG_NAME, 4, MB_TYPE_INTEGER, mHasMidNodesTag, MB_TAG_SPARSE | MB_TAG_CREAT,
00143                           dum_val_array );
00144 
00145     impl->tag_get_handle( "__WriteCCMIO element mark", 1, MB_TYPE_BIT, mEntityMark, MB_TAG_CREAT );
00146 
00147     // Don't need to check return of following, since it doesn't matter if there isn't one
00148     mbImpl->tag_get_handle( NAME_TAG_NAME, NAME_TAG_SIZE, MB_TYPE_OPAQUE, mNameTag );
00149 }
00150 
00151 WriteCCMIO::~WriteCCMIO()
00152 {
00153     mbImpl->release_interface( mWriteIface );
00154     mbImpl->tag_delete( mEntityMark );
00155 }
00156 
00157 ErrorCode WriteCCMIO::write_file( const char* file_name, const bool overwrite, const FileOptions&,
00158                                   const EntityHandle* ent_handles, const int num_sets,
00159                                   const std::vector< std::string >& /* qa_list */, const Tag* /* tag_list */,
00160                                   int /* num_tags */, int /* export_dimension */ )
00161 {
00162     assert( 0 != mMaterialSetTag && 0 != mNeumannSetTag && 0 != mDirichletSetTag );
00163 
00164     ErrorCode result;
00165 
00166     // Check overwrite flag and file existence
00167     if( !overwrite )
00168     {
00169         FILE* file = fopen( file_name, "r" );
00170         if( file )
00171         {
00172             fclose( file );
00173             MB_SET_ERR( MB_FILE_WRITE_ERROR, "File exists but overwrite set to false" );
00174         }
00175     }
00176 
00177     mDimension = 3;
00178 
00179     std::vector< EntityHandle > matsets, dirsets, neusets, partsets;
00180 
00181     // Separate into material, dirichlet, neumann, partition sets
00182     result = get_sets( ent_handles, num_sets, matsets, dirsets, neusets, partsets );MB_CHK_SET_ERR( result, "Failed to get material/etc. sets" );
00183 
00184     // If entity handles were input but didn't contain matsets, return error
00185     if( ent_handles && matsets.empty() )
00186     {
00187         MB_SET_ERR( MB_FILE_WRITE_ERROR, "Sets input to write but no material sets found" );
00188     }
00189 
00190     // Otherwise, if no matsets, use root set
00191     if( matsets.empty() ) matsets.push_back( 0 );
00192 
00193     std::vector< MaterialSetData > matset_info;
00194     Range all_verts;
00195     result = gather_matset_info( matsets, matset_info, all_verts );MB_CHK_SET_ERR( result, "gathering matset info failed" );
00196 
00197     // Assign vertex gids
00198     result = mWriteIface->assign_ids( all_verts, mGlobalIdTag, 1 );MB_CHK_SET_ERR( result, "Failed to assign vertex global ids" );
00199 
00200     // Some CCMIO descriptors
00201     CCMIOID rootID, topologyID, stateID, problemID, verticesID, processorID;
00202 
00203     // Try to open the file and establish state
00204     result = open_file( file_name, overwrite, rootID );MB_CHK_SET_ERR( result, "Couldn't open file or create state" );
00205 
00206     result = create_ccmio_structure( rootID, stateID, processorID );MB_CHK_SET_ERR( result, "Problem creating CCMIO file structure" );
00207 
00208     result = write_nodes( rootID, all_verts, mDimension, verticesID );MB_CHK_SET_ERR( result, "write_nodes failed" );
00209 
00210     std::vector< NeumannSetData > neuset_info;
00211     result = gather_neuset_info( neusets, neuset_info );MB_CHK_SET_ERR( result, "Failed to get neumann set info" );
00212 
00213     result = write_cells_and_faces( rootID, matset_info, neuset_info, all_verts, topologyID );MB_CHK_SET_ERR( result, "write_cells_and_faces failed" );
00214 
00215     result = write_problem_description( rootID, stateID, problemID, processorID, matset_info, neuset_info );MB_CHK_SET_ERR( result, "write_problem_description failed" );
00216 
00217     result = write_solution_data();MB_CHK_SET_ERR( result, "Trouble writing solution data" );
00218 
00219     result = write_processor( processorID, verticesID, topologyID );MB_CHK_SET_ERR( result, "Trouble writing processor" );
00220 
00221     result = close_and_compress( file_name, rootID );MB_CHK_SET_ERR( result, "Close or compress failed" );
00222 
00223     return MB_SUCCESS;
00224 }
00225 
00226 ErrorCode WriteCCMIO::write_solution_data()
00227 {
00228     // For now, no solution (tag) data
00229     return MB_SUCCESS;
00230 }
00231 
00232 ErrorCode WriteCCMIO::write_processor( CCMIOID processorID, CCMIOID verticesID, CCMIOID topologyID )
00233 {
00234     CCMIOError error = kCCMIONoErr;
00235 
00236     // Now we have the mesh (vertices and topology) and the post data written.
00237     // Since we now have their IDs, we can write out the processor information.
00238     CCMIOWriteProcessor( &error, processorID, NULL, &verticesID, NULL, &topologyID, NULL, NULL, NULL, NULL );
00239     CHK_SET_CCMERR( error, "Problem writing CCMIO processor" );
00240 
00241     return MB_SUCCESS;
00242 }
00243 
00244 ErrorCode WriteCCMIO::create_ccmio_structure( CCMIOID rootID, CCMIOID& stateID, CCMIOID& processorID )
00245 {
00246     // Create problem state and other CCMIO nodes under it
00247     CCMIOError error = kCCMIONoErr;
00248 
00249     // Create a new state (or re-use an existing one).
00250     if( CCMIOGetState( NULL, rootID, kStateName, NULL, &stateID ) != kCCMIONoErr )
00251     {
00252         CCMIONewState( &error, rootID, kStateName, NULL, NULL, &stateID );
00253         CHK_SET_CCMERR( error, "Trouble creating state" );
00254     }
00255 
00256     // Create or get an old processor for this state
00257     CCMIOSize_t i = CCMIOSIZEC( 0 );
00258     if( CCMIONextEntity( NULL, stateID, kCCMIOProcessor, &i, &processorID ) != kCCMIONoErr )
00259     {
00260         CCMIONewEntity( &error, stateID, kCCMIOProcessor, NULL, &processorID );
00261         CHK_SET_CCMERR( error, "Trouble creating processor node" );
00262     }
00263     // Get rid of any data that may be in this processor (if the state was
00264     // not new).
00265     else
00266     {
00267         CCMIOClearProcessor( &error, stateID, processorID, TRUE, TRUE, TRUE, TRUE, TRUE );
00268         CHK_SET_CCMERR( error, "Trouble clearing processor data" );
00269     }
00270 
00271     /*
00272      //  for (; i < CCMIOSIZEC(partsets.size()); i++) {
00273      CCMIOSize_t id = CCMIOSIZEC(0);
00274      if (CCMIONextEntity(NULL, stateID, kCCMIOProcessor, &id, &processorID) != kCCMIONoErr)
00275      CCMIONewEntity(&error, stateID, kCCMIOProcessor, NULL, &processorID);
00276      CHKCCMERR(error, "Trouble creating processor node.");
00277      */
00278     return MB_SUCCESS;
00279 }
00280 
00281 ErrorCode WriteCCMIO::close_and_compress( const char*, CCMIOID rootID )
00282 {
00283     CCMIOError error = kCCMIONoErr;
00284     CCMIOCloseFile( &error, rootID );
00285     CHK_SET_CCMERR( error, "File close failed" );
00286 
00287     // The CCMIO library uses ADF to store the actual data.  Unfortunately,
00288     // ADF leaks disk space;  deleting a node does not recover all the disk
00289     // space.  Now that everything is successfully written it might be useful
00290     // to call CCMIOCompress() here to ensure that the file is as small as
00291     // possible.  Please see the Core API documentation for caveats on its
00292     // usage.
00293     // CCMIOCompress(&error, const_cast<char*>(filename));CHK_SET_CCMERR(error, "Error compressing
00294     // file");
00295 
00296     return MB_SUCCESS;
00297 }
00298 
00299 ErrorCode WriteCCMIO::open_file( const char* filename, bool, CCMIOID& rootID )
00300 {
00301     CCMIOError error = kCCMIONoErr;
00302     CCMIOOpenFile( &error, filename, kCCMIOWrite, &rootID );
00303     CHK_SET_CCMERR( error, "Cannot open file" );
00304 
00305     return MB_SUCCESS;
00306 }
00307 
00308 ErrorCode WriteCCMIO::get_sets( const EntityHandle* ent_handles, int num_sets, std::vector< EntityHandle >& matsets,
00309                                 std::vector< EntityHandle >& dirsets, std::vector< EntityHandle >& neusets,
00310                                 std::vector< EntityHandle >& partsets )
00311 {
00312     if( num_sets == 0 )
00313     {
00314         // Default to all defined sets
00315         Range this_range;
00316         mbImpl->get_entities_by_type_and_tag( 0, MBENTITYSET, &mMaterialSetTag, NULL, 1, this_range );
00317         std::copy( this_range.begin(), this_range.end(), std::back_inserter( matsets ) );
00318         this_range.clear();
00319         mbImpl->get_entities_by_type_and_tag( 0, MBENTITYSET, &mDirichletSetTag, NULL, 1, this_range );
00320         std::copy( this_range.begin(), this_range.end(), std::back_inserter( dirsets ) );
00321         this_range.clear();
00322         mbImpl->get_entities_by_type_and_tag( 0, MBENTITYSET, &mNeumannSetTag, NULL, 1, this_range );
00323         std::copy( this_range.begin(), this_range.end(), std::back_inserter( neusets ) );
00324         if( mPartitionSetTag )
00325         {
00326             this_range.clear();
00327             mbImpl->get_entities_by_type_and_tag( 0, MBENTITYSET, &mPartitionSetTag, NULL, 1, this_range );
00328             std::copy( this_range.begin(), this_range.end(), std::back_inserter( partsets ) );
00329         }
00330     }
00331     else
00332     {
00333         int dummy;
00334         for( const EntityHandle* iter = ent_handles; iter < ent_handles + num_sets; ++iter )
00335         {
00336             if( MB_SUCCESS == mbImpl->tag_get_data( mMaterialSetTag, &( *iter ), 1, &dummy ) )
00337                 matsets.push_back( *iter );
00338             else if( MB_SUCCESS == mbImpl->tag_get_data( mDirichletSetTag, &( *iter ), 1, &dummy ) )
00339                 dirsets.push_back( *iter );
00340             else if( MB_SUCCESS == mbImpl->tag_get_data( mNeumannSetTag, &( *iter ), 1, &dummy ) )
00341                 neusets.push_back( *iter );
00342             else if( mPartitionSetTag && MB_SUCCESS == mbImpl->tag_get_data( mPartitionSetTag, &( *iter ), 1, &dummy ) )
00343                 partsets.push_back( *iter );
00344         }
00345     }
00346 
00347     return MB_SUCCESS;
00348 }
00349 
00350 ErrorCode WriteCCMIO::write_problem_description( CCMIOID rootID, CCMIOID stateID, CCMIOID& problemID,
00351                                                  CCMIOID processorID,
00352                                                  std::vector< WriteCCMIO::MaterialSetData >& matset_data,
00353                                                  std::vector< WriteCCMIO::NeumannSetData >& neuset_data )
00354 {
00355     // Write out a dummy problem description.  If we happen to know that
00356     // there already is a problem description previously recorded that
00357     // is valid we could skip this step.
00358     CCMIOID id;
00359     CCMIOError error = kCCMIONoErr;
00360     ErrorCode rval;
00361     const EntityHandle mesh = 0;
00362 
00363     bool root_tagged = false, other_set_tagged = false;
00364     Tag simname;
00365     Range dum_sets;
00366     rval = mbImpl->tag_get_handle( "Title", 0, MB_TYPE_OPAQUE, simname, MB_TAG_ANY );
00367     if( MB_SUCCESS == rval )
00368     {
00369         int tag_size;
00370         rval = mbImpl->tag_get_bytes( simname, tag_size );
00371         if( MB_SUCCESS == rval )
00372         {
00373             std::vector< char > title_tag( tag_size + 1 );
00374             rval = mbImpl->get_entities_by_type_and_tag( 0, MBENTITYSET, &simname, NULL, 1, dum_sets );
00375             if( MB_SUCCESS == rval && !dum_sets.empty() )
00376             {
00377                 rval = mbImpl->tag_get_data( simname, &( *dum_sets.begin() ), 1, &title_tag[0] );MB_CHK_SET_ERR( rval, "Problem getting simulation name tag" );
00378                 other_set_tagged = true;
00379             }
00380             else if( MB_SUCCESS == rval )
00381             {
00382                 // Check to see if interface was tagged
00383                 rval = mbImpl->tag_get_data( simname, &mesh, 1, &title_tag[0] );
00384                 if( MB_SUCCESS == rval )
00385                     root_tagged = true;
00386                 else
00387                     rval = MB_SUCCESS;
00388             }
00389             *title_tag.rbegin() = '\0';
00390             if( root_tagged || other_set_tagged )
00391             {
00392                 CCMIONode rootNode;
00393                 if( kCCMIONoErr == CCMIOGetEntityNode( &error, rootID, &rootNode ) )
00394                 {
00395                     CCMIOSetTitle( &error, rootNode, &title_tag[0] );
00396                     CHK_SET_CCMERR( error, "Trouble setting title" );
00397                 }
00398             }
00399         }
00400     }
00401 
00402     rval = mbImpl->tag_get_handle( "CreatingProgram", 0, MB_TYPE_OPAQUE, mCreatingProgramTag, MB_TAG_ANY );
00403     if( MB_SUCCESS == rval )
00404     {
00405         int tag_size;
00406         rval = mbImpl->tag_get_bytes( mCreatingProgramTag, tag_size );
00407         if( MB_SUCCESS == rval )
00408         {
00409             std::vector< char > cp_tag( tag_size + 1 );
00410             rval = mbImpl->get_entities_by_type_and_tag( 0, MBENTITYSET, &mCreatingProgramTag, NULL, 1, dum_sets );
00411             if( MB_SUCCESS == rval && !dum_sets.empty() )
00412             {
00413                 rval = mbImpl->tag_get_data( mCreatingProgramTag, &( *dum_sets.begin() ), 1, &cp_tag[0] );MB_CHK_SET_ERR( rval, "Problem getting creating program tag" );
00414                 other_set_tagged = true;
00415             }
00416             else if( MB_SUCCESS == rval )
00417             {
00418                 // Check to see if interface was tagged
00419                 rval = mbImpl->tag_get_data( mCreatingProgramTag, &mesh, 1, &cp_tag[0] );
00420                 if( MB_SUCCESS == rval )
00421                     root_tagged = true;
00422                 else
00423                     rval = MB_SUCCESS;
00424             }
00425             *cp_tag.rbegin() = '\0';
00426             if( root_tagged || other_set_tagged )
00427             {
00428                 CCMIONode rootNode;
00429                 if( kCCMIONoErr == CCMIOGetEntityNode( &error, rootID, &rootNode ) )
00430                 {
00431                     CCMIOWriteOptstr( &error, processorID, "CreatingProgram", &cp_tag[0] );
00432                     CHK_SET_CCMERR( error, "Trouble setting creating program" );
00433                 }
00434             }
00435         }
00436     }
00437 
00438     CCMIONewEntity( &error, rootID, kCCMIOProblemDescription, NULL, &problemID );
00439     CHK_SET_CCMERR( error, "Trouble creating problem node" );
00440 
00441     // Write material types and other info
00442     for( unsigned int i = 0; i < matset_data.size(); i++ )
00443     {
00444         if( !matset_data[i].setName.empty() )
00445         {
00446             CCMIONewIndexedEntity( &error, problemID, kCCMIOCellType, matset_data[i].matsetId,
00447                                    matset_data[i].setName.c_str(), &id );
00448             CHK_SET_CCMERR( error, "Failure creating celltype node" );
00449 
00450             CCMIOWriteOptstr( &error, id, "MaterialType", matset_data[i].setName.c_str() );
00451             CHK_SET_CCMERR( error, "Error assigning material name" );
00452         }
00453         else
00454         {
00455             char dum_name[NAME_TAG_SIZE];
00456             std::ostringstream os;
00457             std::string mat_name = "Material", temp_str;
00458             os << mat_name << ( i + 1 );
00459             temp_str = os.str();
00460             strcpy( dum_name, temp_str.c_str() );
00461             CCMIONewIndexedEntity( &error, problemID, kCCMIOCellType, matset_data[i].matsetId, dum_name, &id );
00462             CHK_SET_CCMERR( error, "Failure creating celltype node" );
00463 
00464             CCMIOWriteOptstr( &error, id, "MaterialType", dum_name );
00465             CHK_SET_CCMERR( error, "Error assigning material name" );
00466 
00467             os.str( "" );
00468         }
00469         rval = write_int_option( "MaterialId", matset_data[i].setHandle, mMaterialIdTag, id );MB_CHK_SET_ERR( rval, "Trouble writing MaterialId option" );
00470 
00471         rval = write_int_option( "Radiation", matset_data[i].setHandle, mRadiationTag, id );MB_CHK_SET_ERR( rval, "Trouble writing Radiation option" );
00472 
00473         rval = write_int_option( "PorosityId", matset_data[i].setHandle, mPorosityIdTag, id );MB_CHK_SET_ERR( rval, "Trouble writing PorosityId option" );
00474 
00475         rval = write_int_option( "SpinId", matset_data[i].setHandle, mSpinIdTag, id );MB_CHK_SET_ERR( rval, "Trouble writing SpinId option" );
00476 
00477         rval = write_int_option( "GroupId", matset_data[i].setHandle, mGroupIdTag, id );MB_CHK_SET_ERR( rval, "Trouble writing GroupId option" );
00478 
00479         rval = write_int_option( "ColorIdx", matset_data[i].setHandle, mColorIdxTag, id );MB_CHK_SET_ERR( rval, "Trouble writing ColorIdx option" );
00480 
00481         rval = write_int_option( "ProcessorId", matset_data[i].setHandle, mProcessorIdTag, id );MB_CHK_SET_ERR( rval, "Trouble writing ProcessorId option" );
00482 
00483         rval = write_int_option( "LightMaterial", matset_data[i].setHandle, mLightMaterialTag, id );MB_CHK_SET_ERR( rval, "Trouble writing LightMaterial option." );
00484 
00485         rval = write_int_option( "FreeSurfaceMaterial", matset_data[i].setHandle, mFreeSurfaceMaterialTag, id );MB_CHK_SET_ERR( rval, "Trouble writing FreeSurfaceMaterial option" );
00486 
00487         rval = write_dbl_option( "Thickness", matset_data[i].setHandle, mThicknessTag, id );MB_CHK_SET_ERR( rval, "Trouble writing Thickness option" );
00488 
00489         rval = write_str_option( "MaterialType", matset_data[i].setHandle, mMaterialTypeTag, id );MB_CHK_SET_ERR( rval, "Trouble writing MaterialType option" );
00490     }
00491 
00492     // Write neumann set info
00493     for( unsigned int i = 0; i < neuset_data.size(); i++ )
00494     {
00495         // Use the label to encode the id
00496         std::ostringstream dum_id;
00497         dum_id << neuset_data[i].neusetId;
00498         CCMIONewIndexedEntity( &error, problemID, kCCMIOBoundaryRegion, neuset_data[i].neusetId, dum_id.str().c_str(),
00499                                &id );
00500         CHK_SET_CCMERR( error, "Failure creating BoundaryRegion node" );
00501 
00502         rval = write_str_option( "BoundaryName", neuset_data[i].setHandle, mNameTag, id );MB_CHK_SET_ERR( rval, "Trouble writing boundary type number" );
00503 
00504         rval = write_str_option( "BoundaryType", neuset_data[i].setHandle, mBoundaryTypeTag, id );MB_CHK_SET_ERR( rval, "Trouble writing boundary type number" );
00505 
00506         rval = write_int_option( "ProstarRegionNumber", neuset_data[i].setHandle, mProstarRegionNumberTag, id );MB_CHK_SET_ERR( rval, "Trouble writing prostar region number" );
00507     }
00508 
00509     CCMIOWriteState( &error, stateID, problemID, "Example state" );
00510     CHK_SET_CCMERR( error, "Failure writing problem state" );
00511 
00512     // Get cell types; reuse cell ids array
00513     //  for (i = 0, rit = all_elems.begin(); i < num_elems; i++, ++rit) {
00514     //    egids[i] = ccm_types[mbImpl->type_from_handle(*rit)];
00515     //    assert(-1 != egids[i]);
00516     //  }
00517 
00518     return MB_SUCCESS;
00519 }
00520 
00521 ErrorCode WriteCCMIO::write_int_option( const char* opt_name, EntityHandle seth, Tag& tag, CCMIOID& node )
00522 {
00523     ErrorCode rval;
00524 
00525     if( !tag )
00526     {
00527         rval = mbImpl->tag_get_handle( opt_name, 1, MB_TYPE_INTEGER, tag );
00528         // Return success since that just means we don't have to write this option
00529         if( MB_SUCCESS != rval ) return MB_SUCCESS;
00530     }
00531 
00532     int dum_val;
00533     rval = mbImpl->tag_get_data( tag, &seth, 1, &dum_val );
00534     // Return success since that just means we don't have to write this option
00535     if( MB_SUCCESS != rval ) return MB_SUCCESS;
00536 
00537     CCMIOError error = kCCMIONoErr;
00538     CCMIOWriteOpti( &error, node, opt_name, dum_val );
00539     CHK_SET_CCMERR( error, "Trouble writing int option" );
00540 
00541     return MB_SUCCESS;
00542 }
00543 
00544 ErrorCode WriteCCMIO::write_dbl_option( const char* opt_name, EntityHandle seth, Tag& tag, CCMIOID& node )
00545 {
00546     ErrorCode rval;
00547 
00548     if( !tag )
00549     {
00550         rval = mbImpl->tag_get_handle( opt_name, 1, MB_TYPE_DOUBLE, tag );
00551         // Return success since that just means we don't have to write this option
00552         if( MB_SUCCESS != rval ) return MB_SUCCESS;
00553     }
00554 
00555     double dum_val;
00556     rval = mbImpl->tag_get_data( tag, &seth, 1, &dum_val );
00557     // Return success since that just means we don't have to write this option
00558     if( MB_SUCCESS != rval ) return MB_SUCCESS;
00559 
00560     CCMIOError error = kCCMIONoErr;
00561     CCMIOWriteOptf( &error, node, opt_name, dum_val );
00562     CHK_SET_CCMERR( error, "Trouble writing int option" );
00563 
00564     return MB_SUCCESS;
00565 }
00566 
00567 ErrorCode WriteCCMIO::write_str_option( const char* opt_name, EntityHandle seth, Tag& tag, CCMIOID& node,
00568                                         const char* other_name )
00569 {
00570     int tag_size;
00571     ErrorCode rval;
00572 
00573     if( !tag )
00574     {
00575         rval = mbImpl->tag_get_handle( opt_name, 0, MB_TYPE_OPAQUE, tag, MB_TAG_ANY );
00576         // Return success since that just means we don't have to write this option
00577         if( MB_SUCCESS != rval ) return MB_SUCCESS;
00578     }
00579 
00580     rval = mbImpl->tag_get_bytes( tag, tag_size );
00581     if( MB_SUCCESS != rval ) return MB_SUCCESS;
00582     std::vector< char > opt_val( tag_size + 1 );
00583 
00584     rval = mbImpl->tag_get_data( tag, &seth, 1, &opt_val[0] );
00585     if( MB_SUCCESS != rval ) return MB_SUCCESS;
00586 
00587     // Null-terminate if necessary
00588     if( std::find( opt_val.begin(), opt_val.end(), '\0' ) == opt_val.end() ) *opt_val.rbegin() = '\0';
00589 
00590     CCMIOError error = kCCMIONoErr;
00591     if( other_name )
00592     {
00593         CCMIOWriteOptstr( &error, node, other_name, &opt_val[0] );
00594         CHK_SET_CCMERR( error, "Failure writing an option string MaterialType" );
00595     }
00596     else
00597     {
00598         CCMIOWriteOptstr( &error, node, opt_name, &opt_val[0] );
00599         CHK_SET_CCMERR( error, "Failure writing an option string MaterialType" );
00600     }
00601 
00602     return MB_SUCCESS;
00603 }
00604 
00605 ErrorCode WriteCCMIO::gather_matset_info( std::vector< EntityHandle >& matsets,
00606                                           std::vector< MaterialSetData >& matset_data, Range& all_verts )
00607 {
00608     ErrorCode result;
00609     matset_data.resize( matsets.size() );
00610     if( 1 == matsets.size() && 0 == matsets[0] )
00611     {
00612         // Whole mesh
00613         mWholeMesh = true;
00614 
00615         result = mbImpl->get_entities_by_dimension( 0, mDimension, matset_data[0].elems );MB_CHK_SET_ERR( result, "Trouble getting all elements in mesh" );
00616         result = mWriteIface->gather_nodes_from_elements( matset_data[0].elems, mEntityMark, all_verts );MB_CHK_SET_ERR( result, "Trouble gathering nodes from elements" );
00617 
00618         return result;
00619     }
00620 
00621     std::vector< unsigned char > marks;
00622     for( unsigned int i = 0; i < matsets.size(); i++ )
00623     {
00624         EntityHandle this_set = matset_data[i].setHandle = matsets[i];
00625 
00626         // Get all Entity Handles in the set
00627         result = mbImpl->get_entities_by_dimension( this_set, mDimension, matset_data[i].elems, true );MB_CHK_SET_ERR( result, "Trouble getting m-dimensional ents" );
00628 
00629         // Get all connected vertices
00630         result = mWriteIface->gather_nodes_from_elements( matset_data[i].elems, mEntityMark, all_verts );MB_CHK_SET_ERR( result, "Trouble getting vertices for a matset" );
00631 
00632         // Check for consistent entity type
00633         EntityType start_type = mbImpl->type_from_handle( *matset_data[i].elems.begin() );
00634         if( start_type == mbImpl->type_from_handle( *matset_data[i].elems.rbegin() ) )
00635             matset_data[i].entityType = start_type;
00636 
00637         // Mark elements in this matset
00638         marks.resize( matset_data[i].elems.size(), 0x1 );
00639         result = mbImpl->tag_set_data( mEntityMark, matset_data[i].elems, &marks[0] );MB_CHK_SET_ERR( result, "Couln't mark entities being output" );
00640 
00641         // Get id for this matset
00642         result = mbImpl->tag_get_data( mMaterialSetTag, &this_set, 1, &matset_data[i].matsetId );MB_CHK_SET_ERR( result, "Couln't get global id for material set" );
00643 
00644         // Get name for this matset
00645         if( mNameTag )
00646         {
00647             char dum_name[NAME_TAG_SIZE];
00648             result = mbImpl->tag_get_data( mNameTag, &this_set, 1, dum_name );
00649             if( MB_SUCCESS == result ) matset_data[i].setName = dum_name;
00650 
00651             // Reset success, so later checks don't fail
00652             result = MB_SUCCESS;
00653         }
00654     }
00655 
00656     if( all_verts.empty() ) { MB_SET_ERR( MB_FILE_WRITE_ERROR, "No vertices from elements" ); }
00657 
00658     return MB_SUCCESS;
00659 }
00660 
00661 ErrorCode WriteCCMIO::gather_neuset_info( std::vector< EntityHandle >& neusets,
00662                                           std::vector< NeumannSetData >& neuset_info )
00663 {
00664     ErrorCode result;
00665 
00666     neuset_info.resize( neusets.size() );
00667     for( unsigned int i = 0; i < neusets.size(); i++ )
00668     {
00669         EntityHandle this_set = neuset_info[i].setHandle = neusets[i];
00670 
00671         // Get all Entity Handles of one less dimension than that being output
00672         result = mbImpl->get_entities_by_dimension( this_set, mDimension - 1, neuset_info[i].elems, true );MB_CHK_SET_ERR( result, "Trouble getting (m-1)-dimensional ents for neuset" );
00673 
00674         result = mbImpl->tag_get_data( mGlobalIdTag, &this_set, 1, &neuset_info[i].neusetId );
00675         if( MB_TAG_NOT_FOUND == result )
00676         {
00677             result = mbImpl->tag_get_data( mNeumannSetTag, &this_set, 1, &neuset_info[i].neusetId );
00678             if( MB_SUCCESS != result )
00679                 // Need some id; use the loop iteration number
00680                 neuset_info[i].neusetId = i;
00681         }
00682 
00683         // Get name for this neuset
00684         if( mNameTag )
00685         {
00686             char dum_name[NAME_TAG_SIZE];
00687             result = mbImpl->tag_get_data( mNameTag, &this_set, 1, dum_name );
00688             if( MB_SUCCESS == result ) neuset_info[i].setName = dum_name;
00689 
00690             // Reset success, so later checks don't fail
00691             result = MB_SUCCESS;
00692         }
00693     }
00694 
00695     return MB_SUCCESS;
00696 }
00697 
00698 ErrorCode WriteCCMIO::get_gids( const Range& ents, int*& gids, int& minid, int& maxid )
00699 {
00700     int num_ents     = ents.size();
00701     gids             = new int[num_ents];
00702     ErrorCode result = mbImpl->tag_get_data( mGlobalIdTag, ents, &gids[0] );MB_CHK_SET_ERR( result, "Couldn't get global id data" );
00703     minid = *std::min_element( gids, gids + num_ents );
00704     maxid = *std::max_element( gids, gids + num_ents );
00705     if( 0 == minid )
00706     {
00707         // gids need to be assigned
00708         for( int i = 1; i <= num_ents; i++ )
00709             gids[i] = i;
00710         result = mbImpl->tag_set_data( mGlobalIdTag, ents, &gids[0] );MB_CHK_SET_ERR( result, "Couldn't set global id data" );
00711         maxid = num_ents;
00712     }
00713 
00714     return MB_SUCCESS;
00715 }
00716 
00717 ErrorCode WriteCCMIO::write_nodes( CCMIOID rootID, const Range& verts, const int dimension, CCMIOID& verticesID )
00718 {
00719     // Get/write map (global ids) first (gids already assigned)
00720     unsigned int num_verts = verts.size();
00721     std::vector< int > vgids( num_verts );
00722     ErrorCode result = mbImpl->tag_get_data( mGlobalIdTag, verts, &vgids[0] );MB_CHK_SET_ERR( result, "Failed to get global ids for vertices" );
00723 
00724     // Create the map node for vertex ids, and write them to that node
00725     CCMIOID mapID;
00726     CCMIOError error = kCCMIONoErr;
00727     CCMIONewEntity( &error, rootID, kCCMIOMap, "Vertex map", &mapID );
00728     CHK_SET_CCMERR( error, "Failure creating Vertex map node" );
00729 
00730     int maxid = *std::max_element( vgids.begin(), vgids.end() );
00731 
00732     CCMIOWriteMap( &error, mapID, CCMIOSIZEC( num_verts ), CCMIOSIZEC( maxid ), &vgids[0], CCMIOINDEXC( kCCMIOStart ),
00733                    CCMIOINDEXC( kCCMIOEnd ) );
00734     CHK_SET_CCMERR( error, "Problem writing node map" );
00735 
00736     // Create the vertex coordinate node, and write it
00737     CCMIONewEntity( &error, rootID, kCCMIOVertices, "Vertices", &verticesID );
00738     CHK_SET_CCMERR( error, "Trouble creating vertices node" );
00739 
00740     // Get the vertex locations
00741     double* coords = new double[3 * num_verts];
00742     std::vector< double* > coord_arrays( 3 );
00743     // Cppcheck warning (false positive): variable coord_arrays is assigned a value that is never
00744     // used
00745     coord_arrays[0] = coords;
00746     coord_arrays[1] = coords + num_verts;
00747     coord_arrays[2] = ( dimension == 3 ? coords + 2 * num_verts : NULL );
00748     result          = mWriteIface->get_node_coords( -1, verts.begin(), verts.end(), 3 * num_verts, coords );
00749     if( result != MB_SUCCESS )
00750     {
00751         delete[] coords;
00752         return result;
00753     }
00754 
00755     // Transform coordinates, if necessary
00756     result = transform_coords( dimension, num_verts, coords );
00757     if( result != MB_SUCCESS )
00758     {
00759         delete[] coords;
00760         MB_SET_ERR( result, "Trouble transforming vertex coordinates" );
00761     }
00762 
00763     // Write the vertices
00764     CCMIOWriteVerticesd( &error, verticesID, CCMIOSIZEC( dimension ), 1.0, mapID, coords, CCMIOINDEXC( kCCMIOStart ),
00765                          CCMIOINDEXC( kCCMIOEnd ) );
00766     CHK_SET_CCMERR( error, "CCMIOWriteVertices failed" );
00767 
00768     // Clean up
00769     delete[] coords;
00770 
00771     return MB_SUCCESS;
00772 }
00773 
00774 ErrorCode WriteCCMIO::transform_coords( const int dimension, const int num_nodes, double* coords )
00775 {
00776     Tag trans_tag;
00777     ErrorCode result = mbImpl->tag_get_handle( MESH_TRANSFORM_TAG_NAME, 16, MB_TYPE_DOUBLE, trans_tag );
00778     if( result == MB_TAG_NOT_FOUND )
00779         return MB_SUCCESS;
00780     else if( MB_SUCCESS != result )
00781         return result;
00782     double trans_matrix[16];
00783     const EntityHandle mesh = 0;
00784     result                  = mbImpl->tag_get_data( trans_tag, &mesh, 1, trans_matrix );MB_CHK_SET_ERR( result, "Couldn't get transform data" );
00785 
00786     double* tmp_coords = coords;
00787     for( int i = 0; i < num_nodes; i++, tmp_coords += 1 )
00788     {
00789         double vec1[3] = { 0.0, 0.0, 0.0 };
00790         for( int row = 0; row < 3; row++ )
00791         {
00792             vec1[row] += ( trans_matrix[( row * 4 ) + 0] * coords[0] );
00793             vec1[row] += ( trans_matrix[( row * 4 ) + 1] * coords[num_nodes] );
00794             if( 3 == dimension ) vec1[row] += ( trans_matrix[( row * 4 ) + 2] * coords[2 * num_nodes] );
00795         }
00796 
00797         coords[0]             = vec1[0];
00798         coords[num_nodes]     = vec1[1];
00799         coords[2 * num_nodes] = vec1[2];
00800     }
00801 
00802     return MB_SUCCESS;
00803 }
00804 
00805 ErrorCode WriteCCMIO::write_cells_and_faces( CCMIOID rootID, std::vector< MaterialSetData >& matset_data,
00806                                              std::vector< NeumannSetData >& neuset_data, Range& /* verts */,
00807                                              CCMIOID& topologyID )
00808 {
00809     std::vector< int > connect;
00810     ErrorCode result;
00811     CCMIOID cellMapID, cells;
00812     CCMIOError error = kCCMIONoErr;
00813 
00814     // Don't usually have anywhere near 31 nodes per element
00815     connect.reserve( 31 );
00816     Range::const_iterator rit;
00817 
00818     // Create the topology node, and the cell and cell map nodes
00819     CCMIONewEntity( &error, rootID, kCCMIOTopology, "Topology", &topologyID );
00820     CHK_SET_CCMERR( error, "Trouble creating topology node" );
00821 
00822     CCMIONewEntity( &error, rootID, kCCMIOMap, "Cell map", &cellMapID );
00823     CHK_SET_CCMERR( error, "Failure creating Cell Map node" );
00824 
00825     CCMIONewEntity( &error, topologyID, kCCMIOCells, "Cells", &cells );
00826     CHK_SET_CCMERR( error, "Trouble creating Cell node under Topology node" );
00827 
00828     //================================================
00829     // Loop over material sets, doing each one at a time
00830     //================================================
00831     Range all_elems;
00832     unsigned int i, num_elems = 0;
00833     int max_id = 1;
00834     std::vector< int > egids;
00835     int tot_elems = 0;
00836 
00837     for( unsigned int m = 0; m < matset_data.size(); m++ )
00838         tot_elems += matset_data[m].elems.size();
00839 
00840     for( unsigned int m = 0; m < matset_data.size(); m++ )
00841     {
00842         unsigned int this_num = matset_data[m].elems.size();
00843 
00844         //================================================
00845         // Save all elements being output
00846         //================================================
00847         all_elems.merge( matset_data[m].elems );
00848 
00849         //================================================
00850         // Assign global ids for elements being written
00851         //================================================
00852         egids.resize( matset_data[m].elems.size() );
00853         for( i = 0; i < this_num; i++ )
00854             egids[i] = max_id++;
00855         result = mbImpl->tag_set_data( mGlobalIdTag, matset_data[m].elems, &egids[0] );MB_CHK_SET_ERR( result, "Failed to assign global ids for all elements being written" );
00856 
00857         //================================================
00858         // Write cell ids and material types for this matset; reuse egids for cell mat type
00859         //================================================
00860         CCMIOWriteMap( &error, cellMapID, CCMIOSIZEC( tot_elems ), CCMIOSIZEC( tot_elems ), &egids[0],
00861                        CCMIOINDEXC( 0 == m ? kCCMIOStart : num_elems ),
00862                        CCMIOINDEXC( matset_data.size() == m ? kCCMIOEnd : num_elems + this_num ) );
00863         CHK_SET_CCMERR( error, "Trouble writing cell map" );
00864 
00865         if( -1 == matset_data[m].matsetId )
00866         {
00867             for( i = 0; i < this_num; i++ )
00868                 egids[i] = m;
00869         }
00870         else
00871         {
00872             for( i = 0; i < this_num; i++ )
00873                 egids[i] = matset_data[m].matsetId;
00874         }
00875 
00876         CCMIOWriteCells( &error, cells, cellMapID, &egids[0], CCMIOINDEXC( 0 == m ? kCCMIOStart : num_elems ),
00877                          CCMIOINDEXC( matset_data.size() == m ? kCCMIOEnd : num_elems + this_num ) );
00878         CHK_SET_CCMERR( error, "Trouble writing Cell node" );
00879 
00880         //================================================
00881         // Write cell entity types
00882         //================================================
00883         const EntityHandle* conn;
00884         int num_conn;
00885         int has_mid_nodes[4];
00886         std::vector< EntityHandle > storage;
00887         for( i = 0, rit = matset_data[m].elems.begin(); i < this_num; i++, ++rit )
00888         {
00889             result = mbImpl->get_connectivity( *rit, conn, num_conn, false, &storage );MB_CHK_SET_ERR( result, "Trouble getting connectivity for entity type check" );
00890             CN::HasMidNodes( mbImpl->type_from_handle( *rit ), num_conn, has_mid_nodes );
00891             egids[i] = moab_to_ccmio_type( mbImpl->type_from_handle( *rit ), has_mid_nodes );
00892         }
00893 
00894         CCMIOWriteOpt1i( &error, cells, "CellTopologyType", CCMIOSIZEC( tot_elems ), &egids[0],
00895                          CCMIOINDEXC( 0 == m ? kCCMIOStart : num_elems ),
00896                          CCMIOINDEXC( matset_data.size() == m ? kCCMIOEnd : num_elems + this_num ) );
00897         CHK_SET_CCMERR( error, "Failed to write cell topo types" );
00898 
00899         num_elems += this_num;
00900     }
00901 
00902     //================================================
00903     // Get skin and neumann set faces
00904     //================================================
00905     Range neuset_facets, skin_facets;
00906     Skinner skinner( mbImpl );
00907     result = skinner.find_skin( 0, all_elems, mDimension - 1, skin_facets );MB_CHK_SET_ERR( result, "Failed to get skin facets" );
00908 
00909     // Remove neumann set facets from skin facets, we have to output these
00910     // separately
00911     for( i = 0; i < neuset_data.size(); i++ )
00912         neuset_facets.merge( neuset_data[i].elems );
00913 
00914     skin_facets -= neuset_facets;
00915     // Make neuset_facets the union, and get ids for them
00916     neuset_facets.merge( skin_facets );
00917     result = mWriteIface->assign_ids( neuset_facets, mGlobalIdTag, 1 );
00918 
00919     int fmaxid = neuset_facets.size();
00920 
00921     //================================================
00922     // Write external faces
00923     //================================================
00924     for( i = 0; i < neuset_data.size(); i++ )
00925     {
00926         Range::reverse_iterator rrit;
00927         unsigned char cmarks[2];
00928         Range ext_faces;
00929         std::vector< EntityHandle > mcells;
00930         // Removing the faces connected to two regions
00931         for( rrit = neuset_data[i].elems.rbegin(); rrit != neuset_data[i].elems.rend(); ++rrit )
00932         {
00933             mcells.clear();
00934             result = mbImpl->get_adjacencies( &( *rrit ), 1, mDimension, false, mcells );MB_CHK_SET_ERR( result, "Trouble getting bounding cells" );
00935 
00936             result = mbImpl->tag_get_data( mEntityMark, &mcells[0], mcells.size(), cmarks );MB_CHK_SET_ERR( result, "Trouble getting mark tags on cells bounding facets" );
00937 
00938             if( mcells.size() == 2 && ( mWholeMesh || ( cmarks[0] && cmarks[1] ) ) ) {}
00939             else
00940             {
00941                 // External face
00942                 ext_faces.insert( *rrit );
00943             }
00944         }
00945         if( ext_faces.size() != 0 && neuset_data[i].neusetId != 0 )
00946         {
00947             result = write_external_faces( rootID, topologyID, neuset_data[i].neusetId, ext_faces );MB_CHK_SET_ERR( result, "Trouble writing Neumann set facets" );
00948         }
00949         ext_faces.clear();
00950     }
00951 
00952     if( !skin_facets.empty() )
00953     {
00954         result = write_external_faces( rootID, topologyID, 0, skin_facets );MB_CHK_SET_ERR( result, "Trouble writing skin facets" );
00955     }
00956 
00957     //================================================
00958     // Now internal faces; loop over elements, do each face on the element
00959     //================================================
00960     // Mark tag, for face marking on each non-polyhedral element
00961 
00962     if( num_elems > 1 )
00963     {  // No internal faces for just one element
00964         Tag fmark_tag;
00965         unsigned char mval = 0x0, omval;
00966         result = mbImpl->tag_get_handle( "__fmark", 1, MB_TYPE_OPAQUE, fmark_tag, MB_TAG_DENSE | MB_TAG_CREAT, &mval );MB_CHK_SET_ERR( result, "Couldn't create mark tag" );
00967 
00968         std::vector< EntityHandle > tmp_face_cells, storage;
00969         std::vector< int > iface_connect, iface_cells;
00970         EntityHandle tmp_connect[CN::MAX_NODES_PER_ELEMENT];  // tmp connect vector
00971         const EntityHandle *connectc, *oconnectc;
00972         int num_connectc;  // Cell connectivity
00973         const EntityHandle* connectf;
00974         int num_connectf;  // Face connectivity
00975 
00976         for( i = 0, rit = all_elems.begin(); i < num_elems; i++, ++rit )
00977         {
00978             EntityType etype = TYPE_FROM_HANDLE( *rit );
00979 
00980             //-----------------------
00981             // If not polyh, get mark
00982             //-----------------------
00983             if( MBPOLYHEDRON != etype && MBPOLYGON != etype )
00984             {
00985                 result = mbImpl->tag_get_data( fmark_tag, &( *rit ), 1, &mval );MB_CHK_SET_ERR( result, "Couldn't get mark data" );
00986             }
00987 
00988             //-----------------------
00989             // Get cell connectivity, and whether it's a polyhedron
00990             //-----------------------
00991             result = mbImpl->get_connectivity( *rit, connectc, num_connectc, false, &storage );MB_CHK_SET_ERR( result, "Couldn't get entity connectivity" );
00992 
00993             // If polyh, write faces directly
00994             bool is_polyh = ( MBPOLYHEDRON == etype );
00995 
00996             int num_facets = ( is_polyh ? num_connectc : CN::NumSubEntities( etype, mDimension - 1 ) );
00997 
00998             //----------------------------------------------------------
00999             // Loop over each facet of element, outputting it if not marked
01000             //----------------------------------------------------------
01001             for( int f = 0; f < num_facets; f++ )
01002             {
01003                 //.............................................
01004                 // If this face marked, skip
01005                 //.............................................
01006                 if( !is_polyh && ( ( mval >> f ) & 0x1 ) ) continue;
01007 
01008                 //.................
01009                 // Get face connect and adj cells
01010                 //.................
01011                 if( !is_polyh )
01012                 {
01013                     // (from CN)
01014                     CN::SubEntityConn( connectc, etype, mDimension - 1, f, tmp_connect, num_connectf );
01015                     connectf = tmp_connect;
01016                 }
01017                 else
01018                 {
01019                     // Directly
01020                     result = mbImpl->get_connectivity( connectc[f], connectf, num_connectf, false );MB_CHK_SET_ERR( result, "Couldn't get polyhedron connectivity" );
01021                 }
01022 
01023                 //............................
01024                 // Get adj cells from face connect (same for poly's and not, since both usually
01025                 // go through vertices anyway)
01026                 //............................
01027                 tmp_face_cells.clear();
01028                 result = mbImpl->get_adjacencies( connectf, num_connectf, mDimension, false, tmp_face_cells );MB_CHK_SET_ERR( result, "Error getting adj hexes" );
01029 
01030                 //...............................
01031                 // If this face only bounds one cell, skip, since we exported external faces
01032                 // before this loop
01033                 //...............................
01034                 if( tmp_face_cells.size() != 2 ) continue;
01035 
01036                 //.................
01037                 // Switch cells so that *rit is always 1st (face connectivity is always written such
01038                 // that that one is with forward sense)
01039                 //.................
01040                 int side_num = 0, sense = 0, offset = 0;
01041                 if( !is_polyh && tmp_face_cells[0] != *rit )
01042                 {
01043                     EntityHandle tmph = tmp_face_cells[0];
01044                     tmp_face_cells[0] = tmp_face_cells[1];
01045                     tmp_face_cells[1] = tmph;
01046                 }
01047 
01048                 //.................
01049                 // Save ids of cells
01050                 //.................
01051                 assert( tmp_face_cells[0] != tmp_face_cells[1] );
01052                 iface_cells.resize( iface_cells.size() + 2 );
01053                 result = mbImpl->tag_get_data( mGlobalIdTag, &tmp_face_cells[0], tmp_face_cells.size(),
01054                                                &iface_cells[iface_cells.size() - 2] );MB_CHK_SET_ERR( result, "Trouble getting global ids for bounded cells" );
01055                 iface_connect.push_back( num_connectf );
01056 
01057                 //.................
01058                 // Save indices of face vertices
01059                 //.................
01060                 unsigned int tmp_size = iface_connect.size();
01061                 iface_connect.resize( tmp_size + num_connectf );
01062                 result = mbImpl->tag_get_data( mGlobalIdTag, connectf, num_connectf, &iface_connect[tmp_size] );MB_CHK_SET_ERR( result, "Trouble getting global id for internal face" );
01063 
01064                 //.................
01065                 // Mark other cell with the right side #
01066                 //.................
01067                 if( !is_polyh )
01068                 {
01069                     // Mark other cell for this face, if there is another cell
01070 
01071                     result = mbImpl->get_connectivity( tmp_face_cells[1], oconnectc, num_connectc, false, &storage );MB_CHK_SET_ERR( result, "Couldn't get other entity connectivity" );
01072 
01073                     // Get side number in other cell
01074                     CN::SideNumber( TYPE_FROM_HANDLE( tmp_face_cells[1] ), oconnectc, connectf, num_connectf,
01075                                     mDimension - 1, side_num, sense, offset );
01076                     // Set mark for that face on the other cell
01077                     result = mbImpl->tag_get_data( fmark_tag, &tmp_face_cells[1], 1, &omval );MB_CHK_SET_ERR( result, "Couldn't get mark data for other cell" );
01078                 }
01079 
01080                 omval |= ( 0x1 << (unsigned int)side_num );
01081                 result = mbImpl->tag_set_data( fmark_tag, &tmp_face_cells[1], 1, &omval );MB_CHK_SET_ERR( result, "Couldn't set mark data for other cell" );
01082             }  // Loop over faces in elem
01083         }      // Loop over elems
01084 
01085         //================================================
01086         // Write internal faces
01087         //================================================
01088 
01089         CCMIOID mapID;
01090         CCMIONewEntity( &error, rootID, kCCMIOMap, NULL, &mapID );
01091         CHK_SET_CCMERR( error, "Trouble creating Internal Face map node" );
01092 
01093         unsigned int num_ifaces = iface_cells.size() / 2;
01094 
01095         // Set gids for internal faces; reuse egids
01096         egids.resize( num_ifaces );
01097         for( i = 1; i <= num_ifaces; i++ )
01098             egids[i - 1] = fmaxid + i;
01099         CCMIOWriteMap( &error, mapID, CCMIOSIZEC( num_ifaces ), CCMIOSIZEC( fmaxid + num_ifaces ), &egids[0],
01100                        CCMIOINDEXC( kCCMIOStart ), CCMIOINDEXC( kCCMIOEnd ) );
01101         CHK_SET_CCMERR( error, "Trouble writing Internal Face map node" );
01102 
01103         CCMIOID id;
01104         CCMIONewEntity( &error, topologyID, kCCMIOInternalFaces, "Internal faces", &id );
01105         CHK_SET_CCMERR( error, "Failed to create Internal face node under Topology node" );
01106         CCMIOWriteFaces( &error, id, kCCMIOInternalFaces, mapID, CCMIOSIZEC( iface_connect.size() ), &iface_connect[0],
01107                          CCMIOINDEXC( kCCMIOStart ), CCMIOINDEXC( kCCMIOEnd ) );
01108         CHK_SET_CCMERR( error, "Failure writing Internal face connectivity" );
01109         CCMIOWriteFaceCells( &error, id, kCCMIOInternalFaces, mapID, &iface_cells[0], CCMIOINDEXC( kCCMIOStart ),
01110                              CCMIOINDEXC( kCCMIOEnd ) );
01111         CHK_SET_CCMERR( error, "Failure writing Internal face cells" );
01112     }
01113 
01114     return MB_SUCCESS;
01115 }
01116 
01117 int WriteCCMIO::moab_to_ccmio_type( EntityType etype, int has_mid_nodes[] )
01118 {
01119     int ctype = -1;
01120     if( has_mid_nodes[0] || has_mid_nodes[2] || has_mid_nodes[3] ) return ctype;
01121 
01122     switch( etype )
01123     {
01124         case MBVERTEX:
01125             ctype = 1;
01126             break;
01127         case MBEDGE:
01128             if( !has_mid_nodes[1] )
01129                 ctype = 2;
01130             else
01131                 ctype = 28;
01132             break;
01133         case MBQUAD:
01134             if( has_mid_nodes[1] )
01135                 ctype = 4;
01136             else
01137                 ctype = 3;
01138             break;
01139         case MBTET:
01140             if( has_mid_nodes[1] )
01141                 ctype = 23;
01142             else
01143                 ctype = 13;
01144             break;
01145         case MBPRISM:
01146             if( has_mid_nodes[1] )
01147                 ctype = 22;
01148             else
01149                 ctype = 12;
01150             break;
01151         case MBPYRAMID:
01152             if( has_mid_nodes[1] )
01153                 ctype = 24;
01154             else
01155                 ctype = 14;
01156             break;
01157         case MBHEX:
01158             if( has_mid_nodes[1] )
01159                 ctype = 21;
01160             else
01161                 ctype = 11;
01162             break;
01163         case MBPOLYHEDRON:
01164             ctype = 255;
01165             break;
01166         default:
01167             break;
01168     }
01169 
01170     return ctype;
01171 }
01172 
01173 ErrorCode WriteCCMIO::write_external_faces( CCMIOID rootID, CCMIOID topologyID, int set_num, Range& facets )
01174 {
01175     CCMIOError error = kCCMIONoErr;
01176     CCMIOID mapID, id;
01177 
01178     // Get gids for these faces
01179     int *gids        = NULL, minid, maxid;
01180     ErrorCode result = get_gids( facets, gids, minid, maxid );MB_CHK_SET_ERR( result, "Trouble getting global ids for facets" );
01181 
01182     // Write the face id map
01183     CCMIONewEntity( &error, rootID, kCCMIOMap, NULL, &mapID );
01184     CHK_SET_CCMERR( error, "Problem creating face id map" );
01185 
01186     CCMIOWriteMap( &error, mapID, CCMIOSIZEC( facets.size() ), CCMIOSIZEC( maxid ), gids, CCMIOINDEXC( kCCMIOStart ),
01187                    CCMIOINDEXC( kCCMIOEnd ) );
01188     CHK_SET_CCMERR( error, "Problem writing face id map" );
01189 
01190     // Get the connectivity of the faces; set size by how many verts in last facet
01191     const EntityHandle* connect;
01192     int num_connect;
01193     result = mbImpl->get_connectivity( *facets.rbegin(), connect, num_connect );MB_CHK_SET_ERR( result, "Failed to get connectivity of last facet" );
01194     std::vector< int > fconnect( facets.size() * ( num_connect + 1 ) );
01195 
01196     result = mWriteIface->get_element_connect( facets.begin(), facets.end(), num_connect, mGlobalIdTag, fconnect.size(),
01197                                                &fconnect[0], true );MB_CHK_SET_ERR( result, "Failed to get facet connectivity" );
01198 
01199     // Get and write a new external face entity
01200     CCMIONewIndexedEntity( &error, topologyID, kCCMIOBoundaryFaces, set_num, "Boundary faces", &id );
01201     CHK_SET_CCMERR( error, "Problem creating boundary face entity" );
01202 
01203     CCMIOWriteFaces( &error, id, kCCMIOBoundaryFaces, mapID, CCMIOSIZEC( fconnect.size() ), &fconnect[0],
01204                      CCMIOINDEXC( kCCMIOStart ), CCMIOINDEXC( kCCMIOEnd ) );
01205     CHK_SET_CCMERR( error, "Problem writing boundary faces" );
01206 
01207     // Get info on bounding cells; reuse fconnect
01208     std::vector< EntityHandle > cells;
01209     unsigned char cmarks[2];
01210     int i, j = 0;
01211     Range dead_facets;
01212     Range::iterator rit;
01213 
01214     // About error checking in this loop: if any facets have no bounding cells,
01215     // this is an error, since global ids for facets are computed outside this loop
01216     for( rit = facets.begin(), i = 0; rit != facets.end(); ++rit, i++ )
01217     {
01218         cells.clear();
01219 
01220         // Get cell then gid of cell
01221         result = mbImpl->get_adjacencies( &( *rit ), 1, mDimension, false, cells );MB_CHK_SET_ERR( result, "Trouble getting bounding cells" );
01222         if( cells.empty() ) { MB_SET_ERR( MB_FILE_WRITE_ERROR, "External facet with no output bounding cell" ); }
01223 
01224         // Check we don't bound more than one cell being output
01225         result = mbImpl->tag_get_data( mEntityMark, &cells[0], cells.size(), cmarks );MB_CHK_SET_ERR( result, "Trouble getting mark tags on cells bounding facets" );
01226         if( cells.size() == 2 && ( mWholeMesh || ( cmarks[0] && cmarks[1] ) ) )
01227         {
01228             MB_SET_ERR( MB_FILE_WRITE_ERROR, "External facet with two output bounding cells" );
01229         }
01230         else if( 1 == cells.size() && !mWholeMesh && !cmarks[0] )
01231         {
01232             MB_SET_ERR( MB_FILE_WRITE_ERROR, "External facet with no output bounding cells" );
01233         }
01234 
01235         // Make sure 1st cell is the one being output
01236         if( 2 == cells.size() && !( cmarks[0] | 0x0 ) && ( cmarks[1] & 0x1 ) ) cells[0] = cells[1];
01237 
01238         // Get gid for bounded cell
01239         result = mbImpl->tag_get_data( mGlobalIdTag, &cells[0], 1, &fconnect[j] );MB_CHK_SET_ERR( result, "Couldn't get global id tag for bounded cell" );
01240 
01241         j++;
01242     }
01243 
01244     // Write the bounding cell data
01245     CCMIOWriteFaceCells( &error, id, kCCMIOBoundaryFaces, mapID, &fconnect[0], CCMIOINDEXC( kCCMIOStart ),
01246                          CCMIOINDEXC( kCCMIOEnd ) );
01247     CHK_SET_CCMERR( error, "Problem writing boundary cell data" );
01248 
01249     return MB_SUCCESS;
01250 }
01251 
01252 ErrorCode WriteCCMIO::get_neuset_elems( EntityHandle neuset, int current_sense, Range& forward_elems,
01253                                         Range& reverse_elems )
01254 {
01255     Range neuset_elems, neuset_meshsets;
01256 
01257     // Get the sense tag; don't need to check return, might be an error if the tag
01258     // hasn't been created yet
01259     Tag sense_tag = 0;
01260     mbImpl->tag_get_handle( "SENSE", 1, MB_TYPE_INTEGER, sense_tag );
01261 
01262     // Get the entities in this set, non-recursive
01263     ErrorCode result = mbImpl->get_entities_by_handle( neuset, neuset_elems );
01264     if( MB_FAILURE == result ) return result;
01265 
01266     // Now remove the meshsets into the neuset_meshsets; first find the first meshset,
01267     Range::iterator range_iter = neuset_elems.begin();
01268     while( TYPE_FROM_HANDLE( *range_iter ) != MBENTITYSET && range_iter != neuset_elems.end() )
01269         ++range_iter;
01270 
01271     // Then, if there are some, copy them into neuset_meshsets and erase from neuset_elems
01272     if( range_iter != neuset_elems.end() )
01273     {
01274         std::copy( range_iter, neuset_elems.end(), range_inserter( neuset_meshsets ) );
01275         neuset_elems.erase( range_iter, neuset_elems.end() );
01276     }
01277 
01278     // OK, for the elements, check the sense of this set and copy into the right range
01279     // (if the sense is 0, copy into both ranges)
01280 
01281     // Need to step forward on list until we reach the right dimension
01282     Range::iterator dum_it = neuset_elems.end();
01283     --dum_it;
01284     int target_dim = CN::Dimension( TYPE_FROM_HANDLE( *dum_it ) );
01285     dum_it         = neuset_elems.begin();
01286     while( target_dim != CN::Dimension( TYPE_FROM_HANDLE( *dum_it ) ) && dum_it != neuset_elems.end() )
01287         ++dum_it;
01288 
01289     if( current_sense == 1 || current_sense == 0 )
01290         std::copy( dum_it, neuset_elems.end(), range_inserter( forward_elems ) );
01291     if( current_sense == -1 || current_sense == 0 )
01292         std::copy( dum_it, neuset_elems.end(), range_inserter( reverse_elems ) );
01293 
01294     // Now loop over the contained meshsets, getting the sense of those and calling this
01295     // function recursively
01296     for( range_iter = neuset_meshsets.begin(); range_iter != neuset_meshsets.end(); ++range_iter )
01297     {
01298         // First get the sense; if it's not there, by convention it's forward
01299         int this_sense;
01300         if( 0 == sense_tag || MB_FAILURE == mbImpl->tag_get_data( sense_tag, &( *range_iter ), 1, &this_sense ) )
01301             this_sense = 1;
01302 
01303         // Now get all the entities on this meshset, with the proper (possibly reversed) sense
01304         get_neuset_elems( *range_iter, this_sense * current_sense, forward_elems, reverse_elems );
01305     }
01306 
01307     return result;
01308 }
01309 }  // namespace moab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines