The problem of steady flow in a curved tube is considered with a prescribed Poiseuille flow at the inlet and a traction-free outlet condition. It is not clear that the latter is appropriate, but the main aim of this example is to check that the TubeMesh
works correctly.
A detailed comparison between the flow field and the Dean solution should be performed for validation purposes, but the qualitative features seem reasonable.
Detailed documentation to be written. Here's the driver code...
#include "generic.h"
#include "navier_stokes.h"
#include "meshes/tube_mesh.h"
using namespace std;
using namespace oomph;
{
public:
GeomObject(3,3), Radius(radius),
Delta(delta) { }
void position (const Vector<double>& xi, Vector<double>& r) const
{
r[0] = (1.0/
Delta)*cos(xi[0]) + xi[2]*Radius*cos(xi[0])*cos(xi[1]);
r[1] = (1.0/
Delta)*sin(xi[0]) + xi[2]*Radius*sin(xi[0])*cos(xi[1]);
r[2] = -xi[2]*Radius*sin(xi[1]);
}
void position(const unsigned& t,
const Vector<double>& xi, Vector<double>& r) const
{
position(xi,r);
}
private:
double Radius;
};
{
}
template<class ELEMENT>
{
public:
const double& max_error_target);
void actions_before_newton_solve();
void actions_after_adapt()
{
RefineableNavierStokesEquations<3>::
pin_redundant_nodal_pressures(mesh_pt()->element_pt());
}
void doc_solution();
RefineableTubeMesh<ELEMENT>* mesh_pt()
{
return dynamic_cast<RefineableTubeMesh<ELEMENT>*>(Problem::mesh_pt());
}
private:
DocInfo Doc_info;
GeomObject *Volume_pt;
};
template<class ELEMENT>
const double& min_error_target,
const double& max_error_target)
: Doc_info(doc_info)
{
const double pi = MathematicalConstants::Pi;
Vector<double> centreline_limits(2);
centreline_limits[0] = 0.0;
centreline_limits[1] = pi;
Vector<double> theta_positions(4);
theta_positions[0] = -0.75*pi;
theta_positions[1] = -0.25*pi;
theta_positions[2] = 0.25*pi;
theta_positions[3] = 0.75*pi;
Vector<double> radial_frac(4,0.5);
unsigned nlayer=6;
Problem::mesh_pt()= new RefineableTubeMesh<ELEMENT>(Volume_pt,
centreline_limits,
theta_positions,
radial_frac,
nlayer);
Z2ErrorEstimator* error_estimator_pt=new Z2ErrorEstimator;
mesh_pt()->spatial_error_estimator_pt()=error_estimator_pt;
mesh_pt()->max_permitted_error()=max_error_target;
mesh_pt()->min_permitted_error()=min_error_target;
ELEMENT::Gamma[0] = 0.0;
ELEMENT::Gamma[1] = 0.0;
ELEMENT::Gamma[2] = 0.0;
unsigned num_bound = mesh_pt()->nboundary();
for(unsigned ibound=0;ibound<num_bound;ibound++)
{
unsigned num_nod= mesh_pt()->nboundary_node(ibound);
for (unsigned inod=0;inod<num_nod;inod++)
{
if((ibound==0) || (ibound==1))
{
mesh_pt()->boundary_node_pt(ibound,inod)->pin(0);
mesh_pt()->boundary_node_pt(ibound,inod)->pin(1);
mesh_pt()->boundary_node_pt(ibound,inod)->pin(2);
}
}
}
unsigned n_element = mesh_pt()->nelement();
for(unsigned i=0;i<n_element;i++)
{
ELEMENT* el_pt = dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(i));
}
RefineableNavierStokesEquations<3>::
pin_redundant_nodal_pressures(mesh_pt()->element_pt());
cout <<"Number of equations: " << assign_eqn_numbers() << std::endl;
}
template<class ELEMENT>
{
unsigned ibound=0;
unsigned num_nod= mesh_pt()->nboundary_node(ibound);
for (unsigned inod=0;inod<num_nod;inod++)
{
double x=mesh_pt()->boundary_node_pt(ibound,inod)->x(0) -
double z=mesh_pt()->boundary_node_pt(ibound,inod)->x(2);
double r=sqrt(x*x+z*z);
mesh_pt()->boundary_node_pt(ibound,inod)->
set_value(1,(1.0-pow(r,2.0)));
}
}
template<class ELEMENT>
{
ofstream some_file;
char filename[100];
unsigned npts;
npts=5;
sprintf(filename,"%s/soln_Re%g.dat",Doc_info.directory().c_str(),
some_file.open(filename);
mesh_pt()->output(some_file,npts);
some_file.close();
}
int main(
int argc,
char* argv[])
{
CommandLineArgs::setup(argc,argv);
unsigned max_adapt;
double max_error_target,min_error_target;
if (CommandLineArgs::Argc==1)
{
max_adapt=2;
max_error_target=0.001;
min_error_target=0.00001;
}
else
{
max_adapt=1;
max_error_target=0.02;
min_error_target=0.002;
}
DocInfo doc_info;
{
doc_info.set_directory("RESLT_TH");
doc_info.number()=0;
problem(doc_info,min_error_target,max_error_target);
cout << " Doing Taylor-Hood elements " << std::endl;
problem.newton_solve(max_adapt);
problem.doc_solution();
}
{
doc_info.set_directory("RESLT_CR");
doc_info.number()=0;
problem(doc_info,min_error_target,max_error_target);
cout << " Doing Crouzeix-Raviart elements " << std::endl;
problem.newton_solve(max_adapt);
problem.doc_solution();
}
}
Entry flow problem in tapered tube domain.
void doc_solution()
Doc the solution.
void actions_before_newton_solve()
Update the problem specs before solve.
SteadyCurvedTubeProblem(DocInfo &doc_info, const double &min_error_target, const double &max_error_target)
Constructor: Pass DocInfo object and target errors.
int main(int argc, char *argv[])
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
Namespace for physical parameters.
double Re
Reynolds number.
double Delta
The desired curvature of the pipe.