MeshKit  1.0
ParallelMesher.cpp
Go to the documentation of this file.
00001 #include "meshkit/ParallelMesher.hpp"
00002 #include "meshkit/ModelEnt.hpp"
00003 #include "meshkit/ParExchangeMesh.hpp"
00004 
00005 #include "MBTagConventions.hpp"
00006 #include "MBEntityType.h"
00007 #include "moab/Range.hpp"
00008 #include "moab/Types.hpp"
00009 
00010 #include "RefEntity.hpp"
00011 #include "RefVolume.hpp"
00012 #include "RefFace.hpp"
00013 #include "RefEdge.hpp"
00014 #include "RefVertex.hpp"
00015 #include "CADefines.hpp"
00016 #include "GeometryQueryTool.hpp"
00017 
00018 const bool debug_parallelmesher = false;
00019 
00020 namespace MeshKit
00021 {
00022 // static registration of this mesh scheme
00023 moab::EntityType ParallelMesher_tps[] = {moab::MBVERTEX, moab::MBTRI, moab::MBTET, moab::MBMAXTYPE};
00024 const moab::EntityType* ParallelMesher::output_types()
00025   { return ParallelMesher_tps; }
00026 
00027 ParallelMesher::ParallelMesher(MKCore *mkcore, const MEntVector &me_vec)
00028   : MeshScheme(mkcore, me_vec)
00029 {
00030   // get information related to MOAB parallel communication
00031   m_mpcomm = moab::ParallelComm::get_pcomm(mk_core()->moab_instance(), 0);
00032   if (NULL == m_mpcomm) m_mpcomm = new moab::ParallelComm(mk_core()->moab_instance(), MPI_COMM_WORLD);
00033   m_rank = m_mpcomm->proc_config().proc_rank();
00034 
00035   // create tag
00036   iMesh::Error err = mk_core()->imesh_instance()->createTag("PARALLEL_UNIQUE_ID", 1, iBase_INTEGER, m_mPuniqueIDTag);
00037   IBERRCHK(err, "Trouble create a parallel unique id tag handle.");
00038 
00039   m_sEntity.resize(10);
00040 
00041   if (debug_parallelmesher) m_mpcomm->set_debug_verbosity(5);
00042 }
00043 
00044 ParallelMesher::~ParallelMesher()
00045 {
00046   delete m_mpcomm;
00047 }
00048 
00049 MeshOp *ParallelMesher::get_mesher(PARALLEL_OP_TYPE type)
00050 {
00051   MeshOpProxy* proxy = NULL;
00052   std::vector<MeshOpProxy *> proxies;
00053   if (type == MESH_VERTEX) {
00054     mk_core()->meshop_by_mesh_type(moab::MBVERTEX, proxies);
00055     proxy = *proxies.begin();  }
00056   else if (type == MESH_EDGE) {
00057     mk_core()->meshop_by_mesh_type(moab::MBEDGE, proxies);
00058     proxy = *proxies.begin();
00059   }
00060   else if (type == MESH_INTER_SURF || type == MESH_NINTER_SURF) {
00061     //mk_core()->meshop_by_mesh_type(moab::MBTRI, proxies);
00062     proxy = MKCore::meshop_proxy("AF2DfltTriangleMeshOp");
00063   }
00064   else if (type == MESH_VOLUME) {
00065     //mk_core()->meshop_by_mesh_type(moab::MBTET, proxies);
00066     proxy = MKCore::meshop_proxy("NGTetMesher");
00067   }
00068   else if (type == EXCHANGE_VERTEX || type == EXCHANGE_EDGE) {
00069     proxy = MKCore::meshop_proxy("ParExchangeMesh");
00070   }
00071   else if (type == SEND_POST_SURF_MESH) {
00072     proxy = MKCore::meshop_proxy("ParSendPostSurfMesh");
00073   }
00074   else if (type == RECV_SURF_MESH) {
00075     proxy = MKCore::meshop_proxy("ParRecvSurfMesh");
00076   }
00077 
00078   if (proxy == NULL) throw Error(MK_FAILURE, "Couldn't find a MeshOp capable of producing the given mesh type.");
00079 
00080   return mk_core()->construct_meshop(proxy);
00081 }
00082 
00083 void ParallelMesher::setup_this()
00084 {
00085   // make partitioned and send and receive model entity sets
00086   for (MEntSelection::iterator mit = mentSelection.begin();
00087        mit != mentSelection.end(); mit++) {
00088     ModelEnt *me_vol = (*mit).first;
00089     if (me_vol->dimension() != 3) throw Error(MK_BAD_INPUT, "Parallel mesher assigned to an entity with dimension != 3.");
00090 
00091     RefEntity* vol = reinterpret_cast<RefEntity*> (me_vol->geom_handle());
00092     TDParallel *td_par_vol = (TDParallel *) vol->get_TD(&TDParallel::is_parallel);
00093     if (td_par_vol == NULL) ECERRCHK(MK_FAILURE, "Volume should have partitioned information.");
00094 
00095     unsigned int charge_proc = td_par_vol->get_charge_proc();
00096     MEntVector children;
00097 
00098     // partititoned vols
00099     if (m_rank == charge_proc) {
00100       m_sEntity[MESH_VOLUME].insert(me_vol); // volume
00101       if (debug_parallelmesher) print_geom_info(me_vol, 3, true);
00102 
00103       // get non-interface surfaces
00104       children.clear();
00105       me_vol->get_adjacencies(2, children);
00106       for (MEntVector::iterator cit = children.begin(); cit != children.end(); cit++) {
00107         RefEntity* child = reinterpret_cast< RefEntity* > ((*cit)->geom_handle());
00108         TDParallel *td_par_child = (TDParallel *) child->get_TD(&TDParallel::is_parallel);
00109         if (td_par_child == NULL) {
00110           m_sEntity[MESH_NINTER_SURF].insert(*cit);
00111         }
00112       }
00113     }
00114 
00115     // get child interface entities
00116     for (int i = 2; i > -1; i--) {
00117       children.clear();
00118       me_vol->get_adjacencies(i, children);
00119 
00120       for (MEntVector::iterator cit = children.begin(); cit != children.end(); cit++) {
00121         RefEntity* child = reinterpret_cast< RefEntity* > ((*cit)->geom_handle());
00122         TDParallel *td_par_child = (TDParallel *) child->get_TD(&TDParallel::is_parallel);
00123         if (td_par_child != NULL) {
00124           check_partition(td_par_child, *cit, i);
00125           if (debug_parallelmesher) print_geom_info(*cit, i, m_rank == td_par_child->get_charge_proc());
00126         }
00127       }
00128     }
00129   }
00130 
00131   add_parallel_mesh_op(MESH_VERTEX);
00132   add_parallel_mesh_op(EXCHANGE_VERTEX);
00133   add_parallel_mesh_op(MESH_EDGE);
00134   add_parallel_mesh_op(EXCHANGE_EDGE);
00135   add_parallel_mesh_op(MESH_INTER_SURF);
00136   add_parallel_mesh_op(SEND_POST_SURF_MESH);
00137   add_parallel_mesh_op(MESH_NINTER_SURF);
00138   add_parallel_mesh_op(RECV_SURF_MESH);
00139   add_parallel_mesh_op(MESH_VOLUME);
00140 
00141   if (debug_parallelmesher) {
00142     for (PARALLEL_OP_TYPE type = MESH_VERTEX; type <= MESH_VOLUME;) {
00143       std::cout << "# of parallel mesh type " << type << "="
00144                 << m_sEntity[type].size() << std::endl;
00145       type = static_cast<PARALLEL_OP_TYPE> (type + 1);
00146     }
00147   }
00148 }
00149 
00150 void ParallelMesher::check_partition(TDParallel* td_par, ModelEnt* me, int dim)
00151 {
00152   bool b_partitioned = false;
00153   unsigned int charge_p = td_par->get_charge_proc();
00154   if (m_rank == charge_p) { // charge processor
00155     if (dim == 2) {
00156       m_sEntity[MESH_INTER_SURF].insert(me);
00157       m_sEntity[SEND_POST_SURF_MESH].insert(me);
00158       m_sEntity[RECV_SURF_MESH].insert(me);
00159     }
00160     else if (dim == 1) {
00161       m_sEntity[MESH_EDGE].insert(me);
00162       m_sEntity[EXCHANGE_EDGE].insert(me);
00163     }
00164     else if (dim == 0) {
00165       m_sEntity[MESH_VERTEX].insert(me);
00166       m_sEntity[EXCHANGE_VERTEX].insert(me);
00167     }
00168     b_partitioned = true;
00169   }
00170   else {
00171     DLIList<int>* shared_procs = td_par->get_shared_proc_list();
00172     int n_shared = shared_procs->size();
00173     for (int i = 0; i < n_shared; i++) {
00174       if (m_rank == (unsigned int)shared_procs->get_and_step()) { // shared processor
00175         if (dim == 2) {
00176           m_sEntity[SEND_POST_SURF_MESH].insert(me);
00177           m_sEntity[RECV_SURF_MESH].insert(me);
00178         }
00179         else if (dim == 1) {
00180           m_sEntity[EXCHANGE_EDGE].insert(me);
00181         }
00182         else if (dim == 0) {
00183           m_sEntity[EXCHANGE_VERTEX].insert(me);
00184         }
00185         b_partitioned = true;
00186         break;
00187       }
00188     }
00189   }
00190 
00191   // set geometry unique id to corresponding surface entityset
00192   if (b_partitioned) {
00193     unsigned int unique_id = td_par->get_unique_id();
00194     iBase_EntitySetHandle entityset = reinterpret_cast<iBase_EntitySetHandle> ((me)->mesh_handle());
00195     iMesh::Error err = mk_core()->imesh_instance()->setEntSetIntData(entityset, m_mPuniqueIDTag, unique_id);
00196     IBERRCHK(err, "Couldn't set geometry unique id to corresponding mesh entityset.");
00197   }
00198 }
00199 
00200 void ParallelMesher::print_geom_info(ModelEnt* me, const int dim,
00201                                      const bool local)
00202 {
00203   RefEntity* ent = reinterpret_cast<RefEntity*> (me->geom_handle());
00204   CubitVector edge_geom = ent->center_point();
00205   moab::EntityHandle entityset = me->mesh_handle();
00206   TDParallel *td_par = (TDParallel *) ent->get_TD(&TDParallel::is_parallel);
00207   std::cout << "Partitioned_dim=" << dim;
00208   if (local) std::cout << ",local";
00209   else std::cout << ",remote";
00210   std::cout << ",geom_center=" << edge_geom.x()
00211             << " "<< edge_geom.y() << " " << edge_geom.z() << ", meshset="
00212             << entityset << ",uid=" << td_par->get_unique_id()
00213             << ",id=" << ent->id() << std::endl;
00214 }
00215 
00216 void ParallelMesher::add_parallel_mesh_op(PARALLEL_OP_TYPE type, bool after)
00217 {
00218   bool inserted = false;
00219   MeshOp *mesher = NULL;
00220   std::vector<MeshOp*> meshops;
00221   MEntSet::iterator iter = m_sEntity[type].begin();
00222   MEntSet::iterator end_iter = m_sEntity[type].end();
00223 
00224   for (; iter != end_iter; iter++) {
00225     bool found = false;
00226     if (!mesher) mesher = get_mesher(type); // get a mesher if we haven't already
00227     meshops.clear();
00228     (*iter)->get_meshops(meshops);
00229     int n_meshops = meshops.size();
00230 
00231     if (n_meshops > 0) {
00232       for (int i = 0; i < n_meshops; i++) {
00233         if (meshops[i] == mesher) {
00234           found = true;
00235           break;
00236         }
00237       }
00238     }
00239 
00240     if (!found) { // if no specified meshop
00241       // add this entity to it, and if first, make sure it's added upstream
00242       mesher->add_modelent(*iter);
00243       if (!inserted) {
00244         if (after) mk_core()->insert_node(mesher, mk_core()->leaf_node(), this);
00245         else mk_core()->insert_node(mesher, this);
00246         inserted = true;
00247       }
00248     }
00249   }
00250 }
00251 
00252 void ParallelMesher::execute_this()
00253 {
00254   // create parallel partition, with the rank
00255 
00256   moab::Interface * mb =  mk_core()->moab_instance();
00257   moab::Tag ptag =m_mpcomm-> partition_tag(); // usually PARALLEL_PARTITION tag
00258   // collect all entities of dim 3, and put them in a new set
00259   MEntSet vols=m_sEntity[MESH_VOLUME];
00260   moab::EntityHandle pset;
00261   moab::ErrorCode rval = mb->create_meshset(moab::MESHSET_SET, pset); MB_CHK_ERR_RET(rval);
00262   rval = mb->tag_set_data(ptag, &pset, 1, &m_rank);  MB_CHK_ERR_RET(rval);
00263   for ( MEntSet::iterator viter = vols.begin(); viter!=vols.end(); viter++)
00264   {
00265     ModelEnt * me = *viter;
00266     moab::Range ents;
00267     moab::EntityHandle mEntSet = me->mesh_handle();
00268     rval = mb->get_entities_by_dimension(mEntSet, 3, ents);  MB_CHK_ERR_RET(rval);
00269     rval = mb->add_entities(pset, ents);
00270   }
00271 
00272   // also, do some cleanup, remove the interface sets from database, they are not needed anymore
00273   // (except if you want to do ghosting?)
00274   /*moab::Range intf_sets = m_mpcomm->interface_sets();
00275   rval = mb->delete_entities(intf_sets); MB_CHK_ERR_RET(rval);*/
00276   // delete geometry sets?
00277   moab::Tag geom_tag;
00278   rval = mb->tag_get_handle(GEOM_DIMENSION_TAG_NAME, 1, moab::MB_TYPE_INTEGER, geom_tag);MB_CHK_ERR_RET(rval);
00279   Range geom_sets;
00280   rval = mb->get_entities_by_type_and_tag(0, moab::MBENTITYSET, &geom_tag, NULL, 1, geom_sets);MB_CHK_ERR_RET(rval);
00281   rval = mb->delete_entities(geom_sets); MB_CHK_ERR_RET(rval);
00282   return;
00283 
00284 }
00285 
00286 void ParallelMesher::print_mesh()
00287 {
00288   moab::ErrorCode rval;
00289   int tmp_procs[MAX_SHARING_PROCS];
00290   moab::EntityHandle tmp_hs[MAX_SHARING_PROCS];
00291   unsigned char pstat;
00292   int num_ps;
00293   moab::Range entities;
00294 
00295   for (moab::EntityType type = MBVERTEX; type != MBMAXTYPE; type++) {
00296     entities.clear();
00297     rval = mk_core()->moab_instance()->get_entities_by_type(0, type, entities);
00298     MBERRCHK(rval, mk_core()->moab_instance());
00299 
00300     for (moab::Range::iterator rit = entities.begin(); rit != entities.end(); rit++) {
00301       rval = m_mpcomm->get_sharing_data(*rit, tmp_procs, tmp_hs, pstat, num_ps);
00302       MBERRCHK(rval, mk_core()->moab_instance());
00303 
00304       if (type != MBENTITYSET) {
00305         std::cout << "ParallelMesher::entity=" << *rit << ", type=" << type;
00306         if (type == MBVERTEX) {
00307           double coord[3];
00308           rval = mk_core()->moab_instance()->get_coords(&(*rit), 1, coord);
00309           MBERRCHK(rval, mk_core()->moab_instance());
00310           std::cout << ", coords=" << coord[0] << " " << coord[1] << " " << coord[2];
00311         }
00312         else {
00313           std::vector<moab::EntityHandle> connect;
00314           rval = mk_core()->moab_instance()->get_connectivity(&(*rit), 1, connect);
00315           MBERRCHK(rval, mk_core()->moab_instance());
00316           int n_conn = connect.size();
00317           std::cout << ", connect=";
00318           for (int j = 0; j < n_conn; j++) {
00319             std::cout << connect[j] << " ";
00320           }
00321         }
00322 
00323         std::cout << ", shared_info=";
00324         for (int ii = 0; ii < num_ps; ii++) {
00325           std::cout << tmp_procs[ii] << ":" << tmp_hs[ii] << ", ";
00326         }
00327         std::cout << std::endl;
00328       }
00329     }
00330   }
00331 }
00332 } // namespace MeshKit
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines