31 #ifndef OOMPH_GMSH_TET_MESH_HEADER    32 #define OOMPH_GMSH_TET_MESH_HEADER    36   #include <oomph-lib-config.h>    44 #include "../generic/sample_point_parameters.h"    45 #include "../generic/mesh_as_geometric_object.h"    46 #include "../generic/projection.h"   279   TetEdge(
const unsigned& vertex1, 
const unsigned& vertex2)
   284       Vertex_pair=std::make_pair(vertex2,vertex1);
   286     else if (vertex1<vertex2)
   289       Vertex_pair=std::make_pair(vertex1,vertex2);
   294        "Muppet! You can't build an edge from one vertex to the same vertex!",
   295        OOMPH_CURRENT_FUNCTION,
   296        OOMPH_EXCEPTION_LOCATION);
   304    return Vertex_pair.first;
   310    return Vertex_pair.second;
   323   bool operator ==(
const TetEdge& tet_edge)
 const   331   bool operator < (
const TetEdge& tet_edge)
 const   370  template<
class ELEMENT>
   384   template<
class ELEMENT>
   391                        const bool& use_mesh_grading_from_file) :
   392   Gmsh_parameters_pt(gmsh_parameters_pt)
   395     double t_start=TimingHelpers::timer();
   398     write_geo_file(use_mesh_grading_from_file);
   400     oomph_info << 
"Time for writing geo file           : "   401                << TimingHelpers::timer()-t_start
   402                << 
" sec " << std::endl;
   403     t_start=TimingHelpers::timer();
   406     std::string gmsh_command_line_string=
"";
   410     std::ofstream gmsh_on_screen_output_file;
   411     std::stringstream marker;
   412     if (gmsh_onscreen_output_file_name!=
"")
   415        << 
