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

Topology.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 <boost/foreach.hpp>
00007 
00008 #include "Subgraph.h"
00009 #include "Topology.h"
00010 #include "Topology_Utils.h"
00011 
00012 namespace LCM {
00013 
00014 //
00015 // Default constructor
00016 //
00017 Topology::Topology() :
00018     discretization_(Teuchos::null),
00019     stk_mesh_struct_(Teuchos::null),
00020     fracture_criterion_(Teuchos::null)
00021 {
00022   return;
00023 }
00024 
00025 //
00026 // Constructor with input and output files.
00027 //
00028 Topology::Topology(
00029     std::string const & input_file,
00030     std::string const & output_file) :
00031     discretization_(Teuchos::null),
00032     stk_mesh_struct_(Teuchos::null),
00033     fracture_criterion_(Teuchos::null)
00034 {
00035   RCP<Teuchos::ParameterList>
00036   params = Teuchos::rcp(new Teuchos::ParameterList("params"));
00037 
00038   // Create discretization object
00039   RCP<Teuchos::ParameterList>
00040   disc_params = Teuchos::sublist(params, "Discretization");
00041 
00042   // Set Method to Exodus and set input file name
00043   disc_params->set<std::string>("Method", "Exodus");
00044   disc_params->set<std::string>("Exodus Input File Name", input_file);
00045   disc_params->set<std::string>("Exodus Output File Name", output_file);
00046 
00047   RCP<Teuchos::ParameterList>
00048   problem_params = Teuchos::sublist(params, "Problem");
00049 
00050   RCP<Teuchos::ParameterList>
00051   adapt_params = Teuchos::sublist(problem_params, "Adaptation");
00052 
00053   RCP<Epetra_Comm>
00054   communicator = Albany::createEpetraCommFromMpiComm(Albany_MPI_COMM_WORLD);
00055 
00056   Albany::DiscretizationFactory
00057   disc_factory(params, communicator);
00058 
00059   // Needed, otherwise segfaults.
00060   Teuchos::ArrayRCP<RCP<Albany::MeshSpecsStruct> >
00061   mesh_specs = disc_factory.createMeshSpecs();
00062 
00063   RCP<Albany::StateInfoStruct>
00064   state_info = Teuchos::rcp(new Albany::StateInfoStruct());
00065 
00066   // The default fields
00067   Albany::AbstractFieldContainer::FieldContainerRequirements
00068   req;
00069 
00070   setDiscretization(disc_factory.createDiscretization(3, state_info, req));
00071 
00072   Topology::createDiscretization();
00073 
00074   // Fracture the mesh randomly
00075   // Probability that fracture_criterion will return true.
00076   double const
00077   probability = 0.1;
00078 
00079   setFractureCriterion(
00080       Teuchos::rcp(new FractureCriterionRandom(
00081           getSpaceDimension(), probability))
00082   );
00083 
00084   // Create the full mesh representation. This must be done prior to
00085   // the adaptation query. We are reading the mesh from a file so do
00086   // it here.
00087   Topology::graphInitialization();
00088 
00089   return;
00090 }
00091 
00092 //
00093 // This constructor assumes that the full mesh graph has been
00094 // previously created. Topology::graphInitialization();
00095 //
00096 Topology::
00097 Topology(RCP<Albany::AbstractDiscretization> & discretization) :
00098   discretization_(Teuchos::null),
00099   stk_mesh_struct_(Teuchos::null),
00100   fracture_criterion_(Teuchos::null)
00101 {
00102   setDiscretization(discretization);
00103 
00104   Topology::createDiscretization();
00105 
00106   // Fracture the mesh randomly
00107   // Probability that fracture_criterion will return true.
00108   double const
00109   probability = 0.1;
00110 
00111   setFractureCriterion(
00112       Teuchos::rcp(new FractureCriterionRandom(
00113           getSpaceDimension(), probability))
00114   );
00115 
00116   return;
00117 }
00118 
00119 //
00120 //
00121 //
00122 Topology::
00123 Topology(RCP<Albany::AbstractDiscretization>& discretization,
00124     RCP<AbstractFractureCriterion>& fracture_criterion) :
00125     discretization_(Teuchos::null),
00126     stk_mesh_struct_(Teuchos::null),
00127     fracture_criterion_(Teuchos::null)
00128 {
00129   setDiscretization(discretization);
00130   setFractureCriterion(fracture_criterion);
00131   Topology::createDiscretization();
00132 
00133   return;
00134 }
00135 
00136 //
00137 // Initialize fracture state field
00138 // It exists for all entities except cells (elements)
00139 //
00140 void
00141 Topology::initializeFractureState()
00142 {
00143   stk::mesh::Selector
00144   local_selector = getMetaData()->locally_owned_part();
00145 
00146   for (EntityRank rank = NODE_RANK; rank < getCellRank(); ++rank) {
00147 
00148     std::vector<Bucket*> const &
00149     buckets = getBulkData()->buckets(rank);
00150 
00151     EntityVector
00152     entities;
00153 
00154     stk::mesh::get_selected_entities(local_selector, buckets, entities);
00155 
00156     for (EntityVector::size_type i = 0; i < entities.size(); ++i) {
00157 
00158       Entity const &
00159       entity = *(entities[i]);
00160 
00161       setFractureState(entity, CLOSED);
00162 
00163     }
00164   }
00165 
00166   return;
00167 }
00168 
00169 //
00170 // Create Albany discretization
00171 //
00172 void
00173 Topology::createDiscretization()
00174 {
00175   // Need to access the bulk_data and meta_data classes in the mesh
00176   // data structure
00177   STKDiscretization &
00178   stk_discretization = static_cast<STKDiscretization &>(*getDiscretization());
00179 
00180   setSTKMeshStruct(stk_discretization.getSTKMeshStruct());
00181 
00182   // Get the topology of the elements. NOTE: Assumes one element
00183   // type in mesh.
00184   stk::mesh::Selector
00185   local_selector = getMetaData()->locally_owned_part();
00186 
00187   std::vector<Bucket*> const &
00188   buckets = getBulkData()->buckets(getCellRank());
00189 
00190   EntityVector
00191   cells;
00192 
00193   stk::mesh::get_selected_entities(local_selector, buckets, cells);
00194 
00195   Entity const &
00196   first_cell = *(cells[0]);
00197 
00198   setCellTopology(stk::mesh::fem::get_cell_topology(first_cell));
00199 
00200   return;
00201 }
00202 
00203 //
00204 // Initializes the default stk mesh object needed by class.
00205 //
00206 void Topology::graphInitialization()
00207 {
00208   stk::mesh::PartVector add_parts;
00209   stk::mesh::create_adjacent_entities(*(getBulkData()), add_parts);
00210 
00211   getBulkData()->modification_begin();
00212 
00213   removeMultiLevelRelations();
00214   initializeFractureState();
00215 
00216   getBulkData()->modification_end();
00217 
00218   return;
00219 }
00220 
00221 //
00222 // Removes multilevel relations.
00223 //
00224 void Topology::removeMultiLevelRelations()
00225 {
00226   typedef std::vector<EdgeId> EdgeIdList;
00227 
00228   size_t const
00229   cell_node_rank_distance = getCellRank() - NODE_RANK;
00230 
00231   // Go from points to cells
00232   for (EntityRank rank = NODE_RANK; rank <= getCellRank(); ++rank) {
00233 
00234     EntityVector
00235     entities;
00236 
00237     stk::mesh::get_entities(*(getBulkData()), rank, entities);
00238 
00239     for (size_t i = 0; i < entities.size(); ++i) {
00240 
00241       Entity &
00242       entity = *(entities[i]);
00243 
00244       PairIterRelation
00245       relations = entity.relations();
00246 
00247       EntityVector
00248       far_entities;
00249 
00250       EdgeIdList
00251       multilevel_relation_ids;
00252 
00253       // Collect relations to delete
00254       for (PairIterRelation::iterator relation_iter = relations.begin();
00255           relation_iter != relations.end(); ++relation_iter) {
00256 
00257         Relation const &
00258         relation = *relation_iter;
00259 
00260         EntityRank
00261         target_rank = relation.entity_rank();
00262 
00263         size_t const
00264         rank_distance =
00265             rank > target_rank ? rank - target_rank : target_rank - rank;
00266 
00267         bool const
00268         is_valid_relation =
00269             rank < target_rank ||
00270             rank_distance == 1 ||
00271             rank_distance == cell_node_rank_distance;
00272 
00273         if (is_valid_relation == false) {
00274           far_entities.push_back(relation_iter->entity());
00275           multilevel_relation_ids.push_back(relation_iter->identifier());
00276         }
00277 
00278       }
00279 
00280       // Delete them
00281       for (size_t i = 0; i < multilevel_relation_ids.size(); ++i) {
00282 
00283         Entity &
00284         far_entity = *(far_entities[i]);
00285 
00286         EdgeId const
00287         multilevel_relation_id = multilevel_relation_ids[i];
00288 
00289         getBulkData()->destroy_relation(
00290             entity,
00291             far_entity,
00292             multilevel_relation_id);
00293       }
00294 
00295     }
00296 
00297   }
00298 
00299   return;
00300 }
00301 
00302 //----------------------------------------------------------------------------
00303 //
00304 // Removes unneeded relations from the mesh.
00305 //
00306 void Topology::removeExtraRelations()
00307 {
00308   EntityVector element_list;
00309   stk::mesh::get_entities(*(getBulkData()), getCellRank(), element_list);
00310 
00311   // Remove extra relations from element
00312   for (int i = 0; i < element_list.size(); ++i) {
00313     Entity & element = *(element_list[i]);
00314     PairIterRelation relations = element.relations();
00315     EntityVector del_relations;
00316     std::vector<int> del_ids;
00317     for (PairIterRelation::iterator j = relations.begin();
00318         j != relations.end(); ++j) {
00319       // remove all relationships from element unless to faces(segments
00320       //   in 2D) or nodes
00321       if (j->entity_rank() != getCellRank() - 1
00322           && j->entity_rank() != NODE_RANK) {
00323         del_relations.push_back(j->entity());
00324         del_ids.push_back(j->identifier());
00325       }
00326     }
00327     for (int j = 0; j < del_relations.size(); ++j) {
00328       Entity & entity = *(del_relations[j]);
00329       getBulkData()->destroy_relation(element, entity, del_ids[j]);
00330     }
00331   };
00332 
00333   if (getCellRank() == VOLUME_RANK) {
00334     // Remove extra relations from face
00335     EntityVector face_list;
00336     stk::mesh::get_entities(*(getBulkData()), getCellRank() - 1, face_list);
00337     EntityRank entityRank = face_list[0]->entity_rank();
00338     for (int i = 0; i < face_list.size(); ++i) {
00339       Entity & face = *(face_list[i]);
00340       PairIterRelation relations = face_list[i]->relations();
00341       EntityVector del_relations;
00342       std::vector<int> del_ids;
00343       for (PairIterRelation::iterator j = relations.begin();
00344           j != relations.end(); ++j) {
00345         if (j->entity_rank() != entityRank + 1
00346             && j->entity_rank() != entityRank - 1) {
00347           del_relations.push_back(j->entity());
00348           del_ids.push_back(j->identifier());
00349         }
00350       }
00351       for (int j = 0; j < del_relations.size(); ++j) {
00352         Entity & entity = *(del_relations[j]);
00353         getBulkData()->destroy_relation(face, entity, del_ids[j]);
00354       }
00355     }
00356   }
00357 
00358   return;
00359 }
00360 
00361 //----------------------------------------------------------------------------
00362 //
00363 // Creates temporary nodal connectivity for the elements and removes
00364 // the relationships between the elements and nodes.
00365 //
00366 void Topology::removeNodeRelations()
00367 {
00368   // Create the temporary connectivity array
00369   EntityVector element_list;
00370   stk::mesh::get_entities(*(getBulkData()), getCellRank(), element_list);
00371 
00372   getBulkData()->modification_begin();
00373   for (int i = 0; i < element_list.size(); ++i) {
00374     PairIterRelation nodes = element_list[i]->relations(NODE_RANK);
00375     EntityVector temp;
00376     for (int j = 0; j < nodes.size(); ++j) {
00377       Entity* node = nodes[j].entity();
00378       temp.push_back(node);
00379     }
00380     connectivity_temp_.push_back(temp);
00381 
00382     for (int j = 0; j < temp.size(); ++j) {
00383       getBulkData()->destroy_relation(*(element_list[i]), *(temp[j]), j);
00384     }
00385   }
00386 
00387   getBulkData()->modification_end();
00388 
00389   return;
00390 }
00391 
00392 //
00393 // Returns array of pointers to Entities for the element to node relations
00394 //
00395 std::vector<EntityVector>
00396 Topology::getElementToNodeConnectivity()
00397 {
00398   // Create a list of element entities
00399   EntityVector
00400   element_list;
00401 
00402   EntityVector
00403   node_list;
00404 
00405   stk::mesh::get_entities(*(getBulkData()), getCellRank(), element_list);
00406 
00407   // vector to store the entity pointers
00408   std::vector<EntityVector>
00409   element_to_node_connectivity;
00410 
00411   // Loop over the elements
00412   EntityVector::size_type const
00413   number_of_elements = element_list.size();
00414 
00415   for (EntityVector::size_type i(0); i < number_of_elements; ++i) {
00416 
00417     PairIterRelation
00418     relations = element_list[i]->relations(NODE_RANK);
00419 
00420     size_t const
00421     nodes_per_element = relations.size();
00422 
00423     for (size_t j(0); j < nodes_per_element; ++j) {
00424 
00425       Entity*
00426       node = relations[j].entity();
00427 
00428       node_list.push_back(node);
00429     }
00430 
00431     element_to_node_connectivity.push_back(node_list);
00432   }
00433 
00434   return element_to_node_connectivity;
00435 }
00436 
00437 //----------------------------------------------------------------------------
00438 void
00439 Topology::
00440 removeElementToNodeConnectivity(std::vector<EntityVector>& oldElemToNode)
00441 {
00442   // Create the temporary connectivity array
00443   EntityVector element_list;
00444   stk::mesh::get_entities(*(getBulkData()), getCellRank(), element_list);
00445 
00446   getBulkData()->modification_begin();
00447   for (int i = 0; i < element_list.size(); ++i) {
00448     PairIterRelation nodes = element_list[i]->relations(NODE_RANK);
00449     EntityVector temp;
00450     for (int j = 0; j < nodes.size(); ++j) {
00451       Entity* node = nodes[j].entity();
00452       temp.push_back(node);
00453     }
00454 
00455     // save the current element to node connectivity and the local
00456     // to global numbering
00457     connectivity_temp_.push_back(temp);
00458     element_global_to_local_ids_[element_list[i]->identifier()] = i;
00459 
00460     for (int j = 0; j < temp.size(); ++j) {
00461       getBulkData()->destroy_relation(*(element_list[i]), *(temp[j]), j);
00462     }
00463   }
00464 
00465   getBulkData()->modification_end();
00466 
00467   return;
00468 }
00469 
00470 //----------------------------------------------------------------------------
00471 //
00472 // After mesh manipulations are complete, need to recreate a stk
00473 // mesh understood by Albany_STKDiscretization.
00474 void Topology::restoreElementToNodeConnectivity()
00475 {
00476   EntityVector element_list;
00477   stk::mesh::get_entities(*(getBulkData()), getCellRank(), element_list);
00478 
00479   getBulkData()->modification_begin();
00480 
00481   // Add relations from element to nodes
00482   for (int i = 0; i < element_list.size(); ++i) {
00483     Entity & element = *(element_list[i]);
00484     EntityVector element_connectivity = connectivity_temp_[i];
00485     for (int j = 0; j < element_connectivity.size(); ++j) {
00486       Entity & node = *(element_connectivity[j]);
00487       getBulkData()->declare_relation(element, node, j);
00488     }
00489   }
00490 
00491   // Recreate Albany STK Discretization
00492   STKDiscretization & stk_discretization =
00493       static_cast<STKDiscretization &>(*discretization_);
00494 
00495   RCP<Epetra_Comm> communicator =
00496       Albany::createEpetraCommFromMpiComm(Albany_MPI_COMM_WORLD);
00497 
00498   //stk_discretization.updateMesh(stkMeshStruct_, communicator);
00499   stk_discretization.updateMesh();
00500 
00501   getBulkData()->modification_end();
00502 
00503   return;
00504 }
00505 
00506 //----------------------------------------------------------------------------
00507 void
00508 Topology::
00509 restoreElementToNodeConnectivity(std::vector<EntityVector>& oldElemToNode)
00510 {
00511   EntityVector element_list;
00512   stk::mesh::get_entities(*(getBulkData()), getCellRank(), element_list);
00513 
00514   //    getBulkData()->modification_begin(); // need to comment GAH?
00515 
00516   // Add relations from element to nodes
00517   for (int i = 0; i < element_list.size(); ++i) {
00518     Entity & element = *(element_list[i]);
00519     EntityVector element_connectivity = oldElemToNode[i];
00520     for (int j = 0; j < element_connectivity.size(); ++j) {
00521       Entity & node = *(element_connectivity[j]);
00522       getBulkData()->declare_relation(element, node, j);
00523     }
00524   }
00525 
00526   getBulkData()->modification_end();
00527 
00528   return;
00529 }
00530 
00531 //----------------------------------------------------------------------------
00532 //
00533 // Determine the nodes associated with a face.
00534 //
00535 EntityVector Topology::getFaceNodes(Entity * entity)
00536 {
00537   EntityVector face_nodes;
00538 
00539   PairIterRelation elements = entity->relations(getCellRank());
00540   // local id for the current face
00541   unsigned faceId = elements[0].identifier();
00542   Entity * element = elements[0].entity();
00543   // number of nodes for the face
00544   unsigned numFaceNodes = getCellTopology().getNodeCount(entity->entity_rank(),
00545       faceId);
00546 
00547   // Create the ordered list of nodes for the face
00548   for (int i = 0; i < numFaceNodes; ++i) {
00549     // map the local node id for the face to the local node id for the element
00550     unsigned elem_node = getCellTopology().getNodeMap(entity->entity_rank(),
00551         faceId, i);
00552     // map the local element node id to the global node id
00553     int element_local_id = element_global_to_local_ids_[element->identifier()];
00554     Entity* node = connectivity_temp_[element_local_id][elem_node];
00555     face_nodes.push_back(node);
00556   }
00557 
00558   return face_nodes;
00559 }
00560 
00561 //
00562 // Determine nodes associated with a boundary entity
00563 //
00564 EntityVector
00565 Topology::getBoundaryEntityNodes(Entity const & boundary_entity)
00566 {
00567   EntityRank const
00568   boundary_rank = boundary_entity.entity_rank();
00569 
00570   assert(boundary_rank == getCellRank() - 1);
00571 
00572   EntityVector
00573   nodes;
00574 
00575   PairIterRelation
00576   relations = relations_one_up(boundary_entity);
00577 
00578   Entity const &
00579   first_cell = *(relations[0].entity());
00580 
00581   EdgeId const
00582   face_order = relations[0].identifier();
00583 
00584   size_t const
00585   number_face_nodes =
00586       getCellTopology().getNodeCount(boundary_rank, face_order);
00587 
00588   for (size_t i = 0; i < number_face_nodes; ++i) {
00589     EdgeId const
00590     cell_order = getCellTopology().getNodeMap(boundary_rank, face_order, i);
00591 
00592     // Brute force approach. Maybe there is a better way to do this?
00593     PairIterRelation
00594     node_relations = first_cell.relations(NODE_RANK);
00595 
00596     for (size_t i = 0; i < node_relations.size(); ++i) {
00597       if (node_relations[i].identifier() == cell_order) {
00598         nodes.push_back(node_relations[i].entity());
00599       }
00600     }
00601   }
00602 
00603   return nodes;
00604 }
00605 
00606 //
00607 // Create boundary mesh
00608 //
00609 void
00610 Topology::createBoundary()
00611 {
00612   stk::mesh::Part &
00613   boundary_part = *(getMetaData()->get_part("boundary"));
00614 
00615   stk::mesh::PartVector
00616   add_parts;
00617 
00618   add_parts.push_back(&boundary_part);
00619 
00620   stk::mesh::PartVector const
00621   part_vector = getMetaData()->get_parts();
00622 
00623   for (size_t i = 0; i < part_vector.size(); ++i) {
00624     std::cout << part_vector[i]->name() << '\n';
00625   }
00626 
00627   EntityRank const
00628   boundary_entity_rank = getCellRank() - 1;
00629 
00630   stk::mesh::Selector
00631   local_selector = getMetaData()->locally_owned_part();
00632 
00633   std::vector<Bucket*> const &
00634   buckets = getBulkData()->buckets(boundary_entity_rank);
00635 
00636   EntityVector
00637   entities;
00638 
00639   stk::mesh::get_selected_entities(local_selector, buckets, entities);
00640 
00641   getBulkData()->modification_begin();
00642   for (EntityVector::size_type i = 0; i < entities.size(); ++i) {
00643 
00644     Entity &
00645     entity = *(entities[i]);
00646 
00647     PairIterRelation
00648     relations = relations_one_up(entity);
00649 
00650     size_t const
00651     number_connected_cells = std::distance(relations.begin(), relations.end());
00652 
00653     switch (number_connected_cells) {
00654 
00655     default:
00656       std::cerr << "ERROR: " << __PRETTY_FUNCTION__;
00657       std::cerr << '\n';
00658       std::cerr << "Invalid number of connected cells: ";
00659       std::cerr << number_connected_cells;
00660       std::cerr << '\n';
00661       exit(1);
00662       break;
00663 
00664     case 1:
00665       getBulkData()->change_entity_parts(entity, add_parts);
00666       break;
00667 
00668     case 2:
00669       // Internal face, do nothing.
00670       break;
00671 
00672     }
00673 
00674   }
00675   getBulkData()->modification_end();
00676 
00677   return;
00678 }
00679 
00680 //
00681 // Output of boundary
00682 //
00683 void
00684 Topology::outputBoundary()
00685 {
00686   EntityRank const
00687   boundary_entity_rank = getCellRank() - 1;
00688 
00689   stk::mesh::Selector
00690   local_selector = getMetaData()->locally_owned_part();
00691 
00692   std::vector<Bucket*> const &
00693   buckets = getBulkData()->buckets(boundary_entity_rank);
00694 
00695   EntityVector
00696   entities;
00697 
00698   stk::mesh::get_selected_entities(local_selector, buckets, entities);
00699 
00700   for (EntityVector::size_type i = 0; i < entities.size(); ++i) {
00701 
00702     Entity const &
00703     entity = *(entities[i]);
00704 
00705     PairIterRelation
00706     relations = relations_one_up(entity);
00707 
00708     size_t const
00709     number_connected_cells = std::distance(relations.begin(), relations.end());
00710 
00711     switch (number_connected_cells) {
00712 
00713     default:
00714       std::cerr << "ERROR: " << __PRETTY_FUNCTION__;
00715       std::cerr << '\n';
00716       std::cerr << "Invalid number of connected cells: ";
00717       std::cerr << number_connected_cells;
00718       std::cerr << '\n';
00719       exit(1);
00720       break;
00721 
00722     case 1:
00723       {
00724         EntityVector const
00725         face_nodes = getBoundaryEntityNodes(entity);
00726         std::cout << entity.identifier() << " ";
00727         for (EntityVector::size_type i = 0; i < face_nodes.size(); ++i) {
00728           std::cout << face_nodes[i]->identifier() << " ";
00729         }
00730         std::cout << '\n';
00731       }
00732       break;
00733 
00734     case 2:
00735       // Internal face, do nothing.
00736       break;
00737 
00738     }
00739 
00740   }
00741 
00742   return;
00743 }
00744 
00745 //
00746 // Create cohesive connectivity
00747 // bcell: boundary cell
00748 //
00749 EntityVector
00750 Topology::createSurfaceElementConnectivity(Entity const & bcell1,
00751     Entity const & bcell2)
00752 {
00753   // number of nodes for the face
00754   size_t
00755   number_face_nodes = getCellTopology().getNodeCount(bcell1.entity_rank(), 0);
00756 
00757   // Traverse down the graph from the face. The first node of
00758   // segment $n$ is node $n$ of the face.
00759   PairIterRelation
00760   bcell1_relations = relations_one_down(bcell1);
00761 
00762   PairIterRelation
00763   bcell2_relations = relations_one_down(bcell2);
00764 
00765   EntityVector
00766   connectivity(2 * number_face_nodes);
00767 
00768   for (size_t i = 0; i < bcell1_relations.size(); ++i) {
00769 
00770     Entity &
00771     entity1 = *(bcell1_relations[i].entity());
00772 
00773     Entity &
00774     entity2 = *(bcell2_relations[i].entity());
00775 
00776     EntityRank const
00777     cell_rank = getCellRank();
00778 
00779     switch (getCellRank()) {
00780     default:
00781       std::cerr << "ERROR: " << __PRETTY_FUNCTION__;
00782       std::cerr << '\n';
00783       std::cerr << "Surface element not implemented for dimension: ";
00784       std::cerr << cell_rank;
00785       std::cerr << '\n';
00786       exit(1);
00787       break;
00788 
00789     case FACE_RANK:
00790       connectivity[i] = &entity1;
00791       connectivity[i + number_face_nodes] = &entity2;
00792       break;
00793 
00794     case VOLUME_RANK:
00795     {
00796       PairIterRelation
00797       segment1_relations = entity1.relations(entity1.entity_rank() - 1);
00798       PairIterRelation
00799       segment2_relations = entity2.relations(entity2.entity_rank() - 1);
00800 
00801       // Check for the correct node to add to the connectivity vector.
00802       // Each node should be used only once.
00803       bool const
00804       unique_node =
00805           (i == 0) ||
00806           (i > 0 && connectivity[i - 1] != segment1_relations[0].entity()) ||
00807           (i == number_face_nodes - 1
00808               && connectivity[0] != segment1_relations[0].entity());
00809 
00810       if (unique_node == true) {
00811         connectivity[i] = segment1_relations[0].entity();
00812         connectivity[i + number_face_nodes] = segment2_relations[0].entity();
00813       } else {
00814         connectivity[i] = segment1_relations[1].entity();
00815         connectivity[i + number_face_nodes] = segment2_relations[1].entity();
00816       }
00817     }
00818     break;
00819 
00820     }
00821 
00822   }
00823 
00824   return connectivity;
00825 }
00826 
00827 //
00828 // Create vectors describing the vertices and edges of the star of
00829 // an entity in the stk mesh.
00830 //
00831 void
00832 Topology::createStar(
00833     Entity & entity,
00834     std::set<EntityKey> & subgraph_entities,
00835     std::set<stkEdge, EdgeLessThan> & subgraph_edges)
00836 {
00837   subgraph_entities.insert(entity.key());
00838 
00839   PairIterRelation
00840   relations = relations_one_up(entity);
00841 
00842   for (PairIterRelation::iterator i = relations.begin();
00843       i != relations.end(); ++i) {
00844 
00845     Relation
00846     relation = *i;
00847 
00848     Entity &
00849     source = *(relation.entity());
00850 
00851     stkEdge
00852     edge;
00853 
00854     edge.source = source.key();
00855     edge.target = entity.key();
00856     edge.local_id = relation.identifier();
00857 
00858     subgraph_edges.insert(edge);
00859     createStar(source, subgraph_entities, subgraph_edges);
00860   }
00861 
00862   return;
00863 }
00864 
00865 //
00866 // Fractures all open boundary entities of the mesh.
00867 //
00868 void
00869 Topology::splitOpenFaces()
00870 {
00871   // 3D only for now.
00872   assert(getSpaceDimension() == VOLUME_RANK);
00873 
00874   EntityVector
00875   points;
00876 
00877   EntityVector
00878   open_points;
00879 
00880   stk::mesh::Selector
00881   selector_owned = getMetaData()->locally_owned_part();
00882 
00883   std::set<EntityPair>
00884   fractured_faces;
00885 
00886   stk::mesh::get_selected_entities(
00887       selector_owned,
00888       getBulkData()->buckets(NODE_RANK),
00889       points);
00890 
00891   // Collect open points
00892   for (EntityVector::iterator i = points.begin();i != points.end(); ++i) {
00893 
00894     Entity &
00895     point = *(*i);
00896 
00897     if (getFractureState(point) == OPEN) {
00898       open_points.push_back(&point);
00899     }
00900   }
00901 
00902   getBulkData()->modification_begin();
00903 
00904   // Iterate over open points and fracture them.
00905   for (EntityVector::iterator i = open_points.begin();
00906       i != open_points.end(); ++i) {
00907 
00908     Entity &
00909     point = *(*i);
00910 
00911     PairIterRelation
00912     relations = relations_one_up(point);
00913 
00914     EntityVector
00915     open_segments;
00916 
00917     // Collect open segments.
00918     for (PairIterRelation::iterator j = relations.begin();
00919         j != relations.end(); ++j) {
00920 
00921       Entity &
00922       segment = *j->entity();
00923 
00924       bool const
00925       is_local_and_open =
00926           isLocalEntity(segment) == true && getFractureState(segment) == OPEN;
00927 
00928       if (is_local_and_open == true) {
00929         open_segments.push_back(&segment);
00930       }
00931 
00932     }
00933 
00934     // Iterate over open segments and fracture them.
00935     for (EntityVector::iterator j = open_segments.begin();
00936         j != open_segments.end(); ++j) {
00937 
00938       Entity &
00939       segment = *(*j);
00940 
00941       // Create star of segment
00942       std::set<EntityKey>
00943       subgraph_entities;
00944 
00945       std::set<stkEdge, EdgeLessThan>
00946       subgraph_edges;
00947 
00948       createStar(segment, subgraph_entities, subgraph_edges);
00949 
00950       // Iterators
00951       std::set<EntityKey>::iterator
00952       first_entity = subgraph_entities.begin();
00953 
00954       std::set<EntityKey>::iterator
00955       last_entity = subgraph_entities.end();
00956 
00957       std::set<stkEdge>::iterator
00958       first_edge = subgraph_edges.begin();
00959 
00960       std::set<stkEdge>::iterator
00961       last_edge = subgraph_edges.end();
00962 
00963       Subgraph
00964       subgraph(getSTKMeshStruct(),
00965           first_entity, last_entity, first_edge, last_edge);
00966 
00967       // Collect open faces
00968       PairIterRelation
00969       face_relations = relations_one_up(segment);
00970 
00971       EntityVector
00972       open_faces;
00973 
00974       for (PairIterRelation::iterator k = face_relations.begin();
00975           k != face_relations.end(); ++k) {
00976 
00977         Entity *
00978         face = k->entity();
00979 
00980         if (isInternalAndOpen(*face) == true) {
00981           open_faces.push_back(face);
00982         }
00983       }
00984 
00985       // Iterate over the open faces
00986       for (EntityVector::iterator k = open_faces.begin();
00987           k != open_faces.end(); ++k) {
00988 
00989         Entity *
00990         face = *k;
00991 
00992         Vertex
00993         face_vertex = subgraph.globalToLocal(face->key());
00994 
00995         Vertex
00996         new_face_vertex;
00997         subgraph.cloneBoundaryEntity(face_vertex);
00998 
00999         EntityKey
01000         new_face_key = subgraph.localToGlobal(new_face_vertex);
01001 
01002         Entity *
01003         new_face = getBulkData()->get_entity(new_face_key);
01004 
01005         // Reset fracture state for both old and new faces
01006         setFractureState(*face, CLOSED);
01007         setFractureState(*new_face, CLOSED);
01008 
01009         EntityPair
01010         ff = std::make_pair(face, new_face);
01011 
01012         fractured_faces.insert(ff);
01013       }
01014 
01015       // Split the articulation point (current segment)
01016       Vertex
01017       segment_vertex = subgraph.globalToLocal(segment.key());
01018 
01019       subgraph.splitArticulationPoint(segment_vertex);
01020 
01021       // Reset segment fracture state
01022       setFractureState(segment, CLOSED);
01023 
01024     }
01025 
01026     // All open faces and segments have been dealt with.
01027     // Split the node articulation point
01028     // Create star of node
01029     std::set<EntityKey>
01030     subgraph_entities;
01031 
01032     std::set<stkEdge, EdgeLessThan>
01033     subgraph_edges;
01034 
01035     createStar(point, subgraph_entities, subgraph_edges);
01036 
01037     // Iterators
01038     std::set<EntityKey>::iterator
01039     first_entity = subgraph_entities.begin();
01040 
01041     std::set<EntityKey>::iterator
01042     last_entity = subgraph_entities.end();
01043 
01044     std::set<stkEdge>::iterator
01045     first_edge = subgraph_edges.begin();
01046 
01047     std::set<stkEdge>::iterator
01048     last_edge = subgraph_edges.end();
01049 
01050     Subgraph
01051     subgraph(
01052         getSTKMeshStruct(),
01053         first_entity,
01054         last_entity,
01055         first_edge,
01056         last_edge);
01057 
01058     Vertex
01059     node = subgraph.globalToLocal(point.key());
01060 
01061     std::map<Entity*, Entity*>
01062     new_connectivity = subgraph.splitArticulationPoint(node);
01063 
01064     // Reset fracture state of point
01065     setFractureState(point, CLOSED);
01066 
01067     // Update the connectivity
01068     for (std::map<Entity*, Entity*>::iterator j = new_connectivity.begin();
01069         j != new_connectivity.end(); ++j) {
01070 
01071       Entity *
01072       element = (*j).first;
01073 
01074       Entity *
01075       new_node = (*j).second;
01076 
01077       getBulkData()->copy_entity_fields(point, *new_node);
01078     }
01079 
01080   }
01081 
01082   getBulkData()->modification_end();
01083 
01084   getBulkData()->modification_begin();
01085 
01086   // Create the cohesive connectivity
01087   for (std::set<EntityPair>::iterator i =
01088       fractured_faces.begin(); i != fractured_faces.end(); ++i) {
01089 
01090     Entity & face1 = *((*i).first);
01091     Entity & face2 = *((*i).second);
01092 
01093     EntityVector
01094     cohesive_connectivity = createSurfaceElementConnectivity(face1, face2);
01095 
01096   }
01097 
01098   getBulkData()->modification_end();
01099   return;
01100 }
01101 
01102 //----------------------------------------------------------------------------
01103 //
01104 // Fractures all open boundary entities of the mesh.
01105 //
01106 #if 0  // original
01107 void
01108 Topology::splitOpenFaces(std::map<EntityKey, bool> & entity_open)
01109 {
01110   int numfractured = 0; //counter for number of fractured faces
01111 
01112   // Get set of open nodes
01113   EntityVector node_list; //all nodes
01114   EntityVector open_node_list; //only the open nodes
01115   stk::mesh::Selector select_owned_or_shared = getMetaData()->locally_owned_part() |
01116       getMetaData()->globally_shared_part();
01117 
01118   stk::mesh::get_selected_entities( select_owned_or_shared,
01119       getBulkData()->buckets( NODE_RANK ),
01120       node_list );
01121   for (EntityVector::iterator i = node_list.begin();
01122       i != node_list.end(); ++i) {
01123     Entity* entity = *i;
01124     if (entity_open[entity->key()] == true) {
01125       open_node_list.push_back(entity);
01126     }
01127   }
01128 
01129   getBulkData()->modification_begin();
01130 
01131   // Iterate over the open nodes
01132   for (EntityVector::iterator i = open_node_list.begin();
01133       i != open_node_list.end(); ++i) {
01134     // Get set of open segments
01135     Entity * entity = *i;
01136     PairIterRelation relations = entity->relations(EDGE_RANK);
01137     EntityVector open_segment_list;
01138 
01139     for (PairIterRelation::iterator j = relations.begin();
01140         j != relations.end(); ++j) {
01141       Entity & source = *j->entity();
01142       if (entity_open[source.key()] == true) {
01143         open_segment_list.push_back(&source);
01144       }
01145     }
01146 
01147     // Iterate over the open segments
01148     for (EntityVector::iterator j = open_segment_list.begin();
01149         j != open_segment_list.end(); ++j) {
01150       Entity * segment = *j;
01151       // Create star of segment
01152       std::set<EntityKey> subgraph_entity_list;
01153       std::set<stkEdge, EdgeLessThan> subgraph_edge_list;
01154       Topology::createStar(*segment, subgraph_entity_list, subgraph_edge_list);
01155       // Iterators
01156       std::set<EntityKey>::iterator firstEntity = subgraph_entity_list.begin();
01157       std::set<EntityKey>::iterator lastEntity = subgraph_entity_list.end();
01158       std::set<stkEdge>::iterator firstEdge = subgraph_edge_list.begin();
01159       std::set<stkEdge>::iterator lastEdge = subgraph_edge_list.end();
01160 
01161       Subgraph subgraph(getSTKMeshStruct(), firstEntity, lastEntity, firstEdge,
01162           lastEdge);
01163 
01164       // Clone open faces
01165       PairIterRelation faces = segment->relations(FACE_RANK);
01166       EntityVector open_face_list;
01167       // create a list of open faces
01168       for (PairIterRelation::iterator k = faces.begin();
01169           k != faces.end(); ++k) {
01170         Entity & source = *k->entity();
01171         if (entity_open[source.key()] == true) {
01172           open_face_list.push_back(&source);
01173         }
01174       }
01175 
01176       // Iterate over the open faces
01177       for (EntityVector::iterator k = open_face_list.begin();
01178           k != open_face_list.end(); ++k) {
01179         Entity * face = *k;
01180         Vertex faceVertex = subgraph.globalToLocal(face->key());
01181         Vertex newFaceVertex;
01182         subgraph.cloneBoundaryEntity(faceVertex, newFaceVertex,
01183             entity_open);
01184 
01185         EntityKey newFaceKey = subgraph.localToGlobal(newFaceVertex);
01186         Entity * newFace = getBulkData()->get_entity(newFaceKey);
01187 
01188         // add original and new faces to the fractured face list
01189         fractured_faces_.insert(std::make_pair(face, newFace));
01190 
01191         ++numfractured;
01192       }
01193 
01194       // Split the articulation point (current segment)
01195       Vertex segmentVertex = subgraph.globalToLocal(segment->key());
01196       subgraph.splitArticulationPoint(segmentVertex, entity_open);
01197     }
01198     // All open faces and segments have been dealt with. Split the node articulation point
01199     // Create star of node
01200     std::set<EntityKey> subgraph_entity_list;
01201     std::set<stkEdge, EdgeLessThan> subgraph_edge_list;
01202     Topology::createStar(*entity, subgraph_entity_list, subgraph_edge_list);
01203     // Iterators
01204     std::set<EntityKey>::iterator firstEntity = subgraph_entity_list.begin();
01205     std::set<EntityKey>::iterator lastEntity = subgraph_entity_list.end();
01206     std::set<stkEdge>::iterator firstEdge = subgraph_edge_list.begin();
01207     std::set<stkEdge>::iterator lastEdge = subgraph_edge_list.end();
01208     Subgraph subgraph(getSTKMeshStruct(),
01209         firstEntity, lastEntity, firstEdge, lastEdge);
01210 
01211     Vertex node = subgraph.globalToLocal(entity->key());
01212     std::map<Entity*, Entity*> new_connectivity =
01213         subgraph.splitArticulationPoint(node, entity_open);
01214 
01215     // Update the connectivity
01216     for (std::map<Entity*, Entity*>::iterator j = new_connectivity.begin();
01217         j != new_connectivity.end(); ++j) {
01218       Entity* element = (*j).first;
01219       Entity* newNode = (*j).second;
01220 
01221       int element_id = element_global_to_local_ids_[element->identifier()];
01222       EntityVector & element_connectivity = connectivity_temp_[element_id];
01223       for (int k = 0; k < element_connectivity.size(); ++k) {
01224         // Need to subtract 1 from element number as stk indexes from 1
01225         //   and connectivity_temp indexes from 0
01226         if (element_connectivity[k] == entity) {
01227           element_connectivity[k] = newNode;
01228           // Duplicate the parameters of old node to new node
01229           getBulkData()->copy_entity_fields(*entity, *newNode);
01230         }
01231       }
01232     }
01233   }
01234 
01235   getBulkData()->modification_end();
01236   getBulkData()->modification_begin();
01237 
01238   // Create the cohesive connectivity
01239   int j = 1;
01240   for (std::set<EntityPair>::iterator i =
01241       fractured_faces_.begin(); i != fractured_faces_.end(); ++i, ++j) {
01242     Entity * face1 = (*i).first;
01243     Entity * face2 = (*i).second;
01244     EntityVector cohesive_connectivity;
01245     cohesive_connectivity =
01246         Topology::createSurfaceElementConnectivity(*face1, *face2);
01247 
01248     // Output connectivity for testing purposes
01249     std::cout << "Cohesive Element " << j << ": ";
01250     for (int j = 0; j < cohesive_connectivity.size(); ++j) {
01251       std::cout << cohesive_connectivity[j]->identifier() << ":";
01252     }
01253     std::cout << "\n";
01254   }
01255 
01256   getBulkData()->modification_end();
01257   return;
01258 }
01259 #endif
01260 
01261 void Topology::splitOpenFaces(std::map<EntityKey, bool> & global_entity_open)
01262 {
01263   EntityVector open_node_list; // Global open node list
01264 
01265   std::cout << " \n\nGlobal stuff in fracture_boundary\n\n" << '\n';
01266 
01267   // Build list of open nodes (global)
01268 
01269   std::pair<EntityKey,bool> me; // what a map<EntityKey, bool> is made of
01270 
01271   BOOST_FOREACH(me, global_entity_open) {
01272 
01273     if(stk::mesh::entity_rank( me.first) == NODE_RANK){
01274 
01275       Entity *entity = getBulkData()->get_entity(me.first);
01276       std::cout << "Found open node: " << entity->identifier() << " belonging to pe: " << entity->owner_rank() << '\n';
01277       open_node_list.push_back(entity);
01278     }
01279   }
01280 
01281   getBulkData()->modification_begin();
01282 
01283   // Iterate over the open nodes
01284   for (EntityVector::iterator i = open_node_list.begin();
01285       i != open_node_list.end(); ++i) {
01286     // Get set of open segments
01287     Entity * entity = *i;
01288     PairIterRelation relations = entity->relations(EDGE_RANK);
01289     EntityVector open_segment_list;
01290 
01291     for (PairIterRelation::iterator j = relations.begin();
01292         j != relations.end(); ++j) {
01293       Entity & source = *j->entity();
01294       if (global_entity_open[source.key()] == true) {
01295         std::cout << "Found open segment: " << source.identifier() << " belonging to pe: " << source.owner_rank() << '\n';
01296         open_segment_list.push_back(&source);
01297       }
01298     }
01299 
01300     // Iterate over the open segments
01301     for (EntityVector::iterator j = open_segment_list.begin();
01302         j != open_segment_list.end(); ++j) {
01303       Entity * segment = *j;
01304 
01305       // Create star of segment
01306       std::set<EntityKey> subgraph_entity_list;
01307       std::set<stkEdge, EdgeLessThan> subgraph_edge_list;
01308       Topology::createStar(*segment, subgraph_entity_list, subgraph_edge_list);
01309 
01310       // Iterators
01311       std::set<EntityKey>::iterator first_entity = subgraph_entity_list.begin();
01312       std::set<EntityKey>::iterator last_entity = subgraph_entity_list.end();
01313       std::set<stkEdge>::iterator first_edge = subgraph_edge_list.begin();
01314       std::set<stkEdge>::iterator last_edge = subgraph_edge_list.end();
01315 
01316       Subgraph subgraph(getSTKMeshStruct(),
01317           first_entity, last_entity, first_edge, last_edge);
01318 
01319       // Clone open faces
01320       PairIterRelation faces = segment->relations(FACE_RANK);
01321       EntityVector open_face_list;
01322 
01323       // create a list of open faces
01324       for (PairIterRelation::iterator k = faces.begin();
01325           k != faces.end(); ++k) {
01326         Entity & source = *k->entity();
01327         if (global_entity_open[source.key()] == true) {
01328           std::cout << "Found open face: " << source.identifier() << " belonging to pe: " << source.owner_rank() << '\n';
01329           open_face_list.push_back(&source);
01330         }
01331       }
01332       std::cout << "\n\n\n\n\n" << '\n';
01333 
01334       // Iterate over the open faces
01335       for (EntityVector::iterator k = open_face_list.begin();
01336           k != open_face_list.end(); ++k) {
01337         Entity * face = *k;
01338         Vertex face_vertex = subgraph.globalToLocal(face->key());
01339         Vertex new_face_vertex;
01340         subgraph.cloneBoundaryEntity(face_vertex, new_face_vertex,
01341             global_entity_open);
01342         EntityKey new_face_key = subgraph.localToGlobal(new_face_vertex);
01343         Entity * new_face = getBulkData()->get_entity(new_face_key);
01344 
01345         // add original and new faces to the fractured face list
01346         fractured_faces_.insert(std::make_pair(face, new_face));
01347 
01348       }
01349 
01350       // Split the articulation point (current segment)
01351       Vertex segment_vertex = subgraph.globalToLocal(segment->key());
01352       std::cout << "Calling split_articulation_point with segmentVertex: " << '\n';
01353       subgraph.splitArticulationPoint(segment_vertex, global_entity_open);
01354       std::cout << "done Calling split_articulation_point with segmentVertex: " << '\n';
01355     }
01356     // All open faces and segments have been dealt with. Split the node articulation point
01357     // Create star of node
01358     std::set<EntityKey> subgraph_entity_list;
01359     std::set<stkEdge, EdgeLessThan> subgraph_edge_list;
01360     Topology::createStar(*entity, subgraph_entity_list, subgraph_edge_list);
01361     // Iterators
01362     std::set<EntityKey>::iterator firstEntity = subgraph_entity_list.begin();
01363     std::set<EntityKey>::iterator lastEntity = subgraph_entity_list.end();
01364     std::set<stkEdge>::iterator firstEdge = subgraph_edge_list.begin();
01365     std::set<stkEdge>::iterator lastEdge = subgraph_edge_list.end();
01366     Subgraph subgraph(
01367         getSTKMeshStruct(),
01368         firstEntity, lastEntity, firstEdge, lastEdge);
01369 
01370     Vertex node = subgraph.globalToLocal(entity->key());
01371     std::cout << "Calling split_articulation_point with node: " << '\n';
01372     std::map<Entity*, Entity*> new_connectivity =
01373         subgraph.splitArticulationPoint(node, global_entity_open);
01374     std::cout << "done Calling split_articulation_point with node: " << '\n';
01375 
01376     // Update the connectivity
01377     for (std::map<Entity*, Entity*>::iterator j = new_connectivity.begin();
01378         j != new_connectivity.end(); ++j) {
01379       Entity* element = (*j).first;
01380       Entity* newNode = (*j).second;
01381 
01382       // Need to subtract 1 from element number as stk indexes from 1
01383       //   and connectivity_temp indexes from 0
01384       //        int id = static_cast<int>(element->identifier());
01385       int element_local_id = element_global_to_local_ids_[element->identifier()];
01386       //        EntityVector & element_connectivity = connectivity_temp_[id - 1];
01387       EntityVector & element_connectivity = connectivity_temp_[element_local_id];
01388       for (int k = 0; k < element_connectivity.size(); ++k) {
01389         if (element_connectivity[k] == entity) {
01390           element_connectivity[k] = newNode;
01391           // Duplicate the parameters of old node to new node
01392           getBulkData()->copy_entity_fields(*entity, *newNode);
01393         }
01394       }
01395     }
01396   }
01397 
01398   getBulkData()->modification_end();
01399 
01400 
01401 
01402 
01403   getBulkData()->modification_begin();
01404 
01405   // Create the cohesive connectivity
01406   int j = 1;
01407   for (std::set<EntityPair>::iterator i =
01408       fractured_faces_.begin(); i != fractured_faces_.end(); ++i, ++j) {
01409     Entity & face1 = *((*i).first);
01410     Entity & face2 = *((*i).second);
01411     EntityVector cohesive_connectivity;
01412     cohesive_connectivity =
01413         Topology::createSurfaceElementConnectivity(face1, face2);
01414 
01415     // Output connectivity for testing purposes
01416     std::cout << "Cohesive Element " << j << ": ";
01417     for (int j = 0; j < cohesive_connectivity.size(); ++j) {
01418       std::cout << cohesive_connectivity[j]->identifier() << ":";
01419     }
01420     std::cout << "\n";
01421   }
01422 
01423   getBulkData()->modification_end();
01424 
01425   return;
01426 }
01427 
01428 //
01429 //
01430 //
01431 void Topology::setEntitiesOpen()
01432 {
01433   EntityVector
01434   boundary_entities;
01435 
01436   stk::mesh::Selector
01437   select_owned = getMetaData()->locally_owned_part();
01438 
01439   stk::mesh::get_selected_entities(
01440       select_owned,
01441       getBulkData()->buckets(getBoundaryRank()) ,
01442       boundary_entities);
01443 
01444   // Iterate over the boundary entities
01445   for (size_t i = 0; i < boundary_entities.size(); ++i) {
01446 
01447     Entity &
01448     entity = *(boundary_entities[i]);
01449 
01450     if (checkOpen(entity) == false) continue;
01451 
01452     setFractureState(entity, OPEN);
01453 
01454     switch(getCellRank()) {
01455 
01456     default:
01457       std::cerr << "ERROR: " << __PRETTY_FUNCTION__;
01458       std::cerr << '\n';
01459       std::cerr << "Invalid cells rank in fracture: ";
01460       std::cerr << getCellRank();
01461       std::cerr << '\n';
01462       exit(1);
01463       break;
01464 
01465     case VOLUME_RANK:
01466       {
01467         PairIterRelation segments = entity.relations(EDGE_RANK);
01468         for (size_t j = 0; j < segments.size(); ++j) {
01469           Entity & segment = *(segments[j].entity());
01470           setFractureState(segment, OPEN);
01471           PairIterRelation points = segment.relations(NODE_RANK);
01472           for (size_t k = 0; k < points.size(); ++k) {
01473             Entity & point = *(points[k].entity());
01474             setFractureState(point, OPEN);
01475           }
01476         }
01477       }
01478       break;
01479 
01480     case EDGE_RANK:
01481       {
01482         PairIterRelation points = entity.relations(NODE_RANK);
01483         for (size_t j = 0; j < points.size(); ++j) {
01484           Entity & point = *(points[j].entity());
01485           setFractureState(point, OPEN);
01486         }
01487       }
01488       break;
01489     }
01490 
01491   }
01492 
01493   return;
01494 }
01495 
01505 void Topology::setEntitiesOpen(std::map<EntityKey, bool>& entity_open)
01506 {
01507   // Fracture occurs at the boundary of the elements in the mesh.
01508   //   The rank of the boundary elements is one less than the
01509   //   dimension of the system.
01510   EntityVector boundary_list;
01511   //    stk::mesh::Selector select_owned_or_shared = getMetaData()->locally_owned_part() | getMetaData()->globally_shared_part();
01512   stk::mesh::Selector select_owned = getMetaData()->locally_owned_part();
01513 
01514   //    stk::mesh::get_selected_entities( select_owned_or_shared ,
01515   stk::mesh::get_selected_entities( select_owned,
01516       getBulkData()->buckets(getSpaceDimension() - 1 ) ,
01517       boundary_list );
01518 
01519   // Iterate over the boundary entities
01520   for (int i = 0; i < boundary_list.size(); ++i) {
01521     Entity& entity = *(boundary_list[i]);
01522     bool is_open = fracture_criterion_->check(entity);
01523     // If the criterion is met, need to set lower rank entities
01524     //   open as well
01525     if (is_open == true && getSpaceDimension() == 3) {
01526       entity_open[entity.key()] = true;
01527       PairIterRelation segments = entity.relations(
01528           entity.entity_rank() - 1);
01529       // iterate over the segments
01530       for (int j = 0; j < segments.size(); ++j) {
01531         Entity & segment = *(segments[j].entity());
01532         entity_open[segment.key()] = true;
01533         PairIterRelation nodes = segment.relations(
01534             segment.entity_rank() - 1);
01535         // iterate over nodes
01536         for (int k = 0; k < nodes.size(); ++k) {
01537           Entity& node = *(nodes[k].entity());
01538           entity_open[node.key()] = true;
01539         }
01540       }
01541     }
01542     // If the mesh is 2D
01543     else if (is_open == true && getSpaceDimension() == 2) {
01544       entity_open[entity.key()] = true;
01545       PairIterRelation nodes = entity.relations(
01546           entity.entity_rank() - 1);
01547       // iterate over nodes
01548       for (int j = 0; j < nodes.size(); ++j) {
01549         Entity & node = *(nodes[j].entity());
01550         entity_open[node.key()] = true;
01551       }
01552     }
01553   }
01554 
01555   return;
01556 
01557 }
01558 
01569 void Topology::setEntitiesOpen(const EntityVector& fractured_edges,
01570     std::map<EntityKey, bool>& entity_open)
01571 {
01572 
01573   entity_open.clear();
01574 
01575   // Iterate over the boundary entities
01576   for (int i = 0; i < fractured_edges.size(); ++i) {
01577     Entity& entity = *(fractured_edges[i]);
01578     // Need to set lower rank entities
01579     //   open as well
01580     if (getSpaceDimension() == 3) {
01581       entity_open[entity.key()] = true;
01582       PairIterRelation segments = entity.relations(
01583           entity.entity_rank() - 1);
01584       // iterate over the segments
01585       for (int j = 0; j < segments.size(); ++j) {
01586         Entity & segment = *(segments[j].entity());
01587         entity_open[segment.key()] = true;
01588         PairIterRelation nodes = segment.relations(
01589             segment.entity_rank() - 1);
01590         // iterate over nodes
01591         for (int k = 0; k < nodes.size(); ++k) {
01592           Entity& node = *(nodes[k].entity());
01593           entity_open[node.key()] = true;
01594         }
01595       }
01596     }
01597     // If the mesh is 2D
01598     else if (getSpaceDimension() == 2) {
01599       entity_open[entity.key()] = true;
01600       PairIterRelation nodes = entity.relations(
01601           entity.entity_rank() - 1);
01602       // iterate over nodes
01603       for (int j = 0; j < nodes.size(); ++j) {
01604         Entity & node = *(nodes[j].entity());
01605         entity_open[node.key()] = true;
01606       }
01607     }
01608   }
01609 
01610   return;
01611 
01612 }
01613 
01614 namespace {
01615 
01616 //
01617 // Auxiliary for graphviz output
01618 //
01619 std::string
01620 entity_label(EntityRank const rank)
01621 {
01622   std::ostringstream
01623   oss;
01624 
01625   switch (rank) {
01626   default:
01627     oss << rank << "-Polytope";
01628     break;
01629   case NODE_RANK:
01630     oss << "Point";
01631     break;
01632   case EDGE_RANK:
01633     oss << "Segment";
01634     break;
01635   case FACE_RANK:
01636     oss << "Polygon";
01637     break;
01638   case VOLUME_RANK:
01639     oss << "Polyhedron";
01640     break;
01641   case 4:
01642     oss << "Polychoron";
01643     break;
01644   case 5:
01645     oss << "Polyteron";
01646     break;
01647   case 6:
01648     oss << "Polypeton";
01649     break;
01650   }
01651 
01652   return oss.str();
01653 }
01654 
01655 //
01656 // Auxiliary for graphviz output
01657 //
01658 std::string
01659 entity_color(EntityRank const rank, FractureState const fracture_state)
01660 {
01661   std::ostringstream
01662   oss;
01663 
01664   switch (fracture_state) {
01665 
01666   default:
01667     std::cerr << "ERROR: " << __PRETTY_FUNCTION__;
01668     std::cerr << '\n';
01669     std::cerr << "Fracture state is invalid: " << fracture_state;
01670     std::cerr << '\n';
01671     exit(1);
01672     break;
01673 
01674   case CLOSED:
01675     switch (rank) {
01676     default:
01677       oss << 2 * (rank + 1);
01678       break;
01679     case NODE_RANK:
01680       oss << "6";
01681       break;
01682     case EDGE_RANK:
01683       oss << "4";
01684       break;
01685     case FACE_RANK:
01686       oss << "2";
01687       break;
01688     case VOLUME_RANK:
01689       oss << "8";
01690       break;
01691     case 4:
01692       oss << "10";
01693       break;
01694     case 5:
01695       oss << "12";
01696       break;
01697     case 6:
01698       oss << "14";
01699       break;
01700     }
01701     break;
01702 
01703   case OPEN:
01704     switch (rank) {
01705     default:
01706       oss << 2 * rank + 1;
01707       break;
01708     case NODE_RANK:
01709       oss << "5";
01710       break;
01711     case EDGE_RANK:
01712       oss << "3";
01713       break;
01714     case FACE_RANK:
01715       oss << "1";
01716       break;
01717     case VOLUME_RANK:
01718       oss << "7";
01719       break;
01720     case 4:
01721       oss << "9";
01722       break;
01723     case 5:
01724       oss << "11";
01725       break;
01726     case 6:
01727       oss << "13";
01728       break;
01729     }
01730     break;
01731   }
01732 
01733   return oss.str();
01734 }
01735 
01736 //
01737 // Auxiliary for graphviz output
01738 //
01739 std::string
01740 dot_header()
01741 {
01742   std::string
01743   header = "digraph mesh {\n";
01744 
01745   header += "  node [colorscheme=paired12]\n";
01746   header += "  edge [colorscheme=paired12]\n";
01747 
01748   return header;
01749 }
01750 
01751 //
01752 // Auxiliary for graphviz output
01753 //
01754 std::string
01755 dot_footer()
01756 {
01757   return "}";
01758 }
01759 
01760 //
01761 // Auxiliary for graphviz output
01762 //
01763 std::string
01764 dot_entity(
01765     EntityId const id,
01766     EntityRank const rank,
01767     FractureState const fracture_state)
01768 {
01769   std::ostringstream
01770   oss;
01771 
01772   oss << "  \"";
01773   oss << id;
01774   oss << "_";
01775   oss << rank;
01776   oss << "\"";
01777   oss << " [label=\"";
01778   //oss << entity_label(rank);
01779   //oss << " ";
01780   oss << id;
01781   oss << "\",style=filled,fillcolor=\"";
01782   oss << entity_color(rank, fracture_state);
01783   oss << "\"]\n";
01784 
01785   return oss.str();
01786 }
01787 
01788 //
01789 // Auxiliary for graphviz output
01790 //
01791 std::string
01792 relation_color(unsigned int const relation_id)
01793 {
01794   std::ostringstream
01795   oss;
01796 
01797   switch (relation_id) {
01798   default:
01799     oss << 2 * (relation_id + 1);
01800     break;
01801   case 0:
01802     oss << "6";
01803     break;
01804   case 1:
01805     oss << "4";
01806     break;
01807   case 2:
01808     oss << "2";
01809     break;
01810   case 3:
01811     oss << "8";
01812     break;
01813   case 4:
01814     oss << "10";
01815     break;
01816   case 5:
01817     oss << "12";
01818     break;
01819   }
01820 
01821   return oss.str();
01822 }
01823 
01824 //
01825 // Auxiliary for graphviz output
01826 //
01827 std::string
01828 dot_relation(
01829     EntityId const source_id,
01830     EntityRank const source_rank,
01831     EntityId const target_id,
01832     EntityRank const target_rank,
01833     unsigned int const relation_local_id)
01834 {
01835   std::ostringstream
01836   oss;
01837 
01838   oss << "  \"";
01839   oss << source_id;
01840   oss << "_";
01841   oss << source_rank;
01842   oss << "\" -> \"";
01843   oss << target_id;
01844   oss << "_";
01845   oss << target_rank;
01846   oss << "\" [color=\"";
01847   oss << relation_color(relation_local_id);
01848   oss << "\"]\n";
01849 
01850   return oss.str();
01851 }
01852 
01853 } //anonymous namspace
01854 
01855 //
01856 // Output the graph associated with the mesh to graphviz .dot
01857 // file for visualization purposes. No need for entity_open map
01858 // for this version
01859 //
01860 void
01861 Topology::outputToGraphviz(
01862     std::string const & output_filename,
01863     OutputType const output_type)
01864 {
01865   // Open output file
01866   std::ofstream gviz_out;
01867   gviz_out.open(output_filename.c_str(), std::ios::out);
01868 
01869   if (gviz_out.is_open() == false) {
01870     std::cout << "Unable to open graphviz output file :";
01871     std::cout << output_filename << '\n';
01872     return;
01873   }
01874 
01875   std::cout << "Write graph to graphviz dot file" << '\n';
01876 
01877   // Write beginning of file
01878   gviz_out << dot_header();
01879 
01880   typedef std::vector<EntityPair> RelationList;
01881 
01882   RelationList
01883   relation_list;
01884 
01885   std::vector<EdgeId>
01886   relation_local_id;
01887 
01888   // Entities (graph vertices)
01889   for (EntityRank rank = NODE_RANK; rank <= getCellRank(); ++rank) {
01890 
01891     EntityVector
01892     entities;
01893 
01894     stk::mesh::get_entities(*(getBulkData()), rank, entities);
01895 
01896     for (EntityVector::size_type i = 0; i < entities.size(); ++i) {
01897 
01898       Entity &
01899       source_entity = *(entities[i]);
01900 
01901       FractureState const
01902       fracture_state = getFractureState(source_entity);
01903 
01904       PairIterRelation
01905       relations = relations_all(source_entity);
01906 
01907       gviz_out << dot_entity(source_entity.identifier(), rank, fracture_state);
01908 
01909       for (size_t j = 0; j < relations.size(); ++j) {
01910 
01911         Relation const &
01912         relation = relations[j];
01913 
01914         Entity &
01915         target_entity = *(relation.entity());
01916 
01917         EntityRank const
01918         target_rank = target_entity.entity_rank();
01919 
01920         bool
01921         is_valid_target_rank = false;
01922 
01923         switch (output_type) {
01924 
01925         default:
01926           std::cerr << "ERROR: " << __PRETTY_FUNCTION__;
01927           std::cerr << '\n';
01928           std::cerr << "Invalid output type: ";
01929           std::cerr << output_type;
01930           std::cerr << '\n';
01931           exit(1);
01932           break;
01933 
01934         case UNIDIRECTIONAL_UNILEVEL:
01935           is_valid_target_rank = target_rank + 1 == rank;
01936           break;
01937 
01938         case UNDIRECTIONAL_MULTILEVEL:
01939           is_valid_target_rank = target_rank < rank;
01940           break;
01941 
01942         case BIDIRECTIONAL_UNILEVEL:
01943           is_valid_target_rank =
01944               (target_rank == rank + 1) || (target_rank + 1 == rank);
01945           break;
01946 
01947         case BIDIRECTIONAL_MULTILEVEL:
01948           is_valid_target_rank = target_rank != rank;
01949           break;
01950 
01951         }
01952 
01953         if (is_valid_target_rank == false) continue;
01954 
01955         EntityPair
01956         entity_pair = std::make_pair(&source_entity, &target_entity);
01957 
01958         EdgeId const
01959         edge_id = relation.identifier();
01960 
01961         relation_list.push_back(entity_pair);
01962         relation_local_id.push_back(edge_id);
01963       }
01964 
01965     }
01966 
01967   }
01968 
01969   // Relations (graph edges)
01970   for (RelationList::size_type i = 0; i < relation_list.size(); ++i) {
01971 
01972     EntityPair
01973     entity_pair = relation_list[i];
01974 
01975     Entity &
01976     source = *(entity_pair.first);
01977 
01978     Entity &
01979     target = *(entity_pair.second);
01980 
01981     gviz_out << dot_relation(
01982         source.identifier(), source.entity_rank(),
01983         target.identifier(), target.entity_rank(),
01984         relation_local_id[i]);
01985 
01986   }
01987 
01988   // File end
01989   gviz_out << dot_footer();
01990 
01991   gviz_out.close();
01992 
01993   return;
01994 }
01995 
01996 } // namespace LCM
01997 

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