unstructured_three_d_solid.cc
Go to the documentation of this file.
1 //LIC// ====================================================================
2 //LIC// This file forms part of oomph-lib, the object-oriented,
3 //LIC// multi-physics finite-element library, available
4 //LIC// at http://www.oomph-lib.org.
5 //LIC//
6 //LIC// Copyright (C) 2006-2024 Matthias Heil and Andrew Hazel
7 //LIC//
8 //LIC// This library is free software; you can redistribute it and/or
9 //LIC// modify it under the terms of the GNU Lesser General Public
10 //LIC// License as published by the Free Software Foundation; either
11 //LIC// version 2.1 of the License, or (at your option) any later version.
12 //LIC//
13 //LIC// This library is distributed in the hope that it will be useful,
14 //LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
15 //LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 //LIC// Lesser General Public License for more details.
17 //LIC//
18 //LIC// You should have received a copy of the GNU Lesser General Public
19 //LIC// License along with this library; if not, write to the Free Software
20 //LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 //LIC// 02110-1301 USA.
22 //LIC//
23 //LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
24 //LIC//
25 //LIC//====================================================================
26 // Driver code for a simple unstructured solid problem using a mesh
27 // generated from an input file generated by the 3d mesh generator
28 // tetgen
29 
30 //Generic routines
31 #include "generic.h"
32 #include "solid.h"
33 #include "constitutive.h"
34 
35 // Get the mesh
36 #include "meshes/tetgen_mesh.h"
37 
38 using namespace std;
39 using namespace oomph;
40 
41 
42 
43 //=======================start_mesh========================================
44 /// Tetgen-based mesh upgraded to become a solid mesh
45 //=========================================================================
46 template<class ELEMENT>
47 class MySolidTetgenMesh : public virtual TetgenMesh<ELEMENT>,
48  public virtual SolidMesh
49 {
50 
51 public:
52 
53  /// Constructor:
54  MySolidTetgenMesh(const std::string& node_file_name,
55  const std::string& element_file_name,
56  const std::string& face_file_name,
57  TimeStepper* time_stepper_pt=
58  &Mesh::Default_TimeStepper) :
59  TetgenMesh<ELEMENT>(node_file_name, element_file_name,
60  face_file_name, time_stepper_pt)
61  {
62  //Assign the Lagrangian coordinates
63  set_lagrangian_nodal_coordinates();
64 
65  // Find elements next to boundaries
66  setup_boundary_element_info();
67  }
68 
69  /// Empty Destructor
70  virtual ~MySolidTetgenMesh() { }
71 
72 
73 };
74 
75 
76 /// ///////////////////////////////////////////////////////////////
77 /// ///////////////////////////////////////////////////////////////
78 /// ///////////////////////////////////////////////////////////////
79 
80 
81 //=======start_namespace==========================================
82 /// Global variables
83 //================================================================
85 {
86 
87  /// Poisson's ratio
88  double Nu=0.3;
89 
90  /// Create constitutive law
91  ConstitutiveLaw* Constitutive_law_pt=new GeneralisedHookean(&Nu);
92 
93  /// Non-dim gravity
94  double Gravity=0.0;
95 
96  /// Non-dimensional gravity as body force
97  void gravity(const double& time,
98  const Vector<double> &xi,
99  Vector<double> &b)
100  {
101  b[0]=-Gravity;
102  b[1]=0.0;
103  b[2]=0.0;
104  } // end gravity
105 
106  /// Uniform pressure
107  double P = 0.0;
108 
109  /// Constant pressure load. The arguments to this function are imposed
110  /// on us by the SolidTractionElements which allow the traction to
111  /// depend on the Lagrangian and Eulerian coordinates x and xi, and on the
112  /// outer unit normal to the surface. Here we only need the outer unit
113  /// normal.
114  void constant_pressure(const Vector<double> &xi, const Vector<double> &x,
115  const Vector<double> &n, Vector<double> &traction)
116  {
117  unsigned dim = traction.size();
118  for(unsigned i=0;i<dim;i++)
119  {
120  traction[i] = -P*n[i];
121  }
122  } // end traction
123 
124 
125 } //end namespace
126 
127 
128 
129 
130 
131 
132 //=============start_problem===========================================
133 /// Unstructured solid problem
134 //=====================================================================
135 template<class ELEMENT>
136 class UnstructuredSolidProblem : public Problem
137 {
138 
139 public:
140 
141  /// Constructor:
143 
144  /// Destructor (empty)
146 
147  /// Doc the solution
148  void doc_solution(DocInfo& doc_info);
149 
150 private:
151 
152  /// Create traction elements
153  void create_traction_elements();
154 
155  /// Bulk solid mesh
157 
158  /// Meshes of traction elements
159  Vector<SolidMesh*> Solid_traction_mesh_pt;
160 
161  /// IDs of solid mesh boundaries where displacements are pinned
162  Vector<unsigned> Pinned_solid_boundary_id;
163 
164  /// IDs of solid mesh boundaries which make up the traction interface
165  Vector<unsigned> Solid_traction_boundary_id;
166 
167 };
168 
169 
170 
171 //=============start_constructor==========================================
172 /// Constructor for unstructured solid problem
173 //========================================================================
174 template<class ELEMENT>
176 {
177 
178  //Create solid bulk mesh
179  string node_file_name="fsi_bifurcation_solid.1.node";
180  string element_file_name="fsi_bifurcation_solid.1.ele";
181  string face_file_name="fsi_bifurcation_solid.1.face";
182  Solid_mesh_pt = new MySolidTetgenMesh<ELEMENT>(node_file_name,
183  element_file_name,
184  face_file_name);
185 
186  // The following IDs corresponds to the boundary IDs specified in
187  // the *.poly file from which tetgen generated the unstructured mesh.
188 
189  /// IDs of solid mesh boundaries where displacements are pinned
190  Pinned_solid_boundary_id.resize(3);
191  Pinned_solid_boundary_id[0]=0;
192  Pinned_solid_boundary_id[1]=1;
193  Pinned_solid_boundary_id[2]=2;
194 
195  // The solid mesh boundaries where an internal pressure is applied
196  Solid_traction_boundary_id.resize(12);
197  for (unsigned i=0;i<12;i++)
198  {
199  Solid_traction_boundary_id[i]=i+3;
200  }
201 
202 
203  // Apply BCs for solid
204  //--------------------
205 
206  // Doc pinned solid nodes
207  std::ofstream bc_file("RESLT/pinned_solid_nodes.dat");
208 
209  // Pin positions at inflow boundary (boundaries 0 and 1)
210  unsigned n=Pinned_solid_boundary_id.size();
211  for (unsigned i=0;i<n;i++)
212  {
213  // Get boundary ID
214  unsigned b=Pinned_solid_boundary_id[i];
215  unsigned num_nod= Solid_mesh_pt->nboundary_node(b);
216  for (unsigned inod=0;inod<num_nod;inod++)
217  {
218  // Get node
219  SolidNode* nod_pt=Solid_mesh_pt->boundary_node_pt(b,inod);
220 
221  // Pin all directions
222  for (unsigned i=0;i<3;i++)
223  {
224  nod_pt->pin_position(i);
225 
226  // ...and doc it as pinned
227  bc_file << nod_pt->x(i) << " ";
228  }
229 
230  bc_file << std::endl;
231  }
232  }
233  bc_file.close();
234 
235 
236 
237  // Complete the build of all elements so they are fully functional
238  //----------------------------------------------------------------
239  unsigned n_element = Solid_mesh_pt->nelement();
240  for(unsigned i=0;i<n_element;i++)
241  {
242  //Cast to a solid element
243  ELEMENT *el_pt = dynamic_cast<ELEMENT*>(
244  Solid_mesh_pt->element_pt(i));
245 
246  // Set the constitutive law
247  el_pt->constitutive_law_pt() =
249 
250  //Set the body force
251  el_pt->body_force_fct_pt() = Global_Parameters::gravity;
252  }
253 
254 
255  // Create traction elements
256  //-------------------------
257 
258  // Create meshes of traction elements
259  n=Solid_traction_boundary_id.size();
260  Solid_traction_mesh_pt.resize(n);
261  for (unsigned i=0;i<n;i++)
262  {
263  Solid_traction_mesh_pt[i]=new SolidMesh;
264  }
265 
266  // Build the traction elements
267  create_traction_elements();
268 
269 
270  // Combine the lot
271  //----------------
272 
273  // The solid bulk mesh
274  add_sub_mesh(Solid_mesh_pt);
275 
276  // The solid traction meshes
277  n=Solid_traction_boundary_id.size();
278  for (unsigned i=0;i<n;i++)
279  {
280  add_sub_mesh(Solid_traction_mesh_pt[i]);
281  }
282 
283  // Build global mesh
284  build_global_mesh();
285 
286  // Setup equation numbering scheme
287  std::cout <<"Number of equations: " << assign_eqn_numbers() << std::endl;
288 
289 } // end constructor
290 
291 
292 
293 //============start_of_create_traction_elements==========================
294 /// Create traction elements
295 //=======================================================================
296 template<class ELEMENT>
298 {
299 
300  // Loop over traction boundaries
301  unsigned n=Solid_traction_boundary_id.size();
302  for (unsigned i=0;i<n;i++)
303  {
304  // Get boundary ID
305  unsigned b=Solid_traction_boundary_id[i];
306 
307  // How many bulk elements are adjacent to boundary b?
308  unsigned n_element = Solid_mesh_pt->nboundary_element(b);
309 
310  // Loop over the bulk elements adjacent to boundary b
311  for(unsigned e=0;e<n_element;e++)
312  {
313  // Get pointer to the bulk element that is adjacent to boundary b
314  ELEMENT* bulk_elem_pt = dynamic_cast<ELEMENT*>(
315  Solid_mesh_pt->boundary_element_pt(b,e));
316 
317  //What is the index of the face of the element e along boundary b
318  int face_index = Solid_mesh_pt->face_index_at_boundary(b,e);
319 
320  // Create new element
321  SolidTractionElement<ELEMENT>* el_pt=
322  new SolidTractionElement<ELEMENT>(bulk_elem_pt,face_index);
323 
324  // Add it to the mesh
325  Solid_traction_mesh_pt[i]->add_element_pt(el_pt);
326 
327  //Set the traction function
328  el_pt->traction_fct_pt() = Global_Parameters::constant_pressure;
329  }
330  }
331 
332 } // end of create_traction_elements
333 
334 
335 
336 //========================================================================
337 /// Doc the solution
338 //========================================================================
339 template<class ELEMENT>
341 {
342 
343  ofstream some_file;
344  char filename[100];
345 
346  // Number of plot points
347  unsigned npts;
348  npts=5;
349 
350  // Output solid solution
351  //-----------------------
352  sprintf(filename,"%s/solid_soln%i.dat",doc_info.directory().c_str(),
353  doc_info.number());
354  some_file.open(filename);
355  Solid_mesh_pt->output(some_file,npts);
356  some_file.close();
357 
358 
359  // Output traction
360  //----------------
361  sprintf(filename,"%s/traction%i.dat",doc_info.directory().c_str(),
362  doc_info.number());
363  some_file.open(filename);
364  unsigned n=Solid_traction_boundary_id.size();
365  for (unsigned i=0;i<n;i++)
366  {
367  Solid_traction_mesh_pt[i]->output(some_file,npts);
368  }
369  some_file.close();
370 
371 } // end doc
372 
373 
374 
375 
376 
377 //============================start_main==================================
378 /// Demonstrate how to solve an unstructured 3D solid problem
379 //========================================================================
380 int main(int argc, char **argv)
381 {
382  // Store command line arguments
383  CommandLineArgs::setup(argc,argv);
384 
385  // Label for output
386  DocInfo doc_info;
387 
388  // Output directory
389  doc_info.set_directory("RESLT");
390 
391  //Set up the problem
393 
394  //Output initial configuration
395  problem.doc_solution(doc_info);
396  doc_info.number()++;
397 
398  // Parameter study
400  double g_increment=1.0e-3;
401  double p_increment=1.0e-2;
402 
403  unsigned nstep=6;
404  if (CommandLineArgs::Argc!=1)
405  {
406  std::cout << "Validation -- only doing two steps" << std::endl;
407  nstep=2;
408  }
409 
410  // Do the parameter study
411  for (unsigned istep=0;istep<nstep;istep++)
412  {
413  // Solve the problem
414  problem.newton_solve();
415 
416  //Output solution
417  problem.doc_solution(doc_info);
418  doc_info.number()++;
419 
420  // Bump up load
421  Global_Parameters::Gravity+=g_increment;
422  Global_Parameters::P+=p_increment;
423 
424  }
425 
426 } // end main
427 
428 
429 
430 
Tetgen-based mesh upgraded to become a solid mesh.
MySolidTetgenMesh(const std::string &node_file_name, const std::string &element_file_name, const std::string &face_file_name, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor:
virtual ~MySolidTetgenMesh()
Empty Destructor.
Unstructured solid problem.
~UnstructuredSolidProblem()
Destructor (empty)
Vector< SolidMesh * > Solid_traction_mesh_pt
Meshes of traction elements.
Vector< unsigned > Solid_traction_boundary_id
IDs of solid mesh boundaries which make up the traction interface.
Vector< unsigned > Pinned_solid_boundary_id
IDs of solid mesh boundaries where displacements are pinned.
void create_traction_elements()
Create traction elements.
void doc_solution(DocInfo &doc_info)
Doc the solution.
MySolidTetgenMesh< ELEMENT > * Solid_mesh_pt
Bulk solid mesh.
/////////////////////////////////////////////////////////////// /////////////////////////////////////...
void gravity(const double &time, const Vector< double > &xi, Vector< double > &b)
Non-dimensional gravity as body force.
double Nu
Poisson's ratio.
double P
Uniform pressure.
double Gravity
Non-dim gravity.
void constant_pressure(const Vector< double > &xi, const Vector< double > &x, const Vector< double > &n, Vector< double > &traction)
Constant pressure load. The arguments to this function are imposed on us by the SolidTractionElements...
ConstitutiveLaw * Constitutive_law_pt
Create constitutive law.
int main(int argc, char **argv)
Demonstrate how to solve an unstructured 3D solid problem.