fsi.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// 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 #ifndef OOMPH_FSI_HEADER
31 #define OOMPH_FSI_HEADER
32 
33 // Config header generated by autoconfig
34 #ifdef HAVE_CONFIG_H
35  #include <oomph-lib-config.h>
36 #endif
37 
38 #include<algorithm>
39 
40 //oomph-lib headers
41 #include "elements.h"
42 #include "mesh.h"
43 #include "geom_objects.h"
45 #include "integral.h"
46 #include "problem.h"
47 #include "multi_domain.template.cc"
48 
49 namespace oomph
50 {
51 
52 class AlgebraicNode;
53 
54 
55 ////////////////////////////////////////////////////////////////////////////
56 ////////////////////////////////////////////////////////////////////////////
57 // FSIFluidElement
58 ////////////////////////////////////////////////////////////////////////////
59 ////////////////////////////////////////////////////////////////////////////
60 
61 
62 //=========================================================================
63 /// \short The FSIFluidElement class is a base class for all
64 /// fluid finite elements that apply a load (traction) onto an adjacent
65 /// SolidFiniteElement.
66 //=========================================================================
67 class FSIFluidElement : public virtual FiniteElement
68 {
69 
70  public:
71 
72  /// Constructor
74 
75 
76  /// Broken copy constructor
78  {
79  BrokenCopy::broken_copy("FSIFluidElement");
80  }
81 
82  /// Broken assignment operator
83  void operator=(const FSIFluidElement&)
84  {
85  BrokenCopy::broken_assign("FSIFluidElement");
86  }
87 
88  /// \short Compute the load vector that is applied by current
89  /// element (at its local coordinate s) onto the adjacent
90  /// SolidElement. N is the outer unit normal on the FSIFluidElement.
91  virtual void get_load(const Vector<double> &s,
92  const Vector<double> &N,
93  Vector<double> &load)=0;
94 
95 
96  /// \short Add to the set \c paired_load_data pairs containing
97  /// - the pointer to a Data object
98  /// and
99  /// - the index of the value in that Data object
100  /// .
101  /// for all values (pressures, velocities) that affect the
102  /// load computed in the \c get_load(...) function.
103  virtual void identify_load_data(std::set<std::pair<Data*,unsigned> >&
104  paired_load_data)=0;
105 
106  /// \short Add to the set \c paired_pressure_data pairs containing
107  /// - the pointer to a Data object
108  /// and
109  /// - the index of the value in that Data object
110  /// .
111  /// for all pressure values that affect the load
112  /// computed in the \c get_load(...) function.
113  virtual void identify_pressure_data(std::set<std::pair<Data*,unsigned> >&
114  paired_pressure_data)=0;
115 
116 
117 };
118 
119 
120 
121 /////////////////////////////////////////////////////////////////////////////
122 /////////////////////////////////////////////////////////////////////////////
123 /////////////////////////////////////////////////////////////////////////////
124 
125 
126 
127 
128 //=========================================================================
129 /// \short This is a base class for all SolidFiniteElements
130 /// that participate in FSI computations. These elements
131 /// provide interfaces and generic funcionality for
132 /// the two additional roles that SolidFiniteElements play
133 /// in FSI problems:
134 /// -# They parameterise the domain boundary for the fluid domain.
135 /// To allow them to play this role, FSIWallElements are derived
136 /// from the SolidFiniteElement and the GeomObject class,
137 /// indicating that the every specific FSIWallElement must
138 /// implement the pure virtual function GeomObject::position(...)
139 /// which should compute the position vector to a point in the
140 /// SolidFiniteElement, parametrised by its local coordinates.
141 /// -# In FSI problems fluid exerts a traction onto the wall and this traction
142 /// must be added to any other load terms (such as an external pressure
143 /// acting on an elastic pipe) that are already applied to
144 /// the SolidFiniteElements by other means.
145 /// .
146 ///
147 /// The fluid-traction on the SolidFiniteElements
148 /// depends on the fluid variables (velocities and pressures) in
149 /// those fluid elements that are adjacent to the SolidFiniteElements'
150 /// Gauss points. In an FSI problem these velocities and pressures
151 /// are unknowns in the overall problem and the dependency of the
152 /// SolidFiniteElement's residual vector on these
153 /// unknowns must be taken into account when computing the element's
154 /// Jacobian matrix.
155 ///
156 /// For each Gauss point in the FSIWallElement, we therefore store:
157 /// - [a] pointer[s] to the FSIFluidElement[s] that is [are] "adjacent"
158 /// to the Gauss point in the FSIWallElement.
159 /// - the vector[s] of the local coordinates (in the fluid element[s])
160 /// that identify the point in the fluid element that is
161 /// (deemed to be) "opposite" that Gauss point. (Note
162 /// that we do not require the discretisations of the
163 /// fluid and solid domains to match exactly, therefore,
164 /// small "gaps" may occur between fluid and solid elements.)
165 /// .
166 ///
167 /// By default, each FSIWallElement is assumed to be exposed to fluid
168 /// loading only on one of its faces. For elements that are immersed
169 /// into fluid, so that a fluid traction is "exerted from both sides",
170 /// the element can store pointers to multiple adjacent fluid elements
171 /// (and local coordindates in these). This capability must be enabled
172 /// by a call to FSIWallElement::enable_fluid_loading_on_both_sides().
173 ///
174 /// Since the fluid traction can involve derivatives
175 /// of the velocity (think of Newtonian fluids), the traction is
176 /// also affected by changes in the nodal positions of the adjacent fluid
177 /// elements. Since fluid and solid discretisations are not
178 /// required to match, the nodal positions in an adjacent fluid
179 /// element can be affected by the positional variables in
180 /// another FSIWallElement. To capture this influence, we
181 /// provide the function FSIWallElement::node_update_adjacent_fluid_elements()
182 /// which does exactly what it says....
183 ///
184 /// Finally, since oomph-lib's fluid and solid
185 /// elements tend to employ different non-dimensionalisations
186 /// for the stresses, the fluid traction (computed by
187 /// the adjacent fluid element, on the fluid stress-scale) may have to be
188 /// scaled by the ratio \f$ Q \f$ of the stresses used to non-dimensionalise
189 /// the two sets of stresses. For instance, for a fluid stress
190 /// non-dimensionalisation based on the viscous scale \f$ \mu U / L\f$
191 /// (as in oomph-lib's Navier-Stokes elements) and a non-dimensionalisation
192 /// of the solid mechanics stresses, based on a Young's modulus \f$ E \f$,
193 /// as in oomph-lib's KirchhoffLoveBeamElements, the stress ratio is given
194 /// by
195 /// \f[ Q=\frac{\mu U}{LE} \f]
196 /// For other wall/fluid element combinations the definition of \f$ Q \f$
197 /// will differ -- check the documentation and/or implementation to see
198 /// which parameters are used to non-dimensionalise the stresses
199 /// in the respective elements!
200 ///
201 /// The function FSIWallElement::fluid_load_vector(...) computes
202 /// the fluid traction on the wall on the wall stress-scale.
203 /// This function may be called in the get_load (say) function of
204 /// a specific FSIWallElement to add the fluid load to the
205 /// other tractions that may already be applied to the element by other
206 /// means. By default a stress-ratio of \f$ Q = 1 \f$ is used
207 /// but this may be overwritten with the
208 /// access function FSIWallElement::q_pt().
209 //=========================================================================
210 class FSIWallElement : public virtual SolidFiniteElement,
211  public virtual ElementWithExternalElement
212 {
213 
214  public:
215 
216  /// \short Function to describe the local dofs of the element. The ostream
217  /// specifies the output stream to which the description
218  /// is written; the string stores the currently
219  /// assembled output that is ultimately written to the
220  /// output stream by Data::describe_dofs(...); it is typically
221  /// built up incrementally as we descend through the
222  /// call hierarchy of this function when called from
223  /// Problem::describe_dofs(...)
224  void describe_local_dofs(std::ostream& out,
225  const std::string& current_string) const;
226 
227  /// Static flag that allows the suppression of warning messages
229 
230  /// \short Constructor. Note that element is not fully-functional
231  /// until its setup_fsi_wall_element() function has been called!
232  FSIWallElement() : Only_front_is_loaded_by_fluid(true),
233  Q_pt(&Default_Q_Value), Ignore_shear_stress_in_jacobian(false) {}
234 
235  /// Broken copy constructor
237  {
238  BrokenCopy::broken_copy("FSIWallElement");
239  }
240 
241  /// Broken assignment operator
242  void operator=(const FSIWallElement&)
243  {
244  BrokenCopy::broken_assign("FSIWallElement");
245  }
246 
247  /// Empty virtual destructor for safety
248  virtual ~FSIWallElement() {}
249 
250  /// \short Setup: Assign storage -- pass the Eulerian
251  /// dimension of the "adjacent" fluid elements and the
252  /// number of local coordinates required to parametrise
253  /// the wall element. E.g. for a FSIKirchhoffLoveBeam,
254  /// bounding a 2D fluid domain ndim_fluid=2 and nlagr_solid=1
255  void setup_fsi_wall_element(const unsigned& nlagr_solid,
256  const unsigned& ndim_fluid);
257 
258  /// \short Return the ratio of the stress scales used to non-dimensionalise
259  /// the fluid and solid equations. E.g. \f$ Q = \mu U/(LE) \f$
260  /// if the fluid mechanics stresses (pressures) are scaled on the
261  /// viscous scale \f$ \mu U / L\f$ and the solid mechanics stresses
262  /// on the solid's Young's modulus \f$ E \f$.
263  const double &q() const {return *Q_pt;}
264 
265  /// \short Return a pointer the ratio of stress scales used to
266  /// non-dimensionalise the fluid and solid equations.
267  double* &q_pt() {return Q_pt;}
268 
269 
270  /// \short Allow element to be loaded by fluid on both
271  /// sides. (Resizes containers for lookup schemes and initialises
272  /// data associated with elements at the "back" of the FSIWallElement
273  /// to NULL.
274  void enable_fluid_loading_on_both_sides();
275 
276 
277  /// \short Is the element exposed to (and hence loaded by)
278  /// fluid only on its "front"? True by default. This flag is set to
279  /// false if the FSIWallElement is immersed in fluid in which case
280  /// each integration point is loaded by two adjacent
281  /// fluid elements, one at the "front" and one at the "back".
282  /// This is a read-only function -- the ability have loading
283  /// from both sides must be enabled by a call to
284  /// FSIWallElement::enable_fluid_loading_on_both_sides();
286  {return Only_front_is_loaded_by_fluid;}
287 
288 
289  /// \short Do not include any external data that affects the load
290  /// in the computation of element's Jacobian matrix. This
291  /// functionality is provided to allow the "user" to deem the coupling
292  /// to the fluid equations to be
293  /// irrelevant and to facilitate the solution of a auxiliary solids-only
294  /// problems, e.g. during the assignment of initial conditions
295  /// for a time-dependent FSI problem.
296  void exclude_external_load_data() {Add_external_interaction_data=false;}
297 
298 
299  /// \short Include all external fluid data that affects the load in the
300  /// computation of the element's Jacobian matrix
302  {
303  Add_external_interaction_data=true;
304  Ignore_shear_stress_in_jacobian=false;
305  }
306 
307  /// \short Call this function to ignore shear stress component
308  /// of load when calculating the Jacobian, i.e. to ignore
309  /// fluid velocity Data in the FSIFluidElement and "far away"
310  /// geometric Data that affects nodal positions in the FSIFluidElement,
311  /// also to bypass node updates in the FSIFluidElement.
312  /// This functionality is provided to allow the user to deem the coupling
313  /// to the shear stress component of the fluid equations to be irrelevant.
315  {Ignore_shear_stress_in_jacobian=true; }
316 
317  /// Call thi function to re-enable calculation of the shear stress
318  /// componnent of load when calculating the Jacobian (the default)
320  {Ignore_shear_stress_in_jacobian=false; }
321 
322  /// \short Update the nodal positions in all fluid elements that affect
323  /// the traction on this FSIWallElement
324  void node_update_adjacent_fluid_elements();
325 
326 
327  /// Fill in the element's contribution to the Jacobian matrix
328  /// and the residual vector: Done by finite differencing the
329  /// residual vector w.r.t. all nodal, internal, external and load Data.
331  DenseMatrix<double> &jacobian)
332  {
333  //Add the contribution to the residuals
335 
336  //Solve for the consistent acceleraction in the Newmark scheme
337  if(Solve_for_consistent_newmark_accel_flag)
338  {
339  fill_in_jacobian_for_newmark_accel(jacobian);
340  return;
341  }
342 
343  //Allocate storage for the full residuals (residuals of the entire element)
344  Vector<double> full_residuals(this->ndof());
345  //Get the residuals for the entire element
346  get_residuals(full_residuals);
347  //Add the internal and external by finite differences
348  fill_in_jacobian_from_internal_by_fd(full_residuals,jacobian);
349  fill_in_jacobian_from_external_by_fd(full_residuals,jacobian);
350  fill_in_jacobian_from_nodal_by_fd(full_residuals,jacobian);
351  fill_in_jacobian_from_solid_position_by_fd(jacobian);
352  fill_in_jacobian_from_external_interaction_by_fd(full_residuals,jacobian);
353  }
354 
355  protected:
356 
357  /// \short After an internal data change, update the nodal positions
358  inline void update_in_internal_fd(const unsigned &i)
359  {
360  if (!Ignore_shear_stress_in_jacobian)
361  {
362  node_update_adjacent_fluid_elements();
363  }
364  }
365 
366  //Do nothing
367  inline void reset_in_internal_fd(const unsigned &i) { }
368 
369  //After all internal stuff reset
370  inline void reset_after_internal_fd()
371  {
372  if (!Ignore_shear_stress_in_jacobian)
373  {
374  node_update_adjacent_fluid_elements();
375  }
376  }
377 
378 
379  /// \short After an external data change, update the nodal positions
380  inline void update_in_external_fd(const unsigned &i)
381  {
382  if (!Ignore_shear_stress_in_jacobian)
383  {
384  node_update_adjacent_fluid_elements();
385  }
386  }
387 
388  //Do nothing
389  inline void reset_in_external_fd(const unsigned &i) { }
390 
391  //After all external stuff reset
392  inline void reset_after_external_fd()
393  {
394  if (!Ignore_shear_stress_in_jacobian)
395  {
396  node_update_adjacent_fluid_elements();
397  }
398  }
399 
400 
401  /// \short After a nodal data change, update the nodal positions
402  inline void update_in_nodal_fd(const unsigned &i)
403  {
404  if (!Ignore_shear_stress_in_jacobian)
405  {
406  node_update_adjacent_fluid_elements();
407  }
408  }
409 
410  //Do nothing
411  inline void reset_in_nodal_fd(const unsigned &i) { }
412 
413  //After all nodal stuff reset
414  inline void reset_after_nodal_fd()
415  {
416  if (!Ignore_shear_stress_in_jacobian)
417  {
418  node_update_adjacent_fluid_elements();
419  }
420  }
421 
422  /// \short After an external field data change, update the nodal positions
423  inline void update_in_external_interaction_field_fd(const unsigned &i)
424  {
425  if (!Ignore_shear_stress_in_jacobian)
426  {
427  node_update_adjacent_fluid_elements();
428  }
429  }
430 
431  //Do nothing
432  inline void reset_in_external_interaction_field_fd(const unsigned &i) { }
433 
434  //After all external field stuff reset
436  {
437  if (!Ignore_shear_stress_in_jacobian)
438  {
439  node_update_adjacent_fluid_elements();
440  }
441  }
442 
443 
444  /// \short After an external geometric data change, update the nodal positions
445  inline void update_in_external_interaction_geometric_fd(const unsigned &i)
446  {
447  if (!Ignore_shear_stress_in_jacobian)
448  {
449  node_update_adjacent_fluid_elements();
450  }
451  }
452 
453  //Do nothing
454  inline void reset_in_external_interaction_geometric_fd(const unsigned &i) { }
455 
456  //After all external geometric stuff reset
458  {
459  if (!Ignore_shear_stress_in_jacobian)
460  {
461  node_update_adjacent_fluid_elements();
462  }
463  }
464 
465 
466  /// \short After an internal data change, update the nodal positions
467  inline void update_in_solid_position_fd(const unsigned &i)
468  {
469  if (!Ignore_shear_stress_in_jacobian)
470  {
471  node_update_adjacent_fluid_elements();
472  }
473  }
474 
475  //Do nothing
476  inline void reset_in_solid_position_fd(const unsigned &i) { }
477 
478  //After all internal stuff reset
480  {
481  if (!Ignore_shear_stress_in_jacobian)
482  {
483  node_update_adjacent_fluid_elements();
484  }
485  }
486 
487 
488  /// \short Get FE Jacobian by systematic finite differencing w.r.t.
489  /// nodal positition Data, internal and external Data and any
490  /// load Data that is not included in the previous categories.
491  /// This is a re-implementation of the generic FD routines with
492  /// they key difference being that any updates of values are followed
493  /// by a node update in the adjacent fluid elements since their
494  /// position (and hence the shear stresses they exert onto the solid)
495  /// may be indirectly affected by these. For greater efficiency
496  /// this may be overloaded in derived classes, e.g. if it is known
497  /// that for a specific FSIWallElement, the internal Data does not
498  /// affect the nodal positions in adjacent fluid elements.
499  //void fill_in_jacobian_from_solid_position_and_external_by_fd(
500  // DenseMatrix<double>& jacobian);
501 
502 
503  /// \short Get the contribution to the load vector provided by
504  /// the adjacent fluid element: Pass number of integration point
505  /// in solid element, and the unit normal vector (pointing into the fluid!)
506  /// and return the load vector.
507  /// Note that the load is non-dimensionalised on the wall-stress scale,
508  /// i.e. it is obtained by computing the traction (on the fluid stress-scale)
509  /// from the adjacent fluid element and then multiplying it by
510  /// the stress-scale-ratio \f$ Q. \f$.
511  void fluid_load_vector(const unsigned& intpt,
512  const Vector<double>& N,
513  Vector<double>& load);
514 
515 
516  private:
517 
518  /// \short Overload the function that must return all field data involved
519  /// in the interactions from the external (fluid) element. It allows
520  /// the velocity degrees of freedom to be ignored if we want to
521  /// ignore the shear stresses when computing the Jacobian.
522  void identify_all_field_data_for_external_interaction(
523  Vector<std::set<FiniteElement*> > const &external_elements_pt,
524  std::set<std::pair<Data*,unsigned> > &paired_iteraction_data);
525 
526  /// \short Function that must return all geometric data involved
527  /// in the desired interactions from the external element
528  void identify_all_geometric_data_for_external_interaction(
529  Vector<std::set<FiniteElement*> > const &external_elements_pt,
530  std::set<Data*> &external_geometric_data_pt);
531 
532  /// \short Static default value for the ratio of stress scales
533  /// used in the fluid and solid equations (default is 1.0)
534  static double Default_Q_Value;
535 
536  /// \short Is the element exposed to (and hence loaded by)
537  /// fluid only on its "front"? True by default. This flag is set to
538  /// false if the FSIWallElement is immersed in fluid in which case
539  /// each integration point is loaded by two adjacent
540  /// fluid elements, one at the "front" and one at the "back".
542 
543  /// \short Pointer to the ratio, \f$ Q \f$ , of the stress used to
544  /// non-dimensionalise the fluid stresses to the stress used to
545  /// non-dimensionalise the solid stresses.
546  double *Q_pt;
547 
548  /// \short Set this flag to true to ignore shear stress component
549  /// of load when calculating the Jacobian, i.e. to ignore
550  /// fluid velocity Data in the FSIFluidElement and "far away"
551  /// geometric Data that affects nodal positions in the FSIFluidElement,
552  /// also to bypass node updates in the FSIFluidElement.
554 
555 
556 };
557 
558 
559 ////////////////////////////////////////////////////////////////////////
560 ////////////////////////////////////////////////////////////////////////
561 ////////////////////////////////////////////////////////////////////////
562 
563 
564 
565 
566 //======================================================================
567 // Namespace for "global" FSI functions
568 //======================================================================
569 namespace FSI_functions
570 {
571 
572  //============================================================================
573  /// \short Apply no-slip condition for N.St. on a moving wall node,
574  /// u = St dR/dt, where the Strouhal number St = a/(UT) is defined by
575  /// FSI_functions::Strouhal_for_no_slip and is initialised to 1.0.
576  /// Note: This requires the x,y,[z] velocity components to be stored
577  /// in nodal values 0,1,[2]. This is the default for all currently
578  /// existing Navier-Stokes elements. If you use any others,
579  /// use this function at your own risk.
580  //============================================================================
582 
583 
584  //============================================================================
585  /// \short Strouhal number St = a/(UT) for application of no slip condition.
586  /// Initialised to 1.0.
587  //============================================================================
588  extern double Strouhal_for_no_slip;
589 
590 
591  //============================================================================
592  /// \short Set up the information that the FSIWallElements
593  /// in the specified solid mesh require to obtain the fluid loading from the
594  /// adjacent fluid elements in the specified fluid mesh.
595  /// The parameter b specifies the boundary in the fluid mesh
596  /// that is adjacent to the solid mesh. The template parameters
597  /// specify the type of the fluid element and their spatial
598  /// dimension. The optional final argument, face, identifies the
599  /// face of the FSIWallElements that is exposed to the fluid. face
600  /// defaults to 0, indicating that the front is loaded along the
601  /// specified fluid mesh boundary. Set it to 1 to set up the FSI lookup
602  /// schemes for fluid loading along the "back" of the FSIWallElements.
603  /// This routine uses the procedures in the Multi_domain_functions namespace
604  /// to set up the interaction by locating the adjacent (source) elements
605  /// for each integration point of each solid element
606  ///
607  /// This is the vector based version it works simultaneously on
608  /// fluid fsi boundaries identified in the vector boundary_in_fluid_mesh
609  /// and the corresponding solid meshes in solid_mesh_pt.
610  //============================================================================
611  template<class FLUID_ELEMENT, unsigned DIM_FLUID>
613  Problem* problem_pt,
614  Vector<unsigned>& boundary_in_fluid_mesh,
615  Mesh* const &fluid_mesh_pt,
616  Vector<Mesh*>& solid_mesh_pt,
617  const unsigned& face=0)
618  {
619  // Thin wrapper to multi-domain function
621  <FLUID_ELEMENT, DIM_FLUID>(problem_pt,
622  boundary_in_fluid_mesh,
623  fluid_mesh_pt,
624  solid_mesh_pt,
625  face);
626  }
627 
628  //============================================================================
629  /// \short Set up the information that the FSIWallElements
630  /// in the specified solid mesh require to obtain the fluid loading from the
631  /// adjacent fluid elements in the specified fluid mesh.
632  /// The parameter b specifies the boundary in the fluid mesh
633  /// that is adjacent to the solid mesh. The template parameters
634  /// specify the type of the fluid element and their spatial
635  /// dimension. The optional final argument, face, identifies the
636  /// face of the FSIWallElements that is exposed to the fluid. face
637  /// defaults to 0, indicating that the front is loaded along the
638  /// specified fluid mesh boundary. Set it to 1 to set up the FSI lookup
639  /// schemes for fluid loading along the "back" of the FSIWallElements.
640  /// This routine uses the procedures in the Multi_domain_functions namespace
641  /// to set up the interaction by locating the adjacent (source) elements
642  /// for each integration point of each solid element
643  //============================================================================
644  template<class FLUID_ELEMENT, unsigned DIM_FLUID>
646  Problem* problem_pt,
647  const unsigned &boundary_in_fluid_mesh,
648  Mesh* const &fluid_mesh_pt,
649  Mesh* const &solid_mesh_pt,
650  const unsigned& face=0)
651  {
652  // Thin wrapper to multi-domain function
654  <FLUID_ELEMENT, DIM_FLUID>(problem_pt,
655  boundary_in_fluid_mesh,
656  fluid_mesh_pt,
657  solid_mesh_pt,
658  face);
659  }
660 
661 
662 
663 
664  //============================================================================
665  /// \short Setup multi-domain interaction required for imposition
666  /// of solid displacements onto the pseudo-solid fluid mesh by
667  /// Lagrange multipliers: This function locates the bulk solid
668  /// elements next to boundary b_solid_fsi (the FSI boundary)
669  /// in the solid mesh pointed to by Solid_mesh_pt. The deformation of
670  /// these elements drives the deformation of the pseudo-solid fluid
671  /// mesh via the Lagrange multiplier elements stored in
672  /// lagrange_multiplier_mesh_pt. The template parameters
673  /// specify the type of the bulk solid elements and their spatial
674  /// dimension.
675  ///
676  /// This is the vector based version it works simultaneously on
677  /// solid fsi boundaries identified in the vector b_solid_fsi
678  /// and the corresponding Lagrange multiplier meshes in
679  /// lagrange_multiplier_mesh_pt.
680  //============================================================================
681  template<class SOLID_ELEMENT, unsigned DIM_SOLID>
683  Problem* problem_pt,
684  const Vector<unsigned>& b_solid_fsi,
685  Mesh* const &solid_mesh_pt,
686  Vector<Mesh*>& lagrange_multiplier_mesh_pt)
687  {
688  // Thin wrapper to multi-domain function
690  <SOLID_ELEMENT, DIM_SOLID>(problem_pt,
691  b_solid_fsi,
692  solid_mesh_pt,
693  lagrange_multiplier_mesh_pt,
694  0);
695  }
696 
697 
698 
699 
700 
701  //============================================================================
702  /// \short Setup multi-domain interaction required for imposition
703  /// of solid displacements onto the pseudo-solid fluid mesh by
704  /// Lagrange multipliers: This function locates the bulk solid
705  /// elements next to boundary b_solid_fsi (the FSI boundary)
706  /// in the solid mesh pointed to by Solid_mesh_pt. The deformation of
707  /// these elements drives the deformation of the pseudo-solid fluid
708  /// mesh via the Lagrange multiplier elements stored in l
709  /// lagrange_multiplier_mesh_pt. The template parameters
710  /// specify the type of the bulk solid elements and their spatial
711  /// dimension.
712  //============================================================================
713  template<class SOLID_ELEMENT, unsigned DIM_SOLID>
715  Problem* problem_pt,
716  const unsigned & b_solid_fsi,
717  Mesh* const &solid_mesh_pt,
718  Mesh* const &lagrange_multiplier_mesh_pt)
719  {
720 
721  // Thin wrapper to multi-domain function
723  <SOLID_ELEMENT, DIM_SOLID>(problem_pt,
724  b_solid_fsi,
725  solid_mesh_pt,
726  lagrange_multiplier_mesh_pt,
727  0);
728  }
729 
730 
731 
732 
733 //============================================================================
734 /// Doc FSI:
735 /// -# Which Data values affect the traction onto the FSIWallElements
736 /// and what type of Data is it stored in ([fluid-]nodes, internal
737 /// Data [in fluid elements] or SolidNodes?
738 /// -# Which SolidNodes affect the node update of the fluid nodes?
739 /// .
740 /// Output is in tecplot readable form: Use fs1.mcr and fsi2.mcr
741 /// (or straightforward modifications thereof), stored in
742 /// doc/interaction/fsi_collapsible_channel/nondist_figures to process.
743 ///
744 /// Pass pointer to fluid and solid meshes and pointer to the
745 /// DocInfo object that specifies the directory and the overall
746 /// step number.
747 /// Template parameter specifies the type of node that is used
748 /// to implement the node update strategy.
749 //============================================================================
750 template<class NODE>
751 void doc_fsi(Mesh* fluid_mesh_pt,
752  SolidMesh* wall_mesh_pt,
753  DocInfo& doc_info)
754 {
755 
756  std::ofstream some_file;
757  std::ostringstream filename;
758 
759  // Number of plot points
760  unsigned npts;
761  npts=5;
762 
763  // Part 1: Doc which dofs affect the fluid traction on solid
764  //==========================================================
765 
766  // Tecplot helpers
767  Vector<std::string> label(3);
768  label[0]="X=";
769  label[1]="Y=";
770  label[2]="Z=";
771 
772  // Output fluid solution/mesh
773  //---------------------------
774  filename << doc_info.directory() << "/fsi_doc_fluid_mesh"
775  << doc_info.number() << ".dat";
776  some_file.open(filename.str().c_str());
777  fluid_mesh_pt->output(some_file,npts);
778  some_file.close();
779 
780 
781 
782 
783  // Setup map that links the positional Data of SolidNodes with
784  //------------------------------------------------------------
785  // the nodes
786  //----------
787  std::map<Data*,Node*> solid_node_pt;
788  unsigned nnod=wall_mesh_pt->nnode();
789  for (unsigned j=0;j<nnod;j++)
790  {
791  solid_node_pt[wall_mesh_pt->node_pt(j)->variable_position_pt()]=
792  wall_mesh_pt->node_pt(j);
793  }
794 
795 
796  // Setup map that links the internal (pressure) Data of fluid elements with
797  //-------------------------------------------------------------------------
798  // those fluid elements
799  //---------------------
800  std::map<Data*,FiniteElement*> internal_data_element_pt;
801  unsigned nelemf=fluid_mesh_pt->nelement();
802  for (unsigned e=0;e<nelemf;e++)
803  {
804  unsigned ninternal=fluid_mesh_pt->element_pt(e)->ninternal_data();
805  for (unsigned k=0;k<ninternal;k++)
806  {
807  internal_data_element_pt[
808  fluid_mesh_pt->element_pt(e)->internal_data_pt(k)]=
809  fluid_mesh_pt->finite_element_pt(e);
810  }
811  }
812 
813 
814 #ifdef OOMPH_HAS_MPI
815  // External halo elements must also be included in this check
816  std::set<int> procs=fluid_mesh_pt->external_halo_proc();
817  for (std::set<int>::iterator it=procs.begin();
818  it!=procs.end();it++)
819  {
820  unsigned d=unsigned((*it));
821  unsigned n_ext_halo_f=fluid_mesh_pt->nexternal_halo_element(d);
822  for (unsigned e=0;e<n_ext_halo_f;e++)
823  {
824  unsigned ninternal=fluid_mesh_pt->
825  external_halo_element_pt(d,e)->ninternal_data();
826  for (unsigned k=0;k<ninternal;k++)
827  {
828  internal_data_element_pt[
829  fluid_mesh_pt->external_halo_element_pt(d,e)->internal_data_pt(k)]=
830  dynamic_cast<FiniteElement*>(
831  fluid_mesh_pt->external_halo_element_pt(d,e));
832  }
833  }
834  }
835 #endif
836 
837 
838 
839  // Loop over all wall elements
840  //----------------------------
841  unsigned nelem=wall_mesh_pt->nelement();
842  for (unsigned e=0;e<nelem;e++)
843  {
844  //Reset the string contents to be empty
845  filename.str("");
846  //Set the new filename
847  filename << doc_info.directory()
848  << "/fsi_doc_wall_element" << doc_info.number() << "-"
849  << e << ".dat";
850  some_file.open(filename.str().c_str());
851 
852  // Get pointer to wall element
853  FSIWallElement* el_pt=
854  dynamic_cast<FSIWallElement*>(wall_mesh_pt->finite_element_pt(e));
855 
856 #ifdef OOMPH_HAS_MPI
857  // If it's a halo element then it will not have set an adjacent
858  // fluid element so there's no point trying to output it!
859  if (!el_pt->is_halo())
860  {
861 #endif
862 
863  // Storage for local and global coords
864  unsigned ndim_local = el_pt->dim();
865  Vector<double> s(ndim_local);
866  unsigned ndim_eulerian = el_pt->nodal_dimension();
867  Vector<double> x(ndim_eulerian);
868 
869 
870  // Map to indicate if the internal Data for a given
871  // fluid element has been plotted already
872  std::map<FiniteElement*,bool> element_internal_data_has_been_plotted;
873 
874  // Loop over Gauss points and doc their position
875  //-----------------------------------------------
876  unsigned nint=el_pt->integral_pt()->nweight();
877  some_file << "ZONE I=" << nint << std::endl;
878  for (unsigned i=0;i<nint;i++)
879  {
880  for (unsigned j=0;j<ndim_local;j++)
881  {
882  s[j]=el_pt->integral_pt()->knot(i,j);
883  }
884  el_pt->interpolated_x(s,x);
885  for (unsigned j=0;j<ndim_eulerian;j++)
886  {
887  some_file << x[j] << " ";
888  }
889  some_file << i << std::endl;
890  }
891 
892 
893  // Loop over Gauss points again to find corresponding points in fluid
894  //--------------------------------------------------------------------
895  // elements
896  //---------
897 
898  // Loop over front and back if required: Get number of fluid-loaded faces
899  unsigned n_loaded_face=2;
900  if (el_pt->only_front_is_loaded_by_fluid()) n_loaded_face=1;
901 
902  for (unsigned face=0;face<n_loaded_face;face++)
903  {
904  some_file << "ZONE I=" << nint << std::endl;
905  for (unsigned i=0;i<nint;i++)
906  {
907  // Get corresponding fluid element
908  FSIFluidElement* fluid_el_pt=dynamic_cast<FSIFluidElement*>(
909  el_pt->external_element_pt(face,i));
910 
911  // Get local coordinates in fluid element by copy operation
912  Vector<double> s_fluid(el_pt->external_element_local_coord(face,i));
913 
914  // Get Eulerian position in fluid element
915  fluid_el_pt->interpolated_x(s_fluid,x);
916  for (unsigned j=0;j<ndim_eulerian;j++)
917  {
918  some_file << x[j] << " ";
919  }
920  some_file << i << std::endl;
921  }
922  }
923 
924 
925  // Get the multiplicity of data that affects the load on this wall element
926  //------------------------------------------------------------------------
927  std::map<Data*,unsigned> data_count;
928  std::map<FiniteElement*,unsigned> internal_data_count;
929  {
930  Vector<Data*> external_interaction_field_data_pt(
932  unsigned nexternal_interaction_field =
933  external_interaction_field_data_pt.size();
934  for (unsigned l=0;l<nexternal_interaction_field;l++)
935  {
936  data_count[external_interaction_field_data_pt[l]]++;
937  if (internal_data_element_pt[external_interaction_field_data_pt[l]]!=0)
938  {
939  internal_data_count[internal_data_element_pt[
940  external_interaction_field_data_pt[l]]]++;
941  }
942  }
943  }
944 
945  {
946  Vector<Data*> external_interaction_geometric_data_pt(
948  unsigned nexternal_interaction_geom =
949  external_interaction_geometric_data_pt.size();
950  for (unsigned l=0;l<nexternal_interaction_geom;l++)
951  {
952  data_count[external_interaction_geometric_data_pt[l]]++;
953  if (internal_data_element_pt[
954  external_interaction_geometric_data_pt[l]]!=0)
955  {
956  internal_data_count[internal_data_element_pt[
957  external_interaction_geometric_data_pt[l]]]++;
958  }
959  }
960  }
961 
962  // Loop over unique data entries
963  //------------------------------
964  for(std::map<Data*,unsigned>::iterator it=data_count.begin();
965  it != data_count.end(); it++)
966  {
967  Data* unique_data_pt=it->first;
968 
969  // Try to cast to a Node
970  //----------------------
971  Node* node_pt=dynamic_cast<Node*>(unique_data_pt);
972  if (node_pt==0)
973  {
974  // Is it a solid node? NOTE: This query makes sense as we're
975  //----------------------------------------------------------
976  // checking for the SolidNode's *positional* Data, not for
977  //--------------------------------------------------------
978  // the SolidNode itself!
979  //----------------------
980  if (solid_node_pt[unique_data_pt]!=0)
981  {
982  some_file << "TEXT " ;
983  for (unsigned j=0;j<ndim_eulerian;j++)
984  {
985  some_file << label[j] << solid_node_pt[unique_data_pt]->x(j)
986  << " ";
987  }
988 
989  some_file <<"CS=GRID, HU=FRAME, H=2.5, AN=MIDCENTER, C=GREEN "
990  << "T=\"" << it->second << "\"" << std::endl;
991  }
992 
993  // Is it internal (pressure) Data in a fluid element?
994  //---------------------------------------------------
995  else if (internal_data_element_pt[unique_data_pt]!=0)
996  {
997  if (!element_internal_data_has_been_plotted[
998  internal_data_element_pt[unique_data_pt]])
999  {
1000  some_file << "TEXT " ;
1001  // Pointer to fluid element that contains this internal data
1002  FiniteElement* fluid_el_pt=internal_data_element_pt[unique_data_pt];
1003 
1004  // Get the plot coordinates in this element: centre + a bit of
1005  // offset
1006  double s_max=fluid_el_pt->s_max();
1007  double s_min=fluid_el_pt->s_min();
1008  Vector<double> s_fluid(ndim_eulerian);
1009  Vector<double> x_fluid(ndim_eulerian);
1010  for (unsigned k=0;k<ndim_eulerian;k++)
1011  {
1012  s_fluid[k]=0.5*(s_max+s_min)+0.1*(s_max-s_min);
1013  }
1014  fluid_el_pt->interpolated_x(s_fluid,x_fluid);
1015  for (unsigned j=0;j<ndim_eulerian;j++)
1016  {
1017  some_file << label[j] << x_fluid[j] << " ";
1018  }
1019 
1020  some_file <<"CS=GRID, HU=FRAME, H=2.5, AN=MIDCENTER, C=BLUE "
1021  << "T=\"" << it->second << "\""
1022  // internal_data_count[fluid_el_pt]
1023  << std::endl;
1024 
1025  // Now we have plotted it....
1026  element_internal_data_has_been_plotted[
1027  internal_data_element_pt[unique_data_pt]]=true;
1028  }
1029 
1030  }
1031  else
1032  {
1033  std::ostringstream error_message;
1034  error_message
1035  << "Data that affects the load on an FSIWallElement\n"
1036  << "is neither a (fluid) Node, nor a SolidNode nor\n"
1037  << "internal Data in a (fluid) element\n"
1038  << "I don't think this should happen..."
1039  << std::endl;
1040  throw OomphLibError(error_message.str(),
1041  OOMPH_CURRENT_FUNCTION,
1042  OOMPH_EXCEPTION_LOCATION);
1043  }
1044  }
1045  // It must be a node then
1046  //-----------------------
1047  else
1048  {
1049  some_file << "TEXT " ;
1050  for (unsigned j=0;j<ndim_eulerian;j++)
1051  {
1052  some_file << label[j] << node_pt->x(j) << ", ";
1053  }
1054  some_file <<"CS=GRID, HU=FRAME, H=2.5, AN=MIDCENTER, C=RED "<< "T=\""
1055  << it->second << "\""
1056  << std::endl;
1057  }
1058  }
1059 
1060 #ifdef OOMPH_HAS_MPI
1061  } // end is_halo()
1062 #endif
1063  some_file.close();
1064  }
1065 
1066  // Part 2: Doc which dofs affect the node update functions
1067  //========================================================
1068 
1069 
1070  // Counter for the number of nodes that are actually
1071  // affected by wall motion
1072  unsigned count=0;
1073 
1074  // Loop over nodes in fluid mesh
1075  unsigned nnode_fluid=fluid_mesh_pt->nnode();
1076  for (unsigned j=0;j<nnode_fluid;j++)
1077  {
1078 
1079  // Upcast node to appropriate type
1080  NODE* node_pt=dynamic_cast<NODE*>(fluid_mesh_pt->node_pt(j));
1081 
1082  unsigned ndim_eulerian=node_pt->ndim();
1083 
1084  //Cleart the filename
1085  filename.str("");
1086  filename << doc_info.directory()
1087  << "/fsi_doc_fluid_element"
1088  << doc_info.number() << "-"
1089  << count << ".dat";
1090  some_file.open(filename.str().c_str());
1091  some_file << "ZONE" << std::endl;
1092  for (unsigned i=0;i<ndim_eulerian;i++)
1093  {
1094  some_file << node_pt->x(i) << " ";
1095  }
1096  some_file << std::endl;
1097 
1098  // Extract geom objects that affect the nodal position
1099  Vector<GeomObject*> geom_obj_pt(node_pt->vector_geom_object_pt());
1100 
1101 
1102  // Get the multiplicity of data that affects this node
1103  //----------------------------------------------------
1104  std::map<Data*,unsigned> data_count;
1105  unsigned ngeom=geom_obj_pt.size();
1106  for (unsigned i=0;i<ngeom;i++)
1107  {
1108  unsigned ngeom_dat=geom_obj_pt[i]->ngeom_data();
1109  for (unsigned k=0;k<ngeom_dat;k++)
1110  {
1111  data_count[geom_obj_pt[i]->geom_data_pt(k)]++;
1112  }
1113  }
1114 
1115  // Haven't actually doced any dependcies for this node
1116  bool written_something=false;
1117 
1118  // Loop over unique data entries
1119  //------------------------------
1120  for(std::map<Data*,unsigned>::iterator it=data_count.begin();
1121  it != data_count.end(); it++)
1122  {
1123  Data* unique_data_pt=it->first;
1124 
1125  // Is it a solid node?
1126  if (solid_node_pt[unique_data_pt]!=0)
1127  {
1128  some_file << "TEXT " ;
1129  for (unsigned j=0;j<ndim_eulerian;j++)
1130  {
1131  some_file << label[j] << solid_node_pt[unique_data_pt]->x(j)
1132  << " ";
1133  }
1134 
1135  some_file <<"CS=GRID, HU=FRAME, H=2.5, AN=MIDCENTER, C=GREEN "<< "T=\""
1136  << unique_data_pt->nvalue() << "\""
1137  << std::endl;
1138 
1139  // We've actually produced some output
1140  written_something=true;
1141  }
1142  // It's not a solid node --> ??
1143  else
1144  {
1145  std::ostringstream warn_message;
1146  warn_message
1147  << "Info: Position of a fluid node is affected by Data that"
1148  << "is not a SolidNode --> Can't plot this Data. \n\n"
1149  << "(You may also want to check if this is exepcted or likely to\n"
1150  << "indicate a bug in your code...)"
1151  << std::endl;
1152  throw OomphLibWarning(warn_message.str(),
1153  "FSI_functions::doc_fsi()",
1154  OOMPH_EXCEPTION_LOCATION);
1155  }
1156  }
1157 
1158 
1159  some_file.close();
1160 
1161  // If we've written something for the last node, bump up
1162  // counter for file so we don't overwrite
1163  if (written_something) count++;
1164 
1165  }
1166 
1167 } // end_of_doc_fsi
1168 
1169 }
1170 
1171 }
1172 
1173 #endif
FSIWallElement(const FSIWallElement &)
Broken copy constructor.
Definition: fsi.h:236
virtual void get_residuals(Vector< double > &residuals)
Calculate the vector of residuals of the equations in the element. By default initialise the vector t...
Definition: elements.h:975
void broken_copy(const std::string &class_name)
Issue error message and terminate execution.
void setup_bulk_elements_adjacent_to_face_mesh(Problem *problem_pt, Vector< unsigned > &boundary_in_bulk_mesh, Mesh *const &bulk_mesh_pt, Vector< Mesh *> &face_mesh_pt, const unsigned &interaction=0)
Identify the FaceElements (stored in the mesh pointed to by face_mesh_pt) that are adjacent to the bu...
Vector< Data * > external_interaction_geometric_data_pt() const
Return vector of pointers to the geometric Data objects that affect the interactions on the element...
virtual void fill_in_contribution_to_residuals(Vector< double > &residuals)
Add the elemental contribution to the residuals vector. Note that this function will NOT initialise t...
Definition: elements.h:360
unsigned nexternal_halo_element()
Total number of external halo elements in this Mesh.
Definition: mesh.h:1874
This is a base class for all SolidFiniteElements that participate in FSI computations. These elements provide interfaces and generic funcionality for the two additional roles that SolidFiniteElements play in FSI problems:They parameterise the domain boundary for the fluid domain. To allow them to play this role, FSIWallElements are derived from the SolidFiniteElement and the GeomObject class, indicating that the every specific FSIWallElement must implement the pure virtual function GeomObject::position(...) which should compute the position vector to a point in the SolidFiniteElement, parametrised by its local coordinates.In FSI problems fluid exerts a traction onto the wall and this traction must be added to any other load terms (such as an external pressure acting on an elastic pipe) that are already applied to the SolidFiniteElements by other means.
Definition: fsi.h:210
Vector< double > & external_element_local_coord(const unsigned &interaction_index, const unsigned &ipt)
Access function to get source element&#39;s local coords for specified interaction index at specified int...
bool only_front_is_loaded_by_fluid() const
Is the element exposed to (and hence loaded by) fluid only on its "front"? True by default...
Definition: fsi.h:285
void fill_in_jacobian_from_internal_by_fd(Vector< double > &residuals, DenseMatrix< double > &jacobian, const bool &fd_all_data=false)
Calculate the contributions to the jacobian from the internal degrees of freedom using finite differe...
Definition: elements.cc:1064
virtual void get_load(const Vector< double > &s, const Vector< double > &N, Vector< double > &load)=0
Compute the load vector that is applied by current element (at its local coordinate s) onto the adjac...
Information for documentation of results: Directory and file number to enable output in the form RESL...
void reset_after_external_interaction_geometric_fd()
Function that is call after the finite differencing of the external interaction data associated with ...
Definition: fsi.h:457
std::string directory() const
Output directory.
cstr elem_len * i
Definition: cfortran.h:607
GeneralisedElement *& external_halo_element_pt(const unsigned &p, const unsigned &e)
Access fct to the e-th external halo element in this Mesh whose non-halo counterpart is held on proce...
Definition: mesh.h:1902
void fill_in_contribution_to_jacobian(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Definition: fsi.h:330
double * Q_pt
Pointer to the ratio, , of the stress used to non-dimensionalise the fluid stresses to the stress us...
Definition: fsi.h:546
The Problem class.
Definition: problem.h:152
virtual void describe_local_dofs(std::ostream &out, const std::string &current_string) const
Function to describe the local dofs of the element[s]. The ostream specifies the output stream to whi...
Definition: elements.cc:1682
void disable_shear_stress_in_jacobian()
Call this function to ignore shear stress component of load when calculating the Jacobian, i.e. to ignore fluid velocity Data in the FSIFluidElement and "far away" geometric Data that affects nodal positions in the FSIFluidElement, also to bypass node updates in the FSIFluidElement. This functionality is provided to allow the user to deem the coupling to the shear stress component of the fluid equations to be irrelevant.
Definition: fsi.h:314
A general Finite Element class.
Definition: elements.h:1274
void include_external_load_data()
Include all external fluid data that affects the load in the computation of the element&#39;s Jacobian ma...
Definition: fsi.h:301
bool is_halo() const
Is this element a halo?
Definition: elements.h:1141
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
Definition: nodes.h:852
unsigned nvalue() const
Return number of values stored in data object (incl pinned ones).
Definition: nodes.h:448
void apply_no_slip_on_moving_wall(Node *node_pt)
Apply no-slip condition for N.St. on a moving wall node, u = St dR/dt, where the Strouhal number St =...
Definition: fsi.cc:54
virtual void identify_pressure_data(std::set< std::pair< Data *, unsigned > > &paired_pressure_data)=0
Add to the set paired_pressure_data pairs containing.
e
Definition: cfortran.h:575
virtual void identify_load_data(std::set< std::pair< Data *, unsigned > > &paired_load_data)=0
Add to the set paired_load_data pairs containing.
Vector< Data * > external_interaction_field_data_pt() const
Return vector of pointers to the field Data objects that affect the interactions on the element...
void fill_in_jacobian_from_external_by_fd(Vector< double > &residuals, DenseMatrix< double > &jacobian, const bool &fd_all_data=false)
Calculate the contributions to the jacobian from the external degrees of freedom using finite differe...
Definition: elements.cc:1158
unsigned & number()
Number used (e.g.) for labeling output files.
unsigned long nelement() const
Return number of elements in the mesh.
Definition: mesh.h:587
void operator=(const FSIWallElement &)
Broken assignment operator.
Definition: fsi.h:242
virtual double s_min() const
Min value of local coordinate.
Definition: elements.h:2643
void output(std::ostream &outfile)
Output for all elements.
Definition: mesh.cc:1761
unsigned ndim() const
Return (Eulerian) spatial dimension of the node.
Definition: nodes.h:992
void reset_after_external_fd()
Function that is call after the finite differencing of the external data. This may be overloaded to r...
Definition: fsi.h:392
SolidNode * node_pt(const unsigned long &n)
Return a pointer to the n-th global SolidNode.
Definition: mesh.h:2255
unsigned ndof() const
Return the number of equations/dofs in the element.
Definition: elements.h:834
unsigned nodal_dimension() const
Return the required Eulerian dimension of the nodes in this element.
Definition: elements.h:2370
void operator=(const FSIFluidElement &)
Broken assignment operator.
Definition: fsi.h:83
double & x(const unsigned &i)
Return the i-th nodal coordinate.
Definition: nodes.h:995
virtual double interpolated_x(const Vector< double > &s, const unsigned &i) const
Return FE interpolated coordinate x[i] at local coordinate s.
Definition: elements.cc:3881
void reset_in_external_interaction_field_fd(const unsigned &i)
Function called within the finite difference loop for external interaction data after the values in t...
Definition: fsi.h:432
void enable_shear_stress_in_jacobian()
Definition: fsi.h:319
void update_in_external_fd(const unsigned &i)
After an external data change, update the nodal positions.
Definition: fsi.h:380
GeneralisedElement *& element_pt(const unsigned long &e)
Return pointer to element e.
Definition: mesh.h:462
bool Only_front_is_loaded_by_fluid
Is the element exposed to (and hence loaded by) fluid only on its "front"? True by default...
Definition: fsi.h:541
void reset_in_internal_fd(const unsigned &i)
Function called within the finite difference loop for internal data after the values in the i-th exte...
Definition: fsi.h:367
Integral *const & integral_pt() const
Return the pointer to the integration scheme (const version)
Definition: elements.h:1908
void reset_in_external_interaction_geometric_fd(const unsigned &i)
Function called within the finite difference loop for external interaction data after the values in t...
Definition: fsi.h:454
FSIFluidElement()
Constructor.
Definition: fsi.h:73
void reset_after_solid_position_fd()
Function that is call after the finite differencing of the solid position data. This may be overloade...
Definition: fsi.h:479
void exclude_external_load_data()
Do not include any external data that affects the load in the computation of element&#39;s Jacobian matri...
Definition: fsi.h:296
static char t char * s
Definition: cfortran.h:572
virtual double knot(const unsigned &i, const unsigned &j) const =0
Return local coordinate s[j] of i-th integration point.
void update_in_solid_position_fd(const unsigned &i)
After an internal data change, update the nodal positions.
Definition: fsi.h:467
Data *& internal_data_pt(const unsigned &i)
Return a pointer to i-th internal data object.
Definition: elements.h:623
void update_in_external_interaction_geometric_fd(const unsigned &i)
After an external geometric data change, update the nodal positions.
Definition: fsi.h:445
void reset_after_internal_fd()
Function that is call after the finite differencing of the internal data. This may be overloaded to r...
Definition: fsi.h:370
A class that represents a collection of data; each Data object may contain many different individual ...
Definition: nodes.h:89
Data *const & variable_position_pt() const
Pointer to variable_position data (const version)
Definition: nodes.h:1655
bool Ignore_shear_stress_in_jacobian
Set this flag to true to ignore shear stress component of load when calculating the Jacobian...
Definition: fsi.h:553
void update_in_nodal_fd(const unsigned &i)
After a nodal data change, update the nodal positions.
Definition: fsi.h:402
virtual ~FSIWallElement()
Empty virtual destructor for safety.
Definition: fsi.h:248
virtual double s_max() const
Max. value of local coordinate.
Definition: elements.h:2654
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
Definition: elements.h:2109
double *& q_pt()
Return a pointer the ratio of stress scales used to non-dimensionalise the fluid and solid equations...
Definition: fsi.h:267
void reset_in_solid_position_fd(const unsigned &i)
Function called within the finite difference loop for solid position data after the values in the i-t...
Definition: fsi.h:476
Node *& node_pt(const unsigned long &n)
Return pointer to global node n.
Definition: mesh.h:456
unsigned long nnode() const
Return number of nodes in the mesh.
Definition: mesh.h:590
void update_in_external_interaction_field_fd(const unsigned &i)
After an external field data change, update the nodal positions.
Definition: fsi.h:423
General SolidMesh class.
Definition: mesh.h:2213
FiniteElement * finite_element_pt(const unsigned &e) const
Upcast (downcast?) to FiniteElement (needed to access FiniteElement member functions).
Definition: mesh.h:477
FSIWallElement()
Constructor. Note that element is not fully-functional until its setup_fsi_wall_element() function ha...
Definition: fsi.h:232
virtual void fill_in_jacobian_from_nodal_by_fd(Vector< double > &residuals, DenseMatrix< double > &jacobian)
Calculate the contributions to the jacobian from the nodal degrees of freedom using finite difference...
Definition: elements.cc:3583
unsigned dim() const
Return the spatial dimension of the element, i.e. the number of local coordinates required to paramet...
Definition: elements.h:2482
unsigned ninternal_data() const
Return the number of internal data objects.
Definition: elements.h:828
void setup_fluid_load_info_for_solid_elements(Problem *problem_pt, const unsigned &boundary_in_fluid_mesh, Mesh *const &fluid_mesh_pt, Mesh *const &solid_mesh_pt, const unsigned &face=0)
Set up the information that the FSIWallElements in the specified solid mesh require to obtain the flu...
Definition: fsi.h:645
void broken_assign(const std::string &class_name)
Issue error message and terminate execution.
void reset_in_external_fd(const unsigned &i)
Function called within the finite difference loop for external data after the values in the i-th exte...
Definition: fsi.h:389
const double & q() const
Return the ratio of the stress scales used to non-dimensionalise the fluid and solid equations...
Definition: fsi.h:263
void reset_in_nodal_fd(const unsigned &i)
Function called within the finite difference loop for nodal data after the i-th nodal values is reset...
Definition: fsi.h:411
virtual unsigned nweight() const =0
Return the number of integration points of the scheme.
FiniteElement *& external_element_pt(const unsigned &interaction_index, const unsigned &ipt)
Access function to source element for specified interaction index at specified integration point...
void reset_after_nodal_fd()
Function that is call after the finite differencing of the nodal data. This may be overloaded to rese...
Definition: fsi.h:414
std::string string(const unsigned &i)
Return the i-th string or "" if the relevant string hasn&#39;t been defined.
void update_in_internal_fd(const unsigned &i)
After an internal data change, update the nodal positions.
Definition: fsi.h:358
static bool Dont_warn_about_missing_adjacent_fluid_elements
Static flag that allows the suppression of warning messages.
Definition: fsi.h:228
FSIFluidElement(const FSIFluidElement &)
Broken copy constructor.
Definition: fsi.h:77
double Strouhal_for_no_slip
Strouhal number St = a/(UT) for application of no slip condition. Initialised to 1.0.
Definition: fsi.cc:45
void setup_solid_elements_for_displacement_bc(Problem *problem_pt, const unsigned &b_solid_fsi, Mesh *const &solid_mesh_pt, Mesh *const &lagrange_multiplier_mesh_pt)
Setup multi-domain interaction required for imposition of solid displacements onto the pseudo-solid f...
Definition: fsi.h:714
void reset_after_external_interaction_field_fd()
Function that is call after the finite differencing of the external interaction data associated with ...
Definition: fsi.h:435
std::set< int > external_halo_proc()
Return the set of processors that hold external halo nodes. This is required to avoid having to pass ...
Definition: mesh.h:2121
static double Default_Q_Value
Static default value for the ratio of stress scales used in the fluid and solid equations (default is...
Definition: fsi.h:534
SolidFiniteElement class.
Definition: elements.h:3361
A general mesh class.
Definition: mesh.h:74
void doc_fsi(Mesh *fluid_mesh_pt, SolidMesh *wall_mesh_pt, DocInfo &doc_info)
Definition: fsi.h:751
The FSIFluidElement class is a base class for all fluid finite elements that apply a load (traction) ...
Definition: fsi.h:67