interface_elements.cc
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-2025 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// Non-inline functions for fluid free surface elements
27
28// OOMPH-LIB headers
29#include "interface_elements.h"
30#include "generic/integral.h"
31
32
33namespace oomph
34{
35 //////////////////////////////////////////////////////////////////
36 //////////////////////////////////////////////////////////////////
37 //////////////////////////////////////////////////////////////////
38
39
40 //=========================================================================
41 /// Set a pointer to the desired contact angle. Optional boolean
42 /// (defaults to true)
43 /// chooses strong imposition via hijacking (true) or weak imposition
44 /// via addition to momentum equation (false). The default strong imposition
45 /// is appropriate for static contact problems.
46 //=========================================================================
48 const bool& strong)
49 {
50 // Set the pointer to the contact angle
52
53 // If we are hijacking the kinematic condition (the default)
54 // to do the strong (pointwise form of the contact-angle condition)
55 if (strong)
56 {
57 // Remember what we're doing
59
60 // Hijack the bulk element residuals
62 ->hijack_kinematic_conditions(Bulk_node_number);
63 }
64 // Otherwise, we'll impose it weakly via the momentum equations.
65 // This will require that the appropriate velocity node is unpinned,
66 // which is why this is a bad choice for static contact problems in which
67 // there is a no-slip condition on the wall. In that case, the momentum
68 // equation is never assembled and so the contact angle condition is not
69 // applied unless we use the strong version above.
70 else
71 {
73 }
74 }
75
76
77 //////////////////////////////////////////////////////////////////
78 //////////////////////////////////////////////////////////////////
79 //////////////////////////////////////////////////////////////////
80
81
82 //=========================================================================
83 /// Add contribution to element's residual vector and Jacobian
84 //=========================================================================
88 {
89 // Let's get the info from the parent
91
92 // Find the dimension of the problem
93 unsigned spatial_dim = this->nodal_dimension();
94
95 // Outer unit normal to the wall
97
98 // Outer unit normal to the free surface
100
101 // Storage for the coordinate
103
104 // Find the dimension of the parent
105 unsigned n_dim = parent_pt->dim();
106
107 // Dummy local coordinate, of size zero
109
110 // Get the x coordinate
111 this->interpolated_x(s_local, x);
112
113 // Get the unit normal to the wall
115
116 // Find the local coordinates in the parent
119
120 // Just get the outer unit normal
121 dynamic_cast<FaceElement*>(parent_pt)->outer_unit_normal(s_parent,
123
124 // Find the dot product of the two vectors
125 double dot = 0.0;
126 for (unsigned i = 0; i < spatial_dim; i++)
127 {
129 }
130
131 // Get the value of sigma from the parent
132 double sigma_local =
133 dynamic_cast<FluidInterfaceElement*>(parent_pt)->sigma(s_parent);
134
135 // Are we doing the weak form replacement
136 if (Contact_angle_flag == 2)
137 {
138 // Get the wall tangent vector
140 wall_tangent[0] = -wall_normal[1];
142
143 // Get the capillary number
144 double ca_local = ca();
145
146 // Just add the appropriate contribution to the momentum equations
147 for (unsigned i = 0; i < 2; i++)
148 {
150 if (local_eqn >= 0)
151 {
155 }
156 }
157 }
158 // Otherwise [strong imposition (by hijacking) of contact angle or
159 // "no constraint at all"], add the appropriate contribution to
160 // the momentum equation
161 else
162 {
163 // Need to find the current outer normal from the surface
164 // which does not necessarily correspond to an imposed angle.
165 // It is whatever it is...
168
169 // Get the capillary number
170 double ca_local = ca();
171
172 // Just add the appropriate contribution to the momentum equations
173 // This will, of course, not be added if the equation is pinned
174 //(no slip)
175 for (unsigned i = 0; i < 2; i++)
176 {
178 if (local_eqn >= 0)
179 {
181 }
182 }
183 }
184
185 // If we are imposing the contact angle strongly (by hijacking)
186 // overwrite the kinematic equation
187 if (Contact_angle_flag == 1)
188 {
189 // Read out the kinematic equation number
191
192 // Note that because we have outer unit normals for the free surface
193 // and the wall, the cosine of the contact angle is equal to
194 // MINUS the dot product computed above
195 if (local_eqn >= 0)
196 {
198 }
199 // NOTE: The jacobian entries will be computed automatically
200 // by finite differences.
201 }
202
203 // Dummy arguments
204 Shape psif(1);
205 DShape dpsifds(1, 1);
207 double W = 0.0;
208
209 // Now add the additional contributions
212 }
213
214
215 //////////////////////////////////////////////////////////////////
216 //////////////////////////////////////////////////////////////////
217 //////////////////////////////////////////////////////////////////
218
219
220 //=========================================================================
221 /// Add contribution to element's residual vector and Jacobian
222 //=========================================================================
226 {
227 // Let's get the info from the parent
229
230 // Find the dimension of the problem
231 unsigned spatial_dim = this->nodal_dimension();
232
233 // Outer unit normal to the wall
235
236 // Outer unit normal to the free surface
238
239 // Find the dimension of the parent
240 unsigned n_dim = parent_pt->dim();
241
242 // Find the local coordinates in the parent
244
245 // Storage for the shape functions
246 unsigned n_node = this->nnode();
248 DShape dpsids(n_node, 1);
250
251 // Loop over intergration points
252 unsigned n_intpt = this->integral_pt()->nweight();
253 for (unsigned ipt = 0; ipt < n_intpt; ++ipt)
254 {
255 // Get the local coordinate of the integration point
256 s_local[0] = this->integral_pt()->knot(ipt, 0);
258
259 // Get the local shape functions
261
262 // Zero the position
264
265 // Now construct the position and the tangent
267 for (unsigned n = 0; n < n_node; n++)
268 {
269 const double psi_local = psi(n);
270 const double dpsi_local = dpsids(n, 0);
271 for (unsigned i = 0; i < spatial_dim; i++)
272 {
273 double pos = this->nodal_position(n, i);
275 x[i] += pos * psi_local;
276 }
277 }
278
279 // Now we can calculate the Jacobian term
280 double t_length = 0.0;
281 for (unsigned i = 0; i < spatial_dim; ++i)
282 {
284 }
285 double W = std::sqrt(t_length) * this->integral_pt()->weight(ipt);
286
287 // Imposition of contact angle in weak form
288 if (Contact_angle_flag == 2)
289 {
290 // Get the outer unit normal of the entire interface
291 dynamic_cast<FaceElement*>(parent_pt)->outer_unit_normal(s_parent,
293
294 // Calculate the wall normal
296
297 // Find the dot product of the two
298 double dot = 0.0;
299 for (unsigned i = 0; i < spatial_dim; i++)
300 {
302 }
303
304 // Find the projection of the outer normal of the surface into the plane
306 for (unsigned i = 0; i < spatial_dim; i++)
307 {
309 }
310
311 // Get the value of sigma from the parent
312 const double sigma_local =
313 dynamic_cast<FluidInterfaceElement*>(parent_pt)->sigma(s_parent);
314
315 // Get the capillary number
316 const double ca_local = ca();
317
318 // Get the contact angle
319 const double theta = contact_angle();
320
321 // Add the contributions to the momentum equation
322
323 // Loop over the shape functions
324 for (unsigned l = 0; l < n_node; l++)
325 {
326 // Loop over the velocity components
327 for (unsigned i = 0; i < 3; i++)
328 {
329 // Get the equation number for the momentum equation
330 int local_eqn =
332
333 // If it's not a boundary condition
334 if (local_eqn >= 0)
335 {
336 // Add the surface-tension contribution to the momentum equation
339 (sin(theta) * wall_normal[i] + cos(theta) * binorm[i]) *
340 psi(l) * W;
341 }
342 }
343 }
344 }
345 // Otherwise [strong imposition (by hijacking) of contact angle or
346 // "no constraint at all"], add the appropriate contribution to
347 // the momentum equation
348 else
349 {
350 // Storage for the outer vector
351 Vector<double> m(3);
352
353 // Get the outer unit normal of the line
355
356 // Get the value of sigma from the parent
357 const double sigma_local =
358 dynamic_cast<FluidInterfaceElement*>(parent_pt)->sigma(s_parent);
359
360 // Get the capillary number
361 const double ca_local = ca();
362
363 // Loop over the shape functions
364 for (unsigned l = 0; l < n_node; l++)
365 {
366 // Loop over the velocity components
367 for (unsigned i = 0; i < 3; i++)
368 {
369 // Get the equation number for the momentum equation
370 int local_eqn =
372
373 // If it's not a boundary condition
374 if (local_eqn >= 0)
375 {
376 // Add the surface-tension contribution to the momentum equation
378 m[i] * (sigma_local / ca_local) * psi(l) * W;
379 }
380 }
381 }
382 } // End of the line integral terms
383
384
385 // If we are imposing the contact angle strongly (by hijacking)
386 // overwrite the kinematic equation
387 if (Contact_angle_flag == 1)
388 {
389 // Get the outer unit normal of the whole interface
390 dynamic_cast<FaceElement*>(parent_pt)->outer_unit_normal(s_parent,
392
393 // Calculate the wall normal
395
396 // Find the dot product
397 double dot = 0.0;
398 for (unsigned i = 0; i < spatial_dim; i++)
399 {
401 }
402
403 // Loop over the test functions
404 for (unsigned l = 0; l < n_node; l++)
405 {
406 // Read out the kinematic equation number
408
409 // Note that because we have outer unit normals for the free surface
410 // and the wall, the cosine of the contact angle is equal to
411 // MINUS the dot product
412 if (local_eqn >= 0)
413 {
414 residuals[local_eqn] += (cos(contact_angle()) + dot) * psi(l) * W;
415 }
416 // NOTE: The jacobian entries will be computed automatically
417 // by finite differences.
418 }
419 } // End of strong form of contact angle condition
420
421 // Add any additional residual contributions
424 }
425 }
426
427
428 /////////////////////////////////////////////////////////////////
429 /////////////////////////////////////////////////////////////////
430 /////////////////////////////////////////////////////////////////
431
432
433 //============================================================
434 /// Default value for physical constant (static)
435 //============================================================
437
438
439 //================================================================
440 /// Calculate the i-th velocity component at local coordinate s
441 //================================================================
443 const unsigned& i)
444 {
445 // Find number of nodes
446 unsigned n_node = FiniteElement::nnode();
447
448 // Storage for the local shape function
450
451 // Get values of shape function at local coordinate s
452 this->shape(s, psi);
453
454 // Initialise value of u
455 double interpolated_u = 0.0;
456
457 // Loop over the local nodes and sum
458 for (unsigned l = 0; l < n_node; l++)
459 {
460 interpolated_u += u(l, i) * psi(l);
461 }
462
463 return (interpolated_u);
464 }
465
466 //===========================================================================
467 /// Calculate the contribution to the residuals from the interface
468 /// implemented generically with geometric information to be
469 /// added from the specific elements
470 //========================================================================
473 {
474 // Find out how many nodes there are
475 unsigned n_node = this->nnode();
476
477 // Set up memeory for the shape functions
479
480 // Find out the number of surface coordinates
481 const unsigned el_dim = this->dim();
482 // We have el_dim local surface coordinates
484
485 // Find the dimension of the problem
486 // Note that this will return 2 for the axisymmetric case
487 // which is correct in the sense that no
488 // terms will be added in the azimuthal direction
489 const unsigned n_dim = this->nodal_dimension();
490
491 // Storage for the surface gradient
492 // and divergence terms
493 // These will actually be identical
494 // apart from in the axisymmetric case
497
498 // Set the value of n_intpt
499 unsigned n_intpt = this->integral_pt()->nweight();
500
501 // Get the value of the Capillary number
502 double Ca = ca();
503
504 // Get the value of the Strouhal numer
505 double St = st();
506
507 // Get the value of the external pressure
508 double p_ext = pext();
509
510 // Integers used to hold the local equation numbers and local unknowns
511 int local_eqn = 0, local_unknown = 0;
512
513 // Storage for the local coordinate
515
516 // Loop over the integration points
517 for (unsigned ipt = 0; ipt < n_intpt; ipt++)
518 {
519 // Get the value of the local coordiantes at the integration point
520 for (unsigned i = 0; i < el_dim; i++)
521 {
522 s[i] = this->integral_pt()->knot(ipt, i);
523 }
524
525 // Get the integral weight
526 double W = this->integral_pt()->weight(ipt);
527
528 // Call the derivatives of the shape function
530
531 // Define and zero the tangent Vectors and local velocities
535 ;
537
538 // Loop over the shape functions
539 for (unsigned l = 0; l < n_node; l++)
540 {
541 const double psi_ = psif(l);
542 // Loop over directional components
543 for (unsigned i = 0; i < n_dim; i++)
544 {
545 // Coordinate
546 interpolated_x[i] += this->nodal_position(l, i) * psi_;
547
548 // Calculate velocity of mesh
550
551 // Calculate the tangent vectors
552 for (unsigned j = 0; j < el_dim; j++)
553 {
554 interpolated_t(j, i) += this->nodal_position(l, i) * dpsifds(l, j);
555 }
556
557 // Calculate velocity and tangent vector
558 interpolated_u[i] += u(l, i) * psi_;
559 }
560 }
561
562
563 // Calculate the surface gradient and divergence
564 double J = this->compute_surface_derivatives(
566 // Get the normal vector
567 //(ALH: This could be more efficient because
568 // there is some recomputation of shape functions here)
571
572 // Now also get the (possible variable) surface tension
573 double Sigma = this->sigma(s);
574
575 // Loop over the shape functions
576 for (unsigned l = 0; l < n_node; l++)
577 {
578 // Loop over the velocity components
579 for (unsigned i = 0; i < n_dim; i++)
580 {
581 // Get the equation number for the momentum equation
583
584 // If it's not a boundary condition
585 if (local_eqn >= 0)
586 {
587 // Add the surface-tension contribution to the momentum equation
588 residuals[local_eqn] -= (Sigma / Ca) * dpsifdS_div(l, i) * J * W;
589
590 // If the element is a free surface, add in the external pressure
591 if (Pext_data_pt != 0)
592 {
593 // External pressure term
595 p_ext * interpolated_n[i] * psif(l) * J * W;
596
597 // Add in the Jacobian term for the external pressure
598 // The correct area is included in the length of the normal
599 // vector
600 if (flag)
601 {
603 if (local_unknown >= 0)
604 {
606 interpolated_n[i] * psif(l) * J * W;
607 }
608 }
609 } // End of pressure contribution
610 }
611 } // End of contribution to momentum equation
612
613
614 // Kinematic BC
616 if (local_eqn >= 0)
617 {
618 // Assemble the kinematic condition
619 // The correct area is included in the normal vector
620 for (unsigned k = 0; k < n_dim; k++)
621 {
624 interpolated_n[k] * psif(l) * J * W;
625 }
626
627 // Add in the jacobian
628 if (flag)
629 {
630 // Loop over shape functions
631 for (unsigned l2 = 0; l2 < n_node; l2++)
632 {
633 // Loop over the components
634 for (unsigned i2 = 0; i2 < n_dim; i2++)
635 {
637 this->nodal_local_eqn(l2, this->U_index_interface[i2]);
638 // If it's a non-zero dof add
639 if (local_unknown >= 0)
640 {
642 psif(l2) * interpolated_n[i2] * psif(l) * J * W;
643 }
644 }
645 }
646 } // End of Jacobian contribution
647 }
648 } // End of loop over shape functions
649
650
651 // Add additional contribution required from the implementation
652 // of the node update (e.g. Lagrange multpliers etc)
654 jacobian,
655 flag,
656 psif,
657 dpsifds,
658 dpsifdS,
660 s,
663 W,
664 J);
665
666 } // End of loop over integration points
667 }
668
669 //========================================================
670 /// Overload the output functions generically
671 //=======================================================
673 const unsigned& n_plot)
674 {
675 const unsigned el_dim = this->dim();
676 const unsigned n_dim = this->nodal_dimension();
677 const unsigned n_velocity = this->U_index_interface.size();
678 // Set output Vector
680
681 // Tecplot header info
683
684 // Loop over plot points
686 for (unsigned iplot = 0; iplot < num_plot_points; iplot++)
687 {
688 // Get local coordinates of pliot point
690
691 // Output the x,y,u,v
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++)
695 outfile << interpolated_u(s, i) << " ";
696
697 // Output a dummy pressure
698 outfile << 0.0 << "\n";
699 }
700
702
703 outfile << "\n";
704 }
705
706
707 //===========================================================================
708 /// Overload the output function
709 //===========================================================================
711 {
712 const unsigned el_dim = this->dim();
713 const unsigned n_dim = this->nodal_dimension();
714 const unsigned n_velocity = this->U_index_interface.size();
715 // Set output Vector
717
718 // Tecplot header info
720
721 // Loop over plot points
723 for (unsigned iplot = 0; iplot < num_plot_points; iplot++)
724 {
725 // Get local coordinates of plot point
727
728 // Coordinates
729 for (unsigned i = 0; i < n_dim; i++)
730 {
731 fprintf(file_pt, "%g ", interpolated_x(s, i));
732 }
733
734 // Velocities
735 for (unsigned i = 0; i < n_velocity; i++)
736 {
737 fprintf(file_pt, "%g ", interpolated_u(s, i));
738 }
739
740 // Dummy Pressure
741 fprintf(file_pt, "%g \n", 0.0);
742 }
743 fprintf(file_pt, "\n");
744
745 // Write tecplot footer (e.g. FE connectivity lists)
747 }
748
749
750 /////////////////////////////////////////////////////////////////////////
751 /////////////////////////////////////////////////////////////////////////
752 /////////////////////////////////////////////////////////////////////////
753
754 //====================================================================
755 /// Specialise the surface derivatives for the line interface case
756 //===================================================================
758 const Shape& psi,
759 const DShape& dpsids,
762 DShape& dpsidS,
764 {
765 const unsigned n_shape = psi.nindex1();
766 const unsigned n_dim = 2;
767
768 // Calculate the only entry of the surface
769 // metric tensor (square length of the tangent vector)
770 double a11 = interpolated_t(0, 0) * interpolated_t(0, 0) +
771 interpolated_t(0, 1) * interpolated_t(0, 1);
772
773 // Now set the derivative terms of the shape functions
774 for (unsigned l = 0; l < n_shape; l++)
775 {
776 for (unsigned i = 0; i < n_dim; i++)
777 {
778 dpsidS(l, i) = dpsids(l, 0) * interpolated_t(0, i) / a11;
779 }
780 }
781
782 // The surface divergence is the same as the surface
783 // gradient operator
785
786 // Return the jacobian
787 return sqrt(a11);
788 }
789
790
791 ////////////////////////////////////////////////////////////////////////
792 ////////////////////////////////////////////////////////////////////////
793 ////////////////////////////////////////////////////////////////////////
794
795 //====================================================================
796 /// Specialise the surface derivatives for the axisymmetric interface case
797 //===================================================================
799 const Shape& psi,
800 const DShape& dpsids,
803 DShape& dpsidS,
805 {
806 // Initially the same as the 2D case
807 const unsigned n_shape = psi.nindex1();
808 const unsigned n_dim = 2;
809
810 // Calculate the only entry of the surface
811 // metric tensor (square length of the tangent vector)
812 double a11 = interpolated_t(0, 0) * interpolated_t(0, 0) +
813 interpolated_t(0, 1) * interpolated_t(0, 1);
814
815 // Now set the derivative terms of the shape functions
816 for (unsigned l = 0; l < n_shape; l++)
817 {
818 for (unsigned i = 0; i < n_dim; i++)
819 {
820 dpsidS(l, i) = dpsids(l, 0) * interpolated_t(0, i) / a11;
821 // Set the standard components of the divergence
822 dpsidS_div(l, i) = dpsidS(l, i);
823 }
824 }
825
826 const double r = interpolated_x[0];
827
828 // The surface divergence is different because we need
829 // to take account of variation of the base vectors
830 for (unsigned l = 0; l < n_shape; l++)
831 {
832 dpsidS_div(l, 0) += psi(l) / r;
833 }
834
835 // Return the jacobian, needs to be multiplied by r
836 return r * sqrt(a11);
837 }
838
839
840 ////////////////////////////////////////////////////////////////////////
841 ////////////////////////////////////////////////////////////////////////
842 ////////////////////////////////////////////////////////////////////////
843
844 //====================================================================
845 /// Specialise the surface derivatives for 2D surface case
846 //===================================================================
848 const Shape& psi,
849 const DShape& dpsids,
852 DShape& dpsidS,
854 {
855 const unsigned n_shape = psi.nindex1();
856 const unsigned n_dim = 3;
857
858 // Calculate the local metric tensor
859 // The dot product of the two tangent vectors
860 double amet[2][2];
861 for (unsigned al = 0; al < 2; al++)
862 {
863 for (unsigned be = 0; be < 2; be++)
864 {
865 // Initialise to zero
866 amet[al][be] = 0.0;
867 // Add the dot product contributions
868 for (unsigned i = 0; i < n_dim; i++)
869 {
871 }
872 }
873 }
874
875 // Work out the determinant
876 double det_a = amet[0][0] * amet[1][1] - amet[0][1] * amet[1][0];
877 // Also work out the contravariant metric
878 double aup[2][2];
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;
883
884
885 // Now construct the surface gradient terms
886 for (unsigned l = 0; l < n_shape; l++)
887 {
888 // Do some pre-computation
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)};
892
893 for (unsigned i = 0; i < n_dim; i++)
894 {
895 dpsidS(l, i) = dpsi_temp[0] * interpolated_t(0, i) +
896 dpsi_temp[1] * interpolated_t(1, i);
897 }
898 }
899
900 // The divergence operator is the same
902
903 // Return the jacobian
904 return sqrt(det_a);
905 }
906
907} // namespace oomph
Deform the existing cubic spine mesh into a annular section with spines directed radially inwards fro...
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...
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.
double & contact_angle()
Return value of the contact angle.
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 & ca() const
The value of the Capillary number.
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.
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.