linearised_axisym_navier_stokes/counter_rotating_disks/counter_rotating_disks.cc File Reference

Classes

class  BaseStateProblem< BASE_ELEMENT >
 Base state problem class for Tuckerman counter-rotating lids problem. More...
 
class  PerturbedStateProblem< BASE_ELEMENT, PERTURBED_ELEMENT >
 
class  StabilityProblem< BASE_ELEMENT, PERTURBED_ELEMENT >
 

Namespaces

 GlobalPhysicalVariables
 Namespace for physical parameters.
 

Functions

int main (int argc, char *argv[])
 Driver for Tuckerman counter-rotating lids problem (no power method) More...
 

Variables

double GlobalPhysicalVariables::St = 1.0
 Strouhal number. More...
 
double GlobalPhysicalVariables::InvFr = 0.0
 Inverse of Froude number. More...
 
double GlobalPhysicalVariables::Re_current
 
double GlobalPhysicalVariables::ReSt_current
 
double GlobalPhysicalVariables::ReInvFr_current
 
double GlobalPhysicalVariables::Re_lower_limit = 300
 Loop information. More...
 
double GlobalPhysicalVariables::Re_upper_limit = 302
 
unsigned GlobalPhysicalVariables::Nparam_steps = 5
 
Vector< doubleGlobalPhysicalVariables::G (3)
 Direction of gravity. More...
 

Function Documentation

◆ main()

int main ( int argc  ,
char argv[] 
)

Driver for Tuckerman counter-rotating lids problem (no power method)

////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////

