27 #ifndef OOMPH_TET_MESH_HEADER
28 #define OOMPH_TET_MESH_HEADER
32 #include <oomph-lib-config.h>
61 std::ostringstream error_stream;
62 error_stream <<
"TetMeshVertex should only be used in 3D!\n"
63 <<
"Your Vector of coordinates, contains data for "
64 <<
x.size() <<
"-dimensional coordinates." << std::endl;
66 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
74 const unsigned n_dim = node_pt->
ndim();
78 std::ostringstream error_stream;
79 error_stream <<
"TetMeshVertex should only be used in 3D!\n"
80 <<
"Your Node contains data for " << n_dim
81 <<
"-dimensional coordinates." << std::endl;
83 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
89 for (
unsigned i = 0;
i < n_dim; ++
i)
100 if (zeta.size() != 2)
102 std::ostringstream error_stream;
104 <<
"TetMeshVertex should only be used in 3D!\n"
105 <<
"Your Vector of intrinisic coordinates, contains data for "
106 << zeta.size() <<
"-dimensional coordinates but should be 2!"
109 error_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
124 double x(
const unsigned&
i)
const
218 for (
unsigned j = 0; j < nv; j++)
250 const unsigned& one_based_region_id)
266 outfile <<
"ZONE I=" << n + 1 << std::endl;
267 for (
unsigned j = 0; j < n; j++)
333 return Facet_pt[j]->one_based_boundary_id();
339 return Vertex_pt[j]->one_based_boundary_id();
395 for (
unsigned j = 0; j < n; j++)
405 std::ofstream outfile;
406 outfile.open(filename.c_str());
422 std::set<TetMeshVertex*> vertices;
428 unsigned n_vertices = 0;
431 unsigned n_facets =
Facet_pt.size();
432 for (
unsigned i = 0;
i < n_facets;
i++)
437 for (
unsigned j = 0; j < n_vertices; j++)
444 unsigned current_offset = 0;
448 std::set<TetMeshVertex*>::iterator iterator;
451 for (
const auto& individual_facet_pt :
Facet_pt)
454 n_vertices = individual_facet_pt->nvertex();
473 else if (n_vertices == 4)
485 for (
unsigned j = 0; j < n_vertices; j++)
487 iterator = vertices.find(individual_facet_pt->vertex_pt(j));
488 connectivity.push_back(std::distance(vertices.begin(), iterator));
493 current_offset += n_vertices;
494 offsets.push_back(current_offset);
506 outfile <<
"<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" "
507 "byte_order=\"BigEndian\">\n"
508 <<
"<UnstructuredGrid>\n"
509 <<
"<Piece NumberOfPoints=\"" << vertices.size()
510 <<
"\" NumberOfCells=\"" << offsets.size() <<
"\">" << std::endl;
515 outfile <<
"<Points>\n"
516 <<
"<DataArray type=\"Float32\" NumberOfComponents=\"3\" "
521 for (
const auto& vertex : vertices)
523 outfile << vertex->x(0) <<
" " << vertex->x(1) <<
" " << vertex->x(2)
527 outfile <<
"</DataArray>\n</Points>" << std::endl;
532 outfile <<
"<Cells>\n<DataArray type=\"Int32\" "
533 "Name=\"connectivity\" format=\"ascii\">"
537 for (
const auto& vertex_index : connectivity)
539 outfile << vertex_index <<
" ";
541 outfile << std::endl;
543 outfile <<
"</DataArray>" << std::endl;
548 outfile <<
"<DataArray type=\"Int32\" Name=\"offsets\" "
553 for (
const auto& offset : offsets)
555 outfile << offset <<
" ";
557 outfile << std::endl;
559 outfile <<
"</DataArray>" << std::endl;
564 outfile <<
"<DataArray type=\"Int32\" Name=\"types\" "
569 for (
const auto& type : types)
571 outfile << type <<
" ";
573 outfile << std::endl;
575 outfile <<
"</DataArray>\n</Cells>" << std::endl;
580 outfile <<
"</Piece>\n</UnstructuredGrid>\n</VTKFile>";
591 std::ofstream outfile;
592 outfile.open(filename.c_str());
604 const double& zeta_boundary,
608 zeta_vertex[0] =
Facet_pt[facet_id]->vertex_pt(0)->zeta_in_geom_object();
609 zeta_vertex[1] =
Facet_pt[facet_id]->vertex_pt(1)->zeta_in_geom_object();
610 zeta[0] = zeta_vertex[0][0] +
611 (zeta_vertex[1][0] - zeta_vertex[0][0]) * zeta_boundary;
612 zeta[1] = zeta_vertex[0][1] +
613 (zeta_vertex[1][1] - zeta_vertex[0][1]) * zeta_boundary;
623 const double& zeta_boundary,
627 zeta_vertex[0] =
Facet_pt[facet_id]->vertex_pt(1)->zeta_in_geom_object();
628 zeta_vertex[1] =
Facet_pt[facet_id]->vertex_pt(2)->zeta_in_geom_object();
629 zeta[0] = zeta_vertex[0][0] +
630 (zeta_vertex[1][0] - zeta_vertex[0][0]) * zeta_boundary;
631 zeta[1] = zeta_vertex[0][1] +
632 (zeta_vertex[1][1] - zeta_vertex[0][1]) * zeta_boundary;
642 const double& zeta_boundary,
646 zeta_vertex[0] =
Facet_pt[facet_id]->vertex_pt(2)->zeta_in_geom_object();
647 zeta_vertex[1] =
Facet_pt[facet_id]->vertex_pt(0)->zeta_in_geom_object();
648 zeta[0] = zeta_vertex[0][0] +
649 (zeta_vertex[1][0] - zeta_vertex[0][0]) * zeta_boundary;
650 zeta[1] = zeta_vertex[0][1] +
651 (zeta_vertex[1][1] - zeta_vertex[0][1]) * zeta_boundary;
693 for (
unsigned f = 0; f < nf; f++)
695 unsigned nv =
Facet_pt[f]->nvertex();
697 for (
unsigned v = 0; v < nv; v++)
700 for (
unsigned j = 0; j < nv_overall; j++)
755 const unsigned&
i)
const
772 std::make_pair(region_point, region_id));
887 template<
class ELEMENT>
891 std::ofstream some_file;
894 bool switch_normal =
false;
895 this->setup_boundary_coordinates<ELEMENT>(b, switch_normal, some_file);
918 template<
class ELEMENT>
920 const bool& switch_normal)
923 std::ofstream some_file;
925 this->setup_boundary_coordinates<ELEMENT>(b, switch_normal, some_file);
949 template<
class ELEMENT>
951 const bool& switch_normal,
952 std::ofstream& outfile);
973 template<
class ELEMENT>
977 bool switch_normal =
false;
978 this->setup_boundary_coordinates<ELEMENT>(b, switch_normal, outfile);
984 const unsigned& r)
const
988 std::map<unsigned, Vector<FiniteElement*>>::const_iterator it =
992 return (it->second).size();
1004 const unsigned&
e)
const
1007 std::map<unsigned, Vector<FiniteElement*>>::const_iterator it =
1011 return (it->second)[
e];
1022 const unsigned&
e)
const
1025 std::map<unsigned, Vector<int>>::const_iterator it =
1029 return (it->second)[
e];
1033 std::ostringstream error_message;
1034 error_message <<
"Face indices not set up for boundary " << b
1035 <<
" in region " << r <<
"\n";
1036 error_message <<
"This probably means that the boundary is not "
1037 "adjacent to region\n";
1039 OOMPH_CURRENT_FUNCTION,
1040 OOMPH_EXCEPTION_LOCATION);
1057 for (
unsigned i = 0;
i < n;
i++)
1065 std::ostringstream error_message;
1066 error_message <<
"Region attributes should be unsigneds because we \n"
1067 <<
"only use them to set region ids\n";
1069 OOMPH_CURRENT_FUNCTION,
1070 OOMPH_EXCEPTION_LOCATION);
1103 for (
unsigned i = 0;
i < n;
i++)
1111 std::ostringstream error_message;
1112 error_message <<
"Region attributes should be unsigneds because we \n"
1113 <<
"only use the to set region ids\n";
1115 OOMPH_CURRENT_FUNCTION,
1116 OOMPH_EXCEPTION_LOCATION);
1147 template<
class ELEMENT>
1151 const bool& switch_normal,
1164 template<
class ELEMENT>
1168 const bool& switch_normal)
1173 snap_to_quadratic_surface<ELEMENT>(
1174 boundary_id, quadratic_surface_file_name, switch_normal, doc_info);
1186 template<
class ELEMENT>
1195 std::ofstream outfile;
1239 std::map<unsigned, Vector<Vector<double>>>
1277 template<
class ELEMENT>
1279 const bool& switch_normal,
1280 std::ofstream& outfile)
1282 Node* lower_left_node_pt = 0;
1283 Node* upper_right_node_pt = 0;
1297 f_pt = (*it).second;
1310 bool vertices_are_in_same_plane =
true;
1311 for (
unsigned do_for_real = 0; do_for_real < 2; do_for_real++)
1322 for (
unsigned e = 0;
e < nel;
e++)
1331 face_el_pt.push_back(
1335 if (outfile.is_open())
1337 face_el_pt[face_el_pt.size() - 1]->output(outfile);
1347 for (
unsigned j = 0; j < nnod; j++)
1354 if (nod_pt->
x(2) < lower_left_node_pt->
x(2))
1356 lower_left_node_pt = nod_pt;
1359 else if (nod_pt->
x(2) == lower_left_node_pt->
x(2))
1362 if (nod_pt->
x(1) < lower_left_node_pt->
x(1))
1364 lower_left_node_pt = nod_pt;
1367 else if (nod_pt->
x(1) == lower_left_node_pt->
x(1))
1370 if (nod_pt->
x(0) < lower_left_node_pt->
x(0))
1372 lower_left_node_pt = nod_pt;
1379 if (nod_pt->
x(2) > upper_right_node_pt->
x(2))
1381 upper_right_node_pt = nod_pt;
1384 else if (nod_pt->
x(2) == upper_right_node_pt->
x(2))
1387 if (nod_pt->
x(1) > upper_right_node_pt->
x(1))
1389 upper_right_node_pt = nod_pt;
1392 else if (nod_pt->
x(1) == upper_right_node_pt->
x(1))
1395 if (nod_pt->
x(0) > upper_right_node_pt->
x(0))
1397 upper_right_node_pt = nod_pt;
1414 b0[0] = upper_right_node_pt->
x(0) - lower_left_node_pt->
x(0);
1415 b0[1] = upper_right_node_pt->
x(1) - lower_left_node_pt->
x(1);
1416 b0[2] = upper_right_node_pt->
x(2) - lower_left_node_pt->
x(2);
1420 1.0 / sqrt(b0[0] * b0[0] + b0[1] * b0[1] + b0[2] * b0[2]);
1421 b0[0] *= inv_length;
1422 b0[1] *= inv_length;
1423 b0[2] *= inv_length;
1434 ->outer_unit_normal(
s, normal);
1450 normal[0] = t1y * t2z - t1z * t2y;
1451 normal[1] = t1z * t2x - t1x * t2z;
1452 normal[2] = t1x * t2y - t1y * t2x;
1454 1.0 / sqrt(normal[0] * normal[0] + normal[1] * normal[1] +
1455 normal[2] * normal[2]);
1456 normal[0] *= inv_length;
1457 normal[1] *= inv_length;
1458 normal[2] *= inv_length;
1463 normal[0] = -normal[0];
1464 normal[1] = -normal[1];
1465 normal[2] = -normal[2];
1474 for (
unsigned e = 0;
e < nel;
e++)
1479 ->outer_unit_normal(
s, my_normal);
1482 double dot_prod = normal[0] * my_normal[0] +
1483 normal[1] * my_normal[1] + normal[2] * my_normal[2];
1486 double error = abs(dot_prod) - 1.0;
1489 vertices_are_in_same_plane =
false;
1494 if (vertices_are_in_same_plane)
1497 b1[0] = b0[1] * normal[2] - b0[2] * normal[1];
1498 b1[1] = b0[2] * normal[0] - b0[0] * normal[2];
1499 b1[2] = b0[0] * normal[1] - b0[1] * normal[0];
1506 for (
unsigned j = 0; j < nnod; j++)
1513 delta[0] = nod_pt->
x(0) - lower_left_node_pt->
x(0);
1514 delta[1] = nod_pt->
x(1) - lower_left_node_pt->
x(1);
1515 delta[2] = nod_pt->
x(2) - lower_left_node_pt->
x(2);
1524 zeta[0] = delta[0] * b0[0] + delta[1] * b0[1] + delta[2] * b0[2];
1525 zeta[1] = delta[0] * b1[0] + delta[1] * b1[1] + delta[2] * b1[2];
1528 double error = pow(lower_left_node_pt->
x(0) + zeta[0] * b0[0] +
1529 zeta[1] * b1[0] - nod_pt->
x(0),
1531 pow(lower_left_node_pt->
x(1) + zeta[0] * b0[1] +
1532 zeta[1] * b1[1] - nod_pt->
x(1),
1534 pow(lower_left_node_pt->
x(2) + zeta[0] * b0[2] +
1535 zeta[1] * b1[2] - nod_pt->
x(2),
1540 std::ostringstream error_message;
1542 <<
"Error in projection of boundary coordinates = "
1543 << sqrt(error) <<
" > Tolerance_for_boundary_finding = "
1545 <<
"nv = " << nv << std::endl
1546 <<
"Lower left: " << lower_left_node_pt->
x(0) <<
" "
1547 << lower_left_node_pt->
x(1) <<
" " << lower_left_node_pt->
x(2)
1549 <<
"Upper right: " << upper_right_node_pt->
x(0) <<
" "
1550 << upper_right_node_pt->
x(1) <<
" " << upper_right_node_pt->
x(2)
1553 for (
unsigned j = 0; j < nnod; j++)
1557 error_message << nod_pt->
x(0) <<
" " << nod_pt->
x(1) <<
" "
1558 << nod_pt->
x(2) <<
" " << std::endl;
1561 OOMPH_CURRENT_FUNCTION,
1562 OOMPH_EXCEPTION_LOCATION);
1566 if (do_for_real == 1)
1576 if (do_for_real == 1)
1587 for (
unsigned j = 0; j < 3; j++)
1594 delta[0] = f_pt->
vertex_pt(j)->
x(0) - lower_left_node_pt->
x(0);
1595 delta[1] = f_pt->
vertex_pt(j)->
x(1) - lower_left_node_pt->
x(1);
1596 delta[2] = f_pt->
vertex_pt(j)->
x(2) - lower_left_node_pt->
x(2);
1600 zeta[0] = delta[0] * b0[0] + delta[1] * b0[1] + delta[2] * b0[2];
1601 zeta[1] = delta[0] * b1[0] + delta[1] * b1[1] + delta[2] * b1[2];
1603 for (
unsigned ii = 0; ii < 2; ii++)
1614 unsigned n = face_el_pt.size();
1615 for (
unsigned e = 0;
e < n;
e++)
1617 delete face_el_pt[
e];
1621 if (!vertices_are_in_same_plane)
1644 template<
class ELEMENT>
1648 const bool& switch_normal,
1655 std::ofstream the_file_non_snapped;
1657 "non_snapped_nodes_" + doc_info.
label() +
".dat";
1660 std::ifstream infile(quadratic_surface_file_name.c_str(),
1666 infile.getline(dummy, 100);
1673 infile.getline(dummy, 100);
1676 if (nel != boundary_id.size())
1678 std::ostringstream error_message;
1679 error_message <<
"Number of quadratic facets specified in "
1680 << quadratic_surface_file_name <<
"is: " << nel
1681 <<
"\nThis doesn't match the number of planar boundaries \n"
1682 <<
"specified in boundary_id which is "
1683 << boundary_id.size() << std::endl;
1685 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
1692 for (
unsigned e = 0;
e < nel;
e++)
1700 unsigned n_position_type = 1;
1701 unsigned initial_n_value = 0;
1704 std::map<unsigned, unsigned> node_number;
1705 std::ofstream node_file;
1706 for (
unsigned j = 0; j < n_node; j++)
1710 infile >> nod_pt[j]->x(0);
1711 infile >> nod_pt[j]->x(1);
1712 infile >> nod_pt[j]->x(2);
1713 infile >> node_nmbr;
1714 node_number[node_nmbr] = j;
1721 for (
unsigned e = 0;
e < nel;
e++)
1723 unsigned nnod_el = face_el_pt[
e]->nnode();
1725 for (
unsigned j = 0; j < nnod_el; j++)
1728 face_el_pt[
e]->node_pt(j) = nod_pt[node_number[j_global]];
1729 face_el_pt[
e]->node_pt(j)->add_to_boundary(boundary_id[
e]);
1731 face_el_pt[
e]->set_boundary_number_in_bulk_mesh(boundary_id[
e]);
1732 face_el_pt[
e]->set_nodal_dimension(3);
1741 for (
unsigned e = 0;
e < nel;
e++)
1746 Node* lower_left_node_pt = face_el_pt[
e]->node_pt(0);
1747 Node* upper_right_node_pt = face_el_pt[
e]->node_pt(0);
1750 for (
unsigned j = 0; j < 3; j++)
1753 Node* nod_pt = face_el_pt[
e]->node_pt(j);
1756 if (nod_pt->
x(2) < lower_left_node_pt->
x(2))
1758 lower_left_node_pt = nod_pt;
1761 else if (nod_pt->
x(2) == lower_left_node_pt->
x(2))
1764 if (nod_pt->
x(1) < lower_left_node_pt->
x(1))
1766 lower_left_node_pt = nod_pt;
1769 else if (nod_pt->
x(1) == lower_left_node_pt->
x(1))
1772 if (nod_pt->
x(0) < lower_left_node_pt->
x(0))
1774 lower_left_node_pt = nod_pt;
1781 if (nod_pt->
x(2) > upper_right_node_pt->
x(2))
1783 upper_right_node_pt = nod_pt;
1786 else if (nod_pt->
x(2) == upper_right_node_pt->
x(2))
1789 if (nod_pt->
x(1) > upper_right_node_pt->
x(1))
1791 upper_right_node_pt = nod_pt;
1794 else if (nod_pt->
x(1) == upper_right_node_pt->
x(1))
1797 if (nod_pt->
x(0) > upper_right_node_pt->
x(0))
1799 upper_right_node_pt = nod_pt;
1810 b0[0] = upper_right_node_pt->
x(0) - lower_left_node_pt->
x(0);
1811 b0[1] = upper_right_node_pt->
x(1) - lower_left_node_pt->
x(1);
1812 b0[2] = upper_right_node_pt->
x(2) - lower_left_node_pt->
x(2);
1816 1.0 / sqrt(b0[0] * b0[0] + b0[1] * b0[1] + b0[2] * b0[2]);
1817 b0[0] *= inv_length;
1818 b0[1] *= inv_length;
1819 b0[2] *= inv_length;
1829 face_el_pt[
e]->node_pt(1)->x(0) - face_el_pt[
e]->node_pt(0)->x(0);
1831 face_el_pt[
e]->node_pt(1)->x(1) - face_el_pt[
e]->node_pt(0)->x(1);
1833 face_el_pt[
e]->node_pt(1)->x(2) - face_el_pt[
e]->node_pt(0)->x(2);
1835 face_el_pt[
e]->node_pt(2)->x(0) - face_el_pt[
e]->node_pt(0)->x(0);
1837 face_el_pt[
e]->node_pt(2)->x(1) - face_el_pt[
e]->node_pt(0)->x(1);
1839 face_el_pt[
e]->node_pt(2)->x(2) - face_el_pt[
e]->node_pt(0)->x(2);
1840 normal[0] = -(tang1[1] * tang2[2] - tang1[2] * tang2[1]);
1841 normal[1] = -(tang1[2] * tang2[0] - tang1[0] * tang2[2]);
1842 normal[2] = -(tang1[0] * tang2[1] - tang1[1] * tang2[0]);
1845 inv_length = 1.0 / sqrt(normal[0] * normal[0] + normal[1] * normal[1] +
1846 normal[2] * normal[2]);
1847 normal[0] *= inv_length;
1848 normal[1] *= inv_length;
1849 normal[2] *= inv_length;
1854 normal[0] = -normal[0];
1855 normal[1] = -normal[1];
1856 normal[2] = -normal[2];
1861 b1[0] = b0[1] * normal[2] - b0[2] * normal[1];
1862 b1[1] = b0[2] * normal[0] - b0[0] * normal[2];
1863 b1[2] = b0[0] * normal[1] - b0[1] * normal[0];
1866 for (
unsigned j = 0; j < 3; j++)
1869 Node* nod_pt = face_el_pt[
e]->node_pt(j);
1873 delta[0] = nod_pt->
x(0) - lower_left_node_pt->
x(0);
1874 delta[1] = nod_pt->
x(1) - lower_left_node_pt->
x(1);
1875 delta[2] = nod_pt->
x(2) - lower_left_node_pt->
x(2);
1878 zeta[0] = delta[0] * b0[0] + delta[1] * b0[1] + delta[2] * b0[2];
1879 zeta[1] = delta[0] * b1[0] + delta[1] * b1[1] + delta[2] * b1[2];
1881 vertex_boundary_coord[j].resize(2);
1882 vertex_boundary_coord[j][0] = zeta[0];
1883 vertex_boundary_coord[j][1] = zeta[1];
1888 double error = pow(lower_left_node_pt->
x(0) + zeta[0] * b0[0] +
1889 zeta[1] * b1[0] - nod_pt->
x(0),
1891 pow(lower_left_node_pt->
x(1) + zeta[0] * b0[1] +
1892 zeta[1] * b1[1] - nod_pt->
x(1),
1894 pow(lower_left_node_pt->
x(2) + zeta[0] * b0[2] +
1895 zeta[1] * b1[2] - nod_pt->
x(2),
1900 std::ostringstream error_message;
1902 <<
"Error in setup of boundary coordinate " << sqrt(error)
1904 <<
"exceeds tolerance specified by the static member data\n"
1905 <<
"TetMeshBase::Tolerance_for_boundary_finding = "
1907 <<
"This usually means that the boundary is not planar.\n\n"
1908 <<
"You can suppress this error message by recompiling \n"
1909 <<
"recompiling without PARANOID or by changing the tolerance.\n";
1911 OOMPH_CURRENT_FUNCTION,
1912 OOMPH_EXCEPTION_LOCATION);
1925 0.5 * (vertex_boundary_coord[0][0] + vertex_boundary_coord[1][0]);
1927 0.5 * (vertex_boundary_coord[0][1] + vertex_boundary_coord[1][1]);
1928 face_el_pt[
e]->node_pt(3)->set_coordinates_on_boundary(boundary_id[
e],
1933 0.5 * (vertex_boundary_coord[1][0] + vertex_boundary_coord[2][0]);
1935 0.5 * (vertex_boundary_coord[1][1] + vertex_boundary_coord[2][1]);
1936 face_el_pt[
e]->node_pt(4)->set_coordinates_on_boundary(boundary_id[
e],
1941 0.5 * (vertex_boundary_coord[2][0] + vertex_boundary_coord[0][0]);
1943 0.5 * (vertex_boundary_coord[2][1] + vertex_boundary_coord[0][1]);
1944 face_el_pt[
e]->node_pt(5)->set_coordinates_on_boundary(boundary_id[
e],
1950 bool success =
true;
1951 for (
unsigned b = 0; b < nel; b++)
1954 std::ofstream the_file;
1955 std::ofstream the_file_before;
1956 std::ofstream the_file_after;
1959 std::ostringstream filename;
1960 filename << doc_info.
directory() <<
"/quadratic_coordinates_"
1961 << doc_info.
label() << b <<
".dat";
1962 the_file.open(filename.str().c_str());
1964 std::ostringstream filename1;
1965 filename1 << doc_info.
directory() <<
"/quadratic_nodes_before_"
1966 << doc_info.
label() << b <<
".dat";
1967 the_file_before.open(filename1.str().c_str());
1969 std::ostringstream filename2;
1970 filename2 << doc_info.
directory() <<
"/quadratic_nodes_after_"
1971 << doc_info.
label() << b <<
".dat";
1972 the_file_after.open(filename2.str().c_str());
1984 unsigned n_plot = 3;
1985 the_file << el_pt->tecplot_zone_string(n_plot);
1988 unsigned num_plot_points = el_pt->nplot_points(n_plot);
1989 for (
unsigned iplot = 0; iplot < num_plot_points; iplot++)
1992 el_pt->get_s_plot(iplot, n_plot,
s);
1993 el_pt->interpolated_zeta(
s, zeta);
1994 el_pt->interpolated_x(
s, x);
1995 for (
unsigned i = 0;
i < 3;
i++)
1997 the_file << x[
i] <<
" ";
1999 for (
unsigned i = 0;
i < 2;
i++)
2001 the_file << zeta[
i] <<
" ";
2003 the_file << std::endl;
2005 el_pt->write_tecplot_zone_footer(the_file, n_plot);
2021 for (
unsigned e = 0;
e < nel;
e++)
2028 unsigned nnod = bulk_elem_pt->
nnode();
2029 for (
unsigned j = 0; j < nnod; j++)
2039 the_file_before << nod_pt->
x(0) <<
" " << nod_pt->
x(1) <<
" "
2040 << nod_pt->
x(2) <<
" " << boundary_zeta[0] <<
" "
2041 << boundary_zeta[1] <<
" " << std::endl;
2045 el_pt->locate_zeta(boundary_zeta, geom_obj_pt, s_geom_obj);
2046 if (geom_obj_pt != 0)
2048 geom_obj_pt->
position(s_geom_obj, quadratic_coordinates);
2049 nod_pt->
x(0) = quadratic_coordinates[0];
2050 nod_pt->
x(1) = quadratic_coordinates[1];
2051 nod_pt->
x(2) = quadratic_coordinates[2];
2058 std::ostringstream error_message;
2060 <<
"Warning: Couldn't find GeomObject during snapping to\n"
2061 <<
"quadratic surface for boundary " << boundary_id[b]
2062 <<
". I'm leaving the node where it was. Will bail out "
2065 "TetgenMesh::snap_to_quadratic_surface()",
2066 OOMPH_EXCEPTION_LOCATION);
2067 if (!the_file_non_snapped.is_open())
2069 the_file_non_snapped.open(non_snapped_filename.c_str());
2071 the_file_non_snapped << nod_pt->
x(0) <<
" " << nod_pt->
x(1) <<
" "
2072 << nod_pt->
x(2) <<
" " << boundary_zeta[0]
2073 <<
" " << boundary_zeta[1] <<
" "
2080 the_file_after << nod_pt->
x(0) <<
" " << nod_pt->
x(1) <<
" "
2081 << nod_pt->
x(2) <<
" " << boundary_zeta[0] <<
" "
2082 << boundary_zeta[1] <<
" " << std::endl;
2090 the_file_before.close();
2091 the_file_after.close();
2097 std::ostringstream error_message;
2099 <<
"Warning: Couldn't find GeomObject during snapping to\n"
2100 <<
"quadratic surface. Bailing out.\n"
2101 <<
"Nodes that couldn't be snapped are contained in \n"
2102 <<
"file: " << non_snapped_filename <<
".\n"
2103 <<
"This problem may arise because the switch_normal flag was \n"
2104 <<
"set wrongly.\n";
2106 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
2110 if (!the_file_non_snapped.is_open())
2112 the_file_non_snapped.close();
2116 for (
unsigned e = 0;
e < nel;
e++)
2118 delete face_el_pt[
e];
2123 unsigned nn = nod_pt.size();
2124 for (
unsigned j = 0; j < nn; j++)
2135 template<
class ELEMENT>
2150 if ((nnode_1d != 2) && (nnode_1d != 3))
2152 std::ostringstream error_message;
2153 error_message <<
"Mesh generation from tetgen currently only works\n";
2154 error_message <<
"for nnode_1d = 2 or 3. You're trying to use it\n";
2155 error_message <<
"for nnode_1d=" << nnode_1d << std::endl;
2158 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
2162 std::map<FiniteElement*, unsigned> count;
2166 for (
unsigned b = 0; b < nb; b++)
2170 for (
unsigned e = 0;
e < nel;
e++)
2183 std::set<FiniteElement*> elements_to_be_split;
2184 for (std::map<FiniteElement*, unsigned>::iterator it = count.begin();
2194 elements_to_be_split.insert(el_pt);
2201 new_or_retained_el_pt.reserve(nel);
2205 std::map<FiniteElement*, Vector<FiniteElement*>>
2206 old_to_new_corner_element_map;
2209 for (
unsigned e = 0;
e < nel;
e++)
2215 std::set<FiniteElement*>::iterator it = std::find(
2216 elements_to_be_split.begin(), elements_to_be_split.end(), el_pt);
2219 if (it == elements_to_be_split.end())
2222 new_or_retained_el_pt.push_back(el_pt);
2239 Node* node10_pt = 0;
2260 node0_pt = el_pt->
node_pt(14);
2261 el1_pt->
node_pt(2) = node0_pt;
2303 el2_pt->
node_pt(3) = node0_pt;
2306 el2_pt->
node_pt(6) = node1_pt;
2307 el2_pt->
node_pt(9) = node2_pt;
2313 el2_pt->
node_pt(10) = node5_pt;
2334 el3_pt->
node_pt(0) = node0_pt;
2337 el3_pt->
node_pt(4) = node2_pt;
2338 el3_pt->
node_pt(5) = node3_pt;
2339 el3_pt->
node_pt(6) = node4_pt;
2345 el3_pt->
node_pt(10) = node6_pt;
2346 el3_pt->
node_pt(11) = node10_pt;
2367 el4_pt->
node_pt(1) = node0_pt;
2370 el4_pt->
node_pt(4) = node1_pt;
2371 el4_pt->
node_pt(7) = node3_pt;
2372 el4_pt->
node_pt(9) = node4_pt;
2378 el4_pt->
node_pt(10) = node9_pt;
2379 el4_pt->
node_pt(11) = node8_pt;
2381 el4_pt->
node_pt(13) = node7_pt;
2387 new_or_retained_el_pt.push_back(el1_pt);
2388 new_or_retained_el_pt.push_back(el2_pt);
2389 new_or_retained_el_pt.push_back(el3_pt);
2390 new_or_retained_el_pt.push_back(el4_pt);
2394 temp_vec[0] = el1_pt;
2395 temp_vec[1] = el2_pt;
2396 temp_vec[2] = el3_pt;
2397 temp_vec[3] = el4_pt;
2400 old_to_new_corner_element_map.insert(
2421 for (
unsigned i = 0;
i < 3;
i++)
2433 node1_pt->
x(
i) = 0.5 * (el_pt->
node_pt(0)->
x(
i) + node0_pt->
x(
i));
2434 node2_pt->
x(
i) = 0.5 * (el_pt->
node_pt(1)->
x(
i) + node0_pt->
x(
i));
2435 node3_pt->
x(
i) = 0.5 * (el_pt->
node_pt(2)->
x(
i) + node0_pt->
x(
i));
2436 node4_pt->
x(
i) = 0.5 * (el_pt->
node_pt(3)->
x(
i) + node0_pt->
x(
i));
2447 for (
unsigned i = 0;
i < 3; ++
i)
2456 for (
unsigned i = 0;
i < 3; ++
i)
2465 for (
unsigned i = 0;
i < 3; ++
i)
2474 for (
unsigned i = 0;
i < 3; ++
i)
2483 for (
unsigned i = 0;
i < 3; ++
i)
2492 for (
unsigned i = 0;
i < 3; ++
i)
2504 for (
unsigned i = 0;
i < 3; ++
i)
2506 double av_pos = 0.0;
2507 for (
unsigned j = 0; j < 4; j++)
2512 temp_nod_pt->
x(
i) = 0.25 * av_pos;
2519 for (
unsigned i = 0;
i < 3; ++
i)
2521 double av_pos = 0.0;
2522 for (
unsigned j = 0; j < 4; j++)
2526 temp_nod_pt->
x(
i) = 0.25 * av_pos;
2532 for (
unsigned i = 0;
i < 3; ++
i)
2534 double av_pos = 0.0;
2535 for (
unsigned j = 0; j < 4; j++)
2539 temp_nod_pt->
x(
i) = 0.25 * av_pos;
2545 for (
unsigned i = 0;
i < 3; ++
i)
2547 double av_pos = 0.0;
2548 for (
unsigned j = 0; j < 4; j++)
2552 temp_nod_pt->
x(
i) = 0.25 * av_pos;
2566 nel = new_or_retained_el_pt.size();
2568 for (
unsigned e = 0;
e < nel;
e++)
2599 if (old_to_new_corner_element_map.size() == 0)
2601 oomph_info <<
"\nNo corner elements need splitting\n\n";
2610 old_to_new_corner_element_map.begin();
2611 map_it != old_to_new_corner_element_map.end();
2618 unsigned original_region_index = 0;
2644 original_region_index = region_index;
2659 std::ostringstream error_message;
2661 <<
"The corner element being split does not appear to be in any "
2662 <<
"region, so something has gone wrong with the region lookup "
2666 OOMPH_CURRENT_FUNCTION,
2667 OOMPH_EXCEPTION_LOCATION);
2674 for (
unsigned i = 0;
i < 4;
i++)
2688 for (
unsigned b = 0; b <
nboundary(); b++)
2692 for (
unsigned e = 0;
e < nel;
e++)
2719 oomph_info <<
"\nNumber of outer corner elements split: "
2720 << old_to_new_corner_element_map.size() <<
"\n\n";
A template Class for BoundaryNodes; that is Nodes that MAY live on the boundary of a Mesh....
Base class for upgraded disk-like GeomObject (i.e. 2D surface in 3D space) with specification of boun...
Information for documentation of results: Directory and file number to enable output in the form RESL...
bool is_doc_enabled() const
Are we documenting?
void disable_doc()
Disable documentation.
std::string & label()
String used (e.g.) for labeling output files.
std::string directory() const
Output directory.
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
A general Finite Element class.
virtual Node * construct_node(const unsigned &n)
Construct the local node n and return a pointer to the newly created node object.
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
unsigned nnode() const
Return the number of nodes.
virtual unsigned nnode_1d() const
Return the number of nodes along one edge of the element Default is to return zero — must be overload...
virtual Node * construct_boundary_node(const unsigned &n)
Construct the local node n as a boundary node; that is a node that MAY be placed on a mesh boundary a...
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
/////////////////////////////////////////////////////////////////////
virtual void position(const Vector< double > &zeta, Vector< double > &r) const =0
Parametrised position on object at current time: r(zeta).
unsigned long nboundary_node(const unsigned &ibound) const
Return number of nodes on a particular boundary.
static Steady< 0 > Default_TimeStepper
Default Steady Timestepper, to be used in default arguments to Mesh constructors.
bool Lookup_for_elements_next_boundary_is_setup
Flag to indicate that the lookup schemes for elements that are adjacent to the boundaries has been se...
std::vector< bool > Boundary_coordinate_exists
Vector of boolean data that indicates whether the boundary coordinates have been set for the boundary...
FiniteElement * finite_element_pt(const unsigned &e) const
Upcast (downcast?) to FiniteElement (needed to access FiniteElement member functions).
int face_index_at_boundary(const unsigned &b, const unsigned &e) const
For the e-th finite element on boundary b, return int to indicate the face_index of the face adjacent...
unsigned nboundary_element(const unsigned &b) const
Return number of finite elements that are adjacent to boundary b.
unsigned nboundary() const
Return number of boundaries.
FiniteElement * boundary_element_pt(const unsigned &b, const unsigned &e) const
Return pointer to e-th finite element on boundary b.
unsigned long nnode() const
Return number of nodes in the mesh.
void add_node_pt(Node *const &node_pt)
Add a (pointer to a) node to the mesh.
Node *& boundary_node_pt(const unsigned &b, const unsigned &n)
Return pointer to node n on boundary b.
Vector< GeneralisedElement * > Element_pt
Vector of pointers to generalised elements.
unsigned long nelement() const
Return number of elements in the mesh.
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
double & x(const unsigned &i)
Return the i-th nodal coordinate.
virtual bool is_on_boundary() const
Test whether the Node lies on a boundary. The "bulk" Node cannot lie on a boundary,...
unsigned ndim() const
Return (Eulerian) spatial dimension of the node.
virtual void set_coordinates_on_boundary(const unsigned &b, const unsigned &k, const Vector< double > &boundary_zeta)
Set the vector of the k-th generalised boundary coordinates on mesh boundary b. Broken virtual interf...
virtual void get_coordinates_on_boundary(const unsigned &b, const unsigned &k, Vector< double > &boundary_zeta)
Return the vector of the k-th generalised boundary coordinates on mesh boundary b....
An OomphLibError object which should be thrown when an run-time error is encountered....
An OomphLibWarning object which should be created as a temporary object to issue a warning....
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
virtual ~TetMeshBase()
Destructor (empty)
void snap_nodes_onto_geometric_objects()
Move the nodes on boundaries with associated GeomObjects so that they exactly coincide with the geome...
void snap_to_quadratic_surface(const Vector< unsigned > &boundary_id, const std::string &quadratic_surface_file_name, const bool &switch_normal, DocInfo &doc_info)
Snap boundaries specified by the IDs listed in boundary_id to a quadratric surface,...
int face_index_at_boundary_in_region(const unsigned &b, const unsigned &r, const unsigned &e) const
Return face index of the e-th element adjacent to boundary b in region r.
Vector< double > Region_attribute
Vector of attributes associated with the elements in each region NOTE: double is enforced on us by te...
double region_attribute(const unsigned &i)
Return the i-th region attribute (here only used as the (assumed to be unsigned) region id.
void setup_boundary_coordinates(const unsigned &b, const bool &switch_normal)
Setup boundary coordinate on boundary b which is assumed to be planar. Boundary coordinates are the x...
unsigned nregion()
Return the number of regions specified by attributes.
TimeStepper * Time_stepper_pt
Timestepper used to build nodes.
unsigned nboundary_element_in_region(const unsigned &b, const unsigned &r) const
Return the number of elements adjacent to boundary b in region r.
std::map< unsigned, TetMeshFacetedSurface * > Tet_mesh_faceted_surface_pt
Reverse lookup scheme: Pointer to faceted surface (if any!) associated with boundary b.
Vector< TetMeshFacetedSurface * > Internal_surface_pt
Vector to faceted surfaces that define internal boundaries.
Vector< std::map< unsigned, Vector< FiniteElement * > > > Boundary_region_element_pt
Storage for elements adjacent to a boundary in a particular region.
void operator=(const TetMeshBase &)=delete
Broken assignment operator.
std::map< unsigned, TetMeshFacet * > Tet_mesh_facet_pt
Reverse lookup scheme: Pointer to facet (if any!) associated with boundary b.
void setup_boundary_coordinates(const unsigned &b)
Setup boundary coordinate on boundary b which is assumed to be planar. Boundary coordinates are the x...
TetMeshFacetedClosedSurface * Outer_boundary_pt
Faceted surface that defines outer boundaries.
FiniteElement * boundary_element_in_region_pt(const unsigned &b, const unsigned &r, const unsigned &e) const
Return pointer to the e-th element adjacent to boundary b in region r.
static double Tolerance_for_boundary_finding
Global static data that specifies the permitted error in the setup of the boundary coordinates.
void assess_mesh_quality(std::ofstream &some_file)
Assess mesh quality: Ratio of max. edge length to min. height, so if it's very large it's BAAAAAD.
FiniteElement * region_element_pt(const unsigned &r, const unsigned &e)
Return the e-th element in the r-th region.
TetMeshBase()
Constructor.
void snap_to_quadratic_surface(const Vector< unsigned > &boundary_id, const std::string &quadratic_surface_file_name, const bool &switch_normal)
Snap boundaries specified by the IDs listed in boundary_id to a quadratric surface,...
void setup_boundary_element_info()
Setup lookup schemes which establish which elements are located next to mesh's boundaries (wrapper to...
Vector< std::map< unsigned, Vector< int > > > Face_index_region_at_boundary
Storage for the face index adjacent to a boundary in a particular region.
std::map< unsigned, Vector< Vector< double > > > Triangular_facet_vertex_boundary_coordinate
Boundary coordinates of vertices in triangular facets associated with given boundary....
TetMeshBase(const TetMeshBase &node)=delete
Broken copy constructor.
Vector< Vector< FiniteElement * > > Region_element_pt
Vectors of vectors of elements in each region (note: this just stores them; the region IDs are contai...
void split_elements_in_corners(TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Non-Delaunay split elements that have three faces on a boundary into sons. Timestepper species timest...
void setup_boundary_coordinates(const unsigned &b, std::ofstream &outfile)
Setup boundary coordinate on boundary b which is assumed to be planar. Boundary coordinates are the x...
unsigned nregion_element(const unsigned &r)
Return the number of elements in region r.
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
Vector< TetMeshVertex * > Vertex_pt
Pointer to vertices.
void set_vertex_pt(const unsigned &j, TetMeshVertex *vertex_pt)
Set pointer to j-th vertex and pass one-based boundary id that may already have been set for this fac...
TetMeshVertex * vertex_pt(const unsigned &j) const
Pointer to j-th vertex (const)
void output(std::ostream &outfile) const
Output.
void set_one_based_region_that_facet_is_embedded_in(const unsigned &one_based_region_id)
Facet is to be embedded in specified one-based region.
std::set< unsigned > One_based_adjacent_region_id
Set of one-based adjacent region ids; no adjacent region if it's zero.
bool facet_is_embedded_in_a_specified_region()
Boolean indicating that facet is embedded in a specified region.
void set_one_based_boundary_id(const unsigned &one_based_id)
Set (one-based!) boundary IDs this facet lives on. Passed to any existing vertices and to any future ...
unsigned one_based_boundary_id() const
Constant access to (one-based!) boundary IDs this facet lives on.
unsigned nvertex() const
Number of vertices.
unsigned One_based_boundary_id
(One-based!) boundary IDs this facet lives on
unsigned One_based_region_id_that_facet_is_embedded_in
Facet is to be embedded in specified one-based region. Defaults to zero, indicating that its not embe...
void set_one_based_adjacent_region_id(const unsigned &one_based_id)
Set (one-based!) region ID this facet is adjacent to. Specification of zero argument is harmless as i...
unsigned one_based_region_that_facet_is_embedded_in()
Which (one-based) region is facet embedded in (if zero, it's not embedded in any region)
std::set< unsigned > one_based_adjacent_region_id() const
Return set of (one-based!) region IDs this facet is adjacent to.
TetMeshFacet(const unsigned &nvertex)
Constructor: Specify number of vertices.
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
virtual ~TetMeshFacetedClosedSurfaceForRemesh()
Destructor. Delete allocated memory.
TetMeshFacetedClosedSurfaceForRemesh(Vector< Node * > const &vertex_node_pt, Vector< Vector< unsigned >> const &facet_connectivity, Vector< unsigned > const &facet_boundary_id)
Constructor for a FacetedSurface created from a list of nodes and connectivity information....
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
TetMeshFacetedClosedSurface()
Constructor:
bool Faceted_volume_represents_hole_for_gmsh
Does closed surface represent hole for gmsh?
void enable_faceted_volume_represents_hole_for_gmsh()
Declare closed surface to represent hole for gmsh.
const int & region_id_for_tetgen(const unsigned &j) const
Return the (zero-based) region ID of j-th internal point for tetgen. Negative if it's actually a hole...
bool faceted_volume_represents_hole_for_gmsh() const
Does closed surface represent hole for gmsh?
Vector< std::pair< Vector< double >, int > > Internal_point_for_tetgen
Storage for internal points for tetgen. Stores pair of: – Vector containing coordinates of internal p...
virtual ~TetMeshFacetedClosedSurface()
Empty destructor.
unsigned ninternal_point_for_tetgen()
Number of internal points (identifying either regions or holes) for tetgen.
bool internal_point_identifies_region_for_tetgen(const unsigned &j)
Is j-th internal point for tetgen associated with a region?
bool internal_point_identifies_hole_for_tetgen(const unsigned &j)
Is j-th internal point for tetgen associated with a hole?
const double & internal_point_for_tetgen(const unsigned &j, const unsigned &i) const
i=th coordinate of the j-th internal point for tetgen
void disable_faceted_volume_represents_hole_for_gmsh()
Declare closed surface NOT to represent hole for gmsh.
void set_region_for_tetgen(const unsigned ®ion_id, const Vector< double > ®ion_point)
Specify a region; pass (zero-based) region ID and coordinate of point in region for tetgen.
void set_hole_for_tetgen(const Vector< double > &hole_point)
Specify coordinate of hole for tetgen.
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
unsigned nvertex_on_facet(const unsigned &j) const
Number of vertices defining the j-th facet.
bool Boundaries_can_be_split_in_tetgen
Boolean to indicate whether extra vertices can be added on the boundary in tetgen.
void disable_boundaries_can_be_split_in_tetgen()
Test whether boundaries can be split in tetgen.
virtual void boundary_zeta01(const unsigned &facet_id, const double &zeta_boundary, Vector< double > &zeta)
Virtual function that specifies the variation of the zeta coordinates in the GeomObject along the bou...
Vector< TetMeshVertex * > Vertex_pt
Vector pointers to vertices.
unsigned nfacet() const
Number of facets.
Vector< Vector< unsigned > > Facet_vertex_index_in_tetgen
Facet connectivity: Facet_vertex_index[f][j] is the index of the j-th vertex (in the Vertex_pt vector...
void output_paraview(const std::string &filename) const
Outputs the faceted surface into a file with the specified name in the Paraview format....
DiskLikeGeomObjectWithBoundaries * Geom_object_with_boundaries_pt
GeomObject with boundaries associated with this surface.
void output_paraview(std::ostream &outfile) const
Outputs the faceted surface into a specified file in the Paraview format for viewing in Paraview....
virtual void boundary_zeta12(const unsigned &facet_id, const double &zeta_boundary, Vector< double > &zeta)
Virtual function that specifies the variation of the zeta coordinates in the GeomObject along the bou...
bool boundaries_can_be_split_in_tetgen()
Test whether boundary can be split in tetgen.
Vector< TetMeshFacet * > Facet_pt
Vector of pointers to facets.
unsigned one_based_facet_boundary_id(const unsigned &j) const
One-based boundary id of j-th facet.
TetMeshFacet * facet_pt(const unsigned &j) const
Pointer to j-th facet.
Vector< unsigned > vertex_index_in_tetgen(const unsigned &f)
Facet connectivity: vertex_index[j] is the index of the j-th vertex (in the Vertex_pt vector) in face...
void enable_boundaries_can_be_split_in_tetgen()
Test whether boundaries can be split in tetgen.
virtual void boundary_zeta20(const unsigned &facet_id, const double &zeta_boundary, Vector< double > &zeta)
Virtual function that specifies the variation of the zeta coordinates in the GeomObject along the bou...
void setup_facet_connectivity_for_tetgen()
Setup facet connectivity for tetgen.
double vertex_coordinate(const unsigned &j, const unsigned &i) const
i-th coordinate of j-th vertex
unsigned nvertex() const
Number of vertices.
TetMeshFacetedSurface()
Constructor:
void output(const std::string &filename) const
Output.
TetMeshVertex * vertex_pt(const unsigned &j) const
Pointer to j-th vertex.
void output(std::ostream &outfile) const
Output.
virtual ~TetMeshFacetedSurface()
Empty destructor.
DiskLikeGeomObjectWithBoundaries * geom_object_with_boundaries_pt()
Access to GeomObject with boundaries associated with this surface (Null if there isn't one!...
unsigned one_based_vertex_boundary_id(const unsigned &j) const
First (of possibly multiple) one-based boundary id of j-th vertex.
Vertex for Tet mesh generation. Can lie on multiple boundaries (identified via one-based enumeration!...
void set_zeta_in_geom_object(const Vector< double > &zeta)
Set intrinisic coordinates in GeomObject.
Vector< double > X
Coordinate vector.
TetMeshVertex(Node *const &node_pt)
Vector< double > zeta_in_geom_object() const
Get intrinisic coordinates in GeomObject (returns zero sized vector if no such coordinates have been ...
std::set< unsigned > One_based_boundary_id
Set of (one-based!) boundary IDs this vertex lives on.
unsigned one_based_boundary_id() const
First (of possibly multiple) one-based boundary id.
Vector< double > Zeta_in_geom_object
Intrinisic coordinates in GeomObject (zero sized if there isn't one.
void set_one_based_boundary_id(const unsigned &id)
Set of (one-based!) boundary IDs this vertex lives on.
double x(const unsigned &i) const
i-th coordinate
TetMeshVertex(const Vector< double > &x)
Constructor: Pass coordinates (length 3!)
////////////////////////////////////////////////////////////////////// //////////////////////////////...
std::string string(const unsigned &i)
Return the i-th string or "" if the relevant string hasn't been defined.
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
OomphInfo oomph_info
Single (global) instantiation of the OomphInfo object – this is used throughout the library as a "rep...