26 #ifndef OOMPH_FISH_MESH_TEMPLATE_CC 
   27 #define OOMPH_FISH_MESH_TEMPLATE_CC 
   38   template<
class ELEMENT>
 
   42     MeshChecker::assert_geometric_element<QElementGeometricBase, ELEMENT>(2);
 
   48     Back_pt = 
new Circle(x_c, y_c, r_back);
 
   51     Must_kill_fish_back = 
true;
 
   54     build_mesh(time_stepper_pt);
 
   63   template<
class ELEMENT>
 
   68     MeshChecker::assert_geometric_element<QElementGeometricBase, ELEMENT>(2);
 
   82   template<
class ELEMENT>
 
   86     MeshChecker::assert_geometric_element<QElementGeometricBase, ELEMENT>(2);
 
   95     Domain_pt = 
new FishDomain(Back_pt, xi_lo, xi_hi);
 
  102       std::ofstream some_file;
 
  108       some_file.open(
"fish_domain.dat");
 
  109       Domain_pt->output(some_file, npts);
 
  110       Domain_pt->output_macro_element_boundaries(some_file, npts);
 
  120     Boundary_coordinate_exists[0] = 
true;
 
  121     Boundary_coordinate_exists[4] = 
true;
 
  125     Element_pt.resize(nelem);
 
  128     ELEMENT* dummy_el_pt = 
new ELEMENT;
 
  131     unsigned n_node_1d = dummy_el_pt->nnode_1d();
 
  137     unsigned nnodes_total =
 
  138       (2 * (n_node_1d - 1) + 1) * (2 * (n_node_1d - 1) + 1);
 
  139     Node_pt.resize(nnodes_total);
 
  150     for (
unsigned e = 0; 
e < nelem; 
e++)
 
  153       Element_pt[
e] = 
new ELEMENT;
 
  156       for (
unsigned i1 = 0; i1 < n_node_1d; i1++)
 
  159         for (
unsigned i0 = 0; i0 < n_node_1d; i0++)
 
  162           unsigned j_local = i0 + i1 * n_node_1d;
 
  166             finite_element_pt(
e)->construct_node(j_local, time_stepper_pt);
 
  170           finite_element_pt(
e)->local_fraction_of_node(j_local, s_fraction);
 
  172           s[0] = -1.0 + 2.0 * s_fraction[0];
 
  173           s[1] = -1.0 + 2.0 * s_fraction[1];
 
  176           Domain_pt->macro_element_pt(
e)->macro_map(
s, r);
 
  179           node_pt->
x(0) = r[0];
 
  180           node_pt->
x(1) = r[1];
 
  192     unsigned node_count = 0;
 
  199     double Max_tol_in_node_killing = 1.0e-12;
 
  206     for (
unsigned i1 = 0; i1 < n_node_1d; i1++)
 
  209       for (
unsigned i0 = 0; i0 < n_node_1d; i0++)
 
  212         unsigned j_local = i0 + i1 * n_node_1d;
 
  215         Node_pt[node_count] = finite_element_pt(
e)->node_pt(j_local);
 
  221         if ((i0 == 0) || (i1 == 0))
 
  223           this->convert_to_boundary_node(Node_pt[node_count]);
 
  229           add_boundary_node(6, Node_pt[node_count]);
 
  235           add_boundary_node(0, Node_pt[node_count]);
 
  240             xi_lo + (xi_hi - xi_lo) * 
double(i0) / double(n_node_1d - 1);
 
  241           Node_pt[node_count]->set_coordinates_on_boundary(0, zeta);
 
  255     for (
unsigned i1 = 0; i1 < n_node_1d; i1++)
 
  258       for (
unsigned i0 = 0; i0 < n_node_1d; i0++)
 
  261         unsigned j_local = i0 + i1 * n_node_1d;
 
  271           unsigned e_neigh = 0;
 
  274           unsigned i0_neigh = n_node_1d - 1;
 
  275           unsigned i1_neigh = i1;
 
  276           unsigned j_local_neigh = i0_neigh + i1_neigh * n_node_1d;
 
  280           for (
unsigned i = 0; 
i < 2; 
i++)
 
  282             double error = std::fabs(
 
  283               finite_element_pt(
e)->node_pt(j_local)->x(
i) -
 
  284               finite_element_pt(e_neigh)->node_pt(j_local_neigh)->x(
i));
 
  285             if (error > Max_tol_in_node_killing)
 
  287               oomph_info << 
