Sierra Toolkit Version of the Day
UnitTestBoundaryAnalysis.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 #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::mesh::fem::FEMMetaData::NODE_RANK;
00030 
00031 class UnitTestStkMeshBoundaryAnalysis {
00032 public:
00033   UnitTestStkMeshBoundaryAnalysis(stk::ParallelMachine pm) : m_comm(pm),  m_num_procs(0), m_rank(0)
00034   {
00035     m_num_procs = stk::parallel_machine_size( m_comm );
00036     m_rank = stk::parallel_machine_rank( m_comm );
00037   }
00038 
00039   void test_boundary_analysis();
00040   void test_boundary_analysis_null_topology();
00041 
00042   stk::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::mesh::fixtures::GridFixture grid_mesh(MPI_COMM_WORLD);
00092 
00093   stk::mesh::fem::FEMMetaData& fem_meta = grid_mesh.fem_meta();
00094   stk::mesh::BulkData& bulk_data = grid_mesh.bulk_data();
00095 
00096   const stk::mesh::EntityRank element_rank = fem_meta.element_rank();
00097 
00098   // make shell part
00099   stk::mesh::fem::CellTopology line_top(shards::getCellTopologyData<shards::ShellLine<2> >());
00100   stk::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::mesh::Selector locally_owned(fem_meta.locally_owned_part());
00113   stk::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::mesh::Entity*> shells;
00118   stk::mesh::PartVector shell_parts;
00119   shell_parts.push_back(&shell_part);
00120   for (unsigned i = 1; i <= num_shells; ++i) {
00121     stk::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::mesh::Entity& shell = *(shells[i]);
00131     stk::mesh::Entity& node1 = *(bulk_data.get_entity(NODE_RANK, node_list[i]));
00132     stk::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::mesh::Entity*> closure;
00141   unsigned num_elems_in_closure = 6;
00142   stk::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::mesh::EntityId);
00146        ++i) {
00147     stk::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::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::mesh::EntityLess());
00160 
00161   // Run the bounary analysis!
00162   stk::mesh::EntitySideVector boundary;
00163   stk::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::mesh::EntityId, stk::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::mesh::EntitySideVector::iterator itr = boundary.begin();
00210 
00211   for (; itr != boundary.end(); ++itr, ++i)
00212   {
00213     stk::mesh::EntitySide& side = *itr;
00214     stk::mesh::EntitySideComponent& inside_closure = side.inside;
00215     stk::mesh::EntityId inside_id = inside_closure.entity != NULL ? inside_closure.entity->identifier() : 0;
00216     stk::mesh::EntityId inside_side = inside_closure.entity != NULL ? inside_closure.side_ordinal : 0;
00217     stk::mesh::EntitySideComponent& outside_closure = side.outside;
00218     stk::mesh::EntityId outside_id = outside_closure.entity != NULL ? outside_closure.entity->identifier() : 0;
00219     stk::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::mesh::fem::FEMMetaData fem_meta;
00241   fem_meta.FEM_initialize(spatial_dimension, stk::mesh::fem::entity_rank_names(spatial_dimension));
00242 
00243   const stk::mesh::EntityRank side_rank = fem_meta.side_rank();
00244 
00245   //declare part with topology = NULL
00246   stk::mesh::Part & quad_part = fem_meta.declare_part("quad_part", side_rank);
00247   fem_meta.commit();
00248 
00249   stk::ParallelMachine comm(MPI_COMM_WORLD);
00250   stk::mesh::MetaData & meta = stk::mesh::fem::FEMMetaData::get_meta_data(fem_meta);
00251   stk::mesh::BulkData bulk ( meta , comm , 100 );
00252 
00253   stk::mesh::EntitySideVector boundary;
00254   std::vector<stk::mesh::Entity*> newclosure;
00255 
00256   stk::mesh::PartVector face_parts;
00257   face_parts.push_back(&quad_part);
00258 
00259   bulk.modification_begin();
00260   if (m_rank == 0) {
00261     stk::mesh::Entity & new_face = bulk.declare_entity(side_rank, 1, face_parts);
00262     newclosure.push_back(&new_face);
00263   }
00264 
00265   stk::mesh::boundary_analysis(bulk, newclosure, side_rank, boundary);
00266   /*
00267   STKUNIT_EXPECT_TRUE(!boundary.empty());
00268   */
00269 
00270   bulk.modification_end();
00271 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends