Defining the problem
We now turn to setting up the problem. Each term in the energy
functional (1) is represented by a corresponding functional
object, which acts on a Mesh
(and possibly a Field
) to calculate an
integral quantity such as an energy; Functional objects are also
responsible for calculating gradients of the energy with respect to
vertex positions and components of Fields.
Let's take the terms in (1) one by one: To represent the nematic elasticity we
create a Nematic
object:
var lf=Nematic(nn)
The surface tension term involves the length of the boundary, so we need
a Length
object:
var lt=Length()
The anchoring term doesn't have a simple built in object type, but we
can use a general LineIntegral
object to achieve the correct result.
var la=LineIntegral(fn (x, n) n.inner(tangent())^2, nn)
Notice that we have to supply a functionthe integrandwhich will be
called by LineIntegral
when it evaluates the integral. Integrand
functions are called with the local coordinates first (as a Matrix
object representing a column vector) and then the local interpolated
value of any number of Fields
. We also make use of the special
function tangent()
that locally returns a local tangent to the line.
We also need to impose constraints. Any functional object can be used
equally well as an energy or a constraint, and hence we create a
NormSq
(norm-squared) object that will be used to implement the local
unit vector constraint on the director field:
var ln=NormSq(nn)
and an Area
object for the global constraint. This is really a
constraint fixing the volume of fluid in the droplet, but since we're in
2D that becomes a constraint on the area of the mesh:
var laa=Area()
Now we have a collection of functional objects that we can use to define
the problem. So far, we haven't specified which functionals are energies
and which are constraints; nor have we specified which parts of the mesh
the functionals are to be evaluated over. All that information is
collected in an OptimizationProblem
object, which we will now create:
// Set up the optimization problem
var W = 1
var sigma = 1
var problem = OptimizationProblem(m)
problem.addenergy(lf)
problem.addenergy(la, selection=bnd, prefactor=-W/2)
problem.addenergy(lt, selection=bnd, prefactor=sigma)
problem.addconstraint(laa)
problem.addlocalconstraint(ln, field=nn, target=1)
Notice that some of these functionals only act on a selection such as
the boundary and hence we use the optional selection
parameter to
specify this. We can also specify the prefactor of the functional.