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