FEI Version of the Day
fei_FieldDofMap.hpp
00001 /*
00002 // @HEADER
00003 // ************************************************************************
00004 //             FEI: Finite Element Interface to Linear Solvers
00005 //                  Copyright (2005) Sandia Corporation.
00006 //
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the
00008 // U.S. Government retains certain rights in this software.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Alan Williams (william@sandia.gov) 
00038 //
00039 // ************************************************************************
00040 // @HEADER
00041 */
00042 
00043 
00044 #ifndef _fei_FieldDofMap_hpp_
00045 #define _fei_FieldDofMap_hpp_
00046 
00047 #include <fei_macros.hpp>
00048 #include <fei_constants.hpp>
00049 #include <sstream>
00050 
00051 namespace fei {
00052 
00057 template<class LocalOrdinal>
00058 class FieldDofMap {
00059  public:
00060   FieldDofMap()
00061     : m_dof_id_map(), m_need_to_compute_dof_ids(true)
00062   {}
00063 
00064   ~FieldDofMap(){}
00065 
00066   void add_field(LocalOrdinal fieldID, LocalOrdinal fieldSize, LocalOrdinal fieldType=fei::UNKNOWN);
00067 
00068   LocalOrdinal get_dof_id(LocalOrdinal fieldID, LocalOrdinal offset);
00069 
00070  private:
00071   void compute_dof_ids();
00072 
00073   //dof_id_map maps fields to pairs which each pair is <fieldSize, dof_id>.
00074   typedef std::map<LocalOrdinal,std::pair<LocalOrdinal,LocalOrdinal> > dof_id_map;
00075 
00076   dof_id_map m_dof_id_map;
00077   bool m_need_to_compute_dof_ids;
00078 };//class FieldDofMap
00079 
00080 template<class LocalOrdinal>
00081 void FieldDofMap<LocalOrdinal>::add_field(LocalOrdinal fieldID, LocalOrdinal fieldSize, LocalOrdinal fieldType)
00082 {
00083   //initially store 0 for the dof_id, will compute dof_ids later.
00084   m_dof_id_map.insert(std::make_pair(fieldID,std::make_pair(fieldSize,fieldType)));
00085   m_need_to_compute_dof_ids = true;
00086 }
00087 
00088 template<class LocalOrdinal>
00089 LocalOrdinal FieldDofMap<LocalOrdinal>::get_dof_id(LocalOrdinal fieldID, LocalOrdinal offset)
00090 {
00091   if (m_need_to_compute_dof_ids) {
00092     compute_dof_ids();
00093   }
00094 
00095   typename dof_id_map::const_iterator
00096     iter = m_dof_id_map.find(fieldID);
00097   if (iter == m_dof_id_map.end()) {
00098     throw std::runtime_error("fei::FieldDofMap ERROR, specified fieldID not found.");
00099   }
00100 
00101   if (offset >= iter->second.first) {
00102     throw std::runtime_error("FieldDofMap::get_dof_id ERROR, specified offset is greater than field-size.");
00103   }
00104 
00105   //dof_id_map maps fieldID to a pair<fieldSize,dof_id>.
00106   //We want to return the dof_id plus the input offset:
00107   return iter->second.second + offset;
00108 }
00109 
00110 template<class LocalOrdinal>
00111 void FieldDofMap<LocalOrdinal>::compute_dof_ids()
00112 {
00113   if (!m_need_to_compute_dof_ids) return;
00114 
00115   //first make sure dof_ids are unique. so make a second map which
00116   //maps dof_ids to iterators into the first map, and watch for
00117   //duplicates as we fill the second map. When we find duplicates,
00118   //we'll shift dof_ids up as necessary. (throw an exception if the
00119   //duplicate is not fei::UNKNOWN or bigger.)
00120 
00121   typedef std::map<LocalOrdinal, typename dof_id_map::iterator> dof_iter_map;
00122   dof_iter_map dof_2_iter;
00123 
00124   typename dof_id_map::iterator
00125     iter = m_dof_id_map.begin(), iter_end = m_dof_id_map.end();
00126 
00127   for(; iter!=iter_end; ++iter) {
00128     LocalOrdinal this_dof_id = iter->second.second;
00129 
00130     typename dof_iter_map::iterator di_iter = dof_2_iter.find(this_dof_id);
00131 
00132     if (di_iter != dof_2_iter.end()) {
00133       if (this_dof_id < fei::UNKNOWN) {
00134         std::ostringstream osstr;
00135         osstr << "fei::FieldDofMap::compute_dof_ids ERROR, duplicate field types found (";
00136         osstr << this_dof_id << " used more than once.)";
00137         std::string str = osstr.str();
00138         throw std::runtime_error(str);
00139       }
00140 
00141       //now we need to get fieldSize, and this is a little ugly:
00142       //di_iter->second is the iterator to the other map.
00143       //so di_iter->second->second is the value in the other map, which is a pair.
00144       //so di_iter->second->second.first is the fieldSize that we want.
00145       std::pair<LocalOrdinal,LocalOrdinal>& fsize_and_dof = di_iter->second->second;
00146       LocalOrdinal fieldSize = fsize_and_dof.first;
00147       LocalOrdinal last_dof_id = fsize_and_dof.second;
00148       di_iter->second = iter;
00149       iter->second.second = last_dof_id + fieldSize;
00150     }
00151     else dof_2_iter.insert(std::make_pair(this_dof_id, iter));
00152   }
00153 
00154   m_need_to_compute_dof_ids = false;
00155 }
00156 
00157 }//namespace fei
00158 
00159 #endif
00160 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends