DofMapper.cpp

00001 /*------------------------------------------------------------------------*/
00002 /*                 Copyright 2010 Sandia Corporation.                     */
00003 /*  Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive   */
00004 /*  license for use of this work by or on behalf of the U.S. Government.  */
00005 /*  Export of this program may require a license from the                 */
00006 /*  United States Government.                                             */
00007 /*------------------------------------------------------------------------*/
00008 
00009 
00010 #include <sstream>
00011 #include <stdexcept>
00012 
00013 #include <stk_linsys/DofMapper.hpp>
00014 
00015 #include <stk_mesh/base/FieldData.hpp>
00016 #include <stk_mesh/base/Selector.hpp>
00017 #include <stk_mesh/base/GetBuckets.hpp>
00018 
00019 #include <stk_linsys/ImplDetails.hpp>
00020 
00021 namespace stk {
00022 namespace linsys {
00023 
00024 DofMapper::DofMapper(MPI_Comm comm, bool create_reverse_mappings)
00025  : m_field_id_map(),
00026    m_fei_vecspace(new fei::VectorSpace(comm)),
00027    m_reverse_mappings_enabled(create_reverse_mappings),
00028    m_fei_reversemap(NULL)
00029 {
00030 }
00031 
00032 DofMapper::~DofMapper()
00033 {
00034   delete m_fei_reversemap;
00035 }
00036 
00037 namespace {
00038 
00039 void throw_fei_err(const std::string& mesg, int err)
00040 {
00041   std::ostringstream osstr;
00042   osstr << mesg << err;
00043   std::string str = osstr.str();
00044   throw std::runtime_error(str);
00045 }
00046 
00047 }//namespace <anonymous>
00048 
00049 void
00050 DofMapper::add_dof_mappings(const stk::mesh::BulkData& mesh_bulk,
00051                             const stk::mesh::PartVector& part_intersection,
00052                             stk::mesh::EntityType ent_type,
00053                             const stk::mesh::FieldBase& field)
00054 {
00055   int idType = static_cast<int>(ent_type);
00056 
00057   m_fei_vecspace->defineIDTypes( 1, &idType );
00058 
00059   int field_id = impl::map_field_to_int(m_field_id_map, field);
00060 
00061   stk::mesh::Selector selector = selectIntersection(part_intersection);
00062   const std::vector<stk::mesh::Bucket*>& all_buckets = mesh_bulk.buckets(ent_type);
00063   std::vector<stk::mesh::Bucket*> buckets;
00064   stk::mesh::get_buckets(selector, all_buckets, buckets);
00065 
00066   bool already_declared_fei_field = false;
00067 
00068   for(size_t i=0; i<buckets.size(); ++i) {
00069     int field_data_size = stk::mesh::field_data_size( field, *buckets[i] );
00070 
00071     if (field_data_size == 0) continue;
00072 
00073     if (!already_declared_fei_field) {
00074       int field_size = field.max_size(ent_type);
00075       m_fei_vecspace->defineFields(1, &field_id, &field_size);
00076       already_declared_fei_field = true;
00077     }
00078 
00079     std::vector<int> ids(mesh_bulk.bucket_capacity());
00080 
00081     stk::mesh::Bucket::iterator
00082       iter = buckets[i]->begin(), iter_end = buckets[i]->end();
00083 
00084     int num_ids = 0;
00085 
00086     for(; iter != iter_end; ++iter) {
00087       stk::mesh::Entity& entity = *iter;
00088       ids[num_ids++] = impl::entityid_to_int(entity.identifier());
00089     }
00090 
00091     int err = m_fei_vecspace->addDOFs(field_id, 1, idType, num_ids, &ids[0]);
00092     if (err != 0) throw_fei_err("stk::linsys::DofMapper::add_dof_mappings ERROR: fei::VectorSpace::addDOFs returned error-code=",err);
00093   }
00094 
00095   std::vector<int> shared_ids;
00096   std::vector<int> sharing_procs;
00097 
00098   const std::vector<stk::mesh::Entity*>& entity_comm = mesh_bulk.entity_comm();
00099   for(size_t i=0; i<entity_comm.size(); ++i) {
00100     stk::mesh::Entity* ent = entity_comm[i] ;
00101 
00102     //we only care about entities of the right type, and which have data for 'field'.
00103     if (ent->entity_rank() != ent_type) continue;
00104     if (!stk::mesh::field_data_valid(field, *ent)) continue;
00105 
00106     const stk::mesh::PairIterEntityComm ec = ent->sharing();
00107 
00108     for ( size_t j = 0 ; j < ec.size() ; ++j ) {
00109       shared_ids.push_back(impl::entityid_to_int(ent->identifier()));
00110       sharing_procs.push_back(ec[j].proc);
00111     }
00112   }
00113 
00114   if (shared_ids.size() > 0) {
00115     std::vector<int> num_sharing_procs_per_id(shared_ids.size(), 1);
00116 
00117     int err = m_fei_vecspace->initSharedIDs(shared_ids.size(), idType,
00118                                            &shared_ids[0], &num_sharing_procs_per_id[0],
00119                                            &sharing_procs[0]);
00120     if (err != 0) throw_fei_err("stk::linsys::DofMapper::add_dof_mappings ERROR: fei::VectorSpace::initSharedIDs returned error-code=",err);
00121   }
00122 }
00123 
00124 void
00125 DofMapper::finalize()
00126 {
00127   int err = m_fei_vecspace->initComplete();
00128   if (err != 0) throw_fei_err("stk::linsys::DofMapper::finalize ERROR: fei::VectorSpace::initComplete returned error-code=",err);
00129 
00130   if (m_reverse_mappings_enabled) {
00131     delete m_fei_reversemap;
00132     m_fei_reversemap = new fei::ReverseMapper(*m_fei_vecspace);
00133   }
00134 }
00135 
00136 int
00137 DofMapper::get_field_id(const stk::mesh::FieldBase& field) const
00138 {
00139   return impl::query_field_to_int_mapping(m_field_id_map, field);
00140 }
00141 
00142 int
00143 DofMapper::get_global_index(stk::mesh::EntityType ent_type,
00144                             stk::mesh::EntityId ent_id,
00145                             stk::mesh::FieldBase& field,
00146                             int offset_into_field)
00147 {
00148   int err = 0, index = 0;
00149   int field_id = get_field_id(field);
00150   int int_id = impl::entityid_to_int(ent_id);
00151 
00152   try {
00153     err = m_fei_vecspace->getGlobalIndex(ent_type, int_id, field_id, index);
00154     if (err != 0) throw_fei_err("fei::VectorSpace::getGlobalIndex error=",err);
00155   }
00156   catch (...) {
00157     std::ostringstream msg;
00158     msg << "stk::linsys::DofMapper::get_global_index ERROR: "
00159      << "fei::VectorSpace::getGlobalIndex returned error-code ("<<err
00160      << ") or threw exception, probably meaning that the entity with type="<<ent_type<<" and id="
00161      << ent_id<<" was not found.";
00162     std::string str = msg.str();
00163     throw std::runtime_error(str);
00164   }
00165 
00166   return index + offset_into_field;
00167 }
00168 
00169 void
00170 DofMapper::get_dof(int global_index,
00171                    stk::mesh::EntityType& ent_type,
00172                    stk::mesh::EntityId& ent_id,
00173                    const stk::mesh::FieldBase*& field,
00174                    int& offset_into_field) const
00175 {
00176   if (!m_reverse_mappings_enabled || m_fei_reversemap == NULL) {
00177     std::ostringstream msg;
00178     msg << "stk::linsys::DofMapper::get_dof ERROR: "
00179      << "either reverse-mappings are disabled or DofMapper::finalize hasn't "
00180      << "been called yet.";
00181     std::string str = msg.str();
00182     throw std::runtime_error(str);
00183   }
00184 
00185   fei::EqnRecord eqrec = m_fei_reversemap->getEqnRecord(global_index);
00186 
00187   ent_type = eqrec.IDType;
00188   ent_id   = eqrec.ID;
00189   offset_into_field = eqrec.offset;
00190   field = impl::get_field(m_field_id_map, eqrec.fieldID);
00191 }
00192 
00193 }//namespace linsys
00194 }//namespace stk
00195 

Generated on Tue Jul 13 09:27:32 2010 for Sierra Toolkit by  doxygen 1.4.7