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-2022 Matthias Heil and Andrew Hazel
7// LIC//
8// LIC// This library is free software; you can redistribute it and/or
9// LIC// modify it under the terms of the GNU Lesser General Public
10// LIC// License as published by the Free Software Foundation; either
11// LIC// version 2.1 of the License, or (at your option) any later version.
12// LIC//
13// LIC// This library is distributed in the hope that it will be useful,
14// LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16// LIC// Lesser General Public License for more details.
17// LIC//
18// LIC// You should have received a copy of the GNU Lesser General Public
19// LIC// License along with this library; if not, write to the Free Software
20// LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21// LIC// 02110-1301 USA.
22// LIC//
23// LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
24// LIC//
25// LIC//====================================================================
26#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"
44
45namespace 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
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
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
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
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...
Vector< Data * > external_interaction_geometric_data_pt() const
Return vector of pointers to the geometric 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...
FiniteElement *& external_element_pt(const unsigned &interaction_index, const unsigned &ipt)
Access function to source element for specified interaction index at specified integration point.
bool Add_external_interaction_data
Boolean flag to indicate whether to include the external data.
Vector< Data * > external_interaction_field_data_pt() const
Return vector of pointers to the field Data objects that affect the interactions on the element.
/////////////////////////////////////////////////////////////////////////
Definition: fsi.h:63
virtual void identify_load_data(std::set< std::pair< Data *, unsigned > > &paired_load_data)=0
Add to the set paired_load_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 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...
virtual void identify_pressure_data(std::set< std::pair< Data *, unsigned > > &paired_pressure_data)=0
Add to the set paired_pressure_data pairs containing.
////////////////////////////////////////////////////////////////////////// //////////////////////////...
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
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
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 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 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 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
const double & q() const
Return the ratio of the stress scales used to non-dimensionalise the fluid and solid equations....
Definition: fsi.h:241
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 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
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
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
double *& q_pt()
Return a pointer the ratio of stress scales used to non-dimensionalise the fluid and solid equations.
Definition: fsi.h:248
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
Integral *const & integral_pt() const
Return the pointer to the integration scheme (const version)
Definition: elements.h:1963
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
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
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
FiniteElement * finite_element_pt(const unsigned &e) const
Upcast (downcast?) to FiniteElement (needed to access FiniteElement member functions).
Definition: mesh.h:473
Node *& node_pt(const unsigned long &n)
Return pointer to global node n.
Definition: mesh.h:436
unsigned long nnode() const
Return number of nodes in the mesh.
Definition: mesh.h:596
GeneralisedElement *& element_pt(const unsigned long &e)
Return pointer to element e.
Definition: mesh.h:448
void output(std::ostream &outfile)
Output for all elements.
Definition: mesh.cc:2027
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
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
unsigned ndim() const
Return (Eulerian) spatial dimension of the node.
Definition: nodes.h:1054
double & x(const unsigned &i)
Return the i-th nodal coordinate.
Definition: nodes.h:1060
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...
//////////////////////////////////////////////////////////////////// ////////////////////////////////...