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-2025 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.h"
38
39using namespace std;
40
41using namespace oomph;
42
43
44///////////////////////////////////////////////////////////////////////
45///////////////////////////////////////////////////////////////////////
46///////////////////////////////////////////////////////////////////////
47
48//=========================================================================
49/// Simple cubic mesh upgraded to become a solid mesh
50//=========================================================================
51template<class ELEMENT>
52class ElasticCubicMesh : public virtual SimpleCubicMesh<ELEMENT>,
53 public virtual SolidMesh
54{
55
56public:
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//======================================================================
127template<class ELEMENT>
128class SimpleShearProblem : public Problem
129{
130 double Shear;
131
132 void set_incompressible(ELEMENT *el_pt,const bool &incompressible);
133
134public:
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 {
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//======================================================================
188template<class ELEMENT>
189SimpleShearProblem<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 oomph_info << "Number of equations: " << assign_eqn_numbers() << std::endl;
241}
242
243
244//==================================================================
245/// Doc the solution
246//==================================================================
247template<class ELEMENT>
248void 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 snprintf(filename, sizeof(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 snprintf(filename, sizeof(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//==================================================================
301template<class ELEMENT>
302void 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
336template<>
337void SimpleShearProblem<QPVDElement<3,3> >::set_incompressible(
338 QPVDElement<3,3> *el_pt, const bool &incompressible)
339{
340 //Does nothing
341}
342
343
344template<>
346 QPVDElementWithPressure<3> *el_pt, const bool &incompressible)
347{
348 if(incompressible) {el_pt->set_incompressible();}
349 else {el_pt->set_compressible();}
350}
351
352template<>
354set_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//======================================================================
365int 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
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
Simple cubic mesh upgraded to become a solid mesh.
virtual ~ElasticCubicMesh()
Empty Destructor.
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:
Boundary-driven elastic deformation of fish-shaped domain.
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...
void set_incompressible(ELEMENT *el_pt, const bool &incompressible)
RefineableElasticCubicMesh< ELEMENT > * mesh_pt()
Access function for the mesh.
void actions_after_newton_solve()
Update function (empty)
ElasticCubicMesh< ELEMENT > * mesh_pt()
Access function for the mesh.
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.