65 const unsigned& nhalf,
67 GeomObject* lower_wall_pt,
68 GeomObject* upper_wall_pt,
69 const double& zeta_start,
70 const double& zeta_transition_start,
71 const double& zeta_transition_end,
72 const double& zeta_end,
73 TimeStepper* time_stepper_pt)
75 2 * (nx1 + nx2 + nhalf), nh, 1.0, h, time_stepper_pt),
82 Upper_wall_pt(upper_wall_pt),
83 Lower_wall_pt(lower_wall_pt),
84 Zeta_start(zeta_start),
86 Zeta_transition_start(zeta_transition_start),
87 Zeta_transition_end(zeta_transition_end),
88 Spine_centre_fraction_pt(&Default_spine_centre_fraction),
89 Default_spine_centre_fraction(0.5)
92 unsigned n_bulk = this->nelement();
94 for (
unsigned e = 0; e < n_bulk; e++)
100 MeshChecker::assert_geometric_element<QElementGeometricBase, ELEMENT>(2);
103 MeshChecker::assert_geometric_element<SpineFiniteElement, ELEMENT>(2);
115 Vector<double> r_wall_lo(2), r_wall_up(2);
116 Vector<double> zeta(1), s_lo(1), s_up(1);
117 GeomObject *lower_sub_geom_object_pt = 0, *upper_sub_geom_object_pt = 0;
119 GeomObject* lower_transition_geom_object_pt = 0;
120 GeomObject* upper_transition_geom_object_pt = 0;
121 Vector<double> s_transition_lo(1), s_transition_up(1);
122 Vector<double> spine_centre(2);
130 double radius = -r_wall_lo[1] -
H;
133 if (std::fabs(r_wall_lo[1] + r_wall_up[1]) > 1.0e-4)
135 oomph_info <<
"\n\n=================================================== "
137 oomph_info <<
"Warning: " << std::endl;
138 oomph_info <<
"-------- " << std::endl;
139 oomph_info <<
" " << std::endl;
140 oomph_info <<
"Upper and lower walls are not symmetric at zeta=0"
142 oomph_info <<
"Your initial mesh will look very odd." << std::endl;
143 oomph_info <<
"y-coordinates of walls at zeta=0 are: " << r_wall_lo[1]
144 <<
" and " << r_wall_up[1] << std::endl
146 oomph_info <<
"===================================================\n\n "
153 unsigned n_x = 2 * (nx1 + nx2 + nhalf);
155 for (
unsigned i = 0; i < n_x; i++)
159 FiniteElement* interface_element_element_pt =
new INTERFACE_ELEMENT(
160 this->finite_element_pt(n_x * (n_y - 1) + i), 2);
163 this->Element_pt.push_back(interface_element_element_pt);
179 this->element_pt((nx1 + nx2 + nhalf) * (nh + 1) - 2));
182 Vector<std::set<Node*>> set_boundary_node_pt(6);
185 for (
unsigned ibound = 1; ibound <= 3; ibound++)
187 unsigned numnod = this->nboundary_node(ibound);
188 for (
unsigned j = 0; j < numnod; j++)
190 set_boundary_node_pt[ibound + 2].insert(
191 this->boundary_node_pt(ibound, j));
196 unsigned nnod = this->finite_element_pt(0)->nnode();
199 unsigned np = this->finite_element_pt(0)->nnode_1d();
202 unsigned n_prev_elements = 0;
212 double dzeta_el = llayer / double(nx1);
213 double dzeta_node = llayer / double(nx1 * (np - 1));
216 for (
unsigned i = 0; i < nx1; i++)
219 double zeta_lo =
Zeta_start + double(i) * dzeta_el;
222 for (
unsigned j = 0; j < nh; j++)
225 unsigned e = n_prev_elements + i * (nh + 1) + j;
228 FiniteElement* el_pt = this->finite_element_pt(e);
231 for (
unsigned i0 = 0; i0 < np; i0++)
233 for (
unsigned i1 = 0; i1 < np; i1++)
236 unsigned n = i0 * np + i1;
239 SpineNode* nod_pt =
dynamic_cast<SpineNode*
>(el_pt->node_pt(n));
242 nod_pt->node_update_fct_id() = 0;
249 zeta[0] = zeta_lo + double(i1) * dzeta_node;
252 zeta, lower_sub_geom_object_pt, s_lo);
257 Vector<double> parameters(1, s_lo[0]);
258 nod_pt->spine_pt()->set_geom_parameter(parameters);
261 nod_pt->spine_pt()->height() =
H;
265 Vector<GeomObject*> geom_object_pt(1);
266 geom_object_pt[0] = lower_sub_geom_object_pt;
269 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
272 if (j == 0) set_boundary_node_pt[0].insert(nod_pt);
280 n_prev_elements += nx1 * (nh + 1);
289 zeta, lower_transition_geom_object_pt, s_transition_lo);
291 zeta, upper_transition_geom_object_pt, s_transition_up);
294 lower_transition_geom_object_pt->position(s_transition_lo, r_wall_lo);
295 upper_transition_geom_object_pt->position(s_transition_up, r_wall_up);
299 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);
488 for (
unsigned i = 0; i < nhalf; i++)
491 for (
unsigned j = 0; j < nh; j++)
494 unsigned e = n_prev_elements + i * (nh + 1) + j;
497 FiniteElement* el_pt = this->finite_element_pt(e);
500 for (
unsigned i0 = 0; i0 < np; i0++)
502 for (
unsigned i1 = 0; i1 < np; i1++)
505 unsigned n = i0 * np + i1;
508 SpineNode* nod_pt =
dynamic_cast<SpineNode*
>(el_pt->node_pt(n));
511 nod_pt->node_update_fct_id() = 3;
521 zeta, lower_sub_geom_object_pt, s_lo);
523 zeta, upper_sub_geom_object_pt, s_up);
525 lower_sub_geom_object_pt->position(s_lo, r_wall_lo);
526 upper_sub_geom_object_pt->position(s_up, r_wall_up);
529 double vertical_fraction =
530 0.5 + (double(i) + double(i1) / double(np - 1)) /
534 Vector<double> parameters(5);
535 parameters[0] = s_lo[0];
536 parameters[1] = s_up[0];
537 parameters[2] = vertical_fraction;
538 parameters[3] = s_transition_lo[0];
539 parameters[4] = s_transition_up[0];
540 nod_pt->spine_pt()->set_geom_parameter(parameters);
543 Vector<double> S0(2);
544 S0[0] = r_wall_lo[0] +
545 vertical_fraction * (r_wall_up[0] - r_wall_lo[0]);
546 S0[1] = r_wall_lo[1] +
547 vertical_fraction * (r_wall_up[1] - r_wall_lo[1]);
551 N[0] = spine_centre[0] - S0[0];
552 N[1] = spine_centre[1] - S0[1];
554 double length = sqrt(N[0] * N[0] + N[1] * N[1]);
555 nod_pt->spine_pt()->height() = length - radius;
558 Vector<GeomObject*> geom_object_pt(4);
559 geom_object_pt[0] = lower_sub_geom_object_pt;
560 geom_object_pt[1] = upper_sub_geom_object_pt;
561 geom_object_pt[2] = lower_transition_geom_object_pt;
562 geom_object_pt[3] = upper_transition_geom_object_pt;
565 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
568 if (j == 0) set_boundary_node_pt[1].insert(nod_pt);
575 n_prev_elements += nhalf * (nh + 1);
582 double dzeta_el = d / double(nx2);
583 double dzeta_node = d / double(nx2 * (np - 1));
586 for (
unsigned i = 0; i < nx2; i++)
592 for (
unsigned j = 0; j < nh; j++)
595 unsigned e = n_prev_elements + i * (nh + 1) + j;
598 FiniteElement* el_pt = this->finite_element_pt(e);
601 for (
unsigned i0 = 0; i0 < np; i0++)
603 for (
unsigned i1 = 0; i1 < np; i1++)
606 unsigned n = i0 * np + i1;
609 SpineNode* nod_pt =
dynamic_cast<SpineNode*
>(el_pt->node_pt(n));
612 nod_pt->node_update_fct_id() = 4;
618 zeta[0] = zeta_lo - double(i1) * dzeta_node;
621 zeta, upper_sub_geom_object_pt, s_up);
624 Vector<double> parameters(3);
625 parameters[0] = s_up[0];
626 parameters[1] = s_transition_lo[0];
627 parameters[2] = s_transition_up[0];
628 nod_pt->spine_pt()->set_geom_parameter(parameters);
631 upper_sub_geom_object_pt->position(s_up, r_wall_up);
635 N[0] = spine_centre[0] - r_wall_up[0];
636 N[1] = spine_centre[1] - r_wall_up[1];
637 double length = sqrt(N[0] * N[0] + N[1] * N[1]);
638 nod_pt->spine_pt()->height() = length - radius;
642 Vector<GeomObject*> geom_object_pt(3);
643 geom_object_pt[0] = upper_sub_geom_object_pt;
644 geom_object_pt[1] = lower_transition_geom_object_pt;
645 geom_object_pt[2] = upper_transition_geom_object_pt;
648 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
651 if (j == 0) set_boundary_node_pt[2].insert(nod_pt);
659 n_prev_elements += nx2 * (nh + 1);
666 double dzeta_el = llayer / double(nx1);
667 double dzeta_node = llayer / double(nx1 * (np - 1));
670 for (
unsigned i = 0; i < nx1; i++)
676 for (
unsigned j = 0; j < nh; j++)
679 unsigned e = n_prev_elements + i * (nh + 1) + j;
682 FiniteElement* el_pt = this->finite_element_pt(e);
685 for (
unsigned i0 = 0; i0 < np; i0++)
687 for (
unsigned i1 = 0; i1 < np; i1++)
690 unsigned n = i0 * np + i1;
693 SpineNode* nod_pt =
dynamic_cast<SpineNode*
>(el_pt->node_pt(n));
696 nod_pt->node_update_fct_id() = 5;
702 zeta[0] = zeta_lo - double(i1) * dzeta_node;
705 zeta, upper_sub_geom_object_pt, s_up);
708 Vector<double> parameters(1, s_up[0]);
709 nod_pt->spine_pt()->set_geom_parameter(parameters);
712 nod_pt->spine_pt()->height() =
H;
716 Vector<GeomObject*> geom_object_pt(1);
717 geom_object_pt[0] = upper_sub_geom_object_pt;
720 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
723 if (j == 0) set_boundary_node_pt[2].insert(nod_pt);
732 this->remove_boundary_nodes();
733 this->set_nboundary(6);
736 for (
unsigned ibound = 0; ibound < 6; ibound++)
738 typedef std::set<Node*>::iterator IT;
739 for (IT it = set_boundary_node_pt[ibound].begin();
740 it != set_boundary_node_pt[ibound].end();
743 this->add_boundary_node(ibound, *it);
750 Vector<double> zeta(1);
751 unsigned n_boundary_node = this->nboundary_node(4);
752 for (
unsigned n = 0; n < n_boundary_node; ++n)
754 zeta[0] = this->boundary_node_pt(4, n)->x(0);
755 this->boundary_node_pt(4, n)->set_coordinates_on_boundary(4, zeta);
775 for (
unsigned i = 0;
i <
nnod;
i++)
787 for (
unsigned e = 0;
e < 2 *
nhalf;
e++)
791 for (
unsigned i = 0;
i <
np;
i++)
796 if ((
e < 1) || (
i > 0))
811 typedef std::set<Node*>::iterator
IT;
822 for (
unsigned e = 0;
e <
nelem;
e++)
850 nod_pt->spine_mesh_pt() =
this;
852 nod_pt->node_update_fct_id() = 6;
880 for (
unsigned long i = 0;
i < 2 *
nhalf;
i++)
883 for (
unsigned l1 = 1;
l1 <
np;
l1++)
894 nod_pt->spine_mesh_pt() =
this;
896 nod_pt->node_update_fct_id() = 6;
904 for (
unsigned long j = 0;
j <
Nx3;
j++)
908 for (
unsigned l2 = 1;
l2 <
np;
l2++)
922 nod_pt->spine_mesh_pt() =
this;
924 nod_pt->node_update_fct_id() = 6;
928 if ((
j ==
Nx3 - 1) && (
l2 ==
np - 1))
964 for (
unsigned long i = 0;
i < 2 *
nhalf;
i++)
967 for (
unsigned l1 = 1;
l1 <
np;
l1++)
978 nod_pt->spine_mesh_pt() =
this;
980 nod_pt->node_update_fct_id() = 6;
983 if ((
j ==
Nx3 - 1) && (
l2 ==
np - 1))
1000 this->setup_boundary_element_info();