MeshKit
1.0
|
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