![]() |
Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
00001 /** @example ComputeTriDual.cpp \n
00002 * \brief Compute the polygonal (dual) mesh of the primal simplex grid in 2-D. \n
00003 * To run: ComputeTriDual input_file output_file \n
00004 * An example to demonstrate computing the dual polygonal grid of a triangulation
00005 * on a spherical surface.
00006 */
00007
00008 #include
00009 #include
00010
00011 // Include header for MOAB instance and tag conventions for
00012 #include "moab/Interface.hpp"
00013 #include "moab/Range.hpp"
00014 #include "moab/ProgOptions.hpp"
00015 #include "moab/CartVect.hpp"
00016 #include "moab/Core.hpp"
00017 #include "moab/ReadUtilIface.hpp"
00018
00019 #ifdef MOAB_HAVE_MPI
00020 #include "moab/ParallelComm.hpp"
00021 #endif
00022
00023 ///////////////////////////////////////////////////////////////////////////////
00024
00025 moab::ErrorCode compute_dual_mesh( moab::Interface* mb, moab::EntityHandle& dual_set, moab::Range& cells )
00026 {
00027 moab::ErrorCode rval;
00028
00029 moab::Range verts;
00030 rval = mb->get_connectivity( cells, verts );MB_CHK_SET_ERR( rval, "Failed to get connectivity" );
00031
00032 moab::ReadUtilIface* iface;
00033 rval = mb->query_interface( iface );MB_CHK_SET_ERR( rval, "Can't get reader interface" );
00034
00035 moab::EntityHandle startv;
00036 std::vector< double* > ccenters;
00037 rval = iface->get_node_coords( 3, cells.size(), 0, startv, ccenters );MB_CHK_SET_ERR( rval, "Can't get node coords" );
00038
00039 moab::Tag gidTag = mb->globalId_tag();
00040
00041 std::vector< int > gids( cells.size() );
00042 rval = mb->get_coords( cells, ccenters[0], ccenters[1], ccenters[2] );MB_CHK_SET_ERR( rval, "Failed to get coordinates" );
00043 rval = mb->tag_get_data( gidTag, cells, &gids[0] );MB_CHK_SET_ERR( rval, "Can't set global_id tag" );
00044
00045 moab::Range dualverts( startv, startv + cells.size() - 1 );
00046 rval = mb->add_entities( dual_set, dualverts );MB_CHK_SET_ERR( rval, "Can't add entities" );
00047 rval = mb->tag_set_data( gidTag, dualverts, &gids[0] );MB_CHK_SET_ERR( rval, "Can't set global_id tag" );
00048
00049 #define CC( ind ) moab::CartVect( ccenters[0][ind], ccenters[1][ind], ccenters[2][ind] )
00050 #define CCXMY( ind, cv ) \
00051 moab::CartVect( ccenters[0][ind] - ( cv )[0], ccenters[1][ind] - ( cv )[1], ccenters[2][ind] - ( cv )[2] )
00052
00053 const moab::EntityHandle svtx = *( cells.begin() );
00054
00055 // maintain block-wise polygon elements
00056 moab::Range dualcells;
00057 std::map< size_t, std::vector< moab::EntityHandle > > polygonConn;
00058 // Generate new Face array
00059 for( moab::Range::iterator vit = verts.begin(); vit != verts.end(); ++vit )
00060 {
00061 moab::EntityHandle vtx = *vit;
00062
00063 std::vector< moab::EntityHandle > adjs;
00064 // generate all required adjacencies
00065 rval = mb->get_adjacencies( &vtx, 1, 2, true, adjs );MB_CHK_SET_ERR( rval, "Failed to get adjacencies" );
00066 const size_t nEdges = adjs.size();
00067
00068 double vxyz[3];
00069 rval = mb->get_coords( &vtx, 1, vxyz );MB_CHK_SET_ERR( rval, "Failed to get coordinates" );
00070
00071 // Reorient Faces
00072 moab::CartVect nodeCentral( vxyz );
00073 moab::CartVect noderef = CC( adjs[0] - svtx );
00074 moab::CartVect node0 = noderef - nodeCentral;
00075 double dNode0Mag = node0.length();
00076
00077 moab::CartVect nodeCross = noderef * nodeCentral;
00078
00079 // Determine the angles about the central Node of each Face Node
00080 std::vector< double > dAngles;
00081 dAngles.resize( nEdges );
00082 dAngles[0] = 0.0;
00083
00084 for( size_t j = 1; j < nEdges; j++ )
00085 {
00086 moab::CartVect nodeDiff = CCXMY( adjs[j] - svtx, nodeCentral );
00087 double dNodeDiffMag = nodeDiff.length();
00088
00089 double dSide = nodeCross % nodeDiff;
00090 double dDotNorm = ( node0 % nodeDiff ) / ( dNode0Mag * dNodeDiffMag );
00091
00092 // double dAngle;
00093 if( dDotNorm > 1.0 )
00094 {
00095 dDotNorm = 1.0;
00096 }
00097
00098 dAngles[j] = acos( dDotNorm );
00099
00100 if( dSide > 0.0 )
00101 {
00102 dAngles[j] = -dAngles[j] + 2.0 * M_PI;
00103 }
00104 }
00105
00106 std::vector< moab::EntityHandle >& face = polygonConn[nEdges];
00107 if( face.size() == 0 ) face.reserve( nEdges * verts.size() / 4 );
00108 face.push_back( dualverts[adjs[0] - svtx] );
00109
00110 // Orient each Face by putting Nodes in order of increasing angle
00111 double dCurrentAngle = 0.0;
00112 for( size_t j = 1; j < nEdges; j++ )
00113 {
00114 int ixNextNode = 1;
00115 double dNextAngle = 2.0 * M_PI;
00116
00117 for( size_t k = 1; k < nEdges; k++ )
00118 {
00119 if( ( dAngles[k] > dCurrentAngle ) && ( dAngles[k] < dNextAngle ) )
00120 {
00121 ixNextNode = k;
00122 dNextAngle = dAngles[k];
00123 }
00124 }
00125
00126 face.push_back( dualverts[adjs[ixNextNode] - svtx] );
00127 dCurrentAngle = dNextAngle;
00128 }
00129 }
00130
00131 std::map< size_t, std::vector< moab::EntityHandle > >::iterator eit;
00132 for( eit = polygonConn.begin(); eit != polygonConn.end(); ++eit )
00133 {
00134 const size_t nVPerE = eit->first;
00135 const size_t nElePerType = static_cast< int >( eit->second.size() / nVPerE );
00136
00137 moab::EntityHandle starte; // Connectivity
00138 moab::EntityHandle* conn;
00139
00140 rval = iface->get_element_connect( nElePerType, eit->first, moab::MBPOLYGON, 0, starte, conn );MB_CHK_SET_ERR( rval, "Can't get element connectivity" );
00141
00142 // copy the connectivity that we have accumulated
00143 std::copy( eit->second.begin(), eit->second.end(), conn );
00144 eit->second.clear();
00145
00146 // add this polygon sequence to the aggregate data
00147 moab::Range mbcells( starte, starte + nElePerType - 1 );
00148 dualcells.merge( mbcells );
00149 }
00150
00151 // add the computed dual cells to mesh
00152 rval = mb->add_entities( dual_set, dualcells );MB_CHK_SET_ERR( rval, "Can't add polygonal entities" );
00153
00154 // Assign global IDs to all the dual cells - same as original vertices
00155 assert( dualcells.size() == verts.size() );
00156 gids.resize( verts.size() );
00157 rval = mb->tag_get_data( gidTag, verts, &gids[0] );MB_CHK_SET_ERR( rval, "Can't set global_id tag" );
00158 if( gids[0] == gids[1] && gids[0] < 0 )
00159 {
00160 #ifdef MOAB_HAVE_MPI
00161 moab::ParallelComm pcomm( mb, MPI_COMM_WORLD );
00162
00163 rval = pcomm.assign_global_ids( dual_set, 2, 1, false, true, true );MB_CHK_SET_ERR( rval, "Can't assign global_ids" );
00164 #else
00165 // No global ID assigned to input vertices.
00166 // Can we use std::iota ??
00167 for( size_t ix = 0; ix < gids.size(); ++ix )
00168 gids[ix] = ix + 1;
00169
00170 // set GID tag
00171 rval = mb->tag_set_data( gidTag, dualcells, &gids[0] );MB_CHK_SET_ERR( rval, "Can't set global_id tag" );
00172 std::cout << "GIDs: " << gids[0] << " " << gids[1] << " " << gids[2] << " " << gids[3] << " " << gids[4] << " "
00173 << gids[5] << "\n";
00174 #endif
00175 }
00176 gids.clear();
00177
00178 // delete the original entities from the mesh
00179 rval = mb->delete_entities( cells );MB_CHK_SET_ERR( rval, "Can't remove entities" );
00180 rval = mb->delete_entities( verts );MB_CHK_SET_ERR( rval, "Can't remove entities" );
00181
00182 return moab::MB_SUCCESS;
00183 }
00184
00185 ///////////////////////////////////////////////////////////////////////////////
00186
00187 int main( int argc, char** argv )
00188 {
00189 moab::ErrorCode rval;
00190 ProgOptions opts;
00191
00192 // Get MOAB instance
00193 moab::Interface* mb = new( std::nothrow ) moab::Core;
00194 if( NULL == mb ) return 1;
00195
00196 std::string inputFile = std::string( MESH_DIR ) + "/globalmpas_deltri.h5m";
00197 opts.addOpt< std::string >( "inFile,i", "Specify the input file name string ", &inputFile );
00198 #ifdef MOAB_HAVE_HDF5
00199 std::string outputFile = "outDualMesh.h5m";
00200 #else
00201 std::string outputFile = "outDualMesh.vtk";
00202 #endif
00203 opts.addOpt< std::string >( "outFile,o", "Specify the input file name string ", &outputFile );
00204
00205 opts.parseCommandLine( argc, argv );
00206
00207 moab::EntityHandle triangle_set, dual_set;
00208 rval = mb->create_meshset( moab::MESHSET_SET, triangle_set );MB_CHK_SET_ERR( rval, "Can't create new set" );
00209 rval = mb->create_meshset( moab::MESHSET_SET, dual_set );MB_CHK_SET_ERR( rval, "Can't create new set" );
00210
00211 // This file is in the mesh files directory
00212 const char* readopts = "";
00213 rval = mb->load_file( inputFile.c_str(), &triangle_set, readopts );MB_CHK_SET_ERR( rval, "Failed to read" );
00214
00215 // get all cells of dimension 2;
00216 moab::Range cells;
00217 rval = mb->get_entities_by_dimension( triangle_set, 2, cells );MB_CHK_SET_ERR( rval, "Failed to get cells" );
00218
00219 std::cout << "Original number of triangular cells : " << cells.size() << "\n";
00220
00221 // call the routine to compute the dual grid
00222 rval = compute_dual_mesh( mb, dual_set, cells );MB_CHK_SET_ERR( rval, "Failed to compute dual mesh" );
00223
00224 // write the mesh to disk
00225 rval = mb->write_file( outputFile.c_str() );MB_CHK_SET_ERR( rval, "Failed to write new file" );
00226
00227 cells.clear();
00228 rval = mb->get_entities_by_dimension( dual_set, 2, cells );MB_CHK_SET_ERR( rval, "Failed to get cells" );
00229 std::cout << "Wrote the dual mesh: " << outputFile << " containing " << cells.size() << " polygonal cells\n";
00230
00231 delete mb;
00232
00233 return 0;
00234 }