~ubuntu-branches/ubuntu/trusty/rheolef/trusty-proposed

« back to all changes in this revision

Viewing changes to nfem/lib/geo.cc

  • Committer: Bazaar Package Importer
  • Author(s): Christophe Prud'homme
  • Date: 2010-06-12 09:08:59 UTC
  • Revision ID: james.westby@ubuntu.com-20100612090859-8gpm2gc7j3ab43et
Tags: upstream-5.89
ImportĀ upstreamĀ versionĀ 5.89

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
///
 
2
/// This file is part of Rheolef.
 
3
///
 
4
/// Copyright (C) 2000-2009 Pierre Saramito <Pierre.Saramito@imag.fr>
 
5
///
 
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.
 
10
///
 
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.
 
15
///
 
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
 
19
///
 
20
/// =========================================================================
 
21
//
 
22
// geo
 
23
//
 
24
// authors:
 
25
//      Nicolas.Roquet@imag.fr
 
26
//      Pierre.Saramito@imag.fr
 
27
//
 
28
// date: 12 may 1997
 
29
//
 
30
//   added label_interface and build_subregion for updating meshes for 
 
31
//   multi-region problems. J.Etienne@damtp.cam.ac.uk, 19/9/2006
 
32
//
 
33
// ============================================================================
 
34
//  includes
 
35
// ============================================================================
 
36
 
 
37
#include "rheolef/georep.h"
 
38
#include "rheolef/iorheo.h"
 
39
#include "rheolef/rheostream.h" // i/o utility
 
40
#include "rheolef/tiny_element.h"
 
41
#include "rheolef/tensor.h"
 
42
#include "geo-connectivity.h"
 
43
#include <string>
 
44
using namespace std;
 
45
 
 
46
// ============================================================================
 
47
//  utilities
 
48
// ============================================================================
 
49
 
 
50
template<class T>
 
51
class array2 {
 
52
public:
 
53
    typedef vector<int>::size_type size_type;
 
54
    array2() {}
 
55
    T& operator[](size_type i) { return _t[i]; }
 
56
    const T& operator[](size_type i) const { return _t[i]; }
 
57
protected:
 
58
    T _t[2];
 
59
};
 
60
template<class T>
 
61
class bidimmensional_array {
 
62
public:
 
63
    typedef vector<int>::size_type size_type;
 
64
    bidimmensional_array(size_type ni=0, size_type nj=0)
 
65
      : _nj(nj), _t(ni*nj) {}
 
66
    void resize (size_type ni, size_type nj) { _nj = nj; _t.resize(ni*nj); }
 
67
    T* operator[](size_type i) { return _t.begin() + i*_nj; }
 
68
    T* operator()(size_type i) { return operator[](i); }
 
69
    T& operator()(size_type i, size_type j) { return _t[i*_nj+j]; }
 
70
protected:
 
71
    size_type _nj;
 
72
    vector<T>    _t;
 
73
};
 
74
// ============================================================================
 
75
//  coordinate system mini-handler
 
76
// ============================================================================
 
77
string
 
78
georep::coordinate_system () const
 
79
{
 
80
    return fem_helper::coordinate_system_name (_coord_sys);
 
81
}
 
82
void
 
83
georep::set_coordinate_system (const string& name)
 
84
{
 
85
    _coord_sys = fem_helper::coordinate_system(name);
 
86
}
 
87
// ============================================================================
 
88
//  constructors
 
89
// ============================================================================
 
90
 
 
91
georep::georep(const georep& g)
 
92
 : occurence(),
 
93
   Vector<geo_element>(g),
 
94
   _name(g._name),
 
95
   _number(g._number),
 
96
   _serial_number(g._serial_number),
 
97
   _dim(g._dim),
 
98
   _coord_sys(g._coord_sys),
 
99
   _x(g._x),
 
100
   _domlist(g._domlist),
 
101
   _xmin(g._xmin),
 
102
   _xmax(g._xmax),
 
103
   _save_double_precision(g._save_double_precision),
 
104
   _version(g._version),
 
105
   _tree(),
 
106
   _h(),
 
107
   _h1d(),
 
108
   _localizer_initialized(false),
 
109
   _boundary(g._boundary),
 
110
   _boundary_initialized(g._boundary_initialized)
 
111
{
 
112
    for (size_type i = 0; i < 4; i++)
 
113
        _count_geo[i] = g._count_geo[i];
 
114
    for (size_type i = 0; i < reference_element::max_size; i++)
 
115
        _count_element[i] = g._count_element[i];
 
116
}
 
117
// ----------------------------------------------------------------------------
 
118
// cstor from file name
 
119
// ----------------------------------------------------------------------------
 
120
 
 
121
void
 
122
georep::reset_counters ()
 
123
{
 
124
   fill(_count_geo, _count_geo+4, 0);
 
125
   fill(_count_element, _count_element+reference_element::max_size, 0);
 
126
}
 
127
georep::georep(const string& a_file_name, const string& coord_sys_name)
 
128
  : occurence(),
 
129
    Vector<geo_element>(),
 
130
    _name(), 
 
131
    _number(numeric_limits<size_type>::max()),
 
132
    _serial_number(numeric_limits<size_type>::max()),
 
133
    _dim(0), 
 
134
    _coord_sys(fem_helper::coordinate_system(coord_sys_name)),
 
135
    _x(), 
 
136
    _domlist(), 
 
137
    _xmin(),
 
138
    _xmax(),
 
139
   _save_double_precision(false),
 
140
    _version(0),
 
141
    _tree(),
 
142
    _h(),
 
143
    _h1d(),
 
144
    _localizer_initialized(false),
 
145
    _boundary(),
 
146
    _boundary_initialized()
 
