├── .gitignore ├── doc ├── square.gif ├── catbare.gif ├── catbody.gif ├── cubebare.gif ├── twointor.gif ├── columnbare.gif ├── manual230.pdf ├── moundbare.gif ├── square-e1.gif ├── square-e2.gif ├── square-e3.gif ├── square-e4.gif ├── square-e5.gif ├── square-e6.gif ├── square-e7.gif ├── square-e8.gif ├── ringblobbare.gif ├── twointorbare.gif ├── catbody-saddle.gif ├── news_19.htm ├── news_16.htm ├── evolver.1 ├── profiling.htm ├── default.htm ├── default.html ├── evolver.htm ├── addload_example.fe ├── news_10.htm ├── column.fe ├── news_06.htm ├── news_14.htm ├── twointor.htm ├── news_09.htm ├── news_04.htm ├── news_13.htm ├── intro.htm └── tutorial.htm ├── fe ├── OCTA.WLF ├── popstr.fe ├── quad.fe ├── compdump.cmd ├── rotate.cmd ├── off.cmd ├── metric.fe ├── reorder.cmd ├── simplex3.fe ├── stl.cmd ├── relaxed.fe ├── quadm.fe ├── equi2.cmd ├── equi.cmd ├── order.cmd ├── orderlis.cmd ├── gzipdump.cmd ├── crystal.fe ├── octa.fe ├── polyfilm.cmd ├── rewrap2.cmd ├── saveview.cmd ├── orderdmp.cmd ├── cube.fe ├── dxf.cmd ├── strdup.cmd ├── wavefront.cmd ├── zebra.cmd ├── twointor.fe ├── fourier.cmd ├── symtest.fe ├── gaussequi.cmd ├── slidestr.fe ├── slice.cmd ├── rewrap.cmd ├── intersec.cmd ├── mound.fe ├── qmound.fe ├── slice2.cmd ├── gaussmap.cmd ├── ansurf.cmd ├── x3d.cmd ├── catman.fe ├── cat.fe ├── vrml.cmd ├── gaussref.cmd ├── catbody.fe ├── sphere.fe ├── tankex.fe ├── unshear.cmd ├── README-cmd.txt ├── addload_example.fe ├── rib.cmd ├── column.fe ├── knotty.fe ├── povray.cmd └── xray.cmd ├── CMakeLists.txt ├── cmake └── FindMetis.cmake ├── src ├── resource.h ├── tokname.c ├── lex.h ├── alloca.c ├── nulgraph.c ├── mvgraph.c ├── model.h ├── CMakeLists.txt ├── machine.c ├── softimag.c ├── diffuse.c ├── symmetry.c └── zoom.c └── man └── man1 └── evolver.1 /.gitignore: -------------------------------------------------------------------------------- 1 | CMakeFiles* 2 | CMakeCache.txt 3 | Makefile 4 | bin/* 5 | -------------------------------------------------------------------------------- /doc/square.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kashif/evolver/HEAD/doc/square.gif -------------------------------------------------------------------------------- /doc/catbare.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kashif/evolver/HEAD/doc/catbare.gif -------------------------------------------------------------------------------- /doc/catbody.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kashif/evolver/HEAD/doc/catbody.gif -------------------------------------------------------------------------------- /doc/cubebare.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kashif/evolver/HEAD/doc/cubebare.gif -------------------------------------------------------------------------------- /doc/twointor.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kashif/evolver/HEAD/doc/twointor.gif -------------------------------------------------------------------------------- /doc/columnbare.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kashif/evolver/HEAD/doc/columnbare.gif -------------------------------------------------------------------------------- /doc/manual230.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kashif/evolver/HEAD/doc/manual230.pdf -------------------------------------------------------------------------------- /doc/moundbare.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kashif/evolver/HEAD/doc/moundbare.gif -------------------------------------------------------------------------------- /doc/square-e1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kashif/evolver/HEAD/doc/square-e1.gif -------------------------------------------------------------------------------- /doc/square-e2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kashif/evolver/HEAD/doc/square-e2.gif -------------------------------------------------------------------------------- /doc/square-e3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kashif/evolver/HEAD/doc/square-e3.gif -------------------------------------------------------------------------------- /doc/square-e4.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kashif/evolver/HEAD/doc/square-e4.gif -------------------------------------------------------------------------------- /doc/square-e5.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kashif/evolver/HEAD/doc/square-e5.gif -------------------------------------------------------------------------------- /doc/square-e6.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kashif/evolver/HEAD/doc/square-e6.gif -------------------------------------------------------------------------------- /doc/square-e7.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kashif/evolver/HEAD/doc/square-e7.gif -------------------------------------------------------------------------------- /doc/square-e8.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kashif/evolver/HEAD/doc/square-e8.gif -------------------------------------------------------------------------------- /doc/ringblobbare.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kashif/evolver/HEAD/doc/ringblobbare.gif -------------------------------------------------------------------------------- /doc/twointorbare.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kashif/evolver/HEAD/doc/twointorbare.gif -------------------------------------------------------------------------------- /doc/catbody-saddle.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kashif/evolver/HEAD/doc/catbody-saddle.gif -------------------------------------------------------------------------------- /fe/OCTA.WLF: -------------------------------------------------------------------------------- 1 | 0 0 1 2 | 0 0 -1 3 | 0.707 0.707 0 4 | -0.707 0.707 0 5 | 0.707 -0.707 0 6 | -0.707 -0.707 0 7 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8.0) 2 | 3 | set (CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake" 4 | ${CMAKE_MODULE_PATH}) 5 | 6 | project(evolver) 7 | 8 | set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/bin) 9 | 10 | add_subdirectory(src) 11 | -------------------------------------------------------------------------------- /fe/popstr.fe: -------------------------------------------------------------------------------- 1 | // popstr.fe 2 | // evolver string vertex popping test 3 | 4 | STRING 5 | 6 | vertices 7 | 1 0.0 0.0 0.0 fixed 8 | 2 1.0 0.0 0.0 fixed 9 | 3 1.0 0.0 1.0 fixed 10 | 4 0.0 0.0 1.0 fixed 11 | 5 0.5 0.0 0.5 12 | 13 | edges 14 | 1 1 5 15 | 2 2 5 16 | 3 3 5 17 | 4 4 5 18 | 19 | read 20 | 21 | // Typical evolution 22 | gogo := { o; g 5 } 23 | 24 | -------------------------------------------------------------------------------- /fe/quad.fe: -------------------------------------------------------------------------------- 1 | // quad.fe 2 | // simple skew quadrilateral 3 | 4 | vertices 5 | 1 0 0 1 fixed 6 | 2 2 0 0 fixed 7 | 3 2 2 1 fixed 8 | 4 0 2 0 fixed 9 | 10 | edges 11 | 1 1 2 fixed 12 | 2 2 3 fixed 13 | 3 3 4 fixed 14 | 4 4 1 fixed 15 | 16 | faces 17 | 1 1 2 3 4 18 | 19 | read 20 | 21 | // Typical evolution 22 | gogo := { r; g 5; r; g 5; r; g 5; hessian; hessian; } 23 | 24 | 25 | -------------------------------------------------------------------------------- /fe/compdump.cmd: -------------------------------------------------------------------------------- 1 | // compdump.cmd 2 | // command for dumping datafile directly to compressed form 3 | // 4 | 5 | dumpcmd := sprintf "compress >%s.dmp.Z",datafilename 6 | dodump := { list topinfo; 7 | print "\nvertices\n"; list vertices; 8 | print "\nedges\n"; list edges; 9 | print "\nfaces\n"; list facets; 10 | print "\nbodies\n"; list bodies; 11 | list bottominfo } 12 | compdump := { print dumpcmd; dodump | dumpcmd } 13 | 14 | -------------------------------------------------------------------------------- /cmake/FindMetis.cmake: -------------------------------------------------------------------------------- 1 | FIND_PATH(METIS_INCLUDE_DIR metis.h 2 | /opt/local/include 3 | /usr/local/include 4 | /usr/include 5 | /usr/include/metis) 6 | 7 | FIND_LIBRARY(METIS_LIBRARY metis 8 | /opt/local/lib 9 | /usr/local/lib 10 | /usr/lib) 11 | 12 | include(FindPackageHandleStandardArgs) 13 | find_package_handle_standard_args(LibMetis DEFAULT_MSG 14 | METIS_LIBRARY METIS_INCLUDE_DIR) 15 | 16 | MARK_AS_ADVANCED( METIS_INCLUDE_DIR METIS_LIBRARY ) -------------------------------------------------------------------------------- /fe/rotate.cmd: -------------------------------------------------------------------------------- 1 | // rotate.cmd 2 | // Surface Evolver procedure to rotate unfixed vertices by angle about z axis. 3 | // Programmer: Ken Brakke, brakke@susqu.edu, http://www.susqu.edu/brakke 4 | 5 | // Usage: rotate(angle) 6 | // where angle is in radians. 7 | 8 | procedure rotate(real roth) := { 9 | local sss,ccc,rrad,olds; 10 | sss := sin(roth); ccc := cos(roth); 11 | foreach vertex vv where not fixed do 12 | { rrad := vv.x^2+vv.y^2; 13 | oldx := vv.x; 14 | set vv x vv.x*ccc-vv.y*sss; 15 | set vv y oldx*sss+vv.y*ccc; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /fe/off.cmd: -------------------------------------------------------------------------------- 1 | // off.cmd 2 | 3 | // Surface Evolver command to print OFF format file. 4 | // usage: 5 | // do_off >>> "filename.off" 6 | 7 | // Programmer: Ken Brakke, brakke@susqu.edu, http://www.susqu.edu/brakke 8 | 9 | do_off := { 10 | // file header 11 | printf "OFF\n%g %g %g\n",vertex_count,facet_count,edge_count; 12 | 13 | // vertex list 14 | foreach vertex do { printf "%f %f %f \n",x,y,z }; 15 | 16 | // triangle list 17 | foreach facet ff do 18 | { printf "3 "; 19 | foreach ff.vertex do printf "%g ",id-1; printf "\n"; 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /src/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Developer Studio generated include file. 3 | // Used by evolver.rc 4 | // 5 | #define IDI_ICON1 101 6 | 7 | // Next default values for new objects 8 | // 9 | #ifdef APSTUDIO_INVOKED 10 | #ifndef APSTUDIO_READONLY_SYMBOLS 11 | #define _APS_NEXT_RESOURCE_VALUE 102 12 | #define _APS_NEXT_COMMAND_VALUE 40001 13 | #define _APS_NEXT_CONTROL_VALUE 1000 14 | #define _APS_NEXT_SYMED_VALUE 101 15 | #endif 16 | #endif 17 | -------------------------------------------------------------------------------- /fe/metric.fe: -------------------------------------------------------------------------------- 1 | // metric.fe 2 | // Demonstration of background metric with strings 3 | 4 | // Metric turns punctured plane into catenoid. Initial string 5 | // shrinks to loop around throat. Note that graphing uses just 6 | // the plane coordinates without metric. 7 | 8 | SPACE_DIMENSION 2 9 | 10 | STRING 11 | 12 | #define G11 (1 + 1/(x^2 + y^2))^2 13 | 14 | METRIC 15 | G11 0 16 | 0 G11 17 | 18 | vertices 19 | 1 1 0 20 | 2 0 2 21 | 3 -2 0 22 | 4 0 -1 23 | 24 | edges 25 | 1 1 2 26 | 2 2 3 27 | 3 3 4 28 | 4 4 1 29 | 30 | read 31 | 32 | // Typical evolution 33 | gogo := { g 5; r; g 5; r; g 5; r; g 5; } 34 | -------------------------------------------------------------------------------- /fe/reorder.cmd: -------------------------------------------------------------------------------- 1 | // reorder.cmd 2 | 3 | define vertex attribute vertex_order_key real 4 | define edge attribute edge_order_key real 5 | define facet attribute facet_order_key real 6 | define body attribute body_order_key real 7 | define facetedge attribute facetedge_order_key real 8 | 9 | reorder := { 10 | set vertex vertex_order_key x+y+z; 11 | set edge ee edge_order_key min(ee.vertex,vertex_order_key); 12 | set facetedge fe facetedge_order_key fe.edge[1].edge_order_key; 13 | set facet ff facet_order_key min(ff.vertex,vertex_order_key); 14 | set body bb body_order_key min(bb.facet,facet_order_key); 15 | reorder_storage; 16 | } 17 | -------------------------------------------------------------------------------- /fe/simplex3.fe: -------------------------------------------------------------------------------- 1 | // simplex3.fe 2 | 3 | // Evolver data for bubble in 4-space. Initially simplex. 4 | // Evolves into 3-sphere in 4-space. 5 | 6 | SIMPLEX_REPRESENTATION 7 | SPACE_DIMENSION 4 8 | SURFACE_DIMENSION 3 9 | 10 | vertices 11 | 1 0 0 0 0 12 | 2 1 0 0 0 13 | 3 0 1 0 0 14 | 4 0 0 1 0 15 | 5 0 0 0 1 16 | 17 | faces /* given as oriented vertex list */ 18 | 1 2 3 4 5 19 | 2 3 4 5 1 20 | 3 4 5 1 2 21 | 4 5 1 2 3 22 | 5 1 2 3 4 23 | 24 | bodies 25 | 1 1 2 3 4 5 volume .04 26 | 27 | read 28 | 29 | // Typical evolution 30 | gogo := { r; g 5; U; g 10; r; g 10; r; g 20; r; g 20; } 31 | -------------------------------------------------------------------------------- /fe/stl.cmd: -------------------------------------------------------------------------------- 1 | // stl.cmd 2 | 3 | // Surface Evolver command to produce STL format text file from surface. 4 | // Evolver command line usage: 5 | // read "stl.cmd" 6 | // stl >>> "filename.stl" 7 | 8 | // Programmer: Ken Brakke, brakke@susqu.edu, http://www.susqu.edu/brakke 9 | 10 | stl := { 11 | local mag,inx; 12 | printf "solid\n"; 13 | foreach facet ff do 14 | { mag := sqrt(ff.x^2+ff.y^2+ff.z^2); 15 | printf "facet normal %f %f %f\n",ff.x/mag,ff.y/mag,ff.z/mag; 16 | printf " outer loop\n"; 17 | for ( inx := 1 ; inx <= 3 ; inx += 1 ) 18 | printf " vertex %f %f %f\n",ff.vertex[inx].x,ff.vertex[inx].y, 19 | ff.vertex[inx].z; 20 | printf " endloop\n"; 21 | printf " endfacet\n"; 22 | }; 23 | printf "endsolid\n"; 24 | } 25 | 26 | -------------------------------------------------------------------------------- /fe/relaxed.fe: -------------------------------------------------------------------------------- 1 | // relaxed.fe 2 | // Test of relaxed_elastic energy 3 | 4 | space_dimension 5 // 2 extra for unstrained reference coordinates 5 | 6 | quantity stretchy energy method relaxed_elastic global 7 | quantity stretchy1 info_only method relaxed_elastic1 global 8 | quantity stretchy2 info_only method relaxed_elastic2 global 9 | 10 | define facet attribute poisson_ratio real 11 | define vertex attribute ref_coord real[2] 12 | 13 | constraint 1 formula: x4 = ref_coord[1] 14 | constraint 2 formula: x5 = ref_coord[2] 15 | 16 | vertices 17 | 1 0 0 0 0 0 constraint 1,2 ref_coord 0 0 18 | 2 1 0 0 1 0 constraint 1,2 ref_coord 1 0 19 | 3 0 1 0 1 1 constraint 1,2 ref_coord 0 1 20 | 21 | edges 22 | 1 1 2 23 | 2 2 3 24 | 3 3 1 25 | 26 | faces 27 | 1 1 2 3 28 | 29 | read 30 | set facet poisson_ratio 0.8 31 | set facet tension 0.0 32 | 33 | -------------------------------------------------------------------------------- /fe/quadm.fe: -------------------------------------------------------------------------------- 1 | // quadm.fe 2 | 3 | // quadrilateral boundary wire 4 | // test of metric 5 | 6 | INTEGRAL_ORDER 7 7 | 8 | METRIC 9 | /* 10 | 1+4*x1^2 4*x1*x2 2*x1 11 | 4*x1*x2 1+4*x2^2 2*x2 12 | 2*x1 2*x2 1 13 | */ 14 | 1 0 0 15 | 0 1 0 16 | 0 0 1 17 | 18 | constraint 1 19 | formula: x1 = 0 20 | 21 | constraint 2 22 | formula: x1 = 1 23 | 24 | constraint 3 25 | formula: x2 = 0 26 | 27 | constraint 4 28 | formula: x2 = 1 29 | 30 | constraint 5 31 | formula: x1^2 + x2^2 + x3 = 0 32 | 33 | 34 | vertices 35 | 1 0 0 0 fixed 36 | 2 1 0 -1 fixed 37 | 3 1 1 -2 fixed 38 | 4 0 1 -1 fixed 39 | 40 | edges 41 | 1 1 2 fixed constraints 3,5 42 | 2 2 3 fixed constraints 2,5 43 | 3 3 4 fixed constraints 4,5 44 | 4 4 1 fixed constraints 1,5 45 | 5 2 4 46 | 47 | faces 48 | 1 1 5 4 49 | 2 2 3 -5 50 | 51 | 52 | read 53 | 54 | // Typical evolution 55 | gogo := { r; g 12; U; r; g 12; r; g 12; r; g 20; } 56 | -------------------------------------------------------------------------------- /src/tokname.c: -------------------------------------------------------------------------------- 1 | 2 | /* to be appended to end of ytab.c so it knows about yytoks */ 3 | 4 | /****************************************************************** 5 | * 6 | * function: tokname() 7 | * 8 | * purpose: find name of given token number. Uses yytoks[] 9 | * list used by debugging. 10 | * 11 | */ 12 | 13 | 14 | char *tokname(toknum) 15 | int toknum; 16 | { 17 | char *name; 18 | 19 | #ifndef NO_YACC_DEBUG 20 | #ifdef YYBISON 21 | name = yytname[YYTRANSLATE(toknum)]; 22 | 23 | return name; 24 | #else 25 | int yy_i; 26 | 27 | for ( yy_i = 0; yytoks[yy_i].t_val >= 0; yy_i++ ) 28 | if ( yytoks[yy_i].t_val == toknum ) 29 | return yytoks[yy_i].t_name; 30 | /* unfound */ 31 | name = " "; 32 | sprintf(name,"%4d (unnamed)",toknum); 33 | return name; 34 | #endif 35 | #else 36 | /* unfound */ 37 | name = " "; 38 | sprintf(name,"%4d (unnamed)",toknum); 39 | return name; 40 | #endif 41 | 42 | } 43 | 44 | -------------------------------------------------------------------------------- /fe/equi2.cmd: -------------------------------------------------------------------------------- 1 | // equi2.cmd -- to color edges subject to equiangulation 2 | 3 | // Programmer: Ken Brakke, brakke@susqu.edu, http://www.susqu.edu/brakke 4 | 5 | // useage: showequi 6 | 7 | showequi := { 8 | local ecount, al,bl,cl,dl,el,nn; 9 | 10 | ecount := 0; 11 | foreach edge ee do 12 | { al := ee.length; 13 | nn := 1; 14 | foreach ee.facet ff do 15 | { foreach ff.edge fe do 16 | { if ( fe.id != ee.id ) then 17 | { if ( nn == 1 ) then bl := fe.length 18 | else if ( nn == 2 ) then cl := fe.length 19 | else if ( nn == 3 ) then dl := fe.length 20 | else if ( nn == 4 ) then el := fe.length; 21 | nn := nn + 1; 22 | } 23 | } 24 | }; 25 | if ( nn == 5 ) then 26 | if (bl^2+cl^2-al^2)/bl/cl + (dl^2+el^2-al^2)/dl/el < 0 then 27 | { set ee color green; 28 | ecount := 1 + ecount 29 | } 30 | }; 31 | printf "Found %g edges.\n",ecount; 32 | show_expr edges where 1 33 | } 34 | -------------------------------------------------------------------------------- /fe/equi.cmd: -------------------------------------------------------------------------------- 1 | // equi.cmd -- to color edges green subject to equiangulation 2 | 3 | // Programmer: Ken Brakke, brakke@susqu.edu, http://www.susqu.edu/brakke 4 | 5 | // Usage: showequi 6 | 7 | showequi := { 8 | local ecount, al, nn, cl, dl, el, bl; 9 | 10 | ecount := 0; 11 | foreach edge ee do 12 | { al := ee.length; 13 | nn := 1; 14 | foreach ee.facet ff do 15 | { foreach ff.edge fe do 16 | { if ( fe.id != ee.id ) then 17 | { if ( nn == 1 ) then bl := fe.length 18 | else if ( nn == 2 ) then cl := fe.length 19 | else if ( nn == 3 ) then dl := fe.length 20 | else if ( nn == 4 ) then el := fe.length; 21 | nn := nn + 1; 22 | } 23 | } 24 | }; 25 | if ( nn == 5 ) then 26 | if (bl^2+cl^2-al^2)/bl/cl + (dl^2+el^2-al^2)/dl/el < -1e-5 then 27 | { set ee color green; 28 | ecount := 1 + ecount 29 | } 30 | }; 31 | printf "Found %g edges.\n",ecount; 32 | show_expr edges where 1 33 | } 34 | -------------------------------------------------------------------------------- /fe/order.cmd: -------------------------------------------------------------------------------- 1 | // order.cmd 2 | // Evolver command to number string-model vertices consecutively. 3 | // Result is order number in vertex extra attribute 'number'. 4 | 5 | // Programmer: Ken Brakke, brakke@susqu.edu, http://www.susqu.edu/brakke 6 | 7 | // Usage: order 8 | 9 | define vertex attribute number integer 10 | 11 | order := { 12 | local ecount,e_id,first_e,v_id,newv_id,newe_id; 13 | 14 | ecount := 0; // for safety 15 | // get starting edge, since can't assume edge[1] exists 16 | foreach edge do { e_id := id; break; }; 17 | first_e := e_id; 18 | v_id := edge[e_id].vertex[1].id; 19 | 20 | // follow connected edges 21 | do 22 | { set vertex[v_id] number ecount+1; 23 | foreach edge[e_id].vertex vv do 24 | { if ( vv.id != v_id ) then 25 | { newv_id := vv.id; 26 | foreach vv.edge ee do 27 | if ee.id != e_id then newe_id := ee.id 28 | } 29 | }; 30 | e_id := newe_id; v_id := newv_id; 31 | ecount := ecount + 1; 32 | } while ( (e_id != first_e) and (ecount <= edge_count) ) 33 | } 34 | -------------------------------------------------------------------------------- /src/lex.h: -------------------------------------------------------------------------------- 1 | /************************************************************* 2 | * This file is part of the Surface Evolver source code. * 3 | * Programmer: Ken Brakke, brakke@susqu.edu * 4 | *************************************************************/ 5 | 6 | /************************************************************ 7 | * 8 | * File: lex.h 9 | * 10 | * Contents: Definitions for lexical analyzer for reading 11 | * data files. 12 | */ 13 | 14 | #ifndef _LEX_H_ 15 | #define _LEX_H_ 16 | 17 | /* Data type for yylval and parse semantics stack. */ 18 | typedef struct { int i; /* standard integer yylval */ 19 | int qnum; 20 | REAL r; 21 | int etype; /* element type */ 22 | int datatype; /* expression datatype */ 23 | struct sym *symptr; /* iteration variable names */ 24 | char lexeme[32]; /* for identifiers */ 25 | } yystype; 26 | #define YYSTYPE yystype 27 | extern YYSTYPE yylval; /* parser terminal value */ 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/alloca.c: -------------------------------------------------------------------------------- 1 | /************************************************************* 2 | * This file is part of the Surface Evolver source code. * 3 | * Programmer: Ken Brakke, brakke@susqu.edu * 4 | *************************************************************/ 5 | 6 | 7 | /********************************************************** 8 | * 9 | * File: alloca.c 10 | * 11 | * Contents: Kludge substitute for alloca() for those 12 | * systems that do not have it. alloca() is 13 | * an old unix function that allocates memory 14 | * from the stack. The version of YACC I use 15 | * uses alloca in case of parsing stack overflow, 16 | * so alloca should almost never be called. 17 | * Link with this file only if the linker 18 | * complains about not finding alloca. 19 | * This file simply substitutes a call to 20 | * malloc(), so represents a potential 21 | * memory leak. 22 | */ 23 | 24 | #include "include.h" 25 | 26 | void * alloca(size_t size) 27 | { return (void*)malloc(size); 28 | } 29 | -------------------------------------------------------------------------------- /src/nulgraph.c: -------------------------------------------------------------------------------- 1 | /************************************************************* 2 | * This file is part of the Surface Evolver source code. * 3 | * Programmer: Ken Brakke, brakke@susqu.edu * 4 | *************************************************************/ 5 | 6 | /* Null graphics module for evolver */ 7 | 8 | #include "include.h" 9 | 10 | /* callable null functions of the right types */ 11 | void null_start ARGS((void)) {} 12 | void null_edge(struct graphdata * g,edge_id id) {} 13 | void null_facet(struct graphdata * g,facet_id id) {} 14 | void display_null(struct tsort * t) {} 15 | 16 | void graph_new_surface() {} 17 | 18 | void display() 19 | { 20 | if ( init_graphics == NULL ) 21 | kb_error(1252,"No screen display available. This Evolver compiled with nulgraph.c.\n",WARNING); 22 | 23 | ENTER_GRAPH_MUTEX 24 | init_graphics = null_function; 25 | finish_graphics = null_function; 26 | graph_edge = null_edge; 27 | graph_start = null_start; 28 | graph_facet = null_facet; 29 | graph_end = null_function; 30 | display_facet = display_null; 31 | 32 | graphgen(); 33 | LEAVE_GRAPH_MUTEX 34 | } 35 | -------------------------------------------------------------------------------- /fe/orderlis.cmd: -------------------------------------------------------------------------------- 1 | // orderlist.cmd 2 | // Evolver command to number string vertices consecutively 3 | // by means of extra attribute 'number'. 4 | // And list them to stdout. Can be redirected to file. 5 | 6 | // Programmer: Ken Brakke, brakke@susqu.edu, http://www.susqu.edu/brakke 7 | 8 | // Usage: orderlist 9 | 10 | define vertex attribute number integer 11 | 12 | orderlist := { 13 | local ecount,e_id,first_e,v_id,newv_id,newe_id; 14 | 15 | ecount := 0; // for safety 16 | // get starting edge, since can't assume edge[1] exists 17 | foreach edge do { e_id := id; break; }; 18 | first_e := e_id; 19 | v_id := edge[e_id].vertex[1].id; 20 | // follow connected edges 21 | do 22 | { set vertex[v_id] number ecount+1; 23 | printf "%g %g %g\n",vertex[v_id].x,vertex[v_id].y,vertex[v_id].z; 24 | foreach edge[e_id].vertex vv do 25 | { if ( vv.id != v_id ) then 26 | { newv_id := vv.id; 27 | foreach vv.edge ee do 28 | if ee.id != e_id then newe_id := ee.id 29 | } 30 | }; 31 | e_id := newe_id; v_id := newv_id; 32 | ecount := ecount + 1; 33 | } while ( (e_id != first_e) and (ecount <= edge_count) ) 34 | } 35 | -------------------------------------------------------------------------------- /fe/gzipdump.cmd: -------------------------------------------------------------------------------- 1 | // gzipdump.cmd 2 | // Evolver command for dumping datafile directly to gzip form 3 | // Needs Evolver version 1.99e or later. 4 | 5 | // Usage: gzipdump 6 | // As is, this will dump to a gzipped file with a default name. 7 | // You may change the filename in the command below to your own liking. 8 | 9 | // gzipped file may be reloaded directly with shell command like 10 | // /etc/mknod epipe p; ((gunzip epipe;rm epipe)& evolver epipe) 11 | 12 | // I suggest defining a csh alias like 13 | // alias gzev '/etc/mknod epipe p;((gzip -d < \!$ >epipe;rm epipe)& evolver \!:1- epipe)' 14 | // so you can just do 15 | // gzev cube.dmp.gz 16 | // The alias even works with options, as in 17 | // gzev -q -p2 cube.dmp.gz 18 | 19 | dodump := { 20 | list topinfo; 21 | print "\nvertices\n"; list vertices; 22 | print "\nedges\n"; list edges; 23 | print "\nfaces\n"; list facets; 24 | print "\nbodies\n"; list bodies; 25 | list bottominfo 26 | } 27 | 28 | gzipdump := { 29 | filename := sprintf "%s.dmp.gz",datafilename; 30 | dumpcmd := sprintf "gzip >%s",filename; 31 | printf "Dumping to %s\n",filename; 32 | dodump | dumpcmd 33 | } 34 | 35 | -------------------------------------------------------------------------------- /fe/crystal.fe: -------------------------------------------------------------------------------- 1 | // crystal.fe 2 | // Evolver data for cube of prescribed volume with 3 | // crystalline surface energy. Evolves into an octahedron. 4 | 5 | Wulff "octa.wlf" // Wulff vectors for octahedral crystal 6 | 7 | vertices 8 | 1 0.0 0.0 0.0 9 | 2 1.0 0.0 0.0 10 | 3 1.0 1.0 0.0 11 | 4 0.0 1.0 0.0 12 | 5 0.0 0.0 1.0 13 | 6 1.0 0.0 1.0 14 | 7 1.0 1.0 1.0 15 | 8 0.0 1.0 1.0 16 | 9 0.0 0.0 0.5 17 | 10 1.0 0.0 0.5 18 | 11 1.0 1.0 0.5 19 | 12 0.0 1.0 0.5 20 | 21 | edges /* given by endpoints and attribute */ 22 | 1 1 2 23 | 2 2 3 24 | 3 3 4 25 | 4 4 1 26 | 5 5 6 27 | 6 6 7 28 | 7 7 8 29 | 8 8 5 30 | 9 1 9 31 | 10 2 10 32 | 11 3 11 33 | 12 4 12 34 | 13 9 5 35 | 14 10 6 36 | 15 11 7 37 | 16 12 8 38 | 17 9 10 39 | 18 10 11 40 | 19 11 12 41 | 20 12 9 42 | 43 | faces /* given by oriented edge loop */ 44 | 1 1 10 -17 -9 45 | 2 2 11 -18 -10 46 | 3 3 12 -19 -11 47 | 4 4 9 -20 -12 48 | 5 5 6 7 8 49 | 6 -4 -3 -2 -1 50 | 7 17 14 -5 -13 51 | 8 18 15 -6 -14 52 | 9 19 16 -7 -15 53 | 10 20 13 -8 -16 54 | 55 | bodies /* one body, defined by its oriented faces */ 56 | 1 1 2 3 4 5 6 7 8 9 10 volume 1 57 | 58 | 59 | read 60 | 61 | // Sample evolution 62 | gogo := { g 10; } 63 | -------------------------------------------------------------------------------- /fe/octa.fe: -------------------------------------------------------------------------------- 1 | // octa.fe 2 | 3 | // Evolver data file for symmetric nonstable film in octahedral frame. 4 | // Pop edges, iterate, then pop vertices. 5 | 6 | vertices 7 | 1 0 0 0 8 | 2 2 0 0 fixed 9 | 3 0 2 0 fixed 10 | 4 -2 0 0 fixed 11 | 5 0 -2 0 fixed 12 | 6 0 0 2 fixed 13 | 7 0 0 -2 fixed 14 | 15 | edges 16 | 1 2 3 fixed 17 | 2 3 4 fixed 18 | 3 4 5 fixed 19 | 4 5 2 fixed 20 | 5 2 6 fixed 21 | 6 3 6 fixed 22 | 7 4 6 fixed 23 | 8 5 6 fixed 24 | 9 7 2 fixed 25 | 10 7 3 fixed 26 | 11 7 4 fixed 27 | 12 7 5 fixed 28 | 13 1 2 29 | 14 1 3 30 | 15 1 4 31 | 16 1 5 32 | 17 1 6 33 | 18 7 1 34 | 35 | faces 36 | 1 13 1 -14 37 | 2 14 2 -15 38 | 3 15 3 -16 39 | 4 16 4 -13 40 | 5 13 5 -17 41 | 6 14 6 -17 42 | 7 15 7 -17 43 | 8 16 8 -17 44 | 9 9 -13 -18 45 | 10 10 -14 -18 46 | 11 11 -15 -18 47 | 12 12 -16 -18 48 | 49 | read 50 | 51 | // Typical evolution, winding up with the central tetrahedral point 52 | // version of the octahedral film. This evolution is not real tidy, 53 | // taking several more pops before settling down, but is just recorded 54 | // from a trial sequence without tidying up. 55 | gogo := { o; U; g 20; t .1; g 10; o; g 20; u; V; t .1; o; g 12; o; u; 56 | V; u; V; g 10; t .1; o; V; g 10; t .1; u; V; g 10; t .1; g 10; 57 | } 58 | -------------------------------------------------------------------------------- /fe/polyfilm.cmd: -------------------------------------------------------------------------------- 1 | // polyfilm.cmd 2 | // command to produce Polycut format file 3 | // usage: polyfilm >>> "filename" 4 | 5 | // Programmer: Ken Brakke, brakke@susqu.edu, http://www.susqu.edu/brakke 6 | 7 | define vertex attribute offnumber integer; 8 | 9 | // command to print OFF format part (the vertices and facets) 10 | verlist := { local offnum; 11 | offnum := 0; 12 | foreach vertex vv do 13 | { printf "%f %f %f \n",x,y,z; 14 | vv.offnumber := offnum; 15 | offnum += 1; 16 | } 17 | } // end verlist 18 | 19 | facelist := { foreach facet ff do 20 | { printf "3 "; 21 | foreach ff.vertex vv do printf "%g ",vv.offnumber; 22 | printf "\n"; 23 | } 24 | } // end facelist 25 | 26 | do_off := { printf "OFF\n%g %g %g\n",vertex_count,facet_count,edge_count; 27 | verlist; 28 | facelist 29 | } // end do_off 30 | 31 | // vect-like file command for triple lines 32 | traa := { trcount ::= sum(edges where valence==3,1)} 33 | trbb := { foreach edge ee where ee.valence==3 do 34 | { foreach ee.vertex vv do printf "%f %f %f ",x,y,z ; 35 | printf "\n"; 36 | } 37 | } 38 | trips := { printf "TRIPLE\n"; traa; printf "%g\n",trcount; trbb } 39 | 40 | polyfilm := {do_off; trips} 41 | 42 | -------------------------------------------------------------------------------- /fe/rewrap2.cmd: -------------------------------------------------------------------------------- 1 | // rewrap2.cmd 2 | 3 | // Commands to rewrap torus vertices and edges to get them nicely 4 | // within unit cell. 2D version. For 3D version, see rewrap.cmd. 5 | // Moves vertices at most one period at a time, so you may have to 6 | // repeat if things are very bad to start with. 7 | 8 | // Uses torus wrap representation and wrap_vertex builtin command. 9 | 10 | // Usage: rewrap2 11 | 12 | rewrap2 := { 13 | if space_dimension != 2 then 14 | { errprintf"rewrap2 is for space dimension 2; for 3D use rewrap3.cmd.\n"; 15 | return; 16 | }; 17 | define body attribute old_volume real; // so can adjust volconst 18 | set body old_volume volume; 19 | foreach vertex vv where vv.x*inverse_periods[1][1]+vv.y*inverse_periods[1][2] 20 | < 0 do wrap_vertex(vv.id,1); 21 | foreach vertex vv where vv.x*inverse_periods[1][1]+vv.y*inverse_periods[1][2] 22 | >= 1 do wrap_vertex(vv.id,31); 23 | foreach vertex vv where vv.x*inverse_periods[2][1]+vv.y*inverse_periods[2][2] 24 | < 0 do wrap_vertex(vv.id,64); 25 | foreach vertex vv where vv.x*inverse_periods[2][1]+vv.y*inverse_periods[2][2] 26 | >= 1 do wrap_vertex(vv.id,1984); 27 | recalc; 28 | local torvol; 29 | torvol := abs(torus_periods[1][1]*torus_periods[2][2] 30 | - torus_periods[1][2]*torus_periods[2][1]); 31 | set body volconst floor((old_volume - volume - volconst)/torvol+.5)*torvol; 32 | 33 | } 34 | 35 | -------------------------------------------------------------------------------- /fe/saveview.cmd: -------------------------------------------------------------------------------- 1 | // saveview.cmd 2 | 3 | // Evolver command for saving current view matrix in proper form 4 | // for reading in. 5 | // Typical usage: saveview >>> "viewfile.cmd" 6 | // Then to restore view: read "viewfile.cmd" 7 | 8 | // Programmer: Ken Brakke, brakke@susqu.edu, http://www.susqu.edu/brakke 9 | 10 | saveview := { 11 | printf "oldautodisplay := (autodisplay);\n"; 12 | printf "autodisplay off\n"; 13 | printf "view_matrix[1][1] := %f\n",view_matrix[1][1]; 14 | printf "view_matrix[1][2] := %f\n",view_matrix[1][2]; 15 | printf "view_matrix[1][3] := %f\n",view_matrix[1][3]; 16 | printf "view_matrix[1][4] := %f\n",view_matrix[1][4]; 17 | printf "view_matrix[2][1] := %f\n",view_matrix[2][1]; 18 | printf "view_matrix[2][2] := %f\n",view_matrix[2][2]; 19 | printf "view_matrix[2][3] := %f\n",view_matrix[2][3]; 20 | printf "view_matrix[2][4] := %f\n",view_matrix[2][4]; 21 | printf "view_matrix[3][1] := %f\n",view_matrix[3][1]; 22 | printf "view_matrix[3][2] := %f\n",view_matrix[3][2]; 23 | printf "view_matrix[3][3] := %f\n",view_matrix[3][3]; 24 | printf "view_matrix[3][4] := %f\n",view_matrix[3][4]; 25 | printf "view_matrix[4][1] := %f\n",view_matrix[4][1]; 26 | printf "view_matrix[4][2] := %f\n",view_matrix[4][2]; 27 | printf "view_matrix[4][3] := %f\n",view_matrix[4][3]; 28 | printf "view_matrix[4][4] := %f\n",view_matrix[4][4]; 29 | printf "if oldautodisplay then autodisplay on\n"; 30 | } 31 | -------------------------------------------------------------------------------- /fe/orderdmp.cmd: -------------------------------------------------------------------------------- 1 | // orderdmp.cmd 2 | // Evolver command to number string vertices consecutively 3 | // by means of extra attribute 'number', 4 | // and create an ordered dump file. 5 | // Pipe output to file to save it. 6 | 7 | // Programmer: Ken Brakke, brakke@susqu.edu, http://www.susqu.edu/brakke 8 | 9 | // Usage: oderdmp 10 | 11 | define vertex attribute number integer 12 | 13 | orderdmp := { 14 | local e_id,newv_id,ecount,first_e,v_id,newe_id; 15 | 16 | list topinfo; 17 | ecount := 0; // for safety 18 | // get starting edge, since can't assume edge[1] exists 19 | foreach edge do e_id := id; 20 | first_e := e_id; 21 | v_id := edge[e_id].vertex[1].id; 22 | // follow connected edges 23 | printf "\nVertices\n"; 24 | do 25 | { set vertex[v_id] number ecount+1; 26 | printf "%g %g %g %g\n",ecount+1,vertex[v_id].x,vertex[v_id].y, 27 | vertex[v_id].z; 28 | foreach edge[e_id].vertex vv do 29 | { if ( vv.id != v_id ) then 30 | { newv_id := vv.id; 31 | foreach vv.edge ee do 32 | if ee.id != e_id then newe_id := ee.id 33 | } 34 | }; 35 | e_id := newe_id; v_id := newv_id; 36 | ecount := ecount + 1; 37 | } while ( (e_id != first_e) and (ecount <= edge_count) ); 38 | printf "\nEdges\n"; 39 | foreach edge ee do 40 | { 41 | printf"%g %g %g \n",ee.id,ee.vertex[1].number,ee.vertex[2].number; 42 | }; 43 | list bottominfo; 44 | } 45 | -------------------------------------------------------------------------------- /fe/cube.fe: -------------------------------------------------------------------------------- 1 | // cube.fe 2 | // Evolver data for cube of prescribed volume. 3 | 4 | vertices 5 | 1 0.0 0.0 0.0 6 | 2 1.0 0.0 0.0 7 | 3 1.0 1.0 0.0 8 | 4 0.0 1.0 0.0 9 | 5 0.0 0.0 1.0 10 | 6 1.0 0.0 1.0 11 | 7 1.0 1.0 1.0 12 | 8 0.0 1.0 1.0 13 | 14 | edges /* given by endpoints and attribute */ 15 | 1 1 2 16 | 2 2 3 17 | 3 3 4 18 | 4 4 1 19 | 5 5 6 20 | 6 6 7 21 | 7 7 8 22 | 8 8 5 23 | 9 1 5 24 | 10 2 6 25 | 11 3 7 26 | 12 4 8 27 | 28 | faces /* given by oriented edge loop */ 29 | 1 1 10 -5 -9 30 | 2 2 11 -6 -10 31 | 3 3 12 -7 -11 32 | 4 4 9 -8 -12 33 | 5 5 6 7 8 34 | 6 -4 -3 -2 -1 35 | 36 | bodies /* one body, defined by its oriented faces */ 37 | 1 1 2 3 4 5 6 volume 1 38 | 39 | read 40 | 41 | // Typical evolution to sphere 42 | gogo := { g 5; r; g 5; hessian; r; g 5; hessian; } 43 | 44 | // Evolution to very high accuracy, using higher-order Lagrange elements. 45 | // To be run on original datafile. 46 | gogo2 := { g 5; r; g 5; hessian; r; g 5; hessian; 47 | lagrange 2; g 5; hessian; 48 | lagrange 4; g 5; hessian; 49 | lagrange 6; g 5; hessian; 50 | ideal_rad := (3*body[1].volume/4/pi)^(1/3); 51 | printf "Area error: %g\n",total_area - 4*pi*ideal_rad^2; 52 | printf "Vertex radius spread: %g\n", 53 | max(vertex,sqrt((x-.5)^2+(y-.5)^2+(z-.5)^2)) 54 | - min(vertex,sqrt((x-.5)^2+(y-.5)^2+(z-.5)^2)); 55 | } 56 | -------------------------------------------------------------------------------- /fe/dxf.cmd: -------------------------------------------------------------------------------- 1 | // dfx.cmd 2 | 3 | // Evolver command to produce AutoCad DXF files 4 | 5 | // Programmer: Ken Brakke, brakke@susqu.edu, http://www.susqu.edu/brakke 6 | 7 | // References: 8 | // http://en.wikipedia.org/wiki/AutoCAD_DXF 9 | // http://images.autodesk.com/adsk/files/acad_dxf.pdf 10 | 11 | // Usage: 12 | // dxf >>> "filename.dxf" 13 | 14 | define dxf_colors integer[16]; 15 | dxf_colors[1] := 5 // blue 16 | dxf_colors[2] := 3 // green 17 | dxf_colors[3] := 4 // cyan 18 | dxf_colors[4] := 10 // red 19 | dxf_colors[5] := 6 // magenta 20 | dxf_colors[6] := 1 // brown 21 | dxf_colors[7] := 9 // lightgray 22 | dxf_colors[8] := 8 // darkgray 23 | dxf_colors[9] := 8 // lightblue 24 | dxf_colors[10] := 3 // lightgreen 25 | dxf_colors[11] := 4 // lightcyan 26 | dxf_colors[12] := 14 // lightred 27 | dxf_colors[13] := 6 // lightmagenta 28 | dxf_colors[14] := 2 // yellow 29 | dxf_colors[15] := 7 // white 30 | dxf := { 31 | printf " 0\nSECTION\n 2\nENTITIES\n"; 32 | foreach facet ff do 33 | { printf " 0\n3DFACE\n 8\n0main\n"; 34 | printf " 10\n%8.6f\n 20\n%8.6f\n 30\n%8.6f\n",ff.vertex[1].x, 35 | ff.vertex[1].y,ff.vertex[1].z; 36 | printf " 11\n%8.6f\n 21\n%8.6f\n 31\n%8.6f\n",ff.vertex[2].x, 37 | ff.vertex[2].y,ff.vertex[2].z; 38 | printf " 12\n%8.6f\n 22\n%8.6f\n 32\n%8.6f\n",ff.vertex[3].x, 39 | ff.vertex[3].y,ff.vertex[3].z; 40 | printf " 13\n%8.6f\n 23\n%8.6f\n 33\n%8.6f\n",ff.vertex[3].x, 41 | ff.vertex[3].y,ff.vertex[3].z; 42 | // try color 43 | printf " 62\n%3d\n",dxf_colors[ff.color]; 44 | }; 45 | printf " 0\nENDSEC\n 0\nEOF\n"; 46 | } 47 | 48 | -------------------------------------------------------------------------------- /fe/strdup.cmd: -------------------------------------------------------------------------------- 1 | // strdup.cmd 2 | 3 | // Evolver command to write a datafile that is an n-fold 4 | // covering of a string. Meant to generate multiple coverings 5 | // of elastic figure 8's. 6 | 7 | // Usage: set dupnum to desired multiple and run "strdup". 8 | 9 | // Programmer: Ken Brakke, brakke@susqu.edu, http://www.susqu.edu/brakke 10 | 11 | dupnum := 2 // covering order 12 | strdup := { 13 | local sheet,vbase,connectflag,swapedge,ebase; 14 | list topinfo; 15 | printf "\nvertices\n"; 16 | sheet := 0; 17 | while ( sheet < dupnum ) do 18 | { vbase := sheet*vertex_count; 19 | foreach vertex do 20 | printf "%g %g %g\n",id+vbase,x,y; 21 | sheet := sheet + 1; 22 | }; 23 | printf "\nedges\n"; 24 | connectflag := 0; 25 | sheet := 0; 26 | swapedge := -1; 27 | while ( sheet < dupnum ) do 28 | { ebase := sheet*edge_count; 29 | vbase := sheet*vertex_count; 30 | foreach edge ee do 31 | { if connectflag and (swapedge != ee.id) then 32 | printf "%g %g %g\n", 33 | ee.id+ebase,ee.vertex[1].id+vbase,ee.vertex[2].id+vbase 34 | else 35 | { printf "%g %g %g\n", 36 | ee.id+ebase,ee.vertex[1].id+vbase, 37 | ee.vertex[2].id+((sheet+1)imod dupnum)*vertex_count; 38 | connectflag := 1; 39 | swapedge := ee.id; 40 | } 41 | }; 42 | sheet := sheet + 1; 43 | }; 44 | printf "\nread\n"; 45 | list procedures; 46 | } // end strdup 47 | -------------------------------------------------------------------------------- /fe/wavefront.cmd: -------------------------------------------------------------------------------- 1 | // wavefront.cmd 2 | 3 | // Surface Evolver command file for producing Wavefront format file 4 | // for surface, suitable for feeding to JavaView. 5 | 6 | // Programmer: Ken Brakke, brakke@susqu.edu, http://www.susqu.edu/brakke 7 | 8 | // Usage: 9 | // wavefront >>> "filename.obj" 10 | // or, for version with normals at vertices, 11 | // wavefrontn >>> "filename.obj" 12 | 13 | define vertex attribute v_num integer 14 | wavefront := { 15 | // Make sure vertices consecutively numbered 16 | new_v_num := 1; 17 | foreach vertex vv do { vv.v_num := new_v_num; new_v_num += 1 }; 18 | 19 | printf "# Wavefront .obj file for %s\n",datafilename; 20 | printf "# Produced by the Surface Evolver.\n\n"; 21 | 22 | foreach vertex vv do printf "v %f %f %f\n",vv.x,vv.y,vv.z; 23 | printf "\n"; 24 | foreach facet ff do printf "f %g %g %g\n",ff.vertex[1].v_num, 25 | ff.vertex[2].v_num, ff.vertex[3].v_num; 26 | 27 | } 28 | 29 | // version with normals at vertices 30 | wavefrontn := { 31 | // Make sure vertices consecutively numbered 32 | new_v_num := 1; 33 | foreach vertex vv do { vv.v_num := new_v_num; new_v_num += 1 }; 34 | 35 | printf "# Wavefront .obj file for %s\n",datafilename; 36 | printf "# Produced by the Surface Evolver.\n\n"; 37 | 38 | foreach vertex vv do printf "v %f %f %f\n",vv.x,vv.y,vv.z; 39 | printf "\n"; 40 | foreach vertex vv do printf "vn %f %f %f\n",vv.vertexnormal[1], 41 | vv.vertexnormal[2],vv.vertexnormal[3]; 42 | printf "\n"; 43 | foreach facet ff do printf "f %g/%g %g/%g %g/%g\n",ff.vertex[1].v_num, 44 | ff.vertex[1].v_num, ff.vertex[2].v_num, 45 | ff.vertex[2].v_num, ff.vertex[3].v_num, 46 | ff.vertex[3].v_num; 47 | 48 | } 49 | 50 | -------------------------------------------------------------------------------- /fe/zebra.cmd: -------------------------------------------------------------------------------- 1 | // zebra.cmd 2 | // Evolver command to alternately color string edges black and white 3 | 4 | // Usage: Set color1 and color2 to the two colors you want, if the 5 | // default black and white are not suitable. Then run "zebra". 6 | 7 | // Programmer: Ken Brakke, brakke@susqu.edu, http://www.susqu.edu/brakke 8 | 9 | color1 := white 10 | color2 := black 11 | zebra := { 12 | local ecount,first_e,v_id,zcolor,zinx,e_id; 13 | 14 | ecount := 0; // for safety 15 | 16 | // Look for valence 2 vertices with same color edges and 17 | // propagate zebra coloring in both directions. 18 | foreach vertex vv where valence==2 and vv.edge[1].color == vv.edge[2].color do 19 | { 20 | first_e := vv.edge[1].oid; 21 | v_id := vv.id; 22 | zcolor := color1; 23 | 24 | for ( zinx := 1 ; zinx <= 2 ; zinx += 1 ) 25 | { 26 | // follow connected edges 27 | e_id := first_e; 28 | do 29 | { set edge[e_id] color zcolor; 30 | v_id := edge[e_id].vertex[2].id; 31 | if vertex[v_id].valence != 2 then break; 32 | if vertex[v_id].edge[1].oid == -e_id then 33 | e_id := vertex[v_id].edge[2].oid 34 | else 35 | e_id := vertex[v_id].edge[1].oid; 36 | zcolor := (zcolor == color1) ? color2 : color1; 37 | ecount := ecount + 1; 38 | } while ( (v_id != vv.id) and (ecount <= edge_count) ); 39 | 40 | if ( v_id == vv.id ) then break; // don't need to go around the other way 41 | // set things up to go around other way next time through the loop. 42 | v_id := vv.id; 43 | zcolor := color2; 44 | first_e := vv.edge[2].oid; 45 | } 46 | 47 | } // end valence 2 vertex loop 48 | } // end zebra 49 | -------------------------------------------------------------------------------- /fe/twointor.fe: -------------------------------------------------------------------------------- 1 | // twointor.fe 2 | 3 | // Two Kelvin tetrakaidecahedra in a torus. 4 | 5 | TORUS_FILLED 6 | 7 | periods 8 | 1.000000 0.000000 0.000000 9 | 0.000000 1.000000 0.000000 10 | 0.000000 0.000000 1.000000 11 | 12 | vertices 13 | 1 0.50 0.00 0.75 14 | 2 0.25 0.00 0.50 15 | 3 0.00 0.25 0.50 16 | 4 0.75 0.00 0.50 17 | 5 0.00 0.50 0.75 18 | 6 0.50 0.00 0.25 19 | 7 0.00 0.75 0.50 20 | 8 0.50 0.25 0.00 21 | 9 0.25 0.50 0.00 22 | 10 0.00 0.50 0.25 23 | 11 0.50 0.75 0.00 24 | 12 0.75 0.50 0.00 25 | 26 | edges /* with torus wrap symbols */ 27 | 1 1 2 * * * 28 | 2 2 3 * * * 29 | 3 1 4 * * * 30 | 4 3 5 * * * 31 | 5 2 6 * * * 32 | 6 2 7 * - * 33 | 7 1 8 * * + 34 | 8 4 6 * * * 35 | 9 5 9 * * + 36 | 10 3 10 * * * 37 | 11 3 4 - * * 38 | 12 6 8 * * * 39 | 13 6 11 * - * 40 | 14 7 4 - + * 41 | 15 8 12 * * * 42 | 16 9 8 * * * 43 | 17 9 11 * * * 44 | 18 10 7 * * * 45 | 19 11 1 * + - 46 | 20 12 5 + * - 47 | 21 5 7 * * * 48 | 22 11 12 * * * 49 | 23 10 12 - * * 50 | 24 9 10 * * * 51 | 52 | faces 53 | 1 1 2 4 9 16 -7 54 | 2 -2 5 12 -16 24 -10 55 | 3 -4 10 18 -21 56 | 4 7 15 20 -4 11 -3 57 | 5 -1 3 8 -5 58 | 6 6 14 -11 -2 59 | 7 5 13 -17 24 18 -6 60 | 8 -12 13 19 7 61 | 9 -16 17 22 -15 62 | 10 -10 11 8 12 15 -23 63 | 11 -21 9 17 19 1 6 64 | 12 -14 -18 23 -22 -13 -8 65 | 13 -24 -9 -20 -23 66 | 14 -19 22 20 21 14 -3 67 | 68 | bodies 69 | 1 -1 -2 -3 -4 -5 9 7 11 -9 10 12 5 14 3 volume 0.500 70 | 2 2 -6 -7 8 -10 -12 -11 -13 1 13 -14 6 4 -8 volume 0.500 71 | 72 | read 73 | 74 | // Typical evolution 75 | gogo := { g 5; r; g 5; hessian; r; g 5; hessian; hessian; } 76 | 77 | -------------------------------------------------------------------------------- /fe/fourier.cmd: -------------------------------------------------------------------------------- 1 | // fourier.cmd 2 | // Evolver command to print Fourier components for closed curve 3 | 4 | // Programmer: Ken Brakke, brakke@susqu.edu, http://www.susqu.edu/brakke 5 | 6 | // Usage: f_component(order) 7 | 8 | procedure f_component (integer f_order) 9 | // f_order is the order of Fourier components. 10 | { 11 | local e_id,first_e,v_id,newe_id; 12 | 13 | x_sin_coeff := 0.0; 14 | y_sin_coeff := 0.0; 15 | z_sin_coeff := 0.0; 16 | x_cos_coeff := 0.0; 17 | y_cos_coeff := 0.0; 18 | z_cos_coeff := 0.0; 19 | ecount := 0; 20 | // get starting edge, since can't assume edge[1] exists 21 | foreach edge do e_id := id; 22 | first_e := e_id; 23 | v_id := edge[e_id].vertex[1].id; 24 | // follow connected edges 25 | do { 26 | local ss,cc,newv_id; 27 | ss := sin(f_order*ecount*2*pi/edge_count)*2/edge_count; 28 | x_sin_coeff := x_sin_coeff + vertex[v_id].x*ss; 29 | y_sin_coeff := y_sin_coeff + vertex[v_id].y*ss; 30 | z_sin_coeff := z_sin_coeff + vertex[v_id].z*ss; 31 | cc := cos(f_order*ecount*2*pi/edge_count)*2/edge_count; 32 | x_cos_coeff := x_cos_coeff + vertex[v_id].x*cc; 33 | y_cos_coeff := y_cos_coeff + vertex[v_id].y*cc; 34 | z_cos_coeff := z_cos_coeff + vertex[v_id].z*cc; 35 | foreach edge[e_id].vertex vv do 36 | { if ( vv.id != v_id ) then 37 | { newv_id := vv.id; 38 | foreach vv.edge ee do 39 | if ee.id != e_id then newe_id := ee.id 40 | } 41 | }; 42 | e_id := newe_id; v_id := newv_id; 43 | ecount := ecount + 1; 44 | } while ( (e_id != first_e) and (ecount <= edge_count) ); 45 | printf "Order %g x y z \n",f_order; 46 | printf "sin: %20.15f %20.15f %20.15f\n",x_sin_coeff,y_sin_coeff,z_sin_coeff; 47 | printf "cos: %20.15f %20.15f %20.15f\n",x_cos_coeff,y_cos_coeff,z_cos_coeff; 48 | } 49 | -------------------------------------------------------------------------------- /fe/symtest.fe: -------------------------------------------------------------------------------- 1 | // symtest.fe 2 | // test of quotient space mechanism 3 | // same surface as in twointor.fe 4 | 5 | // Two Kelvin tetrakaidecahedra in a torus. 6 | 7 | SYMMETRY_GROUP "torus" // same name as in quotient.c 8 | 9 | vertices 10 | 1 0.50 0.00 0.75 11 | 2 0.25 0.00 0.50 12 | 3 0.00 0.25 0.50 13 | 4 0.75 0.00 0.50 14 | 5 0.00 0.50 0.75 15 | 6 0.50 0.00 0.25 16 | 7 0.00 0.75 0.50 17 | 8 0.50 0.25 0.00 18 | 9 0.25 0.50 0.00 19 | 10 0.00 0.50 0.25 20 | 11 0.50 0.75 0.00 21 | 12 0.75 0.50 0.00 22 | 23 | // wrap codes for group elements using scheme in quotient.c 24 | #define XWRAP 1 25 | #define XWRAPNEG 31 26 | #define YWRAP 64 27 | #define YWRAPNEG 31*64 28 | #define ZWRAP 64*64 29 | #define ZWRAPNEG 31*64*64 30 | edges /* with torus wrap symbols */ 31 | 1 1 2 32 | 2 2 3 33 | 3 1 4 34 | 4 3 5 35 | 5 2 6 36 | 6 2 7 wrap YWRAPNEG 37 | 7 1 8 wrap ZWRAP 38 | 8 4 6 39 | 9 5 9 wrap ZWRAP 40 | 10 3 10 41 | 11 3 4 wrap XWRAPNEG 42 | 12 6 8 43 | 13 6 11 wrap YWRAPNEG 44 | 14 7 4 wrap XWRAPNEG+YWRAP 45 | 15 8 12 46 | 16 9 8 47 | 17 9 11 48 | 18 10 7 49 | 19 11 1 wrap YWRAP+ZWRAPNEG 50 | 20 12 5 wrap XWRAP+ZWRAPNEG 51 | 21 5 7 52 | 22 11 12 53 | 23 10 12 wrap XWRAPNEG 54 | 24 9 10 55 | 56 | faces 57 | 1 1 2 4 9 16 -7 58 | 2 -2 5 12 -16 24 -10 59 | 3 -4 10 18 -21 60 | 4 7 15 20 -4 11 -3 61 | 5 -1 3 8 -5 62 | 6 6 14 -11 -2 63 | 7 5 13 -17 24 18 -6 64 | 8 -12 13 19 7 65 | 9 -16 17 22 -15 66 | 10 -10 11 8 12 15 -23 67 | 11 -21 9 17 19 1 6 68 | 12 -14 -18 23 -22 -13 -8 69 | 13 -24 -9 -20 -23 70 | 14 -19 22 20 21 14 -3 71 | 72 | bodies 73 | 1 -1 -2 -3 -4 -5 9 7 11 -9 10 12 5 14 3 // volume 0.500 74 | 2 2 -6 -7 8 -10 -12 -11 -13 1 13 -14 6 4 -8 // volume 0.500 75 | 76 | -------------------------------------------------------------------------------- /fe/gaussequi.cmd: -------------------------------------------------------------------------------- 1 | // gaussequi.cmd 2 | 3 | // Equiangulation using Gauss map for swap criterion. 4 | // But has problems; can produce zero area facets. Also, swapping an 5 | // edge changes the Gauss map, so maybe things don't improve. 6 | 7 | // Programmer: Ken Brakke, brakke@susqu.edu, http://www.susqu.edu/brakke 8 | 9 | // Usage: gaussequi 10 | 11 | gaussequi := { 12 | local ax,ay,az,bx,by,bz,ffnum,cx,cy,cz,dx,dy,dz,aa,bb,cc,dd,ee; 13 | swapcount := 0; 14 | foreach edge eee where not fixed and valence == 2 do 15 | { ax := eee.vertex[1].vertexnormal[1]; 16 | ay := eee.vertex[1].vertexnormal[2]; 17 | az := eee.vertex[1].vertexnormal[3]; 18 | bx := eee.vertex[2].vertexnormal[1]; 19 | by := eee.vertex[2].vertexnormal[2]; 20 | bz := eee.vertex[2].vertexnormal[3]; 21 | ffnum := eee.facet[1].id; 22 | foreach facet[ffnum].vertex vv do 23 | { if vv.id != eee.vertex[1].id and vv.id != eee.vertex[2].id then 24 | { vvnum := vv.id; break; } 25 | }; 26 | cx := vertex[vvnum].vertexnormal[1]; 27 | cy := vertex[vvnum].vertexnormal[2]; 28 | cz := vertex[vvnum].vertexnormal[3]; 29 | ffnum := eee.facet[2].id; 30 | foreach facet[ffnum].vertex vv do 31 | { if vv.id != eee.vertex[1].id and vv.id != eee.vertex[2].id then 32 | { vvnum := vv.id; break; } 33 | }; 34 | dx := vertex[vvnum].vertexnormal[1]; 35 | dy := vertex[vvnum].vertexnormal[2]; 36 | dz := vertex[vvnum].vertexnormal[3]; 37 | 38 | aa := (ax-bx)^2+(ay-by)^2+(az-bz)^2; 39 | bb := (ax-cx)^2+(ay-cy)^2+(az-cz)^2; 40 | cc := (bx-cx)^2+(by-cy)^2+(bz-cz)^2; 41 | dd := (ax-dx)^2+(ay-dy)^2+(az-dz)^2; 42 | ee := (bx-dx)^2+(by-dy)^2+(bz-dz)^2; 43 | 44 | if ( (bb+cc-aa)*sqrt(dd*ee) + (dd+ee-aa)*sqrt(bb*cc) < 0 ) then 45 | { edgeswap eee; 46 | swapcount += 1; 47 | }; 48 | }; 49 | printf "Edges gaussequi swapped: %d\n",swapcount; 50 | } 51 | 52 | -------------------------------------------------------------------------------- /src/mvgraph.c: -------------------------------------------------------------------------------- 1 | /************************************************************* 2 | * This file is part of the Surface Evolver source code. * 3 | * Programmer: Ken Brakke, brakke@susqu.edu * 4 | *************************************************************/ 5 | 6 | 7 | /********************************************************** 8 | * 9 | * File: MVgraph.c 10 | * 11 | * Contents: Routines for interface with shared memory 12 | * MinneView. 13 | */ 14 | 15 | #include "include.h" 16 | 17 | 18 | #ifndef OOGL 19 | void Begin_OOGL() 20 | { 21 | kb_error(1251,"This Evolver not compiled with the OOGL option.\n",WARNING); 22 | } 23 | 24 | void UpdateOOGL() 25 | { 26 | } 27 | 28 | void End_OOGL() 29 | { 30 | } 31 | 32 | #else 33 | 34 | void Begin_OOGL() {} 35 | 36 | void End_OOGL() 37 | { 38 | OOGL_flag = 0; 39 | if ( geomview_flag ) End_geomview(); 40 | } 41 | 42 | void UpdateOOGL() 43 | { 44 | void (*old_start)ARGS((void)); 45 | void (*old_end)ARGS((void)); 46 | void (*old_gedge)ARGS((struct graphdata *,edge_id)); 47 | void (*old_gfacet)ARGS((struct graphdata*,facet_id)); 48 | 49 | /* if user has asked us to quit, don't bother redisplaying */ 50 | /* (especially since graphgen resets breakflag!) */ 51 | if (breakflag) return; 52 | 53 | /* save current screen graphics pointers */ 54 | old_start = graph_start; 55 | old_end = graph_end; 56 | old_gfacet = graph_facet; 57 | old_gedge = graph_edge; 58 | 59 | /* OOGL pointers */ 60 | if ( geomview_flag ) 61 | { 62 | graph_start = geomview_start; 63 | graph_facet = geomview_facet; 64 | graph_edge = geomview_edge; 65 | graph_end = geomview_end; 66 | } 67 | 68 | /* do output */ 69 | graphgen(); 70 | 71 | /* restore old graphics */ 72 | graph_start = old_start; 73 | graph_end = old_end; 74 | graph_edge = old_gedge; 75 | graph_facet = old_gfacet; 76 | 77 | } 78 | #endif 79 | 80 | -------------------------------------------------------------------------------- /fe/slidestr.fe: -------------------------------------------------------------------------------- 1 | // slidestr.fe 2 | 3 | // Evolver data for drop of prescribed volume sitting 4 | // on hyperbolic slide with gravity. Illustrates corner 5 | // holding drop against gravity. 6 | 7 | // Instructions for simple use: 8 | // refine once 9 | // iterate until drop settles into curve (datafile starts with 10 | // gravity = 1 to pull drop down) 11 | // Use `G' command to reverse gravity. Blob is stable up to 12 | // about G = -.8 13 | // 14 | // You can color the blob edges with 15 | // set edge color white where not fixed 16 | 17 | STRING // one-dimensional surface 18 | space_dimension 2 19 | 20 | // Constraint of form m*x + x*y = k with m = 0.5, k = 0.1 21 | // Integrals are used for volume, since zero density facets 22 | // don't move, and their stretching around the curve gives 23 | // an inaccurate volume. 24 | 25 | PARAMETER STEEP = 0.5 26 | PARAMETER SHARP = 0.1 27 | 28 | constraint 1 // the slide, constants are steepness and sharpness 29 | formula: STEEP*x + x*y = SHARP 30 | content: 31 | c1: log(x)*SHARP - STEEP*x // note this is indefinite integral of y 32 | 33 | 34 | constraint 2 // the slide, for display 35 | formula: STEEP*x + x*y = SHARP 36 | 37 | vertices 38 | 1 0.0 2.2 constraint 1 39 | 2 0.0 0.8 constraint 1 40 | 3 0.5 2.2 41 | 4 0.5 0.8 42 | 5 0.0 2.5 constraint 2 fixed // for slide display 43 | 6 0.3 0.2 constraint 2 fixed // for slide display 44 | 7 1.5 .0 constraint 2 fixed // for slide display 45 | 46 | edges /* given by endpoints and attribute */ 47 | 1 2 4 48 | 2 4 3 49 | 3 3 1 50 | 4 5 6 fixed constraint 2 // for slide display 51 | 5 6 7 fixed constraint 2 // for slide display 52 | 53 | faces /* given by oriented edge loop */ 54 | 1 1 2 3 55 | 56 | 57 | bodies /* one body, defined by its oriented faces */ 58 | 1 1 volume 0.7 density 1.0 59 | 60 | read 61 | 62 | // Typical evolution, doing V's to keep vertices spread. 63 | gogo := { r; {g 10; V;} 40 } 64 | -------------------------------------------------------------------------------- /fe/slice.cmd: -------------------------------------------------------------------------------- 1 | // slice.cmd --- Calculate length of intersection of plane with surface. 2 | // Does not modify surface. 3 | // plane eq: aa*x + bb*y + cc*z = dd 4 | // output: prints length of slice, and area inside slice. 5 | // Note all area inside slice is counted as positive! 6 | // Try not to slice exactly through vertices!! 7 | 8 | // Programmer: Ken Brakke, brakke@susqu.edu, http://www.susqu.edu/brakke 9 | 10 | // Usage: Set plane coefficients, then do "slice". 11 | // Results: Intersection length printed out, left in variable lensum. 12 | 13 | aa := 0; bb := 0; cc := 1; dd := .1; // set these for desired plane 14 | slice := { 15 | local any,xx1,yy1,zz1,xx2,yy2,zz2; 16 | local denom,lambda,zaa,zbb,darea; 17 | local xa,ya,za,xb,yb,zb; 18 | 19 | lensum := 0; areasum := 0; 20 | foreach facet ff do 21 | { any := 0; 22 | foreach ff.edge ee do 23 | { 24 | xx1 := ee.vertex[1].x; 25 | yy1 := ee.vertex[1].y; 26 | zz1 := ee.vertex[1].z; 27 | xx2 := ee.vertex[2].x; 28 | yy2 := ee.vertex[2].y; 29 | zz2 := ee.vertex[2].z; 30 | denom := aa*(xx1-xx2)+bb*(yy1-yy2)+cc*(zz1-zz2); 31 | if ( denom != 0.0 ) then 32 | { 33 | lambda := (dd-aa*xx2-bb*yy2-cc*zz2)/denom; 34 | if ( (lambda >= 0) and (lambda <= 1) ) then 35 | { 36 | xa := xb; ya := yb; za := zb; 37 | xb := lambda*xx1+(1-lambda)*xx2; 38 | yb := lambda*yy1+(1-lambda)*yy2; 39 | zb := lambda*zz1+(1-lambda)*zz2; 40 | any := any+1; 41 | } 42 | } 43 | } ; 44 | if any == 2 then 45 | { 46 | dx := xa-xb; dy := ya-yb; dz := za - zb; 47 | lensum := lensum + sqrt(dx^2+dy^2+dz^2); 48 | zaa := za - dd/cc; zbb := zb - dd/cc; 49 | darea := sqrt((ya*zbb-yb*zaa)^2+(zaa*xb-zbb*xa)^2+(xa*yb-ya*xb)^2); 50 | areasum := areasum + darea/2; 51 | } 52 | }; 53 | printf "Circumference: %18.15g Area: %18.15g\n",lensum,areasum; 54 | } // end slice 55 | 56 | -------------------------------------------------------------------------------- /doc/news_19.htm: -------------------------------------------------------------------------------- 1 | 2 | Surface Evolver Documentation - Newsletter 18 3 | 4 | 5 | 6 |

Surface Evolver Newsletter no. 19

7 | Back to top of Surface Evolver documentation. 8 |
 9 | 
10 | 
11 |                        Surface Evolver Newsletter 19
12 |                             August 20, 2005
13 | 
14 |                       by Ken Brakke, brakke@susqu.edu
15 | 
16 | 
17 |   Surface Evolver version 2.26 is now available at
18 |   http://www.susqu.edu/brakke/evolver/evolver.htm.
19 |   This is the first full official new version release since
20 |   version 2.24 in October, 2004.
21 | 
22 |   Announcement of interest to fans of Joseph Plateau:
23 |   In my spare time, I have been doing an amateur translation of
24 |   Plateau's famous 1873 book on soap films and surface tension
25 |   phenomena.  You may find the results at 
26 |   http://www.susqu.edu/brakke/PlateauBook/PlateauBook.html.
27 | 
28 |   New features and changes:
29 | 
30 |   PDF version of the manual has been improved, with bookmarks and links.
31 | 
32 |   Runtime help command now finds its keyword information from a new
33 |   separate help text file, rather than extracting it from the HTML
34 |   version of the documentation.
35 | 
36 |   Added "quietload" toggle to supress echoing of command files being
37 |   read in; also corresponding "-Q" command line option.
38 | 
39 |   Quoted strings can be concatenated on input, for example,
40 |      printf "This is a " "long format string.\n"
41 | 
42 |   New "reverse_orientation" command to internally reverse the orientation
43 |   of selected edges and facets.
44 | 
45 |   Added "eigenvalues" array, so user can access all eigenvalues
46 |   produced by "ritz", e.g. "print eigenvalues[2]".
47 | 
48 |   Added "binary_printf" command to write binary files for external
49 |   applications needing a binary format.
50 | 
51 |   Piping of command output with | to external commands now works in
52 |   Windows like it does in unix.
53 | 
54 | 
55 | End of Newsletter 19
56 | 
57 | 
58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /fe/rewrap.cmd: -------------------------------------------------------------------------------- 1 | // rewrap.cmd 2 | 3 | // Commands to rewrap torus vertices and edges to get them nicely 4 | // within unit cell. This version does 3D; for 2D see rewrap2.cmd. 5 | // Moves vertices at most one period at a time, so you may have to 6 | // repeat if things are very bad to start with. 7 | 8 | // Uses torus wrap representation and wrap_vertex builtin command. 9 | 10 | // Usage: rewrap 11 | 12 | // Programmer: Ken Brakke, brakke@susqu.edu, http://www.susqu.edu/brakke 13 | 14 | rewrap := { 15 | if space_dimension != 3 then 16 | { errprintf"rewrap is for space dimension 3; for 2D use rewrap2.cmd.\n"; 17 | return; 18 | }; 19 | define body attribute old_volume real; // so can adjust volconst 20 | set body old_volume volume; 21 | foreach vertex vv where vv.x*inverse_periods[1][1]+vv.y*inverse_periods[1][2] 22 | + vv.z*inverse_periods[1][3] < 0 do wrap_vertex(vv.id,1); 23 | foreach vertex vv where vv.x*inverse_periods[1][1]+vv.y*inverse_periods[1][2] 24 | + vv.z*inverse_periods[1][3] >= 1 do wrap_vertex(vv.id,31); 25 | foreach vertex vv where vv.x*inverse_periods[2][1]+vv.y*inverse_periods[2][2] 26 | + vv.z*inverse_periods[2][3] < 0 do wrap_vertex(vv.id,64); 27 | foreach vertex vv where vv.x*inverse_periods[2][1]+vv.y*inverse_periods[2][2] 28 | + vv.z*inverse_periods[2][3] >= 1 do wrap_vertex(vv.id,1984); 29 | foreach vertex vv where vv.x*inverse_periods[3][1]+vv.y*inverse_periods[3][2] 30 | + vv.z*inverse_periods[3][3] < 0 do wrap_vertex(vv.id,4096); 31 | foreach vertex vv where vv.x*inverse_periods[3][1]+vv.y*inverse_periods[3][2] 32 | + vv.z*inverse_periods[3][3] >= 1 do wrap_vertex(vv.id,126976); 33 | recalc; 34 | // Adjust volconst 35 | local torvol; 36 | torvol := abs((torus_periods[1][1]*torus_periods[2][2] 37 | - torus_periods[1][2]*torus_periods[2][1])*torus_periods[3][3] 38 | + (torus_periods[1][2]*torus_periods[2][3] 39 | - torus_periods[1][3]*torus_periods[2][2])*torus_periods[3][1] 40 | + (torus_periods[1][3]*torus_periods[2][1] 41 | - torus_periods[1][1]*torus_periods[2][3])*torus_periods[3][2]); 42 | set body volconst floor((old_volume - volume - volconst)/torvol+.5)*torvol; 43 | 44 | } 45 | 46 | -------------------------------------------------------------------------------- /fe/intersec.cmd: -------------------------------------------------------------------------------- 1 | // intersec.cmd 2 | // Evolver command to detect intersection of linear edges and facets. 3 | // For each facet, finds if any edge intersects in interior. 4 | // Usage: read "intersec.cmd" 5 | // detect 6 | // Output: prints ids of facets and edges that intersect. 7 | // Notes: In quadratic model, treats edges and facets as simply linear. 8 | // Will not work in Lagrange model. 9 | 10 | eps := 1e-10 // tolerance for being equal to zero 11 | detect := { 12 | local ax,ay,az,bx,by,bz,cx,cy,cz,acx,bcx,px,py,pz,qx,qy,qz,qpx,qcx; 13 | local denom,lambda,mu,sigma; 14 | local acy,acz,bcy,bcz,qpy,qpz,qcy,qcz; 15 | 16 | if lagrange then 17 | { printf "intersect.cmd will not work in Lagrange model.\n";return;}; 18 | foreach facet ff do 19 | { ax := ff.vertex[1].x; 20 | ay := ff.vertex[1].y; 21 | az := ff.vertex[1].z; 22 | bx := ff.vertex[2].x; 23 | by := ff.vertex[2].y; 24 | bz := ff.vertex[2].z; 25 | cx := ff.vertex[3].x; 26 | cy := ff.vertex[3].y; 27 | cz := ff.vertex[3].z; 28 | acx := ax-cx; acy := ay-cy; acz := az- cz; 29 | bcx := bx-cx; bcy := by-cy; bcz := bz- cz; 30 | foreach edge ee do 31 | { px := ee.vertex[1].x; 32 | py := ee.vertex[1].y; 33 | pz := ee.vertex[1].z; 34 | qx := ee.vertex[2].x; 35 | qy := ee.vertex[2].y; 36 | qz := ee.vertex[2].z; 37 | qpx := qx-px; qpy := qy-py; qpz := qz-pz; 38 | qcx := qx-cx; qcy := qy-cy; qcz := qz-cz; 39 | denom := qpx*(acy*bcz-acz*bcy) - qpy*(acx*bcz-acz*bcx) 40 | + qpz*(acx*bcy-acy*bcx); 41 | if ( abs(denom) < eps ) then continue; 42 | lambda := (qpx*(qcy*bcz-qcz*bcy) - qpy*(qcx*bcz-qcz*bcx) 43 | + qpz*(qcx*bcy-qcy*bcx))/denom; 44 | if ( lambda <= eps ) then continue; 45 | mu := (qpx*(acy*qcz-acz*qcy) - qpy*(acx*qcz-acz*qcx) 46 | + qpz*(acx*qcy-acy*qcx))/denom; 47 | if ( mu <= eps ) then continue; 48 | if ( lambda + mu > 1-eps ) then continue; 49 | sigma := (qcx*(acy*bcz-acz*bcy) - qcy*(acx*bcz-acz*bcx) 50 | + qcz*(acx*bcy-acy*bcx))/denom; 51 | if ( (sigma <= eps) or (sigma > 1-eps) ) then continue; 52 | 53 | // now have intersection 54 | printf "Facet %g and edge %g intersect.\n",ff.id,ee.id; 55 | } 56 | 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /fe/mound.fe: -------------------------------------------------------------------------------- 1 | // mound.fe 2 | // Evolver data for drop of prescribed volume sitting on plane with gravity. 3 | // Contact angle with plane can be varied. 4 | 5 | PARAMETER angle = 90 // interior angle between plane and surface, degrees 6 | 7 | gravity_constant 0 // start with gravity off 8 | 9 | #define WALLT (-cos(angle*pi/180)) // virtual tension of facet on plane 10 | 11 | constraint 1 /* the table top */ 12 | formula: x3 = 0 13 | energy: // for contact angle 14 | e1: -(WALLT*y) 15 | e2: 0 16 | e3: 0 17 | 18 | vertices 19 | 1 0.0 0.0 0.0 constraint 1 /* 4 vertices on plane */ 20 | 2 1.0 0.0 0.0 constraint 1 21 | 3 1.0 1.0 0.0 constraint 1 22 | 4 0.0 1.0 0.0 constraint 1 23 | 5 0.0 0.0 1.0 24 | 6 1.0 0.0 1.0 25 | 7 1.0 1.0 1.0 26 | 8 0.0 1.0 1.0 27 | 9 2.0 2.0 0.0 fixed /* for table top */ 28 | 10 2.0 -1.0 0.0 fixed 29 | 11 -1.0 -1.0 0.0 fixed 30 | 12 -1.0 2.0 0.0 fixed 31 | 32 | edges /* given by endpoints and attribute */ 33 | 1 1 2 constraint 1 /* 4 edges on plane */ 34 | 2 2 3 constraint 1 35 | 3 3 4 constraint 1 36 | 4 4 1 constraint 1 37 | 5 5 6 38 | 6 6 7 39 | 7 7 8 40 | 8 8 5 41 | 9 1 5 42 | 10 2 6 43 | 11 3 7 44 | 12 4 8 45 | 13 9 10 no_refine fixed /* for table top */ 46 | 14 10 11 no_refine fixed 47 | 15 11 12 no_refine fixed 48 | 16 12 9 no_refine fixed 49 | 50 | faces /* given by oriented edge loop */ 51 | 1 1 10 -5 -9 52 | 2 2 11 -6 -10 53 | 3 3 12 -7 -11 54 | 4 4 9 -8 -12 55 | 5 5 6 7 8 56 | 7 13 14 15 16 no_refine density 0 fixed /* table top for display */ 57 | 58 | bodies /* one body, defined by its oriented faces */ 59 | 1 1 2 3 4 5 volume 1 density 1 60 | 61 | read 62 | re := {refine edges where on_constraint 1 } 63 | 64 | // Typical evolution 65 | gogo := { re; g 5; r; g 5; r; g 5; hessian; hessian; } 66 | 67 | 68 | // Evolution with 45 degree contact angle 69 | gogo2 := { angle := 45; re; g 5; V;V; r; g 5; V;V; r; g 5; hessian; hessian; } 70 | 71 | // Evolution with 90 contact and high gravity 72 | gogo3 := { angle := 90; G 5; re; g 5; r; g 5; r; g 5; hessian; hessian; } 73 | 74 | // Evolution with 90 contact and negative gravity, i.e. pendant drop 75 | gogo4 := { angle := 90; G -2; re; g 5; r; g 5; r; g 5; hessian; hessian; } 76 | 77 | // Pendant drop falling off ceiling 78 | gogo5 := { angle := 90; G -5; re; g 10; t .1; unset vertex constraint 1; g 3; } 79 | 80 | -------------------------------------------------------------------------------- /src/model.h: -------------------------------------------------------------------------------- 1 | /************************************************************* 2 | * This file is part of the Surface Evolver source code. * 3 | * Programmer: Ken Brakke, brakke@susqu.edu * 4 | *************************************************************/ 5 | 6 | 7 | /********************************************************************** 8 | * 9 | * File: model.h 10 | * 11 | * Header file for evolver. Defines model parameters, i.e. 12 | * for torus model, lagrange model, space dimension. 13 | * 14 | */ 15 | 16 | #ifdef SDIM 17 | #define DEFAULT_SDIM SDIM 18 | #ifndef MAXCOORD 19 | #define MAXCOORD SDIM 20 | #endif 21 | #if SDIM==2 22 | #define SDIM_dot(x,y) ((x)[0]*(y)[0] + (x)[1]*(y)[1]) 23 | #else 24 | #if SDIM==3 25 | #define SDIM_dot(x,y) ((x)[0]*(y)[0] + (x)[1]*(y)[1] + (x)[2]*(y)[2]) 26 | #else 27 | #define SDIM_dot(x,y) dot(x,y,SDIM) 28 | #endif 29 | #endif 30 | #else 31 | #define SDIM web.sdim 32 | #define SDIM_dot(x,y) dot(x,y,SDIM) 33 | #define DEFAULT_SDIM 3 34 | #endif 35 | 36 | /* maximum number of shared memory processors */ 37 | #ifdef SHARED_MEMORY 38 | #ifndef MAXPROCS 39 | #define MAXPROCS 4 40 | #endif 41 | #else 42 | #define MAXPROCS 1 43 | #endif 44 | 45 | /* maximum dimensionality */ 46 | #ifndef MAXCOORD 47 | #define MAXCOORD 4 48 | #endif 49 | 50 | /* MAXPARAM is maximum number of boundary parameters. Must be 51 | at most MAXCOORD since is saved in same space by save_coord(). */ 52 | #define MAXPARAM MAXCOORD 53 | #define EDGE_VERTS 2 54 | #define FACET_VERTS 3 55 | #define FACET_EDGES 3 56 | 57 | /* model types for web.modeltype */ 58 | #define LINEAR 1 59 | #define QUADRATIC 2 60 | #define LAGRANGE 3 61 | 62 | /* Quadratic model point counts */ 63 | /* Control points per edge */ 64 | #define EDGE_CTRL 3 65 | /* Control points per facet */ 66 | #define FACET_CTRL 6 67 | /* Integration points per edge */ 68 | #define EDGE_INTERP 3 69 | /* Integration points per facet */ 70 | #define FACET_INTERP 7 71 | 72 | /* quadratic interpolation coefficients */ 73 | /* partials of interpolation polynomials at midpoints of patch edges */ 74 | /* control points are numbered 0 to 5 counterclockwise */ 75 | /* midpoints are numbered 0 to 2 counterclockwise after control pt 0 */ 76 | /* dip[midpoint][control point][partial] */ 77 | 78 | extern REAL dip[3][FACET_CTRL][2]; 79 | 80 | /* Histogram size */ 81 | #define HISTO_BINS 40 82 | #define HISTO_BINSIZE (1/M_LN2) 83 | -------------------------------------------------------------------------------- /fe/qmound.fe: -------------------------------------------------------------------------------- 1 | // qmound.fe 2 | 3 | // Evolver data for drop of prescribed volume sitting on plane with gravity. 4 | // Contact angle with plane can be varied. 5 | // Volume constraint implemented as quantity constraint 6 | 7 | PARAMETER angle = 90 // interior angle between plane and surface, degrees 8 | 9 | #define T (-cos(angle*pi/180)) // virtual tension of facet on plane 10 | 11 | quantity vol fixed = 1 method facet_vector_integral global // is volume 12 | vector_integrand: 13 | q1: 0 14 | q2: 0 15 | q3: z 16 | 17 | constraint 1 /* the table top */ 18 | formula: x3 = 0 19 | energy: // for contact angle 20 | e1: -T*y 21 | e2: 0 22 | e3: 0 23 | 24 | vertices 25 | 1 0.0 0.0 0.0 constraint 1 /* 4 vertices on plane */ 26 | 2 1.0 0.0 0.0 constraint 1 27 | 3 1.0 1.0 0.0 constraint 1 28 | 4 0.0 1.0 0.0 constraint 1 29 | 5 0.0 0.0 1.0 30 | 6 1.0 0.0 1.0 31 | 7 1.0 1.0 1.0 32 | 8 0.0 1.0 1.0 33 | 9 2.0 2.0 0.0 fixed /* for table top */ 34 | 10 2.0 -1.0 0.0 fixed 35 | 11 -1.0 -1.0 0.0 fixed 36 | 12 -1.0 2.0 0.0 fixed 37 | 38 | edges /* given by endpoints and attribute */ 39 | 1 1 2 constraint 1 /* 4 edges on plane */ 40 | 2 2 3 constraint 1 41 | 3 3 4 constraint 1 42 | 4 4 1 constraint 1 43 | 5 5 6 44 | 6 6 7 45 | 7 7 8 46 | 8 8 5 47 | 9 1 5 48 | 10 2 6 49 | 11 3 7 50 | 12 4 8 51 | 13 9 10 fixed /* for table top */ 52 | 14 10 11 fixed 53 | 15 11 12 fixed 54 | 16 12 9 fixed 55 | 56 | faces /* given by oriented edge loop */ 57 | 1 1 10 -5 -9 58 | 2 2 11 -6 -10 59 | 3 3 12 -7 -11 60 | 4 4 9 -8 -12 61 | 5 5 6 7 8 62 | 7 13 14 15 16 density 0 fixed /* table top for display */ 63 | 64 | bodies /* one body, defined by its oriented faces */ 65 | 1 1 2 3 4 5 density 1 66 | 67 | read 68 | re := {refine edges where on_constraint 1 } 69 | 70 | // Typical evolution 71 | gogo := { re; g 5; r; g 5; r; g 5; hessian; hessian; } 72 | 73 | 74 | // Evolution with 45 degree contact angle 75 | gogo2 := { angle := 45; re; g 5; V;V; r; g 5; V;V; r; g 5; hessian; hessian; } 76 | 77 | // Evolution with 90 contact and high gravity 78 | gogo3 := { angle := 90; G 5; re; g 5; r; g 5; r; g 5; hessian; hessian; } 79 | 80 | // Evolution with 90 contact and negative gravity, i.e. pendant drop 81 | gogo4 := { angle := 90; G -2; re; g 5; r; g 5; r; g 5; hessian; hessian; } 82 | 83 | // Pendant drop falling off ceiling 84 | gogo5 := { angle := 90; G -5; re; g 10; t .1; unset vertex constraint 1; g 3; } 85 | 86 | -------------------------------------------------------------------------------- /fe/slice2.cmd: -------------------------------------------------------------------------------- 1 | // slice2.cmd --- produce intersection of surface with plane 2 | // plane eq: aa*x + bb*y + cc*z = dd 3 | // output: length of slice, and area inside slice. 4 | // Does not modify surface. 5 | // Note all area inside slice is counted as positive! 6 | // Do not to slice exactly through vertices!! Avoid special 7 | // values for dd like 0 or .5! 8 | 9 | // Fixed to do oriented facets of a particular body. 10 | 11 | // Usage: set plane coefficients, then do slice2(body number). 12 | // Results: Intersection length printed out, left in variable lensum. 13 | 14 | // Programmer: Ken Brakke, brakke@susqu.edu, http://www.susqu.edu/brakke 15 | 16 | procedure slice2(integer body_num) := { 17 | local any,xx1,yy1,zz1,xx2,yy2,zz2; 18 | local denom,lambda,zaa,zbb,darea; 19 | lensum := 0; areasum := 0; 20 | 21 | xb := 0; yb := 0; zb := 0; // just for declaration before use. 22 | foreach body[body_num].facet ff do 23 | { any := 0; 24 | foreach ff.edge ee do 25 | { 26 | xx1 := ee.vertex[1].x; 27 | yy1 := ee.vertex[1].y; 28 | zz1 := ee.vertex[1].z; 29 | xx2 := ee.vertex[2].x; 30 | yy2 := ee.vertex[2].y; 31 | zz2 := ee.vertex[2].z; 32 | denom := aa*(xx1-xx2)+bb*(yy1-yy2)+cc*(zz1-zz2); 33 | if ( denom != 0.0 ) then 34 | { 35 | lambda := (dd-aa*xx2-bb*yy2-cc*zz2)/denom; 36 | if ( (lambda >= 0) and (lambda <= 1) ) then 37 | { 38 | xa := xb; ya := yb; za := zb; 39 | xb := lambda*xx1+(1-lambda)*xx2; 40 | yb := lambda*yy1+(1-lambda)*yy2; 41 | zb := lambda*zz1+(1-lambda)*zz2; 42 | any := any+1; 43 | } 44 | } 45 | } ; 46 | if any == 2 then 47 | { 48 | local triple; 49 | dx := xa-xb; dy := ya-yb; dz := za - zb; 50 | lensum := lensum + sqrt(dx^2+dy^2+dz^2); 51 | zaa := za - dd/cc; zbb := zb - dd/cc; 52 | fx := ff.x; fy := ff.y; fz := ff.z; 53 | triple := fx*(dy*cc-dz*bb)+fy*(dz*aa-dx*cc)+fz*(dx*bb-dy*aa); 54 | 55 | darea := (xa*yb-xb*ya)/2; 56 | if ( triple > 0 ) then areasum := areasum + darea 57 | else areasum := areasum - darea; 58 | } 59 | }; 60 | areasum := areasum*sqrt(aa*aa+bb*bb+cc*cc)/cc; 61 | printf "Circumference: %18.15g Area: %18.15g\n",lensum,areasum; 62 | } // end slice 63 | 64 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | find_package (OpenGL) 2 | find_package (GLUT) 3 | find_package (Threads) 4 | find_package (Metis) 5 | 6 | set (targetName evolver) 7 | 8 | include_directories ( 9 | ${CMAKE_CURRENT_SOURCE_DIR} 10 | ${GLUT_INCLUDE_DIR} 11 | ${OPENGL_INCLUDE_DIR} 12 | ) 13 | 14 | if (APPLE) 15 | add_definitions(-DLINUX -DPTHREADS -DOOGL -DMAC_OS_X) 16 | endif (APPLE) 17 | 18 | if (CYGWIN) 19 | add_definitions(-DLINUX -DOOGL -DPTHREADS) 20 | endif(CYGWIN) 21 | 22 | if (UNIX) 23 | add_definitions(-DLINUX -DOOGL -DPTHREADS) 24 | endif (UNIX) 25 | 26 | add_executable (evolver 27 | alice.c 28 | alloca.c 29 | bk.c 30 | boundary.c 31 | calcforc.c 32 | check.c 33 | cnstrnt.c 34 | command.c 35 | curtest.c 36 | diffuse.c 37 | display.c 38 | dodecGroup.c 39 | dump.c 40 | eval_all.c 41 | eval_sec.c 42 | evalmore.c 43 | evaltree.c 44 | exprint.c 45 | filgraph.c 46 | filml.c 47 | filmq.c 48 | fixvol.c 49 | gauss.c 50 | geomgraph.c 51 | glutgraph.c 52 | grapher.c 53 | graphgen.c 54 | help.c 55 | hessian.c 56 | hessian2.c 57 | hessian3.c 58 | hidim.c 59 | iterate.c 60 | khyp.c 61 | klein.c 62 | knot1.c 63 | knot2.c 64 | knot3.c 65 | kusner.c 66 | lagrange.c 67 | lexinit.c 68 | lexinit2.c 69 | lexyy.c 70 | machine.c 71 | matrix.c 72 | meanint.c 73 | method1.c 74 | method2.c 75 | method3.c 76 | method4.c 77 | method5.c 78 | metis.c 79 | metric.c 80 | mindeg.c 81 | model.c 82 | modify.c 83 | mvgraph.c 84 | odrv.c 85 | painter.c 86 | pixgraph.c 87 | popfilm.c 88 | psgraph.c 89 | quantity.c 90 | query.c 91 | quotient.c 92 | readline.c 93 | registry.c 94 | sdrv.c 95 | simequi2.c 96 | simplex.c 97 | skeleton.c 98 | softimag.c 99 | sqcurve.c 100 | sqcurve2.c 101 | sqcurve3.c 102 | storage.c 103 | stringl.c 104 | stringq.c 105 | symtable.c 106 | teix.c 107 | tmain.c 108 | tordup.c 109 | torus.c 110 | torvol.c 111 | trirevis.c 112 | userfunc.c 113 | userio.c 114 | utility.c 115 | variable.c 116 | veravg.c 117 | verpopst.c 118 | wulff.c 119 | yexparse.c 120 | ytab.c 121 | zoom.c 122 | ) 123 | 124 | if (METIS_FOUND) 125 | add_definitions(-DMETIS) 126 | include_directories(${METIS_INCLUDE_DIR}) 127 | endif (METIS_FOUND) 128 | 129 | target_link_libraries (evolver 130 | ${CMAKE_THREAD_LIBS_INIT} 131 | ${METIS_LIBRARIES} 132 | ${GLUT_LIBRARIES} 133 | ${OPENGL_LIBRARIES} 134 | ) 135 | -------------------------------------------------------------------------------- /fe/gaussmap.cmd: -------------------------------------------------------------------------------- 1 | // gaussmap.cmd 2 | // Converts each vertex coordinate to unit normal. 3 | // No vertices should be on constraints or fixed. 4 | // Saves original coordinates so "revert" restores original surface. 5 | // Before running "gaussmap", vertices should be freed from all 6 | // constraints and boundaries. 7 | 8 | // Programmer: Ken Brakke, brakke@susqu.edu, http://www.susqu.edu/brakke 9 | 10 | // Usage: gaussmap 11 | 12 | define vertex attribute gaussx real[3] 13 | define vertex attribute oldx real[3] 14 | gaussmap := { 15 | foreach vertex vv do 16 | { local connum; 17 | connum := 1; 18 | do { unset vv constraint connum; connum += 1; } 19 | while ( connum < 30 ); 20 | vv.oldx[1] := vv.x[1]; 21 | vv.oldx[2] := vv.x[2]; 22 | vv.oldx[3] := vv.x[3]; 23 | vv.gaussx[1] := vv.vertexnormal[1]; 24 | vv.gaussx[2] := vv.vertexnormal[2]; 25 | vv.gaussx[3] := vv.vertexnormal[3]; 26 | }; 27 | set vertex x gaussx[1]; 28 | set vertex y gaussx[2]; 29 | set vertex z gaussx[3]; 30 | } 31 | 32 | revert := { 33 | set vertex x oldx[1]; 34 | set vertex y oldx[2]; 35 | set vertex z oldx[3]; 36 | } 37 | 38 | // Command to find spherical area of gauss map, Lagrange model 39 | calc_gaussarea := { 40 | local jnx, jnxx; 41 | if quadratic then lagrange 2; 42 | gaussarea := 0; 43 | jnx := 2; 44 | jnxx := 3; 45 | foreach facet ff do 46 | { local angle_a, angle_b, angle_c; 47 | angle_a := asin(sqrt( 48 | (ff.vertex[1].vertexnormal[1]-ff.vertex[jnx].vertexnormal[1])^2 49 | +(ff.vertex[1].vertexnormal[2]-ff.vertex[jnx].vertexnormal[2])^2 50 | +(ff.vertex[1].vertexnormal[3]-ff.vertex[jnx].vertexnormal[3])^2)/2); 51 | angle_b := asin(sqrt( 52 | (ff.vertex[jnxx].vertexnormal[1]-ff.vertex[jnx].vertexnormal[1])^2 53 | +(ff.vertex[jnxx].vertexnormal[2]-ff.vertex[jnx].vertexnormal[2])^2 54 | +(ff.vertex[jnxx].vertexnormal[3]-ff.vertex[jnx].vertexnormal[3])^2)/2); 55 | angle_c := asin(sqrt( 56 | (ff.vertex[jnxx].vertexnormal[1]-ff.vertex[1].vertexnormal[1])^2 57 | +(ff.vertex[jnxx].vertexnormal[2]-ff.vertex[1].vertexnormal[2])^2 58 | +(ff.vertex[jnxx].vertexnormal[3]-ff.vertex[1].vertexnormal[3])^2)/2); 59 | gaussarea += 4*atan(sqrt(tan((angle_a+angle_b+angle_c)/2) 60 | *tan((angle_a+angle_b-angle_c)/2) 61 | *tan((angle_a-angle_b+angle_c)/2) 62 | *tan((-angle_a+angle_b+angle_c)/2))); 63 | }; 64 | printf "Gauss map area: %18.15f or %18.15f*pi\n",gaussarea,gaussarea/pi; 65 | } 66 | 67 | -------------------------------------------------------------------------------- /fe/ansurf.cmd: -------------------------------------------------------------------------------- 1 | // ansurf.cmd 2 | // Surface Evolver command to produce file of ANSYS input for 3 | // vertices, edges, and faces to produce a surface 4 | // for ANSYS meshing. Beware this is a very simple-minded 5 | // translation to ANSYS format. 6 | // Modified Feb. 2006 to not assume consecutive numbering of elements. 7 | // Programmer: Ken Brakke, brakke@susqu.edu, http://www.susqu.edu/brakke 8 | 9 | // usage: ansurf >>> "filename" 10 | 11 | // Attributes to hold ANSYS numbering of elements 12 | define vertex attribute ansurf_knumber real 13 | define edge attribute ansurf_lnumber real 14 | define facet attribute ansurf_alnumber real 15 | 16 | // vertices as ANSYS keypoints 17 | ansurf_nodes := { 18 | local knumber; 19 | knumber := 0; 20 | foreach vertex vv do 21 | { printf "k,,%20.15g,%20.15g,%20.15g\n",x,y,z; 22 | knumber += 1; 23 | vv.ansurf_knumber := knumber; 24 | } 25 | } 26 | 27 | ansurf_edges := { 28 | local lnumber; 29 | lnumber := 0; 30 | if (quadratic) then 31 | foreach edge ee do 32 | { printf "larc,%g,%g,%g\n",ee.vertex[1].ansurf_knumber, 33 | ee.vertex[2].ansurf_knumber,ee.vertex[3].ansurf_knumber; 34 | lnumber += 1; 35 | ee.ansurf_lnumber := lnumber; 36 | } 37 | else 38 | foreach edge ee do 39 | { printf "l,%g,%g\n",ee.vertex[1].ansurf_knumber, 40 | ee.vertex[2].ansurf_knumber; 41 | lnumber += 1; 42 | ee.ansurf_lnumber := lnumber; 43 | } 44 | } 45 | 46 | ansurf_faces := { 47 | local alnumber; 48 | alnumber := 0; 49 | foreach facet ff do 50 | { printf "al,%g,%g,%g\n", 51 | ff.edge[1].ansurf_lnumber,ff.edge[2].ansurf_lnumber, 52 | ff.edge[3].ansurf_lnumber; 53 | alnumber += 1; 54 | ff.ansurf_alnumber := alnumber; 55 | } 56 | } 57 | 58 | // define volumes, one per body 59 | ansurf_bodies := { foreach body bb do 60 | { // select areas 61 | local flag; 62 | flag := 0; 63 | foreach bb.facet ff do 64 | { if flag then printf "ASEL,A,AREA,,%g,%g\n",ff.ansurf_alnumber, 65 | ff.ansurf_alnumber 66 | else printf "ASEL,S,AREA,,%g,%g\n",ff.ansurf_alnumber, 67 | ff.ansurf_alnumber; 68 | flag := 1; 69 | }; 70 | printf "VA,ALL\n"; 71 | } 72 | } 73 | 74 | // define areas 75 | ansurf := { printf "/PREP7\n"; 76 | printf "/NOPR\n"; 77 | ansurf_nodes; 78 | ansurf_edges; 79 | ansurf_faces; 80 | ansurf_bodies; 81 | } 82 | 83 | // Usage: ansurf >>> "ansys_file" 84 | -------------------------------------------------------------------------------- /fe/x3d.cmd: -------------------------------------------------------------------------------- 1 | // x3d.cmd 2 | // Surface Evolver script to export surface as an X3D file for 3D viewing 3 | // in a browser. 4 | // Usage: x3d >>> "filename.x3d" 5 | 6 | // Programmer: Ken Brakke, brakke@susqu.edu, http://www.susqu.edu/brakke 7 | 8 | define rgb real[16][4]; 9 | rgb[1][1] := 0.0; rgb[1][2] := 0.0; rgb[1][3] := 0.0; 10 | rgb[2][1] := 0.0; rgb[2][2] := 0.0; rgb[2][3] := 1.; 11 | rgb[3][1] := 0.0; rgb[3][2] := 1.; rgb[3][3] := 0.0; 12 | rgb[4][1] := 0.0; rgb[4][2] := 1.; rgb[4][3] := 1.; 13 | rgb[5][1] := 1.; rgb[5][2] := 0.0; rgb[5][3] := 0.0; 14 | rgb[6][1] := 1.; rgb[6][2] := 0.0; rgb[6][3] := 1.; 15 | rgb[7][1] := 1.; rgb[7][2] := 0.5; rgb[7][3] := 0.; 16 | rgb[8][1] := .6; rgb[8][2] := .6; rgb[8][3] := .6; 17 | rgb[9][1] := .3; rgb[9][2] := .3; rgb[9][3] := .3; 18 | rgb[10][1] := .3; rgb[10][2] := .8; rgb[10][3] := 1.; 19 | rgb[11][1] := .5; rgb[11][2] := 1.; rgb[11][3] := .5; 20 | rgb[12][1] := .5; rgb[12][2] := 1.; rgb[12][3] := 1.; 21 | rgb[13][1] := 1.; rgb[13][2] := .5; rgb[13][3] := .5; 22 | rgb[14][1] := 1.; rgb[14][2] := .5; rgb[14][3] := 1; 23 | rgb[15][1] := 1.; rgb[15][2] := 1.; rgb[15][3] := .0; 24 | rgb[16][1] := 1; rgb[16][2] := 1; rgb[16][3] := 1; 25 | 26 | x3d := { 27 | printf"\n"; 28 | printf"\n"; 29 | printf "\n"; 30 | printf "
\n"; 31 | printf " \n",datafilename; 32 | printf " \n"; 33 | printf " \n"; 34 | printf "
\n"; 35 | printf " \n"; 36 | printf " \n"; 37 | foreach facet ff where color >= 0 do 38 | { printf " \n"; 39 | printf " \n"; 40 | printf " \n", rgb[ff.color+1][1], 41 | rgb[ff.color+1][2],rgb[ff.color+1][3]; 42 | printf " \n"; 43 | printf " \n"; 44 | printf " \n", 45 | ff.vertex[1].x,ff.vertex[1].y,ff.vertex[1].z, 46 | ff.vertex[2].x,ff.vertex[2].y,ff.vertex[2].z, 47 | ff.vertex[3].x,ff.vertex[3].y,ff.vertex[3].z; 48 | printf " \n"; 49 | printf " \n"; 50 | }; 51 | printf " \n"; 52 | printf " \n"; 53 | printf "
\n"; 54 | } 55 | -------------------------------------------------------------------------------- /fe/catman.fe: -------------------------------------------------------------------------------- 1 | // catman.fe 2 | // Evolver datafile for catenoid with parameters as in Manual tutorial. 3 | 4 | PARAMETER radius = 1 // ring radius; runtime adjustable 5 | PARAMETER height = 0.55 // ring height; runtime adjustable 6 | 7 | boundary 1 parameters 1 // upper ring; p1 is ring parameter 8 | x1: radius * cos(p1) 9 | x2: radius * sin(p1) 10 | x3: height 11 | 12 | boundary 2 parameters 1 // lower ring 13 | x1: radius * cos(p1) 14 | x2: radius * sin(p1) 15 | x3: -height 16 | 17 | vertices /* given by parameter value on a boundary */ 18 | 1 0*pi/3 boundary 1 fixed 19 | 2 1*pi/3 boundary 1 fixed 20 | 3 2*pi/3 boundary 1 fixed 21 | 4 3*pi/3 boundary 1 fixed 22 | 5 4*pi/3 boundary 1 fixed 23 | 6 5*pi/3 boundary 1 fixed 24 | 7 0*pi/3 boundary 2 fixed 25 | 8 1*pi/3 boundary 2 fixed 26 | 9 2*pi/3 boundary 2 fixed 27 | 10 3*pi/3 boundary 2 fixed 28 | 11 4*pi/3 boundary 2 fixed 29 | 12 5*pi/3 boundary 2 fixed 30 | 31 | edges /* given by endpoint vertices */ 32 | 1 1 2 boundary 1 fixed 33 | 2 2 3 boundary 1 fixed 34 | 3 3 4 boundary 1 fixed 35 | 4 4 5 boundary 1 fixed 36 | 5 5 6 boundary 1 fixed 37 | 6 6 1 boundary 1 fixed 38 | 7 7 8 boundary 2 fixed 39 | 8 8 9 boundary 2 fixed 40 | 9 9 10 boundary 2 fixed 41 | 10 10 11 boundary 2 fixed 42 | 11 11 12 boundary 2 fixed 43 | 12 12 7 boundary 2 fixed 44 | 13 1 7 45 | 14 2 8 46 | 15 3 9 47 | 16 4 10 48 | 17 5 11 49 | 18 6 12 50 | 51 | faces /* given by oriented edge list */ 52 | 1 1 14 -7 -13 53 | 2 2 15 -8 -14 54 | 3 3 16 -9 -15 55 | 4 4 17 -10 -16 56 | 5 5 18 -11 -17 57 | 6 6 13 -12 -18 58 | 59 | read 60 | 61 | // Demonstrating saddle point due to triangulation arrangement. 62 | // First setting parameters to stable values. 63 | gogo := { g; u; r; g 50; // at this point have nearly a saddle point 64 | g 200; // triangulation twists around to lower energy 65 | } 66 | 67 | // Faster version of the above using conjugate gradient 68 | gogo2 := { g; u; r; U; g 25; // at this point have nearly a saddle point 69 | g 35; 70 | } 71 | 72 | // High accuracy evolution, using higher-order Lagrange elements. 73 | gogo3 := { u; rmax := cosh(height); recalc; 74 | r; g 5; hessian; 75 | r; g 5; hessian; 76 | lagrange 2; g 5; hessian; 77 | lagrange 4; g 5; hessian; 78 | lagrange 6; g 5; hessian; 79 | lagrange 8; g 5; hessian; 80 | true_area := 2*pi*(height + 0.5*sinh(2*height)); 81 | printf"Difference from true area: %g\n",total_area - true_area; 82 | } 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /fe/cat.fe: -------------------------------------------------------------------------------- 1 | // cat.fe 2 | 3 | // Evolver data for catenoid. 4 | 5 | PARAMETER RMAX = 1.5088795 // minimum radius for height 6 | PARAMETER ZMAX = 1.0 7 | 8 | boundary 1 parameters 1 // upper ring 9 | x1: RMAX * cos(p1) 10 | x2: RMAX * sin(p1) 11 | x3: ZMAX 12 | 13 | boundary 2 parameters 1 // lower ring 14 | x1: RMAX * cos(p1) 15 | x2: RMAX * sin(p1) 16 | x3: -ZMAX 17 | 18 | vertices // given in terms of boundary parameter 19 | 1 0.00 boundary 1 fixed 20 | 2 pi/3 boundary 1 fixed 21 | 3 2*pi/3 boundary 1 fixed 22 | 4 pi boundary 1 fixed 23 | 5 4*pi/3 boundary 1 fixed 24 | 6 5*pi/3 boundary 1 fixed 25 | 7 0.00 boundary 2 fixed 26 | 8 pi/3 boundary 2 fixed 27 | 9 2*pi/3 boundary 2 fixed 28 | 10 pi boundary 2 fixed 29 | 11 4*pi/3 boundary 2 fixed 30 | 12 5*pi/3 boundary 2 fixed 31 | 32 | edges 33 | 1 1 2 boundary 1 fixed 34 | 2 2 3 boundary 1 fixed 35 | 3 3 4 boundary 1 fixed 36 | 4 4 5 boundary 1 fixed 37 | 5 5 6 boundary 1 fixed 38 | 6 6 1 boundary 1 fixed 39 | 7 7 8 boundary 2 fixed 40 | 8 8 9 boundary 2 fixed 41 | 9 9 10 boundary 2 fixed 42 | 10 10 11 boundary 2 fixed 43 | 11 11 12 boundary 2 fixed 44 | 12 12 7 boundary 2 fixed 45 | 13 1 7 46 | 14 2 8 47 | 15 3 9 48 | 16 4 10 49 | 17 5 11 50 | 18 6 12 51 | 52 | faces 53 | 1 1 14 -7 -13 54 | 2 2 15 -8 -14 55 | 3 3 16 -9 -15 56 | 4 4 17 -10 -16 57 | 5 5 18 -11 -17 58 | 6 6 13 -12 -18 59 | 60 | read 61 | 62 | // Evolution to collapse and pop neck, as in Manual tutorial 63 | gogo := { r; u; g 120; t .05; o; g 5; } 64 | 65 | // Demonstrating saddle point due to triangulation arrangement. 66 | // First setting parameters to stable values. 67 | gogo2 := { rmax := 1; zmax := 0.55; recalc; 68 | g; u; r; g 50; // at this point have nearly a saddle point 69 | g 200; // triangulation twists around to lower energy 70 | } 71 | 72 | // Faster version of the above using conjugate gradient 73 | gogo3 := { rmax := 1; zmax := 0.55; recalc; 74 | g; u; r; U; g 25; // at this point have nearly a saddle point 75 | g 35; 76 | } 77 | 78 | // High accuracy evolution, using higher-order Lagrange elements. 79 | gogo4 := { u; zmax := 0.55; rmax := cosh(zmax); recalc; 80 | r; g 5; hessian; 81 | r; g 5; hessian; 82 | lagrange 2; g 5; hessian; 83 | lagrange 4; g 5; hessian; 84 | lagrange 6; g 5; hessian; 85 | lagrange 8; g 5; hessian; 86 | true_area := 2*pi*(zmax + 0.5*sinh(2*zmax)); 87 | printf"Difference from true area: %g\n",total_area - true_area; 88 | } 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /src/machine.c: -------------------------------------------------------------------------------- 1 | /************************************************************* 2 | * This file is part of the Surface Evolver source code. * 3 | * Programmer: Ken Brakke, brakke@susqu.edu * 4 | *************************************************************/ 5 | 6 | /* machine.c */ 7 | 8 | /* missing routines on some systems; see include.h for defines */ 9 | 10 | #include "include.h" 11 | 12 | /**********************************************************************8 13 | * 14 | * function: set_ctypes() 15 | * 16 | * purpose: implement toupper and tolower as arrays and set up 17 | * ctype flag bits. 18 | */ 19 | void set_ctypes() 20 | { 21 | int c; 22 | for ( c = 0xFF ; c > 0 ; c-- ) 23 | { kb_upper_array[c] = (char)c; 24 | kb_lower_array[c] = (char)c; 25 | } 26 | for ( c = 'a' ; c <= 'z' ; c++ ) 27 | kb_upper_array[c] = (char)(c + 'A' - 'a'); 28 | for ( c = 'A' ; c <= 'Z' ; c++ ) 29 | kb_lower_array[c] = (char)(c - 'A' + 'a'); 30 | 31 | } 32 | 33 | 34 | int kb_stricmp(a,b) 35 | char *a,*b; 36 | { register char aa,bb; /* lower case versions of characters */ 37 | for(;;a++,b++) 38 | { aa = tolower(*a); 39 | bb = tolower(*b); 40 | if ( aa < bb ) return -1; 41 | if ( aa > bb ) return 1; 42 | if ( !aa ) break; /* have reached both nulls */ 43 | } 44 | return 0; /* equal strings */ 45 | } 46 | 47 | int kb_strnicmp(a,b,n) 48 | char *a,*b; 49 | int n; /* maximum characters to compare */ 50 | { register char aa,bb; /* lower case versions of characters */ 51 | for(;n;n--,a++,b++) 52 | { aa = tolower(*a); 53 | bb = tolower(*b); 54 | if ( aa < bb ) return -1; 55 | if ( aa > bb ) return 1; 56 | if ( !aa ) break; /* have reached both nulls */ 57 | } 58 | return 0; /* equal strings */ 59 | } 60 | 61 | 62 | void kb_strupr(s) 63 | char *s; 64 | { 65 | while ( *s ) 66 | { *s = (char)toupper(*s); 67 | s++; 68 | } 69 | } 70 | 71 | /* finds string b in string a */ 72 | char *kb_strstr(a,b) 73 | char *a; 74 | char *b; 75 | { 76 | char *ptr,*ch; 77 | 78 | for ( ; *a ; a++ ) 79 | { for ( ptr = a, ch = b; *ch && (*ptr == *ch) ; ptr++,ch++ ) ; 80 | if ( *ch == '\0' ) return a; 81 | } 82 | return NULL; 83 | } 84 | 85 | 86 | void kb_memmove(dest,src,n) 87 | char *dest; 88 | char *src; 89 | size_t n; 90 | { 91 | /* crude bytewise move */ 92 | if ( (dest - src) > 0 ) /* move from top down */ 93 | { 94 | src += n; dest += n; 95 | for ( ; n ; n-- ) *(--dest) = *(--src); 96 | } 97 | else /* move from bottom up */ 98 | { 99 | for ( ; n ; n-- ) *(dest++) = *(src++); 100 | } 101 | } 102 | 103 | 104 | -------------------------------------------------------------------------------- /fe/vrml.cmd: -------------------------------------------------------------------------------- 1 | // vrml.cmd 2 | // Makes VRML file for surface. 3 | 4 | // Usage: Set edge_flag to 1 if you want do see all edges. 5 | // Run "vrml" and re-direct output to file, e.g. 6 | // Enter command: vrml >>> "myfile.wrl"; 7 | 8 | // Programmer: Ken Brakke, brakke@susqu.edu, http://www.susqu.edu/brakke 9 | 10 | define vertex attribute order_num integer 11 | edge_flag := 0 // 1 for all edges, 0 for special edges only 12 | vrml := { 13 | local counter; 14 | counter := 0; 15 | printf "#VRML V1.0 ascii\n\n"; 16 | printf "Separator {\n"; 17 | printf " DEF Title Info { string \"%s\" }\n",datafilename; 18 | printf " DEF SceneInfo Info { string \"Created by Surface Evolver\" }\n"; 19 | printf " DEF BackgroundColor Info { string \".5 .6 1\" } \n"; 20 | printf " DirectionalLight { intensity .5 direction 0 0 -1 } \n"; 21 | printf " MaterialBinding { value PER_FACE_INDEXED }\n"; 22 | printf " Material { \n"; 23 | printf " diffuseColor [ 0.0 0.0 0.0 , 0.0 0.0 0.5 ,\n"; 24 | printf " 0.0 0.5 0.0 , 0.0 0.5 0.5 , 0.5 0.0 0.0 , 0.5 0.0 0.5 ,\n"; 25 | printf " 0.5 0.25 0. , .3 .3 .3 , .15 .15 .15 , .25 .25 .5 , .25 .5 .25 ,\n"; 26 | printf " .25 .5 .5 , .5 .25 .25 , .5 .25 .5 , .5 .5 .0 , .5 .5 .5 ] \n"; 27 | printf " emissiveColor [ 0.0 0.0 0.0 , 0.0 0.0 0.5 ,\n"; 28 | printf " 0.0 0.5 0.0 , 0.0 0.5 0.5 , 0.5 0.0 0.0 , 0.5 0.0 0.5 ,\n"; 29 | printf " 0.5 0.25 0. , .3 .3 .3 , .15 .15 .15 , .25 .25 .5 , .25 .5 .25 ,\n"; 30 | printf " .25 .5 .5 , .5 .25 .25 , .5 .25 .5 , .5 .5 .0 , .5 .5 .5 ] \n"; 31 | printf " }\n"; 32 | printf " Separator {\n"; 33 | printf " Coordinate3 { point [\n"; 34 | foreach vertex jvv do { printf " %f %f %f,\n",jvv.x,jvv.y,jvv.z; 35 | set jvv order_num counter; counter := counter + 1; }; 36 | printf " ]\n }\n"; 37 | printf " IndexedFaceSet { coordIndex [\n"; 38 | foreach facet jff do printf " %g,%g,%g,-1,\n", 39 | jff.vertex[1].order_num,jff.vertex[2].order_num,jff.vertex[3].order_num; 40 | printf " ] \n"; 41 | printf " materialIndex [\n"; 42 | foreach facet jff do printf " %g,\n",jff.color; 43 | printf " ]\n"; 44 | printf " }\n"; 45 | printf " Material { ambientColor 0 0 0 diffuseColor 0 0 0 }\n"; 46 | printf " IndexedLineSet { coordIndex [\n"; 47 | if edge_flag then 48 | foreach edge jee do printf " %g,%g,-1,\n", 49 | jee.vertex[1].order_num,jee.vertex[2].order_num 50 | else foreach edge jee where valence != 2 do printf " %g,%g,-1,\n", 51 | jee.vertex[1].order_num,jee.vertex[2].order_num; 52 | printf " ] } \n"; 53 | printf " }\n"; 54 | printf "}\n"; 55 | 56 | } // end vrml 57 | 58 | -------------------------------------------------------------------------------- /fe/gaussref.cmd: -------------------------------------------------------------------------------- 1 | // gaussref.cmd 2 | 3 | // Refining using Gauss map as criterion. 4 | // Refines edges where difference in normal 5 | // exceeds user-set amount. 6 | 7 | // Programmer: Ken Brakke, brakke@susqu.edu, http://www.susqu.edu/brakke 8 | 9 | // Usage: set the variable gaussref_tolerance, and do gaussref. 10 | 11 | // Set by user; difference in normals in radians 12 | gaussref_tolerance := 0.3 13 | 14 | 15 | gaussref := { 16 | local ax,ay,az,bx,by,bz,diff,maga,magb,alen,maxdiff,triples,blen; 17 | local gaussref_count; 18 | 19 | gaussref_count := 0; 20 | foreach edge eee do 21 | { if max ( eee.vertex[1].edge,valence) <= 2 and 22 | max ( eee.vertex[2].edge,valence) <= 2 then 23 | { ax := eee.vertex[1].vertexnormal[1]; 24 | ay := eee.vertex[1].vertexnormal[2]; 25 | az := eee.vertex[1].vertexnormal[3]; 26 | bx := eee.vertex[2].vertexnormal[1]; 27 | by := eee.vertex[2].vertexnormal[2]; 28 | bz := eee.vertex[2].vertexnormal[3]; 29 | diff := pi/2 - abs(pi/2 - acos(ax*bx+ay*by+az*bz)) ; 30 | if ( diff > gaussref_tolerance ) 31 | then { 32 | refine eee; gaussref_count += 1; 33 | } 34 | } 35 | else if eee.valence == 2 then 36 | { ax := eee.facet[1].x[1]; 37 | ay := eee.facet[1].x[2]; 38 | az := eee.facet[1].x[3]; 39 | bx := eee.facet[2].x[1]; 40 | by := eee.facet[2].x[2]; 41 | bz := eee.facet[2].x[3]; 42 | maga := sqrt(ax^2+ay^2+az^2); 43 | magb := sqrt(bx^2+by^2+bz^2); 44 | diff := pi/2 - abs(pi/2 - acos((ax*bx+ay*by+az*bz)/maga/magb)) ; 45 | if ( diff > gaussref_tolerance ) 46 | then { 47 | refine eee; gaussref_count += 1; 48 | } 49 | } 50 | else if eee.valence >= 3 then 51 | { // check bend in continuation triple lines 52 | ax := eee.x; 53 | ay := eee.y; 54 | az := eee.z; 55 | alen := eee.length; 56 | maxdiff := 0; 57 | triples := 0; 58 | foreach eee.vertex vvv do 59 | { foreach vvv.edge eeee where (eeee.id != eee.id) and (valence >= 3) do 60 | { triples += 1; 61 | bx := eeee.x; 62 | by := eeee.y; 63 | bz := eeee.z; 64 | blen := eeee.length; 65 | diff := pi/2 - abs(pi/2 - acos((ax*bx+ay*by+az*bz)/alen/blen)) ; 66 | if ( diff > gaussref_tolerance ) 67 | then { 68 | if ( diff > maxdiff ) then maxdiff := diff; 69 | } 70 | } 71 | }; 72 | if ( (triples <= 1) and (maxdiff > gaussref_tolerance) ) 73 | then { 74 | refine eee; gaussref_count += 1; 75 | } 76 | } 77 | }; 78 | printf "Edges refined by gaussref: %d\n",gaussref_count; 79 | } 80 | 81 | -------------------------------------------------------------------------------- /doc/news_16.htm: -------------------------------------------------------------------------------- 1 | 2 | Surface Evolver Documentation - Newsletter 16 3 | 4 | 5 | 6 |

Surface Evolver Newsletter no. 16

7 | Back to top of Surface Evolver documentation. 8 |
 9 | 
10 |                     Surface Evolver Newsletter Number 16
11 |                                August 18, 1999
12 | 
13 |                        by Ken Brakke, brakke@susqu.edu
14 | 
15 | Contents
16 |   Version 2.14
17 |   New examples
18 |   New features and changes
19 | 
20 | Version 2.14
21 | 
22 |   Version 2.14 is now available at
23 |   http://www.susqu.edu/facstaff/b/brakke/evolver/evolver.htm.
24 |   It is also available from the Geometry Center, geom.umn.edu,
25 |   but I don't know how long that site will be available.
26 |   This is the first publicly announced version since 2.10c a year
27 |   ago, although version 2.13 was unofficially posted in May.
28 | 
29 |   There is finally a current Mac version for the PowerPC.
30 | 
31 | Examples
32 |   
33 |   A gallery of triply periodic minimal surfaces (many new) is at
34 |   http://www.susqu.edu/facstaff/b/brakke/examples/periodic/periodic.html.
35 |   This page is the result of joint work with Alan Schoen.
36 | 
37 |   There are three examples of liquid solder models, each with a
38 |   series of datafiles and commentary:
39 | 
40 |       Ball Grid Array joint (simple column between circular pads)
41 |       http://www.susqu.edu/facstaff/b/brakke/evolver/bga/bga.htm
42 | 
43 |       Gull Wing Lead (curved lead above rectangular pad)
44 |       http://www.susqu.edu/facstaff/b/brakke/evolver/gullwing/gullwing.html
45 | 
46 |       Tombstone (chip pulled upright by solder tension)
47 |       http://www.susqu.edu/facstaff/b/brakke/tombstone/tomb.htm
48 | 
49 | New features and changes
50 | 
51 |     Almost all of the changes are bug fixes, internal improvements,
52 |     and specialized new features. A couple are of general interest:
53 | 
54 |     hessian_normal is now defaults to ON.
55 | 
56 |     Put in automatic convert_to_quantities; still a place or two
57 |     where can't convert on the fly.  Command line option -a-
58 |     disables.
59 | 
60 |     Added "verbose" toggle command for action messages from
61 |     pop edge, pop vertex, delete, notch, refine, dissolve, and edgeswap.
62 | 
63 |     The "dissolve" command will now dissolve facets on bodies in the
64 |     soapfilm model, and edges on facets in the string model.
65 | 
66 |     Edges have frontbody and backbody attributes in the string model.
67 | 
68 |     There is a chdir command to change the working directory. 
69 | 
70 |     Element extra attributes can be declared with code to evaluate their
71 |     values.
72 | 

73 | Back to top of Surface Evolver documentation. 74 | 75 | 76 | -------------------------------------------------------------------------------- /src/softimag.c: -------------------------------------------------------------------------------- 1 | /************************************************************* 2 | * This file is part of the Surface Evolver source code. * 3 | * Programmer: Ken Brakke, brakke@susqu.edu * 4 | *************************************************************/ 5 | 6 | /***************************************************************** 7 | * 8 | * File: softimag.c 9 | * 10 | * Purpose: Triangle list file output for Softimage input. 11 | */ 12 | 13 | #include "include.h" 14 | 15 | static FILE *fd; 16 | 17 | /***************************************************************** 18 | * 19 | * Function: softimage() 20 | * 21 | * Purpose: Write Softimage format files. 22 | */ 23 | 24 | void softimage() 25 | { 26 | char file_name[100]; 27 | char name[100]; 28 | vertex_id v_id; 29 | facet_id f_id; 30 | int *vnumber; 31 | int n; 32 | 33 | prompt("Enter file name (no suffix): ",name,sizeof(name)); 34 | 35 | /* model file */ 36 | strcpy(file_name,name); 37 | strcat(file_name,".mdl"); 38 | fd = fopen(file_name,"w"); 39 | if ( fd == NULL ) 40 | { perror(file_name); 41 | return; 42 | } 43 | fprintf(fd,"SOFTIMAGE 4D Creative Environment v 1.6 \"ASCII\"\n\n\n"); 44 | fprintf(fd," MODL \"%s\"\n {\n type PMSH\n",name); 45 | fprintf(fd," nbdef 1\n"); 46 | fprintf(fd," scal 1.000000 1.000000 1.000000\n"); 47 | fprintf(fd," rot 0.000000 0.000000 0.000000\n"); 48 | fprintf(fd," trans 0.000000 0.000000 0.000000\n"); 49 | fprintf(fd," }\n"); 50 | fclose(fd); 51 | 52 | 53 | strcpy(file_name,name); 54 | strcat(file_name,".def"); 55 | fd = fopen(file_name,"w"); 56 | if ( fd == NULL ) 57 | { perror(file_name); 58 | return; 59 | } 60 | fprintf(fd,"SOFTIMAGE 4D Creative Environment v 1.6 \"ASCII\"\n\n"); 61 | fprintf(fd,"PMSH \"%s\"\n {\n ",name); 62 | 63 | /* vertex list */ 64 | vnumber = (int*)temp_calloc(web.skel[VERTEX].max_ord+1,sizeof(int*)); 65 | 66 | fprintf(fd," vertex %ld\n",web.skel[VERTEX].count); 67 | n = 1; 68 | FOR_ALL_VERTICES(v_id) 69 | { REAL *x = get_coord(v_id); 70 | fprintf(fd,"%12d %14.12f %14.12f %14.12f\n",n, 71 | (DOUBLE)x[0],(DOUBLE)x[1],(DOUBLE)x[2]); 72 | vnumber[loc_ordinal(v_id)] = n; 73 | n++; 74 | } 75 | 76 | 77 | /* triangle list */ 78 | fprintf(fd,"\n polygon %ld\n",web.skel[FACET].count); 79 | FOR_ALL_FACETS(f_id) 80 | { facetedge_id fe = get_facet_fe(f_id); 81 | facetedge_id next_fe = get_next_edge(fe); 82 | int oh = vnumber[loc_ordinal(get_fe_headv(fe))]; 83 | fprintf(fd," %10d %10d %10d %10d\n",oh, 84 | vnumber[loc_ordinal(get_fe_headv(next_fe))], 85 | vnumber[loc_ordinal(get_fe_tailv(fe))], 86 | vnumber[loc_ordinal(get_fe_tailv(fe))]); 87 | } 88 | fprintf(fd," }\n\n"); 89 | 90 | fclose(fd); 91 | 92 | temp_free((char*)vnumber); 93 | } 94 | 95 | 96 | -------------------------------------------------------------------------------- /fe/catbody.fe: -------------------------------------------------------------------------------- 1 | // catbody.fe 2 | 3 | // Evolver data for catenoid with fixed inner volume between plane ends. 4 | 5 | PARAMETER RMAX = 1.0 6 | PARAMETER ZMAX = 0.55 7 | 8 | boundary 1 parameters 1 // upper ring 9 | x1: RMAX * cos(p1) 10 | x2: RMAX * sin(p1) 11 | x3: ZMAX 12 | 13 | 14 | boundary 2 parameters 1 // lower ring 15 | x1: RMAX * cos(p1) 16 | x2: RMAX * sin(p1) 17 | x3: -ZMAX 18 | 19 | 20 | vertices // given in terms of boundary parameter 21 | 1 0.00 boundary 1 fixed 22 | 2 pi/3 boundary 1 fixed 23 | 3 2*pi/3 boundary 1 fixed 24 | 4 pi boundary 1 fixed 25 | 5 4*pi/3 boundary 1 fixed 26 | 6 5*pi/3 boundary 1 fixed 27 | 7 0.00 boundary 2 fixed 28 | 8 pi/3 boundary 2 fixed 29 | 9 2*pi/3 boundary 2 fixed 30 | 10 pi boundary 2 fixed 31 | 11 4*pi/3 boundary 2 fixed 32 | 12 5*pi/3 boundary 2 fixed 33 | 34 | edges 35 | 1 1 2 boundary 1 fixed 36 | 2 2 3 boundary 1 fixed 37 | 3 3 4 boundary 1 fixed 38 | 4 4 5 boundary 1 fixed 39 | 5 5 6 boundary 1 fixed 40 | 6 6 1 boundary 1 fixed 41 | 7 7 8 boundary 2 fixed 42 | 8 8 9 boundary 2 fixed 43 | 9 9 10 boundary 2 fixed 44 | 10 10 11 boundary 2 fixed 45 | 11 11 12 boundary 2 fixed 46 | 12 12 7 boundary 2 fixed 47 | 13 1 7 48 | 14 2 8 49 | 15 3 9 50 | 16 4 10 51 | 17 5 11 52 | 18 6 12 53 | 54 | faces 55 | 1 13 7 -14 -1 56 | 2 14 8 -15 -2 57 | 3 15 9 -16 -3 58 | 4 16 10 -17 -4 59 | 5 17 11 -18 -5 60 | 6 18 12 -13 -6 61 | 62 | bodies 63 | 1 1 2 3 4 5 6 volconst 2*pi*rmax^2*zmax volume 1.1 64 | 65 | read 66 | 67 | // Typical evolution 68 | gogo := { u; r; g 5; r; g 5; r; g 5; hessian; hessian } 69 | 70 | // Adjusting volume to find zero pressure, i.e. the unstable 71 | // equilibrium catenoid. Run after refining to taste. 72 | // Note that no 'g' steps are used in iteration after changing 73 | // the volume. This is because the triangulation is not optimal, 74 | // and 'g' lets the vertices slither sideways, but 'hessian' 75 | // moves vertices only perpendicular to the surface (in the default 76 | // hessian_normal mode). The magnitude of volume changes is limited 77 | // since experimentation showed that too large moves can cause 78 | // blowups. 79 | adjust := { 80 | oldpressure := body[1].pressure; 81 | oldtarget := body[1].target; 82 | dvol := .01; // starting step size 83 | body[1].target += dvol; 84 | hessian; hessian; hessian; 85 | slope := (body[1].pressure - oldpressure)/dvol; 86 | for ( inx := 1 ; inx <= 20; inx += 1 ) 87 | { dvol := -body[1].pressure/slope; 88 | if abs(dvol) > .01 then dvol := (dvol < 0) ? -.01 : .01; 89 | oldpressure := body[1].pressure; 90 | body[1].target += dvol; 91 | hessian; hessian; hessian; 92 | printf "Pressure %g dvol %g slope %f\n",body[1].pressure,dvol,slope; 93 | if abs(dvol) > .001 then 94 | slope := (body[1].pressure - oldpressure)/dvol; 95 | }; 96 | } 97 | 98 | -------------------------------------------------------------------------------- /fe/sphere.fe: -------------------------------------------------------------------------------- 1 | // sphere.fe 2 | 3 | // Spherical tank partially filled with liquid with contact angle. 4 | 5 | SYMMETRIC_CONTENT // natural for a sphere 6 | 7 | parameter rad = 1.00 // sphere radius 8 | parameter angle = 45 // contact angle, in degrees 9 | 10 | // cosine of contact angle 11 | #define WALLT cos(angle*pi/180) 12 | 13 | // density of body 14 | #define RHO 1.0 15 | 16 | // Various expressions used in constraints 17 | #define wstuff (rad^2*z/(x^2 + y^2)/sqrt(x^2+y^2+z^2)) 18 | #define gstuff (G*RHO/8*rad^4*z^4/(x^2 + y^2)*(x^2+y^2+z^2)^2) 19 | #define gapstuff (G*RHO*rad^4/8*z^2/(x^2+y^2+z^2)^2) 20 | 21 | constraint 1 convex // the sphere, as wall for liquid 22 | formula: sqrt(x^2 + y^2 + z^2) = rad 23 | energy: 24 | e1: WALLT*wstuff*y - gstuff*y + G*RHO/8*y*z^2 - gapstuff*y 25 | e2: -WALLT*wstuff*x + gstuff*x - G*RHO/8*x*z^2 + gapstuff*x 26 | e3: 0 27 | content: 28 | c1: -rad*wstuff*y/3 29 | c2: rad*wstuff*x/3 30 | c3: 0 31 | 32 | constraint 2 // the sphere, for display only 33 | formula: sqrt(x^2 + y^2 + z^2) = rad 34 | 35 | vertices: 36 | 1 rad 0 0 constraint 1 37 | 2 0 rad 0 constraint 1 38 | 3 -rad 0 0 constraint 1 39 | 4 0 -rad 0 constraint 1 40 | 5 0 0 rad constraint 2 FIXED // to show back hemisphere 41 | 6 0 0 -rad constraint 2 FIXED 42 | 7 0 rad 0 constraint 2 FIXED 43 | 8 -rad 0 0 constraint 2 FIXED 44 | 9 0 -rad 0 constraint 2 FIXED 45 | 46 | edges: 47 | 1 1 2 constraint 1 48 | 2 2 3 constraint 1 49 | 3 3 4 constraint 1 50 | 4 4 1 constraint 1 51 | 5 5 9 constraint 2 FIXED // to show back hemisphere 52 | 6 9 6 constraint 2 FIXED 53 | 7 6 7 constraint 2 FIXED 54 | 8 7 5 constraint 2 FIXED 55 | 9 5 8 constraint 2 FIXED 56 | 10 9 8 constraint 2 FIXED 57 | 11 6 8 constraint 2 FIXED 58 | 12 7 8 constraint 2 FIXED 59 | 60 | faces: 61 | 1 1 2 3 4 62 | 2 5 10 -9 constraint 2 density 0 FIXED // to show back hemisphere 63 | 3 -10 6 11 constraint 2 density 0 FIXED 64 | 4 -11 7 12 constraint 2 density 0 FIXED 65 | 5 8 9 -12 constraint 2 density 0 FIXED 66 | 67 | bodies: // start with sphere half full 68 | 1 1 volume 2*pi*rad^3/3 volconst 2*pi*rad^3/3 density RHO 69 | 70 | read 71 | 72 | // Typical short evolution 73 | gogo := { g 5; r; g 5; r; g 5; r; g 10; conj_grad; g 20; } 74 | 75 | 76 | // Command to print out coordinates of points along cross-section 77 | // of the surface. This starts at vertex 3 and follows edges that 78 | // point in the positive x direction. 79 | section := { 80 | thisv := 3; 81 | nextv := thisv; 82 | do 83 | { printf "%9.6f %9.6f %9.6f\n",vertex[thisv].x,vertex[thisv].y, 84 | vertex[thisv].z; 85 | foreach vertex[thisv].edge ee do 86 | { if ee.x > 10*abs(ee.y) then 87 | { nextv := ee.vertex[2].id; 88 | break; 89 | } 90 | }; 91 | if nextv == thisv then break; // done 92 | thisv := nextv; 93 | } while 1; 94 | } 95 | -------------------------------------------------------------------------------- /src/diffuse.c: -------------------------------------------------------------------------------- 1 | /************************************************************* 2 | * This file is part of the Surface Evolver source code. * 3 | * Programmer: Ken Brakke, brakke@susqu.edu * 4 | *************************************************************/ 5 | 6 | #include "include.h" 7 | 8 | /******************************************************************** 9 | * 10 | * Function: diffuse() 11 | * 12 | * Purpose: Diffuse mass through permeable surfaces. 13 | * Assumes string lengths or film areas 14 | * already calculated; also assumes pressures 15 | * known. 16 | */ 17 | 18 | /* for per-element diffusion constant */ 19 | #define DIFFUSE_EATTR_NAME "edge_diffusion" 20 | #define DIFFUSE_FATTR_NAME "facet_diffusion" 21 | int edge_diffusion_attr; 22 | int facet_diffusion_attr; 23 | 24 | void diffuse() 25 | { 26 | edge_id e_id; 27 | facet_id f_id; 28 | facetedge_id fe_id; 29 | body_id b_id,bb_id; 30 | REAL pressure; 31 | REAL mass; 32 | REAL coeff; 33 | 34 | if ( web.representation == STRING ) 35 | { edge_diffusion_attr = find_attribute(EDGE,DIFFUSE_EATTR_NAME); 36 | FOR_ALL_EDGES(e_id) 37 | { fe_id = get_edge_fe(e_id); 38 | if ( !valid_id(fe_id) ) return; 39 | b_id = get_facet_body(get_fe_facet(fe_id)); 40 | if ( !valid_id(b_id) ) invert(fe_id); 41 | b_id = get_facet_body(get_fe_facet(fe_id)); 42 | if ( !valid_id(b_id) ) continue; 43 | pressure = get_body_pressure(b_id); 44 | 45 | if ( !equal_id(fe_id,get_next_facet(fe_id)) ) 46 | { fe_id = get_next_facet(fe_id); 47 | bb_id = get_facet_body(get_fe_facet(fe_id)); 48 | if ( !valid_id(bb_id) ) invert(fe_id); 49 | bb_id = get_facet_body(get_fe_facet(fe_id)); 50 | pressure -= get_body_pressure(bb_id); 51 | } 52 | else bb_id = NULLBODY; 53 | if ( edge_diffusion_attr >= 0 ) 54 | coeff = *(REAL*)get_extra(e_id,edge_diffusion_attr); 55 | else coeff = web.diffusion_const; 56 | mass = web.scale*coeff*pressure*get_edge_length(e_id); 57 | set_body_fixvol(b_id,get_body_fixvol(b_id)-mass); 58 | if ( valid_id(bb_id) ) 59 | set_body_fixvol(bb_id,get_body_fixvol(bb_id)+mass); 60 | } 61 | } /* end STRING */ 62 | else 63 | { facet_diffusion_attr = find_attribute(FACET,DIFFUSE_FATTR_NAME); 64 | FOR_ALL_FACETS(f_id) 65 | { pressure = 0.0; 66 | b_id = get_facet_body(f_id); 67 | if ( valid_id(b_id) ) 68 | pressure = get_body_pressure(b_id); 69 | else pressure = web.pressure; 70 | 71 | bb_id = get_facet_body(inverse_id(f_id)); 72 | if ( valid_id(bb_id) ) 73 | pressure -= get_body_pressure(bb_id); 74 | else pressure -= web.pressure; 75 | if ( facet_diffusion_attr >= 0 ) 76 | coeff = *(REAL*)get_extra(f_id,facet_diffusion_attr); 77 | else coeff = web.diffusion_const; 78 | 79 | mass = web.scale*coeff*pressure*get_facet_area(f_id); 80 | if ( valid_id(b_id) ) 81 | set_body_fixvol(b_id,get_body_fixvol(b_id)-mass); 82 | if ( valid_id(bb_id) ) 83 | set_body_fixvol(bb_id,get_body_fixvol(bb_id)+mass); 84 | } 85 | } 86 | } /* end diffuse() */ 87 | -------------------------------------------------------------------------------- /fe/tankex.fe: -------------------------------------------------------------------------------- 1 | // tankex.fe 2 | 3 | // Equilibrium shape of liquid in flat-ended cylindrical tank. 4 | 5 | // Tank has axis along y-axis and flat bottom in x-z plane. This 6 | // is so gravity acting vertically draws liquid toward wall. 7 | 8 | // Straight edges cannot conform exactly to curved walls. 9 | // We need to give them an area so that area cannot shrink by straght edges 10 | // pulling away from the walls. The gaps are also accounted for 11 | // in volume and gravitational energy. 12 | 13 | SYMMETRIC_CONTENT // for volume calculations 14 | 15 | // Contact angles, initially for 45 degrees. 16 | PARAMETER ENDT = 0.707 /* surface tension of uncovered base */ 17 | PARAMETER WALLT = 0.707 /* surface tension of uncovered side wall */ 18 | 19 | // Gravity components 20 | PARAMETER GY = 0 21 | PARAMETER GZ = -1 22 | 23 | SPRING_CONSTANT 1 // for most accurate gap areas for constraint 2 24 | 25 | #define TR 1.00 /* tank radius */ 26 | #define RHO 1.00 /* fuel density */ 27 | 28 | constraint 1 // flat base 29 | function: y = 0 30 | energy: // for contact energy line integral 31 | e1: -ENDT*z 32 | e2: 0 33 | e3: 0 34 | 35 | #define wstuff (WALLT*TR*y/(x^2 + z^2)) // common wall area term 36 | #define vstuff (TR^2/3*y/(x^2 + z^2)) // common wall volume term 37 | #define gstuff (GY*TR^2*y^2/4/(x^2 + z^2) + GZ*TR^3*y*z/3/(x^2+z^2)**1.5) 38 | // common gap gravity term 39 | 40 | constraint 2 CONVEX // cylindrical wall 41 | function: x^2 + z^2 = TR^2 42 | energy: // for contact energy and gravity 43 | e1: -wstuff*z + RHO*GY*y^2*z/4 + RHO*GZ*y*z^2/3 - RHO*gstuff*z 44 | e2: 0 45 | e3: wstuff*x - RHO*GY*y^2*x/4 - RHO*GZ*y*z*x/3 + RHO*gstuff*x 46 | content: // so volumes calculated correctly 47 | c1: vstuff*z - z*y/6 + vstuff*z/2 48 | c2: 0 49 | c3: -vstuff*x + x*y/6 - vstuff*x/2 50 | 51 | // named quantity for arbitrary direction gravity on facets 52 | quantity arb_grav energy method facet_vector_integral global 53 | vector_integrand: 54 | q1: 0 55 | q2: -RHO*GY*y^2/2 - RHO*GZ*y*z 56 | q3: 0 57 | 58 | 59 | // Now the specification of the initial shape 60 | 61 | vertices 62 | 1 0.5 0.0 0.5 constraint 1 63 | 2 0.5 0.0 -0.5 constraint 1 64 | 3 -0.5 0.0 -0.5 constraint 1 65 | 4 -0.5 0.0 0.5 constraint 1 66 | 5 1.0 0.5 0.0 constraint 2 67 | 6 0.0 0.5 -1.0 constraint 2 68 | 7 -1.0 0.5 0.0 constraint 2 69 | 8 0.0 0.5 1.0 constraint 2 70 | 71 | edges 72 | 1 2 1 constraint 1 73 | 2 1 4 constraint 1 74 | 3 4 3 constraint 1 75 | 4 3 2 constraint 1 76 | 5 5 6 constraint 2 77 | 6 6 7 constraint 2 78 | 7 7 8 constraint 2 79 | 8 8 5 constraint 2 80 | 9 1 8 81 | 10 1 5 82 | 11 2 5 83 | 12 2 6 84 | 13 3 6 85 | 14 3 7 86 | 15 4 7 87 | 16 4 8 88 | 89 | faces 90 | 1 13 6 -14 91 | 2 3 14 -15 92 | 3 15 7 -16 93 | 4 2 16 -9 94 | 5 9 8 -10 95 | 6 1 10 -11 96 | 7 11 5 -12 97 | 8 4 12 -13 98 | 99 | bodies 100 | 1 1 2 3 4 5 6 7 8 volume 0.6 density 0 /* no default gravity */ 101 | 102 | -------------------------------------------------------------------------------- /fe/unshear.cmd: -------------------------------------------------------------------------------- 1 | // unshear.cmd 2 | 3 | // Evolver command to get torus fundamental region closer to rectangular. 4 | // Works in either 2 or 3 dimensions. (eventually, just 2D now) 5 | 6 | // NOTE: "unshear" needs to change the torus periods, but can't directly 7 | // since torus_periods is a read-only variable (because it is remembered 8 | // as a formula). So the assumption is that the shear entries of the 9 | // torus_periods matrix are variables of particular names, shearij for 10 | // torus_periods[i][j]. (remember indexing starts with 1) 11 | 12 | // Programmer: Ken Brakke, brakke@susqu.edu, http://www.susqu.edu/brakke 13 | 14 | if not is_defined("shear21") then 15 | errprintf "unshear.cmd assumes torus_periods[2][1] defined as shear21.\n" ; 16 | 17 | // 2D version 18 | unshear2 := { 19 | local shifts,vshifts,wrap1,wrap2,wraprest; 20 | 21 | // test for horizontal shear 22 | shifts := floor(torus_periods[2][1]/torus_periods[1][1] + .5); 23 | 24 | shear21 -= shifts*torus_periods[1][1]; 25 | // move vertices over 26 | foreach vertex vv do 27 | { vshifts := -floor(vv.x*inverse_periods[1][1]+vv.y*inverse_periods[1][2]); 28 | if vshifts != 0 then 29 | wrap_vertex(vv.id,(vshifts imod 32)); 30 | }; 31 | // change edge wraps 32 | foreach edge ee where ((ee.wrap idiv 64) imod 32) == 1 do 33 | { wrap1 := ee.wrap imod 64; 34 | wraprest := ee.wrap - wrap1; 35 | if wrap1 > 15 then wrap1 -= 32; 36 | wrap1 += shifts; 37 | ee.wrap := wraprest + (wrap1 imod 32); 38 | }; 39 | foreach edge ee where ((ee.wrap idiv 64) imod 32) == 31 do 40 | { wrap1 := ee.wrap imod 64; 41 | wraprest := ee.wrap - wrap1; 42 | if wrap1 > 15 then wrap1 -= 32; 43 | wrap1 += -shifts; 44 | ee.wrap := wraprest + (wrap1 imod 32); 45 | }; 46 | 47 | recalc; // get inverse periods set up right for next stage 48 | 49 | // test for vertical shear 50 | shifts := floor(torus_periods[1][2]/torus_periods[2][2] + .5); 51 | 52 | shear12 -= shifts*torus_periods[2][2]; 53 | // move vertices over 54 | foreach vertex vv do 55 | { vshifts := -floor(vv.x*inverse_periods[2][1]+vv.y*inverse_periods[2][2]); 56 | if vshifts != 0 then 57 | wrap_vertex(vv.id,(vshifts imod 32)*64); 58 | }; 59 | 60 | // change edge wraps 61 | foreach edge ee where (ee.wrap imod 32) == 1 do 62 | { wrap2 := (ee.wrap idiv 64) imod 64; 63 | wraprest := ee.wrap - wrap2*64; 64 | if wrap2 > 15 then wrap2 -= 32; 65 | wrap2 += shifts; 66 | ee.wrap := wraprest + (wrap2 imod 32)*64; 67 | }; 68 | foreach edge ee where (ee.wrap imod 32) == 31 do 69 | { wrap2 := (ee.wrap idiv 64) imod 64; 70 | wraprest := ee.wrap - wrap2*64; 71 | if wrap2 > 15 then wrap2 -= 32; 72 | wrap2 -= shifts; 73 | ee.wrap := wraprest + (wrap2 imod 32)*64; 74 | }; 75 | 76 | } 77 | 78 | // 3D version 79 | unshear3 := { 80 | errprintf "Unshear not yet implemented for 3D.\n"; 81 | } 82 | 83 | // Overall command, just a wrapper 84 | unshear := { 85 | if not torus then 86 | { errprintf "Unshear only relevant to torus model.\n"; 87 | return; 88 | }; 89 | if space_dimension == 2 then unshear2 90 | else if space_dimension == 3 then unshear3 91 | else errprintf "Unshear not implemented for space dimension %d\n", 92 | space_dimension; 93 | } 94 | 95 | -------------------------------------------------------------------------------- /doc/evolver.1: -------------------------------------------------------------------------------- 1 | .\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples. 2 | .\"See Also: 3 | .\"man mdoc.samples for a complete listing of options 4 | .\"man mdoc for the short list of editing options 5 | .\"/usr/share/misc/mdoc.template 6 | .Dd Mon May 19 2003 \" DATE 7 | .Dt Evolver 1 \" Program name and manual section number 8 | .Os Darwin 9 | .Sh NAME \" Section Header - required - don't modify 10 | .Nm evolver 11 | .\" The following lines are read in generating the apropos(man -k) database. Use only key 12 | .\" words here as the database is built based on the words here and in the .ND line. 13 | .Nd The Surface Evolver, minimize energy of a surface 14 | .Sh SYNOPSIS \" Section Header - required - don't modify 15 | .Nm 16 | .Op Fl adehimqwxy \" [-adehimqwxy] 17 | .Op Fl f Ar file \" [-f file] 18 | .Op Fl pN \" [-pN] 19 | .Op Ar datafile \" Underlined argument - use .Ar anywhere to underline 20 | .Sh DESCRIPTION \" Section Header - required - don't modify 21 | The Surface Evolver is a program that minimizes the energy of a triangulated 22 | surface according to designated energies and constraints. This man page only 23 | documents command line options and environment variables. The full package 24 | and documentation are available at http://www.susqu.edu/brakke/evolver. 25 | .Pp \" Inserts a space 26 | Command line options (multiple letters may not be combined): 27 | .Bl -tag -width -indent \" Differs from above in tag removed 28 | .It Ar datafile 29 | Text file defining a surface. If omitted, you will be prompted. 30 | .It Fl a 31 | Autoconvert to named quantities when needed (default is on); use "-a-" to 32 | deactivate autoconversion. 33 | .It Fl d 34 | Begin with parser debugging on (equivalent to "debug" runtime command). 35 | Beware of copious output. 36 | .It Fl e 37 | Echo stdin to stdout; meant for testing piped input. 38 | .It Fl f Ar file 39 | After loading datafile, read commands from 40 | .Ar file , 41 | then command line prompt. 42 | .It Fl h 43 | Print help for command line options. 44 | .It Fl i 45 | Preserve datafile numbers for element id's, rather than renumbering. 46 | .It Fl m 47 | Begin with memory debugging on (equivalent to "memdebug" runtime command). 48 | Beware of copious output. 49 | .It Fl pN 50 | Run with N concurrent processes. 51 | .It Fl q 52 | Convert to named quantities at start (equivalent to "convert_to_quantities" 53 | runtime command). 54 | .It Fl w 55 | Exit immediately after any warning or error message; meant for batch runs. 56 | .It Fl x 57 | Exit immediately after any error message; meant for batch runs. 58 | .It Fl y 59 | Break to user prompt after any warning message. 60 | .El \" Ends the list 61 | .Pp 62 | .\" .Sh ENVIRONMENT \" May not be needed 63 | .\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1 64 | .\" .It Ev ENV_VAR_1 65 | .\" Description of ENV_VAR_1 66 | .\" .It Ev ENV_VAR_2 67 | .\" Description of ENV_VAR_2 68 | .\" .El 69 | .Sh ENVIRONMENT VARIABLES 70 | .Bl -tag -width "EVOLVERPATH" -compact 71 | .It EVOLVERPATH 72 | Colon-separated list of paths automatically searched for datafiles, included 73 | files, or help documentation. 74 | 75 | -------------------------------------------------------------------------------- /doc/profiling.htm: -------------------------------------------------------------------------------- 1 | 2 | Surface Evolver Documentation: Debugging 3 | 4 | 5 | 6 |
7 |

