27 #ifndef OOMPH_GMSH_TET_MESH_HEADER
28 #define OOMPH_GMSH_TET_MESH_HEADER
32 #include <oomph-lib-config.h>
40 #include "../generic/sample_point_parameters.h"
41 #include "../generic/mesh_as_geometric_object.h"
42 #include "../generic/projection.h"
271 TetEdge(
const unsigned& vertex1,
const unsigned& vertex2)
273 if (vertex1 > vertex2)
278 else if (vertex1 < vertex2)
286 "Muppet! You can't build an edge from one vertex to the same vertex!",
287 OOMPH_CURRENT_FUNCTION,
288 OOMPH_EXCEPTION_LOCATION);
360 template<
class ELEMENT>
371 template<
class ELEMENT>
378 const bool& use_mesh_grading_from_file)
381 double t_start = TimingHelpers::timer();
386 oomph_info <<
"Time for writing geo file : "
387 << TimingHelpers::timer() - t_start <<
" sec " << std::endl;
388 t_start = TimingHelpers::timer();
391 std::string gmsh_command_line_string =
"";
393 std::string gmsh_onscreen_output_file_name =
395 std::ofstream gmsh_on_screen_output_file;
396 std::stringstream marker;
397 if (gmsh_onscreen_output_file_name !=
"")
399 marker <<
"\n\n====================================================\n"
400 <<
" gmsh invocation: "
403 <<
"====================================================\n\n\n"
406 oomph_info << marker.str();
407 gmsh_on_screen_output_file.open(gmsh_onscreen_output_file_name.c_str(),
409 gmsh_on_screen_output_file << marker.str();
410 gmsh_on_screen_output_file.close();
413 gmsh_command_line_string +=
416 if (gmsh_onscreen_output_file_name !=
"")
418 gmsh_command_line_string +=
" >> " + gmsh_onscreen_output_file_name;
423 int return_flag = system(gmsh_command_line_string.c_str());
424 oomph_info <<
"fyi: return from system command: " << return_flag
426 oomph_info <<
"Time for gmsh system call : "
427 << TimingHelpers::timer() - t_start <<
" sec " << std::endl;
428 t_start = TimingHelpers::timer();
434 oomph_info <<
"Time for creating mesh from msh file: "
435 << TimingHelpers::timer() - t_start <<
" sec " << std::endl;
443 std::string mesh_file_name =
463 std::ifstream mesh_file(mesh_file_name.c_str(), std::ios_base::in);
467 if (!mesh_file.is_open())
469 std::string error_msg(
"Failed to open mesh file: ");
470 error_msg +=
"\"" + mesh_file_name +
"\".";
472 error_msg, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
480 if (line !=
"$MeshFormat")
482 std::string error_msg(
483 "First line has to contain the string \"$MeshFormat\"; ");
484 error_msg +=
" yours contains: " + line;
486 error_msg, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
497 bool keep_going =
true;
502 if (line ==
"$Nodes")
509 std::map<unsigned, Vector<double>> node_coordinate;
510 for (
unsigned j = 0; j < nnod; j++)
512 unsigned node_number = 0;
513 mesh_file >> node_number;
517 std::getline(mesh_file, s);
518 std::istringstream iss(s);
522 node_coordinate[node_number].push_back(atof(sub.c_str()));
527 if (line !=
"$EndNodes")
529 std::string error_msg(
"Line has to contain the string \"$EndNodes\"; ");
530 error_msg +=
" yours contains: " + line;
532 error_msg, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
540 if (line !=
"$MeshFormat")
542 std::string error_msg(
543 "First line has to contain the string \"$MeshFormat\"; ");
544 error_msg +=
" yours contains: " + line;
546 error_msg, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
553 std::map<unsigned, std::set<unsigned>> one_based_boundaries_of_node;
559 std::map<unsigned, std::set<unsigned>> boundary_node;
562 std::map<unsigned, std::set<unsigned>> region_element;
570 if (line ==
"$Elements")
577 unsigned highest_one_based_boundary_id = 0;
578 unsigned n_tet_el = 0;
582 std::map<unsigned, Vector<unsigned>> element_node_index;
583 for (
unsigned e = 0; e < nel; e++)
597 unsigned el_number = 0;
598 mesh_file >> el_number;
601 unsigned el_type = 0;
602 mesh_file >> el_type;
624 std::string error_msg(
"Can't handle element type: ");
625 error_msg += oomph::StringConversion::to_string(el_type);
627 error_msg, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
636 int physical_tag = 0;
637 mesh_file >> physical_tag;
641 mesh_file >> geom_tag;
643 Vector<int> other_tags;
644 for (
unsigned i = 2; i < ntags; i++)
648 other_tags.push_back(tag);
655 std::getline(mesh_file, s);
656 std::istringstream iss(s);
658 Vector<int> other_ints;
661 other_ints.push_back(atoi(sub.c_str()));
663 unsigned n_el_nod = other_ints.size();
664 for (
unsigned j = 0; j < n_el_nod; j++)
666 unsigned node_number = unsigned(other_ints[j]);
667 element_node_index[el_number].push_back(node_number);
673 if (physical_tag != 0)
675 boundary_node[unsigned(physical_tag)].insert(node_number);
676 one_based_boundaries_of_node[node_number].insert(
677 unsigned(physical_tag));
678 if (
unsigned(physical_tag) > highest_one_based_boundary_id)
680 highest_one_based_boundary_id = physical_tag;
689 if (physical_tag != 0)
691 region_element[unsigned(physical_tag)].insert(n_tet_el);
697 if (line !=
"$EndElements")
699 std::string error_msg(
700 "Line has to contain the string \"$EndElements\"; ");
701 error_msg +=
" yours contains: " + line;
703 error_msg, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
711 if (line !=
"$MeshFormat")
713 std::string error_msg(
714 "First line has to contain the string \"$MeshFormat\"; ");
715 error_msg +=
" yours contains: " + line;
717 error_msg, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
730 std::map<unsigned, std::set<unsigned>> element_next_to_boundary;
731 for (std::map<
unsigned, Vector<unsigned>>::iterator it =
732 element_node_index.begin();
733 it != element_node_index.end();
736 unsigned el_number = (*it).first;
737 unsigned nnod = ((*it).second).size();
740 std::map<unsigned, unsigned> boundary_node_count;
741 for (
unsigned j = 0; j < nnod; j++)
743 unsigned node_number = ((*it).second)[j];
744 std::map<unsigned, std::set<unsigned>>::iterator itt =
745 one_based_boundaries_of_node.find(node_number);
746 if (itt != one_based_boundaries_of_node.end())
748 for (std::set<unsigned>::iterator ittt = (itt->second).begin();
749 ittt != (itt->second).end();
752 unsigned one_based_boundary_id = (*ittt);
753 boundary_node_count[one_based_boundary_id]++;
757 for (std::map<unsigned, unsigned>::iterator itt =
758 boundary_node_count.begin();
759 itt != boundary_node_count.end();
762 if ((*itt).second == 3)
764 element_next_to_boundary[(*itt).first].insert(el_number);
770 this->set_nboundary(highest_one_based_boundary_id);
776 Vector<unsigned> oomph_lib_node_number(4);
777 oomph_lib_node_number[0] = 0;
778 oomph_lib_node_number[1] = 3;
779 oomph_lib_node_number[2] = 2;
780 oomph_lib_node_number[3] = 1;
783 Element_pt.resize(n_tet_el);
784 Node_pt.resize(nnod);
787 Vector<Node*> existing_node_pt(nnod, 0);
791 for (std::map<
unsigned, Vector<unsigned>>::iterator it =
792 element_node_index.begin();
793 it != element_node_index.end();
796 unsigned el_nnod = (*it).second.size();
800 TElement<3, 2>* el_pt =
new TElement<3, 2>;
803 Element_pt[e] = el_pt;
807 for (
unsigned j = 0; j < el_nnod; j++)
810 unsigned node_number = (*it).second[j];
813 if (existing_node_pt[node_number - 1] != 0)
815 el_pt->node_pt(oomph_lib_node_number[j]) =
816 existing_node_pt[node_number - 1];
824 if (one_based_boundaries_of_node[node_number].size() == 0)
827 nod_pt = el_pt->construct_node(oomph_lib_node_number[j]);
828 Node_pt[node_number - 1] = nod_pt;
829 existing_node_pt[node_number - 1] = nod_pt;
835 el_pt->construct_boundary_node(oomph_lib_node_number[j]);
836 Node_pt[node_number - 1] = nod_pt;
837 existing_node_pt[node_number - 1] = nod_pt;
840 for (std::set<unsigned>::iterator it =
841 one_based_boundaries_of_node[node_number].begin();
842 it != one_based_boundaries_of_node[node_number].end();
845 add_boundary_node((*it) - 1, nod_pt);
850 Vector<double> x(node_coordinate[node_number]);
851 for (
unsigned i = 0; i < 3; i++)
864 unsigned n_region = region_element.size();
865 this->Region_element_pt.resize(n_region);
866 this->Region_attribute.resize(n_region);
867 unsigned region_count = 0;
868 for (std::map<
unsigned, std::set<unsigned>>::iterator it =
869 region_element.begin();
870 it != region_element.end();
873 this->Region_element_pt[region_count].resize((*it).second.size());
874 unsigned one_based_region_id = (*it).first;
875 this->Region_attribute[region_count] = one_based_region_id - 1;
877 for (std::set<unsigned>::iterator itt = (*it).second.begin();
878 itt != (*it).second.end();
881 unsigned one_based_el_number = (*itt);
882 this->Region_element_pt[region_count][count] =
883 dynamic_cast<FiniteElement*
>(Element_pt[one_based_el_number - 1]);
891 bool plot_for_debugging =
false;
892 if (plot_for_debugging)
894 std::ofstream outfile;
895 std::string outfile_name;
896 std::string mesh_file_stem =
"shite";
900 outfile_name = mesh_file_stem +
"_element_nodes.dat";
901 outfile.open(outfile_name.c_str());
902 for (std::map<
unsigned, Vector<unsigned>>::iterator it =
903 element_node_index.begin();
904 it != element_node_index.end();
907 std::set<unsigned> shite_nodes;
908 unsigned el_id = (*it).first;
909 std::stringstream tmp_out;
910 for (Vector<unsigned>::iterator itt = (*it).second.begin();
911 itt != (*it).second.end();
914 unsigned node_number = (*itt);
915 shite_nodes.insert(node_number);
916 Vector<double> x(node_coordinate[node_number]);
917 unsigned n = x.size();
918 for (
unsigned i = 0; i < n; i++)
920 tmp_out << x[i] <<
" ";
922 tmp_out << node_number << std::endl;
924 std::string prefix =
", N=4, E=1, F=FEPOINT, ET=TETRAHEDRON";
925 std::string postfix =
"1 2 3 4";
926 if ((*it).second.size() == 3)
928 prefix =
", N=3, E=1, F=FEPOINT, ET=TRIANGLE";
931 outfile <<
"ZONE T=\"one-based element id=" << el_id <<
"\"" << prefix
933 outfile << tmp_out.str();
934 outfile << postfix << std::endl;
940 outfile_name = mesh_file_stem +
"_boundary_nodes.dat";
941 outfile.open(outfile_name.c_str());
942 for (std::map<
unsigned, std::set<unsigned>>::iterator it =
943 boundary_node.begin();
944 it != boundary_node.end();
947 unsigned one_based_boundary_id = (*it).first;
948 outfile <<
"ZONE T=\"one-based boundary id=" << one_based_boundary_id
949 <<
"\"" << std::endl;
950 for (std::set<unsigned>::iterator itt = (*it).second.begin();
951 itt != (*it).second.end();
954 unsigned node_number = (*itt);
955 Vector<double> x(node_coordinate[node_number]);
956 unsigned n = x.size();
957 for (
unsigned i = 0; i < n; i++)
959 outfile << x[i] <<
" ";
961 outfile << node_number << std::endl;
969 for (std::map<
unsigned, std::set<unsigned>>::iterator it =
970 element_next_to_boundary.begin();
971 it != element_next_to_boundary.end();
974 unsigned one_based_boundary_id = (*it).first;
976 mesh_file_stem +
"_elements_next_to_boundary_" +
977 oomph::StringConversion::to_string(one_based_boundary_id) +
".dat";
978 outfile.open(outfile_name.c_str());
979 for (std::set<unsigned>::iterator itt = (*it).second.begin();
980 itt != (*it).second.end();
983 outfile <<
"ZONE T=\"one-based boundary " << one_based_boundary_id
984 <<
"\", N=4, E=1, F=FEPOINT, ET=TETRAHEDRON" << std::endl;
985 unsigned el_number = (*itt);
986 unsigned nnod = element_node_index[el_number].size();
987 for (
unsigned j = 0; j < nnod; j++)
989 unsigned node_number = element_node_index[el_number][j];
990 Vector<double> x(node_coordinate[node_number]);
991 unsigned n = x.size();
992 for (
unsigned i = 0; i < n; i++)
994 outfile << x[i] <<
" ";
996 outfile << std::endl;
998 outfile <<
"1 2 3 4" << std::endl;
1007 unsigned nel = this->nelement();
1008 for (
unsigned e = 0; e < nel; e++)
1010 vol += this->finite_element_pt(e)->size();
1012 oomph_info <<
"Total volume of all elements in scaffold mesh: " << vol
1023 TetMeshFacetedClosedSurface* outer_boundary_pt =
1026 Vector<TetMeshFacetedSurface*> internal_surface_pt =
1031 std::string& target_size_file_name =
1035 std::string filename =
1037 std::ofstream geo_file;
1038 geo_file.open(filename.c_str());
1040 geo_file <<
"// Uniform element size" << std::endl;
1041 geo_file <<
"//---------------------" << std::endl;
1042 geo_file <<
"lc=" << pow(element_volume, 1.0 / 3.0) <<
";" << std::endl;
1043 geo_file << std::endl;
1049 geo_file <<
"// Outer box" << std::endl;
1050 geo_file <<
"//==========" << std::endl;
1051 geo_file << std::endl;
1052 geo_file <<
"// Vertices" << std::endl;
1053 geo_file <<
"//---------" << std::endl;
1054 std::map<TetMeshVertex*, unsigned> vertex_number;
1055 unsigned nv = outer_boundary_pt->nvertex();
1056 for (
unsigned j = 0; j < nv; j++)
1058 TetMeshVertex* vertex_pt = outer_boundary_pt->vertex_pt(j);
1059 vertex_number[vertex_pt] = j;
1060 geo_file <<
"Point(" << j + 1 <<
")={";
1061 for (
unsigned i = 0; i < 3; i++)
1063 geo_file << vertex_pt->x(i) <<
",";
1065 geo_file <<
"lc};" << std::endl;
1070 std::set<TetEdge> tet_edge_set;
1071 unsigned nfacet = outer_boundary_pt->nfacet();
1072 for (
unsigned f = 0; f < nfacet; f++)
1074 TetMeshFacet* facet_pt = outer_boundary_pt->facet_pt(f);
1075 unsigned nv = facet_pt->nvertex();
1076 for (
unsigned j = 0; j < nv - 1; j++)
1078 TetMeshVertex* first_vertex_pt = facet_pt->vertex_pt(j);
1079 TetMeshVertex* second_vertex_pt = facet_pt->vertex_pt(j + 1);
1080 TetEdge my_tet_edge(vertex_number[first_vertex_pt] + 1,
1081 vertex_number[second_vertex_pt] + 1);
1082 tet_edge_set.insert(my_tet_edge);
1084 TetMeshVertex* first_vertex_pt = facet_pt->vertex_pt(nv - 1);
1085 TetMeshVertex* second_vertex_pt = facet_pt->vertex_pt(0);
1086 TetEdge my_tet_edge(vertex_number[first_vertex_pt] + 1,
1087 vertex_number[second_vertex_pt] + 1);
1088 tet_edge_set.insert(my_tet_edge);
1092 geo_file << std::endl;
1093 geo_file <<
"// Edge of outer box" << std::endl;
1094 geo_file <<
"//------------------" << std::endl;
1096 std::map<TetEdge, unsigned> tet_edge;
1097 for (std::set<TetEdge>::iterator it = tet_edge_set.begin();
1098 it != tet_edge_set.end();
1101 tet_edge.insert(std::make_pair((*it), count));
1102 geo_file <<
"Line(" << count + 1 <<
")={" << (*it).first_vertex_id()
1103 <<
"," << (*it).second_vertex_id() <<
"};" << std::endl;
1109 geo_file << std::endl;
1110 geo_file <<
"// Faces of outer box" << std::endl;
1111 geo_file <<
"//-------------------" << std::endl;
1112 for (
unsigned f = 0; f < nfacet; f++)
1114 geo_file <<
"Line Loop(" << f + 1 <<
")={";
1116 TetMeshFacet* facet_pt = outer_boundary_pt->facet_pt(f);
1117 unsigned nv = facet_pt->nvertex();
1118 for (
unsigned j = 0; j < nv - 1; j++)
1120 TetMeshVertex* first_vertex_pt = facet_pt->vertex_pt(j);
1121 TetMeshVertex* second_vertex_pt = facet_pt->vertex_pt(j + 1);
1122 TetEdge my_tet_edge(vertex_number[first_vertex_pt] + 1,
1123 vertex_number[second_vertex_pt] + 1);
1125 std::map<TetEdge, unsigned>::iterator it = tet_edge.find(my_tet_edge);
1128 geo_file << -int((it->second) + 1) <<
",";
1132 geo_file << ((it->second) + 1) <<
",";
1136 TetMeshVertex* first_vertex_pt = facet_pt->vertex_pt(nv - 1);
1137 TetMeshVertex* second_vertex_pt = facet_pt->vertex_pt(0);
1138 TetEdge my_tet_edge(vertex_number[first_vertex_pt] + 1,
1139 vertex_number[second_vertex_pt] + 1);
1141 std::map<TetEdge, unsigned>::iterator it = tet_edge.find(my_tet_edge);
1144 geo_file << -int((it->second) + 1) <<
"};" << std::endl;
1148 geo_file << ((it->second) + 1) <<
"};" << std::endl;
1150 geo_file <<
"Plane Surface(" << f + 1 <<
")={" << f + 1 <<
"};"
1155 geo_file << std::endl;
1156 geo_file <<
"// Define Plane Surfaces bounding the volume" << std::endl;
1157 geo_file <<
"//------------------------------------------" << std::endl;
1158 geo_file <<
"Surface Loop(1) = {";
1159 for (
unsigned f = 0; f < nfacet - 1; f++)
1161 geo_file << f + 1 <<
",";
1163 geo_file << nfacet <<
"};" << std::endl;
1166 geo_file << std::endl;
1167 geo_file <<
"// Define one-based boundary IDs" << std::endl;
1168 geo_file <<
"//------------------------------" << std::endl;
1169 for (
unsigned f = 0; f < nfacet; f++)
1171 unsigned one_based_boundary_id =
1172 outer_boundary_pt->one_based_facet_boundary_id(f);
1173 geo_file <<
"Physical Surface(" << one_based_boundary_id <<
") = {"
1174 << f + 1 <<
"};" << std::endl;
1179 Vector<unsigned> volume_id_to_be_subtracted_off;
1180 unsigned nvertex_offset = outer_boundary_pt->nvertex();
1181 unsigned nfacet_offset = outer_boundary_pt->nfacet();
1182 unsigned nvolume_offset = 1;
1183 unsigned nline_offset = tet_edge.size();
1188 Vector<unsigned> surfaces_to_be_embedded_in_main_volume;
1189 std::map<unsigned, Vector<unsigned>>
1190 surfaces_to_be_embedded_in_specified_one_based_region;
1194 unsigned n_internal = internal_surface_pt.size();
1195 for (
unsigned i_internal = 0; i_internal < n_internal; i_internal++)
1198 TetMeshFacetedClosedSurface* closed_srf_pt =
1199 dynamic_cast<TetMeshFacetedClosedSurface*
>(
1200 internal_surface_pt[i_internal]);
1201 bool inner_surface_is_closed =
true;
1202 if (closed_srf_pt == 0)
1204 inner_surface_is_closed =
false;
1208 unsigned number_of_volumes_created_for_this_internal_object = 0;
1211 geo_file << std::endl;
1212 geo_file << std::endl;
1213 geo_file <<
"// Inner faceted surface " << i_internal << std::endl;
1214 geo_file <<
"//==========================" << std::endl;
1215 geo_file << std::endl;
1216 geo_file <<
"// Vertices" << std::endl;
1217 geo_file <<
"//---------" << std::endl;
1218 std::map<TetMeshVertex*, unsigned> vertex_number;
1219 unsigned nv = internal_surface_pt[i_internal]->nvertex();
1220 for (
unsigned j = 0; j < nv; j++)
1222 TetMeshVertex* vertex_pt =
1223 internal_surface_pt[i_internal]->vertex_pt(j);
1224 vertex_number[vertex_pt] = nvertex_offset + j;
1225 geo_file <<
"Point(" << nvertex_offset + j + 1 <<
")={";
1226 for (
unsigned i = 0; i < 3; i++)
1228 geo_file << vertex_pt->x(i) <<
",";
1230 geo_file <<
"lc};" << std::endl;
1234 std::set<TetEdge> tet_edge_set;
1235 unsigned nfacet = internal_surface_pt[i_internal]->nfacet();
1236 for (
unsigned f = 0; f < nfacet; f++)
1238 TetMeshFacet* facet_pt = internal_surface_pt[i_internal]->facet_pt(f);
1239 unsigned nv = facet_pt->nvertex();
1240 for (
unsigned j = 0; j < nv - 1; j++)
1242 TetMeshVertex* first_vertex_pt = facet_pt->vertex_pt(j);
1243 TetMeshVertex* second_vertex_pt = facet_pt->vertex_pt(j + 1);
1244 TetEdge my_tet_edge(vertex_number[first_vertex_pt] + 1,
1245 vertex_number[second_vertex_pt] + 1);
1246 tet_edge_set.insert(my_tet_edge);
1248 TetMeshVertex* first_vertex_pt = facet_pt->vertex_pt(nv - 1);
1249 TetMeshVertex* second_vertex_pt = facet_pt->vertex_pt(0);
1250 TetEdge my_tet_edge(vertex_number[first_vertex_pt] + 1,
1251 vertex_number[second_vertex_pt] + 1);
1252 tet_edge_set.insert(my_tet_edge);
1255 geo_file << std::endl;
1256 geo_file <<
"// Edge of inner faceted surface" << std::endl;
1257 geo_file <<
"//------------------------------" << std::endl;
1259 std::map<TetEdge, unsigned> tet_edge;
1260 for (std::set<TetEdge>::iterator it = tet_edge_set.begin();
1261 it != tet_edge_set.end();
1264 tet_edge.insert(std::make_pair((*it), nline_offset + count));
1265 geo_file <<
"Line(" << nline_offset + count + 1 <<
")={"
1266 << (*it).first_vertex_id() <<
"," << (*it).second_vertex_id()
1267 <<
"};" << std::endl;
1273 geo_file << std::endl;
1274 geo_file <<
"// Faces of inner faceted surface" << std::endl;
1275 geo_file <<
"//-------------------------------" << std::endl;
1276 for (
unsigned f = 0; f < nfacet; f++)
1278 geo_file <<
"Line Loop(" << nfacet_offset + f + 1 <<
")={";
1280 TetMeshFacet* facet_pt = internal_surface_pt[i_internal]->facet_pt(f);
1281 unsigned nv = facet_pt->nvertex();
1282 for (
unsigned j = 0; j < nv - 1; j++)
1284 TetMeshVertex* first_vertex_pt = facet_pt->vertex_pt(j);
1285 TetMeshVertex* second_vertex_pt = facet_pt->vertex_pt(j + 1);
1286 TetEdge my_tet_edge(vertex_number[first_vertex_pt] + 1,
1287 vertex_number[second_vertex_pt] + 1);
1289 std::map<TetEdge, unsigned>::iterator it =
1290 tet_edge.find(my_tet_edge);
1293 geo_file << -int((it->second) + 1) <<
",";
1297 geo_file << ((it->second) + 1) <<
",";
1301 TetMeshVertex* first_vertex_pt = facet_pt->vertex_pt(nv - 1);
1302 TetMeshVertex* second_vertex_pt = facet_pt->vertex_pt(0);
1303 TetEdge my_tet_edge(vertex_number[first_vertex_pt] + 1,
1304 vertex_number[second_vertex_pt] + 1);
1306 std::map<TetEdge, unsigned>::iterator it = tet_edge.find(my_tet_edge);
1309 geo_file << -int((it->second) + 1) <<
"};" << std::endl;
1313 geo_file << ((it->second) + 1) <<
"};" << std::endl;
1315 geo_file <<
"Plane Surface(" << nfacet_offset + f + 1 <<
")={"
1316 << nfacet_offset + f + 1 <<
"};" << std::endl;
1320 bool facet_is_embedded_in_a_volume =
1321 facet_pt->facet_is_embedded_in_a_specified_region();
1322 if (facet_is_embedded_in_a_volume)
1324 unsigned one_based_region_id =
1325 facet_pt->one_based_region_that_facet_is_embedded_in();
1326 if (one_based_region_id == 1)
1328 surfaces_to_be_embedded_in_main_volume.push_back(nfacet_offset +
1333 surfaces_to_be_embedded_in_specified_one_based_region
1334 [one_based_region_id]
1335 .push_back(nfacet_offset + f + 1);
1341 if (!inner_surface_is_closed)
1343 surfaces_to_be_embedded_in_main_volume.push_back(nfacet_offset +
1350 std::set<unsigned> all_regions_id;
1354 std::map<unsigned, Vector<unsigned>> region_bounding_facet;
1359 Vector<unsigned> outer_bounding_facet;
1363 for (
unsigned f = 0; f < nfacet; f++)
1365 TetMeshFacet* facet_pt = internal_surface_pt[i_internal]->facet_pt(f);
1366 std::set<unsigned> region_id(
1367 facet_pt->one_based_adjacent_region_id());
1368 unsigned nr = region_id.size();
1369 if (nr == 1) outer_bounding_facet.push_back(nfacet_offset + f + 1);
1370 if ((nr == 0) && inner_surface_is_closed)
1374 surfaces_to_be_embedded_in_main_volume.push_back(nfacet_offset + f +
1377 for (std::set<unsigned>::iterator it = region_id.begin();
1378 it != region_id.end();
1381 all_regions_id.insert((*it));
1382 region_bounding_facet[(*it)].push_back(nfacet_offset + f + 1);
1387 unsigned n_regions_bounded_by_facets = all_regions_id.size();
1390 if (n_regions_bounded_by_facets == 0)
1392 if (inner_surface_is_closed)
1394 std::ostringstream error_message;
1396 <<
"Something fishy going on! "
1397 <<
"Internal faceted surface " << i_internal
1398 <<
" is closed but does not bound any regions!\n"
1399 <<
"Specify one-based region ID for all facets using\n\n"
1400 <<
" TetMeshFacet::set_one_based_adjacent_region_id(...)\n\n";
1401 throw OomphLibError(error_message.str(),
1402 OOMPH_CURRENT_FUNCTION,
1403 OOMPH_EXCEPTION_LOCATION);
1410 unsigned offset_for_extra_hole = 0;
1411 if (n_regions_bounded_by_facets > 1)
1413 geo_file << std::endl;
1414 geo_file <<
"// Define Plane Surfaces bounding compound volume"
1416 <<
"//-----------------------------------------------"
1418 geo_file <<
"// that will have to be treated as hole in main volume"
1420 <<
"//-----------------------------------------------"
1422 offset_for_extra_hole = 1;
1423 geo_file <<
"Surface Loop(" << nvolume_offset + 1 <<
") = {";
1424 unsigned n = outer_bounding_facet.size();
1425 for (
unsigned f = 0; f < n - 1; f++)
1427 geo_file << outer_bounding_facet[f] <<
",";
1429 geo_file << outer_bounding_facet[n - 1] <<
"};" << std::endl;
1432 number_of_volumes_created_for_this_internal_object++;
1436 volume_id_to_be_subtracted_off.push_back(nvolume_offset + 1);
1440 for (std::map<
unsigned, Vector<unsigned>>::iterator it =
1441 region_bounding_facet.begin();
1442 it != region_bounding_facet.end();
1445 geo_file << std::endl;
1446 geo_file <<
"// Define Plane Surfaces bounding the region volume "
1447 << (*it).first << std::endl;
1448 geo_file <<
"//----------------------------------------------------"
1450 geo_file <<
"Surface Loop("
1451 << nvolume_offset + 1 + offset_for_extra_hole + count
1453 unsigned n = (*it).second.size();
1454 for (
unsigned f = 0; f < n - 1; f++)
1456 geo_file << ((*it).second)[f] <<
",";
1458 geo_file << ((*it).second)[n - 1] <<
"};" << std::endl;
1460 geo_file << std::endl;
1461 geo_file <<
"// Define volume "
1462 << nvolume_offset + 1 + offset_for_extra_hole + count
1463 <<
" as the volume bounded by Surface Loop "
1464 << nvolume_offset + 1 + offset_for_extra_hole + count
1467 <<
"//--------------------------------------------------------"
1469 geo_file <<
"Volume("
1470 << nvolume_offset + 1 + offset_for_extra_hole + count
1472 << nvolume_offset + 1 + offset_for_extra_hole + count
1473 <<
"};" << std::endl;
1474 geo_file << std::endl;
1477 number_of_volumes_created_for_this_internal_object++;
1481 bool mesh_the_volume =
true;
1482 if (closed_srf_pt != 0)
1484 if (closed_srf_pt->faceted_volume_represents_hole_for_gmsh())
1486 mesh_the_volume =
false;
1489 if (mesh_the_volume)
1491 geo_file <<
"// Define one-based region IDs" << std::endl;
1492 geo_file <<
"//----------------------------" << std::endl;
1493 geo_file <<
"Physical Volume(" << (*it).first <<
")={"
1494 << nvolume_offset + 1 + offset_for_extra_hole + count
1495 <<
"};" << std::endl;
1497 unsigned ns_embedded =
1498 surfaces_to_be_embedded_in_specified_one_based_region[(*it)
1501 if (ns_embedded > 0)
1503 geo_file <<
"// This region has " << ns_embedded
1504 <<
" embedded surfaces\n";
1505 geo_file <<
"Surface{";
1506 for (
unsigned i = 0; i < ns_embedded - 1; i++)
1509 << surfaces_to_be_embedded_in_specified_one_based_region
1514 << surfaces_to_be_embedded_in_specified_one_based_region
1515 [(*it).first][ns_embedded - 1]
1517 << nvolume_offset + 1 + offset_for_extra_hole + count <<
"};"
1526 geo_file << std::endl;
1527 geo_file <<
"// Define one-based boundary IDs" << std::endl;
1528 geo_file <<
"//------------------------------" << std::endl;
1529 for (
unsigned f = 0; f < nfacet; f++)
1531 unsigned one_based_boundary_id =
1532 internal_surface_pt[i_internal]->one_based_facet_boundary_id(f);
1533 geo_file <<
"Physical Surface(" << one_based_boundary_id <<
") = {"
1534 << nfacet_offset + f + 1 <<
"};" << std::endl;
1538 nvertex_offset += internal_surface_pt[i_internal]->nvertex();
1539 nfacet_offset += internal_surface_pt[i_internal]->nfacet();
1540 nvolume_offset += number_of_volumes_created_for_this_internal_object;
1541 nline_offset += tet_edge.size();
1547 geo_file << std::endl;
1548 geo_file <<
"// Define volume 1 as the volume bounded by Surface Loop 1"
1550 geo_file <<
"//--------------------------------------------------------"
1552 unsigned n = volume_id_to_be_subtracted_off.size();
1555 geo_file <<
"// with volume[s]: ";
1556 for (
unsigned i = 0; i < n; i++)
1558 geo_file << volume_id_to_be_subtracted_off[i] <<
" ";
1560 geo_file <<
"removed." << std::endl;
1561 geo_file <<
"//--------------------------------------------------------"
1566 geo_file <<
"Volume(1)={1";
1569 for (
unsigned i = 0; i < n; i++)
1571 geo_file <<
"," << volume_id_to_be_subtracted_off[i];
1573 geo_file <<
"};" << std::endl;
1574 geo_file << std::endl;
1577 geo_file <<
"// Define one-based region IDs" << std::endl;
1578 geo_file <<
"//----------------------------" << std::endl;
1579 geo_file <<
"Physical Volume(1"
1580 <<
")={1};" << std::endl;
1584 unsigned ns = surfaces_to_be_embedded_in_main_volume.size();
1587 geo_file << std::endl;
1588 geo_file <<
"// Embed Plane Surfaces in main volume (volume 1)"
1590 geo_file <<
"//-----------------------------------------------"
1592 geo_file <<
"Surface{";
1593 for (
unsigned s = 0; s < ns - 1; s++)
1595 geo_file << surfaces_to_be_embedded_in_main_volume[s] <<
",";
1597 geo_file << surfaces_to_be_embedded_in_main_volume[ns - 1]
1598 <<
"} In Volume{1};" << std::endl;
1599 geo_file << std::endl;
1605 if (use_mesh_grading_from_file)
1610 std::ifstream file(target_size_file_name.c_str(), std::ios_base::in);
1613 if (!file.is_open())
1615 std::string error_msg(
"Failed to open target volume file: ");
1616 error_msg +=
"\"" + target_size_file_name;
1617 throw OomphLibError(
1618 error_msg, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
1622 geo_file <<
"Field[1]=Structured;" << std::endl;
1623 geo_file <<
"Field[1].FileName=\"" << target_size_file_name <<
"\";"
1625 geo_file <<
"Field[1].TextFormat=1;" << std::endl;
1626 geo_file <<
"Background Field = 1;" << std::endl;
1631 geo_file << std::endl;
1632 geo_file <<
"Mesh 3;" << std::endl;
1660 template<
class ELEMENT>
1666 TimeStepper* time_stepper_pt = &Mesh::Default_TimeStepper)
1669 bool use_mesh_grading_from_file =
false;
1670 build_it(time_stepper_pt, use_mesh_grading_from_file);
1677 const bool& use_mesh_grading_from_file,
1678 TimeStepper* time_stepper_pt = &Mesh::Default_TimeStepper)
1681 build_it(time_stepper_pt, use_mesh_grading_from_file);
1688 const bool& use_mesh_grading_from_file)
1691 MeshChecker::assert_geometric_element<TElementGeometricBase, ELEMENT>(3);
1694 TetMeshFacetedClosedSurface* outer_boundary_pt =
1697 Vector<TetMeshFacetedSurface*> internal_surface_pt =
1701 Time_stepper_pt = time_stepper_pt;
1704 Outer_boundary_pt = outer_boundary_pt;
1708 unsigned n_facet = Outer_boundary_pt->nfacet();
1709 for (
unsigned f = 0; f < n_facet; f++)
1711 unsigned b = Outer_boundary_pt->one_based_facet_boundary_id(f);
1714 Tet_mesh_faceted_surface_pt[b - 1] = Outer_boundary_pt;
1715 Tet_mesh_facet_pt[b - 1] = Outer_boundary_pt->facet_pt(f);
1719 std::ostringstream error_message;
1720 error_message <<
"Boundary IDs have to be one-based. Yours is " << b
1722 throw OomphLibError(error_message.str(),
1723 OOMPH_CURRENT_FUNCTION,
1724 OOMPH_EXCEPTION_LOCATION);
1731 Internal_surface_pt = internal_surface_pt;
1735 unsigned n = Internal_surface_pt.size();
1736 for (
unsigned i = 0; i < n; i++)
1738 unsigned n_facet = Internal_surface_pt[i]->nfacet();
1739 for (
unsigned f = 0; f < n_facet; f++)
1741 unsigned b = Internal_surface_pt[i]->one_based_facet_boundary_id(f);
1744 Tet_mesh_faceted_surface_pt[b - 1] = Internal_surface_pt[i];
1745 Tet_mesh_facet_pt[b - 1] = Internal_surface_pt[i]->facet_pt(f);
1749 std::ostringstream error_message;
1750 error_message <<
"Boundary IDs have to be one-based. Yours is "
1752 throw OomphLibError(error_message.str(),
1753 OOMPH_CURRENT_FUNCTION,
1754 OOMPH_EXCEPTION_LOCATION);
1768 delete tmp_scaffold_mesh_pt;
1769 tmp_scaffold_mesh_pt = 0;
1772 unsigned nb = nboundary();
1773 for (
unsigned b = 0; b < nb; b++)
1775 bool switch_normal =
false;
1776 setup_boundary_coordinates<ELEMENT>(b, switch_normal);
1781 snap_nodes_onto_geometric_objects();
1793 TimeStepper* time_stepper_pt)
1796 MeshChecker::assert_geometric_element<TElementGeometricBase, ELEMENT>(3);
1799 unsigned nelem = tmp_scaffold_mesh_pt->nelement();
1800 Element_pt.resize(nelem);
1803 std::map<FiniteElement*, unsigned> scaffold_mesh_element_number;
1806 unsigned nnode_scaffold = tmp_scaffold_mesh_pt->nnode();
1807 Node_pt.resize(nnode_scaffold);
1810 unsigned nbound = tmp_scaffold_mesh_pt->nboundary();
1811 set_nboundary(nbound);
1814 Boundary_element_pt.resize(nbound);
1815 Face_index_at_boundary.resize(nbound);
1816 Boundary_region_element_pt.resize(nbound);
1817 Face_index_region_at_boundary.resize(nbound);
1820 for (
unsigned e = 0; e < nelem; e++)
1822 Element_pt[e] =
new ELEMENT;
1826 unsigned nnod_el = tmp_scaffold_mesh_pt->finite_element_pt(0)->nnode();
1831 std::map<Node*, unsigned> global_number;
1832 unsigned global_count = 0;
1835 for (
unsigned e = 0; e < nelem; e++)
1839 scaffold_mesh_element_number[tmp_scaffold_mesh_pt->finite_element_pt(
1843 for (
unsigned j = 0; j < nnod_el; j++)
1846 Node* scaffold_node_pt =
1847 tmp_scaffold_mesh_pt->finite_element_pt(e)->node_pt(j);
1851 unsigned j_global = global_number[scaffold_node_pt];
1858 std::set<unsigned>* boundaries_pt;
1859 scaffold_node_pt->get_boundaries_pt(boundaries_pt);
1862 if (boundaries_pt != 0)
1865 Node* new_node_pt = finite_element_pt(e)->construct_boundary_node(
1866 j, time_stepper_pt);
1872 global_number[scaffold_node_pt] = global_count;
1875 for (std::set<unsigned>::iterator it = boundaries_pt->begin();
1876 it != boundaries_pt->end();
1879 add_boundary_node(*it, new_node_pt);
1886 finite_element_pt(e)->construct_node(j, time_stepper_pt);
1892 global_number[scaffold_node_pt] = global_count;
1899 Node_pt[global_count - 1] = finite_element_pt(e)->node_pt(j);
1902 Node_pt[global_count - 1]->x(0) = scaffold_node_pt->x(0);
1903 Node_pt[global_count - 1]->x(1) = scaffold_node_pt->x(1);
1904 Node_pt[global_count - 1]->x(2) = scaffold_node_pt->x(2);
1909 finite_element_pt(e)->node_pt(j) = Node_pt[j_global - 1];
1915 FiniteElement* fe_pt = finite_element_pt(e);
1916 for (
unsigned f = 0; f < 4; f++)
1918 Node* face_node0_pt = 0;
1919 Node* face_node1_pt = 0;
1920 Node* face_node2_pt = 0;
1925 face_node0_pt = fe_pt->node_pt(1);
1926 face_node1_pt = fe_pt->node_pt(2);
1927 face_node2_pt = fe_pt->node_pt(3);
1931 face_node0_pt = fe_pt->node_pt(0);
1932 face_node1_pt = fe_pt->node_pt(2);
1933 face_node2_pt = fe_pt->node_pt(3);
1937 face_node0_pt = fe_pt->node_pt(0);
1938 face_node1_pt = fe_pt->node_pt(1);
1939 face_node2_pt = fe_pt->node_pt(3);
1943 face_node0_pt = fe_pt->node_pt(0);
1944 face_node1_pt = fe_pt->node_pt(1);
1945 face_node2_pt = fe_pt->node_pt(2);
1950 std::ostringstream error_message;
1951 error_message <<
"Wrong face number " << f << std::endl;
1952 throw OomphLibError(error_message.str(),
1953 OOMPH_CURRENT_FUNCTION,
1954 OOMPH_EXCEPTION_LOCATION);
1959 std::set<unsigned>* bc0_pt;
1960 face_node0_pt->get_boundaries_pt(bc0_pt);
1963 std::set<unsigned>* bc1_pt;
1964 face_node1_pt->get_boundaries_pt(bc1_pt);
1967 std::set<unsigned>* bc2_pt;
1968 face_node2_pt->get_boundaries_pt(bc2_pt);
1971 std::set<unsigned> common_bound_0_and_1;
1972 std::set_intersection(
1977 std::inserter(common_bound_0_and_1,
1978 common_bound_0_and_1.begin()));
1979 std::set<unsigned> common_bound_0_and_1_and_2;
1980 std::set_intersection(
1981 common_bound_0_and_1.begin(),
1982 common_bound_0_and_1.end(),
1985 std::inserter(common_bound_0_and_1_and_2,
1986 common_bound_0_and_1_and_2.begin()));
1987 for (std::set<unsigned>::iterator it =
1988 common_bound_0_and_1_and_2.begin();
1989 it != common_bound_0_and_1_and_2.end();
1992 Boundary_element_pt[(*it)].push_back(fe_pt);
1993 Face_index_at_boundary[(*it)].push_back(f);
2002 unsigned nr = tmp_scaffold_mesh_pt->Region_element_pt.size();
2003 Region_attribute.resize(nr);
2004 Region_element_pt.resize(nr);
2005 for (
unsigned i = 0; i < nr; i++)
2007 Region_attribute[i] = tmp_scaffold_mesh_pt->Region_attribute[i];
2008 unsigned nel = tmp_scaffold_mesh_pt->Region_element_pt[i].size();
2009 Region_element_pt[i].resize(nel);
2010 for (
unsigned e = 0; e < nel; e++)
2012 FiniteElement* scaff_el_pt =
2013 tmp_scaffold_mesh_pt->Region_element_pt[i][e];
2014 unsigned scaff_el_number = scaffold_mesh_element_number[scaff_el_pt];
2015 Region_element_pt[i][e] =
2016 dynamic_cast<FiniteElement*
>(Element_pt[scaff_el_number]);
2020 FiniteElement* fe_pt = Region_element_pt[i][e];
2021 for (
unsigned f = 0; f < 4; f++)
2023 Node* face_node0_pt = 0;
2024 Node* face_node1_pt = 0;
2025 Node* face_node2_pt = 0;
2030 face_node0_pt = fe_pt->node_pt(1);
2031 face_node1_pt = fe_pt->node_pt(2);
2032 face_node2_pt = fe_pt->node_pt(3);
2036 face_node0_pt = fe_pt->node_pt(0);
2037 face_node1_pt = fe_pt->node_pt(2);
2038 face_node2_pt = fe_pt->node_pt(3);
2042 face_node0_pt = fe_pt->node_pt(0);
2043 face_node1_pt = fe_pt->node_pt(1);
2044 face_node2_pt = fe_pt->node_pt(3);
2048 face_node0_pt = fe_pt->node_pt(0);
2049 face_node1_pt = fe_pt->node_pt(1);
2050 face_node2_pt = fe_pt->node_pt(2);
2054 std::ostringstream error_message;
2055 error_message <<
"Wrong face number " << f << std::endl;
2056 throw OomphLibError(error_message.str(),
2057 OOMPH_CURRENT_FUNCTION,
2058 OOMPH_EXCEPTION_LOCATION);
2063 std::set<unsigned>* bc0_pt;
2064 face_node0_pt->get_boundaries_pt(bc0_pt);
2067 std::set<unsigned>* bc1_pt;
2068 face_node1_pt->get_boundaries_pt(bc1_pt);
2071 std::set<unsigned>* bc2_pt;
2072 face_node2_pt->get_boundaries_pt(bc2_pt);
2075 std::set<unsigned> common_bound_0_and_1;
2076 std::set_intersection(
2081 std::inserter(common_bound_0_and_1,
2082 common_bound_0_and_1.begin()));
2083 std::set<unsigned> common_bound_0_and_1_and_2;
2084 std::set_intersection(
2085 common_bound_0_and_1.begin(),
2086 common_bound_0_and_1.end(),
2089 std::inserter(common_bound_0_and_1_and_2,
2090 common_bound_0_and_1_and_2.begin()));
2091 for (std::set<unsigned>::iterator it =
2092 common_bound_0_and_1_and_2.begin();
2093 it != common_bound_0_and_1_and_2.end();
2096 Boundary_region_element_pt[(*it)][Region_attribute[i]]
2098 Face_index_region_at_boundary[(*it)][Region_attribute[i]]
2109 Lookup_for_elements_next_boundary_is_setup =
true;
2117 unsigned n_node_1d = finite_element_pt(0)->nnode_1d();
2120 if ((n_node_1d != 2) && (n_node_1d != 3))
2122 std::ostringstream error_message;
2123 error_message <<
"Mesh generation from gmsh currently only works\n";
2124 error_message <<
"for nnode_1d = 2 or 3. You're trying to use it\n";
2125 error_message <<
"for nnode_1d=" << n_node_1d << std::endl;
2126 throw OomphLibError(error_message.str(),
2127 OOMPH_CURRENT_FUNCTION,
2128 OOMPH_EXCEPTION_LOCATION);
2132 Vector<double> s(3);
2135 std::map<std::pair<Node*, Node*>, Node*> midside_node_pt;
2138 for (
unsigned e = 0; e < nelem; e++)
2141 FiniteElement*
const el_pt = this->finite_element_pt(e);
2142 FiniteElement*
const simplex_el_pt =
2143 tmp_scaffold_mesh_pt->finite_element_pt(e);
2146 for (
unsigned j = 0; j < 6; ++j)
2150 unsigned new_node_number = 0;
2151 std::pair<Node*, Node*> edge;
2155 nod0_pt = el_pt->node_pt(0);
2156 nod1_pt = el_pt->node_pt(1);
2157 new_node_number = 4;
2161 nod0_pt = el_pt->node_pt(0);
2162 nod1_pt = el_pt->node_pt(2);
2163 new_node_number = 5;
2167 nod0_pt = el_pt->node_pt(0);
2168 nod1_pt = el_pt->node_pt(3);
2169 new_node_number = 6;
2173 nod0_pt = el_pt->node_pt(1);
2174 nod1_pt = el_pt->node_pt(2);
2175 new_node_number = 7;
2179 nod0_pt = el_pt->node_pt(2);
2180 nod1_pt = el_pt->node_pt(3);
2181 new_node_number = 8;
2185 nod0_pt = el_pt->node_pt(1);
2186 nod1_pt = el_pt->node_pt(3);
2187 new_node_number = 9;
2191 std::ostringstream error_message;
2192 error_message <<
"Wrong edge number " << j << std::endl;
2193 throw OomphLibError(error_message.str(),
2194 OOMPH_CURRENT_FUNCTION,
2195 OOMPH_EXCEPTION_LOCATION);
2199 edge = std::make_pair(std::min(nod0_pt, nod1_pt),
2200 std::max(nod0_pt, nod1_pt));
2201 Node* existing_node_pt = midside_node_pt[edge];
2202 if (existing_node_pt == 0)
2206 std::set<unsigned> common_bound_0_and_1;
2207 std::set<unsigned>* bc0_pt;
2208 nod0_pt->get_boundaries_pt(bc0_pt);
2211 std::set<unsigned>* bc1_pt;
2212 nod1_pt->get_boundaries_pt(bc1_pt);
2215 std::set_intersection(
2220 std::inserter(common_bound_0_and_1,
2221 common_bound_0_and_1.begin()));
2225 Node* new_node_pt = 0;
2228 if (common_bound_0_and_1.size() == 0)
2231 el_pt->construct_node(new_node_number, time_stepper_pt);
2236 new_node_pt = el_pt->construct_boundary_node(new_node_number,
2238 for (std::set<unsigned>::iterator it =
2239 common_bound_0_and_1.begin();
2240 it != common_bound_0_and_1.end();
2243 this->add_boundary_node((*it), new_node_pt);
2248 el_pt->local_coordinate_of_node(new_node_number, s);
2252 for (
unsigned i = 0; i < 3; i++)
2254 new_node_pt->x(i) = simplex_el_pt->interpolated_x(s, i);
2258 midside_node_pt[edge] = new_node_pt;
2261 Node_pt.push_back(new_node_pt);
2266 el_pt->node_pt(new_node_number) = existing_node_pt;
2282 template<
class ELEMENT>
2284 public virtual RefineableTetMeshBase
2292 const bool& use_mesh_grading_from_file,
2293 TimeStepper* time_stepper_pt = &Mesh::Default_TimeStepper)
2295 gmsh_parameters_pt, use_mesh_grading_from_file, time_stepper_pt)
2303 TimeStepper* time_stepper_pt = &Mesh::Default_TimeStepper)
2314 void adapt(
const Vector<double>& elem_error);
2320 std::string error_msg(
"Not written yet...");
2321 throw OomphLibError(
2322 error_msg, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
2329 std::string error_msg(
"Not written yet...");
2330 throw OomphLibError(
2331 error_msg, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
2342 this->Max_permitted_edge_ratio =
Class to collate parameters for Gmsh mesh generation.
double Dx_for_target_size_transfer
(Isotropic) grid spacing for target size transfer
Vector< TetMeshFacetedSurface * > & internal_surface_pt()
Internal boundaries.
TetMeshFacetedClosedSurface * Outer_boundary_pt
Pointer to outer boundary.
std::string Geo_and_msh_file_stem
Stem for geo and msh files (input/output to command-line gmsh invocation)
double & min_element_size()
Min. element size during refinement.
double & element_volume()
Uniform target element volume.
std::string Gmsh_command_line_invocation
Gmsh command line invocation string.
std::string & stem_for_filename_gmsh_size_transfer()
Stem for filename used to doc target element sizes on gmsh grid. No doc if stem is equal to empty str...
double Max_element_size
Max. element size during refinement.
GmshParameters(TetMeshFacetedClosedSurface *const &outer_boundary_pt, const std::string &gmsh_command_line_invocation)
Specify outer boundary of domain to be meshed. Other parameters get default values and can be set via...
unsigned Max_sample_points_for_limited_locate_zeta_during_target_size_transfer
Target size is transferred onto regular grid (for gmsh) by locate zeta. We try to find the exact poin...
unsigned & max_sample_points_for_limited_locate_zeta_during_target_size_transfer()
Target size is transferred onto regular grid (for gmsh) by locate zeta. We try to find the exact poin...
std::string & target_size_file_name()
Filename for target volumes (for system-call based transfer to gmsh during mesh adaptation)....
double Min_element_size
Min. element size during refinement.
double Element_volume
Uniform element volume.
Vector< TetMeshFacetedSurface * > Internal_surface_pt
Internal boundaries.
std::string & gmsh_command_line_invocation()
String to be issued via system command to activate gmsh.
unsigned Gmsh_onscreen_output_counter
Counter for marker that indicates where we are in gmsh on-screen output.
std::string & geo_and_msh_file_stem()
Stem for geo and msh files (input/output to command-line gmsh invocation)
TetMeshFacetedClosedSurface *& outer_boundary_pt()
Outer boundary.
double Max_permitted_edge_ratio
Max edge ratio before remesh gets triggered.
std::string & gmsh_onscreen_output_file_name()
Output filename for gmsh on-screen output.
bool projection_is_disabled()
Is projection of old solution onto new mesh disabled?
int & counter_for_filename_gmsh_size_transfer()
Counter for filename used to doc target element sizes on gmsh grid. No doc if stem is equal to empty ...
std::string Stem_for_filename_gmsh_size_transfer
Stem for filename used to doc target element sizes on gmsh grid. No doc if stem is equal to empty str...
void disable_projection()
Disable projection of old solution onto new mesh.
std::string Target_size_file_name
Filename for target volume (for system-call based transfer to gmsh during mesh adaptation)
double & dx_for_target_size_transfer()
(Isotropic) grid spacing for target size transfer
bool Projection_is_disabled
Is projection of old solution onto new mesh disabled?
std::string Gmsh_onscreen_output_file_name
Output filename for gmsh on-screen output.
int Counter_for_filename_gmsh_size_transfer
Counter for filename used to doc target element sizes on gmsh grid. No doc if stem is equal to empty ...
void enable_projection()
Disable projection of old solution onto new mesh.
double & max_element_size()
Max. element size during refinement.
unsigned & gmsh_onscreen_output_counter()
Counter for marker that indicates where we are in gmsh on-screen output.
double & max_permitted_edge_ratio()
Max. permitted edge ratio.
/////////////////////////////////////////////////////////////////////// /////////////////////////////...
GmshTetMesh(GmshParameters *gmsh_parameters_pt, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor.
GmshParameters * Gmsh_parameters_pt
Parameters.
void build_from_scaffold(GmshTetScaffoldMesh *tmp_scaffold_mesh_pt, TimeStepper *time_stepper_pt)
Build unstructured tet gmesh mesh based on output from scaffold.
GmshTetMesh(GmshParameters *gmsh_parameters_pt, const bool &use_mesh_grading_from_file, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor. If boolean is set to true, the target element sizes are read from file (used during adap...
void build_it(TimeStepper *time_stepper_pt, const bool &use_mesh_grading_from_file)
void create_mesh_from_msh_file()
Create mesh from msh file (created internally via disk-based operations)
GmshTetScaffoldMesh(GmshParameters *gmsh_parameters_pt, const bool &use_mesh_grading_from_file)
Build mesh, based on specified parameters. If boolean is set to true, the target element sizes are re...
void write_geo_file(const bool &use_mesh_grading_from_file)
Write geo file for gmsh.
GmshParameters * Gmsh_parameters_pt
Parameters.
/////////////////////////////////////////////////////////////////////// /////////////////////////////...
void refine_uniformly(DocInfo &doc_info)
Unrefine uniformly.
unsigned unrefine_uniformly()
Refine uniformly.
RefineableGmshTetMesh(GmshParameters *gmsh_parameters_pt, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor.
void adapt(const Vector< double > &elem_error)
Adapt mesh, based on elemental error provided.
RefineableGmshTetMesh(GmshParameters *gmsh_parameters_pt, const bool &use_mesh_grading_from_file, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor. If boolean is set to true, the target element sizes are read from file (used during adap...
void initialise_adaptation_data()
Helper function to initialise data associated with adaptation.
////////////////////////////////////////////////////////////////// //////////////////////////////////...
bool operator==(const TetEdge &tet_edge) const
Comparison operator: Edges are identical if their sorted (and therefore possibly reversed) vertex ids...
std::pair< unsigned, unsigned > Vertex_pair
The vertices (sorted by vertex ids)
unsigned second_vertex_id() const
Second vertex id.
bool is_reversed() const
Edge is reversed in the sense that vertex1 actually has a higher id than vertex2 (when specified in t...
TetEdge(const unsigned &vertex1, const unsigned &vertex2)
Constructor: Pass two vertices, identified by their indices Edge "direction" is from lower vertex to ...
bool operator<(const TetEdge &tet_edge) const
Comparison operator. Lexicographic comparison based on vertex ids.
unsigned first_vertex_id() const
First vertex id.
bool Reversed
Is it reversed? I.e. is the first input vertex stored after the second one?
////////////////////////////////////////////////////////////////////// //////////////////////////////...