• Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

Subgraph.cc

Go to the documentation of this file.
00001 //*****************************************************************//
00002 //    Albany 2.0:  Copyright 2012 Sandia Corporation               //
00003 //    This Software is released under the BSD license detailed     //
00004 //    in the file "license.txt" in the top-level Albany directory  //
00005 //*****************************************************************//
00006 #include "Subgraph.h"
00007 #include "Topology_Utils.h"
00008 
00009 namespace LCM {
00010 
00011 //
00012 // Create a subgraph given a vertex list and an edge list.
00013 //
00014 Subgraph::Subgraph(RCP<Albany::AbstractSTKMeshStruct> stk_mesh_struct,
00015     std::set<EntityKey>::iterator first_vertex,
00016     std::set<EntityKey>::iterator last_vertex,
00017     std::set<stkEdge>::iterator first_edge,
00018     std::set<stkEdge>::iterator last_edge) :
00019     stk_mesh_struct_(stk_mesh_struct)
00020 {
00021   // Insert vertices and create the vertex map
00022   for (std::set<EntityKey>::iterator vertex_iterator = first_vertex;
00023       vertex_iterator != last_vertex;
00024       ++vertex_iterator) {
00025 
00026     // get global vertex
00027     EntityKey
00028     global_vertex = *vertex_iterator;
00029 
00030     // get entity rank
00031     EntityRank
00032     vertex_rank = getBulkData()->get_entity(global_vertex)->entity_rank();
00033 
00034     // create new local vertex
00035     Vertex
00036     local_vertex = boost::add_vertex(*this);
00037 
00038     std::pair<Vertex, EntityKey>
00039     local_to_global = std::make_pair(local_vertex, global_vertex);
00040 
00041     std::pair<EntityKey, Vertex>
00042     global_to_local = std::make_pair(global_vertex, local_vertex);
00043 
00044     local_global_vertex_map_.insert(local_to_global);
00045 
00046     global_local_vertex_map_.insert(global_to_local);
00047 
00048     // store entity rank to vertex property
00049     VertexNamePropertyMap
00050     vertex_property_map = boost::get(VertexName(), *this);
00051 
00052     boost::put(vertex_property_map, local_vertex, vertex_rank);
00053   }
00054 
00055   // Add edges to the subgraph
00056   for (std::set<stkEdge>::iterator edge_iterator = first_edge;
00057       edge_iterator != last_edge;
00058       ++edge_iterator) {
00059 
00060     // Get the edge
00061     stkEdge
00062     global_edge = *edge_iterator;
00063 
00064     // Get global source and target vertices
00065     EntityKey
00066     global_source_vertex = global_edge.source;
00067 
00068     EntityKey
00069     global_target_vertex = global_edge.target;
00070 
00071     // Get local source and target vertices
00072     Vertex
00073     local_source_vertex =
00074         global_local_vertex_map_.find(global_source_vertex)->second;
00075 
00076     Vertex
00077     local_target_vertex =
00078         global_local_vertex_map_.find(global_target_vertex)->second;
00079 
00080     EdgeId
00081     edge_id = global_edge.local_id;
00082 
00083     Edge
00084     local_edge;
00085 
00086     bool
00087     is_inserted;
00088 
00089     boost::tie(local_edge, is_inserted) =
00090         boost::add_edge(local_source_vertex, local_target_vertex, *this);
00091 
00092     assert(is_inserted == true);
00093 
00094     // Add edge id to edge property
00095     EdgeNamePropertyMap
00096     edge_property_map = boost::get(EdgeName(), *this);
00097 
00098     boost::put(edge_property_map, local_edge, edge_id);
00099   }
00100 
00101   return;
00102 }
00103 
00104 //
00105 // Map a vertex in the subgraph to a entity in the stk mesh.
00106 //
00107 EntityKey
00108 Subgraph::localToGlobal(Vertex local_vertex)
00109 {
00110   std::map<Vertex, EntityKey>::const_iterator
00111   vertex_map_iterator = local_global_vertex_map_.find(local_vertex);
00112 
00113   assert(vertex_map_iterator != local_global_vertex_map_.end());
00114 
00115   return (*vertex_map_iterator).second;
00116 }
00117 
00118 //
00119 // Map a entity in the stk mesh to a vertex in the subgraph.
00120 //
00121 Vertex
00122 Subgraph::globalToLocal(EntityKey global_vertex_key)
00123 {
00124   std::map<EntityKey, Vertex>::const_iterator
00125   vertex_map_iterator = global_local_vertex_map_.find(global_vertex_key);
00126 
00127   assert(vertex_map_iterator != global_local_vertex_map_.end());
00128 
00129   return (*vertex_map_iterator).second;
00130 }
00131 
00132 //
00133 // Add a vertex in the subgraph.
00134 //
00135 Vertex
00136 Subgraph::addVertex(EntityRank vertex_rank)
00137 {
00138   // Insert the vertex into the stk mesh
00139   // First have to request a new entity of rank N
00140   // number of entity ranks: 1 + number of dimensions
00141   std::vector<size_t>
00142   requests(getSpaceDimension() + 1, 0);
00143 
00144   requests[vertex_rank] = 1;
00145 
00146   EntityVector
00147   new_entities;
00148 
00149   getBulkData()->generate_new_entities(requests, new_entities);
00150 
00151   EntityKey
00152   global_vertex = new_entities[0]->key();
00153 
00154   // Add the vertex to the subgraph
00155   Vertex
00156   local_vertex = boost::add_vertex(*this);
00157 
00158   // Update maps
00159   std::pair<Vertex, EntityKey>
00160   local_to_global = std::make_pair(local_vertex, global_vertex);
00161 
00162   std::pair<EntityKey, Vertex>
00163   global_to_local = std::make_pair(global_vertex, local_vertex);
00164 
00165   local_global_vertex_map_.insert(local_to_global);
00166 
00167   global_local_vertex_map_.insert(global_to_local);
00168 
00169   // store entity rank to the vertex property
00170   VertexNamePropertyMap
00171   vertex_property_map = boost::get(VertexName(), *this);
00172 
00173   boost::put(vertex_property_map, local_vertex, vertex_rank);
00174 
00175   return local_vertex;
00176 }
00177 
00178 //------------------------------------------------------------------------------
00179 void
00180 Subgraph::communicate_and_create_shared_entities(Entity   & node,
00181     EntityKey   new_node_key){
00182 
00183   stk::CommAll comm(getBulkData()->parallel());
00184 
00185   {
00186     stk::mesh::PairIterEntityComm entity_comm = node.sharing();
00187 
00188     for (; entity_comm.first != entity_comm.second; ++entity_comm.first) {
00189 
00190       unsigned proc = entity_comm.first->proc;
00191       comm.send_buffer(proc).pack<EntityKey>(node.key())
00192                                   .pack<EntityKey>(new_node_key);
00193 
00194     }
00195   }
00196 
00197   comm.allocate_buffers(getBulkData()->parallel_size()/4 );
00198 
00199   {
00200     stk::mesh::PairIterEntityComm entity_comm = node.sharing();
00201 
00202     for (; entity_comm.first != entity_comm.second; ++entity_comm.first) {
00203 
00204       unsigned proc = entity_comm.first->proc;
00205       comm.send_buffer(proc).pack<EntityKey>(node.key())
00206                                   .pack<EntityKey>(new_node_key);
00207 
00208     }
00209   }
00210 
00211   comm.communicate();
00212 
00213   const stk::mesh::PartVector no_parts;
00214 
00215   for (size_t process = 0; process < getBulkData()->parallel_size(); ++process) {
00216     EntityKey old_key;
00217     EntityKey new_key;
00218 
00219     while ( comm.recv_buffer(process).remaining()) {
00220 
00221       comm.recv_buffer(process).unpack<EntityKey>(old_key)
00222                                      .unpack<EntityKey>(new_key);
00223 
00224       Entity * new_entity = & getBulkData()->declare_entity(new_key.rank(), new_key.id(), no_parts);
00225       //std::cout << " Proc: " << getBulkData()->parallel_rank() << " created entity: (" << new_entity->identifier() << ", " <<
00226       //new_entity->entity_rank() << ")." << '\n';
00227 
00228     }
00229   }
00230 
00231 }
00232 
00233 //------------------------------------------------------------------------------
00234 void
00235 Subgraph::bcast_key(unsigned root, EntityKey&   node_key){
00236 
00237   stk::CommBroadcast comm(getBulkData()->parallel(), root);
00238 
00239   unsigned rank = getBulkData()->parallel_rank();
00240 
00241   if(rank == root)
00242 
00243     comm.send_buffer().pack<EntityKey>(node_key);
00244 
00245   comm.allocate_buffer();
00246 
00247   if(rank == root)
00248 
00249     comm.send_buffer().pack<EntityKey>(node_key);
00250 
00251   comm.communicate();
00252 
00253   comm.recv_buffer().unpack<EntityKey>(node_key);
00254 
00255 }
00256 
00257 //------------------------------------------------------------------------------
00258 Vertex
00259 Subgraph::cloneVertex(Vertex & vertex)
00260 {
00261 
00262   // Get the vertex rank
00263   EntityRank
00264   vertex_rank = Subgraph::getVertexRank(vertex);
00265 
00266   EntityKey
00267   vertex_key = Subgraph::localToGlobal(vertex);
00268 
00269   // Determine which processor should create the new vertex
00270   Entity *
00271   old_vertex = getBulkData()->get_entity(vertex_key);
00272 
00273   // For now, the owner of the new vertex is the same as the owner of the old one
00274   int owner_proc = old_vertex->owner_rank();
00275 
00276   // The owning processor inserts a new vertex into the stk mesh
00277   // First have to request a new entity of rank N
00278   std::vector<size_t> requests(getSpaceDimension() + 1, 0); // number of entity ranks. 1 + number of dimensions
00279   EntityVector new_entity;
00280   const stk::mesh::PartVector no_parts;
00281 
00282   int my_proc = getBulkData()->parallel_rank();
00283   int source;
00284   Entity *global_vertex;
00285   EntityKey global_vertex_key;
00286   EntityKey::raw_key_type gvertkey;
00287 
00288   if(my_proc == owner_proc){
00289 
00290     // Insert the vertex into the stk mesh
00291     // First have to request a new entity of rank N
00292     requests[vertex_rank] = 1;
00293 
00294     // have stk build the new entity, then broadcast the key
00295 
00296     getBulkData()->generate_new_entities(requests, new_entity);
00297     global_vertex = new_entity[0];
00298     //std::cout << " Proc: " << getBulkData()->parallel_rank() << " created entity: (" << global_vertex->identifier() << ", " <<
00299     //global_vertex->entity_rank() << ")." << '\n';
00300     global_vertex_key = global_vertex->key();
00301     gvertkey = global_vertex_key.raw_key();
00302 
00303   }
00304   else {
00305 
00306     // All other processors do a no-op
00307 
00308     getBulkData()->generate_new_entities(requests, new_entity);
00309 
00310   }
00311 
00312   Subgraph::bcast_key(owner_proc, global_vertex_key);
00313 
00314   if(my_proc != owner_proc){ // All other processors receive the key
00315 
00316     // Get the vertex from stk
00317 
00318     const stk::mesh::PartVector no_parts;
00319     Entity * new_entity = & getBulkData()->declare_entity(global_vertex_key.rank(), global_vertex_key.id(), no_parts);
00320 
00321   }
00322 
00323   // Insert the vertex into the subgraph
00324   Vertex local_vertex = boost::add_vertex(*this);
00325 
00326   // Update maps
00327   local_global_vertex_map_.insert(
00328       std::map<Vertex, EntityKey>::value_type(local_vertex,
00329           global_vertex_key));
00330   global_local_vertex_map_.insert(
00331       std::map<EntityKey, Vertex>::value_type(global_vertex_key,
00332           local_vertex));
00333 
00334   // store entity rank to the vertex property
00335   VertexNamePropertyMap vertex_property_map = boost::get(VertexName(), *this);
00336   boost::put(vertex_property_map, local_vertex, vertex_rank);
00337 
00338   return local_vertex;
00339 }
00340 
00341 //
00342 // Remove vertex in subgraph
00343 //
00344 void
00345 Subgraph::removeVertex(Vertex const vertex)
00346 {
00347   // get the global entity key of vertex
00348   EntityKey
00349   key = localToGlobal(vertex);
00350 
00351   // look up entity from key
00352   Entity *
00353   entity = getBulkData()->get_entity(key);
00354 
00355   // remove the vertex and key from global_local_vertex_map_ and
00356   // local_global_vertex_map_
00357   global_local_vertex_map_.erase(key);
00358   local_global_vertex_map_.erase(vertex);
00359 
00360   // remove vertex from subgraph
00361   // first have to ensure that there are no edges in or out of the vertex
00362   boost::clear_vertex(vertex, *this);
00363   // remove the vertex
00364   boost::remove_vertex(vertex, *this);
00365 
00366   // destroy all relations to or from the entity
00367   PairIterRelation
00368   relations = entity->relations();
00369 
00370   for (size_t i = 0; i < relations.size(); ++i) {
00371 
00372     EdgeId
00373     edge_id = relations[i].identifier();
00374 
00375     Entity &
00376     target = *(relations[i].entity());
00377 
00378     getBulkData()->destroy_relation(*entity, target, edge_id);
00379   }
00380 
00381   // remove the entity from stk mesh
00382   bool const
00383   deleted = getBulkData()->destroy_entity(entity);
00384   assert(deleted);
00385 
00386   return;
00387 }
00388 
00389 //
00390 // Add edge to local graph.
00391 //
00392 std::pair<Edge, bool>
00393 Subgraph::addEdge(
00394     EdgeId const edge_id,
00395     Vertex const local_source_vertex,
00396     Vertex const local_target_vertex)
00397 {
00398   // get global entities
00399   EntityKey
00400   global_source_key = localToGlobal(local_source_vertex);
00401 
00402   EntityKey
00403   global_target_key = localToGlobal(local_target_vertex);
00404 
00405   Entity *
00406   global_source_vertex = getBulkData()->get_entity(global_source_key);
00407 
00408   Entity *
00409   global_target_vertex = getBulkData()->get_entity(global_target_key);
00410 
00411   assert(global_source_vertex->entity_rank() -
00412       global_target_vertex->entity_rank() == 1);
00413 
00414   // Add edge to local graph
00415   std::pair<Edge, bool>
00416   local_edge = boost::add_edge(local_source_vertex, local_target_vertex, *this);
00417 
00418   if (local_edge.second == false) return local_edge;
00419 
00420   // Add edge to stk mesh
00421   getBulkData()->declare_relation(
00422       *(global_source_vertex),
00423       *(global_target_vertex),
00424       edge_id);
00425 
00426   // Add edge id to edge property
00427   EdgeNamePropertyMap
00428   edge_property_map = boost::get(EdgeName(), *this);
00429 
00430   boost::put(edge_property_map, local_edge.first, edge_id);
00431 
00432   return local_edge;
00433 }
00434 
00435 //
00436 //
00437 //
00438 void
00439 Subgraph::removeEdge(
00440     Vertex const & local_source_vertex,
00441     Vertex const & local_target_vertex)
00442 {
00443   // Get the local id of the edge in the subgraph
00444   Edge
00445   edge;
00446 
00447   bool
00448   inserted;
00449 
00450   boost::tie(edge, inserted) =
00451       boost::edge(local_source_vertex, local_target_vertex, *this);
00452 
00453   assert(inserted);
00454 
00455   EdgeId
00456   edge_id = getEdgeId(edge);
00457 
00458   // remove local edge
00459   boost::remove_edge(local_source_vertex, local_target_vertex, *this);
00460 
00461   // remove relation from stk mesh
00462   EntityKey
00463   global_source_id = localToGlobal(local_source_vertex);
00464 
00465   EntityKey
00466   global_target_id = localToGlobal(local_target_vertex);
00467 
00468   Entity *
00469   global_source_vertex = getBulkData()->get_entity(global_source_id);
00470 
00471   Entity *
00472   global_target_vertex = getBulkData()->get_entity(global_target_id);
00473 
00474   getBulkData()->destroy_relation(
00475       *(global_source_vertex),
00476       *(global_target_vertex),
00477       edge_id);
00478 
00479   return;
00480 }
00481 
00482 //
00483 //
00484 //
00485 EntityRank
00486 Subgraph::getVertexRank(Vertex const vertex)
00487 {
00488   VertexNamePropertyMap
00489   vertex_property_map = boost::get(VertexName(), *this);
00490   return boost::get(vertex_property_map, vertex);
00491 }
00492 
00493 //
00494 //
00495 //
00496 EdgeId
00497 Subgraph::getEdgeId(Edge const edge)
00498 {
00499   EdgeNamePropertyMap
00500   edge_property_map = boost::get(EdgeName(), *this);
00501   return boost::get(edge_property_map, edge);
00502 }
00503 
00504 //
00505 // Function determines whether the input vertex is an articulation
00506 // point of the subgraph.
00507 //
00508 void
00509 Subgraph::testArticulationPoint(
00510     Vertex const input_vertex,
00511     size_t & number_components,
00512     ComponentMap & component_map)
00513 {
00514   // Here we use the connected components algorithm, which requires
00515   // and undirected graph. These types are needed to build that graph
00516   // without the overhead that was used for the subgraph.
00517   // The adjacency list type must use a vector container for the vertices
00518   // so that they can be converted to indices to determine the components.
00519   typedef boost::adjacency_list<Vector, Vector, Undirected> UGraph;
00520   typedef boost::graph_traits<UGraph>::vertex_descriptor UVertex;
00521   typedef boost::graph_traits<UGraph>::edge_descriptor UEdge;
00522 
00523   // Map to and from undirected graph and subgraph
00524   std::map<UVertex, Vertex>
00525   u_sub_vertex_map;
00526 
00527   std::map<Vertex, UVertex>
00528   sub_u_vertex_map;
00529 
00530   UGraph
00531   graph;
00532 
00533   VertexIterator
00534   vertex_begin;
00535 
00536   VertexIterator
00537   vertex_end;
00538 
00539   boost::tie(vertex_begin, vertex_end) = vertices(*this);
00540 
00541   // First add the vertices to the graph
00542   for (VertexIterator i = vertex_begin; i != vertex_end; ++i) {
00543 
00544     Vertex
00545     vertex = *i;
00546 
00547     if (vertex == input_vertex) continue;
00548 
00549     UVertex
00550     uvertex = boost::add_vertex(graph);
00551 
00552     // Add to maps
00553     std::pair<UVertex, Vertex>
00554     u_sub = std::make_pair(uvertex, vertex);
00555 
00556     std::pair<Vertex, UVertex>
00557     sub_u = std::make_pair(vertex, uvertex);
00558 
00559     u_sub_vertex_map.insert(u_sub);
00560     sub_u_vertex_map.insert(sub_u);
00561   }
00562 
00563   // Then add the edges
00564   for (VertexIterator i = vertex_begin; i != vertex_end; ++i) {
00565 
00566     Vertex
00567     source = *i;
00568 
00569     if (source == input_vertex) continue;
00570 
00571     std::map<Vertex, UVertex>::const_iterator
00572     source_map_iterator = sub_u_vertex_map.find(source);
00573 
00574     UVertex
00575     usource = (*source_map_iterator).second;
00576 
00577     // write the edges in the subgraph
00578     OutEdgeIterator
00579     out_edge_begin;
00580 
00581     OutEdgeIterator
00582     out_edge_end;
00583 
00584     boost::tie(out_edge_begin, out_edge_end) = out_edges(source, *this);
00585 
00586     for (OutEdgeIterator j = out_edge_begin; j != out_edge_end; ++j) {
00587 
00588       Edge
00589       edge = *j;
00590 
00591       Vertex
00592       target = boost::target(edge, *this);
00593 
00594       if (target == input_vertex) continue;
00595 
00596       std::map<Vertex, UVertex>::const_iterator
00597       target_map_iterator = sub_u_vertex_map.find(target);
00598 
00599       UVertex
00600       utarget = (*target_map_iterator).second;
00601 
00602       boost::add_edge(usource, utarget, graph);
00603 
00604     }
00605   }
00606 
00607   std::vector<size_t>
00608   components(boost::num_vertices(graph));
00609 
00610   number_components = boost::connected_components(graph, &components[0]);
00611 
00612   for (std::map<UVertex, Vertex>::iterator i = u_sub_vertex_map.begin();
00613       i != u_sub_vertex_map.end(); ++i) {
00614 
00615     Vertex
00616     vertex = (*i).second;
00617 
00618     size_t
00619     component_number = static_cast<size_t>((*i).first);
00620 
00621     std::pair<Vertex, size_t>
00622     component = std::make_pair(vertex, components[component_number]);
00623 
00624     component_map.insert(component);
00625   }
00626 
00627   return;
00628 }
00629 
00630 //
00631 // Clones a boundary entity from the subgraph and separates the in-edges
00632 // of the entity.
00633 //
00634 Vertex
00635 Subgraph::cloneBoundaryEntity(Vertex vertex)
00636 {
00637   EntityRank
00638   vertex_rank = getVertexRank(vertex);
00639 
00640   assert(vertex_rank == getBoundaryRank());
00641 
00642   Vertex
00643   new_vertex = addVertex(vertex_rank);
00644 
00645   // Copy the out_edges of vertex to new_vertex
00646   OutEdgeIterator
00647   out_edge_begin;
00648 
00649   OutEdgeIterator
00650   out_edge_end;
00651 
00652   boost::tie(out_edge_begin, out_edge_end) = boost::out_edges(vertex, *this);
00653 
00654   for (OutEdgeIterator i = out_edge_begin; i != out_edge_end; ++i) {
00655     Edge
00656     edge = *i;
00657 
00658     EdgeId
00659     edge_id = getEdgeId(edge);
00660 
00661     Vertex
00662     target = boost::target(edge, *this);
00663 
00664     addEdge(edge_id, new_vertex, target);
00665   }
00666 
00667   // Copy all out edges not in the subgraph to the new vertex
00668   cloneOutEdges(vertex, new_vertex);
00669 
00670   // Remove one of the edges from vertex, copy to new_vertex
00671   // Arbitrarily remove the first edge from original vertex
00672   InEdgeIterator
00673   in_edge_begin;
00674 
00675   InEdgeIterator
00676   in_edge_end;
00677 
00678   boost::tie(in_edge_begin, in_edge_end) = boost::in_edges(vertex, *this);
00679 
00680   Edge
00681   edge = *(in_edge_begin);
00682 
00683   EdgeId
00684   edge_id = getEdgeId(edge);
00685 
00686   Vertex
00687   source = boost::source(edge, *this);
00688 
00689   removeEdge(source, vertex);
00690 
00691   // Add edge to new vertex
00692   addEdge(edge_id, source, new_vertex);
00693 
00694   return new_vertex;
00695 }
00696 
00697 //------------------------------------------------------------------------------
00698 void
00699 Subgraph::cloneBoundaryEntity(Vertex & vertex, Vertex & new_vertex,
00700     std::map<EntityKey, bool> & entity_open)
00701 {
00702   // Check that number of in_edges = 2
00703   boost::graph_traits<Graph>::degree_size_type num_in_edges =
00704       boost::in_degree(vertex, *this);
00705   if (num_in_edges != 2) return;
00706 
00707   // Check that vertex = open
00708   EntityKey vertex_key = Subgraph::localToGlobal(vertex);
00709   assert(entity_open[vertex_key]==true);
00710 
00711   // Get the vertex rank
00712   //    EntityRank vertex_rank = Subgraph::getVertexRank(vertex);
00713 
00714   // Create a new vertex of same rank as vertex
00715   //    newVertex = Subgraph::add_vertex(vertex_rank);
00716   new_vertex = Subgraph::cloneVertex(vertex);
00717 
00718   // Copy the out_edges of vertex to new_vertex
00719   OutEdgeIterator out_edge_begin;
00720   OutEdgeIterator out_edge_end;
00721   boost::tie(out_edge_begin, out_edge_end) = boost::out_edges(vertex, *this);
00722   for (OutEdgeIterator i = out_edge_begin; i != out_edge_end; ++i) {
00723     Edge edge = *i;
00724     EdgeId edgeId = Subgraph::getEdgeId(edge);
00725     Vertex target = boost::target(edge, *this);
00726     Subgraph::addEdge(edgeId, new_vertex, target);
00727   }
00728 
00729   // Copy all out edges not in the subgraph to the new vertex
00730   Subgraph::cloneOutEdges(vertex, new_vertex);
00731 
00732   // Remove one of the edges from vertex, copy to new_vertex
00733   // Arbitrarily remove the first edge from original vertex
00734   InEdgeIterator in_edge_begin;
00735   InEdgeIterator in_edge_end;
00736   boost::tie(in_edge_begin, in_edge_end) = boost::in_edges(vertex, *this);
00737   Edge edge = *(in_edge_begin);
00738   EdgeId edgeId = Subgraph::getEdgeId(edge);
00739   Vertex source = boost::source(edge, *this);
00740   Subgraph::removeEdge(source, vertex);
00741 
00742   // Add edge to new vertex
00743   Subgraph::addEdge(edgeId, source, new_vertex);
00744 
00745   // Have to clone the out edges of the original entity to the new entity.
00746   // These edges are not in the subgraph
00747 
00748   // Clone process complete, set entity_open to false
00749   entity_open[vertex_key] = false;
00750 
00751   return;
00752 }
00753 
00754 //
00755 // Splits an articulation point.
00756 //
00757 std::map<Entity*, Entity*>
00758 Subgraph::splitArticulationPoint(Vertex vertex)
00759 {
00760   EntityRank
00761   vertex_rank = Subgraph::getVertexRank(vertex);
00762 
00763   // Create undirected graph
00764   size_t
00765   number_components;
00766 
00767   ComponentMap
00768   components;
00769 
00770   testArticulationPoint(vertex, number_components, components);
00771 
00772   // The function returns an updated connectivity map.
00773   // If the vertex rank is not node, then this map will be of size 0.
00774   std::map<Entity*, Entity*>
00775   new_connectivity;
00776 
00777   if (number_components == 1) return new_connectivity;
00778 
00779   // If more than one component, split vertex in subgraph and stk mesh.
00780   std::vector<Vertex>
00781   new_vertices;
00782 
00783   for (size_t i = 0; i < number_components - 1; ++i) {
00784     Vertex
00785     new_vertex = addVertex(vertex_rank);
00786 
00787     new_vertices.push_back(new_vertex);
00788   }
00789 
00790   // Create a map of elements to new node numbers
00791   // only if the input vertex is a node
00792   if (vertex_rank == NODE_RANK) {
00793     for (ComponentMap::iterator i = components.begin();
00794         i != components.end(); ++i) {
00795 
00796       size_t
00797       component_number = (*i).second;
00798 
00799       Vertex
00800       current_vertex = (*i).first;
00801 
00802       EntityRank
00803       current_rank = getVertexRank(current_vertex);
00804 
00805       // Only add to map if the vertex is an element
00806       if (current_rank == getCellRank() && component_number != 0) {
00807 
00808         Entity *
00809         element = getBulkData()->get_entity(localToGlobal(current_vertex));
00810 
00811         Vertex
00812         new_vertex = new_vertices[component_number - 1];
00813 
00814         Entity *
00815         new_node = getBulkData()->get_entity(localToGlobal(new_vertex));
00816 
00817         std::pair<Entity*, Entity*>
00818         nc = std::make_pair(element, new_node);
00819 
00820         new_connectivity.insert(nc);
00821       }
00822     }
00823   }
00824 
00825   // Copy the out edges of the original vertex to the new vertex
00826   for (size_t i = 0; i < new_vertices.size(); ++i) {
00827     cloneOutEdges(vertex, new_vertices[i]);
00828   }
00829 
00830   // Vector for edges to be removed. Vertex is source and edgeId the
00831   // local id of the edge
00832   std::vector<std::pair<Vertex, EdgeId> >
00833   removed;
00834 
00835   // Iterate over the in edges of the vertex to determine which will
00836   // be removed
00837   InEdgeIterator
00838   in_edge_begin;
00839 
00840   InEdgeIterator
00841   in_edge_end;
00842 
00843   boost::tie(in_edge_begin, in_edge_end) = boost::in_edges(vertex, *this);
00844 
00845   for (InEdgeIterator i = in_edge_begin; i != in_edge_end; ++i) {
00846     Edge
00847     edge = *i;
00848 
00849     Vertex
00850     source = boost::source(edge, *this);
00851 
00852     ComponentMap::const_iterator
00853     component_iterator = components.find(source);
00854 
00855     size_t
00856     vertex_component = (*component_iterator).second;
00857 
00858     Entity &
00859     entity = *(getBulkData()->get_entity(localToGlobal(source)));
00860 
00861     // Only replace edge if vertex not in component 0
00862     if (vertex_component != 0) {
00863       EdgeId
00864       edge_id = getEdgeId(edge);
00865 
00866       removed.push_back(std::make_pair(source, edge_id));
00867     }
00868   }
00869 
00870   // Remove all edges in vector removed and replace with new edges
00871   for (std::vector<std::pair<Vertex, EdgeId> >::iterator i = removed.begin();
00872       i != removed.end(); ++i) {
00873 
00874     std::pair<Vertex, EdgeId>
00875     edge = *i;
00876 
00877     Vertex
00878     source = edge.first;
00879 
00880     EdgeId
00881     edge_id = edge.second;
00882 
00883     ComponentMap::const_iterator
00884     component_iterator = components.find(source);
00885 
00886     size_t vertex_component = (*component_iterator).second;
00887 
00888     removeEdge(source, vertex);
00889 
00890     Vertex
00891     new_vertex = new_vertices[vertex_component - 1];
00892 
00893     std::pair<Edge, bool>
00894     inserted = addEdge(edge_id, source, new_vertex);
00895 
00896     assert(inserted.second==true);
00897   }
00898 
00899   return new_connectivity;
00900 }
00901 
00902 //----------------------------------------------------------------------------
00903 //
00904 // Splits an articulation point.
00905 //
00906 std::map<Entity*, Entity*>
00907 Subgraph::splitArticulationPoint(Vertex vertex,
00908     std::map<EntityKey, bool> & entity_open)
00909 {
00910   // Check that vertex = open
00911   EntityKey vertex_key = Subgraph::localToGlobal(vertex);
00912   assert(entity_open[vertex_key]==true);
00913 
00914   // get rank of vertex
00915   EntityRank vertex_rank = Subgraph::getVertexRank(vertex);
00916 
00917   // Create undirected graph
00918   size_t num_components;
00919   ComponentMap components;
00920   Subgraph::testArticulationPoint(vertex, num_components, components);
00921 
00922   // The function returns an updated connectivity map. If the vertex
00923   //   rank is not node, then this map will be of size 0.
00924   std::map<Entity*, Entity*> new_connectivity;
00925 
00926   // Check number of connected components in undirected graph. If =
00927   // 1, return
00928   if (num_components == 1) return new_connectivity;
00929 
00930   // If number of connected components > 1, split vertex in subgraph and stk mesh
00931   // number of new vertices = numComponents - 1
00932   std::vector<Vertex> new_vertex;
00933   for (int i = 0; i < num_components - 1; ++i) {
00934     //      Vertex newVert = Subgraph::add_vertex(vertex_rank);
00935     Vertex new_vert = Subgraph::cloneVertex(vertex);
00936     new_vertex.push_back(new_vert);
00937   }
00938 
00939   // create a map of elements to new node numbers
00940   // only do this if the input vertex is a node (don't require otherwise)
00941   if (vertex_rank == 0) {
00942     for (ComponentMap::iterator i = components.begin();
00943         i != components.end(); ++i) {
00944       int component_num = (*i).second;
00945       Vertex current_vertex = (*i).first;
00946       EntityRank current_rank = Subgraph::getVertexRank(current_vertex);
00947       // Only add to map if the vertex is an element
00948       if (current_rank == getSpaceDimension() && component_num != 0) {
00949         Entity* element =
00950             getBulkData()->get_entity(Subgraph::localToGlobal(current_vertex));
00951         Entity* new_node =
00952             getBulkData()->
00953             get_entity(Subgraph::localToGlobal(new_vertex[component_num - 1]));
00954         new_connectivity.
00955         insert(std::map<Entity*, Entity*>::value_type(element, new_node));
00956       }
00957     }
00958   }
00959 
00960   // Copy the out edges of the original vertex to the new vertex
00961   for (int i = 0; i < new_vertex.size(); ++i) {
00962     Subgraph::cloneOutEdges(vertex, new_vertex[i]);
00963   }
00964 
00965   // vector for edges to be removed. Vertex is source and edgeId the
00966   // local id of the edge
00967   std::vector<std::pair<Vertex, EdgeId> > removed;
00968 
00969   // Iterate over the in edges of the vertex to determine which will
00970   // be removed
00971   InEdgeIterator in_edge_begin;
00972   InEdgeIterator in_edge_end;
00973   boost::tie(in_edge_begin, in_edge_end) = boost::in_edges(vertex, *this);
00974   for (InEdgeIterator i = in_edge_begin; i != in_edge_end; ++i) {
00975     Edge edge = *i;
00976     Vertex source = boost::source(edge, *this);
00977 
00978     ComponentMap::const_iterator componentIterator =
00979         components.find(source);
00980     int vertComponent = (*componentIterator).second;
00981     Entity& entity =
00982         *(getBulkData()->get_entity(Subgraph::localToGlobal(source)));
00983     // Only replace edge if vertex not in component 0
00984     if (vertComponent != 0) {
00985       EdgeId edgeId = Subgraph::getEdgeId(edge);
00986       removed.push_back(std::make_pair(source, edgeId));
00987     }
00988   }
00989 
00990   // remove all edges in vector removed and replace with new edges
00991   for (std::vector<std::pair<Vertex, EdgeId> >::iterator i = removed.begin();
00992       i != removed.end(); ++i) {
00993     std::pair<Vertex, EdgeId> edge = *i;
00994     Vertex source = edge.first;
00995     EdgeId edgeId = edge.second;
00996     ComponentMap::const_iterator componentIterator =
00997         components.find(source);
00998     int vertComponent = (*componentIterator).second;
00999 
01000     Subgraph::removeEdge(source, vertex);
01001     std::pair<Edge, bool> inserted =
01002         Subgraph::addEdge(edgeId, source,new_vertex[vertComponent - 1]);
01003     assert(inserted.second==true);
01004   }
01005 
01006   // split process complete, set entity_open to false
01007   entity_open[vertex_key] = false;
01008 
01009   return new_connectivity;
01010 }
01011 
01012 //
01013 // Clone all out edges of a vertex to a new vertex.
01014 //
01015 void
01016 Subgraph::cloneOutEdges(Vertex old_vertex, Vertex new_vertex)
01017 {
01018   // Get the entity for the old and new vertices
01019   EntityKey
01020   old_key = localToGlobal(old_vertex);
01021 
01022   EntityKey
01023   new_key = localToGlobal(new_vertex);
01024 
01025   Entity &
01026   old_entity = *(getBulkData()->get_entity(old_key));
01027 
01028   Entity &
01029   new_entity = *(getBulkData()->get_entity(new_key));
01030 
01031   // Iterate over the out edges of the old vertex and check against the
01032   // out edges of the new vertex. If the edge does not exist, add.
01033   PairIterRelation
01034   old_relations = old_entity.relations(old_entity.entity_rank() - 1);
01035 
01036   for (size_t i = 0; i < old_relations.size(); ++i) {
01037     PairIterRelation
01038     new_relations = new_entity.relations(new_entity.entity_rank() - 1);
01039 
01040     // assume the edge doesn't exist
01041     bool
01042     exists = false;
01043 
01044     for (size_t j = 0; j < new_relations.size(); ++j) {
01045       if (old_relations[i].entity() == new_relations[j].entity()) {
01046         exists = true;
01047       }
01048     }
01049 
01050     if (exists == false) {
01051       EdgeId
01052       edge_id = old_relations[i].identifier();
01053 
01054       Entity &
01055       target = *(old_relations[i].entity());
01056 
01057       getBulkData()->declare_relation(new_entity, target, edge_id);
01058     }
01059   }
01060 
01061   return;
01062 }
01063 
01079 void Subgraph::outputToGraphviz(std::string & gviz_output,
01080     std::map<EntityKey, bool> entity_open)
01081 {
01082   // Open output file
01083   std::ofstream gviz_out;
01084   gviz_out.open(gviz_output.c_str(), std::ios::out);
01085 
01086   std::cout << "Write graph to graphviz dot file\n";
01087 
01088   if (gviz_out.is_open()) {
01089     // Write beginning of file
01090     gviz_out << "digraph mesh {\n" << "  node [colorscheme=paired12]\n"
01091         << "  edge [colorscheme=paired12]\n";
01092 
01093     VertexIterator vertex_begin;
01094     VertexIterator vertex_end;
01095     boost::tie(vertex_begin, vertex_end) = vertices(*this);
01096 
01097     for (VertexIterator i = vertex_begin; i != vertex_end; ++i) {
01098       EntityKey key = localToGlobal(*i);
01099       Entity & entity = *(getBulkData()->get_entity(key));
01100       std::string label;
01101       std::string color;
01102 
01103       // Write the entity name
01104       switch (entity.entity_rank()) {
01105       // nodes
01106       case 0:
01107         label = "Node";
01108         if (entity_open[entity.key()] == false)
01109           color = "6";
01110         else
01111           color = "5";
01112         break;
01113         // segments
01114       case 1:
01115         label = "Segment";
01116         if (entity_open[entity.key()] == false)
01117           color = "4";
01118         else
01119           color = "3";
01120         break;
01121         // faces
01122       case 2:
01123         label = "Face";
01124         if (entity_open[entity.key()] == false)
01125           color = "2";
01126         else
01127           color = "1";
01128         break;
01129         // volumes
01130       case 3:
01131         label = "Element";
01132         if (entity_open[entity.key()] == false)
01133           color = "8";
01134         else
01135           color = "7";
01136         break;
01137       }
01138       gviz_out << "  \"" << entity.identifier() << "_" << entity.entity_rank()
01139                      << "\" [label=\" " << label << " " << entity.identifier()
01140                      << "\",style=filled,fillcolor=\"" << color << "\"]\n";
01141 
01142       // write the edges in the subgraph
01143       OutEdgeIterator out_edge_begin;
01144       OutEdgeIterator out_edge_end;
01145       boost::tie(out_edge_begin, out_edge_end) = out_edges(*i, *this);
01146 
01147       for (OutEdgeIterator j = out_edge_begin; j != out_edge_end; ++j) {
01148         Edge out_edge = *j;
01149         Vertex source = boost::source(out_edge, *this);
01150         Vertex target = boost::target(out_edge, *this);
01151 
01152         EntityKey sourceKey = localToGlobal(source);
01153         Entity & global_source = *(getBulkData()->get_entity(sourceKey));
01154 
01155         EntityKey targetKey = localToGlobal(target);
01156         Entity & global_target = *(getBulkData()->get_entity(targetKey));
01157 
01158         EdgeId edgeId = getEdgeId(out_edge);
01159 
01160         switch (edgeId) {
01161         case 0:
01162           color = "6";
01163           break;
01164         case 1:
01165           color = "4";
01166           break;
01167         case 2:
01168           color = "2";
01169           break;
01170         case 3:
01171           color = "8";
01172           break;
01173         case 4:
01174           color = "10";
01175           break;
01176         case 5:
01177           color = "12";
01178           break;
01179         default:
01180           color = "9";
01181         }
01182         gviz_out << "  \"" << global_source.identifier() << "_"
01183             << global_source.entity_rank() << "\" -> \""
01184             << global_target.identifier() << "_"
01185             << global_target.entity_rank() << "\" [color=\"" << color << "\"]"
01186             << "\n";
01187       }
01188 
01189     }
01190 
01191     // File end
01192     gviz_out << "}";
01193     gviz_out.close();
01194   } else
01195     std::cout << "Unable to open graphviz output file 'output.dot'\n";
01196 
01197   return;
01198 }
01199 
01200 } // namespace LCM

Generated on Wed Mar 26 2014 18:36:44 for Albany: a Trilinos-based PDE code by  doxygen 1.7.1