26 #ifndef OOMPH_TWO_LAYER_SPINE_MESH_TEMPLATE_CC
27 #define OOMPH_TWO_LAYER_SPINE_MESH_TEMPLATE_CC
48 template<
class ELEMENT>
57 nx, ny1 + ny2, 0.0, lx, 0.0, h1 + h2, false, false, time_stepper_pt)
60 MeshChecker::assert_geometric_element<QElementGeometricBase, ELEMENT>(2);
63 MeshChecker::assert_geometric_element<SpineFiniteElement, ELEMENT>(2);
97 template<
class ELEMENT>
104 const bool& periodic_in_x,
117 MeshChecker::assert_geometric_element<QElementGeometricBase, ELEMENT>(2);
120 MeshChecker::assert_geometric_element<SpineFiniteElement, ELEMENT>(2);
155 template<
class ELEMENT>
162 const bool& periodic_in_x,
163 const bool& build_mesh,
176 MeshChecker::assert_geometric_element<QElementGeometricBase, ELEMENT>(2);
179 MeshChecker::assert_geometric_element<SpineFiniteElement, ELEMENT>(2);
210 template<
class ELEMENT>
217 double xstep = (this->Xmax - this->Xmin) / ((this->Np - 1) * this->Nx);
219 return (this->Xmin + xstep * ((this->Np - 1) * xelement + xnode));
226 template<
class ELEMENT>
240 double y1init = Ymin;
242 double y2init = H1 - Ymin;
246 double y1step = (H1 - Ymin) / ((n_p - 1) * Ny1);
248 double y2step = (Ymax - H1) / ((n_p - 1) * Ny2);
254 return (y1init + y1step * ((n_p - 1) * yelement + ynode));
258 return (y2init + y2step * ((n_p - 1) * (yelement - Ny1) + ynode));
266 template<
class ELEMENT>
278 unsigned long n_lower = this->Nx * Ny1;
279 unsigned long n_upper = this->Nx * Ny2;
281 Lower_layer_element_pt.reserve(n_lower);
282 for (
unsigned e = 0;
e < n_lower;
e++)
284 Lower_layer_element_pt.push_back(this->finite_element_pt(
e));
287 Upper_layer_element_pt.reserve(n_upper);
288 for (
unsigned e = n_lower;
e < (n_lower + n_upper);
e++)
290 Upper_layer_element_pt.push_back(this->finite_element_pt(
e));
294 Interface_lower_boundary_element_pt.resize(this->Nx);
295 Interface_upper_boundary_element_pt.resize(this->Nx);
297 unsigned count_lower = this->Nx * (this->Ny1 - 1);
298 unsigned count_upper = count_lower + this->Nx;
299 for (
unsigned e = 0;
e < this->Nx;
e++)
301 Interface_lower_boundary_element_pt[
e] =
302 this->finite_element_pt(count_lower);
304 Interface_upper_boundary_element_pt[
e] =
305 this->finite_element_pt(count_upper);
315 const double y_interface = H1 - this->Ymin;
318 unsigned n_boundary_node = this->nboundary_node(3);
321 for (
unsigned n = 0; n < n_boundary_node; n++)
324 Node*
const nod_pt = this->boundary_node_pt(3, n);
326 if (boundary_coordinate_exists(3))
332 this->Boundary_coordinate_exists[4] =
true;
333 this->Boundary_coordinate_exists[5] =
true;
340 double y = nod_pt->
x(1);
342 if (y >= y_interface)
344 this->add_boundary_node(4, nod_pt);
346 if (this->Boundary_coordinate_exists[4])
352 if (y <= y_interface)
354 this->add_boundary_node(5, nod_pt);
356 if (this->Boundary_coordinate_exists[5])
364 this->Boundary_node_pt[3].clear();
367 n_boundary_node = this->nboundary_node(2);
370 for (
unsigned n = 0; n < n_boundary_node; n++)
373 Node*
const nod_pt = this->boundary_node_pt(2, n);
375 if (this->boundary_coordinate_exists(2))
379 this->Boundary_coordinate_exists[3] =
true;
385 this->add_boundary_node(3, nod_pt);
386 if (this->Boundary_coordinate_exists[3])
393 this->Boundary_node_pt[2].clear();
395 std::list<Node*> nodes_to_be_removed;
398 n_boundary_node = this->nboundary_node(1);
400 for (
unsigned n = 0; n < n_boundary_node; n++)
403 Node*
const nod_pt = this->boundary_node_pt(1, n);
406 double y = nod_pt->
x(1);
408 if (y >= y_interface)
411 if (this->boundary_coordinate_exists(1))
415 this->Boundary_coordinate_exists[2] =
true;
421 nodes_to_be_removed.push_back(nod_pt);
424 this->add_boundary_node(2, nod_pt);
426 if (this->Boundary_coordinate_exists[2])
435 for (std::list<Node*>::iterator it = nodes_to_be_removed.begin();
436 it != nodes_to_be_removed.end();
439 this->remove_boundary_node(1, *it);
441 nodes_to_be_removed.clear();
447 unsigned n_p =
dynamic_cast<ELEMENT*
>(finite_element_pt(0))->nnode_1d();
453 this->Boundary_coordinate_exists[6];
455 unsigned n_start = 0;
456 for (
unsigned e = 0;
e < this->Nx;
e++)
464 FiniteElement* el_pt = this->finite_element_pt(this->Nx * this->Ny1 +
e);
466 for (
unsigned n = n_start; n < n_p; n++)
469 this->convert_to_boundary_node(nod_pt);
470 this->add_boundary_node(6, nod_pt);
471 b_coord[0] = nod_pt->
x(0);
479 Spine_pt.reserve((n_p - 1) * this->Nx);
483 Spine_pt.reserve((n_p - 1) * this->Nx + 1);
494 Spine_pt.push_back(new_spine_pt);
497 SpineNode* nod_pt = element_node_pt(0, 0);
510 for (
unsigned long i = 0;
i < Ny1;
i++)
513 for (
unsigned l1 = 1; l1 < n_p; l1++)
516 SpineNode* nod_pt = element_node_pt(
i * this->Nx, l1 * n_p);
520 nod_pt->
fraction() = (nod_pt->
x(1) - this->Ymin) / (H1);
529 for (
unsigned long i = 0;
i < Ny2;
i++)
532 for (
unsigned l1 = 1; l1 < n_p; l1++)
535 SpineNode* nod_pt = element_node_pt((Ny1 +
i) * this->Nx, l1 * n_p);
540 nod_pt->
fraction() = (nod_pt->
x(1) - (this->Ymin + H1)) / (H2);
553 for (
unsigned long j = 0; j < this->Nx; j++)
559 unsigned n_pmax = n_p;
560 if ((this->Xperiodic) && (j == this->Nx - 1)) n_pmax = n_p - 1;
562 for (
unsigned l2 = 1; l2 < n_pmax; l2++)
565 new_spine_pt =
new Spine(H1);
566 Spine_pt.push_back(new_spine_pt);
569 SpineNode* nod_pt = element_node_pt(j, l2);
582 for (
unsigned long i = 0;
i < Ny1;
i++)
585 for (
unsigned l1 = 1; l1 < n_p; l1++)
589 element_node_pt(
i * this->Nx + j, l1 * n_p + l2);
593 nod_pt->
fraction() = (nod_pt->
x(1) - this->Ymin) / H1;
602 for (
unsigned long i = 0;
i < Ny2;
i++)
605 for (
unsigned l1 = 1; l1 < n_p; l1++)
609 element_node_pt((Ny1 +
i) * this->Nx + j, l1 * n_p + l2);
614 nod_pt->
fraction() = (nod_pt->
x(1) - (this->Ymin + H1)) / H2;
630 Spine* final_spine_pt = Spine_pt[0];
633 SpineNode* nod_pt = element_node_pt((this->Nx - 1), (n_p - 1));
636 nod_pt->
spine_pt() = final_spine_pt;
638 nod_pt->
fraction() = element_node_pt(0, 0)->fraction();
640 nod_pt->
spine_mesh_pt() = element_node_pt(0, 0)->spine_mesh_pt();
643 element_node_pt(0, 0)->node_update_fct_id();
646 for (
unsigned i = 0;
i < (Ny1 + Ny2);
i++)
649 for (
unsigned l1 = 1; l1 < n_p; l1++)
652 SpineNode* nod_pt = element_node_pt(
i * this->Nx + (this->Nx - 1),
653 l1 * n_p + (n_p - 1));
656 nod_pt->
spine_pt() = final_spine_pt;
659 element_node_pt(
i * this->Nx, l1 * n_p)->fraction();
662 element_node_pt(
i * this->Nx, l1 * n_p)->node_update_fct_id();
665 element_node_pt(
i * this->Nx, l1 * n_p)->spine_mesh_pt();
695 this->setup_boundary_element_info();
A general Finite Element class.
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
double & x(const unsigned &i)
Return the i-th nodal coordinate.
virtual unsigned ncoordinates_on_boundary(const unsigned &b)
Get the number of boundary coordinates on mesh boundary b. Broken virtual interface provides run-time...
virtual void remove_from_boundary(const unsigned &b)
Broken interface for removing the node from the mesh boundary b Here to provide error reporting.
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...
virtual void get_coordinates_on_boundary(const unsigned &b, const unsigned &k, Vector< double > &boundary_zeta)
Return the vector of the k-th generalised boundary coordinates on mesh boundary b....
RectangularQuadMesh is a two-dimensional mesh of Quad elements with Nx elements in the "x" (horizonal...
void build_mesh(TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Generic mesh construction function: contains all the hard work.
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...
////////////////////////////////////////////////////////////////////// //////////////////////////////...
double H2
Height of the upper layer.
TwoLayerSpineMesh(const unsigned &nx, const unsigned &ny1, const unsigned &ny2, const double &lx, const double &h1, const double &h2, TimeStepper *time_stepper_pt=&Mesh::Default_TimeStepper)
Constructor: Pass number of elements in x-direction, number of elements in y-direction in bottom and ...
double y_spacing_function(unsigned xelement, unsigned xnode, unsigned yelement, unsigned ynode)
The spacing function for the y co-ordinates with three regions in each fluid.
unsigned Ny2
Number of elements in upper layer.
double x_spacing_function(unsigned xelement, unsigned xnode, unsigned yelement, unsigned ynode)
The spacing function for the x co-ordinates with two regions.
unsigned Ny1
Number of elements in lower layer.
double H1
Height of the lower layer.
virtual void build_two_layer_mesh(TimeStepper *time_stepper_pt)
Helper function to actually build the two-layer spine mesh (called from various constructors)
//////////////////////////////////////////////////////////////////// ////////////////////////////////...