147
{
 
148
  reset_counters ();
 
149
  string file_name = a_file_name;
 
150
  irheostream is(file_name, "geo");
 
151
  if (!is.good()||(file_name.find("field")!=string::npos))
 
152
   {
 
153
        warning_macro("\"" << file_name << "[.geo[.gz]]\" not found, trying for \"" << file_name << "[.[m]field[.gz]]\".");
 
154
        is.open(file_name, "mfield");
 
155
        if (!is.good()) is.open(file_name, "field");
 
156
        check_macro(is.good(), "\"" << file_name << "[.geo[.gz]]\" not found.");
 
157
        scatch(is,"\nfield");
 
158
        int version;
 
159
        size_type ndof;
 
160
        is >> version >> ndof >> file_name;
 
161
        is.open(file_name,"geo");
 
162
        check_macro(is.good(), "\"" << file_name << "[.geo[.gz]]\" not found.");
 
163
   }
 
164
  string root_name = delete_suffix (delete_suffix(file_name, "gz"), "geo");
 
165
  string base_name = get_basename (root_name);
 
166
  string::size_type i = base_name.find_last_of ('+');
 
167
  string::size_type j = base_name.find_last_of ('-');
 
168
  string::size_type l = base_name.length();
 
169
  if (j<i) j=l;
 
170
  if (i<l) 
 
171
   {
 
172
        string digits ="0123456789";
 
173
        string tmp =string(base_name, i+1, j-i-1);
 
174
        if (tmp.find_first_not_of(digits)==string::npos)
 
175
                _number =atoi(tmp.c_str());
 
176
        else // it is not a valid version number
 
177
         {
 
178
                warning_macro(tmp << " is not a valid mesh number in filename " << base_name);
 
179
                i=l; j=l;
 
180
         }
 
181
        if (j<l)
 
182
         {
 
183
                tmp =string(base_name, j+1, l-j-1);
 
184
                if (tmp.find_first_not_of(digits)==string::npos)
 
185
                        _serial_number =atoi(tmp.c_str());
 
186
                else
 
187
                 {
 
188
                        warning_macro(tmp << " is not a valid mesh serial number in filename " << base_name);
 
189
                        i=l; j=l; _number=numeric_limits<size_type>::max();
 
190
                 }
 
191
         }
 
192
        base_name = string(base_name, 0, i);
 
193
   }
 
194
  is >> setbasename(base_name) >> *this; // load data
 
195
  fem_helper::check_coord_sys_and_dimension (_coord_sys, _dim);
 
196
  _name = base_name;
 
197
}
 
198
// ----------------------------------------------------------------------------
 
199
// Cstructor from point list and former geo
 
200
// ----------------------------------------------------------------------------
 
201
 
 
202
georep::georep (const nodelist_type& p, const georep& g)
 
203
 : occurence(),
 
204
   Vector<geo_element>(g),
 
205
   _name(g._name),
 
206
   _number(numeric_limits<size_type>::max()),
 
207
   _serial_number(numeric_limits<size_type>::max()),
 
208
   _dim(g._dim),
 
209
   _coord_sys(g._coord_sys),
 
210
   _x(p),
 
211
   _domlist(g._domlist),
 
212
   _xmin(),
 
213
   _xmax(),
 
214
   _save_double_precision(g._save_double_precision),
 
215
   _version(g._version),
 
216
   _tree(),
 
217
   _h(),
 
218
   _h1d(),
 
219
   _localizer_initialized(false),
 
220
   _boundary(g._boundary),
 
221
   _boundary_initialized(g._boundary_initialized)
 
222
{
 
223
  for (size_type j = 0; j < _dim; j++) {
 
224
    _xmin[j] =  numeric_limits<Float>::max();
 
225
    _xmax[j] = -numeric_limits<Float>::max();
 
226
  }
 
227
  for (size_type j = _dim+1; j < 3; j++) {
 
228
    _xmin [j] = _xmax [j] = 0;
 
229
  }
 
230
  nodelist_type::const_iterator iter_p = p.begin();
 
231
  nodelist_type::const_iterator last_p = p.end();
 
232
 
 
233
  while (iter_p != last_p) {
 
234
    const point& p = *iter_p++;
 
235
    for (size_type j = 0 ; j < _dim; j++) {
 
236
      _xmin[j] = min(p[j], _xmin[j]);
 
237
      _xmax[j] = max(p[j], _xmax[j]);
 
238
    }
 
239
  }
 
240
 
 
241
  if (g._number == numeric_limits<size_type>::max())
 
242
        _number = 1;
 
243
  else
 
244
        _number = g._number+1;
 
245
  _serial_number = numeric_limits<size_type>::max();
 
246
  
 
247
  for (size_type i = 0; i < 4; i++)
 
248
        _count_geo[i] = g._count_geo[i];
 
249
  for (size_type i = 0; i < reference_element::max_size; i++)
 
250
        _count_element[i] = g._count_element[i];
 
251
}
 
252
// ----------------------------------------------------------------------------
 
253
//  cstor from domain
 
254
// ----------------------------------------------------------------------------
 
255
 
 
256
georep::georep(const georep& g, const domain& d)
 
257
  : occurence(),
 
258
    Vector<geo_element>(d.size()),
 
259
    _name(d.name()),
 
260
    _number(numeric_limits<size_type>::max()),
 
261
    _serial_number(numeric_limits<size_type>::max()),
 
262
    _dim(g.dimension()),
 
263
    _coord_sys(g._coord_sys),
 
264
    _x(),
 
265
    _domlist(),
 
266
    _xmin(),
 
267
    _xmax(),
 
268
    _save_double_precision(g._save_double_precision),
 
269
    _version(2),
 
270
    _tree(),
 
271
    _h(),
 
272
    _h1d(),
 
273
    _localizer_initialized(false),
 
274
    _boundary(),
 
275
    _boundary_initialized()
 
276
{
 
277
  g.may_have_version_2();
 
278
 
 
279
  // step 0 : rename the mesh
 
280
 
 
281
  _name = d.name() + "_from_" + g.name() ;
 
282
 
 
283
  // step 1 : numbering of vertices
 
284
 
 
285
  vector<bool> node_on_d (g.n_node(), false);
 
286
  domain::const_iterator last_side = d.end();
 
287
  for (domain::const_iterator i = d.begin(); i != last_side; i++) {
 
288
 
 
289
      const geo_element& S = *i;
 
290
      for (size_type j = 0; j < S.size(); j++)
 
291
        node_on_d [S[j]] = true ;
 
292
  }
 
293
  size_type nvertex = 0;
 
294
  vector<size_type> new_vertex_idx(g.n_node(), numeric_limits<size_type>::max());
 
295
  for (size_type i = 0; i < g.n_node(); i++) {
 
296
      if (node_on_d[i]) {
 
297
        new_vertex_idx[i] = nvertex++ ;
 
298
      }
 
299
  }
 
300
  for (size_type j = 0; j < _dim; j++) {
 
301
    _xmin[j] =  numeric_limits<Float>::max();
 
302
    _xmax[j] = -numeric_limits<Float>::max();
 
303
  }
 
304
  for (size_type j = _dim+1; j < 3; j++) {
 
305
    _xmin [j] = _xmax [j] = 0;
 
306
  }
 
307
  _x.resize(nvertex);
 
308
  size_type i_g_node = 0;
 
309
  iterator_node iter_node = begin_node() ;
 
310
  for (const_iterator_node iter_g_node = g.begin_node(); iter_g_node != g.end_node(); iter_g_node++, i_g_node++) {
 
311
      if (node_on_d[i_g_node]) {
 
312
          *iter_node = *iter_g_node;
 
313
          point& p = *iter_node;
 
314
          for (size_type j = 0 ; j < _dim; j++) {
 
315
              _xmin[j] = min(p[j], _xmin[j]);
 
316
              _xmax[j] = max(p[j], _xmax[j]);
 
317
          }
 
318
          iter_node++;
 
319
      }
 
320
  }
 
321
  // step 2 : copy geo_element from "d" into geo_element of *this
 
322
  reset_counters ();
 
323
  _count_geo     [0] = n_node();
 
324
  _count_element [0] = n_node();
 
325
  resize(d.size());
 
326
  size_type K_idx = 0;
 
327
  iterator iter_elt = begin(); 
 
328
  for (domain::const_iterator iter_side = d.begin(); 
 
329
        iter_side != last_side; 
 
330
        iter_side++, K_idx++, iter_elt++) {
 
331
 
 
332
      const geo_element& S = *iter_side;
 
333
      geo_element&       K = *iter_elt;
 
334
      K.set_type(S.type()) ;
 
335
      K.set_index (K_idx);
 
336
      for (size_type i = 0; i < K.size(); i++) {
 
337
          K[i] = new_vertex_idx [S[i]];
 
338
      }
 
339
      // update counters
 
340
      _count_geo    [K.dimension()]++;
 
341
      _count_element[K.type()]++;
 
342
  }
 
343
  build_connectivity (*this);
 
344
}
 
