unsteady_ring.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 code for a large-amplitude ring oscillation
27
28//Generic stuff
29#include "generic.h"
30
31// The beam equations
32#include "beam.h"
33
34// The mesh
35#include "meshes/one_d_lagrangian_mesh.h"
36
37using namespace std;
38
39using namespace oomph;
40
41
42////////////////////////////////////////////////////////////////////////
43////////////////////////////////////////////////////////////////////////
44////////////////////////////////////////////////////////////////////////
45
46
47//====start_of_namespace============================
48/// Namespace for global parameters
49//==================================================
51{
52
53 /// Perturbation pressure
54 double Pcos;
55
56 /// Duration of transient load
57 double T_kick;
58
59 /// Load function: Perturbation pressure to force non-axisymmetric deformation
60 void press_load(const Vector<double>& xi,
61 const Vector<double> &x,
62 const Vector<double>& N,
63 Vector<double>& load)
64 {
65 for(unsigned i=0;i<2;i++)
66 {
67 load[i] = -Pcos*cos(2.0*xi[0])*N[i];
68 }
69 } //end of load
70
71
72 /// Scaling factor for wall thickness (to be used in an exercise)
73 double Alpha=1.0;
74
75 /// Wall thickness -- 1/20 for default value of scaling factor
76 double H=Alpha*1.0/20.0;
77
78 /// Square of timescale ratio (i.e. non-dimensional density)
79 /// -- 1.0 for default value of scaling factor
80 double Lambda_sq=pow(Alpha,2);
81
82} // end of namespace
83
84
85
86
87
88/////////////////////////////////////////////////////////////////////
89/////////////////////////////////////////////////////////////////////
90/////////////////////////////////////////////////////////////////////
91
92
93
94//===start_of_problem_class=============================================
95/// Ring problem
96//======================================================================
97template<class ELEMENT, class TIMESTEPPER>
98class ElasticRingProblem : public Problem
99{
100
101public:
102
103 /// Constructor: Number of elements
104 ElasticRingProblem(const unsigned& n_element);
105
106 /// Access function for the specific mesh
107 OneDLagrangianMesh<ELEMENT>* mesh_pt()
108 {
109 return dynamic_cast<OneDLagrangianMesh<ELEMENT>*>(Problem::mesh_pt());
110 }
111
112 /// Update function is empty
114
115 /// Update function is empty
117
118 /// Setup initial conditions
120
121 /// Doc solution
122 void doc_solution(DocInfo& doc_info);
123
124 /// Do unsteady run
126
127 /// Dump problem-specific parameter values, then dump
128 /// generic problem data.
129 void dump_it(ofstream& dump_file);
130
131 /// Read problem-specific parameter values, then recover
132 /// generic problem data.
133 void restart(ifstream& restart_file);
134
135
136private:
137
138 /// Trace file for recording control data
139 ofstream Trace_file;
140
141 /// Flag for validation run: Default: 0 = no validation run
143
144 /// Restart flag specified via command line?
146
147}; // end of problem class
148
149
150
151
152
153//===start_of_constructor===============================================
154/// Constructor for elastic ring problem
155//======================================================================
156template<class ELEMENT,class TIMESTEPPER>
158(const unsigned& n_element) :
159 Validation_run_flag(0), //default: false
160 Restart_flag(false)
161{
162
163 // Create the timestepper and add it to the Problem's collection of
164 // timesteppers -- this creates the Problem's Time object.
165 add_time_stepper_pt(new TIMESTEPPER());
166
167 // Undeformed beam is an ellipse with unit axes
168 GeomObject* undef_geom_pt=new Ellipse(1.0,1.0);
169
170 //Length of domain
171 double length = MathematicalConstants::Pi/2.0;
172
173 //Now create the (Lagrangian!) mesh
174 Problem::mesh_pt() = new OneDLagrangianMesh<ELEMENT>(
175 n_element,length,undef_geom_pt,Problem::time_stepper_pt());
176
177 // Boundary condition:
178
179 // Bottom:
180 unsigned ibound=0;
181 // No vertical displacement
182 mesh_pt()->boundary_node_pt(ibound,0)->pin_position(1);
183 // Zero slope: Pin type 1 (slope) dof for displacement direction 0
184 mesh_pt()->boundary_node_pt(ibound,0)->pin_position(1,0);
185
186 // Top:
187 ibound=1;
188 // No horizontal displacement
189 mesh_pt()->boundary_node_pt(ibound,0)->pin_position(0);
190 // Zero slope: Pin type 1 (slope) dof for displacement direction 1
191 mesh_pt()->boundary_node_pt(ibound,0)->pin_position(1,1);
192
193 // Complete build of all elements so they are fully functional
194 // -----------------------------------------------------------
195
196 //Loop over the elements to set physical parameters etc.
197 for(unsigned i=0;i<n_element;i++)
198 {
199 // Cast to proper element type
200 ELEMENT *elem_pt = dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(i));
201
202 // Pass pointer to square of timescale ratio (non-dimensional density)
203 elem_pt->lambda_sq_pt() = &Global_Physical_Variables::Lambda_sq;
204
205 // Pass pointer to non-dimensional wall thickness
206 elem_pt->h_pt() = &Global_Physical_Variables::H;
207
208 // Function that specifies load vector
209 elem_pt->load_vector_fct_pt() = &Global_Physical_Variables::press_load;
210
211 // Assign the undeformed surface
212 elem_pt->undeformed_beam_pt() = undef_geom_pt;
213 }
214
215 // Do equation numbering
216 cout << "# of dofs " << assign_eqn_numbers() << std::endl;
217
218} // end of constructor
219
220
221
222
223//====start_of_doc_solution===============================================
224/// Document solution
225//========================================================================
226template<class ELEMENT, class TIMESTEPPER>
228 DocInfo& doc_info)
229{
230
231 cout << "Doc-ing step " << doc_info.number()
232 << " for time " << time_stepper_pt()->time_pt()->time() << std::endl;
233
234
235 // Loop over all elements to get global kinetic and potential energy
236 unsigned n_elem=mesh_pt()->nelement();
237 double global_kin=0;
238 double global_pot=0;
239 double pot,kin;
240 for (unsigned ielem=0;ielem<n_elem;ielem++)
241 {
242 dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(ielem))->get_energy(pot,kin);
243 global_kin+=kin;
244 global_pot+=pot;
245 }
246
247
248 // Get pointer to last element to document displacement
249 FiniteElement* trace_elem_pt=mesh_pt()->finite_element_pt(n_elem-1);
250
251 // Vector of local coordinates at control point
252 Vector<double> s_trace(1);
253 s_trace[0]=1.0;
254
255 // Write trace file: Time, control position, energies
256 Trace_file << time_pt()->time() << " "
257 << trace_elem_pt->interpolated_x(s_trace,1)
258 << " " << global_pot << " " << global_kin
259 << " " << global_pot + global_kin
260 << std::endl; // end of output to trace file
261
262 ofstream some_file;
263 char filename[100];
264
265 // Number of plot points
266 unsigned npts=5;
267
268 // Output solution
269 snprintf(filename, sizeof(filename), "%s/ring%i.dat",doc_info.directory().c_str(),
270 doc_info.number());
271 some_file.open(filename);
272 mesh_pt()->output(some_file,npts);
273
274 // Write file as a tecplot text object
275 some_file << "TEXT X=2.5,Y=93.6,F=HELV,HU=POINT,C=BLUE,H=26,T=\"time = "
276 << time_pt()->time() << "\"";
277
278 // ...and draw a horizontal line whose length is proportional
279 // to the elapsed time
280 some_file << "GEOMETRY X=2.5,Y=98,T=LINE,C=BLUE,LT=0.4" << std::endl;
281 some_file << "1" << std::endl;
282 some_file << "2" << std::endl;
283 some_file << " 0 0" << std::endl;
284 some_file << time_pt()->time()*20.0 << " 0" << std::endl;
285 some_file.close();
286
287
288 // Loop over all elements do dump out previous solutions
289 unsigned nsteps=time_stepper_pt()->nprev_values();
290 for (unsigned t=0;t<=nsteps;t++)
291 {
292 snprintf(filename, sizeof(filename), "%s/ring%i-%i.dat",doc_info.directory().c_str(),
293 doc_info.number(),t);
294 some_file.open(filename);
295 unsigned n_elem=mesh_pt()->nelement();
296 for (unsigned ielem=0;ielem<n_elem;ielem++)
297 {
298 dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(ielem))->
299 output(t,some_file,npts);
300 }
301 some_file.close();
302 } // end of output of previous solutions
303
304
305 // Write restart file
306 snprintf(filename, sizeof(filename), "%s/ring_restart%i.dat",doc_info.directory().c_str(),
307 doc_info.number());
308 some_file.open(filename);
309 dump_it(some_file);
310 some_file.close();
311
312
313} // end of doc solution
314
315
316
317
318
319
320//===start_of_dump_it====================================================
321/// Dump problem-specific parameter values, then dump
322/// generic problem data.
323//=======================================================================
324template<class ELEMENT,class TIMESTEPPER>
326
327{
328
329 // Write Pcos
330 dump_file << Global_Physical_Variables::Pcos << " # Pcos" << std::endl;
331
332 // Write validation run flag
333 dump_file << Validation_run_flag
334 << " # Validation run flag" << std::endl;
335
336 // Call generic dump()
337 Problem::dump(dump_file);
338
339} // end of dump it
340
341
342//==start_of_restart=====================================================
343/// Read problem-specific parameter values, then recover
344/// generic problem data.
345//=======================================================================
346template<class ELEMENT,class TIMESTEPPER>
348{
349
350 string input_string;
351
352 // Read line up to termination sign
353 getline(restart_file,input_string,'#');
354 // Ignore rest of line
355 restart_file.ignore(80,'\n');
356 // Read in pcos
357 Global_Physical_Variables::Pcos=atof(input_string.c_str());
358
359 // Read line up to termination sign
360 getline(restart_file,input_string,'#');
361 // Ignore rest of line
362 restart_file.ignore(80,'\n');
363 // Read in Long run flag
364 Validation_run_flag=
365 unsigned(atof(input_string.c_str()));
366
367 // Call generic read()
368 Problem::read(restart_file);
369
370} // end of restart
371
372
373
374
375//=====start_of_set_ic=====================================================
376/// Setup initial conditions -- either restart from solution
377/// specified via command line or impulsive start.
378//=========================================================================
379template<class ELEMENT,class TIMESTEPPER>
381{
382
383 // No restart file --> impulsive start from initial configuration
384 // assigned in the Lagrangian mesh.
385 if (!Restart_flag)
386 {
387 // Set initial timestep
388 double dt=1.0;
389
390 // Assign impulsive start
391 assign_initial_values_impulsive(dt);
392 }
393 // Restart file specified via command line
394 else
395 {
396 // Try to open restart file
397 ifstream* restart_file_pt=
398 new ifstream(CommandLineArgs::Argv[2],ios_base::in);
399 if (restart_file_pt!=0)
400 {
401 cout << "Have opened " << CommandLineArgs::Argv[2] <<
402 " for restart. " << std::endl;
403 }
404 else
405 {
406 std::ostringstream error_stream;
407 error_stream << "ERROR while trying to open "
408 << CommandLineArgs::Argv[2]
409 << " for restart." << std::endl;
410
411 throw OomphLibError(error_stream.str(),
412 OOMPH_CURRENT_FUNCTION,
413 OOMPH_EXCEPTION_LOCATION);
414 }
415
416 // Read restart data:
417 restart(*restart_file_pt);
418
419 }
420
421} // end of set ic
422
423
424
425//===start_of_unsteady_run=================================================
426/// Solver loop to perform unsteady run.
427//=========================================================================
428template<class ELEMENT,class TIMESTEPPER>
430{
431
432 // Convert command line arguments (if any) into flags:
433 //----------------------------------------------------
434
435 if (CommandLineArgs::Argc<2)
436 {
437 cout << "No command line arguments -- using defaults."
438 << std::endl;
439 }
440 else if (CommandLineArgs::Argc==2)
441 {
442 // Flag for validation run
443 Validation_run_flag=atoi(CommandLineArgs::Argv[1]);
444 }
445 else if (CommandLineArgs::Argc==3)
446 {
447 // Flag for validation run
448 Validation_run_flag=atoi(CommandLineArgs::Argv[1]);
449
450 // Second argument is restart file. If it's there we're performing
451 // a restart
452 Restart_flag=true;
453 }
454 else
455 {
456 std::string error_message =
457 "Wrong number of command line arguments. Specify two or fewer.\n";
458 error_message += "Arg1: Validation_run_flag [0/1] for [false/true]\n";
459 error_message += "Arg2: Name of restart_file (optional)\n";
460 error_message += "No arguments specified --> default run\n";
461
462 throw OomphLibError(error_message,
463 OOMPH_CURRENT_FUNCTION,
464 OOMPH_EXCEPTION_LOCATION);
465 }
466
467
468 // Label for output
469 DocInfo doc_info;
470
471 // Output directory
472 doc_info.set_directory("RESLT");
473
474 // Step number
475 doc_info.number()=0;
476
477 // Set up trace file
478 char filename[100];
479 snprintf(filename, sizeof(filename), "%s/trace_ring.dat",doc_info.directory().c_str());
480 Trace_file.open(filename);
481
482 Trace_file << "VARIABLES=\"time\",\"R<sub>ctrl</sub>\",\"E<sub>pot</sub>\"";
483 Trace_file << ",\"E<sub>kin</sub>\",\"E<sub>kin</sub>+E<sub>pot</sub>\""
484 << std::endl;
485
486 // Perturbation pressure -- incl. scaling factor (Alpha=1.0 by default)
489
490 // Duration of transient load
492
493 // Number of steps
494 unsigned nstep=600;
495 if (Validation_run_flag==1) {nstep=10;}
496
497 // Setup initial condition (either restart or impulsive start)
498 set_initial_conditions();
499
500 // Extract initial timestep as set up in set_initial_conditions()
501 double dt=time_pt()->dt();
502
503 // Output initial data
504 doc_solution(doc_info);
505
506 // If the run is restarted, dt() contains the size of the timestep
507 // that was taken to reach the dumped solution. In a non-restarted run
508 // the next step would have been taken with a slightly smaller
509 // timestep (see below). For a restarted run we therefore adjust
510 // the next timestep accordingly.
511 if (Restart_flag&&(time_pt()->time()>10.0)&&(time_pt()->time()<100.0))
512 {
513 dt=0.995*dt;
514 }
515
516 // Time integration loop
517 for(unsigned i=1;i<=nstep;i++)
518 {
519 // Switch off perturbation pressure
520 if (time_pt()->time()>Global_Physical_Variables::T_kick)
521 {
522 /// Perturbation pressure
524 }
525
526 // Solve
527 unsteady_newton_solve(dt);
528
529 // Doc solution
530 doc_info.number()++;
531 doc_solution(doc_info);
532
533 // Reduce timestep for the next solve
534 if ((time_pt()->time()>10.0)&&(time_pt()->time()<100.0))
535 {
536 dt=0.995*dt;
537 }
538
539 }
540
541} // end of unsteady run
542
543
544
545
546//===start_of_main=====================================================
547/// Driver for oscillating ring problem
548//=====================================================================
549int main(int argc, char* argv[])
550{
551
552 // Store command line arguments
553 CommandLineArgs::setup(argc,argv);
554
555 // Number of elements
556 unsigned nelem = 13;
557
558 //Set up the problem
560
561 // Do unsteady run
562 problem.unsteady_run();
563
564} // end of main
565
566
567
568
569
570
571
572
Oscillating ring problem: Compare small-amplitude oscillations against analytical solution of the lin...
void restart(ifstream &restart_file)
Read problem-specific parameter values, then recover generic problem data.
unsigned Validation_run_flag
Flag for validation run: Default: 0 = no validation run.
ElasticRingProblem(const unsigned &N, const double &L)
Constructor: Number of elements, length of domain, flag for setting Newmark IC directly or consistent...
void dump_it(ofstream &dump_file)
Dump problem-specific parameter values, then dump generic problem data.
bool Restart_flag
Restart flag specified via command line?
ofstream Trace_file
Trace file for recording control data.
void doc_solution(DocInfo &doc_info)
Doc solution.
void actions_before_newton_solve()
Update function is empty.
void actions_after_newton_solve()
Update function is empty.
void set_initial_conditions()
Setup initial conditions.
OneDLagrangianMesh< ELEMENT > * mesh_pt()
Access function for the specific mesh.
void unsteady_run()
Do unsteady run.
Namespace for physical parameters.
double Lambda_sq
Square of timescale ratio (i.e. non-dimensional density) – 1.0 for default value of scaling factor.
void press_load(const Vector< double > &xi, const Vector< double > &x, const Vector< double > &N, Vector< double > &load)
Load function: Perturbation pressure to force non-axisymmetric deformation.
double T_kick
Duration of transient load.
double Alpha
Scaling factor for wall thickness (to be used in an exercise)
double Pcos
Perturbation pressure.
double H
Wall thickness – 1/20 for default value of scaling factor.
int main(int argc, char *argv[])
Driver for oscillating ring problem.