30 #ifndef OOMPH_XDA_TET_MESH_TEMPLATE_CC    31 #define OOMPH_XDA_TET_MESH_TEMPLATE_CC    34 #include "../generic/Telements.h"    51  template <
class ELEMENT>
    53                                  TimeStepper* time_stepper_pt)
    56   MeshChecker::assert_geometric_element<TElementGeometricBase,ELEMENT>(3);
    59   std::ifstream infile(xda_file_name.c_str(),std::ios_base::in);
    62   unsigned n_bound_face;
    64   if (!infile.is_open())
    66     std::ostringstream error_stream;
    68      << 
"Failed to open " << xda_file_name 
    70     throw OomphLibError(error_stream.str(),
    71                         OOMPH_CURRENT_FUNCTION,
    72                         OOMPH_EXCEPTION_LOCATION);
    79   infile.getline(dummy, 100);
    85   infile.getline(dummy, 100);
    91   infile.getline(dummy, 100);
    94   infile.getline(dummy, 100);
   101   while (dummy[0]!= 
'T') {infile.getline(dummy, 100);}
   104   Node_pt.resize(n_node);
   105   Element_pt.resize(n_element);
   109   std::getline(infile,line);
   110   std::istringstream ostr(line);
   111   std::istream_iterator<std::string> it(ostr);
   112   std::istream_iterator<std::string> end;
   113   unsigned nnod_el = 0;
   114   Vector<unsigned> first_node;
   117     first_node.push_back(atoi((*it).c_str()));
   125     std::ostringstream error_stream;
   127      << 
"XdaTetMesh can currently only be built with quadratic tets "    128      << 
"with 10 nodes. The specified mesh file has " << nnod_el 
   129      << 
"nodes per element.\n";
   130     throw OomphLibError(error_stream.str(),
   131                         OOMPH_CURRENT_FUNCTION,
   132                         OOMPH_EXCEPTION_LOCATION);
   136   Vector<unsigned> global_node(n_element*nnod_el);
   142   for(
unsigned j=0;j<nnod_el;j++)
   144     global_node[k]=first_node[k];
   149   for(
unsigned i=1;i<n_element;i++)
   151     for(
unsigned j=0;j<nnod_el;j++)
   153       infile >> global_node[k];
   156     infile.getline(dummy, 100);
   161   Vector<double> x_node(n_node);
   162   Vector<double> y_node(n_node);
   163   Vector<double> z_node(n_node);
   166   for(
unsigned i=0;i<n_node;i++)
   175   unsigned element_nmbr;
   178   unsigned max_bound=0;
   181   Boundary_id.resize(n_bound_face+1);
   185   Vector<std::set<unsigned> > boundary_id(n_node);
   186   for(
unsigned i=0;i<n_bound_face;i++)
   189     infile>> element_nmbr ;
   198     unsigned oomph_lib_bound_id=bound_id-1;
   199     oomph_lib_bound_id=count;
   200     Boundary_id[bound_id].push_back(count);
   206     if (oomph_lib_bound_id>max_bound) max_bound=oomph_lib_bound_id;
   213     Vector<unsigned> side_node(6);
   217       side_node[0]=global_node[nnod_el*element_nmbr+1];
   218       side_node[1]=global_node[nnod_el*element_nmbr];
   219       side_node[2]=global_node[nnod_el*element_nmbr+2];
   220       side_node[3]=global_node[nnod_el*element_nmbr+4];
   221       side_node[4]=global_node[nnod_el*element_nmbr+6];
   222       side_node[5]=global_node[nnod_el*element_nmbr+5];
   226       side_node[0]=global_node[nnod_el*element_nmbr];
   227       side_node[1]=global_node[nnod_el*element_nmbr+1];
   228       side_node[2]=global_node[nnod_el*element_nmbr+3];
   229       side_node[3]=global_node[nnod_el*element_nmbr+4];
   230       side_node[4]=global_node[nnod_el*element_nmbr+8];
   231       side_node[5]=global_node[nnod_el*element_nmbr+7];
   235       side_node[0]=global_node[nnod_el*element_nmbr+1];
   236       side_node[1]=global_node[nnod_el*element_nmbr+2];
   237       side_node[2]=global_node[nnod_el*element_nmbr+3];
   238       side_node[3]=global_node[nnod_el*element_nmbr+5];
   239       side_node[4]=global_node[nnod_el*element_nmbr+9];
   240       side_node[5]=global_node[nnod_el*element_nmbr+8];
   244       side_node[0]=global_node[nnod_el*element_nmbr+2];
   245       side_node[1]=global_node[nnod_el*element_nmbr];
   246       side_node[2]=global_node[nnod_el*element_nmbr+3];
   247       side_node[3]=global_node[nnod_el*element_nmbr+6];
   248       side_node[4]=global_node[nnod_el*element_nmbr+7];
   249       side_node[5]=global_node[nnod_el*element_nmbr+9];
   254        "Unexcpected side number in your '.xda' input file\n",
   255        OOMPH_CURRENT_FUNCTION,
   256        OOMPH_EXCEPTION_LOCATION);
   260     for (
unsigned j=0;j<6;j++)
   262       boundary_id[side_node[j]].insert(oomph_lib_bound_id);
   267   set_nboundary(max_bound+1);
   270   std::vector<bool> done(n_node,
false);
   272   Vector<unsigned> translate(n_node);
   285   unsigned node_count=0;
   286   for(
unsigned e=0;e<n_element;e++)
   288     Element_pt[e]=
