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