30 #ifndef OOMPH_BRETHERTON_SPINE_MESH_TEMPLATE_CC 31 #define OOMPH_BRETHERTON_SPINE_MESH_TEMPLATE_CC 34 #include "../generic/mesh_as_geometric_object.h" 35 #include "../generic/face_element_as_geometric_object.h" 61 template<
class ELEMENT,
class INTERFACE_ELEMENT>
67 const unsigned &nhalf,
69 GeomObject* lower_wall_pt,
70 GeomObject* upper_wall_pt,
71 const double& zeta_start,
72 const double& zeta_transition_start,
73 const double& zeta_transition_end,
74 const double& zeta_end,
75 TimeStepper* time_stepper_pt) :
77 (2*(nx1+nx2+nhalf),nh,1.0,h,time_stepper_pt),
78 Nx1(nx1), Nx2(nx2), Nx3(nx3), Nhalf(nhalf), Nh(nh), H(h),
79 Upper_wall_pt(upper_wall_pt), Lower_wall_pt(lower_wall_pt),
80 Zeta_start(zeta_start), Zeta_end(zeta_end),
81 Zeta_transition_start(zeta_transition_start),
82 Zeta_transition_end(zeta_transition_end),
83 Spine_centre_fraction_pt(&Default_spine_centre_fraction),
84 Default_spine_centre_fraction(0.5)
87 unsigned n_bulk = this->nelement();
89 for(
unsigned e=0;e<n_bulk;e++)
95 MeshChecker::assert_geometric_element<QElementGeometricBase,ELEMENT>(2);
98 MeshChecker::assert_geometric_element<SpineFiniteElement,ELEMENT>(2);
110 Vector<double> r_wall_lo(2), r_wall_up(2);
111 Vector<double> zeta(1), s_lo(1), s_up(1);
112 GeomObject *lower_sub_geom_object_pt=0, *upper_sub_geom_object_pt=0;
114 GeomObject *lower_transition_geom_object_pt=0;
115 GeomObject *upper_transition_geom_object_pt=0;
116 Vector<double> s_transition_lo(1), s_transition_up(1);
117 Vector<double> spine_centre(2);
125 double radius=-r_wall_lo[1]-
H;
128 if (std::fabs(r_wall_lo[1]+r_wall_up[1])>1.0e-4)
130 oomph_info <<
"\n\n=================================================== " << std::endl;
131 oomph_info <<
"Warning: " << std::endl;
132 oomph_info <<
"-------- " << std::endl;
133 oomph_info <<
" " << std::endl;
134 oomph_info <<
"Upper and lower walls are not symmetric at zeta=0" << std::endl;
135 oomph_info <<
"Your initial mesh will look very odd." << std::endl;
136 oomph_info <<
"y-coordinates of walls at zeta=0 are: " << r_wall_lo[1]
137 <<
" and " << r_wall_up[1] << std::endl << std::endl;
138 oomph_info <<
"===================================================\n\n " << std::endl;
145 unsigned n_x = 2*(nx1+nx2+nhalf);
147 for(
unsigned i=0;i<n_x;i++)
151 FiniteElement *interface_element_element_pt =
152 new INTERFACE_ELEMENT(this->finite_element_pt(n_x*(n_y-1)+i),2);
155 this->Element_pt.push_back(interface_element_element_pt);
172 this->element_pt((nx1+nx2+nhalf)*(nh+1)-2));
175 Vector<std::set<Node*> > set_boundary_node_pt(6);
178 for (
unsigned ibound=1;ibound<=3;ibound++)
180 unsigned numnod = this->nboundary_node(ibound);
181 for (
unsigned j=0;j<numnod;j++)
183 set_boundary_node_pt[ibound+2].insert(this->boundary_node_pt(ibound,j));
188 unsigned nnod = this->finite_element_pt(0)->nnode();
191 unsigned np = this->finite_element_pt(0)->nnode_1d();
194 unsigned n_prev_elements=0;
204 double dzeta_el=llayer/double(nx1);
205 double dzeta_node=llayer/double(nx1*(np-1));
208 for (
unsigned i=0;i<nx1;i++)
211 double zeta_lo = Zeta_start + double(i)*dzeta_el;
214 for (
unsigned j=0;j<nh;j++)
217 unsigned e=n_prev_elements+i*(nh+1)+j;
220 FiniteElement* el_pt = this->finite_element_pt(e);
223 for (
unsigned i0=0;i0<np;i0++)
225 for (
unsigned i1=0;i1<np;i1++)
231 SpineNode* nod_pt=
dynamic_cast<SpineNode*
>(el_pt->node_pt(n));
234 nod_pt->node_update_fct_id()=0;
241 zeta[0] = zeta_lo + double(i1)*dzeta_node;
243 Lower_wall_pt->locate_zeta(zeta,lower_sub_geom_object_pt,s_lo);
248 Vector<double> parameters(1,s_lo[0]);
249 nod_pt->spine_pt()->set_geom_parameter(parameters);
252 nod_pt->spine_pt()->height()=
H;
256 Vector<GeomObject*> geom_object_pt(1);
257 geom_object_pt[0] = lower_sub_geom_object_pt;
260 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
263 if (j==0) set_boundary_node_pt[0].insert(nod_pt);
271 n_prev_elements+=nx1*(nh+1);
280 Lower_wall_pt->locate_zeta(zeta,lower_transition_geom_object_pt,
282 Upper_wall_pt->locate_zeta(zeta,upper_transition_geom_object_pt,
286 lower_transition_geom_object_pt->position(s_transition_lo,r_wall_lo);
287 upper_transition_geom_object_pt->position(s_transition_up,r_wall_up);
292 spine_centre[0] = 0.5*(r_wall_lo[0] + r_wall_up[0]);
296 spine_centre[1] = r_wall_lo[1] +
305 double dzeta_el=d/double(nx2);
306 double dzeta_node=d/double(nx2*(np-1));
309 for (
unsigned i=0;i<nx2;i++)
312 double zeta_lo = Zeta_transition_start + double(i)*dzeta_el;
315 for (
unsigned j=0;j<nh;j++)
318 unsigned e=n_prev_elements+i*(nh+1)+j;
321 FiniteElement* el_pt = this->finite_element_pt(e);
324 for (
unsigned i0=0;i0<np;i0++)
326 for (
unsigned i1=0;i1<np;i1++)
332 SpineNode* nod_pt=
dynamic_cast<SpineNode*
>(el_pt->node_pt(n));
335 nod_pt->node_update_fct_id()=1;
341 zeta[0] = zeta_lo + double(i1)*dzeta_node;
343 Lower_wall_pt->locate_zeta(zeta,lower_sub_geom_object_pt,s_lo);
346 Vector<double> parameters(3);
347 parameters[0] = s_lo[0];
348 parameters[1] = s_transition_lo[0];
349 parameters[2] = s_transition_up[0];
350 nod_pt->spine_pt()->set_geom_parameter(parameters);
353 lower_sub_geom_object_pt->position(s_lo,r_wall_lo);
357 N[0] = spine_centre[0] - r_wall_lo[0];
358 N[1] = spine_centre[1] - r_wall_lo[1];
359 double length=sqrt(N[0]*N[0]+N[1]*N[1]);
360 nod_pt->spine_pt()->height()=length-radius;
364 Vector<GeomObject*> geom_object_pt(3);
365 geom_object_pt[0] = lower_sub_geom_object_pt;
366 geom_object_pt[1] = lower_transition_geom_object_pt;
367 geom_object_pt[2] = upper_transition_geom_object_pt;
370 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
373 if (j==0) set_boundary_node_pt[0].insert(nod_pt);
381 n_prev_elements+=nx2*(nh+1);
387 for (
unsigned i=0;i<nhalf;i++)
390 for (
unsigned j=0;j<nh;j++)
393 unsigned e=n_prev_elements+i*(nh+1)+j;
396 FiniteElement* el_pt = this->finite_element_pt(e);
399 for (
unsigned i0=0;i0<np;i0++)
401 for (
unsigned i1=0;i1<np;i1++)
407 SpineNode* nod_pt=
dynamic_cast<SpineNode*
>(el_pt->node_pt(n));
410 nod_pt->node_update_fct_id()=2;
419 Lower_wall_pt->locate_zeta(zeta,lower_sub_geom_object_pt,s_lo);
420 Upper_wall_pt->locate_zeta(zeta,upper_sub_geom_object_pt,s_up);
422 lower_sub_geom_object_pt->position(s_lo,r_wall_lo);
423 upper_sub_geom_object_pt->position(s_up,r_wall_up);
426 double vertical_fraction=
427 (double(i)+double(i1)/double(np-1))/
double(2.0*nhalf);
430 Vector<double> parameters(5);
431 parameters[0] = s_lo[0];
432 parameters[1] = s_up[0];
433 parameters[2] = vertical_fraction;
434 parameters[3] = s_transition_lo[0];
435 parameters[4] = s_transition_up[0];
436 nod_pt->spine_pt()->set_geom_parameter(parameters);
439 Vector<double> S0(2);
440 S0[0] = r_wall_lo[0] +
441 vertical_fraction*(r_wall_up[0]-r_wall_lo[0]);
442 S0[1] = r_wall_lo[1] +
443 vertical_fraction*(r_wall_up[1]-r_wall_lo[1]);
447 N[0] = spine_centre[0] - S0[0];
448 N[1] = spine_centre[1] - S0[1];
450 double length=sqrt(N[0]*N[0]+N[1]*N[1]);
451 nod_pt->spine_pt()->height()=length-radius;
454 Vector<GeomObject*> geom_object_pt(4);
455 geom_object_pt[0] = lower_sub_geom_object_pt;
456 geom_object_pt[1] = upper_sub_geom_object_pt;
457 geom_object_pt[2] = lower_transition_geom_object_pt;
458 geom_object_pt[3] = upper_transition_geom_object_pt;
461 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
464 if (j==0) set_boundary_node_pt[1].insert(nod_pt);
472 n_prev_elements+=nhalf*(nh+1);
479 for (
unsigned i=0;i<nhalf;i++)
482 for (
unsigned j=0;j<nh;j++)
485 unsigned e=n_prev_elements+i*(nh+1)+j;
488 FiniteElement* el_pt = this->finite_element_pt(e);
491 for (
unsigned i0=0;i0<np;i0++)
493 for (
unsigned i1=0;i1<np;i1++)
499 SpineNode* nod_pt=
dynamic_cast<SpineNode*
>(el_pt->node_pt(n));
502 nod_pt->node_update_fct_id()=3;
511 Lower_wall_pt->locate_zeta(zeta,lower_sub_geom_object_pt,s_lo);
512 Upper_wall_pt->locate_zeta(zeta,upper_sub_geom_object_pt,s_up);
514 lower_sub_geom_object_pt->position(s_lo,r_wall_lo);
515 upper_sub_geom_object_pt->position(s_up,r_wall_up);
518 double vertical_fraction=0.5 +
519 (double(i)+double(i1)/double(np-1))/
double(2.0*nhalf);
522 Vector<double> parameters(5);
523 parameters[0] = s_lo[0];
524 parameters[1] = s_up[0];
525 parameters[2] = vertical_fraction;
526 parameters[3] = s_transition_lo[0];
527 parameters[4] = s_transition_up[0];
528 nod_pt->spine_pt()->set_geom_parameter(parameters);
531 Vector<double> S0(2);
532 S0[0] = r_wall_lo[0] +
533 vertical_fraction*(r_wall_up[0]-r_wall_lo[0]);
534 S0[1] = r_wall_lo[1] +
535 vertical_fraction*(r_wall_up[1]-r_wall_lo[1]);
539 N[0] = spine_centre[0] - S0[0];
540 N[1] = spine_centre[1] - S0[1];
542 double length=sqrt(N[0]*N[0]+N[1]*N[1]);
543 nod_pt->spine_pt()->height()=length-radius;
546 Vector<GeomObject*> geom_object_pt(4);
547 geom_object_pt[0] = lower_sub_geom_object_pt;
548 geom_object_pt[1] = upper_sub_geom_object_pt;
549 geom_object_pt[2] = lower_transition_geom_object_pt;
550 geom_object_pt[3] = upper_transition_geom_object_pt;
553 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
556 if (j==0) set_boundary_node_pt[1].insert(nod_pt);
563 n_prev_elements+=nhalf*(nh+1);
572 double dzeta_el=d/double(nx2);
573 double dzeta_node=d/double(nx2*(np-1));
576 for (
unsigned i=0;i<nx2;i++)
582 for (
unsigned j=0;j<nh;j++)
585 unsigned e=n_prev_elements+i*(nh+1)+j;
588 FiniteElement* el_pt = this->finite_element_pt(e);
591 for (
unsigned i0=0;i0<np;i0++)
593 for (
unsigned i1=0;i1<np;i1++)
599 SpineNode* nod_pt=
dynamic_cast<SpineNode*
>(el_pt->node_pt(n));
602 nod_pt->node_update_fct_id()=4;
609 zeta[0] = zeta_lo - double(i1)*dzeta_node;
611 Upper_wall_pt->locate_zeta(zeta,upper_sub_geom_object_pt,s_up);
614 Vector<double> parameters(3);
615 parameters[0] = s_up[0];
616 parameters[1] = s_transition_lo[0];
617 parameters[2] = s_transition_up[0];
618 nod_pt->spine_pt()->set_geom_parameter(parameters);
621 upper_sub_geom_object_pt->position(s_up,r_wall_up);
625 N[0] = spine_centre[0] - r_wall_up[0];
626 N[1] = spine_centre[1] - r_wall_up[1];
627 double length = sqrt(N[0]*N[0]+N[1]*N[1]);
628 nod_pt->spine_pt()->height()=length-radius;
632 Vector<GeomObject*> geom_object_pt(3);
633 geom_object_pt[0] = upper_sub_geom_object_pt;
634 geom_object_pt[1] = lower_transition_geom_object_pt;
635 geom_object_pt[2] = upper_transition_geom_object_pt;
638 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
641 if (j==0) set_boundary_node_pt[2].insert(nod_pt);
649 n_prev_elements+=nx2*(nh+1);
657 double dzeta_el=llayer/double(nx1);
658 double dzeta_node=llayer/double(nx1*(np-1));
661 for (
unsigned i=0;i<nx1;i++)
664 double zeta_lo = Zeta_transition_start - double(i)*dzeta_el;
667 for (
unsigned j=0;j<nh;j++)
670 unsigned e=n_prev_elements+i*(nh+1)+j;
673 FiniteElement* el_pt = this->finite_element_pt(e);
676 for (
unsigned i0=0;i0<np;i0++)
678 for (
unsigned i1=0;i1<np;i1++)
684 SpineNode* nod_pt=
dynamic_cast<SpineNode*
>(el_pt->node_pt(n));
687 nod_pt->node_update_fct_id()=5;
694 zeta[0] = zeta_lo - double(i1)*dzeta_node;
696 Upper_wall_pt->locate_zeta(zeta,upper_sub_geom_object_pt,s_up);
699 Vector<double> parameters(1,s_up[0]);
700 nod_pt->spine_pt()->set_geom_parameter(parameters);
703 nod_pt->spine_pt()->height()=
H;
707 Vector<GeomObject*> geom_object_pt(1);
708 geom_object_pt[0] = upper_sub_geom_object_pt;
711 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
714 if (j==0) set_boundary_node_pt[2].insert(nod_pt);
723 this->remove_boundary_nodes();
724 this->set_nboundary(6);
727 for (
unsigned ibound=0;ibound<6;ibound++)
729 typedef std::set<Node*>::iterator IT;
730 for (IT it=set_boundary_node_pt[ibound].begin();
731 it!=set_boundary_node_pt[ibound].end();it++)
733 this->add_boundary_node(ibound,*it);
742 Vector<double> zeta(1);
743 unsigned n_boundary_node = this->nboundary_node(4);
744 for(
unsigned n=0;n<n_boundary_node;++n)
746 zeta[0] = this->boundary_node_pt(4,n)->x(0);
747 this->boundary_node_pt(4,n)->set_coordinates_on_boundary(4,zeta);
760 (
Nx3,2*nhalf,1.0,1.0,time_stepper_pt);
763 aux_mesh_pt->remove_boundary_nodes();
767 nnod=aux_mesh_pt->nnode();
768 std::set<Node*> aux_node_pt;
769 for (
unsigned i=0;i<nnod;i++)
771 aux_node_pt.insert(aux_mesh_pt->node_pt(i));
778 unsigned first_bound_node=0;
781 for (
unsigned e=0;e<2*nhalf;e++)
783 FiniteElement* el_pt=aux_mesh_pt->finite_element_pt(e*Nx3);
785 for (
unsigned i=0;i<np;i++)
792 aux_node_pt.erase(el_pt->node_pt(n));
793 delete el_pt->node_pt(n);
796 el_pt->node_pt(n) = this->boundary_node_pt(1,first_bound_node+i);
800 first_bound_node+=np-1;
805 typedef std::set<Node*>::iterator IT;
806 for (IT it=aux_node_pt.begin();it!=aux_node_pt.end();it++)
808 this->Node_pt.push_back(*it);
812 unsigned nelement_orig = this->Element_pt.size();
815 unsigned nelem=aux_mesh_pt->nelement();
816 for (
unsigned e=0;e<nelem;e++)
818 this->Element_pt.push_back(aux_mesh_pt->element_pt(e));
825 this->remove_boundary_nodes(1);
834 Spine* new_spine_pt=
new Spine(1.0);
835 this->Spine_pt.push_back(new_spine_pt);
836 new_spine_pt->spine_height_pt()->pin(0);
839 SpineNode* nod_pt = this->element_node_pt(nelement_orig+0,0);
841 nod_pt->spine_pt() = new_spine_pt;
843 nod_pt->fraction() = 0.0;
845 nod_pt->spine_mesh_pt() =
this;
847 nod_pt->node_update_fct_id() = 6;
852 Lower_wall_pt->locate_zeta(zeta,lower_sub_geom_object_pt,s_lo);
853 Upper_wall_pt->locate_zeta(zeta,upper_sub_geom_object_pt,s_up);
855 lower_sub_geom_object_pt->position(s_lo,r_wall_lo);
856 upper_sub_geom_object_pt->position(s_up,r_wall_up);
859 Vector<double> parameters(2);
860 parameters[0] = s_lo[0];
861 parameters[1] = s_up[0];
862 new_spine_pt->set_geom_parameter(parameters);
866 Vector<GeomObject*> geom_object_pt(2);
867 geom_object_pt[0] = lower_sub_geom_object_pt;
868 geom_object_pt[1] = upper_sub_geom_object_pt;
871 new_spine_pt->set_geom_object_pt(geom_object_pt);
875 for(
unsigned long i=0;i<2*nhalf;i++)
878 for(
unsigned l1=1;l1<np;l1++)
881 SpineNode* nod_pt = this->element_node_pt(nelement_orig+i*Nx3,l1*np);
883 nod_pt->spine_pt() = new_spine_pt;
885 nod_pt->fraction() =(double(i)+double(l1)/double(np-1))/
double(2*nhalf);
887 nod_pt->spine_mesh_pt() =
this;
889 nod_pt->node_update_fct_id() = 6;
898 for(
unsigned long j=0;j<
Nx3;j++)
902 for(
unsigned l2=1;l2<np;l2++)
905 new_spine_pt=
new Spine(1.0);
906 this->Spine_pt.push_back(new_spine_pt);
907 new_spine_pt->spine_height_pt()->pin(0);
910 SpineNode* nod_pt = this->element_node_pt(nelement_orig+j,l2);
912 nod_pt->spine_pt() = new_spine_pt;
914 nod_pt->fraction() = 0.0;
916 nod_pt->spine_mesh_pt() =
this;
918 nod_pt->node_update_fct_id() = 6;
921 this->add_boundary_node(0,nod_pt);
922 if ((j==Nx3-1)&&(l2==np-1))
924 this->add_boundary_node(1,nod_pt);
929 double dzeta_nod=dzeta_el/double(np-1);
935 Lower_wall_pt->locate_zeta(zeta,lower_sub_geom_object_pt,s_lo);
936 Upper_wall_pt->locate_zeta(zeta,upper_sub_geom_object_pt,s_up);
938 lower_sub_geom_object_pt->position(s_lo,r_wall_lo);
939 upper_sub_geom_object_pt->position(s_up,r_wall_up);
942 Vector<double> parameters(2);
943 parameters[0] = s_lo[0];
944 parameters[1] = s_up[0];
945 new_spine_pt->set_geom_parameter(parameters);
949 Vector<GeomObject*> geom_object_pt(2);
950 geom_object_pt[0] = lower_sub_geom_object_pt;
951 geom_object_pt[1] = upper_sub_geom_object_pt;
954 new_spine_pt->set_geom_object_pt(geom_object_pt);
959 for(
unsigned long i=0;i<2*nhalf;i++)
962 for(
unsigned l1=1;l1<np;l1++)
966 this->element_node_pt(nelement_orig+i*Nx3+j,l1*np+l2);
968 nod_pt->spine_pt() = new_spine_pt;
971 (double(i)+double(l1)/double(np-1))/
double(2*nhalf);
973 nod_pt->spine_mesh_pt() =
this;
975 nod_pt->node_update_fct_id() = 6;
978 if ((j==Nx3-1)&&(l2==np-1))
980 this->add_boundary_node(1,nod_pt);
984 if ((i==2*nhalf-1)&&(l1==np-1))
986 this->add_boundary_node(2,nod_pt);
996 this->setup_boundary_element_info();
1000 aux_mesh_pt->flush_element_and_node_storage();
1015 template<
class ELEMENT,
class INTERFACE_ELEMENT>
1018 unsigned Nx = this->
Nx;
1019 unsigned Ny = this->
Ny;
1021 unsigned long Nelement = this->nelement();
1023 unsigned long Nfluid = Nx*
Ny;
1025 Vector<FiniteElement *> dummy;
1028 for(
unsigned long j=0;j<
Nx;j++)
1031 for(
unsigned long i=0;i<
Ny;i++)
1034 dummy.push_back(this->finite_element_pt(Nx*i + j));
1038 dummy.push_back(this->finite_element_pt(Nfluid+j));
1042 for(
unsigned long e=0;e<Nelement;e++)
1044 this->Element_pt[e] = dummy[e];
1053 template<
class ELEMENT,
class INTERFACE_ELEMENT>
1056 Vector<double> &initial_zeta,
1057 const Vector<double> &spine_base,
1058 const Vector<double> &spine_end)
1062 double lambda = 0.5;
1064 Vector<double> dx(2);
1065 Vector<double> new_free_x(2);
1066 DenseDoubleMatrix jacobian(2,2,0.0);
1067 Vector<double> spine_x(2);
1068 Vector<double> free_x(2);
1070 double maxres = 100.0;
1078 for(
unsigned i=0;i<2;++i) {spine_x[i] = spine_base[i] +
1079 lambda*(spine_end[i] - spine_base[i]);}
1082 fs_geom_object_pt->position(initial_zeta,free_x);
1084 for(
unsigned i=0;i<2;++i) {dx[i] = spine_x[i] - free_x[i];}
1087 jacobian(0,0) = (spine_end[0] - spine_base[0]);
1088 jacobian(1,0) = (spine_end[1] - spine_base[1]);
1091 double FD_Jstep = 1.0e-6;
1092 double old_zeta = initial_zeta[0];
1093 initial_zeta[0] += FD_Jstep;
1094 fs_geom_object_pt->position(initial_zeta,new_free_x);
1096 for(
unsigned i=0;i<2;++i)
1097 {jacobian(i,1) = (free_x[i] - new_free_x[i])/FD_Jstep;}
1102 lambda -= dx[0]; initial_zeta[0] = old_zeta - dx[1];
1106 for(
unsigned i=0;i<2;++i) {spine_x[i] = spine_base[i] +
1107 lambda*(spine_end[i] - spine_base[i]);}
1108 fs_geom_object_pt->position(initial_zeta,free_x);
1110 for(
unsigned i=0;i<2;++i) {dx[i] = spine_x[i] - free_x[i];}
1111 maxres = std::fabs(dx[0]) > std::fabs(dx[1]) ? std::fabs(dx[0]) :
1116 throw OomphLibError(
"Failed to converge after 100 steps",
1117 OOMPH_CURRENT_FUNCTION,
1118 OOMPH_EXCEPTION_LOCATION);
1121 }
while(maxres > 1.0e-8);
1124 oomph_info <<
"DONE " << initial_zeta[0] << std::endl;
1125 double spine_length = sqrt(pow((spine_base[0] - spine_end[0]),2.0)
1126 + pow((spine_base[1] - spine_end[1]),2.0));
1128 return (lambda*spine_length);
1134 template<
class ELEMENT,
class INTERFACE_ELEMENT>
1136 const double &zeta_lo_transition_start,
1137 const double &zeta_lo_transition_end,
1138 const double &zeta_up_transition_start,
1139 const double &zeta_up_transition_end)
1142 Mesh* fs_mesh_pt =
new Mesh;
1143 this->
template build_face_mesh<ELEMENT,FaceElementAsGeomObject>
1148 unsigned n_face_element = fs_mesh_pt->nelement();
1150 for(
unsigned e=0;e<n_face_element;e++)
1153 dynamic_cast<FaceElementAsGeomObject<ELEMENT>*
> 1154 (fs_mesh_pt->element_pt(e))->set_boundary_number_in_bulk_mesh(4);
1160 MeshAsGeomObject* fs_geom_object_pt =
new MeshAsGeomObject(fs_mesh_pt);
1164 double llayer_lower = zeta_lo_transition_start -
Zeta_start;
1165 double llayer_upper = zeta_up_transition_start -
Zeta_start;
1168 double d_lower = zeta_lo_transition_end - zeta_lo_transition_start;
1169 double d_upper = zeta_up_transition_end - zeta_up_transition_start;
1172 Vector<double> r_wall_lo(2), r_wall_up(2);
1173 Vector<double> zeta(1), s_lo(1), s_up(1);
1174 GeomObject *lower_sub_geom_object_pt=0, *upper_sub_geom_object_pt=0;
1176 GeomObject *lower_transition_geom_object_pt=0;
1177 GeomObject *upper_transition_geom_object_pt=0;
1178 Vector<double> s_transition_lo(1), s_transition_up(1);
1179 Vector<double> spine_centre(2);
1182 unsigned np = this->finite_element_pt(0)->nnode_1d();
1189 zeta[0] = zeta_lo_transition_start;
1190 Lower_wall_pt->locate_zeta(zeta,lower_transition_geom_object_pt,
1193 zeta[0] = zeta_up_transition_start;
1194 Upper_wall_pt->locate_zeta(zeta,upper_transition_geom_object_pt,
1198 lower_transition_geom_object_pt->position(s_transition_lo,r_wall_lo);
1199 upper_transition_geom_object_pt->position(s_transition_up,r_wall_up);
1204 spine_centre[0] = 0.5*(r_wall_lo[0] + r_wall_up[0]);
1208 spine_centre[1] = r_wall_lo[1] +
1214 unsigned n_prev_elements=0;
1217 Vector<double> spine_end(2);
1218 Vector<double> fs_zeta(1,0.0);
1223 oomph_info <<
"LOWER FILM " << std::endl;
1225 double dzeta_el = llayer_lower/double(
Nx1);
1226 double dzeta_node = llayer_lower/double(
Nx1*(np-1));
1229 for(
unsigned i=0;i<
Nx1;i++)
1232 double zeta_lo = Zeta_start + double(i)*dzeta_el;
1235 unsigned e = n_prev_elements + i*(
Nh+1);
1238 FiniteElement* el_pt = this->finite_element_pt(e);
1241 for(
unsigned i1=0;i1<(np-1);i1++)
1244 SpineNode* nod_pt=
dynamic_cast<SpineNode*
>(el_pt->node_pt(i1));
1247 zeta[0] = zeta_lo + double(i1)*dzeta_node;
1249 nod_pt->set_coordinates_on_boundary(0,zeta);
1251 Lower_wall_pt->locate_zeta(zeta,lower_sub_geom_object_pt,s_lo);
1256 Vector<double> parameters(1,s_lo[0]);
1257 nod_pt->spine_pt()->set_geom_parameter(parameters);
1261 Vector<GeomObject*> geom_object_pt(1);
1262 geom_object_pt[0] = lower_sub_geom_object_pt;
1265 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
1268 lower_sub_geom_object_pt->position(s_lo,r_wall_lo);
1270 spine_end[0] = r_wall_lo[0];
1271 spine_end[1] = spine_centre[1];
1272 nod_pt->spine_pt()->height() =
1278 n_prev_elements += Nx1*(
Nh+1);
1285 oomph_info <<
"LOWER HORIZONTAL TRANSITION " << std::endl;
1287 double dzeta_el=d_lower/double(
Nx2);
1288 double dzeta_node=d_lower/double(
Nx2*(np-1));
1291 for (
unsigned i=0;i<
Nx2;i++)
1294 double zeta_lo = zeta_lo_transition_start + double(i)*dzeta_el;
1297 unsigned e=n_prev_elements+i*(
Nh+1);
1300 FiniteElement* el_pt = this->finite_element_pt(e);
1303 for (
unsigned i1=0;i1<(np-1);i1++)
1306 SpineNode* nod_pt=
dynamic_cast<SpineNode*
>(el_pt->node_pt(i1));
1309 zeta[0] = zeta_lo + double(i1)*dzeta_node;
1311 nod_pt->set_coordinates_on_boundary(0,zeta);
1313 Lower_wall_pt->locate_zeta(zeta,lower_sub_geom_object_pt,s_lo);
1316 Vector<double> parameters(3);
1317 parameters[0] = s_lo[0];
1318 parameters[1] = s_transition_lo[0];
1319 parameters[2] = s_transition_up[0];
1320 nod_pt->spine_pt()->set_geom_parameter(parameters);
1324 Vector<GeomObject*> geom_object_pt(3);
1325 geom_object_pt[0] = lower_sub_geom_object_pt;
1326 geom_object_pt[1] = lower_transition_geom_object_pt;
1327 geom_object_pt[2] = upper_transition_geom_object_pt;
1330 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
1333 lower_sub_geom_object_pt->position(s_lo,r_wall_lo);
1335 nod_pt->spine_pt()->height() =
1341 n_prev_elements += Nx2*(
Nh+1);
1347 oomph_info <<
"LOWER VERTICAL TRANSITION " << std::endl;
1348 for (
unsigned i=0;i<
Nhalf;i++)
1351 unsigned e = n_prev_elements+i*(
Nh+1);
1354 FiniteElement* el_pt = this->finite_element_pt(e);
1357 for (
unsigned i1=0;i1<(np-1);i1++)
1363 SpineNode* nod_pt=
dynamic_cast<SpineNode*
>(el_pt->node_pt(np+i1));
1366 zeta[0] = zeta_lo_transition_end;
1368 Lower_wall_pt->locate_zeta(zeta,lower_sub_geom_object_pt,s_lo);
1369 zeta[0] = zeta_up_transition_end;
1370 Upper_wall_pt->locate_zeta(zeta,upper_sub_geom_object_pt,s_up);
1372 lower_sub_geom_object_pt->position(s_lo,r_wall_lo);
1373 upper_sub_geom_object_pt->position(s_up,r_wall_up);
1376 double vertical_fraction=
1377 (double(i)+double(i1)/double(np-1))/
double(2.0*Nhalf);
1380 Vector<double> parameters(5);
1381 parameters[0] = s_lo[0];
1382 parameters[1] = s_up[0];
1383 parameters[2] = vertical_fraction;
1384 parameters[3] = s_transition_lo[0];
1385 parameters[4] = s_transition_up[0];
1386 nod_pt->spine_pt()->set_geom_parameter(parameters);
1389 Vector<double> S0(2);
1390 S0[0] = r_wall_lo[0] +
1391 vertical_fraction*(r_wall_up[0]-r_wall_lo[0]);
1392 S0[1] = r_wall_lo[1] +
1393 vertical_fraction*(r_wall_up[1]-r_wall_lo[1]);
1396 Vector<GeomObject*> geom_object_pt(4);
1397 geom_object_pt[0] = lower_sub_geom_object_pt;
1398 geom_object_pt[1] = upper_sub_geom_object_pt;
1399 geom_object_pt[2] = lower_transition_geom_object_pt;
1400 geom_object_pt[3] = upper_transition_geom_object_pt;
1403 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
1406 nod_pt->spine_pt()->height() =
1412 n_prev_elements+=Nhalf*(
Nh+1);
1419 oomph_info <<
"UPPER VERTICAL TRANSITION" << std::endl;
1420 for (
unsigned i=0;i<
Nhalf;i++)
1423 unsigned e = n_prev_elements+i*(
Nh+1);
1426 FiniteElement* el_pt = this->finite_element_pt(e);
1429 for (
unsigned i1=0;i1<(np-1);i1++)
1435 SpineNode* nod_pt=
dynamic_cast<SpineNode*
>(el_pt->node_pt(np+i1));
1438 zeta[0] = zeta_lo_transition_end;
1440 Lower_wall_pt->locate_zeta(zeta,lower_sub_geom_object_pt,s_lo);
1441 zeta[0] = zeta_up_transition_end;
1442 Upper_wall_pt->locate_zeta(zeta,upper_sub_geom_object_pt,s_up);
1444 lower_sub_geom_object_pt->position(s_lo,r_wall_lo);
1445 upper_sub_geom_object_pt->position(s_up,r_wall_up);
1449 double vertical_fraction= 0.5 +
1450 (double(i)+double(i1)/double(np-1))/
double(2.0*Nhalf);
1453 Vector<double> parameters(5);
1454 parameters[0] = s_lo[0];
1455 parameters[1] = s_up[0];
1456 parameters[2] = vertical_fraction;
1457 parameters[3] = s_transition_lo[0];
1458 parameters[4] = s_transition_up[0];
1459 nod_pt->spine_pt()->set_geom_parameter(parameters);
1462 Vector<double> S0(2);
1463 S0[0] = r_wall_lo[0] +
1464 vertical_fraction*(r_wall_up[0]-r_wall_lo[0]);
1465 S0[1] = r_wall_lo[1] +
1466 vertical_fraction*(r_wall_up[1]-r_wall_lo[1]);
1469 Vector<GeomObject*> geom_object_pt(4);
1470 geom_object_pt[0] = lower_sub_geom_object_pt;
1471 geom_object_pt[1] = upper_sub_geom_object_pt;
1472 geom_object_pt[2] = lower_transition_geom_object_pt;
1473 geom_object_pt[3] = upper_transition_geom_object_pt;
1476 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
1479 nod_pt->spine_pt()->height() =
1485 n_prev_elements+=Nhalf*(
Nh+1);
1492 oomph_info <<
"UPPER HORIZONTAL TRANSITION " << std::endl;
1494 double dzeta_el=d_upper/double(
Nx2);
1495 double dzeta_node=d_upper/double(
Nx2*(np-1));
1498 for (
unsigned i=0;i<
Nx2;i++)
1501 double zeta_lo = zeta_up_transition_end - double(i)*dzeta_el;
1504 unsigned e=n_prev_elements+i*(
Nh+1);
1507 FiniteElement* el_pt = this->finite_element_pt(e);
1510 for (
unsigned i1=0;i1<(np-1);i1++)
1513 SpineNode* nod_pt=
dynamic_cast<SpineNode*
>(el_pt->node_pt(np+i1));
1516 zeta[0] = zeta_lo - double(i1)*dzeta_node;
1518 el_pt->node_pt(i1)->set_coordinates_on_boundary(2,zeta);
1520 Upper_wall_pt->locate_zeta(zeta,upper_sub_geom_object_pt,s_up);
1523 Vector<double> parameters(3);
1524 parameters[0] = s_up[0];
1525 parameters[1] = s_transition_lo[0];
1526 parameters[2] = s_transition_up[0];
1527 nod_pt->spine_pt()->set_geom_parameter(parameters);
1531 Vector<GeomObject*> geom_object_pt(3);
1532 geom_object_pt[0] = upper_sub_geom_object_pt;
1533 geom_object_pt[1] = lower_transition_geom_object_pt;
1534 geom_object_pt[2] = upper_transition_geom_object_pt;
1537 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
1541 upper_sub_geom_object_pt->position(s_up,r_wall_up);
1543 nod_pt->spine_pt()->height() =
1550 n_prev_elements += Nx2*(
Nh+1);
1557 oomph_info <<
"UPPER THIN FILM" << std::endl;
1559 double dzeta_el=llayer_upper/double(
Nx1);
1560 double dzeta_node=llayer_upper/double(
Nx1*(np-1));
1563 for (
unsigned i=0;i<
Nx1;i++)
1566 double zeta_lo = zeta_up_transition_start - double(i)*dzeta_el;
1569 unsigned e=n_prev_elements+i*(
Nh+1);
1572 FiniteElement* el_pt = this->finite_element_pt(e);
1575 for (
unsigned i1=0;i1<(np-1);i1++)
1578 SpineNode* nod_pt=
dynamic_cast<SpineNode*
>(el_pt->node_pt(i1));
1581 zeta[0] = zeta_lo - double(i1)*dzeta_node;
1583 nod_pt->set_coordinates_on_boundary(2,zeta);
1585 Upper_wall_pt->locate_zeta(zeta,upper_sub_geom_object_pt,s_up);
1588 Vector<double> parameters(1,s_up[0]);
1589 nod_pt->spine_pt()->set_geom_parameter(parameters);
1593 Vector<GeomObject*> geom_object_pt(1);
1594 geom_object_pt[0] = upper_sub_geom_object_pt;
1597 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
1600 upper_sub_geom_object_pt->position(s_up,r_wall_up);
1601 spine_end[0] = r_wall_up[0];
1602 spine_end[1] = spine_centre[1];
1604 nod_pt->spine_pt()->height() =
1606 r_wall_up,spine_end);
1612 n_prev_elements += Nx1*(
Nh+1);
1618 unsigned e = n_prev_elements;
1621 SpineNode* nod_pt = this->element_node_pt(e,0);
1624 zeta[0] = zeta_lo_transition_end;
1626 Lower_wall_pt->locate_zeta(zeta,lower_sub_geom_object_pt,s_lo);
1627 zeta[0] = zeta_up_transition_end;
1628 Upper_wall_pt->locate_zeta(zeta,upper_sub_geom_object_pt,s_up);
1630 lower_sub_geom_object_pt->position(s_lo,r_wall_lo);
1631 upper_sub_geom_object_pt->position(s_up,r_wall_up);
1634 Vector<double> parameters(2);
1635 parameters[0] = s_lo[0];
1636 parameters[1] = s_up[0];
1637 nod_pt->spine_pt()->set_geom_parameter(parameters);
1641 Vector<GeomObject*> geom_object_pt(2);
1642 geom_object_pt[0] = lower_sub_geom_object_pt;
1643 geom_object_pt[1] = upper_sub_geom_object_pt;
1646 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
1652 for(
unsigned long j=0;j<
Nx3;j++)
1654 unsigned e = n_prev_elements + j;
1658 for(
unsigned l2=0;l2<np;l2++)
1661 SpineNode* nod_pt = this->element_node_pt(e,l2);
1664 double dzeta_el_lower=(
Zeta_end-zeta_lo_transition_end)/
double(Nx3);
1665 double dzeta_nod_lower=dzeta_el_lower/double(np-1);
1667 double dzeta_el_upper=(
Zeta_end-zeta_up_transition_end)/
double(Nx3);
1668 double dzeta_nod_upper=dzeta_el_upper/double(np-1);
1671 zeta[0] = zeta_lo_transition_end + j*dzeta_el_lower + l2*dzeta_nod_lower;
1673 nod_pt->set_coordinates_on_boundary(0,zeta);
1676 Lower_wall_pt->locate_zeta(zeta,lower_sub_geom_object_pt,s_lo);
1678 zeta[0] = zeta_up_transition_end + j*dzeta_el_upper + l2*dzeta_nod_upper;
1680 this->element_node_pt(e+Nx3*(2*
Nhalf-1),np*(np-1)+l2)
1681 ->set_coordinates_on_boundary(2,zeta);
1682 Upper_wall_pt->locate_zeta(zeta,upper_sub_geom_object_pt,s_up);
1684 lower_sub_geom_object_pt->position(s_lo,r_wall_lo);
1685 upper_sub_geom_object_pt->position(s_up,r_wall_up);
1688 Vector<double> parameters(2);
1689 parameters[0] = s_lo[0];
1690 parameters[1] = s_up[0];
1691 nod_pt->spine_pt()->set_geom_parameter(parameters);
1695 Vector<GeomObject*> geom_object_pt(2);
1696 geom_object_pt[0] = lower_sub_geom_object_pt;
1697 geom_object_pt[1] = upper_sub_geom_object_pt;
1700 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
1708 delete fs_geom_object_pt;
1711 for(
unsigned e=n_face_element;e>0;e--)
1713 delete fs_mesh_pt->element_pt(e-1);
1714 fs_mesh_pt->element_pt(e-1) = 0;
1717 fs_mesh_pt->flush_element_and_node_storage();
unsigned Nhalf
Number of elements in vertical transition region (there are twice as many elements across the channel...
double Zeta_end
Wall coordinate of end of liquid filled region (inflow)
ELEMENT * Control_element_pt
Pointer to control element (just under the symmetry line near the bubble tip; the bubble tip is locat...
BrethertonSpineMesh(const unsigned &nx1, const unsigned &nx2, const unsigned &nx3, const unsigned &nh, const unsigned &nhalf, const double &h, GeomObject *lower_wall_pt, GeomObject *upper_wall_pt, const double &zeta_start, const double &zeta_transition_start, const double &zeta_transition_end, const double &zeta_end, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor. Arguments:
double Zeta_transition_end
Wall coordinate of end of transition region.
void reposition_spines(const double &zeta_lo_transition_start, const double &zeta_lo_transition_end, const double &zeta_up_transition_start, const double &zeta_up_transition_end)
Reposition the spines in response to changes in geometry.
unsigned Ny
Ny: number of elements in y-direction.
unsigned Nx3
Number of elements along wall in channel region.
unsigned Nx1
Number of elements along wall in deposited film region.
double H
Thickness of deposited film.
double Zeta_transition_start
Wall coordinate of start of the transition region.
double spine_centre_fraction() const
Read the value of the spine centre's vertical fraction.
unsigned Nh
Number of elements across the deposited film.
unsigned Nx2
Number of elements along wall in horizontal transition region.
unsigned Nx
Nx: number of elements in x-direction.
double Zeta_start
Start coordinate on wall.
Vector< FiniteElement * > Interface_element_pt
Vector of pointers to interface elements.
GeomObject * Upper_wall_pt
Pointer to geometric object that represents the upper wall.
Vector< FiniteElement * > Bulk_element_pt
Vector of pointers to element in the fluid layer.
double find_distance_to_free_surface(GeomObject *const &fs_geom_object_pt, Vector< double > &initial_zeta, const Vector< double > &spine_base, const Vector< double > &spine_end)
Recalculate the spine lengths after repositioning.
GeomObject * Lower_wall_pt
Pointer to geometric object that represents the lower wall.
void initial_element_reorder()
Initial reordering elements of the elements – before the channel mesh is added. Vertical stacks of e...