Back to top of Surface Evolver documentation.
     
Index.
 HINTS
This is a collection helpful hints gained from my own experience with Evolver
and from helping others.
-  Evolver works in dimensionless units, and the default settings
work best when size, surface tension, volume, etc. are near 1.
If you decide to work in units that give very large or small numbers,
you may have to adjust parameters such as
scale_limit,
target_tolerance, and
constraint_tolerance.
 
-  When drawing a sketch for constructing the initial datafile, make
it as big as you can.  You will have lots of notation to put on it.
Number all vertices, edges, and facets.  Put orientation arrows on the
edges, and indicate the orientation of facets (I like to use curved
arrows around the facet numbers).  
 
-  Initial faces should be convex.  Although Evolver handles nonconvex
faces, the triangulation algorithm is very simple-minded, and the triangulation
of a nonconvex face can be ugly.  Just put in an extra edge or two to 
divide the face into a couple of convex faces.
 
-  Make separate constraints for edges with constraint energy or content
integrals, and for edges without.  Even if the other edges are fixed,
it is much easier to check that the integrands are correct when only the
precisely needed edges are on constraints with integrals.
 
-  If you don't have all your elements numbered consecutively (which usually
happens due to numbering schemes you use, or adding or deleting elements),
run Evolver with the -i command line option so mouse-picking reports the
same element numbers as in your datafile.  You can instead put "keep_originals"
in the top of your datafile for the same effect.
 
-  Make sure all your body facets are oriented properly.  Evolver will
complain if there are mismatched facet orientations on an ordinary edge,
but fixed edges, constrained edges, etc. are exempt from this checking.
A good way to check is by coloring, for example:
   set body[1].facet color green  
 
-  Make sure vertices, edges, and facets are on their proper constraints.
You can check visually by coloring, e.g.
  set edge color red where on_constraint 1
  set facet color green where on_constraint 1  You can't color vertices directly, but you can get close to the same effect
by refining a couple of times and coloring edges adjacent to vertices:  foreach vertex vv where on_constraint 1 do set vv.edge color blue  
 
-  Check that all the energies, volumes, quantities, etc. in your
initial datafile are correct.  See the section below
for more details on how to check in great detail.
 
-  If you are doing liquids with contact lines on solid walls, I suggest
making the first datafile with all the boundary surfaces of the liquid
represented explicitly as facets, and then make a second version of the
datafile using constraint energy and content integrals to replace the
facets on the fixed walls.  It is far easier to get the energies and
volumes right in the first version, but it is also far more prone to
problems during evolution.  Use the first version to check the correctness
of the second version, and use the second version for serious work.
 
- 
If your edges on curved constraints try to short-cut the curve, there
are several ways to discourage that:
  
   -  Make a second guide constraint, so that  the intersection
    of the two constraints define guiderails for vertices to run
     along. By using vertex attributes to customize the guide constraint,
     you only need one guide constraint.  For example:
    define vertex attribute guides real[2]
    constraint 1 
    formula:  x^2 + y^2 = rad^2   // curved constraint
    constraint 2 
    formula:  guides[1]*x + guides[2]*y = 0  // radial guide planes  Then you can set the guide coefficients at runtime with   set vertex.guides[1] -y where on_constraint 1
   set vertex.guides[1] x where on_constraint 1   
-  If you understand exactly what energy or volume condition
    is encouraging the short-cutting, you can adjust the energy or
     content integrand on the curved constraint to compensate enough
     to eliminate the encouragement.  This basically means calculating
   the surface area of the gap between the edge and the curved constraint,
   or the volume bounded by the gap.
   
-  Declare the curved constraint 
    CONVEX. This adds an energy
    roughly proportional to the gap area.  This is simple to do, and
    works if you set the gap_constant high enough (you should leave 
    the gap constant as low as will work, however), but you cannot
    use any Hessian commands if you use convex constraints.
   
 
 
- 
      Run at low resolution before refining.  A good evolution
      script usually winds up having alternating refining
      and evolultion.  Having many triangles
      not only takes a long time to calculate, but motion can
      propagate only one triangle per iteration.  Don't over-evolve
      at a particular refinement.  Remember it's an approximation.
      There is not much point in evolving to 12 digits precision
      an approximation that is only accurate to 4 digits.
 
