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,
70 const double& zeta_end,
82 Zeta_start(zeta_start),
86 Spine_centre_fraction_pt(&Default_spine_centre_fraction),
87 Default_spine_centre_fraction(0.5)
98 MeshChecker::assert_geometric_element<QElementGeometricBase, ELEMENT>(2);
101 MeshChecker::assert_geometric_element<SpineFiniteElement, ELEMENT>(2);
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;
144 oomph_info <<
"===================================================\n\n "
154 for (
unsigned i = 0;
i <
n_x;
i++)
162 this->
Element_pt.push_back(interface_element_element_pt);
215 for (
unsigned i = 0;
i <
nx1;
i++)
221 for (
unsigned j = 0;
j <
nh;
j++)
230 for (
unsigned i0 = 0;
i0 <
np;
i0++)
232 for (
unsigned i1 = 0;
i1 <
np;
i1++)
241 nod_pt->node_update_fct_id() = 0;
260 nod_pt->spine_pt()->height() =
H;
268 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);
489 for (
unsigned i = 0;
i <
nhalf;
i++)
492 for (
unsigned j = 0;
j <
nh;
j++)
501 for (
unsigned i0 = 0;
i0 <
np;
i0++)
503 for (
unsigned i1 = 0;
i1 <
np;
i1++)
512 nod_pt->node_update_fct_id() = 3;
555 double length =
sqrt(N[0] * N[0] + N[1] * N[1]);
566 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
588 for (
unsigned i = 0;
i <
nx2;
i++)
594 for (
unsigned j = 0;
j <
nh;
j++)
603 for (
unsigned i0 = 0;
i0 <
np;
i0++)
605 for (
unsigned i1 = 0;
i1 <
np;
i1++)
614 nod_pt->node_update_fct_id() = 4;
639 double length =
sqrt(N[0] * N[0] + N[1] * N[1]);
650 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
673 for (
unsigned i = 0;
i <
nx1;
i++)
679 for (
unsigned j = 0;
j <
nh;
j++)
688 for (
unsigned i0 = 0;
i0 <
np;
i0++)
690 for (
unsigned i1 = 0;
i1 <
np;
i1++)
699 nod_pt->node_update_fct_id() = 5;
715 nod_pt->spine_pt()->height() =
H;
723 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
741 typedef std::set<Node*>::iterator
IT;
771 Nx3, 2 *
nhalf, 1.0, 1.0, time_stepper_pt);
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++)
829 this->
Element_pt.push_back(aux_mesh_pt->element_pt(
e));
846 this->
Spine_pt.push_back(new_spine_pt);
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++)
919 this->
Spine_pt.push_back(new_spine_pt);
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))
1012 aux_mesh_pt->flush_element_and_node_storage();
1026 template<
class ELEMENT,
class INTERFACE_ELEMENT>
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));
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)
1096 for (
unsigned i = 0;
i < 2; ++
i)
1111 for (
unsigned i = 0;
i < 2; ++
i)
1124 for (
unsigned i = 0;
i < 2; ++
i)
1130 for (
unsigned i = 0;
i < 2; ++
i)
1134 maxres = std::fabs(
dx[0]) > std::fabs(
dx[1]) ? std::fabs(
dx[0]) :
1144 }
while (maxres > 1.0e-8);
1157 template<
class ELEMENT,
class INTERFACE_ELEMENT>
1177 ->set_boundary_number_in_bulk_mesh(4);
1205 unsigned np = this->finite_element_pt(0)->
nnode_1d();
1251 for (
unsigned i = 0;
i < Nx1;
i++)
1263 for (
unsigned i1 = 0;
i1 < (
np - 1);
i1++)
1271 nod_pt->set_coordinates_on_boundary(0,
zeta);
1287 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
1294 nod_pt->spine_pt()->height() = find_distance_to_free_surface(
1307 oomph_info <<
"LOWER HORIZONTAL TRANSITION " << std::endl;
1313 for (
unsigned i = 0;
i < Nx2;
i++)
1325 for (
unsigned i1 = 0;
i1 < (
np - 1);
i1++)
1333 nod_pt->set_coordinates_on_boundary(0,
zeta);
1352 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
1357 nod_pt->spine_pt()->height() = find_distance_to_free_surface(
1369 oomph_info <<
"LOWER VERTICAL TRANSITION " << std::endl;
1370 for (
unsigned i = 0;
i < Nhalf;
i++)
1379 for (
unsigned i1 = 0;
i1 < (
np - 1);
i1++)
1425 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
1428 nod_pt->spine_pt()->height() = find_distance_to_free_surface(
1441 oomph_info <<
"UPPER VERTICAL TRANSITION" << std::endl;
1442 for (
unsigned i = 0;
i < Nhalf;
i++)
1451 for (
unsigned i1 = 0;
i1 < (
np - 1);
i1++)
1499 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
1502 nod_pt->spine_pt()->height() = find_distance_to_free_surface(
1515 oomph_info <<
"UPPER HORIZONTAL TRANSITION " << std::endl;
1521 for (
unsigned i = 0;
i < Nx2;
i++)
1533 for (
unsigned i1 = 0;
i1 < (
np - 1);
i1++)
1560 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
1566 nod_pt->spine_pt()->height() = find_distance_to_free_surface(
1579 oomph_info <<
"UPPER THIN FILM" << std::endl;
1585 for (
unsigned i = 0;
i < Nx1;
i++)
1597 for (
unsigned i1 = 0;
i1 < (
np - 1);
i1++)
1605 nod_pt->set_coordinates_on_boundary(2,
zeta);
1619 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
1626 nod_pt->spine_pt()->height() = find_distance_to_free_surface(
1667 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
1673 for (
unsigned long j = 0;
j < Nx3;
j++)
1679 for (
unsigned l2 = 0;
l2 <
np;
l2++)
1697 nod_pt->set_coordinates_on_boundary(0,
zeta);
1705 this->element_node_pt(
e + Nx3 * (2 * Nhalf - 1),
np * (
np - 1) +
l2)
1706 ->set_coordinates_on_boundary(2,
zeta);
1725 nod_pt->spine_pt()->set_geom_object_pt(geom_object_pt);
1742 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...
/////////////////////////////////////////////////////////////////////
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.
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()
Constructor: Call constructors for TElement and AdvectionDiffusionReaction equations.
////////////////////////////////////////////////////////////////////// //////////////////////////////...
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
OomphInfo oomph_info
Single (global) instantiation of the OomphInfo object – this is used throughout the library as a "rep...