unsigned value_size(const EntityKey k, const unsigned i=0) const { const mesh::Entity e = entity(k); const mesh::FieldBase &field = *m_values_field[i]; const mesh::Bucket &bucket= m_bulk_data.bucket(e); const unsigned bytes = field_bytes_per_entity(field, bucket); const unsigned bytes_per_entry = field.data_traits().size_of; const unsigned num_entry = bytes/bytes_per_entry; ThrowRequireMsg (bytes == num_entry * bytes_per_entry, __FILE__<<":"<<__LINE__<<" Error:" <<" bytes:" <<bytes<<" num_entry:" <<num_entry <<" bytes_per_entry:" <<bytes_per_entry); return num_entry; }
inline unsigned field_scalars_per_entity(const FieldBase& f, Entity e) { const unsigned bytes_per_scalar = f.data_traits().size_of; BulkData& bulk(f.get_mesh()); ThrowAssert(f.entity_rank() == bulk.entity_rank(e)); return field_bytes_per_entity(f, bulk.bucket(e))/bytes_per_scalar; }
inline unsigned field_bytes_per_entity(const FieldBase& f, Entity e) { BulkData& bulk(f.get_mesh()); ThrowAssert(f.entity_rank() == bulk.entity_rank(e)); return field_bytes_per_entity(f, bulk.bucket(e)); }
//---------------------------------------------------------------------- void communicate_field_data( const Ghosting & ghosts , const std::vector< const FieldBase *> & fields ) { if ( fields.empty() ) { return; } const BulkData & mesh = ghosts.mesh(); const int parallel_size = mesh.parallel_size(); const int parallel_rank = mesh.parallel_rank(); const unsigned ghost_id = ghosts.ordinal(); const std::vector<const FieldBase *>::const_iterator fe = fields.end(); const std::vector<const FieldBase *>::const_iterator fb = fields.begin(); std::vector<const FieldBase *>::const_iterator fi ; // Sizing for send and receive const unsigned zero = 0 ; std::vector<unsigned> send_size( parallel_size , zero ); std::vector<unsigned> recv_size( parallel_size , zero ); for ( EntityCommListInfoVector::const_iterator i = mesh.internal_comm_list().begin() , iend = mesh.internal_comm_list().end(); i != iend ; ++i ) { Entity e = i->entity; const MeshIndex meshIdx = mesh.mesh_index(e); const unsigned bucketId = meshIdx.bucket->bucket_id(); const bool owned = i->owner == parallel_rank ; unsigned e_size = 0 ; for ( fi = fb ; fi != fe ; ++fi ) { const FieldBase & f = **fi ; if(is_matching_rank(f, *meshIdx.bucket)) { e_size += field_bytes_per_entity( f , bucketId ); } } if (e_size == 0) { continue; } const EntityCommInfoVector& infovec = i->entity_comm->comm_map; PairIterEntityComm ec(infovec.begin(), infovec.end()); if ( owned ) { for ( ; ! ec.empty() ; ++ec ) { if (ec->ghost_id == ghost_id) { send_size[ ec->proc ] += e_size ; } } } else { for ( ; ! ec.empty() ; ++ec ) { if (ec->ghost_id == ghost_id) { recv_size[ i->owner ] += e_size ; break;//jump out since we know we're only recving 1 msg from the 1-and-only owner } } } } // Allocate send and receive buffers: CommAll sparse ; { const unsigned * const snd_size = send_size.data() ; const unsigned * const rcv_size = recv_size.data() ; sparse.allocate_buffers( mesh.parallel(), snd_size, rcv_size); } // Send packing: for (int phase = 0; phase < 2; ++phase) { for ( EntityCommListInfoVector::const_iterator i = mesh.internal_comm_list().begin(), iend = mesh.internal_comm_list().end() ; i != iend ; ++i ) { if ( (i->owner == parallel_rank && phase == 0) || (i->owner != parallel_rank && phase == 1) ) { Entity e = i->entity; const MeshIndex meshIdx = mesh.mesh_index(e); const unsigned bucketId = meshIdx.bucket->bucket_id(); for ( fi = fb ; fi != fe ; ++fi ) { const FieldBase & f = **fi ; if(!is_matching_rank(f, e)) continue; const unsigned size = field_bytes_per_entity( f , e ); if ( size ) { unsigned char * ptr = reinterpret_cast<unsigned char *>(stk::mesh::field_data( f , bucketId, meshIdx.bucket_ordinal, size )); const EntityCommInfoVector& infovec = i->entity_comm->comm_map; PairIterEntityComm ec(infovec.begin(), infovec.end()); if (phase == 0) { // send for ( ; !ec.empty() ; ++ec ) { if (ec->ghost_id == ghost_id) { CommBuffer & b = sparse.send_buffer( ec->proc ); b.pack<unsigned char>( ptr , size ); } } } else { //recv for ( ; !ec.empty(); ++ec ) { if (ec->ghost_id == ghost_id) { CommBuffer & b = sparse.recv_buffer( i->owner ); b.unpack<unsigned char>( ptr , size ); break; } } } } } } } if (phase == 0) { sparse.communicate(); } } }
inline void parallel_sum_including_ghosts( const BulkData & mesh , const std::vector< const FieldBase *> & fields ) { if ( fields.empty() ) { return; } const int parallel_size = mesh.parallel_size(); const int parallel_rank = mesh.parallel_rank(); const std::vector<const FieldBase *>::const_iterator fe = fields.end(); const std::vector<const FieldBase *>::const_iterator fb = fields.begin(); std::vector<const FieldBase *>::const_iterator fi ; // Sizing for send and receive const unsigned zero = 0 ; std::vector<unsigned> send_size( parallel_size , zero ); std::vector<unsigned> recv_size( parallel_size , zero ); const EntityCommListInfoVector& comm_info_vec = mesh.internal_comm_list(); size_t comm_info_vec_size = comm_info_vec.size(); for ( fi = fb ; fi != fe ; ++fi ) { const FieldBase & f = **fi ; for (size_t i=0; i<comm_info_vec_size; ++i) { if (!mesh.is_valid(comm_info_vec[i].entity)) { ThrowAssertMsg(mesh.is_valid(comm_info_vec[i].entity),"parallel_sum_including_ghosts found invalid entity"); } const Bucket* bucket = comm_info_vec[i].bucket; unsigned e_size = 0 ; if(is_matching_rank(f, *bucket)) { const unsigned bucketId = bucket->bucket_id(); e_size += field_bytes_per_entity( f , bucketId ); } if (e_size == 0) { continue; } const bool owned = comm_info_vec[i].owner == parallel_rank ; if ( !owned ) { send_size[ comm_info_vec[i].owner ] += e_size ; } else { const EntityCommInfoVector& infovec = comm_info_vec[i].entity_comm->comm_map; size_t info_vec_size = infovec.size(); for (size_t j=0; j<info_vec_size; ++j ) { recv_size[ infovec[j].proc ] += e_size ; } } } } // Allocate send and receive buffers: CommAll sparse ; { const unsigned * const snd_size = & send_size[0] ; const unsigned * const rcv_size = & recv_size[0] ; sparse.allocate_buffers( mesh.parallel(), snd_size, rcv_size); } // Send packing: for (int phase = 0; phase < 2; ++phase) { for ( fi = fb ; fi != fe ; ++fi ) { const FieldBase & f = **fi ; for (size_t i=0; i<comm_info_vec_size; ++i) { const bool owned = comm_info_vec[i].owner == parallel_rank; if ( (!owned && phase == 0) || (owned && phase == 1) ) { const Bucket* bucket = comm_info_vec[i].bucket; if(!is_matching_rank(f, *bucket)) continue; const unsigned bucketId = bucket->bucket_id(); const size_t bucket_ordinal = comm_info_vec[i].bucket_ordinal; const unsigned scalars_per_entity = field_scalars_per_entity(f, bucketId); if ( scalars_per_entity > 0 ) { int owner = comm_info_vec[i].owner; if (f.data_traits().is_floating_point && f.data_traits().size_of == 8) { send_or_recv_field_data_for_assembly<double>(sparse, phase, f, owner, comm_info_vec[i].entity_comm->comm_map, scalars_per_entity, bucketId, bucket_ordinal); } else if (f.data_traits().is_floating_point && f.data_traits().size_of == 4) { send_or_recv_field_data_for_assembly<float>(sparse, phase, f, owner, comm_info_vec[i].entity_comm->comm_map, scalars_per_entity, bucketId, bucket_ordinal); } else if (f.data_traits().is_integral && f.data_traits().size_of == 4 && f.data_traits().is_unsigned) { send_or_recv_field_data_for_assembly<unsigned>(sparse, phase, f, owner, comm_info_vec[i].entity_comm->comm_map, scalars_per_entity, bucketId, bucket_ordinal); } else if (f.data_traits().is_integral && f.data_traits().size_of == 4 && f.data_traits().is_signed) { send_or_recv_field_data_for_assembly<int>(sparse, phase, f, owner, comm_info_vec[i].entity_comm->comm_map, scalars_per_entity, bucketId, bucket_ordinal); } else { ThrowRequireMsg(false,"Unsupported field type in parallel_sum_including_ghosts"); } } } } } if (phase == 0) { sparse.communicate(); } } copy_from_owned(mesh, fields); }
inline void copy_from_owned( const BulkData & mesh , const std::vector< const FieldBase *> & fields ) { if ( fields.empty() ) { return; } const int parallel_size = mesh.parallel_size(); const int parallel_rank = mesh.parallel_rank(); const std::vector<const FieldBase *>::const_iterator fe = fields.end(); const std::vector<const FieldBase *>::const_iterator fb = fields.begin(); std::vector<const FieldBase *>::const_iterator fi ; std::vector<std::vector<unsigned char> > send_data(parallel_size); std::vector<std::vector<unsigned char> > recv_data(parallel_size); const EntityCommListInfoVector &comm_info_vec = mesh.internal_comm_list(); size_t comm_info_vec_size = comm_info_vec.size(); std::vector<unsigned> send_sizes(parallel_size, 0); std::vector<unsigned> recv_sizes(parallel_size, 0); //this first loop calculates send_sizes and recv_sizes. for(fi = fb; fi != fe; ++fi) { const FieldBase & f = **fi; for(size_t i = 0; i<comm_info_vec_size; ++i) { const Bucket* bucket = comm_info_vec[i].bucket; int owner = comm_info_vec[i].owner; const bool owned = (owner == parallel_rank); unsigned e_size = 0; if(is_matching_rank(f, *bucket)) { const unsigned bucketId = bucket->bucket_id(); unsigned size = field_bytes_per_entity(f, bucketId); e_size += size; } if(e_size == 0) { continue; } if(owned) { const EntityCommInfoVector& infovec = comm_info_vec[i].entity_comm->comm_map; size_t infovec_size = infovec.size(); for(size_t j=0; j<infovec_size; ++j) { int proc = infovec[j].proc; send_sizes[proc] += e_size; } } else { recv_sizes[owner] += e_size; } } } //now size the send_data buffers size_t max_len = 0; for(int p=0; p<parallel_size; ++p) { if (send_sizes[p] > 0) { if (send_sizes[p] > max_len) { max_len = send_sizes[p]; } send_data[p].resize(send_sizes[p]); send_sizes[p] = 0; } } //now pack the send buffers std::vector<unsigned char> field_data(max_len); unsigned char* field_data_ptr = field_data.data(); for(fi = fb; fi != fe; ++fi) { const FieldBase & f = **fi; for(size_t i = 0; i<comm_info_vec_size; ++i) { const Bucket* bucket = comm_info_vec[i].bucket; int owner = comm_info_vec[i].owner; const bool owned = (owner == parallel_rank); unsigned e_size = 0; if(is_matching_rank(f, *bucket)) { const unsigned bucketId = bucket->bucket_id(); unsigned size = field_bytes_per_entity(f, bucketId); if (owned && size > 0) { unsigned char * ptr = reinterpret_cast<unsigned char*>(stk::mesh::field_data(f, bucketId, comm_info_vec[i].bucket_ordinal, size)); std::memcpy(field_data_ptr+e_size, ptr, size); // field_data.insert(field_data.end(), ptr, ptr+size); } e_size += size; } if(e_size == 0) { continue; } if(owned) { const EntityCommInfoVector& infovec = comm_info_vec[i].entity_comm->comm_map; size_t infovec_size = infovec.size(); for(size_t j=0; j<infovec_size; ++j) { int proc = infovec[j].proc; unsigned char* dest_ptr = send_data[proc].data()+send_sizes[proc]; unsigned char* src_ptr = field_data_ptr; std::memcpy(dest_ptr, src_ptr, e_size); send_sizes[proc] += e_size; // send_data[proc].insert(send_data[proc].end(), field_data.begin(), field_data.end()); } } else { recv_sizes[owner] += e_size; } } } for(int p=0; p<parallel_size; ++p) { if (recv_sizes[p] > 0) { recv_data[p].resize(recv_sizes[p]); recv_sizes[p] = 0; } } parallel_data_exchange_nonsym_known_sizes_t(send_data, recv_data, mesh.parallel()); //now unpack and store the recvd data for(fi = fb; fi != fe; ++fi) { const FieldBase & f = **fi; for(size_t i=0; i<comm_info_vec_size; ++i) { int owner = comm_info_vec[i].owner; const bool owned = (owner == parallel_rank); if(owned || recv_data[owner].size() == 0) { continue; } const Bucket* bucket = comm_info_vec[i].bucket; if(is_matching_rank(f, *bucket)) { const unsigned bucketId = bucket->bucket_id(); unsigned size = field_bytes_per_entity(f, bucketId); if (size > 0) { unsigned char * ptr = reinterpret_cast<unsigned char*>(stk::mesh::field_data(f, bucketId, comm_info_vec[i].bucket_ordinal, size)); std::memcpy(ptr, &(recv_data[owner][recv_sizes[owner]]), size); // for(unsigned j = 0; j < size; ++j) // { // ptr[j] = recv_data[owner][recv_sizes[owner]+j]; // } recv_sizes[owner] += size; } } } } }