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);
 
  142     Vector<double> s(2), s_fraction(2);
 
  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]);
 
  238           Vector<double> zeta(1);
 
  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));
 
  413           Vector<double> zeta(1);
 
  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++)
 
  572       FiniteElement* el_pt = this->finite_element_pt(e);
 
  578       el_pt->set_macro_elem_pt(this->Domain_pt->macro_element_pt(e));
 
  583     setup_boundary_element_info();
 
  589       Vector<double> zeta(1);
 
  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
 
  621                 oomph_info << 
"x: " << r[0] << 
" " 
  622                            << boundary_node_pt(ibound, inod)->x(0) << std::endl;
 
  624                 oomph_info << 
"y: " << r[1] << 
" " 
  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
 
  642         throw OomphLibError(error_message.str(),
 
  643                             OOMPH_CURRENT_FUNCTION,
 
  644                             OOMPH_EXCEPTION_LOCATION);
 
  660   template<
class ELEMENT>
 
  664     this->setup_quadtree_forest();
 
  681   template<
class ELEMENT>
 
  686     AlgebraicElementBase* lower_body_pt =
 
  687       dynamic_cast<AlgebraicElementBase*
>(Mesh::element_pt(0));
 
  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: " 
  695                     << 
typeid(Mesh::element_pt(0)).name() << std::endl;
 
  698         error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
 
  711       FiniteElement* el_pt = Mesh::finite_element_pt(ielem);
 
  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;
 
  723           Vector<GeomObject*> geom_object_pt(1);
 
  724           geom_object_pt[0] = this->Back_pt;
 
  727           Vector<double> ref_value(3);
 
  730           ref_value[0] = double(i0) / double(n_p - 1);
 
  735           ref_value[1] = 1.0 - double(i1) / double(n_p - 1);
 
  742           dynamic_cast<AlgebraicNode*
>(el_pt->node_pt(jnod))
 
  743             ->add_node_update_info(this->Lower_body, 
 
  756       FiniteElement* el_pt = Mesh::finite_element_pt(ielem);
 
  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;
 
  768           Vector<GeomObject*> geom_object_pt(1);
 
  769           geom_object_pt[0] = this->Back_pt;
 
  772           Vector<double> ref_value(3);
 
  775           ref_value[0] = double(i0) / double(n_p - 1);
 
  780           ref_value[1] = 1.0 - double(i1) / double(n_p - 1);
 
  787           dynamic_cast<AlgebraicNode*
>(el_pt->node_pt(jnod))
 
  788             ->add_node_update_info(this->Lower_fin, 
 
  801       FiniteElement* el_pt = Mesh::finite_element_pt(ielem);
 
  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;
 
  813           Vector<GeomObject*> geom_object_pt(1);
 
  814           geom_object_pt[0] = this->Back_pt;
 
  817           Vector<double> ref_value(3);
 
  820           ref_value[0] = double(i0) / double(n_p - 1);
 
  825           ref_value[1] = double(i1) / double(n_p - 1);
 
  832           dynamic_cast<AlgebraicNode*
>(el_pt->node_pt(jnod))
 
  833             ->add_node_update_info(this->Upper_body, 
 
  846       FiniteElement* el_pt = Mesh::finite_element_pt(ielem);
 
  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;
 
  858           Vector<GeomObject*> geom_object_pt(1);
 
  859           geom_object_pt[0] = this->Back_pt;
 
  862           Vector<double> ref_value(3);
 
  865           ref_value[0] = double(i0) / double(n_p - 1);
 
  870           ref_value[1] = double(i1) / double(n_p - 1);
 
  877           dynamic_cast<AlgebraicNode*
>(el_pt->node_pt(jnod))
 
  878             ->add_node_update_info(this->Upper_fin, 
 
  892   template<
class ELEMENT>
 
  894                                                        AlgebraicNode*& node_pt)
 
  897     GeomObject* back_pt = node_pt->geom_object_pt(
unsigned(0));
 
  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));
 
  916     double fract_y = node_pt->ref_value(1);
 
  920     double sign = node_pt->ref_value(2);
 
  923     Vector<double> zeta(back_pt->nlagrangian());
 
  924     zeta[0] = zeta_mouth + fract_x * (zeta_near_tail - zeta_mouth);
 
  925     Vector<double> r_back(back_pt->ndim());
 
  926     back_pt->position(t, zeta, r_back);
 
  929     zeta[0] = zeta_near_tail;
 
  930     Vector<double> r_near_tail(back_pt->ndim());
 
  931     back_pt->position(t, zeta, r_near_tail);
 
  934     Vector<double> r_sym(2);
 
  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>
 
  950                                                       AlgebraicNode*& node_pt)
 
  953     GeomObject* back_pt = node_pt->geom_object_pt(
unsigned(0));
 
  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));
 
  970     double fract_y = node_pt->ref_value(1);
 
  974     double sign = node_pt->ref_value(2);
 
  977     Vector<double> zeta(back_pt->nlagrangian());
 
  979     Vector<double> r_back(back_pt->ndim());
 
  980     back_pt->position(t, zeta, r_back);
 
  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.
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?
void setup_adaptivity()
Setup all the information that's required for spatial adaptivity: Set pointers to macro elements and ...
////////////////////////////////////////////////////////////////////// //////////////////////////////...