-   Groom your surface triangulation with 
      V (vertex averaging),
      u (equiangulation),
      l (long edge division), and
      t (tiny edge deletion).
      It may take some experimenting to get the right sequence, along
      with refinements.  It may be better to divide certain long edges
      than simply refine the whole surface.  However, overdoing it may
      be counterproductive to convergence; sometimes the converged 
      surface doesn't want to be entirely equiangulated or averaged, and
      you can get into an endless loop of iteration and grooming.
      Once you work out a good script, write it down in a handy command
      at the end of the datafile for easy use.
 
 
-  Use the dump or 
     d commands to save your evolved surface
     regularly. Remember that Evolver has no undo feature to roll back
     disastrous commands.     
 
-   Use conjugate gradient
      mode for faster gradient descent,
      but not too soon.  Use regular gradient descent to adjust
      to volume or constraint changes.
      Conjugate gradient should be used only when regular motion
      has settled down.  Conjugate gradient assumes a quadratic
      energy function, and may get confused when it's not.
      Conjugate gradient may need to be toggled off and on to
      make it forget its history.
 
-  During gradient descent (including conjugate gradient), keep an
     eye on the scale factor.  The scale factor should remain fairly
     steady.   A scale factor going to 0 does NOT mean convergence;
     it means the surface is having trouble.  However, a good scale
     factor may depend on refinement and other considerations.  See
     the section on reasonable scale factors.
 
-   Second-order Hessian convergence is much faster than first-order
      gradient descent, when Hessian works.  So my advice is to use gradient 
      descent just to get to where it's safe to use 
      hessian
      hessian_seek.
      Actually, hessian_seek is pretty  much always safe to use, since
      it makes sure energy is decreasing.  I have found circumstances
      where hessian_seek does an amazingly good job as an iteration step,
      even though the surface is nowhere near convergence.
 
-   Beware saddle points of energy.  A symmetric surface, e.g.
      a blob of solder on a pad or around a wire, may seem to 
      converge with gradient descent, but just have reached a 
      saddle point.  Use the eigenprobe
      command to test for stability, and if not stable, use
      the saddle command to
      get off the saddle point.
 
- 
      Judging convergence in gradient descent is tough. If iterations 
      run at a more
      or less constant scale factor and energy isn't changing much,
      and running in conjugate gradient mode for a long time doesn't
      change much, then you're probably in good shape.  But use
      the eigenprobe command to 
      make sure, and hessian to
      finish off convergence.
 
-   If you intend to use quadratic mode or Lagrange mode for 
      higher precision, evolve in linear model first until the 
      final stage, since it is much  quicker and there are more
      triangulation grooming commands available.
Checking your datafile
You should always check your initial datafile to be sure it is doing
exactly what you want.  It is easy to get signs on integrands wrong,
or apply quantities to the wrong elements.  When you load the initial
datafile, the initial energy, body volumes, and quantities values 
should be exactly what you expect, either from hand calculation or
from another datafile you trust.  In particular, when using constraint
integrals to replace omitted facets, I suggest you make a separate
datafile with facets instead of integrals just for checking the agreement
between the two.
With the named methods and quantities feature, it is possible to get
very detailed information on where numbers are coming from.  If you
give the "convert_to_quantities" command, every energy, volume, and
constraint integrand will be internally converted to named methods
and quantities (although the user interface for all remains the same).
These internal quantities are ordinarily not displayed by the 'v' or 'Q'
commands, but if you do "show_all_quantities" then they will be displayed.
Further, 'Q' will show all the component method instances also. For an
example, consider the following output:
 Enter command: convert_to_quantities
 Enter command: show_all_quantities
 Enter command: Q
