fsi_chan_problem.h
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-2022 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 
27 
28 
29 //====start_of_physical_parameters=====================
31 //======================================================
33 {
34 
36  double Re=250.0;
37 
39  double ReSt=250.0;
40 
42  double H=1.0e-2;
43 
45  double Sigma0=1.0e3;
46 
48  Data* P_ext_data_pt=0;
49 
53  double Pmin=1.5;
54 
58  double Pmax=2.0;
59 
62  double P_step=0.0;
63 
66  double Yprescr = 1.0;
67 
71  double Yprescr_min=0.6;
72 
76  void load(const Vector<double>& xi, const Vector<double>& x,
77  const Vector<double>& N, Vector<double>& load)
78  {
79  for(unsigned i=0;i<2;i++)
80  {
81  load[i] = -P_ext_data_pt->value(0)*N[i];
82  }
83  } //end of load
84 
85 
89  double Q=1.0e-2;
90 
91 
92 } // end of namespace
93 
94 
95 
99 
100 
101 
102 
103 //==========start_of_BL_Squash =========================================
106 //======================================================================
107 namespace BL_Squash
108 {
109 
111  double Delta=0.1;
112 
114  double Fract_in_BL=0.5;
115 
118  double squash_fct(const double& s)
119  {
120  // Default return
121  double y=s;
122  if (s<0.5*Fract_in_BL)
123  {
124  y=Delta*2.0*s/Fract_in_BL;
125  }
126  else if (s>1.0-0.5*Fract_in_BL)
127  {
128  y=2.0*Delta/Fract_in_BL*s+1.0-2.0*Delta/Fract_in_BL;
129  }
130  else
131  {
132  y=(1.0-2.0*Delta)/(1.0-Fract_in_BL)*s+
133  (Delta-0.5*Fract_in_BL)/(1.0-Fract_in_BL);
134  }
135 
136  return y;
137  }
138 }// end of BL_Squash
139 
140 
141 
142 
143 
144 
148 
149 
150 //====start_of_underformed_wall============================================
154 //=========================================================================
156 {
157 
158 public:
159 
162  UndeformedWall(const double& x0, const double& h): GeomObject(1,2)
163  {
164  X0=x0;
165  H=h;
166  }
167 
168 
170  void position(const Vector<double>& zeta, Vector<double>& r) const
171  {
172  // Position Vector
173  r[0] = zeta[0]+X0;
174  r[1] = H;
175  }
176 
177 
181  void position(const unsigned& t, const Vector<double>& zeta,
182  Vector<double>& r) const
183  {
184  // Use the steady version
185  position(zeta,r);
186 
187  } // end of position
188 
189 
195  virtual void d2position(const Vector<double>& zeta,
196  Vector<double>& r,
197  DenseMatrix<double> &drdzeta,
198  RankThreeTensor<double> &ddrdzeta) const
199  {
200  // Position vector
201  r[0] = zeta[0]+X0;
202  r[1] = H;
203 
204  // Tangent vector
205  drdzeta(0,0)=1.0;
206  drdzeta(0,1)=0.0;
207 
208  // Derivative of tangent vector
209  ddrdzeta(0,0,0)=0.0;
210  ddrdzeta(0,0,1)=0.0;
211 
212  } // end of d2position
213 
214 private :
215 
217  double X0;
218 
220  double H;
221 
222 }; //end_of_undeformed_wall
223 
224 
225 
226 
227 
228 
229 //====Namespace_for_flags================================
231 //======================================================
232 namespace Flags
233 {
234 
236  unsigned Resolution_factor=1;
237 
239  unsigned Use_displ_control=1;
240 
242  unsigned Steady_flag=1;
243 
245  unsigned Nsteps=5;
246 
249 
251  string Restart_file_name="";
252 
254  void doc_flags()
255  {
256 
257  std::cout << "\nFlags:\n"
258  << "======\n";
259 
260  std::cout << "-- Resolution factor: " << Resolution_factor << std::endl;
261 
262  if (Steady_flag)
263  {
264  std::cout << "-- Steady run " << std::endl;
265  if (Use_displ_control)
266  {
267  std::cout << "-- Using displacement control " << std::endl;
268  }
269  else
270  {
271  std::cout << "-- Not using displacement control " << std::endl;
272  }
273  }
274  else
275  {
276  std::cout << "-- Unsteady run " << std::endl;
277  if (Use_displ_control)
278  {
279  std::cout << "-- Not using displacement control (command line flag\n"
280  << " overwritten because it's an unsteady run!) "
281  << std::endl;
282  }
283  }
284 
285  std::cout << "-- Reynolds number: "
286  << Global_Physical_Variables::Re << std::endl;
287 
288  std::cout << "-- FSI parameter Q: "
289  << Global_Physical_Variables::Q << std::endl;
290 
291 
292  if (Restart_file_name!="")
293  {
294  std::cout << "-- Performing restart from: " << Restart_file_name
295  << std::endl;
296  std::cout << "-- Jump in pressure: " << Global_Physical_Variables::P_step
297  << std::endl;
298  }
299  else
300  {
301  std::cout << "-- No restart " << std::endl;
302  }
303  std::cout << std::endl;
304  }
305 
306 }
307 
308 
309 
310 //====start_of_problem_class==========================================
312 //====================================================================
313 template <class ELEMENT>
314 class FSICollapsibleChannelProblem : public virtual Problem
315 {
316 
317 public :
318 
321  FSICollapsibleChannelProblem(const unsigned& nup,
322  const unsigned& ncollapsible,
323  const unsigned& ndown,
324  const unsigned& ny,
325  const double& lup,
326  const double& lcollapsible,
327  const double& ldown,
328  const double& ly,
329  const bool& displ_control,
330  const bool& steady_flag);
331 
334  {
335  // Mesh gets killed in general problem destructor
336  }
337 
340  virtual void steady_run();
341 
344  virtual void unsteady_run(const double& dt=0.1);
345 
347  AlgebraicCollapsibleChannelMesh<ELEMENT>* bulk_mesh_pt()
348  {
349  // Upcast from pointer to the Mesh base class to the specific
350  // element type that we're using here.
351  return dynamic_cast<
352  AlgebraicCollapsibleChannelMesh<ELEMENT>*>
353  (Bulk_mesh_pt);
354  }
355 
357  OneDLagrangianMesh<FSIHermiteBeamElement>* wall_mesh_pt()
358  {
359  return Wall_mesh_pt;
360 
361  } // end of access to wall mesh
362 
363 
366  {
367  Newton_iter=0;
368  }
369 
372 
373 
378  {
379  // Update mesh
380  Bulk_mesh_pt->node_update();
381 
382  // Increment counter
383  Newton_iter++;
384  }
385 
386 
388  virtual void doc_solution_steady(DocInfo& doc_info, ofstream& trace_file,
389  const double& cpu, const unsigned &niter);
390 
392  virtual void doc_solution_unsteady(DocInfo& doc_info, ofstream& trace_file,
393  const double& cpu, const unsigned &niter);
394 
396  void set_initial_condition();
397 
398 
399  protected:
400 
402  void dump_it(ofstream& dump_file);
403 
405  void restart(ifstream& restart_file);
406 
408  unsigned Nup;
409 
412  unsigned Ncollapsible;
413 
415  unsigned Ndown;
416 
418  unsigned Ny;
419 
421  double Lup;
422 
424  double Lcollapsible;
425 
427  double Ldown;
428 
430  double Ly;
431 
433  AlgebraicCollapsibleChannelMesh<ELEMENT>* Bulk_mesh_pt;
434 
437 
440 
442  OneDLagrangianMesh<FSIHermiteBeamElement>* Wall_mesh_pt;
443 
446 
449 
452 
455 
458  GeomObject* Ctrl_geom_obj_pt;
459 
462  Vector<double> S_displ_ctrl;
463 
466  MeshAsGeomObject* Wall_geom_object_pt;
467 
469  unsigned Newton_iter;
470 
472  DocInfo Doc_info;
473 
474 };//end of problem class
475 
476 
477 
478 
479 //=====start_of_constructor======================================
481 //===============================================================
482 template <class ELEMENT>
484  const unsigned& nup,
485  const unsigned& ncollapsible,
486  const unsigned& ndown,
487  const unsigned& ny,
488  const double& lup,
489  const double& lcollapsible,
490  const double& ldown,
491  const double& ly,
492  const bool& displ_control,
493  const bool& steady_flag)
494 {
495 
496 
497  // Initialise number of Newton iterations
498  Newton_iter=0;
499 
500  // Store problem parameters
501  Nup=nup;
502  Ncollapsible=ncollapsible;
503  Ndown=ndown;
504  Ny=ny;
505  Lup=lup;
506  Lcollapsible=lcollapsible;
507  Ldown=ldown;
508  Ly=ly;
509  Steady_flag=steady_flag;
510 
511  // Displacement control only makes sense for steady problems
512  if (Steady_flag)
513  {
514  Displ_control=displ_control;
515  }
516  else
517  {
518  Displ_control=false;
519  if (displ_control)
520  {
521  std::cout << "Switched off displacement control for unsteady run!"
522  << std::endl;
523  }
524  }
525 
526 
527  // Overwrite maximum allowed residual to accomodate bad initial guesses
528  Problem::Max_residuals=1000.0;
529 
530  // Allocate the timestepper -- this constructs the Problem's
531  // time object with a sufficient amount of storage to store the
532  // previous timsteps. Note: This is appropriate even for
533  // the steady problem as we'll explicitly call the *steady*
534  // Newton solver which disables the timesteppers
535  // during the solve.
536  add_time_stepper_pt(new BDF<2>);
537 
538  // Create a dummy Steady timestepper that stores two history values
539  Steady<2>* wall_time_stepper_pt = new Steady<2>;
540 
541  // Add the wall timestepper to the Problem's collection of timesteppers.
542  add_time_stepper_pt(wall_time_stepper_pt);
543 
544  // Geometric object that represents the undeformed wall:
545  // A straight line at height y=ly; starting at x=lup.
546  UndeformedWall* undeformed_wall_pt=new UndeformedWall(lup,ly);
547 
548  //Create the "wall" mesh with FSI Hermite elements
549  Wall_mesh_pt = new OneDLagrangianMesh<FSIHermiteBeamElement>
550  (Ncollapsible,Lcollapsible,undeformed_wall_pt,wall_time_stepper_pt);
551 
552  // Build a geometric object (one Lagrangian, two Eulerian coordinates)
553  // from the wall mesh
554  Wall_geom_object_pt=
555  new MeshAsGeomObject(Wall_mesh_pt);
556 
557  // Get pointer to/local coordinate in wall geom object that contains
558  // control node -- adjusted for different values of Q, so that
559  // the point is located near the point of strongest collapse.
560  Vector<double> zeta_displ_ctrl(1);
561  zeta_displ_ctrl[0]=3.5;
562  if (std::abs(Global_Physical_Variables::Q-1.0e-3)<1.0e-10)
563  {
564  zeta_displ_ctrl[0]=3.0;
565  }
566  //if (std::abs(Global_Physical_Variables::Q-1.0e-4)<1.0e-10)
567  if (Global_Physical_Variables::Q<=1.0e-4)
568  {
569  zeta_displ_ctrl[0]=2.5;
570  }
571  std::cout << "Wall control point located at zeta=" <<zeta_displ_ctrl[0]
572  << std::endl;
573  S_displ_ctrl.resize(1);
574 
575  // Locate control point (pointer to GeomObject and local coordinate in it)
576  Wall_geom_object_pt->locate_zeta(zeta_displ_ctrl,
577  Ctrl_geom_obj_pt,
578  S_displ_ctrl);
579 
580 
581  // Normal load incrementation or unsteady run
582  //===========================================
583  Displ_control_mesh_pt=new Mesh;
584 
585  // Choose element in which displacement control is applied:
586  SolidFiniteElement* controlled_element_pt=
587  dynamic_cast<SolidFiniteElement*>(Ctrl_geom_obj_pt);
588 
589  // Fix the displacement in the vertical (1) direction...
590  unsigned controlled_direction=1;
591 
592  // Pointer to displacement control element
593  DisplacementControlElement* displ_control_el_pt;
594 
595  // Build displacement control element
596  displ_control_el_pt=
597  new DisplacementControlElement(controlled_element_pt,
598  S_displ_ctrl,
599  controlled_direction,
601 
602  // The constructor of the DisplacementControlElement has created
603  // a new Data object whose one-and-only value contains the
604  // adjustable load: Use this Data object in the load function:
605  Global_Physical_Variables::P_ext_data_pt=displ_control_el_pt->
606  displacement_control_load_pt();
607 
608  // Add the displacement-control element to its own mesh
609  Displ_control_mesh_pt->add_element_pt(displ_control_el_pt);
610 
611 
612  if (!Displ_control)
613  {
614  // Create Data object whose one-and-only value contains the
615  // (in principle) adjustable load
617 
618  //Pin the external pressure because it isn't actually adjustable.
620  }
621 
622  //Build bulk (fluid) mesh
623  Bulk_mesh_pt =
624  new AlgebraicCollapsibleChannelMesh<ELEMENT>
625  (nup, ncollapsible, ndown, ny,
626  lup, lcollapsible, ldown, ly,
627  Wall_geom_object_pt,
628  time_stepper_pt());
629 
630 
631  // Add the sub meshes to the problem
632  add_sub_mesh(Bulk_mesh_pt);
633  add_sub_mesh(Wall_mesh_pt);
634  add_sub_mesh(Displ_control_mesh_pt);
635 
636  // Combine all submeshes into a single Mesh
637  build_global_mesh();
638 
639 
640  // Complete build of fluid mesh
641  //-----------------------------
642 
643  // Loop over the elements to set up element-specific
644  // things that cannot be handled by constructor
645  unsigned n_element=Bulk_mesh_pt->nelement();
646  for(unsigned e=0;e<n_element;e++)
647  {
648  // Upcast from GeneralisedElement to the present element
649  ELEMENT* el_pt = dynamic_cast<ELEMENT*>(Bulk_mesh_pt->element_pt(e));
650 
651  //Set the Reynolds number
652  el_pt->re_pt() = &Global_Physical_Variables::Re;
653 
654  // Set the Womersley number
655  el_pt->re_st_pt() = &Global_Physical_Variables::ReSt;
656 
657  // Switch off mesh velocity in steady runs
658  if (Flags::Steady_flag)
659  {
660  el_pt->disable_ALE();
661  }
662  else
663  {
664  // Is element in rigid part?
665  bool is_in_rigid_part=true;
666 
667  // Number of nodes
668  unsigned nnod=el_pt->nnode();
669  for (unsigned j=0;j<nnod;j++)
670  {
671  double x=el_pt->node_pt(j)->x(0);
672  if ((x>=Lup)&&(x<=(Lup+Lcollapsible)))
673  {
674  is_in_rigid_part=false;
675  break;
676  }
677  }
678  if (is_in_rigid_part)
679  {
680  el_pt->disable_ALE();
681  }
682  }
683 
684  } // end loop over elements
685 
686 
687 
688  // Apply boundary conditions for fluid
689  //------------------------------------
690 
691  //Pin the velocity on the boundaries
692  //x and y-velocities pinned along boundary 0 (bottom boundary) :
693  unsigned ibound=0;
694  unsigned num_nod= bulk_mesh_pt()->nboundary_node(ibound);
695  for (unsigned inod=0;inod<num_nod;inod++)
696  {
697  for(unsigned i=0;i<2;i++)
698  {
699  bulk_mesh_pt()->boundary_node_pt(ibound, inod)->pin(i);
700  }
701  }
702 
703  //x and y-velocities pinned along boundaries 2, 3, 4 (top boundaries) :
704  for(ibound=2;ibound<5;ibound++)
705  {
706  num_nod= bulk_mesh_pt()->nboundary_node(ibound);
707  for (unsigned inod=0;inod<num_nod;inod++)
708  {
709  for(unsigned i=0;i<2;i++)
710  {
711  bulk_mesh_pt()->boundary_node_pt(ibound, inod)->pin(i);
712  }
713  }
714  }
715 
716  //y-velocity pinned along boundary 1 (right boundary):
717  ibound=1;
718  num_nod= bulk_mesh_pt()->nboundary_node(ibound);
719  for (unsigned inod=0;inod<num_nod;inod++)
720  {
721  bulk_mesh_pt()->boundary_node_pt(ibound, inod)->pin(1);
722  }
723 
724 
725  //Both velocities pinned along boundary 5 (left boundary):
726  ibound=5;
727  num_nod= bulk_mesh_pt()->nboundary_node(ibound);
728  for (unsigned inod=0;inod<num_nod;inod++)
729  {
730  bulk_mesh_pt()->boundary_node_pt(ibound, inod)->pin(0);
731  bulk_mesh_pt()->boundary_node_pt(ibound, inod)->pin(1);
732  }
733 //end of pin_velocity
734 
735 
736  // Complete build of wall elements
737  //--------------------------------
738 
739  //Loop over the elements to set physical parameters etc.
740  n_element = wall_mesh_pt()->nelement();
741  for(unsigned e=0;e<n_element;e++)
742  {
743  // Upcast to the specific element type
744  FSIHermiteBeamElement *elem_pt =
745  dynamic_cast<FSIHermiteBeamElement*>(wall_mesh_pt()->element_pt(e));
746 
747  // Set physical parameters for each element:
748  elem_pt->sigma0_pt() = &Global_Physical_Variables::Sigma0;
749  elem_pt->h_pt() = &Global_Physical_Variables::H;
750 
751  // Set the load vector for each element
752  elem_pt->load_vector_fct_pt() = &Global_Physical_Variables::load;
753 
754  // Function that specifies the load ratios
755  elem_pt->q_pt() = &Global_Physical_Variables::Q;
756 
757  // Set the undeformed shape for each element
758  elem_pt->undeformed_beam_pt() = undeformed_wall_pt;
759 
760  // The normal on the wall elements as computed by the FSIHermiteElements
761  // points away from the fluid rather than into the fluid (as assumed
762  // by default)
763  elem_pt->set_normal_pointing_out_of_fluid();
764 
765  // Displacement control? If so, the load on *all* elements
766  // is affected by an unknown -- the external pressure, stored
767  // as the one-and-only value in a Data object: Add it to the
768  // elements' external Data.
769  if (Displ_control)
770  {
771  //The external pressure is external data for all elements
772  elem_pt->add_external_data(Global_Physical_Variables::P_ext_data_pt);
773  }
774 
775 
776  } // end of loop over elements
777 
778 
779 
780  // Boundary conditions for wall mesh
781  //----------------------------------
782 
783  // Set the boundary conditions: Each end of the beam is fixed in space
784  // Loop over the boundaries (ends of the beam)
785  for(unsigned b=0;b<2;b++)
786  {
787  // Pin displacements in both x and y directions
788  wall_mesh_pt()->boundary_node_pt(b,0)->pin_position(0);
789  wall_mesh_pt()->boundary_node_pt(b,0)->pin_position(1);
790  }
791 
792 
793 
794  //Choose control nodes
795  //---------------------
796 
797  // Left boundary
798  ibound=5;
799  num_nod= bulk_mesh_pt()->nboundary_node(ibound);
800  unsigned control_nod=num_nod/2;
801  Left_node_pt= bulk_mesh_pt()->boundary_node_pt(ibound, control_nod);
802 
803  // Right boundary
804  ibound=1;
805  num_nod= bulk_mesh_pt()->nboundary_node(ibound);
806  control_nod=num_nod/2;
807  Right_node_pt= bulk_mesh_pt()->boundary_node_pt(ibound, control_nod);
808 
809 
810  // Set the pointer to the control node on the wall
811  num_nod= wall_mesh_pt()->nnode();
812  Wall_node_pt=wall_mesh_pt()->node_pt(Ncollapsible/2);
813 
814 
815 
816  // Setup FSI
817  //----------
818 
819  // The velocity of the fluid nodes on the wall (fluid mesh boundary 3)
820  // is set by the wall motion -- hence the no-slip condition must be
821  // re-applied whenever a node update is performed for these nodes.
822  // Such tasks may be performed automatically by the auxiliary node update
823  // function specified by a function pointer:
824  ibound=3;
825  num_nod= bulk_mesh_pt()->nboundary_node(ibound);
826  for (unsigned inod=0;inod<num_nod;inod++)
827  {
828  static_cast<AlgebraicNode*>(
829  bulk_mesh_pt()->boundary_node_pt(ibound, inod))->
830  set_auxiliary_node_update_fct_pt(
832  }
833 
834  // Work out which fluid dofs affect the residuals of the wall elements:
835  // We pass the boundary between the fluid and solid meshes and
836  // pointers to the meshes. The interaction boundary is boundary 3 of the
837  // 2D fluid mesh.
838  FSI_functions::setup_fluid_load_info_for_solid_elements<ELEMENT,2>
839  (this,3,Bulk_mesh_pt,Wall_mesh_pt);
840 
841  // Setup equation numbering scheme
842  cout <<"Total number of equations: " << assign_eqn_numbers() << std::endl;
843 
844 }//end of constructor
845 
846 
847 
848 //====start_of_doc_solution_steady============================================
850 //============================================================================
851 template <class ELEMENT>
854  DocInfo &doc_info,
855  ofstream& trace_file,
856  const double& cpu, const unsigned &niter)
857 {
858 
859  ofstream some_file;
860  char filename[100];
861 
862  // Number of plot points
863  unsigned npts;
864  npts=5;
865 
866  // Output fluid solution
867  sprintf(filename,"%s/soln%i.dat",Doc_info.directory().c_str(),
868  Doc_info.number());
869  some_file.open(filename);
870  bulk_mesh_pt()->output(some_file,npts);
871  some_file.close();
872 
873  // Document the wall shape
874  sprintf(filename,"%s/beam%i.dat",Doc_info.directory().c_str(),
875  Doc_info.number());
876  some_file.open(filename);
877  wall_mesh_pt()->output(some_file,npts);
878  some_file.close();
879 
880 // Write restart file
881  sprintf(filename,"%s/restart%i.dat",Doc_info.directory().c_str(),
882  Doc_info.number());
883  some_file.open(filename);
884  some_file.precision(16);
885  dump_it(some_file);
886  some_file.close();
887 
888  // Write trace file
889  trace_file << Global_Physical_Variables::P_ext_data_pt->value(0) << " ";
890  trace_file << Global_Physical_Variables::Yprescr << " ";
891 
892  // Write trace file
893  trace_file << Left_node_pt->value(0) << " "
894  << Right_node_pt->value(0) << " "
895  << cpu << " "
896  << Newton_iter << " "
897  << std::endl;
898 
899 
900 } // end_of_doc_solution_steady
901 
902 
903 
904 
905 
906 
907 
908 
909 //====start_of_doc_solution_unsteady==========================================
911 //============================================================================
912 template <class ELEMENT>
915  DocInfo& doc_info,
916  ofstream& trace_file,
917  const double& cpu,
918  const unsigned &niter)
919 {
920 
921  ofstream some_file;
922  char filename[100];
923 
924  // Number of plot points
925  unsigned npts;
926  npts=5;
927 
928  // Output fluid solution
929  sprintf(filename,"%s/soln%i.dat",Doc_info.directory().c_str(),
930  Doc_info.number());
931  some_file.open(filename);
932  bulk_mesh_pt()->output(some_file,npts);
933  some_file.close();
934 
935  // Document the wall shape
936  sprintf(filename,"%s/beam%i.dat",Doc_info.directory().c_str(),
937  Doc_info.number());
938  some_file.open(filename);
939  wall_mesh_pt()->output(some_file,npts);
940  some_file.close();
941 
942 // Write restart file
943  sprintf(filename,"%s/restart%i.dat",Doc_info.directory().c_str(),
944  Doc_info.number());
945  some_file.open(filename);
946  dump_it(some_file);
947  some_file.close();
948 
949  // Write trace file
950  trace_file << time_pt()->time() << " ";
951 
952  // Get/doc y-coordinate of control point
953  Vector<double> r(2);
954  Ctrl_geom_obj_pt->position(S_displ_ctrl,r);
955  trace_file << r[1] << " ";
956 
957  // Write trace file
958  trace_file << Left_node_pt->value(0) << " "
959  << Right_node_pt->value(0) << " "
960  << cpu << " "
961  << Newton_iter << " "
962  << std::endl;
963 
964 
965 } // end_of_doc_solution_steady
966 
967 
968 
969 
970 //=====start_of_dump_it===================================================
972 //========================================================================
973 template <class ELEMENT>
975 {
976 
977  // Number of submeshes must agree when dumping/restarting so
978  // temporarily add displacement control mesh back in before dumping...
979  if (!Displ_control)
980  {
981  flush_sub_meshes();
982  add_sub_mesh(Bulk_mesh_pt);
983  add_sub_mesh(Wall_mesh_pt);
984  add_sub_mesh(Displ_control_mesh_pt);
985  rebuild_global_mesh();
986  assign_eqn_numbers();
987  }
988 
989  // Write current external pressure
990  dump_file << Global_Physical_Variables::P_ext_data_pt->value(0)
991  << " # external pressure" << std::endl;
992 
993  // Call generic dump()
994  Problem::dump(dump_file);
995 
996  // ...strip displacement control mesh back out after dumping if
997  // we don't actually need it
998  if (!Displ_control)
999  {
1000  flush_sub_meshes();
1001  add_sub_mesh(Bulk_mesh_pt);
1002  add_sub_mesh(Wall_mesh_pt);
1003  rebuild_global_mesh();
1004  assign_eqn_numbers();
1005  }
1006 
1007 
1008 } // end of dump_it
1009 
1010 
1011 
1012 //=================start_of_restart=======================================
1014 //========================================================================
1015 template <class ELEMENT>
1017 {
1018 
1019 
1020 
1021 // Read external pressure
1022 
1023 // Read line up to termination sign
1024  string input_string;
1025  getline(restart_file,input_string,'#');
1026  restart_file.ignore(80,'\n');
1027 
1029  {
1030  std::cout
1031  << "Increasing external pressure from "
1032  << double(atof(input_string.c_str())) << " to "
1033  << double(atof(input_string.c_str()))+Global_Physical_Variables::P_step
1034  << std::endl;
1035  }
1036  else
1037  {
1038  std::cout << "Running with unchanged external pressure of "
1039  << double(atof(input_string.c_str())) << std::endl;
1040  }
1041 
1042  // Set external pressure
1044  set_value(0,double(atof(input_string.c_str()))+
1046 
1047  // Read the generic problem data from restart file
1048  Problem::read(restart_file);
1049 
1050  //Now update the position of the nodes to be consistent with
1051  //the possible precision loss caused by reading in the data from disk
1052  this->Bulk_mesh_pt->node_update();
1053 
1054  // Strip out displacement control mesh if we don't need it
1055  if (!Displ_control)
1056  {
1057  flush_sub_meshes();
1058  add_sub_mesh(Bulk_mesh_pt);
1059  add_sub_mesh(Wall_mesh_pt);
1060  rebuild_global_mesh();
1061  assign_eqn_numbers();
1062  }
1063 
1064 
1065 } // end of restart
1066 
1067 
1068 
1069 //====start_of_apply_initial_condition========================================
1071 //============================================================================
1072 template <class ELEMENT>
1074 {
1075 
1076  // Check that timestepper is from the BDF family
1077  if (!Steady_flag)
1078  {
1079  if (time_stepper_pt()->type()!="BDF")
1080  {
1081  std::ostringstream error_stream;
1082  error_stream << "Timestepper has to be from the BDF family!\n"
1083  << "You have specified a timestepper from the "
1084  << time_stepper_pt()->type() << " family" << std::endl;
1085 
1086  throw OomphLibError(error_stream.str(),
1089  }
1090  }
1091 
1092 
1093  // Pointer to restart file
1094  ifstream* restart_file_pt=0;
1095 
1096  // Restart?
1097  //---------
1098 
1099  if (Flags::Restart_file_name!="")
1100  {
1101  // Open restart file
1102  restart_file_pt= new ifstream(Flags::Restart_file_name.c_str(),
1103  ios_base::in);
1104  if (restart_file_pt!=0)
1105  {
1106  cout << "Have opened " << Flags::Restart_file_name <<
1107  " for restart. " << std::endl;
1108  restart(*restart_file_pt);
1109  return;
1110  }
1111  else
1112  {
1113  std::ostringstream error_stream;
1114  error_stream
1115  << "ERROR while trying to open " << Flags::Restart_file_name <<
1116  " for restart." << std::endl;
1117 
1118  throw OomphLibError(
1119  error_stream.str(),
1122  }
1123  }
1124 
1125 
1126  // No restart
1127  else
1128  {
1129  // Update the mesh
1130  bulk_mesh_pt()->node_update();
1131 
1132  // Loop over the nodes to set initial guess everywhere
1133  unsigned num_nod = bulk_mesh_pt()->nnode();
1134  for (unsigned n=0;n<num_nod;n++)
1135  {
1136  // Get nodal coordinates
1137  Vector<double> x(2);
1138  x[0]=bulk_mesh_pt()->node_pt(n)->x(0);
1139  x[1]=bulk_mesh_pt()->node_pt(n)->x(1);
1140 
1141  // Assign initial condition: Steady Poiseuille flow
1142  bulk_mesh_pt()->node_pt(n)->set_value(0,6.0*(x[1]/Ly)*(1.0-(x[1]/Ly)));
1143  bulk_mesh_pt()->node_pt(n)->set_value(1,0.0);
1144  }
1145 
1146  // Assign initial values for an impulsive start
1147  bulk_mesh_pt()->assign_initial_values_impulsive();
1148  }
1149 
1150 
1151 } // end of set_initial_condition
1152 
1153 
1154 
1155 
1156 //====steady_run==============================================================
1158 //============================================================================
1159 template <class ELEMENT>
1161 {
1162 
1163  // Set initial value for external pressure (on the wall stiffness scale).
1164  // This can be overwritten in set_initial_condition.
1166  set_value(0,Global_Physical_Variables::Pmin);
1167 
1168  // Apply initial condition
1169  set_initial_condition();
1170 
1171  //Set output directory
1172  Doc_info.set_directory("RESLT");
1173 
1174  // Open a trace file
1175  ofstream trace_file;
1176  char filename[100];
1177  sprintf(filename,"%s/trace.dat",Doc_info.directory().c_str());
1178  trace_file.open(filename);
1179 
1180  // Write trace file header
1181  trace_file << "VARIABLES=\"p<sub>ext</sub>\","
1182  << "\"y<sub>ctrl</sub>\",";
1183  trace_file << "\"u_1\","
1184  << "\"u_2\","
1185  << "\"CPU time for solve\","
1186  << "\"Number of Newton iterations\","
1187  << std::endl;
1188 
1189  trace_file << "ZONE T=\"";
1190  trace_file << "Re=" << Global_Physical_Variables::Re << ", ";
1191  trace_file << "Q=" << Global_Physical_Variables::Q << ", ";
1192  trace_file << "resolution factor: " << Flags::Resolution_factor << ". ";
1193  trace_file << Flags::Run_identifier_string << "\" ";
1194  trace_file << std::endl;
1195 
1196  // Output the initial solution (dummy for CPU time)
1197  doc_solution_steady(Doc_info,trace_file,0.0,0);
1198 
1199  // Increment step number
1200  Doc_info.number()++;
1201 
1202 
1203  // Increment for external pressure (on the wall stiffness scale)
1204  double delta_p=(Global_Physical_Variables::Pmax-
1206 
1207  // Initial and final values for control position
1209 
1210  // Steady run
1211  double delta_y=
1213  double(Flags::Nsteps-1);
1214 
1215 
1216  // Parameter study
1217  //----------------
1218  for (unsigned istep=0;istep<Flags::Nsteps;istep++)
1219  {
1220 
1221  // Displacement control?
1222  if (Displ_control)
1223  {
1224  std::cout << "Solving for control displ = "
1226  << std::endl;
1227  }
1228  else
1229  {
1230  std::cout << "Solving for p_ext = "
1232  << std::endl;
1233  }
1234 
1235  // Solve the problem
1236  //------------------
1237  clock_t t_start = clock();
1238 
1239  // Explit call to the steady Newton solve.
1240  steady_newton_solve();
1241 
1242  clock_t t_end= clock();
1243  double cpu=double(t_end-t_start)/CLOCKS_PER_SEC;
1244 
1245 
1246  // Outpt the solution
1247  //-------------------
1248  doc_solution_steady(Doc_info,trace_file,cpu,0);
1249 
1250  // Step number
1251  Doc_info.number()++;
1252 
1253  // Adjust control parameter
1254  if (Displ_control)
1255  {
1256  // Increment control position
1258  }
1259  else
1260  {
1261  // Increment external pressure
1262  double old_p=Global_Physical_Variables::P_ext_data_pt->value(0);
1263  Global_Physical_Variables::P_ext_data_pt->set_value(0,old_p+delta_p);
1264  }
1265 
1266  }
1267 
1268  // Close trace file.
1269  trace_file.close();
1270 
1271 }
1272 
1273 
1274 
1275 
1276 
1277 
1278 //====unsteady_run============================================================
1280 //============================================================================
1281 template <class ELEMENT>
1283 {
1284 
1285  // Set initial value for external pressure (on the wall stiffness scale).
1286  // Will be overwritten by restart data if a restart file (and pressure
1287  // jump) are specified
1289  set_value(0,Global_Physical_Variables::Pmax);
1290 
1291  // Initialise timestep -- also sets the weights for all timesteppers
1292  // in the problem.
1293  initialise_dt(dt);
1294 
1295  std::cout << "Pressure before set initial: "
1297  << std::endl;
1298 
1299  // Apply initial condition
1300  set_initial_condition();
1301 
1302  std::cout << "Pressure after set initial: "
1304  << std::endl;
1305 
1306  //Set output directory
1307  Doc_info.set_directory("RESLT");
1308 
1309  // Open a trace file
1310  ofstream trace_file;
1311  char filename[100];
1312  sprintf(filename,"%s/trace.dat",Doc_info.directory().c_str());
1313  trace_file.open(filename);
1314 
1315 
1316  // Write trace file header
1317  trace_file << "VARIABLES=\"time\","
1318  << "\"y<sub>ctrl</sub>\",";
1319  trace_file << "\"u_1\","
1320  << "\"u_2\","
1321  << "\"CPU time for solve\","
1322  << "\"Number of Newton iterations\""
1323  << std::endl;
1324 
1325  trace_file << "ZONE T=\"";
1326  trace_file << "Re=" << Global_Physical_Variables::Re << ", ";
1327  trace_file << "Q=" << Global_Physical_Variables::Q << ", ";
1328  trace_file << "resolution factor: " << Flags::Resolution_factor << ". ";
1329  trace_file << Flags::Run_identifier_string << "\" ";
1330  trace_file << std::endl;
1331 
1332  // Output the initial solution (dummy for CPU time)
1333  doc_solution_unsteady(Doc_info,trace_file,0.0,0);
1334 
1335  // Increment step number
1336  Doc_info.number()++;
1337 
1338  // Timestepping loop
1339  //------------------
1340  for (unsigned istep=0;istep<Flags::Nsteps;istep++)
1341  {
1342 
1343  // Solve the problem
1344  //------------------
1345  clock_t t_start = clock();
1346 
1347  // Explit call to the unsteady Newton solve.
1348  unsteady_newton_solve(dt);
1349 
1350  clock_t t_end= clock();
1351  double cpu=double(t_end-t_start)/CLOCKS_PER_SEC;
1352 
1353 
1354  // Output the solution
1355  //--------------------
1356  doc_solution_unsteady(Doc_info,trace_file,cpu,0);
1357 
1358  // Step number
1359  Doc_info.number()++;
1360 
1361  }
1362 
1363  // Close trace file.
1364  trace_file.close();
1365 
1366 }
1367 
1368 
AnnoyingScalar abs(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:135
int i
Definition: BiCGSTAB_step_by_step.cpp:9
const unsigned n
Definition: CG3DPackingUnitTest.cpp:11
Array< double, 1, 3 > e(1./3., 0.5, 2.)
Scalar * b
Definition: benchVecAdd.cpp:17
Problem class.
Definition: fsi_chan_problem.h:315
double Ldown
x-length in the downstream part of the channel
Definition: fsi_chan_problem.h:427
GeomObject * Ctrl_geom_obj_pt
Definition: fsi_chan_problem.h:458
Node * Left_node_pt
Pointer to the left control node.
Definition: fsi_chan_problem.h:445
Node * Right_node_pt
Pointer to right control node.
Definition: fsi_chan_problem.h:448
Vector< double > S_displ_ctrl
Definition: fsi_chan_problem.h:462
unsigned Nup
Number of elements in the x direction in the upstream part of the channel.
Definition: fsi_chan_problem.h:408
OneDLagrangianMesh< FSIHermiteBeamElement > * Wall_mesh_pt
Pointer to the "wall" mesh.
Definition: fsi_chan_problem.h:442
virtual void steady_run()
Steady run.
Definition: fsi_chan_problem.h:1160
void dump_it(ofstream &dump_file)
Dump problem to disk to allow for restart.
Definition: fsi_chan_problem.h:974
void restart(ifstream &restart_file)
Read problem for restart from specified restart file.
Definition: fsi_chan_problem.h:1016
DocInfo Doc_info
DocInfo object.
Definition: fsi_chan_problem.h:472
unsigned Ncollapsible
Definition: fsi_chan_problem.h:412
void actions_after_newton_solve()
Update the problem after solve (empty)
Definition: fsi_chan_problem.h:371
unsigned Ny
Number of elements across the channel.
Definition: fsi_chan_problem.h:418
unsigned Ndown
Number of elements in the x direction in the downstream part of the channel.
Definition: fsi_chan_problem.h:415
virtual void doc_solution_steady(DocInfo &doc_info, ofstream &trace_file, const double &cpu, const unsigned &niter)
Doc the steady solution.
Definition: fsi_chan_problem.h:853
unsigned Newton_iter
Counter for Newton iterations.
Definition: fsi_chan_problem.h:469
FSICollapsibleChannelProblem(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 for the collapsible channel problem.
Definition: fsi_chan_problem.h:483
double Lup
x-length in the upstream part of the channel
Definition: fsi_chan_problem.h:421
bool Steady_flag
Flag for steady run.
Definition: fsi_chan_problem.h:454
MeshAsGeomObject * Wall_geom_object_pt
Geometric object incarnation of the wall mesh.
Definition: fsi_chan_problem.h:466
AlgebraicCollapsibleChannelMesh< ELEMENT > * bulk_mesh_pt()
Access function for the specific bulk (fluid) mesh.
Definition: fsi_chan_problem.h:347
virtual void doc_solution_unsteady(DocInfo &doc_info, ofstream &trace_file, const double &cpu, const unsigned &niter)
Doc the unsteady solution.
Definition: fsi_chan_problem.h:914
~FSICollapsibleChannelProblem()
Destructor.
Definition: fsi_chan_problem.h:333
void actions_before_newton_convergence_check()
Definition: fsi_chan_problem.h:377
Mesh * Displ_control_mesh_pt
Pointer to the mesh that contains the displacement control element.
Definition: fsi_chan_problem.h:436
void actions_before_newton_solve()
Actions before solve. Reset counter for number of Newton iterations.
Definition: fsi_chan_problem.h:365
AlgebraicCollapsibleChannelMesh< ELEMENT > * Bulk_mesh_pt
Pointer to the "bulk" mesh.
Definition: fsi_chan_problem.h:433
Node * Wall_node_pt
Pointer to control node on the wall.
Definition: fsi_chan_problem.h:451
double Ly
Transverse length.
Definition: fsi_chan_problem.h:430
virtual void unsteady_run(const double &dt=0.1)
Unsteady run. Specify timestep or use default of 0.1.
Definition: fsi_chan_problem.h:1282
double Lcollapsible
x-length in the collapsible part of the channel
Definition: fsi_chan_problem.h:424
OneDLagrangianMesh< FSIHermiteBeamElement > * wall_mesh_pt()
Access function for the wall mesh.
Definition: fsi_chan_problem.h:357
bool Displ_control
Use displacement control?
Definition: fsi_chan_problem.h:439
void set_initial_condition()
Apply initial conditions.
Definition: fsi_chan_problem.h:1073
Definition: fsi_chan_problem.h:156
double H
Height of the undeformed wall above y=0.
Definition: fsi_chan_problem.h:220
virtual void d2position(const Vector< double > &zeta, Vector< double > &r, DenseMatrix< double > &drdzeta, RankThreeTensor< double > &ddrdzeta) const
Definition: fsi_chan_problem.h:195
double X0
x position of the undeformed beam's left end.
Definition: fsi_chan_problem.h:217
void position(const unsigned &t, const Vector< double > &zeta, Vector< double > &r) const
Definition: fsi_chan_problem.h:181
void position(const Vector< double > &zeta, Vector< double > &r) const
Position vector at Lagrangian coordinate zeta.
Definition: fsi_chan_problem.h:170
UndeformedWall(const double &x0, const double &h)
Definition: fsi_chan_problem.h:162
GeomObject()
Default constructor.
Definition: geom_objects.h:104
Problem()
Definition: problem.cc:69
Definition: restart2.cpp:8
@ N
Definition: constructor.cpp:22
Scalar * y
Definition: level1_cplx_impl.h:128
RealScalar s
Definition: level1_cplx_impl.h:130
Definition: fsi_chan_problem.h:108
double squash_fct(const double &s)
Definition: fsi_chan_problem.h:118
double Delta
Boundary layer width.
Definition: fsi_chan_problem.h:111
double Fract_in_BL
Fraction of points in boundary layer.
Definition: fsi_chan_problem.h:114
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE std::enable_if_t< PacketLoad, PacketType > read(const TensorMapper &tensorMapper, const StorageIndex &NCIndex, const StorageIndex &CIndex, const StorageIndex &ld)
read, a template function used for loading the data from global memory. This function is used to guar...
Definition: TensorContractionSycl.h:162
EIGEN_STRONG_INLINE const Eigen::CwiseBinaryOp< Eigen::internal::scalar_zeta_op< typename DerivedX::Scalar >, const DerivedX, const DerivedQ > zeta(const Eigen::ArrayBase< DerivedX > &x, const Eigen::ArrayBase< DerivedQ > &q)
Definition: SpecialFunctionsArrayAPI.h:152
Extend namespace for flags.
Definition: fsi_chan_precond_driver.cc:56
string Restart_file_name
Name of restart file.
Definition: fsi_chan_problem.h:251
string Run_identifier_string
String to identify the run type in trace file.
Definition: fsi_chan_problem.h:248
unsigned Resolution_factor
Resolution factor (multiplier for number of elements across channel)
Definition: fsi_chan_problem.h:236
unsigned Nsteps
Number of steps in parameter study.
Definition: fsi_chan_problem.h:245
unsigned Steady_flag
Steady run (1) or unsteady run (0)
Definition: fsi_chan_problem.h:242
void doc_flags()
Doc flags.
Definition: fsi_chan_problem.h:254
unsigned Use_displ_control
Use displacement control (1) or not (0)
Definition: fsi_chan_problem.h:239
unsigned Ny
Definition: structured_cubic_point_source.cc:115
DocInfo Doc_info
Helper for documenting.
Definition: extrude_triangle_generated_mesh.cc:57
double Ly
Length of domain in y direction.
Definition: periodic_load.cc:58
double Lup
upstream length
Definition: interaction/pseudo_solid_collapsible_tube/pseudo_solid_collapsible_tube.cc:347
double Ldown
downstream length
Definition: interaction/pseudo_solid_collapsible_tube/pseudo_solid_collapsible_tube.cc:350
Global variables.
Definition: TwenteMeshGluing.cpp:60
double ReSt
Womersley number.
Definition: rayleigh_instability.cc:56
void load(const Vector< double > &xi, const Vector< double > &x, const Vector< double > &N, Vector< double > &load)
Load function: Apply a constant external pressure to the beam.
Definition: tensioned_string.cc:52
double Pmax
Definition: fsi_chan_problem.h:58
double Sigma0
2nd Piola Kirchhoff pre-stress
Definition: tensioned_string.cc:46
double Q
Ratio of scales.
Definition: elastic_bretherton.cc:131
double P_step
Definition: fsi_chan_problem.h:62
double Re
Reynolds number.
Definition: fibre.cc:55
Data * P_ext_data_pt
Pointer to Data object that stores external pressure.
Definition: fsi_chan_problem.h:48
double Yprescr_min
Definition: fsi_chan_problem.h:71
double Pmin
Definition: fsi_chan_problem.h:53
double H
Nondim thickness.
Definition: steady_ring.cc:50
double Yprescr
Definition: fsi_chan_problem.h:66
Vector< double > x0(2, 0.0)
string filename
Definition: MergeRestartFiles.py:39
const double ly
Definition: ConstraintElementsUnitTest.cpp:34
const unsigned ny
Definition: ConstraintElementsUnitTest.cpp:31
r
Definition: UniformPSDSelfTest.py:20
type
Definition: compute_granudrum_aor.py:141
void apply_no_slip_on_moving_wall(Node *node_pt)
Definition: fsi.cc:48
list x
Definition: plotDoE.py:28
t
Definition: plotPSD.py:36
#define OOMPH_EXCEPTION_LOCATION
Definition: oomph_definitions.h:61
#define OOMPH_CURRENT_FUNCTION
Definition: oomph_definitions.h:86
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2