Sierra Toolkit Version of the Day
UnitTestSkinning.cpp
00001 /*------------------------------------------------------------------------*/
00002 /*                 Copyright 2010, 2011 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 #include <stk_util/unit_test_support/stk_utest_macros.hpp>
00010 
00011 #include <stk_util/parallel/Parallel.hpp>
00012 
00013 #include <stk_mesh/base/MetaData.hpp>
00014 #include <stk_mesh/base/BulkData.hpp>
00015 #include <stk_mesh/base/Entity.hpp>
00016 #include <stk_mesh/base/GetEntities.hpp>
00017 #include <stk_mesh/base/Selector.hpp>
00018 #include <stk_mesh/base/GetBuckets.hpp>
00019 #include <stk_mesh/base/Comm.hpp>
00020 
00021 #include <stk_mesh/fem/BoundaryAnalysis.hpp>
00022 #include <stk_mesh/fem/SkinMesh.hpp>
00023 #include <stk_mesh/fem/FEMHelpers.hpp>
00024 
00025 #include <stk_mesh/fixtures/GridFixture.hpp>
00026 
00027 #include <stk_util/parallel/ParallelReduce.hpp>
00028 
00029 #include <Shards_BasicTopologies.hpp>
00030 
00031 #include <iomanip>
00032 #include <algorithm>
00033 
00034 static const size_t NODE_RANK = stk::mesh::fem::FEMMetaData::NODE_RANK;
00035 
00036 class UnitTestStkMeshSkinning {
00037 public:
00038   UnitTestStkMeshSkinning(stk::ParallelMachine pm) : m_comm(pm),  m_num_procs(0), m_rank(0)
00039   {
00040     m_num_procs = stk::parallel_machine_size( m_comm );
00041     m_rank = stk::parallel_machine_rank( m_comm );
00042   }
00043 
00044   void test_skinning();
00045 
00046   stk::ParallelMachine m_comm;
00047   int m_num_procs;
00048   int m_rank;
00049 };
00050 
00051 namespace {
00052 
00053 STKUNIT_UNIT_TEST( UnitTestStkMeshSkinning , testUnit )
00054 {
00055   UnitTestStkMeshSkinning unit(MPI_COMM_WORLD);
00056   unit.test_skinning();
00057 }
00058 
00059 STKUNIT_UNIT_TEST( UnitTestStkMeshSkinning , testSingleShell )
00060 {
00061   const int spatial_dimension = 3;
00062   stk::mesh::fem::FEMMetaData fem_meta;
00063   fem_meta.FEM_initialize(spatial_dimension, stk::mesh::fem::entity_rank_names(spatial_dimension));
00064   stk::mesh::MetaData & meta_data = stk::mesh::fem::FEMMetaData::get_meta_data(fem_meta);
00065   stk::mesh::BulkData bulk_data( meta_data, MPI_COMM_WORLD );
00066   const stk::mesh::EntityRank element_rank = fem_meta.element_rank();
00067 
00068   const unsigned p_rank = bulk_data.parallel_rank();
00069 
00070   stk::mesh::Part & skin_part = fem_meta.declare_part("skin_part");
00071 
00072   stk::mesh::fem::CellTopology shell_top(shards::getCellTopologyData<shards::ShellQuadrilateral<4> >());
00073   stk::mesh::Part & shell_part = fem_meta.declare_part("shell_part", shell_top);
00074 
00075   fem_meta.commit();
00076 
00077   bulk_data.modification_begin();
00078 
00079   if ( p_rank == 0 ) {
00080 
00081     stk::mesh::EntityId elem_node[4] ;
00082 
00083     // Query nodes from this simple grid fixture via the (i,j,k) indices.
00084     elem_node[0] = 1;
00085     elem_node[1] = 2;
00086     elem_node[2] = 3;
00087     elem_node[3] = 4;
00088 
00089     stk::mesh::EntityId elem_id = 1;
00090 
00091     stk::mesh::fem::declare_element( bulk_data, shell_part, elem_id, elem_node);
00092 
00093   }
00094   bulk_data.modification_end();
00095 
00096 
00097   stk::mesh::skin_mesh( bulk_data, element_rank, &skin_part);
00098 
00099   {
00100     const unsigned mesh_rank = element_rank;
00101     const stk::mesh::MetaData & meta = stk::mesh::MetaData::get(bulk_data);
00102     stk::mesh::Selector select_skin = skin_part & meta.locally_owned_part()  ;
00103     const std::vector<stk::mesh::Bucket*>& buckets = bulk_data.buckets( mesh_rank -1);
00104     int num_skin_entities = stk::mesh::count_selected_entities( select_skin, buckets);
00105 
00106 
00107     stk::all_reduce(MPI_COMM_WORLD, stk::ReduceSum<1>(&num_skin_entities));
00108 
00109     // Verify that the correct 6 sides are present.
00110 
00111     STKUNIT_ASSERT_EQUAL( num_skin_entities, 2 );
00112   }
00113 }
00114 
00115 } //end namespace
00116 
00117 void UnitTestStkMeshSkinning::test_skinning()
00118 {
00119   // This test will only work for np=1
00120   if (m_num_procs > 1) {
00121     return;
00122   }
00123 
00124   stk::mesh::fixtures::GridFixture grid_mesh(MPI_COMM_WORLD);
00125 
00126   stk::mesh::BulkData& bulk_data = grid_mesh.bulk_data();
00127   stk::mesh::fem::FEMMetaData& fem_meta = grid_mesh.fem_meta();
00128   const stk::mesh::EntityRank element_rank = fem_meta.element_rank();
00129 
00130   // Create a part for the skin and the shells
00131   stk::mesh::Part & skin_part = fem_meta.declare_part("skin_part");
00132   stk::mesh::fem::CellTopology line_top(shards::getCellTopologyData<shards::ShellLine<2> >());
00133   stk::mesh::Part & shell_part = fem_meta.declare_part("shell_part", line_top);
00134   fem_meta.commit();
00135 
00136   // Begin modification cycle
00137   grid_mesh.bulk_data().modification_begin();
00138 
00139   // Generate the plain grid
00140   grid_mesh.generate_grid();
00141 
00142   // Add the shells
00143   std::vector<unsigned> count;
00144   stk::mesh::Selector locally_owned(fem_meta.locally_owned_part());
00145   stk::mesh::count_entities(locally_owned, bulk_data, count);
00146   const unsigned num_shell_1_faces = 4;
00147   const unsigned num_shell_2_faces = 2;
00148   const unsigned num_shell_faces = num_shell_1_faces + num_shell_2_faces;
00149   const unsigned num_entities = count[NODE_RANK] +
00150                                 count[element_rank];
00151 
00152   stk::mesh::PartVector shell_parts;
00153   shell_parts.push_back(&shell_part);
00154 
00155   std::vector<stk::mesh::Entity*> shell_faces;
00156   for (unsigned i = 1; i <= num_shell_faces; ++i) {
00157     stk::mesh::Entity& new_shell = bulk_data.declare_entity(element_rank,
00158                                                             num_entities + i,
00159                                                             shell_parts);
00160     shell_faces.push_back(&new_shell);
00161   }
00162 
00163   // Set up relationships for shells
00164 
00165   // declare shell relationships for first shell
00166   unsigned node_list_1[5] = {21, 26, 31, 36, 41};
00167   for (unsigned i = 0; i < num_shell_1_faces; ++i) {
00168     stk::mesh::Entity& shell = *(shell_faces[i]);
00169     stk::mesh::Entity& node1 = *(bulk_data.get_entity(NODE_RANK, node_list_1[i]));
00170     stk::mesh::Entity& node2 = *(bulk_data.get_entity(NODE_RANK, node_list_1[i+1]));
00171     bulk_data.declare_relation(shell, node1, 0);
00172     bulk_data.declare_relation(shell, node2, 1);
00173   }
00174 
00175   // declare shell relationships for second shell
00176   unsigned node_list_2[3] = {31, 36, 41};
00177   for (unsigned i = 0; i < num_shell_2_faces; ++i) {
00178     stk::mesh::Entity& shell = *(shell_faces[i + num_shell_1_faces]);
00179     stk::mesh::Entity& node1 = *(bulk_data.get_entity(NODE_RANK, node_list_2[i]));
00180     stk::mesh::Entity& node2 = *(bulk_data.get_entity(NODE_RANK, node_list_2[i+1]));
00181     bulk_data.declare_relation(shell, node1, 0);
00182     bulk_data.declare_relation(shell, node2, 1);
00183   }
00184 
00185   grid_mesh.bulk_data().modification_end();
00186 
00187   // skin the boundary
00188   stk::mesh::skin_mesh(bulk_data, element_rank, &skin_part);
00189 
00190   // Grab the skin entities
00191   stk::mesh::Selector skin_selector(skin_part);
00192   const std::vector<stk::mesh::Bucket*>& edge_buckets = bulk_data.buckets(fem_meta.edge_rank());
00193   std::vector<stk::mesh::Entity*> skin_entities;
00194   stk::mesh::get_selected_entities(skin_selector, edge_buckets, skin_entities);
00195 
00196   unsigned num_expected_skin_entites = 16;
00197   STKUNIT_EXPECT_EQUAL(num_expected_skin_entites, skin_entities.size());
00198 
00199   // Map the element id to the number of skins associated with that element
00200 
00201   std::map<unsigned, unsigned> results;
00202   std::map<unsigned, unsigned> expected_results;
00203 
00204   expected_results[1] = 2;
00205   expected_results[2] = 1;
00206   expected_results[3] = 1;
00207   expected_results[4] = 1;
00208   expected_results[5] = 1;
00209   expected_results[9] = 1;
00210   expected_results[13] = 2;
00211   expected_results[14] = 1;
00212   expected_results[15] = 1;
00213   expected_results[16] = 1;
00214   expected_results[42] = 1;
00215   expected_results[43] = 1;
00216   expected_results[44] = 1;
00217   expected_results[45] = 1;
00218   expected_results[46] = 1;
00219   expected_results[47] = 1;
00220 
00221   // Vector of of vector of entities (shells) that are expected to share a skin
00222 
00223   std::set<std::set<unsigned> > sharing;
00224   std::set<std::set<unsigned> > expected_sharing;
00225 
00226   std::set<unsigned> temp;
00227   temp.insert(44);
00228   temp.insert(46);
00229   expected_sharing.insert(temp);
00230 
00231   temp.clear();
00232   temp.insert(45);
00233   temp.insert(47);
00234   expected_sharing.insert(temp);
00235 
00236   // map skin-id to ids of elements it is attached to; we will use this to
00237   // compute sharing
00238   for (std::vector<stk::mesh::Entity*>::const_iterator
00239        itr = skin_entities.begin(); itr != skin_entities.end(); ++itr) {
00240     stk::mesh::PairIterRelation upward_relation_itr =
00241       (*itr)->relations(element_rank);
00242     bool has_multiple = upward_relation_itr.size() > 1;
00243     std::set<unsigned> sharing_elements;
00244     for ( ; !upward_relation_itr.empty() ; ++upward_relation_itr ) {
00245       unsigned elem_id = upward_relation_itr->entity()->identifier();
00246       if (results.find(elem_id) != results.end()) {
00247         ++results[elem_id];
00248       }
00249       else {
00250         results[elem_id] = 1;
00251       }
00252 
00253       if (has_multiple) {
00254         sharing_elements.insert(elem_id);
00255       }
00256     }
00257     if (has_multiple) {
00258       sharing.insert(sharing_elements);
00259     }
00260   }
00261 
00262   STKUNIT_EXPECT_TRUE(results == expected_results);
00263   STKUNIT_EXPECT_TRUE(sharing == expected_sharing);
00264 }
00265 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends