Sierra Toolkit  Version of the Day
MetaData.cpp
1 /*------------------------------------------------------------------------*/
2 /* Copyright 2010 Sandia Corporation. */
3 /* Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive */
4 /* license for use of this work by or on behalf of the U.S. Government. */
5 /* Export of this program may require a license from the */
6 /* United States Government. */
7 /*------------------------------------------------------------------------*/
8 
13 #include <string.h>
14 #include <stdexcept>
15 #include <iostream>
16 #include <sstream>
17 #include <algorithm>
18 
19 #include <stk_util/util/string_case_compare.hpp>
20 #include <stk_util/parallel/ParallelComm.hpp>
21 #include <stk_util/parallel/ParallelReduce.hpp>
22 #include <stk_mesh/base/MetaData.hpp>
23 #include <stk_mesh/base/Comm.hpp>
24 
25 #include <stk_mesh/base/BulkData.hpp>
26 
27 
28 #include <stk_mesh/baseImpl/FieldRepository.hpp>
29 
30 namespace stk_classic {
31 namespace mesh {
32 
33 MetaData & MetaData::get( const BulkData & bulk_data) {
34  return bulk_data.meta_data();
35 }
36 
37 MetaData & MetaData::get( const Bucket & bucket) {
38  return MetaData::get(BulkData::get(bucket));
39 }
40 
41 MetaData & MetaData::get( const Entity & entity) {
42  return MetaData::get(BulkData::get(entity));
43 }
44 
45 MetaData & MetaData::get( const Ghosting & ghost) {
46  return MetaData::get(BulkData::get(ghost));
47 }
48 //----------------------------------------------------------------------
49 
50 std::ostream &
51 print_entity_id( std::ostream & os , const MetaData & meta_data ,
52  unsigned type , EntityId id )
53 {
54  const std::string & name = meta_data.entity_rank_name( type );
55  return os << name << "[" << id << "]" ;
56 }
57 
58 
59 std::ostream &
60 print_entity_key( std::ostream & os , const MetaData & meta_data ,
61  const EntityKey & key )
62 {
63  const unsigned type = entity_rank(key);
64  const EntityId id = entity_id(key);
65  return print_entity_id( os , meta_data , type , id );
66 }
67 
68 std::string
69 print_entity_key( const MetaData & meta_data , const EntityKey & key )
70 {
71  std::ostringstream out;
72  print_entity_key(out, meta_data, key);
73  return out.str();
74 }
75 
76 //----------------------------------------------------------------------
77 
78 void MetaData::require_not_committed() const
79 {
80  ThrowRequireMsg(!m_commit, "mesh MetaData has been committed.");
81 }
82 
83 void MetaData::require_committed() const
84 {
85  ThrowRequireMsg(m_commit, "mesh MetaData has not been committed.");
86 }
87 
88 void MetaData::require_same_mesh_meta_data( const MetaData & rhs ) const
89 {
90  ThrowRequireMsg(this == &rhs, "Different mesh_meta_data.");
91 }
92 
93 void MetaData::require_valid_entity_rank( EntityRank rank ) const
94 {
95  ThrowRequireMsg(check_rank(rank),
96  "entity_rank " << rank << " >= " << m_entity_rank_names.size() );
97 }
98 
99 void MetaData::require_not_relation_target( const Part * const part ) const
100 {
101  std::vector<PartRelation>::const_iterator i_end = part->relations().end();
102  std::vector<PartRelation>::const_iterator i = part->relations().begin();
103  for ( ; i != i_end ; ++i ) {
104  ThrowRequireMsg( part != i->m_target,
105  "Part[" << part->name() << "] is a PartRelation target");
106  }
107 }
108 
109 //----------------------------------------------------------------------
110 
111 MetaData::MetaData(const std::vector<std::string>& entity_rank_names)
112  : m_commit( false ),
113  m_part_repo( this ),
114  m_attributes(),
115  m_universal_part( NULL ),
116  m_owns_part( NULL ),
117  m_shares_part( NULL ),
118  m_field_repo(),
119  m_field_relations( ),
120  m_properties( ),
121  m_entity_rank_names( entity_rank_names ),
122  m_spatial_dimension( 0 /*invalid spatial dimension*/)
123 {
124  ThrowErrorMsgIf( entity_rank_names.empty(), "entity ranks empty" );
125 
126  // Declare the predefined parts
127 
128  m_universal_part = m_part_repo.universal_part();
129  m_owns_part = & declare_internal_part("OWNS");
130  m_shares_part = & declare_internal_part("SHARES");
131 }
132 
134  : m_commit( false ),
135  m_part_repo( this ),
136  m_attributes(),
137  m_universal_part( NULL ),
138  m_owns_part( NULL ),
139  m_shares_part( NULL ),
140  m_field_repo(),
141  m_field_relations( ),
142  m_properties( ),
143  m_entity_rank_names( ),
144  m_spatial_dimension( 0 /*invalid spatial dimension*/)
145 {
146  // Declare the predefined parts
147 
148  m_universal_part = m_part_repo.universal_part();
149  m_owns_part = & declare_internal_part("OWNS");
150  m_shares_part = & declare_internal_part("SHARES");
151 }
152 
153 //----------------------------------------------------------------------
154 
155 void MetaData::set_entity_rank_names(const std::vector<std::string> &entity_rank_names)
156 {
157  ThrowErrorMsgIf( entity_rank_names.empty(), "entity ranks empty" );
158 
159  m_entity_rank_names = entity_rank_names;
160 }
161 
162 const std::string& MetaData::entity_rank_name( EntityRank entity_rank ) const
163 {
164  ThrowErrorMsgIf( entity_rank >= m_entity_rank_names.size(),
165  "entity-rank " << entity_rank <<
166  " out of range. Must be in range 0.." << m_entity_rank_names.size());
167 
168  return m_entity_rank_names[entity_rank];
169 }
170 
171 EntityRank MetaData::entity_rank( const std::string &name ) const
172 {
173  EntityRank entity_rank = InvalidEntityRank;
174 
175  for (size_t i = 0; i < m_entity_rank_names.size(); ++i)
176  if (equal_case(name, m_entity_rank_names[i])) {
177  entity_rank = i;
178  break;
179  }
180  return entity_rank;
181 }
182 
183 //----------------------------------------------------------------------
184 
185 Part * MetaData::get_part( const std::string & p_name ,
186  const char * required_by ) const
187 {
188  const PartVector & all_parts = m_part_repo.get_all_parts();
189 
190  Part * const p = find( all_parts , p_name );
191 
192  ThrowErrorMsgIf( required_by && NULL == p,
193  "Failed to find part with name " << p_name <<
194  " for method " << required_by );
195 
196  return p ;
197 }
198 
199 Part & MetaData::declare_part( const std::string & p_name )
200 {
201  require_not_committed();
202 
203  const EntityRank rank = InvalidEntityRank;
204 
205  return *m_part_repo.declare_part( p_name, rank );
206 }
207 
208 Part & MetaData::declare_internal_part( const std::string & p_name )
209 {
210  std::string internal_name = convert_to_internal_name(p_name);
211  return declare_part(internal_name);
212 }
213 
214 Part & MetaData::declare_part( const std::string & p_name , EntityRank rank )
215 {
216  require_not_committed();
217  require_valid_entity_rank(rank);
218 
219  return *m_part_repo.declare_part( p_name , rank );
220 }
221 
222 Part & MetaData::declare_internal_part( const std::string & p_name , EntityRank rank )
223 {
224  std::string internal_name = convert_to_internal_name(p_name);
225  return declare_part(internal_name, rank);
226 }
227 
228 Part & MetaData::declare_part( const PartVector & part_intersect )
229 {
230  require_not_committed();
231 
232  for ( PartVector::const_iterator
233  i = part_intersect.begin() ; i != part_intersect.end() ; ++i ) {
234  require_not_relation_target(*i);
235  }
236 
237  return *m_part_repo.declare_part( part_intersect );
238 }
239 
240 void MetaData::declare_part_subset( Part & superset , Part & subset )
241 {
242  static const char method[] = "stk_classic::mesh::MetaData::declare_part_subset" ;
243 
244  require_not_committed();
245  require_same_mesh_meta_data( MetaData::get(superset) );
246  require_same_mesh_meta_data( MetaData::get(subset) );
247  require_not_relation_target( &superset );
248  require_not_relation_target( &subset );
249 
250  m_part_repo.declare_subset( superset, subset );
251 
252  // The new superset / subset relationship can cause a
253  // field restriction to become incompatible or redundant.
254  m_field_repo.verify_and_clean_restrictions(method, superset, subset, m_part_repo.get_all_parts());
255 }
256 
258  Part & root_part ,
259  relation_stencil_ptr stencil ,
260  Part & target_part )
261 {
262  require_not_committed();
263  require_not_relation_target( &root_part );
264 
265  ThrowErrorMsgIf( !stencil, "stencil function pointer cannot be NULL" );
266 
267  ThrowErrorMsgIf( 0 != target_part.subsets().size() ||
268  0 != target_part.intersection_of().size() ||
269  1 != target_part.supersets().size(),
270  "target Part[" << target_part.name() <<
271  "] cannot be a superset or subset" );
272 
273  PartRelation tmp ;
274  tmp.m_root = & root_part ;
275  tmp.m_target = & target_part ;
276  tmp.m_function = stencil ;
277 
278  m_part_repo.declare_part_relation( root_part, tmp, target_part );
279 }
280 
281 //----------------------------------------------------------------------
282 
283 FieldBase *
285  const std::string & arg_name ,
286  const DataTraits & arg_traits ,
287  unsigned arg_rank ,
288  const shards::ArrayDimTag * const * arg_dim_tags ,
289  unsigned arg_num_states )
290 {
291  require_not_committed();
292 
293  return m_field_repo.declare_field(
294  arg_name,
295  arg_traits,
296  arg_rank,
297  arg_dim_tags,
298  arg_num_states,
299  this
300  );
301 }
302 
304  FieldBase & arg_field ,
305  EntityRank arg_entity_rank ,
306  const Part & arg_part ,
307  const unsigned * arg_stride ,
308  const void * arg_init_value )
309 {
310  static const char method[] =
311  "std::mesh::MetaData::declare_field_restriction" ;
312 
313  //require_not_committed(); // Moved to FieldBaseImpl::declare_field_restriction
314  require_same_mesh_meta_data( MetaData::get(arg_field) );
315  require_same_mesh_meta_data( MetaData::get(arg_part) );
316 
317  m_field_repo.declare_field_restriction(
318  method,
319  arg_field,
320  arg_entity_rank,
321  arg_part,
322  m_part_repo.get_all_parts(),
323  arg_stride,
324  arg_init_value
325  );
326 }
327 
329  FieldBase & arg_field ,
330  EntityRank arg_entity_rank ,
331  const Selector & arg_selector ,
332  const unsigned * arg_stride ,
333  const void * arg_init_value )
334 {
335  static const char method[] =
336  "std::mesh::MetaData::declare_field_restriction" ;
337 
338  //require_not_committed(); // Moved to FieldBaseImpl::declare_field_restriction
339  require_same_mesh_meta_data( MetaData::get(arg_field) );
340 
341  m_field_repo.declare_field_restriction(
342  method,
343  arg_field,
344  arg_entity_rank,
345  arg_selector,
346  m_part_repo.get_all_parts(),
347  arg_stride,
348  arg_init_value
349  );
350 }
351 
352 
353 void MetaData::internal_declare_field_relation(
354  FieldBase & pointer_field ,
355  relation_stencil_ptr stencil ,
356  FieldBase & referenced_field )
357 {
358  FieldRelation tmp ;
359  tmp.m_root = & pointer_field ;
360  tmp.m_target = & referenced_field ;
361  tmp.m_function = stencil ;
362 
363  m_field_relations.push_back( tmp );
364 }
365 
366 //----------------------------------------------------------------------
367 
369 {
370  require_not_committed();
371 
372  m_commit = true ; // Cannot add or change parts or fields now
373 }
374 
376 {
377  // Destroy the properties, used 'new' to allocate so now use 'delete'
378 
379  try {
380  std::vector<PropertyBase * >::iterator j = m_properties.begin();
381 
382  for ( ; j != m_properties.end() ; ++j ) { delete *j ; }
383 
384  m_properties.clear();
385  } catch(...) {}
386 
387  // PartRepository is member data
388  // FieldRepository is member data
389 }
390 
391 //----------------------------------------------------------------------
392 //----------------------------------------------------------------------
393 // Verify parallel consistency of fields and parts
394 
395 namespace {
396 
397 void pack( CommBuffer & b , const PartVector & pset )
398 {
399  PartVector::const_iterator i , j ;
400  for ( i = pset.begin() ; i != pset.end() ; ++i ) {
401  const Part & p = **i ;
402  const PartVector & subsets = p.subsets();
403  const PartVector & intersect = p.intersection_of();
404 
405  const size_t name_len = p.name().size() + 1 ;
406  const char * const name_ptr = p.name().c_str();
407 
408  {
409  const unsigned ord = p.mesh_meta_data_ordinal();
410  b.pack<unsigned>( ord );
411  }
412 
413  b.pack<unsigned>( name_len );
414  b.pack<char>( name_ptr , name_len );
415 
416  const unsigned subset_size = static_cast<unsigned>(subsets.size());
417  b.pack<unsigned>( subset_size );
418  for ( j = subsets.begin() ; j != subsets.end() ; ++j ) {
419  const Part & s = **j ;
420  const unsigned ord = s.mesh_meta_data_ordinal();
421  b.pack<unsigned>( ord );
422  }
423  const unsigned intersect_size = static_cast<unsigned>(intersect.size());
424  b.pack<unsigned>( intersect_size );
425  for ( j = intersect.begin() ; j != intersect.end() ; ++j ) {
426  const Part & s = **j ;
427  const unsigned ord = s.mesh_meta_data_ordinal();
428  b.pack<unsigned>( ord );
429  }
430  }
431 }
432 
433 bool unpack_verify( CommBuffer & b , const PartVector & pset )
434 {
435  enum { MAX_TEXT_LEN = 4096 };
436  char b_text[ MAX_TEXT_LEN ];
437  unsigned b_tmp = 0;
438 
439  bool ok = true ;
440  PartVector::const_iterator i , j ;
441  for ( i = pset.begin() ; ok && i != pset.end() ; ++i ) {
442  const Part & p = **i ;
443  const PartVector & subsets = p.subsets();
444  const PartVector & intersect = p.intersection_of();
445  const unsigned name_len = static_cast<unsigned>(p.name().size()) + 1 ;
446  const char * const name_ptr = p.name().c_str();
447 
448  if ( ok ) {
449  b.unpack<unsigned>( b_tmp );
450  ok = b_tmp == p.mesh_meta_data_ordinal();
451  }
452 
453  if ( ok ) {
454  b.unpack<unsigned>( b_tmp );
455  ok = b_tmp == name_len ;
456  }
457  if ( ok ) {
458  b.unpack<char>( b_text , name_len );
459  ok = 0 == strcmp( name_ptr , b_text );
460  }
461 
462  if ( ok ) {
463  b.unpack<unsigned>( b_tmp );
464  ok = b_tmp == subsets.size() ;
465  }
466  for ( j = subsets.begin() ; ok && j != subsets.end() ; ++j ) {
467  const Part & s = **j ;
468  b.unpack<unsigned>( b_tmp );
469  ok = b_tmp == s.mesh_meta_data_ordinal();
470  }
471 
472  if ( ok ) {
473  b.unpack<unsigned>( b_tmp );
474  ok = b_tmp == intersect.size();
475  }
476  for ( j = intersect.begin() ; ok && j != intersect.end() ; ++j ) {
477  const Part & s = **j ;
478  b.unpack<unsigned>( b_tmp );
479  ok = b_tmp == s.mesh_meta_data_ordinal();
480  }
481  }
482  return ok ;
483 }
484 
485 void pack( CommBuffer & ,
486  const std::vector< FieldBase * > & )
487 {
488 }
489 
490 bool unpack_verify( CommBuffer & ,
491  const std::vector< FieldBase * > & )
492 {
493  bool ok = true ;
494  return ok ;
495 }
496 
497 }
498 
499 //----------------------------------------------------------------------
500 
502 {
503  const unsigned p_rank = parallel_machine_rank( pm );
504 
505  const bool is_root = 0 == p_rank ;
506 
507  CommBroadcast comm( pm , 0 );
508 
509  if ( is_root ) {
510  pack( comm.send_buffer() , s.get_parts() );
511  pack( comm.send_buffer() , s.get_fields() );
512  }
513 
514  comm.allocate_buffer();
515 
516  if ( is_root ) {
517  pack( comm.send_buffer() , s.get_parts() );
518  pack( comm.send_buffer() , s.get_fields() );
519  }
520 
521  comm.communicate();
522 
523  int ok[ 2 ];
524 
525  ok[0] = unpack_verify( comm.recv_buffer() , s.get_parts() );
526  ok[1] = unpack_verify( comm.recv_buffer() , s.get_fields() );
527 
528  all_reduce( pm , ReduceMin<2>( ok ) );
529 
530  ThrowRequireMsg(ok[0], "P" << p_rank << ": FAILED for Parts");
531  ThrowRequireMsg(ok[1], "P" << p_rank << ": FAILED for Fields");
532 }
533 
534 //----------------------------------------------------------------------
535 
536 } // namespace mesh
537 } // namespace stk_classic
538 
FieldBase * m_target
relation range part
void verify_parallel_consistency(const MetaData &s, ParallelMachine pm)
Verify that the meta data is identical on all processors.
Definition: MetaData.cpp:501
Field base class with an anonymous data type and anonymous multi-dimension.
Definition: FieldBase.hpp:53
The manager of an integrated collection of parts and fields.
Definition: MetaData.hpp:56
void declare_part_subset(Part &superset, Part &subset)
Declare a superset-subset relationship between parts.
Definition: MetaData.cpp:240
This is a class for selecting buckets based on a set of meshparts and set logic.
Definition: Selector.hpp:112
Part * get_part(const std::string &p_name, const char *required_by=NULL) const
Get an existing part by its application-defined text name.
Definition: MetaData.cpp:185
MetaData()
Construct a meta data manager to own parts and fields.
Definition: MetaData.cpp:133
const FieldVector & get_fields() const
Get all defined fields.
Definition: MetaData.hpp:218
size_t intersect(const PartVector &v, const PartVector &p)
Query cardinality of intersection of two PartVectors.
Definition: Part.cpp:141
Integer type for the entity keys, which is an encoding of the entity type and entity identifier...
An application-defined subset of a problem domain.
Definition: Part.hpp:49
unsigned parallel_machine_rank(ParallelMachine parallel_machine)
Member function parallel_machine_rank ...
Definition: Parallel.cpp:29
const PartVector & intersection_of() const
Parts for which this part is defined as the intersection.
Definition: Part.hpp:81
FieldBase * m_root
relation domain part
const std::string & name() const
Application-defined text name of this part.
Definition: Part.hpp:67
Part & declare_part(const std::string &p_name, EntityRank rank)
Declare a part of the given name and entity rank Redeclaration returns the previously declared part...
Definition: MetaData.cpp:214
FieldBase * declare_field_base(const std::string &arg_name, const DataTraits &arg_traits, unsigned arg_rank, const shards::ArrayDimTag *const *arg_dim_tags, unsigned arg_num_states)
Declare a field via runtime type information.
Definition: MetaData.cpp:284
unsigned mesh_meta_data_ordinal() const
Internally generated ordinal of this part that is unique within the owning meta data manager...
Definition: Part.hpp:72
Part * m_root
relation domain part
~MetaData()
Destroy the meta data manager and all of the parts and fields that it owns.
Definition: MetaData.cpp:375
const PartVector & supersets() const
Parts that are supersets of this part.
Definition: Part.hpp:75
void set_entity_rank_names(const std::vector< std::string > &entity_rank_names)
entity-rank names
Definition: MetaData.cpp:155
EntityId entity_id(const EntityKey &key)
Given an entity key, return the identifier for the entity.
const PartVector & subsets() const
Parts that are subsets of this part.
Definition: Part.hpp:78
Sierra Toolkit.
bool check_rank(EntityRank rank) const
const PartVector & get_parts() const
Query all parts of the mesh ordered by the parts&#39; ordinal.
Definition: MetaData.hpp:120
A defined entity-relationship between parts. An internal class that should never need to be directly...
MPI_Comm ParallelMachine
Definition: Parallel.hpp:32
bool equal_case(const char *lhs, const char *rhs)
Case-insensitive equality compare.
int(* relation_stencil_ptr)(unsigned from_type, unsigned to_type, unsigned identifier)
A relation stencil maps entity relationships to ordinals.
Definition: Types.hpp:149
void declare_part_relation(Part &root_part, relation_stencil_ptr stencil, Part &target_part)
Declare an entity-relationship between parts.
Definition: MetaData.cpp:257
relation_stencil_ptr m_function
relation stencil
std::vector< Part *> PartVector
Collections of parts are frequently maintained as a vector of Part pointers.
Definition: Types.hpp:31
A defined entity-relationship between a field of a pointer type and the field that it should point to...
Part * find(const PartVector &parts, const std::string &name)
Find a part by name in a collection of parts.
Definition: Part.cpp:22
EntityRank entity_rank(const EntityKey &key)
Given an entity key, return an entity type (rank).
void commit()
Commit the part and field declarations so that the meta data manager can be used to create mesh bulk ...
Definition: MetaData.cpp:368
void declare_field_restriction(FieldBase &arg_field, EntityRank arg_entity_rank, const Part &arg_part, const unsigned *arg_stride, const void *arg_init_value=NULL)
Declare a field restriction via runtime type information.
Definition: MetaData.cpp:303