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-2023 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 
40 using namespace oomph;
41 
42 
43 
44 //=========================================================================
45 /// Triangle-based mesh upgraded to become a solid mesh
46 //=========================================================================
47 template<class ELEMENT>
48 class ElasticTetMesh : public virtual TetgenMesh<ELEMENT>,
49  public virtual SolidMesh
50 {
51 
52 public:
53 
54  /// Constructor:
55  ElasticTetMesh(const std::string& node_file_name,
56  const std::string& element_file_name,
57  const std::string& poly_file_name,
58  TimeStepper* time_stepper_pt=
59  &Mesh::Default_TimeStepper) :
60  TetgenMesh<ELEMENT>(node_file_name, element_file_name,
61  poly_file_name, time_stepper_pt)
62  {
63  //Assign the Lagrangian coordinates
64  set_lagrangian_nodal_coordinates();
65 
66  // Identify special boundaries but remember that
67  // outer boundary is already set to boundary 0; inner
68  // (hole) boundary is already boundary 1.
69  set_nboundary(4);
70 
71  unsigned n_node=this->nnode();
72  for (unsigned j=0;j<n_node;j++)
73  {
74  Node* nod_pt=this->node_pt(j);
75 
76  // Boundary 2 is right boundary
77  if (nod_pt->x(1)>2.99)
78  {
79  this->convert_to_boundary_node(nod_pt);
80  this->remove_boundary_node(0,nod_pt);
81  this->add_boundary_node(2,nod_pt);
82  }
83 
84  // Boundary 3 is upper boundary
85  if (nod_pt->x(2)>2.99)
86  {
87  this->convert_to_boundary_node(nod_pt);
88  this->remove_boundary_node(0,nod_pt);
89  this->add_boundary_node(3,nod_pt);
90  }
91 
92  }
93  TetgenMesh<ELEMENT>::setup_boundary_element_info();
94 
95  }
96 
97  /// Empty Destructor
98  virtual ~ElasticTetMesh() { }
99 
100 
101 };
102 
103 /// ////////////////////////////////////////////////////////////////////
104 /// ////////////////////////////////////////////////////////////////////
105 /// ////////////////////////////////////////////////////////////////////
106 
107 
108 
109 //=======start_namespace==========================================
110 /// Global variables
111 //================================================================
113 {
114 
115  /// Pointer to constitutive law
116  ConstitutiveLaw* Constitutive_law_pt=0;
117 
118  /// Poisson's ratio
119  double Nu=0.3;
120 
121  /// Non-dim gravity
122  double Gravity=0.0;
123 
124  /// Non-dimensional gravity as body force
125  void gravity(const double& time,
126  const Vector<double> &xi,
127  Vector<double> &b)
128  {
129  b[0]=0.0;
130  b[1]=0.0;
131  b[2]=-Gravity;
132  }
133 
134  /// Uniform pressure
135  double P = 0.0;
136 
137  /// Constant pressure load. The arguments to this function are imposed
138  /// on us by the SolidTractionElements which allow the traction to
139  /// depend on the Lagrangian and Eulerian coordinates x and xi, and on the
140  /// outer unit normal to the surface. Here we only need the outer unit
141  /// normal.
142  void constant_pressure(const Vector<double> &xi, const Vector<double> &x,
143  const Vector<double> &n, Vector<double> &traction)
144  {
145  unsigned dim = traction.size();
146  for(unsigned i=0;i<dim;i++)
147  {
148  traction[i] = -P*n[i];
149  }
150  } // end traction
151 
152 
153 } //end namespace
154 
155 
156 
157 
158 
159 
160 //====================================================================
161 /// Unstructured solid problem
162 //====================================================================
163 template<class ELEMENT>
164 class UnstructuredSolidProblem : public Problem
165 {
166 
167 public:
168 
169  /// Constructor:
171 
172  /// Destructor (empty)
174 
175  /// Update the problem specs before solve: empty
177 
178  /// Update the problem specs before solve: empty
180 
181  /// Doc the solution
182  void doc_solution(DocInfo& doc_info);
183 
184 private:
185 
186  /// Bulk mesh
188 
189  /// Pointer to mesh of traction elements
190  SolidMesh* Traction_mesh_pt;
191 
192 };
193 
194 
195 
196 //========================================================================
197 /// Constructor for unstructured solid problem
198 //========================================================================
199 template<class ELEMENT>
202 {
203 
204  //Create bulk mesh
205  string node_file_name="cube_hole.1.node";
206  string element_file_name="cube_hole.1.ele";
207  string face_file_name="cube_hole.1.face";
208  Solid_mesh_pt = new ElasticTetMesh<ELEMENT>(node_file_name,
209  element_file_name,
210  face_file_name);
211 
212  // Traction elements are located on boundary 3:
213  unsigned b=3;
214 
215  // Make traction mesh
216  Traction_mesh_pt=new SolidMesh;
217 
218  // How many bulk elements are adjacent to boundary b?
219  unsigned n_element = Solid_mesh_pt->nboundary_element(b);
220 
221  // Loop over the bulk elements adjacent to boundary b
222  for(unsigned e=0;e<n_element;e++)
223  {
224  // Get pointer to the bulk element that is adjacent to boundary b
225  ELEMENT* bulk_elem_pt = dynamic_cast<ELEMENT*>(
226  Solid_mesh_pt->boundary_element_pt(b,e));
227 
228  //Find the index of the face of element e along boundary b
229  int face_index = Solid_mesh_pt->face_index_at_boundary(b,e);
230 
231  //Create solid traction element
232  SolidTractionElement<ELEMENT> *el_pt =
233  new SolidTractionElement<ELEMENT>(bulk_elem_pt,face_index);
234 
235  // Add to mesh
236  Traction_mesh_pt->add_element_pt(el_pt);
237 
238  //Set the traction function
239  el_pt->traction_fct_pt() = Global_Physical_Variables::constant_pressure;
240 
241  }
242 
243 
244  // Add sub meshes
245  add_sub_mesh(Solid_mesh_pt);
246  add_sub_mesh(Traction_mesh_pt);
247 
248  // Build global mesh
249  build_global_mesh();
250 
251 
252  // Doc pinned solid nodes
253  std::ofstream bc_file("pinned_nodes.dat");
254 
255  // Pin positions at right boundary (boundary 2)
256  unsigned ibound=2;
257  unsigned num_nod= Solid_mesh_pt->nboundary_node(ibound);
258  for (unsigned inod=0;inod<num_nod;inod++)
259  {
260  // Get node
261  SolidNode* nod_pt=Solid_mesh_pt->boundary_node_pt(ibound,inod);
262 
263  // Pin all directions
264  for (unsigned i=0;i<3;i++)
265  {
266  nod_pt->pin_position(i);
267 
268  // ...and doc it as pinned
269  bc_file << nod_pt->x(i) << " ";
270  }
271 
272  bc_file << std::endl;
273  }
274 
275  // Complete the build of all elements so they are fully functional
276  n_element = Solid_mesh_pt->nelement();
277  for(unsigned i=0;i<n_element;i++)
278  {
279  //Cast to a solid element
280  ELEMENT *el_pt = dynamic_cast<ELEMENT*>(Solid_mesh_pt->element_pt(i));
281 
282  // Set the constitutive law
283  el_pt->constitutive_law_pt() =
285 
286  //Set the body force
287  el_pt->body_force_fct_pt() = Global_Physical_Variables::gravity;
288  }
289 
290 
291  // Setup equation numbering scheme
292  cout <<"Number of equations: " << assign_eqn_numbers() << std::endl;
293 
294 }
295 
296 
297 
298 //========================================================================
299 /// Doc the solution
300 //========================================================================
301 template<class ELEMENT>
303 {
304 
305  ofstream some_file;
306  char filename[100];
307 
308  // Number of plot points
309  unsigned npts;
310  npts=5;
311 
312  // Output boundaries
313  //------------------
314  sprintf(filename,"%s/boundaries%i.dat",doc_info.directory().c_str(),
315  doc_info.number());
316  some_file.open(filename);
317  Solid_mesh_pt->output_boundaries(some_file);
318  some_file.close();
319 
320 
321  // Output solution
322  //----------------
323  sprintf(filename,"%s/soln%i.dat",doc_info.directory().c_str(),
324  doc_info.number());
325  some_file.open(filename);
326  Solid_mesh_pt->output(some_file,npts);
327  some_file.close();
328 
329 
330  // Output traction
331  //----------------
332  sprintf(filename,"%s/traction%i.dat",doc_info.directory().c_str(),
333  doc_info.number());
334  some_file.open(filename);
335  Traction_mesh_pt->output(some_file,npts);
336  some_file.close();
337 
338 }
339 
340 
341 
342 
343 
344 //========================================================================
345 /// Demonstrate how to solve an unstructured solid problem
346 //========================================================================
347 int main()
348 {
349 
350  // Label for output
351  DocInfo doc_info;
352 
353  // Output directory
354  doc_info.set_directory("RESLT");
355 
356  // Create generalised Hookean constitutive equations
358  new GeneralisedHookean(&Global_Physical_Variables::Nu);
359 
360  //Set up the problem
362 
363  //Output initial configuration
364  problem.doc_solution(doc_info);
365  doc_info.number()++;
366 
367  // Parameter study
370  double pressure_increment=-8.0e-3;
371 
372  unsigned nstep=2; // 10;
373  for (unsigned istep=0;istep<nstep;istep++)
374  {
375  // Solve the problem
376  problem.newton_solve();
377 
378  //Output solution
379  problem.doc_solution(doc_info);
380  doc_info.number()++;
381 
382  // Bump up suction
383  Global_Physical_Variables::P+=pressure_increment;
384  }
385 
386 }
387 
388 
389 
Triangle-based mesh upgraded to become a solid mesh.
virtual ~ElasticTetMesh()
Empty Destructor.
ElasticTetMesh(const std::string &node_file_name, const std::string &element_file_name, const std::string &poly_file_name, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor:
Unstructured solid problem.
ElasticTetMesh< ELEMENT > * Solid_mesh_pt
Bulk mesh.
~UnstructuredSolidProblem()
Destructor (empty)
void actions_after_newton_solve()
Update the problem specs before solve: empty.
void doc_solution(DocInfo &doc_info)
Doc the solution.
SolidMesh * Traction_mesh_pt
Pointer to mesh of traction elements.
void actions_before_newton_solve()
Update the problem specs before solve: empty.
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
void gravity(const double &time, const Vector< double > &xi, Vector< double > &b)
Non-dimensional gravity as body force.
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
Pointer to constitutive law.
int main()
Demonstrate how to solve an unstructured solid problem.