"Error in node killing for i " << 
i << 
" " << error
 
  294           delete finite_element_pt(
e)->node_pt(j_local);
 
  298           finite_element_pt(
e)->node_pt(j_local) =
 
  299             finite_element_pt(e_neigh)->node_pt(j_local_neigh);
 
  307           Node_pt[node_count] = finite_element_pt(
e)->node_pt(j_local);
 
  311           if ((i1 == 0) || (i0 == n_node_1d - 1))
 
  313             this->convert_to_boundary_node(Node_pt[node_count]);
 
  325           add_boundary_node(1, finite_element_pt(
e)->node_pt(j_local));
 
  329         if (i0 == n_node_1d - 1)
 
  331           add_boundary_node(2, finite_element_pt(
e)->node_pt(j_local));
 
  342     for (
unsigned i1 = 0; i1 < n_node_1d; i1++)
 
  345       for (
unsigned i0 = 0; i0 < n_node_1d; i0++)
 
  348         unsigned j_local = i0 + i1 * n_node_1d;
 
  358           unsigned e_neigh = 0;
 
  361           unsigned i0_neigh = i0;
 
  362           unsigned i1_neigh = n_node_1d - 1;
 
  363           unsigned j_local_neigh = i0_neigh + i1_neigh * n_node_1d;
 
  366           for (
unsigned i = 0; 
i < 2; 
i++)
 
  368             double error = std::fabs(
 
  369               finite_element_pt(
e)->node_pt(j_local)->x(
i) -
 
  370               finite_element_pt(e_neigh)->node_pt(j_local_neigh)->x(
i));
 
  371             if (error > Max_tol_in_node_killing)
 
  373               oomph_info << 
"Error in node killing for i " << 
i << 
" " << error
 
  380           delete finite_element_pt(
e)->node_pt(j_local);
 
  384           finite_element_pt(
e)->node_pt(j_local) =
 
  385             finite_element_pt(e_neigh)->node_pt(j_local_neigh);
 
  392           Node_pt[node_count] = finite_element_pt(
e)->node_pt(j_local);
 
  396           if ((i1 == n_node_1d - 1) || (i0 == 0))
 
  398             this->convert_to_boundary_node(Node_pt[node_count]);
 
  408         if (i1 == n_node_1d - 1)
 
  410           add_boundary_node(4, finite_element_pt(
e)->node_pt(j_local));
 
  415             xi_lo + (xi_hi - xi_lo) * 
