lin_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 for small amplitude ring oscillations
27
28//OOMPH-LIB includes
29#include "generic.h"
30#include "beam.h"
31#include "meshes/one_d_lagrangian_mesh.h"
32
33using namespace std;
34
35using namespace oomph;
36
37////////////////////////////////////////////////////////////////////////
38////////////////////////////////////////////////////////////////////////
39////////////////////////////////////////////////////////////////////////
40
41
42//====start_of_namespace============================
43/// Namespace for physical parameters
44//==================================================
46{
47
48 /// Flag for long/short run: Default = perform long run
49 unsigned Long_run_flag=1;
50
51 /// Flag for fixed timestep: Default = fixed timestep
53
54 /// Boolean flag to decide if to set IC for Newmark
55 /// directly or consistently : No Default
57
58} // end of namespace
59
60/////////////////////////////////////////////////////////////////////
61/////////////////////////////////////////////////////////////////////
62/////////////////////////////////////////////////////////////////////
63
64
65
66//==start_of_problem_class==============================================
67/// Oscillating ring problem: Compare small-amplitude oscillations
68/// against analytical solution of the linearised equations.
69//======================================================================
70template<class ELEMENT, class TIMESTEPPER>
71class ElasticRingProblem : public Problem
72{
73
74public:
75
76 /// Constructor: Number of elements, length of domain, flag for
77 /// setting Newmark IC directly or consistently
78 ElasticRingProblem(const unsigned &N, const double &L);
79
80 /// Access function for the mesh
81 OneDLagrangianMesh<ELEMENT>* mesh_pt()
82 {
83 return dynamic_cast<OneDLagrangianMesh<ELEMENT>*>(Problem::mesh_pt());
84 }
85
86 /// Update function is empty
88
89 /// Update function is empty
91
92 /// Doc solution
93 void doc_solution(DocInfo& doc_info);
94
95 /// Do unsteady run
96 void unsteady_run();
97
98private:
99
100 /// Length of domain (in terms of the Lagrangian coordinates)
101 double Length;
102
103 /// In which element are we applying displacement control?
104 /// (here only used for doc of radius)
106
107 /// At what local coordinate are we applying displacement control?
108 Vector<double> S_displ_control;
109
110 /// Pointer to geometric object that represents the undeformed shape
111 GeomObject* Undef_geom_pt;
112
113 /// Pointer to object that specifies the initial condition
114 SolidInitialCondition* IC_pt;
115
116 /// Trace file for recording control data
117 ofstream Trace_file;
118}; // end of problem class
119
120
121
122
123//===start_of_constructor===============================================
124/// Constructor for elastic ring problem
125//======================================================================
126template<class ELEMENT,class TIMESTEPPER>
128(const unsigned& N, const double& L)
129 : Length(L)
130{
131
132 //Allocate the timestepper -- This constructs the time object as well
133 add_time_stepper_pt(new TIMESTEPPER());
134
135 // Undeformed beam is an elliptical ring
136 Undef_geom_pt=new Ellipse(1.0,1.0);
137
138 //Now create the (Lagrangian!) mesh
139 Problem::mesh_pt() = new OneDLagrangianMesh<ELEMENT>(
140 N,L,Undef_geom_pt,Problem::time_stepper_pt());
141
142 // Boundary condition:
143
144 // Bottom:
145 unsigned ibound=0;
146 // No vertical displacement
147 mesh_pt()->boundary_node_pt(ibound,0)->pin_position(1);
148 // Zero slope: Pin type 1 dof for displacement direction 0
149 mesh_pt()->boundary_node_pt(ibound,0)->pin_position(1,0);
150
151 // Top:
152 ibound=1;
153 // No horizontal displacement
154 mesh_pt()->boundary_node_pt(ibound,0)->pin_position(0);
155 // Zero slope: Pin type 1 dof for displacement direction 1
156 mesh_pt()->boundary_node_pt(ibound,0)->pin_position(1,1);
157
158
159 // Resize vector of local coordinates for control displacement
160 // (here only used to identify the point whose displacement we're
161 // tracing)
162 S_displ_control.resize(1);
163
164 // Complete build of all elements so they are fully functional
165 // -----------------------------------------------------------
166
167 // Find number of elements in mesh
168 unsigned Nelement = mesh_pt()->nelement();
169
170 // Loop over the elements to set pointer to undeformed wall shape
171 for(unsigned i=0;i<Nelement;i++)
172 {
173 // Cast to proper element type
174 ELEMENT *elem_pt = dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(i));
175
176 // Assign the undeformed surface
177 elem_pt->undeformed_beam_pt() = Undef_geom_pt;
178 }
179
180 // Establish control displacment: (even though no displacement
181 // control is applied we still want to doc the displacement at the same point)
182
183 // Choose element: (This is the last one)
184 Displ_control_elem_pt=dynamic_cast<ELEMENT*>(
185 mesh_pt()->element_pt(Nelement-1));
186
187 // Fix/doc the displacement in the vertical (1) direction at right end of
188 // the control element
189 S_displ_control[0]=1.0;
190
191 // Do equation numbering
192 cout << "# of dofs " << assign_eqn_numbers() << std::endl;
193
194 // Geometric object that specifies the initial conditions
195 double eps_buckl=1.0e-2;
196 double HoR=dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(0))->h();
197 unsigned n_buckl=2;
198 unsigned imode=2;
199 GeomObject* ic_geom_object_pt=
200 new PseudoBucklingRing(eps_buckl,HoR,n_buckl,imode,
201 Problem::time_stepper_pt());
202
203 // Setup object that specifies the initial conditions:
204 IC_pt = new SolidInitialCondition(ic_geom_object_pt);
205
206} // end of constructor
207
208
209//===start_of_doc_solution================================================
210/// Document solution
211//========================================================================
212template<class ELEMENT, class TIMESTEPPER>
214 DocInfo& doc_info)
215{
216
217 cout << "Doc-ing step " << doc_info.number()
218 << " for time " << time_stepper_pt()->time_pt()->time() << std::endl;
219
220
221 // Loop over all elements to get global kinetic and potential energy
222 unsigned Nelem=mesh_pt()->nelement();
223 double global_kin=0;
224 double global_pot=0;
225 double pot,kin;
226 for (unsigned ielem=0;ielem<Nelem;ielem++)
227 {
228 dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(ielem))->get_energy(pot,kin);
229 global_kin+=kin;
230 global_pot+=pot;
231 }
232
233
234 // Control displacement for initial condition object
235 Vector<double> xi_ctrl(1);
236 Vector<double> posn_ctrl(2);
237
238 // Lagrangian coordinate of control point
239 xi_ctrl[0]=Displ_control_elem_pt->interpolated_xi(S_displ_control,0);
240
241 // Get position
242 IC_pt->geom_object_pt()->position(xi_ctrl,posn_ctrl);
243
244 // Write trace file: Time, control position, energies
245 Trace_file << time_pt()->time() << " "
246 << Displ_control_elem_pt->interpolated_x(S_displ_control,1)
247 << " " << global_pot << " " << global_kin
248 << " " << global_pot + global_kin
249 << " " << posn_ctrl[1]
250 << std::endl;
251
252
253 ofstream some_file;
254 char filename[100];
255
256 // Number of plot points
257 unsigned npts=5;
258
259 // Output solution
260 snprintf(filename, sizeof(filename), "%s/ring%i.dat",doc_info.directory().c_str(),
261 doc_info.number());
262 some_file.open(filename);
263 mesh_pt()->output(some_file,npts);
264 some_file.close();
265
266 // Loop over all elements do dump out previous solutions
267 unsigned nsteps=time_stepper_pt()->nprev_values();
268 for (unsigned t=0;t<=nsteps;t++)
269 {
270 snprintf(filename, sizeof(filename), "%s/ring%i-%i.dat",doc_info.directory().c_str(),
271 doc_info.number(),t);
272 some_file.open(filename);
273 unsigned Nelem=mesh_pt()->nelement();
274 for (unsigned ielem=0;ielem<Nelem;ielem++)
275 {
276 dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(ielem))->
277 output(t,some_file,npts);
278 }
279 some_file.close();
280 }
281
282 // Output for initial condition object
283 snprintf(filename, sizeof(filename), "%s/ic_ring%i.dat",doc_info.directory().c_str(),
284 doc_info.number());
285 some_file.open(filename);
286
287 unsigned nplot=1+(npts-1)*mesh_pt()->nelement();
288 Vector<double> xi(1);
289 Vector<double> posn(2);
290 Vector<double> veloc(2);
291 Vector<double> accel(2);
292
293 for (unsigned iplot=0;iplot<nplot;iplot++)
294 {
295 xi[0]=Length/double(nplot-1)*double(iplot);
296
297 IC_pt->geom_object_pt()->position(xi,posn);
298 IC_pt->geom_object_pt()->dposition_dt(xi,1,veloc);
299 IC_pt->geom_object_pt()->dposition_dt(xi,2,accel);
300
301 some_file << posn[0] << " " << posn[1] << " "
302 << xi[0] << " "
303 << veloc[0] << " " << veloc[1] << " "
304 << accel[0] << " " << accel[1] << " "
305 << sqrt(pow(posn[0],2)+pow(posn[1],2)) << " "
306 << sqrt(pow(veloc[0],2)+pow(veloc[1],2)) << " "
307 << sqrt(pow(accel[0],2)+pow(accel[1],2)) << " "
308 << std::endl;
309 }
310
311 some_file.close();
312} // end of doc solution
313
314
315
316//===start_of_unsteady_run=================================================
317/// Solver loop to perform unsteady run
318//=========================================================================
319template<class ELEMENT,class TIMESTEPPER>
321{
322
323 /// Label for output
324 DocInfo doc_info;
325
326 // Output directory
327 doc_info.set_directory("RESLT");
328
329 // Step number
330 doc_info.number()=0;
331
332 // Set up trace file
333 char filename[100];
334 snprintf(filename, sizeof(filename), "%s/trace_ring.dat",doc_info.directory().c_str());
335 Trace_file.open(filename);
336
337 Trace_file << "VARIABLES=\"time\",\"R<sub>ctrl</sub>\",\"E<sub>pot</sub>\"";
338 Trace_file << ",\"E<sub>kin</sub>\",\"E<sub>kin</sub>+E<sub>pot</sub>\"";
339 Trace_file << ",\"<sub>exact</sub>R<sub>ctrl</sub>\""
340 << std::endl;
341
342 // Number of steps
343 unsigned nstep=600;
345
346 // Initial timestep
347 double dt=1.0;
348
349 // Ratio for timestep reduction
350 double timestep_ratio=1.0;
351 if (Global_Physical_Variables::Fixed_timestep_flag==0) {timestep_ratio=0.995;}
352
353 // Number of previous timesteps stored
354 unsigned ndt=time_stepper_pt()->time_pt()->ndt();
355
356 // Setup vector of "previous" timesteps
357 Vector<double> dt_prev(ndt);
358 dt_prev[0]=dt;
359 for (unsigned i=1;i<ndt;i++)
360 {
361 dt_prev[i]=dt_prev[i-1]/timestep_ratio;
362 }
363
364 // Initialise the history of previous timesteps
365 time_pt()->initialise_dt(dt_prev);
366
367 // Initialise time
368 double time0=10.0;
369 time_pt()->time()=time0;
370
371 // Setup analytical initial condition?
373 {
374 // Note: Time has been scaled on intrinsic timescale so
375 // we don't need to specify a multiplier for the inertia
376 // terms (the default assignment of 1.0 is OK)
377 SolidMesh::Solid_IC_problem.
378 set_newmark_initial_condition_consistently(
379 this,mesh_pt(),static_cast<TIMESTEPPER*>(time_stepper_pt()),IC_pt,dt);
380 }
381 else
382 {
383 SolidMesh::Solid_IC_problem.
384 set_newmark_initial_condition_directly(
385 this,mesh_pt(),static_cast<TIMESTEPPER*>(time_stepper_pt()),IC_pt,dt);
386 }
387
388 //Output initial data
389 doc_solution(doc_info);
390
391 // Time integration loop
392 for(unsigned i=1;i<=nstep;i++)
393 {
394 // Solve
395 unsteady_newton_solve(dt);
396
397 // Doc solution
398 doc_info.number()++;
399 doc_solution(doc_info);
400
401 // Reduce timestep
402 if (time_pt()->time()<100.0) {dt=timestep_ratio*dt;}
403 }
404
405} // end of unsteady run
406
407
408
409//===start_of_main=====================================================
410/// Driver for ring that performs small-amplitude oscillations
411//=====================================================================
412int main(int argc, char* argv[])
413{
414
415 // Store command line arguments
416 CommandLineArgs::setup(argc,argv);
417
418 /// Convert command line arguments (if any) into flags:
419 if (argc==2)
420 {
421 // Nontrivial command line input: Setup Newmark IC directly
422 // (rather than consistently with PVD)
423 if (atoi(argv[1])==1)
424 {
426 cout << "Setting Newmark IC consistently" << std::endl;
427 }
428 else
429 {
431 cout << "Setting Newmark IC directly" << std::endl;
432 }
433
434 cout << "Not enough command line arguments specified -- using defaults."
435 << std::endl;
436 } // end of 1 argument
437 else if (argc==4)
438 {
439 cout << "Three command line arguments specified:" << std::endl;
440 // Nontrivial command line input: Setup Newmark IC directly
441 // (rather than consistently with PVD)
442 if (atoi(argv[1])==1)
443 {
445 cout << "Setting Newmark IC consistently" << std::endl;
446 }
447 else
448 {
450 cout << "Setting Newmark IC directly" << std::endl;
451 }
452 // Flag for long run
454 // Flag for fixed timestep
456 } // end of 3 arguments
457 else
458 {
459 std::string error_message =
460 "Wrong number of command line arguments. Specify one or three.\n";
461 error_message += "Arg1: Long_run_flag [0/1]\n";
462 error_message += "Arg2: Impulsive_start_flag [0/1]\n";
463 error_message += "Arg3: Restart_flag [restart_file] (optional)\n";
464
465 throw OomphLibError(error_message,
466 OOMPH_CURRENT_FUNCTION,
467 OOMPH_EXCEPTION_LOCATION);
468 } // too many arguments
469 cout << "Setting Newmark IC consistently: "
471 cout << "Long run flag: "
473 cout << "Fixed timestep flag: "
475
476 //Length of domain
477 double L = MathematicalConstants::Pi/2.0;
478
479 // Number of elements
480 unsigned nelem = 13;
481
482 //Set up the problem
484 problem(nelem,L);
485
486 // Do unsteady run
487 problem.unsteady_run();
488
489} // end of main
490
491
492
493
494
495
496
497
Oscillating ring problem: Compare small-amplitude oscillations against analytical solution of the lin...
Vector< double > S_displ_control
At what local coordinate are we applying displacement control?
SolidInitialCondition * IC_pt
Pointer to object that specifies the initial condition.
ElasticRingProblem(const unsigned &N, const double &L)
Constructor: Number of elements, length of domain, flag for setting Newmark IC directly or consistent...
double Length
Length of domain (in terms of the Lagrangian coordinates)
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.
GeomObject * Undef_geom_pt
Pointer to geometric object that represents the undeformed shape.
OneDLagrangianMesh< ELEMENT > * mesh_pt()
Access function for the mesh.
ELEMENT * Displ_control_elem_pt
In which element are we applying displacement control? (here only used for doc of radius)
void unsteady_run()
Do unsteady run.
int main(int argc, char *argv[])
Driver for ring that performs small-amplitude oscillations.
Namespace for physical parameters.
unsigned Fixed_timestep_flag
Flag for fixed timestep: Default = fixed timestep.
unsigned Long_run_flag
Flag for long/short run: Default = perform long run.
bool Consistent_newmark_ic
Boolean flag to decide if to set IC for Newmark directly or consistently : No Default.