INTERFACE Energy;
IMPORT LR3, Triang;
FROM Triang IMPORT Topology;

(* A generic energy function *)

TYPE
  Coords = Triang.Coords;    (* A vector of vertex coordinates *)
  Gradient = ARRAY OF LR3.T; (* A vector of energy gradients per vertex *)

  T = OBJECT METHODS 

      defTop (READONLY top: Topology);
        (*
          Attaches the energy evaluator to some topological
          triangulation.  Must be called at least once
          before "defVar" below. *)

      defVar (READONLY variable: ARRAY OF BOOLEAN);
        (*
          Tells "eval" which vertices "v" should be considered
          variables ("variable[v]=TRUE") or fixed parameters 
          ("variable[v]=FALSE"); see below.  
          
          Must be called at least once before the first use of "eval".
          Since it may be an expensive operation, clients should
          avoid calling it if the variable vertex set hasn't changed. *)

      eval (
          READONLY c: Coords; 
          VAR e: LONGREAL; 
          grad: BOOLEAN; 
          VAR eDc: Gradient;
        );
        (*
          Returns in "e" the energy of triangulation "t" when the vertices
          have the coordinates "c". 

          Also, if "grad" is TRUE, "eval" will return in "eDc" the
          gradient of "e", that is, the partial derivatives of "e"
          relative to each element of "c".

          An "Energy.T" object is typically used inside optimization
          loops where only some vertices are being adjusted, while the
          others are kept fixed in place.  In that context the
          absolute value of the energy is not important; only energy
          differences are important.

          Accordingly, the "eval" method is free to omit any terms of
          the energy formula that depend only on fixed vertices.
          (However, the decision to omit a term must not depend on "c".)
          
          The client should be aware that if vertex "v" is fixed, the
          corresponding component of the gradient "eDc[v]" may not be
          set by "evalGrad", and therefore should not be used. *)

      name(): TEXT;
        (*
          Prints a description of the energy function. *)
    END; 
    
END Energy.