Quantities and instances:
(showing internal quantities also; to suppress, do "show_all_quantities off")
 1. default_length                        64.2842712474619  info_only quantity
                            modulus       1.00000000000000
 2. default_area                          4.00000000000000  energy quantity
                            modulus       1.00000000000000
 3. constraint_1_energy                 -0.342020143325669  energy quantity
                            modulus       1.00000000000000
 4. constraint_2_energy                 -0.342020143325669  energy quantity
                            modulus       1.00000000000000
 5. body_1_vol                            1.00000000000000  fixed quantity
                             target       1.00000000000000
                            modulus       1.00000000000000
    body_1_vol_meth                      0.000000000000000  method instance
                            modulus       1.00000000000000
    body_1_con_2_meth                     1.00000000000000  method instance
                            modulus       1.00000000000000
 6. gravity_quant                        0.000000000000000  energy quantity
                            modulus      0.000000000000000
Here's a detailed explanation of the output of the Q command above:
default_length - total edge length, using the edge_length method.
This would be the default energy in the string model, and I guess it really
doesn't need to exist here.  But it's an info_only quantity, which means
it is only evaluated when somebody asks to know its value.
default_area - the default energy in the soapfilm model, and
included in the energy here, as indicated by "energy quantity" at the right.
constraint_1_energy - the energy integral of constraint 1, using
the edge_vector_integral method applied to all edges on constraint 1.
constraint_2_energy - the energy integral of constraint 2, using
the edge_vector_integral method applied to all edges on constraint 2.
body_1_vol - the volume of body 1, as a sum of several method
instances.  body_1_vol_meth is the  facet_vector_integral of (0,0,z) over
all the facets on the body. body_con_2_meth is the integral of
the constraint 2 content integrand over all edges on facets of body 1
which are edges on constraint 2.  
gravity_quant - the total gravitational energy of all bodies
with assigned densities.  This quantity is always present even if you
don't have any bodies, or don't have any body densities.  But you'll notice
the modulus is 0, which means its evaluation is skipped, so the presence
of this quantity doesn't harm anything.
You can find the quantity or method contribution of single elements
by using the quantity or method name as an attribute of elements.
Using a quantity name really means summing over all its constituent
methods that apply to the element.  For example, in plates_column,
 Enter command: foreach edge ee where on_constraint 2 do printf "%d  %f\n",id, ee.body_1_con_2_meth
5  0.000000
6  0.000000
7  1.000000
8  0.000000
Enter command: foreach edge where constraint_1_energy != 0 do print constraint_1_energy
  -0.342020143325669
 Reasonable scale factors. 
Trouble in evolving is usually signaled by a small scale, which means
there is some obstacle to evolution. Of course, that means you have to
know what a reasonable scale is, and that depends on the type of energy
you are using and how refined your surface si.  In normal evolution, the 
size of the scale is set by
the development of small-scale roughness in the surface. Combined with
a little dimensional analysis, that leads to the conclusion that the
scale should vary as L2-q, where L is the typical edge 
length and
the units of energy are lengthq.  The dimensional analysis goes
like this:  Let D be the perturbation of one vertex away from an equilibrium
surface.  In general, energy is quadratic around an equibrium, so
   E = D2Lq-2
So the gradient of energy at the vertex is 
    grad E = 2D Lq-2
The motion is the scale times the gradient, which we want proportional to D,
so 
    scale * grad E = scale * 2 D Lq-2 = D  
So scale is on the order of L 2-q.  Some examples:
Dimensional Dependence of Scale
| Energy | Energy dimension | Scale | Example file | 
| Area of soapfilm | L2 | L0 | quad.fe | 
| Length of string | L1 | L1 | flower.fe | 
| Squared curvature of string | L-1 | L3 | elastic8.fe | 
| Squared mean curvature of soapfilm | L0 | L2 | sqcube.fe | 
In particular, the scale for area evolution is independent of refinement,
but for most other energies the scale decreases with refinement.
Another common influence on the scale for area evolution is the surface
tension.  Doing a liquid solder simulation in a system of units where
the surface tension of facets is assigned a value 470, say, means that
all calculated gradients are multiplied by 470, so the scale decreases
by a factor of 470 to get the same geometric motion.  Thus you should
set scale_limit to be the inverse of the surface tension.
Back to top of Surface Evolver documentation.
     
Index.