
/*************************************************************
*  This file is part of the Surface Evolver source code.     *
*  Programmer:  Ken Brakke, brakke@geom.umn.edu              *
*************************************************************/


/*****************************************************************
*
*  File: eval_sec.c
*
*  Purpose: To evaluate first and second derivatives of expressions
*      
*/

/* Here starts include.h */
/*************************************************************
*  This file is part of the Surface Evolver source code.     *
*  Programmer:  Ken Brakke, brakke@geom.umn.edu              *
*************************************************************/


/* Precision */
#ifdef LONGDOUBLE
#define REAL  long double 
#define DOT   dot 
#define DWIDTH ((sizeof(REAL)==16) ? 35 : 22)
#define DPREC ((sizeof(REAL)==16) ? 32 : 19)
#else
#ifdef FLOAT
#define REAL float
#define DOT  dotf
#define v3d  v3f
#define v2d  v2f  
#else 
#define REAL  double 
#define DOT   dot 
#endif
#endif

/* for things we really want to be plain double */
#define DOUBLE double

#ifdef LINUX
#include <stdio.h>
#include <setjmp.h>
/* PATHCHAR is name-separating character in paths */
#define PATHCHAR '/'
/* ENVPATHCHAR is the path separating character in environment strings */
#define ENVPATHCHAR ":"
#define FCAST (int(*)(const void*,const void *))
#endif

typedef int DY_OFFSET ;


/**********************************************************************
*
*  File: model.h
*
*  Header file for evolver.  Defines model parameters.
*
*/

#ifdef SDIM
#define DEFAULT_SDIM SDIM
#ifndef MAXCOORD
#define MAXCOORD SDIM
#endif
#if SDIM==2
#define SDIM_dot(x,y)  ((x)[0]*(y)[0] + (x)[1]*(y)[1])
#else
#if SDIM==3
#define SDIM_dot(x,y)  ((x)[0]*(y)[0] + (x)[1]*(y)[1] + (x)[2]*(y)[2])
#else
#define SDIM_dot(x,y)  dot(x,y,SDIM)
#endif
#endif
#else
#define SDIM web.sdim
#define SDIM_dot(x,y)  dot(x,y,SDIM)
#define DEFAULT_SDIM 3
#endif

/* maximum number of shared memory processors */
#ifdef SGI_MULTI
#define MAXPROCS 50
#else
#define MAXPROCS 1
#endif

/* maximum dimensionality */
#ifndef MAXCOORD
#define MAXCOORD 4
#endif

#define MAXCTRL ( (MAXCOORD>5) ? (MAXCOORD+1) : 6)
/* MAXPARAM is maximum number of boundary parameters. Must be
   at most MAXCOORD since is saved in same space by save_coord(). */
#define MAXPARAM MAXCOORD
#define MAXCONSTR (MAXCOORD+2)
#define MAXWDIM 2
#define EDGE_VERTS 2
#define FACET_VERTS 3
#define FACET_EDGES 3
#define MAXINST 10
#define MAXEXTRA 20

/* model types for web.modeltype */
#define LINEAR    1
#define QUADRATIC 2
#define LAGRANGE  3

/* Quadratic model point counts */
/* Control points per edge */
#define EDGE_CTRL  3
/* Control points per facet */
#define FACET_CTRL 6
/* Integration points per edge */
#define EDGE_INTERP  3
/* Integration points per facet */
#define FACET_INTERP 7

/* quadratic interpolation coefficients */
/* partials of interpolation polynomials at midpoints of patch edges */
/* control points are numbered 0 to 5 counterclockwise */
/* midpoints are numbered 0 to 2 counterclockwise after control pt 0 */
/* dip[midpoint][control point][partial]  */

extern REAL dip[3][FACET_CTRL][2];

/* Histogram size */
#define HISTO_BINS 40 
#define HISTO_BINSIZE (1/M_LN2)
/* End of model.h */

/*************************************************************
*  This file is part of the Surface Evolver source code.     *
*  Programmer:  Ken Brakke, brakke@geom.umn.edu              *
*************************************************************/


/********************************************************************
*
*  File: storage.h
*
*  Purpose:  Header file defining details of storage implementation.
*            All machine-dependent gory details should be here
*            (for inclusion in other source files that need to know)
*            or in storage.c (purely private details).
*
*     This version has element ids typed as longs.
*     Also implements id as offset from element base.
*     All elements of same type in one memory block, extended 
*      as needed.  To be used on at least 32 bit machines.
*/

/* using offset as id is 15% faster overall than using ordinal */

#define OFFSET_ID_x
#define INDIRECT_ID
#define NEW_EXTRA
#define BLOCKWISE

#ifdef NOBLOCKWISE
  Error: Now committed to BLOCKWISE and INDIRECT_ID
#endif

#if defined(BLOCKWISE) && !defined(INDIRECT_ID)
  Error: BLOCKWISE needs INDIRECT_ID
#endif

#define NUMELEMENTS 5

/* these values used for identification and as index into skeleton info */
#define  VERTEX  0
#define  EDGE    1
#define  FACET   2
#define  BODY    3
#define  FACETEDGE    4 

#ifdef xelement
/*****************************************************************
*
*  Universal element identifier.  Don't want to use straight
*  pointer since base changes when realloced.
*  (not actually used; just for documentation)
*/

typedef struct xelement_id {
    unsigned int  type : 3;   /* see enum below */
    unsigned int  valid: 1;   /* valid id bit */
    unsigned int  sign : 1;   /* set for reverse orientation */
    unsigned int  offset: 27;   /* offset from block start */
    } xelement_id;
#endif

/* masks for fields */
#define TYPEMASK   0xE0000000
#define VALIDMASK  0x10000000
#define SIGNMASK   0x08000000
#define OFFSETMASK 0x07FFFFFF

/* shifts for fields */
#define TYPESHIFT  29
#define VALIDSHIFT 28
#define SIGNSHIFT  27

#define NULLID 0L 

/* to get type of an element */
#define id_type(id)  ((int)(((id)&TYPEMASK)>>TYPESHIFT))

/* to give switched orientation of first if that of second is inverted */
#define same_sign(id1,id2)    ((id1) ^ ((id2) & SIGNMASK))

/* number of elements to allocate memory for at one time */
#define BATCHSIZE 100

/* outside storage.*, element_id structure is not visible; acts like long */    
typedef unsigned long
     element_id, vertex_id, edge_id, facet_id, body_id, facetedge_id; 

/* macros for getting structure pointer from id */
#ifdef BLOCKWISE
#define vptr(v_id) ((struct vertex *)(vibase[(v_id)&OFFSETMASK]))
#define eptr(e_id) ((struct edge   *)(eibase[(e_id)&OFFSETMASK]))
#define fptr(f_id) ((struct facet  *)(fibase[(f_id)&OFFSETMASK]))
#define bptr(b_id) ((struct body   *)(bibase[(b_id)&OFFSETMASK]))
#define feptr(fe_id) ((struct facetedge *)(feibase[(fe_id)&OFFSETMASK]))
#define ordinal(id)  (valid_id(id) ? (int)((id) & OFFSETMASK) : -1 )
#else
#ifdef INDIRECT_ID
#define vptr(v_id) ((struct vertex *)(vbase + vibase[(v_id)&OFFSETMASK]))
#define eptr(e_id) ((struct edge   *)(ebase + eibase[(e_id)&OFFSETMASK]))
#define fptr(f_id) ((struct facet  *)(fbase + fibase[(f_id)&OFFSETMASK]))
#define bptr(b_id) ((struct body   *)(bbase + bibase[(b_id)&OFFSETMASK]))
#define feptr(fe_id) ((struct facetedge *)(febase+feibase[(fe_id)&OFFSETMASK]))
#define ordinal(id)  (valid_id(id) ? (int)((id) & OFFSETMASK) : -1 )
#else
#ifdef OFFSET_ID
#define vptr(v_id) ((struct vertex *)(vbase + ((v_id)&OFFSETMASK)))
#define eptr(e_id) ((struct edge   *)(ebase + ((e_id)&OFFSETMASK)))
#define fptr(f_id) ((struct facet  *)(fbase + ((f_id)&OFFSETMASK)))
#define bptr(b_id) ((struct body   *)(bbase + ((b_id)&OFFSETMASK)))
#define feptr(fe_id) ((struct facetedge *)(febase + ((fe_id)&OFFSETMASK)))
#else
/* index in id */
#define vptr(v_id) ((struct vertex *)(vbase + ((v_id)&OFFSETMASK)*web.sizes[VERTEX]))
#define eptr(e_id) ((struct edge   *)(ebase + ((e_id)&OFFSETMASK)*web.sizes[EDGE]))
#define fptr(f_id) ((struct facet  *)(fbase + ((f_id)&OFFSETMASK)*web.sizes[FACET]))
#define bptr(b_id) ((struct body   *)(bbase + ((b_id)&OFFSETMASK)*web.sizes[BODY]))
#define feptr(fe_id) ((struct facetedge *)(febase + ((fe_id)&OFFSETMASK)*web.sizes[FACETEDGE]))
#define ordinal(id)  (valid_id(id) ? ((id) & OFFSETMASK) : -1 )
#endif
#endif
#endif

/* id attr bits */
#define VALID_BIT   0x0001
#define INVERSE_BIT 0x0001

#define edge_inverse(id)  inverse_id(id)
#define facet_inverse(id)  inverse_id(id)
#define fe_inverse(id)  inverse_id(id)
#define invert(id)     ((id) ^= SIGNMASK)
#define equal_id(a,b)  ((a)==(b))
#define equal_element(a,b)  (((a)|SIGNMASK) == ((b)|SIGNMASK))
#define valid_id(id)   ((id)&VALIDMASK)
#define inverted(id)   ((id)&SIGNMASK)
#define inverse_id(id) ((id) ^ SIGNMASK)
#define positive_id(id) ((id) & ~SIGNMASK)
typedef int ORDTYPE;                /* element numbering type */

#ifndef BLOCKWISE
/* individual dimension block pointer arrays, handy for fast addressing */
extern char *vbase;
extern char *ebase;
extern char *fbase;
extern char *bbase;
extern char *febase;

/* individual dimension block pointer arrays, handy for fast addressing */
/* useful only for fixed size structures */
extern struct vertex *vvbase;
extern struct edge *eebase;
extern struct facet *ffbase;
extern struct body *bbbase;
extern struct facetedge *fefebase;

/* unified block references, indexed by element type */
extern char *base[NUMELEMENTS];
typedef int INDIRECT_TYPE;   /* may want to do pointers later */
#endif
#ifdef BLOCKWISE
typedef struct element *INDIRECT_TYPE; 
extern struct blocklist_struct
    { struct element *blockptr; /* allocated block */
      int start_ord; /* ordinal of first element */
      int count;    /* elements in block */
    } *blocklist[NUMELEMENTS];
extern int blockcount[NUMELEMENTS];  /* how many blocks allocated */
extern int blockmax[NUMELEMENTS];  /* length of blocklist */
#endif

/* individual indirect block pointer arrays */
extern INDIRECT_TYPE *ibase[NUMELEMENTS];
extern int ialloc[NUMELEMENTS]; /* allocated length of ibase's */
extern INDIRECT_TYPE *vibase;
extern INDIRECT_TYPE *eibase;
extern INDIRECT_TYPE *fibase;
extern INDIRECT_TYPE *bibase;
extern INDIRECT_TYPE *feibase;

/* End of storage.h */

/* Some don't have these manifest constants in math.h */
#ifndef M_LN2
#define M_E             2.71828182845904523536
#define M_PI            3.14159265358979323846
#define M_LN2           0.693147180559945309417
#endif

#ifdef LONGDOUBLE
#undef  M_E
#define M_E             2.7182818284590452353602874713527L
#undef  M_PI
#ifdef TC
#define M_PI (atan(1.0)*4)
#else
#define M_PI            3.1415926535897932384626433832795L
#endif
#undef  M_LN2
#define M_LN2           0.693147180559945309417L
#endif

#ifndef DBL_EPSILON
#define DBL_EPSILON     2.2204460492503131e-16
#endif

/* can undefine or redefine these if your system has decent string functions */
#define stricmp(s1,s2)  kb_stricmp((s1),(s2))
#define strnicmp(s1,s2,n)  kb_strnicmp((s1),(s2),(n))
#define strstr(s1,s2) kb_strstr((s1),(s2))
#ifndef strupr
#define strupr(a) kb_strupr(a)
#endif

/* Since tolower and toupper don't always  check case before converting */
#undef tolower
#undef toupper
#define tolower(c)   (isupper(c) ? ((c)-'A'+'a') : c)
#define toupper(c)   (islower(c) ? ((c)-'a'+'A') : c)

#ifndef MAXDOUBLE
#define MAXDOUBLE 1.0e38
#endif

#ifdef NOPROTO
#define ARGS(x) ()
#else
#define ARGS(x) x
#endif

#ifdef ENABLE_DLL
#include <dlfcn.h>
#endif

/* Evolver header files */
/*************************************************************
*  This file is part of the Surface Evolver source code.     *
*  Programmer:  Ken Brakke, brakke@geom.umn.edu              *
*************************************************************/

/**********************************************************************
*
*  File: skeleton.h
*
*  Header file for evolver.  Defines skeleton structures.
*
*/


/************************************************************************
* structure for defining extra attributes
*/
#define ATTR_NAME_SIZE 31
struct extra { char name[ATTR_NAME_SIZE+1];
               int type;   /* see below */
               int offset; /* within allocated space */
               int dim;    /* size of vector attribute */
               int flags;  /* see below */
             };
/* attribute types */
#define NULL_ATTR    0
#define REAL_ATTR    1
#define INTEGER_ATTR 2
#define ULONG_ATTR   3
#define UCHAR_ATTR   4
#define ELEMENTID_ATTR ULONG_ATTR
#define NUMATTRTYPES 6
extern char *attr_type_name[NUMATTRTYPES];
extern int attr_type_size[NUMATTRTYPES];

/* flags */
#define DUMP_ATTR    1

/************************************************************************
* base structure for a skeleton of a particular dimension 
*/
struct skeleton {
    int             type;     /* type of element, see defines above */
    int             dimension; /* dimension of element */
    int            ctrlpts;   /* number of control points           */
    char           *base;     /* to list of structures              */
    INDIRECT_TYPE  *ibase;    /* to indirect list                   */
    long            maxcount; /* elements allocated                 */
    element_id      free;     /* start of free list                 */
    element_id      used;     /* start of in-use elements           */
    element_id      last;     /* end of in-use chain, for adding on */
    element_id      discard;  /* start of discard list              */
    long            count;    /* number active                      */
    ORDTYPE         max_ord;  /* highest ordinal                    */
    int             extreme[MAXCOORD+1]; /* indices of corners in Lagrange */
    struct extra    extras[MAXEXTRA]; /* extra attributes defines   */
    char           *extra_space;      /* extra attributes           */
    int             extra_size;       /* bytes per element extra    */
    int             extra_count;      /* number of extra attributes */
  } ;

/************************************************************************
*
*  Union skeleton element structure for common operations.
*
*/

typedef int MAP; /* constraint, etc, bitmap type */
typedef long int ATTR;   /* attribute bitmap type */
typedef short int tagtype;         /* element tag type */
typedef short ETYPE;                /* element type type */
typedef long int WRAPTYPE;         /* symmetry group element */

typedef int NTYPE; /* for node indexes, types, etc. */

    /* common fields; added to each element struct type */
#define BASIC_STUFF \
    element_id   forechain;      /* for element and free list forechain */\
    element_id   backchain;      /* for element and free list backchain */\
    ATTR         attr;         /* attribute bits */\
    element_id   self_id;      /* for identifying self */
#define COMMON_STUFF \
    BASIC_STUFF \
    int          original;       /* datafile original number */ \
    unsigned short  qflags;         /* flag bits for quantities */ \
    unsigned short  method_count;    /* number of method instances */ 


struct element {
  COMMON_STUFF
  };

/*****************************************************************
*
*   Structures peculiar to each dimension of skeleton.
*/


/****************************************************
*
*  facetedge structure 
*/

struct facetedge
  { 
    BASIC_STUFF
    edge_id      fe_edge_id;  /* oriented edge of base pair */
    facet_id     fe_facet_id; /* oriented face of base pair */
    facetedge_id nextedge[2];  /* 0 previous, 1 next */
    facetedge_id nextfacet[2];  /* 0 previous, 1 next */
  };

 
/****************************************************
*
*  vertex structure - will be extended by other attributes.
*/

struct vertex
  { 
    COMMON_STUFF
    REAL star;         /* area of surrounding facets */
    edge_id e_id;  /* link to global structure */
                   /* may really be facet in Lagrange model */
    int valence;        /* number of edges incident */
  };

/* attribute numbers for standard attributes */
/* be sure these numbers are in same order as allocation in reset_skeleton() */
#define V_COORD_ATTR       0
#define V_PARAM_ATTR       1
#define V_FORCE_ATTR       2
#define V_VELOCITY_ATTR    3
#define V_BOUNDARY_ATTR    4
#define V_STAR_ATTR        5
#define V_CONSTR_LIST_ATTR 6

/****************************************************
*
*  edge structure - will be extended by other attributes.
*/
  
struct edge
  { 
    COMMON_STUFF
    facetedge_id fe_id;     /* link to global structure */
    edge_id next_vedge[2];    /* link to next edge around vertex */
    REAL density;       /* energy per unit length */
    REAL length;          /* edge length; be careful of validity */
    REAL star;            /* total area of adjacent facets */
    short color;          /* for display */
  };

/* attribute numbers for standard attributes */
/* be sure these numbers are in same order as allocation in reset_skeleton() */
#define E_STAR_ATTR          0
#define E_DENSITY_ATTR       1
#define E_VERTICES_ATTR      2
#define E_BOUNDARY_ATTR      3
#define E_WRAP_ATTR          4
#define E_SURFEN_MAP_ATTR    5
#define E_NUM_QUANT_MAP_ATTR 6
#define E_CONSTR_LIST_ATTR   7

/******************************************************
*
*  facet structure - will be extended by other attributes.
*/

struct facet
  { 
    COMMON_STUFF
    facetedge_id fe_id;  /* link to global structure */
    REAL        density;      /* for doing real currents and varifolds */
    REAL   area;              /* for diffusion or whatever */
    short color;              /* for display */
    short backcolor;          /* for different color backside */
};
/* attribute numbers for standard attributes */
#define F_CONSTR_LIST_ATTR   0
#define F_VERTICES_ATTR      1
#define F_BOUNDARY_ATTR      2
#define F_SURFEN_MAP_ATTR    3
#define F_NUM_QUANT_MAP_ATTR 4
#define F_TAG_ATTR           5
#define F_BODY_LIST_ATTR     6
#define F_NEXT_VFACET_ATTR   7
#define F_NEXT_BFACET_ATTR   8
#define F_PHASE_ATTR         9


/*********************************************************
*
*  body structure
*/

struct body
  { 
    COMMON_STUFF
    REAL fixvol;     /* volume constraint */
    REAL volume;     /* actual volume     */
    REAL oldvolume;  /* volume for restore_coords() */
    REAL pressure;   /* internal pressure */
    facetedge_id fe_id;  /* link to global structure */
    REAL volconst;   /* for body volume constant componenet */
    REAL density;    /* for gravitational potential energy */
    int  volquant;  /* number of named quantity used for volume */
    int  volmethpos; /* number of pos volume method instance */
    int  volmethneg; /* number of neg volume method instance */
    short phase;                /* for phase-dependent boundaries */
  }; 

/*********************************************************************
*
*   Boundaries and constraints
*/
#define BDRYMAX 200
#define CONSTRMAX MAXCON
/* these make web over 32K */
#ifdef MAC_APP
#define SURFENMAX 16
#define QUANTMAX  16
#else
#define SURFENMAX 32
#define QUANTMAX  32
#endif

/* for specifying free boundaries in parametric form */
struct boundary
  {
    ATTR attr;             /* attribute flags */
    int pcount;           /* number of parameters */
    int num;              /* boundary number */
    struct expnode *coordf[MAXCOORD];   /* coordinate functions for eval() */
    struct expnode *envect[MAXCOORD];  /* functions for boundary energy */
    struct expnode *convect[MAXCOORD]; /* functions for boundary interior content */
    int compcount;      /* number of components for integrands */
    int    energy_method;   /* if using named quantity version */
    int    content_method_1;   /* if using named quantity version */
    int    content_method_2;   /* if using named quantity version */
  };


/* for specifying constraints */
#define MAXCONCOMP (MAXCOORD*(MAXCOORD-1)/2)
struct constraint
  {
    ATTR attr;             /* attribute flags */
    struct expnode *formula;   /* function expression for eval() */
    int compcount;      /* number of components for integrands */
    struct expnode *envect[MAXCONCOMP]; /* functions for energy integral */
    struct expnode *convect[MAXCONCOMP]; /* functions for content integral */
    MAP    quantity_map;     /* quantities have integrals on edge */
    struct expnode *quanvect[QUANTMAX][MAXCONCOMP];
    int    energy_method;   /* if using named quantity version */
    int    content_method_1;   /* if using named quantity version */
    int    content_method_2;   /* if using named quantity version */
  };

/* for specifying facet energy integrands */
struct surf_energy
  {
    ATTR attr;             /* attribute flags */
    struct expnode *envect[MAXCOORD]; /* functions for energy integral */
  };

/* for specifying facet quantity integrands */
struct quantity
  {
    ATTR attr;      /* attribute flags, esp. QFIXED for constrained quantity */
    struct expnode *quanvect[MAXCOORD]; /* functions for facet integral */
    REAL  value;    /* actual total value */
    REAL  target;   /* goal if QFIXED */
    REAL  pressure;  /* Lagrange multiplier */
  };


/* boundary and constraint attributes */
#define B_CONVEX     0x0001
#define NONPOSITIVE  0x0400
#define NONNEGATIVE  0x0800
#define GLOBAL       0x0004
#define QFIXED       0x0010
#define IN_USE       0x0020
#define CON_ENERGY   0x0040
#define CON_CONTENT  0x0080
#define USURPED_BY_QUANTITY 0x0100

extern element_id
  NULLVERTEX,
  NULLEDGE,
  NULLFACET,
  NULLBODY,
  NULLFACETEDGE;

/* vertex volume gradient storage */

/* structures chained from each vertex */
typedef struct volgrad 
  {
     body_id   b_id;   /* body involved */
     struct volgrad  *chain;  /* next body for this vertex */
     REAL grad[MAXCOORD];        /* volume gradient of body for this vertex */
     REAL normal[MAXCOORD];      /* approx normal of body at this vertex */
     REAL velocity[MAXCOORD];    /* form converted to vector */
  } volgrad;

extern volgrad *vgradbase;   /* allocated list pointer */
extern volgrad **vgptrbase;   /* allocated list pointer for each vertex */
extern int      vgradtop;    /* number of first free  structure */
extern long     vgradmax;    /* number allocated */

/* loop macros, for use when lists are not modified in loop */

#define FOR_ALL_ELEMENTS(type,id) \
for (id = web.skel[type].used ; valid_id(id) ; id = elptr(id)->forechain)

#define FOR_ALL_VERTICES(v_id) \
for (v_id = web.skel[VERTEX].used ; valid_id(v_id) ; \
v_id = vptr(v_id)->forechain)

#define FOR_ALL_EDGES(e_id) \
for (e_id = web.skel[EDGE].used ; valid_id(e_id) ; \
e_id = eptr(e_id)->forechain)

#define FOR_ALL_FACETS(f_id) \
for (f_id = web.skel[FACET].used ; valid_id(f_id) ; \
f_id = fptr(f_id)->forechain)

#define FOR_ALL_BODIES(b_id) \
for (b_id = web.skel[BODY].used ; valid_id(b_id) ; \
b_id = bptr(b_id)->forechain)

#define FOR_ALL_FACETEDGES(fe_id) \
for (fe_id = web.skel[FACETEDGE].used ; valid_id(fe_id) ; \
fe_id = feptr(fe_id)->forechain)

/* These access functions are defined as macros, since they involve
   only one evaluation of the arguments */

#define valid_element(id)  (valid_id(id) && (get_attr(id) & ALLOCATED))

#define get_edge_midv(e_id)         (get_edge_vertices(e_id)[2])

#define get_fe_side(fe_id,x)  get_edge_side(get_fe_edge(fe_id),x)

/* Macros that should be used only when argument does not expand!!*/
/* Note these begin with Capitals. */
#define Get_fe_edge(fe_id)   \
   (same_sign(feptr(fe_id)->fe_edge_id,fe_id))
#define Get_edge_headv(e_id) \
   (get_edge_vertices(e_id)[inverted(e_id) ? 0 : web.headvnum])
#define Get_edge_tailv(e_id) \
   (get_edge_vertices(e_id)[inverted(e_id) ? web.headvnum : 0])
#define Get_next_edge(fe_id)  (\
   same_sign(feptr(fe_id)->nextedge[inverted(fe_id) ? 0 : 1],fe_id))
#define Get_prev_edge(fe_id)  (\
   same_sign(feptr(fe_id)->nextedge[inverted(fe_id) ? 1 : 0],fe_id))
#define Get_next_facet(fe_id)  (\
   same_sign(feptr(fe_id)->nextfacet[inverted(fe_id) ? 0 : 1],fe_id))
#define Get_prev_facet(fe_id)  (\
   same_sign(feptr(fe_id)->nextfacet[inverted(fe_id) ? 1 : 0],fe_id))
#define Get_fe_tailv(fe_id)     Get_edge_tailv(Get_fe_edge(fe_id))

/* serial versions of macros */
#ifndef PARALLEL_MACHINE
#define get_fe_edge(fe_id)   \
   (x1_id=(fe_id),same_sign(feptr(x1_id)->fe_edge_id,x1_id))
#define get_edge_headv(e_id) \
   (x2_id=(e_id),get_edge_vertices(x2_id)[inverted(x2_id) ? 0 : web.headvnum])
#define get_edge_tailv(e_id) \
   (x3_id=(e_id),get_edge_vertices(x3_id)[inverted(x3_id) ? web.headvnum : 0])
#define get_next_edge(fe_id)  (x4_id = (fe_id),\
   same_sign(feptr(x4_id)->nextedge[inverted(x4_id) ? 0 : 1],x4_id))
#define get_prev_edge(fe_id)  (x5_id = (fe_id),\
   same_sign(feptr(x5_id)->nextedge[inverted(x5_id) ? 1 : 0],x5_id))

/* macros for traversing linked lists of adjoining edges */
#define get_next_tail_edge(e_id)  (xd_id = (e_id),\
     eptr(xd_id)->next_vedge[inverted(xd_id) ?1: 0])
#define get_next_head_edge(e_id)  (xe_id = (e_id),\
     inverse_id(eptr(xe_id)->next_vedge[inverted(xe_id) ? 0: 1]))

#define set_next_tail_edge(e_id,ee_id)  (xd_id = (e_id),\
     eptr(xd_id)->next_vedge[inverted(xd_id) ?1: 0] = (ee_id))
#endif
/* serial versions of macros */

#define V_EXTRA(v,attr) ((char*)(vptr(v))+web.skel[VERTEX].extras[attr].offset)
#define E_EXTRA(e,attr) ((char*)(eptr(e))+web.skel[EDGE].extras[attr].offset)
#define F_EXTRA(f,attr) ((char*)(fptr(f))+web.skel[FACET].extras[attr].offset)

#define VREAL(v,attr) ((REAL*)((char*)(vptr(v))+web.skel[VERTEX].extras[attr].offset))
#define VINT(v,attr) ((int*)((char*)(vptr(v))+web.skel[VERTEX].extras[attr].offset))
#define EREAL(e,attr) ((REAL*)((char*)(eptr(e))+web.skel[EDGE].extras[attr].offset))
#define EINT(e,attr) ((int*)((char*)(eptr(e))+web.skel[EDGE].extras[attr].offset))
#define EULONG(e,attr) ((unsigned long*)((char*)(eptr(e))+web.skel[EDGE].extras[attr].offset))
#define FREAL(f,attr) ((REAL*)((char*)(fptr(f))+web.skel[FACET].extras[attr].offset))
#define FINT(f,attr) ((int*)((char*)(fptr(f))+web.skel[FACET].extras[attr].offset))
#define FULONG(f,attr) ((unsigned long*)((char*)(fptr(f))+web.skel[FACET].extras[attr].offset))
#define BREAL(b,attr) ((REAL*)((char*)(bptr(b))+web.skel[BODY].extras[attr].offset))
#define BINT(b,attr) ((int*)((char*)(bptr(b))+web.skel[BODY].extras[attr].offset))
#define BULONG(b,attr) ((unsinged long*)((char*)(bptr(b))+web.skel[BODY].extras[attr].offset))
#define FEREAL(fe,attr) ((REAL*)((char*)(feptr(fe))+web.skel[FACETEDGE].extras[attr].offset))
#define FEINT(fe,attr) ((int*)((char*)(feptr(fe))+web.skel[FACETEDGE].extras[attr].offset))
#define get_coord(v_id)  VREAL((v_id),V_COORD_ATTR)
#define get_param(v_id)  VREAL((v_id),V_PARAM_ATTR)
#define get_boundary(v_id)      (get_vattr(v_id)&BOUNDARY ?\
                web.boundaries+*VINT(v_id,V_BOUNDARY_ATTR) : NULL)
#define get_edge_boundary_num(e_id)      (get_eattr(e_id)&BOUNDARY ?\
                *EINT(e_id,E_BOUNDARY_ATTR) : 0)
#define set_boundary_num(v_id,bnum) \
                           (*VINT(v_id,V_BOUNDARY_ATTR) = (bnum))
#define get_edge_boundary(e_id)   (get_eattr(e_id)&BOUNDARY ?\
                 web.boundaries+*EINT(e_id,E_BOUNDARY_ATTR) : NULL)
#define set_edge_boundary_num(e_id,bnum) \
                           (*EINT(e_id,E_BOUNDARY_ATTR) = (bnum))
#define get_facet_boundary(f_id)  (get_fattr(f_id)&BOUNDARY ? \
                web.boundaries+*FINT(f_id,F_BOUNDARY_ATTR) : 0)
#define set_facet_boundary_num(f_id,bnum) \
                           (*FINT(f_id,F_BOUNDARY_ATTR) = (bnum))

#define get_surfen(n)           (web.surfen + (n))
#define get_e_surfen_map(e_id)  \
          (web.surfen_count ? *EINT(e_id,E_SURFEN_MAP_ATTR) : 0) 
#define set_e_surfmap(e_id,map) (*EINT(e_id,E_SURFEN_MAP_ATTR) |= (map))
#define set_e_surfen_map(e_id,n)   (*EINT(e_id,E_SURFEN_MAP_ATTR) |= (1<<(n)))
#define get_f_surfen_map(f_id)  \
          (web.surfen_count ? *FINT(f_id,F_SURFEN_MAP_ATTR) : 0)
#define set_f_surfmap(f_id,map) (*FINT(f_id,F_SURFEN_MAP_ATTR) |= (map))
#define set_f_surfen_map(f_id,n)   (*FINT(f_id,F_SURFEN_MAP_ATTR) |= (1<<(n)))

#define get_quant(n)           (web.quants + (n))
#define get_f_quant_map(f_id)  \
          (web.quantity_count ? *FINT(f_id,F_NUM_QUANT_MAP_ATTR) : 0)
#define set_f_quantmap(f_id,map) (*FINT(f_id,F_NUM_QUANT_MAP_ATTR) |= (map))
#define set_f_quant_map(f_id,n)  (*FINT(f_id,F_NUM_QUANT_MAP_ATTR) |= (1<<(n)))
#define get_e_quant_map(e_id)  \
          (web.quantity_count ? *EINT(e_id,E_NUM_QUANT_MAP_ATTR) : 0)
#define set_e_quantmap(e_id,map) (*EINT(e_id,E_SURFEN_MAP_ATTR) |= (map))
#define set_e_quant_map(e_id,n)  (*EINT(e_id,E_SURFEN_MAP_ATTR) |= (1<<(n)))

/* Constraints */
typedef unsigned char conmap_t;  /* in element lists */
/* indicates vertex hit constraint */
#define CON_HIT_BIT ((conmap_t)(1<<(8*sizeof(conmap_t)-1)))
/* maximum possible constraints given size of conmap_t */
#define MAXMAXCON ((1<<(8*sizeof(conmap_t)-1))-1)
/* actual number of constraint slots in struct web; must be < MAXMAXCON */
#define MAXCON  127
/* mask to strip hit bit */
#define CONMASK (MAXMAXCON)
/* maximum size of per-element constraint list */
#define MAXCONPER 23

extern conmap_t nullcon[2];  /* default empty constraint list */
#define get_constraint(n)      (GETCONSTR((n)&CONMASK))
#define get_v_constraint_map(v_id)   ( get_vattr(v_id) & CONSTRAINT ? \
  (conmap_t*)(V_EXTRA(v_id,V_CONSTR_LIST_ATTR)) : nullcon)
#define get_e_constraint_map(e_id)  ( get_eattr(e_id) & CONSTRAINT ? \
  (conmap_t*)(E_EXTRA(e_id,E_CONSTR_LIST_ATTR)) : nullcon)
#define get_f_constraint_map(f_id) ( get_fattr(f_id) & CONSTRAINT ? \
  (conmap_t*)(F_EXTRA(f_id,F_CONSTR_LIST_ATTR)) : nullcon)

#define get_force(v_id)     VREAL((v_id),V_FORCE_ATTR)
#define get_velocity(v_id)     VREAL((v_id),V_VELOCITY_ATTR)
#define get_restore(v_id)   VREAL((v_id),V_RESTORE_ATTR) 
#define set_vertex_edge(v_id,e)  (vptr(v_id)->e_id = (e))
#define get_vertex_edge(v_id)     (vptr(v_id)->e_id)
#define get_vertex_star(v_id)   (vptr(v_id)->star)
#define set_vertex_star(v_id,a) (vptr(v_id)->star = (a))
#define add_vertex_star(v_id,a) (vptr(v_id)->star += (a))
#define set_vertex_valence(v_id,n)  (vptr(v_id)->valence = (n))
#define add_vertex_valence(v_id,n)  (vptr(v_id)->valence += (n))
#define get_vertex_valence(v_id)  (vptr(v_id)->valence)

#define get_fe_wrap(fe_id)    get_edge_wrap(get_fe_edge(fe_id)) 
#define get_fe_tailv(fe_id)     get_edge_tailv(get_fe_edge(fe_id))
#define get_fe_headv(fe_id)     get_edge_headv(get_fe_edge(fe_id))
#define get_fe_midv(fe_id)     get_edge_midv(get_fe_edge(fe_id))
#define set_edge_length(e_id,x) (eptr(e_id)->length = (x))
#define get_edge_density(e_id)      (eptr(e_id)->density)
#define set_edge_density(e_id,den)  (eptr(e_id)->density = (den))
#define get_edge_star(e_id)   (eptr(e_id)->star)
#define set_edge_star(e_id,a) (eptr(e_id)->star = (a))
#define add_edge_star(e_id,a) (eptr(e_id)->star += (a))

#define get_facet_vertices(f_id)  FULONG(f_id,F_VERTICES_ATTR)
#define get_edge_vertices(e_id)   EULONG(e_id,E_VERTICES_ATTR) 

#define get_facet_density(f_id)      (fptr(f_id)->density)
#define set_facet_density(f_id,den)  (fptr(f_id)->density = (den))

#define get_facet_area(f_id)      (fptr(f_id)->area)
#define set_facet_area(f_id,a)  (fptr(f_id)->area = (a))

#define get_facet_flux(f_id)      (fptr(f_id)->flux)
#define set_facet_flux(f_id,a)  (fptr(f_id)->flux = (a))

#define get_body_volquant(b_id) (bptr(b_id)->volquant)
#define set_body_volquant(b_id,n) (bptr(b_id)->volquant = (n))

#define get_body_volmethpos(b_id) (bptr(b_id)->volmethpos)
#define set_body_volmethpos(b_id,n) (bptr(b_id)->volmethpos = (n))
#define get_body_volmethneg(b_id) (bptr(b_id)->volmethneg)
#define set_body_volmethneg(b_id,n) (bptr(b_id)->volmethneg = (n))

#define save_body_volume(b_id) (bptr(b_id)->oldvolume = bptr(b_id)->volume)
#define restore_body_volume(b_id) (bptr(b_id)->volume = bptr(b_id)->oldvolume)

#ifdef NEW_EXTRA
#define get_v_extra(v_id,n) ((char*)vptr(v_id)  \
       + web.skel[VERTEX].extras[n].offset)
#define get_e_extra(e_id,n) ((char*)eptr(e_id)  \
       + web.skel[EDGE].extras[n].offset)
#define get_f_extra(f_id,n) ((char*)fptr(f_id)  \
       + web.skel[FACET].extras[n].offset)
#define get_b_extra(b_id,n) ((char*)bptr(b_id)  \
       + web.skel[BODY].extras[n].offset)
#else
#define get_v_extra(v_id,n) (web.skel[VERTEX].extra_space  \
       + ordinal(v_id)*web.skel[VERTEX].extra_size \
       + web.skel[VERTEX].extras[n].offset)
#define get_e_extra(e_id,n) (web.skel[EDGE].extra_space  \
       + ordinal(e_id)*web.skel[EDGE].extra_size \
       + web.skel[EDGE].extras[n].offset)
#define get_f_extra(f_id,n) (web.skel[FACET].extra_space  \
       + ordinal(f_id)*web.skel[FACET].extra_size \
       + web.skel[FACET].extras[n].offset)
#define get_b_extra(b_id,n) (web.skel[BODY].extra_space  \
       + ordinal(b_id)*web.skel[BODY].extra_size \
       + web.skel[BODY].extras[n].offset)
#endif

/* serial versions of macros */
#ifndef PARALLEL_MACHINE
#define get_vertex_fe(v_id)     ((xx_id=vptr(v_id)->e_id),\
        valid_id(xx_id)?same_sign(eptr(xx_id)->fe_id,xx_id):NULLID)

#define get_body_fe(b_id)  (x6_id=(b_id),\
    ( valid_id(x6_id) ? bptr(x6_id)->fe_id : NULLID ))

#define set_body_fe(b_id,fe)   (x7_id=(b_id),\
            ( valid_id(x7_id) ?  bptr(x7_id)->fe_id = (fe) : NULLID ) )

#define get_body_density(b_id)  (xx_id=(b_id),\
             ( valid_id(xx_id) ?  bptr(xx_id)->density : 0.0 ))

#define get_body_volume(b_id)  (xx_id=(b_id),\
             ( valid_id(xx_id) ?  bptr(xx_id)->volume : 0.0 ))

#define get_body_fixvol(b_id)   (xx_id=(b_id),\
             ( valid_id(xx_id) ?  bptr(xx_id)->fixvol : 0.0 ))

#define get_body_pressure(b_id)  (xx_id=(b_id),\
             ( valid_id(xx_id) ?   bptr(xx_id)->pressure : 0.0 ))

#define get_body_volconst(b_id) (xx_id=(b_id),\
             ( valid_id(xx_id) ?  bptr(xx_id)->volconst : 0.0 ))

#define set_body_volconst(b_id,v) (x8_id=(b_id),\
             ( valid_id(x8_id) ?  bptr(x8_id)->volconst = (v) : 0.0 ) )

#define set_body_density(b_id,v)  (x9_id=(b_id),\
             ( valid_id(x9_id) ?  bptr(x9_id)->density = (v) : 0.0 ) )

#define set_body_volume(b_id,v)  (xa_id=(b_id),\
             ( valid_id(xa_id) ?  bptr(xa_id)->volume = (v) : 0.0 ) )

#define set_body_pressure(b_id,v) (xc_id=(b_id),\
             ( valid_id(xc_id) ?  bptr(xc_id)->pressure = (v) : 0.0 ) )
#endif
/* serial versions of macros */

#define get_attr(id)    (elptr(id)->attr)
#define get_vattr(id)   (vptr(id)->attr)
#define get_eattr(id)   (eptr(id)->attr)
#define get_fattr(id)   (fptr(id)->attr)
#define get_battr(id)   (bptr(id)->attr)
#define get_feattr(id)  (feptr(id)->attr)

#define set_f_phase(f_id,p)  (web.skel[FACET].extras[F_PHASE_ATTR].dim ? (*FINT(f_id,F_PHASE_ATTR) = (p)):0)
#define set_b_phase(b_id,p)   (bptr(b_id)->phase = (short)(p))
#define get_f_phase(f_id)  (web.skel[FACET].extras[F_PHASE_ATTR].dim ? (*FINT(f_id,F_PHASE_ATTR)):0)
#define get_b_phase(b_id)  (bptr(b_id)->phase)

#define set_original(id,num)  (elptr(id)->original = (num) )
#define get_original(id)  (elptr(id)->original)

#define set_edge_color(e_id,col)   (eptr(e_id)->color = (short)(col))
#define get_edge_color(e_id)         (eptr(e_id)->color)
#define set_facet_color(f_id,col) (fptr(f_id)->color = fptr(f_id)->backcolor = (short)(col))
#define get_facet_color(f_id)         (fptr(f_id)->color)
#define set_facet_frontcolor(f_id,col) \
   (inverted(f_id) ? (fptr(f_id)->backcolor = (short)(col)) : (fptr(f_id)->color = (short)(col)))
#define get_facet_frontcolor(f_id)    \
   (inverted(f_id) ? fptr(f_id)->backcolor : fptr(f_id)->color )
#define set_facet_backcolor(f_id,col) \
   (inverted(f_id) ? (fptr(f_id)->color = (short)(col)) : (fptr(f_id)->backcolor = (short)(col)))
#define get_facet_backcolor(f_id)  \
   (inverted(f_id) ? fptr(f_id)->color : fptr(f_id)->backcolor )


/*************************************************************
*  This file is part of the Surface Evolver source code.     *
*  Programmer:  Ken Brakke, brakke@geom.umn.edu              *
*************************************************************/



/******************************************************************
*
*  File:  extern.h
*
*  Purpose:  declare global variables for Evolver program.
*/

#define DEFAULT_EDGE_COLOR BLACK
#define DEFAULT_FACET_COLOR WHITE
#define DEFAULT_TARGET_TOLERANCE (1e-4)
/* extern const char *sys_errlist[]; */
extern int broken_pipe_flag; /* so output routines will know to quit */
extern int match_id_flag; /* to make id match datafile number, option -i */
extern char *cmdfilename; /* for saving command line read file */
extern char *current_prompt; /* prompt string being displayed */
#define DEFAULT_BRIGHTNESS 0.65
extern REAL brightness; /* midlevel gray for screen display */
extern int markedgedrawflag; /* for single-drawing edges */

extern char loadfilename[200]; /* for LOAD command */
extern jmp_buf loadjumpbuf;  /* for LOAD command */
extern jmp_buf graphjumpbuf;  /* for errors during MS graphing */
extern unsigned long draw_thread_id; /* for graphics thread */

#define MAXOPTPARAM 100
extern int optparamcount;  /* number thereof */
struct optparam {
 int  pnum; /* which parameter this is */
 REAL grad; /* energy gradients */
 REAL velocity;  /* adjusted motion */
 REAL cg;  /* conjugate gradient history */
 REAL old_value;  /* for restoring */
 REAL oldgrad;  /* for conjugate gradient */
 int  rownum;  /* row in Hessian */
 };
extern struct optparam optparam[MAXOPTPARAM];
extern REAL **optparam_congrads;  /* constraint gradients */
#define OPTPARAM_DELTA (1.0e-4)

/* for calc_volgrads() mode */
#define NO_OPTS  0
#define DO_OPTS  1
extern int volgrads_every_flag; /* whether recalc volgrads every projection iteration */

extern int zener_drag_flag; /* whether to do zener drag */
#define ZENER_COEFF_NAME "zener_coeff"
extern int backcull_flag;  /* 3D graphics backculling */
extern int setting_backcull; 


extern REAL **vgev;  /* vector vol grads, for approx curvature */
extern REAL **vgef;  /* form vol grads, for approx curvature */

/* macro stuff */
extern int keep_macros_flag; /* to preserve macros after datafile. */
#define MACRONAMESIZE 30
struct macro { char name[MACRONAMESIZE];
                    int  offset;    /* start of substitute string */
                    int  subsize;   /* size of substitute string */
                  };
extern struct macro  *macros;  /* dynamically allocated */
extern int macro_count;  /* number of macros defined */
extern char  *macro_subs;  /* string space for substitution strings */

extern int facet_general_flag;
extern double factorial[20];
extern int everything_quantities_flag;  /* for pure quantity version, after conversion */
extern int show_all_quantities;  /* to display default quantities also */
extern int random_seed;  /* seed for random number generators */
extern int option_q;  /* record command line option */

extern char *VERSION;
extern char *evolver_version;  /* for version checking */
extern char needed_version[30];

extern char *typenames[NUMELEMENTS];

/* silent linesplicing character */
#define MOREIN 1

/* element attr bits */
#define ALL_ATTR    (ATTR)0xFFFFFFFF
#define ALLOCATED   (ATTR)0x0001
#define NODISPLAY   (ATTR)0x0002
#define NEWELEMENT  (ATTR)0x0004
#define NEWVERTEX   (ATTR)0x0004
#define NEWEDGE     (ATTR)0x0004
#define NEWFACET    (ATTR)0x0004
#define NEWBODY     (ATTR)0x0004
#define WRAPPED     (ATTR)0x0008
#define PINNED_V    (ATTR)0x0008
#define DENSITY     (ATTR)0x0010
#define FIXEDVOL    (ATTR)0x0020
#define FIXED       (ATTR)0x0040
#define BOUNDARY    (ATTR)0x0080
#define NEGBOUNDARY (ATTR)0x0100
#define BDRY_ENERGY  (ATTR) 0x0200
#define BDRY_CONTENT (ATTR)0x1000
#define CONSTRAINT    (ATTR)0x0400
#define SURF_ENERGY   (ATTR)0x8000
#define SURF_QUANTITY (ATTR)0x1000
#define PRESSURE    (ATTR)0x0800
#define NEGCONSTRAINT (ATTR)0x4000
#define HIT_WALL      (ATTR)0x2000
#define BARE_NAKED    (ATTR)0x10000
#define Q_MIDPOINT    (ATTR)0x20000
#define TETRA_PT    (ATTR)0x40000
#define TRIPLE_PT    (ATTR)0x80000
#define HIT_ONE_SIDED (ATTR)0x100000
#define Q_MIDFACET (ATTR)0x200000
#define Q_MIDEDGE (ATTR)0x400000
#define AXIAL_POINT  (ATTR)0x800000
#define NO_REFINE  (ATTR)0x1000000
#define DISSOLVED   (ATTR)0x2000000
#define EDGE_DRAWN  (ATTR)0x4000000
#define NO_ORIGINAL (-1)

/* modes for move_vertices() */
#define TEST_MOVE   0

#define ACTUAL_MOVE 1
extern char *dymem; /* dynamic memory region */
extern int  dymemsize; /* size of dynamic memory region */
extern struct constraint null_constraint; /* non-constraint placeholder */
#define GETCONSTR(n) (web.constraint_addr[n]?  \
     (struct constraint*)(dymem+web.constraint_addr[n]):&null_constraint)

extern char *areaname;  /* length or area */
extern int read_command_flag;  /* whether commands at end of datafile */
extern int verb_flag;   /* set if lex looking for a verb */
extern int cond_expr_flag; /* set if parser looking for ':' in condexpr */
extern int exit_after_error; /* auto exit flag */ 
extern int exit_after_warning; /* auto exit flag */ 
extern int change_flag;  /* set during command that changes surface */
extern int assigntype;  /* type of assignment operator */
extern char *cmdptr;   /* current command or input for parsing */
extern int logfile_flag; /* whether logging in progress */
extern char logfilename[200];
extern FILE *logfilefd;

struct vvvv { element_id id;  /* which element */
              int vord[3];    /* id's of vertices */
             };
extern int gocount;        /* number of iterations left */ 
extern int go_display_flag;    /* display each change */
extern int box_flag;  /* whether or not to show outline box */
extern int quiet_flag; /* whether to display normal output */
extern int quiet_go_flag; /* whether to display normal g output */
extern int shading_flag;  /* for facet shading by orientation */
extern int color_flag;   /* facet coloring by user */
extern int background_color;  /* graphics background */
extern int geomview_bug_flag; /* for geomview 1.6.1 picking bug */
extern int gv_binary_flag;  /* whether to do geomview in binary */
extern int gv_pipe[2]; /* for pipe for reading geomview pick commands */
extern int pickvnum,pickenum,pickfnum,pickbnum; /* geomview picks */
extern int new_vertex_id,new_edge_id,new_facet_id,new_body_id; /* just created elements */
extern int gv_vect_start; /* vector vertex start in vpicklist */
/* for piping geomview output */
#define GEOM_TO_GEOMVIEW 0
#define GEOM_NAMED_PIPE 1
#define GEOM_PIPE_COMMAND 2
extern int parallel_update_flag[NUMELEMENTS]; /* set when element info changed */
extern long global_timestamp;  /* universal clock */
extern long web_timestamp; /* something changes */
extern long graph_timestamp;  /* so graph routines know when surface changed */
extern long top_timestamp;   /* timestamp for topology changes */
extern long vedge_timestamp; /* for vertex edgelist currency */
extern long vfacet_timestamp; /* for vertex facetlist currency */
extern long bfacet_timestamp; /* for body facetlist currency */
extern long volume_timestamp; /* for volume calculation */
extern long reset_timestamp;  /* when surface loaded */
extern int ackerman_flag;  /* whether doing phase space motion */
extern int labelflag; /* whether ps doing labels */
extern int gridflag;  /* whether ps doing gridlines */
extern int ps_colorflag; /* whether ps doing color */
extern int crossingflag; /* whether ps doing crossings */
extern char ps_file_name[1000]; /* ps output file */
#define NOLABELS 0
#define LABEL_ID 1
#define LABEL_ORIG 2
extern vertex_id *vpicklist; /* for geomview picking */
extern facet_id *fpicklist;

#define PATHSIZE  60
#define NESTDEPTH 10
extern element_id junk; /* for MSC bug */
#ifndef PARALLEL_MACHINE
extern element_id xx_id;  /* for macros to prevent multiple evaluation */
extern element_id x1_id,x2_id,x3_id,x4_id,x5_id,x6_id,x7_id,x8_id,x9_id;
extern element_id xa_id,xb_id,xc_id,xd_id,xe_id,xf_id,xg_id,xh_id;
/*so nested macros don't tromp each other*/
#endif

/* structure for expression */
struct expnode { 
                  struct treenode *start;  /* start of node list */
                  struct treenode *root;  /* root node, end of list */
                  int flag;   /* USERCOPY if user must free; HAS_STRING */
               };

/* evaluation stack */
#define MAXSTACK 100
struct dstack { REAL value, deriv[2*MAXCOORD];
                  REAL second[2*MAXCOORD][2*MAXCOORD]; };

/* for redefining single letter commands */
extern struct expnode single_redefine[128];

/* for dynamic load library functions */
#define MAX_DLL 5
typedef void (*dll_func_type) ARGS((int , REAL*, struct dstack *));
struct dll { char *name;  /* library name */
             void *handle;    /* for dl functions */
             } ;
extern   struct dll dll_list[MAX_DLL];
#define FUNC_VALUE  1
#define FUNC_DERIV  2
#define FUNC_SECOND 3
             
/* global variable list */
#define GLOBAL_NAME_SIZE 31
struct global
  { char name[GLOBAL_NAME_SIZE + 1];  /* 31 significant characters */
    union { REAL real;
            char *string;
            struct expnode proc;
            struct { REAL *values;
                     char *value_file;
                   } file;
            int quant;  /* quantity */
            int meth_inst; /* method values*/
            dll_func_type funcptr; /* dynamic load function */
          } value;
    REAL delta; /* for optimizing parameter differencing */
    int  flags;    /* see defines below */
    int  proc_timestamp; /* for ordering procedure defines */
  };
#define dy_globals web.dy_globals_w
#define globals ((struct global *)(dymem + dy_globals))
extern struct global *Globals; /* handy for debugging */
extern int proc_timestamp; /* for ordering procedure definitions */
extern int old_global_count; /* for error recovery */
extern int perm_flag;  /* for whether permanent assignment parsing in place */
extern int reading_comp_quant_flag;  
extern int cur_quant;  /* when reading compound quantity */
extern int quantities_only_flag; /* for using named quantities only */
extern int gravity_quantity_num;  /* number of quantity for default gravity */
extern int gap_quantity_num;  /* number of quantity for default gap energy */
extern int default_area_quant_num; /* number of quantity for default area */
extern int rotorder_var; /* for flip_rot order */

/* defines for global variable flags */
#define ORDINARY_PARAM 1  /* ordinary real-valued */
#define FILE_VALUES 2   /* values to be read from file */
#define SUBROUTINE  4   /* value is a parse tree */
#define SURFACE_PARAMETER 8  /* causes recalc when variable changed */
#define PERMANENT  0x10   /* do not forget for new surface */
#define GLOB_USED  0x20   /* if allocated */
#define QUANTITY_MODULUS  0x40  /* multiplier for quantity */
#define QUANTITY_NAME  0x80  /* actual value for quantity */
#define QUANTITY_TARGET  0x100  /* target value for quantity */
#define QUANTITY_TYPE (QUANTITY_MODULUS|QUANTITY_NAME|QUANTITY_TARGET)
#define METHOD_MODULUS 0x200
#define METHOD_NAME 0x400
#define METHOD_TYPE (METHOD_MODULUS|METHOD_NAME)
#define ANY_TYPE  (FILE_VALUES|SUBROUTINE|QUANTITY_TYPE|METHOD_TYPE)
#define STRINGVAL 0x2000  /* string */
#define LEFTOVER  0x4000  /* if permanent left over from prev file */
#define OPTIMIZING_PARAMETER 0x8000  /* variable during optimization */
#define DYNAMIC_LOAD_FUNC 0x10000  /* dynamic load library function */

extern struct expnode torus_period_expr[MAXCOORD][MAXCOORD];
extern struct expnode ***view_transform_gen_expr;

/* for calc_periods() */
#define NO_ADJUST_VOLUMES 0
#define ADJUST_VOLUMES    1

/* Bits for calc_all_grads() and such */
#define CALC_FORCE    1
#define CALC_VOLGRADS 2


extern int torus_display_mode;  /* default, raw, connected, clipped */
/* modes */
#define TORUS_DEFAULT_MODE 0
#define TORUS_RAW_MODE     1
#define TORUS_CONNECTED_MODE 2
#define TORUS_CLIPPED_MODE 3

extern int read_depth,include_depth;
extern char datafilename[PATHSIZE];  /* current datafile name */
extern char filename[PATHSIZE];  /* file name in command */
extern FILE *commandfd;  /* command input file */
extern FILE *logfd;  /* command log file */
extern struct cmdfile { 
         FILE *fd; /* for nested reads */
         char filename[PATHSIZE]; /* command file name */
         int line;   /* for error reporting */
         int datafile_flag;  /* whether datafile */
       } cmdfile_stack[NESTDEPTH],datafile_stack[NESTDEPTH];
extern int datafile_flag;  /* 1 for datafile, 0 for command so expression
                              parser knows what's up */
extern int lists_flag;  /* set when parsing space-separated lists */
#define LISTS_OFF 0
#define LISTS_SOME 1
#define LISTS_FULL 2

extern int const_expr_flag;  /* 1 for const_expr, 0 for command so expression
                              parser knows what's up */
extern int boundary_expr_flag; /* so parser knows when parsing boundary */
extern int reading_elements_flag; /* so parser knows attributes should not
    be accepted in expressions */
extern FILE *outfd;    /* for normal output */
extern int check_increase_flag;  /* to detect blowups */
extern int estimate_flag;   /* for toggling estimate of energy decrease */
extern int autorecalc_flag; /* for toggling autorecalc after variable assign  */
extern int autopop_flag;    /* whether to do autopopping */
extern int autochop_flag;    /* whether to do autochopping */
extern REAL autochop_size;  /* max edge length for autochop */
extern int autopop_count;  /* number of edges found */
extern int autochop_count;  /* number of edges found */
extern int parens;          /* level of parenthesis nesting */
extern int brace_depth;          /* level of brace nesting */
extern int in_quote;       /* so lexer knows when in string */
extern int effective_area_flag; /* use quadratic form for area around vertex */
extern int old_area_flag;    /* on for using old effective area */
extern int runge_kutta_flag; /* whether to use runge-kutta method for motion */
extern REAL total_time;     /* total scale factor */
extern REAL star_fraction;  /* weighting factor for star around vertices */
extern int area_fixed_flag;   /* for fixed area constraint */
extern REAL area_fixed_target;  /* target value for fixed area */
extern REAL area_fixed_pressure; /* Lagrange multiplier */
#define AREA_Q_ID 0x1111        /* for constraint identification */
extern int post_project_flag;    /* project to quant constr after each motion */
extern struct expnode mobility_formula;
extern int mobility_flag; /* whether mobility in effect */
extern struct expnode mobility_tensor[MAXCOORD][MAXCOORD];
extern int mobility_tensor_flag; /* whether tensor mobility in effect */
extern int check_pinning_flag;  /* for vertices changing constraints */
extern int nprocs;    /* number of parallel processors */
extern int procs_requested; /* number of processes desired */
extern REAL proc_total_area[MAXPROCS]; /* for individual processes */
extern int web_checksum; /* to see if web needs sending */
extern int dymem_checksum; /* see if dymem needs sending */
extern int comp_quant_vertex; /* during calc_quant_grad */
extern int comp_quant_type; /* during calc_quant_grad */