345
 
 
346
// ============================================================================
 
347
// modifiers
 
348
// ============================================================================
 
349
void
 
350
georep::build_subregion(const domain& start_from, const domain& dont_cross, 
 
351
        std::string name, std::string name_of_complement) 
 
352
{
 
353
    if (has_domain(name)) 
 
354
     {
 
355
        if (name_of_complement=="" || has_domain(name_of_complement))
 
356
         {
 
357
            warning_macro("Domain `" << name << "' already exists! Not overwriting.");
 
358
            return;
 
359
         }
 
360
        else
 
361
            error_macro("Domain `" << name << "' already exists, but not `"<<name_of_complement<<"'!");
 
362
     }
 
363
    else if (name_of_complement!="" && has_domain(name_of_complement))
 
364
        error_macro("Domain `" << name_of_complement << "' already exists, but not `"<<name<<"'!");
 
365
    bool update_complement=(name_of_complement!="");
 
366
    vector<set<size_type> > ball (n_node());
 
367
    build_point_to_element_sets (begin(), end(), ball.begin());
 
368
    // remember which are the vertices we don't want to cross
 
369
    set< size_type > no_way_vertices;
 
370
    domain::const_iterator iE=dont_cross.begin();
 
371
    domain::const_iterator eE=dont_cross.end();
 
372
    for ( ; iE!=eE; iE++) 
 
373
      for (size_type i=0; i<(*iE).size(); i++)
 
374
        no_way_vertices.insert((*iE)[i]);
 
375
    // a list to remember the furthest we went in our exploration so far
 
376
    slist< size_type > frontier_dofs; // contains dofs
 
377
    // ...and a set to mark elemnts we've seen already
 
378
    set< size_type > elementa_cognita; // contains element indices
 
379
    // take a vertex in start_from to start with:
 
380
    domain::const_iterator i_start=start_from.begin();
 
381
    domain::const_iterator i_start_end=start_from.end();
 
382
    size_type v=(*i_start)[0];
 
383
    while (no_way_vertices.count(v)!=0)
 
384
    {
 
385
      i_start++;
 
386
      check_macro(i_start!=i_start_end, "No domain found between " << start_from.name() << " and " 
 
387
        << dont_cross.name() );
 
388
      v=(*i_start)[0];
 
389
    }
 
390
    frontier_dofs.push_front(v);
 
391
    do
 
392
    {
 
393
      v=*(frontier_dofs.begin());
 
394
      frontier_dofs.pop_front();
 
395
      set<size_type>::const_iterator iK=ball[v].begin();
 
396
      set<size_type>::const_iterator eK=ball[v].end();
 
397
      for (; iK!=eK; iK++)
 
398
        if (elementa_cognita.count(*iK)==0)
 
399
        {
 
400
          elementa_cognita.insert(*iK);
 
401
          for (size_type i=0; i<begin()[*iK].size(); i++)
 
402
            if ( (begin()[*iK][i]!=v) && (no_way_vertices.count(begin()[*iK][i])==0) )
 
403
              frontier_dofs.push_front(begin()[*iK][i]);
 
404
        }
 
405
    } while (!frontier_dofs.empty());
 
406
    // region has been explored, now fill in domain structures for it and its complement
 
407
    domain region, c_region;
 
408
    region.set_name(name);
 
409
    region.set_dimension(_dim);
 
410
    c_region.set_name(name_of_complement);
 
411
    c_region.set_dimension(_dim);
 
412
    const_iterator iK=begin();
 
413
    const_iterator eK=end();
 
414
    for ( ; iK!=eK; iK++)
 
415
        if (elementa_cognita.count((*iK).index())==0) 
 
416
          c_region.push_back(*iK);
 
417
        else
 
418
          region.push_back(*iK);
 
419
    // insert regions in domain list
 
420
    _domlist.push_back(region);
 
421
    if (update_complement) _domlist.push_back(c_region);
 
422
}
 
423
 
 
424
// ============================================================================
 
425
// hazel initialization
 
426
// ============================================================================
 
427
void
 
428
georep::init_localizer (const domain& boundary, Float tolerance, int list_size) const
 
429
{
 
430
    if (_localizer_initialized)
 
431
        return;
 
432
    switch (dimension()) {
 
433
    case 1 : 
 
434
      _h1d.initialize (*this);
 
435
      break;
 
436
    case 2 : 
 
437
      _h.grow (begin(), end(), _x.begin(), _x.end(), 
 
438
               boundary.begin(), boundary.end(),
 
439
               size(), dimension(), xmin(), xmax(),
 
440
               tolerance, list_size);
 
441
      break;
 
442
    case 3 :
 
443
      _tree.initialize (map_dimension(), xmin(), xmax(),
 
444
        n_vertex(), begin_node(), size(), begin());
 
445
      break;
 
446
    default : error_macro("localizer not defined in "  << dimension() << "D");
 
447
    }
 
448
    _localizer_initialized = true;
 
449
}
 
450
// ============================================================================
 
451
//  access
 
452
// ============================================================================
 
453
 
 
454
//
 
455
// index by domain
 
456
//
 
457
bool 
 
458
georep::has_domain (const string& domname) const
 
459
{
 
460
  domlist_type::const_iterator iter = _domlist.begin();
 
461
  domlist_type::const_iterator last = _domlist.end();
 
462
  while (iter != last) {
 
463
    const domain& dom = *iter;
 
464
    if (domname == dom.name())
 
465
      return true;
 
466
    ++iter;
 
467
  }
 
468
  return false;
 
469
}
 
470
const domain&
 
471
georep::operator[] (const string& domname) const
 
472
{
 
473
  domlist_type::const_iterator iter = _domlist.begin();
 
474
  domlist_type::const_iterator last = _domlist.end();
 
475
  while (iter != last) {
 
476
    const domain& dom = *iter;
 
477
    if (domname == dom.name())
 
478
      return dom;
 
479
    ++iter;
 
480
  }
 
481
  error_macro ("geo: undefined domain `" << domname << "'");
 
482
 
 
483
  return *iter;// for no warning at compile time
 
484
}
 
