simple_segregated_driver.cc
Go to the documentation of this file.
1 //LIC// ====================================================================
2 //LIC// This file forms part of oomph-lib, the object-oriented,
3 //LIC// multi-physics finite-element library, available
4 //LIC// at http://www.oomph-lib.org.
5 //LIC//
6 //LIC// Version 1.0; svn revision $LastChangedRevision$
7 //LIC//
8 //LIC// $LastChangedDate$
9 //LIC//
10 //LIC// Copyright (C) 2006-2016 Matthias Heil and Andrew Hazel
11 //LIC//
12 //LIC// This library is free software; you can redistribute it and/or
13 //LIC// modify it under the terms of the GNU Lesser General Public
14 //LIC// License as published by the Free Software Foundation; either
15 //LIC// version 2.1 of the License, or (at your option) any later version.
16 //LIC//
17 //LIC// This library is distributed in the hope that it will be useful,
18 //LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
19 //LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 //LIC// Lesser General Public License for more details.
21 //LIC//
22 //LIC// You should have received a copy of the GNU Lesser General Public
23 //LIC// License along with this library; if not, write to the Free Software
24 //LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 //LIC// 02110-1301 USA.
26 //LIC//
27 //LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
28 //LIC//
29 //LIC//====================================================================
30 // Generic oomph-lib includes
31 #include "generic.h"
32 #include "navier_stokes.h"
33 #include "beam.h"
34 #include "multi_physics.h"
35 
36 // The wall mesh
37 #include "meshes/one_d_lagrangian_mesh.h"
38 
39 //Include the fluid mesh
40 #include "meshes/collapsible_channel_mesh.h"
41 
42 
43 using namespace std;
44 
45 using namespace oomph;
46 
47 
48 // Include the general-purpose fsi collapsible channel problem
49 #include "fsi_chan_problem.h"
50 
51 //====Namespace_for_flags================================
52 /// Extend namespace for control flags
53 //======================================================
54 namespace Flags
55 {
56 
57  /// Use Newton solver (0) or segregated solver (1)?
59 
60  /// Use pointwise Aitken extrapolation (1) or not (0)
62 
63  /// Under-relaxation parameter (1.0: no under-relaxation; 0.0: freeze)
64  double Omega_under_relax=1.0;
65 
66  /// Use Irons and Tuck extrapolation (1) or not (0)
68 
69  /// Convergence criterion: 0: global resmax; 1: abs. change; 2: rel. change
71 
72  /// Convergence tolerance
73  double Convergence_tolerance=1.0e-8;
74 
75 }
76 
77 
78 
79 ///////////////////////////////////////////////////////////////////////
80 ///////////////////////////////////////////////////////////////////////
81 ///////////////////////////////////////////////////////////////////////
82 
83 
84 
85 //====start_of_problem_class==========================================
86 /// Problem class -- add segregated solver capability to an existing
87 /// problem.
88 //====================================================================
89 template <class ELEMENT>
91  public virtual FSICollapsibleChannelProblem<ELEMENT>,
92  public virtual SegregatableFSIProblem
93 {
94 
95 public :
96 
97  /// \short Constructor: The arguments are the same as the original
98  /// (non-segregated) problem, namely, numbers of elements and lengths
99  /// of different sections of the domain.
100  SegregatedFSICollapsibleChannelProblem(const unsigned& nup,
101  const unsigned& ncollapsible,
102  const unsigned& ndown,
103  const unsigned& ny,
104  const double& lup,
105  const double& lcollapsible,
106  const double& ldown,
107  const double& ly,
108  const bool& displ_control,
109  const bool& steady_flag);
110 
111  /// Empty Destructor
113 
114 
115  /// \short Identify the fluid and solid Data and meshes that
116  /// contain only elements involved in the respective sub-problems.
117  /// This is a specific implementation of a pure virtual function in the
118  /// SegregatableFSIProblem base class.
119  void identify_fluid_and_solid_dofs(Vector<Data*>& fluid_data_pt,
120  Vector<Data*>& solid_data_pt,
121  Mesh*& fluid_mesh_pt,
122  Mesh*& solid_mesh_pt);
123 
124  // start_of_convergence_checks
125 
126  /// \short Update nodal positions in the fluid mesh in
127  /// response to changes in the wall displacement field after every
128  /// Newton step in a monolithic or segregated solid solve. Note
129  /// the use of the (protected) flag Solve_type, which can take the
130  /// values Full_solve, Fluid_solve or Solid_solve. This flag is used
131  /// to allow specification of different actions depending on the
132  /// precise solve taking place.
134  {
135  //For a "true" segregated solver, we would not do this in fluid or solid
136  //solves, but adding the bulk node update to the solid solve phase aids
137  //convergence and makes it possible for larger values of Q. Of course,
138  //there is a small cost associated with doing this.
139  if(Solve_type!=Fluid_solve) {this->Bulk_mesh_pt->node_update();}
140  }
141 
142 
143  /// Update nodal positions in the fluid mesh
144  /// in response to any changes in the wall displacement field after every
145  /// segregated solve. This is not strictly necessary because we
146  /// do the solid solve last, which performs its own node update before the
147  /// convergence check of the sub problem. It remains here because if we
148  /// were solving in a completely segregated fashion a node update would be
149  /// required for the fluid mesh in the final converged solution to be
150  /// consistent with the solid positions.
152  {
153  this->Bulk_mesh_pt->node_update();
154  }
155 
156  // end_of_convergence_checks
157 
158  /// Document the solution
159  void doc_solution(DocInfo& doc_info);
160 
161  /// Perform a steady run
162  void steady_run();
163 
164 };
165 
166 
167 //=====start_of_constructor======================================
168 /// Constructor for the collapsible channel problem
169 //===============================================================
170 template <class ELEMENT>
173  const unsigned& ncollapsible,
174  const unsigned& ndown,
175  const unsigned& ny,
176  const double& lup,
177  const double& lcollapsible,
178  const double& ldown,
179  const double& ly,
180  const bool& displ_control,
181  const bool& steady_flag) :
182  FSICollapsibleChannelProblem<ELEMENT>(nup,
183  ncollapsible,
184  ndown,
185  ny,
186  lup,
187  lcollapsible,
188  ldown,
189  ly,
190  displ_control,
191  steady_flag)
192 {
193  // Choose convergence criterion based on Flag::Convergence criterion
194  // with tolerance given by Flag::Convergence_tolerance
196  {
197  assess_convergence_based_on_max_global_residual(
199  }
200  else if (Flags::Convergence_criterion==1)
201  {
202  assess_convergence_based_on_absolute_solid_change(
204  }
205  else if (Flags::Convergence_criterion==2)
206  {
207  assess_convergence_based_on_relative_solid_change(
209  }
210 
211  //Select a convergence-acceleration technique based on control flags
212 
213  // Pointwise Aitken extrapolation
215  {
216  this->enable_pointwise_aitken();
217  }
218  else
219  {
220  this->disable_pointwise_aitken();
221  }
222 
223  // Under-relaxation
224  this->enable_under_relaxation(Flags::Omega_under_relax);
225 
226  // Irons and Tuck's extrapolation
228  {
229  this->enable_irons_and_tuck_extrapolation();
230  }
231  else
232  {
233  this->disable_irons_and_tuck_extrapolation();
234  }
235 
236 } //end_of_constructor
237 
238 
239 
240 //=====start_of_identify_fluid_and_solid======================================
241 /// Identify the fluid and solid Data and the meshes that
242 /// contain only elements that are involved in the respective sub-problems.
243 /// This implements a pure virtual function in the
244 /// SegregatableFSIProblem base class.
245 //============================================================================
246 template <class ELEMENT>
248 identify_fluid_and_solid_dofs(Vector<Data*>& fluid_data_pt,
249  Vector<Data*>& solid_data_pt,
250  Mesh*& fluid_mesh_pt,
251  Mesh*& solid_mesh_pt)
252 {
253 
254  //FLUID DATA:
255  //All fluid elements are stored in the Mesh addressed by bulk_mesh_pt()
256 
257  //Reset the storage
258  fluid_data_pt.clear();
259 
260  //Find number of fluid elements
261  unsigned n_fluid_elem=this->bulk_mesh_pt()->nelement();
262  //Loop over fluid elements and add internal data to fluid_data_ptt
263  for(unsigned e=0;e<n_fluid_elem;e++)
264  {
265  GeneralisedElement* el_pt=this->bulk_mesh_pt()->element_pt(e);
266  unsigned n_internal=el_pt->ninternal_data();
267  for(unsigned i=0;i<n_internal;i++)
268  {
269  fluid_data_pt.push_back(el_pt->internal_data_pt(i));
270  }
271  }
272 
273  //Find number of nodes in fluid mesh
274  unsigned n_fluid_node=this->bulk_mesh_pt()->nnode();
275  //Loop over nodes and add the nodal data to fluid_data_pt
276  for (unsigned n=0;n<n_fluid_node;n++)
277  {
278  fluid_data_pt.push_back(this->bulk_mesh_pt()->node_pt(n));
279  }
280 
281  // The bulk_mesh_pt() is a mesh that contains only fluid elements
282  fluid_mesh_pt = this->bulk_mesh_pt();
283 
284 
285  //SOLID DATA
286  //All solid elements are stored in the Mesh addressed by wall_mesh_pt()
287 
288  //Reset the storage
289  solid_data_pt.clear();
290 
291  //Find number of nodes in the solid mesh
292  unsigned n_solid_node=this->wall_mesh_pt()->nnode();
293  //Loop over nodes and add nodal position data to solid_data_pt
294  for(unsigned n=0;n<n_solid_node;n++)
295  {
296  solid_data_pt.push_back(
297  this->wall_mesh_pt()->node_pt(n)->variable_position_pt());
298  }
299 
300  //If we are using displacement control then the displacement control element
301  //and external pressure degree of freedom should be treated as part
302  //of the solid problem
303 
304  //We will assemble a single solid mesh from a vector of pointers to meshes
305  Vector<Mesh*> s_mesh_pt(1);
306  //The wall_mesh_pt() contains all solid elements and is the first
307  //entry in our vector
308  s_mesh_pt[0]=this->wall_mesh_pt();
309 
310  //If we are using displacement control
311  if (this->Displ_control)
312  {
313  //Add the external pressure data to solid_data_pt
314  solid_data_pt.push_back(Global_Physical_Variables::P_ext_data_pt);
315  //Add a pointer to a Mesh containing the displacement control element
316  //to the vector of pointers to meshes
317  s_mesh_pt.push_back(this->Displ_control_mesh_pt);
318  }
319 
320  // Build "combined" mesh from our vector of solid meshes
321  solid_mesh_pt = new Mesh(s_mesh_pt);
322 
323 } //end_of_identify_fluid_and_solid
324 
325 
326 //====start_of_doc_solution============================================
327 /// Document the solution
328 //============================================================================
329 template <class ELEMENT>
331  DocInfo& doc_info)
332 {
333  //Output stream filenames
334  ofstream some_file;
335  char filename[100];
336 
337  // Number of plot points
338  unsigned npts=5;
339 
340  // Output fluid solution
341  sprintf(filename,"%s/soln%i.dat",doc_info.directory().c_str(),
342  doc_info.number());
343  some_file.open(filename);
344  this->bulk_mesh_pt()->output(some_file,npts);
345  some_file.close();
346 
347  // Document the wall shape
348  sprintf(filename,"%s/beam%i.dat",doc_info.directory().c_str(),
349  doc_info.number());
350  some_file.open(filename);
351  this->wall_mesh_pt()->output(some_file,npts);
352  some_file.close();
353 
354 } // end_of_doc_solution
355 
356 
357 
358 //====steady_run==============================================================
359 /// Perform a steady run in which the external pressure
360 /// (or presribed displacement) is varied causing the channel to collapse.
361 //============================================================================
362 template <class ELEMENT>
364 {
365 
366  // Set initial value for external pressure (on the wall stiffness scale).
367  // This can be overwritten in set_initial_condition.
369  set_value(0,Global_Physical_Variables::Pmin);
370 
371  // Apply initial condition
373 
374  //Set output directory
375  DocInfo doc_info;
376  doc_info.set_directory("RESLT");
377 
378  // Output the initial solution
379  doc_solution(doc_info);
380 
381  // Increment step number
382  doc_info.number()++;
383 
384  // Increment for external pressure (on the wall stiffness scale)
385  double delta_p=(Global_Physical_Variables::Pmax-
387 
388  // Initial and final values for control position
390 
391  // Final value of prescribed displacement
392  double y_min=0.65;
393  //Change in y-coordinate to attain the minimum position in a given
394  //number of steps
395  double delta_y=(y_min-Global_Physical_Variables::Yprescr)/
396  double(Flags::Nsteps-1);
397 
398  // Parameter study (loop over the number of steps)
399  for (unsigned istep=0;istep<Flags::Nsteps;istep++)
400  {
401  // Setup segregated solver
402  //(Default behaviour will identify the fluid and solid dofs and
403  // allocate memory, etc every time. This is a bit inefficient in
404  // this case, but it is safe and will always work)
405  setup_segregated_solver();
406 
407  // SEGREGATED SOLVER
409  {
410  //Set the maximum number of Picard steps
411  Max_picard =50;
412 
413  // Solve ignoring return type (convergence data)
414  (void)steady_segregated_solve();
415  }
416  // NEWTON SOLVER
417  else
418  {
419  //Explit call to the steady Newton solve.
420  steady_newton_solve();
421  }
422 
423  // Output the solution
424  doc_solution(doc_info);
425 
426  //Increase the Step number
427  doc_info.number()++;
428 
429  // Adjust control parameters
430  //If displacment control increment position
431  if (this->Displ_control)
432  {
434  }
435  //Otherwise increment external pressure
436  else
437  {
438  double old_p=Global_Physical_Variables::P_ext_data_pt->value(0);
439  Global_Physical_Variables::P_ext_data_pt->set_value(0,old_p+delta_p);
440  }
441 
442  } // End of parameter study
443 
444 }
445 
446 //============start_of_main====================================================
447 /// Driver code for a segregated collapsible channel problem with FSI.
448 //=============================================================================
449 int main()
450 {
451  // Number of elements in the domain
452  unsigned nup=4*Flags::Resolution_factor;
453  unsigned ncollapsible=20*Flags::Resolution_factor;
454  unsigned ndown=40*Flags::Resolution_factor;
455  unsigned ny=4*Flags::Resolution_factor;
456 
457 
458  // Geometry of the domain
459  double lup=1.0;
460  double lcollapsible=5.0;
461  double ldown=10.0;
462  double ly=1.0;
463 
464  // Steady run by default
465  bool steady_flag=true;
466  // with displacement control
467  bool displ_control=true;
468 
469  // Build the problem with QTaylorHoodElements
471  <AlgebraicElement<QTaylorHoodElement<2> > >
472  problem(nup, ncollapsible, ndown, ny,
473  lup, lcollapsible, ldown, ly, displ_control,
474  steady_flag);
475 
476  //Perform a steady run
477  problem.steady_run();
478 
479 }//end of main
Extend namespace for control flags.
unsigned Nsteps
Number of steps in parameter study.
double Convergence_tolerance
Convergence tolerance.
OneDLagrangianMesh< FSIHermiteBeamElement > * wall_mesh_pt()
Access function for the wall mesh.
unsigned Use_pointwise_aitken
Use pointwise Aitken extrapolation (1) or not (0)
double Yprescr
Current prescribed vertical position of control point (only used for displacement control) ...
void set_initial_condition()
Apply initial conditions.
SegregatedFSICollapsibleChannelProblem(const unsigned &nup, const unsigned &ncollapsible, const unsigned &ndown, const unsigned &ny, const double &lup, const double &lcollapsible, const double &ldown, const double &ly, const bool &displ_control, const bool &steady_flag)
Constructor: The arguments are the same as the original (non-segregated) problem, namely...
void actions_before_newton_convergence_check()
Update nodal positions in the fluid mesh in response to changes in the wall displacement field after ...
double Pmax
Max. pressure. Only used in steady runs during parameter incrementation. Use 2.0 for Re=250; 3...
AlgebraicCollapsibleChannelMesh< ELEMENT > * bulk_mesh_pt()
Access function for the specific bulk (fluid) mesh.
double Omega_under_relax
Under-relaxation parameter (1.0: no under-relaxation; 0.0: freeze)
void identify_fluid_and_solid_dofs(Vector< Data *> &fluid_data_pt, Vector< Data *> &solid_data_pt, Mesh *&fluid_mesh_pt, Mesh *&solid_mesh_pt)
Identify the fluid and solid Data and meshes that contain only elements involved in the respective su...
double Pmin
Min. pressure. Only used in steady runs during parameter incrementation. Use 1.5 for values of Re to ...
unsigned Resolution_factor
Resolution factor (multiplier for number of elements across channel)
unsigned Convergence_criterion
Convergence criterion: 0: global resmax; 1: abs. change; 2: rel. change.
Data * P_ext_data_pt
Pointer to Data object that stores external pressure.
void doc_solution(DocInfo &doc_info)
Document the solution.
unsigned Use_irons_and_tuck_extrapolation
Use Irons and Tuck extrapolation (1) or not (0)
unsigned Use_segregated_solver
Use Newton solver (0) or segregated solver (1)?
Mesh * Displ_control_mesh_pt
Pointer to the mesh that contains the displacement control element.
bool Displ_control
Use displacement control?
int main()
Driver code for a segregated collapsible channel problem with FSI.