Sierra Toolkit  Version of the Day
UnitTestSkinIrregular.cpp
1 /*------------------------------------------------------------------------*/
2 /* Copyright 2010, 2011 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 
9 #include <algorithm>
10 #include <stdexcept>
11 
12 #include <stk_util/unit_test_support/stk_utest_macros.hpp>
13 
14 #include <Shards_BasicTopologies.hpp>
15 
16 #include <stk_util/parallel/Parallel.hpp>
17 
18 #include <stk_mesh/base/Types.hpp>
19 #include <stk_mesh/base/MetaData.hpp>
20 #include <stk_mesh/base/BulkData.hpp>
21 #include <stk_mesh/base/Entity.hpp>
22 #include <stk_mesh/base/GetEntities.hpp>
23 #include <stk_mesh/base/GetBuckets.hpp>
24 #include <stk_mesh/base/Selector.hpp>
25 #include <stk_mesh/base/Field.hpp>
26 #include <stk_mesh/base/DataTraits.hpp>
27 
28 #include <stk_mesh/fem/FEMMetaData.hpp>
29 #include <stk_mesh/fem/FEMHelpers.hpp>
30 #include <stk_mesh/fem/TopologyDimensions.hpp>
31 #include <stk_mesh/fem/SkinMesh.hpp>
32 
33 #include <stk_util/parallel/ParallelReduce.hpp>
34 
35 #include <iostream>
36 
37 using stk_classic::mesh::EntityId;
38 using stk_classic::mesh::EntityRank;
39 
40 //---------------------------------------------------------------------------------------
41 
42 STKUNIT_UNIT_TEST( UnitTestSkin, SkinPocket)
43 {
44  enum { SpatialDim = 3 };
45 
46  stk_classic::ParallelMachine pm = MPI_COMM_WORLD ;
47  const unsigned p_rank = stk_classic::parallel_machine_rank( pm );
48  const unsigned p_size = stk_classic::parallel_machine_size( pm );
49 
51  fem_meta.FEM_initialize(SpatialDim, stk_classic::mesh::fem::entity_rank_names(SpatialDim));
53  stk_classic::mesh::BulkData bulk_data( meta_data , pm );
54  stk_classic::mesh::fem::CellTopology hex_top(shards::getCellTopologyData<shards::Hexahedron<8> >());
55  stk_classic::mesh::Part & hex_part = fem_meta.declare_part( "hex_part", hex_top );
56  const EntityRank element_rank = fem_meta.element_rank();
57  const EntityRank side_rank = fem_meta.side_rank();
58 
59  //create and skin a 2 hex-element mesh with a pocket
60  //in a normal mesh 6 and 13 would be the same node
61  //
62  // 8-------7-------12
63  // /| /|\ /|
64  // / | / | \ / |
65  // 5-------6 | 13-11 |
66  // | 4----|--3/---|--10
67  // | / | // | /
68  // |/ |// |/
69  // 1-------2-------9
70  //
71 
72  fem_meta.commit();
73 
74  bulk_data.modification_begin();
75 
76  // declare left element on first process
77  if (p_rank == 0)
78  {
79  EntityId element_id = 1;
80  EntityId node_ids[8] = { 1, 2, 3, 4, 5, 6, 7, 8};
81 
82  stk_classic::mesh::fem::declare_element( bulk_data, hex_part, element_id, node_ids);
83 
84  }
85 
86  // declare right element on last process
87  if (p_rank == p_size -1)
88  {
89  EntityId element_id = 2;
90  EntityId node_ids[8] = { 2, 9, 10, 3, 13, 11, 12, 7};
91 
92  stk_classic::mesh::fem::declare_element( bulk_data, hex_part, element_id, node_ids);
93  }
94 
95  bulk_data.modification_end();
96 
97  //skin the mesh
98  stk_classic::mesh::skin_mesh(bulk_data, element_rank);
99 
100  //each element should have 6 faces attached to it
101  for (EntityId element_id = 1; element_id < 3; ++element_id) {
102  stk_classic::mesh::Entity * element = bulk_data.get_entity( element_rank, element_id);
103  if ( element != NULL) {
104  stk_classic::mesh::PairIterRelation element_side_relations = element->relations(side_rank);
105  STKUNIT_EXPECT_TRUE( element_side_relations.size() == 6);
106  }
107  }
108 }
109 
110 STKUNIT_UNIT_TEST( UnitTestSkin, SkinTwoStackedShells)
111 {
112  enum { SpatialDim = 3 };
113 
114  stk_classic::ParallelMachine pm = MPI_COMM_WORLD ;
115  const unsigned p_rank = stk_classic::parallel_machine_rank( pm );
116  const unsigned p_size = stk_classic::parallel_machine_size( pm );
117 
119  fem_meta.FEM_initialize(SpatialDim, stk_classic::mesh::fem::entity_rank_names(SpatialDim));
121  stk_classic::mesh::BulkData bulk_data( meta_data , pm );
122  stk_classic::mesh::fem::CellTopology shell_top(shards::getCellTopologyData<shards::ShellQuadrilateral<4> >());
123  stk_classic::mesh::Part & shell_part = fem_meta.declare_part( "shell_part", shell_top );
124  const EntityRank element_rank = fem_meta.element_rank();
125  const EntityRank side_rank = fem_meta.side_rank();
126 
127  fem_meta.commit();
128 
129  //create and skin stacked shells
130  // 4-------3
131  // | |
132  // | |
133  // | |
134  // 1-------2
135  //
136  // create following 8 shells
137  // shells 1 defined with right hand rule
138  // shells 2 defined with left hand rule
139  //
140  // shell_id: node_list
141  // 1: (1,2,3,4)
142  // 2: (1,2,3,4)
143 
144  EntityId node_ids[4] = { 1, 2, 3, 4};
145 
146  bulk_data.modification_begin();
147 
148  {
149  bool create_shell_on_proc = static_cast<int>(p_rank) == 0;
150  if (create_shell_on_proc) {
151  EntityId element_id = static_cast<EntityId>(1);
152  stk_classic::mesh::fem::declare_element( bulk_data, shell_part, element_id, node_ids);
153  }
154  }
155 
156  {
157  bool create_shell_on_proc = static_cast<int>(p_rank) == (std::max(0,static_cast<int>(p_size)-1));
158  if (create_shell_on_proc) {
159  EntityId element_id = static_cast<EntityId>(2);
160  stk_classic::mesh::fem::declare_element( bulk_data, shell_part, element_id, node_ids);
161  }
162  }
163 
164  bulk_data.modification_end();
165 
166  //skin the mesh
167  stk_classic::mesh::skin_mesh(bulk_data, element_rank);
168 
169  //count number of sides in mesh
170  {
171  stk_classic::mesh::Selector select_sides = meta_data.locally_owned_part() ;
172  const std::vector<stk_classic::mesh::Bucket*>& side_buckets = bulk_data.buckets(side_rank);
173  int num_sides = stk_classic::mesh::count_selected_entities( select_sides, side_buckets);
174 
175 
176  stk_classic::all_reduce(MPI_COMM_WORLD, stk_classic::ReduceSum<1>(&num_sides));
177 
178  // Verify that the correct 2 sides are present.
179 
180  STKUNIT_ASSERT_EQUAL( num_sides, 2 );
181  }
182 }
183 
184 //---------------------------------------------------------------------------------------
185 STKUNIT_UNIT_TEST( UnitTestSkin, SkinStackedShells)
186 {
187  enum { SpatialDim = 3 };
188 
189  stk_classic::ParallelMachine pm = MPI_COMM_WORLD ;
190  const unsigned p_rank = stk_classic::parallel_machine_rank( pm );
191  const unsigned p_size = stk_classic::parallel_machine_size( pm );
192 
194  fem_meta.FEM_initialize(SpatialDim, stk_classic::mesh::fem::entity_rank_names(SpatialDim));
196  stk_classic::mesh::BulkData bulk_data( meta_data , pm );
197  stk_classic::mesh::fem::CellTopology shell_top(shards::getCellTopologyData<shards::ShellQuadrilateral<4> >());
198  stk_classic::mesh::Part & shell_part = fem_meta.declare_part( "shell_part", shell_top );
199  const EntityRank element_rank = fem_meta.element_rank();
200  const EntityRank side_rank = fem_meta.side_rank();
201 
202  fem_meta.commit();
203 
204  //create and skin stacked shells
205  // 4-------3
206  // | |
207  // | |
208  // | |
209  // 1-------2
210  //
211  // create following 8 shells
212  // shells 1-4 defined with right hand rule
213  // shells 5-6 defined with left hand rule
214  //
215  // shell_id: node_list
216  // 1: (1,2,3,4)
217  // 2: (2,3,4,1)
218  // 3: (3,4,1,2)
219  // 4: (4,1,2,3)
220  // 5: (4,3,2,1)
221  // 6: (3,2,1,4)
222  // 7: (2,1,4,3)
223  // 8: (1,4,3,2)
224 
225  EntityId node_ids[8] = { 1, 2, 3, 4, 1, 2, 3, 4};
226  EntityId reverse_node_ids[8] = { 4, 3, 2, 1, 4, 3, 2, 1};
227 
228  bulk_data.modification_begin();
229 
230  //create shells
231  for ( int i = 0; i<4; i++ ) {
232 
233  bool create_shell_on_proc = static_cast<int>(p_rank) == (std::max(0,static_cast<int>(p_size)-1-i));
234  if (create_shell_on_proc) {
235  EntityId element_id = static_cast<EntityId>(i+1);
236  stk_classic::mesh::fem::declare_element( bulk_data, shell_part, element_id, node_ids+i);
237  }
238 
239  bool create_reverse_shell_on_proc = static_cast<int>(p_rank) == (std::max(0,static_cast<int>(p_size)-1-4-i));
240  if (create_reverse_shell_on_proc) {
241  EntityId reverse_element_id = static_cast<EntityId>(i+1+4);
242  stk_classic::mesh::fem::declare_element( bulk_data, shell_part, reverse_element_id, reverse_node_ids+i);
243  }
244  }
245 
246  bulk_data.modification_end();
247 
248  //skin the mesh
249  stk_classic::mesh::skin_mesh(bulk_data, element_rank);
250 
251  //count number of sides in mesh
252  {
253  stk_classic::mesh::Selector select_sides = meta_data.locally_owned_part() ;
254  const std::vector<stk_classic::mesh::Bucket*>& side_buckets = bulk_data.buckets( side_rank);
255  int num_sides = stk_classic::mesh::count_selected_entities( select_sides, side_buckets);
256 
257 
258  stk_classic::all_reduce(MPI_COMM_WORLD, stk_classic::ReduceSum<1>(&num_sides));
259 
260  // Verify that the correct 2 sides are present.
261 
262  STKUNIT_ASSERT_EQUAL( num_sides, 2 );
263  }
264 
265  //check that faces are attached to correct sides
266  {
267  EntityId face_1_id = 0; //invalid face id
268  EntityId face_2_id = 0; //invalid face id
269  for (EntityId shell_id = 1; shell_id < 5; ++shell_id) {
270  stk_classic::mesh::Entity * shell = bulk_data.get_entity( element_rank, shell_id);
271  if ( shell != NULL) {
272  stk_classic::mesh::PairIterRelation shell_side_relations = shell->relations(side_rank);
273 
274  STKUNIT_ASSERT_TRUE( shell_side_relations.size() == 2);
275 
276  // verify that only one side has been created
277  // and that all stacked shells reference this side
278  if (face_1_id == 0) {
279  face_1_id = shell_side_relations->entity()->identifier();
280  }
281  else {
282  STKUNIT_EXPECT_TRUE( face_1_id == shell_side_relations->entity()->identifier());
283  }
284 
285  //check that the side is one the correct local side of the shell
286  STKUNIT_EXPECT_TRUE( shell_side_relations->identifier() == 0);
287 
288  ++shell_side_relations;
289 
290  if (face_2_id == 0) {
291  face_2_id = shell_side_relations->entity()->identifier();
292  }
293  else {
294  STKUNIT_EXPECT_TRUE( face_2_id == shell_side_relations->entity()->identifier());
295  }
296 
297  //check that the side is one the correct local side of the shell
298  STKUNIT_EXPECT_TRUE( shell_side_relations->identifier() == 1);
299 
300  }
301  }
302 
303  for (EntityId shell_id = 5; shell_id < 9; ++shell_id) {
304  stk_classic::mesh::Entity * shell = bulk_data.get_entity( element_rank, shell_id);
305  if ( shell != NULL) {
306  stk_classic::mesh::PairIterRelation shell_side_relations = shell->relations(side_rank);
307 
308  STKUNIT_ASSERT_TRUE( shell_side_relations.size() == 2);
309 
310  // verify that only one side has been created
311  // and that all stacked shells reference this side
312  if (face_2_id == 0) {
313  face_2_id = shell_side_relations->entity()->identifier();
314  }
315  else {
316  STKUNIT_EXPECT_TRUE( face_2_id == shell_side_relations->entity()->identifier());
317  }
318 
319  //check that the side is one the correct local side of the shell
320  STKUNIT_EXPECT_TRUE( shell_side_relations->identifier() == 0);
321 
322  ++shell_side_relations;
323 
324  if (face_1_id == 0) {
325  face_1_id = shell_side_relations->entity()->identifier();
326  }
327  else {
328  STKUNIT_EXPECT_TRUE( face_1_id == shell_side_relations->entity()->identifier());
329  }
330 
331  //check that the side is one the correct local side of the shell
332  STKUNIT_EXPECT_TRUE( shell_side_relations->identifier() == 1);
333 
334  }
335  }
336  }
337 }
338 
339 //---------------------------------------------------------------------------------------
340 
341 STKUNIT_UNIT_TEST( UnitTestSkin, SkinShellOnHex)
342 {
343  enum { SpatialDim = 3 };
344 
345  stk_classic::ParallelMachine pm = MPI_COMM_WORLD ;
346  const unsigned p_rank = stk_classic::parallel_machine_rank( pm );
347  const unsigned p_size = stk_classic::parallel_machine_size( pm );
348 
350  fem_meta.FEM_initialize(SpatialDim, stk_classic::mesh::fem::entity_rank_names(SpatialDim));
352  stk_classic::mesh::BulkData bulk_data( meta_data , pm );
353  stk_classic::mesh::fem::CellTopology hex_top(shards::getCellTopologyData<shards::Hexahedron<8> >());
354  stk_classic::mesh::Part & hex_part = fem_meta.declare_part( "hex_part", hex_top );
355  stk_classic::mesh::fem::CellTopology shell_top(shards::getCellTopologyData<shards::ShellQuadrilateral<4> >());
356  stk_classic::mesh::Part & shell_part = fem_meta.declare_part( "shell_part", shell_top );
357  const EntityRank element_rank = fem_meta.element_rank();
358  const EntityRank side_rank = fem_meta.side_rank();
359 
360  //create and skin a hex element mesh with a shell on the first side of the hex
361  // Using a shell defined by the nodes (1, 2, 6, 5) produces an orientated shell
362  //
363  // Therefore the shell will be skinned with 1 side and the hex will have 5.
364  //
365  // 8-------7
366  // /| /|
367  // / | / |
368  // 5=======6 |
369  // || 4----||-3
370  // ||/ ||/
371  // |/ |/
372  // 1=======2
373  //
374 
375  fem_meta.commit();
376 
377  bulk_data.modification_begin();
378 
379  // declare hex element on first process
380  if (p_rank == 0)
381  {
382  EntityId element_id = 1;
383  EntityId node_ids[8] = { 1, 2, 3, 4, 5, 6, 7, 8};
384 
385  stk_classic::mesh::fem::declare_element( bulk_data, hex_part, element_id, node_ids);
386 
387  }
388 
389  // declare shell element on last process
390  if (p_rank == p_size -1)
391  {
392  EntityId element_id = 2;
393  EntityId node_ids[8] = { 1, 2, 6, 5};
394 
395  stk_classic::mesh::fem::declare_element( bulk_data, shell_part, element_id, node_ids);
396  }
397 
398  bulk_data.modification_end();
399 
400  //skin the mesh
401  stk_classic::mesh::skin_mesh(bulk_data, element_rank);
402 
403  //check hex
404  {
405  EntityId hex_id = 1;
406  stk_classic::mesh::Entity * element = bulk_data.get_entity( element_rank, hex_id);
407  if ( element != NULL) {
408  stk_classic::mesh::PairIterRelation element_side_relations = element->relations(side_rank);
409  STKUNIT_EXPECT_TRUE( element_side_relations.size() == 5);
410  for (; !element_side_relations.empty(); ++element_side_relations) {
411  unsigned local_side_id = element_side_relations->identifier();
412  bool correct_side_skinned = local_side_id > 0 && local_side_id < 6;
413  STKUNIT_EXPECT_TRUE (correct_side_skinned);
414  std::cout << "Hex local side id: " << local_side_id << std::endl;
415  }
416  }
417  }
418 
419  //check shell
420  {
421  EntityId shell_id = 2;
422  stk_classic::mesh::Entity * element = bulk_data.get_entity( element_rank, shell_id);
423  if ( element != NULL) {
424  stk_classic::mesh::PairIterRelation element_side_relations = element->relations(side_rank);
425  STKUNIT_EXPECT_TRUE( element_side_relations.size() == 1);
426  for (; !element_side_relations.empty(); ++element_side_relations) {
427  unsigned local_side_id = element_side_relations->identifier();
428  bool correct_side_skinned = local_side_id == 0;
429  STKUNIT_EXPECT_TRUE (correct_side_skinned);
430  std::cout << "Shell local side id: " << local_side_id << std::endl;
431  }
432  }
433  }
434 }
435 
436 //---------------------------------------------------------------------------------------
437 
438 STKUNIT_UNIT_TEST( UnitTestSkin, SkinInvertedShellOnHex)
439 {
440  enum { SpatialDim = 3 };
441 
442  stk_classic::ParallelMachine pm = MPI_COMM_WORLD ;
443  const unsigned p_rank = stk_classic::parallel_machine_rank( pm );
444  const unsigned p_size = stk_classic::parallel_machine_size( pm );
445 
447  fem_meta.FEM_initialize(SpatialDim, stk_classic::mesh::fem::entity_rank_names(SpatialDim));
449  stk_classic::mesh::BulkData bulk_data( meta_data , pm );
450  stk_classic::mesh::fem::CellTopology hex_top(shards::getCellTopologyData<shards::Hexahedron<8> >());
451  stk_classic::mesh::Part & hex_part = fem_meta.declare_part( "hex_part", hex_top );
452  stk_classic::mesh::fem::CellTopology shell_top(shards::getCellTopologyData<shards::ShellQuadrilateral<4> >());
453  stk_classic::mesh::Part & shell_part = fem_meta.declare_part( "shell_part", shell_top );
454  const EntityRank element_rank = fem_meta.element_rank();
455  const EntityRank side_rank = fem_meta.side_rank();
456 
457  //create and skin a hex element mesh with an inverted shell
458  // Using a shell defined by the nodes (1, 2, 5, 6) produces an inverted shell
459  // with no valid orientation
460  //
461  // Therefore the shell will be skinned with 2 sides and the hex will have 6.
462  //
463  // 8-------7
464  // /| /|
465  // / | / |
466  // 5=======6 |
467  // || 4----||-3
468  // ||/ ||/
469  // |/ |/
470  // 1=======2
471  //
472 
473  fem_meta.commit();
474 
475  bulk_data.modification_begin();
476 
477  // declare hex element on first process
478  if (p_rank == 0)
479  {
480  EntityId element_id = 1;
481  EntityId node_ids[8] = { 1, 2, 3, 4, 5, 6, 7, 8};
482 
483  stk_classic::mesh::fem::declare_element( bulk_data, hex_part, element_id, node_ids);
484 
485  }
486 
487  // declare shell element on last process
488  if (p_rank == p_size -1)
489  {
490  EntityId element_id = 2;
491  EntityId node_ids[8] = { 1, 2, 5, 6};
492 
493  stk_classic::mesh::fem::declare_element( bulk_data, shell_part, element_id, node_ids);
494  }
495 
496  bulk_data.modification_end();
497 
498  //skin the mesh
499  stk_classic::mesh::skin_mesh(bulk_data, element_rank);
500 
501  //check hex
502  {
503  EntityId hex_id = 1;
504  stk_classic::mesh::Entity * element = bulk_data.get_entity( element_rank, hex_id);
505  if ( element != NULL) {
506  stk_classic::mesh::PairIterRelation element_side_relations = element->relations(side_rank);
507  STKUNIT_EXPECT_TRUE( element_side_relations.size() == 6);
508  for (; !element_side_relations.empty(); ++element_side_relations) {
509  unsigned local_side_id = element_side_relations->identifier();
510  bool correct_side_skinned = local_side_id < 6;
511  STKUNIT_EXPECT_TRUE (correct_side_skinned);
512  std::cout << "Hex local side id: " << local_side_id << std::endl;
513  }
514  }
515  }
516 
517  //check shell
518  {
519  EntityId shell_id = 2;
520  stk_classic::mesh::Entity * element = bulk_data.get_entity( element_rank, shell_id);
521  if ( element != NULL) {
522  stk_classic::mesh::PairIterRelation element_side_relations = element->relations(side_rank);
523  STKUNIT_EXPECT_TRUE( element_side_relations.size() == 2);
524  for (; !element_side_relations.empty(); ++element_side_relations) {
525  unsigned local_side_id = element_side_relations->identifier();
526  bool correct_side_skinned = local_side_id < 2;
527  STKUNIT_EXPECT_TRUE (correct_side_skinned);
528  std::cout << "Shell local side id: " << element_side_relations->identifier() << std::endl;
529  }
530  }
531  }
532 }
533 
534 //---------------------------------------------------------------------------------------
535 
536 STKUNIT_UNIT_TEST( UnitTestSkin, SkinStackedShellOnHex)
537 {
538  enum { SpatialDim = 3 };
539 
540  stk_classic::ParallelMachine pm = MPI_COMM_WORLD ;
541  const unsigned p_rank = stk_classic::parallel_machine_rank( pm );
542  const unsigned p_size = stk_classic::parallel_machine_size( pm );
543 
545  fem_meta.FEM_initialize(SpatialDim, stk_classic::mesh::fem::entity_rank_names(SpatialDim));
547  stk_classic::mesh::BulkData bulk_data( meta_data , pm );
548  stk_classic::mesh::fem::CellTopology hex_top(shards::getCellTopologyData<shards::Hexahedron<8> >());
549  stk_classic::mesh::Part & hex_part = fem_meta.declare_part( "hex_part", hex_top );
550  stk_classic::mesh::fem::CellTopology shell_top(shards::getCellTopologyData<shards::ShellQuadrilateral<4> >());
551  stk_classic::mesh::Part & shell_part = fem_meta.declare_part( "shell_part", shell_top );
552  const EntityRank element_rank = fem_meta.element_rank();
553  const EntityRank side_rank = fem_meta.side_rank();
554 
555  //create and skin a hex element mesh with 3 shells on the first side of the hex
556  // Using shells defined by the nodes (1, 2, 6, 5), (6, 5, 1, 2), and (1, 5, 6, 2)
557  // produces an orientated shells.
558  //
559  // Therefore the shells will all have a relation to the same side.
560  //
561  // 8-------7
562  // /| /|
563  // / | / |
564  // 5=======6 |
565  // || 4----||-3
566  // ||/ ||/
567  // |/ |/
568  // 1=======2
569  //
570 
571  fem_meta.commit();
572 
573  bulk_data.modification_begin();
574 
575  bool create_hex_this_proc = (p_rank == 0);
576  bool create_shell_1_this_proc = static_cast<int>(p_rank) == (std::max(0,static_cast<int>(p_size)-3));
577  bool create_shell_2_this_proc = static_cast<int>(p_rank) == (std::max(0,static_cast<int>(p_size)-2));
578  bool create_shell_3_this_proc = (p_rank == p_size -1);
579 
580  if (create_hex_this_proc)
581  {
582  EntityId element_id = 1;
583  EntityId node_ids[8] = { 1, 2, 3, 4, 5, 6, 7, 8};
584 
585  stk_classic::mesh::fem::declare_element( bulk_data, hex_part, element_id, node_ids);
586 
587  }
588 
589  if (create_shell_1_this_proc)
590  {
591  EntityId element_id = 2;
592  EntityId node_ids[8] = { 1, 2, 6, 5};
593 
594  stk_classic::mesh::fem::declare_element( bulk_data, shell_part, element_id, node_ids);
595  }
596 
597  if (create_shell_2_this_proc)
598  {
599  EntityId element_id = 3;
600  EntityId node_ids[8] = { 6, 5, 1, 2};
601 
602  stk_classic::mesh::fem::declare_element( bulk_data, shell_part, element_id, node_ids);
603  }
604 
605  if (create_shell_3_this_proc)
606  {
607  EntityId element_id = 4;
608  EntityId node_ids[8] = { 1, 5, 6, 2};
609 
610  stk_classic::mesh::fem::declare_element( bulk_data, shell_part, element_id, node_ids);
611  }
612 
613  bulk_data.modification_end();
614 
615  //skin the mesh
616  stk_classic::mesh::skin_mesh(bulk_data, element_rank);
617 
618  //check hex
619  {
620  EntityId hex_id = 1;
621  stk_classic::mesh::Entity * element = bulk_data.get_entity( element_rank, hex_id);
622  if ( element != NULL) {
623  stk_classic::mesh::PairIterRelation element_side_relations = element->relations(side_rank);
624  STKUNIT_EXPECT_TRUE( element_side_relations.size() == 5);
625  for (; !element_side_relations.empty(); ++element_side_relations) {
626  unsigned local_side_id = element_side_relations->identifier();
627  bool correct_side_skinned = local_side_id > 0 && local_side_id < 6;
628  STKUNIT_EXPECT_TRUE (correct_side_skinned);
629  std::cout << "Hex local side id: " << local_side_id << std::endl;
630  }
631  }
632  }
633 
634  //check shells
635  {
636  EntityId face_id = 0; //invalid face id
637  for (EntityId shell_id = 2; shell_id < 5; ++shell_id) {
638  stk_classic::mesh::Entity * shell = bulk_data.get_entity( element_rank, shell_id);
639  if ( shell != NULL) {
640  stk_classic::mesh::PairIterRelation shell_side_relations = shell->relations(side_rank);
641 
642  STKUNIT_EXPECT_TRUE( shell_side_relations.size() == 1);
643 
644  // verify that only one side has been created
645  // and that all stacked shells reference this side
646  if (face_id == 0) {
647  face_id = shell_side_relations->entity()->identifier();
648  }
649  else {
650  STKUNIT_EXPECT_TRUE( face_id == shell_side_relations->entity()->identifier());
651  std::cout << "Shell: " << shell_id
652  << "\tFace_id: " << face_id
653  << "\tFace_id: " << shell_side_relations->entity()->identifier()
654  << std::endl;
655  }
656 
657  //check that the side is one the correct local side of the shell
658  //shells 1 and 2 follow the right hand rule so the side should be on
659  //local_side_id 0.
660  //shell 3 should have it's side on local_side_1d 1
661  if (shell_id != 4) {
662  STKUNIT_EXPECT_TRUE( shell_side_relations->identifier() == 0);
663  }
664  else {
665  STKUNIT_EXPECT_TRUE( shell_side_relations->identifier() == 1);
666  }
667  }
668  }
669  }
670 }
FEMMetaData is a class that implements a Finite Element Method skin on top of the Sierra Tool Kit Met...
Definition: FEMMetaData.hpp:54
The manager of an integrated collection of parts and fields.
Definition: MetaData.hpp:56
unsigned count_selected_entities(const Selector &selector, const std::vector< Bucket * > &input_buckets)
Count entities in selected buckets (selected by the given selector instance), and sorted by ID...
Definition: GetEntities.cpp:59
EntityRank side_rank() const
Returns the side rank which changes depending on spatial dimension.
Entity & declare_element(BulkData &mesh, Part &part, const EntityId elem_id, const EntityId node_id[])
Declare an element member of a Part with a CellTopology and nodes conformal to that topology...
Definition: FEMHelpers.cpp:72
EntityRank element_rank() const
Returns the element rank which is always equal to spatial dimension.
This is a class for selecting buckets based on a set of meshparts and set logic.
Definition: Selector.hpp:112
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
Part & locally_owned_part() const
Subset for the problem domain that is owned by the local process. Ghost entities are not members of t...
Definition: MetaData.hpp:93
Part & declare_part(const std::string &name, fem::CellTopology cell_topology)
Declare a part with a given cell topology.
PairIterRelation relations() const
All Entity relations for which this entity is a member. The relations are ordered from lowest entity-...
Definition: Entity.hpp:161
unsigned parallel_machine_size(ParallelMachine parallel_machine)
Member function parallel_machine_size ...
Definition: Parallel.cpp:18
Manager for an integrated collection of entities, entity relations, and buckets of field data...
Definition: BulkData.hpp:49
static MetaData & get_meta_data(FEMMetaData &fem_meta)
Getter for MetaData off of a FEMMetaData object.
void commit()
Commit the part and field declarations so that the meta data manager can be used to create mesh bulk ...
A fundamental unit within the discretization of a problem domain, including but not limited to nodes...
Definition: Entity.hpp:120
MPI_Comm ParallelMachine
Definition: Parallel.hpp:32
void all_reduce(ParallelMachine, const ReduceOp &)
void FEM_initialize(size_t spatial_dimension, const std::vector< std::string > &in_entity_rank_names=std::vector< std::string >())
Initialize the spatial dimension and an optional list of entity rank names associated with each rank...
Definition: FEMMetaData.cpp:61