485
// ============================================================================
 
486
// upgrade
 
487
// ============================================================================
 
488
 
 
489
void
 
490
georep::upgrade()
 
491
{
 
492
    if (_version >= 2) {
 
493
        // already done
 
494
        return;
 
495
    }
 
496
    build_connectivity (*this);
 
497
    _version = 2;
 
498
}
 
499
// ============================================================================
 
500
// inquire
 
501
// ============================================================================
 
502
 
 
503
georep::size_type
 
504
georep::map_dimension() const
 
505
{
 
506
    for (size_type d = 3; d >= 0; d--) {
 
507
        if (_count_geo [d] != 0) {
 
508
            return d;
 
509
        }
 
510
    }
 
511
    // has no elements...
 
512
    return _dim;
 
513
}
 
514
 
 
515
Float
 
516
georep::hmin() const 
 
517
{
 
518
    may_have_version_2();
 
519
    const_iterator_node p = begin_node();
 
520
    const_iterator iter_elt = begin();
 
521
    const_iterator last_elt = end();
 
522
    Float hm2 = numeric_limits<Float>::max();
 
523
    while (iter_elt != last_elt) {
 
524
        const geo_element& K = *iter_elt++;
 
525
        for (size_type e = 0; e < K.n_edge(); e++) {
 
526
            size_type i1 = K.subgeo_vertex (1, e, 0);
 
527
            size_type i2 = K.subgeo_vertex (1, e, 1);
 
528
            hm2 = min(hm2, norm2(p[i1] - p[i2]));
 
529
        }
 
530
    }
 
531
    return sqrt(hm2);
 
532
}
 
533
Float
 
534
georep::hmax() const 
 
535
{
 
536
    may_have_version_2();
 
537
    const_iterator_node p = begin_node();
 
538
    const_iterator iter_elt = begin();
 
539
    const_iterator last_elt = end();
 
540
    Float hm2 = 0;
 
541
    while (iter_elt != last_elt) {
 
542
        const geo_element& K = *iter_elt++;
 
543
        for (size_type e = 0; e < K.n_edge(); e++) {
 
544
            size_type i1 = K.subgeo_vertex (1, e, 0);
 
545
            size_type i2 = K.subgeo_vertex (1, e, 1);
 
546
            hm2 = max(hm2, norm2(p[i1] - p[i2]));
 
547
        }
 
548
    }
 
549
    return sqrt(hm2);
 
550
}
 
551
// =================================================================
 
552
// hatter and dehatter:
 
553
//  F : hat(K) --> K is a nonlinear transformation
 
554
// that depends upon the degree of the polynomial basis
 
555
// => depend on the "space" class
 
556
// => cannot be handled by the "geo" class
 
557
// => hatter and dehatter may move to the "piola" class (TODO)
 
558
// =================================================================
 
559
meshpoint 
 
560
georep::hatter (const point& x, size_type K_idx) const
 
561
{
 
562
    const geo_element& K = element(K_idx);
 
563
    switch(begin()[K_idx].type()) {
 
564
        case geo_element::e: {
 
565
            double a = begin_node()[begin()[K_idx][0]][0];
 
566
            double b = begin_node()[begin()[K_idx][1]][0];
 
567
            return meshpoint(K_idx, point((x[0] - a)/(b-a)));
 
568
        }         
 
569
        case geo_element::t: {
 
570
            point a = begin_node()[begin()[K_idx][0]];
 
571
            point b = begin_node()[begin()[K_idx][1]];
 
572
            point c = begin_node()[begin()[K_idx][2]];
 
573
            point xx=x;
 
574
            Float t9 = 1/(-b[0]*c[1]+b[0]*a[1]+a[0]*c[1]+c[0]*b[1]-c[0]*a[1]-a[0]*b[1]);
 
575
            Float t11 = -a[0]+xx[0];
 
576
            Float t15 = -a[1]+xx[1];
 
577
 
 
578
            return meshpoint(K_idx, 
 
579
                point((-c[1]+a[1])*t9*t11-(-c[0]+a[0])*t9*t15,
 
580
                      (b[1]-a[1])*t9*t11-(b[0]-a[0])*t9*t15,
 
581
                       0));
 
582
        }
 
583
        // ICI
 
584
        case geo_element::T: {
 
585
            const point& a = vertex(K[0]);
 
586
            const point& b = vertex(K[1]);
 
587
            const point& c = vertex(K[2]);
 
588
            const point& d = vertex(K[3]);      
 
589
            tensor A;
 
590
            point ax;
 
591
            for (size_t i = 0; i < 3; i++) {
 
592
              ax[i]  = x[i]-a[i];
 
593
              A(i,0) = b[i]-a[i];
 
594
              A(i,1) = c[i]-a[i];
 
595
              A(i,2) = d[i]-a[i];
 
596
            }
 
597
            tensor inv_A;
 
598
            bool is_singular = ! invert_3x3 (A, inv_A);
 
599
            check_macro(!is_singular, "hatter: singular transformation in element: " << K.index());
 
600
            point hat_x = inv_A*ax;
 
601
            return meshpoint(K_idx, hat_x); 
 
602
        }         
 
603
        default : error_macro("hatter: element not yet implemented: " << K.name());
 
604
     }
 
605
}
 
606
point
 
607
georep::dehatter (const meshpoint& S, bool is_a_vector) const
 
608
{
 
609
    switch(begin()[S.element()].type())
 
610
     {
 
611
        case geo_element::e: {
 
612
            double a = begin_node()[begin()[S.element()][0]][0];
 
613
            double b = begin_node()[begin()[S.element()][1]][0];
 
614
            return point(a + S.hat()[0]*(b-a));
 
615
        }         
 
616
        case geo_element::t: {
 
617
            point a = begin_node()[begin()[S.element()][0]];
 
618
            point b = begin_node()[begin()[S.element()][1]];
 
619
            point c = begin_node()[begin()[S.element()][2]];
 
620
            return ((!is_a_vector)?a:point(0,0)) + (b-a)*S.hat()[0]
 
621
                                                 + (c-a)*S.hat()[1];
 
622
        }
 
623
        case geo_element::T: {
 
624
            point a = begin_node()[begin()[S.element()][0]];
 
625
            point b = begin_node()[begin()[S.element()][1]];
 
626
            point c = begin_node()[begin()[S.element()][2]];
 
627
            point d = begin_node()[begin()[S.element()][3]];
 
628
            return ((!is_a_vector)?a:point(0,0)) + (b-a)*S.hat()[0] 
 
629
                                                 + (c-a)*S.hat()[1]
 
630
                                                 + (d-a)*S.hat()[2];
 
631
        }
 
632
        default : error_macro("dehatter: element not yet implemented: " 
 
633
              << begin()[S.element()].name());
 
634
     }
 
635
}
 
