unstructured_two_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// Version 1.0; svn revision $LastChangedRevision$
7 //LIC//
8 //LIC// $LastChangedDate$
9 //LIC//
10 //LIC// Copyright (C) 2006-2016 Matthias Heil and Andrew Hazel
11 //LIC//
12 //LIC// This library is free software; you can redistribute it and/or
13 //LIC// modify it under the terms of the GNU Lesser General Public
14 //LIC// License as published by the Free Software Foundation; either
15 //LIC// version 2.1 of the License, or (at your option) any later version.
16 //LIC//
17 //LIC// This library is distributed in the hope that it will be useful,
18 //LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
19 //LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 //LIC// Lesser General Public License for more details.
21 //LIC//
22 //LIC// You should have received a copy of the GNU Lesser General Public
23 //LIC// License along with this library; if not, write to the Free Software
24 //LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 //LIC// 02110-1301 USA.
26 //LIC//
27 //LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
28 //LIC//
29 //LIC//====================================================================
30 // Driver code for a simple unstructured solid problem using a mesh
31 // generated from an input file generated by the triangle mesh generator
32 // Triangle.
33 
34 //Generic routines
35 #include "generic.h"
36 #include "solid.h"
37 #include "constitutive.h"
38 
39 
40 // The mesh
41 #include "meshes/triangle_mesh.h"
42 
43 using namespace std;
44 using namespace oomph;
45 
46 
47 //================start_mesh===============================================
48 /// Triangle-based mesh upgraded to become a solid mesh
49 //=========================================================================
50 template<class ELEMENT>
51 class ElasticTriangleMesh : public virtual TriangleMesh<ELEMENT>,
52  public virtual SolidMesh
53 {
54 
55 public:
56 
57  /// \short Constructor:
58  ElasticTriangleMesh(const std::string& node_file_name,
59  const std::string& element_file_name,
60  const std::string& poly_file_name,
61  TimeStepper* time_stepper_pt=
62  &Mesh::Default_TimeStepper) :
63  TriangleMesh<ELEMENT>(node_file_name,element_file_name,
64  poly_file_name, time_stepper_pt)
65  {
66  //Assign the Lagrangian coordinates
67  set_lagrangian_nodal_coordinates();
68 
69  // Identify special boundaries
70  set_nboundary(3);
71 
72  unsigned n_node=this->nnode();
73  for (unsigned j=0;j<n_node;j++)
74  {
75  Node* nod_pt=this->node_pt(j);
76 
77  // Boundary 1 is lower boundary
78  if (nod_pt->x(1)<0.15)
79  {
80  this->remove_boundary_node(0,nod_pt);
81  this->add_boundary_node(1,nod_pt);
82  }
83 
84  // Boundary 2 is upper boundary
85  if (nod_pt->x(1)>2.69)
86  {
87  this->remove_boundary_node(0,nod_pt);
88  this->add_boundary_node(2,nod_pt);
89  }
90  }
91 
92  std::cout << "About to setup the boundary elements" << std::endl;
93  // Re-setup boundary info, i.e. elements next to boundaries
94  TriangleMesh<ELEMENT>::setup_boundary_element_info();
95  //This is the bit that has gone wrong
96  }
97 
98  /// Empty Destructor
99  virtual ~ElasticTriangleMesh() { }
100 
101 };
102 
103 ///////////////////////////////////////////////////////////////////////
104 ///////////////////////////////////////////////////////////////////////
105 ///////////////////////////////////////////////////////////////////////
106 
107 
108 
109 //=======start_namespace==========================================
110 /// Global variables
111 //================================================================
113 {
114  /// Poisson's ratio
115  double Nu=0.3;
116 
117  /// Pointer to constitutive law
118  ConstitutiveLaw* Constitutive_law_pt=0;
119 
120  /// Non-dim gravity
121  double Gravity=0.0;
122 
123  /// Non-dimensional gravity as body force
124  void gravity(const double& time,
125  const Vector<double> &xi,
126  Vector<double> &b)
127  {
128  b[0]=0.0;
129  b[1]=-Gravity;
130  }
131 
132  /// Uniform pressure
133  double P = 0.0;
134 
135  /// \short Constant pressure load. The arguments to this function are imposed
136  /// on us by the SolidTractionElements which allow the traction to
137  /// depend on the Lagrangian and Eulerian coordinates x and xi, and on the
138  /// outer unit normal to the surface. Here we only need the outer unit
139  /// normal.
140  void constant_pressure(const Vector<double> &xi, const Vector<double> &x,
141  const Vector<double> &n, Vector<double> &traction)
142  {
143  unsigned dim = traction.size();
144  for(unsigned i=0;i<dim;i++)
145  {
146  traction[i] = -P*n[i];
147  }
148  }
149 
150 } //end namespace
151 
152 
153 
154 
155 
156 
157 //==============start_problem=========================================
158 /// Unstructured solid problem
159 //====================================================================
160 template<class ELEMENT>
161 class UnstructuredSolidProblem : public Problem
162 {
163 
164 public:
165 
166  /// \short Constructor:
168 
169  /// Destructor (empty)
171 
172  /// Doc the solution
173  void doc_solution(DocInfo& doc_info);
174 
175 private:
176 
177  /// Bulk mesh
179 
180  /// Pointer to mesh of traction elements
181  SolidMesh* Traction_mesh_pt;
182 
183 };
184 
185 
186 
187 //===============start_constructor========================================
188 /// Constructor for unstructured solid problem
189 //========================================================================
190 template<class ELEMENT>
192 {
193 
194  //Create solid mesh
195  string node_file_name="solid.fig.1.node";
196  string element_file_name="solid.fig.1.ele";
197  string poly_file_name="solid.fig.1.poly";
198  Solid_mesh_pt = new ElasticTriangleMesh<ELEMENT>(node_file_name,
199  element_file_name,
200  poly_file_name);
201 
202  // Traction elements are located on boundary 2:
203  unsigned b=2;
204 
205  // Make traction mesh
206  Traction_mesh_pt=new SolidMesh;
207 
208  // How many bulk elements are adjacent to boundary b?
209  unsigned n_element = Solid_mesh_pt->nboundary_element(b);
210 
211  // Loop over the bulk elements adjacent to boundary b
212  for(unsigned e=0;e<n_element;e++)
213  {
214  // Get pointer to the bulk element that is adjacent to boundary b
215  ELEMENT* bulk_elem_pt = dynamic_cast<ELEMENT*>(
216  Solid_mesh_pt->boundary_element_pt(b,e));
217 
218  //Find the index of the face of element e along boundary b
219  int face_index = Solid_mesh_pt->face_index_at_boundary(b,e);
220 
221  //Create solid traction element
222  SolidTractionElement<ELEMENT> *el_pt =
223  new SolidTractionElement<ELEMENT>(bulk_elem_pt,face_index);
224 
225  // Add to mesh
226  Traction_mesh_pt->add_element_pt(el_pt);
227 
228  //Set the traction function
229  el_pt->traction_fct_pt() = Global_Physical_Variables::constant_pressure;
230  }
231 
232  // Add sub meshes
233  add_sub_mesh(Solid_mesh_pt);
234  add_sub_mesh(Traction_mesh_pt);
235 
236  // Build global mesh
237  build_global_mesh();
238 
239  // Doc pinned solid nodes
240  std::ofstream bc_file("pinned_nodes.dat");
241 
242  // Pin both positions at lower boundary (boundary 1)
243  unsigned ibound=1;
244  unsigned num_nod= mesh_pt()->nboundary_node(ibound);
245  for (unsigned inod=0;inod<num_nod;inod++)
246  {
247 
248  // Get node
249  SolidNode* nod_pt=Solid_mesh_pt->boundary_node_pt(ibound,inod);
250 
251  // Pin both directions
252  for (unsigned i=0;i<2;i++)
253  {
254  nod_pt->pin_position(i);
255 
256  // ...and doc it as pinned
257  bc_file << nod_pt->x(i) << " ";
258  }
259 
260  bc_file << std::endl;
261  }
262  bc_file.close();
263 
264 
265  // Complete the build of all elements so they are fully functional
266  n_element = Solid_mesh_pt->nelement();
267  for(unsigned i=0;i<n_element;i++)
268  {
269  //Cast to a solid element
270  ELEMENT *el_pt = dynamic_cast<ELEMENT*>(Solid_mesh_pt->element_pt(i));
271 
272  // Set the constitutive law
273  el_pt->constitutive_law_pt() =
275 
276  //Set the body force
277  el_pt->body_force_fct_pt() = Global_Physical_Variables::gravity;
278  }
279 
280  // Setup equation numbering scheme
281  cout <<"Number of equations: " << assign_eqn_numbers() << std::endl;
282 
283 } //end constructor
284 
285 
286 //========================================================================
287 /// Doc the solution
288 //========================================================================
289 template<class ELEMENT>
291 {
292 
293  ofstream some_file;
294  char filename[100];
295 
296  // Number of plot points
297  unsigned npts;
298  npts=5;
299 
300  // Output solution
301  //----------------
302  sprintf(filename,"%s/soln%i.dat",doc_info.directory().c_str(),
303  doc_info.number());
304  some_file.open(filename);
305  Solid_mesh_pt->output(some_file,npts);
306  some_file.close();
307 
308  // Output traction
309  //----------------
310  sprintf(filename,"%s/traction%i.dat",doc_info.directory().c_str(),
311  doc_info.number());
312  some_file.open(filename);
313  Traction_mesh_pt->output(some_file,npts);
314  some_file.close();
315 
316  // Output boundaries
317  //------------------
318  sprintf(filename,"%s/boundaries.dat",doc_info.directory().c_str());
319  some_file.open(filename);
320  Solid_mesh_pt->output_boundaries(some_file);
321  some_file.close();
322 
323 }
324 
325 
326 
327 
328 
329 //===========start_main===================================================
330 /// Demonstrate how to solve an unstructured solid problem
331 //========================================================================
332 int main()
333 {
334  // Label for output
335  DocInfo doc_info;
336 
337  // Output directory
338  doc_info.set_directory("RESLT");
339 
340  // Create generalised Hookean constitutive equations
342  new GeneralisedHookean(&Global_Physical_Variables::Nu);
343 
344  {
345  std::cout << "Running with pure displacement formulation\n";
346 
347  //Set up the problem
349 
350  //Output initial configuration
351  problem.doc_solution(doc_info);
352  doc_info.number()++;
353 
354  // Parameter study
357  double pressure_increment=-1.0e-4;
358 
359  unsigned nstep=2; // 10;
360  for (unsigned istep=0;istep<nstep;istep++)
361  {
362  // Solve the problem
363  problem.newton_solve();
364 
365  //Output solution
366  problem.doc_solution(doc_info);
367  doc_info.number()++;
368 
369  // Bump up suction
370  Global_Physical_Variables::P+=pressure_increment;
371  }
372  } //end_displacement_formulation
373 
374  //Repeat for displacement/pressure formulation
375  {
376  std::cout << "Running with pressure/displacement formulation\n";
377 
378  // Change output directory
379  doc_info.set_directory("RESLT_pres_disp");
380  //Reset doc_info number
381  doc_info.number() = 0;
382 
383  //Set up the problem
385 
386  //Output initial configuration
387  problem.doc_solution(doc_info);
388  doc_info.number()++;
389 
390  // Parameter study
393  double pressure_increment=-1.0e-4;
394 
395  unsigned nstep=2;
396  for (unsigned istep=0;istep<nstep;istep++)
397  {
398  // Solve the problem
399  problem.newton_solve();
400 
401  //Output solution
402  problem.doc_solution(doc_info);
403  doc_info.number()++;
404 
405  // Bump up suction
406  Global_Physical_Variables::P+=pressure_increment;
407  }
408  }
409 
410 
411  //Repeat for displacement/pressure formulation
412  //enforcing incompressibility
413  {
414  std::cout <<
415  "Running with pressure/displacement formulation (incompressible) \n";
416 
417  // Change output directory
418  doc_info.set_directory("RESLT_pres_disp_incomp");
419  //Reset doc_info number
420  doc_info.number() = 0;
421 
422  //Set up the problem
424 
425  //Loop over all elements and set incompressibility flag
426  {
427  const unsigned n_element = problem.mesh_pt()->nelement();
428  for(unsigned e=0;e<n_element;e++)
429  {
430  //Cast the element to the equation base of our 2D elastiticy elements
431  PVDEquationsWithPressure<2> *cast_el_pt =
432  dynamic_cast<PVDEquationsWithPressure<2>*>(
433  problem.mesh_pt()->element_pt(e));
434 
435  //If the cast was successful, it's a bulk element,
436  //so set the incompressibilty flag
437  if(cast_el_pt) {cast_el_pt->set_incompressible();}
438  }
439  }
440 
441 
442  //Output initial configuration
443  problem.doc_solution(doc_info);
444  doc_info.number()++;
445 
446  // Parameter study
449  double pressure_increment=-1.0e-4;
450 
451  unsigned nstep=2;
452  for (unsigned istep=0;istep<nstep;istep++)
453  {
454  // Solve the problem
455  problem.newton_solve();
456 
457  //Output solution
458  problem.doc_solution(doc_info);
459  doc_info.number()++;
460 
461  // Bump up suction
462  Global_Physical_Variables::P+=pressure_increment;
463  }
464  }
465 
466 
467 
468 } // end main
469 
470 
471 
void doc_solution(DocInfo &doc_info)
Doc the solution.
Unstructured solid problem.
ConstitutiveLaw * Constitutive_law_pt
Pointer to constitutive law.
virtual ~ElasticTriangleMesh()
Empty Destructor.
void gravity(const double &time, const Vector< double > &xi, Vector< double > &b)
Non-dimensional gravity as body force.
ElasticTriangleMesh< ELEMENT > * Solid_mesh_pt
Bulk mesh.
int main()
Demonstrate how to solve an unstructured solid problem.
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...
Triangle-based mesh upgraded to become a solid mesh.
~UnstructuredSolidProblem()
Destructor (empty)
ElasticTriangleMesh(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:
double Nu
Poisson&#39;s ratio.