8 | Surface Evolver Documentation

9 |
10 | Back to top of Surface Evolver documentation. 11 | Index. 12 | 13 | 14 |
15 |

Surface Evolver Execution Time Profiling

16 | 17 |
18 |

Coarse Profiling

19 | Coarse timing with resolution of 0,01 second or so can be done with 20 | Evolver's clock variable. 21 | For example, to time iterations I 22 | typically do 23 |
24 | 
25 |    Enter command: quiet; start := clock; g 100; print start-clock; quiet off
26 | 
27 | which will print out the elapsed time in seconds. I do 28 | quiet here 29 | to suppress output to the screen, which can slow down things considerably. 30 |

31 |


32 |

Fine Profiling

33 | Nanosecond resolution can be done with Evolver's 34 | cpu_counter 35 | variable. 36 | 37 |

38 |


39 | 40 | 41 |

Expression Evaluation Profiling

42 | 43 | On systems where Evolver has 44 | cpu_counter 45 | available and Evolver has been compiled with the manifest 46 | constant PROF_EVALS defined, the expression evaluator 47 | inside Evolver keeps track of the clock cycles elapsed 48 | during each expression evaluation. These expressions 49 | include procedures, functions, constraint and boundary 50 | formulas, content integrands, energy integrands, quantity 51 | integrands, etc; everything that prints out as code in 52 | a dump file. The 53 | print profiling command will print the 54 | accumulated CPU cycles so far for each type of expression. 55 | The times are inclusive of any child functions or procedures. 56 | An example, from mound.fe after running "gogo": 57 |
58 | Enter command: print profiling
59 | Inclusive profiling counts:
60 |                       Name            CPU Cycles
61 |                               re           1,952,792
62 |                             gogo         125,201,889
63 |                            gogo2                   0
64 |                            gogo3                   0
65 |                            gogo4                   0
66 |                            gogo5                   0
67 | 
68 | Constraint expressions
69 |                     Constraint  Formula Cycles   Energy Cycles  Content Cycles
70 |                              1         877,047       2,337,727               0
71 | 
72 | Note that hard-coded evaluations of area, volume, etc. do not show up here, 73 | except for their effect on overall elapsed time. 74 |

75 | The command reset_profiling will set all the cycle values back to 0. 76 | 77 |

78 |


79 |

Execution sampling

80 | Of course, if you are compiling Evolver yourself, you can use any 81 | type of profiling you would ordinarily use on a C program. i leave 82 | you to your own devices on this. 83 |

84 |


85 | Back to top of Surface Evolver documentation. 86 | Index. 87 | 88 | 89 | -------------------------------------------------------------------------------- /fe/README-cmd.txt: -------------------------------------------------------------------------------- 1 | A selection of Evolver commands for your edification. Consult remarks at 2 | the top of each file for further information and instructions on use. 3 | Use with caution; no attempt has been made to bulletproof these. 4 | 5 | Note: These scripts do not necessarily take advantage of all the latest 6 | Evolver features, and if I were writing them from scratch now they might 7 | turn out quite different. 8 | 9 | adjoint.cmd 10 | ansurf.cmd Produces input file for ANSYS. 11 | band.cmd Make extremely accurate thick borders for graphics. 12 | bonnet_movie.cmd Show Bonnet rotation of minimal surface. 13 | cmccousin.cmd Create constant mean curvature "cousin" surface. 14 | dirichlet_to_disk.cmd Makes conformal map to disk by minimizing Dirichlet energy. 15 | dxf.cmd Produce AutoCad DXF file. 16 | equi.cmd To color edges subject to equiangulation. 17 | equi2.cmd To color edges subject to equiangulation. 18 | fourier.cmd Calculate Fourier components for closed curve 19 | gaussequi.cmd Equiangulation using Gauss map for swap criterion. 20 | gaussmap.cmd Converts each vertex coordinate to unit normal. 21 | gaussref.cmd Refining using Gauss map as criterion. 22 | iges.cmd Create file in IGES text format. 23 | iges128.cmd Create IGES file using B-spline entity (type 128). 24 | iges136.cmd Create IGES file using finite element entity (type 136). 25 | intersec.cmd Detect intersection of linear edges and facets. 26 | jvx.cmd Creates JVX format file for JavaView. 27 | multiplicate.cmd Create datafile with multiple copies of surface. 28 | neville.cmd Neville's algorithm for interpolating b-splines in 1D and 2D. 29 | off.cmd Prints OFF format file. 30 | order.cmd Numbers string vertices consecutively. 31 | orderdmp.cmd Number string vertices consecutively and create an ordered dump file. 32 | orderlis.cmd Number string vertices consecutively and list them 33 | polyfilm.cmd Produce Polycut format file 34 | povray.cmd Produces POV-Ray input file. 35 | povrays.cmd POV-Ray file with smooth shading. 36 | quadbbox.cmd Finds bounding boxes for quadratic facets in 3D 37 | quadint2.cmd For detecting intersection of quadratic facets in 3D 38 | quadmeet.cmd For detecting intersection of quadratic facets in 3D 39 | reorder.cmd Example of using "reorder_storage" command. 40 | rewrap.cmd Adjusting wraps of edges in 3D torus model. 41 | rewrap2.cmd Adjusting wraps of edges in 2D torus model. 42 | rib.cmd Creates Renderman RIB file. 43 | rotate.cmd Rotate unfixed vertices by angle about z axis. 44 | saveview.cmd Saves view matrix in easily reloadable form. 45 | slice.cmd Calculate length of intersection of plane with surface. 46 | slice2.cmd Calculates length of intersection of plane with one body. 47 | slicer.cmd Create physical intersection of surface and plane. 48 | stl.cmd Creates file in STL stereolithography format. 49 | strdup.cmd Writes a datafile that is an n-fold covering of a string. 50 | tuber.cmd Creates tubes around certain edges. 51 | unshear.cmd Morphs 2D torus fundamental region to rectangle. 52 | vrml.cmd Makes VRML file for surface. 53 | wavefront.cmd Creates Wavefront format file. 54 | wetfoam2.cmd Creates Plateau borders on a dry foam. 55 | x3d.cmd Creates X3D format file. 56 | xray.cmd Creates PostScript file with x-ray image. 57 | zebra.cmd Colors string edges alternately black and white 58 | -------------------------------------------------------------------------------- /doc/default.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | Surface Evolver Documentation 4 | 5 | 6 | 7 |
8 |

The Surface Evolver

9 | 10 | 11 | Kenneth A. Brakke
12 | Mathematics Department
13 | Susquehanna University
14 | Selinsgrove, PA, 17870
15 | brakke@susqu.edu
16 |

17 | with past support from
18 | The Geometry Center
19 | University of Minnesota
20 | Minneapolis, MN 55454
21 | 22 | 23 |

Version 2.26, August 20, 2005

24 |
25 |
26 |

Contents

27 | 28 | 29 | 30 | 57 | 58 | 86 | 87 |
31 | 56 | 59 | 85 |
88 | 89 | This HTML version of the Evolver documentation contains most of what 90 | the printed manual 91 | has, with the main exception of sections with a lot 92 | of mathematical formulas, such as the more advanced examples and the 93 | Techical Reference chapter. Not all possible links are in yet, but 94 | you can consult the Index to find something. 95 | 96 |

Web home page

97 | 98 | My Web home page is 99 | http://www.susqu.edu/brakke/. 100 | Evolver-related material and links will be posted there. In 101 | particular, there are many examples of surfaces. 102 | 103 | 104 |
Back to top of Surface Evolver documentation. 105 |

106 | 107 | Author's home page. 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /doc/default.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Surface Evolver Documentation 4 | 5 | 6 | 7 |

8 |

The Surface Evolver

9 | 10 | 11 | Kenneth A. Brakke
12 | Mathematics Department
13 | Susquehanna University
14 | Selinsgrove, PA, 17870
15 | brakke@susqu.edu
16 |

17 | with past support from
18 | The Geometry Center
19 | University of Minnesota
20 | Minneapolis, MN 55454
21 | 22 | 23 |

Version 2.26, August 20, 2005

24 |
25 |
26 |

Contents

27 | 28 | 29 | 30 | 57 | 58 | 86 | 87 |
31 | 56 | 59 | 85 |
88 | 89 | This HTML version of the Evolver documentation contains most of what 90 | the printed manual 91 | has, with the main exception of sections with a lot 92 | of mathematical formulas, such as the more advanced examples and the 93 | Techical Reference chapter. Not all possible links are in yet, but 94 | you can consult the Index to find something. 95 | 96 |

Web home page