636
// ============================================================================
 
637
// localizer
 
638
// ============================================================================
 
639
bool 
 
640
georep::localize (const point& x, geo_element::size_type& K_idx) const
 
641
{
 
642
  switch (dimension()) {
 
643
    case 1 : 
 
644
      K_idx = _h1d.localize(*this, x[0]);
 
645
      return (K_idx != numeric_limits<hazel_1d::size_type>::max());
 
646
    case 2 : 
 
647
      return _h.localize(x, K_idx);
 
648
    case 3 :
 
649
warning_macro ("localize("<<x<<") = " << K_idx);
 
650
      K_idx = _tree.search_element_containing (begin(), x);
 
651
      return (K_idx != numeric_limits<size_t>::max());
 
652
    default : error_macro("localizer not defined in " << dimension() << "D");
 
653
  }
 
654
  return false;
 
655
}
 
656
void 
 
657
georep::localize_nearest (const point& x, point& y, geo_element::size_type& element) const
 
658
{
 
659
  switch (dimension()) {
 
660
    case 1 : 
 
661
        _h1d.localize_nearest (*this, x[0], y[0], element);
 
662
        return;
 
663
    case 2 : 
 
664
        return _h.localize_nearest (x, y, element);
 
665
    case 3 : // TODO
 
666
        element = _tree.find_close_element (begin(), x, y);
 
667
        return;
 
668
    default : error_macro("localizer/nearest not defined in " << dimension() << "D");
 
669
  }
 
670
}
 
671
bool 
 
672
georep::trace (const point& x0, const point& v, point& x, Float& t, size_type& element) const
 
673
{
 
674
  switch (dimension()) {
 
675
    case 1 : 
 
676
      return _h1d.trace (*this, x0[0], v[0], x[0], t, element);
 
677
    case 2 : 
 
678
      return _h.trace(x0, v, x, t, element);
 
679
    case 3 : // TODO
 
680
    default : error_macro("localizer/trace not defined in 3D");
 
681
  }
 
682
  return false;
 
683
}
 
684
// ============================================================================
 
685
//  basic input/output
 
686
// ============================================================================
 
687
 
 
688
// ----------------------------------------------------------------------------
 
689
//  output
 
690
// ----------------------------------------------------------------------------
 
691
 
 
692
void
 
693
georep::save() const
 
694
{
 
695
    orheostream file (name(), "geo");
 
696
    put(file);
 
697
}
 
698
ostream&
 
699
georep::dump (ostream& os) const
 
700
{
 
701
  os << "dump mesh" << endl
 
702
     << "name " << _name << endl
 
703
     << "version " << _version << endl
 
704
     << "dimension " << _dim << endl
 
705
     << "xmin " << _xmin << endl
 
706
     << "xmax " << _xmax << endl
 
707
    ;
 
708
  for (size_type i = 0; i < 4; i++)
 
709
     os << "count_geo[" << i << "] = " << _count_geo[i] << endl;
 
710
  for (size_type i = 0; i < reference_element::max_size; i++)
 
711
     os << "count_element[" << i << "] = " << _count_element[i] << endl;
 
712
 
 
713
  size_type i = 0;
 
714
  os << "n_vertex " << _x.size() << endl;
 
715
  for (const_iterator_node iter_p = _x.begin(); iter_p != _x.end(); iter_p++, i++) {
 
716
      os << "x[" << i << "] = ";
 
717
      (*iter_p).put (os, _dim);
 
718
      os << endl ;
 
719
  }
 
720
  i = 0;
 
721
  os << "n_element " << size() << endl;
 
722
  for (const_iterator iter_e = begin(); iter_e != end(); iter_e++, i++) {
 
723
      os << "E[" << i << "]: ";
 
724
      (*iter_e).dump(os);
 
725
  }
 
726
  os << "n_domain " << _domlist.size() << endl;
 
727
  for (domlist_type::const_iterator i = _domlist.begin(); i != _domlist.end(); i++) {
 
728
        (*i).dump();
 
729
  }
 
730
  return os;
 
731
}
 
732
ostream& georep::put(ostream& s) const
 
733
{
 
734
  size_type map_d = map_dimension();
 
735
  //
 
736
  // put header
 
737
  //
 
738
  s << "#!geo" << endl 
 
739
    << "mesh" << endl ;
 
740
 
 
741
  s << version() << " " << dimension() << " " << n_node() << " " << size();
 
742
  if (version() >= 2) {
 
743
    if (dimension() >= 3) {
 
744
        if (map_d >= 3) {
 
745
                s << " " << n_face();
 
746
        } else {
 
747
                s << " 0";
 
748
        }
 
749
    }
 
750
    if (dimension() >= 2) {
 
751
        if (map_d >= 2) {
 
752
            s << " " << n_edge();
 
753
        } else {
 
754
                s << " 0";
 
755
        }
 
756
    }
 
757
  }
 
758
  s << endl ;
 
759
  if (version() >= 3) {
 
760
    s << "coordinate_system " << coordinate_system() << endl;
 
761
  }
 
762
  s << endl ;
 
763
  //
 
764
  // put vertices
 
765
  //
 
766
  if (_save_double_precision) s << setprecision(numeric_limits<Float>::digits10);
 
767
  const_iterator_node iter_p = begin_node();
 
768
  const_iterator_node last_p = end_node();
 
769
  while (iter_p != last_p) {
 
770
      const point& p = *iter_p++;
 
771
      p.put (s, dimension());
 
772
      s << endl ;
 
773
  }
 
774
  s << endl ;
 
775
  //
 
776
  // put element
 
777
  //
 
778
  const_iterator iter_e = begin();
 
779
  const_iterator last_e = end();
 
780
  while (iter_e != last_e) {
 
781
      s << (*iter_e) << endl;
 
782
      iter_e++;
 
783
  }
 
784
  s << endl ;
 
785
  //
 
786
  // put faces
 
787
  //
 
788
  if (version() >= 2 && map_d >= 3) {
 
789
      vector<geo_element> f (n_face());
 
790
      const_iterator last_elt = end();
 
791
      for (const_iterator iter_elt = begin(); iter_elt != last_elt; iter_elt++) {
 
792
          const geo_element& K = *iter_elt;
 
793
          for (size_type i = 0; i < K.n_face(); i++) {
 
794
              size_type idx = K.subgeo (2, i);
 
795
              if (f [idx].type() == reference_element::max_size) {
 
796
                // not yet builded:
 
797
                K.build_subgeo (2, i, f[idx]);
 
798
              }
 
799
          }
 
800
      }
 
801
      for (size_type j = 0; j < n_face(); j++) {
 
802
        s << f[j] << endl;
 
803
      }
 
804
      s << endl;
 
805
  }
 
806
  //
 
807
  // put edges
 
808
  //
 
809
  if (version() >= 2 && map_d >= 2) {
 
810
      vector<size_type> v1(n_edge());
 
811
      vector<size_type> v2(n_edge());
 
812
      const_iterator last_elt = end();
 
813
      for (const_iterator iter_elt = begin(); iter_elt != last_elt; iter_elt++) {
 
814
          const geo_element& K = *iter_elt;
 
815
          for (size_type i = 0; i < K.n_edge(); i++) {
 
816
              v1 [K.edge(i)] = K.subgeo_vertex (1, i, 0);
 
817
              v2 [K.edge(i)] = K.subgeo_vertex (1, i, 1);
 
818
          }
 
819
      }
 
820
      for (size_type j = 0; j < n_edge(); j++) {
 
821
        s << v1[j] << " " << v2[j] << "\n" ;
 
822
      }
 
823
      s << endl ;
 
824
  }
 
825
  //
 
826
  // put domains
 
827
  //
 
828
  domlist_type::const_iterator iter = _domlist.begin();
 
829
  domlist_type::const_iterator last = _domlist.end();
 
830
  while (iter != last) s << endl << *iter++;
 
831
  s << endl ;
 
832
 
 
833
  return s ;
 
834
}
 