"\n\n====================================================\n"   416        << 
"          gmsh invocation: "    418        << 
"====================================================\n\n\n"   421       oomph_info << marker.str();
   422       gmsh_on_screen_output_file.open(gmsh_onscreen_output_file_name.c_str(),
   424       gmsh_on_screen_output_file << marker.str();
   425       gmsh_on_screen_output_file.close();
   428     gmsh_command_line_string +=
   429      Gmsh_parameters_pt->gmsh_command_line_invocation() + 
" " +
   430      Gmsh_parameters_pt->geo_and_msh_file_stem() + 
".geo -3";
   431     if (gmsh_onscreen_output_file_name!=
"")
   438     int return_flag=system(gmsh_command_line_string.c_str());
   439     oomph_info << 
"fyi: return from system command: " << return_flag 
   441     oomph_info << 
"Time for gmsh system call           : "   442                << TimingHelpers::timer()-t_start
   443                << 
" sec " << std::endl;
   444     t_start=TimingHelpers::timer();
   448     create_mesh_from_msh_file(); 
   450     oomph_info << 
"Time for creating mesh from msh file: "   451                << TimingHelpers::timer()-t_start
   452                << 
" sec " << std::endl;
   463    std::string mesh_file_name=Gmsh_parameters_pt->
   483    std::ifstream mesh_file(mesh_file_name.c_str(),std::ios_base::in);      
   487    if(!mesh_file.is_open())
   489      std::string error_msg(
"Failed to open mesh file: ");
   490      error_msg += 
"\"" + mesh_file_name + 
"\".";
   491      throw OomphLibError(error_msg, 
   492                          OOMPH_CURRENT_FUNCTION,
   493                          OOMPH_EXCEPTION_LOCATION);
   501    if (line!=
"$MeshFormat")
   503      std::string error_msg
   504       (
"First line has to contain the string \"$MeshFormat\"; ");
   505      error_msg += 
" yours contains: " + line;
   506      throw OomphLibError(error_msg, 
   507                          OOMPH_CURRENT_FUNCTION,
   508                          OOMPH_EXCEPTION_LOCATION);
   519    bool keep_going=
true;
   531    std::map<unsigned,Vector<double> > node_coordinate;
   532    for (
unsigned j=0;j<nnod;j++)
   534      unsigned node_number=0;
   535      mesh_file >> node_number;
   539      std::getline(mesh_file, s);
   540      std::istringstream iss(s);
   544        node_coordinate[node_number].push_back(atof(sub.c_str()));
   549    if (line!=
"$EndNodes")
   551      std::string error_msg(
"Line has to contain the string \"$EndNodes\"; ");
   552      error_msg += 
" yours contains: " + line;
   553      throw OomphLibError(error_msg, 
   554                          OOMPH_CURRENT_FUNCTION,
   555                          OOMPH_EXCEPTION_LOCATION);
   563    if (line!=
"$MeshFormat")
   565      std::string error_msg
   566       (
"First line has to contain the string \"$MeshFormat\"; ");
   567      error_msg += 
" yours contains: " + line;
   568      throw OomphLibError(error_msg, 
   569                          OOMPH_CURRENT_FUNCTION,
   570                          OOMPH_EXCEPTION_LOCATION);
   577    std::map<unsigned,std::set<unsigned> > one_based_boundaries_of_node;
   583    std::map<unsigned,std::set<unsigned> > boundary_node;
   586    std::map<unsigned,std::set<unsigned> > region_element;
   594      if (line==
"$Elements")
   601    unsigned highest_one_based_boundary_id=0;
   606    std::map<unsigned,Vector<unsigned> > element_node_index;
   607    for (
unsigned e=0;e<nel;e++)
   621      unsigned el_number=0;
   622      mesh_file >> el_number;
   626      mesh_file >> el_type;
   648        std:: string error_msg(
"Can't handle element type: ");
   649        error_msg += oomph::StringConversion::to_string(el_type);
   650        throw OomphLibError(error_msg, 
   651                            OOMPH_CURRENT_FUNCTION,
   652                            OOMPH_EXCEPTION_LOCATION);
   662      mesh_file >> physical_tag;
   666      mesh_file >> geom_tag;
   668      Vector<int> other_tags;
   669      for (
unsigned i=2;i<ntags;i++)
   673        other_tags.push_back(tag);
   680      std::getline(mesh_file,s);
   681      std::istringstream iss(s);
   683      Vector<int> other_ints;
   686        other_ints.push_back(atoi(sub.c_str()));
   688      unsigned n_el_nod=other_ints.size();
   689      for (
unsigned j=0;j<n_el_nod;j++)
   691        unsigned node_number=unsigned(other_ints[j]);
   692        element_node_index[el_number].push_back(node_number);
   700            boundary_node[unsigned(physical_tag)].insert(node_number);
   701            one_based_boundaries_of_node[node_number].insert(
   702             unsigned(physical_tag));
   703            if (
unsigned(physical_tag)>highest_one_based_boundary_id) 
   705              highest_one_based_boundary_id=physical_tag;
   716          region_element[unsigned(physical_tag)].insert(n_tet_el);
   722    if (line!=
"$EndElements")
   724      std::string error_msg
   725       (
"Line has to contain the string \"$EndElements\"; ");
   726      error_msg += 
" yours contains: " + line;
   727      throw OomphLibError(error_msg, 
   728                          OOMPH_CURRENT_FUNCTION,
   729                          OOMPH_EXCEPTION_LOCATION);
   737    if (line!=
"$MeshFormat")
   739      std::string error_msg
   740       (
"First line has to contain the string \"$MeshFormat\"; ");
   741      error_msg += 
" yours contains: " + line;
   742      throw OomphLibError(error_msg, 
   743                          OOMPH_CURRENT_FUNCTION,
   744                          OOMPH_EXCEPTION_LOCATION);
   759    std::map<unsigned,std::set<unsigned> > element_next_to_boundary;
   760    for (std::map<
unsigned,Vector<unsigned> >::iterator it=
   761          element_node_index.begin();it!=element_node_index.end();it++)
   763      unsigned el_number=(*it).first;
   764      unsigned nnod=((*it).second).size();
   767        std::map<unsigned,unsigned> boundary_node_count;
   768        for (
unsigned j=0;j<nnod;j++)
   770          unsigned node_number=((*it).second)[j]; 
   771          std::map<unsigned,std::set<unsigned> >::iterator itt=
   772          one_based_boundaries_of_node.find(node_number);
   773          if (itt!=one_based_boundaries_of_node.end()) 
   775            for (std::set<unsigned>::iterator ittt=(itt->second).begin();
   776                 ittt!=(itt->second).end();ittt++)
   778              unsigned one_based_boundary_id=(*ittt);
   779              boundary_node_count[one_based_boundary_id]++;
   783        for (std::map<unsigned,unsigned>::iterator 
   784              itt=boundary_node_count.begin();
   785             itt!=boundary_node_count.end();itt++)
   787          if ((*itt).second==3)
   789            element_next_to_boundary[(*itt).first].insert(el_number);
   795    this->set_nboundary(highest_one_based_boundary_id);
   801    Vector<unsigned> oomph_lib_node_number(4);
   802    oomph_lib_node_number[0]=0;
   803    oomph_lib_node_number[1]=3;
   804    oomph_lib_node_number[2]=2;
   805    oomph_lib_node_number[3]=1;
   808    Element_pt.resize(n_tet_el);
   809    Node_pt.resize(nnod);
   812    Vector<Node*> existing_node_pt(nnod,0);
   816    for (std::map<
unsigned,Vector<unsigned> >::iterator it=
   817          element_node_index.begin();
   818         it!=element_node_index.end();it++)
   820      unsigned el_nnod=(*it).second.size();
   824        TElement<3,2>* el_pt=
new TElement<3,2>;
   831        for (
unsigned j=0;j<el_nnod;j++)
   834          unsigned node_number=(*it).second[j];
   837          if (existing_node_pt[node_number-1]!=0)
   839            el_pt->node_pt(oomph_lib_node_number[j])=
   840             existing_node_pt[node_number-1];
   848            if (one_based_boundaries_of_node[node_number].size()==0)
   851              nod_pt=el_pt->construct_node(oomph_lib_node_number[j]);
   852              Node_pt[node_number-1]=nod_pt;
   853              existing_node_pt[node_number-1]=nod_pt;
   858              nod_pt=el_pt->construct_boundary_node(oomph_lib_node_number[j]);
   859              Node_pt[node_number-1]=nod_pt;
   860              existing_node_pt[node_number-1]=nod_pt;
   863              for (std::set<unsigned>::iterator it=
   864                    one_based_boundaries_of_node[node_number].begin();
   865                   it!=one_based_boundaries_of_node[node_number].end();it++)
   867                add_boundary_node((*it)-1,nod_pt);
   872            Vector<double> x(node_coordinate[node_number]);
   873            for (
unsigned i=0;i<3;i++)
   886    unsigned n_region=region_element.size();
   887    this->Region_element_pt.resize(n_region);
   888    this->Region_attribute.resize(n_region);
   889    unsigned region_count=0;
   890    for (std::map<
unsigned,std::set<unsigned> >::iterator it=
   891          region_element.begin();it!=region_element.end();it++)
   893      this->Region_element_pt[region_count].resize((*it).second.size());
   894      unsigned one_based_region_id=(*it).first;
   895      this->Region_attribute[region_count]=one_based_region_id-1;
   897      for (std::set<unsigned>::iterator itt=(*it).second.begin();
   898           itt!=(*it).second.end();itt++)
   900        unsigned one_based_el_number=(*itt);
   901        this->Region_element_pt[region_count][count]=
   902         dynamic_cast<FiniteElement*
>(Element_pt[one_based_el_number-1]);
   911    bool plot_for_debugging=
false;
   912    if (plot_for_debugging)
   914      std::ofstream outfile;
   915      std::string outfile_name;
   916      std::string mesh_file_stem=
"shite";
   920      outfile_name=mesh_file_stem+
"_element_nodes.dat";
   921      outfile.open(outfile_name.c_str());
   922      for (std::map<
unsigned,Vector<unsigned> >::iterator it=
   923            element_node_index.begin();it!=element_node_index.end();it++)
   925        std::set<unsigned> shite_nodes;
   926        unsigned el_id=(*it).first;
   927        std::stringstream tmp_out;
   928        for (Vector<unsigned>::iterator itt=(*it).second.begin();
   929             itt!=(*it).second.end();itt++)
   931          unsigned node_number=(*itt);
   932          shite_nodes.insert(node_number);
   933          Vector<double> x(node_coordinate[node_number]);
   935          for (
unsigned i=0;i<n;i++)
   937            tmp_out << x[i] << 
" ";
   939          tmp_out << node_number << std::endl;
   941        std::string prefix=
", N=4, E=1, F=FEPOINT, ET=TETRAHEDRON";
   942        std::string postfix=
"1 2 3 4";
   943        if ((*it).second.size()==3)
   945          prefix=
", N=3, E=1, F=FEPOINT, ET=TRIANGLE"; 
   948        outfile << 
"ZONE T=\"one-based element id="    949                << el_id << 
"\"" << prefix << std::endl; 
   950        outfile << tmp_out.str();
   951        outfile << postfix << std::endl;
   957      outfile_name=mesh_file_stem+
"_boundary_nodes.dat";
   958      outfile.open(outfile_name.c_str());
   959      for (std::map<
unsigned,std::set<unsigned> >::iterator it=
   960            boundary_node.begin();it!=boundary_node.end();it++)
   962        unsigned one_based_boundary_id=(*it).first;
   963        outfile << 
"ZONE T=\"one-based boundary id="   964                << one_based_boundary_id << 
"\"" << std::endl;
   965        for (std::set<unsigned>::iterator itt=(*it).second.begin();
   966             itt!=(*it).second.end();itt++)
   968          unsigned node_number=(*itt);
   969          Vector<double> x(node_coordinate[node_number]);
   971          for (
unsigned i=0;i<n;i++)
   973            outfile << x[i] << 
" ";
   975          outfile << node_number << std::endl;
   983      for (std::map<
unsigned,std::set<unsigned> >::iterator it=
   984            element_next_to_boundary.begin();
   985           it!=element_next_to_boundary.end();it++)
   987        unsigned one_based_boundary_id=(*it).first;
   988        outfile_name=mesh_file_stem+
"_elements_next_to_boundary_"   989         +oomph::StringConversion::to_string(one_based_boundary_id)+
".dat";
   990        outfile.open(outfile_name.c_str());
   991        for (std::set<unsigned>::iterator itt=(*it).second.begin();
   992             itt!=(*it).second.end();itt++)
   994          outfile << 
"ZONE T=\"one-based boundary "   995                  << one_based_boundary_id
   996                  << 
"\", N=4, E=1, F=FEPOINT, ET=TETRAHEDRON"   998          unsigned el_number=(*itt);
   999          unsigned nnod=element_node_index[el_number].size();
  1000          for (
unsigned j=0;j<nnod;j++)
  1002            unsigned node_number=element_node_index[el_number][j];
  1003            Vector<double> x(node_coordinate[node_number]);
  1004            unsigned n=x.size();
  1005            for (
unsigned i=0;i<n;i++)
  1007              outfile << x[i] << 
" ";
  1009            outfile << std::endl;
  1011          outfile << 
"1 2 3 4" << std::endl;
  1020       unsigned nel=this->nelement();
  1021       for (
unsigned e=0;e<nel;e++)
  1023         vol+=this->finite_element_pt(e)->size();
  1025       oomph_info << 
"Total volume of all elements in scaffold mesh: "  1026                  << vol << std::endl;
  1038     Gmsh_parameters_pt->outer_boundary_pt();
  1041     Gmsh_parameters_pt->internal_surface_pt();
  1046     Gmsh_parameters_pt->target_size_file_name();
  1049    std::string filename=Gmsh_parameters_pt->geo_and_msh_file_stem()+
".geo";
  1050    std::ofstream geo_file;
  1051    geo_file.open(filename.c_str());
  1053    geo_file << 
"// Uniform element size" << std::endl;
  1054    geo_file << 
"//---------------------" << std::endl;
  1055    geo_file << 
"lc=" << pow(element_volume,1.0/3.0) << 
";" << std::endl; 
  1056    geo_file << std::endl;
  1062    geo_file << 
"// Outer box" << std::endl;
  1063    geo_file << 
"//==========" << std::endl;
  1064    geo_file << std::endl;
  1065    geo_file << 
"// Vertices" << std::endl;
  1066    geo_file << 
"//---------" << std::endl;
  1067    std::map<TetMeshVertex*,unsigned> vertex_number;
  1068    unsigned nv=outer_boundary_pt->nvertex();
  1069    for (
unsigned j=0;j<nv;j++)
  1071      TetMeshVertex* vertex_pt=outer_boundary_pt->vertex_pt(j);
  1072      vertex_number[vertex_pt]=j;
  1073      geo_file << 
"Point(" << j+1 << 
")={";
  1074      for (
unsigned i=0;i<3;i++)
  1076        geo_file << vertex_pt->x(i) << 
",";
  1078      geo_file << 
"lc};" << std::endl;
  1083    std::set<TetEdge> tet_edge_set; 
  1084    unsigned nfacet=outer_boundary_pt->nfacet();
  1085    for (
unsigned f=0;f<nfacet;f++)
  1087      TetMeshFacet* facet_pt=outer_boundary_pt->facet_pt(f);
  1088      unsigned nv=facet_pt->nvertex();
  1089      for (
unsigned j=0;j<nv-1;j++)
  1091        TetMeshVertex* first_vertex_pt=facet_pt->vertex_pt(j);
  1092        TetMeshVertex* second_vertex_pt=facet_pt->vertex_pt(j+1);
  1093        TetEdge my_tet_edge(vertex_number[first_vertex_pt]+1,
  1094                            vertex_number[second_vertex_pt]+1);
  1095        tet_edge_set.insert(my_tet_edge);
  1097      TetMeshVertex* first_vertex_pt=facet_pt->vertex_pt(nv-1); 
  1098      TetMeshVertex* second_vertex_pt=facet_pt->vertex_pt(0);
  1099      TetEdge my_tet_edge(vertex_number[first_vertex_pt]+1,
  1100                          vertex_number[second_vertex_pt]+1);  
  1101      tet_edge_set.insert(my_tet_edge);
  1105    geo_file <<std::endl;
  1106    geo_file << 
"// Edge of outer box" << std::endl;
  1107    geo_file << 
"//------------------" << std::endl;
  1109    std::map<TetEdge,unsigned> tet_edge;
  1110    for (std::set<TetEdge>::iterator it=tet_edge_set.begin();
  1111         it!=tet_edge_set.end();it++)
  1113      tet_edge.insert(std::make_pair((*it),count));
  1114      geo_file << 
"Line(" << count+1 << 
")={"   1115               << (*it).first_vertex_id() 
  1117               << (*it).second_vertex_id()
  1118               << 
"};" << std::endl;
  1124    geo_file <<std::endl;
  1125    geo_file << 
"// Faces of outer box" << std::endl;
  1126    geo_file << 
"//-------------------" << std::endl;
  1127    for (
unsigned f=0;f<nfacet;f++)
  1129      geo_file << 
"Line Loop(" << f+1 << 
")={"; 
  1131      TetMeshFacet* facet_pt=outer_boundary_pt->facet_pt(f);
  1132      unsigned nv=facet_pt->nvertex();
  1133      for (
unsigned j=0;j<nv-1;j++)
  1135        TetMeshVertex* first_vertex_pt=facet_pt->vertex_pt(j);
  1136        TetMeshVertex* second_vertex_pt=facet_pt->vertex_pt(j+1);
  1137        TetEdge my_tet_edge(vertex_number[first_vertex_pt]+1,
  1138                            vertex_number[second_vertex_pt]+1);
  1140        std::map<TetEdge,unsigned>::iterator it=tet_edge.find(my_tet_edge);
  1143          geo_file << -int((it->second)+1) << 
",";
  1147          geo_file << ((it->second)+1) << 
",";
  1153      TetMeshVertex* first_vertex_pt=facet_pt->vertex_pt(nv-1);
  1154      TetMeshVertex* second_vertex_pt=facet_pt->vertex_pt(0);
  1155      TetEdge my_tet_edge(vertex_number[first_vertex_pt]+1,
  1156                          vertex_number[second_vertex_pt]+1);
  1158      std::map<TetEdge,unsigned>::iterator it=tet_edge.find(my_tet_edge);
  1161        geo_file << -int((it->second)+1) << 
"};" << std::endl;
  1165        geo_file << ((it->second)+1) << 
"};" << std::endl;
  1167      geo_file << 
"Plane Surface(" << f+1 << 
")={" << f+1 << 
"};"   1173    geo_file << std::endl;
  1174    geo_file << 
"// Define Plane Surfaces bounding the volume" << std::endl;
  1175    geo_file << 
"//------------------------------------------" << std::endl;
  1176    geo_file << 
"Surface Loop(1) = {";
  1177    for (
unsigned f=0;f<nfacet-1;f++)
  1179      geo_file << f+1 << 
",";
  1181    geo_file << nfacet << 
"};" << std::endl;
  1184    geo_file << std::endl;
  1185    geo_file << 
"// Define one-based boundary IDs" << std::endl;
  1186    geo_file << 
"//------------------------------" << std::endl;
  1187    for (
unsigned f=0;f<nfacet;f++)
  1189      unsigned one_based_boundary_id=
  1190       outer_boundary_pt->one_based_facet_boundary_id(f);
  1191      geo_file << 
"Physical Surface(" << one_based_boundary_id 
  1192               << 
") = {" << f+1 << 
"};" << std::endl; 
  1199    Vector<unsigned> volume_id_to_be_subtracted_off;
  1200    unsigned nvertex_offset=outer_boundary_pt->nvertex();
  1201    unsigned nfacet_offset=outer_boundary_pt->nfacet();
  1202    unsigned nvolume_offset=1;
  1203    unsigned nline_offset=tet_edge.size();
  1208    Vector<unsigned> surfaces_to_be_embedded_in_main_volume;
  1209    std::map<unsigned,Vector<unsigned> > 
  1210     surfaces_to_be_embedded_in_specified_one_based_region;
  1214    unsigned n_internal=internal_surface_pt.size();
  1215    for (
unsigned i_internal=0;i_internal<n_internal;i_internal++)
  1219      TetMeshFacetedClosedSurface* closed_srf_pt=
  1220       dynamic_cast<TetMeshFacetedClosedSurface*
>(
  1221        internal_surface_pt[i_internal]);
  1222      bool inner_surface_is_closed=
true;
  1223      if (closed_srf_pt==0)
  1225        inner_surface_is_closed=
false;
  1229      unsigned number_of_volumes_created_for_this_internal_object=0;
  1232      geo_file <<std::endl;
  1233      geo_file <<std::endl;
  1234      geo_file << 
"// Inner faceted surface " << i_internal << std::endl;
  1235      geo_file << 
"//==========================" << std::endl;
  1236      geo_file << std::endl;
  1237      geo_file << 
"// Vertices" << std::endl;
  1238      geo_file << 
"//---------" << std::endl;
  1239      std::map<TetMeshVertex*,unsigned> vertex_number;
  1240      unsigned nv=internal_surface_pt[i_internal]->nvertex();
  1241      for (
unsigned j=0;j<nv;j++)
  1243        TetMeshVertex* vertex_pt=
  1244         internal_surface_pt[i_internal]->vertex_pt(j);
  1245        vertex_number[vertex_pt]=nvertex_offset+j;
  1246        geo_file << 
"Point(" << nvertex_offset+j+1 << 
")={";
  1247        for (
unsigned i=0;i<3;i++)
  1249          geo_file << vertex_pt->x(i) << 
",";
  1251        geo_file << 
"lc};" << std::endl;
  1255      std::set<TetEdge> tet_edge_set; 
  1256      unsigned nfacet=internal_surface_pt[i_internal]->nfacet();
  1257      for (
unsigned f=0;f<nfacet;f++)
  1259        TetMeshFacet* facet_pt=internal_surface_pt[i_internal]->facet_pt(f);
  1260        unsigned nv=facet_pt->nvertex();
  1261        for (
unsigned j=0;j<nv-1;j++)
  1263          TetMeshVertex* first_vertex_pt=facet_pt->vertex_pt(j);
  1264          TetMeshVertex* second_vertex_pt=facet_pt->vertex_pt(j+1);
  1265          TetEdge my_tet_edge(vertex_number[first_vertex_pt]+1,
  1266                              vertex_number[second_vertex_pt]+1);
  1267          tet_edge_set.insert(my_tet_edge);
  1269        TetMeshVertex* first_vertex_pt=facet_pt->vertex_pt(nv-1); 
  1270        TetMeshVertex* second_vertex_pt=facet_pt->vertex_pt(0);
  1271        TetEdge my_tet_edge(vertex_number[first_vertex_pt]+1,
  1272                            vertex_number[second_vertex_pt]+1);  
  1273        tet_edge_set.insert(my_tet_edge);
  1276      geo_file <<std::endl;
  1277      geo_file << 
"// Edge of inner faceted surface" << std::endl;
  1278      geo_file << 
"//------------------------------" << std::endl;
  1280      std::map<TetEdge,unsigned> tet_edge;
  1281      for (std::set<TetEdge>::iterator it=tet_edge_set.begin();
  1282           it!=tet_edge_set.end();it++)
  1284        tet_edge.insert(std::make_pair((*it),nline_offset+count));
  1285        geo_file << 
"Line(" << nline_offset+count+1 << 
")={"   1286                 << (*it).first_vertex_id() 
  1288                 << (*it).second_vertex_id()
  1289                 << 
"};" << std::endl;
  1295      geo_file <<std::endl;
  1296      geo_file << 
"// Faces of inner faceted surface" << std::endl;
  1297      geo_file << 
"//-------------------------------" << std::endl;
  1298      for (
unsigned f=0;f<nfacet;f++)
  1300        geo_file << 
"Line Loop(" << nfacet_offset+f+1 << 
")={"; 
  1302        TetMeshFacet* facet_pt=internal_surface_pt[i_internal]->facet_pt(f);
  1303        unsigned nv=facet_pt->nvertex();
  1304        for (
unsigned j=0;j<nv-1;j++)
  1306          TetMeshVertex* first_vertex_pt=facet_pt->vertex_pt(j);
  1307          TetMeshVertex* second_vertex_pt=facet_pt->vertex_pt(j+1);
  1308          TetEdge my_tet_edge(vertex_number[first_vertex_pt]+1,
  1309                              vertex_number[second_vertex_pt]+1);
  1311          std::map<TetEdge,unsigned>::iterator it=tet_edge.find(my_tet_edge);
  1314            geo_file << -int((it->second)+1) << 
",";
  1318            geo_file << ((it->second)+1) << 
",";
  1324        TetMeshVertex* first_vertex_pt=facet_pt->vertex_pt(nv-1);
  1325        TetMeshVertex* second_vertex_pt=facet_pt->vertex_pt(0);
  1326        TetEdge my_tet_edge(vertex_number[first_vertex_pt]+1,
  1327                            vertex_number[second_vertex_pt]+1);
  1329        std::map<TetEdge,unsigned>::iterator it=tet_edge.find(my_tet_edge);
  1332          geo_file << -int((it->second)+1) << 
"};" << std::endl;
  1336          geo_file << ((it->second)+1) << 
"};" << std::endl;
  1338        geo_file << 
"Plane Surface(" << nfacet_offset+f+1 << 
")={"   1339                 <<  nfacet_offset+f+1 
  1340                 << 
"};" << std::endl; 
  1344        bool facet_is_embedded_in_a_volume=facet_pt->
  1345         facet_is_embedded_in_a_specified_region();
  1346        if (facet_is_embedded_in_a_volume)
  1348          unsigned one_based_region_id=
  1349           facet_pt->one_based_region_that_facet_is_embedded_in();
  1350          if (one_based_region_id==1)
  1352            surfaces_to_be_embedded_in_main_volume.push_back(nfacet_offset+f+1);
  1356            surfaces_to_be_embedded_in_specified_one_based_region
  1357             [one_based_region_id].push_back(nfacet_offset+f+1);
  1363          if (!inner_surface_is_closed)
  1365            surfaces_to_be_embedded_in_main_volume.push_back(nfacet_offset+f+1);
  1371      std::set<unsigned> all_regions_id;
  1375      std::map<unsigned,Vector<unsigned> > region_bounding_facet;
  1380      Vector<unsigned> outer_bounding_facet;
  1384      for (
unsigned f=0;f<nfacet;f++)
  1386        TetMeshFacet* facet_pt=internal_surface_pt[i_internal]->facet_pt(f);
  1387        std::set<unsigned> region_id(facet_pt->one_based_adjacent_region_id());
  1388        unsigned nr=region_id.size();
  1389        if (nr==1) outer_bounding_facet.push_back(nfacet_offset+f+1);
  1390        if ((nr==0)&&inner_surface_is_closed)
  1395          surfaces_to_be_embedded_in_main_volume.push_back(nfacet_offset+f+1);
  1397        for (std::set<unsigned>::iterator it=region_id.begin();
  1398             it!=region_id.end();it++)
  1400          all_regions_id.insert((*it));
  1401          region_bounding_facet[(*it)].push_back(nfacet_offset+f+1);
  1406      unsigned n_regions_bounded_by_facets=all_regions_id.size();
  1409      if (n_regions_bounded_by_facets==0)
  1411        if (inner_surface_is_closed)
  1413          std::ostringstream error_message;
  1415           << 
"Something fishy going on! "   1416           << 
"Internal faceted surface "  1418           << 
" is closed but does not bound any regions!\n"  1419           << 
"Specify one-based region ID for all facets using\n\n"  1420           << 
"   TetMeshFacet::set_one_based_adjacent_region_id(...)\n\n";
  1421          throw  OomphLibError(error_message.str(),
  1422                               OOMPH_CURRENT_FUNCTION,
  1423                               OOMPH_EXCEPTION_LOCATION);
  1430        unsigned offset_for_extra_hole=0;
  1431        if (n_regions_bounded_by_facets>1)
  1433          geo_file << std::endl;
  1435           << 
"// Define Plane Surfaces bounding compound volume"  1437           << 
"//-----------------------------------------------"   1440           << 
"// that will have to be treated as hole in main volume"  1442           << 
"//-----------------------------------------------"   1444          offset_for_extra_hole=1;
  1445          geo_file << 
"Surface Loop(" << nvolume_offset+1 
  1447          unsigned n=outer_bounding_facet.size();
  1448          for (
unsigned f=0;f<n-1;f++)
  1450            geo_file << outer_bounding_facet[f] << 
",";
  1452          geo_file << outer_bounding_facet[n-1] << 
"};" << std::endl;
  1455          number_of_volumes_created_for_this_internal_object++;
  1459        volume_id_to_be_subtracted_off.push_back(nvolume_offset+1);
  1463        for (std::map<
unsigned,Vector<unsigned> >::iterator it=
  1464              region_bounding_facet.begin();it!=region_bounding_facet.end();
  1467          geo_file << std::endl;
  1468          geo_file << 
"// Define Plane Surfaces bounding the region volume "  1469                   << (*it).first << std::endl;
  1471           << 
"//----------------------------------------------------"   1473          geo_file << 
"Surface Loop("   1474                   << nvolume_offset+1+offset_for_extra_hole+count
  1476          unsigned n=(*it).second.size();
  1477          for (
unsigned f=0;f<n-1;f++)
  1479            geo_file << ((*it).second)[f] << 
",";
  1481          geo_file << ((*it).second)[n-1] << 
"};" << std::endl;
  1483          geo_file << std::endl;
  1484          geo_file << 
"// Define volume "   1485                   << nvolume_offset+1+offset_for_extra_hole+count
  1486                   << 
" as the volume bounded by Surface Loop "  1487                   << nvolume_offset+1+offset_for_extra_hole+count
  1490           << 
"//--------------------------------------------------------"  1492          geo_file << 
"Volume("   1493                   << nvolume_offset+1+offset_for_extra_hole+count << 
")={"   1494                   << nvolume_offset+1+offset_for_extra_hole+count 
  1495                   << 
"};" << std::endl;
  1496          geo_file << std::endl;
  1499          number_of_volumes_created_for_this_internal_object++;
  1503          bool mesh_the_volume=
true;
  1504          if (closed_srf_pt!=0)
  1506            if (closed_srf_pt->faceted_volume_represents_hole_for_gmsh())
  1508              mesh_the_volume=
false;
  1511          if (mesh_the_volume)
  1513            geo_file << 
"// Define one-based region IDs" << std::endl;
  1514            geo_file << 
"//----------------------------" << std::endl;
  1515            geo_file << 
"Physical Volume(" << (*it).first
  1517                     << nvolume_offset+1+offset_for_extra_hole+count 
  1518                     << 
"};" << std::endl;
  1520            unsigned ns_embedded=
  1521             surfaces_to_be_embedded_in_specified_one_based_region
  1522             [(*it).first].size();
  1525              geo_file << 
"// This region has " << ns_embedded 
  1526                       << 
" embedded surfaces\n";
  1527              geo_file << 
"Surface{";
  1528              for (
unsigned i=0;i<ns_embedded-1;i++)
  1530                geo_file << surfaces_to_be_embedded_in_specified_one_based_region
  1531                 [(*it).first][i] << 
",";
  1533              geo_file << surfaces_to_be_embedded_in_specified_one_based_region
  1534               [(*it).first][ns_embedded-1] << 
"}In Volume {"  1535                       << nvolume_offset+1+offset_for_extra_hole+count 
  1536                       << 
"};" << std::endl;
  1544      geo_file << std::endl;
  1545      geo_file << 
"// Define one-based boundary IDs" << std::endl;
  1546      geo_file << 
"//------------------------------" << std::endl;
  1547      for (
unsigned f=0;f<nfacet;f++)
  1549        unsigned one_based_boundary_id=
  1550         internal_surface_pt[i_internal]->one_based_facet_boundary_id(f);
  1551        geo_file << 
"Physical Surface(" << one_based_boundary_id 
  1552                 << 
") = {" << nfacet_offset+f+1
  1553                 << 
"};" << std::endl; 
  1557      nvertex_offset+=internal_surface_pt[i_internal]->nvertex();
  1558      nfacet_offset+=internal_surface_pt[i_internal]->nfacet();
  1559      nvolume_offset+=number_of_volumes_created_for_this_internal_object;
  1560      nline_offset+=tet_edge.size();
  1567    geo_file << std::endl;
  1568    geo_file << 
"// Define volume 1 as the volume bounded by Surface Loop 1"  1570    geo_file << 
"//--------------------------------------------------------"  1572    unsigned n=volume_id_to_be_subtracted_off.size();
  1575      geo_file << 
"// with volume[s]: ";
  1576      for (
unsigned i=0;i<n;i++)
  1578        geo_file << volume_id_to_be_subtracted_off[i] << 
" ";
  1580      geo_file << 
"removed." << std::endl;
  1581      geo_file << 
"//--------------------------------------------------------"  1586    geo_file << 
"Volume(1)={1";
  1589    for (
unsigned i=0;i<n;i++)
  1591      geo_file << 
"," << volume_id_to_be_subtracted_off[i];
  1593    geo_file << 
"};" << std::endl;
  1594    geo_file << std::endl;
  1598    geo_file << 
"// Define one-based region IDs" << std::endl;
  1599    geo_file << 
"//----------------------------" << std::endl;
  1600    geo_file << 
"Physical Volume(1"   1601             << 
")={1};" << std::endl;
  1605    unsigned ns=surfaces_to_be_embedded_in_main_volume.size();
  1608      geo_file << std::endl;
  1609      geo_file << 
"// Embed Plane Surfaces in main volume (volume 1)"   1611      geo_file << 
"//-----------------------------------------------"   1613      geo_file << 
"Surface{";
  1614      for (
unsigned s=0;s<ns-1;s++)
  1616        geo_file << surfaces_to_be_embedded_in_main_volume[s] << 
","; 
  1618      geo_file << surfaces_to_be_embedded_in_main_volume[ns-1] 
  1619               << 
"} In Volume{1};" << std::endl;
  1620      geo_file << std::endl;
  1626     if (use_mesh_grading_from_file)
  1632       std::ifstream file(target_size_file_name.c_str(),
  1638         std::string error_msg(
"Failed to open target volume file: ");
  1640         throw OomphLibError(error_msg, 
  1641                             OOMPH_CURRENT_FUNCTION,
  1642                             OOMPH_EXCEPTION_LOCATION);
  1646       geo_file << 
"Field[1]=Structured;" << std::endl;
  1647       geo_file << 
"Field[1].FileName=\""   1648                << target_size_file_name << 
"\";" << std::endl;
  1649       geo_file << 
"Field[1].TextFormat=1;" << std::endl;
  1650       geo_file << 
"Background Field = 1;" << std::endl;
  1656    geo_file << std::endl;
  1657    geo_file << 
"Mesh 3;" << std::endl;
  1693  template<
class ELEMENT>
  1694   class GmshTetMesh : 
public virtual TetMeshBase, 
public virtual Mesh
  1701                TimeStepper* time_stepper_pt=&Mesh::Default_TimeStepper) :
  1702   Gmsh_parameters_pt(gmsh_parameters_pt)
  1704    bool use_mesh_grading_from_file=
false;
  1705    build_it(time_stepper_pt,use_mesh_grading_from_file);
  1712                const bool& use_mesh_grading_from_file,
  1713                TimeStepper* time_stepper_pt=&Mesh::Default_TimeStepper) :
  1714   Gmsh_parameters_pt(gmsh_parameters_pt)
  1716    build_it(time_stepper_pt,use_mesh_grading_from_file);
  1724                  const bool& use_mesh_grading_from_file)
  1727    MeshChecker::assert_geometric_element<TElementGeometricBase,ELEMENT>(3);
  1731     Gmsh_parameters_pt->outer_boundary_pt();
  1734     Gmsh_parameters_pt->internal_surface_pt();
  1737    Time_stepper_pt=time_stepper_pt;
  1745     for (
unsigned f=0;f<n_facet;f++)
  1755         std::ostringstream error_message;
  1756         error_message << 
