Example codes
and tutorials
The (Not-so) Quick Guide
List of tutorials/demo codes
Single-Physics Problems
Poisson
Adaptivity illustrated for Poisson
Advection-Diffusion
Unsteady heat equation
Linear wave equation
The Young-Laplace equation
Navier-Stokes
Free-surface Navier-Stokes
Axisymmetric Navier-Stokes
Solid mechanics
Beam structures
Shell structures
Multi-physics Problems
Fluid-structure interaction
Boussinesq convection
Steady thermoelasticity
Methods-based example codes and tutorials
Mesh generation
Linear solvers and preconditioners
Visualisation of the results
Parallel processing
How to write a new element
How to write a new refineable element
Default nonlinear solvers -- the sequence of action functions
...
Documentation
FE theory and top-down discussion of the data structure
The (Not-so) Quick Guide
Comprehensive bottom-up discussion of the data structure
List of available structured and unstructured meshes
Linear solvers and preconditioners
Visualisation of the results
Parallel processing
Coding conventions and C++ style
Creating documentation
Optimisation - robustness vs. "raw speed"
Linear vs. nonlinear problems
Storing shape functions
Changing the default "full" integration scheme
Disabling the ALE formulation of unsteady equations
C vs. C++ output
Different sparse assembly techniques and the STL memory pool
Publications
Publications
Talks
Journal publications
Theses
Picture show
Download
Copyright
Download/installation instructions
Download page
FAQ & Contact
FAQ
Change log
Bugs and other known problems
Completeness of the library & our "To-Do List"
Contact the developers
Get involved

 


Beta release!

Please note that the library has not been "officially" released. While we continue to work on the documentation, these web pages are likely to contain broken links and documents in draft form. Please send an email to

oomph-lib AT maths DOT man DOT ac DOT uk

if you wish to be informed of the library's "official" release.

shock_disk.cc

