4. User Defined Functionality#

The code does not make use of MATLAB object-oriented functionality and all the objects are described as structs. The interface for each struct is documented in the st_[name]_options functions, with several concrete implementations given.

All the user-provided functionality must provide the directional derivatives used throughout the code. For example, the cost functional must define derivatives with respect to the velocity field \(\mathbf{u}\), the traction \(\mathbf{f}\), the geometry \(\mathbf{X}\) and the surface tension \(\gamma\) (or capillary number if constant).

Each type can be further combined using st_gradient_combine() to obtain combined derivatives.

st_gradient_combine(varargin)#

Gathers all the gradients from the input structures.

The inputs are given as key-value pairs. The values must be structs (see st_cost_options()) with the structure obj.fn.gradient_{VAR}. This function returns a similar struct with an fn field that sums up all the values from the various other inputs.

The intended usage is as follows

param = struct('Ca', 0.1, 'lambda', 1.0);
jump_g = st_jump_gravity('param', param);
jump_c = st_jump_capillary('param', param);
jump = st_gradient_combine(...
    'gravity', jump_g, 'capillary', jump_c, ...
    'weights', struct('jump_c', 1.0, 'jump_g', 0.5));

A similar setup can be used for structures conforming to st_cost_options() or st_forcing_options().

Returns:

a struct with the structure grad.fn.gradient_{VAR}.

4.1. Boundary Conditions#

st_boundary_condition_options(varargin)#

Default values for boundary conditions.

Supported fields are:

  • fn: name for the boundary conditions passed to st_sym_boundary() or a struct with the required boundary conditions. The naming and usage is described in st_sym_boundary().

  • param: boundary condition parameters. The Capillary number Ca and the viscosity ratio lambda are pretty much always required.

  • user: additional user defined options.

Unsupported fields are silently ignored.

Parameters:

varargin – key-value pairs of options or an existing struct with the required fields.

Returns:

a struct with the mentioned fields.

st_sym_boundary(name, varargin)#

Boundary conditions for Stokes flow.

The returned struct will have function handles f(x), where x is the full collocation point information, as obtained from st_mesh_target_geometry(). The following boundary conditions are provided

  • uinf: freestream velocity field.

  • finf and tinf: freestream normal and tangential traction.

  • pinf: freestream pressure.

  • dudninf and dudtinf: freestream normal and tangential velocity gradient.

  • sinf: freestream stress.

  • usurf: surface velocity field, for single-phase solutions.

  • jump: interfacial jump, for two-phase solutions. This should generally be replaced by structs as st_jump_options().

Known boundary conditions are

  • HadamardRybczynski: full solution, see st_sym_solutions().

  • SolidSphere: full solution, see st_sym_solutions().

  • SolidQuadratic: full solution, see st_sym_solutions().

  • ExtensionalFlow: freestream conditions only.

  • FourRoller: freestream conditions only.

  • UniformFlow: freestream conditions only.

If the boundary conditions have an associated full solution (usually on a sphere), then an additional field sym is provided with the solution obtained from st_sym_solutions(). Function handles for each analytic solution are also given.

Parameters:
  • name – name of the solution.

  • varargin – additional parameters for the boundary conditions.

Returns:

a struct with the above described fields.

st_sym_solutions(name, opts)#

Get symbolic Stokes solutions.

All solutions are returned in Cartesian coordinates. Currently the following solutions are known

  • 'HadamardRybczynski': from Equation 3-7 in [Clift1978]. Optional parameters: R sphere radius (default 1.0), lambda viscosity ratio (default 1.0), pinf farfield pressure (default 0.0), uinf farfield x velocity (default 1.0), alpha interface velocity (default \(1/4 \lambda / (1 + \lambda)\) gives a steady state interface).

  • 'SolidSphere': same as the Hadamard-Rybczynski solution, but with and infinite interior viscosity. Optional parameters: R sphere radius (default 1.0), pinf farfield pressure (default 0.0), uinf farfield velocity field (default 1.0) and usurf surface tangential velocity (default 0.0).

  • 'SolidQuadratic': from Equation 18a in [Chwang1975]. Optional parameters: R sphere radius (default 1.0) and pinf farfield pressure (default 0.0).

The solution struct that is returned has the following fields

  • u_ext, p_ext, sigma_ext, gradu_ext: exterior velocity, pressure, stress tensor and velocity gradient.

  • u_int, p_int, sigma_int, gradu_int: interior velocity, pressure, stress tensor and velocity gradient.

  • x: symbolic Cartesian coordinates.

  • n: symbolic normal vector, as a function of \(\mathbf{x}\).

  • t: symbolic tangent vector, as a function of \(\mathbf{x}\).

  • kappa: mean curvature.

  • theta: symbolic curve parametrization in the \(x-y\) plane.

  • xs: coordinate transformation from \(\mathbf{x}\) to \(\theta\) on the curve. Should be used as subs(exprs, st.x, st.xs).

Parameters:
  • name – name of the solution (case insensitive).

  • opts – option struct for the respective solution.

Returns:

a struct with the solution.

