31 #include "navier_stokes.h"
34 #include "meshes/rectangular_quadmesh.h"
38 using namespace oomph;
68 void get_exact_u(
const double& t,
const Vector<double>& x, Vector<double>& u)
72 complex<double> I(0.0,1.0);
74 double omega=2.0*MathematicalConstants::Pi;
77 lambda = I*sqrt(lambda);
81 exp(complex<double>(0.0,omega*t)) *
82 (exp(lambda*complex<double>(0.0,y))-exp(lambda*complex<double>(0.0,-y)))
83 /(exp(I*lambda)-exp(-I*lambda)) );
95 complex<double> I(0.0,1.0);
97 double omega=2.0*MathematicalConstants::Pi;
100 lambda = I*sqrt(lambda);
103 exp(complex<double>(0.0,omega*t)) *
104 (exp(lambda*complex<double>(0.0,y))-exp(lambda*complex<double>(0.0,-y)))
105 /(exp(I*lambda)-exp(-I*lambda)) );
119 template<
class ELEMENT,
class TIMESTEPPER>
127 const double &lx,
const double &ly);
140 unsigned num_nod=mesh_pt()->nboundary_node(ibound);
141 for (
unsigned inod=0;inod<num_nod;inod++)
144 double y=mesh_pt()->boundary_node_pt(ibound,inod)->x(1);
145 double time=time_pt()->time();
150 mesh_pt()->boundary_node_pt(ibound,inod)->set_value(0,soln);
151 mesh_pt()->boundary_node_pt(ibound,inod)->set_value(1,0.0);
157 void unsteady_run(DocInfo& doc_info);
160 void doc_solution(DocInfo& doc_info);
164 void set_initial_condition();
170 const double &pvalue)
173 dynamic_cast<ELEMENT*
>(mesh_pt()->element_pt(e))->
174 fix_pressure(pdof,pvalue);
186 template<
class ELEMENT,
class TIMESTEPPER>
188 (
const unsigned &nx,
const unsigned &ny,
189 const double &lx,
const double& ly)
192 add_time_stepper_pt(
new TIMESTEPPER);
195 bool periodic_in_x=
true;
197 new RectangularQuadMesh<ELEMENT>(nx,ny,lx,ly,periodic_in_x,
203 unsigned num_bound=mesh_pt()->nboundary();
204 for(
unsigned ibound=0;ibound<num_bound;ibound++)
206 unsigned num_nod=mesh_pt()->nboundary_node(ibound);
207 for (
unsigned inod=0;inod<num_nod;inod++)
210 if ((ibound==0)||(ibound==2))
212 mesh_pt()->boundary_node_pt(ibound,inod)->pin(0);
213 mesh_pt()->boundary_node_pt(ibound,inod)->pin(1);
217 else if ((ibound==1)||(ibound==3))
219 mesh_pt()->boundary_node_pt(ibound,inod)->pin(1);
227 unsigned n_el = mesh_pt()->nelement();
228 for(
unsigned e=0;e<n_el;e++)
231 ELEMENT *el_pt =
dynamic_cast<ELEMENT*
>(mesh_pt()->element_pt(e));
239 fix_pressure(0,0,0.0);
242 cout << assign_eqn_numbers() << std::endl;
252 template<
class ELEMENT,
class TIMESTEPPER>
257 if (time_stepper_pt()->type()!=
"BDF")
259 std::ostringstream error_stream;
260 error_stream <<
"Timestepper has to be from the BDF family!\n"
261 <<
"You have specified a timestepper from the "
262 << time_stepper_pt()->type() <<
" family" << std::endl;
264 throw OomphLibError(error_stream.str(),
265 OOMPH_CURRENT_FUNCTION,
266 OOMPH_EXCEPTION_LOCATION);
270 double backed_up_time=time_pt()->time();
277 Vector<double> soln(2);
281 unsigned num_nod = mesh_pt()->nnode();
285 int nprev_steps=time_stepper_pt()->nprev_values();
286 Vector<double> prev_time(nprev_steps+1);
287 for (
int t=nprev_steps;t>=0;t--)
289 prev_time[t]=time_pt()->time(
unsigned(t));
293 for (
int t=nprev_steps;t>=0;t--)
296 double time=prev_time[t];
297 cout <<
"setting IC at time =" << time << std::endl;
300 for (
unsigned n=0;n<num_nod;n++)
303 x[0]=mesh_pt()->node_pt(n)->x(0);
304 x[1]=mesh_pt()->node_pt(n)->x(1);
310 mesh_pt()->node_pt(n)->set_value(t,0,soln[0]);
311 mesh_pt()->node_pt(n)->set_value(t,1,soln[1]);
315 for (
unsigned i=0;i<2;i++)
317 mesh_pt()->node_pt(n)->x(t,i)=x[i];
323 time_pt()->time()=backed_up_time;
331 template<
class ELEMENT,
class TIMESTEPPER>
341 sprintf(filename,
"%s/soln%i.dat",doc_info.directory().c_str(),
343 some_file.open(filename);
344 mesh_pt()->output(some_file,npts);
347 some_file <<
"TEXT X=2.5,Y=93.6,F=HELV,HU=POINT,C=BLUE,H=26,T=\"time = "
348 << time_pt()->time() <<
"\"";
351 some_file <<
"GEOMETRY X=2.5,Y=98,T=LINE,C=BLUE,LT=0.4" << std::endl;
352 some_file <<
"1" << std::endl;
353 some_file <<
"2" << std::endl;
354 some_file <<
" 0 0" << std::endl;
355 some_file << time_pt()->time()*20.0 <<
" 0" << std::endl;
361 sprintf(filename,
"%s/exact_soln%i.dat",doc_info.directory().c_str(),
363 some_file.open(filename);
364 mesh_pt()->output_fct(some_file,npts,time_pt()->time(),
371 sprintf(filename,
"%s/error%i.dat",doc_info.directory().c_str(),
373 some_file.open(filename);
374 mesh_pt()->compute_error(some_file,
382 cout <<
"error: " << error << std::endl;
383 cout <<
"norm : " << norm << std::endl << std::endl;
386 unsigned n_control=37;
387 Vector<double> x(2), u(2);
388 double time=time_pt()->time();
390 dynamic_cast<ELEMENT*
>(mesh_pt()->element_pt(n_control))->node_pt(1);
391 x[0] = node_pt->x(0);
392 x[1] = node_pt->x(1);
396 Trace_file << time <<
" "
399 << node_pt->value(0) <<
" "
400 << node_pt->value(1) <<
" "
403 << abs(u[0]-node_pt->value(0)) <<
" "
404 << abs(u[1]-node_pt->value(1)) <<
" "
416 template<
class ELEMENT,
class TIMESTEPPER>
422 sprintf(filename,
"%s/trace.dat",doc_info.directory().c_str());
423 Trace_file.open(filename);
426 Trace_file <<
"time" <<
", "
431 <<
"u_exact_1" <<
", "
432 <<
"u_exact_2" <<
", "
435 <<
"L2 error" <<
", "
436 <<
"L2 norm" <<
", " << std::endl;
444 assign_initial_values_impulsive(dt);
445 cout <<
"IC = impulsive start" << std::endl;
452 set_initial_condition();
453 cout <<
"IC = exact solution" << std::endl;
463 cout <<
"validation run" << std::endl;
467 doc_solution(doc_info);
473 for(
unsigned t=1;t<=ntsteps;t++)
475 cout <<
"TIMESTEP " << t << std::endl;
478 unsteady_newton_solve(dt);
481 cout <<
"Time is now " << time_pt()->time() << std::endl;
484 doc_solution(doc_info);
496 int main(
int argc,
char* argv[])
502 cout <<
"No command line arguments specified -- using defaults."
507 cout <<
"Two command line arguments specified:" << std::endl;
515 std::string error_message =
516 "Wrong number of command line arguments. Specify none or two.\n";
518 "Arg1: Long_run_flag [0/1]\n";
520 "Arg2: Impulsive_start_flag [0/1]\n";
522 throw OomphLibError(error_message,
523 OOMPH_CURRENT_FUNCTION,
524 OOMPH_EXCEPTION_LOCATION);
526 cout <<
"Long run flag: "
528 cout <<
"Impulsive start flag: "
555 doc_info.set_directory(
"RESLT_CR");
571 doc_info.set_directory(
"RESLT_TH");
Rayleigh-type problem: 2D channel whose upper wall oscillates periodically.
ofstream Trace_file
Trace file.
RayleighProblem(const unsigned &nx, const unsigned &ny, const double &lx, const double &ly)
Constructor: Pass number of elements in x and y directions and lengths.
void set_initial_condition()
Set initial condition (incl previous timesteps) according to specified function.
void unsteady_run(DocInfo &doc_info)
Run an unsteady simulation.
void actions_after_newton_solve()
Update after solve is empty.
void actions_before_implicit_timestep()
void actions_before_newton_solve()
void fix_pressure(const unsigned &e, const unsigned &pdof, const double &pvalue)
Fix pressure in element e at pressure dof pdof and set to pvalue.
void doc_solution(DocInfo &doc_info)
Doc the solution.
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 get_exact_u(const double &t, const double &y, double &u)
Exact solution of the problem as a scalar.
Namespace 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 channel problem.