FEI Version of the Day
Loading...
Searching...
No Matches
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
16namespace fei {
17
22template<class LocalOrdinal>
24 public:
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
45template<class LocalOrdinal>
46void 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
53template<class LocalOrdinal>
54LocalOrdinal 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
75template<class LocalOrdinal>
76void 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