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

AAdapt_TopologyModification.cpp

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 
00007 #include <Teuchos_TimeMonitor.hpp>
00008 
00009 #include <stk_util/parallel/ParallelReduce.hpp>
00010 
00011 #include "AAdapt_TopologyModification.hpp"
00012 #include "AAdapt_StressFracture.hpp"
00013 
00014 namespace AAdapt {
00015 
00016 typedef stk::mesh::Entity Entity;
00017 typedef stk::mesh::EntityRank EntityRank;
00018 typedef stk::mesh::RelationIdentifier EdgeId;
00019 typedef stk::mesh::EntityKey EntityKey;
00020 
00021 //----------------------------------------------------------------------------
00022 AAdapt::TopologyMod::
00023 TopologyMod(const Teuchos::RCP<Teuchos::ParameterList>& params,
00024             const Teuchos::RCP<ParamLib>& param_lib,
00025             Albany::StateManager& state_mgr,
00026             const Teuchos::RCP<const Epetra_Comm>& comm) :
00027   AAdapt::AbstractAdapter(params, param_lib, state_mgr, comm),
00028   remesh_file_index_(1) {
00029 
00030   discretization_ = state_mgr_.getDiscretization();
00031 
00032   stk_discretization_ =
00033     static_cast<Albany::STKDiscretization*>(discretization_.get());
00034 
00035   stk_mesh_struct_ = stk_discretization_->getSTKMeshStruct();
00036 
00037   bulk_data_ = stk_mesh_struct_->bulkData;
00038   meta_data_ = stk_mesh_struct_->metaData;
00039 
00040   // The entity ranks
00041   node_rank_ = meta_data_->NODE_RANK;
00042   edge_rank_ = meta_data_->EDGE_RANK;
00043   face_rank_ = meta_data_->FACE_RANK;
00044   element_rank_ = meta_data_->element_rank();
00045 
00046   num_dim_ = stk_mesh_struct_->numDim;
00047 
00048   // Save the initial output file name
00049   base_exo_filename_ = stk_mesh_struct_->exoOutFile;
00050 
00051   double critical_stress_ = params->get<double>("Fracture Stress");
00052 
00053   fracture_criterion_ =
00054     Teuchos::rcp(new AAdapt::StressFracture(num_dim_,
00055                                          element_rank_,
00056                                          avg_stresses_,
00057                                          critical_stress_,
00058                                          *stk_discretization_));
00059 
00060   // Modified by GAH from LCM::NodeUpdate.cc
00061   topology_ =
00062     Teuchos::rcp(new LCM::Topology(discretization_, fracture_criterion_));
00063 }
00064 
00065 //----------------------------------------------------------------------------
00066 AAdapt::TopologyMod::
00067 ~TopologyMod() {
00068 }
00069 
00070 //----------------------------------------------------------------------------
00071 bool
00072 AAdapt::TopologyMod::queryAdaptationCriteria() {
00073   // FIXME Dumb criteria
00074 
00075   if(iter == 5 || iter == 10 || iter == 15) { // fracture at iter = 5, 10, 15
00076 
00077     // First, check and see if the mesh fracture criteria is met
00078     // anywhere before messing with things.
00079 
00080     // Get a vector containing the edge set of the mesh where
00081     // fractures can occur
00082 
00083     std::vector<stk::mesh::Entity*> face_list;
00084     stk::mesh::Selector select_owned = meta_data_->locally_owned_part();
00085     stk::mesh::get_selected_entities(select_owned,
00086                                      bulk_data_->buckets(num_dim_ - 1),
00087                                      face_list);
00088 
00089     //    *out << "Num faces : " << face_list.size() << std::endl;
00090     std::cout << "Num faces : " << face_list.size() << std::endl;
00091 
00092     // Probability that fracture_criterion will return true.
00093     double p = iter;
00094     int total_fractured;
00095 
00096     // Iterate over the boundary entities
00097     for(int i = 0; i < face_list.size(); ++i) {
00098 
00099       stk::mesh::Entity& face = *(face_list[i]);
00100 
00101       if(fracture_criterion_->computeFractureCriterion(face, p))
00102 
00103         fractured_faces_.push_back(face_list[i]);
00104 
00105     }
00106 
00107     //    if(fractured_edges.size() == 0) return false; // nothing to do
00108     if((total_fractured = accumulateFractured(fractured_faces_.size())) == 0) {
00109 
00110       fractured_faces_.clear();
00111 
00112       return false; // nothing to do
00113     }
00114 
00115     *output_stream_ << "TopologyModification: Need to split \""
00116                     << total_fractured << "\" mesh elements." << std::endl;
00117 
00118 
00119     return true;
00120   }
00121 
00122   return false;
00123 }
00124 
00125 //----------------------------------------------------------------------------
00126 bool
00127 AAdapt::TopologyMod::adaptMesh(const Epetra_Vector& solution, const Epetra_Vector& ovlp_solution) {
00128 
00129   *output_stream_
00130       << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"
00131       << "Adapting mesh using AAdapt::TopologyMod method      \n"
00132       << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n";
00133 
00134   // Save the current results and close the exodus file
00135 
00136   // Create a remeshed output file naming convention by adding the remesh_file_index_ ahead of the period
00137   std::ostringstream ss;
00138   std::string str = base_exo_filename_;
00139   ss << "_" << remesh_file_index_ << ".";
00140   str.replace(str.find('.'), 1, ss.str());
00141 
00142   *output_stream_ << "Remeshing: renaming output file to - " << str << std::endl;
00143 
00144   // Open the new exodus file for results
00145   stk_discretization_->reNameExodusOutput(str);
00146 
00147   remesh_file_index_++;
00148 
00149   // Print element connectivity before the mesh topology is modified
00150 
00151   //  *output_stream_
00152   //   << "*************************\n"
00153   //   << "Before element separation\n"
00154   //   << "*************************\n";
00155 
00156   // Start the mesh update process
00157 
00158   // Modifies mesh for graph algorithm
00159   // Function must be called each time before there are changes to the mesh
00160 
00161   topology_->removeElementToNodeConnectivity(old_elem_to_node_);
00162 
00163   // Check for failure criterion
00164   std::map<EntityKey, bool> local_entity_open;
00165   std::map<EntityKey, bool> global_entity_open;
00166   topology_->setEntitiesOpen(fractured_faces_, local_entity_open);
00167 
00168   getGlobalOpenList(local_entity_open, global_entity_open);
00169 
00170   // begin mesh update
00171 
00172   topology_->splitOpenFaces(global_entity_open);
00173 
00174   // Clear the list of fractured edges in preparation for the next
00175   // fracture event
00176   fractured_faces_.clear();
00177 
00178   topology_->restoreElementToNodeConnectivity(new_elem_to_node_);
00179   // Throw away all the Albany data structures and re-build them from the mesh
00180 
00181   stk_discretization_->updateMesh();
00182 
00183   return true;
00184 }
00185 
00186 //----------------------------------------------------------------------------
00187 // Transfer solution between meshes.  This is a no-op as the
00188 // solution is copied to the newly created nodes by the
00189 // topology->fracture_boundary() function.
00190 void
00191 AAdapt::TopologyMod::
00192 solutionTransfer(const Epetra_Vector& oldSolution,
00193                  Epetra_Vector& newSolution) {}
00194 
00195 //----------------------------------------------------------------------------
00196 Teuchos::RCP<const Teuchos::ParameterList>
00197 AAdapt::TopologyMod::getValidAdapterParameters() const {
00198   Teuchos::RCP<Teuchos::ParameterList> valid_pl_ =
00199     this->getGenericAdapterParams("ValidTopologyModificationParams");
00200 
00201   valid_pl_->
00202   set<double>("Fracture Stress",
00203               1.0,
00204               "Fracture stress value at which two elements separate");
00205 
00206   return valid_pl_;
00207 }
00208 
00209 
00210 //----------------------------------------------------------------------------
00211 void
00212 AAdapt::TopologyMod::showRelations() {
00213   std::vector<Entity*> element_list;
00214   stk::mesh::get_entities(*(bulk_data_), element_rank_, element_list);
00215 
00216   // Remove extra relations from element
00217   for(int i = 0; i < element_list.size(); ++i) {
00218     Entity& element = *(element_list[i]);
00219     stk::mesh::PairIterRelation relations = element.relations();
00220     std::cout << "Element " << element_list[i]->identifier()
00221               << " relations are :" << std::endl;
00222 
00223     for(int j = 0; j < relations.size(); ++j) {
00224       std::cout << "entity:\t" << relations[j].entity()->identifier() << ","
00225                 << relations[j].entity()->entity_rank() << "\tlocal id: "
00226                 << relations[j].identifier() << "\n";
00227     }
00228   }
00229 }
00230 
00231 #ifdef ALBANY_MPI
00232 //----------------------------------------------------------------------------
00233 int
00234 AAdapt::TopologyMod::accumulateFractured(int num_fractured) {
00235   int total_fractured;
00236 
00237   stk::all_reduce_sum(bulk_data_->parallel(), &num_fractured, &total_fractured, 1);
00238 
00239   return total_fractured;
00240 }
00241 
00242 //----------------------------------------------------------------------------
00243 // Parallel all-gatherv function. Communicates local open list to
00244 // all processors to form global open list.
00245 void
00246 AAdapt::TopologyMod::
00247 getGlobalOpenList(std::map<EntityKey, bool>& local_entity_open,
00248                   std::map<EntityKey, bool>& global_entity_open) {
00249 
00250   // Make certain that we can send keys as MPI_UINT64_T types
00251   assert(sizeof(EntityKey::raw_key_type) >= sizeof(uint64_t));
00252 
00253   const unsigned parallel_size = bulk_data_->parallel_size();
00254 
00255   // Build local vector of keys
00256   std::pair<EntityKey, bool> me; // what a map<EntityKey, bool> is made of
00257   std::vector<EntityKey::raw_key_type> v;     // local vector of open keys
00258 
00259   BOOST_FOREACH(me, local_entity_open) {
00260     v.push_back(me.first.raw_key());
00261 
00262     // Debugging
00263     /*
00264       const unsigned entity_rank = stk::mesh::entity_rank( me.first);
00265       const stk::mesh::EntityId entity_id = stk::mesh::entity_id( me.first );
00266       const std::string & entity_rank_name = metaData->entity_rank_name( entity_rank );
00267       Entity *entity = bulk_data_->get_entity(me.first);
00268       std::cout<<"Single proc fracture list contains "<<" "<<entity_rank_name<<" ["<<entity_id<<"] Proc:"
00269       <<entity->owner_rank() <<std::endl;
00270     */
00271 
00272   }
00273 
00274   int num_open_on_pe = v.size();
00275 
00276   // Perform the allgatherv
00277 
00278   // gather the number of open entities on each processor
00279   int* sizes = new int[parallel_size];
00280   MPI_Allgather(&num_open_on_pe, 1, MPI_INT, sizes, 1, MPI_INT, bulk_data_->parallel());
00281 
00282   // Loop over each processor and calculate the array offset of its entities in the receive array
00283   int* offsets = new int[parallel_size];
00284   int count = 0;
00285 
00286   for(int i = 0; i < parallel_size; i++) {
00287     offsets[i] = count;
00288     count += sizes[i];
00289   }
00290 
00291   int total_number_of_open_entities = count;
00292 
00293   EntityKey::raw_key_type* result_array = new EntityKey::raw_key_type[total_number_of_open_entities];
00294   MPI_Allgatherv(&v[0], num_open_on_pe, MPI_UINT64_T, result_array,
00295                  sizes, offsets, MPI_UINT64_T, bulk_data_->parallel());
00296 
00297   // Save the global keys
00298   for(int i = 0; i < total_number_of_open_entities; i++) {
00299 
00300     EntityKey key = EntityKey(&result_array[i]);
00301     global_entity_open[key] = true;
00302 
00303     // Debugging
00304     /*
00305       const unsigned entity_rank = stk::mesh::entity_rank( key);
00306       const stk::mesh::EntityId entity_id = stk::mesh::entity_id( key );
00307       const std::string & entity_rank_name = metaData->entity_rank_name( entity_rank );
00308       Entity *entity = bulk_data_->get_entity(key);
00309       if(!entity) { std::cout << "Error on this processor: Entity not addressible!!!!!!!!!!!!!" << std::endl;
00310 
00311       std::cout<<"Global proc fracture list contains "<<" "<<entity_rank_name<<" ["<<entity_id<<"]" << std::endl;
00312     std::vector<Entity*> element_lst;
00313     stk::mesh::get_entities(*(bulk_data_),elementRank,element_lst);
00314     for (int i = 0; i < element_lst.size(); ++i){
00315       std::cout << element_lst[i]->identifier() << std::endl;
00316       }
00317     std::vector<Entity*> entity_lst;
00318     stk::mesh::get_entities(*(bulk_data_),entity_rank,entity_lst);
00319     for (int i = 0; i < entity_lst.size(); ++i){
00320       std::cout << entity_lst[i]->identifier() << std::endl;
00321       }
00322       }
00323       else {
00324       std::cout<<"Global proc fracture list contains "<<" "<<entity_rank_name<<" ["<<entity_id<<"] Proc:"
00325       <<entity->owner_rank() <<std::endl;
00326       }
00327     */
00328   }
00329 
00330   delete [] sizes;
00331   delete [] offsets;
00332   delete [] result_array;
00333 }
00334 
00335 #else
00336 //----------------------------------------------------------------------------
00337 int
00338 AAdapt::TopologyMod::accumulateFractured(int num_fractured) {
00339   return num_fractured;
00340 }
00341 
00342 //----------------------------------------------------------------------------
00343 // Parallel all-gatherv function. Communicates local open list to
00344 // all processors to form global open list.
00345 void
00346 AAdapt::TopologyMod::getGlobalOpenList(std::map<EntityKey, bool>& local_entity_open,
00347                                        std::map<EntityKey, bool>& global_entity_open) {
00348 
00349   global_entity_open = local_entity_open;
00350 }
00351 #endif
00352 
00353 }
00354 

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