835
// =======================================================================
 
836
// check
 
837
// =======================================================================
 
838
 
 
839
void 
 
840
georep::check() const
 
841
{
 
842
warning_macro ("checking geo: elements...");
 
843
    if (_version <= 1) {
 
844
warning_macro ("checking geo done (version <= 1).");
 
845
        return;
 
846
    }
 
847
    for (const_iterator i = begin(); i != end(); i++) {
 
848
        (*i).check();
 
849
        check(*i);
 
850
    }
 
851
warning_macro ("checking geo: domains...");
 
852
    domlist_type::const_iterator last = _domlist.end();
 
853
    for (domlist_type::const_iterator i = _domlist.begin(); i != last; i++) {
 
854
        (*i).check();
 
855
        for (domain::const_iterator j = (*i).begin(); j != (*i).end(); j++) {
 
856
            (*j).check();
 
857
            check(*j);
 
858
        }
 
859
    }
 
860
warning_macro ("checking geo done.");
 
861
}
 
862
void
 
863
georep::check (const geo_element& E) const
 
864
{
 
865
    for (size_type d = 0; d < E.dimension(); d++) {
 
866
        for (size_type i_subgeo = 0; i_subgeo < E.n_subgeo(d); i_subgeo++) {
 
867
            for (size_type i = 0; i < E.subgeo_size(d, i_subgeo); i++) {
 
868
                size_type idx = E.subgeo_vertex(d, i_subgeo, i);
 
869
                check_macro (idx < _count_geo[d], d << "D subgeo index `" << idx 
 
870
                  << " out of range 0:" << _count_geo[d]);
 
871
            }
 
872
        }
 
873
    }
 
874
}
 
875
// ----------------------------------------------------------------------------
 
876
//  input
 
877
// ----------------------------------------------------------------------------
 
878
 
 
879
istream&
 
880
get_nodes (
 
881
        istream& s, 
 
882
        georep::iterator_node iter_p, 
 
883
        georep::iterator_node last_p, 
 
884
        point& xmin, 
 
885
        point& xmax,
 
886
        georep::size_type dim)
 
887
{
 
888
  typedef georep::size_type size_type;
 
889
  for (size_type j = 0; j < dim; j++) {
 
890
    xmin[j] =  numeric_limits<Float>::max();
 
891
    xmax[j] = -numeric_limits<Float>::max();
 
892
  }
 
893
  for (size_type j = dim+1; j < 3; j++) {
 
894
    xmin [j] = xmax [j] = 0;
 
895
  }
 
896
  while (s.good() && iter_p != last_p) {
 
897
    point& p = *iter_p++;
 
898
    for (size_type j = 0 ; j < dim; j++) {
 
899
      s >> p[j] ; 
 
900
      xmin[j] = min(p[j], xmin[j]);
 
901
      xmax[j] = max(p[j], xmax[j]);
 
902
    }
 
903
    for (size_type j = dim; j < 3; j++)
 
904
      p [j] = 0;
 
905
  }
 
906
  return s;
 
907
}
 
908
istream&
 
909
georep::get_rheo(istream& is) 
 
910
{
 
911
  typedef georep::size_type size_type;
 
912
  bool verbose = iorheo::getverbose(is);
 
913
  
 
914
  if (!is.good()) error_macro("bad input stream for geo.");
 
915
  
 
916
  if (!scatch(is,"\nmesh"))
 
917
    error_macro("input stream does not contains a geo.");
 
918
  //
 
919
  // get header
 
920
  //
 
921
  size_type n_vert;
 
922
  size_type n_elt;
 
923
  size_type n_edg = 0;
 
924
  size_type n_fac = 0;
 
925
 
 
926
  is >> _version >> _dim >> n_vert >> n_elt;
 
927
  _x.resize(n_vert);
 
928
  resize(n_elt);
 
929
  if (_version == 1) {
 
930
      warning_macro ("obsolete format version 1");
 
931
  } else if (_version >= 2) {
 
932
      if (_dim >= 3) {
 
933
        is >> n_fac ;
 
934
      }
 
935
      if (_dim >= 2) {
 
936
        is >> n_edg ;
 
937
      }
 
938
  } else {
 
939
      fatal_macro("unknown mesh version " << _version);
 
940
  }
 
941
  if (_version >= 3) {
 
942
      if (!scatch(is,"\ncoordinate_system")) {
 
943
        error_macro("read geo version 3: `coordinate_system' expected");
 
944
      } else {
 
945
        string sys_coord;
 
946
        is >> sys_coord;
 
947
        set_coordinate_system (sys_coord);
 
948
      }
 
949
  }
 
950
  //
 
951
  // get coordinates
 
952
  //
 
953
  get_nodes (is, begin_node(), end_node(), _xmin, _xmax, _dim);
 
954
  if (!is.good()) return is;
 
955
  //
 
956
  // get elements
 
957
  //
 
958
  size_type idx = 0;
 
959
  reset_counters ();
 
960
  _count_geo     [0] = n_node();
 
961
  _count_element [0] = n_node();
 
962
  georep::iterator last_elt = end();
 
963
  for (georep::iterator i = begin(); is.good() && i != last_elt; i++, idx++) {
 
964
 
 
965
      is >> (*i);
 
966
      (*i).set_index (idx);
 
967
      _count_geo     [(*i).dimension()]++;
 
968
      _count_element [(*i).type()]++;
 
969
  }
 
970
  size_type map_d = map_dimension();
 
971
 
 
972
  vector<set<size_type> > ball (n_node());
 
973
  if (_version >= 2 && map_d > 0) {
 
974
  
 
975
      // TODO: _count_element [type]++
 
976
 
 
977
      ball.resize(n_node());
 
978
      build_point_to_element_sets (begin(), end(), ball.begin());
 
979
      if (map_d >= 3) { // get faces
 
980
          load_subgeo_numbering (begin(), ball.begin(), 2, n_fac, is,
 
981
                _count_geo, _count_element);
 
982
      }
 
983
      load_subgeo_numbering (begin(), ball.begin(), 1, n_edg, is,
 
984
                _count_geo, _count_element);
 
985
  }
 
986
  //
 
987
  // get domains
 
988
  //
 
989
  while (is.good()) {
 
990
      domain d;
 
991
      if (!(is >> d)) {
 
992
          break;
 
993
      }
 
994
      if (_version >= 2 && d.dimension() > 0 && size() > 0) {
 
995
        propagate_subgeo_numbering (d.begin(), d.end(), begin(), ball.begin());
 
996
      }
 
997
      _domlist.push_back(d);
 
998
  }
 
999
  return is;
 
1000
}
 