1186 {
1187  // Store command line arguments
1188  CommandLineArgs::setup(argc,argv);
1189 
1190  // Set duration of timestep
1191  const double dt = 0.005;
1192 
1193  // Set number of elements in radial (r) direction
1194  const unsigned base_n_r = 25;
1195  const unsigned perturbed_n_r = 25;
1196 
1197  // Set number of elements in axial (z) direction
1198  const unsigned base_n_z = 25;
1199  const unsigned perturbed_n_z = 25;
1200 
1201  // Determine height of computational domain (this is just the aspect
1202  // ratio since we take the cylinder radius to always be one)
1203  const double domain_height = GlobalPhysicalVariables::Gamma;
1204 
1205  // Set direction of gravity (vertically downwards)
1206  GlobalPhysicalVariables::G[0] = 0.0;
1207  GlobalPhysicalVariables::G[1] = -1.0;
1208  GlobalPhysicalVariables::G[2] = 0.0;
1209 
1210  // Set maximum number of iterations of the power method
1211  const unsigned max_iter = 10000;
1212 
1213  // Set tolerance for power method convergence (this is usually machine
1214  // precision according to Bai, Demmel, Dongarra, Ruhe & Van der Vorst)
1215  double power_method_tolerance = 1e-8;
1216 
1217  // Cache upper and lower limits and number of steps for loop over Re
1220  double n_param_steps = GlobalPhysicalVariables::Nparam_steps;
1221 
1222  // If we are doing a validation run, only compute one value of the
1223  // Reynolds number and use a lower tolerance
1224  if(CommandLineArgs::Argc>1)
1225  {
1226  n_param_steps = 1;
1227  power_method_tolerance = 1e-5;
1228  }
1229 
1230  // -----------------------------------------
1231  // LinearisedAxisymmetricQTaylorHoodElements
1232  // -----------------------------------------
1233  {
1234  cout << "\nDoing LinearisedAxisymmetricQTaylorHoodElements\n" << endl;
1235 
1236  // Build stability problem (this creates base and perturbed state problems)
1239  problem(base_n_r,base_n_z,perturbed_n_r,perturbed_n_z,domain_height);
1240 
1241  // Set up labels for output
1242  DocInfo doc_info;
1243 
1244  // Output directory
1245  doc_info.set_directory("RESLT_TH");
1246 
1247  // Initialise timestep (also sets weights for all timesteppers)
1248  problem.initialise_dt(dt);
1249 
1250  // Set initial conditions
1251  problem.set_initial_condition();
1252 
1253  // Set up storage for dominant eigenvector and eigenvalue
1254  DoubleVector eigenvector;
1255  double eigenvalue = 0.0;
1256 
1257  // Get initial guess for eigenvector (these are the initial conditions
1258  // set up in PerturbedStateProblem::set_initial_conditions())
1259  problem.get_perturbed_state_problem_dofs(eigenvector);
1260 
1261  // Create and initialise global trace file
1262  ofstream global_trace;
1263  char filename[256];
1264  sprintf(filename,"%s/global_trace_k%i.dat",
1265  doc_info.directory().c_str(),
1267  global_trace.open(filename);
1268  global_trace << "Re, dominating eigenvalue, "
1269  << "n_base_flow_continuation_steps, "
1270  << "n_power_method_iterations" << std::endl;
1271 
1272  // Begin loop over Reynolds number
1273  for(unsigned param=0;param<n_param_steps;param++)
1274  {
1275  // Set Re_current to the correct value
1276  if(lower==upper || n_param_steps<=1)
1277  {
1279  }
1280  else
1281  {
1283  lower + (((upper-lower)/(n_param_steps-1))*param);
1284  }
1285 
1286  // Set ReSt and ReInvFr to the correct values
1291 
1292  cout << "\n====================================================" << endl;
1293  cout << "Beginning parameter run " << param+1 << " of "
1294  << n_param_steps << ": Re = "
1296  cout << "====================================================" << endl;
1297 
1298  // Pass updated Reynolds number (and ReSt and ReInvFr) to elements
1299  problem.pass_updated_nondim_parameters_to_elements();
1300 
1301  // Reset the global time (of both problems!) to zero
1302  problem.reset_global_time_to_zero();
1303 
1304  // Initialise counter for solutions
1305  doc_info.number()=0;
1306 
1307  // Create trace files
1308  problem.create_trace_files(doc_info);
1309 
1310  // Initialise trace files
1311  problem.initialise_trace_files();
1312 
1313  // Output initial conditions
1314  problem.doc_solution(doc_info,false,false);
1315 
1316  // Increment counter for solutions
1317  doc_info.number()++;
1318 
1319  // Find steady base flow
1320  // ---------------------
1321 
1322  // Determine number of steps to take when ramping up to actual
1323  // Reynolds number
1324  const unsigned n_base_flow_continuation_steps = 1;
1325 
1326  // If we're on the first parameter, need to get to steady state by
1327  // continuation
1328  if(param==0)
1329  {
1330  cout << "\nEntering steady base flow loop..." << endl;
1331 
1332  // Store the current parameter value
1333  const double Re_current_backup = GlobalPhysicalVariables::Re_current;
1334 
1335  // Loop over continuation steps
1336  for(unsigned i=0;i<=n_base_flow_continuation_steps;i++)
1337  {
1338  // Update current parameters
1340  i*(Re_current_backup/n_base_flow_continuation_steps);
1345 
1346  cout << " - Setting GlobalPhysicalVariables::Re_current = "
1348 
1349  // Pass updated Reynolds number (and ReSt and ReInvFr) to elements
1350  problem.pass_updated_nondim_parameters_to_elements();
1351 
1352  // Perform a steady base flow solve
1353  problem.base_flow_steady_newton_solve();
1354  }
1355  }
1356  // Otherwise, just require one steady base flow solve
1357  else { problem.base_flow_steady_newton_solve(); }
1358 
1359  // Enable Jacobian reuse in the perturbed state problem. Note that this
1360  // can only be done since the problem is linear and the base state is
1361  // steady, and so the Jacobian will be the same at each timestep.
1362  // Calling this function also resets the
1363  // Problem::Jacobian_has_been_computed flag to "false", so that during
1364  // the first solve it will be recomputed. Note that this is the reason
1365  // that we call this function here rather than in the problem constructor.
1366  // Were we to call it in the constructor then the Jacobian would not be
1367  // recomputed when we changed the problem parameters (Reynolds number etc.)
1368  problem.perturbed_state_problem_pt()->enable_jacobian_reuse();
1369 
1370  // Perform power method and store number of iterations
1371  const unsigned n_power_method_iterations =
1372  problem.perform_power_method(dt,doc_info,power_method_tolerance,
1373  max_iter,eigenvalue,eigenvector);
1374 
1375  cout << "\nDominating eigenvalue is " << eigenvalue << endl;
1376 
1377  // The corresponding dominating eigenvector is "input"
1378 
1379  // Document in the global trace file
1380  global_trace << GlobalPhysicalVariables::Re_current << " ";
1381  ios_base::fmtflags flags = cout.flags(); // Save old flags
1382  global_trace.precision(14); // ten decimal places
1383  global_trace << eigenvalue << " ";
1384  global_trace.flags(flags); // Set the flags to the way they were
1385  global_trace << n_base_flow_continuation_steps << " "
1386  << n_power_method_iterations << std::endl;
1387 
1388  // The initial guess for the next power method will be the eigenvector
1389  // calculated by this power method
1390 
1391  // Clear and close trace files
1392  problem.close_trace_files();
1393 
1394  } // End loop over Reynolds number
1395  }
1396 
1397  // ----------------------------------------------
1398  // LinearisedAxisymmetricQCrouzeixRaviartElements
1399  // ----------------------------------------------
1400 {
1401  cout << "\nDoing LinearisedAxisymmetricQCrouzeixRaviartElements\n" << endl;
1402 
1403  // Build stability problem (this creates base and perturbed state problems)
1406  problem(base_n_r,base_n_z,perturbed_n_r,perturbed_n_z,domain_height);
1407 
1408  // Set up labels for output
1409  DocInfo doc_info;
1410 
1411  // Output directory
1412  doc_info.set_directory("RESLT_CR");
1413 
1414  // Initialise timestep (also sets weights for all timesteppers)
1415  problem.initialise_dt(dt);
1416 
1417  // Set initial conditions
1418  problem.set_initial_condition();
1419 
1420  // Set up storage for dominant eigenvector and eigenvalue
1421  DoubleVector eigenvector;
1422  double eigenvalue = 0.0;
1423 
1424  // Get initial guess for eigenvector (these are the initial conditions
1425  // set up in PerturbedStateProblem::set_initial_conditions())
1426  problem.get_perturbed_state_problem_dofs(eigenvector);
1427 
1428  // Create and initialise global trace file
1429  ofstream global_trace;
1430  char filename[256];
1431  sprintf(filename,"%s/global_trace_k%i.dat",
1432  doc_info.directory().c_str(),
1434  global_trace.open(filename);
1435  global_trace << "Re, dominating eigenvalue, "
1436  << "n_base_flow_continuation_steps, "
1437  << "n_power_method_iterations" << std::endl;
1438 
1439  // Begin loop over Reynolds number
1440  for(unsigned param=0;param<n_param_steps;param++)
1441  {
1442  // Set Re_current to the correct value
1443  if(lower==upper || n_param_steps<=1)
1444  {
1446  }
1447  else
1448  {
1450  lower + (((upper-lower)/(n_param_steps-1))*param);
1451  }
1452 
1453  // Set ReSt and ReInvFr to the correct values
1458 
1459  cout << "\n====================================================" << endl;
1460  cout << "Beginning parameter run " << param+1 << " of "
1461  << n_param_steps << ": Re = "
1463  cout << "====================================================" << endl;
1464 
1465  // Pass updated Reynolds number (and ReSt and ReInvFr) to elements
1466  problem.pass_updated_nondim_parameters_to_elements();
1467 
1468  // Reset the global time (of both problems!) to zero
1469  problem.reset_global_time_to_zero();
1470 
1471  // Initialise counter for solutions
1472  doc_info.number()=0;
1473 
1474  // Create trace files
1475  problem.create_trace_files(doc_info);
1476 
1477  // Initialise trace files
1478  problem.initialise_trace_files();
1479 
1480  // Output initial conditions
1481  problem.doc_solution(doc_info,false,false);
1482 
1483  // Increment counter for solutions
1484  doc_info.number()++;
1485 
1486  // Find steady base flow
1487  // ---------------------
1488 
1489  // Determine number of steps to take when ramping up to actual
1490  // Reynolds number
1491  const unsigned n_base_flow_continuation_steps = 1;
1492 
1493  // If we're on the first parameter, need to get to steady state by
1494  // continuation
1495  if(param==0)
1496  {
1497  cout << "\nEntering steady base flow loop..." << endl;
1498 
1499  // Store the current parameter value
1500  const double Re_current_backup = GlobalPhysicalVariables::Re_current;
1501 
1502  // Loop over continuation steps
1503  for(unsigned i=0;i<=n_base_flow_continuation_steps;i++)
1504  {
1505  // Update current parameters
1507  i*(Re_current_backup/n_base_flow_continuation_steps);
1512 
1513  cout << " - Setting GlobalPhysicalVariables::Re_current = "
1515 
1516  // Pass updated Reynolds number (and ReSt and ReInvFr) to elements
1517  problem.pass_updated_nondim_parameters_to_elements();
1518 
1519  // Perform a steady base flow solve
1520  problem.base_flow_steady_newton_solve();
1521  }
1522  }
1523  // Otherwise, just require one steady base flow solve
1524  else { problem.base_flow_steady_newton_solve(); }
1525 
1526  // Enable Jacobian reuse in the perturbed state problem. Note that this
1527  // can only be done since the problem is linear and the base state is
1528  // steady, and so the Jacobian will be the same at each timestep.
1529  // Calling this function also resets the
1530  // Problem::Jacobian_has_been_computed flag to "false", so that during
1531  // the first solve it will be recomputed. Note that this is the reason
1532  // that we call this function here rather than in the problem constructor.
1533  // Were we to call it in the constructor then the Jacobian would not be
1534  // recomputed when we changed the problem parameters (Reynolds number etc.)
1535  problem.perturbed_state_problem_pt()->enable_jacobian_reuse();
1536 
1537  // Perform power method and store number of iterations
1538  const unsigned n_power_method_iterations =
1539  problem.perform_power_method(dt,doc_info,power_method_tolerance,
1540  max_iter,eigenvalue,eigenvector);
1541 
1542  cout << "\nDominating eigenvalue is " << eigenvalue << endl;
1543 
1544  // The corresponding dominating eigenvector is "input"
1545 
1546  // Document in the global trace file
1547  global_trace << GlobalPhysicalVariables::Re_current << " ";
1548  ios_base::fmtflags flags = cout.flags(); // Save old flags
1549  global_trace.precision(14); // ten decimal places
1550  global_trace << eigenvalue << " ";
1551  global_trace.flags(flags); // Set the flags to the way they were
1552  global_trace << n_base_flow_continuation_steps << " "
1553  << n_power_method_iterations << std::endl;
1554 
1555  // The initial guess for the next power method will be the eigenvector
1556  // calculated by this power method
1557 
1558  // Clear and close trace files
1559  problem.close_trace_files();
1560 
1561  } // End loop over Reynolds number
1562  }
1563 
1564 } // End of main
int i
Definition: BiCGSTAB_step_by_step.cpp:9
Array< double, 1, 3 > e(1./3., 0.5, 2.)
Definition: demo_drivers/axisym_navier_stokes/counter_rotating_disks/multi_domain_linearised_axisym_navier_stokes_elements.h:186
Definition: demo_drivers/axisym_navier_stokes/counter_rotating_disks/multi_domain_linearised_axisym_navier_stokes_elements.h:54
Definition: axisym_navier_stokes/counter_rotating_disks/counter_rotating_disks.cc:702
Definition: axisym_navier_stokes_elements.h:1234
Definition: axisym_navier_stokes_elements.h:1532
Definition: oomph_utilities.h:499
std::string directory() const
Output directory.
Definition: oomph_utilities.h:524
void set_directory(const std::string &directory)
Definition: oomph_utilities.cc:298
unsigned & number()
Number used (e.g.) for labeling output files.
Definition: oomph_utilities.h:554
Definition: double_vector.h:58
void setup(Time *time_pt)
Create all GeomObjects needed to define the cylinder and the flag.
Definition: turek_flag_non_fsi.cc:277
double ReInvFr_current
Definition: linearised_axisym_navier_stokes/counter_rotating_disks/counter_rotating_disks.cc:72
double St
Strouhal number.
Definition: linearised_axisym_navier_stokes/counter_rotating_disks/counter_rotating_disks.cc:62
double Re_lower_limit
Loop information.
Definition: linearised_axisym_navier_stokes/counter_rotating_disks/counter_rotating_disks.cc:75
int k
Azimuthal mode number k in e^ik(theta) decomposition.
Definition: axisym_navier_stokes/counter_rotating_disks/counter_rotating_disks.cc:73
double Gamma
Aspect ratio (cylinder height / cylinder radius)
Definition: axisym_navier_stokes/counter_rotating_disks/counter_rotating_disks.cc:70
double InvFr
Inverse of Froude number.
Definition: linearised_axisym_navier_stokes/counter_rotating_disks/counter_rotating_disks.cc:65
double Re_current
Definition: linearised_axisym_navier_stokes/counter_rotating_disks/counter_rotating_disks.cc:70
Vector< double > G(3)
Direction of gravity.
double ReSt_current
Definition: linearised_axisym_navier_stokes/counter_rotating_disks/counter_rotating_disks.cc:71
double Re_upper_limit
Definition: linearised_axisym_navier_stokes/counter_rotating_disks/counter_rotating_disks.cc:76
unsigned Nparam_steps
Definition: linearised_axisym_navier_stokes/counter_rotating_disks/counter_rotating_disks.cc:77
string filename
Definition: MergeRestartFiles.py:39
std::string lower(std::string s)
returns the input string after converting upper-case characters to lower case
Definition: StringHelpers.cc:11
int Argc
Number of arguments + 1.
Definition: oomph_utilities.cc:407
Constructor for SteadyAxisymAdvectionDiffusion problem
Definition: steady_axisym_advection_diffusion.cc:213

References oomph::CommandLineArgs::Argc, oomph::DocInfo::directory(), e(), MergeRestartFiles::filename, GlobalPhysicalVariables::G, GlobalPhysicalVariables::Gamma, i, GlobalPhysicalVariables::InvFr, GlobalPhysicalVariables::k, helpers::lower(), GlobalPhysicalVariables::Nparam_steps, oomph::DocInfo::number(), problem, GlobalPhysicalVariables::Re_current, GlobalPhysicalVariables::Re_lower_limit, GlobalPhysicalVariables::Re_upper_limit, GlobalPhysicalVariables::ReInvFr_current, GlobalPhysicalVariables::ReSt_current, oomph::DocInfo::set_directory(), Flag_definition::setup(), and GlobalPhysicalVariables::St.