fish_mesh.template.h
Go to the documentation of this file.
1 // LIC// ====================================================================
2 // LIC// This file forms part of oomph-lib, the object-oriented,
3 // LIC// multi-physics finite-element library, available
4 // LIC// at http://www.oomph-lib.org.
5 // LIC//
6 // LIC// Copyright (C) 2006-2024 Matthias Heil and Andrew Hazel
7 // LIC//
8 // LIC// This library is free software; you can redistribute it and/or
9 // LIC// modify it under the terms of the GNU Lesser General Public
10 // LIC// License as published by the Free Software Foundation; either
11 // LIC// version 2.1 of the License, or (at your option) any later version.
12 // LIC//
13 // LIC// This library is distributed in the hope that it will be useful,
14 // LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // LIC// Lesser General Public License for more details.
17 // LIC//
18 // LIC// You should have received a copy of the GNU Lesser General Public
19 // LIC// License along with this library; if not, write to the Free Software
20 // LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 // LIC// 02110-1301 USA.
22 // LIC//
23 // LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
24 // LIC//
25 // LIC//====================================================================
26 #ifndef OOMPH_FISH_MESH_HEADER
27 #define OOMPH_FISH_MESH_HEADER
28 
29 // Headers
30 #include "../generic/refineable_quad_mesh.h"
31 #include "../generic/macro_element.h"
32 #include "../generic/domain.h"
33 #include "../generic/algebraic_elements.h"
34 #include "../generic/quad_mesh.h"
35 #include "../generic/macro_element_node_update_element.h"
36 
37 // Include algebraic elements
38 #include "../generic/algebraic_elements.h"
39 
40 // Include the macro element node update elements
41 #include "../generic/macro_element_node_update_element.h"
42 
43 
44 // Include the headers file for domain
45 #include "fish_domain.h"
46 
47 namespace oomph
48 {
49  //=================================================================
50  /// Fish shaped mesh. The geometry is defined by
51  /// the Domain object FishDomain.
52  //=================================================================
53  template<class ELEMENT>
54  class FishMesh : public virtual QuadMeshBase
55  {
56  public:
57  /// Constructor: Pass pointer to timestepper
58  /// (defaults to the (Steady) default timestepper defined in Mesh)
59  FishMesh(TimeStepper* time_stepper_pt = &Mesh::Default_TimeStepper);
60 
61  /// Constructor: Pass pointer GeomObject that defines
62  /// the fish's back and pointer to timestepper
63  /// (defaults to the (Steady) default timestepper defined in Mesh)
64  FishMesh(GeomObject* back_pt,
65  TimeStepper* time_stepper_pt = &Mesh::Default_TimeStepper);
66 
67  /// Destructor: Kill the geom object that represents the fish's back
68  /// (if necessary)
69  virtual ~FishMesh()
70  {
72  {
73  delete Back_pt;
74  Back_pt = 0;
75  }
76  }
77 
78  /// Access function to geom object that represents the fish's back
79  GeomObject*& fish_back_pt()
80  {
81  return Back_pt;
82  }
83 
84 
85  /// Access function to FishDomain
87  {
88  return Domain_pt;
89  }
90 
91  protected:
92  /// Remesh function ids
93  enum
94  {
98  Upper_fin
99  };
100 
101  /// Build the mesh, using the geometric object identified by Back_pt
102  void build_mesh(TimeStepper* time_stepper_pt);
103 
104  /// Pointer to fish back
105  GeomObject* Back_pt;
106 
107  /// Pointer to domain
109 
110  /// Do I need to kill the fish back geom object?
112  };
113 
114 
115  /// ////////////////////////////////////////////////////////////////////
116  /// ////////////////////////////////////////////////////////////////////
117  // Refineable fish-shaped mesh
118  /// ////////////////////////////////////////////////////////////////////
119  /// ////////////////////////////////////////////////////////////////////
120 
121 
122  //=================================================================
123  /// Refineable fish shaped mesh. The geometry is defined by
124  /// the Domain object FishDomain.
125  //=============================start_adaptive_fish_mesh============
126  template<class ELEMENT>
127  class RefineableFishMesh : public virtual FishMesh<ELEMENT>,
128  public RefineableQuadMesh<ELEMENT>
129  {
130  public:
131  /// Constructor: Pass pointer to timestepper -- defaults to (Steady)
132  /// default timestepper defined in the Mesh base class
134  TimeStepper* time_stepper_pt = &Mesh::Default_TimeStepper)
135  : FishMesh<ELEMENT>(time_stepper_pt)
136  {
137  // Nodal positions etc. were created in constructor for
138  // FishMesh<...>. Only need to setup adaptive information.
139 
140  // Do what it says....
142 
143  } // end of constructor
144 
145 
146  /// Constructor: Pass pointer GeomObject that defines
147  /// the fish's back and pointer to timestepper
148  /// (defaults to (Steady) default timestepper defined in Mesh)
150  GeomObject* back_pt,
151  TimeStepper* time_stepper_pt = &Mesh::Default_TimeStepper)
152  : FishMesh<ELEMENT>(back_pt, time_stepper_pt)
153  {
154  // Nodal positions etc. were created in constructor for
155  // FishMesh<...>. Only need to setup adaptive information.
156 
157  // Do what it says....
159  }
160 
161  /// Destructor: Empty -- all cleanup gets handled in the base
162  /// classes
163  virtual ~RefineableFishMesh() {}
164 
165 
166  protected:
167  /// Setup all the information that's required for spatial adaptivity:
168  /// Set pointers to macro elements and build quadtree forest.
169  /// (contained in separate function as this functionality is common
170  /// to both constructors),
171  void setup_adaptivity();
172 
173  }; // end adaptive fish mesh
174 
175 
176  /// /////////////////////////////////////////////////////////////////
177  /// /////////////////////////////////////////////////////////////////
178  // MacroElementNodeUpdate-version of RefineableFishMesh
179  /// /////////////////////////////////////////////////////////////////
180  /// /////////////////////////////////////////////////////////////////
181 
182  // Forward declaration
183  class MacroElementNodeUpdateNode;
184 
185 
186  //========================================================================
187  /// Refineable fish shaped mesh with MacroElement-based node update.
188  /// The fish's back is represented by a specified geometric object.
189  /// Some or all of the geometric Data in that geometric object
190  /// may contain unknowns in the global Problem. The dependency
191  /// on these unknowns is taken into account when setting up
192  /// the Jacobian matrix of the elements. For this purpose,
193  /// the element (whose type is specified by the template parameter)
194  /// must inherit from MacroElementNodeUpdateElementBase.
195  //========================================================================
196  template<class ELEMENT>
198  : public virtual MacroElementNodeUpdateMesh,
199  public virtual RefineableFishMesh<ELEMENT>
200  {
201  public:
202  /// Constructor: Pass pointer GeomObject that defines
203  /// the fish's back and pointer to timestepper
204  /// (defaults to (Steady) default timestepper defined in Mesh).
206  GeomObject* back_pt,
207  TimeStepper* time_stepper_pt = &Mesh::Default_TimeStepper)
208  : FishMesh<ELEMENT>(back_pt, time_stepper_pt),
209  RefineableFishMesh<ELEMENT>(time_stepper_pt)
210  {
211 #ifdef PARANOID
212  ELEMENT* el_pt = new ELEMENT;
213  if (dynamic_cast<MacroElementNodeUpdateElementBase*>(el_pt) == 0)
214  {
215  std::ostringstream error_message;
216  error_message << "Base class for ELEMENT in "
217  << "MacroElementNodeUpdateRefineableFishMesh needs"
218  << "to be of type MacroElementNodeUpdateElement!\n";
219  error_message << "Whereas it is: typeid(el_pt).name()"
220  << typeid(el_pt).name() << std::endl;
221 
222  std::string function_name =
223  "MacroElementNodeUpdateRefineableFishMesh::\n";
224  function_name += "MacroElementNodeUpdateRefineableFishMesh()";
225 
226  throw OomphLibError(error_message.str(),
227  OOMPH_CURRENT_FUNCTION,
228  OOMPH_EXCEPTION_LOCATION);
229  }
230  delete el_pt;
231 #endif
232 
233 
234  // Setup all the information that's required for MacroElement-based
235  // node update: Tell the elements that their geometry depends on the
236  // fishback geometric object
237  unsigned n_element = this->nelement();
238  for (unsigned i = 0; i < n_element; i++)
239  {
240  // Upcast from FiniteElement to the present element
241  ELEMENT* el_pt = dynamic_cast<ELEMENT*>(this->element_pt(i));
242 
243 #ifdef PARANOID
244  // Check if cast is successful
245  MacroElementNodeUpdateElementBase* m_el_pt =
246  dynamic_cast<MacroElementNodeUpdateElementBase*>(el_pt);
247  if (m_el_pt == 0)
248  {
249  std::ostringstream error_message;
250  error_message
251  << "Failed to upcast to MacroElementNodeUpdateElementBase\n";
252  error_message << "Element must be derived from "
253  "MacroElementNodeUpdateElementBase\n";
254  error_message << "but it is of type " << typeid(el_pt).name();
255 
256  std::string function_name =
257  "MacroElementNodeUpdateRefineableFishMesh::\n";
258  function_name += "MacroElementNodeUpdateRefinableFishMesh()";
259 
260  throw OomphLibError(error_message.str(),
261  OOMPH_CURRENT_FUNCTION,
262  OOMPH_EXCEPTION_LOCATION);
263  }
264 #endif
265  // There's just one GeomObject
266  Vector<GeomObject*> geom_object_pt(1);
267  geom_object_pt[0] = this->Back_pt;
268 
269  // Tell the element which geom objects its macro-element-based
270  // node update depends on
271  el_pt->set_node_update_info(geom_object_pt);
272  }
273 
274  // Add the geometric object(s) for the wall to the mesh's storage
275  Vector<GeomObject*> geom_object_pt(1);
276  geom_object_pt[0] = this->Back_pt;
277  MacroElementNodeUpdateMesh::set_geom_object_vector_pt(geom_object_pt);
278 
279  // Fill in the domain pointer to the mesh's storage in the base class
280  MacroElementNodeUpdateMesh::macro_domain_pt() = this->domain_pt();
281  }
282 
283  /// Destructor: empty
285 
286  /// Resolve mesh update: NodeUpdate current nodal
287  /// positions via sparse MacroElement-based update.
288  /// [Doesn't make sense to use this mesh with SolidElements anyway,
289  /// so we buffer the case if update_all_solid_nodes is set to
290  /// true.]
291  void node_update(const bool& update_all_solid_nodes = false)
292  {
293 #ifdef PARANOID
294  if (update_all_solid_nodes)
295  {
296  std::string error_message =
297  "Doesn't make sense to use an MacroElementNodeUpdateMesh with\n";
298  error_message +=
299  "SolidElements so specifying update_all_solid_nodes=true\n";
300  error_message += "doesn't make sense either\n";
301 
302  std::string function_name =
303  "MacroElementNodeUpdateRefineableFishMesh::";
304  function_name += "node_update()";
305 
306  throw OomphLibError(
307  error_message, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
308  }
309 #endif
310  MacroElementNodeUpdateMesh::node_update();
311  }
312  };
313 
314 
315  /// ////////////////////////////////////////////////////////////////////
316  /// ////////////////////////////////////////////////////////////////////
317  // AlgebraicElement fish-shaped mesh
318  /// ////////////////////////////////////////////////////////////////////
319  /// ////////////////////////////////////////////////////////////////////
320 
321 
322  //=================================================================
323  /// Fish shaped mesh with algebraic node update function for nodes.
324  //=================================================================
325  template<class ELEMENT>
326  class AlgebraicFishMesh : public AlgebraicMesh,
327  public virtual FishMesh<ELEMENT>
328  {
329  public:
330  /// Constructor: Pass pointer to timestepper.
331  /// (defaults to (Steady) default timestepper defined in Mesh)
332  AlgebraicFishMesh(TimeStepper* time_stepper_pt = &Mesh::Default_TimeStepper)
333  : FishMesh<ELEMENT>(time_stepper_pt)
334  {
335  // Setup algebraic node update operations
337  }
338 
339  /// Constructor: Pass pointer GeomObject that defines
340  /// the fish's back and pointer to timestepper
341  /// (defaults to (Steady) default timestepper defined in Mesh).
342  AlgebraicFishMesh(GeomObject* back_pt,
343  TimeStepper* time_stepper_pt = &Mesh::Default_TimeStepper)
344  : FishMesh<ELEMENT>(back_pt, time_stepper_pt)
345  {
346  // Add the geometric object to the list associated with this AlgebraicMesh
347  AlgebraicMesh::add_geom_object_list_pt(back_pt);
348 
349  // Setup algebraic node update operations
351  }
352 
353  /// Destructor: empty
354  virtual ~AlgebraicFishMesh() {}
355 
356  /// Update nodal position at time level t (t=0: present;
357  /// t>0: previous)
358  void algebraic_node_update(const unsigned& t, AlgebraicNode*& node_pt)
359  {
360  // Update with the update function for the node's first (default)
361  // node update fct
362  unsigned id = node_pt->node_update_fct_id();
363 
364  // Upper/lower body
365  if ((id == this->Lower_body) || (id == this->Upper_body))
366  {
367  node_update_in_body(t, node_pt);
368  }
369  // Upper/lower fin
370  else if ((id == this->Lower_fin) || (id == this->Upper_fin))
371  {
372  node_update_in_fin(t, node_pt);
373  }
374  else
375  {
376  std::ostringstream error_message;
377  error_message << "The node update fct id is " << id
378  << ", but it should only be one of " << this->Lower_body
379  << ", " << this->Upper_body << ", " << this->Lower_fin
380  << " or " << this->Upper_fin << std::endl;
381  std::string function_name =
382  "AlgebraicFishMesh::algebraic_node_update()";
383 
384  throw OomphLibError(error_message.str(),
385  OOMPH_CURRENT_FUNCTION,
386  OOMPH_EXCEPTION_LOCATION);
387  }
388  }
389 
390  /// Resolve the node update function (we neither want the broken
391  /// empty one in the Mesh base class nor the macro-element-based one in the
392  /// RefineableQuadMesh base class but the AlgebraicElement one). [It doesn't
393  /// make sense to use this mesh with SolidElements so we buffer the case if
394  /// update_all_solid_nodes is set to true.]
395  virtual void node_update(const bool& update_all_solid_nodes = false)
396  {
397 #ifdef PARANOID
398  if (update_all_solid_nodes)
399  {
400  std::string error_message =
401  "Doesn't make sense to use an AlgebraicMesh with\n";
402  error_message +=
403  "SolidElements so specifying update_all_solid_nodes=true\n";
404  error_message += "doesn't make sense either\n";
405 
406  std::string function_name = "AlgebraicFishMesh::node_update()";
407 
408  throw OomphLibError(
409  error_message, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
410  }
411 #endif
412  AlgebraicMesh::node_update();
413  }
414 
415  /// Update the geometric references that are used
416  /// to update node after mesh adaptation.
417  /// We're assuming that the GeomObject that specifies
418  /// the fish back does not have sub-objects, therefore
419  /// no update is required -- all reference
420  /// values can simply be scaled. We simply
421  /// paranoid-check that this is actually the case,
422  /// by checking if locate_zeta() returns the
423  /// original data.
424  void update_node_update(AlgebraicNode*& node_pt)
425  {
426 #ifdef PARANOID
427 
428  // Get the start and end Lagrangian coordinates on the
429  // wall from the domain:
430 
431  /// Start coordinate on wall (near nose)
432  double xi_nose = this->Domain_pt->xi_nose();
433 
434  /// End coordinate on wall (near tail)
435  double xi_tail = this->Domain_pt->xi_tail();
436 
437  /// Check halfway along the object
438  Vector<double> zeta(1);
439  zeta[0] = 0.5 * (xi_nose + xi_tail);
440 
441  Vector<double> s(1);
442  GeomObject* geom_obj_pt = 0;
443  this->Back_pt->locate_zeta(zeta, geom_obj_pt, s);
444 
445  if ((geom_obj_pt != this->Back_pt) || (s[0] != zeta[0]))
446  {
447  std::ostringstream error_message;
448  error_message << "AlgebraicFishMesh only works with GeomObjects\n"
449  << "that do not contain sub-elements (e.g. GeomObjects\n"
450  << "that represent a wall finite element mesh!\n"
451  << "Back_pt : " << this->Back_pt << std::endl
452  << "geom_obj_pt: " << geom_obj_pt << std::endl
453  << "s[0] : " << s[0] << std::endl
454  << "zeta[0] : " << zeta[0] << std::endl;
455 
456  throw OomphLibError(error_message.str(),
457  OOMPH_CURRENT_FUNCTION,
458  OOMPH_EXCEPTION_LOCATION);
459  }
460 #endif
461  }
462 
463 
464  protected:
465  /// Algebraic update function for nodes in upper/lower body
466  void node_update_in_body(const unsigned& t, AlgebraicNode*& node_pt);
467 
468  /// Algebraic update function for nodes in upper/lower fin
469  void node_update_in_fin(const unsigned& t, AlgebraicNode*& node_pt);
470 
471  /// Setup algebraic update operation for all nodes
472  /// (separate function because this task needs to be performed by
473  /// both constructors)
475  };
476 
477 
478  /// ////////////////////////////////////////////////////////////////////
479  /// ////////////////////////////////////////////////////////////////////
480  // Refineable algebraic element fish-shaped mesh
481  /// ////////////////////////////////////////////////////////////////////
482  /// ////////////////////////////////////////////////////////////////////
483 
484 
485  //=================================================================
486  /// Refineable fish shaped mesh with algebraic node update function.
487  //=================================================================
488  template<class ELEMENT>
490  public RefineableFishMesh<ELEMENT>
491  {
492  public:
493  /// Constructor: Pass pointer to timestepper.
494  /// (defaults to (Steady) default timestepper defined in Mesh)
495  // Note: FishMesh is virtual base and its constructor is automatically
496  // called first! --> this is where we need to build the mesh;
497  // the constructors of the derived meshes don't call the
498  // base constructor again and simply add the extra functionality.
500  TimeStepper* time_stepper_pt = &Mesh::Default_TimeStepper)
501  : FishMesh<ELEMENT>(time_stepper_pt),
502  AlgebraicFishMesh<ELEMENT>(time_stepper_pt),
503  RefineableFishMesh<ELEMENT>(time_stepper_pt)
504  {
505  }
506 
507 
508  /// Constructor: Pass pointer GeomObject that defines
509  /// the fish's back and pointer to timestepper.
510  /// (defaults to (Steady) default timestepper defined in Mesh)
511  // Note: FishMesh is virtual base and its constructor is automatically
512  // called first! --> this is where we need to build the mesh;
513  // the constructors of the derived meshes don't call the
514  // base constructor again and simply add the extra functionality.
516  GeomObject* back_pt,
517  TimeStepper* time_stepper_pt = &Mesh::Default_TimeStepper)
518  : FishMesh<ELEMENT>(back_pt, time_stepper_pt),
519  AlgebraicFishMesh<ELEMENT>(back_pt, time_stepper_pt),
520  RefineableFishMesh<ELEMENT>(back_pt, time_stepper_pt)
521  {
522  }
523 
524 
525  /// Destructor: empty
527 
528  /// Resolve node update function: Use the one defined
529  /// in the AlgebraicFishMesh (where the bool flag is explained)
530  void node_update(const bool& update_all_solid_nodes = false)
531  {
532  AlgebraicFishMesh<ELEMENT>::node_update(update_all_solid_nodes);
533  }
534  };
535 
536 } // namespace oomph
537 
538 #endif
////////////////////////////////////////////////////////////////////
virtual ~AlgebraicFishMesh()
Destructor: empty.
void setup_algebraic_node_update()
Setup algebraic update operation for all nodes (separate function because this task needs to be perfo...
virtual void node_update(const bool &update_all_solid_nodes=false)
Resolve the node update function (we neither want the broken empty one in the Mesh base class nor the...
AlgebraicFishMesh(TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor: Pass pointer to timestepper. (defaults to (Steady) default timestepper defined in Mesh)
void node_update_in_body(const unsigned &t, AlgebraicNode *&node_pt)
Algebraic update function for nodes in upper/lower body.
void update_node_update(AlgebraicNode *&node_pt)
Update the geometric references that are used to update node after mesh adaptation....
AlgebraicFishMesh(GeomObject *back_pt, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor: Pass pointer GeomObject that defines the fish's back and pointer to timestepper (default...
void algebraic_node_update(const unsigned &t, AlgebraicNode *&node_pt)
Update nodal position at time level t (t=0: present; t>0: previous)
void node_update_in_fin(const unsigned &t, AlgebraicNode *&node_pt)
Algebraic update function for nodes in upper/lower fin.
////////////////////////////////////////////////////////////////////
AlgebraicRefineableFishMesh(GeomObject *back_pt, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor: Pass pointer GeomObject that defines the fish's back and pointer to timestepper....
virtual ~AlgebraicRefineableFishMesh()
Destructor: empty.
void node_update(const bool &update_all_solid_nodes=false)
Resolve node update function: Use the one defined in the AlgebraicFishMesh (where the bool flag is ex...
AlgebraicRefineableFishMesh(TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor: Pass pointer to timestepper. (defaults to (Steady) default timestepper defined in Mesh)
Fish shaped domain, represented by four MacroElements. Shape is parametrised by GeomObject that repre...
Definition: fish_domain.h:43
double & xi_nose()
Start coordinate on wall (near nose)
Definition: fish_domain.h:101
double & xi_tail()
End coordinate on wall (near tail)
Definition: fish_domain.h:107
Fish shaped mesh. The geometry is defined by the Domain object FishDomain.
GeomObject * Back_pt
Pointer to fish back.
virtual ~FishMesh()
Destructor: Kill the geom object that represents the fish's back (if necessary)
FishMesh(TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor: Pass pointer to timestepper (defaults to the (Steady) default timestepper defined in Mes...
GeomObject *& fish_back_pt()
Access function to geom object that represents the fish's back.
void build_mesh(TimeStepper *time_stepper_pt)
Build the mesh, using the geometric object identified by Back_pt.
bool Must_kill_fish_back
Do I need to kill the fish back geom object?
FishDomain *& domain_pt()
Access function to FishDomain.
FishDomain * Domain_pt
Pointer to domain.
Refineable fish shaped mesh with MacroElement-based node update. The fish's back is represented by a ...
void node_update(const bool &update_all_solid_nodes=false)
Resolve mesh update: NodeUpdate current nodal positions via sparse MacroElement-based update....
virtual ~MacroElementNodeUpdateRefineableFishMesh()
Destructor: empty.
MacroElementNodeUpdateRefineableFishMesh(GeomObject *back_pt, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor: Pass pointer GeomObject that defines the fish's back and pointer to timestepper (default...
////////////////////////////////////////////////////////////////////
void setup_adaptivity()
Setup all the information that's required for spatial adaptivity: Set pointers to macro elements and ...
RefineableFishMesh(TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor: Pass pointer to timestepper – defaults to (Steady) default timestepper defined in the Me...
RefineableFishMesh(GeomObject *back_pt, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor: Pass pointer GeomObject that defines the fish's back and pointer to timestepper (default...
virtual ~RefineableFishMesh()
Destructor: Empty – all cleanup gets handled in the base classes.
////////////////////////////////////////////////////////////////////// //////////////////////////////...