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

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

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