compressed_square.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 compressed square
27
28//Oomph-lib includes
29#include "generic.h"
30#include "solid.h"
31
32//The mesh
33#include "meshes/rectangular_quadmesh.h"
34
35using namespace std;
36
37using namespace oomph;
38
39namespace oomph
40{
41
42//=================start_wrapper==================================
43/// Wrapper class for solid element to modify the output
44//================================================================
45template <class ELEMENT>
46class MySolidElement : public virtual ELEMENT
47{
48
49public:
50
51 /// Constructor: Call constructor of underlying element
52 MySolidElement() : ELEMENT() {}
53
54 /// Overload output function
55 void output(std::ostream &outfile, const unsigned &n_plot)
56 {
57 Vector<double> s(2);
58 Vector<double> x(2);
59 Vector<double> xi(2);
60 DenseMatrix<double> sigma(2,2);
61
62 //Tecplot header info
63 outfile << "ZONE I=" << n_plot << ", J=" << n_plot << std::endl;
64
65 //Loop over plot points
66 for(unsigned l2=0;l2<n_plot;l2++)
67 {
68 s[1] = -1.0 + l2*2.0/(n_plot-1);
69 for(unsigned l1=0;l1<n_plot;l1++)
70 {
71 s[0] = -1.0 + l1*2.0/(n_plot-1);
72
73 // Get Eulerian and Lagrangian coordinates and the stress
74 this->interpolated_x(s,x);
75 this->interpolated_xi(s,xi);
76 this->get_stress(s,sigma);
77
78 //Output the x,y coordinates
79 for(unsigned i=0;i<2;i++)
80 {outfile << x[i] << " ";}
81
82 // Output displacements, the difference between Eulerian and Lagrangian
83 // coordinates
84 for(unsigned i=0;i<2;i++)
85 {outfile << x[i]-xi[i] << " ";}
86
87 //Output stress
88 outfile << sigma(0,0) << " "
89 << sigma(1,0) << " "
90 << sigma(1,1) << " "
91 << std::endl;
92 }
93 }
94 }
95};
96
97} //end namespace extension
98
99
100
101///////////////////////////////////////////////////////////////////////
102///////////////////////////////////////////////////////////////////////
103///////////////////////////////////////////////////////////////////////
104
105
106
107//=======start_namespace==========================================
108/// Global variables
109//================================================================
111{
112
113 /// Pointer to constitutive law
114 ConstitutiveLaw* Constitutive_law_pt=0;
115
116 /// Poisson's ratio for Hooke's law
117 double Nu=0.45;
118
119 /// Pointer to strain energy function
120 StrainEnergyFunction* Strain_energy_function_pt=0;
121
122 /// First "Mooney Rivlin" coefficient for generalised Mooney Rivlin law
123 double C1=1.3;
124
125 /// Second "Mooney Rivlin" coefficient for generalised Mooney Rivlin law
126 double C2=1.3;
127
128 /// Non-dim gravity
129 double Gravity=0.0;
130
131 /// Non-dimensional gravity as body force
132 void gravity(const double& time,
133 const Vector<double> &xi,
134 Vector<double> &b)
135 {
136 b[0]=0.0;
137 b[1]=-Gravity;
138 }
139
140} //end namespace
141
142
143
144//=============begin_problem============================================
145/// Problem class
146//======================================================================
147template<class ELEMENT>
148class CompressedSquareProblem : public Problem
149{
150
151public:
152
153 /// Constructor: Pass flag that determines if we want to use
154 /// a true incompressible formulation
155 CompressedSquareProblem(const bool& incompress);
156
157 /// Update function (empty)
159
160 /// Update function (empty)
162
163 /// Doc the solution & exact (linear) solution for compressible
164 /// or incompressible materials
165 void doc_solution(const bool& incompress);
166
167 /// Run the job -- doc in RESLTi_case
168 void run_it(const int& i_case,const bool& incompress);
169
170private:
171
172 /// Trace file
173 ofstream Trace_file;
174
175 /// Pointers to node whose position we're tracing
177
178 /// DocInfo object for output
179 DocInfo Doc_info;
180
181};
182
183
184//===========start_of_constructor=======================================
185/// Constructor: Pass flag that determines if we want to enforce
186/// incompressibility
187//======================================================================
188template<class ELEMENT>
190 const bool& incompress)
191{
192
193 // Create the mesh
194
195 // # of elements in x-direction
196 unsigned n_x=5;
197
198 // # of elements in y-direction
199 unsigned n_y=5;
200
201 // Domain length in x-direction
202 double l_x=1.0;
203
204 // Domain length in y-direction
205 double l_y=1.0;
206
207 //Now create the mesh
208 mesh_pt() = new ElasticRectangularQuadMesh<ELEMENT>(n_x,n_y,l_x,l_y);
209
210
211 //Assign the physical properties to the elements
212 unsigned n_element=mesh_pt()->nelement();
213 for(unsigned i=0;i<n_element;i++)
214 {
215 //Cast to a solid element
216 ELEMENT *el_pt = dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(i));
217
218 // Set the constitutive law
219 el_pt->constitutive_law_pt() =
221
222 //Set the body force
223 el_pt->body_force_fct_pt() = Global_Physical_Variables::gravity;
224
225
226 // Is the element based on the pressure/displacement formulation?
227 PVDEquationsWithPressure<2>* test_pt =
228 dynamic_cast<PVDEquationsWithPressure<2>*>(mesh_pt()->element_pt(i));
229 if (test_pt!=0)
230 {
231 // Do we want true incompressibility (formulation III in the
232 // associated tutorial) or not (formulation II)
233 if (incompress)
234 {
235 test_pt->set_incompressible();
236 }
237 else
238 {
239 // Note that this assignment isn't strictly necessary as it's the
240 // default setting, but it doesn't do any harm to be explicit.
241 test_pt->set_compressible();
242 }
243 }
244 } // end compressibility
245
246
247 // Choose a control node: The last node in the solid mesh
248 unsigned nnod=mesh_pt()->nnode();
249 Trace_node_pt=mesh_pt()->node_pt(nnod-1);
250
251// Pin the left and right boundaries (1 and 2) in the horizontal directions
252 for (unsigned b=1;b<4;b+=2)
253 {
254 unsigned nnod = mesh_pt()->nboundary_node(b);
255 for(unsigned i=0;i<nnod;i++)
256 {
257 dynamic_cast<SolidNode*>(
258 mesh_pt()->boundary_node_pt(b,i))->pin_position(0);
259 }
260 }
261
262// Pin the bottom boundary (0) in the vertical direction
263 unsigned b=0;
264 {
265 unsigned nnod= mesh_pt()->nboundary_node(b);
266 for(unsigned i=0;i<nnod;i++)
267 {
268 dynamic_cast<SolidNode*>(
269 mesh_pt()->boundary_node_pt(b,i))->pin_position(1);
270 }
271 }
272
273 //Assign equation numbers
274 assign_eqn_numbers();
275
276} //end of constructor
277
278
279
280//==============start_doc===========================================
281/// Doc the solution
282//==================================================================
283template<class ELEMENT>
285{
286 ofstream some_file;
287 char filename[100];
288
289 // Number of plot points
290 unsigned n_plot = 5;
291
292 // Output shape of and stress in deformed body
293 snprintf(filename, sizeof(filename), "%s/soln%i.dat",Doc_info.directory().c_str(),
294 Doc_info.number());
295 some_file.open(filename);
296 mesh_pt()->output(some_file,n_plot);
297 some_file.close();
298
299 // Write trace file: Load/displacement characteristics
300 Trace_file << Global_Physical_Variables::Gravity << " "
301 << Trace_node_pt->x(0) << " "
302 << Trace_node_pt->x(1) << " "
303 << std::endl;
304
305
306 // Output exact solution for linear elasticity
307 // -------------------------------------------
308 snprintf(filename, sizeof(filename), "%s/exact_soln%i.dat",Doc_info.directory().c_str(),
309 Doc_info.number());
310 some_file.open(filename);
311 unsigned nelem=mesh_pt()->nelement();
312 Vector<double> s(2);
313 Vector<double> x(2);
314 DenseMatrix<double> sigma(2,2);
315
316 // Poisson's ratio
318 if (incompress) nu=0.5;
319
320 // Loop over all elements
321 for (unsigned e=0;e<nelem;e++)
322 {
323 //Cast to a solid element
324 ELEMENT* el_pt = dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(e));
325
326 //Tecplot header info
327 some_file << "ZONE I=" << n_plot << ", J=" << n_plot << std::endl;
328
329 //Loop over plot points
330 for(unsigned l2=0;l2<n_plot;l2++)
331 {
332 s[1] = -1.0 + l2*2.0/(n_plot-1);
333 for(unsigned l1=0;l1<n_plot;l1++)
334 {
335 s[0] = -1.0 + l1*2.0/(n_plot-1);
336
337 // Get Lagrangian coordinates
338 el_pt->interpolated_x(s,x);
339
340 // Output the x,y,..
341 for(unsigned i=0;i<2;i++)
342 {some_file << x[i] << " ";}
343
344 // Exact vertical displacement
346 (1.0+nu)*(1.0-2*nu)/(1.0-nu)*(0.5*x[1]*x[1]-x[1]);
347
348 // x and y displacement
349 some_file << "0.0 " << v_exact << " ";
350
351 // Stresses
352 sigma(0,0)=nu/(1.0-nu)*Global_Physical_Variables::Gravity*(x[1]-1.0);
353 sigma(1,0)=0.0;
354 sigma(1,1)=Global_Physical_Variables::Gravity*(x[1]-1.0);
355
356 // Output linear stress tensor
357 some_file << sigma(0,0) << " "
358 << sigma(1,0) << " "
359 << sigma(1,1) << " "
360 << std::endl;
361 }
362 }
363 }
364 some_file.close();
365
366 // Increment label for output files
367 Doc_info.number()++;
368
369} //end doc
370
371
372
373
374
375//==============start_run_it========================================
376/// Run it
377//==================================================================
378template<class ELEMENT>
380 const bool& incompress)
381{
382
383 // Set output directory
384 char dirname[100];
385 snprintf(dirname, sizeof(dirname), "RESLT%i",i_case);
386 Doc_info.set_directory(dirname);
387
388 // Open trace file
389 char filename[100];
390 snprintf(filename, sizeof(filename), "%s/trace.dat",Doc_info.directory().c_str());
391 Trace_file.open(filename);
392
393
394 // Doc initial configuration
395 doc_solution(incompress);
396
397 // Initial values for parameter values
399
400 //Parameter incrementation
401 unsigned nstep=1;
402 double g_increment=1.0e-2;
403 for(unsigned i=0;i<nstep;i++)
404 {
405 // Bump up gravity
407
408 // Solve
409 newton_solve();
410
411 // Doc solution
412 doc_solution(incompress);
413 }
414
415}
416
417
418//=======start_of_main==================================================
419/// Driver for compressed square
420//======================================================================
421int main()
422{
423
424 //Flag to indicate if we want the material to be incompressible
425 bool incompress=false;
426
427 // Label for different cases
428 int case_number=-1;
429
430 // Generalised Hookean constitutive equations
431 //===========================================
432 {
433 // Nu values
434 Vector<double> nu_value(3);
435 nu_value[0]=0.45;
436 nu_value[1]=0.499999;
437 nu_value[2]=0.5;
438
439 // Loop over nu values
440 for (unsigned i=0;i<3;i++)
441 {
442 // Set Poisson ratio
444
445 std::cout << "===========================================\n";
446 std::cout << "Doing Nu=" << Global_Physical_Variables::Nu
447 << std::endl;
448 std::cout << "===========================================\n";
449
450 // Create constitutive equation
452 new GeneralisedHookean(&Global_Physical_Variables::Nu);
453
454 // Displacement-based formulation
455 //--------------------------------
456 // (not for nu=1/2, obviously)
457 if (i!=2)
458 {
459 case_number++;
460 std::cout
461 << "Doing Generalised Hookean with displacement formulation: Case "
462 << case_number << std::endl;
463
464 //Set up the problem with pure displacement based elements
465 incompress=false;
467 problem(incompress);
468
469 // Run it
470 problem.run_it(case_number,incompress);
471 }
472
473
474 // Generalised Hookean with continuous pressure, compressible
475 //-----------------------------------------------------------
476 {
477 case_number++;
478 std::cout
479 << "Doing Generalised Hookean with displacement/cont pressure "
480 << "formulation: Case " << case_number << std::endl;
481
482 //Set up the problem with continous pressure/displacement
483 incompress=false;
485 QPVDElementWithContinuousPressure<2> > >
486 problem(incompress);
487
488 // Run it
489 problem.run_it(case_number,incompress);
490 }
491
492
493 // Generalised Hookean with discontinuous pressure, compressible
494 //--------------------------------------------------------------
495 {
496 case_number++;
497 std::cout
498 << "Doing Generalised Hookean with displacement/discont pressure "
499 << "formulation: Case " << case_number << std::endl;
500
501 //Set up the problem with discontinous pressure/displacement
503 QPVDElementWithPressure<2> > > problem(incompress);
504
505 // Run it
506 problem.run_it(case_number,incompress);
507 }
508
509
510
511 // Generalised Hookean with continous pressure/displacement;
512 //----------------------------------------------------------
513 // incompressible
514 //---------------
515 {
516 case_number++;
517 std::cout
518 << "Doing Generalised Hookean with displacement/cont pressure, "
519 << "incompressible formulation: Case " << case_number << std::endl;
520
521 //Set up the problem with continous pressure/displacement
522 incompress=true;
524 QPVDElementWithContinuousPressure<2> > >
525 problem(incompress);
526
527 // Run it
528 problem.run_it(case_number,incompress);
529 }
530
531
532 // Generalised Hookean with discontinous pressure/displacement;
533 //-------------------------------------------------------------
534 // incompressible
535 //---------------
536 {
537 case_number++;
538 std::cout
539 << "Doing Generalised Hookean with displacement/discont pressure, "
540 << "incompressible formulation: Case " << case_number << std::endl;
541
542 //Set up the problem with discontinous pressure/displacement
543 incompress=true;
545 QPVDElementWithPressure<2> > > problem(incompress);
546
547 // Run it
548 problem.run_it(case_number,incompress);
549 }
550
551 // Clean up
554
555 }
556
557 } // end generalised Hookean
558
559
560 // Incompressible Mooney Rivlin
561 //=============================
562 {
563
564 // Create strain energy function
566 new MooneyRivlin(&Global_Physical_Variables::C1,
568
569 // Define a constitutive law (based on strain energy function)
571 new IsotropicStrainEnergyFunctionConstitutiveLaw(
573
574
575 // Mooney-Rivlin with continous pressure/displacement;
576 //----------------------------------------------------
577 // incompressible
578 //---------------
579 {
580 case_number++;
581 std::cout
582 << "Doing Mooney Rivlin with cont pressure formulation: Case "
583 << case_number << std::endl;
584
585 //Set up the problem with continous pressure/displacement
586 incompress=true;
588 QPVDElementWithContinuousPressure<2> > >
589 problem(incompress);
590
591 // Run it
592 problem.run_it(case_number,incompress);
593 }
594
595
596 // Mooney-Rivlin with discontinous pressure/displacement;
597 //-------------------------------------------------------
598 // incompressible
599 //---------------
600 {
601 case_number++;
602 std::cout
603 << "Doing Mooney Rivlin with discont pressure formulation: Case "
604 << case_number << std::endl;
605
606 //Set up the problem with discontinous pressure/displacement
607 incompress=true;
609 QPVDElementWithPressure<2> > >
610 problem(incompress);
611
612 // Run it
613 problem.run_it(case_number,incompress);
614 }
615
616
617 // Clean up
620
623
624 }
625
626} //end of main
627
628
629
630
631
632
633
634
Node * Trace_node_pt
Pointers to node whose position we're tracing.
void run_it(const int &i_case, const bool &incompress)
Run the job – doc in RESLTi_case.
DocInfo Doc_info
DocInfo object for output.
void doc_solution(const bool &incompress)
Doc the solution & exact (linear) solution for compressible or incompressible materials.
void actions_before_newton_solve()
Update function (empty)
CompressedSquareProblem(const bool &incompress)
Constructor: Pass flag that determines if we want to use a true incompressible formulation.
ofstream Trace_file
Trace file.
void actions_after_newton_solve()
Update function (empty)
Wrapper class for solid element to modify the output.
void output(std::ostream &outfile, const unsigned &n_plot)
Overload output function.
MySolidElement()
Constructor: Call constructor of underlying element.
int main()
Driver for compressed square.
void gravity(const double &time, const Vector< double > &xi, Vector< double > &b)
Non-dimensional gravity as body force.
ConstitutiveLaw * Constitutive_law_pt
Pointer to constitutive law.
double Nu
Poisson's ratio for Hooke's law.
StrainEnergyFunction * Strain_energy_function_pt
Pointer to strain energy function.
double C1
First "Mooney Rivlin" coefficient for generalised Mooney Rivlin law.
double Gravity
Non-dim gravity.
double C2
Second "Mooney Rivlin" coefficient for generalised Mooney Rivlin law.