extern REAL *f_sums;  /* facet_knot_energy, for sums to all other vertices */

extern char yytext[];
extern int yydebug;  /* flag for parser debugging */
extern int help_flag; /* avoid error message while doing help */
extern int memdebug;  /* flag for memory debugging in run_checks() */
extern int itdebug;  /* flag for iteration debugginng */
extern int tok;
extern int int_val;
extern REAL real_val;
extern int coord_num;
extern char yytext[];
extern char idname[35]; /* for saving yytext */
extern char set_extra_name[100]; /* for saving name */
extern int line_no;
#define MAXHISTORY 100 
#define HISTORYSPACE 8000
extern char *history_space;
extern int  history_number;   /* number of current command */
extern int history_count;  /* number in list */
extern int  history_list[MAXHISTORY];
#define MAXCMDSIZE 2000 
extern char fulltext[MAXCMDSIZE+5]; /* for full text of commands */
extern int  fulltextsize;           /* length of command */
extern int yylval;  /* parser terminal value */
extern int aggrtype;  /* aggregate type being parsed */
extern int aggregate_depth; /* nesting depth of aggregate loops */
extern int attr_kind; /* kind of attribute being parsed */
extern char *default_name; /* for unnamed elements */
extern char last_name[50]; /* name of last element generator */
#define HISTBINS 21   /* bins in histogram (actually 1 less )*/

/* symbol table stuff */
#define SYMNAMESIZE 31
struct sym {
   char name[SYMNAMESIZE+1];
   int  type; /* element type, or see defines below */
   union { int intval;
         REAL realval;
         element_id idval;
         char *stringval;
          } value;
  };
#define SYMTYPE_INT    6
#define SYMTYPE_REAL   7
extern struct sym *elsym;  /* name of element during parsing */
extern struct sym *yysym;  /* name of identifier from lex */
extern struct sym symtable[];   /* symbol table */

/* squared curvature as part of energy */
extern int sqcurve_ignore_constr; /* set if to count fixed and constrained verts */
extern int square_curvature_flag;  /* set if to be counted */
extern int square_curvature_param;  /* which parameter for modulus */
extern int mean_curvature_param;   /* which parameter for modulus */
extern int mean_curv_int_quantity_num;   /* for everything quantities */
extern int sq_mean_curv_quantity_num; /* for everything quantities */
extern int kusner_flag;   /* set for edge square curvature */
extern int assume_oriented_flag; /* for orientation checking */
extern int boundary_curvature_flag; /* whether to include boundary vertices */
extern int conf_edge_curv_flag; /* set for conformal edge curvature squared */
extern int sqgauss_flag;  /* for squared gaussian curvature */
extern int sqgauss_param;   /* which parameter for modulus */
extern int       normal_sq_mean_curvature_mi;
extern int       eff_area_sq_mean_curvature_mi;
extern int       sq_mean_curvature_mi;
extern int       mix_sq_mean_curvature_mi;
extern int  star_normal_sq_mean_curvature_mi;
extern int  star_eff_area_sq_mean_curvature_mi;
extern int  star_sq_mean_curvature_mi;
extern REAL target_length;  /* for string model */
extern int approx_curve_flag;  /* if approximate curvature in effect */
extern int mean_curv_int_flag;  /* for unsquared mean curvature */
extern int normal_curvature_flag; /* choice of curvature formula */
extern int div_normal_curvature_flag; /* choice of curvature formula */
/* flag bits to say if should be evaluated since modulus nonzero */
#define EVALUATE 0x0002

#define SELFSIM_NAME "self_sim_coeff"
extern int self_similar_flag;

/* for restricting motion to be along normals */
extern int normal_motion_flag;
typedef REAL pt_type[MAXCOORD];
extern pt_type *vertex_normals;  /* for storage of normals by ordinal */

/* for Dennis DeTurck unit normal motion */
extern int unit_normal_flag;
extern REAL deturck_factor;  /* weight for unit normal */

extern REAL **identmat;  /* handy identity matrix, set up in init_view */

/* homothety target value, set when homothety toggled on */
extern REAL homothety_target;

extern char *msg;     /* for constructing user messages */
extern int msgmax;    /* length allocated */
extern char errmsg[200];  /* for error() routine */
extern int  parse_error_flag;  /* set when parser hits error */
extern int parse_errors;    /* for counting errors */
extern int  recovery_flag;     /* set while recovering from parsing error */
extern jmp_buf jumpbuf;   /* for error recovery  */
extern jmp_buf cmdbuf;   /* for command error recovery  */
extern jmp_buf m_jumpbuf[MAXPROCS];   /* for multiproc error recovery  */
#define UNRECOVERABLE 0
#define RECOVERABLE   1
#define WARNING       2
#define PARSE_ERROR   3
#define EXPRESSION_ERROR 4
#define COMMAND_ERROR 5
#define DATAFILE_ERROR 6
#define SYNTAX_ERROR 7
#define Q_ERROR 8
#define RECOVERABLE_QUIET 9

/* for queries */
extern int celement;
extern int commandverb;
extern int condition_flag;
#define ATTRIBUTE 19382
extern struct expnode *show_expr[NUMELEMENTS];  /* for element show exprs */
extern struct expnode show_command[NUMELEMENTS];  /* save for dump */
extern struct expnode show_expr_table[NUMELEMENTS];  /* actual expressions */
extern int query_intval;
extern REAL query_realval;
extern int set_query_type;
extern ATTR set_query_attr;
extern int query_coord;
/* values for set attribute queries */
#define SET_Q_ATTR  1301
#define SET_DENSITY 1302
#define SET_VOLUME  1303
#define SET_CONSTRAINT 1304
#define SET_COORD   1305
#define SET_PARAM   1306
#define SET_TAG     1307
#define UNSET_Q_ATTR 1308
#define UNSET_CONSTRAINT 1309
#define SET_COLOR  1310
#define SET_TRANS  1311
#define SET_FIXED  1312
#define DID_       4000


extern REAL volume_factorial;  /* simplex volume factor */
extern int subsimplex[1<<MAXCOORD][MAXCOORD];  /* for refining simplices */
struct simplex { int pt[MAXCOORD+1]; };
struct divedge { int endpt[2];  /* endpoints */
              int divpt;     /* dividing point of edge */
              };



/* for expression parsing */
#define LISTMAX 200
extern struct treenode *list;   /* tree */
extern int listtop;  /* first spot reserved for root */
extern int listmax;  /* allocated spots */
/* flags for permanence of list */
#define USERCOPY 1
#define NOUSERCOPY 0

/* type of checking to do */
#define PRELIMCHECK  1
#define REGCHECK     2

/* web.representation */
#define STRING   1
#define SOAPFILM 2
#define SIMPLEX  3

/* for vol_project and sp_hessian_solve */
#define NO_SET_PRESSURE 0
#define SET_PRESSURE    1
#define PROJECT_FORCE   2

/* boundary projection types */
#define PARAMPROJ  1
#define TANGPROJ   2
#define GRADPROJ   3
#define PLAINPROJ  4

/* maximum number for constraint projection iterations */
#define MAXCONITER 10

/* for telling constr_proj to detect one-sided constraints */
#define DETECT 1
#define NO_DETECT 0

/* for telling one_sided_adjust() what to adjust */
#define ADJUST_ALL 0
#define ADJUST_VGRADS 1

#define DEFAULT_TOLERANCE  (1e-12)
extern REAL constraint_tolerance;

/* vertex averaging modes */
#define NOVOLKEEP 0
#define VOLKEEP   1
#define RAWEST    2

extern REAL  overall_size;  /* for anybody who wants to know how big */
extern int breakflag;     /* set by user interrupt */
extern int iterate_flag;  /* so handler knows when iteration in progress */
extern int bare_edge_count;  /* edges without facets */

struct oldcoord {  
   REAL  (*coord)[MAXCOORD];  /* allocated space for old coordinates */
   REAL  energy;
   REAL optparam_values[MAXOPTPARAM];
   } ;
extern struct oldcoord saved;

/* ridge or valley indicators  */
#define RIDGE  1
#define VALLEY 2
extern int ridge_color_flag;  /* whether to differently color */
extern int edgeshow_flag;   /* whether to show edges of facets */
extern int triple_edgeshow_flag;   /* whether to show triple edges  */

/* vertex for zooming in on; default is first one read in */
extern int zoom_number;

/* for inner clipping for making zoom pictures */
extern int inner_clip_flag;
extern REAL inner_clip_rad;

/* conjugate gradient stuff */
extern int    conj_grad_flag;  /* whether conjugate gradient in effect */
extern REAL cg_oldsum;  /* total grad*grad from previous step */
extern REAL   (*cg_hvector)[MAXCOORD];  /* saved direction vector */
extern REAL cg_gamma;   /* direction adjustment factor */
extern int  ribiere_flag; /* to do Polak-Ribiere version */
#define RIBIERE_ATTR_NAME "old_force_ribiere"


/* structure for managing the facets of one body */
struct bodyface { facet_id f_id;
                  WRAPTYPE wrap;  /* wraps of base vertex */
                  int      wrapflag; /* whether wrap done */
                };

/* structure for depth sorting triangles */
extern struct tsort { 
               element_id f_id;    /* facet this is for ( or edge ) */
               int   color;     /* color map index */
               int   ecolor[FACET_EDGES]; /* edge colors */
               short  etype[FACET_EDGES]; /* special edge type */
               short  flag;       /* set if not yet displayed */
               float x[FACET_VERTS][MAXCOORD];    /* display coordinates of vertices */
               float normal[MAXCOORD];
               float mins[MAXCOORD];   /* minimum coordinates */
               float maxs[MAXCOORD];   /* maximum coordinates */
             } *trilist;
/* flag is EDGE or FACET in lower bits, and */
#define FLIPPED_FACET 0x1000
#define WAS_BACKMOST  0x2000

/* bounding box, for PostScript */
extern REAL bbox_minx,bbox_miny,bbox_maxx,bbox_maxy;
extern int need_bounding_box;  /* flag to tell painter.c to calculate */

struct graphdata { REAL  x[MAXCOORD+1];  /* homogeneous coordinates */
                   REAL  norm[MAXCOORD]; /* unit normal */
                   int    color;   /* colormap index */
                   int    backcolor;  /* for back of facet */
                   int    ecolor;  /* edge color */
                   short   etype;    /* edge type */
                   element_id id;  /* which element being graphed */
                   element_id v_id;    /* vertex */
                   int flags;
                 };
/* etype flag bits */
#define SIMPLE_FACET  1
#define LIST_FACET    2
/* edge types */
#define  INVISIBLE_EDGE 0
#define  REGULAR_EDGE  1
#define  TRIPLE_EDGE   2
#define  SINGLE_EDGE   4
#define  BOUNDARY_EDGE 8
#define  FIXED_EDGE    0x10
#define  CONSTRAINT_EDGE 0x20
#define  BARE_EDGE     0x40
#define  SPLITTING_EDGE 0x80

typedef REAL  IColor[4];  /* r,g,b,a;  not same as OOGL ColorA */
#define IRIS_COLOR_MAX 16
extern IColor rgb_colors[IRIS_COLOR_MAX];
extern REAL facet_alpha;  /* global transparency */

/* homogeneous coordinate dimensions */
extern int HOMDIM;

/* function pointers for invoking device-specific graphics */
#ifdef NOPROTO
/* first four are for random-order plotting and are fed raw data */
extern void (*graph_start)();  /* called at start of graphing */
extern void (*graph_edge )();  /* called to graph one triangle */
extern void (*graph_facet)();  /* called to graph one triangle */
extern void (*graph_end)();    /* called at end of graphics */
/* second four are for painter algorithm output, are fed digested data */
extern void (*display_edge )();  /* hardware edge  display */
extern void (*display_facet)();  /* hardware facet display */
extern void (*init_graphics)();  /* hardware initialization */
extern void (*finish_graphics)();  /* hardware end of picture */
extern void (*close_graphics)();  /* close graphics window */
#else
extern void (*graph_start)(void); 
extern void (*graph_edge )(struct graphdata *,edge_id); 
extern void (*graph_facet)(struct graphdata *,facet_id); 
extern void (*graph_end)(void);   
extern void (*display_edge )(struct tsort *);
extern void (*display_facet)(struct tsort *);
extern void (*init_graphics)(void);
extern void (*finish_graphics)(void);
extern void (*close_graphics)(void);  /* close graphics window */
#endif

/* graphing flags */
extern  int init_flag; /* whether graphics initialized */
extern  int bdry_showflag;  /* whether to show facets on boundary */
extern  int no_wall_flag;      /* whether to suppress wall facets */
extern  int normflag;
extern  int thickenflag;
extern  int innerflag;
extern  int outerflag;
extern  int colorflag;
extern  int OOGL_flag;   /* whether MinneView initialized */
extern  int geomview_flag;   /* whether geomview initialized */
extern  int geompipe_flag;   /* for pipe only */
extern  REAL thickness;  /* for thickening */
extern  int user_thickness_flag; /* whether user has specified thickness */
extern  int view_4D_flag;  /* 0 for doing 3D xyz projection graphics, */
                           /* 1 for outputting 4D graphics */

extern FILE * savefd;   /* file for binary dump of web */
extern FILE * data_fd;   /* file for initial data */

extern char cmapname[100];  /* colormap file name */
typedef REAL maprow[4];
extern  maprow *colormap; /* rgba colormap, values 0 to 1 */
extern int fillcolor;   /* current polygon fill color */
/* gaussian integration coefficients */
extern REAL gcombo[EDGE_CTRL][EDGE_INTERP];
extern REAL sdip[EDGE_CTRL][EDGE_INTERP];
extern REAL ssimp[EDGE_CTRL][EDGE_INTERP];
extern REAL gauss2wt[EDGE_INTERP];
extern REAL poly2partial[FACET_CTRL][2][2];
extern REAL scoeff[EDGE_CTRL][EDGE_CTRL]; /* plane area coeff */
extern REAL vcoeff[FACET_CTRL][FACET_CTRL][FACET_CTRL]; /* volume coeff*/
extern int set_by_user_gauss_1D;  /* minimums set by user */
extern int set_by_user_gauss_2D;

/* general parameters */
extern REAL **view;  /* transformation matrix */ 
extern int datafile_view_flag; /* whether datafile had view matrix */
extern int steps; 
extern int energy_init;     /* to keep track if we have current config energy */

/* for vertex popping */
struct verfacet { vertex_id v_id; facet_id f_id; };

#define MAXWULFF 100
extern REAL wulff_vector[MAXWULFF][MAXCOORD];  /* the vector components */
#ifdef NOPROTO
extern void (*get_wulff)();
#else
extern void (*get_wulff)(REAL *,REAL *);
#endif

extern int interp_bdry_param; /* flag for interp or extrap bdry param */
extern REAL **phase_data;  /* phase boundary energies */
extern char phase_file_name[PATHSIZE];  /* for dump */
extern int  phase_flag;    /* if phase boundary data in effect */
extern int phasemax;  /* number of phases */    

extern int fixed_constraint_flag;  /* set if restoring force valid */
extern REAL **leftside;  /* volume projection matrix */
extern REAL **rleftside;  /* volume projection matrix */
extern REAL *rightside;  /* right side of volume gradient constraints */
extern REAL *pressures; /* multiples of gradients to subtract from force */
extern int pressure_set_flag; /* pressures have been given values */
extern REAL *vol_deficit; /* bodyu volume deficits */
extern REAL *vol_restore; /* volume restoring gradient coefficients */
extern int no_refine;   /* keyword NOREFINE in data file header sets this
                        to disable initial triangulation of triangular
                        initial faces. */

/* interpolation structures */
#define MAXLEVEL 30
extern int reflevel;  /* refinement level */
extern REAL extrap_val[MAXLEVEL]; /* final value at level */

/* hessian minimization */
/* info for each vertex */
struct hess_verlist { 
                 vertex_id v_id; /* which vertex this is */
                 int freedom;    /* degrees of freedom */
                 int rownum;     /* starting row in sparse matrix  */
                 REAL **proj;    /* projection matrix to constraints */
                 REAL ***conhess;  /* for constraint hessian */
                 REAL slant;     /* cos of angle of normal from constraint */
               };
/* sparse hessian matrix entry */
struct hess_entry { 
               REAL value;
               int col;   /* which column */
               int row;   /* which row */
             };
extern struct hess_entry *entry_start;
/* sparse hessian matrix row header */
struct hess_index { int count;   /* number of entries in row */
               union {
               int listhead;  /* linked list start for row */
               REAL *congrad;   /* for constraint gradient row */
               } u;
             };
extern struct hess_entry *hashtable;  /* the table */
extern int table_size;  /* hashtable size */
extern int hash_per_row;  /* for estimating table size */
#define HASHEMPTY (-1)
extern int hessian_by_diff_flag; /* for crude hessian */
extern int hessian_quiet_flag;  /* 1 to suppress hessian warnings */
extern int hessian_normal_flag; /* 1 for hessian constrained to normal */
extern int hessian_special_normal_flag; /*  for undocumented stuff */
extern int hessian_normal_perp_flag; /* 1 for hessian metric to normal */
extern int hessian_normal_one_flag; /* 1 for hessian constrained to 1D normal */
extern int hessian_double_normal_flag; /* 1 for hessian constrained to normal */
extern int hessian_linear_metric_flag; /* linear interp dot product */
extern REAL linear_metric_mix;  /* proportion of linear interp metric */
extern REAL quadratic_metric_mix; /* proportion of quadratic interp metric */
extern int min_square_grad_flag; /* what to minimize in hessian_line_seek */
extern int hess_move_con_flag; /* whether to project to global constraints in move */
                          /* projecting seems to be good idea */
extern REAL last_hessian_scale; /* from hessian_line_seek() */
extern REAL last_eigenvalue;   /* from eigenprobe and stuff */
extern struct hess_index *congrads; /* constraint grads on left */
extern REAL *conrhs;   /* right side of augmented matrix for constraints */
extern int A_total; /* entries for A matrix */
extern int A_rows;  /* rows for A matrix */
extern int total_entries; /* of hessian */
extern struct hess_verlist *vhead;  /* main vertex list */
extern int vcount;        /* total number of vertices */
extern struct hess_index *array;
#ifdef XXX
extern REAL *X;             /* solution to augmented matrix  */
extern REAL *rhs;             /* right side of augmented matrix  */
#endif
extern int hmode; /* mode of motion */
#define SINGLE_DEGREE 2
#define NORMAL_MOTION 1
#define UNRESTRICTED  0
/* type of solution; YSMP path numbers */
#define HESS_CRITICAL 3
#define HESS_DOWNHILL 7
#define FORT
#ifdef FORT
#define A_OFF 1
#else
#define A_OFF 0
#endif
/* for controlling steps */
extern int rhs_flag;    /* filling in right hand side */
extern int hess_flag;   /* filling in hessian matrix */
extern int negdiag;     /* C index of most negative entry on diagonal */
extern int bodyrowstart;  /* first row of body volume constraints */
extern int quanrowstart;  /* first row of named quantity constraints */

