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