"Boundary IDs have to be one-based. Yours is "   1758         throw OomphLibError(error_message.str(),
  1759                             OOMPH_CURRENT_FUNCTION,
  1760                             OOMPH_EXCEPTION_LOCATION);
  1771     unsigned n=Internal_surface_pt.size();
  1772     for (
unsigned i=0;i<n;i++)
  1774       unsigned n_facet=Internal_surface_pt[i]->nfacet();
  1775       for (
unsigned f=0;f<n_facet;f++)
  1777         unsigned b=Internal_surface_pt[i]->one_based_facet_boundary_id(f);
  1780           Tet_mesh_faceted_surface_pt[b-1]=Internal_surface_pt[i];    
  1781           Tet_mesh_facet_pt[b-1]=
  1782            Internal_surface_pt[i]->facet_pt(f);         
  1786           std::ostringstream error_message;
  1787           error_message << 
"Boundary IDs have to be one-based. Yours is "   1789           throw OomphLibError(error_message.str(),
  1790                               OOMPH_CURRENT_FUNCTION,
  1791                               OOMPH_EXCEPTION_LOCATION);
  1800                             use_mesh_grading_from_file);
  1803    build_from_scaffold(tmp_scaffold_mesh_pt,time_stepper_pt);
  1806    delete tmp_scaffold_mesh_pt;
  1807    tmp_scaffold_mesh_pt=0;
  1810    unsigned nb=nboundary();
  1811    for (
unsigned b=0;b<nb;b++)
  1813      bool switch_normal=
