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 #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
1.4.7