34 #include "navier_stokes.h"    37 #include "meshes/rectangular_quadmesh.h"    41 using namespace oomph;
    71  void get_exact_u(
const double& t, 
const Vector<double>& x, Vector<double>& u)
    75   complex<double> I(0.0,1.0);
    77   double omega=2.0*MathematicalConstants::Pi;
    80   lambda = I*sqrt(lambda);
    84    exp(complex<double>(0.0,omega*t)) * 
    85    (exp(lambda*complex<double>(0.0,y))-exp(lambda*complex<double>(0.0,-y)))
    86    /(exp(I*lambda)-exp(-I*lambda)) );
    97                           const Vector<double>& x,
    98                           const Vector<double> &n,
    99                           Vector<double>& traction)
   103   complex<double> I(0.0,1.0);
   105   double omega=2.0*MathematicalConstants::Pi;
   108   lambda = I*sqrt(lambda);
   112    exp(complex<double>(0.0,omega*t)) * 
   113    (exp(lambda*complex<double>(0.0,y))+exp(lambda*complex<double>(0.0,-y)))
   114    *I*lambda/(exp(I*lambda)-exp(-I*lambda)) );
   118   traction[0]=real(sol);
   128 template<
class ELEMENT, 
class TIMESTEPPER>
   136                  const double &lx, 
const double &ly);
   148  void unsteady_run(DocInfo& doc_info); 
   151  void doc_solution(DocInfo& doc_info);
   155  void set_initial_condition();
   160  void create_traction_elements(
const unsigned &b, 
   161                                Mesh* 
const &bulk_mesh_pt,
   162                                Mesh* 
const &surface_mesh_pt);
   182 template<
class ELEMENT,
class TIMESTEPPER>
   184 (
const unsigned &nx, 
const unsigned &ny,
   185  const double &lx, 
const double& ly)
   188  add_time_stepper_pt(
new TIMESTEPPER); 
   191  bool periodic_in_x=
