26#ifndef OOMPH_BRETHERTON_SPINE_MESH_TEMPLATE_HEADER
27#define OOMPH_BRETHERTON_SPINE_MESH_TEMPLATE_HEADER
29#ifndef OOMPH_BRETHERTON_SPINE_MESH_HEADER
30#error __FILE__ should only be included from bretherton_spine_mesh.h.
59 template<
class ELEMENT,
class INTERFACE_ELEMENT>
65 const unsigned&
nhalf,
69 const double& zeta_start,
72 const double& zeta_end,
84 Zeta_start(zeta_start),
88 Spine_centre_fraction_pt(&Default_spine_centre_fraction),
89 Default_spine_centre_fraction(0.5)
100 MeshChecker::assert_geometric_element<QElementGeometricBase, ELEMENT>(2);
103 MeshChecker::assert_geometric_element<SpineFiniteElement, ELEMENT>(2);
135 oomph_info <<
"\n\n=================================================== "
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;
146 oomph_info <<
"===================================================\n\n "
155 for (
unsigned i = 0;
i <
n_x;
i++)
163 this->
Element_pt.push_back(interface_element_element_pt);
216 for (
unsigned i = 0;
i <
nx1;
i++)
222 for (
unsigned j = 0;
j <
nh;
j++)
231 for (
unsigned i0 = 0;
i0 <
np;
i0++)
233 for (
unsigned i1 = 0;
i1 <
np;
i1++)
242 nod_pt->node_update_fct_id() = 0;
261 nod_pt->spine_pt()->height() =
H;
269 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
315 for (
unsigned i = 0;
i <
nx2;
i++)
321 for (
unsigned j = 0;
j <
nh;
j++)
330 for (
unsigned i0 = 0;
i0 <
np;
i0++)
332 for (
unsigned i1 = 0;
i1 <
np;
i1++)
341 nod_pt->node_update_fct_id() = 1;
366 double length =
sqrt(N[0] * N[0] + N[1] * N[1]);
377 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
394 for (
unsigned i = 0;
i <
nhalf;
i++)
397 for (
unsigned j = 0;
j <
nh;
j++)
406 for (
unsigned i0 = 0;
i0 <
np;
i0++)
408 for (
unsigned i1 = 0;
i1 <
np;
i1++)
417 nod_pt->node_update_fct_id() = 2;
460 double length =
sqrt(N[0] * N[0] + N[1] * N[1]);
471 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
488 for (
unsigned i = 0;
i <
nhalf;
i++)
491 for (
unsigned j = 0;
j <
nh;
j++)
500 for (
unsigned i0 = 0;
i0 <
np;
i0++)
502 for (
unsigned i1 = 0;
i1 <
np;
i1++)
511 nod_pt->node_update_fct_id() = 3;
554 double length =
sqrt(N[0] * N[0] + N[1] * N[1]);
565 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
586 for (
unsigned i = 0;
i <
nx2;
i++)
592 for (
unsigned j = 0;
j <
nh;
j++)
601 for (
unsigned i0 = 0;
i0 <
np;
i0++)
603 for (
unsigned i1 = 0;
i1 <
np;
i1++)
612 nod_pt->node_update_fct_id() = 4;
637 double length =
sqrt(N[0] * N[0] + N[1] * N[1]);
648 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
670 for (
unsigned i = 0;
i <
nx1;
i++)
676 for (
unsigned j = 0;
j <
nh;
j++)
685 for (
unsigned i0 = 0;
i0 <
np;
i0++)
687 for (
unsigned i1 = 0;
i1 <
np;
i1++)
696 nod_pt->node_update_fct_id() = 5;
712 nod_pt->spine_pt()->height() =
H;
720 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
738 typedef std::set<Node*>::iterator
IT;
766 Nx3, 2 *
nhalf, 1.0, 1.0, time_stepper_pt);
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++)
824 this->
Element_pt.push_back(aux_mesh_pt->element_pt(
e));
840 this->
Spine_pt.push_back(new_spine_pt);
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++)
912 this->
Spine_pt.push_back(new_spine_pt);
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))
1004 aux_mesh_pt->flush_element_and_node_storage();
1017 template<
class ELEMENT,
class INTERFACE_ELEMENT>
1021 unsigned Nx = this->Nx;
1022 unsigned Ny = this->Ny;
1024 unsigned long Nelement = this->nelement();
1026 unsigned long Nfluid = Nx * Ny;
1031 for (
unsigned long j = 0;
j < Nx;
j++)
1034 for (
unsigned long i = 0;
i < Ny;
i++)
1037 dummy.push_back(this->finite_element_pt(Nx *
i +
j));
1045 for (
unsigned long e = 0;
e < Nelement;
e++)
1047 this->Element_pt[
e] =
dummy[
e];
1055 template<
class ELEMENT,
class INTERFACE_ELEMENT>
1063 double lambda = 0.5;
1071 double maxres = 100.0;
1079 for (
unsigned i = 0;
i < 2; ++
i)
1087 for (
unsigned i = 0;
i < 2; ++
i)
1102 for (
unsigned i = 0;
i < 2; ++
i)
1115 for (
unsigned i = 0;
i < 2; ++
i)
1121 for (
unsigned i = 0;
i < 2; ++
i)
1125 maxres = std::fabs(
dx[0]) > std::fabs(
dx[1]) ? std::fabs(
dx[0]) :
1135 }
while (maxres > 1.0e-8);
1147 template<
class ELEMENT,
class INTERFACE_ELEMENT>
1167 ->set_boundary_number_in_bulk_mesh(4);
1194 unsigned np = this->finite_element_pt(0)->
nnode_1d();
1239 for (
unsigned i = 0;
i < Nx1;
i++)
1251 for (
unsigned i1 = 0;
i1 < (
np - 1);
i1++)
1259 nod_pt->set_coordinates_on_boundary(0,
zeta);
1275 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
1282 nod_pt->spine_pt()->height() = find_distance_to_free_surface(
1294 oomph_info <<
"LOWER HORIZONTAL TRANSITION " << std::endl;
1300 for (
unsigned i = 0;
i < Nx2;
i++)
1312 for (
unsigned i1 = 0;
i1 < (
np - 1);
i1++)
1320 nod_pt->set_coordinates_on_boundary(0,
zeta);
1339 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
1344 nod_pt->spine_pt()->height() = find_distance_to_free_surface(
1356 oomph_info <<
"LOWER VERTICAL TRANSITION " << std::endl;
1357 for (
unsigned i = 0;
i < Nhalf;
i++)
1366 for (
unsigned i1 = 0;
i1 < (
np - 1);
i1++)
1412 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
1415 nod_pt->spine_pt()->height() = find_distance_to_free_surface(
1427 oomph_info <<
"UPPER VERTICAL TRANSITION" << std::endl;
1428 for (
unsigned i = 0;
i < Nhalf;
i++)
1437 for (
unsigned i1 = 0;
i1 < (
np - 1);
i1++)
1484 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
1487 nod_pt->spine_pt()->height() = find_distance_to_free_surface(
1499 oomph_info <<
"UPPER HORIZONTAL TRANSITION " << std::endl;
1505 for (
unsigned i = 0;
i < Nx2;
i++)
1517 for (
unsigned i1 = 0;
i1 < (
np - 1);
i1++)
1544 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
1549 nod_pt->spine_pt()->height() = find_distance_to_free_surface(
1561 oomph_info <<
"UPPER THIN FILM" << std::endl;
1567 for (
unsigned i = 0;
i < Nx1;
i++)
1579 for (
unsigned i1 = 0;
i1 < (
np - 1);
i1++)
1587 nod_pt->set_coordinates_on_boundary(2,
zeta);
1601 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
1608 nod_pt->spine_pt()->height() = find_distance_to_free_surface(
1647 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
1653 for (
unsigned long j = 0;
j < Nx3;
j++)
1659 for (
unsigned l2 = 0;
l2 <
np;
l2++)
1677 nod_pt->set_coordinates_on_boundary(0,
zeta);
1685 this->element_node_pt(
e + Nx3 * (2 * Nhalf - 1),
np * (
np - 1) +
l2)
1686 ->set_coordinates_on_boundary(2,
zeta);
1705 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
1721 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.
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)....
A general Finite Element class.
void position(const Vector< double > &zeta, Vector< double > &r) const
Return the parametrised position of the FiniteElement in its incarnation as a GeomObject,...
double size() const
Calculate the size of the element (length, area, volume,...) in Eulerian computational coordinates....
void locate_zeta(const Vector< double > &zeta, GeomObject *&geom_object_pt, Vector< double > &s, const bool &use_coordinate_as_initial_guess=false)
For a given value of zeta, the "global" intrinsic coordinate of a mesh of FiniteElements represented ...
unsigned nnode() const
Return the number of nodes.
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
virtual unsigned nnode_1d() const
Return the number of nodes along one edge of the element Default is to return zero — must be overload...
A geometric object is an object that provides a parametrised description of its shape via the functio...
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...
This class provides a GeomObject representation of a given finite element mesh. The Lagrangian coordi...
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.
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...
void remove_boundary_nodes()
Clear all pointers to boundary nodes.
const Vector< GeneralisedElement * > & element_pt() const
Return reference to the Vector of elements.
Vector< GeneralisedElement * > Element_pt
Vector of pointers to generalised elements.
unsigned long nelement() const
Return number of elements in the mesh.
Node *& boundary_node_pt(const unsigned &b, const unsigned &n)
Return pointer to node n on boundary b.
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...
double & x(const unsigned &i)
Return the i-th nodal coordinate.
An OomphLibError object which should be thrown when an run-time error is encountered....
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...
Spines are used for algebraic node update operations in free-surface fluid problems: They form the ba...
TAdvectionDiffusionReactionElement<NREAGENT,DIM,NNODE_1D> elements are isoparametric triangular DIM-d...
TAdvectionDiffusionReactionElement()
Constructor: Call constructors for TElement and AdvectionDiffusionReaction equations.
Base class for time-stepping schemes. Timestepper provides an approximation of the temporal derivativ...
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).
OomphInfo oomph_info
Single (global) instantiation of the OomphInfo object – this is used throughout the library as a "rep...