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-2024 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 
37 using namespace std;
38 
39 using 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 //======================================================================
97 template<class ELEMENT, class TIMESTEPPER>
98 class ElasticRingProblem : public Problem
99 {
100 
101 public:
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
119  void set_initial_conditions();
120 
121  /// Doc solution
122  void doc_solution(DocInfo& doc_info);
123 
124  /// Do unsteady run
125  void 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 
136 private:
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 //======================================================================
156 template<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 //========================================================================
226 template<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  sprintf(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  sprintf(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  sprintf(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 //=======================================================================
324 template<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 //=======================================================================
346 template<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 //=========================================================================
379 template<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 //=========================================================================
428 template<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  sprintf(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 //=====================================================================
549 int 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 
////////////////////////////////////////////////////////////////// //////////////////////////////////...
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?
OneDLagrangianMesh< ELEMENT > * mesh_pt()
Access function for the specific mesh.
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.
void unsteady_run()
Do unsteady run.
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
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.