30 #include "../generic/integral.h"
62 ->hijack_kinematic_conditions(Bulk_node_number);
87 Vector<double>& residuals, DenseMatrix<double>& jacobian,
unsigned flag)
90 FiniteElement* parent_pt = bulk_element_pt();
93 unsigned spatial_dim = this->nodal_dimension();
96 Vector<double> wall_normal(spatial_dim);
99 Vector<double> unit_normal(spatial_dim);
102 Vector<double> x(spatial_dim);
105 unsigned n_dim = parent_pt->dim();
108 Vector<double> s_local(0);
111 this->interpolated_x(s_local, x);
117 Vector<double> s_parent(n_dim);
118 this->get_local_coordinate_in_bulk(s_local, s_parent);
121 dynamic_cast<FaceElement*
>(parent_pt)->outer_unit_normal(s_parent,
126 for (
unsigned i = 0; i < spatial_dim; i++)
128 dot += unit_normal[i] * wall_normal[i];
139 Vector<double> wall_tangent(spatial_dim);
140 wall_tangent[0] = -wall_normal[1];
141 wall_tangent[1] = wall_normal[0];
144 double ca_local =
ca();
147 for (
unsigned i = 0; i < 2; i++)
152 residuals[local_eqn] +=
153 (sigma_local / ca_local) * (sin(
contact_angle()) * wall_normal[i] +
166 Vector<double> m(spatial_dim);
167 this->outer_unit_normal(s_local, m);
170 double ca_local =
ca();
175 for (
unsigned i = 0; i < 2; i++)
180 residuals[local_eqn] += (sigma_local / ca_local) * m[i];
205 DShape dpsifds(1, 1);
206 Vector<double> interpolated_n(1);
211 residuals, jacobian, flag, psif, dpsifds, interpolated_n, W);
225 Vector<double>& residuals, DenseMatrix<double>& jacobian,
unsigned flag)
228 FiniteElement* parent_pt = bulk_element_pt();
231 unsigned spatial_dim = this->nodal_dimension();
234 Vector<double> wall_normal(spatial_dim);
237 Vector<double> unit_normal(spatial_dim);
240 unsigned n_dim = parent_pt->dim();
243 Vector<double> s_parent(n_dim);
246 unsigned n_node = this->nnode();
248 DShape dpsids(n_node, 1);
249 Vector<double> s_local(1);
252 unsigned n_intpt = this->integral_pt()->nweight();
253 for (
unsigned ipt = 0; ipt < n_intpt; ++ipt)
256 s_local[0] = this->integral_pt()->knot(ipt, 0);
257 get_local_coordinate_in_bulk(s_local, s_parent);
260 this->dshape_local(s_local, psi, dpsids);
263 Vector<double> x(spatial_dim, 0.0);
266 Vector<double> interpolated_t1(spatial_dim, 0.0);
267 for (
unsigned n = 0; n < n_node; n++)
269 const double psi_local = psi(n);
270 const double dpsi_local = dpsids(n, 0);
271 for (
unsigned i = 0; i < spatial_dim; i++)
273 double pos = this->nodal_position(n, i);
274 interpolated_t1[i] += pos * dpsi_local;
275 x[i] += pos * psi_local;
280 double t_length = 0.0;
281 for (
unsigned i = 0; i < spatial_dim; ++i)
283 t_length += interpolated_t1[i] * interpolated_t1[i];
285 double W = std::sqrt(t_length) * this->integral_pt()->weight(ipt);
291 dynamic_cast<FaceElement*
>(parent_pt)->outer_unit_normal(s_parent,
299 for (
unsigned i = 0; i < spatial_dim; i++)
301 dot += unit_normal[i] * wall_normal[i];
305 Vector<double> binorm(spatial_dim);
306 for (
unsigned i = 0; i < spatial_dim; i++)
308 binorm[i] = unit_normal[i] - dot * wall_normal[i];
312 const double sigma_local =
316 const double ca_local =
ca();
324 for (
unsigned l = 0; l < n_node; l++)
327 for (
unsigned i = 0; i < 3; i++)
337 residuals[local_eqn] +=
338 (sigma_local / ca_local) *
339 (sin(theta) * wall_normal[i] + cos(theta) * binorm[i]) *
354 this->outer_unit_normal(s_local, m);
357 const double sigma_local =
361 const double ca_local =
ca();
364 for (
unsigned l = 0; l < n_node; l++)
367 for (
unsigned i = 0; i < 3; i++)
377 residuals[local_eqn] +=
378 m[i] * (sigma_local / ca_local) * psi(l) * W;
390 dynamic_cast<FaceElement*
>(parent_pt)->outer_unit_normal(s_parent,
398 for (
unsigned i = 0; i < spatial_dim; i++)
400 dot += unit_normal[i] * wall_normal[i];
404 for (
unsigned l = 0; l < n_node; l++)
414 residuals[local_eqn] += (cos(
contact_angle()) + dot) * psi(l) * W;
423 residuals, jacobian, flag, psi, dpsids, unit_normal, W);
446 unsigned n_node = FiniteElement::nnode();
458 for (
unsigned l = 0; l < n_node; l++)
472 Vector<double>& residuals, DenseMatrix<double>& jacobian,
unsigned flag)
475 unsigned n_node = this->nnode();
481 const unsigned el_dim = this->dim();
483 DShape dpsifds(n_node, el_dim);
489 const unsigned n_dim = this->nodal_dimension();
495 DShape dpsifdS(n_node, n_dim);
496 DShape dpsifdS_div(n_node, n_dim);
499 unsigned n_intpt = this->integral_pt()->nweight();
508 double p_ext =
pext();
511 int local_eqn = 0, local_unknown = 0;
514 Vector<double> s(el_dim);
517 for (
unsigned ipt = 0; ipt < n_intpt; ipt++)
520 for (
unsigned i = 0; i < el_dim; i++)
522 s[i] = this->integral_pt()->knot(ipt, i);
526 double W = this->integral_pt()->weight(ipt);
529 this->dshape_local_at_knot(ipt, psif, dpsifds);
532 Vector<double> interpolated_x(n_dim, 0.0);
534 Vector<double> interpolated_dx_dt(n_dim, 0.0);
536 DenseMatrix<double> interpolated_t(el_dim, n_dim, 0.0);
539 for (
unsigned l = 0; l < n_node; l++)
541 const double psi_ = psif(l);
543 for (
unsigned i = 0; i < n_dim; i++)
546 interpolated_x[i] += this->nodal_position(l, i) * psi_;
549 interpolated_dx_dt[i] += this->dnodal_position_dt(l, i) * psi_;
552 for (
unsigned j = 0; j < el_dim; j++)
554 interpolated_t(j, i) += this->nodal_position(l, i) * dpsifds(l, j);
565 psif, dpsifds, interpolated_t, interpolated_x, dpsifdS, dpsifdS_div);
569 Vector<double> interpolated_n(n_dim);
570 this->outer_unit_normal(s, interpolated_n);
573 double Sigma = this->
sigma(s);
576 for (
unsigned l = 0; l < n_node; l++)
579 for (
unsigned i = 0; i < n_dim; i++)
588 residuals[local_eqn] -= (Sigma /
Ca) * dpsifdS_div(l, i) * J * W;
594 residuals[local_eqn] -=
595 p_ext * interpolated_n[i] * psif(l) * J * W;
603 if (local_unknown >= 0)
605 jacobian(local_eqn, local_unknown) -=
606 interpolated_n[i] * psif(l) * J * W;
620 for (
unsigned k = 0; k < n_dim; k++)
622 residuals[local_eqn] +=
624 interpolated_n[k] * psif(l) * J * W;
631 for (
unsigned l2 = 0; l2 < n_node; l2++)
634 for (
unsigned i2 = 0; i2 < n_dim; i2++)
639 if (local_unknown >= 0)
641 jacobian(local_eqn, local_unknown) +=
642 psif(l2) * interpolated_n[i2] * psif(l) * J * W;
673 const unsigned& n_plot)
675 const unsigned el_dim = this->dim();
676 const unsigned n_dim = this->nodal_dimension();
679 Vector<double> s(el_dim);
682 outfile << tecplot_zone_string(n_plot);
685 unsigned num_plot_points = nplot_points(n_plot);
686 for (
unsigned iplot = 0; iplot < num_plot_points; iplot++)
689 get_s_plot(iplot, n_plot, s);
692 for (
unsigned i = 0; i < n_dim; i++)
693 outfile << this->interpolated_x(s, i) <<
" ";
694 for (
unsigned i = 0; i < n_velocity; i++)
698 outfile << 0.0 <<
"\n";
701 write_tecplot_zone_footer(outfile, n_plot);
712 const unsigned el_dim = this->dim();
713 const unsigned n_dim = this->nodal_dimension();
716 Vector<double> s(el_dim);
719 fprintf(file_pt,
"%s", tecplot_zone_string(n_plot).c_str());
722 unsigned num_plot_points = nplot_points(n_plot);
723 for (
unsigned iplot = 0; iplot < num_plot_points; iplot++)
726 get_s_plot(iplot, n_plot, s);
729 for (
unsigned i = 0; i < n_dim; i++)
731 fprintf(file_pt,
"%g ", interpolated_x(s, i));
735 for (
unsigned i = 0; i < n_velocity; i++)
741 fprintf(file_pt,
"%g \n", 0.0);
743 fprintf(file_pt,
"\n");
746 write_tecplot_zone_footer(file_pt, n_plot);
759 const DShape& dpsids,
760 const DenseMatrix<double>& interpolated_t,
761 const Vector<double>& interpolated_x,
765 const unsigned n_shape = psi.nindex1();
766 const unsigned n_dim = 2;
770 double a11 = interpolated_t(0, 0) * interpolated_t(0, 0) +
771 interpolated_t(0, 1) * interpolated_t(0, 1);
774 for (
unsigned l = 0; l < n_shape; l++)
776 for (
unsigned i = 0; i < n_dim; i++)
778 dpsidS(l, i) = dpsids(l, 0) * interpolated_t(0, i) / a11;
800 const DShape& dpsids,
801 const DenseMatrix<double>& interpolated_t,
802 const Vector<double>& interpolated_x,
807 const unsigned n_shape = psi.nindex1();
808 const unsigned n_dim = 2;
812 double a11 = interpolated_t(0, 0) * interpolated_t(0, 0) +
813 interpolated_t(0, 1) * interpolated_t(0, 1);
816 for (
unsigned l = 0; l < n_shape; l++)
818 for (
unsigned i = 0; i < n_dim; i++)
820 dpsidS(l, i) = dpsids(l, 0) * interpolated_t(0, i) / a11;
822 dpsidS_div(l, i) = dpsidS(l, i);
826 const double r = interpolated_x[0];
830 for (
unsigned l = 0; l < n_shape; l++)
832 dpsidS_div(l, 0) += psi(l) / r;
836 return r * sqrt(a11);
849 const DShape& dpsids,
850 const DenseMatrix<double>& interpolated_t,
851 const Vector<double>& interpolated_x,
855 const unsigned n_shape = psi.nindex1();
856 const unsigned n_dim = 3;
861 for (
unsigned al = 0; al < 2; al++)
863 for (
unsigned be = 0; be < 2; be++)
868 for (
unsigned i = 0; i < n_dim; i++)
870 amet[al][be] += interpolated_t(al, i) * interpolated_t(be, i);
876 double det_a = amet[0][0] * amet[1][1] - amet[0][1] * amet[1][0];
879 aup[0][0] = amet[1][1] / det_a;
880 aup[0][1] = -amet[0][1] / det_a;
881 aup[1][0] = -amet[1][0] / det_a;
882 aup[1][1] = amet[0][0] / det_a;
886 for (
unsigned l = 0; l < n_shape; l++)
889 const double dpsi_temp[2] = {
890 aup[0][0] * dpsids(l, 0) + aup[0][1] * dpsids(l, 1),
891 aup[1][0] * dpsids(l, 0) + aup[1][1] * dpsids(l, 1)};
893 for (
unsigned i = 0; i < n_dim; i++)
895 dpsidS(l, i) = dpsi_temp[0] * interpolated_t(0, i) +
896 dpsi_temp[1] * interpolated_t(1, i);
double compute_surface_derivatives(const Shape &psi, const DShape &dpsids, const DenseMatrix< double > &interpolated_t, const Vector< double > &interpolated_x, DShape &surface_gradient, DShape &surface_divergence)
Fill in the specific surface derivative calculations.
Vector< unsigned > U_index_interface_boundary
Index at which the i-th velocity component is stored in the element's nodes.
virtual int kinematic_local_eqn(const unsigned &n)=0
Function that is used to determine the local equation number of the kinematic equation associated wit...
void wall_unit_normal(const Vector< double > &x, Vector< double > &normal)
Function that returns the unit normal of the bounding wall directed out of the fluid.
double * Contact_angle_pt
Pointer to the desired value of the contact angle (if any)
virtual void add_additional_residual_contributions_interface_boundary(Vector< double > &residuals, DenseMatrix< double > &jacobian, const unsigned &flag, const Shape &psif, const DShape &dpsifds, const Vector< double > &interpolated_n, const double &W)
Empty helper function to calculate the additional contributions arising from the node update strategy...
double & contact_angle()
Return value of the contact angle.
void set_contact_angle(double *const &angle_pt, const bool &strong=true)
Set a pointer to the desired contact angle. Optional boolean (defaults to true) chooses strong imposi...
double ca()
Return the value of the capillary number.
unsigned Contact_angle_flag
Flag used to determine whether the contact angle is to be used (0 if not), and whether it will be app...
Base class establishing common interfaces and functions for all Navier-Stokes-like fluid interface el...
virtual double compute_surface_derivatives(const Shape &psi, const DShape &dpsids, const DenseMatrix< double > &interpolated_t, const Vector< double > &interpolated_x, DShape &dpsidS, DShape &dpsidS_div)=0
Compute the surface gradient and surface divergence operators given the shape functions,...
virtual void add_additional_residual_contributions_interface(Vector< double > &residuals, DenseMatrix< double > &jacobian, const unsigned &flag, const Shape &psif, const DShape &dpsifds, const DShape &dpsifdS, const DShape &dpsifdS_div, const Vector< double > &s, const Vector< double > &interpolated_x, const Vector< double > &interpolated_n, const double &W, const double &J)
Helper function to calculate the additional contributions to the resisuals and Jacobian that arise fr...
const double & st() const
The value of the Strouhal number.
double u(const unsigned &j, const unsigned &i)
Return the i-th velocity component at local node j.
virtual int kinematic_local_eqn(const unsigned &n)=0
Access function that returns the local equation number for the (scalar) kinematic equation associated...
Vector< unsigned > U_index_interface
Nodal index at which the i-th velocity component is stored.
double pext() const
Return the value of the external pressure.
virtual double sigma(const Vector< double > &s_local)
Virtual function that specifies the non-dimensional surface tension as a function of local position w...
double interpolated_u(const Vector< double > &s, const unsigned &i)
Calculate the i-th velocity component at the local coordinate s.
Data * Pext_data_pt
Pointer to the Data item that stores the external pressure.
void output(std::ostream &outfile)
Overload the output function.
const double & ca() const
The value of the Capillary number.
int pext_local_eqn()
Access function for the local equation number that corresponds to the external pressure.
static double Default_Physical_Constant_Value
Default value for physical constants.
virtual void fill_in_generic_residual_contribution_interface(Vector< double > &residuals, DenseMatrix< double > &jacobian, unsigned flag)
Helper function to calculate the residuals and (if flag==1) the Jacobian of the equations....
double compute_surface_derivatives(const Shape &psi, const DShape &dpsids, const DenseMatrix< double > &interpolated_t, const Vector< double > &interpolated_x, DShape &surface_gradient, DShape &surface_divergence)
Fill in the specific surface derivative calculations.
void fill_in_generic_residual_contribution_interface_boundary(Vector< double > &residuals, DenseMatrix< double > &jacobian, unsigned flag)
Overload the helper function to calculate the residuals and (if flag==true) the Jacobian – this funct...
void fill_in_generic_residual_contribution_interface_boundary(Vector< double > &residuals, DenseMatrix< double > &jacobian, unsigned flag)
Overload the helper function to calculate the residuals and (if flag==1) the Jacobian – this function...
double compute_surface_derivatives(const Shape &psi, const DShape &dpsids, const DenseMatrix< double > &interpolated_t, const Vector< double > &interpolated_x, DShape &surface_gradient, DShape &surface_divergence)
Fill in the specific surface derivative calculations.
double Ca
Capillary number.