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

Albany_IossSTKMeshStruct.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 #ifdef ALBANY_SEACAS
00007 
00008 #include <iostream>
00009 
00010 #include "Albany_IossSTKMeshStruct.hpp"
00011 #include "Teuchos_VerboseObject.hpp"
00012 
00013 #include <Shards_BasicTopologies.hpp>
00014 
00015 #include <stk_mesh/base/Entity.hpp>
00016 #include <stk_mesh/base/GetEntities.hpp>
00017 #include <stk_mesh/base/GetBuckets.hpp>
00018 #include <stk_mesh/base/FieldData.hpp>
00019 #include <stk_mesh/base/Selector.hpp>
00020 #include <stk_io/IossBridge.hpp>
00021 #include <Ioss_SubSystem.h>
00022 
00023 //#include <stk_mesh/fem/FEMHelpers.hpp>
00024 #include <boost/algorithm/string/predicate.hpp>
00025 
00026 #include "Albany_Utils.hpp"
00027 
00028 Albany::IossSTKMeshStruct::IossSTKMeshStruct(
00029                                              const Teuchos::RCP<Teuchos::ParameterList>& params, 
00030                                              const Teuchos::RCP<Teuchos::ParameterList>& adaptParams_, 
00031                                              const Teuchos::RCP<const Epetra_Comm>& comm) :
00032   GenericSTKMeshStruct(params, adaptParams_),
00033   out(Teuchos::VerboseObjectBase::getDefaultOStream()),
00034   useSerialMesh(false),
00035   periodic(params->get("Periodic BC", false)),
00036   m_hasRestartSolution(false),
00037   m_restartDataTime(-1.0),
00038   m_solutionFieldHistoryDepth(0)
00039 {
00040   params->validateParameters(*getValidDiscretizationParameters(),0);
00041 
00042   mesh_data = new stk::io::MeshData();
00043 
00044   usePamgen = (params->get("Method","Exodus") == "Pamgen");
00045 
00046   std::vector<std::string> entity_rank_names;
00047 
00048   // eMesh needs "FAMILY_TREE" entity
00049   if(buildEMesh)
00050     entity_rank_names.push_back("FAMILY_TREE");
00051 
00052 #ifdef ALBANY_ZOLTAN  // rebalance requires Zoltan
00053 
00054   if (params->get<bool>("Use Serial Mesh", false) && comm->NumProc() > 1){ 
00055     // We are parallel but reading a single exodus file
00056 
00057     useSerialMesh = true;
00058 
00059     readSerialMesh(comm, entity_rank_names);
00060 
00061   }
00062   else 
00063 #endif
00064     if (!usePamgen) {
00065       *out << "Albany_IOSS: Loading STKMesh from Exodus file  " 
00066            << params->get<std::string>("Exodus Input File Name") << std::endl;
00067 
00068       stk::io::create_input_mesh("exodusII",
00069 //      create_input_mesh("exodusII",
00070                                  params->get<std::string>("Exodus Input File Name"),
00071                                  Albany::getMpiCommFromEpetraComm(*comm), 
00072                                  *metaData, *mesh_data,
00073                                  entity_rank_names); 
00074     }
00075     else {
00076       *out << "Albany_IOSS: Loading STKMesh from Pamgen file  " 
00077            << params->get<std::string>("Pamgen Input File Name") << std::endl;
00078 
00079       stk::io::create_input_mesh("pamgen",
00080 //      create_input_mesh("pamgen",
00081                                  params->get<std::string>("Pamgen Input File Name"),
00082                                  Albany::getMpiCommFromEpetraComm(*comm), 
00083                                  *metaData, *mesh_data,
00084                                  entity_rank_names); 
00085 
00086     }
00087 
00088   typedef Teuchos::Array<std::string> StringArray;
00089   const StringArray additionalNodeSets = params->get("Additional Node Sets", StringArray());
00090   for (StringArray::const_iterator it = additionalNodeSets.begin(), it_end = additionalNodeSets.end(); it != it_end; ++it) {
00091     stk::mesh::Part &newNodeSet = metaData->declare_part(*it, metaData->node_rank());
00092     if (!stk::io::is_part_io_part(newNodeSet)) {
00093       stk::mesh::Field<double> * const distrFactorfield = metaData->get_field<stk::mesh::Field<double> >("distribution_factors");
00094       stk::mesh::put_field(*distrFactorfield, metaData->node_rank(), newNodeSet);
00095       stk::io::put_io_part_attribute(newNodeSet);
00096     }
00097   }
00098 
00099   numDim = metaData->spatial_dimension();
00100 
00101   stk::io::put_io_part_attribute(metaData->universal_part());
00102 
00103   // Set element blocks, side sets and node sets
00104   const stk::mesh::PartVector & all_parts = metaData->get_parts();
00105   std::vector<std::string> ssNames;
00106   std::vector<std::string> nsNames;
00107   int numEB = 0;
00108 
00109   for (stk::mesh::PartVector::const_iterator i = all_parts.begin();
00110        i != all_parts.end(); ++i) {
00111 
00112     stk::mesh::Part * const part = *i ;
00113 
00114     if ( part->primary_entity_rank() == metaData->element_rank()) {
00115       if (part->name()[0] != '{') {
00116         //*out << "IOSS-STK: Element part \"" << part->name() << "\" found " << std::endl;
00117         partVec[numEB] = part;
00118         numEB++;
00119       }
00120     }
00121     else if ( part->primary_entity_rank() == metaData->node_rank()) {
00122       if (part->name()[0] != '{') {
00123         //*out << "Mesh has Node Set ID: " << part->name() << std::endl;
00124         nsPartVec[part->name()]=part;
00125         nsNames.push_back(part->name());
00126       }
00127     }
00128     else if ( part->primary_entity_rank() == metaData->side_rank()) {
00129       if (part->name()[0] != '{') {
00130 //        print(*out, "Found side_rank entity:\n", *part);
00131         ssPartVec[part->name()]=part;
00132       }
00133     }
00134   }
00135 
00136   cullSubsetParts(ssNames, ssPartVec); // Eliminate sidesets that are subsets of other sidesets
00137 
00138 #if 0
00139   // for debugging, print out the parts now
00140   std::map<std::string, stk::mesh::Part*>::iterator it;
00141 
00142   for(it = ssPartVec.begin(); it != ssPartVec.end(); ++it){ // loop over the parts in the map
00143 
00144     // for each part in turn, get the name of parts that are a subset of it
00145 
00146     print(*out, "Found \n", *it->second);
00147   }
00148   // end debugging
00149 #endif
00150 
00151   const int cub      = params->get("Cubature Degree",3);
00152   const int default_cub_rule = static_cast<int>(Intrepid::PL_GAUSS);
00153   const Intrepid::EIntrepidPLPoly cub_rule = static_cast<Intrepid::EIntrepidPLPoly>(params->get("Cubature Rule",default_cub_rule));
00154   int worksetSizeMax = params->get("Workset Size",50);
00155 
00156   // Get number of elements per element block using Ioss for use
00157   // in calculating an upper bound on the worksetSize.
00158   std::vector<int> el_blocks;
00159   stk::io::get_element_block_sizes(*mesh_data, el_blocks);
00160   TEUCHOS_TEST_FOR_EXCEPT(el_blocks.size() != partVec.size());
00161 
00162   int ebSizeMax =  *std::max_element(el_blocks.begin(), el_blocks.end());
00163   int worksetSize = this->computeWorksetSize(worksetSizeMax, ebSizeMax);
00164 
00165   // Build a map to get the EB name given the index
00166 
00167   for (int eb=0; eb<numEB; eb++) 
00168 
00169     this->ebNameToIndex[partVec[eb]->name()] = eb;
00170 
00171   // Construct MeshSpecsStruct
00172   if (!params->get("Separate Evaluators by Element Block",false)) {
00173 
00174     const CellTopologyData& ctd = *metaData->get_cell_topology(*partVec[0]).getCellTopologyData();
00175     this->meshSpecs[0] = Teuchos::rcp(new Albany::MeshSpecsStruct(ctd, numDim, cub,
00176                                                                   nsNames, ssNames, worksetSize, partVec[0]->name(), 
00177                                                                   this->ebNameToIndex, this->interleavedOrdering,cub_rule));
00178 
00179   }
00180   else {
00181 
00182     *out << "MULTIPLE Elem Block in Ioss: DO worksetSize[eb] max?? " << std::endl; 
00183     this->allElementBlocksHaveSamePhysics=false;
00184     this->meshSpecs.resize(numEB);
00185     for (int eb=0; eb<numEB; eb++) {
00186       const CellTopologyData& ctd = *metaData->get_cell_topology(*partVec[eb]).getCellTopologyData();
00187       this->meshSpecs[eb] = Teuchos::rcp(new Albany::MeshSpecsStruct(ctd, numDim, cub,
00188                                                                      nsNames, ssNames, worksetSize, partVec[eb]->name(), 
00189                                                                      this->ebNameToIndex, this->interleavedOrdering,cub_rule));
00190       std::cout << "el_block_size[" << eb << "] = " << el_blocks[eb] << "   name  " << partVec[eb]->name() << std::endl; 
00191     }
00192 
00193   }
00194 
00195   {
00196     const Ioss::Region *inputRegion = mesh_data->m_input_region;
00197     m_solutionFieldHistoryDepth = inputRegion->get_property("state_count").get_int();
00198   }
00199 }
00200 
00201 Albany::IossSTKMeshStruct::~IossSTKMeshStruct()
00202 {
00203   delete mesh_data;
00204 }
00205 
00206 void
00207 Albany::IossSTKMeshStruct::readSerialMesh(const Teuchos::RCP<const Epetra_Comm>& comm,
00208                                           std::vector<std::string>& entity_rank_names){
00209 
00210 #ifdef ALBANY_ZOLTAN // rebalance needs Zoltan
00211 
00212   MPI_Group group_world;
00213   MPI_Group peZero;
00214   MPI_Comm peZeroComm;
00215 
00216   // Read a single exodus mesh on Proc 0 then rebalance it across the machine
00217 
00218   MPI_Comm theComm = Albany::getMpiCommFromEpetraComm(*comm);
00219 
00220   int process_rank[1]; // the reader process
00221 
00222   process_rank[0] = 0;
00223   int my_rank = comm->MyPID();
00224 
00225   //get the group under theComm
00226   MPI_Comm_group(theComm, &group_world);
00227   // create the new group. This group includes only processor zero - that is the only processor that reads the file
00228   MPI_Group_incl(group_world, 1, process_rank, &peZero);
00229   // create the new communicator - it just contains processor zero
00230   MPI_Comm_create(theComm, peZero, &peZeroComm);
00231 
00232   // Note that peZeroComm == MPI_COMM_NULL on all processors but processor 0
00233 
00234   if(my_rank == 0){
00235 
00236     *out << "Albany_IOSS: Loading serial STKMesh from Exodus file  " 
00237          << params->get<std::string>("Exodus Input File Name") << std::endl;
00238 
00239   }
00240 
00241   /* 
00242    * This checks the existence of the file, checks to see if we can open it, builds a handle to the region
00243    * and puts it in mesh_data (in_region), and reads the metaData into metaData.
00244    */
00245 
00246   stk::io::create_input_mesh("exodusII",
00247 //  create_input_mesh("exodusII",
00248                              params->get<std::string>("Exodus Input File Name"), 
00249                              peZeroComm, 
00250                              *metaData, *mesh_data,
00251                              entity_rank_names); 
00252 
00253   // Here, all PEs have read the metaData from the input file, and have a pointer to in_region in mesh_data
00254 
00255 #endif
00256 
00257 }
00258 
00259 void
00260 Albany::IossSTKMeshStruct::setFieldAndBulkData(
00261                                                const Teuchos::RCP<const Epetra_Comm>& comm,
00262                                                const Teuchos::RCP<Teuchos::ParameterList>& params,
00263                                                const unsigned int neq_,
00264                                                const AbstractFieldContainer::FieldContainerRequirements& req,
00265                                                const Teuchos::RCP<Albany::StateInfoStruct>& sis,
00266                                                const unsigned int worksetSize)
00267 {
00268   this->SetupFieldData(comm, neq_, req, sis, worksetSize);
00269 
00270   *out << "IOSS-STK: number of node sets = " << nsPartVec.size() << std::endl;
00271   *out << "IOSS-STK: number of side sets = " << ssPartVec.size() << std::endl;
00272 
00273   metaData->commit();
00274 
00275   // Restart index to read solution from exodus file.
00276   int index = params->get("Restart Index",-1); // Default to no restart
00277   double res_time = params->get<double>("Restart Time",-1.0); // Default to no restart
00278   Ioss::Region *region = mesh_data->m_input_region;
00279 
00280   /*
00281    * The following code block reads a single mesh on PE 0, then distributes the mesh across
00282    * the other processors. stk_rebalance is used, which requires Zoltan
00283    *
00284    * This code is only compiled if ALBANY_MPI and ALBANY_ZOLTAN are true
00285    */
00286 
00287 #ifdef ALBANY_ZOLTAN // rebalance needs Zoltan
00288 
00289   if(useSerialMesh){
00290 
00291     bulkData->modification_begin();
00292 
00293     if(comm->MyPID() == 0){ // read in the mesh on PE 0
00294 
00295       stk::io::process_mesh_bulk_data(region, *bulkData);
00296 
00297       // Read solution from exodus file.
00298       if (index >= 0) { // User has specified a time step to restart at
00299         *out << "Restart Index set, reading solution index : " << index << std::endl;
00300         stk::io::input_mesh_fields(region, *bulkData, index);
00301         m_restartDataTime = region->get_state_time(index);
00302         m_hasRestartSolution = true;
00303       }
00304       else if (res_time >= 0) { // User has specified a time to restart at
00305         *out << "Restart solution time set, reading solution time : " << res_time << std::endl;
00306         stk::io::input_mesh_fields(region, *bulkData, res_time);
00307         m_restartDataTime = res_time;
00308         m_hasRestartSolution = true;
00309       }
00310       else {
00311 
00312         *out << "Neither restart index or time are set. Not reading solution data from exodus file"<< std::endl;
00313 
00314       }
00315     }
00316 
00317     bulkData->modification_end();
00318 
00319   } // End UseSerialMesh - reading mesh on PE 0
00320 
00321   else 
00322 #endif
00323 
00324     /*
00325      * The following code block reads a single mesh when Albany is compiled serially, or a
00326      * Nemspread fileset if ALBANY_MPI is true.
00327      *
00328      */
00329 
00330   { // running in Serial or Parallel read from Nemspread files
00331 
00332     stk::io::populate_bulk_data(*bulkData, *mesh_data);
00333 
00334     if (!usePamgen)  {
00335 
00336       // Read solution from exodus file.
00337       if (index >= 0) { // User has specified a time step to restart at
00338         *out << "Restart Index set, reading solution index : " << index << std::endl;
00339         stk::io::process_input_request(*mesh_data, *bulkData, index);
00340         m_restartDataTime = region->get_state_time(index);
00341         m_hasRestartSolution = true;
00342       }
00343       else if (res_time >= 0) { // User has specified a time to restart at
00344         *out << "Restart solution time set, reading solution time : " << res_time << std::endl;
00345         stk::io::process_input_request(*mesh_data, *bulkData, res_time);
00346         m_restartDataTime = res_time;
00347         m_hasRestartSolution = true;
00348       }
00349       else {
00350         *out << "Restart Index not set. Not reading solution from exodus (" 
00351              << index << ")"<< std::endl;
00352 
00353       }
00354     }
00355 
00356     bulkData->modification_end();
00357 
00358   } // End Parallel Read - or running in serial
00359 
00360   if(m_hasRestartSolution){
00361 
00362     Teuchos::Array<std::string> default_field;
00363     default_field.push_back("solution");
00364     Teuchos::Array<std::string> restart_fields =
00365       params->get<Teuchos::Array<std::string> >("Restart Fields", default_field);
00366 
00367     // Get the fields to be used for restart
00368 
00369     // See what state data was initialized from the stk::io request
00370     // This should be propagated into stk::io
00371     const Ioss::ElementBlockContainer& elem_blocks = region->get_element_blocks();
00372 
00373     /*
00374     // Uncomment to print what fields are in the exodus file
00375     Ioss::NameList exo_fld_names;
00376     elem_blocks[0]->field_describe(&exo_fld_names);
00377     for(std::size_t i = 0; i < exo_fld_names.size(); i++){
00378     *out << "Found field \"" << exo_fld_names[i] << "\" in exodus file" << std::endl;
00379     }
00380     */
00381 
00382     for (std::size_t i=0; i<sis->size(); i++) {
00383       Albany::StateStruct& st = *((*sis)[i]);
00384 
00385       if(elem_blocks[0]->field_exists(st.name))
00386 
00387         for(std::size_t j = 0; j < restart_fields.size(); j++)
00388 
00389           if(boost::iequals(st.name, restart_fields[j])){
00390 
00391             *out << "Restarting from field \"" << st.name << "\" found in exodus file." << std::endl;
00392             st.restartDataAvailable = true;
00393             break;
00394 
00395           }
00396     }
00397   }
00398 
00399 
00400   // ---- DJL DEBUGGING ----
00401 //   const Ioss::ElementBlockContainer& elem_blocks = region->get_element_blocks();
00402 //   Ioss::NameList exo_fld_names;
00403 //   elem_blocks[0]->field_describe(&exo_fld_names);
00404 //   for(std::size_t i = 0; i < exo_fld_names.size(); i++){
00405 //     *out << "DJL DEBUGGING Found field \"" << exo_fld_names[i] << "\" in exodus file" << std::endl;
00406 //   }
00407 
00408 //   stk::mesh::Field<double, stk::mesh::Cartesian>* volumeField = 
00409 //     metaData->get_field< stk::mesh::Field<double, stk::mesh::Cartesian> >("volume");
00410 
00411 //   // Create a selector to select everything in the universal part that is either locally owned or globally shared
00412 //   stk::mesh::Selector selector = 
00413 //     stk::mesh::Selector( metaData->universal_part() ) & ( stk::mesh::Selector( metaData->locally_owned_part() ) | stk::mesh::Selector( metaData->globally_shared_part() ) );
00414 
00415 //   // Select element mesh entities that match the selector
00416 //   std::vector<stk::mesh::Entity*> elements;
00417 //   stk::mesh::get_selected_entities(selector, bulkData->buckets(metaData->element_rank()), elements);
00418 
00419 //   // loop over the elements and load the data into the discretization's data structures
00420 //   for(unsigned int iElem=0 ; iElem<elements.size() ; ++iElem){
00421 //     stk::mesh::PairIterRelation nodeRelations = elements[iElem]->node_relations();
00422 //     if(nodeRelations.size() == 1){
00423 //       double* genesisVolume = stk::mesh::field_data(*volumeField, *elements[iElem]);
00424 //       TEUCHOS_TEST_FOR_EXCEPT_MSG(genesisVolume == NULL, "**** Volume attribute not found for sphere element.\n");
00425 //       std::cout << "DJL DEBUGGING Volume read from genesis file: " << *genesisVolume << std::endl;
00426 //     }
00427 //     else{
00428 //       std::cout << "DJL DEBUGGING Volume read from genesis file: not found because element is not a sphere element (number of nodes = " << nodeRelations.size() << ")" << std::endl;
00429 //     }
00430 //   }
00431   // ---- End DJL DEBUGGING ----
00432 
00433 
00434 //  coordinates_field = metaData->get_field<VectorFieldType>(std::string("coordinates"));
00435 //#ifdef ALBANY_FELIX
00436 //  surfaceHeight_field = metaData->get_field<ScalarFieldType>(std::string("surface height"));
00437 //#endif
00438 
00439   // Refine the mesh before starting the simulation if indicated
00440   uniformRefineMesh(comm);
00441 
00442   // Rebalance the mesh before starting the simulation if indicated
00443   rebalanceInitialMesh(comm);
00444 
00445   // Build additional mesh connectivity needed for mesh fracture (if indicated)
00446   computeAddlConnectivity();
00447 
00448 }
00449 
00450 double
00451 Albany::IossSTKMeshStruct::getSolutionFieldHistoryStamp(int step) const
00452 {
00453   TEUCHOS_ASSERT(step >= 0 && step < m_solutionFieldHistoryDepth);
00454 
00455   const int index = step + 1; // 1-based step indexing
00456   const Ioss::Region * const inputRegion = mesh_data->m_input_region;
00457   return inputRegion->get_state_time(index);
00458 }
00459 
00460 void
00461 Albany::IossSTKMeshStruct::loadSolutionFieldHistory(int step)
00462 {
00463   TEUCHOS_ASSERT(step >= 0 && step < m_solutionFieldHistoryDepth);
00464 
00465   const int index = step + 1; // 1-based step indexing
00466   stk::io::process_input_request(*mesh_data, *bulkData, index);
00467 }
00468 
00469 Teuchos::RCP<const Teuchos::ParameterList>
00470 Albany::IossSTKMeshStruct::getValidDiscretizationParameters() const
00471 {
00472   Teuchos::RCP<Teuchos::ParameterList> validPL =
00473     this->getValidGenericSTKParameters("Valid IOSS_DiscParams");
00474   validPL->set<bool>("Periodic BC", false, "Flag to indicate periodic a mesh");
00475   validPL->set<std::string>("Exodus Input File Name", "", "File Name For Exodus Mesh Input");
00476   validPL->set<std::string>("Pamgen Input File Name", "", "File Name For Pamgen Mesh Input");
00477   validPL->set<int>("Restart Index", 1, "Exodus time index to read for inital guess/condition.");
00478   validPL->set<double>("Restart Time", 1.0, "Exodus solution time to read for inital guess/condition.");
00479 
00480   Teuchos::Array<std::string> emptyStringArray;
00481   validPL->set<Teuchos::Array<std::string> >("Additional Node Sets", emptyStringArray, "Declare additional node sets not present in the input file");
00482 
00483   return validPL;
00484 }
00485 #endif

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