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,
67 const double& zeta_start,
68 const double& zeta_transition_start,
69 const double& zeta_transition_end,
70 const double& zeta_end,
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)
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);
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;
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=================================================== "
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(
162 this->
Element_pt.push_back(interface_element_element_pt);
178 this->
element_pt((nx1 + nx2 + nhalf) * (nh + 1) - 2));
184 for (
unsigned ibound = 1; ibound <= 3; ibound++)
187 for (
unsigned j = 0; j < numnod; j++)
189 set_boundary_node_pt[ibound + 2].insert(
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;
230 for (
unsigned i0 = 0; i0 < np; i0++)
232 for (
unsigned i1 = 0; i1 < np; i1++)
235 unsigned n = i0 * np + i1;
248 zeta[0] = zeta_lo + double(i1) * dzeta_node;
251 zeta, lower_sub_geom_object_pt, s_lo);
265 geom_object_pt[0] = lower_sub_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;
330 for (
unsigned i0 = 0; i0 < np; i0++)
332 for (
unsigned i1 = 0; i1 < np; i1++)
335 unsigned n = i0 * np + i1;
347 zeta[0] = zeta_lo + double(i1) * dzeta_node;
350 zeta, lower_sub_geom_object_pt, s_lo);
354 parameters[0] = s_lo[0];
355 parameters[1] = s_transition_lo[0];
356 parameters[2] = s_transition_up[0];
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]);
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;
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;
406 for (
unsigned i0 = 0; i0 < np; i0++)
408 for (
unsigned i1 = 0; i1 < np; i1++)
411 unsigned n = i0 * np + i1;
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)) /
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];
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]);
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;
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;
501 for (
unsigned i0 = 0; i0 < np; i0++)
503 for (
unsigned i1 = 0; i1 < np; i1++)
506 unsigned n = i0 * np + i1;
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)) /
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];
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]);
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;
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;
603 for (
unsigned i0 = 0; i0 < np; i0++)
605 for (
unsigned i1 = 0; i1 < np; i1++)
608 unsigned n = i0 * np + i1;
620 zeta[0] = zeta_lo - double(i1) * dzeta_node;
623 zeta, upper_sub_geom_object_pt, s_up);
627 parameters[0] = s_up[0];
628 parameters[1] = s_transition_lo[0];
629 parameters[2] = s_transition_up[0];
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]);
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;
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;
688 for (
unsigned i0 = 0; i0 < np; i0++)
690 for (
unsigned i1 = 0; i1 < np; i1++)
693 unsigned n = i0 * np + i1;
705 zeta[0] = zeta_lo - double(i1) * dzeta_node;
708 zeta, upper_sub_geom_object_pt, s_up);
720 geom_object_pt[0] = upper_sub_geom_object_pt;
726 if (j == 0) set_boundary_node_pt[2].insert(nod_pt);
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();
756 for (
unsigned n = 0; n < n_boundary_node; ++n)
771 Nx3, 2 * nhalf, 1.0, 1.0, time_stepper_pt);
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++)
796 for (
unsigned i = 0;
i < np;
i++)
801 if ((
e < 1) || (
i > 0))
803 aux_node_pt.erase(el_pt->
node_pt(n));
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++)
823 unsigned nelement_orig = this->
Element_pt.size();
826 unsigned nelem = aux_mesh_pt->
nelement();
827 for (
unsigned e = 0;
e < nelem;
e++)
846 this->
Spine_pt.push_back(new_spine_pt);
866 lower_sub_geom_object_pt->
position(s_lo, r_wall_lo);
867 upper_sub_geom_object_pt->position(s_up, r_wall_up);
871 parameters[0] = s_lo[0];
872 parameters[1] = s_up[0];
878 geom_object_pt[0] = lower_sub_geom_object_pt;
879 geom_object_pt[1] = upper_sub_geom_object_pt;
886 for (
unsigned long i = 0;
i < 2 * nhalf;
i++)
889 for (
unsigned l1 = 1; l1 < np; l1++)
898 (double(
i) + double(l1) / double(np - 1)) /
double(2 * nhalf);
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);
935 if ((j ==
Nx3 - 1) && (l2 == np - 1))
942 double dzeta_nod = dzeta_el / double(np - 1);
951 lower_sub_geom_object_pt->
position(s_lo, r_wall_lo);
952 upper_sub_geom_object_pt->position(s_up, r_wall_up);
956 parameters[0] = s_lo[0];
957 parameters[1] = s_up[0];
963 geom_object_pt[0] = lower_sub_geom_object_pt;
964 geom_object_pt[1] = upper_sub_geom_object_pt;
972 for (
unsigned long i = 0;
i < 2 * nhalf;
i++)
975 for (
unsigned l1 = 1; l1 < np; l1++)
984 (double(
i) + double(l1) / double(np - 1)) /
double(2 * nhalf);
991 if ((j ==
Nx3 - 1) && (l2 == np - 1))
997 if ((
i == 2 * nhalf - 1) && (l1 == np - 1))
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;
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>
1072 double lambda = 0.5;
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]) :
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)
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++)
1177 ->set_boundary_number_in_bulk_mesh(4);
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;
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;
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;
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);
1263 for (
unsigned i1 = 0; i1 < (np - 1); i1++)
1269 zeta[0] = zeta_lo + double(i1) * dzeta_node;
1273 Lower_wall_pt->locate_zeta(zeta, lower_sub_geom_object_pt, s_lo);
1284 geom_object_pt[0] = lower_sub_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];
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);
1325 for (
unsigned i1 = 0; i1 < (np - 1); i1++)
1331 zeta[0] = zeta_lo + double(i1) * dzeta_node;
1335 Lower_wall_pt->locate_zeta(zeta, lower_sub_geom_object_pt, s_lo);
1339 parameters[0] = s_lo[0];
1340 parameters[1] = s_transition_lo[0];
1341 parameters[2] = s_transition_up[0];
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;
1355 lower_sub_geom_object_pt->
position(s_lo, r_wall_lo);
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);
1379 for (
unsigned i1 = 0; i1 < (np - 1); 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);
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];
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]);
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;
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);
1451 for (
unsigned i1 = 0; i1 < (np - 1); 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);
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];
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]);
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;
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);
1533 for (
unsigned i1 = 0; i1 < (np - 1); i1++)
1539 zeta[0] = zeta_lo - double(i1) * dzeta_node;
1543 Upper_wall_pt->locate_zeta(zeta, upper_sub_geom_object_pt, s_up);
1547 parameters[0] = s_up[0];
1548 parameters[1] = s_transition_lo[0];
1549 parameters[2] = s_transition_up[0];
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;
1564 upper_sub_geom_object_pt->position(s_up, r_wall_up);
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);
1597 for (
unsigned i1 = 0; i1 < (np - 1); i1++)
1603 zeta[0] = zeta_lo - double(i1) * dzeta_node;
1607 Upper_wall_pt->locate_zeta(zeta, upper_sub_geom_object_pt, s_up);
1616 geom_object_pt[0] = upper_sub_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];
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);
1656 parameters[0] = s_lo[0];
1657 parameters[1] = s_up[0];
1663 geom_object_pt[0] = lower_sub_geom_object_pt;
1664 geom_object_pt[1] = upper_sub_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;
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);
1714 parameters[0] = s_lo[0];
1715 parameters[1] = s_up[0];
1721 geom_object_pt[0] = lower_sub_geom_object_pt;
1722 geom_object_pt[1] = upper_sub_geom_object_pt;
1733 delete fs_geom_object_pt;
1736 for (
unsigned e = n_face_element;
e > 0;
e--)
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.
void pin(const unsigned &i)
Pin the i-th stored variable.
Class of matrices containing doubles, and stored as a DenseMatrix<double>, but with solving functiona...
void solve(DoubleVector &rhs)
Complete LU solve (replaces matrix by its LU decomposition and overwrites RHS with solution)....
Class that is used to create FaceElement from bulk elements and to provide these FaceElement with a g...
A general Finite Element class.
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
unsigned nnode() const
Return the number of nodes.
virtual unsigned nnode_1d() const
Return the number of nodes along one edge of the element Default is to return zero — must be overload...
/////////////////////////////////////////////////////////////////////
virtual void position(const Vector< double > &zeta, Vector< double > &r) const =0
Parametrised position on object at current time: r(zeta).
virtual void locate_zeta(const Vector< double > &zeta, GeomObject *&sub_geom_object_pt, Vector< double > &s, const bool &use_coordinate_as_initial_guess=false)
A geometric object may be composed of may sub-objects (e.g. a finite-element representation of a boun...
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
void add_boundary_node(const unsigned &b, Node *const &node_pt)
Add a (pointer to) a node to the b-th boundary.
unsigned long nboundary_node(const unsigned &ibound) const
Return number of nodes on a particular boundary.
Vector< Node * > Node_pt
Vector of pointers to nodes.
void flush_element_and_node_storage()
Flush storage for elements and nodes by emptying the vectors that store the pointers to them....
FiniteElement * finite_element_pt(const unsigned &e) const
Upcast (downcast?) to FiniteElement (needed to access FiniteElement member functions).
void set_nboundary(const unsigned &nbound)
Set the number of boundaries in the mesh.
virtual void setup_boundary_element_info()
Interface for function that is used to setup the boundary information (Empty virtual function – imple...
GeneralisedElement *& element_pt(const unsigned long &e)
Return pointer to element e.
void remove_boundary_nodes()
Clear all pointers to boundary nodes.
unsigned long nnode() const
Return number of nodes in the mesh.
const Vector< GeneralisedElement * > & element_pt() const
Return reference to the Vector of elements.
Node *& node_pt(const unsigned long &n)
Return pointer to global node n.
Node *& boundary_node_pt(const unsigned &b, const unsigned &n)
Return pointer to node n on boundary b.
Vector< GeneralisedElement * > Element_pt
Vector of pointers to generalised elements.
unsigned long nelement() const
Return number of elements in the mesh.
double & x(const unsigned &i)
Return the i-th nodal coordinate.
virtual void set_coordinates_on_boundary(const unsigned &b, const unsigned &k, const Vector< double > &boundary_zeta)
Set the vector of the k-th generalised boundary coordinates on mesh boundary b. Broken virtual interf...
An OomphLibError object which should be thrown when an run-time error is encountered....
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...
Vector< Spine * > Spine_pt
A Spine mesh contains a Vector of pointers to spines.
SpineNode * element_node_pt(const unsigned long &e, const unsigned &n)
Return the n-th local SpineNode in element e. This is required to cast the nodes in a spine mesh to b...
Class for nodes that live on spines. The assumption is that each Node lies at a fixed fraction on a s...
SpineMesh *& spine_mesh_pt()
Access function to Pointer to SpineMesh that this node is a part of and which implements the node upd...
Spine *& spine_pt()
Access function to spine.
unsigned & node_update_fct_id()
Access function to ID of node update function (within specific mesh)
double & fraction()
Set reference to fraction along spine.
Spines are used for algebraic node update operations in free-surface fluid problems: They form the ba...
void set_geom_object_pt(const Vector< GeomObject * > &geom_object_pt)
Set vector of (pointers to) geometric objects that is involved in the node update operations for this...
void set_geom_parameter(const Vector< double > &geom_parameter)
Set vector of geometric parameters that are involved in the node update operations for this Spine....
double & height()
Access function to spine height.
Data *& spine_height_pt()
Access function to Data object that stores the spine height.
////////////////////////////////////////////////////////////////////// //////////////////////////////...
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
OomphInfo oomph_info
Single (global) instantiation of the OomphInfo object – this is used throughout the library as a "rep...