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);
780 for (
unsigned i = 0;
i <
nnod;
i++)
792 for (
unsigned e = 0;
e < 2 *
nhalf;
e++)
796 for (
unsigned i = 0;
i <
np;
i++)
801 if ((
e < 1) || (
i > 0))
816 typedef std::set<Node*>::iterator
IT;
827 for (
unsigned e = 0;
e <
nelem;
e++)
856 nod_pt->spine_mesh_pt() =
this;
858 nod_pt->node_update_fct_id() = 6;
886 for (
unsigned long i = 0;
i < 2 *
nhalf;
i++)
889 for (
unsigned l1 = 1;
l1 <
np;
l1++)
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++)
929 nod_pt->spine_mesh_pt() =
this;
931 nod_pt->node_update_fct_id() = 6;
935 if ((
j ==
Nx3 - 1) && (
l2 ==
np - 1))
972 for (
unsigned long i = 0;
i < 2 *
nhalf;
i++)
975 for (
unsigned l1 = 1;
l1 <
np;
l1++)
986 nod_pt->spine_mesh_pt() =
this;
988 nod_pt->node_update_fct_id() = 6;
991 if ((
j ==
Nx3 - 1) && (
l2 ==
np - 1))
1008 this->setup_boundary_element_info();