action functions
|
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 if you wish to be informed of the library's "official" release. |
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
1.4.7