|
Sierra Toolkit Version of the Day
|
00001 /*------------------------------------------------------------------------*/ 00002 /* Copyright 2010 Sandia Corporation. */ 00003 /* Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive */ 00004 /* license for use of this work by or on behalf of the U.S. Government. */ 00005 /* Export of this program may require a license from the */ 00006 /* United States Government. */ 00007 /*------------------------------------------------------------------------*/ 00008 00009 00014 #include <set> 00015 #include <stdexcept> 00016 #include <iostream> 00017 #include <sstream> 00018 #include <algorithm> 00019 00020 #include <stk_util/parallel/ParallelComm.hpp> 00021 #include <stk_util/parallel/ParallelReduce.hpp> 00022 00023 #include <stk_mesh/base/Ghosting.hpp> 00024 #include <stk_mesh/base/BulkData.hpp> 00025 #include <stk_mesh/base/MetaData.hpp> 00026 #include <stk_mesh/base/FieldData.hpp> 00027 #include <stk_mesh/base/EntityComm.hpp> 00028 #include <stk_mesh/base/Comm.hpp> 00029 00030 namespace stk { 00031 namespace mesh { 00032 00033 namespace { 00034 00035 bool verify_parallel_attributes( BulkData & M , std::ostream & error_log ); 00036 00037 void pack_owned_verify( CommAll & all , const BulkData & mesh ); 00038 00039 bool unpack_not_owned_verify( CommAll & comm_all , 00040 const BulkData & mesh , 00041 std::ostream & error_log ); 00042 00043 } 00044 00045 bool comm_mesh_verify_parallel_consistency( 00046 BulkData & M , std::ostream & error_log ) 00047 { 00048 int result = 1 ; 00049 00050 // Verify consistency of parallel attributes 00051 00052 result = verify_parallel_attributes( M , error_log ); 00053 00054 all_reduce( M.parallel() , ReduceMin<1>( & result ) ); 00055 00056 // Verify entities against owner. 00057 00058 if ( result ) { 00059 CommAll all( M.parallel() ); 00060 00061 pack_owned_verify( all , M ); 00062 00063 all.allocate_buffers( all.parallel_size() / 4 ); 00064 00065 pack_owned_verify( all , M ); 00066 00067 all.communicate(); 00068 00069 result = unpack_not_owned_verify( all , M , error_log ); 00070 00071 all_reduce( M.parallel() , ReduceMin<1>( & result ) ); 00072 } 00073 00074 return result == 1 ; 00075 } 00076 00077 namespace { 00078 00079 bool ordered_comm( const Entity & entity ) 00080 { 00081 const PairIterEntityComm ec = entity.comm(); 00082 const size_t n = ec.size(); 00083 for ( size_t i = 1 ; i < n ; ++i ) { 00084 if ( ! ( ec[i-1] < ec[i] ) ) { 00085 return false ; 00086 } 00087 } 00088 return true ; 00089 } 00090 00091 bool verify_parallel_attributes( BulkData & M , std::ostream & error_log ) 00092 { 00093 bool result = true ; 00094 00095 const MetaData & S = M.mesh_meta_data(); 00096 Part & owns_part = S.locally_owned_part(); 00097 Part & shares_part = S.globally_shared_part(); 00098 00099 const unsigned p_rank = M.parallel_rank(); 00100 00101 const size_t EntityRankEnd = M.mesh_meta_data().entity_rank_count(); 00102 00103 size_t comm_count = 0 ; 00104 00105 for ( size_t itype = 0 ; itype < EntityRankEnd ; ++itype ) { 00106 const std::vector< Bucket * > & all_buckets = M.buckets( itype ); 00107 00108 const std::vector<Bucket*>::const_iterator i_end = all_buckets.end(); 00109 std::vector<Bucket*>::const_iterator i = all_buckets.begin(); 00110 00111 while ( i != i_end ) { 00112 Bucket & bucket = **i ; ++i ; 00113 00114 const bool has_owns_part = has_superset( bucket , owns_part ); 00115 const bool has_shares_part = has_superset( bucket , shares_part ); 00116 00117 const Bucket::iterator j_end = bucket.end(); 00118 Bucket::iterator j = bucket.begin(); 00119 00120 while ( j != j_end ) { 00121 Entity & entity = *j ; ++j ; 00122 00123 bool this_result = true ; 00124 00125 const unsigned p_owner = entity.owner_rank(); 00126 const bool ordered = ordered_comm( entity ); 00127 const bool shares = in_shared( entity ); 00128 const bool recv_ghost = in_receive_ghost( entity ); 00129 const bool send_ghost = in_send_ghost( entity ); 00130 const bool owned_closure = in_owned_closure( entity , p_rank ); 00131 00132 if ( ! ordered ) { 00133 error_log << "Problem is unordered" << std::endl; 00134 this_result = false ; 00135 } 00136 00137 // Owner consistency: 00138 00139 if ( has_owns_part && p_owner != p_rank ) { 00140 error_log << "problem is owner-consistency check 1: " 00141 << "has_owns_part: " << has_owns_part << ", " 00142 << "p_owner: " << p_owner << ", " 00143 << "p_rank: " << p_rank << std::endl; 00144 this_result = false ; 00145 } 00146 00147 if ( ! has_owns_part && p_owner == p_rank ) { 00148 error_log << "problem is owner-consistency check 2: " 00149 << "has_owns_part: " << has_owns_part << ", " 00150 << "p_owner: " << p_owner << ", " 00151 << "p_rank: " << p_rank << std::endl; 00152 this_result = false ; 00153 } 00154 00155 if ( has_shares_part != shares ) { 00156 error_log << "problem is owner-consistency check 3: " 00157 << "has_shares_part: " << has_shares_part << ", " 00158 << "shares: " << shares << std::endl; 00159 this_result = false ; 00160 } 00161 00162 // Definition of 'closure' 00163 00164 if ( ( has_owns_part || has_shares_part ) != owned_closure ) { 00165 error_log << "problem is closure check 1: " 00166 << "has_owns_part: " << has_owns_part << ", " 00167 << "has_shares_part: " << has_shares_part << ", " 00168 << "owned_closure: " << owned_closure << std::endl; 00169 this_result = false ; 00170 } 00171 00172 // Must be either owned_closure or recv_ghost but not both. 00173 00174 if ( owned_closure && recv_ghost ) { 00175 error_log << "problem is recv ghost check 1: " 00176 << "owned_closure: " << owned_closure << ", " 00177 << "recv_ghost: " << recv_ghost << std::endl; 00178 this_result = false ; 00179 } 00180 if ( ! owned_closure && ! recv_ghost ) { 00181 error_log << "problem is recv ghost check 2: " 00182 << "owned_closure: " << owned_closure << ", " 00183 << "recv_ghost: " << recv_ghost << std::endl; 00184 this_result = false ; 00185 } 00186 00187 // If sending as a ghost then I must own it 00188 00189 if ( ! has_owns_part && send_ghost ) { 00190 error_log << "problem is send ghost check 1: " 00191 << "has_owns_part: " << has_owns_part << ", " 00192 << "send_ghost: " << send_ghost << std::endl; 00193 this_result = false ; 00194 } 00195 00196 // If shared then I am owner or owner is in the shared list 00197 00198 if ( shares && p_owner != p_rank ) { 00199 PairIterEntityComm ip = entity.sharing(); 00200 for ( ; ! ip.empty() && p_owner != ip->proc ; ++ip ); 00201 if ( ip.empty() ) { 00202 error_log << "problem is shared check 1" << std::endl; 00203 this_result = false ; 00204 } 00205 } 00206 00207 if ( shares || recv_ghost || send_ghost ) { ++comm_count ; } 00208 00209 if ( ! this_result ) { 00210 result = false ; 00211 error_log << "P" << M.parallel_rank() << ": " ; 00212 print_entity_key( error_log , M.mesh_meta_data(), entity.key() ); 00213 error_log << " ERROR: owner(" << p_owner 00214 << ") owns(" << has_owns_part 00215 << ") shares(" << has_shares_part 00216 << ") owned_closure(" << owned_closure 00217 << ") recv_ghost(" << recv_ghost 00218 << ") send_ghost(" << send_ghost 00219 << ") comm(" ; 00220 PairIterEntityComm ip = entity.comm(); 00221 for ( ; ! ip.empty() ; ++ip ) { 00222 error_log << " " << ip->ghost_id << ":" << ip->proc ; 00223 } 00224 error_log << " )" << std::endl ; 00225 } 00226 } 00227 } 00228 } 00229 00230 for ( std::vector<Entity*>::const_iterator 00231 i = M.entity_comm().begin() ; 00232 i != M.entity_comm().end() ; ++i ) { 00233 00234 const PairIterEntityComm ec = (*i)->comm(); 00235 00236 if ( ec.empty() ) { 00237 print_entity_key( error_log , M.mesh_meta_data(), (*i)->key() ); 00238 error_log << " ERROR: in entity_comm but has no comm info" << std::endl ; 00239 result = false ; 00240 } 00241 } 00242 00243 if ( M.entity_comm().size() != comm_count ) { 00244 error_log << " ERROR: entity_comm.size() = " << M.entity_comm().size(); 00245 error_log << " != " << comm_count << " = entities with comm info" ; 00246 error_log << std::endl ; 00247 result = false ; 00248 } 00249 00250 return result ; 00251 } 00252 00253 //---------------------------------------------------------------------------- 00254 // Packing my owned entities. 00255 00256 void insert( std::vector<unsigned> & vec , unsigned val ) 00257 { 00258 std::vector<unsigned>::iterator j = 00259 std::lower_bound( vec.begin() , vec.end() , val ); 00260 if ( j == vec.end() || *j != val ) { 00261 vec.insert( j , val ); 00262 } 00263 } 00264 00265 void pack_owned_verify( CommAll & all , const BulkData & mesh ) 00266 { 00267 const std::vector<Entity*> & entity_comm = mesh.entity_comm(); 00268 const unsigned p_rank = all.parallel_rank(); 00269 00270 for ( std::vector<Entity*>::const_iterator 00271 i = entity_comm.begin() ; i != entity_comm.end() ; ++i ) { 00272 00273 Entity & entity = **i ; 00274 00275 if ( entity.owner_rank() == p_rank ) { 00276 00277 std::vector<unsigned> share_proc ; 00278 std::vector<unsigned> ghost_proc ; 00279 00280 const PairIterEntityComm comm = entity.comm(); 00281 00282 for ( size_t j = 0 ; j < comm.size() ; ++j ) { 00283 if ( comm[j].ghost_id == 0 ) { 00284 // Will be ordered by proc 00285 share_proc.push_back( comm[j].proc ); 00286 } 00287 else { 00288 // No guarantee of ordering by proc 00289 insert( ghost_proc , comm[j].proc ); 00290 } 00291 } 00292 00293 const unsigned share_count = share_proc.size(); 00294 00295 for ( size_t j = 0 ; j < share_proc.size() ; ++j ) { 00296 00297 // Sharing process, send sharing process list 00298 00299 const unsigned p = share_proc[j] ; 00300 00301 CommBuffer & buf = all.send_buffer( p ); 00302 00303 pack_entity_info( buf , entity ); 00304 00305 buf.pack<unsigned>( share_count ); 00306 00307 // Pack what the receiver should have: 00308 // My list, remove receiver, add myself 00309 size_t k = 0 ; 00310 for ( ; k < share_count && share_proc[k] < p_rank ; ++k ) { 00311 if ( k != j ) { buf.pack<unsigned>( share_proc[k] ); } 00312 } 00313 buf.pack<unsigned>( p_rank ); 00314 for ( ; k < share_count ; ++k ) { 00315 if ( k != j ) { buf.pack<unsigned>( share_proc[k] ); } 00316 } 00317 } 00318 00319 for ( size_t j = 0 ; j < ghost_proc.size() ; ++j ) { 00320 const unsigned p = ghost_proc[j] ; 00321 00322 CommBuffer & buf = all.send_buffer( p ); 00323 00324 pack_entity_info( buf , entity ); 00325 00326 // What ghost subsets go to this process? 00327 unsigned count = 0 ; 00328 for ( size_t k = 0 ; k < comm.size() ; ++k ) { 00329 if ( comm[k].ghost_id != 0 && comm[k].proc == p ) { 00330 ++count ; 00331 } 00332 } 00333 buf.pack<unsigned>( count ); 00334 for ( size_t k = 0 ; k < comm.size() ; ++k ) { 00335 if ( comm[k].ghost_id != 0 && comm[k].proc == p ) { 00336 buf.pack<unsigned>( comm[k].ghost_id ); 00337 } 00338 } 00339 } 00340 } 00341 } 00342 } 00343 00344 //---------------------------------------------------------------------------- 00345 // Unpacking all of my not-owned entities. 00346 00347 bool unpack_not_owned_verify( CommAll & comm_all , 00348 const BulkData & mesh , 00349 std::ostream & error_log ) 00350 { 00351 const MetaData & meta = mesh.mesh_meta_data(); 00352 Part * const owns_part = & meta.locally_owned_part(); 00353 Part * const shares_part = & meta.globally_shared_part(); 00354 const PartVector & mesh_parts = meta.get_parts(); 00355 const unsigned p_rank = mesh.parallel_rank(); 00356 const std::vector<Entity*> & entity_comm = mesh.entity_comm(); 00357 00358 bool result = true ; 00359 00360 EntityKey recv_entity_key ; 00361 unsigned recv_owner_rank = 0 ; 00362 unsigned recv_comm_count = 0 ; 00363 std::vector<Part*> recv_parts ; 00364 std::vector<Relation> recv_relations ; 00365 std::vector<unsigned> recv_comm ; 00366 00367 for ( std::vector<Entity*>::const_iterator 00368 i = entity_comm.begin() ; i != entity_comm.end() ; ++i ) { 00369 00370 Entity & entity = **i ; 00371 00372 if ( entity.owner_rank() != p_rank ) { 00373 00374 const Bucket & bucket = entity.bucket(); 00375 00376 std::pair<const unsigned *,const unsigned *> 00377 part_ordinals = bucket.superset_part_ordinals(); 00378 00379 CommBuffer & buf = comm_all.recv_buffer( entity.owner_rank() ); 00380 00381 unpack_entity_info( buf , mesh , 00382 recv_entity_key , recv_owner_rank , 00383 recv_parts , recv_relations ); 00384 00385 recv_comm_count = 0 ; 00386 buf.unpack<unsigned>( recv_comm_count ); 00387 recv_comm.resize( recv_comm_count ); 00388 buf.unpack<unsigned>( & recv_comm[0] , recv_comm_count ); 00389 00390 // Match key and owner 00391 00392 const bool bad_key = entity.key() != recv_entity_key ; 00393 const bool bad_own = entity.owner_rank() != recv_owner_rank ; 00394 bool bad_part = false ; 00395 bool bad_rel = false ; 00396 bool bad_comm = false ; 00397 00398 // Compare communication information: 00399 00400 if ( ! bad_key && ! bad_own ) { 00401 const PairIterEntityComm ec = entity.comm(); 00402 const unsigned ec_size = ec.size(); 00403 bad_comm = ec_size != recv_comm.size(); 00404 if ( ! bad_comm ) { 00405 size_t j = 0 ; 00406 if ( in_shared( entity ) ) { 00407 for ( ; j < ec_size && 00408 ec[j].ghost_id == 0 && 00409 ec[j].proc == recv_comm[j] ; ++j ); 00410 bad_comm = j != ec_size ; 00411 } 00412 else { 00413 for ( ; j < ec_size && 00414 ec[j].ghost_id == recv_comm[j] && 00415 ec[j].proc == entity.owner_rank() ; ++j ); 00416 bad_comm = j != ec_size ; 00417 } 00418 } 00419 } 00420 00421 // Compare everything but the owns part and uses part 00422 00423 if ( ! bad_key && ! bad_own && ! bad_comm ) { 00424 00425 const unsigned * k = part_ordinals.first ; 00426 00427 std::vector<Part*>::iterator ip = recv_parts.begin(); 00428 00429 for ( ; ! bad_part && ip != recv_parts.end() ; ++ip ) { 00430 if ( owns_part != *ip ) { 00431 if ( shares_part != *ip ) { 00432 // All not-owned and not-shares parts must match: 00433 bad_part = k == part_ordinals.second || 00434 (*ip)->mesh_meta_data_ordinal() != *k ; 00435 ++k ; 00436 } 00437 else if ( k != part_ordinals.second && 00438 *k == shares_part->mesh_meta_data_ordinal() ) { 00439 // shares-part matches 00440 ++k ; 00441 } 00442 } 00443 } 00444 } 00445 00446 // Compare the closure relations: 00447 if ( ! bad_key && ! bad_own && ! bad_comm && ! bad_part ) { 00448 00449 PairIterRelation ir = entity.relations(); 00450 00451 std::vector<Relation>::iterator jr = recv_relations.begin() ; 00452 00453 for ( ; ! bad_rel && jr != recv_relations.end() && 00454 jr->entity_rank() < entity.entity_rank() ; ++jr , ++ir ) { 00455 bad_rel = ir.empty() || *jr != *ir ; 00456 } 00457 } 00458 00459 if ( bad_key || bad_own || bad_comm || bad_part || bad_rel ) { 00460 error_log << "P" << p_rank << ": " ; 00461 print_entity_key( error_log , meta, entity.key() ); 00462 error_log << " owner(" << entity.owner_rank() << ")" ; 00463 00464 if ( bad_key || bad_own ) { 00465 error_log << " != received " ; 00466 print_entity_key( error_log , meta, recv_entity_key ); 00467 error_log << " owner(" << recv_owner_rank 00468 << ")" << std::endl ; 00469 } 00470 else if ( bad_comm ) { 00471 const PairIterEntityComm ec = entity.comm(); 00472 if ( in_shared( entity ) ) { 00473 error_log << " sharing(" ; 00474 for ( size_t j = 0 ; j < ec.size() && 00475 ec[j].ghost_id == 0 ; ++j ) { 00476 error_log << " " << ec[j].proc ; 00477 } 00478 error_log << " ) != received sharing(" ; 00479 for ( size_t j = 0 ; j < recv_comm.size() ; ++j ) { 00480 error_log << " " << recv_comm[j] ; 00481 } 00482 error_log << " )" << std::endl ; 00483 } 00484 else { 00485 error_log << " ghosting(" ; 00486 for ( size_t j = 0 ; j < ec.size() ; ++j ) { 00487 error_log << " (g" << ec[j].ghost_id ; 00488 error_log << ",p" << ec[j].proc ; 00489 error_log << ")" ; 00490 } 00491 error_log << " ) != received ghosting(" ; 00492 for ( size_t j = 0 ; j < recv_comm.size() ; ++j ) { 00493 error_log << " (g" << recv_comm[j] ; 00494 error_log << ",p" << entity.owner_rank(); 00495 error_log << ")" ; 00496 } 00497 error_log << " )" << std::endl ; 00498 } 00499 } 00500 else if ( bad_part ) { 00501 error_log << " Parts( " ; 00502 00503 for ( const unsigned * k = part_ordinals.first ; 00504 k < part_ordinals.second ; ++k ) { 00505 error_log << " \"" << mesh_parts[ *k ]->name() << "\"" ; 00506 } 00507 error_log << " ) != received Parts( " ; 00508 00509 for ( std::vector<Part*>::iterator 00510 ip = recv_parts.begin(); 00511 ip != recv_parts.end() ; ++ip ) { 00512 error_log << " \"" << (*ip)->name() << "\"" ; 00513 } 00514 error_log << " )" << std::endl ; 00515 } 00516 else if ( bad_rel ) { 00517 error_log << " Relations(" ; 00518 PairIterRelation ir = entity.relations(); 00519 for ( ; ! ir.empty() && 00520 ir->entity_rank() < entity.entity_rank() ; ++ir ) { 00521 error_log << " " << *ir ; 00522 } 00523 error_log << " ) != received Relations(" ; 00524 std::vector<Relation>::iterator jr = recv_relations.begin() ; 00525 for ( ; jr != recv_relations.end() && 00526 jr->entity_rank() < entity.entity_rank() ; ++jr ) { 00527 error_log << " " << *jr ; 00528 } 00529 error_log << " )" << std::endl ; 00530 } 00531 result = false ; 00532 } 00533 } 00534 } 00535 00536 return result ; 00537 } 00538 00539 } // namespace<> 00540 00541 } // namespace mesh 00542 } // namespace stk 00543