1001
istream&
 
1002
operator >> (istream& s, georep& m) 
 
1003
{
 
1004
    string basename = iorheo::getbasename(s);
 
1005
    if (basename.length() != 0) {
 
1006
        m._name = basename;
 
1007
    } else {
 
1008
        m._name = "unamed";
 
1009
        warning_macro ("unamed input mesh has been named `" << m._name << "'");
 
1010
    }
 
1011
    m.reset_counters ();
 
1012
    iorheo::flag_type fmt = iorheo::flags(s) & iorheo::format_field;
 
1013
    if      (fmt [iorheo::bamg])        { return m.get_bamg (s); }
 
1014
    else if (fmt [iorheo::grummp])      { return m.get_grummp (s); }
 
1015
    else if (fmt [iorheo::gmsh])        { return m.get_gmsh (s); }
 
1016
    else if (fmt [iorheo::mmg3d])       { return m.get_mmg3d (s); }
 
1017
    else if (fmt [iorheo::tetgen])      { return m.get_tetgen (s); }
 
1018
    else if (fmt [iorheo::qmg])         { return m.get_qmg (s); }
 
1019
    else if (fmt [iorheo::cemagref])    { return m.get_cemagref (s); }
 
1020
    else if (fmt [iorheo::vtkpolydata]) { return m.get_vtk_polydata (s); }
 
1021
    else                                { return m.get_rheo (s); }
 
1022
}
 
1023
void
 
1024
georep::may_have_version_2() const
 
1025
{
 
1026
    if (version() < 2) {
 
1027
        error_macro("geo version 2 requiered (see: geo -upgrade): " 
 
1028
                << _version << " founded");
 
1029
    }
 
1030
}
 
1031
// ----------------------------------------------------------------------------
 
1032
//  domain modifiers
 
1033
// ----------------------------------------------------------------------------
 
1034
void
 
1035
georep::erase_domain (const string& name) 
 
1036
{
 
1037
  for (domlist_type::iterator q = _domlist.begin(); q != _domlist.end(); q++) {
 
1038
    if (name == (*q).name()) {
 
1039
      _domlist.erase(q);
 
1040
      return;
 
1041
    }
 
1042
  }
 
1043
}
 
1044
void
 
1045
georep::insert_domain (const domain& d)
 
1046
{
 
1047
      _domlist.push_back(d);
 
1048
}
 
1049
// ============================================================
 
1050
//  construction of jump-interface domain data:
 
1051
// ============================================================
 
1052
void
 
1053
georep::jump_interface(const domain& interface, const domain& region, 
 
1054
        map<size_type,tiny_vector<size_type> >& special_elements, 
 
1055
        map<size_type,size_type>& node_global_to_interface) const
 
1056
{
 
1057
  check_macro((_dim==2)&&(interface.dimension()==1), "Only 2D implemented");
 
1058
  domain::const_iterator edge_i =interface.begin();
 
1059
  domain::const_iterator end_edges =interface.end();
 
1060
  set<size_type> n_tmp;
 
1061
  for ( ;  edge_i!=end_edges ; edge_i++)
 
1062
   {
 
1063
        n_tmp.insert((*edge_i)[0]);
 
1064
        n_tmp.insert((*edge_i)[1]);
 
1065
        //node_pair* pair0 = new node_pair((*edge_i)[0], 0); 
 
1066
        //if (!(node_global_to_interface.insert(*pair0).second)) (*pair0).~pair();
 
1067
        //node_pair* pair1 = new node_pair((*edge_i)[1], 0); 
 
1068
        //if (!(node_global_to_interface.insert(*pair1).second)) (*pair1).~pair();
 
1069
   }
 
1070
  set<size_type>::iterator n_tmp_i =n_tmp.begin();
 
1071
  set<size_type>::iterator end_n_tmp =n_tmp.end();
 
1072
  for ( size_type j=0 ; n_tmp_i != end_n_tmp ; n_tmp_i++, j++ )
 
1073
   {
 
1074
        //node_global_to_interface.insert(node_global_to_interface.end(),node_pair((*n_tmp_i),j));
 
1075
        node_global_to_interface.insert(make_pair((*n_tmp_i),j));
 
1076
   }
 
1077
  map<size_type,size_type>::iterator end_nodes =node_global_to_interface.end();
 
1078
  map<size_type,tiny_vector<size_type> >::iterator special_K;
 
1079
  domain::const_iterator ele_i =region.begin();
 
1080
  domain::const_iterator end_elements =region.end();
 
1081
  tiny_vector<size_type> *l_conn;
 
1082
  for ( ; ele_i != end_elements ; ele_i++)
 
1083
   {
 
1084
        bool already_inserted=false;
 
1085
        for (size_type j=0; j <(*ele_i).size(); j++)
 
1086
         {
 
1087
                map<size_type,size_type>::const_iterator node
 
1088
                        =node_global_to_interface.find((*ele_i)[j]);
 
1089
                if (node!=end_nodes)
 
1090
                 {
 
1091
                        if (!already_inserted)
 
1092
                         {
 
1093
                                already_inserted=true;
 
1094
                                l_conn= new tiny_vector<size_type>((*ele_i).size());
 
1095
                                (*l_conn).fill(numeric_limits<size_type>::max());
 
1096
                                special_K = special_elements.insert(
 
1097
                                        make_pair((*ele_i).index(),*l_conn)).first;
 
1098
                         }
 
1099
                        (*special_K).second[j] = (*node).second;
 
1100
                 }
 
1101
         }
 
1102
   }
 
1103
}
 
1104
// ============================================================================
 
1105
//  comparator
 
1106
// ============================================================================
 
1107
 
 
1108
// small cpu-time equality check
 
1109
// we base on name changing convention
 
1110
// when mesh change ! 
 
1111
bool
 
1112
georep::operator == (const georep& y) const
 
1113
{
 
1114
    // rought connectivity comparison
 
1115
    if (size() != y.size()) return false;
 
1116
    if (n_node() != y.n_node()) return false;
 
1117
    if (n_edge() != y.n_edge()) return false;
 
1118
    if (n_face() != y.n_face()) return false;
 
1119
    if (n_domain() != y.n_domain()) return false;
 
1120
 
 
1121
    // when only node coords change, we change the name !
 
1122
    if (name() != y.name()) return false;
 
1123
 
 
1124
    return true;
 
1125
}
 
