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
/// =========================================================================
22
// geo tetgen inputs / outputs
25
// Pierre.Saramito@imag.fr
30
// ============================================================================
32
// ============================================================================
34
#include "rheolef/georep.h"
35
#include "rheolef/iorheo.h"
36
#include "rheolef/rheostream.h" // i/o utility
37
#include "rheolef/field.h"
38
#include "rheolef/form.h"
39
#include "rheolef/tiny_element.h"
43
// ============================================================================
45
// use as input the concatenation of 3 files : .node .ele .face
47
// cat toto.node toto.elt toto.face | sed -e 's/#.*$/' |
48
// geo -input-tetgen -upgrade -geo - > toto.geo
49
// Note: strip comments lines as "#comments"
50
// ============================================================================
56
georep::iterator_node p,
63
typedef georep::size_type size_type;
64
xmin[0] = xmin[1] = xmin[2] = numeric_limits<Float>::max();
65
xmax[0] = xmax[1] = xmax[2] = -numeric_limits<Float>::max();
66
size_t vertice_number = 0;
67
for (size_t i = 0; i < np; i++) {
68
// <point #> <x> <y> <z> [attributes] [boundary marker]
71
check_macro (idx < np, "node index "<<idx+1<<" is out of range 1:"<<np);
72
s >> p[idx][0] >> p[idx][1] >> p[idx][2];
75
for (size_t j = 0; j < n_vert_attr + n_bdr_mark; j++) {
81
// get boundary triangles
85
get_boundary_triangles_tetgen (istream& is,
86
size_t n_bdr_triangles, bool has_face_attr, size_t n_vert,
87
vector<domain>& domains,
88
vector<size_t>& triangle_domain_tetgen_number)
90
map<size_t, vector<tiny_element> > domain_map;
92
S.set_type (reference_element::t);
93
for (size_t j = 0; is.good() && j < n_bdr_triangles; j++) {
96
for (size_t i = 0 ; i < 3; i++) {
98
check_macro (S[i] < n_vert, "tetgen input: face " << S_idx+1 << ": "
99
<< i+1 << "-th vertice index "
100
<< S[i]+1 << " out of range 1:" << n_vert);
103
if (has_face_attr) is >> r;
104
domain_map[r].push_back (S);
106
check_macro (is, "a problem occurs while loading a tetgen mesh");
108
// copy domain_map into domains (table)
109
triangle_domain_tetgen_number.resize (domain_map.size());
110
domains.resize (domain_map.size());
111
vector<domain>::iterator iter_domain = domains.begin();
113
for (map<size_t, vector<tiny_element> >::const_iterator iter_domain_map = domain_map.begin();
114
iter_domain_map != domain_map.end(); iter_domain_map++, iter_domain++, i_dom++) {
115
triangle_domain_tetgen_number[i_dom] = (*iter_domain_map).first;
116
const vector<tiny_element>& dom = (*iter_domain_map).second;
117
if (dom.size() == 0) continue;
118
(*iter_domain).set(dom.begin(), dom.size(), 2, "unamed"+itos(i_dom));
122
georep::get_tetgen (istream& s, bool check_optional_domain_name)
124
// tetgen has only boundary edges that are numbered
125
// and have domain numbers
126
// => this is only a version 1 mesh file format type
127
// not consistent for P2 elements
130
typedef georep::size_type size_type;
131
check_macro (s.good(), "bad input stream for tetgen.");
132
bool verbose = iorheo::getverbose(s);
135
// header: <# of points> <dimension (must be 3)> <# of attributes> <# of boundary markers (0 or 1)>
137
size_type n_vert, n_vert_attr, n_bdr_mark;
138
s >> n_vert >>_dim >> n_vert_attr >> n_bdr_mark;
139
check_macro (s, "bad input stream for tetgen.");
140
check_macro (_dim == 3, "bad dimension "<<_dim<<" for tetgen: expect 3");
142
get_nodes_tetgen (s, begin_node(), n_vert, n_vert_attr, n_bdr_mark, _xmin, _xmax);
143
check_macro (s, "bad input stream for tetgen.");
144
_count_geo [0] = _count_element [0] = n_vert;
147
// header: <# of tetrahedra> <nodes per tetrahedron> <# of attributes>
148
// lines : <tetrahedron #> <node> <node> <node> <node> ... [attributes]
149
size_type n_elt, n_vert_per_elt, n_tetra_attr;
150
s >> n_elt >> n_vert_per_elt >> n_tetra_attr;
151
check_macro (n_vert_per_elt == 4, "bad #node per tetra "<<n_vert_per_elt<<" for tetgen: expect 4");
153
iterator elt = begin();
154
for (size_t j = 0; j < n_elt; j++) {
157
check_macro (K_idx < n_elt, "element index "<<K_idx+1<<" is out of range 1:"<<n_elt);
158
geo_element& K = elt[K_idx];
159
K.set_type (n_vert_per_elt, _dim);
161
for (size_type i = 0 ; i < n_vert_per_elt; i++) {
163
check_macro (K[i] < n_vert, "tetgen input: element " << K_idx+1 << ": "
164
<< i+1 << "-th vertice index "
165
<< K[i]+1 << " out of range 1:" << n_vert);
169
for (size_t j = 0; j < n_tetra_attr; j++) {
173
// read triangular faces:
174
// First line: <# of faces> <boundary marker (0 or 1)>
175
// Remaining lines list of # of faces:
176
// <face #> <node> <node> <node> [boundary marker]
177
size_t n_face, bdry_mark;
178
s >> n_face >> bdry_mark;
179
bool has_face_attr = (bdry_mark == 1);
180
vector<domain> triangle_domain;
181
vector<size_t> triangle_domain_tetgen_number;
182
get_boundary_triangles_tetgen (s, n_face, has_face_attr, n_vert,
183
triangle_domain, triangle_domain_tetgen_number);
185
// ---------------------------------------------------------------
186
// check extension to optional domain names
187
// ---------------------------------------------------------------
188
if (!check_optional_domain_name) return s;
190
s >> ws >> c; // skip white and grab a char
191
// have "FaceDomainNames", "EdgeDomainNames" or "VerticeDomainNames" ?
192
// tetgen mesh may be followed by field data and such, so be carrefull...
193
while (c == 'E' || c == 'F' || c == 'V') {
194
s.unget(); // put char back
196
if (!scatch(s,"FaceDomainNames")) return s;
197
// ---------------------------------------------------------------
198
// get triangle domain names
199
// ---------------------------------------------------------------
200
size_type n_dom_triangle;
202
if (n_dom_triangle != triangle_domain.size()) {
204
for (size_t j = 0; j < triangle_domain_tetgen_number.size(); j++) {
205
numbers = numbers + itos(triangle_domain_tetgen_number[j]) + " ";
207
warning_macro("geo input: "
208
<< n_dom_triangle << " domain names founded while "
209
<< triangle_domain.size() << " tetgen triangle domains numbers are defined: "
212
error_macro("HINT: check domain name file (.dmn)");
214
size_t start_triangle_domain = _domlist.size();
215
_domlist.resize(_domlist.size() + n_dom_triangle);
216
for (size_type k = 0; k < n_dom_triangle; k++) {
219
triangle_domain[k].set_name(name);
220
_domlist.at(start_triangle_domain+k) = triangle_domain[k];
222
} else if (c == 'E') {
223
if (!scatch(s,"EdgeDomainNames")) return s;
224
// ---------------------------------------------------------------
225
// get edge domain names
226
// ---------------------------------------------------------------
227
warning_macro ("EdgeDomainNames skiped");
228
size_type n_dom_edge;
230
for (size_type k = 0; k < n_dom_edge; k++) {
234
} else if (c == 'V') {
235
if (!scatch(s,"VerticeDomainNames")) return s;
236
// ---------------------------------------------------------------
237
// get vertice domain names
238
// ---------------------------------------------------------------
239
warning_macro ("VerticeDomainNames skiped");
240
size_type n_dom_vertice;
242
for (size_type k = 0; k < n_dom_vertice; k++) {
247
s >> ws >> c; // skip white and grab a char
251
// =======================================================================
253
// =======================================================================
255
georep::put_tetgen (ostream& os, bool only_boundary) const
257
fatal_macro ("put_tetgen: not yet!");