fei_FieldDofMap.hpp

00001 /*--------------------------------------------------------------------*/
00002 /*    Copyright 2009 Sandia Corporation.                              */
00003 /*    Under the terms of Contract DE-AC04-94AL85000, there is a       */
00004 /*    non-exclusive license for use of this work by or on behalf      */
00005 /*    of the U.S. Government.  Export of this program may require     */
00006 /*    a license from the United States Government.                    */
00007 /*--------------------------------------------------------------------*/
00008 
00009 #ifndef _fei_FieldDofMap_hpp_
00010 #define _fei_FieldDofMap_hpp_
00011 
00012 #include <fei_macros.hpp>
00013 #include <fei_constants.hpp>
00014 #include <sstream>
00015 
00016 namespace fei {
00017 
00022 template<class LocalOrdinal>
00023 class FieldDofMap {
00024  public:
00025   FieldDofMap()
00026     : m_dof_id_map(), m_need_to_compute_dof_ids(true)
00027   {}
00028 
00029   ~FieldDofMap(){}
00030 
00031   void add_field(LocalOrdinal fieldID, LocalOrdinal fieldSize, LocalOrdinal fieldType=fei::UNKNOWN);
00032 
00033   LocalOrdinal get_dof_id(LocalOrdinal fieldID, LocalOrdinal offset);
00034 
00035  private:
00036   void compute_dof_ids();
00037 
00038   //dof_id_map maps fields to pairs which each pair is <fieldSize, dof_id>.
00039   typedef std::map<LocalOrdinal,std::pair<LocalOrdinal,LocalOrdinal> > dof_id_map;
00040 
00041   dof_id_map m_dof_id_map;
00042   bool m_need_to_compute_dof_ids;
00043 };//class FieldDofMap
00044 
00045 template<class LocalOrdinal>
00046 void FieldDofMap<LocalOrdinal>::add_field(LocalOrdinal fieldID, LocalOrdinal fieldSize, LocalOrdinal fieldType)
00047 {
00048   //initially store 0 for the dof_id, will compute dof_ids later.
00049   m_dof_id_map.insert(std::make_pair(fieldID,std::make_pair(fieldSize,fieldType)));
00050   m_need_to_compute_dof_ids = true;
00051 }
00052 
00053 template<class LocalOrdinal>
00054 LocalOrdinal FieldDofMap<LocalOrdinal>::get_dof_id(LocalOrdinal fieldID, LocalOrdinal offset)
00055 {
00056   if (m_need_to_compute_dof_ids) {
00057     compute_dof_ids();
00058   }
00059 
00060   typename dof_id_map::const_iterator
00061     iter = m_dof_id_map.find(fieldID);
00062   if (iter == m_dof_id_map.end()) {
00063     throw std::runtime_error("fei::FieldDofMap ERROR, specified fieldID not found.");
00064   }
00065 
00066   if (offset >= iter->second.first) {
00067     throw std::runtime_error("FieldDofMap::get_dof_id ERROR, specified offset is greater than field-size.");
00068   }
00069 
00070   //dof_id_map maps fieldID to a pair<fieldSize,dof_id>.
00071   //We want to return the dof_id plus the input offset:
00072   return iter->second.second + offset;
00073 }
00074 
00075 template<class LocalOrdinal>
00076 void FieldDofMap<LocalOrdinal>::compute_dof_ids()
00077 {
00078   if (!m_need_to_compute_dof_ids) return;
00079 
00080   //first make sure dof_ids are unique. so make a second map which
00081   //maps dof_ids to iterators into the first map, and watch for
00082   //duplicates as we fill the second map. When we find duplicates,
00083   //we'll shift dof_ids up as necessary. (throw an exception if the
00084   //duplicate is not fei::UNKNOWN or bigger.)
00085 
00086   typedef std::map<LocalOrdinal, typename dof_id_map::iterator> dof_iter_map;
00087   dof_iter_map dof_2_iter;
00088 
00089   typename dof_id_map::iterator
00090     iter = m_dof_id_map.begin(), iter_end = m_dof_id_map.end();
00091 
00092   for(; iter!=iter_end; ++iter) {
00093     LocalOrdinal this_dof_id = iter->second.second;
00094 
00095     typename dof_iter_map::iterator di_iter = dof_2_iter.find(this_dof_id);
00096 
00097     if (di_iter != dof_2_iter.end()) {
00098       if (this_dof_id < fei::UNKNOWN) {
00099         std::ostringstream osstr;
00100         osstr << "fei::FieldDofMap::compute_dof_ids ERROR, duplicate field types found (";
00101         osstr << this_dof_id << " used more than once.)";
00102         std::string str = osstr.str();
00103         throw std::runtime_error(str);
00104       }
00105 
00106       //now we need to get fieldSize, and this is a little ugly:
00107       //di_iter->second is the iterator to the other map.
00108       //so di_iter->second->second is the value in the other map, which is a pair.
00109       //so di_iter->second->second.first is the fieldSize that we want.
00110       std::pair<LocalOrdinal,LocalOrdinal>& fsize_and_dof = di_iter->second->second;
00111       LocalOrdinal fieldSize = fsize_and_dof.first;
00112       LocalOrdinal last_dof_id = fsize_and_dof.second;
00113       di_iter->second = iter;
00114       iter->second.second = last_dof_id + fieldSize;
00115     }
00116     else dof_2_iter.insert(std::make_pair(this_dof_id, iter));
00117   }
00118 
00119   m_need_to_compute_dof_ids = false;
00120 }
00121 
00122 }//namespace fei
00123 
00124 #endif
00125 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends
Generated on Wed Apr 13 10:08:23 2011 for FEI by  doxygen 1.6.3