|
Sierra Toolkit
Version of the Day
|
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_classic::mesh::fem::FEMMetaData::NODE_RANK; 00035 00036 class UnitTestStkMeshSkinning { 00037 public: 00038 UnitTestStkMeshSkinning(stk_classic::ParallelMachine pm) : m_comm(pm), m_num_procs(0), m_rank(0) 00039 { 00040 m_num_procs = stk_classic::parallel_machine_size( m_comm ); 00041 m_rank = stk_classic::parallel_machine_rank( m_comm ); 00042 } 00043 00044 void test_skinning(); 00045 00046 stk_classic::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_classic::mesh::fem::FEMMetaData fem_meta; 00063 fem_meta.FEM_initialize(spatial_dimension, stk_classic::mesh::fem::entity_rank_names(spatial_dimension)); 00064 stk_classic::mesh::MetaData & meta_data = stk_classic::mesh::fem::FEMMetaData::get_meta_data(fem_meta); 00065 stk_classic::mesh::BulkData bulk_data( meta_data, MPI_COMM_WORLD ); 00066 const stk_classic::mesh::EntityRank element_rank = fem_meta.element_rank(); 00067 00068 const unsigned p_rank = bulk_data.parallel_rank(); 00069 00070 stk_classic::mesh::Part & skin_part = fem_meta.declare_part("skin_part"); 00071 00072 stk_classic::mesh::fem::CellTopology shell_top(shards::getCellTopologyData<shards::ShellQuadrilateral<4> >()); 00073 stk_classic::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_classic::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_classic::mesh::EntityId elem_id = 1; 00090 00091 stk_classic::mesh::fem::declare_element( bulk_data, shell_part, elem_id, elem_node); 00092 00093 } 00094 bulk_data.modification_end(); 00095 00096 00097 stk_classic::mesh::skin_mesh( bulk_data, element_rank, &skin_part); 00098 00099 { 00100 const unsigned mesh_rank = element_rank; 00101 const stk_classic::mesh::MetaData & meta = stk_classic::mesh::MetaData::get(bulk_data); 00102 stk_classic::mesh::Selector select_skin = skin_part & meta.locally_owned_part() ; 00103 const std::vector<stk_classic::mesh::Bucket*>& buckets = bulk_data.buckets( mesh_rank -1); 00104 int num_skin_entities = stk_classic::mesh::count_selected_entities( select_skin, buckets); 00105 00106 00107 stk_classic::all_reduce(MPI_COMM_WORLD, stk_classic::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_classic::mesh::fixtures::GridFixture grid_mesh(MPI_COMM_WORLD); 00125 00126 stk_classic::mesh::BulkData& bulk_data = grid_mesh.bulk_data(); 00127 stk_classic::mesh::fem::FEMMetaData& fem_meta = grid_mesh.fem_meta(); 00128 const stk_classic::mesh::EntityRank element_rank = fem_meta.element_rank(); 00129 00130 // Create a part for the skin and the shells 00131 stk_classic::mesh::Part & skin_part = fem_meta.declare_part("skin_part"); 00132 stk_classic::mesh::fem::CellTopology line_top(shards::getCellTopologyData<shards::ShellLine<2> >()); 00133 stk_classic::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_classic::mesh::Selector locally_owned(fem_meta.locally_owned_part()); 00145 stk_classic::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_classic::mesh::PartVector shell_parts; 00153 shell_parts.push_back(&shell_part); 00154 00155 std::vector<stk_classic::mesh::Entity*> shell_faces; 00156 for (unsigned i = 1; i <= num_shell_faces; ++i) { 00157 stk_classic::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_classic::mesh::Entity& shell = *(shell_faces[i]); 00169 stk_classic::mesh::Entity& node1 = *(bulk_data.get_entity(NODE_RANK, node_list_1[i])); 00170 stk_classic::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_classic::mesh::Entity& shell = *(shell_faces[i + num_shell_1_faces]); 00179 stk_classic::mesh::Entity& node1 = *(bulk_data.get_entity(NODE_RANK, node_list_2[i])); 00180 stk_classic::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_classic::mesh::skin_mesh(bulk_data, element_rank, &skin_part); 00189 00190 // Grab the skin entities 00191 stk_classic::mesh::Selector skin_selector(skin_part); 00192 const std::vector<stk_classic::mesh::Bucket*>& edge_buckets = bulk_data.buckets(fem_meta.edge_rank()); 00193 std::vector<stk_classic::mesh::Entity*> skin_entities; 00194 stk_classic::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_classic::mesh::Entity*>::const_iterator 00239 itr = skin_entities.begin(); itr != skin_entities.end(); ++itr) { 00240 stk_classic::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