double(i0) / double(n_node_1d - 1);
 
  416           finite_element_pt(
e)->node_pt(j_local)->set_coordinates_on_boundary(
 
  423           add_boundary_node(5, finite_element_pt(
e)->node_pt(j_local));
 
  434     for (
unsigned i1 = 0; i1 < n_node_1d; i1++)
 
  437       for (
unsigned i0 = 0; i0 < n_node_1d; i0++)
 
  440         unsigned j_local = i0 + i1 * n_node_1d;
 
  450           unsigned e_neigh = 2;
 
  453           unsigned i0_neigh = n_node_1d - 1;
 
  454           unsigned i1_neigh = i1;
 
  455           unsigned j_local_neigh = i0_neigh + i1_neigh * n_node_1d;
 
  459           for (
unsigned i = 0; 
i < 2; 
i++)
 
  461             double error = std::fabs(
 
  462               finite_element_pt(
e)->node_pt(j_local)->x(
i) -
 
  463               finite_element_pt(e_neigh)->node_pt(j_local_neigh)->x(
i));
 
  464             if (error > Max_tol_in_node_killing)
 
  466               oomph_info << 
"Error in node killing for i " << 
i << 
" " << error
 
  473           delete finite_element_pt(
e)->node_pt(j_local);
 
  477           finite_element_pt(
e)->node_pt(j_local) =
 
  478             finite_element_pt(e_neigh)->node_pt(j_local_neigh);
 
  484         if ((i0 != 0) && (i1 == 0))
 
  487           unsigned e_neigh = 1;
 
  490           unsigned i0_neigh = i0;
 
  491           unsigned i1_neigh = n_node_1d - 1;
 
  492           unsigned j_local_neigh = i0_neigh + i1_neigh * n_node_1d;
 
  496           for (
unsigned i = 0; 
i < 2; 
i++)
 
  498             double error = std::fabs(
 
  499               finite_element_pt(
e)->node_pt(j_local)->x(
i) -
 
  500               finite_element_pt(e_neigh)->node_pt(j_local_neigh)->x(
i));
 
  501             if (error > Max_tol_in_node_killing)
 
  503               oomph_info << 
"Error in node killing for i " << 
i << 
" " << error
 
  510           delete finite_element_pt(
e)->node_pt(j_local);
 
  514           finite_element_pt(
e)->node_pt(j_local) =
 
  515             finite_element_pt(e_neigh)->node_pt(j_local_neigh);
 
  523           Node_pt[node_count] = finite_element_pt(
e)->node_pt(j_local);
 
  527           if ((i1 == n_node_1d - 1) || (i0 == n_node_1d - 1))
 
  529             this->convert_to_boundary_node(Node_pt[node_count]);
 
  539         if (i1 == n_node_1d - 1)
 
  541           add_boundary_node(3, finite_element_pt(
e)->node_pt(j_local));
 
  546         if (i0 == n_node_1d - 1)
 
  548           add_boundary_node(2, finite_element_pt(
e)->node_pt(j_local));
 
  556       std::ostringstream error_message;
 
  557       error_message << 
"Error occured in node killing!\n";
 
  559         << 
"Max. permitted difference in position of the two nodes\n " 
  560         << 
"that get 'merged' : " << Max_tol_in_node_killing << std::endl;
 
  563         error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
 
  568     unsigned n_element = this->nelement();
 
  569     for (
unsigned e = 0; 
e < n_element; 
e++)
 
  583     setup_boundary_element_info();
 
  592       unsigned num_bound = nboundary();
 
  593       for (
unsigned ibound = 0; ibound < num_bound; ibound++)
 
  595         if (boundary_coordinate_exists(ibound))
 
  597           unsigned num_nod = nboundary_node(ibound);
 
  598           for (
unsigned inod = 0; inod < num_nod; inod++)
 
  601             boundary_node_pt(ibound, inod)
 
  602               ->get_coordinates_on_boundary(ibound, zeta);
 
  605             Back_pt->position(zeta, r);
 
  608             if (ibound == 0) r[1] = -r[1];
 
  611             for (
unsigned i = 0; 
i < 2; 
i++)
 
  614                 std::fabs(r[
i] - boundary_node_pt(ibound, inod)->x(
i));
 
  615               if (error > Max_tol_in_node_killing)
 
  617                 oomph_info << 
"Error in boundary coordinate for direction " << 
i 
  618                            << 
" on boundary " << ibound << 
":" << error
 
  622                            << boundary_node_pt(ibound, inod)->x(0) << std::endl;
 
  625                            << boundary_node_pt(ibound, inod)->x(1) << std::endl
 
  637         std::ostringstream error_message;
 
  638         error_message << 
"Error occured in boundary coordinate setup!\n";
 
  639         error_message << 
"Max. tolerance: " << Max_tol_in_node_killing
 
  643                             OOMPH_CURRENT_FUNCTION,
 
  644                             OOMPH_EXCEPTION_LOCATION);
 
  660   template<
class ELEMENT>
 
  664     this->setup_quadtree_forest();
 
  681   template<
class ELEMENT>
 
  689     if (lower_body_pt == 0)
 
  691       std::ostringstream error_message;
 
  692       error_message << 
"Element in AlgebraicFishMesh must be\n" 
  693                     << 
"derived from AlgebraicElementBase\n" 
  694                     << 