new ELEMENT;
   291     for(
unsigned j=0;j<nnod_el;j++)
   293       unsigned j_global=global_node[node_count];
   294       if(done[j_global]==
false) 
   296         if (boundary_id[j_global].size()==0)
   299            finite_element_pt(e)->construct_node(translate[j],time_stepper_pt);
   304            finite_element_pt(e)->construct_boundary_node(translate[j],
   306           for (std::set<unsigned>::iterator it=boundary_id[j_global].begin();
   307                it!=boundary_id[j_global].end();it++)
   309             add_boundary_node(*it,Node_pt[j_global]);
   313         Node_pt[j_global]->x(0)=x_node[j_global];
   314         Node_pt[j_global]->x(1)=y_node[j_global];
   315         Node_pt[j_global]->x(2)=z_node[j_global];
   319         finite_element_pt(e)->node_pt(translate[j]) = Node_pt[j_global];
   326   setup_boundary_element_info();
   330   unsigned nb=nboundary();
   331   for (
unsigned b=0;b<nb;b++)
   333     bool switch_normal=
false;
   334     setup_boundary_coordinates(b,switch_normal); 
   351  template <
class ELEMENT>
   353                                                       const bool& switch_normal,
   354                                                       std::ofstream& outfile)
   358   Vector<FiniteElement*> face_el_pt;
   361   std::map<Node*,Vector<double> > backup_position;
   364   unsigned nel=this->nboundary_element(b);
   368     for(
unsigned e=0;e<nel;e++)
   371       FiniteElement* bulk_elem_pt = this->boundary_element_pt(b,e);
   374       int face_index = this->face_index_at_boundary(b,e);
   377       DummyFaceElement<ELEMENT>* el_pt= 
   378        new DummyFaceElement<ELEMENT>(bulk_elem_pt,face_index);
   379       face_el_pt.push_back(el_pt);   
   382       Vector<double> pos(3);
   383       for (
unsigned j=3;j<6;j++)
   385         if (backup_position[el_pt->node_pt(j)].size()==0)
   387           el_pt->node_pt(j)->position(pos);
   388           backup_position[el_pt->node_pt(j)]=pos;
   393       for (
unsigned i=0;i<3;i++)
   396         el_pt->node_pt(3)->x(i)=
   397          0.5*(el_pt->node_pt(0)->x(i)+el_pt->node_pt(1)->x(i));
   400         el_pt->node_pt(4)->x(i)=
   401          0.5*(el_pt->node_pt(1)->x(i)+el_pt->node_pt(2)->x(i));
   404         el_pt->node_pt(5)->x(i)=
   405          0.5*(el_pt->node_pt(2)->x(i)+el_pt->node_pt(0)->x(i));
   410       if (outfile.is_open()) 
   412         face_el_pt[face_el_pt.size()-1]->output(outfile); 
   418     Node* lower_left_node_pt=this->boundary_node_pt(b,0);
   419     Node* upper_right_node_pt=this->boundary_node_pt(b,0);
   422     unsigned nnod=this->nboundary_node(b);
   423     for (
unsigned j=0;j<nnod;j++)
   427       Node* nod_pt=this->boundary_node_pt(b,j);
   430       if (nod_pt->x(2)<lower_left_node_pt->x(2))
   432         lower_left_node_pt=nod_pt;
   435       else if (nod_pt->x(2)==lower_left_node_pt->x(2))
   438         if (nod_pt->x(1)<lower_left_node_pt->x(1))
   440           lower_left_node_pt=nod_pt;
   443         else if (nod_pt->x(1)==lower_left_node_pt->x(1))
   447           if (nod_pt->x(0)<lower_left_node_pt->x(0))
   449             lower_left_node_pt=nod_pt;
   456       if (nod_pt->x(2)>upper_right_node_pt->x(2))
   458         upper_right_node_pt=nod_pt;
   461       else if (nod_pt->x(2)==upper_right_node_pt->x(2))
   464         if (nod_pt->x(1)>upper_right_node_pt->x(1))
   466           upper_right_node_pt=nod_pt;
   469         else if (nod_pt->x(1)==upper_right_node_pt->x(1))
   473           if (nod_pt->x(0)>upper_right_node_pt->x(0))
   475             upper_right_node_pt=nod_pt;
   482     Vector<double> zeta(2);
   485     Vector<double> b0(3);
   486     b0[0]=upper_right_node_pt->x(0)-lower_left_node_pt->x(0);
   487     b0[1]=upper_right_node_pt->x(1)-lower_left_node_pt->x(1);
   488     b0[2]=upper_right_node_pt->x(2)-lower_left_node_pt->x(2);
   491     double inv_length=1.0/sqrt(b0[0]*b0[0]+b0[1]*b0[1]+b0[2]*b0[2]);
   497     Vector<double> normal(3);
   498     Vector<double> s(2,0.0);
   499     dynamic_cast<DummyFaceElement<ELEMENT>*