false;
  1814      setup_boundary_coordinates<ELEMENT>(b,switch_normal); 
  1819    snap_nodes_onto_geometric_objects();
  1834                            TimeStepper* time_stepper_pt)
  1837    MeshChecker::assert_geometric_element<TElementGeometricBase,ELEMENT>(3);
  1840    unsigned nelem=tmp_scaffold_mesh_pt->nelement();
  1841    Element_pt.resize(nelem);
  1844    std::map<FiniteElement*,unsigned> scaffold_mesh_element_number;
  1847    unsigned nnode_scaffold=tmp_scaffold_mesh_pt->nnode();
  1848    Node_pt.resize(nnode_scaffold);
  1851    unsigned nbound=tmp_scaffold_mesh_pt->nboundary();
  1852    set_nboundary(nbound);
  1855    Boundary_element_pt.resize(nbound); 
  1856    Face_index_at_boundary.resize(nbound); 
  1857    Boundary_region_element_pt.resize(nbound);
  1858    Face_index_region_at_boundary.resize(nbound);
  1861    for (
unsigned e=0;e<nelem;e++)
  1863      Element_pt[e]=
new ELEMENT;
  1867    unsigned nnod_el=tmp_scaffold_mesh_pt->finite_element_pt(0)->nnode();
  1872    std::map<Node*,unsigned> global_number;
  1873    unsigned global_count=0;
  1876    for (
unsigned e=0;e<nelem;e++)
  1880      scaffold_mesh_element_number[tmp_scaffold_mesh_pt->finite_element_pt(e)]=e;
  1883      for (
unsigned j=0;j<nnod_el;j++)
  1887        Node* scaffold_node_pt=
  1888         tmp_scaffold_mesh_pt->finite_element_pt(e)->node_pt(j);
  1892        unsigned j_global=global_number[scaffold_node_pt];
  1899          std::set<unsigned>* boundaries_pt;
  1900          scaffold_node_pt->get_boundaries_pt(boundaries_pt);
  1903          if (boundaries_pt!=0)
  1906            Node* new_node_pt=finite_element_pt(e)->
  1907             construct_boundary_node(j,time_stepper_pt);
  1913            global_number[scaffold_node_pt]=global_count;
  1916            for(std::set<unsigned>::iterator it=boundaries_pt->begin();
  1917                it!=boundaries_pt->end();++it)
  1919              add_boundary_node(*it,new_node_pt);
  1926            finite_element_pt(e)->construct_node(j,time_stepper_pt); 
  1932            global_number[scaffold_node_pt]=global_count;
  1939          Node_pt[global_count-1]=finite_element_pt(e)->node_pt(j);
  1942          Node_pt[global_count-1]->x(0)=scaffold_node_pt->x(0);
  1943          Node_pt[global_count-1]->x(1)=scaffold_node_pt->x(1);
  1944          Node_pt[global_count-1]->x(2)=scaffold_node_pt->x(2);
  1950          finite_element_pt(e)->node_pt(j)=Node_pt[j_global-1];         
  1956      FiniteElement* fe_pt=finite_element_pt(e);
  1957      for (
unsigned f=0;f<4;f++)
  1959        Node* face_node0_pt=0;
  1960        Node* face_node1_pt=0;
  1961        Node* face_node2_pt=0;
  1966          face_node0_pt=fe_pt->node_pt(1);
  1967          face_node1_pt=fe_pt->node_pt(2);
  1968          face_node2_pt=fe_pt->node_pt(3);
  1972          face_node0_pt=fe_pt->node_pt(0);
  1973          face_node1_pt=fe_pt->node_pt(2);
  1974          face_node2_pt=fe_pt->node_pt(3);
  1978          face_node0_pt=fe_pt->node_pt(0);
  1979          face_node1_pt=fe_pt->node_pt(1);
  1980          face_node2_pt=fe_pt->node_pt(3);
  1984          face_node0_pt=fe_pt->node_pt(0);
  1985          face_node1_pt=fe_pt->node_pt(1);
  1986          face_node2_pt=fe_pt->node_pt(2);
  1991          std::ostringstream error_message;
  1992          error_message << 
