34 #include "../generic/integral.h" 67 ->hijack_kinematic_conditions(Bulk_node_number);
93 Vector<double> &residuals,
94 DenseMatrix<double> &jacobian,
98 FiniteElement* parent_pt = bulk_element_pt();
101 unsigned spatial_dim = this->nodal_dimension();
104 Vector<double> wall_normal(spatial_dim);
107 Vector<double> unit_normal(spatial_dim);
110 Vector<double> x(spatial_dim);
113 unsigned n_dim = parent_pt->dim();
116 Vector<double> s_local(0);
119 this->interpolated_x(s_local,x);
125 Vector<double> s_parent(n_dim);
126 this->get_local_coordinate_in_bulk(s_local,s_parent);
129 dynamic_cast<FaceElement*
>(parent_pt)->
130 outer_unit_normal(s_parent,unit_normal);
134 for(
unsigned i=0;i<spatial_dim;i++)
135 {dot += unit_normal[i]*wall_normal[i];}
145 Vector<double> wall_tangent(spatial_dim);
146 wall_tangent[0] = - wall_normal[1];
147 wall_tangent[1] = wall_normal[0];
150 double ca_local =
ca();
153 for(
unsigned i=0;i<2;i++)
158 residuals[local_eqn] +=
172 Vector<double> m(spatial_dim);
173 this->outer_unit_normal(s_local,m);
176 double ca_local =
ca();
181 for(
unsigned i=0;i<2;i++)
186 residuals[local_eqn] += (sigma_local/ca_local)*m[i];
212 Vector<double> interpolated_n(1);
239 Vector<double> &residuals,
240 DenseMatrix<double> &jacobian,
244 FiniteElement* parent_pt = bulk_element_pt();
247 unsigned spatial_dim = this->nodal_dimension();
250 Vector<double> wall_normal(spatial_dim);
253 Vector<double> unit_normal(spatial_dim);
256 unsigned n_dim = parent_pt->dim();
259 Vector<double> s_parent(n_dim);
262 unsigned n_node = this->nnode();
264 DShape dpsids(n_node,1);
265 Vector<double> s_local(1);
268 unsigned n_intpt = this->integral_pt()->nweight();
269 for(
unsigned ipt=0;ipt<n_intpt;++ipt)
272 s_local[0] = this->integral_pt()->knot(ipt,0);
273 get_local_coordinate_in_bulk(s_local,s_parent);
276 this->dshape_local(s_local,psi,dpsids);
279 Vector<double> x(spatial_dim,0.0);
282 Vector<double> interpolated_t1(spatial_dim,0.0);
283 for(
unsigned n=0;n<n_node;n++)
285 const double psi_local = psi(n);
286 const double dpsi_local = dpsids(n,0);
287 for(
unsigned i=0;i<spatial_dim;i++)
289 double pos = this->nodal_position(n,i);
290 interpolated_t1[i] += pos*dpsi_local;
291 x[i] += pos*psi_local;
296 double t_length = 0.0;
297 for(
unsigned i=0;i<spatial_dim;++i)
298 {t_length += interpolated_t1[i]*interpolated_t1[i];}
299 double W = std::sqrt(t_length)*this->integral_pt()->weight(ipt);
305 dynamic_cast<FaceElement*
>(parent_pt)->
306 outer_unit_normal(s_parent,unit_normal);
313 for(
unsigned i=0;i<spatial_dim;i++)
314 {dot += unit_normal[i]*wall_normal[i];}
317 Vector<double> binorm(spatial_dim);
318 for(
unsigned i=0;i<spatial_dim;i++)
319 {binorm[i] = unit_normal[i] - dot*wall_normal[i];}
322 const double sigma_local =
326 const double ca_local =
ca();
334 for(
unsigned l=0;l<n_node;l++)
337 for(
unsigned i=0;i<3;i++)
346 residuals[local_eqn] += (sigma_local/ca_local)*
347 (sin(theta)*wall_normal[i]
348 + cos(theta)*binorm[i])*psi(l)*W;
362 this->outer_unit_normal(s_local,m);
365 const double sigma_local =
370 const double ca_local =
ca();
373 for(
unsigned l=0;l<n_node;l++)
376 for(
unsigned i=0;i<3;i++)
385 residuals[local_eqn] += m[i]*(sigma_local/ca_local)*psi(l)*W;
397 dynamic_cast<FaceElement*
>(parent_pt)->
398 outer_unit_normal(s_parent,unit_normal);
405 for(
unsigned i=0;i<spatial_dim;i++)
406 {dot += unit_normal[i]*wall_normal[i];}
409 for(
unsigned l=0;l<n_node;l++)
419 residuals[local_eqn] +=
429 residuals,jacobian,flag,psi,dpsids,unit_normal,W);
452 unsigned n_node = FiniteElement::nnode();
461 double interpolated_u = 0.0;
464 for(
unsigned l=0;l<n_node;l++) {interpolated_u += u(l,i)*psi(l);}
466 return(interpolated_u);
475 DenseMatrix<double> &jacobian,
479 unsigned n_node = this->nnode();
485 const unsigned el_dim = this->dim();
487 DShape dpsifds(n_node,el_dim);
493 const unsigned n_dim = this->nodal_dimension();
499 DShape dpsifdS(n_node,n_dim);
500 DShape dpsifdS_div(n_node,n_dim);
503 unsigned n_intpt = this->integral_pt()->nweight();
512 double p_ext = pext();
515 int local_eqn=0, local_unknown=0;
518 Vector<double> s(el_dim);
521 for(
unsigned ipt=0;ipt<n_intpt;ipt++)
524 for(
unsigned i=0;i<el_dim;i++) {s[i] = this->integral_pt()->knot(ipt,i);}
527 double W = this->integral_pt()->weight(ipt);
530 this->dshape_local_at_knot(ipt,psif,dpsifds);
533 Vector<double> interpolated_x(n_dim,0.0);
534 Vector<double> interpolated_u(n_dim,0.0);
535 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);
558 interpolated_u[i] += u(l,i)*psi_;
566 this->compute_surface_derivatives(psif,dpsifds,
574 Vector<double> interpolated_n(n_dim);
575 this->outer_unit_normal(s,interpolated_n);
578 double Sigma = this->sigma(s);
581 for(
unsigned l=0;l<n_node;l++)
584 for(
unsigned i=0;i<n_dim;i++)
587 local_eqn = this->nodal_local_eqn(l,this->U_index_interface[i]);
593 residuals[local_eqn] -= (Sigma/
Ca)*dpsifdS_div(l,i)*J*W;
599 residuals[local_eqn] -= p_ext*interpolated_n[i]*psif(l)*J*W;
606 local_unknown = pext_local_eqn();
607 if(local_unknown >= 0)
609 jacobian(local_eqn,local_unknown) -=
610 interpolated_n[i]*psif(l)*J*W;
624 for(
unsigned k=0;k<n_dim;k++)
626 residuals[local_eqn] +=
627 (interpolated_u[k] - St*interpolated_dx_dt[k])
628 *interpolated_n[k]*psif(l)*J*W;
635 for(
unsigned l2=0;l2<n_node;l2++)
638 for(
unsigned i2=0;i2<n_dim;i2++)
641 this->nodal_local_eqn(l2,this->U_index_interface[i2]);
643 if(local_unknown >= 0)
645 jacobian(local_eqn,local_unknown) +=
646 psif(l2)*interpolated_n[i2]*psif(l)*J*W;
657 add_additional_residual_contributions_interface(residuals,
677 output(std::ostream &outfile,
const unsigned &n_plot)
679 const unsigned el_dim = this->dim();
680 const unsigned n_dim = this->nodal_dimension();
681 const unsigned n_velocity = this->U_index_interface.size();
683 Vector<double> s(el_dim);
686 outfile << tecplot_zone_string(n_plot);
689 unsigned num_plot_points=nplot_points(n_plot);
690 for (
unsigned iplot=0;iplot<num_plot_points;iplot++)
693 get_s_plot(iplot,n_plot,s);
696 for(
unsigned i=0;i<n_dim;i++) outfile << this->interpolated_x(s,i) <<
" ";
697 for(
unsigned i=0;i<n_velocity;i++) outfile << interpolated_u(s,i) <<
" ";
700 outfile << 0.0 <<
"\n";
703 write_tecplot_zone_footer(outfile,n_plot);
714 output(FILE* file_pt,
const unsigned &n_plot)
716 const unsigned el_dim = this->dim();
717 const unsigned n_dim = this->nodal_dimension();
718 const unsigned n_velocity = this->U_index_interface.size();
720 Vector<double> s(el_dim);
723 fprintf(file_pt,
"%s",tecplot_zone_string(n_plot).c_str());
726 unsigned num_plot_points=nplot_points(n_plot);
727 for (
unsigned iplot=0;iplot<num_plot_points;iplot++)
730 get_s_plot(iplot,n_plot,s);
733 for(
unsigned i=0;i<n_dim;i++)
735 fprintf(file_pt,
"%g ",interpolated_x(s,i));
739 for(
unsigned i=0;i<n_velocity;i++)
741 fprintf(file_pt,
"%g ",interpolated_u(s,i));
745 fprintf(file_pt,
"%g \n",0.0);
747 fprintf(file_pt,
"\n");
750 write_tecplot_zone_footer(file_pt,n_plot);
764 const Shape &psi,
const DShape &dpsids,
765 const DenseMatrix<double> &interpolated_t,
766 const Vector<double> &interpolated_x,
770 const unsigned n_shape = psi.nindex1();
771 const unsigned n_dim = 2;
775 double a11 = interpolated_t(0,0)*interpolated_t(0,0) +
776 interpolated_t(0,1)*interpolated_t(0,1);
779 for(
unsigned l=0;l<n_shape;l++)
781 for(
unsigned i=0;i<n_dim;i++)
783 dpsidS(l,i) = dpsids(l,0)*interpolated_t(0,i)/a11;
804 const Shape &psi,
const DShape &dpsids,
805 const DenseMatrix<double> &interpolated_t,
806 const Vector<double> &interpolated_x,
811 const unsigned n_shape = psi.nindex1();
812 const unsigned n_dim = 2;
816 double a11 = interpolated_t(0,0)*interpolated_t(0,0) +
817 interpolated_t(0,1)*interpolated_t(0,1);
820 for(
unsigned l=0;l<n_shape;l++)
822 for(
unsigned i=0;i<n_dim;i++)
824 dpsidS(l,i) = dpsids(l,0)*interpolated_t(0,i)/a11;
826 dpsidS_div(l,i) = dpsidS(l,i);
830 const double r = interpolated_x[0];
834 for(
unsigned l=0;l<n_shape;l++)
836 dpsidS_div(l,0) += psi(l)/r;
852 const Shape &psi,
const DShape &dpsids,
853 const DenseMatrix<double> &interpolated_t,
854 const Vector<double> &interpolated_x,
858 const unsigned n_shape = psi.nindex1();
859 const unsigned n_dim = 3;
864 for(
unsigned al=0;al<2;al++)
866 for(
unsigned be=0;be<2;be++)
871 for(
unsigned i=0;i<n_dim;i++)
873 amet[al][be] += interpolated_t(al,i)*interpolated_t(be,i);
879 double det_a = amet[0][0]*amet[1][1] - amet[0][1]*amet[1][0];
882 aup[0][0] = amet[1][1]/det_a;
883 aup[0][1] = -amet[0][1]/det_a;
884 aup[1][0] = -amet[1][0]/det_a;
885 aup[1][1] = amet[0][0]/det_a;
889 for(
unsigned l=0;l<n_shape;l++)
892 const double dpsi_temp[2] =
893 {aup[0][0]*dpsids(l,0) + aup[0][1]*dpsids(l,1),
894 aup[1][0]*dpsids(l,0) + aup[1][1]*dpsids(l,1)};
896 for(
unsigned i=0;i<n_dim;i++)
898 dpsidS(l,i) = dpsi_temp[0]*interpolated_t(0,i)
899 + dpsi_temp[1]*interpolated_t(1,i);
static double Default_Physical_Constant_Value
Default value for physical constants.
double ca()
Return the value of the capillary number.
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 functio...
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...
double * Contact_angle_pt
Pointer to the desired value of the contact angle (if any)
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.
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...
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.
void output(std::ostream &outfile)
Overload the output function.
Vector< unsigned > U_index_interface_boundary
Index at which the i-th velocity component is stored in the element's nodes.
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 func...
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.
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...
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 interpolated_u(const Vector< double > &s, const unsigned &i)
Calculate the i-th velocity component at the local coordinate s.
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. This is implemented generically using the surface divergence information that is overloaded in each element i.e. axisymmetric, two- or three-dimensional.
double & contact_angle()
Return value of the contact angle.
double Ca
Capillary number.
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...