File: geo_seq_get.cc

package info (click to toggle)
rheolef 7.2-6
  • links: PTS, VCS
  • area: main
  • in suites: forky
  • size: 88,076 kB
  • sloc: cpp: 110,259; sh: 16,733; makefile: 5,438; python: 1,391; yacc: 218; javascript: 203; xml: 191; awk: 61; sed: 5
file content (329 lines) | stat: -rw-r--r-- 15,069 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
///
/// This file is part of Rheolef.
///
/// Copyright (C) 2000-2009 Pierre Saramito <Pierre.Saramito@imag.fr>
///
/// Rheolef is free software; you can redistribute it and/or modify
/// it under the terms of the GNU General Public License as published by
/// the Free Software Foundation; either version 2 of the License, or
/// (at your option) any later version.
///
/// Rheolef is sequential in the hope that it will be useful,
/// but WITHOUT ANY WARRANTY; without even the implied warranty of
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
/// GNU General Public License for more details.
///
/// You should have received a copy of the GNU General Public License
/// along with Rheolef; if not, write to the Free Software
/// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
/// 
/// =========================================================================
#include "rheolef/geo.h"
#include "rheolef/geo_domain.h"
#include "rheolef/rheostream.h"
#include "rheolef/iorheo.h"
#include "rheolef/rheostream.h"