"Wrong face number " << f << std::endl;
  1993          throw OomphLibError(error_message.str(),
  1994                              OOMPH_CURRENT_FUNCTION,
  1995                              OOMPH_EXCEPTION_LOCATION);
  2001        std::set<unsigned>* bc0_pt;
  2002        face_node0_pt->get_boundaries_pt(bc0_pt);
  2005          std::set<unsigned>* bc1_pt;
  2006          face_node1_pt->get_boundaries_pt(bc1_pt);
  2009            std::set<unsigned>* bc2_pt;
  2010            face_node2_pt->get_boundaries_pt(bc2_pt);
  2013              std::set<unsigned> common_bound_0_and_1;
  2014              std::set_intersection(bc0_pt->begin(),bc0_pt->end(),
  2015                                    bc1_pt->begin(),bc1_pt->end(),
  2016                                    std::inserter(common_bound_0_and_1,
  2017                                                  common_bound_0_and_1.begin()));
  2018              std::set<unsigned> common_bound_0_and_1_and_2;
  2019              std::set_intersection
  2020               (common_bound_0_and_1.begin(),
  2021                common_bound_0_and_1.end(),
  2022                bc2_pt->begin(),bc2_pt->end(),
  2023                std::inserter(common_bound_0_and_1_and_2,
  2024                              common_bound_0_and_1_and_2.begin()));
  2025              for (std::set<unsigned>::iterator it=
  2026                    common_bound_0_and_1_and_2.begin();
  2027                   it!=common_bound_0_and_1_and_2.end();it++)
  2029                Boundary_element_pt[(*it)].push_back(fe_pt);
  2030                Face_index_at_boundary[(*it)].push_back(f);
  2039    unsigned nr=tmp_scaffold_mesh_pt->Region_element_pt.size();
  2040    Region_attribute.resize(nr);
  2041    Region_element_pt.resize(nr);
  2042    for (
unsigned i=0;i<nr;i++)
  2044      Region_attribute[i]=tmp_scaffold_mesh_pt->Region_attribute[i];
  2045      unsigned nel=tmp_scaffold_mesh_pt->Region_element_pt[i].size();
  2046      Region_element_pt[i].resize(nel);
  2047      for (
unsigned e=0;e<nel;e++)
  2049        FiniteElement* scaff_el_pt=tmp_scaffold_mesh_pt->Region_element_pt[i][e];
  2050        unsigned scaff_el_number=scaffold_mesh_element_number[scaff_el_pt];
  2051        Region_element_pt[i][e]=
  2052         dynamic_cast<FiniteElement*
