Surface Evolver Documentation - Column Example

# Surface Evolver Documentation

Back to top of Surface Evolver documentation. Index.
Back to top of tutorial.

# Example: Column of liquid solder

Here we have a tiny drop of liquid solder that bridges between two parallel, horizontal planes at z = 0 and z = `ZH`. On each plane there is a circular pad that the solder perfectly wets, and the solder is perfectly nonwetting off the pads. This would be just a catenoid problem with fixed volume, except that the pads are offset, and it is desired to find out what aligning force the solder exerts. The surface is defined the same way as in the catenoid example, except the lower boundary ring has a shift variable `SHIFT` in it to provide an offset in the y direction. This makes the shift adjustable at run time. Since the top and bottom facets of the body are not included, the constant volume they account for is provided by content integrals around the upper boundary, and the gravitational energy is provided by an energy integral. One could use the volconst attribute of the body instead for the volume, but then one would have to reset that every time `ZH` changed.

The interesting part of this example is the calculation of the forces. One could incrementally shift the pad, minimize the energy at each shift, and numerically differentiate the energy to get the force. Or one could set up integrals to calculate the force directly. But the simplest method is to use the Principle of Virtual Work by shifting the pad, recalculating the energy without re-evolving, and correcting for the volume change. Re-evolution is not necessary because when a surface is at an equilibrium, then by definition any perturbation that respects constraints does not change the energy to first order. To adjust for changes in constraints such as volume, the Lagrange multipliers (pressure for the volume constraint) tell how much the energy changes for given change in the constraints:

              DE = L*DC

where `DE` is the energy change, `L` is the row vector of Lagrange multipliers and `DC` is the column vector of constraint value changes. Therefore, the adjusted energy after a change in a parameter is

              E_adj = E_raw - L*DC

where `E_raw` is the actual energy and `DC` is the vector of differences of constraint values from target values. The commands `do_yforce` and `do_zforce` in the datafile do central difference calculations of the forces on the top pad, and put the surface back to where it was originally. Note that the perturbations are made smoothly, i.e. the shear varies linearly from bottom to top. This is not absolutely necessary, but it gives a smoother perturbation and hence a bit more accuracy.

| The initial column skeleton, with vertices and edges numbered.

    // column.fe
    // Example of calculating forces exerted by a
    // column of liquid solder in shape of skewed catenoid.

    // All units cgs
    parameter RAD = 0.05     // ring radius
    parameter ZH = 0.08      // total height
    parameter SHIFT = 0.025    // shift
    #define SG 8      // specific gravity of solder
    #define TENS 460  // surface tension of solder
    #define GR  980   // acceleration of gravity

    gravity_constant GR

    BOUNDARY 1  PARAMETERS 1
    X1: RAD*cos(P1)
    X2: RAD*sin(P1) + SHIFT
    X3: ZH
    CONTENT  // used to compensate for missing top facets
    c1: 0
    c2: -ZH*x
    c3: 0
    ENERGY  // used to compensate for gravitational energy under top facets
    e1: 0
    e2: GR*ZH^2/2*x
    e3: 0

    BOUNDARY 2  PARAMETERS 1
    X1: RAD*cos(P1)
    X2: RAD*sin(P1)
    X3: 0

    vertices   // given in terms of boundary parameter
    1    0.00  boundary 1   fixed
    2    pi/3  boundary 1   fixed
    3  2*pi/3  boundary 1   fixed
    4    pi    boundary 1   fixed
    5  4*pi/3  boundary 1   fixed
    6  5*pi/3  boundary 1   fixed
    7    0.00  boundary 2   fixed
    8    pi/3  boundary 2   fixed
    9  2*pi/3  boundary 2   fixed
    10   pi    boundary 2   fixed
    11 4*pi/3  boundary 2   fixed
    12 5*pi/3  boundary 2   fixed

    edges
    1    1  2  boundary 1   fixed
    2    2  3  boundary 1   fixed
    3    3  4  boundary 1   fixed
    4    4  5  boundary 1   fixed
    5    5  6  boundary 1   fixed
    6    6  1  boundary 1   fixed
    7    7  8  boundary 2   fixed
    8    8  9  boundary 2   fixed
    9    9  10 boundary 2   fixed
    10   10 11 boundary 2   fixed
    11   11 12 boundary 2   fixed
    12   12 7  boundary 2   fixed
    13   1  7
    14   2  8
    15   3  9
    16   4  10
    17   5  11
    18   6  12

    faces
    1   1 14  -7 -13   density TENS
    2   2 15  -8 -14   density TENS
    3   3 16  -9 -15   density TENS
    4   4 17 -10 -16   density TENS
    5   5 18 -11 -17   density TENS
    6   6 13 -12 -18   density TENS

    bodies
    1    -1 -2 -3 -4 -5 -6 volume 0.00045 density SG

    read

    // horizontal force on upper pad by central differences
    dy := .0001
    do_yforce := { oldshift := shift; shift := shift + dy;
                   set vertex y  y+dy*z/zh; // uniform shear
                   recalc;
                   energy1 := total_energy -
                         body[1].pressure*(body[1].volume - body[1].target);
                   oldshift := shift; shift := shift - 2*dy;
                   set vertex y  y-2*dy*z/zh; // uniform shear
                   recalc;
                   energy2 := total_energy -
                         body[1].pressure*(body[1].volume - body[1].target);
                   yforce := -(energy1-energy2)/2/dy;
                   printf "restoring force: %20.15f\n",yforce;
                   // restore everything
                   oldshift := shift; shift := shift + dy;
                   set vertex y  y+dy*z/zh; // uniform shear
                   recalc;
                 }

    // vertical force on upper pad by central differences.
    dz := .0001
    do_zforce := { oldzh := zh; zh := zh + dz;
                   set vertex z  z+dz*z/oldzh; recalc; // uniform stretch
                   energy1 := total_energy -
                         body[1].pressure*(body[1].volume - body[1].target);
                   oldzh := zh; zh := zh - 2*dz;
                   set vertex z  z-2*dz*z/oldzh; recalc; // uniform stretch
                   energy2 := total_energy -
                         body[1].pressure*(body[1].volume - body[1].target);
                   zforce := -(energy1-energy2)/2/dz;
                   printf "vertical force:  %20.15f\n",zforce;
                   // restore everything
                   oldzh := zh; zh := zh + dz;
                   set vertex z  z+dz*z/oldzh; recalc; // uniform stretch
                 }

Back to top of tutorial.
Back to top of Evolver documentation. Index.