simple_shear.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 for elastic deformation of a cuboidal domain
27 // The deformation is a simple shear in the x-z plane driven by
28 // motion of the top boundary, for exact solution see Green & Zerna
29 
30 // Generic oomph-lib headers
31 #include "generic.h"
32 
33 // Solid mechanics
34 #include "solid.h"
35 
36 // The mesh
37 #include "meshes/simple_cubic_mesh.template.h"
38 
39 using namespace std;
40 
41 using namespace oomph;
42 
43 
44 /// ////////////////////////////////////////////////////////////////////
45 /// ////////////////////////////////////////////////////////////////////
46 /// ////////////////////////////////////////////////////////////////////
47 
48 //=========================================================================
49 /// Simple cubic mesh upgraded to become a solid mesh
50 //=========================================================================
51 template<class ELEMENT>
52 class ElasticCubicMesh : public virtual SimpleCubicMesh<ELEMENT>,
53  public virtual SolidMesh
54 {
55 
56 public:
57 
58  /// Constructor:
59  ElasticCubicMesh(const unsigned &nx, const unsigned &ny, const unsigned &nz,
60  const double &a, const double &b, const double &c,
61  TimeStepper* time_stepper_pt=&Mesh::Default_TimeStepper) :
62  SimpleCubicMesh<ELEMENT>(nx,ny,nz,-a,a,-b,b,-c,c,time_stepper_pt)
63  {
64  //Assign the initial lagrangian coordinates
65  set_lagrangian_nodal_coordinates();
66  }
67 
68  /// Empty Destructor
69  virtual ~ElasticCubicMesh() { }
70 
71 };
72 
73 
74 
75 
76 /// ////////////////////////////////////////////////////////////////////
77 /// ////////////////////////////////////////////////////////////////////
78 /// ////////////////////////////////////////////////////////////////////
79 
80 
81 
82 
83 //================================================================
84 /// Global variables
85 //================================================================
87 {
88  /// Pointer to strain energy function
89  StrainEnergyFunction* Strain_energy_function_pt;
90 
91  /// Pointer to constitutive law
92  ConstitutiveLaw* Constitutive_law_pt;
93 
94  /// Elastic modulus
95  double E=1.0;
96 
97  /// Poisson's ratio
98  double Nu=0.3;
99 
100  /// "Mooney Rivlin" coefficient for generalised Mooney Rivlin law
101  double C1=1.3;
102 
103  /// Body force
104  double Gravity=0.0;
105 
106  /// Body force vector: Vertically downwards with magnitude Gravity
107  void body_force(const Vector<double>& xi,
108  const double& t,
109  Vector<double>& b)
110  {
111  b[0]=0.0;
112  b[1]=-Gravity;
113  }
114 
115 }
116 
117 
118 /// ////////////////////////////////////////////////////////////////////
119 /// ////////////////////////////////////////////////////////////////////
120 /// ////////////////////////////////////////////////////////////////////
121 
122 
123 
124 //======================================================================
125 /// Boundary-driven elastic deformation of fish-shaped domain.
126 //======================================================================
127 template<class ELEMENT>
128 class SimpleShearProblem : public Problem
129 {
130  double Shear;
131 
132  void set_incompressible(ELEMENT *el_pt,const bool &incompressible);
133 
134 public:
135 
136  /// Constructor:
137  SimpleShearProblem(const bool &incompressible);
138 
139  /// Run simulation.
140  void run(const std::string &dirname);
141 
142  /// Access function for the mesh
144  {return dynamic_cast<ElasticCubicMesh<ELEMENT>*>(Problem::mesh_pt());}
145 
146  /// Doc the solution
147  void doc_solution(DocInfo& doc_info);
148 
149  /// Update function (empty)
151 
152  /// Update before solve: We're dealing with a static problem so
153  /// the nodal positions before the next solve merely serve as
154  /// initial conditions. For meshes that are very strongly refined
155  /// near the boundary, the update of the displacement boundary
156  /// conditions (which only moves the SolidNodes *on* the boundary),
157  /// can lead to strongly distorted meshes. This can cause the
158  /// Newton method to fail --> the overall method is actually more robust
159  /// if we use the nodal positions as determined by the Domain/MacroElement-
160  /// based mesh update as initial guesses.
162  {
163  apply_boundary_conditions();
164  bool update_all_solid_nodes=true;
165  mesh_pt()->node_update(update_all_solid_nodes);
166  }
167 
168  /// Shear the top
170  {
171  unsigned ibound = 5;
172  unsigned num_nod=mesh_pt()->nboundary_node(ibound);
173  for (unsigned inod=0;inod<num_nod;inod++)
174  {
175  SolidNode *solid_nod_pt = static_cast<SolidNode*>(
176  mesh_pt()->boundary_node_pt(ibound,inod));
177 
178  solid_nod_pt->x(0) = solid_nod_pt->xi(0) + Shear*
179  solid_nod_pt->xi(2);
180  }
181  }
182 
183 };
184 
185 //======================================================================
186 /// Constructor:
187 //======================================================================
188 template<class ELEMENT>
189 SimpleShearProblem<ELEMENT>::SimpleShearProblem(const bool &incompressible)
190  : Shear(0.0)
191 {
192  double a = 1.0, b = 1.0, c = 1.0;
193  unsigned nx = 5, ny = 5, nz = 5;
194 
195  // Build mesh
196  Problem::mesh_pt()=new ElasticCubicMesh<ELEMENT>(nx,ny,nz,a,b,c);
197 
198  //Loop over all boundaries
199  for(unsigned b=0;b<6;b++)
200  {
201  //Loop over nodes in the boundary
202  unsigned n_node = mesh_pt()->nboundary_node(b);
203  for(unsigned n=0;n<n_node;n++)
204  {
205  //Pin all nodes in the y and z directions to keep the motion in plane
206  for(unsigned i=1;i<3;i++)
207  {
208  mesh_pt()->boundary_node_pt(b,n)->pin_position(i);
209  }
210  //On the top and bottom pin the positions in x
211  if((b==0) || (b==5))
212  {
213  mesh_pt()->boundary_node_pt(b,n)->pin_position(0);
214  }
215  }
216  }
217 
218  //Loop over the elements in the mesh to set parameters/function pointers
219  unsigned n_element =mesh_pt()->nelement();
220  for(unsigned i=0;i<n_element;i++)
221  {
222  //Cast to a solid element
223  ELEMENT *el_pt = dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(i));
224 
225  // Set the constitutive law
226  el_pt->constitutive_law_pt() =
228 
229  set_incompressible(el_pt,incompressible);
230 
231  // Set the body force
232  //el_pt->body_force_fct_pt()=Global_Physical_Variables::body_force;
233  }
234 
235  // Pin the redundant solid pressures (if any)
236  //PVDEquationsBase<2>::pin_redundant_nodal_solid_pressures(
237  // mesh_pt()->element_pt());
238 
239  //Attach the boundary conditions to the mesh
240  cout << assign_eqn_numbers() << std::endl;
241 }
242 
243 
244 //==================================================================
245 /// Doc the solution
246 //==================================================================
247 template<class ELEMENT>
248 void SimpleShearProblem<ELEMENT>::doc_solution(DocInfo& doc_info)
249 {
250 
251  ofstream some_file;
252  char filename[100];
253 
254  // Number of plot points
255  unsigned npts = 5;
256 
257  // Output shape of deformed body
258  sprintf(filename,"%s/soln%i.dat",doc_info.directory().c_str(),
259  doc_info.number());
260  some_file.open(filename);
261  mesh_pt()->output(some_file,npts);
262  some_file.close();
263 
264  sprintf(filename,"%s/stress%i.dat", doc_info.directory().c_str(),
265  doc_info.number());
266  some_file.open(filename);
267  //Output the appropriate stress at the centre of each element
268  Vector<double> s(3,0.0);
269  Vector<double> x(3);
270  DenseMatrix<double> sigma(3,3);
271 
272  unsigned n_element = mesh_pt()->nelement();
273  for(unsigned e=0;e<n_element;e++)
274  {
275  ELEMENT* el_pt = dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(e));
276  el_pt->interpolated_x(s,x);
277  el_pt->get_stress(s,sigma);
278 
279  //Output
280  for(unsigned i=0;i<3;i++)
281  {
282  some_file << x[i] << " ";
283  }
284  for(unsigned i=0;i<3;i++)
285  {
286  for(unsigned j=0;j<3;j++)
287  {
288  some_file << sigma(i,j) << " ";
289  }
290  }
291  some_file << std::endl;
292  }
293  some_file.close();
294 
295 }
296 
297 
298 //==================================================================
299 /// Run the problem
300 //==================================================================
301 template<class ELEMENT>
302 void SimpleShearProblem<ELEMENT>::run(const std::string &dirname)
303 {
304 
305  // Output
306  DocInfo doc_info;
307 
308  // Set output directory
309  doc_info.set_directory(dirname);
310 
311  // Step number
312  doc_info.number()=0;
313 
314  // Initial parameter values
315 
316  // Gravity:
318 
319  //Parameter incrementation
320  unsigned nstep=2;
321  for(unsigned i=0;i<nstep;i++)
322  {
323  //Solve the problem with Newton's method, allowing for up to 5
324  //rounds of adaptation
325  newton_solve();
326 
327  // Doc solution
328  doc_solution(doc_info);
329  doc_info.number()++;
330  //Increase the shear
331  Shear += 0.5;
332  }
333 
334 }
335 
336 template<>
337 void SimpleShearProblem<QPVDElement<3,3> >::set_incompressible(
338  QPVDElement<3,3> *el_pt, const bool &incompressible)
339 {
340  //Does nothing
341 }
342 
343 
344 template<>
346  QPVDElementWithPressure<3> *el_pt, const bool &incompressible)
347 {
348  if(incompressible) {el_pt->set_incompressible();}
349  else {el_pt->set_compressible();}
350 }
351 
352 template<>
354 set_incompressible(
355  QPVDElementWithContinuousPressure<3> *el_pt, const bool &incompressible)
356 {
357  if(incompressible) {el_pt->set_incompressible();}
358  else {el_pt->set_compressible();}
359 }
360 
361 
362 //======================================================================
363 /// Driver for simple elastic problem
364 //======================================================================
365 int main()
366 {
367  //Initialise physical parameters
371 
372  for (unsigned i=0;i<2;i++)
373  {
374 
375  // Define a strain energy function: Generalised Mooney Rivlin
377  new GeneralisedMooneyRivlin(&Global_Physical_Variables::Nu,
380 
381  // Define a constitutive law (based on strain energy function)
383  new IsotropicStrainEnergyFunctionConstitutiveLaw(
385 
386  {
387  //Set up the problem with pure displacement formulation
388  SimpleShearProblem<QPVDElement<3,3> > problem(false);
389  problem.run("RESLT");
390  }
391 
392  //Discontinuous pressure
393  {
394  //Set up the problem with pure displacement formulation
396  problem.run("RESLT_pres");
397  }
398 
399  /*{
400  //Set up the problem with pure displacement formulation
401  SimpleShearProblem<QPVDElementWithPressure<3> > problem(true);
402  problem.run("RESLT_pres_incomp");
403  }*/
404 
405 
406  {
407  //Set up the problem with pure displacement formulation
409  problem.run("RESLT_cont_pres");
410  }
411 
412  /*{
413  //Set up the problem with pure displacement formulation
414  SimpleShearProblem<QPVDElementWithContinuousPressure<3> > problem(true);
415  problem.run("RESLT_cont_pres_incomp");
416  }*/
417 
418 
419  }
420 
421 
422 }
423 
424 
425 
426 
427 
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
Definition: simple_shear.cc:54
virtual ~ElasticCubicMesh()
Empty Destructor.
Definition: simple_shear.cc:69
ElasticCubicMesh(const unsigned &nx, const unsigned &ny, const unsigned &nz, const double &a, const double &b, const double &c, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor:
Definition: simple_shear.cc:59
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
void apply_boundary_conditions()
Shear the top.
void doc_solution(DocInfo &doc_info)
Doc the solution.
void actions_before_newton_solve()
Update before solve: We're dealing with a static problem so the nodal positions before the next solve...
RefineableElasticCubicMesh< ELEMENT > * mesh_pt()
Access function for the mesh.
void set_incompressible(ELEMENT *el_pt, const bool &incompressible)
void actions_after_newton_solve()
Update function (empty)
void run(const std::string &dirname)
Run simulation.
SimpleShearProblem(const bool &incompressible)
Constructor:
ElasticCubicMesh< ELEMENT > * mesh_pt()
Access function for the mesh.
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
void body_force(const Vector< double > &xi, const double &t, Vector< double > &b)
Body force vector: Vertically downwards with magnitude Gravity.
ConstitutiveLaw * Constitutive_law_pt
Pointer to constitutive law.
double C1
"Mooney Rivlin" coefficient for generalised Mooney Rivlin law
StrainEnergyFunction * Strain_energy_function_pt
Pointer to strain energy function.
int main()
Driver for simple elastic problem.