>(Element_pt[scaff_el_number]);
  2057        FiniteElement* fe_pt=Region_element_pt[i][e];
  2058        for (
unsigned f=0;f<4;f++)
  2060          Node* face_node0_pt=0;
  2061          Node* face_node1_pt=0;
  2062          Node* face_node2_pt=0;
  2067            face_node0_pt=fe_pt->node_pt(1);
  2068            face_node1_pt=fe_pt->node_pt(2);
  2069            face_node2_pt=fe_pt->node_pt(3);
  2073            face_node0_pt=fe_pt->node_pt(0);
  2074            face_node1_pt=fe_pt->node_pt(2);
  2075            face_node2_pt=fe_pt->node_pt(3);
  2079            face_node0_pt=fe_pt->node_pt(0);
  2080            face_node1_pt=fe_pt->node_pt(1);
  2081            face_node2_pt=fe_pt->node_pt(3);
  2085            face_node0_pt=fe_pt->node_pt(0);
  2086            face_node1_pt=fe_pt->node_pt(1);
  2087            face_node2_pt=fe_pt->node_pt(2);
  2091            std::ostringstream error_message;
  2092            error_message << 
"Wrong face number " << f << std::endl;
  2093            throw OomphLibError(error_message.str(),
  2094                                OOMPH_CURRENT_FUNCTION,
  2095                                OOMPH_EXCEPTION_LOCATION);
  2100          std::set<unsigned>* bc0_pt;
  2101          face_node0_pt->get_boundaries_pt(bc0_pt);
  2104            std::set<unsigned>* bc1_pt;
  2105            face_node1_pt->get_boundaries_pt(bc1_pt);
  2108              std::set<unsigned>* bc2_pt;
  2109              face_node2_pt->get_boundaries_pt(bc2_pt);
  2112                std::set<unsigned> common_bound_0_and_1;
  2113                std::set_intersection
  2114                 (bc0_pt->begin(),bc0_pt->end(),
  2115                  bc1_pt->begin(),bc1_pt->end(),
  2116                  std::inserter(common_bound_0_and_1,
  2117                                common_bound_0_and_1.begin()));
  2118                std::set<unsigned> common_bound_0_and_1_and_2;
  2119                std::set_intersection
  2120                 (common_bound_0_and_1.begin(),
  2121                  common_bound_0_and_1.end(),
  2122                  bc2_pt->begin(),bc2_pt->end(),
  2123                  std::inserter(common_bound_0_and_1_and_2,
  2124                                common_bound_0_and_1_and_2.begin()));
  2125                for (std::set<unsigned>::iterator it=
  2126                      common_bound_0_and_1_and_2.begin();
  2127                     it!=common_bound_0_and_1_and_2.end();it++)
  2129                  Boundary_region_element_pt[(*it)][Region_attribute[i]].
  2131                  Face_index_region_at_boundary[(*it)][Region_attribute[i]].
  2142    Lookup_for_elements_next_boundary_is_setup=
