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