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