"but it is of type: " 
  698         error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
 
  714       for (
unsigned i1 = 0; i1 < n_p; i1++)
 
  717         for (
unsigned i0 = 0; i0 < n_p; i0++)
 
  720           unsigned jnod = i0 + i1 * n_p;
 
  724           geom_object_pt[0] = this->Back_pt;
 
  730           ref_value[0] = double(i0) / double(n_p - 1);
 
  735           ref_value[1] = 1.0 - double(i1) / double(n_p - 1);
 
  743             ->add_node_update_info(this->Lower_body, 
 
  759       for (
unsigned i1 = 0; i1 < n_p; i1++)
 
  762         for (
unsigned i0 = 0; i0 < n_p; i0++)
 
  765           unsigned jnod = i0 + i1 * n_p;
 
  769           geom_object_pt[0] = this->Back_pt;
 
  775           ref_value[0] = double(i0) / double(n_p - 1);
 
  780           ref_value[1] = 1.0 - double(i1) / double(n_p - 1);
 
  788             ->add_node_update_info(this->Lower_fin, 
 
  804       for (
unsigned i1 = 0; i1 < n_p; i1++)
 
  807         for (
unsigned i0 = 0; i0 < n_p; i0++)
 
  810           unsigned jnod = i0 + i1 * n_p;
 
  814           geom_object_pt[0] = this->Back_pt;
 
  820           ref_value[0] = double(i0) / double(n_p - 1);
 
  825           ref_value[1] = double(i1) / double(n_p - 1);
 
  833             ->add_node_update_info(this->Upper_body, 
 
  849       for (
unsigned i1 = 0; i1 < n_p; i1++)
 
  852         for (
unsigned i0 = 0; i0 < n_p; i0++)
 
  855           unsigned jnod = i0 + i1 * n_p;
 
  859           geom_object_pt[0] = this->Back_pt;
 
  865           ref_value[0] = double(i0) / double(n_p - 1);
 
  870           ref_value[1] = double(i1) / double(n_p - 1);
 
  878             ->add_node_update_info(this->Upper_fin, 
 
  892   template<
class ELEMENT>
 
  900     double x_mouth = this->Domain_pt->x_mouth();
 
  904     double zeta_mouth = this->Domain_pt->xi_nose();
 
  908     double zeta_near_tail = this->Domain_pt->xi_tail();
 
  911     double fract_x = node_pt->
ref_value(
unsigned(0));
 
  924     zeta[0] = zeta_mouth + fract_x * (zeta_near_tail - zeta_mouth);
 
  929     zeta[0] = zeta_near_tail;
 
  935     r_sym[0] = x_mouth + fract_x * (r_near_tail[0] - x_mouth);
 
  939     node_pt->
x(
t, 0) = r_sym[0] + fract_y * (r_back[0] - r_sym[0]);
 
  940     node_pt->
x(
t, 1) = sign * (r_sym[1] + fract_y * (r_back[1] - r_sym[1]));
 
  948   template<
class ELEMENT>
 
  956     double zeta_wall = this->Domain_pt->xi_tail();
 
  959     double x_tail = this->Domain_pt->x_fin();
 
  962     double y_tail = this->Domain_pt->y_fin();
 
  965     double fract_x = node_pt->
ref_value(
unsigned(0));
 
  983     double y_fin_edge = r_back[1] + fract_x * (y_tail - r_back[1]);
 
  986     node_pt->
x(
t, 0) = r_back[0] + fract_x * (x_tail - r_back[0]);
 
  987     node_pt->
x(
t, 1) = sign * fract_y * y_fin_edge;
 
////////////////////////////////////////////////////////////////////
void setup_algebraic_node_update()
Setup algebraic update operation for all nodes (separate function because this task needs to be perfo...
void node_update_in_body(const unsigned &t, AlgebraicNode *&node_pt)
Algebraic update function for nodes in upper/lower body.
void node_update_in_fin(const unsigned &t, AlgebraicNode *&node_pt)
Algebraic update function for nodes in upper/lower fin.
////////////////////////////////////////////////////////////////////
GeomObject * geom_object_pt(const unsigned &i)
Return pointer to i-th geometric object involved in default (usually first) update function.
double ref_value(const unsigned &i)
Return i-th reference value involved in default (usually first) update function.
////////////////////////////////////////////////////////////////////
A general Finite Element class.
virtual void set_macro_elem_pt(MacroElement *macro_elem_pt)
Set pointer to macro element – can be overloaded in derived elements to perform additional tasks.
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Fish shaped domain, represented by four MacroElements. Shape is parametrised by GeomObject that repre...
Fish shaped mesh. The geometry is defined by the Domain object FishDomain.
FishMesh(TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor: Pass pointer to timestepper (defaults to the (Steady) default timestepper defined in Mes...
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?
/////////////////////////////////////////////////////////////////////
unsigned ndim() const
Access function to # of Eulerian coordinates.
virtual void position(const Vector< double > &zeta, Vector< double > &r) const =0
Parametrised position on object at current time: r(zeta).
unsigned nlagrangian() const
Access function to # of Lagrangian coordinates.
FiniteElement * finite_element_pt(const unsigned &e) const
Upcast (downcast?) to FiniteElement (needed to access FiniteElement member functions).
const Vector< GeneralisedElement * > & element_pt() const
Return reference to the Vector of elements.
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
double & x(const unsigned &i)
Return the i-th nodal coordinate.
An OomphLibError object which should be thrown when an run-time error is encountered....
void setup_adaptivity()
Setup all the information that's required for spatial adaptivity: Set pointers to macro elements and ...
////////////////////////////////////////////////////////////////////// //////////////////////////////...
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
OomphInfo oomph_info
Single (global) instantiation of the OomphInfo object – this is used throughout the library as a "rep...