31 template<
typename C>
static bool check_voxel(
const C& c) {
33 unsigned N = c[0].size();
34 if (c.size() != (1U << N))
return false;
35 const base_node P0 = c[0];
36 h[0] = c[1][0] - P0[0];
37 h[1] = c[2][0] - P0[0];
38 if (c.size() != 4) h[2] = c[4][0] - P0[0];
39 for (
unsigned i=1; i < c.size(); ++i) {
40 const base_node d = c[i] - P0;
41 for (
unsigned j=0; j < N; ++j)
42 if (gmm::abs(d[j]) > 1e-7*h[j] && gmm::abs(d[j] - h[j]) > 1e-7*h[j])
49 std::string base64_encode(
const std::vector<unsigned char>& src)
51 const std::string table(
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
53 for (
size_type i = 0; i < src.size(); ++i) {
56 dst.push_back(table[(src[i] & 0xFC) >> 2]);
57 if (i + 1 == src.size()) {
58 dst.push_back(table[(src[i] & 0x03) << 4]);
64 dst.push_back(table[((src[i - 1] & 0x03) << 4) | ((src[i + 0] & 0xF0) >> 4)]);
65 if (i + 1 == src.size()) {
66 dst.push_back(table[(src[i] & 0x0F) << 2]);
71 dst.push_back(table[((src[i - 1] & 0x0F) << 2) | ((src[i + 0] & 0xC0) >> 6)]);
72 dst.push_back(table[src[i] & 0x3F]);
83 struct gf2vtk_dof_mapping :
public std::vector<std::vector<unsigned> > {};
84 struct gf2vtk_vtk_type :
public std::vector<int> {};
86 typedef enum { VTK_VERTEX = 1,
96 VTK_QUADRATIC_EDGE = 21,
97 VTK_QUADRATIC_TRIANGLE = 22,
98 VTK_QUADRATIC_QUAD = 23,
99 VTK_QUADRATIC_TETRA = 24,
100 VTK_QUADRATIC_HEXAHEDRON = 25,
101 VTK_QUADRATIC_WEDGE = 26,
102 VTK_QUADRATIC_PYRAMID = 27,
103 VTK_BIQUADRATIC_QUAD = 28,
104 VTK_TRIQUADRATIC_HEXAHEDRON = 29,
105 VTK_BIQUADRATIC_QUADRATIC_WEDGE = 32 } vtk_cell_type;
107 typedef enum { NO_VTK_MAPPING,
115 N8_TO_VTK_HEXAHEDRON,
118 N3_TO_VTK_QUADRATIC_EDGE,
119 N6_TO_VTK_QUADRATIC_TRIANGLE,
120 N8_TO_VTK_QUADRATIC_QUAD,
121 N10_TO_VTK_QUADRATIC_TETRA,
122 N20_TO_VTK_QUADRATIC_HEXAHEDRON,
123 N15_TO_VTK_QUADRATIC_WEDGE,
124 N13_TO_VTK_QUADRATIC_PYRAMID,
125 N14_TO_VTK_QUADRATIC_PYRAMID,
126 N9_TO_VTK_BIQUADRATIC_QUAD,
127 N27_TO_VTK_TRIQUADRATIC_HEXAHEDRON,
128 N18_TO_VTK_BIQUADRATIC_QUADRATIC_WEDGE } vtk_mapping_type;
140 vtktypes[N1_TO_VTK_VERTEX] = VTK_VERTEX;
141 vtkmaps [N1_TO_VTK_VERTEX] = {0};
142 vtktypes[N2_TO_VTK_LINE] = VTK_LINE;
143 vtkmaps [N2_TO_VTK_LINE] = {0, 1};
144 vtktypes[N3_TO_VTK_TRIANGLE] = VTK_TRIANGLE;
145 vtkmaps [N3_TO_VTK_TRIANGLE] = {0, 1, 2};
146 vtktypes[N4_TO_VTK_PIXEL] = VTK_PIXEL;
147 vtkmaps [N4_TO_VTK_PIXEL] = {0, 1, 2, 3};
148 vtktypes[N4_TO_VTK_QUAD] = VTK_QUAD;
149 vtkmaps [N4_TO_VTK_QUAD] = {0, 1, 3, 2};
150 vtktypes[N4_TO_VTK_TETRA] = VTK_TETRA;
151 vtkmaps [N4_TO_VTK_TETRA] = {0, 1, 2, 3};
152 vtktypes[N8_TO_VTK_VOXEL] = VTK_VOXEL;
153 vtkmaps [N8_TO_VTK_VOXEL] = {0, 1, 2, 3, 4, 5, 6, 7};
154 vtktypes[N8_TO_VTK_HEXAHEDRON] = VTK_HEXAHEDRON;
155 vtkmaps [N8_TO_VTK_HEXAHEDRON] = {0, 1, 3, 2, 4, 5, 7, 6};
156 vtktypes[N6_TO_VTK_WEDGE] = VTK_WEDGE;
157 vtkmaps [N6_TO_VTK_WEDGE] = {0, 1, 2, 3, 4, 5};
158 vtktypes[N5_TO_VTK_PYRAMID] = VTK_PYRAMID;
159 vtkmaps [N5_TO_VTK_PYRAMID] = {0, 1, 3, 2, 4};
160 vtktypes[N3_TO_VTK_QUADRATIC_EDGE] = VTK_QUADRATIC_EDGE;
161 vtkmaps [N3_TO_VTK_QUADRATIC_EDGE] = {0, 2, 1};
162 vtktypes[N6_TO_VTK_QUADRATIC_TRIANGLE] = VTK_QUADRATIC_TRIANGLE;
163 vtkmaps [N6_TO_VTK_QUADRATIC_TRIANGLE] = {0, 2, 5, 1, 4, 3};
164 vtktypes[N8_TO_VTK_QUADRATIC_QUAD] = VTK_QUADRATIC_QUAD;
165 vtkmaps [N8_TO_VTK_QUADRATIC_QUAD] = {0, 2, 7, 5, 1, 4, 6, 3};
166 vtktypes[N10_TO_VTK_QUADRATIC_TETRA] = VTK_QUADRATIC_TETRA;
167 vtkmaps [N10_TO_VTK_QUADRATIC_TETRA] = {0, 2, 5, 9, 1, 4, 3, 6, 7, 8};
168 vtktypes[N20_TO_VTK_QUADRATIC_HEXAHEDRON] = VTK_QUADRATIC_HEXAHEDRON;
169 vtkmaps [N20_TO_VTK_QUADRATIC_HEXAHEDRON] = {0, 2, 7, 5, 12, 14, 19, 17, 1, 4, 6, 3, 13, 16, 18, 15, 8, 9, 11, 10};
170 vtktypes[N15_TO_VTK_QUADRATIC_WEDGE] = VTK_QUADRATIC_WEDGE;
171 vtkmaps [N15_TO_VTK_QUADRATIC_WEDGE] = {0, 2, 5, 9, 11, 14, 1, 4, 3, 10, 13, 12, 6, 7, 8};
173 vtktypes[N13_TO_VTK_QUADRATIC_PYRAMID] = VTK_QUADRATIC_PYRAMID;
174 vtkmaps [N13_TO_VTK_QUADRATIC_PYRAMID] = {0, 2, 7, 5, 12, 1, 4, 6, 3, 8, 9, 11, 10};
175 vtktypes[N14_TO_VTK_QUADRATIC_PYRAMID] = VTK_QUADRATIC_PYRAMID;
176 vtkmaps [N14_TO_VTK_QUADRATIC_PYRAMID] = {0, 2, 8, 6, 13, 1, 5, 7, 3, 9, 10, 12, 11};
177 vtktypes[N9_TO_VTK_BIQUADRATIC_QUAD] = VTK_BIQUADRATIC_QUAD;
178 vtkmaps [N9_TO_VTK_BIQUADRATIC_QUAD] = {0, 2, 8, 6, 1, 5, 7, 3, 4};
179 vtktypes[N27_TO_VTK_TRIQUADRATIC_HEXAHEDRON] = VTK_TRIQUADRATIC_HEXAHEDRON;
180 vtkmaps [N27_TO_VTK_TRIQUADRATIC_HEXAHEDRON] = {0, 2, 8, 6, 18, 20, 26, 24, 1, 5, 7, 3, 19, 23, 25, 21, 9, 11, 17, 15, 12, 14, 10, 16, 4, 22};
181 vtktypes[N18_TO_VTK_BIQUADRATIC_QUADRATIC_WEDGE] = VTK_BIQUADRATIC_QUADRATIC_WEDGE;
182 vtkmaps [N18_TO_VTK_BIQUADRATIC_QUADRATIC_WEDGE] = {0, 2, 5, 12, 14, 17, 1, 4, 3, 13, 16, 15, 6, 8, 11, 7, 10, 9};
185 static const std::vector<unsigned> &
186 select_vtk_dof_mapping(
unsigned t) {
188 if (vtkmaps.size() == 0) init_gf2vtk();
192 int select_vtk_type(
unsigned t) {
194 if (vtktypes.size() == 0) init_gf2vtk();
199 vtk_export::vtk_export(std::ostream &os_,
bool ascii_,
bool vtk_)
200 : os(os_), ascii(ascii_), vtk(vtk_) { init(); }
202 vtk_export::vtk_export(
const std::string& fname,
bool ascii_,
bool vtk_)
203 : os(real_os), ascii(ascii_), vtk(vtk_),
204 real_os(fname.c_str(), !ascii ? std::ios_base::binary | std::ios_base::out
205 : std::ios_base::out) {
206 GMM_ASSERT1(real_os,
"impossible to write to file '" << fname <<
"'");
210 vtk_export::~vtk_export(){
212 if (state == IN_CELL_DATA) os <<
"</CellData>\n";
213 if (state == IN_POINT_DATA) os <<
"</PointData>\n";
215 os <<
"</UnstructuredGrid>\n";
216 os <<
"</VTKFile>\n";
220 void vtk_export::init() {
221 strcpy(header,
"Exported by GetFEM");
222 psl = 0; dim_ = dim_type(-1);
223 static int test_endian = 0x01234567;
224 reverse_endian = (*((
char*)&test_endian) == 0x67);
229 void vtk_export::switch_to_cell_data() {
230 if (state != IN_CELL_DATA) {
233 if (psl)
for (
auto i : {0,1,2,3}) nb_cells += psl->nb_simplexes(i);
234 else nb_cells = pmf->convex_index().card();
236 os <<
"CELL_DATA " << nb_cells <<
"\n";
239 if (state == IN_POINT_DATA) os <<
"</PointData>\n";
240 os <<
"<CellData>\n";
242 state = IN_CELL_DATA;
246 void vtk_export::switch_to_point_data() {
247 if (state != IN_POINT_DATA) {
250 os <<
"POINT_DATA " << (psl ? psl->nb_points()
251 : pmf_dof_used.card()) <<
"\n";
254 if (state == IN_CELL_DATA) os <<
"</CellData>\n";
255 os <<
"<PointData>\n";
257 state = IN_POINT_DATA;
262 void vtk_export::exporting(
const stored_mesh_slice& sl) {
263 psl = &sl; dim_ = dim_type(sl.dim());
264 GMM_ASSERT1(psl->dim() <= 3,
"attempt to export a " <<
int(dim_)
265 <<
"D slice (not supported)");
268 void vtk_export::exporting(
const mesh& m) {
270 GMM_ASSERT1(dim_ <= 3,
"attempt to export a " <<
int(dim_)
271 <<
"D mesh (not supported)");
272 pmf = std::make_unique<mesh_fem>(
const_cast<mesh&
>(m), dim_type(1));
273 for (dal::bv_visitor cv(m.
convex_index()); !cv.finished(); ++cv) {
276 pmf->set_finite_element(cv, pf);
281 void vtk_export::exporting(
const mesh_fem& mf) {
283 GMM_ASSERT1(dim_ <= 3,
"attempt to export a " <<
int(dim_)
284 <<
"D mesh_fem (not supported)");
285 if (&mf != pmf.get())
286 pmf = std::make_unique<mesh_fem>(mf.
linked_mesh());
289 for (dal::bv_visitor cv(mf.
convex_index()); !cv.finished(); ++cv) {
296 pf ==
fem_descriptor(
"FEM_PYRAMID_Q2_INCOMPLETE_DISCONTINUOUS") ||
299 pmf->set_finite_element(cv, pf);
301 bool discontinuous =
false;
302 for (
unsigned i=0; i < pf->nb_dof(cv); ++i) {
304 if (!
dof_linkable(pf->dof_types()[i])) { discontinuous =
true;
break; }
311 if ((pf != classical_pf1 && pf->estimated_degree() > 1) ||
312 pgt->structure() != pgt->basic_structure())
315 pmf->set_finite_element(cv, discontinuous ?
322 const mesh &m = pmf->linked_mesh();
323 pmf_mapping_type.resize(pmf->convex_index().last_true() + 1,
unsigned(-1));
324 pmf_dof_used.sup(0, pmf->nb_basic_dof());
325 for (dal::bv_visitor cv(pmf->convex_index()); !cv.finished(); ++cv) {
326 vtk_mapping_type t = NO_VTK_MAPPING;
327 size_type nbd = pmf->fem_of_element(cv)->nb_dof(cv);
328 switch (pmf->fem_of_element(cv)->dim()) {
329 case 0: t = N1_TO_VTK_VERTEX;
break;
331 if (nbd == 2) t = N2_TO_VTK_LINE;
332 else if (nbd == 3) t = N3_TO_VTK_QUADRATIC_EDGE;
335 if (nbd == 3) t = N3_TO_VTK_TRIANGLE;
337 t = check_voxel(m.points_of_convex(cv)) ? N4_TO_VTK_PIXEL
339 else if (nbd == 6) t = N6_TO_VTK_QUADRATIC_TRIANGLE;
340 else if (nbd == 8) t = N8_TO_VTK_QUADRATIC_QUAD;
341 else if (nbd == 9) t = N9_TO_VTK_BIQUADRATIC_QUAD;
344 if (nbd == 4) t = N4_TO_VTK_TETRA;
345 else if (nbd == 10) t = N10_TO_VTK_QUADRATIC_TETRA;
347 t = check_voxel(m.points_of_convex(cv)) ? N8_TO_VTK_VOXEL
348 : N8_TO_VTK_HEXAHEDRON;
349 else if (nbd == 20) t = N20_TO_VTK_QUADRATIC_HEXAHEDRON;
350 else if (nbd == 27) t = N27_TO_VTK_TRIQUADRATIC_HEXAHEDRON;
351 else if (nbd == 5) t = N5_TO_VTK_PYRAMID;
352 else if (nbd == 13) t = N13_TO_VTK_QUADRATIC_PYRAMID;
353 else if (nbd == 14) t = N14_TO_VTK_QUADRATIC_PYRAMID;
354 else if (nbd == 6) t = N6_TO_VTK_WEDGE;
355 else if (nbd == 15) t = N15_TO_VTK_QUADRATIC_WEDGE;
356 else if (nbd == 18) t = N18_TO_VTK_BIQUADRATIC_QUADRATIC_WEDGE;
359 GMM_ASSERT1(t != -1,
"semi internal error. Could not map " <<
361 <<
" to a VTK cell type");
362 pmf_mapping_type[cv] = t;
364 const std::vector<unsigned> &dmap = select_vtk_dof_mapping(t);
366 GMM_ASSERT1(dmap.size() <= pmf->nb_basic_dof_of_element(cv),
367 "inconsistency in vtk_dof_mapping");
368 for (
unsigned i=0; i < dmap.size(); ++i)
369 pmf_dof_used.add(pmf->ind_basic_dof_of_element(cv)[dmap[i]]);
376 const stored_mesh_slice& vtk_export::get_exported_slice()
const {
377 GMM_ASSERT1(psl,
"no slice!");
381 const mesh_fem& vtk_export::get_exported_mesh_fem()
const {
382 GMM_ASSERT1(pmf.get(),
"no mesh_fem!");
386 void vtk_export::set_header(
const std::string& s)
388 strncpy(header, s.c_str(), 256);
392 void vtk_export::check_header() {
393 if (state >= HEADER_WRITTEN)
return;
395 os <<
"# vtk DataFile Version 2.0\n";
396 os << header <<
"\n";
397 os << (ascii ?
"ASCII\n" :
"BINARY\n");
399 os <<
"<?xml version=\"1.0\"?>\n";
400 os <<
"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" ";
401 os <<
"byte_order=\"" << (reverse_endian ?
"LittleEndian" :
"BigEndian") <<
"\">\n";
402 os <<
"<!--" << header <<
"-->\n";
403 os <<
"<UnstructuredGrid>\n";
405 state = HEADER_WRITTEN;
408 void vtk_export::write_separ()
409 {
if (ascii) os <<
"\n"; }
411 void vtk_export::clear_vals()
412 {
if (!vtk && !ascii) vals.clear(); }
414 void vtk_export::write_vals() {
415 if (!vtk && !ascii) {
416 os << base64_encode(vals);
421 void vtk_export::write_mesh() {
422 if (psl) write_mesh_structure_from_slice();
423 else write_mesh_structure_from_mesh_fem();
427 void vtk_export::write_mesh_structure_from_slice() {
429 static int vtk_simplex_code[4] = { VTK_VERTEX, VTK_LINE, VTK_TRIANGLE, VTK_TETRA };
430 if (state >= STRUCTURE_WRITTEN)
return;
434 for (
size_type ic=0; ic < psl->nb_convex(); ++ic) {
435 for (
const slice_simplex &s : psl->simplexes(ic))
436 cells_cnt += s.dim() + 2;
437 splx_cnt += psl->simplexes(ic).size();
441 os <<
"DATASET UNSTRUCTURED_GRID\n";
442 os <<
"POINTS " << psl->nb_points() <<
" float\n";
444 os <<
"<Piece NumberOfPoints=\"" << psl->nb_points();
445 os <<
"\" NumberOfCells=\"" << splx_cnt <<
"\">\n";
447 os <<
"<DataArray type=\"Float32\" Name=\"Points\" ";
448 os <<
"NumberOfComponents=\"3\" ";
449 os << (ascii ?
"format=\"ascii\">\n" :
"format=\"binary\">\n");
450 if (!ascii) write_val(
int(
sizeof(
float)*psl->nb_points()*3));
457 for (
size_type ic=0; ic < psl->nb_convex(); ++ic) {
458 for (
size_type i=0; i < psl->nodes(ic).size(); ++i)
459 write_vec(psl->nodes(ic)[i].pt.begin(),psl->nodes(ic)[i].pt.size());
464 os << (ascii ?
"" :
"\n") <<
"</DataArray>\n";
471 write_separ(); os <<
"CELLS " << splx_cnt <<
" " << cells_cnt <<
"\n";
474 os <<
"<DataArray type=\"Int32\" Name=\"connectivity\" ";
475 os << (ascii ?
"format=\"ascii\">\n" :
"format=\"binary\">\n");
478 for (
size_type ic=0; ic < psl->nb_convex(); ++ic) {
479 for (
const slice_simplex &s : psl->simplexes(ic))
480 size +=
int((s.dim()+1)*
sizeof(int));
485 for (
size_type ic=0; ic < psl->nb_convex(); ++ic) {
486 for (
const slice_simplex &s : psl->simplexes(ic)) {
488 write_val(
int(s.dim()+1));
490 write_val(
int(s.inodes[j] + nodes_cnt));
493 nodes_cnt += psl->nodes(ic).size();
495 assert(nodes_cnt == psl->nb_points());
498 write_separ(); os <<
"CELL_TYPES " << splx_cnt <<
"\n";
500 os << (ascii ?
"" :
"\n") <<
"</DataArray>\n";
501 os <<
"<DataArray type=\"Int32\" Name=\"offsets\" ";
502 os << (ascii ?
"format=\"ascii\">\n" :
"format=\"binary\">\n");
505 for (
size_type ic=0; ic < psl->nb_convex(); ++ic)
506 size +=
int(psl->simplexes(ic).size()*
sizeof(int));
511 for (
size_type ic=0; ic < psl->nb_convex(); ++ic) {
512 for (
const slice_simplex &s : psl->simplexes(ic))
514 write_val(
int(vtk_simplex_code[s.dim()]));
516 cnt += int(s.dim()+1);
520 splx_cnt -= psl->simplexes(ic).size();
523 assert(splx_cnt == 0);
525 os << (ascii ?
"" :
"\n") <<
"</DataArray>\n";
526 os <<
"<DataArray type=\"Int32\" Name=\"types\" ";
527 os << (ascii ?
"format=\"ascii\">\n" :
"format=\"binary\">\n");
530 for (
size_type ic=0; ic < psl->nb_convex(); ++ic)
531 size +=
int(psl->simplexes(ic).size()*
sizeof(int));
534 for (
size_type ic=0; ic < psl->nb_convex(); ++ic)
535 for (
const slice_simplex &s : psl->simplexes(ic))
536 write_val(
int(vtk_simplex_code[s.dim()]));
538 os <<
"\n" <<
"</DataArray>\n";
541 state = STRUCTURE_WRITTEN;
545 void vtk_export::write_mesh_structure_from_mesh_fem() {
546 if (state >= STRUCTURE_WRITTEN)
return;
550 os <<
"DATASET UNSTRUCTURED_GRID\n";
551 os <<
"POINTS " << pmf_dof_used.card() <<
" float\n";
553 os <<
"<Piece NumberOfPoints=\"" << pmf_dof_used.card()
554 <<
"\" NumberOfCells=\"" << pmf->convex_index().card() <<
"\">\n";
556 os <<
"<DataArray type=\"Float32\" Name=\"Points\" ";
557 os <<
"NumberOfComponents=\"3\" ";
558 os << (ascii ?
"format=\"ascii\">\n" :
"format=\"binary\">\n");
559 if (!ascii) write_val(
int(
sizeof(
float)*pmf_dof_used.card()*3));
561 std::vector<int> dofmap(pmf->nb_dof());
563 for (dal::bv_visitor d(pmf_dof_used); !d.finished(); ++d) {
565 base_node P = pmf->point_of_basic_dof(d);
566 write_vec(P.const_begin(),P.size());
572 for (dal::bv_visitor cv(pmf->convex_index()); !cv.finished(); ++cv)
573 nb_cell_values += (1 + select_vtk_dof_mapping(pmf_mapping_type[cv]).size());
577 os <<
"CELLS " << pmf->convex_index().card() <<
" " << nb_cell_values <<
"\n";
579 os << (ascii ?
"" :
"\n") <<
"</DataArray>\n";
582 os <<
"<DataArray type=\"Int32\" Name=\"connectivity\" ";
583 os << (ascii ?
"format=\"ascii\">\n" :
"format=\"binary\">\n");
586 for (dal::bv_visitor cv(pmf->convex_index()); !cv.finished(); ++cv) {
587 const std::vector<unsigned> &dmap = select_vtk_dof_mapping(pmf_mapping_type[cv]);
588 size += int(
sizeof(
int)*dmap.size());
594 for (dal::bv_visitor cv(pmf->convex_index()); !cv.finished(); ++cv) {
595 const std::vector<unsigned> &dmap = select_vtk_dof_mapping(pmf_mapping_type[cv]);
596 if (vtk) write_val(
int(dmap.size()));
597 for (
size_type i=0; i < dmap.size(); ++i)
598 write_val(
int(dofmap[pmf->ind_basic_dof_of_element(cv)[dmap[i]]]));
605 os <<
"CELL_TYPES " << pmf->convex_index().card() <<
"\n";
607 os << (ascii ?
"" :
"\n") <<
"</DataArray>\n";
608 os <<
"<DataArray type=\"Int32\" Name=\"offsets\" ";
609 os << (ascii ?
"format=\"ascii\">\n" :
"format=\"binary\">\n");
611 write_val(
int(pmf->convex_index().card()*
sizeof(
int)));
613 for (dal::bv_visitor cv(pmf->convex_index()); !cv.finished(); ++cv) {
614 const std::vector<unsigned> &dmap = select_vtk_dof_mapping(pmf_mapping_type[cv]);
615 cnt += int(dmap.size());
619 os <<
"\n" <<
"</DataArray>\n";
620 os <<
"<DataArray type=\"Int32\" Name=\"types\" ";
621 os << (ascii ?
"format=\"ascii\">\n" :
"format=\"binary\">\n");
623 write_val(
int(pmf->convex_index().card()*
sizeof(
int)));
625 for (dal::bv_visitor cv(pmf->convex_index()); !cv.finished(); ++cv) {
626 write_val(
int(select_vtk_type(pmf_mapping_type[cv])));
627 if (vtk) write_separ();
630 if (!vtk) os <<
"\n" <<
"</DataArray>\n" <<
"</Cells>\n";
632 state = STRUCTURE_WRITTEN;
635 void vtk_export::write_mesh_quality(
const mesh &m) {
639 std::vector<scalar_type> q(mf.
nb_dof());
643 write_point_data(mf, q,
"convex_quality");
645 std::vector<scalar_type> q(pmf->convex_index().card());
646 for (dal::bv_visitor cv(pmf->convex_index()); !cv.finished(); ++cv) {
649 write_cell_data(q,
"convex_quality");
658 dx_export::dx_export(std::ostream &os_,
bool ascii_)
659 : os(os_), ascii(ascii_) { init(); }
661 dx_export::dx_export(
const std::string& fname,
bool ascii_,
bool append_)
662 : os(real_os), ascii(ascii_) {
663 real_os.open(fname.c_str(),
664 std::ios_base::openmode(std::ios_base::in |
666 (append_ ? std::ios_base::ate : std::ios_base::trunc)));
667 GMM_ASSERT1(real_os.good(),
"impossible to write to dx file '"
670 if (append_) { reread_metadata(); header_written =
true; }
673 dx_export::~dx_export() {
674 std::ios::pos_type p = os.tellp();
676 os <<
"\n# --end of getfem export\nend\n";
680 void dx_export::init() {
681 strcpy(header,
"Exported by GetFEM");
682 psl = 0; dim_ = dim_type(-1); connections_dim = dim_type(-1);
683 psl_use_merged =
false;
684 header_written =
false;
687 void dx_export::write_separ()
688 {
if (ascii) os <<
"\n"; }
690 template<
typename T>
static typename std::list<T>::iterator
691 get_from_name(std::list<T> &c,
692 const std::string& name,
bool raise_error) {
693 for (
typename std::list<T>::iterator it = c.begin();
694 it != c.end(); ++it) {
695 if (it->name == name)
return it;
697 GMM_ASSERT1(!raise_error,
"object not found in dx file: " << name);
701 std::list<dx_export::dxMesh>::iterator
702 dx_export::get_mesh(
const std::string& name,
bool raise_error) {
703 return get_from_name(meshes,name,raise_error);
705 std::list<dx_export::dxObject>::iterator
706 dx_export::get_object(
const std::string& name,
bool raise_error) {
707 return get_from_name(objects,name,raise_error);
711 bool dx_export::new_mesh(std::string &name) {
712 name = default_name(name,
int(meshes.size()),
"mesh");
713 std::list<dxMesh>::iterator it = get_mesh(name,
false);
714 if (it != meshes.end()) {
715 if (&(*it) != ¤t_mesh())
716 std::swap(current_mesh(),*it);
719 meshes.push_back(dxMesh()); meshes.back().name = name;
724 void dx_export::exporting(
const stored_mesh_slice& sl,
bool merge_points,
726 if (!new_mesh(name))
return;
727 psl_use_merged = merge_points;
728 if (merge_points) sl.merge_nodes();
729 psl = &sl; dim_ = dim_type(sl.dim());
730 GMM_ASSERT1(psl->
dim() <= 3,
"4D slices and more are not supported");
731 for (dim_type d = 0; d <= psl->
dim(); ++d) {
733 if (connections_dim == dim_type(-1)) connections_dim = d;
734 else GMM_ASSERT1(
false,
"Cannot export a slice containing "
735 "simplexes of different dimensions");
738 GMM_ASSERT1(connections_dim != dim_type(-1),
"empty slice!");
742 void dx_export::exporting(
const mesh_fem& mf, std::string name) {
743 name = default_name(name,
int(meshes.size()),
"mesh");
744 if (!new_mesh(name))
return;
745 const mesh &m = mf.linked_mesh();
746 GMM_ASSERT1(mf.linked_mesh().convex_index().card() != 0,
747 "won't export an empty mesh");
750 GMM_ASSERT1(dim_ <= 3,
"4D meshes and more are not supported");
751 if (&mf != pmf.get())
752 pmf = std::make_unique<mesh_fem>(
const_cast<mesh&
>(m), dim_type(1));
754 GMM_ASSERT1(dxname_of_convex_structure
756 "DX Cannot handle " <<
759 for (dal::bv_visitor cv(mf.convex_index()); !cv.finished(); ++cv) {
763 "Cannot export this mesh to opendx, it contains "
764 "different convex types. Slice it first.");
765 pfem pf = mf.fem_of_element(cv);
766 bool discontinuous =
false;
767 for (
unsigned i=0; i < pf->nb_dof(cv); ++i) {
769 if (!
dof_linkable(pf->dof_types()[i])) { discontinuous =
true;
break; }
773 pmf->set_finite_element(cv, classical_pf1);
775 pmf_dof_used.add(0, pmf->nb_basic_dof());
776 connections_dim = dim_type(pmf->nb_basic_dof_of_element(m.convex_index().first_true()));
779 void dx_export::exporting(
const mesh& m, std::string name) {
781 GMM_ASSERT1(dim_ <= 3,
"4D meshes and more are not supported");
782 pmf = std::make_unique<mesh_fem>(
const_cast<mesh&
>(m), dim_type(1));
783 pmf->set_classical_finite_element(1);
784 exporting(*pmf, name);
787 void dx_export::write_series() {
788 for (std::list<dxSeries>::const_iterator it = series.begin();
789 it != series.end(); ++it) {
790 if (it->members.size() == 0)
continue;
792 os <<
"\nobject \"" << it->name <<
"\" class series\n";
793 for (std::list<std::string>::const_iterator ito = it->members.begin();
794 ito != it->members.end(); ++ito, ++count) {
795 os <<
" member " << count <<
" \"" << (*ito) <<
"\"\n";
800 void dx_export::serie_add_object_(
const std::string &serie_name,
801 const std::string &object_name) {
802 std::list<dxSeries>::iterator it = series.begin();
803 while (it != series.end() && it->name != serie_name) ++it;
804 if (it == series.end()) {
805 series.push_back(dxSeries()); it = series.end(); --it;
806 it->name = serie_name;
808 it->members.push_back(object_name);
812 const std::string &object_name) {
815 std::list<dxObject>::iterator ito = get_object(object_name,
false);
816 if (ito != objects.end()) {
817 std::list<dxMesh>::iterator itm = get_mesh(ito->mesh);
818 if (itm != meshes.end() && (itm->flags & dxMesh::WITH_EDGES)) {
819 serie_add_object_(serie_name +
"_edges",
820 object_name +
"_edges");
824 serie_add_object_(serie_name, object_name);
828 { strncpy(header, s.c_str(), 256); header[255] = 0; }
830 void dx_export::check_header() {
831 if (header_written)
return;
832 header_written =
true;
833 os <<
"# data file for IBM OpenDX, generated by GetFem++ v "
834 << GETFEM_VERSION <<
"\n";
835 os <<
"# " << header <<
"\n";
838 void dx_export::update_metadata(std::ios::pos_type pos_series) {
839 os.seekp(0,std::ios::end);
840 os <<
"# This file contains the following objects\n";
841 std::ios::pos_type pos_end = os.tellp();
842 for (std::list<dxSeries>::const_iterator it = series.begin();
843 it != series.end(); ++it) {
844 os <<
"#S \"" << it->name <<
"\" which contains:\n";
845 for (std::list<std::string>::const_iterator its = it->members.begin();
846 its != it->members.end(); ++its)
847 os <<
"#+ \"" << *its <<
"\"\n";
849 for (std::list<dxObject>::const_iterator it = objects.begin();
850 it != objects.end(); ++it) {
851 os <<
"#O \"" << it->name <<
"\" \"" << it->mesh <<
"\"\n";
853 for (std::list<dxMesh>::const_iterator it = meshes.begin();
854 it != meshes.end(); ++it) {
855 os <<
"#M \"" << it->name <<
"\" " << it->flags <<
"\n";
857 os <<
"#E \"THE_END\" " << std::setw(20) << pos_series << std::setw(20) << pos_end <<
"\n";
860 void dx_export::reread_metadata() {
862 real_os.seekg(0, std::ios::end);
864 unsigned long lu_end, lu_series;
866 real_os.seekg(-1, std::ios::cur);
867 c = char(real_os.peek());
868 }
while (++count < 512 && c !=
'#');
869 real_os.getline(line,
sizeof line);
870 if (sscanf(line,
"#E \"THE_END\" %lu %lu", &lu_series, &lu_end) != 2)
871 GMM_ASSERT1(
false,
"this file was not generated by getfem, "
872 "cannot append data to it!\n");
873 real_os.seekg(lu_end, std::ios::beg);
875 char name[512];
unsigned n;
877 real_os.getline(line,
sizeof line);
878 if (sscanf(line,
"#%c \"%512[^\"]\"%n", &c, name, &pos) < 1)
879 GMM_ASSERT1(
false,
"corrupted file! your .dx file is broken\n");
881 series.push_back(dxSeries()); series.back().name = name;
882 }
else if (c ==
'+') {
883 series.back().members.push_back(name);
884 }
else if (c ==
'O') {
885 objects.push_back(dxObject()); objects.back().name = name;
886 sscanf(line+pos,
" \"%512[^\"]\"", name); objects.back().mesh = name;
887 }
else if (c ==
'M') {
888 meshes.push_back(dxMesh()); meshes.back().name = name;
889 sscanf(line+pos,
"%u", &n); meshes.back().flags = n;
890 }
else if (c ==
'E') {
892 }
else GMM_ASSERT1(
false,
"corrupted file! your .dx file is broken\n");
894 real_os.seekp(lu_series, std::ios::beg);
898 const char *s_elem_type = dxname_of_convex_structure(cvs);
900 GMM_WARNING1(
"OpenDX won't handle this kind of convexes");
901 os <<
"\n attribute \"element type\" string \"" << s_elem_type <<
"\"\n"
902 <<
" attribute \"ref\" string \"positions\"\n\n";
906 const char *s_elem_type = 0;
907 switch (cvs->dim()) {
909 case 1: s_elem_type =
"lines";
break;
911 if (cvs->nb_points() == 3)
912 s_elem_type =
"triangles";
913 else if (cvs->nb_points() == 4)
914 s_elem_type =
"quads";
917 if (cvs->nb_points() == 4)
918 s_elem_type =
"tetrahedra";
919 else if (cvs->nb_points() == 8)
920 s_elem_type =
"cubes";
926 void dx_export::write_mesh() {
928 if (current_mesh().flags & dxMesh::STRUCTURE_WRITTEN)
return;
929 if (psl) write_mesh_structure_from_slice();
930 else write_mesh_structure_from_mesh_fem();
933 <<
" component \"positions\" value \""
935 <<
" component \"connections\" value \""
937 current_mesh().flags |= dxMesh::STRUCTURE_WRITTEN;
941 void dx_export::write_mesh_structure_from_slice() {
943 <<
"\" class array type float rank 1 shape "
946 if (!ascii) os <<
" " << endianness() <<
" binary";
947 os <<
" data follows\n";
948 if (psl_use_merged) {
958 write_val(
float(psl->
nodes(ic)[i].pt[k]));
964 <<
"\" class array type int rank 1 shape "
965 << int(connections_dim+1)
967 if (!ascii) os <<
" " << endianness() <<
" binary";
968 os <<
" data follows\n";
972 for (
const slice_simplex &s : psl->
simplexes(ic)) {
973 if (s.dim() == connections_dim) {
974 for (
size_type j=0; j < s.dim()+1; ++j) {
977 k = psl->merged_index(ic, s.inodes[j]);
978 else k = psl->global_index(ic, s.inodes[j]);
984 nodes_cnt += psl->
nodes(ic).size();
991 void dx_export::write_mesh_structure_from_mesh_fem() {
993 <<
"\" class array type float rank 1 shape "
994 << int(pmf->linked_mesh().dim())
995 <<
" items " << pmf->nb_dof();
996 if (!ascii) os <<
" " << endianness() <<
" binary";
997 os <<
" data follows\n";
1000 for (
size_type d = 0; d < pmf->nb_basic_dof(); ++d) {
1001 const base_node P = pmf->point_of_basic_dof(d);
1003 write_val(
float(P[k]));
1008 <<
"\" class array type int rank 1 shape "
1009 << int(connections_dim)
1010 <<
" items " << pmf->convex_index().card();
1011 if (!ascii) os <<
" " << endianness() <<
" binary";
1012 os <<
" data follows\n";
1014 for (dal::bv_visitor cv(pmf->convex_index()); !cv.finished(); ++cv) {
1015 for (
size_type i=0; i < connections_dim; ++i)
1016 write_val(
int(pmf->ind_basic_dof_of_element(cv)[i]));
1019 write_convex_attributes(
basic_structure(pmf->linked_mesh().structure_of_convex(pmf->convex_index().first_true())));
1024 if (current_mesh().flags & dxMesh::WITH_EDGES)
return;
1025 if (psl) write_mesh_edges_from_slice(with_slice_edges);
1026 else write_mesh_edges_from_mesh();
1027 current_mesh().flags |= dxMesh::WITH_EDGES;
1029 <<
"\" class field\n"
1030 <<
" component \"positions\" value \""
1032 <<
" component \"connections\" value \""
1037 void dx_export::write_mesh_edges_from_slice(
bool with_slice_edges) {
1038 std::vector<size_type> edges;
1039 dal::bit_vector slice_edges;
1040 psl->
get_edges(edges, slice_edges, psl_use_merged);
1041 if (with_slice_edges) slice_edges.clear();
1044 <<
"\" class array type int rank 1 shape 2"
1045 <<
" items " << edges.size()/2 - slice_edges.card();
1046 if (!ascii) os <<
" " << endianness() <<
" binary";
1047 os <<
" data follows\n";
1048 for (
size_type i=0; i < edges.size()/2; ++i) {
1049 if (!slice_edges.is_in(i)) {
1050 write_val(
int(edges[2*i]));
1051 write_val(
int(edges[2*i+1]));
1053 if ((i+1)%10 == 0) write_separ();
1059 void dx_export::write_mesh_edges_from_mesh() {
1063 <<
"\" class array type int rank 1 shape 2"
1064 <<
" items " << ms.convex_index().card();
1065 if (!ascii) os <<
" " << endianness() <<
" binary";
1066 os <<
" data follows\n";
1067 for (dal::bv_visitor cv(ms.convex_index()); !cv.finished(); ++cv) {
1068 write_val(
int(ms.ind_points_of_convex(cv)[0]));
1069 write_val(
int(ms.ind_points_of_convex(cv)[1]));
1070 if ((cv+1)%20 == 0) write_separ();
1080 struct gf2pos_dof_mapping :
public std::vector<std::vector<unsigned> > {};
1082 static const std::vector<unsigned>& getfem_to_pos_dof_mapping(
int t) {
1084 if (dm.size() == 0) {
1086 dm[pos_export::POS_PT] = {0};
1087 dm[pos_export::POS_LN] = {0, 1};
1088 dm[pos_export::POS_TR] = {0, 1, 2};
1089 dm[pos_export::POS_QU] = {0, 1, 3, 2};
1090 dm[pos_export::POS_SI] = {0, 1, 2, 3};
1091 dm[pos_export::POS_HE] = {0, 1, 3, 2, 4, 5, 7, 6};
1092 dm[pos_export::POS_PR] = {0, 1, 2, 3, 4, 5};
1093 dm[pos_export::POS_PY] = {0, 1, 3, 2, 4};
1098 pos_export::pos_export(std::ostream& osname): os(osname) {
1102 pos_export::pos_export(
const std::string& fname)
1103 : os(real_os), real_os(fname.c_str()) {
1104 GMM_ASSERT1(real_os,
"impossible to write to pos file '" << fname <<
"'");
1108 void pos_export::init() {
1109 strcpy(header,
"Exported by GetFEM");
1114 void pos_export::set_header(
const std::string& s){
1115 strncpy(header, s.c_str(), 256);
1119 void pos_export::check_header() {
1120 if (state >= HEADER_WRITTEN)
return;
1121 os <<
"/* " << header <<
" */\n";
1122 os <<
"General.FastRedraw = 0;\n";
1123 os <<
"General.ColorScheme = 1;\n";
1124 state = HEADER_WRITTEN;
1127 void pos_export::exporting(
const mesh& m) {
1128 if (state >= STRUCTURE_WRITTEN)
return;
1129 dim = dim_type(m.dim());
1130 GMM_ASSERT1(
int(dim) <= 3,
"attempt to export a "
1131 <<
int(dim) <<
"D mesh (not supported)");
1132 pmf = std::make_unique<mesh_fem>(
const_cast<mesh&
>(m), dim_type(1));
1133 pmf->set_classical_finite_element(1);
1135 state = STRUCTURE_WRITTEN;
1138 void pos_export::exporting(
const mesh_fem& mf) {
1139 if (state >= STRUCTURE_WRITTEN)
return;
1140 dim = dim_type(mf.linked_mesh().dim());
1141 GMM_ASSERT1(
int(dim) <= 3,
"attempt to export a "
1142 <<
int(dim) <<
"D mesh_fem (not supported)");
1143 if (&mf != pmf.get())
1144 pmf = std::make_unique<mesh_fem>(mf.linked_mesh(), dim_type(1));
1147 for (dal::bv_visitor cv(mf.convex_index()); !cv.finished(); ++cv) {
1149 pfem pf = mf.fem_of_element(cv);
1151 bool discontinuous =
false;
1152 for (
unsigned i=0; i < pf->nb_dof(cv); ++i) {
1154 if (!
dof_linkable(pf->dof_types()[i])) { discontinuous =
true;
break; }
1156 pfem classical_pf1 = discontinuous ?
1158 pmf->set_finite_element(cv, classical_pf1);
1163 for (dal::bv_visitor cv(pmf->convex_index()); !cv.finished(); ++cv) {
1165 switch (pmf->fem_of_element(cv)->nb_dof(cv)){
1166 case 1: t = POS_PT;
break;
1167 case 2: t = POS_LN;
break;
1168 case 3: t = POS_TR;
break;
1170 if ( 2 == pmf->fem_of_element(cv)->dim() ) t = POS_QU;
1171 else if (3 == pmf->fem_of_element(cv)->dim()) t = POS_SI;
1173 case 6: t = POS_PR;
break;
1174 case 8: t = POS_HE;
break;
1175 case 5: t = POS_PY;
break;
1177 GMM_ASSERT1(t != -1,
"semi internal error. Could not map "
1179 <<
" to a POS primitive type");
1180 pos_cell_type.push_back(
unsigned(t));
1182 const std::vector<unsigned>& dmap = getfem_to_pos_dof_mapping(t);
1183 GMM_ASSERT1(dmap.size() <= pmf->nb_basic_dof_of_element(cv),
1184 "inconsistency in pos_dof_mapping");
1185 std::vector<unsigned> cell_dof;
1186 cell_dof.resize(dmap.size(),
unsigned(-1));
1187 for (
size_type i=0; i < dmap.size(); ++i)
1188 cell_dof[i] =
unsigned(pmf->ind_basic_dof_of_element(cv)[dmap[i]]);
1189 pos_cell_dof.push_back(cell_dof);
1191 for (
size_type i=0; i< pmf->nb_basic_dof(); ++i){
1192 std::vector<float> pt;
1193 pt.resize(dim,
float(0));
1195 pt[j] =
float(pmf->point_of_basic_dof(i)[j]);
1196 pos_pts.push_back(pt);
1198 state = STRUCTURE_WRITTEN;
1201 void pos_export::exporting(
const stored_mesh_slice& sl) {
1202 if (state >= STRUCTURE_WRITTEN)
return;
1204 dim = dim_type(sl.dim());
1205 GMM_ASSERT1(
int(dim) <= 3,
"attempt to export a "
1206 <<
int(dim) <<
"D slice (not supported)");
1209 for (
const slice_simplex &s : psl->
simplexes(ic)) {
1212 case 0: t = POS_PT;
break;
1213 case 1: t = POS_LN;
break;
1214 case 2: t = POS_TR;
break;
1215 case 3: t = POS_SI;
break;
1217 GMM_ASSERT1(t != -1,
"semi internal error.. could not map to a POS primitive type");
1218 pos_cell_type.push_back(
unsigned(t));
1220 const std::vector<unsigned>& dmap = getfem_to_pos_dof_mapping(t);
1221 GMM_ASSERT1(dmap.size() <=
size_type(t+1),
"inconsistency in pos_dof_mapping");
1223 std::vector<unsigned> cell_dof;
1224 cell_dof.resize(dmap.size(),
unsigned(-1));
1225 for (
size_type i=0; i < dmap.size(); ++i)
1226 cell_dof[i] =
unsigned(s.inodes[dmap[i]] + pcnt);
1227 pos_cell_dof.push_back(cell_dof);
1229 for (
const slice_node &n : psl->
nodes(ic)) {
1230 std::vector<float> pt;
1231 pt.resize(dim,
float(0));
1233 pt[i] =
float(n.pt[i]);
1234 pos_pts.push_back(pt);
1236 pcnt += psl->
nodes(ic).size();
1238 state = STRUCTURE_WRITTEN;
1241 void pos_export::write(
const mesh& m,
const std::string &name){
1242 if (state >= IN_CELL_DATA)
return;
1243 GMM_ASSERT1(
int(m.dim()) <= 3,
"attempt to export a "
1244 <<
int(m.dim()) <<
"D mesh (not supported)");
1245 pmf = std::make_unique<mesh_fem>(
const_cast<mesh&
>(m), dim_type(1));
1246 pmf->set_classical_finite_element(1);
1248 state = IN_CELL_DATA;
1251 void pos_export::write(
const mesh_fem& mf,
const std::string &name){
1252 if (state >= IN_CELL_DATA)
return;
1256 if (
""==name) os <<
"View \"mesh " << view <<
"\" {\n";
1257 else os <<
"View \"" << name <<
"\" {\n";
1260 std::vector<unsigned> cell_dof;
1261 std::vector<float> cell_dof_val;
1262 for (
size_type cell = 0; cell < pos_cell_type.size(); ++cell) {
1263 t = pos_cell_type[cell];
1264 cell_dof = pos_cell_dof[cell];
1265 cell_dof_val.resize(cell_dof.size(),
float(0));
1266 write_cell(t,cell_dof,cell_dof_val);
1270 os <<
"View[" << view <<
"].ShowScale = 0;\n";
1271 os <<
"View[" << view <<
"].ShowElement = 1;\n";
1272 os <<
"View[" << view <<
"].DrawScalars = 0;\n";
1273 os <<
"View[" << view <<
"].DrawVectors = 0;\n";
1274 os <<
"View[" << view++ <<
"].DrawTensors = 0;\n";
1275 state = IN_CELL_DATA;
1278 void pos_export::write(
const stored_mesh_slice& sl,
const std::string &name){
1279 if (state >= IN_CELL_DATA)
return;
1283 if (
""==name) os <<
"View \"mesh " << view <<
"\" {\n";
1284 else os <<
"View \"" << name <<
"\" {\n";
1287 std::vector<unsigned> cell_dof;
1288 std::vector<float> cell_dof_val;
1289 for (
size_type cell = 0; cell < pos_cell_type.size(); ++cell) {
1290 t = pos_cell_type[cell];
1291 cell_dof = pos_cell_dof[cell];
1292 cell_dof_val.resize(cell_dof.size(),
float(0));
1293 write_cell(t,cell_dof,cell_dof_val);
1297 os <<
"View[" << view <<
"].ShowScale = 0;\n";
1298 os <<
"View[" << view <<
"].ShowElement = 1;\n";
1299 os <<
"View[" << view <<
"].DrawScalars = 0;\n";
1300 os <<
"View[" << view <<
"].DrawVectors = 0;\n";
1301 os <<
"View[" << view++ <<
"].DrawTensors = 0;\n";
1302 state = IN_CELL_DATA;
convenient initialization of vectors via overload of "operator,".
Mesh structure definition.
const dal::bit_vector & convex_index() const
Return the list of valid convex IDs.
static T & instance()
Instance from the current thread.
std::string current_mesh_name()
return the name of current mesh (use exporting(...) to change the current mesh)
void serie_add_object(const std::string &serie_name, const std::string &object_name)
add an object (typically the name of a data field) to a 'series', i.e.
void set_header(const std::string &s)
the header is the second line of text in the exported file, you can put whatever you want – call this...
void exporting_mesh_edges(bool with_slice_edge=true)
append edges information (if you want to draw the mesh and are using a refined slice.
Describe a finite element method linked to a mesh.
virtual size_type first_convex_of_basic_dof(size_type d) const
Shortcut for convex_to_dof(d)[0].
virtual size_type nb_dof() const
Return the total number of degrees of freedom.
const mesh & linked_mesh() const
Return a reference to the underlying mesh.
void set_classical_finite_element(size_type cv, dim_type fem_degree, bool complete=false)
Set a classical (i.e.
virtual pfem fem_of_element(size_type cv) const
Return the basic fem associated with an element (if no fem is associated, the function will crash!...
const dal::bit_vector & convex_index() const
Get the set of convexes where a finite element has been assigned.
Describe a mesh (collection of convexes (elements) and points).
scalar_type convex_quality_estimate(size_type ic) const
Return an estimate of the convex quality (0 <= Q <= 1).
size_type dim() const
return the slice dimension
void nb_simplexes(std::vector< size_type > &c) const
return the simplex count, in an array.
const base_node merged_point(size_type i_merged) const
Return the physical position of the merged node.
const mesh_slicer::cs_nodes_ct & nodes(size_type ic) const
Return the list of nodes for the 'ic'th convex of the slice.
const mesh_slicer::cs_simplexes_ct & simplexes(size_type ic) const
Return the list of simplexes for the 'ic'th convex of the slice.
size_type nb_points() const
Return the number of nodes in the slice.
size_type nb_convex() const
return the number of convexes of the original mesh referenced in the slice
void get_edges(std::vector< size_type > &edges, dal::bit_vector &slice_edges, bool from_merged_nodes) const
Extract the list of mesh edges.
size_type nb_merged_nodes() const
Return the number of merged nodes in slice.
A simple singleton implementation.
Export solutions to various formats.
bool dof_linkable(pdof_description)
Says if the dof is linkable.
std::shared_ptr< const getfem::virtual_fem > pfem
type of pointer on a fem description
pfem fem_descriptor(const std::string &name)
get a fem descriptor from its string name.
pfem classical_discontinuous_fem(bgeot::pgeometric_trans pg, short_type k, scalar_type alpha=0, bool complete=false)
Give a pointer on the structures describing the classical polynomial discontinuous fem of degree k on...
pfem classical_fem(bgeot::pgeometric_trans pgt, short_type k, bool complete=false)
Give a pointer on the structures describing the classical polynomial fem of degree k on a given conve...
std::string name_of_fem(pfem p)
get the string name of a fem descriptor.
gmm::uint16_type short_type
used as the common short type integer in the library
std::string name_of_geometric_trans(pgeometric_trans p)
Get the string name of a geometric transformation.
std::shared_ptr< const convex_structure > pconvex_structure
Pointer on a convex structure description.
pconvex_structure simplex_structure(dim_type nc)
Give a pointer on the structures of a simplex of dimension d.
size_t size_type
used as the common size type in the library
pconvex_structure basic_structure(pconvex_structure cv)
Original structure (if concerned)
std::shared_ptr< const bgeot::geometric_trans > pgeometric_trans
pointer type for a geometric transformation
GEneric Tool for Finite Element Methods.