xda_to_poly_fsi.cc File Reference
#include <iostream>
#include <sstream>
#include <string>
#include <iterator>
#include "generic.h"

Functions

int main ()
 

Function Documentation

◆ main()

int main ( )
93 {
94 
95  // Prompt input from user
96  //-----------------------
97  std::cout << "Please enter the file name without the file extension '.xda': ";
98  std::string input_filename;
99  std::cin >> input_filename;
100 
101 
102  std::cout << "\n\nEnter the (uniform) wall thickness ";
103  double wall_thickness;
104  std::cin >> wall_thickness;
105 
106 
107  std::cout << "\n\nDo you want to create a separate ID for each planar facet\n"
108  << "on the fluid-structure interaction boundary?"
109  << "\n" <<"Enter y or n: ";
110  char multi_boundary_ids_marker;
111  std::cin >> multi_boundary_ids_marker;
112  bool do_multi_boundary_ids=true;
113  if(multi_boundary_ids_marker=='n') do_multi_boundary_ids=false;
114 
115 
116  // Define filenames
117  //-----------------
118 
119  // Build filename for xda input file
120  std::string xda_file_name;
121  xda_file_name=input_filename+".xda";
122 
123  std::string fluid_surface_file;
124  fluid_surface_file="fluid_"+input_filename+".poly";
125 
126  std::string solid_surface_file;
127  solid_surface_file="solid_"+input_filename+".poly";
128 
129 
130  // Open and process xda input file
131  //--------------------------------
132  std::ifstream infile(xda_file_name.c_str(),std::ios_base::in);
133  unsigned n_node;
134  unsigned n_element;
135  unsigned nbound_cond;
136 
137  // Dummy storage to jump lines
138  char dummy[100];
139 
140  // Ignore file format
141  infile.getline(dummy, 100);
142 
143  // Get number of elements
144  infile>>n_element;
145 
146  // Ignore rest of line
147  infile.getline(dummy, 100);
148 
149  // Get number of nodes
150  infile>>n_node;
151 
152  // Ignore rest of line
153  infile.getline(dummy, 100);
154 
155  // Ignore sum of element weights (whatever that is...)
156  infile.getline(dummy, 100);
157 
158  // Get number of boundaries = number of boundary conditions
159  infile>>nbound_cond;
160 
161  // Keep reading until "Title String"
162  while (dummy[0]!= 'T') {infile.getline(dummy, 100);}
163 
164 
165  // Read first line with node labels and count them
166  string line;
167  getline(infile,line);
168  istringstream ostr(line);
169  istream_iterator<string> it(ostr);
170  istream_iterator<string> end;
171  unsigned nnod_el = 0;
172  Vector<unsigned> first_node;
173  while (it != end)
174  {
175  first_node.push_back(atoi((*it).c_str()));
176  it++;
177  nnod_el++;
178  }
179  oomph_info << "Number of nodes per element: " << nnod_el << std::endl;
180 
181  // Storage for the global node numbers listed element-by-element
182  Vector<unsigned> global_node(n_element*nnod_el);
183 
184  // Read in nodes
185  unsigned k=0;
186 
187  // Copy across first nodes
188  cout << "First nodes: " << std::endl;
189  for(unsigned j=0;j<nnod_el;j++)
190  {
191  global_node[k]=first_node[k];
192  cout << first_node[k] << " ";
193  k++;
194  }
195  cout << std::endl;
196 
197  // Read the other ones
198  for(unsigned i=1;i<n_element;i++)
199  {
200  for(unsigned j=0;j<nnod_el;j++)
201  {
202  infile >> global_node[k];
203  k++;
204  }
205  infile.getline(dummy, 100);
206  }
207 
208 
209  // Create storage for coordinates
210  Vector<double> x_node(n_node);
211  Vector<double> y_node(n_node);
212  Vector<double> z_node(n_node);
213 
214  // Get nodal coordinates
215  for(unsigned i=0;i<n_node;i++)
216  {
217  infile>>x_node[i];
218  infile>>y_node[i];
219  infile>>z_node[i];
220  }
221 
222  // Vector of bools, will tell us if we already visited a node
223  std::vector<bool> done_for_fluid(n_node,false);
224  std::vector<bool> done_for_solid(n_node,false);
225 
226  // A map, indexed by the old node number, gives the new node number
227  // in the fluid poly file
228  std::map<unsigned,unsigned> fluid_node_nmbr;
229 
230  // Each node in the fluid surface creates two nodes in the solid
231  // surfaces, one in the inner surface and the other in the outer surface.
232  // These maps, indexed by the old node number, give the new node number
233  // in the solid poly file.
234  std::map<unsigned,unsigned> solid_inner_node_nmbr;
235  std::map<unsigned,unsigned> solid_outer_node_nmbr;
236 
237  // nfluid_face[i] will store the number of facets on boundary i+1.
238  // The fluid mesh has four distinct boundaries.
239  Vector<unsigned> nfluid_face(4);
240 
241  // nsolid_linking_faces[i] will store the number of facets on the solid
242  // boundaries that connect the inner and outer solid surface.
243  // With the enumeration chosen, nsolid_linking_faces[i] corresponds
244  // to boundary i+2. (We don't store the number of facets in boundaries
245  // 1 and 5 because they are the same as the number of fluid facets
246  // on boundary 1.
247  Vector<unsigned> nsolid_linking_faces(3);
248 
249  // Initialise number of nodes in the solid surface
250  unsigned n_solid_node=0;
251 
252  // Initalise number of nodes in the fluid surface
253  unsigned n_fluid_node=0;
254 
255  // Create storage for outer solid nodes coordinates. Indexed by the old
256  // node number, these maps returns the nodes coordinates.
257  std::map<unsigned, double> x_outer_node;
258  std::map<unsigned, double> y_outer_node;
259  std::map<unsigned, double> z_outer_node;
260  std::map<unsigned,Vector<double> > normal_for_outer_wall;
261 
262 
263  // Create storage for fluid faces informations :
264  // fluid_faces[i][j] will store a vector containing the three node numbers
265  // of the j-th face in the (i+1)-th boundary
267  fluid_faces(4, Vector<Vector<unsigned> >(nbound_cond,Vector<unsigned>(3) ));
268 
269  // Create storage for solid facets:
270  // As the solid inner and outer facets come from the fluid surface,
271  // we only need to store solid facet information in boundaries 2, 3 and 4.
272  // solid_faces[i][j] will store a vector containing the three node numbers
273  // of the j-th face in the (i+2)-th boundary
275  solid_linking_faces(3, Vector<Vector<unsigned> >(nbound_cond,
276  Vector<unsigned>(3) ));
277 
278 
279  // Storage for node numbers of nodes that make up fluid fsi boundary
280  // in quadratic (six node triangle) representation)
281  std::set<unsigned> quadratic_fsi_boundary_nodes;
282  Vector<Vector<unsigned> > quadratic_fsi_boundary_face_element_nodes;
283 
284 
285  // Get boundary enumeration
286  //--------------------------
287  unsigned element_nmbr;
288  unsigned side_nmbr;
289  int bound_id;
290  for(unsigned i=0;i<nbound_cond;i++)
291  {
292 
293  // Number of the element
294  infile>> element_nmbr ;
295 
296  // Which side/face on the tet are we dealing with (xda enumeratation)?
297  infile>> side_nmbr ;
298 
299  // What's the boundary ID?
300  infile>> bound_id ;
301 
302  // Sanity check
303  if(bound_id!=1 && bound_id!=2 && bound_id!=3 && bound_id!=4 )
304  {
305  std::ostringstream error_stream;
306  error_stream << "bound_id=" << bound_id
307  << ". This function only takes xda type meshes with"
308  <<" one inflow (boundary 2) and two outflows (boundaries 3"
309  <<" and 4); the FSI interface must have the id 1. Your"
310  <<" input file contains a boundary with id : "
311  << bound_id <<".\n"
312  <<"Don't panic, there are only few things to change"
313  <<" in this well commented code, good luck ;) \n";
314  throw OomphLibError(
315  error_stream.str(),
318  }
319 
320  // Identify the "side nodes" (i.e. the nodes on the faces of
321  // the bulk tet) according to the
322  // conventions in '.xda' mesh files so that orientation of the
323  // faces is always the same (required for computation of
324  // outer unit normals
325  Vector<unsigned> side_node(6);
326 
327  switch(side_nmbr)
328  {
329  case 0:
330  side_node[0]=global_node[nnod_el*element_nmbr+1];
331  side_node[1]=global_node[nnod_el*element_nmbr];
332  side_node[2]=global_node[nnod_el*element_nmbr+2];
333  side_node[3]=global_node[nnod_el*element_nmbr+4];
334  side_node[4]=global_node[nnod_el*element_nmbr+6];
335  side_node[5]=global_node[nnod_el*element_nmbr+5];
336  break;
337 
338  case 1:
339  side_node[0]=global_node[nnod_el*element_nmbr];
340  side_node[1]=global_node[nnod_el*element_nmbr+1];
341  side_node[2]=global_node[nnod_el*element_nmbr+3];
342  side_node[3]=global_node[nnod_el*element_nmbr+4];
343  side_node[4]=global_node[nnod_el*element_nmbr+8];
344  side_node[5]=global_node[nnod_el*element_nmbr+7];
345  break;
346 
347  case 2:
348  side_node[0]=global_node[nnod_el*element_nmbr+1];
349  side_node[1]=global_node[nnod_el*element_nmbr+2];
350  side_node[2]=global_node[nnod_el*element_nmbr+3];
351  side_node[3]=global_node[nnod_el*element_nmbr+5];
352  side_node[4]=global_node[nnod_el*element_nmbr+9];
353  side_node[5]=global_node[nnod_el*element_nmbr+8];
354  break;
355 
356  case 3:
357  side_node[0]=global_node[nnod_el*element_nmbr+2];
358  side_node[1]=global_node[nnod_el*element_nmbr];
359  side_node[2]=global_node[nnod_el*element_nmbr+3];
360  side_node[3]=global_node[nnod_el*element_nmbr+6];
361  side_node[4]=global_node[nnod_el*element_nmbr+7];
362  side_node[5]=global_node[nnod_el*element_nmbr+9];
363  break;
364 
365  default :
366  throw OomphLibError(
367  "Unexcpected side number in your '.xda' input file\n",
370  }
371 
372 
373  // Are we on the FSI interface?
374  //-----------------------------
375  if(bound_id==1)
376  {
377  // Create storage for the normal vector to the face
378  Vector<double> normal(3,0.0);
379 
380  // Identify quadratic nodes
381  quadratic_fsi_boundary_nodes.insert(side_node[0]);
382  quadratic_fsi_boundary_nodes.insert(side_node[1]);
383  quadratic_fsi_boundary_nodes.insert(side_node[2]);
384  quadratic_fsi_boundary_nodes.insert(side_node[3]);
385  quadratic_fsi_boundary_nodes.insert(side_node[4]);
386  quadratic_fsi_boundary_nodes.insert(side_node[5]);
387 
388  // Identify quadratic facet
389  Vector<unsigned> quadratic_nodes(6);
390  quadratic_nodes[0]=side_node[0];
391  quadratic_nodes[1]=side_node[1];
392  quadratic_nodes[2]=side_node[2];
393  quadratic_nodes[3]=side_node[3];
394  quadratic_nodes[4]=side_node[4];
395  quadratic_nodes[5]=side_node[5];
396  quadratic_fsi_boundary_face_element_nodes.push_back(quadratic_nodes);
397 
398  // Get the vertex nodes' coordinates
399  double x1=x_node[side_node[0] ];
400  double x2=x_node[side_node[1] ];
401  double x3=x_node[side_node[2] ];
402 
403  double y1=y_node[side_node[0] ];
404  double y2=y_node[side_node[1] ];
405  double y3=y_node[side_node[2] ];
406 
407  double z1=z_node[side_node[0] ];
408  double z2=z_node[side_node[1] ];
409  double z3=z_node[side_node[2] ];
410 
411  // Compute the outer normal vector
412  normal[0] =(y2-y1)*(z3-z1) - (z2-z1)*(y3-y1);
413  normal[1] =(z2-z1)*(x3-x1) - (x2-x1)*(z3-z1);
414  normal[2] =(x2-x1)*(y3-y1) - (y2-y1)*(x3-x1);
415 
416  // Normalise
417  double length= sqrt((normal[0])*(normal[0]) +
418  (normal[1])*(normal[1]) +
419  (normal[2])*(normal[2]));
420  for(unsigned idim=0; idim<3; idim++)
421  {
422  normal[idim]/=length;
423  }
424 
425  // Loop over the facet's nodes vertex/simplex nodes
426  for(unsigned ii=0; ii<6; ii++)
427  {
428  // get the node number
429  unsigned inod=side_node[ii];
430 
431  if (ii<3)
432  {
433  // Have we already dealt with this node in its incarnation as a
434  // fluid node?
435  if(!done_for_fluid[inod])
436  {
437  done_for_fluid[inod]=true;
438 
439  // This node is a new fluid node
440  n_fluid_node++;
441  }
442  }
443 
444  // Have we already dealt with this node in its incarnation as a
445  // solid node?
446  if(!done_for_solid[inod])
447  {
448  done_for_solid[inod]=true;
449  normal_for_outer_wall[inod].resize(3);
450  if (ii<3)
451  {
452  // This node is a solid node on boundary 1 and this node
453  // creates another one on boundary 5
454  n_solid_node+=2;
455  }
456  }
457  // Compute the coordinates of the new node (on boundary 5)
458  x_outer_node[inod]= x_node[inod];//+ wall_thickness* normal[0];
459  y_outer_node[inod]= y_node[inod];//+ wall_thickness* normal[1];
460  z_outer_node[inod]= z_node[inod];//+ wall_thickness* normal[2];
461 
462  normal_for_outer_wall[inod][0]+=normal[0];
463  normal_for_outer_wall[inod][1]+=normal[1];
464  normal_for_outer_wall[inod][2]+=normal[2];
465  }
466 
467  // We've just created a new fluid facet on boundary 1
468  nfluid_face[0]++;
469 
470  // Store the face node numbers
471  for(unsigned ii=0;ii<3; ii++)
472  {
473  fluid_faces[0][nfluid_face[0]-1][ii]=side_node[ii];
474  }
475  }
476 
477  // We're on a non-FSI boundary
478  //----------------------------
479  else
480  {
481  // loop over the facet's vertex/simplex nodes
482  for(unsigned ii=0; ii<3; ii++)
483  {
484  // get the node number
485  unsigned inod=side_node[ii];
486 
487  // Have we dealt with this fluid node?
488  if(!done_for_fluid[inod])
489  {
490  done_for_fluid[inod]=true;
491 
492  // this node is a new fluid node
493  n_fluid_node++;
494  }
495  }
496  // We've just created a new facet on boundary bound_id
497  nfluid_face[bound_id-1]++;
498 
499  // Store the face node numbers
500  for(unsigned ii=0;ii<3; ii++)
501  {
502  fluid_faces[bound_id-1][nfluid_face[bound_id-1]-1][ii]=side_node[ii];
503  }
504  }
505  }
506 
507  // Done reading xda file
508  infile.close();
509 
510 
511  // Now create storage for fluid facets on the four boundaries of the
512  // fluid mesh
513  for(unsigned i=0; i<4; i++)
514  {
515  fluid_faces[i].resize(nfluid_face[i]);
516  }
517 
518 
519  // Re-normalise unit normals to wall
520  for (std::map<unsigned,Vector<double> >::iterator it=
521  normal_for_outer_wall.begin();
522  it!=normal_for_outer_wall.end();it++)
523  {
524  double sum=0.0;
525  for (unsigned i=0;i<3;i++)
526  {
527  sum+=pow((*it).second[i],2);
528  }
529  for (unsigned i=0;i<3;i++)
530  {
531  (*it).second[i]/=sqrt(sum);
532  }
533  }
534 
535  // Output quadratic representation of fsi boundary (six node triangles)
536  //---------------------------------------------------------------------
537  unsigned nquadratic_nodes=quadratic_fsi_boundary_nodes.size();
538 
540  filename=input_filename+"_quadratic_fsi_boundary.dat";
541  std::ofstream quadratic_fsi_boundary_file(filename.c_str());
542  quadratic_fsi_boundary_file << nquadratic_nodes
543  << " # number of quadratic FSI nodes\n";
544  quadratic_fsi_boundary_file << quadratic_fsi_boundary_face_element_nodes.size()
545  << " # number of FSI facets\n";
546  for (std::set<unsigned>::iterator it=quadratic_fsi_boundary_nodes.begin();
547  it!=quadratic_fsi_boundary_nodes.end();it++)
548  {
549  quadratic_fsi_boundary_file << x_node[*it] << " "
550  << y_node[*it] << " "
551  << z_node[*it] << " "
552  << *it << std::endl;
553  }
554 
555 
556  for (Vector<Vector<unsigned> >::iterator it=
557  quadratic_fsi_boundary_face_element_nodes.begin();
558  it!=quadratic_fsi_boundary_face_element_nodes.end();it++)
559  {
560  quadratic_fsi_boundary_file << (*it)[0] << " "
561  << (*it)[1] << " "
562  << (*it)[2] << " "
563  << (*it)[3] << " "
564  << (*it)[4] << " "
565  << (*it)[5] << " " << std::endl;
566  }
567  quadratic_fsi_boundary_file.close();
568 
569 
570 
571  // Output quadratic representation of outer solid boundary (six node triangles)
572  //-----------------------------------------------------------------------------
573  filename=input_filename+"_quadratic_outer_solid_boundary.dat";
574  std::ofstream quadratic_outer_solid_boundary_file(filename.c_str());
575  quadratic_outer_solid_boundary_file
576  << nquadratic_nodes
577  << " # number of quadratic nodes on outer solid boundary\n";
578  quadratic_outer_solid_boundary_file
579  << quadratic_fsi_boundary_face_element_nodes.size()
580  << " # number of facets on outer solid boundary\n";
581  for (std::set<unsigned>::iterator it=
582  quadratic_fsi_boundary_nodes.begin();
583  it!=quadratic_fsi_boundary_nodes.end();it++)
584  {
585  quadratic_outer_solid_boundary_file
586  << x_outer_node[*it]+wall_thickness*normal_for_outer_wall[*it][0] << " "
587  << y_outer_node[*it]+wall_thickness*normal_for_outer_wall[*it][1] << " "
588  << z_outer_node[*it]+wall_thickness*normal_for_outer_wall[*it][2] << " "
589  << *it << std::endl;
590  }
591 
592 
593  for (Vector<Vector<unsigned> >::iterator it=
594  quadratic_fsi_boundary_face_element_nodes.begin();
595  it!=quadratic_fsi_boundary_face_element_nodes.end();it++)
596  {
597  quadratic_outer_solid_boundary_file << (*it)[0] << " "
598  << (*it)[1] << " "
599  << (*it)[2] << " "
600  << (*it)[3] << " "
601  << (*it)[4] << " "
602  << (*it)[5] << " " << std::endl;
603  }
604  quadratic_outer_solid_boundary_file.close();
605 
606 
607 
608 
609  // Start poly files, describing fluid and solid domains via
610  //---------------------------------------------------------
611  // planar facets
612  //--------------
613  std::ofstream fluid_output_stream(fluid_surface_file.c_str(),std::ios::out);
614  fluid_output_stream << "# This poly file was created from a"
615  <<" VMTK mesh." << '\n'
616  << "# VMTK assigns for the front inflow "
617  <<"face the boundary id 2, the left " << '\n'
618  <<"# bifurcation face the id 3, the right"
619  <<" bifurcation face the id 4 and for the other"
620  <<" boundaries (FSI interface) the id 1 " << '\n'
621  << "# Oomph-lib's meshes need distinct ids "
622  <<"for each planar facet, so we assign new boundary ids."
623  << '\n'
624  <<"# The relation between old and new ids is listed"
625  <<" at the end of this file.\n";
626 
627  std::ofstream solid_output_stream(solid_surface_file.c_str(),std::ios::out);
628  solid_output_stream << "# This poly file was created from the fluid vmtk "
629  << " mesh assuming constant wall thickness.\n"
630  << "# Oomph-lib's meshes need distinct "
631  <<"ids for each planar facet so we assign new \n"
632  <<"# boundary ids. The relation between old and new "
633  << " ids is listed at the end of this file.\n";
634 
635 
636  // Write the node list for the fluid boundaries
637  //---------------------------------------------
638  fluid_output_stream << '\n' << "# Node list : " << '\n';
639 
640  // Number of nodes, dimension =3 , no attributes, with boundary markers
641  fluid_output_stream << n_fluid_node << ' ' << 3 << ' ' << 0
642  << ' ' << 1 << '\n'<< '\n';
643 
644  // Has a specific node been done yet?
645  std::vector<bool> done_fluid_node(n_node,false);
646  unsigned counter=0;
647 
648  // Loop over the boundaries in the fluid mesh
649  for(unsigned i=0; i<4; i++)
650  {
651  // How many facets are on boundary 'i+1' ?
652  unsigned nface=nfluid_face[i];
653 
654  // Loop over the facets
655  for(unsigned iface=0; iface<nface; iface++)
656  {
657  // Get pointer to the Vector storing the three vertex nodes defining
658  // the facet
659  Vector<unsigned>* face_node=&(fluid_faces[i][iface]);
660 
661  // Loop over the facet's nodes
662  for(unsigned ii=0; ii<3; ii++)
663  {
664  // Get the node number (in the old numbering scheme)
665  unsigned inod=(*face_node)[ii];
666 
667  // Done yet?
668  if(!done_fluid_node[inod])
669  {
670  done_fluid_node[inod]=true;
671  counter++;
672 
673  // Assign the new node number on the fluid surface
674  fluid_node_nmbr[inod]=counter;
675 
676  // Write the node coordinates (boundary marker =0 )
677  fluid_output_stream << counter << ' '
678  << x_node[inod] << ' '
679  << y_node[inod] << ' '
680  << z_node[inod] << ' '
681  << 0 << '\n';
682  }
683  }
684  }
685  }
686 
687 
688  // Write the node list for the solid boundaries
689  //---------------------------------------------
690  solid_output_stream << '\n' << "# Node list : " << '\n';
691 
692  // Number of nodes, dimension =3 , no attributes, with boundary markers
693  solid_output_stream << n_solid_node << ' ' << 3 << ' ' << 0
694  << ' ' << 1 << '\n'<< '\n';
695 
696  // Has a specific node been done yet?
697  std::vector<bool> done_solid_node(n_node,false);
698  counter=0;
699 
700 
701  // Do FSI and outer surfaces
702  //--------------------------
703 
704  // How many facets are on boundary 0 (FSI surface)
705  unsigned nface=nfluid_face[0];
706 
707  // Loop over the facets
708  for(unsigned iface=0; iface<nface; iface++)
709  {
710  // Get pointer to the Vector storing the three nodes
711  Vector<unsigned>* face_node=&(fluid_faces[0][iface]);
712 
713  // Loop over the facet's nodes
714  for(unsigned ii=0; ii<3; ii++)
715  {
716  // get the node number (in the old numbering scheme)
717  unsigned inod=(*face_node)[ii];
718 
719  // Done yet?
720  if(!done_solid_node[inod])
721  {
722  done_solid_node[inod]=true;
723  counter++;
724 
725  // Assign the new node number on the solid surface
726  solid_inner_node_nmbr[inod]=counter;
727 
728  solid_output_stream << counter << ' '
729  << x_node[inod] << ' '
730  << y_node[inod] << ' '
731  << z_node[inod] << ' '
732  << 0 << '\n';
733 
734  // Store the new nodes on boundary 5 (outer surface)
735  counter++;
736 
737  // Assign the new node number on the solid surface
738  solid_outer_node_nmbr[inod]=counter;
739 
740  solid_output_stream
741  << counter << " "
742  << x_outer_node[inod]+wall_thickness*normal_for_outer_wall[inod][0]
743  << " "
744  << y_outer_node[inod]+wall_thickness*normal_for_outer_wall[inod][1]
745  << " "
746  << z_outer_node[inod]+wall_thickness*normal_for_outer_wall[inod][2]
747  << 0 << '\n';
748  }
749  }
750  }
751 
752  // Face lists for the fluid mesh
753  //------------------------------
754  fluid_output_stream << '\n' << "# Face list : " << '\n';
755 
756  // Total number of facets and, yes, we do specify boundary IDs
757  fluid_output_stream << nfluid_face[0]+nfluid_face[1]+nfluid_face[2]
758  +nfluid_face[3] << ' ' << 1 << '\n'<< '\n';
759 
760 
761  // All four original boundaries
762  counter=0;
763  for(unsigned i=0; i<4; i++)
764  {
765  fluid_output_stream <<'\n'
766  << "#============================="
767  <<"====================================="
768  << '\n'<<"# Faces originally on boundary "
769  << i+1 << '\n'
770  <<"# --------------------------------" << '\n';
771 
772  // How many facest are on boundary 'i+1' ?
773  unsigned nface=nfluid_face[i];
774 
775  // Loop over the all facets
776  for(unsigned iface=0; iface<nface; iface++)
777  {
778  counter++;
779  fluid_output_stream <<"# Face " << counter << '\n';
780 
781  // one polygon, zero holes
782  fluid_output_stream << 1 << ' ' << 0 << ' ' ;
783 
784  // If we want a separate ID for each facet, the boundary ID is
785  // counter, otherwise, the boundary ID is i+1
786  if(do_multi_boundary_ids)
787  {
788  fluid_output_stream << counter << '\n';
789  }
790  else
791  {
792  fluid_output_stream << i+1 << '\n';
793  }
794 
795  // We have three vertices
796  fluid_output_stream << 3 << ' ' ;
797 
798  // Get pointer to the Vector storing the three nodes
799  Vector<unsigned>* face_node=&(fluid_faces[i][iface]);
800 
801  // This vector stores the nodes that are on boundaries 1 AND
802  // another one (2,3 or 4). We only store these nodes if a
803  // facet contains two or more such "double boundary" nodes.
804  // These are used to identify nodes that are part of the
805  // linking faces that connect the inner and outer solid surfaces.
806  Vector<unsigned> double_boundary_nod(3);
807 
808  // Storage for the number of entries in double_boundary_nod;
809  unsigned n_double_boundary_nodes=0;
810 
811  // loop over the three vertex/simplex nodes
812  for(unsigned l=0; l<3;l++)
813  {
814 
815  // get the old node number
816  unsigned inod=(*face_node)[l];
817 
818  // Write the vertices indices
819  fluid_output_stream <<fluid_node_nmbr[inod] << ' ';
820 
821  // find out how many nodes are double boundary nodes
822  if(i!=0)
823  {
824  if (done_for_solid[inod])
825  {
826  double_boundary_nod[n_double_boundary_nodes]=inod;
827  n_double_boundary_nodes++;
828  }
829  }
830  }
831 
832  // If we have more than one double boundary node,
833  // create faces linking the solid faces on
834  // boundary 1 and the solid faces on boundary 5
835  if(n_double_boundary_nodes>1)
836  {
837  for(unsigned idbn=0; idbn<n_double_boundary_nodes-1; idbn++)
838  {
839  // Each two double boundary nodes create two faces
840  for(unsigned j=0; j<2; j++)
841  {
842  unsigned index=0;
843 
844  for(unsigned l=j+idbn; l<2+idbn; l++)
845  {
846  // *[i-1] because *[k] stores informations for the
847  // (k+2)-th boundary
848  solid_linking_faces[i-1][nsolid_linking_faces[i-1]][index]=
849  solid_inner_node_nmbr[double_boundary_nod[l]];
850  index++;
851  }
852  for(unsigned l=idbn; l<idbn+j+1; l++)
853  {
854  // *[i-1] because *[k] stores informations for the
855  // (k+2)-th boundary
856  solid_linking_faces[i-1][nsolid_linking_faces[i-1]][index]=
857  solid_outer_node_nmbr[double_boundary_nod[l]];
858  index++;
859  }
860  nsolid_linking_faces[i-1]++;
861  }
862  }
863  }
864  fluid_output_stream << '\n'<< '\n';
865  }
866  }
867 
868 
869  // Write the face list of the solid surface
870  //-----------------------------------------
871  solid_output_stream << '\n' << "# Face list : " << '\n';
872 
873  // Total number of facets and, yes, we do specify boundary IDs
874  solid_output_stream << 2*nfluid_face[0]+ nsolid_linking_faces[0]
875  + nsolid_linking_faces[1]+ nsolid_linking_faces[2]
876  << ' ' << 1 << '\n'<< '\n';
877 
878  // Loop over all five original boundaries in the fluid mesh
879  counter=0;
880  for(unsigned i=0; i<5; i++)
881  {
882  solid_output_stream <<'\n'
883  << "#====================================="
884  <<"============================="
885  << '\n'<<"# Faces originally on boundary "
886  <<i+1 << '\n'
887  <<"# --------------------------------" << '\n';
888 
889  // Get the number of facets -- either the number of faces on the
890  // fluid's FSI interface or the number of "linking" faces that
891  // connect the inner and outer solid surfaces
892  unsigned nface;
893  if(i==0 || i==4)
894  {
895  nface=nfluid_face[0];
896  }
897  else
898  {
899  nface=nsolid_linking_faces[i-1];
900  }
901 
902  // Loop over faces
903  for(unsigned iface=0; iface<nface; iface++)
904  {
905  // Get pointer to the Vector storing the three vertex/simplex nodes
906  Vector<unsigned>* face_node;
907  if(i==0 || i==4)
908  {
909  face_node=&(fluid_faces[0][iface]);
910  }
911  // *[i-1] because *[k] stores informations for the (k+2)-th boundary
912  else
913  {
914  face_node=&(solid_linking_faces[i-1][iface]);
915  }
916 
917  counter++;
918  solid_output_stream <<"# Face " << counter << '\n';
919 
920  // One polygon, zero holes, boundary counter
921  solid_output_stream << 1 << ' ' << 0 << ' ' ;
922 
923  // If we want a separate ID for each FSI facet, the boundary ID is
924  // counter, otherwise, the boundary ID is i+1
925  if(do_multi_boundary_ids)
926  {
927  solid_output_stream << counter << '\n';
928  }
929  else
930  {
931  solid_output_stream << i+1 << '\n';
932  }
933 
934  // Three vertices and their indices in node list
935  solid_output_stream << 3 << ' ' ;
936 
937  // Loop over the three vertex/simplex nodes
938  for(unsigned l=0; l<3;l++)
939  {
940  // get the node number
941  unsigned inod=(*face_node)[l];
942 
943  // FSI surface
944  if(i==0)
945  {
946  // it's the old node number
947  solid_output_stream << solid_inner_node_nmbr[inod] << ' ';
948  }
949  // Outer surface
950  else if(i==4)
951  {
952  // it's the old node number
953  solid_output_stream << solid_outer_node_nmbr[inod] << ' ';
954  }
955  // Linking surfaces
956  else
957  {
958  // it's the new node number
959  solid_output_stream <<inod << ' ';
960  }
961 
962  }
963  solid_output_stream << '\n'<< '\n';
964  }
965  }
966 
967 
968  // Write the hole and region lists of the fluid and solid (empty)
969  //---------------------------------------------------------------
970  fluid_output_stream << '\n' << "# Hole list : " << '\n';
971  fluid_output_stream << 0 << '\n';
972  fluid_output_stream << '\n' << "# Region list : " << '\n';
973  fluid_output_stream << 0 << '\n';
974 
975  solid_output_stream << '\n' << "# Hole list : " << '\n';
976  solid_output_stream << 0 << '\n';
977  solid_output_stream << '\n' << "# Region list : " << '\n';
978  solid_output_stream << 0 << '\n';
979 
980 
981 
982 
983 
984  // Doc enumeration of boundaries
985  //------------------------------
986  filename=input_filename+"_boundary_enumeration.dat";
987  std::ofstream boundary_enumeration(filename.c_str());
988 
989  // Write the boundary informations for the fluid surface
990  fluid_output_stream << '\n'<< '\n'<< '\n'
991  <<"# Old (vmtk) enumeration of fluid boundaries:\n"
992  <<"# 1: FSI surface\n"
993  <<"# 2: Inlet\n"
994  <<"# 3: Outlet\n"
995  <<"# 4: Outlet\n"
996  <<"# The new boundary ids are as follow:"<< '\n' << '\n';
997 
998 
999  // Loop over four initial fluid boundaries
1000  for(unsigned i=0; i<4; i++)
1001  {
1002  fluid_output_stream << "# Boundary "<< i+1
1003  << " : from boundary id " ;
1004  unsigned id=0;
1005  for(unsigned j=0; j<i; j++)
1006  {
1007  id+=nfluid_face[j];
1008  }
1009 
1010  fluid_output_stream << id << " until boundary id "
1011  << id+nfluid_face[i]-1 << '\n';
1012  boundary_enumeration << id << " "
1013  << id+nfluid_face[i]-1 << " "
1014  << "# (fluid boundary" << i+1 << ") \n";
1015  }
1016  fluid_output_stream.close();
1017 
1018 
1019  // Write the boundary informations for the solid surface
1020  solid_output_stream << '\n'<< '\n'<< '\n'
1021  <<"# The new boundary ids are as follow:"<< '\n' << '\n';
1022 
1023  solid_output_stream << "# the inner surface : from boundary id "
1024  << 0 << " until boundary id ";
1025  unsigned id=nfluid_face[0]-1;
1026  solid_output_stream << id << "\n";
1027  boundary_enumeration << 0 << " " << id << " # (solid fsi boundary)\n";
1028 
1029 
1030  solid_output_stream << "# the front inflow face : from boundary id "
1031  << id+1 << " until boundary id " ;
1032  boundary_enumeration << id+1 << " ";
1033  id+=nsolid_linking_faces[0];
1034  solid_output_stream <<id<< "\n";
1035  boundary_enumeration << id << " # (solid inflow boundary)\n";
1036 
1037 
1038  solid_output_stream << "# the left bifurcation face : from boundary id "
1039  << id+1 << " until boundary id " ;
1040  boundary_enumeration << id+1 << " ";
1041  id+=nsolid_linking_faces[1];
1042  solid_output_stream << id<< "\n" ;
1043  boundary_enumeration << id << " # (solid left outflow boundary)\n";
1044 
1045  solid_output_stream << "# the right bifurcation : from boundary id "
1046  << id+1 << " until boundary id " ;
1047  boundary_enumeration << id+1 << " ";
1048  id+=nsolid_linking_faces[2];
1049  solid_output_stream << id << "\n";
1050  boundary_enumeration << id << " # (solid right outflow boundary)\n";
1051 
1052  solid_output_stream << "# the outer surface : from boundary id "
1053  << id+1 << " until boundary id " ;
1054  boundary_enumeration << id+1 << " ";
1055  id+=nfluid_face[0];
1056  solid_output_stream << id << "\n";
1057  boundary_enumeration << id << " # (solid outer boundary)\n";
1058  solid_output_stream.close();
1059  boundary_enumeration.close();
1060 
1061 
1062 }
AnnoyingScalar sqrt(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:134
int i
Definition: BiCGSTAB_step_by_step.cpp:9
EIGEN_DEVICE_FUNC const GlobalUnaryPowReturnType< Derived, ScalarExponent > pow(const Eigen::ArrayBase< Derived > &x, const ScalarExponent &exponent)
Definition: GlobalFunctions.h:137
Definition: oomph_definitions.h:222
static constexpr lastp1_t end
Definition: IndexedViewHelper.h:79
char char char int int * k
Definition: level2_impl.h:374
Vector< double > x1(const Vector< double > &coord)
Cartesian coordinates centered at the point (0.5,1)
Definition: poisson/poisson_with_singularity/two_d_poisson.cc:86
Vector< double > x2(const Vector< double > &coord)
Cartesian coordinates centered at the point (1.5,1)
Definition: poisson/poisson_with_singularity/two_d_poisson.cc:102
string filename
Definition: MergeRestartFiles.py:39
void normal(const Vector< double > &x, Vector< double > &normal)
Definition: free_surface_rotation.cc:65
default
Definition: calibrate.py:45
line
Definition: calibrate.py:103
std::string string(const unsigned &i)
Definition: oomph_definitions.cc:286
OomphInfo oomph_info
Definition: oomph_definitions.cc:319
#define OOMPH_EXCEPTION_LOCATION
Definition: oomph_definitions.h:61
#define OOMPH_CURRENT_FUNCTION
Definition: oomph_definitions.h:86
std::ofstream out("Result.txt")
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2

References calibrate::default, Eigen::placeholders::end, MergeRestartFiles::filename, i, j, k, calibrate::line, WallFunction::normal(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION, oomph::oomph_info, out(), Eigen::bfloat16_impl::pow(), sqrt(), oomph::Global_string_for_annotation::string(), Global_parameters::x1(), and Global_parameters::x2().