2
/// This file is part of Rheolef.
4
/// Copyright (C) 2000-2009 Pierre Saramito <Pierre.Saramito@imag.fr>
6
/// Rheolef is free software; you can redistribute it and/or modify
7
/// it under the terms of the GNU General Public License as published by
8
/// the Free Software Foundation; either version 2 of the License, or
9
/// (at your option) any later version.
11
/// Rheolef is distributed in the hope that it will be useful,
12
/// but WITHOUT ANY WARRANTY; without even the implied warranty of
13
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
/// GNU General Public License for more details.
16
/// You should have received a copy of the GNU General Public License
17
/// along with Rheolef; if not, write to the Free Software
18
/// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
/// =========================================================================
21
#include "rheolef/hazel_1d.h"
22
#include "rheolef/georep.h"
25
hazel_1d::insert (pair<size_type,size_type>& v2e_ix, size_type K_idx)
27
static const size_type none = numeric_limits<size_type>::max();
28
if (v2e_ix.first == none) { v2e_ix.first = K_idx; return; }
29
if (v2e_ix.second == none) { v2e_ix.second = K_idx; return; }
30
error_macro ("unexpected 1d mesh connectivity arround element " << K_idx);
32
hazel_1d::hazel_1d (const georep& Ih)
33
: vector<vector<size_type> >(),
39
hazel_1d::initialize (const georep& Ih)
41
check_macro (Ih.map_dimension() == 1, "only 1D mesh here");
42
// ------------------------------------
43
// 1) initialize vertex2edge table
44
// ------------------------------------
45
size_type dimension = Ih.dimension(); // number of physical coordinates
46
static const size_type none = numeric_limits<size_type>::max();
47
pair<size_type,size_type> none_pair = make_pair(none,none);
48
vector<pair<size_type,size_type> > vertex2edge (Ih.n_vertex(), none_pair);
49
georep::const_iterator K = Ih.begin();
50
georep::const_iterator_vertex x = Ih.begin_vertex();
51
for (size_type k = 0; k < Ih.size(); k++) {
52
insert (vertex2edge[K[k][0]], k);
53
insert (vertex2edge[K[k][1]], k);
56
for (size_type i = 0; i < vertex2edge.size(); i++) {
57
check_macro (vertex2edge[i].first != none, "vertex " << i
58
<< " has no elements");
60
// -------------------------------------
61
// 2) build list of connected components
62
// -------------------------------------
63
list<list<size_type> > path_list;
64
vector<bool> mark (Ih.n_vertex(), false);
65
list<pair<Float,Float> > interval_list;
66
for (size_type i = 0; i < Ih.n_vertex(); i++) {
67
// search for an extremity of a connected component
68
// i.e a boundary none that is included in only one element
72
if (dimension == 1 && vertex2edge[i].second != none) {
75
path_list.push_back(list<size_type>());
76
list<size_type>& path = *(path_list.rbegin());
78
size_type k = vertex2edge[i].first;
82
j = (K[k][0] != j_prec) ? K[k][0] : K[k][1];
90
k = (vertex2edge[j].first != k_prev) ? vertex2edge[j].first : vertex2edge[j].second;
92
// path from i to j : ordered by increasing coordinate ?
94
pair<Float,Float> boundary;
95
if (x[i][0] < x[j][0]) {
96
boundary = make_pair(x[i][0], x[j][0]);
98
boundary = make_pair(x[j][0], x[i][0]);
101
interval_list.push_back(boundary);
104
// copy list<list> into hard-sized vector<vector> : save memory
105
size_type n_component = path_list.size();
106
vector<vector<size_type> >::resize(n_component);
107
size_type i_component = 0;
108
for (list<list<size_type> >::const_iterator p = path_list.begin(); p != path_list.end(); p++, i_component++) {
109
const list<size_type>& path = *p;
110
vector<size_type>& new_path = vector<vector<size_type> >::operator[](i_component);
111
new_path.resize(path.size());
112
copy (path.begin(), path.end(), new_path.begin());
114
// copy also interval list into hard-sized version (when dimension = 1)
115
if (dimension == 1) {
116
_interval.resize(n_component);
117
copy (interval_list.begin(), interval_list.end(), _interval.begin());
121
hazel_1d::localize (const georep& Ih, const Float& x0) const
123
check_macro (_interval.size() != 0, "cannot localize in a " << Ih.dimension()
125
// step 1 : find connex component containing x0
126
static const size_type none = numeric_limits<size_type>::max();
128
for (size_type i = 0; i < _interval.size(); i++) {
129
if (_interval[i].first <= x0 && _interval[i].second >= x0) {
134
if (i0 == none) return none;
135
const vector<size_type>& component = operator[](i0);
136
size_type n = component.size();
137
// step 2 : find element containing x0 in component
138
// by using dichotomy on elements
139
georep::const_iterator K = Ih.begin();
140
georep::const_iterator_vertex x = Ih.begin_vertex();
144
while (kmin+1 < kmax) {
145
k = size_type((kmin + kmax)/2.0);
146
Float xk = min(x[K[k][0]][0],x[K[k][1]][0]);
147
if (x0 >= xk) kmin = k;
154
Float x1 = min(x[K[k][0]][0],x[K[k][1]][0]);
155
Float x2 = max(x[K[k][0]][0],x[K[k][1]][0]);
156
check_macro (x1 <= x0 && x0 <= x2, "locate error");
161
hazel_1d::localize_nearest (const georep& Ih, const Float& x0,
162
Float& y0, size_type& k) const
164
static const size_type none = numeric_limits<size_type>::max();
165
k = localize (Ih, x0);
166
if (k != none) { y0 = x0; return true; }
167
// loop on intervals and search closest boundary
169
Float dist_min = numeric_limits<Float>::max();
170
size_t extremity = 0;
171
for (size_type i = 0; i < _interval.size(); i++) {
172
Float d1 = fabs(x0 - _interval[i].first);
174
y0 = _interval[i].first;
179
Float d2 = fabs(x0 - _interval[i].second);
181
y0 = _interval[i].second;
187
const vector<size_type>& component = operator[](i0);
188
if (extremity == 0) {
191
k = component[component.size()-1];
196
// return true if x0+v is inside the mesh
197
// otherwise return nearest element containing x,
198
// also t such that x=x0+t*v (for the method of characteristic)
200
hazel_1d::trace (const georep& Ih, const Float& x0, const Float& v, Float& x, Float& t, size_type& k) const
202
static const size_type none = numeric_limits<size_type>::max();
203
bool is_inside = localize_nearest (Ih, x0+v, x, k);
207
t = (1+v != 1) ? (x-x0)/v : 0;