|
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 #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/FEMHelpers.hpp> 00023 00024 #include <stk_mesh/fixtures/GridFixture.hpp> 00025 00026 #include <iomanip> 00027 #include <algorithm> 00028 00029 static const size_t NODE_RANK = stk_classic::mesh::fem::FEMMetaData::NODE_RANK; 00030 00031 class UnitTestStkMeshBoundaryAnalysis { 00032 public: 00033 UnitTestStkMeshBoundaryAnalysis(stk_classic::ParallelMachine pm) : m_comm(pm), m_num_procs(0), m_rank(0) 00034 { 00035 m_num_procs = stk_classic::parallel_machine_size( m_comm ); 00036 m_rank = stk_classic::parallel_machine_rank( m_comm ); 00037 } 00038 00039 void test_boundary_analysis(); 00040 void test_boundary_analysis_null_topology(); 00041 00042 stk_classic::ParallelMachine m_comm; 00043 int m_num_procs; 00044 int m_rank; 00045 }; 00046 00047 namespace { 00048 00049 STKUNIT_UNIT_TEST( UnitTestStkMeshBoundaryAnalysis , testUnit ) 00050 { 00051 UnitTestStkMeshBoundaryAnalysis unit(MPI_COMM_WORLD); 00052 unit.test_boundary_analysis(); 00053 } 00054 00055 STKUNIT_UNIT_TEST( UnitTestStkMeshBoundaryAnalysis , testNullTopology ) 00056 { 00057 UnitTestStkMeshBoundaryAnalysis unit(MPI_COMM_WORLD); 00058 unit.test_boundary_analysis_null_topology(); 00059 } 00060 00061 } //end namespace 00062 00063 void UnitTestStkMeshBoundaryAnalysis::test_boundary_analysis() 00064 { 00065 // Test the boundary_analysis algorithm in stk_mesh/fem/BoundaryAnalysis.hpp 00066 // with a boundary that is both shelled and non-shelled. 00067 // 00068 // We will be testing the algorithm on the following 2D mesh: 00069 // 00070 // 17---18---19---20---21 00071 // | 1 | 2 | 3 || 4 | 00072 // 22---23---24---25---26 00073 // | 5 | 6 | 7 || 8 | 00074 // 27---28---29---30---31 00075 // | 9 | 10 | 11 ||12 | 00076 // 32---33---34---35---36 00077 // | 13 | 14 | 15 ||16 | 00078 // 37---38---39---40---41 00079 // 00080 // Note the shells along nodes 20-40. 00081 // 00082 // We will be computing the boundary of the closure of 00083 // elements: 6, 7, 10, 11, 14, 15 00084 00085 // This test will only work for np=1 00086 if (m_num_procs > 1) { 00087 return; 00088 } 00089 00090 // set up grid_mesh 00091 stk_classic::mesh::fixtures::GridFixture grid_mesh(MPI_COMM_WORLD); 00092 00093 stk_classic::mesh::fem::FEMMetaData& fem_meta = grid_mesh.fem_meta(); 00094 stk_classic::mesh::BulkData& bulk_data = grid_mesh.bulk_data(); 00095 00096 const stk_classic::mesh::EntityRank element_rank = fem_meta.element_rank(); 00097 00098 // make shell part 00099 stk_classic::mesh::fem::CellTopology line_top(shards::getCellTopologyData<shards::ShellLine<2> >()); 00100 stk_classic::mesh::Part& shell_part = fem_meta.declare_part("shell_part", line_top); 00101 00102 fem_meta.commit(); 00103 00104 bulk_data.modification_begin(); 00105 grid_mesh.generate_grid(); 00106 00107 // Add some shells 00108 const unsigned num_shells = 4; 00109 00110 // get a count of entities that have already been created 00111 std::vector<unsigned> count; 00112 stk_classic::mesh::Selector locally_owned(fem_meta.locally_owned_part()); 00113 stk_classic::mesh::count_entities(locally_owned, bulk_data, count); 00114 const unsigned num_entities = count[NODE_RANK] + count[element_rank]; 00115 00116 // Declare the shell entities, placing them in the shell part 00117 std::vector<stk_classic::mesh::Entity*> shells; 00118 stk_classic::mesh::PartVector shell_parts; 00119 shell_parts.push_back(&shell_part); 00120 for (unsigned i = 1; i <= num_shells; ++i) { 00121 stk_classic::mesh::Entity& new_shell = bulk_data.declare_entity(element_rank, 00122 num_entities + i, 00123 shell_parts); 00124 shells.push_back(&new_shell); 00125 } 00126 00127 // declare shell relationships 00128 unsigned node_list[5] = {20, 25, 30, 35, 40}; 00129 for (unsigned i = 0; i < num_shells; ++i) { 00130 stk_classic::mesh::Entity& shell = *(shells[i]); 00131 stk_classic::mesh::Entity& node1 = *(bulk_data.get_entity(NODE_RANK, node_list[i])); 00132 stk_classic::mesh::Entity& node2 = *(bulk_data.get_entity(NODE_RANK, node_list[i+1])); 00133 bulk_data.declare_relation(shell, node1, 0); 00134 bulk_data.declare_relation(shell, node2, 1); 00135 } 00136 00137 bulk_data.modification_end(); 00138 00139 // create the closure we want to analyze 00140 std::vector<stk_classic::mesh::Entity*> closure; 00141 unsigned num_elems_in_closure = 6; 00142 stk_classic::mesh::EntityId ids_of_entities_in_closure[] = 00143 {6, 7, 10, 11, 14, 15, 23, 24, 25, 28, 29, 30, 33, 34, 35, 38, 39, 40}; 00144 for (unsigned i = 0; 00145 i < sizeof(ids_of_entities_in_closure)/sizeof(stk_classic::mesh::EntityId); 00146 ++i) { 00147 stk_classic::mesh::EntityRank rank_of_entity; 00148 if (i < num_elems_in_closure) { 00149 rank_of_entity = element_rank; 00150 } 00151 else { 00152 rank_of_entity = NODE_RANK; 00153 } 00154 stk_classic::mesh::Entity* closure_entity = 00155 bulk_data.get_entity(rank_of_entity, ids_of_entities_in_closure[i]); 00156 closure.push_back(closure_entity); 00157 } 00158 // sort the closure (boundary analysis expects it this way) 00159 std::sort(closure.begin(), closure.end(), stk_classic::mesh::EntityLess()); 00160 00161 // Run the bounary analysis! 00162 stk_classic::mesh::EntitySideVector boundary; 00163 stk_classic::mesh::boundary_analysis(bulk_data, closure, element_rank, boundary); 00164 STKUNIT_EXPECT_TRUE(!boundary.empty()); 00165 00166 // Prepare the expected-results as a vector of pairs of pairs representing 00167 // ( inside, outside ) where 00168 // inside is ( element-id, side-ordinal ) of element inside the closure 00169 // outside is ( element-id, side-ordinal ) of element outside the closure 00170 // and inside and outside border each other 00171 00172 typedef std::pair<stk_classic::mesh::EntityId, stk_classic::mesh::Ordinal> BoundaryItem; 00173 typedef std::pair<BoundaryItem, BoundaryItem> BoundaryPair; 00174 00175 // Note that certain sides of elements 7, 11, 15 have a boundary with 00176 // a shell AND the adjacent element outside the closure. 00177 00178 BoundaryPair results[] = { 00179 BoundaryPair(BoundaryItem(6, 0), BoundaryItem(5, 2)), 00180 00181 BoundaryPair(BoundaryItem(6, 3), BoundaryItem(2, 1)), 00182 00183 BoundaryPair(BoundaryItem(7, 2), BoundaryItem(8, 0)), 00184 BoundaryPair(BoundaryItem(7, 2), BoundaryItem(43, 0)), 00185 00186 BoundaryPair(BoundaryItem(7, 3), BoundaryItem(3, 1)), 00187 00188 BoundaryPair(BoundaryItem(10, 0), BoundaryItem(9, 2)), 00189 00190 BoundaryPair(BoundaryItem(11, 2), BoundaryItem(12, 0)), 00191 BoundaryPair(BoundaryItem(11, 2), BoundaryItem(44, 0)), 00192 00193 BoundaryPair(BoundaryItem(14, 0), BoundaryItem(13, 2)), 00194 00195 BoundaryPair(BoundaryItem(14, 1), BoundaryItem(0, 0)), 00196 00197 BoundaryPair(BoundaryItem(15, 1), BoundaryItem(0, 0)), 00198 00199 BoundaryPair(BoundaryItem(15, 2), BoundaryItem(16, 0)), 00200 BoundaryPair(BoundaryItem(15, 2), BoundaryItem(45, 0)) 00201 }; 00202 00203 // Convert the boundary returned by boundary_analysis into a data-structure 00204 // comparable to expected_results 00205 00206 BoundaryPair expected_results[sizeof(results)/sizeof(BoundaryPair)]; 00207 00208 unsigned i = 0; 00209 stk_classic::mesh::EntitySideVector::iterator itr = boundary.begin(); 00210 00211 for (; itr != boundary.end(); ++itr, ++i) 00212 { 00213 stk_classic::mesh::EntitySide& side = *itr; 00214 stk_classic::mesh::EntitySideComponent& inside_closure = side.inside; 00215 stk_classic::mesh::EntityId inside_id = inside_closure.entity != NULL ? inside_closure.entity->identifier() : 0; 00216 stk_classic::mesh::EntityId inside_side = inside_closure.entity != NULL ? inside_closure.side_ordinal : 0; 00217 stk_classic::mesh::EntitySideComponent& outside_closure = side.outside; 00218 stk_classic::mesh::EntityId outside_id = outside_closure.entity != NULL ? outside_closure.entity->identifier() : 0; 00219 stk_classic::mesh::EntityId outside_side = outside_closure.entity != NULL ? outside_closure.side_ordinal : 0; 00220 00221 expected_results[i] = BoundaryPair(BoundaryItem(inside_id, inside_side), 00222 BoundaryItem(outside_id, outside_side)); 00223 } 00224 00225 // Check that results match expected results 00226 00227 STKUNIT_EXPECT_EQ(sizeof(results), sizeof(expected_results)); 00228 00229 for (i = 0; i < sizeof(results)/sizeof(BoundaryPair); ++i) { 00230 STKUNIT_EXPECT_TRUE(results[i] == expected_results[i]); 00231 } 00232 } 00233 00234 void UnitTestStkMeshBoundaryAnalysis::test_boundary_analysis_null_topology() 00235 { 00236 //test on boundary_analysis for closure with a NULL topology - coverage of lines 39-40 of BoundaryAnalysis.cpp 00237 00238 //create new fem_meta, bulk and boundary for this test 00239 const int spatial_dimension = 3; 00240 stk_classic::mesh::fem::FEMMetaData fem_meta; 00241 fem_meta.FEM_initialize(spatial_dimension, stk_classic::mesh::fem::entity_rank_names(spatial_dimension)); 00242 00243 const stk_classic::mesh::EntityRank side_rank = fem_meta.side_rank(); 00244 00245 //declare part with topology = NULL 00246 stk_classic::mesh::Part & quad_part = fem_meta.declare_part("quad_part", side_rank); 00247 fem_meta.commit(); 00248 00249 stk_classic::ParallelMachine comm(MPI_COMM_WORLD); 00250 stk_classic::mesh::MetaData & meta = stk_classic::mesh::fem::FEMMetaData::get_meta_data(fem_meta); 00251 stk_classic::mesh::BulkData bulk ( meta , comm , 100 ); 00252 00253 stk_classic::mesh::EntitySideVector boundary; 00254 std::vector<stk_classic::mesh::Entity*> newclosure; 00255 00256 stk_classic::mesh::PartVector face_parts; 00257 face_parts.push_back(&quad_part); 00258 00259 bulk.modification_begin(); 00260 if (m_rank == 0) { 00261 stk_classic::mesh::Entity & new_face = bulk.declare_entity(side_rank, 1, face_parts); 00262 newclosure.push_back(&new_face); 00263 } 00264 00265 stk_classic::mesh::boundary_analysis(bulk, newclosure, side_rank, boundary); 00266 /* 00267 STKUNIT_EXPECT_TRUE(!boundary.empty()); 00268 */ 00269 00270 bulk.modification_end(); 00271 }