30 #ifndef OOMPH_FISH_MESH_TEMPLATE_CC 31 #define OOMPH_FISH_MESH_TEMPLATE_CC 43 template<
class ELEMENT>
48 MeshChecker::assert_geometric_element<QElementGeometricBase,ELEMENT>(2);
54 Back_pt=
new Circle(x_c,y_c,r_back);
57 Must_kill_fish_back=
true;
60 build_mesh(time_stepper_pt);
69 template<
class ELEMENT>
71 TimeStepper* time_stepper_pt) : Back_pt(back_pt)
74 MeshChecker::assert_geometric_element<QElementGeometricBase,ELEMENT>(2);
88 template<
class ELEMENT>
92 MeshChecker::assert_geometric_element<QElementGeometricBase,ELEMENT>(2);
108 std::ofstream some_file;
114 some_file.open(
"fish_domain.dat");
116 Domain_pt->output_macro_element_boundaries(some_file,npts);
126 Boundary_coordinate_exists[0] =
true;
127 Boundary_coordinate_exists[4] =
true;
131 Element_pt.resize(nelem);
134 ELEMENT* dummy_el_pt=
new ELEMENT;
137 unsigned n_node_1d=dummy_el_pt->nnode_1d();
143 unsigned nnodes_total=(2*(n_node_1d-1)+1)*(2*(n_node_1d-1)+1);
144 Node_pt.resize(nnodes_total);
147 Vector<double> s(2), s_fraction(2);
155 for (
unsigned e=0;e<nelem;e++)
158 Element_pt[e] =
new ELEMENT;
161 for (
unsigned i1=0;i1<n_node_1d;i1++)
165 for (
unsigned i0=0;i0<n_node_1d;i0++)
168 unsigned j_local=i0+i1*n_node_1d;
171 Node* node_pt=finite_element_pt(e)->
172 construct_node(j_local,time_stepper_pt);
176 finite_element_pt(e)->local_fraction_of_node(j_local,s_fraction);
178 s[0]=-1.0+2.0*s_fraction[0];
179 s[1]=-1.0+2.0*s_fraction[1];
182 Domain_pt->macro_element_pt(e)->macro_map(s,r);
185 node_pt->x(0) = r[0];
186 node_pt->x(1) = r[1];
198 unsigned node_count=0;
205 double Max_tol_in_node_killing=1.0e-12;
212 for (
unsigned i1=0;i1<n_node_1d;i1++)
216 for (
unsigned i0=0;i0<n_node_1d;i0++)
219 unsigned j_local=i0+i1*n_node_1d;
222 Node_pt[node_count]=finite_element_pt(e)->node_pt(j_local);
228 if((i0==0) || (i1==0))
230 this->convert_to_boundary_node(Node_pt[node_count]);
236 add_boundary_node(6,Node_pt[node_count]);
242 add_boundary_node(0,Node_pt[node_count]);
245 Vector<double> zeta(1);
246 zeta[0]=xi_lo+(xi_hi-xi_lo)*
double(i0)/double(n_node_1d-1);
247 Node_pt[node_count]->set_coordinates_on_boundary(0,zeta);
262 for (
unsigned i1=0;i1<n_node_1d;i1++)
266 for (
unsigned i0=0;i0<n_node_1d;i0++)
270 unsigned j_local=i0+i1*n_node_1d;
284 unsigned i0_neigh=n_node_1d-1;
285 unsigned i1_neigh=i1;
286 unsigned j_local_neigh=i0_neigh+i1_neigh*n_node_1d;
290 for (
unsigned i=0;i<2;i++)
292 double error=std::fabs(
293 finite_element_pt(e)->node_pt(j_local)->x(i)-
294 finite_element_pt(e_neigh)->
295 node_pt(j_local_neigh)->x(i));
296 if (error>Max_tol_in_node_killing)
298 oomph_info <<
"Error in node killing for i " 299 << i <<
" " << error << std::endl;
305 delete finite_element_pt(e)->node_pt(j_local);
309 finite_element_pt(e)->node_pt(j_local)=
310 finite_element_pt(e_neigh)->node_pt(j_local_neigh);
319 Node_pt[node_count]=finite_element_pt(e)->node_pt(j_local);
323 if((i1==0) ||(i0==n_node_1d-1))
325 this->convert_to_boundary_node(Node_pt[node_count]);
338 add_boundary_node(1,finite_element_pt(e)->node_pt(j_local));
344 add_boundary_node(2,finite_element_pt(e)->node_pt(j_local));
357 for (
unsigned i1=0;i1<n_node_1d;i1++)
361 for (
unsigned i0=0;i0<n_node_1d;i0++)
365 unsigned j_local=i0+i1*n_node_1d;
379 unsigned i0_neigh=i0;
380 unsigned i1_neigh=n_node_1d-1;
381 unsigned j_local_neigh=i0_neigh+i1_neigh*n_node_1d;
384 for (
unsigned i=0;i<2;i++)
386 double error=std::fabs(
387 finite_element_pt(e)->node_pt(j_local)->x(i)-
388 finite_element_pt(e_neigh)->
389 node_pt(j_local_neigh)->x(i));
390 if (error>Max_tol_in_node_killing)
392 oomph_info <<
"Error in node killing for i " 393 << i <<
" " << error << std::endl;
399 delete finite_element_pt(e)->node_pt(j_local);
403 finite_element_pt(e)->node_pt(j_local)=
404 finite_element_pt(e_neigh)->node_pt(j_local_neigh);
412 Node_pt[node_count]=finite_element_pt(e)->node_pt(j_local);
416 if((i1==n_node_1d-1) || (i0==0))
418 this->convert_to_boundary_node(Node_pt[node_count]);
431 add_boundary_node(4,finite_element_pt(e)->node_pt(j_local));
434 Vector<double> zeta(1);
435 zeta[0]=xi_lo+(xi_hi-xi_lo)*
double(i0)/double(n_node_1d-1);
436 finite_element_pt(e)->node_pt(j_local)->
437 set_coordinates_on_boundary(4,zeta);
443 add_boundary_node(5,finite_element_pt(e)->node_pt(j_local));
456 for (
unsigned i1=0;i1<n_node_1d;i1++)
460 for (
unsigned i0=0;i0<n_node_1d;i0++)
464 unsigned j_local=i0+i1*n_node_1d;
478 unsigned i0_neigh=n_node_1d-1;
479 unsigned i1_neigh=i1;
480 unsigned j_local_neigh=i0_neigh+i1_neigh*n_node_1d;
484 for (
unsigned i=0;i<2;i++)
486 double error=std::fabs(
487 finite_element_pt(e)->node_pt(j_local)->x(i)-
488 finite_element_pt(e_neigh)->
489 node_pt(j_local_neigh)->x(i));
490 if (error>Max_tol_in_node_killing)
492 oomph_info <<
"Error in node killing for i " 493 << i <<
" " << error << std::endl;
499 delete finite_element_pt(e)->node_pt(j_local);
503 finite_element_pt(e)->node_pt(j_local)=
504 finite_element_pt(e_neigh)->node_pt(j_local_neigh);
512 if ((i0!=0)&&(i1==0))
519 unsigned i0_neigh=i0;
520 unsigned i1_neigh=n_node_1d-1;
521 unsigned j_local_neigh=i0_neigh+i1_neigh*n_node_1d;
525 for (
unsigned i=0;i<2;i++)
527 double error=std::fabs(
528 finite_element_pt(e)->node_pt(j_local)->x(i)-
529 finite_element_pt(e_neigh)->
530 node_pt(j_local_neigh)->x(i));
531 if (error>Max_tol_in_node_killing)
533 oomph_info <<
"Error in node killing for i " 534 << i <<
" " << error << std::endl;
540 delete finite_element_pt(e)->node_pt(j_local);
544 finite_element_pt(e)->node_pt(j_local)=
545 finite_element_pt(e_neigh)->node_pt(j_local_neigh);
554 Node_pt[node_count]=finite_element_pt(e)->node_pt(j_local);
558 if((i1==n_node_1d-1) || (i0==n_node_1d-1))
560 this->convert_to_boundary_node(Node_pt[node_count]);
573 add_boundary_node(3,finite_element_pt(e)->node_pt(j_local));
580 add_boundary_node(2,finite_element_pt(e)->node_pt(j_local));
588 std::ostringstream error_message;
589 error_message <<
"Error occured in node killing!\n";
591 <<
"Max. permitted difference in position of the two nodes\n " 592 <<
"that get 'merged' : " << Max_tol_in_node_killing << std::endl;
594 throw OomphLibError(error_message.str(),
595 OOMPH_CURRENT_FUNCTION,
596 OOMPH_EXCEPTION_LOCATION);
602 unsigned n_element=this->nelement();
603 for (
unsigned e=0;e<n_element;e++)
606 FiniteElement* el_pt=this->finite_element_pt(e);
612 el_pt->set_macro_elem_pt(this->
Domain_pt->macro_element_pt(e));
617 setup_boundary_element_info();
623 Vector<double> zeta(1);
626 unsigned num_bound=nboundary();
627 for(
unsigned ibound=0;ibound<num_bound;ibound++)
629 if (boundary_coordinate_exists(ibound))
632 unsigned num_nod=nboundary_node(ibound);
633 for (
unsigned inod=0;inod<num_nod;inod++)
636 boundary_node_pt(ibound,inod)->
637 get_coordinates_on_boundary(ibound,zeta);
643 if (ibound==0) r[1]=-r[1];
646 for (
unsigned i=0;i<2;i++)
648 double error=std::fabs(r[i]-boundary_node_pt(ibound,inod)->x(i));
649 if (error>Max_tol_in_node_killing)
651 oomph_info <<
"Error in boundary coordinate for direction " 652 << i <<
" on boundary " << ibound <<
":" 653 << error << std::endl;
655 oomph_info <<
"x: " << r[0] <<
" " 656 << boundary_node_pt(ibound,inod)->x(0)
659 oomph_info <<
"y: " << r[1] <<
" " 660 << boundary_node_pt(ibound,inod)->x(1)
661 << std::endl << std::endl;
673 std::ostringstream error_message;
674 error_message <<
"Error occured in boundary coordinate setup!\n";
676 <<
"Max. tolerance: " << Max_tol_in_node_killing << std::endl;
678 throw OomphLibError(error_message.str(),
679 OOMPH_CURRENT_FUNCTION,
680 OOMPH_EXCEPTION_LOCATION);
701 template <
class ELEMENT>
705 this->setup_quadtree_forest();
727 template <
class ELEMENT>
733 AlgebraicElementBase*
734 lower_body_pt=
dynamic_cast<AlgebraicElementBase*
>(Mesh::element_pt(0));
736 if (lower_body_pt==0)
738 std::ostringstream error_message;
739 error_message <<
"Element in AlgebraicFishMesh must be\n" 740 <<
"derived from AlgebraicElementBase\n" 741 <<
"but it is of type: " 742 <<
typeid(Mesh::element_pt(0)).name() << std::endl;
744 throw OomphLibError(error_message.str(),
745 OOMPH_CURRENT_FUNCTION,
746 OOMPH_EXCEPTION_LOCATION);
758 FiniteElement* el_pt=Mesh::finite_element_pt(ielem);
761 for (
unsigned i1=0;i1<n_p;i1++)
764 for (
unsigned i0=0;i0<n_p;i0++)
767 unsigned jnod=i0+i1*n_p;
770 Vector<GeomObject*> geom_object_pt(1);
771 geom_object_pt[0]=this->
Back_pt;
774 Vector<double> ref_value(3);
777 ref_value[0]=double(i0)/double(n_p-1);
782 ref_value[1]=1.0-double(i1)/double(n_p-1);
789 dynamic_cast<AlgebraicNode*
>(el_pt->node_pt(jnod))->
790 add_node_update_info(
805 FiniteElement* el_pt=Mesh::finite_element_pt(ielem);
808 for (
unsigned i1=0;i1<n_p;i1++)
812 for (
unsigned i0=0;i0<n_p;i0++)
816 unsigned jnod=i0+i1*n_p;
819 Vector<GeomObject*> geom_object_pt(1);
820 geom_object_pt[0]=this->
Back_pt;
823 Vector<double> ref_value(3);
826 ref_value[0]=double(i0)/double(n_p-1);
831 ref_value[1]=1.0-double(i1)/double(n_p-1);
838 dynamic_cast<AlgebraicNode*
>(el_pt->node_pt(jnod))->
839 add_node_update_info(
853 FiniteElement* el_pt=Mesh::finite_element_pt(ielem);
856 for (
unsigned i1=0;i1<n_p;i1++)
859 for (
unsigned i0=0;i0<n_p;i0++)
862 unsigned jnod=i0+i1*n_p;
865 Vector<GeomObject*> geom_object_pt(1);
866 geom_object_pt[0]=this->
Back_pt;
869 Vector<double> ref_value(3);
872 ref_value[0]=double(i0)/double(n_p-1);
877 ref_value[1]=double(i1)/double(n_p-1);
884 dynamic_cast<AlgebraicNode*
>(el_pt->node_pt(jnod))->
885 add_node_update_info(
899 FiniteElement* el_pt=Mesh::finite_element_pt(ielem);
902 for (
unsigned i1=0;i1<n_p;i1++)
905 for (
unsigned i0=0;i0<n_p;i0++)
908 unsigned jnod=i0+i1*n_p;
911 Vector<GeomObject*> geom_object_pt(1);
912 geom_object_pt[0]=this->
Back_pt;
915 Vector<double> ref_value(3);
918 ref_value[0]=double(i0)/double(n_p-1);
923 ref_value[1]=double(i1)/double(n_p-1);
930 dynamic_cast<AlgebraicNode*
>(el_pt->node_pt(jnod))->
931 add_node_update_info(
949 template <
class ELEMENT>
951 AlgebraicNode*& node_pt)
954 GeomObject* back_pt=node_pt->geom_object_pt(
unsigned(0));
968 double fract_x=node_pt->ref_value(
unsigned(0));
973 double fract_y=node_pt->ref_value(1);
977 double sign=node_pt->ref_value(2);
980 Vector<double> zeta(back_pt->nlagrangian());
981 zeta[0]=zeta_mouth+fract_x*(zeta_near_tail-zeta_mouth);
982 Vector<double> r_back(back_pt->ndim());
983 back_pt->position(t,zeta,r_back);
986 zeta[0]=zeta_near_tail;
987 Vector<double> r_near_tail(back_pt->ndim());
988 back_pt->position(t,zeta,r_near_tail);
991 Vector<double> r_sym(2);
992 r_sym[0]=x_mouth+fract_x*(r_near_tail[0]-x_mouth);
996 node_pt->x(t,0) = r_sym[0]+fract_y*(r_back[0]-r_sym[0]);
997 node_pt->x(t,1) =sign*(r_sym[1]+fract_y*(r_back[1]-r_sym[1]));
1009 template <
class ELEMENT>
1011 AlgebraicNode*& node_pt)
1014 GeomObject* back_pt=node_pt->geom_object_pt(
unsigned(0));
1026 double fract_x=node_pt->ref_value(
unsigned(0));
1031 double fract_y=node_pt->ref_value(1);
1035 double sign=node_pt->ref_value(2);
1038 Vector<double> zeta(back_pt->nlagrangian());
1040 Vector<double> r_back(back_pt->ndim());
1041 back_pt->position(t,zeta,r_back);
1044 double y_fin_edge=r_back[1]+fract_x*(y_tail-r_back[1]);
1047 node_pt->x(t,0)=r_back[0]+fract_x*(x_tail-r_back[0]);
1048 node_pt->x(t,1)=sign*fract_y*y_fin_edge;
GeomObject * Back_pt
Pointer to fish back.
double & y_fin()
y-position of fin tip
Fish shaped mesh. The geometry is defined by the Domain object FishDomain.
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?
double & xi_tail()
End coordinate on wall (near tail)
double & x_mouth()
x-position of mouth
void node_update_in_body(const unsigned &t, AlgebraicNode *&node_pt)
Algebraic update function for nodes in upper/lower body.
FishDomain * Domain_pt
Pointer to domain.
void setup_adaptivity()
Setup all the information that's required for spatial adaptivity: Set pointers to macro elements and ...
Fish shaped domain, represented by four MacroElements. Shape is parametrised by GeomObject that repre...
void setup_algebraic_node_update()
Setup algebraic update operation for all nodes (separate function because this task needs to be perfo...
FishMesh(TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor: Pass pointer to timestepper (defaults to the (Steady) default timestepper defined in Mes...
void node_update_in_fin(const unsigned &t, AlgebraicNode *&node_pt)
Algebraic update function for nodes in upper/lower fin.
double & x_fin()
x-position of fin tip
double & xi_nose()
Start coordinate on wall (near nose)