Go to the documentation of this file.
00001 //LIC// ====================================================================
00002 //LIC// This file forms part of oomph-lib, the object-oriented, 
00003 //LIC// multi-physics finite-element library, available 
00004 //LIC// at http://www.oomph-lib.org.
00005 //LIC// 
00006 //LIC//           Version 0.90. August 3, 2009.
00007 //LIC// 
00008 //LIC// Copyright (C) 2006-2009 Matthias Heil and Andrew Hazel
00009 //LIC// 
00010 //LIC// This library is free software; you can redistribute it and/or
00011 //LIC// modify it under the terms of the GNU Lesser General Public
00012 //LIC// License as published by the Free Software Foundation; either
00013 //LIC// version 2.1 of the License, or (at your option) any later version.
00014 //LIC// 
00015 //LIC// This library is distributed in the hope that it will be useful,
00016 //LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 //LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 //LIC// Lesser General Public License for more details.
00019 //LIC// 
00020 //LIC// You should have received a copy of the GNU Lesser General Public
00021 //LIC// License along with this library; if not, write to the Free Software
00022 //LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00023 //LIC// 02110-1301  USA.
00024 //LIC// 
00025 //LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
00026 //LIC// 
00027 //LIC//====================================================================
00028 // Driver for large-displacement elasto-dynamic test problem:
00029 // Circular disk impulsively loaded by compressive load.
00030 
00031 #include <iostream>
00032 #include <fstream>
00033 #include <cmath>
00034 
00035 //My own includes
00036 #include "generic.h"
00037 #include "solid.h"
00038 
00039 //Need to instantiate templated mesh
00040 #include "meshes/quarter_circle_sector_mesh.h"
00041 
00042 using namespace std;
00043 
00044 using namespace oomph;
00045  
00046 ///////////////////////////////////////////////////////////////////////
00047 ///////////////////////////////////////////////////////////////////////
00048 ///////////////////////////////////////////////////////////////////////
00049 
00050 
00051 //================================================================
00052 /// Global variables
00053 //================================================================
00054 namespace Global_Physical_Variables
00055 {
00056  /// Pointer to constitutive law
00057  ConstitutiveLaw* Constitutive_law_pt;
00058 
00059  /// Elastic modulus
00060  double E=1.0;
00061 
00062  /// Poisson's ratio
00063  double Nu=0.3;
00064 
00065  /// Uniform pressure
00066  double P = 0.00;
00067 
00068  /// Constant pressure load
00069  void constant_pressure(const Vector<double> &xi,const Vector<double> &x,
00070                         const Vector<double> &n, Vector<double> &traction)
00071  {
00072   unsigned dim = traction.size();
00073   for(unsigned i=0;i<dim;i++)
00074    {
00075     traction[i] = -P*n[i];
00076    }
00077  }
00078 
00079 }
00080 
00081 
00082 
00083 ///////////////////////////////////////////////////////////////////////
00084 ///////////////////////////////////////////////////////////////////////
00085 ///////////////////////////////////////////////////////////////////////
00086 
00087 
00088 
00089 //================================================================
00090 /// Elastic quarter circle sector mesh with functionality to
00091 /// attach traction elements to the curved surface. We "upgrade"
00092 /// the RefineableQuarterCircleSectorMesh to become an
00093 /// SolidMesh and equate the Eulerian and Lagrangian coordinates,
00094 /// thus making the domain represented by the mesh the stress-free 
00095 /// configuration. 
00096 /// \n\n
00097 /// The member function \c make_traction_element_mesh() creates
00098 /// a separate mesh of SolidTractionElements that are attached to the
00099 /// mesh's curved boundary (boundary 1). 
00100 //================================================================
00101 template <class ELEMENT>
00102 class ElasticRefineableQuarterCircleSectorMesh :
00103  public virtual RefineableQuarterCircleSectorMesh<ELEMENT>,
00104  public virtual SolidMesh
00105 {
00106 
00107 
00108 public:
00109 
00110  /// \short Constructor: Build mesh and copy Eulerian coords to Lagrangian
00111  /// ones so that the initial configuration is the stress-free one.
00112  ElasticRefineableQuarterCircleSectorMesh<ELEMENT>(GeomObject* wall_pt,
00113                                          const double& xi_lo,
00114                                          const double& fract_mid,
00115                                          const double& xi_hi,
00116                                          TimeStepper* time_stepper_pt=
00117                                          &Mesh::Default_TimeStepper) :
00118   RefineableQuarterCircleSectorMesh<ELEMENT>(wall_pt,xi_lo,fract_mid,xi_hi,
00119                                              time_stepper_pt)
00120   {
00121 #ifdef PARANOID
00122    /// Check that the element type is derived from the SolidFiniteElement
00123    SolidFiniteElement* el_pt=dynamic_cast<SolidFiniteElement*>
00124     (finite_element_pt(0));
00125    if (el_pt==0)
00126     {
00127      throw OomphLibError(
00128       "Element needs to be derived from SolidFiniteElement\n",
00129       "ElasticRefineableQuarterCircleSectorMesh::constructor()",
00130       OOMPH_EXCEPTION_LOCATION);
00131     }
00132 #endif
00133 
00134    // Make the current configuration the undeformed one by
00135    // setting the nodal Lagrangian coordinates to their current
00136    // Eulerian ones
00137    set_lagrangian_nodal_coordinates();
00138   }
00139 
00140 
00141  /// Function to create mesh made of traction elements
00142  void make_traction_element_mesh(SolidMesh*& traction_mesh_pt)
00143   {
00144 
00145    // Make new mesh
00146    traction_mesh_pt=new SolidMesh;
00147 
00148    // Loop over all elements on boundary 1:
00149    unsigned b=1;
00150    unsigned n_element = this->nboundary_element(b);
00151    for (unsigned e=0;e<n_element;e++)
00152     {
00153      // The element itself:
00154      FiniteElement* fe_pt = this->boundary_element_pt(b,e);
00155      
00156      // Find the index of the face of element e along boundary b
00157      int face_index = this->face_index_at_boundary(b,e);
00158      
00159      // Create new element
00160      traction_mesh_pt->add_element_pt(new SolidTractionElement<ELEMENT>
00161                                       (fe_pt,face_index));
00162     }
00163   }
00164 
00165 
00166  /// Function to wipe and re-create mesh made of traction elements
00167  void remake_traction_element_mesh(SolidMesh*& traction_mesh_pt)
00168   {
00169 
00170    // Wipe existing mesh (but don't call it's destructor as this
00171    // would wipe all the nodes too!)
00172    traction_mesh_pt->flush_element_and_node_storage();
00173 
00174    // Loop over all elements on boundary 1:
00175    unsigned b=1;
00176    unsigned n_element = this->nboundary_element(b);
00177    for (unsigned e=0;e<n_element;e++)
00178     {
00179      // The element itself:
00180      FiniteElement* fe_pt = this->boundary_element_pt(b,e);
00181      
00182      // Find the index of the face of element e along boundary b
00183      int face_index = this->face_index_at_boundary(b,e);
00184      
00185      // Create new element
00186      traction_mesh_pt->add_element_pt(new SolidTractionElement<ELEMENT>
00187                                       (fe_pt,face_index));
00188     }
00189   }
00190 
00191 
00192 };
00193 
00194 
00195 
00196 
00197 
00198 /////////////////////////////////////////////////////////////////////////
00199 /////////////////////////////////////////////////////////////////////////
00200 /////////////////////////////////////////////////////////////////////////
00201 
00202 
00203 
00204 //====================================================================== 
00205 /// "Shock" wave propagates through an impulsively loaded
00206 /// circular disk.
00207 //====================================================================== 
00208 template<class ELEMENT, class TIMESTEPPER>
00209 class DiskShockWaveProblem : public Problem
00210 {
00211 
00212 public:
00213 
00214  /// Constructor:
00215  DiskShockWaveProblem();
00216 
00217  /// \short Run the problem; specify case_number to label output
00218  /// directory
00219  void run(const unsigned& case_number);
00220  
00221  /// Access function for the solid mesh
00222  ElasticRefineableQuarterCircleSectorMesh<ELEMENT>*& solid_mesh_pt() 
00223   {
00224    return Solid_mesh_pt;  
00225   } 
00226 
00227  /// Access function for the mesh of surface traction elements
00228  SolidMesh*& traction_mesh_pt() 
00229   {
00230    return Traction_mesh_pt;  
00231   } 
00232 
00233  /// Doc the solution
00234  void doc_solution();
00235 
00236  /// Update function (empty)
00237  void actions_after_newton_solve() {}
00238 
00239  /// Update function (empty)
00240  void actions_before_newton_solve() {}
00241 
00242  /// \short Actions after adaption: Kill and then re-build the traction 
00243  /// elements on boundary 1 and re-assign the equation numbers
00244  void actions_after_adapt();
00245 
00246  /// \short Doc displacement and velocity: label file with before and after
00247  void doc_displ_and_veloc(const int& stage=0);
00248 
00249  /// \short Dump problem-specific parameters values, then dump
00250  /// generic problem data.
00251  void dump_it(ofstream& dump_file);
00252 
00253  /// \short Read problem-specific parameter values, then recover
00254  /// generic problem data.
00255  void restart(ifstream& restart_file);
00256 
00257 private:
00258 
00259  // Output
00260  DocInfo Doc_info;
00261 
00262  /// Trace file
00263  ofstream Trace_file;
00264  
00265  /// Vector of pointers to nodes whose position we're tracing
00266  Vector<Node*> Trace_node_pt;
00267 
00268  /// Pointer to solid mesh
00269  ElasticRefineableQuarterCircleSectorMesh<ELEMENT>* Solid_mesh_pt;
00270 
00271  /// Pointer to mesh of traction elements
00272  SolidMesh* Traction_mesh_pt;
00273 
00274 };
00275 
00276 
00277 
00278 
00279 
00280 //====================================================================== 
00281 /// Constructor
00282 //====================================================================== 
00283 template<class ELEMENT, class TIMESTEPPER>
00284 DiskShockWaveProblem<ELEMENT,TIMESTEPPER>::DiskShockWaveProblem() 
00285 {
00286 
00287 
00288  //Allocate the timestepper
00289  add_time_stepper_pt(new TIMESTEPPER);
00290  
00291  // Set coordinates and radius for the circle that defines 
00292  // the outer curvilinear boundary of the domain
00293  double x_c=0.0;
00294  double y_c=0.0;
00295  double r=1.0;
00296  
00297  // Build geometric object that specifies the fish back in the
00298  // undeformed configuration (basically a deep copy of the previous one)
00299  GeomObject* curved_boundary_pt=new Circle(x_c,y_c,r,time_stepper_pt());
00300 
00301  // The curved boundary of the mesh is defined by the geometric object
00302  // What follows are the start and end coordinates on the geometric object:
00303  double xi_lo=0.0;
00304  double xi_hi=2.0*atan(1.0);
00305 
00306  // Fraction along geometric object at which the radial dividing line
00307  // is placed
00308  double fract_mid=0.5;
00309 
00310  //Now create the mesh
00311  solid_mesh_pt() = new ElasticRefineableQuarterCircleSectorMesh<ELEMENT>(
00312   curved_boundary_pt,xi_lo,fract_mid,xi_hi,time_stepper_pt());
00313 
00314  // Set up trace nodes as the nodes on boundary 1 (=curved boundary) in 
00315  // the original mesh (they exist under any refinement!) 
00316  unsigned nnod0=solid_mesh_pt()->nboundary_node(0);
00317  unsigned nnod1=solid_mesh_pt()->nboundary_node(1);
00318  Trace_node_pt.resize(nnod0+nnod1);
00319  for (unsigned j=0;j<nnod0;j++)
00320   {
00321    Trace_node_pt[j]=solid_mesh_pt()->boundary_node_pt(0,j);
00322   }
00323  for (unsigned j=0;j<nnod1;j++)
00324   {
00325    Trace_node_pt[j+nnod0]=solid_mesh_pt()->boundary_node_pt(1,j);
00326   }
00327 
00328  // Build traction element mesh
00329  solid_mesh_pt()->make_traction_element_mesh(traction_mesh_pt());
00330  
00331  // Solid mesh is first sub-mesh
00332  add_sub_mesh(solid_mesh_pt());
00333 
00334  // Traction mesh is first sub-mesh
00335  add_sub_mesh(traction_mesh_pt());
00336 
00337  // Build combined "global" mesh
00338  build_global_mesh();
00339 
00340 
00341  // Create/set error estimator
00342  solid_mesh_pt()->spatial_error_estimator_pt()=new Z2ErrorEstimator;
00343   
00344  // Fiddle with adaptivity targets and doc
00345  solid_mesh_pt()->max_permitted_error()=0.006; //0.03;
00346  solid_mesh_pt()->min_permitted_error()=0.0006;// 0.0006; //0.003;
00347  solid_mesh_pt()->doc_adaptivity_targets(cout);
00348 
00349  // Pin the bottom in the vertical direction
00350  unsigned n_bottom = solid_mesh_pt()->nboundary_node(0);
00351 
00352  //Loop over the node
00353  for(unsigned i=0;i<n_bottom;i++)
00354   {
00355    solid_mesh_pt()->boundary_node_pt(0,i)->pin_position(1);
00356   }
00357 
00358  // Pin the left edge in the horizontal direction
00359  unsigned n_side = solid_mesh_pt()->nboundary_node(2);
00360  //Loop over the node
00361  for(unsigned i=0;i<n_side;i++)
00362   {
00363    solid_mesh_pt()->boundary_node_pt(2,i)->pin_position(0);
00364   }
00365 
00366  //Find number of elements in solid mesh
00367  unsigned n_element =solid_mesh_pt()->nelement();
00368   
00369  //Set parameters and function pointers for solid elements
00370  for(unsigned i=0;i<n_element;i++)
00371   {
00372    //Cast to a solid element
00373    ELEMENT *el_pt = dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(i));
00374 
00375    //Set the constitutive law
00376    el_pt->constitutive_law_pt() =
00377     Global_Physical_Variables::Constitutive_law_pt;
00378    
00379    // Switch on inertia
00380    el_pt->unsteady()=true;
00381 
00382    // Use MacroElement representation for 
00383    // Lagrangian coordinates of newly created 
00384    // nodes hierher simply retained to let self tests pass during
00385    // re-development of code
00386    el_pt->use_undeformed_macro_element_for_new_lagrangian_coords()
00387     =true;
00388   }
00389 
00390  // Pin the redundant solid pressures
00391  PVDEquationsBase<2>::pin_redundant_nodal_solid_pressures(
00392   solid_mesh_pt()->element_pt());
00393 
00394  //Find number of elements in traction mesh
00395  n_element=traction_mesh_pt()->nelement();
00396   
00397  //Set function pointers for traction elements
00398  for(unsigned i=0;i<n_element;i++)
00399   {
00400    //Cast to a solid traction element
00401    SolidTractionElement<ELEMENT> *el_pt = 
00402     dynamic_cast<SolidTractionElement<ELEMENT>*>
00403     (traction_mesh_pt()->element_pt(i));
00404 
00405    //Set the traction function
00406    el_pt->traction_fct_pt() = Global_Physical_Variables::constant_pressure;
00407   }
00408 
00409  //Attach the boundary conditions to the mesh
00410  cout << assign_eqn_numbers() << std::endl; 
00411 
00412  // Refine uniformly
00413  refine_uniformly();
00414  refine_uniformly();
00415  refine_uniformly();
00416  
00417 
00418  // Now the non-pinned positions of the SolidNodes will have been
00419  // determined by interpolation. This is appropriate for uniform
00420  // refinements once the code is up and running since we can't place
00421  // new SolidNodes at the positions determined by the MacroElement.
00422  // However, here we want to update the nodes to fit the exact
00423  // intitial configuration.
00424 
00425  // Update all solid nodes based on the Mesh's Domain/MacroElement
00426  // representation
00427  bool update_all_solid_nodes=true;
00428  solid_mesh_pt()->node_update(update_all_solid_nodes);
00429 
00430  // Now set the Eulerian equal to the Lagrangian coordinates
00431  solid_mesh_pt()->set_lagrangian_nodal_coordinates();
00432  
00433 }
00434 
00435 
00436 
00437 
00438 
00439 
00440 //==================================================================
00441 /// Kill and then re-build the traction elements on boundary 1,
00442 /// pin redundant pressure dofs and re-assign the equation numbers.
00443 //==================================================================
00444 template<class ELEMENT, class TIMESTEPPER>
00445 void DiskShockWaveProblem<ELEMENT,TIMESTEPPER>::actions_after_adapt()
00446 { 
00447  // Wipe and re-build traction element mesh
00448  solid_mesh_pt()->remake_traction_element_mesh(traction_mesh_pt());
00449  
00450  // Re-build combined "global" mesh
00451  rebuild_global_mesh();
00452 
00453  //Find number of elements in traction mesh
00454  unsigned n_element=traction_mesh_pt()->nelement();
00455   
00456  //Loop over the elements in the traction element mesh
00457  for(unsigned i=0;i<n_element;i++)
00458   {
00459    //Cast to a solid traction element
00460    SolidTractionElement<ELEMENT> *el_pt = 
00461     dynamic_cast<SolidTractionElement<ELEMENT>*>
00462     (traction_mesh_pt()->element_pt(i));
00463 
00464    //Set the traction function
00465    el_pt->traction_fct_pt() = Global_Physical_Variables::constant_pressure;
00466   }
00467 
00468  // Pin the redundant solid pressures
00469  PVDEquationsBase<2>::pin_redundant_nodal_solid_pressures(
00470   solid_mesh_pt()->element_pt());
00471 
00472 
00473  //Do equation numbering
00474  cout << assign_eqn_numbers() << std::endl; 
00475 
00476 }
00477 
00478 
00479 //==================================================================
00480 /// Doc the solution
00481 //==================================================================
00482 template<class ELEMENT, class TIMESTEPPER>
00483 void DiskShockWaveProblem<ELEMENT,TIMESTEPPER>::doc_solution()
00484 {
00485  // Number of plot points
00486  unsigned npts;
00487  npts=5; 
00488 
00489  // Output shape of deformed body
00490  ofstream some_file;
00491  char filename[100];
00492  sprintf(filename,"%s/soln%i.dat",Doc_info.directory().c_str(),
00493          Doc_info.number());
00494  some_file.open(filename);
00495  solid_mesh_pt()->output(some_file,npts);
00496  some_file.close();
00497 
00498 
00499  // Output traction
00500  unsigned nel=traction_mesh_pt()->nelement();
00501  sprintf(filename,"%s/traction%i.dat",Doc_info.directory().c_str(),
00502          Doc_info.number());
00503  some_file.open(filename);
00504  Vector<double> unit_normal(2);
00505  Vector<double> traction(2);
00506  Vector<double> x_dummy(2);
00507  Vector<double> s_dummy(1);
00508  for (unsigned e=0;e<nel;e++)
00509   {
00510    some_file << "ZONE " << std::endl;
00511    for (unsigned i=0;i<npts;i++)
00512     {
00513      s_dummy[0]=-1.0+2.0*double(i)/double(npts-1);
00514      SolidTractionElement<ELEMENT>* el_pt=
00515       dynamic_cast<SolidTractionElement<ELEMENT>*>(
00516        traction_mesh_pt()->finite_element_pt(e));
00517      el_pt->outer_unit_normal(s_dummy,unit_normal);
00518      el_pt->traction(s_dummy,traction);
00519      el_pt->interpolated_x(s_dummy,x_dummy);
00520      some_file << x_dummy[0] << " " << x_dummy[1] << " " 
00521                << traction[0] << " " << traction[1] << " "  
00522                << std::endl;
00523     }
00524   }
00525  some_file.close(); 
00526 
00527  // Doc displacement and velocity
00528  doc_displ_and_veloc();
00529 
00530  // Get displacement as a function of the radial coordinate
00531  // along boundary 0
00532  {
00533 
00534   // Number of elements along boundary 0:
00535   unsigned nelem=solid_mesh_pt()->nboundary_element(0);
00536 
00537   // Open files
00538   sprintf(filename,"%s/displ%i.dat",Doc_info.directory().c_str(),
00539           Doc_info.number());
00540   some_file.open(filename);
00541   
00542   Vector<double> s(2);
00543   Vector<double> x(2);
00544   Vector<double> dxdt(2);
00545   Vector<double> xi(2);
00546   Vector<double> r_exact(2);
00547   Vector<double> v_exact(2);
00548 
00549   for (unsigned e=0;e<nelem;e++)
00550    {
00551     some_file << "ZONE " << std::endl;
00552     for (unsigned i=0;i<npts;i++)
00553      {
00554       // Move along bottom edge of element
00555       s[0]=-1.0+2.0*double(i)/double(npts-1);
00556       s[1]=-1.0;
00557 
00558       // Get pointer to element
00559       SolidFiniteElement* el_pt=dynamic_cast<SolidFiniteElement*>
00560        (solid_mesh_pt()->boundary_element_pt(0,e));
00561       
00562       // Get Lagrangian coordinate
00563       el_pt->interpolated_xi(s,xi);
00564 
00565       // Get Eulerian coordinate
00566       el_pt->interpolated_x(s,x);
00567 
00568       // Get velocity 
00569       el_pt->interpolated_dxdt(s,1,dxdt);
00570   
00571       // Plot radial distance and displacement
00572       some_file << xi[0] << " " << x[0]-xi[0] << " " 
00573                 << dxdt[0] << std::endl;
00574      }
00575    }
00576   some_file.close(); 
00577  }
00578 
00579   
00580  // Write trace file
00581  Trace_file << time_pt()->time()  << " ";
00582  unsigned ntrace_node=Trace_node_pt.size();
00583  for (unsigned j=0;j<ntrace_node;j++)
00584   {
00585    Trace_file << sqrt(pow(Trace_node_pt[j]->x(0),2)+
00586                       pow(Trace_node_pt[j]->x(1),2)) << " ";
00587   }
00588  Trace_file << std::endl;
00589 
00590  // Output principal stress vectors at the centre of all elements
00591  SolidHelpers::doc_2D_principal_stress<ELEMENT>(Doc_info,solid_mesh_pt());
00592 
00593 //  // Write restart file
00594 //  sprintf(filename,"%s/restart%i.dat",Doc_info.directory().c_str(),
00595 //          Doc_info.number());
00596 //  some_file.open(filename);
00597 //  dump_it(some_file);
00598 //  some_file.close();
00599  
00600 
00601  cout << "Doced solution for step " 
00602       << Doc_info.number() 
00603       << std::endl << std::endl << std::endl;
00604 }
00605 
00606 
00607 
00608 
00609 
00610 
00611 //==================================================================
00612 /// Doc displacement and veloc in displ_and_veloc*.dat.
00613 /// The int stage defaults to 0, in which case the '*' in the
00614 /// filename is simply the step number specified by the Problem's
00615 /// DocInfo object. If it's +/-1, the word "before" and "after"
00616 /// get inserted. This allows checking of the veloc/displacment
00617 /// interpolation during adaptive mesh refinement.
00618 //==================================================================
00619 template<class ELEMENT, class TIMESTEPPER>
00620 void DiskShockWaveProblem<ELEMENT,TIMESTEPPER>::doc_displ_and_veloc(
00621  const int& stage)
00622 {
00623 
00624  ofstream some_file;
00625  char filename[100];
00626 
00627  // Number of plot points
00628  unsigned npts;
00629  npts=5; 
00630 
00631  // Open file
00632  if (stage==-1)
00633   {
00634    sprintf(filename,"%s/displ_and_veloc_before%i.dat",
00635            Doc_info.directory().c_str(),Doc_info.number());
00636   }
00637  else if (stage==1)
00638   {
00639    sprintf(filename,"%s/displ_and_veloc_after%i.dat",
00640            Doc_info.directory().c_str(),Doc_info.number());
00641   }
00642  else 
00643   {
00644    sprintf(filename,"%s/displ_and_veloc%i.dat",
00645            Doc_info.directory().c_str(),Doc_info.number());
00646   }
00647  some_file.open(filename);
00648 
00649  Vector<double> s(2),x(2),dxdt(2),xi(2),displ(2);
00650 
00651  //Loop over solid elements
00652  unsigned nel=solid_mesh_pt()->nelement();
00653  for (unsigned e=0;e<nel;e++)
00654   {
00655    some_file << "ZONE I=" << npts << ", J=" << npts << std::endl;
00656    for (unsigned i=0;i<npts;i++)
00657     {
00658      s[0]=-1.0+2.0*double(i)/double(npts-1);
00659      for (unsigned j=0;j<npts;j++)
00660       {
00661        s[1]=-1.0+2.0*double(j)/double(npts-1);
00662 
00663        // Cast to full element type
00664        ELEMENT* el_pt=dynamic_cast<ELEMENT*>(solid_mesh_pt()->
00665                                              finite_element_pt(e));
00666 
00667        // Eulerian coordinate
00668        el_pt->interpolated_x(s,x);
00669 
00670        // Lagrangian coordinate
00671        el_pt->interpolated_xi(s,xi);
00672 
00673        // Displacement
00674        displ[0]=x[0]-xi[0];
00675        displ[1]=x[1]-xi[1];
00676 
00677        // Velocity (1st deriv)
00678        el_pt->interpolated_dxdt(s,1,dxdt);
00679 
00680        some_file << x[0] << " " << x[1] << " " 
00681                  << displ[0] << " " << displ[1] << " "  
00682                  << dxdt[0] << " " << dxdt[1] << " "  
00683                  << std::endl;
00684       }
00685     }
00686   }
00687  some_file.close(); 
00688 
00689 }
00690 
00691 
00692 
00693 //========================================================================
00694 /// Dump the solution
00695 //========================================================================
00696 template<class ELEMENT, class TIMESTEPPER>
00697 void DiskShockWaveProblem<ELEMENT,TIMESTEPPER>::dump_it(ofstream& dump_file)
00698 {
00699  // Call generic dump()
00700  Problem::dump(dump_file);
00701 }
00702 
00703 
00704 
00705 //========================================================================
00706 /// Read solution from disk
00707 //========================================================================
00708 template<class ELEMENT, class TIMESTEPPER>
00709 void DiskShockWaveProblem<ELEMENT,TIMESTEPPER>::restart(ifstream& restart_file)
00710 {
00711  // Read generic problem data
00712  Problem::read(restart_file);
00713 }
00714 
00715 
00716 
00717 //==================================================================
00718 /// Run the problem; specify case_number to label output directory
00719 //==================================================================
00720 template<class ELEMENT, class TIMESTEPPER>
00721 void DiskShockWaveProblem<ELEMENT,TIMESTEPPER>::run(
00722  const unsigned& case_number)
00723 {
00724 
00725  // If there's a command line argument, run the validation (i.e. do only 
00726  // 3 timesteps; otherwise do a few cycles
00727  unsigned nstep=400;
00728  if (CommandLineArgs::Argc!=1)
00729   {
00730    nstep=3;
00731   }
00732 
00733  // Define output directory
00734  char dirname[100];
00735  sprintf(dirname,"RESLT%i",case_number);
00736  Doc_info.set_directory(dirname);
00737 
00738  // Step number
00739  Doc_info.number()=0;
00740 
00741  // Open trace file
00742  char filename[100];   
00743  sprintf(filename,"%s/trace.dat",Doc_info.directory().c_str());
00744  Trace_file.open(filename);
00745 
00746  // Set up trace nodes as the nodes on boundary 1 (=curved boundary) in 
00747  // the original mesh (they exist under any refinement!) 
00748  unsigned nnod0=solid_mesh_pt()->nboundary_node(0);
00749  unsigned nnod1=solid_mesh_pt()->nboundary_node(1);
00750  Trace_file << "VARIABLES=\"time\"";
00751  for (unsigned j=0;j<nnod0;j++)
00752   {
00753    Trace_file << ", \"radial node " << j << "\" ";
00754   }
00755  for (unsigned j=0;j<nnod1;j++)
00756   {
00757    Trace_file << ", \"azimuthal node " << j << "\" ";
00758   }
00759  Trace_file << std::endl;
00760 
00761 
00762 
00763 //  // Restart?
00764 //  //---------
00765 
00766 //  // Pointer to restart file
00767 //  ifstream* restart_file_pt=0;
00768 
00769 //  // No restart
00770 //  //-----------
00771 //  if (CommandLineArgs::Argc==1)
00772 //   {
00773 //    cout << "No restart" << std::endl;
00774 //   }
00775 //  // Restart
00776 //  //--------
00777 //  else if (CommandLineArgs::Argc==2)
00778 //   {
00779 //    // Open restart file
00780 //    restart_file_pt=new ifstream(CommandLineArgs::Argv[1],ios_base::in);
00781 //    if (restart_file_pt!=0)
00782 //     {
00783 //      cout << "Have opened " << CommandLineArgs::Argv[1] << 
00784 //       " for restart. " << std::endl;
00785 //     }
00786 //    else
00787 //     {
00788 //      cout << "ERROR while trying to open " << CommandLineArgs::Argv[1] << 
00789 //       " for restart." << std::endl;
00790 //     }
00791 //    // Do the actual restart
00792 //    pause("need to do the actual restart");
00793 //    //problem.restart(*restart_file_pt);
00794 //   }
00795 //  // More than one restart file specified?
00796 //  else 
00797 //   {
00798 //    cout << "Can only specify one input file " << std::endl;
00799 //    cout << "You specified the following command line arguments: " << std::endl;
00800 //    CommandLineArgs::output();
00801 //    //assert(false);
00802 //   }
00803 
00804 
00805  // Initial parameter values
00806  Global_Physical_Variables::P = 0.1; 
00807 
00808  // Initialise time
00809  double time0=0.0;
00810  time_pt()->time()=time0;
00811 
00812  // Set initial timestep
00813  double dt=0.01; 
00814 
00815  // Impulsive start
00816  assign_initial_values_impulsive(dt); 
00817  
00818  // Doc initial state
00819  doc_solution();
00820  Doc_info.number()++;
00821 
00822  // First step without adaptivity
00823  unsteady_newton_solve(dt); 
00824  doc_solution();
00825  Doc_info.number()++;
00826 
00827  //Timestepping loop for subsequent steps with adaptivity
00828  unsigned max_adapt=1;
00829  for(unsigned i=1;i<nstep;i++)
00830   {
00831    unsteady_newton_solve(dt,max_adapt,false);
00832    doc_solution();
00833    Doc_info.number()++;
00834   }
00835 
00836 }
00837 
00838 
00839 
00840 
00841 
00842 //======================================================================
00843 /// Driver for simple elastic problem
00844 //======================================================================
00845 int main(int argc, char* argv[])
00846 {
00847 
00848  // Store command line arguments
00849  CommandLineArgs::setup(argc,argv);
00850 
00851  //Initialise physical parameters
00852  Global_Physical_Variables::E = 1.0; // ADJUST 
00853  Global_Physical_Variables::Nu = 0.3; // ADJUST
00854 
00855   // "Big G" Linear constitutive equations:
00856   Global_Physical_Variables::Constitutive_law_pt = 
00857    new GeneralisedHookean(&Global_Physical_Variables::Nu,
00858                           &Global_Physical_Variables::E);
00859  
00860   //Set up the problem:
00861   unsigned case_number=0;
00862 
00863 
00864  // Pure displacement formulation
00865   {
00866    cout << "Running case " << case_number 
00867         << ": Pure displacement formulation" << std::endl;
00868    DiskShockWaveProblem<RefineableQPVDElement<2,3>, Newmark<1> > problem;
00869    problem.run(case_number);
00870    case_number++;
00871   }
00872    
00873  // Pressure-displacement with Crouzeix Raviart-type pressure
00874   {
00875    cout << "Running case " << case_number 
00876         << ": Pressure/displacement with Crouzeix-Raviart pressure" << std::endl;
00877    DiskShockWaveProblem<RefineableQPVDElementWithPressure<2>, Newmark<1> >
00878     problem;
00879    problem.run(case_number);
00880    case_number++;
00881   }
00882 
00883 
00884   // Pressure-displacement with Taylor-Hood-type pressure
00885   {
00886    cout << "Running case " << case_number 
00887         << ": Pressure/displacement with Taylor-Hood pressure" << std::endl;
00888    DiskShockWaveProblem<RefineableQPVDElementWithContinuousPressure<2>, 
00889     Newmark<1> > problem;
00890    problem.run(case_number);
00891    case_number++;
00892   }
00893 
00894  
00895  // Clean up 
00896  delete Global_Physical_Variables::Constitutive_law_pt;
00897  Global_Physical_Variables::Constitutive_law_pt=0;
00898 
00899 }
00900 
00901 
00902 
00903 
00904 
00905 
00906 
00907 

Generated on Mon Aug 10 11:39:29 2009 by  doxygen 1.4.7