true;
   193   new RectangularQuadMesh<ELEMENT>(nx,ny,lx,ly,periodic_in_x,
   199  Surface_mesh_pt = 
new Mesh;
   203  create_traction_elements(2,Bulk_mesh_pt,Surface_mesh_pt);
   206  add_sub_mesh(Bulk_mesh_pt);
   207  add_sub_mesh(Surface_mesh_pt);
   215  unsigned num_bound=Bulk_mesh_pt->nboundary();
   216  for(
unsigned ibound=0;ibound<num_bound;ibound++)
   218    unsigned num_nod=Bulk_mesh_pt->nboundary_node(ibound);
   219    for (
unsigned inod=0;inod<num_nod;inod++)
   225        Bulk_mesh_pt->boundary_node_pt(ibound,inod)->pin(0);
   226        Bulk_mesh_pt->boundary_node_pt(ibound,inod)->pin(1);
   230      else if ((ibound==1) || (ibound==3))
   232        Bulk_mesh_pt->boundary_node_pt(ibound,inod)->pin(1);
   240  unsigned n_el = Bulk_mesh_pt->nelement();
   241  for(
unsigned e=0;e<n_el;e++)
   244    ELEMENT *el_pt = 
dynamic_cast<ELEMENT*
>(Bulk_mesh_pt->element_pt(e));
   253  n_el=Surface_mesh_pt->nelement();
   254  for(
unsigned e=0;e<n_el;e++)
   257    NavierStokesTractionElement<ELEMENT> *el_pt = 
   258     dynamic_cast< NavierStokesTractionElement<ELEMENT>*
>(
   259      Surface_mesh_pt->element_pt(e));
   262    el_pt->traction_fct_pt() = 
   267  cout << assign_eqn_numbers() << std::endl; 
   275 template<
class ELEMENT,
class TIMESTEPPER>
   279  double backed_up_time=time_pt()->time();
   286  Vector<double> soln(2);
   290  unsigned num_nod = mesh_pt()->nnode();
   294  int nprev_steps=time_stepper_pt()->nprev_values();
   295  Vector<double> prev_time(nprev_steps+1);
   296  for (
int t=nprev_steps;t>=0;t--)
   298    prev_time[t]=time_pt()->time(
unsigned(t));
   302  for (
int t=nprev_steps;t>=0;t--)
   305    double time=prev_time[t];
   306    cout << 
"setting IC at time =" << time << std::endl;
   309    for (
unsigned n=0;n<num_nod;n++)
   312      x[0]=mesh_pt()->node_pt(n)->x(0);
   313      x[1]=mesh_pt()->node_pt(n)->x(1);
   319      mesh_pt()->node_pt(n)->set_value(t,0,soln[0]);
   320      mesh_pt()->node_pt(n)->set_value(t,1,soln[1]);
   324      for (
unsigned i=0;i<2;i++)
   326        mesh_pt()->node_pt(n)->x(t,i)=x[i];
   332  time_pt()->time()=backed_up_time;
   342 template<
class ELEMENT,
class TIMESTEPPER>
   354  sprintf(filename,
"%s/soln%i.dat",doc_info.directory().c_str(),
   356  some_file.open(filename);
   357  Bulk_mesh_pt->output(some_file,npts);
   360  some_file << 
"TEXT X=2.5,Y=93.6,F=HELV,HU=POINT,C=BLUE,H=26,T=\"time = "    361            << time_pt()->time() << 
"\"";
   364  some_file << 
"GEOMETRY X=2.5,Y=98,T=LINE,C=BLUE,LT=0.4" << std::endl;
   365  some_file << 
"1" << std::endl;
   366  some_file << 
"2" << std::endl;
   367  some_file << 
" 0 0" << std::endl;
   368  some_file << time_pt()->time()*20.0 << 
" 0" << std::endl;
   374  sprintf(filename,
"%s/exact_soln%i.dat",doc_info.directory().c_str(),
   376  some_file.open(filename);
   377  Bulk_mesh_pt->output_fct(some_file,npts,time_pt()->time(),
   384  sprintf(filename,
"%s/error%i.dat",doc_info.directory().c_str(),
   386  some_file.open(filename);
   387  Bulk_mesh_pt->compute_error(some_file,
   395  cout << 
"error: " << error << std::endl; 
   396  cout << 
"norm : " << norm << std::endl << std::endl;
   399  Vector<double> x(2), u(2);
   400  double time=time_pt()->time();
   401  Node* node_pt=
dynamic_cast<ELEMENT*
>(mesh_pt()->element_pt(37))->node_pt(1);
   402  x[0] = node_pt->x(0);
   403  x[1] = node_pt->x(1);
   407  Trace_file << time << 
" "    410             << node_pt->value(0) << 
" "   411             << node_pt->value(1) << 
" "   414             << abs(u[0]-node_pt->value(0)) << 
" "   415             << abs(u[1]-node_pt->value(1)) << 
" "    427 template<
class ELEMENT,
class TIMESTEPPER>
   430                          Mesh* 
const &surface_mesh_pt)
   433  unsigned n_element = bulk_mesh_pt->nboundary_element(b);
   436  for(
unsigned e=0;e<n_element;e++)
   439    ELEMENT* bulk_elem_pt = 
dynamic_cast<ELEMENT*
>(
   440     bulk_mesh_pt->boundary_element_pt(b,e));
   443    int face_index = bulk_mesh_pt->face_index_at_boundary(b,e);
   446    NavierStokesTractionElement<ELEMENT>* flux_element_pt = 
new    447     NavierStokesTractionElement<ELEMENT>(bulk_elem_pt,face_index);
   450    surface_mesh_pt->add_element_pt(flux_element_pt);
   461 template<
class ELEMENT,
class TIMESTEPPER>
   467  sprintf(filename,
"%s/trace.dat",doc_info.directory().c_str());
   468  Trace_file.open(filename);
   471  Trace_file << 
"time" << 
",      "    476             << 
"u_exact_1" << 
", "   477             << 
"u_exact_2" << 
", "   480             << 
"L2 error" << 
",  "   481             << 
"L2 norm" << 
",   " << std::endl;
   489    assign_initial_values_impulsive(dt);
   490    cout << 
"IC = impulsive start" << std::endl;
   497    set_initial_condition();
   498    cout << 
"IC = exact solution" << std::endl;
   502  unsigned ntsteps=500;
   508    cout << 
"validation run" << std::endl;
   512  doc_solution(doc_info);
   518  for(
unsigned t=1;t<=ntsteps;t++)
   520    cout << 
"TIMESTEP " << t << std::endl;
   523    unsteady_newton_solve(dt);
   526    cout << 
"Time is now " << time_pt()->time() << std::endl;
   529    doc_solution(doc_info);
   541 int main(
int argc, 
char* argv[]) 
   548    cout << 
"No command line arguments specified -- using defaults." << std::endl;
   552    cout << 
"Two command line arguments specified:" << std::endl;
   560    std::string error_message = 
   561     "Wrong number of command line arguments. Specify none or two.\n";
   563     "Arg1: Long_run_flag [0/1]\n";
   565     "Arg2: Impulsive_start_flag [0/1]\n";
   567    throw OomphLibError(error_message,
   568                        OOMPH_CURRENT_FUNCTION,
   569                        OOMPH_EXCEPTION_LOCATION);
   571  cout << 
"Long run flag: "    573  cout << 
"Impulsive start flag: "    600   doc_info.set_directory(
"RESLT_CR");
   604    problem(nx,ny,lx,ly);
   616   doc_info.set_directory(
"RESLT_TH");
   620    problem(nx,ny,lx,ly);
 Rayleigh-type problem: 2D channel flow driven by traction bc. 
RectangularQuadMesh< ELEMENT > * Bulk_mesh_pt
Pointer to the "bulk" mesh. 
void create_traction_elements(const unsigned &b, Mesh *const &bulk_mesh_pt, Mesh *const &surface_mesh_pt)
Create traction elements on boundary b of the Mesh pointed to by bulk_mesh_pt and add them to the Mes...
unsigned Impulsive_start_flag
Flag for impulsive start: Default = start from exact time-periodic solution. 
void doc_solution(DocInfo &doc_info)
Doc the solution. 
Namespace for exact solution. 
int main(int argc, char *argv[])
Driver code for Rayleigh-type problem. 
void actions_after_newton_solve()
Update after solve is empty. 
RayleighTractionProblem(const unsigned &nx, const unsigned &ny, const double &lx, const double &ly)
Problem constructor. 
void actions_before_newton_solve()
Update before solve is empty. 
unsigned Long_run_flag
Flag for long/short run: Default = perform long run. 
void prescribed_traction(const double &t, const Vector< double > &x, const Vector< double > &n, Vector< double > &traction)
Traction required at the top boundary. 
void unsteady_run(DocInfo &doc_info)
Run an unsteady simulation. 
Namepspace for global parameters. 
void get_exact_u(const double &t, const Vector< double > &x, Vector< double > &u)
Exact solution of the problem as a vector. 
double ReSt
Womersley = Reynolds times Strouhal. 
void set_initial_condition()
Set initial condition (incl previous timesteps) according to specified function. 
void actions_before_implicit_timestep()
Actions before timestep (empty) 
double Re
Reynolds number. 
Mesh * Surface_mesh_pt
Pointer to the "surface" mesh. 
ofstream Trace_file
Trace file.