namespace rheolef {

template <class T> idiststream& geo_get_vtk  (idiststream& ips, geo_basic<T,sequential>& omega);
template <class T> idiststream& geo_get_bamg (idiststream& ips, geo_basic<T,sequential>& omega);

template <class T>
idiststream&
geo_basic<T,sequential>::get (idiststream& ips)
{
  iorheo::flag_type format = iorheo::flags(ips.is()) & iorheo::format_field;
  if (format [iorheo::vtk])     { return geo_get_vtk     (ips,*this); }
  if (format [iorheo::bamg])    { return geo_get_bamg    (ips,*this); }

  // else: standard .geo format:
  // allocate a new geo_rep object (TODO: do a dynamic_cast ?)
  geo_rep<T,sequential>* ptr = new_macro((geo_rep<T,sequential>));
  ptr->get (ips);
  base::operator= (ptr);
  return ips;
}
/** ------------------------------------------------------------------------
 * on any 3d geo_element K, set K.dis_iface(iloc) number
 * ------------------------------------------------------------------------
 */
template <class T>
void
geo_rep<T,sequential>::set_element_side_index (size_type side_dim)
{
  if (map_dimension() <= side_dim) return;
  // ------------------------------------------------------------------------
  // 1) ball(X) := { E; X is a vertex of E }
  // ------------------------------------------------------------------------
  index_set empty_set; // TODO: add a global allocator to empty_set
  disarray<index_set,sequential> ball (geo_element_ownership(0), empty_set);
  {
    size_type isid = 0;
    for (const_iterator iter = begin(side_dim), last = end(side_dim); iter != last; iter++, isid++) {
      const geo_element& S = *iter;
      for (size_type iloc = 0, nloc = S.size(); iloc < nloc; iloc++) {
        size_type iv = S[iloc];
        ball [iv] += isid;
      }
    }
  }
  // ------------------------------------------------------------------------
  // 2) pour K dans partition(iproc)
  //      pour (dis_A,dis_B) arete de K
  //        set = dis_ball(dis_A) inter dis_ball(dis_B) = {dis_iedg}
  //        E = dis_edges(dis_iedg)
  //        => on numerote dis_iedg cette arete dans le geo_element K
  //        et on indique son orient en comparant a E, arete qui definit l'orient
  // ------------------------------------------------------------------------
  for (size_type dim = side_dim+1; dim <= base::_gs._map_dimension; dim++) {
    for (iterator iter = begin(dim), last = end(dim); iter != last; iter++) {
      geo_element& K = *iter;
      for (size_type loc_isid = 0, loc_nsid = K.n_subgeo(side_dim); loc_isid < loc_nsid; loc_isid++) {
        size_type loc_jv0 = K.subgeo_local_vertex (side_dim, loc_isid, 0);
        size_type     jv0 = K[loc_jv0];
        index_set isid_set = ball [jv0]; // copy: will be intersected
	for (size_type sid_jloc = 1, sid_nloc = K.subgeo_size (side_dim, loc_isid); sid_jloc < sid_nloc; sid_jloc++) { 
          size_type loc_jv = K.subgeo_local_vertex (side_dim, loc_isid, sid_jloc);
          size_type     jv = K[loc_jv];
          const index_set& ball_jv = ball [jv];
          isid_set.inplace_intersection (ball_jv);
	}
        check_macro (isid_set.size() == 1, "connectivity: side not found in the side set");
	size_type isid = *(isid_set.begin());
	const geo_element& S = get_geo_element(side_dim,isid);
	if (side_dim == 1) {
          // side: edge
	  size_type jv1 = K [K.subgeo_local_vertex (side_dim, loc_isid, 1)];
          geo_element::orientation_type orient = S.get_edge_orientation (jv0, jv1);
          K.edge_indirect (loc_isid).set (orient, isid);
        } else { // side_dim == 2 
          geo_element::orientation_type orient;
          geo_element::shift_type       shift;
          if (K.subgeo_size (side_dim, loc_isid) == 3) {
	    // side: triangle
	    size_type jv1 = K [K.subgeo_local_vertex (side_dim, loc_isid, 1)];
	    size_type jv2 = K [K.subgeo_local_vertex (side_dim, loc_isid, 2)];
	    S.get_orientation_and_shift (jv0, jv1, jv2, orient, shift);
          } else {
	    // side: quadrangle
	    size_type jv1 = K [K.subgeo_local_vertex (side_dim, loc_isid, 1)];
	    size_type jv2 = K [K.subgeo_local_vertex (side_dim, loc_isid, 2)];
	    size_type jv3 = K [K.subgeo_local_vertex (side_dim, loc_isid, 3)];
	    S.get_orientation_and_shift (jv0, jv1, jv2, jv3, orient, shift);
          }
          K.face_indirect (loc_isid).set (orient, isid, shift);
        }
      }
    }
  }
}
// =========================================================================
// get
// =========================================================================
/// @brief io for geo
template <class T>
idiststream&
geo_rep<T,sequential>::get (idiststream& ips)
{
  using namespace std;
  check_macro (ips.good(), "bad input stream for geo.");
  istream& is = ips.is();
  // ------------------------------------------------------------------------
  // 0) get header
  // ------------------------------------------------------------------------
  check_macro (dis_scatch(ips,ips.comm(),"\nmesh"), "input stream does not contains a geo.");
  ips >> base::_version;
  check_macro (base::_version == 4, "mesh format version 4 expected, but format version " << base::_version << " founded");
  geo_header hdr;
  ips >> hdr;
  bool do_upgrade = iorheo::getupgrade(is);
  if (do_upgrade || hdr.need_upgrade()) {
    return get_upgrade  (ips, hdr);
  } else {
    return get_standard (ips, hdr);
  }
}
template <class T>
idiststream&
geo_rep<T,sequential>::get_standard (idiststream& ips, const geo_header& hdr)
{
  using namespace std;
  check_macro (ips.good(), "bad input stream for geo.");
  istream& is = ips.is();
  // ------------------------------------------------------------------------
  // 1) store header infos in geo
  // ------------------------------------------------------------------------
  base::_have_connectivity = true;
  base::_name          = "unnamed";
  base::_dimension     = hdr.dimension;
  base::_gs._map_dimension = hdr.map_dimension;
  base::_sys_coord     = hdr.sys_coord;
  base::_piola_basis.reset_family_index (hdr.order); 
  size_type nnod  = hdr.dis_size_by_dimension [0];
  size_type n_edg = hdr.dis_size_by_dimension [1];
  size_type n_fac = hdr.dis_size_by_dimension [2];
  size_type n_elt = hdr.dis_size_by_dimension [base::_gs._map_dimension];
  // ------------------------------------------------------------------------
  // 2) get coordinates
  // ------------------------------------------------------------------------
  base::_node.resize (nnod);
  if (base::_dimension > 0) {
    base::_node.get_values (ips, _point_get<T>(geo_base_rep<T,sequential>::_dimension));
    check_macro (ips.good(), "bad input stream for geo.");
  }
  base::_gs.node_ownership = base::_node.ownership();
  // ------------------------------------------------------------------------
  // 3) get elements
  // ------------------------------------------------------------------------
  if (base::_gs._map_dimension > 0) {
    for (size_type variant = reference_element::first_variant_by_dimension(base::_gs._map_dimension);
                   variant < reference_element:: last_variant_by_dimension(base::_gs._map_dimension); variant++) {
      geo_element::parameter_type param (variant, 1);
      base::_geo_element [variant].resize (hdr.dis_size_by_variant [variant], param);
      base::_geo_element [variant].get_values (ips);
      base::_gs.ownership_by_variant [variant] = base::_geo_element [variant].ownership();
    }
    base::_gs.ownership_by_dimension [base::_gs._map_dimension] = distributor (n_elt, base::comm(), n_elt);
  }
  // ------------------------------------------------------------------------
  // 4) check that nodes are numbered by increasing node_subgeo_dim
  // ------------------------------------------------------------------------
  // ICI va devenir obsolete car les noeuds seront numerotes par _numbering=Pk_numbering
  {
    std::vector<size_type> node_subgeo_dim (nnod, size_type(-1));
    size_type prev_variant = 0;
    for (iterator iter = begin(base::_gs._map_dimension), last = end(base::_gs._map_dimension); iter != last; iter++) {
      geo_element& K = *iter;
      check_macro (prev_variant <= K.variant(), "elements should be numbered by increasing variants (petqTPH)");
      prev_variant = K.variant();
      for (size_type d = 0; d <= base::_gs._map_dimension; d++) { 
        for (size_type loc_inod = K.first_inod(d), loc_nnod = K.last_inod(d); loc_inod < loc_nnod; loc_inod++) {
          node_subgeo_dim [K[loc_inod]] = d;
        }
      }
    }
    size_type prev_node_dim = 0;
    for (typename std::vector<size_type>::const_iterator iter = node_subgeo_dim.begin(), last = node_subgeo_dim.end();
		iter != last; iter++) {
      check_macro (prev_node_dim <= *iter, "nodes should be numbered by increasing subgeo dimension");
      prev_node_dim = *iter;
    }
  }
  // ------------------------------------------------------------------------
  // 5) compute n_vert (n_vert < nnod when order > 1) and set element indexes (K.dis_ie & K.ios_dis_ie)
  // ------------------------------------------------------------------------
  size_type n_vert = 0;
  if (base::_gs._map_dimension == 0) {
    n_vert = nnod;
  } else {
    std::vector<size_t> is_vertex (nnod, 0);
    size_type ie = 0;
    for (iterator iter = begin(base::_gs._map_dimension), last = end(base::_gs._map_dimension); iter != last; iter++, ie++) {
  	geo_element& K = *iter;
  	K.set_ios_dis_ie (ie);
  	K.set_dis_ie (ie);
        if (base::order() > 1) {
          for (size_type iloc = 0, nloc = K.size(); iloc < nloc; iloc++) {
            is_vertex [K[iloc]] = 1;
          }
        }
    }
    if (base::order() == 1) {
      n_vert = nnod;
    } else {
      n_vert = accumulate (is_vertex.begin(), is_vertex.end(), 0);
    }
  }
  // ------------------------------------------------------------------------
  // 6) create vertex-element (0d elements)
  // ------------------------------------------------------------------------
  geo_element::parameter_type param (reference_element::p, 1);
  base::_geo_element [reference_element::p].resize (n_vert, param);
  size_type first_iv = base::_node.ownership().first_index();
  {
    size_type iv = 0;
    for (iterator iter = begin(0), last = end(0); iter != last; iter++, iv++) {
      geo_element& P = *iter;
      P[0]            = first_iv + iv;
      P.set_dis_ie     (first_iv + iv); // TODO: P[0] & dis_ie redundant for `p'
      P.set_ios_dis_ie (first_iv + iv);
    }
  }
  // ownership_by_dimension[0]: used by connectivity
  base::_gs.ownership_by_variant   [reference_element::p] = base::_geo_element [reference_element::p].ownership();
  base::_gs.ownership_by_dimension [0] = base::_geo_element [reference_element::p].ownership();
  // ------------------------------------------------------------------------
  // 7) get faces & edge
  // ------------------------------------------------------------------------
  if (base::_gs._map_dimension > 0) {
    
    for (size_type side_dim = base::_gs._map_dimension - 1; side_dim >= 1; side_dim--) {
      for (size_type variant = reference_element::first_variant_by_dimension(side_dim);
                     variant < reference_element:: last_variant_by_dimension(side_dim); variant++) {
        geo_element::parameter_type param (variant, 1);
        base::_geo_element [variant].resize (hdr.dis_size_by_variant [variant], param);
        base::_geo_element [variant].get_values (ips);
        base::_gs.ownership_by_variant [variant] = base::_geo_element [variant].ownership();
      }
      size_type nsid = hdr.dis_size_by_dimension [side_dim];
      base::_gs.ownership_by_dimension [side_dim] = distributor (nsid, base::comm(), nsid);
      size_type isid = 0;
      for (iterator iter = begin(side_dim), last = end(side_dim); iter != last; iter++, isid++) {
        geo_element& S = *iter;
        S.set_ios_dis_ie (isid);
        S.set_dis_ie     (isid);
      }
    }
  }
  // ------------------------------------------------------------------------
  // 8) get domain, until end-of-file
  // ------------------------------------------------------------------------
  vector<index_set> ball [4];
  domain_indirect_basic<sequential> dom;
  while (dom.get (ips, *this, ball)) {
     base::_domains.push_back (dom);
  }
  // ------------------------------------------------------------------------
  // 9) set indexes on faces and edges of elements, for P2 approx
  // ------------------------------------------------------------------------
  set_element_side_index (1);
  set_element_side_index (2);
  // ------------------------------------------------------------------------
  // 10) bounding box: _xmin, _xmax
  // ------------------------------------------------------------------------
  base::compute_bbox();
  return ips;
}
// ----------------------------------------------------------------------------
// dump
// ----------------------------------------------------------------------------
template <class T>
void
geo_rep<T,sequential>::dump (std::string name)  const {
  std::ofstream os ((name + "-dump.geo").c_str());
  odiststream ods (os, base::_node.ownership().comm());
  put_geo (ods);
}
// ----------------------------------------------------------------------------
// read from file
// ----------------------------------------------------------------------------
template <class T>
void
geo_rep<T,sequential>::load (std::string filename, const communicator&) 
{
  idiststream ips;
  ips.open (filename, "geo");
  check_macro(ips.good(), "\"" << filename << "[.geo[.gz]]\" not found.");
  get (ips);
  std::string root_name = delete_suffix (delete_suffix(filename, "gz"), "geo");
  std::string name = get_basename (root_name);
  base::_name = name;
}
// ----------------------------------------------------------------------------
// instanciation in library
// ----------------------------------------------------------------------------
template class geo_rep<Float,sequential>;
template idiststream& geo_basic<Float,sequential>::get (idiststream&);

} // namespace rheolef