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