30 #include "navier_stokes.h"
33 #include "meshes/rectangular_quadmesh.h"
37 using namespace oomph;
67 void get_exact_u(
const double& t,
const Vector<double>& x, Vector<double>& u)
71 complex<double> I(0.0,1.0);
73 double omega=2.0*MathematicalConstants::Pi;
76 lambda = I*sqrt(lambda);
80 exp(complex<double>(0.0,omega*t)) *
81 (exp(lambda*complex<double>(0.0,y))-exp(lambda*complex<double>(0.0,-y)))
82 /(exp(I*lambda)-exp(-I*lambda)) );
93 const Vector<double>& x,
94 const Vector<double> &n,
95 Vector<double>& traction)
99 complex<double> I(0.0,1.0);
101 double omega=2.0*MathematicalConstants::Pi;
104 lambda = I*sqrt(lambda);
108 exp(complex<double>(0.0,omega*t)) *
109 (exp(lambda*complex<double>(0.0,y))+exp(lambda*complex<double>(0.0,-y)))
110 *I*lambda/(exp(I*lambda)-exp(-I*lambda)) );
114 traction[0]=real(sol);
124 template<
class ELEMENT,
class TIMESTEPPER>
132 const double &lx,
const double &ly);
144 void unsteady_run(DocInfo& doc_info);
147 void doc_solution(DocInfo& doc_info);
151 void set_initial_condition();
156 void create_traction_elements(
const unsigned &b,
157 Mesh*
const &bulk_mesh_pt,
158 Mesh*
const &surface_mesh_pt);
178 template<
class ELEMENT,
class TIMESTEPPER>
180 (
const unsigned &nx,
const unsigned &ny,
181 const double &lx,
const double& ly)
184 add_time_stepper_pt(
new TIMESTEPPER);
187 bool periodic_in_x=
true;
189 new RectangularQuadMesh<ELEMENT>(nx,ny,lx,ly,periodic_in_x,
195 Surface_mesh_pt =
new Mesh;
199 create_traction_elements(2,Bulk_mesh_pt,Surface_mesh_pt);
202 add_sub_mesh(Bulk_mesh_pt);
203 add_sub_mesh(Surface_mesh_pt);
211 unsigned num_bound=Bulk_mesh_pt->nboundary();
212 for(
unsigned ibound=0;ibound<num_bound;ibound++)
214 unsigned num_nod=Bulk_mesh_pt->nboundary_node(ibound);
215 for (
unsigned inod=0;inod<num_nod;inod++)
221 Bulk_mesh_pt->boundary_node_pt(ibound,inod)->pin(0);
222 Bulk_mesh_pt->boundary_node_pt(ibound,inod)->pin(1);
226 else if ((ibound==1) || (ibound==3))
228 Bulk_mesh_pt->boundary_node_pt(ibound,inod)->pin(1);
236 unsigned n_el = Bulk_mesh_pt->nelement();
237 for(
unsigned e=0;e<n_el;e++)
240 ELEMENT *el_pt =
dynamic_cast<ELEMENT*
>(Bulk_mesh_pt->element_pt(e));
249 n_el=Surface_mesh_pt->nelement();
250 for(
unsigned e=0;e<n_el;e++)
253 NavierStokesTractionElement<ELEMENT> *el_pt =
254 dynamic_cast< NavierStokesTractionElement<ELEMENT>*
>(
255 Surface_mesh_pt->element_pt(e));
258 el_pt->traction_fct_pt() =
263 cout << assign_eqn_numbers() << std::endl;
271 template<
class ELEMENT,
class TIMESTEPPER>
275 double backed_up_time=time_pt()->time();
282 Vector<double> soln(2);
286 unsigned num_nod = mesh_pt()->nnode();
290 int nprev_steps=time_stepper_pt()->nprev_values();
291 Vector<double> prev_time(nprev_steps+1);
292 for (
int t=nprev_steps;t>=0;t--)
294 prev_time[t]=time_pt()->time(
unsigned(t));
298 for (
int t=nprev_steps;t>=0;t--)
301 double time=prev_time[t];
302 cout <<
"setting IC at time =" << time << std::endl;
305 for (
unsigned n=0;n<num_nod;n++)
308 x[0]=mesh_pt()->node_pt(n)->x(0);
309 x[1]=mesh_pt()->node_pt(n)->x(1);
315 mesh_pt()->node_pt(n)->set_value(t,0,soln[0]);
316 mesh_pt()->node_pt(n)->set_value(t,1,soln[1]);
320 for (
unsigned i=0;i<2;i++)
322 mesh_pt()->node_pt(n)->x(t,i)=x[i];
328 time_pt()->time()=backed_up_time;
338 template<
class ELEMENT,
class TIMESTEPPER>
350 sprintf(filename,
"%s/soln%i.dat",doc_info.directory().c_str(),
352 some_file.open(filename);
353 Bulk_mesh_pt->output(some_file,npts);
356 some_file <<
"TEXT X=2.5,Y=93.6,F=HELV,HU=POINT,C=BLUE,H=26,T=\"time = "
357 << time_pt()->time() <<
"\"";
360 some_file <<
"GEOMETRY X=2.5,Y=98,T=LINE,C=BLUE,LT=0.4" << std::endl;
361 some_file <<
"1" << std::endl;
362 some_file <<
"2" << std::endl;
363 some_file <<
" 0 0" << std::endl;
364 some_file << time_pt()->time()*20.0 <<
" 0" << std::endl;
370 sprintf(filename,
"%s/exact_soln%i.dat",doc_info.directory().c_str(),
372 some_file.open(filename);
373 Bulk_mesh_pt->output_fct(some_file,npts,time_pt()->time(),
380 sprintf(filename,
"%s/error%i.dat",doc_info.directory().c_str(),
382 some_file.open(filename);
383 Bulk_mesh_pt->compute_error(some_file,
391 cout <<
"error: " << error << std::endl;
392 cout <<
"norm : " << norm << std::endl << std::endl;
395 Vector<double> x(2), u(2);
396 double time=time_pt()->time();
397 Node* node_pt=
dynamic_cast<ELEMENT*
>(mesh_pt()->element_pt(37))->node_pt(1);
398 x[0] = node_pt->x(0);
399 x[1] = node_pt->x(1);
403 Trace_file << time <<
" "
406 << node_pt->value(0) <<
" "
407 << node_pt->value(1) <<
" "
410 << abs(u[0]-node_pt->value(0)) <<
" "
411 << abs(u[1]-node_pt->value(1)) <<
" "
423 template<
class ELEMENT,
class TIMESTEPPER>
426 Mesh*
const &surface_mesh_pt)
429 unsigned n_element = bulk_mesh_pt->nboundary_element(b);
432 for(
unsigned e=0;e<n_element;e++)
435 ELEMENT* bulk_elem_pt =
dynamic_cast<ELEMENT*
>(
436 bulk_mesh_pt->boundary_element_pt(b,e));
439 int face_index = bulk_mesh_pt->face_index_at_boundary(b,e);
442 NavierStokesTractionElement<ELEMENT>* flux_element_pt =
new
443 NavierStokesTractionElement<ELEMENT>(bulk_elem_pt,face_index);
446 surface_mesh_pt->add_element_pt(flux_element_pt);
457 template<
class ELEMENT,
class TIMESTEPPER>
463 sprintf(filename,
"%s/trace.dat",doc_info.directory().c_str());
464 Trace_file.open(filename);
467 Trace_file <<
"time" <<
", "
472 <<
"u_exact_1" <<
", "
473 <<
"u_exact_2" <<
", "
476 <<
"L2 error" <<
", "
477 <<
"L2 norm" <<
", " << std::endl;
485 assign_initial_values_impulsive(dt);
486 cout <<
"IC = impulsive start" << std::endl;
493 set_initial_condition();
494 cout <<
"IC = exact solution" << std::endl;
498 unsigned ntsteps=500;
504 cout <<
"validation run" << std::endl;
508 doc_solution(doc_info);
514 for(
unsigned t=1;t<=ntsteps;t++)
516 cout <<
"TIMESTEP " << t << std::endl;
519 unsteady_newton_solve(dt);
522 cout <<
"Time is now " << time_pt()->time() << std::endl;
525 doc_solution(doc_info);
537 int main(
int argc,
char* argv[])
544 cout <<
"No command line arguments specified -- using defaults." << std::endl;
548 cout <<
"Two command line arguments specified:" << std::endl;
556 std::string error_message =
557 "Wrong number of command line arguments. Specify none or two.\n";
559 "Arg1: Long_run_flag [0/1]\n";
561 "Arg2: Impulsive_start_flag [0/1]\n";
563 throw OomphLibError(error_message,
564 OOMPH_CURRENT_FUNCTION,
565 OOMPH_EXCEPTION_LOCATION);
567 cout <<
"Long run flag: "
569 cout <<
"Impulsive start flag: "
596 doc_info.set_directory(
"RESLT_CR");
600 problem(nx,ny,lx,ly);
612 doc_info.set_directory(
"RESLT_TH");
616 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...
void doc_solution(DocInfo &doc_info)
Doc the solution.
void unsteady_run(DocInfo &doc_info)
Run an unsteady simulation.
RayleighTractionProblem(const unsigned &nx, const unsigned &ny, const double &lx, const double &ly)
Constructor: Pass number of elements in x and y directions and lengths.
ofstream Trace_file
Trace file.
Mesh * Surface_mesh_pt
Pointer to the "surface" mesh.
void set_initial_condition()
Set initial condition (incl previous timesteps) according to specified function.
void actions_after_newton_solve()
Update after solve is empty.
void actions_before_newton_solve()
Update before solve is empty.
void actions_before_implicit_timestep()
Actions before timestep (empty)
Namespace for exact solution.
void get_exact_u(const double &t, const Vector< double > &x, Vector< double > &u)
Exact solution of the problem as a vector.
void prescribed_traction(const double &t, const Vector< double > &x, const Vector< double > &n, Vector< double > &traction)
Traction required at the top boundary.
Namepspace for global parameters.
unsigned Long_run_flag
Flag for long/short run: Default = perform long run.
double ReSt
Womersley = Reynolds times Strouhal.
double Re
Reynolds number.
unsigned Impulsive_start_flag
Flag for impulsive start: Default = start from exact time-periodic solution.
int main(int argc, char *argv[])
Driver code for Rayleigh-type problem.