Surface Evolver Newsletter no. 3

Back to top of Surface Evolver documentation.


		      Surface Evolver Newsletter Number 3
			      April 3, 1993

                    Editor: Ken Brakke, brakke@geom.umn.edu

Contents:
  A question
  DOS 32-bit version
  Version 1.90 
  Some examples of using new language features

A question:

Is anybody out there still using Minneview?  That was the precursor
to geomview.  Any objections if I drop Minneview support from the
Evolver?

DOS 32-bit version:

I have made a DOS version of the Surface Evolver using a 
32-bit compiler and DOS extender, the DJGPP package from 
the Free Software Foundation.  It requires at least a 386
with math coprocessor, and will use any extended memory it
finds.  Also VGA graphics. It is available for anonymous ftp 
from geom.umn.edu as pub/evolver.zip.  This contains the binary, 
the extender, and a short documentation file.  Version 1.90 for
DOS may not be posted for ftp for a day or two after this newsletter
goes out, so check the date when you get it.

This is my first venture into DOS extenders, and I've tested it
on just my own machine, so there may be some glitches.  However,
it is vastly superior to any 16 bit version.  I do not intend to
support a 16-bit version any more.

Version 1.90:

Now available for ftp.

Version 1.90 new features:

Named quantities and methods.
These are an effort to provide a more systematic way of adding new
energies and constraints.  A "method" is a way of calculating a scalar
value from some particular type of element (vertex, edge, facet, body).
A "quantity" is the sum total of various methods applied to various
elements, although usually just one method is involved. Any quantities
may be declared to be one of three types: 
1) energy quantities are added to the overall energy of the surface; 
2) fixed quantities that are constrained to a fixed target value (by a 
single Newton step at each iteration); and
3) information quantities whose values are merely reported to the user.
Each quantity has a "modulus", which is just a scalar multiplier of
the whole quantity. A modulus of 0 will turn off an energy quantity.
Adding a new method involves writing C routines to calculate the value
and the gradient as a function of vertex coordinates, and adding a
structure to the method name  array in quantity.c.  Currently implemented 
methods include edge_length, facet_area, mean_curvature_integral (first 
power, not square), gauss_curvature_integral (first power),  hooke_energy 
(for edges as springs with an equilibrium length), and various knot energies.
See the Datafile chapter for details on how to set these up. The sample
datafile  knotty.fe contains some examples. Quantity values can be seen 
with the Q or A command, and the A command can be used to change the 
target value of a fixed quantity, the modulus of a quantity, or some 
parameters associated to various methods.  NOTE: named quantities and
methods are still under development, and the syntax and usage may
change as I get more experience with them.  But they are the way I
intend to add all new energies and quantity constraints to the Evolver.  
In particular, the `AREA_FIXED' feature should be regarded as obsolete,
and you should use something like
`quantity surface_area fixed = 6 modulus 1 global_method facet_area'
in the top of your datafile. This may seem a little long-winded,
but that's the price of generality.

Conjugate gradient ON/OFF state saved in dump file.
Note that conjugate gradient history vector is not saved.

Notching and "dihedral" attribute apply to vertices in the string model.

FOREACH iterator added to the command language to iterate over elements.
See examples below.

LOAD command added. Syntax: LOAD ``filename''. Useful
for starting new surfaces, especially in scripts.

PRINTF command added for formatted printing. Syntax:
      PRINTF "format string",expr,expr,...
expr is floating point, so use %f or %g formats.  Everything is passed
to the C printf functions, so you can use all its precision and
format options on %f and %g. See examples below.