97 | 98 | My Web home page is 99 | http://www.susqu.edu/brakke/. 100 | Evolver-related material and links will be posted there. In 101 | particular, there are many examples of surfaces. 102 | 103 | 104 |
Back to top of Surface Evolver documentation. 105 |

106 | 107 | Author's home page. 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /doc/evolver.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | Surface Evolver Documentation 4 | 5 | 6 | 7 |

8 |

The Surface Evolver

9 | 10 | 11 | Kenneth A. Brakke
12 | Mathematics Department
13 | Susquehanna University
14 | Selinsgrove, PA, 17870
15 | brakke@susqu.edu
16 |

17 | with past support from
18 | The Geometry Center
19 | University of Minnesota
20 | Minneapolis, MN 55454
21 | 22 | 23 |

Version 2.30, January 1, 2008

24 |
25 |
26 |

Contents

27 | 28 | 29 | 30 | 60 | 61 | 89 | 90 |
31 | 59 | 62 | 88 |
91 | 92 | This HTML version of the Evolver documentation contains most of what 93 | the printed manual 94 | has, with the main exception of sections with a lot 95 | of mathematical formulas, such as the more advanced examples and the 96 | Techical Reference chapter. Not all possible links are in yet, but 97 | you can consult the Index to find something. 98 | 99 |

Web home page

100 | 101 | My Web home page is 102 | http://www.susqu.edu/brakke/. 103 | Evolver-related material and links will be posted there. In 104 | particular, there are many examples of surfaces. 105 | 106 | 107 |
Back to top of Surface Evolver documentation. 108 |

109 | 110 | Author's home page. 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /doc/addload_example.fe: -------------------------------------------------------------------------------- 1 | // addload_example.fe 2 | 3 | // Demonstration of using the addload command to load multiple 4 | // copies of the same file. Basic surface is that of mound.fe, 5 | // a liquid drop on a plane. 6 | // Each separate mound will have its own contact angle, implemented 7 | // by having a contact angle attribute for each edge. 8 | 9 | // The "setup" script below invokes addload multiple times on this same 10 | // datafile, moviing each instance to its appropriate location. 11 | // Note that addload does not execute the "read" section of a datafile, 12 | // so such "setup" scripts are ru only once. 13 | 14 | // Programmeer: Ken Brakke, brakke@susqu.edu 15 | 16 | define edge attribute angle real // interior angle between plane and surface, degrees 17 | 18 | gravity_constant 0 // start with gravity off 19 | 20 | #define WALLT (-cos(angle*pi/180)) // virtual tension of facet on plane 21 | 22 | constraint 1 /* the table top */ 23 | formula: x3 = 0 24 | energy: // for contact angle 25 | e1: -(WALLT*y) 26 | e2: 0 27 | e3: 0 28 | 29 | vertices 30 | 1 0.0 0.0 0.0 constraint 1 /* 4 vertices on plane */ 31 | 2 1.0 0.0 0.0 constraint 1 32 | 3 1.0 1.0 0.0 constraint 1 33 | 4 0.0 1.0 0.0 constraint 1 34 | 5 0.0 0.0 1.0 35 | 6 1.0 0.0 1.0 36 | 7 1.0 1.0 1.0 37 | 8 0.0 1.0 1.0 38 | 9 2.0 2.0 0.0 fixed /* for table top */ 39 | 10 2.0 -1.0 0.0 fixed 40 | 11 -1.0 -1.0 0.0 fixed 41 | 12 -1.0 2.0 0.0 fixed 42 | 43 | edges /* given by endpoints and attribute */ 44 | 1 1 2 constraint 1 /* 4 edges on plane */ 45 | 2 2 3 constraint 1 46 | 3 3 4 constraint 1 47 | 4 4 1 constraint 1 48 | 5 5 6 49 | 6 6 7 50 | 7 7 8 51 | 8 8 5 52 | 9 1 5 53 | 10 2 6 54 | 11 3 7 55 | 12 4 8 56 | 13 9 10 no_refine fixed /* for table top */ 57 | 14 10 11 no_refine fixed 58 | 15 11 12 no_refine fixed 59 | 16 12 9 no_refine fixed 60 | 61 | faces /* given by oriented edge loop */ 62 | 1 1 10 -5 -9 63 | 2 2 11 -6 -10 64 | 3 3 12 -7 -11 65 | 4 4 9 -8 -12 66 | 5 5 6 7 8 67 | 7 13 14 15 16 no_refine density 0 fixed /* table top for display */ 68 | 69 | bodies /* one body, defined by its oriented faces */ 70 | 1 1 2 3 4 5 volume 1 density 1 71 | 72 | read 73 | 74 | setup := { 75 | 76 | // Read in 3 x 3 arrangement of drops. The first has already been 77 | // read in, so we need to read in 8 more copies of this datafile. 78 | // We use a vertex attribute to distinguish between old and new 79 | // elements; for more elaborate massaging of new input you could 80 | // use more attributes on more types of elements. 81 | 82 | define vertex attribute load_marker integer; 83 | for ( row := 0 ; row < 3 ; row += 1 ) 84 | for ( col := 0 ; col < 3 ; col += 1 ) 85 | { if ( row > 0 or col > 0 ) then addload datafilename; 86 | // Move and mark vertices 87 | foreach vertex vv where load_marker == 0 do 88 | { vv.x += 2*row; 89 | vv.y += 2*col; 90 | vv.load_marker := 3*row+col+1; // different loads get different marks 91 | }; 92 | }; 93 | 94 | // Now assign contact angles to contact line edges 95 | foreach edge ee where on_constraint 1 do 96 | ee.angle := 90 + (ee.vertex[1].load_marker - 5)*10; 97 | 98 | } // end setup 99 | 100 | setup 101 | 102 | // From here on, we have the usual evolution commands 103 | 104 | re := {refine edges where on_constraint 1 } 105 | 106 | // Typical evolution 107 | gogo := { re; g 5; r; g 5; r; g 5; hessian; hessian; } 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /fe/addload_example.fe: -------------------------------------------------------------------------------- 1 | // addload_example.fe 2 | 3 | // Demonstration of using the addload command to load multiple 4 | // copies of the same file. Basic surface is that of mound.fe, 5 | // a liquid drop on a plane. 6 | // Each separate mound will have its own contact angle, implemented 7 | // by having a contact angle attribute for each edge. 8 | 9 | // The "setup" script below invokes addload multiple times on this same 10 | // datafile, moviing each instance to its appropriate location. 11 | // Note that addload does not execute the "read" section of a datafile, 12 | // so such "setup" scripts are ru only once. 13 | 14 | // Programmeer: Ken Brakke, brakke@susqu.edu 15 | 16 | define edge attribute angle real // interior angle between plane and surface, degrees 17 | 18 | gravity_constant 0 // start with gravity off 19 | 20 | #define WALLT (-cos(angle*pi/180)) // virtual tension of facet on plane 21 | 22 | constraint 1 /* the table top */ 23 | formula: x3 = 0 24 | energy: // for contact angle 25 | e1: -(WALLT*y) 26 | e2: 0 27 | e3: 0 28 | 29 | vertices 30 | 1 0.0 0.0 0.0 constraint 1 /* 4 vertices on plane */ 31 | 2 1.0 0.0 0.0 constraint 1 32 | 3 1.0 1.0 0.0 constraint 1 33 | 4 0.0 1.0 0.0 constraint 1 34 | 5 0.0 0.0 1.0 35 | 6 1.0 0.0 1.0 36 | 7 1.0 1.0 1.0 37 | 8 0.0 1.0 1.0 38 | 9 2.0 2.0 0.0 fixed /* for table top */ 39 | 10 2.0 -1.0 0.0 fixed 40 | 11 -1.0 -1.0 0.0 fixed 41 | 12 -1.0 2.0 0.0 fixed 42 | 43 | edges /* given by endpoints and attribute */ 44 | 1 1 2 constraint 1 /* 4 edges on plane */ 45 | 2 2 3 constraint 1 46 | 3 3 4 constraint 1 47 | 4 4 1 constraint 1 48 | 5 5 6 49 | 6 6 7 50 | 7 7 8 51 | 8 8 5 52 | 9 1 5 53 | 10 2 6 54 | 11 3 7 55 | 12 4 8 56 | 13 9 10 no_refine fixed /* for table top */ 57 | 14 10 11 no_refine fixed 58 | 15 11 12 no_refine fixed 59 | 16 12 9 no_refine fixed 60 | 61 | faces /* given by oriented edge loop */ 62 | 1 1 10 -5 -9 63 | 2 2 11 -6 -10 64 | 3 3 12 -7 -11 65 | 4 4 9 -8 -12 66 | 5 5 6 7 8 67 | 7 13 14 15 16 no_refine density 0 fixed /* table top for display */ 68 | 69 | bodies /* one body, defined by its oriented faces */ 70 | 1 1 2 3 4 5 volume 1 density 1 71 | 72 | read 73 | 74 | setup := { 75 | 76 | // Read in 3 x 3 arrangement of drops. The first has already been 77 | // read in, so we need to read in 8 more copies of this datafile. 78 | // We use a vertex attribute to distinguish between old and new 79 | // elements; for more elaborate massaging of new input you could 80 | // use more attributes on more types of elements. 81 | 82 | define vertex attribute load_marker integer; 83 | for ( row := 0 ; row < 3 ; row += 1 ) 84 | for ( col := 0 ; col < 3 ; col += 1 ) 85 | { if ( row > 0 or col > 0 ) then addload datafilename; 86 | // Move and mark vertices 87 | foreach vertex vv where load_marker == 0 do 88 | { vv.x += 2*row; 89 | vv.y += 2*col; 90 | vv.load_marker := 3*row+col+1; // different loads get different marks 91 | }; 92 | }; 93 | 94 | // Now assign contact angles to contact line edges 95 | foreach edge ee where on_constraint 1 do 96 | ee.angle := 90 + (ee.vertex[1].load_marker - 5)*10; 97 | 98 | } // end setup 99 | 100 | setup 101 | 102 | // From here on, we have the usual evolution commands 103 | 104 | re := {refine edges where on_constraint 1 } 105 | 106 | // Typical evolution 107 | gogo := { re; g 5; r; g 5; r; g 5; hessian; hessian; } 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /fe/rib.cmd: -------------------------------------------------------------------------------- 1 | // rib.cmd 2 | // Surface Evolver command to write RenderMan RIB file for surface 3 | // Usage: rib >>> "filename.rib" 4 | 5 | // This version does facets only, on a light blue background. 6 | // Viewpoint is the same as 's' command. Orthogonal projection. 7 | 8 | // Programmer: Ken Brakke, brakke@susqu.edu, http://www.susqu.edu/brakke 9 | 10 | rib := { 11 | printf"##RenderMan RIB-Structure 1.0\n"; 12 | printf "version 3.03\n"; 13 | printf "\n"; 14 | printf "Option \"searchpath\" \"shader\" [\".:../shaders:&\"]\n"; 15 | printf "Display \"%s.tif\" \"file\" \"rgba\"\n",datafilename; 16 | printf "Format 512 512 -1\n"; 17 | printf "PixelSamples 1 1\n"; 18 | printf "Orientation \"rh\"\n"; 19 | printf "Clipping 0.1 10.0\n"; 20 | printf "\n"; 21 | 22 | printf "WorldBegin\n"; 23 | printf "\n"; 24 | 25 | printf "Surface \"constant\"\n"; /* blue background */ 26 | printf "Color [ 0.3 0.8 1.0 ]\n"; 27 | printf "Polygon \"P\" [ 1 1 9 -1 1 9 -1 -1 9 1 -1 9]\n"; 28 | printf "\n"; 29 | 30 | printf "Translate 0 0 5 \n"; 31 | printf "Rotate 240 1 1 1 \n"; 32 | printf "Scale -1 1 1 \n"; 33 | printf "Scale .66667 .66667 .66667 \n"; 34 | printf "ConcatTransform [ %f %f %f %f\n", 35 | view_matrix[1][1],view_matrix[2][1],view_matrix[3][1],view_matrix[4][1]; 36 | printf " %f %f %f %f\n", 37 | view_matrix[1][2],view_matrix[2][2],view_matrix[3][2],view_matrix[4][2]; 38 | printf " %f %f %f %f\n", 39 | view_matrix[1][3],view_matrix[2][3],view_matrix[3][3],view_matrix[4][3]; 40 | printf " %f %f %f %f ]\n", 41 | view_matrix[1][4],view_matrix[2][4],view_matrix[3][4],view_matrix[4][4]; 42 | 43 | printf "LightSource \"ambientlight\" 1 \"intensity\" 0.30\n"; 44 | printf "LightSource \"distantlight\" 1 \"from\" [1 0 1] \"to\" [0 0 0] \"intensity\" 0.7\n"; 45 | printf "\n"; 46 | printf "AttributeBegin\n"; 47 | printf " Surface \"constant\"\n"; 48 | foreach facet ff do { 49 | if ( ff.color == CLEAR ) then continue; 50 | if ( ff.color == WHITE ) then printf " Color [ 1.0 1.0 1.0 ]\n" 51 | else if ( ff.color == WHITE ) then printf " Color [ 1.0 1.0 1.0 ]\n" 52 | else if ( ff.color == BLACK ) then printf " Color [ 0.0 0.0 0.0 ]\n" 53 | else if ( ff.color == BLUE ) then printf " Color [ 0.0 0.0 1. ]\n" 54 | else if ( ff.color == GREEN ) then printf " Color [ 0.0 1. 0.0 ]\n" 55 | else if ( ff.color == CYAN ) then printf " Color [ 0.0 1. 1. ]\n" 56 | else if ( ff.color == RED ) then printf " Color [ 1. 0.0 0.0 ]\n" 57 | else if ( ff.color == MAGENTA ) then printf " Color [ 1. 0.0 1. ]\n" 58 | else if ( ff.color == BROWN ) then printf " Color [ 1. 0.5 0. ]\n" 59 | else if ( ff.color == LIGHTGRAY ) then printf " Color [ .6 .6 .6 ]\n" 60 | else if ( ff.color == DARKGRAY ) then printf " Color [ .3 .3 .3 ]\n" 61 | else if ( ff.color == LIGHTBLUE ) then printf " Color [ .5 .5 1. ]\n" 62 | else if ( ff.color == LIGHTGREEN ) then printf " Color [ .5 1. .5 ]\n" 63 | else if ( ff.color == LIGHTCYAN ) then printf " Color [ .5 1. 1. ]\n" 64 | else if ( ff.color == LIGHTRED ) then printf " Color [ 1. .5 .5 ]\n" 65 | else if ( ff.color == LIGHTMAGENTA ) then printf " Color [ 1. .5 1. ]\n" 66 | else if ( ff.color == YELLOW ) then printf " Color [ 1. 1. .0 ]\n"; 67 | printf " Polygon \"P\" [ %f %f %f %f %f %f %f %f %f ]\n", 68 | ff.vertex[1].x,ff.vertex[1].y,ff.vertex[1].z, 69 | ff.vertex[2].x,ff.vertex[2].y,ff.vertex[2].z, 70 | ff.vertex[3].x,ff.vertex[3].y,ff.vertex[3].z; 71 | }; 72 | printf "AttributeEnd\n"; 73 | printf "\n"; 74 | printf "WorldEnd\n"; 75 | } 76 | -------------------------------------------------------------------------------- /man/man1/evolver.1: -------------------------------------------------------------------------------- 1 | .\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples. 2 | .\"See Also: 3 | .\"man mdoc.samples for a complete listing of options 4 | .\"man mdoc for the short list of editing options 5 | .\"/usr/share/misc/mdoc.template 6 | .Dd Mon May 19 2003 \" DATE 7 | .Dt Evolver 1 \" Program name and manual section number 8 | .Sh NAME \" Section Header - required - don't modify 9 | .Nm evolver 10 | .\" The following lines are read in generating the apropos(man -k) database. Use only key 11 | .\" words here as the database is built based on the words here and in the .ND line. 12 | .Nd The Surface Evolver, minimize energy of a surface 13 | .Sh SYNOPSIS \" Section Header - required - don't modify 14 | .Nm 15 | .Op Fl adehimqwxy \" [-adehimqwxy] 16 | .Op Fl f Ar file \" [-f file] 17 | .Op Fl pN \" [-pN] 18 | .Op Ar datafile \" Underlined argument - use .Ar anywhere to underline 19 | .Sh DESCRIPTION \" Section Header - required - don't modify 20 | The Surface Evolver is a program that minimizes the energy of a triangulated 21 | surface according to designated energies and constraints. This man page only 22 | documents command line options and environment variables. The full package 23 | and documentation are available at http://www.susqu.edu/brakke/evolver. 24 | .Pp \" Inserts a space 25 | Command line options: 26 | .Bl -tag -width -indent \" Differs from above in tag removed 27 | .It Ar datafile 28 | Text file defining a surface. If omitted, you will be prompted. 29 | .It Fl a 30 | Autoconvert to named quantities when needed (default is on); use "-a-" to 31 | deactivate autoconversion. 32 | .It Fl d 33 | Begin with parser debugging on (equivalent to "debug" runtime command). 34 | Beware of copious output. 35 | .It Fl e 36 | Echo stdin to stdout; meant for testing piped input. 37 | .It Fl f Ar file 38 | After loading datafile, read commands from 39 | .Ar file , 40 | then command line prompt. 41 | .It Fl h 42 | Print help for command line options. 43 | .It Fl i 44 | Preserve datafile numbers for element id's, rather than renumbering. 45 | .It Fl m 46 | Begin with memory debugging on (equivalent to "memdebug" runtime command). 47 | Beware of copious output. 48 | .It Fl pN 49 | Run with N concurrent processes. 50 | .It Fl q 51 | Convert to named quantities at start (equivalent to "convert_to_quantities" 52 | runtime command). 53 | .It Fl Q 54 | Suppress echoing of "read" section of datafile, and other files read in. 55 | .It Fl w 56 | Exit immediately after any warning or error message; meant for batch runs. 57 | .It Fl x 58 | Exit immediately after any error message; meant for batch runs. 59 | .It Fl y 60 | Break to user prompt after any warning message. 61 | .El \" Ends the list 62 | .Pp 63 | .\" .Sh ENVIRONMENT \" May not be needed 64 | .\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1 65 | .\" .It Ev ENV_VAR_1 66 | .\" Description of ENV_VAR_1 67 | .\" .It Ev ENV_VAR_2 68 | .\" Description of ENV_VAR_2 69 | .\" .El 70 | .Sh ENVIRONMENT VARIABLES 71 | .Bl -tag -width "EVOLVERPATH" -compact 72 | .It EVOLVERPATH 73 | Colon-separated list of paths automatically searched for datafiles, included 74 | files, or help documentation. 75 | .Sh FURTHER DOCUMENTATION 76 | See manual224.pdf in the Evolver distribution, browse evolver.htm in the 77 | doc subdirectory of the distribution, or browse the documentation on-line 78 | at http://www.susqu.edu/brakke/evolver/html/evolver.htm 79 | .Sh WEBSITE 80 | The Surface Evolver home page is http://www.susqu.edu/brakke/evolver. 81 | .Sh BUGS 82 | Send bug reports to brakke@susqu.edu. Please include the datafile and 83 | exact instructions for reproducing the problem. 84 | 85 | -------------------------------------------------------------------------------- /doc/news_10.htm: -------------------------------------------------------------------------------- 1 | 2 | Surface Evolver Documentation - Newsletter 10) 3 | 4 | 5 | 6 |

Surface Evolver Newsletter no. 10

7 | Back to top of Surface Evolver documentation. 8 |
 9 | 
