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 ...
////////////////////////////////////////////////////////////////////// //////////////////////////////...