FEI  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
fei_FieldDofMap.hpp
1 /*--------------------------------------------------------------------*/
2 /* Copyright 2009 Sandia Corporation. */
3 /* Under the terms of Contract DE-AC04-94AL85000, there is a */
4 /* non-exclusive license for use of this work by or on behalf */
5 /* of the U.S. Government. Export of this program may require */
6 /* a license from the United States Government. */
7 /*--------------------------------------------------------------------*/
8 
9 #ifndef _fei_FieldDofMap_hpp_
10 #define _fei_FieldDofMap_hpp_
11 
12 #include <fei_macros.hpp>
13 #include <fei_constants.hpp>
14 #include <sstream>
15 
16 namespace fei {
17 
22 template<class LocalOrdinal>
23 class FieldDofMap {
24  public:
25  FieldDofMap()
26  : m_dof_id_map(), m_need_to_compute_dof_ids(true)
27  {}
28 
29  ~FieldDofMap(){}
30 
31  void add_field(LocalOrdinal fieldID, LocalOrdinal fieldSize, LocalOrdinal fieldType=fei::UNKNOWN);
32 
33  LocalOrdinal get_dof_id(LocalOrdinal fieldID, LocalOrdinal offset);
34 
35  private:
36  void compute_dof_ids();
37 
38  //dof_id_map maps fields to pairs which each pair is <fieldSize, dof_id>.
39  typedef std::map<LocalOrdinal,std::pair<LocalOrdinal,LocalOrdinal> > dof_id_map;
40 
41  dof_id_map m_dof_id_map;
42  bool m_need_to_compute_dof_ids;
43 };//class FieldDofMap
44 
45 template<class LocalOrdinal>
46 void FieldDofMap<LocalOrdinal>::add_field(LocalOrdinal fieldID, LocalOrdinal fieldSize, LocalOrdinal fieldType)
47 {
48  //initially store 0 for the dof_id, will compute dof_ids later.
49  m_dof_id_map.insert(std::make_pair(fieldID,std::make_pair(fieldSize,fieldType)));
50  m_need_to_compute_dof_ids = true;
51 }
52 
53 template<class LocalOrdinal>
54 LocalOrdinal FieldDofMap<LocalOrdinal>::get_dof_id(LocalOrdinal fieldID, LocalOrdinal offset)
55 {
56  if (m_need_to_compute_dof_ids) {
57  compute_dof_ids();
58  }
59 
60  typename dof_id_map::const_iterator
61  iter = m_dof_id_map.find(fieldID);
62  if (iter == m_dof_id_map.end()) {
63  throw std::runtime_error("fei::FieldDofMap ERROR, specified fieldID not found.");
64  }
65 
66  if (offset >= iter->second.first) {
67  throw std::runtime_error("FieldDofMap::get_dof_id ERROR, specified offset is greater than field-size.");
68  }
69 
70  //dof_id_map maps fieldID to a pair<fieldSize,dof_id>.
71  //We want to return the dof_id plus the input offset:
72  return iter->second.second + offset;
73 }
74 
75 template<class LocalOrdinal>
76 void FieldDofMap<LocalOrdinal>::compute_dof_ids()
77 {
78  if (!m_need_to_compute_dof_ids) return;
79 
80  //first make sure dof_ids are unique. so make a second map which
81  //maps dof_ids to iterators into the first map, and watch for
82  //duplicates as we fill the second map. When we find duplicates,
83  //we'll shift dof_ids up as necessary. (throw an exception if the
84  //duplicate is not fei::UNKNOWN or bigger.)
85 
86  typedef std::map<LocalOrdinal, typename dof_id_map::iterator> dof_iter_map;
87  dof_iter_map dof_2_iter;
88 
89  typename dof_id_map::iterator
90  iter = m_dof_id_map.begin(), iter_end = m_dof_id_map.end();
91 
92  for(; iter!=iter_end; ++iter) {
93  LocalOrdinal this_dof_id = iter->second.second;
94 
95  typename dof_iter_map::iterator di_iter = dof_2_iter.find(this_dof_id);
96 
97  if (di_iter != dof_2_iter.end()) {
98  if (this_dof_id < fei::UNKNOWN) {
99  std::ostringstream osstr;
100  osstr << "fei::FieldDofMap::compute_dof_ids ERROR, duplicate field types found (";
101  osstr << this_dof_id << " used more than once.)";
102  std::string str = osstr.str();
103  throw std::runtime_error(str);
104  }
105 
106  //now we need to get fieldSize, and this is a little ugly:
107  //di_iter->second is the iterator to the other map.
108  //so di_iter->second->second is the value in the other map, which is a pair.
109  //so di_iter->second->second.first is the fieldSize that we want.
110  std::pair<LocalOrdinal,LocalOrdinal>& fsize_and_dof = di_iter->second->second;
111  LocalOrdinal fieldSize = fsize_and_dof.first;
112  LocalOrdinal last_dof_id = fsize_and_dof.second;
113  di_iter->second = iter;
114  iter->second.second = last_dof_id + fieldSize;
115  }
116  else dof_2_iter.insert(std::make_pair(this_dof_id, iter));
117  }
118 
119  m_need_to_compute_dof_ids = false;
120 }
121 
122 }//namespace fei
123 
124 #endif
125