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-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// 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.h"
40
41using namespace std;
42
43using namespace oomph;
44
45
46///////////////////////////////////////////////////////////////////////
47///////////////////////////////////////////////////////////////////////
48///////////////////////////////////////////////////////////////////////
49
50//=========================================================================
51/// Simple cubic mesh upgraded to become a solid mesh
52//=========================================================================
53template<class ELEMENT>
54class RefineableElasticCubicMesh : public virtual SimpleCubicMesh<ELEMENT>,
55 public virtual RefineableBrickMesh<ELEMENT>,
56 public virtual SolidMesh
57{
58
59public:
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//======================================================================
136template<class ELEMENT>
137class SimpleShearProblem : public Problem
138{
139 double Shear;
140
141 void set_incompressible(ELEMENT *el_pt,const bool &incompressible);
142
143public:
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 {
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//======================================================================
239template<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//==================================================================
280template<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 snprintf(filename, sizeof(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 snprintf(filename, sizeof(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//==================================================================
334template<class ELEMENT>
335void 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
378template<class ELEMENT>
380 ELEMENT *el_pt, const bool &incompressible)
381{
382 //Does nothing
383}
384
385
386template<>
388 QPVDElementWithPressure<3> *el_pt, const bool &incompressible)
389{
390 if(incompressible) {el_pt->set_incompressible();}
391 else {el_pt->set_compressible();}
392}
393
394template<>
396set_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//======================================================================
407int 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
Simple cubic mesh upgraded to become a solid mesh.
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:
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_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.