This source file includes following definitions.
- get_vertexList
- get_relevant_precision
- identity_map
- get_relevant_precision
- create_precision_vec
- max
- node_to_string
- string_to_node
- normalize_node
- clean_whitespace
- dgfFile_to_vec
- to_string
- to_key
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 #include <iterator>
17 #include <dassert.h>
18 #include "grid_GridAndTime_impl.h"
19
20 using namespace std;
21 using Esfem::Impl::Evolving_grid;
22 using Esfem::Impl::hash::grid;
23 using Node = Evolving_grid::Node;
24 using Nodes_key = Evolving_grid::Nodes_key;
25 using Map = Evolving_grid::Map;
26
27
28
29
30
31 Esfem::Impl::Evolving_grid::Evolving_grid(const std::string& filename)
32 try : original_vertices {get_vertexList(filename)},
33 digit_precision {get_relevant_precision(original_vertices)},
34 vertices_map {identity_map(original_vertices, digit_precision)}
35 {}
36 catch(const std::exception&){
37 std::throw_with_nested
38 (logic_error {"Error in constructor of Evolving_grid."});
39 }
40 catch(...){
41 throw logic_error {"Unknown error in constructor of Evolving_grid."};
42 }
43
44 const Node& Esfem::Impl::Evolving_grid::operator[](const Node& node) const try{
45 const auto node_as_string = node_to_string(node, digit_precision);
46 const Node* n_ptr {nullptr};
47 try{ n_ptr = &vertices_map.at(node_as_string); }
48 catch(...){
49 throw runtime_error {"Bad input: " + node_as_string};
50 }
51 return *n_ptr;
52 }
53 catch(const std::exception&){
54 std::throw_with_nested
55 (runtime_error {"Error in Evolving_grid::operator[]."});
56 }
57 catch(...){
58 throw runtime_error {"Unkown error in Evolving_grid::operator[]."};
59 }
60
61 Esfem::Impl::Evolving_grid& Esfem::Impl::Evolving_grid::
62 operator=(const Grid::Vec_FEfun& new_nodes) try{
63 using std::cbegin;
64 using std::cend;
65
66 constexpr std::size_t dim = 3;
67 static_assert(dim == Node::dimension, "Bad dimension.");
68 const auto no_vertices = original_vertices.size();
69 const auto dof_times_dim = new_nodes.size();
70 if(no_vertices * dim != dof_times_dim) throw logic_error {"Bad dimension."};
71
72 update_vertices(cbegin(new_nodes), cend(new_nodes), cbegin(original_vertices), dim);
73 }
74 catch(const std::exception&){
75 std::throw_with_nested
76 (runtime_error {"Error in Evolving_grid::operator=()."});
77 }
78 catch(...){
79 throw runtime_error {"Unkown error in Evolving_grid::operator=()."};
80 }
81
82
83
84
85 Nodes_key Esfem::Impl::
86 get_vertexList(const std::string& filename) try{
87 using std::cbegin;
88 using std::cend;
89 const auto whole_file = dgfFile_to_vec(filename);
90
91 auto first = dgf_find_vertex(cbegin(whole_file), cend(whole_file), filename);
92 auto last = dgf_close_list(first, cend(whole_file), filename);
93 return {first, last};
94 }
95 catch(const std::exception&){
96 std::throw_with_nested
97 (logic_error {"Error in get_vertexList()."});
98 }
99 catch(...){
100 throw runtime_error {"Unknown error in get_vertexList()."};
101 }
102 size_t Esfem::Impl::
103 get_relevant_precision(const vector<string>& vertex_list) try{
104 if(vertex_list.empty()) throw logic_error {"Empty input"};
105 const auto precision_vec = create_precision_vec(vertex_list);
106 return Esfem::Impl::max(precision_vec);
107 }
108 catch(const std::exception&){
109 std::throw_with_nested
110 (runtime_error {"Error in get_relevant_precision(const vector<string>&)"});
111 }
112 catch(...){
113 throw runtime_error
114 {"Unknown error in get_relevant_precision(const vector<string>&)"};
115 }
116
117 Map Esfem::Impl::
118 identity_map(const Nodes_key& nodes_lines, const std::size_t precision){
119 Map rv {};
120 rv.reserve(nodes_lines.size());
121 for(const auto& line : nodes_lines)
122 rv[normalize_node(line, precision)] = string_to_node(line);
123 return rv;
124 }
125
126 std::size_t Esfem::Impl::get_relevant_precision(const std::string& number) try{
127 const auto dot_iter = number.find(".");
128 const auto exp_iter = number.find("e");
129 const auto dist = exp_iter - dot_iter ;
130 if(dist < 1) throw logic_error {"Input has not scientific format."};
131 return dist;
132 }
133 catch(const std::exception&){
134 std::throw_with_nested(logic_error
135 {"Error in get_relevant_precision(const string&)"});
136 }
137 catch(...){
138 throw runtime_error {"Unknown error in get_relevant_precision(const string&)"};
139 }
140 vector<size_t> Esfem::Impl::create_precision_vec(const vector<string>& vertex_list){
141 vector<size_t> rv {};
142
143 constexpr int world_dim {3};
144 rv.reserve(vertex_list.size() * world_dim);
145
146
147 for(const auto& line : vertex_list){
148 istringstream interpreter {line};
149 for(string s; interpreter >> s; )
150 rv.push_back(get_relevant_precision(s));
151 }
152 return rv;
153 }
154
155 std::size_t Esfem::Impl::max(const std::vector<std::size_t>& v){
156 const auto rv_ptr = max_element(cbegin(v), cend(v));
157 if(rv_ptr == cend(v)) throw logic_error {"Error in max()"};
158 return *rv_ptr;
159 }
160
161 std::string Esfem::Impl::node_to_string(const Node& node, const int precision) try{
162
163 std::ostringstream oss;
164 oss << std::scientific;
165 for(std::size_t i = 0; i < Node::dimension - 1; ++i)
166 if( !(oss << std::setprecision(precision) << node[i] << ' ') )
167 throw runtime_error {"Node is too big."};
168 oss << std::setprecision(precision) << node[Node::dimension - 1];
169
170
171
172
173
174
175 return oss.str();
176 }
177 catch(const std::exception&){
178 std::throw_with_nested(runtime_error {"Error in node_to_string()."});
179 }
180 catch(...){
181 throw runtime_error {"Unknown error in node_to_string()."};
182 }
183
184 Node Esfem::Impl::string_to_node(const std::string& str_node) try{
185 std::istringstream interpreter {str_node};
186 Node rv;
187 double value {0.};
188 for(std::size_t it = 0; it < Node::dimension; ++it){
189 if(interpreter >> value) rv[it] = value;
190 else throw runtime_error("operator>>() failed!");
191 }
192 if( !(interpreter >> std::ws).eof())
193 throw runtime_error("Stuff left in node.");
194 return rv;
195 }
196 catch(const std::exception&){
197 std::throw_with_nested
198 (runtime_error {"Error in string_to_node()."});
199 }
200 catch(...){
201 throw runtime_error {"Unknown error in string_to_node()."};
202 }
203
204 std::string Esfem::Impl::
205 normalize_node(const std::string& str_node, const int precision){
206 return node_to_string(string_to_node(str_node), precision);
207 }
208
209 std::string Esfem::Impl::clean_whitespace(const std::string& line){
210 std::string clean_line {};
211 std::istringstream iss {line};
212 for(std::string s; iss >> s; )
213 clean_line += s + ' ';
214 clean_line.pop_back();
215 return clean_line;
216 }
217
218 std::vector<std::string> Esfem::Impl::
219 dgfFile_to_vec(const std::string& filename) try{
220 std::ifstream dgf_file {filename};
221 if(!dgf_file) throw logic_error {"Could not open \"" + filename + "\"."};
222
223 std::vector<std::string> lines;
224 for(std::string line; std::getline(dgf_file, line); )
225 lines.push_back(clean_whitespace(line));
226 dgf_file.close();
227 return lines;
228 }
229 catch(const std::exception&){
230 std::throw_with_nested
231 (runtime_error {"Error in dgfFile_to_vec()."});
232 }
233 catch(...){
234 throw runtime_error {"Unknown error in dgfFile_to_vec()."};
235 }
236
237
238
239
240 grid::grid(const std::string& fname){
241 const auto str_keys = get_vertexList(fname);
242
243 m.reserve(str_keys.size());
244 ol.reserve(str_keys.size());
245 istringstream iss;
246 iss.exceptions(ios_base::badbit);
247 size_t line_no {1};
248 range k {};
249 try{
250 for(const auto& line : str_keys){
251 iss.str(line);
252 for(int i = 0; i < dim; ++i) if(!(iss >> k[i])) throw bad {"Non-number"};
253 if(!(iss >> ws).eof()) throw bad {"Too many entries."};
254 const auto k2 = to_key(k);
255 m.emplace(k2, k);
256 ol.emplace_back(k2);
257 iss.clear();
258 ++line_no;
259 }
260 }
261 catch(...){
262 ostringstream oss;
263 oss << "In " << fname << " vertex no. " << line_no << ": "
264 << str_keys[line_no-1];
265 throw_with_nested(bad {Assert::compose(__FILE__, __LINE__, oss.str())});
266 }
267 }
268 grid::grid(const Grid::Vec_FEfun& init_keys){
269 const auto size = init_keys.size()/dim;
270
271 Assert::dynamic<Assert::level(Assert::default_level), bad>
272 (size * dim == init_keys.size(),
273 Assert::compose(__FILE__, __LINE__, "init_keys.size()%dim != 0"));
274
275 m.reserve(size);
276 ol.reserve(size);
277 for(auto it = init_keys.begin(); it != init_keys.end(); ++it){
278 range k {};
279 for(int i = 0; i < dim; ++i, ++it) k[i] = *it;
280 const auto k2 = to_key(k);
281 m.emplace(k2, k);
282 ol.emplace_back(k2);
283 }
284 }
285
286 auto grid::operator=(const Grid::Vec_FEfun& value_list) -> grid&{
287 Assert::dynamic<Assert::level(Assert::default_level), bad>
288 (dim * m.size() == value_list.size(),
289 Assert::compose(__FILE__, __LINE__, "grid::operator=()"));
290
291 auto m_it = ol.cbegin();
292 range k {};
293 for(auto v_it = value_list.begin(); v_it != value_list.end(); ){
294 for(int i = 0; i < dim; ++i, ++v_it) k[i] = *v_it;
295 m.at(*m_it++) = k;
296 }
297 return *this;
298 }
299 auto grid::operator[](const range& k) const -> const range& try{
300 return m.at(to_key(k));
301 }
302 catch(...){
303 throw_with_nested(bad {to_string(k)});
304 }
305 std::string Esfem::Impl::hash::to_string(const range& k){
306 ostringstream oss;
307 oss << scientific << '('
308 << setprecision(17) << k[0] << ", "
309 << setprecision(17) << k[1] << ", "
310 << setprecision(17) << k[2] << ')';
311 return oss.str();
312 }
313 auto Esfem::Impl::hash::to_key(const range& r) -> key{
314 constexpr auto fac = 1e5;
315 key rv {};
316 for(int i = 0; i < range::dimension; ++i)
317 rv[i] = static_cast<int>(fac * r[i]);
318 return rv;
319 }