>(face_el_pt[0])-> 
   500      outer_unit_normal(s,normal);
   504       normal[0]=-normal[0];
   505       normal[1]=-normal[1];
   506       normal[2]=-normal[2];
   512     for(
unsigned e=0;e<nel;e++)
   515       Vector<double> my_normal(3);
   516       dynamic_cast<DummyFaceElement<ELEMENT>*
>(face_el_pt[0])->
   517        outer_unit_normal(s,my_normal);
   521        normal[0]*my_normal[0]+
   522        normal[1]*my_normal[1]+
   523        normal[2]*my_normal[2];
   526       if (switch_normal) error+=1.0;
   528       if (error>Tolerance_for_boundary_finding)
   530         std::ostringstream error_message;
   532          << 
"Error in alingment of normals (dot product-1) "    533          << error << 
" for element " << e << std::endl
   534          << 
"exceeds tolerance specified by the static member data\n"   535          << 
"TetMeshBase::Tolerance_for_boundary_finding = "    536          << Tolerance_for_boundary_finding << std::endl
   537          << 
"This usually means that the boundary is not planar.\n\n"   538          << 
"You can suppress this error message by recompiling \n"   539          << 
"recompiling without PARANOID or by changing the tolerance.\n";
   540         throw OomphLibError(error_message.str(),
   541                             OOMPH_CURRENT_FUNCTION,
   542                             OOMPH_EXCEPTION_LOCATION);
   548     Vector<double> b1(3);
   549     b1[0]=b0[1]*normal[2]-b0[2]*normal[1];
   550     b1[1]=b0[2]*normal[0]-b0[0]*normal[2];
   551     b1[2]=b0[0]*normal[1]-b0[1]*normal[0];
   554     for (
unsigned j=0;j<nnod;j++)
   557       Node* nod_pt=this->boundary_node_pt(b,j);
   560       Vector<double> delta(3);
   561       delta[0]=nod_pt->x(0)-lower_left_node_pt->x(0);
   562       delta[1]=nod_pt->x(1)-lower_left_node_pt->x(1);
   563       delta[2]=nod_pt->x(2)-lower_left_node_pt->x(2);
   566       zeta[0]=delta[0]*b0[0]+delta[1]*b0[1]+delta[2]*b0[2];
   567       zeta[1]=delta[0]*b1[0]+delta[1]*b1[1]+delta[2]*b1[2];
   573        pow(lower_left_node_pt->x(0)+zeta[0]*b0[0]+zeta[1]*b1[0]-
   575        pow(lower_left_node_pt->x(1)+zeta[0]*b0[1]+zeta[1]*b1[1]-
   577        pow(lower_left_node_pt->x(2)+zeta[0]*b0[2]+zeta[1]*b1[2]-
   580       if (sqrt(error)>Tolerance_for_boundary_finding)
   582         std::ostringstream error_message;
   584          << 
"Error in setup of boundary coordinate "    585          << sqrt(error) << std::endl
   586          << 
"exceeds tolerance specified by the static member data\n"   587          << 
"TetMeshBase::Tolerance_for_boundary_finding = "    588          << Tolerance_for_boundary_finding << std::endl
   589          << 
"This usually means that the boundary is not planar.\n\n"   590          << 
"You can suppress this error message by recompiling \n"   591          << 
"recompiling without PARANOID or by changing the tolerance.\n";
   592         throw OomphLibError(error_message.str(),
   593                             OOMPH_CURRENT_FUNCTION,
   594                             OOMPH_EXCEPTION_LOCATION);
   599       nod_pt->set_coordinates_on_boundary(b,zeta);
   605   Boundary_coordinate_exists[b]=
true;
   608   unsigned n=face_el_pt.size();
   609   for (
unsigned e=0;e<n;e++)
   611     delete face_el_pt[e];
   616   for (std::map<Node*,Vector<double> >::iterator it=backup_position.begin();
   617        it!=backup_position.end();it++)
   619     Node* nod_pt=(*it).first;
   620     Vector<double> pos((*it).second);
   621     for (
unsigned i=0;i<3;i++)
 void setup_boundary_coordinates(const unsigned &b, const bool &switch_normal)
Setup boundary coordinate on boundary b while is temporarily flattened to simplex faces...
 
XdaTetMesh(const std::string xda_file_name, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor: Pass name of xda file. Note that all boundary elements get their own ID – this is requi...