true;
  2150    unsigned n_node_1d=finite_element_pt(0)->nnode_1d();
  2153    if ((n_node_1d!=2)&&(n_node_1d!=3))
  2155      std::ostringstream error_message;
  2156      error_message << 
"Mesh generation from gmsh currently only works\n";
  2157      error_message << 
"for nnode_1d = 2 or 3. You're trying to use it\n";
  2158      error_message << 
"for nnode_1d=" << n_node_1d << std::endl;
  2159      throw OomphLibError(error_message.str(),
  2160                          OOMPH_CURRENT_FUNCTION,
  2161                          OOMPH_EXCEPTION_LOCATION);
  2165    Vector<double> s(3);
  2168    std::map<std::pair<Node*,Node*>,Node*> midside_node_pt;
  2171    for(
unsigned e=0;e<nelem;e++)
  2174      FiniteElement* 
const el_pt = this->finite_element_pt(e);
  2175      FiniteElement* 
const simplex_el_pt = 
  2176       tmp_scaffold_mesh_pt->finite_element_pt(e);
  2179      for(
unsigned j=0;j<6;++j)
  2183        unsigned new_node_number=0;
  2184        std::pair<Node*,Node*> edge;
  2188          nod0_pt=el_pt->node_pt(0);
  2189          nod1_pt=el_pt->node_pt(1);
  2194          nod0_pt=el_pt->node_pt(0);
  2195          nod1_pt=el_pt->node_pt(2);
  2200          nod0_pt=el_pt->node_pt(0);
  2201          nod1_pt=el_pt->node_pt(3);
  2206          nod0_pt=el_pt->node_pt(1);
  2207          nod1_pt=el_pt->node_pt(2);
  2212          nod0_pt=el_pt->node_pt(2);
  2213          nod1_pt=el_pt->node_pt(3);
  2218          nod0_pt=el_pt->node_pt(1);
  2219          nod1_pt=el_pt->node_pt(3);
  2224          std::ostringstream error_message;
  2225          error_message << 
