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 
stk_classic::mesh::FieldBase
Field base class with an anonymous data type and anonymous multi-dimension.
Definition: FieldBase.hpp:53
stk_classic::mesh::MetaData::MetaData
MetaData()
Construct a meta data manager to own parts and fields.
Definition: MetaData.cpp:133
stk_classic::mesh::FieldRelation::m_target
FieldBase * m_target
relation range part
Definition: FieldRelation.hpp:79
stk_classic::mesh::MetaData::get_parts
const PartVector & get_parts() const
Query all parts of the mesh ordered by the parts' ordinal.
Definition: MetaData.hpp:120
stk_classic::mesh::EntityKey
Integer type for the entity keys, which is an encoding of the entity type and entity identifier.
Definition: base/EntityKey.hpp:63
stk_classic::mesh::MetaData::declare_field_base
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
stk_classic::mesh::PartRelation
A defined entity-relationship between parts. An internal class that should never need to be directly...
Definition: PartRelation.hpp:33
stk_classic::mesh::MetaData::declare_part
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
stk_classic::mesh::MetaData::get_fields
const FieldVector & get_fields() const
Get all defined fields.
Definition: MetaData.hpp:218
stk_classic::mesh::MetaData::get_part
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
stk_classic::mesh::Part
An application-defined subset of a problem domain.
Definition: Part.hpp:49
stk_classic::mesh::Part::mesh_meta_data_ordinal
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
stk_classic::mesh::MetaData::commit
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
stk_classic::mesh::MetaData::~MetaData
~MetaData()
Destroy the meta data manager and all of the parts and fields that it owns.
Definition: MetaData.cpp:375
stk_classic::ParallelMachine
MPI_Comm ParallelMachine
Definition: Parallel.hpp:32
stk_classic::mesh::MetaData::declare_part_relation
void declare_part_relation(Part &root_part, relation_stencil_ptr stencil, Part &target_part)
Declare an entity-relationship between parts.
Definition: MetaData.cpp:257
stk_classic::mesh::verify_parallel_consistency
void verify_parallel_consistency(const MetaData &s, ParallelMachine pm)
Verify that the meta data is identical on all processors.
Definition: MetaData.cpp:501
stk_classic::mesh::Part::subsets
const PartVector & subsets() const
Parts that are subsets of this part.
Definition: Part.hpp:78
stk_classic::mesh::FieldRelation::m_root
FieldBase * m_root
relation domain part
Definition: FieldRelation.hpp:76
stk_classic::mesh::MetaData::declare_field_restriction
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
stk_classic::mesh::relation_stencil_ptr
int(* relation_stencil_ptr)(unsigned from_type, unsigned to_type, unsigned identifier)
A relation stencil maps entity relationships to ordinals.
Definition: Types.hpp:149
stk_classic
Sierra Toolkit.
Definition: AlgorithmRunner.cpp:16
stk_classic::mesh::MetaData::set_entity_rank_names
void set_entity_rank_names(const std::vector< std::string > &entity_rank_names)
entity-rank names
Definition: MetaData.cpp:155
stk_classic::mesh::entity_id
EntityId entity_id(const EntityKey &key)
Given an entity key, return the identifier for the entity.
Definition: base/EntityKey.hpp:167
stk_classic::mesh::MetaData
The manager of an integrated collection of parts and fields.
Definition: MetaData.hpp:56
stk_classic::mesh::PartVector
std::vector< Part * > PartVector
Collections of parts are frequently maintained as a vector of Part pointers.
Definition: Types.hpp:31
stk_classic::mesh::find
Part * find(const PartVector &parts, const std::string &name)
Find a part by name in a collection of parts.
Definition: Part.cpp:22
stk_classic::mesh::Selector
This is a class for selecting buckets based on a set of meshparts and set logic.
Definition: Selector.hpp:112
stk_classic::mesh::entity_rank
EntityRank entity_rank(const EntityKey &key)
Given an entity key, return an entity type (rank).
Definition: base/EntityKey.hpp:161
stk_classic::mesh::PartRelation::m_root
Part * m_root
relation domain part
Definition: PartRelation.hpp:35
stk_classic::mesh::MetaData::check_rank
bool check_rank(EntityRank rank) const
stk_classic::mesh::Part::name
const std::string & name() const
Application-defined text name of this part.
Definition: Part.hpp:67
stk_classic::mesh::Part::intersection_of
const PartVector & intersection_of() const
Parts for which this part is defined as the intersection.
Definition: Part.hpp:81
stk_classic::mesh::FieldRelation::m_function
relation_stencil_ptr m_function
relation stencil
Definition: FieldRelation.hpp:82
stk_classic::mesh::FieldRelation
A defined entity-relationship between a field of a pointer type and the field that it should point to...
Definition: FieldRelation.hpp:74
stk_classic::mesh::Part::supersets
const PartVector & supersets() const
Parts that are supersets of this part.
Definition: Part.hpp:75
stk_classic::equal_case
bool equal_case(const char *lhs, const char *rhs)
Case-insensitive equality compare.
Definition: string_case_compare.hpp:27
stk_classic::parallel_machine_rank
unsigned parallel_machine_rank(ParallelMachine parallel_machine)
Member function parallel_machine_rank ...
Definition: Parallel.cpp:29
stk_classic::mesh::intersect
size_t intersect(const PartVector &v, const PartVector &p)
Query cardinality of intersection of two PartVectors.
Definition: Part.cpp:141
stk_classic::mesh::MetaData::declare_part_subset
void declare_part_subset(Part &superset, Part &subset)
Declare a superset-subset relationship between parts.
Definition: MetaData.cpp:240