10 | 
11 | 
12 |                       Surface Evolver Newsletter Number 10
13 |                               December 16, 1994
14 | 
15 |                     Editor: Ken Brakke, brakke@geom.umn.edu
16 | 
17 | Contents:
18 |   Query on curvature.
19 |   Version 1.97
20 | 
21 | 
22 | Query on curvature.
23 |   From Christian Burger <burger@pc1442.phys-chemie.uni-marburg.de>:
24 | 
25 |      I am interested in the investigation of physical systems which are
26 |      usually highly symmetric two-phase systems separated by an interface
27 |      which should be some kind of minimal surface. Very often, the systems
28 |      are bicontinuous, i.e., two unconnected 3D network domains live in a
29 |      common matrix of surrounding matter (I'm speaking in physical terms
30 |      here, not mathematical). Naturally, I'm using the evolver with the
31 |      torus model. The domains have defined volumes and are incompressible.
32 |      Physical examples for such systems are micro-emulsions,
33 |      polyelectrolyte-surfactant complexes, block copolymers, etc. It is
34 |      likely that curvature plays an important role for these systems. If the
35 |      structure unit building up the interface is not symmetric this leads to
36 |      a `spontaneous curvature', i.e., a finite H_ZERO in terms of evolver
37 |      nomenclature.  If you are aware of any work in this direction people 
38 |      have done so far using the evolver, I'd like to get some references on it.
39 | 
40 | Version 1.97:
41 | 
42 |  Version 1.97 is now available for ftp (except Mac version hasn't
43 |  been updated yet.)
44 | 
45 |  Changes from 1.96 are mostly a lot of obscure bug fixes.  But
46 |  there are some new features of general interest.
47 | 
48 |  New Hessian commands: "eigenprobe value" will print the number of
49 |  eigenvalues of the energy Hessian that are less than, equal to, and
50 |  greater than the given value.  It is OK to use an exact eigenvalue
51 |  (like 0, often) for the value.   Useful for probing stability.
52 |  "lanczos value" will do a little Lanczos algorithm and report
53 |  the 15 nearest approximate eigenvalues to the given value.  Do not
54 |  use an eigenvalue for the value! Not real polished yet.
55 | 
56 |  The default way of factoring the Hessian is with routines from the
57 |  Yale Sparse Matrix Package (YSMP), patched a bit to cope with zeroes
58 |  on the diagonal.  I've been tinkering around with my own version
59 |  of minimal degree factoring that is a little more aware of the
60 |  surface structure.  It can be activated by "ysmp off" and deactivated
61 |  by "ysmp on".  My version seems to have 10-20% less fill, and so
62 |  be a little faster.  It also seems to not have as many spurious
63 |  zeroes on the diagonal.  Further, in an attempt to cope with
64 |  indefinite Hessians, there is a toggle "bunch_kauffman" that enables
65 |  a version of Bunch-Kauffman factoring in my version.
66 | 
67 |  Certain named quantity attributes can now be referred to in expressions.
68 |  For quantity qqq, qqq.value is the current value, qqq.target is 
69 |  the constrained value, qqq.modulus is the same as the modulus in the
70 |  datafile definition, and qqq.pressure is the Lagrange multiplier
71 |  for a constrained quantity.  You can assign values to qqq.modulus
72 |  and qqq.target.
73 | 
74 |  The dump command 'd' now saves almost all toggle states (except some
75 |  debugging toggles) if not the default values.
76 | 
77 | 

78 | Back to top of Surface Evolver documentation. 79 | 80 | 81 | -------------------------------------------------------------------------------- /doc/column.fe: -------------------------------------------------------------------------------- 1 | // column.fe 2 | // Example of calculating forces exerted by a 3 | // column of liquid solder in shape of skewed catenoid. 4 | 5 | // All units cgs 6 | parameter RAD = 0.05 // ring radius 7 | parameter ZH = 0.08 // total height 8 | parameter SHIFT = 0.025 // shift 9 | #define SG 8 // specific gravity of solder 10 | #define TENS 460 // surface tension of solder 11 | #define GR 980 // acceleration of gravity 12 | 13 | gravity_constant GR 14 | 15 | BOUNDARY 1 PARAMETERS 1 16 | X1: RAD*cos(P1) 17 | X2: RAD*sin(P1) + SHIFT 18 | X3: ZH 19 | CONTENT // used to compensate for missing top facets 20 | c1: 0 21 | c2: ZH*x 22 | c3: 0 23 | ENERGY // used to compensate for gravitational energy under top facets 24 | e1: 0 25 | e2: SG*GR*ZH^2/2*x 26 | e3: 0 27 | 28 | BOUNDARY 2 PARAMETERS 1 29 | X1: RAD*cos(P1) 30 | X2: RAD*sin(P1) 31 | X3: 0 32 | 33 | vertices // given in terms of boundary parameter 34 | 1 0.00 boundary 1 fixed 35 | 2 pi/3 boundary 1 fixed 36 | 3 2*pi/3 boundary 1 fixed 37 | 4 pi boundary 1 fixed 38 | 5 4*pi/3 boundary 1 fixed 39 | 6 5*pi/3 boundary 1 fixed 40 | 7 0.00 boundary 2 fixed 41 | 8 pi/3 boundary 2 fixed 42 | 9 2*pi/3 boundary 2 fixed 43 | 10 pi boundary 2 fixed 44 | 11 4*pi/3 boundary 2 fixed 45 | 12 5*pi/3 boundary 2 fixed 46 | 47 | edges 48 | 1 1 2 boundary 1 fixed 49 | 2 2 3 boundary 1 fixed 50 | 3 3 4 boundary 1 fixed 51 | 4 4 5 boundary 1 fixed 52 | 5 5 6 boundary 1 fixed 53 | 6 6 1 boundary 1 fixed 54 | 7 7 8 boundary 2 fixed 55 | 8 8 9 boundary 2 fixed 56 | 9 9 10 boundary 2 fixed 57 | 10 10 11 boundary 2 fixed 58 | 11 11 12 boundary 2 fixed 59 | 12 12 7 boundary 2 fixed 60 | 13 1 7 61 | 14 2 8 62 | 15 3 9 63 | 16 4 10 64 | 17 5 11 65 | 18 6 12 66 | 67 | faces 68 | 1 -1 13 7 -14 density TENS 69 | 2 -2 14 8 -15 density TENS 70 | 3 -3 15 9 -16 density TENS 71 | 4 -4 16 10 -17 density TENS 72 | 5 -5 17 11 -18 density TENS 73 | 6 -6 18 12 -13 density TENS 74 | 75 | 76 | bodies 77 | 1 1 2 3 4 5 6 volume 0.00045 density SG 78 | 79 | read 80 | 81 | // horizontal force on upper pad by central differences 82 | dy := .0001 83 | do_yforce := { oldshift := shift; shift := shift + dy; 84 | set vertex y y+dy*z/zh; // uniform shear 85 | recalc; 86 | energy1 := total_energy - 87 | body[1].pressure*(body[1].volume - body[1].target); 88 | oldshift := shift; shift := shift - 2*dy; 89 | set vertex y y-2*dy*z/zh; // uniform shear 90 | recalc; 91 | energy2 := total_energy - 92 | body[1].pressure*(body[1].volume - body[1].target); 93 | yforce := -(energy1-energy2)/2/dy; 94 | printf "restoring force: %20.15f\n",yforce; 95 | // restore everything 96 | oldshift := shift; shift := shift + dy; 97 | set vertex y y+dy*z/zh; // uniform shear 98 | recalc; 99 | } 100 | 101 | // vertical force on upper pad by central differences. 102 | dz := .0001 103 | do_zforce := { oldzh := zh; zh := zh + dz; 104 | set vertex z z+dz*z/oldzh; recalc; // uniform stretch 105 | energy1 := total_energy - 106 | body[1].pressure*(body[1].volume - body[1].target); 107 | oldzh := zh; zh := zh - 2*dz; 108 | set vertex z z-2*dz*z/oldzh; recalc; // uniform stretch 109 | energy2 := total_energy - 110 | body[1].pressure*(body[1].volume - body[1].target); 111 | zforce := -(energy1-energy2)/2/dz; 112 | printf "vertical force: %20.15f\n",zforce; 113 | // restore everything 114 | oldzh := zh; zh := zh + dz; 115 | set vertex z z+dz*z/oldzh; recalc; // uniform stretch 116 | } 117 | 118 | // Sample evolution and force calculation 119 | gogo := { u; g 5; r; g 5 ; r; g 5; hessian; hessian; 120 | do_yforce; do_zforce; 121 | } 122 | -------------------------------------------------------------------------------- /fe/column.fe: -------------------------------------------------------------------------------- 1 | // column.fe 2 | // Example of calculating forces exerted by a 3 | // column of liquid solder in shape of skewed catenoid. 4 | 5 | // All units cgs 6 | parameter RAD = 0.05 // ring radius 7 | parameter ZH = 0.08 // total height 8 | parameter SHIFT = 0.025 // shift 9 | #define SG 8 // specific gravity of solder 10 | #define TENS 460 // surface tension of solder 11 | #define GR 980 // acceleration of gravity 12 | 13 | gravity_constant GR 14 | 15 | BOUNDARY 1 PARAMETERS 1 16 | X1: RAD*cos(P1) 17 | X2: RAD*sin(P1) + SHIFT 18 | X3: ZH 19 | CONTENT // used to compensate for missing top facets 20 | c1: 0 21 | c2: ZH*x 22 | c3: 0 23 | ENERGY // used to compensate for gravitational energy under top facets 24 | e1: 0 25 | e2: GR*ZH^2/2*x 26 | e3: 0 27 | 28 | BOUNDARY 2 PARAMETERS 1 29 | X1: RAD*cos(P1) 30 | X2: RAD*sin(P1) 31 | X3: 0 32 | 33 | vertices // given in terms of boundary parameter 34 | 1 0.00 boundary 1 fixed 35 | 2 pi/3 boundary 1 fixed 36 | 3 2*pi/3 boundary 1 fixed 37 | 4 pi boundary 1 fixed 38 | 5 4*pi/3 boundary 1 fixed 39 | 6 5*pi/3 boundary 1 fixed 40 | 7 0.00 boundary 2 fixed 41 | 8 pi/3 boundary 2 fixed 42 | 9 2*pi/3 boundary 2 fixed 43 | 10 pi boundary 2 fixed 44 | 11 4*pi/3 boundary 2 fixed 45 | 12 5*pi/3 boundary 2 fixed 46 | 47 | edges 48 | 1 1 2 boundary 1 fixed 49 | 2 2 3 boundary 1 fixed 50 | 3 3 4 boundary 1 fixed 51 | 4 4 5 boundary 1 fixed 52 | 5 5 6 boundary 1 fixed 53 | 6 6 1 boundary 1 fixed 54 | 7 7 8 boundary 2 fixed 55 | 8 8 9 boundary 2 fixed 56 | 9 9 10 boundary 2 fixed 57 | 10 10 11 boundary 2 fixed 58 | 11 11 12 boundary 2 fixed 59 | 12 12 7 boundary 2 fixed 60 | 13 1 7 61 | 14 2 8 62 | 15 3 9 63 | 16 4 10 64 | 17 5 11 65 | 18 6 12 66 | 67 | faces 68 | 1 -1 13 7 -14 density TENS 69 | 2 -2 14 8 -15 density TENS 70 | 3 -3 15 9 -16 density TENS 71 | 4 -4 16 10 -17 density TENS 72 | 5 -5 17 11 -18 density TENS 73 | 6 -6 18 12 -13 density TENS 74 | 75 | 76 | bodies 77 | 1 1 2 3 4 5 6 volume 0.00045 density SG 78 | 79 | read 80 | 81 | // horizontal force on upper pad by central differences 82 | dy := .0001 83 | do_yforce := { oldshift := shift; shift := shift + dy; 84 | set vertex y y+dy*z/zh; // uniform shear 85 | recalc; 86 | energy1 := total_energy - 87 | body[1].pressure*(body[1].volume - body[1].target); 88 | oldshift := shift; shift := shift - 2*dy; 89 | set vertex y y-2*dy*z/zh; // uniform shear 90 | recalc; 91 | energy2 := total_energy - 92 | body[1].pressure*(body[1].volume - body[1].target); 93 | yforce := -(energy1-energy2)/2/dy; 94 | printf "restoring force: %20.15f\n",yforce; 95 | // restore everything 96 | oldshift := shift; shift := shift + dy; 97 | set vertex y y+dy*z/zh; // uniform shear 98 | recalc; 99 | } 100 | 101 | // vertical force on upper pad by central differences. 102 | dz := .0001 103 | do_zforce := { oldzh := zh; zh := zh + dz; 104 | set vertex z z+dz*z/oldzh; recalc; // uniform stretch 105 | energy1 := total_energy - 106 | body[1].pressure*(body[1].volume - body[1].target); 107 | oldzh := zh; zh := zh - 2*dz; 108 | set vertex z z-2*dz*z/oldzh; recalc; // uniform stretch 109 | energy2 := total_energy - 110 | body[1].pressure*(body[1].volume - body[1].target); 111 | zforce := -(energy1-energy2)/2/dz; 112 | printf "vertical force: %20.15f\n",zforce; 113 | // restore everything 114 | oldzh := zh; zh := zh + dz; 115 | set vertex z z+dz*z/oldzh; recalc; // uniform stretch 116 | } 117 | 118 | // Sample evolution and force calculation 119 | gogo := { u; g 5; r; g 5 ; r; g 5; hessian; hessian; 120 | do_yforce; do_zforce; 121 | } 122 | -------------------------------------------------------------------------------- /src/symmetry.c: -------------------------------------------------------------------------------- 1 | /************************************************************* 2 | * This file is part of the Surface Evolver source code. * 3 | * Programmer: Ken Brakke, brakke@susqu.edu * 4 | *************************************************************/ 5 | 6 | /************************************************************* 7 | /* 8 | /* file: symmetry.c 9 | /* 10 | /* Purpose: Functions dealing with symmetries of surface. 11 | /* Has the three functions for torus. 12 | /* If user wants to define his/her own symmetry 13 | /* group, put your functions in this file, 14 | /* and change names right below here. But leave 15 | /* torus functions intact, so torus domain can 16 | /* be used. 17 | /* 18 | */ 19 | 20 | #include "include.h" 21 | 22 | /* change torus stuff in following lines to your own names */ 23 | char *symmetry_name = "torus"; /* name appearing in datafile. lowercase! */ 24 | #ifdef NOPROTO 25 | void torus_wrap(); /* declare */ 26 | WRAPTYPE torus_compose(); /* declare */ 27 | WRAPTYPE torus_inverse(); /* declare */ 28 | void (*sym_func)() = torus_wrap; /* set global pointer to function */ 29 | WRAPTYPE (*sym_compose)() = torus_compose; /* set global pointer to function */ 30 | WRAPTYPE (*sym_inverse)() = torus_inverse; /* set global pointer to function */ 31 | #else 32 | void torus_wrap(REAL*,REAL*,WRAPTYPE); /* declare */ 33 | WRAPTYPE torus_compose(WRAPTYPE,WRAPTYPE); /* declare */ 34 | WRAPTYPE torus_inverse(WRAPTYPE); /* declare */ 35 | void (*sym_func)(REAL*,REAL*,WRAPTYPE) = torus_wrap; 36 | WRAPTYPE (*sym_compose)(WRAPTYPE,WRAPTYPE) = torus_compose; 37 | WRAPTYPE (*sym_inverse)(WRAPTYPE) = torus_inverse; 38 | #endif 39 | 40 | /* 41 | Group elements are encoded in three-bit fields in "wrap", 42 | one for each dimension, with "001" for positive wrap 43 | and "011" for negative wrap. You are free to encode 44 | any way you want, but use wrap = 0 for the identity. 45 | */ 46 | 47 | #define ALLWRAPMASK 03333333333 48 | 49 | /******************************************************************* 50 | * 51 | * function: torus_wrap 52 | * 53 | * purpose: Provide adjusted coordinates for vertices that get 54 | * wrapped around torus. Serves as example for user-written 55 | * symmetry function. 56 | * 57 | * This function uses the values of the torus periods read 58 | * in from the data file. Yours doesn't have the privilege 59 | * of defining its own datafile syntax, but you can access 60 | * values of parameters defined in the datafile as 61 | * web.params[n].value. 62 | */ 63 | 64 | void torus_wrap(x,y,wrap) 65 | REAL *x; /* original coordinates */ 66 | REAL *y; /* wrapped coordinates */ 67 | WRAPTYPE wrap; /* encoded symmetry group element, 3 bits per dimension */ 68 | { 69 | int i,j; 70 | 71 | memcpy((char*)y,(char*)x,web.space_dimension*sizeof(REAL)); 72 | for ( i = 0 ; wrap != 0 ; i++, wrap >>= TWRAPBITS ) 73 | switch ( wrap & WRAPMASK ) 74 | { case 0: break; 75 | case POSWRAP: for ( j = 0 ; j < web.space_dimension ; j++ ) 76 | y[j] += web.torus_period[i][j]; 77 | break; 78 | case NEGWRAP: for ( j = 0 ; j < web.space_dimension ; j++ ) 79 | y[j] -= web.torus_period[i][j]; 80 | break; 81 | default: error("Unexpectedly large torus wrap.\n",WARNING); 82 | } 83 | } 84 | 85 | /******************************************************************** 86 | * 87 | * function: torus_compose() 88 | * 89 | * purpose: do composition of two group elements 90 | * 91 | */ 92 | 93 | WRAPTYPE torus_compose(wrap1,wrap2) 94 | WRAPTYPE wrap1,wrap2; /* the elements to compose */ 95 | { 96 | return (wrap1 + wrap2) & ALLWRAPMASK; 97 | } 98 | 99 | 100 | /******************************************************************** 101 | * 102 | * function: torus_inverse() 103 | * 104 | * purpose: return inverse of group element. 105 | * 106 | */ 107 | 108 | WRAPTYPE torus_inverse(wrap) 109 | WRAPTYPE wrap; /* the element invert */ 110 | { 111 | return ((~ALLWRAPMASK)-wrap) & ALLWRAPMASK; 112 | } 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /doc/news_06.htm: -------------------------------------------------------------------------------- 1 | 2 | Surface Evolver Documentation - Newsletter 6 3 | 4 | 5 | 6 |

Surface Evolver Newsletter no. 6

7 | Back to top of Surface Evolver documentation. 8 |
  9 | 
 10 | 
 11 |                       Surface Evolver Newsletter Number 6
 12 |                               December 16, 1993
 13 | 
 14 |                     Editor: Ken Brakke, brakke@geom.umn.edu
 15 | 
 16 | Contents:
 17 |   Kelvin's partition beaten
 18 |   Ftp directory changes
 19 |   New features of version 1.93
 20 |   Bibliography
 21 | 
 22 | 
 23 | 
 24 | Kelvin's partition beaten:
 25 | In 1887, Lord Kelvin posed the problem of finding the partition
 26 | of space into equal volume cells minimizing the interface area.
 27 | He suggested the cell shown in twointor.fe, which is basically
 28 | the voronoi cell for a bcc lattice.  Now Robert Phelan and Denis
 29 | Weaire of Trinity College, Dublin, have found a structure using
 30 | two types of cells that has 0.3% less area than Kelvin's. Their
 31 | Evolver datafile, phelan.fe, is now included in the Evolver package.
 32 | 
 33 | Ftp directory changes: 
 34 | 
 35 | Version 1.93 is now available for ftp.  Due to a
 36 | rearrangement of The Geometry Center's ftp directory, the path
 37 | is now  pub/software/evolver/evolver.tar.Z.  There is not a Mac
 38 | version of 1.93, as I do not have access to a Mac at the moment.
 39 | 
 40 | When you download, please check the date on the file and be sure
 41 | it is Dec. 16 or later.  I am sending this newsletter out before
 42 | the files actually get into the ftp directory, due to my travel plans.
 43 | 
 44 | Also the archive now unpacks into three subdirectories: src (source code),
 45 | doc (manual), and fe (sample datafiles).
 46 | 
 47 | New features:
 48 | 
 49 |  "history" command added to print command history.  Single-letter
 50 |   commands now included in history for convenience.  But history
 51 |   does not record responses to prompts commands may issue.
 52 | 
 53 |   Named quantities for scalar and vector integrands over edges and 
 54 |   facets added.  Method names are edge_scalar_integral,
 55 |   facet_scalar_integral, edge_vector_integral, and facte_vector_integral.
 56 |   Example use in datafile:
 57 | 
 58 |      quantity zweight info_only method facet_scalar_integral global
 59 |      scalar_integrand z^2
 60 | 
 61 |      quantity fvec energy method facet_vector_integral global
 62 |      vector_integrand
 63 |      q1: y^2
 64 |      q2: x*z 
 65 |      q3: y^4
 66 | 
 67 |   Quantity names may now be used as element attributes. Value
 68 |   of total quantity must be referred to as "total quantityname".
 69 | 
 70 |   Command repeat counts can now be expressions.
 71 | 
 72 |   More internal variables for counters on command events:
 73 |   equi_count, delete_count, notch_count, dissolve_count, pop_count, 
 74 |   where_count.  These can be used in queries to make actions
 75 |   depend on the outcome of previous equiangulation, delete, notch,
 76 |   dissolve, or pop commands, or to use the number of items satisfying
 77 |   the last where clause of a command.  These variables keep their
 78 |   values until the next command of the appropriate type.
 79 | 
 80 |   The manual index in 1.92 was slightly off in its page numbers.
 81 |   Fixed in current manual.
 82 | 
 83 |   DOS version has improved graphics.  Recognizes higher resolution
 84 |   and more colors.  See evolver.doc in evolver.zip.
 85 | 
 86 |   Can apply named quantities to elements with SET command. For
 87 |   example, if you have defined a named quantity, say pogo, for
 88 |   facets, you could do
 89 |      set facet quantity pogo where color == red
 90 |   Unset also works.  Of course, these commands do not apply to
 91 |   quantities declared global.
 92 | 
 93 | 
 94 | Bibliography
 95 | 
 96 |   D. Weaire and R. Phelan, "A counter-example to Kelvin's conjecture
 97 |   on minimal surfaces", preprint.
 98 | 
 99 |   X. Michalet, D. Bensimon,a nd B. Fourcade, "Fluctuating vesicles
100 |   of high topology", to appear in Physical Review Letters.
101 |   Uses Evolver with squared mean curvature energy to model
102 |   elastic cell membranes.
103 | 
104 | 
105 | Have a Merry Solstice and a Happy Perihelion!
106 | 
107 | End of Evolver Newsletter 6
108 | 

109 | Back to top of Surface Evolver documentation. 110 | 111 | 112 | -------------------------------------------------------------------------------- /doc/news_14.htm: -------------------------------------------------------------------------------- 1 | 2 | Surface Evolver Documentation - Newsletter 12 3 | 4 | 5 | 6 |

Surface Evolver Newsletter no. 14

7 | Back to top of Surface Evolver documentation. 8 |
  9 | 
 10 | 
 11 | 
 12 | 
 13 |                     Surface Evolver Newsletter Number 14
 14 |                               August 15, 1996
 15 | 
 16 |                    Editor: Ken Brakke, brakke@geom.umn.edu
 17 | 
 18 | Contents
 19 |   Version 2.01
 20 |   New features and changes
 21 |   Tetrahedralization
 22 |   grad/postdoc opening wanting Evolver experience
 23 | 
 24 | Version 2.01
 25 |   Surface Evolver version 2.01 is now available at
 26 |   http://www.geom.umn.edu/locate/evolver
 27 |   or by anonymous ftp from geom.umn.edu in /pub/software/evolver.
 28 |   This version is mostly bug fixes, but with a couple new features
 29 |   as listed below.
 30 | 
 31 |   There are new Mac 68K and Power PC versions in Evolver68K.sea.Hqx
 32 |   and EvolverPPC.sea.Hqx, respectively.  This is the first native
 33 |   Power PC version, and the first 68K update in a year.
 34 | 
 35 | New features and changes
 36 | 
 37 |   There is a new no_refine attribute for edges and facets.  It
 38 |   prevents edges from being subdivided by the 'r' command.
 39 |   Useful for large flat fixed surfaces or outlines.
 40 | 
 41 |   You can create new elements on the fly with new_vertex, new_edge,
 42 |   new_face, and new_body.  
 43 | 
 44 |   The V command has been tweaked to work better on constrained vertices.
 45 |   Also, there is a new command vertex_average to do individual
 46 |   vertex averaging on the vertices of your choice.
 47 | 
 48 |   Command output can be appended to a file using the >> redirection
 49 |   symbol, as in    { g 100; u; g 20 } >> "logfile"
 50 | 
 51 |   Equiangulation has been implemented for surfaces made of 3D
 52 |   simplices.
 53 | 
 54 |   The knot_energy method now uses "node_charge" vertex attribute
 55 |   for calculating its electrostatic-type energy.  Useful for
 56 |   spreading network graphs out in 3D.
 57 | 
 58 |   There is an experimental implementation dynamic link libraries for 
 59 |   functions used in constraints, boundaries, integrands, etc.
 60 |   This can replace interpreted functions with compiled functions
 61 |   for greater speed.
 62 |  
 63 |   DOS, Windows versions leaves alphanumeric escape sequences alone
 64 |   in quoted strings, so path names don't get mangled.
 65 |   
 66 |   The variables transform_expr and transform_count can be printed,
 67 |   so you can see the current state if you are using multiple
 68 |   image transforms.
 69 | 
 70 | Tetrahedralization.
 71 | 
 72 |   Some users are interested in constructing tetrahedral meshes
 73 |   of the inside of an Evolver surface, e.g. for doing stress
 74 |   analysis on solidified solder.  I've put together a set of
 75 |   programs that does this, which those interested may get by
 76 |   anonymous ftp from geom.umn.edu as /priv/brakke/tetra.tar.
 77 | 
 78 | Research Opportunity wanting Evolver experience:
 79 | 
 80 | 
 81 | 	Project:  3-D Imaging of Flexible Polyurethane Foam
 82 | 
 83 | 	   -  Advisers:  Xiaodaong Zhang and Professor Chris Macosko
 84 | 		         (Chemical Engineering and Material Science)
 85 | 
 86 | 	   -  Goals:     To image foam using laser confocal microscopy and 
 87 | 	 	         other methods and use existing software 
 88 | 			 (such as Koros, Surface Evolver) or create 
 89 | 			 algorithms to size foam cells
 90 | 	
 91 | 	*  Graduate assistant or Postdoctoral salary level
 92 | 
 93 | 	*  Potential for industrial interaction
 94 | 
 95 | 	*  Desired qualifications:
 96 | 	   -  Strong math skills (particularly geometry)
 97 | 	   -  Works well with computers (programming not necessary)
 98 | 	   -  Experience with image processing and UNIX
 99 |               (desirable but not necessary)
100 | 
101 | 	*  For further information, please contact Xiaodong Zhang
102 |            (send resume to apply):
103 | 	     Dept. of Chemical Engineering and Materials Science
104 | 	     University of Minnesota
105 | 	     151 Admundson Hall
106 | 	     421 Washington Avenue SE
107 | 	     Minneapolis, MN 55455
108 | 	     Phone:  625-8573
109 | 	     E-mail:  zhan0063@maroon.tc.umn.edu 
110 | 
111 | 
112 | 

113 | Back to top of Surface Evolver documentation. 114 | 115 | 116 | -------------------------------------------------------------------------------- /fe/knotty.fe: -------------------------------------------------------------------------------- 1 | // knotty.fe 2 | // Evolver data for 3,2 torus knot (trefoil) with various knot energies. 3 | 4 | // You need to set one type of energy and one type of length constraint; 5 | // see the set_* commands in the "read" section of the datafile. 6 | // Not all combinations are workable. 7 | 8 | string // this is a 1D surface 9 | parameter maj_r = 2 // torus major radius 10 | parameter min_r = 0.5 // torus minor radius 11 | 12 | boundary 1 parameter 1 // parametric curve around torus 13 | x1: cos(2*p1)*(maj_r + min_r*cos(3*p1)) 14 | x2: sin(2*p1)*(maj_r + min_r*cos(3*p1)) 15 | x3: min_r*sin(3*p1) 16 | 17 | // Here follow six different types of energy. Switch between them 18 | // with the set_* commands in the bottom section of this datafile. 19 | 20 | // elastic bending energy, i.e. squared curvature 21 | quantity bending_energy ENERGY modulus 0 method sqcurve_string global 22 | 23 | // conducting wire vertex energy 24 | quantity conduct_energy ENERGY modulus 1 method knot_energy global 25 | 26 | // insulating wire vertex energy 27 | quantity insul_energy ENERGY modulus 0 method edge_knot_energy global 28 | 29 | // Greg Buck's 1/(d1+d2+d3+d4-2(L1+L2)) energy 30 | quantity buck_energy ENERGY modulus 0 method buck_knot_energy global 31 | // have to start with modulus 0 since edges too long at start */ 32 | 33 | // Greg Buck's normal projection energy 34 | quantity proj_energy ENERGY modulus 0 method proj_knot_energy global 35 | 36 | // Peter Doyle's conformal circle energy 37 | quantity circle_energy ENERGY modulus 0 method circle_knot_energy global 38 | 39 | // Here follow three ways to control the length of edges. 40 | // Switch between them with the set_* commands below. 41 | 42 | // Elastic stretching energy to encourage edges to all have the same length. 43 | // Use "hooke_length := value" command to set hooke_length to desired 44 | // edge length 45 | quantity hooke ENERGY modulus 0 method hooke_energy global 46 | 47 | // Individually set edge equilibrium lengths. 48 | // Use "set edge hooke_size expr" to set desired edge lengths 49 | // When used, the modulus needs to be set high, like 1000 or 10000, 50 | // to provide decent stiffness. 51 | define edge attribute hooke_size real 52 | quantity hooke2 ENERGY modulus 0 method hooke2_energy global 53 | 54 | // to keep total length fixed 55 | quantity knot_length FIXED = 24 modulus 1 method edge_tension global 56 | 57 | vertices 58 | 1 0.0*pi boundary 1 59 | 2 0.2*pi boundary 1 60 | 3 0.4*pi boundary 1 61 | 4 0.6*pi boundary 1 62 | 5 0.8*pi boundary 1 63 | 6 1.0*pi boundary 1 64 | 7 1.2*pi boundary 1 65 | 8 1.4*pi boundary 1 66 | 9 1.6*pi boundary 1 67 | 10 1.8*pi boundary 1 68 | edges 69 | 1 1 2 boundary 1 70 | 2 2 3 boundary 1 71 | 3 3 4 boundary 1 72 | 4 4 5 boundary 1 73 | 5 5 6 boundary 1 74 | 6 6 7 boundary 1 75 | 7 7 8 boundary 1 76 | 8 8 9 boundary 1 77 | 9 9 10 boundary 1 78 | 10 10 1 boundary 1 79 | 80 | read // some initialization commands 81 | r 2 // refining twice produces 40 vertices 82 | unset vertices boundary 1 // release from parametric curve 83 | unset edges boundary 1 84 | set edge tension 0 // get rid of default tension energy 85 | set edge color white where id <= edge_count/2 // dashed coloring 86 | 87 | // Set all quantity moduli to zero 88 | zero_moduli := { 89 | bending_energy.modulus := 0; 90 | conduct_energy.modulus := 0; 91 | insul_energy.modulus := 0; 92 | buck_energy.modulus := 0; 93 | proj_energy.modulus := 0; 94 | circle_energy.modulus := 0; 95 | } 96 | 97 | // Set up individual types of energy 98 | set_bending := { zero_moduli; bending_energy.modulus := 1; } 99 | set_conduct := { zero_moduli; conduct_energy.modulus := 1; } 100 | set_insul := { zero_moduli; insul_energy.modulus := 1; } 101 | set_buck := { zero_moduli; buck_energy.modulus := 1; } 102 | set_proj := { zero_moduli; proj_energy.modulus := 1; } 103 | set_circle := { zero_moduli; circle_energy.modulus := 1; } 104 | 105 | // Set up type of length constraint 106 | hooke_length := total_length/edge_count; 107 | set edge hooke_size total_length/edge_count; 108 | set_length := { fix knot_length; hooke.modulus := 0; hooke2.modulus := 0; } 109 | set_hooke := { unfix knot_length; hooke.modulus := 1000; hooke2.modulus := 0; } 110 | set_hooke2 := { unfix knot_length; hooke.modulus := 0; hooke2.modulus := 1000; } 111 | 112 | // Sample evolution 113 | gogo := { g 50; U; g 50; } 114 | -------------------------------------------------------------------------------- /src/zoom.c: -------------------------------------------------------------------------------- 1 | /************************************************************* 2 | * This file is part of the Surface Evolver source code. * 3 | * Programmer: Ken Brakke, brakke@susqu.edu * 4 | *************************************************************/ 5 | 6 | /****************************************************************** 7 | * 8 | * File: zoom.c 9 | * 10 | * Contents: Routines to zoom in on vertex. 11 | * 12 | */ 13 | 14 | #include "include.h" 15 | 16 | /****************************************************************** 17 | * 18 | * Function: zoom_vertex() 19 | * 20 | * Purpose: Zoom in on a vertex by chopping off everything beyond 21 | * a given distance and fixing in place the jagged edges. 22 | */ 23 | 24 | void zoom_vertex(v_id,radius) 25 | vertex_id v_id; /* vertex to zoom on */ 26 | REAL radius; /* cutoff distance from v_id */ 27 | { 28 | vertex_id vv_id; 29 | edge_id e_id; 30 | facet_id f_id; 31 | facetedge_id fe_id,next,prev; 32 | int i; 33 | 34 | if ( (web.bodycount != 0) && (web.representation == SOAPFILM) ) 35 | kb_error(1540,"Zoom is not implemented for bodies.\n",RECOVERABLE); 36 | 37 | if ( radius <= 0.0 ) 38 | kb_error(1541,"Must have positive cut-off radius.\n",RECOVERABLE); 39 | 40 | if ( !valid_id(v_id) || !valid_element(v_id) ) 41 | { sprintf(errmsg,"Vertex %s is not valid.\n",ELNAME(v_id)); 42 | kb_error(1542,errmsg,RECOVERABLE); 43 | } 44 | 45 | /* eliminate all vertices beyond cutoff */ 46 | FOR_ALL_VERTICES(vv_id) 47 | { 48 | if ( distance(v_id,vv_id) > radius ) 49 | set_attr(vv_id,DISSOLVED); 50 | } 51 | 52 | /* eliminate all edges connected to gone vertices */ 53 | FOR_ALL_EDGES(e_id) 54 | { int val_head,val_tail; 55 | 56 | val_tail = !(get_vattr(get_edge_tailv(e_id)) & DISSOLVED); 57 | val_head = !(get_vattr(get_edge_headv(e_id)) & DISSOLVED); 58 | if ( !val_head || !val_tail ) 59 | { if (val_head) 60 | { set_attr(get_edge_headv(e_id),FIXED); 61 | } 62 | if (val_tail) 63 | { set_attr(get_edge_tailv(e_id),FIXED); 64 | } 65 | set_attr(e_id,DISSOLVED); 66 | } 67 | } 68 | 69 | /* eliminate all facets verging on gone edges */ 70 | FOR_ALL_FACETS(f_id) 71 | { 72 | fe_id = get_facet_fe(f_id); 73 | for ( i = 0 ; i < FACET_EDGES ; i++ ) 74 | { if ( get_eattr(get_fe_edge(fe_id)) & DISSOLVED ) 75 | { set_attr(f_id,DISSOLVED); 76 | break; 77 | } 78 | fe_id = get_next_edge(fe_id); 79 | } 80 | } 81 | 82 | /* eliminate all facet-edges on gone facets */ 83 | FOR_ALL_FACETEDGES(fe_id) 84 | { 85 | e_id = get_fe_edge(fe_id); 86 | if ( get_eattr(e_id) & DISSOLVED ) 87 | { set_attr(fe_id,DISSOLVED); continue; } 88 | f_id = get_fe_facet(fe_id); 89 | if ( valid_id(f_id) && (get_fattr(f_id) & DISSOLVED) ) 90 | { /* have kept edge on removed facet */ 91 | /* patch up ragged edges */ 92 | next = get_next_facet(fe_id); 93 | prev = get_prev_facet(fe_id); 94 | if ( equal_id(next,fe_id) ) 95 | { /* was only facet on edge */ 96 | set_edge_fe(e_id,NULLFACETEDGE); 97 | } 98 | else 99 | { /* close ranks */ 100 | set_next_facet(prev,next); 101 | set_prev_facet(next,prev); 102 | set_edge_fe(e_id,next); 103 | } 104 | 105 | if ( web.representation == SOAPFILM) 106 | { 107 | /* fix edge in place */ 108 | set_attr(e_id,FIXED); 109 | set_attr(get_edge_tailv(e_id),FIXED); 110 | set_attr(get_edge_headv(e_id),FIXED); 111 | } 112 | set_attr(fe_id,DISSOLVED); 113 | } 114 | } 115 | FOR_ALL_VERTICES(v_id) 116 | if ( get_vattr(v_id) & DISSOLVED ) free_element(v_id); 117 | FOR_ALL_EDGES(e_id) 118 | if ( get_eattr(e_id) & DISSOLVED ) free_element(e_id); 119 | FOR_ALL_FACETS(f_id) 120 | if ( get_fattr(f_id) & DISSOLVED ) free_element(f_id); 121 | FOR_ALL_FACETEDGES(fe_id) 122 | if ( get_attr(fe_id) & DISSOLVED ) free_element(fe_id); 123 | 124 | } 125 | 126 | 127 | -------------------------------------------------------------------------------- /doc/twointor.htm: -------------------------------------------------------------------------------- 1 | 2 | Surface Evolver Documentation - Torus Example 3 | 4 |
5 |

6 | Surface Evolver Documentation

7 |
8 | Back to top of Surface Evolver documentation. 9 | Index. 10 | 11 | 12 |

Example: Torus partitioned into two cells (Kelvin's foam) 13 |

14 | 15 | This example has a flat 3-torus (i.e. periodic boundary conditions) 16 | divided into two bodies. The unit cell is 17 | a unit cube, and the surface has the topology of Kelvin's partitioning of 18 | space into tetrakaidecahedra [TW], which 19 | was the least area partitioning of space into equal volumes known until 20 | recently [WP]. 21 |

22 | The datafile handles the 23 | wrapping of edges around the torus by specifying for each direction whether 24 | an edge wraps positively (+), negatively (-), or not at all (*). 25 |

26 | Note the use of the keyword TORUS_FILLED in the datafile. 27 | This informs Evolver that one of the volume constraints is redundant, 28 | preventing a singular matrix when the time comes to enforce volume 29 | constraints. One could use just TORUS and only put on one 30 | volume constraint. 31 |

32 | The display of a surface in a torus can be done several ways. 33 | The connected 34 | command (my favorite) makes each body show as a single unit. 35 | The clipped 36 | command shows the surface clipped to the fundamental 37 | parallelpiped. The raw_cells 38 | command shows the unedited surface. 39 |

40 | The Weaire-Phelan structure 41 | [WP]. 42 | is in the datafile phelanc.fe. 43 | It has area 0.3% less than Kelvin's. 44 | 45 | 46 | 47 | 49 | 52 | 53 |
48 | twointor The initial two-cell Kelvin shape. Note that due to 50 | periodidity, a single vertex or edge may appear 51 | multiple times in the image.
54 | 55 | 56 |

 57 | // twointor.fe
 58 | // Two Kelvin tetrakaidecahedra in a torus.
 59 | 
 60 | TORUS_FILLED   // signals that domain is a torus and bodies fill it.
 61 | 
 62 | periods
 63 | 1.000000 0.000000 0.000000
 64 | 0.000000 1.000000 0.000000
 65 | 0.000000 0.000000 1.000000
 66 | 
 67 | vertices // values from another program
 68 | 1  0.499733 0.015302 0.792314
 69 | 2  0.270081 0.015548 0.500199
 70 | 3  0.026251 0.264043 0.500458
 71 | 4  0.755123 0.015258 0.499302
 72 | 5  0.026509 0.499036 0.794636
 73 | 6  0.500631 0.015486 0.293622
 74 | 7  0.025918 0.750639 0.499952
 75 | 8  0.499627 0.251759 0.087858
 76 | 9  0.256701 0.499113 0.087842
 77 | 10 0.026281 0.500286 0.292918
 78 | 11 0.500693 0.765009 0.086526
 79 | 12 0.770240 0.499837 0.087382
 80 | 
 81 | edges // with wraps in axis directions
 82 | 1    1 2  * * *    
 83 | 2    2 3  * * *
 84 | 3    1 4  * * *
 85 | 4    3 5  * * *
 86 | 5    2 6  * * *
 87 | 6    2 7  * - *
 88 | 7    1 8  * * +
 89 | 8    4 6  * * *
 90 | 9    5 9  * * +
 91 | 10   3 10 * * *
 92 | 11   3 4  - * *
 93 | 12   6 8  * * *
 94 | 13   6 11 * - *
 95 | 14   7 4  - + *
 96 | 15   8 12 * * *
 97 | 16   9 8  * * *
 98 | 17   9 11 * * *
 99 | 18   10 7 * * *
100 | 19   11 1 * + -
101 | 20   12 5 + * -
102 | 21   5 7  * * *
103 | 22  11 12 * * *
104 | 23  10 12 - * *
105 | 24   9 10 * * *
106 | 
107 | faces
108 | 1    1 2 4 9 16 -7 
109 | 2    -2 5 12 -16 24 -10 
110 | 3    -4 10 18 -21 
111 | 4    7 15 20 -4 11 -3 
112 | 5    -1 3 8 -5 
113 | 6    6 14 -11 -2 
114 | 7    5 13 -17 24 18 -6 
115 | 8    -12 13 19 7 
116 | 9    -16 17 22 -15 
117 | 10   -10 11 8 12 15 -23 
118 | 11   -21 9 17 19 1 6 
119 | 12   -14 -18 23 -22 -13 -8 
120 | 13   -24 -9 -20 -23 
121 | 14   -19 22 20 21 14 -3 
122 | 
123 | bodies
124 | 1    -1 -2 -3 -4 -5 9 7 11 -9 10 12 5 14 3 volume 0.500
125 | 2     2 -6 -7 8 -10 -12 -11 -13 1 13 -14 6 4 -8 volume 0.500
126 | 
127 | 
128 | Doing some refining and iterating will show that the optimal shape 129 | is curved a bit. 130 |
131 | Spinning ring example. 132 | Back to top of tutorial. 133 |
134 | Back to top of Evolver documentation. 135 | Index. 136 | 137 | 138 | 139 | -------------------------------------------------------------------------------- /doc/news_09.htm: -------------------------------------------------------------------------------- 1 | 2 | Surface Evolver Documentation - Newsletter 9 3 | 4 | 5 | 6 |

Surface Evolver Newsletter no. 9

7 | Back to top of Surface Evolver documentation. 8 |
  9 | 
 10 | 
 11 |                       Surface Evolver Newsletter Number 9
 12 |                               September 30, 1994
 13 | 
 14 |                     Editor: Ken Brakke, brakke@geom.umn.edu
 15 | 
 16 | Version 1.96 is now available.
 17 | 
 18 | New features:
 19 | 
 20 |    Indexing can be done on element generators in commands.  That is, you
 21 |    can say "list vertex[23]" instead of "list vertex where id==23".
 22 |    The new syntax avoids searching through the entire element list for just
 23 |    one element. You can also apply indices to component elements, as
 24 |    in "foreach edge ee do print ee.vertex[1].id".  Component elements are
 25 |    accessed by linear search through a list, but the list is usually short.
 26 |    Remember indices start at 1.
 27 | 
 28 |    Named quantities can be composed of arbitrary functions of method instances,
 29 |    instead of just sums.  The keyword "function" indicates this.  Example:
 30 |    method_instance inst_1 method edge_length global
 31 |    method_instance inst_2 method vertex_scalar_integral global
 32 |    scalar_integrand x^2-y*z
 33 |    quantity comp energy function inst_1^2 + sin(inst_2)
 34 | 
 35 |    Named quantities may refer to element attributes in expressions for
 36 |    integrands. This can give more discriminating control over quantities
 37 |    on different elements, by using facet densities in integrands for
 38 |    example.  This feature is especially useful with `extra' attributes,
 39 |    which are added completely under the user's control.
 40 | 
 41 |    Hessian: Newton's Method can greatly accelerate convergence to a minimum,
 42 |    but users of the "hessian" command know that one has to be extremely
 43 |    close to the minimum before the command works.  This is largely due
 44 |    to motions tangential to the surface as the triangulation rearranges itself.
 45 |    There is now a toggle "hessian_normal" that constrains motion to be along
 46 |    the surface normal (volume gradient, to be precise).  Points without
 47 |    a well-defined normal (such as along triple junctions or at tetrahedral
 48 |    points) are not constrained.
 49 | 
 50 |    More Hessian: Some experimental stuff using the Hessian matrix can be
 51 |    accessed with the command "hessian_menu".  This brings up a menu of
 52 |    various things.  Some of the more interesting: choice E will find the
 53 |    lowest eigenvalue and corresponding eigenvector.  Useful at a saddle
 54 |    point.  After E, use choice S to move along eigenvector direction to minimum
 55 |    energy.  Choice P finds the number of eigenvalues above and below
 56 |    a value.
 57 | 
 58 |    The command "saddle" will seek lowest energy along the lowest eigenvalue's
 59 |    eigenvector, without the need to go into hessian_menu.
 60 | 
 61 |    Conjugate gradient now does the Polak-Ribiere variety of the algorithm as
 62 |    the default.  Seems to work much better than the previous Fletcher-Reeves
 63 |    variety, especially in automatically restarting itself when it gets in
 64 |    trouble.
 65 | 
 66 |    Users can send geomview commands through Evolver.  Syntax:
 67 |    geomview "command"
 68 |    Example:
 69 |    geomview "(transform mound mound Camera rotate 1 0 0)"
 70 |    Useful in scripts to have geomview save frames for a movie.
 71 | 
 72 |    The gravity-setting 'G' command now takes a numerical argument instead of 
 73 |    a repetition count.  So "G 5" sets gravity to 5 instead of producing 5
 74 |    gravity prompts.
 75 | 
 76 |    The name of the current datafile can be referred to in commands as
 77 |    `datafilename' wherever a string can be used.  See next item.
 78 | 
 79 |    sprintf, printf now accept string arguments, but a string pointer is pushed
 80 |    as 8 bytes on the calling stack to C's sprintf, so %s in format string should 
 81 |    be followed by %0.0s to dispose of the second half.  Example:  
 82 |    printf "This is %s%0.0s with total energy %f\n",datafilename,total_energy
 83 | 
 84 |    The print command also accepts strings. Example: print datafilename
 85 | 
 86 |    'Extra' attributes now inherited for same type element.  That is, edges
 87 |    formed from subdividing an edge will inherit its extra attributes.
 88 | 
 89 |    Added 'jiggle' toggle command, and jiggle_temperature internal variable.
 90 | 
 91 |    Added total_time internal variable. Settable also.
 92 | 
 93 | 
 94 | End of newsletter 9.
 95 | 
 96 | 

97 | Back to top of Surface Evolver documentation. 98 | 99 | 100 | -------------------------------------------------------------------------------- /fe/povray.cmd: -------------------------------------------------------------------------------- 1 | // povray.cmd 2 | 3 | // Surface Evolver command for producing POV-Ray input file. 4 | // Usage: 5 | // Use the "show edge where ..." command to declare which 6 | // edges are to be depicted as thin cylinders. 7 | // Set "edge_radius" to desired radius of edge cylinders. 8 | // Run "povray" and redirect to desired file, e.g. 9 | // Enter command: povray >>> "something.pov" 10 | 11 | // Programmer: Ken Brakke, brakke@susqu.edu, http://www.susqu.edu/brakke 12 | 13 | edge_radius := 0.003; // adjust this for desired radius of edge cylinders 14 | povray := { 15 | printf "// %s in POV-Ray format.\n\n",datafilename; 16 | 17 | printf "light_source { <0,0,300> color rgb <1,1,1> }\n"; 18 | printf "light_source { <100,0,0> color rgb <1,1,1> }\n"; 19 | printf "camera { location <12,0,0> sky <0,0,1> // right handed \n"; 20 | printf " up <0,0,1> right <1.3,0,0> look_at <0,0,0> angle 15 }\n"; 21 | printf "background { color <0.3,0.8,1.0> } // light blue\n\n"; 22 | printf "// Textures corresponding to Evolver colors\n\n"; 23 | 24 | printf "#declare t_black = texture { pigment { rgb <0.0,0.0,0.0> }}\n"; 25 | printf "#declare t_blue = texture { pigment { rgb <0.0,0.0,1.,> }}\n"; 26 | printf "#declare t_green = texture { pigment { rgb <0.0,1.,0.0,> }}\n"; 27 | printf "#declare t_cyan = texture { pigment { rgb <0.0,1.,1.,> }}\n"; 28 | printf "#declare t_red = texture { pigment { rgb <1.,0.0,0.0,> }}\n"; 29 | printf "#declare t_magenta = texture { pigment { rgb <1.,0.0,1.,> }}\n"; 30 | printf "#declare t_brown = texture { pigment { rgb <1.,0.5,0.,> }}\n"; 31 | printf "#declare t_lightgray = texture { pigment { rgb <.6,.6,.6,> }}\n"; 32 | printf "#declare t_darkgray = texture { pigment { rgb <.3,.3,.3,> }}\n"; 33 | printf "#declare t_lightblue = texture { pigment { rgb <.3,.8,1.,> }}\n"; 34 | printf "#declare t_lightgreen = texture { pigment { rgb <.5,1.,.5,> }}\n"; 35 | printf "#declare t_lightcyan = texture { pigment { rgb <.5,1.,1.,> }}\n"; 36 | printf "#declare t_lightred = texture { pigment { rgb <1.,.5,.5,> }}\n"; 37 | printf "#declare t_lightmagenta = texture { pigment { rgb <1.,.5,1.,> }}\n"; 38 | printf "#declare t_yellow = texture { pigment { rgb <1.,1.,.0,> }}\n"; 39 | printf "#declare t_white = texture { pigment { rgb <1.,1.,1.,> }}\n"; 40 | 41 | printf "\n//One overall object.\n"; 42 | printf "union {\n"; 43 | printf "// All facets in one big mesh object for efficiency.\n"; 44 | printf " mesh { \n"; 45 | foreach facet ff do { 46 | printf " triangle { <%f,%f,%f>,<%f,%f,%f>,<%f,%f,%f> texture {", 47 | ff.vertex[1].x,ff.vertex[1].y,ff.vertex[1].z, 48 | ff.vertex[2].x,ff.vertex[2].y,ff.vertex[2].z, 49 | ff.vertex[3].x,ff.vertex[3].y,ff.vertex[3].z; 50 | if ( ff.color == white ) then printf " t_white " 51 | else if ( ff.color == black ) then printf " t_black " 52 | else if ( ff.color == blue) then printf " t_blue " 53 | else if ( ff.color == green ) then printf " t_green " 54 | else if ( ff.color == cyan ) then printf " t_cyan " 55 | else if ( ff.color == red ) then printf " t_red " 56 | else if ( ff.color == magenta ) then printf " t_magenta " 57 | else if ( ff.color == brown ) then printf " t_brown " 58 | else if ( ff.color == lightgray ) then printf " t_lightgray " 59 | else if ( ff.color == darkgray ) then printf " t_darkgray " 60 | else if ( ff.color == lightblue ) then printf " t_lightblue " 61 | else if ( ff.color == lightgreen ) then printf " t_lightgreen " 62 | else if ( ff.color == lightcyan ) then printf " t_lightcyan " 63 | else if ( ff.color == lightred ) then printf " t_lightred " 64 | else if ( ff.color == lightmagenta ) then printf " t_lightmagenta " 65 | else if ( ff.color == yellow ) then printf " t_yellow "; 66 | printf " } }\n"; 67 | }; 68 | printf " } // end of mesh object\n"; 69 | 70 | // Do desired edges 71 | printf "#declare edge_radius = %f;\n",edge_radius; 72 | foreach edge ee where ee.show do 73 | { printf "cylinder { <%f,%f,%f>,<%f,%f,%f> edge_radius texture { t_black } }\n", 74 | ee.vertex[1].x,ee.vertex[1].y,ee.vertex[1].z, 75 | ee.vertex[2].x,ee.vertex[2].y,ee.vertex[2].z; 76 | }; 77 | 78 | // Windup 79 | printf "// overall viewing transformation\n"; 80 | printf " matrix < %f,%f,%f,\n", 81 | view_matrix[1][1],view_matrix[2][1],view_matrix[3][1]; 82 | printf " %f,%f,%f,\n", 83 | view_matrix[1][2],view_matrix[2][2],view_matrix[3][2]; 84 | printf " %f,%f,%f,\n", 85 | view_matrix[1][3],view_matrix[2][3],view_matrix[3][3]; 86 | printf " %f,%f,%f>\n", 87 | view_matrix[1][4],view_matrix[2][4],view_matrix[3][4]; 88 | printf " } // end of all objects\n"; 89 | } 90 | 91 | 92 | -------------------------------------------------------------------------------- /doc/news_04.htm: -------------------------------------------------------------------------------- 1 | 2 | Surface Evolver Documentation - Newsletter 4 3 | 4 | 5 | 6 |

Surface Evolver Newsletter no. 4

7 | Back to top of Surface Evolver documentation. 8 |
  9 | 
 10 | 
 11 | 		      Surface Evolver Newsletter Number 4
 12 | 			      May 28, 1993
 13 | 
 14 |                     Editor: Ken Brakke, brakke@geom.umn.edu
 15 | 
 16 | Contents:
 17 | 
 18 | New features
 19 | Bibliography
 20 | 
 21 | Version 1.91 now available. New features:
 22 | 
 23 |       The two sides of a facets can have different colors. 'COLOR'
 24 |       applies to both sides, 'FRONTCOLOR' and 'BACKCOLOR'
 25 |       to different sides, according to the orientation inherited
 26 |       from the datafile. Example:
 27 | 	"set facet backcolor red"
 28 | 
 29 |       Attributes of individual named elements can be set inside
 30 |       loops, i.e. "foreach facet ff do set ff color red"
 31 |       does the same as "set facet color red".
 32 | 
 33 |       To reduce need for explicit line-splicing on long commands,
 34 |       the parser now keeps track of depth of brace and parenthesis
 35 |       nesting, and will call for more input if a line ends inside nest.
 36 |       So if you want to type a multiline command, start with '{'
 37 |       and end with '}' many lines later.  Also does auto line-splicing 
 38 |       if certain tokens are last token in line (such as '+'), but it
 39 |       is wiser to enclose with braces rather than count on this.  
 40 | 
 41 |       Queries can run through edges and facets adjacent to
 42 |       a vertex, and facets of a body, as in "list vertices vv
 43 |       where max(vv.facet,color==red) > 0".
 44 | 
 45 |       New attributes: Valence attribute has been extended to vertices
 46 |       and bodies.  Vertex valence is the number of edges on
 47 |       a vertex.  Body valence is the number of facets on the
 48 |       body (edges in the string model). Example:
 49 |       "list vertices where valence == 4"
 50 | 
 51 |       Surface area can be minimized by minimizing Dirichlet integral,
 52 |       according to a scheme of Polthier and Pinkall.  Command 'dirichlet'.
 53 |       Not a replacement for other evolutions.
 54 | 
 55 |       Using a command from the history list now echoes it.
 56 | 
 57 |       Improved NeXT terminal interface.  -u option for no graphics,
 58 |       -t for terminal and graphics.
 59 | 
 60 |       Command assignment fixed to assign only one command.
 61 |       so "ggg := g; g" will be the same as "{ggg := g}; g"
 62 |       and not "ggg := {g;g}".
 63 | 
 64 |       Every time a command changed a global variable, the surface
 65 |       was being recalculated.  This slowed down scripts immensely.
 66 |       So now the only variables that cause recalculation are
 67 |       1) adjustable parameters defined in the datafile
 68 |       2) quantity moduli and parameters
 69 |       You can turn off even this with "autorecalc off".
 70 | 
 71 |       "view_4d" command to toggle sending full 4D coordinates
 72 |       to geomview.  Default is OFF.
 73 | 
 74 | 
 75 | Bibliography:
 76 | 
 77 |       Alice Underwood, "Constructing barriers to minimal surfaces from
 78 |       polyhedral data," Ph.D. thesis, Princeton, 1993.
 79 | 
 80 |          When the Evolver reaches a minimum area for a given triangulation
 81 |       of a surface, can you guarantee that there is a smooth minimal
 82 |       surface nearby?  This thesis proves some sufficient conditions.
 83 |       You have to be able to "blow" on the surface and still have it
 84 |       stable.  The triangulation must be well-behaved.  Unfortunately,
 85 |       the estimates are far from the best possible (I hope!), and one
 86 |       needs on the order of 10^7 to apply the proof.
 87 | 
 88 |       Ken Brakke, "Stability of a toroidal bubble in a rotating tank."
 89 | 
 90 | 	 This is the final report of an Evolver project I did for Lockheed.
 91 |       A tank of liquid helium is rotating in weightlessness.  The tank
 92 |       has a rod along the axis of rotation.  The tank is partially full,
 93 |       and the bubble is supposed to form an axisymmetric torus so the center
 94 |       of mass is on the axis.  The questions are: what is the rotation rate
 95 |       needed to force a spherical bubble to form a torus, and what is the
 96 |       minimum rotation rate at which the torus is stable against breaking 
 97 |       up into a sphere?  This is not an official publication of anybody,
 98 |       but copies are available to anybody interested.
 99 | 
100 |       Hans Mittelmann, "Symmetric Capillary Surfaces in a Cube",
101 |       Math. Comp. Simul. 35 (1993), 139-152.  (reference update)
102 | 
103 | 
104 | End of Evolver Newsletter 4
105 | 
106 | 

107 | Back to top of Surface Evolver documentation. 108 | 109 | 110 | -------------------------------------------------------------------------------- /doc/news_13.htm: -------------------------------------------------------------------------------- 1 | 2 | Surface Evolver Documentation - Newsletter 12 3 | 4 | 5 | 6 |

Surface Evolver Newsletter no. 13

7 | Back to top of Surface Evolver documentation. 8 |
  9 | 
 10 | 
 11 | 
 12 | 
 13 |                     Surface Evolver Newsletter Number 13
 14 |                               April 30, 1996
 15 | 
 16 |                    Editor: Ken Brakke, brakke@geom.umn.edu
 17 | 
 18 | Contents
 19 |   Version 2.00 released
 20 |   New Features
 21 |   Minor backward compatibilities
 22 |   Request for web links
 23 |   Bibliography
 24 | 
 25 | Version 2.00 released
 26 | 
 27 |   Version 2.00 is now available from geom.umn.edu by ftp, or from
 28 |   http://www.geom.umn.edu/software/download/evolver/evolver.html, or from 
 29 |   my own home page, http://www.susqu.edu/facstaff/b/brakke/evolver/evolver.htm.
 30 |   The version number is 2.00 mostly because the last version was 1.99.
 31 |   No big rewrite, but there are some major new features.
 32 | 
 33 |   Anybody who happened to get a pre-release version 2.00, dated before
 34 |   April 30, should get the official release, as there have been a few
 35 |   bug fixes.
 36 | 
 37 | New features
 38 | 
 39 |   There are now versions for Windows-95 and Windows-NT.
 40 | 
 41 |   Much of the manual has been translated into HTML form, which
 42 |   can be browsed with standard Web browsers.  I've only tested
 43 |   it with Netscape, and I don't make any guarantees about how
 44 |   other browsers will do. But it's mostly just basic text.  No
 45 |   pictures or fancy graphics yet.
 46 | 
 47 |   The Evolver has a "help" command which will print extracts
 48 |   from the HTML files, based on keyword.
 49 | 
 50 |   Error and warning messages are numbered.  Someday there may be
 51 |   helpful documentation of all the error messages, but for now the
 52 |   numbers are useful to me to pinpoint the exact error.
 53 |   
 54 |   For precision freaks, higher-order Lagrange elements have been
 55 |   added (LINEAR is Lagrange order 1, QUADRATIC is Lagrange order 2).
 56 | 
 57 |   Also for precision freaks, if you compile with -DLONGDOUBLE then
 58 |   all floating point calculations will be in your system's
 59 |   long double type, which may provide up to 30 significant digits.
 60 | 
 61 |   There is a "postscript" command that prints postscript files 
 62 |   without asking you any questions.  Various toggles control the
 63 |   options.
 64 | 
 65 |   The distribution has a bunch of sample command files.  One is
 66 |   "vrml.cmd", which writes a VRML file suitable for your web site.
 67 | 
 68 |   The "interp_bdry_param" toggle causes boundary parameters to be
 69 |   interpolated rather than extrapolated when refining an edge.
 70 | 
 71 |   The 'X' command shows the dictionary of extra attributes, including
 72 |   those used internally.
 73 | 
 74 |   There is a "return" command for exiting the current command, or causing
 75 |   a subcommand to return to its parent command.
 76 | 
 77 |   When using the -q option (which converts everything to named quantities),
 78 |   only the user's explicitly defined quantities are shown by the 'A' and
 79 |   'v' commands.  The "show_all_quantities" toggle will cause those commands
 80 |   to list all quantities.
 81 |   
 82 | Minor backward compatibilities
 83 | 
 84 |   Fixed facets, edges, and vertices are now included when calculating 
 85 |   energies and areas.
 86 | 
 87 |   Evolver now enforces in the datafile the rule that all variable names 
 88 |   must be at least two characters.
 89 | 
 90 |   The term "variable_parameter", introduced in version 1.99, has been
 91 |   replaced by the more descriptive term "optimizing_parameter".
 92 | 
 93 |   There have been some changes in the internal workings of the 'g'
 94 |   command that might cause slightly different numerical values. 
 95 | 
 96 | Request for web links
 97 | 
 98 |   If you have web pages relevant to the Surface Evolver, please let
 99 |   me know.  One site with several Evolver examples involving liquid
100 |   solder is http://www.ctcms.nist.gov/programs/solder/.
101 | 
102 | Bibliography
103 | 
104 |   Xavier Michalet and David Bensimon, "Observation of stable
105 |   shapes and conformal diffusion in genus 2 vesicles",
106 |   Science, vol. 269 (4 Aug 1995), 666-668.
107 |   Tests hypothesis that some cell membranes are shaped by
108 |   an elastic bending energy (i.e. squared mean curvature)
109 |   by comparing Evolver surfaces to actual vesicles.
110 | 
111 |   R. Phelan, D. Weaire, and K. Brakke, "Computation of equilibrium
112 |   foam structures using the Surface Evolver", Experimental Mathematics,
113 |   vol. 4 no. 3 (1995), 181-192.  Discusses foam structures that beat
114 |   Kelvin's tetrakaidecahedral foam, including the now-famous
115 |   Weaire-Phelan structure.  Also describes the stability of the 
116 |   structures as liquid is added to form Plateau borders.  Color pictures.
117 | 
118 | 

119 | Back to top of Surface Evolver documentation. 120 | 121 | 122 | -------------------------------------------------------------------------------- /doc/intro.htm: -------------------------------------------------------------------------------- 1 | 2 | Surface Evolver Documentation 3 | 4 | 5 | 6 |
7 |

8 | Surface Evolver Documentation

9 |
10 | Back to top of Surface Evolver documentation. 11 | Index. 12 | 13 |

14 | Surface Evolver Overview

15 | 16 |

General description

17 | 18 | The Surface Evolver is an interactive program for the study of 19 | surfaces shaped by surface tension and other 20 | energies, and subject 21 | to various constraints. A 22 | surface is implemented as a simplicial complex, that is, a union 23 | of triangles. The user defines an initial surface in a datafile. The 24 | Evolver evolves the surface toward minimal energy by a gradient 25 | descent method. The aim can be to find a minimal energy surface, 26 | or to model 27 | the process of evolution by mean curvature, which was studied 28 | in [B1] for surface tension energy in the context of varifolds 29 | and geometric measure theory. The energy in the Evolver can be 30 | a combination of 31 | surface tension, gravitational energy, squared mean curvature, 32 | user-defined surface integrals, or knot energies. The Evolver can handle 33 | arbitrary topology (as seen in real soap bubble clusters), 34 | volume constraints, boundary constraints, boundary contact 35 | angles, prescribed mean curvature, crystalline integrands, 36 | gravity, and constraints expressed as surface integrals. The 37 | surface can be in an ambient space of arbitrary dimension, which 38 | can have a Riemannian metric, and the ambient space can be a 39 | quotient space under a group action. The user can interactively 40 | modify the surface to change its properties or to keep the 41 | evolution well-behaved. The Evolver was written for one and two 42 | dimensional surfaces, but it can do higher dimensional surfaces 43 | with some restrictions on the features available. Graphical 44 | output is available as screen graphics and in several file 45 | formats, including PostScript. 46 |

47 | The Surface Evolver program is freely 48 | available 49 | and is in use by a number of researchers. Some of the 50 | applications of the Evolver so far include modelling the shape 51 | of fuel in rocket tanks in low gravity [Te], calculating areas 52 | for the Opaque Cube Problem [B4], computing capillary surfaces 53 | in cubes [MH] and in exotic containers [C], simulating grain 54 | growth [FT] 55 | [WM], studying grain boundaries pinned by 56 | inclusions, finding partitions of space more efficient 57 | than Kelvin's tetrakaidecahedra [WP] 58 | [KS1], 59 | foam rheology [KR1] 60 | [KR2], 61 | sphere eversion [FS], 62 | modelling the shape of molten solder on 63 | microcircuits [RSB], studying polymer chain packing, modelling 64 | cell membranes [MB], and classifying minimal surface singularities. 65 |

66 | The strength of the Surface Evolver program is in the breadth 67 | of problems it handles, rather than optimal treatment of some 68 | specific problem. It is under continuing development, and 69 | users are invited to suggest new features. 70 |

71 | This manual contains full operational details. 72 | A journal article description of the Evolver 73 | appeared in [B2]. 74 |

75 |

Portability

76 | The Evolver is written in portable C and has been run 77 | on several systems: Sun, Silicon Graphics, HP, Dec, MS-DOS, 78 | Macintosh, and various MS-Windows versions. It is meant to be easily portable to any 79 | system that has C. 80 |

81 |

Acknowledgements

82 | The Evolver was written as part of the Geometry Supercomputing 83 | Project (later 84 | The Geometry Center, now defunct), 85 | sponsored by the National Science Foundation, the Department 86 | of Energy, Minnesota Technology, Inc., and the University of 87 | Minnesota. The program is available free of charge. 88 |

89 |


90 | Back to top of Surface Evolver documentation. 91 | Index. 92 |
93 | 94 | Author's home page. 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /fe/xray.cmd: -------------------------------------------------------------------------------- 1 | // xray.cmd 2 | 3 | // Produces xray image of a 3D wet foam. Calculates liquid content on 4 | // grid of probe lines. Plateau borders are detected as bounded by 5 | // facets with less than 2/3 of the maximum facet tension. 6 | // Outputs a PostScript file to stdout with a grid of grayscale pixels. 7 | // Usage: set xgridsize and ygridsize to the desired resolution, 8 | // i.e. pixels across and down and give the command 9 | // xray >>> "filename.ps" 10 | // The xray command will calculate the bounding box of the surface itself. 11 | // Works in torus or non-torus mode. In torus mode, everything will 12 | // automatically be wrapped back to the unit cell, so you don't have 13 | // to worry about that. 14 | 15 | // Programmer: Ken Brakke, brakke@susqu.edu, http://www.susqu.edu/brakke 16 | 17 | xgridsize := 100 // xgridsize x ygridsize grid 18 | ygridsize := 100 19 | 20 | 21 | xray := { 22 | local xx,yy,jitterx,jittery,minx,miny,maxx,maxy,tension_cutoff; 23 | local dx,dy,ax,ay,az,bx,by,bz,cx,cy,cz,hix,hiy,lox,loy,maxi,maxj; 24 | local mini,minj,fsign,xyarea,ii,jj,area1,area2,area3,maxr,xpts,ypts; 25 | 26 | define results real[xgridsize][ygridsize]; 27 | for ( xx := 1 ; xx <= xgridsize ; xx += 1 ) 28 | for ( yy := 1 ; yy <= ygridsize ; yy += 1 ) 29 | results[xx][yy] := 0.0; // clean out old results 30 | 31 | // random offsets to prevent edge effects */ 32 | jitterx := 0.5213414312341; 33 | jittery := 0.4934129768877; 34 | 35 | /* box to map results to */ 36 | if torus then 37 | { // assumes orthogonal fundamental region 38 | minx := 0; 39 | miny := 0; 40 | maxx := torus_periods[1][1]; 41 | maxy := torus_periods[2][2]; 42 | tension_cutoff := max(facet,tension)*2/3; // do only Plateau borders 43 | } 44 | else 45 | { minx := min(vertex,x); 46 | maxx := max(vertex,x); 47 | miny := min(vertex,y); 48 | maxy := max(vertex,y); 49 | tension_cutoff := 100000; // do all facets 50 | }; 51 | 52 | dx := (maxx-minx)/xgridsize; 53 | dy := (maxy-miny)/ygridsize; 54 | 55 | foreach facet ff where tension < tension_cutoff do 56 | { ax := ff.vertex[1].x; 57 | ay := ff.vertex[1].y; 58 | az := ff.vertex[1].z; 59 | bx := ax + ff.edge[1].x; // let Evolver take care of unwrapping 60 | by := ay + ff.edge[1].y; 61 | bz := az + ff.edge[1].z; 62 | cx := bx + ff.edge[2].x; // let Evolver take care of unwrapping 63 | cy := by + ff.edge[2].y; 64 | cz := bz + ff.edge[2].z; 65 | // get bounding box to find possible grid points 66 | hix := (ax > bx) ? (ax > cx ? ax : cx) : (bx > cx ? bx : cx); 67 | hiy := (ay > by) ? (ay > cy ? ay : cy) : (by > cy ? by : cy); 68 | lox := (ax < bx) ? (ax < cx ? ax : cx) : (bx < cx ? bx : cx); 69 | loy := (ay < by) ? (ay < cy ? ay : cy) : (by < cy ? by : cy); 70 | // compact to integers 71 | maxi := floor(hix/dx-jitterx); 72 | maxj := floor(hiy/dy-jittery); 73 | mini := ceil(lox/dx-jitterx); 74 | minj := ceil(loy/dy-jittery); 75 | // loop among possible values 76 | fsign := ff.z > 0 ? 1 : -1; 77 | xyarea := 2*abs(ff.z); 78 | for ( ii := mini ; ii <= maxi ; ii += 1 ) 79 | for ( jj := minj ; jj <= maxj ; jj += 1 ) 80 | { // test inclusion 81 | xx := ii*dx + dx*jitterx; yy := jj*dy + dy*jittery; 82 | area1 := fsign*((ax-xx)*(by-yy) - (bx-xx)*(ay-yy)); 83 | area2 := fsign*((bx-xx)*(cy-yy) - (cx-xx)*(by-yy)); 84 | area3 := fsign*((cx-xx)*(ay-yy) - (ax-xx)*(cy-yy)); 85 | if ( (area1 > 0) and (area2 > 0) and (area3 > 0) ) then 86 | { results[(ii imod xgridsize)+1][(jj imod ygridsize)+1] += 87 | fsign*(area1*cz + area2*az + area3*bz)/xyarea; 88 | } 89 | } 90 | }; 91 | if ( torus ) then 92 | { // correct results for wrap in z 93 | for ( ii := 1 ; ii <= xgridsize ; ii += 1 ) 94 | for ( jj := 1 ; jj <= ygridsize ; jj += 1 ) 95 | results[ii][jj] := results[ii][jj] mod torus_periods[3][3]; 96 | }; 97 | 98 | // map to range 0,1 99 | maxr := 0; 100 | for ( ii := 1 ; ii <= xgridsize ; ii += 1 ) 101 | for ( jj := 1 ; jj <= ygridsize ; jj += 1 ) 102 | if results[ii][jj] > maxr then maxr := results[ii][jj]; 103 | if maxr > 0 then 104 | for ( ii := 1 ; ii <= xgridsize ; ii += 1 ) 105 | for ( jj := 1 ; jj <= ygridsize ; jj += 1 ) 106 | results[ii][jj] /= maxr; 107 | 108 | /* output results in postscript format, making low density white */ 109 | xpts := 500; ypts := 500; // point size of image 110 | // using kludges to get %% stuff to print right on Windows and Unix 111 | printf "%!"; printf"PS-Adobe-3.0 EPSF-3.0\n"; 112 | printf "%%"; printf"BoundingBox: 0 0 %d %d\n",xpts,ypts; 113 | printf "%%"; printf"Creator: Surface Evolver xray.cmd\n"; 114 | printf "%%"; printf"EndComments\n\n"; 115 | printf "%f %f scale\n",xpts/xgridsize,ypts/ygridsize; 116 | printf "/px { newpath setgray moveto 1 0 rlineto 0 1 rlineto -1 0 rlineto closepath fill} def\n"; 117 | for ( ii := 0 ; ii < xgridsize ; ii += 1 ) 118 | for ( jj := 0 ; jj < ygridsize ; jj += 1 ) 119 | { printf "%f %f %f px\n",ii,jj,(1-results[ii+1][jj+1]); 120 | }; 121 | printf "\nshowpage\n"; 122 | printf "\n%%"; printf"EOF\n"; 123 | } 124 | 125 | 126 | -------------------------------------------------------------------------------- /doc/tutorial.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Surface Evolver tutorial 5 | 6 | 7 | 8 |
9 |

10 | Surface Evolver Documentation

11 |
12 | Back to top of Surface Evolver documentation. 13 | Index. 14 | 15 | 16 |

Surface Evolver Tutorial

17 | To get started using the Surface Evolver, read the Basic Concepts 18 | section for a quick introduction, then try the examples. 19 | Many more examples can be found at the 20 | 21 | Evolver Examples Web Page 22 | 31 |
32 | 33 |

Basic Concepts

34 | 35 | The basic geometric elements used to represent a surface 36 | are vertices, edges, facets, and bodies. 37 | Vertices are points in space. 38 | Edges are straight line segments joining pairs of vertices. 39 | Facets are flat triangles bounded by three edges. A surface 40 | is a union of facets. (Actually, there is no separate surface 41 | entity in the program; all facets belong to one 42 | logical surface.) A body is defined by giving its bounding 43 | facets.

44 | 45 | The term "surface", when used to refer to the entity upon 46 | which the Evolver operates, refers to all the geometric 47 | elements plus auxiliary data such as constraints, boundaries, 48 | and forces.

49 | 50 | There are no limitations on how 51 | many edges may share a vertex nor on how many facets may 52 | share an edge. Thus arbitrary topologies are possible, 53 | including the triple junctions of surfaces characteristic 54 | of soap films.

55 | 56 | Edges and facets are oriented for bookkeeping purposes, 57 | but there are no restrictions on the orientation of 58 | neighboring facets. Unoriented surfaces are thus possible.

59 | 60 | A surface is deemed to have a total energy, arising 61 | from surface tension, gravitational energy, and possibly 62 | other sources. It is this energy which the Evolver 63 | minimizes.

64 | 65 | No particular units of measurement are used. The program 66 | only deals with numerical values. If you wish to relate 67 | the program values to the real world, then all values 68 | should be within one consistent system, such as cgs or mks.

69 | 70 | The initial surface is specified in a text file (hereafter 71 | referred to as the datafile) that may be created with any 72 | standard text editor. 73 | (The .fe extension I always use for datafiles stands for 74 | facet-edge, which refers to the internal data structure 75 | used to represent the surface. You may use any name 76 | you wish for a datafile.)

77 | 78 | The basic operation of the Evolver is to read in a 79 | datafile and take commands from the user. The main 80 | command prompt is 81 |

 82 |      Enter command:
 83 | 
84 | The most common commands are one letter (case is significant 85 | for these), sometimes 86 | with a numerical parameter. The most frequently used commands 87 | are: 88 |
 89 |      g n     do n iterations  ('g' is for 'go')
 90 |      r       refine the triangulation of surface 
 91 |      P       graphics output (option 8 for geomview, option 3 for PostScript)
 92 |      s       show surface on screen (Evolver's own simple graphics)
 93 |      q       quit 
 94 | 
95 | There is also a more elaborate command language (in which case is 96 | not significant). 97 | Commands must be followed with the ENTER key; Evolver only reads 98 | complete lines.

99 | 100 | An iteration is one evolution step. The motion for 101 | the step is calculated as follows: First, the force 102 | on each vertex is calculated from the gradient of the 103 | total energy of the surface as a function of the position 104 | of that vertex. The force gives the direction of motion. 105 | Second, the force is made to conform to whatever 106 | constraints are applicable. Third, the actual 107 | motion is found by multiplying the force by a global 108 | scale factor.

109 |


110 | Cube example. 111 | Back to top of tutorial. 112 |
113 | Back to top of Evolver documentation. 114 | Index. 115 | 116 | 117 | --------------------------------------------------------------------------------