/* Lanczos default parameters */
#define KRYLOVDIM 100
#define NPRINT 15

/**************************************************************************/
/*   Linear system structure                                              */
/*   for indefinite symmetric square systems, with linear constraints     */
/**************************************************************************/

/*************************************************************************
* The following data structure stores a node of the Metis separator tree
**************************************************************************/
struct SepNodeType {
  int nvtxs;    /* The number of vertices in the graph */
  int lo;       /* Low index of separator (inclusive) */
  int hi;       /* High index of separator (exclusive) */
  int isleaf;   /* Indicates if it is a leaf node */
  union { struct {
     REAL opc;   /* The opcount for this node */
     REAL subopc;        /* The opcount for the subtree of this node */
      } opc;  /* original metis fields */
      struct {
          int size; /* size of matrix */
          int *vlist; /* list of variable numbers */
          REAL *mat; /* triangular matrix */
      } info;  /* stuff useful in factoring */
  } u;
};
typedef struct SepNodeType SepNodeType;

extern int BK_flag; /*for enabling Bunch-Kauffman version of sparse factoring*/
extern REAL BKalpha; /* single/REAL pivot ratio */
struct BKrow { int start; /* index of first nonzero column in row */
               REAL *entry; /* entries */
             };
struct linsys { int flags; /* status bits, see below */
                int N;  /* number of variables */
                /* sparse storage of original matrix in upper triangle */
                int *IA;   /* row starts (unpermuted) */
                int *JA;   /* columns of each entry, starting on diag */
                REAL *A;   /* entry values */
                int *P;    /* permutation in factors; P[0] is first variable */
                int *IP;   /* inverse permutation */
                struct SepNodeType *stree; /* metis separation tree */
                int streemax; /* max index of used stree */
                int maxsepsize; /* maximum separator size */
                int NSP;   /* size of work space, for ysmp */
                int *ISP;  /* work space for ysmp or whoever */
                /* permuted storage */
                int *pIA;   /* row starts */
                int *pJA;   /* columns of each entry, starting on diag */
                REAL *pA;   /* entry values */
                /* factorization */
                REAL lambda; /* factor A - lambda */
                int *psize;  /* types of pivots on diagonal */
                struct BKrow *rowhead; /* for rows of factors */
                /* for mindegree factorization */
                int Lsize; /* number of entries */
                int *LIA;   /* starting indices */
                int *LJA;  /* columns for entries */
                int *LIJA; /* starts of rows in LJA (overlapped) */
                REAL *LA; /* values */
                /* constraint stuff */
                int concount; /* number of possible constraints */
                int CN;    /* number of actual constraints */
                int *coninx; /* map from possible to actual constraints */
                int *coninxinv; /* inverse of coninx */
                REAL **C;  /* constraint gradients, rowwise, orth'd */
                REAL **HinvC;  /* H^(-1)*C (transposed, actually) */
                REAL **CHinvCinv; /* (C^T*H^(-1)*C)^(-1) */
                /* inertia */
                int pos,neg,zero;
                /* Approximate inverse diagonal, for metric */
                REAL *apinv;
             };
/* flag bits */
#define S_HESSFILLED 1
#define S_RHSFILLED  2
#define S_FACTORED   4
#define S_PROJECTED  8
#define S_ODRV_REORDERED 0x10
#define S_JA_INCLUDED 0x20

/* psize values */
/* size of diagonal elements, 1 for 1x1, 2 for first of 2x2, 
   3 for second of 2x2, 0 for zero valued 1x1 */
#define ZEROPIVOT 0
#define ONEBYONE  1
#define FIRSTOFPAIR 2
#define SECONDOFPAIR 3

/* vector-to-form  metric */
extern struct linsys Met;

extern int ysmp_flag;  /* set if doing Yale Sparse Matrix version */
/* sparse matrix function pointers, for easy switching among algorithms */
/* values for ysmp_flag */
#define MINDEG_FACTORING 0
#define YSMP_FACTORING 1
#define METIS_FACTORING 2

/* multiply vector by original sparse matrix */
extern void (*sp_mul_func)ARGS((struct linsys *, REAL*,REAL*));

/* convert raw Hessian data to standard sparse format */
extern void (*sp_AIJ_setup_func)ARGS((struct hess_index*,int,struct linsys*));

/* set up  matrices needed for handling constraints */
extern void (*sp_constraint_setup_func)ARGS((struct hess_index *,int,
   struct linsys *));

/* set up projection to constraints using hessian metric */
extern void (*sp_hess_project_setup_func)ARGS((struct linsys *)) ;

/* factor matrix */
extern void (*sp_factor_func)ARGS((struct linsys *)) ;

/* return a vector in kernel, supposing nullity > 0 */
extern int (*sp_kernel_func)ARGS((struct linsys *,REAL *)) ;

/* solve given rhs */
extern void (*sp_solve_func)ARGS((struct linsys *,REAL *,REAL *)) ;

/* solve multiple given rhs */
extern void (*sp_solve_multi_func)ARGS((struct linsys*,REAL**,REAL**,int));

/* optional ordering of vertices */
extern void (*sp_ordering_func)ARGS((struct linsys *)) ;


/* to suppress a proliferation of warnings */
extern int pos_def_warning_flag;
extern int eigen_pos,eigen_neg,eigen_zero;  /* inertia of shifted hessian */
extern int mat_index; /* number of negatives on diagonal */
extern int mat_null; /* number of zeroes on diagonal */
extern REAL hessian_epsilon; /* cutoff for diagonal elements */
extern int make_pos_def_flag;   /* force hessian to positive definiteness */
extern int hess_debug;  /* debugging flag */



/* model dependent function pointers */
#ifdef NOPROTO
extern REAL (*userfunc[])();
extern REAL (*userfunc_deriv[])();
extern REAL (*userfunc_seconds[])();
extern void (*calc_facet_energy)();
extern void (*calc_facet_forces)();
extern void (*calc_facet_volume)();
extern void (*calc_edge_energy)();
extern void (*calc_edge_forces)();
extern void (*calc_edge_area)();
extern void (*string_grad)();
extern void (*film_grad)();
#else
extern REAL (*userfunc[])(REAL*);
extern REAL (*userfunc_deriv[])(REAL*,REAL*);
extern REAL (*userfunc_seconds[])(REAL*,REAL*,REAL**);
extern void (*calc_facet_energy)(facet_id);
extern void (*calc_facet_forces)(facet_id);
extern void (*calc_facet_volume)(facet_id);
extern void (*calc_edge_energy)(edge_id);
extern void (*calc_edge_forces)(edge_id);
extern void (*calc_edge_area)(edge_id);
extern void (*string_grad)(void);
extern void (*film_grad)(void);
#endif

/* gaussian integration on [0,1] */
extern REAL *gauss1Dpt;
extern REAL *gauss1Dwt;
extern int  gauss1D_num;
extern REAL **gauss1poly;  /* interp polys at gauss pts */
extern REAL **gauss1polyd; /* and derivatives           */
              /* values for linear or quadratic model, whichever in effect */
extern int  edge_ctrl; /* control points on edge, 2 linear, 3 quadratic */

/* 2D gauss */
typedef REAL barytype[3];
extern barytype *gauss2Dpt;
extern REAL *gauss2Dwt; 
extern REAL gauss2Dpt1[1][3]; 
extern REAL gauss2Dwt1[1];
extern REAL gauss2Dpt2[3][3]; 
extern REAL gauss2Dwt2[3];
extern REAL gauss2Dpt5[7][3]; 
extern REAL gauss2Dwt5[7];
extern REAL gauss2Dpt6[12][3]; 
extern REAL gauss2Dwt6[12];
extern REAL gauss2Dpt8[16][3]; 
extern REAL gauss2Dwt8[16];
extern REAL gauss2Dpt11[28][3]; 
extern REAL gauss2Dwt11[28];
extern REAL gauss2Dpt13[37][3]; 
extern REAL gauss2Dwt13[37];

/* general dimension gauss integration variables and arrays */
extern int ctrl_num;  /* number of control points */
extern int gauss2D_num; /* number of integration points */
extern REAL **gpoly;   /* interpolation polynomial value at integration point k
                   for polynomial of control point j */
extern REAL ***gpolypartial; /* partials of interpolation polynomials */
                   /* gausspt,dim,ctrlpt */

/* new gaussian-lagrange structure */
#define MAXGAUSSORDER 40
struct gauss_lag { int lagrange_order;  /* computed for */
                   int  gnumpts;     /* number of gauss points */
                   REAL **gausspt;  /* gaussian integration pts,
                                       in barycentric coords add to 1 */
                   REAL *gausswt;  /* weights at gauss pts */
                   int  lagpts;    /* number of lagrange pts */
                   REAL **gpoly;   /* basis polynomial of lagrange pt
                                      at gauss pt; index [g][l];
                                      mat mult lagrange to get gauss */
                   REAL ***gpolypart; /* partials of basis polynomials;
                                 index [g][dim][l];  mult lagrange
                                  to get tangents */
                   REAL ***lpolypart; /* partials at lagrange pts */
                };
extern struct gauss_lag gauss_lagrange[MAXCOORD][MAXGAUSSORDER];

extern REAL **metric;  /* metric values at a point */
extern REAL ***metric_partial; /* partial derivatives of metric */
extern REAL **det_array;   /* tangent vector dot products */
/*extern REAL **tang; */   /* tangents to surface at point */
extern REAL euclidean_area;   /* euclidean area for conformal metrics */
extern int klein_metric_flag;
extern int metric_convert_flag; /* whether to do form-to-vector conversion */

/* for defining pointer-pointer matrices as local variables */

/* need token-pasting, so gets weird with testing style needed */
#define bbxt 1
#define cxtc
#define bbxtcxtc  2
#if  defined(NeXT) || (__STDC__ == 1) || defined(__SUNPRO_C)
#define ddxt 1
#else
#define ddxt  bbxt/**/cxtc
#endif

#if  (ddxt == 1)

