31 #ifndef OOMPH_AXISYM_POROELASTIC_FSI_TRACTION_ELEMENTS_HEADER 32 #define OOMPH_AXISYM_POROELASTIC_FSI_TRACTION_ELEMENTS_HEADER 36 #include <oomph-lib-config.h> 41 #include "../generic/shape.h" 42 #include "../generic/elements.h" 43 #include "../generic/element_with_external_element.h" 56 namespace LinearisedAxisymPoroelasticBJS_FSIHelper
74 template <
class FLUID_BULK_ELEMENT,
class POROELASTICITY_BULK_ELEMENT>
89 const int& face_index,
90 const unsigned &
id=0);
100 "LinearisedAxisymPoroelasticBJS_FSIElement");
107 "LinearisedAxisymPoroelasticBJS_FSIElement");
123 return *Inverse_slip_rate_coeff_pt;
130 return Inverse_slip_rate_coeff_pt;
139 fill_in_generic_residual_contribution_axisym_poroelastic_fsi(
170 const unsigned n_node = this->nnode();
177 const unsigned n_intpt = this->integral_pt()->nweight();
183 for(
unsigned ipt=0;ipt<n_intpt;ipt++)
186 s[0] = this->integral_pt()->knot(ipt,0);
189 double W = this->integral_pt()->weight(ipt);
192 this->dshape_local_at_knot(ipt,psi,dpsids);
197 for(
unsigned l=0;l<n_node;l++)
200 for(
unsigned i=0;
i<2;
i++)
202 interpolated_x[
i] += this->nodal_position(l,
i)*psi(l);
203 interpolated_t1[
i] += this->nodal_position(l,
i)*dpsids(l,0);
208 double tlength = interpolated_t1[0]*interpolated_t1[0] +
209 interpolated_t1[1]*interpolated_t1[1];
212 double J = sqrt(tlength)*interpolated_x[0];
216 this->outer_unit_normal(ipt,interpolated_n);
220 for(
unsigned k=0;k<2;k++)
222 dot += interpolated_x[k]*interpolated_n[k];
245 void output(std::ostream &outfile,
const unsigned &n_plot)
248 unsigned n_node = nnode();
251 const unsigned n_intpt = integral_pt()->nweight();
254 outfile << this->tecplot_zone_string(n_intpt);
263 const double local_st=st();
266 const double local_inverse_slip_rate_coeff=inverse_slip_rate_coefficient();
269 for(
unsigned ipt=0;ipt<n_intpt;ipt++)
272 for(
unsigned i=0;
i<(
Dim-1);
i++)
274 s[
i] = integral_pt()->knot(ipt,
i);
279 outer_unit_normal(ipt,interpolated_normal);
283 interpolated_tangent[0]=-interpolated_normal[1];
284 interpolated_tangent[1]= interpolated_normal[0];
287 POROELASTICITY_BULK_ELEMENT* ext_el_pt=
288 dynamic_cast<POROELASTICITY_BULK_ELEMENT*
>(
289 external_element_pt(0,ipt));
293 ext_el_pt->interpolated_du_dt(s_ext,du_dt);
294 ext_el_pt->interpolated_q(s_ext,q);
295 x_bulk[0]=ext_el_pt->interpolated_x(s_ext,0);
296 x_bulk[1]=ext_el_pt->interpolated_x(s_ext,1);
300 this->interpolated_x(s,x);
306 double error=sqrt((x[0]-x_bulk[0])*(x[0]-x_bulk[0])+
307 (x[1]-x_bulk[1])*(x[1]-x_bulk[1]));
311 std::stringstream junk;
313 <<
"Gap between external and face element coordinate\n" 314 <<
"is suspiciously large: " 315 << error <<
"\nBulk/external at: " 316 << x_bulk[0] <<
" " << x_bulk[1] <<
"\n" 317 <<
"Face at: " << x[0] <<
" " << x[1] <<
"\n";
319 OOMPH_CURRENT_FUNCTION,
320 OOMPH_EXCEPTION_LOCATION);
326 const double permeability=ext_el_pt->permeability();
327 const double local_permeability_ratio=ext_el_pt->permeability_ratio();
331 s_bulk=local_coordinate_in_bulk(s);
335 dynamic_cast<FLUID_BULK_ELEMENT*
>(bulk_element_pt())->traction(
336 s_bulk,interpolated_normal,traction_nst);
340 dynamic_cast<FLUID_BULK_ELEMENT*
>(bulk_element_pt())->
341 interpolated_u_axi_nst(s_bulk,fluid_veloc);
344 double p_fluid=
dynamic_cast<FLUID_BULK_ELEMENT*
>(bulk_element_pt())->
345 interpolated_p_axi_nst(s_bulk);
348 double scaled_normal_wall_veloc=0.0;
349 double scaled_normal_poro_veloc=0.0;
350 double scaled_tangential_wall_veloc=0.0;
351 double scaled_tangential_poro_veloc=0.0;
352 double normal_nst_veloc=0.0;
353 for(
unsigned i=0;
i<
Dim;
i++)
355 scaled_normal_wall_veloc+=
356 local_st*du_dt[
i]*interpolated_normal[
i];
358 scaled_normal_poro_veloc+=
359 local_st*permeability*q[
i]*interpolated_normal[
i];
361 scaled_tangential_wall_veloc+=
362 local_st*du_dt[
i]*interpolated_tangent[
i];
364 scaled_tangential_poro_veloc+=
365 -traction_nst[
i]*sqrt(local_permeability_ratio)*
366 local_inverse_slip_rate_coeff*interpolated_tangent[
i];
368 normal_nst_veloc+=fluid_veloc[
i]*interpolated_normal[
i];
372 double total_poro_normal_component=
373 scaled_normal_wall_veloc+scaled_normal_poro_veloc;
374 double total_poro_tangential_component=
375 scaled_tangential_wall_veloc+scaled_tangential_poro_veloc;
377 for(
unsigned i=0;
i<
Dim;
i++)
380 total_poro_normal_component*interpolated_normal[
i]+
381 total_poro_tangential_component*interpolated_tangent[
i];
386 this->dshape_local_at_knot(ipt,psi,dpsids);
390 for(
unsigned l=0;l<n_node;l++)
393 for(
unsigned i=0;
i<2;
i++)
395 interpolated_t1[
i] += this->nodal_position(l,
i)*dpsids(l,0);
401 (interpolated_t1[0]*interpolated_t1[0])/
402 (interpolated_t1[1]*interpolated_t1[1]))*x[0];
406 double lagrangian_eulerian_translation_factor=1.0;
411 FLUID_BULK_ELEMENT>* ext_face_el_pt=
413 FLUID_BULK_ELEMENT
>*>(external_element_pt(1,ipt));
416 if (ext_face_el_pt!=0)
421 lagrangian_eulerian_translation_factor=
422 ext_face_el_pt->lagrangian_eulerian_translation_factor(s_ext_face);
431 << fluid_veloc[0] <<
" " 432 << fluid_veloc[1] <<
" " 433 << poro_veloc[0] <<
" " 434 << poro_veloc[1] <<
" " 435 << normal_nst_veloc*interpolated_normal[0] <<
" " 436 << normal_nst_veloc*interpolated_normal[1] <<
" " 437 << total_poro_normal_component*interpolated_normal[0] <<
" " 438 << total_poro_normal_component*interpolated_normal[1] <<
" " 439 << scaled_normal_wall_veloc*interpolated_normal[0] <<
" " 440 << scaled_normal_wall_veloc*interpolated_normal[1] <<
" " 441 << scaled_normal_poro_veloc*interpolated_normal[0] <<
" " 442 << scaled_normal_poro_veloc*interpolated_normal[1] <<
" " 447 << lagrangian_eulerian_translation_factor <<
" " 459 double& seepage_flux_contrib,
460 double& nst_flux_contrib)
463 const unsigned n_intpt = integral_pt()->nweight();
470 const unsigned n_node = this->nnode();
477 skeleton_flux_contrib=0.0;
478 seepage_flux_contrib=0.0;
479 nst_flux_contrib=0.0;
480 for(
unsigned ipt=0;ipt<n_intpt;ipt++)
483 for(
unsigned i=0;
i<(
Dim-1);
i++)
485 s[
i] = integral_pt()->knot(ipt,
i);
490 outer_unit_normal(ipt,interpolated_normal);
493 double W = this->integral_pt()->weight(ipt);
496 this->dshape_local_at_knot(ipt,psi,dpsids);
501 for(
unsigned l=0;l<n_node;l++)
504 for(
unsigned i=0;
i<2;
i++)
506 interpolated_x[
i] += this->nodal_position(l,
i)*psi(l);
507 interpolated_t1[
i] += this->nodal_position(l,
i)*dpsids(l,0);
512 double tlength = interpolated_t1[0]*interpolated_t1[0] +
513 interpolated_t1[1]*interpolated_t1[1];
516 double J = sqrt(tlength)*interpolated_x[0];
519 POROELASTICITY_BULK_ELEMENT* ext_el_pt=
520 dynamic_cast<POROELASTICITY_BULK_ELEMENT*
>(
521 external_element_pt(0,ipt));
525 ext_el_pt->interpolated_du_dt(s_ext,du_dt);
526 ext_el_pt->interpolated_q(s_ext,q);
527 x_bulk[0]=ext_el_pt->interpolated_x(s_ext,0);
528 x_bulk[1]=ext_el_pt->interpolated_x(s_ext,1);
536 this->interpolated_x(s,x);
538 double error=sqrt((interpolated_x[0]-x_bulk[0])*(interpolated_x[0]-x_bulk[0])+
539 (interpolated_x[1]-x_bulk[1])*(interpolated_x[1]-x_bulk[1]));
543 std::stringstream junk;
545 <<
"Gap between external and face element coordinate\n" 546 <<
"is suspiciously large: " 547 << error <<
"\nBulk/external at: " 548 << x_bulk[0] <<
" " << x_bulk[1] <<
"\n" 549 <<
"Face at: " << x[0] <<
" " << x[1] <<
"\n";
551 OOMPH_CURRENT_FUNCTION,
552 OOMPH_EXCEPTION_LOCATION);
559 double lagrangian_eulerian_translation_factor=1.0;
568 FLUID_BULK_ELEMENT>* ext_face_el_pt=
570 <POROELASTICITY_BULK_ELEMENT,
571 FLUID_BULK_ELEMENT
>*>(external_element_pt(1,ipt));
574 if (ext_face_el_pt!=0)
581 x_face[0]=ext_face_el_pt->interpolated_x(s_ext_face,0);
582 x_face[1]=ext_face_el_pt->interpolated_x(s_ext_face,1);
585 double error=std::fabs(x_bulk[0]-x_face[0])+std::fabs(x_bulk[1]-x_face[1]);
588 std::stringstream junk;
590 <<
"Difference in Eulerian coordinates: " << error
591 <<
" is suspiciously large: " 592 <<
"Bulk: " << x_bulk[0] <<
" " << x_bulk[1] <<
" " 593 <<
"Face: " << x_face[0] <<
" " << x_face[1] <<
"\n";
595 OOMPH_CURRENT_FUNCTION,
596 OOMPH_EXCEPTION_LOCATION);
602 lagrangian_eulerian_translation_factor=
603 ext_face_el_pt->lagrangian_eulerian_translation_factor(s_ext_face);
606 ext_face_el_pt->outer_unit_normal(s_ext_face,poro_normal);
607 poro_normal[0]=-poro_normal[0];
608 poro_normal[1]=-poro_normal[1];
613 const double permeability=ext_el_pt->permeability();
617 s_bulk=local_coordinate_in_bulk(s);
621 dynamic_cast<FLUID_BULK_ELEMENT*
>(bulk_element_pt())->
622 interpolated_u_axi_nst(s_bulk,fluid_veloc);
626 double dudt_flux=0.0;
628 for(
unsigned i=0;
i<2;
i++)
630 q_flux+=permeability*q[
i]*poro_normal[
i];
631 dudt_flux+=du_dt[
i]*interpolated_normal[
i];
632 nst_flux+=fluid_veloc[
i]*interpolated_normal[
i];
637 lagrangian_eulerian_translation_factor*W*J;
649 void output(FILE* file_pt,
const unsigned &n_plot)
664 unsigned n_node = nnode();
670 for(
unsigned i=0;
i<n_node;
i++) {test[
i] = psi[
i];}
673 return J_eulerian(s);
686 unsigned n_node = nnode();
689 shape_at_knot(ipt,psi);
692 for(
unsigned i=0;
i<n_node;
i++) {test[
i] = psi[
i];}
695 return J_eulerian_at_knot(ipt);
703 void fill_in_generic_residual_contribution_axisym_poroelastic_fsi(
705 const unsigned& flag);
738 template <
class FLUID_BULK_ELEMENT,
class POROELASTICITY_BULK_ELEMENT>
740 <FLUID_BULK_ELEMENT,POROELASTICITY_BULK_ELEMENT>::
741 LinearisedAxisymPoroelasticBJS_FSIElement(
743 const int &face_index,
744 const unsigned &
id) :
774 FLUID_BULK_ELEMENT* cast_bulk_el_pt=
775 dynamic_cast<FLUID_BULK_ELEMENT*
>(bulk_el_pt);
779 for(
unsigned i=0;
i<3;
i++)
786 unsigned n=cast_bulk_el_pt->nnode();
787 for (
unsigned j=0;j<n;j++)
789 Node* nod_pt=cast_bulk_el_pt->node_pt(j);
792 for (
unsigned jj=0;jj<nn;jj++)
817 template <
class FLUID_BULK_ELEMENT,
class POROELASTICITY_BULK_ELEMENT>
819 <FLUID_BULK_ELEMENT,POROELASTICITY_BULK_ELEMENT>
:: 822 const unsigned& flag)
825 const unsigned n_node =
nnode();
828 Shape psif(n_node), testf(n_node);
837 const double local_st=
st();
847 for(
unsigned ipt=0;ipt<n_intpt;ipt++)
860 double interpolated_r=0;
870 for(
unsigned j=0;j<n_node;j++)
879 unsigned first_index=
886 for(
unsigned i=0;
i<
Dim+1;
i++)
888 lambda[
i]+=nod_pt->
value(first_index+
i)*psif(j);
902 interpolated_u_axi_nst(s_bulk,fluid_veloc_from_bulk);
905 for(
unsigned i=0;
i<
Dim+1;
i++)
908 (fluid_veloc[
i]-fluid_veloc_from_bulk[
i])*
909 (fluid_veloc[
i]-fluid_veloc_from_bulk[
i]);
915 std::stringstream junk;
917 <<
"Difference in Navier-Stokes velocities\n" 918 <<
"is suspiciously large: " 919 << error <<
"\nVeloc from bulk: " 920 << fluid_veloc_from_bulk[0] <<
" " << fluid_veloc_from_bulk[1] <<
"\n" 921 <<
"Veloc from face: " 922 << fluid_veloc[0] <<
" " << fluid_veloc[1] <<
"\n";
924 OOMPH_CURRENT_FUNCTION,
925 OOMPH_EXCEPTION_LOCATION);
931 POROELASTICITY_BULK_ELEMENT* ext_el_pt=
932 dynamic_cast<POROELASTICITY_BULK_ELEMENT*
>(
936 ext_el_pt->interpolated_du_dt(s_ext,du_dt);
937 ext_el_pt->interpolated_q(s_ext,q);
945 interpolated_tangent[0]=-interpolated_normal[1];
946 interpolated_tangent[1]= interpolated_normal[0];
952 double lagrangian_eulerian_translation_factor=1.0;
957 FLUID_BULK_ELEMENT>* ext_face_el_pt=
962 if (ext_face_el_pt!=0)
994 lagrangian_eulerian_translation_factor=
995 ext_face_el_pt->lagrangian_eulerian_translation_factor(s_ext_face);
998 ext_face_el_pt->outer_unit_normal(s_ext_face,poro_normal);
999 poro_normal[0]=-poro_normal[0];
1000 poro_normal[1]=-poro_normal[1];
1005 const double permeability=ext_el_pt->permeability();
1006 const double local_permeability_ratio=ext_el_pt->permeability_ratio();
1011 double poro_normal_component=0.0;
1012 double poro_tangential_component=0.0;
1017 s_bulk,interpolated_normal,traction_nst);
1020 for(
unsigned i=0;
i<
Dim;
i++)
1023 poro_normal_component+=local_st*
1024 (du_dt[
i]*interpolated_normal[
i]+permeability*q[
i]*
1025 lagrangian_eulerian_translation_factor*poro_normal[
i]);
1029 poro_tangential_component+=
1030 (local_st*du_dt[
i]-traction_nst[
i]*
1031 sqrt(local_permeability_ratio)*local_inverse_slip_rate_coeff)
1032 *interpolated_tangent[
i];
1036 double nst_normal_component=0.0;
1037 double nst_tangential_component=0.0;
1038 for(
unsigned i=0;
i<
Dim;
i++)
1040 nst_normal_component+=fluid_veloc[
i]*interpolated_normal[
i];
1041 nst_tangential_component+=fluid_veloc[
i]*interpolated_tangent[
i];
1046 bjs_term[0]=nst_normal_component-poro_normal_component;
1047 bjs_term[1]=nst_tangential_component-poro_tangential_component;
1052 for(
unsigned l=0;l<n_node;l++)
1055 for(
unsigned i=0;
i<Dim+1;
i++)
1067 residuals[local_eqn]-=lambda[
i]*testf[l]*interpolated_r*
W;
1073 OOMPH_CURRENT_FUNCTION,
1074 OOMPH_EXCEPTION_LOCATION);
1077 for(
unsigned l2=0;l2<n_node;l2++)
1086 index_of_first_value_assigned_by_face_element(
Id)+i);
1089 if(local_unknown>=0)
1091 jacobian(local_eqn,local_unknown)-=
1092 psif[l2]*testf[l]*interpolated_r*
W;
1115 std::stringstream junk;
1116 junk <<
"Elements have not been validated for nonzero swirl!\n";
1118 OOMPH_CURRENT_FUNCTION,
1119 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++)
1140 if(local_unknown>=0)
1142 jacobian(local_eqn,local_unknown)-=
1143 psif[l2]*testf[l]*interpolated_r*
W;
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 broken_copy(const std::string &class_name)
Issue error message and terminate execution.
bool Allow_gap_in_FSI
Public boolean to allow gap between poro-elastic and Navier Stokes element in FSI computations...
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...
double * St_pt
Pointer to fluid Strouhal number.
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 ...
A class for elements that allow the imposition of the linearised poroelastic FSI slip condition (acco...
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 ...
LinearisedAxisymPoroelasticBJS_FSIElement(const LinearisedAxisymPoroelasticBJS_FSIElement &dummy)
Broken copy constructor.
const double Pi
50 digits from maple
void outer_unit_normal(const Vector< double > &s, Vector< double > &unit_normal) const
Compute outer unit normal at the specified local coordinate.
double contribution_to_enclosed_volume()
Return this element's contribution to the total volume enclosed by collection of these elements...
A general Finite Element class.
Nodes are derived from Data, but, in addition, have a definite (Eulerian) position in a space of a gi...
void set_ninteraction(const unsigned &n_interaction)
Set the number of interactions in the element This function is usually called in the specific element...
void output(FILE *file_pt)
C-style output function.
double Default_strouhal_number
Default for fluid Strouhal number.
void output(std::ostream &outfile, const unsigned &n_plot)
Output function: Output at Gauss points; n_plot is ignored.
double * Inverse_slip_rate_coeff_pt
Pointer to inverse slip rate coefficient.
virtual double weight(const unsigned &i) const =0
Return weight of i-th integration point.
unsigned add_external_data(Data *const &data_pt, const bool &fd=true)
void add_additional_values(const Vector< unsigned > &nadditional_values, const unsigned &id)
Helper function adding additional values for the unknowns associated with the FaceElement. This function also sets the map containing the position of the first entry of this face element's additional values.The inputs are the number of additional values and the face element's ID. Note the same number of additonal values are allocated at ALL nodes.
unsigned Dim
Dimension of zeta tuples (set by get_dim_helper) – needed because we store the scalar coordinates in...
unsigned Dim
The spatial dimension of the problem.
unsigned ndim() const
Return (Eulerian) spatial dimension of the node.
A class that contains the information required by Nodes that are located on Mesh boundaries. A BoundaryNode of a particular type is obtained by combining a given Node with this class. By differentiating between Nodes and BoundaryNodes we avoid a lot of un-necessary storage in the bulk Nodes.
double *& st_pt()
Access function for the pointer to the fluid Strouhal number (if not set, St defaults to 1) ...
void operator=(const LinearisedAxisymPoroelasticBJS_FSIElement &)
Broken assignment operator.
Integral *const & integral_pt() const
Return the pointer to the integration scheme (const version)
virtual double knot(const unsigned &i, const unsigned &j) const =0
Return local coordinate s[j] of i-th integration point.
Node *& node_pt(const unsigned &n)
Return a pointer to the local node n.
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...
void shape(const double &s, double *Psi)
Definition for 1D Lagrange shape functions. The value of all the shape functions at the local coordin...
void output(std::ostream &outfile)
Output with default number of plot points.
void fill_in_contribution_to_residuals(Vector< double > &residuals)
Add the element's contribution to its residual vector.
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...
double Default_inverse_slip_rate_coefficient
Default for inverse slip rate coefficient: no slip.
void output(std::ostream &outfile)
Output function.
double dot(const Vector< double > &a, const Vector< double > &b)
Probably not always best/fastest because not optimised for dimension but useful...
void broken_assign(const std::string &class_name)
Issue error message and terminate execution.
LinearisedAxisymPoroelasticBJS_FSIElement()
Default constructor.
virtual unsigned nweight() const =0
Return the number of integration points of the scheme.
FiniteElement *& external_element_pt(const unsigned &interaction_index, const unsigned &ipt)
Access function to source element for specified interaction index at specified integration point...
FiniteElement *& bulk_element_pt()
Pointer to higher-dimensional "bulk" element.
void output(FILE *file_pt, const unsigned &n_plot)
C-style output function.
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...
double st() const
Access function for the fluid Strouhal number.
Vector< unsigned > U_index_axisym_poroelastic_fsi
The index at which the velocity unknowns are stored at the nodes.
double *& inverse_slip_rate_coefficient_pt()
Pointer to inverse slip rate coefficient.
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 = u_displ / t n ds q_se...
unsigned nnode() const
Return the number of nodes.
double inverse_slip_rate_coefficient() const
Inverse slip rate coefficient.
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...
double value(const unsigned &i) const
Return i-th value (dofs or pinned) at this node either directly or via hanging node representation...
static DenseMatrix< double > Dummy_matrix
Empty dense matrix used as a dummy argument to combined residual and jacobian functions in the case w...
int nodal_local_eqn(const unsigned &n, const unsigned &i) const
Return the local equation number corresponding to the i-th value at the n-th local node...