"Wrong edge number " << j << std::endl;
  2226          throw OomphLibError(error_message.str(),
  2227                              OOMPH_CURRENT_FUNCTION,
  2228                              OOMPH_EXCEPTION_LOCATION);
  2232        edge=std::make_pair(std::min(nod0_pt,nod1_pt),
  2233                            std::max(nod0_pt,nod1_pt));
  2234        Node* existing_node_pt=midside_node_pt[edge];
  2235        if (existing_node_pt==0)
  2239          std::set<unsigned> common_bound_0_and_1;
  2240          std::set<unsigned>* bc0_pt;
  2241          nod0_pt->get_boundaries_pt(bc0_pt);
  2244            std::set<unsigned>* bc1_pt;
  2245            nod1_pt->get_boundaries_pt(bc1_pt);
  2248              std::set_intersection(bc0_pt->begin(),bc0_pt->end(),
  2249                                    bc1_pt->begin(),bc1_pt->end(),
  2250                                    std::inserter(common_bound_0_and_1,
  2251                                                  common_bound_0_and_1.begin()));
  2255          Node* new_node_pt = 0;
  2258          if (common_bound_0_and_1.size()==0)
  2260            new_node_pt=el_pt->construct_node(new_node_number,time_stepper_pt); 
  2265            new_node_pt=el_pt->construct_boundary_node
  2266             (new_node_number,time_stepper_pt);
  2267            for (std::set<unsigned>::iterator it=common_bound_0_and_1.begin();
  2268                 it!=common_bound_0_and_1.end();it++)
  2270              this->add_boundary_node((*it),new_node_pt);
  2275          el_pt->local_coordinate_of_node(new_node_number,s);
  2279          for(
unsigned i=0;i<3;i++)
  2281            new_node_pt->x(i)=simplex_el_pt->interpolated_x(s,i);
  2285          midside_node_pt[edge]=new_node_pt;
  2288          Node_pt.push_back(new_node_pt);
  2293          el_pt->node_pt(new_node_number)=existing_node_pt;
  2313  template<
class ELEMENT>
  2315   public virtual RefineableTetMeshBase
  2324                          const bool& use_mesh_grading_from_file,
  2325                          TimeStepper* time_stepper_pt=
  2326                          &Mesh::Default_TimeStepper) :
  2328                        use_mesh_grading_from_file,
  2331     initialise_adaptation_data();
  2337     TimeStepper* time_stepper_pt=&Mesh::Default_TimeStepper) :
  2343     initialise_adaptation_data();
  2348   void adapt(
const Vector<double>& elem_error);
  2354    std::string error_msg(
"Not written yet...");
  2355    throw OomphLibError(error_msg,
  2356                        OOMPH_CURRENT_FUNCTION,
  2357                        OOMPH_EXCEPTION_LOCATION);
  2364    std::string error_msg(
"Not written yet...");
  2365    throw OomphLibError(error_msg,
  2366                        OOMPH_CURRENT_FUNCTION,
  2367                        OOMPH_EXCEPTION_LOCATION);
  2380      this->Gmsh_parameters_pt->max_permitted_edge_ratio();
 void create_mesh_from_msh_file()
Create mesh from msh file (created internally via disk-based operations) 
 
bool Reversed
Is it reversed? I.e. is the first input vertex stored after the second one? 
 
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...
 
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...
 
unsigned Gmsh_onscreen_output_counter
Counter for marker that indicates where we are in 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 ...
 
bool is_reversed() const
Edge is reversed in the sense that vertex1 actually has a higher id than vertex2 (when specified in t...
 
void disable_projection()
Disable projection of old solution onto new mesh. 
 
TetMeshFacetedClosedSurface * Outer_boundary_pt
Pointer to outer boundary. 
 
bool projection_is_disabled()
Is projection of old solution onto new mesh disabled? 
 
std::string Target_size_file_name
Filename for target volume (for system-call based transfer to gmsh during mesh adaptation) ...
 
double Max_element_size
Max. element size during refinement. 
 
bool Projection_is_disabled
Is projection of old solution onto new mesh disabled? 
 
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...
 
GmshTetMesh(GmshParameters *gmsh_parameters_pt, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor. 
 
void enable_projection()
Disable projection of old solution onto new mesh. 
 
unsigned & gmsh_onscreen_output_counter()
Counter for marker that indicates where we are in gmsh on-screen output. 
 
unsigned second_vertex_id() const
Second vertex id. 
 
double Min_element_size
Min. element size during refinement. 
 
double & min_element_size()
Min. element size during refinement. 
 
std::string Gmsh_onscreen_output_file_name
Output filename for gmsh on-screen output. 
 
void build_from_scaffold(GmshTetScaffoldMesh *tmp_scaffold_mesh_pt, TimeStepper *time_stepper_pt)
Build unstructured tet gmesh mesh based on output from scaffold. 
 
GmshParameters * Gmsh_parameters_pt
Parameters. 
 
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...
 
TetMeshFacetedClosedSurface *& outer_boundary_pt()
Outer boundary. 
 
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...
 
std::string & target_size_file_name()
Filename for target volumes (for system-call based transfer to gmsh during mesh adaptation). Default: .gmsh_target_size_for_adaptation.dat. 
 
TetEdge(const unsigned &vertex1, const unsigned &vertex2)
Constructor: Pass two vertices, identified by their indices Edge "direction" is from lower vertex to ...
 
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 build_it(TimeStepper *time_stepper_pt, const bool &use_mesh_grading_from_file)
 
unsigned unrefine_uniformly()
Refine uniformly. 
 
double & element_volume()
Uniform target element volume. 
 
double & dx_for_target_size_transfer()
(Isotropic) grid spacing for target size transfer 
 
double & max_element_size()
Max. element size during refinement. 
 
unsigned first_vertex_id() const
First vertex id. 
 
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...
 
Vector< TetMeshFacetedSurface * > Internal_surface_pt
Internal boundaries. 
 
double Element_volume
Uniform element volume. 
 
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...
 
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::pair< unsigned, unsigned > Vertex_pair
The vertices (sorted by vertex ids) 
 
Class to collate parameters for Gmsh mesh generation. 
 
void write_geo_file(const bool &use_mesh_grading_from_file)
Write geo file for gmsh. 
 
Helper class to keep track of edges in tet mesh generation. 
 
GmshParameters * Gmsh_parameters_pt
Parameters. 
 
std::string & gmsh_onscreen_output_file_name()
Output filename for gmsh on-screen output. 
 
double & max_permitted_edge_ratio()
Max. permitted edge ratio. 
 
void initialise_adaptation_data()
Helper function to initialise data associated with adaptation. 
 
std::string & geo_and_msh_file_stem()
Stem for geo and msh files (input/output to command-line gmsh invocation) 
 
Vector< TetMeshFacetedSurface * > & internal_surface_pt()
Internal boundaries. 
 
double Max_permitted_edge_ratio
Max edge ratio before remesh gets triggered. 
 
std::string Gmsh_command_line_invocation
Gmsh command line invocation string. 
 
std::string Geo_and_msh_file_stem
Stem for geo and msh files (input/output to command-line gmsh invocation) 
 
double Dx_for_target_size_transfer
(Isotropic) grid spacing for target size transfer 
 
void refine_uniformly(DocInfo &doc_info)
Unrefine uniformly. 
 
std::string & gmsh_command_line_invocation()
String to be issued via system command to activate gmsh.