String variables have been added.  Can be used where quoted strings needed.  
Can be assigned to.  SPRINTF is a version of PRINTF giving string output.
NOTE: Piping and `system' command work only with quoted strings or
string variables.

A view_transformation matrix in the datafile may be preceded by "color n" 
to give that transform a color (overrides any facet color).

In queries, element attribute ``oid'' added, which returns a 
signed version of id.  Useful if you want to use the command language
to make a special version of a datafile.  See example below.

Many knot energies added.  Also a ``hooke energy'' that keeps edges near 
a uniform length.  These were due to a Knot Workshop held at the
Geometry Center in March.  It is a popular thing these days to 
put an "electric charge" on a knot and let it repel itself into
a nice smooth curve.  Some people even evolver knotted 2-spheres
in 4-space!

PostScript output now optionally includes color.  When making a
PostScript file from the P menu, you will be asked if you want
to include color.  Including color makes the file longer, but
the files should still print on monochrome postscript devices.

On NeXT version, -t option added to command line arguments (i.e. when
starting evolver) to give terminal interface instead of menu and
dialog boxes.


Some examples of using new language features

The Evolver command language continues to grow by accretion, and it
looks like it's headed towards a full programming language.  It has
variables, expressions, subroutines, conditionals, and iteration constructs.
But not subroutine arguments, local variables, structures, or arrays.
Variables are either floating point, string, or subroutine names.
There are no integer variables, so you can use only floating point
formats in printf.  But the %g format will print whole number floats
as integers.  Remember to use at least two-letter names for variables,
as single letters tend to be interpreted as commands.

One feature different from ordinary C is the presence of iterators
over geometric elements.  These occur wherever an element type
(vertices, edges, facets, bodies, singular or plural) appears in a 
command.  Attributes of the iteration element may be used later in the
command.  The iteration element may be named (useful in nested iterations),
in which case the name must be used when the attribute is referenced.
Element types used as attributes will just generate the elements 
associated with the parent element, so if ff is a facet, then
ff.vertex will generate its three vertices.  Also, each iterator
can take a "where" clause to limit the elements included.

Here are some examples.  Since the language expects one command per
line, line splicing is needed for long commands.  Hence I tend to
break long commands up into several little named commands.
The best way to use these longer commands is to put their definitions
at the end of your datafile in a "read" section, or have them in a
separate file you can read with the "read" command.


1. A script to evolve and regularly save dumps in different files:

nn := 1
while nn < 100 do { g 100; ff := sprintf "stage%g.dmp",nn; dump ff; nn:=nn+1}


2. Your own iterate command to print out what you want, like energy
change each step:

olde := total_energy;
gg := { g; printf "Change: %10.5g\n",total_energy-olde; olde:=total_energy}


3. A command to print a file listing vertices and edges (happens to
be the OFF format for geomview):

aa:=foreach vertex vv do { printf "%f %f %f \n",x,y,z }
bb:=foreach facet ff do { printf "3 ";\
       foreach ff.vertex do printf "%g ",id-1; printf "\n"}
do_off:= {printf "OFF\n%g %g %g\n",vertex_count,facet_count,edge_count;aa;bb}

This prints to stdout, so you would use it with redirection:

Enter command: do_off | "cat > test.off"


4. A command to duplicate the fundamental region of a symmetric surface
across a plane of mirror symmetry. 

// Producing datafile surface duplicated across a mirror.
// This is set up to do constraint 1 only.
// Mirrored constraints given x numbers.
// Resulting datafile needs mirrored constraints added by hand.
// Usage: mm | "cat > filename.fe"

// Mirror plane aa*x + bb*y + cc*z = dd
aa := 1; bb := 0; cc := 0; dd := 0
// You have to set these to the proper coefficients for constraint 1
// before doing mm.

ma := foreach vertex do { printf "%g  %g %g %g ",id,x,y,z;  \
           if fixed then printf "fixed "; \
	   if on_constraint 1 then printf "constraint 1 " ;\
	   if on_constraint 2 then printf "constraint 2 " ;\
	   if on_constraint 3 then printf "constraint 3 " ;\
	   if on_constraint 4 then printf "constraint 4 " ;\
	   if on_constraint 5 then printf "constraint 5 " ;\
	   printf "\n";\
	   }
mb := { voff := vertex_count }
mc := foreach vertex do if not on_constraint 1 then { \
  	   lam := 2*(dd-aa*x-bb*y-cc*z)/(aa*aa+bb*bb+cc*cc);\
           printf "%g  %g %g %g ",id+voff,x+lam*aa,y+lam*bb,z+lam*cc;  \
           if fixed then printf "fixed "; \
	   if on_constraint 1 then printf "constraint 1x " ;\
	   if on_constraint 2 then printf "constraint 2x " ;\
	   if on_constraint 3 then printf "constraint 3x " ;\
	   if on_constraint 4 then printf "constraint 4x " ;\
	   if on_constraint 5 then printf "constraint 5x " ;\
	   printf "\n";\
	   }
md := foreach edge ee do {\
	   printf "%g   ",id; \
	   foreach ee.vertex do printf "%g ",oid; \
           if ee.fixed then printf "fixed "; \
	   if ee.on_constraint 1 then printf "constraint 1 " ;\
	   if ee.on_constraint 2 then printf "constraint 2 " ;\
	   if ee.on_constraint 3 then printf "constraint 3 " ;\
	   if ee.on_constraint 4 then printf "constraint 4 " ;\
	   if ee.on_constraint 5 then printf "constraint 5 " ;\
	   printf "\n";\
	   }
me := { eoff := edge_count }
mf := foreach edge ee do if not on_constraint 1 then {\
	   printf "%g   ",id+eoff; \
	   foreach ee.vertex do { \
	   if on_constraint 1 then { printf "%g ",oid;} \
	   else { printf "%g ", id+voff;} };   \
           if ee.fixed then printf "fixed "; \
	   if ee.on_constraint 1 then printf "constraint 1x " ;\
	   if ee.on_constraint 2 then printf "constraint 2x " ;\
	   if ee.on_constraint 3 then printf "constraint 3x " ;\
	   if ee.on_constraint 4 then printf "constraint 4x " ;\
	   if ee.on_constraint 5 then printf "constraint 5x " ;\
	   printf "\n";\
	   }
mg := foreach facet ff do {\
	   printf "%g   ",id; \
	   foreach ff.edge do printf "%g ",oid;\
           if ff.fixed then printf "fixed "; \
	   if ff.on_constraint 1 then printf "constraint 1 " ;\
	   if ff.on_constraint 2 then printf "constraint 2 " ;\
	   if ff.on_constraint 3 then printf "constraint 3 " ;\
	   if ff.on_constraint 4 then printf "constraint 4 " ;\
	   if ff.on_constraint 5 then printf "constraint 5 " ;\
	   printf "\n";\
	   }
mh := {foff := facet_count}
mi := foreach facet ff do if not on_constraint 1 then  {\
	   printf "%g   ",id+foff; \
	   foreach ff.edge do \
	     { if on_constraint 1 then { printf "%g ",id;} \
	       else printf "%g ",(oid<0?-(id+eoff):id+eoff); }; \
           if ff.fixed then printf "fixed "; \
	   if ff.on_constraint 1 then printf "constraint 1x " ;\
	   if ff.on_constraint 2 then printf "constraint 2x " ;\
	   if ff.on_constraint 3 then printf "constraint 3x " ;\
	   if ff.on_constraint 4 then printf "constraint 4x " ;\
	   if ff.on_constraint 5 then printf "constraint 5x " ;\
	   printf "\n";\
	   }
mm := { list topinfo; \
	printf "\nVertices\n"; ma;mb;mc;\
	printf "\nEdges\n"; md;me;mf;\
	printf "\nFaces\n"; mg;mh;mi;\
	}


End of Evolver Newsletter 3.


Back to top of Surface Evolver documentation.