4.2. Jump Conditions#

st_jump_options(varargin)#

Constructs a default struct for defining jump conditions for the traction.

The main fields accepted are

  • param: a structure containing flow parameters. The mandatory parameters are the Capillary number Ca and the viscosity ratio lambda.

  • user: a struct containing user defined options, which is empty by default.

  • optype: can be 'scalar' or 'vector', for the normal component or the full shape gradient, respectively

It can also contain a struct fn of function handles of the type f(jump, t, x, y, st), where st is a struct containing the Stokes solution (forward and adjoint, as necessary). The defined fields are the same as for st_cost_options().

Returns:

a struct with the fields initialized to their defaults.

st_jump_angle(varargin)#

Defines an artificial traction jump.

The jump is given in its non-dimensional form as

\[[\![\mathbf{n} \cdot \sigma]\!] = 6 \alpha \frac{2 + 3 \lambda}{R^4 \lambda} \cos \theta \mathbf{n}.\]
Returns:

a struct compatible with st_jump_options().

st_jump_capillary(varargin)#

Defines a traction jump based on the Young-Laplace law with constant surface tension.

The jump is given it its non-dimensional form by the Young-Laplace law

\[[\![\mathbf{n} \cdot \sigma]\!] = \frac{1}{\mathrm{Ca}} \kappa \mathbf{n}.\]
Returns:

a struct compatible with st_jump_options().

st_jump_capillary_variable(varargin)#

Defines a variable surface tension traction jump.

The jump is given it its non-dimensional form by the Young-Laplace law

\[[\![\mathbf{n} \cdot \sigma]\!] = \frac{1}{\mathrm{Ca}_0} (\gamma \kappa \mathbf{n} + \nabla_\Sigma \gamma),\]

where \(\gamma\) is the surface tension and \(\nabla_\Sigma\) is the tangential gradient.

Returns:

a struct compatible with st_jump_options().

st_jump_gravity(varargin)#

Defines a traction jump for when gravity is present.

This is meant to be used in conjunction with a surface tension-based jump, e.g. st_jump_capillary(), where we have that

\[[\![\mathbf{n} \cdot \sigma]\!] = x \mathbf{n} + \frac{1}{\mathrm{Bo}} \kappa \mathbf{n},\]

where \(\mathrm{Bo}\) is the Bond number. It is given by

\[\mathrm{Bo} = \frac{\Delta \rho g R^2}{\gamma},\]

where \(\Delta \rho\) is the difference in density between the fluids and \(g\) is the gravitational acceleration. This function implements the gravity term in the expression above.

Returns:

a struct compatible with st_jump_options().

st_jump_hadamard(varargin)#

Defines the traction jump in the Hadamard-Rybczynski solution.

This is basically a mix of st_jump_capillary() and st_jump_angle(). See st_sym_solutions() for more details. The parameters can include a enable_capillary and enable_angle flag to turn each part on and off.

Returns:

a struct compatible with st_jump_options().

st_jump_zero(varargin)#

Defines a uniformly zero jump condition.

This jump is meant for the zero surface tension (or infinite Capillary number) case.

Returns:

a struct compatible with st_jump_options().

st_jump_shape_gradient(jump, t, x, y, st)#

Computes the shape gradient components of a jump term.

Parameters:
  • jump – jump information compatible with st_jump_options().

  • x – target geometry information.

  • y – source geometry information.

  • st – forward and adjoint solutions to the Stokes problem.

Returns:

the gradient.

st_jump_surface_tension(name, xi, varargin)#

Variable surface tension formulae from literature.

Available formulae are

  • 'Seric': from [Seric2018], Section 4.1.

  • 'Bump': similar to 'Seric', but with a perturbation of \(\sin (\pi / 4 \cos (4 \pi k \xi))\).

  • 'LiLubkin': from [Li2001], Section 4.2.

Parameters:
  • name – name of the formula (case insensitive).

  • xi – computational grid points.

  • varargin – additional options.

Returns:

surface tension evaluated at the given points.

4.3. Forcing Terms#

st_forcing_options(varargin)#

Constructs a default struct for defining the forcing condition.

The main fields accepted are

  • param: a structure containing flow parameters. The mandatory parameters are the Capillary number Ca and the viscosity ratio lambda.

  • user: a struct containing user defined options, which is empty by default.

  • variables: a cell array definings the variables required to compute the forcing term, passed to st_repr_density_solution().

It must also contain a struct fn of function handles of the type f(forcing, t, x, y, st), where st is a struct containing the Stokes solution (forward and adjoint, as necessary). The defined fields are are the same as for st_cost_options().

Returns:

a struct with the fields initialized to their defaults.

st_forcing_normal_velocity(varargin)#

Defines a forcing condition based on the normal velocity.

It is given by st_ode_steady_forcing(). One important node here regards the gradients that are also computed: they only consider the normal velocity component of the forcing condition, even if the tangential and curvature terms are active.

Returns:

a struct compatible with st_forcing_options().

st_forcing_adjoint(varargin)#

Forcing for the adjoint evolution equation.

