27 #ifndef OOMPH_AXISYM_POROELASTIC_FSI_TRACTION_ELEMENTS_HEADER
28 #define OOMPH_AXISYM_POROELASTIC_FSI_TRACTION_ELEMENTS_HEADER
32 #include <oomph-lib-config.h>
37 #include "../generic/shape.h"
38 #include "../generic/elements.h"
39 #include "../generic/element_with_external_element.h"
50 namespace LinearisedAxisymPoroelasticBJS_FSIHelper
67 template<
class FLUID_BULK_ELEMENT,
class POROELASTICITY_BULK_ELEMENT>
81 const unsigned&
id = 0);
157 const unsigned n_node = this->
nnode();
170 for (
unsigned ipt = 0; ipt < n_intpt; ipt++)
184 for (
unsigned l = 0; l < n_node; l++)
187 for (
unsigned i = 0;
i < 2;
i++)
195 double tlength = interpolated_t1[0] * interpolated_t1[0] +
196 interpolated_t1[1] * interpolated_t1[1];
207 for (
unsigned k = 0; k < 2; k++)
231 void output(std::ostream& outfile,
const unsigned& n_plot)
234 unsigned n_node =
nnode();
249 const double local_st =
st();
252 const double local_inverse_slip_rate_coeff =
256 for (
unsigned ipt = 0; ipt < n_intpt; ipt++)
259 for (
unsigned i = 0;
i < (
Dim - 1);
i++)
270 interpolated_tangent[0] = -interpolated_normal[1];
271 interpolated_tangent[1] = interpolated_normal[0];
274 POROELASTICITY_BULK_ELEMENT* ext_el_pt =
275 dynamic_cast<POROELASTICITY_BULK_ELEMENT*
>(
280 ext_el_pt->interpolated_du_dt(s_ext, du_dt);
281 ext_el_pt->interpolated_q(s_ext, q);
282 x_bulk[0] = ext_el_pt->interpolated_x(s_ext, 0);
283 x_bulk[1] = ext_el_pt->interpolated_x(s_ext, 1);
292 double error = sqrt((x[0] - x_bulk[0]) * (x[0] - x_bulk[0]) +
293 (x[1] - x_bulk[1]) * (x[1] - x_bulk[1]));
294 double tol = 1.0e-10;
297 std::stringstream junk;
298 junk <<
"Gap between external and face element coordinate\n"
299 <<
"is suspiciously large: " << error
300 <<
"\nBulk/external at: " << x_bulk[0] <<
" " << x_bulk[1]
302 <<
"Face at: " << x[0] <<
" " << x[1] <<
"\n";
304 junk.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
310 const double permeability = ext_el_pt->permeability();
311 const double local_permeability_ratio = ext_el_pt->permeability_ratio();
320 ->traction(s_bulk, interpolated_normal, traction_nst);
325 ->interpolated_u_axi_nst(s_bulk, fluid_veloc);
329 ->interpolated_p_axi_nst(s_bulk);
332 double scaled_normal_wall_veloc = 0.0;
333 double scaled_normal_poro_veloc = 0.0;
334 double scaled_tangential_wall_veloc = 0.0;
335 double scaled_tangential_poro_veloc = 0.0;
336 double normal_nst_veloc = 0.0;
337 for (
unsigned i = 0;
i <
Dim;
i++)
339 scaled_normal_wall_veloc +=
340 local_st * du_dt[
i] * interpolated_normal[
i];
342 scaled_normal_poro_veloc +=
343 local_st * permeability * q[
i] * interpolated_normal[
i];
345 scaled_tangential_wall_veloc +=
346 local_st * du_dt[
i] * interpolated_tangent[
i];
348 scaled_tangential_poro_veloc +=
349 -traction_nst[
i] * sqrt(local_permeability_ratio) *
350 local_inverse_slip_rate_coeff * interpolated_tangent[
i];
352 normal_nst_veloc += fluid_veloc[
i] * interpolated_normal[
i];
356 double total_poro_normal_component =
357 scaled_normal_wall_veloc + scaled_normal_poro_veloc;
358 double total_poro_tangential_component =
359 scaled_tangential_wall_veloc + scaled_tangential_poro_veloc;
361 for (
unsigned i = 0;
i <
Dim;
i++)
364 total_poro_normal_component * interpolated_normal[
i] +
365 total_poro_tangential_component * interpolated_tangent[
i];
374 for (
unsigned l = 0; l < n_node; l++)
377 for (
unsigned i = 0;
i < 2;
i++)
384 double J = sqrt(1.0 + (interpolated_t1[0] * interpolated_t1[0]) /
385 (interpolated_t1[1] * interpolated_t1[1])) *
390 double lagrangian_eulerian_translation_factor = 1.0;
395 POROELASTICITY_BULK_ELEMENT,
396 FLUID_BULK_ELEMENT>* ext_face_el_pt =
398 POROELASTICITY_BULK_ELEMENT,
402 if (ext_face_el_pt != 0)
407 lagrangian_eulerian_translation_factor =
408 ext_face_el_pt->lagrangian_eulerian_translation_factor(s_ext_face);
413 outfile << x_bulk[0] <<
" "
415 << fluid_veloc[0] <<
" "
416 << fluid_veloc[1] <<
" "
417 << poro_veloc[0] <<
" "
418 << poro_veloc[1] <<
" "
419 << normal_nst_veloc * interpolated_normal[0] <<
" "
420 << normal_nst_veloc * interpolated_normal[1] <<
" "
421 << total_poro_normal_component * interpolated_normal[0]
423 << total_poro_normal_component * interpolated_normal[1]
425 << scaled_normal_wall_veloc * interpolated_normal[0]
427 << scaled_normal_wall_veloc * interpolated_normal[1]
429 << scaled_normal_poro_veloc * interpolated_normal[0]
431 << scaled_normal_poro_veloc * interpolated_normal[1]
437 << lagrangian_eulerian_translation_factor <<
" "
448 double& seepage_flux_contrib,
449 double& nst_flux_contrib)
459 const unsigned n_node = this->
nnode();
466 skeleton_flux_contrib = 0.0;
467 seepage_flux_contrib = 0.0;
468 nst_flux_contrib = 0.0;
469 for (
unsigned ipt = 0; ipt < n_intpt; ipt++)
472 for (
unsigned i = 0;
i < (
Dim - 1);
i++)
490 for (
unsigned l = 0; l < n_node; l++)
493 for (
unsigned i = 0;
i < 2;
i++)
501 double tlength = interpolated_t1[0] * interpolated_t1[0] +
502 interpolated_t1[1] * interpolated_t1[1];
508 POROELASTICITY_BULK_ELEMENT* ext_el_pt =
509 dynamic_cast<POROELASTICITY_BULK_ELEMENT*
>(
514 ext_el_pt->interpolated_du_dt(s_ext, du_dt);
515 ext_el_pt->interpolated_q(s_ext, q);
516 x_bulk[0] = ext_el_pt->interpolated_x(s_ext, 0);
517 x_bulk[1] = ext_el_pt->interpolated_x(s_ext, 1);
530 double tol = 1.0e-10;
533 std::stringstream junk;
534 junk <<
"Gap between external and face element coordinate\n"
535 <<
"is suspiciously large: " << error
536 <<
"\nBulk/external at: " << x_bulk[0] <<
" " << x_bulk[1]
538 <<
"Face at: " << x[0] <<
" " << x[1] <<
"\n";
540 junk.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
547 double lagrangian_eulerian_translation_factor = 1.0;
556 POROELASTICITY_BULK_ELEMENT,
557 FLUID_BULK_ELEMENT>* ext_face_el_pt =
559 POROELASTICITY_BULK_ELEMENT,
563 if (ext_face_el_pt != 0)
570 x_face[0] = ext_face_el_pt->interpolated_x(s_ext_face, 0);
571 x_face[1] = ext_face_el_pt->interpolated_x(s_ext_face, 1);
573 double tol = 1.0e-10;
575 std::fabs(x_bulk[0] - x_face[0]) + std::fabs(x_bulk[1] - x_face[1]);
578 std::stringstream junk;
579 junk <<
"Difference in Eulerian coordinates: " << error
580 <<
" is suspiciously large: "
581 <<
"Bulk: " << x_bulk[0] <<
" " << x_bulk[1] <<
" "
582 <<
"Face: " << x_face[0] <<
" " << x_face[1] <<
"\n";
584 junk.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
590 lagrangian_eulerian_translation_factor =
591 ext_face_el_pt->lagrangian_eulerian_translation_factor(s_ext_face);
594 ext_face_el_pt->outer_unit_normal(s_ext_face, poro_normal);
595 poro_normal[0] = -poro_normal[0];
596 poro_normal[1] = -poro_normal[1];
600 const double permeability = ext_el_pt->permeability();
609 ->interpolated_u_axi_nst(s_bulk, fluid_veloc);
613 double dudt_flux = 0.0;
614 double nst_flux = 0.0;
615 for (
unsigned i = 0;
i < 2;
i++)
617 q_flux += permeability * q[
i] * poro_normal[
i];
618 dudt_flux += du_dt[
i] * interpolated_normal[
i];
619 nst_flux += fluid_veloc[
i] * interpolated_normal[
i];
624 lagrangian_eulerian_translation_factor *
W * J;
625 skeleton_flux_contrib +=
639 void output(FILE* file_pt,
const unsigned& n_plot)
654 unsigned n_node =
nnode();
660 for (
unsigned i = 0;
i < n_node;
i++)
678 unsigned n_node =
nnode();
684 for (
unsigned i = 0;
i < n_node;
i++)
700 const unsigned& flag);
731 template<
class FLUID_BULK_ELEMENT,
class POROELASTICITY_BULK_ELEMENT>
733 POROELASTICITY_BULK_ELEMENT>::
734 LinearisedAxisymPoroelasticBJS_FSIElement(
FiniteElement*
const& bulk_el_pt,
735 const int& face_index,
767 FLUID_BULK_ELEMENT* cast_bulk_el_pt =
768 dynamic_cast<FLUID_BULK_ELEMENT*
>(bulk_el_pt);
772 for (
unsigned i = 0;
i < 3;
i++)
779 unsigned n = cast_bulk_el_pt->nnode();
780 for (
unsigned j = 0; j < n; j++)
782 Node* nod_pt = cast_bulk_el_pt->node_pt(j);
784 unsigned nn =
nnode();
785 for (
unsigned jj = 0; jj < nn; jj++)
809 template<
class FLUID_BULK_ELEMENT,
class POROELASTICITY_BULK_ELEMENT>
811 POROELASTICITY_BULK_ELEMENT>::
812 fill_in_generic_residual_contribution_axisym_poroelastic_fsi(
815 const unsigned& flag)
818 const unsigned n_node = nnode();
821 Shape psif(n_node), testf(n_node);
824 const unsigned n_intpt = integral_pt()->nweight();
830 const double local_st = st();
833 const double local_inverse_slip_rate_coeff =
834 inverse_slip_rate_coefficient();
841 for (
unsigned ipt = 0; ipt < n_intpt; ipt++)
844 for (
unsigned i = 0;
i < (
Dim - 1);
i++)
846 s[
i] = integral_pt()->knot(ipt,
i);
850 double w = integral_pt()->weight(ipt);
854 double J = shape_and_test(
s, psif, testf);
857 double interpolated_r = 0;
867 for (
unsigned j = 0; j < n_node; j++)
869 Node* nod_pt = node_pt(j);
876 unsigned first_index =
880 interpolated_r += nodal_position(j, 0) * psif(j);
883 for (
unsigned i = 0;
i <
Dim + 1;
i++)
885 lambda[
i] += nod_pt->
value(first_index +
i) * psif(j);
887 nod_pt->
value(U_index_axisym_poroelastic_fsi[
i]) * psif(j);
893 s_bulk = local_coordinate_in_bulk(
s);
899 dynamic_cast<FLUID_BULK_ELEMENT*
>(bulk_element_pt())
900 ->interpolated_u_axi_nst(s_bulk, fluid_veloc_from_bulk);
903 for (
unsigned i = 0;
i <
Dim + 1;
i++)
905 error += (fluid_veloc[
i] - fluid_veloc_from_bulk[
i]) *
906 (fluid_veloc[
i] - fluid_veloc_from_bulk[
i]);
909 double tol = 1.0e-15;
912 std::stringstream junk;
913 junk <<
"Difference in Navier-Stokes velocities\n"
914 <<
"is suspiciously large: " << error
915 <<
"\nVeloc from bulk: " << fluid_veloc_from_bulk[0] <<
" "
916 << fluid_veloc_from_bulk[1] <<
"\n"
917 <<
"Veloc from face: " << fluid_veloc[0] <<
" " << fluid_veloc[1]
920 junk.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
926 POROELASTICITY_BULK_ELEMENT* ext_el_pt =
927 dynamic_cast<POROELASTICITY_BULK_ELEMENT*
>(external_element_pt(0, ipt));
930 ext_el_pt->interpolated_du_dt(s_ext, du_dt);
931 ext_el_pt->interpolated_q(s_ext, q);
935 outer_unit_normal(ipt, interpolated_normal);
939 interpolated_tangent[0] = -interpolated_normal[1];
940 interpolated_tangent[1] = interpolated_normal[0];
946 double lagrangian_eulerian_translation_factor = 1.0;
954 POROELASTICITY_BULK_ELEMENT,
955 FLUID_BULK_ELEMENT
>*>(external_element_pt(1, ipt));
958 if (ext_face_el_pt != 0)
992 lagrangian_eulerian_translation_factor =
993 ext_face_el_pt->lagrangian_eulerian_translation_factor(s_ext_face);
996 ext_face_el_pt->outer_unit_normal(s_ext_face, poro_normal);
997 poro_normal[0] = -poro_normal[0];
998 poro_normal[1] = -poro_normal[1];
1003 const double permeability = ext_el_pt->permeability();
1004 const double local_permeability_ratio = ext_el_pt->permeability_ratio();
1009 double poro_normal_component = 0.0;
1010 double poro_tangential_component = 0.0;
1014 dynamic_cast<FLUID_BULK_ELEMENT*
>(bulk_element_pt())
1015 ->traction(s_bulk, interpolated_normal, traction_nst);
1018 for (
unsigned i = 0;
i <
Dim;
i++)
1021 poro_normal_component +=
1023 (du_dt[
i] * interpolated_normal[
i] +
1024 permeability * q[
i] * lagrangian_eulerian_translation_factor *
1029 poro_tangential_component +=
1030 (local_st * du_dt[
i] - traction_nst[
i] *
1031 sqrt(local_permeability_ratio) *
1032 local_inverse_slip_rate_coeff) *
1033 interpolated_tangent[
i];
1037 double nst_normal_component = 0.0;
1038 double nst_tangential_component = 0.0;
1039 for (
unsigned i = 0;
i <
Dim;
i++)
1041 nst_normal_component += fluid_veloc[
i] * interpolated_normal[
i];
1042 nst_tangential_component += fluid_veloc[
i] * interpolated_tangent[
i];
1047 bjs_term[0] = nst_normal_component - poro_normal_component;
1048 bjs_term[1] = nst_tangential_component - poro_tangential_component;
1053 for (
unsigned l = 0; l < n_node; l++)
1056 for (
unsigned i = 0;
i <
Dim + 1;
i++)
1062 local_eqn = nodal_local_eqn(l, U_index_axisym_poroelastic_fsi[
i]);
1068 residuals[local_eqn] -= lambda[
i] * testf[l] * interpolated_r *
W;
1074 OOMPH_CURRENT_FUNCTION,
1075 OOMPH_EXCEPTION_LOCATION);
1078 for (
unsigned l2 = 0; l2 < n_node; l2++)
1085 int local_unknown = nodal_local_eqn(
1091 if (local_unknown >= 0)
1093 jacobian(local_eqn, local_unknown) -=
1094 psif[l2] * testf[l] * interpolated_r *
W;
1107 int local_eqn = nodal_local_eqn(
1116 std::stringstream junk;
1117 junk <<
"Elements have not been validated for nonzero swirl!\n";
1119 junk.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
1123 residuals[local_eqn] += bjs_term[
i] * testf(l) * interpolated_r *
W;
1129 OOMPH_CURRENT_FUNCTION,
1130 OOMPH_EXCEPTION_LOCATION);
1134 for (
unsigned l2 = 0; l2 < n_node; l2++)
1137 nodal_local_eqn(l2, U_index_axisym_poroelastic_fsi[
i]);
1140 if (local_unknown >= 0)
1142 jacobian(local_eqn, local_unknown) -=
1143 psif[l2] * testf[l] * interpolated_r *
W;
A class that contains the information required by Nodes that are located on Mesh boundaries....
unsigned index_of_first_value_assigned_by_face_element(const unsigned &face_id=0) const
Return the index of the first value associated with the i-th face element value. If no argument is sp...
A Class for the derivatives of shape functions The class design is essentially the same as Shape,...
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...
void set_ninteraction(const unsigned &n_interaction)
Set the number of interactions in the element This function is usually called in the specific element...
FiniteElement *& external_element_pt(const unsigned &interaction_index, const unsigned &ipt)
Access function to source element for specified interaction index at specified integration point.
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
FaceElements are elements that coincide with the faces of higher-dimensional "bulk" elements....
int & face_index()
Index of the face (a number that uniquely identifies the face in the element)
void outer_unit_normal(const Vector< double > &s, Vector< double > &unit_normal) const
Compute outer unit normal at the specified local coordinate.
Vector< double > local_coordinate_in_bulk(const Vector< double > &s) const
Return vector of local coordinates in bulk element, given the local coordinates in this FaceElement.
void add_additional_values(const Vector< unsigned > &nadditional_values, const unsigned &id)
Helper function adding additional values for the unknowns associated with the FaceElement....
FiniteElement *& bulk_element_pt()
Pointer to higher-dimensional "bulk" element.
double interpolated_x(const Vector< double > &s, const unsigned &i) const
Return FE interpolated coordinate x[i] at local coordinate s. Overloaded to get information from bulk...
double J_eulerian(const Vector< double > &s) const
Return the Jacobian of mapping from local to global coordinates at local position s....
double J_eulerian_at_knot(const unsigned &ipt) const
Return the Jacobian of the mapping from local to global coordinates at the ipt-th integration point O...
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
A general Finite Element class.
virtual void dshape_local_at_knot(const unsigned &ipt, Shape &psi, DShape &dpsids) const
Return the geometric shape function and its derivative w.r.t. the local coordinates at the ipt-th int...
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
virtual std::string tecplot_zone_string(const unsigned &nplot) const
Return string for tecplot zone header (when plotting nplot points in each "coordinate direction")
virtual void shape(const Vector< double > &s, Shape &psi) const =0
Calculate the geometric shape functions at local coordinate s. This function must be overloaded for e...
unsigned nnode() const
Return the number of nodes.
Integral *const & integral_pt() const
Return the pointer to the integration scheme (const version)
double nodal_position(const unsigned &n, const unsigned &i) const
Return the i-th coordinate at local node n. If the node is hanging, the appropriate interpolation is ...
virtual void build_face_element(const int &face_index, FaceElement *face_element_pt)
Function for building a lower dimensional FaceElement on the specified face of the FiniteElement....
virtual void shape_at_knot(const unsigned &ipt, Shape &psi) const
Return the geometric shape function at the ipt-th integration point.
static DenseMatrix< double > Dummy_matrix
Empty dense matrix used as a dummy argument to combined residual and jacobian functions in the case w...
unsigned add_external_data(Data *const &data_pt, const bool &fd=true)
Add a (pointer to an) external data object to the element and return its index (i....
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.
virtual double weight(const unsigned &i) const =0
Return weight of i-th integration point.
A class for elements that allow the imposition of the linearised poroelastic FSI slip condition (acco...
double inverse_slip_rate_coefficient() const
Inverse slip rate coefficient.
LinearisedAxisymPoroelasticBJS_FSIElement()
Default constructor.
void output(std::ostream &outfile, const unsigned &n_plot)
Output function: Output at Gauss points; n_plot is ignored.
double * St_pt
Pointer to fluid Strouhal number.
double st() const
Access function for the fluid Strouhal number.
LinearisedAxisymPoroelasticBJS_FSIElement(const LinearisedAxisymPoroelasticBJS_FSIElement &dummy)=delete
Broken copy constructor.
double * Inverse_slip_rate_coeff_pt
Pointer to inverse slip rate coefficient.
void fill_in_generic_residual_contribution_axisym_poroelastic_fsi(Vector< double > &residuals, DenseMatrix< double > &jacobian, const unsigned &flag)
Add the element's contribution to its residual vector. flag=1(or 0): do (or don't) compute the contri...
double contribution_to_enclosed_volume()
Return this element's contribution to the total volume enclosed by collection of these elements.
double shape_and_test(const Vector< double > &s, Shape &psi, Shape &test) const
Function to compute the shape and test functions and to return the Jacobian of mapping between local ...
double *& inverse_slip_rate_coefficient_pt()
Pointer to inverse slip rate coefficient.
void operator=(const LinearisedAxisymPoroelasticBJS_FSIElement &)=delete
Broken assignment operator.
void output(FILE *file_pt)
C-style output function.
Vector< unsigned > U_index_axisym_poroelastic_fsi
The index at which the velocity unknowns are stored at the nodes.
void output(std::ostream &outfile)
Output function.
double *& st_pt()
Access function for the pointer to the fluid Strouhal number (if not set, St defaults to 1)
void output(FILE *file_pt, const unsigned &n_plot)
C-style output function.
double shape_and_test_at_knot(const unsigned &ipt, Shape &psi, Shape &test) const
Function to compute the shape and test functions and to return the Jacobian of mapping between local ...
void fill_in_contribution_to_residuals(Vector< double > &residuals)
Add the element's contribution to its residual vector.
unsigned Dim
The spatial dimension of the problem.
void contribution_to_total_porous_flux(double &skeleton_flux_contrib, double &seepage_flux_contrib, double &nst_flux_contrib)
Compute contributions to integrated porous flux over boundary: q_skeleton = \int \partial u_displ / \...
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
unsigned ndim() const
Return (Eulerian) spatial dimension of the node.
double value(const unsigned &i) const
Return i-th value (dofs or pinned) at this node either directly or via hanging node representation....
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....
A Class for shape functions. In simple cases, the shape functions have only one index that can be tho...
bool Allow_gap_in_FSI
Public boolean to allow gap between poro-elastic and Navier Stokes element in FSI computations....
void output()
Doc the command line arguments.
double Default_strouhal_number
Default for fluid Strouhal number.
double Default_inverse_slip_rate_coefficient
Default for inverse slip rate coefficient: no slip.
const double Pi
50 digits from maple
unsigned Dim
Dimension of zeta tuples (set by get_dim_helper) – needed because we store the scalar coordinates in ...
double dot(const Vector< double > &a, const Vector< double > &b)
Probably not always best/fastest because not optimised for dimension but useful...
//////////////////////////////////////////////////////////////////// ////////////////////////////////...