#define MAT2D(name,rows,cols)  \
  REAL *name##qXvS[rows];\
  REAL name##xJ[rows][cols];\
  REAL **name = mat2d_setup(name##qXvS,(REAL*)name##xJ,rows,cols)

#define MAT3D(name,rows,cols,levels)  \
  REAL **name##qXvS[(rows)+(rows)*(cols)];\
  REAL name##xJ[rows][cols][levels];\
  REAL *** name=mat3d_setup(name##qXvS,(REAL*)name##xJ,rows,cols,levels)

#define MAT4D(name,rows,cols,levels,tiers)  \
  REAL ***name##qXvS[(rows)+(rows)*(cols)+(rows)*(cols)*(levels)];\
  REAL name##xJ[rows][cols][levels][tiers];\
  REAL ****name=mat4d_setup(name##qXvS,(REAL*)name##xJ,rows,cols,levels,tiers)

#else

#define MAT2D(name,rows,cols)  \
  REAL *name/**/qXvS[rows];\
  REAL name/**/xJ[rows][cols];\
  REAL ** name = mat2d_setup(name/**/qXvS,(REAL*)name/**/xJ,rows,cols)

#define MAT3D(name,rows,cols,levels)  \
  REAL **name/**/qXvS[(rows)+(rows)*(cols)];\
  REAL name/**/xJ[rows][cols][levels];\
  REAL *** name = mat3d_setup(name/**/qXvS,(REAL*)name/**/xJ,rows,cols,levels)

#define MAT4D(name,rows,cols,levels,tiers)  \
  REAL ***name/**/qXvS[(rows)+(rows)*(cols)+(rows)*(cols)*(levels)];\
  REAL name/**/xJ[rows][cols][levels][tiers];\
  REAL **** name=mat4d_setup(name/**/qXvS,(REAL*)name/**/xJ,rows,cols,levels,tiers)
#endif
/* end matrix defines */


struct veredge { vertex_id v_id; edge_id e_id; }; /* used in verpopst.c */

/* symmetry group stuff */
extern char *symmetry_name;   /* to be sure datafile matches */
#ifdef NOPROTO
typedef void SYM_WRAP();     /* points to user-defined wrap function */
typedef WRAPTYPE SYM_COMP(); /* points to group composition function */
typedef WRAPTYPE SYM_INV (); /* points to group inverse function     */
typedef void SYM_FORM();     /* points to form pullback function     */
#else
typedef void SYM_WRAP(REAL*,REAL*,WRAPTYPE);
typedef WRAPTYPE SYM_COMP(WRAPTYPE,WRAPTYPE);
typedef WRAPTYPE SYM_INV (WRAPTYPE);
typedef void SYM_FORM(REAL*,REAL*,REAL*,WRAPTYPE);
#endif
extern SYM_WRAP *sym_wrap;
extern int       sym_flags;
extern SYM_FORM *sym_form_pullback;
extern SYM_INV  *sym_inverse;
extern SYM_COMP *sym_compose;
/* structure for registry.c */
struct sym_registry {
   char *name;  /* name to match in datafile SYMMETRY_GROUP phrase */
   int flags;  /* see bits below */
   SYM_WRAP *wrapper; /* point wrap function */
   SYM_COMP *compose; /* group composition function */
   SYM_INV  *inverse; /* group inverse function */
   SYM_FORM *pullback; /* form pullback function */
   };
 extern struct sym_registry sym_register[]; /* actual in registry.c */
/* flag bits */
#define HAS_FIXED_PTS 1
#define NEED_FORM_UNWRAPPING 2
#define DOUBLE_AXIAL 4
   

/* specific case of torus symmetry representation */
#define TWRAPBITS 6
#define POSWRAP   1
#define WRAPMASK  037
#define ALLWRAPMASK 03737373737
#define NEGWRAP   WRAPMASK

/* for symmetry group "rotate" */
extern int rotorder;

/* additional viewing transforms */
extern int transform_count;
extern REAL ***view_transforms;
extern int *view_transform_det; /* to see if normals need flipping */
extern int transforms_flag; /* whether to show transforms */
extern int transform_gen_count;
extern REAL ***view_transform_gens;   /* generators */
extern char transform_expr[100];  /* save it */
extern int transform_depth;  /* tree depth in transform generation */
extern int *transform_colors;
extern int *transform_gen_swap;
#define SAME_COLOR  0xf9878
#define SWAP_COLORS  0xFABC
extern int transform_colors_flag;

/* color for transparent facets */
#define CLEAR (-1)
/* color for unshown facet */
#define UNSHOWN (-2)

/* from borlandc/graphics.h */
#if     !defined(__COLORS)
#define __COLORS

enum COLORS {
    BLACK,                  /* dark colors */
    BLUE,
    GREEN,
    CYAN,
    RED,
    MAGENTA,
    BROWN,
    LIGHTGRAY,
    DARKGRAY,               /* light colors */
    LIGHTBLUE,
    LIGHTGREEN,
    LIGHTCYAN,
    LIGHTRED,
    LIGHTMAGENTA,
    YELLOW,
    WHITE
};
#endif


#ifdef SGI_MULTI
/* process ids */
extern int proc_ids[MAXPROCS];

#define M_ACTIVE 423
#define M_INACTIVE 0
extern int mpflag;  /* whether multiprocessing in action */
extern int m_breakflag[MAXPROCS]; /* for user interrupts */

/* locks and stuff */
extern usptr_t *lock_arena;  /* arena where locks are */
extern ulock_t locklist[_MAXLOCKS];  /* only 4096 available */
extern char lock_arena_name[]; /* for usinit() */

/* for keeping force updates from conflicting */
struct procforce { vertex_id v_id;
                   int next;  /* link */
                   REAL f[MAXCOORD];
                   };
extern struct procforce *pforce;
extern int phead[MAXPROCS][MAXPROCS]; /* [owner][calculator] */
extern struct procforce *pbase[MAXPROCS];  /* allocated to calculator */
extern int ptop[MAXPROCS];   /* used per calculator */
extern int pmax[MAXPROCS];   /* available per calculator */
#endif

/* Graphing mutual exclusion for multi-threaded version */
#ifdef WIN32
extern int volatile graph_semaphore;
#define ENTER_GRAPH_MUTEX { while ( graph_semaphore ) ; \
                           graph_semaphore = 1; }
#define LEAVE_GRAPH_MUTEX  graph_semaphore = 0;
#else
#define ENTER_GRAPH_MUTEX 
#define LEAVE_GRAPH_MUTEX  
#endif


/********************************************************************
*
*  File: express.h
*
*  Contents: defines for expression parsing and evaluation.
*/

/* node types, numbered above 512 to avoid yacc token numbers */
#define      INIT_VERTEX_EDGE_  513
#define      INIT_VERTEX_FACET_  514
#define      INIT_VERTEX_BODY_ 515
#define      INIT_EDGE_VERTEX_ 516
#define      INIT_EDGE_FACET_  517
#define      INIT_EDGE_BODY_ 518
#define      INIT_FACET_VERTEX_  519
#define      INIT_FACET_EDGE_  520
#define      INIT_FACET_BODY_ 521
#define      INIT_BODY_VERTEX_  522
#define      INIT_BODY_EDGE_  523
#define      INIT_BODY_FACET_ 524
#define      NEXT_VERTEX_EDGE_  525
#define      NEXT_VERTEX_FACET_  526
#define      NEXT_VERTEX_BODY_ 527
#define      NEXT_EDGE_VERTEX_  528
#define      NEXT_EDGE_FACET_  529
#define      NEXT_EDGE_BODY_ 530
#define      NEXT_FACET_VERTEX_  531
#define      NEXT_FACET_EDGE_  532
#define      NEXT_FACET_BODY_ 533
#define      NEXT_BODY_VERTEX_  534
#define      NEXT_BODY_EDGE_  535
#define      NEXT_BODY_FACET_ 536
#define      NEXT_VERTEX_  537
#define      NEXT_EDGE_  538
#define      NEXT_FACET_  539
#define      NEXT_BODY_  540
#define      NEXT_ELEMENT_  541
#define      INIT_VERTEX_  542
#define      INIT_EDGE_  543
#define      INIT_FACET_  544
#define      INIT_BODY_  545
#define      INIT_ELEMENT_  546
#define      SET_GRAVITY_     547
#define      SET_DIFFUSION_     548
#define      SET_GLOBAL_     549
#define      SET_COLOR_     550
#define      SET_DENSITY_     551
#define      SET_PRESSURE_     552
#define      SET_VOLUME_     553
#define      SET_CONSTRAINT_     554
#define      SET_TAG_     555
#define      SET_OPACITY_     556
#define      SET_SCALE_     557
#define      SET_COORD_      558
#define      SET_COORD_1     559
#define      SET_COORD_2     560
#define      SET_COORD_3     561
#define      SET_COORD_4     562
#define      SET_COORD_5     563
#define      SET_COORD_6     564
#define      SET_COORD_7     565
#define      SET_COORD_8     566
#define      SET_PROCEDURE_     567
#define      SET_PROC_END_     568
#define      SET_QUANTITY_     569
#define      SET_AUTOCHOP_     570
#define      SET_GAP_CONSTANT_     571
#define      SET_AMBIENT_PRESSURE_     572
#define      SET_FIXED_AREA_     573
#define      SET_COLORMAP_     574
#define      SET_THICKEN_     575
#define      SET_BACKGROUND_     576
#define      SET_OPTIMIZE_     577
#define      SET_FIXED_ 578
#define      GET_FIXED_ 579
#define      GET_LENGTH_ 580
#define      GET_VALENCE_ 581
#define      GET_AREA_ 582
#define      GET_VOLUME_ 583
#define      GET_DENSITY_ 584
#define      GET_ID_ 585
#define      GET_TAG_ 586
#define      GET_ORIGINAL_ 587
#define      INIT_AVG_ 588
#define      INIT_SUM_ 589
#define      INIT_MAX_ 590
#define      INIT_MIN_ 591
#define      INIT_COUNT_ 592
#define      AGGREGATE_INIT_ 593
#define      AGGREGATE_END_ 594
#define      AGGREGATE_ 595
#define      SET_INIT_ 596
#define      UNSET_CONSTRAINT_ 597
#define      UNSET_BOUNDARY_ 598
#define      GET_COLOR_ 599
#define      GET_SQ_MEAN_CURV_ 600
#define      GET_INTERNAL_ 601
#define      V_VERTEXCOUNT 602
#define      V_EDGECOUNT 603
#define      V_FACETCOUNT 604
#define      V_BODYCOUNT 605
#define      V_FACETEDGECOUNT 606
#define      V_ENERGY 607
#define      V_AREA 608
#define      V_LENGTH 609
#define      V_SCALE 610
#define      LIST_PROCS_ 611
#define      PRINTFHEAD_ 612
#define      PREPRINTF_  613
#define      EXPRLIST_  614
#define      SPRINTFHEAD_ 615
#define      SET_SGLOBAL_     616
#define      GET_OID_ 617
#define  GET_FRONTCOLOR_ 618
#define  GET_BACKCOLOR_  619
#define  SET_FRONTCOLOR_ 620
#define  SET_BACKCOLOR_  621
#define      SET_PARAM_     622
#define      SET_PARAM_1     623
#define      SET_PARAM_2     624
#define      SET_PARAM_3     625
#define      SET_PARAM_4     626
#define      SET_PARAM_5     627
#define      SET_PARAM_6     628
#define      SET_PARAM_7     629
#define  SET_ATTRIBUTE_      630
#define      SET_PHASE_      631
#define      GET_PHASE_      632
#define      LEXERROR        633
#define      PRESPRINTF_     634
#define      V_SURFACE_DIMENSION 635
#define      V_SPACE_DIMENSION 636
#define      TOGGLEVALUE     637
#define      V_TORUS          638
#define      V_TORUS_FILLED   639
#define      V_SYMMETRY_GROUP 640
#define      V_SIMPLEX        641
#define      V_INTEGRAL_ORDER 642
#define      GET_STAR_         643
#define      GET_PRESSURE_     644
#define      SET_INTERNAL_     645
#define      V_TOLERANCE       646
#define      AUTODISPLAY_      647
#define      V_EQUI_COUNT      648
#define      V_DELETE_COUNT      650
#define      V_REFINE_COUNT      651
#define      V_NOTCH_COUNT      652
#define      V_DISSOLVE_COUNT      653
#define      V_POP_COUNT      654
#define      V_WHERE_COUNT      655
#define      PUSH_NAMED_QUANTITY 656
#define      SET_NAMED_QUANTITY_ 657
#define      GET_USERATTR_ 658
#define      GET_QUANTITY_ 659
#define      UNSET_NAMED_QUANTITY_ 660
#define      GET_WRAP_ 661
#define FINISHED   701
#define PUSHCONST  702
#define PUSHPARAM  703
#define PUSHPI     704
#define PUSHE      705
#define PLUS       706
#define MINUS      707
#define TIMES      708
#define DIVIDE     709
#define INTPOW    710
#define POW       711
#define SIN       712
#define COS       713
#define TAN       714
#define SQRT      715
#define LOG       716
#define EXP       717
#define COPY      718
#define ACOS      719
#define ASIN      720
#define ATAN      721
#define CHS       722
#define INV       723
#define SQR       724
#define PUSHG     725
#define EQUATE    726
#define PUSHADJUSTABLE 727
#define ABS       728
#define USERFUNC  729
#define EXEC_     729
#define REPEAT_   730
#define FULLEXPR  731
#define SINH  732
#define COSH  733
#define REPLACECONST 734
#define REALMOD    735
#define CEIL_    736
#define FLOOR_    737
#define ATAN2_    738
#define NOP_      739
#define      V_HESS_EPSILON       740
#define HESSIAN_DIFF_ 741
#define SHOW_INNER_   742
#define SHOW_OUTER_   743
#define CLIPPED_CELLS_ 744
#define RAW_CELLS_   745
#define  CONNECTED_CELLS_ 746
#define NORMAL_MOTION_  747
#define RUNGE_KUTTA_  748
#define DETURCK_   749
#define KUSNER_   750
#define VIEW_4D_   751
#define CONF_EDGE_SQCURV_ 752
#define  SQGAUSS_  753
#define AUTOPOP_ 754
#define OLD_AREA_ 755
#define APPROX_CURV_ 756
#define CHECK_INCREASE_ 757
#define DEBUG_ 758
#define MEMDEBUG_ 759
#define EFFECTIVE_AREA_ 760
#define ESTIMATE_  761
#define POST_PROJECT_ 762
#define TRANSFORMS_ 763
#define QUIET_ 764
#define CONJ_GRAD_ 765
#define HOMOTHETY_ 766
#define FACET_COLORS_ 767
#define SHADING_  768
#define DIV_NORMAL_CURVATURE_ 769
#define NORMAL_CURVATURE_ 770
#define BOUNDARY_CURVATURE_ 771
#define SELF_SIMILAR_ 772
#define GV_BINARY_ 773
#define METRIC_CONVERSION_ 774
#define AUTORECALC_ 775
#define PINNING_ 776
#define FORCE_POS_DEF_ 777
#define V_SCALE_SCALE 778
#define GET_EXTRA_ATTR_ 779
#define SET_EXTRA_ATTR_ 780
#define SET_ATTRIBUTE_LOOP_  781
#define  SET_ATTRIBUTE_L      782
#define  TANH   783
#define  ATANH   784
#define  ASINH   785
#define  ACOSH   786
#define  V_ITER_COUNTER 787
#define QUIETGO_ 788
#define      GET_MIDV_ 789
#define      RIBIERE_CG_ 790
#define      ASSUME_ORIENTED_ 791
#define HESSIAN_QUIET_ 792
#define CONJUNCTION_END 793
#define JIGGLE_TOGGLE_ 794
#define V_TIME 795
#define V_JIG_TEMP 796
#define SYMBOL_ELEMENT_ 797
#define SINGLE_ELEMENT_ 798
#define INDEXED_SUBTYPE_ 799
#define INDEXED_ATTRIBUTE 800
#define QUALIFIED_ATTRIBUTE 801
#define STRPRINT_ 802
#define GET_TRIPLE_PT_ 804
#define SET_TRIPLE_PT_ 805
#define GET_TETRA_PT_ 806
#define SET_TETRA_PT_ 807
#define UNSET_TETRA_PT_ 808
#define UNSET_TRIPLE_PT_ 809
#define PUSHQPRESSURE_ 810
#define PUSHQTARGET_ 811
#define PUSHQVALUE_ 812
#define PUSHQMODULUS_ 813
#define SET_QMODULUS_ 814
#define SET_QTARGET_ 815
#define YSMP_        816
#define BUNCH_KAUFFMAN_ 817
#define V_EIGENPOS 818
#define V_EIGENNEG 819
#define V_EIGENZERO 820
#define QUANTITIES_ONLY_ 821
#define EVERYTHING_QUANTITIES_ 822
#define METRIC_CONVERT_ 823
#define GET_TARGET_ 824
#define MAXIMUM_ 825
#define UNSET_FACET_BODY_ 826
#define SET_ORIENTATION_ 827
#define V_PICKVNUM 828
#define V_PICKENUM 829
#define V_PICKFNUM 830
#define LINEAR_METRIC_ 831
#define V_LINEAR_METRIC_MIX 832
#define INVOKE_P_MENU_ 833
#define GEOMVIEW_TOGGLE_ 834
#define DO_TOP_ 835
#define DO_END_ 836
#define DO_ENTRY_ 837
#define SET_MODEL_ 838
#define V_RANDOM_SEED 839
#define MINIMUM_ 840
#define      V_INTEGRAL_ORDER_1D 841
#define      V_INTEGRAL_ORDER_2D 842
#define      GET_ORIENTATION_ 843
#define SET_TARGET_ 844
#define      UNSET_FIXED_  845
#define   UNSET_DENSITY_  846 
#define  UNSET_VOLUME_   847
#define  UNSET_PRESSURE_  848
#define  UNSET_TARGET_  849
#define  GET_VOLCONST_  850
#define  SET_VOLCONST_  851
#define  GET_TORUS_PERIODS_  852
#define  PUSHQVOLCONST_  853
#define  GET_FIXEDVOL_  854
#define  SET_QVOLCONST_  855
#define  SET_QPARAMETER_1_  856
#define  PUSHQPARAMETER_1_  857
#define  SINGLE_ELEMENT_INIT_  858
#define  REDEFINE_SINGLE_  859
#define  UNREDEFINE_SINGLE_  860
#define V_QUADRATIC_METRIC_MIX 861
#define GEOMPIPE_TOGGLE_ 862
#define V_LAST_EIGENVALUE 863
#define V_LAST_HESSIAN_SCALE 864
#define SQUARED_GRADIENT_ 865
#define PRINT_LETTER_ 866
#define REDIRECT_END_ 867
#define PIPE_END_ 868
#define V_LAGRANGE_ORDER 869
#define SET_AXIAL_POINT_ 870
#define UNSET_AXIAL_POINT_ 871
#define GET_AXIAL_POINT_ 872
#define H_INVERSE_METRIC_ 873
#define HELP_KEYWORD 874
#define SKINNY_ 875
#define TORDUP_ 876
#define V_GAP_CONSTANT 877
#define V_THICKNESS 878
#define V_TARGET_TOLERANCE 879
#define V_CLOCK 880
#define FIX_QUANTITY_ 881
#define UNFIX_QUANTITY_ 882
#define SET_ORIGINAL_ 883
#define V_SCALE_LIMIT 884
#define SET_MMODULUS_ 885
#define GET_INSTANCE_ 886
#define PUSHMMODULUS_ 887
#define PUSHMVALUE_   888
#define PSCOLORFLAG_  889
#define GRIDFLAG_     890
#define CROSSINGFLAG_ 891
#define LABELFLAG_    892
#define SHOW_ALL_QUANTITIES_ 893
#define  GET_INVERSE_PERIODS_  894
#define CREATE_EDGE_  895
#define SET_NO_REFINE_ 896
#define UNSET_NO_REFINE_ 897
#define GET_NO_REFINE_ 898
#define CREATE_VERTEX_  899
#define CREATE_FACET_  900
#define CREATE_BODY_  901
#define SET_FRONTBODY_ 902
#define SET_BACKBODY_ 903
#define V_TRANSFORM_COUNT 904
#define GT_            905
#define LT_            906
#define GET_BACKBODY_  907
#define GET_FRONTBODY_ 908
#define GET_TRANSFORM_EXPR_ 909
#define LOGFILE_TOGGLE_ 910
#define SET_WRAP_ 911
#define PLUSASSIGN_ 912
#define SUBASSIGN_ 913
#define MULTASSIGN_ 914
#define DIVASSIGN_ 915
#define NULLBLOCK_ 916
#define SINGLE_ASSIGN_ 917
#define SET_ATTRIBUTE_A 918
#define SET_METHOD_INSTANCE_ 919
#define UNSET_METHOD_INSTANCE_ 920
#define PUSH_METHOD_INSTANCE_ 921
#define LIST_ATTRIBUTES_ 922
#define NULLCMD_ 923
#define FIX_PARAMETER_ 924
#define UNFIX_PARAMETER_ 925
#define ITDEBUG_ 926
#define ZENER_DRAG_ 927
#define VOLGRADS_EVERY_ 928
#define V_RANDOM 929
#define PUSHQTOLERANCE_ 930
#define SET_QTOLERANCE_ 931
#define PUSHDELTA_  932
#define SET_DELTA_  933
#define BACKCULL_  934
#define V_BRIGHTNESS 935
#define V_DIFFUSION 936
#define DEFINE_IDENT_ 937
#define V_BACKGROUND 938
#define SET_NO_DISPLAY_ 939
#define UNSET_NO_DISPLAY_ 940
#define GET_NO_DISPLAY_ 941
#define V_MEMARENA 942
#define V_MEMUSED 943
#define  INDEXED_COORD_ 944

/* for BREAK and CONTINUE */
extern int loopdepth;

/* tree node for expression trees */
struct treenode { int left;   /* left subexpression index offset */
                 int right;  /* right subexpression index offset */
                 int type;  /* type of node */
                 int flags;
                 union { int intval; /* misc. integer data */
                         REAL  real;  /* constant value */
                         struct sym *symptr;  /* symbol table ptrs */
                         char *string;
                         element_id id;  /* element ids */
                         struct expnode enode;  /* for expression */
                         dll_func_type funcptr;
                   } op1;   /* operand */
                 union { int intval; /* misc. integer data */
                         struct sym *symptr;  /* symbol table ptrs */
                         char *string;
                         element_id id;  /* element ids */
                   } op2;   /* operand */
                 union { int intval[2]; /* misc. integer data */
                         struct sym *symptr;  /* symbol table ptrs */
                         char *string;
                         element_id id;  /* element ids */
                   } op3;
               };
/* flags */
#define LOCAL_VAR_REF 4
#define LOCAL_VAR_REF_2 8
#define LOCAL_VAR_REF_3 0x10
#define HAS_STRING      0x20

/* for some bit packing */
#define ESHIFT 12

/*************************************************************
*  This file is part of the Surface Evolver source code.     *
*  Programmer:  Ken Brakke, brakke@geom.umn.edu              *
*************************************************************/

/******************************************************************
*
*  File:  quantity.h
*
*  Purpose:  Header file for general quantities.
*/

struct qgrad { REAL *g;};
struct qhess { REAL **gg;};
#define MAXMETH 50

#ifdef NOPROTO
#define QINT
#define QINFO
#else
#define QINT int
#define QINFO struct qinfo *
typedef struct method_instance *MIPTR;
#endif

#define MAXVCOUNT 100
/* structure for passing info to element methods */
struct qinfo {
   element_id id;
   int method;   /* instance number; unreliable to use pointer here */
   int vcount;  /* number of vertices involved */
   vertex_id v[MAXVCOUNT];  /* vertex list */
   REAL *x[MAXVCOUNT];      /* vertex coordinates */
   WRAPTYPE wraps[MAXVCOUNT];  /* wraps of individual vertices */
   REAL **xx; /* room if facet coords need unwrapping */
   REAL **u;  /* room for affine coords of vertices in torus model */
   REAL **uu[3]; /* ptrs to edge vertex coords for torus volume */
   REAL **ugrad;  /* room for affine gradient in torus model */
   REAL **uugrad[3]; /* ptrs to edge vertex grads for torus volume */
   REAL ****uhess;  /* room for affine hessian in torus model */
   REAL ****uuhess[3]; /* ptrs to edge vertex hessians for torus volume */
   REAL **gauss_pt; /* for gaussian integration */
   int gauss_num;
   REAL ***sides;  /* edge or facet sides, or tangents at gauss pts in quad */
   REAL **ss;     /* matrix of dot products of sides */
   REAL normal[MAXCOORD];  /* facet normal */
   REAL **grad; /* vertex gradients */
   REAL ****hess; /* vertex hessians */
   int axial_order; /* number of times vertex repeats around axial point */
   };

/* for type of initialization */
#define METHOD_VALUE     1767
#define METHOD_GRADIENT  4321
#define METHOD_HESSIAN   8763


typedef void (*INIT_METHOD)ARGS((QINT,MIPTR));
typedef REAL (*VALUE_METHOD)(QINFO);
typedef REAL (*GRAD_METHOD)(QINFO);
typedef REAL (*HESS_METHOD)(QINFO);

/* structure for one quantity */
struct gen_quant {
   char name[32];   /* for identification */
   int num;         /* number in gen_quant list */
   int flags;       /* see defines below */
                    /* used for Q_ENERGY,Q_FIXED, or Q_INFO */
   REAL target;     /* for fixed quantities */
   REAL value;      /* current value */
   REAL oldvalue;   /* value for restore_coords() */
   REAL modulus;    /* overall multiplier */
   REAL tolerance;  /* for fixed quantity */
   REAL pressure;   /* Lagrange multiplier */
   body_id b_id;    /* body this is volume of, if any */
   int  vol_number;  /* equivalent body number for fixvol */
   REAL volconst;  /* additive constant, for torus volume */
   struct qgrad *grad;   /* gradients at vertices */
   struct qhess *hess;   /* hessian on vertices and edges */
   int method_count;    /* number of methods */
   int meth_inst[MAXMETH];
       /* method instances contributing */
   struct expnode  expr;  /* for compound formula */
   long timestamp;  /* when quantity last calculated */
   };
#define Q_ENERGY 1   /* part of energy */
#define Q_FIXED  2  /* is a constraint */
#define Q_INFO   4  /* only for information */
#define Q_DOTHIS 0x0010
#define Q_COMPOUND 0x0100   /* quantity defined by compound formula */
#define Q_FILLED_SKIP 0x0200 /* for torus_filled */
#define STANDARD_QUANTITY 0x1000
#define DEFAULT_QUANTITY  0x2000
#define TORUS_MODULO_MUNGE 0x4000
#define Q_PRESSURE_SET  0x8000

/* structure for one quantity calculating method */
/* split so can use same method for many quantities, */
/* or several methods for one quantity */

struct gen_quant_method {
  char name[32];  /* for easy user identification */
  int  type;      /* type of element applies to */
  int flags; 
  int spec_flags; /* what needs to be specified in datafile */
  INIT_METHOD  init;    /* initialization */
  VALUE_METHOD value;   /* function for value on element */
  GRAD_METHOD  gradient; /* function for gradient on element */
  HESS_METHOD  hessian;  /* function for hessian on element */
  };
/* flags for needed element atributes */
/* (low bits used in global_meth_inst_flags for Q_ENERGY etc.))))))))) */
#define NEED_SIDE  0x10
#define NEED_NORMAL 0x20
#define NEED_WINGS  0x40
#define NEED_GAUSS  0x80
#define NEED_STAR  0x100
#define NEED_STRING_STAR  0x200
/* flags bit for orientability */
#define ORIENTABLE_METHOD 0x10000
/*#define TORUS_MODULO_MUNGE 0x4000 also used in flags */
/* bits for spec_flags */
#define NOSPEC        0
#define SPEC_SCALAR   0x0001
#define SPEC_VECTOR   0x0002
#define SPEC_2FORM    0x0004
#define SPEC_EXTRADIM 0x0008
#define SPEC_USE_DENSITY 0x0010
#define SPEC_KVECTOR   0x0020

/* structure for instance of method */
#define MAXMEXPR ((MAXCOORD*MAXCOORD)/2) /* enough for 2-forms */
struct method_instance {
  char name[32];
  int type; /* element type */
  int flags;
  int gen_method;  /* parent method */
  int quant;  /* quantity this is a part of */
  int vec_order;  /* dimension of k-vector */
  struct expnode *expr[MAXMEXPR];  /* whatever interpreted expressions needed */
  REAL modulus;    /* adjustable multiplier */
  REAL value;    /* total value of this instance */
  REAL oldvalue;   /* value for restore_coords() */
  REAL newvalue;    /* accumulating value of this instance */
  REAL procvalue[MAXPROCS]; /* separate multiprocessor values */
  REAL grad[MAXCOORD+2][MAXCOORD];  /* at current vertex, for compound quants */
  REAL hess[MAXCOORD][MAXCOORD];  /* at current vertex, for compound quants */
  REAL parameter_1;  /* parameter particular to this instance */
  long timestamp;  /* when value last calculated */
/*  struct method_instance *next; */  /* linked list */
  };
/* flags, (avoid quantity flag bits) */
#define GLOBAL_INST  0x10000
#define IMPLICIT_INSTANCE 0x20000
#define DEFAULT_INSTANCE 0x40000
#define METH_PARAMETER_1 0x80000
#define BODY_INSTANCE   0x100000
#define IGNORE_CONSTR   0x200000
#define FAKE_IMPLICIT   0x400000

#define METH_INST ((struct method_instance *)(dymem + dy_meth_inst))
#define dy_meth_inst web.dy_meth_inst_w
extern struct method_instance *Meth_inst;
#define meth_inst_alloc web.meth_inst_alloc_w  /* number allocated */
#define meth_inst_count web.meth_inst_count_w   /* number defined   */

#define dy_gen_quants web.dy_gen_quants_w
#define GEN_QUANTS ((struct gen_quant *)(dymem + dy_gen_quants))
extern struct gen_quant *Gen_quants;
#define gen_quant_count web.gen_quant_count_w /* used */
#define gen_quant_alloc web.gen_quant_alloc_w /* allocated */

/* for list of available methods */
extern struct gen_quant_method basic_gen_methods[];

/* global method instances, applying to every element of type */
#define MAXGLOBINST 100
#define global_meth_inst_flags web.global_meth_inst_flags_w
#define global_meth_inst web.global_meth_inst_w /* lists */
#define global_meth_inst_count web.global_meth_inst_count_w

/* flags telling which quantity calculations necessary */
/* flag set for Q_ENERGY,Q_FIXED, or Q_INFO if any element
   needs a quantity calculated */
#define quant_flags web.quant_flags_w

extern int quanrowstart;  /* first row of named quantity constraints */

void q_edge_setup(QINFO);
void q_facet_setup(QINFO);
void q_vertex_setup(QINFO);
void q_body_setup(QINFO);
void q_facetedge_setup(QINFO);

extern void (*q_setup[NUMELEMENTS])(QINFO);

void q_edge_setup_q(QINFO);
void q_facet_setup_q(QINFO);
void q_vertex_setup_q(QINFO);
void q_body_setup_q(QINFO);

void q_edge_setup_lagrange(QINFO);
void q_facet_setup_lagrange(QINFO);
/********************************************************************
   Declarations of available methods.
*/
extern REAL null_q_value(QINFO);
extern REAL null_q_grad(QINFO);
extern REAL null_q_hess(QINFO);

extern void q_edge_tension_init ARGS((QINT,struct method_instance*));
extern REAL q_edge_tension_value(QINFO);
extern REAL q_edge_tension_gradient(QINFO);
extern REAL q_edge_tension_hessian(QINFO);

extern REAL edge_length_q_value(QINFO);
extern REAL edge_length_q_grad(QINFO);
extern REAL edge_length_q_hess(QINFO);

extern REAL lagrange_edge_tension_value(QINFO);
extern REAL lagrange_edge_tension_grad(QINFO);
extern REAL lagrange_edge_tension_hess(QINFO);

extern REAL q_edge_area(QINFO);
extern REAL q_edge_area_grad(QINFO);
extern REAL q_edge_area_hess(QINFO);

extern REAL q_edge_area_q(QINFO);
extern REAL q_edge_area_q_grad(QINFO);
extern REAL q_edge_area_q_hess(QINFO);

extern REAL q_edge_area_lagrange(QINFO);
extern REAL q_edge_area_lagrange_grad(QINFO);
extern REAL q_edge_area_lagrange_hess(QINFO);

extern REAL q_edge_torus_area(QINFO);
extern REAL q_edge_torus_area_grad(QINFO);
extern REAL q_edge_torus_area_hess(QINFO);

extern REAL q_edge_torus_area_q(QINFO);
extern REAL q_edge_torus_area_q_grad(QINFO);
extern REAL q_edge_torus_area_q_hess(QINFO);

extern REAL q_edge_torus_area_lagrange(QINFO);
extern REAL q_edge_torus_area_lagrange_grad(QINFO);
extern REAL q_edge_torus_area_lagrange_hess(QINFO);

extern REAL gap_energy(QINFO);
extern REAL gap_grads(QINFO);

extern REAL dihedral_hooke_energy(QINFO);
extern REAL dihedral_hooke_grad(QINFO);
extern REAL dihedral_hooke_hess(QINFO);

extern void wulff_method_init ARGS((QINT,struct method_instance*));
extern REAL facet_wulff_value(QINFO);
extern REAL facet_wulff_grad(QINFO);

extern REAL klein_length_method(QINFO);
extern REAL klein_length_method_grad(QINFO);

extern REAL klein_area_method(QINFO);
extern REAL klein_area_method_grad(QINFO);

extern void q_facet_tension_init ARGS((QINT,struct method_instance*));
extern REAL q_facet_tension_value(QINFO);
extern REAL q_facet_tension_gradient(QINFO);
extern REAL q_facet_tension_hessian(QINFO);

extern void q_facet_tension_u_init ARGS((QINT,struct method_instance*));
extern REAL q_facet_tension_u_value(QINFO);
extern REAL q_facet_tension_u_gradient(QINFO);
extern REAL q_facet_tension_u_hessian(QINFO);

extern REAL q_facet_tension_q(QINFO);
extern REAL q_facet_tension_q_grad(QINFO);
extern REAL q_facet_tension_q_hess(QINFO);

extern REAL q_facet_tension_uq(QINFO);
extern REAL q_facet_tension_uq_grad(QINFO);
extern REAL q_facet_tension_uq_hess(QINFO);

extern REAL lagrange_facet_tension_value(QINFO);
extern REAL lagrange_facet_tension_grad(QINFO);
extern REAL lagrange_facet_tension_hess(QINFO);

extern void metric_area_init ARGS((QINT,struct method_instance*));
extern REAL metric_area_value(QINFO);
extern REAL metric_area_grad(QINFO);
extern REAL metric_area_hess(QINFO);

extern REAL area_square_value(QINFO);
extern REAL area_square_gradient(QINFO);

extern void q_facet_volume_init ARGS((QINT,struct method_instance*));
extern REAL q_facet_volume(QINFO);
extern REAL q_facet_volume_grad(QINFO);
extern REAL q_facet_volume_hess(QINFO);

extern REAL q_facet_volume_q(QINFO);
extern REAL q_facet_volume_q_grad(QINFO);
extern REAL q_facet_volume_q_hess(QINFO);

extern REAL q_facet_torus_volume(QINFO);
extern REAL q_facet_torus_volume_grad(QINFO);
extern REAL q_facet_torus_volume_hess(QINFO);

extern REAL q_facet_torus_volume_q(QINFO);
extern REAL q_facet_torus_volume_q_grad(QINFO);
extern REAL q_facet_torus_volume_q_hess(QINFO);

extern REAL lagrange_facet_volume(QINFO);
extern REAL lagrange_facet_volume_grad(QINFO);
extern REAL lagrange_facet_volume_hess(QINFO);

extern REAL q_facet_torus_volume_lagr(QINFO);
extern REAL q_facet_torus_volume_lagr_grad(QINFO);
extern REAL q_facet_torus_volume_lagr_hess(QINFO);

extern void pos_area_hess_init ARGS((QINT,struct method_instance*));
extern REAL pos_area_hess(QINFO);

extern void sobolev_area_init ARGS((QINT,struct method_instance*));
extern REAL sobolev_area_hess(QINFO);

extern void dirichlet_area_init ARGS((QINT,struct method_instance*));
extern REAL dirichlet_area_hess(QINFO);

extern void gauss_integral_init ARGS((QINT,struct method_instance*));
extern REAL gauss_int_gradient(QINFO);
extern REAL gauss_int_energy(QINFO);

extern void sqgauss_method_init ARGS((QINT,struct method_instance*));
extern REAL sqgauss_method_value(QINFO);
extern REAL sqgauss_method_grad(QINFO);

extern void star_sqgauss_method_init ARGS((QINT,struct method_instance*));
extern REAL star_sqgauss_method_value(QINFO);
extern REAL star_sqgauss_method_grad(QINFO);

extern void sqcurve_string_init ARGS((QINT,struct method_instance*));
extern REAL sqcurve_string_value(QINFO);
extern REAL sqcurve_string_grad(QINFO);
extern REAL sqcurve_string_hess(QINFO);

extern void mean_int_init ARGS((QINT,struct method_instance*));
extern REAL mean_int_value(QINFO);
extern REAL mean_int_gradient(QINFO);

extern REAL vertex_scalar_integral(QINFO);
extern REAL vertex_scalar_integral_grad(QINFO);
extern REAL vertex_scalar_integral_hess(QINFO);

extern REAL edge_scalar_integral(QINFO);
extern REAL edge_scalar_integral_grad(QINFO);
extern REAL edge_scalar_integral_hess(QINFO);

extern REAL edge_scalar_integral_q(QINFO);
extern REAL edge_scalar_integral_q_grad(QINFO);
extern REAL edge_scalar_integral_q_hess(QINFO);

extern REAL edge_scalar_integral_lagr(QINFO);
extern REAL edge_scalar_integral_lagr_grad(QINFO);
extern REAL edge_scalar_integral_lagr_hess(QINFO);

extern REAL edge_vector_integral(QINFO);
extern REAL edge_vector_integral_grad(QINFO);
extern REAL edge_vector_integral_hess(QINFO);

extern REAL edge_vector_integral_q(QINFO);
extern REAL edge_vector_integral_q_grad(QINFO);
extern REAL edge_vector_integral_q_hess(QINFO);

extern REAL edge_vector_integral_lagrange(QINFO);
extern REAL edge_vector_integral_lagrange_grad(QINFO);
extern REAL edge_vector_integral_lagrange_hess(QINFO);

extern void edge_general_init ARGS((QINT,struct method_instance*));
extern REAL edge_general_value(QINFO);
extern REAL edge_general_grad(QINFO);
extern REAL edge_general_hess(QINFO);
extern REAL edge_general_value_lagrange(QINFO);
extern REAL edge_general_grad_lagrange(QINFO);
extern REAL edge_general_hess_lagrange(QINFO);

extern void facet_scalar_integral_init ARGS((QINT,struct method_instance*));
extern REAL facet_scalar_integral(QINFO);
extern REAL facet_scalar_integral_grad(QINFO);
extern REAL facet_scalar_integral_hess(QINFO);

extern REAL facet_scalar_integral_q(QINFO);
extern REAL facet_scalar_integral_q_grad(QINFO);
extern REAL facet_scalar_integral_q_hess(QINFO);

extern REAL facet_scalar_integral_lagr(QINFO);
extern REAL facet_scalar_integral_lagr_grad(QINFO);
extern REAL facet_scalar_integral_lagr_hess(QINFO);

extern void facet_vector_integral_init ARGS((QINT,struct method_instance*));
extern REAL facet_vector_integral(QINFO);
extern REAL facet_vector_integral_grad(QINFO);
extern REAL facet_vector_integral_hess(QINFO);

extern REAL lagrange_vector_integral(QINFO);
extern REAL lagrange_vector_integral_grad(QINFO);
extern REAL lagrange_vector_integral_hess(QINFO);

extern void simplex_vector_integral_init ARGS((QINT,struct method_instance*));
extern REAL simplex_vector_integral(QINFO);
extern REAL simplex_vector_integral_grad(QINFO);
extern REAL simplex_vector_integral_hess(QINFO);

extern void simplex_k_vector_integral_init ARGS((QINT,struct method_instance*));
extern REAL simplex_k_vector_integral(QINFO);
extern REAL simplex_k_vector_integral_grad(QINFO);
extern REAL simplex_k_vector_integral_hess(QINFO);

extern REAL lagrange_k_vector_integral(QINFO);
extern REAL lagrange_k_vector_integral_grad(QINFO);
extern REAL lagrange_k_vector_integral_hess(QINFO);

extern REAL facet_vector_integral_q(QINFO);
extern REAL facet_vector_integral_q_grad(QINFO);
extern REAL facet_vector_integral_q_hess(QINFO);

extern void facet_2form_integral_init ARGS((QINT,struct method_instance*));
extern REAL facet_2form_integral(QINFO);
extern REAL facet_2form_integral_grad(QINFO);
extern REAL facet_2form_integral_hess(QINFO);

extern REAL facet_2form_integral_lagrange(QINFO);
extern REAL facet_2form_integral_lagrange_grad(QINFO);
extern REAL facet_2form_integral_lagrange_hess(QINFO);

extern void facet_general_init ARGS((QINT,struct method_instance*));
extern REAL facet_general_value(QINFO);
extern REAL facet_general_grad(QINFO);
extern REAL facet_general_hess(QINFO);

extern REAL facet_general_value_lagr(QINFO);
extern REAL facet_general_grad_lagr(QINFO);
extern REAL facet_general_hess_lagr(QINFO);

extern void stress_integral_init ARGS((QINT,struct method_instance*));
extern REAL stress_integral(QINFO);
extern REAL stress_integral_grad(QINFO);

extern void sqcurve_method_init ARGS((QINT,struct method_instance*));
extern REAL sqcurve_method_value(QINFO);
extern REAL sqcurve_method_grad(QINFO);

extern void star_sqcurve_method_init ARGS((QINT,struct method_instance*));
extern REAL star_sqcurve_method_value(QINFO);
extern REAL star_sqcurve_method_grad(QINFO);
extern REAL star_sqcurve_method_hess(QINFO);

extern void hooke_energy_init ARGS((QINT,struct method_instance*));
extern REAL hooke_energy(QINFO);
extern REAL hooke_energy_gradient(QINFO);
extern REAL hooke_energy_hessian(QINFO);

extern void hooke2_energy_init ARGS((QINT,struct method_instance*));
extern REAL hooke2_energy(QINFO);
extern REAL hooke2_energy_gradient(QINFO);
extern REAL hooke2_energy_hessian(QINFO);

extern void hooke3_energy_init ARGS((QINT,struct method_instance*));
extern REAL hooke3_energy(QINFO);
extern REAL hooke3_energy_gradient(QINFO);
extern REAL hooke3_energy_hessian(QINFO);

extern void local_hooke_init ARGS((QINT,struct method_instance*));
extern REAL local_hooke(QINFO);
extern REAL local_hooke_gradient(QINFO);

extern void linear_elastic_init ARGS((QINT,struct method_instance*));
extern REAL linear_elastic_energy(QINFO);
extern REAL linear_elastic_gradient(QINFO);
extern REAL linear_elastic_hessian(QINFO);

extern void linear_elastic_B_init ARGS((QINT,struct method_instance*));
extern REAL linear_elastic_B_energy(QINFO);
extern REAL linear_elastic_B_gradient(QINFO);
extern REAL linear_elastic_B_hessian(QINFO);

extern void knot_energy_init ARGS((QINT,struct method_instance*));

extern void facet_vector_integral_init ARGS((QINT,struct method_instance*));
extern REAL facet_vector_integral(QINFO);
extern REAL facet_vector_integral_grad(QINFO);
extern REAL facet_vector_integral_hess(QINFO);

extern REAL facet_2form_integral(QINFO);
extern REAL facet_2form_integral_grad(QINFO);
extern REAL facet_2form_integral_hess(QINFO);

extern REAL stress_integral(QINFO);
extern REAL stress_integral_grad(QINFO);

extern void sqcurve_method_init ARGS((QINT,struct method_instance*));
extern REAL sqcurve_method_value(QINFO);
extern REAL sqcurve_method_grad(QINFO);

extern void hooke_energy_init ARGS((QINT,struct method_instance*));
extern REAL hooke_energy(QINFO);
extern REAL hooke_energy_gradient(QINFO);

extern void hooke2_energy_init ARGS((QINT,struct method_instance*));
extern REAL hooke2_energy(QINFO);
extern REAL hooke2_energy_gradient(QINFO);

extern void local_hooke_init ARGS((QINT,struct method_instance*));
extern REAL local_hooke(QINFO);
extern REAL local_hooke_gradient(QINFO);

extern void knot_power_init ARGS((QINT,struct method_instance*));

extern REAL knot_energy(QINFO);
extern REAL knot_energy_gradient(QINFO);
extern REAL knot_energy_hessian(QINFO);

extern void charge_gradient_init ARGS((QINT,struct method_instance*));
extern REAL charge_gradient(QINFO);
extern REAL charge_gradient_gradient(QINFO);

extern void uniform_knot_energy_init ARGS((QINT,struct method_instance*));
extern REAL uniform_knot_energy(QINFO);
extern REAL uniform_knot_energy_gradient(QINFO);

extern REAL edge_edge_knot_energy(QINFO);
extern REAL edge_edge_knot_energy_gradient(QINFO);

extern REAL edge_min_knot_energy(QINFO);

extern REAL uniform_normalization(QINFO);
extern REAL uniform_binormalization(QINFO);

extern REAL edge_normalization(QINFO);

extern REAL simon_normalization(QINFO);

extern void facet_knot_energy_init ARGS((QINT,struct method_instance*));
extern REAL facet_knot_energy(QINFO);
extern REAL facet_knot_energy_gradient(QINFO);

extern void facet_knot_energy_fix_init ARGS((QINT,struct method_instance*));
extern REAL facet_knot_energy_fix(QINFO);
extern REAL facet_knot_energy_fix_gradient(QINFO);

extern REAL buck_knot_energy(QINFO);
extern REAL buck_knot_energy_gradient(QINFO);

extern REAL proj_knot_energy(QINFO);
extern REAL proj_knot_energy_gradient(QINFO);

extern REAL sin_knot_energy(QINFO);
extern REAL sin_knot_energy_gradient(QINFO);

extern REAL circle_knot_energy(QINFO);
extern REAL circle_knot_energy_gradient(QINFO);

extern REAL average_crossing(QINFO);

extern REAL writhe(QINFO);
extern REAL writhe_gradient(QINFO);

extern REAL twist(QINFO);

extern void sphere_knot_energy_init ARGS((QINT,struct method_instance*));
extern REAL sphere_knot_energy(QINFO);
extern REAL sphere_knot_energy_gradient(QINFO);

extern REAL johndust_energy(QINFO);
extern REAL johndust_gradient(QINFO);

extern void curvature_forces_init ARGS((QINT,struct method_instance*));
extern REAL curvature_forces_energy(QINFO);
extern REAL curvature_forces(QINFO);

/* extern INIT_METHOD ackerman_init; */
extern void ackerman_init ARGS((QINT,MIPTR)); 
extern REAL ackerman_energy(QINFO);
extern REAL ackerman_forces(QINFO);

extern void carter_energy_init ARGS((QINT,struct method_instance*));
extern REAL carter_energy(QINFO);
extern REAL carter_energy_gradient(QINFO);

extern void full_gravity_init ARGS((QINT,struct method_instance*));

extern void gravity_init ARGS((QINT,struct method_instance*));
extern REAL gravity_energy(QINFO);
extern REAL gravity_grads(QINFO);
extern REAL gravity_hessian(QINFO);

extern void string_gravity_init ARGS((QINT,struct method_instance*));
extern REAL string_gravity_energy(QINFO);
extern REAL string_gravity_grads(QINFO);
extern REAL string_gravity_hessian(QINFO);

extern void curvature_binormal_init ARGS((QINT,struct method_instance*));
extern REAL curvature_binormal_energy(QINFO);
extern REAL curvature_binormal_force(QINFO);

extern void ddd_gamma_sq_init ARGS((QINT,struct method_instance*));
extern REAL ddd_gamma_sq_energy(QINFO);
extern REAL ddd_gamma_sq_gradient(QINFO);

extern REAL true_average_crossing(QINFO);
extern REAL true_writhe(QINFO);



/*************************************************************
*  This file is part of the Surface Evolver source code.     *
*  Programmer:  Ken Brakke, brakke@geom.umn.edu              *
*************************************************************/


/**********************************************************************
*
* The ultimate structure for a whole surface , including all global
* variables needed to export for distributed computing.
*/

struct web {
    struct skeleton skel[NUMELEMENTS];
    int sizes[NUMELEMENTS];
    int sdim;  /* dimension of ambient space */
    int dimension;   /* where tension resides */
    int representation; /* STRING, SOAPFILM, or SIMPLEX */
    int modeltype;   /* quadratic or linear, see defines below */
    int lagrange_order; /* polynomial order of elements */
    int headvnum;  /* number of head vertex in edge list */
    int maxparam;   /* maximum number of parameters in any boundary */
    int constraint_addr[MAXCON]; /* allocated in dymem as needed */
    int concount;    /* number of constraints */
    conmap_t con_global_map[MAXCONPER]; /* global vertex constraints */
    int con_global_count;  /* number of global vertex constraints */
    REAL tolerance;     /* constraint error tolerance */
    REAL target_tolerance; /* error tolerance for extensive constraints */
    struct boundary boundaries[BDRYMAX]; /* for free boundaries */
    struct surf_energy surfen[SURFENMAX]; /* facet energy integrands */
    MAP surf_global_map; /* bitmap for global surface energies */
    int surfen_count;    /* number of surface energy integrands */
    struct quantity quants[QUANTMAX]; /* facet quantity integrands */
    MAP quant_global_map; /* bitmap for global quantities */
    int quantity_count;    /* number of quantities */
    int diffusion_flag;  /* whether diffusion in effect */
    REAL diffusion_const;  /* coefficient for diffusion */
    REAL simplex_factorial; /* content correction factor for determinant */
    int torus_clip_flag;
    int torus_body_flag;
    int symmetric_content; /* 1 if volumes use symmetric divergence */
    int h_inverse_metric_flag; /* for laplacian of curvature */
    REAL meritfactor;   /* for multiplying figure of merit */
    int gravflag;       /* whether gravity is on */
    REAL grav_const;     /* multiplier for gravitational force */
    int convex_flag;    /* whether any convex boundaries present */
    int pressflag;      /* whether prescribed pressures present */
    int constr_flag;    /* set if there are any one-sided constraints */
    int hide_flag;      /* set for hidden surface removal */
    int motion_flag;    /* set for fixed scale of motion;
                                otherwise seek minimum. */
    int symmetry_flag;  /* whether symmetry group in effect */
    int torus_flag;    /* whether working in toroidal domain */
    int full_flag;    /* whether torus solidly packed with bodies */
    int pressure_flag;  /* whether pressure used dynamically */
    int projection_flag; /* whether to project */
    int area_norm_flag; /* whether to normalize force by area surrounding vertex */
    int norm_check_flag;  /* whether area normalization checks normal deviation */
    REAL norm_check_max;  /* maximum allowable deviation */
    int vol_flag;       /* whether body volumes up to date */
    int jiggle_flag;    /* whether to jiggle vertices at each move */
    int homothety;      /* flag for homothety adjustment each iteration */
    int wulff_flag;     /* whether we are using wulff shapes for energy */
    int wulff_count;    /* number of Wulff vectors read in */
    char wulff_name[60]; /* Wulff file or keyword */
    vertex_id  zoom_v;   /* vertex to zoom on */
    REAL zoom_radius;    /* current zoom radius */
    REAL total_area;
    REAL total_energy;
    REAL spring_energy;
    int total_facets;
    int bodycount;  /* number of bodies */
    body_id outside_body;  /* a body surrounding all others */
    REAL scale;    /* force to motion scale factor */
    REAL scale_scale;    /* over-relaxation factor */
    REAL maxscale;    /* upper limit on scale factor */
    REAL pressure;   /* ambient pressure */
    REAL min_area;      /* criterion on weeding out small triangles */
    REAL min_length;    /* criterion on weeding out small triangles */
    REAL max_len;       /* criterion for dividing long edges */
    REAL max_angle;     /* max allowed deviation from parallelism */
    REAL temperature;  /* "temperature" for jiggling */
    REAL spring_constant;  /* for forcing edges to conform to boundary */
    int  gauss1D_order;      /* order for gaussian 1D integration */
    int  gauss2D_order;      /* order for gaussian 2D integration */
    REAL torusv;             /* unit cell volume or area */
    REAL torus_period[MAXCOORD][MAXCOORD];
    REAL **inverse_periods;/* inverse matrix of torus periods */
    int  metric_flag;     /* set if background metric in force */
    int  conformal_flag;  /* set for conformal metrics */
    struct expnode metric[MAXCOORD][MAXCOORD]; /* metric component functions */
     
    /* some counters */
    int equi_count; 
    int weed_count; 
    int delete_count; 
    int refine_count; 
    int notch_count; 
    int dissolve_count; 
    int pop_count; 
    int where_count; 

/* here follows stuff moved from independent globals to inside web
   so as to be easily exported.  Previous global names are defined
   to web fields elsewhere.
   */
DY_OFFSET dy_gen_quants_w;
int gen_quant_count_w;
int gen_quant_alloc_w;
int global_count;
int maxglobals;  /* number allocated */

DY_OFFSET dy_meth_inst_w; /* for storing instance structures */
int meth_inst_alloc_w;  /* number allocated */
int meth_inst_count_w;  /* number defined   */

/* global method instances, applying to every element of type */
int global_meth_inst_flags_w[NUMELEMENTS];
int global_meth_inst_w[NUMELEMENTS][MAXGLOBINST]; /* lists */
int global_meth_inst_count_w[NUMELEMENTS];

/* flags telling which quantity calculations necessary */
/* flag set for Q_ENERGY,Q_FIXED, or Q_INFO if any element
   needs a quantity calculated */
int quant_flags_w[NUMELEMENTS];

DY_OFFSET dy_freestart_w;  /* initial block of freelist, 0 if none */
DY_OFFSET dy_globals_w;
#define dy_freestart web.dy_freestart_w

/* "extra attribute" numbers of expandable or optional attributes */
/* common */
int meth_attr[NUMELEMENTS] ; /* method instances list */
/* vertices */
/* edges */
/* facets */
/* bodies */
/* facet-edges */
  };

extern struct web web;


#ifdef NOPROTO
#include "noproto.h"
#else
#include "proto.h"
#endif

/* in case of non-parallel machines */
#ifndef M_LOCK
#define M_LOCK(addr)
#define M_UNLOCK(addr) 
#endif

#ifndef MAXINT
#define MAXINT (~(1<<(8*sizeof(int)-1)))
#endif

#ifndef FPRESET
#define FPRESET
#endif

#if defined(LONGDOUBLE) && !defined(NOLONGMATHFUNC)
/* have to do these after math.h */
#define sin sinl
#define cos cosl
#define tan tanl
#define asin asinl
#define acos acosl
#define atan atanl
#define sinh sinhl
#define cosh coshl
#define tanh tanhl
#define asinh asinhl
#define acosh acoshl
#define atanh atanhl
#define exp expl
#define log logl
#define pow powl
#define sqrt sqrtl
#define ceil ceill
#define fabs fabsl
extern REAL fabsl(REAL); /* wasn't in IRIX6.1 math.h */
#define floor floorl
#define fmod fmodl
#define modf modfl
#define atof atold
#endif




/* Here starts "ytab.h" */
# define EXPRESSION_START_ 257
# define COMMAND_START_ 258
# define HISTORY_ 259
# define GEOMVIEW_ 260
# define VIEW_MATRIX_ 261
# define LEAD_INTEGER_ 262
# define INTEGER_ 263
# define REAL_ 264
# define SIGNED_NUMBER_ 265
# define NEWIDENT_ 266
# define REDEFINE_ 267
# define MATHFUNC_ 268
# define MATHFUNC2_ 269
# define POW_ 270
# define USERFUNC_ 271
# define MIDV_ 272
# define DATAFILENAME_ 273
# define LOGFILE_ 274
# define PI_ 275
# define E_ 276
# define G_ 277
# define PARAM_ 278
# define SYMBOL_ 279
# define TOTAL_ 280
# define EXTRA_ATTRIBUTE_ 281
# define FIXEDVOL_ 282
# define IDENT_ 283
# define UMINUS_ 284
# define SHELL_ 285
# define COLOR_ 286
# define HESSIAN_ 287
# define VOLCONST_ 288
# define TORUS_PERIODS_ 289
# define VERTICES_ 290
# define EDGES_ 291
# define FACETS_ 292
# define BODIES_ 293
# define HESSIAN_MENU_ 294
# define POSTSCRIPT_ 295
# define LENGTH_ 296
# define AREA_ 297
# define VOLUME_ 298
# define ID_ 299
# define OID_ 300
# define TAG_ 301
# define ORIGINAL_ 302
# define FACETEDGES_ 303
# define WRAP_ 304
# define QUOTATION_ 305
# define UNSET_ 306
# define TOPINFO_ 307
# define OPACITY_ 308
# define VALENCE_ 309
# define HESSIAN_SADDLE_ 310
# define SET_ 311
# define FIXED_ 312
# define DENSITY_ 313
# define PRESSURE_ 314
# define CONSTRAINT_ 315
# define COORD_ 316
# define DISSOLVE_ 317
# define WHERE_ 318
# define LIST_ 319
# define SHOW_ 320
# define DELETE_ 321
# define REFINE_ 322
# define RECALC_ 323
# define SHOWQ_ 324
# define EDGESWAP_ 325
# define FIX_ 326
# define UNFIX_ 327
# define TOGGLENAME_ 328
# define TOGGLEVALUE_ 329
# define STAR_ 330
# define QUANTITY_NAME_ 331
# define PAUSE_ 332
# define GO_ 333
# define SHOW_VOL_ 334
# define CHECK_ 335
# define CMDLIST_ 336
# define READ_ 337
# define ZOOM_ 338
# define ON_ 339
# define OFF_ 340
# define GEOMPIPE_ 341
# define SINGLE_LETTER_ 342
# define LONG_JIGGLE_ 343
# define RAW_VERAVG_ 344
# define COUNTS_ 345
# define ULONG_TYPE_ 346
# define ALICE_ 347
# define STABILITY_TEST_ 348
# define DEFINE_ 349
# define INTEGER_TYPE_ 350
# define REAL_TYPE_ 351
# define UPLUS_ 352
# define AUTOCHOP_ 353
# define UTEST_ 354
# define ATTRIBUTE_ 355
# define INDEXED_ELEMENT_ 356
# define RITZ_ 357
# define MOVE_ 358
# define SYSTEM_ 359
# define TETRA_POINT_ 360
# define TRIPLE_POINT_ 361
# define LANCZOS_ 362
# define EIGENPROBE_ 363
# define AREAWEED_ 364
# define EDGEWEED_ 365
# define GRAVITY_ 366
# define EDGEDIVIDE_ 367
# define LINEAR_ 368
# define QUADRATIC_ 369
# define DIFFUSION_ 370
# define MEAN_CURV_ 371
# define EXTRAPOLATE_ 372
# define TRANSFORM_DEPTH_ 373
# define PRINTF_ 374
# define PRINT_ 375
# define MAX_ 376
# define MIN_ 377
# define COUNT_ 378
# define SUM_ 379
# define AVG_ 380
# define BREAK_ 381
# define CONTINUE_ 382
# define SIZEOF_ 383
# define REPEAT_INIT_ 384
# define TRANSFORM_EXPR_ 385
# define BARE_ 386
# define BOTTOMINFO_ 387
# define METIS_ 388
# define KMETIS_ 389
# define SCALE_ 390
# define BURCHARD_ 391
# define REBODY_ 392
# define BOUNDARY_ 393
# define ORIENTATION_ 394
# define OMETIS_ 395
# define SYMATTR_ 396
# define SQ_MEAN_CURV_ 397
# define FRONTCOLOR_ 398
# define SINGLE_REDEFD_ 399
# define METHOD_NAME_ 400
# define RAWEST_VERAVG_ 401
# define SINGLE_LETTER_ARG_ 402
# define BACKCOLOR_ 403
# define LAGRANGE_ 404
# define RETURN_ 405
# define INIT_SUBELEMENT_ 406
# define SPRINTF_ 407
# define CONVERT_TO_QUANTS_ 408
# define METIS_FACTOR_ 409
# define DIHEDRAL_ 410
# define GET_DIHEDRAL_ 411
# define INIT_FACETEDGE_ 412
# define GET_EDGE_ 413
# define GET_FACET_ 414
# define NEXT_FACETEDGE_ 415
# define SHOW_EXPR_ 416
# define SHOW_TRANS_ 417
# define AXIAL_POINT_ 418
# define ASSIGN_ 419
# define PUSHGLOBAL_ 420
# define PROCEDURE_ 421
# define FOREACH_ 422
# define STRINGGLOBAL_ 423
# define HISTOGRAM_ 424
# define LOGHISTOGRAM_ 425
# define COMMAND_BLOCK_ 426
# define AREA_FIXED_ 427
# define QUIT_ 428
# define IF_ 429
# define IFTEST_ 430
# define WHILE_ 431
# define DO_ 432
# define WHILE_TOP_ 433
# define NO_REFINE_ 434
# define STRING_ 435
# define WHILE_END_ 436
# define PRINT_PROCEDURE_ 437
# define SHOW_END_ 438
# define FRONTBODY_ 439
# define BACKBODY_ 440
# define THICKEN_ 441
# define COLORMAP_ 442
# define REDIRECT_ 443
# define NEWVERTEX_ 444
# define NEWEDGE_ 445
# define NEWFACET_ 446
# define MODULUS_ 447
# define TARGET_ 448
# define VALUE_ 449
# define INVERSE_PERIODS_ 450
# define NEWBODY_ 451
# define DELTA_ 452
# define GAP_CONSTANT_ 453
# define DUMP_ 454
# define AMBIENT_PRESSURE_ 455
# define NOTCH_ 456
# define QUANTITY_ 457
# define LOAD_ 458
# define TOGGLE_QUANTITY_ 459
# define PROCEDURE_WORD_ 460
# define DYNAMIC_LOAD_FUNC_ 461
# define INTERP_NORMALS_ 462
# define HELP_ 463
# define VERTEX_AVERAGE_ 464
# define METHOD_INSTANCE_ 465
# define MEAN_CURV_INT_ 466
# define OPTIMIZE_ 467
# define REDIRECTOVER_ 468
# define TOLERANCE_ 469
# define JIGGLE_ 470
# define VIEW_TRANSFORMS_ 471
# define CLOSE_SHOW_ 472
# define IS_DEFINED_ 473
# define NODISPLAY_ 474
# define PERM_ASSIGN_ 475
# define COND_TEST_ 476
# define COND_EXPR_ 477
# define COND_ELSE_ 478
# define PHASE_ 479
# define BACKGROUND_ 480
# define INTERNAL_VARIABLE_ 481
# define DIRICHLET_ 482
# define SOBOLEV_ 483
# define SOBOLEV_SEEK_ 484
# define DIRICHLET_SEEK_ 485
# define HESSIAN_SEEK_ 486
# define REORDER_STORAGE_ 487
# define RENUMBER_ALL_ 488
# define ASSIGNOP_ 489
# define PIPE_ 490
# define THEN_ 491
# define ELSE_ 492
# define OR_ 493
# define AND_ 494
# define NOT_ 495
# define EQ_ 496
# define LE_ 497
# define GE_ 498
# define NE_ 499
# define ON_CONSTRAINT_ 500
# define HIT_CONSTRAINT_ 501
# define ON_BOUNDARY_ 502
# define IMOD_ 503
# define IDIV_ 504
# define EPRINT_ 505
# define THEN 506
# define ELSE 507


/* for easy assignments */
#define FIRST for ( i = 0 ; i < pcount ; i++ ) stacktop->deriv[i] 
#define SECOND  for ( i = 0 ; i < pcount ; i++ )\
               for ( j = 0 ; j < pcount ; j++ ) stacktop->second[i][j] 

/* to save a little code size */
void zero_seconds ARGS((int, struct dstack *));
void zero_seconds (pcount, stacktop)
int pcount;
struct dstack *stacktop;
{ int i,j;
  FIRST = 0.0;
  SECOND = 0.0;
}

/*****************************************************************
*
*  Function eval_second()
*
*  Purpose: runtime tree_evaluation of expression and all of its
*           partial derivatives and second derivatives.
*
*/

void eval_second(ex,params,pcount,fval,partials,seconds,q_id)
struct expnode *ex;      /* expression tree */
REAL *params;    /* vector of paramters */
int  pcount;     /* number of variables */
REAL *fval;      /* function value */
REAL *partials;  /* values of partials */
REAL **seconds;  /* second derivatives */
element_id q_id; /* reference element, if any */
{
  int i,j,n;
  REAL x,y,denom;
  struct dstack stack[100];
  register struct dstack *stacktop = stack;
  register struct treenode *node;
  element_id id;

  if ( pcount > 2*MAXCOORD )
     kb_error(1009,"More variables than 2*MAXCOORD in eval_second().\n",RECOVERABLE);



 stacktop->value = 0.0;  /* for empty expression */
 FIRST = 0.0;
 SECOND = 0.0;
 if ( ex ) 
  for ( node = ex->start+1 ; ; node++ )
   {
    switch ( node->type )
      {
        case OR_:
            stacktop--;
            stacktop[0].value = (REAL)(stacktop[0].value || stacktop[1].value);
            zero_seconds(pcount,stacktop);
            break;

          default:
            sprintf(errmsg,"Bad expression eval_second() node type: %s.",
                 tokname(node->type));
          kb_error(1016,errmsg,RECOVERABLE);

            break;
     }     
   if ( node == ex->root ) break;
  }     

  *fval = stacktop->value;
  for ( i = 0 ; i < pcount ; i++ )
    { partials[i] = stacktop->deriv[i]; 
      for ( j = 0 ; j < pcount ; j++ )
        seconds[i][j] = stacktop->second[i][j];
    }

  return;
}