This should not be used as is, but is mostly meant as a nice wrapper for use in st_ode_unsteady_adjoint().

Returns:

a struct compatible with st_forcing_options().

st_ode_steady_forcing(forcing, ~, x, ~, st)#

Compute the right-hand side of the kinematic equation.

This function provides a right-hand side for st_ode_steady() and st_ode_unsteady(). It is given by:

\[f(\mathbf{u}, \mathbf{X}) = (\mathbf{u} \cdot \mathbf{n}) \mathbf{n} + w \mathbf{t} + m \kappa \mathbf{n}\]

where \(w\) is described in Equation 2.2 from [Loewenberg1996] and \(m \kappa\) is a mean curvature flow-type term meant to smooth out the interface. The following fields in options are used (defaults defined by st_ode_options()):

  • tangential_forcing: enables the tangential term.

  • curvature_forcing: enables the mean curvature term.

  • mobility: coefficient for the mean curvature flow. A small coefficient is desired, so that the droplet doesn’t collapse to a point.

Parameters:
  • t – current time.

  • x – target geometry information.

  • y – source geometry information.

  • st – Stokes solution, containing a field u.

Returns:

the forcing term for the kinematic steady state equation.

4.4. Cost Functionals#

st_cost_options(varargin)#

Constructs a default struct for defining cost functionals.

The main fields accepted are

  • param: a structure containing flow parameters. The mandatory parameters are the Capillary number Ca and the viscosity ratio lambda. This should be consistent between various objects, e.g. like st_boundary_condition_options().

  • variables: a cell array of variable names needed to compute the cost functional. These are passed to st_repr_density_solution().

  • forward_variables: a cell array of variable names needed in the computation of the adjoint gradient. Only the variables explicitly in the cost functional are required.

  • adjoint_variables: a cell array that should be left empty.

  • optype: can be 'scalar' or 'vector' for the normal component of the shape gradient or the full gradient.

  • user: a struct containing user defined options, which is empty by default.

It can also contain a struct fn of function handles of the type f(cost, t, x, y, st), where st is a struct containing the Stokes solution (forward and adjoint, as necessary). The defined fields are:

  • evaluate: evaluates the cost functional.

  • gradient_x: shape gradient of the cost functional. The shape gradient is given in a weak form.

  • gradient_u: gradient with respect to the velocity field.

  • gradient_s: gradient with respect to the traction field.

  • gradient_ca: gradient with respect to the surface tension.

  • operator_x: matrix operator representing the shape derivative as an action on the adjoint variables.

Additional fields used in finite difference calculations involving the cost functional (see st_shape_finite_gradient()) are

  • eps: a step size for finite difference

  • bump(cost, x, y, f): a function handle that constructs an appropriate bump function. By default, this is defined by st_shape_finite_bump().

  • bump_type, bump_cells, bump_eps and sigma are all parameters that are passed to st_shape_finite_bump().

This function is mostly meant for custom cost functionals. Several examples, e.g. st_cost_normal_velocity(), are already included.

Parameters:

varargin – key-value pairs, where additional keys are ignored.

Returns:

a struct with the above fields initialized to their defaults.

st_cost_centroid(varargin)#

Defines a cost functional that maximizes the centroid movement.

It is given by

\[\mathcal{J} = \frac{\beta}{2} \|X_c(T) - X_0\|^2 + \frac{\alpha}{2} \|\gamma\|_2^2,\]

where \(X_c(T)\) is the \(x\) component of the centroid at the final time and \(X_0\) is a desired value.

Additional user parameters:

  • 'x0': desired centroid position.

  • 'beta': weighting for the first term in \([-\infty, \infty]\). If negative, this is a maximization problem instead.

  • 'alpha': weighting for the second term in \([0, \infty]\). If negative, the second term is disabled.

  • 'tmax': final time.

Returns:

a struct compatible with st_cost_options().

st_cost_exterior_traction(varargin)#

Defines a traction matching cost functional.

It is given by

\[\mathcal{J} = \frac{1}{2} \int_{\Sigma} \|\mathbf{f} - \mathbf{f}_d \|^2 \,\mathrm{d}S.\]
Returns:

a struct compatible with st_cost_options().

st_cost_geometry(varargin)#

Defines a geometry matching cost functional.

It is given by

\[\mathcal{J} = \frac{1}{2} \int_{\Sigma} \|\mathbf{X}(T) - \mathbf{X}_d \|^2 \,\mathrm{d}S.\]

This cost functional expects param.tmax to be present.

Returns:

a struct compatible with st_cost_options().

st_cost_normal_velocity(varargin)#

Defined a cost functional matching the normal velocity.

It is given by

\[\mathcal{J} = \frac{1}{2} \int_{\Sigma} |\mathbf{u} \cdot \mathbf{n} - u_d|^2 \,\mathrm{d}S.\]
Returns:

a struct compatible with st_cost_options().

st_cost_surface_area(varargin)#

Defines a cost functional that maximizes the surface area.

It is given by

\[\mathcal{J} = -\int_\Sigma \,\mathrm{d}S.\]
Returns:

a struct compatible with st_cost_options().