|
Sierra Toolkit Version of the Day
|
00001 00002 #include <map> 00003 00004 #include <stk_mesh/base/BulkData.hpp> 00005 #include <stk_mesh/base/BulkModification.hpp> 00006 #include <stk_mesh/base/Entity.hpp> 00007 #include <stk_mesh/base/GetEntities.hpp> 00008 #include <stk_mesh/base/MetaData.hpp> 00009 #include <stk_mesh/base/Selector.hpp> 00010 #include <stk_mesh/base/Types.hpp> 00011 00012 #include <stk_mesh/fem/FEMTypes.hpp> 00013 #include <stk_mesh/fem/BoundaryAnalysis.hpp> 00014 #include <stk_mesh/fem/EntityRanks.hpp> 00015 #include <stk_mesh/fem/TopologyHelpers.hpp> 00016 00017 #include <stk_mesh/fem/SkinMesh.hpp> 00018 00019 namespace stk { 00020 namespace mesh { 00021 00022 namespace { 00023 00024 typedef std::multimap< std::vector<EntityId>, EntitySideComponent> BoundaryMap; 00025 typedef std::pair< std::vector<EntityId>, EntitySideComponent> BoundaryValue; 00026 00027 // \TODO Without the sorting, this would be a good general utility for 'fem' 00028 void get_elem_side_nodes( const Entity & elem, 00029 unsigned side_ordinal, 00030 std::vector<EntityId> & nodes 00031 ) 00032 { 00033 const CellTopologyData * const elem_top = TopologicalMetaData::get_cell_topology( elem ); 00034 00035 if (elem_top == NULL) { 00036 std::ostringstream msg ; 00037 msg << "skin_mesh" ; 00038 msg << "( Element[" << elem.identifier() << "] has no defined topology" ; 00039 throw std::runtime_error( msg.str() ); 00040 } 00041 00042 const CellTopologyData * const side_top = elem_top->side[ side_ordinal ].topology; 00043 00044 if (side_top == NULL) { 00045 std::ostringstream msg ; 00046 msg << "skin_mesh" ; 00047 msg << "( Element[" << elem.identifier() << "]" ; 00048 msg << " , side_ordinal = " << side_ordinal << " ) FAILED: " ; 00049 msg << " Side has no defined topology" ; 00050 throw std::runtime_error( msg.str() ); 00051 } 00052 00053 const unsigned * const side_node_map = elem_top->side[ side_ordinal ].node ; 00054 00055 PairIterRelation relations = elem.relations( NodeRank ); 00056 00057 // Find positive polarity permutation that starts with lowest entity id: 00058 // We're using this as the unique key in a map for a side. 00059 const int num_permutations = side_top->permutation_count; 00060 int lowest_entity_id_permutation = 0; 00061 for (int p = 0; p < num_permutations; ++p) { 00062 00063 if (side_top->permutation[p].polarity == 00064 CELL_PERMUTATION_POLARITY_POSITIVE) { 00065 00066 const unsigned * const pot_lowest_perm_node = 00067 side_top->permutation[p].node ; 00068 00069 const unsigned * const curr_lowest_perm_node = 00070 side_top->permutation[lowest_entity_id_permutation].node; 00071 00072 unsigned first_node_index = 0; 00073 00074 unsigned current_lowest_entity_id = 00075 relations[side_node_map[curr_lowest_perm_node[first_node_index]]].entity()->identifier(); 00076 00077 unsigned potential_lowest_entity_id = 00078 relations[side_node_map[pot_lowest_perm_node[first_node_index]]].entity()->identifier(); 00079 00080 if ( potential_lowest_entity_id < current_lowest_entity_id ) { 00081 lowest_entity_id_permutation = p; 00082 } 00083 } 00084 } 00085 const unsigned * const perm_node = 00086 side_top->permutation[lowest_entity_id_permutation].node; 00087 00088 nodes.reserve(side_top->node_count); 00089 for ( unsigned i = 0 ; i < side_top->node_count ; ++i ) { 00090 unsigned node_id = relations[side_node_map[perm_node[i]]].entity()->identifier(); 00091 nodes.push_back(node_id); 00092 } 00093 00094 } 00095 00096 } 00097 00098 void skin_mesh( BulkData & mesh, EntityRank element_rank, Part * skin_part) { 00099 if (mesh.synchronized_state() == BulkData::MODIFIABLE) { 00100 throw std::runtime_error("stk::mesh::skin_mesh is not SYNCHRONIZED"); 00101 } 00102 00103 EntityVector owned_elements; 00104 00105 // select owned 00106 Selector owned = mesh.mesh_meta_data().locally_owned_part(); 00107 get_selected_entities( owned, 00108 mesh.buckets(element_rank), 00109 owned_elements); 00110 00111 reskin_mesh(mesh, element_rank, owned_elements, skin_part); 00112 } 00113 00114 void reskin_mesh( BulkData & mesh, EntityRank element_rank, EntityVector & owned_elements, Part * skin_part) { 00115 if (mesh.synchronized_state() == BulkData::MODIFIABLE) { 00116 throw std::runtime_error("stk::mesh::skin_mesh is not SYNCHRONIZED"); 00117 } 00118 00119 EntityVector elements_closure; 00120 00121 // compute owned closure 00122 find_closure( mesh, owned_elements, elements_closure ); 00123 00124 // compute boundary 00125 EntitySideVector boundary; 00126 boundary_analysis( mesh, elements_closure, element_rank, boundary); 00127 00128 // find the sides that need to be created to make a skin. The map below 00129 // maps sorted EntityVectors of nodes to EntitySideComponents 00130 BoundaryMap skin; 00131 00132 int num_new_sides = 0; 00133 for (stk::mesh::EntitySideVector::const_iterator itr = boundary.begin(); 00134 itr != boundary.end(); ++itr) { 00135 const EntitySideComponent & inside = itr->inside; 00136 const EntitySideComponent & outside = itr->outside; 00137 const unsigned side_ordinal = inside.side_ordinal; 00138 Entity& inside_entity = *(inside.entity); 00139 00140 // If this process owns the inside and the outside entity does not exist, 00141 // we need to apply a skin. This means we need to ensure that the side 00142 // entity exists at this boundary. 00143 if ( inside_entity.owner_rank() == mesh.parallel_rank() && 00144 outside.entity == NULL ) { 00145 // search through existing sides 00146 PairIterRelation existing_sides = inside_entity.relations(element_rank -1); 00147 for (; existing_sides.first != existing_sides.second && 00148 existing_sides.first->identifier() != side_ordinal ; 00149 ++existing_sides.first); 00150 00151 // the side we need for the skin does not exist on the inside entity, 00152 // we may need to create it 00153 if (existing_sides.first == existing_sides.second) { 00154 // Get the nodes for the inside entity 00155 std::vector<EntityId> inside_key; 00156 get_elem_side_nodes(inside_entity, side_ordinal, inside_key); 00157 00158 //if a side for these nodes is not present in the map already increment the 00159 //number of side we need to create 00160 if (skin.count(inside_key) == 0) { 00161 ++num_new_sides; 00162 } 00163 00164 skin.insert( BoundaryValue(inside_key, inside)); 00165 00166 } 00167 } 00168 } 00169 00170 mesh.modification_begin(); 00171 00172 // formulate request ids for the new sides 00173 std::vector<size_t> requests(mesh.mesh_meta_data().entity_rank_count(), 0); 00174 requests[element_rank -1] = num_new_sides; 00175 00176 // create the new sides 00177 EntityVector requested_sides; 00178 mesh.generate_new_entities(requests, requested_sides); 00179 00180 std::vector<EntityId> previous_key; 00181 size_t current_side = 0; 00182 for ( BoundaryMap::const_iterator i = skin.begin(); i!= skin.end(); ++i) { 00183 const std::vector<EntityId> & key = i->first; 00184 Entity & entity = *(i->second.entity); 00185 const unsigned side_ordinal = i->second.side_ordinal; 00186 00187 if (key != previous_key) { 00188 Entity & side = *(requested_sides[current_side]); 00189 declare_element_side(entity, side, side_ordinal, skin_part); 00190 00191 previous_key = key; 00192 ++current_side; 00193 } 00194 else { 00195 Entity & side = *(requested_sides[current_side-1]); 00196 mesh.declare_relation(entity, side, side_ordinal); 00197 } 00198 } 00199 00200 mesh.modification_end(); 00201 } 00202 00203 } 00204 }