![]() |
Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
#include <MeshGeneration.hpp>
Classes | |
struct | BrickOpts |
Public Member Functions | |
MeshGeneration (Interface *mbi, EntityHandle rset=0) | |
virtual | ~MeshGeneration () |
ErrorCode | BrickInstance (BrickOpts &opts) |
Private Attributes | |
Interface * | mb |
EntityHandle | cset |
Definition at line 18 of file MeshGeneration.hpp.
moab::MeshGeneration::MeshGeneration | ( | Interface * | mbi, |
EntityHandle | rset = 0 |
||
) |
Definition at line 30 of file MeshGeneration.cpp.
References moab::ParallelComm::get_pcomm(), and mb.
: mb( impl ),
#ifdef MOAB_HAVE_MPI
pc( comm ),
#endif
cset( rset )
{
// ErrorCode error;
#ifdef MOAB_HAVE_MPI
// Get the Parallel Comm instance to prepare all new sets to work in parallel
// in case the user did not provide any arguments
if( !comm ) pc = moab::ParallelComm::get_pcomm( mb, 0 );
#endif
}
moab::MeshGeneration::~MeshGeneration | ( | ) | [virtual] |
Definition at line 50 of file MeshGeneration.cpp.
{}
Definition at line 52 of file MeshGeneration.cpp.
References moab::MeshGeneration::BrickOpts::A, moab::Interface::add_entities(), moab::MeshGeneration::BrickOpts::adjEnts, moab::MeshGeneration::BrickOpts::B, moab::Range::begin(), moab::MeshGeneration::BrickOpts::blockSize, moab::MeshGeneration::BrickOpts::C, CC, moab::Interface::create_meshset(), cset, moab::E, moab::Range::end(), ErrorCode, moab::F, moab::Interface::get_adjacencies(), moab::ReadUtilIface::get_element_connect(), moab::Interface::get_entities_by_dimension(), moab::ReadUtilIface::get_node_coords(), moab::MeshGeneration::BrickOpts::GL, iface, moab::Range::insert(), moab::MeshGeneration::BrickOpts::K, moab::MeshGeneration::BrickOpts::keep_skins, moab::MeshGeneration::BrickOpts::M, mb, MB_CHK_ERR, MB_CHK_SET_ERR, MB_SUCCESS, MB_TAG_CREAT, MB_TAG_DENSE, MB_TAG_SPARSE, MB_TYPE_INTEGER, MB_TYPE_OPAQUE, MBHEX, MBTET, moab::ParallelMergeMesh::merge(), moab::Range::merge(), moab::MergeMesh::merge_entities(), moab::MergeMesh::merge_using_integer_tag(), MESHSET_SET, moab::MeshGeneration::BrickOpts::N, moab::MeshGeneration::BrickOpts::newMergeMethod, moab::MeshGeneration::BrickOpts::parmerge, moab::Range::print(), moab::MeshGeneration::BrickOpts::quadratic, moab::Interface::query_interface(), moab::Interface::remove_entities(), size, moab::Range::size(), moab::Interface::tag_delete(), moab::Interface::tag_get_handle(), moab::Interface::tag_set_data(), moab::MeshGeneration::BrickOpts::tetra, moab::Interface::UNION, moab::ReadUtilIface::update_adjacencies(), moab::MeshGeneration::BrickOpts::xsize, moab::MeshGeneration::BrickOpts::ysize, and moab::MeshGeneration::BrickOpts::zsize.
Referenced by main().
{
int A = opts.A, B = opts.B, C = opts.C, M = opts.M, N = opts.N, K = opts.K;
int blockSize = opts.blockSize;
double xsize = opts.xsize, ysize = opts.ysize, zsize = opts.zsize; // The size of the region
bool newMergeMethod = opts.newMergeMethod;
bool quadratic = opts.quadratic;
bool tetra = opts.tetra;
bool adjEnts = opts.adjEnts;
bool parmerge = opts.parmerge;
#ifdef MOAB_HAVE_MPI
int GL = opts.GL; // number of ghost layers
bool keep_skins = opts.keep_skins;
#endif
int rank = 0, size = 1;
#ifndef _MSC_VER /* windows */
clock_t tt = clock();
#endif
#ifdef MOAB_HAVE_MPI
rank = pc->rank();
size = pc->size();
#endif
if( M * N * K != size )
{
if( 0 == rank ) std::cout << "M*N*K = " << M * N * K << " != size = " << size << "\n";
return MB_FAILURE;
}
// Determine m, n, k for processor rank
int m, n, k;
k = rank / ( M * N );
int leftover = rank % ( M * N );
n = leftover / M;
m = leftover % M;
// Used for nodes increments
int q = ( quadratic ) ? 2 : 1;
// Used for element increments
int factor = ( tetra ) ? 6 : 1;
double dx = xsize / ( A * M * blockSize * q ); // Distance between 2 nodes in x direction
double dy = ysize / ( B * N * blockSize * q ); // Distance between 2 nodes in y direction
double dz = zsize / ( C * K * blockSize * q ); // Distance between 2 nodes in z direction
int NX = ( q * M * A * blockSize + 1 );
int NY = ( q * N * B * blockSize + 1 );
int nex = M * A * blockSize; // Number of elements in x direction, used for global id on element
int ney = N * B * blockSize; // Number of elements in y direction ...
// int NZ = (K * C * blockSize + 1); // Not used
int blockSize1 = q * blockSize + 1; // Used for vertices
long num_total_verts = (long)NX * NY * ( K * C * blockSize + 1 );
if( 0 == rank )
{
std::cout << "Generate mesh on " << size << " processors \n";
std::cout << "Total number of vertices: " << num_total_verts << "\n";
}
// int xstride = 1;
int ystride = blockSize1;
int zstride = blockSize1 * blockSize1;
// Generate the block at (a, b, c); it will represent a partition, it will get a partition tag
ReadUtilIface* iface;
ErrorCode rval = mb->query_interface( iface );MB_CHK_SET_ERR( rval, "Can't get reader interface" );
Tag global_id_tag;
rval = mb->tag_get_handle( "GLOBAL_ID", 1, MB_TYPE_INTEGER, global_id_tag );MB_CHK_SET_ERR( rval, "Can't get global id tag" );
// set global ids
Tag new_id_tag;
if( !parmerge )
{
rval =
mb->tag_get_handle( "HANDLEID", sizeof( long ), MB_TYPE_OPAQUE, new_id_tag, MB_TAG_CREAT | MB_TAG_DENSE );MB_CHK_SET_ERR( rval, "Can't get handle id tag" );
}
Tag part_tag;
int dum_id = -1;
rval =
mb->tag_get_handle( "PARALLEL_PARTITION", 1, MB_TYPE_INTEGER, part_tag, MB_TAG_CREAT | MB_TAG_SPARSE, &dum_id );MB_CHK_SET_ERR( rval, "Can't get parallel partition tag" );
Range wsets; // write only part sets
Range localVerts;
Range all3dcells;
for( int a = 0; a < A; a++ )
{
for( int b = 0; b < B; b++ )
{
for( int c = 0; c < C; c++ )
{
// We will generate (q*block + 1)^3 vertices, and block^3 hexas; q is 1 for linear,
// 2 for quadratic the global id of the vertices will come from m, n, k, a, b, c x
// will vary from m*A*q*block + a*q*block to m*A*q*block + (a+1)*q*block etc;
int num_nodes = blockSize1 * blockSize1 * blockSize1;
vector< double* > arrays;
EntityHandle startv;
rval = iface->get_node_coords( 3, num_nodes, 0, startv, arrays );MB_CHK_SET_ERR( rval, "Can't get node coords" );
// Will start with the lower corner:
int x = m * A * q * blockSize + a * q * blockSize;
int y = n * B * q * blockSize + b * q * blockSize;
int z = k * C * q * blockSize + c * q * blockSize;
int ix = 0;
vector< int > gids( num_nodes );
vector< long > lgids( num_nodes );
Range verts( startv, startv + num_nodes - 1 );
for( int kk = 0; kk < blockSize1; kk++ )
{
for( int jj = 0; jj < blockSize1; jj++ )
{
for( int ii = 0; ii < blockSize1; ii++ )
{
arrays[0][ix] = ( x + ii ) * dx;
arrays[1][ix] = ( y + jj ) * dy;
arrays[2][ix] = ( z + kk ) * dz;
gids[ix] = 1 + ( x + ii ) + ( y + jj ) * NX + ( z + kk ) * ( NX * NY );
if( !parmerge )
lgids[ix] = 1 + ( x + ii ) + ( y + jj ) * NX + (long)( z + kk ) * ( NX * NY );
// Set int tags, some nice values?
ix++;
}
}
}
rval = mb->tag_set_data( global_id_tag, verts, &gids[0] );MB_CHK_SET_ERR( rval, "Can't set global ids to vertices" );
if( !parmerge )
{
rval = mb->tag_set_data( new_id_tag, verts, &lgids[0] );MB_CHK_SET_ERR( rval, "Can't set the new handle id tags" );
}
localVerts.merge( verts );
int num_hexas = blockSize * blockSize * blockSize;
int num_el = num_hexas * factor;
EntityHandle starte; // Connectivity
EntityHandle* conn;
int num_v_per_elem = 8;
if( quadratic )
{
num_v_per_elem = 27;
rval = iface->get_element_connect( num_el, 27, MBHEX, 0, starte, conn );MB_CHK_SET_ERR( rval, "Can't get element connectivity" );
}
else if( tetra )
{
num_v_per_elem = 4;
rval = iface->get_element_connect( num_el, 4, MBTET, 0, starte, conn );MB_CHK_SET_ERR( rval, "Can't get element connectivity" );
}
else
{
rval = iface->get_element_connect( num_el, 8, MBHEX, 0, starte, conn );MB_CHK_SET_ERR( rval, "Can't get element connectivity" );
}
Range cells( starte, starte + num_el - 1 ); // Should be elements
// Fill cells
ix = 0;
// Identify the elements at the lower corner, for their global ids
int xe = m * A * blockSize + a * blockSize;
int ye = n * B * blockSize + b * blockSize;
int ze = k * C * blockSize + c * blockSize;
gids.resize( num_el );
lgids.resize( num_el );
int ie = 0; // Index now in the elements, for global ids
for( int kk = 0; kk < blockSize; kk++ )
{
for( int jj = 0; jj < blockSize; jj++ )
{
for( int ii = 0; ii < blockSize; ii++ )
{
EntityHandle corner = startv + q * ii + q * jj * ystride + q * kk * zstride;
// These could overflow for large numbers
gids[ie] = 1 + ( ( xe + ii ) + ( ye + jj ) * nex + ( ze + kk ) * ( nex * ney ) ) *
factor; // 6 more for tetra
lgids[ie] = 1 + ( ( xe + ii ) + ( ye + jj ) * nex + (long)( ze + kk ) * ( nex * ney ) ) *
factor; // 6 more for tetra
// EntityHandle eh = starte + ie;
ie++;
if( quadratic )
{
// 4 ----- 19 ----- 7
// . | . |
// 16 25 18 |
// . | . |
// 5 ----- 17 ----- 6 |
// | 12 | 23 15
// | | |
// | 20 | 26 | 22 |
// | | |
// 13 21 | 14 |
// | 0 ----- 11 ----- 3
// | . | .
// | 8 24 | 10
// | . | .
// 1 ----- 9 ----- 2
//
conn[ix] = corner;
conn[ix + 1] = corner + 2;
conn[ix + 2] = corner + 2 + 2 * ystride;
conn[ix + 3] = corner + 2 * ystride;
conn[ix + 4] = corner + 2 * zstride;
conn[ix + 5] = corner + 2 + 2 * zstride;
conn[ix + 6] = corner + 2 + 2 * ystride + 2 * zstride;
conn[ix + 7] = corner + 2 * ystride + 2 * zstride;
conn[ix + 8] = corner + 1; // 0-1
conn[ix + 9] = corner + 2 + ystride; // 1-2
conn[ix + 10] = corner + 1 + 2 * ystride; // 2-3
conn[ix + 11] = corner + ystride; // 3-0
conn[ix + 12] = corner + zstride; // 0-4
conn[ix + 13] = corner + 2 + zstride; // 1-5
conn[ix + 14] = corner + 2 + 2 * ystride + zstride; // 2-6
conn[ix + 15] = corner + 2 * ystride + zstride; // 3-7
conn[ix + 16] = corner + 1 + 2 * zstride; // 4-5
conn[ix + 17] = corner + 2 + ystride + 2 * zstride; // 5-6
conn[ix + 18] = corner + 1 + 2 * ystride + 2 * zstride; // 6-7
conn[ix + 19] = corner + ystride + 2 * zstride; // 4-7
conn[ix + 20] = corner + 1 + zstride; // 0154
conn[ix + 21] = corner + 2 + ystride + zstride; // 1265
conn[ix + 22] = corner + 1 + 2 * ystride + zstride; // 2376
conn[ix + 23] = corner + ystride + zstride; // 0374
conn[ix + 24] = corner + 1 + ystride; // 0123
conn[ix + 25] = corner + 1 + ystride + 2 * zstride; // 4567
conn[ix + 26] = corner + 1 + ystride + zstride; // center
ix += 27;
}
else if( tetra )
{
// E H
// F G
//
// A D
// B C
EntityHandle AA = corner;
EntityHandle BB = corner + 1;
EntityHandle CC = corner + 1 + ystride;
EntityHandle D = corner + ystride;
EntityHandle E = corner + zstride;
EntityHandle F = corner + 1 + zstride;
EntityHandle G = corner + 1 + ystride + zstride;
EntityHandle H = corner + ystride + zstride;
// tet EDHG
conn[ix] = E;
conn[ix + 1] = D;
conn[ix + 2] = H;
conn[ix + 3] = G;
// tet ABCF
conn[ix + 4] = AA;
conn[ix + 5] = BB;
conn[ix + 6] = CC;
conn[ix + 7] = F;
// tet ADEF
conn[ix + 8] = AA;
conn[ix + 9] = D;
conn[ix + 10] = E;
conn[ix + 11] = F;
// tet CGDF
conn[ix + 12] = CC;
conn[ix + 13] = G;
conn[ix + 14] = D;
conn[ix + 15] = F;
// tet ACDF
conn[ix + 16] = AA;
conn[ix + 17] = CC;
conn[ix + 18] = D;
conn[ix + 19] = F;
// tet DGEF
conn[ix + 20] = D;
conn[ix + 21] = G;
conn[ix + 22] = E;
conn[ix + 23] = F;
ix += 24;
for( int ff = 0; ff < factor - 1; ff++ )
{
gids[ie] = gids[ie - 1] + 1; // 6 more for tetra
// eh = starte + ie;
ie++;
}
}
else
{ // Linear hex
conn[ix] = corner;
conn[ix + 1] = corner + 1;
conn[ix + 2] = corner + 1 + ystride;
conn[ix + 3] = corner + ystride;
conn[ix + 4] = corner + zstride;
conn[ix + 5] = corner + 1 + zstride;
conn[ix + 6] = corner + 1 + ystride + zstride;
conn[ix + 7] = corner + ystride + zstride;
ix += 8;
}
}
}
}
EntityHandle part_set;
rval = mb->create_meshset( MESHSET_SET, part_set );MB_CHK_SET_ERR( rval, "Can't create mesh set" );
rval = mb->add_entities( part_set, cells );MB_CHK_SET_ERR( rval, "Can't add entities to set" );
all3dcells.merge( cells );
// update adjacencies now, because some elements are new;
rval = iface->update_adjacencies( starte, num_el, num_v_per_elem, conn );MB_CHK_SET_ERR( rval, "Can't update adjacencies" );
// If needed, add all edges and faces
if( adjEnts )
{
// Generate all adj entities dimension 1 and 2 (edges and faces/ tri or qua)
Range edges, faces;
rval = mb->get_adjacencies( cells, 1, true, edges, Interface::UNION );MB_CHK_SET_ERR( rval, "Can't get edges" );
rval = mb->get_adjacencies( cells, 2, true, faces, Interface::UNION );MB_CHK_SET_ERR( rval, "Can't get faces" );
// rval = mb->add_entities(part_set, edges);MB_CHK_SET_ERR(rval, "Can't add
// edges to partition set"); rval = mb->add_entities(part_set,
// faces);MB_CHK_SET_ERR(rval, "Can't add faces to partition set");
}
rval = mb->tag_set_data( global_id_tag, cells, &gids[0] );MB_CHK_SET_ERR( rval, "Can't set global ids to elements" );
if( !parmerge )
{
rval = mb->tag_set_data( new_id_tag, cells, &lgids[0] );MB_CHK_SET_ERR( rval, "Can't set new ids to elements" );
}
int part_num = a + m * A + ( b + n * B ) * ( M * A ) + ( c + k * C ) * ( M * A * N * B );
rval = mb->tag_set_data( part_tag, &part_set, 1, &part_num );MB_CHK_SET_ERR( rval, "Can't set part tag on set" );
wsets.insert( part_set );
}
}
}
mb->add_entities( cset, all3dcells );
rval = mb->add_entities( cset, wsets );MB_CHK_SET_ERR( rval, "Can't add entity sets" );
#ifdef MOAB_HAVE_MPI
pc->partition_sets() = wsets;
#endif
/*
// Before merge locally
rval = mb->write_file("test0.h5m", 0, ";;PARALLEL=WRITE_PART");MB_CHK_SET_ERR(rval, "Can't write
in parallel, before merging");
*/
// After the mesh is generated on each proc, merge the vertices
MergeMesh mm( mb );
// rval = mb->get_entities_by_dimension(0, 3, all3dcells);MB_CHK_SET_ERR(rval, "Can't get all 3d
// cells elements");
if( 0 == rank )
{
#ifndef _MSC_VER /* windows */
std::cout << "generate local mesh: " << ( clock() - tt ) / (double)CLOCKS_PER_SEC << " seconds" << endl;
tt = clock();
#endif
std::cout << "number of elements on rank 0: " << all3dcells.size() << endl;
std::cout << "Total number of elements " << all3dcells.size() * size << endl;
std::cout << "Element type: " << ( tetra ? "MBTET" : "MBHEX" )
<< " order:" << ( quadratic ? "quadratic" : "linear" ) << endl;
}
if( A * B * C != 1 )
{ // Merge needed
if( newMergeMethod )
{
rval = mm.merge_using_integer_tag( localVerts, global_id_tag );MB_CHK_SET_ERR( rval, "Can't merge" );
}
else
{
rval = mm.merge_entities( all3dcells, 0.0001 );MB_CHK_SET_ERR( rval, "Can't merge" );
}
#ifndef _MSC_VER /* windows */
if( 0 == rank )
{
std::cout << "merge locally: " << ( clock() - tt ) / (double)CLOCKS_PER_SEC << " seconds" << endl;
tt = clock();
}
#endif
}
// if adjEnts, add now to each set
if( adjEnts )
{
for( Range::iterator wsit = wsets.begin(); wsit != wsets.end(); ++wsit )
{
EntityHandle ws = *wsit; // write set
Range cells, edges, faces;
rval = mb->get_entities_by_dimension( ws, 3, cells );MB_CHK_SET_ERR( rval, "Can't get cells" );
rval = mb->get_adjacencies( cells, 1, false, edges, Interface::UNION );MB_CHK_SET_ERR( rval, "Can't get edges" );
rval = mb->get_adjacencies( cells, 2, false, faces, Interface::UNION );MB_CHK_SET_ERR( rval, "Can't get faces" );
rval = mb->add_entities( ws, edges );MB_CHK_SET_ERR( rval, "Can't add edges to partition set" );
rval = mb->add_entities( ws, faces );MB_CHK_SET_ERR( rval, "Can't add faces to partition set" );
}
}
#ifdef MOAB_HAVE_MPI
if( size > 1 )
{
// rval = mb->create_meshset(MESHSET_SET, mesh_set);MB_CHK_SET_ERR(rval, "Can't create new
// set");
if( parmerge )
{
ParallelMergeMesh pm( pc, 0.00001 );
rval = pm.merge();MB_CHK_SET_ERR( rval, "Can't resolve shared ents" );
#ifndef _MSC_VER /* windows */
if( 0 == rank )
{
std::cout << "parallel mesh merge: " << ( clock() - tt ) / (double)CLOCKS_PER_SEC << " seconds" << endl;
tt = clock();
}
#endif
}
else
{
rval = pc->resolve_shared_ents( cset, -1, -1, &new_id_tag );MB_CHK_SET_ERR( rval, "Can't resolve shared ents" );
#ifndef _MSC_VER /* windows */
if( 0 == rank )
{
std::cout << "resolve shared entities: " << ( clock() - tt ) / (double)CLOCKS_PER_SEC << " seconds"
<< endl;
tt = clock();
}
#endif
}
if( !keep_skins )
{ // Default is to delete the 1- and 2-dimensional entities
// Delete all quads and edges
Range toDelete;
rval = mb->get_entities_by_dimension( cset, 1, toDelete );MB_CHK_SET_ERR( rval, "Can't get edges" );
rval = mb->get_entities_by_dimension( cset, 2, toDelete );MB_CHK_SET_ERR( rval, "Can't get faces" );
rval = pc->delete_entities( toDelete );MB_CHK_SET_ERR( rval, "Can't delete entities" );
rval = mb->remove_entities( cset, toDelete );MB_CHK_SET_ERR( rval, "Can't remove entities from base set" );
if( 0 == rank )
{
std::cout << "delete edges and faces \n";
toDelete.print( std::cout );
#ifndef _MSC_VER /* windows */
std::cout << ( clock() - tt ) / (double)CLOCKS_PER_SEC << " seconds" << endl;
tt = clock();
#endif
}
}
// do some ghosting if required
if( GL > 0 )
{
rval = pc->exchange_ghost_cells( 3, // int ghost_dim
0, // int bridge_dim
GL, // int num_layers
0, // int addl_ents
true );MB_CHK_ERR( rval ); // bool store_remote_handles
#ifndef _MSC_VER /* windows */
if( 0 == rank )
{
std::cout << "exchange " << GL << " ghost layer(s) :" << ( clock() - tt ) / (double)CLOCKS_PER_SEC
<< " seconds" << endl;
tt = clock();
}
#endif
}
}
#endif
if( !parmerge )
{
rval = mb->tag_delete( new_id_tag );MB_CHK_SET_ERR( rval, "Can't delete new ID tag" );
}
return MB_SUCCESS;
}
EntityHandle moab::MeshGeneration::cset [private] |
Definition at line 53 of file MeshGeneration.hpp.
Referenced by BrickInstance().
Interface* moab::MeshGeneration::mb [private] |
Definition at line 49 of file MeshGeneration.hpp.
Referenced by BrickInstance(), and MeshGeneration().