1126
 
 
1127
// ============================================================================
 
1128
//   Boundary builders 
 
1129
// ============================================================================
 
1130
const domain&
 
1131
georep::boundary () const
 
1132
{
 
1133
    if (_boundary_initialized) return _boundary;
 
1134
    _boundary_initialized = true;
 
1135
    size_type d = dimension();
 
1136
    _boundary.set_name("boundary");
 
1137
    vector<set<size_type> > ball (n_node());
 
1138
    build_point_to_element_sets (begin(), end(), ball.begin());
 
1139
    build_boundary (begin(), end(), ball.begin(), d-1, _boundary);
 
1140
    return _boundary;
 
1141
}
 
1142
void
 
1143
georep::label_interface(const domain& dom1, const domain& dom2, const string& name)
 
1144
{    
 
1145
    // for 2D domains only
 
1146
    check_macro(dom1.dimension()==2 && dom2.dimension()==2, "only 2D domains supported"); 
 
1147
    geo_element K;
 
1148
    K.set_name('e');
 
1149
    domain interface;
 
1150
    interface.set_dimension(1); 
 
1151
    interface.set_name(name);
 
1152
    // first step: sort vertices of larger domain in a set
 
1153
    domain smaller, larger;
 
1154
    if (dom1.size()<dom2.size()) { smaller=dom1; larger=dom2; }
 
1155
        else { smaller=dom2; larger=dom1; }
 
1156
    set< size_type > larger_vertices;
 
1157
    domain::const_iterator iK=larger.begin();
 
1158
    domain::const_iterator eK=larger.end();
 
1159
    for ( ; iK!=eK; iK++) 
 
1160
      for (size_type i=0; i<(*iK).size(); i++)
 
1161
        larger_vertices.insert((*iK)[i]);
 
1162
    // second step: find smaller domain vertices which are within set and build interface
 
1163
    iK=smaller.begin();
 
1164
    eK=smaller.end();
 
1165
    for ( ; iK!=eK; iK++) 
 
1166
      for (size_type i=0, j=(*iK).size(); i<(*iK).size(); i++, j=i-1)
 
1167
        if ( (larger_vertices.count((*iK)[j])>0)
 
1168
           && (larger_vertices.count((*iK)[i])>0) ) 
 
1169
             {
 
1170
                K[0]=(*iK)[j]; K[1]=(*iK)[i];
 
1171
                interface.push_back(K);
 
1172
             }
 
1173
    _domlist.push_back(interface);
 
1174
}
 
1175
Float
 
1176
georep::measure (const geo_element& K) const
 
1177
{
 
1178
  georep::const_iterator_vertex p = begin_vertex();
 
1179
  switch (K.type()) {
 
1180
    case geo_element::p:
 
1181
      return 0;
 
1182
    case geo_element::e:
 
1183
      switch (dimension()) {
 
1184
       case 1: return       fabs(p[K[1]][0] - p[K[0]][0]);
 
1185
       case 2: return sqrt ( sqr(p[K[1]][0] - p[K[0]][0])
 
1186
                           + sqr(p[K[1]][1] - p[K[0]][1]));
 
1187
       default: return dist(p[K[1]], p[K[0]]);
 
1188
      }
 
1189
    case geo_element::t:
 
1190
      switch (dimension()) {
 
1191
       case 2:  return fabs(vect2d( p[K[1]] -p[K[0]], p[K[2]] -p[K[0]] )/2.0);
 
1192
       default: return norm(vect  ( p[K[1]] -p[K[0]], p[K[2]] -p[K[0]] )/2.0);
 
1193
      }
 
1194
    case geo_element::q: {
 
1195
      switch (dimension()) {
 
1196
       case 2: {
 
1197
        Float area1 = fabs(vect2d( p[K[1]] -p[K[0]], p[K[2]] -p[K[0]] )/2);
 
1198
        Float area2 = fabs(vect2d( p[K[2]] -p[K[0]], p[K[3]] -p[K[0]] )/2);
 
1199
        return area1 + area2;
 
1200
       }
 
1201
       default: {
 
1202
        Float area1 = norm(vect( p[K[1]] -p[K[0]], p[K[2]] -p[K[0]] )/2.0);
 
1203
        Float area2 = norm(vect( p[K[2]] -p[K[0]], p[K[3]] -p[K[0]] )/2.0);
 
1204
        return area1 + area2;
 
1205
       }
 
1206
      }
 
1207
    }
 
1208
    case geo_element::T:
 
1209
       return fabs(mixt(p[K[1]]-p[K[0]], p[K[2]]-p[K[0]], p[K[3]]-p[K[0]])/6);
 
1210
    default:
 
1211
      error_macro("area: element " << K.name() << " not yet supported yet.");
 
1212
      return 0;
 
1213
  }
 
1214
}
 
1215
// compute normal to a side of an element
 
1216
point
 
1217
georep::normal (const geo_element& K, georep::size_type side) const
 
1218
{
 
1219
  switch (K.type()) {
 
1220
    case reference_element::e:  { // works also in 2d and 3d
 
1221
      point t = vertex(K[1]) - vertex(K[0]);
 
1222
      t = t/norm(t);
 
1223
      if (side == 1) return t; else return -t;
 
1224
    }
 
1225
    case reference_element::t:
 
1226
    case reference_element::q: { // works also in 3d
 
1227
      point t = vertex(K[(side+1)%3]) - vertex(K[side]);
 
1228
      return point(t[1],-t[0])/norm(t);
 
1229
    }
 
1230
    // TODO: T, P, H...
 
1231
    default:
 
1232
      error_macro("normal to element not yet implemented for element type `"
 
1233
        << K.type() << "'");
 
1234
  }
 
1235
}
 
1236
// compute normal to a facet: triangle in 3D, etc
 
1237
point
 
1238
georep::normal (const geo_element& S) const
 
1239
{
 
1240
  switch (S.type()) {
 
1241
    case reference_element::e:  { // 2d space
 
1242
      point t = vertex(S[1]) - vertex(S[0]);
 
1243
      t = t/norm(t);
 
1244
      return point (-t[1], t[0]);
 
1245
    }
 
1246
    case reference_element::t:
 
1247
    case reference_element::q: { // 3d space
 
1248
      const point& a = vertex(S[0]);
 
1249
      const point& b = vertex(S[1]);
 
1250
      const point& c = vertex(S[2]);
 
1251
      point n = vect (b-a, c-a);
 
1252
      return n/norm(n);
 
1253
    }
 
1254
    default:
 
1255
      error_macro("normal to facet not yet implemented for element type `"
 
1256
        << S.type() << "'");
 
1257
  }
 
1258
}