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.

quarter_tube_mesh.template.h

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 #ifndef OOMPH_QUARTER_TUBE_MESH_HEADER
00029 #define OOMPH_QUARTER_TUBE_MESH_HEADER
00030 
00031 // Headers
00032 #include "../generic/refineable_brick_mesh.h"
00033 #include "../generic/macro_element.h"
00034 #include "../generic/domain.h"
00035 #include "../generic/algebraic_elements.h"
00036 #include "../generic/brick_mesh.h"
00037 #include "../generic/macro_element_node_update_element.h"
00038 
00039 
00040 //Include the headers file for domain
00041 #include "quarter_tube_domain.h"
00042 
00043 namespace oomph
00044 {
00045 
00046 
00047 //====================================================================
00048 /// \short 3D quarter tube mesh class.
00049 /// The domain is specified by the GeomObject that identifies 
00050 /// boundary 3. Non-refineable base version!
00051 /// \n
00052 /// The mesh boundaries are numbered as follows:
00053 /// - Boundary 0: "Inflow" cross section; located along the 
00054 ///               line parametrised by \f$ \xi_0 =  \xi_0^{lo} \f$
00055 ///               on the geometric object that specifies the wall.
00056 /// - Boundary 1: Plane x=0
00057 /// - Boundary 2: Plane y=0
00058 /// - Boundary 3: The curved wall
00059 /// - Boundary 4: "Outflow" cross section; located along the 
00060 ///               line parametrised by \f$ \xi_0 =  \xi_0^{hi} \f$
00061 ///               on the geometric object that specifies the wall.
00062 ///
00063 /// IMPORTANT NOTE: The interface looks more general than it should.
00064 ///                 The toplogy must remain that of a quarter tube,
00065 ///                 or the mesh generation will break. 
00066 //====================================================================
00067 template <class ELEMENT>
00068 class QuarterTubeMesh : public virtual BrickMeshBase
00069 {
00070 
00071 public:
00072 
00073  /// \short Constructor: Pass pointer to geometric object that
00074  /// specifies the wall, start and end coordinates on the 
00075  /// geometric object, and the fraction along
00076  /// which the dividing line is to be placed, and the timestepper.
00077  /// Timestepper defaults to Steady dummy timestepper.
00078   QuarterTubeMesh(GeomObject* wall_pt,
00079                  const Vector<double>& xi_lo,
00080                  const double& fract_mid,
00081                  const Vector<double>& xi_hi,
00082                  const unsigned& nlayer,
00083                  TimeStepper* time_stepper_pt=
00084                  &Mesh::Default_TimeStepper);
00085 
00086  /// \short Destructor: empty
00087  virtual ~QuarterTubeMesh()
00088   {
00089    delete Domain_pt;
00090   }
00091 
00092  /// Access function to GeomObject representing wall
00093  GeomObject*& wall_pt(){return Wall_pt;}
00094 
00095  /// Access function to domain
00096  QuarterTubeDomain* domain_pt(){return Domain_pt;}
00097 
00098  /// \short Function pointer for function that squashes
00099  /// the outer macro elements towards 
00100  /// the wall by mapping the input value of the "radial" macro element
00101  /// coordinate to the return value (defined in the underlying Domain object)
00102  QuarterTubeDomain::BLSquashFctPt& bl_squash_fct_pt()
00103   {
00104    return Domain_pt->bl_squash_fct_pt();
00105   }
00106 
00107 
00108  /// \short Function pointer for function that hierher
00109  virtual QuarterTubeDomain::AxialSpacingFctPt& axial_spacing_fct_pt()
00110   {
00111    return Domain_pt->axial_spacing_fct_pt();
00112   }
00113 
00114  /// Access function to underlying domain
00115  QuarterTubeDomain* domain_pt() const {return Domain_pt;}
00116 
00117 protected:
00118 
00119  /// Pointer to domain
00120  QuarterTubeDomain* Domain_pt;
00121 
00122  /// Pointer to the geometric object that represents the curved wall
00123  GeomObject* Wall_pt;
00124 
00125  /// Lower limits for the coordinates along the wall
00126  Vector<double> Xi_lo;
00127 
00128  /// Fraction along wall where outer ring is to be divided
00129  double Fract_mid;
00130 
00131  /// Upper limits for the coordinates along the wall
00132  Vector<double> Xi_hi;
00133 
00134 };
00135 
00136 
00137 
00138 
00139 ////////////////////////////////////////////////////////////////////
00140 ////////////////////////////////////////////////////////////////////
00141 ////////////////////////////////////////////////////////////////////
00142 
00143 
00144 
00145 
00146 
00147 //=============================================================
00148 /// Adaptative version of the QuarterTubeMesh base mesh.
00149 /// The domain is specified by the GeomObject that identifies 
00150 /// boundary 3.
00151 /// \n
00152 /// The mesh boundaries are numbered as follows:
00153 /// - Boundary 0: "Inflow" cross section; located along the 
00154 ///               line parametrised by \f$ \xi_0 =  \xi_0^{lo} \f$
00155 ///               on the geometric object that specifies the wall.
00156 /// - Boundary 1: Plane x=0
00157 /// - Boundary 2: Plane y=0
00158 /// - Boundary 3: The curved wall
00159 /// - Boundary 4: "Outflow" cross section; located along the 
00160 ///               line parametrised by \f$ \xi_0 =  \xi_0^{hi} \f$
00161 ///               on the geometric object that specifies the wall.
00162 //=============================================================
00163 template<class ELEMENT> 
00164 class RefineableQuarterTubeMesh : public virtual QuarterTubeMesh<ELEMENT>,
00165                                 public RefineableBrickMesh<ELEMENT>
00166                                 
00167 {
00168 
00169 public :
00170 
00171 /// \short Constructor for adaptive deformable quarter tube mesh class. 
00172 /// The domain is specified by the GeomObject that 
00173 /// identifies boundary 3. Pass pointer to geometric object that
00174 /// specifies the wall, start and end coordinates on the 
00175 /// geometric object, and the fraction along
00176 /// which the dividing line is to be placed, and the timestepper.
00177 /// Timestepper defaults to Steady dummy timestepper.
00178  RefineableQuarterTubeMesh(GeomObject* wall_pt,
00179                            const Vector<double>& xi_lo,
00180                            const double& fract_mid,
00181                            const Vector<double>& xi_hi,
00182                            const unsigned& nlayer,
00183                            TimeStepper* time_stepper_pt=
00184                            &Mesh::Default_TimeStepper):
00185   QuarterTubeMesh<ELEMENT>(wall_pt,xi_lo,fract_mid,xi_hi,
00186                            nlayer,time_stepper_pt)
00187   {
00188    // Loop over all elements and set macro element pointer
00189    for (unsigned ielem=0;ielem<QuarterTubeMesh<ELEMENT>::nelement();ielem++)
00190     {
00191      dynamic_cast<RefineableQElement<3>*>(
00192       QuarterTubeMesh<ELEMENT>::element_pt(ielem))->
00193       set_macro_elem_pt(this->Domain_pt->macro_element_pt(ielem));
00194     }
00195    
00196 
00197    // Setup Octree forest: Turn elements into individual octrees 
00198    // and plant in forest
00199    Vector<TreeRoot*> trees_pt;
00200    for (unsigned iel=0;iel<QuarterTubeMesh<ELEMENT>::nelement();iel++)
00201     {
00202      FiniteElement* el_pt=QuarterTubeMesh<ELEMENT>::finite_element_pt(iel);
00203      ELEMENT* ref_el_pt=dynamic_cast<ELEMENT*>(el_pt);
00204      OcTreeRoot* octree_root_pt=new OcTreeRoot(ref_el_pt);
00205      trees_pt.push_back(octree_root_pt);
00206     }
00207    this->Forest_pt = new OcTreeForest(trees_pt);
00208 
00209 #ifdef PARANOID
00210    // Run self test
00211    unsigned success_flag=
00212     dynamic_cast<OcTreeForest*>(this->Forest_pt)->self_test();
00213    if (success_flag==0)
00214     {
00215      oomph_info << "Successfully built octree forest " << std::endl;
00216     }
00217    else
00218     {
00219      throw OomphLibError(
00220       "Trouble in building octree forest ",
00221       "RefineableQuarterTubeMesh::RefineableQuarterTubeMesh()",
00222       OOMPH_EXCEPTION_LOCATION);
00223     }
00224 #endif
00225    
00226   }
00227  
00228  /// \short Destructor: empty
00229  virtual ~RefineableQuarterTubeMesh(){}
00230  
00231 }; 
00232 
00233 
00234 
00235 
00236 
00237 ////////////////////////////////////////////////////////////////////
00238 ////////////////////////////////////////////////////////////////////
00239 // MacroElementNodeUpdate-version of RefineableQuarterTubeMesh
00240 ////////////////////////////////////////////////////////////////////
00241 ////////////////////////////////////////////////////////////////////
00242 
00243 class MacroElementNodeUpdateNode;
00244 
00245 //========================================================================
00246 /// MacroElementNodeUpdate version of RefineableQuarterTubeMesh
00247 //========================================================================
00248 template<class ELEMENT>
00249 class MacroElementNodeUpdateRefineableQuarterTubeMesh : 
00250 public virtual MacroElementNodeUpdateMesh, 
00251 public virtual RefineableQuarterTubeMesh<ELEMENT>
00252 {
00253 
00254 
00255 public:
00256 
00257 
00258  /// \short Constructor: Pass pointer to geometric object, start and
00259  /// end coordinates on the geometric object and the fraction along
00260  /// which the dividing line is to be placed when updating the nodal positions,
00261  /// and timestepper (defaults to (Steady) default timestepper
00262  /// defined in Mesh). Setup the refineable mesh (by calling the
00263  /// constructor for the underlying  RefineableQuarterTubeMesh)
00264  /// and the algebraic node update functions for nodes.
00265  MacroElementNodeUpdateRefineableQuarterTubeMesh(GeomObject* wall_pt,
00266                            const Vector<double>& xi_lo,
00267                            const double& fract_mid,
00268                            const Vector<double>& xi_hi,
00269                            const unsigned& nlayer,
00270                            TimeStepper* time_stepper_pt=
00271                            &Mesh::Default_TimeStepper) :
00272   MacroElementNodeUpdateMesh(),
00273   RefineableQuarterTubeMesh<ELEMENT>(wall_pt,xi_lo,fract_mid,xi_hi,
00274                                      nlayer,time_stepper_pt),
00275   QuarterTubeMesh<ELEMENT>(wall_pt,xi_lo,fract_mid,xi_hi,
00276                            nlayer,time_stepper_pt)
00277   {
00278 
00279 #ifdef PARANOID
00280    ELEMENT* el_pt=new ELEMENT;
00281    if (dynamic_cast<MacroElementNodeUpdateElementBase*>(el_pt)==0)
00282     {
00283      std::ostringstream error_message;
00284      error_message 
00285       << "Base class for ELEMENT in "
00286       << "MacroElementNodeUpdateRefineableQuarterTubeMesh needs" 
00287       << "to be of type MacroElementNodeUpdateElement!\n";
00288      error_message << "Whereas it is: typeid(el_pt).name()" 
00289                    << typeid(el_pt).name() 
00290                    << std::endl;
00291      
00292      std::string function_name =
00293       "MacroElementNodeUpdateRefineableQuaterCircleSectorMesh::\n";
00294      function_name += 
00295       "MacroElementNodeUpdateRefineableQuaterCircleSectorMesh()";
00296 
00297      throw OomphLibError(error_message.str(),function_name,
00298                          OOMPH_EXCEPTION_LOCATION);
00299     }
00300    delete el_pt;
00301 #endif
00302 
00303    // Setup all the information that's required for MacroElement-based
00304    // node update: Tell the elements that their geometry depends on the
00305    // fishback geometric object
00306    this->setup_macro_element_node_update();
00307   }
00308 
00309  /// \short Destructor: empty
00310  virtual ~MacroElementNodeUpdateRefineableQuarterTubeMesh(){}
00311 
00312  /// \short Resolve mesh update: Update current nodal
00313  /// positions via sparse MacroElement-based update.
00314  /// [Doesn't make sense to use this mesh with SolidElements anyway,
00315  /// so we buffer the case if update_all_solid_nodes is set to 
00316  /// true.]
00317  void node_update(const bool& update_all_solid_nodes=false)
00318   {
00319 #ifdef PARANOID
00320    if (update_all_solid_nodes)
00321     {
00322      std::string error_message = 
00323       "Doesn't make sense to use an MacroElementNodeUpdateMesh with\n";
00324      error_message += 
00325       "SolidElements so specifying update_all_solid_nodes=true\n";
00326      error_message += "doesn't make sense either\n";
00327 
00328      std::string function_name =
00329       "MacroElementNodeUpdateRefineableQuaterCircleSectorMesh::\n";
00330      function_name += "node_update()";
00331 
00332      throw OomphLibError(error_message,function_name,
00333                          OOMPH_EXCEPTION_LOCATION);
00334     }
00335 #endif
00336    MacroElementNodeUpdateMesh::node_update();
00337   }
00338 
00339   private:
00340 
00341  /// \short Setup all the information that's required for MacroElement-based
00342  /// node update: Tell the elements that their geometry depends on the
00343  /// geometric object that parametrises the wall
00344  void setup_macro_element_node_update()
00345   {
00346    unsigned n_element = this->nelement();
00347    for(unsigned i=0;i<n_element;i++)
00348     {
00349      // Upcast from FiniteElement to the present element
00350      ELEMENT *el_pt = dynamic_cast<ELEMENT*>(this->element_pt(i));
00351      
00352 #ifdef PARANOID
00353      // Check if cast is successful
00354      MacroElementNodeUpdateElementBase* m_el_pt=dynamic_cast<
00355       MacroElementNodeUpdateElementBase*>(el_pt);
00356      if (m_el_pt==0)
00357       {
00358        std::ostringstream error_message;
00359        error_message 
00360         << "Failed to upcast to MacroElementNodeUpdateElementBase\n";
00361        error_message
00362         << "Element must be derived from MacroElementNodeUpdateElementBase\n";
00363        error_message << "but it is of type " << typeid(el_pt).name();
00364        
00365        std::string function_name =
00366         "MacroElementNodeUpdateRefineableQuaterCircleSectorMesh::\n";
00367        function_name += "setup_macro_element_node_update()";
00368        
00369        throw OomphLibError(error_message.str(),function_name,
00370                            OOMPH_EXCEPTION_LOCATION);
00371       }
00372 #endif       
00373      // There's just one GeomObject
00374      Vector<GeomObject*> geom_object_pt(1);
00375      geom_object_pt[0] = this->Wall_pt;
00376      
00377      // Tell the element which geom objects its macro-element-based
00378      // node update depends on     
00379      el_pt->set_node_update_info(geom_object_pt);
00380     }
00381 
00382    // Add the geometric object(s) for the wall to the mesh's storage
00383    Vector<GeomObject*> geom_object_pt(1);
00384    geom_object_pt[0] = this->Wall_pt;
00385    MacroElementNodeUpdateMesh::set_geom_object_vector_pt(geom_object_pt);
00386 
00387    // Fill in the domain pointer to the mesh's storage in the base class
00388    MacroElementNodeUpdateMesh::macro_domain_pt()=this->domain_pt();
00389 
00390   }
00391 };
00392 
00393 
00394 
00395 //======================================================================
00396 /// AlgebraicMesh version of RefineableQuarterTubeMesh
00397 //=====================================================================
00398 
00399 
00400 //====================================================================
00401 /// \short Algebraic 3D quarter tube mesh class.
00402 /// \n
00403 /// The mesh boundaries are numbered as follows:
00404 /// - Boundary 0: "Inflow" cross section; located along the
00405 ///               line parametrised by \f$ \xi_0 =  \xi_0^{lo} \f$
00406 ///               on the geometric object that specifies the wall.
00407 /// - Boundary 1: Plane x=0
00408 /// - Boundary 2: Plane y=0
00409 /// - Boundary 3: The curved wall - specified by the GeomObject
00410 ///               passed to the mesh constructor.
00411 /// - Boundary 4: "Outflow" cross section; located along the
00412 ///               line parametrised by \f$ \xi_0 =  \xi_0^{hi} \f$
00413 ///               on the geometric object that specifies the wall.
00414 //====================================================================
00415 
00416 
00417 
00418 //========================================================================
00419 /// Algebraic version of RefineableQuarterTubeMesh
00420 ///
00421 /// Cross section through mesh looking along tube.........
00422 ///
00423 ///                      ---___
00424 ///                     |      ---____
00425 ///                     |              -   BOUNDARY 3
00426 ///                     |                /
00427 ///                     |  [Region 2]   /  |
00428 ///                     |              /     |
00429 ///                     | N           /        |
00430 ///                     | |_ E       /          |
00431 ///       BOUNDARY 1    |------------            |
00432 ///                     |            |            |
00433 ///                     | [Region 0] | [Region 1] |  ^
00434 ///                     |            |            | / \  direction of
00435 ///                     | N          |    N       |  |   2nd Lagrangian
00436 ///                     | |_ E       |    |_ E    |  |   coordinate
00437 ///                     |____________|____________|  |   along wall GeomObject
00438 ///
00439 ///                           BOUNDARY 2
00440 ///
00441 /// The Domain is built of slices each consisting of three
00442 /// MacroElements as sketched.
00443 /// The local coordinates are such that the (E)astern direction
00444 /// coincides with the positive s_0 direction, while the
00445 /// (N)orther direction coincides with the positive s_1 direction.
00446 /// The positive s_2 direction points down the tube.
00447 ///
00448 /// Elements need to be derived from AlgebraicElementBase. In
00449 /// addition to the refinement procedures available for the
00450 /// RefineableQuarterTubeMesh which forms the basis for this mesh,
00451 /// three algebraic node update functions are implemented for the nodes
00452 /// in the three regions defined by the Domain MacroElements.
00453 /// Note: it is assumed the cross section down the tube is
00454 /// uniform when setup_algebraic_node_update() is called.
00455 //========================================================================
00456 template<class ELEMENT>
00457 class AlgebraicRefineableQuarterTubeMesh :
00458  public virtual AlgebraicMesh,
00459  public RefineableQuarterTubeMesh<ELEMENT>
00460 {
00461 
00462 public:
00463 
00464  /// \short Constructor: Pass pointer to geometric object, start and
00465  /// end coordinates of the geometric object and the fraction along
00466  /// the 2nd Lagrangian coordinate at which the dividing line between
00467  /// region 1 and region 2 is to be placed, and timestepper
00468  /// (defaults to (Steady) default timestepper defined in Mesh).
00469  /// Sets up the refineable mesh (by calling the constructor for the
00470  /// underlying RefineableQuarterTubeMesh).
00471  AlgebraicRefineableQuarterTubeMesh(GeomObject* wall_pt,
00472                                     const Vector<double>& xi_lo,
00473                                     const double& fract_mid,
00474                                     const Vector<double>& xi_hi,
00475                                     const unsigned& nlayer,
00476                                     const double centre_box_size=1.0,
00477                                     TimeStepper* time_stepper_pt=
00478                                     &Mesh::Default_TimeStepper) :
00479   QuarterTubeMesh<ELEMENT>(wall_pt, xi_lo, fract_mid, xi_hi,
00480                            nlayer, time_stepper_pt),
00481   RefineableQuarterTubeMesh<ELEMENT>(wall_pt,xi_lo,fract_mid,xi_hi,
00482                                      nlayer, time_stepper_pt),
00483   Centre_box_size(centre_box_size)
00484   {
00485 
00486 #ifdef PARANOID
00487    ELEMENT* el_pt=new ELEMENT;
00488    if (dynamic_cast<AlgebraicElementBase*>(el_pt)==0)
00489     {
00490      std::ostringstream error_message;
00491 
00492      error_message << "Base class for ELEMENT in "
00493                    << "AlgebraicRefineableQuarterTubeMesh needs"
00494                    << "to be of type AlgebraicElement!\n";
00495      error_message << "Whereas it is: typeid(el_pt).name()"
00496                    << typeid(el_pt).name()
00497                    << std::endl;
00498 
00499      std::string function_name =
00500       " AlgebraicRefineableQuarterTubeMesh::\n";
00501      function_name += "AlgebraicRefineableQuarterTubeMesh()";
00502 
00503      throw OomphLibError(error_message.str(),function_name,
00504                          OOMPH_EXCEPTION_LOCATION);
00505     }
00506    delete el_pt;
00507 #endif
00508 
00509    // Add the geometric object to the list associated with this AlgebraicMesh
00510    AlgebraicMesh::add_geom_object_list_pt(wall_pt);
00511 
00512    // Setup algebraic node update operations
00513    setup_algebraic_node_update();
00514 
00515    // Ensure nodes are in their default position
00516    node_update();
00517   }
00518 
00519  /// Run self-test for algebraic mesh -- return 0/1 for OK/failure
00520  unsigned self_test()
00521   {
00522    return AlgebraicMesh::self_test();
00523   }
00524 
00525  /// \short Broken version of the QuarterTubeDomain function
00526  /// Function is broken because axial spacing isn't implemented
00527  /// yet for the Algebraic version of the RefineableQuarterTubeMesh.
00528  /// Note: this function must be used BEFORE algebraic_node_update(...)
00529  /// is called.
00530  QuarterTubeDomain::AxialSpacingFctPt& axial_spacing_fct_pt()
00531   {
00532    std::ostringstream error_message;
00533    error_message << "AxialSpacingFctPt has not been implemented "
00534                  << "for the AlgebraicRefineableQuarterTubeMesh\n";
00535 
00536    std::string function_name =
00537     " AlgebraicRefineableQuarterTubeMesh::AxialSpacingFctPt()";
00538 
00539    throw OomphLibError(error_message.str(),function_name,
00540                        OOMPH_EXCEPTION_LOCATION);
00541 
00542    return this->Domain_pt->axial_spacing_fct_pt();
00543   }
00544 
00545  /// \short Resolve mesh update: Update current nodal
00546  /// positions via algebraic node update.
00547  /// [Doesn't make sense to use this mesh with SolidElements anyway,
00548  /// so we buffer the case if update_all_solid_nodes is set to
00549  /// true.]
00550  void node_update(const bool& update_all_solid_nodes=false)
00551   {
00552 #ifdef PARANOID
00553    if (update_all_solid_nodes)
00554     {
00555      std::string error_message =
00556       "Doesn't make sense to use an AlgebraicMesh with\n";
00557      error_message +=
00558       "SolidElements so specifying update_all_solid_nodes=true\n";
00559      error_message += "doesn't make sense either\n";
00560 
00561      std::string function_name =
00562       " AlgebraicRefineableQuarterTubeMesh::";
00563      function_name += "node_update()";
00564 
00565      throw OomphLibError(error_message,function_name,
00566                          OOMPH_EXCEPTION_LOCATION);
00567     }
00568 #endif
00569 
00570    AlgebraicMesh::node_update();
00571   }
00572 
00573 
00574  /// \short Implement the algebraic node update function for a node
00575  /// at time level t (t=0: present; t>0: previous): Update with
00576  /// the node's first (default) update function.
00577  void algebraic_node_update(const unsigned& t, AlgebraicNode*& node_pt)
00578   {
00579    // Update with the update function for the node's first (default)
00580    // node update fct
00581    unsigned id=node_pt->node_update_fct_id();
00582 
00583    switch (id)
00584     {
00585 
00586     case Central_region:
00587 
00588      // Central region
00589      node_update_central_region(t,node_pt);
00590      break;
00591 
00592     case Lower_right_region:
00593 
00594      // Lower right region
00595      node_update_lower_right_region(t,node_pt);
00596      break;
00597 
00598     case Upper_left_region:
00599 
00600      // Upper left region
00601      node_update_upper_left_region(t,node_pt);
00602      break;
00603 
00604     default:
00605 
00606      std::ostringstream error_message;
00607      error_message << "The node update fct id is "
00608                    << id << ", but it should only be one of "
00609                    << Central_region  << ", "
00610                    << Lower_right_region << " or "
00611                    << Upper_left_region << std::endl;
00612      std::string function_name =
00613       " AlgebraicRefineableQuarterTubeMesh::";
00614      function_name += "algebraic_node_update()";
00615 
00616      throw OomphLibError(error_message.str(),function_name,
00617                          OOMPH_EXCEPTION_LOCATION);
00618     }
00619   }
00620 
00621  /// \short Update the node update info for specified algebraic node
00622  /// following any spatial mesh adaptation.
00623  void update_node_update(AlgebraicNode*& node_pt)
00624   {
00625    // Get all node update fct for this node (resizes internally)
00626    Vector<int> id;
00627    node_pt->node_update_fct_id(id);
00628 
00629    // Loop over all update fcts
00630    unsigned n_update=id.size();
00631    for (unsigned i=0;i<n_update;i++)
00632     {
00633      update_node_update_in_region(node_pt, id[i]);
00634     }
00635 
00636   }
00637 
00638 private:
00639 
00640  /// Size of centre box
00641  double Centre_box_size;
00642 
00643  /// Remesh function ids
00644  enum{Central_region, Lower_right_region, Upper_left_region};
00645 
00646  /// Fractional width of central region
00647  double Lambda_x;
00648 
00649  /// Fractional height of central region
00650  double Lambda_y;
00651 
00652  /// \short Algebraic update function for a node that is located
00653  /// in the central region
00654  void node_update_central_region(const unsigned& t,
00655                                  AlgebraicNode*& node_pt);
00656 
00657  /// \short Algebraic update function for a node that is located
00658  /// in the lower-right region
00659  void node_update_lower_right_region(const unsigned& t,
00660                                      AlgebraicNode*& node_pt);
00661 
00662  /// \short Algebraic update function for a node that is located
00663  /// in the upper-left region
00664  void node_update_upper_left_region(const unsigned& t,
00665                                     AlgebraicNode*& node_pt);
00666 
00667  /// \short Setup algebraic update operation for all nodes
00668  void setup_algebraic_node_update();
00669 
00670  /// \short Update algebraic node update function for nodes in
00671  /// the region defined by region_id
00672  void update_node_update_in_region(AlgebraicNode*& node_pt,
00673                                    int& region_id);
00674 
00675 };
00676 
00677 
00678 }
00679 #endif

Generated on Mon Aug 10 11:23:49 2009 by  doxygen 1.4.7