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-2023 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 
33 using namespace std;
34 
35 using 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
52  unsigned Fixed_timestep_flag=1;
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 //======================================================================
70 template<class ELEMENT, class TIMESTEPPER>
71 class ElasticRingProblem : public Problem
72 {
73 
74 public:
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 
98 private:
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 //======================================================================
126 template<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 //========================================================================
212 template<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  sprintf(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  sprintf(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  sprintf(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 //=========================================================================
319 template<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  sprintf(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;
344  if (Global_Physical_Variables::Long_run_flag==0) {nstep=10;}
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 //=====================================================================
412 int 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 
////////////////////////////////////////////////////////////////// //////////////////////////////////...
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)
OneDLagrangianMesh< ELEMENT > * mesh_pt()
Access function for the mesh.
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.
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.
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
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.