26 #ifndef OOMPH_BRETHERTON_SPINE_MESH_TEMPLATE_CC
27 #define OOMPH_BRETHERTON_SPINE_MESH_TEMPLATE_CC
30 #include "../generic/mesh_as_geometric_object.h"
31 #include "../generic/face_element_as_geometric_object.h"
57 template<
class ELEMENT,
class INTERFACE_ELEMENT>
63 const unsigned& nhalf,
65 GeomObject* lower_wall_pt,
66 GeomObject* upper_wall_pt,
67 const double& zeta_start,
68 const double& zeta_transition_start,
69 const double& zeta_transition_end,
70 const double& zeta_end,
71 TimeStepper* time_stepper_pt)
73 2 * (nx1 + nx2 + nhalf), nh, 1.0, h, time_stepper_pt),
80 Upper_wall_pt(upper_wall_pt),
81 Lower_wall_pt(lower_wall_pt),
82 Zeta_start(zeta_start),
84 Zeta_transition_start(zeta_transition_start),
85 Zeta_transition_end(zeta_transition_end),
86 Spine_centre_fraction_pt(&Default_spine_centre_fraction),
87 Default_spine_centre_fraction(0.5)
90 unsigned n_bulk = this->nelement();
92 for (
unsigned e = 0; e < n_bulk; e++)
98 MeshChecker::assert_geometric_element<QElementGeometricBase, ELEMENT>(2);
101 MeshChecker::assert_geometric_element<SpineFiniteElement, ELEMENT>(2);
113 Vector<double> r_wall_lo(2), r_wall_up(2);
114 Vector<double> zeta(1), s_lo(1), s_up(1);
115 GeomObject *lower_sub_geom_object_pt = 0, *upper_sub_geom_object_pt = 0;
117 GeomObject* lower_transition_geom_object_pt = 0;
118 GeomObject* upper_transition_geom_object_pt = 0;
119 Vector<double> s_transition_lo(1), s_transition_up(1);
120 Vector<double> spine_centre(2);
128 double radius = -r_wall_lo[1] -
H;
131 if (std::fabs(r_wall_lo[1] + r_wall_up[1]) > 1.0e-4)
133 oomph_info <<
"\n\n=================================================== "
135 oomph_info <<
"Warning: " << std::endl;
136 oomph_info <<
"-------- " << std::endl;
137 oomph_info <<
" " << std::endl;
138 oomph_info <<
"Upper and lower walls are not symmetric at zeta=0"
140 oomph_info <<
"Your initial mesh will look very odd." << std::endl;
141 oomph_info <<
"y-coordinates of walls at zeta=0 are: " << r_wall_lo[1]
142 <<
" and " << r_wall_up[1] << std::endl
144 oomph_info <<
"===================================================\n\n "
152 unsigned n_x = 2 * (nx1 + nx2 + nhalf);
154 for (
unsigned i = 0; i < n_x; i++)
158 FiniteElement* interface_element_element_pt =
new INTERFACE_ELEMENT(
159 this->finite_element_pt(n_x * (n_y - 1) + i), 2);
162 this->Element_pt.push_back(interface_element_element_pt);
178 this->element_pt((nx1 + nx2 + nhalf) * (nh + 1) - 2));
181 Vector<std::set<Node*>> set_boundary_node_pt(6);
184 for (
unsigned ibound = 1; ibound <= 3; ibound++)
186 unsigned numnod = this->nboundary_node(ibound);
187 for (
unsigned j = 0; j < numnod; j++)
189 set_boundary_node_pt[ibound + 2].insert(
190 this->boundary_node_pt(ibound, j));
195 unsigned nnod = this->finite_element_pt(0)->nnode();
198 unsigned np = this->finite_element_pt(0)->nnode_1d();
201 unsigned n_prev_elements = 0;
211 double dzeta_el = llayer / double(nx1);
212 double dzeta_node = llayer / double(nx1 * (np - 1));
215 for (
unsigned i = 0; i < nx1; i++)
218 double zeta_lo =
Zeta_start + double(i) * dzeta_el;
221 for (
unsigned j = 0; j < nh; j++)
224 unsigned e = n_prev_elements + i * (nh + 1) + j;
227 FiniteElement* el_pt = this->finite_element_pt(e);
230 for (
unsigned i0 = 0; i0 < np; i0++)
232 for (
unsigned i1 = 0; i1 < np; i1++)
235 unsigned n = i0 * np + i1;
238 SpineNode* nod_pt =
dynamic_cast<SpineNode*
>(el_pt->node_pt(n));
241 nod_pt->node_update_fct_id() = 0;
248 zeta[0] = zeta_lo + double(i1) * dzeta_node;
251 zeta, lower_sub_geom_object_pt, s_lo);
256 Vector<double> parameters(1, s_lo[0]);
257 nod_pt->spine_pt()->set_geom_parameter(parameters);
260 nod_pt->spine_pt()->height() =
H;
264 Vector<GeomObject*> geom_object_pt(1);
265 geom_object_pt[0] = lower_sub_geom_object_pt;
268 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
271 if (j == 0) set_boundary_node_pt[0].insert(nod_pt);
279 n_prev_elements += nx1 * (nh + 1);
288 zeta, lower_transition_geom_object_pt, s_transition_lo);
290 zeta, upper_transition_geom_object_pt, s_transition_up);
293 lower_transition_geom_object_pt->position(s_transition_lo, r_wall_lo);
294 upper_transition_geom_object_pt->position(s_transition_up, r_wall_up);
298 spine_centre[0] = 0.5 * (r_wall_lo[0] + r_wall_up[0]);
311 double dzeta_el = d / double(nx2);
312 double dzeta_node = d / double(nx2 * (np - 1));
315 for (
unsigned i = 0; i < nx2; i++)
321 for (
unsigned j = 0; j < nh; j++)
324 unsigned e = n_prev_elements + i * (nh + 1) + j;
327 FiniteElement* el_pt = this->finite_element_pt(e);
330 for (
unsigned i0 = 0; i0 < np; i0++)
332 for (
unsigned i1 = 0; i1 < np; i1++)
335 unsigned n = i0 * np + i1;
338 SpineNode* nod_pt =
dynamic_cast<SpineNode*
>(el_pt->node_pt(n));
341 nod_pt->node_update_fct_id() = 1;
347 zeta[0] = zeta_lo + double(i1) * dzeta_node;
350 zeta, lower_sub_geom_object_pt, s_lo);
353 Vector<double> parameters(3);
354 parameters[0] = s_lo[0];
355 parameters[1] = s_transition_lo[0];
356 parameters[2] = s_transition_up[0];
357 nod_pt->spine_pt()->set_geom_parameter(parameters);
360 lower_sub_geom_object_pt->position(s_lo, r_wall_lo);
364 N[0] = spine_centre[0] - r_wall_lo[0];
365 N[1] = spine_centre[1] - r_wall_lo[1];
366 double length = sqrt(N[0] * N[0] + N[1] * N[1]);
367 nod_pt->spine_pt()->height() = length - radius;
371 Vector<GeomObject*> geom_object_pt(3);
372 geom_object_pt[0] = lower_sub_geom_object_pt;
373 geom_object_pt[1] = lower_transition_geom_object_pt;
374 geom_object_pt[2] = upper_transition_geom_object_pt;
377 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
380 if (j == 0) set_boundary_node_pt[0].insert(nod_pt);
388 n_prev_elements += nx2 * (nh + 1);
394 for (
unsigned i = 0; i < nhalf; i++)
397 for (
unsigned j = 0; j < nh; j++)
400 unsigned e = n_prev_elements + i * (nh + 1) + j;
403 FiniteElement* el_pt = this->finite_element_pt(e);
406 for (
unsigned i0 = 0; i0 < np; i0++)
408 for (
unsigned i1 = 0; i1 < np; i1++)
411 unsigned n = i0 * np + i1;
414 SpineNode* nod_pt =
dynamic_cast<SpineNode*
>(el_pt->node_pt(n));
417 nod_pt->node_update_fct_id() = 2;
427 zeta, lower_sub_geom_object_pt, s_lo);
429 zeta, upper_sub_geom_object_pt, s_up);
431 lower_sub_geom_object_pt->position(s_lo, r_wall_lo);
432 upper_sub_geom_object_pt->position(s_up, r_wall_up);
435 double vertical_fraction =
436 (double(i) + double(i1) / double(np - 1)) /
440 Vector<double> parameters(5);
441 parameters[0] = s_lo[0];
442 parameters[1] = s_up[0];
443 parameters[2] = vertical_fraction;
444 parameters[3] = s_transition_lo[0];
445 parameters[4] = s_transition_up[0];
446 nod_pt->spine_pt()->set_geom_parameter(parameters);
449 Vector<double> S0(2);
450 S0[0] = r_wall_lo[0] +
451 vertical_fraction * (r_wall_up[0] - r_wall_lo[0]);
452 S0[1] = r_wall_lo[1] +
453 vertical_fraction * (r_wall_up[1] - r_wall_lo[1]);
457 N[0] = spine_centre[0] - S0[0];
458 N[1] = spine_centre[1] - S0[1];
460 double length = sqrt(N[0] * N[0] + N[1] * N[1]);
461 nod_pt->spine_pt()->height() = length - radius;
464 Vector<GeomObject*> geom_object_pt(4);
465 geom_object_pt[0] = lower_sub_geom_object_pt;
466 geom_object_pt[1] = upper_sub_geom_object_pt;
467 geom_object_pt[2] = lower_transition_geom_object_pt;
468 geom_object_pt[3] = upper_transition_geom_object_pt;
471 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
474 if (j == 0) set_boundary_node_pt[1].insert(nod_pt);
482 n_prev_elements += nhalf * (nh + 1);
489 for (
unsigned i = 0; i < nhalf; i++)
492 for (
unsigned j = 0; j < nh; j++)
495 unsigned e = n_prev_elements + i * (nh + 1) + j;
498 FiniteElement* el_pt = this->finite_element_pt(e);
501 for (
unsigned i0 = 0; i0 < np; i0++)
503 for (
unsigned i1 = 0; i1 < np; i1++)
506 unsigned n = i0 * np + i1;
509 SpineNode* nod_pt =
dynamic_cast<SpineNode*
>(el_pt->node_pt(n));
512 nod_pt->node_update_fct_id() = 3;
522 zeta, lower_sub_geom_object_pt, s_lo);
524 zeta, upper_sub_geom_object_pt, s_up);
526 lower_sub_geom_object_pt->position(s_lo, r_wall_lo);
527 upper_sub_geom_object_pt->position(s_up, r_wall_up);
530 double vertical_fraction =
531 0.5 + (double(i) + double(i1) / double(np - 1)) /
535 Vector<double> parameters(5);
536 parameters[0] = s_lo[0];
537 parameters[1] = s_up[0];
538 parameters[2] = vertical_fraction;
539 parameters[3] = s_transition_lo[0];
540 parameters[4] = s_transition_up[0];
541 nod_pt->spine_pt()->set_geom_parameter(parameters);
544 Vector<double> S0(2);
545 S0[0] = r_wall_lo[0] +
546 vertical_fraction * (r_wall_up[0] - r_wall_lo[0]);
547 S0[1] = r_wall_lo[1] +
548 vertical_fraction * (r_wall_up[1] - r_wall_lo[1]);
552 N[0] = spine_centre[0] - S0[0];
553 N[1] = spine_centre[1] - S0[1];
555 double length = sqrt(N[0] * N[0] + N[1] * N[1]);
556 nod_pt->spine_pt()->height() = length - radius;
559 Vector<GeomObject*> geom_object_pt(4);
560 geom_object_pt[0] = lower_sub_geom_object_pt;
561 geom_object_pt[1] = upper_sub_geom_object_pt;
562 geom_object_pt[2] = lower_transition_geom_object_pt;
563 geom_object_pt[3] = upper_transition_geom_object_pt;
566 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
569 if (j == 0) set_boundary_node_pt[1].insert(nod_pt);
576 n_prev_elements += nhalf * (nh + 1);
584 double dzeta_el = d / double(nx2);
585 double dzeta_node = d / double(nx2 * (np - 1));
588 for (
unsigned i = 0; i < nx2; i++)
594 for (
unsigned j = 0; j < nh; j++)
597 unsigned e = n_prev_elements + i * (nh + 1) + j;
600 FiniteElement* el_pt = this->finite_element_pt(e);
603 for (
unsigned i0 = 0; i0 < np; i0++)
605 for (
unsigned i1 = 0; i1 < np; i1++)
608 unsigned n = i0 * np + i1;
611 SpineNode* nod_pt =
dynamic_cast<SpineNode*
>(el_pt->node_pt(n));
614 nod_pt->node_update_fct_id() = 4;
620 zeta[0] = zeta_lo - double(i1) * dzeta_node;
623 zeta, upper_sub_geom_object_pt, s_up);
626 Vector<double> parameters(3);
627 parameters[0] = s_up[0];
628 parameters[1] = s_transition_lo[0];
629 parameters[2] = s_transition_up[0];
630 nod_pt->spine_pt()->set_geom_parameter(parameters);
633 upper_sub_geom_object_pt->position(s_up, r_wall_up);
637 N[0] = spine_centre[0] - r_wall_up[0];
638 N[1] = spine_centre[1] - r_wall_up[1];
639 double length = sqrt(N[0] * N[0] + N[1] * N[1]);
640 nod_pt->spine_pt()->height() = length - radius;
644 Vector<GeomObject*> geom_object_pt(3);
645 geom_object_pt[0] = upper_sub_geom_object_pt;
646 geom_object_pt[1] = lower_transition_geom_object_pt;
647 geom_object_pt[2] = upper_transition_geom_object_pt;
650 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
653 if (j == 0) set_boundary_node_pt[2].insert(nod_pt);
661 n_prev_elements += nx2 * (nh + 1);
669 double dzeta_el = llayer / double(nx1);
670 double dzeta_node = llayer / double(nx1 * (np - 1));
673 for (
unsigned i = 0; i < nx1; i++)
679 for (
unsigned j = 0; j < nh; j++)
682 unsigned e = n_prev_elements + i * (nh + 1) + j;
685 FiniteElement* el_pt = this->finite_element_pt(e);
688 for (
unsigned i0 = 0; i0 < np; i0++)
690 for (
unsigned i1 = 0; i1 < np; i1++)
693 unsigned n = i0 * np + i1;
696 SpineNode* nod_pt =
dynamic_cast<SpineNode*
>(el_pt->node_pt(n));
699 nod_pt->node_update_fct_id() = 5;
705 zeta[0] = zeta_lo - double(i1) * dzeta_node;
708 zeta, upper_sub_geom_object_pt, s_up);
711 Vector<double> parameters(1, s_up[0]);
712 nod_pt->spine_pt()->set_geom_parameter(parameters);
715 nod_pt->spine_pt()->height() =
H;
719 Vector<GeomObject*> geom_object_pt(1);
720 geom_object_pt[0] = upper_sub_geom_object_pt;
723 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
726 if (j == 0) set_boundary_node_pt[2].insert(nod_pt);
735 this->remove_boundary_nodes();
736 this->set_nboundary(6);
739 for (
unsigned ibound = 0; ibound < 6; ibound++)
741 typedef std::set<Node*>::iterator IT;
742 for (IT it = set_boundary_node_pt[ibound].begin();
743 it != set_boundary_node_pt[ibound].end();
746 this->add_boundary_node(ibound, *it);
754 Vector<double> zeta(1);
755 unsigned n_boundary_node = this->nboundary_node(4);
756 for (
unsigned n = 0; n < n_boundary_node; ++n)
758 zeta[0] = this->boundary_node_pt(4, n)->x(0);
759 this->boundary_node_pt(4, n)->set_coordinates_on_boundary(4, zeta);
771 Nx3, 2 * nhalf, 1.0, 1.0, time_stepper_pt);
774 aux_mesh_pt->remove_boundary_nodes();
778 nnod = aux_mesh_pt->nnode();
779 std::set<Node*> aux_node_pt;
780 for (
unsigned i = 0; i < nnod; i++)
782 aux_node_pt.insert(aux_mesh_pt->node_pt(i));
789 unsigned first_bound_node = 0;
792 for (
unsigned e = 0; e < 2 * nhalf; e++)
794 FiniteElement* el_pt = aux_mesh_pt->finite_element_pt(e *
Nx3);
796 for (
unsigned i = 0; i < np; i++)
801 if ((e < 1) || (i > 0))
803 aux_node_pt.erase(el_pt->node_pt(n));
804 delete el_pt->node_pt(n);
807 el_pt->node_pt(n) = this->boundary_node_pt(1, first_bound_node + i);
811 first_bound_node += np - 1;
816 typedef std::set<Node*>::iterator IT;
817 for (IT it = aux_node_pt.begin(); it != aux_node_pt.end(); it++)
819 this->Node_pt.push_back(*it);
823 unsigned nelement_orig = this->Element_pt.size();
826 unsigned nelem = aux_mesh_pt->nelement();
827 for (
unsigned e = 0; e < nelem; e++)
829 this->Element_pt.push_back(aux_mesh_pt->element_pt(e));
836 this->remove_boundary_nodes(1);
845 Spine* new_spine_pt =
new Spine(1.0);
846 this->Spine_pt.push_back(new_spine_pt);
847 new_spine_pt->spine_height_pt()->pin(0);
850 SpineNode* nod_pt = this->element_node_pt(nelement_orig + 0, 0);
852 nod_pt->spine_pt() = new_spine_pt;
854 nod_pt->fraction() = 0.0;
856 nod_pt->spine_mesh_pt() =
this;
858 nod_pt->node_update_fct_id() = 6;
863 Lower_wall_pt->locate_zeta(zeta, lower_sub_geom_object_pt, s_lo);
864 Upper_wall_pt->locate_zeta(zeta, upper_sub_geom_object_pt, s_up);
866 lower_sub_geom_object_pt->position(s_lo, r_wall_lo);
867 upper_sub_geom_object_pt->position(s_up, r_wall_up);
870 Vector<double> parameters(2);
871 parameters[0] = s_lo[0];
872 parameters[1] = s_up[0];
873 new_spine_pt->set_geom_parameter(parameters);
877 Vector<GeomObject*> geom_object_pt(2);
878 geom_object_pt[0] = lower_sub_geom_object_pt;
879 geom_object_pt[1] = upper_sub_geom_object_pt;
882 new_spine_pt->set_geom_object_pt(geom_object_pt);
886 for (
unsigned long i = 0; i < 2 * nhalf; i++)
889 for (
unsigned l1 = 1; l1 < np; l1++)
893 this->element_node_pt(nelement_orig + i *
Nx3, l1 * np);
895 nod_pt->spine_pt() = new_spine_pt;
898 (double(i) + double(l1) / double(np - 1)) /
double(2 * nhalf);
900 nod_pt->spine_mesh_pt() =
this;
902 nod_pt->node_update_fct_id() = 6;
911 for (
unsigned long j = 0; j <
Nx3; j++)
915 for (
unsigned l2 = 1; l2 < np; l2++)
918 new_spine_pt =
new Spine(1.0);
919 this->Spine_pt.push_back(new_spine_pt);
920 new_spine_pt->spine_height_pt()->pin(0);
923 SpineNode* nod_pt = this->element_node_pt(nelement_orig + j, l2);
925 nod_pt->spine_pt() = new_spine_pt;
927 nod_pt->fraction() = 0.0;
929 nod_pt->spine_mesh_pt() =
this;
931 nod_pt->node_update_fct_id() = 6;
934 this->add_boundary_node(0, nod_pt);
935 if ((j ==
Nx3 - 1) && (l2 == np - 1))
937 this->add_boundary_node(1, nod_pt);
942 double dzeta_nod = dzeta_el / double(np - 1);
948 Lower_wall_pt->locate_zeta(zeta, lower_sub_geom_object_pt, s_lo);
949 Upper_wall_pt->locate_zeta(zeta, upper_sub_geom_object_pt, s_up);
951 lower_sub_geom_object_pt->position(s_lo, r_wall_lo);
952 upper_sub_geom_object_pt->position(s_up, r_wall_up);
955 Vector<double> parameters(2);
956 parameters[0] = s_lo[0];
957 parameters[1] = s_up[0];
958 new_spine_pt->set_geom_parameter(parameters);
962 Vector<GeomObject*> geom_object_pt(2);
963 geom_object_pt[0] = lower_sub_geom_object_pt;
964 geom_object_pt[1] = upper_sub_geom_object_pt;
967 new_spine_pt->set_geom_object_pt(geom_object_pt);
972 for (
unsigned long i = 0; i < 2 * nhalf; i++)
975 for (
unsigned l1 = 1; l1 < np; l1++)
979 this->element_node_pt(nelement_orig + i *
Nx3 + j, l1 * np + l2);
981 nod_pt->spine_pt() = new_spine_pt;
984 (double(i) + double(l1) / double(np - 1)) /
double(2 * nhalf);
986 nod_pt->spine_mesh_pt() =
this;
988 nod_pt->node_update_fct_id() = 6;
991 if ((j ==
Nx3 - 1) && (l2 == np - 1))
993 this->add_boundary_node(1, nod_pt);
997 if ((i == 2 * nhalf - 1) && (l1 == np - 1))
999 this->add_boundary_node(2, nod_pt);
1008 this->setup_boundary_element_info();
1012 aux_mesh_pt->flush_element_and_node_storage();
1026 template<
class ELEMENT,
class INTERFACE_ELEMENT>
1028 INTERFACE_ELEMENT>::initial_element_reorder()
1030 unsigned Nx = this->Nx;
1031 unsigned Ny = this->Ny;
1033 unsigned long Nelement = this->nelement();
1035 unsigned long Nfluid = Nx * Ny;
1037 Vector<FiniteElement*> dummy;
1040 for (
unsigned long j = 0; j < Nx; j++)
1043 for (
unsigned long i = 0; i < Ny; i++)
1046 dummy.push_back(this->finite_element_pt(Nx * i + j));
1050 dummy.push_back(this->finite_element_pt(Nfluid + j));
1054 for (
unsigned long e = 0; e < Nelement; e++)
1056 this->Element_pt[e] = dummy[e];
1064 template<
class ELEMENT,
class INTERFACE_ELEMENT>
1067 Vector<double>& initial_zeta,
1068 const Vector<double>& spine_base,
1069 const Vector<double>& spine_end)
1072 double lambda = 0.5;
1074 Vector<double> dx(2);
1075 Vector<double> new_free_x(2);
1076 DenseDoubleMatrix jacobian(2, 2, 0.0);
1077 Vector<double> spine_x(2);
1078 Vector<double> free_x(2);
1080 double maxres = 100.0;
1088 for (
unsigned i = 0; i < 2; ++i)
1090 spine_x[i] = spine_base[i] + lambda * (spine_end[i] - spine_base[i]);
1094 fs_geom_object_pt->position(initial_zeta, free_x);
1096 for (
unsigned i = 0; i < 2; ++i)
1098 dx[i] = spine_x[i] - free_x[i];
1102 jacobian(0, 0) = (spine_end[0] - spine_base[0]);
1103 jacobian(1, 0) = (spine_end[1] - spine_base[1]);
1106 double FD_Jstep = 1.0e-6;
1107 double old_zeta = initial_zeta[0];
1108 initial_zeta[0] += FD_Jstep;
1109 fs_geom_object_pt->position(initial_zeta, new_free_x);
1111 for (
unsigned i = 0; i < 2; ++i)
1113 jacobian(i, 1) = (free_x[i] - new_free_x[i]) / FD_Jstep;
1120 initial_zeta[0] = old_zeta - dx[1];
1124 for (
unsigned i = 0; i < 2; ++i)
1126 spine_x[i] = spine_base[i] + lambda * (spine_end[i] - spine_base[i]);
1128 fs_geom_object_pt->position(initial_zeta, free_x);
1130 for (
unsigned i = 0; i < 2; ++i)
1132 dx[i] = spine_x[i] - free_x[i];
1134 maxres = std::fabs(dx[0]) > std::fabs(dx[1]) ? std::fabs(dx[0]) :
1139 throw OomphLibError(
"Failed to converge after 100 steps",
1140 OOMPH_CURRENT_FUNCTION,
1141 OOMPH_EXCEPTION_LOCATION);
1144 }
while (maxres > 1.0e-8);
1147 oomph_info <<
"DONE " << initial_zeta[0] << std::endl;
1148 double spine_length = sqrt(pow((spine_base[0] - spine_end[0]), 2.0) +
1149 pow((spine_base[1] - spine_end[1]), 2.0));
1151 return (lambda * spine_length);
1157 template<
class ELEMENT,
class INTERFACE_ELEMENT>
1159 const double& zeta_lo_transition_start,
1160 const double& zeta_lo_transition_end,
1161 const double& zeta_up_transition_start,
1162 const double& zeta_up_transition_end)
1165 Mesh* fs_mesh_pt =
new Mesh;
1166 this->
template build_face_mesh<ELEMENT, FaceElementAsGeomObject>(
1171 unsigned n_face_element = fs_mesh_pt->nelement();
1173 for (
unsigned e = 0; e < n_face_element; e++)
1176 dynamic_cast<FaceElementAsGeomObject<ELEMENT>*
>(fs_mesh_pt->element_pt(e))
1177 ->set_boundary_number_in_bulk_mesh(4);
1183 MeshAsGeomObject* fs_geom_object_pt =
new MeshAsGeomObject(fs_mesh_pt);
1187 double llayer_lower = zeta_lo_transition_start - Zeta_start;
1188 double llayer_upper = zeta_up_transition_start - Zeta_start;
1191 double d_lower = zeta_lo_transition_end - zeta_lo_transition_start;
1192 double d_upper = zeta_up_transition_end - zeta_up_transition_start;
1195 Vector<double> r_wall_lo(2), r_wall_up(2);
1196 Vector<double> zeta(1), s_lo(1), s_up(1);
1197 GeomObject *lower_sub_geom_object_pt = 0, *upper_sub_geom_object_pt = 0;
1199 GeomObject* lower_transition_geom_object_pt = 0;
1200 GeomObject* upper_transition_geom_object_pt = 0;
1201 Vector<double> s_transition_lo(1), s_transition_up(1);
1202 Vector<double> spine_centre(2);
1205 unsigned np = this->finite_element_pt(0)->nnode_1d();
1212 zeta[0] = zeta_lo_transition_start;
1213 Lower_wall_pt->locate_zeta(
1214 zeta, lower_transition_geom_object_pt, s_transition_lo);
1216 zeta[0] = zeta_up_transition_start;
1217 Upper_wall_pt->locate_zeta(
1218 zeta, upper_transition_geom_object_pt, s_transition_up);
1221 lower_transition_geom_object_pt->position(s_transition_lo, r_wall_lo);
1222 upper_transition_geom_object_pt->position(s_transition_up, r_wall_up);
1226 spine_centre[0] = 0.5 * (r_wall_lo[0] + r_wall_up[0]);
1231 r_wall_lo[1] + spine_centre_fraction() * (r_wall_up[1] - r_wall_lo[1]);
1236 unsigned n_prev_elements = 0;
1239 Vector<double> spine_end(2);
1240 Vector<double> fs_zeta(1, 0.0);
1245 oomph_info <<
"LOWER FILM " << std::endl;
1247 double dzeta_el = llayer_lower / double(Nx1);
1248 double dzeta_node = llayer_lower / double(Nx1 * (np - 1));
1251 for (
unsigned i = 0; i < Nx1; i++)
1254 double zeta_lo = Zeta_start + double(i) * dzeta_el;
1257 unsigned e = n_prev_elements + i * (Nh + 1);
1260 FiniteElement* el_pt = this->finite_element_pt(e);
1263 for (
unsigned i1 = 0; i1 < (np - 1); i1++)
1266 SpineNode* nod_pt =
dynamic_cast<SpineNode*
>(el_pt->node_pt(i1));
1269 zeta[0] = zeta_lo + double(i1) * dzeta_node;
1271 nod_pt->set_coordinates_on_boundary(0, zeta);
1273 Lower_wall_pt->locate_zeta(zeta, lower_sub_geom_object_pt, s_lo);
1278 Vector<double> parameters(1, s_lo[0]);
1279 nod_pt->spine_pt()->set_geom_parameter(parameters);
1283 Vector<GeomObject*> geom_object_pt(1);
1284 geom_object_pt[0] = lower_sub_geom_object_pt;
1287 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
1290 lower_sub_geom_object_pt->position(s_lo, r_wall_lo);
1292 spine_end[0] = r_wall_lo[0];
1293 spine_end[1] = spine_centre[1];
1294 nod_pt->spine_pt()->height() = find_distance_to_free_surface(
1295 fs_geom_object_pt, fs_zeta, r_wall_lo, spine_end);
1300 n_prev_elements += Nx1 * (Nh + 1);
1307 oomph_info <<
"LOWER HORIZONTAL TRANSITION " << std::endl;
1309 double dzeta_el = d_lower / double(Nx2);
1310 double dzeta_node = d_lower / double(Nx2 * (np - 1));
1313 for (
unsigned i = 0; i < Nx2; i++)
1316 double zeta_lo = zeta_lo_transition_start + double(i) * dzeta_el;
1319 unsigned e = n_prev_elements + i * (Nh + 1);
1322 FiniteElement* el_pt = this->finite_element_pt(e);
1325 for (
unsigned i1 = 0; i1 < (np - 1); i1++)
1328 SpineNode* nod_pt =
dynamic_cast<SpineNode*
>(el_pt->node_pt(i1));
1331 zeta[0] = zeta_lo + double(i1) * dzeta_node;
1333 nod_pt->set_coordinates_on_boundary(0, zeta);
1335 Lower_wall_pt->locate_zeta(zeta, lower_sub_geom_object_pt, s_lo);
1338 Vector<double> parameters(3);
1339 parameters[0] = s_lo[0];
1340 parameters[1] = s_transition_lo[0];
1341 parameters[2] = s_transition_up[0];
1342 nod_pt->spine_pt()->set_geom_parameter(parameters);
1346 Vector<GeomObject*> geom_object_pt(3);
1347 geom_object_pt[0] = lower_sub_geom_object_pt;
1348 geom_object_pt[1] = lower_transition_geom_object_pt;
1349 geom_object_pt[2] = upper_transition_geom_object_pt;
1352 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
1355 lower_sub_geom_object_pt->position(s_lo, r_wall_lo);
1357 nod_pt->spine_pt()->height() = find_distance_to_free_surface(
1358 fs_geom_object_pt, fs_zeta, r_wall_lo, spine_centre);
1363 n_prev_elements += Nx2 * (Nh + 1);
1369 oomph_info <<
"LOWER VERTICAL TRANSITION " << std::endl;
1370 for (
unsigned i = 0; i < Nhalf; i++)
1373 unsigned e = n_prev_elements + i * (Nh + 1);
1376 FiniteElement* el_pt = this->finite_element_pt(e);
1379 for (
unsigned i1 = 0; i1 < (np - 1); i1++)
1385 SpineNode* nod_pt =
dynamic_cast<SpineNode*
>(el_pt->node_pt(np + i1));
1388 zeta[0] = zeta_lo_transition_end;
1390 Lower_wall_pt->locate_zeta(zeta, lower_sub_geom_object_pt, s_lo);
1391 zeta[0] = zeta_up_transition_end;
1392 Upper_wall_pt->locate_zeta(zeta, upper_sub_geom_object_pt, s_up);
1394 lower_sub_geom_object_pt->position(s_lo, r_wall_lo);
1395 upper_sub_geom_object_pt->position(s_up, r_wall_up);
1398 double vertical_fraction =
1399 (double(i) + double(i1) / double(np - 1)) /
double(2.0 * Nhalf);
1402 Vector<double> parameters(5);
1403 parameters[0] = s_lo[0];
1404 parameters[1] = s_up[0];
1405 parameters[2] = vertical_fraction;
1406 parameters[3] = s_transition_lo[0];
1407 parameters[4] = s_transition_up[0];
1408 nod_pt->spine_pt()->set_geom_parameter(parameters);
1411 Vector<double> S0(2);
1413 r_wall_lo[0] + vertical_fraction * (r_wall_up[0] - r_wall_lo[0]);
1415 r_wall_lo[1] + vertical_fraction * (r_wall_up[1] - r_wall_lo[1]);
1418 Vector<GeomObject*> geom_object_pt(4);
1419 geom_object_pt[0] = lower_sub_geom_object_pt;
1420 geom_object_pt[1] = upper_sub_geom_object_pt;
1421 geom_object_pt[2] = lower_transition_geom_object_pt;
1422 geom_object_pt[3] = upper_transition_geom_object_pt;
1425 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
1428 nod_pt->spine_pt()->height() = find_distance_to_free_surface(
1429 fs_geom_object_pt, fs_zeta, S0, spine_centre);
1434 n_prev_elements += Nhalf * (Nh + 1);
1441 oomph_info <<
"UPPER VERTICAL TRANSITION" << std::endl;
1442 for (
unsigned i = 0; i < Nhalf; i++)
1445 unsigned e = n_prev_elements + i * (Nh + 1);
1448 FiniteElement* el_pt = this->finite_element_pt(e);
1451 for (
unsigned i1 = 0; i1 < (np - 1); i1++)
1457 SpineNode* nod_pt =
dynamic_cast<SpineNode*
>(el_pt->node_pt(np + i1));
1460 zeta[0] = zeta_lo_transition_end;
1462 Lower_wall_pt->locate_zeta(zeta, lower_sub_geom_object_pt, s_lo);
1463 zeta[0] = zeta_up_transition_end;
1464 Upper_wall_pt->locate_zeta(zeta, upper_sub_geom_object_pt, s_up);
1466 lower_sub_geom_object_pt->position(s_lo, r_wall_lo);
1467 upper_sub_geom_object_pt->position(s_up, r_wall_up);
1471 double vertical_fraction =
1473 (double(i) + double(i1) / double(np - 1)) /
double(2.0 * Nhalf);
1476 Vector<double> parameters(5);
1477 parameters[0] = s_lo[0];
1478 parameters[1] = s_up[0];
1479 parameters[2] = vertical_fraction;
1480 parameters[3] = s_transition_lo[0];
1481 parameters[4] = s_transition_up[0];
1482 nod_pt->spine_pt()->set_geom_parameter(parameters);
1485 Vector<double> S0(2);
1487 r_wall_lo[0] + vertical_fraction * (r_wall_up[0] - r_wall_lo[0]);
1489 r_wall_lo[1] + vertical_fraction * (r_wall_up[1] - r_wall_lo[1]);
1492 Vector<GeomObject*> geom_object_pt(4);
1493 geom_object_pt[0] = lower_sub_geom_object_pt;
1494 geom_object_pt[1] = upper_sub_geom_object_pt;
1495 geom_object_pt[2] = lower_transition_geom_object_pt;
1496 geom_object_pt[3] = upper_transition_geom_object_pt;
1499 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
1502 nod_pt->spine_pt()->height() = find_distance_to_free_surface(
1503 fs_geom_object_pt, fs_zeta, S0, spine_centre);
1508 n_prev_elements += Nhalf * (Nh + 1);
1515 oomph_info <<
"UPPER HORIZONTAL TRANSITION " << std::endl;
1517 double dzeta_el = d_upper / double(Nx2);
1518 double dzeta_node = d_upper / double(Nx2 * (np - 1));
1521 for (
unsigned i = 0; i < Nx2; i++)
1524 double zeta_lo = zeta_up_transition_end - double(i) * dzeta_el;
1527 unsigned e = n_prev_elements + i * (Nh + 1);
1530 FiniteElement* el_pt = this->finite_element_pt(e);
1533 for (
unsigned i1 = 0; i1 < (np - 1); i1++)
1536 SpineNode* nod_pt =
dynamic_cast<SpineNode*
>(el_pt->node_pt(np + i1));
1539 zeta[0] = zeta_lo - double(i1) * dzeta_node;
1541 el_pt->node_pt(i1)->set_coordinates_on_boundary(2, zeta);
1543 Upper_wall_pt->locate_zeta(zeta, upper_sub_geom_object_pt, s_up);
1546 Vector<double> parameters(3);
1547 parameters[0] = s_up[0];
1548 parameters[1] = s_transition_lo[0];
1549 parameters[2] = s_transition_up[0];
1550 nod_pt->spine_pt()->set_geom_parameter(parameters);
1554 Vector<GeomObject*> geom_object_pt(3);
1555 geom_object_pt[0] = upper_sub_geom_object_pt;
1556 geom_object_pt[1] = lower_transition_geom_object_pt;
1557 geom_object_pt[2] = upper_transition_geom_object_pt;
1560 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
1564 upper_sub_geom_object_pt->position(s_up, r_wall_up);
1566 nod_pt->spine_pt()->height() = find_distance_to_free_surface(
1567 fs_geom_object_pt, fs_zeta, r_wall_up, spine_centre);
1572 n_prev_elements += Nx2 * (Nh + 1);
1579 oomph_info <<
"UPPER THIN FILM" << std::endl;
1581 double dzeta_el = llayer_upper / double(Nx1);
1582 double dzeta_node = llayer_upper / double(Nx1 * (np - 1));
1585 for (
unsigned i = 0; i < Nx1; i++)
1588 double zeta_lo = zeta_up_transition_start - double(i) * dzeta_el;
1591 unsigned e = n_prev_elements + i * (Nh + 1);
1594 FiniteElement* el_pt = this->finite_element_pt(e);
1597 for (
unsigned i1 = 0; i1 < (np - 1); i1++)
1600 SpineNode* nod_pt =
dynamic_cast<SpineNode*
>(el_pt->node_pt(i1));
1603 zeta[0] = zeta_lo - double(i1) * dzeta_node;
1605 nod_pt->set_coordinates_on_boundary(2, zeta);
1607 Upper_wall_pt->locate_zeta(zeta, upper_sub_geom_object_pt, s_up);
1610 Vector<double> parameters(1, s_up[0]);
1611 nod_pt->spine_pt()->set_geom_parameter(parameters);
1615 Vector<GeomObject*> geom_object_pt(1);
1616 geom_object_pt[0] = upper_sub_geom_object_pt;
1619 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
1622 upper_sub_geom_object_pt->position(s_up, r_wall_up);
1623 spine_end[0] = r_wall_up[0];
1624 spine_end[1] = spine_centre[1];
1626 nod_pt->spine_pt()->height() = find_distance_to_free_surface(
1627 fs_geom_object_pt, fs_zeta, r_wall_up, spine_end);
1633 n_prev_elements += Nx1 * (Nh + 1);
1639 unsigned e = n_prev_elements;
1642 SpineNode* nod_pt = this->element_node_pt(e, 0);
1645 zeta[0] = zeta_lo_transition_end;
1647 Lower_wall_pt->locate_zeta(zeta, lower_sub_geom_object_pt, s_lo);
1648 zeta[0] = zeta_up_transition_end;
1649 Upper_wall_pt->locate_zeta(zeta, upper_sub_geom_object_pt, s_up);
1651 lower_sub_geom_object_pt->position(s_lo, r_wall_lo);
1652 upper_sub_geom_object_pt->position(s_up, r_wall_up);
1655 Vector<double> parameters(2);
1656 parameters[0] = s_lo[0];
1657 parameters[1] = s_up[0];
1658 nod_pt->spine_pt()->set_geom_parameter(parameters);
1662 Vector<GeomObject*> geom_object_pt(2);
1663 geom_object_pt[0] = lower_sub_geom_object_pt;
1664 geom_object_pt[1] = upper_sub_geom_object_pt;
1667 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
1673 for (
unsigned long j = 0; j < Nx3; j++)
1675 unsigned e = n_prev_elements + j;
1679 for (
unsigned l2 = 0; l2 < np; l2++)
1682 SpineNode* nod_pt = this->element_node_pt(e, l2);
1685 double dzeta_el_lower =
1686 (Zeta_end - zeta_lo_transition_end) /
double(Nx3);
1687 double dzeta_nod_lower = dzeta_el_lower / double(np - 1);
1689 double dzeta_el_upper =
1690 (Zeta_end - zeta_up_transition_end) /
double(Nx3);
1691 double dzeta_nod_upper = dzeta_el_upper / double(np - 1);
1695 zeta_lo_transition_end + j * dzeta_el_lower + l2 * dzeta_nod_lower;
1697 nod_pt->set_coordinates_on_boundary(0, zeta);
1700 Lower_wall_pt->locate_zeta(zeta, lower_sub_geom_object_pt, s_lo);
1703 zeta_up_transition_end + j * dzeta_el_upper + l2 * dzeta_nod_upper;
1705 this->element_node_pt(e + Nx3 * (2 * Nhalf - 1), np * (np - 1) + l2)
1706 ->set_coordinates_on_boundary(2, zeta);
1707 Upper_wall_pt->locate_zeta(zeta, upper_sub_geom_object_pt, s_up);
1709 lower_sub_geom_object_pt->position(s_lo, r_wall_lo);
1710 upper_sub_geom_object_pt->position(s_up, r_wall_up);
1713 Vector<double> parameters(2);
1714 parameters[0] = s_lo[0];
1715 parameters[1] = s_up[0];
1716 nod_pt->spine_pt()->set_geom_parameter(parameters);
1720 Vector<GeomObject*> geom_object_pt(2);
1721 geom_object_pt[0] = lower_sub_geom_object_pt;
1722 geom_object_pt[1] = upper_sub_geom_object_pt;
1725 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
1733 delete fs_geom_object_pt;
1736 for (
unsigned e = n_face_element; e > 0; e--)
1738 delete fs_mesh_pt->element_pt(e - 1);
1739 fs_mesh_pt->element_pt(e - 1) = 0;
1742 fs_mesh_pt->flush_element_and_node_storage();
Mesh for 2D Bretherton problem – based on single layer mesh. Templated by spine-ified Navier-Stokes e...
GeomObject * Lower_wall_pt
Pointer to geometric object that represents the lower wall.
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.
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_start
Start coordinate on wall.
double Zeta_transition_end
Wall coordinate of end of transition region.
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.
unsigned Nx3
Number of elements along wall in channel region.
double H
Thickness of deposited film.
void initial_element_reorder()
Initial reordering elements of the elements – before the channel mesh is added. Vertical stacks of el...
double spine_centre_fraction() const
Read the value of the spine centre's vertical fraction.
Vector< FiniteElement * > Interface_element_pt
Vector of pointers to interface elements.
ELEMENT * Control_element_pt
Pointer to control element (just under the symmetry line near the bubble tip; the bubble tip is locat...
double Zeta_end
Wall coordinate of end of liquid filled region (inflow)
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.
double Zeta_transition_start
Wall coordinate of start of the transition region.
Simple rectangular 2D Quad mesh class. Nx : number of elements in the x direction.
Single-layer spine mesh class derived from standard 2D mesh. The mesh contains a layer of spinified f...
////////////////////////////////////////////////////////////////////// //////////////////////////////...